Socket
Socket
Sign inDemoInstall

rehype-mathjax

Package Overview
Dependencies
Maintainers
2
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rehype-mathjax - npm Package Compare versions

Comparing version 4.0.3 to 5.0.0

lib/browser.d.ts

10

browser.d.ts

@@ -1,8 +0,2 @@

export default rehypeMathJaxBrowser
export type Options = import('./lib/create-plugin').Options
declare const rehypeMathJaxBrowser: (
this: import('unified').Processor<void, import('hast').Root, void, void>,
options?: void | import('./lib/create-plugin.js').Options | undefined
) =>
| void
| import('unified').Transformer<import('hast').Root, import('hast').Root>
export { default } from "./lib/browser.js";
export type Options = import('./lib/create-plugin.js').Options;

20

browser.js
/**
* @typedef {import('./lib/create-plugin').Options} Options
* @typedef {import('./lib/create-plugin.js').Options} Options
*/
import {createPlugin} from './lib/create-plugin.js'
const rehypeMathJaxBrowser = createPlugin((options) => {
const tex = options.tex || {}
const display = tex.displayMath || [['\\[', '\\]']]
const inline = tex.inlineMath || [['\\(', '\\)']]
return {
render(node, options) {
const delimiters = (options.display ? display : inline)[0]
node.children.unshift({type: 'text', value: delimiters[0]})
node.children.push({type: 'text', value: delimiters[1]})
}
}
})
export default rehypeMathJaxBrowser
export {default} from './lib/browser.js'

@@ -1,8 +0,2 @@

export default rehypeMathJaxCHtml
export type Options = import('./lib/create-plugin').Options
declare const rehypeMathJaxCHtml: (
this: import('unified').Processor<void, import('hast').Root, void, void>,
options?: void | import('./lib/create-plugin.js').Options | undefined
) =>
| void
| import('unified').Transformer<import('hast').Root, import('hast').Root>
export { default } from "./lib/chtml.js";
export type Options = import('./lib/create-plugin.js').Options;
/**
* @typedef {import('./lib/create-plugin').Options} Options
* @typedef {import('./lib/create-plugin.js').Options} Options
*/
import {CHTML} from 'mathjax-full/js/output/chtml.js'
import {createRenderer} from './lib/create-renderer.js'
import {createPlugin} from './lib/create-plugin.js'
const rehypeMathJaxCHtml = createPlugin((options) => {
if (!options.chtml || !options.chtml.fontURL) {
throw new Error(
'rehype-mathjax: missing `fontURL` in options, which must be set to a URL to reach MathJaX fonts'
)
}
return createRenderer(options, new CHTML(options.chtml))
})
export default rehypeMathJaxCHtml
export {default} from './lib/chtml.js'
/**
* Create a plugin.
*
* @param {CreateRenderer} createRenderer
* Create a renderer.
* @returns
* Plugin.
*/
export function createPlugin(
createRenderer: CreateRenderer
): (
this: import('unified').Processor<void, import('hast').Root, void, void>,
options?: void | Options | undefined
) =>
| void
| import('unified').Transformer<import('hast').Root, import('hast').Root>
export type Root = import('hast').Root
export type Element = import('hast').Element
export function createPlugin(createRenderer: CreateRenderer): (options?: Readonly<Options> | null | undefined) => (tree: Root) => undefined;
export type Element = import('hast').Element;
export type ElementContent = import('hast').ElementContent;
export type Root = import('hast').Root;
/**
* Create a renderer.
*/
export type CreateRenderer = (options: Readonly<Options>) => Renderer;
/**
* Format an error.
*/
export type FormatError = (jax: any, error: any) => string;
/**
* Configuration for input tex math.
* <http://docs.mathjax.org/en/latest/options/input/tex.html#the-configuration-block>
*/
export type InputTexOptions = {
/**
* URL for use with links to tags, when there is a `<base>` tag in effect
* (optional).
*/
baseURL?: string | null | undefined;
/**
* Pattern for recognizing numbers (optional).
*/
digits?: RegExp | null | undefined;
/**
* Start/end delimiter pairs for display math (optional).
*/
displayMath?: ReadonlyArray<MathNotation> | null | undefined;
/**
* Function called when TeX syntax errors occur (optional).
*/
formatError?: FormatError | null | undefined;
/**
* Start/end delimiter pairs for in-line math (optional).
*/
inlineMath?: ReadonlyArray<MathNotation> | null | undefined;
/**
* Max size for the internal TeX string (5K) (optional).
*/
maxBuffer?: number | null | undefined;
/**
* Max number of macro substitutions per expression (optional).
*/
maxMacros?: number | null | undefined;
/**
* Extensions to use (optional).
*/
packages?: ReadonlyArray<string> | null | undefined;
/**
* Process `\begin{xxx}...\end{xxx}` outside math mode (optional).
*/
processEnvironments?: boolean | null | undefined;
/**
* Use `\$` to produce a literal dollar sign (optional).
*/
processEscapes?: boolean | null | undefined;
/**
* Process `\ref{...}` outside of math mode (optional).
*/
processRefs?: boolean | null | undefined;
/**
* Amount to indent tags (optional).
*/
tagIndent?: string | null | undefined;
/**
* Side for `\tag` macros (optional).
*/
tagSide?: 'left' | 'right' | null | undefined;
/**
* Optional.
*/
tags?: 'all' | 'ams' | 'none' | null | undefined;
/**
* Use label name rather than tag for ids (optional).
*/
useLabelIds?: boolean | null | undefined;
};
/**
* Markers to use for math.
* See: <http://docs.mathjax.org/en/latest/options/input/tex.html#the-configuration-block>
*/
export type MathNotation = [string, string]
export type MathNotation = [string, string];
/**
* <http://docs.mathjax.org/en/latest/options/output/svg.html#the-configuration-block>
* Configuration.
*
* ###### Notes
*
* When using `rehype-mathjax/browser`, only `options.tex.displayMath` and
* `options.tex.inlineMath` are used.
* That plugin will use the first delimiter pair in those fields to wrap
* math.
* Then you need to load MathJax yourself on the client and start it with the
* same markers.
* You can pass other options on the client.
*
* When using `rehype-mathjax/chtml`, `options.chtml.fontURL` is required.
* For example:
*
* ```js
* // …
* .use(rehypeMathjaxChtml, {
* chtml: {
* fontURL: 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/output/chtml/fonts/woff-v2'
* }
* })
* // …
* ```
*/
export type OutputSvgOptions = {
scale?: number | undefined
minScale?: number | undefined
mtextInheritFont?: boolean | undefined
merrorInheritFont?: boolean | undefined
mathmlSpacing?: boolean | undefined
skipAttributes?: Record<string, boolean> | undefined
exFactor?: number | undefined
displayAlign?: 'left' | 'center' | 'right' | undefined
displayIndent?: string | undefined
fontCache?: 'local' | 'global' | undefined
localID?: string | null | undefined
internalSpeechTitles?: boolean | undefined
titleID?: number | undefined
}
export type Options = {
/**
* Configuration for the output, when CHTML (optional).
*/
chtml?: Readonly<OutputCHtmlOptions> | null | undefined;
/**
* Configuration for the output, when SVG (optional).
*/
svg?: Readonly<OutputSvgOptions> | null | undefined;
/**
* Configuration for the input TeX (optional).
*/
tex?: Readonly<InputTexOptions> | null | undefined;
};
/**
* Configuration for output CHTML.
* <http://docs.mathjax.org/en/latest/options/output/chtml.html#the-configuration-block>
*/
export type OutputCHtmlOptions = {
scale?: number | undefined
minScale?: number | undefined
matchFontHeight?: boolean | undefined
mtextInheritFont?: boolean | undefined
merrorInheritFont?: boolean | undefined
mathmlSpacing?: boolean | undefined
skipAttributes?: Record<string, boolean> | undefined
exFactor?: number | undefined
displayAlign?: 'left' | 'center' | 'right' | undefined
displayIndent?: string | undefined
fontURL: string
adaptiveCSS?: boolean | undefined
}
/**
* `true` means only produce CSS that is used in the processed equations (optional).
*/
adaptiveCSS?: boolean | null | undefined;
/**
* Default for indentalign when set to `'auto'` (optional).
*/
displayAlign?: 'center' | 'left' | 'right' | null | undefined;
/**
* Default for indentshift when set to `'auto'` (optional).
*/
displayIndent?: string | null | undefined;
/**
* Default size of ex in em units (optional).
*/
exFactor?: number | null | undefined;
/**
* The URL where the fonts are found (**required**).
*/
fontURL: string;
/**
* `true` to match ex-height of surrounding font (optional).
*/
matchFontHeight?: boolean | null | undefined;
/**
* `true` for MathML spacing rules, false for TeX rules (optional).
*/
mathmlSpacing?: boolean | null | undefined;
/**
* `true` to make merror text use surrounding font (optional).
*/
merrorInheritFont?: boolean | null | undefined;
/**
* Smallest scaling factor to use (optional).
*/
minScale?: number | null | undefined;
/**
* `true` to make mtext elements use surrounding font (optional).
*/
mtextInheritFont?: boolean | null | undefined;
/**
* Global scaling factor for all expressions (optional).
*/
scale?: number | null | undefined;
/**
* RFDa and other attributes NOT to copy to the output (optional).
*/
skipAttributes?: Readonly<Record<string, boolean>> | null | undefined;
};
/**
* <http://docs.mathjax.org/en/latest/options/input/tex.html#the-configuration-block>
* Configuration for output SVG.
* <http://docs.mathjax.org/en/latest/options/output/svg.html#the-configuration-block>
*/
export type InputTexOptions = {
packages?: string[] | undefined
inlineMath?: MathNotation[] | undefined
displayMath?: MathNotation[] | undefined
processEscapes?: boolean | undefined
processEnvironments?: boolean | undefined
processRefs?: boolean | undefined
digits?: RegExp | undefined
tags?: 'none' | 'ams' | 'all' | undefined
tagSide?: 'left' | 'right' | undefined
tagIndent?: string | undefined
useLabelIds?: boolean | undefined
multlineWidth?: string | undefined
maxMacros?: number | undefined
maxBuffer?: number | undefined
baseURL?: string | undefined
formatError?: ((jax: any, error: any) => string) | undefined
}
export type OutputSvgOptions = {
/**
* Default for indentalign when set to `'auto'` (optional).
*/
displayAlign?: 'center' | 'left' | 'right' | null | undefined;
/**
* Default for indentshift when set to `'auto'` (optional).
*/
displayIndent?: string | null | undefined;
/**
* Default size of ex in em units (optional).
*/
exFactor?: number | null | undefined;
/**
* Or `'global'` or `'none'` (optional).
*/
fontCache?: 'global' | 'local' | 'none' | null | undefined;
/**
* Insert `<title>` tags with speech content (optional).
*/
internalSpeechTitles?: boolean | null | undefined;
/**
* ID to use for local font cache, for single equation processing (optional).
*/
localID?: string | null | undefined;
/**
* `true` for MathML spacing rules, `false` for TeX rules (optional).
*/
mathmlSpacing?: boolean | null | undefined;
/**
* `true` to make merror text use surrounding font (optional).
*/
merrorInheritFont?: boolean | null | undefined;
/**
* Smallest scaling factor to use (optional).
*/
minScale?: number | null | undefined;
/**
* `true` to make mtext elements use surrounding font (optional).
*/
mtextInheritFont?: boolean | null | undefined;
/**
* Global scaling factor for all expressions (optional).
*/
scale?: number | null | undefined;
/**
* RFDa and other attributes *not* to copy to the output (optional).
*/
skipAttributes?: Readonly<Record<string, boolean>> | null | undefined;
/**
* Initial ID number to use for `aria-labeledby` titles (optional).
*/
titleID?: number | null | undefined;
};
/**
* Render a math node.
*/
export type Render = (value: string, options: Readonly<RenderOptions>) => Array<ElementContent>;
/**
* Configuration.
*/
export type Options = {
/**
* Configuration for the input TeX.
*/
tex?: InputTexOptions | undefined
/**
* Configuration for the output (when CHTML).
*/
chtml?: OutputCHtmlOptions | undefined
/**
* Configuration for the output (when SVG).
*/
svg?: OutputSvgOptions | undefined
}
export type RenderOptions = {
/**
* Whether to render display math.
*/
display: boolean;
};
/**
* Renderer.
*/
export type Renderer = {
render: (
node: Element,
options: {
display: boolean
}
) => void
styleSheet?: (() => Element) | undefined
}
export type CreateRenderer = (options: Options) => Renderer
/**
* Render a math node.
*/
render: Render;
/**
* Render a style sheet (optional).
*/
styleSheet?: StyleSheet | null | undefined;
};
/**
* Render a style sheet.
*/
export type StyleSheet = () => Element;
/**
* @typedef {import('hast').Element} Element
* @typedef {import('hast').ElementContent} ElementContent
* @typedef {import('hast').Root} Root
* @typedef {import('hast').Element} Element
*/
/**
* @callback CreateRenderer
* Create a renderer.
* @param {Readonly<Options>} options
* Configuration.
* @returns {Renderer}
* Rendeder.
*
* @callback FormatError
* Format an error.
* @param {any} jax
* MathJax object.
* @param {any} error
* Error.
* @returns {string}
* Formatted error.
*
* @typedef InputTexOptions
* Configuration for input tex math.
* <http://docs.mathjax.org/en/latest/options/input/tex.html#the-configuration-block>
* @property {string | null | undefined} [baseURL]
* URL for use with links to tags, when there is a `<base>` tag in effect
* (optional).
* @property {RegExp | null | undefined} [digits]
* Pattern for recognizing numbers (optional).
* @property {ReadonlyArray<MathNotation> | null | undefined} [displayMath]
* Start/end delimiter pairs for display math (optional).
* @property {FormatError | null | undefined} [formatError]
* Function called when TeX syntax errors occur (optional).
* @property {ReadonlyArray<MathNotation> | null | undefined} [inlineMath]
* Start/end delimiter pairs for in-line math (optional).
* @property {number | null | undefined} [maxBuffer]
* Max size for the internal TeX string (5K) (optional).
* @property {number | null | undefined} [maxMacros]
* Max number of macro substitutions per expression (optional).
* @property {ReadonlyArray<string> | null | undefined} [packages]
* Extensions to use (optional).
* @property {boolean | null | undefined} [processEnvironments]
* Process `\begin{xxx}...\end{xxx}` outside math mode (optional).
* @property {boolean | null | undefined} [processEscapes]
* Use `\$` to produce a literal dollar sign (optional).
* @property {boolean | null | undefined} [processRefs]
* Process `\ref{...}` outside of math mode (optional).
* @property {string | null | undefined} [tagIndent]
* Amount to indent tags (optional).
* @property {'left' | 'right' | null | undefined} [tagSide]
* Side for `\tag` macros (optional).
* @property {'all' | 'ams' | 'none' | null | undefined} [tags]
* Optional.
* @property {boolean | null | undefined} [useLabelIds]
* Use label name rather than tag for ids (optional).
*
* @typedef {[string, string]} MathNotation

@@ -9,103 +63,208 @@ * Markers to use for math.

*
* @typedef OutputSvgOptions
* <http://docs.mathjax.org/en/latest/options/output/svg.html#the-configuration-block>
* @property {number} [scale]
* @property {number} [minScale]
* @property {boolean} [mtextInheritFont]
* @property {boolean} [merrorInheritFont]
* @property {boolean} [mathmlSpacing]
* @property {Record<string, boolean>} [skipAttributes]
* @property {number} [exFactor]
* @property {'left'|'center'|'right'} [displayAlign]
* @property {string} [displayIndent]
* @property {'local'|'global'} [fontCache]
* @property {string|null} [localID]
* @property {boolean} [internalSpeechTitles]
* @property {number} [titleID]
* @typedef Options
* Configuration.
*
* ###### Notes
*
* When using `rehype-mathjax/browser`, only `options.tex.displayMath` and
* `options.tex.inlineMath` are used.
* That plugin will use the first delimiter pair in those fields to wrap
* math.
* Then you need to load MathJax yourself on the client and start it with the
* same markers.
* You can pass other options on the client.
*
* When using `rehype-mathjax/chtml`, `options.chtml.fontURL` is required.
* For example:
*
* ```js
* // …
* .use(rehypeMathjaxChtml, {
* chtml: {
* fontURL: 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/output/chtml/fonts/woff-v2'
* }
* })
* // …
* ```
* @property {Readonly<OutputCHtmlOptions> | null | undefined} [chtml]
* Configuration for the output, when CHTML (optional).
* @property {Readonly<OutputSvgOptions> | null | undefined} [svg]
* Configuration for the output, when SVG (optional).
* @property {Readonly<InputTexOptions> | null | undefined} [tex]
* Configuration for the input TeX (optional).
*
* @typedef OutputCHtmlOptions
* Configuration for output CHTML.
* <http://docs.mathjax.org/en/latest/options/output/chtml.html#the-configuration-block>
* @property {number} [scale]
* @property {number} [minScale]
* @property {boolean} [matchFontHeight]
* @property {boolean} [mtextInheritFont]
* @property {boolean} [merrorInheritFont]
* @property {boolean} [mathmlSpacing]
* @property {Record<string, boolean>} [skipAttributes]
* @property {number} [exFactor]
* @property {'left'|'center'|'right'} [displayAlign]
* @property {string} [displayIndent]
* @property {boolean | null | undefined} [adaptiveCSS]
* `true` means only produce CSS that is used in the processed equations (optional).
* @property {'center' | 'left' | 'right' | null | undefined} [displayAlign]
* Default for indentalign when set to `'auto'` (optional).
* @property {string | null | undefined} [displayIndent]
* Default for indentshift when set to `'auto'` (optional).
* @property {number | null | undefined} [exFactor]
* Default size of ex in em units (optional).
* @property {string} fontURL
* @property {boolean} [adaptiveCSS]
* The URL where the fonts are found (**required**).
* @property {boolean | null | undefined} [matchFontHeight]
* `true` to match ex-height of surrounding font (optional).
* @property {boolean | null | undefined} [mathmlSpacing]
* `true` for MathML spacing rules, false for TeX rules (optional).
* @property {boolean | null | undefined} [merrorInheritFont]
* `true` to make merror text use surrounding font (optional).
* @property {number | null | undefined} [minScale]
* Smallest scaling factor to use (optional).
* @property {boolean | null | undefined} [mtextInheritFont]
* `true` to make mtext elements use surrounding font (optional).
* @property {number | null | undefined} [scale]
* Global scaling factor for all expressions (optional).
* @property {Readonly<Record<string, boolean>> | null | undefined} [skipAttributes]
* RFDa and other attributes NOT to copy to the output (optional).
*
* @typedef InputTexOptions
* <http://docs.mathjax.org/en/latest/options/input/tex.html#the-configuration-block>
* @property {string[]} [packages]
* @property {MathNotation[]} [inlineMath]
* @property {MathNotation[]} [displayMath]
* @property {boolean} [processEscapes]
* @property {boolean} [processEnvironments]
* @property {boolean} [processRefs]
* @property {RegExp} [digits]
* @property {'none'|'ams'|'all'} [tags]
* @property {'left'|'right'} [tagSide]
* @property {string} [tagIndent]
* @property {boolean} [useLabelIds]
* @property {string} [multlineWidth]
* @property {number} [maxMacros]
* @property {number} [maxBuffer]
* @property {string} [baseURL]
* @property {(jax: any, error: any) => string} [formatError]
* @typedef OutputSvgOptions
* Configuration for output SVG.
* <http://docs.mathjax.org/en/latest/options/output/svg.html#the-configuration-block>
* @property {'center' | 'left' | 'right' | null | undefined} [displayAlign]
* Default for indentalign when set to `'auto'` (optional).
* @property {string | null | undefined} [displayIndent]
* Default for indentshift when set to `'auto'` (optional).
* @property {number | null | undefined} [exFactor]
* Default size of ex in em units (optional).
* @property {'global' | 'local' | 'none' | null | undefined} [fontCache]
* Or `'global'` or `'none'` (optional).
* @property {boolean | null | undefined} [internalSpeechTitles]
* Insert `<title>` tags with speech content (optional).
* @property {string | null | undefined} [localID]
* ID to use for local font cache, for single equation processing (optional).
* @property {boolean | null | undefined} [mathmlSpacing]
* `true` for MathML spacing rules, `false` for TeX rules (optional).
* @property {boolean | null | undefined} [merrorInheritFont]
* `true` to make merror text use surrounding font (optional).
* @property {number | null | undefined} [minScale]
* Smallest scaling factor to use (optional).
* @property {boolean | null | undefined} [mtextInheritFont]
* `true` to make mtext elements use surrounding font (optional).
* @property {number | null | undefined} [scale]
* Global scaling factor for all expressions (optional).
* @property {Readonly<Record<string, boolean>> | null | undefined} [skipAttributes]
* RFDa and other attributes *not* to copy to the output (optional).
* @property {number | null | undefined} [titleID]
* Initial ID number to use for `aria-labeledby` titles (optional).
*
* @typedef Options
* @callback Render
* Render a math node.
* @param {string} value
* Math value.
* @param {Readonly<RenderOptions>} options
* Configuration.
* @property {InputTexOptions} [tex]
* Configuration for the input TeX.
* @property {OutputCHtmlOptions} [chtml]
* Configuration for the output (when CHTML).
* @property {OutputSvgOptions} [svg]
* Configuration for the output (when SVG).
* @returns {Array<ElementContent>}
* Content.
*
* @typedef RenderOptions
* Configuration.
* @property {boolean} display
* Whether to render display math.
*
* @typedef Renderer
* @property {(node: Element, options: {display: boolean}) => void} render
* @property {() => Element} [styleSheet]
* Renderer.
* @property {Render} render
* Render a math node.
* @property {StyleSheet | null | undefined} [styleSheet]
* Render a style sheet (optional).
*
* @callback CreateRenderer
* @param {Options} options
* @returns {Renderer}
* @callback StyleSheet
* Render a style sheet.
* @returns {Element}
* Style sheet.
*/
import {visit, SKIP} from 'unist-util-visit'
import {toText} from 'hast-util-to-text'
import {SKIP, visitParents} from 'unist-util-visit-parents'
/** @type {Readonly<Options>} */
const emptyOptions = {}
/** @type {ReadonlyArray<unknown>} */
const emptyClasses = []
/**
* Create a plugin.
*
* @param {CreateRenderer} createRenderer
* Create a renderer.
* @returns
* Plugin.
*/
export function createPlugin(createRenderer) {
/** @type {import('unified').Plugin<[Options?]|void[], Root>} */
return (options = {}) =>
(tree) => {
const renderer = createRenderer(options)
/**
* Plugin.
*
* @param {Readonly<Options> | null | undefined} [options]
* Configuration (optional).
* @returns
* Transform.
*/
return function (options) {
/**
* Transform.
*
* @param {Root} tree
* Tree.
* @returns {undefined}
* Nothing.
*/
return function (tree) {
const renderer = createRenderer(options || emptyOptions)
let found = false
/** @type {Root|Element} */
/** @type {Element | Root} */
let context = tree
visit(tree, 'element', (node) => {
const classes =
node.properties && Array.isArray(node.properties.className)
? node.properties.className
: []
const inline = classes.includes('math-inline')
const display = classes.includes('math-display')
visitParents(tree, 'element', function (element, parents) {
const classes = Array.isArray(element.properties.className)
? element.properties.className
: emptyClasses
// This class can be generated from markdown with ` ```math `.
const languageMath = classes.includes('language-math')
// This class is used by `remark-math` for flow math (block, `$$\nmath\n$$`).
const mathDisplay = classes.includes('math-display')
// This class is used by `remark-math` for text math (inline, `$math$`).
const mathInline = classes.includes('math-inline')
let display = mathDisplay
if (node.tagName === 'head') {
context = node
// Find `<head>`.
if (element.tagName === 'head') {
context = element
}
if (!inline && !display) {
// Any class is fine.
if (!languageMath && !mathDisplay && !mathInline) {
return
}
let parent = parents[parents.length - 1]
let scope = element
// If this was generated with ` ```math `, replace the `<pre>` and use
// display.
if (
element.tagName === 'code' &&
languageMath &&
parent &&
parent.type === 'element' &&
parent.tagName === 'pre'
) {
scope = parent
parent = parents[parents.length - 2]
display = true
}
/* c8 ignore next -- verbose to test. */
if (!parent) return
found = true
renderer.render(node, {display})
const text = toText(scope, {whitespace: 'pre'})
const result = renderer.render(text, {display})
const index = parent.children.indexOf(scope)
parent.children.splice(index, 1, ...result)
return SKIP

@@ -118,2 +277,3 @@ })

}
}
}
/**
* Create a renderer.
*
* @param {Options} options
* Configuration.
* @param {OutputJax} output
* Output jax.
* @returns {Renderer}
* Rendeder.
*/
export function createRenderer(
options: Options,
output: import('mathjax-full/js/core/OutputJax').OutputJax<
HTMLElement,
Text,
Document
>
): Renderer
export type Element = import('hast').Element
export type OutputJax = import('mathjax-full/js/core/OutputJax').OutputJax<
HTMLElement,
Text,
Document
>
export type MathDocument =
import('mathjax-full/js/core/MathDocument.js').MathDocument<
HTMLElement,
Text,
Document
>
export type TeX_ = import('mathjax-full/js/input/tex.js').TeX<
HTMLElement,
Text,
Document
>
export type Options = import('./create-plugin.js').Options
export type Renderer = import('./create-plugin.js').Renderer
export function createRenderer(options: Options, output: import("mathjax-full/js/core/OutputJax.js").OutputJax<HTMLElement, Text, Document>): Renderer;
export type Element = import('hast').Element;
export type MathDocument = import('mathjax-full/js/core/MathDocument.js').MathDocument<HTMLElement, Text, Document>;
export type OutputJax = import('mathjax-full/js/core/OutputJax.js').OutputJax<HTMLElement, Text, Document>;
export type Options = import('./create-plugin.js').Options;
export type Renderer = import('./create-plugin.js').Renderer;
/**
* @typedef {import('hast').Element} Element
* @typedef {import('mathjax-full/js/core/OutputJax').OutputJax<HTMLElement, Text, Document>} OutputJax
* @typedef {import('mathjax-full/js/core/MathDocument.js').MathDocument<HTMLElement, Text, Document>} MathDocument
* @typedef {import('mathjax-full/js/input/tex.js').TeX<HTMLElement, Text, Document>} TeX_
* @typedef {import('mathjax-full/js/core/OutputJax.js').OutputJax<HTMLElement, Text, Document>} OutputJax
* @typedef {import('./create-plugin.js').Options} Options

@@ -10,13 +9,12 @@ * @typedef {import('./create-plugin.js').Renderer} Renderer

import {mathjax} from 'mathjax-full/js/mathjax.js'
import {fromDom} from 'hast-util-from-dom'
import {RegisterHTMLHandler} from 'mathjax-full/js/handlers/html.js'
import {TeX} from 'mathjax-full/js/input/tex.js'
import {AllPackages} from 'mathjax-full/js/input/tex/AllPackages.js'
import {fromDom} from 'hast-util-from-dom'
import {toText} from 'hast-util-to-text'
import {createAdaptor} from './create-adaptor.js'
import {mathjax} from 'mathjax-full/js/mathjax.js'
import {createAdapter} from '#create-adapter'
const adaptor = createAdaptor()
const adapter = createAdapter()
// To do next major: Keep resultant HTML handler from `register(adaptor)` to
// To do next major: Keep resultant HTML handler from `register(adapter)` to
// allow registering the `AssistiveMmlHandler` as in this demo:

@@ -32,11 +30,16 @@ // <https://github.com/mathjax/MathJax-demos-node/tree/master/direct>

/* eslint-disable-next-line new-cap */
RegisterHTMLHandler(adaptor)
RegisterHTMLHandler(adapter)
/**
* Create a renderer.
*
* @param {Options} options
* Configuration.
* @param {OutputJax} output
* Output jax.
* @returns {Renderer}
* Rendeder.
*/
export function createRenderer(options, output) {
const input = new TeX(Object.assign({packages: AllPackages}, options.tex))
const input = new TeX({packages: AllPackages, ...options.tex})
/** @type {MathDocument} */

@@ -46,13 +49,11 @@ const doc = mathjax.document('', {InputJax: input, OutputJax: output})

return {
render(node, options) {
const domNode = fromDom(
// @ts-expect-error: assume mathml nodes can be handled by
// `hast-util-from-dom`.
doc.convert(toText(node, {whitespace: 'pre'}), options)
)
// @ts-expect-error: `fromDom` returns an element for a given element.
node.children = [domNode]
render(value, options) {
// Cast as this practically results in `HTMLElement`.
const domNode = /** @type {HTMLElement} */ (doc.convert(value, options))
// Cast as `HTMLElement` results in an `Element`.
const hastNode = /** @type {Element} */ (fromDom(domNode))
return [hastNode]
},
styleSheet() {
const value = adaptor.textContent(output.styleSheet(doc))
const value = adapter.textContent(output.styleSheet(doc))

@@ -59,0 +60,0 @@ return {

{
"name": "rehype-mathjax",
"version": "4.0.3",
"version": "5.0.0",
"description": "rehype plugin to transform inline and block math with MathJax",
"license": "MIT",
"keywords": [
"unified",
"remark",
"rehype",
"rehype-plugin",
"plugin",
"mdast",
"markdown",
"hast",
"html",
"latex",
"markdown",
"math",
"mathjax",
"latex",
"tex"
"mdast",
"plugin",
"rehype",
"rehype-plugin",
"remark",
"tex",
"unified"
],

@@ -34,4 +34,17 @@ "repository": "https://github.com/remarkjs/remark-math/tree/main/packages/rehype-mathjax",

"type": "module",
"main": "index.js",
"types": "index.d.ts",
"exports": {
".": "./svg.js",
"./browser": "./browser.js",
"./chtml": "./chtml.js",
"./svg": "./svg.js"
},
"imports": {
"#create-adapter": {
"deno": "./lib/create-adapter.default.js",
"react-native": "./lib/create-adapter.default.js",
"worker": "./lib/create-adapter.default.js",
"browser": "./lib/create-adapter.browser.js",
"default": "./lib/create-adapter.default.js"
}
},
"files": [

@@ -43,41 +56,29 @@ "lib/",

"chtml.js",
"index.d.ts",
"index.js",
"svg.d.ts",
"svg.js"
],
"browser": {
"./lib/create-adaptor.js": "./lib/create-adaptor.browser.js"
},
"dependencies": {
"@types/hast": "^2.0.0",
"@types/hast": "^3.0.0",
"@types/mathjax": "^0.0.37",
"hast-util-from-dom": "^4.0.0",
"hast-util-to-text": "^3.1.0",
"jsdom": "^20.0.0",
"hast-util-from-dom": "^5.0.0",
"hast-util-to-text": "^4.0.0",
"jsdom": "^22.0.0",
"mathjax-full": "^3.0.0",
"unified": "^10.0.0",
"unist-util-visit": "^4.0.0"
"unified": "^11.0.0",
"unist-util-visit-parents": "^6.0.0"
},
"devDependencies": {
"@types/jsdom": "^20.0.0"
"@types/jsdom": "^21.0.0"
},
"scripts": {
"build": "rimraf \"lib/**/*.d.ts\" \"test/**/*.d.ts\" \"*.d.ts\" && tsc && type-coverage",
"test-api": "node --conditions development test/index.js",
"test": "npm run build && npm run test-api"
},
"xo": false,
"typeCoverage": {
"atLeast": 100,
"detail": true,
"strict": true,
"ignoreCatch": true,
"#": "needed `any`s",
"ignoreFiles": [
"lib/create-plugin.d.ts",
"lib/create-renderer.d.ts",
"lib/create-renderer.js"
]
"xo": {
"prettier": true,
"rules": {
"n/file-extension-in-import": "off",
"unicorn/prefer-at": "off"
}
}
}

@@ -11,4 +11,4 @@ # rehype-mathjax

**[rehype][]** plugin to render `<span class=math-inline>` and
`<div class=math-display>` with [MathJax][].
**[rehype][]** plugin to render elements with a `language-math` class with
[MathJax][].

@@ -22,5 +22,7 @@ ## Contents

* [API](#api)
* [`unified().use(rehypeMathjaxSvg[, options])`](#unifieduserehypemathjaxsvg-options)
* [`unified().use(rehypeMathjax[, options])`](#unifieduserehypemathjax-options)
* [`Options`](#options)
* [Markdown](#markdown)
* [HTML](#html)
* [CSS](#css)
* [Syntax tree](#syntax-tree)
* [Types](#types)

@@ -36,11 +38,5 @@ * [Compatibility](#compatibility)

This package is a [unified][] ([rehype][]) plugin to render math.
You can combine it with [`remark-math`][remark-math] for math in markdown or add
`math-inline` and `math-display` classes in HTML.
You can add classes to HTML elements, use fenced code in markdown, or combine
with [`remark-math`][remark-math] for a `$C$` syntax extension.
**unified** is a project that transforms content with abstract syntax trees
(ASTs).
**rehype** adds support for HTML to unified.
**hast** is the HTML AST that rehype uses.
This is a rehype plugin that transforms hast.
## When should I use this?

@@ -51,9 +47,9 @@

A different plugin, [`rehype-katex`][rehype-katex], is similar but uses
[KaTeX][] instead.
A different plugin, [`rehype-katex`][rehype-katex], does the same but with
[KaTeX][].
## Install
This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).
In Node.js (version 12.20+, 14.14+, or 16.0+), install with [npm][]:
This package is [ESM only][esm].
In Node.js (version 16+), install with [npm][]:

@@ -67,3 +63,3 @@ ```sh

```js
import rehypeMathjax from 'https://esm.sh/rehype-mathjax@4'
import rehypeMathjax from 'https://esm.sh/rehype-mathjax@5'
```

@@ -75,3 +71,3 @@

<script type="module">
import rehypeMathjax from 'https://esm.sh/rehype-mathjax@4?bundle'
import rehypeMathjax from 'https://esm.sh/rehype-mathjax@5?bundle'
</script>

@@ -82,23 +78,22 @@ ```

Say we have the following file `example.html`:
Say our document `input.html` contains:
```html
<p>
Lift(<span class="math math-inline">L</span>) can be determined by Lift Coefficient
(<span class="math math-inline">C_L</span>) like the following equation.
Lift(<code class="language-math">L</code>) can be determined by Lift Coefficient
(<code class="language-math">C_L</code>) like the following equation.
</p>
<div class="math math-display">
<pre><code class="language-math">
L = \frac{1}{2} \rho v^2 S C_L
</div>
</code></pre>
```
And our module `example.js` looks as follows:
…and our module `example.js` contains:
```js
import {read} from 'to-vfile'
import {unified} from 'unified'
import rehypeMathjax from 'rehype-mathjax'
import rehypeParse from 'rehype-parse'
import rehypeMathjax from 'rehype-mathjax'
import rehypeStringify from 'rehype-stringify'
import {read, write} from 'to-vfile'
import {unified} from 'unified'

@@ -109,16 +104,16 @@ const file = await unified()

.use(rehypeStringify)
.process(await read('example.html'))
.process(await read('input.html'))
console.log(String(file))
file.basename = 'output.html'
await write(file)
```
Now running `node example.js` yields:
…then running `node example.js` creates an `output.html` with:
```html
<p>
Lift(<span class="math math-inline"><mjx-container class="MathJax" jax="SVG"><!--…--></mjx-container></span>) can be determined by Lift Coefficient
(<span class="math math-inline"><mjx-container class="MathJax" jax="SVG"><!--…--></mjx-container></span>) like the following equation.
Lift(<mjx-container class="MathJax" jax="SVG"><!--…--></mjx-container>) can be determined by Lift Coefficient
(<mjx-container class="MathJax" jax="SVG"><!--…--></mjx-container>) like the following equation.
</p>
<div class="math math-display"><mjx-container class="MathJax" jax="SVG" display="true"><!--…--></mjx-container></div>
<mjx-container class="MathJax" jax="SVG" display="true"><!--…--></mjx-container>
<style>

@@ -132,57 +127,61 @@ mjx-container[jax="SVG"] {

…open `output.html` in a browser to see the rendered math.
## API
This package exports no identifiers.
The default export is `rehypeMathjaxSvg`.
This package has an export map with several entries for plugins using different
strategies:
### `unified().use(rehypeMathjaxSvg[, options])`
* `rehype-mathjax/browser` — browser (±1kb)
* `rehype-mathjax/chtml` — [CHTML][mathjax-chtml] (±154kb)
* `rehype-mathjax/svg` — [SVG][mathjax-svg] (±566kb)
* `rehype-mathjax` — same as SVG
Transform `<span class="math-inline">` and `<div class="math-display">` with
[MathJax][].
Each module exports the plugin [`rehypeMathjax`][api-rehype-mathjax] as
the default export.
This package includes three plugins, split out because MathJax targets have a
big memory and bundle size footprint: SVG, CHTML, and browser:
### `unified().use(rehypeMathjax[, options])`
###### SVG
Render elements with a `language-math` (or `math-display`, `math-inline`)
class with [MathJax][].
Render math as [SVG][mathjax-svg]
(`import rehypeMathjaxSvg from 'rehype-mathjax/svg.js'`, default).
About 566kb minzipped.
###### Parameters
###### CHTML
* `options` ([`Options`][api-options], typically optional)
— configuration
Render math as [CHTML][mathjax-chtml]
(`import rehypeMathjaxChtml from 'rehype-mathjax/chtml.js'`).
About 154kb minzipped.
Needs a `fontURL` to be passed.
###### Returns
###### Browser
Transform ([`Transformer`][unified-transformer]).
Tiny wrapper that expects MathJax to do work client side
(`import rehypeMathjaxBrowser from 'rehype-mathjax/browser.js'`).
About 1kb minzipped.
### `Options`
Uses `options.displayMath` (default: `['\\[', '\\]']`) for display math and
`options.inlineMath` (default: `['\\(', '\\)']`) for inline math.
Configuration (TypeScript type).
You need to load MathJax on the client yourself and start it with corresponding
markers.
Options are not passed to MathJax: do that yourself on the client.
###### Fields
#### `options`
* `chtml` (`unknown`, optional)
— configuration for the output, when CHTML;
see [*CommonHTML Output Processor Options* on
`mathjax.org`][mathjax-chtml-options]
* `svg` (`unknown`, optional)
— configuration for the output, when SVG;
see [*SVG Output Processor Options* on
`mathjax.org`][mathjax-svg-options]
* `tex` (`unknown`, optional)
— configuration for the input TeX;
see [*TeX Input Processor Options* on
`mathjax.org`][mathjax-tex-options]
All options, except when using the browser plugin, are passed to
[MathJax][mathjax-options].
###### Notes
#### `options.tex`
When using `rehype-mathjax/browser`, only `options.tex.displayMath` and
`options.tex.inlineMath` are used.
That plugin will use the first delimiter pair in those fields to wrap
math.
Then you need to load MathJax yourself on the client and start it with the
same markers.
You can pass other options on the client.
These options are passed to the [TeX input processor][mathjax-tex-options].
The browser plugin uses the first delimiter pair in `tex.displayMath` and
`tex.inlineMath` to instead wrap math.
#### `options.chtml`
These options are passed to the [CommonHTML output
processor][mathjax-chtml-options].
Passing `fontURL` is required!
When using `rehype-mathjax/chtml`, `options.chtml.fontURL` is required.
For example:

@@ -200,6 +199,22 @@

#### `options.svg`
## Markdown
These options are passed to the [SVG output processor][mathjax-svg-options].
This plugin supports the syntax extension enabled by
[`remark-math`][remark-math].
It also supports math generated by using fenced code:
````markdown
```math
C_L
```
````
## HTML
The content of any element with a `language-math`, `math-inline`, or
`math-display` class is transformed.
The elements are replaced by what MathJax renders.
Either a `math-display` class or using `<pre><code class="language-math">` will
result in “display” math: math that is a centered block on its own line.
## CSS

@@ -209,19 +224,17 @@

## Syntax tree
This plugin transforms elements with a class name of either `math-inline` and/or
`math-display`.
## Types
This package is fully typed with [TypeScript][].
An extra `Options` type is exported, which models the accepted options.
It exports the additional type [`Options`][api-options].
## Compatibility
Projects maintained by the unified collective are compatible with all maintained
Projects maintained by the unified collective are compatible with maintained
versions of Node.js.
As of now, that is Node.js 12.20+, 14.14+, and 16.0+.
Our projects sometimes work with older versions, but this is not guaranteed.
When we cut a new major release, we drop support for unmaintained versions of
Node.
This means we try to keep the current release line, `rehype-mathjax@^5`,
compatible with Node.js 16.
This plugin works with unified version 6+ and rehype version 4+.

@@ -231,36 +244,36 @@

Using `rehype-mathjax` should be safe assuming that you trust MathJax.
Any vulnerability in it could open you to a [cross-site scripting (XSS)][xss]
attack.
Always be wary of user input and use [`rehype-sanitize`][rehype-sanitize].
Assuming you trust MathJax, using `rehype-mathjax` is safe.
A vulnerability in it could open you to a
[cross-site scripting (XSS)][wiki-xss] attack.
Be wary of user input and use [`rehype-sanitize`][rehype-sanitize].
When you don’t trust user content but do trust MathKax, you can allow the
classes added by `remark-math` while disallowing anything else in the
`rehype-sanitize` schema, and run `rehype-katex` afterwards.
Like so:
When you don’t trust user content but do trust MathJax, run `rehype-mathjax`
*after* `rehype-sanitize`:
```js
import rehypeSanitize, {defaultSchema} from 'rehype-stringify'
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 mathSanitizeSchema = {
...defaultSchema,
attributes: {
...defaultSchema.attributes,
div: [
...defaultSchema.attributes.div,
['className', 'math', 'math-display']
],
span: [
['className', 'math', 'math-inline']
]
}
}
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$')
// …
unified()
// …
.use(rehypeSanitize, mathSanitizeSchema)
.use(rehypeMathjax)
// …
console.log(String(file))
```

@@ -309,5 +322,5 @@

[size-badge]: https://img.shields.io/bundlephobia/minzip/rehype-mathjax.svg
[size-badge]: https://img.shields.io/bundlejs/size/rehype-mathjax
[size]: https://bundlephobia.com/result?p=rehype-mathjax
[size]: https://bundlejs.com/?q=rehype-mathjax

@@ -326,2 +339,4 @@ [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg

[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
[esmsh]: https://esm.sh

@@ -331,7 +346,7 @@

[contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md
[contributing]: https://github.com/remarkjs/.github/blob/main/contributing.md
[support]: https://github.com/remarkjs/.github/blob/HEAD/support.md
[support]: https://github.com/remarkjs/.github/blob/main/support.md
[coc]: https://github.com/remarkjs/.github/blob/HEAD/code-of-conduct.md
[coc]: https://github.com/remarkjs/.github/blob/main/code-of-conduct.md

@@ -342,30 +357,34 @@ [license]: https://github.com/remarkjs/remark-math/blob/main/license

[rehype]: https://github.com/rehypejs/rehype
[katex]: https://github.com/Khan/KaTeX
[unified]: https://github.com/unifiedjs/unified
[mathjax-svg]: http://docs.mathjax.org/en/latest/output/svg.html
[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
[mathjax-chtml]: http://docs.mathjax.org/en/latest/output/html.html
[typescript]: https://www.typescriptlang.org
[mathjax-tex-options]: http://docs.mathjax.org/en/latest/options/input/tex.html
[mathjax-svg-options]: http://docs.mathjax.org/en/latest/options/output/svg.html
[mathjax-chtml-options]: http://docs.mathjax.org/en/latest/options/output/chtml.html
[rehype]: https://github.com/rehypejs/rehype
[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize
[mathjax]: https://mathjax.org/
[typescript]: https://www.typescriptlang.org
[mathjax-options]: http://docs.mathjax.org/en/latest/options/
[unified]: https://github.com/unifiedjs/unified
[mathjax-svg]: http://docs.mathjax.org/en/latest/output/svg.html
[unified-transformer]: https://github.com/unifiedjs/unified#transformer
[mathjax-chtml]: http://docs.mathjax.org/en/latest/output/html.html
[wiki-xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
[mathjax-tex-options]: http://docs.mathjax.org/en/latest/options/input/tex.html
[mathjax]: https://mathjax.org/
[mathjax-svg-options]: http://docs.mathjax.org/en/latest/options/output/svg.html
[remark-math]: ../remark-math/
[mathjax-chtml-options]: http://docs.mathjax.org/en/latest/options/output/chtml.html
[rehype-katex]: ../rehype-katex/
[katex]: https://github.com/Khan/KaTeX
[api-options]: #options
[remark-math]: ../remark-math
[rehype-katex]: ../rehype-katex
[api-rehype-mathjax]: #unifieduserehypemathjax-options

@@ -1,8 +0,2 @@

export default rehypeMathJaxSvg
export type Options = import('./lib/create-plugin.js').Options
declare const rehypeMathJaxSvg: (
this: import('unified').Processor<void, import('hast').Root, void, void>,
options?: void | import('./lib/create-plugin.js').Options | undefined
) =>
| void
| import('unified').Transformer<import('hast').Root, import('hast').Root>
export { default } from "./lib/svg.js";
export type Options = import('./lib/create-plugin.js').Options;

@@ -5,10 +5,2 @@ /**

import {SVG} from 'mathjax-full/js/output/svg.js'
import {createRenderer} from './lib/create-renderer.js'
import {createPlugin} from './lib/create-plugin.js'
const rehypeMathJaxSvg = createPlugin((options) =>
createRenderer(options, new SVG(options.svg))
)
export default rehypeMathJaxSvg
export {default} from './lib/svg.js'
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc