First version done

This commit is contained in:
2024-11-16 14:35:32 +01:00
parent 22d38a3b5e
commit c54eb91951
7 changed files with 2491 additions and 0 deletions

10
.editorconfig Normal file
View File

@@ -0,0 +1,10 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
[*.{js,json,yml}]
charset = utf-8
indent_style = space
indent_size = 2

4
.gitattributes vendored Normal file
View File

@@ -0,0 +1,4 @@
/.yarn/** linguist-vendored
/.yarn/releases/* binary
/.yarn/plugins/**/* binary
/.pnp.* binary linguist-generated

5
.yarnrc.yml Normal file
View File

@@ -0,0 +1,5 @@
compressionLevel: mixed
enableGlobalCache: false
nodeLinker: node-modules

19
package.json Normal file
View File

@@ -0,0 +1,19 @@
{
"name": "markdown2png",
"version": "1.0.0",
"description": "Convert Markdown files to PNG",
"scripts": {
"dev": "ts-node src/index.ts"
},
"license": "MIT",
"dependencies": {
"marked": "^4.3.0",
"puppeteer": "^21.0.0"
},
"devDependencies": {
"@types/marked": "^4.0.8",
"@types/node": "^18.15.11",
"ts-node": "^10.9.1",
"typescript": "^5.0.3"
}
}

109
src/index.ts Normal file
View File

@@ -0,0 +1,109 @@
import puppeteer from 'puppeteer';
import { marked } from 'marked';
import { promises as fs } from 'fs';
import path from 'path';
interface PageDimensions {
width: number;
height: number;
}
async function convertMarkdownToImage(markdownPath: string): Promise<void> {
try {
const markdownContent = await fs.readFile(markdownPath, 'utf-8');
const htmlContent = marked(markdownContent);
const fullHtml = `
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
line-height: 1.6;
padding: 20px;
max-width: 900px;
margin: 0 auto;
background: white;
color: #24292e;
}
pre {
background-color: #f6f8fa;
padding: 16px;
border-radius: 6px;
overflow-x: auto;
}
code {
font-family: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace;
font-size: 85%;
}
img {
max-width: 100%;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 24px;
margin-bottom: 16px;
font-weight: 600;
line-height: 1.25;
}
</style>
</head>
<body>
${htmlContent}
</body>
</html>
`;
await fs.mkdir('output', { recursive: true });
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setContent(fullHtml, { waitUntil: 'networkidle0' });
const dimensions = await page.evaluate((): PageDimensions => {
return {
width: document.documentElement.offsetWidth,
height: document.documentElement.offsetHeight
};
});
await page.setViewport({
width: dimensions.width,
height: dimensions.height,
deviceScaleFactor: 2
});
const outputPath = path.join(
'output',
`${path.basename(markdownPath, '.md')}.png`
);
await page.screenshot({
path: outputPath,
fullPage: true,
type: 'png'
});
await browser.close();
console.log(`Successfully converted ${markdownPath} to ${outputPath}`);
} catch (error) {
console.error('Conversion error:', error);
throw error;
}
}
async function main(): Promise<void> {
const inputFile = process.argv[2];
if (!inputFile) {
console.log('Usage: npm start <markdown-file>');
console.log('Example: npm start input/document.md');
return;
}
await convertMarkdownToImage(inputFile);
}
main().catch(console.error);

19
tsconfig.json Normal file
View File

@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020", "DOM"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"sourceMap": true,
"declaration": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}

2325
yarn.lock Normal file

File diff suppressed because it is too large Load Diff