1.0.3 • Published 1 year ago

react-mathjax-component v1.0.3

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

React component for Mathjax

npm CI

react-mathjax-component is a package to render math expressions as React element tree with Mathjax.

Basic usage is very simple. This renders $e = mc^2$. Visit the demo page to see how it works on your browser.

import React from 'react';
import { createRoot } from 'react-dom/client';
import Mathjax from 'react-mathjax-component';

const root = document.getElementById('root');
createRoot(root).render(<Mathjax expr="e = mc^2"/>);

This package is built with the idea of converting Mathjax's LiteDOM into React element tree. It is

  • Clean: No dangerouslySetInnerHTML. No hacky DOM manipulation.
  • Fast: React runtime can do differential update correctly. (Single math expression consists of bunch of SVG elements)
  • Small: No complicated hack for DOM cache and no React context value. It's a single small functional component.

Installation

npm install --save react-mathjax-component

This package assumes React v16 or later and uses Mathjax 3.2 or later.

Motivation

When you use Mathjax in React app, you would use dangerouslySetInnerHTML. However it is not safe as you know. And the React cannot do differential update for the inner HTML string.

Instead, you may use existing several React libraries for Mathjax. However all of them are relying on hacky real DOM manipulations.

In contrast, the idea of converting LiteDOM into React element tree does not need such hacks. And React runtime can do differential DOM update for the coverted React element tree. A simple math expression consists of bunch of SVG elements so this is important for performance.

LiteDOM is a small internal representation used by Mathjax to represent an SVG element tree. It was created to render math expressions on non-browser environment like Node.js. Mathjax converts LiteDOM tree into HTML string. This package converts it into React element tree instead.

Advanced usage

Customize Mathjax document object

By default, this package uses its own Mathjax document object. But you can use your own document object when you want to customize some options (e.g. extra packages). It can be done through document property.

import { mathjax } from 'mathjax-full/js/mathjax';
import { TeX } from 'mathjax-full/js/input/tex';
import { SVG } from 'mathjax-full/js/output/svg';

const yourDocument = mathjax.document('', {
    InputJax: new TeX({ packages: ... }), // customize packages
    OutputJax: new SVG({ fontCache: 'global' }), // customize cache strategy
});

const SomeComponent: React.FC<{expr: string}> = ({expr}) => (
    <Mathjax expr={expr} document={yourDocument} />
);

Styling math expression element

React element tree returned from <Mathjax/> component is a React fragment which contains a SVG element tree. So you can style it as you like with its parent element.

const InlineMath: React.FC<{expr: string}> = ({expr}) => (
    <span className="math-inline">
        <Mathjax expr={expr} />
    </span>
);

const RedMathBlock: React.FC<{expr: string}> = ({expr}) => (
    <div className="math-block" style={{color: 'red'}}>
        <Mathjax expr={expr} />
    </div>
);

API

See the demo source for the working example.

import Mathjax from 'react-mathjax-component'

Signature:

function Mathjax(props: MathjaxProps): React.ReactElement

This returns SVG element tree rendered by Mathjax using the given properties.

import type { MathjaxProps } from 'react-mathjax-component'

Signature:

interface MathjaxProps {
    expr: string;
    document?: Document;
}

expr is the math expression to render.

document is a Mathjax document object. Basically you don't need to set this property because this package uses the default document object when it is not set.

import type { Document } from 'react-mathjax-component'

Signature:

type Document = MathDocument<LiteElement, LiteText, LiteDocument>;

Type for document property.

Bug report or feature request

Please create a new issue ticket.

License

This package is distributed under the MIT license.