code icon Code

Render Markdown

Convert Markdown to HTML

Source Code

import fs from "fs";
import path from "path";
import { marked } from "marked";

const [inputPath, outputPath, optionsJson = "{}"] = process.argv.slice(2);

if (!inputPath || !outputPath) {
  console.error("Usage: inputPath outputPath [options]");
  process.exit(1);
}

try {
  console.log(`Rendering Markdown: ${inputPath}...`);

  let options;
  try {
    options = JSON.parse(optionsJson);
  } catch {
    console.error("Invalid options JSON:", optionsJson);
    process.exit(1);
  }

  const markdown = fs.readFileSync(inputPath, "utf-8");

  // Configure marked
  marked.setOptions({
    gfm: options.gfm !== false, // GitHub Flavored Markdown (default true)
    breaks: options.breaks || false, // Convert \n to <br>
    headerIds: options.headerIds !== false,
    mangle: false, // Don't mangle email addresses
  });

  let html = marked.parse(markdown);

  // Optionally wrap in HTML document
  if (options.wrapHtml) {
    const title = options.title || path.basename(inputPath, path.extname(inputPath));
    const style =
      options.style ||
      `
      body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 800px; margin: 0 auto; padding: 2rem; line-height: 1.6; }
      pre { background: #f4f4f4; padding: 1rem; overflow-x: auto; }
      code { background: #f4f4f4; padding: 0.2em 0.4em; border-radius: 3px; }
      pre code { background: none; padding: 0; }
      blockquote { border-left: 4px solid #ddd; margin: 0; padding-left: 1rem; color: #666; }
      table { border-collapse: collapse; width: 100%; }
      th, td { border: 1px solid #ddd; padding: 0.5rem; text-align: left; }
      th { background: #f4f4f4; }
    `;

    html = `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>${title}</title>
  <style>${style}</style>
</head>
<body>
${html}
</body>
</html>`;
  }

  // Ensure output directory exists
  const dir = path.dirname(outputPath);
  if (dir && dir !== ".") {
    fs.mkdirSync(dir, { recursive: true });
  }

  fs.writeFileSync(outputPath, html);

  const inputSize = markdown.length;
  const outputSize = html.length;

  console.log(`\nāœ“ Rendered Markdown to HTML`);
  console.log(`  Input: ${inputSize} characters`);
  console.log(`  Output: ${outputSize} characters`);
  console.log(`  GFM: ${options.gfm !== false}`);
  console.log(`  Wrapped: ${!!options.wrapHtml}`);
  console.log(`  Written to: ${outputPath}`);

  console.log(
    JSON.stringify({
      success: true,
      inputPath,
      outputPath,
      inputSize,
      outputSize,
      gfm: options.gfm !== false,
      wrapped: !!options.wrapHtml,
    })
  );
} catch (error) {
  console.error("Error:", error.message);
  process.exit(1);
}