data-math

Enhance code elements with precompiled MathML rendering. Add data-math to any code element for automatic MathML injection with numbering, copy, and Markdown integration.

Overview

The data-math attribute enhances <code> elements with precompiled MathML. The original LaTeX source stays readable without JavaScript, and when JS runs, it is replaced by rendered MathML.

<code data-math data-mathml="<math display='block'><mi>x</mi><mo>=</mo><mfrac><mrow><mo>-</mo><mi>b</mi><mo>&pm;</mo><msqrt><msup><mi>b</mi><mn>2</mn></msup><mo>-</mo><mn>4</mn><mi>a</mi><mi>c</mi></msqrt></mrow><mrow><mn>2</mn><mi>a</mi></mrow></mfrac></math>"> x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a} </code>

How It Works

  1. Add data-math to a <code> element with LaTeX source as its text content
  2. Add data-mathml with the precompiled MathML string
  3. On page load, the script reads data-mathml, injects a <math> element, and hides the original <code>
  4. Without data-mathml, the LaTeX source displays as-is — readable fallback with no JS dependency

Attributes

Attribute Type Description
data-math token list Space-separated tokens: inline, numbered, copyable. An empty value defaults to block rendering.
data-mathml string Precompiled MathML string to inject. Without this, the element shows the raw LaTeX source.
data-math-state string Set automatically: "rendered" when MathML injected, "source" when showing raw LaTeX.
data-math-init boolean Set automatically to prevent double-binding. Do not set manually.

Tokens

Token Description
inline Renders inline math, wrapping in a <span> instead of a <div>.
numbered Auto-increments the equation counter and displays a number. Registers in window.VBMath.equations if the element has an id.
copyable Clicking the rendered math copies the original LaTeX source to the clipboard with a screen reader announcement.

Inline Math

Use the inline token for math that flows within paragraph text.

The area is \pi r^2 .

<p>The area is <code data-math="inline" data-mathml="<math><mi>&pi;</mi><msup><mi>r</mi><mn>2</mn></msup></math>"> \pi r^2 </code>. </p>

Numbered Equations

Combine numbered with an id for linkable, numbered equations.

E = mc^2
<code data-math="numbered" id="eq-energy" data-mathml="<math display='block'><mi>E</mi><mo>=</mo><mi>m</mi><msup><mi>c</mi><mn>2</mn></msup></math>"> E = mc^2 </code> <p>See <a href="#eq-energy">Equation 1</a>.</p>

Copyable Math

The copyable token adds a click-to-copy interaction. Clicking copies the LaTeX source to the clipboard and announces it to screen readers.

\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}
<code data-math="copyable" data-mathml="<math display='block'><msubsup><mo>&int;</mo><mn>0</mn><mo>&infin;</mo></msubsup><msup><mi>e</mi><mrow><mo>-</mo><msup><mi>x</mi><mn>2</mn></msup></mrow></msup><mi>d</mi><mi>x</mi><mo>=</mo><mfrac><msqrt><mi>&pi;</mi></msqrt><mn>2</mn></mfrac></math>"> \int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2} </code>

Markdown Integration

Markdown processors emit code.language-math for fenced math blocks. The enhancement script auto-detects these — no extra configuration needed.

```math x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a} ```

This produces the standard HTML output:

<pre><code class="language-math"> x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a} </code></pre>

The code.language-math selector is matched automatically alongside [data-math]. For precompiled MathML, add data-mathml to the element at build time via a Remark or Markdown-it plugin.

Events

Event Detail Description
math:rendered { latex, inline, number } Fired after MathML is injected. latex is the source text, inline is a boolean, number is the equation number (or null).
const el = document.querySelector('[data-math]'); el.addEventListener('math:rendered', (e) => { console.log('LaTeX:', e.detail.latex); console.log('Inline:', e.detail.inline); console.log('Number:', e.detail.number); });

Progressive Enhancement

Without data-mathml, the LaTeX source displays as a readable <code> block. This is the no-JS fallback:

<code data-math>E = mc^2</code> <!-- Without data-mathml, the LaTeX source displays as readable code -->

The element receives data-math-state="source" so you can style the fallback state differently if needed.

Dynamic Content

Elements added to the DOM after page load are automatically enhanced via a MutationObserver. No manual initialization needed.

const code = document.createElement('code'); code.dataset.math = 'inline'; code.dataset.mathml = '<math><mi>x</mi></math>'; code.textContent = 'x'; document.body.appendChild(code); // Auto-enhanced via MutationObserver

Accessibility

  • The injected <math> element is natively understood by screen readers (VoiceOver, NVDA)
  • The original LaTeX source is preserved in the DOM as hidden fallback content
  • Copy confirmation uses aria-live="polite" for screen reader announcements
  • Numbered equations are linkable via id and standard <a href>