4.4 KiB
4.4 KiB
| name | description |
|---|---|
| md2img | This skill should be used when the user wants to render a Markdown document (containing Mermaid diagrams, LaTeX math formulas, or rich formatting) into a PNG image. |
md2img — Markdown → PNG
Render Markdown documents into high-quality PNG images with full support for Mermaid diagrams, LaTeX math formulas, code syntax highlighting, and GFM tables.
Features
- Mermaid diagrams: flowchart, sequence, class, state, gantt, pie, etc. (rendered in-browser via mermaid.js)
- LaTeX math: inline
$...$and block$$...$$/\[...\](via KaTeX) - GFM syntax: tables, task lists, strikethrough, code blocks
- Code highlighting: via highlight.js CSS
- Dark/Light theme: auto-detects system preference, or override with
--dark/--light - Paper sizes: A4 (default) or Letter, 2x DPI for crisp output
- Cross-platform: Windows (Chrome/Edge) and Linux (Chrome/Chromium)
Usage Workflow
- Write the Markdown content to a temporary
.mdfile - Run the render script
- Present the generated PNG to the user
Command
node <skill_dir>/scripts/render.js <input.md> [output.png] [--paper=a4|letter] [--dark|--light]
Parameters
| Parameter | Default | Description |
|---|---|---|
input.md |
(required) | Input Markdown file path |
output.png |
<input>.png |
Output PNG file path |
--paper |
a4 |
Paper size: a4 (794px) or letter (816px) |
--dark |
auto | Force dark theme |
--light |
auto | Force light theme |
Examples
# Basic usage
node render.js readme.md
# Specify output path and paper size
node render.js slides.md output.png --paper=letter
# Force dark theme (for dark background images)
node render.js notes.md card.png --dark
Environment Setup
Windows (current machine)
Already configured. Uses local Edge/Chrome via puppeteer-core.
Linux (headless server)
On Linux servers without a GUI browser, install Chromium:
# Option 1: Install puppeteer (auto-downloads Chromium)
cd ~/.workbuddy/skills/md2img/scripts
npm install puppeteer
npx puppeteer browsers install chrome
# Option 2: Install system Chromium
# Ubuntu/Debian:
sudo apt install -y chromium-browser
# CentOS/RHEL:
sudo yum install -y chromium
# Alpine:
apk add chromium
# Option 3: Set CHROME_PATH env variable
export CHROME_PATH=/usr/bin/chromium-browser
Linux headless prerequisites:
# Ubuntu/Debian — required shared libraries
sudo apt install -y libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 \
libxkbcommon0 libxcomposite1 libxdamage1 libxrandr2 libgbm1 libasound2 \
libpango-1.0-0 libcairo2 libxshmfence1
# Alpine
apk add nss atk cups-libs libdrm libxkbcommon libxcomposite libxdamage \
libxrandr mesa-gbm alsa-lib pango cairo
Docker deployment
FROM node:20-slim
# Install Chromium dependencies
RUN apt-get update && apt-get install -y \
chromium \
fonts-noto-cjk \
--no-install-recommends && \
rm -rf /var/lib/apt/lists/*
# Set CHROME_PATH so puppeteer-core finds it
ENV CHROME_PATH=/usr/bin/chromium
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
WORKDIR /app
COPY scripts/package.json scripts/render.js ./
RUN npm install --production
ENTRYPOINT ["node", "render.js"]
Technical Details
- Markdown parsing:
markedv12 with custom renderer for mermaid code blocks - LaTeX rendering:
KaTeXserver-side pre-render (no browser-side JS needed) - Mermaid rendering:
mermaid.jsbrowser-side rendering via CDN (mermaid requires DOM API, cannot render in Node.js) - Browser automation:
puppeteer-core(Windows, uses local Edge/Chrome) orpuppeteer(Linux, bundled Chromium), with auto-detection - Output: 2x DPI PNG (A4: 1588px wide, Letter: 1632px wide)
- Font stack: System fonts + CJK fallback (PingFang SC, Microsoft YaHei, Noto Sans SC)
Troubleshooting
| Issue | Solution |
|---|---|
| "No Chrome/Edge/Chromium found" | Install Chrome/Chromium or run npm install puppeteer |
| Chinese characters missing on Linux | Install CJK fonts: apt install fonts-noto-cjk |
/dev/shm errors on Linux |
Use --disable-dev-shm-usage (already included) |
| Puppeteer download timeout in China | Set mirror: PUPPETEER_DOWNLOAD_BASE_URL=https://cdn.npmmirror.com/binaries/chrome-for-testing npx puppeteer browsers install chrome |
| Screenshot blank/white | Ensure waitUntil: 'networkidle0' completes; check font availability |