remark-math

repository·main·Indexed 19 days ago

https://github.com/remarkjs/remark-math

A suite of unified plugins for handling LaTeX math in Markdown and HTML. Includes remark-math for parsing math syntax in Markdown, and rehype-katex and rehype-mathjax for rendering math nodes into static HTML at compile time, eliminating the need for client-side JavaScript.

Tokens
6K
Snippets
20
Records
25
Agent score
66%

What's inside remark-math

  1. Overview of remark-math packages

    main

    The remark-math monorepo provides a suite of plugins for handling LaTeX math in Markdown and HTML using the unified ecosystem. It is split into three primary packages:

    1. remark-math: A remark plugin that adds support for math syntax in Markdown (both inline and display math) or via fenced code blocks (```math).
    2. rehype-katex: A rehype plugin that renders math nodes into HTML using the KaTeX engine.
    3. rehype-mathjax: A rehype plugin that renders math nodes into HTML using the MathJax engine.

    This workflow allows you to parse math syntax during the Markdown processing phase and render it into static HTML at compile time, eliminating the need for client-side JavaScript for math rendering.

  2. Install rehype-mathjax

    main

    Install the package via npm for Node.js (version 18+). Note that this package is ESM only.

    In Deno with esm.sh:

    import rehypeMathjax from 'https://esm.sh/rehype-mathjax@7'

    In browsers with esm.sh:

    <script type="module">
      import rehypeMathjax from 'https://esm.sh/rehype-mathjax@7?bundle'
    </script>
    npm install rehype-mathjax
  3. Use rehype-mathjax to render math

    main

    The plugin transforms HTML elements with classes language-math, math-inline, or math-display into MathJax-rendered content.

    • math-inline or <code class="language-math"> results in inline math.
    • math-display or <pre><code class="language-math"> results in "display" math (centered block on its own line).

    It also supports the remark-math syntax extension and fenced code blocks like:

    C_L
    import rehypeMathjax from 'rehype-mathjax'
    import rehypeParse from 'rehype-parse'
    import rehypeStringify from 'rehype-stringify'
    import {read, write} from 'to-vfile'
    import {unified} from 'unified'
    
    const file = await unified()
      .use(rehypeParse, {fragment: true})
      .use(rehypeMathjax)
      .use(rehypeStringify)
      .process(await read('input.html'))
    
    file.basename = 'output.html'
    await write(file)
  4. Secure math rendering with rehype-sanitize

    main

    If you do not trust user-generated content, you should run rehype-mathjax after rehype-sanitize. You must update the rehype-sanitize schema to allow the language-* class names used for math identification.

    import rehypeMathjax from 'rehype-mathjax'
    import rehypeSanitize, {defaultSchema} from 'rehype-sanitize'
    import rehypeStringify from 'rehype-stringify'
    import remarkMath from 'remark-math'
    import remarkParse from 'remark-parse'
    import remarkRehype from 'remark-rehype'
    import {unified} from 'unified'
    
    const file = await unified()
      .use(remarkParse)
      .use(remarkMath)
      .use(remarkRehype)
      .use(rehypeSanitize, {
        ...defaultSchema,
        attributes: {
          ...defaultSchema.attributes,
          // The `language-*` regex is allowed by default.
          code: [['className', /^language-./, 'math-inline', 'math-display']]
        }
      })
      .use(rehypeMathjax)
      .use(rehypeStringify)
      .process('$C$')
    
    console.log(String(file))
  5. Use rehype-katex to render math

    main

    Use rehype-katex within a unified pipeline to transform HTML elements with specific classes into rendered KaTeX math.

    Supported classes:

    • language-math: Used for both inline and display math (often via fenced code blocks).
    • math-inline: For inline math.
    • math-display: For centered block (display) math.

    When using rehype-document, ensure you include the KaTeX CSS in the document head so the math renders correctly in the browser.

    import rehypeDocument from 'rehype-document'
    import rehypeKatex from 'rehype-katex'
    import rehypeParse from 'rehype-parse'
    import rehypeStringify from 'rehype-stringify'
    import {read, write} from 'to-vfile'
    import {unified} from 'unified'
    
    const file = await unified()
      .use(rehypeParse, {fragment: true})
      .use(rehypeDocument, {
        // Get the latest one from: <https://katex.org/docs/browser>.
        css: 'https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css'
      })
      .use(rehypeKatex)
      .use(rehypeStringify)
      .process(await read('input.html'))
    
    file.basename = 'output.html'
    await write(file)
  6. Render math with KaTeX

    main

    To render math using KaTeX, you need to include remark-math to parse the syntax and rehype-katex to transform the nodes into HTML.

    Important: KaTeX requires its CSS to render correctly. You must include the KaTeX CSS in your final HTML page (e.g., via a CDN link) to ensure the math is styled properly.

    import rehypeKatex from 'rehype-katex'
    import rehypeStringify from 'rehype-stringify'
    import remarkMath from 'remark-math'
    import remarkParse from 'remark-parse'
    import remarkRehype from 'remark-rehype'
    import {read} from 'to-vfile'
    import {unified} from 'unified'
    
    const file = await unified()
      .use(remarkParse)
      .use(remarkMath)
      .use(remarkRehype)
      .use(rehypeKatex)
      .use(rehypeStringify)
      .process(await read('example.md'))
    
    console.log(String(file))

    Required CSS for KaTeX:

    <link href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" rel="stylesheet">
  7. Install remark-math

    main

    remark-math is an ESM-only package. Use the following commands depending on your environment:

    Node.js (version 16+):

    npm install remark-math

    Deno (via esm.sh):

    import remarkMath from 'https://esm.sh/remark-math@6'

    Browsers (via esm.sh):

    <script type="module">
      import remarkMath from 'https://esm.sh/remark-math@6?bundle'
    </script>
  8. Render math with MathJax

    main

    To render math using MathJax, replace rehype-katex with rehype-mathjax in your unified pipeline. This will transform math nodes into MathJax-compatible HTML (such as <mjx-container> elements).

    import rehypeMathjax from 'rehype-mathjax'
    import rehypeStringify from 'rehype-stringify'
    import remarkMath from 'remark-math'
    import remarkParse from 'remark-parse'
    import remarkRehype from 'remark-rehype'
    import {read} from 'to-vfile'
    import {unified} from 'unified'
    
    const file = await unified()
      .use(remarkParse)
      .use(remarkMath)
      .use(remarkRehype)
      .use(rehypeMathjax)
      .use(rehypeStringify)
      .process(await read('example.md'))
    
    console.log(String(file))
  9. Install rehype-katex

    main

    Install rehype-katex depending on your runtime. Note that this package is ESM only.

    Node.js (version 16+):

    npm install rehype-katex

    Deno:

    import rehypeKatex from 'https://esm.sh/rehype-katex@7'

    Browsers:

    <script type="module">
      import rehypeKatex from 'https://esm.sh/rehype-katex@7?bundle'
    </script>
    npm install rehype-katex
  10. Use remark-math in a unified pipeline

    main

    To support math syntax in your markdown processing pipeline, include remarkMath in your unified() chain. Typically, you will also need remark-parse to parse the markdown, remark-rehype to convert the markdown syntax tree (mdast) to an HTML syntax tree (hast), and a rehype plugin like rehype-katex or rehype-mathjax to actually render the math into HTML.

    Example workflow:

    1. remark-parse parses the markdown.
    2. remark-math identifies math syntax.
    3. remark-rehype converts math nodes to HTML elements.
    4. rehype-katex (or similar) renders the math.
    5. rehype-stringify produces the final HTML string.
    import rehypeKatex from 'rehype-katex'
    import rehypeStringify from 'rehype-stringify'
    import remarkMath from 'remark-math'
    import remarkParse from 'remark-parse'
    import remarkRehype from 'remark-rehype'
    import {read} from 'to-vfile'
    import {unified} from 'unified'
    
    const file = await unified()
      .use(remarkParse)
      .use(remarkMath)
      .use(remarkRehype)
      .use(rehypeKatex)
      .use(rehypeStringify)
      .process(await read('example.md'))
    
    console.log(String(file))
  11. Securely use rehype-katex with rehype-sanitize

    main

    If you are processing untrusted user input, you must run rehype-katex after rehype-sanitize. You also need to update the rehype-sanitize schema to allow the language-* class names on code elements so they aren't stripped before reaching the KaTeX plugin.

    import rehypeKatex from 'rehype-katex'
    import rehypeSanitize, {defaultSchema} from 'rehype-sanitize'
    import rehypeStringify from 'rehype-stringify'
    import remarkMath from 'remark-math'
    import remarkParse from 'remark-parse'
    import remarkRehype from 'remark-rehype'
    import {unified} from 'unified'
    
    const file = await unified()
      .use(remarkParse)
      .use(remarkMath)
      .use(remarkRehype)
      .use(rehypeSanitize, {
        ...defaultSchema,
        attributes: {
          ...defaultSchema.attributes,
          // The `language-*` regex is allowed by default.
          code: [['className', /^language-./, 'math-inline', 'math-display']]
        }
      })
      .use(rehypeKatex)
      .use(rehypeStringify)
      .process('$C$')
    
    console.log(String(file))
  12. Configure remarkMath options

    main

    The remarkMath plugin accepts an optional options object to control math parsing behavior.

    OptionTypeDefaultDescription
    singleDollarTextMathbooleantrueWhether to support inline math using a single dollar sign ($). If set to false, you must use two or more dollars for text math.
    // Example of disabling single dollar support
    .use(remarkMath, { singleDollarTextMath: false })