Input Markdown

The Pipeline

Markdown
remark-parse
MDAST
remark-rehype
HAST
rehype-stringify
HTML
typescript
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkGfm from 'remark-gfm';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';

// The pipeline: Markdown → MDAST → HAST → HTML
const result = await unified()
  .use(remarkParse)      // Parse markdown → MDAST
  .use(remarkGfm)        // Add GFM support
  .use(remarkRehype)     // Transform MDAST → HAST
  .use(rehypeStringify)  // Serialize HAST → HTML
  .process('# Hello **world**');

console.log(String(result));
// → '<h1>Hello <strong>world</strong></h1>'

Key Concepts

  • MDAST (Markdown AST) — Tree representation of markdown. Nodes: root, heading, paragraph, text, emphasis, strong, link, code, etc.
  • HAST (HTML AST) — Tree representation of HTML. Nodes: element, text, comment, doctype. Maps directly to DOM.
  • unified — The core processor interface. Composes parsers, transformers, and serializers.
  • remark — Markdown processor. Plugins operate on MDAST.
  • rehype — HTML processor. Plugins operate on HAST.

Custom Plugins

The real power: write custom plugins that transform the AST at any stage:

typescript
// Custom remark plugin example
function remarkCapitalizeHeadings() {
  return (tree) => {
    visit(tree, 'heading', (node) => {
      visit(node, 'text', (textNode) => {
        textNode.value = textNode.value.toUpperCase();
      });
    });
  };
}

// Use it in the pipeline
unified()
  .use(remarkParse)
  .use(remarkCapitalizeHeadings)  // Custom transform
  .use(remarkRehype)
  .use(rehypeStringify)
  .process(markdown);

Popular Plugins

remark-gfm

Tables, task lists, strikethrough, autolinks

remark-math

Math equations ($inline$ and $$block$$)

remark-frontmatter

YAML/TOML frontmatter parsing

rehype-highlight

Syntax highlighting for code blocks

rehype-sanitize

HTML sanitization (XSS protection)

rehype-slug

Add id attributes to headings

Strengths

  • Standard, well-maintained ecosystem
  • Modular — use only what you need
  • Huge plugin library (200+)
  • AST-based — full control over transformations
  • Used by mdsvex, Gatsby, Astro, etc.

Weaknesses

  • Learning curve for AST manipulation
  • Many small packages to manage
  • Processing is async (not always ideal)
  • Documentation spread across many repos