Skip to content

About

Chrome extension that renders raw Markdown as readable HTML in place — GFM, syntax highlighting, TOC sidebar, Mermaid diagrams, and KaTeX math. Works on local files and raw web URLs.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Markdown Viewer

A Chrome extension that renders raw Markdown as readable HTML, in place.

Open a .md file in Chrome and you get unstyled plain text. This extension detects those pages and renders them properly — headings, tables, syntax-highlighted code, diagrams, math — while keeping the original URL and a one-click toggle back to the source.

Works on local files (file://) and on raw Markdown served over the web.

Features

  • GitHub Flavored Markdown — tables, task lists, strikethrough, autolinks
  • Syntax highlighting for fenced code blocks via highlight.js
  • Table of contents sidebar with scroll-spy, auto-generated from headings
  • Mermaid diagrams — ```mermaid fences render as flowcharts, sequence diagrams, and more
  • Math — $inline$ and $$block$$ LaTeX via KaTeX
  • Light and dark themes that follow your system setting
  • Toggle to source at any time, with no refetch — works offline
  • Nothing leaves your machine. No network requests, no analytics, no remote code.

Mermaid (~1 MB) and KaTeX (~250 kB) load only when a document actually contains them. A typical document loads neither.

Install

Not yet on the Chrome Web Store, so installation is manual.

From a release (recommended)

  1. Download the latest ZIP from Releases and unzip it
  2. Open chrome://extensions
  3. Enable Developer mode (top right)
  4. Click Load unpacked and select the unzipped folder
  5. Click Details on the extension card and enable Allow access to file URLs

No Node.js or build step required.

From source

git clone https://github.com/cemhurturk/chrome-markdown-viewer.git
cd chrome-markdown-viewer
npm install
npm run build

Then follow steps 2–5 above, selecting the dist/ folder.

Two things to know

Step 5 is required for local files. Chrome does not allow extensions to request that permission programmatically — you have to grant it by hand. Without it the extension still works on Markdown served over the web, but local .md files keep showing as plain text. The extension opens a page explaining this on first install.

Developer mode is unavoidable outside the Web Store. Chrome has blocked installing extensions from outside the store since Chrome 33, so there is no one-click install from GitHub. Chrome will show a "Disable developer mode extensions" prompt on startup, and some managed work profiles block Developer mode entirely.

Limitations

Content-Type: text/markdown triggers a download instead of a render. When a web server sends that header, Chrome downloads the file rather than displaying it, so no content script ever runs and the extension cannot help. Servers sending text/plain — including GitHub raw URLs — work fine.

Strict page CSPs can block diagrams and math. Mermaid and KaTeX load at runtime as separate chunks. A page whose Content-Security-Policy forbids that (raw.githubusercontent.com sends default-src 'none') will still render Markdown, but diagrams fall back to an error card and math stays as raw LaTeX text.

Non-ASCII headings get generic anchor ids. A heading in CJK or Cyrillic produces section, section-1, and so on. The TOC links still work; the anchors are just not meaningful.

Editing and saving

Toggling to the source view on a local file:// page gives you an editable textarea instead of read-only text. This only works on file:// pages — there is no writeback path for http(s) URLs, so Markdown served over the web stays read-only source.

The first time you save, Chrome shows a native file-save dialog so you confirm which file on disk you're writing to. Every later save in that same tab writes to the same file silently, with no further dialog. Cmd+S (or Ctrl+S on Windows/Linux) saves from the textarea, same as the Save button. If you close or navigate away from the tab with unsaved edits, Chrome warns you before letting you leave.

How it works

Chrome already displays .md files as plain text inside a <pre> element. A content script reads that text, renders it, and replaces the document body — so the URL never changes, bookmarks keep working, and reload behaves normally.

Module Responsibility
src/detect.ts Pure predicate: is this page raw Markdown?
src/render.ts Pure transform: Markdown → sanitized HTML + heading metadata
src/content.ts The only impure unit — reads the DOM, swaps the page, wires the toggle
src/toc.ts Sidebar construction and scroll-spy
src/lazy.ts Runtime loading of Mermaid/KaTeX, with per-block error handling
src/background.ts Opens the onboarding page once on install

detect.ts and render.ts are pure functions — string in, value out — which is why the bulk of the test suite needs no browser.

Detection is deliberately conservative

The extension renders a page only when all of these hold:

  1. The document body contains exactly one element child, a <pre> (Chrome's plain-text signature)
  2. The URL path ends in .md, .markdown, or .mdown — a .md in a query string does not count
  3. The page has not already been rendered

A false negative just means you see raw text. A false positive would mean destroying a real webpage's DOM. The second is far worse, so the rules err toward doing nothing.

Security

A .md file is fully untrusted input — it can contain <script> tags, onerror= handlers, and javascript: URLs.

  • All rendered HTML passes through DOMPurify before entering the DOM
  • Author-supplied id attributes are stripped, so a document cannot hijack a TOC anchor
  • <style> is forbidden in rendered Markdown — including inside <svg>, where it would otherwise apply document-wide and could blank the page
  • Mermaid runs with securityLevel: 'strict'; KaTeX runs with trust: false
  • No remote code is loaded; every dependency is bundled, as Manifest V3 requires

The XSS test cases in the suite are treated as non-negotiable.

Failure behavior

A rendering failure always degrades to readable text, never to a broken page.

Failure Behavior
Markdown parsing throws Page left completely untouched — you see the raw source
A Mermaid diagram is malformed That block shows an inline error card; the rest of the page renders
A math expression is malformed Same — a per-block error card, document survives
Mermaid or KaTeX fails to load Affected blocks fall back to displaying their source text

Development

npm test          # run the test suite (93 tests)
npm run build     # build to dist/

After rebuilding, click the reload icon on the extension card at chrome://extensions.

The build produces three bundles for a reason. Manifest V3 content scripts declared in the manifest cannot be ES modules, so content.js is a self-contained IIFE. But await import() at runtime requires an ES module target, so the Mermaid and KaTeX chunks are built separately as ESM and exposed through web_accessible_resources. The service worker is a third IIFE bundle.

Contributions are welcome. If you change rendering behavior, please add a test — and if you touch sanitization, do not weaken an existing XSS test to make something pass.

Built with

marked · DOMPurify · highlight.js · Mermaid · KaTeX

KaTeX's stylesheet and WOFF2 fonts are vendored into public/ because Manifest V3 forbids loading them remotely. They remain under KaTeX's MIT license.

License

MIT — see LICENSE.

About

Chrome extension that renders raw Markdown as readable HTML in place — GFM, syntax highlighting, TOC sidebar, Mermaid diagrams, and KaTeX math. Works on local files and raw web URLs.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages