diff --git a/md2img/SKILL.md b/md2img/SKILL.md index ca3ab85..f6800ff 100644 --- a/md2img/SKILL.md +++ b/md2img/SKILL.md @@ -5,7 +5,7 @@ description: > (containing Mermaid diagrams, LaTeX math formulas, or rich formatting) into a PNG image. --- -# md2img — Markdown → PNG +# md2img Render Markdown documents into high-quality PNG images with full support for Mermaid diagrams, LaTeX math formulas, code syntax highlighting, and GFM tables. @@ -66,7 +66,7 @@ On Linux servers without a GUI browser, install Chromium: ```bash # Option 1: Install puppeteer (auto-downloads Chromium) -cd ~/.workbuddy/skills/md2img/scripts +cd skills/md2img/scripts npm install puppeteer npx puppeteer browsers install chrome @@ -95,15 +95,36 @@ apk add nss atk cups-libs libdrm libxkbcommon libxcomposite libxdamage \ libxrandr mesa-gbm alsa-lib pango cairo ``` +**Emoji font support (Linux):** + +Linux默认不支持emoji渲染,需安装emoji字体: + +```bash +# Ubuntu/Debian: +sudo apt install -y fonts-noto-color-emoji + +# Fedora: +sudo dnf install -y google-noto-emoji-color-fonts + +# Arch/Manjaro: +sudo pacman -S noto-fonts-emoji + +# Verify: +fc-list | grep -i emoji +fc-match "😀" # Should return: NotoColorEmoji.ttf +``` + + ### Docker deployment ```dockerfile FROM node:20-slim -# Install Chromium dependencies +# Install Chromium dependencies and fonts (including emoji support) RUN apt-get update && apt-get install -y \ chromium \ fonts-noto-cjk \ + fonts-noto-color-emoji \ --no-install-recommends && \ rm -rf /var/lib/apt/lists/* @@ -133,6 +154,7 @@ ENTRYPOINT ["node", "render.js"] |-------|----------| | "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` | +| Emoji显示为方框□ on Linux | Install emoji fonts: `apt install fonts-noto-color-emoji` | | `/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 | diff --git a/md2img/scripts/render.js b/md2img/scripts/render.js index 3b5f4ea..3691c77 100644 --- a/md2img/scripts/render.js +++ b/md2img/scripts/render.js @@ -223,8 +223,9 @@ function buildHtml(md) { // CSS template function buildCss(theme) { const isDark = theme === 'dark'; - // CJK font stack: Linux优先使用Noto Sans CJK,macOS用PingFang,Windows用Microsoft YaHei + // CJK font stack with emoji support const cjkFonts = "'Noto Sans SC', 'Noto Sans CJK SC', 'Source Han Sans SC', 'WenQuanYi Micro Hei', 'PingFang SC', 'Microsoft YaHei', sans-serif"; + const emojiFonts = "'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji', 'Noto Emoji', 'Android Emoji', 'EmojiOne Color', sans-serif"; return ` @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;600;700&display=swap'); @@ -249,7 +250,7 @@ body { width: ${PAGE_WIDTH}px; background: var(--bg); color: var(--text); - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', ${cjkFonts}; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', ${cjkFonts}, ${emojiFonts}; font-size: 14px; line-height: 1.7; padding: ${MARGIN}px; @@ -265,7 +266,7 @@ ul, ol { margin: 0.6em 0; padding-left: 1.8em; } li { margin: 0.2em 0; } li > p { margin: 0.3em 0; } pre { margin: 0.8em 0; padding: 12px 16px; border-radius: 6px; overflow-x: auto; font-size: 13px; background: var(--code-bg); border: 1px solid var(--border); } -code { font-family: 'Cascadia Code', 'Fira Code', 'JetBrains Mono', 'Consolas', 'Noto Sans Mono CJK SC', monospace; font-size: 0.9em; } +code { font-family: 'Cascadia Code', 'Fira Code', 'JetBrains Mono', 'Consolas', 'Noto Sans Mono CJK SC', ${emojiFonts}, monospace; font-size: 0.9em; } p code, li code { padding: 2px 6px; border-radius: 4px; background: var(--code-bg); border: 1px solid var(--border); } table { border-collapse: collapse; margin: 0.8em 0; width: 100%; } th, td { border: 1px solid var(--border); padding: 6px 12px; text-align: left; }