` with
74 | [KaTeX][].
75 |
76 | #### `options`
77 |
78 | ##### `options.throwOnError`
79 |
80 | Throw if a KaTeX parse error occurs (`boolean`, default: `false`).
81 | See [KaTeX options][katex-options].
82 |
83 | ##### `options.<*>`
84 |
85 | All other options, except for `displayMode`, are passed to
86 | [KaTeX][katex-options].
87 |
88 | ## Security
89 |
90 | Use of `rehype-katex` renders user content with [KaTeX][], so any vulnerability
91 | in KaTeX can open you to a [cross-site scripting (XSS)][xss] attack.
92 |
93 | Always be wary of user input and use [`rehype-sanitize`][rehype-sanitize].
94 |
95 | ## Contribute
96 |
97 | See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways
98 | to get started.
99 | See [`support.md`][support] for ways to get help.
100 |
101 | This project has a [code of conduct][coc].
102 | By interacting with this repository, organization, or community you agree to
103 | abide by its terms.
104 |
105 | ## License
106 |
107 | [MIT][license] © [Junyoung Choi][author]
108 |
109 |
110 |
111 | [build-badge]: https://img.shields.io/travis/remarkjs/remark-math/main.svg
112 |
113 | [build]: https://travis-ci.org/remarkjs/remark-math
114 |
115 | [coverage-badge]: https://img.shields.io/codecov/c/github/remarkjs/remark-math.svg
116 |
117 | [coverage]: https://codecov.io/github/remarkjs/remark-math
118 |
119 | [downloads-badge]: https://img.shields.io/npm/dm/rehype-katex.svg
120 |
121 | [downloads]: https://www.npmjs.com/package/rehype-katex
122 |
123 | [size-badge]: https://img.shields.io/bundlephobia/minzip/rehype-katex.svg
124 |
125 | [size]: https://bundlephobia.com/result?p=rehype-katex
126 |
127 | [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg
128 |
129 | [backers-badge]: https://opencollective.com/unified/backers/badge.svg
130 |
131 | [collective]: https://opencollective.com/unified
132 |
133 | [chat-badge]: https://img.shields.io/badge/chat-spectrum-7b16ff.svg
134 |
135 | [chat]: https://spectrum.chat/unified/remark
136 |
137 | [npm]: https://docs.npmjs.com/cli/install
138 |
139 | [health]: https://github.com/remarkjs/.github
140 |
141 | [contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md
142 |
143 | [support]: https://github.com/remarkjs/.github/blob/HEAD/support.md
144 |
145 | [coc]: https://github.com/remarkjs/.github/blob/HEAD/code-of-conduct.md
146 |
147 | [license]: https://github.com/remarkjs/remark-math/blob/main/license
148 |
149 | [author]: https://rokt33r.github.io
150 |
151 | [rehype]: https://github.com/rehypejs/rehype
152 |
153 | [xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
154 |
155 | [rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize
156 |
157 | [katex]: https://github.com/Khan/KaTeX
158 |
159 | [katex-options]: https://katex.org/docs/options.html
160 |
--------------------------------------------------------------------------------
/packages/remark-math/readme.md:
--------------------------------------------------------------------------------
1 | # remark-math
2 |
3 | [![Build][build-badge]][build]
4 | [![Coverage][coverage-badge]][coverage]
5 | [![Downloads][downloads-badge]][downloads]
6 | [![Size][size-badge]][size]
7 | [![Sponsors][sponsors-badge]][collective]
8 | [![Backers][backers-badge]][collective]
9 | [![Chat][chat-badge]][chat]
10 |
11 | [**remark**][remark] plugin to parse and stringify math.
12 |
13 | ## Install
14 |
15 | [npm][]:
16 |
17 | ```sh
18 | npm install remark-math
19 | ```
20 |
21 | ## Use
22 |
23 | Say we have the following file, `example.md`:
24 |
25 | ```markdown
26 | Lift($L$) can be determined by Lift Coefficient ($C_L$) like the following equation.
27 |
28 | $$
29 | L = \frac{1}{2} \rho v^2 S C_L
30 | $$
31 | ```
32 |
33 | And our script, `example.js`, looks as follows:
34 |
35 | ```js
36 | const vfile = require('to-vfile')
37 | const unified = require('unified')
38 | const markdown = require('remark-parse')
39 | const math = require('remark-math')
40 | const remark2rehype = require('remark-rehype')
41 | const katex = require('rehype-katex')
42 | const stringify = require('rehype-stringify')
43 |
44 | unified()
45 | .use(markdown)
46 | .use(math)
47 | .use(remark2rehype)
48 | .use(katex)
49 | .use(stringify)
50 | .process(vfile.readSync('example.md'), function(err, file) {
51 | if (err) throw err
52 | console.log(String(file))
53 | })
54 | ```
55 |
56 | Now, running `node example` yields:
57 |
58 | ```html
59 |
Lift(L L L ) can be determined by Lift Coefficient (C L C_L C L ) like the following equation.
60 |
L = 1 2 ρ v 2 S C L L = \frac{1}{2} \rho v^2 S C_L L = 2 1 ρ v 2 S C L
61 | ```
62 |
63 | ## API
64 |
65 | ### `remark().use(math[, options])`
66 |
67 | Parse and stringify math.
68 |
69 | Get’s useful when combined with [`rehype-katex`][rehype-katex] or
70 | [`remark-html-katex`][remark-html-katex].
71 |
72 | You can also support only inline, or online block math, by importing them
73 | directly:
74 |
75 | ```js
76 | const mathInline = require('remark-math/inline')
77 |
78 | // …
79 |
80 | unified()
81 | // …
82 | .use(mathInline)
83 | // …
84 | ```
85 |
86 | #### `options`
87 |
88 | ##### `options.inlineMathDouble`
89 |
90 | Add an extra `math-display` class to inline `$$` math (default: `false`).
91 |
92 | #### Notes
93 |
94 | ##### Escaping
95 |
96 | You can escape dollar signs with a back slash (`\`):
97 |
98 | ```markdown
99 | \$\alpha\$
100 |
101 | $\alpha\$$
102 |
103 | $$
104 | \beta\$
105 | $$
106 | ```
107 |
108 | ## Security
109 |
110 | Use of `remark-math` itself doesn’t open you up to [cross-site scripting
111 | (XSS)][xss] attacks.
112 |
113 | Always be wary of user input and use [`rehype-sanitize`][rehype-sanitize].
114 |
115 | ## Contribute
116 |
117 | See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways
118 | to get started.
119 | See [`support.md`][support] for ways to get help.
120 |
121 | This project has a [code of conduct][coc].
122 | By interacting with this repository, organization, or community you agree to
123 | abide by its terms.
124 |
125 | ## License
126 |
127 | [MIT][license] © [Junyoung Choi][author]
128 |
129 |
130 |
131 | [build-badge]: https://img.shields.io/travis/remarkjs/remark-math/main.svg
132 |
133 | [build]: https://travis-ci.org/remarkjs/remark-math
134 |
135 | [coverage-badge]: https://img.shields.io/codecov/c/github/remarkjs/remark-math.svg
136 |
137 | [coverage]: https://codecov.io/github/remarkjs/remark-math
138 |
139 | [downloads-badge]: https://img.shields.io/npm/dm/remark-math.svg
140 |
141 | [downloads]: https://www.npmjs.com/package/remark-math
142 |
143 | [size-badge]: https://img.shields.io/bundlephobia/minzip/remark-math.svg
144 |
145 | [size]: https://bundlephobia.com/result?p=remark-math
146 |
147 | [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg
148 |
149 | [backers-badge]: https://opencollective.com/unified/backers/badge.svg
150 |
151 | [collective]: https://opencollective.com/unified
152 |
153 | [chat-badge]: https://img.shields.io/badge/chat-spectrum-7b16ff.svg
154 |
155 | [chat]: https://spectrum.chat/unified/remark
156 |
157 | [npm]: https://docs.npmjs.com/cli/install
158 |
159 | [health]: https://github.com/remarkjs/.github
160 |
161 | [contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md
162 |
163 | [support]: https://github.com/remarkjs/.github/blob/HEAD/support.md
164 |
165 | [coc]: https://github.com/remarkjs/.github/blob/HEAD/code-of-conduct.md
166 |
167 | [license]: https://github.com/remarkjs/remark-math/blob/main/license
168 |
169 | [author]: https://rokt33r.github.io
170 |
171 | [remark]: https://github.com/remarkjs/remark
172 |
173 | [xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
174 |
175 | [rehype-katex]: https://github.com/remarkjs/remark-math/tree/main/packages/rehype-katex
176 |
177 | [remark-html-katex]: https://github.com/remarkjs/remark-math/tree/main/packages/remark-html-katex
178 |
179 | [rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize
180 |
--------------------------------------------------------------------------------
/packages/rehype-mathjax/test/fixture/small-chtml.html:
--------------------------------------------------------------------------------
1 |
Inline math .
2 |
Block math:
3 |
4 |
397 |
--------------------------------------------------------------------------------
/packages/remark-html-katex/readme.md:
--------------------------------------------------------------------------------
1 | # remark-html-katex
2 |
3 | [![Build][build-badge]][build]
4 | [![Coverage][coverage-badge]][coverage]
5 | [![Downloads][downloads-badge]][downloads]
6 | [![Size][size-badge]][size]
7 | [![Sponsors][sponsors-badge]][collective]
8 | [![Backers][backers-badge]][collective]
9 | [![Chat][chat-badge]][chat]
10 |
11 | [**remark**][remark] plugin to transform `inlineMath` and `math` nodes with
12 | [KaTeX][] for [`remark-html`][remark-html].
13 |
14 | > This package integrates with [`remark-html`][remark-html].
15 | > It’s better to work with [**rehype**][rehype], which is specifically made
16 | > for HTML, and to use [`rehype-katex`][rehype-katex] instead of this package.
17 |
18 | ## Install
19 |
20 | [npm][]:
21 |
22 | ```sh
23 | npm install remark-html-katex
24 | ```
25 |
26 | ## Use
27 |
28 | Say we have the following file, `example.md`:
29 |
30 | ```html
31 | Lift($L$) can be determined by Lift Coefficient ($C_L$) like the following equation.
32 |
33 | $$
34 | L = \frac{1}{2} \rho v^2 S C_L
35 | $$
36 | ```
37 |
38 | And our script, `example.js`, looks as follows:
39 |
40 | ```js
41 | const vfile = require('to-vfile')
42 | const unified = require('unified')
43 | const markdown = require('remark-parse')
44 | const math = require('remark-math')
45 | const htmlKatex = require('remark-html-katex')
46 | const html = require('remark-html')
47 |
48 | unified()
49 | .use(markdown)
50 | .use(math)
51 | .use(htmlKatex)
52 | .use(html)
53 | .process(vfile.readSync('example.md'), function(err, file) {
54 | if (err) throw err
55 | console.log(String(file))
56 | })
57 | ```
58 |
59 | Now, running `node example` yields:
60 |
61 | ```html
62 |
Lift(L L L ) can be determined by Lift Coefficient (C L C_L C L ) like the following equation.
63 |
L = 1 2 ρ v 2 S C L L = \frac{1}{2} \rho v^2 S C_L L = 2 1 ρ v 2 S C L
64 | ```
65 |
66 | ## API
67 |
68 | ### `remark().use(htmlKatex[, options])`
69 |
70 | Transform `inlineMath` and `math` nodes with [KaTeX][] for
71 | [`remark-html`][remark-html].
72 |
73 | #### `options`
74 |
75 | ##### `options.throwOnError`
76 |
77 | Throw if a KaTeX parse error occurs (`boolean`, default: `false`).
78 | See [KaTeX options][katex-options].
79 |
80 | ##### `options.<*>`
81 |
82 | All other options, except for `displayMode`, are passed to
83 | [KaTeX][katex-options].
84 |
85 | ## Security
86 |
87 | Use of `remark-html-katex` renders user content with [KaTeX][], so any
88 | vulnerability in KaTeX can open you to a [cross-site scripting (XSS)][xss]
89 | attack.
90 |
91 | Always be wary of user input and use the [`sanitize`][remark-html-sanitize]
92 | option of `remark-html`.
93 |
94 | ## Contribute
95 |
96 | See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways
97 | to get started.
98 | See [`support.md`][support] for ways to get help.
99 |
100 | This project has a [code of conduct][coc].
101 | By interacting with this repository, organization, or community you agree to
102 | abide by its terms.
103 |
104 | ## License
105 |
106 | [MIT][license] © [Junyoung Choi][author]
107 |
108 |
109 |
110 | [build-badge]: https://img.shields.io/travis/remarkjs/remark-math/main.svg
111 |
112 | [build]: https://travis-ci.org/remarkjs/remark-math
113 |
114 | [coverage-badge]: https://img.shields.io/codecov/c/github/remarkjs/remark-math.svg
115 |
116 | [coverage]: https://codecov.io/github/remarkjs/remark-math
117 |
118 | [downloads-badge]: https://img.shields.io/npm/dm/remark-html-katex.svg
119 |
120 | [downloads]: https://www.npmjs.com/package/remark-html-katex
121 |
122 | [size-badge]: https://img.shields.io/bundlephobia/minzip/remark-html-katex.svg
123 |
124 | [size]: https://bundlephobia.com/result?p=remark-html-katex
125 |
126 | [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg
127 |
128 | [backers-badge]: https://opencollective.com/unified/backers/badge.svg
129 |
130 | [collective]: https://opencollective.com/unified
131 |
132 | [chat-badge]: https://img.shields.io/badge/chat-spectrum-7b16ff.svg
133 |
134 | [chat]: https://spectrum.chat/unified/remark
135 |
136 | [npm]: https://docs.npmjs.com/cli/install
137 |
138 | [health]: https://github.com/remarkjs/.github
139 |
140 | [contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md
141 |
142 | [support]: https://github.com/remarkjs/.github/blob/HEAD/support.md
143 |
144 | [coc]: https://github.com/remarkjs/.github/blob/HEAD/code-of-conduct.md
145 |
146 | [license]: https://github.com/remarkjs/remark-math/blob/main/license
147 |
148 | [author]: https://rokt33r.github.io
149 |
150 | [remark]: https://github.com/remarkjs/remark
151 |
152 | [remark-html]: https://github.com/remarkjs/remark-html
153 |
154 | [remark-html-sanitize]: https://github.com/remarkjs/remark-html#optionssanitize
155 |
156 | [rehype]: https://github.com/rehypejs/rehype
157 |
158 | [xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
159 |
160 | [katex]: https://github.com/Khan/KaTeX
161 |
162 | [katex-options]: https://katex.org/docs/options.html
163 |
164 | [rehype-katex]: https://github.com/remarkjs/remark-math/tree/main/packages/rehype-katex
165 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # remark-math
2 |
3 | [![Build][build-badge]][build]
4 | [![Coverage][coverage-badge]][coverage]
5 | [![Downloads][downloads-badge]][downloads]
6 | [![Size][size-badge]][size]
7 | [![Sponsors][sponsors-badge]][collective]
8 | [![Backers][backers-badge]][collective]
9 | [![Chat][chat-badge]][chat]
10 |
11 | [**remark**][remark] and [**rehype**][rehype] plugins to support math!
12 |
13 | ## Install
14 |
15 | [npm][]:
16 |
17 | ```sh
18 | npm install remark-math rehype-katex
19 | ```
20 |
21 | ## Use
22 |
23 | Say we have the following file, `example.md`:
24 |
25 | ```markdown
26 | Lift($L$) can be determined by Lift Coefficient ($C_L$) like the following equation.
27 |
28 | $$
29 | L = \frac{1}{2} \rho v^2 S C_L
30 | $$
31 | ```
32 |
33 | And our script, `example.js`, looks as follows:
34 |
35 | ```js
36 | const vfile = require('to-vfile')
37 | const unified = require('unified')
38 | const markdown = require('remark-parse')
39 | const math = require('remark-math')
40 | const remark2rehype = require('remark-rehype')
41 | const katex = require('rehype-katex')
42 | const stringify = require('rehype-stringify')
43 |
44 | unified()
45 | .use(markdown)
46 | .use(math)
47 | .use(remark2rehype)
48 | .use(katex)
49 | .use(stringify)
50 | .process(vfile.readSync('example.md'), function(err, file) {
51 | if (err) throw err
52 | console.log(String(file))
53 | })
54 | ```
55 |
56 | Now, running `node example` yields:
57 |
58 | ```html
59 |
Lift(L L L ) can be determined by Lift Coefficient (C L C_L C L ) like the following equation.
60 |
L = 1 2 ρ v 2 S C L L = \frac{1}{2} \rho v^2 S C_L L = 2 1 ρ v 2 S C L
61 | ```
62 |
63 | Wow, that’s a lot!
64 | But in a browser, that looks something like this:
65 |
66 | ![][screenshot]
67 |
68 | > Note: you should also use `katex.css` somewhere on the page to style math
69 | > properly:
70 | >
71 | > ```html
72 | >
73 | > ```
74 |
75 | ## Packages
76 |
77 | This repo houses four packages:
78 |
79 | * [`remark-math`][remark-math]
80 | — Parses `$` as `inlineMath` and `$$` as `math` nodes
81 | * [`rehype-katex`][rehype-katex]
82 | — Transforms math nodes with [KaTeX][]
83 | (✨ recommended)
84 | * [`rehype-mathjax`][rehype-mathjax]
85 | — Transforms math nodes with [MathJax][]
86 | (✨ recommended)
87 | * [`remark-html-katex`][remark-html-katex]
88 | — Transforms math nodes with [KaTeX][] for [`remark-html`][remark-html]
89 | (discouraged)
90 |
91 | See their readmes for more information.
92 |
93 | ## Security
94 |
95 | Use of `rehype-katex` or `remark-html-katex` renders user content with
96 | [KaTeX][], so any vulnerability in KaTeX can open you to a
97 | [cross-site scripting (XSS)][xss] attack.
98 |
99 | Always be wary of user input and use [`rehype-sanitize`][rehype-sanitize].
100 |
101 | ## Related
102 |
103 | * [`remark-github`][remark-github]
104 | — Auto-link references like in GitHub issues, PRs, and comments
105 | * [`remark-frontmatter`][remark-frontmatter]
106 | — Support frontmatter (YAML, TOML, and more)
107 | * [`remark-footnotes`][remark-footnotes]
108 | — Support footnotes
109 | * [`remark-breaks`][remark-breaks]
110 | – Support hard breaks without needing spaces (like on issues)
111 |
112 | ## Contribute
113 |
114 | See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways
115 | to get started.
116 | See [`support.md`][support] for ways to get help.
117 |
118 | This project has a [code of conduct][coc].
119 | By interacting with this repository, organization, or community you agree to
120 | abide by its terms.
121 |
122 | ## License
123 |
124 | [MIT][license] © [Junyoung Choi][author]
125 |
126 |
127 |
128 | [build-badge]: https://img.shields.io/travis/remarkjs/remark-math/main.svg
129 |
130 | [build]: https://travis-ci.org/remarkjs/remark-math
131 |
132 | [coverage-badge]: https://img.shields.io/codecov/c/github/remarkjs/remark-math.svg
133 |
134 | [coverage]: https://codecov.io/github/remarkjs/remark-math
135 |
136 | [downloads-badge]: https://img.shields.io/npm/dm/remark-math.svg
137 |
138 | [downloads]: https://www.npmjs.com/package/remark-math
139 |
140 | [size-badge]: https://img.shields.io/bundlephobia/minzip/remark-math.svg
141 |
142 | [size]: https://bundlephobia.com/result?p=remark-math
143 |
144 | [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg
145 |
146 | [backers-badge]: https://opencollective.com/unified/backers/badge.svg
147 |
148 | [collective]: https://opencollective.com/unified
149 |
150 | [chat-badge]: https://img.shields.io/badge/chat-spectrum-7b16ff.svg
151 |
152 | [chat]: https://spectrum.chat/unified/remark
153 |
154 | [npm]: https://docs.npmjs.com/cli/install
155 |
156 | [health]: https://github.com/remarkjs/.github
157 |
158 | [contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md
159 |
160 | [support]: https://github.com/remarkjs/.github/blob/HEAD/support.md
161 |
162 | [coc]: https://github.com/remarkjs/.github/blob/HEAD/code-of-conduct.md
163 |
164 | [license]: license
165 |
166 | [author]: https://rokt33r.github.io
167 |
168 | [remark]: https://github.com/remarkjs/remark
169 |
170 | [remark-html]: https://github.com/remarkjs/remark-html
171 |
172 | [remark-github]: https://github.com/remarkjs/remark-github
173 |
174 | [remark-frontmatter]: https://github.com/remarkjs/remark-frontmatter
175 |
176 | [remark-footnotes]: https://github.com/remarkjs/remark-footnotes
177 |
178 | [remark-breaks]: https://github.com/remarkjs/remark-breaks
179 |
180 | [rehype]: https://github.com/rehypejs/rehype
181 |
182 | [rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize
183 |
184 | [katex]: https://github.com/Khan/KaTeX
185 |
186 | [mathjax]: https://mathjax.org/
187 |
188 | [xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
189 |
190 | [remark-math]: ./packages/remark-math
191 |
192 | [rehype-katex]: ./packages/rehype-katex
193 |
194 | [rehype-mathjax]: ./packages/rehype-mathjax
195 |
196 | [remark-html-katex]: ./packages/remark-html-katex
197 |
198 | [screenshot]: screenshot.png
199 |
--------------------------------------------------------------------------------
/packages/remark-math/test.js:
--------------------------------------------------------------------------------
1 | const test = require('tape')
2 | const unified = require('unified')
3 | const parse = require('remark-parse')
4 | const remark2rehype = require('remark-rehype')
5 | const rehypeStringify = require('rehype-stringify')
6 | const stringify = require('remark-stringify')
7 | const u = require('unist-builder')
8 | const math = require('.')
9 |
10 | test('remark-math', function (t) {
11 | const toHtml = unified()
12 | .use(parse)
13 | .use(math, {inlineMathDouble: true})
14 | .use(remark2rehype)
15 | .use(rehypeStringify)
16 |
17 | t.deepEqual(
18 | unified()
19 | .use(parse, {position: false})
20 | .use(math)
21 | .parse('Math $\\alpha$\n\n$$\n\\beta+\\gamma\n$$'),
22 | u('root', [
23 | u('paragraph', [
24 | u('text', 'Math '),
25 | u(
26 | 'inlineMath',
27 | {
28 | data: {
29 | hName: 'span',
30 | hProperties: {className: ['math', 'math-inline']},
31 | hChildren: [u('text', '\\alpha')]
32 | }
33 | },
34 | '\\alpha'
35 | )
36 | ]),
37 | u(
38 | 'math',
39 | {
40 | data: {
41 | hName: 'div',
42 | hProperties: {className: ['math', 'math-display']},
43 | hChildren: [u('text', '\\beta+\\gamma')]
44 | }
45 | },
46 | '\\beta+\\gamma'
47 | )
48 | ]),
49 | 'should parse inline and block math'
50 | )
51 |
52 | t.deepEqual(
53 | unified().use(parse, {position: false}).use(math).parse('\\$\\alpha$'),
54 | u('root', [u('paragraph', [u('text', '$'), u('text', '\\alpha$')])]),
55 | 'should ignore an escaped opening dollar sign'
56 | )
57 |
58 | t.deepEqual(
59 | unified().use(parse, {position: false}).use(math).parse('$\\alpha\\$'),
60 | u('root', [u('paragraph', [u('text', '$\\alpha'), u('text', '$')])]),
61 | 'should ignore an escaped closing dollar sign'
62 | )
63 |
64 | t.deepEqual(
65 | unified().use(parse, {position: false}).use(math).parse('\\$\\alpha$'),
66 | u('root', [u('paragraph', [u('text', '$'), u('text', '\\alpha$')])]),
67 | 'should ignore an escaped opening dollar sign'
68 | )
69 | t.deepEqual(
70 | unified().use(parse, {position: false}).use(math).parse('$\\alpha\\$'),
71 | u('root', [u('paragraph', [u('text', '$\\alpha'), u('text', '$')])]),
72 | 'should ignore an escaped closing dollar sign'
73 | )
74 |
75 | t.deepEqual(
76 | unified().use(parse, {position: false}).use(math).parse('\\\\$\\alpha$'),
77 | u('root', [
78 | u('paragraph', [
79 | u('text', '\\'),
80 | u(
81 | 'inlineMath',
82 | {
83 | data: {
84 | hName: 'span',
85 | hProperties: {className: ['math', 'math-inline']},
86 | hChildren: [u('text', '\\alpha')]
87 | }
88 | },
89 | '\\alpha'
90 | )
91 | ])
92 | ]),
93 | 'should support a escaped escape before a dollar sign'
94 | )
95 |
96 | t.deepEqual(
97 | unified().use(parse, {position: false}).use(math).parse('`$`\\alpha$'),
98 | u('root', [u('paragraph', [u('inlineCode', '$'), u('text', '\\alpha$')])]),
99 | 'should ignore dollar signs in inline code (#1)'
100 | )
101 |
102 | t.deepEqual(
103 | unified().use(parse, {position: false}).use(math).parse('$\\alpha`$`'),
104 | u('root', [
105 | u('paragraph', [
106 | u(
107 | 'inlineMath',
108 | {
109 | data: {
110 | hName: 'span',
111 | hProperties: {className: ['math', 'math-inline']},
112 | hChildren: [u('text', '\\alpha`')]
113 | }
114 | },
115 | '\\alpha`'
116 | ),
117 | u('text', '`')
118 | ])
119 | ]),
120 | 'should allow backticks in math'
121 | )
122 |
123 | t.deepEqual(
124 | unified().use(parse, {position: false}).use(math).parse('$`\\alpha`$'),
125 | u('root', [
126 | u('paragraph', [
127 | u(
128 | 'inlineMath',
129 | {
130 | data: {
131 | hName: 'span',
132 | hProperties: {className: ['math', 'math-inline']},
133 | hChildren: [u('text', '`\\alpha`')]
134 | }
135 | },
136 | '`\\alpha`'
137 | )
138 | ])
139 | ]),
140 | 'should support backticks in inline math'
141 | )
142 |
143 | t.deepEqual(
144 | unified().use(parse, {position: false}).use(math).parse('$\\alpha\\$$'),
145 | u('root', [
146 | u('paragraph', [
147 | u(
148 | 'inlineMath',
149 | {
150 | data: {
151 | hName: 'span',
152 | hProperties: {className: ['math', 'math-inline']},
153 | hChildren: [u('text', '\\alpha\\$')]
154 | }
155 | },
156 | '\\alpha\\$'
157 | )
158 | ])
159 | ]),
160 | 'should support a super factorial in inline math'
161 | )
162 |
163 | t.deepEqual(
164 | unified()
165 | .use(parse, {position: false})
166 | .use(math)
167 | .parse('$$\n\\alpha\\$\n$$'),
168 | u('root', [
169 | u(
170 | 'math',
171 | {
172 | data: {
173 | hName: 'div',
174 | hProperties: {className: ['math', 'math-display']},
175 | hChildren: [u('text', '\\alpha\\$')]
176 | }
177 | },
178 | '\\alpha\\$'
179 | )
180 | ]),
181 | 'should support a super factorial in block math'
182 | )
183 |
184 | t.deepEqual(
185 | unified()
186 | .use(parse, {position: false})
187 | .use(math)
188 | .parse('tango\n$$\n\\alpha\n$$'),
189 | u('root', [
190 | u('paragraph', [u('text', 'tango')]),
191 | u(
192 | 'math',
193 | {
194 | data: {
195 | hName: 'div',
196 | hProperties: {className: ['math', 'math-display']},
197 | hChildren: [u('text', '\\alpha')]
198 | }
199 | },
200 | '\\alpha'
201 | )
202 | ]),
203 | 'should support a math block right after a paragraph'
204 | )
205 |
206 | t.deepEqual(
207 | unified().use(parse, {position: false}).use(math).parse('$$\\alpha$$'),
208 | u('root', [
209 | u('paragraph', [
210 | u(
211 | 'inlineMath',
212 | {
213 | data: {
214 | hName: 'span',
215 | hProperties: {className: ['math', 'math-inline']},
216 | hChildren: [u('text', '\\alpha')]
217 | }
218 | },
219 | '\\alpha'
220 | )
221 | ])
222 | ]),
223 | 'should support inline math with double dollars'
224 | )
225 |
226 | t.deepEqual(
227 | unified()
228 | .use(parse, {position: false})
229 | .use(math)
230 | .parse('$$$\n\\alpha\n$$$'),
231 | u('root', [
232 | u(
233 | 'math',
234 | {
235 | data: {
236 | hName: 'div',
237 | hProperties: {className: ['math', 'math-display']},
238 | hChildren: [u('text', '\\alpha')]
239 | }
240 | },
241 | '\\alpha'
242 | )
243 | ]),
244 | 'should support block math with triple dollars'
245 | )
246 |
247 | t.deepEqual(
248 | unified()
249 | .use(parse, {position: false})
250 | .use(math)
251 | .parse(' $$\n \\alpha\n $$'),
252 | u('root', [
253 | u(
254 | 'math',
255 | {
256 | data: {
257 | hName: 'div',
258 | hProperties: {className: ['math', 'math-display']},
259 | hChildren: [u('text', ' \\alpha')]
260 | }
261 | },
262 | ' \\alpha'
263 | )
264 | ]),
265 | 'should support indented block math'
266 | )
267 |
268 | t.deepEqual(
269 | unified()
270 | .use(parse, {position: false})
271 | .use(stringify)
272 | .use(math)
273 | .processSync('Math $\\alpha$\n\n$$\n\\beta+\\gamma\n$$\n')
274 | .toString(),
275 | 'Math $\\alpha$\n\n$$\n\\beta+\\gamma\n$$\n',
276 | 'should stringify inline and block math'
277 | )
278 |
279 | t.deepEqual(
280 | unified()
281 | .use(parse, {position: false})
282 | .use(stringify)
283 | .use(math)
284 | .processSync('> $$\n> \\alpha\\beta\n> $$\n')
285 | .toString(),
286 | '> $$\n> \\alpha\\beta\n> $$\n',
287 | 'should stringify math in a blockquote'
288 | )
289 |
290 | t.deepEqual(
291 | String(toHtml.processSync('$$just two dollars')),
292 | '
$$just two dollars
',
293 | 'should not support an opening fence without newline'
294 | )
295 | t.deepEqual(
296 | String(toHtml.processSync('$$ must\n\\alpha\n$$')),
297 | '
must\n\\alpha
',
298 | 'should include values after the opening fence (except for spacing #1)'
299 | )
300 | t.deepEqual(
301 | String(toHtml.processSync('$$ \n\\alpha\n$$')),
302 | '
\\alpha
',
303 | 'should include values after the opening fence (except for spacing #2)'
304 | )
305 | t.deepEqual(
306 | String(toHtml.processSync('$$\n\\alpha\nmust $$')),
307 | '
\\alpha\nmust
',
308 | 'should include values before the closing fence (except for spacing #1)'
309 | )
310 | t.deepEqual(
311 | String(toHtml.processSync('$$\n\\alpha\n $$')),
312 | '
\\alpha
',
313 | 'should include values before the closing fence (except for spacing #2)'
314 | )
315 | t.deepEqual(
316 | String(toHtml.processSync('$$\n\\alpha$$ ')),
317 | '
\\alpha
',
318 | 'should exclude spacing after the closing fence'
319 | )
320 |
321 | t.deepEqual(
322 | unified()
323 | .use(parse, {position: false})
324 | .use(math)
325 | .parse('$$\n\\alpha\n$$\n```\nbravo\n```\n'),
326 | u('root', [
327 | u(
328 | 'math',
329 | {
330 | data: {
331 | hName: 'div',
332 | hProperties: {className: ['math', 'math-display']},
333 | hChildren: [u('text', '\\alpha')]
334 | }
335 | },
336 | '\\alpha'
337 | ),
338 | u('code', {lang: null, meta: null}, 'bravo')
339 | ]),
340 | 'should not affect the next block'
341 | )
342 |
343 | t.deepEqual(
344 | unified()
345 | .use(parse, {position: false})
346 | .use(math, {inlineMathDouble: true})
347 | .parse('$$\\alpha$$'),
348 | u('root', [
349 | u('paragraph', [
350 | u(
351 | 'inlineMath',
352 | {
353 | data: {
354 | hName: 'span',
355 | hProperties: {className: ['math', 'math-inline', 'math-display']},
356 | hChildren: [u('text', '\\alpha')]
357 | }
358 | },
359 | '\\alpha'
360 | )
361 | ])
362 | ]),
363 | 'should add a `math-display` class to inline math with double dollars if `inlineMathDouble: true`'
364 | )
365 |
366 | t.deepEqual(
367 | unified()
368 | .use(stringify)
369 | .use(math)
370 | .stringify(
371 | u('root', [
372 | u('paragraph', [u('text', 'Math '), u('inlineMath', '\\alpha')]),
373 | u('math', '\\beta+\\gamma')
374 | ])
375 | )
376 | .toString(),
377 | 'Math $\\alpha$\n\n$$\n\\beta+\\gamma\n$$\n',
378 | 'should stringify a tree'
379 | )
380 |
381 | t.deepEqual(
382 | unified()
383 | .use(parse, {position: false})
384 | .use(stringify)
385 | .use(math)
386 | .processSync('$$\\alpha$$')
387 | .toString(),
388 | '$\\alpha$\n',
389 | 'should stringify inline math with double dollars using one dollar by default'
390 | )
391 |
392 | t.deepEqual(
393 | unified()
394 | .use(parse, {position: false})
395 | .use(stringify)
396 | .use(math, {inlineMathDouble: true})
397 | .processSync('$$\\alpha$$')
398 | .toString(),
399 | '$$\\alpha$$\n',
400 | 'should stringify inline math with double dollars using one dollar if `inlineMathDouble: true`'
401 | )
402 |
403 | t.deepEqual(
404 | String(toHtml.processSync('$1+1 = 2$')),
405 | '
1+1 = 2
',
406 | 'markdown-it-katex#01'
407 | )
408 | t.deepEqual(
409 | String(toHtml.processSync('$$1+1 = 2$$')),
410 | '
1+1 = 2
',
411 | 'markdown-it-katex#02'
412 | )
413 | t.deepEqual(
414 | String(toHtml.processSync('foo$1+1 = 2$bar')),
415 | '
foo1+1 = 2 bar
',
416 | 'markdown-it-katex#03: no whitespace before and after is fine'
417 | )
418 | t.deepEqual(
419 | String(toHtml.processSync('foo$-1+1 = 2$bar')),
420 | '
foo-1+1 = 2 bar
',
421 | 'markdown-it-katex#04: even when it starts with a negative sign'
422 | )
423 | t.deepEqual(
424 | String(toHtml.processSync('aaa $$ bbb')),
425 | '
aaa $$ bbb
',
426 | 'markdown-it-katex#05: shouldn’t render empty content'
427 | )
428 | t.deepEqual(
429 | String(toHtml.processSync('aaa $5.99 bbb')),
430 | '
aaa $5.99 bbb
',
431 | 'markdown-it-katex#06: should require a closing delimiter'
432 | )
433 | t.deepEqual(
434 | String(toHtml.processSync('foo $1+1\n\n= 2$ bar')),
435 | '
foo $1+1
\n
= 2$ bar
',
436 | 'markdown-it-katex#07: paragraph break in inline math is not allowed'
437 | )
438 | t.deepEqual(
439 | String(toHtml.processSync('foo $1 *i* 1$ bar')),
440 | '
foo 1 *i* 1 bar
',
441 | 'markdown-it-katex#08: inline math with apparent markup should not be processed'
442 | )
443 | t.deepEqual(
444 | String(toHtml.processSync(' $$\n 1+1 = 2\n $$')),
445 | '
1+1 = 2
',
446 | 'markdown-it-katex#09: block math can be indented up to 3 spaces'
447 | )
448 | t.deepEqual(
449 | String(toHtml.processSync(' $$\n 1+1 = 2\n $$')),
450 | '
$$\n1+1 = 2\n$$\n',
451 | 'markdown-it-katex#10: …but 4 means a code block'
452 | )
453 | t.deepEqual(
454 | String(toHtml.processSync('foo $1 + 1\n= 2$ bar')),
455 | '
foo 1 + 1\n= 2 bar
',
456 | 'markdown-it-katex#11: multiline inline math'
457 | )
458 | t.deepEqual(
459 | String(toHtml.processSync('$$\n\n 1\n+ 1\n\n= 2\n\n$$')),
460 | '
\n 1\n+ 1\n\n= 2\n\n
',
461 | 'markdown-it-katex#12: multiline display math'
462 | )
463 | t.deepEqual(
464 | String(toHtml.processSync('$n$-th order')),
465 | '
n -th order
',
466 | 'markdown-it-katex#13: text can immediately follow inline math'
467 | )
468 | t.deepEqual(
469 | String(toHtml.processSync('$$\n1+1 = 2')),
470 | '
1+1 = 2
',
471 | 'markdown-it-katex#14: display math self-closes at the end of document'
472 | )
473 | t.deepEqual(
474 | String(toHtml.processSync('* $1+1 = 2$\n* $$\n 1+1 = 2\n $$')),
475 | '
',
476 | 'markdown-it-katex#15: display and inline math can appear in lists'
477 | )
478 | t.deepEqual(
479 | String(toHtml.processSync('$$1+1 = 2$$')),
480 | '
1+1 = 2
',
481 | 'markdown-it-katex#16: display math can be written in one line'
482 | )
483 | // To do: this is broken.
484 | t.deepEqual(
485 | String(toHtml.processSync('$$[\n[1, 2]\n[3, 4]\n]$$')),
486 | '
[\n[1, 2]\n[3, 4]\n]
',
487 | 'markdown-it-katex#17: …or on multiple lines with expression starting and ending on delimited lines'
488 | )
489 | t.deepEqual(
490 | String(toHtml.processSync('Foo \\$1$ bar\n\\$\\$\n1\n\\$\\$')),
491 | '
Foo $1$ bar\n$$\n1\n$$
',
492 | 'markdown-it-katex#18: escaped delimiters should not render math'
493 | )
494 | t.deepEqual(
495 | String(
496 | toHtml.processSync('Thus, $20,000 and USD$30,000 won’t parse as math.')
497 | ),
498 | '
Thus, $20,000 and USD$30,000 won’t parse as math.
',
499 | 'markdown-it-katex#19: numbers can not follow closing inline math'
500 | )
501 | t.deepEqual(
502 | String(toHtml.processSync('It is 2$ for a can of soda, not 1$.')),
503 | '
It is 2$ for a can of soda, not 1$.
',
504 | 'markdown-it-katex#20: require non whitespace to right of opening inline math'
505 | )
506 | t.deepEqual(
507 | String(
508 | toHtml.processSync('I’ll give $20 today, if you give me more $ tomorrow.')
509 | ),
510 | '
I’ll give $20 today, if you give me more $ tomorrow.
',
511 | 'markdown-it-katex#21: require non whitespace to left of closing inline math'
512 | )
513 | // #22 “inline blockmath is not (currently) registered” <-- we do support it!
514 | t.deepEqual(
515 | String(toHtml.processSync('Money adds: $\\$X + \\$Y = \\$Z$.')),
516 | '
Money adds: \\$X + \\$Y = \\$Z .
',
517 | 'markdown-it-katex#23: escaped delimiters in math mode'
518 | )
519 | t.deepEqual(
520 | String(
521 | toHtml.processSync(
522 | 'Weird-o: $\\displaystyle{\\begin{pmatrix} \\$ & 1\\\\\\$ \\end{pmatrix}}$.'
523 | )
524 | ),
525 | '
Weird-o: \\displaystyle{\\begin{pmatrix} \\$ & 1\\\\\\$ \\end{pmatrix}} .
',
526 | 'markdown-it-katex#24: multiple escaped delimiters in math module'
527 | )
528 |
529 | t.end()
530 | })
531 |
--------------------------------------------------------------------------------