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