Pixel-perfect GitHub rendering, locally. Works as a standalone server (browser) and a VS Code extension.
| GHMD | Built-in Preview | MPE | |
|---|---|---|---|
| GitHub-accurate rendering | Yes | No | Approximate |
| Alerts, footnotes, math, mermaid | All | None | All |
| Install size | ~420 KB | Built-in | ~50 MB |
| Config required | Zero | Zero | Extensive |
| Standalone server | Yes | No | No |
| Feature | Syntax |
|---|---|
| GitHub Alerts | > [!NOTE], > [!TIP], > [!IMPORTANT], > [!WARNING], > [!CAUTION] |
| Mermaid diagrams | ```mermaid (flowchart, sequence, gantt, class, state, ER, pie, git) |
| LaTeX math | $...$ inline, $$...$$ block |
| Code highlighting | ```lang via marked-highlight + highlight.js |
| Diff highlighting | ```diff with +/- lines |
| Collapsible sections | <details> / <summary> |
| Footnotes | [^label] |
| YAML front matter | --- metadata rendered as table |
| Emoji shortcodes | :sparkles: → ✨ (full GitHub set via gemoji) |
| Auto-linked URLs | Bare URLs become clickable links |
| Task lists | - [x] / - [ ] |
| Keyboard keys | <kbd>Cmd</kbd> |
| Sub/superscript | <sub> / <sup> |
| Theme-aware images | <picture> with prefers-color-scheme |
| Light/dark toggle | Toolbar button, persisted |
| Table of contents | Collapsible TOC panel |
| Live reload | Auto-updates on file change |
git clone git@github.com:Ubpa/ghmd.git
cd ghmd
npm installnode serve.mjs README.md # http://localhost:6419
node serve.mjs docs/guide.md 8080 # custom portAuto-reloads in browser on file change. KaTeX and Mermaid load from CDN.
Offline mode
node serve.mjs --init # one-time: downloads katex + mermaid
node serve.mjs README.md # now fully offlinenpm run package # build + create .vsix
code --install-extension ghmd-*.vsix --extensions-dir ~/.vscode/extensionsWarning
The code CLI may install to a different extensions directory than your editor loads from (e.g. ~/.cursor/extensions/ vs ~/.vscode/extensions/). Use --extensions-dir to target the correct path. After installing, run Cmd+Shift+P → Developer: Reload Window.
| Shortcut | Action |
|---|---|
| Cmd+K V | Open preview to the side |
| Shift+Cmd+V | Open preview (same tab) |
Tip
The preview automatically follows your active markdown editor — no need to reopen when switching files.
The extension replaces the built-in markdown preview button with the GitHub icon. Theme toggle and TOC panel are in the top-right corner.
Bidirectional scroll sync between editor and preview:
- Editor → Preview: scrolling the editor smoothly scrolls the preview to the matching position
- Preview → Editor: scrolling the preview jumps the editor to the corresponding source line
flowchart LR
MD["Markdown file"] --> P[marked + plugins]
P --> H["highlight.js"]
H --> HTML["GitHub-styled HTML"]
HTML --> K["KaTeX (math)"]
HTML --> M["Mermaid (diagrams)"]
K --> R["Rendered preview"]
M --> R
Both entry points share the same pipeline:
- marked parses GFM with plugins: alerts, footnotes, front matter, emoji, auto-linking, syntax highlighting
- marked-highlight + highlight.js handle code syntax highlighting
- source-lines wraps all block renderers to inject
data-source-lineattributes (for scroll sync) - github-markdown-css provides GitHub's exact styling
- KaTeX renders math client-side
- Mermaid renders diagrams client-side
Note
Both entry points load KaTeX, Mermaid, highlight.js CSS, and github-markdown-css from CDN. The standalone server also supports offline mode via --init. The VS Code extension ships as a ~420 KB .vsix with no vendored assets.
npm install # install dependencies
npm run build # bundle extension + server
npm run dev # build with sourcemaps (F5 debugging)
npm run typecheck # tsc type checking only
npm run package # build + create .vsix
npm test # build + VS Code e2e tests (headless)
npx tsx test/unit/frontmatter.test.mts # frontmatter unit tests
npx tsx test/unit/svg-slider.test.mts # SVG slider unit testsProject structure
ghmd/
src/
extension.ts VS Code extension (bundled → dist/extension.cjs)
serve.mts Standalone server (bundled → dist/serve.mjs)
frontmatter.ts YAML front matter extension for marked
source-lines.ts Injects data-source-line attrs for scroll sync
scroll-sync.js Client-side bidirectional scroll sync
ui.css Shared UI styles (read at runtime by both entry points)
toc.js Shared TOC logic (read at runtime by both entry points)
test/
suite/ VS Code e2e tests (mocha + @vscode/test-electron)
unit/ Unit tests (run with tsx, no VS Code required)
dist/ Build output (gitignored)
Updating dependencies
npm update # update node_modules
npm run build # rebuild vendor/ + dist/
npm run package # create new .vsix