@xubpa/ghmd
v0.2.0
Published
GitHub-style Markdown preview: standalone server + VS Code extension
Readme
ghmd — GitHub Markdown Preview
Pixel-perfect GitHub rendering, locally. Works as a standalone server (browser) and a VS Code extension.
Why GHMD?
| | 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 |
Features
| 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 |
Install
git clone [email protected]:Ubpa/ghmd.git
cd ghmd
npm installUsage
Standalone Server
node 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.
Root mode (multi-file)
Serve any markdown file under a directory and switch via ?file=:
node serve.mjs --root ./docs --port 6419
# http://127.0.0.1:6419/ → renders ./docs/README.md (if any)
# http://127.0.0.1:6419/?file=guide.md → renders ./docs/guide.md
# http://127.0.0.1:6419/?file=sub/x.md → renders ./docs/sub/x.md--port 0 lets the OS pick a free port. ghmd prints
LISTENING http://127.0.0.1:<port> on the first stdout line so a parent
process spawning ghmd can pick up the chosen port.
Path is constrained to <root> — .. escapes return 400, non-markdown
files return 400, missing files return 404.
node serve.mjs --init # one-time: downloads katex + mermaid
node serve.mjs README.md # now fully offlineVS Code Extension
Install
npm run package # build + create .vsix
code --install-extension ghmd-*.vsix --extensions-dir ~/.vscode/extensions[!WARNING] The
codeCLI may install to a different extensions directory than your editor loads from (e.g.~/.cursor/extensions/vs~/.vscode/extensions/). Use--extensions-dirto target the correct path. After installing, run Cmd+Shift+P → Developer: Reload Window.
Keybindings
| 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.
Scroll Sync
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
How It Works
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 --> RBoth 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.vsixwith no vendored assets.
Development
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 testsghmd/
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)npm update # update node_modules
npm run build # rebuild vendor/ + dist/
npm run package # create new .vsix