katex 0.10.1 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/CHANGELOG.md +141 -0
  2. package/LICENSE +1 -1
  3. package/README.md +6 -6
  4. package/cli.js +0 -0
  5. package/contrib/auto-render/auto-render.js +12 -3
  6. package/contrib/copy-tex/README.md +3 -5
  7. package/contrib/mathtex-script-type/README.md +12 -14
  8. package/contrib/mhchem/README.md +3 -1
  9. package/contrib/render-a11y-string/render-a11y-string.js +712 -0
  10. package/contrib/render-a11y-string/test/render-a11y-string-spec.js +526 -0
  11. package/dist/README.md +6 -6
  12. package/dist/contrib/auto-render.js +14 -3
  13. package/dist/contrib/auto-render.min.js +1 -1
  14. package/dist/contrib/auto-render.mjs +14 -3
  15. package/dist/contrib/mhchem.min.js +1 -1
  16. package/dist/contrib/render-a11y-string.js +870 -0
  17. package/dist/contrib/render-a11y-string.min.js +1 -0
  18. package/dist/contrib/render-a11y-string.mjs +753 -0
  19. package/dist/fonts/KaTeX_AMS-Regular.ttf +0 -0
  20. package/dist/fonts/KaTeX_AMS-Regular.woff +0 -0
  21. package/dist/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  22. package/dist/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  23. package/dist/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  24. package/dist/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  25. package/dist/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  26. package/dist/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  27. package/dist/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  28. package/dist/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  29. package/dist/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  30. package/dist/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  31. package/dist/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  32. package/dist/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  33. package/dist/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  34. package/dist/fonts/KaTeX_Main-Bold.ttf +0 -0
  35. package/dist/fonts/KaTeX_Main-Bold.woff +0 -0
  36. package/dist/fonts/KaTeX_Main-Bold.woff2 +0 -0
  37. package/dist/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  38. package/dist/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  39. package/dist/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  40. package/dist/fonts/KaTeX_Main-Italic.ttf +0 -0
  41. package/dist/fonts/KaTeX_Main-Italic.woff +0 -0
  42. package/dist/fonts/KaTeX_Main-Italic.woff2 +0 -0
  43. package/dist/fonts/KaTeX_Main-Regular.ttf +0 -0
  44. package/dist/fonts/KaTeX_Main-Regular.woff +0 -0
  45. package/dist/fonts/KaTeX_Main-Regular.woff2 +0 -0
  46. package/dist/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  47. package/dist/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  48. package/dist/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  49. package/dist/fonts/KaTeX_Math-Italic.ttf +0 -0
  50. package/dist/fonts/KaTeX_Math-Italic.woff +0 -0
  51. package/dist/fonts/KaTeX_Math-Italic.woff2 +0 -0
  52. package/dist/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  53. package/dist/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  54. package/dist/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  55. package/dist/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  56. package/dist/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  57. package/dist/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  58. package/dist/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  59. package/dist/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  60. package/dist/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  61. package/dist/fonts/KaTeX_Script-Regular.ttf +0 -0
  62. package/dist/fonts/KaTeX_Script-Regular.woff +0 -0
  63. package/dist/fonts/KaTeX_Script-Regular.woff2 +0 -0
  64. package/dist/fonts/KaTeX_Size1-Regular.ttf +0 -0
  65. package/dist/fonts/KaTeX_Size1-Regular.woff +0 -0
  66. package/dist/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  67. package/dist/fonts/KaTeX_Size2-Regular.ttf +0 -0
  68. package/dist/fonts/KaTeX_Size2-Regular.woff +0 -0
  69. package/dist/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  70. package/dist/fonts/KaTeX_Size3-Regular.ttf +0 -0
  71. package/dist/fonts/KaTeX_Size3-Regular.woff +0 -0
  72. package/dist/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  73. package/dist/fonts/KaTeX_Size4-Regular.ttf +0 -0
  74. package/dist/fonts/KaTeX_Size4-Regular.woff +0 -0
  75. package/dist/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  76. package/dist/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  77. package/dist/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  78. package/dist/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  79. package/dist/katex.css +34 -10
  80. package/dist/katex.js +2906 -2115
  81. package/dist/katex.min.css +1 -1
  82. package/dist/katex.min.js +1 -1
  83. package/dist/katex.mjs +2809 -2020
  84. package/package.json +12 -11
  85. package/src/Lexer.js +1 -0
  86. package/src/MacroExpander.js +39 -10
  87. package/src/Options.js +15 -75
  88. package/src/Parser.js +152 -115
  89. package/src/Settings.js +70 -7
  90. package/src/Token.js +2 -0
  91. package/src/buildCommon.js +24 -90
  92. package/src/buildHTML.js +31 -31
  93. package/src/buildMathML.js +52 -9
  94. package/src/buildTree.js +13 -6
  95. package/src/defineFunction.js +7 -22
  96. package/src/delimiter.js +66 -27
  97. package/src/domTree.js +71 -4
  98. package/src/environments/array.js +235 -25
  99. package/src/fontMetrics.js +11 -2
  100. package/src/functions/accent.js +9 -9
  101. package/src/functions/accentunder.js +2 -2
  102. package/src/functions/arrow.js +15 -5
  103. package/src/functions/color.js +9 -38
  104. package/src/functions/def.js +184 -0
  105. package/src/functions/delimsizing.js +32 -8
  106. package/src/functions/enclose.js +33 -6
  107. package/src/functions/font.js +4 -1
  108. package/src/functions/genfrac.js +39 -27
  109. package/src/functions/horizBrace.js +6 -7
  110. package/src/functions/href.js +16 -0
  111. package/src/functions/html.js +102 -0
  112. package/src/functions/includegraphics.js +153 -0
  113. package/src/functions/lap.js +4 -7
  114. package/src/functions/math.js +1 -5
  115. package/src/functions/mclass.js +41 -2
  116. package/src/functions/op.js +27 -111
  117. package/src/functions/operatorname.js +136 -92
  118. package/src/functions/ordgroup.js +1 -1
  119. package/src/functions/overline.js +3 -2
  120. package/src/functions/phantom.js +5 -2
  121. package/src/functions/raisebox.js +4 -16
  122. package/src/functions/rule.js +20 -9
  123. package/src/functions/styling.js +0 -9
  124. package/src/functions/supsub.js +27 -7
  125. package/src/functions/symbolsOp.js +4 -0
  126. package/src/functions/tag.js +20 -4
  127. package/src/functions/text.js +4 -3
  128. package/src/functions/underline.js +3 -2
  129. package/src/functions/utils/assembleSupSub.js +110 -0
  130. package/src/functions.js +3 -0
  131. package/src/katex.less +45 -9
  132. package/src/macros.js +259 -98
  133. package/src/mathMLTree.js +6 -4
  134. package/src/parseNode.js +37 -57
  135. package/src/stretchy.js +3 -1
  136. package/src/svgGeometry.js +136 -44
  137. package/src/symbols.js +52 -69
  138. package/src/tree.js +2 -2
  139. package/src/types.js +2 -1
  140. package/src/unicodeAccents.js +3 -1
  141. package/src/unicodeSymbols.js +30 -321
  142. package/src/utils.js +10 -0
  143. package/src/wide-character.js +2 -2
  144. package/src/unicodeMake.js +0 -70
@@ -0,0 +1,526 @@
1
+ /* eslint-disable max-len */
2
+ // @flow
3
+ import renderA11yString from "../render-a11y-string";
4
+
5
+ describe("renderA11yString", () => {
6
+ describe("basic expressions", () => {
7
+ test("simple addition", () => {
8
+ const result = renderA11yString("1 + 2");
9
+ expect(result).toMatchInlineSnapshot(`"1, plus, 2"`);
10
+ });
11
+ });
12
+
13
+ describe("accent", () => {
14
+ test("\\vec", () => {
15
+ const result = renderA11yString("\\vec{a}");
16
+ expect(result).toMatchInlineSnapshot(`"a, with, vector, on top"`);
17
+ });
18
+
19
+ test("\\acute{a}", () => {
20
+ const result = renderA11yString("\\acute{a}");
21
+ expect(result).toMatchInlineSnapshot(`"a, with, acute, on top"`);
22
+ });
23
+
24
+ test("\\hat{a}", () => {
25
+ const result = renderA11yString("\\hat{a}");
26
+ expect(result).toMatchInlineSnapshot(`"a, with, hat, on top"`);
27
+ });
28
+ });
29
+
30
+ describe("accentUnder", () => {
31
+ test("\\underleftarrow", () => {
32
+ const result = renderA11yString("\\underleftarrow{1+2}");
33
+ expect(result).toMatchInlineSnapshot(
34
+ `"1, plus, 2, with, left arrow, underneath"`,
35
+ );
36
+ });
37
+
38
+ test("\\underlinesegment", () => {
39
+ const result = renderA11yString("\\underlinesegment{1+2}");
40
+ expect(result).toMatchInlineSnapshot(
41
+ `"1, plus, 2, with, line segment, underneath"`,
42
+ );
43
+ });
44
+ });
45
+
46
+ describe("atom", () => {
47
+ test("punct", () => {
48
+ const result = renderA11yString("1, 2, 3");
49
+ expect(result).toMatchInlineSnapshot(`"1, comma, 2, comma, 3"`);
50
+ });
51
+ });
52
+
53
+ describe("color", () => {
54
+ test("\\color{red}", () => {
55
+ const result = renderA11yString("\\color{red}1+2");
56
+ expect(result).toMatchInlineSnapshot(
57
+ `"start color red, 1, plus, 2, end color red"`,
58
+ );
59
+ });
60
+
61
+ test("\\color{FF0000}", () => {
62
+ const result = renderA11yString("\\color{FF0000}1+2");
63
+ expect(result).toMatchInlineSnapshot(
64
+ `"start color #FF0000, 1, plus, 2, end color #FF0000"`,
65
+ );
66
+ });
67
+
68
+ // colorIsTextColor is an option added in KaTeX 0.9.0 for backward
69
+ // compatibility. It makes \color parse like \textcolor. We use it
70
+ // in the KA webapp, and need it here because the tests are written
71
+ // assuming it is set.
72
+ test("\\color{red} with {colorIsTextColor: true}", () => {
73
+ const result = renderA11yString("\\color{red}1+2", {
74
+ colorIsTextColor: true,
75
+ });
76
+ expect(result).toMatchInlineSnapshot(
77
+ `"start color red, 1, end color red, plus, 2"`,
78
+ );
79
+ });
80
+
81
+ test("\\textcolor{red}", () => {
82
+ const result = renderA11yString("\\textcolor{red}1+2");
83
+ expect(result).toMatchInlineSnapshot(
84
+ `"start color red, 1, end color red, plus, 2"`,
85
+ );
86
+ });
87
+ });
88
+
89
+ describe("delimiters", () => {
90
+ test("simple parens", () => {
91
+ const result = renderA11yString("(1 + 3)");
92
+ expect(result).toMatchInlineSnapshot(
93
+ `"left parenthesis, 1, plus, 3, right parenthesis"`,
94
+ );
95
+ });
96
+
97
+ test("simple brackets", () => {
98
+ const result = renderA11yString("[1 + 3]");
99
+ expect(result).toMatchInlineSnapshot(
100
+ `"open bracket, 1, plus, 3, close bracket"`,
101
+ );
102
+ });
103
+
104
+ test("nested parens", () => {
105
+ const result = renderA11yString("(a + (b + c))");
106
+ expect(result).toMatchInlineSnapshot(
107
+ `"left parenthesis, a, plus, left parenthesis, b, plus, c, right parenthesis, right parenthesis"`,
108
+ );
109
+ });
110
+
111
+ test("stretchy parens around fractions", () => {
112
+ const result = renderA11yString("\\left(\\frac{1}{x}\\right)");
113
+ expect(result).toMatchInlineSnapshot(
114
+ `"left parenthesis, start fraction, 1, divided by, x, end fraction, right parenthesis"`,
115
+ );
116
+ });
117
+ });
118
+
119
+ describe("delimsizing", () => {
120
+ test("\\bigl(1+2\\bigr)", () => {
121
+ const result = renderA11yString("\\bigl(1+2\\bigr)");
122
+ expect(result).toMatchInlineSnapshot(
123
+ `"left parenthesis, 1, plus, 2, right parenthesis"`,
124
+ );
125
+ });
126
+ });
127
+
128
+ describe("enclose", () => {
129
+ test("\\cancel", () => {
130
+ const result = renderA11yString("\\cancel{a}");
131
+ expect(result).toMatchInlineSnapshot(
132
+ `"start cancel, a, end cancel"`,
133
+ );
134
+ });
135
+
136
+ test("\\fbox", () => {
137
+ const result = renderA11yString("\\fbox{a}");
138
+ expect(result).toMatchInlineSnapshot(`"start box, a, end box"`);
139
+ });
140
+
141
+ test("\\boxed", () => {
142
+ const result = renderA11yString("\\boxed{a}");
143
+ expect(result).toMatchInlineSnapshot(`"start box, a, end box"`);
144
+ });
145
+
146
+ test("\\sout", () => {
147
+ const result = renderA11yString("\\sout{a}");
148
+ expect(result).toMatchInlineSnapshot(
149
+ `"start strikeout, a, end strikeout"`,
150
+ );
151
+ });
152
+ });
153
+
154
+ describe("exponents", () => {
155
+ test("simple exponent", () => {
156
+ const result = renderA11yString("e^x");
157
+ expect(result).toMatchInlineSnapshot(
158
+ `"e, start superscript, x, end superscript"`,
159
+ );
160
+ });
161
+
162
+ test("^{\\circ} => degrees", () => {
163
+ const result = renderA11yString("90^{\\circ}");
164
+ expect(result).toMatchInlineSnapshot(`"90, degrees"`);
165
+ });
166
+
167
+ test("^{\\degree} => degrees", () => {
168
+ const result = renderA11yString("90^{\\degree}");
169
+ expect(result).toMatchInlineSnapshot(`"90, degrees"`);
170
+ });
171
+
172
+ test("^{\\prime} => prime", () => {
173
+ const result = renderA11yString("f^{\\prime}");
174
+ expect(result).toMatchInlineSnapshot(`"f, prime"`);
175
+ });
176
+
177
+ test("^2 => squared", () => {
178
+ const result = renderA11yString("x^2");
179
+ expect(result).toMatchInlineSnapshot(`"x, squared"`);
180
+ });
181
+
182
+ test("^3 => cubed", () => {
183
+ const result = renderA11yString("x^3");
184
+ expect(result).toMatchInlineSnapshot(`"x, cubed"`);
185
+ });
186
+
187
+ test("log_2", () => {
188
+ const result = renderA11yString("\\log_2{x+1}");
189
+ expect(result).toMatchInlineSnapshot(
190
+ `"log, start base, 2, end base, x, plus, 1"`,
191
+ );
192
+ });
193
+
194
+ test("a_{n+1}", () => {
195
+ const result = renderA11yString("a_{n+1}");
196
+ expect(result).toMatchInlineSnapshot(
197
+ `"a, start subscript, n, plus, 1, end subscript"`,
198
+ );
199
+ });
200
+ });
201
+
202
+ describe("genfrac", () => {
203
+ test("simple fractions", () => {
204
+ const result = renderA11yString("\\frac{2}{3}");
205
+ expect(result).toMatchInlineSnapshot(
206
+ `"start fraction, 2, divided by, 3, end fraction"`,
207
+ );
208
+ });
209
+
210
+ test("nested fractions", () => {
211
+ const result = renderA11yString("\\frac{1}{1+\\frac{1}{x}}");
212
+ // TODO: this result is ambiguous, we need to fix this
213
+ expect(result).toMatchInlineSnapshot(
214
+ `"start fraction, 1, divided by, 1, plus, start fraction, 1, divided by, x, end fraction, end fraction"`,
215
+ );
216
+ });
217
+
218
+ test("binomials", () => {
219
+ const result = renderA11yString("\\binom{n}{k}");
220
+ // TODO: drop the parenthesis as they're not normally read
221
+ expect(result).toMatchInlineSnapshot(
222
+ `"start binomial, left parenthesis, n, over, k, right parenthesis, end binomial"`,
223
+ );
224
+ });
225
+ });
226
+
227
+ describe("horizBrace", () => {
228
+ test("\\overbrace", () => {
229
+ const result = renderA11yString("\\overbrace{1+2}");
230
+ expect(result).toMatchInlineSnapshot(
231
+ `"start overbrace, 1, plus, 2, end overbrace"`,
232
+ );
233
+ });
234
+
235
+ test("\\underbrace", () => {
236
+ const result = renderA11yString("\\underbrace{1+2}");
237
+ expect(result).toMatchInlineSnapshot(
238
+ `"start underbrace, 1, plus, 2, end underbrace"`,
239
+ );
240
+ });
241
+ });
242
+
243
+ describe("infix", () => {
244
+ test("\\over", () => {
245
+ const result = renderA11yString("a \\over b");
246
+ expect(result).toMatchInlineSnapshot(
247
+ `"start fraction, a, divided by, b, end fraction"`,
248
+ );
249
+ });
250
+
251
+ test("\\choose", () => {
252
+ const result = renderA11yString("a \\choose b");
253
+ expect(result).toMatchInlineSnapshot(
254
+ `"start binomial, left parenthesis, a, over, b, right parenthesis, end binomial"`,
255
+ );
256
+ });
257
+
258
+ test("\\above", () => {
259
+ const result = renderA11yString("a \\above{2pt} b");
260
+ expect(result).toMatchInlineSnapshot(
261
+ `"start fraction, a, divided by, b, end fraction"`,
262
+ );
263
+ });
264
+ });
265
+
266
+ describe("inner", () => {
267
+ test("\\ldots", () => {
268
+ const result = renderA11yString("\\ldots");
269
+ expect(result).toMatchInlineSnapshot(`"dots"`);
270
+ });
271
+ });
272
+
273
+ describe("lap", () => {
274
+ test("\\llap", () => {
275
+ const result = renderA11yString("a\\llap{b}");
276
+ expect(result).toMatchInlineSnapshot(
277
+ `"a, start text, b, end text"`,
278
+ );
279
+ });
280
+
281
+ test("\\rlap", () => {
282
+ const result = renderA11yString("a\\rlap{b}");
283
+ expect(result).toMatchInlineSnapshot(
284
+ `"a, start text, b, end text"`,
285
+ );
286
+ });
287
+ });
288
+
289
+ describe("middle", () => {
290
+ test("\\middle", () => {
291
+ const result = renderA11yString("\\left(a\\middle|b\\right)");
292
+ expect(result).toMatchInlineSnapshot(
293
+ `"left parenthesis, a, vertical bar, b, right parenthesis"`,
294
+ );
295
+ });
296
+ });
297
+
298
+ describe("mod", () => {
299
+ test("\\mod", () => {
300
+ const result = renderA11yString("\\mod{23}");
301
+ // TODO: drop the "space"
302
+ // TODO: collate m, o, d... we should fix this inside of KaTeX since
303
+ // this affects the HTML and MathML output as well
304
+ expect(result).toMatchInlineSnapshot(`"space, m, o, d, 23"`);
305
+ });
306
+ });
307
+
308
+ describe("op", () => {
309
+ test("\\lim", () => {
310
+ const result = renderA11yString("\\lim{x+1}");
311
+ // TODO: add begin/end to track argument of operators
312
+ expect(result).toMatchInlineSnapshot(`"limit, x, plus, 1"`);
313
+ });
314
+
315
+ test("\\sin 2\\pi", () => {
316
+ const result = renderA11yString("\\sin{2\\pi}");
317
+ // TODO: add begin/end to track argument of operators
318
+ expect(result).toMatchInlineSnapshot(`"sine, 2, pi"`);
319
+ });
320
+
321
+ test("\\sum_{i=0}", () => {
322
+ const result = renderA11yString("\\sum_{i=0}");
323
+ expect(result).toMatchInlineSnapshot(
324
+ `"sum, start subscript, i, equals, 0, end subscript"`,
325
+ );
326
+ });
327
+
328
+ test("\u2211_{i=0}", () => {
329
+ const result = renderA11yString("\u2211_{i=0}");
330
+ expect(result).toMatchInlineSnapshot(
331
+ `"sum, start subscript, i, equals, 0, end subscript"`,
332
+ );
333
+ });
334
+ });
335
+
336
+ describe("operatorname", () => {
337
+ test("\\limsup", () => {
338
+ const result = renderA11yString("\\limsup");
339
+ // TODO: collate strings so that this is "lim, sup"
340
+ // NOTE: this also affect HTML and MathML output
341
+ expect(result).toMatchInlineSnapshot(`"l, i, m, s, u, p"`);
342
+ });
343
+
344
+ test("\\liminf", () => {
345
+ const result = renderA11yString("\\liminf");
346
+ expect(result).toMatchInlineSnapshot(`"l, i, m, i, n, f"`);
347
+ });
348
+
349
+ test("\\argmin", () => {
350
+ const result = renderA11yString("\\argmin");
351
+ expect(result).toMatchInlineSnapshot(`"a, r, g, m, i, n"`);
352
+ });
353
+ });
354
+
355
+ describe("overline", () => {
356
+ test("\\overline", () => {
357
+ const result = renderA11yString("\\overline{1+2}");
358
+ expect(result).toMatchInlineSnapshot(
359
+ `"start overline, 1, plus, 2, end overline"`,
360
+ );
361
+ });
362
+ });
363
+
364
+ describe("phantom", () => {
365
+ test("\\phantom", () => {
366
+ const result = renderA11yString("1+\\phantom{2}");
367
+ expect(result).toMatchInlineSnapshot(`"1, plus, empty space"`);
368
+ });
369
+ });
370
+
371
+ describe("raisebox", () => {
372
+ test("\\raisebox", () => {
373
+ const result = renderA11yString("x+\\raisebox{1em}{y}");
374
+ expect(result).toMatchInlineSnapshot(`"x, plus, y"`);
375
+ });
376
+ });
377
+
378
+ describe("relations", () => {
379
+ test("1 \\neq 2", () => {
380
+ const result = renderA11yString("1 \\neq 2");
381
+ expect(result).toMatchInlineSnapshot(`"1, does not equal, 2"`);
382
+ });
383
+
384
+ test("1 \\ne 2", () => {
385
+ const result = renderA11yString("1 \\ne 2");
386
+ expect(result).toMatchInlineSnapshot(`"1, does not equal, 2"`);
387
+ });
388
+
389
+ test("1 \\geq 2", () => {
390
+ const result = renderA11yString("1 \\geq 2");
391
+ expect(result).toMatchInlineSnapshot(
392
+ `"1, is greater than or equal to, 2"`,
393
+ );
394
+ });
395
+
396
+ test("1 \\ge 2", () => {
397
+ const result = renderA11yString("1 \\ge 2");
398
+ expect(result).toMatchInlineSnapshot(
399
+ `"1, is greater than or equal to, 2"`,
400
+ );
401
+ });
402
+
403
+ test("1 \\leq 2", () => {
404
+ const result = renderA11yString("1 \\leq 3");
405
+ expect(result).toMatchInlineSnapshot(
406
+ `"1, is less than or equal to, 3"`,
407
+ );
408
+ });
409
+
410
+ test("1 \\le 2", () => {
411
+ const result = renderA11yString("1 \\le 3");
412
+ expect(result).toMatchInlineSnapshot(
413
+ `"1, is less than or equal to, 3"`,
414
+ );
415
+ });
416
+ });
417
+
418
+ describe("rule", () => {
419
+ test("\\rule", () => {
420
+ const result = renderA11yString("\\rule{1em}{1em}");
421
+ expect(result).toMatchInlineSnapshot(`"rectangle"`);
422
+ });
423
+ });
424
+
425
+ describe("smash", () => {
426
+ test("1 + \\smash{2}", () => {
427
+ const result = renderA11yString("1 + \\smash{2}");
428
+ expect(result).toMatchInlineSnapshot(`"1, plus, 2"`);
429
+ });
430
+ });
431
+
432
+ describe("sqrt", () => {
433
+ test("square root", () => {
434
+ const result = renderA11yString("\\sqrt{x + 1}");
435
+ expect(result).toMatchInlineSnapshot(
436
+ `"square root of, x, plus, 1, end square root"`,
437
+ );
438
+ });
439
+
440
+ test("nest square root", () => {
441
+ const result = renderA11yString("\\sqrt{x + \\sqrt{y}}");
442
+ // TODO: this sounds ambiguous as well... we should probably say "start square root"
443
+ expect(result).toMatchInlineSnapshot(
444
+ `"square root of, x, plus, square root of, y, end square root, end square root"`,
445
+ );
446
+ });
447
+
448
+ test("cube root", () => {
449
+ const result = renderA11yString("\\sqrt[3]{x + 1}");
450
+ expect(result).toMatchInlineSnapshot(
451
+ `"cube root of, x, plus, 1, end cube root"`,
452
+ );
453
+ });
454
+
455
+ test("nth root", () => {
456
+ const result = renderA11yString("\\sqrt[n]{x + 1}");
457
+ expect(result).toMatchInlineSnapshot(
458
+ `"root, start index, n, end index"`,
459
+ );
460
+ });
461
+ });
462
+
463
+ describe("sizing", () => {
464
+ test("\\Huge is ignored", () => {
465
+ const result = renderA11yString("\\Huge{a+b}");
466
+ expect(result).toMatchInlineSnapshot(`"a, plus, b"`);
467
+ });
468
+
469
+ test("\\small is ignored", () => {
470
+ const result = renderA11yString("\\small{a+b}");
471
+ expect(result).toMatchInlineSnapshot(`"a, plus, b"`);
472
+ });
473
+
474
+ // We don't need to test all sizing commands since all style
475
+ // nodes are treated in the same way.
476
+ });
477
+
478
+ describe("styling", () => {
479
+ test("\\displaystyle is ignored", () => {
480
+ const result = renderA11yString("\\displaystyle{a+b}");
481
+ expect(result).toMatchInlineSnapshot(`"a, plus, b"`);
482
+ });
483
+
484
+ test("\\textstyle is ignored", () => {
485
+ const result = renderA11yString("\\textstyle{a+b}");
486
+ expect(result).toMatchInlineSnapshot(`"a, plus, b"`);
487
+ });
488
+
489
+ // We don't need to test all styling commands since all style
490
+ // nodes are treated in the same way.
491
+ });
492
+
493
+ describe("text", () => {
494
+ test("\\text", () => {
495
+ const result = renderA11yString("\\text{hello}");
496
+ expect(result).toMatchInlineSnapshot(
497
+ `"start text, h, e, l, l, o, end text"`,
498
+ );
499
+ });
500
+
501
+ test("\\textbf", () => {
502
+ const result = renderA11yString("\\textbf{hello}");
503
+ expect(result).toMatchInlineSnapshot(
504
+ `"start bold text, h, e, l, l, o, end bold text"`,
505
+ );
506
+ });
507
+ });
508
+
509
+ describe("underline", () => {
510
+ test("\\underline", () => {
511
+ const result = renderA11yString("\\underline{1+2}");
512
+ expect(result).toMatchInlineSnapshot(
513
+ `"start underline, 1, plus, 2, end underline"`,
514
+ );
515
+ });
516
+ });
517
+
518
+ describe("verb", () => {
519
+ test("\\verb", () => {
520
+ const result = renderA11yString("\\verb|hello|");
521
+ expect(result).toMatchInlineSnapshot(
522
+ `"start verbatim, hello, end verbatim"`,
523
+ );
524
+ });
525
+ });
526
+ });
package/dist/README.md CHANGED
@@ -3,9 +3,9 @@
3
3
  [![CircleCI](https://circleci.com/gh/KaTeX/KaTeX.svg?style=shield)](https://circleci.com/gh/KaTeX/KaTeX)
4
4
  [![codecov](https://codecov.io/gh/KaTeX/KaTeX/branch/master/graph/badge.svg)](https://codecov.io/gh/KaTeX/KaTeX)
5
5
  [![Join the chat at https://gitter.im/KaTeX/KaTeX](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/KaTeX/KaTeX?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6
- [![Greenkeeper badge](https://badges.greenkeeper.io/KaTeX/KaTeX.svg)](https://greenkeeper.io/)
6
+ [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=KaTeX/KaTeX)](https://dependabot.com)
7
7
  [![jsDelivr](https://data.jsdelivr.com/v1/package/npm/katex/badge?style=rounded)](https://www.jsdelivr.com/package/npm/katex)
8
- ![](https://img.badgesize.io/KaTeX/KaTeX/v0.10.1/dist/katex.min.js?compression=gzip)
8
+ ![](https://img.badgesize.io/KaTeX/KaTeX/v0.12.0/dist/katex.min.js?compression=gzip)
9
9
 
10
10
  KaTeX is a fast, easy-to-use JavaScript library for TeX math rendering on the web.
11
11
 
@@ -14,7 +14,7 @@ KaTeX is a fast, easy-to-use JavaScript library for TeX math rendering on the we
14
14
  * **Self contained:** KaTeX has no dependencies and can easily be bundled with your website resources.
15
15
  * **Server side rendering:** KaTeX produces the same output regardless of browser or environment, so you can pre-render expressions using Node.js and send them as plain HTML.
16
16
 
17
- KaTeX is compatible with all major browsers, including Chrome, Safari, Firefox, Opera, Edge, and IE 9–11.
17
+ KaTeX is compatible with all major browsers, including Chrome, Safari, Firefox, Opera, Edge, and IE 11.
18
18
 
19
19
  KaTeX supports much (but not all) of LaTeX and many LaTeX packages. See the [list of supported functions](https://katex.org/docs/supported.html).
20
20
 
@@ -29,13 +29,13 @@ Try out KaTeX [on the demo page](https://katex.org/#demo)!
29
29
  <!-- KaTeX requires the use of the HTML5 doctype. Without it, KaTeX may not render properly -->
30
30
  <html>
31
31
  <head>
32
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.10.1/dist/katex.min.css" integrity="sha384-dbVIfZGuN1Yq7/1Ocstc1lUEm+AT+/rCkibIcC/OmWo5f0EA48Vf8CytHzGrSwbQ" crossorigin="anonymous">
32
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css" integrity="sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X" crossorigin="anonymous">
33
33
 
34
34
  <!-- The loading of KaTeX is deferred to speed up page rendering -->
35
- <script defer src="https://cdn.jsdelivr.net/npm/katex@0.10.1/dist/katex.min.js" integrity="sha384-2BKqo+exmr9su6dir+qCw08N2ZKRucY4PrGQPPWU1A7FtlCGjmEGFqXCv5nyM5Ij" crossorigin="anonymous"></script>
35
+ <script defer src="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.js" integrity="sha384-g7c+Jr9ZivxKLnZTDUhnkOnsh30B4H0rpLUpJ4jAIKs4fnJI+sEnkvrMWph2EDg4" crossorigin="anonymous"></script>
36
36
 
37
37
  <!-- To automatically render math in text elements, include the auto-render extension: -->
38
- <script defer src="https://cdn.jsdelivr.net/npm/katex@0.10.1/dist/contrib/auto-render.min.js" integrity="sha384-kWPLUVMOks5AQFrykwIup5lo0m3iMkkHrD0uJ4H5cjeGihAutqP0yW0J6dpFiVkI" crossorigin="anonymous"
38
+ <script defer src="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/contrib/auto-render.min.js" integrity="sha384-mll67QQFJfxn0IYznZYonOWZ644AWYC+Pt2cHqMaRhXVrursRwvLnLaebdGIlYNa" crossorigin="anonymous"
39
39
  onload="renderMathInElement(document.body);"></script>
40
40
  </head>
41
41
  ...
@@ -229,6 +229,14 @@ var auto_render_splitWithDelimiters = function splitWithDelimiters(text, delimit
229
229
 
230
230
  var auto_render_renderMathInText = function renderMathInText(text, optionsCopy) {
231
231
  var data = auto_render_splitWithDelimiters(text, optionsCopy.delimiters);
232
+
233
+ if (data.length === 1 && data[0].type === 'text') {
234
+ // There is no formula in the text.
235
+ // Let's return null which means there is no need to replace
236
+ // the current text node with a new one.
237
+ return null;
238
+ }
239
+
232
240
  var fragment = document.createDocumentFragment();
233
241
 
234
242
  for (var i = 0; i < data.length; i++) {
@@ -271,8 +279,11 @@ var renderElem = function renderElem(elem, optionsCopy) {
271
279
  if (childNode.nodeType === 3) {
272
280
  // Text node
273
281
  var frag = auto_render_renderMathInText(childNode.textContent, optionsCopy);
274
- i += frag.childNodes.length - 1;
275
- elem.replaceChild(frag, childNode);
282
+
283
+ if (frag) {
284
+ i += frag.childNodes.length - 1;
285
+ elem.replaceChild(frag, childNode);
286
+ }
276
287
  } else if (childNode.nodeType === 1) {
277
288
  (function () {
278
289
  // Element node
@@ -323,7 +334,7 @@ var renderMathInElement = function renderMathInElement(elem, options) {
323
334
  right: "\\]",
324
335
  display: true
325
336
  }];
326
- optionsCopy.ignoredTags = optionsCopy.ignoredTags || ["script", "noscript", "style", "textarea", "pre", "code"];
337
+ optionsCopy.ignoredTags = optionsCopy.ignoredTags || ["script", "noscript", "style", "textarea", "pre", "code", "option"];
327
338
  optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || [];
328
339
  optionsCopy.errorCallback = optionsCopy.errorCallback || console.error; // Enable sharing of global macros defined via `\gdef` between different
329
340
  // math elements within a single call to `renderMathInElement`.
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,function(e){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=1)}([function(t,r){t.exports=e},function(e,t,r){"use strict";r.r(t);var n=r(0),o=r.n(n),a=function(e,t,r){for(var n=r,o=0,a=e.length;n<t.length;){var i=t[n];if(o<=0&&t.slice(n,n+a)===e)return n;"\\"===i?n++:"{"===i?o++:"}"===i&&o--,n++}return-1},i=function(e,t,r,n){for(var o=[],i=0;i<e.length;i++)if("text"===e[i].type){var l=e[i].data,d=!0,s=0,f=void 0;for(-1!==(f=l.indexOf(t))&&(s=f,o.push({type:"text",data:l.slice(0,s)}),d=!1);;){if(d){if(-1===(f=l.indexOf(t,s)))break;o.push({type:"text",data:l.slice(s,f)}),s=f}else{if(-1===(f=a(r,l,s+t.length)))break;o.push({type:"math",data:l.slice(s+t.length,f),rawData:l.slice(s,f+r.length),display:n}),s=f+r.length}d=!d}o.push({type:"text",data:l.slice(s)})}else o.push(e[i]);return o},l=function(e,t){for(var r=function(e,t){for(var r=[{type:"text",data:e}],n=0;n<t.length;n++){var o=t[n];r=i(r,o.left,o.right,o.display||!1)}return r}(e,t.delimiters),n=document.createDocumentFragment(),a=0;a<r.length;a++)if("text"===r[a].type)n.appendChild(document.createTextNode(r[a].data));else{var l=document.createElement("span"),d=r[a].data;t.displayMode=r[a].display;try{t.preProcess&&(d=t.preProcess(d)),o.a.render(d,l,t)}catch(e){if(!(e instanceof o.a.ParseError))throw e;t.errorCallback("KaTeX auto-render: Failed to parse `"+r[a].data+"` with ",e),n.appendChild(document.createTextNode(r[a].rawData));continue}n.appendChild(l)}return n};t.default=function(e,t){if(!e)throw new Error("No element provided to render");var r={};for(var n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);r.delimiters=r.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\[",right:"\\]",display:!0}],r.ignoredTags=r.ignoredTags||["script","noscript","style","textarea","pre","code"],r.ignoredClasses=r.ignoredClasses||[],r.errorCallback=r.errorCallback||console.error,r.macros=r.macros||{},function e(t,r){for(var n=0;n<t.childNodes.length;n++){var o=t.childNodes[n];if(3===o.nodeType){var a=l(o.textContent,r);n+=a.childNodes.length-1,t.replaceChild(a,o)}else 1===o.nodeType&&function(){var t=" "+o.className+" ";-1===r.ignoredTags.indexOf(o.nodeName.toLowerCase())&&r.ignoredClasses.every(function(e){return-1===t.indexOf(" "+e+" ")})&&e(o,r)}()}}(e,r)}}]).default});
1
+ !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,function(e){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=1)}([function(t,r){t.exports=e},function(e,t,r){"use strict";r.r(t);var n=r(0),o=r.n(n),a=function(e,t,r){for(var n=r,o=0,a=e.length;n<t.length;){var i=t[n];if(o<=0&&t.slice(n,n+a)===e)return n;"\\"===i?n++:"{"===i?o++:"}"===i&&o--,n++}return-1},i=function(e,t,r,n){for(var o=[],i=0;i<e.length;i++)if("text"===e[i].type){var l=e[i].data,d=!0,s=0,f=void 0;for(-1!==(f=l.indexOf(t))&&(s=f,o.push({type:"text",data:l.slice(0,s)}),d=!1);;){if(d){if(-1===(f=l.indexOf(t,s)))break;o.push({type:"text",data:l.slice(s,f)}),s=f}else{if(-1===(f=a(r,l,s+t.length)))break;o.push({type:"math",data:l.slice(s+t.length,f),rawData:l.slice(s,f+r.length),display:n}),s=f+r.length}d=!d}o.push({type:"text",data:l.slice(s)})}else o.push(e[i]);return o},l=function(e,t){var r=function(e,t){for(var r=[{type:"text",data:e}],n=0;n<t.length;n++){var o=t[n];r=i(r,o.left,o.right,o.display||!1)}return r}(e,t.delimiters);if(1===r.length&&"text"===r[0].type)return null;for(var n=document.createDocumentFragment(),a=0;a<r.length;a++)if("text"===r[a].type)n.appendChild(document.createTextNode(r[a].data));else{var l=document.createElement("span"),d=r[a].data;t.displayMode=r[a].display;try{t.preProcess&&(d=t.preProcess(d)),o.a.render(d,l,t)}catch(e){if(!(e instanceof o.a.ParseError))throw e;t.errorCallback("KaTeX auto-render: Failed to parse `"+r[a].data+"` with ",e),n.appendChild(document.createTextNode(r[a].rawData));continue}n.appendChild(l)}return n};t.default=function(e,t){if(!e)throw new Error("No element provided to render");var r={};for(var n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);r.delimiters=r.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\[",right:"\\]",display:!0}],r.ignoredTags=r.ignoredTags||["script","noscript","style","textarea","pre","code","option"],r.ignoredClasses=r.ignoredClasses||[],r.errorCallback=r.errorCallback||console.error,r.macros=r.macros||{},function e(t,r){for(var n=0;n<t.childNodes.length;n++){var o=t.childNodes[n];if(3===o.nodeType){var a=l(o.textContent,r);a&&(n+=a.childNodes.length-1,t.replaceChild(a,o))}else 1===o.nodeType&&function(){var t=" "+o.className+" ";-1===r.ignoredTags.indexOf(o.nodeName.toLowerCase())&&r.ignoredClasses.every(function(e){return-1===t.indexOf(" "+e+" ")})&&e(o,r)}()}}(e,r)}}]).default});
@@ -113,6 +113,14 @@ const splitWithDelimiters = function splitWithDelimiters(text, delimiters) {
113
113
 
114
114
  const renderMathInText = function renderMathInText(text, optionsCopy) {
115
115
  const data = splitWithDelimiters(text, optionsCopy.delimiters);
116
+
117
+ if (data.length === 1 && data[0].type === 'text') {
118
+ // There is no formula in the text.
119
+ // Let's return null which means there is no need to replace
120
+ // the current text node with a new one.
121
+ return null;
122
+ }
123
+
116
124
  const fragment = document.createDocumentFragment();
117
125
 
118
126
  for (let i = 0; i < data.length; i++) {
@@ -155,8 +163,11 @@ const renderElem = function renderElem(elem, optionsCopy) {
155
163
  if (childNode.nodeType === 3) {
156
164
  // Text node
157
165
  const frag = renderMathInText(childNode.textContent, optionsCopy);
158
- i += frag.childNodes.length - 1;
159
- elem.replaceChild(frag, childNode);
166
+
167
+ if (frag) {
168
+ i += frag.childNodes.length - 1;
169
+ elem.replaceChild(frag, childNode);
170
+ }
160
171
  } else if (childNode.nodeType === 1) {
161
172
  // Element node
162
173
  const className = ' ' + childNode.className + ' ';
@@ -203,7 +214,7 @@ const renderMathInElement = function renderMathInElement(elem, options) {
203
214
  right: "\\]",
204
215
  display: true
205
216
  }];
206
- optionsCopy.ignoredTags = optionsCopy.ignoredTags || ["script", "noscript", "style", "textarea", "pre", "code"];
217
+ optionsCopy.ignoredTags = optionsCopy.ignoredTags || ["script", "noscript", "style", "textarea", "pre", "code", "option"];
207
218
  optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || [];
208
219
  optionsCopy.errorCallback = optionsCopy.errorCallback || console.error; // Enable sharing of global macros defined via `\gdef` between different
209
220
  // math elements within a single call to `renderMathInElement`.