mdlib-pure

Markdown, to the letter.

mdlib-pure renders Markdown to HTML in the browser and follows CommonMark to the letter: all 652 spec examples, in 11.04 KB gzipped, with zero dependencies.

npm install https://github.com/MichelePolo/mdlib-pure/releases/download/mdlib-pure-v0.1.1/mdlib-pure-0.1.1.tgz

Not on the npm registry yet: this installs the tarball attached to the GitHub release. Other ways to install.

Read the docs Open the playground

Markdown

Result

Try it here

The result updates as you type, with gfm() and mark.

  • CommonMark 0.31.2, 652 of 652 examples
  • tables, strikethrough, footnotes, alerts
  • your plugin

Tip

The DOM is built without parsing HTML.

A live example: edit the text, mdlib-pure renders it in your browser.

Datasheet

CommonMark 0.31.2
652 of 652 spec examples, with byte-identical output
GitHub Flavored Markdown
54 of 54 extension examples, in the optional mdlib-pure/gfm plugin (3.92 KB gzip)
Size
11.04 KB minified and gzipped, within a 15 KB budget checked by npm run size
Runtime dependencies
none, checked by npm run check
Safe by default
raw HTML not recognized, URLs filtered by an allowlist, DOM built without parsing HTML
Linear time
on adversarial input too: 30+ hostile inputs with time limits in test/pathological.test.ts
Output
an HTML string, DOM nodes, React, Preact and Vue elements through the adapter, or the <mdlib-markdown> and <mdlib-editor> Web Components, which the Blazor and Angular wrappers build on

Ways to use it

One parser and one renderer behind five entry points: pick the one your stack speaks. None is on a package registry yet: each guide says how to install it today.

JavaScript

The core API: render() returns an HTML string, renderTo() builds DOM nodes without parsing HTML. Each plugin is one more import.

import { createMarkdown } from 'mdlib-pure'
import { gfm } from 'mdlib-pure/gfm'

const md = createMarkdown({ plugins: gfm() })
md.render('# Hello')        // an HTML string
md.renderTo(el, '# Hello')  // DOM nodes, no HTML parsing

HTML: Web Components

mdlib-pure/element defines <mdlib-markdown>, a viewer, and <mdlib-editor>, an editor with toolbar and live preview, for plain pages and any framework. Core and every plugin included: 20.19 KB gzip.

<script type="module">
  // with a bundler or an import map
  import { defineElements } from 'mdlib-pure/element'
  defineElements()
</script>

<mdlib-markdown class="md" plugins="gfm"
  source="# Hello"></mdlib-markdown>
<mdlib-editor name="body" plugins="all"
  value="# Draft"></mdlib-editor>

React, Preact, Vue

mdlib-pure/adapter turns the output into elements with the framework’s own createElement or h, following its conventions: className, defaultChecked, keys.

import { createElement } from 'react'
import { toElements } from 'mdlib-pure/adapter'

export const Markdown = ({ source }) => (
  <article className="md">
    {toElements(md.toVNodes(source), createElement, 'react')}
  </article>
)
// Vue: toElements(vnodes, h, 'vue')
// Preact: toElements(vnodes, h, 'preact')

Blazor (.NET 10)

MdlibPure.Blazor 0.2.0 wraps the Web Components for every render mode (Static SSR, Server, WebAssembly, Auto): @bind-Value, EditForm validation, a C# service for the AST and a podcast editor (PodcastEditor). Not on nuget.org yet: the .nupkg is attached to the GitHub release.

@using MdlibPure.Blazor

<MarkdownEditor @bind-Value="Body" Plugins="MarkdownPlugins.All" />
<Markdown Value="@Body" Plugins="MarkdownPlugins.Gfm" />

Angular (21, 22)

ngx-mdlib-pure 0.2.0: standalone components whose tag is the Web Component, [(value)] with signals, a form control for ngModel and reactive forms, SSR with hydration, a service for the AST and a podcast editor (ngx-mdlib-pure/podcast). Not on npm yet, like mdlib-pure: both tarballs are attached to GitHub releases.

// app.config.ts
providers: [provideMdlibPure({ loaders: { mermaid: () => import('mermaid') } })]

// a component, imports: [MarkdownEditor, MarkdownViewer]
template: `
  <mdlib-editor [(value)]="body" plugins="all" />
  <mdlib-markdown [source]="body()" plugins="all" />`

Plugins

The core does CommonMark and nothing else. Everything else is one import away: each plugin is a separate module, measured on its own, so you pay only for what you use. First-party plugins use the same API that is open to you: block rules, inline rules, delimiter runs, AST transforms and render overrides.

Plugin Adds gzip
mdlib-pure/gfm tables, task lists, footnotes, strikethrough, autolinks, alerts 3.92 KB
mdlib-pure/headings heading ids, permalinks, table of contents 0.56 KB
mdlib-pure/container ::: container blocks 0.81 KB
mdlib-pure/math $inline$, $$display$$ and $$ blocks 0.94 KB
mdlib-pure/mermaid ```mermaid diagrams, no dependency on Mermaid 1.49 KB
mdlib-pure/deflist definition lists 1.22 KB
mdlib-pure/mark ==highlight== 0.13 KB
mdlib-pure/frontmatter YAML and TOML front matter 0.57 KB
mdlib-pure/adapter React, Preact and Vue elements 0.53 KB
mdlib-pure/element the <mdlib-markdown> viewer and the <mdlib-editor> editor with live preview, as Web Components (core and every plugin included) 20.19 KB
mdlib-pure/entities the full HTML entity table, for Node, SSR and workers 10.75 KB

All plugins, with syntax and examples

Performance

As fast as marked, faster than markdown-it, smaller than both, and as conformant as commonmark.js.

Library CommonMark examples (exact) spec.txt MB/s README MB/s min + gzip
mdlib-pure 652/652 43.5 36.4 10.9 KB
marked 503/652 44.6 32.7 14.0 KB
markdown-it 649/652 35.6 22.0 40.6 KB
commonmark.js 652/652 47.4 48.2 46.8 KB

Node 22.22.1, render to an HTML string, median of 15 runs, measured on 28 October 2026; differences under about 10% are noise. With GFM: mdlib-pure + gfm() 39.6 / 25.1 MB/s, marked 38.8 / 27.2 MB/s, markdown-it 28.7 / 17.4 MB/s; mdlib-pure also does footnotes, task lists and alerts. Full method and results.

For AI agents

This site reads fine without a browser. Every page has a Markdown version at the same address with .md, and /llms.txt lists them all.

  • Start at /llms.txt, or take everything in one file with /llms-full.txt.
  • AGENTS.md is the extension contract: rules checked by commands, recipes for each extension point, a definition of done.
  • To get a plugin from an agent: “Read AGENTS.md and write a plugin that…”, then let it run npm run verify. Example prompts are in the guide for agents.
  • To use it in an app rather than extend it, the guides are docs/elements.md for the Web Components, bindings/blazor/README.md for Blazor and bindings/angular/README.md for Angular; all are in llms-full.txt.
  • Nothing is on a registry yet: no npm install mdlib-pure, no NuGet package. Each guide's Install section says what works today.

The start of /llms.txt

# mdlib-pure

> Lightweight, zero-dependency Markdown renderer for the browser: 100% CommonMark 0.31.2 (652/652 spec examples), GitHub Flavored Markdown as an opt-in plugin (54/54 extension examples), an ~11 KB gzipped core, safe by default, linear time on any input. Extensible through plugins, styled with semantic CSS tokens, output as HTML, DOM, React/Preact/Vue elements, or the <mdlib-markdown> and <mdlib-editor> Web Components, which the MdlibPure.Blazor (.NET 10) and ngx-mdlib-pure (Angular) wrappers build on. Not on a package registry yet (no npm, no NuGet): the Install section of each guide says how to install it today.

Every page of this site has a Markdown version at the same path with `.md`; the docs are the repository's own Markdown files. To extend the library, read AGENTS.md ("Extending: plugin guide") fully first: it is the contract for AI agents, and `npm run verify` must pass before a task is done. To use it in a page or an app, the guides are docs/elements.md (Web Components), bindings/blazor/README.md (Blazor) and bindings/angular/README.md (Angular). Nothing is published on npm or NuGet yet: never suggest `npm install mdlib-pure`; README.md (Install) gives the tarball URL on the GitHub release.

## Docs

- [Getting started](https://michelepolo.github.io/mdlib-pure/docs/getting-started.md): install, usage, options, highlighting, frameworks, styling, plugins, performance