diff --git a/packages/rehype-katex/readme.md b/packages/rehype-katex/readme.md index dbb5c2b..d963f72 100644 --- a/packages/rehype-katex/readme.md +++ b/packages/rehype-katex/readme.md @@ -8,23 +8,71 @@ [![Backers][backers-badge]][collective] [![Chat][chat-badge]][chat] -[**rehype**][rehype] plugin to transform `` and +**[rehype][]** plugin to render `` and `
` with [KaTeX][]. -## Install +## Contents + +* [What is this?](#what-is-this) +* [When should I use this?](#when-should-i-use-this) +* [Install](#install) +* [Use](#use) +* [API](#api) + * [`unified().use(rehypeKatex[, options])`](#unifieduserehypekatex-options) +* [CSS](#css) +* [Syntax tree](#syntax-tree) +* [Types](#types) +* [Security](#security) +* [Related](#related) +* [Contribute](#contribute) +* [License](#license) + +## What is this? + +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. -This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c): -Node 12+ is needed to use it and it must be `import`ed instead of `require`d. +**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. -[npm][]: +## When should I use this? + +This project is useful as it renders math with KaTeX at compile time, which +means that there is no client side JavaScript needed. + +A different plugin, [`rehype-mathjax`][rehype-mathjax], is similar but uses +[MathJax][] instead. + +## 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][]: ```sh npm install rehype-katex ``` +In Deno with [Skypack][]: + +```js +import rehypeKatex from 'https://cdn.skypack.dev/rehype-katex@6?dts' +``` + +In browsers with [Skypack][]: + +```html + +``` + ## Use -Say we have the following file, `example.html`: +Say we have the following file `example.html`: ```html

@@ -37,41 +85,51 @@ Say we have the following file, `example.html`:

``` -And our module, `example.js`, looks as follows: +And our module `example.js` looks as follows: ```js -import {readSync} from 'to-vfile' +import {read} from 'to-vfile' import {unified} from 'unified' import rehypeParse from 'rehype-parse' import rehypeKatex from 'rehype-katex' import rehypeDocument from 'rehype-document' import rehypeStringify from 'rehype-stringify' -const file = readSync('example.html') +main() -unified() - .use(rehypeParse, {fragment: true}) - .use(rehypeKatex) - .use(rehypeDocument, { - css: 'https://cdn.jsdelivr.net/npm/katex@0.13.13/dist/katex.min.css' - }) - .use(rehypeStringify) - .process(file) - .then((file) => { - console.log(String(file)) - }) +async function main() { + const file = await unified() + .use(rehypeParse, {fragment: true}) + .use(rehypeKatex) + .use(rehypeDocument, { + css: 'https://cdn.jsdelivr.net/npm/katex@0.13.13/dist/katex.min.css' + }) + .use(rehypeStringify) + .process(await read('example.html')) + + console.log(String(file)) +} ``` -Now, running `node example` yields: +Now running `node example.js` yields: ```html + + + + +example + + + +

- Lift(LL) can be determined by Lift Coefficient - (CLC_L) like the following equation. + Lift() can be determined by Lift Coefficient + () like the following equation.

- -
L=12ρv2SCLL = \frac{1}{2} \rho v^2 S C_L
- +
+ + ``` ## API @@ -84,25 +142,97 @@ The default export is `rehypeKatex`. Transform `` and `
` with [KaTeX][]. -#### `options` +##### `options` -##### `options.throwOnError` +Configuration (optional). +All options, except for `displayMode`, are passed to [KaTeX][katex-options]. + +###### `options.throwOnError` Throw if a KaTeX parse error occurs (`boolean`, default: `false`). See [KaTeX options][katex-options]. -##### `options.<*>` +## CSS -All other options, except for `displayMode`, are passed to -[KaTeX][katex-options]. +The HTML produced by KaTeX requires CSS to render correctly. +You should use `katex.css` somewhere on the page where the math is shown to +style it properly. +At the time of writing, the last version is: -## Security +```html + +``` + +## 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. + +## Compatibility -Use of `rehype-katex` renders user content with [KaTeX][], so any vulnerability -in KaTeX can open you to a [cross-site scripting (XSS)][xss] attack. +Projects maintained by the unified collective are compatible with all 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. +This plugin works with unified version 6+ and rehype version 4+. + +## Security + +Using `rehype-katex` should be safe assuming that you trust KaTeX. +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]. +When you don’t trust user content but do trust KaTeX, 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: + +```js +import rehypeSanitize, {defaultSchema} from 'rehype-stringify' + +const mathSanitizeSchema = { + ...defaultSchema, + attributes: { + ...defaultSchema.attributes, + div: [ + ...defaultSchema.attributes.div, + ['className', 'math', 'math-display'] + ], + span: [ + ['className', 'math', 'math-inline'] + ] + } +} + +// … + +unified() + // … + .use(rehypeSanitize, mathSanitizeSchema) + .use(rehypeKatex) + // … +``` + +## Related + +* [`rehype-mathjax`][rehype-mathjax] + — same but with MathJax +* [`rehype-highlight`](https://github.com/rehypejs/rehype-highlight) + — highlight code blocks +* [`rehype-autolink-headings`](https://github.com/rehypejs/rehype-autolink-headings) + — add links to headings +* [`rehype-sanitize`](https://github.com/rehypejs/rehype-sanitize) + — sanitize HTML +* [`rehype-document`](https://github.com/rehypejs/rehype-document) + — wrap a document around the tree + ## Contribute See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways @@ -147,6 +277,8 @@ abide by its terms. [npm]: https://docs.npmjs.com/cli/install +[skypack]: https://www.skypack.dev + [health]: https://github.com/remarkjs/.github [contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md @@ -159,12 +291,22 @@ abide by its terms. [author]: https://rokt33r.github.io +[unified]: https://github.com/unifiedjs/unified + [rehype]: https://github.com/rehypejs/rehype [xss]: https://en.wikipedia.org/wiki/Cross-site_scripting +[typescript]: https://www.typescriptlang.org + [rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize [katex]: https://github.com/Khan/KaTeX [katex-options]: https://katex.org/docs/options.html + +[mathjax]: https://www.mathjax.org + +[remark-math]: ../remark-math + +[rehype-mathjax]: ../rehype-mathjax diff --git a/packages/rehype-mathjax/browser.js b/packages/rehype-mathjax/browser.js index 246d075..f5ecbbd 100644 --- a/packages/rehype-mathjax/browser.js +++ b/packages/rehype-mathjax/browser.js @@ -1,7 +1,4 @@ /** - * @typedef {import('hast').Root} Root - * @typedef {import('hast').Element} Element - * @typedef {import('./lib/create-plugin').MathNotation} MathNotation * @typedef {import('./lib/create-plugin').Options} Options */ diff --git a/packages/rehype-mathjax/chtml.js b/packages/rehype-mathjax/chtml.js index 90e3397..5953e21 100644 --- a/packages/rehype-mathjax/chtml.js +++ b/packages/rehype-mathjax/chtml.js @@ -1,6 +1,4 @@ /** - * @typedef {import('hast').Root} Root - * @typedef {import('mathjax-full/js/output/chtml.js').CHTML} CHTML_ * @typedef {import('./lib/create-plugin').Options} Options */ diff --git a/packages/rehype-mathjax/index.js b/packages/rehype-mathjax/index.js index 1032b6e..57f23b0 100644 --- a/packages/rehype-mathjax/index.js +++ b/packages/rehype-mathjax/index.js @@ -1,3 +1,7 @@ +/** + * @typedef {import('./lib/create-plugin.js').Options} Options + */ + import rehypeMathJaxSvg from './svg.js' export default rehypeMathJaxSvg diff --git a/packages/rehype-mathjax/readme.md b/packages/rehype-mathjax/readme.md index f3fc00b..d47424a 100644 --- a/packages/rehype-mathjax/readme.md +++ b/packages/rehype-mathjax/readme.md @@ -8,23 +8,71 @@ [![Backers][backers-badge]][collective] [![Chat][chat-badge]][chat] -[**rehype**][rehype] plugin to transform `` and +**[rehype][]** plugin to render `` and `
` with [MathJax][]. -## Install +## Contents + +* [What is this?](#what-is-this) +* [When should I use this?](#when-should-i-use-this) +* [Install](#install) +* [Use](#use) +* [API](#api) + * [`unified().use(rehypeMathjaxSvg[, options])`](#unifieduserehypemathjaxsvg-options) +* [CSS](#css) +* [Syntax tree](#syntax-tree) +* [Types](#types) +* [Security](#security) +* [Related](#related) +* [Contribute](#contribute) +* [License](#license) + +## What is this? + +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. + +**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? + +This project is useful as it renders math with MathJax at compile time, which +means that there is no client side JavaScript needed. -This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c): -Node 12+ is needed to use it and it must be `import`ed instead of `require`d. +A different plugin, [`rehype-katex`][rehype-katex], is similar but uses +[KaTeX][] instead. -[npm][]: +## 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][]: ```sh npm install rehype-mathjax ``` +In Deno with [Skypack][]: + +```js +import rehypeMathjax from 'https://cdn.skypack.dev/rehype-mathjax@4?dts' +``` + +In browsers with [Skypack][]: + +```html + +``` + ## Use -Say we have the following file, `example.html`: +Say we have the following file `example.html`: ```html

@@ -37,45 +85,41 @@ Say we have the following file, `example.html`:

``` -And our module, `example.js`, looks as follows: +And our module `example.js` looks as follows: ```js -import {readSync} from 'to-vfile' +import {read} from 'to-vfile' import {unified} from 'unified' import rehypeParse from 'rehype-parse' -import rehypeMathJax from 'rehype-mathjax' +import rehypeMathjax from 'rehype-mathjax' import rehypeStringify from 'rehype-stringify' -const file = readSync('example.html') +main() -unified() - .use(rehypeParse, {fragment: true}) - .use(rehypeMathJax) - .use(rehypeStringify) - .process(file) - .then((file) => { - console.log(String(file)) - }) +async function main() { + const file = await unified() + .use(rehypeParse, {fragment: true}) + .use(rehypeMathjax) + .use(rehypeStringify) + .process(await read('example.html')) + + console.log(String(file)) +} ``` -Now, running `node example` yields: +Now running `node example.js` yields: ```html

- Lift() can be determined by Lift Coefficient - () like the following equation. + Lift() can be determined by Lift Coefficient + () like the following equation.

-
+
``` @@ -83,36 +127,36 @@ mjx-container[jax="SVG"] > svg { ## API This package exports no identifiers. -The default export is `rehypeMathJaxSvg`. +The default export is `rehypeMathjaxSvg`. -### `unified().use(rehypeMathJaxSvg[, options])` +### `unified().use(rehypeMathjaxSvg[, options])` Transform `` and `
` with [MathJax][]. This package includes three plugins, split out because MathJax targets have a -big memory and size footprint: SVG, CHTML, and browser: +big memory and bundle size footprint: SVG, CHTML, and browser: ###### SVG -Render math as [SVG][mathjax-svg] (`import rehypeMathJaxSvg from -'rehype-mathjax/svg.js'`, default). +Render math as [SVG][mathjax-svg] +(`import rehypeMathjaxSvg from 'rehype-mathjax/svg.js'`, default). About 566kb minzipped. ###### CHTML -Render math as [CHTML][mathjax-chtml] (`import rehypeMathJaxChtml from -'rehype-mathjax/chtml.js'`). +Render math as [CHTML][mathjax-chtml] +(`import rehypeMathjaxChtml from 'rehype-mathjax/chtml.js'`). About 154kb minzipped. Needs a `fontURL` to be passed. ###### Browser -Tiny wrapper to render MathJax client-side (`import rehypeMathJaxBrowser from -'rehype-mathjax/browser.js'`). +Tiny wrapper that expects MathJax to do work client side +(`import rehypeMathjaxBrowser from 'rehype-mathjax/browser.js'`). About 1kb minzipped. -Uses `options.displayMath` (default: `['\\[', '\\]']`) for display, and +Uses `options.displayMath` (default: `['\\[', '\\]']`) for display math and `options.inlineMath` (default: `['\\(', '\\)']`) for inline math. You need to load MathJax on the client yourself and start it with corresponding @@ -135,19 +179,96 @@ The browser plugin uses the first delimiter pair in `tex.displayMath` and These options are passed to the [CommonHTML output processor][mathjax-chtml-options]. Passing `fontURL` is required! +For example: + +```js + // … + .use(rehypeMathjaxChtml, { + chtml: { + fontURL: 'https://cdn.jsdelivr.net/npm/mathjax@3/components/output/chtml/fonts/woff-v2' + } + }) + // … +``` #### `options.svg` These options are passed to the [SVG output processor][mathjax-svg-options]. +## CSS + +The HTML produced by MathJax does not require any extra CSS to render correctly. + +## 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. + +## Compatibility + +Projects maintained by the unified collective are compatible with all 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. + +This plugin works with unified version 6+ and rehype version 4+. + ## Security -Use of `rehype-mathjax` renders user content with [MathJax][], so any -vulnerability in MathJax can open you to a [cross-site scripting (XSS)][xss] +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]. +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: + +```js +import rehypeSanitize, {defaultSchema} from 'rehype-stringify' + +const mathSanitizeSchema = { + ...defaultSchema, + attributes: { + ...defaultSchema.attributes, + div: [ + ...defaultSchema.attributes.div, + ['className', 'math', 'math-display'] + ], + span: [ + ['className', 'math', 'math-inline'] + ] + } +} + +// … + +unified() + // … + .use(rehypeSanitize, mathSanitizeSchema) + .use(rehypeMathjax) + // … +``` + +## Related + +* [`rehype-katex`][rehype-katex] + — same but with KaTeX +* [`rehype-highlight`](https://github.com/rehypejs/rehype-highlight) + — highlight code blocks +* [`rehype-autolink-headings`](https://github.com/rehypejs/rehype-autolink-headings) + — add links to headings +* [`rehype-sanitize`](https://github.com/rehypejs/rehype-sanitize) + — sanitize HTML +* [`rehype-document`](https://github.com/rehypejs/rehype-document) + — wrap a document around the tree + ## Contribute See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways @@ -192,6 +313,8 @@ abide by its terms. [npm]: https://docs.npmjs.com/cli/install +[skypack]: https://www.skypack.dev + [health]: https://github.com/remarkjs/.github [contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md @@ -206,8 +329,12 @@ abide by its terms. [rehype]: https://github.com/rehypejs/rehype +[unified]: https://github.com/unifiedjs/unified + [xss]: https://en.wikipedia.org/wiki/Cross-site_scripting +[typescript]: https://www.typescriptlang.org + [rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize [mathjax]: https://mathjax.org/ @@ -223,3 +350,9 @@ abide by its terms. [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 + +[katex]: https://github.com/Khan/KaTeX + +[remark-math]: ../remark-math + +[rehype-katex]: ../rehype-katex diff --git a/packages/rehype-mathjax/svg.js b/packages/rehype-mathjax/svg.js index 23fc64a..dd16ab8 100644 --- a/packages/rehype-mathjax/svg.js +++ b/packages/rehype-mathjax/svg.js @@ -1,6 +1,4 @@ /** - * @typedef {import('hast').Root} Root - * @typedef {import('mathjax-full/js/output/svg.js').SVG} SVG_ * @typedef {import('./lib/create-plugin.js').Options} Options */ diff --git a/packages/remark-math/readme.md b/packages/remark-math/readme.md index 6849090..cbf8291 100644 --- a/packages/remark-math/readme.md +++ b/packages/remark-math/readme.md @@ -8,43 +8,87 @@ [![Backers][backers-badge]][collective] [![Chat][chat-badge]][chat] -[**remark**][remark] plugin to parse and stringify math. - -## Important! - -This plugin is affected by the new parser in remark -([`micromark`](https://github.com/micromark/micromark), -see [`remarkjs/remark#536`](https://github.com/remarkjs/remark/pull/536)). -Use version 3 while you’re still on remark 12. -Use version 4 for remark 13+. +**[remark][]** plugin to support math (`$C_L$`). + +## Contents + +* [What is this?](#what-is-this) +* [When should I use this?](#when-should-i-use-this) +* [Install](#install) +* [Use](#use) +* [API](#api) + * [`unified().use(remarkMath[, options])`](#unifieduseremarkmath-options) +* [Syntax](#syntax) +* [HTML](#html) +* [Syntax tree](#syntax-tree) +* [Types](#types) +* [Compatibility](#compatibility) +* [Security](#security) +* [Related](#related) +* [Contribute](#contribute) +* [License](#license) + +## What is this? + +This package is a [unified][] ([remark][]) plugin to add support for math. +You can use this to add support for parsing and serializing this syntax +extension. + +**unified** is a project that transforms content with abstract syntax trees +(ASTs). +**remark** adds support for markdown to unified. +**mdast** is the markdown AST that remark uses. +**micromark** is the markdown parser we use. +This is a remark plugin that adds support for the math syntax and AST to remark. + +## When should I use this? + +This project is useful when you want to support math in markdown. +Extending markdown with a syntax extension makes the markdown less portable. +LaTeX equations are also quite hard. +But this mechanism works well when you want authors, that have some LaTeX +experience, to be able to embed rich diagrams of math in scientific text. ## Install -This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c): -Node 12+ is needed to use it and it must be `import`ed instead of `require`d. - -[npm][]: +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][]: ```sh npm install remark-math ``` +In Deno with [Skypack][]: + +```js +import remarkMath from 'https://cdn.skypack.dev/remark-math@5?dts' +``` + +In browsers with [Skypack][]: + +```html + +``` + ## Use -Say we have the following file, `example.md`: +Say we have the following file `example.md`: ```markdown -Lift($L$) can be determined by Lift Coefficient ($C_L$) like the following equation. +Lift($L$) can be determined by Lift Coefficient ($C_L$) like the following +equation. $$ L = \frac{1}{2} \rho v^2 S C_L $$ ``` -And our module, `example.js`, looks as follows: +And our module `example.js` looks as follows: ```js -import {readSync} from 'to-vfile' +import {read} from 'to-vfile' import {unified} from 'unified' import remarkParse from 'remark-parse' import remarkMath from 'remark-math' @@ -52,25 +96,26 @@ import remarkRehype from 'remark-rehype' import rehypeKatex from 'rehype-katex' import rehypeStringify from 'rehype-stringify' -const file = readSync('example.md') - -unified() - .use(remarkParse) - .use(remarkMath) - .use(remarkRehype) - .use(rehypeKatex) - .use(rehypeStringify) - .process(file) - .then((file) => { - console.log(String(file)) - }) +main() + +async function main() { + const file = await unified() + .use(remarkParse) + .use(remarkMath) + .use(remarkRehype) + .use(rehypeKatex) + .use(rehypeStringify) + .process(await read('example.md')) + + console.log(String(file)) +} ``` -Now, running `node example` yields: +Now running `node example.js` yields: ```html -

Lift(LL) can be determined by Lift Coefficient (CLC_L) like the following equation.

-
L=12ρv2SCLL = \frac{1}{2} \rho v^2 S C_L
+

Lift() can be determined by Lift Coefficient () like the following equation.

+
``` ## API @@ -80,16 +125,12 @@ The default export is `remarkMath`. ### `unified().use(remarkMath[, options])` -Parse and stringify math. - -Get’s useful when combined with [`rehype-katex`][rehype-katex] or -[`rehype-mathjax`][rehype-mathjax]. - -See [`micromark/micromark-extension-math`][extension-math] for more info on what -syntax is supported. +Plugin to support math. ##### `options` +Configuration (optional). + ###### `options.singleDollarTextMath` Whether to support math (text) with a single dollar (`boolean`, default: @@ -97,21 +138,81 @@ Whether to support math (text) with a single dollar (`boolean`, default: Single dollars work in Pandoc and many other places, but often interfere with “normal” dollars in text. -#### Notes +## Syntax + +This plugin applies a micromark extensions to parse the syntax. +See its readme for parse details: + +* [`micromark-extension-math`](https://github.com/micromark/micromark-extension-math#syntax) + +> 👉 **Note**: `$math$` works similar to `` `code` ``. +> That means escapes don’t work inside math but you can use more dollars around +> the math instead: `$$\raisebox{0.25em}{$\frac a b$}$$` -##### Escaping +## HTML -Markdown escapes don’t work in math, similar to code, but you can use more -dollars around the math instead: `$$\raisebox{0.25em}{$\frac -a b$}$$` +This plugin integrates with [`remark-rehype`][remark-rehype]. +When mdast (markdown AST) is turned into hast (the HTML AST) the math nodes +are turned into `` and `
` +elements. + +## Syntax tree + +This plugin applies one mdast utility to build and serialize the AST. +See its readme for the node types supported in the tree: + +* [`mdast-util-math`](https://github.com/syntax-tree/mdast-util-math#syntax-tree) + +## Types + +This package is fully typed with [TypeScript][]. +It exports an extra `Options` type which models the interface of the accepted +options. + +If you’re working with the syntax tree, make sure to import this plugin +somewhere in your types, as that registers the new node types in the tree. + +```js +/** @typedef {import('remark-math')} */ + +import {visit} from 'unist-util-visit' + +/** @type {import('unified').Plugin<[], import('mdast').Root>} */ +export default function myRemarkPlugin() => { + return (tree) => { + visit(tree, (node) => { + // `node` can now be one of the nodes for math. + }) + } +} +``` + +## Compatibility + +Projects maintained by the unified collective are compatible with all 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. + +This plugin works with unified version 6+ and remark version 14+. +The previous major (version 4) worked with remark 13. ## Security -Use of `remark-math` itself doesn’t open you up to [cross-site scripting +Use of `remark-math` itself does not open you up to [cross-site scripting (XSS)][xss] attacks. - Always be wary of user input and use [`rehype-sanitize`][rehype-sanitize]. +## Related + +* [`remark-gfm`](https://github.com/remarkjs/remark-gfm) + — support GFM (autolink literals, footnotes, strikethrough, tables, + tasklists) +* [`remark-frontmatter`](https://github.com/remarkjs/remark-frontmatter) + — support frontmatter (YAML, TOML, and more) +* [`remark-directive`](https://github.com/remarkjs/remark-directive) + — support directives + ## Contribute See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways @@ -156,6 +257,8 @@ abide by its terms. [npm]: https://docs.npmjs.com/cli/install +[skypack]: https://www.skypack.dev + [health]: https://github.com/remarkjs/.github [contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md @@ -168,14 +271,14 @@ abide by its terms. [author]: https://rokt33r.github.io +[unified]: https://github.com/unifiedjs/unified + [remark]: https://github.com/remarkjs/remark [xss]: https://en.wikipedia.org/wiki/Cross-site_scripting -[rehype-katex]: https://github.com/remarkjs/remark-math/tree/main/packages/rehype-katex - -[rehype-mathjax]: https://github.com/remarkjs/remark-math/tree/main/packages/rehype-mathjax +[typescript]: https://www.typescriptlang.org -[extension-math]: https://github.com/micromark/micromark-extension-math +[remark-rehype]: https://github.com/remarkjs/remark-rehype [rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize diff --git a/readme.md b/readme.md index 0cacf69..55b6995 100644 --- a/readme.md +++ b/readme.md @@ -8,22 +8,58 @@ [![Backers][backers-badge]][collective] [![Chat][chat-badge]][chat] -[**remark**][remark] and [**rehype**][rehype] plugins to support math! +This project is a monorepo that contains several packages for dealing with +math in markdown and HTML. -## Install +## Contents -This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c): -Node 12+ is needed to use it and it must be `import`ed instead of `require`d. +* [What is this?](#what-is-this) +* [When should I use this?](#when-should-i-use-this) +* [Examples](#examples) + * [Example: KaTeX](#example-katex) + * [Example: MathJax](#example-mathjax) +* [Security](#security) +* [Contribute](#contribute) +* [License](#license) -[npm][]: +## What is this? -```sh -npm install remark-math rehype-katex -``` +This repository contains [unified][] ([remark][] and [rehype][]) plugins to add +support for math. +You can use them to add support for parsing and serializing this syntax +extension and to render math with KaTeX or MathJax. + +* [`remark-math`][remark-math] + — remark plugin to support a math syntax in markdown +* [`rehype-katex`][rehype-katex] + — rehype plugin to render math in HTML with [KaTeX][] +* [`rehype-mathjax`][rehype-mathjax] + — rehype plugin to render math in HTML with [MathJax][] + +You typically use `remark-math` combined with either `rehype-katex` or +`rehype-mathjax`. + +**unified** is a project that transforms content with abstract syntax trees +(ASTs). +**remark** adds support for markdown and **rehype** adds support for HTML to +unified. + +## When should I use this? + +This project is useful when you want to support LaTeX math. +This mechanism works well when you want authors, that have some LaTeX +experience, to be able to embed rich diagrams of math to scientific +documentation. +The syntax of math in markdown does not work everywhere so it makes markdown +less portable. +This project is also useful as it renders math with KaTeX or MathJax at compile +time, which means that there is no client side JavaScript needed. -## Use +## Examples -Say we have the following file, `example.md`: +### Example: KaTeX + +Say we have the following file `example.md`: ```markdown Lift($L$) can be determined by Lift Coefficient ($C_L$) like the following @@ -34,10 +70,10 @@ L = \frac{1}{2} \rho v^2 S C_L $$ ``` -And our module, `example.js`, looks as follows: +And our module `example.js` looks as follows: ```js -import {readSync} from 'to-vfile' +import {read} from 'to-vfile' import {unified} from 'unified' import remarkParse from 'remark-parse' import remarkMath from 'remark-math' @@ -45,105 +81,77 @@ import remarkRehype from 'remark-rehype' import rehypeKatex from 'rehype-katex' import rehypeStringify from 'rehype-stringify' -const file = readSync('example.md') - -unified() - .use(remarkParse) - .use(remarkMath) - .use(remarkRehype) - .use(rehypeKatex) - .use(rehypeStringify) - .process(file) - .then((file) => { - console.log(String(file)) - }) -``` +main() -Now, running `node example` yields: +async function main() { + const file = await unified() + .use(remarkParse) + .use(remarkMath) + .use(remarkRehype) + .use(rehypeKatex) + .use(rehypeStringify) + .process(await read('example.md')) -```html -

Lift(LL) can be determined by Lift Coefficient (CLC_L) like the following equation.

-
L=12ρv2SCLL = \frac{1}{2} \rho v^2 S C_L
+ console.log(String(file)) +} ``` -Wow, that’s a lot! -But in a browser, that looks something like this: +Now running `node example.js` yields: -![][screenshot] +```html +

Lift() can be determined by Lift Coefficient () like the following equation.

+
+``` -> Note: you should also use `katex.css` somewhere on the page to style math +> 👉 **Note**: KaTeX requires CSS to render correctly. +> Use `katex.css` somewhere on the page where the math is shown to style it > properly: > > ```html > > ``` -## Packages - -This repo houses three packages: - -* [`remark-math`][remark-math] - — Parses `$` as `inlineMath` and `$$` as `math` nodes -* [`rehype-katex`][rehype-katex] - — Transforms math nodes with [KaTeX][] -* [`rehype-mathjax`][rehype-mathjax] - — Transforms math nodes with [MathJax][] - -See their readmes for more information. - -## Security - -Use of `rehype-katex` or `rehype-mathjax` renders user content with [KaTeX][], -so any vulnerability in KaTeX can open you to a -[cross-site scripting (XSS)][xss] attack. - -Always be wary of user input and use [`rehype-sanitize`][rehype-sanitize]. - -If you are using [`rehype-sanitize`][rehype-sanitize] and trust [KaTeX][], you -can allow the classes added by `remark-math` by extending the default schema -like so: - -```js -const mathSanitizeSchema = { - ...defaultSchema, - attributes: { - ...defaultSchema.attributes, - div: [ - ...defaultSchema.attributes.div, - ['className', 'math', 'math-display'] - ], - span: [ - ['className', 'math', 'math-inline'] - ] - } -} +### Example: MathJax + +Supporting either MathJax or KaTeX is very similar. +Take the above KaTeX example and change: + +```diff +@@ -3,7 +3,7 @@ import {unified} from 'unified' + import remarkParse from 'remark-parse' + import remarkMath from 'remark-math' + import remarkRehype from 'remark-rehype' +-import rehypeKatex from 'rehype-katex' ++import rehypeMathjax from 'rehype-mathjax' + import rehypeStringify from 'rehype-stringify' + + main() +@@ -13,7 +13,7 @@ async function main() { + .use(remarkParse) + .use(remarkMath) + .use(remarkRehype) +- .use(rehypeKatex) ++ .use(rehypeMathjax) + .use(rehypeStringify) + .process(await read('example.md')) ``` -And applying the `rehype-katex` plugin *after* the -[`rehype-sanitize`][rehype-sanitize] plugin like so: +Now running `node example.js` yields: -```js -[ - rehypeRaw, - // … - [rehypeSanitize, mathSanitizeSchema], - rehypeKatex - // … -] +```html +

Lift() can be determined by Lift Coefficient () like the following +equation.

+
+ ``` -## Related +## Security -* [`remark-breaks`](https://github.com/remarkjs/remark-breaks) - – Support hard breaks without needing spaces (like on issues) -* [`remark-gfm`](https://github.com/remarkjs/remark-gfm) - — GFM (autolink literals, strikethrough, tables, tasklists) -* [`remark-github`](https://github.com/remarkjs/remark-github) - — Autolink references like in GitHub issues, PRs, and comments -* [`remark-footnotes`](https://github.com/remarkjs/remark-footnotes) - — Footnotes -* [`remark-frontmatter`](https://github.com/remarkjs/remark-frontmatter) - — Frontmatter (YAML, TOML, and more) +Using `rehype-katex` or `rehype-mathjax` should be safe assuming that you trust +KaTeX and MathJax. +Any vulnerability in them could open you to a [cross-site scripting (XSS)][xss] +attack. +See their readmes for more info. ## Contribute @@ -157,7 +165,7 @@ abide by its terms. ## License -[MIT][license] © [Junyoung Choi][author] +[MIT][license] © [Junyoung Choi][author] and TANIGUCHI Masaya @@ -187,8 +195,6 @@ abide by its terms. [chat]: https://github.com/remarkjs/remark/discussions -[npm]: https://docs.npmjs.com/cli/install - [health]: https://github.com/remarkjs/.github [contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md @@ -201,12 +207,12 @@ abide by its terms. [author]: https://rokt33r.github.io +[unified]: https://github.com/unifiedjs/unified + [remark]: https://github.com/remarkjs/remark [rehype]: https://github.com/rehypejs/rehype -[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize - [katex]: https://github.com/Khan/KaTeX [mathjax]: https://mathjax.org/ @@ -218,5 +224,3 @@ abide by its terms. [rehype-katex]: ./packages/rehype-katex [rehype-mathjax]: ./packages/rehype-mathjax - -[screenshot]: screenshot.png