rehype-katex
Advanced tools
Comparing version 6.0.3 to 7.0.0
@@ -1,8 +0,2 @@ | ||
export default function rehypeKatex( | ||
this: import('unified').Processor<void, import('hast').Root, void, void>, | ||
...settings: [(import('katex').KatexOptions | undefined)?] | void[] | ||
): | ||
| void | ||
| import('unified').Transformer<import('hast').Root, import('hast').Root> | ||
export type Root = import('hast').Root | ||
export type Options = import('katex').KatexOptions | ||
export { default } from "./lib/index.js"; | ||
export type Options = import('./lib/index.js').Options; |
88
index.js
/** | ||
* @typedef {import('hast').Root} Root | ||
* @typedef {import('katex').KatexOptions} Options | ||
* @typedef {import('./lib/index.js').Options} Options | ||
*/ | ||
import katex from 'katex' | ||
import {visit} from 'unist-util-visit' | ||
import {toText} from 'hast-util-to-text' | ||
import {fromHtmlIsomorphic} from 'hast-util-from-html-isomorphic' | ||
const assign = Object.assign | ||
const source = 'rehype-katex' | ||
/** | ||
* Plugin to transform `<span class=math-inline>` and `<div class=math-display>` | ||
* with KaTeX. | ||
* | ||
* @type {import('unified').Plugin<[Options?]|void[], Root>} | ||
*/ | ||
export default function rehypeKatex(options) { | ||
const settings = options || {} | ||
const throwOnError = settings.throwOnError || false | ||
return (tree, file) => { | ||
visit(tree, 'element', (element) => { | ||
const classes = | ||
element.properties && Array.isArray(element.properties.className) | ||
? element.properties.className | ||
: [] | ||
const inline = classes.includes('math-inline') | ||
const displayMode = classes.includes('math-display') | ||
if (!inline && !displayMode) { | ||
return | ||
} | ||
const value = toText(element, {whitespace: 'pre'}) | ||
/** @type {string} */ | ||
let result | ||
try { | ||
result = katex.renderToString( | ||
value, | ||
assign({}, settings, {displayMode, throwOnError: true}) | ||
) | ||
} catch (error_) { | ||
const error = /** @type {Error} */ (error_) | ||
const fn = throwOnError ? 'fail' : 'message' | ||
const origin = [source, error.name.toLowerCase()].join(':') | ||
file[fn](error.message, element.position, origin) | ||
// KaTeX can handle `ParseError` itself, but not others. | ||
// Generate similar markup if this is an other error. | ||
// See: <https://github.com/KaTeX/KaTeX/blob/5dc7af0/docs/error.md>. | ||
if (error.name !== 'ParseError') { | ||
element.children = [ | ||
{ | ||
type: 'element', | ||
tagName: 'span', | ||
properties: { | ||
className: ['katex-error'], | ||
title: String(error), | ||
style: 'color:' + (settings.errorColor || '#cc0000') | ||
}, | ||
children: [{type: 'text', value}] | ||
} | ||
] | ||
return | ||
} | ||
result = katex.renderToString( | ||
value, | ||
assign({}, settings, { | ||
displayMode, | ||
throwOnError: false, | ||
strict: 'ignore' | ||
}) | ||
) | ||
} | ||
const root = fromHtmlIsomorphic(result, {fragment: true}) | ||
// @ts-expect-error: assume no `doctypes` in KaTeX result. | ||
element.children = root.children | ||
}) | ||
} | ||
} | ||
export {default} from './lib/index.js' |
{ | ||
"name": "rehype-katex", | ||
"version": "6.0.3", | ||
"version": "7.0.0", | ||
"description": "rehype plugin to transform inline and block math with KaTeX", | ||
"license": "MIT", | ||
"keywords": [ | ||
"unified", | ||
"remark", | ||
"rehype", | ||
"rehype-plugin", | ||
"plugin", | ||
"mdast", | ||
"markdown", | ||
"hast", | ||
"html", | ||
"math", | ||
"katex", | ||
"latex", | ||
"tex" | ||
"markdown", | ||
"math", | ||
"mdast", | ||
"plugin", | ||
"rehype", | ||
"rehype-plugin", | ||
"remark", | ||
"tex", | ||
"unified" | ||
], | ||
@@ -34,5 +34,5 @@ "repository": "https://github.com/remarkjs/remark-math/tree/main/packages/rehype-katex", | ||
"type": "module", | ||
"main": "index.js", | ||
"types": "index.d.ts", | ||
"exports": "./index.js", | ||
"files": [ | ||
"lib/", | ||
"index.d.ts", | ||
@@ -42,21 +42,20 @@ "index.js" | ||
"dependencies": { | ||
"@types/hast": "^2.0.0", | ||
"@types/katex": "^0.14.0", | ||
"hast-util-from-html-isomorphic": "^1.0.0", | ||
"hast-util-to-text": "^3.1.0", | ||
"@types/hast": "^3.0.0", | ||
"@types/katex": "^0.16.0", | ||
"hast-util-from-html-isomorphic": "^2.0.0", | ||
"hast-util-to-text": "^4.0.0", | ||
"katex": "^0.16.0", | ||
"unist-util-visit": "^4.0.0" | ||
"unist-util-visit-parents": "^6.0.0", | ||
"vfile": "^6.0.0" | ||
}, | ||
"scripts": { | ||
"build": "rimraf \"*.d.ts\" && tsc && type-coverage", | ||
"test-api": "node --conditions development test.js", | ||
"test": "npm run build && npm run test-api" | ||
}, | ||
"xo": false, | ||
"typeCoverage": { | ||
"atLeast": 100, | ||
"detail": true, | ||
"strict": true, | ||
"ignoreCatch": true | ||
"xo": { | ||
"prettier": true, | ||
"rules": { | ||
"unicorn/prefer-at": "off" | ||
} | ||
} | ||
} |
239
readme.md
@@ -11,4 +11,4 @@ # rehype-katex | ||
**[rehype][]** plugin to render `<span class=math-inline>` and | ||
`<div class=math-display>` with [KaTeX][]. | ||
**[rehype][]** plugin to render elements with a `language-math` class with | ||
[KaTeX][]. | ||
@@ -23,4 +23,6 @@ ## Contents | ||
* [`unified().use(rehypeKatex[, options])`](#unifieduserehypekatex-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-mathjax`][rehype-mathjax], is similar but uses | ||
[MathJax][] instead. | ||
A different plugin, [`rehype-mathjax`][rehype-mathjax], does the same but with | ||
[MathJax][]. | ||
## 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 rehypeKatex from 'https://esm.sh/rehype-katex@6' | ||
import rehypeKatex from 'https://esm.sh/rehype-katex@7' | ||
``` | ||
@@ -75,3 +71,3 @@ | ||
<script type="module"> | ||
import rehypeKatex from 'https://esm.sh/rehype-katex@6?bundle' | ||
import rehypeKatex from 'https://esm.sh/rehype-katex@7?bundle' | ||
</script> | ||
@@ -82,38 +78,39 @@ ``` | ||
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 rehypeDocument from 'rehype-document' | ||
import rehypeKatex from 'rehype-katex' | ||
import rehypeParse from 'rehype-parse' | ||
import rehypeKatex from 'rehype-katex' | ||
import rehypeDocument from 'rehype-document' | ||
import rehypeStringify from 'rehype-stringify' | ||
import {read, write} from 'to-vfile' | ||
import {unified} from 'unified' | ||
const file = await unified() | ||
.use(rehypeParse, {fragment: true}) | ||
.use(rehypeKatex) | ||
.use(rehypeDocument, { | ||
css: 'https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.css' | ||
// Get the latest one from: <https://katex.org/docs/browser>. | ||
css: 'https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css' | ||
}) | ||
.use(rehypeKatex) | ||
.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: | ||
@@ -125,12 +122,12 @@ ```html | ||
<meta charset="utf-8"> | ||
<title>example</title> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.css"> | ||
<title>input</title> | ||
<meta content="width=device-width, initial-scale=1" name="viewport"> | ||
<link href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" rel="stylesheet"> | ||
</head> | ||
<body> | ||
<p> | ||
Lift(<span class="math math-inline"><span class="katex">…</span></span>) can be determined by Lift Coefficient | ||
(<span class="math math-inline"><span class="katex">…</span></span>) like the following equation. | ||
Lift(<span class="katex"><!--…--></span>) can be determined by Lift Coefficient | ||
(<span class="katex"><!--…--></span>) like the following equation. | ||
</p> | ||
<div class="math math-display"><span class="katex-display">…</span></div> | ||
<span class="katex-display"><!--…--></span> | ||
</body> | ||
@@ -140,22 +137,57 @@ </html> | ||
…open `output.html` in a browser to see the rendered math. | ||
## API | ||
This package exports no identifiers. | ||
The default export is `rehypeKatex`. | ||
The default export is [`rehypeKatex`][api-rehype-katex]. | ||
### `unified().use(rehypeKatex[, options])` | ||
Transform `<span class="math-inline">` and `<div class="math-display">` with | ||
[KaTeX][]. | ||
Render elements with a `language-math` (or `math-display`, `math-inline`) | ||
class with [KaTeX][]. | ||
##### `options` | ||
###### Parameters | ||
Configuration (optional). | ||
All options, except for `displayMode`, are passed to [KaTeX][katex-options]. | ||
* `options` ([`Options`][api-options]) | ||
— configuration | ||
###### `options.throwOnError` | ||
###### Returns | ||
Throw if a KaTeX parse error occurs (`boolean`, default: `false`). | ||
See [KaTeX options][katex-options]. | ||
Transform ([`Transformer`][unified-transformer]). | ||
### `Options` | ||
Configuration (TypeScript type). | ||
###### Type | ||
```ts | ||
import {KatexOptions} from 'katex' | ||
type Options = Omit<KatexOptions, 'displayMode' | 'throwOnError'> | ||
``` | ||
See [*Options* on `katex.org`][katex-options] for more info. | ||
## Markdown | ||
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 KaTeX 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 | ||
@@ -169,24 +201,21 @@ | ||
```html | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.css" integrity="sha384-Xi8rHCmBmhbuyyhbI88391ZKP2dmfnOl4rT9ZfRI7mLTdk1wblIUnrIq35nqwEvC" crossorigin="anonymous"> | ||
<!-- Get the latest one from: https://katex.org/docs/browser --> | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css"> | ||
``` | ||
<!-- To update the above, read the note in the monorepo readme. --> | ||
## 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-katex@^7`, | ||
compatible with Node.js 16. | ||
This plugin works with unified version 6+ and rehype version 4+. | ||
@@ -196,36 +225,36 @@ | ||
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]. | ||
Assuming you trust KaTeX, using `rehype-katex` 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 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: | ||
When you don’t trust user content but do trust KaTeX, run `rehype-katex` | ||
*after* `rehype-sanitize`: | ||
```js | ||
import rehypeKatex from 'rehype-katex' | ||
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(rehypeKatex) | ||
.use(rehypeStringify) | ||
.process('$C$') | ||
// … | ||
unified() | ||
// … | ||
.use(rehypeSanitize, mathSanitizeSchema) | ||
.use(rehypeKatex) | ||
// … | ||
console.log(String(file)) | ||
``` | ||
@@ -274,5 +303,5 @@ | ||
[size-badge]: https://img.shields.io/bundlephobia/minzip/rehype-katex.svg | ||
[size-badge]: https://img.shields.io/bundlejs/size/rehype-katex | ||
[size]: https://bundlephobia.com/result?p=rehype-katex | ||
[size]: https://bundlejs.com/?q=rehype-katex | ||
@@ -291,2 +320,4 @@ [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg | ||
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c | ||
[esmsh]: https://esm.sh | ||
@@ -296,7 +327,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 | ||
@@ -307,20 +338,26 @@ [license]: https://github.com/remarkjs/remark-math/blob/main/license | ||
[unified]: https://github.com/unifiedjs/unified | ||
[katex]: https://github.com/Khan/KaTeX | ||
[katex-options]: https://katex.org/docs/options.html | ||
[rehype]: https://github.com/rehypejs/rehype | ||
[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting | ||
[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize | ||
[typescript]: https://www.typescriptlang.org | ||
[unified]: https://github.com/unifiedjs/unified | ||
[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize | ||
[unified-transformer]: https://github.com/unifiedjs/unified#transformer | ||
[katex]: https://github.com/Khan/KaTeX | ||
[typescript]: https://www.typescriptlang.org | ||
[katex-options]: https://katex.org/docs/options.html | ||
[wiki-xss]: https://en.wikipedia.org/wiki/Cross-site_scripting | ||
[mathjax]: https://www.mathjax.org | ||
[remark-math]: ../remark-math | ||
[remark-math]: ../remark-math/ | ||
[rehype-mathjax]: ../rehype-mathjax | ||
[rehype-mathjax]: ../rehype-mathjax/ | ||
[api-options]: #options | ||
[api-rehype-katex]: #unifieduserehypekatex-options |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
15698
6
150
349
7
1
+ Addedvfile@^6.0.0
+ Added@types/hast@3.0.4(transitive)
+ Added@types/katex@0.16.7(transitive)
+ Added@types/unist@3.0.3(transitive)
+ Addeddequal@2.0.3(transitive)
+ Addeddevlop@1.1.0(transitive)
+ Addedhast-util-from-dom@5.0.0(transitive)
+ Addedhast-util-from-html@2.0.3(transitive)
+ Addedhast-util-from-html-isomorphic@2.0.0(transitive)
+ Addedhast-util-from-parse5@8.0.1(transitive)
+ Addedhast-util-is-element@3.0.0(transitive)
+ Addedhast-util-parse-selector@4.0.0(transitive)
+ Addedhast-util-to-text@4.0.2(transitive)
+ Addedhastscript@8.0.0(transitive)
+ Addedunist-util-find-after@5.0.0(transitive)
+ Addedunist-util-is@6.0.0(transitive)
+ Addedunist-util-remove-position@5.0.0(transitive)
+ Addedunist-util-stringify-position@4.0.0(transitive)
+ Addedunist-util-visit@5.0.0(transitive)
+ Addedunist-util-visit-parents@6.0.1(transitive)
+ Addedvfile@6.0.3(transitive)
+ Addedvfile-location@5.0.3(transitive)
+ Addedvfile-message@4.0.2(transitive)
- Removedunist-util-visit@^4.0.0
- Removed@types/hast@2.3.10(transitive)
- Removed@types/katex@0.14.0(transitive)
- Removed@types/unist@2.0.11(transitive)
- Removedhast-util-from-dom@4.2.0(transitive)
- Removedhast-util-from-html@1.0.2(transitive)
- Removedhast-util-from-html-isomorphic@1.0.0(transitive)
- Removedhast-util-from-parse5@7.1.2(transitive)
- Removedhast-util-is-element@2.1.3(transitive)
- Removedhast-util-parse-selector@3.1.1(transitive)
- Removedhast-util-to-text@3.1.2(transitive)
- Removedhastscript@7.2.0(transitive)
- Removedis-buffer@2.0.5(transitive)
- Removedunist-util-find-after@4.0.1(transitive)
- Removedunist-util-is@5.2.1(transitive)
- Removedunist-util-remove-position@4.0.2(transitive)
- Removedunist-util-stringify-position@3.0.3(transitive)
- Removedunist-util-visit@4.1.2(transitive)
- Removedunist-util-visit-parents@5.1.3(transitive)
- Removedvfile@5.3.7(transitive)
- Removedvfile-location@4.1.0(transitive)
- Removedvfile-message@3.1.4(transitive)
Updated@types/hast@^3.0.0
Updated@types/katex@^0.16.0
Updatedhast-util-to-text@^4.0.0