katex 0.12.0 → 0.13.3

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 (167) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/LICENSE +1 -1
  3. package/README.md +8 -7
  4. package/contrib/auto-render/auto-render.js +12 -19
  5. package/contrib/auto-render/index.html +9 -3
  6. package/contrib/auto-render/splitAtDelimiters.js +44 -61
  7. package/contrib/auto-render/test/auto-render-spec.js +88 -52
  8. package/contrib/copy-tex/README.md +5 -9
  9. package/contrib/copy-tex/copy-tex.css +0 -3
  10. package/contrib/mathtex-script-type/README.md +5 -5
  11. package/contrib/mhchem/README.md +4 -2
  12. package/contrib/render-a11y-string/render-a11y-string.js +31 -2
  13. package/contrib/render-a11y-string/test/render-a11y-string-spec.js +23 -0
  14. package/dist/README.md +8 -7
  15. package/dist/contrib/auto-render.js +148 -171
  16. package/dist/contrib/auto-render.min.js +1 -1
  17. package/dist/contrib/auto-render.mjs +91 -95
  18. package/dist/contrib/copy-tex.css +3 -3
  19. package/dist/contrib/copy-tex.js +11 -108
  20. package/dist/contrib/copy-tex.min.css +1 -1
  21. package/dist/contrib/copy-tex.min.js +1 -1
  22. package/dist/contrib/copy-tex.mjs +21 -20
  23. package/dist/contrib/mathtex-script-type.js +66 -91
  24. package/dist/contrib/mathtex-script-type.min.js +1 -1
  25. package/dist/contrib/mathtex-script-type.mjs +3 -3
  26. package/dist/contrib/mhchem.js +70 -95
  27. package/dist/contrib/mhchem.min.js +1 -1
  28. package/dist/contrib/mhchem.mjs +2 -2
  29. package/dist/contrib/render-a11y-string.js +97 -92
  30. package/dist/contrib/render-a11y-string.min.js +1 -1
  31. package/dist/contrib/render-a11y-string.mjs +86 -45
  32. package/dist/fonts/KaTeX_AMS-Regular.ttf +0 -0
  33. package/dist/fonts/KaTeX_AMS-Regular.woff +0 -0
  34. package/dist/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  35. package/dist/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  36. package/dist/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  37. package/dist/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  38. package/dist/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  39. package/dist/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  40. package/dist/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  41. package/dist/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  42. package/dist/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  43. package/dist/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  44. package/dist/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  45. package/dist/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  46. package/dist/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  47. package/dist/fonts/KaTeX_Main-Bold.ttf +0 -0
  48. package/dist/fonts/KaTeX_Main-Bold.woff +0 -0
  49. package/dist/fonts/KaTeX_Main-Bold.woff2 +0 -0
  50. package/dist/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  51. package/dist/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  52. package/dist/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  53. package/dist/fonts/KaTeX_Main-Italic.ttf +0 -0
  54. package/dist/fonts/KaTeX_Main-Italic.woff +0 -0
  55. package/dist/fonts/KaTeX_Main-Italic.woff2 +0 -0
  56. package/dist/fonts/KaTeX_Main-Regular.ttf +0 -0
  57. package/dist/fonts/KaTeX_Main-Regular.woff +0 -0
  58. package/dist/fonts/KaTeX_Main-Regular.woff2 +0 -0
  59. package/dist/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  60. package/dist/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  61. package/dist/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  62. package/dist/fonts/KaTeX_Math-Italic.ttf +0 -0
  63. package/dist/fonts/KaTeX_Math-Italic.woff +0 -0
  64. package/dist/fonts/KaTeX_Math-Italic.woff2 +0 -0
  65. package/dist/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  66. package/dist/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  67. package/dist/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  68. package/dist/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  69. package/dist/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  70. package/dist/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  71. package/dist/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  72. package/dist/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  73. package/dist/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  74. package/dist/fonts/KaTeX_Script-Regular.ttf +0 -0
  75. package/dist/fonts/KaTeX_Script-Regular.woff +0 -0
  76. package/dist/fonts/KaTeX_Script-Regular.woff2 +0 -0
  77. package/dist/fonts/KaTeX_Size1-Regular.ttf +0 -0
  78. package/dist/fonts/KaTeX_Size1-Regular.woff +0 -0
  79. package/dist/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  80. package/dist/fonts/KaTeX_Size2-Regular.ttf +0 -0
  81. package/dist/fonts/KaTeX_Size2-Regular.woff +0 -0
  82. package/dist/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  83. package/dist/fonts/KaTeX_Size3-Regular.ttf +0 -0
  84. package/dist/fonts/KaTeX_Size3-Regular.woff +0 -0
  85. package/dist/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  86. package/dist/fonts/KaTeX_Size4-Regular.ttf +0 -0
  87. package/dist/fonts/KaTeX_Size4-Regular.woff +0 -0
  88. package/dist/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  89. package/dist/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  90. package/dist/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  91. package/dist/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  92. package/dist/katex.css +66 -10
  93. package/dist/katex.js +2714 -1950
  94. package/dist/katex.min.css +1 -1
  95. package/dist/katex.min.js +1 -1
  96. package/dist/katex.mjs +3162 -2372
  97. package/katex.js +4 -3
  98. package/package.json +69 -59
  99. package/src/Lexer.js +4 -2
  100. package/src/MacroExpander.js +117 -37
  101. package/src/Options.js +2 -2
  102. package/src/ParseError.js +1 -1
  103. package/src/Parser.js +100 -159
  104. package/src/Settings.js +2 -2
  105. package/src/Style.js +4 -4
  106. package/src/Token.js +1 -1
  107. package/src/buildCommon.js +12 -5
  108. package/src/buildHTML.js +11 -0
  109. package/src/buildMathML.js +6 -0
  110. package/src/defineEnvironment.js +0 -3
  111. package/src/defineFunction.js +15 -22
  112. package/src/delimiter.js +61 -57
  113. package/src/domTree.js +1 -1
  114. package/src/environments/array.js +223 -35
  115. package/src/environments/cd.js +312 -0
  116. package/src/fontMetrics.js +1 -1
  117. package/src/fontMetricsData.js +2076 -0
  118. package/src/fonts/.gitignore +9 -0
  119. package/src/fonts/Makefile +139 -0
  120. package/src/fonts/default.cfg +20 -0
  121. package/src/fonts/generate_fonts.py +61 -0
  122. package/src/fonts/lib/Extra.otf +0 -0
  123. package/src/fonts/lib/Space.ttx +234 -0
  124. package/src/fonts/makeBlacker +49 -0
  125. package/src/fonts/makeFF +2003 -0
  126. package/src/fonts/xbbold.mf +182 -0
  127. package/src/fonts.less +64 -0
  128. package/src/functions/accent.js +3 -2
  129. package/src/functions/arrow.js +8 -2
  130. package/src/functions/color.js +4 -4
  131. package/src/functions/cr.js +7 -25
  132. package/src/functions/def.js +50 -24
  133. package/src/functions/delimsizing.js +8 -0
  134. package/src/functions/enclose.js +80 -12
  135. package/src/functions/environment.js +1 -1
  136. package/src/functions/font.js +3 -4
  137. package/src/functions/genfrac.js +36 -11
  138. package/src/functions/hbox.js +39 -0
  139. package/src/functions/kern.js +1 -0
  140. package/src/functions/mathchoice.js +1 -0
  141. package/src/functions/mclass.js +2 -1
  142. package/src/functions/op.js +3 -7
  143. package/src/functions/operatorname.js +1 -1
  144. package/src/functions/raisebox.js +0 -1
  145. package/src/functions/styling.js +1 -0
  146. package/src/functions/supsub.js +1 -3
  147. package/src/functions/symbolsOrd.js +0 -2
  148. package/src/functions/text.js +2 -3
  149. package/src/functions/vcenter.js +44 -0
  150. package/src/functions.js +3 -0
  151. package/src/katex.less +69 -16
  152. package/src/macros.js +42 -6
  153. package/src/mathMLTree.js +16 -1
  154. package/src/metrics/.gitignore +1 -0
  155. package/src/metrics/README.md +23 -0
  156. package/src/metrics/extract_tfms.py +114 -0
  157. package/src/metrics/extract_ttfs.py +119 -0
  158. package/src/metrics/format_json.py +28 -0
  159. package/src/metrics/mapping.pl +1224 -0
  160. package/src/metrics/parse_tfm.py +211 -0
  161. package/src/parseNode.js +29 -1
  162. package/src/parseTree.js +6 -0
  163. package/src/stretchy.js +12 -5
  164. package/src/svgGeometry.js +33 -4
  165. package/src/symbols.js +5 -3
  166. package/src/types.js +3 -2
  167. package/src/unicodeScripts.js +5 -0
package/CHANGELOG.md CHANGED
@@ -1,6 +1,118 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file. This CHANGELOG roughly follows the guidelines from [www.keepachangelog.com](https://keepachangelog.com/en/1.0.0/).
3
3
 
4
+ ## [0.13.3](https://github.com/KaTeX/KaTeX/compare/v0.13.2...v0.13.3) (2021-04-24)
5
+
6
+
7
+ ### Bug Fixes
8
+
9
+ * Respect catcode in macro expansion and set ~'s catcode correctly ([#2949](https://github.com/KaTeX/KaTeX/issues/2949)) ([01ae7f8](https://github.com/KaTeX/KaTeX/commit/01ae7f8eef09bcddc6e327c2cb5a3460800652d5)), closes [#2924](https://github.com/KaTeX/KaTeX/issues/2924)
10
+ * **array:** Keep single empty row in AMS environments ([#2947](https://github.com/KaTeX/KaTeX/issues/2947)) ([24332e0](https://github.com/KaTeX/KaTeX/commit/24332e053c0f33b37e6d30384b42232f321a6fc7)), closes [#2944](https://github.com/KaTeX/KaTeX/issues/2944)
11
+
12
+ ## [0.13.2](https://github.com/KaTeX/KaTeX/compare/v0.13.1...v0.13.2) (2021-04-06)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * update version and SRI in dist/README.md ([#2905](https://github.com/KaTeX/KaTeX/issues/2905)) ([319c52d](https://github.com/KaTeX/KaTeX/commit/319c52db6433f5fc5327b1f3f32ff361e6a00e50))
18
+
19
+ ## [0.13.1](https://github.com/KaTeX/KaTeX/compare/v0.13.0...v0.13.1) (2021-04-05)
20
+
21
+
22
+ ### Bug Fixes
23
+
24
+ * Protect fraction bars from CSS border-color ([#2870](https://github.com/KaTeX/KaTeX/issues/2870)) ([2f62c0d](https://github.com/KaTeX/KaTeX/commit/2f62c0d8ee8135f4d5b7fe727add6ad25d5c86a0))
25
+
26
+ ## [v0.13.0]
27
+ ### See https://github.com/KaTeX/KaTeX/issues/2490 for breaking changes and migration guide!
28
+
29
+ ### Bug Fixes
30
+ - fix: Remove topEnv parameter. (#2712)
31
+ - fix(builder): combine characters together in all expressions (#2080)
32
+ - fix: Prevent global group from adversely affecting color. (#2703)
33
+ - fix: Use SVGs to avoid gaps in tall delimiters. (#2698)
34
+ - fix: rewrite of splitAtDelimiters.js -- new fix for #2523 (#2679)
35
+ - fix: Improve MathML for math operators with subscripts (#2596)
36
+ - fix: Remove premature CD screenshotter images (#2641)
37
+ - fix: Support Armenian characters (#2618)
38
+ - fix: MathML \lim\limits in Safari (#2556)
39
+ - fix: Support MathML \oiint and \oiiint (#2461)
40
+ - fix: \injlim typo (#2459)
41
+
42
+ ### Features
43
+ - feat: Support \underbar (#2713)
44
+ - feat: Add {CD} to auto-render. (#2710)
45
+ - feat: Set Auto-render to recognize AMS environments without $$…$$ delimiters. (#2701)
46
+ - feat: Support {CD} (#2396)
47
+ - feat: Support \vcenter and \hbox (#2452)
48
+ - feat(function): add `allowedInArgument` instead of `greediness` property (#2134)
49
+ - feat: Support matrix*, pmatrix*, bmatrix*, Bmatrix*, vmatrix*, and Vmatrix*. (#2488)
50
+ - feat(macro): improve argument parsing (#2085)
51
+ - feat: support AMS log-like symbols (#2429)
52
+ - feat: support Unicode ◯, U+25EF (#2430)
53
+ - feat: Support \phase (#2406)
54
+ - feat: Support \mathstrut (#2416)
55
+ - feat: support {equation}, {equation*}, and {split} (#2369)
56
+ - feat(css): use postcss-preset-env (#2313)
57
+ - feat: support {align}, {align*}, {alignat}, and {alignat*} (#2341)
58
+ - Support {gather} and {gather*} (#2183)
59
+ - feat: support MathML \big, \bigg, \Big, and \Bigg (#2332)
60
+ - feat: support \angl and \angln (#2334)
61
+ - Support \origof and \imageof (#2283)
62
+
63
+ ### Documentation
64
+ - docs: Add TiddlyWiki to list of users (#2765)
65
+ - docs: Fix fallback CSS classes (#2809)
66
+ - docs: Rearrange environment documentation. (#2700)
67
+ - docs: Explain how to make macros persist. (#2702)
68
+ - docs: Revise placement of colonequals in Relations table (#2704)
69
+ - docs: delete stray backtick (#2680)
70
+ - docs: Add colonequals functions to docs (#2651)
71
+ - docs: add new user link (#2597)
72
+ - fix: typo in example on homepage (#2577)
73
+ - docs: Add \char to support_table. (#2620)
74
+ - docs: Update \operatorname in supported_table.md 0.12.0 (#2571)
75
+ - docs: Fix documentation typo in operatorname* (#2570)
76
+ - docs: add warning re:defer to mhchem documentation (#2485)
77
+ - docs: update Gastby logo and link (#2481)
78
+ - docs: add MonsterWriter to the users page (#2478)
79
+ - docs: add comment re: \arrowvert (#2449)
80
+ - docs: add link to Discussions (#2405)
81
+ - Update \color documentation (#2370)
82
+ - docs: add Marker as a KaTeX user (#2329)
83
+
84
+ ### Other Changes
85
+ - ci: run screenshotter in container (#2644)
86
+ - ci: setup CodeQL code scanning (#2645)
87
+ - fix(browserslist): remove Chrome 49, Samsung 4, and Node (#2591)
88
+ - chore: add devcontainer.json (#2545)
89
+ - Configure Renovate (#2493)
90
+ - ci: don't persist credentials and run scripts (#2450)
91
+ - build: upgrade Yarn to 2.2.0 (#2477)
92
+ - build: make vscode work with PnP (#2444)
93
+ - refactor: Delete obsolete comment re: mn elements (#2472)
94
+ - test: lint all js files and inline scripts in workflow (#2442)
95
+ - refactor: Delete obsolete comment re: limsup (#2464)
96
+ - ci: migrate to GitHub Actions from CircleCI, allow running Browserstack on forked repo via label (#2417)
97
+ - ci: enable Dependabot for website, submodules, and GitHub Actions (#2424)
98
+ - test: add missing screenshots for safari (#2423)
99
+ - ci: fix Dependabot autofix (#2400)
100
+ - chore: don't include `dist` in the release commit (#2385)
101
+ - ci: autofix Dependabot commits (#2394)
102
+ - chore(screenshotter): support Browserstack and test on Safari 13.1 (#2306)
103
+ - chore: enable Gitpod (#2335)
104
+ - chore: migrate to Yarn 2 (#2316)
105
+ - test: mock console implementation (#2363)
106
+ - Update LICENSE year (#2374)
107
+ - test(screenshotter): move coverage to Jest (#2324)
108
+ - Fix test/symgroups.js (#2314)
109
+ - Use base revision provided by CircleCI (#2309)
110
+ - Delete bower.json (#2372)
111
+ - Enable a MathML option in the KaTeX demo. (#2371)
112
+ - Create dependabot.yml (#2311)
113
+ - Run screenshotter using Chrome 83 and Firefox 76 (#2304)
114
+
115
+
4
116
  ## [v0.12.0]
5
117
  ### Added
6
118
  - `globalGroup` option to place definitions in global scope (#2091)
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2013-2019 Khan Academy and other contributors
3
+ Copyright (c) 2013-2020 Khan Academy and other contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,11 +1,12 @@
1
1
  # [<img src="https://katex.org/img/katex-logo-black.svg" width="130" alt="KaTeX">](https://katex.org/)
2
2
  [![npm](https://img.shields.io/npm/v/katex.svg)](https://www.npmjs.com/package/katex)
3
- [![CircleCI](https://circleci.com/gh/KaTeX/KaTeX.svg?style=shield)](https://circleci.com/gh/KaTeX/KaTeX)
3
+ [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
4
+ [![CI](https://github.com/KaTeX/KaTeX/workflows/CI/badge.svg?branch=master&event=push)](https://github.com/KaTeX/KaTeX/actions?query=workflow%3ACI)
4
5
  [![codecov](https://codecov.io/gh/KaTeX/KaTeX/branch/master/graph/badge.svg)](https://codecov.io/gh/KaTeX/KaTeX)
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
- [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=KaTeX/KaTeX)](https://dependabot.com)
6
+ [![Discussions](https://img.shields.io/badge/Discussions-join-brightgreen)](https://github.com/KaTeX/KaTeX/discussions)
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.12.0/dist/katex.min.js?compression=gzip)
8
+ ![katex.min.js size](https://img.badgesize.io/https://unpkg.com/katex/dist/katex.min.js?compression=gzip)
9
+ [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/KaTeX/KaTeX)
9
10
 
10
11
  KaTeX is a fast, easy-to-use JavaScript library for TeX math rendering on the web.
11
12
 
@@ -29,13 +30,13 @@ Try out KaTeX [on the demo page](https://katex.org/#demo)!
29
30
  <!-- KaTeX requires the use of the HTML5 doctype. Without it, KaTeX may not render properly -->
30
31
  <html>
31
32
  <head>
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
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.13.3/dist/katex.min.css" integrity="sha384-ThssJ7YtjywV52Gj4JE/1SQEDoMEckXyhkFVwaf4nDSm5OBlXeedVYjuuUd0Yua+" crossorigin="anonymous">
33
34
 
34
35
  <!-- The loading of KaTeX is deferred to speed up page rendering -->
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
+ <script defer src="https://cdn.jsdelivr.net/npm/katex@0.13.3/dist/katex.min.js" integrity="sha384-Bi8OWqMXO1ta+a4EPkZv7bYGIes7C3krGSZoTGNTAnAn5eYQc7IIXrJ/7ck1drAi" crossorigin="anonymous"></script>
36
37
 
37
38
  <!-- To automatically render math in text elements, include the auto-render extension: -->
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
+ <script defer src="https://cdn.jsdelivr.net/npm/katex@0.13.3/dist/contrib/auto-render.min.js" integrity="sha384-vZTG03m+2yp6N6BNi5iM4rW4oIwk5DfcNdFfxkk9ZWpDriOkXX8voJBFrAO7MpVl" crossorigin="anonymous"
39
40
  onload="renderMathInElement(document.body);"></script>
40
41
  </head>
41
42
  ...
@@ -3,22 +3,11 @@
3
3
  import katex from "katex";
4
4
  import splitAtDelimiters from "./splitAtDelimiters";
5
5
 
6
- const splitWithDelimiters = function(text, delimiters) {
7
- let data = [{type: "text", data: text}];
8
- for (let i = 0; i < delimiters.length; i++) {
9
- const delimiter = delimiters[i];
10
- data = splitAtDelimiters(
11
- data, delimiter.left, delimiter.right,
12
- delimiter.display || false);
13
- }
14
- return data;
15
- };
16
-
17
6
  /* Note: optionsCopy is mutated by this method. If it is ever exposed in the
18
7
  * API, we should copy it before mutating.
19
8
  */
20
9
  const renderMathInText = function(text, optionsCopy) {
21
- const data = splitWithDelimiters(text, optionsCopy.delimiters);
10
+ const data = splitAtDelimiters(text, optionsCopy.delimiters);
22
11
  if (data.length === 1 && data[0].type === 'text') {
23
12
  // There is no formula in the text.
24
13
  // Let's return null which means there is no need to replace
@@ -48,7 +37,7 @@ const renderMathInText = function(text, optionsCopy) {
48
37
  }
49
38
  optionsCopy.errorCallback(
50
39
  "KaTeX auto-render: Failed to parse `" + data[i].data +
51
- "` with ",
40
+ "` with ",
52
41
  e
53
42
  );
54
43
  fragment.appendChild(document.createTextNode(data[i].rawData));
@@ -76,8 +65,8 @@ const renderElem = function(elem, optionsCopy) {
76
65
  const className = ' ' + childNode.className + ' ';
77
66
  const shouldRender = optionsCopy.ignoredTags.indexOf(
78
67
  childNode.nodeName.toLowerCase()) === -1 &&
79
- optionsCopy.ignoredClasses.every(
80
- x => className.indexOf(' ' + x + ' ') === -1);
68
+ optionsCopy.ignoredClasses.every(
69
+ x => className.indexOf(' ' + x + ' ') === -1);
81
70
 
82
71
  if (shouldRender) {
83
72
  renderElem(childNode, optionsCopy);
@@ -107,11 +96,15 @@ const renderMathInElement = function(elem, options) {
107
96
  {left: "\\(", right: "\\)", display: false},
108
97
  // LaTeX uses $…$, but it ruins the display of normal `$` in text:
109
98
  // {left: "$", right: "$", display: false},
99
+ // $ must come after $$
100
+
101
+ // Render AMS environments even if outside $$…$$ delimiters.
102
+ {left: "\\begin{equation}", right: "\\end{equation}", display: true},
103
+ {left: "\\begin{align}", right: "\\end{align}", display: true},
104
+ {left: "\\begin{alignat}", right: "\\end{alignat}", display: true},
105
+ {left: "\\begin{gather}", right: "\\end{gather}", display: true},
106
+ {left: "\\begin{CD}", right: "\\end{CD}", display: true},
110
107
 
111
- // \[…\] must come last in this array. Otherwise, renderMathInElement
112
- // will search for \[ before it searches for $$ or \(
113
- // That makes it susceptible to finding a \\[0.3em] row delimiter and
114
- // treating it as if it were the start of a KaTeX math zone.
115
108
  {left: "\\[", right: "\\]", display: true},
116
109
  ];
117
110
  optionsCopy.ignoredTags = optionsCopy.ignoredTags || [
@@ -25,13 +25,15 @@
25
25
  <div id="test">
26
26
  This is some text $math \frac12$ other text $\unsupported$
27
27
  <span class="blue">
28
- Other node \[ displaymath \frac{1}{2} \] blah $$ \int_2^3 $$
28
+ Other node \[ \text{displaymath} \frac{1}{2} \] blah $$ \int_2^3 $$
29
29
  </span>
30
30
  and some <!-- comment --> more text \(and math\) blah. And $math with a
31
31
  \$ sign$.
32
32
  <pre>
33
33
  Stuff in a $pre tag$
34
34
  </pre>
35
+ <p>An AMS environment without <code>$$…$$</code> delimiters.</p>
36
+ <p>\begin{equation} \begin{split} a &=b+c\\ &=e+f \end{split} \end{equation}</p>
35
37
  </div>
36
38
  <script>
37
39
  renderMathInElement(
@@ -39,9 +41,13 @@
39
41
  {
40
42
  delimiters: [
41
43
  {left: "$$", right: "$$", display: true},
42
- {left: "\\[", right: "\\]", display: true},
43
44
  {left: "$", right: "$", display: false},
44
- {left: "\\(", right: "\\)", display: false}
45
+ {left: "\\begin{equation}", right: "\\end{equation}", display: true},
46
+ {left: "\\begin{align}", right: "\\end{align}", display: true},
47
+ {left: "\\begin{alignat}", right: "\\end{alignat}", display: true},
48
+ {left: "\\begin{gather}", right: "\\end{gather}", display: true},
49
+ {left: "\\(", right: "\\)", display: false},
50
+ {left: "\\[", right: "\\]", display: true}
45
51
  ]
46
52
  }
47
53
  );
@@ -27,76 +27,59 @@ const findEndOfMath = function(delimiter, text, startIndex) {
27
27
  return -1;
28
28
  };
29
29
 
30
- const splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
31
- const finalData = [];
32
-
33
- for (let i = 0; i < startData.length; i++) {
34
- if (startData[i].type === "text") {
35
- const text = startData[i].data;
36
-
37
- let lookingForLeft = true;
38
- let currIndex = 0;
39
- let nextIndex;
40
-
41
- nextIndex = text.indexOf(leftDelim);
42
- if (nextIndex !== -1) {
43
- currIndex = nextIndex;
44
- finalData.push({
45
- type: "text",
46
- data: text.slice(0, currIndex),
47
- });
48
- lookingForLeft = false;
49
- }
50
-
51
- while (true) {
52
- if (lookingForLeft) {
53
- nextIndex = text.indexOf(leftDelim, currIndex);
54
- if (nextIndex === -1) {
55
- break;
56
- }
57
-
58
- finalData.push({
59
- type: "text",
60
- data: text.slice(currIndex, nextIndex),
61
- });
62
-
63
- currIndex = nextIndex;
64
- } else {
65
- nextIndex = findEndOfMath(
66
- rightDelim,
67
- text,
68
- currIndex + leftDelim.length);
69
- if (nextIndex === -1) {
70
- break;
71
- }
30
+ const escapeRegex = function(string) {
31
+ return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
32
+ };
72
33
 
73
- finalData.push({
74
- type: "math",
75
- data: text.slice(
76
- currIndex + leftDelim.length,
77
- nextIndex),
78
- rawData: text.slice(
79
- currIndex,
80
- nextIndex + rightDelim.length),
81
- display: display,
82
- });
34
+ const amsRegex = /^\\begin{/;
83
35
 
84
- currIndex = nextIndex + rightDelim.length;
85
- }
36
+ const splitAtDelimiters = function(text, delimiters) {
37
+ let index;
38
+ const data = [];
86
39
 
87
- lookingForLeft = !lookingForLeft;
88
- }
40
+ const regexLeft = new RegExp(
41
+ "(" + delimiters.map((x) => escapeRegex(x.left)).join("|") + ")"
42
+ );
89
43
 
90
- finalData.push({
44
+ while (true) {
45
+ index = text.search(regexLeft);
46
+ if (index === -1) {
47
+ break;
48
+ }
49
+ if (index > 0) {
50
+ data.push({
91
51
  type: "text",
92
- data: text.slice(currIndex),
52
+ data: text.slice(0, index),
93
53
  });
94
- } else {
95
- finalData.push(startData[i]);
54
+ text = text.slice(index); // now text starts with delimiter
55
+ }
56
+ // ... so this always succeeds:
57
+ const i = delimiters.findIndex((delim) => text.startsWith(delim.left));
58
+ index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length);
59
+ if (index === -1) {
60
+ break;
96
61
  }
62
+ const rawData = text.slice(0, index + delimiters[i].right.length);
63
+ const math = amsRegex.test(rawData)
64
+ ? rawData
65
+ : text.slice(delimiters[i].left.length, index);
66
+ data.push({
67
+ type: "math",
68
+ data: math,
69
+ rawData,
70
+ display: delimiters[i].display,
71
+ });
72
+ text = text.slice(index + delimiters[i].right.length);
73
+ }
74
+
75
+ if (text !== "") {
76
+ data.push({
77
+ type: "text",
78
+ data: text,
79
+ });
97
80
  }
98
81
 
99
- return finalData;
82
+ return data;
100
83
  };
101
84
 
102
85
  export default splitAtDelimiters;
@@ -1,8 +1,3 @@
1
- /* global beforeEach: false */
2
- /* global expect: false */
3
- /* global it: false */
4
- /* global describe: false */
5
-
6
1
  import splitAtDelimiters from "../splitAtDelimiters";
7
2
  import renderMathInElement from "../auto-render";
8
3
 
@@ -11,17 +6,16 @@ beforeEach(function() {
11
6
  toSplitInto: function(actual, left, right, result) {
12
7
  const message = {
13
8
  pass: true,
14
- message: "'" + actual + "' split correctly",
9
+ message: () => "'" + actual + "' split correctly",
15
10
  };
16
11
 
17
- const startData = [{type: "text", data: actual}];
18
-
19
12
  const split =
20
- splitAtDelimiters(startData, left, right, false);
13
+ splitAtDelimiters(actual,
14
+ [{left: left, right: right, display: false}]);
21
15
 
22
16
  if (split.length !== result.length) {
23
17
  message.pass = false;
24
- message.message = "Different number of splits: " +
18
+ message.message = () => "Different number of splits: " +
25
19
  split.length + " vs. " + result.length + " (" +
26
20
  JSON.stringify(split) + " vs. " +
27
21
  JSON.stringify(result) + ")";
@@ -48,7 +42,7 @@ beforeEach(function() {
48
42
 
49
43
  if (!good) {
50
44
  message.pass = false;
51
- message.message = "Difference at split " +
45
+ message.message = () => "Difference at split " +
52
46
  (i + 1) + ": " + JSON.stringify(real) +
53
47
  " vs. " + JSON.stringify(correct) +
54
48
  " (" + diff + " differs)";
@@ -103,6 +97,15 @@ describe("A delimiter splitter", function() {
103
97
  rawData: "[[ world ]]", display: false},
104
98
  {type: "text", data: " boo"},
105
99
  ]);
100
+ expect("hello \\begin{equation} world \\end{equation} boo").toSplitInto(
101
+ "\\begin{equation}", "\\end{equation}",
102
+ [
103
+ {type: "text", data: "hello "},
104
+ {type: "math", data: "\\begin{equation} world \\end{equation}",
105
+ rawData: "\\begin{equation} world \\end{equation}",
106
+ display: false},
107
+ {type: "text", data: " boo"},
108
+ ]);
106
109
  });
107
110
 
108
111
  it("splits mutliple times", function() {
@@ -151,6 +154,19 @@ describe("A delimiter splitter", function() {
151
154
  ]);
152
155
  });
153
156
 
157
+ it("correctly processes sequences of $..$", function() {
158
+ expect("$hello$$world$$boo$").toSplitInto(
159
+ "$", "$",
160
+ [
161
+ {type: "math", data: "hello",
162
+ rawData: "$hello$", display: false},
163
+ {type: "math", data: "world",
164
+ rawData: "$world$", display: false},
165
+ {type: "math", data: "boo",
166
+ rawData: "$boo$", display: false},
167
+ ]);
168
+ });
169
+
154
170
  it("doesn't split at escaped delimiters", function() {
155
171
  expect("hello ( world \\) ) boo").toSplitInto(
156
172
  "(", ")",
@@ -162,14 +178,14 @@ describe("A delimiter splitter", function() {
162
178
  ]);
163
179
 
164
180
  /* TODO(emily): make this work maybe?
165
- expect("hello \\( ( world ) boo").toSplitInto(
166
- "(", ")",
167
- [
168
- {type: "text", data: "hello \\( "},
169
- {type: "math", data: " world ",
170
- rawData: "( world )", display: false},
171
- {type: "text", data: " boo"},
172
- ]);
181
+ expect("hello \\( ( world ) boo").toSplitInto(
182
+ "(", ")",
183
+ [
184
+ {type: "text", data: "hello \\( "},
185
+ {type: "math", data: " world ",
186
+ rawData: "( world )", display: false},
187
+ {type: "text", data: " boo"},
188
+ ]);
173
189
  */
174
190
  });
175
191
 
@@ -184,10 +200,20 @@ describe("A delimiter splitter", function() {
184
200
  ]);
185
201
  });
186
202
 
203
+ it("ignores \\$", function() {
204
+ expect("$x = \\$5$").toSplitInto(
205
+ "$", "$",
206
+ [
207
+ {type: "math", data: "x = \\$5",
208
+ rawData: "$x = \\$5$", display: false},
209
+ ]);
210
+ });
211
+
187
212
  it("remembers which delimiters are display-mode", function() {
188
- const startData = [{type: "text", data: "hello ( world ) boo"}];
213
+ const startData = "hello ( world ) boo";
189
214
 
190
- expect(splitAtDelimiters(startData, "(", ")", true)).toEqual(
215
+ expect(splitAtDelimiters(startData,
216
+ [{left:"(", right:")", display:true}])).toEqual(
191
217
  [
192
218
  {type: "text", data: "hello "},
193
219
  {type: "math", data: " world ",
@@ -196,42 +222,52 @@ describe("A delimiter splitter", function() {
196
222
  ]);
197
223
  });
198
224
 
199
- it("works with more than one start datum", function() {
200
- const startData = [
201
- {type: "text", data: "hello ( world ) boo"},
202
- {type: "math", data: "math", rawData: "(math)", display: true},
203
- {type: "text", data: "hello ( world ) boo"},
204
- ];
205
-
206
- expect(splitAtDelimiters(startData, "(", ")", false)).toEqual(
225
+ it("handles nested delimiters irrespective of order", function() {
226
+ expect(splitAtDelimiters("$\\fbox{\\(hi\\)}$",
207
227
  [
208
- {type: "text", data: "hello "},
209
- {type: "math", data: " world ",
210
- rawData: "( world )", display: false},
211
- {type: "text", data: " boo"},
212
- {type: "math", data: "math", rawData: "(math)", display: true},
213
- {type: "text", data: "hello "},
214
- {type: "math", data: " world ",
215
- rawData: "( world )", display: false},
216
- {type: "text", data: " boo"},
228
+ {left:"\\(", right:"\\)", display:false},
229
+ {left:"$", right:"$", display:false},
230
+ ])).toEqual(
231
+ [
232
+ {type: "math", data: "\\fbox{\\(hi\\)}",
233
+ rawData: "$\\fbox{\\(hi\\)}$", display: false},
234
+ ]);
235
+ expect(splitAtDelimiters("\\(\\fbox{$hi$}\\)",
236
+ [
237
+ {left:"\\(", right:"\\)", display:false},
238
+ {left:"$", right:"$", display:false},
239
+ ])).toEqual(
240
+ [
241
+ {type: "math", data: "\\fbox{$hi$}",
242
+ rawData: "\\(\\fbox{$hi$}\\)", display: false},
217
243
  ]);
218
244
  });
219
245
 
220
- it("doesn't do splitting inside of math nodes", function() {
221
- const startData = [
222
- {type: "text", data: "hello ( world ) boo"},
223
- {type: "math", data: "hello ( world ) boo",
224
- rawData: "(hello ( world ) boo)", display: true},
225
- ];
226
-
227
- expect(splitAtDelimiters(startData, "(", ")", false)).toEqual(
246
+ it("handles a mix of $ and $$", function() {
247
+ expect(splitAtDelimiters("$hello$world$$boo$$",
228
248
  [
229
- {type: "text", data: "hello "},
230
- {type: "math", data: " world ",
231
- rawData: "( world )", display: false},
232
- {type: "text", data: " boo"},
233
- {type: "math", data: "hello ( world ) boo",
234
- rawData: "(hello ( world ) boo)", display: true},
249
+ {left:"$$", right:"$$", display:true},
250
+ {left:"$", right:"$", display:false},
251
+ ])).toEqual(
252
+ [
253
+ {type: "math", data: "hello",
254
+ rawData: "$hello$", display: false},
255
+ {type: "text", data: "world"},
256
+ {type: "math", data: "boo",
257
+ rawData: "$$boo$$", display: true},
258
+ ]);
259
+ expect(splitAtDelimiters("$hello$$world$$$boo$$",
260
+ [
261
+ {left:"$$", right:"$$", display:true},
262
+ {left:"$", right:"$", display:false},
263
+ ])).toEqual(
264
+ [
265
+ {type: "math", data: "hello",
266
+ rawData: "$hello$", display: false},
267
+ {type: "math", data: "world",
268
+ rawData: "$world$", display: false},
269
+ {type: "math", data: "boo",
270
+ rawData: "$$boo$$", display: true},
235
271
  ]);
236
272
  });
237
273
  });
@@ -1,6 +1,6 @@
1
1
  # Copy-tex extension
2
2
 
3
- This extension modifes the copy/paste behavior in any browser supporting the
3
+ This extension modifies the copy/paste behavior in any browser supporting the
4
4
  [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent)
5
5
  so that, when selecting and copying whole KaTeX-rendered elements, the text
6
6
  content of the resulting clipboard renders KaTeX elements as their LaTeX source
@@ -21,8 +21,8 @@ provided by this extension). Without this CSS, partially selected equations
21
21
  will just get the usual HTML copy/paste behavior.
22
22
 
23
23
  ```html
24
- <link href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/contrib/copy-tex.css" rel="stylesheet" type="text/css">
25
- <script src="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/contrib/copy-tex.min.js" integrity="sha384-XhWAe6BtVcvEdS3FFKT7Mcft4HJjPqMQvi5V4YhzH9Qxw497jC13TupOEvjoIPy7" crossorigin="anonymous"></script>
24
+ <link href="https://cdn.jsdelivr.net/npm/katex@0.13.3/dist/contrib/copy-tex.css" rel="stylesheet" type="text/css">
25
+ <script src="https://cdn.jsdelivr.net/npm/katex@0.13.3/dist/contrib/copy-tex.min.js" integrity="sha384-Ep9Es0VCjVn9dFeaN2uQxgGcGmG+pfZ4eBaHxUpxXDORrrVACZVOpywyzvFRGbmv" crossorigin="anonymous"></script>
26
26
  ```
27
27
 
28
28
  See [index.html](index.html) for an example.
@@ -37,17 +37,13 @@ statement with `require('katex/contrib/copy-tex/katex2tex.js')`.
37
37
 
38
38
  ECMAScript module is also available:
39
39
  ```html
40
- <script type="module" src="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/contrib/copy-tex.mjs" integrity="sha384-kS7UtO844uqLwxPmaRwzg1nGbKiHsIteWh+DP2cvT2FtigL0v6w1yPXYKEDzct0C" crossorigin="anonymous"></script>
40
+ <script type="module" src="https://cdn.jsdelivr.net/npm/katex@0.13.3/dist/contrib/copy-tex.mjs" integrity="sha384-+gSYJ3yzY30+a6FGYJXOx9swmWs5oPKEi1AeCsAxsLexABlUXgHXkOkEZCj0Lz8U" crossorigin="anonymous"></script>
41
+ ```
41
42
 
42
43
  ### Known Issues
43
44
 
44
45
  This extension has been tested on Chrome, Firefox, Edge, and Safari.
45
46
 
46
- Microsoft Edge
47
- [does not seem to support](https://developer.microsoft.com/en-us/microsoft-edge/platform/status/clipboardapi/)
48
- text and HTML content in a single clipboard. In this browser, this extension
49
- will just put the text content into the clipboard.
50
-
51
47
  Safari copies correctly, but the selection rectangle renders strangely
52
48
  (too big) when interacting with display math
53
49
  (because of the `user-select: all` CSS).
@@ -7,7 +7,4 @@
7
7
  .katex,
8
8
  .katex-display {
9
9
  user-select: all;
10
- -moz-user-select: all;
11
- -webkit-user-select: all;
12
- -ms-user-select: all;
13
10
  }