import Path from "node:path"; import { parseArgs } from "util"; import { marked } from "marked"; const { values: flags, positionals } = parseArgs({ args: Bun.argv.slice(2), options: { outfile: { type: 'string', short: 'o', default: 'index.html', }, template: { type: 'string', short: 't', default: 'template.html', }, stylesheet: { type: 'string', short: 's', default: 'style.css', }, }, allowPositionals: true, }); async function readOptionalFileContent(filePath: string, defaultContent: string): Promise { const file = Bun.file(filePath); const exists = await file.exists(); if (!exists) { return defaultContent; } return file.text(); } const inputFileArg: string | null = positionals[0] ?? null; const inputFileName = Path.basename(inputFileArg ?? 'Document', '.md'); const inputFile = inputFileArg ? Bun.file(inputFileArg) : Bun.stdin; const inputFileExists = await inputFile.exists(); if (!inputFileExists) { throw new Error(`Input file ${inputFileArg} does not exist.`); } const outputFile = Bun.file(flags.outfile); const templateFile = await readOptionalFileContent(flags.template, ` %title%
%content%
`.trim()); const stylesheetFile = await readOptionalFileContent(flags.stylesheet, ` :root { --color-bg: #333; --color-text: #DDD; --color-link: #FFF; --color-strong: #ff8f8f; --color-emphasis: #FF8F00; --font-size: 18px; --font-family: Seravek, 'Gill Sans Nova', Ubuntu, Calibri, 'DejaVu Sans', source-sans-pro, sans-serif; --font-weight: 400; --font-weight-bold: 500; --line-height: 1.4; --max-width: 700px; } body { background-color: var(--color-bg); color: var(--color-text); font-size: var(--font-size); font-family: var(--font-family); font-weight: var(--font-weight); line-height: var(--line-height); } article { max-width: var(--max-width); margin: 0 auto; } h1, h2, h3, h4, h5, h6 { font-family: var(--font-family); font-weight: var(--font-weight-bold); } em, i { color: var(--color-emphasis); } strong, b { color: var(--color-strong); font-weight: var(--font-weight-bold); } a { color: var(--color-link); } table { border-collapse: collapse; width: 100%; margin: 1em 0; font-size: 1em; background-color: var(--color-bg); color: var(--color-text); border: 1px solid var(--color-text); } th, td { padding: 0.75em 1em; text-align: left; border-bottom: 1px solid var(--color-text); } th { background: var(--color-bg); font-weight: 500; } `.trim()); const markdown = await inputFile.text(); const html = await marked.parse(markdown, { gfm: true, }); const output = templateFile .replace("%stylesheet%", stylesheetFile) .replace("%content%", html) .replace("%title%", inputFileName); await outputFile.write(output);