kern

Typst math, in the browser.

Install

npm install kern-typ
pnpm add kern-typ

The npm package is kern-typ because kern was already registered. The UMD global, CSS prefix, and everything else is still kern.

Via CDN (jsDelivr):

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/kern-typ/styles/kern.css">
<script src="https://cdn.jsdelivr.net/npm/kern-typ/dist/kern.min.js"></script>

Via unpkg:

<script src="https://unpkg.com/kern-typ/dist/kern.min.js"></script>

Quick start

import { render, renderToString } from 'kern-typ';

// Render into a DOM element
render('frac(a, b)', document.getElementById('math'));

// Render to string (for SSR or innerHTML)
const html = renderToString('x^2 + y^2 = r^2');
document.getElementById('math').innerHTML = html;

UMD (script tag):

<script src="https://cdn.jsdelivr.net/npm/kern-typ/dist/kern.min.js"></script>
<script>
  kern.render('e^(i pi) + 1 = 0', document.getElementById('math'));
</script>

API

render(source, element, options?)

Renders Typst math source into element, replacing its contents. Throws ParseError on invalid input unless throwOnError: false.

kern.render('sum_(i=0)^n i^2', el);
kern.render('frac(x, y)', el, { displayMode: true });

renderToString(source, options?)

Returns the rendered HTML string without touching the DOM.

const html = kern.renderToString('alpha + beta = gamma', {
  output: 'mathml',
  displayMode: false,
});

Options

Option Type Default Description
displayMode boolean false Block (display) vs. inline rendering
output 'mathml' | 'html' | 'htmlAndMathml' 'mathml' Output format
throwOnError boolean true Throw ParseError on invalid input
errorColor string '#cc0000' Error message color when throwOnError is false
macros Record<string, string> {} Custom macro definitions
strict boolean | 'ignore' | 'warn' | 'error' 'warn' Strictness level for unrecognized input
trust boolean | function false Trust level for security-sensitive features

Auto-render

Automatically find and render all math delimiters in a DOM subtree. Same interface as KaTeX's auto-render extension.

import renderMathInElement from 'kern-typ/auto-render';

renderMathInElement(document.body, {
  delimiters: [
    { left: '$$', right: '$$', display: true },
    { left: '$',  right: '$',  display: false },
    { left: '\\[', right: '\\]', display: true },
    { left: '\\(', right: '\\)', display: false },
  ],
  ignoredTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'],
  errorCallback: (msg, err) => console.warn(msg, err),
});

Auto-render options

OptionDescription
delimiters Array of { left, right, display } objects
ignoredTags Tag names whose content is skipped
ignoredClasses Elements with these classes are skipped
errorCallback Called with (message, error) on parse failure
preProcess Transform math string before rendering

Output modes

output: 'mathml' (default) emits a native <math> element. All major browsers support MathML as of 2023. This is the recommended mode.

output: 'html' emits a span tree using kern-* CSS classes, styled by kern.css. Useful for environments that don't support MathML (older webviews, PDF renderers).

output: 'htmlAndMathml' emits both: the HTML tree is aria-hidden and the MathML element provides accessible semantics.

Errors

kern throws a ParseError (subclass of Error) with two extra fields: position (byte offset in the source string) and source (the original input).

import { ParseError } from 'kern-typ';

try {
  kern.renderToString('frac(x,');
} catch (e) {
  if (e instanceof ParseError) {
    console.log(e.position); // offset of the unexpected token
    console.log(e.source);   // the original input string
  }
}

Set throwOnError: false to render a styled error span instead of throwing.

Migration from KaTeX

kern's API is intentionally identical to KaTeX's. The only changes are the import name and the math source syntax.

KaTeXkern
katex.render(src, el) kern.render(src, el)
\frac{a}{b} frac(a, b)
\sqrt{x} sqrt(x)
x_{n+1} x_(n+1)
\hat{f} hat(f)
\mathbf{x} bold(x)
\mathcal{A} cal(A)
\mathbb{R} bb(R)
\text{hello} "hello"
\alpha, \beta alpha, beta
\infty infinity

Syntax cheat sheet

Each example is rendered live by kern:

Fonts

For Typst visual parity, include kern-newcm.css after kern.css. It loads New Computer Modern Math (Typst's default math font) from fred-wang/MathFonts via jsDelivr:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/kern-typ/styles/kern.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/kern-typ/styles/kern-newcm.css">

For MathML output, the browser uses its system math font by default. Add this to your CSS to use New Computer Modern Math for MathML elements too:

@font-face {
  font-family: 'NewCMMath-Regular';
  src: url('https://cdn.jsdelivr.net/gh/fred-wang/MathFonts@master/NewComputerModern/fonts/NewCMMath-Regular.woff2') format('woff2'),
       url('https://cdn.jsdelivr.net/gh/fred-wang/MathFonts@master/NewComputerModern/fonts/NewCMMath-Regular.woff') format('woff');
}

math {
  font-family: 'NewCMMath-Regular', 'New Computer Modern Math', serif;
}