-
-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
216 additions
and
199 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,116 +1,5 @@ | ||
/** | ||
* @typedef {import('hast').ElementContent} ElementContent | ||
* @typedef {import('hast').Root} Root | ||
* | ||
* @typedef {import('katex').KatexOptions} KatexOptions | ||
* | ||
* @typedef {import('vfile').VFile} VFile | ||
* @typedef {import('./lib/index.js').Options} Options | ||
*/ | ||
|
||
/** | ||
* @typedef {Omit<KatexOptions, 'throwOnError'>} Options | ||
*/ | ||
|
||
import {fromHtmlIsomorphic} from 'hast-util-from-html-isomorphic' | ||
import {toText} from 'hast-util-to-text' | ||
import katex from 'katex' | ||
import {visit} from 'unist-util-visit' | ||
|
||
/** @type {Readonly<Options>} */ | ||
const emptyOptions = {} | ||
/** @type {ReadonlyArray<unknown>} */ | ||
const emptyClasses = [] | ||
|
||
/** | ||
* Plugin to transform `<span class=math-inline>` and `<div class=math-display>` | ||
* with KaTeX. | ||
* | ||
* @param {Readonly<Options> | null | undefined} [options] | ||
* Configuration (optional). | ||
* @returns | ||
* Transform. | ||
*/ | ||
export default function rehypeKatex(options) { | ||
const settings = options || emptyOptions | ||
|
||
/** | ||
* Transform. | ||
* | ||
* @param {Root} tree | ||
* Tree. | ||
* @param {VFile} file | ||
* File. | ||
* @returns {undefined} | ||
* Nothing. | ||
*/ | ||
return function (tree, file) { | ||
visit(tree, 'element', function (element, _, parent) { | ||
const classes = Array.isArray(element.properties.className) | ||
? element.properties.className | ||
: emptyClasses | ||
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, { | ||
...settings, | ||
displayMode, | ||
throwOnError: true | ||
}) | ||
} catch (error) { | ||
const cause = /** @type {Error} */ (error) | ||
const ruleId = cause.name.toLowerCase() | ||
|
||
file.message('Could not render math with KaTeX', { | ||
/* c8 ignore next -- verbose to test */ | ||
ancestors: parent ? [parent, element] : [element], | ||
cause, | ||
place: element.position, | ||
ruleId, | ||
source: 'rehype-katex' | ||
}) | ||
|
||
// KaTeX can handle `ParseError` itself, but not others. | ||
if (ruleId === 'parseerror') { | ||
result = katex.renderToString(value, { | ||
...settings, | ||
displayMode, | ||
strict: 'ignore', | ||
throwOnError: false | ||
}) | ||
} | ||
// Generate similar markup if this is an other error. | ||
// See: <https://github.com/KaTeX/KaTeX/blob/5dc7af0/docs/error.md>. | ||
else { | ||
element.children = [ | ||
{ | ||
type: 'element', | ||
tagName: 'span', | ||
properties: { | ||
className: ['katex-error'], | ||
style: 'color:' + (settings.errorColor || '#cc0000'), | ||
title: String(error) | ||
}, | ||
children: [{type: 'text', value}] | ||
} | ||
] | ||
return | ||
} | ||
} | ||
|
||
const root = fromHtmlIsomorphic(result, {fragment: true}) | ||
// Cast because there will not be `doctypes` in KaTeX result. | ||
const content = /** @type {Array<ElementContent>} */ (root.children) | ||
element.children = content | ||
}) | ||
} | ||
} | ||
export {default} from './lib/index.js' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
/** | ||
* @typedef {import('hast').ElementContent} ElementContent | ||
* @typedef {import('hast').Root} Root | ||
* | ||
* @typedef {import('katex').KatexOptions} KatexOptions | ||
* | ||
* @typedef {import('vfile').VFile} VFile | ||
*/ | ||
|
||
/** | ||
* @typedef {Omit<KatexOptions, 'throwOnError'>} Options | ||
*/ | ||
|
||
import {fromHtmlIsomorphic} from 'hast-util-from-html-isomorphic' | ||
import {toText} from 'hast-util-to-text' | ||
import katex from 'katex' | ||
import {visit} from 'unist-util-visit' | ||
|
||
/** @type {Readonly<Options>} */ | ||
const emptyOptions = {} | ||
/** @type {ReadonlyArray<unknown>} */ | ||
const emptyClasses = [] | ||
|
||
/** | ||
* Plugin to transform `<span class=math-inline>` and `<div class=math-display>` | ||
* with KaTeX. | ||
* | ||
* @param {Readonly<Options> | null | undefined} [options] | ||
* Configuration (optional). | ||
* @returns | ||
* Transform. | ||
*/ | ||
export default function rehypeKatex(options) { | ||
const settings = options || emptyOptions | ||
|
||
/** | ||
* Transform. | ||
* | ||
* @param {Root} tree | ||
* Tree. | ||
* @param {VFile} file | ||
* File. | ||
* @returns {undefined} | ||
* Nothing. | ||
*/ | ||
return function (tree, file) { | ||
visit(tree, 'element', function (element, _, parent) { | ||
const classes = Array.isArray(element.properties.className) | ||
? element.properties.className | ||
: emptyClasses | ||
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, { | ||
...settings, | ||
displayMode, | ||
throwOnError: true | ||
}) | ||
} catch (error) { | ||
const cause = /** @type {Error} */ (error) | ||
const ruleId = cause.name.toLowerCase() | ||
|
||
file.message('Could not render math with KaTeX', { | ||
/* c8 ignore next -- verbose to test */ | ||
ancestors: parent ? [parent, element] : [element], | ||
cause, | ||
place: element.position, | ||
ruleId, | ||
source: 'rehype-katex' | ||
}) | ||
|
||
// KaTeX can handle `ParseError` itself, but not others. | ||
if (ruleId === 'parseerror') { | ||
result = katex.renderToString(value, { | ||
...settings, | ||
displayMode, | ||
strict: 'ignore', | ||
throwOnError: false | ||
}) | ||
} | ||
// Generate similar markup if this is an other error. | ||
// See: <https://github.com/KaTeX/KaTeX/blob/5dc7af0/docs/error.md>. | ||
else { | ||
element.children = [ | ||
{ | ||
type: 'element', | ||
tagName: 'span', | ||
properties: { | ||
className: ['katex-error'], | ||
style: 'color:' + (settings.errorColor || '#cc0000'), | ||
title: String(error) | ||
}, | ||
children: [{type: 'text', value}] | ||
} | ||
] | ||
return | ||
} | ||
} | ||
|
||
const root = fromHtmlIsomorphic(result, {fragment: true}) | ||
// Cast because there will not be `doctypes` in KaTeX result. | ||
const content = /** @type {Array<ElementContent>} */ (root.children) | ||
element.children = content | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,7 @@ | |
"main": "index.js", | ||
"types": "index.d.ts", | ||
"files": [ | ||
"lib/", | ||
"index.d.ts", | ||
"index.js" | ||
], | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,5 @@ | ||
/** | ||
* @typedef {import('./lib/create-plugin.js').Options} Options | ||
* @typedef {import('./lib/create-plugin.js').InputTexOptions} InputTexOptions | ||
*/ | ||
|
||
import {createPlugin} from './lib/create-plugin.js' | ||
|
||
/** @type {Readonly<InputTexOptions>} */ | ||
const emptyTexOptions = {} | ||
|
||
const rehypeMathJaxBrowser = createPlugin(function (options) { | ||
const tex = options.tex || emptyTexOptions | ||
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' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/** | ||
* @typedef {import('./create-plugin.js').InputTexOptions} InputTexOptions | ||
*/ | ||
|
||
import {createPlugin} from './create-plugin.js' | ||
|
||
/** @type {Readonly<InputTexOptions>} */ | ||
const emptyTexOptions = {} | ||
|
||
const rehypeMathJaxBrowser = createPlugin(function (options) { | ||
const tex = options.tex || emptyTexOptions | ||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import {CHTML} from 'mathjax-full/js/output/chtml.js' | ||
import {createPlugin} from './create-plugin.js' | ||
import {createRenderer} from './create-renderer.js' | ||
|
||
const rehypeMathJaxCHtml = createPlugin(function (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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import {SVG} from 'mathjax-full/js/output/svg.js' | ||
import {createPlugin} from './create-plugin.js' | ||
import {createRenderer} from './create-renderer.js' | ||
|
||
const rehypeMathJaxSvg = createPlugin(function (options) { | ||
// MathJax types do not allow `null`. | ||
return createRenderer(options, new SVG(options.svg || undefined)) | ||
}) | ||
|
||
export default rehypeMathJaxSvg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.