{"id":50966851,"url":"https://github.com/mash/markdown-fast","last_synced_at":"2026-06-18T21:03:00.289Z","repository":{"id":357720760,"uuid":"1227500006","full_name":"mash/markdown-fast","owner":"mash","description":"A faster Markdown preview for VS Code. Drop-in replacement for the builtin — TTFP drops from ~4.6s to under 1s on large code-heavy docs.","archived":false,"fork":false,"pushed_at":"2026-05-03T17:34:18.000Z","size":1384,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-14T03:06:11.364Z","etag":null,"topics":["autoresearch","claude-code","markdown","markdown-preview","performance","vscode","vscode-extension"],"latest_commit_sha":null,"homepage":"https://marketplace.visualstudio.com/items?itemName=maaashjp.markdown-fast","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mash.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-02T19:13:55.000Z","updated_at":"2026-05-04T13:22:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mash/markdown-fast","commit_stats":null,"previous_names":["mash/markdown-fast"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/mash/markdown-fast","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mash%2Fmarkdown-fast","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mash%2Fmarkdown-fast/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mash%2Fmarkdown-fast/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mash%2Fmarkdown-fast/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mash","download_url":"https://codeload.github.com/mash/markdown-fast/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mash%2Fmarkdown-fast/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34507160,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-18T02:00:06.871Z","response_time":128,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["autoresearch","claude-code","markdown","markdown-preview","performance","vscode","vscode-extension"],"created_at":"2026-06-18T21:02:59.105Z","updated_at":"2026-06-18T21:03:00.284Z","avatar_url":"https://github.com/mash.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Markdown Fast\n\nA faster Markdown preview for VS Code.\n\n## Why\n\nI didn't have a problem with the builtin Markdown viewer until this morning, when I opened a large plan file and it took at least a whole second before anything showed up. In the AI era we're reading a lot more Markdown than before — especially long, code-heavy design documents written in plan mode — and those pauses add up.\n\nMarkdown Fast is a fork of the builtin that keeps the same UX — same `markdown-it` pipeline, same keybindings, same syntax highlighting, same scroll-sync — but cuts time-to-first-paint by deferring and slicing work that the builtin does eagerly. You see the top of the document immediately; the rest fills in just after, with off-screen syntax highlighting deferred until you scroll there.\n\nIt's a drop-in replacement. Disable the builtin `vscode.markdown-language-features` extension to make Markdown Fast the default previewer.\n\n![demo](docs/media/before-after.gif)\n\n## Install\n\n**From the Marketplace (recommended):** [maaashjp.markdown-fast](https://marketplace.visualstudio.com/items?itemName=maaashjp.markdown-fast)\n\n```bash\ncode --install-extension maaashjp.markdown-fast\n```\n\nOr search for \"Markdown Fast\" in the Extensions sidebar (`⇧⌘X`).\n\n**From VSIX:**\n\n```bash\ncd ext/markdown-fast\nnpm install\nnpm run package         # compiles + produces markdown-fast-*.vsix\ncode --install-extension markdown-fast-*.vsix\n```\n\n**From source (development):**\n\n```bash\n(cd ext/markdown-fast \u0026\u0026 npm install)\nnpm run build\n# then launch a dev VS Code with --extensionDevelopmentPath=./ext/markdown-fast\n```\n\n**Usage:** open a `.md` file and press `⇧⌘V` (preview) or `⌘K V` (preview to side).\n\n### Disable the builtin Markdown preview\n\nMarkdown Fast and the builtin both register the same commands and view types, so to make Markdown Fast the active previewer you should disable the builtin.\n\n1. Open the **Extensions** sidebar (`⇧⌘X`).\n2. In the search box, type `@builtin markdown language features`.\n3. Click the entry **\"Markdown Language Features\"** (publisher: `vscode`) and choose **Disable** (or **Disable (Workspace)** if you only want it disabled in this project). Only this one — leave **\"Markdown Language Basics\"**, **\"Markdown Math\"**, and any other `@builtin markdown ...` extensions enabled.\n\nAfter disabling, reload the window (`⌘R` / `Cmd+Shift+P` → \"Developer: Reload Window\") so VS Code picks up the change.\n\nOn first activation Markdown Fast will also prompt to set itself as the default editor for `*.md` (writing `workbench.editorAssociations` to your user settings). Without this, opening a `.md` still goes to the plain text editor; with it, opening goes straight to the rendered preview.\n\n![default editor prompt](docs/media/default-editor-prompt.png)\n\n## How is it fast\n\nThree optimizations, all benchmarked to actually move TTFP, run together:\n\n- **Lazy highlight** — `highlight.js` is deferred from the host to the webview, and only visible code blocks get highlighted on first paint. The rest highlight as you scroll.\n- **Viewport-first rendering** — the visible viewport is rendered and painted before anything below the fold; the rest of the document is rendered after first paint.\n- **Token-boundary slicing** — the document is parsed once, then split at top-level markdown-it token boundaries: only the viewport's tokens are rendered synchronously; the rest is rendered lazily after first paint. Splitting on tokens (not source lines) means a slice never bisects a fenced code block, list, table, or blockquote.\n\nNet effect: TTFP on a large plan file drops from roughly 4.6s to under 1s in the bench harness. Correctness and final DOM match the builtin once everything has finished rendering.\n\n---\n\n## Benchmarks \u0026 autoresearch\n\nThis repo is also an experiment: applying Karpathy's [autoresearch](https://github.com/karpathy/autoresearch) idea — let an agent run a tight measure → propose → keep-or-revert loop against a hard metric — to user-interfacing software instead of model training. The hard metric here is **TTFP (Time To First Paint)** of the preview pane, measured in two flavors:\n\n- **Offline TTFP-host** — `parse + render(+ highlight)` in Node, measured by `benchmark/bench-engine.ts`. Fast feedback for host-side changes.\n- **E2E TTFP** — wall-clock time between the harness pressing `Enter` in Quick Open and the first heading rendering inside the preview webview, captured via Playwright + Chrome DevTools Protocol.\n\n```bash\nnpm run bench:e2e                                                              # baseline (builtin VS Code preview)\nnpm run build\nBENCH_FORK=1 BENCH_LAZY_HL=1 BENCH_VIEWPORT_FIRST=1 BENCH_TOKEN_SLICE=1 npm run bench:e2e\n```\n\nEach run writes one JSON to `benchmark/results/e2e-${variant}.json`, including per-iteration TTFP samples and `[BENCH]`-prefixed phase markers (parse/render on the host, firstMorph/firstAnimFrame in the webview) so regressions can be attributed to a phase rather than a vague \"slower.\"\n\nThe harness opens files via Quick Open (`Cmd+P` → type filename → `Enter`). Both variants are configured so the rendered preview is the default editor for `*.md` — the fork via its `customEditor` contribution, the baseline via a `workbench.editorAssociations` setting written into the test user-data dir — so a single `Enter` opens straight into a preview. Same gesture, same code path, apples-to-apples.\n\n### Autoresearch\n\nThe `autoresearch` skill (`.claude/skills/autoresearch/SKILL.md`) runs the loop autonomously: pick an idea, edit the fork, build, bench, log to `results.tsv`, and either commit-and-keep or revert based on the numbers. The decision rule is simple: **keep** if median TTFP improves ≥3% and p95 doesn't regress \u003e5%; otherwise **discard**.\n\n![autoresearch progress](docs/media/autoresearch-progress.png)\n\nThe chart above is a representative run: each grey dot is a discarded experiment, each green dot is a kept improvement, and the green staircase is the running best.\n\nThe optimizations themselves were written by the autoresearch loop. I worked with Claude Code to set up the benchmark harness, the fork scaffolding, and the skill, contributed the \"viewport-first rendering\" idea, and let the loop iterate on the rest.\n\n## Layout\n\n```\nbenchmark/\n  gen-corpus.ts            deterministic synthetic .md generator (4 profiles × 4 sizes)\n  bench-engine.ts          offline (Node) markdown-it + highlight.js phase timings\n  e2e/run-ttfp.ts          E2E harness; baseline or fork via BENCH_FORK=1\n  e2e-summarize.ts         joins offline + e2e numbers into a markdown report\n  results/                 *.json + *.md (gitignored — re-run to reproduce)\next/markdown-fast/         the extension; this is what we're optimizing\ntmp/vscode-markdown/       upstream microsoft/vscode shallow clone (reference; not edited)\ntmp/corpus/                generated test corpus (gitignored)\n```\n\n## Conventions\n\n- Synthetic corpus is deterministic (LCG-seeded); regenerate with `npm run gen:corpus`.\n- Results JSON is gitignored — re-run benchmarks to reproduce.\n\n## License \u0026 credits\n\nMIT — see [LICENSE](LICENSE). Forked from [microsoft/vscode/extensions/markdown-language-features](https://github.com/microsoft/vscode/tree/main/extensions/markdown-language-features), © Microsoft Corporation, also MIT.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmash%2Fmarkdown-fast","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmash%2Fmarkdown-fast","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmash%2Fmarkdown-fast/lists"}