Skip to content

Commit 23914b6

Browse files
committed
Refactor to move code to lib/
1 parent e8039d7 commit 23914b6

File tree

12 files changed

+216
-199
lines changed

12 files changed

+216
-199
lines changed

packages/rehype-katex/index.js

Lines changed: 2 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,5 @@
11
/**
2-
* @typedef {import('hast').ElementContent} ElementContent
3-
* @typedef {import('hast').Root} Root
4-
*
5-
* @typedef {import('katex').KatexOptions} KatexOptions
6-
*
7-
* @typedef {import('vfile').VFile} VFile
2+
* @typedef {import('./lib/index.js').Options} Options
83
*/
94

10-
/**
11-
* @typedef {Omit<KatexOptions, 'throwOnError'>} Options
12-
*/
13-
14-
import {fromHtmlIsomorphic} from 'hast-util-from-html-isomorphic'
15-
import {toText} from 'hast-util-to-text'
16-
import katex from 'katex'
17-
import {visit} from 'unist-util-visit'
18-
19-
/** @type {Readonly<Options>} */
20-
const emptyOptions = {}
21-
/** @type {ReadonlyArray<unknown>} */
22-
const emptyClasses = []
23-
24-
/**
25-
* Plugin to transform `<span class=math-inline>` and `<div class=math-display>`
26-
* with KaTeX.
27-
*
28-
* @param {Readonly<Options> | null | undefined} [options]
29-
* Configuration (optional).
30-
* @returns
31-
* Transform.
32-
*/
33-
export default function rehypeKatex(options) {
34-
const settings = options || emptyOptions
35-
36-
/**
37-
* Transform.
38-
*
39-
* @param {Root} tree
40-
* Tree.
41-
* @param {VFile} file
42-
* File.
43-
* @returns {undefined}
44-
* Nothing.
45-
*/
46-
return function (tree, file) {
47-
visit(tree, 'element', function (element, _, parent) {
48-
const classes = Array.isArray(element.properties.className)
49-
? element.properties.className
50-
: emptyClasses
51-
const inline = classes.includes('math-inline')
52-
const displayMode = classes.includes('math-display')
53-
54-
if (!inline && !displayMode) {
55-
return
56-
}
57-
58-
const value = toText(element, {whitespace: 'pre'})
59-
60-
/** @type {string} */
61-
let result
62-
63-
try {
64-
result = katex.renderToString(value, {
65-
...settings,
66-
displayMode,
67-
throwOnError: true
68-
})
69-
} catch (error) {
70-
const cause = /** @type {Error} */ (error)
71-
const ruleId = cause.name.toLowerCase()
72-
73-
file.message('Could not render math with KaTeX', {
74-
/* c8 ignore next -- verbose to test */
75-
ancestors: parent ? [parent, element] : [element],
76-
cause,
77-
place: element.position,
78-
ruleId,
79-
source: 'rehype-katex'
80-
})
81-
82-
// KaTeX can handle `ParseError` itself, but not others.
83-
if (ruleId === 'parseerror') {
84-
result = katex.renderToString(value, {
85-
...settings,
86-
displayMode,
87-
strict: 'ignore',
88-
throwOnError: false
89-
})
90-
}
91-
// Generate similar markup if this is an other error.
92-
// See: <https://github.com/KaTeX/KaTeX/blob/5dc7af0/docs/error.md>.
93-
else {
94-
element.children = [
95-
{
96-
type: 'element',
97-
tagName: 'span',
98-
properties: {
99-
className: ['katex-error'],
100-
style: 'color:' + (settings.errorColor || '#cc0000'),
101-
title: String(error)
102-
},
103-
children: [{type: 'text', value}]
104-
}
105-
]
106-
return
107-
}
108-
}
109-
110-
const root = fromHtmlIsomorphic(result, {fragment: true})
111-
// Cast because there will not be `doctypes` in KaTeX result.
112-
const content = /** @type {Array<ElementContent>} */ (root.children)
113-
element.children = content
114-
})
115-
}
116-
}
5+
export {default} from './lib/index.js'

packages/rehype-katex/lib/index.js

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/**
2+
* @typedef {import('hast').ElementContent} ElementContent
3+
* @typedef {import('hast').Root} Root
4+
*
5+
* @typedef {import('katex').KatexOptions} KatexOptions
6+
*
7+
* @typedef {import('vfile').VFile} VFile
8+
*/
9+
10+
/**
11+
* @typedef {Omit<KatexOptions, 'throwOnError'>} Options
12+
*/
13+
14+
import {fromHtmlIsomorphic} from 'hast-util-from-html-isomorphic'
15+
import {toText} from 'hast-util-to-text'
16+
import katex from 'katex'
17+
import {visit} from 'unist-util-visit'
18+
19+
/** @type {Readonly<Options>} */
20+
const emptyOptions = {}
21+
/** @type {ReadonlyArray<unknown>} */
22+
const emptyClasses = []
23+
24+
/**
25+
* Plugin to transform `<span class=math-inline>` and `<div class=math-display>`
26+
* with KaTeX.
27+
*
28+
* @param {Readonly<Options> | null | undefined} [options]
29+
* Configuration (optional).
30+
* @returns
31+
* Transform.
32+
*/
33+
export default function rehypeKatex(options) {
34+
const settings = options || emptyOptions
35+
36+
/**
37+
* Transform.
38+
*
39+
* @param {Root} tree
40+
* Tree.
41+
* @param {VFile} file
42+
* File.
43+
* @returns {undefined}
44+
* Nothing.
45+
*/
46+
return function (tree, file) {
47+
visit(tree, 'element', function (element, _, parent) {
48+
const classes = Array.isArray(element.properties.className)
49+
? element.properties.className
50+
: emptyClasses
51+
const inline = classes.includes('math-inline')
52+
const displayMode = classes.includes('math-display')
53+
54+
if (!inline && !displayMode) {
55+
return
56+
}
57+
58+
const value = toText(element, {whitespace: 'pre'})
59+
60+
/** @type {string} */
61+
let result
62+
63+
try {
64+
result = katex.renderToString(value, {
65+
...settings,
66+
displayMode,
67+
throwOnError: true
68+
})
69+
} catch (error) {
70+
const cause = /** @type {Error} */ (error)
71+
const ruleId = cause.name.toLowerCase()
72+
73+
file.message('Could not render math with KaTeX', {
74+
/* c8 ignore next -- verbose to test */
75+
ancestors: parent ? [parent, element] : [element],
76+
cause,
77+
place: element.position,
78+
ruleId,
79+
source: 'rehype-katex'
80+
})
81+
82+
// KaTeX can handle `ParseError` itself, but not others.
83+
if (ruleId === 'parseerror') {
84+
result = katex.renderToString(value, {
85+
...settings,
86+
displayMode,
87+
strict: 'ignore',
88+
throwOnError: false
89+
})
90+
}
91+
// Generate similar markup if this is an other error.
92+
// See: <https://github.com/KaTeX/KaTeX/blob/5dc7af0/docs/error.md>.
93+
else {
94+
element.children = [
95+
{
96+
type: 'element',
97+
tagName: 'span',
98+
properties: {
99+
className: ['katex-error'],
100+
style: 'color:' + (settings.errorColor || '#cc0000'),
101+
title: String(error)
102+
},
103+
children: [{type: 'text', value}]
104+
}
105+
]
106+
return
107+
}
108+
}
109+
110+
const root = fromHtmlIsomorphic(result, {fragment: true})
111+
// Cast because there will not be `doctypes` in KaTeX result.
112+
const content = /** @type {Array<ElementContent>} */ (root.children)
113+
element.children = content
114+
})
115+
}
116+
}

packages/rehype-katex/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"main": "index.js",
3535
"types": "index.d.ts",
3636
"files": [
37+
"lib/",
3738
"index.d.ts",
3839
"index.js"
3940
],

packages/rehype-mathjax/browser.js

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,5 @@
11
/**
22
* @typedef {import('./lib/create-plugin.js').Options} Options
3-
* @typedef {import('./lib/create-plugin.js').InputTexOptions} InputTexOptions
43
*/
54

6-
import {createPlugin} from './lib/create-plugin.js'
7-
8-
/** @type {Readonly<InputTexOptions>} */
9-
const emptyTexOptions = {}
10-
11-
const rehypeMathJaxBrowser = createPlugin(function (options) {
12-
const tex = options.tex || emptyTexOptions
13-
const display = tex.displayMath || [['\\[', '\\]']]
14-
const inline = tex.inlineMath || [['\\(', '\\)']]
15-
16-
return {
17-
render(node, options) {
18-
const delimiters = (options.display ? display : inline)[0]
19-
node.children.unshift({type: 'text', value: delimiters[0]})
20-
node.children.push({type: 'text', value: delimiters[1]})
21-
}
22-
}
23-
})
24-
25-
export default rehypeMathJaxBrowser
5+
export {default} from './lib/browser.js'

packages/rehype-mathjax/chtml.js

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,4 @@
22
* @typedef {import('./lib/create-plugin.js').Options} Options
33
*/
44

5-
import {CHTML} from 'mathjax-full/js/output/chtml.js'
6-
import {createPlugin} from './lib/create-plugin.js'
7-
import {createRenderer} from './lib/create-renderer.js'
8-
9-
const rehypeMathJaxCHtml = createPlugin(function (options) {
10-
if (!options.chtml || !options.chtml.fontURL) {
11-
throw new Error(
12-
'rehype-mathjax: missing `fontURL` in options, which must be set to a URL to reach MathJaX fonts'
13-
)
14-
}
15-
16-
return createRenderer(options, new CHTML(options.chtml))
17-
})
18-
19-
export default rehypeMathJaxCHtml
5+
export {default} from './lib/chtml.js'

packages/rehype-mathjax/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
* @typedef {import('./lib/create-plugin.js').Options} Options
33
*/
44

5-
export {default} from './svg.js'
5+
export {default} from './lib/svg.js'
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* @typedef {import('./create-plugin.js').InputTexOptions} InputTexOptions
3+
*/
4+
5+
import {createPlugin} from './create-plugin.js'
6+
7+
/** @type {Readonly<InputTexOptions>} */
8+
const emptyTexOptions = {}
9+
10+
const rehypeMathJaxBrowser = createPlugin(function (options) {
11+
const tex = options.tex || emptyTexOptions
12+
const display = tex.displayMath || [['\\[', '\\]']]
13+
const inline = tex.inlineMath || [['\\(', '\\)']]
14+
15+
return {
16+
render(node, options) {
17+
const delimiters = (options.display ? display : inline)[0]
18+
node.children.unshift({type: 'text', value: delimiters[0]})
19+
node.children.push({type: 'text', value: delimiters[1]})
20+
}
21+
}
22+
})
23+
24+
export default rehypeMathJaxBrowser

packages/rehype-mathjax/lib/chtml.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import {CHTML} from 'mathjax-full/js/output/chtml.js'
2+
import {createPlugin} from './create-plugin.js'
3+
import {createRenderer} from './create-renderer.js'
4+
5+
const rehypeMathJaxCHtml = createPlugin(function (options) {
6+
if (!options.chtml || !options.chtml.fontURL) {
7+
throw new Error(
8+
'rehype-mathjax: missing `fontURL` in options, which must be set to a URL to reach MathJaX fonts'
9+
)
10+
}
11+
12+
return createRenderer(options, new CHTML(options.chtml))
13+
})
14+
15+
export default rehypeMathJaxCHtml

packages/rehype-mathjax/lib/svg.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import {SVG} from 'mathjax-full/js/output/svg.js'
2+
import {createPlugin} from './create-plugin.js'
3+
import {createRenderer} from './create-renderer.js'
4+
5+
const rehypeMathJaxSvg = createPlugin(function (options) {
6+
// MathJax types do not allow `null`.
7+
return createRenderer(options, new SVG(options.svg || undefined))
8+
})
9+
10+
export default rehypeMathJaxSvg

packages/rehype-mathjax/svg.js

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,4 @@
22
* @typedef {import('./lib/create-plugin.js').Options} Options
33
*/
44

5-
import {SVG} from 'mathjax-full/js/output/svg.js'
6-
import {createPlugin} from './lib/create-plugin.js'
7-
import {createRenderer} from './lib/create-renderer.js'
8-
9-
const rehypeMathJaxSvg = createPlugin(function (options) {
10-
// `mathjax-types` do not allow `null`.
11-
return createRenderer(options, new SVG(options.svg || undefined))
12-
})
13-
14-
export default rehypeMathJaxSvg
5+
export {default} from './lib/svg.js'

0 commit comments

Comments
 (0)