From bb078fe88541a5d2a1c9b7b2b08176d9b1f84622 Mon Sep 17 00:00:00 2001 From: Ron Kok Date: Sat, 11 Jun 2022 12:31:52 -0700 Subject: [PATCH] Release 0.6.9 --- .eslintignore | 2 - .eslintrc | 73 - .gitattributes | 3 - CHANGELOG.md | 366 - LICENSE | 21 - README.md | 44 - contrib/auto-render/README.md | 89 - contrib/auto-render/auto-render.js | 128 - contrib/auto-render/dist/auto-render.js | 217 - contrib/auto-render/dist/auto-render.min.js | 1 - contrib/auto-render/splitAtDelimiters.js | 84 - contrib/auto-render/test/auto-render-spec.js | 234 - contrib/auto-render/test/auto-render.js | 217 - contrib/auto-render/test/test_page.html | 59 - contrib/mhchem/README.md | 26 - contrib/mhchem/mhchem.js | 1705 -- contrib/mhchem/mhchem.min.js | 1 - contrib/physics/README.md | 20 - contrib/physics/physics.js | 131 - contrib/texvc/README.md | 23 - contrib/texvc/texvc.js | 61 - docs/administration.md | 385 - docs/comparison.html | 9740 ------------ docs/support_table.md | 1570 -- docs/supported.md | 1623 -- package.json | 37 - site/assets/Asana-Math.woff2 | Bin 247716 -> 0 bytes site/assets/GUST-FONT-LICENSE.txt | 30 - site/assets/MANIFEST-Latin-Modern-Math.txt | 60 - site/assets/README-Latin-Modern-Math.txt | 92 - site/assets/STIXTwoMath-Regular.woff2 | Bin 551908 -> 0 bytes site/assets/Temml-Asana.css | 57 - site/assets/Temml-Latin-Modern.css | 68 - site/assets/Temml-Local.css | 47 - site/assets/Temml-STIX2.css | 56 - site/assets/Temml-XITS.css | 63 - site/assets/Temml.woff2 | Bin 11744 -> 0 bytes site/assets/XITS-FAQ.txt | 369 - site/assets/XITS-README.txt | 37 - site/assets/XITS.txt | 103 - site/assets/latinmodernmath.woff2 | Bin 388456 -> 0 bytes site/assets/mhchem.min.js | 1 - site/assets/physics.js | 132 - site/assets/temml.min.js | 1 - site/assets/texvc.js | 61 - site/assets/xits-math.woff2 | Bin 293336 -> 0 bytes site/assets/xits-mathbold.woff2 | Bin 140880 -> 0 bytes site/docs/docStyles.css | 375 - site/docs/en/administration.html | 254 - site/docs/en/comparison.html | 9732 ------------ site/docs/en/support_table.html | 1587 -- site/docs/en/supported.html | 751 - site/docs/katex.css | 11 - site/docs/sphere.jpg | Bin 12278 -> 0 bytes site/index.html | 222 - site/indexStyles.css | 200 - site/mathml.css | 218 - site/tests/LaTeXML-tests.html | 84 - site/tests/images/AccentsText.svg | 207 - site/tests/images/ArrayMode.svg | 330 - site/tests/images/ArrayType.svg | 33 - site/tests/images/Arrays.svg | 238 - site/tests/images/BinCancellation.svg | 99 - site/tests/images/BoldSymbol.svg | 178 - site/tests/images/CD.svg | 61 - site/tests/images/ColorBox.svg | 52 - site/tests/images/ColorImplicit.svg | 183 - site/tests/images/ColorSpacing.svg | 54 - site/tests/images/DashesAndQuotes.svg | 276 - site/tests/images/DelimiterSizing1.svg | 102 - site/tests/images/DelimiterSizing2.svg | 69 - site/tests/images/DisplayMode.svg | 52 - site/tests/images/ExtensibleArrows.svg | 326 - site/tests/images/Fractions1.svg | 119 - site/tests/images/Fractions2.svg | 158 - site/tests/images/HorizontalBraces.svg | 191 - site/tests/images/Integrands.svg | 129 - site/tests/images/LargeRuleNumerator.svg | 17 - site/tests/images/LeftRight.svg | 60 - site/tests/images/LeftRightListStyling.svg | 57 - site/tests/images/LeftRightMiddle.svg | 111 - site/tests/images/LeftRightStyleSizing.svg | 72 - site/tests/images/LimitControls.svg | 120 - site/tests/images/MathChoice.svg | 51 - site/tests/images/MathtoolsMatrix.svg | 69 - site/tests/images/NegativeSpace.svg | 55 - site/tests/images/NestedFractions.svg | 90 - .../tests/images/NullDelimiterInteraction.svg | 39 - site/tests/images/OpLimits.svg | 301 - site/tests/images/OperatorName.svg | 231 - site/tests/images/OverUnderline.svg | 87 - site/tests/images/OverUnderset.svg | 229 - site/tests/images/PrimeSpacing.svg | 57 - site/tests/images/PrimeSuper.svg | 81 - site/tests/images/RelativeUnits.svg | 99 - site/tests/images/SizingBaseline.svg | 63 - site/tests/images/SqrtRoot.svg | 169 - site/tests/images/StretchyAccent.svg | 385 - site/tests/images/StrikeThrough.svg | 337 - site/tests/images/StrikeThroughColor.svg | 103 - site/tests/images/StyleSpacing.svg | 33 - site/tests/images/StyleSwitching.svg | 61 - site/tests/images/SupSubCharacterBox.svg | 75 - site/tests/images/SupSubHorizSpacing.svg | 99 - site/tests/images/SupSubLeftAlignReset.svg | 85 - site/tests/images/SupSubOffsets.svg | 114 - site/tests/images/TextSpace.svg | 141 - site/tests/images/TextStacked.svg | 405 - site/tests/images/TextWithMath.svg | 226 - site/tests/images/accents.svg | 82 - site/tests/images/align.svg | 105 - site/tests/images/aligned.svg | 81 - site/tests/images/alignedat.svg | 123 - site/tests/images/angl.svg | 18 - site/tests/images/baseline.svg | 63 - site/tests/images/binom.svg | 99 - site/tests/images/boxed.svg | 76 - site/tests/images/cases.svg | 207 - site/tests/images/colors.svg | 21 - site/tests/images/displaystyle.svg | 73 - site/tests/images/dots.svg | 141 - site/tests/images/equation.svg | 96 - site/tests/images/ex1.gif | Bin 202 -> 0 bytes site/tests/images/ex10.gif | Bin 684 -> 0 bytes site/tests/images/ex11.gif | Bin 156 -> 0 bytes site/tests/images/ex12.gif | Bin 951 -> 0 bytes site/tests/images/ex13.gif | Bin 1763 -> 0 bytes site/tests/images/ex14.gif | Bin 1131 -> 0 bytes site/tests/images/ex15.gif | Bin 175 -> 0 bytes site/tests/images/ex16.gif | Bin 362 -> 0 bytes site/tests/images/ex17.gif | Bin 522 -> 0 bytes site/tests/images/ex18.gif | Bin 1476 -> 0 bytes site/tests/images/ex19.gif | Bin 467 -> 0 bytes site/tests/images/ex2.gif | Bin 163 -> 0 bytes site/tests/images/ex20.gif | Bin 144 -> 0 bytes site/tests/images/ex21.gif | Bin 1072 -> 0 bytes site/tests/images/ex22.gif | Bin 1039 -> 0 bytes site/tests/images/ex23.gif | Bin 1600 -> 0 bytes site/tests/images/ex24.gif | Bin 2003 -> 0 bytes site/tests/images/ex25.gif | Bin 145 -> 0 bytes site/tests/images/ex26.gif | Bin 343 -> 0 bytes site/tests/images/ex27.gif | Bin 222 -> 0 bytes site/tests/images/ex28.gif | Bin 179 -> 0 bytes site/tests/images/ex29.png | Bin 3313 -> 0 bytes site/tests/images/ex3.gif | Bin 349 -> 0 bytes site/tests/images/ex30.png | Bin 3392 -> 0 bytes site/tests/images/ex4.gif | Bin 268 -> 0 bytes site/tests/images/ex5.gif | Bin 235 -> 0 bytes site/tests/images/ex6.gif | Bin 906 -> 0 bytes site/tests/images/ex7.gif | Bin 739 -> 0 bytes site/tests/images/ex8.gif | Bin 416 -> 0 bytes site/tests/images/ex9.gif | Bin 869 -> 0 bytes site/tests/images/exponents.svg | 39 - site/tests/images/functions.svg | 78 - site/tests/images/gather.svg | 61 - site/tests/images/greek.svg | 33 - site/tests/images/kern.svg | 52 - site/tests/images/lap.svg | 220 - site/tests/images/latex.svg | 54 - site/tests/images/mathop.svg | 111 - site/tests/images/mod.svg | 183 - site/tests/images/newline.svg | 155 - site/tests/images/not.svg | 147 - site/tests/images/oldfont.svg | 128 - site/tests/images/phantom.svg | 147 - site/tests/images/pmb.svg | 54 - site/tests/images/raisebox.svg | 92 - site/tests/images/rcases.svg | 75 - site/tests/images/rlapbug.svg | 22 - site/tests/images/rule.svg | 9 - site/tests/images/sizing.svg | 64 - site/tests/images/smash.svg | 52 - site/tests/images/spacing.svg | 330 - site/tests/images/sqrt.svg | 176 - site/tests/images/stackrel.svg | 60 - site/tests/images/subarray.svg | 39 - site/tests/images/text.svg | 64 - site/tests/images/units.svg | 351 - site/tests/images/verb.svg | 271 - site/tests/katex-tests.html | 382 - site/tests/mhchem-tests.html | 242 - site/tests/mozilla-tests.html | 60 - site/tests/wiki-tests.html | 359 - site/xml-formatter.js | 432 - src/Lexer.js | 121 - src/MacroExpander.js | 437 - src/Namespace.js | 91 - src/ParseError.js | 64 - src/Parser.js | 948 -- src/Settings.js | 50 - src/SourceLocation.js | 29 - src/Style.js | 144 - src/Token.js | 40 - src/autocorrect.js | 126 - src/buildMathML.js | 187 - src/constants.js | 25 - src/defineEnvironment.js | 25 - src/defineFunction.js | 69 - src/defineMacro.js | 11 - src/domTree.js | 185 - src/environments.js | 8 - src/environments/array.js | 857 - src/environments/cd.js | 260 - src/functions.js | 59 - src/functions/accent.js | 128 - src/functions/accentunder.js | 38 - src/functions/arrow.js | 192 - src/functions/cancelto.js | 36 - src/functions/char.js | 33 - src/functions/color.js | 254 - src/functions/cr.js | 46 - src/functions/def.js | 203 - src/functions/delimsizing.js | 296 - src/functions/enclose.js | 158 - src/functions/envTag.js | 38 - src/functions/environment.js | 59 - src/functions/font.js | 123 - src/functions/genfrac.js | 333 - src/functions/hbox.js | 29 - src/functions/horizBrace.js | 31 - src/functions/href.js | 90 - src/functions/html.js | 95 - src/functions/includegraphics.js | 131 - src/functions/kern.js | 72 - src/functions/label.js | 29 - src/functions/lap.js | 50 - src/functions/math.js | 40 - src/functions/mathchoice.js | 41 - src/functions/mclass.js | 174 - src/functions/multiscript.js | 91 - src/functions/not.js | 46 - src/functions/op.js | 335 - src/functions/operatorname.js | 128 - src/functions/ordgroup.js | 9 - src/functions/overline.js | 31 - src/functions/phantom.js | 73 - src/functions/pmb.js | 31 - src/functions/raise.js | 66 - src/functions/ref.js | 28 - src/functions/relax.js | 16 - src/functions/rule.js | 52 - src/functions/sizing.js | 64 - src/functions/smash.js | 66 - src/functions/sqrt.js | 31 - src/functions/styling.js | 58 - src/functions/supsub.js | 135 - src/functions/symbolsOp.js | 41 - src/functions/symbolsOrd.js | 103 - src/functions/symbolsSpacing.js | 53 - src/functions/tag.js | 8 - src/functions/text.js | 76 - src/functions/tip.js | 63 - src/functions/toggle.js | 13 - src/functions/underline.js | 30 - src/functions/verb.js | 33 - src/linebreaking.js | 145 - src/macros.js | 709 - src/mathMLTree.js | 175 - src/parseNode.js | 42 - src/parseTree.js | 40 - src/postProcess.js | 57 - src/replace.js | 225 - src/stretchy.js | 66 - src/symbols.js | 971 -- src/tree.js | 52 - src/unicodeAccents.js | 16 - src/unicodeScripts.js | 119 - src/unicodeSupOrSub.js | 108 - src/unicodeSymbolBuilder.js | 31 - src/unicodeSymbols.js | 320 - src/units.js | 109 - src/utils.js | 160 - src/variant.js | 103 - temml.js | 177 - test/Investigate.html | 104 - test/LaTeXML-tests.md | 141 - test/auto-render.js | 212 - test/katex-tests.md | 1159 -- test/main.css | 16 - test/mhchem-tests.md | 279 - test/mozilla-tests.md | 176 - test/processTests.js | 6 - test/repl.html | 59 - test/temml.js | 11204 ------------- test/temmlPostProcess.js | 70 - test/unit-test.js | 2146 --- test/wiki-tests.md | 928 -- utils/TeXZilla.js | 4220 ----- utils/buildDocs.js | 92 - utils/buildTests.js | 23 - utils/copyfiles.js | 56 - utils/hurmetMark.cjs | 1160 -- utils/insertPlugins.js | 22 - utils/katex.min.js | 1 - utils/rollupConfig.js | 28 - utils/temml.cjs | 13101 ---------------- utils/temml.cjs.js | 13022 --------------- utils/temml.mjs | 13099 --------------- utils/temml.mjs.js | 13020 --------------- yarn-error.log | 5361 ------- yarn.lock | 648 - 301 files changed, 136290 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc delete mode 100644 .gitattributes delete mode 100644 CHANGELOG.md delete mode 100644 LICENSE delete mode 100644 README.md delete mode 100644 contrib/auto-render/README.md delete mode 100644 contrib/auto-render/auto-render.js delete mode 100644 contrib/auto-render/dist/auto-render.js delete mode 100644 contrib/auto-render/dist/auto-render.min.js delete mode 100644 contrib/auto-render/splitAtDelimiters.js delete mode 100644 contrib/auto-render/test/auto-render-spec.js delete mode 100644 contrib/auto-render/test/auto-render.js delete mode 100644 contrib/auto-render/test/test_page.html delete mode 100644 contrib/mhchem/README.md delete mode 100644 contrib/mhchem/mhchem.js delete mode 100644 contrib/mhchem/mhchem.min.js delete mode 100644 contrib/physics/README.md delete mode 100644 contrib/physics/physics.js delete mode 100644 contrib/texvc/README.md delete mode 100644 contrib/texvc/texvc.js delete mode 100644 docs/administration.md delete mode 100644 docs/comparison.html delete mode 100644 docs/support_table.md delete mode 100644 docs/supported.md delete mode 100644 package.json delete mode 100644 site/assets/Asana-Math.woff2 delete mode 100644 site/assets/GUST-FONT-LICENSE.txt delete mode 100644 site/assets/MANIFEST-Latin-Modern-Math.txt delete mode 100644 site/assets/README-Latin-Modern-Math.txt delete mode 100644 site/assets/STIXTwoMath-Regular.woff2 delete mode 100644 site/assets/Temml-Asana.css delete mode 100644 site/assets/Temml-Latin-Modern.css delete mode 100644 site/assets/Temml-Local.css delete mode 100644 site/assets/Temml-STIX2.css delete mode 100644 site/assets/Temml-XITS.css delete mode 100644 site/assets/Temml.woff2 delete mode 100644 site/assets/XITS-FAQ.txt delete mode 100644 site/assets/XITS-README.txt delete mode 100644 site/assets/XITS.txt delete mode 100644 site/assets/latinmodernmath.woff2 delete mode 100644 site/assets/mhchem.min.js delete mode 100644 site/assets/physics.js delete mode 100644 site/assets/temml.min.js delete mode 100644 site/assets/texvc.js delete mode 100644 site/assets/xits-math.woff2 delete mode 100644 site/assets/xits-mathbold.woff2 delete mode 100644 site/docs/docStyles.css delete mode 100644 site/docs/en/administration.html delete mode 100644 site/docs/en/comparison.html delete mode 100644 site/docs/en/support_table.html delete mode 100644 site/docs/en/supported.html delete mode 100644 site/docs/katex.css delete mode 100644 site/docs/sphere.jpg delete mode 100644 site/index.html delete mode 100644 site/indexStyles.css delete mode 100644 site/mathml.css delete mode 100644 site/tests/LaTeXML-tests.html delete mode 100644 site/tests/images/AccentsText.svg delete mode 100644 site/tests/images/ArrayMode.svg delete mode 100644 site/tests/images/ArrayType.svg delete mode 100644 site/tests/images/Arrays.svg delete mode 100644 site/tests/images/BinCancellation.svg delete mode 100644 site/tests/images/BoldSymbol.svg delete mode 100644 site/tests/images/CD.svg delete mode 100644 site/tests/images/ColorBox.svg delete mode 100644 site/tests/images/ColorImplicit.svg delete mode 100644 site/tests/images/ColorSpacing.svg delete mode 100644 site/tests/images/DashesAndQuotes.svg delete mode 100644 site/tests/images/DelimiterSizing1.svg delete mode 100644 site/tests/images/DelimiterSizing2.svg delete mode 100644 site/tests/images/DisplayMode.svg delete mode 100644 site/tests/images/ExtensibleArrows.svg delete mode 100644 site/tests/images/Fractions1.svg delete mode 100644 site/tests/images/Fractions2.svg delete mode 100644 site/tests/images/HorizontalBraces.svg delete mode 100644 site/tests/images/Integrands.svg delete mode 100644 site/tests/images/LargeRuleNumerator.svg delete mode 100644 site/tests/images/LeftRight.svg delete mode 100644 site/tests/images/LeftRightListStyling.svg delete mode 100644 site/tests/images/LeftRightMiddle.svg delete mode 100644 site/tests/images/LeftRightStyleSizing.svg delete mode 100644 site/tests/images/LimitControls.svg delete mode 100644 site/tests/images/MathChoice.svg delete mode 100644 site/tests/images/MathtoolsMatrix.svg delete mode 100644 site/tests/images/NegativeSpace.svg delete mode 100644 site/tests/images/NestedFractions.svg delete mode 100644 site/tests/images/NullDelimiterInteraction.svg delete mode 100644 site/tests/images/OpLimits.svg delete mode 100644 site/tests/images/OperatorName.svg delete mode 100644 site/tests/images/OverUnderline.svg delete mode 100644 site/tests/images/OverUnderset.svg delete mode 100644 site/tests/images/PrimeSpacing.svg delete mode 100644 site/tests/images/PrimeSuper.svg delete mode 100644 site/tests/images/RelativeUnits.svg delete mode 100644 site/tests/images/SizingBaseline.svg delete mode 100644 site/tests/images/SqrtRoot.svg delete mode 100644 site/tests/images/StretchyAccent.svg delete mode 100644 site/tests/images/StrikeThrough.svg delete mode 100644 site/tests/images/StrikeThroughColor.svg delete mode 100644 site/tests/images/StyleSpacing.svg delete mode 100644 site/tests/images/StyleSwitching.svg delete mode 100644 site/tests/images/SupSubCharacterBox.svg delete mode 100644 site/tests/images/SupSubHorizSpacing.svg delete mode 100644 site/tests/images/SupSubLeftAlignReset.svg delete mode 100644 site/tests/images/SupSubOffsets.svg delete mode 100644 site/tests/images/TextSpace.svg delete mode 100644 site/tests/images/TextStacked.svg delete mode 100644 site/tests/images/TextWithMath.svg delete mode 100644 site/tests/images/accents.svg delete mode 100644 site/tests/images/align.svg delete mode 100644 site/tests/images/aligned.svg delete mode 100644 site/tests/images/alignedat.svg delete mode 100644 site/tests/images/angl.svg delete mode 100644 site/tests/images/baseline.svg delete mode 100644 site/tests/images/binom.svg delete mode 100644 site/tests/images/boxed.svg delete mode 100644 site/tests/images/cases.svg delete mode 100644 site/tests/images/colors.svg delete mode 100644 site/tests/images/displaystyle.svg delete mode 100644 site/tests/images/dots.svg delete mode 100644 site/tests/images/equation.svg delete mode 100644 site/tests/images/ex1.gif delete mode 100644 site/tests/images/ex10.gif delete mode 100644 site/tests/images/ex11.gif delete mode 100644 site/tests/images/ex12.gif delete mode 100644 site/tests/images/ex13.gif delete mode 100644 site/tests/images/ex14.gif delete mode 100644 site/tests/images/ex15.gif delete mode 100644 site/tests/images/ex16.gif delete mode 100644 site/tests/images/ex17.gif delete mode 100644 site/tests/images/ex18.gif delete mode 100644 site/tests/images/ex19.gif delete mode 100644 site/tests/images/ex2.gif delete mode 100644 site/tests/images/ex20.gif delete mode 100644 site/tests/images/ex21.gif delete mode 100644 site/tests/images/ex22.gif delete mode 100644 site/tests/images/ex23.gif delete mode 100644 site/tests/images/ex24.gif delete mode 100644 site/tests/images/ex25.gif delete mode 100644 site/tests/images/ex26.gif delete mode 100644 site/tests/images/ex27.gif delete mode 100644 site/tests/images/ex28.gif delete mode 100644 site/tests/images/ex29.png delete mode 100644 site/tests/images/ex3.gif delete mode 100644 site/tests/images/ex30.png delete mode 100644 site/tests/images/ex4.gif delete mode 100644 site/tests/images/ex5.gif delete mode 100644 site/tests/images/ex6.gif delete mode 100644 site/tests/images/ex7.gif delete mode 100644 site/tests/images/ex8.gif delete mode 100644 site/tests/images/ex9.gif delete mode 100644 site/tests/images/exponents.svg delete mode 100644 site/tests/images/functions.svg delete mode 100644 site/tests/images/gather.svg delete mode 100644 site/tests/images/greek.svg delete mode 100644 site/tests/images/kern.svg delete mode 100644 site/tests/images/lap.svg delete mode 100644 site/tests/images/latex.svg delete mode 100644 site/tests/images/mathop.svg delete mode 100644 site/tests/images/mod.svg delete mode 100644 site/tests/images/newline.svg delete mode 100644 site/tests/images/not.svg delete mode 100644 site/tests/images/oldfont.svg delete mode 100644 site/tests/images/phantom.svg delete mode 100644 site/tests/images/pmb.svg delete mode 100644 site/tests/images/raisebox.svg delete mode 100644 site/tests/images/rcases.svg delete mode 100644 site/tests/images/rlapbug.svg delete mode 100644 site/tests/images/rule.svg delete mode 100644 site/tests/images/sizing.svg delete mode 100644 site/tests/images/smash.svg delete mode 100644 site/tests/images/spacing.svg delete mode 100644 site/tests/images/sqrt.svg delete mode 100644 site/tests/images/stackrel.svg delete mode 100644 site/tests/images/subarray.svg delete mode 100644 site/tests/images/text.svg delete mode 100644 site/tests/images/units.svg delete mode 100644 site/tests/images/verb.svg delete mode 100644 site/tests/katex-tests.html delete mode 100644 site/tests/mhchem-tests.html delete mode 100644 site/tests/mozilla-tests.html delete mode 100644 site/tests/wiki-tests.html delete mode 100644 site/xml-formatter.js delete mode 100644 src/Lexer.js delete mode 100644 src/MacroExpander.js delete mode 100644 src/Namespace.js delete mode 100644 src/ParseError.js delete mode 100644 src/Parser.js delete mode 100644 src/Settings.js delete mode 100644 src/SourceLocation.js delete mode 100644 src/Style.js delete mode 100644 src/Token.js delete mode 100644 src/autocorrect.js delete mode 100644 src/buildMathML.js delete mode 100644 src/constants.js delete mode 100644 src/defineEnvironment.js delete mode 100644 src/defineFunction.js delete mode 100644 src/defineMacro.js delete mode 100644 src/domTree.js delete mode 100644 src/environments.js delete mode 100644 src/environments/array.js delete mode 100644 src/environments/cd.js delete mode 100644 src/functions.js delete mode 100644 src/functions/accent.js delete mode 100644 src/functions/accentunder.js delete mode 100644 src/functions/arrow.js delete mode 100644 src/functions/cancelto.js delete mode 100644 src/functions/char.js delete mode 100644 src/functions/color.js delete mode 100644 src/functions/cr.js delete mode 100644 src/functions/def.js delete mode 100644 src/functions/delimsizing.js delete mode 100644 src/functions/enclose.js delete mode 100644 src/functions/envTag.js delete mode 100644 src/functions/environment.js delete mode 100644 src/functions/font.js delete mode 100644 src/functions/genfrac.js delete mode 100644 src/functions/hbox.js delete mode 100644 src/functions/horizBrace.js delete mode 100644 src/functions/href.js delete mode 100644 src/functions/html.js delete mode 100644 src/functions/includegraphics.js delete mode 100644 src/functions/kern.js delete mode 100644 src/functions/label.js delete mode 100644 src/functions/lap.js delete mode 100644 src/functions/math.js delete mode 100644 src/functions/mathchoice.js delete mode 100644 src/functions/mclass.js delete mode 100644 src/functions/multiscript.js delete mode 100644 src/functions/not.js delete mode 100644 src/functions/op.js delete mode 100644 src/functions/operatorname.js delete mode 100644 src/functions/ordgroup.js delete mode 100644 src/functions/overline.js delete mode 100644 src/functions/phantom.js delete mode 100644 src/functions/pmb.js delete mode 100644 src/functions/raise.js delete mode 100644 src/functions/ref.js delete mode 100644 src/functions/relax.js delete mode 100644 src/functions/rule.js delete mode 100644 src/functions/sizing.js delete mode 100644 src/functions/smash.js delete mode 100644 src/functions/sqrt.js delete mode 100644 src/functions/styling.js delete mode 100644 src/functions/supsub.js delete mode 100644 src/functions/symbolsOp.js delete mode 100644 src/functions/symbolsOrd.js delete mode 100644 src/functions/symbolsSpacing.js delete mode 100644 src/functions/tag.js delete mode 100644 src/functions/text.js delete mode 100644 src/functions/tip.js delete mode 100644 src/functions/toggle.js delete mode 100644 src/functions/underline.js delete mode 100644 src/functions/verb.js delete mode 100644 src/linebreaking.js delete mode 100644 src/macros.js delete mode 100644 src/mathMLTree.js delete mode 100644 src/parseNode.js delete mode 100644 src/parseTree.js delete mode 100644 src/postProcess.js delete mode 100644 src/replace.js delete mode 100644 src/stretchy.js delete mode 100644 src/symbols.js delete mode 100644 src/tree.js delete mode 100644 src/unicodeAccents.js delete mode 100644 src/unicodeScripts.js delete mode 100644 src/unicodeSupOrSub.js delete mode 100644 src/unicodeSymbolBuilder.js delete mode 100644 src/unicodeSymbols.js delete mode 100644 src/units.js delete mode 100644 src/utils.js delete mode 100644 src/variant.js delete mode 100644 temml.js delete mode 100644 test/Investigate.html delete mode 100644 test/LaTeXML-tests.md delete mode 100644 test/auto-render.js delete mode 100644 test/katex-tests.md delete mode 100644 test/main.css delete mode 100644 test/mhchem-tests.md delete mode 100644 test/mozilla-tests.md delete mode 100644 test/processTests.js delete mode 100644 test/repl.html delete mode 100644 test/temml.js delete mode 100644 test/temmlPostProcess.js delete mode 100644 test/unit-test.js delete mode 100644 test/wiki-tests.md delete mode 100644 utils/TeXZilla.js delete mode 100644 utils/buildDocs.js delete mode 100644 utils/buildTests.js delete mode 100644 utils/copyfiles.js delete mode 100644 utils/hurmetMark.cjs delete mode 100644 utils/insertPlugins.js delete mode 100644 utils/katex.min.js delete mode 100644 utils/rollupConfig.js delete mode 100644 utils/temml.cjs delete mode 100644 utils/temml.cjs.js delete mode 100644 utils/temml.mjs delete mode 100644 utils/temml.mjs.js delete mode 100644 yarn-error.log delete mode 100644 yarn.lock diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index a0a65c66..00000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -contrib/auto-render/test/*.js -src/autocorrect.js diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 0511c021..00000000 --- a/.eslintrc +++ /dev/null @@ -1,73 +0,0 @@ -{ - "extends": [ - "eslint:recommended" - ], - "globals":{ - "BigInt":true - }, - "rules": { - "arrow-spacing": 2, - "brace-style": [2, "1tbs", { "allowSingleLine": true }], - "camelcase": [2, { "properties": "never" }], - "comma-dangle": [2, "never"], - "comma-spacing": [2, { "before": false, "after": true }], - "constructor-super": 2, - "curly": 2, - "eol-last": 2, - "eqeqeq": [2, "allow-null"], - "guard-for-in": 2, - "indent": "off", - "indent-legacy": [2, 2, {"SwitchCase": 1}], - "keyword-spacing": 2, - "linebreak-style": [2, "unix"], - "max-len": [2, 100, 4, { "ignoreUrls": true, "ignoreRegExpLiterals": true }], - "new-cap": 2, - "no-alert": 2, - "no-array-constructor": 2, - "no-console": 2, - "no-const-assign": 2, - "no-debugger": 2, - "no-dupe-class-members": 2, - "no-dupe-keys": 2, - "no-extra-bind": 2, - "no-misleading-character-class": 0, - "no-new": 2, - "no-new-func": 2, - "no-new-object": 2, - "no-spaced-func": 2, - "no-this-before-super": 2, - "no-throw-literal": 2, - "no-trailing-spaces": 2, - "no-undef": 2, - "no-unexpected-multiline": 2, - "no-unreachable": 2, - "no-unused-vars": [2, {"args": "none", "varsIgnorePattern": "^_*$"}], - "no-useless-call": 2, - "no-var": 2, - "no-with": 2, - "object-curly-spacing": [2, "always"], - "one-var": [2, "never"], - "prefer-const": 2, - "prefer-spread": 0, - "semi": 0, - "space-before-blocks": 2, - "space-before-function-paren": [2, "never"], - "space-infix-ops": 2, - "space-unary-ops": 2, - "prefer-template": 0, - "arrow-parens": 0, - "prefer-arrow-callback": 0, - "valid-jsdoc": 0, - "require-jsdoc": 0 - }, - "env": { - "node": true, - "browser": true, - "es6": true - }, - "parserOptions": { - "ecmaVersion": 8, - "sourceType": "module" - }, - "root": true -} diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 5dc46e6b..00000000 --- a/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -* text=auto eol=lf -*.{cmd,[cC][mM][dD]} text eol=crlf -*.{bat,[bB][aA][tT]} text eol=crlf \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 30a6a350..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,366 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. This CHANGELOG roughly follows the guidelines from [keepachangelog.com](https://keepachangelog.com/en/1.0.0/). - -## [0.6.9] = 2022-06-11 - -### Fixed - -- Colors of lower-case color names -- `\surd` vertical alignment when rendered in Latin Modern - -## [0.6.8] = 2022-05-20 - -### Fixed - -- Avoid crash when mhchem \ce{} is empty -- Numerals in text mode - -### Added - -- Support Unicode (sub|superscript) characters - -## [0.6.7] = 2022-03-27 - -### Fixed - -- Added operator spacing to Unicode characters ∖∘∙ -- Avoid error when a spacing function is the base of a subscript. -- Fix nested font size changes -- Replace string.substr() with string.slice() -- Use Unicode U+203E, Overline, for \bar{} - -### Added - -- Support \strictif and \strictfi - -### Docs - -- Explain how to work around a Cambria Math radical size problem -- Edit README for brevity - -## [0.6.6] = 2022-01-28 - -### Fixed - -- Workaround a Firefox bug. Prevent space around a \mathrm{} function with a one-character argument. - -## [0.6.5] = 2022-01-20 - -### Added - -- 15 functions from the `cmll` package - -### Fixed - -- Omit color attribute and wrapper from \rule when unecessary - -## [0.6.4] = 2022-01-15 - -### Fixed - -- More improvement of recognition of delimiters after functions like \sin - -## [0.6.3] = 2022-01-14 - -### Fixed - -- Improve recognition of delimiters after functions like \sin - -## [0.6.2] = 2022-01-13 - -### Fixed - -- \bm{\sin} -- Remove spurious space between \sin (x) - -## [0.6.1] = 2022-01-12 - -### Fixed - -- \mathinner when part of a denominator - -## [0.6.0] = 2022-01-11 - -### Changed - -- In default Temml, Numbers are now consolidated into one element if they begin and end with a number and contain numerals, commas, or dots -- Some error messages are revised - -### Added - -- Documentation section regarding numbers - -## [0.5.3] = 2022-01-08 - -### Fixed - -- Suppress operator spacing between adjacent relations - -## [0.5.2] = 2022-01-07 - -### Fixed - -- \tag now stays in display mode - -### Changed - -- Parse error message now is displayed on screen, not in a hover hint. -- Added locations to some error messages. - -## [0.5.1] = 2022-01-05 - -### Fixed - -- \vcentcolon, \ratio - -## [0.5.0] = 2022-01-04 - -### Changed - -- Rendering option `maxSize` now takes an array of two numbers. - -### Added - -- \centerdot - -### Fixed - -- text-mode colon -- All unit tests now pass. -- All SVG images have been removed from Temml - -## [0.4.2] = 2021-12-24 - -### Fixed - -- \mathcal{ego} -- \not\operatorname -- \big\backslash and \right\backslash -- displaystyle \sideset -- := -- {cases} environment row spacing -- \varnothing -- math-mode \O and \o -- Greek edge cases of bold, italic, and sans-serif -- \shortmid, \nshortmid, \shortparallel, \nshortparallel, \smallsetminus -- non-stretchy accents (so they do not stretch) -- Make best effort to support Greek sans-serif - -### Added - -- \sgn - -## [0.4.1] = 2021-12-20 - -### Fixed - -- \bmod -- \colon spacing -- \right . -- \includegraphics -- \angle padding -- \subarray row spacing -- "/" spacing -- width of stacked harpoons -- operator spacing when adjacent to \color -- Improve laps -- Use character U+2044 for inline fractions -- Work around Firefox bug affecting \mathrlap -- \boldsymbol when it wraps an operator -- array environment enclosing lines -- \mathbf{\Omega} -- \mathop - -### Added - -- Copy button to home page. -- Images from LaTeX in KaTeX screenshotter tests -- Mozilla test suite -- mhchem test suite - -## [0.4.0] = 2021-12-06 - -### Changed - -- Remove \centerdot -- Remove \vcenter -- Remove \newextarrow -- Edit mhchem to sync w/extensible arrow fix. - -### Fixed - -- Prevent arrowhead distortion on extensible arrows -- Fix scriptstyle errors. -- Adjust RGB values of base colors. - -## [0.3.3] - 2021-11-24 - -### Added - -- Support \odv and \pdv from derivative package -- Rendering option `elementIsMath` - -### Changed - -- Make color names case-sensitive -- Use Unicode character U+212B for \AA - -### Fixed - -- Explicitly set stretchy="true" on delimiters to evade a Firefox bug -- Soft line breaks inside \color -- \mathbin that contains a - -## [0.3.2] - 2021-11-21 - -### Added - -- \definecolor -- Optional argument that sets the color model in color functions -- Predefined colors per Tables 4.1 and 4.2 in xcolor package -- \nsubset and \nsupset - -### Changed - -- Use character U+005F for \overline and \underline. Regain stretchiness. - -### Fixed - -- Spacing for \mid -- Workaround a Fireox bug for spacing of - -## [0.3.1] - 2021-11-15 - -### Added - -- Rendering option preventTagLap - -## [0.3.0] - 2021-11-12 - -### Removed - -- Support for \global, \gdef, and \xdef - -### Added - -- Preamble definition -- Support \nonumber -- STIX2 is now available on the home page - -### Fixed - -- Text mode accents in strict mode get only a console message, not an error. - -### Changed - -- Revert to macron character for \bar -- Change a font name from Temml-Script.woff2 to Temml.woff2. -- Change a folder name from /temml/ to /assets/. -- Documentation clarifies the current chancery/roundhand situation. - -## [0.2.3] - 2021-11-06 - -### Added - -- Support \ballotx -- Support \permil - -## [0.2.2] - 2021-11-04 - -### Added - -- Support \c -- Support \female and \male -- Support \relax -- Soft line breaks in Firefox, if no - -### Changed - -- element namespace is now optional -- elemennt w/TeX string is now optional -- Removed "temml" class from element -- Reduced number of visible DOM elements -- Support AMS environment w/one empty row -- \bar{} accent now uses character U+2015, horizontal bar - -### Fixed - -- Spaces inside \text{} -- \char now supports >16-bit Unicode characters -- \mathbb operating on numbers -- Circular dependency -- Stretchy arrow bug -- Validation errors in \mathop, \mathrel, and \operatorname - -## [0.2.1] - 2021-08-10 - -### Changed - -- Change CSS files. Each CSS file now is synchronized with a single math font. - -### Added - -- Support Asana and XITS fonts. -- Support \Braket, \Set, and \set. - -## [0.2.0] - 2021-08-02 - -### Removed - -- Soft line breaks, since they will not work in Chromium. - -### Fixed - -- Improve handling of \limits -- Improve handling of newline. -- Respect catcode in macro expansion and set ~ correctly. -- Improve \operatorname*. -- Fix non-stretchy accents in Firefox. -- Use correct Unicode for uppercase Greek. - -### Changed - -- Support font functions via substitution of Unicode characters instead of `mathvariant`. Font functions will now work in Chromium. -- Change \pmb to use CSS text-shadow instead of `mathvariant = bold`. - -### Added - -- Support \backcong. - -## [0.1.3] - 2021-05-21 - -### Fixed - -- Treat `\` followed by whitespace including up to one newline as equivalent to `\ `. -- Isolate `border-color` from page CSS. - -### Added - -- `\P` and `\S` in math mode. - -## [0.1.2] - 2021-02-18 - -### Fixed - -- Workaround for Firefox arrow minlength bug. - -### Removed - -- \overlinesegment & \underlinesegment - -## [0.1.1] - 2021-02-17 - -### Fixed - -- \overlinesegment & \underlinesegment SVGs - -### Changed - -- Removed Firefox browser sniff from CSS - -## [0.1.0] - 2021-02-01 - -### Added - -- Initial Release diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 676c8a47..00000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2020 Ron Kok - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index 021b08a1..00000000 --- a/README.md +++ /dev/null @@ -1,44 +0,0 @@ -*Temml* is a LaTeX-to-MathML JavaScript conversion utility. It is built to be lightweight. - -| Library | Minified JavaScript + CSS | -|:--------------|:-------------------------:| -| Temml | 142 KB | -| MathJax 2.7.5 | 338 KB | -| KaTeX | 280 KB | -| TeXZilla | 168 KB | - -As a futher advantage, Temml can use local system fonts. The minimum Temml installation serves a font file that is only 12kb. - -When the [MathML-in-Chromium](https://mathml.igalia.com/news/) project is complete, all the major browsers will support MathML and Temml will become the most lightweight way to render math in a browser. - -Temml’s coverage of LaTeX functions is as good as MathJax, slightly better than KaTeX 0.13.0 and substantially better than TeXZilla. See a [detailed coverage comparison](https://temml.org/docs/en/comparison.html). - -Temml's [test](https://temml.org/docs/en/supported.html) suite [includes](https://temml.org/tests/mozilla-tests.html) many [rendered](https://temml.org/tests/wiki-tests.html) examples [that](https://temml.org/tests/mhchem-tests.html) are [available](https://temml.org/tests/LaTeXML-tests.html) for viewing. - -Temml's demonstration page is at https://temml.org/ - -Documentation can be found at: - -* [Installation](https://temml.org/docs/en/administration.html) - -* LaTeX function support, [sorted into logical groups](https://temml.org/docs/en/supported.html). - -* LaTeX function support, [sorted alphabetically](https://temml.org/docs/en/support_table.html). - -### Acknowledgements - -I built Temml by: - -1. Forking [KaTeX](https://katex.org/). - -2. Deleting half the code, removing the HTML parts and keeping the parser, the macro expander, and the MathML parts. - -3. Doing some code refactoring and many MathML bug fixes. - -4. Adding new functionality: upright lower-case Greek letters, `\euro`, `\label{…}`, `\ref{…}`, `\longdiv{…}`, `\prescript`, `\definecolor`, `xcolor` color names, etc. - -I wish to thank Khan Academy and the many volunteer KaTeX contributors. This library would not exist if KaTeX had not existed first. - ---- - -Temml is released under terms of the [MIT license](https://mit-license.org/) diff --git a/contrib/auto-render/README.md b/contrib/auto-render/README.md deleted file mode 100644 index db7a1276..00000000 --- a/contrib/auto-render/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# Auto-render extension - -This is a client-side extension to automatically render all of the math inside of the -text of a running HTML document. It searches all of the text nodes in a given element -for the given delimiters, and renders the math in place. - - -This extension isn't part of Temml proper, so the script needs to be included -(via a ` - ... - - - - ... - - - ... - - -``` - -The auto-render extension exposes a single function, `window.renderMathInElement`, with -the following API: - -```js -function renderMathInElement(elem, options) -``` - -`elem` is an HTML DOM element, typically `document.main`. The function will -recursively search for text nodes inside this element and render the math in them. - -`options` is an optional object argument that can have the same keys as [the -options](https://temml.org/docs/en/administration.html#options) passed to -`temml.render`. In addition, there are five auto-render-specific keys: - -- `delimiters`: This is a list of delimiters to look for math, processed in - the same order as the list. Each delimiter has three properties: - - - `left`: A string which starts the math expression (i.e. the left delimiter). - - `right`: A string which ends the math expression (i.e. the right delimiter). - - `display`: A boolean of whether the math in the expression should be - rendered in display mode or not. - - The default `delimiters` value is: - - ```js - [ - { left: "$$", right: "$$", display: true }, - { left: "\\(", right: "\\)", display: false }, - { left: "\\begin{equation}", right: "\\end{equation}", display: true }, - { left: "\\begin{align}", right: "\\end{align}", display: true }, - { left: "\\begin{alignat}", right: "\\end{alignat}", display: true }, - { left: "\\begin{gather}", right: "\\end{gather}", display: true }, - { left: "\\begin{CD}", right: "\\end{CD}", display: true }, - { left: "\\begin{multline}", right: "\\end{multline}", display: true }, - { left: "\\[", right: "\\]", display: true } - ] - ``` - - If you want to add support for inline math via `$…$`, be sure to list it - **after** `$$…$$`. Because rules are processed in order, putting a `$` rule first would - match `$$` and treat as an empty math expression. Here is an example that includes `$…$`: - - ```js - [ - {left: "$$", right: "$$", display: true}, - // Put $ after $$. - {left: "$", right: "$", display: false}, - {left: "\\(", right: "\\)", display: false}, - // Put \[ last to avoid conflict with possible future \\[1em] row separator. - {left: "\\[", right: "\\]", display: true} - ] - ``` - -- `ignoredTags`: This is a list of DOM node types to ignore when recursing - through. The default value is - `["script", "noscript", "style", "textarea", "pre", "code", "option"]`. - -- `ignoredClasses`: This is a list of DOM node class names to ignore when - recursing through. By default, this value is not set. - -- `errorCallback`: A callback method returning a message and an error stack - in case of an critical error during rendering. The default uses `console.error`. - -- `preProcess`: A callback function, `(math: string) => string`, used to process - math expressions before rendering. diff --git a/contrib/auto-render/auto-render.js b/contrib/auto-render/auto-render.js deleted file mode 100644 index e0de5cad..00000000 --- a/contrib/auto-render/auto-render.js +++ /dev/null @@ -1,128 +0,0 @@ -/* eslint no-console:0 */ - -import temml from "temml"; -import splitAtDelimiters from "./splitAtDelimiters"; - -/* Note: optionsCopy is mutated by this method. If it is ever exposed in the - * API, we should copy it before mutating. - */ -const renderMathInText = function(text, optionsCopy) { - const data = splitAtDelimiters(text, optionsCopy.delimiters); - if (data.length === 1 && data[0].type === "text") { - // There is no formula in the text. - // Let's return null which means there is no need to replace - // the current text node with a new one. - return null; - } - - const fragment = document.createDocumentFragment(); - - for (let i = 0; i < data.length; i++) { - if (data[i].type === "text") { - fragment.appendChild(document.createTextNode(data[i].data)); - } else { - const span = document.createElement("span"); - let math = data[i].data; - // Override any display mode defined in the settings with that - // defined by the text itself - optionsCopy.displayMode = data[i].display; - try { - if (optionsCopy.preProcess) { - math = optionsCopy.preProcess(math); - } - temml.render(math, span, optionsCopy); - } catch (e) { - if (!(e instanceof temml.ParseError)) { - throw e; - } - optionsCopy.errorCallback( - "Temml auto-render: Failed to parse `" + data[i].data + "` with ", - e - ); - fragment.appendChild(document.createTextNode(data[i].rawData)); - continue; - } - fragment.appendChild(span); - } - } - - return fragment; -}; - -const renderElem = function(elem, optionsCopy) { - for (let i = 0; i < elem.childNodes.length; i++) { - const childNode = elem.childNodes[i]; - if (childNode.nodeType === 3) { - // Text node - const frag = renderMathInText(childNode.textContent, optionsCopy); - if (frag) { - i += frag.childNodes.length - 1; - elem.replaceChild(frag, childNode); - } - } else if (childNode.nodeType === 1) { - // Element node - const className = " " + childNode.className + " "; - const shouldRender = - optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) === -1 && - optionsCopy.ignoredClasses.every((x) => className.indexOf(" " + x + " ") === -1); - - if (shouldRender) { - renderElem(childNode, optionsCopy); - } - } - // Otherwise, it's something else, and ignore it. - } -}; - -const renderMathInElement = function(elem, options) { - if (!elem) { - throw new Error("No element provided to render"); - } - - const optionsCopy = {}; - - // Object.assign(optionsCopy, option) - for (const option in options) { - if (Object.prototype.hasOwnProperty.call(options, option)) { - optionsCopy[option] = options[option]; - } - } - - // default options - optionsCopy.delimiters = optionsCopy.delimiters || [ - { left: "$$", right: "$$", display: true }, - { left: "\\(", right: "\\)", display: false }, - // LaTeX uses $…$, but it ruins the display of normal `$` in text: - // {left: "$", right: "$", display: false}, - // $ must come after $$ - - // Render AMS environments even if outside $$…$$ delimiters. - { left: "\\begin{equation}", right: "\\end{equation}", display: true }, - { left: "\\begin{align}", right: "\\end{align}", display: true }, - { left: "\\begin{alignat}", right: "\\end{alignat}", display: true }, - { left: "\\begin{gather}", right: "\\end{gather}", display: true }, - { left: "\\begin{CD}", right: "\\end{CD}", display: true }, - - { left: "\\[", right: "\\]", display: true } - ]; - optionsCopy.ignoredTags = optionsCopy.ignoredTags || [ - "script", - "noscript", - "style", - "textarea", - "pre", - "code", - "option" - ]; - optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || []; - optionsCopy.errorCallback = optionsCopy.errorCallback || console.error; - - // Enable sharing of global macros defined via `\gdef` between different - // math elements within a single call to `renderMathInElement`. - optionsCopy.macros = optionsCopy.macros || {}; - - renderElem(elem, optionsCopy); - temml.postProcess(elem); -}; - -export default renderMathInElement; diff --git a/contrib/auto-render/dist/auto-render.js b/contrib/auto-render/dist/auto-render.js deleted file mode 100644 index 3848e38f..00000000 --- a/contrib/auto-render/dist/auto-render.js +++ /dev/null @@ -1,217 +0,0 @@ -var renderMathInElement = (function (temml) { - 'use strict'; - - function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } - - var temml__default = /*#__PURE__*/_interopDefaultLegacy(temml); - - /* eslint no-constant-condition:0 */ - const findEndOfMath = function(delimiter, text, startIndex) { - // Adapted from - // https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx - let index = startIndex; - let braceLevel = 0; - - const delimLength = delimiter.length; - - while (index < text.length) { - const character = text[index]; - - if (braceLevel <= 0 && text.slice(index, index + delimLength) === delimiter) { - return index; - } else if (character === "\\") { - index++; - } else if (character === "{") { - braceLevel++; - } else if (character === "}") { - braceLevel--; - } - - index++; - } - - return -1; - }; - - const escapeRegex = function(string) { - return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"); - }; - - const amsRegex = /^\\begin{/; - - const splitAtDelimiters = function(text, delimiters) { - let index; - const data = []; - - const regexLeft = new RegExp( - "(" + delimiters.map((x) => escapeRegex(x.left)).join("|") + ")" - ); - - while (true) { - index = text.search(regexLeft); - if (index === -1) { - break; - } - if (index > 0) { - data.push({ - type: "text", - data: text.slice(0, index) - }); - text = text.slice(index); // now text starts with delimiter - } - // ... so this always succeeds: - const i = delimiters.findIndex((delim) => text.startsWith(delim.left)); - index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length); - if (index === -1) { - break; - } - const rawData = text.slice(0, index + delimiters[i].right.length); - const math = amsRegex.test(rawData) - ? rawData - : text.slice(delimiters[i].left.length, index); - data.push({ - type: "math", - data: math, - rawData, - display: delimiters[i].display - }); - text = text.slice(index + delimiters[i].right.length); - } - - if (text !== "") { - data.push({ - type: "text", - data: text - }); - } - - return data; - }; - - /* eslint no-console:0 */ - - /* Note: optionsCopy is mutated by this method. If it is ever exposed in the - * API, we should copy it before mutating. - */ - const renderMathInText = function(text, optionsCopy) { - const data = splitAtDelimiters(text, optionsCopy.delimiters); - if (data.length === 1 && data[0].type === "text") { - // There is no formula in the text. - // Let's return null which means there is no need to replace - // the current text node with a new one. - return null; - } - - const fragment = document.createDocumentFragment(); - - for (let i = 0; i < data.length; i++) { - if (data[i].type === "text") { - fragment.appendChild(document.createTextNode(data[i].data)); - } else { - const span = document.createElement("span"); - let math = data[i].data; - // Override any display mode defined in the settings with that - // defined by the text itself - optionsCopy.displayMode = data[i].display; - try { - if (optionsCopy.preProcess) { - math = optionsCopy.preProcess(math); - } - temml__default["default"].render(math, span, optionsCopy); - } catch (e) { - if (!(e instanceof temml__default["default"].ParseError)) { - throw e; - } - optionsCopy.errorCallback( - "Temml auto-render: Failed to parse `" + data[i].data + "` with ", - e - ); - fragment.appendChild(document.createTextNode(data[i].rawData)); - continue; - } - fragment.appendChild(span); - } - } - - return fragment; - }; - - const renderElem = function(elem, optionsCopy) { - for (let i = 0; i < elem.childNodes.length; i++) { - const childNode = elem.childNodes[i]; - if (childNode.nodeType === 3) { - // Text node - const frag = renderMathInText(childNode.textContent, optionsCopy); - if (frag) { - i += frag.childNodes.length - 1; - elem.replaceChild(frag, childNode); - } - } else if (childNode.nodeType === 1) { - // Element node - const className = " " + childNode.className + " "; - const shouldRender = - optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) === -1 && - optionsCopy.ignoredClasses.every((x) => className.indexOf(" " + x + " ") === -1); - - if (shouldRender) { - renderElem(childNode, optionsCopy); - } - } - // Otherwise, it's something else, and ignore it. - } - }; - - const renderMathInElement = function(elem, options) { - if (!elem) { - throw new Error("No element provided to render"); - } - - const optionsCopy = {}; - - // Object.assign(optionsCopy, option) - for (const option in options) { - if (Object.prototype.hasOwnProperty.call(options, option)) { - optionsCopy[option] = options[option]; - } - } - - // default options - optionsCopy.delimiters = optionsCopy.delimiters || [ - { left: "$$", right: "$$", display: true }, - { left: "\\(", right: "\\)", display: false }, - // LaTeX uses $…$, but it ruins the display of normal `$` in text: - // {left: "$", right: "$", display: false}, - // $ must come after $$ - - // Render AMS environments even if outside $$…$$ delimiters. - { left: "\\begin{equation}", right: "\\end{equation}", display: true }, - { left: "\\begin{align}", right: "\\end{align}", display: true }, - { left: "\\begin{alignat}", right: "\\end{alignat}", display: true }, - { left: "\\begin{gather}", right: "\\end{gather}", display: true }, - { left: "\\begin{CD}", right: "\\end{CD}", display: true }, - - { left: "\\[", right: "\\]", display: true } - ]; - optionsCopy.ignoredTags = optionsCopy.ignoredTags || [ - "script", - "noscript", - "style", - "textarea", - "pre", - "code", - "option" - ]; - optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || []; - optionsCopy.errorCallback = optionsCopy.errorCallback || console.error; - - // Enable sharing of global macros defined via `\gdef` between different - // math elements within a single call to `renderMathInElement`. - optionsCopy.macros = optionsCopy.macros || {}; - - renderElem(elem, optionsCopy); - temml__default["default"].postProcess(elem); - }; - - return renderMathInElement; - -})(temml); diff --git a/contrib/auto-render/dist/auto-render.min.js b/contrib/auto-render/dist/auto-render.min.js deleted file mode 100644 index 55bcd20c..00000000 --- a/contrib/auto-render/dist/auto-render.min.js +++ /dev/null @@ -1 +0,0 @@ -var renderMathInElement=function(e){"use strict";function t(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n=t(e);const r=function(e,t,n){let r=n,a=0;const i=e.length;for(;re.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"))).join("|")+")");for(;n=e.search(l),-1!==n;){n>0&&(i.push({type:"text",data:e.slice(0,n)}),e=e.slice(n));const l=t.findIndex((t=>e.startsWith(t.left)));if(n=r(t[l].right,e,t[l].left.length),-1===n)break;const o=e.slice(0,n+t[l].right.length),s=a.test(o)?o:e.slice(t[l].left.length,n);i.push({type:"math",data:s,rawData:o,display:t[l].display}),e=e.slice(n+t[l].right.length)}return""!==e&&i.push({type:"text",data:e}),i}(e,t.delimiters);if(1===i.length&&"text"===i[0].type)return null;const l=document.createDocumentFragment();for(let e=0;e-1===e.indexOf(" "+t+" ")))&&l(r,t)}}};return function(e,t){if(!e)throw new Error("No element provided to render");const r={};for(const e in t)Object.prototype.hasOwnProperty.call(t,e)&&(r[e]=t[e]);r.delimiters=r.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\begin{equation}",right:"\\end{equation}",display:!0},{left:"\\begin{align}",right:"\\end{align}",display:!0},{left:"\\begin{alignat}",right:"\\end{alignat}",display:!0},{left:"\\begin{gather}",right:"\\end{gather}",display:!0},{left:"\\begin{CD}",right:"\\end{CD}",display:!0},{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||{},l(e,r),n.default.postProcess(e)}}(temml); \ No newline at end of file diff --git a/contrib/auto-render/splitAtDelimiters.js b/contrib/auto-render/splitAtDelimiters.js deleted file mode 100644 index 0c93c13a..00000000 --- a/contrib/auto-render/splitAtDelimiters.js +++ /dev/null @@ -1,84 +0,0 @@ -/* eslint no-constant-condition:0 */ -const findEndOfMath = function(delimiter, text, startIndex) { - // Adapted from - // https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx - let index = startIndex; - let braceLevel = 0; - - const delimLength = delimiter.length; - - while (index < text.length) { - const character = text[index]; - - if (braceLevel <= 0 && text.slice(index, index + delimLength) === delimiter) { - return index; - } else if (character === "\\") { - index++; - } else if (character === "{") { - braceLevel++; - } else if (character === "}") { - braceLevel--; - } - - index++; - } - - return -1; -}; - -const escapeRegex = function(string) { - return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"); -}; - -const amsRegex = /^\\begin{/; - -const splitAtDelimiters = function(text, delimiters) { - let index; - const data = []; - - const regexLeft = new RegExp( - "(" + delimiters.map((x) => escapeRegex(x.left)).join("|") + ")" - ) - - while (true) { - index = text.search(regexLeft); - if (index === -1) { - break; - } - if (index > 0) { - data.push({ - type: "text", - data: text.slice(0, index) - }); - text = text.slice(index); // now text starts with delimiter - } - // ... so this always succeeds: - const i = delimiters.findIndex((delim) => text.startsWith(delim.left)); - index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length); - if (index === -1) { - break; - } - const rawData = text.slice(0, index + delimiters[i].right.length); - const math = amsRegex.test(rawData) - ? rawData - : text.slice(delimiters[i].left.length, index); - data.push({ - type: "math", - data: math, - rawData, - display: delimiters[i].display - }); - text = text.slice(index + delimiters[i].right.length); - } - - if (text !== "") { - data.push({ - type: "text", - data: text - }); - } - - return data; -}; - -export default splitAtDelimiters; diff --git a/contrib/auto-render/test/auto-render-spec.js b/contrib/auto-render/test/auto-render-spec.js deleted file mode 100644 index 3875bfb1..00000000 --- a/contrib/auto-render/test/auto-render-spec.js +++ /dev/null @@ -1,234 +0,0 @@ -/* global beforeEach: false */ -/* global expect: false */ -/* global it: false */ -/* global describe: false */ - -import splitAtDelimiters from "../splitAtDelimiters"; -import renderMathInElement from "../auto-render"; - -beforeEach(function() { - expect.extend({ - toSplitInto: function(actual, left, right, result) { - const message = { - pass: true, - message: "'" + actual + "' split correctly" - }; - - const startData = [{ type: "text", data: actual }]; - - const split = splitAtDelimiters(startData, left, right, false); - - if (split.length !== result.length) { - message.pass = false; - message.message = - "Different number of splits: " + - split.length + - " vs. " + - result.length + - " (" + - JSON.stringify(split) + - " vs. " + - JSON.stringify(result) + - ")"; - return message; - } - - for (let i = 0; i < split.length; i++) { - const real = split[i]; - const correct = result[i]; - - let good = true; - let diff; - - if (real.type !== correct.type) { - good = false; - diff = "type"; - } else if (real.data !== correct.data) { - good = false; - diff = "data"; - } else if (real.display !== correct.display) { - good = false; - diff = "display"; - } - - if (!good) { - message.pass = false; - message.message = - "Difference at split " + - (i + 1) + - ": " + - JSON.stringify(real) + - " vs. " + - JSON.stringify(correct) + - " (" + - diff + - " differs)"; - break; - } - } - - return message; - } - }); -}); - -describe("A delimiter splitter", function() { - it("doesn't split when there are no delimiters", function() { - expect("hello").toSplitInto("(", ")", [{ type: "text", data: "hello" }]); - }); - - it("doesn't create a math node with only one left delimiter", function() { - expect("hello ( world").toSplitInto("(", ")", [ - { type: "text", data: "hello " }, - { type: "text", data: "( world" } - ]); - }); - - it("doesn't split when there's only a right delimiter", function() { - expect("hello ) world").toSplitInto("(", ")", [{ type: "text", data: "hello ) world" }]); - }); - - it("splits when there are both delimiters", function() { - expect("hello ( world ) boo").toSplitInto("(", ")", [ - { type: "text", data: "hello " }, - { type: "math", data: " world ", rawData: "( world )", display: false }, - { type: "text", data: " boo" } - ]); - }); - - it("splits on multi-character delimiters", function() { - expect("hello [[ world ]] boo").toSplitInto("[[", "]]", [ - { type: "text", data: "hello " }, - { type: "math", data: " world ", rawData: "[[ world ]]", display: false }, - { type: "text", data: " boo" } - ]); - }); - - it("splits mutliple times", function() { - expect("hello ( world ) boo ( more ) stuff").toSplitInto("(", ")", [ - { type: "text", data: "hello " }, - { type: "math", data: " world ", rawData: "( world )", display: false }, - { type: "text", data: " boo " }, - { type: "math", data: " more ", rawData: "( more )", display: false }, - { type: "text", data: " stuff" } - ]); - }); - - it("leaves the ending when there's only a left delimiter", function() { - expect("hello ( world ) boo ( left").toSplitInto("(", ")", [ - { type: "text", data: "hello " }, - { type: "math", data: " world ", rawData: "( world )", display: false }, - { type: "text", data: " boo " }, - { type: "text", data: "( left" } - ]); - }); - - it("doesn't split when close delimiters are in {}s", function() { - expect("hello ( world { ) } ) boo").toSplitInto("(", ")", [ - { type: "text", data: "hello " }, - { type: "math", data: " world { ) } ", rawData: "( world { ) } )", display: false }, - { type: "text", data: " boo" } - ]); - - expect("hello ( world { { } ) } ) boo").toSplitInto("(", ")", [ - { type: "text", data: "hello " }, - { type: "math", data: " world { { } ) } ", rawData: "( world { { } ) } )", display: false }, - { type: "text", data: " boo" } - ]); - }); - - it("doesn't split at escaped delimiters", function() { - expect("hello ( world \\) ) boo").toSplitInto("(", ")", [ - { type: "text", data: "hello " }, - { type: "math", data: " world \\) ", rawData: "( world \\) )", display: false }, - { type: "text", data: " boo" } - ]); - - /* TODO(emily): make this work maybe? - expect("hello \\( ( world ) boo").toSplitInto( - "(", ")", - [ - {type: "text", data: "hello \\( "}, - {type: "math", data: " world ", - rawData: "( world )", display: false}, - {type: "text", data: " boo"}, - ]); - */ - }); - - it("splits when the right and left delimiters are the same", function() { - expect("hello $ world $ boo").toSplitInto("$", "$", [ - { type: "text", data: "hello " }, - { type: "math", data: " world ", rawData: "$ world $", display: false }, - { type: "text", data: " boo" } - ]); - }); - - it("remembers which delimiters are display-mode", function() { - const startData = [{ type: "text", data: "hello ( world ) boo" }]; - - expect(splitAtDelimiters(startData, "(", ")", true)).toEqual([ - { type: "text", data: "hello " }, - { type: "math", data: " world ", rawData: "( world )", display: true }, - { type: "text", data: " boo" } - ]); - }); - - it("works with more than one start datum", function() { - const startData = [ - { type: "text", data: "hello ( world ) boo" }, - { type: "math", data: "math", rawData: "(math)", display: true }, - { type: "text", data: "hello ( world ) boo" } - ]; - - expect(splitAtDelimiters(startData, "(", ")", false)).toEqual([ - { type: "text", data: "hello " }, - { type: "math", data: " world ", rawData: "( world )", display: false }, - { type: "text", data: " boo" }, - { type: "math", data: "math", rawData: "(math)", display: true }, - { type: "text", data: "hello " }, - { type: "math", data: " world ", rawData: "( world )", display: false }, - { type: "text", data: " boo" } - ]); - }); - - it("doesn't do splitting inside of math nodes", function() { - const startData = [ - { type: "text", data: "hello ( world ) boo" }, - { - type: "math", - data: "hello ( world ) boo", - rawData: "(hello ( world ) boo)", - display: true - } - ]; - - expect(splitAtDelimiters(startData, "(", ")", false)).toEqual([ - { type: "text", data: "hello " }, - { type: "math", data: " world ", rawData: "( world )", display: false }, - { type: "text", data: " boo" }, - { - type: "math", - data: "hello ( world ) boo", - rawData: "(hello ( world ) boo)", - display: true - } - ]); - }); -}); - -describe("Pre-process callback", function() { - it("replace `-squared` with `^2 `", function() { - const el1 = document.createElement("div"); - el1.textContent = "Circle equation: $x-squared + y-squared = r-squared$."; - const el2 = document.createElement("div"); - el2.textContent = "Circle equation: $x^2 + y^2 = r^2$."; - const delimiters = [{ left: "$", right: "$", display: false }]; - renderMathInElement(el1, { - delimiters, - preProcess: (math) => math.replace(/-squared/g, "^2") - }); - renderMathInElement(el2, { delimiters }); - expect(el1.innerHTML).toEqual(el2.innerHTML); - }); -}); diff --git a/contrib/auto-render/test/auto-render.js b/contrib/auto-render/test/auto-render.js deleted file mode 100644 index 3848e38f..00000000 --- a/contrib/auto-render/test/auto-render.js +++ /dev/null @@ -1,217 +0,0 @@ -var renderMathInElement = (function (temml) { - 'use strict'; - - function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } - - var temml__default = /*#__PURE__*/_interopDefaultLegacy(temml); - - /* eslint no-constant-condition:0 */ - const findEndOfMath = function(delimiter, text, startIndex) { - // Adapted from - // https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx - let index = startIndex; - let braceLevel = 0; - - const delimLength = delimiter.length; - - while (index < text.length) { - const character = text[index]; - - if (braceLevel <= 0 && text.slice(index, index + delimLength) === delimiter) { - return index; - } else if (character === "\\") { - index++; - } else if (character === "{") { - braceLevel++; - } else if (character === "}") { - braceLevel--; - } - - index++; - } - - return -1; - }; - - const escapeRegex = function(string) { - return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"); - }; - - const amsRegex = /^\\begin{/; - - const splitAtDelimiters = function(text, delimiters) { - let index; - const data = []; - - const regexLeft = new RegExp( - "(" + delimiters.map((x) => escapeRegex(x.left)).join("|") + ")" - ); - - while (true) { - index = text.search(regexLeft); - if (index === -1) { - break; - } - if (index > 0) { - data.push({ - type: "text", - data: text.slice(0, index) - }); - text = text.slice(index); // now text starts with delimiter - } - // ... so this always succeeds: - const i = delimiters.findIndex((delim) => text.startsWith(delim.left)); - index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length); - if (index === -1) { - break; - } - const rawData = text.slice(0, index + delimiters[i].right.length); - const math = amsRegex.test(rawData) - ? rawData - : text.slice(delimiters[i].left.length, index); - data.push({ - type: "math", - data: math, - rawData, - display: delimiters[i].display - }); - text = text.slice(index + delimiters[i].right.length); - } - - if (text !== "") { - data.push({ - type: "text", - data: text - }); - } - - return data; - }; - - /* eslint no-console:0 */ - - /* Note: optionsCopy is mutated by this method. If it is ever exposed in the - * API, we should copy it before mutating. - */ - const renderMathInText = function(text, optionsCopy) { - const data = splitAtDelimiters(text, optionsCopy.delimiters); - if (data.length === 1 && data[0].type === "text") { - // There is no formula in the text. - // Let's return null which means there is no need to replace - // the current text node with a new one. - return null; - } - - const fragment = document.createDocumentFragment(); - - for (let i = 0; i < data.length; i++) { - if (data[i].type === "text") { - fragment.appendChild(document.createTextNode(data[i].data)); - } else { - const span = document.createElement("span"); - let math = data[i].data; - // Override any display mode defined in the settings with that - // defined by the text itself - optionsCopy.displayMode = data[i].display; - try { - if (optionsCopy.preProcess) { - math = optionsCopy.preProcess(math); - } - temml__default["default"].render(math, span, optionsCopy); - } catch (e) { - if (!(e instanceof temml__default["default"].ParseError)) { - throw e; - } - optionsCopy.errorCallback( - "Temml auto-render: Failed to parse `" + data[i].data + "` with ", - e - ); - fragment.appendChild(document.createTextNode(data[i].rawData)); - continue; - } - fragment.appendChild(span); - } - } - - return fragment; - }; - - const renderElem = function(elem, optionsCopy) { - for (let i = 0; i < elem.childNodes.length; i++) { - const childNode = elem.childNodes[i]; - if (childNode.nodeType === 3) { - // Text node - const frag = renderMathInText(childNode.textContent, optionsCopy); - if (frag) { - i += frag.childNodes.length - 1; - elem.replaceChild(frag, childNode); - } - } else if (childNode.nodeType === 1) { - // Element node - const className = " " + childNode.className + " "; - const shouldRender = - optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) === -1 && - optionsCopy.ignoredClasses.every((x) => className.indexOf(" " + x + " ") === -1); - - if (shouldRender) { - renderElem(childNode, optionsCopy); - } - } - // Otherwise, it's something else, and ignore it. - } - }; - - const renderMathInElement = function(elem, options) { - if (!elem) { - throw new Error("No element provided to render"); - } - - const optionsCopy = {}; - - // Object.assign(optionsCopy, option) - for (const option in options) { - if (Object.prototype.hasOwnProperty.call(options, option)) { - optionsCopy[option] = options[option]; - } - } - - // default options - optionsCopy.delimiters = optionsCopy.delimiters || [ - { left: "$$", right: "$$", display: true }, - { left: "\\(", right: "\\)", display: false }, - // LaTeX uses $…$, but it ruins the display of normal `$` in text: - // {left: "$", right: "$", display: false}, - // $ must come after $$ - - // Render AMS environments even if outside $$…$$ delimiters. - { left: "\\begin{equation}", right: "\\end{equation}", display: true }, - { left: "\\begin{align}", right: "\\end{align}", display: true }, - { left: "\\begin{alignat}", right: "\\end{alignat}", display: true }, - { left: "\\begin{gather}", right: "\\end{gather}", display: true }, - { left: "\\begin{CD}", right: "\\end{CD}", display: true }, - - { left: "\\[", right: "\\]", display: true } - ]; - optionsCopy.ignoredTags = optionsCopy.ignoredTags || [ - "script", - "noscript", - "style", - "textarea", - "pre", - "code", - "option" - ]; - optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || []; - optionsCopy.errorCallback = optionsCopy.errorCallback || console.error; - - // Enable sharing of global macros defined via `\gdef` between different - // math elements within a single call to `renderMathInElement`. - optionsCopy.macros = optionsCopy.macros || {}; - - renderElem(elem, optionsCopy); - temml__default["default"].postProcess(elem); - }; - - return renderMathInElement; - -})(temml); diff --git a/contrib/auto-render/test/test_page.html b/contrib/auto-render/test/test_page.html deleted file mode 100644 index 04172f26..00000000 --- a/contrib/auto-render/test/test_page.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - Auto-render test - - - - - - -
- This is some text $math \frac12$ other text - - Other node \[ displaymath \frac{1}{2} \] blah $$ \int_2^3 $$ - - and some more text \(and math\) blah. And $math with a - \$ sign$. -
-        Stuff in a $pre tag$
-      
-

An AMS environment without $$…$$ delimiters.

-

\begin{equation}\begin{split} a &=b+c\\ &=e+f \end{split} \end{equation}

-

$\unsupported$

-
- - - diff --git a/contrib/mhchem/README.md b/contrib/mhchem/README.md deleted file mode 100644 index b81ffcfa..00000000 --- a/contrib/mhchem/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# mhchem extension - -This extension adds to Temml the `\ce` and `\pu` functions from the [mhchem](https://mhchem.github.io/MathJax-mhchem/) package. - -You can download the `mhchem.min.js` file from this repository. - -### Usage - -This extension isn't part of core Temml, so the script should be separately included. Write the following line into the HTML page's ``. Place it _after_ the line that calls `temml.js`. - -```html - - -``` - -If you are working sever-side, just use `temml.cjs`. It already includes all the functions in `mhchem.js`. - -### Syntax - -See the [mhchem Manual](https://mhchem.github.io/MathJax-mhchem/) for a full explanation of the input syntax, with working examples. The manual also includes a demonstration box. - -Note that old versions of `mhchem.sty` used `\cf` for chemical formula and `\ce` for chemical equations, but `\cf` has been deprecated in place of `\ce`. This extension supports only `\ce`. You can define a macro mapping `\cf` to `\ce` if needed. - -### Browser Support - -This extension has been tested on Chrome, Firefox, Opera, and Edge. diff --git a/contrib/mhchem/mhchem.js b/contrib/mhchem/mhchem.js deleted file mode 100644 index 6e507ce7..00000000 --- a/contrib/mhchem/mhchem.js +++ /dev/null @@ -1,1705 +0,0 @@ -/* eslint-disable */ -/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ - -/************************************************************* - * - * Temml mhchem.js - * - * This file implements a Temml version of mhchem version 3.3.0. - * It is adapted from MathJax/extensions/TeX/mhchem.js - * It differs from the MathJax version as follows: - * 1. The interface is changed so that it can be called from Temml, not MathJax. - * 2. \rlap and \llap are replaced with \mathrlap and \mathllap. - * 3. The reaction arrow code is simplified. All reaction arrows are rendered - * using Temml extensible arrows instead of building non-extensible arrows. - * 4. The ~bond forms are composed entirely of \rule elements. - * 5. Two dashes in _getBond are wrapped in braces to suppress spacing. i.e., {-} - * 6. The electron dot uses \textbullet instead of \bullet. - * - * This code, as other Temml code, is released under the MIT license. - * - * /************************************************************* - * - * MathJax/extensions/TeX/mhchem.js - * - * Implements the \ce command for handling chemical formulas - * from the mhchem LaTeX package. - * - * --------------------------------------------------------------------- - * - * Copyright (c) 2011-2015 The MathJax Consortium - * Copyright (c) 2015-2018 Martin Hensel - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Coding Style -// - use '' for identifiers that can by minified/uglified -// - use "" for strings that need to stay untouched - -// version: "3.3.0" for MathJax and Temml - - -// Add \ce, \pu, and \tripleDash to the Temml macros. - -temml.__defineMacro("\\ce", function(context) { - return chemParse(context.consumeArgs(1)[0], "ce") -}); - -temml.__defineMacro("\\pu", function(context) { - return chemParse(context.consumeArgs(1)[0], "pu"); -}); - -// Math fonts do not include glyphs for the ~ form of bonds. So we'll send path geometry -// So we'll compose characters built from \rule elements. -temml.__defineMacro("\\uniDash", `{\\rule{0.672em}{0.06em}}`) -temml.__defineMacro("\\triDash", `{\\rule{0.15em}{0.06em}\\kern2mu\\rule{0.15em}{0.06em}\\kern2mu\\rule{0.15em}{0.06em}}`) -temml.__defineMacro("\\tripleDash", `\\kern0.075em\\raise0.25em{\\triDash}\\kern0.075em`) -temml.__defineMacro("\\tripleDashOverLine", `\\kern0.075em\\mathrlap{\\raise0.125em{\\uniDash}}\\raise0.34em{\\triDash}\\kern0.075em`) -temml.__defineMacro("\\tripleDashOverDoubleLine", `\\kern0.075em\\mathrlap{\\mathrlap{\\raise0.48em{\\triDash}}\\raise0.27em{\\uniDash}}{\\raise0.05em{\\uniDash}}\\kern0.075em`) -temml.__defineMacro("\\tripleDashBetweenDoubleLine", `\\kern0.075em\\mathrlap{\\mathrlap{\\raise0.48em{\\uniDash}}\\raise0.27em{\\triDash}}{\\raise0.05em{\\uniDash}}\\kern0.075em`) - - // - // This is the main function for handing the \ce and \pu commands. - // It takes the argument to \ce or \pu and returns the corresponding TeX string. - // - - var chemParse = function (tokens, stateMachine) { - // Recreate the argument string from Temml's array of tokens. - var str = ""; - var expectedLoc = tokens.length && tokens[tokens.length - 1].loc.start - for (var i = tokens.length - 1; i >= 0; i--) { - if(tokens[i].loc.start > expectedLoc) { - // context.consumeArgs has eaten a space. - str += " "; - expectedLoc = tokens[i].loc.start; - } - str += tokens[i].text; - expectedLoc += tokens[i].text.length; - } - // Call the mhchem core parser. - var tex = texify.go(mhchemParser.go(str, stateMachine)); - return tex; - }; - - // - // Core parser for mhchem syntax (recursive) - // - /** @type {MhchemParser} */ - var mhchemParser = { - // - // Parses mchem \ce syntax - // - // Call like - // go("H2O"); - // - go: function (input, stateMachine) { - if (!input) { return []; } - if (stateMachine === undefined) { stateMachine = 'ce'; } - var state = '0'; - - // - // String buffers for parsing: - // - // buffer.a == amount - // buffer.o == element - // buffer.b == left-side superscript - // buffer.p == left-side subscript - // buffer.q == right-side subscript - // buffer.d == right-side superscript - // - // buffer.r == arrow - // buffer.rdt == arrow, script above, type - // buffer.rd == arrow, script above, content - // buffer.rqt == arrow, script below, type - // buffer.rq == arrow, script below, content - // - // buffer.text_ - // buffer.rm - // etc. - // - // buffer.parenthesisLevel == int, starting at 0 - // buffer.sb == bool, space before - // buffer.beginsWithBond == bool - // - // These letters are also used as state names. - // - // Other states: - // 0 == begin of main part (arrow/operator unlikely) - // 1 == next entity - // 2 == next entity (arrow/operator unlikely) - // 3 == next atom - // c == macro - // - /** @type {Buffer} */ - var buffer = {}; - buffer['parenthesisLevel'] = 0; - - input = input.replace(/\n/g, " "); - input = input.replace(/[\u2212\u2013\u2014\u2010]/g, "-"); - input = input.replace(/[\u2026]/g, "..."); - - // - // Looks through mhchemParser.transitions, to execute a matching action - // (recursive) - // - var lastInput; - var watchdog = 10; - /** @type {ParserOutput[]} */ - var output = []; - while (true) { - if (lastInput !== input) { - watchdog = 10; - lastInput = input; - } else { - watchdog--; - } - // - // Find actions in transition table - // - var machine = mhchemParser.stateMachines[stateMachine]; - var t = machine.transitions[state] || machine.transitions['*']; - iterateTransitions: - for (var i=0; i 0) { - if (!task.revisit) { - input = matches.remainder; - } - if (!task.toContinue) { - break iterateTransitions; - } - } else { - return output; - } - } - } - // - // Prevent infinite loop - // - if (watchdog <= 0) { - throw ["MhchemBugU", "mhchem bug U. Please report."]; // Unexpected character - } - } - }, - concatArray: function (a, b) { - if (b) { - if (Array.isArray(b)) { - for (var iB=0; iB': /^[=<>]/, - '#': /^[#\u2261]/, - '+': /^\+/, - '-$': /^-(?=[\s_},;\]/]|$|\([a-z]+\))/, // -space -, -; -] -/ -$ -state-of-aggregation - '-9': /^-(?=[0-9])/, - '- orbital overlap': /^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/, - '-': /^-/, - 'pm-operator': /^(?:\\pm|\$\\pm\$|\+-|\+\/-)/, - 'operator': /^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/, - 'arrowUpDown': /^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/, - '\\bond{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\bond{", "", "", "}"); }, - '->': /^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/, - 'CMT': /^[CMT](?=\[)/, - '[(...)]': function (input) { return mhchemParser.patterns.findObserveGroups(input, "[", "", "", "]"); }, - '1st-level escape': /^(&|\\\\|\\hline)\s*/, - '\\,': /^(?:\\[,\ ;:])/, // \\x - but output no space before - '\\x{}{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); }, - '\\x{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", ""); }, - '\\ca': /^\\ca(?:\s+|(?![a-zA-Z]))/, - '\\x': /^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/, - 'orbital': /^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/, // only those with numbers in front, because the others will be formatted correctly anyway - 'others': /^[\/~|]/, - '\\frac{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\frac{", "", "", "}", "{", "", "", "}"); }, - '\\overset{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\overset{", "", "", "}", "{", "", "", "}"); }, - '\\underset{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\underset{", "", "", "}", "{", "", "", "}"); }, - '\\underbrace{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\underbrace{", "", "", "}_", "{", "", "", "}"); }, - '\\color{(...)}0': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}"); }, - '\\color{(...)}{(...)}1': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}", "{", "", "", "}"); }, - '\\color(...){(...)}2': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color", "\\", "", /^(?=\{)/, "{", "", "", "}"); }, - '\\ce{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\ce{", "", "", "}"); }, - 'oxidation$': /^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, - 'd-oxidation$': /^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, // 0 could be oxidation or charge - 'roman numeral': /^[IVX]+/, - '1/2$': /^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/, - 'amount': function (input) { - var match; - // e.g. 2, 0.5, 1/2, -2, n/2, +; $a$ could be added later in parsing - match = input.match(/^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/); - if (match) { - return { match_: match[0], remainder: input.substr(match[0].length) }; - } - var a = mhchemParser.patterns.findObserveGroups(input, "", "$", "$", ""); - if (a) { // e.g. $2n-1$, $-$ - match = a.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/); - if (match) { - return { match_: match[0], remainder: input.substr(match[0].length) }; - } - } - return null; - }, - 'amount2': function (input) { return this['amount'](input); }, - '(KV letters),': /^(?:[A-Z][a-z]{0,2}|i)(?=,)/, - 'formula$': function (input) { - if (input.match(/^\([a-z]+\)$/)) { return null; } // state of aggregation = no formula - var match = input.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/); - if (match) { - return { match_: match[0], remainder: input.substr(match[0].length) }; - } - return null; - }, - 'uprightEntities': /^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/, - '/': /^\s*(\/)\s*/, - '//': /^\s*(\/\/)\s*/, - '*': /^\s*[*.]\s*/ - }, - findObserveGroups: function (input, begExcl, begIncl, endIncl, endExcl, beg2Excl, beg2Incl, end2Incl, end2Excl, combine) { - /** @type {{(input: string, pattern: string | RegExp): string | string[] | null;}} */ - var _match = function (input, pattern) { - if (typeof pattern === "string") { - if (input.indexOf(pattern) !== 0) { return null; } - return pattern; - } else { - var match = input.match(pattern); - if (!match) { return null; } - return match[0]; - } - }; - /** @type {{(input: string, i: number, endChars: string | RegExp): {endMatchBegin: number, endMatchEnd: number} | null;}} */ - var _findObserveGroups = function (input, i, endChars) { - var braces = 0; - while (i < input.length) { - var a = input.charAt(i); - var match = _match(input.substr(i), endChars); - if (match !== null && braces === 0) { - return { endMatchBegin: i, endMatchEnd: i + match.length }; - } else if (a === "{") { - braces++; - } else if (a === "}") { - if (braces === 0) { - throw ["ExtraCloseMissingOpen", "Extra close brace or missing open brace"]; - } else { - braces--; - } - } - i++; - } - if (braces > 0) { - return null; - } - return null; - }; - var match = _match(input, begExcl); - if (match === null) { return null; } - input = input.substr(match.length); - match = _match(input, begIncl); - if (match === null) { return null; } - var e = _findObserveGroups(input, match.length, endIncl || endExcl); - if (e === null) { return null; } - var match1 = input.substring(0, (endIncl ? e.endMatchEnd : e.endMatchBegin)); - if (!(beg2Excl || beg2Incl)) { - return { - match_: match1, - remainder: input.substr(e.endMatchEnd) - }; - } else { - var group2 = this.findObserveGroups(input.substr(e.endMatchEnd), beg2Excl, beg2Incl, end2Incl, end2Excl); - if (group2 === null) { return null; } - /** @type {string[]} */ - var matchRet = [match1, group2.match_]; - return { - match_: (combine ? matchRet.join("") : matchRet), - remainder: group2.remainder - }; - } - }, - - // - // Matching function - // e.g. match("a", input) will look for the regexp called "a" and see if it matches - // returns null or {match_:"a", remainder:"bc"} - // - match_: function (m, input) { - var pattern = mhchemParser.patterns.patterns[m]; - if (pattern === undefined) { - throw ["MhchemBugP", "mhchem bug P. Please report. (" + m + ")"]; // Trying to use non-existing pattern - } else if (typeof pattern === "function") { - return mhchemParser.patterns.patterns[m](input); // cannot use cached var pattern here, because some pattern functions need this===mhchemParser - } else { // RegExp - var match = input.match(pattern); - if (match) { - var mm; - if (match[2]) { - mm = [ match[1], match[2] ]; - } else if (match[1]) { - mm = match[1]; - } else { - mm = match[0]; - } - return { match_: mm, remainder: input.substr(match[0].length) }; - } - return null; - } - } - }, - - // - // Generic state machine actions - // - actions: { - 'a=': function (buffer, m) { buffer.a = (buffer.a || "") + m; }, - 'b=': function (buffer, m) { buffer.b = (buffer.b || "") + m; }, - 'p=': function (buffer, m) { buffer.p = (buffer.p || "") + m; }, - 'o=': function (buffer, m) { buffer.o = (buffer.o || "") + m; }, - 'q=': function (buffer, m) { buffer.q = (buffer.q || "") + m; }, - 'd=': function (buffer, m) { buffer.d = (buffer.d || "") + m; }, - 'rm=': function (buffer, m) { buffer.rm = (buffer.rm || "") + m; }, - 'text=': function (buffer, m) { buffer.text_ = (buffer.text_ || "") + m; }, - 'insert': function (buffer, m, a) { return { type_: a }; }, - 'insert+p1': function (buffer, m, a) { return { type_: a, p1: m }; }, - 'insert+p1+p2': function (buffer, m, a) { return { type_: a, p1: m[0], p2: m[1] }; }, - 'copy': function (buffer, m) { return m; }, - 'rm': function (buffer, m) { return { type_: 'rm', p1: m || ""}; }, - 'text': function (buffer, m) { return mhchemParser.go(m, 'text'); }, - '{text}': function (buffer, m) { - var ret = [ "{" ]; - mhchemParser.concatArray(ret, mhchemParser.go(m, 'text')); - ret.push("}"); - return ret; - }, - 'tex-math': function (buffer, m) { return mhchemParser.go(m, 'tex-math'); }, - 'tex-math tight': function (buffer, m) { return mhchemParser.go(m, 'tex-math tight'); }, - 'bond': function (buffer, m, k) { return { type_: 'bond', kind_: k || m }; }, - 'color0-output': function (buffer, m) { return { type_: 'color0', color: m[0] }; }, - 'ce': function (buffer, m) { return mhchemParser.go(m); }, - '1/2': function (buffer, m) { - /** @type {ParserOutput[]} */ - var ret = []; - if (m.match(/^[+\-]/)) { - ret.push(m.substr(0, 1)); - m = m.substr(1); - } - var n = m.match(/^([0-9]+|\$[a-z]\$|[a-z])\/([0-9]+)(\$[a-z]\$|[a-z])?$/); - n[1] = n[1].replace(/\$/g, ""); - ret.push({ type_: 'frac', p1: n[1], p2: n[2] }); - if (n[3]) { - n[3] = n[3].replace(/\$/g, ""); - ret.push({ type_: 'tex-math', p1: n[3] }); - } - return ret; - }, - '9,9': function (buffer, m) { return mhchemParser.go(m, '9,9'); } - }, - // - // createTransitions - // convert { 'letter': { 'state': { action_: 'output' } } } to { 'state' => [ { pattern: 'letter', task: { action_: [{type_: 'output'}] } } ] } - // with expansion of 'a|b' to 'a' and 'b' (at 2 places) - // - createTransitions: function (o) { - var pattern, state; - /** @type {string[]} */ - var stateArray; - var i; - // - // 1. Collect all states - // - /** @type {Transitions} */ - var transitions = {}; - for (pattern in o) { - for (state in o[pattern]) { - stateArray = state.split("|"); - o[pattern][state].stateArray = stateArray; - for (i=0; i': { - '0|1|2|3': { action_: 'r=', nextState: 'r' }, - 'a|as': { action_: [ 'output', 'r=' ], nextState: 'r' }, - '*': { action_: [ 'output', 'r=' ], nextState: 'r' } }, - '+': { - 'o': { action_: 'd= kv', nextState: 'd' }, - 'd|D': { action_: 'd=', nextState: 'd' }, - 'q': { action_: 'd=', nextState: 'qd' }, - 'qd|qD': { action_: 'd=', nextState: 'qd' }, - 'dq': { action_: [ 'output', 'd=' ], nextState: 'd' }, - '3': { action_: [ 'sb=false', 'output', 'operator' ], nextState: '0' } }, - 'amount': { - '0|2': { action_: 'a=', nextState: 'a' } }, - 'pm-operator': { - '0|1|2|a|as': { action_: [ 'sb=false', 'output', { type_: 'operator', option: '\\pm' } ], nextState: '0' } }, - 'operator': { - '0|1|2|a|as': { action_: [ 'sb=false', 'output', 'operator' ], nextState: '0' } }, - '-$': { - 'o|q': { action_: [ 'charge or bond', 'output' ], nextState: 'qd' }, - 'd': { action_: 'd=', nextState: 'd' }, - 'D': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' }, - 'q': { action_: 'd=', nextState: 'qd' }, - 'qd': { action_: 'd=', nextState: 'qd' }, - 'qD|dq': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' } }, - '-9': { - '3|o': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '3' } }, - '- orbital overlap': { - 'o': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' }, - 'd': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' } }, - '-': { - '0|1|2': { action_: [ { type_: 'output', option: 1 }, 'beginsWithBond=true', { type_: 'bond', option: "-" } ], nextState: '3' }, - '3': { action_: { type_: 'bond', option: "-" } }, - 'a': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' }, - 'as': { action_: [ { type_: 'output', option: 2 }, { type_: 'bond', option: "-" } ], nextState: '3' }, - 'b': { action_: 'b=' }, - 'o': { action_: { type_: '- after o/d', option: false }, nextState: '2' }, - 'q': { action_: { type_: '- after o/d', option: false }, nextState: '2' }, - 'd|qd|dq': { action_: { type_: '- after o/d', option: true }, nextState: '2' }, - 'D|qD|p': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' } }, - 'amount2': { - '1|3': { action_: 'a=', nextState: 'a' } }, - 'letters': { - '0|1|2|3|a|as|b|p|bp|o': { action_: 'o=', nextState: 'o' }, - 'q|dq': { action_: ['output', 'o='], nextState: 'o' }, - 'd|D|qd|qD': { action_: 'o after d', nextState: 'o' } }, - 'digits': { - 'o': { action_: 'q=', nextState: 'q' }, - 'd|D': { action_: 'q=', nextState: 'dq' }, - 'q': { action_: [ 'output', 'o=' ], nextState: 'o' }, - 'a': { action_: 'o=', nextState: 'o' } }, - 'space A': { - 'b|p|bp': {} }, - 'space': { - 'a': { nextState: 'as' }, - '0': { action_: 'sb=false' }, - '1|2': { action_: 'sb=true' }, - 'r|rt|rd|rdt|rdq': { action_: 'output', nextState: '0' }, - '*': { action_: [ 'output', 'sb=true' ], nextState: '1'} }, - '1st-level escape': { - '1|2': { action_: [ 'output', { type_: 'insert+p1', option: '1st-level escape' } ] }, - '*': { action_: [ 'output', { type_: 'insert+p1', option: '1st-level escape' } ], nextState: '0' } }, - '[(...)]': { - 'r|rt': { action_: 'rd=', nextState: 'rd' }, - 'rd|rdt': { action_: 'rq=', nextState: 'rdq' } }, - '...': { - 'o|d|D|dq|qd|qD': { action_: [ 'output', { type_: 'bond', option: "..." } ], nextState: '3' }, - '*': { action_: [ { type_: 'output', option: 1 }, { type_: 'insert', option: 'ellipsis' } ], nextState: '1' } }, - '. |* ': { - '*': { action_: [ 'output', { type_: 'insert', option: 'addition compound' } ], nextState: '1' } }, - 'state of aggregation $': { - '*': { action_: [ 'output', 'state of aggregation' ], nextState: '1' } }, - '{[(': { - 'a|as|o': { action_: [ 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' }, - '0|1|2|3': { action_: [ 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' }, - '*': { action_: [ 'output', 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' } }, - ')]}': { - '0|1|2|3|b|p|bp|o': { action_: [ 'o=', 'parenthesisLevel--' ], nextState: 'o' }, - 'a|as|d|D|q|qd|qD|dq': { action_: [ 'output', 'o=', 'parenthesisLevel--' ], nextState: 'o' } }, - ', ': { - '*': { action_: [ 'output', 'comma' ], nextState: '0' } }, - '^_': { // ^ and _ without a sensible argument - '*': { } }, - '^{(...)}|^($...$)': { - '0|1|2|as': { action_: 'b=', nextState: 'b' }, - 'p': { action_: 'b=', nextState: 'bp' }, - '3|o': { action_: 'd= kv', nextState: 'D' }, - 'q': { action_: 'd=', nextState: 'qD' }, - 'd|D|qd|qD|dq': { action_: [ 'output', 'd=' ], nextState: 'D' } }, - '^a|^\\x{}{}|^\\x{}|^\\x|\'': { - '0|1|2|as': { action_: 'b=', nextState: 'b' }, - 'p': { action_: 'b=', nextState: 'bp' }, - '3|o': { action_: 'd= kv', nextState: 'd' }, - 'q': { action_: 'd=', nextState: 'qd' }, - 'd|qd|D|qD': { action_: 'd=' }, - 'dq': { action_: [ 'output', 'd=' ], nextState: 'd' } }, - '_{(state of aggregation)}$': { - 'd|D|q|qd|qD|dq': { action_: [ 'output', 'q=' ], nextState: 'q' } }, - '_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x': { - '0|1|2|as': { action_: 'p=', nextState: 'p' }, - 'b': { action_: 'p=', nextState: 'bp' }, - '3|o': { action_: 'q=', nextState: 'q' }, - 'd|D': { action_: 'q=', nextState: 'dq' }, - 'q|qd|qD|dq': { action_: [ 'output', 'q=' ], nextState: 'q' } }, - '=<>': { - '0|1|2|3|a|as|o|q|d|D|qd|qD|dq': { action_: [ { type_: 'output', option: 2 }, 'bond' ], nextState: '3' } }, - '#': { - '0|1|2|3|a|as|o': { action_: [ { type_: 'output', option: 2 }, { type_: 'bond', option: "#" } ], nextState: '3' } }, - '{}': { - '*': { action_: { type_: 'output', option: 1 }, nextState: '1' } }, - '{...}': { - '0|1|2|3|a|as|b|p|bp': { action_: 'o=', nextState: 'o' }, - 'o|d|D|q|qd|qD|dq': { action_: [ 'output', 'o=' ], nextState: 'o' } }, - '$...$': { - 'a': { action_: 'a=' }, // 2$n$ - '0|1|2|3|as|b|p|bp|o': { action_: 'o=', nextState: 'o' }, // not 'amount' - 'as|o': { action_: 'o=' }, - 'q|d|D|qd|qD|dq': { action_: [ 'output', 'o=' ], nextState: 'o' } }, - '\\bond{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'bond' ], nextState: "3" } }, - '\\frac{(...)}': { - '*': { action_: [ { type_: 'output', option: 1 }, 'frac-output' ], nextState: '3' } }, - '\\overset{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'overset-output' ], nextState: '3' } }, - '\\underset{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'underset-output' ], nextState: '3' } }, - '\\underbrace{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'underbrace-output' ], nextState: '3' } }, - '\\color{(...)}{(...)}1|\\color(...){(...)}2': { - '*': { action_: [ { type_: 'output', option: 2 }, 'color-output' ], nextState: '3' } }, - '\\color{(...)}0': { - '*': { action_: [ { type_: 'output', option: 2 }, 'color0-output' ] } }, - '\\ce{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'ce' ], nextState: '3' } }, - '\\,': { - '*': { action_: [ { type_: 'output', option: 1 }, 'copy' ], nextState: '1' } }, - '\\x{}{}|\\x{}|\\x': { - '0|1|2|3|a|as|b|p|bp|o|c0': { action_: [ 'o=', 'output' ], nextState: '3' }, - '*': { action_: ['output', 'o=', 'output' ], nextState: '3' } }, - 'others': { - '*': { action_: [ { type_: 'output', option: 1 }, 'copy' ], nextState: '3' } }, - 'else2': { - 'a': { action_: 'a to o', nextState: 'o', revisit: true }, - 'as': { action_: [ 'output', 'sb=true' ], nextState: '1', revisit: true }, - 'r|rt|rd|rdt|rdq': { action_: [ 'output' ], nextState: '0', revisit: true }, - '*': { action_: [ 'output', 'copy' ], nextState: '3' } } - }), - actions: { - 'o after d': function (buffer, m) { - var ret; - if ((buffer.d || "").match(/^[0-9]+$/)) { - var tmp = buffer.d; - buffer.d = undefined; - ret = this['output'](buffer); - buffer.b = tmp; - } else { - ret = this['output'](buffer); - } - mhchemParser.actions['o='](buffer, m); - return ret; - }, - 'd= kv': function (buffer, m) { - buffer.d = m; - buffer.dType = 'kv'; - }, - 'charge or bond': function (buffer, m) { - if (buffer['beginsWithBond']) { - /** @type {ParserOutput[]} */ - var ret = []; - mhchemParser.concatArray(ret, this['output'](buffer)); - mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-")); - return ret; - } else { - buffer.d = m; - } - }, - '- after o/d': function (buffer, m, isAfterD) { - var c1 = mhchemParser.patterns.match_('orbital', buffer.o || ""); - var c2 = mhchemParser.patterns.match_('one lowercase greek letter $', buffer.o || ""); - var c3 = mhchemParser.patterns.match_('one lowercase latin letter $', buffer.o || ""); - var c4 = mhchemParser.patterns.match_('$one lowercase latin letter$ $', buffer.o || ""); - var hyphenFollows = m==="-" && ( c1 && c1.remainder==="" || c2 || c3 || c4 ); - if (hyphenFollows && !buffer.a && !buffer.b && !buffer.p && !buffer.d && !buffer.q && !c1 && c3) { - buffer.o = '$' + buffer.o + '$'; - } - /** @type {ParserOutput[]} */ - var ret = []; - if (hyphenFollows) { - mhchemParser.concatArray(ret, this['output'](buffer)); - ret.push({ type_: 'hyphen' }); - } else { - c1 = mhchemParser.patterns.match_('digits', buffer.d || ""); - if (isAfterD && c1 && c1.remainder==='') { - mhchemParser.concatArray(ret, mhchemParser.actions['d='](buffer, m)); - mhchemParser.concatArray(ret, this['output'](buffer)); - } else { - mhchemParser.concatArray(ret, this['output'](buffer)); - mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-")); - } - } - return ret; - }, - 'a to o': function (buffer) { - buffer.o = buffer.a; - buffer.a = undefined; - }, - 'sb=true': function (buffer) { buffer.sb = true; }, - 'sb=false': function (buffer) { buffer.sb = false; }, - 'beginsWithBond=true': function (buffer) { buffer['beginsWithBond'] = true; }, - 'beginsWithBond=false': function (buffer) { buffer['beginsWithBond'] = false; }, - 'parenthesisLevel++': function (buffer) { buffer['parenthesisLevel']++; }, - 'parenthesisLevel--': function (buffer) { buffer['parenthesisLevel']--; }, - 'state of aggregation': function (buffer, m) { - return { type_: 'state of aggregation', p1: mhchemParser.go(m, 'o') }; - }, - 'comma': function (buffer, m) { - var a = m.replace(/\s*$/, ''); - var withSpace = (a !== m); - if (withSpace && buffer['parenthesisLevel'] === 0) { - return { type_: 'comma enumeration L', p1: a }; - } else { - return { type_: 'comma enumeration M', p1: a }; - } - }, - 'output': function (buffer, m, entityFollows) { - // entityFollows: - // undefined = if we have nothing else to output, also ignore the just read space (buffer.sb) - // 1 = an entity follows, never omit the space if there was one just read before (can only apply to state 1) - // 2 = 1 + the entity can have an amount, so output a\, instead of converting it to o (can only apply to states a|as) - /** @type {ParserOutput | ParserOutput[]} */ - var ret; - if (!buffer.r) { - ret = []; - if (!buffer.a && !buffer.b && !buffer.p && !buffer.o && !buffer.q && !buffer.d && !entityFollows) { - //ret = []; - } else { - if (buffer.sb) { - ret.push({ type_: 'entitySkip' }); - } - if (!buffer.o && !buffer.q && !buffer.d && !buffer.b && !buffer.p && entityFollows!==2) { - buffer.o = buffer.a; - buffer.a = undefined; - } else if (!buffer.o && !buffer.q && !buffer.d && (buffer.b || buffer.p)) { - buffer.o = buffer.a; - buffer.d = buffer.b; - buffer.q = buffer.p; - buffer.a = buffer.b = buffer.p = undefined; - } else { - if (buffer.o && buffer.dType==='kv' && mhchemParser.patterns.match_('d-oxidation$', buffer.d || "")) { - buffer.dType = 'oxidation'; - } else if (buffer.o && buffer.dType==='kv' && !buffer.q) { - buffer.dType = undefined; - } - } - ret.push({ - type_: 'chemfive', - a: mhchemParser.go(buffer.a, 'a'), - b: mhchemParser.go(buffer.b, 'bd'), - p: mhchemParser.go(buffer.p, 'pq'), - o: mhchemParser.go(buffer.o, 'o'), - q: mhchemParser.go(buffer.q, 'pq'), - d: mhchemParser.go(buffer.d, (buffer.dType === 'oxidation' ? 'oxidation' : 'bd')), - dType: buffer.dType - }); - } - } else { // r - /** @type {ParserOutput[]} */ - var rd; - if (buffer.rdt === 'M') { - rd = mhchemParser.go(buffer.rd, 'tex-math'); - } else if (buffer.rdt === 'T') { - rd = [ { type_: 'text', p1: buffer.rd || "" } ]; - } else { - rd = mhchemParser.go(buffer.rd); - } - /** @type {ParserOutput[]} */ - var rq; - if (buffer.rqt === 'M') { - rq = mhchemParser.go(buffer.rq, 'tex-math'); - } else if (buffer.rqt === 'T') { - rq = [ { type_: 'text', p1: buffer.rq || ""} ]; - } else { - rq = mhchemParser.go(buffer.rq); - } - ret = { - type_: 'arrow', - r: buffer.r, - rd: rd, - rq: rq - }; - } - for (var p in buffer) { - if (p !== 'parenthesisLevel' && p !== 'beginsWithBond') { - delete buffer[p]; - } - } - return ret; - }, - 'oxidation-output': function (buffer, m) { - var ret = [ "{" ]; - mhchemParser.concatArray(ret, mhchemParser.go(m, 'oxidation')); - ret.push("}"); - return ret; - }, - 'frac-output': function (buffer, m) { - return { type_: 'frac-ce', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'overset-output': function (buffer, m) { - return { type_: 'overset', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'underset-output': function (buffer, m) { - return { type_: 'underset', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'underbrace-output': function (buffer, m) { - return { type_: 'underbrace', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'color-output': function (buffer, m) { - return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1]) }; - }, - 'r=': function (buffer, m) { buffer.r = m; }, - 'rdt=': function (buffer, m) { buffer.rdt = m; }, - 'rd=': function (buffer, m) { buffer.rd = m; }, - 'rqt=': function (buffer, m) { buffer.rqt = m; }, - 'rq=': function (buffer, m) { buffer.rq = m; }, - 'operator': function (buffer, m, p1) { return { type_: 'operator', kind_: (p1 || m) }; } - } - }, - 'a': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - '1/2$': { - '0': { action_: '1/2' } }, - 'else': { - '0': { nextState: '1', revisit: true } }, - '$(...)$': { - '*': { action_: 'tex-math tight', nextState: '1' } }, - ',': { - '*': { action_: { type_: 'insert', option: 'commaDecimal' } } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: {} - }, - 'o': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - '1/2$': { - '0': { action_: '1/2' } }, - 'else': { - '0': { nextState: '1', revisit: true } }, - 'letters': { - '*': { action_: 'rm' } }, - '\\ca': { - '*': { action_: { type_: 'insert', option: 'circa' } } }, - '\\x{}{}|\\x{}|\\x': { - '*': { action_: 'copy' } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '{(...)}': { - '*': { action_: '{text}' } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: {} - }, - 'text': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '{...}': { - '*': { action_: 'text=' } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '\\greek': { - '*': { action_: [ 'output', 'rm' ] } }, - '\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: [ 'output', 'copy' ] } }, - 'else': { - '*': { action_: 'text=' } } - }), - actions: { - 'output': function (buffer) { - if (buffer.text_) { - /** @type {ParserOutput} */ - var ret = { type_: 'text', p1: buffer.text_ }; - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - } - }, - 'pq': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - 'state of aggregation $': { - '*': { action_: 'state of aggregation' } }, - 'i$': { - '0': { nextState: '!f', revisit: true } }, - '(KV letters),': { - '0': { action_: 'rm', nextState: '0' } }, - 'formula$': { - '0': { nextState: 'f', revisit: true } }, - '1/2$': { - '0': { action_: '1/2' } }, - 'else': { - '0': { nextState: '!f', revisit: true } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '{(...)}': { - '*': { action_: 'text' } }, - 'a-z': { - 'f': { action_: 'tex-math' } }, - 'letters': { - '*': { action_: 'rm' } }, - '-9.,9': { - '*': { action_: '9,9' } }, - ',': { - '*': { action_: { type_: 'insert+p1', option: 'comma enumeration S' } } }, - '\\color{(...)}{(...)}1|\\color(...){(...)}2': { - '*': { action_: 'color-output' } }, - '\\color{(...)}0': { - '*': { action_: 'color0-output' } }, - '\\ce{(...)}': { - '*': { action_: 'ce' } }, - '\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'copy' } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: { - 'state of aggregation': function (buffer, m) { - return { type_: 'state of aggregation subscript', p1: mhchemParser.go(m, 'o') }; - }, - 'color-output': function (buffer, m) { - return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1], 'pq') }; - } - } - }, - 'bd': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - 'x$': { - '0': { nextState: '!f', revisit: true } }, - 'formula$': { - '0': { nextState: 'f', revisit: true } }, - 'else': { - '0': { nextState: '!f', revisit: true } }, - '-9.,9 no missing 0': { - '*': { action_: '9,9' } }, - '.': { - '*': { action_: { type_: 'insert', option: 'electron dot' } } }, - 'a-z': { - 'f': { action_: 'tex-math' } }, - 'x': { - '*': { action_: { type_: 'insert', option: 'KV x' } } }, - 'letters': { - '*': { action_: 'rm' } }, - '\'': { - '*': { action_: { type_: 'insert', option: 'prime' } } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '{(...)}': { - '*': { action_: 'text' } }, - '\\color{(...)}{(...)}1|\\color(...){(...)}2': { - '*': { action_: 'color-output' } }, - '\\color{(...)}0': { - '*': { action_: 'color0-output' } }, - '\\ce{(...)}': { - '*': { action_: 'ce' } }, - '\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'copy' } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: { - 'color-output': function (buffer, m) { - return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1], 'bd') }; - } - } - }, - 'oxidation': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - 'roman numeral': { - '*': { action_: 'roman-numeral' } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - 'else': { - '*': { action_: 'copy' } } - }), - actions: { - 'roman-numeral': function (buffer, m) { return { type_: 'roman numeral', p1: m || "" }; } - } - }, - 'tex-math': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '\\ce{(...)}': { - '*': { action_: [ 'output', 'ce' ] } }, - '{...}|\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'o=' } }, - 'else': { - '*': { action_: 'o=' } } - }), - actions: { - 'output': function (buffer) { - if (buffer.o) { - /** @type {ParserOutput} */ - var ret = { type_: 'tex-math', p1: buffer.o }; - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - } - }, - 'tex-math tight': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '\\ce{(...)}': { - '*': { action_: [ 'output', 'ce' ] } }, - '{...}|\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'o=' } }, - '-|+': { - '*': { action_: 'tight operator' } }, - 'else': { - '*': { action_: 'o=' } } - }), - actions: { - 'tight operator': function (buffer, m) { buffer.o = (buffer.o || "") + "{"+m+"}"; }, - 'output': function (buffer) { - if (buffer.o) { - /** @type {ParserOutput} */ - var ret = { type_: 'tex-math', p1: buffer.o }; - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - } - }, - '9,9': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - ',': { - '*': { action_: 'comma' } }, - 'else': { - '*': { action_: 'copy' } } - }), - actions: { - 'comma': function () { return { type_: 'commaDecimal' }; } - } - }, - //#endregion - // - // \pu state machines - // - //#region pu - 'pu': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - 'space$': { - '*': { action_: [ 'output', 'space' ] } }, - '{[(|)]}': { - '0|a': { action_: 'copy' } }, - '(-)(9)^(-9)': { - '0': { action_: 'number^', nextState: 'a' } }, - '(-)(9.,9)(e)(99)': { - '0': { action_: 'enumber', nextState: 'a' } }, - 'space': { - '0|a': {} }, - 'pm-operator': { - '0|a': { action_: { type_: 'operator', option: '\\pm' }, nextState: '0' } }, - 'operator': { - '0|a': { action_: 'copy', nextState: '0' } }, - '//': { - 'd': { action_: 'o=', nextState: '/' } }, - '/': { - 'd': { action_: 'o=', nextState: '/' } }, - '{...}|else': { - '0|d': { action_: 'd=', nextState: 'd' }, - 'a': { action_: [ 'space', 'd=' ], nextState: 'd' }, - '/|q': { action_: 'q=', nextState: 'q' } } - }), - actions: { - 'enumber': function (buffer, m) { - /** @type {ParserOutput[]} */ - var ret = []; - if (m[0] === "+-" || m[0] === "+/-") { - ret.push("\\pm "); - } else if (m[0]) { - ret.push(m[0]); - } - if (m[1]) { - mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9')); - if (m[2]) { - if (m[2].match(/[,.]/)) { - mhchemParser.concatArray(ret, mhchemParser.go(m[2], 'pu-9,9')); - } else { - ret.push(m[2]); - } - } - m[3] = m[4] || m[3]; - if (m[3]) { - m[3] = m[3].trim(); - if (m[3] === "e" || m[3].substr(0, 1) === "*") { - ret.push({ type_: 'cdot' }); - } else { - ret.push({ type_: 'times' }); - } - } - } - if (m[3]) { - ret.push("10^{"+m[5]+"}"); - } - return ret; - }, - 'number^': function (buffer, m) { - /** @type {ParserOutput[]} */ - var ret = []; - if (m[0] === "+-" || m[0] === "+/-") { - ret.push("\\pm "); - } else if (m[0]) { - ret.push(m[0]); - } - mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9')); - ret.push("^{"+m[2]+"}"); - return ret; - }, - 'operator': function (buffer, m, p1) { return { type_: 'operator', kind_: (p1 || m) }; }, - 'space': function () { return { type_: 'pu-space-1' }; }, - 'output': function (buffer) { - /** @type {ParserOutput | ParserOutput[]} */ - var ret; - var md = mhchemParser.patterns.match_('{(...)}', buffer.d || ""); - if (md && md.remainder === '') { buffer.d = md.match_; } - var mq = mhchemParser.patterns.match_('{(...)}', buffer.q || ""); - if (mq && mq.remainder === '') { buffer.q = mq.match_; } - if (buffer.d) { - buffer.d = buffer.d.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C"); - buffer.d = buffer.d.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F"); - } - if (buffer.q) { // fraction - buffer.q = buffer.q.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C"); - buffer.q = buffer.q.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F"); - var b5 = { - d: mhchemParser.go(buffer.d, 'pu'), - q: mhchemParser.go(buffer.q, 'pu') - }; - if (buffer.o === '//') { - ret = { type_: 'pu-frac', p1: b5.d, p2: b5.q }; - } else { - ret = b5.d; - if (b5.d.length > 1 || b5.q.length > 1) { - ret.push({ type_: ' / ' }); - } else { - ret.push({ type_: '/' }); - } - mhchemParser.concatArray(ret, b5.q); - } - } else { // no fraction - ret = mhchemParser.go(buffer.d, 'pu-2'); - } - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - }, - 'pu-2': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '*': { - '*': { action_: [ 'output', 'cdot' ], nextState: '0' } }, - '\\x': { - '*': { action_: 'rm=' } }, - 'space': { - '*': { action_: [ 'output', 'space' ], nextState: '0' } }, - '^{(...)}|^(-1)': { - '1': { action_: '^(-1)' } }, - '-9.,9': { - '0': { action_: 'rm=', nextState: '0' }, - '1': { action_: '^(-1)', nextState: '0' } }, - '{...}|else': { - '*': { action_: 'rm=', nextState: '1' } } - }), - actions: { - 'cdot': function () { return { type_: 'tight cdot' }; }, - '^(-1)': function (buffer, m) { buffer.rm += "^{"+m+"}"; }, - 'space': function () { return { type_: 'pu-space-2' }; }, - 'output': function (buffer) { - /** @type {ParserOutput | ParserOutput[]} */ - var ret = []; - if (buffer.rm) { - var mrm = mhchemParser.patterns.match_('{(...)}', buffer.rm || ""); - if (mrm && mrm.remainder === '') { - ret = mhchemParser.go(mrm.match_, 'pu'); - } else { - ret = { type_: 'rm', p1: buffer.rm }; - } - } - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - }, - 'pu-9,9': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '0': { action_: 'output-0' }, - 'o': { action_: 'output-o' } }, - ',': { - '0': { action_: [ 'output-0', 'comma' ], nextState: 'o' } }, - '.': { - '0': { action_: [ 'output-0', 'copy' ], nextState: 'o' } }, - 'else': { - '*': { action_: 'text=' } } - }), - actions: { - 'comma': function () { return { type_: 'commaDecimal' }; }, - 'output-0': function (buffer) { - /** @type {ParserOutput[]} */ - var ret = []; - buffer.text_ = buffer.text_ || ""; - if (buffer.text_.length > 4) { - var a = buffer.text_.length % 3; - if (a === 0) { a = 3; } - for (var i=buffer.text_.length-3; i>0; i-=3) { - ret.push(buffer.text_.substr(i, 3)); - ret.push({ type_: '1000 separator' }); - } - ret.push(buffer.text_.substr(0, a)); - ret.reverse(); - } else { - ret.push(buffer.text_); - } - for (var p in buffer) { delete buffer[p]; } - return ret; - }, - 'output-o': function (buffer) { - /** @type {ParserOutput[]} */ - var ret = []; - buffer.text_ = buffer.text_ || ""; - if (buffer.text_.length > 4) { - var a = buffer.text_.length - 3; - for (var i=0; i, so we change \vphantom{X} to {} - // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed. -// res += "{\\vphantom{X}}"; - res += "{{}}"; - res += "_{\\smash[t]{"+b5.q+"}}"; - } - } else { - if (b5.q) { - // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed. -// res += "{\\vphantom{X}}"; - res += "{{}}"; - res += "_{\\smash[t]{"+b5.q+"}}"; - } - if (b5.d) { - // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed. -// res += "{\\vphantom{X}}"; - res += "{{}}"; - res += "^{"+b5.d+"}"; - } - } - break; - case 'rm': - res = "\\mathrm{"+buf.p1+"}"; - break; - case 'text': - if (buf.p1.match(/[\^_]/)) { - buf.p1 = buf.p1.replace(" ", "~").replace("-", "\\text{-}"); - res = "\\mathrm{"+buf.p1+"}"; - } else { - res = "\\text{"+buf.p1+"}"; - } - break; - case 'roman numeral': - res = "\\mathrm{"+buf.p1+"}"; - break; - case 'state of aggregation': - res = "\\mskip2mu "+texify._goInner(buf.p1); - break; - case 'state of aggregation subscript': - res = "\\mskip1mu "+texify._goInner(buf.p1); - break; - case 'bond': - res = texify._getBond(buf.kind_); - if (!res) { - throw ["MhchemErrorBond", "mhchem Error. Unknown bond type (" + buf.kind_ + ")"]; - } - break; - case 'frac': - var c = "\\frac{" + buf.p1 + "}{" + buf.p2 + "}"; - res = "\\mathchoice{\\textstyle"+c+"}{"+c+"}{"+c+"}{"+c+"}"; - break; - case 'pu-frac': - var d = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - res = "\\mathchoice{\\textstyle"+d+"}{"+d+"}{"+d+"}{"+d+"}"; - break; - case 'tex-math': - res = buf.p1 + " "; - break; - case 'frac-ce': - res = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - break; - case 'overset': - res = "\\overset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - break; - case 'underset': - res = "\\underset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - break; - case 'underbrace': - res = "\\underbrace{" + texify._goInner(buf.p1) + "}_{" + texify._goInner(buf.p2) + "}"; - break; - case 'color': - res = "{\\color{" + buf.color1 + "}{" + texify._goInner(buf.color2) + "}}"; - break; - case 'color0': - res = "\\color{" + buf.color + "}"; - break; - case 'arrow': - var b6 = { - rd: texify._goInner(buf.rd), - rq: texify._goInner(buf.rq) - }; - var arrow = texify._getArrow(buf.r); - if (b6.rq) { arrow += "[{\\rm " + b6.rq + "}]"; } - if (b6.rd) { - arrow += "{\\rm " + b6.rd + "}"; - } else { - arrow += "{}"; - } - res = arrow; - break; - case 'operator': - res = texify._getOperator(buf.kind_); - break; - case '1st-level escape': - res = buf.p1+" "; // &, \\\\, \\hlin - break; - case 'space': - res = " "; - break; - case 'entitySkip': - res = "~"; - break; - case 'pu-space-1': - res = "~"; - break; - case 'pu-space-2': - res = "\\mkern3mu "; - break; - case '1000 separator': - res = "\\mkern2mu "; - break; - case 'commaDecimal': - res = "{,}"; - break; - case 'comma enumeration L': - res = "{"+buf.p1+"}\\mkern6mu "; - break; - case 'comma enumeration M': - res = "{"+buf.p1+"}\\mkern3mu "; - break; - case 'comma enumeration S': - res = "{"+buf.p1+"}\\mkern1mu "; - break; - case 'hyphen': - res = "\\text{-}"; - break; - case 'addition compound': - res = "\\,{\\cdot}\\,"; - break; - case 'electron dot': - res = "\\mkern1mu \\text{\\textbullet}\\mkern1mu "; - break; - case 'KV x': - res = "{\\times}"; - break; - case 'prime': - res = "\\prime "; - break; - case 'cdot': - res = "\\cdot "; - break; - case 'tight cdot': - res = "\\mkern1mu{\\cdot}\\mkern1mu "; - break; - case 'times': - res = "\\times "; - break; - case 'circa': - res = "{\\sim}"; - break; - case '^': - res = "uparrow"; - break; - case 'v': - res = "downarrow"; - break; - case 'ellipsis': - res = "\\ldots "; - break; - case '/': - res = "/"; - break; - case ' / ': - res = "\\,/\\,"; - break; - default: - assertNever(buf); - throw ["MhchemBugT", "mhchem bug T. Please report."]; // Missing texify rule or unknown MhchemParser output - } - assertString(res); - return res; - }, - _getArrow: function (a) { - switch (a) { - case "->": return "\\yields"; - case "\u2192": return "\\yields"; - case "\u27F6": return "\\yields"; - case "<-": return "\\yieldsLeft"; - case "<->": return "\\mesomerism"; - case "<-->": return "\\yieldsLeftRight"; - case "<=>": return "\\equilibrium"; - case "\u21CC": return "\\equilibrium"; - case "<=>>": return "\\equilibriumRight"; - case "<<=>": return "\\equilibriumLeft"; - default: - assertNever(a); - throw ["MhchemBugT", "mhchem bug T. Please report."]; - } - }, - _getBond: function (a) { - switch (a) { - case "-": return "{-}"; - case "1": return "{-}"; - case "=": return "{=}"; - case "2": return "{=}"; - case "#": return "{\\equiv}"; - case "3": return "{\\equiv}"; - case "~": return "{\\tripleDash}"; - case "~-": return "{\\tripleDashOverLine}"; - case "~=": return "{\\tripleDashOverDoubleLine}"; - case "~--": return "{\\tripleDashOverDoubleLine}"; - case "-~-": return "{\\tripleDashBetweenDoubleLine}"; - case "...": return "{{\\cdot}{\\cdot}{\\cdot}}"; - case "....": return "{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}"; - case "->": return "{\\rightarrow}"; - case "<-": return "{\\leftarrow}"; - case "<": return "{<}"; - case ">": return "{>}"; - default: - assertNever(a); - throw ["MhchemBugT", "mhchem bug T. Please report."]; - } - }, - _getOperator: function (a) { - switch (a) { - case "+": return " {}+{} "; - case "-": return " {}-{} "; - case "=": return " {}={} "; - case "<": return " {}<{} "; - case ">": return " {}>{} "; - case "<<": return " {}\\ll{} "; - case ">>": return " {}\\gg{} "; - case "\\pm": return " {}\\pm{} "; - case "\\approx": return " {}\\approx{} "; - case "$\\approx$": return " {}\\approx{} "; - case "v": return " \\downarrow{} "; - case "(v)": return " \\downarrow{} "; - case "^": return " \\uparrow{} "; - case "(^)": return " \\uparrow{} "; - default: - assertNever(a); - throw ["MhchemBugT", "mhchem bug T. Please report."]; - } - } - }; - - // - // Helpers for code anaylsis - // Will show type error at calling position - // - /** @param {number} a */ - function assertNever(a) {} - /** @param {string} a */ - function assertString(a) {} diff --git a/contrib/mhchem/mhchem.min.js b/contrib/mhchem/mhchem.min.js deleted file mode 100644 index 2eafa389..00000000 --- a/contrib/mhchem/mhchem.min.js +++ /dev/null @@ -1 +0,0 @@ -temml.__defineMacro("\\ce",(function(t){return chemParse(t.consumeArgs(1)[0],"ce")})),temml.__defineMacro("\\pu",(function(t){return chemParse(t.consumeArgs(1)[0],"pu")})),temml.__defineMacro("\\uniDash","{\\rule{0.672em}{0.06em}}"),temml.__defineMacro("\\triDash","{\\rule{0.15em}{0.06em}\\kern2mu\\rule{0.15em}{0.06em}\\kern2mu\\rule{0.15em}{0.06em}}"),temml.__defineMacro("\\tripleDash","\\kern0.075em\\raise0.25em{\\triDash}\\kern0.075em"),temml.__defineMacro("\\tripleDashOverLine","\\kern0.075em\\mathrlap{\\raise0.125em{\\uniDash}}\\raise0.34em{\\triDash}\\kern0.075em"),temml.__defineMacro("\\tripleDashOverDoubleLine","\\kern0.075em\\mathrlap{\\mathrlap{\\raise0.48em{\\triDash}}\\raise0.27em{\\uniDash}}{\\raise0.05em{\\uniDash}}\\kern0.075em"),temml.__defineMacro("\\tripleDashBetweenDoubleLine","\\kern0.075em\\mathrlap{\\mathrlap{\\raise0.48em{\\uniDash}}\\raise0.27em{\\triDash}}{\\raise0.05em{\\uniDash}}\\kern0.075em");var chemParse=function(t,e){for(var r="",a=t.length&&t[t.length-1].loc.start,n=t.length-1;n>=0;n--)t[n].loc.start>a&&(r+=" ",a=t[n].loc.start),r+=t[n].text,a+=t[n].text.length;return texify.go(mhchemParser.go(r,e))},mhchemParser={go:function(t,e){if(!t)return[];void 0===e&&(e="ce");var r,a="0",n={};n.parenthesisLevel=0,t=(t=(t=t.replace(/\n/g," ")).replace(/[\u2212\u2013\u2014\u2010]/g,"-")).replace(/[\u2026]/g,"...");for(var o=10,i=[];;){r!==t?(o=10,r=t):o--;var c=mhchemParser.stateMachines[e],s=c.transitions[a]||c.transitions["*"];t:for(var u=0;u0))return i;if(m.revisit||(t=p.remainder),!m.toContinue)break t}}if(o<=0)throw["MhchemBugU","mhchem bug U. Please report."]}},concatArray:function(t,e){if(e)if(Array.isArray(e))for(var r=0;r":/^[=<>]/,"#":/^[#\u2261]/,"+":/^\+/,"-$":/^-(?=[\s_},;\]/]|$|\([a-z]+\))/,"-9":/^-(?=[0-9])/,"- orbital overlap":/^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/,"-":/^-/,"pm-operator":/^(?:\\pm|\$\\pm\$|\+-|\+\/-)/,operator:/^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/,arrowUpDown:/^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/,"\\bond{(...)}":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\bond{","","","}")},"->":/^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/,CMT:/^[CMT](?=\[)/,"[(...)]":function(t){return mhchemParser.patterns.findObserveGroups(t,"[","","","]")},"1st-level escape":/^(&|\\\\|\\hline)\s*/,"\\,":/^(?:\\[,\ ;:])/,"\\x{}{}":function(t){return mhchemParser.patterns.findObserveGroups(t,"",/^\\[a-zA-Z]+\{/,"}","","","{","}","",!0)},"\\x{}":function(t){return mhchemParser.patterns.findObserveGroups(t,"",/^\\[a-zA-Z]+\{/,"}","")},"\\ca":/^\\ca(?:\s+|(?![a-zA-Z]))/,"\\x":/^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/,orbital:/^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/,others:/^[\/~|]/,"\\frac{(...)}":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\frac{","","","}","{","","","}")},"\\overset{(...)}":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\overset{","","","}","{","","","}")},"\\underset{(...)}":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\underset{","","","}","{","","","}")},"\\underbrace{(...)}":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\underbrace{","","","}_","{","","","}")},"\\color{(...)}0":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\color{","","","}")},"\\color{(...)}{(...)}1":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\color{","","","}","{","","","}")},"\\color(...){(...)}2":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\color","\\","",/^(?=\{)/,"{","","","}")},"\\ce{(...)}":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\ce{","","","}")},oxidation$:/^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,"d-oxidation$":/^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,"roman numeral":/^[IVX]+/,"1/2$":/^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/,amount:function(t){var e;if(e=t.match(/^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/))return{match_:e[0],remainder:t.substr(e[0].length)};var r=mhchemParser.patterns.findObserveGroups(t,"","$","$","");return r&&(e=r.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/))?{match_:e[0],remainder:t.substr(e[0].length)}:null},amount2:function(t){return this.amount(t)},"(KV letters),":/^(?:[A-Z][a-z]{0,2}|i)(?=,)/,formula$:function(t){if(t.match(/^\([a-z]+\)$/))return null;var e=t.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/);return e?{match_:e[0],remainder:t.substr(e[0].length)}:null},uprightEntities:/^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/,"/":/^\s*(\/)\s*/,"//":/^\s*(\/\/)\s*/,"*":/^\s*[*.]\s*/},findObserveGroups:function(t,e,r,a,n,o,i,c,s,u){var p=function(t,e){if("string"==typeof e)return 0!==t.indexOf(e)?null:e;var r=t.match(e);return r?r[0]:null},m=p(t,e);if(null===m)return null;if(t=t.substr(m.length),null===(m=p(t,r)))return null;var h=function(t,e,r){for(var a=0;e":{"0|1|2|3":{action_:"r=",nextState:"r"},"a|as":{action_:["output","r="],nextState:"r"},"*":{action_:["output","r="],nextState:"r"}},"+":{o:{action_:"d= kv",nextState:"d"},"d|D":{action_:"d=",nextState:"d"},q:{action_:"d=",nextState:"qd"},"qd|qD":{action_:"d=",nextState:"qd"},dq:{action_:["output","d="],nextState:"d"},3:{action_:["sb=false","output","operator"],nextState:"0"}},amount:{"0|2":{action_:"a=",nextState:"a"}},"pm-operator":{"0|1|2|a|as":{action_:["sb=false","output",{type_:"operator",option:"\\pm"}],nextState:"0"}},operator:{"0|1|2|a|as":{action_:["sb=false","output","operator"],nextState:"0"}},"-$":{"o|q":{action_:["charge or bond","output"],nextState:"qd"},d:{action_:"d=",nextState:"d"},D:{action_:["output",{type_:"bond",option:"-"}],nextState:"3"},q:{action_:"d=",nextState:"qd"},qd:{action_:"d=",nextState:"qd"},"qD|dq":{action_:["output",{type_:"bond",option:"-"}],nextState:"3"}},"-9":{"3|o":{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"3"}},"- orbital overlap":{o:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"},d:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"}},"-":{"0|1|2":{action_:[{type_:"output",option:1},"beginsWithBond=true",{type_:"bond",option:"-"}],nextState:"3"},3:{action_:{type_:"bond",option:"-"}},a:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"},as:{action_:[{type_:"output",option:2},{type_:"bond",option:"-"}],nextState:"3"},b:{action_:"b="},o:{action_:{type_:"- after o/d",option:!1},nextState:"2"},q:{action_:{type_:"- after o/d",option:!1},nextState:"2"},"d|qd|dq":{action_:{type_:"- after o/d",option:!0},nextState:"2"},"D|qD|p":{action_:["output",{type_:"bond",option:"-"}],nextState:"3"}},amount2:{"1|3":{action_:"a=",nextState:"a"}},letters:{"0|1|2|3|a|as|b|p|bp|o":{action_:"o=",nextState:"o"},"q|dq":{action_:["output","o="],nextState:"o"},"d|D|qd|qD":{action_:"o after d",nextState:"o"}},digits:{o:{action_:"q=",nextState:"q"},"d|D":{action_:"q=",nextState:"dq"},q:{action_:["output","o="],nextState:"o"},a:{action_:"o=",nextState:"o"}},"space A":{"b|p|bp":{}},space:{a:{nextState:"as"},0:{action_:"sb=false"},"1|2":{action_:"sb=true"},"r|rt|rd|rdt|rdq":{action_:"output",nextState:"0"},"*":{action_:["output","sb=true"],nextState:"1"}},"1st-level escape":{"1|2":{action_:["output",{type_:"insert+p1",option:"1st-level escape"}]},"*":{action_:["output",{type_:"insert+p1",option:"1st-level escape"}],nextState:"0"}},"[(...)]":{"r|rt":{action_:"rd=",nextState:"rd"},"rd|rdt":{action_:"rq=",nextState:"rdq"}},"...":{"o|d|D|dq|qd|qD":{action_:["output",{type_:"bond",option:"..."}],nextState:"3"},"*":{action_:[{type_:"output",option:1},{type_:"insert",option:"ellipsis"}],nextState:"1"}},". |* ":{"*":{action_:["output",{type_:"insert",option:"addition compound"}],nextState:"1"}},"state of aggregation $":{"*":{action_:["output","state of aggregation"],nextState:"1"}},"{[(":{"a|as|o":{action_:["o=","output","parenthesisLevel++"],nextState:"2"},"0|1|2|3":{action_:["o=","output","parenthesisLevel++"],nextState:"2"},"*":{action_:["output","o=","output","parenthesisLevel++"],nextState:"2"}},")]}":{"0|1|2|3|b|p|bp|o":{action_:["o=","parenthesisLevel--"],nextState:"o"},"a|as|d|D|q|qd|qD|dq":{action_:["output","o=","parenthesisLevel--"],nextState:"o"}},", ":{"*":{action_:["output","comma"],nextState:"0"}},"^_":{"*":{}},"^{(...)}|^($...$)":{"0|1|2|as":{action_:"b=",nextState:"b"},p:{action_:"b=",nextState:"bp"},"3|o":{action_:"d= kv",nextState:"D"},q:{action_:"d=",nextState:"qD"},"d|D|qd|qD|dq":{action_:["output","d="],nextState:"D"}},"^a|^\\x{}{}|^\\x{}|^\\x|'":{"0|1|2|as":{action_:"b=",nextState:"b"},p:{action_:"b=",nextState:"bp"},"3|o":{action_:"d= kv",nextState:"d"},q:{action_:"d=",nextState:"qd"},"d|qd|D|qD":{action_:"d="},dq:{action_:["output","d="],nextState:"d"}},"_{(state of aggregation)}$":{"d|D|q|qd|qD|dq":{action_:["output","q="],nextState:"q"}},"_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x":{"0|1|2|as":{action_:"p=",nextState:"p"},b:{action_:"p=",nextState:"bp"},"3|o":{action_:"q=",nextState:"q"},"d|D":{action_:"q=",nextState:"dq"},"q|qd|qD|dq":{action_:["output","q="],nextState:"q"}},"=<>":{"0|1|2|3|a|as|o|q|d|D|qd|qD|dq":{action_:[{type_:"output",option:2},"bond"],nextState:"3"}},"#":{"0|1|2|3|a|as|o":{action_:[{type_:"output",option:2},{type_:"bond",option:"#"}],nextState:"3"}},"{}":{"*":{action_:{type_:"output",option:1},nextState:"1"}},"{...}":{"0|1|2|3|a|as|b|p|bp":{action_:"o=",nextState:"o"},"o|d|D|q|qd|qD|dq":{action_:["output","o="],nextState:"o"}},"$...$":{a:{action_:"a="},"0|1|2|3|as|b|p|bp|o":{action_:"o=",nextState:"o"},"as|o":{action_:"o="},"q|d|D|qd|qD|dq":{action_:["output","o="],nextState:"o"}},"\\bond{(...)}":{"*":{action_:[{type_:"output",option:2},"bond"],nextState:"3"}},"\\frac{(...)}":{"*":{action_:[{type_:"output",option:1},"frac-output"],nextState:"3"}},"\\overset{(...)}":{"*":{action_:[{type_:"output",option:2},"overset-output"],nextState:"3"}},"\\underset{(...)}":{"*":{action_:[{type_:"output",option:2},"underset-output"],nextState:"3"}},"\\underbrace{(...)}":{"*":{action_:[{type_:"output",option:2},"underbrace-output"],nextState:"3"}},"\\color{(...)}{(...)}1|\\color(...){(...)}2":{"*":{action_:[{type_:"output",option:2},"color-output"],nextState:"3"}},"\\color{(...)}0":{"*":{action_:[{type_:"output",option:2},"color0-output"]}},"\\ce{(...)}":{"*":{action_:[{type_:"output",option:2},"ce"],nextState:"3"}},"\\,":{"*":{action_:[{type_:"output",option:1},"copy"],nextState:"1"}},"\\x{}{}|\\x{}|\\x":{"0|1|2|3|a|as|b|p|bp|o|c0":{action_:["o=","output"],nextState:"3"},"*":{action_:["output","o=","output"],nextState:"3"}},others:{"*":{action_:[{type_:"output",option:1},"copy"],nextState:"3"}},else2:{a:{action_:"a to o",nextState:"o",revisit:!0},as:{action_:["output","sb=true"],nextState:"1",revisit:!0},"r|rt|rd|rdt|rdq":{action_:["output"],nextState:"0",revisit:!0},"*":{action_:["output","copy"],nextState:"3"}}}),actions:{"o after d":function(t,e){var r;if((t.d||"").match(/^[0-9]+$/)){var a=t.d;t.d=void 0,r=this.output(t),t.b=a}else r=this.output(t);return mhchemParser.actions["o="](t,e),r},"d= kv":function(t,e){t.d=e,t.dType="kv"},"charge or bond":function(t,e){if(t.beginsWithBond){var r=[];return mhchemParser.concatArray(r,this.output(t)),mhchemParser.concatArray(r,mhchemParser.actions.bond(t,e,"-")),r}t.d=e},"- after o/d":function(t,e,r){var a=mhchemParser.patterns.match_("orbital",t.o||""),n=mhchemParser.patterns.match_("one lowercase greek letter $",t.o||""),o=mhchemParser.patterns.match_("one lowercase latin letter $",t.o||""),i=mhchemParser.patterns.match_("$one lowercase latin letter$ $",t.o||""),c="-"===e&&(a&&""===a.remainder||n||o||i);!c||t.a||t.b||t.p||t.d||t.q||a||!o||(t.o="$"+t.o+"$");var s=[];return c?(mhchemParser.concatArray(s,this.output(t)),s.push({type_:"hyphen"})):(a=mhchemParser.patterns.match_("digits",t.d||""),r&&a&&""===a.remainder?(mhchemParser.concatArray(s,mhchemParser.actions["d="](t,e)),mhchemParser.concatArray(s,this.output(t))):(mhchemParser.concatArray(s,this.output(t)),mhchemParser.concatArray(s,mhchemParser.actions.bond(t,e,"-")))),s},"a to o":function(t){t.o=t.a,t.a=void 0},"sb=true":function(t){t.sb=!0},"sb=false":function(t){t.sb=!1},"beginsWithBond=true":function(t){t.beginsWithBond=!0},"beginsWithBond=false":function(t){t.beginsWithBond=!1},"parenthesisLevel++":function(t){t.parenthesisLevel++},"parenthesisLevel--":function(t){t.parenthesisLevel--},"state of aggregation":function(t,e){return{type_:"state of aggregation",p1:mhchemParser.go(e,"o")}},comma:function(t,e){var r=e.replace(/\s*$/,"");return r!==e&&0===t.parenthesisLevel?{type_:"comma enumeration L",p1:r}:{type_:"comma enumeration M",p1:r}},output:function(t,e,r){var a,n,o;t.r?(n="M"===t.rdt?mhchemParser.go(t.rd,"tex-math"):"T"===t.rdt?[{type_:"text",p1:t.rd||""}]:mhchemParser.go(t.rd),o="M"===t.rqt?mhchemParser.go(t.rq,"tex-math"):"T"===t.rqt?[{type_:"text",p1:t.rq||""}]:mhchemParser.go(t.rq),a={type_:"arrow",r:t.r,rd:n,rq:o}):(a=[],(t.a||t.b||t.p||t.o||t.q||t.d||r)&&(t.sb&&a.push({type_:"entitySkip"}),t.o||t.q||t.d||t.b||t.p||2===r?t.o||t.q||t.d||!t.b&&!t.p?t.o&&"kv"===t.dType&&mhchemParser.patterns.match_("d-oxidation$",t.d||"")?t.dType="oxidation":t.o&&"kv"===t.dType&&!t.q&&(t.dType=void 0):(t.o=t.a,t.d=t.b,t.q=t.p,t.a=t.b=t.p=void 0):(t.o=t.a,t.a=void 0),a.push({type_:"chemfive",a:mhchemParser.go(t.a,"a"),b:mhchemParser.go(t.b,"bd"),p:mhchemParser.go(t.p,"pq"),o:mhchemParser.go(t.o,"o"),q:mhchemParser.go(t.q,"pq"),d:mhchemParser.go(t.d,"oxidation"===t.dType?"oxidation":"bd"),dType:t.dType})));for(var i in t)"parenthesisLevel"!==i&&"beginsWithBond"!==i&&delete t[i];return a},"oxidation-output":function(t,e){var r=["{"];return mhchemParser.concatArray(r,mhchemParser.go(e,"oxidation")),r.push("}"),r},"frac-output":function(t,e){return{type_:"frac-ce",p1:mhchemParser.go(e[0]),p2:mhchemParser.go(e[1])}},"overset-output":function(t,e){return{type_:"overset",p1:mhchemParser.go(e[0]),p2:mhchemParser.go(e[1])}},"underset-output":function(t,e){return{type_:"underset",p1:mhchemParser.go(e[0]),p2:mhchemParser.go(e[1])}},"underbrace-output":function(t,e){return{type_:"underbrace",p1:mhchemParser.go(e[0]),p2:mhchemParser.go(e[1])}},"color-output":function(t,e){return{type_:"color",color1:e[0],color2:mhchemParser.go(e[1])}},"r=":function(t,e){t.r=e},"rdt=":function(t,e){t.rdt=e},"rd=":function(t,e){t.rd=e},"rqt=":function(t,e){t.rqt=e},"rq=":function(t,e){t.rq=e},operator:function(t,e,r){return{type_:"operator",kind_:r||e}}}},a:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"1",revisit:!0}},"$(...)$":{"*":{action_:"tex-math tight",nextState:"1"}},",":{"*":{action_:{type_:"insert",option:"commaDecimal"}}},else2:{"*":{action_:"copy"}}}),actions:{}},o:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"1",revisit:!0}},letters:{"*":{action_:"rm"}},"\\ca":{"*":{action_:{type_:"insert",option:"circa"}}},"\\x{}{}|\\x{}|\\x":{"*":{action_:"copy"}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"{(...)}":{"*":{action_:"{text}"}},else2:{"*":{action_:"copy"}}}),actions:{}},text:{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"{...}":{"*":{action_:"text="}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"\\greek":{"*":{action_:["output","rm"]}},"\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:["output","copy"]}},else:{"*":{action_:"text="}}}),actions:{output:function(t){if(t.text_){var e={type_:"text",p1:t.text_};for(var r in t)delete t[r];return e}}}},pq:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"state of aggregation $":{"*":{action_:"state of aggregation"}},i$:{0:{nextState:"!f",revisit:!0}},"(KV letters),":{0:{action_:"rm",nextState:"0"}},formula$:{0:{nextState:"f",revisit:!0}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"!f",revisit:!0}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"{(...)}":{"*":{action_:"text"}},"a-z":{f:{action_:"tex-math"}},letters:{"*":{action_:"rm"}},"-9.,9":{"*":{action_:"9,9"}},",":{"*":{action_:{type_:"insert+p1",option:"comma enumeration S"}}},"\\color{(...)}{(...)}1|\\color(...){(...)}2":{"*":{action_:"color-output"}},"\\color{(...)}0":{"*":{action_:"color0-output"}},"\\ce{(...)}":{"*":{action_:"ce"}},"\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"copy"}},else2:{"*":{action_:"copy"}}}),actions:{"state of aggregation":function(t,e){return{type_:"state of aggregation subscript",p1:mhchemParser.go(e,"o")}},"color-output":function(t,e){return{type_:"color",color1:e[0],color2:mhchemParser.go(e[1],"pq")}}}},bd:{transitions:mhchemParser.createTransitions({empty:{"*":{}},x$:{0:{nextState:"!f",revisit:!0}},formula$:{0:{nextState:"f",revisit:!0}},else:{0:{nextState:"!f",revisit:!0}},"-9.,9 no missing 0":{"*":{action_:"9,9"}},".":{"*":{action_:{type_:"insert",option:"electron dot"}}},"a-z":{f:{action_:"tex-math"}},x:{"*":{action_:{type_:"insert",option:"KV x"}}},letters:{"*":{action_:"rm"}},"'":{"*":{action_:{type_:"insert",option:"prime"}}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"{(...)}":{"*":{action_:"text"}},"\\color{(...)}{(...)}1|\\color(...){(...)}2":{"*":{action_:"color-output"}},"\\color{(...)}0":{"*":{action_:"color0-output"}},"\\ce{(...)}":{"*":{action_:"ce"}},"\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"copy"}},else2:{"*":{action_:"copy"}}}),actions:{"color-output":function(t,e){return{type_:"color",color1:e[0],color2:mhchemParser.go(e[1],"bd")}}}},oxidation:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"roman numeral":{"*":{action_:"roman-numeral"}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},else:{"*":{action_:"copy"}}}),actions:{"roman-numeral":function(t,e){return{type_:"roman numeral",p1:e||""}}}},"tex-math":{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"\\ce{(...)}":{"*":{action_:["output","ce"]}},"{...}|\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"o="}},else:{"*":{action_:"o="}}}),actions:{output:function(t){if(t.o){var e={type_:"tex-math",p1:t.o};for(var r in t)delete t[r];return e}}}},"tex-math tight":{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"\\ce{(...)}":{"*":{action_:["output","ce"]}},"{...}|\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"o="}},"-|+":{"*":{action_:"tight operator"}},else:{"*":{action_:"o="}}}),actions:{"tight operator":function(t,e){t.o=(t.o||"")+"{"+e+"}"},output:function(t){if(t.o){var e={type_:"tex-math",p1:t.o};for(var r in t)delete t[r];return e}}}},"9,9":{transitions:mhchemParser.createTransitions({empty:{"*":{}},",":{"*":{action_:"comma"}},else:{"*":{action_:"copy"}}}),actions:{comma:function(){return{type_:"commaDecimal"}}}},pu:{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},space$:{"*":{action_:["output","space"]}},"{[(|)]}":{"0|a":{action_:"copy"}},"(-)(9)^(-9)":{0:{action_:"number^",nextState:"a"}},"(-)(9.,9)(e)(99)":{0:{action_:"enumber",nextState:"a"}},space:{"0|a":{}},"pm-operator":{"0|a":{action_:{type_:"operator",option:"\\pm"},nextState:"0"}},operator:{"0|a":{action_:"copy",nextState:"0"}},"//":{d:{action_:"o=",nextState:"/"}},"/":{d:{action_:"o=",nextState:"/"}},"{...}|else":{"0|d":{action_:"d=",nextState:"d"},a:{action_:["space","d="],nextState:"d"},"/|q":{action_:"q=",nextState:"q"}}}),actions:{enumber:function(t,e){var r=[];return"+-"===e[0]||"+/-"===e[0]?r.push("\\pm "):e[0]&&r.push(e[0]),e[1]&&(mhchemParser.concatArray(r,mhchemParser.go(e[1],"pu-9,9")),e[2]&&(e[2].match(/[,.]/)?mhchemParser.concatArray(r,mhchemParser.go(e[2],"pu-9,9")):r.push(e[2])),e[3]=e[4]||e[3],e[3]&&(e[3]=e[3].trim(),"e"===e[3]||"*"===e[3].substr(0,1)?r.push({type_:"cdot"}):r.push({type_:"times"}))),e[3]&&r.push("10^{"+e[5]+"}"),r},"number^":function(t,e){var r=[];return"+-"===e[0]||"+/-"===e[0]?r.push("\\pm "):e[0]&&r.push(e[0]),mhchemParser.concatArray(r,mhchemParser.go(e[1],"pu-9,9")),r.push("^{"+e[2]+"}"),r},operator:function(t,e,r){return{type_:"operator",kind_:r||e}},space:function(){return{type_:"pu-space-1"}},output:function(t){var e,r=mhchemParser.patterns.match_("{(...)}",t.d||"");r&&""===r.remainder&&(t.d=r.match_);var a=mhchemParser.patterns.match_("{(...)}",t.q||"");if(a&&""===a.remainder&&(t.q=a.match_),t.d&&(t.d=t.d.replace(/\u00B0C|\^oC|\^{o}C/g,"{}^{\\circ}C"),t.d=t.d.replace(/\u00B0F|\^oF|\^{o}F/g,"{}^{\\circ}F")),t.q){t.q=t.q.replace(/\u00B0C|\^oC|\^{o}C/g,"{}^{\\circ}C"),t.q=t.q.replace(/\u00B0F|\^oF|\^{o}F/g,"{}^{\\circ}F");var n={d:mhchemParser.go(t.d,"pu"),q:mhchemParser.go(t.q,"pu")};"//"===t.o?e={type_:"pu-frac",p1:n.d,p2:n.q}:(e=n.d,n.d.length>1||n.q.length>1?e.push({type_:" / "}):e.push({type_:"/"}),mhchemParser.concatArray(e,n.q))}else e=mhchemParser.go(t.d,"pu-2");for(var o in t)delete t[o];return e}}},"pu-2":{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"*":{"*":{action_:["output","cdot"],nextState:"0"}},"\\x":{"*":{action_:"rm="}},space:{"*":{action_:["output","space"],nextState:"0"}},"^{(...)}|^(-1)":{1:{action_:"^(-1)"}},"-9.,9":{0:{action_:"rm=",nextState:"0"},1:{action_:"^(-1)",nextState:"0"}},"{...}|else":{"*":{action_:"rm=",nextState:"1"}}}),actions:{cdot:function(){return{type_:"tight cdot"}},"^(-1)":function(t,e){t.rm+="^{"+e+"}"},space:function(){return{type_:"pu-space-2"}},output:function(t){var e=[];if(t.rm){var r=mhchemParser.patterns.match_("{(...)}",t.rm||"");e=r&&""===r.remainder?mhchemParser.go(r.match_,"pu"):{type_:"rm",p1:t.rm}}for(var a in t)delete t[a];return e}}},"pu-9,9":{transitions:mhchemParser.createTransitions({empty:{0:{action_:"output-0"},o:{action_:"output-o"}},",":{0:{action_:["output-0","comma"],nextState:"o"}},".":{0:{action_:["output-0","copy"],nextState:"o"}},else:{"*":{action_:"text="}}}),actions:{comma:function(){return{type_:"commaDecimal"}},"output-0":function(t){var e=[];if(t.text_=t.text_||"",t.text_.length>4){var r=t.text_.length%3;0===r&&(r=3);for(var a=t.text_.length-3;a>0;a-=3)e.push(t.text_.substr(a,3)),e.push({type_:"1000 separator"});e.push(t.text_.substr(0,r)),e.reverse()}else e.push(t.text_);for(var n in t)delete t[n];return e},"output-o":function(t){var e=[];if(t.text_=t.text_||"",t.text_.length>4){for(var r=t.text_.length-3,a=0;a":case"→":case"⟶":return"\\yields";case"<-":return"\\yieldsLeft";case"<->":return"\\mesomerism";case"<--\x3e":return"\\yieldsLeftRight";case"<=>":case"⇌":return"\\equilibrium";case"<=>>":return"\\equilibriumRight";case"<<=>":return"\\equilibriumLeft";default:throw assertNever(t),["MhchemBugT","mhchem bug T. Please report."]}},_getBond:function(t){switch(t){case"-":case"1":return"{-}";case"=":case"2":return"{=}";case"#":case"3":return"{\\equiv}";case"~":return"{\\tripleDash}";case"~-":return"{\\tripleDashOverLine}";case"~=":case"~--":return"{\\tripleDashOverDoubleLine}";case"-~-":return"{\\tripleDashBetweenDoubleLine}";case"...":return"{{\\cdot}{\\cdot}{\\cdot}}";case"....":return"{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}";case"->":return"{\\rightarrow}";case"<-":return"{\\leftarrow}";case"<":return"{<}";case">":return"{>}";default:throw assertNever(t),["MhchemBugT","mhchem bug T. Please report."]}},_getOperator:function(t){switch(t){case"+":return" {}+{} ";case"-":return" {}-{} ";case"=":return" {}={} ";case"<":return" {}<{} ";case">":return" {}>{} ";case"<<":return" {}\\ll{} ";case">>":return" {}\\gg{} ";case"\\pm":return" {}\\pm{} ";case"\\approx":case"$\\approx$":return" {}\\approx{} ";case"v":case"(v)":return" \\downarrow{} ";case"^":case"(^)":return" \\uparrow{} ";default:throw assertNever(t),["MhchemBugT","mhchem bug T. Please report."]}}};function assertNever(t){}function assertString(t){} \ No newline at end of file diff --git a/contrib/physics/README.md b/contrib/physics/README.md deleted file mode 100644 index 5df6d4e6..00000000 --- a/contrib/physics/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# physics extension - -This extension adds to Temml many of the functions from the LaTeX [physics package](https://www.ctan.org/tex-archive/macros/latex/contrib/physics). - -You can download the `physics.js` file from this repository. - -### Usage - -This extension isn't part of core Temml, so the script should be separately included in the HTML page's ``. Place it _after_ the line that calls `temml.js`. - -```html - - -``` - -If you are working sever-side, just use `temml.cjs`. It already includes all the functions in `physics.js`. - -### Syntax - -All the functions in the physics extension are listed in the [physics section](https://temml.org/docs/en/supported.html#physics-and-chemistry) (below the fold) of the Temml docs. diff --git a/contrib/physics/physics.js b/contrib/physics/physics.js deleted file mode 100644 index 961e7f22..00000000 --- a/contrib/physics/physics.js +++ /dev/null @@ -1,131 +0,0 @@ -/* eslint-disable no-undef */ - -/**************************************************** - * - * physics.js - * - * Implements the Physics Package for LaTeX input. - * - * --------------------------------------------------------------------- - * - * The original version of this file is licensed as follows: - * Copyright (c) 2015-2016 Kolen Cheung . - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * --------------------------------------------------------------------- - * - * This file has been revised from the original in the following ways: - * 1. The interface is changed so that it can be called from Temml, not MathJax. - * 2. \Re and \Im are not used, to avoid conflict with existing LaTeX letters. - * - * This revision of the file is released under the MIT license. - * https://mit-license.org/ - */ -temml.__defineMacro("\\quantity", "{\\left\\{ #1 \\right\\}}"); -temml.__defineMacro("\\qty", "{\\left\\{ #1 \\right\\}}"); -temml.__defineMacro("\\pqty", "{\\left( #1 \\right)}"); -temml.__defineMacro("\\bqty", "{\\left[ #1 \\right]}"); -temml.__defineMacro("\\vqty", "{\\left\\vert #1 \\right\\vert}"); -temml.__defineMacro("\\Bqty", "{\\left\\{ #1 \\right\\}}"); -temml.__defineMacro("\\absolutevalue", "{\\left\\vert #1 \\right\\vert}"); -temml.__defineMacro("\\abs", "{\\left\\vert #1 \\right\\vert}"); -temml.__defineMacro("\\norm", "{\\left\\Vert #1 \\right\\Vert}"); -temml.__defineMacro("\\evaluated", "{\\left.#1 \\right\\vert}"); -temml.__defineMacro("\\eval", "{\\left.#1 \\right\\vert}"); -temml.__defineMacro("\\order", "{\\mathcal{O} \\left( #1 \\right)}"); -temml.__defineMacro("\\commutator", "{\\left[ #1 , #2 \\right]}"); -temml.__defineMacro("\\comm", "{\\left[ #1 , #2 \\right]}"); -temml.__defineMacro("\\anticommutator", "{\\left\\{ #1 , #2 \\right\\}}"); -temml.__defineMacro("\\acomm", "{\\left\\{ #1 , #2 \\right\\}}"); -temml.__defineMacro("\\poissonbracket", "{\\left\\{ #1 , #2 \\right\\}}"); -temml.__defineMacro("\\pb", "{\\left\\{ #1 , #2 \\right\\}}"); -temml.__defineMacro("\\vectorbold", "{\\boldsymbol{ #1 }}"); -temml.__defineMacro("\\vb", "{\\boldsymbol{ #1 }}"); -temml.__defineMacro("\\vectorarrow", "{\\vec{\\boldsymbol{ #1 }}}"); -temml.__defineMacro("\\va", "{\\vec{\\boldsymbol{ #1 }}}"); -temml.__defineMacro("\\vectorunit", "{{\\boldsymbol{\\hat{ #1 }}}}"); -temml.__defineMacro("\\vu", "{{\\boldsymbol{\\hat{ #1 }}}}"); -temml.__defineMacro("\\dotproduct", "\\mathbin{\\boldsymbol\\cdot}"); -temml.__defineMacro("\\vdot", "{\\boldsymbol\\cdot}"); -temml.__defineMacro("\\crossproduct", "\\mathbin{\\boldsymbol\\times}"); -temml.__defineMacro("\\cross", "\\mathbin{\\boldsymbol\\times}"); -temml.__defineMacro("\\cp", "\\mathbin{\\boldsymbol\\times}"); -temml.__defineMacro("\\gradient", "{\\boldsymbol\\nabla}"); -temml.__defineMacro("\\grad", "{\\boldsymbol\\nabla}"); -temml.__defineMacro("\\divergence", "{\\grad\\vdot}"); -//temml.__defineMacro("\\div", "{\\grad\\vdot}"); Not included in Temml. Conflicts w/LaTeX \div -temml.__defineMacro("\\curl", "{\\grad\\cross}"); -temml.__defineMacro("\\laplacian", "\\nabla^2"); -temml.__defineMacro("\\tr", "{\\operatorname{tr}}"); -temml.__defineMacro("\\Tr", "{\\operatorname{Tr}}"); -temml.__defineMacro("\\rank", "{\\operatorname{rank}}"); -temml.__defineMacro("\\erf", "{\\operatorname{erf}}"); -temml.__defineMacro("\\Res", "{\\operatorname{Res}}"); -temml.__defineMacro("\\principalvalue", "{\\mathcal{P}}"); -temml.__defineMacro("\\pv", "{\\mathcal{P}}"); -temml.__defineMacro("\\PV", "{\\operatorname{P.V.}}"); -// Temml does not use the next two lines. They conflict with LaTeX letters. -//temml.__defineMacro("\\Re", "{\\operatorname{Re} \\left\\{ #1 \\right\\}}"); -//temml.__defineMacro("\\Im", "{\\operatorname{Im} \\left\\{ #1 \\right\\}}"); -temml.__defineMacro("\\qqtext", "{\\quad\\text{ #1 }\\quad}"); -temml.__defineMacro("\\qq", "{\\quad\\text{ #1 }\\quad}"); -temml.__defineMacro("\\qcomma", "{\\text{,}\\quad}"); -temml.__defineMacro("\\qc", "{\\text{,}\\quad}"); -temml.__defineMacro("\\qcc", "{\\quad\\text{c.c.}\\quad}"); -temml.__defineMacro("\\qif", "{\\quad\\text{if}\\quad}"); -temml.__defineMacro("\\qthen", "{\\quad\\text{then}\\quad}"); -temml.__defineMacro("\\qelse", "{\\quad\\text{else}\\quad}"); -temml.__defineMacro("\\qotherwise", "{\\quad\\text{otherwise}\\quad}"); -temml.__defineMacro("\\qunless", "{\\quad\\text{unless}\\quad}"); -temml.__defineMacro("\\qgiven", "{\\quad\\text{given}\\quad}"); -temml.__defineMacro("\\qusing", "{\\quad\\text{using}\\quad}"); -temml.__defineMacro("\\qassume", "{\\quad\\text{assume}\\quad}"); -temml.__defineMacro("\\qsince", "{\\quad\\text{since}\\quad}"); -temml.__defineMacro("\\qlet", "{\\quad\\text{let}\\quad}"); -temml.__defineMacro("\\qfor", "{\\quad\\text{for}\\quad}"); -temml.__defineMacro("\\qall", "{\\quad\\text{all}\\quad}"); -temml.__defineMacro("\\qeven", "{\\quad\\text{even}\\quad}"); -temml.__defineMacro("\\qodd", "{\\quad\\text{odd}\\quad}"); -temml.__defineMacro("\\qinteger", "{\\quad\\text{integer}\\quad}"); -temml.__defineMacro("\\qand", "{\\quad\\text{and}\\quad}"); -temml.__defineMacro("\\qor", "{\\quad\\text{or}\\quad}"); -temml.__defineMacro("\\qas", "{\\quad\\text{as}\\quad}"); -temml.__defineMacro("\\qin", "{\\quad\\text{in}\\quad}"); -temml.__defineMacro("\\differential", "{\\text{d}}"); -temml.__defineMacro("\\dd", "{\\text{d}}"); -temml.__defineMacro("\\derivative", "{\\frac{\\text{d}{ #1 }}{\\text{d}{ #2 }}}"); -temml.__defineMacro("\\dv", "{\\frac{\\text{d}{ #1 }}{\\text{d}{ #2 }}}"); -temml.__defineMacro("\\partialderivative", "{\\frac{\\partial{ #1 }}{\\partial{ #2 }}}"); -temml.__defineMacro("\\variation", "{\\delta}"); -temml.__defineMacro("\\var", "{\\delta}"); -temml.__defineMacro("\\functionalderivative", "{\\frac{\\delta{ #1 }}{\\delta{ #2 }}}"); -temml.__defineMacro("\\fdv", "{\\frac{\\delta{ #1 }}{\\delta{ #2 }}}"); -temml.__defineMacro("\\innerproduct", "{\\left\\langle {#1} \\mid { #2} \\right\\rangle}"); -temml.__defineMacro("\\outerproduct", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -temml.__defineMacro("\\dyad", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -temml.__defineMacro("\\ketbra", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -temml.__defineMacro("\\op", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -temml.__defineMacro("\\expectationvalue", "{\\left\\langle {#1 } \\right\\rangle}"); -temml.__defineMacro("\\expval", "{\\left\\langle {#1 } \\right\\rangle}"); -temml.__defineMacro("\\ev", "{\\left\\langle {#1 } \\right\\rangle}"); -temml.__defineMacro("\\matrixelement", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); -temml.__defineMacro("\\matrixel", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); -temml.__defineMacro("\\mel", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); diff --git a/contrib/texvc/README.md b/contrib/texvc/README.md deleted file mode 100644 index 2b6d8cac..00000000 --- a/contrib/texvc/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# texvc extension - -This extension adds to Temml functions available in mediawiki pages. - -It omits the functions deprecated at -https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax - -You can download the `texvc.js` file from this repository. - -### Usage - -This extension isn't part of core Temml, so the script should be separately included in the HTML page's ``. Place it _after_ the line that calls `temml.js`. - -```html - - -``` - -If you are working sever-side, just use `temml.cjs`. It already includes all the functions in `texvc.js`. - -### Syntax - -All the functions in the _texvc_ extension are listed in the [Temml docs](https://temml.org/docs/en/supported.html). diff --git a/contrib/texvc/texvc.js b/contrib/texvc/texvc.js deleted file mode 100644 index ddd5b1aa..00000000 --- a/contrib/texvc/texvc.js +++ /dev/null @@ -1,61 +0,0 @@ -/* eslint-disable no-undef */ - -////////////////////////////////////////////////////////////////////// -// texvc.sty - -// The texvc package contains macros available in mediawiki pages. -// We omit the functions deprecated at -// https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax - -// We also omit texvc's \O, which conflicts with \text{\O} - -temml.__defineMacro("\\darr", "\\downarrow"); -temml.__defineMacro("\\dArr", "\\Downarrow"); -temml.__defineMacro("\\Darr", "\\Downarrow"); -temml.__defineMacro("\\lang", "\\langle"); -temml.__defineMacro("\\rang", "\\rangle"); -temml.__defineMacro("\\uarr", "\\uparrow"); -temml.__defineMacro("\\uArr", "\\Uparrow"); -temml.__defineMacro("\\Uarr", "\\Uparrow"); -temml.__defineMacro("\\N", "\\mathbb{N}"); -temml.__defineMacro("\\R", "\\mathbb{R}"); -temml.__defineMacro("\\Z", "\\mathbb{Z}"); -temml.__defineMacro("\\alef", "\\aleph"); -temml.__defineMacro("\\alefsym", "\\aleph"); -temml.__defineMacro("\\bull", "\\bullet"); -temml.__defineMacro("\\clubs", "\\clubsuit"); -temml.__defineMacro("\\cnums", "\\mathbb{C}"); -temml.__defineMacro("\\Complex", "\\mathbb{C}"); -temml.__defineMacro("\\Dagger", "\\ddagger"); -temml.__defineMacro("\\diamonds", "\\diamondsuit"); -temml.__defineMacro("\\empty", "\\emptyset"); -temml.__defineMacro("\\exist", "\\exists"); -temml.__defineMacro("\\harr", "\\leftrightarrow"); -temml.__defineMacro("\\hArr", "\\Leftrightarrow"); -temml.__defineMacro("\\Harr", "\\Leftrightarrow"); -temml.__defineMacro("\\hearts", "\\heartsuit"); -temml.__defineMacro("\\image", "\\Im"); -temml.__defineMacro("\\infin", "\\infty"); -temml.__defineMacro("\\isin", "\\in"); -temml.__defineMacro("\\larr", "\\leftarrow"); -temml.__defineMacro("\\lArr", "\\Leftarrow"); -temml.__defineMacro("\\Larr", "\\Leftarrow"); -temml.__defineMacro("\\lrarr", "\\leftrightarrow"); -temml.__defineMacro("\\lrArr", "\\Leftrightarrow"); -temml.__defineMacro("\\Lrarr", "\\Leftrightarrow"); -temml.__defineMacro("\\natnums", "\\mathbb{N}"); -temml.__defineMacro("\\plusmn", "\\pm"); -temml.__defineMacro("\\rarr", "\\rightarrow"); -temml.__defineMacro("\\rArr", "\\Rightarrow"); -temml.__defineMacro("\\Rarr", "\\Rightarrow"); -temml.__defineMacro("\\real", "\\Re"); -temml.__defineMacro("\\reals", "\\mathbb{R}"); -temml.__defineMacro("\\Reals", "\\mathbb{R}"); -temml.__defineMacro("\\sdot", "\\cdot"); -temml.__defineMacro("\\sect", "\\S"); -temml.__defineMacro("\\spades", "\\spadesuit"); -temml.__defineMacro("\\sub", "\\subset"); -temml.__defineMacro("\\sube", "\\subseteq"); -temml.__defineMacro("\\supe", "\\supseteq"); -temml.__defineMacro("\\thetasym", "\\vartheta"); -temml.__defineMacro("\\weierp", "\\wp"); diff --git a/docs/administration.md b/docs/administration.md deleted file mode 100644 index 321e5dfa..00000000 --- a/docs/administration.md +++ /dev/null @@ -1,385 +0,0 @@ - - - - - - Temml Administration - - - - -
- -# Temml Administration - -# Browser Support - -Temml works in browsers that support MathML. This includes Firefox and Safari. -It will [soon](https://www.igalia.com/2021/08/09/MathML-Progress.html) include -Chrome, Edge, Opera, Brave, and Vivaldi.\ -Temml will never work in Internet Explorer. - -# Installation - -You can download a zip file of Temml from the [releases page][] of the Temml repository -and serve Temml files from your own site. The minimum browser installation needs the -following files. The `css` file and font file must be in the same folder. - -[releases page]: https://github.com/ronkok/Temml/releases - -* temml.min.js -* Temml-Local.css -* Temml.woff2 - -A server-side installation should include `temml.cjs` instead of `temml.min.js`. - -#### Starter template - -```html - - - - - ... - - - - ... - -``` - -# API - -### Overview - -Say that you have an HTMLCollection of elements whose contents should be converted from TeX -strings to math. And also say that you wish to define two macros and a color with document-wide -scope. The code for such a conversion might look like this: - -```js -// Optional preamble. -const macros = temml.definePreamble( - `\\newcommand\\d[0]{\\operatorname{d}\\!} - \\def\\foo{x^2} - \\definecolor{sortaGreen}{RGB}{128,128,0}` -); -// Render all the math. -for (let aSpan of [...mathSpans]) { - const tex = aSpan.textContent; - const displayMode = aSpan.classList.contains("display"); - temml.render(tex, aSpan, { macros, displayMode }); -} -// Optional postProcess to render \ref{} -temml.postProcess(document.body); -``` - -Below, we examine the parts of that code. - -### In-Browser - -To render math in one DOM element, call `temml.render` with a TeX expression -and a DOM element to render into: - -```js -temml.render("c = \\pm\\sqrt{a^2 + b^2}", element); -``` - -### Server-Side - -To generate MathML on the server or to generate an MathML string of the -rendered math, you can use `temml.renderToString`: - -```js -const temml = require('./temml.cjs'); // if in Node.js -const mathML = temml.renderToString("c = \\pm\\sqrt{a^2 + b^2}"); -``` - -### Preamble - -To give document-wide scope to a set of macros or colors, define them in a preamble. - -```js -const macros = temml.definePreamble( - `\\newcommand\\d[0]{\\operatorname{d}\\!} - \\def\\foo{x^2} - \\definecolor{sortaGreen}{RGB}{128,128,0}` -); -``` - -Any valid [Temml macro](supported.html#macros) or [\definecolor](supported.html#style-color-size-and-font) -may be written into a preamble. Then include the resulting macros in the Temml options. - -### Options - -You can provide an object of options as the last argument to `temml.render` and `temml.renderToString`. For example: - -```js -temml.render( - "c = \\pm\\sqrt{a^2 + b^2}", - element, - { displayMode: true, macros } -); -``` - -Available options are: - -- `displayMode`: `boolean`. If `true` the math will be rendered in display mode, which will put the math in display style (so `\int` and `\sum` are large, for example), and will center the math on the page on its own line. If `false` the math will be rendered in inline mode. (default: `false`) - -- `macros`: `object`. A collection of custom macros. The easy way to create them is via a preamble, noted just above. Alternatively, you can provide a set of key-value pairs in which each key is a new Temml function name and each value is the expansion of the macro. Example: `macros: {"\\R": "\\mathbb{R}"}`. - -- `annotate`: `boolean`. If `true`, Temml will include an `` element that contains the input TeX string. Note: this will defeat [soft line breaks](./supported.html#line-breaks) in Firefox. (default: `false`) - -- `elementIsMath`: `boolean`. When you call the `temml.render()` function, you pass an `element` as an argument to the function. If that `element` is a span, then allow `elementIsMath` to remain `false` (the default), and Temml will create a new `` element inside the span. It you pass a `` element as the argument, then set `elementIsMath` to `true`. Then Temml will populate it with math contents. - -- `leqno`: `boolean`. If `true`, display math has `\tag`s rendered on the left instead of the right, like `\usepackage[leqno]{amsmath}` in LaTeX. (default: `false`) - -- `preventTagLap`: `boolean`. This option affects the horizontal alignment of `displayMode` math and `\tag`s. The default (`false`) acts in the LaTeX manner and centers the math. That’s good in a wide container, but if the container is narrow, the tag will overlap the math. The `preventTagLap: true` option acts differently. It will first place the tag and then center the math in the remainder of the container, with no overlap. If you are targeting mobile, `preventTagLap: true` is probably a good choice . - -- `colorIsTextColor`: `boolean`. In LaTeX, `\color` is a switch, but in early versions of MathJax and KaTeX, `\color` applied its color to a second argument, the way that LaTeX `\textcolor` works. Set option `colorIsTextColor` to `true` if you want `\color` to work like early MathJax or KaTeX. (default: `false`) - -- `errorColor`: `string`. A color string given in the format `"#XXX"` or `"#XXXXXX"`. This option determines the color that unsupported commands and invalid LaTeX are rendered in. (default: `#b22222`) - -- `maxSize`: `[number, number]`. This provides a way to cap all user-specified sizes, e.g. in `\rule{500em}{500em}`. The first number is the cap in `em` units, which will be applied to user-specified relative units. The second number is the cap in CSS `pt` units, which will be applied to user-specified absolute units. The default is `[Infinity, Infinity]`, which allows users to make elements and spaces arbitrarily large. - -- `maxExpand`: `number`. Limit the number of macro expansions to the specified number, to prevent e.g. infinite macro loops. If set to `Infinity`, the macro expander will try to fully expand as in LaTeX. (default: 1000) - -- `strict`: `boolean`. If `false` (similar to MathJax), allow features that make writing LaTeX convenient but are not actually supported by LaTeX. If `true` (LaTeX faithfulness mode), throw an error for any such transgressions. (default: `false`) -- `xml`: `boolean`. If `true`, Temml will write a namespace into the `` element. That namespace is `xmlns="http://www.w3.org/1998/Math/MathML"`. Such a namespace is unnecessary for modern browsers but may be helpful for other user agents. (default: `false`) - -- `trust`: `boolean` or `function` (default: `false`). If `false` (do not trust input), prevent any commands like `\includegraphics` that could enable adverse behavior, rendering them instead in `errorColor`. If `true` (trust input), allow all such commands. Provide a custom function `handler(context)` to customize behavior depending on the context (command, arguments e.g. a URL, etc.). A list of possible contexts: - - - `{command: "\\url", url, protocol}` - - `{command: "\\href", url, protocol}` - - `{command: "\\includegraphics", url, protocol}` - - `{command: "\\class", class}` - - `{command: "\\id", id}` - - `{command: "\\style", style}` - - `{command: "\\data", attributes}` - - Here are some sample trust settings: - - - Forbid specific command: `trust: (context) => context.command !== '\\includegraphics'` - - Allow specific command: `trust: (context) => context.command === '\\url'` - - Allow multiple specific commands: `trust: (context) => ['\\url', '\\href'].includes(context.command)` - - Allow all commands with a specific protocol: `trust: (context) => context.protocol === 'http'` - - Allow all commands with specific protocols: `trust: (context) => ['http', 'https', '_relative'].includes(context.protocol)` - - Allow all commands but forbid specific protocol: `trust: (context) => context.protocol !== 'file'` - - Allow certain commands with specific protocols: `trust: (context) => ['\\url', '\\href'].includes(context.command) && ['http', 'https', '_relative'].includes(context.protocol)` - -## Post Process - -The `postProcess` function implements the AMS functions `\ref` and `\label`. It should be called outside of any loop. - -The main Temml functions, `temml.render` and `temml.renderToString`, each operate on only one element at a time. In contrast, the `postProcess` function makes two passes through the entire document. If you choose not to support `\ref`, `postProcess` can be omitted. - -If Temml is used server-side, `\ref` and `\label` are still implemented at runtime with client-side JavaScript. A small file, `temmlPostProcess.js`, is provided to be installed in place of `temml.min.js`. It exposes one function: - -``` -temml.postProcess(document.body) -``` - -If you do not provide a runtime `postProcess`, everthing in Temml will work except `\ref`. - -If you use the [auto-render extension][https://github.com/ronkok/Temml/tree/main/contrib/auto-render], it includes the post-processor nuances. - -# Fonts - -Temml has several different pre-written CSS files. You should use only one and by that choice, you also choose a math font. There are several math fonts available and each has different advantages. - -**Cambria Math** comes pre-installed in Windows, Macs, and iOS, so it is the light-weight option. Cambria Math lacks roundhand glyphs, so you still have to serve a small (12 kb) font, `Temml.woff2`, in order to support `\mathscr{…}`. Sadly, Cambria Math radicals are sometimes too tall for their content. - -
More… - -You can mitigate the radical problem. It occurs because the font expects a cramped subscript when under a radical and Firefox does not perform that cramp. You can create your own cramp with braces. The expression `f{_c'}` will render just fine when `f_c'` renders poorly. - -
- -**Latin Modern** is a clone of Computer Modern and so is very home-like for readers accustomed to LaTeX documents. Rendering is excellent except that some line thicknesses may be too thin for some screens. This option also needs that additional 12kb `Temml.woff2` file in order to support `\mathscr{…}`. - -**Asana**, **STIX TWO**, and **XITS** can be served without the `Temml.woff2` file. - -Several other math fonts exist and you can try them out at Frédéric Wang’s [Mathematical OpenType Fonts][]. - -Where to find font files: - -- Temml.woff2 can be found in the Temml [dist folder][]. -- STIXTwoMath-Regular.woff2 is located at the STIX [repository](https://github.com/stipub/stixfonts/blob/master/fonts/static_otf_woff2/STIXTwoMath-Regular.woff2). -- The other fonts can be downloaded at [Mathematical OpenType Fonts][]. - -[Mathematical OpenType Fonts]: https://fred-wang.github.io/MathFonts/ - -If you want a different math font size, you can add a rule to your own page's CSS, like this example: - -```css -math { font-size: 125%; } -``` - -# Equation numbering - -In order to place automatic equation numbering in certain AMS environments, Temml contains these CSS rules: - -``` -.tml-eqn::before { - counter-increment: tmlEqnNo; - content: "(" counter(tmlEqnNo) ")"; -} -body { counter-reset: tmlEqnNo; } -``` - -You can overwrite the `content` rule to produce customized equation numbers. -For instance, if chapter three of your book is in its own html file, that file’s -`
` could contain: - -``` - -``` - -Then the automatic equation numbering in that chapter would look like: (3.1) - -If your site does not render automatic numbering properly, check if your other -CSS has overwritten the Temml counter-reset. - -# Extensions - -More Temml functionality can be added via the following extensions: - -* [auto-render][]: Find and render all math in a running HTML page. -* [mhchem][]: Write beautiful chemical equations easily. -* [physics][]: Implement much of the LaTeX `physics` package. -* [texvc][]: Provide functions used in wikimedia. - -[auto-render]: https://github.com/ronkok/Temml/tree/main/contrib/auto-render -[mhchem]: https://github.com/ronkok/Temml/tree/main/contrib/mhchem -[physics]: https://github.com/ronkok/Temml/tree/main/contrib/texvc -[texvc]: https://github.com/ronkok/Temml/tree/main/contrib/texvc - -To install extensions for browser use, include the appropriate file from the `contrib` folder of the Temml repository. Then reference the file in the `` of the HTML page. As in this `mhchem` example: - -```html - - ... - - - - -``` - -The extension reference must come after the reference to `temml.min.js`. - -For server-side use, just use `temml.cjs` instead of `temml.min.js`. `temml.cjs` includes `mhchem`, `physics`, and `texvc`. - -# Security - -Any HTML generated by Temml should be safe from ` - - - - - -
- -

Foreword

- -

This page compares the MathML output from four TeX-to-MathML conversion libraries. You should use Firefox or Safari to view this page because they can render the MathML today. MathML will be viewable in Chrome and Edge soon.

- -

MathJax and KaTeX of course also render math in other formats. This comparison is limited to MathML.

- -

Versions used are: Temml 0.6.9, MathJax 2.7.5, KaTeX 0.13.9, and TeXZilla 1.0.2.0

- -

Symbols

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Symbol/FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
+₮a+b₮\(a+b\)₭a+b₭₸a+b₸a+b
-₮a-b₮\(a-b\)₭a-b₭₸a-b₸a-b
!₮n!₮\(n!\)₭n!₭₸n!₸n!
\!₮a!b₮\(a!b\)₭a!b₭₸a!b₸a\!b
#₮\def\bar#1{#1^2} \bar{y}₮\(\def\bar#1{#1^2} \bar{y}\)₭\def\bar#1{#1^2} \bar{y}₭Not supported\def\bar#1{#1^2} \bar{y}
\#₮\#₮\(\#\)₭\#₭₸\#₸
%₮%a comment₮\(%a comment\)₭%a comment₭Not supported%a comment
\%₮\%₮\(\%\)₭\%₭₸\%₸
&₮\begin{matrix} a & b\cr c & d \end{matrix}₮\(\begin{matrix} a & b\\ c & d \end{matrix}\)₭\begin{matrix} a & b\\ c & d \end{matrix}₭₸\begin{matrix} a & b\\ c & d \end{matrix}₸\begin{matrix}
   a & b \\
   c & d
\end{matrix}
\&₮\&₮\(\&\)₭\&₭₸\&₸
'₮'₮\('\)₭'₭₸'₸
\'₮\text{\'{a}}₮Not supported₭\text{\'{a}}₭₸\text{\'{a}}₸\text{\'{a}}
(₮(₮\((\)₭(₭₸(₸
)₮)₮\()\)₭)₭₸)₸
\₮a\ b₮\(a\ b\)₭a\ b₭Not supporteda\ b
\"₮\text{\"{a}}₮Not supported₭\text{\"{a}}₭₸\text{\"{a}}₸\text{\"{a}}
\$₮\text{\textdollar}₮Not supported₭\text{\textdollar}₭₸\text{\textdollar}₸
\,₮a\,\,{b}₮\(a\,\,{b}\)₭a\,\,{b}₭₸a\,\,{b}₸a\,\,{b}
\.₮\text{\.{a}}₮Not supported₭\text{\.{a}}₭₸\text{\.{a}}₸\text{\.{a}}
\:₮a\:\:{b}₮\(a\:\:{b}\)₭a\:\:{b}₭₸a\:\:{b}₸a\:\:{b}
\;₮a\;\;{b}₮\(a\;\;{b}\)₭a\;\;{b}₭₸a\;\;{b}₸aa\;\;{b}
_₮x_i₮\(x_i\)₭x_i₭₸x_i₸x_i
\_₮\_₮\(\_\)₭\_₭₸\_₸
\`₮\text{\'{a}}₮Not supported₭\text{\'{a}}₭₸\text{\'{a}}₸\text{\'{a}}
<₮<₮\(<\)₭<₭₸<₸
\=₮\text{\={a}}₮Not supported₭\text{\={a}}₭₸\text{\={a}}₸\text{\={a}}
>₮>₮\( > \)₭>₭₸>₸
\>₮a\>\>{b}₮\(a\>\>{b}\)₭a\>\>{b}₭Not supporteda\>\>{b}
[₮[₮\([\)₭[₭₸[₸
]₮]₮\(]\)₭]₭₸]₸
{₮{a}₮\({a}\)₭{a}₭₸{a}₸{a}
}₮{a}₮\({a}\)₭{a}₭₸{a}₸{a}
\{₮\{₮\(\{\)₭\{₭₸\{₸
\}₮\}₮\(\}\)₭\}₭₸\}₸
|₮|₮\(|\)₭|₭₸|₸
\|₮\|₮\(\|\)₭\|₭₸\|₸
~₮\text{no~break}₮\(\text{no~break}\)₭\text{no~break}₭Not supported\text{no~break}
\~₮\text{\~{a}}₮Not supported₭\text{\~{a}}₭₸\text{\~{a}}₸\text{\~{a}}
\\₮\begin{matrix} a & b\\ c & d\end{matrix}₮\(\begin{matrix} a & b\\ c & d\end{matrix}\)₭\begin{matrix} a & b\\ c & d\end{matrix}₭₸\begin{matrix} a & b\\ c & d\end{matrix}₸\begin{matrix}
   a & b \\
   c & d
\end{matrix}
\\₮x \\ y₮\(x \\ y\)₭x \\ y₭₸x \\ y₸x \\ y
^₮x^i₮\(x^i\)₭x^i₭₸x^i₸x^i
\^₮\text{\^{a}}₮Not supported₭\text{\^{a}}₭₸\text{\^{a}}₸\text{\^{a}}
special fraction₮1\kern2mu \text{³⁄₄}₮\(1\kern2mu \text{³⁄₄}\)₭1\kern2mu \text{³⁄₄}₭Not supported1\kern2mu \text{³⁄₄}
- -

A

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\AA₮\text{\AA}₮Not supported₭\text{\AA}₭₸\text{\AA}₸\text{\AA}
\aa₮\text{\aa}₮Not supported₭\text{\aa}₭₸\text{\aa}₸\text{\aa}
\above₮{a \above{2pt} b+1}₮\({a \above{2pt} b+1}\)₭{a \above{2pt} b+1}₭Not supported{a \above{2pt} b+1}
\abovewithdelimsNot supported\(a+1 \abovewithdelims [ ] 1pt b\)Not supportedNot supporteda+1 \abovewithdelims [ ] 1pt b
\acute₮\acute e₮\(\acute e\)₭\acute e₭Not supported\acute e
\AE₮\text{\AE}₮Not supported₭\text{\AE}₭₸\text{\AE}₸\text{\AE}
\ae₮\text{\ae}₮Not supported₭\text{\ae}₭₸\text{\ae}₸\text{\ae}
\alef₮\alef₮\(\alef\)₭\alef₭Not supported
\alefsym₮\alefsym₮\(\alefsym\)₭\alefsym₭Not supported
\aleph₮\aleph₮\(\aleph\)₭\aleph₭₸\aleph₸
{align}₮₮\begin{align}a&=b+c\\d+e&=f\end{align}₮₮\[\begin{align}a &=b+c\\d+e&=f\end{align}\]₭₭\begin{align}a &=b+c\\d+e&=f\end{align}₭₭₸\begin{align}a&=b+c\\d+e&=f\end{align}₸\begin{align}
   a&=b+c \\
   d+e&=f
\end{align}
{align*}₮₮\begin{align*}a&=b+c\\d+e&=f\end{align*}₮₮\[\begin{align*}a &=b+c\\d+e&=f\end{align*}\]₭₭\begin{align*}a &=b+c\\d+e&=f\end{align*}₭₭₸\begin{align}a&=b+c\\d+e&=f\end{align}₸\begin{align*}
   a&=b+c \\
   d+e&=f
\end{align*}
{aligned}₮\begin{aligned}x&=y & a&=b+c\\x'&=y' & a'&=b'\end{aligned}₮\(\begin{aligned}x&=y & a&=b+c\\x'&=y' & a'&=b'\end{aligned}\)₭\begin{aligned}x&=y & a&=b+c\\x'&=y' & a'&=b'\end{aligned}₭₸\begin{aligned}x&=y & a&=b+c\\x'&=y' & a'&=b'\end{aligned}₸\begin{aligned}
x&=y & a&=b+c\\
x'&=y' & a'&=b'
\end{aligned}
{alignat}₮₮\begin{alignat}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignat}₮₮\[\begin{alignat}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignat}\]₭₭\begin{alignat}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignat}₭₭₸\begin{alignat}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignat}₸
{alignat*}₮₮\begin{alignat*}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignat*}₮₮\[\begin{alignat*}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignat*}\]₭₭\begin{alignat*}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignat*}₭₭₸\begin{alignat*}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignat*}₸
{alignedat}₮\begin{alignedat}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignedat}₮\(\begin{alignedat}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignedat}\)₭\begin{alignedat}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignedat}₭₸\begin{alignedat}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignedat}₸\begin{alignedat}{2}
   10&x+ &3&y = 2 \\
   3&x+&13&y = 4
\end{alignedat}
\allowbreakSupportedNot supportedNot supportedNot supported
\Alpha₮\Alpha₮\(\Alpha\)₭\Alpha₭₸\Alpha₸
\alpha₮\alpha₮\(\alpha\)₭\alpha₭₸\alpha₸
\amalg₮\amalg₮\(\amalg\)₭\amalg₭₸\amalg₸
\And₮\And₮\(\And\)₭\And₭Not supported
\andNot supported\(\and\)Not supportedNot supportedDeprecated
\angNot supported\(\ang\)Not supportedNot supportedDeprecated
\angl₮a_{\angl n}₮Not supported
See \enclose
₭a_{\angl n}₭Not supporteda_{\angl n}
\angle₮\angle₮\(\angle\)₭\angle₭₸\angle₸
\angln₮a_\angln₮Not supported
See \enclose
₭a_\angln₭Not supporteda_\angln
\approx₮\approx₮\(\approx\)₭\approx₭₸\approx₸
\approxeq₮\approxeq₮\(\approxeq\)₭\approxeq₭₸\approxeq₸
\arccos₮\arccos x₮\(\arccos x\)₭\arccos x₭₸\arccos x₸
\arcctg₮\arcctg x₮Not supported₭\arcctg x₭Not supported
\arcsin₮\arcsin x₮\(\arcsin x\)₭\arcsin x₭₸\arcsin x₸
\arctan₮\arctan x₮\(\arctan x\)₭\arctan x₭₸\arctan x₸
\arctg₮\arctg x₮Not supported₭\arctg x₭Not supported
\arg₮\arg₮\(\arg\)₭\arg₭₸\arg₸
\argmax₮\begin{matrix}\argmax x \\ \argmax_y x \\\argmax\limits_y x\end{matrix}₮Not supported₭\begin{matrix}\argmax x \\ \argmax_y x \\\argmax\limits_y x\end{matrix}₭Not supported
\argmin₮\argmin₮Not supported₭\argmin₭Not supported
{array}₮\begin{array}{cc}a&b\\c&d\end{array}₮\(\begin{array}{cc}a&b\\c&d\end{array}\)₭\begin{array}{cc}a&b\\c&d\end{array}₭₸\begin{array}{cc}a&b\\c&d\end{array}₸\begin{array}{cc}
   a & b \\
   c & d
\end{array}
{array}
with lines
₮\begin{array}{c|c:c}a & b & c \\ \hline d & e & f \\ \hdashline g & h & i\end{array}₮\(\begin{array}{c|c:c}a & b & c \\ \hline d & e & f \\ \hdashline g & h & i\end{array}\)₭\begin{array}{c|c:c}a & b & c \\ \hline d & e & f \\ \hdashline g & h & i\end{array}₭Not supported\begin{array}{c|c:c}
a & b & c \\ \hline
d & e & f\\
\hdashline g & h & i
\end{array}
\arrayNot supported\(\array{ a & b+1 \\ c+1 & d }\)Not supported₸\array{ a & b+1 \\ c+1 & d }₸\array{ a & b+1 \\ c+1 & d }
\arraystretch₮\def\arraystretch{1.5}\begin{array}{cc}a&b\\c&d\end{array}₮\(\def\arraystretch{1.5}\begin{array}{cc}a&b\\c&d\end{array}\)₭\def\arraystretch{1.5}\begin{array}{cc}a&b\\c&d\end{array}₭₸\def\arraystretch{1.5}\begin{array}{cc}a&b\\c&d\end{array}₸\def\arraystretch{1.5}
\begin{array}{cc}
   a & b \\
   c & d
\end{array}
\ArrowvertNot supported\(\Arrowvert\)Not supportedNot supported
\arrowvertNot supported\(\arrowvert\)Not supportedNot supported
\ast₮\ast₮\(\ast\)₭\ast₭₸\ast₸
\asymp₮\asymp₮\(\asymp\)₭\asymp₭₸\asymp₸
\atop₮{a \atop b}₮\({a \atop b}\)₭{a \atop b}₭₸{a \atop b}₸{a \atop b}
\atopwithdelimsNot supported\(a \atopwithdelims [ ] b\)Not supportedNot supporteda \atopwithdelims [ ] b
- -

B

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\backepsilon₮\backepsilon₮\(\backepsilon\)₭\backepsilon₭₸\backepsilon₸
\backprime₮\backprime₮\(\backprime\)₭\backprime₭₸\backprime₸
\backsim₮\backsim₮\(\backsim\)₭\backsim₭₸\backsim₸
\backsimeq₮\backsimeq₮\(\backsimeq\)₭\backsimeq₭₸\backsimeq₸
\backslash₮\backslash₮\(\backslash\)₭\backslash₭₸\backslash₸
\ballotx₮\ballotx₮Not supportedNot supportedNot supported
\bar₮\bar{y}₮\(\bar{y}\)₭\bar{y}₭₸\bar{y}₸\bar{y}
\barwedge₮\barwedge₮\(\barwedge\)₭\barwedge₭₸\barwedge₸
\Bbb₮\Bbb{ABC}₮\(\Bbb{ABC}\)₭\Bbb{ABC}₭Not supported\Bbb{ABC}
\Bbbk₮\Bbbk₮\(\Bbbk\)₭\Bbbk₭Not supported
\bboxNot supportedRequires extensionNot supportedNot supported
\bcancel₮\bcancel{5}₮\(\bcancel{5}\)₭\bcancel{5}₭Not supported\bcancel{5}
\because₮\because₮\(\because\)₭\because₭₸\because₸
\begin₮\begin{matrix} a & b\\ c & d\end{matrix}₮\(\begin{matrix} a & b\\ c & d\end{matrix}\)₭\begin{matrix} a & b\\ c & d\end{matrix}₭₸\begin{matrix} a & b\\ c & d\end{matrix}₸\begin{matrix}
   a & b \\
   c & d
\end{matrix}
\begingroup₮\begingroup a \endgroup₮\(\begingroup a \endgroup\)₭\begingroup a \endgroup₭Not supported\begingroup a\endgroup
\Beta₮\Beta₮\(\Beta\)₭\Beta₭₸\Beta₸
\beta₮\beta₮\(\beta\)₭\beta₭₸\beta₸
\beth₮\beth₮\(\beth\)₭\beth₭₸\beth₸
\between₮\between₮\(\between\)₭\between₭₸\between₸
\bf₮\bf AaBb12₮\(\bf AaBb12\)₭\bf AaBb12₭Not supported\bf AaBb12
\big₮\big(\big)₮\(\big(\big)\)₭\big(\big)₭₸\big(\big)₸\big(\big)
\Big₮\Big(\Big)₮\(\Big(\Big)\)₭\Big(\Big)₭₸\Big(\Big)₸\Big(\Big)
\bigcap₮\bigcap_0^n x \; \displaystyle \bigcap_0^n x₮\(\bigcap_0^n x \; \displaystyle \bigcap_0^n x\)₭\bigcap_0^n x \; \displaystyle \bigcap_0^n x₭₸\bigcap₸
\bigcirc₮\bigcirc₮\(\bigcirc\)₭\bigcirc₭₸\bigcirc₸
\bigcup₮\bigcup_0^n x \; \displaystyle \bigcup_0^n x₮\(\bigcup_0^n x \; \displaystyle \bigcup_0^n x\)₭\bigcup_0^n x \; \displaystyle \bigcup_0^n x₭₸\bigcup₸
\bigg₮\bigg(\bigg)₮\(\bigg(\bigg)\)₭\bigg(\bigg)₭₸\bigg(\bigg)₸\bigg(\bigg)
\Bigg₮\Bigg(\Bigg)₮\(\Bigg(\Bigg)\)₭\Bigg(\Bigg)₭₸\Bigg(\Bigg)₸\Bigg(\Bigg)
\biggl₮\biggl(₮\(\biggl(\)₭\biggl(₭₸\biggl(₸\biggl(
\Biggl₮\Biggl(₮\(\Biggl(\)₭\Biggl(₭₸\Biggl(₸\Biggl(
\biggm₮\biggm\vert₮\(\biggm\vert\)₭\biggm\vert₭₸\biggm\vert₸\biggm\vert
\Biggm₮\Biggm\vert₮\(\Biggm\vert\)₭\Biggm\vert₭₸\Biggm\vert₸\Biggm\vert
\biggr₮\biggr)₮\(\biggr)\)₭\biggr)₭₸\biggr)₸\biggr)
\Biggr₮\Biggr)₮\(\Biggr)\)₭\Biggr)₭₸\Biggr)₸\Biggr)
\bigl₮\bigl(₮\(\bigl(\)₭\bigl(₭₸\bigl(₸\bigl(
\Bigl₮\Bigl(₮\(\Bigl(\)₭\Bigl(₭₸\Bigl(₸\Bigl(
\bigm₮\bigm\vert₮\(\bigm\vert\)₭\bigm\vert₭₸\bigm\vert₸\bigm\vert
\Bigm₮\Bigm\vert₮\(\Bigm\vert\)₭\Bigm\vert₭₸\Bigm\vert₸\Bigm\vert
\bigodot₮\bigodot_0^n x \; \displaystyle \bigodot_0^n x₮\(\bigodot_0^n x \; \displaystyle \bigodot_0^n x\)₭\bigodot_0^n x \; \displaystyle \bigodot_0^n x₭₸\bigodot₸
\bigominusNot supportedNot supportedNot supported₸\bigominus₸
\bigoplus₮\bigoplus_0^n x \; \displaystyle \bigoplus_0^n x₮\(\bigoplus_0^n x \; \displaystyle \bigoplus_0^n x\)₭\bigoplus_0^n x \; \displaystyle \bigoplus_0^n x₭₸\bigoplus₸
\bigoslashNot supportedNot supportedNot supported₸\bigoslash₸
\bigotimes₮\bigotimes_0^n x \; \displaystyle \bigotimes_0^n x₮\(\bigotimes_0^n x \; \displaystyle \bigotimes_0^n x\)₭\bigotimes_0^n x \; \displaystyle \bigotimes_0^n x₭₸\bigotimes₸
\bigr₮\bigr)₮\(\bigr)\)₭\bigr)₭₸\bigr)₸\bigr)
\Bigr₮\Bigr)₮\(\Bigr)\)₭\Bigr)₭₸\Bigr)₸\Bigr)
\bigsqcapNot supportedNot supportedNot supported₸\bigsqcap₸
\bigsqcup₮\bigsqcup_0^n x \; \displaystyle \bigsqcup_0^n x₮\(\bigsqcup_0^n x \; \displaystyle \bigsqcup_0^n x\)₭\bigsqcup_0^n x \; \displaystyle \bigsqcup_0^n x₭₸\bigsqcup₸
\bigstar₮\bigstar₮\(\bigstar\)₭\bigstar₭₸\bigstar₸
\bigtriangledown₮\bigtriangledown₮\(\bigtriangledown\)₭\bigtriangledown₭₸\bigtriangledown₸
\bigtriangleup₮\bigtriangleup₮\(\bigtriangleup\)₭\bigtriangleup₭₸\bigtriangleup₸
\biguplus₮\biguplus_0^n x \; \displaystyle \biguplus_0^n x₮\(\biguplus_0^n x \; \displaystyle \biguplus_0^n x\)₭\biguplus_0^n x \; \displaystyle \biguplus_0^n x₭₸\biguplus₸
\bigvee₮\bigvee_0^n x \; \displaystyle \bigvee_0^n x₮\(\bigvee_0^n x \; \displaystyle \bigvee_0^n x\)₭\bigvee_0^n x \; \displaystyle \bigvee_0^n x₭₸\bigvee₸
\bigwedge₮\bigwedge_0^n x \; \displaystyle \bigwedge_0^n x₮\(\bigwedge_0^n x \; \displaystyle \bigwedge_0^n x\)₭\bigwedge_0^n x \; \displaystyle \bigwedge_0^n x₭₸\bigwedge₸
\binom₮\binom n k₮\(\binom n k\)₭\binom n k₭₸\binom n k₸\binom n k
\blacklozenge₮\blacklozenge₮\(\blacklozenge\)₭\blacklozenge₭₸\blacklozenge₸
\blacksquare₮\blacksquare₮\(\blacksquare\)₭\blacksquare₭₸\blacksquare₸
\blacktriangle₮\blacktriangle₮\(\blacktriangle\)₭\blacktriangle₭₸\blacktriangle₸
\blacktriangledown₮\blacktriangledown₮\(\blacktriangledown\)₭\blacktriangledown₭₸\blacktriangledown₸
\blacktriangleleft₮\blacktriangleleft₮\(\blacktriangleleft\)₭\blacktriangleleft₭₸\blacktriangleleft₸
\blacktriangleright₮\blacktriangleright₮\(\blacktriangleright\)₭\blacktriangleright₭₸\blacktriangleright₸
\bm₮\bm{AaBb}₮Not supported₭\bm{AaBb}₭Not supported\bm{AaBb}
{Bmatrix}₮\begin{Bmatrix}a&b\\c&d\end{Bmatrix}₮\(\begin{Bmatrix}a&b\\c&d\end{Bmatrix}\)₭\begin{Bmatrix}a&b\\c&d\end{Bmatrix}₭₸\begin{Bmatrix}a&b\\c&d\end{Bmatrix}₸\begin{Bmatrix}
   a & b \\
   c & d
\end{Bmatrix}
{bmatrix}₮\begin{bmatrix}a&b\\c&d\end{bmatrix}₮\(\begin{bmatrix}a&b\\c&d\end{bmatrix}\)₭\begin{bmatrix}a&b\\c&d\end{bmatrix}₭₸\begin{bmatrix}a&b\\c&d\end{bmatrix}₸\begin{bmatrix}
   a & b \\
   c & d
\end{bmatrix}
\bmod₮a \bmod b₮\(a \bmod b\)₭a \bmod b₭Not supporteda \bmod b
\bold₮\bold{AaBb123}₮\(\bold{AaBb123}\)₭\bold{AaBb123}₭Not supported\bold{AaBb123}
\boldsymbol₮\boldsymbol{AaBb0}₮\(\boldsymbol{AaBb0}\)₭\boldsymbol{AaBb0}₭₸\boldsymbol{AaBb0}₸\boldsymbol{AaBb0}
\bot₮\bot₮\(\bot\)₭\bot₭₸\bot₸
\Bot₮\Bot₮Not supportedNot supportedNot supported
\bowtie₮\bowtie₮\(\bowtie\)₭\bowtie₭₸\bowtie₸
\Box₮\Box₮\(\Box\)₭\Box₭₸\Box₸
\boxdot₮\boxdot₮\(\boxdot\)₭\boxdot₭₸\boxdot₸
\boxed₮\boxed{ab}₮\(\boxed{ab}\)₭\boxed{ab}₭₸\boxed{ab}₸\boxed{ab}
\boxminus₮\boxminus₮\(\boxminus\)₭\boxminus₭₸\boxminus₸
\boxplus₮\boxplus₮\(\boxplus\)₭\boxplus₭₸\boxplus₸
\boxtimes₮\boxtimes₮\(\boxtimes\)₭\boxtimes₭₸\boxtimes₸
\Bra₮\Bra{\psi}₮Requires extension₭\Bra{\psi}₭Not supported\Bra{\psi}
\bra₮\bra{\psi}₮Requires extension₭\bra{\psi}₭Not supported\bra{\psi}
\brace₮{n\brace k}₮\({n\brace k}\)₭{n\brace k}₭Not supported{n\brace k}
\brack₮{n\brack k}₮\({n\brack k}\)₭{n\brack k}₭Not supported{n\brack k}
\braket₮\braket{\phi|\psi}₮Not supported₭\braket{\phi|\psi}₭Not supported\braket{\phi|\psi}
\Braket₮\Braket{ϕ|\frac{∂^2}{∂ t^2}|ψ}₮Requires extenstionNot supportedNot supported\Braket{ϕ|\frac{∂^2}{∂ t^2}|ψ}
\breve₮\breve{eu}₮\(\breve{eu}\)₭\breve{eu}₭Not supported\breve{eu}
\buildrelNot supported\(\buildrel \rm def \over {:=}\)Not supported₸\buildrel \rm def \over {:=}₸\buildrel \rm def \over {:=}
\bull₮\bull₮\(\bull\)₭\bull₭Not supported
\bullet₮\bullet₮\(\bullet\)₭\bullet₭₸\bullet₸
\Bumpeq₮\Bumpeq₮\(\Bumpeq\)₭\Bumpeq₭₸\Bumpeq₸
\bumpeq₮\bumpeq₮\(\bumpeq\)₭\bumpeq₭₸\bumpeq₸
- -

C

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\CNot supported\(\C\)Not supportedNot supportedDeprecated
\c₮\text{\c{c}}₮Not supported₭\text{\c{c}}₭Not supported\text{\c{c}}
\cal₮\cal ABC₮Not supported₭\cal ABC₭Not supported\cal ABC
\cancel₮\cancel{5}₮\(\cancel{5}\)₭\cancel{5}₭Not supported\cancel{5}
\cancelto₮\cancelto{0}{x}₮Not supportedNot supportedNot supported
\Cap₮\Cap₮\(\Cap\)₭\Cap₭₸\Cap₸
\cap₮\cap₮\(\cap\)₭\cap₭₸\cap₸
{cases}₮\begin{cases}a&\text{if }b\\c&\text{if }d\end{cases}₮\(\begin{cases}a&\text{if }b\\c&\text{if }d\end{cases}\)₭\begin{cases}a&\text{if }b\\c&\text{if }d\end{cases}₭₸\begin{cases}a&\text{if }b\\c&\text{if }d\end{cases}₸\begin{cases}
   a &\text{if } b \\
   c &\text{if } d
\end{cases}
\casesNot supported\(\cases{ x & \text{if } x\ge 0\\ -x & \text{if } x\lt 0}\)Not supported₸\cases{ x & \text{if } x\ge 0\\ -x & \text{if } x\lt 0}₸\cases{x & \text{if } x\ge 0\\
- -x & \text{if } x\lt 0} -
{CD}₮₮\begin{CD} A @>a>> B\\@VbVV @AAcA \\ C @= D\end{CD}₮₮\(\begin{CD} A @>a>> B\\@VbVV @AAcA \\ C @= D\end{CD}\)₭₭\begin{CD} A @>a>> B\\@VbVV @AAcA \\ C @= D\end{CD}₭₭Not supported
\cdot₮\cdot₮\(\cdot\)₭\cdot₭₸\cdot₸
\cdotp₮\cdotp₮\(\cdotp\)₭\cdotp₭₸\cdotp₸
\cdots₮\cdots₮\(\cdots\)₭\cdots₭₸\cdots₸
\ce₮\ce{A\bond{~}B\bond{~-}C}₮\(\ce{A\bond{~}B\bond{~-}C}\)₭\ce{A\bond{~}B\bond{~-}C}₭Not supported\ce{A\bond{~}B\bond{~-}C}
Requires `mhchem` extension
\ceeNot supported\(\cee{C6H5-CHO}\)Not supportedNot supportedDeprecated by mhchem
\centerdot₮a\centerdot b₮\(a\centerdot b\)₭a\centerdot b₭Not supportedIn LaTeX, \centerdot is a small
square on the baseline, not
a centered dot.
\cfNot supported\(\cf{C6H5-CHO}\)Not supportedNot supportedDeprecated by mhchem
\cfrac₮\cfrac{2}{1+\cfrac{2}{1+\cfrac{2}{1}}}₮\(\cfrac{2}{1+\cfrac{2}{1+\cfrac{2}{1}}}\)₭\cfrac{2}{1+\cfrac{2}{1+\cfrac{2}{1}}}₭Not supported\cfrac{2}{1+\cfrac{2}{1+\cfrac{2}{1}}}
\char₮\char"263a₮Not supported
See \unicode
₭\char"263a₭Not supported\char"263a
\check₮\check{oe}₮\(\check{oe}\)₭\check{oe}₭₸\check{oe}₸\check{oe}
\ch₮\ch₮Not supported₭\ch₭Not supported
\checkmark₮\checkmark₮\(\checkmark\)₭\checkmark₭Not supported
\Chi₮\Chi₮\(\Chi\)₭\Chi₭Not supported
\chi₮\chi₮\(\chi\)₭\chi₭₸\chi₸
\choose₮{n+1 \choose k+2}₮\({n+1 \choose k+2}\)₭{n+1 \choose k+2}₭₸{n+1 \choose k+2}₸{n+1 \choose k+2}
\circ₮\circ₮\(\circ\)₭\circ₭₸\circ₸
\circeq₮\circeq₮\(\circeq\)₭\circeq₭₸\circeq₸
\circlearrowleft₮\circlearrowleft₮\(\circlearrowleft\)₭\circlearrowleft₭₸\circlearrowleft₸
\circlearrowright₮\circlearrowright₮\(\circlearrowright\)₭\circlearrowright₭₸\circlearrowright₸
\circledast₮\circledast₮\(\circledast\)₭\circledast₭₸\circledast₸
\circledcirc₮\circledcirc₮\(\circledcirc\)₭\circledcirc₭₸\circledcirc₸
\circleddash₮\circleddash₮\(\circleddash\)₭\circleddash₭₸\circleddash₸
\circledR₮\circledR₮\(\circledR\)₭\circledR₭Not supported
\circledS₮\circledS₮\(\circledS\)₭\circledS₭Not supported
\class₮ab\class{mathHighlight}{cdef}gh₮Not supportedNot supportedNot supportedab\class{mathHighlight}{cdef}gh
\clineNot supportedNot supportedNot supportedNot supported
\clubs₮\clubs₮\(\clubs\)₭\clubs₭Not supported
\clubsuit₮\clubsuit₮\(\clubsuit\)₭\clubsuit₭₸\clubsuit₸
\cnums₮\cnums₮\(\cnums\)₭\cnums₭Not supported
\coh₮\coh₮Not supportedNot supportedNot supported
\colon₮\colon₮\(\colon\)₭\colon₭₸\colon₸
\Colonapprox₮\Colonapprox₮Not supported₭\Colonapprox₭₸\Colonapprox₸
\colonapprox₮\colonapprox₮Not supported₭\colonapprox₭₸\colonapprox₸
\Coloneq₮\Coloneq₮Not supported₭\Coloneq₭₸\Coloneq₸
\coloneq₮\coloneq₮Not supported₭\coloneq₭₸\coloneq₸
\Coloneqq₮\Coloneqq₮Not supported₭\Coloneqq₭₸\Coloneqq₸
\coloneqq₮a \coloneqq b₮Not supported₭a \coloneqq b₭₸a \coloneqq b₸
\Colonsim₮\Colonsim₮Not supported₭\Colonsim₭₸\Colonsim₸
\colonsim₮\colonsim₮Not supported₭\colonsim₭₸\colonsim₸
\color₮\color{#0000FF} AaBb123₮\(\color{#0000FF} AaBb123\)₭\color{#0000FF} AaBb123₭₸\color{#0000FF} AaBb123₸\color{#0000FF} AaBb123
\colorbox₮\colorbox{red}{Black on red}₮\(\colorbox{red}{Black on red}\)₭\colorbox{red}{Black on red}₭₸\colorbox{red}{Black on red}₸\colorbox{red}{Black on red}
\complement₮\complement₮\(\complement\)₭\complement₭₸\complement₸
\Complex₮\Complex₮\(\Complex\)₭\Complex₭Not supported
\cong₮\cong₮\(\cong\)₭\cong₭₸\cong₸
\Coppa₮\Coppa₮Not supportedNot supportedNot supported
\coppa₮\coppa₮Not supportedNot supportedNot supported
\coprod₮\coprod_0^n x \; \displaystyle \coprod_0^n x₮\(\coprod_0^n x \; \displaystyle \coprod_0^n x\)₭\coprod_0^n x \; \displaystyle \coprod_0^n x₭₸\coprod₸
\copyright₮\copyright₮Not supported₭\copyright₭Not supported
\cos₮\cos x₮\(\cos x\)₭\cos x₭₸\cos x₸
\cosec₮\cosec x₮Not supported₭\cosec x₭Not supported
\cosh₮\cosh x₮\(\cosh x\)₭\cosh x₭₸\cosh x₸
\cot₮\cot x₮\(\cot x\)₭\cot x₭₸\cot x₸
\cotg₮\cotg x₮Not supported₭\cotg x₭Not supported
\coth₮\coth x₮\(\coth x\)₭\coth x₭₸\coth x₸
\cr₮\begin{matrix} a & b\cr c & d \end{matrix}₮\(\begin{matrix} a & b\\ c & d \end{matrix}\)₭\begin{matrix} a & b\\ c & d \end{matrix}₭₸\begin{matrix} a & b\\ c & d \end{matrix}₸\begin{matrix}
   a & b \cr
   c & d
\end{matrix}
\csc₮\csc x₮\(\csc x\)₭\csc x₭₸\csc x₸
\cssIdNot supportedNot supportedNot supported
\ctg₮\ctg x₮Not supported₭\ctg x₭Not supported
\cth₮\cth x₮Not supported₭\cth x₭Not supported
\Cup₮\Cup₮\(\Cup\)₭\Cup₭₸\Cup₸
\cup₮\cup₮\(\cup\)₭\cup₭₸\cup₸
\curlyeqprec₮\curlyeqprec₮\(\curlyeqprec\)₭\curlyeqprec₭₸\curlyeqprec₸
\curlyeqsucc₮\curlyeqsucc₮\(\curlyeqsucc\)₭\curlyeqsucc₭₸\curlyeqsucc₸
\curlyvee₮\curlyvee₮\(\curlyvee\)₭\curlyvee₭₸\curlyvee₸
\curlywedge₮\curlywedge₮\(\curlywedge\)₭\curlywedge₭₸\curlywedge₸
\curvearrowleft₮\curvearrowleft₮\(\curvearrowleft\)₭\curvearrowleft₭₸\curvearrowleft₸
\curvearrowright₮\curvearrowright₮\(\curvearrowright\)₭\curvearrowright₭₸\curvearrowright₸
- -

D

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\dag₮\dag₮Not supported₭\dag₭Not supported
\Dagger₮\Dagger₮\(\Dagger\)₭\Dagger₭Not supported
\dagger₮\dagger₮\(\dagger\)₭\dagger₭₸\dagger₸
\daleth₮\daleth₮\(\daleth\)₭\daleth₭₸\daleth₸
\Darr₮\Darr₮\(\Darr\)₭\Darr₭Not supported
\dArr₮\dArr₮\(\dArr\)₭\dArr₭Not supported
\darr₮\darr₮\(\darr\)₭\darr₭₸\darr₸
{darray}₮\begin{array}{cc}a & b\\c & d\end{array}₮\(\begin{array}{cc}a & b\\c & d\end{array}\)₭\begin{array}{cc}a & b\\c & d\end{array}₭₸\begin{array}{cc}a & b\\c & d\end{array}₸\begin{darray}{cc}
   a & b \\
   c & d
\end{darray}
\dashleftarrow₮\dashleftarrow₮\(\dashleftarrow\)₭\dashleftarrow₭₸\dashleftarrow₸
\dashrightarrow₮\dashrightarrow₮\(\dashrightarrow\)₭\dashrightarrow₭₸\dashrightarrow₸
\dashv₮\dashv₮\(\dashv\)₭\dashv₭₸\dashv₸
\dbinom₮\dbinom n k₮\(\dbinom n k\)₭\dbinom n k₭Not supported\dbinom n k
\dblcolon₮\dblcolon₮Not supported₭\dblcolon₭₸\dblcolon₸
{dcases}₮\begin{dcases}a&\text{if }b\\c&\text{if }d\end{dcases}₮Not supported₭\begin{dcases}a&\text{if }b\\c&\text{if }d\end{dcases}₭₸\begin{dcases}a&\text{if }b\\c&\text{if }d\end{dcases}₸\begin{dcases}
   a &\text{if } b \\
   c &\text{if } d
\end{dcases}
\ddag₮\ddag₮Not supported₭\ddag₭Not supported
\ddagger₮\ddagger₮\(\ddagger\)₭\ddagger₭₸\ddagger₸
\ddddot₮\ddddot x₮Not supportedNot supported₸\ddddot x₸
\dddot₮\dddot x₮Not supportedNot supported₸\dddot x₸
\ddot₮\ddot x₮\(\ddot x\)₭\ddot x₭₸\ddot x₸\ddot x
\ddots₮\ddots₮\(\ddots\)₭\ddots₭₸\ddots₸
\DeclareMathOperatorNot supported\(\DeclareMathOperator - {\myOp}{myOp} - \myOp(x)\) - Not supportedNot supported
\def₮\def\foo{x^2} \foo + \foo₮\(\def\foo{x^2} \foo + \foo\)₭\def\foo{x^2} \foo + \foo₭Not supported\def\foo{x^2} \foo + \foo
\definecolor₮\definecolor{sortaGreen}{RGB}{128,128,0} \color{sortaGreen} F=ma₮Not supportedNot supportedNot supported
\deg₮\deg x₮\(\deg x\)₭\deg x₭₸\deg x₸
\degree₮\degree₮Not supported₭\degree₭₸\degree₸
\delta₮\delta₮\(\delta\)₭\delta₭₸\delta₸
\Delta₮\Delta₮\(\Delta\)₭\Delta₭₸\Delta₸
\det₮\begin{matrix}\det x \\ \det_y x \\\det\limits_y x\end{matrix}₮\(\begin{matrix}\det x \\ \det_y x \\\det\limits_y x\end{matrix}\)₭\begin{matrix}\det x \\ \det_y x \\\det\limits_y x\end{matrix}₭₸\det₸
\DigammaNot supported\(\Digamma\)Not supportedNot supported
\digamma₮\digamma₮\(\digamma\)₭\digamma₭₸\digamma₸
\dfrac₮\dfrac{a-1}{b-1}₮\(\dfrac{a-1}{b-1}\)₭\dfrac{a-1}{b-1}₭Not supported\dfrac{a-1}{b-1}
\diagdown₮\diagdown₮\(\diagdown\)₭\diagdown₭Not supported
\diagup₮\diagup₮\(\diagup\)₭\diagup₭Not supported
\Diamond₮\Diamond₮\(\Diamond\)₭\Diamond₭₸\Diamond₸
\diamond₮\diamond₮\(\diamond\)₭\diamond₭₸\diamond₸
\diamonds₮\diamonds₮\(\diamonds\)₭\diamonds₭Not supported
\diamondsuit₮\diamondsuit₮\(\diamondsuit\)₭\diamondsuit₭₸\diamondsuit₸
\dim₮\dim x₮\(\dim x\)₭\dim x₭₸\dim x₸
\displaylinesNot supported\(\displaylines{a\\ a+b=c+d}\)Not supported₸\displaylines{a\\ a+b=c+d}₸\displaylines{a\\ a+b=c+d}
\displaystyle₮\displaystyle\sum_0^n₮\(\displaystyle\sum_0^n\)₭\displaystyle\sum_0^n₭₸\displaystyle\sum_0^n₸\displaystyle\sum_0^n
\div₮\div₮\(\div\)₭\div₭₸\div₸
\divideontimes₮\divideontimes₮\(\divideontimes\)₭\divideontimes₭₸\divideontimes₸
\dot₮\dot x₮\(\dot x\)₭\dot x₭₸\dot x₸\dot x
\Doteq₮\Doteq₮\(\Doteq\)₭\Doteq₭₸\Doteq₸
\doteq₮\doteq₮\(\doteq\)₭\doteq₭₸\doteq₸
\doteqdot₮\doteqdot₮\(\doteqdot\)₭\doteqdot₭₸\doteqdot₸
\dotplus₮\dotplus₮\(\dotplus\)₭\dotplus₭₸\dotplus₸
\dots₮x_1 + \dots + x_n₮\(x_1 + \dots + x_n\)₭x_1 + \dots + x_n₭₸x_1 + \dots + x_n₸x_1 + \dots + x_n
\dotsb₮x_1 +\dotsb + x_n₮\(x_1 +\dotsb + x_n\)₭x_1 +\dotsb + x_n₭Not supportedx_1 +\dotsb + x_n
\dotsc₮x,\dotsc,y₮\(x,\dotsc,y\)₭x,\dotsc,y₭Not supportedx,\dotsc,y
\dotsi₮\int_{A_1}\int_{A_2}\dotsi₮\(\int_{A_1}\int_{A_2}\dotsi\)₭\int_{A_1}\int_{A_2}\dotsi₭Not supported\int_{A_1}\int_{A_2}\dotsi
\dotsm₮x_1 x_2 \dotsm x_n₮\(x_1 x_2 \dotsm x_n\)₭x_1 x_2 \dotsm x_n₭Not supportedx_1 x_2 \dotsm x_n
\dotso₮\dotso₮\(\dotso\)₭\dotso₭Not supported
\doublebarwedge₮\doublebarwedge₮\(\doublebarwedge\)₭\doublebarwedge₭₸\doublebarwedge₸
\doublecap₮\doublecap₮\(\doublecap\)₭\doublecap₭Not supported
\doublecup₮\doublecup₮\(\doublecup\)₭\doublecup₭Not supported
\Downarrow₮\Downarrow₮\(\Downarrow\)₭\Downarrow₭₸\Downarrow₸
\downarrow₮\downarrow₮\(\downarrow\)₭\downarrow₭₸\downarrow₸
\downdownarrows₮\downdownarrows₮\(\downdownarrows\)₭\downdownarrows₭₸\downdownarrows₸
\downharpoonleft₮\downharpoonleft₮\(\downharpoonleft\)₭\downharpoonleft₭₸\downharpoonleft₸
\downharpoonright₮\downharpoonright₮\(\downharpoonright\)₭\downharpoonright₭₸\downharpoonright₸
{drcases}₮\begin{drcases}a&\text{if }b\\c&\text{if }d\end{drcases}₮Not supported₭\begin{drcases}a&\text{if }b\\c&\text{if }d\end{drcases}₭₸\begin{drcases}a&\text{if }b\\c&\text{if }d\end{drcases}₸\begin{drcases}
   a&\text{if }b\\
   c&\text{if }d
\end{drcases}
- -

E

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\ell₮\ell₮\(\ell\)₭\ell₭₸\ell₸
\elseNot supportedNot supportedNot supportedNot supported
\empty₮\empty₮\(\empty\)₭\empty₭₸\empty₸
\emptyset₮\emptyset₮\(\emptyset\)₭\emptyset₭₸\emptyset₸
\encloseNot supported
See \longdiv,
\angl, \phase
\(\enclose{longdiv}{500}\)
\(\enclose{actuarial}{500}\)
\(\enclose{phasorangle}{500}\)
Not supportedNot supported\enclose{longdiv}{500}
\enclose{actuarial}{500}
\enclose{phasorangle}{500}
Non-standard
\end₮\begin{matrix} a & b\\ c & d\end{matrix}₮\(\begin{matrix} a & b\\ c & d\end{matrix}\)₭\begin{matrix} a & b\\ c & d\end{matrix}₭₸\begin{matrix} a & b\\ c & d\end{matrix}₸\begin{matrix}
   a & b \\
   c & d
\end{matrix}
\endgroup₮\begingroup a \endgroup₮\(\begingroup a \endgroup\)₭\begingroup a \endgroup₭Not supported\begingroup a\endgroup
\enspace₮a\enspace b₮\(a\enspace b\)₭a\enspace b₭Not supporteda\enspace b
\Epsilon₮\Epsilon₮\(\Epsilon\)₭\Epsilon₭Not supported
\epsilon₮\epsilon₮\(\epsilon\)₭\epsilon₭₸\epsilon₸
\eqalignNot supported\(\eqalign{3x - 4y &= 5\\x + 7 &= -2y}\)Not supported₸\eqalign{3x - 4y &= 5\\x + 7 &= -2y}₸
\eqalignnoNot supported\(\eqalignno{3x - 4y &= 5 &(\dagger) \\ x + 7 &= -2y &(\ddagger)\\ z &= 2}\)Not supportedNot supported
\eqcirc₮\eqcirc₮\(\eqcirc\)₭\eqcirc₭₸\eqcirc₸
\Eqcolon₮\Eqcolon₮Not supported₭\Eqcolon₭₸\Eqcolon₸
\eqcolon₮\eqcolon₮Not supported₭\eqcolon₭₸\eqcolon₸
{equation}₮₮\begin{equation}\label{maxwell}\begin{split}∇·𝐃&=ρ_v \\ ∇·𝐁&=0 \end{split}\end{equation}₮₮\[\begin{equation}\begin{split}∇·𝐃&=ρ_v \\∇·𝐁&=0\end{split}\end{equation}\]₭₭\begin{equation}\begin{split}∇·𝐃&=ρ_v \\∇·𝐁&=0\end{split}\end{equation}₭₭Not supported\begin{equation}
\begin{split}
   ∇·𝐃&=ρ_v \\
   ∇·𝐁&=0
\end{split}
\end{equation}
{equation*}₮₮\begin{equation*}\begin{split}∇·𝐃&=ρ_v \\ ∇·𝐁&=0 \end{split}\end{equation*}₮₮\[\begin{equation*}\begin{split}∇·𝐃&=ρ_v \\∇·𝐁&=0\end{split}\end{equation*}\]₭₭\begin{equation*}\begin{split}∇·𝐃&=ρ_v \\∇·𝐁&=0\end{split}\end{equation*}₭₭Not supported
{eqnarray}Not supported\(\begin{eqnarray} -y &=& (x-1)^2 \\ - &=& (x-1)(x-1) \\ - &=& x^2 - 2x + 1 -\end{eqnarray}\)Not supportedNot supported
{eqnarray*}Not supported\(\begin{eqnarray*} -y &=& (x-1)^2 \\ - &=& (x-1)(x-1) \\ - &=& x^2 - 2x + 1 -\end{eqnarray*}\)Not supportedNot supported
\Eqqcolon₮\Eqqcolon₮Not supported₭\Eqqcolon₭₸\Eqqcolon₸
\eqqcolon₮\eqqcolon₮Not supported₭\eqqcolon₭₸\eqqcolon₸
\eqref₮\eqref{maxwell}₮Not supportedNot supportedNot supported
\eqsim₮\eqsim₮\(\eqsim\)₭\eqsim₭₸\eqsim₸
\eqslantgtr₮\eqslantgtr₮\(\eqslantgtr\)₭\eqslantgtr₭₸\eqslantgtr₸
\eqslantless₮\eqslantless₮\(\eqslantless\)₭\eqslantless₭₸\eqslantless₸
\equiv₮\equiv₮\(\equiv\)₭\equiv₭₸\equiv₸
\Eta₮\Eta₮\(\Eta\)₭\Eta₭₸\Eta₸
\eta₮\eta₮\(\eta\)₭\eta₭₸\eta₸
\eth₮\eth₮\(\eth\)₭\eth₭₸\eth₸
\euro₮\euro₮\(\euro\)Not supportedNot supported
\exist₮\exist₮\(\exist\)₭\exist₭Not supported
\exists₮\exists₮\(\exists\)₭\exists₭₸\exists₸
\exp₮\exp x₮\(\exp x\)₭\exp x₭₸\exp x₸
- -

F

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\fallingdotseq₮\fallingdotseq₮\(\fallingdotseq\)₭\fallingdotseq₭₸\fallingdotseq₸
\fbox₮\fbox{Hi there!}₮\(\fbox{Hi there!}\)₭\fbox{Hi there!}₭Not supported\fbox{Hi there!}
\fcolorbox₮\fcolorbox{red}{aqua}{A}₮\(\fcolorbox{red}{aqua}{A}\)₭\fcolorbox{red}{aqua}{A}₭Not supported\fcolorbox{red}{aqua}{A}
\female₮\female₮Not supportedNot supportedNot supported\female
\fiNot supportedNot supportedNot supportedNot supported
\Finv₮\Finv₮\(\Finv\)₭\Finv₭Not supported
\flat₮\flat₮\(\flat\)₭\flat₭₸\flat₸
\footnotesize₮\footnotesize footnotesize₮Not supported₭\footnotesize footnotesize₭Not supported\footnotesize footnotesize
\forall₮\forall₮\(\forall\)₭\forall₭₸\forall₸
\frac₮\frac{a+b}{c+d}₮\(\frac{a+b}{c+d}\)₭\frac{a+b}{c+d}₭₸\frac{a+b}{c+d}₸\frac{a+b}{c+d}
\frak₮\frak{AaBb}₮\(\frak{AaBb}\)₭\frak{AaBb}₭Not supported\frak{AaBb}
\frown₮\frown₮\(\frown\)₭\frown₭₸\frown₸
- -

G

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\Game₮\Game₮\(\Game\)₭\Game₭Not supported
\Gamma₮\Gamma₮\(\Gamma\)₭\Gamma₭₸\Gamma₸
\gamma₮\gamma₮\(\gamma\)₭\gamma₭₸\gamma₸
{gather}₮₮\begin{gather}a=b\\e=b+c\end{gather}₮₮\(\begin{gather}a=b\\e=b+c\end{gather}\)₭₭\begin{gather}a=b\\e=b+c\end{gather}₭₭₸\begin{gather}a=b\\e=b+c\end{gather}₸\begin{gather}
   a=b \\
   e=b+c
\end{gather}
{gather*}₮₮\begin{gather*}a=b\\e=b+c\end{gather*}₮₮\(\begin{gather*}a=b\\e=b+c\end{gather*}\)₭₭\begin{gather*}a=b\\e=b+c\end{gather*}₭₭₸\begin{gather*}a=b\\e=b+c\end{gather*}₸\begin{gather*}
   a=b \\
   e=b+c
\end{gather*}
{gathered}₮\begin{gathered}a=b\\e=b+c\end{gathered}₮\(\begin{gathered}a=b\\e=b+c\end{gathered}\)₭\begin{gathered}a=b\\e=b+c\end{gathered}₭₸\begin{gathered}a=b\\e=b+c\end{gathered}₸\begin{gathered}
   a=b \\
   e=b+c
\end{gathered}
\gcd₮\begin{matrix}\gcd x \\ \gcd_y x \\\gcd\limits_y x\end{matrix}₮\(\begin{matrix}\gcd x \\ \gcd_y x \\\gcd\limits_y x\end{matrix}\)₭\begin{matrix}\gcd x \\ \gcd_y x \\\gcd\limits_y x\end{matrix}₭₸\begin{matrix}\gcd x \\ \gcd_y x \\\gcd\limits_y x\end{matrix}₸
\gdefNot supportedNot supported₭\gdef\bar#1{#1^2} \bar{y} + \bar{y}₭Not supported\gdef\bar#1{#1^2} \bar{y} + \bar{y}
\ge₮\ge₮\(\ge\)₭\ge₭₸\ge₸
\geneuroNot supported\(\geneuro\)Not supportedNot supported
\geneuronarrowNot supported\(\geneuronarrow\)Not supportedNot supported
\geneurowideNot supported\(\geneurowide\)Not supportedNot supported
\genfrac₮\genfrac ( ] {2pt}{0}a{a+1}₮\(\genfrac ( ] {2pt}{0}a{a+1}\)₭\genfrac ( ] {2pt}{0}a{a+1}₭Not supported\genfrac ( ] {2pt}{0}a{a+1}
\geq₮\geq₮\(\geq\)₭\geq₭₸\geq₸
\geqq₮\geqq₮\(\geqq\)₭\geqq₭₸\geqq₸
\geqslant₮\geqslant₮\(\geqslant\)₭\geqslant₭₸\geqslant₸
\gets₮\gets₮\(\gets\)₭\gets₭Not supported
\gg₮\gg₮\(\gg\)₭\gg₭₸\gg₸
\ggg₮\ggg₮\(\ggg\)₭\ggg₭₸\ggg₸
\gggtr₮\gggtr₮\(\gggtr\)₭\gggtr₭Not supported
\gimel₮\gimel₮\(\gimel\)₭\gimel₭₸\gimel₸
\globalNot supported\(\global\def\add#1#2{#1+#2} \add 2 3\)₭\global\def\add#1#2{#1+#2} \add 2 3₭Not supported\global\def\add#1#2{#1+#2} \add 2 3
\gnapprox₮\gnapprox₮\(\gnapprox\)₭\gnapprox₭₸\gnapprox₸
\gneq₮\gneq₮\(\gneq\)₭\gneq₭₸\gneq₸
\gneqq₮\gneqq₮\(\gneqq\)₭\gneqq₭₸\gneqq₸
\gnsim₮\gnsim₮\(\gnsim\)₭\gnsim₭₸\gnsim₸
\grave₮\grave{eu}₮\(\grave{eu}\)₭\grave{eu}₭Not supported\grave{eu}
\gt₮a \gt b₮\(a \gt b\)₭a \gt b₭₸a \gt b₸a \gt b
\gtrdot₮\gtrdot₮\(\gtrdot\)₭\gtrdot₭₸\gtrdot₸
\gtrapprox₮\gtrapprox₮\(\gtrapprox\)₭\gtrapprox₭₸\gtrapprox₸
\gtreqless₮\gtreqless₮\(\gtreqless\)₭\gtreqless₭₸\gtreqless₸
\gtreqqless₮\gtreqqless₮\(\gtreqqless\)₭\gtreqqless₭₸\gtreqqless₸
\gtrless₮\gtrless₮\(\gtrless\)₭\gtrless₭₸\gtrless₸
\gtrsim₮\gtrsim₮\(\gtrsim\)₭\gtrsim₭₸\gtrsim₸
\gvertneqq₮\gvertneqq₮\(\gvertneqq\)₭\gvertneqq₭₸\gvertneqq₸
- -

H

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\H₮\text{\H{a}}₮Not supported₭\text{\H{a}}₭₸\text{\H{a}}₸\text{\H{a}}
\Harr₮\Harr₮\(\Harr\)₭\Harr₭Not supported
\hArr₮\hArr₮Not supported₭\hArr₭Not supported
\harr₮\harr₮\(\harr\)₭\harr₭Not supported
\hat₮\hat{\theta}₮\(\hat{\theta}\)₭\hat{\theta}₭₸\hat{\theta}₸\hat{\theta}
\hbar₮\hbar₮\(\hbar\)₭\hbar₭₸\hbar₸
\hbox₮\hbox{in a box}₮\(\hbox{in a box}\)₭\hbox{in a box}₭Not supported\hbox{in a box}
\hdashline₮\begin{matrix}a&b\\ \hdashline c &d\end{matrix}₮\(\begin{matrix}a&b\\ \hdashline c &d\end{matrix}\)₭\begin{matrix}a&b\\ \hdashline c &d\end{matrix}₭Not supported\begin{matrix}
   a & b \\
   \hdashline
   c & d
\end{matrix}
\hearts₮\hearts₮\(\hearts\)₭\hearts₭Not supported
\heartsuit₮\heartsuit₮\(\heartsuit\)₭\heartsuit₭₸\heartsuit₸
\hfilNot supportedSee \hfillNot supportedNot supported
\hfillNot supported\(\begin{matrix}xxxxxx & xxxxxx & xxxxxx \\ ab & \hfil ab & ab\hfil\\ \end{matrix}\)Not supportedNot supported
\hline₮\begin{matrix}a&b\\ \hline c &d\end{matrix}₮\(\begin{matrix}a&b\\ \hline c &d\end{matrix}\)₭\begin{matrix}a&b\\ \hline c &d\end{matrix}₭Not supported\begin{matrix}
   a & b \\ \hline
   c & d
\end{matrix}
\hom₮\hom x₮\(\hom x\)₭\hom x₭₸\hom x₸
\hookleftarrow₮\hookleftarrow₮\(\hookleftarrow\)₭\hookleftarrow₭₸\hookleftarrow₸
\hookrightarrow₮\hookrightarrow₮\(\hookrightarrow\)₭\hookrightarrow₭₸\hookrightarrow₸
\hphantom₮a\hphantom{bc}d₮\(a\hphantom{bc}d\)₭a\hphantom{bc}d₭Not supporteda\hphantom{bc}d
\href₮\href{https://www.mathjax.org/}{\text{MathJax}}₮\(\href{https://MathJax.org/}{\text{MathJax}}\)₭\href{https://MathJax.org/}{\text{MathJax}}₭Not supported\href{https://www.mathjax.org/}{\text{MathJax}}
\hskip₮w\hskip1em i\hskip2em d₮\(w\hskip1em i\hskip2em d\)₭w\hskip1em i\hskip2em d₭Not supportedw\hskip1em i\hskip2em d
\hslash₮\hslash₮\(\hslash\)₭\hslash₭₸\hslash₸
\hspace₮s\hspace7ex k₮\(s\hspace7ex k\)₭s\hspace7ex k₭Not supporteds\hspace7ex k
\htmlClass₮\htmlClass{foo}{x}₮Not supportedNot supportedNot supported\htmlClass{foo}{x}
\htmlData₮\htmlData{foo=a, bar=b}{x}₮Not supportedNot supportedNot supported\htmlData{foo=a, bar=b}{x}
\htmlId₮\htmlId{bar}{x}₮Not supportedNot supportedNot supported\htmlId{bar}{x}
\htmlStyle₮\htmlStyle{color: red;}{x}₮Not supportedNot supportedNot supported\htmlStyle{color: red;}{x}}
\huge₮\huge huge₮\(\huge huge\)₭\huge huge₭Not supported\huge huge
\Huge₮\Huge Huge₮\(\Huge Huge\)₭\Huge Huge₭Not supported\Huge Huge
- -

I

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\i₮\text{\i}₮Not supported₭\text{\i}₭₸\text{\i}₸\text{\i}
\idotsint₮\idotsint₮Not supportedNot supportedNot supported
\iddotsNot supportedNot supportedNot supportedNot supported
\ifNot supportedNot supportedNot supportedNot supported
\iff₮A\iff B₮\(A\iff B\)₭A\iff B₭₸A\iff B₸A\iff B
\ifmodeNot supportedNot supportedNot supportedNot supported
\ifxNot supportedNot supportedNot supportedNot supported
\iiiintNot supportedNot supportedNot supportedNot supported
\iiint₮\iiint_0^n x \; \displaystyle \iiint_0^n x₮\(\iiint_0^n x \; \displaystyle \iiint_0^n x\)₭\iiint_0^n x \; \displaystyle \iiint_0^n x₭₸\iiint₸
\iint₮\iint_0^n x \; \displaystyle \iint_0^n x₮\(\iint_0^n x \; \displaystyle \iint_0^n x\)₭\iint_0^n x \; \displaystyle \iint_0^n x₭₸\iint₸
\Im₮\Im₮\(\Im\)₭\Im₭₸\Im₸
\image₮\image₮\(\image\)₭\image₭Not supported
\imageof₮\imageof₮Not supported₭\imageof₭Not supported
\imath₮\imath₮\(\imath\)₭\imath₭₸\imath₸
\impliedby₮P\impliedby Q₮\(P\impliedby Q\)₭P\impliedby Q₭₸P\impliedby Q₸P\impliedby Q
\implies₮P\implies Q₮\(P\implies Q\)₭P\implies Q₭₸P\implies Q₸P\implies Q
\in₮\in₮\(\in\)₭\in₭₸\in₸
\includegraphics₮\includegraphics[height=0.8em, totalheight=0.9em, width=0.9em, alt=KA logo]{https://cdn.kastatic.org/images/apple-touch-icon-57x57-precomposed.new.png}₮Not supported₭\includegraphics[height=0.8em, totalheight=0.9em, width=0.9em, alt=KA logo]{https://cdn.kastatic.org/images/apple-touch-icon-57x57-precomposed.new.png}₭Not supported
\incoh₮\incoh₮Not supportedNot supportedNot supported
\inf₮\begin{matrix}\inf x \\ \inf_y x \\\inf\limits_y x\end{matrix}₮\(\begin{matrix}\inf x \\ \inf_y x \\\inf\limits_y x\end{matrix}\)₭\begin{matrix}\inf x \\ \inf_y x \\\inf\limits_y x\end{matrix}₭₸\inf₸
\infin₮\infin₮\(\infin\)₭\infin₭Not supported
\infty₮\infty₮\(\infty\)₭\infty₭₸\infty₸
\injlim₮\begin{matrix}\injlim x \\ \injlim_y x \\\injlim\limits_y x\end{matrix}₮\(\begin{matrix}\injlim x \\ \injlim_y x \\\injlim\limits_y x\end{matrix}\)₭\begin{matrix}\injlim x \\ \injlim_y x \\\injlim\limits_y x\end{matrix}₭Not supported\injlim x
\injlim_y x
\injlim\limits_y x
\int₮\int_0^n x \; \displaystyle \int_0^n x₮\(\int_0^n x \; \displaystyle \int_0^n x\)₭\int_0^n x \; \displaystyle \int_0^n x₭₸\int₸
\intercal₮\intercal₮\(\intercal\)₭\intercal₭₸\intercal₸
\intop₮\intop_0^n x \; \displaystyle \intop_0^n x₮\(\intop_0^n x \; \displaystyle \intop_0^n x\)₭\intop_0^n x \; \displaystyle \intop_0^n x₭Not supported
\invamp₮\invamp₮Not supportedNot supportedNot supported
\Iota₮\Iota₮\(\Iota\)₭\Iota₭₸\Iota₸
\iota₮\iota₮\(\iota\)₭\iota₭₸\iota₸
\isin₮\isin₮\(\isin\)₭\isin₭Not supported
\it₮{\it AaBb}₮\({\it AaBb}\)₭{\it AaBb}₭Not supported{\it AaBb}
- -

JK

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\j₮\text{\j}₮Not supported₭\text{\j}₭₸\text{\j}₸\text{\j}
\jmath₮\jmath₮\(\jmath\)₭\jmath₭₸\jmath₸
\Join₮\Join₮\(\Join\)₭\Join₭Not supported
\Kappa₮\Kappa₮\(\Kappa\)₭\Kappa₭₸\Kappa₸
\kappa₮\kappa₮\(\kappa\)₭\kappa₭₸\kappa₸
\ker₮\ker x₮\(\ker x\)₭\ker x₭₸\ker x₸
\kern₮I\kern-2.5pt R₮\(I\kern-2.5pt R\)₭I\kern-2.5pt R₭Not supportedI\kern-2.5pt R
\Ket₮\Ket{\psi}₮Requires extension₭\Ket{\psi}₭Not supported\Ket{\psi}
\ket₮\ket{\psi}₮Requires extension₭\ket{\psi}₭Not supported\ket{\psi}
\Koppa₮\Koppa₮Not supportedNot supportedNot supported
\koppa₮\koppa₮Not supportedNot supportedNot supported
- -

L

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\LNot supportedNot supportedNot supportedNot supported
\lNot supportedNot supportedNot supportedNot supported
\Lambda₮\Lambda₮\(\Lambda\)₭\Lambda₭₸\Lambda₸
\lambda₮\lambda₮\(\lambda\)₭\lambda₭₸\lambda₸
\labelSee {equation}SupportedNot supported
\land₮\land₮\(\land\)₭\land₭Not supported
\lang₮\lang A\rangle₮\(\lang A\rangle\)₭\lang A\rangle₭₸\lang A\rangle₸\lang A\rangle
\langle₮\langle A\rangle₮\(\langle A\rangle\)₭\langle A\rangle₭₸\langle A\rangle₸\langle A\rangle
\Larr₮\Larr₮\(\Larr\)₭\Larr₭Not supported
\lArr₮\lArr₮\(\lArr\)₭\lArr₭Not supported
\larr₮\larr₮\(\larr\)₭\larr₭Not supported
\large₮\large large₮\(\large large\)₭\large large₭Not supported\large large
\Large₮\Large Large₮\(\Large Large\)₭\Large Large₭Not supported\Large Large
\LARGE₮\LARGE LARGE₮\(\LARGE LARGE\)₭\LARGE LARGE₭Not supported\LARGE LARGE
\LaTeX₮\LaTeX₮\(\LaTeX\)₭\LaTeX₭Not supported
\lBrace₮\lBrace₮Not supported₭\lBrace₭Not supported
\lbrace₮\lbrace₮\(\lbrace\)₭\lbrace₭₸\lbrace₸
\lbrack₮\lbrack₮\(\lbrack\)₭\lbrack₭₸\lbrack₸
\lceil₮\lceil₮\(\lceil\)₭\lceil₭₸\lceil₸
\lcroofNot supportedNot supportedNot supportedNot supportedSee \enclose
\ldotp₮\ldotp₮\(\ldotp\)₭\ldotp₭Not supported
\ldots₮\ldots₮\(\ldots\)₭\ldots₭₸\ldots₸
\le₮\le₮\(\le\)₭\le₭₸\le₸
\leadsto₮\leadsto₮\(\leadsto\)₭\leadsto₭Not supported
\left₮\left\lbrace \frac ab \right.₮\(\left\lbrace \frac ab \right.\)₭\left\lbrace \frac ab \right.₭₸\left\lbrace \frac ab \right.₸\left\lbrace \frac ab \right.
\leftarrow₮\leftarrow₮\(\leftarrow\)₭\leftarrow₭₸\leftarrow₸
\Leftarrow₮\Leftarrow₮\(\Leftarrow\)₭\Leftarrow₭₸\Leftarrow₸
\leftarrowtail₮\leftarrowtail₮\(\leftarrowtail\)₭\leftarrowtail₭₸\leftarrowtail₸
\leftharpoondown₮\leftharpoondown₮\(\leftharpoondown\)₭\leftharpoondown₭₸\leftharpoondown₸
\leftharpoonup₮\leftharpoonup₮\(\leftharpoonup\)₭\leftharpoonup₭₸\leftharpoonup₸
\leftleftarrows₮\leftleftarrows₮\(\leftleftarrows\)₭\leftleftarrows₭₸\leftleftarrows₸
\Leftrightarrow₮\Leftrightarrow₮\(\Leftrightarrow\)₭\Leftrightarrow₭₸\Leftrightarrow₸
\leftrightarrow₮\leftrightarrow₮\(\leftrightarrow\)₭\leftrightarrow₭₸\leftrightarrow₸
\leftrightarrows₮\leftrightarrows₮\(\leftrightarrows\)₭\leftrightarrows₭₸\leftrightarrows₸
\leftrightharpoons₮\leftrightharpoons₮\(\leftrightharpoons\)₭\leftrightharpoons₭₸\leftrightharpoons₸
\leftrightsquigarrow₮\leftrightsquigarrow₮\(\leftrightsquigarrow\)₭\leftrightsquigarrow₭₸\leftrightsquigarrow₸
\leftrootNot supported\(\sqrt[3\leftroot1]{x}\)Not supportedNot supported
\leftthreetimes₮\leftthreetimes₮\(\leftthreetimes\)₭\leftthreetimes₭₸\leftthreetimes₸
\leq₮\leq₮\(\leq\)₭\leq₭₸\leq₸
\leqalignnoNot supportedNot supportedNot supported
\leqq₮\leqq₮\(\leqq\)₭\leqq₭₸\leqq₸
\leqslant₮\leqslant₮\(\leqslant\)₭\leqslant₭₸\leqslant₸
\lessapprox₮\lessapprox₮\(\lessapprox\)₭\lessapprox₭₸\lessapprox₸
\lessdot₮\lessdot₮\(\lessdot\)₭\lessdot₭₸\lessdot₸
\lesseqgtr₮\lesseqgtr₮\(\lesseqgtr\)₭\lesseqgtr₭₸\lesseqgtr₸
\lesseqqgtr₮\lesseqqgtr₮\(\lesseqqgtr\)₭\lesseqqgtr₭₸\lesseqqgtr₸
\lessgtr₮\lessgtr₮\(\lessgtr\)₭\lessgtr₭₸\lessgtr₸
\lesssim₮\lesssim₮\(\lesssim\)₭\lesssim₭₸\lesssim₸
\letNot supportedNot supportedNot supported
\lfloor₮\lfloor₮\(\lfloor\)₭\lfloor₭₸\lfloor₸
\lg₮\lg₮\(\lg\)₭\lg₭₸\lg₸
\lgroup₮\lgroup₮\(\lgroup\)₭\lgroup₭Not supported
\lhd₮\lhd₮\(\lhd\)₭\lhd₭₸\lhd₸
\lim₮\begin{matrix}\lim x \\ \lim_y x \\\lim\limits_y x\end{matrix}₮\(\begin{matrix}\lim x \\ \lim_y x \\\lim\limits_y x\end{matrix}\)₭\begin{matrix}\lim x \\ \lim_y x \\\lim\limits_y x\end{matrix}₭₸\lim_y x₸\lim x
\lim_y x
\lim\limits_y x
\liminf₮\begin{matrix}\liminf x \\ \liminf_y x \\\liminf\limits_y x\end{matrix}₮\(\begin{matrix}\liminf x \\ \liminf_y x \\\liminf\limits_y x\end{matrix}\)₭\begin{matrix}\liminf x \\ \liminf_y x \\\liminf\limits_y x\end{matrix}₭₸\liminf₸
\limits₮\lim\limits_x₮\(\lim\limits_x\)₭\lim\limits_x₭Not supported\lim\limits_x
\limsup₮\begin{matrix}\limsup x \\ \limsup_y x \\\limsup\limits_y x\end{matrix}₮\(\begin{matrix}\limsup x \\ \limsup_y x \\\limsup\limits_y x\end{matrix}\)₭\begin{matrix}\limsup x \\ \limsup_y x \\\limsup\limits_y x\end{matrix}₭₸\limsup₸
\ll₮\ll₮\(\ll\)₭\ll₭₸\ll₸
\llap₮{=}\llap{/\,}₮\({=}\llap{/\,}\)₭{=}\llap{/\,}₭Not supported{=}\llap{/\,}
\llbracket₮\llbracket₮Not supported₭\llbracket₭Not supported
\llcorner₮\llcorner a \lrcorner₮\(\llcorner a \lrcorner\)₭\llcorner a \lrcorner₭Not supported
\Lleftarrow₮\Lleftarrow₮\(\Lleftarrow\)₭\Lleftarrow₭₸\Lleftarrow₸
\lll₮\lll₮\(\lll\)₭\lll₭₸\lll₸
\llless₮\llless₮\(\llless\)₭\llless₭Not supported
\lmoustache₮\lmoustache₮\(\lmoustache\)₭\lmoustache₭₸\lmoustache₸
\ln₮\ln x₮\(\ln x\)₭\ln x₭₸\ln x₸
\lnapprox₮\lnapprox₮\(\lnapprox\)₭\lnapprox₭₸\lnapprox₸
\lneq₮\lneq₮\(\lneq\)₭\lneq₭₸\lneq₸
\lneqq₮\lneqq₮\(\lneqq\)₭\lneqq₭₸\lneqq₸
\longdiv₮\longdiv{45.2}₮Not supported
See \enclose
₭\longdiv{45.2}₭Not supported\longdiv{45.2}
\lnot₮\lnot₮\(\lnot\)₭\lnot₭Not supported
\lnsim₮\lnsim₮\(\lnsim\)₭\lnsim₭₸\lnsim₸
\log₮\begin{matrix}\log x \\ \log_y x \\ \log\limits_y x\end{matrix}₮\(\begin{matrix}\log x \\ \log_y x \\ \log\limits_y x\end{matrix}\)₭\begin{matrix}\log x \\ \log_y x \\ \log\limits_y x\end{matrix}₭₸\begin{matrix}\log x \\ \log_y x \\ \log\limits_y x\end{matrix}₸\log x
\log_y x
\log\limits_y x
\Longleftarrow₮\Longleftarrow₮\(\Longleftarrow\)₭\Longleftarrow₭₸\Longleftarrow₸
\longleftarrow₮\longleftarrow₮\(\longleftarrow\)₭\longleftarrow₭₸\longleftarrow₸
\Longleftrightarrow₮\Longleftrightarrow₮\(\Longleftrightarrow\)₭\Longleftrightarrow₭₸\Longleftrightarrow₸
\longleftrightarrow₮\longleftrightarrow₮\(\longleftrightarrow\)₭\longleftrightarrow₭₸\longleftrightarrow₸
\longmapsto₮\longmapsto₮\(\longmapsto\)₭\longmapsto₭₸\longmapsto₸
\Longrightarrow₮\Longrightarrow₮\(\Longrightarrow\)₭\Longrightarrow₭₸\Longrightarrow₸
\longrightarrow₮\longrightarrow₮\(\longrightarrow\)₭\longrightarrow₭₸\longrightarrow₸
\looparrowleft₮\looparrowleft₮\(\looparrowleft\)₭\looparrowleft₭₸\looparrowleft₸
\looparrowright₮\looparrowright₮\(\looparrowright\)₭\looparrowright₭₸\looparrowright₸
\lor₮\lor₮\(\lor\)₭\lor₭Not supported
\lower₮l\lower 2pt{owe}r₮\(l\lower 2pt{owe}r\)₭l\lower 2pt{owe}r₭Not supportedl\lower 2pt{owe}r
\lozenge₮\lozenge₮\(\lozenge\)₭\lozenge₭₸\lozenge₸
\lparen₮\lparen₮Not supported₭\lparen₭Not supported
\Lrarr₮\Lrarr₮\(\Lrarr\)₭\Lrarr₭Not supported
\lrArr₮\lrArr₮\(\lrArr\)₭\lrArr₭Not supported
\lrarr₮\lrarr₮\(\lrarr\)₭\lrarr₭Not supported
\lrcorner₮\lrcorner₮\(\lrcorner\)₭\lrcorner₭Not supported
\lq₮\lq₮Not supported₭\lq₭₸\lq₸
\Lsh₮\Lsh₮\(\Lsh\)₭\Lsh₭₸\Lsh₸
\lt₮\lt₮\(\lt\)₭\lt₭₸\lt₸
\ltimes₮\ltimes₮\(\ltimes\)₭\ltimes₭₸\ltimes₸
\lVert₮\lVert₮\(\lVert\)₭\lVert₭Not supported
\lvert₮\lvert₮\(\lvert\)₭\lvert₭Not supported
\lvertneqq₮\lvertneqq₮\(\lvertneqq\)₭\lvertneqq₭₸\lvertneqq₸
- -

M

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\male₮\male₮Not supportedNot supportedNot supported\male
\maltese₮\maltese₮\(\maltese\)₭\maltese₭Not supported
\mapsto₮\mapsto₮\(\mapsto\)₭\mapsto₭₸\mapsto₸
\mathbb₮\mathbb{AB}₮\(\mathbb{AB}\)₭\mathbb{AB}₭₸\mathbb{AB}₸\mathbb{AB}
\mathbf₮\mathbf{AaBb123}₮\(\mathbf{AaBb123}\)₭\mathbf{AaBb123}₭₸\mathbf{AaBb123}₸\mathbf{AaBb123}
\mathbin₮a\mathbin{!}b₮\(a\mathbin{!}b\)₭a\mathbin{!}b₭₸a\mathbin{!}b₸a\mathbin{!}b
\mathcal₮\mathcal{AaBb123}₮\(\mathcal{AaBb123}\)₭\mathcal{AaBb123}₭₸\mathcal{AaBb123}₸\mathcal{AaBb123}
\mathchoice₮a\mathchoice{\,}{\,\,}{\,\,\,}{\,\,\,\,}b₮\(a\mathchoice{\,}{\,\,}{\,\,\,}{\,\,\,\,}b\)₭a\mathchoice{\,}{\,\,}{\,\,\,}{\,\,\,\,}b₭Not supporteda\mathchoice{\,}{\,\,}{\,\,\,}{\,\,\,\,}b
\mathclap₮\displaystyle\sum_{\mathclap{1\le i\le n}} x_{i}₮Not supported₭\displaystyle\sum_{\mathclap{1\le i\le n}} x_{i}₭₸\displaystyle\sum_{\mathclap{1\le i\le n}} x_{i}₸\sum_{\mathclap{1\le i\le n}} x_{i}
\mathclose₮a + (b\mathclose\gt + c₮\(a + (b\mathclose\gt + c\)₭a + (b\mathclose\gt + c₭Not supporteda + (b\mathclose\gt + c
\mathellipsis₮\mathellipsis₮Not supported₭\mathellipsis₭Not supported
\mathfrak₮\mathfrak{AaBb}₮\(\mathfrak{AaBb}\)₭\mathfrak{AaBb}₭₸\mathfrak{AaBb}₸\mathfrak{AaBb}
\mathinner₮ab\mathinner{\text{inside}}cd₮\(ab\mathinner{\text{inside}}cd\)₭ab\mathinner{\text{inside}}cd₭Not supportedab\mathinner{\text{inside}}cd
\mathit₮\mathit{AaBb}₮\(\mathit{AaBb}\)₭\mathit{AaBb}₭₸\mathit{AaBb}₸\mathit{AaBb}
\mathllap₮{\mathrlap{\,/}{=}}₮Not supported₭{\mathrlap{\,/}{=}}₭₸{\mathrlap{\,/}{=}}₸\mathrlap{\,/}{=}
\mathnormal₮\mathnormal{AaBb\theta}₮Not supported₭\mathnormal{AaBb\theta}₭Not supported\mathnormal{AaBb\theta}
\mathop₮a \mathop{x} b₮\(a \mathop{x} b\)₭a \mathop{x} b₭₸a \mathop{x} b₸a \mathop{x} b
\mathopen₮a + \mathopen\lt b) + c₮\(a + \mathopen\lt b) + c\)₭a + \mathopen\lt b) + c₭₸a + \mathopen\lt b) + c₸a + \mathopen\lt b) + c
\mathord₮1\mathord{,}234{,}567₮\(1\mathord{,}234{,}567\)₭1\mathord{,}234{,}567₭Not supported1\mathord{,}234{,}567
\mathpunct₮A\mathpunct{-}B₮\(A\mathpunct{-}B\)₭A\mathpunct{-}B₭Not supportedA\mathpunct{-}B
\mathraiseboxNot supportedNot supportedNot supported₸h\mathraisebox{2pt}{ighe}r₸
\mathrel₮a \mathrel{\#} b₮\(a \mathrel{\#} b\)₭a \mathrel{\#} b₭₸a \mathrel{#} b₸a \mathrel{\#} b
\mathrlap₮{\displaystyle \int_0^{\mathrlap{2\pi}} x \,\mathrm{d} x}₮Not supported₭{\displaystyle \int_0^{\mathrlap{2\pi}} x \,\mathrm{d} x}₭₸{\displaystyle \int_0^{\mathrlap{2\pi}} x \,\mathrm{d} x}₸\int_0^{\mathrlap{2\pi}} x\,\mathrm{d} x
\mathring₮\mathring{a}₮\(\mathring{a}\)₭\mathring{a}₭Not supported\mathring{a}
\mathrm₮\mathrm{AaBb12\theta}₮\(\mathrm{AaBb12\theta}\)₭\mathrm{AaBb12\theta}₭₸\mathrm{AaBb12\theta}₸\mathrm{AaBb12\theta}
\mathscr₮\mathscr{AB}₮\(\mathscr{AB}\)₭\mathscr{AB}₭₸\mathscr{AB}₸\mathscr{AaBb123}
\mathsf₮\mathsf{AaBb123}₮\(\mathsf{AaBb123}\)₭\mathsf{AaBb123}₭₸\mathsf{AaBb123}₸\mathsf{AaBb123}
\mathsterling₮\mathsterling₮Not supported₭\mathsterling₭Not supported
\mathstrut₮\sqrt{\mathstrut\alpha}₮\(\sqrt{\mathstrut\alpha}\)₭\sqrt{\mathstrut\alpha}₭Not supported\sqrt{\mathstrut\alpha}
\mathtip₮\mathtip{a=b}{tip}₮Not supportedNot supportedNot supported\mathtip{a=b}{tip}s
\mathtt₮\mathtt{AaBb123}₮\(\mathtt{AaBb123}\)₭\mathtt{AaBb123}₭₸\mathtt{AaBb123}₸\mathtt{AaBb123}
\matrixNot supported\(\matrix{a & b \\ c & d}\)Not supported₸\matrix{a & b \\ c & d}₸\matrix{a & b \\ c & d}
{matrix}₮\begin{matrix}\frac A B&b\\\frac A B&d\end{matrix}₮\(\begin{matrix}\frac A B&b\\\frac A B&d\end{matrix}\)₭\begin{matrix}\frac A B&b\\\frac A B&d\end{matrix}₭₸\begin{matrix}\frac A B&b\\\frac A B&d\end{matrix}₸\begin{matrix}
   \frac A B & b \\
   \frac A B & d
\end{matrix}
\max₮\begin{matrix}\max x \\ \max_y x \\\max\limits_y x\end{matrix}₮\(\begin{matrix}\max x \\ \max_y x \\\max\limits_y x\end{matrix}\)₭\begin{matrix}\max x \\ \max_y x \\\max\limits_y x\end{matrix}₭₸\max₸
\mboxNot supported\(\mbox{in a box}\)Not supportedNot supported\mbox{in a box}
\measuredangle₮\measuredangle₮\(\measuredangle\)₭\measuredangle₭₸\measuredangle₸
\medspace₮a\medspace b₮Not supported₭a\medspace b₭₸a\medspace b₸a\medspace b
\mho₮\mho₮\(\mho\)₭\mho₭₸\mho₸
\mid₮\{x∈ℝ\mid x > 0\}₮\(\{x∈ℝ\mid x>0\}\)₭\{x∈ℝ\mid x > 0\}₭₸\{x∈ℝ\mid x>0\}₸\{x∈ℝ\mid x>0\}
\middle₮P\left(A\middle\vert B\right)₮\(P\left(A\middle\vert B\right)\)₭P\left(A\middle\vert B\right)₭Not supportedP\left(A\middle\vert B\right)
\min₮\begin{matrix}\min x \\ \min_y x \\\min\limits_y x\end{matrix}₮\(\begin{matrix}\min x \\ \min_y x \\\min\limits_y x\end{matrix}\)₭\begin{matrix}\min x \\ \min_y x \\\min\limits_y x\end{matrix}₭₸\min₸
\minusoNot supported
See \standardstate
Not supported₭\minuso₭Not supported
\mitNot supported\(\mit{\Gamma\Theta}\)Not supportedNot supported\mit{\Gamma\Theta}
\mkern₮a\mkern18mu b₮\(a\mkern18mu b\)₭a\mkern18mu b₭Not supporteda\mkern18mu b
\mmlToken?Not supportedNot supportedNot supported
\mod₮3\equiv 5 \mod 2₮\(3\equiv 5 \mod 2\)₭3\equiv 5 \mod 2₭₸3\equiv 5 \mod 2₸3\equiv 5 \mod 2
\models₮\models₮\(\models\)₭\models₭₸\models₸
\moveleftNot supported\(O\moveleft3pt O\)Not supportedNot supportedO\moveleft3pt O
\moverightNot supported\(O\moveright3pt O\)Not supportedNot supportedO\moveright3pt O
\mp₮\mp₮\(\mp\)₭\mp₭₸\mp₸
\mskip₮a\mskip{10mu}b₮\(a\mskip{10mu}b\)₭a\mskip{10mu}b₭₸a\mskip{10mu}b₸a\mskip{10mu}b
\mspaceNot supported\(a\mspace18mu b\)Not supportedNot supporteda\mspace18mu b
\Mu₮\Mu₮\(\Mu\)₭\Mu₭₸\Mu₸
\mu₮\mu₮\(\mu\)₭\mu₭₸\mu₸
\multicolumnNot supportedNot supportedNot supportedNot supported
{multline}₮₮\begin{multline} -\rm first\ line \\ -\rm second\ line \\ -\rm third\ line -\end{multline}₮₮\[\begin{multline} - \rm first\ line \\ - \rm second\ line \\ - \rm third\ line - \end{multline}\]Not supportedNot supported
{multline*}₮₮\begin{multline*} -\rm first\ line \\ -\rm second\ line \\ -\rm third\ line -\end{multline*}₮₮\[\begin{multline*} - \rm first\ line \\ - \rm second\ line \\ - \rm third\ line - \end{multline*}\]Not supportedNot supported
\multimap₮\multimap₮\(\multimap\)₭\multimap₭₸\multimap₸
\multimapboth₮\multimapboth₮Not supportedNot supportedNot supported
\multimapinv₮\multimapinv₮Not supportedNot supportedNot supported
- -

N

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\N₮\N₮\(\N\)₭\N₭Not supported
\nabla₮\nabla₮\(\nabla\)₭\nabla₭₸\nabla₸
\natnums₮\natnums₮\(\natnums\)₭\natnums₭Not supported
\natural₮\natural₮\(\natural\)₭\natural₭₸\natural₸
\negmedspace₮a\negmedspace b₮\(a\negmedspace b\)₭a\negmedspace b₭₸a\negmedspace b₸a\negmedspace b
\ncong₮\ncong₮\(\ncong\)₭\ncong₭₸\ncong₸
\ne₮\ne₮\(\ne\)₭\ne₭₸\ne₸
\nearrow₮\nearrow₮\(\nearrow\)₭\nearrow₭₸\nearrow₸
\neg₮\neg₮\(\neg\)₭\neg₭₸\neg₸
\negthickspace₮a\negthickspace b₮\(a\negthickspace b\)₭a\negthickspace b₭Not supporteda\negthickspace b
\negthinspace₮a\negthinspace b₮\(a\negthinspace b\)₭a\negthinspace b₭Not supporteda\negthinspace b
\neq₮\neq₮\(\neq\)₭\neq₭₸\neq₸
\newcommand₮\newcommand\chk{\checkmark} \chk₮\(\newcommand\chk{\checkmark} \chk\)₭\newcommand\chk{\checkmark} \chk₭Not supported\newcommand\chk{\checkmark} \chk
\newenvironmentNot supported\(\newenvironment{tinyit}{\tiny\it}{\normalsize\rm}\begin{tinyit}Really small.\end{tinyit}\)Not supportedNot supported\newenvironment{tinyit}{\tiny\it}{\normalsize\rm}
\begin{tinyit}Really small.\end{tinyit}
\NewextarrowNot supported\(\Newextarrow{\xrightharpoonup}{5,10}{0x21C0} A \xrightharpoonup{\text{note}} B\)Not supportedNot supported\Newextarrow{\xrightharpoonup}{5,10}{0x21C0}
A \xrightharpoonup{\text{note}} B
\newextarrowNot supported<Not supportedNot supportedNot supportedSpelling per LaTeX.
\newline₮a\newline b₮Not supported₭a\newline b₭Not supporteda\newline b
\nexists₮\nexists₮\(\nexists\)₭\nexists₭₸\nexists₸
\ngeq₮\ngeq₮\(\ngeq\)₭\ngeq₭₸\ngeq₸
\ngeqq₮\ngeqq₮\(\ngeqq\)₭\ngeqq₭₸\ngeqq₸
\ngeqslant₮\ngeqslant₮\(\ngeqslant\)₭\ngeqslant₭₸\ngeqslant₸
\ngtr₮\ngtr₮\(\ngtr\)₭\ngtr₭₸\ngtr₸
\ni₮\ni₮\(\ni\)₭\ni₭₸\ni₸
\nleftarrow₮\nleftarrow₮\(\nleftarrow\)₭\nleftarrow₭₸\nleftarrow₸
\nLeftarrow₮\nLeftarrow₮\(\nLeftarrow\)₭\nLeftarrow₭₸\nLeftarrow₸
\nLeftrightarrow₮\nLeftrightarrow₮\(\nLeftrightarrow\)₭\nLeftrightarrow₭₸\nLeftrightarrow₸
\nleftrightarrow₮\nleftrightarrow₮\(\nleftrightarrow\)₭\nleftrightarrow₭₸\nleftrightarrow₸
\nleq₮\nleq₮\(\nleq\)₭\nleq₭₸\nleq₸
\nleqq₮\nleqq₮\(\nleqq\)₭\nleqq₭₸\nleqq₸
\nleqslant₮\nleqslant₮\(\nleqslant\)₭\nleqslant₭₸\nleqslant₸
\nless₮\nless₮\(\nless\)₭\nless₭₸\nless₸
\nmid₮\nmid₮\(\nmid\)₭\nmid₭₸\nmid₸
\nobreakNot supportedNot supportedNot supportedNot supported
\nobreakspace₮a\nobreakspace b₮\(a\nobreakspace b\)₭a\nobreakspace b₭Not supporteda\nobreakspace b
\nolimits₮\lim\nolimits_x₮\(\lim\nolimits_x\)₭\lim\nolimits_x₭Not supported\lim\nolimits_x
\normalsize₮\normalsize normalsize₮\(\normalsize normalsize\)₭\normalsize normalsize₭Not supported\normalsize normalsize
\not₮\not =₮\(\not =\)₭\not =₭₸\not =₸\not =
\notagNot supportedNot supportedNot supported
\notin₮\notin₮\(\notin\)₭\notin₭₸\notin₸
\notni₮\notni₮Not supported₭\notni₭₸\notni₸
\nparallel₮\nparallel₮\(\nparallel\)₭\nparallel₭₸\nparallel₸
\nprec₮\nprec₮\(\nprec\)₭\nprec₭₸\nprec₸
\npreceq₮\npreceq₮\(\npreceq\)₭\npreceq₭₸\npreceq₸
\nRightarrow₮\nRightarrow₮\(\nRightarrow\)₭\nRightarrow₭₸\nRightarrow₸
\nrightarrow₮\nrightarrow₮\(\nrightarrow\)₭\nrightarrow₭₸\nrightarrow₸
\nshortmid₮\nshortmid₮\(\nshortmid\)₭\nshortmid₭₸\nshortmid₸
\nshortparallel₮\nshortparallel₮\(\nshortparallel\)₭\nshortparallel₭₸\nshortparallel₸
\nsim₮\nsim₮\(\nsim\)₭\nsim₭₸\nsim₸
\nsubset₮\nsubset₮Not supportedNot supported₸\nsubset₸
\nsubseteq₮\nsubseteq₮\(\nsubseteq\)₭\nsubseteq₭₸\nsubseteq₸
\nsubseteqq₮\nsubseteqq₮\(\nsubseteqq\)₭\nsubseteqq₭₸\nsubseteqq₸
\nsucc₮\nsucc₮\(\nsucc\)₭\nsucc₭₸\nsucc₸
\nsucceq₮\nsucceq₮\(\nsucceq\)₭\nsucceq₭₸\nsucceq₸
\nsupset₮\nsupset₮Not supportedNot supported₸\nsupset₸
\nsupseteq₮\nsupseteq₮\(\nsupseteq\)₭\nsupseteq₭₸\nsupseteq₸
\nsupseteqq₮\nsupseteqq₮\(\nsupseteqq\)₭\nsupseteqq₭Not supported
\ntriangleleft₮\ntriangleleft₮\(\ntriangleleft\)₭\ntriangleleft₭₸\ntriangleleft₸
\ntrianglelefteq₮\ntrianglelefteq₮\(\ntrianglelefteq\)₭\ntrianglelefteq₭₸\ntrianglelefteq₸
\ntriangleright₮\ntriangleright₮\(\ntriangleright\)₭\ntriangleright₭₸\ntriangleright₸
\ntrianglerighteq₮\ntrianglerighteq₮\(\ntrianglerighteq\)₭\ntrianglerighteq₭₸\ntrianglerighteq₸
\Nu₮\Nu₮\(\Nu\)₭\Nu₭₸\Nu₸
\nu₮\nu₮\(\nu\)₭\nu₭₸\nu₸
\nVDash₮\nVDash₮\(\nVDash\)₭\nVDash₭₸\nVDash₸
\nVdash₮\nVdash₮\(\nVdash\)₭\nVdash₭₸\nVdash₸
\nvDash₮\nvDash₮\(\nvDash\)₭\nvDash₭₸\nvDash₸
\nvdash₮\nvdash₮\(\nvdash\)₭\nvdash₭₸\nvdash₸
\nwarrow₮\nwarrow₮\(\nwarrow\)₭\nwarrow₭₸\nwarrow₸
- -

O

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\O₮\text{\O}₮Not supported₭\text{\O}₭₸\text{\O}₸\text{\O}
\o₮\text{\o}₮Not supported₭\text{\o}₭₸\text{\o}₸\text{\o}
\oc₮\oc₮Not supportedNot supportedNot supported
\odv₮\odv{f}{x}₮Not supportedNot supportedNot supported\odv{f}{x}
\odv*`₮\odv*{f}{x}₮Not supportedNot supportedNot supported\odv*{f}{x}
\odot₮\odot₮\(\odot\)₭\odot₭₸\odot₸
\OE₮\text{\OE}₮Not supported₭\text{\OE}₭₸\text{\OE}₸\text{\OE}
\oe₮\text{\oe}₮Not supported₭\text{\oe}₭₸\text{\oe}₸\text{\oe}
\officialeuroNot supported
See \euro
\(\officialeuro\)Not supportedNot supported
\oiiint₮\oiiint_0^n x \; \displaystyle \oiiint_0^n x₮\(\oiiint_0^n x \; \displaystyle \oiiint_0^n x\)₭\oiiint_0^n x \; \displaystyle \oiiint_0^n x₭₸\oiiint₸
\oiint₮\oiint_0^n x \; \displaystyle \oiint_0^n x₮\(\oiint_0^n x \; \displaystyle \oiint_0^n x\)₭\oiint_0^n x \; \displaystyle \oiint_0^n x₭₸\oiint₸
\oint₮\oint_0^n x \; \displaystyle \oint_0^n x₮\(\oint_0^n x \; \displaystyle \oint_0^n x\)₭\oint_0^n x \; \displaystyle \oint_0^n x₭₸\oint₸
\oldstyleNot supported
See \oldstylenums
\(\oldstyle 0123456\)Not supportedNot supported\oldstyle 0123456
\oldstylenums₮\oldstylenums{123}₮Not supportedNot supportedNot supported\oldstylenums{123}
\omega₮\omega₮\(\omega\)₭\omega₭₸\omega₸
\Omega₮\Omega₮\(\Omega\)₭\Omega₭₸\Omega₸
\Omicron₮\Omicron₮\(\Omicron\)₭\Omicron₭Not supported
\omicron₮\omicron₮\(\omicron\)₭\omicron₭₸\omicron₸
\ominus₮\ominus₮\(\ominus\)₭\ominus₭₸\ominus₸
\operatorname₮\operatorname{asin} x₮\(\operatorname{asin} x\)₭\operatorname{asin} x₭₸\operatorname{asin} x₸\operatorname{asin} x
\operatorname*₮\begin{matrix}\operatorname*{asin} x \\ \operatorname*{asin}_y x \\ \operatorname*{asin}\limits_y x\end{matrix}₮\(\begin{matrix}\operatorname*{asin} x \\ \operatorname*{asin}_y x \\ \operatorname*{asin}\limits_y x\end{matrix}\)₭\begin{matrix}\operatorname*{asin} x \\ \operatorname*{asin}_y x \\ \operatorname*{asin}\limits_y x\end{matrix}₭₸\operatorname*{func}\limits_a^b(x)₸\operatorname*{asin} x
\operatorname*{asin}_y x
\operatorname*{asin}\limits_y x\end
\oplus₮\oplus₮\(\oplus\)₭\oplus₭₸\oplus₸
\orNot supportedNot supportedNot supportedNot supported
\origof₮\origof₮Not supported₭\origof₭Not supported
\oslash₮\oslash₮\(\oslash\)₭\oslash₭₸\oslash₸
\otimes₮\otimes₮\(\otimes\)₭\otimes₭₸\otimes₸
\over₮{a+1 \over b+2}+c₮\({a+1 \over b+2}+c\)₭{a+1 \over b+2}+c₭₸{a+1 \over b+2}+c₸{a+1 \over b+2}+c
\overbrace₮\overbrace{x+⋯+x}^{n\text{ times}}₮\(\overbrace{x+⋯+x}^{n\text{ times}}\)₭\overbrace{x+⋯+x}^{n\text{ times}}₭₸\overbrace{x+⋯+x}^{n\text{ times}}₸\overbrace{x+⋯+x}^{n\text{ times}}
\overbracketNot supportedNot supportedNot supportedNot supported
\overgroup₮\overgroup{AB}₮Not supported₭\overgroup{AB}₭₸\overgroup{AB}₸\overgroup{AB}
\overleftarrow₮\overleftarrow{AB}₮\(\overleftarrow{AB}\)₭\overleftarrow{AB}₭₸\overleftarrow{AB}₸\overleftarrow{AB}
\overleftharpoon₮\overleftharpoon{AB}₮Not supported₭\overleftharpoon{AB}₭₸\overleftharpoon{AB}₸\overleftharpoon{AB}
\overleftrightarrow₮\overleftrightarrow{AB}₮\(\overleftrightarrow{AB}\)₭\overleftrightarrow{AB}₭₸\overleftrightarrow{AB}₸\overleftrightarrow{AB}
\overline₮\overline{\text{a long argument}}₮\(\overline{\text{a long argument}}\)₭\overline{\text{a long argument}}₭₸\overline{\text{a long argument}}₸\overline{\text{a long argument}}
\overlinesegmentNot supportedNot supportedNot supportedNot supported
\overparen₮\overparen{AB}₮\(\overparen{AB}\)Not supported₸\overparen{AB}₸See \overgroup
\Overrightarrow₮\Overrightarrow{AB}₮Not supported₭\Overrightarrow{AB}₭Not supported\Overrightarrow{AB}
\overrightarrow₮\overrightarrow{AB}₮\(\overrightarrow{AB}\)₭\overrightarrow{AB}₭₸\overrightarrow{AB}₸\overrightarrow{AB}
\overrightharpoon₮\overrightharpoon{ac}₮Not supported₭\overrightharpoon{ac}₭₸\overrightharpoon{ac}₸\overrightharpoon{ac}
\overset₮\overset{!}{=}₮\(\overset{!}{=}\)₭\overset{!}{=}₭₸\overset{!}{=}₸\overset{!}{=}
\overwithdelimsNot supported\(a \overwithdelims [ ] b\)Not supportedNot supported
\owns₮\owns₮\(\owns\)₭\owns₭Not supported
- -

P

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\P₮\text{\P}₮Not supported₭\text{\P}₭₸\text{\P}₸\text{\P}
\pagecolor?Not supportedNot supportedNot supportedDeprecated
\parallel₮\parallel₮\(\parallel\)₭\parallel₭₸\parallel₸
\parr₮\parr₮Not supportedNot supportedNot supported
\part??Not supportedNot supportedNot supportedDeprecated
\partial₮\partial₮\(\partial\)₭\partial₭₸\partial₸
\permil₮\permil₮Not supportedNot supportedNot supported
\pdv₮\pdv{f}{x,y}₮Not supportedNot supportedNot supported\pdv{f}{x,y}
\pdv*₮\pdv*{f}{x,y}₮Not supportedNot supportedNot supported\pdv*{f}{x,y}
\perp₮\perp₮\(\perp\)₭\perp₭₸\perp₸
\phantom₮\Gamma^{\phantom{i}j}_{i\phantom{j}k}₮\(\Gamma^{\phantom{i}j}_{i\phantom{j}k}\)₭\Gamma^{\phantom{i}j}_{i\phantom{j}k}₭₸\Gamma^{\phantom{i}j}_{i\phantom{j}k}₸\Gamma^{\phantom{i}j}_{i\phantom{j}k}
\phase₮120\text{V}\phase{78.2\degree}₮Not supported
See \enclose
₭120\text{V}\phase{78.2\degree}₭Not supported120\text{V}\phase{78.2\degree}
\Phi₮\Phi₮\(\Phi\)₭\Phi₭₸\Phi₸
\phi₮\phi₮\(\phi\)₭\phi₭₸\phi₸
\Pi₮\Pi₮\(\Pi\)₭\Pi₭₸\Pi₸
\pi₮\pi₮\(\pi\)₭\pi₭₸\pi₸
{picture}Not supportedNot supportedNot supportedNot supported
\pitchfork₮\pitchfork₮\(\pitchfork\)₭\pitchfork₭₸\pitchfork₸
\plim₮\plim₮Not supported₭\plim₭Not supported
\plusmn₮\plusmn₮\(\plusmn\)₭\plusmn₭Not supported
\pm₮\pm₮\(\pm\)₭\pm₭₸\pm₸
\pmatrixNot supported\(\pmatrix{a&b\\c&d}\)Not supported₸\pmatrix{a&b\\c&d}₸See {pmatrix}
{pmatrix}₮\begin{pmatrix}a&b\\c&d\end{pmatrix}₮\(\begin{pmatrix}a&b\\c&d\end{pmatrix}\)₭\begin{pmatrix}a&b\\c&d\end{pmatrix}₭₸\begin{pmatrix}a&b\\c&d\end{pmatrix}₸\begin{pmatrix}
   a & b \\
   c & d
\end{pmatrix}
\pmb₮\pmb{\mu}₮\(\pmb{\mu}\)₭\pmb{\mu}₭Not supported\pmb{\mu}
\pmod₮x\pmod a₮\(x\pmod a\)₭x\pmod a₭Not supportedx\pmod a
\pod₮x \pod a₮\(x \pod a\)₭x \pod a₭Not supportedx \pod a
\pounds₮\pounds₮Not supported₭\pounds₭Not supported
\Pr₮\begin{matrix}\Pr x \\ \Pr_y x \\\Pr\limits_y x\end{matrix}₮\(\begin{matrix}\Pr x \\ \Pr_y x \\\Pr\limits_y x\end{matrix}\)₭\begin{matrix}\Pr x \\ \Pr_y x \\\Pr\limits_y x\end{matrix}₭₸\Pr₸
\prec₮\prec₮\(\prec\)₭\prec₭₸\prec₸
\precapprox₮\precapprox₮\(\precapprox\)₭\precapprox₭₸\precapprox₸
\preccurlyeq₮\preccurlyeq₮\(\preccurlyeq\)₭\preccurlyeq₭₸\preccurlyeq₸
\preceq₮\preceq₮\(\preceq\)₭\preceq₭₸\preceq₸
\precnapprox₮\precnapprox₮\(\precnapprox\)₭\precnapprox₭₸\precnapprox₸
\precneqq₮\precneqq₮\(\precneqq\)₭\precneqq₭₸\precneqq₸
\precnsim₮\precnsim₮\(\precnsim\)₭\precnsim₭₸\precnsim₸
\precsim₮\precsim₮\(\precsim\)₭\precsim₭₸\precsim₸
\prescript₮\prescript{a}{2}{\mathbf{C}}^{5+}_{2}₮Not supported₭\prescript{a}{2}{\mathbf{C}}^{5+}_{2}₭Not supported\prescript{a}{2}{\mathbf{C}}^{5+}_{2}
\prime₮\prime₮\(\prime\)₭\prime₭₸\prime₸
\prod₮\prod_0^n x \; \displaystyle \prod_0^n x₮\(\prod_0^n x \; \displaystyle \prod_0^n x\)₭\prod_0^n x \; \displaystyle \prod_0^n x₭₸\prod₸
\projlim₮\projlim_n x₮\(\projlim_n x\)₭\projlim_n x₭Not supported\projlim_n x
\propto₮\propto₮\(\propto\)₭\propto₭₸\propto₸
\providecommand₮\providecommand\greet{\text{Hello}} \greet₮Not supported₭\providecommand\greet{\text{Hello}} \greet₭Not supported\providecommand\greet{\text{Hello}} \greet
\psi₮\psi₮\(\psi\)₭\psi₭₸\psi₸
\Psi₮\Psi₮\(\Psi\)₭\Psi₭₸\Psi₸
\pu₮{123~\mathchoice{\textstyle\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}}₮\({123~\mathchoice{\textstyle\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}}\)₭{123~\mathchoice{\textstyle\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}}₭Not supported\pu{123 kJ//mol}
- -

QR

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\QNot supported\(\Q\)Not supportedNot supportedSee \Bbb{Q}
\qquad₮a\qquad\qquad{b}₮\(a\qquad\qquad{b}\)₭a\qquad\qquad{b}₭₸a\qquad\qquad{b}₸a\qquad\qquad{b}
\quad₮a\quad\quad{b}₮\(a\quad\quad{b}\)₭a\quad\quad{b}₭₸a\quad\quad{b}₸a\quad\quad{b}
\R₮\R₮\(\R\)₭\R₭Not supported
\r₮\text{\r{a}}₮\(\text{\r{a}}\)₭\text{\r{a}}₭₸\text{\r{a}}₸\text{\r{a}}
\raise₮h\raise{2pt}{ighe}r₮\(h\raise{2pt}{ighe}r\)₭h\raise{2pt}{ighe}r₭Not supportedh\raise{2pt}{ighe}r
\raisebox₮h\raisebox{2pt}{ighe}r₮Not supported₭h\raisebox{2pt}{ighe}r₭Not supportedh\raisebox{2pt}{ighe}r
\rang₮\langle A\rang₮\(\langle A\rang\)₭\langle A\rang₭₸\langle A\rang₸\langle A\rang
\rangle₮\langle A\rangle₮\(\langle A\rangle\)₭\langle A\rangle₭₸\langle A\rangle₸\langle A\rangle
\Rarr₮\Rarr₮\(\Rarr\)₭\Rarr₭Not supported
\rArr₮\rArr₮\(\rArr\)₭\rArr₭Not supported
\rarr₮\rarr₮\(\rarr\)₭\rarr₭Not supported
\rBrace₮\rBrace₮Not supported₭\rBrace₭Not supported
\rbrace₮\rbrace₮\(\rbrace\)₭\rbrace₭₸\rbrace₸
\rbrack₮\rbrack₮\(\rbrack\)₭\rbrack₭₸\rbrack₸
{rcases}₮\begin{rcases}a&\text{if }b\\c&\text{if }d\end{rcases}₮Not supported₭\begin{rcases}a&\text{if }b\\c&\text{if }d\end{rcases}₭₸\begin{rcases}a&\text{if }b\\c&\text{if }d\end{rcases}₸\begin{rcases}
   a&\text{if }b\\
   c&\text{if }d
\end{rcases}
\rceil₮\rceil₮\(\rceil\)₭\rceil₭₸\rceil₸
\Re₮\Re₮\(\Re\)₭\Re₭₸\Re₸
\real₮\real₮\(\real\)₭\real₭Not supported
\Reals₮\Reals₮\(\Reals\)₭\Reals₭Not supported
\reals₮\reals₮\(\reals\)₭\reals₭Not supported
\ref₮\ref{maxwell}₮SupportedNot supportedNot supported\ref{maxwell}
\relaxNot supportedNot supported
\renewcommand₮\def\hail{Hi!}\renewcommand\hail{\text{Ahoy!}} \hail₮\(\def\hail{Hi!}\renewcommand\hail{\text{Ahoy!}} \hail\)₭\def\hail{Hi!}\renewcommand\hail{\text{Ahoy!}} \hail₭Not supported\def\hail{Hi!}
\renewcommand\hail{\text{Ahoy!}}
\hail
\renewenvironmentNot supportedNot supportedNot supported
\requireNot supportedNot supportedNot supported
\restriction₮\restriction₮\(\restriction\)₭\restriction₭Not supported
\rfloor₮\rfloor₮\(\rfloor\)₭\rfloor₭₸\rfloor₸
\rgroup₮\rgroup₮\(\rgroup\)₭\rgroup₭Not supported
\rhd₮\rhd₮\(\rhd\)₭\rhd₭₸\rhd₸
\Rho₮\Rho₮\(\Rho\)₭\Rho₭₸\Rho₸
\rho₮\rho₮\(\rho\)₭\rho₭₸\rho₸
\right₮\left.\frac a b\right)₮\(\left.\frac a b\right)\)₭\left.\frac a b\right)₭₸\left.\frac a b\right)₸\left.\frac a b\right)
\Rightarrow₮\Rightarrow₮\(\Rightarrow\)₭\Rightarrow₭₸\Rightarrow₸
\rightarrow₮\rightarrow₮\(\rightarrow\)₭\rightarrow₭₸\rightarrow₸
\rightarrowtail₮\rightarrowtail₮\(\rightarrowtail\)₭\rightarrowtail₭₸\rightarrowtail₸
\rightharpoondown₮\rightharpoondown₮\(\rightharpoondown\)₭\rightharpoondown₭₸\rightharpoondown₸
\rightharpoonup₮\rightharpoonup₮\(\rightharpoonup\)₭\rightharpoonup₭₸\rightharpoonup₸
\rightleftarrows₮\rightleftarrows₮\(\rightleftarrows\)₭\rightleftarrows₭₸\rightleftarrows₸
\rightleftharpoons₮\rightleftharpoons₮\(\rightleftharpoons\)₭\rightleftharpoons₭₸\rightleftharpoons₸
\rightrightarrows₮\rightrightarrows₮\(\rightrightarrows\)₭\rightrightarrows₭₸\rightrightarrows₸
\rightsquigarrow₮\rightsquigarrow₮\(\rightsquigarrow\)₭\rightsquigarrow₭₸\rightsquigarrow₸
\rightthreetimes₮\rightthreetimes₮\(\rightthreetimes\)₭\rightthreetimes₭₸\rightthreetimes₸
\risingdotseq₮\risingdotseq₮\(\risingdotseq\)₭\risingdotseq₭₸\risingdotseq₸
\rlap₮\rlap{\,/}{=}₮\(\rlap{\,/}{=}\)₭\rlap{\,/}{=}₭Not supported\rlap{\,/}{=}
\rm₮\rm AaBb12\theta₮\(\rm AaBb12\theta\)₭\rm AaBb12\theta₭Not supported\rm AaBb12\theta
\rmoustache₮\rmoustache₮\(\rmoustache\)₭\rmoustache₭₸\rmoustache₸
\rootNot supported\(\root 3 \of x\)Not supported₸\root{3}{x}₸MathJax and TeXZilla differ in syntax:
\root 3 \of x vs. \root{3}{x}
\rotateboxNot supportedNot supportedNot supportedNot supported
\rparen₮\rparen₮Not supported₭\rparen₭Not supported
\rq₮\rq₮Not supported₭\rq₭₸\rq₸
\Rrightarrow₮\Rrightarrow₮\(\Rrightarrow\)₭\Rrightarrow₭₸\Rrightarrow₸
\rrbracket₮\rrbracket₮Not supported₭\rrbracket₭Not supported
\Rsh₮\Rsh₮\(\Rsh\)₭\Rsh₭₸\Rsh₸
\rtimes₮\rtimes₮\(\rtimes\)₭\rtimes₭₸\rtimes₸
\RuleNot supported\(x\Rule{3px}{0.5ex}{2ex}x\)Not supportedNot supportedNon-standard
\rule₮x\color{blue}\rule[6pt]{2ex}{1ex}x₮\(x\color{blue}\rule[6pt]{2ex}{1ex}x\)₭x\color{blue}\rule[6pt]{2ex}{1ex}x₭Not supportedx\color{blue}\rule[6pt]{2ex}{1ex}x
\rVert₮\rVert₮\(\rVert\)₭\rVert₭Not supported
\rvert₮\rvert₮\(\rvert\)₭\rvert₭Not supported
- -

S

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\S₮\text{\S}₮Not supported₭\text{\S}₭₸\text{\S}₸\text{\S}
\Sampi₮\Sampi₮Not supportedNot supportedNot supported
\sampi₮\sampi₮Not supportedNot supportedNot supported
\scaleboxNot supportedNot supportedNot supportedNot supported
\scoh₮\scoh₮Not supportedNot supportedNot supported
\scrNot supported\(\scr M\)Not supportedNot supported\scr M
\scriptscriptstyle₮\scriptscriptstyle \frac cd₮\(\scriptscriptstyle \frac cd\)₭\scriptscriptstyle \frac cd₭Not supported\scriptscriptstyle \frac cd
\scriptsize₮\scriptsize scriptsize₮\(\scriptsize scriptsize\)₭\scriptsize scriptsize₭₸\scriptsize scriptsize₸\scriptsize scriptsize
\scriptstyle₮\frac ab + {\scriptstyle \frac cd}₮\(\frac ab + {\scriptstyle \frac cd}\)₭\frac ab + {\scriptstyle \frac cd}₭Not supported\frac ab + {\scriptstyle \frac cd}
\sdot₮\sdot₮\(\sdot\)₭\sdot₭Not supported
\searrow₮\searrow₮\(\searrow\)₭\searrow₭₸\searrow₸
\sec₮\sec₮\(\sec\)₭\sec₭₸\sec₸
\sect₮\text{\sect}₮Not supported₭\text{\sect}₭Not supported\text{\sect}
\set₮\set{ x | x<5 }₮Requires extensionNot supportedNot supported\Set{x|x<5}
\Set₮\Set{ x | x<\frac 1 2 }₮Requires extensionNot supportedNot supported\Set{ x | x<\frac 1 2 }
\setlengthNot supportedNot supportedNot supportedNot supported
\setminus₮\setminus₮\(\setminus\)₭\setminus₭₸\setminus₸
\sf₮\sf AaBb123₮\(\sf AaBb123\)₭\sf AaBb123₭Not supported\sf AaBb123
\sgn₮\sgn₮Not supportedNot supportedNot supported
\sharp₮\sharp₮\(\sharp\)₭\sharp₭₸\sharp₸
\shift₮\shift₮Not supportedNot supportedNot supported
\shneg₮\shneg₮Not supportedNot supportedNot supported
\shortmid₮\shortmid₮\(\shortmid\)₭\shortmid₭₸\shortmid₸
\shortparallel₮\shortparallel₮\(\shortparallel\)₭\shortparallel₭₸\shortparallel₸
\shoveleftNot supported\(\begin{multline*} -\rm first\ line \\ -\shoveleft{\rm 2nd} \\ -\rm third\ line -\end{multline*}\)Not supportedNot supported
\shoverightNot supported\(\begin{multline*} -\rm first\ line \\ -\shoveright{\rm 2nd} \\ -\rm third\ line -\end{multline*}\)Not supportedNot supported
\shpos₮\shpos₮Not supportedNot supportedNot supported
\sideset₮\sideset{_1^2}{_3^4}\sum₮Not supportedNot supported₸\sideset{_1^2}{_3^4}\sum₸
\Sigma₮\Sigma₮\(\Sigma\)₭\Sigma₭₸\Sigma₸
\sigma₮\sigma₮\(\sigma\)₭\sigma₭₸\sigma₸
\sim₮\sim₮\(\sim\)₭\sim₭₸\sim₸
\simeq₮\simeq₮\(\simeq\)₭\simeq₭₸\simeq₸
\sin₮\sin x₮\(\sin x\)₭\sin x₭₸\sin x₸
\sincoh₮\sincoh₮Not supportedNot supportedNot supported
\sinh₮\sinh x₮\(\sinh x\)₭\sinh x₭₸\sinh x₸
\sixptsize₮\sixptsize sixptsize₮Not supported₭\sixptsize sixptsize₭Not supported\sixptsize sixptsize
\sh₮\sh₮Not supported₭\sh₭Not supported
\skewNot supported\(\hat A\skew9\hat A\)Not supportedNot supported\hat A\skew9\hat A
\skipNot supportedNot supportedNot supportedNot supported
\small₮\small small₮\(\small small\)₭\small small₭Not supported\small small
\smallfrown₮\smallfrown₮\(\smallfrown\)₭\smallfrown₭₸\smallfrown₸
\smallint₮\smallint_0^n x \; \smallint\limits_0^n x \; \displaystyle \smallint_0^n x₮\(\smallint_0^n x \; \smallint\limits_0^n x \; \displaystyle \smallint_0^n x\)₭\smallint_0^n x \; \smallint\limits_0^n x \; \displaystyle \smallint_0^n x₭Not supported - \smallint_0^n x
\smallint\limits_0^n x
\displaystyle \smallint_0^n x -
{smallmatrix}₮\begin{smallmatrix}a & b\\c & d\end{smallmatrix}₮\(\begin{smallmatrix}a & b\\c & d\end{smallmatrix}\)₭\begin{smallmatrix}a & b\\c & d\end{smallmatrix}₭₸\begin{smallmatrix}a & b\\c & d\end{smallmatrix}₸\begin{smallmatrix}a & b\\
c & d\end{smallmatrix}
\smallsetminus₮\smallsetminus₮\(\smallsetminus\)₭\smallsetminus₭₸\smallsetminus₸
\smallsmile₮\smallsmile₮\(\smallsmile\)₭\smallsmile₭₸\smallsmile₸
\smash₮\left(x^{\smash{2}}\right)₮\(\left(x^{\smash{2}}\right)\)₭\left(x^{\smash{2}}\right)₭Not supported\left(x^{\smash{2}}\right)
\smile₮\smile₮\(\smile\)₭\smile₭₸\smile₸
\smiley₮\smiley₮Not supportedNot supportedNot supportedwasysym
\sout₮\sout{abc}₮Not supported₭\sout{abc}₭Not supported\sout{abc}
\SpaceNot supported\(a\Space{5px}{4ex}{2ex}^b_c d\)Not supportedNot supporteda\Space{5px}{4ex}{2ex}^b_c d
\space₮a\space{b}₮\(a\space{b}\)₭a\space{b}₭₸a\space{b}₸a\space{b}
\spades₮\spades₮\(\spades\)₭\spades₭Not supported
\spadesuit₮\spadesuit₮\(\spadesuit\)₭\spadesuit₭₸\spadesuit₸
\sphericalangle₮\sphericalangle₮\(\sphericalangle\)₭\sphericalangle₭₸\sphericalangle₸
{split}₮₮\begin{equation}\begin{split}∇·𝐃&=ρ_v \\ ∇·𝐁&=0 \end{split}\end{equation}₮₮\[\begin{equation}\begin{split}∇·𝐃&=ρ_v \\∇·𝐁&=0\end{split}\end{equation}\]₭₭\begin{equation}\begin{split}∇·𝐃&=ρ_v \\∇·𝐁&=0\end{split}\end{equation}₭₭Not supported\begin{equation}
\begin{split}
   ∇·𝐃&=ρ_v \\
   ∇·𝐁&=0
\end{split}
\end{equation}
\sqcap₮\sqcap₮\(\sqcap\)₭\sqcap₭₸\sqcap₸
\sqcup₮\sqcup₮\(\sqcup\)₭\sqcup₭₸\sqcup₸
\square₮\square₮\(\square\)₭\square₭₸\square₸
\sqrt₮\sqrt[3]{x}₮\(\sqrt[3]{x}\)₭\sqrt[3]{x}₭₸\sqrt[3]{x}₸\sqrt[3]{x}
\sqsubset₮\sqsubset₮\(\sqsubset\)₭\sqsubset₭₸\sqsubset₸
\sqsubseteq₮\sqsubseteq₮\(\sqsubseteq\)₭\sqsubseteq₭₸\sqsubseteq₸
\sqsupset₮\sqsupset₮\(\sqsupset\)₭\sqsupset₭₸\sqsupset₸
\sqsupseteq₮\sqsupseteq₮\(\sqsupseteq\)₭\sqsupseteq₭₸\sqsupseteq₸
\ss₮\text{\ss}₮Not supported₭\text{\ss}₭₸\text{\ss}₸\text{\ss}
\stackrel₮\stackrel{!}{=}₮\(\stackrel{!}{=}\)₭\stackrel{!}{=}₭₸\stackrel{!}{=}₸\stackrel{!}{=}
\star₮\star₮\(\star\)₭\star₭₸\star₸
\Stigma₮\Stigma₮Not supportedNot supportedNot supported
\stigma₮\stigma₮Not supportedNot supportedNot supported
\strictif₮\strictif₮Not supportedNot supportedNot supported
\strictfi₮\strictfi₮Not supportedNot supportedNot supported
\strutNot supported\(\boxed{ab\strut}\)Not supportedNot supported\boxed{ab\strut}
\styleNot supported\(\frac{\style{color:red}{x+1}}{y+2}\)Not supportedNot supported\frac{\style{color:red}{x+1}}{y+2}
Non standard
\sub₮\sub₮\(\sub\)₭\sub₭Not supported
{subarray}₮\begin{subarray}{c} a \\ c \end{subarray}₮\(\begin{subarray}{c} a \\ c \end{subarray}\)₭\begin{subarray}{c} a \\ c \end{subarray}₭Not supported\sum_{\begin{subarray}
   {c} a \\
   c
\end{subarray}}
\sube₮\sube₮\(\sube\)₭\sube₭Not supported
\Subset₮\Subset₮\(\Subset\)₭\Subset₭₸\Subset₸
\subset₮\subset₮\(\subset\)₭\subset₭₸\subset₸
\subseteq₮\subseteq₮\(\subseteq\)₭\subseteq₭₸\subseteq₸
\subseteqq₮\subseteqq₮\(\subseteqq\)₭\subseteqq₭₸\subseteqq₸
\subsetneq₮\subsetneq₮\(\subsetneq\)₭\subsetneq₭₸\subsetneq₸
\subsetneqq₮\subsetneqq₮\(\subsetneqq\)₭\subsetneqq₭₸\subsetneqq₸
\substack₮\displaystyle\sum_{\substack{1\lt i\lt 3 \\ 1\le j\lt 5}}a_{ij}₮\(\displaystyle\sum_{\substack{1\lt i\lt 3 \\ 1\le j\lt 5}}a_{ij}\)₭\displaystyle\sum_{\substack{1\lt i\lt 3 \\ 1\le j\lt 5}}a_{ij}₭₸\displaystyle\sum_{\substack{1\lt i\lt 3 \\ 1\le j\lt 5}}a_{ij}₸\sum_{\substack{1\lt i\lt 3 \\
1\le j\lt 5}}a_{ij}
\succ₮\succ₮\(\succ\)₭\succ₭₸\succ₸
\succapprox₮\succapprox₮\(\succapprox\)₭\succapprox₭₸\succapprox₸
\succcurlyeq₮\succcurlyeq₮\(\succcurlyeq\)₭\succcurlyeq₭₸\succcurlyeq₸
\succeq₮\succeq₮\(\succeq\)₭\succeq₭₸\succeq₸
\succnapprox₮\succnapprox₮\(\succnapprox\)₭\succnapprox₭₸\succnapprox₸
\succneqq₮\succneqq₮\(\succneqq\)₭\succneqq₭₸\succneqq₸
\succnsim₮\succnsim₮\(\succnsim\)₭\succnsim₭₸\succnsim₸
\succsim₮\succsim₮\(\succsim\)₭\succsim₭₸\succsim₸
\sum₮\sum_0^n x \; \displaystyle \sum_0^n x₮\(\sum_0^n x \; \displaystyle \sum_0^n x\)₭\sum_0^n x \; \displaystyle \sum_0^n x₭₸\sum_0^n x₸
\sup₮\begin{matrix}\sup x \\ \sup_y x \\\sup\limits_y x\end{matrix}₮\(\begin{matrix}\sup x \\ \sup_y x \\\sup\limits_y x\end{matrix}\)₭\begin{matrix}\sup x \\ \sup_y x \\\sup\limits_y x\end{matrix}₭₸\begin{matrix}\sup x \\ \sup_y x \\\sup\limits_y x\end{matrix}₸
\supe₮\supe₮\(\supe\)₭\supe₭₸\supe₸
\Supset₮\Supset₮\(\Supset\)₭\Supset₭₸\Supset₸
\supset₮\supset₮\(\supset\)₭\supset₭₸\supset₸
\supseteq₮\supseteq₮\(\supseteq\)₭\supseteq₭₸\supseteq₸
\supseteqq₮\supseteqq₮\(\supseteqq\)₭\supseteqq₭₸\supseteqq₸
\supsetneq₮\supsetneq₮\(\supsetneq\)₭\supsetneq₭₸\supsetneq₸
\supsetneqq₮\supsetneqq₮\(\supsetneqq\)₭\supsetneqq₭₸\supsetneqq₸
\surd₮\surd₮\(\surd\)₭\surd₭₸\surd₸
\swarrow₮\swarrow₮\(\swarrow\)₭\swarrow₭₸\swarrow₸
- -

T

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\tag₮₮\tag{3.1c} a^2+b^2=c^2₮₮\(\tag{3.1c} a^2+b^2=c^2\)₭₭\tag{3.1c} a^2+b^2=c^2₭₭Not supported\tag{3.1c} a^2+b^2=c^2
\tag*₮₮\tag*{3.1c} a^2+b^2=c^2₮₮\(\tag*{3.1c} a^2+b^2=c^2\)₭₭\tag*{3.1c} a^2+b^2=c^2₭₭Not supported\tag*{3.1c} a^2+b^2=c^2
\tan₮\tan x₮\(\tan x\)₭\tan x₭₸\tan x₸
\tanh₮\tanh x₮\(\tanh x\)₭\tanh x₭₸\tanh x₸
\Tau₮\Tau₮\(\Tau\)₭\Tau₭₸\Tau₸
\tau₮\tau₮\(\tau\)₭\tau₭₸\tau₸
\tbinom₮\tbinom n k₮\(\tbinom n k\)₭\tbinom n k₭₸\tbinom n k₸\tbinom n k
\TeX₮\TeX₮\(\TeX\)₭\TeX₭Not supported
\text₮\text{ yes }\&\text{ no }₮\(\text{ yes }\&\text{ no }\)₭\text{ yes }\&\text{ no }₭₸\text{ yes }\&\text{ no }₸\text{ yes }\&\text{ no }
\text₮\text{MMM$M\mkern2mu M$M}₮\(\text{MMM$M\mkern2mu M$M}\)₭\text{MMM$M\mkern2mu M$M}₭₸\text{MMM$M\mkern2mu M$M}₸\text{MMM$M\mkern2mu M$M}
\textasciitilde₮\text{\textasciitilde}₮Not supported₭\text{\textasciitilde}₭₸\text{\textasciitilde}₸\text{\textasciitilde}
\textasciicircum₮\text{\textasciicircum}₮Not supported₭\text{\textasciicircum}₭₸\text{\textasciicircum}₸\text{\textasciicircum}
\textbackslash₮\text{\textbackslash}₮Not supported₭\text{\textbackslash}₭₸\text{\textbackslash}₸\text{\textbackslash}
\textbar₮\text{\textbar}₮Not supported₭\text{\textbar}₭₸\text{\textbar}₸\text{\textbar}
\textbardbl₮\text{\textbardbl}₮Not supported₭\text{\textbardbl}₭₸\text{\textbardbl}₸\text{\textbardbl}
\textbf₮\textbf{AaBb123}₮\(\textbf{AaBb123}\)₭\textbf{AaBb123}₭₸\textbf{AaBb123}₸\textbf{AaBb123}
\textbraceleft₮\text{\textbraceleft}₮Not supported₭\text{\textbraceleft}₭₸\text{\textbraceleft}₸\text{\textbraceleft}
\textbraceright₮\text{\textbraceright}₮Not supported₭\text{\textbraceright}₭₸\text{\textbraceright}₸\text{\textbraceright}
\textcircledNot supportedNot supportedNot supported₸\text{\textcircled a}₸\text{\textcircled a}
\textcolor₮\textcolor{blue}{F=ma}₮\(\textcolor{blue}{F=ma}\)₭\textcolor{blue}{F=ma}₭₸\textcolor{blue}{F=ma}₸\textcolor{blue}{F=ma}
\textdagger₮\text{\textdagger}₮Not supported₭\text{\textdagger}₭₸\text{\textdagger}₸\text{\textdagger}
\textdaggerdbl₮\text{\textdaggerdbl}₮Not supported₭\text{\textdaggerdbl}₭₸\text{\textdaggerdbl}₸\text{\textdaggerdbl}
\textdegree₮\text{\textdegree}₮Not supported₭\text{\textdegree}₭₸\text{\textdegree}₸\text{\textdegree}
\textdollar₮\text{\textdollar}₮Not supported₭\text{\textdollar}₭₸\text{\textdollar}₸\text{\textdollar}
\textellipsis₮\text{\textellipsis}₮Not supported₭\text{\textellipsis}₭₸\text{\textellipsis}₸\text{\textellipsis}
\textemdash₮\text{\textemdash}₮Not supported₭\text{\textemdash}₭₸\text{\textemdash}₸\text{\textemdash}
\textendash₮\text{\textendash}₮Not supported₭\text{\textendash}₭₸\text{\textendash}₸\text{\textendash}
\textgreater₮\text{\textgreater}₮Not supported₭\text{\textgreater}₭₸\text{\textgreater}₸\text{\textgreater}
\textit₮\textit{AaBb}₮\(\textit{AaBb}\)₭\textit{AaBb}₭₸\textit{AaBb}₸\textit{AaBb}
\textless₮\text{\textless}₮Not supported₭\text{\textless}₭₸\text{\textless}₸\text{\textless}
\textnormal₮\textnormal{AB}₮Not supported₭\textnormal{AB}₭₸\textnormal{AB}₸\textnormal{AB}
\textquotedblleft₮\text{\textquotedblleft}₮Not supported₭\text{\textquotedblleft}₭₸\text{\textquotedblleft}₸\text{\textquotedblleft}
\textquotedblright₮\text{\textquotedblright}₮Not supported₭\text{\textquotedblright}₭₸\text{\textquotedblright}₸\text{\textquotedblright}
\textquoteleft₮\text{\textquoteleft}₮Not supported₭\text{\textquoteleft}₭₸\text{\textquoteleft}₸\text{\textquoteleft}
\textquoteright₮\text{\textquoteright}₮Not supported₭\text{\textquoteright}₭₸\text{\textquoteright}₸\text{\textquoteright}
\textregistered₮\text{\textregistered}₮Not supported₭\text{\textregistered}₭₸\text{\textregistered}₸\text{\textregistered}
\textrm₮\textrm{AaBb123}₮\(\textrm{AaBb123}\)₭\textrm{AaBb123}₭₸\textrm{AaBb123}₸\textrm{AaBb123}
\textscNot supportedNot supportedNot supportedNot supported
\textsf₮\textsf{AaBb123}₮\(\textsf{AaBb123}\)₭\textsf{AaBb123}₭₸\textsf{AaBb123}₸\textsf{AaBb123}
\textsterling₮\text{\textsterling}₮Not supported₭\text{\textsterling}₭₸\text{\textsterling}₸\text{\textsterling}
\textstyle₮\textstyle\sum_0^n₮\(\textstyle\sum_0^n\)₭\textstyle\sum_0^n₭₸\textstyle\sum_0^n₸\textstyle\sum_0^n
\texttip₮\texttip{\text{hover here}}{tip}₮Not supportedNot supportedNot supported\texttip{\text{hover here}}{tip}
\texttt₮\texttt{AaBb123}₮\(\texttt{AaBb123}\)₭\texttt{AaBb123}₭₸\texttt{AaBb123}₸\texttt{AaBb123}
\textunderscore₮\text{\textunderscore}₮Not supported₭\text{\textunderscore}₭Not supported\text{\textunderscore}
\textvisiblespaceNot supported\(a\textvisiblespace b\)Not supportedNot supported
\tfrac₮\displaystyle \tfrac a b₮\(\displaystyle \tfrac a b\)₭\displaystyle \tfrac a b₭₸\displaystyle \tfrac a b₸\displaystyle \tfrac a b
\tg₮\tg₮Not supported₭\tg₭Not supported
\th₮\th₮Not supported₭\th₭Not supported
\therefore₮\therefore₮\(\therefore\)₭\therefore₭₸\therefore₸
\Theta₮\Theta₮\(\Theta\)₭\Theta₭₸\Theta₸
\theta₮\theta₮\(\theta\)₭\theta₭₸\theta₸
\thetasym₮\thetasym₮\(\thetasym\)₭\thetasym₭₸\thetasym₸
\thickapprox₮\thickapprox₮\(\thickapprox\)₭\thickapprox₭₸\thickapprox₸
\thicksim₮\thicksim₮\(\thicksim\)₭\thicksim₭₸\thicksim₸
\thickspace₮a\thickspace b₮Not supported₭a\thickspace b₭₸a\thickspace b₸a\thickspace b
\thinspace₮a\thinspace b₮\(a\thinspace b\)₭a\thinspace b₭₸a\thinspace b₸a\thinspace b
\tilde₮\tilde M₮\(\tilde M\)₭\tilde M₭₸\tilde M₸\tilde M
\times₮\times₮\(\times\)₭\times₭₸\times₸
\Tiny₮{\Tiny A B}₮Not supportedNot supportedNot supportedNon standard
\tiny₮\tiny tiny₮\(\tiny tiny\)₭\tiny tiny₭Not supported\tiny tiny
\to₮\to₮\(\to\)₭\to₭₸\to₸
\toggle₮\toggle{\text{Click Here}}{Ouch}\endtoggle₮Not supportedNot supported₸\toggle{\text{Hey!}}{\text{Click Here}}₸
\top₮\top₮\(\top\)₭\top₭₸\top₸
\triangle₮\triangle₮\(\triangle\)₭\triangle₭₸\triangle₸
\triangledown₮\triangledown₮\(\triangledown\)₭\triangledown₭₸\triangledown₸
\triangleleft₮\triangleleft₮\(\triangleleft\)₭\triangleleft₭₸\triangleleft₸
\trianglelefteq₮\trianglelefteq₮\(\trianglelefteq\)₭\trianglelefteq₭₸\trianglelefteq₸
\triangleq₮\triangleq₮\(\triangleq\)₭\triangleq₭₸\triangleq₸
\triangleright₮\triangleright₮\(\triangleright\)₭\triangleright₭₸\triangleright₸
\trianglerighteq₮\trianglerighteq₮\(\trianglerighteq\)₭\trianglerighteq₭₸\trianglerighteq₸
\tt₮{\tt AaBb123}₮\({\tt AaBb123}\)₭{\tt AaBb123}₭Not supported{\tt AaBb123}
\twoheadleftarrow₮\twoheadleftarrow₮\(\twoheadleftarrow\)₭\twoheadleftarrow₭₸\twoheadleftarrow₸
\twoheadrightarrow₮\twoheadrightarrow₮\(\twoheadrightarrow\)₭\twoheadrightarrow₭₸\twoheadrightarrow₸
- -

U

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\u₮\text{\u{a}}₮Not supported₭\text{\u{a}}₭₸\text{\u{a}}₸\text{\u{a}}
\Uarr₮\Uarr₮\(\Uarr\)₭\Uarr₭Not supported
\uArr₮\uArr₮\(\uArr\)₭\uArr₭Not supported
\uarr₮\uarr₮\(\uarr\)₭\uarr₭Not supported
\ulcorner₮\ulcorner₮\(\ulcorner\)₭\ulcorner₭Not supported
\underbrace₮\underbrace{x+⋯+x}_{n\text{ times}}₮\(\underbrace{x+⋯+x}_{n\text{ times}}\)₭\underbrace{x+⋯+x}_{n\text{ times}}₭₸\underbrace{x+⋯+x}_{n\text{ times}}₸\underbrace{x+⋯+x}_{n\text{ times}}
\underbracketNot supportedNot supportedNot supportedNot supported
\undergroup₮\undergroup{AB}₮Not supported₭\undergroup{AB}₭Not supported\undergroup{AB}
\underleftarrow₮\underleftarrow{AB}₮\(\underleftarrow{AB}\)₭\underleftarrow{AB}₭Not supported\underleftarrow{AB}
\underleftrightarrow₮\underleftrightarrow{AB}₮\(\underleftrightarrow{AB}\)₭\underleftrightarrow{AB}₭Not supported\underleftrightarrow{AB}
\underrightarrow₮\underrightarrow{AB}₮\(\underrightarrow{AB}\)₭\underrightarrow{AB}₭Not supported\underrightarrow{AB}
\underline₮\underline{\text{a long argument}}₮\(\underline{\text{a long argument}}\)₭\underline{\text{a long argument}}₭₸\underline{\text{a long argument}}₸\underline{\text{a long argument}}
\underlinesegmentNot supportedNot supportedNot supportedNot supported
\underparen₮\underparen{abc}₮Not supportedNot supportedNot supported\underparen{abc}
\underrightarrow₮\underrightarrow{AB}₮\(\underrightarrow{AB}\)₭\underrightarrow{AB}₭Not supported\underrightarrow{AB}
\underset₮\underset{!}{=}₮\(\underset{!}{=}\)₭\underset{!}{=}₭₸\underset{!}{=}₸\underset{!}{=}
\unicodeNot supported
See \char
\(\unicode{x263a}\)Not supportedNot supported\unicode{x263a}
See \char for alternate.
\unlhd₮\unlhd₮\(\unlhd\)₭\unlhd₭₸\unlhd₸
\unrhd₮\unrhd₮\(\unrhd\)₭\unrhd₭₸\unrhd₸
\upalpha₮\upalpha₮Not supported₭\upalpha₭Not supported
\Uparrow₮\Uparrow₮\(\Uparrow\)₭\Uparrow₭₸\Uparrow₸
\uparrow₮\uparrow₮\(\uparrow\)₭\uparrow₭₸\uparrow₸
\upbeta₮\upbeta₮Not supported₭\upbeta₭Not supported
\upchi₮\upchi₮Not supported₭\upchi₭Not supported
\updelta₮\updelta₮Not supported₭\updelta₭Not supported
\Updownarrow₮\Updownarrow₮\(\Updownarrow\)₭\Updownarrow₭₸\Updownarrow₸
\updownarrow₮\updownarrow₮\(\updownarrow\)₭\updownarrow₭₸\updownarrow₸
\upeta₮\upeta₮Not supported₭\upeta₭Not supported
\upepsilon₮\upepsilon₮Not supported₭\upepsilon₭Not supported
\upgamma₮\upgamma₮Not supported₭\upgamma₭Not supported
\upharpoonleft₮\upharpoonleft₮\(\upharpoonleft\)₭\upharpoonleft₭₸\upharpoonleft₸
\upharpoonright₮\upharpoonright₮\(\upharpoonright\)₭\upharpoonright₭₸\upharpoonright₸
\upiota₮\upiota₮Not supported₭\upiota₭Not supported
\upkappa₮\upkappa₮Not supported₭\upkappa₭Not supported
\uplambda₮\uplambda₮Not supported₭\uplambda₭Not supported
\uplus₮\uplus₮\(\uplus\)₭\uplus₭₸\uplus₸
\upmu₮\upmu₮Not supported₭\upmu₭Not supported
\upnu₮\upnu₮Not supported₭\upnu₭Not supported
\upomega₮\upomega₮Not supported₭\upomega₭Not supported
\upomicron₮\upomicron₮Not supported₭\upomicron₭Not supported
\upphi₮\upphi₮Not supported₭\upphi₭Not supported
\uppi₮\uppi₮Not supported₭\uppi₭Not supported
\uppsi₮\uppsi₮Not supported₭\uppsi₭Not supported
\uprho₮\uprho₮Not supported₭\uprho₭Not supported
\uprootNot supported\(\sqrt[3\uproot2]{x}\)Not supportedNot supported\sqrt[3\uproot2]{x}
\upsigma₮\upsigma₮Not supported₭\upsigma₭Not supported
\Upsilon₮\Upsilon₮\(\Upsilon\)₭\Upsilon₭₸\Upsilon₸
\upsilon₮\upsilon₮\(\upsilon\)₭\upsilon₭₸\upsilon₸
\uptau₮\uptau₮Not supported₭\uptau₭Not supported
\uptheta₮\uptheta₮Not supported₭\uptheta₭Not supported
\upuparrows₮\upuparrows₮\(\upuparrows\)₭\upuparrows₭₸\upuparrows₸
\upupsilon₮\upupsilon₮Not supported₭\upupsilon₭Not supported
\upxi₮\upxi₮Not supported₭\upxi₭Not supported
\upzeta₮\upzeta₮Not supported₭\upzeta₭Not supported
\urcorner₮\urcorner₮\(\urcorner\)₭\urcorner₭Not supported
\url₮\url{https://temml.org/}₮Not supported₭\url{https://temml.org/}₭Not supported\url{https://temml.org/}
\utilde₮\utilde{AB}₮Not supported₭\utilde{AB}₭Not supported\utilde{AB}
- -

V

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\v₮\text{\v{a}}₮Not supported₭\text{\v{a}}₭₸\text{\v{a}}₸\text{\v{a}}
\varcoppa₮\varcoppa₮Not supportedNot supportedNot supported
\varDelta₮\varDelta₮\(\varDelta\)₭\varDelta₭Not supported
\varepsilon₮\varepsilon₮\(\varepsilon\)₭\varepsilon₭₸\varepsilon₸
\varGamma₮\varGamma₮\(\varGamma\)₭\varGamma₭Not supported
\varinjlim₮\varinjlim\limits_n x₮\(\varinjlim\limits_n x\)₭\varinjlim\limits_n x₭Not supported\varinjlim\limits_n x
\varkappa₮\varkappa₮\(\varkappa\)₭\varkappa₭₸\varkappa₸
\varLambda₮\varLambda₮\(\varLambda\)₭\varLambda₭Not supported
\varliminf₮\varliminf\limits_n x₮\(\varliminf\limits_n x\)₭\varliminf\limits_n x₭Not supported\varliminf\limits_n x
\varlimsup₮\varlimsup\limits_n x₮\(\varlimsup\limits_n x\)₭\varlimsup\limits_n x₭Not supported\varlimsup\limits_n x
\varnothing₮\varnothing₮\(\varnothing\)₭\varnothing₭₸\varnothing₸
\varOmega₮\varOmega₮\(\varOmega\)₭\varOmega₭Not supported
\varPhi₮\varPhi₮\(\varPhi\)₭\varPhi₭Not supported
\varphi₮\varphi₮\(\varphi\)₭\varphi₭₸\varphi₸
\varPi₮\varPi₮\(\varPi\)₭\varPi₭Not supported
\varpi₮\varpi₮\(\varpi\)₭\varpi₭₸\varpi₸
\varprojlim₮\varprojlim\limits_n x₮\(\varprojlim\limits_n x\)₭\varprojlim\limits_n x₭Not supported\varprojlim\limits_n x
\varpropto₮\varpropto₮\(\varpropto\)₭\varpropto₭₸\varpropto₸
\varPsi₮\varPsi₮\(\varPsi\)₭\varPsi₭Not supported
\varrho₮\varrho₮\(\varrho\)₭\varrho₭₸\varrho₸
\varSigma₮\varSigma₮\(\varSigma\)₭\varSigma₭Not supported
\varsigma₮\varsigma₮\(\varsigma\)₭\varsigma₭₸\varsigma₸
\varstigmaNot supported\(\varstigma\)Not supportedNot supported
\varsubsetneq₮\varsubsetneq₮\(\varsubsetneq\)₭\varsubsetneq₭₸\varsubsetneq₸
\varsubsetneqq₮\varsubsetneqq₮\(\varsubsetneqq\)₭\varsubsetneqq₭₸\varsubsetneqq₸
\varsupsetneq₮\varsupsetneq₮\(\varsupsetneq\)₭\varsupsetneq₭₸\varsupsetneq₸
\varsupsetneqq₮\varsupsetneqq₮\(\varsupsetneqq\)₭\varsupsetneqq₭₸\varsupsetneqq₸
\varTheta₮\varTheta₮\(\varTheta\)₭\varTheta₭Not supported
\vartheta₮\vartheta₮\(\vartheta\)₭\vartheta₭₸\vartheta₸
\vartriangle₮\vartriangle₮\(\vartriangle\)₭\vartriangle₭₸\vartriangle₸
\vartriangleleft₮\vartriangleleft₮\(\vartriangleleft\)₭\vartriangleleft₭₸\vartriangleleft₸
\vartriangleright₮\vartriangleright₮\(\vartriangleright\)₭\vartriangleright₭₸\vartriangleright₸
\varUpsilon₮\varUpsilon₮\(\varUpsilon\)₭\varUpsilon₭Not supported
\varXi₮\varXi₮\(\varXi\)₭\varXi₭Not supported
\vcentcolon₮\mathrel{\vcentcolon =}₮Not supported₭\mathrel{\vcentcolon =}₭Not supported\mathrel{\vcentcolon =}
\vcenterNot supportedNot supportedNot supportedNot supported
\Vdash₮\Vdash₮\(\Vdash\)₭\Vdash₭₸\Vdash₸
\vDash₮\vDash₮\(\vDash\)₭\vDash₭₸\vDash₸
\vdash₮\vdash₮\(\vdash\)₭\vdash₭₸\vdash₸
\vdots₮\vdots₮\(\vdots\)₭\vdots₭₸\vdots₸
\vec₮\vec{F}₮\(\vec{F}\)₭\vec{F}₭₸\vec{F}₸\vec{F}
\vee₮\vee₮\(\vee\)₭\vee₭₸\vee₸
\veebar₮\veebar₮\(\veebar\)₭\veebar₭₸\veebar₸
\verb₮\verb!\frac a b!₮\(\verb!\frac a b!\)₭\verb!\frac a b!₭Not supported\verb!\frac a b!
\Vert₮\Vert₮\(\Vert\)₭\Vert₭₸\Vert₸
\vert₮\vert₮\(\vert\)₭\vert₭₸\vert₸
\vfilNot supportedNot supportedNot supportedNot supported
\vfillNot supportedNot supportedNot supportedNot supported
\vlineNot supportedNot supportedNot supportedNot supported
{Vmatrix}₮\begin{Vmatrix}a&b\\c&d\end{Vmatrix}₮\(\begin{Vmatrix}a&b\\c&d\end{Vmatrix}\)₭\begin{Vmatrix}a&b\\c&d\end{Vmatrix}₭₸\begin{Vmatrix}a&b\\c&d\end{Vmatrix}₸\begin{Vmatrix}
   a & b \\
   c & d
\end{Vmatrix}
{vmatrix}₮\begin{vmatrix}a&b\\c&d\end{vmatrix}₮\(\begin{vmatrix}a&b\\c&d\end{vmatrix}\)₭\begin{vmatrix}a&b\\c&d\end{vmatrix}₭₸\begin{vmatrix}a&b\\c&d\end{vmatrix}₸\begin{vmatrix}
   a & b \\
   c & d
\end{vmatrix}
\vphantom₮\overline{\vphantom{M}a}₮\(\overline{\vphantom{M}a}\)₭\overline{\vphantom{M}a}₭Not supported\overline{\vphantom{M}a}
\Vvdash₮\Vvdash₮\(\Vvdash\)₭\Vvdash₭₸\Vvdash₸
- -

W

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\wedge₮\wedge₮\(\wedge\)₭\wedge₭₸\wedge₸
\weierp₮\weierp₮\(\weierp\)₭\weierp₭Not supported
\widecheck₮\widecheck{AB}₮Not supported₭\widecheck{AB}₭₸\widecheck{AB}₸\widecheck{AB}
\widehat₮\widehat{AB}₮\(\widehat{AB}\)₭\widehat{AB}₭₸\widehat{AB}₸\widehat{AB}
\wideparen₮\wideparen{AB}₮Not supportedNot supportedNot supported -
\widetilde₮\widetilde{AB}₮\(\widetilde{AB}\)₭\widetilde{AB}₭₸\widetilde{AB}₸\widetilde{AB}
\with₮\with₮Not supportedNot supportedNot supported -
\wn₮\wn₮Not supportedNot supportedNot supported
\wp₮\wp₮\(\wp\)₭\wp₭₸\wp₸
\wr₮\wr₮\(\wr\)₭\wr₭₸\wr₸
- -

X

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\xcancel₮\xcancel{ABC}₮\(\xcancel{ABC}\)₭\xcancel{ABC}₭Not supported\xcancel{ABC}
\Xi₮\Xi₮\(\Xi\)₭\Xi₭₸\Xi₸
\xi₮\xi₮\(\xi\)₭\xi₭₸\xi₸
\xhookleftarrow₮\xhookleftarrow{abc}₮Not supported₭\xhookleftarrow{abc}₭₸\xhookleftarrow{abc}₸\xhookleftarrow{abc}
\xhookrightarrow₮\xhookrightarrow{abc}₮Not supported₭\xhookrightarrow{abc}₭₸\xhookrightarrow{abc}₸\xhookrightarrow{abc}
\xLeftarrow₮\xLeftarrow{abc}₮Not supported₭\xLeftarrow{abc}₭₸\xLeftarrow{abc}₸\xLeftarrow{abc}
\xleftarrow₮\xleftarrow{abc}₮\(\xleftarrow{abc}\)₭\xleftarrow{abc}₭₸\xleftarrow{abc}₸\xleftarrow{abc}
\xleftharpoondown₮\xleftharpoondown{abc}₮Not supported₭\xleftharpoondown{abc}₭Not supported\xleftharpoondown{abc}
\xleftharpoonup₮\xleftharpoonup{abc}₮Not supported₭\xleftharpoonup{abc}₭Not supported\xleftharpoonup{abc}
\xLeftrightarrow₮\xLeftrightarrow{abc}₮Not supported₭\xLeftrightarrow{abc}₭₸\xLeftrightarrow{abc}₸\xLeftrightarrow{abc}
\xleftrightarrow₮\xleftrightarrow{abc}₮\(\xleftrightarrow{abc}\)₭\xleftrightarrow{abc}₭₸\xleftrightarrow{abc}₸\xleftrightarrow{abc}
\xleftrightharpoons₮\xleftrightharpoons{abc}₮Not supported₭\xleftrightharpoons{abc}₭₸\xleftrightharpoons{abc}₸\xleftrightharpoons{abc}
\xlongequal₮\xlongequal{abc}₮\(\xlongequal{abc}\)₭\xlongequal{abc}₭Not supported\xlongequal{abc}
\xmapsto₮\xmapsto{abc}₮\(\xmapsto{abc}\)₭\xmapsto{abc}₭₸\xmapsto{abc}₸\xmapsto{abc}
\xRightarrow₮\xRightarrow{abc}₮Not supported₭\xRightarrow{abc}₭₸\xRightarrow{abc}₸\xRightarrow{abc}
\xrightarrow₮\begin{matrix}A \xrightarrow{abc} B\\ A \xrightarrow[ghi]{abcdef} B \end{matrix}₮\(\begin{matrix}A \xrightarrow{abc} B\\ A \xrightarrow[ghi]{abcdef} B \end{matrix}\)₭\begin{matrix}A \xrightarrow{abc} B\\ A \xrightarrow[ghi]{abcdef} B \end{matrix}₭₸\begin{matrix}A \xrightarrow{abc} B\\ A \xrightarrow[ghi]{abcdef} B \end{matrix}₸A \xrightarrow{abc} B
A \xrightarrow[ghi]{abcdef} B
\xrightharpoondown₮\xrightharpoondown{abc}₮Not supported₭\xrightharpoondown{abc}₭Not supported\xrightharpoondown{abc}
\xrightharpoonup₮\xrightharpoonup{abc}₮Not supported₭\xrightharpoonup{abc}₭Not supported\xrightharpoonup{abc}
\xrightleftharpoons₮\xrightleftharpoons{abc}₮\(\xrightleftharpoons{abc}\)₭\xrightleftharpoons{abc}₭₸\xrightleftharpoons{abc}₸\xrightleftharpoons{abc}
\xtofrom₮\xtofrom{abc}₮\(\xtofrom{abc}\)₭\xtofrom{abc}₭Not supported\xtofrom{abc}
\xtwoheadleftarrow₮\xtwoheadleftarrow{abc}₮\(\xtwoheadleftarrow{abc}\)₭\xtwoheadleftarrow{abc}₭Not supported\xtwoheadleftarrow{abc}
\xtwoheadrightarrow₮\xtwoheadrightarrow{abc}₮\(\xtwoheadrightarrow{abc}\)₭\xtwoheadrightarrow{abc}₭Not supported\xtwoheadrightarrow{abc}
- -

YZ

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
\yen₮\yen₮\(\yen\)₭\yen₭Not supported
\Z₮\Z₮\(\Z\)₭\Z₭Not supported
\Zeta₮\Zeta₮\(\Zeta\)₭\Zeta₭₸\Zeta₸
\zeta₮\zeta₮\(\zeta\)₭\zeta₭₸\zeta₸
- -
- -

Copyright © 2021, 2022 Ron Kok. Released under the MIT License

- -
- -
- - - - - - - - - \ No newline at end of file diff --git a/docs/support_table.md b/docs/support_table.md deleted file mode 100644 index 690b61b0..00000000 --- a/docs/support_table.md +++ /dev/null @@ -1,1570 +0,0 @@ - - - - - - Temml Support Table - - - - - - - -
- -# Support Table - -**Temml** is a JavaScript library that converts TeX math-mode functions to MathML. -This page provides an alphabetically sorted list of TeX functions that Temml -supports and some functions that it does not support. There is a similar page, -with functions [sorted by type](supported.html). - -To read this page, use a browser that supports MathML, such as Firefox or Safari. -Chrome and Edge will support MathML [soon](https://www.igalia.com/2021/08/09/MathML-Progress.html). - -Some functions are provided by an extension and are listed as such. They will -be available only in pages that include the extension. - -If you know the shape of a character, but not its name, -[Detexify](http://detexify.kirelabs.org/classify.html) can help. - - -## Symbols - -| Function | Rendered | Source or Comment | Package | -|----------------|-------------|-------------------|-----------| -|\!|$`n!`|`n!`|| -|\\\!|$`a\!b`|`a\!b`|| -|#|$`\def\bar#1{#1^2} \bar{y}`|`\def\bar#1{#1^2} \bar{y}`|| -|\\#|$`\#`||| -|%||`%this is a comment`|| -|\\%|$`\%`||| -|&|$`\begin{matrix} a & b\\ c & d \end{matrix}`|`\begin{matrix}`
   `a & b \\`
   `c & d`
`\end{matrix}`|| -|\\&|$`\&`||| -|'|$`'`||| -|\\\'|$`\text{\'{a}}`|`\text{\'{a}}`|| -|(|$`(`||| -|)|$`)`||| -|\\ |$`a\ b`|`a\ b`|| -|\\"|$`\text{\"{a}}`|`\text{\"{a}}`|| -|\\$ | $`\text{\textdollar}`||| -|\\,|$`a\,\,{b}`|`a\,\,{b}`|| -|\\.|$`\text{\.{a}}`|`\text{\.{a}}`|| -|\\:|$`a\:\:{b}`|`a\:\:{b}`|| -|\\;|$`a\;\;{b}`|a`\;\;{b}`|| -| \_ | $`x_i` | `x_i` || -|\\_|$`\_`||| -|\\\` | $``\text{\`{a}}`` | ``\text{\'{a}}`` || -|$`<`|$`<`||| -|\\=|$`\text{\={a}}`|`\text{\={a}}`|| -| >|$`>`||| -|\\>|$`a\>\>{b}`|`a\>\>{b}`|| -|\[|$`[`||| -|\]|$`]`||| -|{|$`{a}`|`{a}`|| -|}|$`{a}`|`{a}`|| -|\\{|$`\{`||| -|\\}|$`\}`||| -| \| |$`\vert`||| -| \\\| |$`\Vert`||| -|~|$`\text{no~no~no~breaks}`|`\text{no~no~no~breaks}`|| -|\\~|$`\text{\~{a}}`|`\text{\~{a}}`|| -|\\\\|$`\begin{matrix} a & b\\ c & d\end{matrix}`|`\begin{matrix}`
   `a & b \\`
   `c & d`
`\end{matrix}`|| -|^|$`x^i`|`x^i`|| -|\\^|$`\text{\^{a}}`|`\text{\^{a}}`|| - -## A - -
- -| Function | Rendered | Source or Comment| Package -|----------------|-------------|------------------|-----------| -|\AA|$`\text{\AA}`|`\text{\AA}`||| -|\aa|$`\text{\aa}`|`\text{\aa}`||| -|\above|$`{a \above{2pt} b+1}`|`{a \above{2pt} b+1}`|| -|\abovewithdelims|(Not supported)||| -|\abs|$`\abs{x}`|`\abs{x}`| physics extension | -|\absolutevalue|$`\absolutevalue{x}`|`\absolutevalue{x}`| physics extension | -|\acomm|$`\acomm{A}{B}`|`\acomm{A}{B}`| physics extension | -|\acute|$`\acute e`|`\acute e`|| -|\AE|$`\text{\AE}`|`\text{\AE}`|| -|\ae|$`\text{\ae}`|`\text{\ae}`|| -|\alef|$`\alef`|| texvc extension | -|\alefsym|$`\alefsym`|| texvc extension | -|\aleph|$`\aleph`||| -|{align}|$$\begin{align}a&=b+c\\d+e&=f\end{align}$$|`\begin{align}`
   `a&=b+c \\`
   `d+e&=f`
`\end{align}` | ams | -|{align\*}|$$\begin{align*}a&=b+c\\d+e&=f\end{align*}$$|`\begin{align*}`
   `a&=b+c \\`
   `d+e&=f`
`\end{align*}` | ams | -|{aligned}|$$\begin{aligned}a&=b+c\\d+e&=f\end{aligned}$$|`\begin{aligned}`
   `a&=b+c \\`
   `d+e&=f`
`\end{aligned}`| ams | -|{alignat}|$$\begin{alignat}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignat}$$|`\begin{alignat}{2}`
   `10&x+ &3&y = 2 \\`
   ` 3&x+&13&y = 4`
`\end{alignat}` | ams | -|{alignat\*}|$$\begin{alignat*}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignat*}$$|`\begin{alignat*}{2}`
   `10&x+ &3&y = 2 \\`
   ` 3&x+&13&y = 4`
`\end{alignat*}` | ams | -|{alignedat}|$$\begin{alignedat}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignedat}$$|`\begin{alignedat}{2}`
   `10&x+ &3&y = 2 \\`
   ` 3&x+&13&y = 4`
`\end{alignedat}` | ams | -|\allowbreak|||| -|\Alpha|$`\Alpha`||| -|\alpha|$`\alpha`||| -|\amalg|$`\amalg`||| -|\And|$`\And`||| -|\and|(Not supported)|[Deprecated](https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax)| texvc | -|\ang|(Not supported)|[Deprecated](https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax)| texvc | -|\angl|$`a_{\angl n}`|`a_{\angl n}` | actuarialangle | -|\angln|$`a_\angln`|`a_\angln` | actuarialangle | -|\angle|$`\angle`||| -|\anticommutator|$`\anticommutator{A}{B}`|`\anticommutator{A}{B}`| physics extension | -|\approx|$`\approx`||| -|\approxeq|$`\approxeq`||| -|\arccos|$`\arccos`||| -|\arcctg|$`\arcctg`||| -|\arceq|$`\arceq`|| stix | -|\arcsin|$`\arcsin`||| -|\arctan|$`\arctan`||| -|\arctg|$`\arctg`||| -|\arg|$`\arg`||| -|\argmax|$`\argmax`|| statmath | -|\argmin|$`\argmin`|| statmath | -|{array}|$`\begin{array}{cc}a&b\\c&d\end{array}` | `\begin{array}{cc}`
   `a & b \\`
   `c & d`
`\end{array}`| LaTeX2ε | -|\array|(Not supported)|See `{array}`|| -|\arraystretch|$`\def\arraystretch{1.5}\begin{array}{cc}a&b\\c&d\end{array}`|`\def\arraystretch{1.5}`
`\begin{array}{cc}`
   `a & b \\`
   `c & d`
`\end{array}`|| -|\Arrowvert|(Not supported)|see `\Vert`|| -|\arrowvert|(Not supported)|see `\vert`|| -|\ast|$`\ast`||| -|\asymp|$`\asymp`||| -|\atop|$`{a \atop b}`|`{a \atop b}`|| -|\atopwithdelims|(Not supported)||| - -## B - -| Function | Rendered | Source or Comment| Package -|----------------|-------------|------------------|-----------| -|\backcong|$`\backcong`|| MnSymbol | -|\backepsilon|$`\backepsilon`|| ams | -|\backprime|$`\backprime`|| ams | -|\backsim|$`\backsim`|| ams | -|\backsimeq|$`\backsimeq`|| ams | -|\backslash|$`\backslash`||| -|\bar|$`\bar{y}`|`\bar{y}`|| -|\barwedge|$`\barwedge`|| ams | -|\ballotx|$`\ballotx`|| arev | -|\Bbb|$`\Bbb{ABC}`|`\Bbb{ABC}`|| -|\Bbbk|$`\Bbbk`||| -|\bbox|(Not supported)||| -|\bcancel|$`\bcancel{5}`|`\bcancel{5}`| cancel | -|\because|$`\because`|| ams | -|\begin|$`\begin{matrix} a & b\\ c & d\end{matrix}`|`\begin{matrix}`
   `a & b \\`
   `c & d`
`\end{matrix}`| ams | -|\begingroup|$`\begingroup a\endgroup`|`\begingroup a\endgroup`|| -|\Beta|$`\Beta`||| -|\beta|$`\beta`||| -|\beth|$`\beth`|| ams | -|\between|$`\between`|| ams | -|\bf|$`{\bf AaBb12}`|`{\bf AaBb12}`|| -|\bfseries|(Not supported)||| -|\big|$`\big(\big)`|`\big(\big)`|| -|\Big|$`\Big(\Big)`|`\Big(\Big)`|| -|\bigcap|$`\bigcap`||| -|\bigcirc|$`\bigcirc`||| -|\bigcup|$`\bigcup`||| -|\bigg|$`\bigg(\bigg)`|`\bigg(\bigg)`|| -|\Bigg|$`\Bigg(\Bigg)`|`\Bigg(\Bigg)`|| -|\biggl|$`\biggl(`|`\biggl(`|| -|\Biggl|$`\Biggl(`|`\Biggl(`|| -|\biggm|$`\biggm\vert`|`\biggm\vert`|| -|\Biggm|$`\Biggm\vert`|`\Biggm\vert`|| -|\biggr|$`\biggr)`|`\biggr)`|| -|\Biggr|$`\Biggr)`|`\Biggr)`|| -|\bigl|$`\bigl(`|`\bigl(`|| -|\Bigl|$`\Bigl(`|`\Bigl(`|| -|\bigm|$`\bigm\vert`|`\bigm\vert`|| -|\Bigm|$`\Bigm\vert`|`\Bigm\vert`|| -|\bigodot|$`\bigodot`||| -|\bigominus|(Not supported)||| -|\bigoplus|$`\bigoplus`||| -|\bigoslash|(Not supported)||| -|\bigotimes|$`\bigotimes`||| -|\bigr|$`\bigr)`|`\bigr)`|| -|\Bigr|$`\Bigr)`|`\Bigr)`|| -|\bigsqcap|$`\bigsqcap`||| -|\bigsqcup|$`\bigsqcup`||| -|\bigstar|$`\bigstar`|| ams | -|\bigtriangledown|$`\bigtriangledown`||| -|\bigtriangleup|$`\bigtriangleup`||| -|\biguplus|$`\biguplus`||| -|\bigvee|$`\bigvee`||| -|\bigwedge|$`\bigwedge`||| -|\binom|$`\binom n k`|`\binom n k`| ams | -|\blacklozenge|$`\blacklozenge`|| ams | -|\blacksquare|$`\blacksquare`|| ams | -|\blacktriangle|$`\blacktriangle`|| ams | -|\blacktriangledown|$`\blacktriangledown`|| ams | -|\blacktriangleleft|$`\blacktriangleleft`|| ams | -|\blacktriangleright|$`\blacktriangleright`|| ams | -|\bm|$`\bm{AaBb}`|`\bm{AaBb}`| bm | -|{Bmatrix}|$`\begin{Bmatrix}a&b\\c&d\end{Bmatrix}`|`\begin{Bmatrix}`
   `a & b \\`
   `c & d`
`\end{Bmatrix}`| ams | -|{Bmatrix*}|$`\begin{Bmatrix*}[r] -1 & 3\\ 2 & -4 \end{Bmatrix*}`|`\begin{Bmatrix*}[r]`
   `-1 & 3 \\`
   `2 & -4`
`\end{Bmatrix*}`| mathtools | -|{bmatrix}|$`\begin{bmatrix}a&b\\c&d\end{bmatrix}`|`\begin{bmatrix}`
   `a & b \\`
   `c & d`
`\end{bmatrix}`| ams | -|{bmatrix*}|$`\begin{bmatrix*}[r] -1 & 3\\ 2 & -4 \end{bmatrix*}`|`\begin{bmatrix*}[r]`
   `-1 & 3 \\`
   `2 & -4`
`\end{bmatrix*}`| mathtools | -|\bmod|$`a \bmod b`|`a \bmod b`|| -|\bold|$`\bold{AaBb123}`|`\bold{AaBb123}`|| -|\boldsymbol|$`\boldsymbol{AaBb}`|`\boldsymbol{AaBb}`| ams | -|\bot|$`\bot`||| -|\Bot|$`\Bot`|| cmll | -|\bowtie|$`\bowtie`||| -|\Box|$`\Box`|| ams | -|\boxdot|$`\boxdot`|| ams | -|\boxed|$`\boxed{ab}`|`\boxed{ab}`| ams | -|\boxminus|$`\boxminus`|| ams | -|\boxplus|$`\boxplus`|| ams | -|\boxtimes|$`\boxtimes`|| ams | -|\Bqty|$`\Bqty{5 \text{mm}}`|`\Bqty{5 \text{mm}}`| physics extension | -|\bqty|$`\bqty{5 \text{mm}}`|`\bqty{5 \text{mm}}`| physics extension | -|\Bra|$`\left\langle\psi\right|`|`\Bra{\psi}`| braket | -|\bra|$`\mathinner{\langle{\psi}|}`|`\bra{\psi}`| braket | -|\braket|$`\mathinner{\langle{\phi | \psi}\rangle}`|`\braket{\phi\|\psi}`| braket | -|\Braket|$`\Braket{ \phi \| \frac{\partial^2}{\partial t^2} \| \psi }`|`\Braket{ϕ\|\frac{∂^2}{∂ t^2}\|ψ}`| braket -|\brace|$`{n\brace k}`|`{n\brace k}`|| -|\bracevert|(Not supported)||| -|\brack|$`{n\brack k}`|`{n\brack k}`|| -|\breve|$`\breve{eu}`|`\breve{eu}`|| -|\buildrel|(Not supported)||| -|\bull|$`\bull`|| texvc extension | -|\bullet|$`\bullet`||| -|\Bumpeq|$`\Bumpeq`|| ams | -|\bumpeq|$`\bumpeq`|| ams | - -## C - -| Function | Rendered | Source or Comment| Package -|----------------|-------------|------------------|-----------| -|\C|(Not supported)|[Deprecated](https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax)| texvc | -|\c|$`\text{\c{c}}`|`\text{\c{c}}`|| -|\cal|$`{\cal AaBb}`|`{\cal AaBb}`|| -|\cancel|$`\cancel{5}`|`\cancel{5}`| cancel | -|\cancelto|$`\cancelto{0}{x+1}`|`\cancelto{0}{x+1}`| cancel | -|\Cap|$`\Cap`|| ams | -|\cap|$`\cap`||| -|{cases}|$$\begin{cases}a&\text{if }b\\c&\text{if }d\end{cases}$$|`\begin{cases}`
   `a &\text{if } b \\`
   `c &\text{if } d`
`\end{cases}`| ams | -|\cases|(Not supported)|see `{cases}`|| -|{CD}|$$\begin{CD}A @>a>> B \\@VbVV @AAcA\\C @= D\end{CD}$$|`\begin{CD}`
   `A @>a>> B \\`
`@VbVV @AAcA \\`
   `C @= D`
`\end{CD}`| ams | -|\cdot|$`\cdot`||| -|\cdotp|$`\cdotp`||| -|\cdots|$`\cdots`||| -|\ce |$`{\mathrm{C}{\vphantom{X}}_{\smash[t]{6}}\mathrm{H}{\vphantom{X}}_{\smash[t]{5}}{-}\mathrm{CHO}}`|`\ce{C6H5-CHO}` | mhchem extension | -|\cee|(Not supported)|Deprecated
Use `\ce` instead. | mhchem | -|\centerdot|$`\centerdot`|| ams | -|\cf|(Not supported)|Deprecated
Use `\ce` instead.| mhchem | -|\cfrac|$`\cfrac{2}{1+\cfrac{2}{1}}`|`\cfrac{2}{1+\cfrac{2}{1}}`| ams | -|\check|$`\check{oe}`|`\check{oe}`|| -|\ch|$`\ch`||| -|\checkmark|$`\checkmark`|| ams | -|\Chi|$`\Chi`||| -|\chi|$`\chi`||| -|\choose|$`{n+1 \choose k+2}`|`{n+1 \choose k+2}`|| -|\circ|$`\circ`||| -|\circeq|$`\circeq`|| ams | -|\circlearrowleft|$`\circlearrowleft`|| ams | -|\circlearrowright|$`\circlearrowright`|| ams | -|\circledast|$`\circledast`|| ams | -|\circledcirc|$`\circledcirc`|| ams | -|\circleddash|$`\circleddash`|| ams | -|\circledR|$`\circledR`|| ams | -|\circledS|$`\circledS`|| ams | -|\class|(Not supported)||| -|\cline|(Not supported)||| -|\clubs|$`\clubs`|| texvc extension | -|\clubsuit|$`\clubsuit`||| -|\cnums|$`\cnums`|| texvc extension | -|\coh|$`\coh`|| cmll | -|\colon|$`\colon`||| -|\Colonapprox|$`\Colonapprox`|| mathtools | -|\colonapprox|$`\colonapprox`|| mathtools | -|\coloncolon|$`\coloncolon`|| colonequals | -|\coloncolonapprox|$`\coloncolonapprox`|| colonequals | -|\coloncolonequals|$`\coloncolonequals`|| colonequals | -|\coloncolonminus|$`\coloncolonminus`|| colonequals | -|\coloncolonsim|$`\coloncolonsim`|| colonequals | -|\colonminus|$`\colonminus`|| colonequals | -|\Coloneq|$`\Coloneq`|| mathtools | -|\coloneq|$`\coloneq`|| mathtools | -|\Coloneqq|$`\Coloneqq`|| mathtools | -|\coloneqq|$`\coloneqq`|| mathtools | -|\Colonsim|$`\Colonsim`|| mathtools | -|\colonsim|$`\colonsim`|| mathtools | -|\color|$`\color{#0000FF} AaBb123`|`\color{#0000FF} AaBb123`| color | -|\colorbox|$`\colorbox{red}{Black on red}`|`\colorbox{red}{Black on red}`| color | -|\comm|$`\comm{A}{B}`|`\comm{A}{B}`| physics extension | -|\commutator|$`\commutator{A}{B}`|`\commutator{A}{B}`| physics extension | -|\complement|$`\complement`|| ams | -|\Complex|$`\Complex`|| texvc extension | -|\cong|$`\cong`||| -|\Coppa|$`\Coppa`||| -|\coppa|$`\coppa`||| -|\coprod|$`\coprod`||| -|\copyright|$`\copyright`||| -|\cos|$`\cos`||| -|\cosec|$`\cosec`||| -|\cosh|$`\cosh`||| -|\cot|$`\cot`||| -|\cotg|$`\cotg`||| -|\coth|$`\coth`||| -|\cp|$`\cp`|| physics extension | -|\cr|$`\begin{matrix} a & b\cr c & d \end{matrix}`|`\begin{matrix}`
   `a & b \cr`
   `c & d`
`\end{matrix}`|| -|\cross|$`\cross`|| physics extension | -|\crossproduct|$`\crossproduct`|| physics extension | -|\csc|$`\csc`||| -|\cssId|(Not supported)|See `\id`.| -|\ctg|$`\ctg`||| -|\cth|$`\cth`||| -|\Cup|$`\Cup`|| ams | -|\cup|$`\cup`||| -|\curl|$`\curl`|| physics extension | -|\curlyeqprec|$`\curlyeqprec`|| ams | -|\curlyeqsucc|$`\curlyeqsucc`|| ams | -|\curlyvee|$`\curlyvee`|| ams | -|\curlywedge|$`\curlywedge`|| ams | -|\curvearrowleft|$`\curvearrowleft`|| ams | -|\curvearrowright|$`\curvearrowright`|| ams | - -## D - -| Function | Rendered | Source or Comment | Package | -|----------------|-------------|-------------------|-----------| -|\dag|$`\dag`||| -|\Dagger|$`\Dagger`|| texvc extension | -|\dagger|$`\dagger`||| -|\daleth|$`\daleth`|| ams | -|\Darr|$`\Darr`|| texvc extension | -|\dArr|$`\dArr`|| texvc extension | -|\darr|$`\darr`|| texvc extension | -|{darray}|$$\begin{darray}{cc}a&b\\c&d\end{darray}$$ | `\begin{darray}{cc}`
   `a & b \\`
   `c & d`
`\end{darray}`|| -|\dashleftarrow|$`\dashleftarrow`|| ams | -|\dashrightarrow|$`\dashrightarrow`|| ams | -|\dashv|$`\dashv`||| -|\dbinom|$`\dbinom n k`|`\dbinom n k`| ams | -|\dblcolon|$`\dblcolon`|| mathtools | -|{dcases}|$$\begin{dcases}a&\text{if }b\\c&\text{if }d\end{dcases}$$ | `\begin{dcases}`
   `a &\text{if } b \\`
   `c &\text{if } d`
`\end{dcases}`| mathtools | -|\dd|$`\dd`|`\dd`| physics extension | -|\ddag|$`\ddag`||| -|\ddagger|$`\ddagger`||| -|\ddddot|$`\ddddot x`|`\ddddot x`| ams | -|\dddot|$`\dddot x`|`\dddot x`| ams | -|\ddot|$`\ddot x`|`\ddot x`|| -|\ddots|$`\ddots`||| -|\DeclareMathOperator|(Not supported)||| -|\def|$`\def\foo{x^2} \foo + \foo`|`\def\foo{x^2} \foo + \foo`|| -|\definecolor|$`\definecolor{sortaGreen}{RGB}{128,128,0} \color{sortaGreen} F=ma`| `\definecolor{sortaGreen}{RGB}{128,128,0}`
`\color{sortaGreen} F=ma` | xcolor | -|\deg|$`\deg`||| -|\degree|$`\degree`||| -|\delta|$`\delta`||| -|\Delta|$`\Delta`||| -|\derivative|$`\derivative{x}{y}`|`\derivative{x}{y}`| physics extension | -|\det|$`\det`||| -|\dfrac|$`\dfrac{a-1}{b-1}`|`\dfrac{a-1}{b-1}`| ams | -|\differential|$`\differential`|`\differential`| physics extension | -|\diagdown|$`\diagdown`|| ams | -|\diagonalmatrix|(Not supported)|| physics | -|\diagup|$`\diagup`|| ams | -|\Diamond|$`\Diamond`||| -|\diamond|$`\diamond`||| -|\diamonds|$`\diamonds`|| texvc extension | -|\diamondsuit|$`\diamondsuit`||| -|\Digamma|(Not supported)||| -|\digamma|$`\digamma`|| ams | -|\dim|$`\dim`||| -|\displaylines|(Not supported)||| -|\displaystyle|$`\displaystyle\sum_0^n`|`\displaystyle\sum_0^n`|| -|\div|$`\div`||| -|\divergence|$`\divergence`|`\divergence`| physics extension | -|\divideontimes|$`\divideontimes`|| ams | -|\dot|$`\dot x`|`\dot x`|| -|\Doteq|$`\Doteq`|| ams | -|\doteq|$`\doteq`||| -|\doteqdot|$`\doteqdot`|| ams | -|\dotplus|$`\dotplus`|| ams | -|\dotproduct|$`\dotproduct`|`\dotproduct`| physics extension | -|\dots|$`x_1 + \dots + x_n` | `x_1 + \dots + x_n` || -|\dotsb|$`x_1 +\dotsb + x_n` | `x_1 +\dotsb + x_n` | ams | -|\dotsc|$`x,\dotsc,y`|`x,\dotsc,y`| ams | -|\dotsi|$$\int_{A_1}\int_{A_2}\dotsi$$|`\int_{A_1}\int_{A_2}\dotsi`| ams | -|\dotsm|$`x_1 x_2 \dotsm x_n`|`$x_1 x_2 \dotsm x_n`| ams | -|\dotso|$`\dotso`|| ams | -|\doublebarwedge|$`\doublebarwedge`|| ams | -|\doublecap|$`\doublecap`|| ams | -|\doublecup|$`\doublecup`|| ams | -|\Downarrow|$`\Downarrow`||| -|\downarrow|$`\downarrow`||| -|\downdownarrows|$`\downdownarrows`|| ams | -|\downharpoonleft|$`\downharpoonleft`|| ams | -|\downharpoonright|$`\downharpoonright`|| ams | -|{drcases}|$`\begin{drcases}a&\text{if }b\\c&\text{if }d\end{drcases}`|`\begin{drcases}`
   `a &\text{if } b \\`
   `c &\text{if } d`
`\end{drcases}`| mathtools | -|\dv|$`\dv{x}{y}`|`\dv{x}{y}`| physics extension | -|\dyad|$`\dyad{a}{b}`|`\dyad{a}{b}`| physics extension | - - -## E - -
- -| Function | Rendered | Source or Comment | Package | -|----------------|-------------|-------------------|-----------| -|\edef|$`\def\foo{a}\edef\bar{\foo}\def\foo{}\bar`|`\def\foo{a}\edef\bar{\foo}\def\foo{}\bar`|| -|\ell|$`\ell`||| -|\else|(Not supported)||| -|\em|(Not supported)||| -|\emph|(Not supported)||| -|\empty|$`\empty`|| texvc extension | -|\emptyset|$`\emptyset`||| -|\enclose|(Not supported)|Non standard.
See `\boxed`, `\cancel`, `\bcancel`,
`\xcancel`, `\sout`, `\longdiv`, `\angl`|| -|\end|$`\begin{matrix} a & b\\ c & d\end{matrix}`|`\begin{matrix}`
   `a & b \\`
   `c & d`
`\end{matrix}`|| -|\endgroup|$`\begingroup a\endgroup`|`\begingroup a\endgroup`|| -|\enspace|$`a\enspace b`|`a\enspace b`|| -|\Epsilon|$`\Epsilon`||| -|\epsilon|$`\epsilon`||| -|\eqalign|(Not supported)|See {align*}|| -|\eqalignno|(Not supported)|See {align}|| -|\eqcirc|$`\eqcirc`|| ams | -|\Eqcolon|$`\Eqcolon`|| mathtools | -|\eqcolon|$`\eqcolon`|| mathtools | -|\equalscolon|$`\equalscolon`|| colonequals | -|\equalscoloncolon|$`\equalscoloncolon`|| colonequals | -|{equation}|$$\begin{equation}a = b + c\end{equation}$$|`\begin{equation}`
   `a = b + c`
`\end{equation}`| ams | -|{equation*}|$$\begin{equation*}a = b + c\end{equation*}$$|`\begin{equation*}`
   `a = b + c`
`\end{equation*}`| ams | -|{eqnarray}|(Not supported)||| -|\Eqqcolon|$`\Eqqcolon`|| mathtools | -|\eqqcolon|$`\eqqcolon`|| mathtools | -|\eqdef|$`\eqdef`|| stix | -|\eqref|$`\eqref{tag1}`|`\eqref{tag1}`
Some sites do not support `\eqref`.| ams | -|\eqsim|$`\eqsim`|| ams | -|\eqslantgtr|$`\eqslantgtr`|| ams | -|\eqslantless|$`\eqslantless`|| ams | -|\equiv|$`\equiv`||| -|\erf|$`\erf(x)`|`\erf(x)`| physics extension || -|\Eta|$`\Eta`||| -|\eta|$`\eta`||| -|\eth|$`\eth`|| ams | -|\euro|$`\euro`||| -|\ev|$`\ev{x}`|`\ev{x}`| physics extension | -|\eval|$`\eval{\tfrac 1 2 x}_0^n`|`\eval{\tfrac 1 2 x}_0^n`| physics extension | -|\evaluated|$`\evaluated{\tfrac 1 2 x}_0^n`|`\evaluated{\tfrac 1 2 x}_0^n`| physics extension | -|\exist|$`\exist`|| texvc extension | -|\exists|$`\exists`||| -|\exp|$`\exp`||| -|\expandafter|||| -|\expectationvalue|$`\expectationvalue{x}`|`\expectationvalue{x}`| physics extension | -|\expval|$`\expval{x}`|`\expval{x}`| physics extension | - -## F - -| Function | Rendered | Source or Comment | Package | -|-----------------------|--------------------------------|------------------------------|-------------------| -| \fallingdotseq | $`\fallingdotseq` | | ams | -| \fbox | $`\fbox{Hi there!}` | `\fbox{Hi there!}` | | -| \fcolorbox | $`\fcolorbox{red}{aqua}{A}` | `\fcolorbox{red}{aqua}{A}` | xcolor | -| \fdv | $`\fdv{x}{y}` | `\fdv{x}{y}` | physics extension | -| \female | $`\female` | | stix | -| \fi | (Not supported) | | | -| \Finv | $`\Finv` | | ams | -| \flat | $`\flat` | | | -| \footnotesize | $`\footnotesize footnotesize` | `\footnotesize footnotesize` | | -| \forall | $`\forall` | | | -| \frac | $`\frac a b` | `\frac a b` | ams | -| \frak | $`\frak{AaBb}` | `\frak{AaBb}` | | -| \frown | $`\frown` | | | -| \functionalderivative | $`\functionalderivative{x}{y}` | `\functionalderivative{x}{y}`| physics extension | -| \futurelet | | | | - -## G - -
- -| Function | Rendered | Source or Comment | Package | -|----------------|-------------|-------------------|-----------| -| \Game | $`\Game`| | ams | -| \Gamma | $`\Gamma`| | | -| \gamma | $`\gamma`| | | -| {gather} | $$\begin{gather}a=b\\e=b+c\end{gather}$$| `\begin{gather}`
   `a=b \\ `
   `e=b+c`
`\end{gather}`| ams | -| {gather*} | $$\begin{gather*}a=b\\e=b+c\end{gather*}$$| `\begin{gather*}`
   `a=b \\ `
   `e=b+c`
`\end{gather*}`| ams | -| {gathered} | $`\begin{gathered}a=b\\e=b+c\end{gathered}`| `\begin{gathered}`
   `a=b \\ `
   `e=b+c`
`\end{gathered}`| ams | -| \gcd | $`\gcd`| | | -| \gdef | (Not supported)| | | -| \ge | $`\ge`| | | -| \geneuro | (Not supported) | See `\euro`| | -| \geneuronarrow | (Not supported) | See `\euro`| | -| \geneurowide | (Not supported) | See `\euro`| | -| \genfrac | $`\genfrac ( ] {2pt}{0}a{a+1}` | `\genfrac ( ] {2pt}{0}a{a+1}`| ams | -| \geq | $`\geq`| | | -| \geqq | $`\geqq`| | ams | -| \geqslant | $`\geqslant`| | ams | -| \gets | $`\gets`| | | -| \gg | $`\gg`| | | -| \ggg | $`\ggg`| | ams | -| \gggtr | $`\gggtr`| | ams | -| \gimel | $`\gimel`| | ams | -| \global | (Not supported)| | | -| \gnapprox | $`\gnapprox`| | ams | -| \gneq | $`\gneq`| | ams | -| \gneqq | $`\gneqq`| | ams | -| \gnsim | $`\gnsim`| | ams | -| \grad | $`\grad`| | physics extension | -| \gradient | $`\gradient`| | physics extension | -| \grave | $`\grave{eu}`| `\grave{eu}`| | -| \gt | $`a \gt b`| `a \gt b`| MathJax | -| \gtrapprox | $`\gtrapprox`| | ams | -| \gtrdot | $`\gtrdot`| | ams | -| \gtreqless | $`\gtreqless`| | ams | -| \gtreqqless | $`\gtreqqless`| | ams | -| \gtrless | $`\gtrless`| | ams | -| \gtrsim | $`\gtrsim`| | ams | -| \gvertneqq | $`\gvertneqq`| | ams | - -## H - -| Function | Rendered | Source or Comment | Package | -|-----------------|---------------------------|-------------------|-----------| -| \H | $`\text{\H{a}}` | `\text{\H{a}}`| | -| \Harr | $`\Harr` | | texvc extension | -| \hArr | $`\hArr` | | texvc extension | -| \harr | $`\harr` | | texvc extension | -| \hat | $`\hat{\theta}` | `\hat{\theta}`| | -| \hbar | $`\hbar` | | | -| \hbox | $`\hbox{$x^2$}` | `\hbox{$x^2$}`| | -| \hbox to | (Not supported) | | | -| \hdashline | $`\begin{matrix}a&b\\ \hdashline c &d\end{matrix}`| `\begin{matrix}`
   `a & b \\`
   `\hdashline`
   `c & d`
`\end{matrix}`| arydshln | -| \hearts | $`\hearts` | | texvc extension | -| \heartsuit | $`\heartsuit` | | | -| \hfil | (Not supported) | | | -| \hfill | (Not supported) | | | -| \hline | $`\begin{matrix}a&b\\ \hline c &d\end{matrix}`| `\begin{matrix}`
   `a & b \\ \hline`
   `c & d`
`\end{matrix}`| | -| \hom | $`\hom` | | | -| \hookleftarrow | $`\hookleftarrow` | | | -| \hookrightarrow | $`\hookrightarrow` | | | -| \hphantom | $`a\hphantom{bc}d` | `a\hphantom{bc}d`| | -| \href | $`\href{https://temml.org/}{\Temml}`| `\href{https://temml.org/}{\Temml}`
Requires `trust` [option](options.md)| href | -| \hskip | $`w\hskip1em i\hskip2em d` | `w\hskip1em i\hskip2em d`| | -| \hslash | $`\hslash` | | ams | -| \hspace | $`s\hspace{7ex} k` | `s\hspace{7ex} k`| | -| \class | $`\class{foo}{x}` | `\class{foo}{x}`
Must enable `trust` and disable `strict` [option](options.md)| | -| \data | $`\data{foo=a, bar=b}{x}` | `\data{foo=a, bar=b}{x}`
Must enable `trust` and disable `strict` [option](options.md)| | -| \id | $`\id{bar}{x}`| `\id{bar}{x}`
Must enable `trust` and disable `strict` [option](options.md)| | -| \style | $`\style{color: red;}{x}`| `\style{color: red;}{x}`
Must enable `trust` and disable `strict` [option](options.md)| | -| \huge | $`\huge huge` | `\huge huge`| | -| \Huge | $`\Huge Huge` | `\Huge Huge`| | - -## I - -| Function | Rendered | Source or Comment | Package | -|------------------|------------------------|-----------------------|-------------------| -| \i | $`\text{\i}` | `\text{\i}` | | -| \idotsint | $`\int\idotsint\int` | `\int\idotsint\int` | ams | -| \iddots | $`\iddots` | | | -| \if | (Not supported) | | | -| \iff | $`A\iff B` | `A\iff B` | | -| \ifmode | (Not supported) | | | -| \ifx | (Not supported) | | | -| \iiiint | $`\iiiint` | | ams | -| \iiint | $`\iiint` | | ams | -| \iint | $`\iint` | | ams | -| \Im | $`\Im` | | | -| \image | $`\image` | | texvc extension | -| \imageof | $`\imageof` | | stix | -| \imath | $`\imath` | | | -| \impliedby | $`P\impliedby Q` | `P\impliedby Q` | ams | -| \implies | $`P\implies Q` | `P\implies Q` | ams | -| \in | $`\in` | | | -| \includegraphics | $`\includegraphics[height=1em, totalheight=1.2em, width=1.2em, alt=sphere]{../sphere.jpg}` | `\includegraphics[height=1em,`
`totalheight=1.2em, width=1.2em,`
`alt=sphere]{../sphere.jpg}` | graphicx | -|\incoh | $`\incoh` | | cmll | -| \inf | $`\inf` | | | -| \infin | $`\infin` | | texvc extension | -| \infty | $`\infty` | | | -| \injlim | $`\injlim` | `\injlim` | ams | -| \innerproduct | $`\innerproduct{a}{b}` | `\innerproduct{a}{b}` | physics extension | -| \int | $`\int` | | | -| \intbar | $`\intbar` | | | -| \intBar | $`\intBar` | | | -| \intcap | $`\intcap` | | | -| \intclockwise | $`\intclockwise` | | | -| \intcup | $`\intcup` | | | -| \intercal | $`\intercal` | | ams | -| \intlarhk | $`\intlarhk` | | | -| \intop | $`\intop` | | | -| \intx | $`\intx` | | | -| \invamp | $`\invamp` | | cmll | -| \Iota | $`\Iota` | | | -| \iota | $`\iota` | | | -| \isin | $`\isin` | | texvc extension | -| \it | $`{\it AaBb}` | `{\it AaBb}` | | -| \itshape | (Not supported) | | | - -## JK - -| Function | Rendered | Source or Comment | Package | -|----------|---------------------------------|-------------------|-------------------| -| \j | $`\text{\j}` | `\text{\j}` | | -| \jmath | $`\jmath` | | | -| \Join | $`\Join` | | ams | -| \Kappa | $`\Kappa` | | | -| \kappa | $`\kappa` | | | -| \ker | $`\ker` | | | -| \kern | $`I\kern-2.5pt R` | `I\kern-2.5pt R` | | -| \Ket | $`\left| \psi\right\rangle` | `\Ket{\psi}` | braket | -| \ket | $`\mathinner{| {\psi}\rangle}` | `\ket{\psi}` | braket | -| \ketbra | $`\ketbra{a}{b}` | `\ketbra{a}{b}` | physics extension | -| \Koppa | $`\Koppa` | | | -| \koppa | $`\koppa` | | | - -## L - -| Function | Rendered | Source or Comment | Package | -|----------------------|----------------------------|-------------------|-----------| -| \L | (Not supported) | | | -| \l | (Not supported) | | | -| \Lambda | $`\Lambda` | | | -| \lambda | $`\lambda` | | | -| \label | | `\label{idName}`
Creates an HTML id.
Characters limited to: `A-Za-z0-9_-`| | -| \land | $`\land` | | | -| \lang | $`\lang A\rangle` | `\lang A\rangle` | texvc extension | -| \langle | $`\langle A\rangle` | `\langle A\rangle` | | -| \laplacian | $`\laplacian` | | physics extension | -| \Larr | $`\Larr` | | texvc extension | -| \lArr | $`\lArr` | | texvc extension | -| \larr | $`\larr` | | texvc extension | -| \large | $`\large large` | `\large large`| | -| \Large | $`\Large Large` | `\Large Large`| | -| \LARGE | $`\LARGE LARGE` | `\LARGE LARGE`| | -| \LaTeX | $`\LaTeX` | | | -| \lBrace | $`\lBrace` | | stix | -| \lbrace | $`\lbrace` | | | -| \lbrack | $`\lbrack` | | | -| \lceil | $`\lceil` | | | -| \ldotp | $`\ldotp` | | | -| \ldots | $`\ldots` | | | -| \le | $`\le` | | | -| \leadsto | $`\leadsto` | | ams | -| \left | $`\left\lbrace \dfrac ab \right.` | `\left\lbrace \dfrac ab \right.`| | -| \leftarrow | $`\leftarrow` | | | -| \Leftarrow | $`\Leftarrow` | | | -| \LeftArrow | (Not supported) | Non standard | | -| \leftarrowtail | $`\leftarrowtail` | | ams | -| \leftharpoondown | $`\leftharpoondown` | | | -| \leftharpoonup | $`\leftharpoonup` | | | -| \leftleftarrows | $`\leftleftarrows` | | ams | -| \Leftrightarrow | $`\Leftrightarrow` | | | -| \leftrightarrow | $`\leftrightarrow` | | | -| \leftrightarrows | $`\leftrightarrows` | | ams | -| \leftrightharpoons | $`\leftrightharpoons` | | ams | -| \leftrightsquigarrow | $`\leftrightsquigarrow` | | ams | -| \leftroot | (Not supported) | | | -| \leftthreetimes | $`\leftthreetimes` | | ams | -| \leq | $`\leq` | | | -| \leqalignno | (Not supported) | | | -| \leqq | $`\leqq` | | ams | -| \leqslant | $`\leqslant` | | ams | -| \lessapprox | $`\lessapprox` | | ams | -| \lessdot | $`\lessdot` | | ams | -| \lesseqgtr | $`\lesseqgtr` | | ams | -| \lesseqqgtr | $`\lesseqqgtr` | | ams | -| \lessgtr | $`\lessgtr` | | ams | -| \lesssim | $`\lesssim` | | ams | -| \let | | | | -| \lfloor | $`\lfloor` | | | -| \lg | $`\lg` | | | -| \lgroup | $`\lgroup` | | | -| \lhd | $`\lhd` | | ams | -| \lightning | $`\lightning` | | -| \lim | $`\lim` | | -| \liminf | $`\liminf` | | | -| \limits | $`\lim\limits_x` | `\lim\limits_x`| | -| \limsup | $`\limsup` | | | -| \ll | $`\ll` | | | -| \llap | $`{=}\llap{/\,}` | `{=}\llap{/\,}`| | -| \llbracket | $`\llbracket` | | stmaryrd | -| \llcorner | $`\llcorner` | | ams | -| \Lleftarrow | $`\Lleftarrow` | | ams | -| \lll | $`\lll` | | ams | -| \llless | $`\llless` | | ams | -| \lmoustache | $`\lmoustache` | | | -| \ln | $`\ln` | | | -| \lnapprox | $`\lnapprox` | | ams | -| \lneq | $`\lneq` | | ams | -| \lneqq | $`\lneqq` | | ams | -| \lnot | $`\lnot` | | | -| \lnsim | $`\lnsim` | | ams | -| \log | $`\log` | | | -| \long | | | | -| \longdiv | $`\longdiv{3x^2 + 2x + 5}` | `\longdiv{3x^2 + 2x + 5}` | Temml | -| \Longleftarrow | $`\Longleftarrow` | | | -| \longleftarrow | $`\longleftarrow` | | | -| \Longleftrightarrow | $`\Longleftrightarrow` | | | -| \longleftrightarrow | $`\longleftrightarrow` | | | -| \longmapsto | $`\longmapsto` | | | -| \Longrightarrow | $`\Longrightarrow` | | | -| \longrightarrow | $`\longrightarrow` | | | -| \looparrowleft | $`\looparrowleft` | | ams | -| \looparrowright | $`\looparrowright` | | ams | -| \lor | $`\lor` | | | -| \lower | $`M\lower5pt{M^2}M` | `M\lower5pt{M^2}M`  or
`M\lower5pt\hbox{$`M^2`}M`| | -| \lozenge | $`\lozenge` | | ams | -| \lparen | $`\lparen` | | mathtools | -| \Lrarr | $`\Lrarr` | | texvc extension | -| \lrArr | $`\lrArr` | | texvc extension | -| \lrarr | $`\lrarr` | | texvc extension | -| \lrcorner | $`\lrcorner` | | ams | -| \lq | $`\lq` | | | -| \Lsh | $`\Lsh` | | ams | -| \lt | $`\lt` | | MathJax | -| \ltimes | $`\ltimes` | | ams | -| \lVert | $`\lVert` | | ams | -| \lvert | $`\lvert` | | ams | -| \lvertneqq | $`\lvertneqq` | | ams | - -## M - -| Function | Rendered | Source or Comment | Package | -|----------------|-------------|-------------------|-----------| -|\male|$`\male`|| stix | -|\maltese|$`\maltese`|| ams | -|\mapsto|$`\mapsto`||| -|\mathbb|$`\mathbb{AB}`|`\mathbb{AB}`| ams | -|\mathbf|$`\mathbf{AaBb123}`|`\mathbf{AaBb123}`|| -|\mathbin|$`a\mathbin{!}b`|`a\mathbin{!}b`|| -|\mathcal|$`\mathcal{AaBb}`|`\mathcal{AaBb}`|| -|\mathchoice|$`a\mathchoice{\,}{\,\,}{\,\,\,}{\,\,\,\,}b`|`a\mathchoice{\,}{\,\,}{\,\,\,}{\,\,\,\,}b`|| -|\mathclap|$`\displaystyle\sum_{\mathclap{1\le i\le n}} x_{i}`|`\sum_{\mathclap{1\le i\le n}} x_{i}`| mathtools | -|\mathclose|$`a + (b\mathclose\gt + c`|`a + (b\mathclose\gt + c`|| -|\mathellipsis|$`\mathellipsis`||| -|\mathfrak|$`\mathfrak{AaBb}`|`\mathfrak{AaBb}`| ams | -|\mathinner|$`ab\mathinner{\text{inside}}cd`|`ab\mathinner{\text{inside}}cd`|| -|\mathit|$`\mathit{AaBb}`|`\mathit{AaBb}`|| -|\mathllap|$`{=}\mathllap{/\,}`|`{=}\mathllap{/\,}`| mathtools | -|\mathnormal|$`\mathnormal{AaBb}`|`\mathnormal{AaBb}`|| -|\mathop|$`\mathop{\star}_a^b`|`\mathop{\star}_a^b`|| -|\mathopen|$`a + \mathopen\lt b) + c`|`a + \mathopen\lt b) + c`|| -|\mathord|$`1\mathord{,}234{,}567`|`1\mathord{,}234{,}567`|| -|\mathpunct|$`A\mathpunct{-}B`|`A\mathpunct{-}B`|| -|\mathrel|$`a \mathrel{\#} b`|`a \mathrel{\#} b`|| -|\mathrlap|$`\mathrlap{\,/}{=}`|`\mathrlap{\,/}{=}`| mathtools | -|\mathring|$`\mathring{a}`|`\mathring{a}`| ams | -|\mathrm|$`\mathrm{AaBb12}`|`\mathrm{AaBb12}`|| -|\mathscr|$`\mathscr{AB}`|`\mathscr{AB}`|| -|\mathsf|$`\mathsf{AaBb123}`|`\mathsf{AaBb123}`|| -|\mathsterling|$`\mathsterling`||| -|\mathstrut|$`\sqrt{\mathstrut a}`|`\sqrt{\mathstrut a}`|| -|\mathtip|(Not supported)|See `\texttip`|| -|\mathtt|$`\mathtt{AaBb123}`|`\mathtt{AaBb123}`|| -|\matrix|(Not supported)|See `{matrix}`|| -|{matrix}|$`\begin{matrix}a&b\\c&d\end{matrix}`|`\begin{matrix}`
   `a & b \\`
   `c & d`
`\end{matrix}`| ams | -|{matrix*}|$`\begin{matrix*}[r] -1 & 3\\ 2 & -4 \end{matrix*}`|`\begin{matrix*}[r]`
   `-1 & 3 \\`
   `2 & -4`
`\end{matrix*}`| mathtools | -|\matrixel|$`\matrixel{n}{A}{m}`|`\matrixel{n}{A}{m}`| physics extension | -|\matrixelement|$`\matrixelement{n}{A}{m}`|`\matrixelement{n}{A}{m}`| physics extension | -|\mel|$`\mel{n}{A}{m}`|`\mel{n}{A}{m}`| physics extension | -|\max|$`\max`||| -|\mbox|(Not supported)||| -|\md|(Not supported)||| -|\mdseries|(Not supported)||| -|\measeq|$`\measeq`|| stix | -|\measuredangle|$`\measuredangle`|| ams | -|\medspace|$`a\medspace b`|`a\medspace b`| ams | -|\mho|$`\mho`||| -|\mid|$`\{x∈ℝ\mid x>0\}`|`\{x∈ℝ\mid x>0\}`|| -|\middle|$`P\left(A\middle\vert B\right)`|`P\left(A\middle\vert B\right)`|| -|\min|$`\min`||| -|\minuscolon|$`\minuscolon`|| colonequals | -|\minuscoloncolon|$`\minuscoloncolon`|| colonequals | -|\minuso|(Not supported)| See `\standardstate`|| -|\mit|(Not supported)|See `\mathit`|| -|\mkern|$`a\mkern18mu b`|`a\mkern18mu b`|| -|\mmlToken|(Not supported)||| -|\mod|$`3\equiv 5 \mod 2`|`3\equiv 5 \mod 2`| ams | -|\models|$`\models`||| -|\moveleft|(Not supported)||| -|\moveright|(Not supported)||| -|\mp|$`\mp`||| -|\mskip|$`a\mskip{10mu}b`|`a\mskip{10mu}b`|| -|\mspace|(Not supported)||| -|\Mu|$`\Mu`||| -|\mu|$`\mu`||| -|\multicolumn|(Not supported)||| -|\multimap|$`\multimap`|| ams | -|\multimapboth|$`\multimapboth`|| cmll | -|\multimapinv|$`\multimapinv`|| cmll | -|{multline}|$$\begin{multline}\rm uno \\ \rm dos \\ \rm tres\end{multline}$$|`\begin{multline}`
  `\rm uno \\`
  `\rm dos \\`
  `\rm tres`
`\end{multline}`| ams | -|{multline*}|$$\begin{multline*}\rm uno \\ \rm dos \\ \rm tres\end{multline*}$$|`\begin{multline*}`
  `\rm uno \\`
  `\rm dos \\`
  `\rm tres`
`\end{multline*}`| ams | - -## N - -
- -| Function | Rendered | Source or Comment | Package | -|----------------|-------------|-------------------|-----------| -|\N|$`\N`|| texvc extension | -|\nabla|$`\nabla`||| -|\natnums|$`\natnums`|| texvc extension | -|\natural|$`\natural`||| -|\negmedspace|$`a\negmedspace b`|`a\negmedspace b`| ams | -|\ncong|$`\ncong`|| ams | -|\ne|$`\ne`||| -|\nearrow|$`\nearrow`||| -|\neg|$`\neg`||| -|\negthickspace|$`a\negthickspace b`|`a\negthickspace b`| ams | -|\negthinspace|$`a\negthinspace b`|`a\negthinspace b`| ams | -|\neq|$`\neq`||| -|\newcommand|$`\newcommand\chk{\checkmark} \chk`|`\newcommand\chk{\checkmark} \chk`| newcommand | -|\newenvironment|(Not supported)||| -|\newextarrow|(Not supported)|| extpfeil | -|\newline|$`a\newline b`|`a\newline b`|| -|\nexists|$`\nexists`|| ams | -|\ngeq|$`\ngeq`|| ams | -|\ngeqq|$`\ngeqq`|| ams | -|\ngeqslant|$`\ngeqslant`|| ams | -|\ngtr|$`\ngtr`|| ams | -|\ni|$`\ni`||| -|\nleftarrow|$`\nleftarrow`|| ams | -|\nLeftarrow|$`\nLeftarrow`|| ams | -|\nLeftrightarrow|$`\nLeftrightarrow`|| ams | -|\nleftrightarrow|$`\nleftrightarrow`|| ams | -|\nleq|$`\nleq`|| ams | -|\nleqq|$`\nleqq`|| ams | -|\nleqslant|$`\nleqslant`|| ams | -|\nless|$`\nless`|| ams | -|\nmid|$`\nmid`|| ams | -|\nobreak|||| -|\nobreakspace|$`a\nobreakspace b`|`a\nobreakspace b`| ams | -|\noexpand|||| -|\nolimits|$`\lim\nolimits_x`|`\lim\nolimits_x`|| -|\norm|$`\norm{x}`|\norm{x}| physics extension | -|\normalfont|(Not supported)||| -|\normalsize|$`\normalsize normalsize`|`\normalsize normalsize`|| -|\not|$`\not =`|`\not =`|| -|\notag|$$\begin{align} a&=b \\ \notag d+e&=f \end{align}$$|`\begin{align}`
  `a&=b \\`
  `\notag d+e&=f`
`\end{align}`| ams | -|\notin|$`\notin`||| -|\notni|$`\notni`|| txfonts/pxfonts | -|\nparallel|$`\nparallel`|| ams | -|\nprec|$`\nprec`|| ams | -|\npreceq|$`\npreceq`|| ams | -|\nRightarrow|$`\nRightarrow`|| ams | -|\nrightarrow|$`\nrightarrow`|| ams | -|\nshortmid|$`\nshortmid`|| ams | -|\nshortparallel|$`\nshortparallel`|| ams | -|\nsim|$`\nsim`|| ams | -|\nsubset|$`\nsubset`|| mathabx | -|\nsubseteq|$`\nsubseteq`|| ams | -|\nsubseteqq|$`\nsubseteqq`|| ams | -|\nsucc|$`\nsucc`|| ams | -|\nsucceq|$`\nsucceq`|| ams | -|\nsupset|$`\nsupset`|| mathabx | -|\nsupseteq|$`\nsupseteq`|| ams | -|\nsupseteqq|$`\nsupseteqq`|| ams | -|\ntriangleleft|$`\ntriangleleft`|| ams | -|\ntrianglelefteq|$`\ntrianglelefteq`|| ams | -|\ntriangleright|$`\ntriangleright`|| ams | -|\ntrianglerighteq|$`\ntrianglerighteq`|| ams | -|\Nu|$`\Nu`||| -|\nu|$`\nu`||| -|\nVDash|$`\nVDash`|| ams | -|\nVdash|$`\nVdash`|| ams | -|\nvDash|$`\nvDash`|| ams | -|\nvdash|$`\nvdash`|| ams | -|\nwarrow|$`\nwarrow`||| - -## O - -| Function | Rendered | Source or Comment | Package | -|----------------|-------------|-------------------|-----------| -|\O|$`\text{\O}`|`\text{\O}`|| -|\o|$`\text{\o}`|`\text{\o}`|| -|\oc|$`\oc`|| cmll | -|\odot|$`\odot`||| -|\odv|$`\odv{f}{x}`|`\odv{f}{x}`| derivative | -|\odv*|$`\odv*{f}{x}`|`\odv*{f}{x}`| derivative | -|\OE|$`\text{\OE}`|`\text{\OE}`|| -|\oe|$`\text{\oe}`|`\text{\oe}`|| -|\officialeuro|(Not supported)|See `\euro`|| -|\oiiint|$`\oiiint`||| -|\oiint|$`\oiint`||| -|\oint|$`\oint`||| -|\oldstyle|(Not supported)| See `\oldstylenums`|| -|\oldstylenums|$`\oldstylenums{123}`|`\oldstylenums{123}`| LaTeX2ε | -|\omega|$`\omega`||| -|\Omega|$`\Omega`||| -|\Omicron|$`\Omicron`||| -|\omicron|$`\omicron`||| -|\ominus|$`\ominus`||| -|\op|$`\op{a}{b}`|`\op{a}{b}`| physics extension | -|\operatorname|$`\operatorname{asin} x`|\operatorname{asin} x| ams | -|\operatorname\*|$`\operatorname*{asin}\limits_y x`|`\operatorname*{asin}\limits_y x`| ams | -|\operatornamewithlimits|$`\operatornamewithlimits{asin}\limits_y x`|`\operatornamewithlimits{asin}\limits_y x`| | -|\oplus|$`\oplus`||| -|\or|(Not supported)||| -|\order|$`\order{x^2}`|`\order{x^2}`| physics extension | -|\origof|$`\origof`|| stix | -|\oslash|$`\oslash`||| -|\otimes|$`\otimes`||| -|\outerproduct|$`\outerproduct{a}{b}`|`\outerproduct{a}{b}`| physics extension | -|\over|$`{a+1 \over b+2}+c`|`{a+1 \over b+2}+c`|| -|\overbrace|$`\overbrace{x+⋯+x}^{n\text{ times}}`|`\overbrace{x+⋯+x}^{n\text{ times}}`|| -|\overbracket|(Not supported)||| -|\overgroup|$`\overgroup{AB}`|`\overgroup{AB}`| MnSymbol | -|\overleftarrow|$`\overleftarrow{AB}`|`\overleftarrow{AB}`| ams | -|\overleftharpoon|$`\overleftharpoon{AB}`|`\overleftharpoon{AB}`| MnSymbol | -|\overleftrightarrow|$`\overleftrightarrow{AB}`|`\overleftrightarrow{AB}`| ams | -|\overline|$`\overline{\text{a long argument}}`|`\overline{\text{a long argument}}`|| -|\overlinesegment|(Not supported)||| -|\overparen|$`\overparen{abc}`|`\overparen{abc}`|| -|\Overrightarrow|$`\Overrightarrow{AB}`|`\Overrightarrow{AB}`| overrightarrow | -|\overrightarrow|$`\overrightarrow{AB}`|`\overrightarrow{AB}`| ams | -|\overrightharpoon|$`\overrightharpoon{ac}`|`\overrightharpoon{ac}`|| -|\overset|$`\overset{!}{=}`|`\overset{!}{=}`| ams | -|\overwithdelims|(Not supported)||| -|\owns|$`\owns`||| - -## P - -| Function | Rendered | Source or Comment | Package | -|----------------|-------------|-------------------|-----------| -|\P|$`\text{\P}`|`\text{\P}` or `\P`|| -|\pagecolor|(Not supported)|[Deprecated](https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax)| texvc | -|\parallel|$`\parallel`||| -|\parr|$`\parr`|| cmll | -|\part|(Not supported)|[Deprecated](https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax)| texvc | -|\partial|$`\partial`||| -|\partialderivative|$`\partialderivative{x}{y}`|`\partialderivative{x}{y}`| physics extension | -|\pb|$`\pb{x}{y}`|`\pb{x}{y}`| physics extension | -|\pdv|$`\pdv{f}{x,y}`|`\pdv{f}{x,y}`| derivative | -|\pdv*|$`\pdv*{f}{x,y}`|`\pdv*{f}{x,y}`| derivative | -|\permil|$`\permil`|| wasysym | -|\perp|$`\perp`||| -|\Perp|$`\Perp`|| cmll | -|\phantom|$`\Gamma^{\phantom{i}j}_{i\phantom{j}k}`|`\Gamma^{\phantom{i}j}_{i\phantom{j}k}`|| -|\phase|$`\phase{-78^\circ}`|`\phase{-78^\circ}`| steinmetz | -|\Phi|$`\Phi`||| -|\phi|$`\phi`||| -|\Pi|$`\Pi`||| -|\pi|$`\pi`||| -|{picture}|(Not supported)||| -|\pitchfork|$`\pitchfork`|| ams | -|\plim|$`\plim`|| statmath | -|\plusmn|$`\plusmn`|| texvc extension | -|\pm|$`\pm`||| -|\pmatrix|(Not supported)| See `{pmatrix}` || -|{pmatrix}|$`\begin{pmatrix}a&b\\c&d\end{pmatrix}`|`\begin{pmatrix}`
   `a & b \\`
   `c & d`
`\end{pmatrix}`| ams | -|{pmatrix*}|$`\begin{pmatrix*}[r] -1 & 3\\ 2 & -4 \end{pmatrix*}`|`\begin{pmatrix*}[r]`
   `-1 & 3 \\`
   `2 & -4`
`\end{pmatrix*}`| mathtools | -|\pmb|$`\pmb{\mu}`|`\pmb{\mu}`| ams | -|\pmod|$`x\pmod a`|`x\pmod a`|| -|\pod|$`x \pod a`|`x \pod a`| ams | -|\pointint|$`\pointint`||| -|\poissonbracket|$`\poissonbracket{A}{B}`|`\poissonbracket{A}{B}`| physics extension | -|\pounds|$`\pounds`||| -|\pqty|$`\pqty{5}`|`\pqty{5}`| physics extension | -|\Pr|$`\Pr`||| -|\prec|$`\prec`||| -|\precapprox|$`\precapprox`|| ams | -|\preccurlyeq|$`\preccurlyeq`|| ams | -|\preceq|$`\preceq`|| ams | -|\precnapprox|$`\precnapprox`|| ams | -|\precneqq|$`\precneqq`|| ams | -|\precnsim|$`\precnsim`|| ams | -|\precsim|$`\precsim`|| ams | -|\prescript|$`\prescript{a}{2}{\mathbf{C}}^{5+}_{2}`|`\prescript{a}{2}{\mathbf{C}}^{5+}_{2}`| mathtools | -|\prime|$`\prime`||| -|\principalvalue|$`\principalvalue`|| physics extension | -|\pv|$`\pv`|| physics extension | -|\PV|$`\PV(x)`|`\PV(x)`| physics extension | -|\prod|$`\prod`||| -|\projlim|$`\projlim`|`\projlim`| ams | -|\propto|$`\propto`||| -|\providecommand|$`\providecommand\greet{\text{Hello}} \greet`|`\providecommand\greet{\text{Hello}}`
`\greet`|| -|\psi|$`\psi`||| -|\Psi|$`\Psi`||| -|\pu |$`{123~\mathchoice{\textstyle\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}}`|`\pu{123 kJ//mol}`| mhchem extension | - -## Q - -| Function | Rendered | Source or Comment | Package | -|-------------|--------------------------|-------------------------|-------------------| -| \Q | (Not supported) | See `\Bbb{Q}` | | -| \qall | $`\qall` | | physics extension | -| \qand | $`\qand` | | physics extension | -| \qas | $`\qas` | | physics extension | -| \qassume | $`\qassume` | | physics extension | -| \qc | $`\qc` | | physics extension | -| \qcc | $`\qcc` | | physics extension | -| \qcomma | $`\qcomma` | | physics extension | -| \qelse | $`\qelse` | | physics extension | -| \qeven | $`\qeven` | | physics extension | -| \qfor | $`\qfor` | | physics extension | -| \qgiven | $`\qgiven` | | physics extension | -| \qif | $`\qif` | | physics extension | -| \qin | $`\qin` | | physics extension | -| \qinteger | $`\qinteger` | | physics extension | -| \qlet | $`\qlet` | | physics extension | -| \qodd | $`\qodd` | | physics extension | -| \qor | $`\qor` | | physics extension | -| \qotherwise | $`\qotherwise` | | physics extension | -| \qq | $`\qq{text}` | `\qq{text}` | physics extension | -| \qqtext | $`\qqtext{text}` | `\qqtext{text}` | physics extension | -| \qquad | $`a\qquad\qquad{b}` | `a\qquad\qquad{b}` | | -| \qsince | $`\qsince` | | physics extension | -| \qthen | $`\qthen` | | physics extension | -| \qty | $`\qty{5 \text{m}}` | `\qty{5 \text{m}}` | physics extension | -| \quad | $`a\quad\quad{b}` | `a\quad\quad{b}` | | -| \quantity | $`\quantity{5 \text{m}}` | `\quantity{5 \text{m}}` | physics extension | -| \qunless | $`\qunless` | | physics extension | -| \qusing | $`\qusing` | | physics extension | -| \questeq | $`\questeq` | | stix | - -## R - -| Function | Rendered | Source or Comment | Package | -|--------------------|-------------|-------------------|-----------| -| \R | $`\R`| | texvc extension | -| \r | $`\text{\r{a}}`| `\text{\r{a}}`| | -| \raise | $`M\raise3pt{M^2}M`| `M\raise3pt{M^2}M`  or
`M\raise3pt\hbox{$`M^2`}M`| | -| \raisebox | $`h\raisebox{2pt}{ighe}r`| `h\raisebox{2pt}{ighe}r`| | -| \rang | $`\langle A\rang`| `\langle A\rang` | texvc extension | -| \rangle | $`\langle A\rangle`| `\langle A\rangle`| | -| \rank | $`\rank M`| `\rank M`| physics extension | -| \Rarr | $`\Rarr`| | texvc extension | -| \rArr | $`\rArr`| | texvc extension | -| \rarr | $`\rarr`| | texvc extension | -| \ratio | $`\ratio`| | colonequals | -| \rBrace | $`\rBrace`| | stix | -| \rbrace | $`\rbrace`| | | -| \rbrack | $`\rbrack`| | | -| {rcases} | $`\begin{rcases}a&\text{if }b\\c&\text{if }d\end{rcases}`| `\begin{rcases}`
   `a &\text{if } b \\`
   `c &\text{if } d`
`\end{rcases}`| mathtools | -| \rceil | $`\rceil`| | | -| \Re | $`\Re`| | | -| \real | $`\real`| | texvc extension | -| \Reals | $`\Reals`| | texvc extension | -| \reals | $`\reals`| | texvc extension | -| \ref | $`\ref{tag1}`| `\ref{tag1}`
Some sites do not support `\ref`.| | -| \relax | | | | -| \renewcommand | $`\def\hail{Hi!}\renewcommand\hail{\text{Ahoy!}} \hail`| `\def\hail{Hi!}`
`\renewcommand\hail{\text{Ahoy!}}`
`\hail`| newcommand | -| \renewenvironment | (Not supported)| | newcommand | -| \require | (Not supported)| | | -| \Res | $`\Res[f(z)]`| `\Res[f(z)]`| physics extension | -| \restriction | $`\restriction`| | ams | -| \rfloor | $`\rfloor`| | | -| \rgroup | $`\rgroup`| | | -| \rhd | $`\rhd`| | ams | -| \Rho | $`\Rho`| | | -| \rho | $`\rho`| | | -| \right | $`\left.\dfrac a b\right)`| `\left.\dfrac a b\right)`| | -| \Rightarrow | $`\Rightarrow`| | | -| \rightarrow | $`\rightarrow`| | | -| \rightarrowtail | $`\rightarrowtail`| | ams | -| \rightharpoondown | $`\rightharpoondown`| | | -| \rightharpoonup | $`\rightharpoonup`| | | -| \rightleftarrows | $`\rightleftarrows`| | ams | -| \rightleftharpoons | $`\rightleftharpoons`| | ams | -| \rightrightarrows | $`\rightrightarrows`| | ams | -| \rightsquigarrow | $`\rightsquigarrow`| | ams | -| \rightthreetimes | $`\rightthreetimes`| | ams | -| \risingdotseq | $`\risingdotseq`| | ams | -| \rlap | $`\rlap{\,/}{=}`| `\rlap{\,/}{=}`| | -| \rm | $`{\rm AaBb12}`| `{\rm AaBb12}`| | -| \rmoustache | $`\rmoustache`| | | -| \root | (Not supported)| | | -| \rotatebox | (Not supported)| | | -| \rparen | $`\rparen`| | mathtools | -| \rppolint | $`\rppolint`| | | -| \rq | $`\rq`| | | -| \rrbracket | $`\rrbracket`| | stmaryrd | -| \Rrightarrow | $`\Rrightarrow`| | ams | -| \Rsh | $`\Rsh`| | ams | -| \rtimes | $`\rtimes`| | ams | -| \Rule | (Not supported)| see `\rule`| | -| \rule | $`x\rule[6pt]{2ex}{1ex}x`| `x\rule[6pt]{2ex}{1ex}x`| | -| \rVert | $`\rVert`| | ams | -| \rvert | $`\rvert`| | ams | - -## S - -
- -| Function | Rendered | Source or Comment | Package | -|----------------|-------------|-------------------|-----------| -|\S|$`\text{\S}`|`\text{\S}` or `\S`|| -|\Sampi|$`\Sampi`||| -|\sampi|$`\sampi`||| -|\sc|(Not supported)|See `\textsc`|| -|\scoh|$`\scoh`|| cmll | -|\scalebox|(Not supported)||| -|\scpolint|$`\scpolint`||| -|\scr|(Not supported)|See `\mathscr`|| -|\scriptscriptstyle|$`\scriptscriptstyle \frac cd`|`\scriptscriptstyle \frac cd`|| -|\scriptsize|$`\scriptsize scriptsize`|`\scriptsize scriptsize`|| -|\scriptstyle|$`A{\scriptstyle B}`|`A{\scriptstyle B}`|| -|\sdot|$`\sdot`|| texvc extension | -|\searrow|$`\searrow`||| -|\sec|$`\sec`||| -|\sect|$`\text{\sect}`|`\text{\sect}`| texvc extension | -|\set| $`\Set{ x | x<5 }` |`\set{x | x<5}`| braket -|\Set| $`\Set{ x | x<\tfrac 1 2 }` |`\Set{ x | x<\tfrac 1 2 }`| braket -|\setlength|(Not supported)||| -|\setminus|$`\setminus`||| -|\sf|$`{\sf AaBb123}`|`{\sf AaBb123}`|| -|\sgn|$`\sgn`|| mismath | -|\sharp|$`\sharp`||| -|\shift|$`\shift`|| cmll | -|\shneg|$`\shneg`|| cmll | -|\shortmid|$`\shortmid`|| ams | -|\shortparallel|$`\shortparallel`|| ams | -|\shoveleft|(Not supported)|| ams | -|\shoveright|(Not supported)|| ams | -|\shpos|$`\shpos`|| cmll | -|\sideset|$`\sideset{_a^b}{_c^d}\sum`|`\sideset{_a^b}{_c^d}\sum`| ams | -|\Sigma|$`\Sigma`||| -|\sigma|$`\sigma`||| -|\sim|$`\sim`||| -|\simeq|$`\simeq`||| -|\sin|$`\sin`||| -|\sincoh|$`\sincoh`|| cmll | -|\sinh|$`\sinh`||| -|\sixptsize|$`\sixptsize sixptsize`|`\sixptsize sixptsize`|| -|\sh|$`\sh`||| -|\skew|(Not supported)||| -|\skip|(Not supported)||| -|\sl|(Not supported)||| -|\small|$`\small small`|`\small small`|| -|\smallfrown|$`\smallfrown`|| ams | -|\smallint|$`\smallint`||| -|{smallmatrix}|$`\begin{smallmatrix} a & b \\ c & d \end{smallmatrix}`|`\begin{smallmatrix}`
   `a & b \\`
   `c & d`
`\end{smallmatrix}`|| -|\smallsetminus|$`\smallsetminus`|| ams | -|\smallsmile|$`\smallsmile`|| ams | -|\smash|$`\left(x^{\smash{2}}\right)`|`\left(x^{\smash{2}}\right)`|| -|\smile|$`\smile`||| -|\smiley|$`\smiley`|| wasysym | -|\sout|$`\sout{abc}`|`\sout{abc}`| ulem | -|\Space|(Not supported)|see `\space`|| -|\space|$`a\space b`|`a\space b`|| -|\spades|$`\spades`|| texvc extension | -|\spadesuit|$`\spadesuit`||| -|\sphericalangle|$`\sphericalangle`|| ams | -|{split}|$$\begin{equation}\begin{split}a &=b+c\\&=e+f\end{split}\end{equation}$$|`\begin{equation}`
`\begin{split}`
   `a &=b+c\\`
      `&=e+f`
`\end{split}`
`\end{equation}`| ams | -|\sqcap|$`\sqcap`||| -|\sqcup|$`\sqcup`||| -|\sqint|$`\sqint`||| -|\square|$`\square`||| -|\sqrt|$`\sqrt[3]{x}`|`\sqrt[3]{x}`|| -|\sqsubset|$`\sqsubset`|| ams | -|\sqsubseteq|$`\sqsubseteq`||| -|\sqsupset|$`\sqsupset`|| ams | -|\sqsupseteq|$`\sqsupseteq`|| ams | -|\ss|$`\text{\ss}`|`\text{\ss}`|| -|\stackrel|$`\stackrel{!}{=}`|`\stackrel{!}{=}`|| -|\standardstate|$`\standardstate`|| chemstyle | -|\star|$`\star`||| -|\stareq|$`\stareq`|| stix | -|\Stigma|$`\Stigma`||| -|\stigma|$`\stigma`||| -|\strictif|$`\strictif`|| txfonts/pxfonts | -|\strictfi|$`\strictfi`|| txfonts/pxfonts | -|\strut|(Not supported)||| -|\style|(Not supported)|Non standard|| -|\sub|$`\sub`|| texvc extension | -|{subarray}|$$\sum_{\begin{subarray}{l} i\in\Lambda\\ 0 `i\in\Lambda\\`
  `0`\end{subarray}}P(i,j)`| ams | -|\sube|$`\sube`|| texvc extension | -|\Subset|$`\Subset`|| ams | -|\subset|$`\subset`||| -|\subseteq|$`\subseteq`||| -|\subseteqq|$`\subseteqq`|| ams | -|\subsetneq|$`\subsetneq`|| ams | -|\subsetneqq|$`\subsetneqq`|| ams | -|\substack|$$\sum_{\substack{0 - -| Function | Rendered | Source or Comment | Package | -|----------------|-------------|-------------------|-----------| -|\tag|$$\tag{hi} e=mc^2 \label{tag1}$$|`\tag{hi} e=mc^2 \label{tag1}`| ams | -|\tag*|$$\tag*{hey} e=mc^2$$|`\tag*{hey} e=mc^2`| ams | -|\tan|$`\tan`||| -|\tanh|$`\tanh`||| -|\Tau|$`\Tau`||| -|\tau|$`\tau`||| -|\tbinom|$`\tbinom n k`|`\tbinom n k`| ams | -|\TeX|$`\TeX`||| -|\text|$`\text{ yes }\&\text{ no }`|`\text{ yes }\&\text{ no }`|| -|\textasciitilde|$`\text{\textasciitilde}`|`\text{\textasciitilde}`|| -|\textasciicircum|$`\text{\textasciicircum}`|`\text{\textasciicircum}`|| -|\textbackslash|$`\text{\textbackslash}`|`\text{\textbackslash}`|| -|\textbar|$`\text{\textbar}`|`\text{\textbar}`|| -|\textbardbl|$`\text{\textbardbl}`|`\text{\textbardbl}`|| -|\textbf|$`\textbf{AaBb123}`|`\textbf{AaBb123}`|| -|\textbraceleft|$`\text{\textbraceleft}`|`\text{\textbraceleft}`|| -|\textbraceright|$`\text{\textbraceright}`|`\text{\textbraceright}`|| -|\textbullet|$`\text{\textbullet}`|`\text{\textbullet}`|| -|\textcircled|(Not supported)||| -|\textcolor|$`\textcolor{blue}{F=ma}`|`\textcolor{blue}{F=ma}`| color | -|\textdagger|$`\text{\textdagger}`|`\text{\textdagger}`|| -|\textdaggerdbl|$`\text{\textdaggerdbl}`|`\text{\textdaggerdbl}`|| -|\textdegree|$`\text{\textdegree}`|`\text{\textdegree}`|| -|\textdollar|$`\text{\textdollar}`|`\text{\textdollar}`|| -|\textellipsis|$`\text{\textellipsis}`|`\text{\textellipsis}`|| -|\textemdash|$`\text{\textemdash}`|`\text{\textemdash}`|| -|\textendash|$`\text{\textendash}`|`\text{\textendash}`|| -|\\texteuro|$`\text{\texteuro}`|`\text{\texteuro}`|| -|\textgreater|$`\text{\textgreater}`|`\text{\textgreater}`|| -|\textit|$`\textit{AaBb}`|`\textit{AaBb}`|| -|\textless|$`\text{\textless}`|`\text{\textless}`|| -|\textmd|$`\textmd{AaBb123}`|`\textmd{AaBb123}`|| -|\textnormal|$`\textnormal{AB}`|`\textnormal{AB}`|| -|\textquotedblleft|$`\text{\textquotedblleft}`|`\text{\textquotedblleft}`|| -|\textquotedblright|$`\text{\textquotedblright}`|`\text{\textquotedblright}`|| -|\textquoteleft|$`\text{\textquoteleft}`|`\text{\textquoteleft}`|| -|\textquoteright|$`\text{\textquoteright}`|`\text{\textquoteright}`|| -|\textregistered|$`\text{\textregistered}`|`\text{\textregistered}`|| -|\textrm|$`\textrm{AaBb123}`|`\textrm{AaBb123}`|| -|\textsc|$`\textsc{hey}`|`\textsc{hey}`|| -|\textsf|$`\textsf{AaBb123}`|`\textsf{AaBb123}`|| -|\textsl|(Not supported)||| -|\textsterling|$`\text{\textsterling}`|`\text{\textsterling}`|| -|\textstyle|$`\textstyle\sum_0^n`|`\textstyle\sum_0^n`|| -|\texttip|$`\texttip{\text{hover here}}{This is a tooltip.}`|`\texttip{\text{hover here}}`
`{This is a tooltip.}`|MathJax| -|\texttt|$`\texttt{AaBb123}`|`\texttt{AaBb123}`|| -|\textunderscore|$`\text{\textunderscore}`|`\text{\textunderscore}`|| -|\textup|$`\textup{AaBb123}`|`\textup{AaBb123}`|| -|\textvisiblespace|$`\text{\textvisiblespace}`|`\text{\textvisiblespace}`|| -|\tfrac|$`\tfrac ab`|`\tfrac ab`| ams | -|\tg|$`\tg`||| -|\th|$`\th`||| -|\therefore|$`\therefore`|| ams | -|\Theta|$`\Theta`||| -|\theta|$`\theta`||| -|\thetasym|$`\thetasym`|| texvc extension | -|\thickapprox|$`\thickapprox`|| ams | -|\thicksim|$`\thicksim`|| ams | -|\thickspace|$`a\thickspace b`|`a\thickspace b`| ams | -|\thinspace|$`a\thinspace b`|`a\thinspace b`| ams | -|\tilde|$`\tilde M`|`\tilde M`|| -|\times|$`\times`||| -|\Tiny|$`\Tiny Tiny`|`\Tiny Tiny`|| -|\tiny|$`\tiny tiny`|`\tiny tiny`|| -|\to|$`\to`||| -|\toggle|$`\toggle{\text{Click me}}{Hey!}{Ow!}\endtoggle`|`\toggle{\text{Click me}}`
`{Hey!}{Ow!}\endtoggle`| MathJax | -|\top|$`\top`||| -|\Tr|$`\Tr\rho`|`\Tr\rho`| physics extension | -|\tr|$`\tr\rho`|`\tr\rho`| physics extension | -|\triangle|$`\triangle`||| -|\triangledown|$`\triangledown`|| ams | -|\triangleleft|$`\triangleleft`||| -|\trianglelefteq|$`\trianglelefteq`|| ams | -|\triangleq|$`\triangleq`|| ams | -|\triangleright|$`\triangleright`||| -|\trianglerighteq|$`\trianglerighteq`|| ams | -|\tt|$`{\tt AaBb123}`|`{\tt AaBb123}`|| -|\twoheadleftarrow|$`\twoheadleftarrow`|| ams | -|\twoheadrightarrow|$`\twoheadrightarrow`|| ams | - -## U - -| Function | Rendered | Source or Comment | Package | -|----------------------|-----------------------------|----------------------------|-----------------| -| \u | $`\text{\u{a}}` | `\text{\u{a}}` | | -| \Uarr | $`\Uarr` | | texvc extension | -| \uArr | $`\uArr` | | texvc extension | -| \uarr | $`\uarr` | | texvc extension | -| \ulcorner | $`\ulcorner` | | ams | -| \underbar | $`\underbar{X}` | `\underbar{X}` | | -| \underbrace | $`\underbrace{x+⋯+x}_{n\text{ times}}`| `\underbrace{x+⋯+x}_{n\text{ times}}`| | -| \underbracket | (Not supported) | | | -| \undergroup | $`\undergroup{AB}` | `\undergroup{AB}` | MnSymbol | -| \underleftarrow | $`\underleftarrow{AB}` | `\underleftarrow{AB}` | ams | -| \underleftrightarrow | $`\underleftrightarrow{AB}` | `\underleftrightarrow{AB}` | ams | -| \underrightarrow | $`\underrightarrow{AB}` | `\underrightarrow{AB}` | ams | -| \underline | $`\underline{\text{a long argument}}`| `\underline{\text{a long argument}}`| | -| \underlinesegment | (Not supported) | | | -| \underparen | $`\underparen{abc}` | `\underparen{abc}` | | -| \underrightarrow | $`\underrightarrow{AB}` | `\underrightarrow{AB}` | | -| \underset | $`\underset{!}{=}` | `\underset{!}{=}` | AMS | -| \unicode | (Not supported) | See `\char` | | -| \unlhd | $`\unlhd` | | ams | -| \unrhd | $`\unrhd` | | ams | -| \up | (Not supported) | | | -| \upalpha | $`\upalpha` | | upgreek | -| \Uparrow | $`\Uparrow` | | | -| \uparrow | $`\uparrow` | | | -| \upbeta | $`\upbeta` | | upgreek | -| \updelta | $`\updelta` | | upgreek | -| \upchi | $`\upchi` | | upgreek | -| \Updownarrow | $`\Updownarrow` | | | -| \updownarrow | $`\updownarrow` | | | -| \upeta | $`\upeta` | | upgreek | -| \upepsilon | $`\upepsilon` | | upgreek | -| \upgamma | $`\upgamma` | | upgreek | -| \upharpoonleft | $`\upharpoonleft` | | ams | -| \upharpoonright | $`\upharpoonright` | | ams | -| \upiota | $`\upiota` | | upgreek | -| \upkappa | $`\upkappa` | | upgreek | -| \uplambda | $`\uplambda` | | upgreek | -| \upmu | $`\upmu` | | upgreek | -| \upnu | $`\upnu` | | upgreek | -| \upomega | $`\upomega` | | upgreek | -| \upomicron | $`\upomicron` | | upgreek | -| \uplus | $`\uplus` | | upgreek | -| \upphi | $`\upphi` | | upgreek | -| \uppi | $`\uppi` | | upgreek | -| \uppsi | $`\uppsi` | | upgreek | -| \uprho | $`\uprho` | | upgreek | -| \uproot | (Not supported) | | | -| \upshape | (Not supported) | | | -| \upsigma | $`\upsigma` | | upgreek | -| \Upsilon | $`\Upsilon` | | | -| \upsilon | $`\upsilon` | | | -| \uptau | $`\uptau` | | upgreek | -| \uptheta | $`\uptheta` | | upgreek | -| \upuparrows | $`\upuparrows` | | ams | -| \upupsilon | $`\upupsilon` | | upgreek | -| \upxi | $`\upxi` | | upgreek | -| \upzeta | $`\upzeta` | | upgreek | -| \urcorner | $`\urcorner` | | ams | -| \url | $`\footnotesize\url{https://temml.org/}`| `\url{https://temml.org/}`
Requires `trust` [option](options.md)| | -| \utilde | $`\utilde{AB}` | `\utilde{AB}` | undertilde | - -## V - -| Function | Rendered | Source or Comment | Package | -|----------------|-------------|-------------------|-----------| -|\v|$`\text{\v{a}}`|`\text{\v{a}}`|| -|\va|$`\va{a}`|`\va{a}`| physics extension | -|\var|$`\var`|| physics extension | -|\varcoppa|$`\varcoppa`||| -|\varclubsuit|$`\varclubsuit`|| txfonts | -|\varDelta|$`\varDelta`|| ams | -|\vardiamondsuit|$`\vardiamondsuit`|| txfonts | -|\varepsilon|$`\varepsilon`||| -|\varGamma|$`\varGamma`|| ams | -|\varheartsuit|$`\varheartsuit`|| txfonts | -|\variation|$`\variation`|| physics extension | -|\varinjlim|$`\varinjlim`|`\varinjlim`| ams | -|\varkappa|$`\varkappa`|| ams | -|\varLambda|$`\varLambda`|| ams | -|\varliminf|$`\varliminf`|`\varliminf`| ams | -|\varlimsup|$`\varlimsup`|`\varlimsup`| ams | -|\varnothing|$`\varnothing`|| ams | -|\varointclockwise|$`\varointclockwise`||| -|\varOmega|$`\varOmega`|| ams | -|\varPhi|$`\varPhi`|| ams | -|\varphi|$`\varphi`||| -|\varPi|$`\varPi`|| ams | -|\varpi|$`\varpi`||| -|\varprojlim|$`\varprojlim`|`\varprojlim`| ams | -|\varpropto|$`\varpropto`|| ams | -|\varPsi|$`\varPsi`|| ams | -|\varrho|$`\varrho`||| -|\varSigma|$`\varSigma`|| ams | -|\varsigma|$`\varsigma`||| -|\varspadesuit|$`\varspadesuit`|| txfonts | -|\varstigma|(Not supported)||| -|\varsubsetneq|$`\varsubsetneq`|| ams | -|\varsubsetneqq|$`\varsubsetneqq`|| ams | -|\varsupsetneq|$`\varsupsetneq`|| ams | -|\varsupsetneqq|$`\varsupsetneqq`|| ams | -|\varTheta|$`\varTheta`|| ams | -|\vartheta|$`\vartheta`||| -|\vartriangle|$`\vartriangle`|| ams | -|\vartriangleleft|$`\vartriangleleft`|| ams | -|\vartriangleright|$`\vartriangleright`|| ams | -|\varUpsilon|$`\varUpsilon`|| ams | -|\varXi|$`\varXi`|| ams | -|\vb|$`\vb{a}`|`\vb{a}`| physics extension | -|\vcentcolon|$`\vcentcolon`||| -|\vcenter|(Not supported)||| -|\Vdash|$`\Vdash`|| ams | -|\vDash|$`\vDash`|| ams | -|\vdash|$`\vdash`||| -|\vdot|$`\vdot`|| physics extension | -|\vdots|$`\vdots`||| -|\vec|$`\vec{F}`|`\vec{F}`|| -|\vectorarrow|$`\vectorarrow{a}`|`\vectorarrow{a}`| physics extension | -|\vectorbold|$`\vectorbold{a}`|`\vectorbold{a}`| physics extension | -|\vectorunit|$`\vectorunit{a}`|`\vectorunit{a}`| physics extension | -|\vee|$`\vee`||| -|\veebar|$`\veebar`|| ams | -|\veeeq|$`\veeeq`|| stix | -|\verb|$`\verb!\frac a b!`|`\verb!\frac a b!`|| -|\Vert|$`\Vert`||| -|\vert|$`\vert`||| -|\vfil|(Not supported)||| -|\vfill|(Not supported)||| -|\vline|(Not supported)||| -|{Vmatrix}|$`\begin{Vmatrix}a&b\\c&d\end{Vmatrix}`|`\begin{Vmatrix}`
   `a & b \\`
   `c & d`
`\end{Vmatrix}`| ams | -|{Vmatrix*}|$`\begin{Vmatrix*}[r] -1 & 3\\ 2 & -4 \end{Vmatrix*}`|`\begin{Vmatrix*}[r]`
   `-1 & 3 \\`
   `2 & -4`
`\end{Vmatrix*}`| mathtools | -|{vmatrix}|$`\begin{vmatrix}a&b\\c&d\end{vmatrix}`|`\begin{vmatrix}`
   `a & b \\`
   `c & d`
`\end{vmatrix}`| ams | -|{vmatrix*}|$`\begin{vmatrix*}[r] -1 & 3\\ 2 & -4 \end{vmatrix*}`|`\begin{vmatrix*}[r]`
   `-1 & 3 \\`
   `2 & -4`
`\end{vmatrix*}`| mathtools | -|\vphantom|$`\overline{\vphantom{M}a}`|`\overline{\vphantom{M}a}`|| -|\vqty|$`\vqty{x}`|`\vqty{x}`| physics extension | -|\vu|$`\vu{a}`|`\vu{a}`| physics extension | -|\Vvdash|$`\Vvdash`|| ams | - -## W - -| Function | Rendered | Source or Comment | Package | -|------------|--------------------|-------------------|-----------------| -| \wedge | $`\wedge` | | | -| \wedgeq | $`\wedgeq` | | stix | -| \weierp | $`\weierp` | | texvc extension | -| \widecheck | $`\widecheck{AB}` |`\widecheck{AB}` | mathabx | -| \widehat | $`\widehat{AB}` |`\widehat{AB}` | | -| \wideparen | $`\wideparen{abc}` |`\wideparen{abc}` | MnSymbol | -| \widetilde | $`\widetilde{AB}` |`\widetilde{AB}` | | -| \with | $`\with` | | cmll | -| \wn | $`\wn` | | cmll | -| \wp | $`\wp` | | | -| \wr | $`\wr` | | | - -## X - -| Function | Rendered | Source or Comment | Package | -|---------------------|-----------------------------|----------------------------|-----------| -| \xcancel | $`\xcancel{ABC}` | `\xcancel{ABC}` | cancel | -| \xdef | (Not supported) | | | -| \Xi | $`\Xi` | | | -| \xi | $`\xi` | | | -| \xhookleftarrow | $`\xhookleftarrow{abc}` | `\xhookleftarrow{abc}` | mathtools | -| \xhookrightarrow | $`\xhookrightarrow{abc}` | `\xhookrightarrow{abc}` | mathtools | -| \xLeftarrow | $`\xLeftarrow{abc}` | `\xLeftarrow{abc}` | mathtools | -| \xleftarrow | $`\xleftarrow{abc}` | `\xleftarrow{abc}` | ams | -| \xleftharpoondown | $`\xleftharpoondown{abc}` | `\xleftharpoondown{abc}` | mathtools | -| \xleftharpoonup | $`\xleftharpoonup{abc}` | `\xleftharpoonup{abc}` | mathtools | -| \xLeftrightarrow | $`\xLeftrightarrow{abc}` | `\xLeftrightarrow{abc}` | mathtools | -| \xleftrightarrow | $`\xleftrightarrow{abc}` | `\xleftrightarrow{abc}` | mathtools | -| \xleftrightharpoons | $`\xleftrightharpoons{abc}` | `\xleftrightharpoons{abc}` | mathtools | -| \xlongequal | $`\xlongequal{abc}` | `\xlongequal{abc}` | extpfeil | -| \xmapsto | $`\xmapsto{abc}` | `\xmapsto{abc}` | mathtools | -| \xRightarrow | $`\xRightarrow{abc}` | `\xRightarrow{abc}` | mathtools | -| \xrightarrow | $`\xrightarrow{abc}` | `\xrightarrow{abc}` | ams | -| \xrightharpoondown | $`\xrightharpoondown{abc}` | `\xrightharpoondown{abc}` | mathtools | -| \xrightharpoonup | $`\xrightharpoonup{abc}` | `\xrightharpoonup{abc}` | mathtools | -| \xrightleftharpoons | $`\xrightleftharpoons{abc}` | `\xrightleftharpoons{abc}` | mathtools | -| \xtofrom | $`\xtofrom{abc}` | `\xtofrom{abc}` | extpfeil | -| \xtwoheadleftarrow | $`\xtwoheadleftarrow{abc}` | `\xtwoheadleftarrow{abc}` | extpfeil | -| \xtwoheadrightarrow | $`\xtwoheadrightarrow{abc}` | `\xtwoheadrightarrow{abc}` | extpfeil | - -## YZ - -| Function | Rendered | Source or Comment | Package | -|----------------|-------------|-------------------|-----------------| -| \yen | $`\yen` | | ams | -| \Z | $`\Z` | | texvc extension | -| \Zeta | $`\Zeta` | | | -| \zeta |$`\zeta` | | | - - -
- -

Copyright © 2021, 2022 Ron Kok. Released under the MIT License

- -
- -
- - - -
- - - - -
- - - - - \ No newline at end of file diff --git a/docs/supported.md b/docs/supported.md deleted file mode 100644 index 192e5f16..00000000 --- a/docs/supported.md +++ /dev/null @@ -1,1623 +0,0 @@ - - - - - - Temml Functions - - - - - - - -
- -# Supported Functions - -**Temml** is a JavaScript library that converts TeX math-mode functions to MathML. -This page lists the TeX functions it supports, sorted into logical groups. - -To read this page, use a browser that supports MathML, such as Firefox or Safari. -Chrome and Edge will support MathML [soon](https://www.igalia.com/2021/08/09/MathML-Progress.html). - -There is a similar [Support Table](./support_table.html), sorted alphabetically, -that lists both supported and some un-supported functions. - -## Accents - -+:-------------------------+:-------------------------+:-----------------------------------+ -| $`a'` `a'` | $`\tilde{a}` `\tilde{a}` | $`\widetilde{ac}` `\widetilde{ac}` | -+--------------------------+--------------------------+------------------------------------+ -| $`a''` `a''` | $`\vec{F}` `\vec{F}` | $`\utilde{AB}` `\utilde{AB}` | -+--------------------------+--------------------------+------------------------------------+ -| $`a^{\prime}` | $`\overleftarrow{AB}` | $`\overrightarrow{AB}` | -| `a^{\prime}` | `\overleftarrow{AB}` | `\overrightarrow{AB}` | -+--------------------------+--------------------------+------------------------------------+ -| $`\acute{a}` `\acute{a}` | $`\underleftarrow{AB}` | $`\underrightarrow{AB}` | -| | `\underleftarrow{AB}` | `\underrightarrow{AB}` | -+--------------------------+--------------------------+------------------------------------+ -| $`\bar{y}` `\bar{y}` | $`\overline{AB}` | $`\Overrightarrow{AB}` | -| | `\overline{AB}` | `\Overrightarrow{AB}` | -+--------------------------+--------------------------+------------------------------------+ -| $`\breve{a}` `\breve{a}` | $`\underline{AB}` | $`\overleftrightarrow{AB}` | -| | `\underline{AB}` | `\overleftrightarrow{AB}` | -+--------------------------+--------------------------+------------------------------------+ -| $`\check{a}` `\check{a}` | $`\widecheck{ac}` | $`\underleftrightarrow{AB}` | -| | `\widecheck{ac}` | `\underleftrightarrow{AB}` | -+--------------------------+--------------------------+------------------------------------+ -| $`\dot{a}` `\dot{a}` | $`\overleftharpoon{ac}` | $`\overrightharpoon{ac}` | -| | `\overleftharpoon{ac}` | `\overrightharpoon{ac}` | -+--------------------------+--------------------------+------------------------------------+ -| $`\ddot{a}` `\ddot{a}` | $`\overgroup{AB}` | $`\wideparen{AB}` | -| | `\overgroup{AB}` | `\wideparen{AB}` | -+--------------------------+--------------------------+------------------------------------+ -| $`\dddot{a}` `\dddot{a}` | $`\undergroup{AB}` | $`\overparen{AB}` | -| | `\undergroup{AB}` | `\overparen{AB}` | -+--------------------------+--------------------------+------------------------------------+ -| $`\ddddot{a}` | $`\underbar{X}` | $`\underparen{AB}` | -| `\ddddot{a}` | `\underbar{X}` | `\underparen{AB}` | -+--------------------------+--------------------------+------------------------------------+ -| $`\grave{a}` `\grave{a}` | $`\mathring{g}` | $`\overbrace{AB}` | -| | `\mathring{g}` | `\overbrace{AB}` | -+--------------------------+--------------------------+------------------------------------+ -| $`\hat{\theta}` | $`\widehat{ac}` | $`\underbrace{AB}` | -| `\hat{\theta}` | `\widehat{ac}` | `\underbrace{AB}` | -+--------------------------+--------------------------+------------------------------------+ - - -**Accent functions inside \\text{…}** - -+:------------------+:------------------+:-----------------+:----------------+ -| $`\text{\'{a}}` | $`\text{\~{a}}` | $`\text{\.{a}}` | $`\text{\H{a}}` | -| `\'{a}` | `\~{a}` | `\.{a}` | `\H{a}` | -+-------------------+-------------------+------------------+-----------------+ -| $``\text{\`{a}}`` | $`\text{\={a}}` | $`\text{\"{a}}` | $`\text{\v{a}}` | -| ``\`{a}`` | `\={a}` | `\"{a}` | `\v{a}` | -+-------------------+-------------------+------------------+-----------------+ -| $`\text{\^{a}}` | $`\text{\u{a}}` | $`\text{\r{a}}` | $`\text{\c{c}}` | -| `\^{a}` | `\u{a}` | `\r{a}` | `\c{c}` | -+-------------------+-------------------+------------------+-----------------+ - -See also [letters](#letters) - -## Annotation - -+:---------------------------------+:---------------------------------------------------+ -| $`\cancel{5}` `\cancel{5}` | $`\overbrace{a+b+c}^{\text{note}}` | -| | `\overbrace{a+b+c}^{\text{note}}` | -+----------------------------------+----------------------------------------------------+ -| $`\bcancel{5}` `\bcancel{5}` | $`\underbrace{a+b+c}_{\text{note}}` | -| | `\underbrace{a+b+c}_{\text{note}}` | -+----------------------------------+----------------------------------------------------+ -| $`\xcancel{ABC}` `\xcancel{ABC}` | $`\cancelto{0}{x+1}` | -| | `\cancelto{0}{x+1}` | -+----------------------------------+----------------------------------------------------+ -| $`\sout{abc}` `\sout{abc}` | $`\boxed{\pi=\frac c d}` | -| | `\boxed{\pi=\frac c d}` | -+----------------------------------+----------------------------------------------------+ -| $`\ref{tag1}` `\ref{tag1}` | $`\texttip{\text{hover here}}{This is a tooltip.}` | -| |`\texttip{\text{hover here}}{This is a tooltip.}` | -+----------------------------------+----------------------------------------------------+ -| | $`\toggle{\text{Click me}}{Hey!}{Ow!}\endtoggle` | -| | `\toggle{\text{Click me}}{Hey!}{Ow!}\endtoggle` | -+----------------------------------+----------------------------------------------------+ -| $$ | `\tag{hi} x+y^{2x} \label{tag1}` | -| \tag{hi} x+y^{2x} \label{tag1} | | -| $$ | | -+----------------------------------+----------------------------------------------------+ -| $$ | `\tag*{bye} x+y^{2x}` | -| \tag*{bye} x+y^{2x} | | -| $$ | | -+----------------------------------+----------------------------------------------------+ - -Also some [environments](#environments) have automatic equation numbering. - -A `\label{…}` may be placed anywhere and will create an HTML id matching the -`\label{…}` argument. That argument may contain only the characters `A-Za-z0-9_-`. - -On sites where Temml fields are updated dynamically, `\ref{…}` may not be -supported. Other Temml functions update only the local field. `\ref{…}` must -make two passes through the entire document. Some sites may choose not to do this. - -## Color - -+------------------------------+---------------------------------------------+ -| $`\color{blue} F=ma` | $`\color[RGB]{255,0,255} F=ma` | -| `{\color{blue} F=ma}` | `{\color[RGB]{255,0,255} F=ma}` | -+------------------------------+---------------------------------------------+ -| $`\textcolor{blue}{F=ma}` | $`\color[rgb]{1,0,1} F=ma` | -| `\textcolor{blue}{F=ma}` | `{\color[rgb]{1,0,1} F=ma}` | -+------------------------------+---------------------------------------------+ -| $`\textcolor{#228B22}{F=ma}` | $`\color[HTML]{ff00ff} F=ma` | -| `\textcolor{#228B22}{F=ma}` | `{\color[HTML]{ff00ff} F=ma}` | -+------------------------------+---------------------------------------------+ -| $`\colorbox{aqua}{A}` | `\definecolor{sortaGreen}{RGB}{128,128,0}`\ | -| `\colorbox{aqua}{A}` | $`\definecolor{sortaGreen}{RGB}{128,128,0} | -+------------------------------+ \color{sortaGreen} F=ma` + -| $`\fcolorbox{red}{aqua}{A}` | `{\color{sortaGreen} F=ma}` | -| `\fcolorbox{red}{aqua}{A}` | | -+------------------------------+---------------------------------------------+ - -`\definecolor` functions can be included in a [preamble](administration.html#preamble). -If so, their color definitions will have document-wide scope. - -Color functions can all take an optional argument to set the color model, as -in the `xcolor` package. (Exception: `\definecolor`’s model argument is -required.) Temml supports color models `HTML`, `RGB`, and `rgb`. - -If the color model is omitted, Temml color functions will accept: - -- `#rrggbb`, `#rgb`, or `rrggbb`. -- A color name previously created by `\definecolor`. -- Any color from the following `xcolor` table. -- Any of the standard HTML [predefined color names](https://www.w3schools.com/colors/colors_names.asp). - -
- -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{Apricot}\rule{1em}{0.8em}} `  Apricot | $` {\color{ForestGreen}\rule{1em}{0.8em}} `  ForestGreen | $` {\color{olive}\rule{1em}{0.8em}} `  olive | $` {\color{RoyalPurple}\rule{1em}{0.8em}} `  RoyalPurple | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{Aquamarine}\rule{1em}{0.8em}} `  Aquamarine | $` {\color{Fuchsia}\rule{1em}{0.8em}} `  Fuchsia | $` {\color{OliveGreen}\rule{1em}{0.8em}} `  OliveGreen | $` {\color{RubineRed}\rule{1em}{0.8em}} `  RubineRed | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{Bittersweet}\rule{1em}{0.8em}} `  Bittersweet | $` {\color{Goldenrod}\rule{1em}{0.8em}} `  Goldenrod | $` {\color{orange}\rule{1em}{0.8em}} `  orange | $` {\color{Salmon}\rule{1em}{0.8em}} `  Salmon | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{blue}\rule{1em}{0.8em}} `  blue | $` {\color{gray}\rule{1em}{0.8em}} `  gray | $` {\color{Orange}\rule{1em}{0.8em}} `  Orange | $` {\color{SeaGreen}\rule{1em}{0.8em}} `  SeaGreen | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{Blue}\rule{1em}{0.8em}} `  Blue | $` {\color{Gray}\rule{1em}{0.8em}} `  Gray | $` {\color{OrangeRed}\rule{1em}{0.8em}} `  OrangeRed | $` {\color{Sepia}\rule{1em}{0.8em}} `  Sepia | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{BlueGreen}\rule{1em}{0.8em}} `  BlueGreen | $` {\color{green}\rule{1em}{0.8em}} `  green | $` {\color{Orchid}\rule{1em}{0.8em}} `  Orchid | $` {\color{SkyBlue}\rule{1em}{0.8em}} `  SkyBlue | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{BlueViolet}\rule{1em}{0.8em}} `  BlueViolet | $` {\color{Green}\rule{1em}{0.8em}} `  Green | $` {\color{Peach}\rule{1em}{0.8em}} `  Peach | $` {\color{SpringGreen}\rule{1em}{0.8em}} `  SpringGreen | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{BrickRed}\rule{1em}{0.8em}} `  BrickRed | $` {\color{GreenYellow}\rule{1em}{0.8em}} `  GreenYellow | $` {\color{Periwinkle}\rule{1em}{0.8em}} `  Periwinkle | $` {\color{Tan}\rule{1em}{0.8em}} `  Tan | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{brown}\rule{1em}{0.8em}} `  brown | $` {\color{JungleGreen}\rule{1em}{0.8em}} `  JungleGreen | $` {\color{PineGreen}\rule{1em}{0.8em}} `  PineGreen | $` {\color{teal}\rule{1em}{0.8em}} `  teal | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{Brown}\rule{1em}{0.8em}} `  Brown | $` {\color{Lavender}\rule{1em}{0.8em}} `  Lavender | $` {\color{pink}\rule{1em}{0.8em}} `  pink | $` {\color{TealBlue}\rule{1em}{0.8em}} `  TealBlue | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{BurntOrange}\rule{1em}{0.8em}} `  BurntOrange | $` {\color{lightgray}\rule{1em}{0.8em}} `  lightgray | $` {\color{Plum}\rule{1em}{0.8em}} `  Plum | $` {\color{Thistle}\rule{1em}{0.8em}} `  Thistle | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{CadetBlue}\rule{1em}{0.8em}} `  CadetBlue | $` {\color{lime}\rule{1em}{0.8em}} `  lime | $` {\color{ProcessBlue}\rule{1em}{0.8em}} `  ProcessBlue | $` {\color{Turquoise}\rule{1em}{0.8em}} `  Turquoise | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{CarnationPink}\rule{1em}{0.8em}} `  CarnationPink | $` {\color{LimeGreen}\rule{1em}{0.8em}} `  LimeGreen | $` {\color{purple}\rule{1em}{0.8em}} `  purple | $` {\color{violet}\rule{1em}{0.8em}} `  violet | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{Cerulean}\rule{1em}{0.8em}} `  Cerulean | $` {\color{magenta}\rule{1em}{0.8em}} `  magenta | $` {\color{Purple}\rule{1em}{0.8em}} `  Purple | $` {\color{Violet}\rule{1em}{0.8em}} `  Violet | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{CornflowerBlue}\rule{1em}{0.8em}} `  CornflowerBlue | $` {\color{Magenta}\rule{1em}{0.8em}} `  Magenta | $` {\color{RawSienna}\rule{1em}{0.8em}} `  RawSienna | $` {\color{VioletRed}\rule{1em}{0.8em}} `  VioletRed | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{cyan}\rule{1em}{0.8em}} `  cyan | $` {\color{Mahogany}\rule{1em}{0.8em}} `  Mahogany | $` {\color{red}\rule{1em}{0.8em}} `  red | $` {\color{WildStrawberry}\rule{1em}{0.8em}} `  WildStrawberry | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{Cyan}\rule{1em}{0.8em}} `  Cyan | $` {\color{Maroon}\rule{1em}{0.8em}} `  Maroon | $` {\color{Red}\rule{1em}{0.8em}} `  Red | $` {\color{yellow}\rule{1em}{0.8em}} `  yellow | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{Dandelion}\rule{1em}{0.8em}} `  Dandelion | $` {\color{Melon}\rule{1em}{0.8em}} `  Melon | $` {\color{RedOrange}\rule{1em}{0.8em}} `  RedOrange | $` {\color{Yellow}\rule{1em}{0.8em}} `  Yellow | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{darkgray}\rule{1em}{0.8em}} `  darkgray | $` {\color{MidnightBlue}\rule{1em}{0.8em}} `  MidnightBlue | $` {\color{RedViolet}\rule{1em}{0.8em}} `  RedViolet | $` {\color{YellowGreen}\rule{1em}{0.8em}} `  YellowGreen | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{DarkOrchid}\rule{1em}{0.8em}} `  DarkOrchid | $` {\color{Mulberry}\rule{1em}{0.8em}} `  Mulberry | $` {\color{Rhodamine}\rule{1em}{0.8em}} `  Rhodamine | $` {\color{YellowOrange}\rule{1em}{0.8em}} `  YellowOrange | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ -| $` {\color{Emerald}\rule{1em}{0.8em}} `  Emerald | $` {\color{NavyBlue}\rule{1em}{0.8em}} `  NavyBlue | $` {\color{RoyalBlue}\rule{1em}{0.8em}} `  RoyalBlue | | -+----------------------------------------------------------------+------------------------------------------------------------+----------------------------------------------------------+----------------------------------------------------------------+ - - -## Delimiters - -+:-----------------+:-------------------+:-------------+:---------------------------+:--------------------+ -| $`(~)` `( )` | $`\lparen~\rparen` | $`⌈~⌉` `⌈ ⌉` | $`\lceil~\rceil` | $`\uparrow` | -| | `\lparen`\ | | `\lceil`\ | `\uparrow` | -| | $`~~~~` `\rparen` | | $`~~~~~` `\rceil` | | -+------------------+--------------------+--------------+----------------------------+---------------------+ -| $`[~]` `[ ]` | $`\lbrack~\rbrack` | $`⌊~⌋` `⌊ ⌋` | $`\lfloor~\rfloor` | $`\downarrow` | -| | `\lbrack`\ | | `\lfloor`\ | `\downarrow` | -| | $`~~~~` `\rbrack` | | $`~~~~~` `\rfloor` | | -+------------------+--------------------+--------------+----------------------------+---------------------+ -| $`\{ \}` | $`\lbrace \rbrace` | $`⎰⎱` `⎰⎱` | $`\lmoustache \rmoustache` | $`\updownarrow` | -| `\{ \}` | `\lbrace`\ | | `\lmoustache`\ | `\updownarrow` | -| | $`~~~~` `\rbrace` | | $`~~~~` `\rmoustache` | | -+------------------+--------------------+--------------+----------------------------+---------------------+ -| $`⟨~⟩` `⟨ ⟩` | $`\langle~\rangle` | $`⟮~⟯` `⟮ ⟯` | $`\lgroup~\rgroup` | $`\Uparrow` | -| | `\langle` \ | | `\lgroup`\ | `\Uparrow` | -| | $`~~~~~` `\rangle` | | $`~~~~~` `\rgroup` | | -+------------------+--------------------+--------------+----------------------------+---------------------+ -| $`\vert` | $`\vert` | $`┌ ┐` `┌ ┐` | $`\ulcorner \urcorner` | $`\Downarrow` | -| `|` | `\vert` | | `\ulcorner`\ | `\Downarrow` | -| | | | $`~~~~` `\urcorner` | | -+------------------+--------------------+--------------+----------------------------+---------------------+ -| $`\Vert` | $`\Vert` `\Vert` | $`└ ┘` `└ ┘` | $`\llcorner \lrcorner` | $`\Updownarrow` | -| `\|` | | | `\llcorner`\ | `\Updownarrow` | -| | | | $`~~~~` `\lrcorner` | | -+------------------+--------------------+--------------+----------------------------+---------------------+ -| $`\lvert~\rvert` | $`\lVert~\rVert` | `\left.` | `\right.` | $`\backslash` | -| `\lvert`\ | `\lVert`\ | | | `\backslash` | -| $`~~~~` `\rvert` | $`~~~~~` `\rVert` | | | | -+------------------+--------------------+--------------+----------------------------+---------------------+ -| | $`\lt\gt` `\lt`\ | $`⟦~⟧` `⟦ ⟧` | $`\llbracket~\rrbracket` | $`\lBrace~\rBrace` | -| | $`~~~~~~~~~~` | | `\llbracket`\ | `\lBrace \rBrace` | -| | `\gt` | | $`~~~~` `\rrbracket` | | -+------------------+--------------------+--------------+----------------------------+---------------------+ - -The _texvc_ extension includes $`\lang` `\lang` and $`\rang` `\rang`. - -#### Delimiter Sizing - -$`\left(\LARGE{AB}\right)` `\left(\LARGE{AB}\right)` - -$`( \big( \Big( \bigg( \Bigg(` `( \big( \Big( \bigg( \Bigg(` - -+:----------+:--------+:---------+:---------+:---------+ -| `\left` | `\big` | `\bigl` | `\bigm` | `\bigr` | -+-----------+---------+----------+----------+----------+ -| `\middle` | `\Big` | `\Bigl` | `\Bigm` | `\Bigr` | -+-----------+---------+----------+----------+----------+ -| `\right` | `\bigg` | `\biggl` | `\biggm` | `\biggr` | -+-----------+---------+----------+----------+----------+ -| | `\Bigg` | `\Biggl` | `\Biggm` | `\Biggr` | -+-----------+---------+----------+----------+----------+ - -## Environments - -+:---------------------:+:---------------------------+:--------------------------:+:-----------------------------+ -| $`\begin{matrix} | `\begin{matrix}`\ | $`\begin{array}{cc} | `\begin{array}{cc}`\ | -| a & b \\ |    `a & b \\`\ |    a & b \\ |    `a & b \\`\ | -| c & d |    `c & d`\ |    c & d |    `c & d`\ | -| \end{matrix}` | `\end{matrix}` | \end{array}` | `\end{array}` | -+-----------------------+---------------------------+----------------------------+------------------------------+ -| $`\begin{pmatrix} | `\begin{pmatrix}`\ | $`\begin{bmatrix} | `\begin{bmatrix}`\ | -| a & b \\ |    `a & b \\`\ | a & b \\ |    `a & b \\`\ | -| c & d |    `c & d`\ | c & d |    `c & d`\ | -| \end{pmatrix}` | `\end{pmatrix}` | \end{bmatrix}` | `\end{matrix}` | -+-----------------------+----------------------------+----------------------------+------------------------------+ -| $`\begin{vmatrix} | `\begin{vmatrix}`\ | $`\begin{Vmatrix} | `\begin{Vmatrix}`\ | -| a & b \\ |    `a & b \\`\ | a & b \\ |    `a & b \\`\ | -| c & d |    `c & d`\ | c & d |    `c & d`\ | -| \end{vmatrix}` | `\end{vmatrix}` | \end{Vmatrix}` | `\end{Vmatrix}` | -+-----------------------+----------------------------+----------------------------+------------------------------+ -| $`\begin{Bmatrix} | `\begin{Bmatrix}`\ | $`\def\arraystretch{1.5} | `\def\arraystretch{1.5}`\ | -| a & b \\ |    `a & b \\`\ | \begin{array}{c|c:c} | `\begin{array}{c|c:c}`\ | -| c & d |    `c & d`\ | a & b & c \\ \hline |    `a & b & c \\ \hline`\ | -| \end{Bmatrix}` | `\end{Bmatrix}` | d & e & f \\ \hdashline |    `d & e & f \\`\ | -| | | g & h & i |    `\hdashline`\ | -| | | \end{array}` |    `g & h & i`\ | -| | | | `\end{array}` | -+-----------------------+----------------------------+----------------------------+------------------------------+ -| $`x = \begin{cases} | `x = \begin{cases}`\ | $`\begin{rcases} | `\begin{rcases}`\ | -| a &\text{if } b \\ |    `a &\text{if } b \\`\ | a &\text{if } b \\ |    `a &\text{if } b \\`\ | -| c &\text{if } d |    `c &\text{if } d`\ | c &\text{if } d |   `c &\text{if } d`\ | -| \end{cases}` | `\end{cases}` | \end{rcases}⇒` | `\end{rcases}⇒` | -+-----------------------+----------------------------+----------------------------+------------------------------+ -| $`\begin{smallmatrix} | `\begin{smallmatrix}`\ | $$ | `\sum_{\begin{subarray}{l}`\ | -| a & b \\ |    `a & b \\`\ | \sum_{\begin{subarray}{l} |    `i\in\Lambda\\`\ | -| c & d |    `c & d`\ | i\in\Lambda\\ |    `0 - -+:-----------------+:-----------------------+:-------------------+:--------------------------+ -| $$ | `\begin{equation}`\ | $$ | `\begin{align}`\ | -| \begin{equation} | `\begin{split}`\ | \begin{align} |    `a&=b+c \\`\ | -| \begin{split} |    `a &=b+c\\`\ | a&=b+c \\ |    `d+e&=f`\ | -| a &=b+c\\ |    `&=e+f`\ | d+e&=f | `\endalign` | -| &=e+f | `\end{split}`\ | \end{align} | | -| \end{split} | `\end{equation}` | $$ | | -| \end{equation} | | | | -| $$ | | | | -+------------------+------------------------+--------------------+---------------------------+ -| $$ | `\begin{gather}`\ | $$ | `\begin{alignat}{2}`\ | -| \begin{gather} |    `a=b \\`\ | \begin{alignat}{2} |    `10&x+ &3&y = 2 \\`\ | -| a=b \\ |    `e=b+c`\ | 10&x+ &3&y = 2 \\ |    `3&x+&13&y = 4`\ | -| e=b+c | `\end{gather}` | 3&x+&13&y = 4 | `\end{alignat}` | -| \end{gather} | | \end{alignat} | | -| $$ | | $$ | | -+------------------+------------------------+--------------------+---------------------------+ -| $$ | `\begin{CD}`\ | $$ | `\begin{multline}`\ | -| \begin{CD} | `A @>a>> B \\`\ | \begin{multline} |    `\rm uno \\`\ | -| A @>a>> B \\ | `@VbVV @AAcA \\`\ | \rm uno \\ \    `\rm dos \\`\ | -| @VbVV @AAcA\\ | `C @= D`\ | \rm dos \\ |    `\rm tres`\ | -| C @= D | `\end{CD}` | \rm tres | `\end{multline}` | -| \end{CD} | | \end{multline} | | -| $$ | | $$ | | -+------------------+------------------------+--------------------+---------------------------+ - -#### Other Temml Environments - -+:------------------------------------+:----------------------------------------------+ -| Environments | How they differ from those shown above | -+=====================================+===============================================+ -| `darray`, `dcases`, `drcases` | … apply `displaystyle` | -+-------------------------------------+-----------------------------------------------+ -| `matrix*`, `pmatrix*`, `bmatrix*`\ | … take an optional argument that sets column\ | -| `Bmatrix*`, `vmatrix*`, `Vmatrix*` | alignment, as in `\begin{matrix*}[r]` | -+-------------------------------------+-----------------------------------------------+ -| `equation*`, `gather*`\ | … have no automatic numbering. | -| `align*`, `alignat*` | | -+-------------------------------------+-----------------------------------------------+ -| `gathered`, `aligned`, `alignedat` | … do not need to be in display mode.\ | -| | … have no automatic numbering.\ | -| | … must be inside math delimiters in\ | -| | order to be rendered by the auto-render\ | -| | extension. | -+-------------------------------------+-----------------------------------------------+ - -Acceptable horizontal line separators are: `\\` and `\cr`. - -Temml supports `\tag{…}`, `\notag`, and `\nonumber` to modify equation numbering. - -The `{array}` environment does not yet support `\cline` or `\multicolumn`. - -## HTML - -The following "raw HTML" features are potentially dangerous for untrusted -inputs, so they are disabled by default, and attempting to use them produces -the command names in red (which you can configure via the `errorColor` -[option](administration.html#options)). To fully trust your LaTeX input, you need to pass -an option of `trust: true`; you can also enable just some of the commands -or for just some URLs via the `trust` [option](administration.html#options). - -+:-------------------------------------+:-----------------------------------------------+ -| $`\href{https://temml.org/}{\Temml}` | `\href{https://temml.org/}{\Temml}` | -+--------------------------------------+------------------------------------------------+ -| $`\url{https://temml.org/}` | `\url{https://temml.org/}` | -+--------------------------------------+------------------------------------------------+ -| $`\includegraphics[height=1em, | `\includegraphics[height=1em,`\ | -| totalheight=1.2em, width=1.2em, | `totalheight=1.2em,width=1.2em, alt=sphere]`\ | -| alt=sphere]{../sphere.jpg}` | `{../sphere.jpg}` | -+--------------------------------------+------------------------------------------------+ -| $`\id{idName}{x}` | `\id{idName}{x}` | -+--------------------------------------+------------------------------------------------+ -| $`\class{class-name}{x}` | `\class{class-name}{x}` | -+--------------------------------------+------------------------------------------------+ -| $`\style{color: red;}{x}` | `\style{color: red;}{x}` | -+--------------------------------------+------------------------------------------------+ -| $`\data{datum1=a, datum2=b}{x}` | `\data{datum1=a, datum2=b}{x}` | -+--------------------------------------+------------------------------------------------+ - -## Letters - -**Greek Letters** - -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\Alpha` `\Alpha` | $`\Beta` `\Beta` | $`\Gamma` `\Gamma` | $`\Delta` `\Delta` | $`\Epsilon` `\Epsilon` | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\Zeta` `\Zeta` | $`\Eta` `\Eta` | $`\Theta` `\Theta` | $`\Iota` `\Iota` | $`\Kappa` `\Kappa` | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\Lambda` | $`\Mu` `\Mu` | $`\Nu` `\Nu` | $`\Xi` `\Xi` | $`\Omicron` `\Omicron` | -| `\Lambda` | | | | | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\Pi` `\Pi` | $`\Rho` `\Rho` | $`\Sigma` `\Sigma` | $`\Tau` `\Tau` | $`\Upsilon` `\Upsilon` | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\Phi` `\Phi` | $`\Chi` `\Chi` | $`\Psi` `\Psi` | $`\Omega` `\Omega` | $`\varGamma` `\varGamma` | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\varDelta` | $`\varTheta` | $`\varLambda` | $`\varXi` `\varXi` | $`\varPi` `\varPi` | -| `\varDelta` | `\varTheta` | `\varLambda` | | | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\varSigma` | $`\varUpsilon` | $`\varPhi` | $`\varPsi` | $`\varOmega` `\varOmega` | -| `\varSigma` | `\varUpsilon` | `\varPhi` | `\varPsi` | | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\alpha` `\alpha` | $`\beta` `\beta` | $`\gamma` `\gamma` | $`\delta` `\delta` | $`\epsilon` `\epsilon` | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\zeta` `\zeta` | $`\eta` `\eta` | $`\theta` `\theta` | $`\iota` `\iota` | $`\kappa` `\kappa` | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\lambda` | $`\mu` `\mu` | $`\nu` `\nu` | $`\xi` `\xi` | $`\omicron` `\omicron` | -|`\lambda` | | | | | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\pi` `\pi` | $`\rho` `\rho` | $`\sigma` `\sigma` | $`\tau` `\tau` | $`\upsilon` `\upsilon` | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\phi` `\phi` | $`\chi` `\chi` | $`\psi` `\psi` | $`\omega` `\omega` | | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\upalpha` | $`\upbeta` | $`\upgamma` | $`\updelta` | $`\upepsilon` | -| `\upalpha` | `\upbeta` | `\upgamma` | `\updelta` | `\upepsilon` | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\upzeta` | $`\upeta` | $`\uptheta` | $`\upiota` | $`\upkappa` `\upkappa` | -| `\upzeta` | `\upeta` | `\uptheta` | `\upiota` | | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\uplambda` | $`\upmu` `\upmu` | $`\upnu` `\upnu` | $`\upxi` `\upxi` | $`\upomicron` | -| `\uplambda` | | | | `\upomicron` | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\uppi` `\uppi` | $`\uprho` | $`\upsigma` | $`\uptau` `\uptau` | $`\upupsilon` | -| | `\uprho` | `\upsigma` | | `\upupsilon` | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\upphi` `\upphi` | $`\upchi` | $`\uppsi` `\uppsi` | $`\upomega` | | -| | `\upchi` | | `\upomega` | | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\varepsilon` | $`\varkappa` | $`\vartheta` | $`\varpi` `\varpi` | $`\varrho` `\varrho` | -| `\varepsilon` | `\varkappa` | `\vartheta` | | | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\varsigma` | $`\varphi` | $`\Coppa` `\Coppa` | $`\coppa` `\coppa` | $`\Koppa` `\Koppa` | -| `\varsigma` | `\varphi` | | | | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\koppa` `\koppa` | $`\Sampi` | $`\sampi` `\sampi` | $`\Stigma` | $`\stigma` `\stigma` | -| | `\Sampi` | | `\Stigma` | | -+--------------------+------------------+--------------------+--------------------+--------------------------+ -| $`\digamma` | $`\varcoppa` | | | | -| `\digamma` | `\varcoppa` | | | | -+--------------------+------------------+--------------------+--------------------+--------------------------+ - -Direct Input: Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ Φ Χ Ψ Ω - α β γ δ ϵ ζ η θ ι κ λ μ ν ξ o π ρ σ τ υ ϕ χ ψ ω ε ϑ ϖ ϱ ς φ ϝ - -#### Other Letters - -+:---------------------+:-------------------+:-------------------+:---------------------------+:---------------------------+ -| $`\aleph` `\aleph` | $`\nabla` `\nabla` | $`\imath` `\imath` | $`\text{\aa}` `\text{\aa}` | $`\text{\OE}` `\text{\OE}` | -+----------------------+--------------------+--------------------+----------------------------+----------------------------+ -| $`\beth` `\beth` | $`\partial` | $`\jmath` `\jmath` | $`\text{\AA}` `\text{\AA}` | $`\text{\o}` `\text{\o}` | -| | `\partial` | | | | -+----------------------+--------------------+--------------------+----------------------------+----------------------------+ -| $`\gimel` `\gimel` | $`\Game` `\Game` | $`\Im` `\Im` | $`\text{\ae}` `\text{\ae}` | $`\text{\O}` `\text{\O}` | -+----------------------+--------------------+--------------------+----------------------------+----------------------------+ -| $`\daleth` `\daleth` | $`\Finv` `\Finv` | $`\Bbbk` `\Bbbk` | $`\text{\AE}` `\text{\AE}` | $`\text{\ss}` `\text{\ss}` | -+----------------------+--------------------+--------------------+----------------------------+----------------------------+ -| $`\eth` `\eth` | $`\hbar` `\hbar` | $`\Re` `\Re` | $`\text{\oe}` `\text{\oe}` | $`\text{\i}` `\text{\i}` | -+----------------------+--------------------+--------------------+----------------------------+----------------------------+ -| $`\ell` `\ell` | $`\hslash` | $`\wp` `\wp` | | $`\text{\j}` `\text{\j}` | -| | `\hslash` | | | | -+----------------------+--------------------+--------------------+----------------------------+----------------------------+ - -Letters in the _texvc_ extension - -+:-----------------------+:-----------------------+:-----------------------+:-------------------+:-------------------------+ -| $`\alef` `\alef` | $`\Complex` `\Complex` | $`\natnums` `\natnums` | $`\real` `\real` | $`\weierp` `\weierp` | -+------------------------+------------------------+------------------------+--------------------+--------------------------+ -| $`\alefsym` `\alefsym` | $`\image` `\image` | $`\R` `\R` | $`\reals` `\reals` | $`\thetasym` `\thetasym` | -+------------------------+------------------------+------------------------+--------------------+--------------------------+ -| $`\cnums` `\cnums` | $`\N` `\N` | $`\Reals` `\Reals` | | $`\Z` `\Z` | -+------------------------+------------------------+------------------------+--------------------+--------------------------+ - -Direct Input: ∂ ∇ ℑ Ⅎ ℵ ℶ ℷ ℸ ⅁ ℏ ð À Á Â Ã Ä Å Æ Ç È É Ê Ë -Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö Ù Ú Û Ü Ý Þ ß à á â ã ä å ç è é ê ë ì í î ï ð ñ ò ó ô ö ù ú û ü ý þ ÿ - ₊ ₋ ₌ ₍ ₎ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉ ₐ ₑ ₕ ᵢ ⱼ ₖ ₗ ₘ ₙ ₒ ₚ ᵣ ₛ ₜ ᵤ ᵥ ₓ ᵦ ᵧ ᵨ ᵩ ᵪ ⁺ ⁻ ⁼ ⁽ ⁾ ⁰ ¹ ² ³ ⁴ ⁵ ⁶ ⁷ ⁸ ⁹ ᵃ ᵇ ᶜ ᵈ ᵉ ᵍ ʰ ⁱ ʲ ᵏ ˡ ᵐ ⁿ ᵒ ᵖ ʳ ˢ ᵗ ᵘ ʷ ˣ ʸ ᶻ ᵛ ᵝ ᵞ ᵟ ᵠ ᵡ - -Math-mode Unicode (sub|super)script characters will render as if you had written regular -characters in a subscript or superscript. For instance, `A²⁺³` will render the same -as `A^{2+3}`. - -#### Unicode Mathematical Alphanumeric Symbols - -| Item | Range | Item | Range | -|--------------|-----------------------|-------------------|-------------------------| -| Bold | $`\text{𝐀-𝐙 𝐚-𝐳 𝟎-𝟗}` | Double-struck | $`\text{𝔸-ℤ 𝕒-𝕫 𝟘-𝟡}` | -| Italic | $`\text{𝐴-𝑍 𝑎-𝑧}` | Sans serif | $`\text{𝖠-𝖹 𝖺-𝗓 𝟢-𝟫}` | -| Bold Italic | $`\text{𝑨-𝒁 𝒂-𝒛}` | Sans serif bold | $`\text{𝗔-𝗭 𝗮-𝘇 𝟬-𝟵}` | -| Fractur | $`\text{𝔄-ℨ}\text{𝔞-𝔷}`| Sans serif italic | $`\text{𝘈-𝘡 𝘢-𝘻}` | -| Monospace | $`\text{𝙰-𝚉 𝚊-𝚣 𝟶-𝟿}` | Sans serif bold italic | $`\text{𝘼-𝙕 𝙖-𝙯}` | - -Any character can be written with the `\char` function and the Unicode code in hex. For example `\char"263a` will render as $`\char"263a`. - -
- -
For chancery or roundhand characters, it’s probably best to use \mathcal and \mathscr instead of Unicode input.
Why? -

Unicode has historically accepted either chancery or roundhand glyphs in the range U+1D49C—U+1D4B5. That's confusing, -because Cambria Math has chancery in those code points and some other math fonts have roundhand in the same code points. -Unicode 14 has recently added code points that resolve the ambiguity. Both chancery and roundhand still occupy the same range, but each unambigous chancery character has a \ufe00 appended to the code point and each unambigous roundhand character has a \ufe01 appended to the code point.

-

Published fonts have not yet caught up to the new code point assignments. If you want your documents to not break in the future, it’s probably best to avoid Unicode input and stick with \mathcal and \mathscr.

-
-
- -## Layout - -### Line Breaks - -Hard line breaks are `\\` and `\newline`. - -If the rendering options do not include annotations, Hurmet will write MathML -with soft line breaks after relations and binary operators. These soft line -breaks will appear only in Firefox. Chromium and Safari do not support soft -line breaks. - -### Vertical Layout - -+:---------------+:-------------------------------------+:---------------------------------------------------+ -| $`x_n` `x_n` | $`\stackrel{!}{=}` `\stackrel{!}{=}` | $`a\raisebox{0.25em}{b}c` `a\raisebox{0.25em}{b}c` | -+----------------+--------------------------------------+----------------------------------------------------+ -| $`e^x` `e^x` | $`\overset{!}{=}` `\overset{!}{=}` | $`M\raise3pt{M^2}M` `M\raise3pt{M^2}M` | -+----------------+--------------------------------------+----------------------------------------------------+ -| $`_u^o` `_u^o` | $`\underset{!}{=}` `\underset{!}{=}` | $`M\lower3pt{M^2}M` `M\lower3pt{M^2}M` | -+----------------+--------------------------------------+----------------------------------------------------+ -| | $`a \atop b` `a \atop b` | | -+----------------+--------------------------------------+----------------------------------------------------+ - -+:-------------------------------+:---------------------------------+ -| $$ | `\sum_{\substack{0` | ⁴∕₁₈ em space | `\mskip{distance}` | space, width = _distance_ | -| `\:` | ⁴∕₁₈ em space | `\hskip{distance}` | space, width = _distance_ | -| `\medspace` | ⁴∕₁₈ em space | `\hspace{distance}` | space, width = _distance_ | -| `\;` | ⁵∕₁₈ em space | `\hspace*{distance}` | space, width = _distance_ | -| `\thickspace` | ⁵∕₁₈ em space | `\phantom{content}` | space the width and height of content | -| `\enspace` | ½ em space | `\hphantom{content}` | space the width of content | -| `\quad` | 1 em space | `\vphantom{content}` | a strut the height of content | -| `\qquad` | 2 em space | `\!` | – ³∕₁₈ em space | -| `~` | non-breaking space | `\negthinspace` | – ³∕₁₈ em space | -| `\` | space | `\negmedspace` | – ⁴∕₁₈ em space | -| `\nobreakspace` | non-breaking space | `\negthickspace` | – ⁵∕₁₈ em space | -| `\space` | space | | | - -**Notes:** - -`distance` will accept any of the [Temml units](#units). - -`\kern`, `\mkern`, `\mskip`, and `\hskip` accept unbraced distances, as in: `\kern1em`. - -`\mkern` and `\mskip` will not work in text mode and both will write a console warning for any unit except `mu`. - -`\rule{}{distance}` is valuable as a vertical strut. - -## Logic and Set Theory - -+:-----------------------+:---------------------+:----------------------------+:-----------------------------+ -| $`\forall` `\forall` | $`\complement` | $`\therefore` | $`\emptyset` `\emptyset` | -| | `\complement` | `\therefore` | | -+------------------------+----------------------+-----------------------------+------------------------------+ -| $`\exists` `\exists` | $`\subset` `\subset` | $`\because` `\because` | $`\varnothing` `\varnothing` | -+------------------------+----------------------+-----------------------------+------------------------------+ -| $`\nexists` `\nexists` | $`\supset` `\supset` | $`\mapsto` `\mapsto` | $`\implies` `\implies` | -+------------------------+----------------------+-----------------------------+------------------------------+ -| $`\in` `\in` | $`\mid` `\mid` | $`\to` `\to` | $`\impliedby` `\impliedby` | -+------------------------+----------------------+-----------------------------+------------------------------+ -| $`\ni` `\ni` | $`\land` `\land` | $`\gets` `\gets` | $`\iff` `\iff` | -+------------------------+----------------------+-----------------------------+------------------------------+ -| $`\notin` `\notin` | $`\lor` `\lor` | $`\leftrightarrow` | $`\lightning` `\lightning` | -| | | `\leftrightarrow` | | -+------------------------+----------------------+-----------------------------+------------------------------+ -| $`\notni` `\notni` | $`\neg` `\neg` | $`\Set{ x | x<\frac 1 2 }`\ | $`\set{x|x<5 }`\ | -| | or `\lnot` | `\Set{ x | x<\frac 1 2 }` | `\set{x|x<5}` | -+------------------------+----------------------+ | | -| $`\strictif` | $`\strictfi` | | | -| `\strictif` | `\strictfi` | | | -+------------------------+----------------------+-----------------------------+------------------------------+ - -Linear Logic (from the `cmll` package): - -+-----------+----------------------+------------------------+----------------------+------------------------+ -| Operators | $` \oc ` `\oc` | $` \wn ` `\wn` | $` \with ` `\with` | $` \parr ` `\parr` | -* +----------------------+------------------------+----------------------+------------------------+ -| | $` \shpos ` `\shpos` | $` \shneg ` `\shneg` | $` \shift ` `\shift` | $` \invamp ` `\invamp` | -+-----------+----------------------+------------------------+----------------------+------------------------+ -| Relations | $` \coh ` `\coh` | $` \scoh ` `\scoh` | $` \Perp ` `\Perp` | $` \multimapboth ` | -| | | | | `\multimapboth` | -* +----------------------+------------------------+----------------------+------------------------+ -| | $` \incoh ` `\incoh` | $` \sincoh ` `\sincoh` | | $` \multimapinv ` | -| | | | | `\multimapinv` | -+-----------+----------------------+------------------------+----------------------+------------------------+ - -Equivalents in the _texvc_ extension - -+:-------------------+:-----------------+:-------------------+:---------------+ -| $`\exist` `\exist` | $`\isin` `\isin` | $`\empty` `\empty` | $`\sub` `\sub` | -+--------------------+------------------+--------------------+----------------+ - -Direct Input: ∀ ∴ ∁ ∵ ∃ ∣ ∈ ∉ ∋ ⊂ ⊃ ∧ ∨ ↦ → ← ↔ ∅ ⟹ ⟺ ¬ ↯ ⥼ ⥽\ -ℂ ℍ ℕ ℙ ℚ ℝ - -## Macros - -+:---------------------------------+:--------------------------------------------------------+ -| $`\def\foo#1#2{#1^2 #2^3} | `\def\macroname{definition to be expanded}` \ | -| \foo a b + \foo c d` | `\def\foo#1#2{#1^2 #2^3}` \ | -| | `\foo a b + \foo c d` | -+----------------------------------+---------------------------------------------------------+ -| | `\edef\macroname#1#2…{definition}` | -+----------------------------------+---------------------------------------------------------+ -| | `\let\foo=\bar` | -+----------------------------------+---------------------------------------------------------+ -| | `\futurelet\foo\bar x` | -+----------------------------------+---------------------------------------------------------+ -| $`\newcommand\foo[2]{#1^2 #2^3} | `\newcommand\macroname[numargs]{definition}` \ | -| \foo a b + \foo c d` | `\newcommand\foo[2]{#1^2 #2^3}` \ | -| | `\foo a b + \foo c d` | -+----------------------------------+---------------------------------------------------------+ -| | `\renewcommand\macroname[numargs]{definition}` | -+----------------------------------+---------------------------------------------------------+ -| | `\providecommand\macroname[numargs]{definition}` | -+----------------------------------+---------------------------------------------------------+ - -To create macros with document-wide scope, a [preamble](./administration.html#preamble) can be defined -as one of the Temml [rendering options](./administration.html#options) - -Macros accept up to nine arguments: #1, #2, etc. - -Available functions include: - -`\char` `\mathchoice` `\TextOrMath` `\@ifstar` `\@ifnextchar` `\@firstoftwo` `\@secondoftwo` `\relax` `\expandafter` `\noexpand` - -@ is a valid character for commands, as if `\makeatletter` were in effect. - -Temml macros do not escape their group, so `\gdef`, `\xdef`, and`\global` are not supported. -Temml has no `\par`, so `\long` is ignored. - -## Numbers - -Temml’s default mode will consolidate a string of numerals into a single MathML -`` element. This applies to any string that begins and ends with a digit -(0-9) and includes digits, commas, or dots. Example: `2,000.00`. - -In strict mode, Temml acts like LaTeX and treats each digit individually. This -is not as nice semantically, but it does maintain backwards compatibility for -LaTeX macros. - -## Operators - -### Big Operators - -+----------------------+--------------------------+----------------------------+-------------------------------+ -| $`\sum` `\sum` | $`\prod` `\prod` | $`\bigotimes` `\bigotimes` | $`\bigvee` `\bigvee` | -+----------------------+--------------------------+----------------------------+-------------------------------+ -| $`\int` `\int` | $`\coprod` `\coprod` | $`\bigoplus` `\bigoplus` | $`\bigwedge` `\bigwedge` | -+----------------------+--------------------------+----------------------------+-------------------------------+ -| $`\iint` `\iint` | $`\intop` `\intop` | $`\bigodot` `\bigodot` | $`\bigcap` `\bigcap` | -+----------------------+--------------------------+----------------------------+-------------------------------+ -| $`\iiint` `\iiint` | $`\smallint` `\smallint` | $`\biguplus` `\biguplus` | $`\bigcup` `\bigcup` | -+----------------------+--------------------------+----------------------------+-------------------------------+ -| $`\iiiint` `\iiiint` | $`\intcap` `\intcap` | $`\intcup` `\intcup` | $`\bigsqcup` `\bigsqcup` | -+----------------------+--------------------------+----------------------------+-------------------------------+ -| $`\oint` `\oint` | $`\varointclockwise` | $`\intclockwise` | $`\bigsqcap` | -| | `\varointclockwise` | `\intclockwise` | `\bigsqcap` | -+----------------------+--------------------------+----------------------------+-------------------------------+ -| $`\oiint` `\oiint` | $`\pointint` `\pointint` | $`\rppolint` `\rppolint` | $`\scpolint` `\scpolint` | -+----------------------+--------------------------+----------------------------+-------------------------------+ -| $`\oiiint` `\oiiint` | $`\intlarhk` `\intlarhk` | $`\sqint` `\sqint` | $`\intx` `\intx` | -+----------------------+--------------------------+----------------------------+-------------------------------+ -| $`\intbar` `\intbar` | $`\intBar` `\intBar` | $`\fint` `\fint` | $`\sideset{_a^b}{_c^d}\sum` | -| | | | `\sideset{_a^b}{_c^d}\sum` | -+----------------------+--------------------------+----------------------------+-------------------------------+ - -Direct Input: ∫ ∬ ∭ ⨌ ∮ ∯ ∰ ⨖ ∲ ∏ ∐ ∑ ⋀ ⋁ ⋂ ⋃ ⨀ ⨁ ⨂ ⨄ ⨆ ⨅ - -### Binary Operators - -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` + ` `+` | $` \cdot ` `\cdot` | $` \gtrdot ` `\gtrdot` | $` x \pmod a ` `x \pmod | -| | | | a` | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` - ` `-` | $` \cdotp ` `\cdotp` | $` \intercal ` | $` x \pod a ` `x \pod a` | -| | | `\intercal` | | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` / ` `/` | $`\centerdot` | $` \land ` `\land` | $` \rhd ` `\rhd` | -| | `\centerdot` | | | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` * ` `*` | $` \circ ` `\circ` | $` \leftthreetimes ` | $` \rightthreetimes ` | -| | | `\leftthreetimes` | `\rightthreetimes` | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` \amalg ` `\amalg` | $` \circledast ` | $` \ldotp ` `\ldotp` | $` \rtimes ` `\rtimes` | -| | `\circledast` | | | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` \And ` `\And` | $` \circledcirc ` | $` \lor ` `\lor` | $` \setminus ` | -| | `\circledcirc` | | `\setminus` | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` \ast ` `\ast` | $` \circleddash ` | $` \lessdot ` `\lessdot` | $` \smallsetminus ` | -| | `\circleddash` | | `\smallsetminus` | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` \barwedge ` | $` \Cup ` `\Cup` | $` \lhd ` `\lhd` | $` \sqcap ` `\sqcap` | -| `\barwedge` | | | | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` \bigcirc ` `\bigcirc` | $` \cup ` `\cup` | $` \ltimes ` `\ltimes` | $` \sqcup ` `\sqcup` | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` \bmod ` `\bmod` | $` \curlyvee ` | $` x \mod a ` `x\mod a` | $` \times ` `\times` | -| | `\curlyvee` | | | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` \boxdot ` `\boxdot` | $` \curlywedge ` | $` \mp ` `\mp` | $` \unlhd ` `\unlhd` | -| | `\curlywedge` | | | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` \boxminus ` | $` \div ` `\div` | $` \odot ` `\odot` | $` \unrhd ` `\unrhd` | -| `\boxminus` | | | | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` \boxplus ` `\boxplus` | $` \divideontimes ` | $` \ominus ` `\ominus` | $` \uplus ` `\uplus` | -| | `\divideontimes` | | | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` \boxtimes ` | $` \dotplus ` `\dotplus` | $` \oplus ` `\oplus` | $` \vee ` `\vee` | -| `\boxtimes` | | | | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` \bullet ` `\bullet` | $` \doublebarwedge ` | $` \otimes ` `\otimes` | $` \veebar ` `\veebar` | -| | `\doublebarwedge` | | | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` \Cap ` `\Cap` | $` \doublecap ` | $` \oslash ` `\oslash` | $` \wedge ` `\wedge` | -| | `\doublecap` | | | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| $` \cap ` `\cap` | $` \doublecup ` | $` \parr ` ` \parr ` | $` \with ` ` \with ` | -| | `\doublecup` | | | -+--------------------------+--------------------------+--------------------------+--------------------------+ -| | | $` \pm ` `\pm` | $` \wr ` `\wr` | -+--------------------------+--------------------------+--------------------------+--------------------------+ - -The _texvc_ extension provides $`\plusmn` `\plusmn`. - -Direct Input: + - / ∖ * ⋅ ∘ ± × ÷ ∓ ∔ ∧ ∨ ∩ ∪ ≀ ⊎ ⊓ ⊔ ⊕ ⊖ ⊗ ⊘ ⊙ ⊚ ⊛ ⊝ ◯ - -### Fractions and Binomials - -+:----------------+:-----------------+:-------------------------------+ -| $`\frac{a}{b}` | $`\tfrac{a}{b}` | $`\genfrac ( ] {2pt}{1}a{a+1}` | -| `\frac{a}{b}` | `\tfrac{a}{b}` | `\genfrac ( ] {2pt}{1}a{a+1}` | -+-----------------+------------------+--------------------------------+ -| $`{a \over b}` | $`\dfrac{a}{b}` | $`{a \above{2pt} b+1}` | -| `{a \over b}` | `\dfrac{a}{b}` | `{a \above{2pt} b+1}` | -+-----------------+------------------+--------------------------------+ -| $`a/b` `a/b` | | $`\cfrac{a}{1 + \cfrac{1}{b}}` | -| | | `\cfrac{a}{1 + \cfrac{1}{b}}` | -+-----------------+------------------+--------------------------------+ - -+:---------------------------------+:---------------------------------+:-----------------------------+ -| $`\binom{n}{k}` `\binom{n}{k}` | $`\dbinom{n}{k}` `\dbinom{n}{k}` | $`{n\brace k}` `{n\brace k}` | -+----------------------------------+----------------------------------+------------------------------+ -| $`{n \choose k}` `{n \choose k}` | $`\tbinom{n}{k}` `\tbinom{n}{k}` | $`{n\brack k}` `{n\brack k}` | -+----------------------------------+----------------------------------+------------------------------+ - -### Math Operators - -+---------------------------+------------------------+--------------------------------+--------------------+ -| $` \operatorname{f} ` | $` \cosec ` `\cosec` | $` \dim ` `\dim` | $`\pdv*{f}{x,y}` | -| `\operatorname{f}` | | | `\pdv*{f}{x,y}` | -+---------------------------+------------------------+--------------------------------+--------------------+ -| $` \arcsin ` `\arcsin` | $` \cosh ` `\cosh` | $` \exp ` `\exp` | $` \sec ` `\sec` | -+---------------------------+------------------------+--------------------------------+--------------------+ -| $` \arccos ` `\arccos` | $` \cot ` `\cot` | $` \hom ` `\hom` | $` \sgn ` `\sgn` | -+---------------------------+------------------------+--------------------------------+--------------------+ -| $` \arctan ` `\arctan` | $` \cotg ` `\cotg` | $` \ker ` `\ker` | $` \sin ` `\sin` | -+---------------------------+------------------------+--------------------------------+--------------------+ -| $` \arctg ` `\arctg` | $` \coth ` `\coth` | $` \lg ` `\lg` | $` \sinh ` `\sinh` | -+---------------------------+------------------------+--------------------------------+--------------------+ -| $` \arcctg ` `\arcctg` | $` \csc ` `\csc` | $` \ln ` `\ln` | $` \sh ` `\sh` | -+---------------------------+------------------------+--------------------------------+--------------------+ -| $` \arg ` `\arg` | $` \ctg ` `\ctg` | $` \log ` `\log` | $` \tan ` `\tan` | -+---------------------------+------------------------+--------------------------------+--------------------+ -| $` \ch ` `\ch` | $` \cth ` `\cth` | $`\odv{f}{x}` `\odv{f}{x}` | $` \tanh ` `\tanh` | -+---------------------------+------------------------+--------------------------------+--------------------+ -| $` \cos ` `\cos` | $` \nabla ` `\nabla` | $`\odv*{f}{x}` `\odv*{f}{x}` | $` \tg ` `\tg` | -+---------------------------+------------------------+--------------------------------+--------------------+ -| $` \partial ` `\partial` | $` \deg ` `\deg` | $`\pdv{f}{x,y}` `\pdv{f}{x,y}` | $` \th ` `\th` | -+---------------------------+------------------------+--------------------------------+--------------------+ -| $` \operatorname*{f} ` | $` \inf ` `\inf` | $` \max ` `\max` | $` \sup ` `\sup` | -| `\operatorname*{f}` or\ | | | | -| `\operatornamewithlimits` | | | | -+---------------------------+------------------------+--------------------------------+--------------------+ -| $` \argmax ` `\argmax` | $` \injlim ` `\injlim` | $` \min ` `\min` | $` \varinjlim ` | -| | | | `\varinjlim` | -+---------------------------+------------------------+--------------------------------+--------------------+ -| $` \argmin ` `\argmin` | $` \lim ` `\lim` | $` \plim ` `\plim` | $` \varliminf ` | -| | | | `\varliminf` | -+---------------------------+------------------------+--------------------------------+--------------------+ -| $` \det ` `\det` | $` \liminf ` `\liminf` | $` \Pr ` `\Pr` | $` \varlimsup ` | -| | | | `\varlimsup` | -+---------------------------+------------------------+--------------------------------+--------------------+ -| $` \gcd ` `\gcd` | $` \limsup ` `\limsup` | $` \projlim ` `\projlim` | $` \varprojlim ` | -| | | | `\varprojlim` | -+---------------------------+------------------------+--------------------------------+--------------------+ - -Functions in the bottom five rows of this table can take `\limits`. - -### Enclosing Operators - -+:-------------------------------+:-----------------------------------------------------+ -| $`\sqrt{x}` `\sqrt{x}` | $`\longdiv{3x^2 + 2x + 5}` `\longdiv{3x^2 + 2x + 5}` | -+--------------------------------+------------------------------------------------------+ -| $`\sqrt[3]{x}` `\sqrt[3]{x}` | $`\phase{-78^\circ}` `\phase{-78^\circ}` | -+--------------------------------+------------------------------------------------------+ -| $`a_{\angl n}`   `a_{\angl n}` | $`a_\angln`   `a_\angln` | -+--------------------------------+------------------------------------------------------+ - -## Physics and Chemistry - -+:---------------------------+:-------------------------------------------------------------+ -| $`\bra{\phi}` `\bra{\phi}` | $`\prescript{a}{2}{\mathbf{C}}^{5+}_{2}` | -| | `\prescript{a}{2}{\mathbf{C}}^{5+}_{2}` | -+----------------------------+--------------------------------------------------------------+ -| $`\ket{\psi}` `\ket{\psi}` | $`\braket{\phi\vert\psi}` | -| | `\braket{\phi\vert\psi}` | -+----------------------------+--------------------------------------------------------------+ -| $`\Bra{\phi}` `\Bra{\phi}` | $`\Braket{ \phi | \frac{\partial^2}{\partial t^2} | \psi }`\ | -| | `\Braket{ \phi | \frac{\partial^2}{\partial t^2} | \psi }` | -+----------------------------+ + -| $`\Ket{\psi}` `\Ket{\psi}` | | -+----------------------------+--------------------------------------------------------------+ - -From the _mhchem_ extension: - -+:----------------------------------+:---------------------------------+ -| $`\ce{SO4^2- + Ba^2+ -> BaSO4 v}` | `\ce{SO4^2- + Ba^2+ -> BaSO4 v}` | -+-----------------------------------+----------------------------------+ -| $`\pu{75.3 J // mol K}` | `\pu{75.3 J // mol K}` | -+-----------------------------------+----------------------------------+ - -

There is much more mhchem information in the -mhchem docs.

- -
- -
Click to see the physics extension. - -+:--------------------------------+:----------------------------+:-------------------------+ -| $`\abs{x}` `\abs{x}` | $`\innerproduct{a}{b}` | $`\qif` `\qif` | -| | `\innerproduct{a}{b}` | | -+---------------------------------+-----------------------------+--------------------------+ -| $`\absolutevalue{x}` | $`\ketbra{a}{b}` | $`\qin` `\qin` | -| `\absolutevalue{x}` | `\ketbra{a}{b}` | | -+---------------------------------+-----------------------------+--------------------------+ -| $`\acomm{A}{B}` `\acomm{A}{B}` | $`\laplacian` | $`\qinteger` `\qinteger` | -| | `\laplacian` | | -+---------------------------------+-----------------------------+--------------------------+ -| $`\anticommutator{A}{B}` | $`\matrixel{n}{A}{m}` | $`\qlet` `\qlet` | -| `\anticommutator{A}{B}` | `\matrixel{n}{A}{m}` | | -+---------------------------------+-----------------------------+--------------------------+ -| $`\Bqty{5 \text{mm}}` | $`\matrixelement{n}{A}{m}` | $`\qodd` `\qodd` | -| `\Bqty{5 \text{mm}}` | `\matrixelement{n}{A}{m}` | | -+---------------------------------+-----------------------------+--------------------------+ -| $`\bqty{5 \text{mm}}` | $`\mel{n}{A}{m}` | $`\qor` `\qor` | -| `\bqty{5 \text{mm}}` | `\mel{n}{A}{m}` | | -+---------------------------------+-----------------------------+--------------------------+ -| $`\comm{A}{B}` `\comm{A}{B}` | $`\norm{x}` `\norm{x}` | $`\qotherwise` | -| | | `\qotherwise` | -+---------------------------------+-----------------------------+--------------------------+ -| $`\commutator{A}{B}` | $`\op{a}{b}` `\op{a}{b}` | $`\qq{text}` `\qq{text}` | -| `\commutator{A}{B}` | | | -+---------------------------------+-----------------------------+--------------------------+ -| $`\cp` `\cp` | $`\order{x^2}` | $`\qqtext{text}` | -| | `\order{x^2}` | `\qqtext{text}` | -+---------------------------------+-----------------------------+--------------------------+ -| $`\cross` `\cross` | $`\outerproduct{a}{b}` | $`\qsince` `\qsince` | -| | `\outerproduct{a}{b}` | | -+---------------------------------+-----------------------------+--------------------------+ -| $`\crossproduct` | $`\partialderivative{x}{y}` | $`\qthen` `\qthen` | -| `\crossproduct` | `\partialderivative{x}{y}` | | -+---------------------------------+-----------------------------+--------------------------+ -| $`\curl` `\curl` | $`\pb{x}{y}` `\pb{x}{y}` | $`\qty{5 \text{m}}` | -| | | `\qty{5 \text{m}}` | -+---------------------------------+-----------------------------+--------------------------+ -| $`\dd` `\dd` | | $`\quantity{5 \text{m}}` | -| | | `\quantity{5 \text{m}}` | -+---------------------------------+-----------------------------+--------------------------+ -| $`\derivative{x}{y}` | $`\poissonbracket{A}{B}` | $`\qunless` `\qunless` | -| `\derivative{x}{y}` | `\poissonbracket{A}{B}` | | -+---------------------------------+-----------------------------+--------------------------+ -| $`\differential` | $`\pqty{5}` `\pqty{5}` | $`\qusing` `\qusing` | -| `\differential` | | | -+---------------------------------+-----------------------------+--------------------------+ -| $`\divergence` `\divergence` | $`\principalvalue` | $`\rank M` `\rank M` | -| | `\principalvalue` | | -+---------------------------------+-----------------------------+--------------------------+ -| $`\dotproduct` `\dotproduct` | $`\pv` `\pv` | $`\Res[f(z)]` | -| | | `\Res\[f(z)\]` | -+---------------------------------+-----------------------------+--------------------------+ -| $`\dv{x}{y}` `\dv{x}{y}` | $`\PV(x)` `\PV(x)` | $`\Tr\rho` `\Tr\rho` | -+---------------------------------+-----------------------------+--------------------------+ -| $`\dyad{a}{b}` `\dyad{a}{b}` | $`\qall` `\qall` | $`\tr\rho` `\tr\rho` | -+---------------------------------+-----------------------------+--------------------------+ -| $`\erf(x)` `\erf(x)` | $`\qand` `\qand` | $`\va{a}` `\va{a}` | -+---------------------------------+-----------------------------+--------------------------+ -| $`\ev{x}` `\ev{x}` | $`\qas` `\qas` | $`\var` `\var` | -+---------------------------------+-----------------------------+--------------------------+ -| $`\eval{\tfrac 1 2 x}_0^n` | $`\qassume` `\qassume` | $`\variation` | -| `\eval{\tfrac 1 2 x}_0^n` | | `\variation` | -+---------------------------------+-----------------------------+--------------------------+ -| $`\evaluated{\tfrac 1 2 x}_0^n` | $`\qc` `\qc` | $`\vb{a}` `\vb{a}` | -| `\evaluated{\tfrac 1 2 x}_0^n` | | | -+---------------------------------+-----------------------------+--------------------------+ -| $`\expectationvalue{x}` | $`\qcc` `\qcc` | $`\vdot` `\vdot` | -| `\expectationvalue{x}` | | | -+---------------------------------+-----------------------------+--------------------------+ -| $`\expval{x}` `\expval{x}` | $`\qcomma` `\qcomma` | $`\vectorarrow{a}` | -| | | `\vectorarrow{a}` | -+---------------------------------+-----------------------------+--------------------------+ -| $`\fdv{x}{y}` `\fdv{x}{y}` | $`\qelse` `\qelse` | $`\vectorbold{a}` | -| | | `\vectorbold{a}` | -+---------------------------------+-----------------------------+--------------------------+ -| $`\functionalderivative{x}{y}` | $`\qeven` `\qeven` | $`\vectorunit{a}` | -| `\functionalderivative{x}{y}` | | `\vectorunit{a}` | -+---------------------------------+-----------------------------+--------------------------+ -| $`\grad` `\grad` | $`\qfor` `\qfor` | $`\vqty{x}` `\vqty{x}` | -+---------------------------------+-----------------------------+--------------------------+ -| $`\gradient` `\gradient` | $`\qgiven` `\qgiven` | $`\vu{a}` `\vu{a}` | -+---------------------------------+-----------------------------+--------------------------+ - -
- -## Relations - -$`\stackrel{!}{=}\vphantom{\frac a b}` `\stackrel{!}{=}` - -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` = ` `=` | $` \eqcirc ` `\eqcirc` | $` \lesseqqgtr ` | $` \smallsmile ` | -| | | `\lesseqqgtr` | `\smallsmile` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` < ` `<` | $` \eqcolon ` `\eqcolon` | $` \lessgtr ` `\lessgtr` | $` \smile ` `\smile` | -| | or\ | | | -| |   `\minuscolon` | | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` > ` `>` | $` \Eqcolon ` `\Eqcolon` | $` \lesssim ` `\lesssim` | $` \sqsubset ` | -| | or\ | | `\sqsubset` | -| |    `\minuscoloncolon` | | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` : ` `:` | $` \eqqcolon ` | $` \ll ` `\ll` | $` \sqsubseteq ` | -| | `\eqqcolon` | | `\sqsubseteq` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` := ` `:=` | $` \Eqqcolon ` | $` \lll ` `\lll` | $` \sqsupset ` | -| | `\Eqqcolon` | | `\sqsupset` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \approx ` `\approx` | $` \eqdef ` `\eqdef` | $` \llless ` `\llless` | $` \sqsupseteq ` | -| | | | `\sqsupseteq` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \approxeq ` | $` \eqsim ` `\eqsim` | $` \lt ` `\lt` | $` \stareq ` `\stareq` | -| `\approxeq` | | | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \arceq ` `\arceq` | $` \eqslantgtr ` | $` \measeq ` `\measeq` | $` \Subset ` `\Subset` | -| | `\eqslantgtr` | | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \asymp ` `\asymp` | $` \eqslantless ` | $` \mid ` `\mid` | $` \subset ` `\subset` | -| | `\eqslantless` | | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \backcong ` | $` \equiv ` `\equiv` | $` \models ` `\models` | $` \subseteq ` | -| `\backcong` | | | `\subseteq` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \backepsilon ` | $` \fallingdotseq ` | $` \multimap ` | $` \subseteqq ` | -| `\backepsilon` | `\fallingdotseq` | `\multimap` | `\subseteqq` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \backsim ` `\backsim` | $` \frown ` `\frown` | $`\multimapboth ` `\multimapboth` | $` \succ ` `\succ` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \backsimeq ` | $` \ge ` `\ge` | $`\multimapinv ` `\multimapinv` | $` \succapprox ` | -| `\backsimeq` | | | `\succapprox` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \between ` `\between` | $` \geq ` `\geq` | $` \origof ` `\origof` | $` \succcurlyeq ` | -| | | | `\succcurlyeq` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \bowtie ` `\bowtie` | $` \geqq ` `\geqq` | $` \owns ` `\owns` | $` \succeq ` `\succeq` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \bumpeq ` `\bumpeq` | $` \geqslant ` | $` \parallel ` | $` \succsim ` `\succsim` | -| | `\geqslant` | `\parallel` | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \Bumpeq ` `\Bumpeq` | $` \gg ` `\gg` | $` \perp ` `\perp` | $` \Supset ` `\Supset` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \circeq ` `\circeq` | $` \ggg ` `\ggg` | $` \Perp ` `\Perp` | $` \supset ` `\supset` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \coh ` `\coh` | $` \gggtr ` `\gggtr` | $` \pitchfork ` | $` \supseteq ` | -| | | `\pitchfork` | `\supseteq` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \colonapprox ` | $` \gt ` `\gt` | $` \prec ` `\prec` | $` \supseteqq ` | -| `\colonapprox` | | | `\supseteqq` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \Colonapprox ` | $` \gtrapprox ` | $` \precapprox ` | $` \thickapprox ` | -| `\Colonapprox` or\ | `\gtrapprox` | `\precapprox` | `\thickapprox` | -|    `\coloncolonapprox` | | | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \coloneq ` `\coloneq` | $` \gtreqless ` | $` \preccurlyeq ` | $` \thicksim ` | -| or\ | `\gtreqless` | `\preccurlyeq` | `\thicksim` | -|    `\colonminus` | | | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \Coloneq ` `\Coloneq` | $` \gtreqqless ` | $` \preceq ` `\preceq` | $` \trianglelefteq ` | -| or\ | `\gtreqqless` | | `\trianglelefteq` | -|    `\coloncolonminus` | | | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \coloneqq ` | $` \gtrless ` `\gtrless` | $` \precsim ` `\precsim` | $` \triangleq ` | -| `\coloneqq` or\ | | | `\triangleq` | -|    `\colonequals` | | | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \Coloneqq ` | $` \gtrsim ` `\gtrsim` | $` \propto ` `\propto` | $` \trianglerighteq ` | -| `\Coloneqq` or \ | | | `\trianglerighteq` | -|     `\coloncolonequals` | | | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \colonsim ` | $` \imageof ` `\imageof` | $` \questeq ` `\questeq` | $` \varpropto ` | -| `\colonsim` | | | `\varpropto` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \Colonsim ` | $` \in ` `\in` or `\isin` | :`\ratio` or\ | $` \vartriangle ` | -| `\Colonsim` or\ | |   `\vcentcolon` | `\vartriangle` | -|    `\coloncolonsim` | | | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \cong ` `\cong` | $` \incoh ` `\incoh` | $` \risingdotseq ` | $` \vartriangleleft ` | -| | | `\risingdotseq` | `\vartriangleleft` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \curlyeqprec ` | $` \Join ` `\Join` | $` \scoh ` `\scoh` | $` \vartriangleright ` | -| `\curlyeqprec` | | | `\vartriangleright` | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \curlyeqsucc ` | $` \le ` `\le` | $` \shortmid ` | $` \vdash ` `\vdash` | -| `\curlyeqsucc` | | `\shortmid` | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \dashv ` `\dashv` | $` \leq ` `\leq` | $` \shortparallel ` | $` \vDash ` `\vDash` | -| | | `\shortparallel` | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \dblcolon ` | $` \leqq ` `\leqq` | $` \sim ` `\sim` | $` \Vdash ` `\Vdash` | -| `\dblcolon` or\ | | | | -|    `\coloncolon` | | | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \doteq ` `\doteq` | $` \leqslant ` | $` \simeq ` `\simeq` | $` \Vvdash ` `\Vvdash` | -| | `\leqslant` | | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \Doteq ` `\Doteq` | $` \lessapprox ` | $` \sincoh ` `\sincoh` | $` \veeeq ` `\veeeq` | -| | `\lessapprox` | | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ -| $` \doteqdot ` | $` \lesseqgtr ` | $` \smallfrown ` | $` \wedgeq ` `\wedgeq` | -| `\doteqdot` | `\lesseqgtr` | `\smallfrown` | | -+---------------------------+---------------------------+-----------------------------------+--------------------------+ - -The _texvc_ extension provides $`\sub` `\sub`, $`\sube` `\sube`, and $`\supe` `\supe`. - -Direct Input: = < > : ∈ ∋ ∝ ∼ ∽ ≂ ≃ ≅ ≈ ≊ ≍ ≎ ≏ ≐ ≑ ≒ ≓ ≖ -≗ ≜ ≡ ≤ ≥ ≦ ≧ ≫ ≬ ≳ ≷ ≺ ≻ ≼ ≽ ≾ ≿ ⊂ ⊃ ⊆ ⊇ ⊏ ⊐ ⊑ ⊒ ⊢ ⊣ ⊩ ⊪ ⊸ ⋈ ⋍ ⋐ ⋑ ⋔ ⋙ -⋛ ⋞ ⋟ ⌢ ⌣ ⩾ ⪆ ⪌ ⪕ ⪖ ⪯ ⪰ ⪷ ⪸ ⫅ ⫆ ≲ ⩽ ⪅ ≶ ⋚ ⪋ ⟂ ⊨ ≔ ≕ ⩴ ⊷ ⊶ - -### Negated Relations - -$`\not =` `\not =` - -+----------------------+---------------------------+--------------------------+------------------------+ -| $` \gnapprox ` | $` \ngeqslant ` | $` \nsubset ` | $` \nVdash ` `\nVdash` | -| `\gnapprox` | `\ngeqslant` | ` \nsubset ` | | -+----------------------+---------------------------+--------------------------+------------------------+ -| $` \gneq ` `\gneq` | $` \ngtr ` `\ngtr` | $` \nsubseteq ` | $` \precnapprox ` | -| | | `\nsubseteq` | `\precnapprox` | -+----------------------+---------------------------+--------------------------+------------------------+ -| $` \gneqq ` `\gneqq` | $` \nleq ` `\nleq` | $` \nsubseteqq ` | $` \precneqq ` | -| | | `\nsubseteqq` | `\precneqq` | -+----------------------+---------------------------+--------------------------+------------------------+ -| $` \gnsim ` `\gnsim` | $` \nleqq ` `\nleqq` | $` \nsucc ` `\nsucc` | $` \precnsim ` | -| | | | `\precnsim` | -+----------------------+---------------------------+--------------------------+------------------------+ -| $` \gvertneqq ` | $` \nleqslant ` | $` \nsucceq ` `\nsucceq` | $` \subsetneq ` | -| `\gvertneqq` | `\nleqslant` | | `\subsetneq` | -+----------------------+---------------------------+--------------------------+------------------------+ -| $` \lnapprox ` | $` \nless ` `\nless` | $` \nsupset ` | $` \subsetneqq ` | -| `\lnapprox` | | ` \nsupset ` | `\subsetneqq` | -+----------------------+---------------------------+--------------------------+------------------------+ -| $` \lneq ` `\lneq` | $` \nmid ` `\nmid` | $` \nsupseteq ` | $` \succnapprox ` | -| | | `\nsupseteq` | `\succnapprox` | -+----------------------+---------------------------+--------------------------+------------------------+ -| $` \lneqq ` `\lneqq` | $` \notin ` `\notin` | $` \nsupseteqq ` | $` \succneqq ` | -| | | `\nsupseteqq` | `\succneqq` | -+----------------------+---------------------------+--------------------------+------------------------+ -| $` \lnsim ` `\lnsim` | $` \notni ` `\notni` | $` \ntriangleleft ` | $` \succnsim ` | -| | | `\ntriangleleft` | `\succnsim` | -+----------------------+---------------------------+--------------------------+------------------------+ -| $` \lvertneqq ` | $` \nparallel ` | $` \ntrianglelefteq ` | $` \supsetneq ` | -| `\lvertneqq` | `\nparallel` | `\ntrianglelefteq` | `\supsetneq` | -+----------------------+---------------------------+--------------------------+------------------------+ -| $` \ncong ` `\ncong` | $` \nprec ` `\nprec` | $` \ntriangleright ` | $` \supsetneqq ` | -| | | `\ntriangleright` | `\supsetneqq` | -+----------------------+---------------------------+--------------------------+------------------------+ -| $` \ne ` `\ne` | $` \npreceq ` `\npreceq` | $` \ntrianglerighteq ` | $` \varsubsetneq ` | -| | | `\ntrianglerighteq` | `\varsubsetneq` | -+----------------------+---------------------------+--------------------------+------------------------+ -| $` \neq ` `\neq` | $` \nshortmid ` | $` \nvdash ` `\nvdash` | $` \varsubsetneqq ` | -| | `\nshortmid` | | `\varsubsetneqq` | -+----------------------+---------------------------+--------------------------+------------------------+ -| $` \ngeq ` `\ngeq` | $` \nshortparallel ` | $` \nvDash ` `\nvDash` | $` \varsupsetneq ` | -| | `\nshortparallel` | | `\varsupsetneq` | -+----------------------+---------------------------+--------------------------+------------------------+ -| $` \ngeqq ` `\ngeqq` | $` \nsim ` `\nsim` | $` \nVDash ` `\nVDash` | $` \varsupsetneqq ` | -| | | | `\varsupsetneqq` | -+----------------------+---------------------------+--------------------------+------------------------+ - -Direct Input: ∉ ∌ ∤ ∦ ≁ ≆ ≠ ≨ ≩ ≮ ≯ ≰ ≱ ⊀ ⊁ ⊄ ⊅ ⊈ ⊉ ⊊ ⊋ ⊬ ⊭ -⊮ ⊯ ⋠ ⋡ ⋦ ⋧ ⋨ ⋩ ⋬ ⋭ ⪇ ⪈ ⪉ ⪊ ⪵ ⪶ ⪹ ⪺ ⫋ ⫌ - -### Arrows - -+------------------------+-------------------------+------------------------+ -| $`\circlearrowleft` | $`\Leftrightarrow` | $`\rightarrow` | -| `\circlearrowleft` | `\Leftrightarrow` | `\rightarrow` | -+------------------------+-------------------------+------------------------+ -| $`\circlearrowright` | $`\leftrightarrows` | $`\Rightarrow` | -| `\circlearrowright` | `\leftrightarrows` | `\Rightarrow` | -+------------------------+-------------------------+------------------------+ -| $`\curvearrowleft` | $`\leftrightharpoons` | $`\rightarrowtail` | -| `\curvearrowleft` | `\leftrightharpoons` | `\rightarrowtail` | -+------------------------+-------------------------+------------------------+ -| $`\curvearrowright` | $`\leftrightsquigarrow` | $`\rightharpoondown` | -| `\curvearrowright` | `\leftrightsquigarrow` | `\rightharpoondown` | -+------------------------+-------------------------+------------------------+ -| $`\dashleftarrow` | $`\Lleftarrow` | $`\rightharpoonup` | -| `\dashleftarrow` | `\Lleftarrow` | `\rightharpoonup` | -+------------------------+-------------------------+------------------------+ -| $`\dashrightarrow` | $`\longleftarrow` | $`\rightleftarrows` | -| `\dashrightarrow` | `\longleftarrow` | `\rightleftarrows` | -+------------------------+-------------------------+------------------------+ -| $`\downarrow` | $`\Longleftarrow` | $`\rightleftharpoons` | -| `\downarrow` | `\Longleftarrow` | `\rightleftharpoons` | -+------------------------+-------------------------+------------------------+ -| $`\Downarrow` | $`\longleftrightarrow` | $`\rightrightarrows` | -| `\Downarrow` | `\longleftrightarrow` | `\rightrightarrows` | -+------------------------+-------------------------+------------------------+ -| $`\downdownarrows` | $`\Longleftrightarrow` | $`\rightsquigarrow` | -| `\downdownarrows` | `\Longleftrightarrow` | `\rightsquigarrow` | -+------------------------+-------------------------+------------------------+ -| $`\downharpoonleft` | $`\longmapsto` | $`\Rrightarrow` | -| `\downharpoonleft` | `\longmapsto` | `\Rrightarrow` | -+------------------------+-------------------------+------------------------+ -| $`\downharpoonright` | $`\longrightarrow` | $`\Rsh` `\Rsh` | -| `\downharpoonright` | `\longrightarrow` | | -+------------------------+-------------------------+------------------------+ -| $`\gets` `\gets` | $`\Longrightarrow` | $`\searrow` `\searrow` | -| | `\Longrightarrow` | | -+------------------------+-------------------------+------------------------+ -| $`\hookleftarrow` | $`\looparrowleft` | $`\swarrow` `\swarrow` | -| `\hookleftarrow` | `\looparrowleft` | | -+------------------------+-------------------------+------------------------+ -| $`\hookrightarrow` | $`\looparrowright` | $`\to` `\to` | -| `\hookrightarrow` | `\looparrowright` | | -+------------------------+-------------------------+------------------------+ -| $`\iff` `\iff` | $`\Lsh` `\Lsh` | $`\twoheadleftarrow` | -| | | `\twoheadleftarrow` | -+------------------------+-------------------------+------------------------+ -| $`\impliedby` | $`\mapsto` `\mapsto` | $`\twoheadrightarrow` | -| `\impliedby` | | `\twoheadrightarrow` | -+------------------------+-------------------------+------------------------+ -| $`\implies` `\implies` | $`\nearrow` `\nearrow` | $`\uparrow` `\uparrow` | -+------------------------+-------------------------+------------------------+ -| $`\leadsto` `\leadsto` | $`\nleftarrow` | $`\Uparrow` `\Uparrow` | -| | `\nleftarrow` | | -+------------------------+-------------------------+------------------------+ -| $`\leftarrow` | $`\nLeftarrow` | $`\updownarrow` | -| `\leftarrow` | `\nLeftarrow` | `\updownarrow` | -+------------------------+-------------------------+------------------------+ -| $`\Leftarrow` | $`\nleftrightarrow` | $`\Updownarrow` | -| `\Leftarrow` | `\nleftrightarrow` | `\Updownarrow` | -+------------------------+-------------------------+------------------------+ -| $`\leftarrowtail` | $`\nLeftrightarrow` | $`\upharpoonleft` | -| `\leftarrowtail` | `\nLeftrightarrow` | `\upharpoonleft` | -+------------------------+-------------------------+------------------------+ -| $`\leftharpoondown` | $`\nrightarrow` | $`\upharpoonright` | -| `\leftharpoondown` | `\nrightarrow` | `\upharpoonright` | -+------------------------+-------------------------+------------------------+ -| $`\leftharpoonup` | $`\nRightarrow` | $`\upuparrows` | -| `\leftharpoonup` | `\nRightarrow` | `\upuparrows` | -+------------------------+-------------------------+------------------------+ -| $`\leftleftarrows` | $`\nwarrow` `\nwarrow` | | -| `\leftleftarrows` | | | -+------------------------+-------------------------+------------------------+ -| $`\leftrightarrow` | $`\restriction` | | -| `\leftrightarrow` | `\restriction` | | -+------------------------+-------------------------+------------------------+ - -Arrows in the _texvc_ extension - -+:-----------------+:-----------------+:-----------------+:-------------------+:-----------------+:-----------------+ -| $`\Darr` `\Darr` | $`\Harr` `\Harr` | $`\Larr` `\Larr` | $`\Lrarr` `\Lrarr` | $`\Rarr` `\Rarr` | $`\Uarr` `\Uarr` | -+------------------+------------------+------------------+--------------------+------------------+------------------+ -| $`\dArr` `\dArr` | $`\hArr` `\hArr` | $`\lArr` `\lArr` | $`\lrArr` `\lrArr` | $`\rArr` `\rArr` | $`\uArr` `\uArr` | -+------------------+------------------+------------------+--------------------+------------------+------------------+ -| $`\darr` `\darr` | $`\harr` `\harr` | $`\larr` `\larr` | $`\lrarr` `\lrarr` | $`\rarr` `\rarr` | $`\uarr` `\uarr` | -+------------------+------------------+------------------+--------------------+------------------+------------------+ - -Direct Input: ← ↑ → ↓ ↔ ↕ ↖ ↗ ↘ ↙ ↚ ↛ ↞ ↠ ↢ ↣ ↦ ↩ ↪ ↫ ↬ ↭ ↮ ↰ ↱↶ ↷ ↺ ↻ ↼ ↽ ↾ ↾ ↿ ⇀ ⇁ ⇂ ⇃ ⇄ ⇆ ⇇ ⇈ ⇉ ⇊ ⇋ ⇌⇍ ⇎ ⇏ ⇐ ⇑ ⇒ ⇓ ⇔ ⇕ ⇚ ⇛ ⇝ ⇠ ⇢ ⟵ ⟶ ⟷ ⟸ ⟹ ⟺ ⟼ ↽ - -### Extensible Arrows - -+:-------------------------------------------------------+:---------------------------------------------------------+ -| $`\xleftarrow{abc}` `\xleftarrow{abc}` | $`\xrightarrow[under]{over}` `\xrightarrow[under]{over}` | -+--------------------------------------------------------+----------------------------------------------------------+ -| $`\xLeftarrow{abc}` `\xLeftarrow{abc}` | $`\xRightarrow{abc}` `\xRightarrow{abc}` | -+--------------------------------------------------------+----------------------------------------------------------+ -| $`\xleftrightarrow{abc}` `\xleftrightarrow{abc}` | $`\xLeftrightarrow{abc}` `\xLeftrightarrow{abc}` | -+--------------------------------------------------------+----------------------------------------------------------+ -| $`\xhookleftarrow{abc}` `\xhookleftarrow{abc}` | $`\xhookrightarrow{abc}` `\xhookrightarrow{abc}` | -+--------------------------------------------------------+----------------------------------------------------------+ -| $`\xtwoheadleftarrow{abc}` `\xtwoheadleftarrow{abc}` | $`\xtwoheadrightarrow{abc}` `\xtwoheadrightarrow{abc}` | -+--------------------------------------------------------+----------------------------------------------------------+ -| $`\xleftharpoonup{abc}` `\xleftharpoonup{abc}` | $`\xrightharpoonup{abc}` `\xrightharpoonup{abc}` | -+--------------------------------------------------------+----------------------------------------------------------+ -| $`\xleftharpoondown{abc}` `\xleftharpoondown{abc}` | $`\xrightharpoondown{abc}` `\xrightharpoondown{abc}` | -+--------------------------------------------------------+----------------------------------------------------------+ -| $`\xleftrightharpoons{abc}` `\xleftrightharpoons{abc}` | $`\xrightleftharpoons{abc}` `\xrightleftharpoons{abc}` | -+--------------------------------------------------------+----------------------------------------------------------+ -| $`\xtofrom{abc}` `\xtofrom{abc}` | $`\xmapsto{abc}` `\xmapsto{abc}` | -+--------------------------------------------------------+----------------------------------------------------------+ -| $`\xlongequal{abc}` `\xlongequal{abc}` | | -+--------------------------------------------------------+----------------------------------------------------------+ - -All extensible arrows can take an optional argument in the same manner as `\xrightarrow[under]{over}`. - -## Style, Size, and Font - -#### Class Assignment - -Override the usual spacing and semantic meaning of a character or fragment. - -+-----------------------------------------------+-----------------------------------------------+ -| $`a = b`  `a = b` \ | $`a | b\;\,`  `a | b` \ | -| $`a \mathord = b\;\,`  `a \mathord{=} b` \ | $`a \mathpunct | b\;`  `a \mathpunct{|} b` \ | -| $`a \mathopen = b\;\,`  `a \mathopen{=} b` \ | $`a \mathop | b\;`  `a \mathop{|} b` \ | -| $`a \mathclose = b\;\,`  `a \mathclose{=} b` | $`a \mathbin | b\,`  `a \mathbin{|} b` \ | -| | $`a \mathrel | b`  `a \mathrel{|} b` | -+-----------------------------------------------+-----------------------------------------------+ - -See also [\operatorname](#math-operators). - -#### Font - -+:-------------------------------+:---------------------------------+:---------------------------------+ -| $`\mathrm{Ab0}` `\mathrm{Ab0}` | $`\mathbf{Ab0θ}` `\mathbf{Ab0θ}` | $`\mathit{Ab0θ}` `\mathit{Ab0θ}` | -+--------------------------------+----------------------------------+----------------------------------+ -| $`\mathnormal{Ab0}` | $`\textbf{Ab0θ}` `\textbf{Ab0θ}` | $`\textit{Ab0θ}` `\textit{Ab0θ}` | -| `\mathnormal{Ab0}` | | | -+--------------------------------+----------------------------------+----------------------------------+ -| $`\textrm{Ab0θ}` | $`{\bf Ab0θ}` `{\bf Ab0θ}` | $`{\it Ab0θ}` `{\it Ab0θ}` | -| `\textrm{Ab0θ}` | | | -+--------------------------------+----------------------------------+----------------------------------+ -| $`{\rm Ab0}` `{\rm Ab0}` | $`\bold{Ab0θ}` `\bold{Ab0θ}` | $`\textup{Ab0θ}` `\textup{Ab0θ}` | -+--------------------------------+----------------------------------+----------------------------------+ -| $`\textnormal{Ab0θ}` | $`\boldsymbol{Ab0θ}` | $`\Bbb{Ab0}` `\Bbb{Ab0}` | -| `\textnormal{Ab0θ}` | `\boldsymbol{Ab0θ}` | | -+--------------------------------+----------------------------------+----------------------------------+ -| $`\text{Ab0θ}` `\text{Ab0θ}` | $`\bm{Ab0θ}` `\bm{Ab0θ}` | $`\mathbb{Ab0}` `\mathbb{Ab0}` | -+--------------------------------+----------------------------------+----------------------------------+ -| $`\mathsf{Ab0}` `\mathsf{Ab0}` | $`\textmd{Ab0θ}` `\textmd{Ab0θ}` | $`\frak{Ab}` `\frak{Ab}` | -+--------------------------------+----------------------------------+----------------------------------+ -| $`\textsf{Ab0}` `\textsf{Ab0}` | $`\mathtt{Ab0}` `\mathtt{Ab0}` | $`\mathfrak{Ab}` `\mathfrak{Ab}` | -+--------------------------------+----------------------------------+----------------------------------+ -| $`{\sf Ab0}` `{\sf Ab0}` | $`\texttt{Ab0}` `\texttt{Ab0}` | $`\mathcal{AB}` `\mathcal{AB}` | -+--------------------------------+----------------------------------+----------------------------------+ -| $`\textsc{hey}` `\textsc{hey}` | $`{\tt Ab0}` `{\tt Ab0 }` | $`{\cal AB}` `{\cal AB}` | -+--------------------------------+----------------------------------+----------------------------------+ -| $`\oldstylenums{123}` | | $`\mathscr{AB}` `\mathscr{AB}` | -| `\oldstylenums{123}` | | | -+--------------------------------+----------------------------------+----------------------------------+ - -The `\textXX` versions can stack font family, font weight, and font shape. So `\textsf{\textbf{H}}` will produce $`\textsf{\textbf{H}}`. The other versions do not stack, e.g., `\mathsf{\mathbf{H}}` will produce $`\mathsf{\mathbf{H}}`. - -In cases where math fonts do not have a bold glyph, `\pmb` can simulate one. For example, `\pmb{\vartheta}` renders as : $`\pmb{\vartheta}` - -#### Font Size - -+:-------------------------+:---------------------------------------+ -| $`\Huge AB` `\Huge AB` | $`\normalsize AB` `\normalsize AB` | -+--------------------------+----------------------------------------+ -| $`\huge AB` `\huge AB` | $`\small AB` `\small AB` | -+--------------------------+----------------------------------------+ -| $`\LARGE AB` `\LARGE AB` | $`\footnotesize AB` `\footnotesize AB` | -+--------------------------+----------------------------------------+ -| $`\Large AB` `\Large AB` | $`\scriptsize AB` `\scriptsize AB` | -+--------------------------+----------------------------------------+ -| $`\large AB` `\large AB` | $`\Tiny AB` `\Tiny AB` | -+--------------------------+----------------------------------------+ -| | $`\tiny AB` `\tiny AB` | -+--------------------------+----------------------------------------+ - -#### Style - -+:-----------------------------+:-----------------------------------------------------------------+ -| $`\displaystyle\sum_{i=1}^n` | `\displaystyle\sum_{i=1}^n` | -+------------------------------+------------------------------------------------------------------+ -| $`\textstyle\sum_{i=1}^n` | `\textstyle\sum_{i=1}^n` | -+------------------------------+------------------------------------------------------------------+ -| $`\scriptstyle x` | `\scriptstyle x`     (The size of a first sub/superscript) | -+------------------------------+------------------------------------------------------------------+ -| $`\scriptscriptstyle x` | `\scriptscriptstyle x` (The size of subsequent sub/superscripts) | -+------------------------------+------------------------------------------------------------------+ -| $`\lim\limits_y x` | `\lim\limits_y x` | -+------------------------------+------------------------------------------------------------------+ -| $`\lim\nolimits_y x` | `\lim\nolimits_y x` | -+------------------------------+------------------------------------------------------------------+ -| $`\verb!x^2!` | `\verb!x^2!` | -+------------------------------+------------------------------------------------------------------+ -| $`\text{ABcd }ABcd` | `\text{ABcd $ABcd$}` | -+------------------------------+------------------------------------------------------------------+ - -`\text{…}` shifts its contents into text mode, but you can shift back into math mode by nesting `$…$`. - -## Symbols and Punctuation - -+:-----------------------------+:------------------------+:-----------------------------------+ -| `% comment` | $`\dots` `\dots` | $`\TeX` `\TeX` | -+------------------------------+-------------------------+------------------------------------+ -| $`\%` `\%` | $`\cdots` `\cdots` | $`\LaTeX` `\LaTeX` | -+------------------------------+-------------------------+------------------------------------+ -| $`\#` `\#` | $`\ddots` `\ddots` | $`\Temml` `\Temml` | -+------------------------------+-------------------------+------------------------------------+ -| $`\&` `\&` | $`\ldots` `\ldots` | $`\rule[6pt]{2ex}{1ex}` | -| | | `\rule[6pt]{2ex}{1ex}` | -+------------------------------+-------------------------+------------------------------------+ -| $`\_` `\_` | $`\vdots` `\vdots` | $`\surd` `\surd` | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textunderscore}` | $`\iddots` `\iddots` | $`\infty` `\infty` | -| `\text{\textunderscore}` | | | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{--}` `\text{--}` | $`\dotsb` `\dotsb` | $`\checkmark` `\checkmark` | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textendash}` | $`\dotsc` `\dotsc` | $`\ballotx` `\ballotx` | -| `\text{\textendash}` | | | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{---}` `\text{---}` | $`\dotsi` `\dotsi` | $`\dag` `\dagger` or `\dag` | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textemdash}` | $`\dotsm` `\dotsm` | $`\text{\textdagger}` | -| `\text{\textemdash}` | | `\text{\textdagger}` | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textasciitilde}` | $`\dotso` `\dotso` | $`\ddagger` `\ddagger` or `\ddag` | -| `\text{\textasciitilde}` | | | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textasciicircum}` | $`\dotsi` `\idotsin` | $`\text{\textdaggerdbl}` | -| `\text{\textasciicircum}` | | `\text{\textdaggerdbl}` | -+------------------------------+-------------------------+------------------------------------+ -| $`` ` `` `` ` `` | $`\mathellipsis` | $`\angle` `\angle` | -| | `\mathellipsis` | | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textquoteleft}` | $`\text{\textellipsis}` | $`\measuredangle` `\measuredangle` | -| `text{\textquoteleft}` | `\text{\textellipsis}` | | -+------------------------------+-------------------------+------------------------------------+ -| $`\lq` `\lq` | $`\Box` `\Box` | $`\sphericalangle` | -| | | `\sphericalangle` | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textquoteright}` | $`\square` `\square` | $`\top` `\top` | -| `\text{\textquoteright}` | | | -+------------------------------+-------------------------+------------------------------------+ -| $`\rq` `\rq` | $`\blacksquare` | $`\bot` `\bot` | -| | `\blacksquare` | | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textquotedblleft}` | $`\triangle` | $`\Bot` `\Bot` | -| `\text{\textquotedblleft}` | `\triangle` | | -+------------------------------+-------------------------+------------------------------------+ -| $`"` `"` | $`\triangledown` | $`\$` `\$` | -| | `\triangledown` | | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textquotedblright}` | $`\triangleleft` | $`\text{\textdollar}` | -| `\text{\textquotedblright}` | `\triangleleft` | `\text{\textdollar}` | -+------------------------------+-------------------------+------------------------------------+ -| $`\colon` `\colon` | $`\triangleright` | $`\pounds` `\pounds` | -| | `\triangleright` | | -+------------------------------+-------------------------+------------------------------------+ -| $`\backprime` `\backprime` | $`\bigtriangledown` | $`\mathsterling` `\mathsterling` | -| | `\bigtriangledown` | | -+------------------------------+-------------------------+------------------------------------+ -| $`\prime` `\prime` | $`\bigtriangleup` | $`\text{\textsterling}` | -| | `\bigtriangleup` | `\text{\textsterling}` | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textless}` | $`\blacktriangle` | $`\yen` `\yen` | -| `\text{\textless}` | `\blacktriangle` | | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textgreater}` | $`\blacktriangledown` | $`\euro` `\euro` | -| `\text{\textgreater}` | `\blacktriangledown` | | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textbar}` | $`\blacktriangleleft` | $`\text{\texteuro}` | -| `\text{\textbar}` | `\blacktriangleleft` | `\text{\texteuro}` | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textbardbl}` | $`\blacktriangleright` | $`\degree` `\degree` | -| `\text{\textbardbl}` | `\blacktriangleright` | | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textbraceleft}` | $`\diamond` `\diamond` | $`\text{\textdegree}` | -| `\text{\textbraceleft}` | | `\text{\textdegree}` | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textbraceright}` | $`\Diamond` `\Diamond` | $`\mho` `\mho` | -| `\text{\textbraceright}` | | | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textbackslash}` | $`\lozenge` `\lozenge` | $`\diagdown` `\diagdown` | -| `\text{\textbackslash}` | | | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textvisiblespace}` | $`\blacklozenge` | $`\diagup` `\diagup` | -| `\text{\textvisiblespace}` | `\blacklozenge` | | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\P}` `\text{\P}` | $`\star` `\star` | $`\flat` `\flat` | -| or `\P` | | | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\S}` `\text{\S}` | $`\bigstar` `\bigstar` | $`\natural` `\natural` | -| or `\S` | | | -+------------------------------+-------------------------+------------------------------------+ -| $`\copyright` `\copyright` | $`\maltese` `\maltese` | $`\sharp` `\sharp` | -+------------------------------+-------------------------+------------------------------------+ -| $`\circledR` `\circledR` | $`\clubsuit` | $`\varclubsuit` `\varclubsuit` | -| | `\clubsuit` | | -+------------------------------+-------------------------+------------------------------------+ -| $`\circledS` `\circledS` | $`\diamondsuit` | $`\vardiamondsuit` | -| | `\diamondsuit` | `\vardiamondsuit` | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textregistered}` | $`\heartsuit` | $`\varheartsuit` `\varheartsuit` | -| `\text{\textregistered}` | `\heartsuit` | | -+------------------------------+-------------------------+------------------------------------+ -| $`\text{\textbullet}` | $`\spadesuit` | $`\varspadesuit` `\varspadesuit` | -| `\text{\textbullet}` | `\spadesuit` | | -+------------------------------+-------------------------+------------------------------------+ -| $`\smiley` `\smiley` | $`\female` `\female` | $`\male` `\male` | -+------------------------------+-------------------------+------------------------------------+ -| $`\standardstate` | $`\lightning` | $`\permil` `\permil` | -| `\standardstate` | `\lightning` | | -+------------------------------+-------------------------+------------------------------------+ - -Symbols in the _texvc_ extension - -+:-------------------------+:-------------------------------+:---------------------+ -| $`\clubs` `\clubs` | $`\hearts` `\hearts` | $`\sdot` `\sdot` | -+--------------------------+--------------------------------+----------------------+ -| $`\diamonds` `\diamonds` | $`\spades` `\spades` | $`\infin` `\infin` | -+--------------------------+--------------------------------+----------------------+ -| $`\bull` `\bull` | $`\text{\sect}` `\text{\sect}` | $`\Dagger` `\Dagger` | -+--------------------------+--------------------------------+----------------------+ - -Direct Input: § ¶ £ ¥ € ∇ ∞ · ∠ ∡ ∢ ♠ ♡ ♢ ♣ ♭ ♮ ♯ © ® ☺ ✓ ↯ … ⋮ ⋯ ⋱ ! ‼ - -## Units - -| Unit | Value | Unit | Value | -|:-----|:-------------|:-----|:--------------| -| em | CSS em | bp | 1/72​ inch | -| ex | CSS ex | pc | 12 pt | -| mu | 1/18 em | dd | 1238/1157​ pt | -| pt | 1/72.27 inch | cc | 14856/1157 pt | -| mm | 1 mm | nd | 685/642 pt | -| cm | 1 cm | nc | 1370/107​ pt | -| in | 1 inch | sp | 1/65536 pt | - -The effect of script level and font size: - -| Unit | textstyle
normal size | scriptscript | huge | -|:------:|:-----------------:|:-----------------------------------:|:--------------------------:| -|em or ex|$`\rule{1em}{1em}` |$`\scriptscriptstyle\rule{1em}{1em}` |$`\huge\rule{1em}{1em}` | -| mu |$`\rule{18mu}{18mu}`|$`\scriptscriptstyle\rule{18mu}{18mu}`|$`\huge\rule{18mu}{18mu}` | -| others |$`\rule{16pt}{16pt}`|$`\scriptscriptstyle\rule{16pt}{16pt}`|$`\huge\rule{16pt}{16pt}` | - -`em` and `ex` are affected by font size changes such as `\Large`, but they are not affected -by script level, so they will not change size in a fraction numerator or an -exponent. - -`mu` is affected by both script level and font size. - -The other units are absolute and are not affected by either script level or font size. - -
- -

Copyright © 2021, 2022 Ron Kok. -Released under the MIT License

- -
- -
- - - - - - - - - \ No newline at end of file diff --git a/package.json b/package.json deleted file mode 100644 index cb95070d..00000000 --- a/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "temml", - "version": "0.6.9", - "description": "TeX to MathML conversion in JavaScript.", - "main": "dist/temml.js", - "homepage": "https://temml.org", - "repository": { - "type": "git", - "url": "git://github.com/ronkok/Temml" - }, - "files": [ - "temml.js", - "src/", - "contrib/", - "dist/" - ], - "license": "MIT", - "devDependencies": { - "eslint": "^8.7.0", - "esm": "^3.2.25", - "rollup": "^2.66.1", - "terser": "^5.10.0" - }, - "scripts": { - "lint": "eslint temml.js src", - "unit-test": "node -r esm ./test/unit-test.js", - "visual-test": "node utils/buildTests.js", - "test": "yarn lint && node utils/buildTests.js && yarn unit-test", - "minify": "terser test/temml.js -o site/assets/temml.min.js -c -m && terser contrib/mhchem/mhchem.js -o site/assets/mhchem.min.js -c -m", - "build": "rollup --config ./utils/rollupConfig.js && yarn minify && node utils/insertPlugins.js", - "docs": "node utils/buildDocs.js", - "dist": "yarn build && node ./utils/copyfiles.js && terser contrib/auto-render/test/auto-render.js -o contrib/auto-render/dist/auto-render.min.js -c -m" - }, - "dependencies": { - "xml-formatter": "^2.4.0" - } -} diff --git a/site/assets/Asana-Math.woff2 b/site/assets/Asana-Math.woff2 deleted file mode 100644 index 9ca8cda86a6f8e28e433cdfb7a604d19765fc265..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 247716 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 F000V$6HEXA diff --git a/site/assets/GUST-FONT-LICENSE.txt b/site/assets/GUST-FONT-LICENSE.txt deleted file mode 100644 index 60b55002..00000000 --- a/site/assets/GUST-FONT-LICENSE.txt +++ /dev/null @@ -1,30 +0,0 @@ -% This is a preliminary version (2006-09-30), barring acceptance from -% the LaTeX Project Team and other feedback, of the GUST Font License. -% (GUST is the Polish TeX Users Group, http://www.gust.org.pl) -% -% For the most recent version of this license see -% http://www.gust.org.pl/fonts/licenses/GUST-FONT-LICENSE.txt -% or -% http://tug.org/fonts/licenses/GUST-FONT-LICENSE.txt -% -% This work may be distributed and/or modified under the conditions -% of the LaTeX Project Public License, either version 1.3c of this -% license or (at your option) any later version. -% -% Please also observe the following clause: -% 1) it is requested, but not legally required, that derived works be -% distributed only after changing the names of the fonts comprising this -% work and given in an accompanying "manifest", and that the -% files comprising the Work, as listed in the manifest, also be given -% new names. Any exceptions to this request are also given in the -% manifest. -% -% We recommend the manifest be given in a separate file named -% MANIFEST-.txt, where is some unique identification -% of the font family. If a separate "readme" file accompanies the Work, -% we recommend a name of the form README-.txt. -% -% The latest version of the LaTeX Project Public License is in -% http://www.latex-project.org/lppl.txt and version 1.3c or later -% is part of all distributions of LaTeX version 2006/05/20 or later. - diff --git a/site/assets/MANIFEST-Latin-Modern-Math.txt b/site/assets/MANIFEST-Latin-Modern-Math.txt deleted file mode 100644 index c84e1e5a..00000000 --- a/site/assets/MANIFEST-Latin-Modern-Math.txt +++ /dev/null @@ -1,60 +0,0 @@ -########################################################################### -############ The TeX Gyre Collection of Fonts ############ -########################################################################### - -Font: Latin Modern Math -Authors: Bogus\l{}aw Jackowski, Piotr Strzelczyk and Piotr Pianowski -Version: 1.959 -Date: 5 IX 2014 - -Copyright 2012--2014 for TeX Gyre math extensions by B. Jackowski, -P. Strzelczyk and P. Pianowski (on behalf of TeX Users Groups). - -This work can be freely used and distributed under -the GUST Font License (GFL -- see GUST-FONT-LICENSE.txt) -which is actually an instance of the LaTeX Project Public License -(LPPL -- see http://www.latex-project.org/lppl.txt). - -This work has the maintenance status "maintained". The Current Maintainer -of this work is Bogus\l{}aw Jackowski, Piotr Strzelczyk and Piotr Pianowski. - -This work consists of the files listed in this file. - -Below, in three sections required by the GUST Font License, -font names and file names specific for the Latin Modern Math -font are listed. - -NOTE: the names of the directories are not subject to the renaming -restrictions. - -1. Fonts whose names should be changed in derived works as requested - by clause 1 of GUST-FONT-LICENSE.txt - - 1.1 OTF menu names - Latin Modern Math - LatinModernMath-Regular - -2. Files whose names should be changed in derived works as requested - by clause 1 of GUST-FONT-LICENSE.txt - - 2.1 otf/latinmodern-math.otf - - 2.2 doc/MANIFEST-Latin-Modern-Math.txt - doc/README-Latin-Modern-Math.txt - doc/presentation-lmodern_math.pdf - doc/math-test.tex - doc/math-test-context.tex - doc/test-context-latinmodern_math.pdf - doc/test-context-latinmodern_math.tex - doc/test-lualatex-latinmodern_math.pdf - doc/test-lualatex-latinmodern_math.tex - doc/test-xelatex-latinmodern_math.pdf - doc/test-xelatex-latinmodern_math.tex - doc/test-word-tg_latinmodern_math.docx - doc/test-word-tg_latinmodern_math.pdf - -3. Files whose names need not be changed in derived works as requested - by clause 1 of GUST-FONT-LICENSE.txt - - doc/GUST-FONT-LICENSE.txt - doc/INSTALL.txt diff --git a/site/assets/README-Latin-Modern-Math.txt b/site/assets/README-Latin-Modern-Math.txt deleted file mode 100644 index 30c8e602..00000000 --- a/site/assets/README-Latin-Modern-Math.txt +++ /dev/null @@ -1,92 +0,0 @@ -########################################################################### -############ Latin Modern Collection of Fonts ############ -########################################################################### - -Font: Latin Modern Math -Authors: Bogus\l{}aw Jackowski, Piotr Strzelczyk and Piotr Pianowski -Version: 1.959 -Date: 5 IX 2014 - -License: - % Copyright 2012--2014 for the Latin Modern math extensions by B. Jackowski, - % P. Strzelczyk and P. Pianowski (on behalf of TeX Users Groups). - % - % This work can be freely used and distributed under - % the GUST Font License (GFL -- see GUST-FONT-LICENSE.txt) - % which is actually an instance of the LaTeX Project Public License - % (LPPL -- see http://www.latex-project.org/lppl.txt). - % - % This work has the maintenance status "maintained". The Current Maintainer - % of this work is Bogus\l{}aw Jackowski, Piotr Strzelczyk and Piotr Pianowski. - % - % This work consists of the files listed - % in the MANIFEST-Latin-Modern-Math.txt file. - -########################################################################### -############ A BRIEF DESCRIPTION OF THE FONT ############ -########################################################################### - -Latin Modern Math is a math companion for the Latin Modern family -of fonts (see http://www.gust.org.pl/projects/e-foundry/latin-modern) in -the OpenType format. - -The math OTF fonts should contain a special table, MATH, described in the -confidential Microsoft document "The MATH table and OpenType Features -for Math Processing". Moreover, they should contain a broad collection -of special characters (see "Draft Unicode Technical Report #25. -UNICODE SUPPORT FOR MATHEMATICS" by Barbara Beeton, Asmus Freytag, -and Murray Sargent III). In particular, math OTF fonts are expected -to contain the following scripts: a basic serif script (regular, bold, -italic and bold italic), a calligraphic script (regular and bold), -a double-struck script, a fraktur script (regular and bold), a sans-serif -script (regular, bold, oblique and bold oblique), and a monospaced script. - -The basic script is, obviously, Latin Modern. Some scripts, however, -are borrowed from other fonts (the current selection, however, may -be subject to change), belonging, however, to the "TeX circle": - - * the calligraphic and fraktur alphabets are excerpted from the renowned - Euler family (http://en.wikipedia.org/wiki/AMS_Euler); - - * the double struck script is excerpted from Alan Jeffrey's bbold font - (http://www.tug.org/texlive/Contents/live/texmf-dist/doc/latex/bbold/bbold.pdf) - - * the sans serif and monospaced alphabets are excerpted from - the Latin Modern Sans and Latin Modern Mono fonts - (http://www.gust.org.pl/projects/e-foundry/latin-modern); - sans serif bold Greek symbols (required by the already mentioned - "Unicode Technical Report #25") were prepared using D.E. Knuth's - font sources with some manual tuning - -The main math component, that is, the math extension, was programmed -from scratch, with an attempt to retain the visual compatiblility -with the original D.E. Knuth's fonts. In particular, all symbols -(with a few exceptions) appearing in the D.E. Knuth's "canonical" fonts -have the same width (rounded) as the corresponding Knuthian ones. - -Note that the members of all the mentioned alphabets, except -the main roman alphabet, should be considerd symbols, not letters; -symbols are not expected to occur in a text stream; instead, -they are expected to appear lonely, perhaps with some embellishments -like subscripts, superscripts, primes, dots above and below, etc. - -To produce the font, MetaType1 and the FontForge library were used: -the Type1 PostScript font containing all relevant characters was -generated with the MetaType1 engine, and the result was converted -into the OTF format with all the necessary data structures by -a Python script employing the FontForge library. - -Recent changes (ver. 1.958 --> ver. 1.959) comprised -mainly interline settings in OTF tables (HHEA and -OS/2) and the correction of unicode slots assigned to -the contour integrals (glyphs `clockwise contour -integral', u+2232, and `anticlockwise contour -integral', u+2233, used to have swapped slots). - - * * * - -The TeX Gyre Math Project was launched and is supported by -TeX USERS GROUPS (CS TUG, DANTE eV, GUST, NTG, TUG India, TUG, UK TUG). -Hearty thanks to the representatives of these groups and also -to all people who helped with their work, comments, ideas, -remarks, bug reports, objections, hints, consolations, etc. diff --git a/site/assets/STIXTwoMath-Regular.woff2 b/site/assets/STIXTwoMath-Regular.woff2 deleted file mode 100644 index 3b97c9c897e5f52c544eaf4e89ebb15c4f2c1c22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 551908 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%0AR_4GRx4Aqn`o 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

    I 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�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 z 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 O(ugTOJ+*uf)&l_48RR|y diff --git a/site/assets/Temml-Asana.css b/site/assets/Temml-Asana.css deleted file mode 100644 index f792d0ff..00000000 --- a/site/assets/Temml-Asana.css +++ /dev/null @@ -1,57 +0,0 @@ -/* -Asana Math is released under the SIL Open Font License. See the files in this -directory for details. The font can be obtained from several TeX distributions -or package managers. The font does not seem to have a corresponding "non-MATH" -font, it is recommended to use a Palatino-like font for the surrounding text. - -The WOFF fonts have been obtained from -http://mirrors.ctan.org/fonts/ -*/ - -@font-face { - font-family: Asana Math; - src: local('Asana Math'), local('Asana-Math'), - url('./Asana-Math.woff2'); -} - -math { - font-style: normal; - font-weight: normal; - line-height: normal; - font-size-adjust: none; - text-indent: 0; - text-transform: none; - letter-spacing: normal; - word-wrap: normal; - direction: ltr; -} - -math * { - border-color: currentColor; -} - -mtext { - font-family: Asana Math; -} - -math { - font-family: Asana Math; -} - -*.mathcal { - font-feature-settings: 'salt'; -} - -.oldstylenums { - font-feature-settings: 'onum'; -} - -/* AMS environment auto-numbering via CSS counter. */ -.tml-eqn::before { - counter-increment: tmlEqnNo; - content: "(" counter(tmlEqnNo) ")"; -} - -body { - counter-reset: tmlEqnNo; -} diff --git a/site/assets/Temml-Latin-Modern.css b/site/assets/Temml-Latin-Modern.css deleted file mode 100644 index 15fd2398..00000000 --- a/site/assets/Temml-Latin-Modern.css +++ /dev/null @@ -1,68 +0,0 @@ -/* -The Latin Modern fonts are released under the GUST font license, which is -legally equivalent to the LaTeX Project Public License. See the files in this -directory for details. The fonts can be obtained from several TeX distributions -or package managers. - -The Latin Modern WOFF font has been obtained from -http://www.gust.org.pl/projects/e-foundry/ - -The Temml.woff2 is a clone of KaTeX_Script-Regular, except that the code points -have been changed from ASCII to Unicode Mathematical Alphanumeric Symbols Script capitals, -Unicode range 1D49C to 1D4B5. -*/ - -@font-face { - font-family: 'Temml'; - src: url('Temml.woff2') format('woff2'); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: Latin Modern Math; - src: url('./latinmodernmath.woff2'); -} - -math { - font-style: normal; - font-weight: normal; - line-height: normal; - font-size-adjust: none; - text-indent: 0; - text-transform: none; - letter-spacing: normal; - word-wrap: normal; - direction: ltr; -} - -math * { - border-color: currentColor; -} - -.latin-modern math { - font-family: "Latin Modern Math", "Times New Roman", math; -} - -math { - font-family: Latin Modern Math; -} - -*.mathscr { - font-family: "Temml"; -} - -.oldstylenums { - font-family: "Cambria Math", math; - font-feature-settings: 'onum'; -} - -/* AMS environment auto-numbering via CSS counter. */ -.tml-eqn::before { - counter-increment: tmlEqnNo; - content: "(" counter(tmlEqnNo) ")"; -} - -body { - counter-reset: tmlEqnNo; -} diff --git a/site/assets/Temml-Local.css b/site/assets/Temml-Local.css deleted file mode 100644 index 42c98143..00000000 --- a/site/assets/Temml-Local.css +++ /dev/null @@ -1,47 +0,0 @@ -/* -Temml.woff2 is a clone of KaTeX_Script-Regular, except that the code points -have been changed from ASCII to Unicode Mathematical Alphanumeric Symbols Script capitals, -Unicode range 1D49C to 1D4B5. -*/ - -@font-face { - font-family: 'Temml'; - src: url('Temml.woff2') format('woff2'); - font-weight: normal; - font-style: normal; -} - -math { - font-family: "Cambria Math", "Times New Roman", math; - font-style: normal; - font-weight: normal; - line-height: normal; - font-size-adjust: none; - text-indent: 0; - text-transform: none; - letter-spacing: normal; - word-wrap: normal; - direction: ltr; -} - -math * { - border-color: currentColor; -} - -math .mathscr { - font-family: "Temml"; -} - -math .oldstylenums { - font-feature-settings: 'onum'; -} - -/* AMS environment auto-numbering via CSS counter. */ -.tml-eqn::before { - counter-increment: tmlEqnNo; - content: "(" counter(tmlEqnNo) ")"; -} - -body { - counter-reset: tmlEqnNo; -} diff --git a/site/assets/Temml-STIX2.css b/site/assets/Temml-STIX2.css deleted file mode 100644 index 7b0dbbc1..00000000 --- a/site/assets/Temml-STIX2.css +++ /dev/null @@ -1,56 +0,0 @@ -/* -XITS is released under the SIL Open Font License. -See https://github.com/stipub/stixfonts/blob/master/OFL.txt details. - -The WOFF font has been obtained from -https://github.com/stipub/stixfonts -*/ - -@font-face { - font-family: STIX2; - src: local('STIXTwoMath-Regular'), - url('./STIXTwoMath-Regular.woff2'); -} - -math { - font-style: normal; - font-weight: normal; - line-height: normal; - font-size-adjust: none; - text-indent: 0; - text-transform: none; - letter-spacing: normal; - word-wrap: normal; - direction: ltr; -} - -math * { - border-color: currentColor; -} - -mtext { - font-family: STIX2; -} - -math { - font-family: STIX2, math; -} - -*.mathscr { - font-feature-settings: 'ss01'; -} - -.oldstylenums { - font-family: "Cambria Math", math; - font-feature-settings: 'onum'; -} - -/* AMS environment auto-numbering via CSS counter. */ -.tml-eqn::before { - counter-increment: tmlEqnNo; - content: "(" counter(tmlEqnNo) ")"; -} - -body { - counter-reset: tmlEqnNo; -} diff --git a/site/assets/Temml-XITS.css b/site/assets/Temml-XITS.css deleted file mode 100644 index 32421750..00000000 --- a/site/assets/Temml-XITS.css +++ /dev/null @@ -1,63 +0,0 @@ -/* -XITS is released under the SIL Open Font License. See the files in this -directory for details. The font can be obtained from several TeX distributions -or package managers. - -The WOFF fonts have been obtained from -http://mirrors.ctan.org/fonts/ -*/ - -@font-face { - font-family: XITS Math; - src: local('XITS Math'), local('XITSMath-Regular'), - url('./xits-math.woff2'); -} -@font-face { - font-family: XITS Math; - src: local('XITS Math Bold'), local('XITSMath-Bold'), - url('./xits-mathbold.woff2'); - font-weight: bold; -} - -math { - font-style: normal; - font-weight: normal; - line-height: normal; - font-size-adjust: none; - text-indent: 0; - text-transform: none; - letter-spacing: normal; - word-wrap: normal; - direction: ltr; -} - -math * { - border-color: currentColor; -} - -mtext { - font-family: XITS; -} - -math { - font-family: XITS Math, math; -} - -*.mathcal { - font-feature-settings: 'ss01'; -} - -.oldstylenums { - font-family: "Cambria Math", math; - font-feature-settings: 'onum'; -} - -/* AMS environment auto-numbering via CSS counter. */ -.tml-eqn::before { - counter-increment: tmlEqnNo; - content: "(" counter(tmlEqnNo) ")"; -} - -body { - counter-reset: tmlEqnNo; -} diff --git a/site/assets/Temml.woff2 b/site/assets/Temml.woff2 deleted file mode 100644 index 367dda777ed32ced5ecc8a6e0c56a957b5a05da1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11744 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 C0;jV8 diff --git a/site/assets/XITS-FAQ.txt b/site/assets/XITS-FAQ.txt deleted file mode 100644 index edb55c61..00000000 --- a/site/assets/XITS-FAQ.txt +++ /dev/null @@ -1,369 +0,0 @@ -OFL FAQ - Frequently Asked Questions about the SIL Open Font License (OFL) -Version 1.1-update2 - 23 August 2010 -(See http://scripts.sil.org/OFL for updates) - - -CONTENTS OF THIS FAQ -1 USING AND DISTRIBUTING FONTS LICENSED UNDER THE OFL -2 USING OFL FONTS FOR WEB PAGES AND ONLINE WEBFONT SERVICES -3 MODIFYING OFL-LICENSED FONTS -4 LICENSING YOUR ORIGINAL FONTS UNDER THE OFL -5 CHOOSING RESERVED FONT NAMES -6 ABOUT THE FONTLOG -7 MAKING CONTRIBUTIONS TO OFL PROJECTS -8 ABOUT THE LICENSE ITSELF -9 ABOUT SIL INTERNATIONAL -APPENDIX A - FONTLOG EXAMPLE - - -1 USING AND DISTRIBUTING FONTS LICENSED UNDER THE OFL - -1.1 Can I use the fonts for a book or other print publication? -Yes. You can mention the font and author in the book's colophon if you wish, but that is not required. - -1.2 Can the fonts be included with Free/Libre and Open Source Software collections such as GNU/Linux and BSD distributions? -Yes! Fonts licensed under the OFL can be freely included alongside other software under FLOSS (Free/Libre and Open Source Software) licenses. Since fonts are typically aggregated with, not merged into, existing software, there is little need to be concerned about incompatibility with existing software licenses. You may also repackage the fonts and the accompanying components in a .rpm or .deb package and include them in distribution CD/DVDs and online repositories. (Also see section 5.9 about rebuilding from source.) - -1.3 I want to distribute the fonts with my program. Does this mean my program also has to be Free/Libre and Open Source Software? -No. Only the portions based on the Font Software are required to be released under the OFL. The intent of the license is to allow aggregation or bundling with software under restricted licensing as well. - -1.4 Can I sell a software package that includes these fonts? -Yes, you can do this with both the Original Version and a Modified Version of the fonts. Examples of bundling made possible by the OFL would include: word processors, design and publishing applications, training and educational software, games and entertainment software, mobile device applications, etc. - -1.5 Can I include the fonts on a CD of freeware or commercial fonts? -Yes, as long some other font or software is also on the disk, so the OFL font is not sold by itself. - -1.6 Why won't the OFL let me sell the fonts alone? -The intent is to keep people from making money by simply redistributing the fonts. The only people who ought to profit directly from the fonts should be the original authors, and those authors have kindly given up potential direct income to distribute their fonts under the OFL. Please honour and respect their contribution! - -1.7 What about sharing OFL fonts with friends on a CD, DVD or USB stick? -You are very welcome to share open fonts with friends, family and colleagues through removable media. Just remember to include the full font package, including any copyright notices and licensing information as available in OFL.txt. In the case where you sell the font, it has to come bundled with software. - -1.8 Can I host the fonts on a web site for others to use? -Yes, as long as you make the full font package available. In most cases it may be best to point users to the main site that distributes the Original Version so they always get the most recent stable and complete version. See also discussion of webfonts in Section 2. - -1.9 Can I host the fonts on a server for use over our internal network? -Yes. If the fonts are transferred from the server to the client computer by means that allow them to be used even if the computer is no longer attached to the network, the full package (copyright notices, licensing information, etc.) should be included. - -1.10 Does the full OFL license text always need to accompany the font? -The only situation in which an OFL font can be distributed without the text of the OFL (either in a separate file or in font metadata), is when a font is embedded in a document or bundled within a program. In the case of metadata included within a font, it is legally sufficient to include only a link to the text of the OFL on http://scripts.sil.org/OFL, but we strongly recommend against this. Most modern font formats include metadata fields that will accept the full OFL text, and full inclusion increases the likelihood that users will understand and properly apply the license. - -1.11 What do you mean by 'embedding'? How does that differ from other means of distribution? -By 'embedding' we mean inclusion of the font in a document or file in a way that makes extraction (and redistribution) difficult or clearly discouraged. In many cases the names of embedded fonts might also not be obvious to those reading the document, the font data format might be altered, and only a subset of the font - only the glyphs required for the text - might be included. Any other means of delivering a font to another person is considered 'distribution', and needs to be accompanied by any copyright notices and licensing information available in OFL.txt. - -1.12 So can I embed OFL fonts in my document? -Yes, either in full or a subset. The restrictions regarding font modification and redistribution do not apply, as the font is not intended for use outside the document. - -1.13 Does embedding alter the license of the document itself? -No. Referencing or embedding an OFL font in any document does not change the license of the document itself. The requirement for fonts to remain under the OFL does not apply to any document created using the fonts and their derivatives. Similarly, creating any kind of graphic using a font under OFL does not make the resulting artwork subject to the OFL. - -1.14 If OFL fonts are extracted from a document in which they are embedded (such as a PDF file), what can be done with them? Is this a risk to author(s)? -The few utilities that can extract fonts embedded in a PDF will typically output limited amounts of outlines - not a complete font. To create a working font from this method is much more difficult and time consuming than finding the source of the original OFL font. So there is little chance that an OFL font would be extracted and redistributed inappropriately through this method. Even so, copyright laws address any misrepresentation of authorship. All Font Software released under the OFL and marked as such by the author(s) is intended to remain under this license regardless of the distribution method, and cannot be redistributed under any other license. We strongly discourage any font extraction - we recommend directly using the font sources instead - but if you extract font outlines from a document, please be considerate: use your common sense and respect the work of the author(s) and the licensing model. - -1.15 What about distributing fonts with a document? Within a compressed folder structure? Is it distribution, bundling or embedding? -Certain document formats may allow the inclusion of an unmodified font within their file structure which consists of a compressed folder containing the various resources forming the document (such as pictures and thumbnails). Including fonts within such a structure is understood as being different from embedding but rather similar to bundling (or mere aggregation) which the license explicitly allows. In this case the font is conveyed unchanged whereas embedding a font usually transforms it from the original format. The OFL does not allow anyone to extract the font from such a structure to then redistribute it under another license. The explicit permission to redistribute and embed does not cancel the requirement for the Font Software to remain under the license chosen by its author(s). - -1.16 What about ebooks shipping with open fonts? -The requirements differ depending on whether the fonts are linked, embedded or distributed (bundled or aggregated). Some ebook formats use web technologies to do font linking via @font-face, others are designed for font embedding, some use fonts distributed with the document or reading software, and a few rely solely on the fonts already present on the target system. The license requirements depend on the type of inclusion as discussed in 1.15. - -1.17 Can Font Software released under the OFL be subject to URL-based access restrictions methods or DRM (Digital Rights Management) mechanisms? -Yes, but these issues are out-of-scope for the OFL. The license itself neither encourages their use nor prohibits them since such mechanisms are not implemented in the components of the Font Software but through external software. Such restrictions are put in place for many different purposes corresponding to various usage scenarios. One common example is to limit potentially dangerous cross-site scripting attacks. However, in the spirit of libre/open fonts and unrestricted writing systems, we strongly encourage open sharing and reuse of OFL fonts, and the establishment of an environment where such restrictions are unnecessary. Note that whether you wish to use such mechanisms or you prefer not to, you must still abide by the rules set forth by the OFL when using fonts released by their authors under this license. Derivative fonts must be licensed under the OFL, even if they are part of a service for which you charge fees and/or for which access to source code is restricted. You may not sell the fonts on their own - they must be part of a larger software package, bundle or subscription plan. For example, even if the OFL font is distributed in a software package or via an online service using a DRM mechanism, the user would still have the right to extract that font, use, study, modify and redistribute it under the OFL. - -1.18 I've come across a font released under the OFL. How can I easily get more information about the Original Version? How can I know where it stands compared to the Original Version or other Modified Versions? -Consult the copyright statement(s) in the license for ways to contact the original authors. Consult the FONTLOG for information on how the font differs from the Original Version, and get in touch with the various contributors via the information in the acknowledgement section. Please consider using the Original Versions of the fonts whenever possible. - -1.19 What do you mean in condition 4? Can you provide examples of abusive promotion / endorsement / advertisement vs. normal acknowledgement? -The intent is that the goodwill and reputation of the author(s) should not be used in a way that makes it sound like the original author(s) endorse or approve of a specific Modified Version or software bundle. For example, it would not be right to advertise a word processor by naming the author(s) in a listing of software features, or to promote a Modified Version on a web site by saying "designed by ...". However, it would be appropriate to acknowledge the author(s) if your software package has a list of people who deserve thanks. We realize that this can seem to be a grey area, but the standard used to judge an acknowledgement is that if the acknowledgement benefits the author(s) it is allowed, but if it primarily benefits other parties, or could reflect poorly on the author(s), then it is not. - - -2 USING OFL FONTS FOR WEBPAGES AND ONLINE WEBFONT SERVICES - -2.1 Can I make webpages using these fonts? -Yes! Go ahead! Using CSS (Cascading Style Sheets) is recommended. Your three best options: -- referring directly in your stylesheet to open fonts which may be available on the user's system -- providing links to download the full package of the font - either from your own website or from elsewhere - so users can install it themselves -- using @font-face to distribute the font directly to browsers. This is recommended and explicitly allowed by the licensing model because it is distribution. The font file itself is distributed with other components of the webpage. It is not embedded in the webpage but referenced through a web address which will cause the browser to retrieve and use the corresponding font to render the webpage (see 1.11 and 1.15 for details related to embedding fonts into documents). As you take advantage of the @font-face cross-platform standard, be aware that webfonts are often tuned for a web environment and not intended for installation and use outside a browser. The reasons in favour of using webfonts are to allow design of dynamic text elements instead of static graphics, to make it easier for content to be localized and translated, indexed and searched, and all this with cross-platform open standards without depending on restricted extensions or plugins. You should check the CSS cascade (the order in which fonts are being called or delivered to your users) when testing. - -2.2 Can I make and use WOFF (Web Open Font Format) versions of OFL fonts? -Yes, but you need to be careful. A change in font format normally is considered modification, and Reserved Font Names (RFNs) cannot be used. Because of the design of the WOFF format, however, it is possible to create a WOFF version that is not considered modification, and so would not require a name change. You are allowed to create, use and distribute a WOFF version of an OFL font without changing the font name, but only if: - -- the original font data remains unchanged except for WOFF compression, and -- WOFF-specific metadata is either omitted altogether or present and includes, unaltered, the contents of all equivalent metadata in the original font. - -If the original font data or metadata is changed, or the WOFF-specific metadata is incomplete, the font must be considered a Modified Version, the OFL restrictions would apply and the name of the font must be changed: any RFNs cannot be used and copyright notices and licensing information must be included and cannot be deleted or modified. You must come up with a unique name - we recommend one corresponding to your domain or your particular web application. Be aware that only the original author(s) can use RFNs. This is to prevent collisions between a derivative tuned to your audience and the original upstream version and so to reduce confusion. - -Please note that most WOFF conversion tools and online services do not meet the two requirements listed above, and so their output must be considered a Modified Version. So be very careful and check to be sure that the tool or service you're using is compressing unchanged data and completely and accurately reflecting the original font metadata. - -2.3 What about other webfont formats such as EOT/EOTLite/CWT/etc.? -In most cases these formats alter the original font data more than WOFF, and do not completely support appropriate metadata, so their use must be considered modification and RFNs may not be used. - -2.4 Can I make OFL fonts available through webfont online services? -Yes, you are welcome to include OFL fonts in online webfont services as long as you properly meet all the conditions of the license. The origin and open status of the font should be clear among the other fonts you are hosting. Authorship, copyright notices and license information must be sufficiently visible to your users or subscribers so they know where the font comes from and the rights granted by the author(s). Make sure the font file contains the needed copyright notice(s) and licensing information in its metadata. Please double-check the accuracy of every field to prevent contradictory information. Other font formats, including EOT/EOTLite/CWT and superior alternatives like WOFF, already provide fields for this information. Remember that if you modify the font within your library or convert it to another format for any reason the OFL restrictions apply and you need to change the names accordingly. Please respect the author's wishes as expressed in the OFL and do not misrepresent original designers and their work. Don't lump quality open fonts together with dubious freeware or public domain fonts. Consider how you can best work with the original designers and foundries, support their efforts and generate goodwill that will benefit your service. (See 1.17 for details related to URL-based access restrictions methods or DRM mechanisms). - -2.5 Can I make and publish CMS themes or templates that use OFL fonts? Can I include the fonts themselves in the themes or templates? Can I sell the whole package? -Yes, you are very welcome to integrate open fonts into themes and templates for your preferred CMS and make them more widely available. Be aware that you can only sell the fonts and your CMS add-on as part of a software bundle. (See 1.4 for details and examples about selling bundles). - -2.6 Some webfont formats and services provide ways of "optimising" the font for a particular website or web application; is that allowed? -Yes, it is permitted, but remember that these optimised versions are Modified Versions and so must follow OFL requirements like appropriate renaming. Also you need to bear in mind the other important parameters beyond compression, speed and responsiveness: you need to consider the audience of your particular website or web application, as choosing some optimisation parameters may turn out to be less than ideal for them. Subsetting by removing certain glyphs or features may seriously limit functionality of the font in various languages used by your users. It may also introduce degradation of quality in the rendering or specific bugs on the various platforms compared to the original font. In other words, remember that one person's optimised font may be another person's missing feature. Various advanced typographic features are also available through CSS and may provide the desired effects without the need to modify the font. - - -3 MODIFYING OFL-LICENSED FONTS - -3.1 Can I change the fonts? Are there any limitations to what things I can and cannot change? -You are allowed to change anything, as long as such changes do not violate the terms of the license. In other words, you are not allowed to remove the copyright statement(s) from the font, but you could put additional information into it that covers your contribution. - -3.2 I have a font that needs a few extra glyphs - can I take them from an OFL licensed font and copy them into mine? -Yes, but if you distribute that font to others it must be under the OFL, and include the information mentioned in condition 2 of the license. - -3.3 Can I charge people for my additional work? In other words, if I add a bunch of special glyphs and/or OpenType/Graphite code, can I sell the enhanced font? -Not by itself. Derivative fonts must be released under the OFL and cannot be sold by themselves. It is permitted, however, to include them in a larger software package (such as text editors, office suites or operating systems), even if the larger package is sold. In that case, you are strongly encouraged, but not required, to also make that derived font easily and freely available outside of the larger package. - -3.4 Can I pay someone to enhance the fonts for my use and distribution? -Yes. This is a good way to fund the further development of the fonts. Keep in mind, however, that if the font is distributed to others it must be under the OFL. You won't be able to recover your investment by exclusively selling the font, but you will be making a valuable contribution to the community. Please remember how you have benefited from the contributions of others. - -3.5 I need to make substantial revisions to the font to make it work with my program. It will be a lot of work, and a big investment, and I want to be sure that it can only be distributed with my program. Can I restrict its use? -No. If you redistribute a Modified Version of the font it must be under the OFL. You may not restrict it in any way beyond what the OFL permits and requires. This is intended to ensure that all released improvements to the fonts become available to everyone. But you will likely get an edge over competitors by being the first to distribute a bundle with the enhancements. Again, please remember how you have benefited from the contributions of others. - -3.6 Do I have to make any derivative fonts (including extended source files, build scripts, documentation, etc.) publicly available? -No, but please consider sharing your improvements with others. You may find that you receive in return more than what you gave. - -3.7 If a trademark is claimed in the OFL font, does that trademark need to remain in modified fonts? -Yes, any trademark notices must remain in any derivative fonts to respect trademark laws, but you may add any additional trademarks you claim, officially registered or not. For example if an OFL font called "Foo" contains a notice that "Foo is a trademark of Acme", then if you rename the font to "Bar" when creating a Modified Version, the new trademark notice could say "Foo is a trademark of Acme Inc. - Bar is a trademark of Roadrunner Technologies Ltd.". Trademarks work alongside the OFL and are not subject to the terms of the licensing agreement. Please refer to the appropriate trademark laws. - - -4 LICENSING YOUR ORIGINAL FONTS UNDER THE OFL - -4.1 Can I use the SIL OFL for my own fonts? -Yes! We heartily encourage everyone to use the OFL to distribute their own original fonts. It is a carefully constructed license that allows great freedom along with enough artistic integrity protection for the work of the authors as well as clear rules for other contributors and those who redistribute the fonts. The licensing model is used successfully by various organisations, both for-profit and not-for-profit, to release fonts of varying levels of scope and complexity. - -4.2 What do I have to do to apply the OFL to my font? -If you want to release your fonts under the OFL, we recommend you do the following: - -4.2.1 Put your copyright and Reserved Font Names information at the beginning of the main OFL.txt file in place of the dedicated placeholders. Include this file in your release package. - -4.2.2 Put your copyright and the OFL text with Reserved Font Names into your font files (the copyright and license fields). A link to the OFL text on the OFL web site is an acceptable (but not recommended) alternative. Also add this information to any other components (build scripts, glyph databases, documentation, test files, etc). Depending on the format of your fonts and sources, you can use template human-readable headers or machine-readable metadata. - -4.2.3 Write an initial FONTLOG.txt for your font and include it in the release package. - -4.2.4 Include the relevant practical documentation on the license by including the OFL-FAQ.txt in your package. - -4.3 Will you make my font OFL for me? -We won't do the work for you. We can, however, try to answer your questions, unfortunately we do not have the resources to review and check your font packages for correct use of the OFL. - -4.4 Will you distribute my OFL font for me? -No, although if the font is of sufficient quality and general interest we may include a link to it on our partial list of OFL fonts on the OFL web site. You may wish to consider other open font catalogs or hosting services, such as the Unifont Font Guide (http://unifont.org/fontguide), The League of Movable Type (http://theleagueofmovabletype.com), Kernest (http://kernest.com/) or the Open Font Library (http://openfontlibrary.org/), which despite the name has no direct relationship to the OFL or SIL. We do not endorse any particular catalog or hosting service - it is your responsibility to determine if the service is right for you. - -4.5 Why should I use the OFL for my fonts? -- to meet needs for fonts that can be modified to support minority languages -- to provide a legal and clear way for people to respect your work but still use it (and reduce piracy) -- to involve others in your font project -- to enable your fonts to be expanded with new weights and improved writing system/language support -- to allow more technical font developers to add features to your design (such as OpenType and Graphite support) -- to renew the life of an old font lying on your hard drive with no business model -- to allow your font to be included in Libre Software operating systems like Ubuntu -- to give your font world status and wide, unrestricted distribution -- to educate students about quality typeface and font design -- to expand your test base and get more useful feedback -- to extend your reach to new markets when users see your metadata and go to your website -- to get your font more easily into one of the webfont online services -- to attract attention for your commercial fonts -- to make money through webfont services -- to make money by bundling fonts with applications -- to make money adjusting and extending existing open fonts -- to get a better chance that foundations/NGOs/charities/companies who commission fonts will pick you -- to be part of a sharing design and development community -- to give back and contribute to a growing body of font sources - - -5 CHOOSING RESERVED FONT NAMES - -5.1 What are Reserved Font Names? -These are font names, or portions of font names, that the author has chosen to reserve for use only with the Original Version of the font, or for Modified Version(s) created by the original author. - -5.2 Why can't I use the Reserved Font Names in my derivative font names? I'd like people to know where the design came from. -The best way to acknowledge the source of the design is to thank the original authors and any other contributors in the files that are distributed with your revised font (although no acknowledgement is required). The FONTLOG is a natural place to do this. Reserved Font Names ensure that the only fonts that have the original names are the unmodified Original Versions. This allows designers to maintain artistic integrity while allowing collaboration to happen. It eliminates potential confusion and name conflicts. When choosing a name, be creative and avoid names that reuse almost all the same letters in the same order or sound like the original. It will help everyone if Original Versions and Modified Versions can easily be distinguished from one another and from other derivatives. Any substitution and matching mechanism is outside the scope of the license. - -5.3 What do you mean by "primary name as presented to the user"? Are you referring to the font menu name? -Yes, this applies to the font menu name and other mechanisms that specify a font in a document. It would be fine, however, to keep a text reference to the original fonts in the description field, in your modified source file or in documentation provided alongside your derivative as long as no one could be confused that your modified source is the original. But you cannot use the Reserved Font Names in any way to identify the font to the user (unless the Copyright Holder(s) allow(s) it through a separate agreement). Users who install derivatives (Modified Versions) on their systems should not see any of the original Reserved Font Names in their font menus, for example. Again, this is to ensure that users are not confused and do not mistake one font for another and so expect features only another derivative or the Original Version can actually offer. - -5.4 Am I not allowed to use any part of the Reserved Font Names? -You may not use individual words from the Reserved Font Names, but you would be allowed to use parts of words, as long as you do not use any word from the Reserved Font Names entirely. We do not recommend using parts of words because of potential confusion, but it is allowed. For example, if "Foobar" was a Reserved Font Name, you would be allowed to use "Foo" or "bar", although we would not recommend it. Such an unfortunate choice would confuse the users of your fonts as well as make it harder for other designers to contribute. - -5.5 So what should I, as an author, identify as Reserved Font Names? -Original authors are encouraged to name their fonts using clear, distinct names, and only declare the unique parts of the name as Reserved Font Names. For example, the author of a font called "Foobar Sans" would declare "Foobar" as a Reserved Font Name, but not "Sans", as that is a common typographical term, and may be a useful word to use in a derivative font name. Reserved Font Names should also be single words. A font called "Flowing River" should have Reserved Font Names "Flowing" and "River", not "Flowing River". You also need to be very careful about reserving font names which are already linked to trademarks (whether registered or not) which you do not own. - -5.6 Do I, as an author, have to identify any Reserved Font Names? -No, but we strongly encourage you to do so. This is to avoid confusion between your work and Modified Versions. - -5.7 Are any names (such as the main font name) reserved by default? -No. That is a change to the license as of version 1.1. If you want any names to be Reserved Font Names, they must be specified after the copyright statement(s). - -5.8 Is there any situation in which I can use Reserved Font Names for a Modified Version? -The Copyright Holder(s) can give certain trusted parties the right to use any of the Reserved Font Names through separate written agreements. For example, even if "Foobar" is a RFN, you could write up an agreement to give company "XYZ" the right to distribute a modified version with a name that includes "Foobar". This allows for freedom without confusion. - -5.9 Do font rebuilds require a name change? Do I have to change the name of the font when my packaging workflow includes a full rebuild from source? -Yes, all rebuilds which change the font data and the smart code are Modified Versions and the requirements of the OFL apply: you need to respect what the Author(s) have chosen in terms of Reserved Font Names. However if a package (or installer) is simply a wrapper or a compressed structure around the final font - leaving them intact on the inside - then no name change is required. Please get in touch with the author(s) and copyright holder(s) to inquire about the presence of font sources beyond the final font file(s) and the recommended build path. That build path may very well be non-trivial and hard to reproduce accurately by the maintainer. If a full font build path is made available by the upstream author(s) please be aware that any regressions and changes you may introduce when doing a rebuild for packaging purposes is your responsibility as a package maintainer since you are effectively creating a separate branch. You should make it very clear to your users that your rebuilt version is not the canonical one from upstream. - -5.10 Can I add other Reserved Font Names when making a derivative font? -Yes. List your additional Reserved Font Names after your additional copyright statement, as indicated with example placeholders at the top of the OFL.txt file. Be sure you do not remove any exiting RFNs but only add your own. - - -6 ABOUT THE FONTLOG - -6.1 What is this FONTLOG thing exactly? -It has three purposes: 1) to provide basic information on the font to users and other developers, 2) to document changes that have been made to the font or accompanying files, either by the original authors or others, and 3) to provide a place to acknowledge authors and other contributors. Please use it! - -6.2 Is the FONTLOG required? -It is not a requirement of the license, but we strongly recommend you have one. - -6.3 Am I required to update the FONTLOG when making Modified Versions? -No, but users, designers and other developers might get very frustrated with you if you don't. People need to know how derivative fonts differ from the original, and how to take advantage of the changes, or build on them. There are utilities that can help create and maintain a FONTLOG, such as the FONTLOG support in FontForge. - -6.4 What should the FONTLOG look like? -It is typically a separate text file (FONTLOG.txt), but can take other formats. It commonly includes these four sections: - -- brief header describing the FONTLOG itself and name of the font family -- Basic Font Information - description of the font family, purpose and breadth -- ChangeLog - chronological listing of changes -- Acknowledgements - list of authors and contributors with contact information - -It could also include other sections, such as: where to find documentation, how to make contributions, information on contributing organizations, source code details, and a short design guide. See Appendix A for an example FONTLOG. - - -7 MAKING CONTRIBUTIONS TO OFL PROJECTS - -7.1 Can I contribute work to OFL projects? -In many cases, yes. It is common for OFL fonts to be developed by a team of people who welcome contributions from the wider community. Contact the original authors for specific information on how to participate in their projects. - -7.2 Why should I contribute my changes back to the original authors? -It would benefit many people if you contributed back in response to what you've received. Your contributions and improvements to the fonts and other components could be a tremendous help and would encourage others to contribute as well and 'give back'. You will then benefit from other people's contributions as well. Sometimes maintaining your own separate version takes more effort than merging back with the original. Be aware that any contributions, however, must be either your own original creation or work that you own, and you may be asked to affirm that clearly when you contribute. - -7.3 I've made some very nice improvements to the font. Will you consider adopting them and putting them into future Original Versions? -Most authors would be very happy to receive such contributions. Keep in mind that it is unlikely that they would want to incorporate major changes that would require additional work on their end. Any contributions would likely need to be made for all the fonts in a family and match the overall design and style. Authors are encouraged to include a guide to the design with the fonts. It would also help to have contributions submitted as patches or clearly marked changes - the use of smart source revision control systems like subversion, svk, mercurial, git or bzr is a good idea. Please follow the recommendations given by the author(s) in terms of preferred source formats and configuration parameters for sending contributions. If this is not indicated in a FONTLOG or other documentation of the font, consider asking them directly. Examples of useful contributions are bug fixes, additional glyphs, stylistic alternates (and the smart font code to access them) or improved hinting. Keep in mind that some kinds of changes (esp. hinting) may be technically difficult to integrate. - -7.4 How can I financially support the development of OFL fonts? -It is likely that most authors of OFL fonts would accept financial contributions - contact them for instructions on how to do this. Such contributions would support future development. You can also pay for others to enhance the fonts and contribute the results back to the original authors for inclusion in the Original Version. - - -8 ABOUT THE LICENSE ITSELF - -8.1 I see that this is version 1.1 of the license. Will there be later changes? -Version 1.1 is the first minor revision of the OFL. We are confident that version 1.1 will meet most needs, but are open to future improvements. Any revisions would be for future font releases, and previously existing licenses would remain in effect. No retroactive changes are possible, although the Copyright Holder(s) can re-release the font under a revised OFL. All versions will be available on our web site: http://scripts.sil.org/OFL. - -8.2 Does this license restrict the rights of the Copyright Holder(s)? -No. The Copyright Holder(s) still retain(s) all the rights to their creation; they are only releasing a portion of it for use in a specific way. For example, the Copyright Holder(s) may choose to release a 'basic' version of their font under the OFL, but sell a restricted 'enhanced' version. Only the Copyright Holder(s) can do this. - -8.3 Is the OFL a contract or a license? -The OFL is a license and not a contract and so does not require you to sign it to have legal validity. By using, modifying and redistributing components under the OFL you indicate that you accept the license. - -8.4 I really like the terms of the OFL, but want to change it a little. Am I allowed to take ideas and actual wording from the OFL and put them into my own custom license for distributing my fonts? -We strongly recommend against creating your very own unique open licensing model. Using a modified or derivative license will likely cut you off - along with the font(s) under that license - from the community of designers using the OFL, potentially expose you and your users to legal liabilities, and possibly put your work and rights at risk. The OFL went though a community and legal review process that took years of effort, and that review is only applicable to an unmodified OFL. The text of the OFL has been written by SIL (with review and consultation from the community) and is copyright (c) 2005-2010 SIL International. You may re-use the ideas and wording (in part, not in whole) in another non-proprietary license provided that you call your license by another unambiguous name, that you do not use the preamble, that you do not mention SIL and that you clearly present your license as different from the OFL so as not to cause confusion by being too similar to the original. If you feel the OFL does not meet your needs for an open license, please contact us. - -8.5 Can I translate the license and the FAQ into other languages? -SIL certainly recognises the need for people who are not familiar with English to be able to understand the OFL and its use. Making the license very clear and readable has been a key goal for the OFL, but we know that people understand their own language best. - -If you are an experienced translator, you are very welcome to translate the OFL and OFL-FAQ so that designers and users in your language community can understand the license better. But only the original English version of the license has legal value and has been approved by the community. Translations do not count as legal substitutes and should only serve as a way to explain the original license. SIL - as the author and steward of the license for the community at large - does not approve any translation of the OFL as legally valid because even small translation ambiguities could be abused and create problems. - -SIL gives permission to publish unofficial translations into other languages provided that they comply with the following guidelines: - -- Put the following disclaimer in both English and the target language stating clearly that the translation is unofficial: - -"This is an unofficial translation of the SIL Open Font License into . It was not published by SIL International, and does not legally state the distribution terms for fonts that use the OFL. A release under the OFL is only valid when using the original English text. However, we recognize that this unofficial translation will help users and designers not familiar with English to better understand and use the OFL. We encourage designers who consider releasing their creation under the OFL to read the OFL-FAQ in their own language if it is available. Please go to http://scripts.sil.org/OFL for the official version of the license and the accompanying OFL-FAQ." - -- Keep your unofficial translation current and update it at our request if needed, for example if there is any ambiguity which could lead to confusion. - -If you start such a unofficial translation effort of the OFL and OFL-FAQ please let us know. - - -9 ABOUT SIL INTERNATIONAL - -9.1 Who is SIL International and what do they do? -SIL serves language communities worldwide, building their capacity for sustainable language development, by means of research, translation, training and materials development. SIL makes its services available to all without regard to religious belief, political ideology, gender, race, or ethnic background. SIL's members and volunteers share a Christian commitment. - -9.2 What does this have to do with font licensing? -The ability to read, write, type and publish in one's own language is one of the most critical needs for millions of people around the world. This requires fonts that are widely available and support lesser-known languages. SIL develops - and encourages others to develop - a complete stack of writing systems implementation components available under open licenses. This open stack includes input methods, smart fonts, smart rendering libraries and smart applications. There has been a need for a common open license that is specifically applicable to fonts and related software (a crucial component of this stack), so SIL developed the SIL Open Font License with the help of the Free/Libre and Open Source Software community. - -9.3 How can I contact SIL? -Our main web site is: http://www.sil.org/ -Our site about complex scripts is: http://scripts.sil.org/ -Information about this license (and contact information) is at: http://scripts.sil.org/OFL - - -APPENDIX A - FONTLOG EXAMPLE - -Here is an example of the recommended format for a FONTLOG, although other formats are allowed. - ------ -FONTLOG for the GlobalFontFamily fonts - -This file provides detailed information on the GlobalFontFamily Font Software. This information should be distributed along with the GlobalFontFamily fonts and any derivative works. - -Basic Font Information - -GlobalFontFamily is a Unicode typeface family that supports all languages that use the Latin script and its variants, and could be expanded to support other scripts. - -NewWorldFontFamily is based on the GlobalFontFamily and also supports Greek, Hebrew, Cyrillic and Armenian. - -More specifically, this release supports the following Unicode ranges... -This release contains... -Documentation can be found at... -To contribute to the project... - -ChangeLog - -1 August 2008 (Tom Parker) GlobalFontFamily version 1.2.1 -- Tweaked the smart font code (Branch merged with trunk version) -- Provided improved build and debugging environment for smart behaviours - -7 February 2007 (Pat Johnson) NewWorldFontFamily Version 1.3 -- Added Greek and Cyrillic glyphs - -7 March 2006 (Fred Foobar) NewWorldFontFamily Version 1.2 -- Tweaked contextual behaviours - -1 Feb 2005 (Jane Doe) NewWorldFontFamily Version 1.1 -- Improved build script performance and verbosity -- Extended the smart code documentation -- Corrected minor typos in the documentation -- Fixed position of combining inverted breve below (U+032F) -- Added OpenType/Graphite smart code for Armenian -- Added Armenian glyphs (U+0531 -> U+0587) -- Released as "NewWorldFontFamily" - -1 Jan 2005 (Joe Smith) GlobalFontFamily Version 1.0 -- Initial release - -Acknowledgements - -If you make modifications be sure to add your name (N), email (E), web-address (if you have one) (W) and description (D). This list is in alphabetical order. - -N: Jane Doe -E: jane@university.edu -W: http://art.university.edu/projects/fonts -D: Contributor - Armenian glyphs and code - -N: Fred Foobar -E: fred@foobar.org -W: http://foobar.org -D: Contributor - misc Graphite fixes - -N: Pat Johnson -E: pat@fontstudio.org -W: http://pat.fontstudio.org -D: Designer - Greek & Cyrillic glyphs based on Roman design - -N: Tom Parker -E: tom@company.com -W: http://www.company.com/tom/projects/fonts -D: Engineer - original smart font code - -N: Joe Smith -E: joe@fontstudio.org -W: http://joe.fontstudio.org -D: Designer - original Roman glyphs - -Fontstudio.org is an not-for-profit design group whose purpose is... -Foobar.org is a distributed community of developers... -Company.com is a small business who likes to support community designers... -University.edu is a renowed educational institution with a strong design department... ------ diff --git a/site/assets/XITS-README.txt b/site/assets/XITS-README.txt deleted file mode 100644 index 4611489a..00000000 --- a/site/assets/XITS-README.txt +++ /dev/null @@ -1,37 +0,0 @@ -The XITS font project -====================== - -XITS is a Times-like typeface for mathematical and scientific publishing, -based on [STIX fonts][1]. The main mission of XITS is to provide a -version of STIX fonts enriched with the OpenType MATH extension, making -it suitable for high quality mathematic typesetting with OpenType MATH -capable layout systems, like MS Office 2007 and the new TeX engines -XeTeX and LuaTeX. - -XITS font is free, open source font, under [Open Font License][2], -version 1.1. - -The current version of XITS is based on version 1.1.0-beta1 of STIX fonts. - -This is work in progress, feedback, bug reports and even patches are -welcomed. - -Developers ----------- - -The preferred way for modifying the fonts is by editing the SFD files under -`sources`, using [Sorts Mill Tools][3] or [FontForge][4]. When submitting -patches, please make sure they are as clean as possible, avoiding any unrelated -or unnecessary changes. - -To build the fonts from source you need a make program (only GNU Make is -tested), either [Sorts Mill Tools][3] (preferred) or [FontForge][4] with Python -support, and [FontTools][5]. - - - -[1]: http://www.stixfonts.org -[2]: http://scripts.sil.org/OFL -[3]: http://sortsmill.bitbucket.org/ -[4]: http://fontforge.org/ -[5]: http://github.com/behdad/fonttools diff --git a/site/assets/XITS.txt b/site/assets/XITS.txt deleted file mode 100644 index 15435ef4..00000000 --- a/site/assets/XITS.txt +++ /dev/null @@ -1,103 +0,0 @@ -STIX Font License - -24 May 2010 - -Copyright (c) 2001-2010 by the STI Pub Companies, consisting of the American -Institute of Physics, the American Chemical Society, the American Mathematical -Society, the American Physical Society, Elsevier, Inc., and The Institute of -Electrical and Electronic Engineers, Inc. (www.stixfonts.org), with Reserved -Font Name STIX Fonts, STIX Fonts (TM) is a trademark of The Institute of -Electrical and Electronics Engineers, Inc. - -Portions copyright (c) 1998-2003 by MicroPress, Inc. (www.micropress-inc.com), -with Reserved Font Name TM Math. To obtain additional mathematical fonts, please -contact MicroPress, Inc., 68-30 Harrow Street, Forest Hills, NY 11375, USA, -Phone: (718) 575-1816. - -Portions copyright (c) 1990 by Elsevier, Inc. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - ---------------------------------------------------------------------------- -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ---------------------------------------------------------------------------- - -PREAMBLE - -The goals of the Open Font License (OFL) are to stimulate worldwide development -of collaborative font projects, to support the font creation efforts of academic -and linguistic communities, and to provide a free and open framework in which -fonts may be shared and improved in partnership with others. - -The OFL allows the licensed fonts to be used, studied, modified and redistributed -freely as long as they are not sold by themselves. The fonts, including any -derivative works, can be bundled, embedded, redistributed and/or sold with any -software provided that any reserved names are not used by derivative works. The -fonts and derivatives, however, cannot be released under any other type of license. -The requirement for fonts to remain under this license does not apply to any -document created using the fonts or their derivatives. - -DEFINITIONS - -"Font Software" refers to the set of files released by the Copyright Holder(s) under -this license and clearly marked as such. This may include source files, build -scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the copyright -statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, or -substituting -- in part or in whole -- any of the components of the Original Version, -by changing formats or by porting the Font Software to a new environment. - -"Author" refers to any designer, engineer, programmer, technical writer or other -person who contributed to the Font Software. - -PERMISSION & CONDITIONS - -Permission is hereby granted, free of charge, to any person obtaining a copy of the -Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell -modified and unmodified copies of the Font Software, subject to the following -conditions: - -1) Neither the Font Software nor any of its individual components, in Original or -Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, redistributed -and/or sold with any software, provided that each copy contains the above copyright -notice and this license. These can be included either as stand-alone text files, -human-readable headers or in the appropriate machine-readable metadata fields within -text or binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless -explicit written permission is granted by the corresponding Copyright Holder. This -restriction only applies to the primary font name as presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall -not be used to promote, endorse or advertise any Modified Version, except to -acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with -their explicit written permission. - -5) The Font Software, modified or unmodified, in part or in whole, must be distributed -entirely under this license, and must not be distributed under any other license. The -requirement for fonts to remain under this license does not apply to any document -created using the Font Software. - -TERMINATION - -This license becomes null and void if any of the above conditions are not met. - -DISCLAIMER - -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER -RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR -INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/site/assets/latinmodernmath.woff2 b/site/assets/latinmodernmath.woff2 deleted file mode 100644 index 81369b87f8c7b799b116f4d884da7d39db126643..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 388456 zcmZs?b95$6)IIvdHYT=h+sVYX?POw1jES8mwr$(C?Myr|=lRY1eHVY+d)Df+s!yM; zuG(wWu3cTLJe8!_l+@Lg08rP~0Av6F0RNQmuZ#=;dkXq@_x~}ZvI19ODJgXY0z4vo z5`r~U;-F!5Xk$Q7ggqD+I0Zyd8Z0C;o&K-@?d3LhO<1bIk&=dS1P6kn zBSl6!r}@xbLykb_5@92cJY?>=PY>>|d%GJC&?_!Zi^f4ghMF2j1;L?FXn54hOmIxW zgUwN{DHBEqq7G89lP191?1x$>m?}ux_cNCNz_$R8Q=vBB_m&XFAqWY^aE^fjx*nHL zL8N$18)rAL!kUR1%&Oew#|Vb7+$4UbjQ!frhnDwB$}p$OkhM%g!%zT{bS8&X8~`d= z6lPg?C;zYt^20nJoGSx$w5!F4k&9MM7>?123(_b@vF>T=YEP^U+>4e;RW$@#f2p_8 zpcTj^M$+2fDsPeb#|wDfehDB>+mDPURt_?$-un0aB&eW6BzIWy9rKK!&aKSVmm60r zvnj~1%$&&niFZ2ADD)}sQW`ZoYUPIZwcWG~WO&j|KJUI*Hjea{VoN6Q7q(s8+o50V zz>_-+h?5g3Pki*Y^vgGx`Oy~(ZaMu5Zu;IG@ihS1i}MxsUHw6lb_y(0J!gK3=ZS)S zg5ZnNHMBx75w$j3Pk?B!$pp_=i7k1WVu|tnq-vPGL~ptgvEm|MvEs zP5{$ZShA(1W)Ji;Jnu*`%LG9W-oXmduF9>y4^~B`EmB401?N>ynFPgspkHjo+Q(rs zQKtH}9YR^|KSYcAM0+>Y#7?an$d^*<$dsS7v zQa8a$4RPaoU0J_7M^+Q833Y!Vqltu`KkfF|zBvuZHPtHY3zW%+n#bMtl&@rB%H}v@ z-3h&cB~MG>>Z5@#cS5jtDYnO$$Hf*|W&nE>+h3iAQzG^~hF}lq&MeiNax4Qe^*-xH z-E25zlZpjnlP5Fcd`NLyF@U4kAVyPS7l}1_Z0w{Y*oNE0nID&J0c~I<85t!q8X8y? zKV^QwQj)1`b$LckcXSauSQuMcTK;#*a4M6D{gPR(h_6sDUiw}9KQRrBIg%CMlt^V) z!@>Y`wdaYaQ*}f10&t;NZeqkzC+Z0cvI4;wuaxn;5c)j-xSbA^zVe zk~?=(?rB6R29yAn5R_SrdvI?Ep)r&{gwwBpAI)m)?CfQFO*HDm+^qhX!A&J~aNj^} ztXKy*Z|1p;uYJ)KM3tn+DH@Y6D#+(wa=w@Y8k0fy$PyD-^6<%VW(+1@ zs6f=cfe$<9~6N*^EVCi5#}Z!@GWHGRf7|0iV?<(1A> z+~yrk(2zC%p#OFx@Y5?@Ko+s!uQ^(i5jt65JZ;ga5`|y{emxg7Cv=2YG0iB}%?=kk zJ3*4m?ZICfL+5tf12+3v@g~XXJzUks*J%QdtfuhI%F0cIG`4cF=xs`?bFSr!P?0Ej zXxS#FZzWpVH!ylEzWR|t5$I|7%b35<+52TNfIB+p=;X?FqGbkj)iKl)*(b_$lRXi9 zZ)9(j7e|(KB!p6&JU=}Qpa#L~Z{2K(9Jv`en>O;+5xv)ob&=d)KCI0~@-l&1N?=D^ z>!)+Tl^Sn?V5jeXFc|ggW8}zb#Z&wJz9>D-R^uTryLy|6^=i zFXY_3r}YAz4Iy2%bIxif%k}t-7wc%_cS*j82J;@K085~WYa(wogD+0It{NAncWqRE zmnXG*lIU*%^g6a|lVuZ*3G3W0c0qBX3#8k`+t7=sLb6f~)oE8J&05Aj*t{wkl(4bE$8EEI|vf7{na;0pRyG&iW| z&jYm>F-wPz#WPjgE2IsDQn^VG>^0A3(!Nd-uHnkHNw7QUwD*~2evdt7sxtc$gvGUJ z!SOqYAGndJH76uml_N;v^D*~O+0=1c2O$G}vYLCf@WINi@2}H)UH6V0X999sK zePKtrMO|4z^Q!t7PaQD)NREol{ zPe*N)^gI>aW9FR=4Gn1Z8nX~=zL13a!be2iytyVy&%kM(Uh2oQoM;pkmGf_Fj#xC& zw`$SXP2WF87K{=!xADF%6Y=e~K(D9luP5&JdB>-H=VQ%9sSLjZ(zn)(x_q#{B63TJ z7eTRxWmU(RpD1}!79aWxJ3~R!Jg#_xll`dPPz7P*Sd8#gqMGv2CP8p|EsYViRE`qSI&3TL*jlc}>&6opry4 zg;NYEO0Fa>3oI&AY_3FT-g*{zX!16&#;uNz-Pv{KU2Po|bbk6Dg8Y9**PTXxnx!>Z zrcjYat#53Q;|4nDlH{8%%Qg6PvVF_f#)*xEw`5VbSGS+uXtI3F_SBrKRCxJK7ON8! zH}Z753@_)`-}@LnAze-W?B)lh9t1(hKf;)=>#-iI;XH3+h@o^@Xf)4sX(`|d?=wYr zpmq;FbkqtG_L}OIIVs;f&ta7c3oIm)QYDqK-n+Bxekr2+3sSQCdU174@g8NhE0GFl zqPVm0$D^lJqdoGIiGr0yBfaE?>a8xzm&p$dwzcOMZ!4>Fc`m=Pf!NpY?M4(V$UpO; z1?b&j4?}^5xjUxYV+n$gVJRjV-MsFjZm|6Q2NN!1Q#Q5$ zO2#Yf?hEY3@PoY})?7?GMdEugjKQH%kIJ3mrji<~8;8gbJC&Fk9RR-lGBi01KC3M` zG(Hx3jXIyQs{|aPuCj^*>M@om!}7N(7Kjl#7L;KUG44JsqY^s~oUlhoHV-(&Kyc^t zg_u!Fv%u3;NybWT7Myyt3_2BP8;Zh6860`qBGduLYCrO$l{OGe;ZM|jJ`ZcEY%k1m zURg<%MliP5z&jTfc+c9SN=JfM(A;g-SJ|k=&5vFGdl1UT)0d&CB3}1QWKX(gY%`7u z12`+Zri$cYq*Ma3Pa<8EwJ4$(B-*VU_=rCB4=t+!sW-b$*R8Td z3?#(gi2@v1xayis?p{FjPks8eiqCBt?}T9lY*Qrl3^+(8a~uaYJo7M-KC;k(JT6x( z`lhyTIReRc)>r13_U~`q0bk`yKLvwR^gkw2)wMh@rA0glpzZ(%Ly!Vr7QOhZ!e4E3 z)kc+(pEpP#yp9+Y2w=5@Jqptk8k%Dj~^ z5ScNGb8^9TW3+lwQV6;m2KYIYE4UmjlQV985Ok!#JS+?}BBS14tC`0~H?61Xn_kZe zQc)}OKgVYJAL;&_~?Ef%J{u%L75CX5PA+c9enE ziWve8*NTaa4%Y!07o;+T4rxQlZ-{|}1m_i0G4%InAW5i1IgP=&DR{we`P1H6aiqQ* z`sM2g0xoDIqR)Z`p$7SMf;kAszbUG6v=-TwV@pRpiD6?>u%wOUVccR~6a(aDPnCa( ztel$Y)_Dxh<451J>s*9>W7$Y-Hl_@|Wm89`#WF`Sb-pr z$Rv{4^XtC5lVGuD^qqPHVMN-wG$>v~cyP$+{REFb`AW)^zW?f??xlh9!H()w^x%@1|T*@1EL%xilO zxgSWc@ac%p@*%A*ZY=_4#!g*%AzbL%um8T7FMD>sk1DCc(V4!m4{hH~E;?iRH1rKa z{uy+%{5Qb;sWs8IhUaw1o&Mpfk4VUt2+;R$e^BbK9TxgJsZs< z*jx+XOmalB>KP;TmDny#x)<2>l(-Za_Os7AaWGGF2M;&1SN^x@RNFynaCpj?W?-LV zAwWzKNHmsHv0a7j25Al|a2g6@cSWaQQ860NkWuHGsQJfB40lLUTl`d?fd-qMrrsw969~*mIQZAO zhu$rau;DCI|I;?QmZ6@JEzOLy2>(~GN3&UlO6^=QAw%lC7Ca-^F#VWfy`-Wt8RrYC zN{7B#NHk|Uq^K{4<#fyF=0^yaD;J_T>6vP;O=^vNeO8Gz*s3*4 zz^{@ue5W|~u0IUyN2cYS%wT&25|2T7K50SA<9&xn{flgAptWDma9n#o4_Gk&K%4k7 zvI?eT5c2FbrsTiE!Z{|UUD9(HpZ3p{lrS_(bqPsH?F~REe!Z_aAq9uTFbJq;gI{=m zZ05RyPRhPh8aalJh8Ev<`6?y`FZ3LDy+nwdB(8k^d;=TYpO#Qa`IA%T95v%FbCQS! zT@nBsf+PmXmlL*?b0ZiBk&LVrbRFRTJA$y@g$v$3B-R^)gPX@WwvZ;X)F!hq$Mult zUz?ze9_yp|bFwdKqZCyzDV;=9@Cn+Lmi}w5!qVqZ;+1RGm4AkLk}TCf2W5EfJt;QZ z`+$H3`UnV!2BA24xqQhRl^Sle#*!||Hpc?3e`J9hO9aEykg?v7zd7>+%CH2%nu;O9 ziHnT{2908}it(Rr{_w4vY@WRFhHiR&6|(YZ%VNabFmEeeoWV|#3#I^oV=5P>Owurt zss{mJWfLGp!BinAWOnQ&J=De>uM%_4J7GuHtj9x-;=)>&*UfG$UXoUavfaUb@l zV=D$UwBdoEhc|(^qxQR)Ip3wH+*$&V61d*GO5lDLRc2CH^xit&)j(r-IRg&6MgANt$Q4@)ew^3WMACN6=aGfu1ZrnLzhWAo2lm zAkke5C(06ujU7zTXDfp}f*}>g(cijShB3bK@+>Q2aBPLZs_RB6S);#;-@F8JMP#*! zNZmy?s}Fv^?alS73|0#s8R6;XMDp8^mPUHHxJ1*S2LwF>eb!{xCZ>>MQ3Z9zm9Da4 z#S$rG524TgBL{^g4#sw5B^3Fh1)8YBe*^}$8|a?q>}8u^y1B3|)+<9cdnHM2+VA#I zv_C3eHUKV;4Pe0x6a^E(3=B2u`~0b41&WjyhWklPc29fuS2oNE@{6`2&-_Bw~xh z2}AXl7^kF1rJM(wqd19eK9sKAX4$yB4aN2kh!|$d2$g1eI>mJ|3$$YGK;kM6`tL52#PQ=K8CgO$Q*+Nz(BV zNXUxY$n6#(*wu6;+jRn}gD(dmkZ5S+i=e7zL5Vby&KCfb9bi*@0Sh+}Hs}scJUT}! zp{M}W=Rk7aMekIf7GT0^aymPxFJm*kS8IhR97*S=QtZm~i|8sq6jt1o=X3V^(V}3M z#vWVSyM||x3er+JbfjenHl$>|tSm)wMnxr;Jx3-Gdb}VrA2*ReypLjpb(sfGCnml3 zq>V|>O4cRD@>CC_!`icHhKr2)&{6=Oc6meQAQb<0jth<}Dxh7q)1*D&pn^AB+l(=i zvlX`2K^^6rlWu+kGywq7*!ju+&mF%I;wk9%dyDQ0@5>i#0&$832q3{qQ&L4HgMyZl zjf;9c$tXK9*&(>fvAz=Gn<=~-e=rsgyMF|cFBFiVP9m}x1fYZhC&7Xh;er521{Ryk z(RNwr=_t@sd)v!BXS<%p69-~O0%%FV_ff%+Vgk?EWHu}Ula!JsIV7i;zBd|V3QX|M zyKYjhomYf!?9i_<`L;}LuCz*&J`gBz^7^_y^DsWQR9igNruAG|Fs2F051Fn!SZ-BW zfbwQ0n|qs;TdK*`aivEyek3@f@=bRA>p5OVN6sOBp?yj9#lEH3rN^(r% z!r{-BIDIckg&Y*ZLk)UUZE^Cw@zsE&x*+Yp5x{^-a%RLG9h3yM?}*}2%~@w z%I_HPFqz>{Rt^a^W*d(P3tB*n9n?-ko4pdC^YUTw6qT95x!KU0iKIdiDFsKCx$VC`>rKRV zCR`D^(BtAK+2241>neMbl*aQn#2&9$`tUYWiEtU>Qw?rZQJ>=Fv5- z`79`4DR@&?=~nx!Z_DH|l)_vL9L}UX@bEn2pKMt@1kF3Ma~yuT=SYDKP>Rl!Sg-~8 zRLza)|AisWuS?yN>x3$}tPd_&PqM&4onU*(g@J0&w5T}0*#+^n?iA(+me0>c(8T1= z7b!w3+BMJyBna6T@MGG!S4#ll)o4`M8}=DQCX&1xAA}`yO2_9mFD$+Vj2@t$6z3z8 zwm^)k-)km=I{v~zR{tBGAl>UoJrwL^+$XwPIBc%VE(^czV`tpEebM5`NXSG~iQ<3_ zIhWSnH_iA7{@x}nVX=QgG!#7;5)F=wY$rKDJGmh&h%^hOX&j2zT$G47dSl-cj>eb- z*>2mj^CH1#dd)$5ctDraeI?Yi*Sj&>?={0Vq1G2h z?$qav=t8Is0WIR%&mmCJRMlElS1&RE99{%!J($&`5EYRDS z+Bw{VMHB$f5(FcE0O=G;f~|dAM8N13@2Wf>ZBw0J&b}QIcT^$PV4>ykBZ`i^!UO4W z>0wgOePt>oyYW3vKd``dU@{gfnpuUE?`70HZhCq&j9(y@Jd{I|rG1BYmnzd_xEsO2 z>^Usm(B{egxr{ShDYIkYc)*?CzVHlAyio#MKD|oYzQwQ_3s;M~%S6@3P^a3g%cCd1 zFv6u!;#}KXve*L7HdhN`fR%uqPnx35)s0!q#!eEaQAy8Jhcb%O1)7WvuTu)!gXk2X z=O~`1R;ZWX`CMjWdA$$DnW+7C9IVP{_95}TQ7(z?hmfS@tQrqht?ISUL#ji2iEV7A z$LbPdvc(TqsoH8kNcb$*3tY=Qs{zV%gDjkHRmU|cmt6Uq0s^pz{6|3NLWOsH5*vD2I7W< z$|I1KgV0(5(AXTX#_(L2^@m@lN8^Vi1Th%HwwOg&_~T}wLLT5L>-w~7XU8f3CXV82rqMCzVgBuDX$7#hatg;F9p zN$6vHOUNcka`Da?IEKZe0om}eq0k9Z`1d{oF%wwG)3yOrl>E63B9hc$ERil36Yuv9 z6PbhSwd~xvpESSm^g91kv}My*U1sS{$QyB>5fu!e(>S9V8&7}_poNhp1$jx3z{WV) z`d~XwD?5v@1iO+HigcZ$o|H?Vb6N*G(ta+&OEtv}Pc|__Sr8(8NI(Iid3_07X1FbM zA8{H^!clyt?<&rYmxE09N5F+ID z!Z15{hWxkpFIy?pXB=eha5^x%X7~u$(qMGMk!K|dh*$7Lotl6g# ztNOvxhbtD1XSC2;Gdq5q|AR*0VInG*+;cbei9!FZZ|ytFn{)rHV8FRmrh=mPF&7w{ z`njuINCKsne%HLp;oy&?LH;S+JUc2SZSx{ae^r#+hatK+3&ekZc7o`2h}$5@Yg^;V_USG$zS!(y(BdxzQ9*w1u5|LfSc4R@e`@5E|X zR=2VFB_&miN|_a-o~+`JoH2G>J3sRQ_q~eMdY{y+Z4io zS-4~n6A>wbNR@GN%iD{a?Ux!)M|%!s9>cIOT&}6gjJ)=b2~iAhtE1~Wu6GoLE(__M z+(*G#lRFqnlE^!Tc~4o;z(kBuAPCG}Y3hgJ$lM^uMOnJ=*ja<4ldO)r<_ZaV+o&CD1>*7rWj!s3^r+6`@xcW|V) zvv1zoHqRo_kU$1gX-F!bBK2#AoESR1nWT*C+=Sx3)j4a)#B96vmyK}Ga^Dp{gL04F zRIA`atyq~MZcWxF5cdBg?4Kdq(00t3k8Y3-il7It$_TN1eW6fD?KVX2cZuX-aCy9N|93W^=ANmo#-pw2ob%%Jl&Moea1b9@C({3j+=ax4jbO3bk} zIOBZDG=5LXw>G9{y;4v?*-WWFkImLT6Lr7en?9U>J~I|^N~SAoLwL_{*eq1quIY)F z7F)un*i|%nRk)^BuFejHZYV0~>+pHqY-k-tpn$4z^)_4&JL0kJaXQ`3x(mfOF;Th? zA^Pr!5wyo(yLiUPd)u}k>)w+~@>tzm_Y@<-Ap=DVhVUS!O&~sah9G(q!h$16SKGw^ zfiQ?sg)+0hbX4n4l1>=byod37Stk+g+<5n+zR5M?Bs(+P&Wp(#>djb7Tlp;Z+1grH zCS!(?ZF;x!zs%37O<@?`m&W^_p_J)2xKF9wesR=a4-c==aiMaU3}<2}32ARcCUYkf zi;NT*Pw>v6vi>T^3G=pJcR!qre)n*BarW}&S6yQDxY<2p;)ty#c#KdHO`+iUT9+@9 zHy5(w9oP7`O~?xLDBUwl^WW-)90!6;zW%$)s9NITum^9EIN3 zmvDiW8HInEHSv9$LwFe--M2oEJUE)R2)3D5Vh}AwuD}R}7MiDVfPoodAuzCbL42E9=JA3_VeY&_hUaZTnf++)ww3 zTo}W*!!QNuT7g$b$}yc$bKYOmJZq8~kcIS`hiGXo!Ri~w*p!OOGF*Zhm(AYZSxn}N z@HQv==Iul%YSD%`g!Gi|FXHmlC&-+!bzG%O9{hS0CwM#8bj zoflaHZI`_bmI`jpGlb5+0nyMX^_XA*Vk}6$)E+OA*vK4GZKd|j4VLz;r%cK=8SCE4 z%G}NMFO0If`qG|CPDXa|aZ*~I6O%4Gr-VmK2=o`X+yA1VRrGC;Z&Tp?GZkr7DXG>14Ib!;3 zf779Plxk}=&uX>c_poexuB~0>Z1{00DVop7k=*|5F97Q822ENRj6ltHRcy6C5Tncr zcYmFqeA@#(kF<2f8)g6XX;V#i!?Xk1Eg~5`4@&R86&Stt^p%9EDcsB1>3Z7cCg~{a zE|q?BJvk~^S1sV~jG8-??T)+ViJAfqEBLWE&Q@9v_1fi4;*F|GV;FT=22nj`G@Jx? z(=O)E#V|@cdLQ7Eh~3F-I8U&j(g24sm6`bH7iHfwER%nX(}yiDO>txqxF(ltGl-Iu#CU9bIUr{>9tkX>p4^V zZ#uVM2sc|JG9Xp}df!)A0o`qX&zWO461iq(Q6wobrdUE}Sf$&A2CfH9h_MwTM~P9( z!Iv*sOvWLbF_1jBQ;0=@bE4)knWbHI3>F#hqa}+2yXyMj(Z8Duqh`{PF&UiJx=y>S zbrh-1@;Dzm-Vg#wXgEG1ITm;=W;jemsv$*b#W7eR6DUZ_0*hcJ(&qayHAzH*p%Gx= z*Z>i*h#_huzghJU66T!)jcsvc>7!lO)ESyq*ZH2poW8c5K6hV!-WA3FJL1h$TH<;rEeoL(Oh zUf=xe8x!sM0_HE9;$N1!)+MnXeB}kSH8Kel3TX-G7O1KPS_`9`-zAU(qX+03#d(gi z^>TkDiY}kCSx)34ph(E7Nr-a%W;dG(<7MMxLc>K8eELP`Yh(7ZaoVh{XXI%AZx~-) zkFibODsZ25*n7E%njOZ;(TG4}=*#4X5?S(yl18e?n_*9_4+|-}#A{I~gBL{eDx#VI z3J0~FM;K*)Pim@5PT6&MTy_&(wxDY;sLkN5l{!+UYp7^&rXeRdhN%8Yh*rV)EiF)oy?48tqf{%u1di8HlF!5#ecM}EES0{*sAfjxC8W?pgU+48F4rc7LEcGHSHm^lqJDWmQ^%BqD(>&AVMsH zv$i299-ROt-R)x2@#6Ug4vbGM<=o)o_LpoK4r`Il%t`fVj^8<=(8WXVO~lXZy1!1# zF4Q?5t!>?!4w<|jmkP)y-P;Kf_i{p0Mj7e4K8?)Z?yZrXOCsGp^#wP}Zov^_z#ldb ze6pA~9B;+>w5=m#*TeN*^(_7=?@b|r`rp~ftje}60Oy`CRb^_^hi zdwPxf{`~wL=!)-sOEmi7X=>_tc^+HW-FURT9_vI&OKCGHv+9~yN0}AQG<_Tgo4N=} z_*-Vp9EV0Y+;K?OIz(4JRT^W)hoC(!b;akaFgu~(ExDWG#F=Mv)0qC+_b1?t5-0eN zb3X%*DH>NpJiIQBF+3ibTYDtftIWbE>K4y1Qg>iFnkYQfGE2OMy~&>9$0e8&J5thU z?r4_XE)=$*{e(rD(FUDX(>rI4JK?1!D4aW!vBu##$6!aW$NwwmLSL(EBZug*`K;$k zJn!RH7fhT4$E;Yi5D`sb`bdDvM1p`tfX|4=D%|J+-beaZ;C2fNF1$d786%4{i8E~?7)h5cQ_d(;O^1w3q_ z^!ogPfl5(LlT$B4p6h!aIGg)x((W!TE2c(mp4&8SMhT~w%rMd!~Pb$K5%zbMv5_^G|@S zX!>>*N&6IdzTf|5{`u7<{P*M*^!~<nxy<%sh%U<$? zjva_9lWl@czdnL{(-1<=6K&TX6yX&H$51!`{p=h}FR+gUrM@6RjKNSp0w%drzL3JE zUW%+>Bkh1!imOX`9#~5wYe9A~AA|f@NconcB5mq?a?CNsd2<)Zy?rd2d#JIyPu_cw zjp4bT;RlCNqUIPzt%W3p=ue}}ftZ~aQRLbgWOrkIwdt=21cd}uiYW=Pgnjk*IPYSF z(5nd7LZwh}Lq=n-J90YH_A7{D3sGH(*Q=zyYvvLN_6qbN7@`&)B5@N@2dCLtWqoa+ ze5mfZz~3E?IA2Xa-7px0P0>umc+Dx=y(oH%YbhmZhxGJKdDaAYrzz!y3Vo%Xuusml zW}UC{AP6mfAw)X|fA1*mAGtdpiyz{)LH4`KsNA@<-deML>wSPMbvK7$N!KPg!0FS; zg_^)yZg|*v4JNfC)yF{}ni={eQhA);?_c{QYhBa*!R*d}t=Y7BR3S#lUEK8j1|x}J0JLM*YH>S< zcbiY`V8Z9LyGW>Q@GA!rvDqjb;2lX`I2#UMWDatU>KuR(SBj@y=0S@s&~nKy(>?*$ zD~wao8LO-?@!vIFv0j%qk^6szwr$R3dAI%?9@`*F^785s#9{VN+hGH%ySUFgE1Ns^ zyUwCG#B38u^Y?A<(^O*3aA!VCVc?6Qq>Lsip&W=)>>3^&rYxv8=KTI&;1^-e4F%ql zNbIj~f?6s`d>5lh(-Dr-gexI1Ekh^u`g|%V3bqkXIJ!MUuFXGE_fD98`sn+F(>TY# zBb*OjgeNqq^~Y}_yyMS~SN{ZiX4q#}ePBLubuRd>pGLaz4U9f$n-$~E6%xG8vv`jo zKTcgLx>o`_!Qs2}K~l>2MK;0+Jid)}xBi6P@f>-2+%yoam4H8ZxNA!Et>-3?Z}d=C zQ;CS$XH1ByTxEl}BORE~9S(J;i!G8T)*ni{{HXI{s=dx7yQ71yFpm3W>y8}>^lY)V3)05rlu)KpIqAHd51_ag%p*%yC`g5SOxE>za(QrqFe9 zz_cg3C$$&M9)@JhDLbzU-Jd4hw8DqgS*N~l{$Sx*u~5gUw>@sPghDHz4K=alBL5)UQ1Nze+cmwOi=ZV5-B0Zl`-JiW817TCXoM>_*C5C3)+Zl(j{U#$BOG z3$KA)Rcsz`*QkCH+>S^1HJF7Vq$&RPO&8Xpak;R&r(Sziq9ag{1S;6w*|~uT+4|tb z7~K&$?v?kok#q`#5RgkQo4a)UC+*-RC{kH{0#;m#zd7_w8jqiiUQh8pI~N~t{|44N zIK&9_hEQg+L^7@R@Bn|o)T?whZ4x_a`>9-`Is#cneQDiRr}8+w8TEMg9V=Kc3v-I6 zYG-r*Eq?a)XJg6{VknQSmMozi7D+?((@A8 zzifa>`usMH-f@DX&!EI*S;&T$incAG+B{ToQw*b;Hr$<54BpETIAMjScp{Mp5bXK9!E3&BP7l@YpVyAb~|B=Dz!d~v;naI#es8eqUUWxp~LcAOK-*< zPw ztkmLK${J32HbS787>HDk$336Z^Xyc2a?5 z$wat$fo)(^arG6`pD&3u*Y z4$MPNIG8MEolT0l+5<>dejvbCQ8H<- zZX?UEVKw5FeYvb@j}`ygd2vTP4~EzV_X^mddb8+EiKCFLI(wZmOF8=|B{ybYv09{v zr%1xzITLFZY=L4?jhJ~(!sxyHP41GDyLs8r-{w;O6m{RtnK1n2;+(I4Wq`oCGlgBD ziubzf#BshB0IQ$Ic)?MtsRO) zc?Q5yGJL9wNm~RU+e}e4Co2KqsnCi6RmZ_n7Iil!p_Q|(0V-n3QK;YmK&up_h!`Xw z3ql*)wgwUoEs$kE)D)mz7&8S9h}woW4*k(g6S%q=V4dLtmCs2H`R`Pp2-tcnO*9)A z>WCA-2Fw@{Knei#14&p)X<`x)0l(Y`0tR26FxUWqKyyG09JpE3AdUtAJwawHkzy(d z5rTvyF^=5LxdWij1V~5te{*cWND_-}l3EoqOOId~|9gstssiO40R}*q&7`u~Dz@Q^ zo1>NmkR&EiB&JzRni=oB=E-bY`%yXN251VeMA*$q6D>yO6_=?jP_o>>S2Q;~>7opV zf*;i;$l>eNxu8-l)E}SQ;dqAWw?Y86ugFlTFxMqP4i)uiL0Sw-6nvCq|C{P`AqrGB z-o{e3F}qYC2%VVcM=L^|1N+zY{voa)mI74u$Dv(Za6EHF4TOI|Q~;npl3rS3*M(*; zVKDQPCGfHj^w%B%X zxB*YB5kjeS#a*fMR0Upw4s8j^%^XutU1N=@RY05ue0=ke3qwKZ(2DFeYL_E?P1r zu{GRB|63RC_KMTZ`RW5hx(M9=e(xcDZzBTWca%y^y;afS>{^F{>kRdy3!Bs`%~-nN zjexxBdP@*v4aUFF3F6)-coQa`b8!q`|1^JL>Fv2~B)nJ%bh!o;@cW$Dq{c5tgmhIP zOx&oM`svB4t;e#yZ*e!_Z_=i&Qg1|;-+T?-6FVCM779Um>c(=DSaVgk(dK z)9=BK0?9-p=)R@k00hC$NB1_rPhLL4)l7uq7GVygMZto_=K>;zfoaYhjt5*9mBLH~~&Y%x#k zZzY%CqK`b33D2#@3rEmxDZQhX;sXw5WS6!mWd%X%N)9jFY>Lo-XGKtXq!lQm+B{u9P5i|8*M;;cI8Xz%Eur{VNe*u_j%9r)PbFC_1!hCVE zNKJ=%Q9DQ_Hc{&P+f3-cx=R^jmT# z&q6=|);y`BC8O8{E=}W!U^7(`I_qk^T}UQW9=Cjo+gL0BTA=$oe`~_A6AG)>+WsBs zBr0s*c2cT0t<2*kuVZ^f9O5{wa1U5tip0T**wg3D#{JbRg9e|domdo<=4z*7-;2M z<;5j3^_A^DTt8+DWh!J`aINy9A(qaH$0W>}I+JQ@jm{P3Kz}Wuu3b2zh=_=C8M$;B zTAk*m1%SCCCieC$O9G>;&csH<)>YIP?h507KHoUKaJ###(lmWgjYv8ey4nTl*tNIrmsN!wkG&QGU`ezbB>F`WnW7UVH$ObQLEQY zfnMF{#s8_0{jl??2`4jA^E zAoEPGGG(>PH-?(aB;`CPQtrwQ@=Nn^nu-|@hRQmM3O&IFP$Z%7-)DcB$bdKsb-bY7 zV97vv_^)W@yk{2oiLz~Sh9?F(FKXXtl7EJqaz2DzHfQ8mPc{U9j8tzx{aRb^;y3a- zxHD*u(C)}+2TGVHj(f|f>&nQ6GH;o>d6)#8TVzl7U0TL{~$)yz7$k7&D!M)dPm@lICS^14bxeqSguqNOCvSGBt`ewpN*;Xj%yda&Y zzK9Rwn&wTavtdQ1)c26u`}!>Kcxi`obmIJG9K$+_WA@K^@rsSh6}!TchN6o7=Ni#V z+&Faw|2rE~@}Dz60$_`}{13?i0LEx$_KceR|M$B%deJ|6-4*U=SQFjL&2o7Sz10tN zm!lxXz)X|DoIX||eCBp?9$8pL=-y9GhwMp7k()KHKj1vjVY+Fembkto`plUQy4d zXEjF18NDNWT@FqVDHqW)%|}XYc*gg3{$6!I9K1x4K*Kd&8G>yl4@;V&3J>VVG0T3q zJr@TpG&*1eBB0kbxBs4YpKEA|xu?6)R}`qXRv6%BzmHzwnh*AcL$UYWhXuD~0HOQF86bu3pCq51nI{%)r&s zYS}Eh0%J9%GnaBQPNKN#YGzJ&;#o(JUfD=P<&!Q`RQVL*!2sdTS*)X$|A(w|4Duuh z`t;bgZQI_lZQC|?Y}>YN?%1|=X8vQ_bNk}%y|~K{-CsI7GO9AG^XaJk)rQ|J_eqUI zq2v8h`s?lCTyp)-S(Q$o|LdKF9A{ZWFSZtX)`SRnlY2U#CKB1sqmekl-V2O|= zTrJ>ioQAqf(`s-VhhJ5lhDa6{wJ8uj*l|FNNXZh8BTw#l)gFF+@jC?NOg3tIBY>o3 z(RmxBbxqM_Pfk|$8Ry~ej%aXO>dNmznlH<#+dNl0vD2krzg7hz*>YR@X|b8E5AnEu zg|zmK2dkgq69ymSZm*!XY9-i=kXV*;Xl~H{af&+pJ0mGqdz}gV1hzz1rF@a-mD-BEffHe1G+CA8y5V=hkuBWD2L{z_^Caw!Aou z7n~?-KAkUNP^jN0xnz+A8bUh&f`SV~i4rBt(BguL9bA;r5v`Aj^-nGzPIbePAXC%G zW(v+f0E4A;d_v1v16Pye{Eb^t_$b^$ZrB$ULX{0S`b_gOJ1VJ98yhVoKC{5)6)&V} zewNB_f?3faZuMS`_5HLL)Bd3rP8DAU$n zuS5)4{PW7>Ru78~M>2)np#dmR`+b1U0s;xnNDIQ|4R}pjpH7(Z=`maK-QTpA6lRG* z8)~57DBKbD-uCm#>&o`p*r9j#g?&3O0K%G6v2V8l{;GEj*Yz_VvFm<{!hL8<3I5O; z$%qO5qGPxe0l|ubXPvO_Y|*R~5w`Eks|!d;f(8Q7Wf`zlTh`&GbngbLQwB@OFi@sM z7&Ao?;X-1BOS~yMUPLjOxnOX7_o=++VRibQF>KX7e$SY2n0)gC8ce)^dDldot8{M% zeBqzsGU{}alw+>XlRR9T(irctJxP02VxYL~j8DtQs&hTBLRuf9HSgVr#&7Xg%YVSSj#}#^6^-`^^zNi}R<8sZleUlD1N8A|UcRQn zODOOJA-6-px~Vh&uj`mMa;X7DhyxSD{BXFzkIy6T({{9;>=ToHHV!kUfwtweO0TTf z{Zg*vM~L@d+Yc5LurMKDEIiD>%kvdcc?#SGA=X>aD14?P{;xX&&q`R=C}7{Ns`TI+ zgBVO7!GnfVm|h3Z0G*B&^o`Z;P`<;;M@b_&IKNE;UsfWG) zl{QqYuypEQ{;zr$|9_XU?$my>!2dA9=icGdeFXI7>EOPMs3+=nP>jM%Wl zX0G=Ln{R_+Amvn6pRKGDW*d!?a)RDytHTCy+NrXoc1=8kg_#g8SQz8~WfHW1Jfga} z?rryfYGu8yJdPCC20FpYzGF1Sa@J}Eo0tlzTFHXLP`w>{41iv(`7xi!1lgMW0&x(s z3Z+P_Y-QbX=%D_ueNXXE1`;!$Lsb9 zPi!OajwOfeaQB7hH1|o4i~kF$N9SP-6`c&R-Lo})3k*Kcc7rRM5$-1Owo8q4sa#rJ zJMxg@Q?E3^e}B*Z<2C?)vv?D3;5_(m^UHjgV|(}BO-~&Wz0LKdv+@h;n`C$Hc6rvn z?)Twq^I)>Tl1)29Q!Ul{3nE!d;ya{%9RvUE7_7Vdo5op}Pf`Pa#CO(>HN)^7BW^rm ze95Z#HczVIXwsWoanX!#gjPm|EraMfx9f1pJGOhRFO0ea!BCIWQhdn5!aMf&165>g;EH`Sm+> zQ3=ruxL#607`upWk*bFhx6^jm>yW4jrow>^+LFc5)okZ~tf_f>%mMEnMeQ4$=>JWe-UV|56%C0^4}EoAE1?!{MYEe zUh@B45y`Aff?Fv6;r;*EK!S4ibnszTH>fp%`365p%jN|AQ{m3EsKkSj2(DO;`BAvl zRX8K(T>g|~^TV4Kc+c|JI^6}=9UOoqad`m^bVhc&%EATxn%>7x0VQ$hf?i|StCm!} zgKcVn_JZ#pO-^?Un8S_Usj7)d<6mkg*q_n#H~Ih6jiYU1{M(_#RG?jBsJGOWk6|gH z2K#|SdMdO3aM^b@A$b>!xf@_c$IiD{>ht*rlF@`9^XE{sE8QwpRYtH^%wWbxvN)?E zHqq>*fQr@)20R6vu+GN2xZWD*4h*LQnJKu>w!`7w}2a zwr1IsznSp<+#kCcebsfYIKHO>T_8QNo#2pt4A~j6pel+bZ^3p-MRZh@PO10rqpLoq zVU%9aSWmjxGPM2_i zRe0GK=zq7!Fph82*vPOeLN&aXRW|>DGz~r>d{wu~* zgbPw&gNUG1|BMf^pWG|nHh(b_n*50+Q_$sLS@cWzg8eI#Z=4!`Adz49S06A-2Om01 z+fsSO6QOuqrM-634r1_Wdq?O0oXNg@(X#LM%jg(=^D$@%EQCcP)QDE~zk+4JnxWeS z4SH7+HvY`sBUDyS=U+AvzyyQfb{K1F&1eK|h{0?k*dTyWfKno)ip~%ZNxErRKR15JpL#zao9Rm0U3$ti$9h4bZjQVB zdl<8YALbl1a00j-zY5hPjsEX1P@m<0x%JQf&|V6mMXs7T5c*u1Ozl34qz&W2NdRX< z=sP)iw|8oo0o-V-tyyR`g59EEt*+dv^h-#wJW5%{$enff5yJW|^^Bg7cl_jeG4~Ck{p#R)s0BU^LlaIe|n0gJ*9<-&f`mj7FtXN ztC=%1!p&3pF#qMy)~?gX)w|S7L&HFyVxekWSM%+E!Jp`~J;+w+Q9wc>8%Stf`2d0GS z)&H~GKHO+G{tGAkOv~F^@C;qgf$P-?m~-F8@-%;!C(9i33*XM`CX0Zp8C7SgyTd`` zW^KSc$>)=xEuYUD>&<~ZV&N92n9W#X>G!WimENuXXd$m*yGZ|jPEkj;$BB$8;MjQ; z2hWC-0mHDTJtNU}f{_ZW za85^Jies{>J#}r+zCkB_FFzRb^W}0})zMS|>;Wc$!6R*P zXfj9qNWd0r>{M2D`DtJb16Aw%(+5d{^Cd{6esw#ODl_<}!#m`sHIk zmW>b6VjKiy-+uTP^D!}u`$I1cGIVr8O;Vjs-dU``T7U^abLCvww(T3^kGXIVKq@$-%f~F74#guqL!K=4PQwnmO)NgW++JmED zp2Rdi7w^EGYR!kiXO-_&PAUkW!yCHKYn@Qj-yX;x#Ip<*Q z$6YRre6VYB3O_y&@U0xv@)|U=4UHr6sz_CRopEN?wm#W-^sFY%915;CES2U7{5w+w z+TJ_))7m)3K1xPi*>o+_bUfKq!+-kBt!kqqeRH1}elcd_n07)rVK-Sjfb>k(2pT<5F@oZ=Po{?j8(kFI7X-U6tdtc^Z__XX;Q_{1*cniJZX? zL0uabMb9}7A!nv(hkQcqNHsn>^HVhH%3yW{zCpDD@@u-308<7ZLqn;q^=W@lLshHO z>XAjG!UEgH!J$0+?7m?&EgPL=*kZhyn^XAuiJB2tPp)|_SpZ;XBkn`m;yiTt4X`O~ z&zy~%OKGk%O6yY8{&s_RDS$*y?b=kA50npsb#AN)n(oXvEXY=-rR@m(F56fiEV4cu z*}?hHOP;?Gscq$4qzjLy9hs)>!R1&hp%m-LTCXAD&1zSOa;DX;unG!o!%!}2?wE{z z^620tpKCLRjmlQ>#ozJNTTF{eEn^fb^~RiPIv3wae%Hzh z1tm|lw>qqUGb>5+s`)H{X;ZBzl>j^=tIK-1W$X9l>KK1)XM?xFxKv8?+G&}Z{XDe{ zHP%H;m2!j^A;sC1U6;wsrGjEZ}rvQ^=Hv-Y2ntOpEs2+zN^dRzOQIEyY%Xk3AtLeDs0uexsKKj z)K**=@-Nw*%l7WbRCwe)*}wF7Aj;G@Fe&)gX{h(N*}y+tO8<%Tv)(s;!Px<*df;Tw zt^Ji%TU#D<%)^LI$*D{zRZoMu(b==sT+S>jargCEcXhF$Irl+FwRSVz= zGql^ot+i^Lcm4V;jNzkcZzBKcz2qrjj{)o6SmF;O2j46i!3%hnsct?K;Xl(rmG8A& zj4OAPN`2l6tOgA6ohqofJ+h9KKFYPbR3Oew?;mz_o3U5VPk>$M-WT1>Y&^8A{@vv? z_@yC$;I)2&(V~rQ5t^L$Tt8wBvBA)o^u4^e2KTXDUqCKlV&~X_5P-bAao_(Zv^KMfX4_^0JIz!`~dH7o+wMA`=soZ<( zdC~PsNW$LTwN}sZ$SAnltVLtba%|GRzm~f0u{;%t}&`lRA{c+p{im3 zYg?lQD7sW*sX_)6xHE6~C*lTEz}hKD(2!X(xGMbGmbkfWE1@T8#Qg*E?E`U$#^Mr8 z=VIE-gg>NPZb`RmH)OplXDerSh4pN&H`G`#$2I0fFG!kduj{qh%E=Emywk>V&i=^K z+Rvtr9&NCr?8Bb)E<8|Y0;c1sQa0vp@MN{LD)sU%GCnlkgRg$CgG!3QyE&O3BTFDn zpKsYw;U`}MKOsP&X&n7!Ol!WN>2nzR7*dkfoRB2N{?K31mrSs#G*^9Y+ga>Ktg@pj zT$-eoxeo1&;VoSg^NVpe4qc%z>w5KhJ=(ix`%{4nrn$GmEjt zlg66i`7zQO9`&_DnTH+r$_olbMd0b2f_udRhjdGA0&FmII{0F?6 z9^ul}15*%UDG+nxs&+c<)a-5Y3D?Vdrrntw2_mplWDr5JEX+t-JhJ=iH zXHC7n_2V%^M|VvLM%ntYd#64-$7m#rX8Xalu9q#(L-lqc#qsS+gMsbG23@I$#N{Is zeZccoY}-1q0t@zDaJSpgHcfQ#vLfQ44z*go%SGwM=?Y6`*LxcneW(LlJJGdD?R0v$ zw%i*33q$WiTlOez=1XGTL#9sV6yf{qjl0vQ-V`!ZiE3bQoI#L0Y+hYi5mcdYYPSus z+fV0<;&92g*S-rDUk^hUs)M?P%doglZx71cG4yGm=M7A6MdIMpT&lO3y#giK3+E~v zZyc*KhNoAnM%WTa{j)*utuZnUVY}`TP5DL3Lgp%dI_oEg_lNqfG-eA|cuGxvJFRY8 z9k@ZkWnGcfhu)p_T5i5)>7H+jor=Kb)v>#h8ELQ%06sR@N8t&YUFM2P)J|@uH)%n^ z?HG?1i4wq1e(>{X=lr1Wfcw`Ux7Vk_&G)5MZd>!Jncvd$GnJsC8hFoa_Whi@+yij^ zG`nQcrZ+G681W!59sW)!XgX2$iglK(AWkl`c_l-tU;4pQuDO?kcUC0~9*%%x%~)cL z4%sFIfF>=}W7k$=t%iLp24)=0J}qpv>f zvYu&Fy};+#8}$fCOg4`FoJ+xEki#Un!SJSv^7!})UCZLzThC~z7hXZDfyGb z3ux1R`K;Hg={`wZd1&k6g9}iZrYBpn-Dw!rZP;btUzz8EFfIldpk3y3P(Gfh%Rk zB-TSFQ!L-p3=fg?fSBRf95jK}LkIyPrp~CnhL7Ze>j4;|Z81pFicIsyZ{$NwILQel zWY9YCpcGP6K$bt-AHtB;y8aC8{HBb^;q&5R(pxMlT?~`(*AXU)ET|8;=Qn?9F;kGF zZuBvR?hUxr;VVX}v9Rp&jxt>4*`uoPBIwRATL|E2l{AtigDSP|X_|SGFR|IA z_qrp&&UkL~@J-AnpTKf$UB`h!>!tAx(=J*}OGDxjvw^7qNJ$&zXOY}CY8{QpMN)$s z1RU9~hp}}Z2@*}lwKCXJy}z24@I9n;CpQm?>4r6I^tc&^bb8ux;4>N)N?~7^QH!QS zvMo2xAF~@)@ExqTMX47pW)RhL>(h9hp&xbox~>4xf6HsSjlQR)ctWtB+iBO>-6a)c z_f5%p;608o*b$Y+Bnn}N>UP}3Em4`YyJ?1W`263B2%dynz5@bATqFNAz_wPS=~cEI zJf@f*FXpXKEYzdcZ~E@;C8e4TDH?4tR|+?IWu=yl>bji_-ND>~si(V;_#M>7bK{|7pToB*Fu|E#CmMb;N=d{%N$Lo zt!~)mCWV5!xL&IBHmZ2?!5lD^0_q~9? zxUfOT>4lk9*`YuzR#bK*t8GOPdUMk4W2aKoIjH5+QX|?0Gl^Py4WiLX7oEd zrBi+WgOje2s&enX*sjU= z9CyOM1>+pjZHB}3Wl}M0hB9`;`D%cJ+pEuPt8h!HJMo!}hc&ZeLDQn_^k?z-wyIc? za^=e`x0ws`VZ&HPppNazqxSFkOc+9E<4r*TJnujkZmyI%$aWHMvTabxNDDl&WrW5y zi)e&I2DStiHBHN#dEu{#$mrZ6jcu_>r3;fOBxbP4cr0=Vrt@CbZ2{MOG*W^hG%s4_ z&D0}=Q}KJGf>Ih$pN|R6!uL#FcySLO>WqSt*KIdo5yaDog&lnwck>26x!O~kA6VGN zWQT?a6369^2q%r&Eye7!eXgEUpO7@ouTeS=UA!T2;3(1w>7=a@`>w83NfIvDYVJaw;{K6t){5Q7Z#n0>R#=m33{;&OCuK@UQS} zDu6)d**%A@>NZ^FnFFd8Ra+0P&7@pNP|^2})bFrzr3X894aJH=4|*&xsf4W=ehR$T zNR0~h{`}eiYHFF}M)~XD!Xe?PR?iuKH-AAwM5)b>6>X%pCCJvT=(3|FV;%HdiY~9= zM!+)!yE~B(?SvyP{swCyBG`I`sUK zqz9H0jsE@Of+8Xw30mgE{Dz}K1Qt0)&m-F^Y&x172Vd*!JRmw=lKD3Vop7e`RBpfN zysv=+a#OEOKVcF^%qqwG(gDSwLQlIKd_loqw|t0$dG(6^Tw!Nkmi1oo1rC8_>DIo{ zaOMXz(m6xQn`kfB!4&3TWl&TpAy-1rKDW{l$GI(k7Y7;zUMwFKp5}0s+iS} zpvg&HeeoQ(QFnHM`i5v&6a}IH4@7xFVsgdkntJ)WLl; z0aO^p%X zL9oGu_FeB=y$L_J1bl8xaG{l_Nk-4rW=hY7?(dv9%F4B#)H;A2IuCqnAAWfp{;a-6 z--8rrca!z{jB(GF78D8lmE896jr6nHPVmRvi2>a@-+u6;-FM?txqLsb9?3lze*a!Q zWWQ3E7o?m#>+%P0G#|V`mi-NrfO{02<^u|`Mlte3Tep^2L@3nP+)T0Fm}B9cf?&M? ztxD?|gR&z(*+ft=6g5pN7W-jKck<&a=dr`Pfx+32IRwpT>OZ9kq5)myy*Zerl>?RZ zEk~YB`yN6Du%8OO8NnB94gbh!Hd^X_c)i)K$+vP2&Uw!E03C#OyLS#s!n3EH!H@1S zy|s^`pWAz-*~6xmyq~Ub?z@0?{pI7yKjMhhJ&%L|;k4a+^WRMdb5A>r0ci8ARMq!1 z6aEKjRCPeJ3k#2A z_tx8Y^SVv_vZS>CXchCwanHPF;Ya>6eIBZ;E~k8qt&^=vh0|Th(`RAbb}Wf+Q+B;X z;|WCVkV^m)dn0pO@dYJ8YRKmyaac;><0s<$aMO$NlP3{+&cs<(-R`#-jS^KOd$z=B zUC_HmVL%1mp}q~U36s0vYy5bOaY?m($+DiE~Jt+sGRDN zD<&C>jk$n6F5P6WrQ_@{EM9SF8=;Zd^oLRY8E85W&}pJ5(0&dDU9Tcfb(8JPVU07j z$C=aA)QgXC3L|YfHB%1nVc+>t&o-RgW9y~#EWfKzm4GM_-AC|shlh3Lf_jeg5^+OG6t4GtyAd2aabMTAdz)!38B>L39 z^kA*B;-}bOrKFSGYR;1uA2bd01+*#BoN&X?tO zWxwlh53ZtSN-h# z7Q+u_Z*)MyEz`jQo}cCY!pE7R-}MjRLnb?&v9JH@&Xo05@7w+01A^Cx@ZqJ+I-nWB z9`AZ>q5E)((#Ne!*`nLc|8LP}Y4mq`OH_aLcjxWPRlket)@k`~IKyF&j2@u&0V3>i zlpn(jAQu}=_aPq0Q!64P{!7-sSfD4Yj`X4B?W2O=Yfy*<0f0^EItNSx;2%}6GLS9m z2S&$wR%i6yU-#YU^{KC6rl86J$$3%JRHi>>Vh%UTN@7;Xs0CDT*%FiTtb5Pe4M zY%}l4r7|rETbMwJy-T=rQKmt?IP#>3pIppb&G*+3p7T}zyw@)s#9Omve!$b9w3fwO zwUN=}tMVCYny~rc6loV!ywEx`Hw$_fbW4`DGd1pmHtSm%>GobN+gjzhp55?;`Lg{O zdAd*~v_pC>i>Y<@7r*W?oO2Qk3vT$6c)|7V^VF<;!kC7aPEkMA0&u!W->Uy+D^GQ? z;rE|2=vSzD`EhYEnRur}Aj=jVfF)Ys1+_qi(*chA%?#Gi-C+TJ%)Jlm_yb%IZmUGZ z1t!9Y#Qj?n9*i>qD|jsLlGCeuple<(i>k{n!UK^HOP-ZLOy5X7#lz&m)Iozn=nXqP zZ1O7nvr41mZF&5>+>6A^*^BXE)yn^9ZG}YO-e0xwkX+KkCV#&~e>xdcq)s8zFoPzC z)>+jxd)@8s1O-(6vO&G|Z^%~E`cA?}z2ennU5kd;j9)ts=C;h1&dAt$JLPY5f^lHP zC}!IYl;2r<=cda|GsZeg&zNQ2ylt7goUB{eMty6(_AmM}_OE&6jNJP^&9$n}W__C$ zR~CQ31vQ;dLEZ^?z~n^7id_~~!fO#U@SGYyEH!+WUoA7fP8;bF#_*%!vhm}cPz3Lm ztfYzn+ zC~7dZuX^?ycC8PhMz5b>-SyAD_?z5RcD{(_e*0|5@@^l2`0qVv*z~Rs2-1KXV)LWE z@2`P~OG))t(EjoG#7rfy*FVup!F{C9@i=H^vC>VGba7X) zSTTIjPScBp!K8oI7d0<^Hi}#{@qh`L$-Oi0ZtnEU6yy8tXDwhX030RXa=3$}QuEv* zJSn*J@wT2*8nVALtu>%u)95q##p0wMbA{46=3Dj4tzPd7Q{MsWWQ_^SARB4DCPz}L zN%DQmyMBg*y!6ZY!@SGY+dAD_+;mO)c!{93rt`AKgV?X{3&-o%n-QTYEDp?Ez!4({ z4Mpm(pAvOx;`fZ_NNTNGyM*P6k3_UJh(FxgXzbqS*;918QD%~W zmtj*ov#E6Lgpu{!a%|;k76`h4jE;Mw9Le=k713%;w8zdY@y_ENX;oR$ue)-A|8hiv_p)h472>f8`M195#%H##3wC7W}rFO?pi9c`4lq zu7mKkV(8}Ffn!rh6s3QD8(~I+>B>mELvV4-u zBUdAyRV(6lLk3g-wx6b7bXa7~#gX@93c~VPG#X|8Q_nF0g|3DPz!-F-i`qrUM}9c! zqyLUSY&B&jjQmM_%#$rC2)V4ejKgDDxnA*f`Rlo%&6(>B{NO(!7GwxDtZdW8#hh(LDG`aKFeV{&6o&25#+ z!@qP^d@tkChyyv_U7`+XlPj(~rWjYGzxA~H+$foRDc(T)x`L2TLm6;RRq`-FFl1li zT6*s~^Ij4^q&%jl3)4xt#It)tI1Ki(AlIbX1lJhSIQ_7HBwqjw1mzXw znk-}ZZS-G)kGhT6B@+YPt2N=h32ZR!G7At1(Dw=W2Ym+il z$B@^N5%B+&?#eYyi;%IEDS{-!rTp>>dl&K{$Xm?QPAyB8M;tc=H z`2J9AZU3a@@OQF>L3SSX=k;(H{w2!Y|D_$}cu_(J$lmF%VI zrL?7m*wolVVyG6W)``YSM{^epH+9EVPmVV5pf<2}eImJpxN$>MdS^Rah)wgYG>Jk* zgbIe`k&1J#p|{bvNBM=3=elu*=X+m~XBvRD%^pmN)n1>pcU@Aq_x4LO)ybI#7Pb~9 zcM5??cZRX@dvmIZt(G(|5FuMRO6k`n1+YB1+AQIgGf#c}bR}}yQ^LD^f>C;$d?-$s z{1Bqed}|n@3Yz-r`>A}#`0Pdn6ZOK!Hu|77<7TL+F_N0F?K|Zadz&#m5acICJuoR& zOf)>sYCFVoPIJPvZe5h zLcjx>^6z^vbZ!q~Vn@~?(_~$k$$Ug?0FF}v>W=N%x1EZ;(v`-}k*dJ^qfC28=PbEN zLVHxM?_V(ajCdxQ!k6W^YS+et8uA&-*=dV`|okJ7c;&*#>cUy)r2E7B;9!&Emqh1 zUP6Z}?S>mxJR}8&RHFCHr%qk`54sA6l$!xK6hyY@Pk6&o=?9__R((UBx$Y|i7t$IVZr$V(h~s;+()V1DY4Q&P&E z2)3FAS8c&jcH%SFCmoNTSfI1XlwmtuCr31$!266+@7L-kH;4#F;Opv-DNO=OY^KB3 zkL|{12rhNq$~o{C5@GimOd2pOg4**=D0oP`4Q1V1I6HzT_#JF-G>NEmwxCrJCS60V zVr=|c7fboMgmUaTVsr#Ju^7_BlshX+hF}GpuzdU!+Dh}QMMu46wAmt%T=*#S^e67? zJXe91;Mg9r{G9cH>x_DQQd0M|7Gp%nq7+*9$vt*?(jqLSvFE6_aA1kldHQ4#lSU)` zwg4v+%T?Fd6AU!;+@ma)W5yp0#UG<28!^Z4zGakBDi zU)?A_9tNifM7{>4WqS2k5|b2a34PCO0E9n~D#zk8{hjYvPguK=)DkK2@8*Z}jt?mO zk|393X%mfVv6%4TNqljOe=@ng@uM%7iNE)(T5#U7Y}SyW8TQ2U8rapG@p*C2d2T$N-nB1}A71_t6>6dC&WC*RRu1kraa@!C2%#ET8u|4#s9v7}2%pOawd>{g?-XMQ+k@v%Cl;hZU z_s)$+w@@IhG>R#1u;)AIm@}&@Ct&wx5oNy0w%$d;7Y1qvyYFOKVYRI&U)U0~MqDFJm zBM>wR>#N@3HpEd=m`jM5IuhUo_- zcfn1#y~JOVMbrM&FJR+WjL)Ro)OS5}m^=9$?8y|*4RUAe1o8Q`|A3Pl1L9y%xIk+x zUoMs>G4xJgmn9-}%d70m_YNfndXxuh<-r7gMMKi$6g!Tr2`TooNucTJeW_lgu)6&e zzcQrx2FV{uCqP6KB!crAzQE%tr|A28C8XWRWooGFRlPgG&EEY(O5g5X-WBX{2RMBZa4iGpNjuQ1RT z%qM9h*AP*6t>KU|aNxqTud$-5HkeR|93B%l({8p~5jXMw;;zI;cxEbmuzPtqR%DeC7gBf~Wdf{(79tTM*4q7$8z2cKZ) z3SMGDL^R<5bm3QzU5&o}*8y)%=PXwvu?W|}BX7heT0p~S}rfHO} ztq@mEFv3lGx)5E{xx29JhxThW89+uAC?N!+vE+==BDfcacb7wB886Jm<~fXa8n4pe zg)j2MU}Tc4Z!3!b8kHU5vCQ0GW*=w&wz~CFj!^h0LLuQXPv2xylTG!_P>?*;t#(FD z9k@9*%vf|kS^`G#R(KDe*Df|}BgfNjSO1FIF8$1-Jw)SKDm+D!IQ3)tm!AIaWzfTe zekky>k_bRi>UylEu4mNuxf9O3IIH93J43eT-R(O`<%H|#VZ7UvAHce5q_ty)r`Pqf z{W?o6D5Zbsewntx4{rn`xLM&JegR`m+Q+;13EuSuN)ytg%pxw*FwBw4#{h0xM!?A= z%7u-dlqIp=`O#w5zJ_)oJyU<3Wh}-t9S6l%Rt>4OiM^4xBsj=}L{!Gaa#jlfr)-RI zTTg!aoDgq_0++>$@&--$1&>HQWi2tQ7h0^6^6^!-szvb39Mq<)%m3lFxg>QQ#ET|1 zrjK=-qqM&IbL2zh0^@wTHqH+itCYUWW0*7sm+YHChDml+5ox(5;5mt>>nwkF`2B<`Oiw=1ZyrwN@3YlPo%oVF}4ZW8-6 zQYVDwg7Vp!s*_xfYSp-(ikb>D$X7?p6D>782S1(zm<=`@GC#HgYVEWU%n_W3y(0qV z6e{m9gS=ia)W!qz5C#tkbBNsM*}Xcewn#eH{ogptl3$?szC^#6h&l8;8m>avUg_u* zlWQBOd;j%vqL7Z9?|KnCvcN4@YtR}c?<}1QHKNBETaCU9TNeU9`aTQ>bWQhf4d6YF zz57}FXaM1y{8&JN?%q|5s~TGUlj6i+8bG4PY7IfG#5*aaa8+t5Rq4digR?oBda z7|~0`FFD=MWJSDel=$k3z~swQ!SJjjGP(u*32eqedgVCxb5US)n2zVpuPqgRs2AuD!+9f==q;`}#!)#=BLy88zWnl_JBa^DG^B-AfSn+f%$_b)(j}ke&C7ta5n6%%g4c`{?5}0TdZk zWRS@>LfSY9{}_NSokLGF$fxFmyaHoPSk{iV>VTVdYWqpr4NWlL>YP+jYxDtnDXUWm zs?avy$IGWz{|(4>(r2qTEh3lC2==#V%}!^MK>^bUX}T=(8X54czMz=@H<4C)T`F<0 z>W1Q~(j&o4>2`oXGNb*)Tm}UR6t_$6)NG={3nOLA+CX_Hi|yF(pY0 zPv*D<*TUG5>2TKC2v})FH}u}W4r8rt!MlqV8YM9<-?6&lfPQGsCvbYA!`6;UTz#KC%-X{{O}kkD9b{|_62V^6N1RQV&!1XV(^CU4x79+X)g-ePzjCCc4`;n?p6( z`sm)vuBtL@a(bpCScsyUsI&C35xr9hNSk3MNF(J^(l1_2!+-ysdy7j_sxsSLV+1Ff z(8DH_6CBJ-w^XucmCKw}Kot|c%{q^? zwMm4pLX$RQL+pi5NYHu}=vkmmd3q-?`0JgnbXSu~xq`2^?tYEF5$Hb81OChW9nQ%9 zTq0R(m6eScgp>5~iQ~QW89P1wS^;^BpVu1>W$h_6u#0cQ!1Jwq3?vKeu5z7uSf*JR&Nn?P}?N7s;KvJH*l8)15||bOLxrZY28&`{H(MUqm1EcAeBHUviQO zya+$GhsWQ!@Aga^6qbY6^#5Ksyrnpc0xARJ>eCli3csSX1Eq;AhIt2r5+!$)7)XNa za5rf-eeqUWYq}p>40~xWD!Qu*r-}1j;yEz5QaesCALw_&Me#YStrR`_G;5x;f=OU= z$(%vnaDH`?4>>sadR0HuxAI_LmVA&3Lh1|F13)Dh{uq_AR`NCZd+=#*H_ZPeizXdh zlZLl!i_liqy22*xw92SHG9HrqY==C(NIA1@Hl_wDT&q;rS zp0Vd#$~R{8YOO62nB}eOe9l}RM?T8u5)VJ~1^;+_0bEdog*3eIzdIG$9-zd~pxtN~ zMRz1DIc44omlU&;Ia}Vwja5lXbPnN3uILLys%h~`@R0^qv8oD?uaae*`yV_O^t#lvP?1$x`#aYrUoIVB z%7=MkC}fnRHRQ2bs1}(!?Ir|aS_5wP^pAgj2sBE)Kwh?b(JH^+7MK~;_jko?67DFo z8sz)4?~6Q-7me8U6~X@f@aFEUBwaZZnVo(u{?|-O+j`|Kh0E(~uhFE-l6zeqTPqJ3 z(Mny{trAUrXlA8fYv}p46+!OEF496h2aV^WvW#$5+nSzF%Ltz(5mgM|cYy&n|I~Fk zjXgyxB-Htd=xIb5P{_|!9nOoM2*#=>7Ze0$)I)v&{Nn5c?pl7HZO4|vx9^xeY1(7`CbiO5)P6aX33yY ztsH}!5WZ(X!jQhAu9wBW!@G7!`)5LJ$+`2TvmO*JZ5kvC-i0N-@J&NUU*?lVUNCu# z-mF)~7&ibIhhOhHpTL?V|r2&Wu7;4!hVasD|sF%f-k=W z^UYVRArp?-5{UhYnDEaqbOzBDsB9U!Dp`K2|Ei!ug&Jg5p#}<}0Go~r6nKZiuCM)J zp9q#^AU;KTv2#Ksb+1PxfSW0T*m;UAmC;i~R#r(WP=2Oj{9A?Fm@;Fz3pr}GiJ%)( zHg*@lnqQV`I!(#b3XVOTAxD81M(KG1wee1vRj2W*;$0DrU#6eCZ4Y~07~xPR9Hx>Q zI-aVn^$?M+(YYO;GVL>7J{T~MUKuJGqiC%oxLLi*`=`}VqRic^F*VI|zJew$ChDkU zN;?di72wG1cg}UlfP)_f0xE2XX?BoHDFmWcpr_3<4}F&C{+*IX9l!ea>-)%{1p(0+ zyxK@EFHRSdALRy_o-xuFjH=z+!+>awFx@NW8^pL|DLVZmLPJ!DhTVj&RSac_3Nckh zhT5<6n5vx$Heu-iqkY-EA~c^-XW=Y?E;?AZ(@e}}-GMuQV0`D`dW9z8$=SMc={{RR z@GVCvnw=qRYc<(`od?5FyI>@bXHSKJ(6MWe^VN875LsF3RinYHa;aI1PCoks@G!^! zwRmyId~2Dwl_BMfnS#S!lS3jS!iz_r+~;M|%WKC6&%t)K#wgASlE$Z@8h^)thy|r` z49VO3TwW7`>M?b;|$wGys-p3vq%$D?Xs!K^_dLd)=-r zxouI2#N%%Int7S3L!W9}R#XOVP0wu#hbH9#W}BjU#Ms=2O}Kp43XYh1NggbBIwE`` z5`YoE26%2Tg}+qrKgv)~{9gb~K(fCi4K;>r(yjrDm8#~mEnnqK1rFfgMW*`Du$#6_uYEVj}VVkqf!prF;z9e9-5I2wZCJ(MlS!BV1 z-5{St2=2oPmk4&n4hl)(v)LO7I6dlH2_&~ZSi2++ z>out8izOz^|2+z?==7Wr8H_< zl7sB+KJ=41+zqxF%D-wfTtXCkLv6_kMJat60tj^!Zh-=;qe(lFYwWDnFe!_Uf4_bb+PtRF5dTxY=k{{qhD$wG&mb`TWQOmVgWd@jFIJUYD6l`IB<)-S5B1~l& zfwC!Ur|$cnPffb~Yhjl83=hkw5rh0vmpSd`lW!l}y~iitU-5a5@0l{ZR6{{#4Zc`I z)yM+fH&w}q4L-4vY~mX{;Nk41+-jxxAsdD&Y)Ae;fJ=!QJK16j>y+fs(gx*^m>Syl zbB#ZcFfK+Pw%8_Cmyl(JQj;H!o@=6p{ig44Dq#A_jd&RCw%sI~j_h@wjl$m|`qCdX zUD`)Q9&R6b``uzr+3bjwhPhtTHauAg&p1B`L+(UmC9g8dtC8P=jbCg(GNt^J%LFO) zy%@Y>Gi-oBmf3`v66v&Af~p6&r29}N+yfH2TvMz|txjh7@u6U{r`scKLm42d%KIQO zcCR92px(zvhL~Q4nlaJ4d)VznnfzO8@oVWw=}fR``MW}Sn!$iEqj^2Jm|$ya`FrrN z^e7LCT3Vj+4ymLrXSDgQ73HMzNs~b|Ks^~8Gu*SOt|hZ&H2zA6z)5v03Ta*W1xtCs z-O82bmu}%%m@k*CS$SKPxI0w~n^GN2X$g~vtChfoiSoO;9K4IAR$3X->%&>_H(>^%-nId2aaSX zwY^3g9;hMQ&XuDRBs+&rdi1KMvxv`MGW@)YZdVVoUb_cC^+RQrCrUyCnH{?BqwNmg z2gv(H#=zX~r55V1#YXyd(`8nze79#KG4WTV|Peliczv zb`>2+$pITlFE!yp`7P|3Wy*#z|Gd&q z3wO_DJdI^vb8*V{xd-!0Z((gVN;cU^aA?xeZ_*da{CQG3(L(`x=D{`@_hThWwL0}~c@XYd!a zeMd}3cJD&Ckdtw93IK`phW&qa74wmlgSa2w=c#DVI?Hzb4coP@T+;BdE@`CCA|D1A zm*X2pojv350a~CS274M7knqJqk!U;-P6ud->60yjL1zKh_(>Qv;Epouo?Cp!ez zXuwJ4)WZLnx`*MU%K5fR{#PZ1Z5>Q0o78`R9@*#!VZ-~~BtZ26x+T_ECIp&!RDQeu zwV!#4x#Epmhwh*F9d`$Ido{)GMONp4T6aDaA=3DEbn=POX@#Tnpesa34uT{*I%1;N zWoWrouPZNVs!aj7|DV=cSd_~^79J?hAhmJ?JQeL3#>)VAvB_$NwQTq(ZIcqjX>-tq z6DX4sGoCM#g$+sWJb%ZfeN!EozpkyK?At0H{n2^F!)43QS$n6Kr}SH$;+q;Hr8PQ` zKbA}81O6b;q=2M{KVMH>4~OCc*4fj0m1~)4Pabse^oe_A8Jdq(FIoE$Rh|Fo`+N*i zFuj%Q1wZtK$OO@&^CfSmGgClY&w5YUe6q4raU=H#ixKK!Z$R)UqM=UhC04SPnPx9Sf7L5X zZuPb7!x)4yk2DPhHc#JQdG3G!>AW$ZD0}59w8xrseT`RmDzxcQaH*~7X=`d{se3{o z^O@&1Ip*evN%NK8v>R1BI%iKVT)kAX+f(ZuygXsU`wdm;(V{2@Q~h(1RA1a5y|@Mo3tU zs8;t7Z99D`hzN)Uo)wC}1%#vVb`Me3;=4xuN1+REAl;CSGytRkJA8t%XIw_74@V$? zkR(nfuay|zvtUbQKTT^Bv(oJnTgOu4f9cY_U7N?zJ0G64t}s54Y;n$Y83NiV6XUAsWh8_%h5Qi#!^Ma=OwCPk{EJHkwMM(g=YmRbUD_xvg?q zP0syg@!B|bcbZh(T$hanMJ`AV2xv-0lEZ&~O<=efrV+a~^9@~b6X=hCk?ZNprCi

    dKx32QsO$ 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%0DYfZCA2jZ9T5(lzcII7?+v% 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⁢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 X(Yuayj8SH1Aq)Ah*k9!V9{>OVtL7TN diff --git a/site/docs/docStyles.css b/site/docs/docStyles.css deleted file mode 100644 index b2c69fee..00000000 --- a/site/docs/docStyles.css +++ /dev/null @@ -1,375 +0,0 @@ -* { - margin: 0; -} /* reset */ - -body { - font-family: "Times New Roman", Cambria, "Cambria Math", Georgia, serif; -} - -body { - font-size: 18px; -} -@media (max-width: 830px) { - body { - font-size: 16px; - } -} -@media (max-width: 740px) { - body { - font-size: 16px; - } -} - -main { - position: absolute; - top: 0; - padding: 0px 2.5px 0px 2.5px; -} - -#sidebar { - position: fixed; - top: 0; - margin: 0px 2.5px 0px 2.5px; - overflow: fixed; -} - -#demo { - margin: 0px 2.5px 0px 2.5px; - overflow: fixed; -} - -@media all { - #sidebar { - left: 50px; - width: 245px; - } - #sidebar.narrow { - width: 100px; - } - main { - left: 330px; - width: 580px; - } - main.sptable { - left: 190px; - } - main.comp { - left: 200px; - } -} - -@media (max-width: 880px) { - #sidebar { - left: 0px; - width: 20%; - } - main { - left: 24%; - width: 75%; - } -} - -@media (max-width: 670px) { - #sidebar { - left: 0px; - width: 5%; - } - main { - left: 7%; - width: 90%; - } -} - - -h1, -h2, -h3 { - font-family: Verdana, sans-serif; - font-variant: small-caps; - letter-spacing: 0.05em; - margin-top: 3em; -} - -h1 { - font-size: 140%; - margin-top: 1em; -} -h2 { - font-size: 110%; - margin-bottom: 0.5em; -} -h3 { - font-size: 110%; - margin-bottom: 0.5em; - margin-top: 0.8em; -} -h4 { - margin-bottom: 0.5em; - margin-top: 0.8em; -} - -p { - margin-top: 1em; - line-height: 1.35; - text-align: justify; -} - -hr { - margin: 1em; -} - -/* Style subscripts and superscripts to avoid wide line spacing. */ -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} -sup { - top: -0.5em; -} -sub { - bottom: -0.25em; -} - -.direct { - font-family: "Cambria Math"; -} -.reduced { - font-size: 80%; -} -.dim { - color: gray; -} - -.indented { - margin-left: 2.5em; -} -p.indented { - margin-top: 0.25em; - text-align: left; -} -.indented p { - margin-top: 0.5em; - text-align: left; -} - -table { - font-size: inherit; - border-collapse: collapse; - width: auto; -} - -div > table { - margin-left: 0; -} - -table td { - padding: 0.3em 0.8em 0.3em 0.8em; - vertical-align: middle; - hyphens: none; - white-space: nowrap; - border: 1px solid #ddd; -} - -table th { - font-size: 95%; - padding: 0.3rem 0.5rem 0.3rem 0.5rem; - line-height: 1.05; - border-bottom: 1px solid #ccc; - white-space: nowrap; -} - -table tbody tr:nth-child(even) { - background-color: #f6f8fa; -} - -/* Column alignment. Apply these classes to the table node. */ -.c1r td:nth-child(1), .c1r th:nth-child(1), -.c2r td:nth-child(2), .c2r th:nth-child(2), -.c3r td:nth-child(3), .c3r th:nth-child(3), -.c4r td:nth-child(4), .c4r th:nth-child(4), -.c5r td:nth-child(5), .c5r th:nth-child(5), -.c6r td:nth-child(6), .c6r th:nth-child(6), -.c7r td:nth-child(7), .c7r th:nth-child(7), -.c8r td:nth-child(8), .c8r th:nth-child(8), -.c9r td:nth-child(9), .c9r th:nth-child(9) { text-align:right } - -.c1c td:nth-child(1), .c1c th:nth-child(1), -.c2c td:nth-child(2), .c2c th:nth-child(2), -.c3c td:nth-child(3), .c3c th:nth-child(3), -.c4c td:nth-child(4), .c4c th:nth-child(4), -.c5c td:nth-child(5), .c5c th:nth-child(5), -.c6c td:nth-child(6), .c6c th:nth-child(6), -.c7c td:nth-child(7), .c7c th:nth-child(7), -.c8c td:nth-child(8), .c8c th:nth-child(8), -.c9c td:nth-child(9), .c9c th:nth-child(9) { text-align:center } - -ul { - padding: 0; -} - -ol li { - position: relative; - left: 2.2em; - width: 88%; - line-height: 1.35; - margin-top: 0.5em; -} -ul li { - list-style-type: disc; - line-height: 1.35; - margin-top: 0.5em; - position: relative; - left: 1.8em; -} - -ul li p { - margin-top: 0; -} - -a { - text-decoration: underline; - color: black; -} - -pre { - margin: 0px; - padding: 12px 12px 12px 12px; - line-height: 1.5; - display: block; - overflow: visible; -} - -code { - font-family: Consolas, "Courier New", Courier, monospace; - font-size: 85%; - /*color: #404040;*/ - background-color: rgba(27, 31, 35, 0.05); -} -pre > code, -td code { - background-color: transparent; -} - -.no-sup { - color: dimgray; -} - -#input-container { - font-size: 0.9em; - width: 100%; - height: 3em; - border-radius: 4px; - border: 1px solid rgb(200, 200, 200); - display: inline-block; - padding: 0.5em 0.5em; - vertical-align: top; - resize: none; -} - -#demo-output { - font-size: 0.9em; - width: 100%; - height: 5em; - padding: 1em 1em; - vertical-align: top; -} - -summary { - outline: none; - cursor: pointer; -} - -.mobile-menu { - position: absolute; - background: #fff; - border: 1px solid #aaa; - padding-right: 3em; -} -.mobile-menu summary:after { - content: none; -} - -/* Table of Contents, sidebar version */ -#sidebar { - cursor: pointer; - font-family: Calibri, sans-serif; - padding-top: 0.5em; - background: #fff; -} - -#sidebar li { - list-style: none; - line-height: 1.35; - position: relative; - margin-top: 0em; - left: 0em; -} - -#sidebar ul li ul { - padding-left: 1.3em; -} - -#sidebar ul li ul li { - margin-top: 0em; - width: 88%; -} - -#sidebar a { - text-decoration: none; - color: black; -} - -/* Table of Contents, mobile version */ -#mobile-nav { - display: none; /* hidden on large screens */ - position: fixed; -} - -/* On small screens, switch from sidebar TOC to navicon and drop-down menu */ -@media screen and (max-width: 670px) { - #mobile-nav { - display: block; - } - #sidebar { - display: none; - } -} - -#mobile-nav ul { - position: absolute; - top: -9999px; - left: -9999px; - display: block; - background:#fff; - border:1px solid #aaa; - padding-right: 3em; - color: black; - display: block; -} - -#mobile-nav input[type="checkbox"]:checked ~ ul { - top: 26px; - left: 25px; -} - -input[type="checkbox"] { - display: none; -} - -#mobile-nav li { - list-style: none; - margin: 0; - padding: 0.2em; -} - -#mobile-nav li a { - width: 60px; -} - -#mobile-nav a { - text-decoration: none; - color: black; -} diff --git a/site/docs/en/administration.html b/site/docs/en/administration.html deleted file mode 100644 index 4f5dc224..00000000 --- a/site/docs/en/administration.html +++ /dev/null @@ -1,254 +0,0 @@ - - - - - - Temml Administration - - - -

    -

    Temml Administration

    -

    Browser Support

    -

    Temml works in browsers that support MathML. This includes Firefox and Safari. It will soon include Chrome, Edge, Opera, Brave, and Vivaldi.
    Temml will never work in Internet Explorer.

    -

    Installation

    -

    You can download a zip file of Temml from the releases page of the Temml repository and serve Temml files from your own site. The minimum browser installation needs the following files. The css file and font file must be in the same folder.

    -
    • temml.min.js
    • -
    • Temml-Local.css
    • -
    • Temml.woff2
    • -
    -

    A server-side installation should include temml.cjs instead of temml.min.js.

    -

    Starter template

    -
    <!DOCTYPE html>
    -<!-- Temml requires the use of the HTML5 doctype. -->
    -<html>
    -    <head>
    -        ...
    -        <link rel="stylesheet" href="./Temml-Local.css">
    -        <script src="./temml.min.js"></script>
    -    </head>
    -    ...
    -</html>

    API

    -

    Overview

    -

    Say that you have an HTMLCollection of elements whose contents should be converted from TeX strings to math. And also say that you wish to define two macros and a color with document-wide scope. The code for such a conversion might look like this:

    -
    // Optional preamble.
    -const macros = temml.definePreamble(
    -    `\\newcommand\\d[0]{\\operatorname{d}\\!}
    -    \\def\\foo{x^2}
    -    \\definecolor{sortaGreen}{RGB}{128,128,0}`
    -);
    -// Render all the math.
    -for (let aSpan of [...mathSpans]) {
    -    const tex = aSpan.textContent;
    -    const displayMode = aSpan.classList.contains("display");
    -    temml.render(tex, aSpan, { macros, displayMode });
    -}
    -// Optional postProcess to render \ref{}
    -temml.postProcess(document.body);

    Below, we examine the parts of that code.

    -

    In-Browser

    -

    To render math in one DOM element, call temml.render with a TeX expression and a DOM element to render into:

    -
    temml.render("c = \\pm\\sqrt{a^2 + b^2}", element);

    Server-Side

    -

    To generate MathML on the server or to generate an MathML string of the rendered math, you can use temml.renderToString:

    -
    const temml = require('./temml.cjs');  // if in Node.js
    -const mathML = temml.renderToString("c = \\pm\\sqrt{a^2 + b^2}");

    Preamble

    -

    To give document-wide scope to a set of macros or colors, define them in a preamble.

    -
    const macros = temml.definePreamble(
    -    `\\newcommand\\d[0]{\\operatorname{d}\\!}
    -    \\def\\foo{x^2}
    -    \\definecolor{sortaGreen}{RGB}{128,128,0}`
    -);

    Any valid Temml macro or \definecolor may be written into a preamble. Then include the resulting macros in the Temml options.

    -

    Options

    -

    You can provide an object of options as the last argument to temml.render and temml.renderToString. For example:

    -
    temml.render(
    -  "c = \\pm\\sqrt{a^2 + b^2}",
    -  element, 
    -  { displayMode: true,  macros }
    -);

    Available options are:

    -
    • displayMode: boolean. If true the math will be rendered in display mode, which will put the math in display style (so \int and \sum are large, for example), and will center the math on the page on its own line. If false the math will be rendered in inline mode. (default: false)

      -
    • -
    • macros: object. A collection of custom macros. The easy way to create them is via a preamble, noted just above. Alternatively, you can provide a set of key-value pairs in which each key is a new Temml function name and each value is the expansion of the macro. Example: macros: {"\\R": "\\mathbb{R}"}.

      -
    • -
    • annotate: boolean. If true, Temml will include an <annotation> element that contains the input TeX string. Note: this will defeat soft line breaks in Firefox. (default: false)

      -
    • -
    • elementIsMath: boolean. When you call the temml.render() function, you pass an element as an argument to the function. If that element is a span, then allow elementIsMath to remain false (the default), and Temml will create a new <math> element inside the span. It you pass a <math> element as the argument, then set elementIsMath to true. Then Temml will populate it with math contents.

      -
    • -
    • leqno: boolean. If true, display math has \tags rendered on the left instead of the right, like \usepackage[leqno]{amsmath} in LaTeX. (default: false)

      -
    • -
    • preventTagLap: boolean. This option affects the horizontal alignment of displayMode math and \tags. The default (false) acts in the LaTeX manner and centers the math. That’s good in a wide container, but if the container is narrow, the tag will overlap the math. The preventTagLap: true option acts differently. It will first place the tag and then center the math in the remainder of the container, with no overlap. If you are targeting mobile, preventTagLap: true is probably a good choice .

      -
    • -
    • colorIsTextColor: boolean. In LaTeX, \color is a switch, but in early versions of MathJax and KaTeX, \color applied its color to a second argument, the way that LaTeX \textcolor works. Set option colorIsTextColor to true if you want \color to work like early MathJax or KaTeX. (default: false)

      -
    • -
    • errorColor: string. A color string given in the format "#XXX" or "#XXXXXX". This option determines the color that unsupported commands and invalid LaTeX are rendered in. (default: #b22222)

      -
    • -
    • maxSize: [number, number]. This provides a way to cap all user-specified sizes, e.g. in \rule{500em}{500em}. The first number is the cap in em units, which will be applied to user-specified relative units. The second number is the cap in CSS pt units, which will be applied to user-specified absolute units. The default is [Infinity, Infinity], which allows users to make elements and spaces arbitrarily large.

      -
    • -
    • maxExpand: number. Limit the number of macro expansions to the specified number, to prevent e.g. infinite macro loops. If set to Infinity, the macro expander will try to fully expand as in LaTeX. (default: 1000)

      -
    • -
    • strict: boolean. If false (similar to MathJax), allow features that make writing LaTeX convenient but are not actually supported by LaTeX. If true (LaTeX faithfulness mode), throw an error for any such transgressions. (default: false)

      -
    • -
    • xml: boolean. If true, Temml will write a namespace into the <math> element. That namespace is xmlns="http://www.w3.org/1998/Math/MathML". Such a namespace is unnecessary for modern browsers but may be helpful for other user agents. (default: false)

      -
    • -
    • trust: boolean or function (default: false). If false (do not trust input), prevent any commands like \includegraphics that could enable adverse behavior, rendering them instead in errorColor. If true (trust input), allow all such commands. Provide a custom function handler(context) to customize behavior depending on the context (command, arguments e.g. a URL, etc.). A list of possible contexts:

      -
      • {command: "\\url", url, protocol}
      • -
      • {command: "\\href", url, protocol}
      • -
      • {command: "\\includegraphics", url, protocol}
      • -
      • {command: "\\class", class}
      • -
      • {command: "\\id", id}
      • -
      • {command: "\\style", style}
      • -
      • {command: "\\data", attributes}
      • -
      -

      Here are some sample trust settings:

      -
      • Forbid specific command: trust: (context) => context.command !== '\\includegraphics'
      • -
      • Allow specific command: trust: (context) => context.command === '\\url'
      • -
      • Allow multiple specific commands: trust: (context) => ['\\url', '\\href'].includes(context.command)
      • -
      • Allow all commands with a specific protocol: trust: (context) => context.protocol === 'http'
      • -
      • Allow all commands with specific protocols: trust: (context) => ['http', 'https', '_relative'].includes(context.protocol)
      • -
      • Allow all commands but forbid specific protocol: trust: (context) => context.protocol !== 'file'
      • -
      • Allow certain commands with specific protocols: trust: (context) => ['\\url', '\\href'].includes(context.command) && ['http', 'https', '_relative'].includes(context.protocol)
      • -
      -
    • -
    -

    Post Process

    -

    The postProcess function implements the AMS functions \ref and \label. It should be called outside of any loop.

    -

    The main Temml functions, temml.render and temml.renderToString, each operate on only one element at a time. In contrast, the postProcess function makes two passes through the entire document. If you choose not to support \ref, postProcess can be omitted.

    -

    If Temml is used server-side, \ref and \label are still implemented at runtime with client-side JavaScript. A small file, temmlPostProcess.js, is provided to be installed in place of temml.min.js. It exposes one function:

    -
    temml.postProcess(document.body)

    If you do not provide a runtime postProcess, everthing in Temml will work except \ref.

    -

    If you use the auto-render extension, it includes the post-processor nuances.

    -

    Fonts

    -

    Temml has several different pre-written CSS files. You should use only one and by that choice, you also choose a math font. There are several math fonts available and each has different advantages.

    -

    Cambria Math comes pre-installed in Windows, Macs, and iOS, so it is the light-weight option. Cambria Math lacks roundhand glyphs, so you still have to serve a small (12 kb) font, Temml.woff2, in order to support \mathscr{…}. Sadly, Cambria Math radicals are sometimes too tall for their content.

    -
    More… -

    You can mitigate the radical problem. It occurs because the font expects a cramped subscript when under a radical and Firefox does not perform that cramp. You can create your own cramp with braces. The expression f{_c'} will render just fine when f_c' renders poorly.

    -
    -

    Latin Modern is a clone of Computer Modern and so is very home-like for readers accustomed to LaTeX documents. Rendering is excellent except that some line thicknesses may be too thin for some screens. This option also needs that additional 12kb Temml.woff2 file in order to support \mathscr{…}.

    -

    Asana, STIX TWO, and XITS can be served without the Temml.woff2 file.

    -

    Several other math fonts exist and you can try them out at Frédéric Wang’s Mathematical OpenType Fonts.

    -

    Where to find font files:

    - -

    If you want a different math font size, you can add a rule to your own page's CSS, like this example:

    -
    math { font-size: 125%; }

    Equation numbering

    -

    In order to place automatic equation numbering in certain AMS environments, Temml contains these CSS rules:

    -
    .tml-eqn::before {
    -  counter-increment: tmlEqnNo;
    -  content: "(" counter(tmlEqnNo) ")";
    -}
    -body { counter-reset: tmlEqnNo; }

    You can overwrite the content rule to produce customized equation numbers. For instance, if chapter three of your book is in its own html file, that file’s <head> could contain:

    -
    <style>
    -   .tml-eqn::before { content: "(3." counter(tmlEqnNo) ")"; }
    -</style>

    Then the automatic equation numbering in that chapter would look like: (3.1)

    -

    If your site does not render automatic numbering properly, check if your other CSS has overwritten the Temml counter-reset.

    -

    Extensions

    -

    More Temml functionality can be added via the following extensions:

    -
    • auto-render: Find and render all math in a running HTML page.
    • -
    • mhchem: Write beautiful chemical equations easily.
    • -
    • physics: Implement much of the LaTeX physics package.
    • -
    • texvc: Provide functions used in wikimedia.
    • -
    -

    To install extensions for browser use, include the appropriate file from the contrib folder of the Temml repository. Then reference the file in the <head> of the HTML page. As in this mhchem example:

    -
      <head>
    -    ...
    -    <link rel="stylesheet" href="./Temml-Local.css">
    -    <script src="./temml.min.js"></script>
    -    <script src="./mhchem.min.js"></script>
    -  </head>

    The extension reference must come after the reference to temml.min.js.

    -

    For server-side use, just use temml.cjs instead of temml.min.js. temml.cjs includes mhchem, physics, and texvc.

    -

    Security

    -

    Any HTML generated by Temml should be safe from <script> or other code injection attacks.

    -

    A variety of options give finer control over the security of Temml with untrusted inputs; refer to Options for more details.

    -
    • maxSize can prevent large width/height visual affronts.
    • -
    • maxExpand can prevent infinite macro loop attacks.
    • -
    • trust can allow certain commands that may load external resources or change HTML attributes and thus are not always safe (e.g., \includegraphics or \class)
    • -
    -

    Of course, it’s never a bad idea to sanitize your HTML. If you so choose, there is a list of Temml tags and attributes below the fold.

    -
    More… -
    allowedTags: [
    -  'span', 'img', 'math', 'annotation', 'semantics',
    -  'maction', 'menclose', 'mfrac', 'mi', 'mmultiscripts',
    -  'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot',
    -  'mrow', 'mspace', 'msub', 'msup', 'msubsup', 'msqrt', 'mstyle', 'mtable',
    -  'mtd', 'mtext', 'mtr', 'munder', 'munderover'
    -],
    -allowedAttributes: {
    -  span: ['style'],
    -  img: ['src', 'alt', 'width', 'height'],
    -  math: ['xmlns', 'display'],
    -  annotation: ['encoding'],
    -  maction: ['actiontype'],
    -  menclose: ['notation', 'mathbackground'],
    -  mfrac: ['linethickness'],
    -  mi: ['mathvariant', 'style'],
    -  mn: ['mathvariant', 'style'],
    -  mo: ['accent', 'fence', 'form', 'height', 'largeop', 'mathvariant', 'mathcolor', 'movablelimits',
    -       'separator', 'stretchy', 'linebreak', 'minsize', 'maxsize', 'lspace', 'rspace'],
    -  mpadded: ['width', 'height', 'depth', 'lspace', 'rspace', 'voffset', 'mathbackground', 'style'],
    -  mrow: ['data', 'href', 'id'], // See `trust` rendering option.
    -  mspace: ['mathbackground', 'width', 'height'],
    -  mstyle: ['displaystyle', 'mathcolor', 'mathsize', 'scriptlevel', 'style'],
    -  mtable: ['columnalign', 'rowspacing', 'columnspacing', 'columnlines', 'rowlines',
    -           'width', 'scriptlevel'],
    -  mtd: ['columnalign', 'style'],
    -  mtext: ['mathvariant'],
    -  munder: ['accentunder'],
    -  mover: ['accent']
    -},
    -allowedClasses: [
    -  // Temml creates these classes:
    -  'mathcal', 'mathscr', 'oldstylenums', 'temml-error', 'tml-eqn', 'tml-tageqn', 'tml-label', 'tml-tag'
    -  // If the trust setting allows \class, then users can create their own classes.
    -]
    -// The \label function can create HTML ids. These ids can contain only the characters [A-Za-z_0-9-]
    -// An \id function, if allowed by the trust settings, can create HTML ids with unrestricted contents.
    -
    -

    Copyright © 2021, 2022 Ron Kok. Released under the MIT License

    -
    -
    - -
    - - - - -
    - - diff --git a/site/docs/en/comparison.html b/site/docs/en/comparison.html deleted file mode 100644 index 7aa08487..00000000 --- a/site/docs/en/comparison.html +++ /dev/null @@ -1,9732 +0,0 @@ - - - - - Comparison of TeX Coverage - - - - - - - - - - -
    - -

    Foreword

    - -

    This page compares the MathML output from four TeX-to-MathML conversion libraries. You should use Firefox or Safari to view this page because they can render the MathML today. MathML will be viewable in Chrome and Edge soon.

    - -

    MathJax and KaTeX of course also render math in other formats. This comparison is limited to MathML.

    - -

    Versions used are: Temml 0.6.9, MathJax 2.7.5, KaTeX 0.13.9, and TeXZilla 1.0.2.0

    - -

    Symbols

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Symbol/FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    +a+b\(a+b\)a+ba+ba+ba+ba+b
    -ab\(a-b\)aba-baba-ba-b
    !n!\(n!\)n!n!n!n!n!
    \!a!b\(a!b\)a!ba!ba!ba!ba\!b
    #y2\(\def\bar#1{#1^2} \bar{y}\)y2\def\bar#1{#1^2} \bar{y}Not supported\def\bar#1{#1^2} \bar{y}
    \##\(\#\)#\##\#
    %\(%a comment\)%a commentNot supported%a comment
    \%%\(\%\)%\%%\%
    &abcd\(\begin{matrix} a & b\\ c & d \end{matrix}\)abcd\begin{matrix} a & b\\ c & d \end{matrix}abcd\begin{matrix} a & b\\ c & d \end{matrix}\begin{matrix}
       a & b \\
       c & d
    \end{matrix}
    \&&\(\&\)&\&&\&
    '\('\)'Not supported
    \'aˊNot supportedaˊ\text{\'{a}}Not supported\text{\'{a}}
    ((\((\)((((
    ))\()\)))))
    \a b\(a\ b\)a ba\ bNot supporteda\ b
    \"a¨Not supporteda¨\text{\"{a}}Not supported\text{\"{a}}
    \$$Not supported$\text{\textdollar}Not supported
    \,ab\(a\,\,{b}\)aba\,\,{b}aba\,\,{b}a\,\,{b}
    \.a˙Not supporteda˙\text{\.{a}}Not supported\text{\.{a}}
    \:ab\(a\:\:{b}\)aba\:\:{b}aba\:\:{b}a\:\:{b}
    \;ab\(a\;\;{b}\)a    ba\;\;{b}aba\;\;{b}aa\;\;{b}
    _xi\(x_i\)xix_ixix_ix_i
    \__\(\_\)_\_Not supported
    \`aˊNot supportedaˊ\text{\'{a}}Not supported\text{\'{a}}
    <<\(<\)<<<<
    \=aˉNot supportedaˉ\text{\={a}}Not supported\text{\={a}}
    >>\( > \)>>>>
    \>ab\(a\>\>{b}\)aba\>\>{b}Not supporteda\>\>{b}
    [[\([\)[[[[
    ]]\(]\)]]]]
    {a\({a}\)a{a}a{a}{a}
    }a\({a}\)a{a}a{a}{a}
    \{{\(\{\){\{{\{
    \}}\(\}\)}\}}\}
    ||\(|\)|||
    \|\(\|\)\|\|
    ~no break\(\text{no~break}\)no break\text{no~break}Not supported\text{no~break}
    \~a˜Not supporteda˜\text{\~{a}}Not supported\text{\~{a}}
    \\abcd\(\begin{matrix} a & b\\ c & d\end{matrix}\)abcd\begin{matrix} a & b\\ c & d\end{matrix}abcd\begin{matrix} a & b\\ c & d\end{matrix}\begin{matrix}
       a & b \\
       c & d
    \end{matrix}
    \\xy\(x \\ y\)xyx \\ yNot supportedx \\ y
    ^xi\(x^i\)xix^ixix^ix^i
    \^aˆNot supportedaˆ\text{\^{a}}Not supported\text{\^{a}}
    special fraction1³⁄₄\(1\kern2mu \text{³⁄₄}\)1³⁄₄1\kern2mu \text{³⁄₄}Not supported1\kern2mu \text{³⁄₄}
    - -

    A

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \AANot supportedA˚\text{\AA}Not supported\text{\AA}
    \aaa˚Not supporteda˚\text{\aa}Not supported\text{\aa}
    \aboveab+1\({a \above{2pt} b+1}\)ab+1{a \above{2pt} b+1}Not supported{a \above{2pt} b+1}
    \abovewithdelimsNot supported\(a+1 \abovewithdelims [ ] 1pt b\)Not supportedNot supporteda+1 \abovewithdelims [ ] 1pt b
    \acuteeˊ\(\acute e\)eˊ\acute eNot supported\acute e
    \AEÆNot supportedÆ\text{\AE}Not supported\text{\AE}
    \aeæNot supportedæ\text{\ae}Not supported\text{\ae}
    \alef\(\alef\)\alefNot supported
    \alefsym\(\alefsym\)\alefsymNot supported
    \aleph\(\aleph\)\aleph\aleph
    {align}a=b+cd+e=f\[\begin{align}a &=b+c\\d+e&=f\end{align}\]a=b+cd+e=f\begin{align}a &=b+c\\d+e&=f\end{align}Not supported\begin{align}
       a&=b+c \\
       d+e&=f
    \end{align}
    {align*}a=b+cd+e=f\[\begin{align*}a &=b+c\\d+e&=f\end{align*}\]a=b+cd+e=f\begin{align*}a &=b+c\\d+e&=f\end{align*}Not supported\begin{align*}
       a&=b+c \\
       d+e&=f
    \end{align*}
    {aligned}x=ya=b+cx=ya=b\(\begin{aligned}x&=y & a&=b+c\\x'&=y' & a'&=b'\end{aligned}\)x=ya=b+cx=ya=b\begin{aligned}x&=y & a&=b+c\\x'&=y' & a'&=b'\end{aligned}x=ya=b+cx=ya=b\begin{aligned}x&=y & a&=b+c\\x'&=y' & a'&=b'\end{aligned}\begin{aligned}
    x&=y & a&=b+c\\
    x'&=y' & a'&=b'
    \end{aligned}
    {alignat}10x+3y=23x+13y=4\[\begin{alignat}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignat}\]10x+3y=23x+13y=4\begin{alignat}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignat}Not supported
    {alignat*}10x+3y=23x+13y=4\[\begin{alignat*}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignat*}\]10x+3y=23x+13y=4\begin{alignat*}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignat*}Not supported
    {alignedat}10x+3y=23x+13y=4\(\begin{alignedat}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignedat}\)10x+3y=23x+13y=4\begin{alignedat}{2}10&x+&3&y=2\\3&x+&13&y=4\end{alignedat}Not supported\begin{alignedat}{2}
       10&x+ &3&y = 2 \\
       3&x+&13&y = 4
    \end{alignedat}
    \allowbreakSupportedNot supportedNot supportedNot supported
    \AlphaΑ\(\Alpha\)A\AlphaΑ\Alpha
    \alphaα\(\alpha\)α\alphaα\alpha
    \amalg⨿\(\amalg\)⨿\amalg⨿\amalg
    \And&\(\And\)&\AndNot supported
    \andNot supported\(\and\)Not supportedNot supportedDeprecated
    \angNot supported\(\ang\)Not supportedNot supportedDeprecated
    \anglanNot supported
    See \enclose
    ana_{\angl n}Not supporteda_{\angl n}
    \angle\(\angle\)\angle\angle
    \anglnanNot supported
    See \enclose
    ana_\anglnNot supporteda_\angln
    \approx\(\approx\)\approx\approx
    \approxeq\(\approxeq\)\approxeq\approxeq
    \arccosarccosx\(\arccos x\)arccosx\arccos xarccosx\arccos x
    \arcctgarcctgxNot supportedarcctgx\arcctg xNot supported
    \arcsinarcsinx\(\arcsin x\)arcsinx\arcsin xarcsinx\arcsin x
    \arctanarctanx\(\arctan x\)arctanx\arctan xarctanx\arctan x
    \arctgarctgxNot supportedarctgx\arctg xNot supported
    \argarg\(\arg\)arg\argarg\arg
    \argmaxargmaxxargmaxyxargmaxyxNot supportedarg maxxarg maxyxarg maxyx\begin{matrix}\argmax x \\ \argmax_y x \\\argmax\limits_y x\end{matrix}Not supported
    \argminargminNot supportedarg min\argminNot supported
    {array}abcd\(\begin{array}{cc}a&b\\c&d\end{array}\)abcd\begin{array}{cc}a&b\\c&d\end{array}abcd\begin{array}{cc}a&b\\c&d\end{array}\begin{array}{cc}
       a & b \\
       c & d
    \end{array}
    {array}
    with lines
    abcdefghi\(\begin{array}{c|c:c}a & b & c \\ \hline d & e & f \\ \hdashline g & h & i\end{array}\)abcdefghi\begin{array}{c|c:c}a & b & c \\ \hline d & e & f \\ \hdashline g & h & i\end{array}Not supported\begin{array}{c|c:c}
    a & b & c \\ \hline
    d & e & f\\
    \hdashline g & h & i
    \end{array}
    \arrayNot supported\(\array{ a & b+1 \\ c+1 & d }\)Not supportedab+1c+1d\array{ a & b+1 \\ c+1 & d }\array{ a & b+1 \\ c+1 & d }
    \arraystretchabcd\(\def\arraystretch{1.5}\begin{array}{cc}a&b\\c&d\end{array}\)abcd\def\arraystretch{1.5}\begin{array}{cc}a&b\\c&d\end{array}Not supported\def\arraystretch{1.5}
    \begin{array}{cc}
       a & b \\
       c & d
    \end{array}
    \ArrowvertNot supported\(\Arrowvert\)Not supportedNot supported
    \arrowvertNot supported\(\arrowvert\)Not supportedNot supported
    \ast\(\ast\)\ast\ast
    \asymp\(\asymp\)\asymp\asymp
    \atopab\({a \atop b}\)ab{a \atop b}ab{a \atop b}{a \atop b}
    \atopwithdelimsNot supported\(a \atopwithdelims [ ] b\)Not supportedNot supporteda \atopwithdelims [ ] b
    - -

    B

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \backepsilon\(\backepsilon\)\backepsilon϶\backepsilon
    \backprime\(\backprime\)\backprimeNot supported
    \backsim\(\backsim\)\backsim\backsim
    \backsimeq\(\backsimeq\)\backsimeq\backsimeq
    \backslash\\(\backslash\)\\backslash\\backslash
    \ballotxNot supportedNot supportedNot supported
    \bary\(\bar{y}\)y2\bar{y}y¯\bar{y}\bar{y}
    \barwedge\(\barwedge\)\barwedge\barwedge
    \Bbb𝔸𝔹\(\Bbb{ABC}\)ABC\Bbb{ABC}Not supported\Bbb{ABC}
    \Bbbk𝕜\(\Bbbk\)k\BbbkNot supported
    \bboxNot supportedRequires extensionNot supportedNot supported
    \bcancel5\(\bcancel{5}\)5\bcancel{5}Not supported\bcancel{5}
    \because\(\because\)\because\because
    \beginabcd\(\begin{matrix} a & b\\ c & d\end{matrix}\)abcd\begin{matrix} a & b\\ c & d\end{matrix}abcd\begin{matrix} a & b\\ c & d\end{matrix}\begin{matrix}
       a & b \\
       c & d
    \end{matrix}
    \begingroupa\(\begingroup a \endgroup\)a\begingroup a \endgroupNot supported\begingroup a\endgroup
    \BetaΒ\(\Beta\)B\BetaΒ\Beta
    \betaβ\(\beta\)β\betaβ\beta
    \beth\(\beth\)\beth\beth
    \between\(\between\)\between\between
    \bf𝐀𝐚𝐁𝐛𝟏𝟐\(\bf AaBb12\)AaBb12\bf AaBb12Not supported\bf AaBb12
    \big()\(\big(\big)\)()\big(\big)()\big(\big)\big(\big)
    \Big()\(\Big(\Big)\)()\Big(\Big)()\Big(\Big)\Big(\Big)
    \bigcap0nx0nx\(\bigcap_0^n x \; \displaystyle \bigcap_0^n x\)0nx  0nx\bigcap_0^n x \; \displaystyle \bigcap_0^n x\bigcap
    \bigcirc\(\bigcirc\)\bigcirc\bigcirc
    \bigcup0nx0nx\(\bigcup_0^n x \; \displaystyle \bigcup_0^n x\)0nx  0nx\bigcup_0^n x \; \displaystyle \bigcup_0^n x\bigcup
    \bigg()\(\bigg(\bigg)\)()\bigg(\bigg)()\bigg(\bigg)\bigg(\bigg)
    \Bigg()\(\Bigg(\Bigg)\)()\Bigg(\Bigg)()\Bigg(\Bigg)\Bigg(\Bigg)
    \biggl(\(\biggl(\)(\biggl((\biggl(\biggl(
    \Biggl(\(\Biggl(\)(\Biggl((\Biggl(\Biggl(
    \biggm|\(\biggm\vert\)\biggm\vertNot supported\biggm\vert
    \Biggm|\(\Biggm\vert\)\Biggm\vertNot supported\Biggm\vert
    \biggr)\(\biggr)\))\biggr))\biggr)\biggr)
    \Biggr)\(\Biggr)\))\Biggr))\Biggr)\Biggr)
    \bigl(\(\bigl(\)(\bigl((\bigl(\bigl(
    \Bigl(\(\Bigl(\)(\Bigl((\Bigl(\Bigl(
    \bigm|\(\bigm\vert\)\bigm\vertNot supported\bigm\vert
    \Bigm|\(\Bigm\vert\)\Bigm\vertNot supported\Bigm\vert
    \bigodot0nx0nx\(\bigodot_0^n x \; \displaystyle \bigodot_0^n x\)0nx  0nx\bigodot_0^n x \; \displaystyle \bigodot_0^n x\bigodot
    \bigominusNot supportedNot supportedNot supportedNot supported
    \bigoplus0nx0nx\(\bigoplus_0^n x \; \displaystyle \bigoplus_0^n x\)0nx  0nx\bigoplus_0^n x \; \displaystyle \bigoplus_0^n x\bigoplus
    \bigoslashNot supportedNot supportedNot supportedNot supported
    \bigotimes0nx0nx\(\bigotimes_0^n x \; \displaystyle \bigotimes_0^n x\)0nx  0nx\bigotimes_0^n x \; \displaystyle \bigotimes_0^n x\bigotimes
    \bigr)\(\bigr)\))\bigr))\bigr)\bigr)
    \Bigr)\(\Bigr)\))\Bigr))\Bigr)\Bigr)
    \bigsqcapNot supportedNot supportedNot supported\bigsqcap
    \bigsqcup0nx0nx\(\bigsqcup_0^n x \; \displaystyle \bigsqcup_0^n x\)0nx  0nx\bigsqcup_0^n x \; \displaystyle \bigsqcup_0^n x\bigsqcup
    \bigstar\(\bigstar\)\bigstar\bigstar
    \bigtriangledown\(\bigtriangledown\)\bigtriangledown\bigtriangledown
    \bigtriangleup\(\bigtriangleup\)\bigtriangleup\bigtriangleup
    \biguplus0nx0nx\(\biguplus_0^n x \; \displaystyle \biguplus_0^n x\)0nx  0nx\biguplus_0^n x \; \displaystyle \biguplus_0^n x\biguplus
    \bigvee0nx0nx\(\bigvee_0^n x \; \displaystyle \bigvee_0^n x\)0nx  0nx\bigvee_0^n x \; \displaystyle \bigvee_0^n x\bigvee
    \bigwedge0nx0nx\(\bigwedge_0^n x \; \displaystyle \bigwedge_0^n x\)0nx  0nx\bigwedge_0^n x \; \displaystyle \bigwedge_0^n x\bigwedge
    \binom(nk)\(\binom n k\)(nk)\binom n k(nk)\binom n k\binom n k
    \blacklozenge\(\blacklozenge\)\blacklozenge\blacklozenge
    \blacksquare\(\blacksquare\)\blacksquare\blacksquare
    \blacktriangle\(\blacktriangle\)\blacktriangle\blacktriangle
    \blacktriangledown\(\blacktriangledown\)\blacktriangledown\blacktriangledown
    \blacktriangleleft\(\blacktriangleleft\)\blacktriangleleft\blacktriangleleft
    \blacktriangleright\(\blacktriangleright\)\blacktriangleright\blacktriangleright
    \bm𝑨𝒂𝑩𝒃Not supportedAaBb\bm{AaBb}Not supported\bm{AaBb}
    {Bmatrix}{abcd}\(\begin{Bmatrix}a&b\\c&d\end{Bmatrix}\){abcd}\begin{Bmatrix}a&b\\c&d\end{Bmatrix}{abcd}\begin{Bmatrix}a&b\\c&d\end{Bmatrix}\begin{Bmatrix}
       a & b \\
       c & d
    \end{Bmatrix}
    {bmatrix}[abcd]\(\begin{bmatrix}a&b\\c&d\end{bmatrix}\)[abcd]\begin{bmatrix}a&b\\c&d\end{bmatrix}[abcd]\begin{bmatrix}a&b\\c&d\end{bmatrix}\begin{bmatrix}
       a & b \\
       c & d
    \end{bmatrix}
    \bmodamodb\(a \bmod b\)amodba \bmod bNot supporteda \bmod b
    \bold𝐀𝐚𝐁𝐛𝟏𝟐𝟑\(\bold{AaBb123}\)AaBb123\bold{AaBb123}Not supported\bold{AaBb123}
    \boldsymbol𝑨𝒂𝑩𝒃0\(\boldsymbol{AaBb0}\)AaBb0\boldsymbol{AaBb0}𝐀𝐚𝐁𝐛𝟎\boldsymbol{AaBb0}\boldsymbol{AaBb0}
    \bot\(\bot\)\bot\bot
    \BotNot supportedNot supportedNot supported
    \bowtie\(\bowtie\)\bowtie\bowtie
    \Box\(\Box\)\Box\Box
    \boxdot\(\boxdot\)\boxdot\boxdot
    \boxedab\(\boxed{ab}\)ab\boxed{ab}ab\boxed{ab}\boxed{ab}
    \boxminus\(\boxminus\)\boxminus\boxminus
    \boxplus\(\boxplus\)\boxplus\boxplus
    \boxtimes\(\boxtimes\)\boxtimes\boxtimes
    \Braψ|Requires extensionψ\Bra{\psi}Not supported\Bra{\psi}
    \braψ|Requires extensionψ\bra{\psi}Not supported\bra{\psi}
    \brace{nk}\({n\brace k}\){nk}{n\brace k}Not supported{n\brace k}
    \brack[nk]\({n\brack k}\)[nk]{n\brack k}Not supported{n\brack k}
    \braketϕ|ψNot supportedϕψ\braket{\phi|\psi}Not supported\braket{\phi|\psi}
    \Braketϕ|2t2|ψRequires extenstionNot supportedNot supported\Braket{ϕ|\frac{∂^2}{∂ t^2}|ψ}
    \breveeu˘\(\breve{eu}\)eu˘\breve{eu}Not supported\breve{eu}
    \buildrelNot supported\(\buildrel \rm def \over {:=}\)Not supportedNot supported\buildrel \rm def \over {:=}
    \bull\(\bull\)\bullNot supported
    \bullet\(\bullet\)\bullet\bullet
    \Bumpeq\(\Bumpeq\)\Bumpeq\Bumpeq
    \bumpeq\(\bumpeq\)\bumpeq\bumpeq
    - -

    C

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \CNot supported\(\C\)Not supportedNot supportedDeprecated
    \cc¸Not supportedNot supportedNot supported\text{\c{c}}
    \cal𝒜𝒞Not supportedABC\cal ABCNot supported\cal ABC
    \cancel5\(\cancel{5}\)5\cancel{5}Not supported\cancel{5}
    \canceltox0Not supportedNot supportedNot supported
    \Cap\(\Cap\)\Cap\Cap
    \cap\(\cap\)\cap\cap
    {cases}{aif bcif d\(\begin{cases}a&\text{if }b\\c&\text{if }d\end{cases}\){aif bcif d\begin{cases}a&\text{if }b\\c&\text{if }d\end{cases}{aif bcif d\begin{cases}a&\text{if }b\\c&\text{if }d\end{cases}\begin{cases}
       a &\text{if } b \\
       c &\text{if } d
    \end{cases}
    \casesNot supported\(\cases{ x & \text{if } x\ge 0\\ -x & \text{if } x\lt 0}\)Not supportedNot supported\cases{x & \text{if } x\ge 0\\
    - -x & \text{if } x\lt 0} -
    {CD}AaBbcC=D\(\begin{CD} A @>a>> B\\@VbVV @AAcA \\ C @= D\end{CD}\)AaBbcC=D\begin{CD} A @>a>> B\\@VbVV @AAcA \\ C @= D\end{CD}Not supported
    \cdot\(\cdot\)\cdot\cdot
    \cdotp·\(\cdotp\)\cdotp·\cdotp
    \cdots\(\cdots\)\cdots\cdots
    \ceABC\(\ce{A\bond{~}B\bond{~-}C}\)Not supportedNot supported\ce{A\bond{~}B\bond{~-}C}
    Requires `mhchem` extension
    \ceeNot supported\(\cee{C6H5-CHO}\)Not supportedNot supportedDeprecated by mhchem
    \centerdotab\(a\centerdot b\)aba\centerdot bNot supportedIn LaTeX, \centerdot is a small
    square on the baseline, not
    a centered dot.
    \cfNot supported\(\cf{C6H5-CHO}\)Not supportedNot supportedDeprecated by mhchem
    \cfrac21+21+21\(\cfrac{2}{1+\cfrac{2}{1+\cfrac{2}{1}}}\)21+21+21\cfrac{2}{1+\cfrac{2}{1+\cfrac{2}{1}}}Not supported\cfrac{2}{1+\cfrac{2}{1+\cfrac{2}{1}}}
    \charNot supported
    See \unicode
    \char"263aNot supported\char"263a
    \checkoeˇ\(\check{oe}\)oeˇ\check{oe}oeˇ\check{oe}\check{oe}
    \chchNot supportedch\chNot supported
    \checkmark\(\checkmark\)\checkmarkNot supported
    \ChiΧ\(\Chi\)X\ChiNot supported
    \chiχ\(\chi\)χ\chiχ\chi
    \choose(n+1k+2)\({n+1 \choose k+2}\)(n+1k+2){n+1 \choose k+2}(n+1k+2){n+1 \choose k+2}{n+1 \choose k+2}
    \circ\(\circ\)\circ\circ
    \circeq\(\circeq\)\circeq\circeq
    \circlearrowleft\(\circlearrowleft\)\circlearrowleft\circlearrowleft
    \circlearrowright\(\circlearrowright\)\circlearrowright\circlearrowright
    \circledast\(\circledast\)\circledast\circledast
    \circledcirc\(\circledcirc\)\circledcirc\circledcirc
    \circleddash\(\circleddash\)\circleddash\circleddash
    \circledR®\(\circledR\)®\circledRNot supported
    \circledS\(\circledS\)\circledSNot supported
    \classabcdefghNot supportedNot supportedNot supportedab\class{mathHighlight}{cdef}gh
    \clineNot supportedNot supportedNot supportedNot supported
    \clubs\(\clubs\)\clubsNot supported
    \clubsuit\(\clubsuit\)\clubsuit\clubsuit
    \cnums\(\cnums\)C\cnumsNot supported
    \cohNot supportedNot supportedNot supported
    \colon:\(\colon\) ⁣:\colon:\colon
    \Colonapprox∷≈Not supported\Colonapprox∷≈\Colonapprox
    \colonapprox:Not supported:\colonapprox∶≈\colonapprox
    \Coloneq∷−Not supported\Coloneq∷−\Coloneq
    \coloneq:Not supported:\coloneq\coloneq
    \ColoneqqNot supported=\Coloneqq\Coloneqq
    \coloneqqabNot supportedaba \coloneqq baba \coloneqq b
    \Colonsim:Not supported\Colonsim∷∼\Colonsim
    \colonsim:Not supported:\colonsim∶∼\colonsim
    \colorAaBb123\(\color{#0000FF} AaBb123\)AaBb123\color{#0000FF} AaBb123AaBb123\color{#0000FF} AaBb123\color{#0000FF} AaBb123
    \colorboxBlack on red\(\colorbox{red}{Black on red}\)Black on red\colorbox{red}{Black on red}Not supported\colorbox{red}{Black on red}
    \complement\(\complement\)\complement\complement
    \Complex\(\Complex\)C\ComplexNot supported
    \cong\(\cong\)\cong\cong
    \CoppaϘNot supportedNot supportedNot supported
    \coppaϙNot supportedNot supportedNot supported
    \coprod0nx0nx\(\coprod_0^n x \; \displaystyle \coprod_0^n x\)0nx  0nx\coprod_0^n x \; \displaystyle \coprod_0^n x\coprod
    \copyright©Not supported©\copyrightNot supported
    \coscosx\(\cos x\)cosx\cos xcosx\cos x
    \coseccosecxNot supportedcosecx\cosec xNot supported
    \coshcoshx\(\cosh x\)coshx\cosh xcoshx\cosh x
    \cotcotx\(\cot x\)cotx\cot xcotx\cot x
    \cotgcotgxNot supportedcotgx\cotg xNot supported
    \cothcothx\(\coth x\)cothx\coth xcothx\coth x
    \crabcd\(\begin{matrix} a & b\\ c & d \end{matrix}\)abcd\begin{matrix} a & b\\ c & d \end{matrix}abcd\begin{matrix} a & b\\ c & d \end{matrix}\begin{matrix}
       a & b \cr
       c & d
    \end{matrix}
    \csccscx\(\csc x\)cscx\csc xcscx\csc x
    \cssIdNot supportedNot supportedNot supported
    \ctgctgxNot supportedctgx\ctg xNot supported
    \cthcthxNot supportedcthx\cth xNot supported
    \Cup\(\Cup\)\Cup\Cup
    \cup\(\cup\)\cup\cup
    \curlyeqprec\(\curlyeqprec\)\curlyeqprec\curlyeqprec
    \curlyeqsucc\(\curlyeqsucc\)\curlyeqsucc\curlyeqsucc
    \curlyvee\(\curlyvee\)\curlyvee\curlyvee
    \curlywedge\(\curlywedge\)\curlywedge\curlywedge
    \curvearrowleft\(\curvearrowleft\)\curvearrowleft\curvearrowleft
    \curvearrowright\(\curvearrowright\)\curvearrowright\curvearrowright
    - -

    D

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \dagNot supported\dagNot supported
    \Dagger\(\Dagger\)\DaggerNot supported
    \dagger\(\dagger\)\dagger\dagger
    \daleth\(\daleth\)\daleth\daleth
    \Darr\(\Darr\)\DarrNot supported
    \dArr\(\dArr\)\dArrNot supported
    \darr\(\darr\)\darr\darr
    {darray}abcd\(\begin{array}{cc}a & b\\c & d\end{array}\)abcd\begin{array}{cc}a & b\\c & d\end{array}abcd\begin{array}{cc}a & b\\c & d\end{array}\begin{darray}{cc}
       a & b \\
       c & d
    \end{darray}
    \dashleftarrow\(\dashleftarrow\)\dashleftarrow\dashleftarrow
    \dashrightarrow\(\dashrightarrow\)\dashrightarrow\dashrightarrow
    \dashv\(\dashv\)\dashv\dashv
    \dbinom(nk)\(\dbinom n k\)(nk)\dbinom n kNot supported\dbinom n k
    \dblcolonNot supported\dblcolon\dblcolon
    {dcases}{aif bcif dNot supported{aif bcif d\begin{dcases}a&\text{if }b\\c&\text{if }d\end{dcases}Not supported\begin{dcases}
       a &\text{if } b \\
       c &\text{if } d
    \end{dcases}
    \ddagNot supported\ddagNot supported
    \ddagger\(\ddagger\)\ddagger\ddagger
    \ddddotxNot supportedNot supportedx\ddddot x
    \dddotxNot supportedNot supportedx\dddot x
    \ddotx¨\(\ddot x\)x¨\ddot xẍ\ddot x\ddot x
    \ddots\(\ddots\)\ddots\ddots
    \DeclareMathOperatorNot supported\(\DeclareMathOperator - {\myOp}{myOp} - \myOp(x)\) - Not supportedNot supported
    \defx2+x2\(\def\foo{x^2} \foo + \foo\)x2+x2\def\foo{x^2} \foo + \fooNot supported\def\foo{x^2} \foo + \foo
    \definecolorF=maNot supportedNot supportedNot supported
    \degdegx\(\deg x\)degx\deg xdegx\deg x
    \degree°Not supported°\degree°\degree
    \deltaδ\(\delta\)δ\deltaδ\delta
    \DeltaΔ\(\Delta\)Δ\DeltaΔ\Delta
    \detdetxdetyxdetyx\(\begin{matrix}\det x \\ \det_y x \\\det\limits_y x\end{matrix}\)detxdetyxdetyx\begin{matrix}\det x \\ \det_y x \\\det\limits_y x\end{matrix}det\det
    \DigammaNot supported\(\Digamma\)Not supportedNot supported
    \digammaϝ\(\digamma\)ϝ\digammaϝ\digamma
    \dfraca1b1\(\dfrac{a-1}{b-1}\)a1b1\dfrac{a-1}{b-1}Not supported\dfrac{a-1}{b-1}
    \diagdown\(\diagdown\)\diagdownNot supported
    \diagup\(\diagup\)\diagupNot supported
    \Diamond\(\Diamond\)\Diamond\Diamond
    \diamond\(\diamond\)\diamond\diamond
    \diamonds\(\diamonds\)\diamondsNot supported
    \diamondsuit\(\diamondsuit\)\diamondsuit\diamondsuit
    \dimdimx\(\dim x\)dimx\dim xdimx\dim x
    \displaylinesNot supported\(\displaylines{a\\ a+b=c+d}\)Not supportedNot supported\displaylines{a\\ a+b=c+d}
    \displaystyle0n\(\displaystyle\sum_0^n\)0n\displaystyle\sum_0^n0n\displaystyle\sum_0^n\displaystyle\sum_0^n
    \div÷\(\div\)÷\div÷\div
    \divideontimes\(\divideontimes\)\divideontimes\divideontimes
    \dotx˙\(\dot x\)x˙\dot xx˙\dot x\dot x
    \Doteq\(\Doteq\)\Doteq\Doteq
    \doteq\(\doteq\)\doteq\doteq
    \doteqdot\(\doteqdot\)\doteqdot\doteqdot
    \dotplus\(\dotplus\)\dotplus\dotplus
    \dotsx1++xn\(x_1 + \dots + x_n\)x1++xnx_1 + \dots + x_nx1++xnx_1 + \dots + x_nx_1 + \dots + x_n
    \dotsbx1++xn\(x_1 +\dotsb + x_n\)x1++xnx_1 +\dotsb + x_nNot supportedx_1 +\dotsb + x_n
    \dotscx,,y\(x,\dotsc,y\)x,,yx,\dotsc,yNot supportedx,\dotsc,y
    \dotsiA1A2\(\int_{A_1}\int_{A_2}\dotsi\)A1A2 ⁣\int_{A_1}\int_{A_2}\dotsiNot supported\int_{A_1}\int_{A_2}\dotsi
    \dotsmx1x2xn\(x_1 x_2 \dotsm x_n\)x1x2xnx_1 x_2 \dotsm x_nNot supportedx_1 x_2 \dotsm x_n
    \dotso\(\dotso\)\dotsoNot supported
    \doublebarwedge\(\doublebarwedge\)\doublebarwedge\doublebarwedge
    \doublecap\(\doublecap\)\doublecapNot supported
    \doublecup\(\doublecup\)\doublecupNot supported
    \Downarrow\(\Downarrow\)\Downarrow\Downarrow
    \downarrow\(\downarrow\)\downarrow\downarrow
    \downdownarrows\(\downdownarrows\)\downdownarrows\downdownarrows
    \downharpoonleft\(\downharpoonleft\)\downharpoonleft\downharpoonleft
    \downharpoonright\(\downharpoonright\)\downharpoonright\downharpoonright
    {drcases}aif bcif d}Not supportedaif bcif d}\begin{drcases}a&\text{if }b\\c&\text{if }d\end{drcases}Not supported\begin{drcases}
       a&\text{if }b\\
       c&\text{if }d
    \end{drcases}
    - -

    E

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \ell\(\ell\)\ell\ell
    \elseNot supportedNot supportedNot supportedNot supported
    \empty\(\empty\)\empty\empty
    \emptyset\(\emptyset\)\emptyset\emptyset
    \encloseNot supported
    See \longdiv,
    \angl, \phase
    \(\enclose{longdiv}{500}\)
    \(\enclose{actuarial}{500}\)
    \(\enclose{phasorangle}{500}\)
    Not supportedNot supported\enclose{longdiv}{500}
    \enclose{actuarial}{500}
    \enclose{phasorangle}{500}
    Non-standard
    \endabcd\(\begin{matrix} a & b\\ c & d\end{matrix}\)abcd\begin{matrix} a & b\\ c & d\end{matrix}abcd\begin{matrix} a & b\\ c & d\end{matrix}\begin{matrix}
       a & b \\
       c & d
    \end{matrix}
    \endgroupa\(\begingroup a \endgroup\)a\begingroup a \endgroupNot supported\begingroup a\endgroup
    \enspaceab\(a\enspace b\)aba\enspace bNot supporteda\enspace b
    \EpsilonΕ\(\Epsilon\)E\EpsilonNot supported
    \epsilonϵ\(\epsilon\)ϵ\epsilonϵ\epsilon
    \eqalignNot supported\(\eqalign{3x - 4y &= 5\\x + 7 &= -2y}\)Not supportedNot supported
    \eqalignnoNot supported\(\eqalignno{3x - 4y &= 5 &(\dagger) \\ x + 7 &= -2y &(\ddagger)\\ z &= 2}\)Not supportedNot supported
    \eqcirc\(\eqcirc\)\eqcirc\eqcirc
    \Eqcolon−∷Not supported\Eqcolon−∷\Eqcolon
    \eqcolonNot supported\eqcolon\eqcolon
    {equation}·𝐃=ρv·𝐁=0\[\begin{equation}\begin{split}∇·𝐃&=ρ_v \\∇·𝐁&=0\end{split}\end{equation}\]𝐃=ρv𝐁=0\begin{equation}\begin{split}∇·𝐃&=ρ_v \\∇·𝐁&=0\end{split}\end{equation}Not supported\begin{equation}
    \begin{split}
       ∇·𝐃&=ρ_v \\
       ∇·𝐁&=0
    \end{split}
    \end{equation}
    {equation*}·𝐃=ρv·𝐁=0\[\begin{equation*}\begin{split}∇·𝐃&=ρ_v \\∇·𝐁&=0\end{split}\end{equation*}\]𝐃=ρv𝐁=0\begin{equation*}\begin{split}∇·𝐃&=ρ_v \\∇·𝐁&=0\end{split}\end{equation*}Not supported
    {eqnarray}Not supported\(\begin{eqnarray} -y &=& (x-1)^2 \\ - &=& (x-1)(x-1) \\ - &=& x^2 - 2x + 1 -\end{eqnarray}\)Not supportedNot supported
    {eqnarray*}Not supported\(\begin{eqnarray*} -y &=& (x-1)^2 \\ - &=& (x-1)(x-1) \\ - &=& x^2 - 2x + 1 -\end{eqnarray*}\)Not supportedNot supported
    \Eqqcolon=∷Not supported=\Eqqcolon=∷\Eqqcolon
    \eqqcolonNot supported\eqqcolon\eqqcolon
    \eqrefNot supportedNot supportedNot supported
    \eqsim\(\eqsim\)\eqsim\eqsim
    \eqslantgtr\(\eqslantgtr\)\eqslantgtr\eqslantgtr
    \eqslantless\(\eqslantless\)\eqslantless\eqslantless
    \equiv\(\equiv\)\equiv\equiv
    \EtaΗ\(\Eta\)H\EtaΗ\Eta
    \etaη\(\eta\)η\etaη\eta
    \ethð\(\eth\)ð\ethð\eth
    \euro\(\euro\)Not supportedNot supported
    \exist\(\exist\)\existNot supported
    \exists\(\exists\)\exists\exists
    \expexpx\(\exp x\)expx\exp xexpx\exp x
    - -

    F

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \fallingdotseq\(\fallingdotseq\)\fallingdotseq\fallingdotseq
    \fboxHi there!\(\fbox{Hi there!}\)Hi there!\fbox{Hi there!}Not supported\fbox{Hi there!}
    \fcolorboxA\(\fcolorbox{red}{aqua}{A}\)A\fcolorbox{red}{aqua}{A}Not supported\fcolorbox{red}{aqua}{A}
    \femaleNot supportedNot supportedNot supported\female
    \fiNot supportedNot supportedNot supportedNot supported
    \Finv\(\Finv\)\FinvNot supported
    \flat\(\flat\)\flat\flat
    \footnotesizefootnotesizeNot supportedfootnotesize\footnotesize footnotesizeNot supported\footnotesize footnotesize
    \forall\(\forall\)\forall\forall
    \fraca+bc+d\(\frac{a+b}{c+d}\)a+bc+d\frac{a+b}{c+d}a+bc+d\frac{a+b}{c+d}\frac{a+b}{c+d}
    \frak𝔄𝔞𝔅𝔟\(\frak{AaBb}\)AaBb\frak{AaBb}Not supported\frak{AaBb}
    \frown\(\frown\)\frown\frown
    - -

    G

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \Game\(\Game\)\GameNot supported
    \GammaΓ\(\Gamma\)Γ\GammaΓ\Gamma
    \gammaγ\(\gamma\)γ\gammaγ\gamma
    {gather}a=be=b+c\(\begin{gather}a=b\\e=b+c\end{gather}\)a=be=b+c\begin{gather}a=b\\e=b+c\end{gather}Not supported\begin{gather}
       a=b \\
       e=b+c
    \end{gather}
    {gather*}a=be=b+c\(\begin{gather*}a=b\\e=b+c\end{gather*}\)a=be=b+c\begin{gather*}a=b\\e=b+c\end{gather*}Not supported\begin{gather*}
       a=b \\
       e=b+c
    \end{gather*}
    {gathered}a=be=b+c\(\begin{gathered}a=b\\e=b+c\end{gathered}\)a=be=b+c\begin{gathered}a=b\\e=b+c\end{gathered}a=be=b+c\begin{gathered}a=b\\e=b+c\end{gathered}\begin{gathered}
       a=b \\
       e=b+c
    \end{gathered}
    \gcdgcdxgcdyxgcdyx\(\begin{matrix}\gcd x \\ \gcd_y x \\\gcd\limits_y x\end{matrix}\)gcdxgcdyxgcdyx\begin{matrix}\gcd x \\ \gcd_y x \\\gcd\limits_y x\end{matrix}gcdxgcdyxgcdlimitsyx\begin{matrix}\gcd x \\ \gcd_y x \\\gcd\limits_y x\end{matrix}
    \gdefNot supportedNot supportedy2+y2\gdef\bar#1{#1^2} \bar{y} + \bar{y}Not supported\gdef\bar#1{#1^2} \bar{y} + \bar{y}
    \ge\(\ge\)\ge\ge
    \geneuroNot supported\(\geneuro\)Not supportedNot supported
    \geneuronarrowNot supported\(\geneuronarrow\)Not supportedNot supported
    \geneurowideNot supported\(\geneurowide\)Not supportedNot supported
    \genfrac(aa+1]\(\genfrac ( ] {2pt}{0}a{a+1}\)(aa+1]\genfrac ( ] {2pt}{0}a{a+1}Not supported\genfrac ( ] {2pt}{0}a{a+1}
    \geq\(\geq\)\geq\geq
    \geqq\(\geqq\)\geqq\geqq
    \geqslant\(\geqslant\)\geqslant\geqslant
    \gets\(\gets\)\getsNot supported
    \gg\(\gg\)\gg\gg
    \ggg\(\ggg\)\ggg\ggg
    \gggtr\(\gggtr\)\gggtrNot supported
    \gimel\(\gimel\)\gimel\gimel
    \globalNot supported\(\global\def\add#1#2{#1+#2} \add 2 3\)2+3\global\def\add#1#2{#1+#2} \add 2 3Not supported\global\def\add#1#2{#1+#2} \add 2 3
    \gnapprox\(\gnapprox\)\gnapprox\gnapprox
    \gneq\(\gneq\)\gneq\gneq
    \gneqq\(\gneqq\)\gneqq\gneqq
    \gnsim\(\gnsim\)\gnsim\gnsim
    \graveeu`\(\grave{eu}\)euˋ\grave{eu}Not supported\grave{eu}
    \gta>b\(a \gt b\)a>ba \gt ba>ba \gt ba \gt b
    \gtrdot\(\gtrdot\)\gtrdot\gtrdot
    \gtrapprox\(\gtrapprox\)\gtrapprox\gtrapprox
    \gtreqless\(\gtreqless\)\gtreqless\gtreqless
    \gtreqqless\(\gtreqqless\)\gtreqqless\gtreqqless
    \gtrless\(\gtrless\)\gtrless\gtrless
    \gtrsim\(\gtrsim\)\gtrsim\gtrsim
    \gvertneqq≩︀\(\gvertneqq\)\gvertneqq≩︀\gvertneqq
    - -

    H

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \Ha˝Not supporteda˝\text{\H{a}}Not supported\text{\H{a}}
    \Harr\(\Harr\)\HarrNot supported
    \hArrNot supported\hArrNot supported
    \harr\(\harr\)\harrNot supported
    \hatθ^\(\hat{\theta}\)θ^\hat{\theta}θ^\hat{\theta}\hat{\theta}
    \hbar\(\hbar\)\hbar\hbar
    \hboxin a box\(\hbox{in a box}\)in a box\hbox{in a box}Not supported\hbox{in a box}
    \hdashlineabcd\(\begin{matrix}a&b\\ \hdashline c &d\end{matrix}\)abcd\begin{matrix}a&b\\ \hdashline c &d\end{matrix}Not supported\begin{matrix}
       a & b \\
       \hdashline
       c & d
    \end{matrix}
    \hearts\(\hearts\)\heartsNot supported
    \heartsuit\(\heartsuit\)\heartsuit\heartsuit
    \hfilNot supportedSee \hfillNot supportedNot supported
    \hfillNot supported\(\begin{matrix}xxxxxx & xxxxxx & xxxxxx \\ ab & \hfil ab & ab\hfil\\ \end{matrix}\)Not supportedNot supported
    \hlineabcd\(\begin{matrix}a&b\\ \hline c &d\end{matrix}\)abcd\begin{matrix}a&b\\ \hline c &d\end{matrix}Not supported\begin{matrix}
       a & b \\ \hline
       c & d
    \end{matrix}
    \homhomx\(\hom x\)homx\hom xhomx\hom x
    \hookleftarrow\(\hookleftarrow\)\hookleftarrow\hookleftarrow
    \hookrightarrow\(\hookrightarrow\)\hookrightarrow\hookrightarrow
    \hphantomabcd\(a\hphantom{bc}d\)abcda\hphantom{bc}dNot supporteda\hphantom{bc}d
    \hrefMathJax\(\href{https://MathJax.org/}{\text{MathJax}}\)MathJax\href{https://MathJax.org/}{\text{MathJax}}Not supported\href{https://www.mathjax.org/}{\text{MathJax}}
    \hskipwid\(w\hskip1em i\hskip2em d\)widw\hskip1em i\hskip2em dNot supportedw\hskip1em i\hskip2em d
    \hslash\(\hslash\)\hslash\hslash
    \hspaceNot supported\(s\hspace7ex k\)sks\hspace7ex kNot supporteds\hspace7ex k
    \htmlClassNot supportedNot supportedNot supportedNot supported\htmlClass{foo}{x}
    \htmlDataNot supportedNot supportedNot supportedNot supported\htmlData{foo=a, bar=b}{x}
    \htmlIdNot supportedNot supportedNot supportedNot supported\htmlId{bar}{x}
    \htmlStyleNot supportedNot supportedNot supportedNot supported\htmlStyle{color: red;}{x}}
    \hugehuge\(\huge huge\)huge\huge hugeNot supported\huge huge
    \HugeHuge\(\Huge Huge\)Huge\Huge HugeNot supported\Huge Huge
    - -

    I

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \iıNot supportedı\text{\i}Not supported\text{\i}
    \idotsintNot supportedNot supportedNot supported
    \iddotsNot supportedNot supportedNot supportedNot supported
    \ifNot supportedNot supportedNot supportedNot supported
    \iffAB\(A\iff B\)A    BA\iff BABA\iff BA\iff B
    \ifmodeNot supportedNot supportedNot supportedNot supported
    \ifxNot supportedNot supportedNot supportedNot supported
    \iiiintNot supportedNot supportedNot supportedNot supported
    \iiint0nx0nx\(\iiint_0^n x \; \displaystyle \iiint_0^n x\)0nx  0nx\iiint_0^n x \; \displaystyle \iiint_0^n x\iiint
    \iint0nx0nx\(\iint_0^n x \; \displaystyle \iint_0^n x\)0nx  0nx\iint_0^n x \; \displaystyle \iint_0^n x\iint
    \Im\(\Im\)\Im\Im
    \image\(\image\)\imageNot supported
    \imageofNot supported\imageofNot supported
    \imathı\(\imath\)ı\imathı\imath
    \impliedbyPQ\(P\impliedby Q\)P    QP\impliedby QPQP\impliedby QP\impliedby Q
    \impliesPQ\(P\implies Q\)P    QP\implies QPQP\implies QP\implies Q
    \in\(\in\)\in\in
    \includegraphicsKA logoNot supported\includegraphics[height=0.8em, totalheight=0.9em, width=0.9em, alt=KA logo]{https://cdn.kastatic.org/images/apple-touch-icon-57x57-precomposed.new.png}Not supported
    \incohNot supportedNot supportedNot supported
    \infinfxinfyxinfyx\(\begin{matrix}\inf x \\ \inf_y x \\\inf\limits_y x\end{matrix}\)infxinfyxinfyx\begin{matrix}\inf x \\ \inf_y x \\\inf\limits_y x\end{matrix}inf\inf
    \infin\(\infin\)\infinNot supported
    \infty\(\infty\)\infty\infty
    \injliminjlimxinjlimyxinjlimyx\(\begin{matrix}\injlim x \\ \injlim_y x \\\injlim\limits_y x\end{matrix}\)inj limxinj limyxinj limyx\begin{matrix}\injlim x \\ \injlim_y x \\\injlim\limits_y x\end{matrix}Not supported\injlim x
    \injlim_y x
    \injlim\limits_y x
    \int0nx0nx\(\int_0^n x \; \displaystyle \int_0^n x\)0nx  0nx\int_0^n x \; \displaystyle \int_0^n x\int
    \intercal\(\intercal\)\intercal\intercal
    \intop0nx0nx\(\intop_0^n x \; \displaystyle \intop_0^n x\)0nx  0nx\intop_0^n x \; \displaystyle \intop_0^n xNot supported
    \invampNot supportedNot supportedNot supported
    \IotaΙ\(\Iota\)I\IotaΙ\Iota
    \iotaι\(\iota\)ι\iotaι\iota
    \isin\(\isin\)\isinNot supported
    \itAaBb\({\it AaBb}\)AaBb{\it AaBb}Not supported{\it AaBb}
    - -

    JK

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \jȷNot supportedȷ\text{\j}Not supported\text{\j}
    \jmathȷ\(\jmath\)ȷ\jmathȷ\jmath
    \Join\(\Join\)\JoinNot supported
    \KappaΚ\(\Kappa\)K\KappaΚ\Kappa
    \kappaκ\(\kappa\)κ\kappaκ\kappa
    \kerkerx\(\ker x\)kerx\ker xkerx\ker x
    \kernIR\(I\kern-2.5pt R\)IRI\kern-2.5pt RNot supportedI\kern-2.5pt R
    \Ket|ψRequires extensionψ\Ket{\psi}Not supported\Ket{\psi}
    \ket|ψRequires extensionψ\ket{\psi}Not supported\ket{\psi}
    \KoppaϞNot supportedNot supportedNot supported
    \koppaϟNot supportedNot supportedNot supported
    - -

    L

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \LNot supportedNot supportedNot supportedNot supported
    \lNot supportedNot supportedNot supportedNot supported
    \LambdaΛ\(\Lambda\)Λ\LambdaΛ\Lambda
    \lambdaλ\(\lambda\)λ\lambdaλ\lambda
    \labelSee {equation}SupportedNot supported
    \land\(\land\)\landNot supported
    \langA\(\lang A\rangle\)A\lang A\rangleA\lang A\rangle\lang A\rangle
    \langleA\(\langle A\rangle\)A\langle A\rangleA\langle A\rangle\langle A\rangle
    \Larr\(\Larr\)\LarrNot supported
    \lArr\(\lArr\)\lArrNot supported
    \larr\(\larr\)\larrNot supported
    \largelarge\(\large large\)large\large largeNot supported\large large
    \LargeLarge\(\Large Large\)Large\Large LargeNot supported\Large Large
    \LARGELARGE\(\LARGE LARGE\)LARGE\LARGE LARGENot supported\LARGE LARGE
    \LaTeXLATEX\(\LaTeX\)LaTeX\LaTeXNot supported
    \lBraceNot supported\lBraceNot supported
    \lbrace{\(\lbrace\){\lbrace{\lbrace
    \lbrack[\(\lbrack\)[\lbrack[\lbrack
    \lceil\(\lceil\)\lceil\lceil
    \lcroofNot supportedNot supportedNot supportedNot supportedSee \enclose
    \ldotp.\(\ldotp\).\ldotpNot supported
    \ldots\(\ldots\)\ldots\ldots
    \le\(\le\)\le\le
    \leadsto\(\leadsto\)\leadstoNot supported
    \left{ab\(\left\lbrace \frac ab \right.\){ab\left\lbrace \frac ab \right.{ab\left\lbrace \frac ab \right.\left\lbrace \frac ab \right.
    \leftarrow\(\leftarrow\)\leftarrow\leftarrow
    \Leftarrow\(\Leftarrow\)\Leftarrow\Leftarrow
    \leftarrowtail\(\leftarrowtail\)\leftarrowtail\leftarrowtail
    \leftharpoondown\(\leftharpoondown\)\leftharpoondown\leftharpoondown
    \leftharpoonup\(\leftharpoonup\)\leftharpoonup\leftharpoonup
    \leftleftarrows\(\leftleftarrows\)\leftleftarrows\leftleftarrows
    \Leftrightarrow\(\Leftrightarrow\)\Leftrightarrow\Leftrightarrow
    \leftrightarrow\(\leftrightarrow\)\leftrightarrow\leftrightarrow
    \leftrightarrows\(\leftrightarrows\)\leftrightarrows\leftrightarrows
    \leftrightharpoons\(\leftrightharpoons\)\leftrightharpoons\leftrightharpoons
    \leftrightsquigarrow\(\leftrightsquigarrow\)\leftrightsquigarrow\leftrightsquigarrow
    \leftrootNot supported\(\sqrt[3\leftroot1]{x}\)Not supportedNot supported
    \leftthreetimes\(\leftthreetimes\)\leftthreetimes\leftthreetimes
    \leq\(\leq\)\leq\leq
    \leqalignnoNot supportedNot supportedNot supported
    \leqq\(\leqq\)\leqq\leqq
    \leqslant\(\leqslant\)\leqslant\leqslant
    \lessapprox\(\lessapprox\)\lessapprox\lessapprox
    \lessdot\(\lessdot\)\lessdot\lessdot
    \lesseqgtr\(\lesseqgtr\)\lesseqgtr\lesseqgtr
    \lesseqqgtr\(\lesseqqgtr\)\lesseqqgtr\lesseqqgtr
    \lessgtr\(\lessgtr\)\lessgtr\lessgtr
    \lesssim\(\lesssim\)\lesssim\lesssim
    \letNot supportedNot supportedNot supported
    \lfloor\(\lfloor\)\lfloor\lfloor
    \lglg\(\lg\)lg\lglg\lg
    \lgroup\(\lgroup\)\lgroupNot supported
    \lhd\(\lhd\)\lhd\lhd
    \limlimxlimyxlimyx\(\begin{matrix}\lim x \\ \lim_y x \\\lim\limits_y x\end{matrix}\)limxlimyxlimyx\begin{matrix}\lim x \\ \lim_y x \\\lim\limits_y x\end{matrix}limyx\lim_y x\lim x
    \lim_y x
    \lim\limits_y x
    \liminfliminfxliminfyxliminfyx\(\begin{matrix}\liminf x \\ \liminf_y x \\\liminf\limits_y x\end{matrix}\)lim infxlim infyxlim infyx\begin{matrix}\liminf x \\ \liminf_y x \\\liminf\limits_y x\end{matrix}liminf\liminf
    \limitslimx\(\lim\limits_x\)limx\lim\limits_xNot supported\lim\limits_x
    \limsuplimsupxlimsupyxlimsupyx\(\begin{matrix}\limsup x \\ \limsup_y x \\\limsup\limits_y x\end{matrix}\)lim supxlim supyxlim supyx\begin{matrix}\limsup x \\ \limsup_y x \\\limsup\limits_y x\end{matrix}limsup\limsup
    \ll\(\ll\)\ll\ll
    \llap=\({=}\llap{/\,}\)=/{=}\llap{/\,}Not supported{=}\llap{/\,}
    \llbracketNot supported\llbracketNot supported
    \llcornera\(\llcorner a \lrcorner\)a\llcorner a \lrcornerNot supported
    \Lleftarrow\(\Lleftarrow\)\Lleftarrow\Lleftarrow
    \lll\(\lll\)\lll\lll
    \llless\(\llless\)\lllessNot supported
    \lmoustache\(\lmoustache\)\lmoustache\lmoustache
    \lnlnx\(\ln x\)lnx\ln xlnx\ln x
    \lnapprox\(\lnapprox\)\lnapprox\lnapprox
    \lneq\(\lneq\)\lneq\lneq
    \lneqq\(\lneqq\)\lneqq\lneqq
    \longdiv45.2Not supported
    See \enclose
    Not supportedNot supported\longdiv{45.2}
    \lnot¬\(\lnot\)¬\lnotNot supported
    \lnsim\(\lnsim\)\lnsim\lnsim
    \loglogxlogyxlogyx\(\begin{matrix}\log x \\ \log_y x \\ \log\limits_y x\end{matrix}\)logxlogyxlogyx\begin{matrix}\log x \\ \log_y x \\ \log\limits_y x\end{matrix}logxlogyxloglimitsyx\begin{matrix}\log x \\ \log_y x \\ \log\limits_y x\end{matrix}\log x
    \log_y x
    \log\limits_y x
    \Longleftarrow\(\Longleftarrow\)\Longleftarrow\Longleftarrow
    \longleftarrow\(\longleftarrow\)\longleftarrow\longleftarrow
    \Longleftrightarrow\(\Longleftrightarrow\)\Longleftrightarrow\Longleftrightarrow
    \longleftrightarrow\(\longleftrightarrow\)\longleftrightarrow\longleftrightarrow
    \longmapsto\(\longmapsto\)\longmapsto\longmapsto
    \Longrightarrow\(\Longrightarrow\)\Longrightarrow\Longrightarrow
    \longrightarrow\(\longrightarrow\)\longrightarrow\longrightarrow
    \looparrowleft\(\looparrowleft\)\looparrowleft\looparrowleft
    \looparrowright\(\looparrowright\)\looparrowright\looparrowright
    \lor\(\lor\)\lorNot supported
    \lowerlower\(l\lower 2pt{owe}r\)Not supportedNot supportedl\lower 2pt{owe}r
    \lozenge\(\lozenge\)\lozenge\lozenge
    \lparen(Not supported(\lparenNot supported
    \Lrarr\(\Lrarr\)\LrarrNot supported
    \lrArr\(\lrArr\)\lrArrNot supported
    \lrarr\(\lrarr\)\lrarrNot supported
    \lrcorner\(\lrcorner\)\lrcornerNot supported
    \lqNot supported\lqNot supported
    \Lsh\(\Lsh\)\Lsh\Lsh
    \lt<\(\lt\)<\lt<\lt
    \ltimes\(\ltimes\)\ltimes\ltimes
    \lVert\(\lVert\)\lVertNot supported
    \lvert|\(\lvert\)\lvertNot supported
    \lvertneqq≨︀\(\lvertneqq\)\lvertneqq≨︀\lvertneqq
    - -

    M

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \maleNot supportedNot supportedNot supported\male
    \maltese\(\maltese\)\malteseNot supported
    \mapsto\(\mapsto\)\mapsto\mapsto
    \mathbb𝔸𝔹\(\mathbb{AB}\)AB\mathbb{AB}𝔸𝔹\mathbb{AB}\mathbb{AB}
    \mathbf𝐀𝐚𝐁𝐛𝟏𝟐𝟑\(\mathbf{AaBb123}\)AaBb123\mathbf{AaBb123}𝐀𝐚𝐁𝐛𝟏𝟐𝟑\mathbf{AaBb123}\mathbf{AaBb123}
    \mathbina!b\(a\mathbin{!}b\)a!ba\mathbin{!}ba!ba\mathbin{!}ba\mathbin{!}b
    \mathcal𝒜𝒶𝒷123\(\mathcal{AaBb123}\)AaBb123\mathcal{AaBb123}𝒜𝒶𝒷123\mathcal{AaBb123}\mathcal{AaBb123}
    \mathchoiceab\(a\mathchoice{\,}{\,\,}{\,\,\,}{\,\,\,\,}b\)aba\mathchoice{\,}{\,\,}{\,\,\,}{\,\,\,\,}bNot supporteda\mathchoice{\,}{\,\,}{\,\,\,}{\,\,\,\,}b
    \mathclap1inxiNot supported1inxi\displaystyle\sum_{\mathclap{1\le i\le n}} x_{i}1inxi\displaystyle\sum_{\mathclap{1\le i\le n}} x_{i}\sum_{\mathclap{1\le i\le n}} x_{i}
    \mathclosea+(b>+c\(a + (b\mathclose\gt + c\)a+(b>+ca + (b\mathclose\gt + cNot supporteda + (b\mathclose\gt + c
    \mathellipsisNot supported\mathellipsisNot supported
    \mathfrak𝔄𝔞𝔅𝔟\(\mathfrak{AaBb}\)AaBb\mathfrak{AaBb}𝔄𝔞𝔅𝔟\mathfrak{AaBb}\mathfrak{AaBb}
    \mathinnerabinsidecd\(ab\mathinner{\text{inside}}cd\)abinsidecdab\mathinner{\text{inside}}cdNot supportedab\mathinner{\text{inside}}cd
    \mathitAaBb\(\mathit{AaBb}\)AaBb\mathit{AaBb}𝐴𝑎𝐵𝑏\mathit{AaBb}\mathit{AaBb}
    \mathllap=Not supported/={\mathrlap{\,/}{=}}/={\mathrlap{\,/}{=}}\mathrlap{\,/}{=}
    \mathnormalAaBbθNot supportedAaBbθ\mathnormal{AaBb\theta}Not supported\mathnormal{AaBb\theta}
    \mathopaxb\(a \mathop{x} b\)axba \mathop{x} baxba \mathop{x} ba \mathop{x} b
    \mathopena+<b)+c\(a + \mathopen\lt b) + c\)a+<b)+ca + \mathopen\lt b) + cNot supporteda + \mathopen\lt b) + c
    \mathord1,234,567\(1\mathord{,}234{,}567\)1,234,5671\mathord{,}234{,}567Not supported1\mathord{,}234{,}567
    \mathpunctAB\(A\mathpunct{-}B\)ABA\mathpunct{-}BNot supportedA\mathpunct{-}B
    \mathraiseboxNot supportedNot supportedNot supportedhigherh\mathraisebox{2pt}{ighe}r
    \mathrela#b\(a \mathrel{\#} b\)a#ba \mathrel{\#} ba#ba \mathrel{#} ba \mathrel{\#} b
    \mathrlap02πxdxNot supported02πxdx{\displaystyle \int_0^{\mathrlap{2\pi}} x \,\mathrm{d} x}02πxdx{\displaystyle \int_0^{\mathrlap{2\pi}} x \,\mathrm{d} x}\int_0^{\mathrlap{2\pi}} x\,\mathrm{d} x
    \mathringa˚\(\mathring{a}\)a˚\mathring{a}Not supported\mathring{a}
    \mathrmAaBb12θ\(\mathrm{AaBb12\theta}\)AaBb12θ\mathrm{AaBb12\theta}AaBb12θ\mathrm{AaBb12\theta}\mathrm{AaBb12\theta}
    \mathscr𝒜\(\mathscr{AB}\)AB\mathscr{AB}𝒜\mathscr{AB}\mathscr{AaBb123}
    \mathsf𝖠𝖺𝖡𝖻𝟣𝟤𝟥\(\mathsf{AaBb123}\)AaBb123\mathsf{AaBb123}𝖠𝖺𝖡𝖻𝟣𝟤𝟥\mathsf{AaBb123}\mathsf{AaBb123}
    \mathsterling£Not supported£\mathsterlingNot supported
    \mathstrut(α\(\sqrt{\mathstrut\alpha}\)(α\sqrt{\mathstrut\alpha}Not supported\sqrt{\mathstrut\alpha}
    \mathtipa=bNot supportedNot supportedNot supported\mathtip{a=b}{tip}s
    \mathtt𝙰𝚊𝙱𝚋𝟷𝟸𝟹\(\mathtt{AaBb123}\)AaBb123\mathtt{AaBb123}𝙰𝚊𝙱𝚋𝟷𝟸𝟹\mathtt{AaBb123}\mathtt{AaBb123}
    \matrixNot supported\(\matrix{a & b \\ c & d}\)Not supportedNot supported\matrix{a & b \\ c & d}
    {matrix}ABbABd\(\begin{matrix}\frac A B&b\\\frac A B&d\end{matrix}\)ABbABd\begin{matrix}\frac A B&b\\\frac A B&d\end{matrix}ABbABd\begin{matrix}\frac A B&b\\\frac A B&d\end{matrix}\begin{matrix}
       \frac A B & b \\
       \frac A B & d
    \end{matrix}
    \maxmaxxmaxyxmaxyx\(\begin{matrix}\max x \\ \max_y x \\\max\limits_y x\end{matrix}\)maxxmaxyxmaxyx\begin{matrix}\max x \\ \max_y x \\\max\limits_y x\end{matrix}max\max
    \mboxNot supported\(\mbox{in a box}\)Not supportedNot supported\mbox{in a box}
    \measuredangle\(\measuredangle\)\measuredangle\measuredangle
    \medspaceabNot supportedaba\medspace baba\medspace ba\medspace b
    \mho\(\mho\)\mho\mho
    \mid{x|x>0}\(\{x∈ℝ\mid x>0\}\){xRx>0}\{x∈ℝ\mid x > 0\}{xx>0}\{x∈ℝ\mid x>0\}\{x∈ℝ\mid x>0\}
    \middleP(A|B)\(P\left(A\middle\vert B\right)\)P(A|B)P\left(A\middle\vert B\right)Not supportedP\left(A\middle\vert B\right)
    \minminxminyxminyx\(\begin{matrix}\min x \\ \min_y x \\\min\limits_y x\end{matrix}\)minxminyxminyx\begin{matrix}\min x \\ \min_y x \\\min\limits_y x\end{matrix}min\min
    \minusoNot supported
    See \standardstate
    Not supported\minusoNot supported
    \mitNot supported\(\mit{\Gamma\Theta}\)Not supportedNot supported\mit{\Gamma\Theta}
    \mkernab\(a\mkern18mu b\)aba\mkern18mu bNot supporteda\mkern18mu b
    \mmlToken?Not supportedNot supportedNot supported
    \mod35mod2\(3\equiv 5 \mod 2\)35mod23\equiv 5 \mod 2Not supported3\equiv 5 \mod 2
    \models\(\models\)\models\models
    \moveleftNot supported\(O\moveleft3pt O\)Not supportedNot supportedO\moveleft3pt O
    \moverightNot supported\(O\moveright3pt O\)Not supportedNot supportedO\moveright3pt O
    \mp\(\mp\)\mp\mp
    \mskipab\(a\mskip{10mu}b\)aba\mskip{10mu}bNot supporteda\mskip{10mu}b
    \mspaceNot supported\(a\mspace18mu b\)Not supportedNot supporteda\mspace18mu b
    \MuΜ\(\Mu\)M\MuΜ\Mu
    \muμ\(\mu\)μ\muμ\mu
    \multicolumnNot supportedNot supportedNot supportedNot supported
    {multline}first linesecond linethird line\[\begin{multline} - \rm first\ line \\ - \rm second\ line \\ - \rm third\ line - \end{multline}\]Not supportedNot supported
    {multline*}first linesecond linethird line\[\begin{multline*} - \rm first\ line \\ - \rm second\ line \\ - \rm third\ line - \end{multline*}\]Not supportedNot supported
    \multimap\(\multimap\)\multimap\multimap
    \multimapbothNot supportedNot supportedNot supported
    \multimapinvNot supportedNot supportedNot supported
    - -

    N

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \N\(\N\)N\NNot supported
    \nabla\(\nabla\)\nabla\nabla
    \natnums\(\natnums\)N\natnumsNot supported
    \natural\(\natural\)\natural\natural
    \negmedspaceab\(a\negmedspace b\)a ⁣ba\negmedspace baba\negmedspace ba\negmedspace b
    \ncong\(\ncong\)\ncong\ncong
    \ne\(\ne\)\ne\ne
    \nearrow\(\nearrow\)\nearrow\nearrow
    \neg¬\(\neg\)¬\neg¬\neg
    \negthickspaceab\(a\negthickspace b\)a ⁣ba\negthickspace bNot supporteda\negthickspace b
    \negthinspaceab\(a\negthinspace b\)a ⁣ba\negthinspace bNot supporteda\negthinspace b
    \neq\(\neq\)\neq\neq
    \newcommand\(\newcommand\chk{\checkmark} \chk\)\newcommand\chk{\checkmark} \chkNot supported\newcommand\chk{\checkmark} \chk
    \newenvironmentNot supported\(\newenvironment{tinyit}{\tiny\it}{\normalsize\rm}\begin{tinyit}Really small.\end{tinyit}\)Not supportedNot supported\newenvironment{tinyit}{\tiny\it}{\normalsize\rm}
    \begin{tinyit}Really small.\end{tinyit}
    \NewextarrowNot supported\(\Newextarrow{\xrightharpoonup}{5,10}{0x21C0} A \xrightharpoonup{\text{note}} B\)Not supportedNot supported\Newextarrow{\xrightharpoonup}{5,10}{0x21C0}
    A \xrightharpoonup{\text{note}} B
    \newextarrowNot supported<Not supportedNot supportedNot supportedSpelling per LaTeX.
    \newlineabNot supportedaba\newline bNot supporteda\newline b
    \nexists\(\nexists\)\nexists\nexists
    \ngeq\(\ngeq\)\ngeq\ngeq
    \ngeqq\(\ngeqq\)\ngeqq⩾̸\ngeqq
    \ngeqslant\(\ngeqslant\)\ngeqslant⩾̸\ngeqslant
    \ngtr\(\ngtr\)\ngtr\ngtr
    \ni\(\ni\)\ni\ni
    \nleftarrow\(\nleftarrow\)\nleftarrow\nleftarrow
    \nLeftarrow\(\nLeftarrow\)\nLeftarrow\nLeftarrow
    \nLeftrightarrow\(\nLeftrightarrow\)\nLeftrightarrow\nLeftrightarrow
    \nleftrightarrow\(\nleftrightarrow\)\nleftrightarrow\nleftrightarrow
    \nleq\(\nleq\)\nleq\nleq
    \nleqq\(\nleqq\)\nleqq⩽̸\nleqq
    \nleqslant\(\nleqslant\)\nleqslant⩽̸\nleqslant
    \nless\(\nless\)\nless\nless
    \nmid\(\nmid\)\nmid\nmid
    \nobreakNot supportedNot supportedNot supportedNot supported
    \nobreakspacea b\(a\nobreakspace b\)a ba\nobreakspace bNot supporteda\nobreakspace b
    \nolimitslimx\(\lim\nolimits_x\)limx\lim\nolimits_xNot supported\lim\nolimits_x
    \normalsizenormalsize\(\normalsize normalsize\)normalsize\normalsize normalsizeNot supported\normalsize normalsize
    \not\(\not =\)\not =¬=\not =\not =
    \notagNot supportedNot supportedNot supported
    \notin\(\notin\)\notin\notin
    \notniNot supported\notni\notni
    \nparallel\(\nparallel\)\nparallel\nparallel
    \nprec\(\nprec\)\nprec\nprec
    \npreceq\(\npreceq\)\npreceq⪯̸\npreceq
    \nRightarrow\(\nRightarrow\)\nRightarrow\nRightarrow
    \nrightarrow\(\nrightarrow\)\nrightarrow\nrightarrow
    \nshortmid\(\nshortmid\)\nshortmid\nshortmid
    \nshortparallel\(\nshortparallel\)\nshortparallel\nshortparallel
    \nsim\(\nsim\)\nsim\nsim
    \nsubsetNot supportedNot supported\nsubset
    \nsubseteq\(\nsubseteq\)\nsubseteq\nsubseteq
    \nsubseteqq\(\nsubseteqq\)\nsubseteqq\nsubseteqq
    \nsucc\(\nsucc\)\nsucc\nsucc
    \nsucceq\(\nsucceq\)\nsucceq⪰̸\nsucceq
    \nsupsetNot supportedNot supported\nsupset
    \nsupseteq\(\nsupseteq\)\nsupseteq\nsupseteq
    \nsupseteqq\(\nsupseteqq\)\nsupseteqqNot supported
    \ntriangleleft\(\ntriangleleft\)\ntriangleleft\ntriangleleft
    \ntrianglelefteq\(\ntrianglelefteq\)\ntrianglelefteq\ntrianglelefteq
    \ntriangleright\(\ntriangleright\)\ntriangleright\ntriangleright
    \ntrianglerighteq\(\ntrianglerighteq\)\ntrianglerighteq\ntrianglerighteq
    \NuΝ\(\Nu\)N\NuΝ\Nu
    \nuν\(\nu\)ν\nuν\nu
    \nVDash\(\nVDash\)\nVDash\nVDash
    \nVdash\(\nVdash\)\nVdash\nVdash
    \nvDash\(\nvDash\)\nvDash\nvDash
    \nvdash\(\nvdash\)\nvdash\nvdash
    \nwarrow\(\nwarrow\)\nwarrow\nwarrow
    - -

    O

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \OØNot supportedØ\text{\O}Not supported\text{\O}
    \oøNot supportedø\text{\o}Not supported\text{\o}
    \oc!Not supportedNot supportedNot supported
    \odvdfdxNot supportedNot supportedNot supported\odv{f}{x}
    \odv*`ddxfNot supportedNot supportedNot supported\odv*{f}{x}
    \odot\(\odot\)\odot\odot
    \OEŒNot supportedŒ\text{\OE}Not supported\text{\OE}
    \oeœNot supportedœ\text{\oe}Not supported\text{\oe}
    \officialeuroNot supported
    See \euro
    \(\officialeuro\)Not supportedNot supported
    \oiiint0nx0nx\(\oiiint_0^n x \; \displaystyle \oiiint_0^n x\)0nx  0nx\oiiint_0^n x \; \displaystyle \oiiint_0^n x\oiiint
    \oiint0nx0nx\(\oiint_0^n x \; \displaystyle \oiint_0^n x\)0nx  0nx\oiint_0^n x \; \displaystyle \oiint_0^n x\oiint
    \oint0nx0nx\(\oint_0^n x \; \displaystyle \oint_0^n x\)0nx  0nx\oint_0^n x \; \displaystyle \oint_0^n x\oint
    \oldstyleNot supported
    See \oldstylenums
    \(\oldstyle 0123456\)Not supportedNot supported\oldstyle 0123456
    \oldstylenums123Not supportedNot supportedNot supported\oldstylenums{123}
    \omegaω\(\omega\)ω\omegaω\omega
    \OmegaΩ\(\Omega\)Ω\OmegaΩ\Omega
    \OmicronΟ\(\Omicron\)O\OmicronNot supported
    \omicronο\(\omicron\)ο\omicron\omicron
    \ominus\(\ominus\)\ominus\ominus
    \operatornameasinx\(\operatorname{asin} x\)asinx\operatorname{asin} xasinx\operatorname{asin} x\operatorname{asin} x
    \operatorname*asinxasinyxasinyx\(\begin{matrix}\operatorname*{asin} x \\ \operatorname*{asin}_y x \\ \operatorname*{asin}\limits_y x\end{matrix}\)asinxasinyxasinyx\begin{matrix}\operatorname*{asin} x \\ \operatorname*{asin}_y x \\ \operatorname*{asin}\limits_y x\end{matrix}Not supported\operatorname*{asin} x
    \operatorname*{asin}_y x
    \operatorname*{asin}\limits_y x\end
    \oplus\(\oplus\)\oplus\oplus
    \orNot supportedNot supportedNot supportedNot supported
    \origofNot supported\origofNot supported
    \oslash\(\oslash\)\oslash\oslash
    \otimes\(\otimes\)\otimes\otimes
    \overa+1b+2+c\({a+1 \over b+2}+c\)a+1b+2+c{a+1 \over b+2}+ca+1b+2+c{a+1 \over b+2}+c{a+1 \over b+2}+c
    \overbracex++xn times\(\overbrace{x+⋯+x}^{n\text{ times}}\)x++xn times\overbrace{x+⋯+x}^{n\text{ times}}x++xn times\overbrace{x+⋯+x}^{n\text{ times}}\overbrace{x+⋯+x}^{n\text{ times}}
    \overbracketNot supportedNot supportedNot supportedNot supported
    \overgroupABNot supportedAB\overgroup{AB}Not supported\overgroup{AB}
    \overleftarrowAB\(\overleftarrow{AB}\)AB\overleftarrow{AB}Not supported\overleftarrow{AB}
    \overleftharpoonABNot supportedAB\overleftharpoon{AB}Not supported\overleftharpoon{AB}
    \overleftrightarrowAB\(\overleftrightarrow{AB}\)AB\overleftrightarrow{AB}Not supported\overleftrightarrow{AB}
    \overlinea long argument_\(\overline{\text{a long argument}}\)a long argument\overline{\text{a long argument}}a long argument¯\overline{\text{a long argument}}\overline{\text{a long argument}}
    \overlinesegmentNot supportedNot supportedNot supportedNot supported
    \overparenAB\(\overparen{AB}\)Not supportedNot supportedSee \overgroup
    \OverrightarrowABNot supportedAB\Overrightarrow{AB}Not supported\Overrightarrow{AB}
    \overrightarrowAB\(\overrightarrow{AB}\)AB\overrightarrow{AB}Not supported\overrightarrow{AB}
    \overrightharpoonacNot supportedac\overrightharpoon{ac}Not supported\overrightharpoon{ac}
    \overset=!\(\overset{!}{=}\)=!\overset{!}{=}=!\overset{!}{=}\overset{!}{=}
    \overwithdelimsNot supported\(a \overwithdelims [ ] b\)Not supportedNot supported
    \owns\(\owns\)\ownsNot supported
    - -

    P

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \PNot supported\text{\P}Not supported\text{\P}
    \pagecolor?Not supportedNot supportedNot supportedDeprecated
    \parallel\(\parallel\)\parallel\parallel
    \parrNot supportedNot supportedNot supported
    \part??Not supportedNot supportedNot supportedDeprecated
    \partial\(\partial\)\partial\partial
    \permilNot supportedNot supportedNot supported
    \pdv2fxyNot supportedNot supportedNot supported\pdv{f}{x,y}
    \pdv*2xyfNot supportedNot supportedNot supported\pdv*{f}{x,y}
    \perp\(\perp\)\perp\perp
    \phantomΓijkij\(\Gamma^{\phantom{i}j}_{i\phantom{j}k}\)Γijkij\Gamma^{\phantom{i}j}_{i\phantom{j}k}Γijkij\Gamma^{\phantom{i}j}_{i\phantom{j}k}\Gamma^{\phantom{i}j}_{i\phantom{j}k}
    \phase120V78.2°Not supported
    See \enclose
    120V78.2°120\text{V}\phase{78.2\degree}Not supported120\text{V}\phase{78.2\degree}
    \PhiΦ\(\Phi\)Φ\PhiΦ\Phi
    \phiϕ\(\phi\)ϕ\phiϕ\phi
    \PiΠ\(\Pi\)Π\PiΠ\Pi
    \piπ\(\pi\)π\piπ\pi
    {picture}Not supportedNot supportedNot supportedNot supported
    \pitchfork\(\pitchfork\)\pitchfork\pitchfork
    \plimplimNot supportedplim\plimNot supported
    \plusmn±\(\plusmn\)±\plusmnNot supported
    \pm±\(\pm\)±\pm±\pm
    \pmatrixNot supported\(\pmatrix{a&b\\c&d}\)Not supportedNot supportedSee {pmatrix}
    {pmatrix}(abcd)\(\begin{pmatrix}a&b\\c&d\end{pmatrix}\)(abcd)\begin{pmatrix}a&b\\c&d\end{pmatrix}(abcd)\begin{pmatrix}a&b\\c&d\end{pmatrix}\begin{pmatrix}
       a & b \\
       c & d
    \end{pmatrix}
    \pmbμ\(\pmb{\mu}\)μ\pmb{\mu}Not supported\pmb{\mu}
    \pmodx(moda)\(x\pmod a\)x(moda)x\pmod aNot supportedx\pmod a
    \podx(a)\(x \pod a\)x(a)x \pod aNot supportedx \pod a
    \pounds£Not supported£\poundsNot supported
    \PrPrxPryxPryx\(\begin{matrix}\Pr x \\ \Pr_y x \\\Pr\limits_y x\end{matrix}\)PrxPryxPryx\begin{matrix}\Pr x \\ \Pr_y x \\\Pr\limits_y x\end{matrix}Pr\Pr
    \prec\(\prec\)\prec\prec
    \precapprox\(\precapprox\)\precapprox\precapprox
    \preccurlyeq\(\preccurlyeq\)\preccurlyeq\preccurlyeq
    \preceq\(\preceq\)\preceq\preceq
    \precnapprox\(\precnapprox\)\precnapprox\precnapprox
    \precneqq\(\precneqq\)\precneqq\precneqq
    \precnsim\(\precnsim\)\precnsim\precnsim
    \precsim\(\precsim\)\precsim\precsim
    \prescript𝐂25+a2Not supportedNot supportedNot supported\prescript{a}{2}{\mathbf{C}}^{5+}_{2}
    \prime\(\prime\)\primeNot supported
    \prod0nx0nx\(\prod_0^n x \; \displaystyle \prod_0^n x\)0nx  0nx\prod_0^n x \; \displaystyle \prod_0^n x\prod
    \projlimprojlimnx\(\projlim_n x\)proj limnx\projlim_n xNot supported\projlim_n x
    \propto\(\propto\)\propto\propto
    \providecommandHelloNot supportedHello\providecommand\greet{\text{Hello}} \greetNot supported\providecommand\greet{\text{Hello}} \greet
    \psiψ\(\psi\)ψ\psiψ\psi
    \PsiΨ\(\Psi\)Ψ\PsiΨ\Psi
    \pu123 kJmol\({123~\mathchoice{\textstyle\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}}\)123 kJmol{123~\mathchoice{\textstyle\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}{\frac{\mathrm{kJ}}{\mathrm{mol}}}}Not supported\pu{123 kJ//mol}
    - -

    QR

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \QNot supported\(\Q\)Not supportedNot supportedSee \Bbb{Q}
    \qquadab\(a\qquad\qquad{b}\)aba\qquad\qquad{b}aba\qquad\qquad{b}a\qquad\qquad{b}
    \quadab\(a\quad\quad{b}\)aba\quad\quad{b}aba\quad\quad{b}a\quad\quad{b}
    \R\(\R\)R\RNot supported
    \ra˚\(\text{\r{a}}\)a˚\text{\r{a}}Not supported\text{\r{a}}
    \raisehigher\(h\raise{2pt}{ighe}r\)Not supportedNot supportedh\raise{2pt}{ighe}r
    \raiseboxhigherNot supportedhigherh\raisebox{2pt}{ighe}rNot supportedh\raisebox{2pt}{ighe}r
    \rangA\(\langle A\rang\)A\langle A\rangA\langle A\rang\langle A\rang
    \rangleA\(\langle A\rangle\)A\langle A\rangleA\langle A\rangle\langle A\rangle
    \Rarr\(\Rarr\)\RarrNot supported
    \rArr\(\rArr\)\rArrNot supported
    \rarr\(\rarr\)\rarrNot supported
    \rBraceNot supported\rBraceNot supported
    \rbrace}\(\rbrace\)}\rbrace}\rbrace
    \rbrack]\(\rbrack\)]\rbrack]\rbrack
    {rcases}aif bcif d}Not supportedaif bcif d}\begin{rcases}a&\text{if }b\\c&\text{if }d\end{rcases}Not supported\begin{rcases}
       a&\text{if }b\\
       c&\text{if }d
    \end{rcases}
    \rceil\(\rceil\)\rceil\rceil
    \Re\(\Re\)\Re\Re
    \real\(\real\)\realNot supported
    \Reals\(\Reals\)R\RealsNot supported
    \reals\(\reals\)R\realsNot supported
    \refSupportedNot supportedNot supported\ref{maxwell}
    \relaxNot supportedNot supported
    \renewcommandAhoy!\(\def\hail{Hi!}\renewcommand\hail{\text{Ahoy!}} \hail\)Ahoy!\def\hail{Hi!}\renewcommand\hail{\text{Ahoy!}} \hailNot supported\def\hail{Hi!}
    \renewcommand\hail{\text{Ahoy!}}
    \hail
    \renewenvironmentNot supportedNot supportedNot supported
    \requireNot supportedNot supportedNot supported
    \restriction\(\restriction\)\restrictionNot supported
    \rfloor\(\rfloor\)\rfloor\rfloor
    \rgroup\(\rgroup\)\rgroupNot supported
    \rhd\(\rhd\)\rhd\rhd
    \RhoΡ\(\Rho\)P\RhoΡ\Rho
    \rhoρ\(\rho\)ρ\rhoρ\rho
    \rightab)\(\left.\frac a b\right)\)ab)\left.\frac a b\right)ab)\left.\frac a b\right)\left.\frac a b\right)
    \Rightarrow\(\Rightarrow\)\Rightarrow\Rightarrow
    \rightarrow\(\rightarrow\)\rightarrow\rightarrow
    \rightarrowtail\(\rightarrowtail\)\rightarrowtail\rightarrowtail
    \rightharpoondown\(\rightharpoondown\)\rightharpoondown\rightharpoondown
    \rightharpoonup\(\rightharpoonup\)\rightharpoonup\rightharpoonup
    \rightleftarrows\(\rightleftarrows\)\rightleftarrows\rightleftarrows
    \rightleftharpoons\(\rightleftharpoons\)\rightleftharpoons\rightleftharpoons
    \rightrightarrows\(\rightrightarrows\)\rightrightarrows\rightrightarrows
    \rightsquigarrow\(\rightsquigarrow\)\rightsquigarrow\rightsquigarrow
    \rightthreetimes\(\rightthreetimes\)\rightthreetimes\rightthreetimes
    \risingdotseq\(\risingdotseq\)\risingdotseq\risingdotseq
    \rlap=\(\rlap{\,/}{=}\)/=\rlap{\,/}{=}Not supported\rlap{\,/}{=}
    \rmAaBb12θ\(\rm AaBb12\theta\)AaBb12θ\rm AaBb12\thetaNot supported\rm AaBb12\theta
    \rmoustache\(\rmoustache\)\rmoustache\rmoustache
    \rootNot supported\(\root 3 \of x\)Not supportedx3\root{3}{x}MathJax and TeXZilla differ in syntax:
    \root 3 \of x vs. \root{3}{x}
    \rotateboxNot supportedNot supportedNot supportedNot supported
    \rparen)Not supported)\rparenNot supported
    \rqNot supported\rqNot supported
    \Rrightarrow\(\Rrightarrow\)\Rrightarrow\Rrightarrow
    \rrbracketNot supported\rrbracketNot supported
    \Rsh\(\Rsh\)\Rsh\Rsh
    \rtimes\(\rtimes\)\rtimes\rtimes
    \RuleNot supported\(x\Rule{3px}{0.5ex}{2ex}x\)Not supportedNot supportedNon-standard
    \rulexx\(x\color{blue}\rule[6pt]{2ex}{1ex}x\)xxx\color{blue}\rule[6pt]{2ex}{1ex}xNot supportedx\color{blue}\rule[6pt]{2ex}{1ex}x
    \rVert\(\rVert\)\rVertNot supported
    \rvert|\(\rvert\)\rvertNot supported
    - -

    S

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \S§Not supported§\text{\S}Not supported\text{\S}
    \SampiϠNot supportedNot supportedNot supported
    \sampiϡNot supportedNot supportedNot supported
    \scaleboxNot supportedNot supportedNot supportedNot supported
    \scohNot supportedNot supportedNot supported
    \scrNot supported\(\scr M\)Not supportedNot supported\scr M
    \scriptscriptstylecd\(\scriptscriptstyle \frac cd\)cd\scriptscriptstyle \frac cdNot supported\scriptscriptstyle \frac cd
    \scriptsizescriptsize\(\scriptsize scriptsize\)scriptsize\scriptsize scriptsizescriptsize\scriptsize scriptsize\scriptsize scriptsize
    \scriptstyleab+cd\(\frac ab + {\scriptstyle \frac cd}\)ab+cd\frac ab + {\scriptstyle \frac cd}Not supported\frac ab + {\scriptstyle \frac cd}
    \sdot\(\sdot\)\sdotNot supported
    \searrow\(\searrow\)\searrow\searrow
    \secsec\(\sec\)sec\secsec\sec
    \sect§Not supported§\text{\sect}Not supported\text{\sect}
    \set{x|x<5}Requires extensionNot supportedNot supported\Set{x|x<5}
    \Set{x|x<12}Requires extensionNot supportedNot supported\Set{ x | x<\frac 1 2 }
    \setlengthNot supportedNot supportedNot supportedNot supported
    \setminus\(\setminus\)\setminus\setminus
    \sf𝖠𝖺𝖡𝖻𝟣𝟤𝟥\(\sf AaBb123\)AaBb123\sf AaBb123Not supported\sf AaBb123
    \sgnsgnNot supportedNot supportedNot supported
    \sharp\(\sharp\)\sharp\sharp
    \shiftNot supportedNot supportedNot supported
    \shnegNot supportedNot supportedNot supported
    \shortmid\(\shortmid\)\shortmid\shortmid
    \shortparallel\(\shortparallel\)\shortparallel\shortparallel
    \shoveleftNot supported\(\begin{multline*} -\rm first\ line \\ -\shoveleft{\rm 2nd} \\ -\rm third\ line -\end{multline*}\)Not supportedNot supported
    \shoverightNot supported\(\begin{multline*} -\rm first\ line \\ -\shoveright{\rm 2nd} \\ -\rm third\ line -\end{multline*}\)Not supportedNot supported
    \shposNot supportedNot supportedNot supported
    \sideset3412Not supportedNot supportedNot supported
    \SigmaΣ\(\Sigma\)Σ\SigmaΣ\Sigma
    \sigmaσ\(\sigma\)σ\sigmaσ\sigma
    \sim\(\sim\)\sim\sim
    \simeq\(\simeq\)\simeq\simeq
    \sinsinx\(\sin x\)sinx\sin xsinx\sin x
    \sincohNot supportedNot supportedNot supported
    \sinhsinhx\(\sinh x\)sinhx\sinh xsinhx\sinh x
    \sixptsizesixptsizeNot supportedsixptsize\sixptsize sixptsizeNot supported\sixptsize sixptsize
    \shshNot supportedsh\shNot supported
    \skewNot supported\(\hat A\skew9\hat A\)Not supportedNot supported\hat A\skew9\hat A
    \skipNot supportedNot supportedNot supportedNot supported
    \smallsmall\(\small small\)small\small smallNot supported\small small
    \smallfrown\(\smallfrown\)\smallfrown\smallfrown
    \smallint0nx0nx0nx\(\smallint_0^n x \; \smallint\limits_0^n x \; \displaystyle \smallint_0^n x\)0nx  0nx  0nx\smallint_0^n x \; \smallint\limits_0^n x \; \displaystyle \smallint_0^n xNot supported - \smallint_0^n x
    \smallint\limits_0^n x
    \displaystyle \smallint_0^n x -
    {smallmatrix}abcd\(\begin{smallmatrix}a & b\\c & d\end{smallmatrix}\)abcd\begin{smallmatrix}a & b\\c & d\end{smallmatrix}abcd\begin{smallmatrix}a & b\\c & d\end{smallmatrix}\begin{smallmatrix}a & b\\
    c & d\end{smallmatrix}
    \smallsetminus\(\smallsetminus\)\smallsetminus\smallsetminus
    \smallsmile\(\smallsmile\)\smallsmile\smallsmile
    \smash(x2)\(\left(x^{\smash{2}}\right)\)(x2)\left(x^{\smash{2}}\right)Not supported\left(x^{\smash{2}}\right)
    \smile\(\smile\)\smile\smile
    \smileyNot supportedNot supportedNot supportedwasysym
    \soutabcNot supportedabc\sout{abc}Not supported\sout{abc}
    \SpaceNot supported\(a\Space{5px}{4ex}{2ex}^b_c d\)Not supportedNot supporteda\Space{5px}{4ex}{2ex}^b_c d
    \spacea b\(a\space{b}\)a ba\space{b}Not supporteda\space{b}
    \spades\(\spades\)\spadesNot supported
    \spadesuit\(\spadesuit\)\spadesuit\spadesuit
    \sphericalangle\(\sphericalangle\)\sphericalangle\sphericalangle
    {split}·𝐃=ρv·𝐁=0\[\begin{equation}\begin{split}∇·𝐃&=ρ_v \\∇·𝐁&=0\end{split}\end{equation}\]𝐃=ρv𝐁=0\begin{equation}\begin{split}∇·𝐃&=ρ_v \\∇·𝐁&=0\end{split}\end{equation}Not supported\begin{equation}
    \begin{split}
       ∇·𝐃&=ρ_v \\
       ∇·𝐁&=0
    \end{split}
    \end{equation}
    \sqcap\(\sqcap\)\sqcap\sqcap
    \sqcup\(\sqcup\)\sqcup\sqcup
    \square\(\square\)\square\square
    \sqrtx3\(\sqrt[3]{x}\)x3\sqrt[3]{x}x3\sqrt[3]{x}\sqrt[3]{x}
    \sqsubset\(\sqsubset\)\sqsubset\sqsubset
    \sqsubseteq\(\sqsubseteq\)\sqsubseteq\sqsubseteq
    \sqsupset\(\sqsupset\)\sqsupset\sqsupset
    \sqsupseteq\(\sqsupseteq\)\sqsupseteq\sqsupseteq
    \ssßNot supportedß\text{\ss}Not supported\text{\ss}
    \stackrel=!\(\stackrel{!}{=}\)=!\stackrel{!}{=}=!\stackrel{!}{=}\stackrel{!}{=}
    \star\(\star\)\star\star
    \StigmaϚNot supportedNot supportedNot supported
    \stigmaϛNot supportedNot supportedNot supported
    \strictifNot supportedNot supportedNot supported
    \strictfiNot supportedNot supportedNot supported
    \strutNot supported\(\boxed{ab\strut}\)Not supportedNot supported\boxed{ab\strut}
    \styleNot supported\(\frac{\style{color:red}{x+1}}{y+2}\)Not supportedNot supported\frac{\style{color:red}{x+1}}{y+2}
    Non standard
    \sub\(\sub\)\subNot supported
    {subarray}ac\(\begin{subarray}{c} a \\ c \end{subarray}\)ac\begin{subarray}{c} a \\ c \end{subarray}Not supported\sum_{\begin{subarray}
       {c} a \\
       c
    \end{subarray}}
    \sube\(\sube\)\subeNot supported
    \Subset\(\Subset\)\Subset\Subset
    \subset\(\subset\)\subset\subset
    \subseteq\(\subseteq\)\subseteq\subseteq
    \subseteqq\(\subseteqq\)\subseteqq\subseteqq
    \subsetneq\(\subsetneq\)\subsetneq\subsetneq
    \subsetneqq\(\subsetneqq\)\subsetneqq\subsetneqq
    \substack1<i<31j<5aij\(\displaystyle\sum_{\substack{1\lt i\lt 3 \\ 1\le j\lt 5}}a_{ij}\)1<i<31j<5aij\displaystyle\sum_{\substack{1\lt i\lt 3 \\ 1\le j\lt 5}}a_{ij}1<i<31j<5aij\displaystyle\sum_{\substack{1\lt i\lt 3 \\ 1\le j\lt 5}}a_{ij}\sum_{\substack{1\lt i\lt 3 \\
    1\le j\lt 5}}a_{ij}
    \succ\(\succ\)\succ\succ
    \succapprox\(\succapprox\)\succapprox\succapprox
    \succcurlyeq\(\succcurlyeq\)\succcurlyeq\succcurlyeq
    \succeq\(\succeq\)\succeq\succeq
    \succnapprox\(\succnapprox\)\succnapprox\succnapprox
    \succneqq\(\succneqq\)\succneqq\succneqq
    \succnsim\(\succnsim\)\succnsim\succnsim
    \succsim\(\succsim\)\succsim\succsim
    \sum0nx0nx\(\sum_0^n x \; \displaystyle \sum_0^n x\)0nx  0nx\sum_0^n x \; \displaystyle \sum_0^n x0nx\sum_0^n x
    \supsupxsupyxsupyx\(\begin{matrix}\sup x \\ \sup_y x \\\sup\limits_y x\end{matrix}\)supxsupyxsupyx\begin{matrix}\sup x \\ \sup_y x \\\sup\limits_y x\end{matrix}supxsupyxsuplimitsyx\begin{matrix}\sup x \\ \sup_y x \\\sup\limits_y x\end{matrix}
    \supe\(\supe\)\supesupe\supe
    \Supset\(\Supset\)\Supset\Supset
    \supset\(\supset\)\supset\supset
    \supseteq\(\supseteq\)\supseteq\supseteq
    \supseteqq\(\supseteqq\)\supseteqq\supseteqq
    \supsetneq\(\supsetneq\)\supsetneq\supsetneq
    \supsetneqq\(\supsetneqq\)\supsetneqq\supsetneqq
    \surd\(\surd\)\surd\surd
    \swarrow\(\swarrow\)\swarrow\swarrow
    - -

    T

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \taga2+b2=c2(3.1c)\(\tag{3.1c} a^2+b^2=c^2\)a2+b2=c2(3.1c)\tag{3.1c} a^2+b^2=c^2Not supported\tag{3.1c} a^2+b^2=c^2
    \tag*a2+b2=c23.1c\(\tag*{3.1c} a^2+b^2=c^2\)a2+b2=c23.1c\tag*{3.1c} a^2+b^2=c^2Not supported\tag*{3.1c} a^2+b^2=c^2
    \tantanx\(\tan x\)tanx\tan xtanx\tan x
    \tanhtanhx\(\tanh x\)tanhx\tanh xtanhx\tanh x
    \TauΤ\(\Tau\)T\TauΤ\Tau
    \tauτ\(\tau\)τ\tauτ\tau
    \tbinom(nk)\(\tbinom n k\)(nk)\tbinom n k(nk)\tbinom n k\tbinom n k
    \TeXTEX\(\TeX\)TeX\TeXNot supported
    \text yes & no \(\text{ yes }\&\text{ no }\) yes & no \text{ yes }\&\text{ no } yes & no \text{ yes }\&\text{ no }\text{ yes }\&\text{ no }
    \textMMMMMMMM\(\text{MMM$M\mkern2mu M$M}\)MMMMMM\text{MMM$M\mkern2mu M$M}Not supported\text{MMM$M\mkern2mu M$M}
    \textasciitilde~Not supported~\text{\textasciitilde}Not supported\text{\textasciitilde}
    \textasciicircum^Not supported^\text{\textasciicircum}Not supported\text{\textasciicircum}
    \textbackslash\Not supported\\text{\textbackslash}Not supported\text{\textbackslash}
    \textbar|Not supported|\text{\textbar}Not supported\text{\textbar}
    \textbardblNot supported\text{\textbardbl}Not supported\text{\textbardbl}
    \textbf𝐀𝐚𝐁𝐛𝟏\(\textbf{AaBb123}\)AaBb123\textbf{AaBb123}Not supported\textbf{AaBb123}
    \textbraceleft{Not supported{\text{\textbraceleft}Not supported\text{\textbraceleft}
    \textbraceright}Not supported}\text{\textbraceright}Not supported\text{\textbraceright}
    \textcircledNot supportedNot supportedNot supportedNot supported\text{\textcircled a}
    \textcolorF=ma\(\textcolor{blue}{F=ma}\)F=ma\textcolor{blue}{F=ma}Not supported\textcolor{blue}{F=ma}
    \textdaggerNot supported\text{\textdagger}Not supported\text{\textdagger}
    \textdaggerdblNot supported\text{\textdaggerdbl}Not supported\text{\textdaggerdbl}
    \textdegree°Not supported°\text{\textdegree}Not supported\text{\textdegree}
    \textdollar$Not supported$\text{\textdollar}Not supported\text{\textdollar}
    \textellipsisNot supported\text{\textellipsis}Not supported\text{\textellipsis}
    \textemdashNot supported\text{\textemdash}Not supported\text{\textemdash}
    \textendashNot supported\text{\textendash}Not supported\text{\textendash}
    \textgreater>Not supported>\text{\textgreater}Not supported\text{\textgreater}
    \textit𝐴𝑎𝐵𝑏\(\textit{AaBb}\)AaBb\textit{AaBb}Not supported\textit{AaBb}
    \textless<Not supported<\text{\textless}Not supported\text{\textless}
    \textnormalABNot supportedAB\textnormal{AB}Not supported\textnormal{AB}
    \textquotedblleftNot supported\text{\textquotedblleft}Not supported\text{\textquotedblleft}
    \textquotedblrightNot supported\text{\textquotedblright}Not supported\text{\textquotedblright}
    \textquoteleftNot supported\text{\textquoteleft}Not supported\text{\textquoteleft}
    \textquoterightNot supported\text{\textquoteright}Not supported\text{\textquoteright}
    \textregistered®Not supported®\text{\textregistered}Not supported\text{\textregistered}
    \textrmAaBb123\(\textrm{AaBb123}\)AaBb123\textrm{AaBb123}Not supported\textrm{AaBb123}
    \textscNot supportedNot supportedNot supportedNot supported
    \textsf𝖠𝖺𝖡𝖻𝟣\(\textsf{AaBb123}\)AaBb123\textsf{AaBb123}Not supported\textsf{AaBb123}
    \textsterling£Not supported£\text{\textsterling}Not supported\text{\textsterling}
    \textstyle0n\(\textstyle\sum_0^n\)0n\textstyle\sum_0^n0n\textstyle\sum_0^n\textstyle\sum_0^n
    \texttiphover hereNot supportedNot supportedNot supported\texttip{\text{hover here}}{tip}
    \texttt𝙰𝚊𝙱𝚋𝟷\(\texttt{AaBb123}\)AaBb123\texttt{AaBb123}Not supported\texttt{AaBb123}
    \textunderscore_Not supported_\text{\textunderscore}Not supported\text{\textunderscore}
    \textvisiblespaceNot supported\(a\textvisiblespace b\)Not supportedNot supported
    \tfracab\(\displaystyle \tfrac a b\)ab\displaystyle \tfrac a bab\displaystyle \tfrac a b\displaystyle \tfrac a b
    \tgtgNot supportedtg\tgNot supported
    \ththNot supportedth\thNot supported
    \therefore\(\therefore\)\therefore\therefore
    \ThetaΘ\(\Theta\)Θ\ThetaΘ\Theta
    \thetaθ\(\theta\)θ\thetaθ\theta
    \thetasymϑ\(\thetasym\)ϑ\thetasymθsym\thetasym
    \thickapprox\(\thickapprox\)\thickapprox\thickapprox
    \thicksim\(\thicksim\)\thicksim\thicksim
    \thickspaceabNot supporteda  ba\thickspace baba\thickspace ba\thickspace b
    \thinspaceab\(a\thinspace b\)aba\thinspace baba\thinspace ba\thinspace b
    \tildeM~\(\tilde M\)M~\tilde MM˜\tilde M\tilde M
    \times×\(\times\)×\times×\times
    \TinyABNot supportedNot supportedNot supportedNon standard
    \tinytiny\(\tiny tiny\)tiny\tiny tinyNot supported\tiny tiny
    \to\(\to\)\to\to
    \toggleClick HereOuchNot supportedNot supportedHey!Click Here\toggle{\text{Hey!}}{\text{Click Here}}
    \top\(\top\)\top\top
    \triangle\(\triangle\)\triangle\triangle
    \triangledown\(\triangledown\)\triangledown\triangledown
    \triangleleft\(\triangleleft\)\triangleleft\triangleleft
    \trianglelefteq\(\trianglelefteq\)\trianglelefteq\trianglelefteq
    \triangleq\(\triangleq\)\triangleq\triangleq
    \triangleright\(\triangleright\)\triangleright\triangleright
    \trianglerighteq\(\trianglerighteq\)\trianglerighteq\trianglerighteq
    \tt𝙰𝚊𝙱𝚋𝟷𝟸𝟹\({\tt AaBb123}\)AaBb123{\tt AaBb123}Not supported{\tt AaBb123}
    \twoheadleftarrow\(\twoheadleftarrow\)\twoheadleftarrow\twoheadleftarrow
    \twoheadrightarrow\(\twoheadrightarrow\)\twoheadrightarrow\twoheadrightarrow
    - -

    U

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \ua˘Not supporteda˘\text{\u{a}}Not supported\text{\u{a}}
    \Uarr\(\Uarr\)\UarrNot supported
    \uArr\(\uArr\)\uArrNot supported
    \uarr\(\uarr\)\uarrNot supported
    \ulcorner\(\ulcorner\)\ulcornerNot supported
    \underbracex++xn times\(\underbrace{x+⋯+x}_{n\text{ times}}\)x++xn times\underbrace{x+⋯+x}_{n\text{ times}}x++xn times\underbrace{x+⋯+x}_{n\text{ times}}\underbrace{x+⋯+x}_{n\text{ times}}
    \underbracketNot supportedNot supportedNot supportedNot supported
    \undergroupABNot supportedAB\undergroup{AB}Not supported\undergroup{AB}
    \underleftarrowAB\(\underleftarrow{AB}\)AB\underleftarrow{AB}Not supported\underleftarrow{AB}
    \underleftrightarrowAB\(\underleftrightarrow{AB}\)AB\underleftrightarrow{AB}Not supported\underleftrightarrow{AB}
    \underrightarrowAB\(\underrightarrow{AB}\)AB\underrightarrow{AB}Not supported\underrightarrow{AB}
    \underlinea long argument_\(\underline{\text{a long argument}}\)a long argument\underline{\text{a long argument}}a long argument_\underline{\text{a long argument}}\underline{\text{a long argument}}
    \underlinesegmentNot supportedNot supportedNot supportedNot supported
    \underparenabcNot supportedNot supportedNot supported\underparen{abc}
    \underrightarrowAB\(\underrightarrow{AB}\)AB\underrightarrow{AB}Not supported\underrightarrow{AB}
    \underset=!\(\underset{!}{=}\)=!\underset{!}{=}=!\underset{!}{=}\underset{!}{=}
    \unicodeNot supported
    See \char
    \(\unicode{x263a}\)Not supportedNot supported\unicode{x263a}
    See \char for alternate.
    \unlhd\(\unlhd\)\unlhd\unlhd
    \unrhd\(\unrhd\)\unrhd\unrhd
    \upalphaαNot supportedNot supportedNot supported
    \Uparrow\(\Uparrow\)\Uparrow\Uparrow
    \uparrow\(\uparrow\)\uparrow\uparrow
    \upbetaβNot supportedNot supportedNot supported
    \upchiχNot supportedNot supportedNot supported
    \updeltaδNot supportedNot supportedNot supported
    \Updownarrow\(\Updownarrow\)\Updownarrow\Updownarrow
    \updownarrow\(\updownarrow\)\updownarrow\updownarrow
    \upetaηNot supportedNot supportedNot supported
    \upepsilonϵNot supportedNot supportedNot supported
    \upgammaγNot supportedNot supportedNot supported
    \upharpoonleft\(\upharpoonleft\)\upharpoonleft\upharpoonleft
    \upharpoonright\(\upharpoonright\)\upharpoonright\upharpoonright
    \upiotaιNot supportedNot supportedNot supported
    \upkappaκNot supportedNot supportedNot supported
    \uplambdaλNot supportedNot supportedNot supported
    \uplus\(\uplus\)\uplus\uplus
    \upmuμNot supportedNot supportedNot supported
    \upnuνNot supportedNot supportedNot supported
    \upomegaωNot supportedNot supportedNot supported
    \upomicronοNot supportedNot supportedNot supported
    \upphiϕNot supportedNot supportedNot supported
    \uppiπNot supportedNot supportedNot supported
    \uppsiψNot supportedNot supportedNot supported
    \uprhoρNot supportedNot supportedNot supported
    \uprootNot supported\(\sqrt[3\uproot2]{x}\)Not supportedNot supported\sqrt[3\uproot2]{x}
    \upsigmaσNot supportedNot supportedNot supported
    \UpsilonΥ\(\Upsilon\)Υ\Upsilonϒ\Upsilon
    \upsilonυ\(\upsilon\)υ\upsilonυ\upsilon
    \uptauτNot supportedNot supportedNot supported
    \upthetaθNot supportedNot supportedNot supported
    \upuparrows\(\upuparrows\)\upuparrows\upuparrows
    \upupsilonυNot supportedNot supportedNot supported
    \upxiξNot supportedNot supportedNot supported
    \upzetaζNot supportedNot supportedNot supported
    \urcorner\(\urcorner\)\urcornerNot supported
    \url𝚑𝚝𝚝𝚙𝚜://𝚝𝚎𝚖𝚖𝚕.𝚘𝚛𝚐/Not supportedhttps://temml.org/\url{https://temml.org/}Not supported\url{https://temml.org/}
    \utildeAB~Not supportedAB~\utilde{AB}Not supported\utilde{AB}
    - -

    V

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \vaˇNot supportedaˇ\text{\v{a}}Not supported\text{\v{a}}
    \varcoppaϙNot supportedNot supportedNot supported
    \varDelta𝛥\(\varDelta\)Δ\varDeltaNot supported
    \varepsilonε\(\varepsilon\)ε\varepsilonε\varepsilon
    \varGamma𝛤\(\varGamma\)Γ\varGammaNot supported
    \varinjlimlimnx\(\varinjlim\limits_n x\)limnx\varinjlim\limits_n xNot supported\varinjlim\limits_n x
    \varkappaϰ\(\varkappa\)ϰ\varkappaϰ\varkappa
    \varLambda𝛬\(\varLambda\)Λ\varLambdaNot supported
    \varliminflim_nx\(\varliminf\limits_n x\)limnx\varliminf\limits_n xNot supported\varliminf\limits_n x
    \varlimsuplim_nx\(\varlimsup\limits_n x\)limnx\varlimsup\limits_n xNot supported\varlimsup\limits_n x
    \varnothingø\(\varnothing\)\varnothing\varnothing
    \varOmega𝛺\(\varOmega\)Ω\varOmegaNot supported
    \varPhi𝛷\(\varPhi\)Φ\varPhiNot supported
    \varphiφ\(\varphi\)φ\varphiφ\varphi
    \varPi𝛱\(\varPi\)Π\varPiNot supported
    \varpiϖ\(\varpi\)ϖ\varpiϖ\varpi
    \varprojlimlimnx\(\varprojlim\limits_n x\)limnx\varprojlim\limits_n xNot supported\varprojlim\limits_n x
    \varpropto\(\varpropto\)\varpropto\varpropto
    \varPsi𝛹\(\varPsi\)Ψ\varPsiNot supported
    \varrhoϱ\(\varrho\)ϱ\varrhoϱ\varrho
    \varSigma𝛴\(\varSigma\)Σ\varSigmaNot supported
    \varsigmaς\(\varsigma\)ς\varsigmaς\varsigma
    \varstigmaNot supported\(\varstigma\)Not supportedNot supported
    \varsubsetneq⊊︀\(\varsubsetneq\)\varsubsetneq⊊︀\varsubsetneq
    \varsubsetneqq⫋︀\(\varsubsetneqq\)\varsubsetneqq⫋︀\varsubsetneqq
    \varsupsetneq\(\varsupsetneq\)\varsupsetneq⊋︀\varsupsetneq
    \varsupsetneqq⫌︀\(\varsupsetneqq\)\varsupsetneqq⫌︀\varsupsetneqq
    \varTheta𝛩\(\varTheta\)Θ\varThetaNot supported
    \varthetaϑ\(\vartheta\)ϑ\varthetaϑ\vartheta
    \vartriangle\(\vartriangle\)\vartriangle\vartriangle
    \vartriangleleft\(\vartriangleleft\)\vartriangleleft\vartriangleleft
    \vartriangleright\(\vartriangleright\)\vartriangleright\vartriangleright
    \varUpsilon𝛶\(\varUpsilon\)Υ\varUpsilonNot supported
    \varXi𝛯\(\varXi\)Ξ\varXiNot supported
    \vcentcolon:=Not supported:=\mathrel{\vcentcolon =}Not supported\mathrel{\vcentcolon =}
    \vcenterNot supportedNot supportedNot supportedNot supported
    \Vdash\(\Vdash\)\Vdash\Vdash
    \vDash\(\vDash\)\vDash\vDash
    \vdash\(\vdash\)\vdash\vdash
    \vdots\(\vdots\)\vdots\vdots
    \vecF\(\vec{F}\)F\vec{F}F\vec{F}\vec{F}
    \vee\(\vee\)\vee\vee
    \veebar\(\veebar\)\veebar\veebar
    \verb\frac a b\(\verb!\frac a b!\)\frac a b\verb!\frac a b!Not supported\verb!\frac a b!
    \Vert\(\Vert\)\Vert\Vert
    \vert|\(\vert\)\vert|\vert
    \vfilNot supportedNot supportedNot supportedNot supported
    \vfillNot supportedNot supportedNot supportedNot supported
    \vlineNot supportedNot supportedNot supportedNot supported
    {Vmatrix}abcd\(\begin{Vmatrix}a&b\\c&d\end{Vmatrix}\)abcd\begin{Vmatrix}a&b\\c&d\end{Vmatrix}abcd\begin{Vmatrix}a&b\\c&d\end{Vmatrix}\begin{Vmatrix}
       a & b \\
       c & d
    \end{Vmatrix}
    {vmatrix}|abcd|\(\begin{vmatrix}a&b\\c&d\end{vmatrix}\)abcd\begin{vmatrix}a&b\\c&d\end{vmatrix}|abcd|\begin{vmatrix}a&b\\c&d\end{vmatrix}\begin{vmatrix}
       a & b \\
       c & d
    \end{vmatrix}
    \vphantomMa_\(\overline{\vphantom{M}a}\)Ma\overline{\vphantom{M}a}Not supported\overline{\vphantom{M}a}
    \Vvdash\(\Vvdash\)\Vvdash\Vvdash
    - -

    W

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \wedge\(\wedge\)\wedge\wedge
    \weierp\(\weierp\)\weierpNot supported
    \widecheckABˇNot supportedABˇ\widecheck{AB}ABˇ\widecheck{AB}\widecheck{AB}
    \widehatAB^\(\widehat{AB}\)AB^\widehat{AB}AB^\widehat{AB}\widehat{AB}
    \wideparenABNot supportedNot supportedNot supported -
    \widetildeAB~\(\widetilde{AB}\)AB~\widetilde{AB}AB˜\widetilde{AB}\widetilde{AB}
    \with&Not supportedNot supportedNot supported -
    \wn?Not supportedNot supportedNot supported
    \wp\(\wp\)\wp\wp
    \wr\(\wr\)\wr\wr
    - -

    X

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \xcancelABC\(\xcancel{ABC}\)ABC\xcancel{ABC}Not supported\xcancel{ABC}
    \XiΞ\(\Xi\)Ξ\XiΞ\Xi
    \xiξ\(\xi\)ξ\xiξ\xi
    \xhookleftarrowabcNot supportedabc\xhookleftarrow{abc}abc\xhookleftarrow{abc}\xhookleftarrow{abc}
    \xhookrightarrowabcNot supportedabc\xhookrightarrow{abc}abc\xhookrightarrow{abc}\xhookrightarrow{abc}
    \xLeftarrowabcNot supportedabc\xLeftarrow{abc}abc\xLeftarrow{abc}\xLeftarrow{abc}
    \xleftarrowabc\(\xleftarrow{abc}\)abc\xleftarrow{abc}abc\xleftarrow{abc}\xleftarrow{abc}
    \xleftharpoondownabcNot supportedabc\xleftharpoondown{abc}Not supported\xleftharpoondown{abc}
    \xleftharpoonupabcNot supportedabc\xleftharpoonup{abc}Not supported\xleftharpoonup{abc}
    \xLeftrightarrowabcNot supportedabc\xLeftrightarrow{abc}abc\xLeftrightarrow{abc}\xLeftrightarrow{abc}
    \xleftrightarrowabc\(\xleftrightarrow{abc}\)abc\xleftrightarrow{abc}abc\xleftrightarrow{abc}\xleftrightarrow{abc}
    \xleftrightharpoonsabcabcNot supportedabc\xleftrightharpoons{abc}abc\xleftrightharpoons{abc}\xleftrightharpoons{abc}
    \xlongequal=abc\(\xlongequal{abc}\)=abc\xlongequal{abc}Not supported\xlongequal{abc}
    \xmapstoabc\(\xmapsto{abc}\)abc\xmapsto{abc}abc\xmapsto{abc}\xmapsto{abc}
    \xRightarrowabcNot supportedabc\xRightarrow{abc}abc\xRightarrow{abc}\xRightarrow{abc}
    \xrightarrowAabcBAghiabcdefB\(\begin{matrix}A \xrightarrow{abc} B\\ A \xrightarrow[ghi]{abcdef} B \end{matrix}\)AabcBAghiabcdefB\begin{matrix}A \xrightarrow{abc} B\\ A \xrightarrow[ghi]{abcdef} B \end{matrix}AabcBAghiabcdefB\begin{matrix}A \xrightarrow{abc} B\\ A \xrightarrow[ghi]{abcdef} B \end{matrix}A \xrightarrow{abc} B
    A \xrightarrow[ghi]{abcdef} B
    \xrightharpoondownabcNot supportedabc\xrightharpoondown{abc}Not supported\xrightharpoondown{abc}
    \xrightharpoonupabcNot supportedabc\xrightharpoonup{abc}Not supported\xrightharpoonup{abc}
    \xrightleftharpoonsabcabc\(\xrightleftharpoons{abc}\)abc\xrightleftharpoons{abc}abc\xrightleftharpoons{abc}\xrightleftharpoons{abc}
    \xtofromabcabc\(\xtofrom{abc}\)abc\xtofrom{abc}Not supported\xtofrom{abc}
    \xtwoheadleftarrowabc\(\xtwoheadleftarrow{abc}\)abc\xtwoheadleftarrow{abc}Not supported\xtwoheadleftarrow{abc}
    \xtwoheadrightarrowabc\(\xtwoheadrightarrow{abc}\)abc\xtwoheadrightarrow{abc}Not supported\xtwoheadrightarrow{abc}
    - -

    YZ

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FunctionTemmlMathJaxKaTeXTeXZillaSource or Comment
    \yen¥\(\yen\)¥\yenNot supported
    \Z\(\Z\)Z\ZNot supported
    \ZetaΖ\(\Zeta\)Z\ZetaΖ\Zeta
    \zetaζ\(\zeta\)ζ\zetaζ\zeta
    - -
    - -

    Copyright © 2021, 2022 Ron Kok. Released under the MIT License

    - -
    - -
    - - - - - - - - - \ No newline at end of file diff --git a/site/docs/en/support_table.html b/site/docs/en/support_table.html deleted file mode 100644 index 6066ab1c..00000000 --- a/site/docs/en/support_table.html +++ /dev/null @@ -1,1587 +0,0 @@ - - - - - - Temml Support Table - - - - - - -
    -

    Support Table

    -

    Temml is a JavaScript library that converts TeX math-mode functions to MathML. This page provides an alphabetically sorted list of TeX functions that Temml supports and some functions that it does not support. There is a similar page, with functions sorted by type.

    -

    To read this page, use a browser that supports MathML, such as Firefox or Safari. Chrome and Edge will support MathML soon.

    -

    Some functions are provided by an extension and are listed as such. They will be available only in pages that include the extension.

    -

    If you know the shape of a character, but not its name, Detexify can help.

    -

    Symbols

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    !n!n!
    \!aba\!b
    #y2\def\bar#1{#1^2} \bar{y}
    \##
    %%this is a comment
    \%%
    &abcd\begin{matrix}
       a & b \\
       c & d
    \end{matrix}
    \&&
    '
    \'aˊ\text{\'{a}}
    ((
    ))
    \a ba\ b
    \"a¨\text{\"{a}}
    \$ $
    \,aba\,\,{b}
    \.a˙\text{\.{a}}
    \:aba\:\:{b}
    \;aba\;\;{b}
    _xix_i
    \__
    \`aˋ\text{\'{a}}
    <<
    \=aˉ\text{\={a}}
    >>
    \>aba\>\>{b}
    [[
    ]]
    {a{a}
    }a{a}
    \{{
    \}}
    ||
    \|
    ~no no no breaks\text{no~no~no~breaks}
    \~a˜\text{\~{a}}
    \\abcd\begin{matrix}
       a & b \\
       c & d
    \end{matrix}
    ^xix^i
    \^aˆ\text{\^{a}}
    -

    A

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or CommentPackage
    \AA\text{\AA}
    \aaa˚\text{\aa}
    \aboveab+1{a \above{2pt} b+1}
    \abovewithdelimsNot supported
    \abs|x|\abs{x}physics extension
    \absolutevalue|x|\absolutevalue{x}physics extension
    \acomm{A,B}\acomm{A}{B}physics extension
    \acuteeˊ\acute e
    \AEÆ\text{\AE}
    \aeæ\text{\ae}
    \aleftexvc extension
    \alefsymtexvc extension
    \aleph
    {align}a=b+cd+e=f\begin{align}
       a&=b+c \\
       d+e&=f
    \end{align}
    ams
    {align*}a=b+cd+e=f\begin{align*}
       a&=b+c \\
       d+e&=f
    \end{align*}
    ams
    {aligned}a=b+cd+e=f\begin{aligned}
       a&=b+c \\
       d+e&=f
    \end{aligned}
    ams
    {alignat}10x+3y=23x+13y=4\begin{alignat}{2}
       10&x+ &3&y = 2 \\
       3&x+&13&y = 4
    \end{alignat}
    ams
    {alignat*}10x+3y=23x+13y=4\begin{alignat*}{2}
       10&x+ &3&y = 2 \\
       3&x+&13&y = 4
    \end{alignat*}
    ams
    {alignedat}10x+3y=23x+13y=4\begin{alignedat}{2}
       10&x+ &3&y = 2 \\
       3&x+&13&y = 4
    \end{alignedat}
    ams
    \allowbreak
    \AlphaΑ
    \alphaα
    \amalg⨿
    \And&
    \andNot supportedDeprecatedtexvc
    \angNot supportedDeprecatedtexvc
    \anglana_{\angl n}actuarialangle
    \anglnana_\anglnactuarialangle
    \angle
    \anticommutator{A,B}\anticommutator{A}{B}physics extension
    \approx
    \approxeq
    \arccosarccos
    \arcctgarcctg
    \arceqstix
    \arcsinarcsin
    \arctanarctan
    \arctgarctg
    \argarg
    \argmaxargmaxstatmath
    \argminargminstatmath
    {array}abcd\begin{array}{cc}
       a & b \\
       c & d
    \end{array}
    LaTeX2ε
    \arrayNot supportedSee {array}
    \arraystretchabcd\def\arraystretch{1.5}
    \begin{array}{cc}
       a & b \\
       c & d
    \end{array}
    \ArrowvertNot supportedsee \Vert
    \arrowvertNot supportedsee \vert
    \ast
    \asymp
    \atopab{a \atop b}
    \atopwithdelimsNot supported
    -

    B

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or CommentPackage
    \backcongMnSymbol
    \backepsilonams
    \backprimeams
    \backsimams
    \backsimeqams
    \backslash\
    \bary\bar{y}
    \barwedgeams
    \ballotxarev
    \Bbb𝔸𝔹\Bbb{ABC}
    \Bbbk𝕜
    \bboxNot supported
    \bcancel5\bcancel{5}cancel
    \becauseams
    \beginabcd\begin{matrix}
       a & b \\
       c & d
    \end{matrix}
    ams
    \begingroupa\begingroup a\endgroup
    \BetaΒ
    \betaβ
    \bethams
    \betweenams
    \bf𝐀𝐚𝐁𝐛𝟏𝟐{\bf AaBb12}
    \bfseriesNot supported
    \big()\big(\big)
    \Big()\Big(\Big)
    \bigcap
    \bigcirc
    \bigcup
    \bigg()\bigg(\bigg)
    \Bigg()\Bigg(\Bigg)
    \biggl(\biggl(
    \Biggl(\Biggl(
    \biggm|\biggm\vert
    \Biggm|\Biggm\vert
    \biggr)\biggr)
    \Biggr)\Biggr)
    \bigl(\bigl(
    \Bigl(\Bigl(
    \bigm|\bigm\vert
    \Bigm|\Bigm\vert
    \bigodot
    \bigominusNot supported
    \bigoplus
    \bigoslashNot supported
    \bigotimes
    \bigr)\bigr)
    \Bigr)\Bigr)
    \bigsqcap
    \bigsqcup
    \bigstarams
    \bigtriangledown
    \bigtriangleup
    \biguplus
    \bigvee
    \bigwedge
    \binom(nk)\binom n kams
    \blacklozengeams
    \blacksquareams
    \blacktriangleams
    \blacktriangledownams
    \blacktriangleleftams
    \blacktrianglerightams
    \bm𝑨𝒂𝑩𝒃\bm{AaBb}bm
    {Bmatrix}{abcd}\begin{Bmatrix}
       a & b \\
       c & d
    \end{Bmatrix}
    ams
    {Bmatrix*}{1324}\begin{Bmatrix*}[r]
       -1 & 3 \\
       2 & -4
    \end{Bmatrix*}
    mathtools
    {bmatrix}[abcd]\begin{bmatrix}
       a & b \\
       c & d
    \end{bmatrix}
    ams
    {bmatrix*}[1324]\begin{bmatrix*}[r]
       -1 & 3 \\
       2 & -4
    \end{bmatrix*}
    mathtools
    \bmodamodba \bmod b
    \bold𝐀𝐚𝐁𝐛𝟏𝟐𝟑\bold{AaBb123}
    \boldsymbol𝑨𝒂𝑩𝒃\boldsymbol{AaBb}ams
    \bot
    \Botcmll
    \bowtie
    \Boxams
    \boxdotams
    \boxedab\boxed{ab}ams
    \boxminusams
    \boxplusams
    \boxtimesams
    \Bqty{5mm}\Bqty{5 \text{mm}}physics extension
    \bqty[5mm]\bqty{5 \text{mm}}physics extension
    \Braψ|\Bra{\psi}braket
    \braψ|\bra{\psi}braket
    \braketϕ|ψ\braket{\phi\|\psi}braket
    \Braketϕ|2t2|ψ\Braket{ϕ\|\frac{∂^2}{∂ t^2}\|ψ}braket
    \brace{nk}{n\brace k}
    \bracevertNot supported
    \brack[nk]{n\brack k}
    \breveeu˘\breve{eu}
    \buildrelNot supported
    \bulltexvc extension
    \bullet
    \Bumpeqams
    \bumpeqams
    -

    C

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or CommentPackage
    \CNot supportedDeprecatedtexvc
    \cc¸\text{\c{c}}
    \cal𝒜𝒶𝒷{\cal AaBb}
    \cancel5\cancel{5}cancel
    \canceltox+10\cancelto{0}{x+1}cancel
    \Capams
    \cap
    {cases}{aif bcif d\begin{cases}
       a &\text{if } b \\
       c &\text{if } d
    \end{cases}
    ams
    \casesNot supportedsee {cases}
    {CD}AaBbcC=D\begin{CD}
       A @>a>> B \\
    @VbVV @AAcA \\
       C @= D
    \end{CD}
    ams
    \cdot
    \cdotp·
    \cdots
    \ce CX6HX5CHO\ce{C6H5-CHO}mhchem extension
    \ceeNot supportedDeprecated
    Use \ce instead.
    mhchem
    \centerdotams
    \cfNot supportedDeprecated
    Use \ce instead.
    mhchem
    \cfrac21+21\cfrac{2}{1+\cfrac{2}{1}}ams
    \checkoeˇ\check{oe}
    \chch
    \checkmarkams
    \ChiΧ
    \chiχ
    \choose(n+1k+2){n+1 \choose k+2}
    \circ
    \circeqams
    \circlearrowleftams
    \circlearrowrightams
    \circledastams
    \circledcircams
    \circleddashams
    \circledR®ams
    \circledSams
    \classNot supported
    \clineNot supported
    \clubstexvc extension
    \clubsuit
    \cnumstexvc extension
    \cohcmll
    \colon:
    \Colonapprox∷≈mathtools
    \colonapprox:mathtools
    \coloncoloncolonequals
    \coloncolonapprox∷≈colonequals
    \coloncolonequalscolonequals
    \coloncolonminus∷−colonequals
    \coloncolonsim:colonequals
    \colonminus:colonequals
    \Coloneq∷−mathtools
    \coloneq:mathtools
    \Coloneqqmathtools
    \coloneqqmathtools
    \Colonsim:mathtools
    \colonsim:mathtools
    \colorAaBb123\color{#0000FF} AaBb123color
    \colorboxBlack on red\colorbox{red}{Black on red}color
    \comm[A,B]\comm{A}{B}physics extension
    \commutator[A,B]\commutator{A}{B}physics extension
    \complementams
    \Complextexvc extension
    \cong
    \CoppaϘ
    \coppaϙ
    \coprod
    \copyright©
    \coscos
    \coseccosec
    \coshcosh
    \cotcot
    \cotgcotg
    \cothcoth
    \cp×physics extension
    \crabcd\begin{matrix}
       a & b \cr
       c & d
    \end{matrix}
    \cross×physics extension
    \crossproduct×physics extension
    \csccsc
    \cssIdNot supportedSee \id.
    \ctgctg
    \cthcth
    \Cupams
    \cup
    \curl𝛁×physics extension
    \curlyeqprecams
    \curlyeqsuccams
    \curlyveeams
    \curlywedgeams
    \curvearrowleftams
    \curvearrowrightams
    -

    D

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \dag
    \Daggertexvc extension
    \dagger
    \dalethams
    \Darrtexvc extension
    \dArrtexvc extension
    \darrtexvc extension
    {darray}abcd\begin{darray}{cc}
       a & b \\
       c & d
    \end{darray}
    \dashleftarrowams
    \dashrightarrowams
    \dashv
    \dbinom(nk)\dbinom n kams
    \dblcolonmathtools
    {dcases}{aif bcif d\begin{dcases}
       a &\text{if } b \\
       c &\text{if } d
    \end{dcases}
    mathtools
    \ddd\ddphysics extension
    \ddag
    \ddagger
    \ddddotx\ddddot xams
    \dddotx\dddot xams
    \ddotx¨\ddot x
    \ddots
    \DeclareMathOperatorNot supported
    \defx2+x2\def\foo{x^2} \foo + \foo
    \definecolorF=ma\definecolor{sortaGreen}{RGB}{128,128,0}
    \color{sortaGreen} F=ma
    xcolor
    \degdeg
    \degree°
    \deltaδ
    \DeltaΔ
    \derivativedxdy\derivative{x}{y}physics extension
    \detdet
    \dfraca1b1\dfrac{a-1}{b-1}ams
    \differentiald\differentialphysics extension
    \diagdownams
    \diagonalmatrixNot supportedphysics
    \diagupams
    \Diamond
    \diamond
    \diamondstexvc extension
    \diamondsuit
    \DigammaNot supported
    \digammaϝams
    \dimdim
    \displaylinesNot supported
    \displaystyle0n\displaystyle\sum_0^n
    \div÷
    \divergence𝛁\divergencephysics extension
    \divideontimesams
    \dotx˙\dot x
    \Doteqams
    \doteq
    \doteqdotams
    \dotplusams
    \dotproduct\dotproductphysics extension
    \dotsx1++xnx_1 + \dots + x_n
    \dotsbx1++xnx_1 +\dotsb + x_nams
    \dotscx,,yx,\dotsc,yams
    \dotsiA1A2\int_{A_1}\int_{A_2}\dotsiams
    \dotsmx1x2xn$x_1 x_2 \dotsm x_nams
    \dotsoams
    \doublebarwedgeams
    \doublecapams
    \doublecupams
    \Downarrow
    \downarrow
    \downdownarrowsams
    \downharpoonleftams
    \downharpoonrightams
    {drcases}aif bcif d}\begin{drcases}
       a &\text{if } b \\
       c &\text{if } d
    \end{drcases}
    mathtools
    \dvdxdy\dv{x}{y}physics extension
    \dyad|ab|\dyad{a}{b}physics extension
    -

    E

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \edefa\def\foo{a}\edef\bar{\foo}\def\foo{}\bar
    \ell
    \elseNot supported
    \emNot supported
    \emphNot supported
    \emptytexvc extension
    \emptyset
    \encloseNot supportedNon standard.
    See \boxed, \cancel, \bcancel,
    \xcancel, \sout, \longdiv, \angl
    \endabcd\begin{matrix}
       a & b \\
       c & d
    \end{matrix}
    \endgroupa\begingroup a\endgroup
    \enspaceaba\enspace b
    \EpsilonΕ
    \epsilonϵ
    \eqalignNot supportedSee {align*}
    \eqalignnoNot supportedSee {align}
    \eqcircams
    \Eqcolon−∷mathtools
    \eqcolonmathtools
    \equalscoloncolonequals
    \equalscoloncolon=∷colonequals
    {equation}a=b+c\begin{equation}
       a = b + c
    \end{equation}
    ams
    {equation*}a=b+c\begin{equation*}
       a = b + c
    \end{equation*}
    ams
    {eqnarray}Not supported
    \Eqqcolon=∷mathtools
    \eqqcolonmathtools
    \eqdefstix
    \eqref\eqref{tag1}
    Some sites do not support \eqref.
    ams
    \eqsimams
    \eqslantgtrams
    \eqslantlessams
    \equiv
    \erferf(x)\erf(x)physics extension
    \EtaΗ
    \etaη
    \ethðams
    \euro
    \evx\ev{x}physics extension
    \eval12x|0n\eval{\tfrac 1 2 x}_0^nphysics extension
    \evaluated12x|0n\evaluated{\tfrac 1 2 x}_0^nphysics extension
    \existtexvc extension
    \exists
    \expexp
    \expandafter
    \expectationvaluex\expectationvalue{x}physics extension
    \expvalx\expval{x}physics extension
    -

    F

    - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \fallingdotseq ams
    \fbox Hi there!\fbox{Hi there!}
    \fcolorbox A\fcolorbox{red}{aqua}{A}xcolor
    \fdv δxδy\fdv{x}{y}physics extension
    \female stix
    \fi Not supported
    \Finv ams
    \flat
    \footnotesize footnotesize\footnotesize footnotesize
    \forall
    \frac ab\frac a bams
    \frak 𝔄𝔞𝔅𝔟\frak{AaBb}
    \frown
    \functionalderivative δxδy\functionalderivative{x}{y}physics extension
    \futurelet
    -

    G

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \Game ams
    \Gamma Γ
    \gamma γ
    {gather} a=be=b+c\begin{gather}
       a=b \\
       e=b+c
    \end{gather}
    ams
    {gather*} a=be=b+c\begin{gather*}
       a=b \\
       e=b+c
    \end{gather*}
    ams
    {gathered} a=be=b+c\begin{gathered}
       a=b \\
       e=b+c
    \end{gathered}
    ams
    \gcd gcd
    \gdef Not supported
    \ge
    \geneuro Not supported See \euro
    \geneuronarrow Not supported See \euro
    \geneurowide Not supported See \euro
    \genfrac (aa+1]\genfrac ( ] {2pt}{0}a{a+1}ams
    \geq
    \geqq ams
    \geqslant ams
    \gets
    \gg
    \ggg ams
    \gggtr ams
    \gimel ams
    \global Not supported
    \gnapprox ams
    \gneq ams
    \gneqq ams
    \gnsim ams
    \grad 𝛁physics extension
    \gradient 𝛁physics extension
    \grave eu`\grave{eu}
    \gt a>ba \gt bMathJax
    \gtrapprox ams
    \gtrdot ams
    \gtreqless ams
    \gtreqqless ams
    \gtrless ams
    \gtrsim ams
    \gvertneqq ≩︀ams
    -

    H

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \H a˝\text{\H{a}}
    \Harr texvc extension
    \hArr texvc extension
    \harr texvc extension
    \hat θ^\hat{\theta}
    \hbar
    \hbox x2\hbox{$x^2$}
    \hbox to Not supported
    \hdashline abcd\begin{matrix}
       a & b \\
       \hdashline
       c & d
    \end{matrix}
    arydshln
    \hearts texvc extension
    \heartsuit
    \hfil Not supported
    \hfill Not supported
    \hline abcd\begin{matrix}
       a & b \\ \hline
       c & d
    \end{matrix}
    \hom hom
    \hookleftarrow
    \hookrightarrow
    \hphantom abcda\hphantom{bc}d
    \href TEMML\href{https://temml.org/}{\Temml}
    Requires trust option
    href
    \hskip widw\hskip1em i\hskip2em d
    \hslash ams
    \hspace sks\hspace{7ex} k
    \class x\class{foo}{x}
    Must enable trust and disable strict option
    \data x\data{foo=a, bar=b}{x}
    Must enable trust and disable strict option
    \id x\id{bar}{x}
    Must enable trust and disable strict option
    \style x\style{color: red;}{x}
    Must enable trust and disable strict option
    \huge huge\huge huge
    \Huge Huge\Huge Huge
    -

    I

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \i ı\text{\i}
    \idotsint \int\idotsint\intams
    \iddots
    \if Not supported
    \iff ABA\iff B
    \ifmode Not supported
    \ifx Not supported
    \iiiint ams
    \iiint ams
    \iint ams
    \Im
    \image texvc extension
    \imageof stix
    \imath ı
    \impliedby PQP\impliedby Qams
    \implies PQP\implies Qams
    \in
    \includegraphics sphere\includegraphics[height=1em,
    totalheight=1.2em, width=1.2em,
    alt=sphere]{../sphere.jpg}
    graphicx
    \incoh cmll
    \inf inf
    \infin texvc extension
    \infty
    \injlim injlim\injlimams
    \innerproduct a|b\innerproduct{a}{b}physics extension
    \int
    \intbar
    \intBar
    \intcap
    \intclockwise
    \intcup
    \intercal ams
    \intlarhk
    \intop
    \intx
    \invamp cmll
    \Iota Ι
    \iota ι
    \isin texvc extension
    \it AaBb{\it AaBb}
    \itshape Not supported
    -

    JK

    - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \j ȷ\text{\j}
    \jmath ȷ
    \Join ams
    \Kappa Κ
    \kappa κ
    \ker ker
    \kern IRI\kern-2.5pt R
    \Ket |ψ\Ket{\psi}braket
    \ket |ψ\ket{\psi}braket
    \ketbra |ab|\ketbra{a}{b}physics extension
    \Koppa Ϟ
    \koppa ϟ
    -

    L

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \L Not supported
    \l Not supported
    \Lambda Λ
    \lambda λ
    \label \label{idName}
    Creates an HTML id.
    Characters limited to: A-Za-z0-9_-
    \land
    \lang A\lang A\rangletexvc extension
    \langle A\langle A\rangle
    \laplacian 2physics extension
    \Larr texvc extension
    \lArr texvc extension
    \larr texvc extension
    \large large\large large
    \Large Large\Large Large
    \LARGE LARGE\LARGE LARGE
    \LaTeX LATEX
    \lBrace stix
    \lbrace {
    \lbrack [
    \lceil
    \ldotp .
    \ldots
    \le
    \leadsto ams
    \left {ab\left\lbrace \dfrac ab \right.
    \leftarrow
    \Leftarrow
    \LeftArrow Not supported Non standard
    \leftarrowtail ams
    \leftharpoondown
    \leftharpoonup
    \leftleftarrows ams
    \Leftrightarrow
    \leftrightarrow
    \leftrightarrows ams
    \leftrightharpoons ams
    \leftrightsquigarrow ams
    \leftroot Not supported
    \leftthreetimes ams
    \leq
    \leqalignno Not supported
    \leqq ams
    \leqslant ams
    \lessapprox ams
    \lessdot ams
    \lesseqgtr ams
    \lesseqqgtr ams
    \lessgtr ams
    \lesssim ams
    \let
    \lfloor
    \lg lg
    \lgroup
    \lhd ams
    \lightning
    \lim lim
    \liminf liminf
    \limits limx\lim\limits_x
    \limsup limsup
    \ll
    \llap ={=}\llap{/\,}
    \llbracket stmaryrd
    \llcorner ams
    \Lleftarrow ams
    \lll ams
    \llless ams
    \lmoustache
    \ln ln
    \lnapprox ams
    \lneq ams
    \lneqq ams
    \lnot ¬
    \lnsim ams
    \log log
    \long
    \longdiv 3x2+2x+5\longdiv{3x^2 + 2x + 5}Temml
    \Longleftarrow
    \longleftarrow
    \Longleftrightarrow
    \longleftrightarrow
    \longmapsto
    \Longrightarrow
    \longrightarrow
    \looparrowleft ams
    \looparrowright ams
    \lor
    \lower MM2MM\lower5pt{M^2}M  or
    M\lower5pt\hbox{$M^2}M
    \lozenge ams
    \lparen (mathtools
    \Lrarr texvc extension
    \lrArr texvc extension
    \lrarr texvc extension
    \lrcorner ams
    \lq
    \Lsh ams
    \lt <MathJax
    \ltimes ams
    \lVert ams
    \lvert |ams
    \lvertneqq ≨︀ams
    -

    M

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \malestix
    \malteseams
    \mapsto
    \mathbb𝔸𝔹\mathbb{AB}ams
    \mathbf𝐀𝐚𝐁𝐛𝟏𝟐𝟑\mathbf{AaBb123}
    \mathbina!ba\mathbin{!}b
    \mathcal𝒜𝒶𝒷\mathcal{AaBb}
    \mathchoiceaba\mathchoice{\,}{\,\,}{\,\,\,}{\,\,\,\,}b
    \mathclap1inxi\sum_{\mathclap{1\le i\le n}} x_{i}mathtools
    \mathclosea+(b>+ca + (b\mathclose\gt + c
    \mathellipsis
    \mathfrak𝔄𝔞𝔅𝔟\mathfrak{AaBb}ams
    \mathinnerabinsidecdab\mathinner{\text{inside}}cd
    \mathitAaBb\mathit{AaBb}
    \mathllap={=}\mathllap{/\,}mathtools
    \mathnormalAaBb\mathnormal{AaBb}
    \mathopab\mathop{\star}_a^b
    \mathopena+<b)+ca + \mathopen\lt b) + c
    \mathord1,234,5671\mathord{,}234{,}567
    \mathpunctABA\mathpunct{-}B
    \mathrela#ba \mathrel{\#} b
    \mathrlap=\mathrlap{\,/}{=}mathtools
    \mathringa˚\mathring{a}ams
    \mathrmAaBb12\mathrm{AaBb12}
    \mathscr𝒜\mathscr{AB}
    \mathsf𝖠𝖺𝖡𝖻𝟣𝟤𝟥\mathsf{AaBb123}
    \mathsterling£
    \mathstrut(a\sqrt{\mathstrut a}
    \mathtipNot supportedSee \texttip
    \mathtt𝙰𝚊𝙱𝚋𝟷𝟸𝟹\mathtt{AaBb123}
    \matrixNot supportedSee {matrix}
    {matrix}abcd\begin{matrix}
       a & b \\
       c & d
    \end{matrix}
    ams
    {matrix*}1324\begin{matrix*}[r]
       -1 & 3 \\
       2 & -4
    \end{matrix*}
    mathtools
    \matrixeln|A|m\matrixel{n}{A}{m}physics extension
    \matrixelementn|A|m\matrixelement{n}{A}{m}physics extension
    \meln|A|m\mel{n}{A}{m}physics extension
    \maxmax
    \mboxNot supported
    \mdNot supported
    \mdseriesNot supported
    \measeqstix
    \measuredangleams
    \medspaceaba\medspace bams
    \mho
    \mid{x|x>0}\{x∈ℝ\mid x>0\}
    \middleP(A|B)P\left(A\middle\vert B\right)
    \minmin
    \minuscoloncolonequals
    \minuscoloncolon−∷colonequals
    \minusoNot supportedSee \standardstate
    \mitNot supportedSee \mathit
    \mkernaba\mkern18mu b
    \mmlTokenNot supported
    \mod35mod23\equiv 5 \mod 2ams
    \models
    \moveleftNot supported
    \moverightNot supported
    \mp
    \mskipaba\mskip{10mu}b
    \mspaceNot supported
    \MuΜ
    \muμ
    \multicolumnNot supported
    \multimapams
    \multimapbothcmll
    \multimapinvcmll
    {multline}unodostres\begin{multline}
      \rm uno \\
      \rm dos \\
      \rm tres
    \end{multline}
    ams
    {multline*}unodostres\begin{multline*}
      \rm uno \\
      \rm dos \\
      \rm tres
    \end{multline*}
    ams
    -

    N

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \Ntexvc extension
    \nabla
    \natnumstexvc extension
    \natural
    \negmedspaceaba\negmedspace bams
    \ncongams
    \ne
    \nearrow
    \neg¬
    \negthickspaceaba\negthickspace bams
    \negthinspaceaba\negthinspace bams
    \neq
    \newcommand\newcommand\chk{\checkmark} \chknewcommand
    \newenvironmentNot supported
    \newextarrowNot supportedextpfeil
    \newlineaba\newline b
    \nexistsams
    \ngeqams
    \ngeqqams
    \ngeqslantams
    \ngtrams
    \ni
    \nleftarrowams
    \nLeftarrowams
    \nLeftrightarrowams
    \nleftrightarrowams
    \nleqams
    \nleqqams
    \nleqslantams
    \nlessams
    \nmidams
    \nobreak
    \nobreakspacea ba\nobreakspace bams
    \noexpand
    \nolimitslimx\lim\nolimits_x
    \normx\norm{x}physics extension
    \normalfontNot supported
    \normalsizenormalsize\normalsize normalsize
    \not\not =
    \notaga=bd+e=f\begin{align}
      a&=b \\
      \notag d+e&=f
    \end{align}
    ams
    \notin
    \notnitxfonts/pxfonts
    \nparallelams
    \nprecams
    \npreceqams
    \nRightarrowams
    \nrightarrowams
    \nshortmidams
    \nshortparallelams
    \nsimams
    \nsubsetmathabx
    \nsubseteqams
    \nsubseteqqams
    \nsuccams
    \nsucceqams
    \nsupsetmathabx
    \nsupseteqams
    \nsupseteqqams
    \ntriangleleftams
    \ntrianglelefteqams
    \ntrianglerightams
    \ntrianglerighteqams
    \NuΝ
    \nuν
    \nVDashams
    \nVdashams
    \nvDashams
    \nvdashams
    \nwarrow
    -

    O

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \OØ\text{\O}
    \oø\text{\o}
    \oc!cmll
    \odot
    \odvdfdx\odv{f}{x}derivative
    \odv*ddxf\odv*{f}{x}derivative
    \OEŒ\text{\OE}
    \oeœ\text{\oe}
    \officialeuroNot supportedSee \euro
    \oiiint
    \oiint
    \oint
    \oldstyleNot supportedSee \oldstylenums
    \oldstylenums123\oldstylenums{123}LaTeX2ε
    \omegaω
    \OmegaΩ
    \OmicronΟ
    \omicronο
    \ominus
    \op|ab|\op{a}{b}physics extension
    \operatornameasinx\operatorname{asin} xams
    \operatorname*asinyx\operatorname*{asin}\limits_y xams
    \operatornamewithlimitsasinyx\operatornamewithlimits{asin}\limits_y x
    \oplus
    \orNot supported
    \order𝒪(x2)\order{x^2}physics extension
    \origofstix
    \oslash
    \otimes
    \outerproduct|ab|\outerproduct{a}{b}physics extension
    \overa+1b+2+c{a+1 \over b+2}+c
    \overbracex++xn times\overbrace{x+⋯+x}^{n\text{ times}}
    \overbracketNot supported
    \overgroupAB\overgroup{AB}MnSymbol
    \overleftarrowAB\overleftarrow{AB}ams
    \overleftharpoonAB\overleftharpoon{AB}MnSymbol
    \overleftrightarrowAB\overleftrightarrow{AB}ams
    \overlinea long argument_\overline{\text{a long argument}}
    \overlinesegmentNot supported
    \overparenabc\overparen{abc}
    \OverrightarrowAB\Overrightarrow{AB}overrightarrow
    \overrightarrowAB\overrightarrow{AB}ams
    \overrightharpoonac\overrightharpoon{ac}
    \overset=!\overset{!}{=}ams
    \overwithdelimsNot supported
    \owns
    -

    P

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \P\text{\P} or \P
    \pagecolorNot supportedDeprecatedtexvc
    \parallel
    \parrcmll
    \partNot supportedDeprecatedtexvc
    \partial
    \partialderivativexy\partialderivative{x}{y}physics extension
    \pb{x,y}\pb{x}{y}physics extension
    \pdv2fxy\pdv{f}{x,y}derivative
    \pdv*2xyf\pdv*{f}{x,y}derivative
    \permilwasysym
    \perp
    \Perpcmll
    \phantomΓijkij\Gamma^{\phantom{i}j}_{i\phantom{j}k}
    \phase78\phase{-78^\circ}steinmetz
    \PhiΦ
    \phiϕ
    \PiΠ
    \piπ
    {picture}Not supported
    \pitchforkams
    \plimplimstatmath
    \plusmn±texvc extension
    \pm±
    \pmatrixNot supportedSee {pmatrix}
    {pmatrix}(abcd)\begin{pmatrix}
       a & b \\
       c & d
    \end{pmatrix}
    ams
    {pmatrix*}(1324)\begin{pmatrix*}[r]
       -1 & 3 \\
       2 & -4
    \end{pmatrix*}
    mathtools
    \pmbμ\pmb{\mu}ams
    \pmodx(moda)x\pmod a
    \podx(a)x \pod aams
    \pointint
    \poissonbracket{A,B}\poissonbracket{A}{B}physics extension
    \pounds£
    \pqty(5)\pqty{5}physics extension
    \PrPr
    \prec
    \precapproxams
    \preccurlyeqams
    \preceqams
    \precnapproxams
    \precneqqams
    \precnsimams
    \precsimams
    \prescript𝐂25+a2\prescript{a}{2}{\mathbf{C}}^{5+}_{2}mathtools
    \prime
    \principalvalue𝒫physics extension
    \pv𝒫physics extension
    \PVP.V.(x)\PV(x)physics extension
    \prod
    \projlimprojlim\projlimams
    \propto
    \providecommandHello\providecommand\greet{\text{Hello}}
    \greet
    \psiψ
    \PsiΨ
    \pu 123 kJmol\pu{123 kJ//mol}mhchem extension
    -

    Q

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \Q Not supported See \Bbb{Q}
    \qall allphysics extension
    \qand andphysics extension
    \qas asphysics extension
    \qassume assumephysics extension
    \qc ,physics extension
    \qcc c.c.physics extension
    \qcomma ,physics extension
    \qelse elsephysics extension
    \qeven evenphysics extension
    \qfor forphysics extension
    \qgiven givenphysics extension
    \qif ifphysics extension
    \qin inphysics extension
    \qinteger integerphysics extension
    \qlet letphysics extension
    \qodd oddphysics extension
    \qor orphysics extension
    \qotherwise otherwisephysics extension
    \qq  text \qq{text}physics extension
    \qqtext  text \qqtext{text}physics extension
    \qquad aba\qquad\qquad{b}
    \qsince sincephysics extension
    \qthen thenphysics extension
    \qty {5m}\qty{5 \text{m}}physics extension
    \quad aba\quad\quad{b}
    \quantity {5m}\quantity{5 \text{m}}physics extension
    \qunless unlessphysics extension
    \qusing usingphysics extension
    \questeq stix
    -

    R

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \R texvc extension
    \r a˚\text{\r{a}}
    \raise MM2MM\raise3pt{M^2}M  or
    M\raise3pt\hbox{$M^2}M
    \raisebox higherh\raisebox{2pt}{ighe}r
    \rang A\langle A\rangtexvc extension
    \rangle A\langle A\rangle
    \rank rankM\rank Mphysics extension
    \Rarr texvc extension
    \rArr texvc extension
    \rarr texvc extension
    \ratio :colonequals
    \rBrace stix
    \rbrace }
    \rbrack ]
    {rcases} aif bcif d}\begin{rcases}
       a &\text{if } b \\
       c &\text{if } d
    \end{rcases}
    mathtools
    \rceil
    \Re
    \real texvc extension
    \Reals texvc extension
    \reals texvc extension
    \ref \ref{tag1}
    Some sites do not support \ref.
    \relax
    \renewcommand Ahoy!\def\hail{Hi!}
    \renewcommand\hail{\text{Ahoy!}}
    \hail
    newcommand
    \renewenvironment Not supportednewcommand
    \require Not supported
    \Res Res[f(z)]\Res[f(z)]physics extension
    \restriction ams
    \rfloor
    \rgroup
    \rhd ams
    \Rho Ρ
    \rho ρ
    \right ab)\left.\dfrac a b\right)
    \Rightarrow
    \rightarrow
    \rightarrowtail ams
    \rightharpoondown
    \rightharpoonup
    \rightleftarrows ams
    \rightleftharpoons ams
    \rightrightarrows ams
    \rightsquigarrow ams
    \rightthreetimes ams
    \risingdotseq ams
    \rlap =\rlap{\,/}{=}
    \rm AaBb12{\rm AaBb12}
    \rmoustache
    \root Not supported
    \rotatebox Not supported
    \rparen )mathtools
    \rppolint
    \rq
    \rrbracket stmaryrd
    \Rrightarrow ams
    \Rsh ams
    \rtimes ams
    \Rule Not supportedsee \rule
    \rule xxx\rule[6pt]{2ex}{1ex}x
    \rVert ams
    \rvert |ams
    -

    S

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \S§\text{\S} or \S
    \SampiϠ
    \sampiϡ
    \scNot supportedSee \textsc
    \scohcmll
    \scaleboxNot supported
    \scpolint
    \scrNot supportedSee \mathscr
    \scriptscriptstylecd\scriptscriptstyle \frac cd
    \scriptsizescriptsize\scriptsize scriptsize
    \scriptstyleABA{\scriptstyle B}
    \sdottexvc extension
    \searrow
    \secsec
    \sect§\text{\sect}texvc extension
    \set{x|x<5}\set{x | x<5}braket
    \Set{x|x<12}\Set{ x | x<\tfrac 1 2 }braket
    \setlengthNot supported
    \setminus
    \sf𝖠𝖺𝖡𝖻𝟣𝟤𝟥{\sf AaBb123}
    \sgnsgnmismath
    \sharp
    \shiftcmll
    \shnegcmll
    \shortmidams
    \shortparallelams
    \shoveleftNot supportedams
    \shoverightNot supportedams
    \shposcmll
    \sidesetcdab\sideset{_a^b}{_c^d}\sumams
    \SigmaΣ
    \sigmaσ
    \sim
    \simeq
    \sinsin
    \sincohcmll
    \sinhsinh
    \sixptsizesixptsize\sixptsize sixptsize
    \shsh
    \skewNot supported
    \skipNot supported
    \slNot supported
    \smallsmall\small small
    \smallfrownams
    \smallint
    {smallmatrix}abcd\begin{smallmatrix}
       a & b \\
       c & d
    \end{smallmatrix}
    \smallsetminusams
    \smallsmileams
    \smash(x2)\left(x^{\smash{2}}\right)
    \smile
    \smileywasysym
    \soutabc\sout{abc}ulem
    \SpaceNot supportedsee \space
    \spacea ba\space b
    \spadestexvc extension
    \spadesuit
    \sphericalangleams
    {split}a=b+c=e+f\begin{equation}
    \begin{split}
       a &=b+c\\
          &=e+f
    \end{split}
    \end{equation}
    ams
    \sqcap
    \sqcup
    \sqint
    \square
    \sqrtx3\sqrt[3]{x}
    \sqsubsetams
    \sqsubseteq
    \sqsupsetams
    \sqsupseteqams
    \ssß\text{\ss}
    \stackrel=!\stackrel{!}{=}
    \standardstatechemstyle
    \star
    \stareqstix
    \StigmaϚ
    \stigmaϛ
    \strictiftxfonts/pxfonts
    \strictfitxfonts/pxfonts
    \strutNot supported
    \styleNot supportedNon standard
    \subtexvc extension
    {subarray}iΛ0<j<nP(i,j)\sum_{\begin{subarray}{l}
     i\in\Lambda\\
      0<j<n
    \end{subarray}}P(i,j)
    ams
    \subetexvc extension
    \Subsetams
    \subset
    \subseteq
    \subseteqqams
    \subsetneqams
    \subsetneqqams
    \substack0<i<m0<j<n\sum_{\substack{0<i<m\\0<j<n}}ams
    \succ
    \succapproxams
    \succcurlyeqams
    \succeq
    \succnapproxams
    \succneqqams
    \succnsimams
    \succsimams
    \sum
    \supsup
    \supetexvc extension
    \Supsetams
    \supsetams
    \supseteq
    \supseteqqams
    \supsetneqams
    \supsetneqqams
    \surd
    \swarrow
    -

    T

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \tage=mc2(hi)\tag{hi} e=mc^2 \label{tag1}ams
    \tag*e=mc2hey\tag*{hey} e=mc^2ams
    \tantan
    \tanhtanh
    \TauΤ
    \tauτ
    \tbinom(nk)\tbinom n kams
    \TeXTEX
    \text yes & no \text{ yes }\&\text{ no }
    \textasciitilde~\text{\textasciitilde}
    \textasciicircum^\text{\textasciicircum}
    \textbackslash\\text{\textbackslash}
    \textbar|\text{\textbar}
    \textbardbl\text{\textbardbl}
    \textbf𝐀𝐚𝐁𝐛𝟏\textbf{AaBb123}
    \textbraceleft{\text{\textbraceleft}
    \textbraceright}\text{\textbraceright}
    \textbullet\text{\textbullet}
    \textcircledNot supported
    \textcolorF=ma\textcolor{blue}{F=ma}color
    \textdagger\text{\textdagger}
    \textdaggerdbl\text{\textdaggerdbl}
    \textdegree°\text{\textdegree}
    \textdollar$\text{\textdollar}
    \textellipsis\text{\textellipsis}
    \textemdash\text{\textemdash}
    \textendash\text{\textendash}
    \texteuro\text{\texteuro}
    \textgreater>\text{\textgreater}
    \textit𝐴𝑎𝐵𝑏\textit{AaBb}
    \textless<\text{\textless}
    \textmdAaBb123\textmd{AaBb123}
    \textnormalAB\textnormal{AB}
    \textquotedblleft\text{\textquotedblleft}
    \textquotedblright\text{\textquotedblright}
    \textquoteleft\text{\textquoteleft}
    \textquoteright\text{\textquoteright}
    \textregistered®\text{\textregistered}
    \textrmAaBb123\textrm{AaBb123}
    \textscʜᴇʏ\textsc{hey}
    \textsf𝖠𝖺𝖡𝖻𝟣\textsf{AaBb123}
    \textslNot supported
    \textsterling£\text{\textsterling}
    \textstyle0n\textstyle\sum_0^n
    \texttiphover here\texttip{\text{hover here}}
    {This is a tooltip.}
    MathJax
    \texttt𝙰𝚊𝙱𝚋𝟷\texttt{AaBb123}
    \textunderscore_\text{\textunderscore}
    \textupAaBb123\textup{AaBb123}
    \textvisiblespace\text{\textvisiblespace}
    \tfracab\tfrac abams
    \tgtg
    \thth
    \thereforeams
    \ThetaΘ
    \thetaθ
    \thetasymϑtexvc extension
    \thickapproxams
    \thicksimams
    \thickspaceaba\thickspace bams
    \thinspaceaba\thinspace bams
    \tildeM~\tilde M
    \times×
    \TinyTiny\Tiny Tiny
    \tinytiny\tiny tiny
    \to
    \toggleClick meHey!Ow!\toggle{\text{Click me}}
    {Hey!}{Ow!}\endtoggle
    MathJax
    \top
    \TrTrρ\Tr\rhophysics extension
    \trtrρ\tr\rhophysics extension
    \triangle
    \triangledownams
    \triangleleft
    \trianglelefteqams
    \triangleqams
    \triangleright
    \trianglerighteqams
    \tt𝙰𝚊𝙱𝚋𝟷𝟸𝟹{\tt AaBb123}
    \twoheadleftarrowams
    \twoheadrightarrowams
    -

    U

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \u a˘\text{\u{a}}
    \Uarr texvc extension
    \uArr texvc extension
    \uarr texvc extension
    \ulcorner ams
    \underbar X_\underbar{X}
    \underbrace x++xn times\underbrace{x+⋯+x}_{n\text{ times}}
    \underbracket Not supported
    \undergroup AB\undergroup{AB}MnSymbol
    \underleftarrow AB\underleftarrow{AB}ams
    \underleftrightarrow AB\underleftrightarrow{AB}ams
    \underrightarrow AB\underrightarrow{AB}ams
    \underline a long argument_\underline{\text{a long argument}}
    \underlinesegment Not supported
    \underparen abc\underparen{abc}
    \underrightarrow AB\underrightarrow{AB}
    \underset =!\underset{!}{=}AMS
    \unicode Not supported See \char
    \unlhd ams
    \unrhd ams
    \up Not supported
    \upalpha αupgreek
    \Uparrow
    \uparrow
    \upbeta βupgreek
    \updelta δupgreek
    \upchi χupgreek
    \Updownarrow
    \updownarrow
    \upeta ηupgreek
    \upepsilon ϵupgreek
    \upgamma γupgreek
    \upharpoonleft ams
    \upharpoonright ams
    \upiota ιupgreek
    \upkappa κupgreek
    \uplambda λupgreek
    \upmu μupgreek
    \upnu νupgreek
    \upomega ωupgreek
    \upomicron οupgreek
    \uplus upgreek
    \upphi ϕupgreek
    \uppi πupgreek
    \uppsi ψupgreek
    \uprho ρupgreek
    \uproot Not supported
    \upshape Not supported
    \upsigma σupgreek
    \Upsilon Υ
    \upsilon υ
    \uptau τupgreek
    \uptheta θupgreek
    \upuparrows ams
    \upupsilon υupgreek
    \upxi ξupgreek
    \upzeta ζupgreek
    \urcorner ams
    \url 𝚑𝚝𝚝𝚙𝚜://𝚝𝚎𝚖𝚖𝚕.𝚘𝚛𝚐/\url{https://temml.org/}
    Requires trust option
    \utilde AB~\utilde{AB}undertilde
    -

    V

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \vaˇ\text{\v{a}}
    \va𝒂\va{a}physics extension
    \varδphysics extension
    \varcoppaϙ
    \varclubsuittxfonts
    \varDelta𝛥ams
    \vardiamondsuittxfonts
    \varepsilonε
    \varGamma𝛤ams
    \varheartsuittxfonts
    \variationδphysics extension
    \varinjlimlim\varinjlimams
    \varkappaϰams
    \varLambda𝛬ams
    \varliminflim_\varliminfams
    \varlimsuplim_\varlimsupams
    \varnothingøams
    \varointclockwise
    \varOmega𝛺ams
    \varPhi𝛷ams
    \varphiφ
    \varPi𝛱ams
    \varpiϖ
    \varprojlimlim\varprojlimams
    \varproptoams
    \varPsi𝛹ams
    \varrhoϱ
    \varSigma𝛴ams
    \varsigmaς
    \varspadesuittxfonts
    \varstigmaNot supported
    \varsubsetneq⊊︀ams
    \varsubsetneqq⫋︀ams
    \varsupsetneqams
    \varsupsetneqq⫌︀ams
    \varTheta𝛩ams
    \varthetaϑ
    \vartriangleams
    \vartriangleleftams
    \vartrianglerightams
    \varUpsilon𝛶ams
    \varXi𝛯ams
    \vb𝒂\vb{a}physics extension
    \vcentcolon:
    \vcenterNot supported
    \Vdashams
    \vDashams
    \vdash
    \vdotphysics extension
    \vdots
    \vecF\vec{F}
    \vectorarrow𝒂\vectorarrow{a}physics extension
    \vectorbold𝒂\vectorbold{a}physics extension
    \vectorunit𝒂^\vectorunit{a}physics extension
    \vee
    \veebarams
    \veeeqstix
    \verb\frac a b\verb!\frac a b!
    \Vert
    \vert|
    \vfilNot supported
    \vfillNot supported
    \vlineNot supported
    {Vmatrix}abcd\begin{Vmatrix}
       a & b \\
       c & d
    \end{Vmatrix}
    ams
    {Vmatrix*}1324\begin{Vmatrix*}[r]
       -1 & 3 \\
       2 & -4
    \end{Vmatrix*}
    mathtools
    {vmatrix}|abcd|\begin{vmatrix}
       a & b \\
       c & d
    \end{vmatrix}
    ams
    {vmatrix*}|1324|\begin{vmatrix*}[r]
       -1 & 3 \\
       2 & -4
    \end{vmatrix*}
    mathtools
    \vphantomMa_\overline{\vphantom{M}a}
    \vqty|x|\vqty{x}physics extension
    \vu𝒂^\vu{a}physics extension
    \Vvdashams
    -

    W

    - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \wedge
    \wedgeq stix
    \weierp texvc extension
    \widecheck ABˇ\widecheck{AB}mathabx
    \widehat AB^\widehat{AB}
    \wideparen abc\wideparen{abc}MnSymbol
    \widetilde AB~\widetilde{AB}
    \with &cmll
    \wn ?cmll
    \wp
    \wr
    -

    X

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Function Rendered Source or Comment Package
    \xcancel ABC\xcancel{ABC}cancel
    \xdef Not supported
    \Xi Ξ
    \xi ξ
    \xhookleftarrow abc\xhookleftarrow{abc}mathtools
    \xhookrightarrow abc\xhookrightarrow{abc}mathtools
    \xLeftarrow abc\xLeftarrow{abc}mathtools
    \xleftarrow abc\xleftarrow{abc}ams
    \xleftharpoondown abc\xleftharpoondown{abc}mathtools
    \xleftharpoonup abc\xleftharpoonup{abc}mathtools
    \xLeftrightarrow abc\xLeftrightarrow{abc}mathtools
    \xleftrightarrow abc\xleftrightarrow{abc}mathtools
    \xleftrightharpoons abcabc\xleftrightharpoons{abc}mathtools
    \xlongequal =abc\xlongequal{abc}extpfeil
    \xmapsto abc\xmapsto{abc}mathtools
    \xRightarrow abc\xRightarrow{abc}mathtools
    \xrightarrow abc\xrightarrow{abc}ams
    \xrightharpoondown abc\xrightharpoondown{abc}mathtools
    \xrightharpoonup abc\xrightharpoonup{abc}mathtools
    \xrightleftharpoons abcabc\xrightleftharpoons{abc}mathtools
    \xtofrom abcabc\xtofrom{abc}extpfeil
    \xtwoheadleftarrow abc\xtwoheadleftarrow{abc}extpfeil
    \xtwoheadrightarrow abc\xtwoheadrightarrow{abc}extpfeil
    -

    YZ

    - - - - - - - - - -
    Function Rendered Source or Comment Package
    \yen ¥ams
    \Z texvc extension
    \Zeta Ζ
    \zeta ζ
    -
    -

    Copyright © 2021, 2022 Ron Kok. Released under the MIT License

    -
    -
    - -
    - - - - -
    - - - diff --git a/site/docs/en/supported.html b/site/docs/en/supported.html deleted file mode 100644 index a5b3dafe..00000000 --- a/site/docs/en/supported.html +++ /dev/null @@ -1,751 +0,0 @@ - - - - - - Temml Functions - - - - - - -
    -

    Supported Functions

    -

    Temml is a JavaScript library that converts TeX math-mode functions to MathML. This page lists the TeX functions it supports, sorted into logical groups.

    -

    To read this page, use a browser that supports MathML, such as Firefox or Safari. Chrome and Edge will support MathML soon.

    -

    There is a similar Support Table, sorted alphabetically, that lists both supported and some un-supported functions.

    -

    Accents

    - - - - - - - - - - - - - -
    a a'a~ \tilde{a}ac~ \widetilde{ac}
    a a''F \vec{F}AB~ \utilde{AB}
    a a^{\prime}AB \overleftarrow{AB}AB \overrightarrow{AB}
    aˊ \acute{a} AB \underleftarrow{AB}AB \underrightarrow{AB}
    y \bar{y} AB_ \overline{AB}AB \Overrightarrow{AB}
    a˘ \breve{a} AB_ \underline{AB}AB \overleftrightarrow{AB}
    aˇ \check{a} acˇ \widecheck{ac}AB \underleftrightarrow{AB}
    a˙ \dot{a} ac \overleftharpoon{ac}ac \overrightharpoon{ac}
    a¨ \ddot{a} AB \overgroup{AB}AB \wideparen{AB}
    a \dddot{a} AB \undergroup{AB}AB \overparen{AB}
    a \ddddot{a}X_ \underbar{X}AB \underparen{AB}
    a` \grave{a} g˚ \mathring{g}AB \overbrace{AB}
    θ^ \hat{\theta}ac^ \widehat{ac}AB \underbrace{AB}
    -

    Accent functions inside \text{…}

    - - - -
    aˊ \'{a}a˜ \~{a}a˙ \.{a}a˝ \H{a}
    aˋ \`{a}aˉ \={a}a¨ \"{a}aˇ \v{a}
    aˆ \^{a}a˘ \u{a}a˚ \r{a}c¸ \c{c}
    -

    See also letters

    -

    Annotation

    - - - - - - - - -
    5 \cancel{5} a+b+cnote \overbrace{a+b+c}^{\text{note}}
    5 \bcancel{5} a+b+cnote \underbrace{a+b+c}_{\text{note}}
    ABC \xcancel{ABC} x+10 \cancelto{0}{x+1}
    abc \sout{abc} π=cd \boxed{\pi=\frac c d}
    \ref{tag1} hover here \texttip{\text{hover here}}{This is a tooltip.}`
    Click meHey!Ow! \toggle{\text{Click me}}{Hey!}{Ow!}\endtoggle
    x+y2x(hi)\tag{hi} x+y^{2x} \label{tag1}
    x+y2xbye\tag*{bye} x+y^{2x}
    -

    Also some environments have automatic equation numbering.

    -

    A \label{…} may be placed anywhere and will create an HTML id matching the \label{…} argument. That argument may contain only the characters A-Za-z0-9_-.

    -

    On sites where Temml fields are updated dynamically, \ref{…} may not be supported. Other Temml functions update only the local field. \ref{…} must make two passes through the entire document. Some sites may choose not to do this.

    -

    Color

    - - - - - -
    F=ma {\color{blue} F=ma}F=ma {\color[RGB]{255,0,255} F=ma}
    F=ma \textcolor{blue}{F=ma}F=ma {\color[rgb]{1,0,1} F=ma}
    F=ma \textcolor{#228B22}{F=ma}F=ma {\color[HTML]{ff00ff} F=ma}
    A \colorbox{aqua}{A}\definecolor{sortaGreen}{RGB}{128,128,0}
    F=ma {\color{sortaGreen} F=ma}
    A \fcolorbox{red}{aqua}{A}
    -

    \definecolor functions can be included in a preamble. If so, their color definitions will have document-wide scope.

    -

    Color functions can all take an optional argument to set the color model, as in the xcolor package. (Exception: \definecolor’s model argument is required.) Temml supports color models HTML, RGB, and rgb.

    -

    If the color model is omitted, Temml color functions will accept:

    -
    • #rrggbb, #rgb, or rrggbb.
    • -
    • A color name previously created by \definecolor.
    • -
    • Any color from the following xcolor table.
    • -
    • Any of the standard HTML predefined color names.
    • -
    -
    - - - - - - - - - - - - - - - - - - - - - -
      Apricot  ForestGreen  olive  RoyalPurple
      Aquamarine  Fuchsia  OliveGreen  RubineRed
      Bittersweet  Goldenrod  orange  Salmon
      blue  gray  Orange  SeaGreen
      Blue  Gray  OrangeRed  Sepia
      BlueGreen  green  Orchid  SkyBlue
      BlueViolet  Green  Peach  SpringGreen
      BrickRed  GreenYellow  Periwinkle  Tan
      brown  JungleGreen  PineGreen  teal
      Brown  Lavender  pink  TealBlue
      BurntOrange  lightgray  Plum  Thistle
      CadetBlue  lime  ProcessBlue  Turquoise
      CarnationPink  LimeGreen  purple  violet
      Cerulean  magenta  Purple  Violet
      CornflowerBlue  Magenta  RawSienna  VioletRed
      cyan  Mahogany  red  WildStrawberry
      Cyan  Maroon  Red  yellow
      Dandelion  Melon  RedOrange  Yellow
      darkgray  MidnightBlue  RedViolet  YellowGreen
      DarkOrchid  Mulberry  Rhodamine  YellowOrange
      Emerald  NavyBlue  RoyalBlue
    -

    Delimiters

    - - - - - - - - -
    ( ) ( ) ( ) \lparen
         \rparen
      ⌈ ⌉   \lceil
          \rceil
    \uparrow
    [ ] [ ] [ ] \lbrack
         \rbrack
      ⌊ ⌋   \lfloor
          \rfloor
    \downarrow
    {} \{ \} {} \lbrace
         \rbrace
    ⎰⎱ \lmoustache
         \rmoustache
    \updownarrow
      ⟨ ⟩   \langle
          \rangle
      ⟮ ⟯   \lgroup
          \rgroup
    \Uparrow
    | | | \vert ┌ ┐ \ulcorner
         \urcorner
    \Downarrow
    \| \Vert └ ┘ \llcorner
         \lrcorner
    \Updownarrow
    | | \lvert
         \rvert
      \lVert
          \rVert
    \left. \right. \ \backslash
    <> \lt
               \gt
      ⟦ ⟧   \llbracket
         \rrbracket
      \lBrace \rBrace
    -

    The texvc extension includes \lang and \rang.

    -

    Delimiter Sizing

    -

    (AB) \left(\LARGE{AB}\right)

    -

    ((((( ( \big( \Big( \bigg( \Bigg(

    - - - - -
    \left\big\bigl\bigm\bigr
    \middle\Big\Bigl\Bigm\Bigr
    \right\bigg\biggl\biggm\biggr
    \Bigg\Biggl\Biggm\Biggr
    -

    Environments

    - - - - - - -
    abcd\begin{matrix}
       a & b \\
       c & d
    \end{matrix}
       ab   cd\begin{array}{cc}
       a & b \\
       c & d
    \end{array}
    (abcd)\begin{pmatrix}
       a & b \\
       c & d
    \end{pmatrix}
    [abcd]\begin{bmatrix}
       a & b \\
       c & d
    \end{matrix}
    |abcd|\begin{vmatrix}
       a & b \\
       c & d
    \end{vmatrix}
    abcd\begin{Vmatrix}
       a & b \\
       c & d
    \end{Vmatrix}
    {abcd} \begin{Bmatrix}
       a & b \\
       c & d
    \end{Bmatrix}
    abcdefghi \def\arraystretch{1.5}
    \begin{array}{c|c:c}
       a & b & c \\ \hline
       d & e & f \\
       \hdashline
       g & h & i
    \end{array}
    x={aif bcif dx = \begin{cases}
       a &\text{if } b \\
       c &\text{if } d
    \end{cases}
    aif bcif d}\begin{rcases}
       a &\text{if } b \\
      c &\text{if } d
    \end{rcases}⇒
    abcd \begin{smallmatrix}
       a & b \\
       c & d
    \end{smallmatrix}
    iΛ0<j<n\sum_{\begin{subarray}{l}
       i\in\Lambda\\
       0<j<n
    \end{subarray}}
    -

    The auto-render extension will render the following environments even if they are not inside math delimiters such as $$…$$. They are display-mode only.

    -
    - - - -
    a=b+c=e+f\begin{equation}
    \begin{split}
       a &=b+c\\
       &=e+f
    \end{split}
    \end{equation}
    a=b+cd+e=f \begin{align}
       a&=b+c \\
       d+e&=f
    \endalign
    a=be=b+c\begin{gather}
       a=b \\
       e=b+c
    \end{gather}
    10x+3y=23x+13y=4\begin{alignat}{2}
       10&x+ &3&y = 2 \\
       3&x+&13&y = 4
    \end{alignat}
    AaBbcC=D\begin{CD}
    A @>a>> B \\
    @VbVV @AAcA \\
    C @= D
    \end{CD}
    unodostres\begin{multline}
       \rm uno \\
       \rm dos \\
       \rm tres
    \end{multline}
    -

    Other Temml Environments

    - - - - - - - -
    EnvironmentsHow they differ from those shown above
    darray, dcases, drcases… apply displaystyle
    matrix*, pmatrix*, bmatrix*
    Bmatrix*, vmatrix*, Vmatrix*
    … take an optional argument that sets column
    alignment, as in \begin{matrix*}[r]
    equation*, gather*
    align*, alignat*
    … have no automatic numbering.
    gathered, aligned, alignedat … do not need to be in display mode.
    … have no automatic numbering.
    … must be inside math delimiters in
    order to be rendered by the auto-render
    extension.
    -

    Acceptable horizontal line separators are: \\ and \cr.

    -

    Temml supports \tag{…}, \notag, and \nonumber to modify equation numbering.

    -

    The {array} environment does not yet support \cline or \multicolumn.

    -

    HTML

    -

    The following "raw HTML" features are potentially dangerous for untrusted inputs, so they are disabled by default, and attempting to use them produces the command names in red (which you can configure via the errorColor option). To fully trust your LaTeX input, you need to pass an option of trust: true; you can also enable just some of the commands or for just some URLs via the trust option.

    - - - - - - - -
    TEMML\href{https://temml.org/}{\Temml}
    𝚑𝚝𝚝𝚙𝚜://𝚝𝚎𝚖𝚖𝚕.𝚘𝚛𝚐/\url{https://temml.org/}
    sphere\includegraphics[height=1em,
    totalheight=1.2em,width=1.2em, alt=sphere]
    {../sphere.jpg}
    x\id{idName}{x}
    x\class{class-name}{x}
    x\style{color: red;}{x}
    x\data{datum1=a, datum2=b}{x}
    -

    Letters

    -

    Greek Letters

    - - - - - - - - - - - - - - - - - - - - - -
    Α \AlphaΒ \BetaΓ \GammaΔ \DeltaΕ \Epsilon
    Ζ \ZetaΗ \EtaΘ \ThetaΙ \IotaΚ \Kappa
    Λ \LambdaΜ \Mu Ν \Nu Ξ \Xi Ο \Omicron
    Π \PiΡ \RhoΣ \SigmaΤ \TauΥ \Upsilon
    Φ \PhiΧ \ChiΨ \PsiΩ \Omega𝛤 \varGamma
    𝛥 \varDelta𝛩 \varTheta𝛬 \varLambda𝛯 \varXi 𝛱 \varPi
    𝛴 \varSigma𝛶 \varUpsilon𝛷 \varPhi𝛹 \varPsi𝛺 \varOmega
    α \alphaβ \betaγ \gammaδ \deltaϵ \epsilon
    ζ \zetaη \etaθ \thetaι \iotaκ \kappa
    λ \lambda`μ \mu ν \nu ξ \xi ο \omicron
    π \piρ \rhoσ \sigmaτ \tauυ \upsilon
    ϕ \phiχ \chiψ \psiω \omega
    α \upalphaβ \upbetaγ \upgammaδ \updeltaϵ \upepsilon
    ζ \upzetaη \upetaθ \upthetaι \upiotaκ \upkappa
    λ \uplambdaμ \upmu ν \upnu ξ \upxi ο \upomicron
    π \uppi ρ \uprhoσ \upsigmaτ \uptau υ \upupsilon
    ϕ \upphi χ \upchiψ \uppsi ω \upomega
    ε \varepsilonϰ \varkappaϑ \varthetaϖ \varpi ϱ \varrho
    ς \varsigmaφ \varphiϘ \Coppa ϙ \coppa Ϟ \Koppa
    ϟ \koppa Ϡ \Sampiϡ \sampi Ϛ \Stigmaϛ \stigma
    ϝ \digammaϙ \varcoppa
    -

    Direct Input: Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ Φ Χ Ψ Ω - α β γ δ ϵ ζ η θ ι κ λ μ ν ξ o π ρ σ τ υ ϕ χ ψ ω ε ϑ ϖ ϱ ς φ ϝ

    -

    Other Letters

    - - - - - - -
    \aleph \nablaı \imatha˚ \text{\aa}Œ \text{\OE}
    \beth \partialȷ \jmath \text{\AA} ø \text{\o}
    \gimel \Game \Imæ \text{\ae}Ø \text{\O}
    \daleth \Finv𝕜 \BbbkÆ \text{\AE}ß \text{\ss}
    ð \eth \hbar \Reœ \text{\oe}ı \text{\i}
    \ell \hslash \wp ȷ \text{\j}
    -

    Letters in the texvc extension

    - - - -
    \alef \Complex \natnums \real \weierp
    \alefsym \image \R \realsϑ \thetasym
    \cnums \N \Reals \Z
    -

    Direct Input: ∂ ∇ ℑ Ⅎ ℵ ℶ ℷ ℸ ⅁ ℏ ð À Á Â Ã Ä Å Æ Ç È É Ê Ë -Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö Ù Ú Û Ü Ý Þ ß à á â ã ä å ç è é ê ë ì í î ï ð ñ ò ó ô ö ù ú û ü ý þ ÿ - ₊ ₋ ₌ ₍ ₎ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉ ₐ ₑ ₕ ᵢ ⱼ ₖ ₗ ₘ ₙ ₒ ₚ ᵣ ₛ ₜ ᵤ ᵥ ₓ ᵦ ᵧ ᵨ ᵩ ᵪ ⁺ ⁻ ⁼ ⁽ ⁾ ⁰ ¹ ² ³ ⁴ ⁵ ⁶ ⁷ ⁸ ⁹ ᵃ ᵇ ᶜ ᵈ ᵉ ᵍ ʰ ⁱ ʲ ᵏ ˡ ᵐ ⁿ ᵒ ᵖ ʳ ˢ ᵗ ᵘ ʷ ˣ ʸ ᶻ ᵛ ᵝ ᵞ ᵟ ᵠ ᵡ

    -

    Math-mode Unicode (sub|super)script characters will render as if you had written regular characters in a subscript or superscript. For instance, A²⁺³ will render the same as A^{2+3}.

    -

    Unicode Mathematical Alphanumeric Symbols

    - - - - - - - - - - -
    Item Range Item Range
    Bold 𝐀-𝐙 𝐚-𝐳 𝟎-𝟗Double-struck 𝔸-ℤ 𝕒-𝕫 𝟘-𝟡
    Italic 𝐴-𝑍 𝑎-𝑧Sans serif 𝖠-𝖹 𝖺-𝗓 𝟢-𝟫
    Bold Italic 𝑨-𝒁 𝒂-𝒛Sans serif bold 𝗔-𝗭 𝗮-𝘇 𝟬-𝟵
    Fractur 𝔄-ℨ𝔞-𝔷Sans serif italic 𝘈-𝘡 𝘢-𝘻
    Monospace 𝙰-𝚉 𝚊-𝚣 𝟶-𝟿Sans serif bold italic 𝘼-𝙕 𝙖-𝙯
    -

    Any character can be written with the \char function and the Unicode code in hex. For example \char"263a will render as .

    -
    -
    For chancery or roundhand characters, it’s probably best to use \mathcal and \mathscr instead of Unicode input.
    Why? -

    Unicode has historically accepted either chancery or roundhand glyphs in the range U+1D49C—U+1D4B5. That's confusing, -because Cambria Math has chancery in those code points and some other math fonts have roundhand in the same code points. -Unicode 14 has recently added code points that resolve the ambiguity. Both chancery and roundhand still occupy the same range, but each unambigous chancery character has a \ufe00 appended to the code point and each unambigous roundhand character has a \ufe01 appended to the code point.

    -

    Published fonts have not yet caught up to the new code point assignments. If you want your documents to not break in the future, it’s probably best to avoid Unicode input and stick with \mathcal and \mathscr.

    -
    -
    -

    Layout

    -

    Line Breaks

    -

    Hard line breaks are \\ and \newline.

    -

    If the rendering options do not include annotations, Hurmet will write MathML with soft line breaks after relations and binary operators. These soft line breaks will appear only in Firefox. Chromium and Safari do not support soft line breaks.

    -

    Vertical Layout

    - - - - -
    xn x_n=! \stackrel{!}{=}abc a\raisebox{0.25em}{b}c
    ex e^x=! \overset{!}{=}MM2M M\raise3pt{M^2}M
    uo _u^o=! \underset{!}{=}MM2M M\lower3pt{M^2}M
    ab a \atop b
    - -
    0<i<m0<j<n\sum_{\substack{0<i<m\\0<j<n}}
    -

    LaTeX puts the second argument of \raisebox into text mode, but it can contain math if the math is nested within $…$ delimiters, as in \raisebox{0.25em}{$\frac a b$}

    -

    Overlap and Spacing

    - - -
    = {=}\mathllap{/\,}(x2) \left(x^{\smash{2}}\right)
    = \mathrlap{\,/}{=}y \sqrt{\smash[b]{y}}
    - -
    1ijnxij\sum\_{\mathclap{1\le i\le j\le n}} x\_{ij}
    -

    Temml also supports \llap, \rlap, and \clap. They work only in text mode if the rendering options include strict: true.

    -

    Spacing

    - - - - - - - - - - - - - - - - - - - -
    Function Produces Function Produces
    \,³∕₁₈ em space \kern{distance}space, width = distance
    \thinspace³∕₁₈ em space \mkern{distance}space, width = distance
    \>⁴∕₁₈ em space \mskip{distance}space, width = distance
    \:⁴∕₁₈ em space \hskip{distance}space, width = distance
    \medspace⁴∕₁₈ em space \hspace{distance}space, width = distance
    \;⁵∕₁₈ em space \hspace*{distance}space, width = distance
    \thickspace⁵∕₁₈ em space \phantom{content}space the width and height of content
    \enspace½ em space \hphantom{content}space the width of content
    \quad1 em space \vphantom{content}a strut the height of content
    \qquad2 em space \!– ³∕₁₈ em space
    ~non-breaking space \negthinspace– ³∕₁₈ em space
    \<space>space \negmedspace– ⁴∕₁₈ em space
    \nobreakspacenon-breaking space \negthickspace– ⁵∕₁₈ em space
    \spacespace
    -

    Notes:

    -

    distance will accept any of the Temml units.

    -

    \kern\mkern, \mskip, and \hskip accept unbraced distances, as in: \kern1em.

    -

    \mkern and \mskip will not work in text mode and both will write a console warning for any unit except mu.

    -

    \rule{}{distance} is valuable as a vertical strut.

    -

    Logic and Set Theory

    - - - - - - - - -
    \forall \complement \therefore \emptyset
    \exists \subset \becauseø \varnothing
    \nexists \supset \mapsto \implies
    \in| \mid \to \impliedby
    \ni \land \gets \iff
    \notin \lor \leftrightarrow \lightning
    \notni ¬ \neg or \lnot{x|x<12}
    \Set{ x | x<\frac 1 2 }
    {x|x<5}
    \set{x|x<5}
    \strictif \strictfi
    -

    Linear Logic (from the cmll package):

    - - - - -
    Operators ! \oc? \wn& \with \parr
    \shpos \shneg \shift \invamp
    Relations \coh \scoh \Perp \multimapboth
    \incoh \sincoh \multimapinv
    -

    Equivalents in the texvc extension

    - -
    \exist \isin \empty \sub
    -

    Direct Input: ∀ ∴ ∁ ∵ ∃ ∣ ∈ ∉ ∋ ⊂ ⊃ ∧ ∨ ↦ → ← ↔ ∅ ⟹ ⟺ ¬ ↯ ⥼ ⥽
    ℂ ℍ ℕ ℙ ℚ ℝ

    -

    Macros

    - - - - - - - -
    a2b3+c2d3 \def\macroname<arg list>{definition to be expanded}
    \def\foo#1#2{#1^2 #2^3}
    \foo a b + \foo c d
    \edef\macroname#1#2…{definition}
    \let\foo=\bar
    \futurelet\foo\bar x
    a2b3+c2d3 \newcommand\macroname[numargs]{definition}
    \newcommand\foo[2]{#1^2 #2^3}
    \foo a b + \foo c d
    \renewcommand\macroname[numargs]{definition}
    \providecommand\macroname[numargs]{definition}
    -

    To create macros with document-wide scope, a preamble can be defined as one of the Temml rendering options

    -

    Macros accept up to nine arguments: #1, #2, etc.

    -

    Available functions include:

    -

    \char \mathchoice \TextOrMath \@ifstar \@ifnextchar \@firstoftwo \@secondoftwo \relax \expandafter \noexpand

    -

    @ is a valid character for commands, as if \makeatletter were in effect.

    -

    Temml macros do not escape their group, so \gdef, \xdef, and\global are not supported. Temml has no \par, so \long is ignored.

    -

    Numbers

    -

    Temml’s default mode will consolidate a string of numerals into a single MathML <mn> element. This applies to any string that begins and ends with a digit (0-9) and includes digits, commas, or dots. Example: <mn>2,000.00</mn>.

    -

    In strict mode, Temml acts like LaTeX and treats each digit individually. This is not as nice semantically, but it does maintain backwards compatibility for LaTeX macros.

    -

    Operators

    -

    Big Operators

    - - - - - - - - - -
    \sum \prod \bigotimes \bigvee
    \int \coprod \bigoplus \bigwedge
    \iint \intop \bigodot \bigcap
    \iiint \smallint \biguplus \bigcup
    \iiiint \intcap \intcup \bigsqcup
    \oint \varointclockwise \intclockwise \bigsqcap
    \oiint \pointint \rppolint \scpolint
    \oiiint \intlarhk \sqint \intx
    \intbar \intBar \fint cdab \sideset{_a^b}{_c^d}\sum
    -

    Direct Input: ∫ ∬ ∭ ⨌ ∮ ∯ ∰ ⨖ ∲ ∏ ∐ ∑ ⋀ ⋁ ⋂ ⋃ ⨀ ⨁ ⨂ ⨄ ⨆ ⨅

    -

    Binary Operators

    - - - - - - - - - - - - - - - - - - -
    + + \cdot \gtrdot x(moda) x \pmod -a
    - · \cdotp \intercalx(a) x \pod a
    / \centerdot \land \rhd
    * * \circ \leftthreetimes \rightthreetimes
    ⨿ \amalg \circledast. \ldotp \rtimes
    & \And \circledcirc \lor \setminus
    \ast \circleddash \lessdot \smallsetminus
    \barwedge \Cup \lhd \sqcap
    \bigcirc \cup \ltimes \sqcup
    mod \bmod \curlyveexmoda x\mod a × \times
    \boxdot \curlywedge \mp \unlhd
    \boxminus÷ \div \odot \unrhd
    \boxplus \divideontimes \ominus \uplus
    \boxtimes \dotplus \oplus \vee
    \bullet \doublebarwedge \otimes \veebar
    \Cap \doublecap \oslash \wedge
    \cap \doublecup \parr & \with
    ± \pm \wr
    -

    The texvc extension provides ± \plusmn.

    -

    Direct Input: + - / ∖ * ⋅ ∘ ± × ÷ ∓ ∔ ∧ ∨ ∩ ∪ ≀ ⊎ ⊓ ⊔ ⊕ ⊖ ⊗ ⊘ ⊙ ⊚ ⊛ ⊝ ◯

    -

    Fractions and Binomials

    - - - -
    ab \frac{a}{b}ab \tfrac{a}{b}(aa+1] \genfrac ( ] {2pt}{1}a{a+1}
    ab {a \over b}ab \dfrac{a}{b}ab+1 {a \above{2pt} b+1}
    ab a/b a1+1b \cfrac{a}{1 + \cfrac{1}{b}}
    - - -
    (nk) \binom{n}{k}(nk) \dbinom{n}{k}{nk} {n\brace k}
    (nk) {n \choose k}(nk) \tbinom{n}{k}[nk] {n\brack k}
    -

    Math Operators

    - - - - - - - - - - - - - - - -
    f \operatorname{f}cosec \cosec dim \dim 2xyf \pdv*{f}{x,y}
    arcsin \arcsincosh \coshexp \expsec \sec
    arccos \arccoscot \cothom \homsgn \sgn
    arctan \arctancotg \cotgker \kersin \sin
    arctg \arctgcoth \cothlg \lgsinh \sinh
    arcctg \arcctgcsc \cscln \lnsh \sh
    arg \argctg \ctg log \logtan \tan
    ch \chcth \cthdfdx \odv{f}{x}tanh \tanh
    cos \cos \nabladdxf \odv*{f}{x}tg \tg
    \partialdeg \deg2fxy \pdv{f}{x,y}th \th
    f \operatorname*{f} or
    \operatornamewithlimits
    inf \inf max \max sup \sup
    argmax \argmax injlim \injlim min \min lim \varinjlim
    argmin \argmin lim \lim plim \plim lim_ \varliminf
    det \det liminf \liminf Pr \Pr lim_ \varlimsup
    gcd \gcd limsup \limsup projlim \projlim lim \varprojlim
    -

    Functions in the bottom five rows of this table can take \limits.

    -

    Enclosing Operators

    - - - -
    x \sqrt{x}3x2+2x+5 \longdiv{3x^2 + 2x + 5}
    x3 \sqrt[3]{x}78 \phase{-78^\circ}
    an   a_{\angl n}an   a_\angln
    -

    Physics and Chemistry

    - - - - -
    ϕ| \bra{\phi} 𝐂25+a2 \prescript{a}{2}{\mathbf{C}}^{5+}_{2}
    |ψ \ket{\psi} ϕ|ψ \braket{\phi\vert\psi}
    ϕ| \Bra{\phi} ϕ|2t2|ψ
    \Braket{ \phi | \frac{\partial^2}{\partial t^2} | \psi }
    |ψ \Ket{\psi}
    -

    From the mhchem extension:

    - - -
    SO42+Ba2+BaSO4\ce{SO4^2- + Ba^2+ -> BaSO4 v}
    75.3 JmolK\pu{75.3 J // mol K}
    -

    There is much more mhchem information in the -mhchem docs.

    -
    -
    Click to see the physics extension. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    |x| \abs{x} a|b \innerproduct{a}{b}if \qif
    |x| \absolutevalue{x}|ab| \ketbra{a}{b}in \qin
    {A,B} \acomm{A}{B} 2 \laplacianinteger \qinteger
    {A,B} \anticommutator{A}{B}n|A|m \matrixel{n}{A}{m}let \qlet
    {5mm} \Bqty{5 \text{mm}}n|A|m \matrixelement{n}{A}{m}odd \qodd
    [5mm] \bqty{5 \text{mm}}n|A|m \mel{n}{A}{m}or \qor
    [A,B] \comm{A}{B} x \norm{x} otherwise \qotherwise
    [A,B] \commutator{A}{B}|ab| \op{a}{b}  text  \qq{text}
    × \cp 𝒪(x2) \order{x^2} text  \qqtext{text}
    × \cross |ab| \outerproduct{a}{b}since \qsince
    × \crossproductxy \partialderivative{x}{y}then \qthen
    𝛁× \curl {x,y} \pb{x}{y} {5m} \qty{5 \text{m}}
    d \dd {5m} \quantity{5 \text{m}}
    dxdy \derivative{x}{y}{A,B} \poissonbracket{A}{B}unless \qunless
    d \differential(5) \pqty{5} using \qusing
    𝛁 \divergence 𝒫 \principalvaluerankM \rank M
    \dotproduct 𝒫 \pv Res[f(z)] \Res\[f(z)\]
    dxdy \dv{x}{y}P.V.(x) \PV(x)Trρ \Tr\rho
    |ab| \dyad{a}{b}all \qalltrρ \tr\rho
    erf(x) \erf(x)and \qand𝒂 \va{a}
    x \ev{x}as \qasδ \var
    12x|0n \eval{\tfrac 1 2 x}_0^nassume \qassume δ \variation
    12x|0n \evaluated{\tfrac 1 2 x}_0^n, \qc 𝒂 \vb{a}
    x \expectationvalue{x}c.c. \qcc \vdot
    x \expval{x} , \qcomma 𝒂 \vectorarrow{a}
    δxδy \fdv{x}{y} else \qelse 𝒂 \vectorbold{a}
    δxδy \functionalderivative{x}{y}even \qeven 𝒂^ \vectorunit{a}
    𝛁 \gradfor \qfor|x| \vqty{x}
    𝛁 \gradientgiven \qgiven𝒂^ \vu{a}
    -
    -

    Relations

    -

    =!ab \stackrel{!}{=}

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    = = \eqcirc \lesseqqgtr \smallsmile
    < < \eqcolon or
      \minuscolon
    \lessgtr \smile
    > > −∷ \Eqcolon or
       \minuscoloncolon
    \lesssim \sqsubset
    : : \eqqcolon \ll \sqsubseteq
    := := =∷ \Eqqcolon \lll \sqsupset
    \approx \eqdef \llless \sqsupseteq
    \approxeq \eqsim < \lt \stareq
    \arceq \eqslantgtr \measeq \Subset
    \asymp \eqslantless| \mid \subset
    \backcong \equiv \models \subseteq
    \backepsilon \fallingdotseq \multimap \subseteqq
    \backsim \frown \multimapboth \succ
    \backsimeq \ge \multimapinv \succapprox
    \between \geq \origof \succcurlyeq
    \bowtie \geqq \owns \succeq
    \bumpeq \geqslant \parallel \succsim
    \Bumpeq \gg \perp \Supset
    \circeq \ggg \Perp \supset
    \coh \gggtr \pitchfork \supseteq
    : \colonapprox> \gt \prec \supseteqq
    ∷≈ \Colonapprox or
       \coloncolonapprox
    \gtrapprox \precapprox \thickapprox
    : \coloneq or
       \colonminus
    \gtreqless \preccurlyeq \thicksim
    ∷− \Coloneq or
       \coloncolonminus
    \gtreqqless \preceq \trianglelefteq
    \coloneqq or
       \colonequals
    \gtrless \precsim \triangleq
    \Coloneqq or
        \coloncolonequals
    \gtrsim \propto \trianglerighteq
    : \colonsim \imageof \questeq \varpropto
    : \Colonsim or
       \coloncolonsim
    \in or \isin :\ratio or
      \vcentcolon
    \vartriangle
    \cong \incoh \risingdotseq \vartriangleleft
    \curlyeqprec \Join \scoh \vartriangleright
    \curlyeqsucc \le \shortmid \vdash
    \dashv \leq \shortparallel \vDash
    \dblcolon or
       \coloncolon
    \leqq \sim \Vdash
    \doteq \leqslant \simeq \Vvdash
    \Doteq \lessapprox \sincoh \veeeq
    \doteqdot \lesseqgtr \smallfrown \wedgeq
    -

    The texvc extension provides \sub, \sube, and \supe.

    -

    Direct Input: = < > : ∈ ∋ ∝ ∼ ∽ ≂ ≃ ≅ ≈ ≊ ≍ ≎ ≏ ≐ ≑ ≒ ≓ ≖ -≗ ≜ ≡ ≤ ≥ ≦ ≧ ≫ ≬ ≳ ≷ ≺ ≻ ≼ ≽ ≾ ≿ ⊂ ⊃ ⊆ ⊇ ⊏ ⊐ ⊑ ⊒ ⊢ ⊣ ⊩ ⊪ ⊸ ⋈ ⋍ ⋐ ⋑ ⋔ ⋙ -⋛ ⋞ ⋟ ⌢ ⌣ ⩾ ⪆ ⪌ ⪕ ⪖ ⪯ ⪰ ⪷ ⪸ ⫅ ⫆ ≲ ⩽ ⪅ ≶ ⋚ ⪋ ⟂ ⊨ ≔ ≕ ⩴ ⊷ ⊶

    -

    Negated Relations

    -

    \not =

    - - - - - - - - - - - - - - - -
    \gnapprox \ngeqslant \nsubset \nVdash
    \gneq \ngtr \nsubseteq \precnapprox
    \gneqq \nleq \nsubseteqq \precneqq
    \gnsim \nleqq \nsucc \precnsim
    ≩︀ \gvertneqq \nleqslant \nsucceq \subsetneq
    \lnapprox \nless \nsupset \subsetneqq
    \lneq \nmid \nsupseteq \succnapprox
    \lneqq \notin \nsupseteqq \succneqq
    \lnsim \notni \ntriangleleft \succnsim
    ≨︀ \lvertneqq \nparallel \ntrianglelefteq \supsetneq
    \ncong \nprec \ntriangleright \supsetneqq
    \ne \npreceq \ntrianglerighteq⊊︀ \varsubsetneq
    \neq \nshortmid \nvdash ⫋︀ \varsubsetneqq
    \ngeq \nshortparallel \nvDash \varsupsetneq
    \ngeqq \nsim \nVDash ⫌︀ \varsupsetneqq
    -

    Direct Input: ∉ ∌ ∤ ∦ ≁ ≆ ≠ ≨ ≩ ≮ ≯ ≰ ≱ ⊀ ⊁ ⊄ ⊅ ⊈ ⊉ ⊊ ⊋ ⊬ ⊭ -⊮ ⊯ ⋠ ⋡ ⋦ ⋧ ⋨ ⋩ ⋬ ⋭ ⪇ ⪈ ⪉ ⪊ ⪵ ⪶ ⪹ ⪺ ⫋ ⫌

    -

    Arrows

    - - - - - - - - - - - - - - - - - - - - - - - - - -
    \circlearrowleft \Leftrightarrow \rightarrow
    \circlearrowright \leftrightarrows \Rightarrow
    \curvearrowleft \leftrightharpoons \rightarrowtail
    \curvearrowright \leftrightsquigarrow \rightharpoondown
    \dashleftarrow \Lleftarrow \rightharpoonup
    \dashrightarrow \longleftarrow \rightleftarrows
    \downarrow \Longleftarrow \rightleftharpoons
    \Downarrow \longleftrightarrow \rightrightarrows
    \downdownarrows \Longleftrightarrow \rightsquigarrow
    \downharpoonleft \longmapsto \Rrightarrow
    \downharpoonright \longrightarrow \Rsh
    \gets \Longrightarrow \searrow
    \hookleftarrow \looparrowleft \swarrow
    \hookrightarrow \looparrowright \to
    \iff \Lsh \twoheadleftarrow
    \impliedby \mapsto \twoheadrightarrow
    \implies \nearrow \uparrow
    \leadsto \nleftarrow \Uparrow
    \leftarrow \nLeftarrow \updownarrow
    \Leftarrow \nleftrightarrow \Updownarrow
    \leftarrowtail \nLeftrightarrow \upharpoonleft
    \leftharpoondown \nrightarrow \upharpoonright
    \leftharpoonup \nRightarrow \upuparrows
    \leftleftarrows \nwarrow
    \leftrightarrow \restriction
    -

    Arrows in the texvc extension

    - - - -
    \Darr \Harr \Larr \Lrarr \Rarr \Uarr
    \dArr \hArr \lArr \lrArr \rArr \uArr
    \darr \harr \larr \lrarr \rarr \uarr
    -

    Direct Input: ← ↑ → ↓ ↔ ↕ ↖ ↗ ↘ ↙ ↚ ↛ ↞ ↠ ↢ ↣ ↦ ↩ ↪ ↫ ↬ ↭ ↮ ↰ ↱↶ ↷ ↺ ↻ ↼ ↽ ↾ ↾ ↿ ⇀ ⇁ ⇂ ⇃ ⇄ ⇆ ⇇ ⇈ ⇉ ⇊ ⇋ ⇌⇍ ⇎ ⇏ ⇐ ⇑ ⇒ ⇓ ⇔ ⇕ ⇚ ⇛ ⇝ ⇠ ⇢ ⟵ ⟶ ⟷ ⟸ ⟹ ⟺ ⟼ ↽

    -

    Extensible Arrows

    - - - - - - - - - - -
    abc \xleftarrow{abc}underover \xrightarrow[under]{over}
    abc \xLeftarrow{abc}abc \xRightarrow{abc}
    abc \xleftrightarrow{abc}abc \xLeftrightarrow{abc}
    abc \xhookleftarrow{abc}abc \xhookrightarrow{abc}
    abc \xtwoheadleftarrow{abc}abc \xtwoheadrightarrow{abc}
    abc \xleftharpoonup{abc}abc \xrightharpoonup{abc}
    abc \xleftharpoondown{abc}abc \xrightharpoondown{abc}
    abcabc \xleftrightharpoons{abc}abcabc \xrightleftharpoons{abc}
    abcabc \xtofrom{abc}abc \xmapsto{abc}
    =abc \xlongequal{abc}
    -

    All extensible arrows can take an optional argument in the same manner as \xrightarrow[under]{over}.

    -

    Style, Size, and Font

    -

    Class Assignment

    -

    Override the usual spacing and semantic meaning of a character or fragment.

    - -
    a=b  a = b
    a=b  a \mathord{=} b
    a=b  a \mathopen{=} b
    a=b  a \mathclose{=} b
    a|b  a | b
    a|b  a \mathpunct{|} b
    a|b  a \mathop{|} b
    a|b  a \mathbin{|} b
    a|b  a \mathrel{|} b
    -

    See also \operatorname.

    -

    Font

    - - - - - - - - - - - -
    Ab0 \mathrm{Ab0}𝐀𝐛𝟎𝛉 \mathbf{Ab0θ}Ab0θ \mathit{Ab0θ}
    Ab0 \mathnormal{Ab0}𝐀𝐛𝟎𝛉 \textbf{Ab0θ} 𝐴𝑏𝑏0𝜃 \textit{Ab0θ}
    Ab0θ \textrm{Ab0θ}𝐀𝐛𝟎𝛉 {\bf Ab0θ} Ab0θ {\it Ab0θ}
    Ab0 {\rm Ab0}𝐀𝐛𝟎𝛉 \bold{Ab0θ}Ab0θ \textup{Ab0θ}
    Ab0θ \textnormal{Ab0θ}𝑨𝒃0𝜽 \boldsymbol{Ab0θ}𝔸𝕓𝟘 \Bbb{Ab0}
    Ab0θ \text{Ab0θ}𝑨𝒃0𝜽 \bm{Ab0θ}𝔸𝕓𝟘 \mathbb{Ab0}
    𝖠𝖻𝟢 \mathsf{Ab0}Ab0θ \textmd{Ab0θ}𝔄𝔟 \frak{Ab}
    𝖠𝖻𝟢 \textsf{Ab0}𝙰𝚋𝟶 \mathtt{Ab0}𝔄𝔟 \mathfrak{Ab}
    𝖠𝖻𝟢 {\sf Ab0}𝙰𝚋𝟶 \texttt{Ab0}𝒜 \mathcal{AB}
    ʜᴇʏ \textsc{hey}𝙰𝚋𝟶 {\tt Ab0 }𝒜 {\cal AB}
    123 \oldstylenums{123}𝒜 \mathscr{AB}
    -

    The \textXX versions can stack font family, font weight, and font shape. So \textsf{\textbf{H}} will produce 𝗛. The other versions do not stack, e.g., \mathsf{\mathbf{H}} will produce 𝐇.

    -

    In cases where math fonts do not have a bold glyph, \pmb can simulate one. For example, \pmb{\vartheta} renders as : ϑ

    -

    Font Size

    - - - - - - -
    AB \Huge ABAB \normalsize AB
    AB \huge ABAB \small AB
    AB \LARGE ABAB \footnotesize AB
    AB \Large ABAB \scriptsize AB
    AB \large ABAB \Tiny AB
    AB \tiny AB
    -

    Style

    - - - - - - - - -
    i=1n\displaystyle\sum_{i=1}^n
    i=1n\textstyle\sum_{i=1}^n
    x\scriptstyle x     (The size of a first sub/superscript)
    x\scriptscriptstyle x (The size of subsequent sub/superscripts)
    limyx\lim\limits_y x
    limyx\lim\nolimits_y x
    x^2\verb!x^2!
    ABcd ABcd\text{ABcd $ABcd$}
    -

    \text{…} shifts its contents into text mode, but you can shift back into math mode by nesting $…$.

    -

    Symbols and Punctuation

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    % comment \dotsTEX \TeX
    % \% \cdotsLATEX \LaTeX
    # \# \ddotsTEMML \Temml
    & \& \ldots \rule[6pt]{2ex}{1ex}
    _ \_ \vdots \surd
    _ \text{\textunderscore} \iddots \infty
    \text{--} \dotsb \checkmark
    \text{\textendash} \dotsc \ballotx
    \text{---} \dotsi \dagger or \dag
    \text{\textemdash} \dotsm \text{\textdagger}
    ~ \text{\textasciitilde} \dotso \ddagger or \ddag
    ^ \text{\textasciicircum} \idotsin \text{\textdaggerdbl}
    ` \mathellipsis \angle
    text{\textquoteleft} \text{\textellipsis} \measuredangle
    \lq \Box \sphericalangle
    \text{\textquoteright} \square \top
    \rq \blacksquare \bot
    \text{\textquotedblleft} \triangle \Bot
    " " \triangledown$ \$
    \text{\textquotedblright} \triangleleft$ \text{\textdollar}
    : \colon \triangleright£ \pounds
    \backprime \bigtriangledown£ \mathsterling
    \prime \bigtriangleup£ \text{\textsterling}
    < \text{\textless} \blacktriangle¥ \yen
    > \text{\textgreater} \blacktriangledown \euro
    | \text{\textbar} \blacktriangleleft \text{\texteuro}
    \text{\textbardbl} \blacktriangleright° \degree
    { \text{\textbraceleft} \diamond ° \text{\textdegree}
    } \text{\textbraceright} \Diamond \mho
    \ \text{\textbackslash} \lozenge \diagdown
    \text{\textvisiblespace} \blacklozenge \diagup
    \text{\P} or \P \star \flat
    § \text{\S} or \S \bigstar \natural
    © \copyright \maltese \sharp
    ® \circledR \clubsuit \varclubsuit
    \circledS \diamondsuit \vardiamondsuit
    ® \text{\textregistered} \heartsuit \varheartsuit
    \text{\textbullet} \spadesuit \varspadesuit
    \smiley \female \male
    \standardstate \lightning \permil
    -

    Symbols in the texvc extension

    - - - -
    \clubs \hearts \sdot
    \diamonds \spades \infin
    \bull§ \text{\sect} \Dagger
    -

    Direct Input: § ¶ £ ¥ € ∇ ∞ · ∠ ∡ ∢ ♠ ♡ ♢ ♣ ♭ ♮ ♯ © ® ☺ ✓ ↯ … ⋮ ⋯ ⋱ ! ‼

    -

    Units

    - - - - - - - - - - - - -
    Unit Value Unit Value
    em CSS em bp 1/72​ inch
    ex CSS ex pc 12 pt
    mu 1/18 em dd 1238/1157​ pt
    pt 1/72.27 inch cc 14856/1157 pt
    mm 1 mm nd 685/642 pt
    cm 1 cm nc 1370/107​ pt
    in 1 inch sp 1/65536 pt
    -

    The effect of script level and font size:

    - - - - - - - - -
    Unit textstyle
    normal size
    scriptscript huge
    em or ex
    mu
    others
    -

    em and ex are affected by font size changes such as \Large, but they are not affected by script level, so they will not change size in a fraction numerator or an exponent.

    -

    mu is affected by both script level and font size.

    -

    The other units are absolute and are not affected by either script level or font size.

    -
    -

    Copyright © 2021, 2022 Ron Kok. -Released under the MIT License

    -
    -
    - - - - - diff --git a/site/docs/katex.css b/site/docs/katex.css deleted file mode 100644 index 73bb33e6..00000000 --- a/site/docs/katex.css +++ /dev/null @@ -1,11 +0,0 @@ -.katex .eqn-num::before { - counter-increment: katexEqnNo; - content: "(" counter(katexEqnNo) ")"; -} -.katex .mml-eqn-num::before { - counter-increment: mmlEqnNo; - content: "(" counter(mmlEqnNo) ")"; -} -body { - counter-reset: katexEqnNo mmlEqnNo tmlEqnNo; -} diff --git a/site/docs/sphere.jpg b/site/docs/sphere.jpg deleted file mode 100644 index d5f063a4f69e8f7d9903c7d01529a6e0b6a4c881..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12278 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 diff --git a/site/index.html b/site/index.html deleted file mode 100644 index d97077d6..00000000 --- a/site/index.html +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - -Temml - Convert TeX to MathML - - - - - - - - - - - - -
    - - -

    - TEMML -

    - -
    -
    -

    A TeX-to-MathML conversion library in JavaScript.

    - -

    - -
    -
    - -
    - - -
    -
    -
    - -
    - -
    -
    - CBdl=μ0(Ienc+ε0ddtSEn^da) -
    -
    -
    - -
    -
    -
    -
    - -     - -   -
    - -   -    -   - -
    -
    - -
    -
      -
    • Fast
    • -
    • Lightweight
    • -
    • Extensive LaTeX coverage
    • -
    • Thoroughly - - - Mozilla tests - Wikipedia tests - mhchem tests - LaTeXML tests - -
    • -
    • Works in browser or server-side with Node.js
    • -
    • No dependencies
    • -
    • Use any math font
    • -
    • MathML is supported by Firefox and partly supported by Safari.
      - It will soon be supported by Chrome, Edge, Opera, and Brave.
    • -
    -
    -
    - -
    - - - - - - - diff --git a/site/indexStyles.css b/site/indexStyles.css deleted file mode 100644 index 88321280..00000000 --- a/site/indexStyles.css +++ /dev/null @@ -1,200 +0,0 @@ -* { margin:0; } /* reset */ - -body { - margin: 0 0 5px; - line-height: 1.45; - background: white; - font-family: Calibri, 'Helvetica Neue', Arial, Cambria, sans-serif; - font-size: 18px; - position: relative; -} - -nav { - max-width: 800px; - margin: 0 auto; - background: #fff; - font-size: 16px; - height: 66px -} - -nav * { - font-family: Arial, sans-serif; -} - -nav ul { - list-style: none; - margin: 0; - padding: 0; - float: right; -} - -nav ul li { - display: block; - float: right; - padding-top: 27px; - text-decoration: none -} - -nav a { - padding: 33px 0 0 18px; - text-decoration: none; - color: inherit; -} - -article, #title { - max-width: 800px; - margin: 0 auto; -} - -#demo { - margin: 0px 2.5px 0px 2.5px; - overflow: fixed; -} - -h1 { - font-family: Verdana, sans-serif; - font-variant: small-caps; - letter-spacing: 0.05em; - margin-top: 3em; - font-size: 140%; - margin-top: 1em; -} - -p { - margin-top: 1em; - line-height: 1.35; - text-align: justify; -} - -#why { - width: 70%; - margin-top: 2em; - margin-left: auto; - margin-right: auto; -} - -#why ul li { - list-style-type: disc; - line-height: 1.35; - margin-top: 0.5em; - position: relative; - left: 1.8em; -} - -a { - text-decoration: underline; - color: black; -} - -#demo-parent { - width: 100%; -} - -#demo { - width: 100%; - display: flex; - flex-direction: row; - flex-wrap: wrap; -} - -.wide #demo { - flex-direction: column; -} - -#input, -#output { - width: 395px; - flex-basis: auto; -} - -.wide #input, -.wide #output { - width: 100%; -} - -#spacer { - width: 10px; -} - -.ioArea { - font-size: 0.9em; - width: 360px; - height: 10em; - border-radius: 4px; - border: 1px solid rgb(200, 200, 200); - display: inline-block; - padding: 1em 1em; - vertical-align: top; - resize: none; - overflow: auto; -} - -.wide .ioArea { - width: 760px; -} - -math { - font-size: 115%; -} - -#demoSource { - font-family: Consolas, Menlo, Monaco, monospace; -} - -#notice { - margin-top: 2em; - color:rgb(182, 32, 32); -} - -@media (max-width: 799px){ - nav { - width: 90%; - } - article, #input, #output, #title, #copyright { - width: 100%; - } - .ioArea { - width: 93% - } - #why ul { padding-inline-start: 0; } -} - -#copyright { - max-width: 800px; - margin: 0 auto; - font-family: Arial, sans-serif; - font-size: 10px; - text-align: center; -} - -#copyright a { - color: inherit; -} - -.dropdown { - position: relative; - display: inline-block; -} - -.dropbtn { - background-color: #d3d3d3; - padding: 4px; - border: none; - cursor: pointer; -} - -.dropdown-content { - display: none; - position: absolute; - background-color: #f9f9f9; - min-width: 160px; - box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); - padding: 12px 16px; - z-index: 1; -} - -.dropdown a { text-decoration: none; } - -.dropdown:hover .dropdown-content { - display: block; -} \ No newline at end of file diff --git a/site/mathml.css b/site/mathml.css deleted file mode 100644 index af84a2d7..00000000 --- a/site/mathml.css +++ /dev/null @@ -1,218 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - - /* This file is a backup for browsers that do not support MathML. - * Hopefully, it will get very little use. - */ - -/* See https://github.com/fred-wang/mathml.css */ - -@namespace "http://www.w3.org/1998/Math/MathML"; - -/* math */ -math { - display: inline; - text-indent: 0; -} -math[display="block"] { - display: block; - text-align: center; -} - -/* fraction */ -mfrac { - display: inline-block !important; - vertical-align: -50%; - border-collapse: collapse; - text-align: center; -} -mfrac > * { - display: block !important; -} -mfrac > * + * { - display: inline-block !important; - vertical-align: top; -} -mfrac:not([linethickness="0"]) > *:first-child { - border-bottom: solid thin; -} - -/* sub/sup scripts */ -msub > *:nth-child(2), msubsup > *:nth-child(2), -mmultiscripts > *:nth-child(2n+2), -mmultiscripts > mprescripts ~ *:nth-child(2n+3) { - font-size: 0.8em; - vertical-align: sub; -} -msup > *:nth-child(2), msubsup > *:nth-child(3), -mmultiscripts > *:nth-child(2n+3), -mmultiscripts > mprescripts ~ *:nth-child(2n+2) { - font-size: 0.8em; - vertical-align: super; -} -mprescripts:after { - content: ";"; -} - -/* under/over scripts */ -munder, mover, munderover { - display: inline-flex !important; - flex-direction: column; -} -munder > *:nth-child(2), munderover > *:nth-child(2) { - font-size: 0.8em; - order: +1; -} -mover > *:nth-child(2), munderover > *:nth-child(3) { - font-size: 0.8em; - order: -1; -} -munder { - vertical-align: text-top; -} -mover { - vertical-align: text-bottom; -} -munderover { - vertical-align: middle; -} - -/* roots */ -msqrt, mroot { - display: inline-flex !important; - margin-left: .6em; - vertical-align: middle; - border-top: solid thin; -} -msqrt:before, mroot:before { - margin-left: -.6em; - content: "\221A"; -} -mroot > *:nth-child(2) { - margin-right: .25em; - margin-left: -.75em; - font-size: 0.8em; - order: -1; -} - -/* menclose */ -menclose { - display: inline-table !important; - border-collapse: separate; - border-spacing: 0.4ex 0; -} -menclose[notation*="top"], menclose[notation*="actuarial"] { - border-top: solid thin; -} -menclose[notation*="bottom"], menclose[notation*="madruwb"] { - border-bottom: solid thin; -} -menclose[notation*="right"], menclose[notation*="actuarial"], -menclose[notation*="madruwb"] { - border-right: solid thin; -} -menclose[notation*="left"] { - border-left: solid thin; -} -menclose[notation*="box"], menclose[notation*="roundedbox"], -menclose[notation*="circle"] { - border: solid thin; -} -menclose[notation*="roundedbox"] { - border-radius: 15%; -} -menclose[notation*="circle"] { - border-radius: 50%; -} -menclose[notation*="horizontalstrike"] { - text-decoration: line-through; -} - -/* table */ -mtable { - display: inline-table !important; - vertical-align: middle; - text-align: center; -} -mtr { - display: table-row !important; -} -mtd { - display: table-cell !important; - padding: 0 0.5ex; -} - -/* token elements */ -mspace { - margin: .2em; -} -mi { - font-style: italic; -} -mo { - margin-right: .2em; - margin-left: .2em; -} -ms:before, ms:after { - content:"\0022"; -} -ms[lquote]:before { - content: attr(lquote); -} -ms[rquote]:after { - content: attr(rquote); -} - -/* mathvariants */ -[mathvariant="bold"], [mathvariant="bold-italic"], -[mathvariant="bold-sans-serif"], [mathvariant="sans-serif-bold-italic"] { - font-weight: bold; - font-style: normal; -} -[mathvariant="monospace"] { - font-family: monospace; - font-style: normal; -} -[mathvariant="sans-serif"], -[mathvariant="bold-sans-serif"], [mathvariant="sans-serif-italic"], -[mathvariant="sans-serif-bold-italic"] { - font-family: sans-serif; - font-style: normal; -} -[mathvariant="italic"], [mathvariant="bold-italic"], -[mathvariant="sans-serif-italic"], [mathvariant="sans-serif-bold-italic"] { - font-style: italic; -} -[mathvariant="normal"] { - font-style: normal; -} - -/* mphantom */ -mphantom { - visibility: hidden; -} - -/* merror */ -merror { - outline: solid thin red; -} -merror:before { - content: "Error: "; -} - -/* annotations */ -semantics > *:first-child { - display: inline; -} -annotation, annotation-xml { - font-family: monospace; - display: none !important; -} -math:active > semantics > *:first-child, -math:active > semantics > *:first-child { - display: none !important; -} -math:active annotation:first-of-type { - display: inline !important; -} \ No newline at end of file diff --git a/site/tests/LaTeXML-tests.html b/site/tests/LaTeXML-tests.html deleted file mode 100644 index 7734160d..00000000 --- a/site/tests/LaTeXML-tests.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - Temml LaTeXML Tests - - - - - - -

    LaTeXML Test

    -

    This LaTeXML test reproduces math examples from https://latexml.mathweb.org/editor
    The equations in the first table came originally from http://www.mathjax.org/demos/tex-samples/, which no longer exists.

    -

    Equations

    - - - - - - - - - - - - - - - - - - -
    SourceTemml
    The Lorenz Equations
    1 \begin{aligned}
    \dot{x} & = \sigma(y-x) \\
    \dot{y} & = \rho x - y - xz \\
    \dot{z} & = -\beta z + xy
    \end{aligned}
    x˙=σ(yx)y˙=ρxyxzz˙=βz+xy
    The Cauchy-Schwarz Inequality
    2 \left( \sum_{k=1}^n ak bk \right)^2
    \leq \left( \sum_{k=1}^n ak^2 \right)
    \left( \sum_{k=1}^n bk^2 \right) \
    (k=1nakbk)2(k=1nak2)(k=1nbk2)
    A Cross Product Formula
    3 \mathbf{V}_1 \times \mathbf{V}_2 =
    \begin{vmatrix}
    \mathbf{i} & \mathbf{j} & \mathbf{k} \\
    \frac{\partial X}{\partial u} &
    \frac{\partial Y}{\partial u} & 0 \\
    \frac{\partial X}{\partial v} &
    \frac{\partial Y}{\partial v} & 0
    \end{vmatrix}
    𝐕1×𝐕2=|𝐢𝐣𝐤XuYu0XvYv0|
    The probability of getting k heads when flipping n coins is:
    4P(E) = {n \choose k} p^k (1-p)^{ n-k} \P(E)=(nk)pk(1p)nk
    An Identity of Ramanujan
    5 \frac{1}{\Bigl(\sqrt{\phi \sqrt{5}}-
    \phi\Bigr) e^{\frac25 \pi}} =
    1+\frac{e^{-2\pi}} {1+\frac{e^{-4\pi}}
    {1+\frac{e^{-6\pi}}
    {1+\frac{e^{-8\pi}} {1+\ldots} } } }
    1(ϕ5ϕ)e25π=1+e2π1+e4π1+e6π1+e8π1+
    A Rogers-Ramanujan Identity
    6 1 + \frac{q^2}{(1-q)}+
    \frac{q^6}{(1-q)(1-q^2)}+\cdots =
    \prod_{j=0}^{\infty}\frac{1}
    {(1-q^{5j+2})(1-q^{5j+3})},
    \quad\quad \text{for} |q|<1.
    1+q2(1q)+q6(1q)(1q2)+=j=01(1q5j+2)(1q5j+3),for|q|<1.
    Maxwell's Equations
    7 \begin{aligned}
    \nabla \times \vec{\mathbf{B}} -\\,
    \frac1c\, \frac{\partial\vec{
    \mathbf{E}}}{\partial t} &
    = \frac{4\pi}{c}\vec{\mathbf{j}} \\
    \nabla \cdot \vec{\mathbf{E}} &
    = 4 \pi \rho \\
    \nabla \times \vec{\mathbf{E}}\, +\,
    \frac1c\, \frac{\partial\vec{
    \mathbf{B}}}{\partial t} &
    = \vec{\mathbf{0}} \\
    \nabla \cdot \vec{\mathbf{B}} &
    = 0
    \end{aligned} \
    ×𝐁1c𝐄t=4πc𝐣𝐄=4πρ×𝐄+1c𝐁t=𝟎𝐁=0
    -

    Boxes

    - - - - -
    Source Temml
    \raisebox{0pt}[0pt][0pt]{\Large%
    \textbf{Aaaa\raisebox{-0.3ex}{a}%
    \raisebox{-0.7ex}{aa}\raisebox{-1.2ex}{r}%
    \raisebox{-2.2ex}{g}\raisebox{-4.5ex}{h}}}
    𝐀𝐚𝐚𝐚𝐚𝐚𝐚𝐚𝐚𝐚𝐫𝐠𝐡
    -

    Unicode

    -

    The tests below come from https://latexml.mathweb.org/editor
    They got them from https://trac.edgewall.org/wiki/TracUnicode
    I have no idea what these lines say.

    -

    All the Unicode characters are written inside \text{}.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Language Temml
    Arabic تراك يقوم بحفظ كل الكلمات باستخدام صيغة2
    Bulgarian Българският език работи ли?2
    Česky Cˇesˇtina v koˊdovaˊnıˊ UTF-8, zˇaˊdnyˊ probleˊm.2
    Chinese (Traditional) 繁體中文, 漢字測試2
    Chinese (Simplified) 简体中文,汉字测试2
    Croatian (Ako podrko podrzˇava srpski i slovenski mora podrzˇavati i Hrvatski - i Hrvatski - cˇcˊzˇsˇđ CˇCˊZˇSˇĐ)
    English Yes indeed, Trac supports English. Fully.2
    Français Il est possible d’l est possible deˊcrire en Français : aˋ, ç, uˆ, 2
    German (Trac-Wiki muß auch deutsche Umlaute richtig anzeigen:o¨, a¨, u¨, A¨, O¨, U¨; und das scharfe ß)
    Greek Τα Ελληνικα Ελληνικαˊ υποστηριˊζονται επαρκωˊς επιˊσης.2
    Hebrew אני יכול לאכול זכוכית וזה לא מזיק לי2
    Hindi अब हिन्दी में।2
    Hungarian Aˊrvıˊztu˝ro˝ tu¨ko¨rfuˊroˊgeˊp2
    Icelandic Ævar sagði við var sagði við o¨mmu sıˊna: Sjaˊðu hvað eˊg er stoˊr!2
    Japanese 漢字 ひらがな カタカナ ハンカクカナ 日本語試験2
    Korean 이번에는 한글로 써보겠습니다. 잘 보이나요? 한글2
    Latvian Latvieatviesˇu valoda arıˉ straˉdaˉ!2
    Lithuanian (Sudalyvaukime ir mes. Ar veikia lietuviudalyvaukime ir mes. Ar veikia lietuvisˇkos raide˙s?ącˇęe˙įsˇųuˉzˇ ĄCˇĘE˙ĮSˇŲUˉZˇ Zˇinoma, kad veikia :) Kas tie mes?)
    Persian (Farsi) (ولی امکان نوشتن مستقیم فارسی نیست چون حالت متن از راست به چپ و جوداین یک متن فارسی است ندارد برای فارسی نوشتن باید از HTML استفاده کنید.)
    Polish (Pchnąchnącˊ w tę łoˊdzˊ jez˙a lub osiem skrzynˊ fig;Nocna gocna gz˙egz˙oˊłka zawsze dzienną przekuka.)
    Portuguese (Eˊ possıˊvel guardar caracteres especias da lıˊngua portuguesa, incluindo o sncluindo o sıˊmbolo da moeda europeˊia , trema u¨, crase aˋ, agudos aˊeˊıˊoˊuˊ,circunflexos ’ircunflexos aˆeˆoˆ, til a˜o˜, cedilha ç, ordinais ªº, grau °¹²³.)
    Russian (Проверка русского языка: кажется работает... И буква "ё" есть...2
    Serbian (Podrodrzˇan, uprkos cˇinjenici da se za njegovopisanje koriste чак два алфабета.)
    Slovenian Ta suhi a suhi sˇkafec pusˇcˇa vodo zˇe od nekdaj!2
    Spanish (Esto es un pequesto es un pequen˜o texto en Espan˜ol,donde el veloz murcionde el veloz murcieˊlago hinduˊ comıˊa cardlllo y kiwi)
    Swedish Ra¨ven raskar o¨ver isen med luva pa˚.2
    Thai Trac แสดงภาษาไทยได้อย่างถูกต้อง!2
    Ukrainian Перевірка української мови...2
    Urdu ٹریک اردو بھی سپورٹ کرتا ہے۔2
    Vietnamese Viieˆˊt tieˆˊng Vit cu˜ng đưc.2
    -
    - - diff --git a/site/tests/images/AccentsText.svg b/site/tests/images/AccentsText.svg deleted file mode 100644 index 8020e45e..00000000 --- a/site/tests/images/AccentsText.svg +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/ArrayMode.svg b/site/tests/images/ArrayMode.svg deleted file mode 100644 index 683d1aa9..00000000 --- a/site/tests/images/ArrayMode.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/ArrayType.svg b/site/tests/images/ArrayType.svg deleted file mode 100644 index ca29097d..00000000 --- a/site/tests/images/ArrayType.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/Arrays.svg b/site/tests/images/Arrays.svg deleted file mode 100644 index 075bfb7b..00000000 --- a/site/tests/images/Arrays.svg +++ /dev/null @@ -1,238 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/BinCancellation.svg b/site/tests/images/BinCancellation.svg deleted file mode 100644 index 43585d72..00000000 --- a/site/tests/images/BinCancellation.svg +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/BoldSymbol.svg b/site/tests/images/BoldSymbol.svg deleted file mode 100644 index 5a65f027..00000000 --- a/site/tests/images/BoldSymbol.svg +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/CD.svg b/site/tests/images/CD.svg deleted file mode 100644 index fdc49725..00000000 --- a/site/tests/images/CD.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/site/tests/images/ColorBox.svg b/site/tests/images/ColorBox.svg deleted file mode 100644 index 4796accc..00000000 --- a/site/tests/images/ColorBox.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/ColorImplicit.svg b/site/tests/images/ColorImplicit.svg deleted file mode 100644 index b51c9868..00000000 --- a/site/tests/images/ColorImplicit.svg +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/ColorSpacing.svg b/site/tests/images/ColorSpacing.svg deleted file mode 100644 index 0e4eec2c..00000000 --- a/site/tests/images/ColorSpacing.svg +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/DashesAndQuotes.svg b/site/tests/images/DashesAndQuotes.svg deleted file mode 100644 index d1478411..00000000 --- a/site/tests/images/DashesAndQuotes.svg +++ /dev/null @@ -1,276 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/DelimiterSizing1.svg b/site/tests/images/DelimiterSizing1.svg deleted file mode 100644 index 5eef3f3c..00000000 --- a/site/tests/images/DelimiterSizing1.svg +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/DelimiterSizing2.svg b/site/tests/images/DelimiterSizing2.svg deleted file mode 100644 index d56576cf..00000000 --- a/site/tests/images/DelimiterSizing2.svg +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/DisplayMode.svg b/site/tests/images/DisplayMode.svg deleted file mode 100644 index 40c7d930..00000000 --- a/site/tests/images/DisplayMode.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/ExtensibleArrows.svg b/site/tests/images/ExtensibleArrows.svg deleted file mode 100644 index 5fac9045..00000000 --- a/site/tests/images/ExtensibleArrows.svg +++ /dev/null @@ -1,326 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/Fractions1.svg b/site/tests/images/Fractions1.svg deleted file mode 100644 index 07a80f1c..00000000 --- a/site/tests/images/Fractions1.svg +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/Fractions2.svg b/site/tests/images/Fractions2.svg deleted file mode 100644 index cd42d03a..00000000 --- a/site/tests/images/Fractions2.svg +++ /dev/null @@ -1,158 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/HorizontalBraces.svg b/site/tests/images/HorizontalBraces.svg deleted file mode 100644 index a304a034..00000000 --- a/site/tests/images/HorizontalBraces.svg +++ /dev/null @@ -1,191 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/Integrands.svg b/site/tests/images/Integrands.svg deleted file mode 100644 index 77ccc388..00000000 --- a/site/tests/images/Integrands.svg +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/LargeRuleNumerator.svg b/site/tests/images/LargeRuleNumerator.svg deleted file mode 100644 index 6dc12522..00000000 --- a/site/tests/images/LargeRuleNumerator.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/LeftRight.svg b/site/tests/images/LeftRight.svg deleted file mode 100644 index 55f59eec..00000000 --- a/site/tests/images/LeftRight.svg +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/LeftRightListStyling.svg b/site/tests/images/LeftRightListStyling.svg deleted file mode 100644 index 505f0e76..00000000 --- a/site/tests/images/LeftRightListStyling.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/LeftRightMiddle.svg b/site/tests/images/LeftRightMiddle.svg deleted file mode 100644 index 8ae04751..00000000 --- a/site/tests/images/LeftRightMiddle.svg +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/LeftRightStyleSizing.svg b/site/tests/images/LeftRightStyleSizing.svg deleted file mode 100644 index 10caa36b..00000000 --- a/site/tests/images/LeftRightStyleSizing.svg +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/LimitControls.svg b/site/tests/images/LimitControls.svg deleted file mode 100644 index 6c2bbf40..00000000 --- a/site/tests/images/LimitControls.svg +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/MathChoice.svg b/site/tests/images/MathChoice.svg deleted file mode 100644 index 1e7a205c..00000000 --- a/site/tests/images/MathChoice.svg +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/MathtoolsMatrix.svg b/site/tests/images/MathtoolsMatrix.svg deleted file mode 100644 index 4304daf3..00000000 --- a/site/tests/images/MathtoolsMatrix.svg +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/NegativeSpace.svg b/site/tests/images/NegativeSpace.svg deleted file mode 100644 index a7fa46c8..00000000 --- a/site/tests/images/NegativeSpace.svg +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/NestedFractions.svg b/site/tests/images/NestedFractions.svg deleted file mode 100644 index 3c82194b..00000000 --- a/site/tests/images/NestedFractions.svg +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/NullDelimiterInteraction.svg b/site/tests/images/NullDelimiterInteraction.svg deleted file mode 100644 index db3d62eb..00000000 --- a/site/tests/images/NullDelimiterInteraction.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/OpLimits.svg b/site/tests/images/OpLimits.svg deleted file mode 100644 index 585914c8..00000000 --- a/site/tests/images/OpLimits.svg +++ /dev/null @@ -1,301 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/OperatorName.svg b/site/tests/images/OperatorName.svg deleted file mode 100644 index 1b6fd3be..00000000 --- a/site/tests/images/OperatorName.svg +++ /dev/null @@ -1,231 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/OverUnderline.svg b/site/tests/images/OverUnderline.svg deleted file mode 100644 index 3865b737..00000000 --- a/site/tests/images/OverUnderline.svg +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/OverUnderset.svg b/site/tests/images/OverUnderset.svg deleted file mode 100644 index 16b105fa..00000000 --- a/site/tests/images/OverUnderset.svg +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/PrimeSpacing.svg b/site/tests/images/PrimeSpacing.svg deleted file mode 100644 index 1575dfa6..00000000 --- a/site/tests/images/PrimeSpacing.svg +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/PrimeSuper.svg b/site/tests/images/PrimeSuper.svg deleted file mode 100644 index 009ce817..00000000 --- a/site/tests/images/PrimeSuper.svg +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/RelativeUnits.svg b/site/tests/images/RelativeUnits.svg deleted file mode 100644 index 68f44547..00000000 --- a/site/tests/images/RelativeUnits.svg +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/SizingBaseline.svg b/site/tests/images/SizingBaseline.svg deleted file mode 100644 index a5a2207c..00000000 --- a/site/tests/images/SizingBaseline.svg +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/SqrtRoot.svg b/site/tests/images/SqrtRoot.svg deleted file mode 100644 index 636858dd..00000000 --- a/site/tests/images/SqrtRoot.svg +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/StretchyAccent.svg b/site/tests/images/StretchyAccent.svg deleted file mode 100644 index a44f996f..00000000 --- a/site/tests/images/StretchyAccent.svg +++ /dev/null @@ -1,385 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/StrikeThrough.svg b/site/tests/images/StrikeThrough.svg deleted file mode 100644 index 721dce43..00000000 --- a/site/tests/images/StrikeThrough.svg +++ /dev/null @@ -1,337 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/StrikeThroughColor.svg b/site/tests/images/StrikeThroughColor.svg deleted file mode 100644 index df033b99..00000000 --- a/site/tests/images/StrikeThroughColor.svg +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/StyleSpacing.svg b/site/tests/images/StyleSpacing.svg deleted file mode 100644 index 45c03462..00000000 --- a/site/tests/images/StyleSpacing.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/StyleSwitching.svg b/site/tests/images/StyleSwitching.svg deleted file mode 100644 index fd2de68c..00000000 --- a/site/tests/images/StyleSwitching.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/SupSubCharacterBox.svg b/site/tests/images/SupSubCharacterBox.svg deleted file mode 100644 index 755711fc..00000000 --- a/site/tests/images/SupSubCharacterBox.svg +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/SupSubHorizSpacing.svg b/site/tests/images/SupSubHorizSpacing.svg deleted file mode 100644 index 7cbcc203..00000000 --- a/site/tests/images/SupSubHorizSpacing.svg +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/SupSubLeftAlignReset.svg b/site/tests/images/SupSubLeftAlignReset.svg deleted file mode 100644 index 65be9280..00000000 --- a/site/tests/images/SupSubLeftAlignReset.svg +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/SupSubOffsets.svg b/site/tests/images/SupSubOffsets.svg deleted file mode 100644 index 6b2edf53..00000000 --- a/site/tests/images/SupSubOffsets.svg +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/TextSpace.svg b/site/tests/images/TextSpace.svg deleted file mode 100644 index 01d15c69..00000000 --- a/site/tests/images/TextSpace.svg +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/TextStacked.svg b/site/tests/images/TextStacked.svg deleted file mode 100644 index 734253f0..00000000 --- a/site/tests/images/TextStacked.svg +++ /dev/null @@ -1,405 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/TextWithMath.svg b/site/tests/images/TextWithMath.svg deleted file mode 100644 index a01d94f0..00000000 --- a/site/tests/images/TextWithMath.svg +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/accents.svg b/site/tests/images/accents.svg deleted file mode 100644 index 20942f66..00000000 --- a/site/tests/images/accents.svg +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/align.svg b/site/tests/images/align.svg deleted file mode 100644 index 8df18980..00000000 --- a/site/tests/images/align.svg +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/aligned.svg b/site/tests/images/aligned.svg deleted file mode 100644 index 89dd2bbb..00000000 --- a/site/tests/images/aligned.svg +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/alignedat.svg b/site/tests/images/alignedat.svg deleted file mode 100644 index 2dd5edc9..00000000 --- a/site/tests/images/alignedat.svg +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/angl.svg b/site/tests/images/angl.svg deleted file mode 100644 index b54829e7..00000000 --- a/site/tests/images/angl.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/site/tests/images/baseline.svg b/site/tests/images/baseline.svg deleted file mode 100644 index 92c16ffa..00000000 --- a/site/tests/images/baseline.svg +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/binom.svg b/site/tests/images/binom.svg deleted file mode 100644 index 52ba9ac6..00000000 --- a/site/tests/images/binom.svg +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/boxed.svg b/site/tests/images/boxed.svg deleted file mode 100644 index f7c5d50e..00000000 --- a/site/tests/images/boxed.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/cases.svg b/site/tests/images/cases.svg deleted file mode 100644 index 0517a9a1..00000000 --- a/site/tests/images/cases.svg +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/colors.svg b/site/tests/images/colors.svg deleted file mode 100644 index 7b0dc958..00000000 --- a/site/tests/images/colors.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/displaystyle.svg b/site/tests/images/displaystyle.svg deleted file mode 100644 index d88829f6..00000000 --- a/site/tests/images/displaystyle.svg +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/dots.svg b/site/tests/images/dots.svg deleted file mode 100644 index b8b82d35..00000000 --- a/site/tests/images/dots.svg +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/equation.svg b/site/tests/images/equation.svg deleted file mode 100644 index afd21ac0..00000000 --- a/site/tests/images/equation.svg +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/ex1.gif b/site/tests/images/ex1.gif deleted file mode 100644 index 7d39a37dfa150dd37eec1de012cf859b7e550358..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 202 zcmZ?wbhEHbRAUfhIK%(~2M!!)XlVHV|G$HS16Tk=DE?$&WME)q&;fBkY8{ySEq1L@ z4A^pV5l0DI(&r}vh73p4c$aVIcqG8EQj7oTogCgA<6W2Dn@w88wnQLG`8Ibm(;KEU zNpDyR^iqWygBKpnYm9xjUBh)!yY4ih1AlHFI;wSJPqO_?!#7FNPL5$>ff_R0`g&qQ v0d_*}#*y)PA_dk3lX-jXD<$i@|IX*lc6yZ_)oKtgDKK*>BzaGjtFHvtgLc{<5 z8(#v7PIgq9KpQB94;y)b;ks<#;`RI!eS%N&&JU{#a$#`56;VWpB*E1 zrXddy#g7VrpnR$@f7Wa48TMwOlcD%S^lbewgwpY(hA@2bJQ$quZ_S=z0;@b^Fp=E3 zSy>`9yvF{qqel?3mQ4Dnrcxzhgt7#wXl{v@3ooaUT*1T_4OUjn5W@M+feINLX9^t} z!<$SEDv82-^QFeW5*3{ia%Co{(lFsH(PQag+#W9?m6p^ewwOkA>C}~l2jOCeBWv4a zJ9>{-*eO;s{Bb+zle+~h7h;;jRbira15f6qf@CkRPa_J2>QeX~PoGHUp8Dp^8aql> zMcNApqTH!*PV}MXFpl(FZJJznO|288KG_;BFC}qwazF9d>{rCcNwj=8x zl5-XQW(WpELTi~spDlsOfnZH~eD_ful}Y7OLlVXT7!zPQh~I{q{4oJv9!kI+hlXfK zVo(0j@tYAVo`?lgsaZoAQmw&+5_+7#L6sQotm4)UWe`Z79z8UaP=!JK1QUK;OmicO SNKK@Riy&QaAC(v+0027&xGISN diff --git a/site/tests/images/ex11.gif b/site/tests/images/ex11.gif deleted file mode 100644 index cc6596a08ea93dc3021a04fd9f98fa75deb522bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 156 zcmZ?wbhEHblx7fOIK%(~2M!!)XlVHV|G$HS16Tk=DE?$&WME)q&;fBkY8{vpEq1L@ z4A|lssSv0o#HPr6Ah9cK?u#Q+7c%QL%;dXpre;Gg+ughCr5F+f7`|vV-J75o@oFBo z%v;u_CbCScil@cem~55oUs_M)jwA<^WrVJ5>$U+PqXH0Ige;WKWW}?T z?L{ntasZzZI5ZBBN|!2dBM}~&7i8zUIv26(*W0~CPTXx{paSm*Tt)S?ki;9ljly10 zKLHtmf`LdfNf$A2gNtW|GGY`tjEsdcQD2xX5+qb0ndFX%FAqqn1;hr&deNS)YXSyK#)Z_z#(A^)*{y9 z7P|`O!r)Dy9_k^{VC^IF9a*jRwGCqWVEq*ET^mTy*bZ8%R_XHhMocV2vpU#nHz}aM zf*AWK%E`A`fw*@Mm6W+>vLL5MUUE zB6Mv538~!V8EA{uTxzBVt7>RjD2RS=-hRcA#@#5n&SzwL9n7dHcrpAMm#aTOf5|6h zwVJZ2C`dqAl0I#AtOKjt2Dx;JD06T~nw449{ diff --git a/site/tests/images/ex13.gif b/site/tests/images/ex13.gif deleted file mode 100644 index fa8405b71cf1f214fdda2e0a3800a52dc2c5b784..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1763 zcmV<91|0cENk%w1VU+=70KxzO0002Mz`%fjfdBvhKtMnM0000000000A^8LW00031 zEC2ui0F?n`06+u&IJ!ImFv>}*y*TU5yZ>M)j$~<`XvzsqE3j=W&vb3yc&_h!@BhG{ za7Zi~Yp-Jwplmvy(5Q4utqzjb95ai9Qx>s(W!V9`E5DoyYeydm5K+Dj7&&t|11jfVR zKi|8i=w0T&p4`Da$=OQq*XuX-sITo=!1z#V>8rGsn#PYHLyFw-aHPqTC{xzE_(h`1moQ@*De1&z6q+(~>O6u|iA^XyZ?fD; zl+sXtjgE%-3599Vj6sb!g{YKE)Fps4JuPyT$kdgAz8>)T zwDFCjD06U;4AmNgY>T;axrWPot7@|~Y7M)nb~kM?6E9$jwve(6*(@MTDt_L=~@}a=P&{l*Cc#)2yEIuTALkG3b<(9PXc)C-FuvI z9}k8TSYv0aYb@%V!!(;CwUA+18^0GfEkG{S8PwHznBJiTV{rmXy>)+46 zzyAOK00t=FfCLt3;DHDx7|Ct}gQ+_+1b|<0_7(cqpLdx`->0N5(5RzhzKWl$gl>w=eW$)a9Up_n{+4K| z^%YADu+Us#X*-t&d)lnI(ovPDbGl*Zwb1lat!szsnkOmWYJnQ9+IA)lyJFG+z#jAs zv)HO)BSJ?6(6dx z0;P1Ug~&__(b~u8?i&X}0sot7$xPycGP)$I3-is7JW%hGHRJ5FN*Dhu^w3tdO!U!6 zYnt@ZO!H)P(@_6BbJSFSH#GwkfvNS@TzBpD*I=U%uftWBeb&{=nyq$(PXp2O+HeEa zc7sXDX!qTC=dJhNdwd=Y_BR80tfB zrSb7BFT7Ffqt|})9i7{K{x{#hGW>wTUs>cQz{S-sIr4HJ>;5Ob!3cmNVBo|HAozql z4Z>A+QNjZpcozy5tpykiniRS;!MAy#gbWl`@G1qb!mLIcmwD6;l%ub-iGnjY@F2Fl zB}3w;NvKi12Ps2 z>H+4fW38HHJ7ayKkXrm9vnJTcXVHLLef*0#FlZlGm9dCxoa6&5`7%t#uvho-WF%@B z%0*K0KB?kX7l&mlSQb$^SEQC0p%}?!nNc)y)MO8Nskj>|@do;uMHY8hMaEF^jN>a; zCO39W8AK*y3g81_0{Ot=yzH5ff|CTh>Bz>ptC+fa!Mt>VkBZQ)gyl4%F~JE!b>0e( z#B5VxC=yRJdJHe*w4^-CVaR?epoT%w$6U;!kG4bwAFgc~jy?W?q8{)K zcnT6xos?sXW5LH-!M&Cc^=R{$noOls4VLne3OjRN5FVCOAwHF5hFGRnRl0?%UGqy_ zwc%K05*f6GEJ(OAvv!@<3t#W+|Sj%G9yuu9vc%?;O{i?PN685mw5h!98dy)hI F06Py|UV#7r diff --git a/site/tests/images/ex14.gif b/site/tests/images/ex14.gif deleted file mode 100644 index 2c927bcd36c3be793d95401c2d884de2cf3cf6c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1131 zcmV-x1eE(nNk%w1VGsc_0IC20|NsAhfPer10KmY&KtMnM0000000000A^8LW00093 zEC2ui01yE(06+u(2)Y~mFoHnCkT~lttJTBBjbv$_XsSkpW41~txGhDj_yPkmUEL*t zC`T+BkEwz1GyqbN$EMItV0Blo&Q(kHegn@q}R*EBehb4R)l9M1y6Nr6=kPk{AS2>lASDIm?n2C{|cCL#G zv8)fVjfD-aBLS+kzQ4dyz`+%Ik-fvo%22|lpKi#*j|;BNqRZIXTDp6%oZ5j{-zmJ{ z<{Y=Iv*!)t?CabbrR45JuJdPU6zlAp{o)Y}QHe7u9Se*4K$WJ?JoDAa2KtO=S zix@2$YcLA`MmY{UdW7K>f`T!IMw*D&$1#pT5~0eh*vO9Ns&g?T2;(EiLX(M!2wadu zvqnV}AO9)sClscQA(w#C>e)1gCaG1IYSlJPg+8rcOI+GY)>qP9stlSt8!kuAve>4v z4T|#BgRJZf;?04o7F;N$=BiQqH!rt%8utF`ns}o=4>ogDmBKG?U2O0`>7mnCmmHxz zBQuaXWk+e3qa$86vWW9)vmSWWDAq4CpctETVW@n_gO%7eB?=P0a9C>rj4eH-M4LHM z8zdmNqIs_(@^PL*|6ENPKnr6=@2O5EtSaw4uX#jEgcyRg4E(%VTK}u(2T;hm)9M?6 zZ9-iCW6egNJ;t!%hahYS2vR-m6=s5dv zP-5U=Bqn+1#g*WMX60>TpcUnp0W~?}XlB?4As2Yj;eeUxJqcz?9$=VWEI5Kg=YS;e z_+|+u0z+6gpfs3_K~s7akDzbPqnH|chGEEiI6aD|3GvOeRb-XCVHTq9ovBPuWcf=V^2mOt{smo65w*q`RPa%on!KWQY)rE(5DCwo%$euIP*h%yGRc^Xq>9 z*x6y^J}Xsoftub;O4@;dBqWe0t6G;)Mm8bK5NF?(Ywo$+#3mbXWuWUWx(o%|wsxf^jldNV3maMTdN)H2$hASH z9K+R$4jw~%q=c~#83)OqI+c7`jAHup;4?Y8Sfr={$zw6VILsy9r&ZcZ;*yl^+#*z? z4pJA+cHp_FaX=`hSi!8Vrlp%3BsuJwqiPM2tfNH|^Pn9VT?ES%ZpOwI)G~(U8P+sW z2ez)h4Jg=q_F;ArSl7Y{j%u+vSazNHyJl=0c%8R{l@Y2-vPjS=@Nh|gz4(_fFTQ0B x9Uv#X7$SR_4EdIqgV}csR7ZH<9<(x9`ksYi9`)E0wEp^tkluc(?n5R306TB_3mE_a diff --git a/site/tests/images/ex15.gif b/site/tests/images/ex15.gif deleted file mode 100644 index 63c99884e1e21f3b16780ead3d1599a4f79dd26d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 175 zcmZ?wbhEHblxGlQIK%(~2M!!)XlVHV|G$HS16Tk=DE?$&WME)q&;fBkY8{wMEOy03j7yT|r<04!3??P4u(+o6){{$>ZE5Z8gR-;qZ&qao1OOX_XjPPp&!GkSf3|(n9cZ&y3d;&4%>a591{pv8>_jX?dZV z5amHEFAqWxV;BKKax)@T89!%P1Avon9WRbe0bmh|3Lu#-TX;-7mZU@|p{OmGtWbwV zBCm-N8?iVhuaYOLU2sED7PYz#cdvgENE~%_D~V=Ab-W+Am&b!Frw|02lhzl}UA|<; zO(2`t=7{2d$Kvf6duP$vRO_hzNk%w1VOsz%0KxzO0002Mz`%fjfdBvhKtMnM0000000000A^8LW00031 zEC2ui09ybr06+u&IJ(S1BDD76yg2L4Zvevfg-?LiV3SbfieLQn~l4)0$;yO zP|;fyi;dPsDQmg{0+KMM88VOqtaB>^NS0r&nETmf%H#A_CB?9tkimm0mw+T@3PA#s zhK_U#Fo6?;PEcPK3W#!wFCI0%@A@@D;Tv z6F0{C=}c+OTgDp3iJAw&B&mQwSoONKkGHq~2EwhmWR`tcd}}1S3fGR}BK6vC8l`q4 M}*4Z`ZpyZ>M)jt~H7!U+kPgR$fQw8|{mO9};e*8+qA z0T6%?2t`nD5lF_K9+M~#gj%myD{Vm#@SH+01(|(F%jmRvto4GG0OwRAd}gb~PqMfq)!*Y-fTjnuvK3FECS^1D~9GqF5M3scED%mTYL4 zu(PzawzIM&TaUGxal0^Jz6zgBnnlBh11w^r%sDWn&eFHlB#f`NjHNgN+fLtc;DkMo zmKZsDOjYP@f7Z4h)cY>2$8~Ch_G}8qyO)f#|7%-aC<6s9rgzf=Dp^sRR zBTO_b8c6=IU>S!RIeHvfP!6bvYd|)@Lu7@kZ7r>I1C%6%NO~1XY^ zCgo2F3s(|q2WbREMO%8Ni-@q2zzUnZ&7ey1gVYJxx_W4p_2h`MWp64H8{+GzDoIJ^ zbjp>j-AX`i>^iDuP}V#&hL~vK_tdDC84&+Um#537nhAkqReN_0m6#8-f}O-^XoxTO zf&gq_DegZuhCGd~9Ab41ES$0hX~xTdgb)n?NaLtlB+EE6ZWA2y$WZMlW;VY~!kY8AU2!Qu_t8zei(kC zKmM-m^aWT=ZorXe-3anr;9XG+yl@~`)V(F!4$laP6@<;0)D&oQa3xqIAV#7VhuYDQ zTUfM3NJ2#^9=O{TJ6(Xmc69uKo-$>SsF8|cye7g^=Rx-(Sb&WpQj8k}a-(PV_<)^G zc~KzE7GXi+M3ilfha6^D2I<@hIPh1@bPN)ErBhB?=ntQ@CWRZ+%V`3oP?DFTLh*Dvqa)}-`2V_mO#KWb9!Z^f0X0@rt zrX5jv0;wx>^PY)%09xszovuNR3&D|A;S>={Y93IrK3Hdh^!SA4OPF3U6N5E){%|OM zWbRRfpmh!rq$2aQXlz|f`iUmAARx&Tp>cjXEpndhDqe?r-6JHoYR+&GwFL%8&YbkY zhhDtG(uFQ^d*K8wF-4xa4!#qx>!!VYEyy08*X`TUaZ<8-BOnC7@$bR(=1ZD+CR}N* z20-qh4vz?ZiKD>qS|^;Zthtre9I7SLtth12tbt!}aX3|57;bzz;hjc?G~tS(4i!Q7;QQ6p718cY$(ucFQpt7$S(2ah~LD!HHh5mc`)=`5uICTrn5w`Y5zS88|kO;De{R z5FVxtmIwQq*YG6`2xDhR=A&qIy!px_-1r(WK&JqR2O*k>3&2Ca`r&8?3>02+kf0uC z?5AzIi3|`hs1RQj(126W9@)C`uLI%kM-5C?r0_^y;zYMU1Rfx)<0|kkKf#@xKXvkI_qXI^vEDwL=fMh;alDtvgBL|f9z|9Ks e0w&OG8e(WAtunGZUpNgK;4us?Ng09!0029VJD^+u diff --git a/site/tests/images/ex19.gif b/site/tests/images/ex19.gif deleted file mode 100644 index 27b81934ec0c6cd8261c21ab33f198e4238d604a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 467 zcmV;^0WAJUNk%w1VPya;0KxzO0002Mz`%fjfdBvhKtMnM0000000000A^8LW00031 zEC2ui0A&Cy06+u&IJ(@qPIh+CExU6U2_~Yh$6##%; zZ%FJ3fEc2xNUSLV5tgvBWcHjN=y5SshGMc=P%?;>juC+jbYXzVWy0G^uiNkU2m!hH z0pv+|f`f!MTN!U}1agUi42usxjuv4Mi6CQ%8i#mTGlifYL6Z$mRZ=u5jB|@{p&Kp% zq+A$j6LYpLu^_c+ufM>-I6r8@h(O56%FE2n%3UeW($msAkjB^**F#m=o;|W8K?B=} z(7@jg;YT6m4C999zv&e4cHP+Y!fhFjv)OcFX!rpT*acZ?>NPlpA)$x`mB>gb*hh}L zQVUb1(1@9D;~$C^FhH3lBV3CWTr`#`5e`ZmkT7G)oJq502X;1p#c=t9A51mWf(rE~ zw5T*W6#M|W#I&i?r>^=zol5mhvRWT=hT0QBYcP3UZFUrV!Z diff --git a/site/tests/images/ex2.gif b/site/tests/images/ex2.gif deleted file mode 100644 index c0c54b45b196ba9859b0cd51ff6618a847f2e25a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 163 zcmZ?wbhEHblw%NNIK%(~2M!!)XlVHV|G$HS16Tk=DE?$&WME)q&;fBkY8{v}EOza2 zYUudckddq<^kD;^a_$iZ#urc5N*>)Pv0{a+G{Zce*-zg+;GN2^yurt9+pS)XJGM^E zw+y%@EL!HesASg#$DQ_V1)>+$lsta1q-?2?WOQWMo#YC`RHxc)XWdz%)5V=K{X)6C HIT@@03~oB` diff --git a/site/tests/images/ex20.gif b/site/tests/images/ex20.gif deleted file mode 100644 index b6a137509c40601d26ed847a70a3e465ddcec0da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 144 zcmZ?wbhEHblw{y#IK%(~2M!!)XlVHV|G$HS16Tk=DE?$&WME)q&;fBkY8{wEEu4(x z4xIE}*y|@t}vj1QxI$UX<=sB)zI}m^?&$I^vL_Gmr$HW+* zE+XI!7sWv!z~GRC3a2F*d>DVN0DyTMP#fQ$&kG$~y9(_VeHMeuNVs_%PW#~XIRqe= zXvY`;m#4Tkw%k=(dqsNaR39V730LV8b=17G+;*A@JeS%VwSr>{)5t=YJKw8POr_Y}=uH^$t zwCJvmMn9?p2~Km;MGD^O|rEM{LK7Ll6*&hFU-p@eVFFK7~Y* z4w_O#j3e;C3>G997f5j2C{ziB7QAy~Xe2;+kSQ)s6B$CnO!oqnQR2p*2*xb(2n-rx z$-qJjX{nr$LvVnDDufEk9+>bgF;q8^Kp_^Mqqte5m;h;3#u9NgXj_phmXHAqaDqS? zU&p*QhLc`k)5AGv1qWydprVoK8*Iv1TPA7Nke6|d%u1_1iul?d9&qexoTLSD_&Jaq z)a1k7Z(?-{%&U&k1Ii$?MK;Dgm83*$tJsi&tOlWKCs48GQ1l?KBeuX9N#rjoaI@cw)U-#=f-u2VFsdRU3Kg-`A_y&!ymE4PI#d1RnW$k& q5`!hZJqIFg>uAzRW5qYO-Rt6aS>7^!{4wE(gVQe3i8t;+0suSublkN7 diff --git a/site/tests/images/ex22.gif b/site/tests/images/ex22.gif deleted file mode 100644 index 207568a2ca86a199eea5e05f0fd36aef725b115a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1039 zcmV+q1n~PuNk%w1VV?j|0KxzO0002Mz`%fjfdBvhKtMnM0000000000A^8LW00031 zEC2ui0G|L+06+u&IJ(^a0=(Hspg3zSaBKmwjby1vgP=Y^HxO$hT&Zi`7z)v%(+@hF za0mj>h{)t1U{oTR7N>L)YO(;)>9l&B0BqVY@gp9R9p@#?@m-|LqjWoSe#1RFJK?7g z@Hb#(fpI1QU1Eb9Ya2`ejw+Cml9QB`mY0xmn46rPla7vuccY}GrY0y6qCgZe6Oczi zuzf}nWv^f#K*`R5{7eV7tJ&w3V+GQ4Q(yH3sKq0-rwM3o{SR?T5l;v{rLplv z?WZdgLa(`Tv4ZJ>lr3|T@CgoT4KzDdexdp^B|5IfTG_DHXkgZ}Xw#})o8;FEvuxFf z*h7<86;OEd>c#sK4Z6L6^}@9nxNthK?+gbX%%N!7zAM%C&1WTUi53~{VHS0gK|;$T zK8F*%tH^`Oq>)9ob9!vuQ_U)$IFvAU2e75;NI>edu{;d&=zTG(*t$@qPk)h4^idZh z&;Ho`lIYh5Q()`?o?3>uLBU44n3UOin+@1Ogb>!((-IbTvjk>pp{Id{^~~qNAdbO= z6juu!VMBzY<&Z)yOC=apeLiKu&q}X_^~!(OL}Q{ttHfYoK197&22}omM9Yjs(FBYz zXh2e8ZV{ko%LKqMX5N-ucIoApVETYXdF4#WTopf*nIlYSYNVxIe|h%^1ak7VWWG=U^s*Nri__2mBa?4^*9>lq&rf&RtruV3Egwm>`4u$=CRgK zO2SzRgr=mBRw@WTIKomERdQfOd%4XjLmrdKf$EVqh(W?5Zl!$v2|KTJn_Yg1sYzW(E!@; zTIe+U@yH~XZ1Tx%nMqZ^3m&5}T7Lc%B`UOwiYkEuhvqbR%Qd*|^X|Qd}a7 J@&X9}06UEU<+%U= diff --git a/site/tests/images/ex23.gif b/site/tests/images/ex23.gif deleted file mode 100644 index da8f92e6f1229d139d4a4afea8ec960cb7302afd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1600 zcmV-G2EX}7Nk%w1VbuU^0IC20|Ns90004l1fWW}OKtMnM0000000000A^8LW00093 zEC2ui0M!6&06+u(2)f+3nPWMW82S|DhH@U5kDwx6ZOoDk$L?z99| zuX4K#0=0<_cG0mUKvxpi0uY$Zoo`aScof6!qPuZ!0@}qAL>9ZxShx92hqJXhR4!e| zwI6eJe|;B&7J)2i0BCU>NETNNjUrt)lM9iAl6p#Mh9O-i0GF7gHfW4)Uz#PWtQI7% zBCbBDsj|4ay1Q?-pS-}b0-V7cN42)5#mi!dki@;pYJ850Xj99Gzs!Kt+#$}8T}RN_ z0@B|P+YRd?;S}u(h^aCnl5+W~)i|<}2*6w|*3s0k zQCHBPGk@k;G;~x?3~2^jRt?TVj1<{Zh}JK=zI|v8)qzJbH^7U?2J|YI^E7Xk z9d|Cw;D*##K0JTjBMqy_K?4|5E%(ZF zqXfmzeq=d$2VYx+WDj{j={15$mw8!2k@}TsW(;JWspgttVacXww0sk%A2q%yQ+wqR z;-V5Vwt0)4n|a6#kZA%s*H1i(#GzX%B#M$r;2pXL08$N>U{i{O*x_UP0lD4|bM^?1 zVlQnEg{;4hiH=17 zH6ZI?f5RsG>TqT_A*&^cKx<5&($Zn2KzL%nZMXM8_t&_;}vaIthEBTJJ0xAFI2p+r+6pYY({PyB29bEn}U%nAbtig$UuJ=W|hT*dB z7syUiMxRn2r282qy_AbjG52|Y_SOiSJKFf0=Pvb(lqRcW}b>l6@CF6RBv2! zw|b+*wtIW*aCuDvm7KRGlDASXex*s=vJw=#7xgCARKEKdno|6+1X`$C$ygUU5X+FyIUi7?{^+xDbd&i9a38HnWr$_0noogqw71(nm zGFd*~=jJTRkRY=U8ALHP7sp2r38lirpZBC-JT%qG1nt8G_r$=x?>*#m@Hk-H637a5 z$s$yLb6FiMSdIDNz-esh9~CI5ClNBmgQ*F~{+O}C%$cx3C?uB*^CH0++K@RlyrB*w zm%|$9wxG*jAjHyae{U%>GTD9aoj?Du*JDt(Wp`Bb3-hQNTHux zA&Z;K35YUPw_?z(ObaALrT8PpylJ74z|aQdSV6}R&Okn+a@;0I^)%6R@>Q!U0@`d+ zO2?cs82kwhCL=eSK7Vs3eKL*a_4t8w*BV!ixf zCD|trWJNNP#S0Q5pBO*g&5nZ8yq>PWg3Bw;D+pjj-*%{|AzPY}Z60yL3q^sOe0j!= y$+Q@9P;d-cUEzy3W5YIu7)iE}ESmYG-at*X(1dPqn8I;rnP6oF4|gsg0RTJDUG~@j diff --git a/site/tests/images/ex24.gif b/site/tests/images/ex24.gif deleted file mode 100644 index 4f165bd4fefb321bd0b43cc792def8281fc3c390..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2003 zcmV;^2Q2tUNk%w1VORlz0KxzO0002Mz`%fjfdBvhKtMnM0000000000A^8LW00031 zEC2ui09XNn06+u&IJ(^a55P&Qy*TU5yZ>O=34&;v5+$S!xwzp0t zi4f?)dPrPy$!t2GP|z`&q*1Tftab~Taz$3h4HEv083901_{*LbfnV;soqx&-Z>voQ z;roDrf=z!GdV?8-h>MJkO@~o-hDsD^YiMc;nIV>9ERtEB5CH^yjy(iHcMqv~s$!-l zX$)$h19oq;I-vD4=d883<9rJ$lKiAX42h?-s9xk z!Qg$2$-s$Y|@>lNR^Y{2$_1y6J{{K?I@l(-HL@o`%3K9(HK-4})wiL9|gybQ> zMi%u6yvY8shqz8@vhe^3KqMfNCOcl3NMMtbjE)pCc$Ly4vL72&UeiHJ2oIQzWa=Dx z5h%n9af%qtkdzIhrb|1*5NadmsdT_1{5)j!(Ubs}4qgG@pi zZ`D<>HV)}td49Of0T;*wi_|WF5?f<*;M?SarRhu>FcaIjgPY@x2)OX$j0yuXj=Xt0 z;&h!$m#4fB^Xb^JRHyS1+V)Z2p)-Lh9^lj{-?@m(I&+O;gI*ZFHcgxL*-UU|z^Aj*9d73k76v(T|2VrzVO z*F@T3Xq^R>rS<}bEz$x=jI>yW#b?umh9d~2@r0UFTir8SQ(pZih+8V=ql}FV&2wFL zQ1+GN7f(iMWfBc)QRS6f){tcukKu&L4%Pse8iZMt>C>5N-WK8j2r@W9o3IF}Aq{a} z_a>ZYy%!3eVPP}n2XS6QAP8-i0MMF+3be zBCC=S@($rbSu(*IbFA{d9z)U3$-j+Uo6PaR%tW~^udFjdEk8l?&R62>Gtfk<(6bXi z7oDBZNLQfd!%uIpDQVY5t-;jBFuBc}0=k9e(E(4eCt1sEV%*qDiGoK$C!j5a+R;>E zF;h13GPMSYI#8L}O$Mi!1O@-S<{lH!EO@iAP&#)xq}T`ND}Xzfw9?c5F&(ys;fSP*wbns8S;0Z3A`A9xx1}6|e<`xQ?+J z!-XAIDmbBW7B-;u8c$uYfh^L@S)N3rdUu^qebW0&*{FmM!w?-NUla0X>S6V>PIQgu=KZUy! z8v10$NZwv;w(S}oP6D$u7tn-0vPVDKr! zfEogn3e_J(4dYP-mef@&m8soC!Be5?#|FqS30Dq){n6uHJu9&e>92ka^$y{d$->8t8mm-f}74)#=S-9TQW09Y)F)`r?iQ1ZO~Gi zR@qt!witj%>%6L22wJIvodl!UI#|uU68BcepUu@yDVi`pVv2)w<;tFT#9Zw)#B9CA zf(#i|Tvz##c0~9^cXLF;@D8DvCp`gp!E)YMI&>Y!ya6fL8&Z~4HAWR=4t|e7gZ{ws zdm-4b9Ck7UN|~a%imhSw`B_TU_!vZ2GtilfVq8&xY7Q}sXaQRqQ@)ATG l&W3oP<3X`|3H&JpWmv;#h~qz=;T{#+7QM-#ZL1Oh06Tb_#uESl diff --git a/site/tests/images/ex25.gif b/site/tests/images/ex25.gif deleted file mode 100644 index 18d1498066aa88ca029043f12031e6e21810d130..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 145 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 X<(JXImQ}=`e-T4HGi;^K&FKFDMIlZx diff --git a/site/tests/images/ex3.gif b/site/tests/images/ex3.gif deleted file mode 100644 index bf10c18c1417f854d9a130b59182c9d0d468442f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 349 zcmV-j0iym#Nk%w1VLAXW0KxzO0002Mz`%fjfdBvhKtMnM0000000000A^8LW00031 zEC2ui06G9K06+u&IJ(^aFfu_!c$ADP7wsM)ECHa1S;L_hxQ*_B5@u}QI1a!$7*IQ% z2+)F5Dg;!e_z3o%&_O_hsYQ+%C51V$3artv;&kko9^szZ(qJ@Zi`^gfIXm!5z#Kj2_Zh5yqKENm#=JZ`=;2 zH`QI(#RO9@yqPfqR3-0G=onPQAbBU@`u_kKL>ox3puvL(6DlMauwg@Uq3$)Q=YgU) vi+{kxvq&Ru)`$@_5^==%g%=iiS}aKDxa*n?iIyyyyS4EK%QG-zBme+Ad@qXk diff --git a/site/tests/images/ex30.png b/site/tests/images/ex30.png deleted file mode 100644 index e8f75cfbe178ef9cc4abdca0694f13692ca10b6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3392 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 Mv7Ch2QcebI0LoHiC;$Ke diff --git a/site/tests/images/ex5.gif b/site/tests/images/ex5.gif deleted file mode 100644 index 4c3a7b9ba7da59054b113958102c6206c74c3d7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 235 zcmZ?wbhEHblw;6hSjE8b|Nnmm28M=)h64u>N*{Xe|_?xQz`+2rUE=irJaku1w)$>z5uY+&4T|cIos;9#Kd~Jn=o@K3F z9z(NZ4mV45UH^oMlRAQ?PMbb`vO`r!tGaEHpi(23AA^vWXOu#CPFXW!su{1b97{o7 gySHl9hB@=3y$prBox~)P%H%fpFY7-b&&gm70Da?Do&W#< diff --git a/site/tests/images/ex6.gif b/site/tests/images/ex6.gif deleted file mode 100644 index 679f278f378a2ee372f712146c55c913a2f710e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 906 zcmV;519kjINk%w1VcY}*y>t-FyZ>M)j${=GWvZ@E5U_A8&#CY#Cxb3K<h$sHv8#u2H0` z8a%BSs;{^yo23@Fxxc`tvBAW}WCL@QrF#;-#?KSZ5pd89v(?xt!`a;3$9)T$3&?)p z4krTX>g(wci!Si-^7Hid_V@Vle%=%B@VW1l@f%n{Ai-a?4tg?UP=PrL2^C75NO8oI z99wQktC(W{8%KT~KXwZ#vgE;yCId0ta!pbTd79+yYrw9i&6_xL>fFh*r_Y~2gYGni zOp8Muy_ls06>q7C00bgBeMWLBv8q;qVa+;iCf7isG)VQK^y?W)q)?tKYxYFYZO!{>FWAaZ#`rwC|aW^EBlz=fb@>YA1HAohMYG|aMeH@twVHH}8cHv?gZfHb!9?}3}h%$^w zA`B*;m|lP?wwRuaA}oT(Q|iI!fNuiq0$+_bhO$Tk&3$f2+2ey*Zkd8V{BcB{m*aIvrZ#4tSwf0xa=>PrZlnq4j#0Tc=bhT% zIfR@x26x+Vy6JhNX$-I!Xa=w)s_3HmSg2PrESX~;pDkXbhXdCfDrliMFeeuWl)|YX zRBk*1<)$70imDu1uKGu-u0jNBtP-e7YX`R8s_U*)gz6$xZ~2B8t)z0oDUZIAxRPN{ z#$n3ZJg+f&s%Dnn#_3@bBuip@FId@vj(f?j`zZq>0UtF368dl=|kci gC#<~2rq;(y8%*n}Bzag{8(g!t>o30RNRR*kJD<xc~qF diff --git a/site/tests/images/ex7.gif b/site/tests/images/ex7.gif deleted file mode 100644 index 981d6a3221b44d18e99fb8d1d02496f9eddddcb5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 739 zcmV<90v!EENk%w1VaNbg0KxzO0002Mz`%fjfdBvhKtMnM0000000000A^8LW00031 zEC2ui0LTDU06+u&IJ(^aFv>}*y($pQyZ>M)j-3FIXsQl^u)c6CQ-G_O%(>`PJO99- za7Zlnc*dl1$!x-E3tYn&X;}pX!c`D}1h(L?cuX#v&uDPh$%X~iL27$0k}9AXz*;Wh zx8HPuf&)BAR&ZZdHHQpoT!WC27#kV{a4txann#nX6B;|2B{rg|O&bfWJ*cWl zp|P}@v$ZQ4Ediz+ez?FPT3otQu&=?O$H{+|EO;Nk%+nTBUk=NC*)P3S+tk!wU5^8R zEZN=Q>X88L>w&lL@-Xr9_9*rD`uj@K{K=u9ks9Fa0hlaX;52B*u%W|;5F<*QNU@^D zix@L%1fc#Uj|&?}(i!^~q6GnwgRYPyl5eF;2rXaAJa=-}%pd-4rqZ+Hn7L}-bb5jY z1y)XjLBaj}cNAMvYE6Z*iJF3{)Jdp9T~VmbLLx_C({R;k2gkC3$lyJ_N?{lluVY7P z>1Y9EBZO=vQL%D2E}^{p5>@Hb1#KR{GZn2x4D=-9#C9Lciz#_>K+t#k&a^;JWn`m%htmEMdVd=1OL zzpDTKqP>=tDYKae-w1T^B3u;d8K??<@0HhJgta(W3w>GyD3gT;b|nOdnE9~ODM4UJ z&Uw5<0b4W_b_fD5aAdInjCaIk(Kh@2r{jrI*#V=CYk~Lz7A?NyObaJ0v*H9oRxqJ@ zSvgrG2CFqGRE{y|w&VoXxtJv@hJiHW6^q!!AQ~Ea*;YBjI8e|+YC@vho5X1&UYx+) VAX}Gs4nYhm&hXi16DTDB06W*5SX=-A diff --git a/site/tests/images/ex8.gif b/site/tests/images/ex8.gif deleted file mode 100644 index 016ddab00a2bc7a2c067cfe0746575ff2e990dff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 416 zcmV;R0bl+{Nk%w1VKx9V0KxzO0002Mz`%fjfdBvhKtMnM0000000000A^8LW00031 zEC2ui05$+J06+u&IJz3dFv__cT|iu^1qq4(Y*My}WU5}MxxVlKWFzUaS_lE)gkrsj ziSXd$B%cf6I7yN$G3RC(s{$jxST?|`{%+Q=aK;pyWuxrG6lfQB8!$tCWwa}0nNPs) z2NhHoTxTgBaess&G^yhw<4k|kw>ST!icZx8~1d4?23FRn3M!L-Yy4cQdK+7OKq#@{~N zA?AX;tsd8cv*Rlo0B?||+1~M~yGlpUF}J^9jN3;6o`X*|I^ZJ5VuUn?E4YY22(bj2 zij^*6%%o;M)j(|{^!lVc$BmiS9&vf+G_)_Bc)pI+M zgCiIYiXl~Q$!wBZwVw_42@XmuXfu%QdM{kBcuX#vk&Cl>%_dVV+AHN^odF&LrIQ(; z)b|-EZ-5wo0CN_46#;{UjyZohQh|+2kspc{Mvt7Go}VKGaT_V1rksk$5r4is0VFp6BUP}jx{zwR_(Hw9g+gn$SfD+y}Yvy+qxaa*+$L(d3Gl=v$M zA>GKMB5>v`s%(c$4T93Z$b_`2Bc(pw;rwCKs#hmn8%Wd%mL*b(r_cgoH0Px{I#z6k z{c7hYDw=@YDv-u@7hOVFndvZL)Gr^BD;5lmV9|!HWqSWM30w$9kir?4ykKz+#8ZxD zC5s-tk^@!JsOd&#hBq}KW34-dp^Tw%6}7JKYP35ow6#9}fb!1WWbP^2i^7?R8+tYI zN5)MdkKi2f;N;J1#{M+@Rp{$0zULXP_+@n*pF?_!4yrr&6NiEuezGB%F%j$?!DfNm z)BfyYG<061l-Xd0}p!e5fBo5U=(=`9>?KQ22K#h9E*7e z#XkIf=*5H`_Trv(^c(?0UxCPY-F7WX_M(mAOmhv6BP1vW7;O|;r*t zosj~?jya07<0KQeBj2u&p zdf{nsngo|-m(rZ9wmRodG(xq|3$E5mOraG33V|NWkXoq*RLVoagZ*_%ggh^yEvZ0- v4b(acv%h8#>;y$TFb{}4z@v<^rD4KtwBW{YDum&d%Lz?=nyYRF2><{)Ky83) diff --git a/site/tests/images/exponents.svg b/site/tests/images/exponents.svg deleted file mode 100644 index f1bc8c0f..00000000 --- a/site/tests/images/exponents.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/functions.svg b/site/tests/images/functions.svg deleted file mode 100644 index eb73cbb9..00000000 --- a/site/tests/images/functions.svg +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/gather.svg b/site/tests/images/gather.svg deleted file mode 100644 index b9da20e4..00000000 --- a/site/tests/images/gather.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/greek.svg b/site/tests/images/greek.svg deleted file mode 100644 index dcecf702..00000000 --- a/site/tests/images/greek.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/kern.svg b/site/tests/images/kern.svg deleted file mode 100644 index 663bc3bc..00000000 --- a/site/tests/images/kern.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/lap.svg b/site/tests/images/lap.svg deleted file mode 100644 index 96c9fdf2..00000000 --- a/site/tests/images/lap.svg +++ /dev/null @@ -1,220 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/latex.svg b/site/tests/images/latex.svg deleted file mode 100644 index 3cab59a1..00000000 --- a/site/tests/images/latex.svg +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/mathop.svg b/site/tests/images/mathop.svg deleted file mode 100644 index 5cd5fec6..00000000 --- a/site/tests/images/mathop.svg +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/mod.svg b/site/tests/images/mod.svg deleted file mode 100644 index 50fde308..00000000 --- a/site/tests/images/mod.svg +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/newline.svg b/site/tests/images/newline.svg deleted file mode 100644 index 5cf3127a..00000000 --- a/site/tests/images/newline.svg +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/not.svg b/site/tests/images/not.svg deleted file mode 100644 index f6282dab..00000000 --- a/site/tests/images/not.svg +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/oldfont.svg b/site/tests/images/oldfont.svg deleted file mode 100644 index fa3aefc7..00000000 --- a/site/tests/images/oldfont.svg +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/phantom.svg b/site/tests/images/phantom.svg deleted file mode 100644 index 174f72f4..00000000 --- a/site/tests/images/phantom.svg +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/pmb.svg b/site/tests/images/pmb.svg deleted file mode 100644 index 56f21738..00000000 --- a/site/tests/images/pmb.svg +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/raisebox.svg b/site/tests/images/raisebox.svg deleted file mode 100644 index 1fb62705..00000000 --- a/site/tests/images/raisebox.svg +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/rcases.svg b/site/tests/images/rcases.svg deleted file mode 100644 index b7fcc413..00000000 --- a/site/tests/images/rcases.svg +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/rlapbug.svg b/site/tests/images/rlapbug.svg deleted file mode 100644 index 7bc1588f..00000000 --- a/site/tests/images/rlapbug.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/rule.svg b/site/tests/images/rule.svg deleted file mode 100644 index 0e987fd9..00000000 --- a/site/tests/images/rule.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/site/tests/images/sizing.svg b/site/tests/images/sizing.svg deleted file mode 100644 index fe4dcb37..00000000 --- a/site/tests/images/sizing.svg +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/smash.svg b/site/tests/images/smash.svg deleted file mode 100644 index d0083e45..00000000 --- a/site/tests/images/smash.svg +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/spacing.svg b/site/tests/images/spacing.svg deleted file mode 100644 index ddb3fd6a..00000000 --- a/site/tests/images/spacing.svg +++ /dev/null @@ -1,330 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/sqrt.svg b/site/tests/images/sqrt.svg deleted file mode 100644 index 240c63fa..00000000 --- a/site/tests/images/sqrt.svg +++ /dev/null @@ -1,176 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/stackrel.svg b/site/tests/images/stackrel.svg deleted file mode 100644 index 2409d798..00000000 --- a/site/tests/images/stackrel.svg +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/subarray.svg b/site/tests/images/subarray.svg deleted file mode 100644 index b874f36b..00000000 --- a/site/tests/images/subarray.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/text.svg b/site/tests/images/text.svg deleted file mode 100644 index 8f83ceed..00000000 --- a/site/tests/images/text.svg +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/units.svg b/site/tests/images/units.svg deleted file mode 100644 index db485204..00000000 --- a/site/tests/images/units.svg +++ /dev/null @@ -1,351 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/images/verb.svg b/site/tests/images/verb.svg deleted file mode 100644 index fb31aae7..00000000 --- a/site/tests/images/verb.svg +++ /dev/null @@ -1,271 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/site/tests/katex-tests.html b/site/tests/katex-tests.html deleted file mode 100644 index 77c04e6c..00000000 --- a/site/tests/katex-tests.html +++ /dev/null @@ -1,382 +0,0 @@ - - - - - - Temml Screen Tests - - - - - - -

    Tests from KaTeX

    -

    This file renders examples from KaTeX’s screenshotter tests.
    Images from LaTeX are also provided for comparison.
    (Images come from LaTeX Previewer, thanks.)

    -

    Accents

    - - - - - -
    SourceTemmlLaTeX
    \vec{A}\vec{x}\vec x^2
    \vec{x}_2^2 \vec{A}^2
    \vec{xA}^2; \underbar{X}
    Axx2x22A2xA2X_ accents
    -

    AccentsText

    - -
    ıˊı˙ıˋı¨ı˝ı˚ȷˊȷ˙ȷˋȷ¨ȷ˝ȷ˚aˊa˙aˋa¨a˝a˚AˊA˙AˋA¨A˝A˚I˙ I˙e˝ e˝ııAccentsText
    -

    Actuarial Angle

    - -
    a_{\angl n}\; a_\anglnananangl
    -

    Align

    - -
    \begin{align}
    a &= 1 & b &= 2 \\
    3a &= 3 & 17b &= 34
    \end{align}
    a=1b=23a=317b=34
    -

    Alignat

    - -
    \begin{alignat}{3}
    a &= 1\quad & b &= 2 &\quad c &= 3\\
    3a &= 3 &\quad 17b &= 34 &\quad 400c &= 1200
    \end{alignat}
    a=1b=2c=33a=317b=34400c=1200
    -

    Aligned

    - -
    \begin{aligned}
    a &= 1 & b &= 2 \\
    3a &= 3 & 17b &= 34
    \end{aligned}
    a=1b=23a=317b=34 aligned
    -

    Alignedat

    - -
    \begin{alignedat}{3}
    a &= 1\quad & b &= 2 &\quad c &= 3\\
    3a &= 3 &\quad 17b &= 34 &\quad 400c &= 1200
    \end{alignedat}
    a=1b=2c=33a=317b=34400c=1200alignedat
    -

    Arrays

    -

    This LaTeX image does include dashed lines.
    LaTeX Previewer does not include the arydshln package.

    - - -
    \left(\begin{array}{|rl:c|} 1&2&3\\ \hline
    1+1&2+1&3+1\cr1\over2&\scriptstyle 1/2&\frac 1 2\\
    \hdashline
    \begin{pmatrix}x\\y\end{pmatrix}&0&
    \begin{vmatrix}a&b\\c&d\end{vmatrix}
    \end{array}\right]
    (1231+12+13+1121212(xy)0|abcd|]Arrays
    \begin{smallmatrix} a & b \\ c & d \end{smallmatrix}
    \begin{subarray}{c}a \\ b\end{subarray}
    abcd absubarray
    -

    ArrayMode

    - -
    2fx122fx1x22fx1xn2fx2x12fx222fx2xn2fxnx12fxnx22fxn2ArrayMode
    -

    ArrayType

    - -
    1\begin{array}{c}2\\3\end{array}41234ArrayType
    -

    ArrayRemoveEmptyLine

    -

    A \\ at the end of a matrix should not create another line.

    - -
    \begin{pmatrix} 1 \\ 2 \\ \end{pmatrix}(12)
    -

    Baseline

    - -
    a+b-c\cdot d/ea+bcdeBaseline
    -

    BasicTest

    -

    a

    -

    BinCancellation

    - -
    \begin{array}{cccc}
    +1 & 1+ & 1+1 & (,) \\
    1++1 & 3\times) & 1+, & \left(,\right)
    \end{array}
    +11+1+1(,)1++13×)1+,(,)BinCancellation
    -

    Binom

    - -
    \dbinom{a}{b}\tbinom{a}{b}^{\binom{a}{b}+17}(ab)(ab)(ab)+17binom
    -

    BoldSpacing

    - -
    \mathbf{A}^2+\mathbf{B}_3*\mathscr{C}'𝐀2+𝐁3*𝒞
    -

    BoldSymbol

    - -
    \sum_{\boldsymbol{\alpha}}^{\boldsymbol{\beta}}
    \boldsymbol{\omega}+
    \boldsymbol{\int_\alpha^\beta}
    \boldsymbol{\Omega + {}} \\
    \boldsymbol{\lim_{x \to \infty}
    \log Ax2k\omega\Omega\imath+} \\
    x \boldsymbol{+} y \boldsymbol{=} z
    𝜶𝜷𝝎+𝜶𝜷𝛀+lim𝒙log𝑨𝒙2𝒌𝝎𝛀ı+x+y=zBoldSymbol
    -

    Boxed

    - -
    \boxed{F=ma} \quad \boxed{ac}
    \color{magenta}{\boxed{F}}\boxed{F=mg}
    F=maacFF=mgboxed
    -

    Cases

    - - -
    f(a,b)=
    \begin{cases}
    a+1&\text{if }b\text{ is odd} \\
    a&\text{if }b=0 \\
    a-1&\text{otherwise}
    \end{cases}
    f(a,b)={a+1if b is oddaif b=0a1otherwisecases
    \begin{rcases}
    a &\text{if } b \\
    c &\text{if } d
    \end{rcases}\Rightarrow\ldots
    aif bcif d}rcases
    -

    CD

    - -
    \begin{CD}
    A @<a<< B @>>b> C \\
    @| @AcAA @VVdV \\
    D @= E @>>> F
    \end{CD}
    AaBbCcdD=EFCD
    -

    Colors

    - -
    \textcolor{#0f0}{b}
    \textcolor{red}{c}
    bccolors
    -

    ColorImplicit

    - -
    bl{ack\color{red}red
    \textcolor{green}{green}
    red\color{blue}blue}black \\
    black\left(black
    \color{red}red\right)black
    blackredgreenredblueblackblack(blackred)blackColorImplicit
    -

    ColorSpacing

    - -
    \textcolor{red}{x} + 1
    {\color{green}+ 2 +} 3 + 4
    x+1+2+3+4ColorSpacing
    -

    Colorbox

    - -
    a \colorbox{teal} B
    \fcolorbox{blue}{red}{C}
    e+\colorbox{teal}x
    aBCe+xColorbox
    -

    DashesAndQuotes

    - -

    \begin{array}{l}
    \text{``a'' b---c -- d----`e'-{-}-f} -- \\
    \text{\it ``a'' b---c -- d----`e'-{-}-f} ``x'' \\
    \text{\tt ``a''---} \texttt{``a''---} \mathtt{--}
    \end{array}

    -

    “a” b—c – d—-‘e’---f“𝑎” 𝑏—𝑐 – 𝑑—-‘𝑒’---𝑓x``𝚊''---``𝚊''---

    -
    DashesAndQuotes
    -

    DelimiterSizing

    - - -
    \bigl\uparrow\Bigl\downarrow
    \biggl\updownarrow
    \Biggl\Uparrow\Biggr\Downarrow
    \biggr\langle\Bigr\}\bigr\rfloor
    }DelimiterSizing1
    \begin{pmatrix}
    a & b & c\\
    a & b & c\\
    a & b & c
    \end{pmatrix}
    (abcabcabc)DelimiterSizing2
    -

    DisplayMode

    - -
    \sum_{i=0}^\infty \frac{1}{i}i=01iDisplayMode
    -

    DisplayStyle

    - -
    {\displaystyle\sqrt{x}}{\sqrt{x}}
    {\displaystyle \frac 1 2}{\frac 1 2}
    {\displaystyle x^1_2}{x^1_2}
    xx1212x21x21displaystyle
    -

    Dots

    - -
    \begin{array}{l}
    \cdots;\dots+\dots\int\dots,\dots \\
    \cdots{};\ldots+\ldots\int\ldots,\ldots
    \end{array}
    ;+,;+,dots
    -

    Equation

    - -
    \begin{equation}
    \begin{split}
    a& =b+c-d \\
    & \quad +e-f \\
    & =g+h \\
    & =i
    \end{split}
    \end{equation}
    a=b+cd+ef=g+h=iequation
    -

    Exponents

    - -
    a^{a^a_a}_{a^a_a}aaaaaaaexponents
    -

    ExtensibleArrows

    - -
    \begin{array}{l}
    \xrightarrow[ab]{ABC} +
    \xRightarrow{ABC} \\
    \xleftrightharpoons[ab]{ABC} +
    \xhookrightarrow[ab]{ABC} \\
    \xmapsto{ABC} +
    \frac{\xrightarrow[ab]{ABC}}
    {\xrightarrow[ab]{ABC}} +
    \left\lvert\xrightarrow[ab]{ABC}
    \right\rvert
    \end{array}
    abABC+ABCabABCabABC+abABCABC+abABCabABC+|abABC|ExtensibleArrows
    -

    Fractions

    - - -
    \dfrac{a}{b}\frac{a}{b}
    \tfrac{a}{b}\;-
    \dfrac 1 2\;1\tfrac 1 2\;{1 \atop 2}\;
    {a \brace b} \; {a \brack b}
    ababab1211212{ab}[ab]Fractions1
    \genfrac \{ ]{0.8pt}{0}{a}{b}\;
    {a \above1.0pt b} \;
    \cfrac{1}{1+\cfrac{1}{x}}
    \xrightarrow[\dfrac g h]{\displaystyle\frac g h}
    \; \xrightarrow [2.\, \dfrac c d]
    {1.\, \displaystyle\frac c d}
    {ab]ab11+1xghgh2.cd1.cdFractions2
    -

    Functions

    - -
    \sin\cos\tan\ln\logsincostanlnlogfunctions
    -

    Gather

    - -
    \begin{gather}
    a=\frac 1 2 \\
    e=b+c
    \end{gather}
    a=12e=b+cgather
    -

    GreekLetters

    - -
    \alpha\beta\gamma\omegaαβγωgreek
    -

    GreekUnicode

    - -
    \frac{αβγδεϵζηθϑικλμνξοπϖρϱςστυφϕχψω}
    {ΓΔΘΞΠΣΦΨΩϝ\mathbf{Ω}\mathbf{\Omega}}
    αβγδεϵζηθϑικλμνξοπϖρϱςστυφϕχψωΓΔΘΞΠΣΦΨΩϝ𝛀𝛀
    -

    HorizontalBraces

    - -
    \overbrace{\displaystyle{
    \oint_S{\vec E\cdot\hat n\,\mathrm d a}}}^
    \text{emf} =
    \underbrace{\frac{q_{
    \text{enc}}}{\varepsilon_0}}_{\text{charge}}
    SEn^daemf=qencε0chargeHorizontalBraces
    -

    HTML

    - -
    \id{a}{a+}b\style{color:red;}{+c}a+b+cN/A
    -

    Includegraphics

    -

    Asphere_+sphere+AspheresphereAsphere_+xsphere+Aspheresphere

    -

    Integrands

    - -
    \begin{array}{l}
    \displaystyle \int + \oint +
    \iint + \oiint_i^n \\
    \displaystyle \iiint + \oiiint +
    \textstyle \int + \oint_i^n \\
    \iint + \oiint +
    \iiint + \oiiint \end{array}
    +++in+++in+++Integrands
    -

    Kern

    - -
    \frac{a\kern{1em}b}{c}a
    \kern{1em}b
    \kern{1ex}c\kern{-0.25em}d
    abcabcdkern
    -

    Lap

    - -
    \begin{array}{l}
    ab\mathllap{f}cd\mathrlap{g}hij\mathclap{k}lm ;
    ab\llap{f}cd\rlap{g}hij\clap{k}lm \\
    \mathrlap{\frac a b}\frac a b \\
    \mathrlap{\overbrace{
    \phantom{a_0+a_1+a_2}}^m}a_0+a_1+a_2
    \end{array}
    abfcdghijklmabfcdghijklmababa0+a1+a2ma0+a1+a2lap
    -

    LargeRuleNumerator

    - -
    \frac{\textcolor{blue}
    {\rule{1em}{2em}}}{x}
    xLargeRuleNumerator
    -

    LaTeX

    - -
    \text{\LaTeX}, \text{\TeX}LATEX,TEXlatex
    -

    LeftRight

    - -
    \left( x^2 \right)
    \left\{ x^{x^{x^{x^x}}} \right.
    (x2){xxxxxLeftRight
    -

    LeftRightListStyling

    - -
    a+\left(x+y\right)-xa+(x+y)xLeftRightListStyling
    -

    LeftRightMiddle

    - -
    \left( x^2 \middle/ \right)
    \left\{ x^{x^{x^{x^x}}}
    \middle/ y \right.
    \left(x\middle|y\,\middle|\,z\right)
    (x2){xxxxxy(x|y|z)LeftRightMiddle
    -

    LeftRightStyleSizing

    - -
    +\left\{\rule{0.1em}{1em}\right.
    x^{+\left\{\rule{0.1em}{1em}\right.
    x^{+\left\{\rule{0.1em}{1em}\right.}}
    +{x+{x+{LeftRightStyleSizing
    -

    LimitControls

    - -
    \displaystyle\int\limits_2^3 3x^2\,dx
    + \sum\nolimits^n_{i=1}i +
    \textstyle\int\limits_x^y z
    233x2dx+i=1ni+xyzLimitControls
    -

    LineBreak

    -

    Firefox will apply soft lines breaks after relationss and binary operators.

    -

    x2y2+z2=z2+x2y2=x2y2+z2=z2+x2y2=x2y2+ z2=z2+x2y2=x2y2+z2=z2+x2y2=x2y2+z2=z2+x2y2=x2y2+z2=hithere=hithere

    -

    LowerAccent

    - -
    \begin{array}{l}
    \underleftarrow{AB} \quad \underrightarrow{AB} \quad
    \underleftrightarrow{AB} \quad \undergroup{AB} \\
    \text{\underline{text}} \quad \utilde{AB}
    \quad \underrightarrow{AB} \\
    \underrightarrow{F} + \underrightarrow{AB} +
    \underrightarrow{AB}^2 + \underrightarrow{AB}_2 \\
    \frac{\underrightarrow{AB}}{\underrightarrow{AB}} +
    \sqrt{\underrightarrow{AB}} +
    \left\lvert\underrightarrow{AB}\right\rvert
    \end{array}
    ABABABABtext_AB~ABF+AB+AB2+AB2ABAB+AB+|AB|
    -

    MathChoice

    - -
    {\displaystyle\mathchoice{D}{T}{S}{SS}}\;
    {\textstyle\mathchoice{D}{T}{S}{SS}}\;
    {\scriptstyle \mathchoice{D}{T}{S}{SS}}\;
    {\scriptscriptstyle\mathchoice{D}{T}{S}{SS}}\;
    \displaystyle X_{\mathchoice{D}{T}{S}{SS}_
    {\mathchoice{D}{T}{S}{SS}}}
    DTSSSXSSSMathChoice
    -

    MathDefaultFonts

    - -
    Ax2k\breve{a}\omega\Omega\imathAx2ka˘ωΩı
    -

    MathBb

    - -
    \mathbb{Ax2k\breve{a}\omega\Omega\imath}𝔸𝕩𝟚𝕜𝕒˘ωΩı
    -

    MathBf

    - -
    \mathbf{Ax2k\breve{a}\omega\Omega\imath}𝐀𝐱𝟐𝐤𝐚˘𝛚𝛀ı
    -

    MathCal

    - -
    \mathcal{Ax2k\breve{a}\omega\Omega\imath}𝒜𝓍2𝓀𝒶˘ωΩı
    -

    MathFrak

    - -
    \mathfrak{Ax2k\breve{a}\omega\Omega\imath}𝔄𝔵2𝔨𝔞˘ωΩı
    -

    MathIt

    - -
    \mathit{Ax2k\breve{a}\omega\Omega\imath}Ax2ka˘ωΩı
    -

    MathNormal

    - -
    \mathnormal{Ax2k\breve{a}\omega\Omega\imath}Ax2ka˘ωΩı
    -

    MathOp

    - -
    a\mathop+b\mathop:c\mathop{\delta}
    e\mathop{\textrm{and}}f
    \mathrel{\mathop{:}}=g\sin h
    a+b:cδeandf:=gsinhmathop
    -

    MathRm

    - -
    \mathrm{Ax2k\breve{a}\omega\Omega\imath}Ax2ka˘ωΩı
    -

    MathSf

    - -
    \mathsf{Ax2k\breve{a}\omega\Omega\imath}𝖠𝗑𝟤𝗄𝖺˘𝞈𝝮ı
    -

    MathScr

    - -
    \mathscr{Ax2k\breve{a}\omega\Omega\imath}𝒜𝓍2𝓀𝒶˘ωΩı
    -

    MathtoolsMatrix

    - -
    \begin{matrix*}[l]
    a & -1 \\
    -1 & d
    \end{matrix*} \;
    \begin{pmatrix*}[r]
    a & -1 \\
    -1 & d
    \end{pmatrix*}
    a11d(a11d)MathtoolsMatrix
    -

    MathTt

    - -
    \mathtt{Ax2k\breve{a}\omega\Omega\imath}𝙰𝚡𝟸𝚔𝚊˘ωΩı
    -

    Mod

    - -
    \begin{array}{cc} a \bmod 2 & b \pod 3 \\
    c \pmod{4} & d \mod{56} \\
    \displaystyle a\bmod 2 & b \pod 3 \\
    \displaystyle c\pmod{4} & d \mod{56}
    \end{array}
    amod2b(3)c(mod4)dmod56amod2b(3)c(mod4)dmod56mod
    -

    NegativeSpace

    - -
    \boxed{$1,!000,!000}$1,000,000NegativeSpace
    -

    NestedFractions

    - -
    \dfrac{\frac{a}{b}}{\frac{c}{d}}
    \dfrac{\dfrac{a}{b}}{\dfrac{c}{d}}
    \frac{\frac{a}{b}}{\frac{c}{d}}
    abcdabcdabcdNestedFractions
    -

    NewLine

    - -
    \frac{a^2+b^2}{c^2} \newline
    \frac{a^2+b^2}{c^2} \\
    \begin{pmatrix} a & b \\
    c & d \cr \end{pmatrix} \\
    a+b+c+{d+\\e}+f+g
    a2+b2c2a2+b2c2(abcd)a+b+c+d+e+f+gnewline
    -

    Not

    - -
    \not = \begin{array}{l}
    \not=\not>\not\geq\not\in\not<\not\leq\not{abc} \\
    \not xy + ab \not xy \\
    a \neq b \notin c \end{array}
    ≱∉≰̸abcy+abyabcnot
    -

    NullDelimiterInteraction

    - -
    a \bigl. + 2 \quad \left. + a \right)a+2+a)NullDelimiterInteraction
    -

    OldFont

    - -
    \begin{matrix}
    \rm rm & it & \it it &
    \bf bf & \sf sf & \tt tt \\
    \text{\rm rm} & \text{rm} & \text{\it it} &
    \text{\bf bf} & \text{\sf sf} & \text{\tt tt} \\
    i\rm r\it i & \text{r\it i\rm r}
    \end{matrix}
    rmitit𝐛𝐟𝗌𝖿𝚝𝚝rmrm𝑖𝑡𝐛𝐟𝗌𝖿𝚝𝚝irir𝑖roldfont
    -

    OperatorName

    - -
    \begin{matrix} \operatorname g (z) + 5\operatorname{g}z
    + \operatorname{Gam-ma}(z) \\
    \operatorname{Gam ma}(z)
    + \operatorname{\Gamma}(z)
    + \operatorname{}x \\
    \operatorname*{asin} x +
    \operatorname*{asin}_y x +
    \operatorname*{asin}\limits_y x \\
    {\displaystyle \operatorname*{asin}_y x}
    \end{matrix}
    g(z)+5gz+Gam-ma(z)Gamma(z)+Γ(z)+xasinx+asinyx+asinyxasinyxOperatorName
    -

    OpLimits

    - -
    \begin{matrix}
    {\sin_2^2 \lim_2^2 \int_2^2 \sum_2^2}
    {\displaystyle \lim_2^2 \int_2^2 \intop_2^2 \sum_2^2} \\
    \limsup_{x \rightarrow \infty} x \stackrel{?}=
    \liminf_{x \rightarrow \infty} x \\
    {\displaystyle \limsup_{x \rightarrow \infty}
    x\:\: \sum_{\substack{0<i<m\\0<j<n}}} \end{matrix}
    sin22lim222222lim22222222limsupxx=?liminfxxlimsupxx0<i<m0<j<nOpLimits
    -

    OverUnderline

    - -
    x\underline{x}\underline{\underline{x}}
    \underline{x{x{x_x}}}\underline{x^{x^{x^x}}}
    \overline{x}\overline{x}\overline{x^{x^{x^x}}}
    \textcolor{blue}{\overline{\underline{x}}
    \underline{\overline{x}}}
    xx_x__xxxx_xxxx_x_x_xxxx_x__x__OverUnderline
    -

    OverUnderset

    - -
    \begin{array}{l}
    x\overset?=1 \quad \underset{*}{x}^2 \quad
    \overset{a}{b}b\underset{a}{b}b \\
    {\displaystyle\lim_{t\underset{>0}\to0}}\\
    a+b+c+d\overset{b+c=0}
    \longrightarrow a+d\\
    \overset { x = y } { \sqrt { a b } }
    \end{array}
    x=?1x*2babbablimt>00a+b+c+db+c=0a+dabx=yOverUnderset
    -

    Phantom

    - -
    \begin{array}{l} \dfrac{1+\phantom{x^{\textcolor{blue}{2}}} = x}
    {1+x^{\textcolor{blue}{2}} = x}
    \left(\vphantom{\int_t} zzz \right)
    \left( X \hphantom{\frac{\frac X X}{X}} \right)\\
    \text{a \phantom{123}} b \hphantom{\frac{1}{2}}=c
    \vphantom{101112} d \\
    \sqrt{\mathstrut a} + \sqrt{\mathstrut d}
    \end{array}
    1+x2=x1+x2=x(tzzz)(XXXX) 123b12=c101112d(a+(dphantom
    -

    Phase

    - -
    120\text{V}\phase{-78.2^\circ};
    \Large\phase{78.2^\circ}
    120V78.278.2
    -

    Pmb

    - -
    \mu\pmb{\mu}\pmb{=}\mu\pmb{+}\muμμ=μ+μpmb
    -

    PrimeSpacing

    - -
    f'+f_2'+f^{f'}f+f2+ffPrimeSpacing
    -

    PrimeSuper

    - -
    x'^2+x'''^2+x'^2_3+x_3'^2x2+x2+x32+x32PrimeSuper
    -

    Raisebox

    - -
    \frac{a}{a\raisebox{0.5em}{b}} \cdot
    \frac{a\raisebox{-0.5em}{b}}{a} \cdot
    \sqrt{a\raisebox{0.5em}{b}} \cdot
    \sqrt{a\raisebox{-0.5em}{b}} \cdot
    \sqrt{a\raisebox{0.5em}{b}\raisebox{-0.5em}{b}}
    aababaabababbraisebox
    -

    RelativeUnits

    - -
    \begin{array}{ll}
    a\kern1emb^{a\kern1emb^{a\kern1emb}} &
    {\footnotesize a\kern1emb^
    {a\kern1emb^{a\kern1emb}}} \\
    a\mkern18mub^{a\mkern18mub^{a\mkern18mub}} &
    {\footnotesize a\mkern18mub^
    {a\mkern18mub^{a\mkern18mub}}} \\
    \end{array}
    ababababababababababababRelativeUnits
    -

    RlapBug

    - -
    \frac{\mathrlap{x}}{2}x2rlapbug
    -

    Rule

    - -
    \rule{1em}{0.5em}\rule{1ex}{2ex}
    \rule{1em}{1ex}\rule{1em}{0.431ex}
    rule
    -

    SizingBaseline

    - -
    \text{{\tiny a+b}a+b{\Huge a+b}}a+ba+ba+bSizingBaseline
    -

    Sizing

    - -
    \text{{\Huge x}{\LARGE y}
    {\normalsize z}{\scriptsize w}}
    \sqrt[\text{\small 3}]{x+1}
    xy zwx+13sizing
    -

    Smash

    - -
    \left( X^{\smash 2} \right)
    \sqrt{\smash[b]{y=}}
    (X2)y=smash
    -

    Spacing

    - -
    \begin{matrix}
    ^3+[-1][1-1]1=1(=1)\lvert a\rvert~b \\
    \scriptstyle{^3+[-1][1-1]
    1=1(=1)\lvert a\rvert~b} \\
    \scriptscriptstyle{^3+[-1][1-1]
    1=1(=1)\lvert a\rvert~b} \\
    a : a \colon a \\
    \end{matrix}
    3+[1][11]1=1(=1)|a| b3+[1][11]1=1(=1)|a| b3+[1][11]1=1(=1)|a| ba:a:aspacing
    -

    Sqrt

    - -
    \sqrt{\sqrt{\sqrt{x}}}_
    {\sqrt{\sqrt{x}}}^
    {\sqrt{\sqrt{\sqrt{x}}}
    ^{\sqrt{\sqrt{\sqrt{x}}}}} \\
    \sqrt{\frac{\frac{A}{B}}{\frac{A}{B}}} \;
    \sqrt{\frac{\frac{\frac{A}{B}}{\frac{A}{B}}}
    {\frac{\frac{A}{B}}{\frac{A}{B}}}}
    xxxxABABABABABABsqrt
    -

    SqrtRoot

    - -
    \begin{array}{l}
    1+\sqrt[3]{2}+\sqrt[1923^234]
    {2^{2^{2^{2^{2^{2^{2^{2^{2^{2^{2^2}}}}}}}}}}} \\
    \Huge \sqrt[3]{M} + x^{\sqrt[3] a}
    \end{array}
    1+23+2222222222221923234M3+xa3SqrtRoot
    -

    StackRel

    - -
    a \stackrel{?}{=} b
    \stackrel{\text{def}}{=} c
    a=?b=defcStackRel
    -

    StretchyAccent

    - -
    \begin{array}{l}
    \overrightarrow{AB} \quad \overleftarrow{AB} \quad
    \overleftrightarrow{AB} \quad
    \left(\underleftarrow{\frac{value}{j}}\right) \\
    \widehat{ABC} \quad
    \widetilde{AB} \quad \widetilde{ABC} \\
    \overrightarrow{F} + \overrightarrow{AB} +
    \overrightarrow{F}^2 + \overrightarrow{F}_2 +
    \overrightarrow{F}_1^2 \\
    \overrightarrow{AB}^2+
    \frac{\overrightarrow{AB}}{\overrightarrow{AB}} +
    \sqrt{\overrightarrow{AB}} +
    \left\lvert\overrightarrow{AB}\right\rvert \end{array}
    ABABAB(valuej)ABC^AB~ABC~F+AB+F2+F2+F12AB2+ABAB+AB+|AB|StretchyAccent
    -

    StrikeThrough

    - -
    \begin{array}{l}
    \cancel x \quad \cancel{2B} +
    \bcancel 5 +\bcancel{5ay} \\
    \sout{5ab} + \sout{5ABC} +
    \xcancel{\oint_S{\vec E\cdot\hat n
    \,\mathrm d a}} \\[0.3em]
    \frac{x+\cancel B}{x+\cancel x} +
    \frac{x+\cancel y}{x} + \cancel{B}_1^2
    + \cancel{B^2} \\[0.2em]
    \left\lvert\cancel{ac}\right\rvert
    \end{array}
    x2B+5+5ay5ab+5ABC+SEn^dax+Bx+x+x+yx+B12+B2|ac|StrikeThrough
    -

    StrikeThroughColor

    - -
    \begin{array}{l} \textcolor{red}{\cancel x \quad \cancel{2B}} \\
    \textcolor{red}{\bcancel{\textcolor{black}{5}}} +
    \textcolor{red}{\bcancel{\textcolor{black}{5ay}}} \\
    \color{green}{\sout{5ABC}}
    \end{array}
    x2B5+5ay5ABCStrikeThroughColor
    -

    StyleSpacing

    - -
    \scriptstyle ab\;cdabcdStyleSpacing
    -

    StyleSwitching

    - -
    a\cdot b\scriptstyle a\cdot ba
    \textstyle\cdot ba\scriptstyle\cdot b
    ababababStyleSwitching
    -

    SupSubCharacterBox

    - -
    a_2f_2{f}_2{aa}_2{af}_2\mathbf{y}_Ay_Aa2f2f2aa2af2𝐲AyASupSubCharacterBox
    -

    SupSubHorizSpacing

    - -
    x^{x^{x}}\Big|
    x_{x_{x_{x_{x}}}}\bigg|
    x^{x^{x_{x_{x_{x_{x}}}}}}\bigg|
    xxx|xxxxx|xxxxxxx|SupSubHorizSpacing
    -

    SupSubLeftAlignReset

    - -
    \omega^8_{888} \quad
    \frac{1}{\hat{\omega}^{8}_{888}} \quad
    \displaystyle\sum_{\omega^{8}_{888}}
    ω88881ω^8888ω8888SupSubLeftAlignReset
    -

    SupSubOffsets

    - -
    \displaystyle \int_{2+3}x f^{2+3}
    +3\lim_{2+3+4+5}f
    2+3xf2+3+3lim2+3+4+5fSupSubOffsets
    -

    SurrogatePairs

    - - - - - - - - -
    Source Temml
    𝐀𝐚𝟎𝐴𝑎𝑨𝒂𝔅𝔞𝔸𝒜 𝐀𝐚𝟎𝐴𝑎𝑨𝒂𝔅𝔞𝔸𝒜
    𝖠𝖺𝟢𝗔𝗮𝟬𝘈𝘢𝙰𝚊𝟶 𝖠𝖺𝟢𝗔𝗮𝟬𝘈𝘢𝙰𝚊𝟶
    \text{𝐀𝐚𝟎𝐴𝑎𝑨𝒂𝔅𝔞𝔸𝒜} 𝐀𝐚𝟎𝐴𝑎𝑨𝒂𝔅𝔞𝔸𝒜
    \text{𝖠𝖺𝟢𝗔𝗮𝟬𝘈𝘢𝙰𝚊𝟶} 𝖠𝖺𝟢𝗔𝗮𝟬𝘈𝘢𝙰𝚊𝟶
    \mathrm{𝐀𝐚𝑨𝒂𝔅𝔞𝔸𝒜} 𝐀𝐚𝑨𝒂𝔅𝔞𝔸𝒜
    -

    Symbols1

    - -
    \maltese\degree\standardstate\pounds\$
    \text{\maltese\degree\pounds\textdollar}
    °£$✠°£$
    -

    Tag

    - -
    \tag{$+$hi} \frac{x^2}{y}+x^{2^y}x2y+x2y(+hi)
    -

    Text

    - -
    \frac{a}{b}\text{c~ {ab} \ e}+fgabc  ab  e+fgtext
    -

    TextSpace

    - -
    \begin{array}{l}
    \texttt{12345678901234} \\
    \texttt{A test 1~~2 \ \ 3} \\
    \verb|A test 1 2 3|
    \end{array}
    𝟷𝙰 𝚝𝚎𝚜𝚝 𝟷  𝟸  𝟹A test 1  2  3TextSpace
    -

    TextStacked

    - -
    \begin{matrix}
    \textsf{abc123 \textbf{abc123}
    \textit{abc123}}\\
    \text{abc123 \textbf{abc123}
    \textit{abc123}}\\
    \textrm{abc123 \textbf{abc123}
    \textit{abc123}}\\
    \textsf{\textrm{\textbf{abc123}}
    \textbf{abc123}
    \textit{abc123}}\\
    \textit{abc123 \textbf{abc123}
    \textsf{abc123}}\\
    \end{matrix}
    𝖺𝖻𝖼𝟣 𝗮𝗯𝗰𝟭 𝘢𝘣𝘤1abc123 𝐚𝐛𝐜𝟏 𝑎𝑏𝑐𝑏𝑐bc123 𝐚𝐛𝐜𝟏 𝑎𝑏𝑐𝑏𝑐123abc123 𝐚𝐛𝐜𝟏 𝑎𝑏𝑐𝑏𝑐bc123 𝐚𝐛𝐜𝟏 𝑎𝑏𝑐𝑏𝑐123𝐚𝐛𝐜𝟏 𝗮𝗯𝗰𝟭 𝘢𝘣𝘤1𝑎𝑏𝑐𝑏𝑐123 𝒂𝒃𝒄𝒃𝒄123 𝘢𝘣𝘤1TextStacked
    -

    TextWithMath

    - -
    \begin{matrix}
    \text{for $a < b$ and $ c < d $}. \\
    \textsf{for $a < b$ and $ c < d $}. \\
    \textsf{for $a < b \textbf{ and } c < d $} \\
    \text{\sf for $a < b$ and $c < d$.}
    \end{matrix}
    for or a<b and c<d.𝖿𝗈𝗋 𝗈𝗋 𝖺<𝖻 𝖺𝗇𝖽 𝖼<𝖽.𝖿𝗈𝗋 𝗈𝗋 𝖺<𝖻 𝗮𝗻𝗱 𝖼<𝖽𝖿𝗈𝗋 𝗈𝗋 𝖺<𝖻 𝖺𝗇𝖽 𝖼<𝖽.TextWithMath
    -

    Unicode

    - - - - - - - -
    Source Temml
    \text{ÀàÇçÉéÏïÖöÛû} AˋaˋÇçEˊeˊI¨ı¨O¨o¨Uˆuˆ
    \text{БГДЖЗЙЛФЦШЫЮЯ} БГДЖЗЙЛФЦШЫЮЯ
    \text{여보세요} 여보세요
    \text{私はバナナです} 私はバナナです
    -

    Units

    - -
    \begin{array}{ll}
    \mathrm H\kern 1em\mathrm H
    \text{\tiny (1em)} &
    \mathrm H\kern 1ex\mathrm H
    \text{\tiny (1ex)} \\
    \mathrm H{\scriptstyle \kern 1em}\mathrm H
    \text{\tiny (ss 1em)} &
    \mathrm H{\scriptstyle \kern 1ex}\mathrm H
    \text{\tiny (ss 1ex)} \\
    \mathrm H{\small \kern 1em}\mathrm H
    \text{\tiny (sm 1em)} &
    \mathrm H{\small \kern 1ex}\mathrm H
    \text{\tiny (sm 1ex)} \\
    \mathrm H\mkern 18mu\mathrm H
    \text{\tiny (18mu)} &
    \mathrm H\kern 1cm\mathrm H
    \text{\tiny (1cm)} \\
    \mathrm H{\scriptstyle \mkern 18mu}\mathrm H
    \text{\tiny (ss 18mu)} &
    \mathrm H{\scriptstyle \kern 1cm}\mathrm H
    \text{\tiny (ss 1cm)} \\
    \mathrm H{\small \mkern 18mu}\mathrm H
    \text{\tiny (sm 18mu)} &
    \mathrm H{\small \kern 1cm}\mathrm H
    \text{\tiny (sm 1cm)}
    \end{array}
    HH(1em)HH(1ex)HH(ss 1em)HH(ss 1ex)HH(sm 1em)HH(sm 1ex)HH(18mu)HH(1cm)HH(ss 18mu)HH(ss 1cm)HH(sm 18mu)HH(sm 1cm)units
    -

    UnsupportedCmds

    -

    \err\fracerr32\suberr\superr\sqrterr

    -

    deliberately does not compile

    -

    Verb

    - -
    \begin{array}{ll}
    \verb \verb , & \verb|\verb |, \\
    \verb* \verb* , & \verb*|\verb* |, \\
    \verb!<x> & </y>! & \scriptstyle\verb|ss verb| \\
    \verb*!<x> & </y>! & \small\verb|sm verb| \\
    \verb|``---''~|
    \end{array}
    \verb,\verb  ,\verb*,\verb*␣,<x> & </y>ss verb<x>␣&␣</y>sm verb``---''~verb
    - - diff --git a/site/tests/mhchem-tests.html b/site/tests/mhchem-tests.html deleted file mode 100644 index fb49e5bf..00000000 --- a/site/tests/mhchem-tests.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - Temml mhchem Tests - - - - - - -

    mhchem

    -

    This file contains all the examples in the mhchem manual.
    Ref: https://mhchem.github.io/MathJax-mhchem/

    -

    Chemical Equations (ce)

    - - - - - - -
    Source Temml
    \ce{CO2 + C -> 2 CO}CO2+C2CO
    \ce{Hg^2+ ->[I-] HgI2 ->[I-] [Hg^{II}I4]^2-}Hg2+IHgI2I[HgXIII4]2
    C_p[\ce{H2O(l)}] = \pu{75.3 J // mol K}Cp[H2O(l)]=75.3 JmolK
    -

    Chemical Formulae

    - - - - - -
    Source Temml
    \ce{H2O}H2O
    \ce{Sb2O3}Sb2O3
    -

    Charges

    - - - - - - - - -
    Source Temml
    \ce{H+}H+
    \ce{CrO4^2-}CrO42
    \ce{[AgCl2]-}[AgCl2]
    \ce{Y^99+}Y99+
    \ce{Y^{99+}}Y99+
    -

    Stoichiometric Numbers

    - - - - - - - - - -
    Source Temml
    \ce{2 H2O}2H2O
    \ce{2H2O}2H2O
    \ce{0.5 H2O}0.5H2O
    \ce{1/2 H2O}12H2O
    \ce{(1/2) H2O}(12)H2O
    \ce{$n$ H2O}nH2O
    -

    Isotopes

    - - - - - - -
    \ce{^{227}_{90}Th+}X90227X2902227Th+
    \ce{^227_90Th+}X90227X2902227Th+
    \ce{^{0}_{-1}n^{-}}X10X2120n
    \ce{^0_-1n-}X10X2120n
    \ce{H{}^3HO}HX3X223HO
    \ce{H^3HO}HX3X223HO
    -

    Reaction Arrows

    - - - - - - - - - - - - - -
    Source Temml
    \ce{A -> B}AB
    \ce{A <- B}AB
    \ce{A <-> B}AB
    \ce{A <--> B}AB
    \ce{A <=> B}AB
    \ce{A <=>> B}AB
    \ce{A <<=> B}AB
    \ce{A ->[H2O] B}AH2OB
    \ce{A ->[{text above}][{text below}] B}Atext belowtext aboveB
    \ce{A ->[$x$][$x_i$] B}AxixB
    -

    Parentheses, Brackets, Braces

    - - - - - - -
    Source Temml
    \ce{(NH4)2S}(NH4)2S
    \ce{[\{(X2)3\}2]^3+}[{(X2)3}2]3+
    \ce{CH4 + 2 $\left( \ce{O2 + 79/21 N2} \right)$}CH4+2 (O2+7921N2)
    -

    States of Aggregation

    - - - - - - -
    Source Temml
    \ce{H2(aq)}H2(aq)
    \ce{CO3^2-_{(aq)}}CO32(aq)
    \ce{NaOH(aq,$\infty$)}NaOH(aq,)
    -

    Crystal Systems

    - - - - - -
    Source Temml
    \ce{ZnS($c$)}ZnS(c)
    \ce{ZnS(\ca$c$)}ZnS(c)
    -

    Variables

    - - - - - - -
    Source Temml
    \ce{NO_x}NOx
    \ce{Fe^n+}Fen+
    \ce{x Na(NH4)HPO4 ->[\Delta]
    (NaPO3)_x + x NH3 ^ + x H2O}
    xNa(NH4)HPO4Δ(NaPO3)x+xNH3+xH2O
    -

    Greek Characters

    - - - - - - - -
    Source Temml
    \ce{\mu-Cl}μ-Cl
    \ce{[Pt(\eta^2-C2H4)Cl3]-}[Pt(η2-C2H4)Cl3]
    \ce{\beta +}β+
    \ce{^40_18Ar + \gamma{} + \nu_e}X1840X218240Ar+γ+νe
    -

    (Italic) Math

    - - - - - - - -
    Source Temml
    \ce{NaOH(aq,$\infty$)}NaOH(aq,)
    \ce{Fe(CN)_{$\frac{6}{2}$}}Fe(CN)62
    \ce{X_{$i$}^{$x$}}Xix
    \ce{X_$i$^$x$}Xix
    -

    Italic Text

    - - - - - -
    Source Temml
    \ce{$cis${-}[PtCl2(NH3)2]}cis-[PtCl2(NH3)2]
    \ce{CuS($hP12$)}CuS(hP12)
    -

    Upright Text, Escape Parsing

    - - - - - - -
    Source Temml
    \ce{{Gluconic Acid} + H2O2}Gluconic Acid+H2O2
    \ce{X_{{red}}}Xred
    \ce{{(+)}_589{-}[Co(en)3]Cl3}(+)589-[Co(en)3]Cl3
    -

    Bonds

    - - - - - - - - - - - -
    Source Temml
    \ce{C6H5-CHO}C6H5CHO
    \ce{A-B=C#D}AB=CD
    \ce{A\bond{-}B\bond{=}C\bond{#}D}AB=CD
    \ce{A\bond{1}B\bond{2}C\bond{3}D}AB=CD
    \ce{A\bond{~}B\bond{~-}C}ABC
    \ce{A\bond{~--}B\bond{~=}C\bond{-~-}D}ABCD
    \ce{A\bond{...}B\bond{....}C}ABC
    \ce{A\bond{->}B\bond{<-}C}ABC
    -

    Addition Compounds

    - - - - - - -
    Source Temml
    \ce{KCr(SO4)2*12H2O}KCr(SO4)212H2O
    \ce{KCr(SO4)2.12H2O}KCr(SO4)212H2O
    \ce{KCr(SO4)2 * 12 H2O}KCr(SO4)212H2O
    -

    Oxidation States

    - - - - -
    Source Temml
    \ce{Fe^{II}Fe^{III}2O4}FeXIIFeXIII2O4
    -

    Unpaired Electrons, Radical Dots

    - - - - - -
    Source Temml
    \ce{OCO^{.-}}OCO
    \ce{NO^{(2.)-}}NO(2)
    -

    Kröger-Vink Notation

    - - - - - - - - -
    Source Temml
    \ce{Li^x_{Li,1-2x}Mg^._{Li,x}
    $V$'_{Li,x}Cl^x_{Cl}}
    LiXLi,12x×MgXLi,x VXLi,xClXCl×

    \ce{O''_{i,x}}

    -

    OXi,x

    -
    \ce{M^{..}_i}MXi
    \ce{$V$^{4'}_{Ti}}VXTi4
    \ce{V_{V,1}C_{C,0.8}$V$_{C,0.2}}VV,1CC,0.8 VC,0.2
    -

    Equation Operators

    - - - - - - - -
    Source Temml
    \ce{A + B}A+B
    \ce{A - B}AB
    \ce{A = B}A=B
    \ce{A \pm B}A±B
    -

    Precipitate and Gas

    - - - - - -
    Source Temml
    \ce{SO4^2- + Ba^2+ -> BaSO4 v}SO42+Ba2+BaSO4
    \ce{A v B (v) -> B ^ B (^)}A BB B
    -

    Other Symbols and Shortcuts

    - - - - - - - - - - -
    Source Temml
    \ce{NO^*}NO*
    \ce{1s^2-N}1s2-N
    \ce{n-Pr}n-Pr
    \ce{iPr}iPr
    \ce{\ca Fe}Fe
    \ce{A, B, C; F}A,B,C;F
    \ce{{and others}}and others
    -

    Complex Examples

    - - - - - - - -
    Source Temml
    \ce{Zn^2+ <=>+ 2OH-
    $\underset{\text{amphoteres Hydroxid}}
    {\ce{Zn(OH)2 v}}$ <=>+ 2OH-
    $\underset{\text{Hydroxozikat}}
    {\ce{[Zn(OH)4]^2-}}$}
    Zn2++2H++2OH+2H++2OHZn(OH)2amphoteres Hydroxid+2H++2OH+2H++2OH[Zn(OH)4]2Hydroxozikat
    \ce{$K = \frac{\ce{Hg^2+}}
    {[\ce{Hg2^2+}]}$}
    K=[Hg2+][Hg][Hg22+]
    \ce{$K =
    \ce{\frac{Hg^2+}{[Hg2^2+]}}$}
    K=[Hg2+][Hg][Hg22+]
    \ce{Hg^2+ ->[I-]
    $\underset{\mathrm{red}}{\ce{HgI2}}$
    ->[I-] $\underset{\mathrm{red}}
    {\ce{[Hg^{II}I4]^2-}}$}
    Hg2+IHgI2redI[HgXIII4]2red
    -

    Physical Units

    - - - - - - - - - - - - - - - -
    Source Temml
    \pu{123 kJ}123 kJ
    \pu{123 mm2}123 mm2
    \pu{123 J s}123 Js
    \pu{123 J*s}123 Js
    \pu{123 kJ/mol}123 kJmol
    \pu{123 kJ//mol}123 kJmol
    \pu{123 kJ mol-1}123 kJmol1
    \pu{123 kJ*mol-1}123 kJmol1
    \pu{1.2e3 kJ}1.2103 kJ
    \pu{1,2e3 kJ}1,2103 kJ
    \pu{1.2E3 kJ}1.2×103 kJ
    \pu{1,2E3 kJ}1,2×103 kJ
    - - diff --git a/site/tests/mozilla-tests.html b/site/tests/mozilla-tests.html deleted file mode 100644 index 869926aa..00000000 --- a/site/tests/mozilla-tests.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - Temml Mozilla Tests - - - - - - -

    Mozilla Torture Test

    -

    This page reproduces the tests from
    https://www-archive.mozilla.org/projects/mathml/demo/texvsmml.xhtml and
    https://fred-wang.github.io/MathFonts/mozilla_mathml_test/

    -

    Images from LaTeX are also included for comparison.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    SourceTemmlLaTeXComment
    1x^2y^2x2y2ex1TeXbook p128
    2_2F_32F3ex2TeXbook p128
    3x+y^2\over k+1x+y2k+1ex3TeXbook p139
    4x+y^{2\over k+1}x+y2k+1ex4TeXbook p139
    5a\over{b/2}ab2ex5TeXbook p139
    6 a_0 + \cfrac{1}{a_1 +
    \cfrac{1}{a_2 +
    \cfrac{1}{a_3 +
    \cfrac{1}{a_4}}}}
    a0+1a1+1a2+1a3+1a4ex6 TeXbook p142
    7 a_0+{1\over a_1+{1\over
    a_2+{1\over a_3+
    {1\over a_4}}}}
    a0+1a1+1a2+1a3+1a4ex7 TeXbook p142
    8n\choose {k / 2}(nk2)ex8TeXbook p143
    9 {p \choose 2} x^2 y^{p-2}
    - {1\over{1-x}}
    {1\over{1-x^2}}
    (p2)x2yp211x11x2ex9 TeXbook p143
    10 \sum_{\scriptstyle 0 \le
    i \le m \atop \scriptstyle
    0 < j < n} P(i, j)
    0im0<j<nP(i,j)ex10 TeXbook p145
    11x^{2y}x2yex11TeXbook p128
    12 \sum_{i=1}^p
    \sum_{j=1}^q
    \sum_{k=1}^r
    a_{ij}b_{jk}c_{ki}
    i=1pj=1qk=1raijbjkckiex12 TeXbook p145
    13 \sqrt{1+\sqrt{1+\sqrt{1+
    \sqrt{1+\sqrt{1+\sqrt{1+
    \sqrt{1+x}}}}}}}
    1+1+1+1+1+1+1+xex13 TeXbook p145
    14 \bigg(\frac{\partial^2}
    {\partial x^2} + \frac
    {\partial^2}{\partial y^2}
    \bigg) \big\lvert\varphi
    (x+iy)\big\rvert^2
    (2x2+2y2)|φ(x+iy)|2ex14 TeXbook p147
    152^{2^{2^x}}222xex15TeXbook p128
    16\int_1^x {dt\over t}1xdttex16TeXbook p168
    17\int\!\!\!\int_D dx,dyDdxdyex17TeXbook p169
    18 f(x) = \begin{cases}1/3 &
    \text{if }0 \le x \le 1;
    \\
    2/3 & \text{if }3\le x \le
    4;\\ 0 &\text{elsewhere.}
    \end{cases}
    f(x)={13if 0x1;23if 3x4;0elsewhere. ex18 TeXbook p175
    19 \overbrace{x +\cdots + x}
    ^{k \text{ times}}
    x++xk timesex19 TeXbook p176
    20y_{x^2}yx2ex20TeXbook p128
    21 \sum_{p\text{ prime}}
    f(p)=\int_{t>1} f(t)d\pi(t)
    p primef(p)=t>1f(t)dπ(t)ex21 TeXbook p181
    22 {\underbrace{\overbrace{
    \mathstrut a,\dots,a}^{k
    ,a\rq\text{s}},\overbrace{
    \mathstrut b,\dots,b}^{l,
    b\rq\text{s}}}_{k+l
    \text{ elements}}}
    {(a,,akas,(b,,blbsk+l elements}ex22 TeXbook p181
    23 \begin{pmatrix}
    \begin{pmatrix}a&b\\c&d
    \end{pmatrix} &
    \begin{pmatrix}e&f\\g&h
    \end{pmatrix} \\ 0 &
    \begin{pmatrix}i&j\\k&l
    \end{pmatrix}
    \end{pmatrix}
    ((abcd)(efgh)0(ijkl))ex23 TeXbook p181
    24 \det\begin{vmatrix}
    c_0&c_1&c_2&\dots& c_n\\
    c_1 & c_2 & c_3 & \dots &
    c_{n+1}\\ c_2 & c_3 & c_4
    &\dots & c_{n+2}\\ \vdots
    &\vdots&\vdots & &\vdots
    \\c_n & c_{n+1} & c_{n+2}
    &\dots&c_{2n}
    \end{vmatrix} > 0
    det|c0c1c2cnc1c2c3cn+1c2c3c4cn+2cncn+1cn+2c2n|>0ex24 TeXbook p181
    25y_{x_2}yx2ex25TeXbook p128
    26x_{92}^{31415} + \pix9231415+πex26TeXbook p129
    27x_{y^a_b}^{z^c_d}xybazdcex27TeXbook p129
    28y_3'''y3ex28TeXbook p130
    29 \lim_{n\rightarrow+\infty}
    {\sqrt{2\pi n}\over n!}
    {\binom{n}{e}}^n = 1
    limn+2πnn!(ne)n=1ex29
    30 \det(A) = \sum_{\sigma
    \in S_n} \epsilon(\sigma)
    \prod_{i=1}^n
    a_{i, \sigma_i}
    det(A)=σSnϵ(σ)i=1nai,σiex30
    - - diff --git a/site/tests/wiki-tests.html b/site/tests/wiki-tests.html deleted file mode 100644 index e08de700..00000000 --- a/site/tests/wiki-tests.html +++ /dev/null @@ -1,359 +0,0 @@ - - - - - - Temml Wiki Tests - - - - - - -

    Wiki Test

    -

    Rows 1 thru 261 on this page reproduce the math examples from
    https://en.wikipedia.org/wiki/Help:Displaying_a_formula

    -

    A few of the functions on this page require Temml’s texvc extension.

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    SourceTemml
    1\alphaα
    2f(x) = x^2f(x)=x2
    3\{1,e,\pi\}{1,e,π}
    4|z + 1| \leq 2|z+1|2
    5 \# \$ \% ^\wedge \& \_ \{ \} \sim
    \backslash
    #$%&_{}\
    Accents
    6\dot{a}, \ddot{a}, \acute{a}, \grave{a}a˙,a¨,aˊ,a`
    7\dot{a}, \ddot{a}, \acute{a}, \grave{a}a˙,a¨,aˊ,a`
    8\check{a}, \breve{a}, \tilde{a}, \bar{a}aˇ,a˘,a~,a
    9\hat{a}, \widehat{a}, \vec{a}a^,a^,a
    Functions
    10\exp_a b = a^b, \exp b = e^b, 10^mexpab=ab,expb=eb,10m
    11\ln c, \lg d = \log e, \log_{10} flnc,lgd=loge,log10f
    12 \sin a, \cos b, \tan c, \cot d, \sec e,
    \csc f
    sina,cosb,tanc,cotd,sece,cscf
    13\arcsin h, \arccos i, \arctan jarcsinh,arccosi,arctanj
    14\sinh k, \cosh l, \tanh m, \coth nsinhk,coshl,tanhm,cothn
    15 \operatorname{sh}k, \operatorname{ch}l,
    \operatorname{th}m, \operatorname{coth}n
    shk,chl,thm,cothn
    16\sgn r, \left\vert s \right\vertsgnr,|s|
    17\min(x,y), \max(x,y)min(x,y),max(x,y)
    Bounds
    18\min x, \max y, \inf s, \sup tminx,maxy,infs,supt
    19\lim u, \liminf v, \limsup wlimu,liminfv,limsupw
    20\dim p, \deg q, \det m, \ker\phidimp,degq,detm,kerϕ
    Projections
    21\Pr j, \hom l, \lVert z \rVert, \arg zPrj,homl,z,argz
    Differentials and derivatives
    22dt, \mathrm{d}t, \partial t, \nabla\psidt,dt,t,ψ
    23 dy/dx, \mathrm{d}y/\mathrm{d}x,
    \frac{dy}{dx},
    \frac{\mathrm{d}y}{\mathrm{d}x},
    \frac{\partial^2}
    {\partial x_1\partial x_2}y
    dydx,dydx,dydx,dydx,2x1x2y
    24 \prime, \backprime, f^\prime, f', f'',
    f^{(3)}, \dot y, \ddot y
    ,,f,f,f,f(3),y˙,y¨
    Letter-like symbols or constants
    25 \infty, \aleph, \complement,\backepsilon,
    \eth, \Finv, \hbar
    ,,,,ð,,
    26 \Im, \imath, \jmath, \Bbbk, \ell, \mho,
    \wp, \Re, \circledS, \S, \P, \AA
    ,ı,ȷ,𝕜,,,,,,§,,
    Modular arithmetic
    27s_k \equiv 0 \pmod{m}sk0(modm)
    28a \bmod bamodb
    29\gcd(m, n), \operatorname{lcm}(m, n)gcd(m,n),lcm(m,n)
    30\mid, \nmid, \shortmid, \nshortmid|,,,
    Radicals
    31 \surd, \sqrt{2}, \sqrt[n]{2},
    \sqrt[3]{\frac{x^3+y^3}{2}}
    ,2,2n,x3+y323
    Operators
    32+, -, \pm, \mp, \dotplus+,,±,,
    33\times, \div, \divideontimes, /,\backslash×,÷,,,\
    34\cdot, * \ast, \star, \circ, \bullet,*,,,
    35\boxplus, \boxminus, \boxtimes, \boxdot,,,
    36\oplus, \ominus, \otimes, \oslash, \odot,,,,
    37\circleddash, \circledcirc, \circledast,,
    38\bigoplus, \bigotimes, \bigodot,,
    Sets
    39{ }, \O \empty \emptyset, \varnothing{},Ø,ø
    40\in, \notin \not\in, \ni, \not\ni,∉,,∌
    41\cap, \Cap, \sqcap, \bigcap,,,
    42 \cup, \Cup, \sqcup, \bigcup, \bigsqcup,
    \uplus, \biguplus
    ,,,,,,
    43\setminus, \smallsetminus, \times,,×
    44\subset, \Subset, \sqsubset,,
    45\supset, \Supset, \sqsupset,,
    46 \subseteq, \nsubseteq, \subsetneq,
    \varsubsetneq, \sqsubseteq
    ,,,⊊︀,
    47 \supseteq, \nsupseteq, \supsetneq,
    \varsupsetneq, \sqsupseteq
    ,,,,
    48 \subseteqq, \nsubseteqq, \subsetneqq,
    \varsubsetneqq
    ,,,⫋︀
    49 \supseteqq, \nsupseteqq, \supsetneqq,
    \varsupsetneqq
    ,,,⫌︀
    Relations
    50=, \ne, \neq, \equiv, \not\equiv=,,,,≢
    51 \doteq, \doteqdot,
    \overset{\underset{\mathrm{def}}{}}{=}, :=
    ,,=def,:=
    52 \sim, \nsim, \backsim, \thicksim, \simeq,
    \backsimeq, \eqsim, \cong, \ncong
    ,,,,,,,,
    53 \approx, \thickapprox, \approxeq, \asymp,
    \propto, \varpropto
    ,,,,,
    54 <, \nless, \ll, \not\ll, \lll, \not\lll,
    \lessdot
    <,,,≪̸,,⋘̸,
    55 \le, \leq, \lneq, \leqq, \nleq, \nleqq,
    \lneqq, \lvertneqq
    ,,,,,,,≨︀
    56 \ge, \geq, \gneq, \geqq, \ngeq, \ngeqq,
    \gneqq, \gvertneqq
    ,,,,,,,≩︀
    57 \lessgtr, \lesseqgtr, \lesseqqgtr,
    \gtrless, \gtreqless, \gtreqqless
    ,,,,,
    58\leqslant, \nleqslant, \eqslantless,,
    59\geqslant, \ngeqslant, \eqslantgtr,,
    60\lesssim, \lnsim, \lessapprox, \lnapprox,,,
    61\gtrsim, \gnsim, \gtrapprox, \gnapprox,,,
    62\prec, \nprec, \preceq, \npreceq,\precneqq,,,,
    63\succ, \nsucc, \succeq, \nsucceq,\succneqq,,,,
    64\preccurlyeq, \curlyeqprec,
    65\succcurlyeq, \curlyeqsucc,
    66 \precsim, \precnsim, \precapprox,
    \precnapprox
    ,,,
    67 \succsim, \succnsim, \succapprox,
    \succnapprox
    ,,,
    Geometric
    68 \parallel, \nparallel, \shortparallel,
    \nshortparallel
    ,,,
    69 \perp, \angle, \sphericalangle,
    \measuredangle, 45^\circ
    ,,,,45
    70 \Box, \square, \blacksquare, \diamond,
    \Diamond, \lozenge, \blacklozenge,\bigstar
    ,,,,,,,
    71 \bigcirc, \triangle, \bigtriangleup,
    \bigtriangledown
    ,,,
    72\vartriangle, \triangledown,
    73 \blacktriangle, \blacktriangledown,
    \blacktriangleleft, \blacktriangleright
    ,,,
    Logic
    74\forall, \exists, \nexists,,
    75\therefore, \because, \And,,&
    76\lor \vee, \curlyvee, \bigvee,,
    77\land \wedge, \curlywedge, \bigwedge,,
    78 \bar{q}, \bar{abc}, \overline{q},
    \overline{abc},\\
    \lnot \neg, \not\operatorname{R},\bot,\top
    q,abc,q_,abc_,¬¬,̸R,,
    79\vdash \dashv, \vDash, \Vdash, \models,,,
    80\Vvdash \nvdash \nVdash \nvDash \nVDash
    81\ulcorner \urcorner \llcorner \lrcorner
    Arrows
    82\Rrightarrow, \Lleftarrow,
    83 \Rightarrow, \nRightarrow,
    \Longrightarrow, \implies
    ,,,
    84\Leftarrow, \nLeftarrow, \Longleftarrow,,
    85 \Leftrightarrow, \nLeftrightarrow,
    \Longleftrightarrow, \iff
    ,,,
    86\Uparrow, \Downarrow, \Updownarrow,,
    87 \rightarrow \to, \nrightarrow,
    \longrightarrow
    ,,
    88 \leftarrow \gets, \nleftarrow,
    \longleftarrow
    ,,
    89 \leftrightarrow, \nleftrightarrow,
    \longleftrightarrow
    ,,
    90\uparrow, \downarrow, \updownarrow,,
    91\nearrow, \swarrow, \nwarrow, \searrow,,,
    92\mapsto, \longmapsto,
    93 \rightharpoonup \rightharpoondown
    \leftharpoonup \leftharpoondown
    \upharpoonleft \upharpoonright
    \downharpoonleft \downharpoonright
    \rightleftharpoons \leftrightharpoons
    94 \curvearrowleft \circlearrowleft \Lsh
    \upuparrows \rightrightarrows
    \rightleftarrows \rightarrowtail
    \looparrowright
    95 \curvearrowright \circlearrowright \Rsh
    \downdownarrows \leftleftarrows
    \leftrightarrows \leftarrowtail
    \looparrowleft
    96 \hookrightarrow \hookleftarrow \multimap
    \leftrightsquigarrow \rightsquigarrow
    \twoheadrightarrow \twoheadleftarrow
    Special
    97\amalg \P \S %\dagger\ddagger\ldots\cdots⨿§%
    98 \smile \frown \wr \triangleleft
    \triangleright
    99 \diamondsuit, \heartsuit, \clubsuit,
    \spadesuit, \Game, \flat, \natural, \sharp
    ,,,,,,,
    Unsorted
    100 \diagup \diagdown \centerdot \ltimes
    \rtimes \leftthreetimes \rightthreetimes
    101 \eqcirc \circeq \triangleq \bumpeq\Bumpeq
    \doteqdot \risingdotseq \fallingdotseq
    102 \intercal \barwedge \veebar
    \doublebarwedge \between \pitchfork
    103 \vartriangleleft \ntriangleleft
    \vartriangleright \ntriangleright
    104 \trianglelefteq \ntrianglelefteq
    \trianglerighteq \ntrianglerighteq
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Larger expressions
    SourceTemml
    105a^2, a^{x+3}a2,ax+3
    106a_2a2
    107 10^{30} a^{2+2}
    a_{i,j} b_{f'}
    1030a2+2ai,jbf
    108 x_2^3
    {x_2}^3
    x23x23
    10910^{10^{8}}10108
    110 \sideset{_1^2}{_3^4}\prod_a^b
    {}_1^2\!\Omega_3^4
    3412ab 12Ω34
    111 \overset{\alpha}{\omega}
    \underset{\alpha}{\omega}
    \overset{\alpha}{\underset{\gamma}{\omega}}
    \stackrel{\alpha}{\omega}
    ωαωαωγαωα
    112 x', y'', f', f''
    x^\prime, y^{\prime\prime}
    x,y,f,fx,y
    113\dot{x}, \ddot{x}x˙,x¨
    114 \hat a \ \bar b \ \vec c
    \overrightarrow{a b} \ \overleftarrow{c d}
    \widehat{d e f}
    \overline{g h i} \ \underline{j k l}
    a^ b cab cddef^ghi_ jkl_
    115\overset{\frown} {AB}A
    116 A \xleftarrow{n+\mu-1} B
    \xrightarrow[T]{n\pm i-1} C
    An+μ1BTn±i1C
    117\overbrace{ 1+2+\cdots+100 }^{5050}1+2++1005050
    118\underbrace{ a+b+\cdots+z }_{26}a+b++z26
    119\sum_{k=1}^N k^2k=1Nk2
    120\textstyle \sum_{k=1}^N k^2k=1Nk2
    121\frac{\sum_{k=1}^N k^2}{a}k=1Nk2a
    122\frac{\sum\limits^{^N}_{k=1} k^2}{a}k=1Nk2a
    123\prod_{i=1}^N x_ii=1Nxi
    124\textstyle \prod_{i=1}^N x_ii=1Nxi
    125\coprod_{i=1}^N x_ii=1Nxi
    126\textstyle \coprod_{i=1}^N x_ii=1Nxi
    127\lim_{n \to \infty}x_nlimnxn
    128\textstyle \lim_{n \to \infty}x_nlimnxn
    129\int\limits_{1}^{3}\frac{e^3/x}{x^2}\, dx13e3xx2dx
    130\int_{1}^{3}\frac{e^3/x}{x^2}\, dx13e3xx2dx
    131\textstyle \int\limits_{-N}^{N} e^x dxNNexdx
    132\textstyle \int_{-N}^{N} e^x dxNNexdx
    133\iint\limits_D dx\,dyDdxdy
    134\iiint\limits_E dx\,dy\,dzEdxdydz
    135\iiiint\limits_F dx\,dy\,dz\,dtFdxdydzdt
    136\int_{(x,y)\in C} x^3\, dx + 4y^2\, dy(x,y)Cx3dx+4y2dy
    137\oint_{(x,y)\in C} x^3\, dx + 4y^2\, dy(x,y)Cx3dx+4y2dy
    138\bigcap_{i=1}^n E_ii=1nEi
    139\bigcup_{i=1}^n E_ii=1nEi
    Fractions, matrices, multiline
    140\frac{2}{4}=0.5 or {2 \over 4}=0.524=0.5 or 24=0.5
    141\tfrac{2}{4} = 0.524=0.5
    142 \dfrac{2}{4} = 0.5 \qquad \dfrac{2}{c +
    \dfrac{2}{d + \dfrac{2}{4}}} = a
    24=0.52c+2d+24=a
    143\cfrac{2}{c +\cfrac{2}{d +\cfrac{2}{4}}} = a2c+2d+24=a
    144 \cfrac{x}{1 + \cfrac{\cancel{y}}
    {\cancel{y}}} = \cfrac{x}{2}
    x1+yy=x2
    145\binom{n}{k}(nk)
    146\tbinom{n}{k}(nk)
    147\dbinom{n}{k}(nk)
    148 \begin{matrix}
    x & y \\
    z & v
    \end{matrix}
    xyzv
    149 \begin{vmatrix}
    x & y \\
    z & v
    \end{vmatrix}
    |xyzv|
    150 \begin{Vmatrix}
    x & y \\
    z & v
    \end{Vmatrix}
    xyzv
    151 \begin{bmatrix}
    0 & \cdots & 0 \\
    \vdots & \ddots & \vdots \\
    0 & \cdots & 0
    \end{bmatrix}
    [0000]
    152 \begin{Bmatrix}
    x & y \\
    z & v
    \end{Bmatrix}
    {xyzv}
    153 \begin{pmatrix}
    x & y \\
    z & v
    \end{pmatrix}
    (xyzv)
    154 \bigl( \begin{smallmatrix}
    a&b\\ c&d
    \end{smallmatrix} \bigr)
    (abcd)
    155 f(n) = \begin{cases}
    n/2, & \text{if }n\text{ is even} \\
    3n+1, & \text{if }n\text{ is odd} \end{cases}
    f(n)={n2,if n is even3n+1,if n is odd
    156 \begin{cases}
    3x + 5y + z \\
    7x - 2y + 4z \\
    -6x + 3y + 2z \end{cases}
    {3x+5y+z7x2y+4z6x+3y+2z
    157 \begin{align}
    f(x) & = (a+b)^2 \\
    & = a^2+2ab+b^2 \\
    \end{align}
    f(x)=(a+b)2=a2+2ab+b2
    158 \begin{alignat}{2}
    f(x) & = (a+b)^2 \\
    & = a^2+2ab+b^2 \\
    \end{alignat}
    f(x)=(a+b)2=a2+2ab+b2
    159 \begin{align}
    f(a,b) & = (a+b)^2 && = (a+b)(a+b) \\
    & = a^2+ab+ba+b^2 && = a^2+2ab+b^2 \\
    \end{align}
    f(a,b)=(a+b)2=(a+b)(a+b)=a2+ab+ba+b2=a2+2ab+b2
    159 \begin{alignat}{3}
    f(a,b) & = (a+b)^2 && = (a+b)(a+b) \\
    & = a^2+ab+ba+b^2 && = a^2+2ab+b^2 \\
    \end{alignat}
    f(a,b)=(a+b)2=(a+b)(a+b)=a2+ab+ba+b2=a2+2ab+b2
    160 \begin{array}{lcl}
    z & = & a \\
    f(x,y,z) & = & x + y + z \end{array}
    z=af(x,y,z)=x+y+z
    161 \begin{array}{lcr}
    z & = & a \\
    f(x,y,z) & = & x + y + z \end{array}
    z=af(x,y,z)=x+y+z
    162 \begin{alignat}{4}
    F:\; && C(X) && \;\to\; & C(X) \\
    && g && \;\mapsto\; & g^2 \end{alignat}
    F:C(X)C(X)gg2
    163 \begin{alignat}{4}
    F:\; && C(X) && \;\to\; && C(X) \\
    && g && \;\mapsto\; && g^2 \end{alignat}
    F:C(X)C(X)gg2
    164 f(x) \,\! \sum_{n=0}^\infty a_n x^n
    = a_0+a_1x+a_2x^2+\cdots
    f(x) =n=0anxn =a0+a1x+a2x2+
    165 \begin{array}{|c|c|c|}
    a & b & S \\
    \hline
    0 & 0 & 1 \\
    0 & 1 & 1 \\
    1 & 0 & 1 \\
    1 & 1 & 0 \\
    \end{array}
    abS001011101110
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Delimiters
    166( \frac{1}{2} )^n(12)n
    167\left ( \frac{1}{2} \right )^n(12)n
    168\left ( \frac{a}{b} \right )(ab)
    169 \left [ \frac{a}{b} \right ] \quad
    \left \lbrack \frac{a}{b} \right \rbrack
    [ab][ab]
    170 \left { \frac{a}{b} \right } \quad
    \left \lbrace \frac{a}{b} \right \rbrace
    {ab}{ab}
    171\left \langle \frac{a}{b} \right \rangleab
    172 \left | \frac{a}{b} \right \vert \quad
    \left \Vert \frac{c}{d} \right |
    |ab|cd
    173 \left \lfloor \frac{a}{b} \right \rfloor
    \quad \left \lceil \frac{c}{d} \right \rceil
    abcd
    174\left / \frac{a}{b} \right \backslashab
    175 \left\uparrow\frac{a}{b}\right\downarrow\;
    \left\Uparrow\frac{a}{b}\right\Downarrow\;
    \left \updownarrow \frac{a}{b} \right
    \Updownarrow
    ababab
    176 \left [ 0,1 \right )
    \left \langle \psi \right |
    [0,1)ψ|
    177\left . \frac{A}{B} \right } \to XAB}X
    178 ( \bigl( \Bigl( \biggl( \Biggl( \dots
    \Biggr] \biggr] \Bigr] \bigr] ]
    (((((]]]]]
    179 { \bigl{ \Bigl{ \biggl{ \Biggl{ \dots
    \Biggr\rangle \biggr\rangle \Bigr\rangle
    \bigr\rangle \rangle
    {{{{{
    180 | \big| \Big| \bigg| \Bigg| \dots
    \Bigg| \bigg| \Big| \big| |
    |||||
    181 \lfloor \bigl\lfloor \Bigl\lfloor
    \biggl\lfloor \Biggl\lfloor \dots
    \Biggr\rceil \biggr\rceil \Bigr\rceil
    \bigr\rceil \ceil
    182 \uparrow \big\uparrow \Big\uparrow
    \bigg\uparrow \Bigg\uparrow \dots
    \Bigg\Downarrow \bigg\Downarrow
    \Big\Downarrow \big\Downarrow \Downarrow
    183 \updownarrow\big\updownarrow\Big\updownarrow
    \bigg\updownarrow \Bigg\updownarrow \dots
    \Bigg\Updownarrow \bigg\Updownarrow \Big
    \Updownarrow \big\Updownarrow \Updownarrow
    184 / \big/ \Big/ \bigg/ \Bigg/ \dots
    \Bigg\backslash \bigg\backslash \Big
    \backslash \big\backslash \backslash
    \
    Greek Alphabet
    185 \Alpha \Beta \Gamma \Delta \Epsilon \Zeta
    \Eta \Theta
    ΑΒΓΔΕΖΗΘ
    186\Iota \Kappa \Lambda \Mu \Nu \Xi \Omicron \PiΙΚΛΜΝΞΟΠ
    187 \Rho \Sigma \Tau \Upsilon \Phi \Chi \Psi
    \Omega
    ΡΣΤΥΦΧΨΩ
    188 \alpha \beta \gamma \delta \epsilon \zeta
    \eta \theta
    αβγδϵζηθ
    189\iota \kappa \lambda \mu \nu \xi \omicron \piικλμνξοπ
    190 \rho \sigma \tau \upsilon \phi \chi \psi
    \omega
    ρστυϕχψω
    191 \varGamma \varDelta \varTheta \varLambda
    \varXi \varPi \varSigma \varPhi \varUpsilon
    \varOmega
    𝛤𝛥𝛩𝛬𝛯𝛱𝛴𝛷𝛶𝛺
    192 \varepsilon \digamma \varkappa \varpi
    \varrho \varsigma \vartheta \varphi
    εϝϰϖϱςϑφ
    Hebrew symbols
    193\aleph \beth \gimel \daleth
    Blackboard bold
    194 \mathbb{ABCDEFGHI}
    \mathbb{JKLMNOPQR}
    \mathbb{STUVWXYZ}
    𝔸𝔹𝔻𝔼𝔽𝔾𝕀𝕁𝕂𝕃𝕄𝕆𝕊𝕋𝕌𝕍𝕎𝕏𝕐
    Boldface
    195 \mathbf{ABCDEFGHI}
    \mathbf{JKLMNOPQR}
    \mathbf{STUVWXYZ}
    \mathbf{abcdefghijklm}
    \mathbf{nopqrstuvwxyz}
    \mathbf{0123456789}
    𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳𝟎𝟏𝟐𝟑𝟒𝟓𝟔𝟕𝟖𝟗
    Boldface Greek
    196 \boldsymbol{\Alpha \Beta \Gamma \Delta
    \Epsilon \Zeta \Eta \Theta}
    𝚨𝚩𝚪𝚫𝚬𝚭𝚮𝚯
    197 \boldsymbol{\Iota \Kappa \Lambda \Mu \Nu \Xi
    \Omicron \Pi}
    𝚰𝚱𝚲𝚳𝚴𝚵𝚶𝚷
    198 \boldsymbol{\Rho \Sigma \Tau \Upsilon \Phi
    \Chi \Psi \Omega}
    𝚸𝚺𝚻𝚼𝚽𝚾𝚿𝛀
    199 \boldsymbol{\alpha \beta \gamma \delta
    \epsilon \zeta \eta \theta}
    𝜶𝜷𝜸𝜹𝝐𝜻𝜼𝜽
    200 \boldsymbol{\iota \kappa \lambda \mu \nu \xi
    \omicron \pi}
    𝜾𝜿𝝀𝝁𝝂𝝃𝝄𝝅
    201 \boldsymbol{\rho \sigma \tau \upsilon \phi
    \chi \psi \omega}
    𝝆𝝈𝝉𝝊𝝓𝝌𝝍𝝎
    202 \boldsymbol{\varepsilon\digamma\varkappa
    \varpi}
    𝜺ϝ𝝒𝝕
    203\boldsymbol{\varrho\varsigma\vartheta\varphi}𝝔𝝇𝝑𝝋
    Italics
    204\mathit{0123456789}0123456789
    Greek Italics
    205 \mathit{\Alpha \Beta \Gamma \Delta \Epsilon
    \Zeta \Eta \Theta}
    ΑΒΓΔΕΖΗΘ
    206 \mathit{\Iota \Kappa \Lambda \Mu \Nu \Xi
    \Omicron \Pi}
    ΙΚΛΜΝΞΟΠ
    207 \mathit{\Rho \Sigma \Tau \Upsilon \Phi \Chi
    \Psi \Omega}
    ΡΣΤΥΦΧΨΩ
    Greek uppercase boldface italics
    208 \boldsymbol{\varGamma \varDelta \varTheta
    \varLambda}
    𝜞𝜟𝜣𝜦
    209 \boldsymbol{\varXi \varPi \varSigma
    \varUpsilon \varOmega}
    𝜩𝜫𝜮𝜰𝜴
    Roman typeface
    210 \mathrm{ABCDEFGHI}
    \mathrm{JKLMNOPQR}
    \mathrm{STUVWXYZ}
    \mathrm{abcdefghijklm}
    \mathrm{nopqrstuvwxyz}
    \mathrm{0123456789}
    ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
    Sans serif
    211 \mathsf{ABCDEFGHI}
    \mathsf{JKLMNOPQR}
    \mathsf{STUVWXYZ}
    \mathsf{abcdefghijklm}
    \mathsf{nopqrstuvwxyz}
    \mathsf{0123456789}
    𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹𝖺𝖻𝖼𝖽𝖾𝖿𝗀𝗁𝗂𝗃𝗄𝗅𝗆𝗇𝗈𝗉𝗊𝗋𝗌𝗍𝗎𝗏𝗐𝗑𝗒𝗓𝟢𝟣𝟤𝟥𝟦𝟧𝟨𝟩𝟪𝟫
    Sans serif Greek
    212 \mathsf{\Alpha \Beta \Gamma \Delta \Epsilon
    \Zeta \Eta \Theta}
    𝝖𝝗𝝘𝝙𝝚𝝛𝝜𝝝
    213 \mathsf{\Iota \Kappa \Lambda \Mu \Nu \Xi
    \Omicron \Pi}
    𝝞𝝟𝝠𝝡𝝢𝝣𝝤𝝥
    214 \mathsf{\Rho \Sigma \Tau \Upsilon \Phi \Chi
    \Psi \Omega}
    𝝦𝝨𝝩𝝪𝝫𝝬𝝭𝝮
    -

    Unicode has special code points for bold Greek sans-serif, but no code points for
    regular-weight Greek sans-serif. Since Chromium is not going to support the math-variant
    attribute, these bold Greek sans-serif glyphs are the best approximation I can make to
    sans-serif Greek.

    -
    - - - - - - - - - - - - - - - - - - - -
    Calligraphy
    215 \mathcal{ABCDEFGHI}
    \mathcal{JKLMNOPQR}
    \mathcal{STUVWXYZ}
    \mathcal{abcdefghi}
    \mathcal{jklmnopqr}
    \mathcal{stuvwxyz}
    𝒜𝒞𝒟𝒢𝒥𝒦𝒩𝒪𝒫𝒬𝒮𝒯𝒰𝒱𝒲𝒳𝒴𝒵𝒶𝒷𝒸𝒹𝒻𝒽𝒾𝒿𝓀𝓁𝓂𝓃𝓅𝓆𝓇𝓈𝓉𝓊𝓋𝓌𝓍𝓎𝓏
    Fraktur
    216 \mathfrak{ABCDEFGHI}
    \mathfrak{JKLMNOPQR}
    \mathfrak{STUVWXYZ}
    \mathfrak{abcdefghi}
    \mathfrak{jklmnopqr}
    \mathfrak{stuvwxyz}
    𝔄𝔅𝔇𝔈𝔉𝔊𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔𝔖𝔗𝔘𝔙𝔚𝔛𝔜𝔞𝔟𝔠𝔡𝔢𝔣𝔤𝔥𝔦𝔧𝔨𝔩𝔪𝔫𝔬𝔭𝔮𝔯𝔰𝔱𝔲𝔳𝔴𝔵𝔶𝔷
    Scriptstyle text
    217{\scriptstyle\text{abcdefghijklm}}abcdefghijklm
    Mixed text faces
    218x y zxyz
    219\text{x y z}x y z
    220\text{if} n \text{is even}ifnis even
    221\text{if }n\text{ is even}if n is even
    222\text{if}~n\ \text{is even}if n is even
    Color
    223 {\color{Blue}x^2}+{\color{Orange}2x}-
    {\color{LimeGreen}1}
    x2+2x1
    224 x_{1,2}=\frac{{\color{Blue}-b}\pm
    \sqrt{\color{Red}b^2-4ac}}{\color{Green}2a }
    x1,2=b±b24ac2a
    225 {\color{Blue}x^2}+{\color{Orange}2x}-
    {\color{LimeGreen}1}
    x2+2x1
    226 \color{Blue}x^2\color{Black}+\color{Orange}
    2x\color{Black}-\color{LimeGreen}1
    x2+2x1
    227 \color{Blue}{x^2}+\color{Orange}{2x}-
    \color{LimeGreen}{1}
    x2+2x1
    228 \definecolor{myorange}{rgb}{1,0.65,0.4}
    \color{myorange}e^{i \pi}\color{Black} + 1= 0
    eiπ+1=0
    -

    For color names, see the color section in the Temml function support page.

    -
    - - - - - - - - - - - - - - - - -
    Spacing
    229 a \qquad b
    a \quad b
    a\ b
    a \text{ } b
    a\;b
    a\,b
    ab
    a b
    \mathit{ab}
    a\!b
    ababa ba babababababab
    230| \uparrow \rangle|
    231\left| \uparrow \right\rangle|
    232| {\uparrow} \rangle|
    233| \mathord\uparrow \rangle|
    Temml replacements for wiki workarounds
    234 \oiint\limits_D dx\,dy
    \oiiint\limits_E dx\,dy\,dz
    Ddxdy Edxdydz
    234\wideparen{AB}AB
    235\dddot{x}x
    236 \operatorname*{median}_
    {j\,\ne\,i} X_{i,j}
    medianjiXi,j
    237\sout{q}q
    238\mathrlap{\,/}{=}=
    239\text{\textsf{textual description}}𝗍𝖾𝗑𝗍𝗎𝖺𝗅 𝖽𝖾𝗌𝖼𝗋𝗂𝗉𝗍𝗂𝗈𝗇
    240α παπ
    -

    mhchem examples are displayed on their own test page.

    -
    - - - - - - - - - - - - - - - - - - - - - - -
    Examples of implemented TeX formulas
    241ax^2 + bx + c = 0ax2+bx+c=0
    242x=\frac{-b\pm\sqrt{b^2-4ac}}{2a}x=b±b24ac2a
    243 \left( \frac{\left(3-x\right)
    \times 2}{3-x} \right)
    ((3x)×23x)
    244 S_{\text{new}} = S_{\text{old}} -
    \frac{ \left( 5-T \right) ^2} {2}
    Snew=Sold(5T)22
    245 \int_a^x \int_a^s f(y)\,dy\,ds =
    \int_a^x f(y)(x-y)\,dy
    axasf(y)dyds=axf(y)(xy)dy
    246 \int_e^{\infty}\frac {1}{t(\ln t)^2}dt =
    \left. \frac{-1}{\ln t}\right\vert_e^\infty
    = 1
    e1t(lnt)2dt=1lnt|e=1
    247\det(\mathsf{A}-\lambda\mathsf{I}) = 0det(𝖠λ𝖨)=0
    248\sum_{i=0}^{n-1} ii=0n1i
    249 \sum_{m=1}^\infty\sum_{n=1}^\infty
    \frac{m^2 n}{3^m\left(m 3^n + n 3^m\right)}
    m=1n=1m2n3m(m3n+n3m)
    250u'' + p(x)u' + q(x)u=f(x),\quad x>au+p(x)u+q(x)u=f(x),x>a
    251 |\bar{z}| = |z|, |(\bar{z})^n| = |z|^n,
    \arg(z^n) = n \arg(z)
    |z|=|z|,|(z)n|=|z|n,arg(zn)=narg(z)
    252\lim_{z\to z_0} f(z)=f(z_0)limzz0f(z)=f(z0)
    253 \phi_n(\kappa) =
    \frac{1}{4\pi^2\kappa^2} \int_0^\infty
    \frac{\sin(\kappa R)}{\kappa R}
    \frac{\partial}{\partial R}
    \left [ R^2\frac{\partial D_n(R)}
    {\partial R} \right ] \,dR
    ϕn(κ)=14π2κ20sin(κR)κRR[R2Dn(R)R]dR
    254 \phi_n(\kappa) = 0.033C_n^2\kappa^{-11/3},
    \quad\frac{1}{L_0}\ll\kappa\ll\frac{1}{l_0}
    ϕn(κ)=0.033Cn2κ113,1L0κ1l0
    255 f(x) = \begin{cases}
    1 & -1 \le x < 0 \\
    \frac{1}{2} & x = 0 \\
    1 - x^2 & \text{otherwise}
    \end{cases}
    f(x)={11x<012x=01x2otherwise
    256 {}_pF_q(a_1,\dots,a_p;c_1,\dots,c_q;z)
    = \sum_{n=0}^\infty
    \frac{(a1)_n\cdots(ap)_n}
    {(c_1)_n\cdots(c_q)_n}\frac{z^n}{n!}
    pFq(a1,,ap;c1,,cq;z)=n=0(a1)n(ap)n(c1)n(cq)nznn!
    258\frac{a}{b}\ \tfrac{a}{b}ab ab
    259S=dD\sin\alphaS=dDsinα
    260 V = \frac{1}{6} \pi h \left [ 3 \left
    ( r1^2 + r2^2 \right ) + h^2 \right ]
    V=16πh[3(r12+r22)+h2]
    261 \begin{align}
    u & = \tfrac{1}{\sqrt{2}}(x+y) \qquad &
    x &= \tfrac{1}{\sqrt{2}}(u+v) \\[0.6ex]
    v & = \tfrac{1}{\sqrt{2}}(x-y) \qquad &
    y &= \tfrac{1}{\sqrt{2}}(u-v)
    \end{align}
    u=12(x+y)x=12(u+v)v=12(xy)y=12(uv)
    -

    That concludes the tests from Wikipedia. Now a few more tests.

    -
    - - - - - -
    Linear Logic
    262A \with B \parr CA&BC
    263a \coh \oc b \incoh \wn c \scoh d \sincoh ea!b?cde
    264a \Perp \shpos b \multimapinv \shneg cabc
    - - - -
    Nested font size
    265\mathrm{f{\large f{\normalsize f{\tiny f}}}}ffff
    -
    - - diff --git a/site/xml-formatter.js b/site/xml-formatter.js deleted file mode 100644 index c06fbf84..00000000 --- a/site/xml-formatter.js +++ /dev/null @@ -1,432 +0,0 @@ -require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i true); - - function nextChild() { - return tag() || content() || comment() || cdata(); - } - - function nextRootChild() { - match(/\s*/); - return tag(true) || comment() || doctype() || processingInstruction(false); - } - - function document() { - const decl = declaration(); - const children = []; - let documentRootNode; - let child = nextRootChild(); - - while (child) { - if (child.node.type === 'Element') { - if (documentRootNode) { - throw new Error('Found multiple root nodes'); - } - documentRootNode = child.node; - } - - if (!child.excluded) { - children.push(child.node); - } - - child = nextRootChild(); - } - - if (!documentRootNode) { - throw new Error('Failed to parse XML'); - } - - return { - declaration: decl ? decl.node : null, - root: documentRootNode, - children - }; - } - - function declaration() { - return processingInstruction(true); - } - - function processingInstruction(matchDeclaration) { - const m = matchDeclaration ? match(/^<\?(xml)\s*/) : match(/^<\?([\w-:.]+)\s*/); - if (!m) return; - - // tag - const node = { - name: m[1], - type: 'ProcessingInstruction', - attributes: {} - }; - - // attributes - while (!(eos() || is('?>'))) { - const attr = attribute(); - if (!attr) return node; - node.attributes[attr.name] = attr.value; - } - - match(/\?>/); - - return { - excluded: matchDeclaration ? false : options.filter(node) === false, - node - }; - } - - function tag(matchRoot) { - const m = match(/^<([\w-:.]+)\s*/); - if (!m) return; - - // name - const node = { - type: 'Element', - name: m[1], - attributes: {}, - children: [] - }; - - // attributes - while (!(eos() || is('>') || is('?>') || is('/>'))) { - const attr = attribute(); - if (!attr) return node; - node.attributes[attr.name] = attr.value; - } - - const excluded = matchRoot ? false : options.filter(node) === false; - - // self closing tag - if (match(/^\s*\/>/)) { - node.children = null; - return { - excluded, - node - }; - } - - match(/\??>/); - - if (!excluded) { - // children - let child = nextChild(); - while (child) { - if (!child.excluded) { - node.children.push(child.node); - } - child = nextChild(); - } - } - - // closing - match(/^<\/[\w-:.]+>/); - - return { - excluded, - node - }; - } - - function doctype() { - const m = match(/^]*>/); - if (m) { - const node = { - type: 'DocumentType', - content: m[0] - }; - return { - excluded: options.filter(node) === false, - node - }; - } - } - - function cdata() { - if (xml.startsWith(''); - if (endPositionStart > -1) { - const endPositionFinish = endPositionStart + 3; - const node = { - type: 'CDATA', - content: xml.substring(0, endPositionFinish) - }; - xml = xml.slice(endPositionFinish); - return { - excluded: options.filter(node) === false, - node - }; - } - } - } - - function comment() { - const m = match(/^/); - if (m) { - const node = { - type: 'Comment', - content: m[0] - }; - return { - excluded: options.filter(node) === false, - node - }; - } - } - - function content() { - const m = match(/^([^<]+)/); - if (m) { - const node = { - type: 'Text', - content: m[1] - }; - return { - excluded: options.filter(node) === false, - node - }; - } - } - - function attribute() { - const m = match(/([\w:-]+)\s*=\s*("[^"]*"|'[^']*'|\w+)\s*/); - if (!m) return; - return {name: m[1], value: strip(m[2])} - } - - /** - * Strip quotes from `val`. - */ - function strip(val) { - return val.replace(/^['"]|['"]$/g, ''); - } - - /** - * Match `re` and advance the string. - */ - function match(re) { - const m = xml.match(re); - if (!m) return; - xml = xml.slice(m[0].length); - return m; - } - - /** - * End-of-source. - */ - function eos() { - return 0 === xml.length; - } - - /** - * Check for `prefix`. - */ - function is(prefix) { - return 0 === xml.indexOf(prefix); - } - - xml = xml.trim(); - - return document(); -} - -module.exports = parse; - -},{}],"xml-formatter":[function(require,module,exports){ -/** - * @typedef {Object} XMLFormatterOptions - * @property {String} [indentation=' '] The value used for indentation - * @property {function(node): boolean} [filter] Return false to exclude the node. - * @property {Boolean} [collapseContent=false] True to keep content in the same line as the element. Only works if element contains at least one text node - * @property {String} [lineSeparator='\r\n'] The line separator to use - * @property {String} [whiteSpaceAtEndOfSelfclosingTag=false] to either end ad self closing tag with `` or `` - */ - -/** - * @typedef {Object} XMLFormatterState - * @param {String} content - * @param {Number} level - * @param {XMLFormatterOptions} options - */ - -/** - * @param {XMLFormatterState} state - * @return {void} - */ -function newLine(state) { - if (!state.options.indentation && !state.options.lineSeparator) return; - state.content += state.options.lineSeparator; - let i; - for (i = 0; i < state.level; i++) { - state.content += state.options.indentation; - } -} - -/** - * @param {XMLFormatterState} state - * @param {String} content - * @return {void} - */ -function appendContent(state, content) { - state.content += content; -} - -/** - * @param {Object} node - * @param {XMLFormatterState} state - * @param {Boolean} preserveSpace - * @return {void} - */ -function processNode(node, state, preserveSpace) { - if (typeof node.content === 'string') { - processContentNode(node, state, preserveSpace); - } else if (node.type === 'Element') { - processElementNode(node, state, preserveSpace); - } else if (node.type === 'ProcessingInstruction') { - processProcessingIntruction(node, state, preserveSpace); - } else { - throw new Error('Unknown node type: ' + node.type); - } -} - -/** - * @param {Object} node - * @param {XMLFormatterState} state - * @param {Boolean} preserveSpace - * @return {void} - */ -function processContentNode(node, state, preserveSpace) { - if (!preserveSpace) { - node.content = node.content.trim(); - } - if (node.content.length > 0) { - if (!preserveSpace && state.content.length > 0) { - newLine(state); - } - appendContent(state, node.content); - } -} - -/** - * @param {Object} node - * @param {XMLFormatterState} state - * @param {Boolean} preserveSpace - * @return {void} - */ -function processElementNode(node, state, preserveSpace) { - if (!preserveSpace && state.content.length > 0) { - newLine(state); - } - - appendContent(state, '<' + node.name); - processAttributes(state, node.attributes); - - if (node.children === null) { - const selfClosingNodeClosingTag = state.options.whiteSpaceAtEndOfSelfclosingTag ? ' />' : '/>' - // self-closing node - appendContent(state, selfClosingNodeClosingTag); - } else if (node.children.length === 0) { - // empty node - appendContent(state, '>'); - } else { - - appendContent(state, '>'); - - state.level++; - - let nodePreserveSpace = node.attributes['xml:space'] === 'preserve'; - - if (!nodePreserveSpace && state.options.collapseContent) { - - const containsTextNodes = node.children.some(function(child) { - return child.type === 'Text' && child.content.trim() !== ''; - }); - - if (containsTextNodes) { - nodePreserveSpace = true; - } - } - - node.children.forEach(function(child) { - processNode(child, state, preserveSpace || nodePreserveSpace, state.options); - }); - - state.level--; - - if (!preserveSpace && !nodePreserveSpace) { - newLine(state); - } - appendContent(state, ''); - } -} - -/** - * @param {XMLFormatterState} state - * @param {Record} attributes - * @return {void} - */ -function processAttributes(state, attributes) { - Object.keys(attributes).forEach(function(attr) { - const escaped = attributes[attr].replace(/"/g, '"'); - appendContent(state, ' ' + attr + '="' + escaped + '"'); - }); -} - -/** - * @param {Object} node - * @param {XMLFormatterState} state - * @return {void} - */ -function processProcessingIntruction(node, state) { - if (state.content.length > 0) { - newLine(state); - } - appendContent(state, ''); -} - - -/** - * Converts the given XML into human readable format. - * - * @param {String} xml - * @param {XMLFormatterOptions} options - * @returns {string} - */ -function format(xml, options = {}) { - options.indentation = 'indentation' in options ? options.indentation : ' '; - options.collapseContent = options.collapseContent === true; - options.lineSeparator = 'lineSeparator' in options ? options.lineSeparator : '\r\n'; - options.whiteSpaceAtEndOfSelfclosingTag = !!options.whiteSpaceAtEndOfSelfclosingTag; - - const parser = require('xml-parser-xo'); - const parsedXml = parser(xml, {filter: options.filter}); - const state = {content: '', level: 0, options: options}; - - if (parsedXml.declaration) { - processProcessingIntruction(parsedXml.declaration, state); - } - - parsedXml.children.forEach(function(child) { - processNode(child, state, false); - }); - - return state.content; -} - - -module.exports = format; - -},{"xml-parser-xo":1}]},{},[]); diff --git a/src/Lexer.js b/src/Lexer.js deleted file mode 100644 index 45d69378..00000000 --- a/src/Lexer.js +++ /dev/null @@ -1,121 +0,0 @@ -/** - * The Lexer class handles tokenizing the input in various ways. Since our - * parser expects us to be able to backtrack, the lexer allows lexing from any - * given starting point. - * - * Its main exposed function is the `lex` function, which takes a position to - * lex from and a type of token to lex. It defers to the appropriate `_innerLex` - * function. - * - * The various `_innerLex` functions perform the actual lexing of different - * kinds. - */ - -import ParseError from "./ParseError"; -import SourceLocation from "./SourceLocation"; -import { Token } from "./Token"; - -/* The following tokenRegex - * - matches typical whitespace (but not NBSP etc.) using its first two groups - * - does not match any control character \x00-\x1f except whitespace - * - does not match a bare backslash - * - matches any ASCII character except those just mentioned - * - does not match the BMP private use area \uE000-\uF8FF - * - does not match bare surrogate code units - * - matches any BMP character except for those just described - * - matches any valid Unicode surrogate pair - * - mathches numerals - * - matches a backslash followed by one or more whitespace characters - * - matches a backslash followed by one or more letters then whitespace - * - matches a backslash followed by any BMP character - * Capturing groups: - * [1] regular whitespace - * [2] backslash followed by whitespace - * [3] anything else, which may include: - * [4] left character of \verb* - * [5] left character of \verb - * [6] backslash followed by word, excluding any trailing whitespace - * Just because the Lexer matches something doesn't mean it's valid input: - * If there is no matching function or symbol definition, the Parser will - * still reject the input. - */ -const spaceRegexString = "[ \r\n\t]"; -const controlWordRegexString = "\\\\[a-zA-Z@]+"; -const controlSymbolRegexString = "\\\\[^\uD800-\uDFFF]"; -const controlWordWhitespaceRegexString = `(${controlWordRegexString})${spaceRegexString}*` -const controlSpaceRegexString = "\\\\(\n|[ \r\t]+\n?)[ \r\t]*"; -const combiningDiacriticalMarkString = "[\u0300-\u036f]"; -export const combiningDiacriticalMarksEndRegex = new RegExp(`${combiningDiacriticalMarkString}+$`); -const tokenRegexString = - `(${spaceRegexString}+)|` + // whitespace - `${controlSpaceRegexString}|` + // whitespace - "(number" + // numbers (in non-strict mode) - "|[!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + // single codepoint - `${combiningDiacriticalMarkString}*` + // ...plus accents - "|[\uD800-\uDBFF][\uDC00-\uDFFF]" + // surrogate pair - `${combiningDiacriticalMarkString}*` + // ...plus accents - "|\\\\verb\\*([^]).*?\\4" + // \verb* - "|\\\\verb([^*a-zA-Z]).*?\\5" + // \verb unstarred - `|${controlWordWhitespaceRegexString}` + // \macroName + spaces - `|${controlSymbolRegexString})`; // \\, \', etc. - -/** Main Lexer class */ -export default class Lexer { - constructor(input, settings) { - // Separate accents from characters - this.input = input; - this.settings = settings; - this.tokenRegex = new RegExp( - // Strict Temml, like TeX, lexes one numeral at a time. - // Default Temml lexes contiguous numerals into a single element. - tokenRegexString.replace("number|", settings.strict ? "" : "\\d(?:[\\d,.]*\\d)?|"), - "g" - ); - // Category codes. The lexer only supports comment characters (14) for now. - // MacroExpander additionally distinguishes active (13). - this.catcodes = { - "%": 14, // comment character - "~": 13 // active character - }; - } - - setCatcode(char, code) { - this.catcodes[char] = code; - } - - /** - * This function lexes a single token. - */ - lex() { - const input = this.input; - const pos = this.tokenRegex.lastIndex; - if (pos === input.length) { - return new Token("EOF", new SourceLocation(this, pos, pos)); - } - const match = this.tokenRegex.exec(input); - if (match === null || match.index !== pos) { - throw new ParseError( - `Unexpected character: '${input[pos]}'`, - new Token(input[pos], new SourceLocation(this, pos, pos + 1)) - ); - } - const text = match[6] || match[3] || (match[2] ? "\\ " : " ") - - if (this.catcodes[text] === 14) { - // comment character - const nlIndex = input.indexOf("\n", this.tokenRegex.lastIndex); - if (nlIndex === -1) { - this.tokenRegex.lastIndex = input.length; // EOF - if (this.settings.strict) { - throw new ParseError("% comment has no terminating newline; LaTeX would " + - "fail because of commenting the end of math mode") - } - } else { - this.tokenRegex.lastIndex = nlIndex + 1; - } - return this.lex(); - } - - return new Token(text, new SourceLocation(this, pos, this.tokenRegex.lastIndex)); - } -} diff --git a/src/MacroExpander.js b/src/MacroExpander.js deleted file mode 100644 index 1d5bf61a..00000000 --- a/src/MacroExpander.js +++ /dev/null @@ -1,437 +0,0 @@ -/** - * This file contains the “gullet” where macros are expanded - * until only non-macro tokens remain. - */ - -import functions from "./functions"; -import symbols from "./symbols"; -import Lexer from "./Lexer"; -import { Token } from "./Token"; - -import ParseError from "./ParseError"; -import Namespace from "./Namespace"; -import macros from "./macros"; - -// List of commands that act like macros but aren't defined as a macro, -// function, or symbol. Used in `isDefined`. -export const implicitCommands = { - "^": true, // Parser.js - _: true, // Parser.js - "\\limits": true, // Parser.js - "\\nolimits": true // Parser.js -}; - -export default class MacroExpander { - constructor(input, settings, mode) { - this.settings = settings; - this.expansionCount = 0; - this.feed(input); - // Make new global namespace - this.macros = new Namespace(macros, settings.macros); - this.mode = mode; - this.stack = []; // contains tokens in REVERSE order - } - - /** - * Feed a new input string to the same MacroExpander - * (with existing macros etc.). - */ - feed(input) { - this.lexer = new Lexer(input, this.settings); - } - - /** - * Switches between "text" and "math" modes. - */ - switchMode(newMode) { - this.mode = newMode; - } - - /** - * Start a new group nesting within all namespaces. - */ - beginGroup() { - this.macros.beginGroup(); - } - - /** - * End current group nesting within all namespaces. - */ - endGroup() { - this.macros.endGroup(); - } - - /** - * Returns the topmost token on the stack, without expanding it. - * Similar in behavior to TeX's `\futurelet`. - */ - future() { - if (this.stack.length === 0) { - this.pushToken(this.lexer.lex()) - } - return this.stack[this.stack.length - 1] - } - - /** - * Remove and return the next unexpanded token. - */ - popToken() { - this.future(); // ensure non-empty stack - return this.stack.pop(); - } - - /** - * Add a given token to the token stack. In particular, this get be used - * to put back a token returned from one of the other methods. - */ - pushToken(token) { - this.stack.push(token); - } - - /** - * Append an array of tokens to the token stack. - */ - pushTokens(tokens) { - this.stack.push(...tokens); - } - - /** - * Find an macro argument without expanding tokens and append the array of - * tokens to the token stack. Uses Token as a container for the result. - */ - scanArgument(isOptional) { - let start; - let end; - let tokens; - if (isOptional) { - this.consumeSpaces(); // \@ifnextchar gobbles any space following it - if (this.future().text !== "[") { - return null; - } - start = this.popToken(); // don't include [ in tokens - ({ tokens, end } = this.consumeArg(["]"])); - } else { - ({ tokens, start, end } = this.consumeArg()); - } - - // indicate the end of an argument - this.pushToken(new Token("EOF", end.loc)); - - this.pushTokens(tokens); - return start.range(end, ""); - } - - /** - * Consume all following space tokens, without expansion. - */ - consumeSpaces() { - for (;;) { - const token = this.future(); - if (token.text === " ") { - this.stack.pop(); - } else { - break; - } - } - } - - /** - * Consume an argument from the token stream, and return the resulting array - * of tokens and start/end token. - */ - consumeArg(delims) { - // The argument for a delimited parameter is the shortest (possibly - // empty) sequence of tokens with properly nested {...} groups that is - // followed ... by this particular list of non-parameter tokens. - // The argument for an undelimited parameter is the next nonblank - // token, unless that token is ‘{’, when the argument will be the - // entire {...} group that follows. - const tokens = []; - const isDelimited = delims && delims.length > 0; - if (!isDelimited) { - // Ignore spaces between arguments. As the TeXbook says: - // "After you have said ‘\def\row#1#2{...}’, you are allowed to - // put spaces between the arguments (e.g., ‘\row x n’), because - // TeX doesn’t use single spaces as undelimited arguments." - this.consumeSpaces(); - } - const start = this.future(); - let tok; - let depth = 0; - let match = 0; - do { - tok = this.popToken(); - tokens.push(tok); - if (tok.text === "{") { - ++depth; - } else if (tok.text === "}") { - --depth; - if (depth === -1) { - throw new ParseError("Extra }", tok); - } - } else if (tok.text === "EOF") { - throw new ParseError( - "Unexpected end of input in a macro argument" + - ", expected '" + - (delims && isDelimited ? delims[match] : "}") + - "'", - tok - ); - } - if (delims && isDelimited) { - if ((depth === 0 || (depth === 1 && delims[match] === "{")) && tok.text === delims[match]) { - ++match; - if (match === delims.length) { - // don't include delims in tokens - tokens.splice(-match, match); - break; - } - } else { - match = 0; - } - } - } while (depth !== 0 || isDelimited); - // If the argument found ... has the form ‘{}’, - // ... the outermost braces enclosing the argument are removed - if (start.text === "{" && tokens[tokens.length - 1].text === "}") { - tokens.pop(); - tokens.shift(); - } - tokens.reverse(); // to fit in with stack order - return { tokens, start, end: tok }; - } - - /** - * Consume the specified number of (delimited) arguments from the token - * stream and return the resulting array of arguments. - */ - consumeArgs(numArgs, delimiters) { - if (delimiters) { - if (delimiters.length !== numArgs + 1) { - throw new ParseError("The length of delimiters doesn't match the number of args!"); - } - const delims = delimiters[0]; - for (let i = 0; i < delims.length; i++) { - const tok = this.popToken(); - if (delims[i] !== tok.text) { - throw new ParseError("Use of the macro doesn't match its definition", tok); - } - } - } - - const args = []; - for (let i = 0; i < numArgs; i++) { - args.push(this.consumeArg(delimiters && delimiters[i + 1]).tokens); - } - return args; - } - - /** - * Expand the next token only once if possible. - * - * If the token is expanded, the resulting tokens will be pushed onto - * the stack in reverse order and will be returned as an array, - * also in reverse order. - * - * If not, the next token will be returned without removing it - * from the stack. This case can be detected by a `Token` return value - * instead of an `Array` return value. - * - * In either case, the next token will be on the top of the stack, - * or the stack will be empty. - * - * Used to implement `expandAfterFuture` and `expandNextToken`. - * - * If expandableOnly, only expandable tokens are expanded and - * an undefined control sequence results in an error. - */ - expandOnce(expandableOnly) { - const topToken = this.popToken(); - const name = topToken.text; - const expansion = !topToken.noexpand ? this._getExpansion(name) : null; - if (expansion == null || (expandableOnly && expansion.unexpandable)) { - if (expandableOnly && expansion == null && name[0] === "\\" && !this.isDefined(name)) { - throw new ParseError("Undefined control sequence: " + name); - } - this.pushToken(topToken); - return topToken; - } - this.expansionCount++; - if (this.expansionCount > this.settings.maxExpand) { - throw new ParseError( - "Too many expansions: infinite loop or " + "need to increase maxExpand setting" - ); - } - let tokens = expansion.tokens; - const args = this.consumeArgs(expansion.numArgs, expansion.delimiters); - if (expansion.numArgs) { - // paste arguments in place of the placeholders - tokens = tokens.slice(); // make a shallow copy - for (let i = tokens.length - 1; i >= 0; --i) { - let tok = tokens[i]; - if (tok.text === "#") { - if (i === 0) { - throw new ParseError("Incomplete placeholder at end of macro body", tok); - } - tok = tokens[--i]; // next token on stack - if (tok.text === "#") { - // ## → # - tokens.splice(i + 1, 1); // drop first # - } else if (/^[1-9]$/.test(tok.text)) { - // replace the placeholder with the indicated argument - tokens.splice(i, 2, ...args[+tok.text - 1]); - } else { - throw new ParseError("Not a valid argument number", tok); - } - } - } - } - // Concatenate expansion onto top of stack. - this.pushTokens(tokens); - return tokens; - } - - /** - * Expand the next token only once (if possible), and return the resulting - * top token on the stack (without removing anything from the stack). - * Similar in behavior to TeX's `\expandafter\futurelet`. - * Equivalent to expandOnce() followed by future(). - */ - expandAfterFuture() { - this.expandOnce(); - return this.future(); - } - - /** - * Recursively expand first token, then return first non-expandable token. - */ - expandNextToken() { - for (;;) { - const expanded = this.expandOnce(); - // expandOnce returns Token if and only if it's fully expanded. - if (expanded instanceof Token) { - // The token after \noexpand is interpreted as if its meaning were ‘\relax’ - if (expanded.treatAsRelax) { - expanded.text = "\\relax" - } - return this.stack.pop(); // === expanded - } - } - - // This pathway is impossible. - throw new Error(); // eslint-disable-line no-unreachable - } - - /** - * Fully expand the given macro name and return the resulting list of - * tokens, or return `undefined` if no such macro is defined. - */ - expandMacro(name) { - return this.macros.has(name) ? this.expandTokens([new Token(name)]) : undefined; - } - - /** - * Fully expand the given token stream and return the resulting list of - * tokens. Note that the input tokens are in reverse order, but the - * output tokens are in forward order. - */ - expandTokens(tokens) { - const output = []; - const oldStackLength = this.stack.length; - this.pushTokens(tokens); - while (this.stack.length > oldStackLength) { - const expanded = this.expandOnce(true); // expand only expandable tokens - // expandOnce returns Token if and only if it's fully expanded. - if (expanded instanceof Token) { - if (expanded.treatAsRelax) { - // the expansion of \noexpand is the token itself - expanded.noexpand = false; - expanded.treatAsRelax = false; - } - output.push(this.stack.pop()); - } - } - return output; - } - - /** - * Fully expand the given macro name and return the result as a string, - * or return `undefined` if no such macro is defined. - */ - expandMacroAsText(name) { - const tokens = this.expandMacro(name); - if (tokens) { - return tokens.map((token) => token.text).join(""); - } else { - return tokens; - } - } - - /** - * Returns the expanded macro as a reversed array of tokens and a macro - * argument count. Or returns `null` if no such macro. - */ - _getExpansion(name) { - const definition = this.macros.get(name); - if (definition == null) { - // mainly checking for undefined here - return definition; - } - // If a single character has an associated catcode other than 13 - // (active character), then don't expand it. - if (name.length === 1) { - const catcode = this.lexer.catcodes[name] - if (catcode != null && catcode !== 13) { - return - } - } - const expansion = typeof definition === "function" ? definition(this) : definition; - if (typeof expansion === "string") { - let numArgs = 0; - if (expansion.indexOf("#") !== -1) { - const stripped = expansion.replace(/##/g, ""); - while (stripped.indexOf("#" + (numArgs + 1)) !== -1) { - ++numArgs; - } - } - const bodyLexer = new Lexer(expansion, this.settings); - const tokens = []; - let tok = bodyLexer.lex(); - while (tok.text !== "EOF") { - tokens.push(tok); - tok = bodyLexer.lex(); - } - tokens.reverse(); // to fit in with stack using push and pop - const expanded = { tokens, numArgs }; - return expanded; - } - - return expansion; - } - - /** - * Determine whether a command is currently "defined" (has some - * functionality), meaning that it's a macro (in the current group), - * a function, a symbol, or one of the special commands listed in - * `implicitCommands`. - */ - isDefined(name) { - return ( - this.macros.has(name) || - Object.prototype.hasOwnProperty.call(functions, name ) || - Object.prototype.hasOwnProperty.call(symbols.math, name ) || - Object.prototype.hasOwnProperty.call(symbols.text, name ) || - Object.prototype.hasOwnProperty.call(implicitCommands, name ) - ); - } - - /** - * Determine whether a command is expandable. - */ - isExpandable(name) { - const macro = this.macros.get(name); - return macro != null - ? typeof macro === "string" || typeof macro === "function" || !macro.unexpandable - : Object.prototype.hasOwnProperty.call(functions, name ) && !functions[name].primitive; - } -} diff --git a/src/Namespace.js b/src/Namespace.js deleted file mode 100644 index b32f4a4e..00000000 --- a/src/Namespace.js +++ /dev/null @@ -1,91 +0,0 @@ -/** - * A `Namespace` refers to a space of nameable things like macros or lengths, - * which can be `set` either globally or local to a nested group, using an - * undo stack similar to how TeX implements this functionality. - * Performance-wise, `get` and `set` take constant time. - */ - -import ParseError from "./ParseError"; - -export default class Namespace { - /** - * Both arguments are optional. The first argument is an object of - * built-in mappings which never change. The second argument is an object - * of initial (global-level) mappings, which will constantly change - * according to any global/top-level `set`s done. - */ - constructor(builtins = {}, globalMacros = {}) { - this.current = globalMacros; - this.builtins = builtins; - this.undefStack = []; - } - - /** - * Start a new nested group, affecting future local `set`s. - */ - beginGroup() { - this.undefStack.push({}); - } - - /** - * End current nested group, restoring values before the group began. - */ - endGroup() { - if (this.undefStack.length === 0) { - throw new ParseError( - "Unbalanced namespace destruction: attempt " + - "to pop global namespace; please report this as a bug" - ); - } - const undefs = this.undefStack.pop(); - for (const undef in undefs) { - if (Object.prototype.hasOwnProperty.call(undefs, undef )) { - if (undefs[undef] === undefined) { - delete this.current[undef]; - } else { - this.current[undef] = undefs[undef]; - } - } - } - } - - /** - * Detect whether `name` has a definition. Equivalent to - * `get(name) != null`. - */ - has(name) { - return Object.prototype.hasOwnProperty.call(this.current, name ) || - Object.prototype.hasOwnProperty.call(this.builtins, name ); - } - - /** - * Get the current value of a name, or `undefined` if there is no value. - * - * Note: Do not use `if (namespace.get(...))` to detect whether a macro - * is defined, as the definition may be the empty string which evaluates - * to `false` in JavaScript. Use `if (namespace.get(...) != null)` or - * `if (namespace.has(...))`. - */ - get(name) { - if (Object.prototype.hasOwnProperty.call(this.current, name )) { - return this.current[name]; - } else { - return this.builtins[name]; - } - } - - /** - * Set the current value of a name, and adds an undo - * operation to the undo stack. - */ - set(name, value) { - // Undo this set at end of this group (possibly to `undefined`), - // unless an undo is already in place, in which case that older - // value is the correct one. - const top = this.undefStack[this.undefStack.length - 1]; - if (top && !Object.prototype.hasOwnProperty.call(top, name )) { - top[name] = this.current[name]; - } - this.current[name] = value; - } -} diff --git a/src/ParseError.js b/src/ParseError.js deleted file mode 100644 index ea31ca09..00000000 --- a/src/ParseError.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * This is the ParseError class, which is the main error thrown by Temml - * functions when something has gone wrong. This is used to distinguish internal - * errors from errors in the expression that the user provided. - * - * If possible, a caller should provide a Token or ParseNode with information - * about where in the source string the problem occurred. - */ -class ParseError { - constructor( - message, // The error message - token // An object providing position information - ) { - let error = " " + message; - let start; - - const loc = token && token.loc; - if (loc && loc.start <= loc.end) { - // If we have the input and a position, make the error a bit fancier - - // Get the input - const input = loc.lexer.input; - - // Prepend some information - start = loc.start; - const end = loc.end; - if (start === input.length) { - error += " at end of input: "; - } else { - error += " at position " + (start + 1) + ": "; - } - - // Underline token in question using combining underscores - const underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332"); - - // Extract some context from the input and add it to the error - let left; - if (start > 15) { - left = "…" + input.slice(start - 15, start); - } else { - left = input.slice(0, start); - } - let right; - if (end + 15 < input.length) { - right = input.slice(end, end + 15) + "…"; - } else { - right = input.slice(end); - } - error += left + underlined + right; - } - - // Some hackery to make ParseError a prototype of Error - // See http://stackoverflow.com/a/8460753 - const self = new Error(error); - self.name = "ParseError"; - self.__proto__ = ParseError.prototype; - self.position = start; - return self; - } -} - -ParseError.prototype.__proto__ = Error.prototype; - -export default ParseError; diff --git a/src/Parser.js b/src/Parser.js deleted file mode 100644 index a3113b72..00000000 --- a/src/Parser.js +++ /dev/null @@ -1,948 +0,0 @@ -/* eslint no-constant-condition:0 */ -import functions from "./functions"; -import MacroExpander, { implicitCommands } from "./MacroExpander"; -import symbols, { ATOMS } from "./symbols"; -import { validUnit } from "./units"; -import { supportedCodepoint } from "./unicodeScripts"; -import ParseError from "./ParseError"; -import { combiningDiacriticalMarksEndRegex } from "./Lexer"; -import { uSubsAndSups, unicodeSubRegEx } from "./unicodeSupOrSub" -import SourceLocation from "./SourceLocation"; - -// Pre-evaluate both modules as unicodeSymbols require String.normalize() -import unicodeAccents from /*preval*/ "./unicodeAccents"; -import unicodeSymbols from /*preval*/ "./unicodeSymbols"; - -const numberRegEx = /^\d(?:[\d,.]*\d)?$/ // Keep in sync with numberRegEx in symbolsOrd.js - -/** - * This file contains the parser used to parse out a TeX expression from the - * input. Since TeX isn't context-free, standard parsers don't work particularly - * well. - * - * The strategy of this parser is as such: - * - * The main functions (the `.parse...` ones) take a position in the current - * parse string to parse tokens from. The lexer (found in Lexer.js, stored at - * this.gullet.lexer) also supports pulling out tokens at arbitrary places. When - * individual tokens are needed at a position, the lexer is called to pull out a - * token, which is then used. - * - * The parser has a property called "mode" indicating the mode that - * the parser is currently in. Currently it has to be one of "math" or - * "text", which denotes whether the current environment is a math-y - * one or a text-y one (e.g. inside \text). Currently, this serves to - * limit the functions which can be used in text mode. - * - * The main functions then return an object which contains the useful data that - * was parsed at its given point, and a new position at the end of the parsed - * data. The main functions can call each other and continue the parsing by - * using the returned position as a new starting point. - * - * There are also extra `.handle...` functions, which pull out some reused - * functionality into self-contained functions. - * - * The functions return ParseNodes. - */ - -export default class Parser { - constructor(input, settings, isPreamble = false) { - // Start in math mode - this.mode = "math"; - // Create a new macro expander (gullet) and (indirectly via that) also a - // new lexer (mouth) for this parser (stomach, in the language of TeX) - this.gullet = new MacroExpander(input, settings, this.mode); - // Store the settings for use in parsing - this.settings = settings; - // Are we defining a preamble? - this.isPreamble = isPreamble; - // Count leftright depth (for \middle errors) - this.leftrightDepth = 0; - this.prevAtomType = ""; - } - - /** - * Checks a result to make sure it has the right type, and throws an - * appropriate error otherwise. - */ - expect(text, consume = true) { - if (this.fetch().text !== text) { - throw new ParseError(`Expected '${text}', got '${this.fetch().text}'`, this.fetch()); - } - if (consume) { - this.consume(); - } - } - - /** - * Discards the current lookahead token, considering it consumed. - */ - consume() { - this.nextToken = null; - } - - /** - * Return the current lookahead token, or if there isn't one (at the - * beginning, or if the previous lookahead token was consume()d), - * fetch the next token as the new lookahead token and return it. - */ - fetch() { - if (this.nextToken == null) { - this.nextToken = this.gullet.expandNextToken(); - } - return this.nextToken; - } - - /** - * Switches between "text" and "math" modes. - */ - switchMode(newMode) { - this.mode = newMode; - this.gullet.switchMode(newMode); - } - - /** - * Main parsing function, which parses an entire input. - */ - parse() { - // Create a group namespace for every $...$, $$...$$, \[...\].) - // A \def is then valid only within that pair of delimiters. - this.gullet.beginGroup(); - - if (this.settings.colorIsTextColor) { - // Use old \color behavior (same as LaTeX's \textcolor) if requested. - // We do this within the group for the math expression, so it doesn't - // pollute settings.macros. - this.gullet.macros.set("\\color", "\\textcolor"); - } - - // Try to parse the input - const parse = this.parseExpression(false); - - // If we succeeded, make sure there's an EOF at the end - this.expect("EOF"); - - if (this.isPreamble) { - const macros = Object.create(null) - Object.entries(this.gullet.macros.current).forEach(([key, value]) => { - macros[key] = value - }) - this.gullet.endGroup(); - return macros - } - - // The only local macro that we want to save is from \tag. - const tag = this.gullet.macros.get("\\df@tag") - - // End the group namespace for the expression - this.gullet.endGroup(); - - if (tag) { this.gullet.macros.current["\\df@tag"] = tag } - - return parse; - } - - static get endOfExpression() { - return ["}", "\\endgroup", "\\end", "\\right", "\\endtoggle", "&"]; - } - - /** - * Parses an "expression", which is a list of atoms. - * - * `breakOnInfix`: Should the parsing stop when we hit infix nodes? This - * happens when functions have higher precendence han infix - * nodes in implicit parses. - * - * `breakOnTokenText`: The text of the token that the expression should end - * with, or `null` if something else should end the - * expression. - */ - parseExpression(breakOnInfix, breakOnTokenText) { - const body = []; - // Keep adding atoms to the body until we can't parse any more atoms (either - // we reached the end, a }, or a \right) - while (true) { - // Ignore spaces in math mode - if (this.mode === "math") { - this.consumeSpaces(); - } - const lex = this.fetch(); - if (Parser.endOfExpression.indexOf(lex.text) !== -1) { - break; - } - if (breakOnTokenText && lex.text === breakOnTokenText) { - break; - } - if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) { - break; - } - const atom = this.parseAtom(breakOnTokenText); - if (!atom) { - break; - } else if (atom.type === "internal") { - continue; - } - body.push(atom); - // Keep a record of the atom type, so that op.js can set correct spacing. - this.prevAtomType = atom.type === "atom" ? atom.family : atom.type; - } - if (this.mode === "text") { - this.formLigatures(body); - } - return this.handleInfixNodes(body); - } - - /** - * Rewrites infix operators such as \over with corresponding commands such - * as \frac. - * - * There can only be one infix operator per group. If there's more than one - * then the expression is ambiguous. This can be resolved by adding {}. - */ - handleInfixNodes(body) { - let overIndex = -1; - let funcName; - - for (let i = 0; i < body.length; i++) { - if (body[i].type === "infix") { - if (overIndex !== -1) { - throw new ParseError("only one infix operator per group", body[i].token); - } - overIndex = i; - funcName = body[i].replaceWith; - } - } - - if (overIndex !== -1 && funcName) { - let numerNode; - let denomNode; - - const numerBody = body.slice(0, overIndex); - const denomBody = body.slice(overIndex + 1); - - if (numerBody.length === 1 && numerBody[0].type === "ordgroup") { - numerNode = numerBody[0]; - } else { - numerNode = { type: "ordgroup", mode: this.mode, body: numerBody }; - } - - if (denomBody.length === 1 && denomBody[0].type === "ordgroup") { - denomNode = denomBody[0]; - } else { - denomNode = { type: "ordgroup", mode: this.mode, body: denomBody }; - } - - let node; - if (funcName === "\\\\abovefrac") { - node = this.callFunction(funcName, [numerNode, body[overIndex], denomNode], []); - } else { - node = this.callFunction(funcName, [numerNode, denomNode], []); - } - return [node]; - } else { - return body; - } - } - - /** - * Handle a subscript or superscript with nice errors. - */ - handleSupSubscript( - name // For error reporting. - ) { - const symbolToken = this.fetch(); - const symbol = symbolToken.text; - this.consume(); - this.consumeSpaces(); // ignore spaces before sup/subscript argument - const group = this.parseGroup(name); - - if (!group) { - throw new ParseError("Expected group after '" + symbol + "'", symbolToken); - } - - return group; - } - - /** - * Converts the textual input of an unsupported command into a text node - * contained within a color node whose color is determined by errorColor - */ - formatUnsupportedCmd(text) { - const textordArray = []; - - for (let i = 0; i < text.length; i++) { - textordArray.push({ type: "textord", mode: "text", text: text[i] }); - } - - const textNode = { - type: "text", - mode: this.mode, - body: textordArray - }; - - const colorNode = { - type: "color", - mode: this.mode, - color: this.settings.errorColor, - body: [textNode] - }; - - return colorNode; - } - - /** - * Parses a group with optional super/subscripts. - */ - parseAtom(breakOnTokenText) { - // The body of an atom is an implicit group, so that things like - // \left(x\right)^2 work correctly. - const base = this.parseGroup("atom", breakOnTokenText); - - // In text mode, we don't have superscripts or subscripts - if (this.mode === "text") { - return base; - } - - // Note that base may be empty (i.e. null) at this point. - - let superscript; - let subscript; - while (true) { - // Guaranteed in math mode, so eat any spaces first. - this.consumeSpaces(); - - // Lex the first token - const lex = this.fetch(); - - if (lex.text === "\\limits" || lex.text === "\\nolimits") { - // We got a limit control - if (base && base.type === "op") { - const limits = lex.text === "\\limits"; - base.limits = limits; - base.alwaysHandleSupSub = true; - } else if (base && base.type === "operatorname") { - if (base.alwaysHandleSupSub) { - base.limits = lex.text === "\\limits" - } - } else { - throw new ParseError("Limit controls must follow a math operator", lex); - } - this.consume(); - } else if (lex.text === "^") { - // We got a superscript start - if (superscript) { - throw new ParseError("Double superscript", lex); - } - superscript = this.handleSupSubscript("superscript"); - } else if (lex.text === "_") { - // We got a subscript start - if (subscript) { - throw new ParseError("Double subscript", lex); - } - subscript = this.handleSupSubscript("subscript"); - } else if (lex.text === "'") { - // We got a prime - if (superscript) { - throw new ParseError("Double superscript", lex); - } - const prime = { type: "textord", mode: this.mode, text: "\\prime" }; - - // Many primes can be grouped together, so we handle this here - const primes = [prime]; - this.consume(); - // Keep lexing tokens until we get something that's not a prime - while (this.fetch().text === "'") { - // For each one, add another prime to the list - primes.push(prime); - this.consume(); - } - // If there's a superscript following the primes, combine that - // superscript in with the primes. - if (this.fetch().text === "^") { - primes.push(this.handleSupSubscript("superscript")); - } - // Put everything into an ordgroup as the superscript - superscript = { type: "ordgroup", mode: this.mode, body: primes }; - } else if (uSubsAndSups[lex.text]) { - // A Unicode subscript or superscript character. - // We treat these similarly to the unicode-math package. - // So we render a string of Unicode (sub|super)scripts the - // same as a (sub|super)script of regular characters. - let str = uSubsAndSups[lex.text] - const isSub = unicodeSubRegEx.test(lex.text) - this.consume() - // Continue fetching tokens to fill out the string. - while (true) { - const token = this.fetch().text - if (!(uSubsAndSups[token])) { break } - if (unicodeSubRegEx.test(token) !== isSub) { break } - this.consume() - str += uSubsAndSups[token] - } - // Now create a (sub|super)script. - const body = (new Parser(str, this.settings)).parse() - if (isSub) { - subscript = { type: "ordgroup", mode: "math", body } - } else { - superscript = { type: "ordgroup", mode: "math", body } - } - } else { - // If it wasn't ^, _, a Unicode (sub|super)script, or ', stop parsing super/subscripts - break; - } - } - - if (superscript || subscript) { - if (base && base.type === "multiscript" && !base.postscripts) { - // base is the result of a \prescript function. - // Write the sub- & superscripts into the multiscript element. - base.postscripts = { sup: superscript, sub: subscript } - return base - } else { - // We got either a superscript or subscript, create a supsub - return { - type: "supsub", - mode: this.mode, - base: base, - sup: superscript, - sub: subscript - } - } - } else { - // Otherwise return the original body - return base; - } - } - - /** - * Parses an entire function, including its base and all of its arguments. - */ - parseFunction( - breakOnTokenText, - name // For determining its context - ) { - const token = this.fetch(); - const func = token.text; - const funcData = functions[func]; - if (!funcData) { - return null; - } - this.consume(); // consume command token - - if (name && name !== "atom" && !funcData.allowedInArgument) { - throw new ParseError( - "Got function '" + func + "' with no arguments" + (name ? " as " + name : ""), - token - ); - } else if (this.mode === "text" && !funcData.allowedInText) { - throw new ParseError("Can't use function '" + func + "' in text mode", token); - } else if (this.mode === "math" && funcData.allowedInMath === false) { - throw new ParseError("Can't use function '" + func + "' in math mode", token); - } - - const prevAtomType = this.prevAtomType; - const { args, optArgs } = this.parseArguments(func, funcData); - this.prevAtomType = prevAtomType; - return this.callFunction(func, args, optArgs, token, breakOnTokenText); - } - - /** - * Call a function handler with a suitable context and arguments. - */ - callFunction(name, args, optArgs, token, breakOnTokenText) { - const context = { - funcName: name, - parser: this, - token, - breakOnTokenText - }; - const func = functions[name]; - if (func && func.handler) { - return func.handler(context, args, optArgs); - } else { - throw new ParseError(`No function handler for ${name}`); - } - } - - /** - * Parses the arguments of a function or environment - */ - parseArguments( - func, // Should look like "\name" or "\begin{name}". - funcData - ) { - const totalArgs = funcData.numArgs + funcData.numOptionalArgs; - if (totalArgs === 0) { - return { args: [], optArgs: [] }; - } - - const args = []; - const optArgs = []; - - for (let i = 0; i < totalArgs; i++) { - let argType = funcData.argTypes && funcData.argTypes[i]; - const isOptional = i < funcData.numOptionalArgs; - - if ( - (funcData.primitive && argType == null) || - // \sqrt expands into primitive if optional argument doesn't exist - (funcData.type === "sqrt" && i === 1 && optArgs[0] == null) - ) { - argType = "primitive"; - } - - const arg = this.parseGroupOfType(`argument to '${func}'`, argType, isOptional); - if (isOptional) { - optArgs.push(arg); - } else if (arg != null) { - args.push(arg); - } else { - // should be unreachable - throw new ParseError("Null argument, please report this as a bug"); - } - } - - return { args, optArgs }; - } - - /** - * Parses a group when the mode is changing. - */ - parseGroupOfType(name, type, optional) { - switch (type) { - case "size": - return this.parseSizeGroup(optional); - case "url": - return this.parseUrlGroup(optional); - case "math": - case "text": - return this.parseArgumentGroup(optional, type); - case "hbox": { - // hbox argument type wraps the argument in the equivalent of - // \hbox, which is like \text but switching to \textstyle size. - const group = this.parseArgumentGroup(optional, "text"); - return group != null - ? { - type: "styling", - mode: group.mode, - body: [group], - scriptLevel: "text" // simulate \textstyle - } - : null; - } - case "raw": { - const token = this.parseStringGroup("raw", optional); - return token != null - ? { - type: "raw", - mode: "text", - string: token.text - } - : null; - } - case "primitive": { - if (optional) { - throw new ParseError("A primitive argument cannot be optional"); - } - const group = this.parseGroup(name); - if (group == null) { - throw new ParseError("Expected group as " + name, this.fetch()); - } - return group; - } - case "original": - case null: - case undefined: - return this.parseArgumentGroup(optional); - default: - throw new ParseError("Unknown group type as " + name, this.fetch()); - } - } - - /** - * Discard any space tokens, fetching the next non-space token. - */ - consumeSpaces() { - while (this.fetch().text === " ") { - this.consume(); - } - } - - /** - * Parses a group, essentially returning the string formed by the - * brace-enclosed tokens plus some position information. - */ - parseStringGroup( - modeName, // Used to describe the mode in error messages. - optional - ) { - const argToken = this.gullet.scanArgument(optional); - if (argToken == null) { - return null; - } - let str = ""; - let nextToken; - while ((nextToken = this.fetch()).text !== "EOF") { - str += nextToken.text; - this.consume(); - } - this.consume(); // consume the end of the argument - argToken.text = str; - return argToken; - } - - /** - * Parses a regex-delimited group: the largest sequence of tokens - * whose concatenated strings match `regex`. Returns the string - * formed by the tokens plus some position information. - */ - parseRegexGroup( - regex, - modeName // Used to describe the mode in error messages. - ) { - const firstToken = this.fetch(); - let lastToken = firstToken; - let str = ""; - let nextToken; - while ((nextToken = this.fetch()).text !== "EOF" && regex.test(str + nextToken.text)) { - lastToken = nextToken; - str += lastToken.text; - this.consume(); - } - if (str === "") { - throw new ParseError("Invalid " + modeName + ": '" + firstToken.text + "'", firstToken); - } - return firstToken.range(lastToken, str); - } - - /** - * Parses a size specification, consisting of magnitude and unit. - */ - parseSizeGroup(optional) { - let res; - let isBlank = false; - // don't expand before parseStringGroup - this.gullet.consumeSpaces(); - if (!optional && this.gullet.future().text !== "{") { - res = this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size"); - } else { - res = this.parseStringGroup("size", optional); - } - if (!res) { - return null; - } - if (!optional && res.text.length === 0) { - // Because we've tested for what is !optional, this block won't - // affect \kern, \hspace, etc. It will capture the mandatory arguments - // to \genfrac and \above. - res.text = "0pt"; // Enable \above{} - isBlank = true; // This is here specifically for \genfrac - } - const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(res.text); - if (!match) { - throw new ParseError("Invalid size: '" + res.text + "'", res); - } - const data = { - number: +(match[1] + match[2]), // sign + magnitude, cast to number - unit: match[3] - }; - if (!validUnit(data)) { - throw new ParseError("Invalid unit: '" + data.unit + "'", res); - } - return { - type: "size", - mode: this.mode, - value: data, - isBlank - }; - } - - /** - * Parses an URL, checking escaped letters and allowed protocols, - * and setting the catcode of % as an active character (as in \hyperref). - */ - parseUrlGroup(optional) { - this.gullet.lexer.setCatcode("%", 13); // active character - this.gullet.lexer.setCatcode("~", 12); // other character - const res = this.parseStringGroup("url", optional); - this.gullet.lexer.setCatcode("%", 14); // comment character - this.gullet.lexer.setCatcode("~", 13); // active character - if (res == null) { - return null; - } - // hyperref package allows backslashes alone in href, but doesn't - // generate valid links in such cases; we interpret this as - // "undefined" behaviour, and keep them as-is. Some browser will - // replace backslashes with forward slashes. - let url = res.text.replace(/\\([#$%&~_^{}])/g, "$1"); - url = res.text.replace(/{\u2044}/g, "/"); - return { - type: "url", - mode: this.mode, - url - }; - } - - /** - * Parses an argument with the mode specified. - */ - parseArgumentGroup(optional, mode) { - const argToken = this.gullet.scanArgument(optional); - if (argToken == null) { - return null; - } - const outerMode = this.mode; - if (mode) { - // Switch to specified mode - this.switchMode(mode); - } - - this.gullet.beginGroup(); - const expression = this.parseExpression(false, "EOF"); - // TODO: find an alternative way to denote the end - this.expect("EOF"); // expect the end of the argument - this.gullet.endGroup(); - const result = { - type: "ordgroup", - mode: this.mode, - loc: argToken.loc, - body: expression - }; - - if (mode) { - // Switch mode back - this.switchMode(outerMode); - } - return result; - } - - /** - * Parses an ordinary group, which is either a single nucleus (like "x") - * or an expression in braces (like "{x+y}") or an implicit group, a group - * that starts at the current position, and ends right before a higher explicit - * group ends, or at EOF. - */ - parseGroup( - name, // For error reporting. - breakOnTokenText - ) { - const firstToken = this.fetch(); - const text = firstToken.text; - - let result; - // Try to parse an open brace or \begingroup - if (text === "{" || text === "\\begingroup" || text === "\\toggle") { - this.consume(); - const groupEnd = text === "{" - ? "}" - : text === "\\begingroup" - ? "\\endgroup" - : "\\endtoggle" - - this.gullet.beginGroup(); - // If we get a brace, parse an expression - const expression = this.parseExpression(false, groupEnd); - const lastToken = this.fetch(); - this.expect(groupEnd); // Check that we got a matching closing brace - this.gullet.endGroup(); - result = { - type: (lastToken.text === "\\endtoggle" ? "toggle" : "ordgroup"), - mode: this.mode, - loc: SourceLocation.range(firstToken, lastToken), - body: expression, - // A group formed by \begingroup...\endgroup is a semi-simple group - // which doesn't affect spacing in math mode, i.e., is transparent. - // https://tex.stackexchange.com/questions/1930/when-should-one- - // use-begingroup-instead-of-bgroup - semisimple: text === "\\begingroup" || undefined - }; - } else { - // If there exists a function with this name, parse the function. - // Otherwise, just return a nucleus - result = this.parseFunction(breakOnTokenText, name) || this.parseSymbol(); - if (result == null && text[0] === "\\" && - !Object.prototype.hasOwnProperty.call(implicitCommands, text )) { - result = this.formatUnsupportedCmd(text); - this.consume(); - } - } - return result; - } - - /** - * Form ligature-like combinations of characters for text mode. - * This includes inputs like "--", "---", "``" and "''". - * The result will simply replace multiple textord nodes with a single - * character in each value by a single textord node having multiple - * characters in its value. The representation is still ASCII source. - * The group will be modified in place. - */ - formLigatures(group) { - let n = group.length - 1; - for (let i = 0; i < n; ++i) { - const a = group[i]; - const v = a.text; - if (v === "-" && group[i + 1].text === "-") { - if (i + 1 < n && group[i + 2].text === "-") { - group.splice(i, 3, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 2]), - text: "---" - }); - n -= 2; - } else { - group.splice(i, 2, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 1]), - text: "--" - }); - n -= 1; - } - } - if ((v === "'" || v === "`") && group[i + 1].text === v) { - group.splice(i, 2, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 1]), - text: v + v - }); - n -= 1; - } - } - } - - /** - * Parse a single symbol out of the string. Here, we handle single character - * symbols and special functions like \verb. - */ - parseSymbol() { - const nucleus = this.fetch(); - let text = nucleus.text; - - if (/^\\verb[^a-zA-Z]/.test(text)) { - this.consume(); - let arg = text.slice(5); - const star = arg.charAt(0) === "*"; - if (star) { - arg = arg.slice(1); - } - // Lexer's tokenRegex is constructed to always have matching - // first/last characters. - if (arg.length < 2 || arg.charAt(0) !== arg.slice(-1)) { - throw new ParseError(`\\verb assertion failed -- - please report what input caused this bug`); - } - arg = arg.slice(1, -1); // remove first and last char - return { - type: "verb", - mode: "text", - body: arg, - star - }; - } - // At this point, we should have a symbol, possibly with accents. - // First expand any accented base symbol according to unicodeSymbols. - if (Object.prototype.hasOwnProperty.call(unicodeSymbols, text[0]) && - !symbols[this.mode][text[0]]) { - // This behavior is not strict (XeTeX-compatible) in math mode. - if (this.settings.strict && this.mode === "math") { - throw new ParseError(`Accented Unicode text character "${text[0]}" used in ` + `math mode`, - nucleus - ); - } - text = unicodeSymbols[text[0]] + text.slice(1); - } - // Strip off any combining characters - const match = combiningDiacriticalMarksEndRegex.exec(text); - if (match) { - text = text.substring(0, match.index); - if (text === "i") { - text = "\u0131"; // dotless i, in math and text mode - } else if (text === "j") { - text = "\u0237"; // dotless j, in math and text mode - } - } - // Recognize base symbol - let symbol; - if (symbols[this.mode][text]) { - const group = symbols[this.mode][text].group; - const loc = SourceLocation.range(nucleus); - let s; - if (Object.prototype.hasOwnProperty.call(ATOMS, group )) { - const family = group; - s = { - type: "atom", - mode: this.mode, - family, - loc, - text - }; - } else { - s = { - type: group, - mode: this.mode, - loc, - text - }; - } - symbol = s; - } else if (!this.strict && numberRegEx.test(text)) { - // A number. Wrap in a if in math mode; otherwise. - this.consume() - return { - type: "textord", - mode: this.mode, - loc: SourceLocation.range(nucleus), - text - } - } else if (text.charCodeAt(0) >= 0x80) { - // no symbol for e.g. ^ - if (this.settings.strict) { - if (!supportedCodepoint(text.charCodeAt(0))) { - throw new ParseError(`Unrecognized Unicode character "${text[0]}"` + - ` (${text.charCodeAt(0)})`, nucleus); - } else if (this.mode === "math") { - throw new ParseError(`Unicode text character "${text[0]}" used in math mode`, nucleus) - } - } - // All nonmathematical Unicode characters are rendered as if they - // are in text mode (wrapped in \text) because that's what it - // takes to render them in LaTeX. - symbol = { - type: "textord", - mode: "text", - loc: SourceLocation.range(nucleus), - text - }; - } else { - return null; // EOF, ^, _, {, }, etc. - } - this.consume(); - // Transform combining characters into accents - if (match) { - for (let i = 0; i < match[0].length; i++) { - const accent = match[0][i]; - if (!unicodeAccents[accent]) { - throw new ParseError(`Unknown accent ' ${accent}'`, nucleus); - } - const command = unicodeAccents[accent][this.mode] || - unicodeAccents[accent].text; - if (!command) { - throw new ParseError(`Accent ${accent} unsupported in ${this.mode} mode`, nucleus); - } - symbol = { - type: "accent", - mode: this.mode, - loc: SourceLocation.range(nucleus), - label: command, - isStretchy: false, - isShifty: true, - base: symbol - }; - } - } - return symbol; - } -} diff --git a/src/Settings.js b/src/Settings.js deleted file mode 100644 index 9c154a7c..00000000 --- a/src/Settings.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * This is a module for storing settings passed into Temml. It correctly handles - * default settings. - */ - -import utils from "./utils"; - -/** - * The main Settings object - */ -export default class Settings { - constructor(options) { - // allow null options - options = options || {}; - this.displayMode = utils.deflt(options.displayMode, false); // boolean - this.annotate = utils.deflt(options.annotate, false) // boolean - this.elementIsMath = utils.deflt(options.elementIsMath, false) // boolean - this.leqno = utils.deflt(options.leqno, false); // boolean - this.errorColor = utils.deflt(options.errorColor, "#b22222"); // string - this.preventTagLap = utils.deflt(options.preventTagLap, false); // boolean - this.macros = options.macros || {}; - this.xml = utils.deflt(options.xml, false); // boolean - this.colorIsTextColor = utils.deflt(options.colorIsTextColor, false); // booelean - this.strict = utils.deflt(options.strict, false); // boolean - this.trust = utils.deflt(options.trust, false); // trust context. See html.js. - this.maxSize = (options.maxSize === undefined - ? [Infinity, Infinity] - : Array.isArray(options.maxSize) - ? options.maxSize - : [Infinity, Infinity] - ) - this.maxExpand = Math.max(0, utils.deflt(options.maxExpand, 1000)); // number - } - - /** - * Check whether to test potentially dangerous input, and return - * `true` (trusted) or `false` (untrusted). The sole argument `context` - * should be an object with `command` field specifying the relevant LaTeX - * command (as a string starting with `\`), and any other arguments, etc. - * If `context` has a `url` field, a `protocol` field will automatically - * get added by this function (changing the specified object). - */ - isTrusted(context) { - if (context.url && !context.protocol) { - context.protocol = utils.protocolFromUrl(context.url); - } - const trust = typeof this.trust === "function" ? this.trust(context) : this.trust; - return Boolean(trust); - } -} diff --git a/src/SourceLocation.js b/src/SourceLocation.js deleted file mode 100644 index ad0f8031..00000000 --- a/src/SourceLocation.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Lexing or parsing positional information for error reporting. - * This object is immutable. - */ -export default class SourceLocation { - constructor(lexer, start, end) { - this.lexer = lexer; // Lexer holding the input string. - this.start = start; // Start offset, zero-based inclusive. - this.end = end; // End offset, zero-based exclusive. - } - - /** - * Merges two `SourceLocation`s from location providers, given they are - * provided in order of appearance. - * - Returns the first one's location if only the first is provided. - * - Returns a merged range of the first and the last if both are provided - * and their lexers match. - * - Otherwise, returns null. - */ - static range(first, second) { - if (!second) { - return first && first.loc; - } else if (!first || !first.loc || !second.loc || first.loc.lexer !== second.loc.lexer) { - return null; - } else { - return new SourceLocation(first.loc.lexer, first.loc.start, second.loc.end); - } - } -} diff --git a/src/Style.js b/src/Style.js deleted file mode 100644 index c98fd9de..00000000 --- a/src/Style.js +++ /dev/null @@ -1,144 +0,0 @@ -/** - * This file contains information about the style that the mathmlBuilder carries - * around with it. Data is held in an `Style` object, and when - * recursing, a new `Style` object can be created with the `.with*` functions. - */ - -const subOrSupLevel = [2, 2, 3, 3]; - -/** - * This is the main Style class. It contains the current style.level, color, and font. - * - * Style objects should not be modified. To create a new Style with - * different properties, call a `.with*` method. - */ -class Style { - constructor(data) { - // Style.level can be 0 | 1 | 2 | 3, which correspond to - // displaystyle, textstyle, scriptstyle, and scriptscriptstyle. - // style.level does not directly set MathML's script level. MathML does that itself. - // We use style.level to track, not set, math style so that we can get the - // correct scriptlevel when needed in supsub.js, mathchoice.js, or for dimensions in em. - this.level = data.level; - this.color = data.color; // string | void - // A font family applies to a group of fonts (i.e. SansSerif), while a font - // represents a specific font (i.e. SansSerif Bold). - // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm - this.font = data.font || ""; // string - this.fontFamily = data.fontFamily || ""; // string - this.fontSize = data.fontSize || 1.0; // number - this.fontWeight = data.fontWeight || ""; - this.fontShape = data.fontShape || ""; - this.maxSize = data.maxSize; // [number, number] - } - - /** - * Returns a new style object with the same properties as "this". Properties - * from "extension" will be copied to the new style object. - */ - extend(extension) { - const data = { - level: this.level, - color: this.color, - font: this.font, - fontFamily: this.fontFamily, - fontSize: this.fontSize, - fontWeight: this.fontWeight, - fontShape: this.fontShape, - maxSize: this.maxSize - }; - - for (const key in extension) { - if (Object.prototype.hasOwnProperty.call(extension, key)) { - data[key] = extension[key]; - } - } - - return new Style(data); - } - - withLevel(n) { - return this.extend({ - level: n - }); - } - - incrementLevel() { - return this.extend({ - level: Math.min(this.level + 1, 3) - }); - } - - inSubOrSup() { - return this.extend({ - level: subOrSupLevel[this.level] - }) - } - - /** - * Create a new style object with the given color. - */ - withColor(color) { - return this.extend({ - color: color - }); - } - - /** - * Creates a new style object with the given math font or old text font. - * @type {[type]} - */ - withFont(font) { - return this.extend({ - font - }); - } - - /** - * Create a new style objects with the given fontFamily. - */ - withTextFontFamily(fontFamily) { - return this.extend({ - fontFamily, - font: "" - }); - } - - /** - * Creates a new style object with the given font size - */ - withFontSize(num) { - return this.extend({ - fontSize: num - }); - } - - /** - * Creates a new style object with the given font weight - */ - withTextFontWeight(fontWeight) { - return this.extend({ - fontWeight, - font: "" - }); - } - - /** - * Creates a new style object with the given font weight - */ - withTextFontShape(fontShape) { - return this.extend({ - fontShape, - font: "" - }); - } - - /** - * Gets the CSS color of the current style object - */ - getColor() { - return this.color; - } -} - -export default Style; diff --git a/src/Token.js b/src/Token.js deleted file mode 100644 index fce73082..00000000 --- a/src/Token.js +++ /dev/null @@ -1,40 +0,0 @@ -import SourceLocation from "./SourceLocation"; - -/** - * Interface required to break circular dependency between Token, Lexer, and - * ParseError. - */ - -/** - * The resulting token returned from `lex`. - * - * It consists of the token text plus some position information. - * The position information is essentially a range in an input string, - * but instead of referencing the bare input string, we refer to the lexer. - * That way it is possible to attach extra metadata to the input string, - * like for example a file name or similar. - * - * The position information is optional, so it is OK to construct synthetic - * tokens if appropriate. Not providing available position information may - * lead to degraded error reporting, though. - */ -export class Token { - constructor( - text, // the text of this token - loc - ) { - this.text = text; - this.loc = loc; - } - - /** - * Given a pair of tokens (this and endToken), compute a `Token` encompassing - * the whole input range enclosed by these two. - */ - range( - endToken, // last token of the range, inclusive - text // the text of the newly constructed token - ) { - return new Token(text, SourceLocation.range(this, endToken)); - } -} diff --git a/src/autocorrect.js b/src/autocorrect.js deleted file mode 100644 index 94178f6a..00000000 --- a/src/autocorrect.js +++ /dev/null @@ -1,126 +0,0 @@ - -const autoCorrections = { - "\\alpha": "α", - "\\beta": "β", - "\\chi": "χ", - "\\delta": "δ", - "\\Delta": "Δ", - "\\epsilon": "ε", - "\\varepsilon": "\u025B", - "\\eta": "\u03B7", - "\\gamma": "γ", - "\\Gamma": "Γ", - "\\iota": "\u03B9", - "\\kappa": "\u03BA", - "\\lambda": "λ", - "\\Lambda": "Λ", - "\\mu": "μ", - "\\nu": "\u03BD", - "\\omega": "ω", - "\\Omega": "Ω", - "\\phi": "\u03D5", - "\\varphi": "\u03C6", - "\\Phi": "\u03A6", - "\\pi": "π", - "\\Pi": "Π", - "\\psi": "ψ", - "\\Psi": "Ψ", - "\\rho": "ρ", - "\\sigma": "σ", - "\\Sigma": "Σ", - "\\tau": "τ", - "\\theta": "θ", - "\\vartheta": "\u03D1", - "\\Theta": "Θ", - "\\upsilon": "\u03C5", - "\\xi": "\u03BE", - "\\Xi": "\u039E", - "\\zeta": "\u03B6", - "\\mathbb{C}": "\u2102", - "\\mathbb{H}": "\u210D", - "\\mathbb{N}": "\u2115", - "\\mathbb{Q}": "\u211A", - "\\mathbb{R}": "\u211D", - "\\mathbb{Z}": "\u2124", - "\\infty": "∞", - "\\degree": "°", - "\\lnot": "¬", - "\\neg": "¬", - "\\cdots": "\u22ef", - "\\vdots": "\u22ee", - "\\ddots": "\u22f1", - "\\lceil": "⌈", - "\\rceil": "⌉", - "\\lfloor": "⌊", - "\\rfloor": "⌋", - "\\times": "×", - "\\int": "∫", - "\\iint": "∬", - "\\iiint": "∭", - "\\iiiint": "⨌", - "\\oint": "∮", - "\\oiint": "∯", - "\\oiiint": "∰", - "\\sum": "∑", - "\\cap": "∩", - "\\bigcap": "⋂", - "\\cup": "∪", - "\\bigcup": "⋃", - "\\del": "∂", - "\\grad": "∇", - "\\hbar": "ℏ", - "\\ell": "ℓ", - "\\nabla": "∇", - "\\aleph": "ℵ", - "\\beth": "ℶ", - "\\gimel": "ℷ", - "\\daleth": "ℸ", - "\\eth": "ð", - "\\subset": "⊂", - "\\supset": "⊃", - "\\Subset": "⋐", - "\\Supset": "⋑", - "\\complement": "∁", - "\\forall": "∀", - "\\exists": "∃", - "\\nexists": "∄", - "\\therefore": "∴", - "\\because": "∵", - "\\mapsto": "↦", - "\\checkmark": "✓", - "\\land": "∧", - "\\lor": "∨", - "\\in": "∈", - "\\ni": "∋", - "\\notin": "∉", - "\\notni": "∌", - "\\implies": "⟹", - "\\impliedby": "⟸", - "\\iff": "⟺", - "\\euro": "€", - "\\pound": "£", - "\\yen": "¥", - "\\o": "ø", - vvv: "⋁", - "\\xor": "⊻", - "!=": "≠", - ":=": "≔", - "<=": "≤", - ">=": "≥", - "-=": "≡", - "~=": "≅", - "~~": "≈", - "+-": "±", - "-+": "∓", - "\\langle ": "\u27E8", - "\\rangle ": "\u27E9", - "<->": "\u2194", - "<-": "\u2190", - "<--": "\u27F5", - "-->": "⟶", - "->": "→", - "=>": "⇒", - "\\circ": "∘", - "\\otimes": "⊗", - "\\angle": "∠" -} diff --git a/src/buildMathML.js b/src/buildMathML.js deleted file mode 100644 index ba45c072..00000000 --- a/src/buildMathML.js +++ /dev/null @@ -1,187 +0,0 @@ -/** - * This file converts a parse tree into a cooresponding MathML tree. The main - * entry point is the `buildMathML` function, which takes a parse tree from the - * parser. - */ - -import mathMLTree from "./mathMLTree" -import ParseError from "./ParseError" -import symbols, { ligatures } from "./symbols" -import { _mathmlGroupBuilders as groupBuilders } from "./defineFunction" -import { MathNode } from "./mathMLTree" -import setLineBreaks from "./linebreaking" -import utils from "./utils"; - -/** - * Takes a symbol and converts it into a MathML text node after performing - * optional replacement from symbols.js. - */ -export const makeText = function(text, mode, style) { - if ( - symbols[mode][text] && - symbols[mode][text].replace && - text.charCodeAt(0) !== 0xd835 && - !( - Object.prototype.hasOwnProperty.call(ligatures, text) && - style && - ((style.fontFamily && style.fontFamily.slice(4, 6) === "tt") || - (style.font && style.font.slice(4, 6) === "tt")) - ) - ) { - text = symbols[mode][text].replace; - } - - return new mathMLTree.TextNode(text); -}; - -/** - * Wrap the given array of nodes in an node if needed, i.e., - * unless the array has length 1. Always returns a single node. - */ -export const makeRow = function(body) { - if (body.length === 1) { - return body[0]; - } else { - return new mathMLTree.MathNode("mrow", body); - } -}; - -const isRel = item => { - return (item.type === "atom" && item.family === "rel") || - (item.type === "mclass" && item.mclass === "mrel") -} - -/** - * Takes a list of nodes, builds them, and returns a list of the generated - * MathML nodes. Also do a couple chores along the way: - * (1) Suppress spacing when an author wraps an operator w/braces, as in {=}. - * (2) Suppress spacing between two adjacent relations. - */ -export const buildExpression = function(expression, style, isOrdgroup) { - if (expression.length === 1) { - const group = buildGroup(expression[0], style); - if (isOrdgroup && group instanceof MathNode && group.type === "mo") { - // When TeX writers want to suppress spacing on an operator, - // they often put the operator by itself inside braces. - group.setAttribute("lspace", "0em"); - group.setAttribute("rspace", "0em"); - } - return [group]; - } - - const groups = []; - for (let i = 0; i < expression.length; i++) { - const group = buildGroup(expression[i], style); - // Suppress spacing between adjacent relations - if (i < expression.length - 1 && isRel(expression[i]) && isRel(expression[i + 1])) { - group.setAttribute("rspace", "0em") - } - if (i > 0 && isRel(expression[i]) && isRel(expression[i - 1])) { - group.setAttribute("lspace", "0em") - } - groups.push(group); - } - return groups; -}; - -/** - * Equivalent to buildExpression, but wraps the elements in an - * if there's more than one. Returns a single node instead of an array. - */ -export const buildExpressionRow = function(expression, style, isOrdgroup) { - return makeRow(buildExpression(expression, style, isOrdgroup)); -}; - -/** - * Takes a group from the parser and calls the appropriate groupBuilders function - * on it to produce a MathML node. - */ -export const buildGroup = function(group, style) { - if (!group) { - return new mathMLTree.MathNode("mrow"); - } - - if (groupBuilders[group.type]) { - // Call the groupBuilders function - const result = groupBuilders[group.type](group, style); - return result; - } else { - throw new ParseError("Got group of unknown type: '" + group.type + "'"); - } -}; - -const glue = _ => { - const glueNode = new mathMLTree.MathNode("mtd", []) - glueNode.setAttribute("style", "padding: 0;width: 50%;") - return glueNode -} - -const taggedExpression = (expression, tag, style, leqno, preventTagLap) => { - tag = buildExpressionRow(tag[0].body, style) - tag = utils.consolidateText(tag) - tag.classes = ["tml-tag"]; - if (!preventTagLap) { - tag = new mathMLTree.MathNode("mpadded", [tag]) - tag.setAttribute("style", "width:0;") - tag.setAttribute("width", "0") - tag.setAttribute((leqno ? "rspace" : "lspace"), "-1width") - } - tag = new mathMLTree.MathNode("mtd", [tag]) - if (!preventTagLap) { tag.setAttribute("style", "padding: 0; min-width:0") } - - expression = new mathMLTree.MathNode("mtd", [expression]) - const rowArray = leqno - ? [tag, glue(), expression, glue()] - : [glue(), expression, glue(), tag]; - const mtr = new mathMLTree.MathNode("mtr", rowArray, ["tml-tageqn"]) - const table = new mathMLTree.MathNode("mtable", [mtr]) - table.setAttribute("width", "100%") - table.setAttribute("displaystyle", "true") - return table -} - -/** - * Takes a full parse tree and settings and builds a MathML representation of - * it. - */ -export default function buildMathML(tree, texExpression, style, settings) { - // Strip off outer tag wrapper for processing below. - let tag = null - if (tree.length === 1 && tree[0].type === "tag") { - tag = tree[0].tag - tree = tree[0].body - } - - const expression = buildExpression(tree, style); - - const n1 = expression.length === 0 ? null : expression[0] - let wrapper = expression.length === 1 && tag === null && (n1 instanceof MathNode) - && !(n1.type === "mstyle" && n1.attributes.mathcolor) - ? expression[0] - : setLineBreaks(expression, settings.displayMode, settings.annotate) - - if (tag) { - wrapper = taggedExpression(wrapper, tag, style, settings.leqno, settings.preventTagLap) - } - - let semantics - if (settings.annotate) { - // Build a TeX annotation of the source - const annotation = new mathMLTree.MathNode( - "annotation", [new mathMLTree.TextNode(texExpression)]); - annotation.setAttribute("encoding", "application/x-tex"); - semantics = new mathMLTree.MathNode("semantics", [wrapper, annotation]); - } - - const math = settings.annotate - ? new mathMLTree.MathNode("math", [semantics]) - : new mathMLTree.MathNode("math", [wrapper]) - - if (settings.xml) { - math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML") - } - if (settings.displayMode) { - math.setAttribute("display", "block"); - } - return math; -} diff --git a/src/constants.js b/src/constants.js deleted file mode 100644 index d568fd3a..00000000 --- a/src/constants.js +++ /dev/null @@ -1,25 +0,0 @@ -// In TeX, there are actually three sets of dimensions, one for each of -// textstyle, scriptstyle, and scriptscriptstyle. These are -// provided in the the arrays below, in that order. -// -export const metrics = { - quad: [1.0, 1.171, 1.472], // Extracted from TeX - - // The TeX default rule thickness, 0.04 em, often disappears from a browser screen. - // So we use a thicker rule. - defaultRuleThickness: [0.06, 0.074, 0.074], - - // The space between adjacent `|` columns in an array definition. - doubleRuleSep: [0.3, 0.3, 0.3], - - // The width of separator lines in {array} environments. - arrayRuleWidth: [0.06, 0.06, 0.04] -}; - -// Math style is not quite the same thing as script level. -export const StyleLevel = { - DISPLAY: 0, - TEXT: 1, - SCRIPT: 2, - SCRIPTSCRIPT: 3 -}; diff --git a/src/defineEnvironment.js b/src/defineEnvironment.js deleted file mode 100644 index a85b419f..00000000 --- a/src/defineEnvironment.js +++ /dev/null @@ -1,25 +0,0 @@ -import { _mathmlGroupBuilders } from "./defineFunction"; - -/** - * All registered environments. - * `environments.js` exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary via `environments.js`. - */ -export const _environments = {}; - -export default function defineEnvironment({ type, names, props, handler, mathmlBuilder }) { - // Set default values of environments. - const data = { - type, - numArgs: props.numArgs || 0, - allowedInText: false, - numOptionalArgs: 0, - handler - }; - for (let i = 0; i < names.length; ++i) { - _environments[names[i]] = data; - } - if (mathmlBuilder) { - _mathmlGroupBuilders[type] = mathmlBuilder; - } -} diff --git a/src/defineFunction.js b/src/defineFunction.js deleted file mode 100644 index 6733612a..00000000 --- a/src/defineFunction.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * All registered functions. - * `functions.js` just exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary. - */ -export const _functions = {} - -/** - * All MathML builders. Should be only used in the `define*` and the `build*ML` - * functions. - */ -export const _mathmlGroupBuilders = {} - -export default function defineFunction({ - type, - names, - props, - handler, - mathmlBuilder -}) { - // Set default values of functions - const data = { - type, - numArgs: props.numArgs, - argTypes: props.argTypes, - allowedInArgument: !!props.allowedInArgument, - allowedInText: !!props.allowedInText, - allowedInMath: props.allowedInMath === undefined ? true : props.allowedInMath, - numOptionalArgs: props.numOptionalArgs || 0, - infix: !!props.infix, - primitive: !!props.primitive, - handler: handler - } - for (let i = 0; i < names.length; ++i) { - _functions[names[i]] = data - } - if (type) { - if (mathmlBuilder) { - _mathmlGroupBuilders[type] = mathmlBuilder - } - } -} - -/** - * Use this to register only the MathML builder for a function(e.g. - * if the function's ParseNode is generated in Parser.js rather than via a - * stand-alone handler provided to `defineFunction`). - */ -export function defineFunctionBuilders({ type, mathmlBuilder }) { - defineFunction({ - type, - names: [], - props: { numArgs: 0 }, - handler() { - throw new Error("Should never be called.") - }, - mathmlBuilder - }) -} - -export const normalizeArgument = function(arg) { - return arg.type === "ordgroup" && arg.body.length === 1 ? arg.body[0] : arg -} - -// Since the corresponding buildMathML function expects a -// list of elements, we normalize for different kinds of arguments -export const ordargument = function(arg) { - return arg.type === "ordgroup" ? arg.body : [arg] -} diff --git a/src/defineMacro.js b/src/defineMacro.js deleted file mode 100644 index 130371cc..00000000 --- a/src/defineMacro.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * All registered global/built-in macros. - * `macros.js` exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary via `macros.js`. - */ -export const _macros = {}; - -// This function might one day accept an additional argument and do more things. -export default function defineMacro(name, body) { - _macros[name] = body; -} diff --git a/src/domTree.js b/src/domTree.js deleted file mode 100644 index ee7ffdb3..00000000 --- a/src/domTree.js +++ /dev/null @@ -1,185 +0,0 @@ -/** - * These objects store the data about the DOM nodes we create, as well as some - * extra data. They can then be transformed into real DOM nodes with the - * `toNode` function or HTML markup using `toMarkup`. They are useful for both - * storing extra properties on the nodes, as well as providing a way to easily - * work with the DOM. - * - * Similar functions for working with MathML nodes exist in mathMLTree.js. - * - */ -import utils from "./utils"; - -/** - * Create an HTML className based on a list of classes. In addition to joining - * with spaces, we also remove empty classes. - */ -export const createClass = function(classes) { - return classes.filter((cls) => cls).join(" "); -}; - -const initNode = function(classes, style) { - this.classes = classes || []; - this.attributes = {}; - this.style = style || {}; -}; - -/** - * Convert into an HTML node - */ -const toNode = function(tagName) { - const node = document.createElement(tagName); - - // Apply the class - node.className = createClass(this.classes); - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - // Apply attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr )) { - node.setAttribute(attr, this.attributes[attr]); - } - } - - // Append the children, also as HTML nodes - for (let i = 0; i < this.children.length; i++) { - node.appendChild(this.children[i].toNode()); - } - - return node; -}; - -/** - * Convert into an HTML markup string - */ -const toMarkup = function(tagName) { - let markup = `<${tagName}`; - - // Add the class - if (this.classes.length) { - markup += ` class="${utils.escape(createClass(this.classes))}"`; - } - - let styles = ""; - - // Add the styles, after hyphenation - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - styles += `${utils.hyphenate(style)}:${this.style[style]};`; - } - } - - if (styles) { - markup += ` style="${styles}"`; - } - - // Add the attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr )) { - markup += ` ${attr}="${utils.escape(this.attributes[attr])}"`; - } - } - - markup += ">"; - - // Add the markup of the children, also as markup - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - markup += ``; - - return markup; -}; - -/** - * This node represents a span node, with a className, a list of children, and - * an inline style. - * - */ -export class Span { - constructor(classes, children, style) { - initNode.call(this, classes, style); - this.children = children || []; - } - - setAttribute(attribute, value) { - this.attributes[attribute] = value; - } - - toNode() { - return toNode.call(this, "span"); - } - - toMarkup() { - return toMarkup.call(this, "span"); - } -} - -export class TextNode { - constructor(text) { - this.text = text; - } - toNode() { - return document.createTextNode(this.text); - } - toMarkup() { - return utils.escape(this.text); - } -} - -/** - * This node represents an image embed () element. - */ -export class Img { - constructor(src, alt, style) { - this.alt = alt; - this.src = src; - this.classes = ["mord"]; - this.style = style; - } - - hasClass(className) { - return utils.contains(this.classes, className); - } - - toNode() { - const node = document.createElement("img"); - node.src = this.src; - node.alt = this.alt; - node.className = "mord"; - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - return node; - } - - toMarkup() { - let markup = `${this.alt} { - const settings = context.parser.settings; - if (!settings.displayMode) { - throw new ParseError(`{${context.envName}} can be used only in display mode.`); - } -} - -const getTag = (group, style, rowNum) => { - let tag - const tagContents = group.tags.shift() - if (tagContents) { - // The author has written a \tag or a \notag in this row. - if (tagContents.body) { - tag = mml.buildExpressionRow(tagContents.body, style) - tag.classes = ["tml-tag"] - } else { - // \notag. Return an empty cell. - tag = new mathMLTree.MathNode("mtd", []) - tag.setAttribute("style", "padding: 0; min-width:0") - return tag - } - } else if (group.colSeparationType === "multline" && - ((group.leqno && rowNum !== 0) || (!group.leqno && rowNum !== group.body.length - 1))) { - // A multiline that does not receive a tag. Return an empty cell. - tag = new mathMLTree.MathNode("mtd", []) - tag.setAttribute("style", "padding: 0; min-width:0") - return tag - } else { - // AMS automatcally numbered equaton. - // Insert a class so the element can be populated by a post-processor. - tag = new mathMLTree.MathNode("mtext", [], ["tml-eqn"]) - } - if (!group.preventTagLap) { - tag = new mathMLTree.MathNode("mpadded", [tag]) - tag.setAttribute("style", "width:0;") - tag.setAttribute("width", "0") - if (!group.leqno) { tag.setAttribute("lspace", "-1width") } - } - tag = new mathMLTree.MathNode("mtd", [tag]) - if (!group.preventTagLap) { tag.setAttribute("style", "padding: 0; min-width:0") } - return tag -} - -/** - * Parse the body of the environment, with rows delimited by \\ and - * columns delimited by &, and create a nested list in row-major order - * with one group per cell. If given an optional argument scriptLevel - * ("text", "display", etc.), then each cell is cast into that scriptLevel. - */ -function parseArray( - parser, - { - hskipBeforeAndAfter, // boolean - addJot, // boolean - cols, // [{ type: string , align: l|c|r|null }] - arraystretch, // number - colSeparationType, // "align" | "alignat" | "gather" | "small" | "CD" | "multline" - addEqnNum, // boolean - singleRow, // boolean - emptySingleRow, // boolean - maxNumCols, // number - leqno // boolean - }, - scriptLevel -) { - parser.gullet.beginGroup(); - if (!singleRow) { - // \cr is equivalent to \\ without the optional size argument (see below) - // TODO: provide helpful error when \cr is used outside array environment - parser.gullet.macros.set("\\cr", "\\\\\\relax"); - } - if (addEqnNum) { - parser.gullet.macros.set("\\tag", "\\env@tag{\\text{#1}}"); - parser.gullet.macros.set("\\notag", "\\env@notag"); - parser.gullet.macros.set("\\nonumber", "\\env@notag") - } - - // Get current arraystretch if it's not set by the environment - if (arraystretch === undefined || Number.isNaN(arraystretch)) { - const stretch = parser.gullet.expandMacroAsText("\\arraystretch"); - if (stretch == null) { - // Default \arraystretch from lttab.dtx - arraystretch = 1 - } else { - arraystretch = parseFloat(stretch); - if (!arraystretch || arraystretch < 0) { - throw new ParseError(`Invalid \\arraystretch: ${stretch}`); - } - } - } - - // Start group for first cell - parser.gullet.beginGroup(); - - let row = []; - const body = [row]; - const rowGaps = []; - const tags = []; - let rowTag; - const hLinesBeforeRow = []; - - // Test for \hline at the top of the array. - hLinesBeforeRow.push(getHLines(parser)); - - // eslint-disable-next-line no-constant-condition - while (true) { - // Parse each cell in its own group (namespace) - let cell = parser.parseExpression(false, singleRow ? "\\end" : "\\\\"); - - if (addEqnNum && !rowTag) { - // Check if the author wrote a \tag{} inside this cell. - for (let i = 0; i < cell.length; i++) { - if (cell[i].type === "envTag" || cell[i].type === "noTag") { - // Get the contents of the \text{} nested inside the \env@Tag{} - rowTag = cell[i].type === "envTag" - ? cell.splice(i, 1)[0].body.body[0] - : { body: null }; - break - } - } - } - parser.gullet.endGroup(); - parser.gullet.beginGroup(); - - cell = { - type: "ordgroup", - mode: parser.mode, - body: cell - }; - row.push(cell); - const next = parser.fetch().text; - if (next === "&") { - if (maxNumCols && row.length === maxNumCols) { - if (colSeparationType === "split") { - throw new ParseError("The split environment accepts no more than two columns", - parser.nextToken); - } else if (colSeparationType === "array") { - if (parser.settings.strict) { - throw new ParseError("Too few columns " + "specified in the {array} column argument.", - parser.nextToken) - } - } else { - throw new ParseError("The equation environment accepts only one column", - parser.nextToken) - } - } - parser.consume(); - } else if (next === "\\end") { - // Arrays terminate newlines with `\crcr` which consumes a `\cr` if - // the last line is empty. However, AMS environments keep the - // empty row if it's the only one. - // NOTE: Currently, `cell` is the last item added into `row`. - if (row.length === 1 && cell.body.length === 0 && (body.length > 1 || !emptySingleRow)) { - body.pop(); - } - if (hLinesBeforeRow.length < body.length + 1) { - hLinesBeforeRow.push([]); - } - break; - } else if (next === "\\\\") { - parser.consume(); - let size; - // \def\Let@{\let\\\math@cr} - // \def\math@cr{...\math@cr@} - // \def\math@cr@{\new@ifnextchar[\math@cr@@{\math@cr@@[\z@]}} - // \def\math@cr@@[#1]{...\math@cr@@@...} - // \def\math@cr@@@{\cr} - if (parser.gullet.future().text !== " ") { - size = parser.parseSizeGroup(true); - } - rowGaps.push(size ? size.value : null); - - tags.push(rowTag) - - // check for \hline(s) following the row separator - hLinesBeforeRow.push(getHLines(parser)); - - row = []; - rowTag = null; - body.push(row); - } else { - throw new ParseError("Expected & or \\\\ or \\cr or \\end", parser.nextToken); - } - } - - // End cell group - parser.gullet.endGroup(); - // End array group defining \cr - parser.gullet.endGroup(); - - tags.push(rowTag) - - return { - type: "array", - mode: parser.mode, - addJot, - arraystretch, - body, - cols, - rowGaps, - hskipBeforeAndAfter, - hLinesBeforeRow, - colSeparationType, - addEqnNum, - scriptLevel, - tags, - leqno, - preventTagLap: parser.settings.preventTagLap - }; -} - -// Decides on a scriptLevel for cells in an array according to whether the given -// environment name starts with the letter 'd'. -function dCellStyle(envName) { - return envName.slice(0, 1) === "d" ? "display" : "text" -} - -const alignMap = { - c: "center ", - l: "left ", - r: "right " -}; - -const mathmlBuilder = function(group, style) { - const tbl = []; - const numRows = group.body.length - let glue - if (group.addEqnNum) { - glue = new mathMLTree.MathNode("mtd", [], []) - const glueStyle = "padding: 0;width: " + - (group.colSeparationType === "multline" ? "7.5%" : "50%") - glue.setAttribute("style", glueStyle) - } - - for (let i = 0; i < numRows; i++) { - const rw = group.body[i]; - const row = []; - const cellStyle = group.scriptLevel === "text" - ? StyleLevel.TEXT - : group.scriptLevel === "script" - ? StyleLevel.SCRIPT - : StyleLevel.DISPLAY - - for (let j = 0; j < rw.length; j++) { - const mtd = new mathMLTree.MathNode( - "mtd", - [mml.buildGroup(rw[j], style.withLevel(cellStyle))] - ) - if (group.colSeparationType === "multline") { - const align = i === 0 ? "left" : i === numRows - 1 ? "right" : "center" - mtd.setAttribute("columnalign", align) - } - row.push(mtd) - } - if (group.addEqnNum) { - row.unshift(glue); - row.push(glue); - const tag = getTag(group, style.withLevel(cellStyle), i) - if (group.leqno) { - row.unshift(tag) - } else { - row.push(tag) - } - } - // If group.addEqnNum, insert a breadcrumb to be found by temmlPostProcess(). - tbl.push(new mathMLTree.MathNode("mtr", row, group.addEqnNum ? ["tml-tageqn"] : [] )); - } - let table = new mathMLTree.MathNode("mtable", tbl); - if (group.scriptLevel === "display") { table.setAttribute("displaystyle", "true") } - - // Set column alignment, row spacing, column spacing, and - // array lines by setting attributes on the table element. - - // Set the row spacing. In MathML, we specify a gap distance. - // We do not use rowGap[] because MathML automatically increases - // cell height with the height/depth of the element content. - - // LaTeX \arraystretch multiplies the row baseline-to-baseline distance. - // We simulate this by adding (arraystretch - 1)em to the gap. This - // does a reasonable job of adjusting arrays containing 1 em tall content. - - // The 0.16 and 0.09 values are found emprically. They produce an array - // similar to LaTeX and in which content does not interfere with \hines. - const gap = - group.arraystretch === 0 - ? 0 // {subarray} - : group.arraystretch === 0.5 - ? 0.1 // {smallmatrix} - : 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0); - table.setAttribute("rowspacing", utils.round(gap) + "em") - - if (group.addEqnNum || group.colSeparationType === "multline") { - table.setAttribute("width", "100%") - } - - // MathML table lines go only between cells. - // To place a line on an edge we'll use , if necessary. - let menclose = ""; - let align = ""; - - if (group.cols && group.cols.length > 0) { - // Find column alignment, column spacing, and vertical lines. - const cols = group.cols; - let columnLines = ""; - let prevTypeWasAlign = false; - let iStart = 0; - let iEnd = cols.length; - - if (cols[0].type === "separator") { - menclose += "left "; - iStart = 1; - } - if (cols[cols.length - 1].type === "separator") { - menclose += "right "; - iEnd -= 1; - } - - for (let i = iStart; i < iEnd; i++) { - if (cols[i].type === "align") { - align += alignMap[cols[i].align]; - - if (prevTypeWasAlign) { - columnLines += "none "; - } - prevTypeWasAlign = true; - } else if (cols[i].type === "separator") { - // MathML accepts only single lines between cells. - // So we read only the first of consecutive separators. - if (prevTypeWasAlign) { - columnLines += cols[i].separator === "|" ? "solid " : "dashed "; - prevTypeWasAlign = false; - } - } - } - if (group.addEqnNum) { - align = "left " + align + "right " // allow for glue cells on each side - align = group.leqno ? "left " + align : align += "right" // eqn num cell - } - - table.setAttribute("columnalign", align.trim()); - - if (/[sd]/.test(columnLines)) { - table.setAttribute("columnlines", columnLines.trim()); - } - } - - // Set column spacing. - switch (group.colSeparationType) { - case "gather": - case "gathered": - case "alignedat": - case "alignat": - case "alignat*": - table.setAttribute("columnspacing", "0em"); - break - case "small": - table.setAttribute("columnspacing", "0.2778em"); - break - case "CD": - table.setAttribute("columnspacing", "0.5em"); - break - case "align": - case "align*": { - const cols = group.cols || []; - let spacing = group.addEqnNum ? "0em " : "" - for (let i = 1; i < cols.length; i++) { - spacing += i % 2 ? "0em " : "1em " - } - if (group.addEqnNum) { spacing += "0em" } - table.setAttribute("columnspacing", spacing.trim()); - break - } - default: - table.setAttribute("columnspacing", "1em"); - } - - // Address \hline and \hdashline - let rowLines = ""; - const hlines = group.hLinesBeforeRow; - - menclose += hlines[0].length > 0 ? "top " : ""; - menclose += hlines[hlines.length - 1].length > 0 ? "bottom " : ""; - - for (let i = 1; i < hlines.length - 1; i++) { - rowLines += - hlines[i].length === 0 - ? "none " - : // MathML accepts only a single line between rows. Read one element. - hlines[i][0] - ? "dashed " - : "solid "; - } - if (/[sd]/.test(rowLines)) { - table.setAttribute("rowlines", rowLines.trim()); - } - - if (menclose !== "") { - table = new mathMLTree.MathNode("menclose", [table]); - table.setAttribute("notation", menclose.trim()); - } - - if (!Number.isNaN(group.arraystretch) && group.arraystretch < 1) { - // A small array. Wrap in scriptstyle so row gap is not too large. - table = new mathMLTree.MathNode("mstyle", [table]); - table.setAttribute("scriptlevel", "1"); - } - - return table; -}; - -// Convenience function for align, align*, aligned, alignat, alignat*, alignedat. -const alignedHandler = function(context, args) { - if (context.envName.indexOf("ed") === -1) { - validateAmsEnvironmentContext(context); - } - const cols = []; - const res = parseArray( - context.parser, - { - cols, - addJot: true, - addEqnNum: context.envName === "align" || context.envName === "alignat", - emptySingleRow: true, - colSeparationType: context.envName, - maxNumCols: context.envName === "split" ? 2 : undefined, - leqno: context.parser.settings.leqno - }, - "display" - ); - - // Determining number of columns. - // 1. If the first argument is given, we use it as a number of columns, - // and makes sure that each row doesn't exceed that number. - // 2. Otherwise, just count number of columns = maximum number - // of cells in each row ("aligned" mode -- isAligned will be true). - // - // At the same time, prepend empty group {} at beginning of every second - // cell in each row (starting with second cell) so that operators become - // binary. This behavior is implemented in amsmath's \start@aligned. - let numMaths; - let numCols = 0; - if (args[0] && args[0].type === "ordgroup") { - let arg0 = ""; - for (let i = 0; i < args[0].body.length; i++) { - const textord = assertNodeType(args[0].body[i], "textord"); - arg0 += textord.text; - } - numMaths = Number(arg0); - numCols = numMaths * 2; - } - const isAligned = !numCols; - res.body.forEach(function(row) { - if (!isAligned) { - // Case 1 - const curMaths = row.length / 2; - if (numMaths < curMaths) { - throw new ParseError( - "Too many math in a row: " + `expected ${numMaths}, but got ${curMaths}`, - row[0] - ); - } - } else if (numCols < row.length) { - // Case 2 - numCols = row.length; - } - }); - - // Adjusting alignment. - // In aligned mode, we add one \qquad between columns; - // otherwise we add nothing. - for (let i = 0; i < numCols; ++i) { - let align = "r"; - if (i % 2 === 1) { - align = "l"; - } - cols[i] = { - type: "align", - align: align - }; - } - res.colSeparationType = isAligned ? "align" : "alignat"; - return res; -}; - -// Arrays are part of LaTeX, defined in lttab.dtx so its documentation -// is part of the source2e.pdf file of LaTeX2e source documentation. -// {darray} is an {array} environment where cells are set in \displaystyle, -// as defined in nccmath.sty. -defineEnvironment({ - type: "array", - names: ["array", "darray"], - props: { - numArgs: 1 - }, - handler(context, args) { - // Since no types are specified above, the two possibilities are - // - The argument is wrapped in {} or [], in which case Parser's - // parseGroup() returns an "ordgroup" wrapping some symbol node. - // - The argument is a bare symbol node. - const symNode = checkSymbolNodeType(args[0]); - const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; - const cols = colalign.map(function(nde) { - const node = assertSymbolNodeType(nde); - const ca = node.text; - if ("lcr".indexOf(ca) !== -1) { - return { - type: "align", - align: ca - }; - } else if (ca === "|") { - return { - type: "separator", - separator: "|" - }; - } else if (ca === ":") { - return { - type: "separator", - separator: ":" - }; - } - throw new ParseError("Unknown column alignment: " + ca, nde); - }); - const res = { - cols, - colSeparationType: "array", - hskipBeforeAndAfter: true, // \@preamble in lttab.dtx - maxNumCols: cols.length - }; - return parseArray(context.parser, res, dCellStyle(context.envName)); - }, - mathmlBuilder -}); - -// The matrix environments of amsmath builds on the array environment -// of LaTeX, which is discussed above. -// The mathtools package adds starred versions of the same environments. -// These have an optional argument to choose left|center|right justification. -defineEnvironment({ - type: "array", - names: [ - "matrix", - "pmatrix", - "bmatrix", - "Bmatrix", - "vmatrix", - "Vmatrix", - "matrix*", - "pmatrix*", - "bmatrix*", - "Bmatrix*", - "vmatrix*", - "Vmatrix*" - ], - props: { - numArgs: 0 - }, - handler(context) { - const delimiters = { - matrix: null, - pmatrix: ["(", ")"], - bmatrix: ["[", "]"], - Bmatrix: ["\\{", "\\}"], - vmatrix: ["|", "|"], - Vmatrix: ["\\Vert", "\\Vert"] - }[context.envName.replace("*", "")]; - // \hskip -\arraycolsep in amsmath - let colAlign = "c"; - const payload = { - hskipBeforeAndAfter: false, - colSeparationType: "matrix", - cols: [{ type: "align", align: colAlign }] - }; - if (context.envName.charAt(context.envName.length - 1) === "*") { - // It's one of the mathtools starred functions. - // Parse the optional alignment argument. - const parser = context.parser; - parser.consumeSpaces(); - if (parser.fetch().text === "[") { - parser.consume(); - parser.consumeSpaces(); - colAlign = parser.fetch().text; - if ("lcr".indexOf(colAlign) === -1) { - throw new ParseError("Expected l or c or r", parser.nextToken); - } - parser.consume(); - parser.consumeSpaces(); - parser.expect("]"); - parser.consume(); - payload.cols = [{ type: "align", align: colAlign }]; - } - } - const res = parseArray(context.parser, payload, "text"); - // Populate cols with the correct number of column alignment specs. - const numCols = Math.max(0, ...res.body.map((row) => row.length)); - res.cols = new Array(numCols).fill({ type: "align", align: colAlign }) - return delimiters - ? { - type: "leftright", - mode: context.mode, - body: [res], - left: delimiters[0], - right: delimiters[1], - rightColor: undefined // \right uninfluenced by \color in array - } - : res; - }, - mathmlBuilder -}); - -defineEnvironment({ - type: "array", - names: ["smallmatrix"], - props: { - numArgs: 0 - }, - handler(context) { - const payload = { arraystretch: 0.5 }; - const res = parseArray(context.parser, payload, "script"); - res.colSeparationType = "small"; - return res; - }, - mathmlBuilder -}); - -defineEnvironment({ - type: "array", - names: ["subarray"], - props: { - numArgs: 1 - }, - handler(context, args) { - // Parsing of {subarray} is similar to {array} - const symNode = checkSymbolNodeType(args[0]); - const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; - const cols = colalign.map(function(nde) { - const node = assertSymbolNodeType(nde); - const ca = node.text; - // {subarray} only recognizes "l" & "c" - if ("lc".indexOf(ca) !== -1) { - return { - type: "align", - align: ca - }; - } - throw new ParseError("Unknown column alignment: " + ca, nde); - }); - if (cols.length > 1) { - throw new ParseError("{subarray} can contain only one column"); - } - let res = { - cols, - hskipBeforeAndAfter: false, - colSeparationType: "array", - arraystretch: 0 - }; - res = parseArray(context.parser, res, "script"); - if (res.body.length > 0 && res.body[0].length > 1) { - throw new ParseError("{subarray} can contain only one column"); - } - return res; - }, - mathmlBuilder -}); - -// A cases environment (in amsmath.sty) is almost equivalent to -// \def -// \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right. -// {dcases} is a {cases} environment where cells are set in \displaystyle, -// as defined in mathtools.sty. -// {rcases} is another mathtools environment. It's brace is on the right side. -defineEnvironment({ - type: "array", - names: ["cases", "dcases", "rcases", "drcases"], - props: { - numArgs: 0 - }, - handler(context) { - const payload = { - cols: [ - { - type: "align", - align: "l" - }, - { - type: "align", - align: "l" - } - ], - colSeparationType: "cases" - }; - const res = parseArray(context.parser, payload, dCellStyle(context.envName)); - return { - type: "leftright", - mode: context.mode, - body: [res], - left: context.envName.indexOf("r") > -1 ? "." : "\\{", - right: context.envName.indexOf("r") > -1 ? "\\}" : ".", - rightColor: undefined - }; - }, - mathmlBuilder -}); - -// In the align environment, one uses ampersands, &, to specify number of -// columns in each row, and to locate spacing between each column. -// align gets automatic numbering. align* and aligned do not. -// The alignedat environment can be used in math mode. -// Note that we assume \nomallineskiplimit to be zero, -// so that \strut@ is the same as \strut. -defineEnvironment({ - type: "array", - names: ["align", "align*", "aligned", "split"], - props: { - numArgs: 0 - }, - handler: alignedHandler, - mathmlBuilder -}); - -// A gathered environment is like an array environment with one centered -// column, but where rows are considered lines so get \jot line spacing -// and contents are set in \displaystyle. -defineEnvironment({ - type: "array", - names: ["gathered", "gather", "gather*"], - props: { - numArgs: 0 - }, - handler(context) { - if (utils.contains(["gather", "gather*"], context.envName)) { - validateAmsEnvironmentContext(context); - } - const res = { - cols: [ - { - type: "align", - align: "c" - } - ], - addJot: true, - colSeparationType: "gather", - addEqnNum: context.envName === "gather", - emptySingleRow: true, - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder -}); - -// alignat environment is like an align environment, but one must explicitly -// specify maximum number of columns in each row, and can adjust spacing between -// each columns. -defineEnvironment({ - type: "array", - names: ["alignat", "alignat*", "alignedat"], - props: { - numArgs: 1 - }, - handler: alignedHandler, - mathmlBuilder -}); - -defineEnvironment({ - type: "array", - names: ["equation", "equation*"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - const res = { - addEqnNum: context.envName === "equation", - emptySingleRow: true, - singleRow: true, - maxNumCols: 1, - colSeparationType: "gather", - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder -}); - -defineEnvironment({ - type: "array", - names: ["multline", "multline*"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - const res = { - addEqnNum: context.envName === "multline", - maxNumCols: 1, - colSeparationType: "multline", - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder -}); - -defineEnvironment({ - type: "array", - names: ["CD"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - return parseCD(context.parser); - }, - mathmlBuilder -}); - -// Catch \hline outside array environment -defineFunction({ - type: "text", // Doesn't matter what this is. - names: ["\\hline", "\\hdashline"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: true - }, - handler(context, args) { - throw new ParseError(`${context.funcName} valid only within array environment`); - } -}); diff --git a/src/environments/cd.js b/src/environments/cd.js deleted file mode 100644 index 9bb550de..00000000 --- a/src/environments/cd.js +++ /dev/null @@ -1,260 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import * as mml from "../buildMathML"; -import { assertSymbolNodeType } from "../parseNode"; -import ParseError from "../ParseError"; - -const cdArrowFunctionName = { - ">": "\\\\cdrightarrow", - "<": "\\\\cdleftarrow", - "=": "\\\\cdlongequal", - A: "\\uparrow", - V: "\\downarrow", - "|": "\\Vert", - ".": "no arrow" -}; - -const newCell = () => { - // Create an empty cell, to be filled below with parse nodes. - return { type: "styling", body: [], mode: "math", scriptLevel: "display" }; -}; - -const isStartOfArrow = (node) => { - return node.type === "textord" && node.text === "@"; -}; - -const isLabelEnd = (node, endChar) => { - return (node.type === "mathord" || node.type === "atom") && node.text === endChar; -}; - -function cdArrow(arrowChar, labels, parser) { - // Return a parse tree of an arrow and its labels. - // This acts in a way similar to a macro expansion. - const funcName = cdArrowFunctionName[arrowChar]; - switch (funcName) { - case "\\\\cdrightarrow": - case "\\\\cdleftarrow": - return parser.callFunction(funcName, [labels[0]], [labels[1]]); - case "\\uparrow": - case "\\downarrow": { - const leftLabel = parser.callFunction("\\\\cdleft", [labels[0]], []); - const bareArrow = { - type: "atom", - text: funcName, - mode: "math", - family: "rel" - }; - const sizedArrow = parser.callFunction("\\Big", [bareArrow], []); - const rightLabel = parser.callFunction("\\\\cdright", [labels[1]], []); - const arrowGroup = { - type: "ordgroup", - mode: "math", - body: [leftLabel, sizedArrow, rightLabel] - }; - return parser.callFunction("\\\\cdparent", [arrowGroup], []); - } - case "\\\\cdlongequal": - return parser.callFunction("\\\\cdlongequal", [], []); - case "\\Vert": { - const arrow = { type: "textord", text: "\\Vert", mode: "math" }; - return parser.callFunction("\\Big", [arrow], []); - } - default: - return { type: "textord", text: " ", mode: "math" }; - } -} - -export function parseCD(parser) { - // Get the array's parse nodes with \\ temporarily mapped to \cr. - const parsedRows = []; - parser.gullet.beginGroup(); - parser.gullet.macros.set("\\cr", "\\\\\\relax"); - parser.gullet.beginGroup(); - while (true) { // eslint-disable-line no-constant-condition - // Get the parse nodes for the next row. - parsedRows.push(parser.parseExpression(false, "\\\\")); - parser.gullet.endGroup(); - parser.gullet.beginGroup(); - const next = parser.fetch().text; - if (next === "&" || next === "\\\\") { - parser.consume(); - } else if (next === "\\end") { - if (parsedRows[parsedRows.length - 1].length === 0) { - parsedRows.pop(); // final row ended in \\ - } - break; - } else { - throw new ParseError("Expected \\\\ or \\cr or \\end", parser.nextToken); - } - } - - let row = []; - const body = [row]; - - // Loop thru the parse nodes. Collect them into cells and arrows. - for (let i = 0; i < parsedRows.length; i++) { - // Start a new row. - const rowNodes = parsedRows[i]; - // Create the first cell. - let cell = newCell(); - - for (let j = 0; j < rowNodes.length; j++) { - if (!isStartOfArrow(rowNodes[j])) { - // If a parseNode is not an arrow, it goes into a cell. - cell.body.push(rowNodes[j]); - } else { - // Parse node j is an "@", the start of an arrow. - // Before starting on the arrow, push the cell into `row`. - row.push(cell); - - // Now collect parseNodes into an arrow. - // The character after "@" defines the arrow type. - j += 1; - const arrowChar = assertSymbolNodeType(rowNodes[j]).text; - - // Create two empty label nodes. We may or may not use them. - const labels = new Array(2); - labels[0] = { type: "ordgroup", mode: "math", body: [] }; - labels[1] = { type: "ordgroup", mode: "math", body: [] }; - - // Process the arrow. - if ("=|.".indexOf(arrowChar) > -1) { - // Three "arrows", ``@=`, `@|`, and `@.`, do not take labels. - // Do nothing here. - } else if ("<>AV".indexOf(arrowChar) > -1) { - // Four arrows, `@>>>`, `@<<<`, `@AAA`, and `@VVV`, each take - // two optional labels. E.g. the right-point arrow syntax is - // really: @>{optional label}>{optional label}> - // Collect parseNodes into labels. - for (let labelNum = 0; labelNum < 2; labelNum++) { - let inLabel = true; - for (let k = j + 1; k < rowNodes.length; k++) { - if (isLabelEnd(rowNodes[k], arrowChar)) { - inLabel = false; - j = k; - break; - } - if (isStartOfArrow(rowNodes[k])) { - throw new ParseError( - "Missing a " + arrowChar + " character to complete a CD arrow.", - rowNodes[k] - ); - } - - labels[labelNum].body.push(rowNodes[k]); - } - if (inLabel) { - // isLabelEnd never returned a true. - throw new ParseError( - "Missing a " + arrowChar + " character to complete a CD arrow.", - rowNodes[j] - ); - } - } - } else { - throw new ParseError(`Expected one of "<>AV=|." after @.`); - } - - // Now join the arrow to its labels. - const arrow = cdArrow(arrowChar, labels, parser); - - // Wrap the arrow in a styling node - row.push(arrow); - // In CD's syntax, cells are implicit. That is, everything that - // is not an arrow gets collected into a cell. So create an empty - // cell now. It will collect upcoming parseNodes. - cell = newCell(); - } - } - if (i % 2 === 0) { - // Even-numbered rows consist of: cell, arrow, cell, arrow, ... cell - // The last cell is not yet pushed into `row`, so: - row.push(cell); - } else { - // Odd-numbered rows consist of: vert arrow, empty cell, ... vert arrow - // Remove the empty cell that was placed at the beginning of `row`. - row.shift(); - } - row = []; - body.push(row); - } - - // End row group - parser.gullet.endGroup(); - // End array group defining \\ - parser.gullet.endGroup(); - - // define column separation. - const cols = new Array(body[0].length).fill({ - type: "align", - align: "c" - }); - - return { - type: "array", - mode: "math", - body, - arraystretch: 1, - addJot: true, - rowGaps: [null], - cols, - colSeparationType: "CD", - hLinesBeforeRow: new Array(body.length + 1).fill([]) - }; -} - -// The functions below are not available for general use. -// They are here only for internal use by the {CD} environment in placing labels -// next to vertical arrows. - -// We don't need any such functions for horizontal arrows because we can reuse -// the functionality that already exists for extensible arrows. - -defineFunction({ - type: "cdlabel", - names: ["\\\\cdleft", "\\\\cdright"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - return { - type: "cdlabel", - mode: parser.mode, - side: funcName.slice(4), - label: args[0] - }; - }, - mathmlBuilder(group, style) { - let label = new mathMLTree.MathNode("mrow", [mml.buildGroup(group.label, style)]); - label = new mathMLTree.MathNode("mpadded", [label]); - label.setAttribute("width", "0"); - if (group.side === "left") { - label.setAttribute("lspace", "-1width"); - } - // We have to guess at vertical alignment. We know the arrow is 1.8em tall, - // But we don't know the height or depth of the label. - label.setAttribute("voffset", "0.7em"); - label = new mathMLTree.MathNode("mstyle", [label]); - label.setAttribute("displaystyle", "false"); - label.setAttribute("scriptlevel", "1"); - return label; - } -}); - -defineFunction({ - type: "cdlabelparent", - names: ["\\\\cdparent"], - props: { - numArgs: 1 - }, - handler({ parser }, args) { - return { - type: "cdlabelparent", - mode: parser.mode, - fragment: args[0] - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow", [mml.buildGroup(group.fragment, style)]); - } -}); diff --git a/src/functions.js b/src/functions.js deleted file mode 100644 index 72e8e5b5..00000000 --- a/src/functions.js +++ /dev/null @@ -1,59 +0,0 @@ -/** Include this to ensure that all functions are defined. */ -import { _functions } from "./defineFunction"; - -const functions = _functions; -export default functions; - -// TODO(kevinb): have functions return an object and call defineFunction with -// that object in this file instead of relying on side-effects. -import "./functions/accent"; -import "./functions/accentunder"; -import "./functions/arrow"; -import "./functions/cancelto"; -import "./environments/cd"; -import "./functions/char"; -import "./functions/color"; -import "./functions/cr"; -import "./functions/def"; -import "./functions/delimsizing"; -import "./functions/enclose"; -import "./functions/environment"; -import "./functions/envTag"; -import "./functions/font"; -import "./functions/genfrac"; -import "./functions/horizBrace"; -import "./functions/href"; -import "./functions/html"; -import "./functions/includegraphics"; -import "./functions/kern"; -import "./functions/label"; -import "./functions/lap"; -import "./functions/math"; -import "./functions/mathchoice"; -import "./functions/mclass"; -import "./functions/multiscript"; -import "./functions/not"; -import "./functions/op"; -import "./functions/operatorname"; -import "./functions/ordgroup"; -import "./functions/overline"; -import "./functions/phantom"; -import "./functions/pmb"; -import "./functions/raise"; -import "./functions/ref"; -import "./functions/relax"; -import "./functions/rule"; -import "./functions/sizing"; -import "./functions/smash"; -import "./functions/sqrt"; -import "./functions/styling"; -import "./functions/supsub"; -import "./functions/symbolsOp"; -import "./functions/symbolsOrd"; -import "./functions/symbolsSpacing"; -import "./functions/tag"; -import "./functions/text"; -import "./functions/tip"; -import "./functions/toggle"; -import "./functions/underline"; -import "./functions/verb"; diff --git a/src/functions/accent.js b/src/functions/accent.js deleted file mode 100644 index 051d0b8d..00000000 --- a/src/functions/accent.js +++ /dev/null @@ -1,128 +0,0 @@ -import defineFunction, { normalizeArgument } from "../defineFunction" -import mathMLTree from "../mathMLTree" -import stretchy from "../stretchy" -import * as mml from "../buildMathML" - -const mathmlBuilder = (group, style) => { - const accentNode = group.isStretchy - ? stretchy.mathMLnode(group.label) - : new mathMLTree.MathNode("mo", [mml.makeText(group.label, group.mode)]); - - if (!group.isStretchy) { - accentNode.setAttribute("stretchy", "false") - } - - const node = new mathMLTree.MathNode((group.label === "\\c" ? "munder" : "mover"), - [mml.buildGroup(group.base, style), accentNode] - ); - - node.setAttribute("accent", "true"); - return node; -}; - -const NON_STRETCHY_ACCENT_REGEX = new RegExp( - [ - "\\acute", - "\\grave", - "\\ddot", - "\\dddot", - "\\ddddot", - "\\tilde", - "\\bar", - "\\breve", - "\\check", - "\\hat", - "\\vec", - "\\dot", - "\\mathring" - ] - .map((accent) => `\\${accent}`) - .join("|") -); - -// Accents -defineFunction({ - type: "accent", - names: [ - "\\acute", - "\\grave", - "\\ddot", - "\\dddot", - "\\ddddot", - "\\tilde", - "\\bar", - "\\breve", - "\\check", - "\\hat", - "\\vec", - "\\dot", - "\\mathring", - "\\overparen", - "\\widecheck", - "\\widehat", - "\\wideparen", - "\\widetilde", - "\\overrightarrow", - "\\overleftarrow", - "\\Overrightarrow", - "\\overleftrightarrow", - "\\overgroup", - "\\overleftharpoon", - "\\overrightharpoon" - ], - props: { - numArgs: 1 - }, - handler: (context, args) => { - const base = normalizeArgument(args[0]); - - const isStretchy = !NON_STRETCHY_ACCENT_REGEX.test(context.funcName); - const isShifty = - !isStretchy || - context.funcName === "\\widehat" || - context.funcName === "\\widetilde" || - context.funcName === "\\widecheck"; - - return { - type: "accent", - mode: context.parser.mode, - label: context.funcName, - isStretchy: isStretchy, - isShifty: isShifty, - base: base - }; - }, - mathmlBuilder -}); - -// Text-mode accents -defineFunction({ - type: "accent", - names: ["\\'", "\\`", "\\^", "\\~", "\\=", "\\c", "\\u", "\\.", '\\"', "\\r", "\\H", "\\v"], - props: { - numArgs: 1, - allowedInText: true, - allowedInMath: true, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const base = normalizeArgument(args[0]); - const mode = context.parser.mode; - - if (mode === "math" && context.parser.settings.strict) { - // LaTeX only writes a warning. It doesn't stop. We'll issue the same warning. - // eslint-disable-next-line no-console - console.log(`Temml parse error: Command ${context.funcName} is invalid in math mode.`) - } - - return { - type: "accent", - mode: mode, - label: context.funcName, - isStretchy: false, - isShifty: true, - base: base - }; - }, - mathmlBuilder -}); diff --git a/src/functions/accentunder.js b/src/functions/accentunder.js deleted file mode 100644 index 6ac3cbff..00000000 --- a/src/functions/accentunder.js +++ /dev/null @@ -1,38 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import stretchy from "../stretchy"; - -import * as mml from "../buildMathML"; - -defineFunction({ - type: "accentUnder", - names: [ - "\\underleftarrow", - "\\underrightarrow", - "\\underleftrightarrow", - "\\undergroup", - "\\underparen", - "\\utilde" - ], - props: { - numArgs: 1 - }, - handler: ({ parser, funcName }, args) => { - const base = args[0]; - return { - type: "accentUnder", - mode: parser.mode, - label: funcName, - base: base - }; - }, - mathmlBuilder: (group, style) => { - const accentNode = stretchy.mathMLnode(group.label); - const node = new mathMLTree.MathNode("munder", [ - mml.buildGroup(group.base, style), - accentNode - ]); - node.setAttribute("accentunder", "true"); - return node; - } -}); diff --git a/src/functions/arrow.js b/src/functions/arrow.js deleted file mode 100644 index b5412c4a..00000000 --- a/src/functions/arrow.js +++ /dev/null @@ -1,192 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import stretchy from "../stretchy"; -import { emScale } from "../units"; -import * as mml from "../buildMathML"; - -// Helper functions -const paddedNode = (group, width, lspace = "0.3em") => { - const node = new mathMLTree.MathNode("mpadded", group ? [group] : []); - node.setAttribute("width", width) - node.setAttribute("lspace", lspace) - return node; -}; - -const labelSize = (size, scriptLevel) => (size / emScale(scriptLevel)).toFixed(4) + "em" - -const munderoverNode = (name, body, below, style) => { - const arrowNode = stretchy.mathMLnode(name); - // Is this the short part of a mhchem equilibrium arrow? - const isEq = name.slice(1, 3) === "eq" - const minWidth = name.charAt(1) === "x" - ? "1.75" // mathtools extensible arrows are 1.75em long - : name.slice(2, 4) === "cd" - ? "3.0" // cd package arrows - : isEq - ? "1.0" // The shorter harpoon of a mhchem equilibrium arrow - : "2.0"; // other mhchem arrows - arrowNode.setAttribute("minsize", String(minWidth) + "em"); - arrowNode.setAttribute("lspace", "0") - arrowNode.setAttribute("rspace", (isEq ? "0.5em" : "0")) - - // upper and lower labels are set to scriptlevel by MathML - // So we have to adjust our dimensions accordingly. - const labelStyle = style.withLevel(style.level < 2 ? 2 : 3) - const emptyLabelWidth = labelSize(minWidth, labelStyle.level) - const lspace = labelSize((isEq ? 0 : 0.3), labelStyle.level) - let widthAdder = labelSize((isEq ? -0.4 : 0.6), labelStyle.level) - if (widthAdder.charAt(0) !== "-") { widthAdder = "+" + widthAdder } - - const upperNode = (body && body.body && - // \hphantom visible content - (body.body.body || body.body.length > 0)) - ? paddedNode(mml.buildGroup(body, labelStyle), widthAdder, lspace) - // Since Firefox does not recognize minsize set on the arrow, - // create an upper node w/correct width. - : paddedNode(null, emptyLabelWidth, "0") - const lowerNode = (below && below.body && - (below.body.body || below.body.length > 0)) - ? paddedNode(mml.buildGroup(below, labelStyle), widthAdder, lspace) - : paddedNode(null, emptyLabelWidth, "0") - const node = new mathMLTree.MathNode("munderover", [arrowNode, lowerNode, upperNode]); - return node -} - -// Stretchy arrows with an optional argument -defineFunction({ - type: "xArrow", - names: [ - "\\xleftarrow", - "\\xrightarrow", - "\\xLeftarrow", - "\\xRightarrow", - "\\xleftrightarrow", - "\\xLeftrightarrow", - "\\xhookleftarrow", - "\\xhookrightarrow", - "\\xmapsto", - "\\xrightharpoondown", - "\\xrightharpoonup", - "\\xleftharpoondown", - "\\xleftharpoonup", - "\\xlongequal", - "\\xtwoheadrightarrow", - "\\xtwoheadleftarrow", - // The next 7 functions are here only to support mhchem - "\\yields", - "\\yieldsLeft", - "\\mesomerism", - "\\longrightharpoonup", - "\\longleftharpoondown", - // The next 3 functions are here only to support the {CD} environment. - "\\\\cdrightarrow", - "\\\\cdleftarrow", - "\\\\cdlongequal" - ], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser, funcName }, args, optArgs) { - return { - type: "xArrow", - mode: parser.mode, - name: funcName, - body: args[0], - below: optArgs[0] - }; - }, - mathmlBuilder(group, style) { - // Build the arrow and its labels. - const node = munderoverNode(group.name, group.body, group.below, style) - // Create operator spacing for a relation. - const wrapper = new mathMLTree.MathNode("mpadded", [node]) - wrapper.setAttribute("lspace", "0.2778em") - wrapper.setAttribute("width", "+0.5556em") - return wrapper - } -}); - -const arrowComponent = { - "\\xtofrom": ["\\xrightarrow", "\\xleftarrow"], - "\\xleftrightharpoons": ["\\xleftharpoonup", "\\xrightharpoondown"], - "\\xrightleftharpoons": ["\\xrightharpoonup", "\\xleftharpoondown"], - "\\yieldsLeftRight": ["\\yields", "\\yieldsLeft"], - // The next three all get the same harpoon glyphs. Only the lengths and paddings differ. - "\\equilibrium": ["\\longrightharpoonup", "\\longleftharpoondown"], - "\\equilibriumRight": ["\\longrightharpoonup", "\\eqleftharpoondown"], - "\\equilibriumLeft": ["\\eqrightharpoonup", "\\longleftharpoondown"] -} - -// Browsers are not good at stretching a glyph that contains a pair of stacked arrows such as ⇄. -// So we stack a pair of single arrows. -defineFunction({ - type: "stackedArrow", - names: [ - "\\xtofrom", // expfeil - "\\xleftrightharpoons", // mathtools - "\\xrightleftharpoons", // mathtools - "\\yieldsLeftRight", // mhchem - "\\equilibrium", // mhchem - "\\equilibriumRight", - "\\equilibriumLeft" - ], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser, funcName }, args, optArgs) { - const lowerArrowBody = args[0] - ? { - type: "hphantom", - mode: parser.mode, - body: args[0] - } - : null; - const upperArrowBelow = optArgs[0] - ? { - type: "hphantom", - mode: parser.mode, - body: optArgs[0] - } - : null; - return { - type: "stackedArrow", - mode: parser.mode, - name: funcName, - body: args[0], - upperArrowBelow, - lowerArrowBody, - below: optArgs[0] - }; - }, - mathmlBuilder(group, style) { - const topLabel = arrowComponent[group.name][0] - const botLabel = arrowComponent[group.name][1] - const topArrow = munderoverNode(topLabel, group.body, group.upperArrowBelow, style) - const botArrow = munderoverNode(botLabel, group.lowerArrowBody, group.below, style) - let wrapper - - const raiseNode = new mathMLTree.MathNode("mpadded", [topArrow]) - raiseNode.setAttribute("voffset", "0.3em") - raiseNode.setAttribute("height", "+0.3em") - raiseNode.setAttribute("depth", "-0.3em") - // One of the arrows is given ~zero width. so the other has the same horzontal alignment. - if (group.name === "\\equilibriumLeft") { - const botNode = new mathMLTree.MathNode("mpadded", [botArrow]) - botNode.setAttribute("width", "0.5em") - wrapper = new mathMLTree.MathNode("mpadded", [botNode, raiseNode]) - } else { - raiseNode.setAttribute("width", (group.name === "\\equilibriumRight" ? "0.5em" : "0")) - wrapper = new mathMLTree.MathNode("mpadded", [raiseNode, botArrow]) - } - - wrapper.setAttribute("voffset", "-0.18em") - wrapper.setAttribute("width", "+0.5556em") - wrapper.setAttribute("height", "-0.18em") - wrapper.setAttribute("depth", "+0.18em") - wrapper.setAttribute("lspace", "0.2778em") - return wrapper - } -}); - diff --git a/src/functions/cancelto.js b/src/functions/cancelto.js deleted file mode 100644 index 1b418a24..00000000 --- a/src/functions/cancelto.js +++ /dev/null @@ -1,36 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import * as mml from "../buildMathML"; - -defineFunction({ - type: "cancelto", - names: ["\\cancelto"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "cancelto", - mode: parser.mode, - value: args[0], - expression: args[1] - }; - }, - mathmlBuilder(group, style) { - const value = new mathMLTree.MathNode( - "mpadded", - [mml.buildGroup(group.value, style)] - ) - value.setAttribute("depth", `-0.1em`) - value.setAttribute("height", `+0.1em`) - value.setAttribute("voffset", `0.1em`) - - const expression = new mathMLTree.MathNode( - "menclose", - [mml.buildGroup(group.expression, style)] - ) - expression.setAttribute("notation", `updiagonalarrow`) - - return new mathMLTree.MathNode("msup", [expression, value]) - } -}) diff --git a/src/functions/char.js b/src/functions/char.js deleted file mode 100644 index b2355c0b..00000000 --- a/src/functions/char.js +++ /dev/null @@ -1,33 +0,0 @@ -import defineFunction from "../defineFunction" -import ParseError from "../ParseError" -import { assertNodeType } from "../parseNode" - -// \@char is an internal function that takes a grouped decimal argument like -// {123} and converts into symbol with code 123. It is used by the *macro* -// \char defined in macros.js. -defineFunction({ - type: "textord", - names: ["\\@char"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser, token }, args) { - const arg = assertNodeType(args[0], "ordgroup") - const group = arg.body - let number = "" - for (let i = 0; i < group.length; i++) { - const node = assertNodeType(group[i], "textord") - number += node.text - } - const code = parseInt(number) - if (isNaN(code)) { - throw new ParseError(`\\@char has non-numeric argument ${number}`, token) - } - return { - type: "textord", - mode: parser.mode, - text: String.fromCodePoint(code) - } - } -}) diff --git a/src/functions/color.js b/src/functions/color.js deleted file mode 100644 index eb15c6aa..00000000 --- a/src/functions/color.js +++ /dev/null @@ -1,254 +0,0 @@ -import defineFunction, { ordargument } from "../defineFunction" -import mathMLTree, { wrapWithMstyle } from "../mathMLTree" -import { assertNodeType } from "../parseNode" -import ParseError from "../ParseError" -import * as mml from "../buildMathML" - -// Helpers -const htmlRegEx = /^(#[a-f0-9]{3}|#?[a-f0-9]{6})$/i -const htmlOrNameRegEx = /^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i -const RGBregEx = /^ *\d{1,3} *(?:, *\d{1,3} *){2}$/ -const rgbRegEx = /^ *[10](?:\.\d*)? *(?:, *[10](?:\.\d*)? *){2}$/ -const xcolorHtmlRegEx = /^[a-f0-9]{6}$/i -const toHex = num => { - let str = num.toString(16) - if (str.length === 1) { str = "0" + str } - return str -} - -// Colors from Tables 4.1 and 4.2 of the xcolor package. -// Table 4.1 (lower case) RGB values are taken from chroma and xcolor.dtx. -// Table 4.2 (Capitalizzed) values were sampled, because Chroma contains a unreliable -// conversion from cmyk to RGB. See https://tex.stackexchange.com/a/537274. -const xcolors = JSON.parse(`{ - "Apricot": "#ffb484", - "Aquamarine": "#08b4bc", - "Bittersweet": "#c84c14", - "blue": "#0000FF", - "Blue": "#303494", - "BlueGreen": "#08b4bc", - "BlueViolet": "#503c94", - "BrickRed": "#b8341c", - "brown": "#BF8040", - "Brown": "#802404", - "BurntOrange": "#f8941c", - "CadetBlue": "#78749c", - "CarnationPink": "#f884b4", - "Cerulean": "#08a4e4", - "CornflowerBlue": "#40ace4", - "cyan": "#00FFFF", - "Cyan": "#08acec", - "Dandelion": "#ffbc44", - "darkgray": "#404040", - "DarkOrchid": "#a8548c", - "Emerald": "#08ac9c", - "ForestGreen": "#089c54", - "Fuchsia": "#90348c", - "Goldenrod": "#ffdc44", - "gray": "#808080", - "Gray": "#98949c", - "green": "#00FF00", - "Green": "#08a44c", - "GreenYellow": "#e0e474", - "JungleGreen": "#08ac9c", - "Lavender": "#f89cc4", - "lightgray": "#c0c0c0", - "lime": "#BFFF00", - "LimeGreen": "#90c43c", - "magenta": "#FF00FF", - "Magenta": "#f0048c", - "Mahogany": "#b0341c", - "Maroon": "#b03434", - "Melon": "#f89c7c", - "MidnightBlue": "#086494", - "Mulberry": "#b03c94", - "NavyBlue": "#086cbc", - "olive": "#7F7F00", - "OliveGreen": "#407c34", - "orange": "#FF8000", - "Orange": "#f8843c", - "OrangeRed": "#f0145c", - "Orchid": "#b074ac", - "Peach": "#f8945c", - "Periwinkle": "#8074bc", - "PineGreen": "#088c74", - "pink": "#ff7f7f", - "Plum": "#98248c", - "ProcessBlue": "#08b4ec", - "purple": "#BF0040", - "Purple": "#a0449c", - "RawSienna": "#983c04", - "red": "#ff0000", - "Red": "#f01c24", - "RedOrange": "#f86434", - "RedViolet": "#a0246c", - "Rhodamine": "#f0549c", - "Royallue": "#0874bc", - "RoyalPurple": "#683c9c", - "RubineRed": "#f0047c", - "Salmon": "#f8948c", - "SeaGreen": "#30bc9c", - "Sepia": "#701404", - "SkyBlue": "#48c4dc", - "SpringGreen": "#c8dc64", - "Tan": "#e09c74", - "teal": "#007F7F", - "TealBlue": "#08acb4", - "Thistle": "#d884b4", - "Turquoise": "#08b4cc", - "violet": "#800080", - "Violet": "#60449c", - "VioletRed": "#f054a4", - "WildStrawberry": "#f0246c", - "yellow": "#FFFF00", - "Yellow": "#fff404", - "YellowGreen": "#98cc6c", - "YellowOrange": "#ffa41c" -}`) - -export const colorFromSpec = (model, spec) => { - let color = "" - if (model === "HTML") { - if (!htmlRegEx.test(spec)) { - throw new ParseError("Invalid HTML input.") - } - color = spec - } else if (model === "RGB") { - if (!RGBregEx.test(spec)) { - throw new ParseError("Invalid RGB input.") - } - spec.split(",").map(e => { color += toHex(Number(e.trim())) }) - } else { - if (!rgbRegEx.test(spec)) { - throw new ParseError("Invalid rbg input.") - } - spec.split(",").map(e => { - const num = Number(e.trim()) - if (num > 1) { throw new ParseError("Color rgb input must be < 1.") } - color += toHex((num * 255)) - }) - } - if (color.charAt(0) !== "#") { color = "#" + color } - return color -} - -export const validateColor = (color, macros, token) => { - const macroName = `\\\\color@${color}` // from \defineColor. - const match = htmlOrNameRegEx.exec(color); - if (!match) { throw new ParseError("Invalid color: '" + color + "'", token) } - // We allow a 6-digit HTML color spec without a leading "#". - // This follows the xcolor package's HTML color model. - // Predefined color names are all missed by this RegEx pattern. - if (xcolorHtmlRegEx.test(color)) { - return "#" + color - } else if (color.charAt(0) === "#") { - return color - } else if (macros.has(macroName)) { - color = macros.get(macroName).tokens[0].text - } else if (xcolors[color]) { - color = xcolors[color] - } - return color -} - -const mathmlBuilder = (group, style) => { - const inner = mml.buildExpression(group.body, style.withColor(group.color)) - // Wrap with an element. - const node = wrapWithMstyle(inner) - node.setAttribute("mathcolor", group.color) - // Wrap w/. We get better operator spacing that way. - return new mathMLTree.MathNode("mrow", [node]) -} - -defineFunction({ - type: "color", - names: ["\\textcolor"], - props: { - numArgs: 2, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "original"] - }, - handler({ parser, token }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string - let color = "" - if (model) { - const spec = assertNodeType(args[0], "raw").string - color = colorFromSpec(model, spec) - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros, token) - } - const body = args[1]; - return { - type: "color", - mode: parser.mode, - color, - body: ordargument(body) - } - }, - mathmlBuilder -}) - -defineFunction({ - type: "color", - names: ["\\color"], - props: { - numArgs: 1, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw"] - }, - handler({ parser, token }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string - let color = "" - if (model) { - const spec = assertNodeType(args[0], "raw").string - color = colorFromSpec(model, spec) - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros, token) - } - - // Set macro \current@color in current namespace to store the current - // color, mimicking the behavior of color.sty. - // This is currently used just to correctly color a \right - // that follows a \color command. - parser.gullet.macros.set("\\current@color", color) - - // Parse out the implicit body that should be colored. - // Since \color nodes should not be nested, break on \color. - const body = parser.parseExpression(true, "\\color") - - return { - type: "color", - mode: parser.mode, - color, - body - } - }, - mathmlBuilder -}) - -defineFunction({ - type: "color", - names: ["\\definecolor"], - props: { - numArgs: 3, - allowedInText: true, - argTypes: ["raw", "raw", "raw"] - }, - handler({ parser, funcName, token }, args) { - const name = assertNodeType(args[0], "raw").string - if (!/^[A-Za-z]+$/.test(name)) { - throw new ParseError("Color name must be latin letters.", token) - } - const model = assertNodeType(args[1], "raw").string - if (!["HTML", "RGB", "rgb"].includes(model)) { - throw new ParseError("Color model must be HTML, RGB, or rgb.", token) - } - const spec = assertNodeType(args[2], "raw").string - const color = colorFromSpec(model, spec) - parser.gullet.macros.set(`\\\\color@${name}`, { tokens: [{ text: color }], numArgs: 0 }) - return { type: "internal", mode: parser.mode } - } - // No mathmlBuilder. The point of \definecolor is to set a macro. -}) diff --git a/src/functions/cr.js b/src/functions/cr.js deleted file mode 100644 index 18de4655..00000000 --- a/src/functions/cr.js +++ /dev/null @@ -1,46 +0,0 @@ -// Row breaks within tabular environments, and line breaks at top level - -import defineFunction from "../defineFunction" -import mathMLTree from "../mathMLTree" -import { calculateSize } from "../units" -import { assertNodeType } from "../parseNode" - -// \DeclareRobustCommand\\{...\@xnewline} -defineFunction({ - type: "cr", - names: ["\\\\"], - props: { - numArgs: 0, - numOptionalArgs: 1, - argTypes: ["size"], - allowedInText: true - }, - - handler({ parser }, args, optArgs) { - const size = optArgs[0]; - const newLine = !parser.settings.displayMode; - return { - type: "cr", - mode: parser.mode, - newLine, - size: size && assertNodeType(size, "size").value - } - }, - - // The following builder is called only at the top level, - // not within tabular/array environments. - - mathmlBuilder(group, style) { - // MathML 3.0 calls for newline to occur in an or an . - // Ref: https://www.w3.org/TR/MathML3/chapter3.html#presm.linebreaking - const node = new mathMLTree.MathNode("mo") - if (group.newLine) { - node.setAttribute("linebreak", "newline") - if (group.size) { - const size = calculateSize(group.size, style) - node.setAttribute("height", size.number + size.unit) - } - } - return node - } -}) diff --git a/src/functions/def.js b/src/functions/def.js deleted file mode 100644 index 072611bb..00000000 --- a/src/functions/def.js +++ /dev/null @@ -1,203 +0,0 @@ -import defineFunction from "../defineFunction"; -import ParseError from "../ParseError"; - -const checkControlSequence = (tok) => { - const name = tok.text; - if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { - throw new ParseError("Expected a control sequence", tok); - } - return name; -}; - -const getRHS = (parser) => { - let tok = parser.gullet.popToken(); - if (tok.text === "=") { - // consume optional equals - tok = parser.gullet.popToken(); - if (tok.text === " ") { - // consume one optional space - tok = parser.gullet.popToken(); - } - } - return tok; -}; - -const letCommand = (parser, name, tok) => { - let macro = parser.gullet.macros.get(tok.text); - if (macro == null) { - // don't expand it later even if a macro with the same name is defined - // e.g., \let\foo=\frac \def\frac{\relax} \frac12 - tok.noexpand = true; - macro = { - tokens: [tok], - numArgs: 0, - // reproduce the same behavior in expansion - unexpandable: !parser.gullet.isExpandable(tok.text) - }; - } - parser.gullet.macros.set(name, macro); -}; - -// Basic support for macro definitions: \def -// -> -// -> -defineFunction({ - type: "internal", - names: ["\\def", "\\edef"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - let tok = parser.gullet.popToken(); - const name = tok.text; - if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { - throw new ParseError("Expected a control sequence", tok); - } - - let numArgs = 0; - let insert; - const delimiters = [[]]; - // contains no braces - while (parser.gullet.future().text !== "{") { - tok = parser.gullet.popToken(); - if (tok.text === "#") { - // If the very last character of the is #, so that - // this # is immediately followed by {, TeX will behave as if the { - // had been inserted at the right end of both the parameter text - // and the replacement text. - if (parser.gullet.future().text === "{") { - insert = parser.gullet.future(); - delimiters[numArgs].push("{"); - break; - } - - // A parameter, the first appearance of # must be followed by 1, - // the next by 2, and so on; up to nine #’s are allowed - tok = parser.gullet.popToken(); - if (!/^[1-9]$/.test(tok.text)) { - throw new ParseError(`Invalid argument number "${tok.text}"`); - } - if (parseInt(tok.text) !== numArgs + 1) { - throw new ParseError(`Argument number "${tok.text}" out of order`); - } - numArgs++; - delimiters.push([]); - } else if (tok.text === "EOF") { - throw new ParseError("Expected a macro definition"); - } else { - delimiters[numArgs].push(tok.text); - } - } - // replacement text, enclosed in '{' and '}' and properly nested - let { tokens } = parser.gullet.consumeArg(); - if (insert) { - tokens.unshift(insert); - } - - if (funcName === "\\edef") { - tokens = parser.gullet.expandTokens(tokens); - tokens.reverse(); // to fit in with stack order - } - // Final arg is the expansion of the macro - parser.gullet.macros.set(name, { tokens, numArgs, delimiters } - ); - return { type: "internal", mode: parser.mode }; - } -}); - -// -> -// -> \futurelet -// | \let -// -> |= -defineFunction({ - type: "internal", - names: ["\\let"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - const name = checkControlSequence(parser.gullet.popToken()); - parser.gullet.consumeSpaces(); - const tok = getRHS(parser); - letCommand(parser, name, tok); - return { type: "internal", mode: parser.mode }; - } -}); - -// ref: https://www.tug.org/TUGboat/tb09-3/tb22bechtolsheim.pdf -defineFunction({ - type: "internal", - names: ["\\futurelet"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - const name = checkControlSequence(parser.gullet.popToken()); - const middle = parser.gullet.popToken(); - const tok = parser.gullet.popToken(); - letCommand(parser, name, tok); - parser.gullet.pushToken(tok); - parser.gullet.pushToken(middle); - return { type: "internal", mode: parser.mode }; - } -}); - -defineFunction({ - type: "internal", - names: ["\\newcommand", "\\renewcommand", "\\providecommand"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - let name = "" - const tok = parser.gullet.popToken() - if (tok.text === "{") { - name = checkControlSequence(parser.gullet.popToken()) - parser.gullet.popToken() - } else { - name = checkControlSequence(tok) - } - - const exists = parser.gullet.isDefined(name); - if (exists && funcName === "\\newcommand") { - throw new ParseError( - `\\newcommand{${name}} attempting to redefine ${name}; use \\renewcommand` - ); - } - if (!exists && funcName === "\\renewcommand") { - throw new ParseError( - `\\renewcommand{${name}} when command ${name} does not yet exist; use \\newcommand` - ); - } - - let numArgs = 0; - if (parser.gullet.future().text === "[") { - let tok = parser.gullet.popToken(); - tok = parser.gullet.popToken(); - if (!/^[0-9]$/.test(tok.text)) { - throw new ParseError(`Invalid number of arguments: "${tok.text}"`); - } - numArgs = parseInt(tok.text); - tok = parser.gullet.popToken(); - if (tok.text !== "]") { - throw new ParseError(`Invalid argument "${tok.text}"`); - } - } - - // replacement text, enclosed in '{' and '}' and properly nested - const { tokens } = parser.gullet.consumeArg(); - - parser.gullet.macros.set(name, { tokens, numArgs }) - - return { type: "internal", mode: parser.mode }; - - } -}); diff --git a/src/functions/delimsizing.js b/src/functions/delimsizing.js deleted file mode 100644 index 953aa2b0..00000000 --- a/src/functions/delimsizing.js +++ /dev/null @@ -1,296 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import ParseError from "../ParseError"; -import utils from "../utils"; -import { assertNodeType, checkSymbolNodeType } from "../parseNode"; - -import * as mml from "../buildMathML"; - -// Extra data needed for the delimiter handler down below -export const delimiterSizes = { - "\\bigl": { mclass: "mopen", size: 1 }, - "\\Bigl": { mclass: "mopen", size: 2 }, - "\\biggl": { mclass: "mopen", size: 3 }, - "\\Biggl": { mclass: "mopen", size: 4 }, - "\\bigr": { mclass: "mclose", size: 1 }, - "\\Bigr": { mclass: "mclose", size: 2 }, - "\\biggr": { mclass: "mclose", size: 3 }, - "\\Biggr": { mclass: "mclose", size: 4 }, - "\\bigm": { mclass: "mrel", size: 1 }, - "\\Bigm": { mclass: "mrel", size: 2 }, - "\\biggm": { mclass: "mrel", size: 3 }, - "\\Biggm": { mclass: "mrel", size: 4 }, - "\\big": { mclass: "mord", size: 1 }, - "\\Big": { mclass: "mord", size: 2 }, - "\\bigg": { mclass: "mord", size: 3 }, - "\\Bigg": { mclass: "mord", size: 4 } -}; - -export const delimiters = [ - "(", - "\\lparen", - ")", - "\\rparen", - "[", - "\\lbrack", - "]", - "\\rbrack", - "\\{", - "\\lbrace", - "\\}", - "\\rbrace", - "\\lfloor", - "\\rfloor", - "\u230a", - "\u230b", - "\\lceil", - "\\rceil", - "\u2308", - "\u2309", - "<", - ">", - "\\langle", - "\u27e8", - "\\rangle", - "\u27e9", - "\\lt", - "\\gt", - "\\lvert", - "\\rvert", - "\\lVert", - "\\rVert", - "\\lgroup", - "\\rgroup", - "\u27ee", - "\u27ef", - "\\lmoustache", - "\\rmoustache", - "\u23b0", - "\u23b1", - "\\llbracket", - "\\rrbracket", - "\u27e6", - "\u27e6", - "\\lBrace", - "\\rBrace", - "\u2983", - "\u2984", - "/", - "\\backslash", - "|", - "\\vert", - "\\|", - "\\Vert", - "\\uparrow", - "\\Uparrow", - "\\downarrow", - "\\Downarrow", - "\\updownarrow", - "\\Updownarrow", - "." -]; - -// Metrics of the different sizes. Found by looking at TeX's output of -// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$ -// Used to create stacked delimiters of appropriate sizes in makeSizedDelim. -const sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0]; - -// Delimiter functions -function checkDelimiter(delim, context) { - if (delim.type === "ordgroup" && delim.body.length === 1 && delim.body[0].text === "\u2044") { - // Recover "/" from the zero spacing group. (See macros.js) - delim = { type: "textord", text: "/", mode: "math" } - } - const symDelim = checkSymbolNodeType(delim) - if (symDelim && utils.contains(delimiters, symDelim.text)) { - // If a character is not in the MathML operator dictionary, it will not stretch. - // Replace such characters w/characters that will stretch. - if (utils.contains(["<", "\\lt"], symDelim.text)) { symDelim.text = "⟨" } - if (utils.contains([">", "\\gt"], symDelim.text)) { symDelim.text = "⟩" } - if (symDelim.text === "/") { symDelim.text = "\u2215" } - if (symDelim.text === "\\backslash") { symDelim.text = "\u2216" } - return symDelim; - } else if (symDelim) { - throw new ParseError(`Invalid delimiter '${symDelim.text}' after '${context.funcName}'`, delim); - } else { - throw new ParseError(`Invalid delimiter type '${delim.type}'`, delim); - } -} - -defineFunction({ - type: "delimsizing", - names: [ - "\\bigl", - "\\Bigl", - "\\biggl", - "\\Biggl", - "\\bigr", - "\\Bigr", - "\\biggr", - "\\Biggr", - "\\bigm", - "\\Bigm", - "\\biggm", - "\\Biggm", - "\\big", - "\\Big", - "\\bigg", - "\\Bigg" - ], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - - return { - type: "delimsizing", - mode: context.parser.mode, - size: delimiterSizes[context.funcName].size, - mclass: delimiterSizes[context.funcName].mclass, - delim: delim.text - }; - }, - mathmlBuilder: (group) => { - const children = []; - - if (group.delim === ".") { group.delim = "" } - children.push(mml.makeText(group.delim, group.mode)); - - const node = new mathMLTree.MathNode("mo", children); - - if (group.mclass === "mopen" || group.mclass === "mclose") { - // Only some of the delimsizing functions act as fences, and they - // return "mopen" or "mclose" mclass. - node.setAttribute("fence", "true"); - } else { - // Explicitly disable fencing if it's not a fence, to override the - // defaults. - node.setAttribute("fence", "false"); - } - if (group.delim === "\u2216") { - // \backslash is not in the operator dictionary, - // so we have to explicitly set stretchy to true. - node.setAttribute("stretchy", "true") - } - - node.setAttribute("symmetric", "true"); // Needed for tall arrows in Firefox. - node.setAttribute("minsize", sizeToMaxHeight[group.size] + "em"); - node.setAttribute("maxsize", sizeToMaxHeight[group.size] + "em"); - - return node; - } -}); - -function assertParsed(group) { - if (!group.body) { - throw new Error("Bug: The leftright ParseNode wasn't fully parsed."); - } -} - -defineFunction({ - type: "leftright-right", - names: ["\\right"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - // \left case below triggers parsing of \right in - // `const right = parser.parseFunction();` - // uses this return value. - const color = context.parser.gullet.macros.get("\\current@color"); - if (color && typeof color !== "string") { - throw new ParseError("\\current@color set to non-string in \\right"); - } - return { - type: "leftright-right", - mode: context.parser.mode, - delim: checkDelimiter(args[0], context).text, - color // undefined if not set via \color - }; - } -}); - -defineFunction({ - type: "leftright", - names: ["\\left"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - - const parser = context.parser; - // Parse out the implicit body - ++parser.leftrightDepth; - // parseExpression stops before '\\right' - const body = parser.parseExpression(false); - --parser.leftrightDepth; - // Check the next token - parser.expect("\\right", false); - const right = assertNodeType(parser.parseFunction(), "leftright-right"); - return { - type: "leftright", - mode: parser.mode, - body, - left: delim.text, - right: right.delim, - rightColor: right.color - }; - }, - mathmlBuilder: (group, style) => { - assertParsed(group); - const inner = mml.buildExpression(group.body, style); - - if (group.left === ".") { group.left = "" } - const leftNode = new mathMLTree.MathNode("mo", [mml.makeText(group.left, group.mode)]); - leftNode.setAttribute("fence", "true") - leftNode.setAttribute("form", "prefix") - if (group.left === "\u2216") { leftNode.setAttribute("stretchy", "true") } - inner.unshift(leftNode) - - if (group.right === ".") { group.right = "" } - const rightNode = new mathMLTree.MathNode("mo", [mml.makeText(group.right, group.mode)]); - rightNode.setAttribute("fence", "true") - rightNode.setAttribute("form", "postfix") - if (group.right === "\u2216") { rightNode.setAttribute("stretchy", "true") } - if (group.rightColor) { rightNode.setAttribute("mathcolor", group.rightColor) } - inner.push(rightNode) - - return mml.makeRow(inner); - } -}); - -defineFunction({ - type: "middle", - names: ["\\middle"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - if (!context.parser.leftrightDepth) { - throw new ParseError("\\middle without preceding \\left", delim); - } - - return { - type: "middle", - mode: context.parser.mode, - delim: delim.text - }; - }, - mathmlBuilder: (group, style) => { - const textNode = mml.makeText(group.delim, group.mode); - const middleNode = new mathMLTree.MathNode("mo", [textNode]); - middleNode.setAttribute("fence", "true"); - // MathML gives 5/18em spacing to each element. - // \middle should get delimiter spacing instead. - middleNode.setAttribute("lspace", "0.05em"); - middleNode.setAttribute("rspace", "0.05em"); - return middleNode; - } -}); diff --git a/src/functions/enclose.js b/src/functions/enclose.js deleted file mode 100644 index 8816f951..00000000 --- a/src/functions/enclose.js +++ /dev/null @@ -1,158 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import { assertNodeType } from "../parseNode"; -import { colorFromSpec, validateColor } from "./color" -import * as mml from "../buildMathML"; - -const mathmlBuilder = (group, style) => { - const node = new mathMLTree.MathNode( - group.label.indexOf("colorbox") > -1 ? "mpadded" : "menclose", - [mml.buildGroup(group.body, style)] - ); - switch (group.label) { - case "\\cancel": - node.setAttribute("notation", "updiagonalstrike"); - break; - case "\\bcancel": - node.setAttribute("notation", "downdiagonalstrike"); - break; - case "\\longdiv": - node.setAttribute("notation", "longdiv"); - break; - case "\\phase": - node.setAttribute("notation", "phasorangle"); - break; - case "\\sout": - node.setAttribute("notation", "horizontalstrike"); - break; - case "\\fbox": - node.setAttribute("notation", "box"); - break; - case "\\angl": - node.setAttribute("notation", "actuarial"); - break; - case "\\fcolorbox": - case "\\colorbox": { - // doesn't have a good notation option for \colorbox. - // So use instead. Set some attributes that come - // included with . - const fboxsep = 3; // 3 pt from LaTeX source2e - node.setAttribute("width", `+${2 * fboxsep}pt`); - node.setAttribute("height", `+${2 * fboxsep}pt`); - node.setAttribute("lspace", `${fboxsep}pt`); // - node.setAttribute("voffset", `${fboxsep}pt`); - if (group.label === "\\fcolorbox") { - node.setAttribute("style", "border: 0.06em solid " + String(group.borderColor)); - } - break; - } - case "\\xcancel": - node.setAttribute("notation", "updiagonalstrike downdiagonalstrike"); - break; - } - if (group.backgroundColor) { - node.setAttribute("mathbackground", group.backgroundColor); - } - return node; -}; - -defineFunction({ - type: "enclose", - names: ["\\colorbox"], - props: { - numArgs: 2, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "text"] - }, - handler({ parser, funcName }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string - let color = "" - if (model) { - const spec = assertNodeType(args[0], "raw").string - color = colorFromSpec(model, spec) - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros) - } - const body = args[1]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - backgroundColor: color, - body - }; - }, - mathmlBuilder -}); - -defineFunction({ - type: "enclose", - names: ["\\fcolorbox"], - props: { - numArgs: 3, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "raw", "text"] - }, - handler({ parser, funcName }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string - let borderColor = "" - let backgroundColor - if (model) { - const borderSpec = assertNodeType(args[0], "raw").string - const backgroundSpec = assertNodeType(args[0], "raw").string - borderColor = colorFromSpec(model, borderSpec) - backgroundColor = colorFromSpec(model, backgroundSpec) - } else { - borderColor = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros) - backgroundColor = validateColor(assertNodeType(args[1], "raw").string, parser.gullet.macros) - } - const body = args[2]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - backgroundColor, - borderColor, - body - }; - }, - mathmlBuilder -}); - -defineFunction({ - type: "enclose", - names: ["\\fbox"], - props: { - numArgs: 1, - argTypes: ["hbox"], - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "enclose", - mode: parser.mode, - label: "\\fbox", - body: args[0] - }; - } -}); - -defineFunction({ - type: "enclose", - names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\angl", "\\phase", "\\longdiv"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - const body = args[0]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - body - }; - }, - mathmlBuilder -}); diff --git a/src/functions/envTag.js b/src/functions/envTag.js deleted file mode 100644 index 6a035ad0..00000000 --- a/src/functions/envTag.js +++ /dev/null @@ -1,38 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; - -defineFunction({ - type: "envTag", - names: ["\\env@tag"], - props: { - numArgs: 1, - argTypes: ["math"] - }, - handler({ parser }, args) { - return { - type: "envTag", - mode: parser.mode, - body: args[0] - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow"); - } -}); - -defineFunction({ - type: "noTag", - names: ["\\env@notag"], - props: { - numArgs: 0 - }, - handler({ parser }) { - return { - type: "noTag", - mode: parser.mode - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow"); - } -}); diff --git a/src/functions/environment.js b/src/functions/environment.js deleted file mode 100644 index ced5acd0..00000000 --- a/src/functions/environment.js +++ /dev/null @@ -1,59 +0,0 @@ -import defineFunction from "../defineFunction"; -import ParseError from "../ParseError"; -import { assertNodeType } from "../parseNode"; -import environments from "../environments"; - -// Environment delimiters. HTML/MathML rendering is defined in the corresponding -// defineEnvironment definitions. -defineFunction({ - type: "environment", - names: ["\\begin", "\\end"], - props: { - numArgs: 1, - argTypes: ["text"] - }, - handler({ parser, funcName }, args) { - const nameGroup = args[0]; - if (nameGroup.type !== "ordgroup") { - throw new ParseError("Invalid environment name", nameGroup); - } - let envName = ""; - for (let i = 0; i < nameGroup.body.length; ++i) { - envName += assertNodeType(nameGroup.body[i], "textord").text; - } - - if (funcName === "\\begin") { - // begin...end is similar to left...right - if (!Object.prototype.hasOwnProperty.call(environments, envName )) { - throw new ParseError("No such environment: " + envName, nameGroup); - } - // Build the environment object. Arguments and other information will - // be made available to the begin and end methods using properties. - const env = environments[envName]; - const { args, optArgs } = parser.parseArguments("\\begin{" + envName + "}", env); - const context = { - mode: parser.mode, - envName, - parser - }; - const result = env.handler(context, args, optArgs); - parser.expect("\\end", false); - const endNameToken = parser.nextToken; - const end = assertNodeType(parser.parseFunction(), "environment"); - if (end.name !== envName) { - throw new ParseError( - `Mismatch: \\begin{${envName}} matched by \\end{${end.name}}`, - endNameToken - ); - } - return result; - } - - return { - type: "environment", - mode: parser.mode, - name: envName, - nameGroup - }; - } -}); diff --git a/src/functions/font.js b/src/functions/font.js deleted file mode 100644 index bd984261..00000000 --- a/src/functions/font.js +++ /dev/null @@ -1,123 +0,0 @@ -import defineFunction, { normalizeArgument } from "../defineFunction" -import * as mml from "../buildMathML" -import mathMLTree from "../mathMLTree" - -const mathmlBuilder = (group, style) => { - const font = group.font - const newStyle = style.withFont(font) - const mathGroup = mml.buildGroup(group.body, newStyle) - - if (mathGroup.children.length === 0) { return mathGroup } // empty group, e.g., \mathrm{} - if (font === "boldsymbol" && ["mo", "mpadded"].includes(mathGroup.type)) { - mathGroup.style.fontWeight = "bold" - return mathGroup - } - // Check if it is possible to consolidate elements into a single element. - let canConsolidate = mathGroup.children[0].type === "mo" - for (let i = 1; i < mathGroup.children.length; i++) { - if (mathGroup.children[i].type === "mo" && font === "boldsymbol") { - mathGroup.children[i].style.fontWeight = "bold" - } - if (mathGroup.children[i].type !== "mi") { canConsolidate = false } - const localVariant = mathGroup.children[i].attributes && - mathGroup.children[i].attributes.mathvariant || "" - if (localVariant !== "normal") { canConsolidate = false } - } - if (!canConsolidate) { return mathGroup } - // Consolidate the elements. - const mi = mathGroup.children[0] - for (let i = 1; i < mathGroup.children.length; i++) { - mi.children.push(mathGroup.children[i].children[0]) - } - if (mathGroup.attributes.mathcolor) { mi.attributes.mathcolor = mathGroup.attributes.mathcolor } - if (mi.attributes.mathvariant && mi.attributes.mathvariant === "normal") { - // Workaround for a Firefox bug that renders spurious space around - // a - // Ref: https://bugs.webkit.org/show_bug.cgi?id=129097 - // We insert a text node that contains a zero-width space and wrap in an mrow. - // TODO: Get rid of this workaround when the Firefox bug is fixed. - const bogus = new mathMLTree.MathNode("mtext", new mathMLTree.TextNode("\u200b")) - return new mathMLTree.MathNode("mrow", [bogus, mi]) - } - return mi -}; - -const fontAliases = { - "\\Bbb": "\\mathbb", - "\\bold": "\\mathbf", - "\\frak": "\\mathfrak", - "\\bm": "\\boldsymbol" -}; - -defineFunction({ - type: "font", - names: [ - // styles - "\\mathrm", - "\\mathit", - "\\mathbf", - "\\mathnormal", - "\\up@greek", - "\\boldsymbol", - - // families - "\\mathbb", - "\\mathcal", - "\\mathfrak", - "\\mathscr", - "\\mathsf", - "\\mathtt", - "\\oldstylenums", - - // aliases - "\\Bbb", - "\\bm", - "\\bold", - "\\frak" - ], - props: { - numArgs: 1, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const body = normalizeArgument(args[0]); - let func = funcName; - if (func in fontAliases) { - func = fontAliases[func]; - } - return { - type: "font", - mode: parser.mode, - font: func.slice(1), - body - }; - }, - mathmlBuilder -}); - -// Old font changing functions -defineFunction({ - type: "font", - names: ["\\rm", "\\sf", "\\tt", "\\bf", "\\it", "\\cal"], - props: { - numArgs: 0, - allowedInText: true - }, - handler: ({ parser, funcName, breakOnTokenText }, args) => { - const { mode } = parser; - const body = parser.parseExpression(true, breakOnTokenText); - const fontStyle = `math${funcName.slice(1)}`; - - return { - type: "font", - mode: mode, - font: fontStyle, - body: { - type: "ordgroup", - mode: parser.mode, - body - } - }; - }, - mathmlBuilder -}); diff --git a/src/functions/genfrac.js b/src/functions/genfrac.js deleted file mode 100644 index 37dd41d3..00000000 --- a/src/functions/genfrac.js +++ /dev/null @@ -1,333 +0,0 @@ -import defineFunction, { normalizeArgument } from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import { StyleLevel } from "../constants" -import { assertNodeType } from "../parseNode"; -import { assert } from "../utils"; -import * as mml from "../buildMathML"; -import { calculateSize } from "../units"; - -const stylArray = ["display", "text", "script", "scriptscript"]; -const scriptLevel = { auto: -1, display: 0, text: 0, script: 1, scriptscript: 2 }; - -const mathmlBuilder = (group, style) => { - // Track the scriptLevel of the numerator and denominator. - // We may need that info for \mathchoice or for adjusting em dimensions. - const childOptions = group.scriptLevel === "auto" - ? style.incrementLevel() - : group.scriptLevel === "display" - ? style.withLevel(StyleLevel.TEXT) - : group.scriptLevel === "text" - ? style.withLevel(StyleLevel.SCRIPT) - : style.withLevel(StyleLevel.SCRIPTSCRIPT); - - let node = new mathMLTree.MathNode("mfrac", [ - mml.buildGroup(group.numer, childOptions), - mml.buildGroup(group.denom, childOptions) - ]); - - if (!group.hasBarLine) { - node.setAttribute("linethickness", "0px"); - } else if (group.barSize) { - const ruleWidth = calculateSize(group.barSize, style); - node.setAttribute("linethickness", ruleWidth.number + ruleWidth.unit); - } - - if (group.leftDelim != null || group.rightDelim != null) { - const withDelims = []; - - if (group.leftDelim != null) { - const leftOp = new mathMLTree.MathNode("mo", [ - new mathMLTree.TextNode(group.leftDelim.replace("\\", "")) - ]); - leftOp.setAttribute("fence", "true"); - withDelims.push(leftOp); - } - - withDelims.push(node); - - if (group.rightDelim != null) { - const rightOp = new mathMLTree.MathNode("mo", [ - new mathMLTree.TextNode(group.rightDelim.replace("\\", "")) - ]); - rightOp.setAttribute("fence", "true"); - withDelims.push(rightOp); - } - - node = mml.makeRow(withDelims); - } - - if (group.scriptLevel !== "auto") { - node = new mathMLTree.MathNode("mstyle", [node]); - node.setAttribute("displaystyle", String(group.scriptLevel === "display")); - node.setAttribute("scriptlevel", scriptLevel[group.scriptLevel]); - } - - return node; -}; - -defineFunction({ - type: "genfrac", - names: [ - "\\dfrac", - "\\frac", - "\\tfrac", - "\\dbinom", - "\\binom", - "\\tbinom", - "\\\\atopfrac", // can’t be entered directly - "\\\\bracefrac", - "\\\\brackfrac" // ditto - ], - props: { - numArgs: 2, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const denom = args[1]; - let hasBarLine = false; - let leftDelim = null; - let rightDelim = null; - let scriptLevel = "auto"; - - switch (funcName) { - case "\\dfrac": - case "\\frac": - case "\\tfrac": - hasBarLine = true; - break; - case "\\\\atopfrac": - hasBarLine = false; - break; - case "\\dbinom": - case "\\binom": - case "\\tbinom": - leftDelim = "("; - rightDelim = ")"; - break; - case "\\\\bracefrac": - leftDelim = "\\{"; - rightDelim = "\\}"; - break; - case "\\\\brackfrac": - leftDelim = "["; - rightDelim = "]"; - break; - default: - throw new Error("Unrecognized genfrac command"); - } - - switch (funcName) { - case "\\dfrac": - case "\\dbinom": - scriptLevel = "display"; - break; - case "\\tfrac": - case "\\tbinom": - scriptLevel = "text"; - break; - } - - return { - type: "genfrac", - mode: parser.mode, - continued: false, - numer, - denom, - hasBarLine, - leftDelim, - rightDelim, - scriptLevel, - barSize: null - }; - }, - mathmlBuilder -}); - -defineFunction({ - type: "genfrac", - names: ["\\cfrac"], - props: { - numArgs: 2 - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const denom = args[1]; - - return { - type: "genfrac", - mode: parser.mode, - continued: true, - numer, - denom, - hasBarLine: true, - leftDelim: null, - rightDelim: null, - scriptLevel: "display", - barSize: null - }; - } -}); - -// Infix generalized fractions -- these are not rendered directly, but replaced -// immediately by one of the variants above. -defineFunction({ - type: "infix", - names: ["\\over", "\\choose", "\\atop", "\\brace", "\\brack"], - props: { - numArgs: 0, - infix: true - }, - handler({ parser, funcName, token }) { - let replaceWith; - switch (funcName) { - case "\\over": - replaceWith = "\\frac"; - break; - case "\\choose": - replaceWith = "\\binom"; - break; - case "\\atop": - replaceWith = "\\\\atopfrac"; - break; - case "\\brace": - replaceWith = "\\\\bracefrac"; - break; - case "\\brack": - replaceWith = "\\\\brackfrac"; - break; - default: - throw new Error("Unrecognized infix genfrac command"); - } - return { - type: "infix", - mode: parser.mode, - replaceWith, - token - }; - } -}); - -const delimFromValue = function(delimString) { - let delim = null; - if (delimString.length > 0) { - delim = delimString; - delim = delim === "." ? null : delim; - } - return delim; -}; - -defineFunction({ - type: "genfrac", - names: ["\\genfrac"], - props: { - numArgs: 6, - allowedInArgument: true, - argTypes: ["math", "math", "size", "text", "math", "math"] - }, - handler({ parser }, args) { - const numer = args[4]; - const denom = args[5]; - - // Look into the parse nodes to get the desired delimiters. - const leftNode = normalizeArgument(args[0]); - const leftDelim = leftNode.type === "atom" && leftNode.family === "open" - ? delimFromValue(leftNode.text) - : null; - const rightNode = normalizeArgument(args[1]); - const rightDelim = - rightNode.type === "atom" && rightNode.family === "close" - ? delimFromValue(rightNode.text) - : null; - - const barNode = assertNodeType(args[2], "size"); - let hasBarLine; - let barSize = null; - if (barNode.isBlank) { - // \genfrac acts differently than \above. - // \genfrac treats an empty size group as a signal to use a - // standard bar size. \above would see size = 0 and omit the bar. - hasBarLine = true; - } else { - barSize = barNode.value; - hasBarLine = barSize.number > 0; - } - - // Find out if we want displaystyle, textstyle, etc. - let scriptLevel = "auto"; - let styl = args[3]; - if (styl.type === "ordgroup") { - if (styl.body.length > 0) { - const textOrd = assertNodeType(styl.body[0], "textord"); - scriptLevel = stylArray[Number(textOrd.text)]; - } - } else { - styl = assertNodeType(styl, "textord"); - scriptLevel = stylArray[Number(styl.text)]; - } - - return { - type: "genfrac", - mode: parser.mode, - numer, - denom, - continued: false, - hasBarLine, - barSize, - leftDelim, - rightDelim, - scriptLevel - }; - }, - mathmlBuilder -}); - -// \above is an infix fraction that also defines a fraction bar size. -defineFunction({ - type: "infix", - names: ["\\above"], - props: { - numArgs: 1, - argTypes: ["size"], - infix: true - }, - handler({ parser, funcName, token }, args) { - return { - type: "infix", - mode: parser.mode, - replaceWith: "\\\\abovefrac", - barSize: assertNodeType(args[0], "size").value, - token - }; - } -}); - -defineFunction({ - type: "genfrac", - names: ["\\\\abovefrac"], - props: { - numArgs: 3, - argTypes: ["math", "size", "math"] - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const barSize = assert(assertNodeType(args[1], "infix").barSize); - const denom = args[2]; - - const hasBarLine = barSize.number > 0; - return { - type: "genfrac", - mode: parser.mode, - numer, - denom, - continued: false, - hasBarLine, - barSize, - leftDelim: null, - rightDelim: null, - scriptLevel: "auto" - }; - }, - - mathmlBuilder -}); diff --git a/src/functions/hbox.js b/src/functions/hbox.js deleted file mode 100644 index e871d38b..00000000 --- a/src/functions/hbox.js +++ /dev/null @@ -1,29 +0,0 @@ -import defineFunction, { ordargument } from "../defineFunction"; -import { StyleLevel } from "../constants" -import mathMLTree from "../mathMLTree"; -import * as mml from "../buildMathML"; - -// \hbox is provided for compatibility with LaTeX functions that act on a box. -// This function by itself doesn't do anything but prevent a soft line break. - -defineFunction({ - type: "hbox", - names: ["\\hbox"], - props: { - numArgs: 1, - argTypes: ["hbox"], - allowedInArgument: true, - allowedInText: false - }, - handler({ parser }, args) { - return { - type: "hbox", - mode: parser.mode, - body: ordargument(args[0]) - }; - }, - mathmlBuilder(group, style) { - const newOptions = style.withLevel(StyleLevel.TEXT) - return new mathMLTree.MathNode("mrow", mml.buildExpression(group.body, newOptions)); - } -}); diff --git a/src/functions/horizBrace.js b/src/functions/horizBrace.js deleted file mode 100644 index 554021cb..00000000 --- a/src/functions/horizBrace.js +++ /dev/null @@ -1,31 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import stretchy from "../stretchy"; -import * as mml from "../buildMathML"; - -const mathmlBuilder = (group, style) => { - const accentNode = stretchy.mathMLnode(group.label); - return new mathMLTree.MathNode(group.isOver ? "mover" : "munder", [ - mml.buildGroup(group.base, style), - accentNode - ]); -}; - -// Horizontal stretchy braces -defineFunction({ - type: "horizBrace", - names: ["\\overbrace", "\\underbrace"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - return { - type: "horizBrace", - mode: parser.mode, - label: funcName, - isOver: /^\\over/.test(funcName), - base: args[0] - }; - }, - mathmlBuilder -}); diff --git a/src/functions/href.js b/src/functions/href.js deleted file mode 100644 index 7c35d50c..00000000 --- a/src/functions/href.js +++ /dev/null @@ -1,90 +0,0 @@ -import defineFunction, { ordargument } from "../defineFunction"; -import { assertNodeType } from "../parseNode"; -import { MathNode } from "../mathMLTree"; -import * as mml from "../buildMathML"; -import ParseError from "../ParseError"; - -defineFunction({ - type: "href", - names: ["\\href"], - props: { - numArgs: 2, - argTypes: ["url", "original"], - allowedInText: true - }, - handler: ({ parser, token }, args) => { - const body = args[1]; - const href = assertNodeType(args[0], "url").url; - - if ( - !parser.settings.isTrusted({ - command: "\\href", - url: href - }) - ) { - throw new ParseError(`Function "\\href" is not trusted`, token) - } - - return { - type: "href", - mode: parser.mode, - href, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - let math = mml.buildExpressionRow(group.body, style); - if (!(math instanceof MathNode)) { - math = new MathNode("mrow", [math]); - } - math.setAttribute("href", group.href); - return math; - } -}); - -defineFunction({ - type: "href", - names: ["\\url"], - props: { - numArgs: 1, - argTypes: ["url"], - allowedInText: true - }, - handler: ({ parser, token }, args) => { - const href = assertNodeType(args[0], "url").url; - - if ( - !parser.settings.isTrusted({ - command: "\\url", - url: href - }) - ) { - throw new ParseError(`Function "\\url" is not trusted`, token) - } - - const chars = []; - for (let i = 0; i < href.length; i++) { - let c = href[i]; - if (c === "~") { - c = "\\textasciitilde"; - } - chars.push({ - type: "textord", - mode: "text", - text: c - }); - } - const body = { - type: "text", - mode: parser.mode, - font: "\\texttt", - body: chars - }; - return { - type: "href", - mode: parser.mode, - href, - body: ordargument(body) - }; - } -}); diff --git a/src/functions/html.js b/src/functions/html.js deleted file mode 100644 index 4b4124ba..00000000 --- a/src/functions/html.js +++ /dev/null @@ -1,95 +0,0 @@ -import defineFunction, { ordargument } from "../defineFunction"; -import { assertNodeType } from "../parseNode"; -import ParseError from "../ParseError"; - -import * as mml from "../buildMathML"; - -defineFunction({ - type: "html", - names: ["\\class", "\\id", "\\style", "\\data"], - props: { - numArgs: 2, - argTypes: ["raw", "original"], - allowedInText: true - }, - handler: ({ parser, funcName, token }, args) => { - const value = assertNodeType(args[0], "raw").string; - const body = args[1]; - - if (parser.settings.strict) { - throw new ParseError(`Function "${funcName}" is disabled in strict mode`, token) - } - - let trustContext; - const attributes = {}; - - switch (funcName) { - case "\\class": - attributes.class = value; - trustContext = { - command: "\\class", - class: value - }; - break; - case "\\id": - attributes.id = value; - trustContext = { - command: "\\id", - id: value - }; - break; - case "\\style": - attributes.style = value; - trustContext = { - command: "\\style", - style: value - }; - break; - case "\\data": { - const data = value.split(","); - for (let i = 0; i < data.length; i++) { - const keyVal = data[i].split("="); - if (keyVal.length !== 2) { - throw new ParseError("Error parsing key-value for \\data"); - } - attributes["data-" + keyVal[0].trim()] = keyVal[1].trim(); - } - - trustContext = { - command: "\\data", - attributes - }; - break; - } - default: - throw new Error("Unrecognized html command"); - } - - if (!parser.settings.isTrusted(trustContext)) { - throw new ParseError(`Function "${funcName}" is not trusted`, token) - } - return { - type: "html", - mode: parser.mode, - attributes, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - const element = mml.buildExpressionRow(group.body, style); - - const classes = []; - if (group.attributes.class) { - classes.push(...group.attributes.class.trim().split(/\s+/)); - } - element.classes = classes; - - for (const attr in group.attributes) { - if (attr !== "class" && Object.prototype.hasOwnProperty.call(group.attributes, attr)) { - element.setAttribute(attr, group.attributes[attr]); - } - } - - return element; - } -}); diff --git a/src/functions/includegraphics.js b/src/functions/includegraphics.js deleted file mode 100644 index 574b53e1..00000000 --- a/src/functions/includegraphics.js +++ /dev/null @@ -1,131 +0,0 @@ -import defineFunction from "../defineFunction" -import { calculateSize, validUnit } from "../units" -import ParseError from "../ParseError" -import { Img } from "../domTree" -import mathMLTree from "../mathMLTree" -import { assertNodeType } from "../parseNode" - -const sizeData = function(str) { - if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(str)) { - // str is a number with no unit specified. - // default unit is bp, per graphix package. - return { number: +str, unit: "bp" } - } else { - const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(str); - if (!match) { - throw new ParseError("Invalid size: '" + str + "' in \\includegraphics"); - } - const data = { - number: +(match[1] + match[2]), // sign + magnitude, cast to number - unit: match[3] - } - if (!validUnit(data)) { - throw new ParseError("Invalid unit: '" + data.unit + "' in \\includegraphics."); - } - return data - } -} - -defineFunction({ - type: "includegraphics", - names: ["\\includegraphics"], - props: { - numArgs: 1, - numOptionalArgs: 1, - argTypes: ["raw", "url"], - allowedInText: false - }, - handler: ({ parser, token }, args, optArgs) => { - let width = { number: 0, unit: "em" } - let height = { number: 0.9, unit: "em" } // sorta character sized. - let totalheight = { number: 0, unit: "em" } - let alt = "" - - if (optArgs[0]) { - const attributeStr = assertNodeType(optArgs[0], "raw").string - - // Parser.js does not parse key/value pairs. We get a string. - const attributes = attributeStr.split(",") - for (let i = 0; i < attributes.length; i++) { - const keyVal = attributes[i].split("=") - if (keyVal.length === 2) { - const str = keyVal[1].trim() - switch (keyVal[0].trim()) { - case "alt": - alt = str - break - case "width": - width = sizeData(str) - break - case "height": - height = sizeData(str) - break - case "totalheight": - totalheight = sizeData(str) - break - default: - throw new ParseError("Invalid key: '" + keyVal[0] + "' in \\includegraphics.") - } - } - } - } - - const src = assertNodeType(args[0], "url").url - - if (alt === "") { - // No alt given. Use the file name. Strip away the path. - alt = src - alt = alt.replace(/^.*[\\/]/, "") - alt = alt.substring(0, alt.lastIndexOf(".")) - } - - if ( - !parser.settings.isTrusted({ - command: "\\includegraphics", - url: src - }) - ) { - throw new ParseError(`Function "\\includegraphics" is not trusted`, token) - } - - return { - type: "includegraphics", - mode: parser.mode, - alt: alt, - width: width, - height: height, - totalheight: totalheight, - src: src - } - }, - mathmlBuilder: (group, style) => { - const height = calculateSize(group.height, style) - const depth = { number: 0, unit: "em" } - - if (group.totalheight.number > 0) { - if (group.totalheight.unit === height.unit && - group.totalheight.number > height.number) { - depth.number = group.totalheight.number - height.number - depth.unit = height.unit - } - } - - let width = 0 - if (group.width.number > 0) { - width = calculateSize(group.width, style) - } - - const graphicStyle = { height: height.number + depth.number + "em" } - if (width.number > 0) { - graphicStyle.width = width.number + width.unit - } - if (depth.number > 0) { - graphicStyle.verticalAlign = -depth.number + depth.unit - } - - const node = new Img(group.src, group.alt, graphicStyle) - node.height = height - node.depth = depth - return new mathMLTree.MathNode("mtext", [node]) - } -}) diff --git a/src/functions/kern.js b/src/functions/kern.js deleted file mode 100644 index f67075f5..00000000 --- a/src/functions/kern.js +++ /dev/null @@ -1,72 +0,0 @@ -// Horizontal spacing commands - -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import { calculateSize } from "../units"; -import { assertNodeType } from "../parseNode"; -import ParseError from "../ParseError" - -// TODO: \hskip and \mskip should support plus and minus in lengths - -defineFunction({ - type: "kern", - names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"], - props: { - numArgs: 1, - argTypes: ["size"], - primitive: true, - allowedInText: true - }, - handler({ parser, funcName, token }, args) { - const size = assertNodeType(args[0], "size"); - if (parser.settings.strict) { - const mathFunction = funcName[1] === "m"; // \mkern, \mskip - const muUnit = size.value.unit === "mu"; - if (mathFunction) { - if (!muUnit) { - throw new ParseError(`LaTeX's ${funcName} supports only mu units, ` + - `not ${size.value.unit} units`, token) - } - if (parser.mode !== "math") { - throw new ParseError(`LaTeX's ${funcName} works only in math mode`, token) - } - } else { - // !mathFunction - if (muUnit) { - throw new ParseError(`LaTeX's ${funcName} doesn't support mu units`, token) - } - } - } - return { - type: "kern", - mode: parser.mode, - dimension: size.value - }; - }, - mathmlBuilder(group, style) { - const dimension = calculateSize(group.dimension, style); - const ch = dimension.unit === "em" ? spaceCharacter(dimension.number) : ""; - if (group.mode === "text" && ch.length > 0) { - const character = new mathMLTree.TextNode(ch); - return new mathMLTree.MathNode("mtext", [character]); - } else { - const node = new mathMLTree.MathNode("mspace"); - node.setAttribute("width", dimension.number + dimension.unit); - return node; - } - } -}); - -export const spaceCharacter = function(width) { - if (width >= 0.05555 && width <= 0.05556) { - return "\u200a"; //   - } else if (width >= 0.1666 && width <= 0.1667) { - return "\u2009"; //   - } else if (width >= 0.2222 && width <= 0.2223) { - return "\u2005"; //   - } else if (width >= 0.2777 && width <= 0.2778) { - return "\u2005\u200a"; //    - } else { - return ""; - } -}; diff --git a/src/functions/label.js b/src/functions/label.js deleted file mode 100644 index 458cabee..00000000 --- a/src/functions/label.js +++ /dev/null @@ -1,29 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; - -// Limit valid characters to a small set, for safety. -export const invalidIdRegEx = /[^A-Za-z_0-9-]/g - -defineFunction({ - type: "label", - names: ["\\label"], - props: { - numArgs: 1, - argTypes: ["raw"] - }, - handler({ parser }, args) { - return { - type: "label", - mode: parser.mode, - string: args[0].string.replace(invalidIdRegEx, "") - }; - }, - mathmlBuilder(group, style) { - // Return a no-width, no-ink element with an HTML id. - const node = new mathMLTree.MathNode("mrow", [], ["tml-label"]) - if (group.string.length > 0) { - node.setAttribute("id", group.string) - } - return node - } -}); diff --git a/src/functions/lap.js b/src/functions/lap.js deleted file mode 100644 index db0133d9..00000000 --- a/src/functions/lap.js +++ /dev/null @@ -1,50 +0,0 @@ -// Horizontal overlap functions -import defineFunction from "../defineFunction" -import mathMLTree from "../mathMLTree" -import * as mml from "../buildMathML" -import ParseError from "../ParseError"; - -const textModeLap = ["\\clap", "\\llap", "\\rlap"] - -defineFunction({ - type: "lap", - names: ["\\mathllap", "\\mathrlap", "\\mathclap", "\\clap", "\\llap", "\\rlap"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser, funcName, token }, args) => { - if (textModeLap.includes(funcName)) { - if (parser.settings.strict && parser.mode !== "text") { - throw new ParseError(`{${funcName}} can be used only in text mode. - Try \\math${funcName.slice(1)}`, token) - } - funcName = funcName.slice(1) - } else { - funcName = funcName.slice(5) - } - const body = args[0] - return { - type: "lap", - mode: parser.mode, - alignment: funcName, - body - } - }, - mathmlBuilder: (group, style) => { - // mathllap, mathrlap, mathclap - const node = new mathMLTree.MathNode("mpadded", [mml.buildGroup(group.body, style)]) - - if (group.alignment === "rlap") { - if (group.body.body.length > 0 && group.body.body[0].type === "genfrac") { - // In Firefox, a squashes the 3/18em padding of a child \frac. Put it back. - node.setAttribute("lspace", "0.16667em") - } - } else { - const offset = group.alignment === "llap" ? "-1" : "-0.5" - node.setAttribute("lspace", offset + "width") - } - node.setAttribute("width", "0px") - return node - } -}) diff --git a/src/functions/math.js b/src/functions/math.js deleted file mode 100644 index 0f036018..00000000 --- a/src/functions/math.js +++ /dev/null @@ -1,40 +0,0 @@ -import defineFunction from "../defineFunction"; -import ParseError from "../ParseError"; - -// Switching from text mode back to math mode -defineFunction({ - type: "ordgroup", - names: ["\\(", "$"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: false - }, - handler({ funcName, parser }, args) { - const outerMode = parser.mode; - parser.switchMode("math"); - const close = funcName === "\\(" ? "\\)" : "$"; - const body = parser.parseExpression(false, close); - parser.expect(close); - parser.switchMode(outerMode); - return { - type: "ordgroup", - mode: parser.mode, - body - }; - } -}); - -// Check for extra closing math delimiters -defineFunction({ - type: "text", // Doesn't matter what this is. - names: ["\\)", "\\]"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: false - }, - handler(context, token) { - throw new ParseError(`Mismatched ${context.funcName}`, token); - } -}); diff --git a/src/functions/mathchoice.js b/src/functions/mathchoice.js deleted file mode 100644 index 1bb2390b..00000000 --- a/src/functions/mathchoice.js +++ /dev/null @@ -1,41 +0,0 @@ -import defineFunction, { ordargument } from "../defineFunction"; -import { StyleLevel } from "../constants"; -import * as mml from "../buildMathML"; - -const chooseStyle = (group, style) => { - switch (style.level) { - case StyleLevel.DISPLAY: // 0 - return group.display; - case StyleLevel.TEXT: // 1 - return group.text; - case StyleLevel.SCRIPT: // 2 - return group.script; - case StyleLevel.SCRIPTSCRIPT: // 3 - return group.scriptscript; - default: - return group.text; - } -}; - -defineFunction({ - type: "mathchoice", - names: ["\\mathchoice"], - props: { - numArgs: 4, - primitive: true - }, - handler: ({ parser }, args) => { - return { - type: "mathchoice", - mode: parser.mode, - display: ordargument(args[0]), - text: ordargument(args[1]), - script: ordargument(args[2]), - scriptscript: ordargument(args[3]) - }; - }, - mathmlBuilder: (group, style) => { - const body = chooseStyle(group, style); - return mml.buildExpressionRow(body, style); - } -}); diff --git a/src/functions/mclass.js b/src/functions/mclass.js deleted file mode 100644 index 5ff0dc36..00000000 --- a/src/functions/mclass.js +++ /dev/null @@ -1,174 +0,0 @@ -import defineFunction, { ordargument } from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import utils from "../utils"; - -import * as mml from "../buildMathML"; - -const textAtomTypes = ["text", "textord", "mathord", "atom"] - -function mathmlBuilder(group, style) { - let node; - const inner = mml.buildExpression(group.body, style); - - if (group.mclass === "minner") { - node = new mathMLTree.MathNode("mpadded", inner) - } else if (group.mclass === "mord") { - if (group.isCharacterBox || inner[0].type === "mathord") { - node = inner[0]; - node.type = "mi"; - } else { - node = new mathMLTree.MathNode("mi", inner); - } - } else { - if (group.mustPromote) { - node = inner[0]; - node.type = "mo"; - if (group.isCharacterBox && group.body[0].text && /[A-Za-z]/.test(group.body[0].text)) { - node.setAttribute("mathvariant", "italic") - } - } else { - node = new mathMLTree.MathNode("mo", inner); - } - - // Set spacing based on what is the most likely adjacent atom type. - // See TeXbook p170. - const doSpacing = style.level < 2 // Operator spacing is zero inside a (sub|super)script. - if (group.mclass === "mbin") { - // medium space - node.attributes.lspace = (doSpacing ? "0.2222em" : "0") - node.attributes.rspace = (doSpacing ? "0.2222em" : "0") - } else if (group.mclass === "mrel") { - // thickspace - node.attributes.lspace = (doSpacing ? "0.2778em" : "0") - node.attributes.rspace = (doSpacing ? "0.2778em" : "0") - } else if (group.mclass === "mpunct") { - node.attributes.lspace = "0em"; - node.attributes.rspace = (doSpacing ? "0.1667em" : "0") - } else if (group.mclass === "mopen" || group.mclass === "mclose") { - node.attributes.lspace = "0em" - node.attributes.rspace = "0em" - } else if (group.mclass === "minner" && doSpacing) { - node.attributes.lspace = "0.0556em" // 1 mu is the most likely option - node.attributes.width = "+0.1111em" - } - if (!(group.mclass === "mopen" || group.mclass === "mclose")) { - delete node.attributes.stretchy - delete node.attributes.form - } - } - return node; -} - -// Math class commands except \mathop -defineFunction({ - type: "mclass", - names: [ - "\\mathord", - "\\mathbin", - "\\mathrel", - "\\mathopen", - "\\mathclose", - "\\mathpunct", - "\\mathinner" - ], - props: { - numArgs: 1, - primitive: true - }, - handler({ parser, funcName }, args) { - const body = args[0] - const isCharacterBox = utils.isCharacterBox(body) - // We should not wrap a around a or . That would be invalid MathML. - // In that case, we instead promote the text contents of the body to the parent. - let mustPromote = true - const mord = { type: "mathord", text: "", mode: parser.mode } - const arr = (body.body) ? body.body : [body]; - for (const arg of arr) { - if (textAtomTypes.includes(arg.type)) { - if (arg.text) { - mord.text += arg.text - } else if (arg.body) { - arg.body.map(e => { mord.text += e.text }) - } - } else { - mustPromote = false - break - } - } - return { - type: "mclass", - mode: parser.mode, - mclass: "m" + funcName.slice(5), - body: ordargument(mustPromote ? mord : body), - isCharacterBox, - mustPromote - }; - }, - mathmlBuilder -}); - -export const binrelClass = (arg) => { - // \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument. - // (by rendering separately and with {}s before and after, and measuring - // the change in spacing). We'll do roughly the same by detecting the - // atom type directly. - const atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg; - if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) { - return "m" + atom.family; - } else { - return "mord"; - } -}; - -// \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord. -// This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX. -defineFunction({ - type: "mclass", - names: ["\\@binrel"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "mclass", - mode: parser.mode, - mclass: binrelClass(args[0]), - body: ordargument(args[1]), - isCharacterBox: utils.isCharacterBox(args[1]) - }; - } -}); - -// Build a relation or stacked op by placing one symbol on top of another -defineFunction({ - type: "mclass", - names: ["\\stackrel", "\\overset", "\\underset"], - props: { - numArgs: 2 - }, - handler({ parser, funcName }, args) { - const baseArg = args[1]; - const shiftedArg = args[0]; - - const baseOp = { - type: "op", - mode: baseArg.mode, - limits: true, - alwaysHandleSupSub: true, - parentIsSupSub: false, - symbol: false, - stack: true, - suppressBaseShift: funcName !== "\\stackrel", - body: ordargument(baseArg) - }; - - return { - type: "supsub", - mode: shiftedArg.mode, - base: baseOp, - sup: funcName === "\\underset" ? null : shiftedArg, - sub: funcName === "\\underset" ? shiftedArg : null - }; - }, - mathmlBuilder -}); diff --git a/src/functions/multiscript.js b/src/functions/multiscript.js deleted file mode 100644 index ce3da76e..00000000 --- a/src/functions/multiscript.js +++ /dev/null @@ -1,91 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import * as mml from "../buildMathML" -import ParseError from "../ParseError"; - -// Helper function -export const buildGroup = (el, style, noneNode) => { - if (!el) { return noneNode } - const node = mml.buildGroup(el, style) - if (node.type === "mrow" && node.children.length === 0) { return noneNode } - return node -} - -defineFunction({ - type: "multiscript", - names: ["\\sideset", "\\pres@cript"], // See macros.js for \prescript - props: { - numArgs: 3 - }, - handler({ parser, funcName, token }, args) { - if (args[2].body.length === 0) { - throw new ParseError(funcName + `cannot parse an empty base.`) - } - const base = args[2].body[0] - if (parser.settings.strict && funcName === "\\sideset" && !base.symbol) { - throw new ParseError(`The base of \\sideset must be a big operator. Try \\prescript.`) - } - - if ((args[0].body.length > 0 && args[0].body[0].type !== "supsub") || - (args[1].body.length > 0 && args[1].body[0].type !== "supsub")) { - throw new ParseError("\\sideset can parse only subscripts and " + - "superscripts in its first two arguments", token) - } - - // The prescripts and postscripts come wrapped in a supsub. - const prescripts = args[0].body.length > 0 ? args[0].body[0] : null - const postscripts = args[1].body.length > 0 ? args[1].body[0] : null - - if (!prescripts && !postscripts) { - return base - } else if (!prescripts) { - // It's not a multi-script. Get a \textstyle supsub. - return { - type: "styling", - mode: parser.mode, - scriptLevel: "text", - body: [{ - type: "supsub", - mode: parser.mode, - base, - sup: postscripts.sup, - sub: postscripts.sub - }] - } - } else { - return { - type: "multiscript", - mode: parser.mode, - isSideset: funcName === "\\sideset", - prescripts, - postscripts, - base - } - } - }, - mathmlBuilder(group, style) { - const base = mml.buildGroup(group.base, style) - - const prescriptsNode = new mathMLTree.MathNode("mprescripts") - const noneNode = new mathMLTree.MathNode("none") - let children = [] - - const preSub = buildGroup(group.prescripts.sub, style, noneNode) - const preSup = buildGroup(group.prescripts.sup, style, noneNode) - if (group.isSideset) { - // This seems silly, but LaTeX does this. Firefox ignores it, which does not make me sad. - preSub.setAttribute("style", "text-align: left;") - preSup.setAttribute("style", "text-align: left;") - } - - if (group.postscripts) { - const postSub = buildGroup(group.postscripts.sub, style, noneNode) - const postSup = buildGroup(group.postscripts.sup, style, noneNode) - children = [base, postSub, postSup, prescriptsNode, preSub, preSup] - } else { - children = [base, prescriptsNode, preSub, preSup] - } - - return new mathMLTree.MathNode("mmultiscripts", children); - } -}); diff --git a/src/functions/not.js b/src/functions/not.js deleted file mode 100644 index 32f8d3f9..00000000 --- a/src/functions/not.js +++ /dev/null @@ -1,46 +0,0 @@ -import defineFunction, { ordargument } from "../defineFunction"; -import symbols from "../symbols"; -import * as mml from "../buildMathML"; -import utils from "../utils" - -defineFunction({ - type: "not", - names: ["\\not"], - props: { - numArgs: 1, - primitive: true, - allowedInText: false - }, - handler({ parser }, args) { - const isCharacterBox = utils.isCharacterBox(args[0]) - let body - if (isCharacterBox) { - body = ordargument(args[0]) - if (body[0].text.charAt(0) === "\\") { - body[0].text = symbols.math[body[0].text].replace - } - // \u0338 is the Unicode Combining Long Solidus Overlay - body[0].text = body[0].text.slice(0, 1) + "\u0338" + body[0].text.slice(1) - } else { - // When the argument is not a character box, TeX does an awkward, poorly placed overlay. - // We'll do the same. - const notNode = { type: "textord", mode: "math", text: "\u0338" } - const kernNode = { type: "kern", mode: "math", dimension: { number: -0.6, unit: "em" } } - body = [notNode, kernNode, args[0]] - } - return { - type: "not", - mode: parser.mode, - body, - isCharacterBox - }; - }, - mathmlBuilder(group, style) { - if (group.isCharacterBox) { - const inner = mml.buildExpression(group.body, style); - return inner[0] - } else { - return mml.buildExpressionRow(group.body, style, true) - } - } -}); diff --git a/src/functions/op.js b/src/functions/op.js deleted file mode 100644 index 7b10eab9..00000000 --- a/src/functions/op.js +++ /dev/null @@ -1,335 +0,0 @@ -// Limits, symbols -import defineFunction, { ordargument } from "../defineFunction"; -import * as mathMLTree from "../mathMLTree"; -import * as mml from "../buildMathML"; -import utils from "../utils"; -import { delimiters, delimiterSizes } from "./delimsizing" - -// Some helpers - -const ordAtomTypes = ["textord", "mathord", "atom"] - -// Most operators have a large successor symbol, but these don't. -const noSuccessor = ["\\smallint"]; - -// Math operators (e.g. \sin) need a space between these types and themselves: -export const ordTypes = ["textord", "mathord", "ordgroup", "close", "leftright"]; - -const dels = ["}", "\\left", "\\middle", "\\right"] -const isDelimiter = str => str.length > 0 && - (delimiters.includes(str) || delimiterSizes[str] || dels.includes(str)) - -// NOTE: Unlike most `builders`s, this one handles not only "op", but also -// "supsub" since some of them (like \int) can affect super/subscripting. - -const mathmlBuilder = (group, style) => { - let node; - - if (group.symbol) { - // This is a symbol. Just add the symbol. - node = new mathMLTree.MathNode("mo", [mml.makeText(group.name, group.mode)]); - if (utils.contains(noSuccessor, group.name)) { - node.setAttribute("largeop", "false") - } else { - node.setAttribute("movablelimits", "false") - } - } else if (group.body) { - // This is an operator with children. Add them. - node = new mathMLTree.MathNode("mo", mml.buildExpression(group.body, style)); - } else { - // This is a text operator. Add all of the characters from the operator's name. - node = new mathMLTree.MathNode("mi", [new mathMLTree.TextNode(group.name.slice(1))]); - - if (!group.parentIsSupSub) { - // Append an invisible . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new mathMLTree.MathNode("mo", [mml.makeText("\u2061", "text")]); - node = new mathMLTree.MathNode("mpadded", [node, operator]) - const lSpace = group.needsLeadingSpace ? 0.1667 : 0 - const rSpace = group.isFollowedByDelimiter ? 0 : 0.1666 - if (group.needsLeadingSpace) { - node.setAttribute("lspace", "0.1667em") // thin space. - } - if ((lSpace + rSpace) > 0) { - node.setAttribute("width", `+${lSpace + rSpace}em`) - } - } - } - - return node; -}; - -const singleCharBigOps = { - "\u220F": "\\prod", - "\u2210": "\\coprod", - "\u2211": "\\sum", - "\u22c0": "\\bigwedge", - "\u22c1": "\\bigvee", - "\u22c2": "\\bigcap", - "\u22c3": "\\bigcup", - "\u2a00": "\\bigodot", - "\u2a01": "\\bigoplus", - "\u2a02": "\\bigotimes", - "\u2a04": "\\biguplus", - "\u2a05": "\\bigsqcap", - "\u2a06": "\\bigsqcup" -}; - -defineFunction({ - type: "op", - names: [ - "\\coprod", - "\\bigvee", - "\\bigwedge", - "\\biguplus", - "\\bigcap", - "\\bigcup", - "\\intop", - "\\prod", - "\\sum", - "\\bigotimes", - "\\bigoplus", - "\\bigodot", - "\\bigsqcap", - "\\bigsqcup", - "\\smallint", - "\u220F", - "\u2210", - "\u2211", - "\u22c0", - "\u22c1", - "\u22c2", - "\u22c3", - "\u2a00", - "\u2a01", - "\u2a02", - "\u2a04", - "\u2a06" - ], - props: { - numArgs: 0 - }, - handler: ({ parser, funcName }, args) => { - let fName = funcName; - if (fName.length === 1) { - fName = singleCharBigOps[fName]; - } - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: true, - stack: false, // This is true for \stackrel{}, not here. - name: fName - }; - }, - mathmlBuilder -}); - -// Note: calling defineFunction with a type that's already been defined only -// works because the same mathmlBuilder is being used. -defineFunction({ - type: "op", - names: ["\\mathop"], - props: { - numArgs: 1, - primitive: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - // It would be convienient to just wrap a around the argument. - // But if the argument is a or , that would be invalid MathML. - // In that case, we instead promote the text contents of the body to the parent. - const arr = (body.body) ? body.body : [body]; - const isSymbol = arr.length === 1 && ordAtomTypes.includes(arr[0].type) - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: isSymbol, - stack: false, - name: isSymbol ? arr[0].text : null, - body: isSymbol ? null : ordargument(body) - }; - }, - mathmlBuilder -}); - -// There are 2 flags for operators; whether they produce limits in -// displaystyle, and whether they are symbols and should grow in -// displaystyle. These four groups cover the four possible choices. - -const singleCharIntegrals = { - "\u222b": "\\int", - "\u222c": "\\iint", - "\u222d": "\\iiint", - "\u222e": "\\oint", - "\u222f": "\\oiint", - "\u2230": "\\oiiint", - "\u2231": "\\intclockwise", - "\u2232": "\\varointclockwise", - "\u2a0c": "\\iiiint", - "\u2a0d": "\\intbar", - "\u2a0e": "\\intBar", - "\u2a0f": "\\fint", - "\u2a12": "\\rppolint", - "\u2a13": "\\scpolint", - "\u2a15": "\\pointint", - "\u2a16": "\\sqint", - "\u2a17": "\\intlarhk", - "\u2a18": "\\intx", - "\u2a19": "\\intcap", - "\u2a1a": "\\intcup" -}; - -// No limits, not symbols -defineFunction({ - type: "op", - names: [ - "\\arcsin", - "\\arccos", - "\\arctan", - "\\arctg", - "\\arcctg", - "\\arg", - "\\ch", - "\\cos", - "\\cosec", - "\\cosh", - "\\cot", - "\\cotg", - "\\coth", - "\\csc", - "\\ctg", - "\\cth", - "\\deg", - "\\dim", - "\\exp", - "\\hom", - "\\ker", - "\\lg", - "\\ln", - "\\log", - "\\sec", - "\\sin", - "\\sinh", - "\\sh", - "\\sgn", - "\\tan", - "\\tanh", - "\\tg", - "\\th" - ], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - const prevAtomType = parser.prevAtomType - const next = parser.gullet.future().text - return { - type: "op", - mode: parser.mode, - limits: false, - parentIsSupSub: false, - symbol: false, - stack: false, - isFollowedByDelimiter: isDelimiter(next), - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType), - name: funcName - }; - }, - mathmlBuilder -}); - -// Limits, not symbols -defineFunction({ - type: "op", - names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - const prevAtomType = parser.prevAtomType - const next = parser.gullet.future().text - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: false, - stack: false, - isFollowedByDelimiter: isDelimiter(next), - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType), - name: funcName - }; - }, - mathmlBuilder -}); - -// No limits, symbols -defineFunction({ - type: "op", - names: [ - "\\int", - "\\iint", - "\\iiint", - "\\iiiint", - "\\oint", - "\\oiint", - "\\oiiint", - "\\intclockwise", - "\\varointclockwise", - "\\intbar", - "\\intBar", - "\\fint", - "\\rppolint", - "\\scpolint", - "\\pointint", - "\\sqint", - "\\intlarhk", - "\\intx", - "\\intcap", - "\\intcup", - "\u222b", - "\u222c", - "\u222d", - "\u222e", - "\u222f", - "\u2230", - "\u2231", - "\u2232", - "\u2a0c", - "\u2a0d", - "\u2a0e", - "\u2a0f", - "\u2a12", - "\u2a13", - "\u2a15", - "\u2a16", - "\u2a17", - "\u2a18", - "\u2a19", - "\u2a1a" - ], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - let fName = funcName; - if (fName.length === 1) { - fName = singleCharIntegrals[fName]; - } - return { - type: "op", - mode: parser.mode, - limits: false, - parentIsSupSub: false, - symbol: true, - stack: false, - name: fName - }; - }, - mathmlBuilder -}); diff --git a/src/functions/operatorname.js b/src/functions/operatorname.js deleted file mode 100644 index 1c2e36c1..00000000 --- a/src/functions/operatorname.js +++ /dev/null @@ -1,128 +0,0 @@ -import defineFunction, { ordargument } from "../defineFunction" -import defineMacro from "../defineMacro"; -import mathMLTree from "../mathMLTree" -import { spaceCharacter } from "./kern" -import { ordTypes } from "./op" -import utils from "../utils" - -import * as mml from "../buildMathML" - -// NOTE: Unlike most builders, this one handles not only -// "operatorname", but also "supsub" since \operatorname* can -// affect super/subscripting. - -const mathmlBuilder = (group, style) => { - let expression = mml.buildExpression(group.body, style.withFont("mathrm")) - - // Is expression a string or has it something like a fraction? - let isAllString = true; // default - for (let i = 0; i < expression.length; i++) { - const node = expression[i] - if (node instanceof mathMLTree.MathNode) { - switch (node.type) { - case "mi": - case "mn": - case "ms": - case "mtext": - break; // Do nothing yet. - case "mspace": - { - if (node.attributes.width) { - const width = node.attributes.width.replace("em", "") - const ch = spaceCharacter(Number(width)) - if (ch === "") { - isAllString = false - } else { - expression[i] = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode(ch)]) - } - } - } - break - case "mo": { - const child = node.children[0] - if (node.children.length === 1 && child instanceof mathMLTree.TextNode) { - child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*") - } else { - isAllString = false - } - break - } - default: - isAllString = false - } - } else { - isAllString = false - } - } - - if (isAllString) { - // Write a single TextNode instead of multiple nested tags. - const word = expression.map((node) => node.toText()).join("") - expression = [new mathMLTree.TextNode(word)] - } else if ( - expression.length === 1 - && utils.contains(["mover", "munder"], expression[0].type) && - (expression[0].children[0].type === "mi" || expression[0].children[0].type === "mtext") - ) { - expression[0].children[0].type = "mi" - if (group.parentIsSupSub) { - return new mathMLTree.MathNode("mrow", expression) - } else { - const operator = new mathMLTree.MathNode("mo", [mml.makeText("\u2061", "text")]) - return mathMLTree.newDocumentFragment([expression[0], operator]) - } - } - - let wrapper; - if (isAllString) { - wrapper = new mathMLTree.MathNode("mi", expression) - wrapper.setAttribute("mathvariant", "normal") - } else { - wrapper = new mathMLTree.MathNode("mrow", expression) - } - - if (!group.parentIsSupSub) { - // Append an . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new mathMLTree.MathNode("mo", [mml.makeText("\u2061", "text")]) - if (group.needsLeadingSpace) { - // LaTeX gives operator spacing, but a gets ord spacing. - // So add a leading space. - const space = new mathMLTree.MathNode("mspace") - space.setAttribute("width", "0.1667em") // thin space. - return mathMLTree.newDocumentFragment([space, wrapper, operator]) - } else { - return mathMLTree.newDocumentFragment([wrapper, operator]) - } - } - - return wrapper -}; - -// \operatorname -// amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@ -defineFunction({ - type: "operatorname", - names: ["\\operatorname@", "\\operatornamewithlimits"], - props: { - numArgs: 1, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const body = args[0] - const prevAtomType = parser.prevAtomType - return { - type: "operatorname", - mode: parser.mode, - body: ordargument(body), - alwaysHandleSupSub: (funcName === "\\operatornamewithlimits"), - limits: false, - parentIsSupSub: false, - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType) - }; - }, - mathmlBuilder -}); - -defineMacro("\\operatorname", - "\\@ifstar\\operatornamewithlimits\\operatorname@"); diff --git a/src/functions/ordgroup.js b/src/functions/ordgroup.js deleted file mode 100644 index 52c2196c..00000000 --- a/src/functions/ordgroup.js +++ /dev/null @@ -1,9 +0,0 @@ -import { defineFunctionBuilders } from "../defineFunction"; -import * as mml from "../buildMathML"; - -defineFunctionBuilders({ - type: "ordgroup", - mathmlBuilder(group, style) { - return mml.buildExpressionRow(group.body, style, true); - } -}); diff --git a/src/functions/overline.js b/src/functions/overline.js deleted file mode 100644 index e6c54e19..00000000 --- a/src/functions/overline.js +++ /dev/null @@ -1,31 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import * as mml from "../buildMathML"; - -defineFunction({ - type: "overline", - names: ["\\overline"], - props: { - numArgs: 1 - }, - handler({ parser }, args) { - const body = args[0]; - return { - type: "overline", - mode: parser.mode, - body - }; - }, - mathmlBuilder(group, style) { - const operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u005F")]); - operator.setAttribute("stretchy", "true"); - - const node = new mathMLTree.MathNode( - "mover", - [mml.buildGroup(group.body, style), operator] - ); - node.setAttribute("accent", "true"); - - return node; - } -}); diff --git a/src/functions/phantom.js b/src/functions/phantom.js deleted file mode 100644 index 24ed1624..00000000 --- a/src/functions/phantom.js +++ /dev/null @@ -1,73 +0,0 @@ -import defineFunction, { ordargument } from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import * as mml from "../buildMathML"; - -defineFunction({ - type: "phantom", - names: ["\\phantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "phantom", - mode: parser.mode, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - const inner = mml.buildExpression(group.body, style); - return new mathMLTree.MathNode("mphantom", inner); - } -}); - -defineFunction({ - type: "hphantom", - names: ["\\hphantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "hphantom", - mode: parser.mode, - body - }; - }, - mathmlBuilder: (group, style) => { - const inner = mml.buildExpression(ordargument(group.body), style); - const phantom = new mathMLTree.MathNode("mphantom", inner); - const node = new mathMLTree.MathNode("mpadded", [phantom]); - node.setAttribute("height", "0px"); - node.setAttribute("depth", "0px"); - return node; - } -}); - -defineFunction({ - type: "vphantom", - names: ["\\vphantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "vphantom", - mode: parser.mode, - body - }; - }, - mathmlBuilder: (group, style) => { - const inner = mml.buildExpression(ordargument(group.body), style); - const phantom = new mathMLTree.MathNode("mphantom", inner); - const node = new mathMLTree.MathNode("mpadded", [phantom]); - node.setAttribute("width", "0px"); - return node; - } -}); diff --git a/src/functions/pmb.js b/src/functions/pmb.js deleted file mode 100644 index 4af78962..00000000 --- a/src/functions/pmb.js +++ /dev/null @@ -1,31 +0,0 @@ -import defineFunction, { ordargument } from "../defineFunction" -import { wrapWithMstyle } from "../mathMLTree" -import * as mml from "../buildMathML" - -// \pmb is a simulation of bold font. -// The version of \pmb in ambsy.sty works by typesetting three copies of the argument -// with small offsets. We use CSS text-shadow. -// It's a hack. Not as good as a real bold font. Better than nothing. - -defineFunction({ - type: "pmb", - names: ["\\pmb"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "pmb", - mode: parser.mode, - body: ordargument(args[0]) - } - }, - mathmlBuilder(group, style) { - const inner = mml.buildExpression(group.body, style) - // Wrap with an element. - const node = wrapWithMstyle(inner) - node.setAttribute("style", "text-shadow: 0.02em 0.01em 0.04px") - return node - } -}) diff --git a/src/functions/raise.js b/src/functions/raise.js deleted file mode 100644 index d8ecd51b..00000000 --- a/src/functions/raise.js +++ /dev/null @@ -1,66 +0,0 @@ -import defineFunction from "../defineFunction" -import { StyleLevel } from "../constants" -import mathMLTree from "../mathMLTree" -import { assertNodeType } from "../parseNode" -import { calculateSize } from "../units" -import * as mml from "../buildMathML" - -const sign = num => num >= 0 ? "+" : "-" - -// \raise, \lower, and \raisebox - -const mathmlBuilder = (group, style) => { - const newStyle = style.withLevel(StyleLevel.TEXT) - const node = new mathMLTree.MathNode("mpadded", [mml.buildGroup(group.body, newStyle)]) - const dy = calculateSize(group.dy, style) - node.setAttribute("voffset", dy.number + dy.unit) - const dyAbs = Math.abs(dy.number) - node.setAttribute("height", sign(dy.number) + dyAbs + dy.unit) - node.setAttribute("depth", sign(-dy.number) + dyAbs + dy.unit) - return node -} - -defineFunction({ - type: "raise", - names: ["\\raise", "\\lower"], - props: { - numArgs: 2, - argTypes: ["size", "primitive"], - primitive: true - }, - handler({ parser, funcName }, args) { - const amount = assertNodeType(args[0], "size").value; - if (funcName === "\\lower") { amount.number *= -1 } - const body = args[1] - return { - type: "raise", - mode: parser.mode, - dy: amount, - body - }; - }, - mathmlBuilder -}) - - -defineFunction({ - type: "raise", - names: ["\\raisebox"], - props: { - numArgs: 2, - argTypes: ["size", "hbox"], - allowedInText: true - }, - handler({ parser, funcName }, args) { - const amount = assertNodeType(args[0], "size").value - const body = args[1] - return { - type: "raise", - mode: parser.mode, - dy: amount, - body - }; - }, - mathmlBuilder -}) - diff --git a/src/functions/ref.js b/src/functions/ref.js deleted file mode 100644 index 12ef6024..00000000 --- a/src/functions/ref.js +++ /dev/null @@ -1,28 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import { invalidIdRegEx } from "./label"; - -defineFunction({ - type: "ref", - names: ["\\ref", "\\eqref"], - props: { - numArgs: 1, - argTypes: ["raw"] - }, - handler({ parser, funcName }, args) { - return { - type: "ref", - mode: parser.mode, - funcName, - string: args[0].string.replace(invalidIdRegEx, "") - }; - }, - mathmlBuilder(group, style) { - // Create an empty text node. Set a class and an href. - // The post-processor will populate with the target's tag or equation number. - const classes = group.funcName === "\\ref" ? ["tml-ref"] : ["tml-ref", "tml-eqref"] - const node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("")], classes) - node.setAttribute("href", "#" + group.string) - return node - } -}); diff --git a/src/functions/relax.js b/src/functions/relax.js deleted file mode 100644 index 5527cfab..00000000 --- a/src/functions/relax.js +++ /dev/null @@ -1,16 +0,0 @@ -import defineFunction from "../defineFunction" - -defineFunction({ - type: "internal", - names: ["\\relax"], - props: { - numArgs: 0, - allowedInText: true - }, - handler({ parser }) { - return { - type: "internal", - mode: parser.mode - }; - } -}) diff --git a/src/functions/rule.js b/src/functions/rule.js deleted file mode 100644 index 96230e87..00000000 --- a/src/functions/rule.js +++ /dev/null @@ -1,52 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import { assertNodeType } from "../parseNode"; -import { calculateSize } from "../units"; - -defineFunction({ - type: "rule", - names: ["\\rule"], - props: { - numArgs: 2, - numOptionalArgs: 1, - argTypes: ["size", "size", "size"] - }, - handler({ parser }, args, optArgs) { - const shift = optArgs[0]; - const width = assertNodeType(args[0], "size"); - const height = assertNodeType(args[1], "size"); - return { - type: "rule", - mode: parser.mode, - shift: shift && assertNodeType(shift, "size").value, - width: width.value, - height: height.value - }; - }, - mathmlBuilder(group, style) { - const width = calculateSize(group.width, style); - const height = calculateSize(group.height, style); - const shift = group.shift - ? calculateSize(group.shift, style) - : { number: 0, unit: "em" }; - const color = (style.color && style.getColor()) || "black"; - - const rule = new mathMLTree.MathNode("mspace"); - if (width.number > 0 && height.number > 0) { - rule.setAttribute("mathbackground", color); - } - rule.setAttribute("width", width.number + width.unit); - rule.setAttribute("height", height.number + height.unit); - if (shift.number === 0) { return rule } - - const wrapper = new mathMLTree.MathNode("mpadded", [rule]); - if (shift.number >= 0) { - wrapper.setAttribute("height", "+" + shift.number + shift.unit); - } else { - wrapper.setAttribute("height", shift.number + shift.unit); - wrapper.setAttribute("depth", "+" + -shift.number + shift.unit); - } - wrapper.setAttribute("voffset", shift.number + shift.unit); - return wrapper; - } -}); diff --git a/src/functions/sizing.js b/src/functions/sizing.js deleted file mode 100644 index 9d51d4e1..00000000 --- a/src/functions/sizing.js +++ /dev/null @@ -1,64 +0,0 @@ -import defineFunction from "../defineFunction"; -import { wrapWithMstyle } from "../mathMLTree" -import * as mml from "../buildMathML"; - -// The size mappings are taken from TeX with \normalsize=10pt. -// We don't have to track script level. MathML does that. -const sizeMap = { - "\\tiny": 0.5, - "\\sixptsize": 0.6, - "\\Tiny": 0.6, - "\\scriptsize": 0.7, - "\\footnotesize": 0.8, - "\\small": 0.9, - "\\normalsize": 1.0, - "\\large": 1.2, - "\\Large": 1.44, - "\\LARGE": 1.728, - "\\huge": 2.074, - "\\Huge": 2.488 -}; - -defineFunction({ - type: "sizing", - names: [ - "\\tiny", - "\\sixptsize", - "\\Tiny", - "\\scriptsize", - "\\footnotesize", - "\\small", - "\\normalsize", - "\\large", - "\\Large", - "\\LARGE", - "\\huge", - "\\Huge" - ], - props: { - numArgs: 0, - allowedInText: true - }, - handler: ({ breakOnTokenText, funcName, parser }, args) => { - if (parser.settings.strict && parser.mode === "math") { - // eslint-disable-next-line no-console - console.log(`Temml strict-mode warning: Command ${funcName} is invalid in math mode.`) - } - const body = parser.parseExpression(false, breakOnTokenText); - return { - type: "sizing", - mode: parser.mode, - funcName, - body - }; - }, - mathmlBuilder: (group, style) => { - const newStyle = style.withFontSize(sizeMap[group.funcName]); - const inner = mml.buildExpression(group.body, newStyle); - // Wrap with an element. - const node = wrapWithMstyle(inner) - const factor = (sizeMap[group.funcName] / style.fontSize).toFixed(4) - node.setAttribute("mathsize", factor + "em"); - return node; - } -}); diff --git a/src/functions/smash.js b/src/functions/smash.js deleted file mode 100644 index 71890a62..00000000 --- a/src/functions/smash.js +++ /dev/null @@ -1,66 +0,0 @@ -// smash, with optional [tb], as in AMS -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import { assertNodeType } from "../parseNode"; - -import * as mml from "../buildMathML"; - -defineFunction({ - type: "smash", - names: ["\\smash"], - props: { - numArgs: 1, - numOptionalArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args, optArgs) => { - let smashHeight = false; - let smashDepth = false; - const tbArg = optArgs[0] && assertNodeType(optArgs[0], "ordgroup"); - if (tbArg) { - // Optional [tb] argument is engaged. - // ref: amsmath: \renewcommand{\smash}[1][tb]{% - // def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}% - let letter = ""; - for (let i = 0; i < tbArg.body.length; ++i) { - const node = tbArg.body[i]; - // TODO: Write an AssertSymbolNode - letter = node.text; - if (letter === "t") { - smashHeight = true; - } else if (letter === "b") { - smashDepth = true; - } else { - smashHeight = false; - smashDepth = false; - break; - } - } - } else { - smashHeight = true; - smashDepth = true; - } - - const body = args[0]; - return { - type: "smash", - mode: parser.mode, - body, - smashHeight, - smashDepth - }; - }, - mathmlBuilder: (group, style) => { - const node = new mathMLTree.MathNode("mpadded", [mml.buildGroup(group.body, style)]); - - if (group.smashHeight) { - node.setAttribute("height", "0px"); - } - - if (group.smashDepth) { - node.setAttribute("depth", "0px"); - } - - return node; - } -}); diff --git a/src/functions/sqrt.js b/src/functions/sqrt.js deleted file mode 100644 index fd54ce52..00000000 --- a/src/functions/sqrt.js +++ /dev/null @@ -1,31 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import * as mml from "../buildMathML"; - -defineFunction({ - type: "sqrt", - names: ["\\sqrt"], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser }, args, optArgs) { - const index = optArgs[0]; - const body = args[0]; - return { - type: "sqrt", - mode: parser.mode, - body, - index - }; - }, - mathmlBuilder(group, style) { - const { body, index } = group; - return index - ? new mathMLTree.MathNode("mroot", [ - mml.buildGroup(body, style), - mml.buildGroup(index, style.incrementLevel()) - ]) - : new mathMLTree.MathNode("msqrt", [mml.buildGroup(body, style)]); - } -}); diff --git a/src/functions/styling.js b/src/functions/styling.js deleted file mode 100644 index 23f65d06..00000000 --- a/src/functions/styling.js +++ /dev/null @@ -1,58 +0,0 @@ -import defineFunction from "../defineFunction"; -import { wrapWithMstyle } from "../mathMLTree" -import * as mml from "../buildMathML"; - -const styleMap = { - display: 0, - text: 1, - script: 2, - scriptscript: 3 -}; - -const styleAttributes = { - display: ["0", "true"], - text: ["0", "false"], - script: ["1", "false"], - scriptscript: ["2", "false"] -}; - -defineFunction({ - type: "styling", - names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ breakOnTokenText, funcName, parser }, args) { - // parse out the implicit body - const body = parser.parseExpression(true, breakOnTokenText); - - const scriptLevel = funcName.slice(1, funcName.length - 5); - return { - type: "styling", - mode: parser.mode, - // Figure out what scriptLevel to use by pulling out the scriptLevel from - // the function name - scriptLevel, - body - }; - }, - mathmlBuilder(group, style) { - // Figure out what scriptLevel we're changing to. - const newStyle = style.withLevel(styleMap[group.scriptLevel]); - // The style argument in the next line does NOT directly set a MathML script level. - // It just tracks the style level, in case we need to know it for supsub or mathchoice. - const inner = mml.buildExpression(group.body, newStyle); - // Wrap with an element. - const node = wrapWithMstyle(inner) - - const attr = styleAttributes[group.scriptLevel]; - - // Here is where we set the MathML script level. - node.setAttribute("scriptlevel", attr[0]); - node.setAttribute("displaystyle", attr[1]); - - return node; - } -}); diff --git a/src/functions/supsub.js b/src/functions/supsub.js deleted file mode 100644 index 80b9c7f2..00000000 --- a/src/functions/supsub.js +++ /dev/null @@ -1,135 +0,0 @@ -import { defineFunctionBuilders } from "../defineFunction" -import { StyleLevel } from "../constants" -import mathMLTree from "../mathMLTree" -import * as mml from "../buildMathML" - -/** - * Sometimes, groups perform special rules when they have superscripts or - * subscripts attached to them. This function lets the `supsub` group know that - * Sometimes, groups perform special rules when they have superscripts or - * its inner element should handle the superscripts and subscripts instead of - * handling them itself. - */ - -// Helpers -const symbolRegEx = /^m(over|under|underover)$/ - -// Super scripts and subscripts, whose precise placement can depend on other -// functions that precede them. -defineFunctionBuilders({ - type: "supsub", - mathmlBuilder(group, style) { - // Is the inner group a relevant horizonal brace? - let isBrace = false - let isOver - let isSup - let appendApplyFunction = false - let needsLeadingSpace = false - - if (group.base && group.base.type === "horizBrace") { - isSup = !!group.sup - if (isSup === group.base.isOver) { - isBrace = true - isOver = group.base.isOver - } - } - - if (group.base && !group.base.stack && - (group.base.type === "op" || group.base.type === "operatorname")) { - group.base.parentIsSupSub = true - appendApplyFunction = !group.base.symbol - needsLeadingSpace = group.base.needsLeadingSpace - } - - const children = group.base && group.base.stack - ? [mml.buildGroup(group.base.body[0], style)] - : [mml.buildGroup(group.base, style)] - - const childStyle = style.inSubOrSup() - if (group.sub) { - children.push(mml.buildGroup(group.sub, childStyle)) - } - - if (group.sup) { - children.push(mml.buildGroup(group.sup, childStyle)) - } - - let nodeType; - if (isBrace) { - nodeType = isOver ? "mover" : "munder" - } else if (!group.sub) { - const base = group.base - if ( - base && - base.type === "op" && - base.limits && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "mover" - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (base.limits || style.level === StyleLevel.DISPLAY) - ) { - nodeType = "mover" - } else { - nodeType = "msup" - } - } else if (!group.sup) { - const base = group.base; - if ( - base && - base.type === "op" && - base.limits && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "munder"; - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (base.limits || style.level === StyleLevel.DISPLAY) - ) { - nodeType = "munder" - } else { - nodeType = "msub" - } - } else { - const base = group.base; - if (base && ((base.type === "op" && base.limits) || base.type === "multiscript") && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "munderover" - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (style.level === StyleLevel.DISPLAY || base.limits) - ) { - nodeType = "munderover" - } else { - nodeType = "msubsup" - } - } - - let node = new mathMLTree.MathNode(nodeType, children) - if (appendApplyFunction) { - // Append an . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new mathMLTree.MathNode("mo", [mml.makeText("\u2061", "text")]) - if (needsLeadingSpace) { - const space = new mathMLTree.MathNode("mspace") - space.setAttribute("width", "0.1667em") // thin space. - node = mathMLTree.newDocumentFragment([space, node, operator]) - } else { - node = mathMLTree.newDocumentFragment([node, operator]) - } - } else if (symbolRegEx.test(nodeType)) { - // Wrap in a . Otherwise Firefox stretchy parens will not stretch to include limits. - node = new mathMLTree.MathNode("mrow", [node]) - } - - return node - } -}); diff --git a/src/functions/symbolsOp.js b/src/functions/symbolsOp.js deleted file mode 100644 index 3a56de43..00000000 --- a/src/functions/symbolsOp.js +++ /dev/null @@ -1,41 +0,0 @@ -import { defineFunctionBuilders } from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import * as mml from "../buildMathML"; - -// Operator ParseNodes created in Parser.js from symbol Groups in src/symbols.js. - -const short = ["\\shortmid", "\\nshortmid", "\\shortparallel", - "\\nshortparallel", "\\smallsetminus"] - -defineFunctionBuilders({ - type: "atom", - mathmlBuilder(group, style) { - const node = new mathMLTree.MathNode("mo", [mml.makeText(group.text, group.mode)]); - if (group.family === "punct") { - node.setAttribute("separator", "true"); - } else if (group.family === "open" || group.family === "close") { - // Delims built here should not stretch vertically. - // See delimsizing.js for stretchy delims. - if (group.family === "open") { - node.setAttribute("form", "prefix") - // Set an explicit attribute for stretch. Otherwise Firefox may do it wrong. - node.setAttribute("stretchy", "false") - } else if (group.family === "close") { - node.setAttribute("form", "postfix"); - node.setAttribute("stretchy", "false") - } - } else if (group.text === "\\mid") { - // Firefox messes up this spacing if at the end of an . See it explicitly. - node.setAttribute("lspace", "0.22em") // medium space - node.setAttribute("rspace", "0.22em") - node.setAttribute("stretchy", "false") - } else if (short.includes(group.text)) { - node.setAttribute("mathsize", "70%") - } else if (group.text === ":") { - // ":" is not in the MathML operator dictionary. Give it BIN spacing. - node.attributes.lspace = "0.2222em" - node.attributes.rspace = "0.2222em" - } - return node; - } -}); diff --git a/src/functions/symbolsOrd.js b/src/functions/symbolsOrd.js deleted file mode 100644 index 9b5cebf2..00000000 --- a/src/functions/symbolsOrd.js +++ /dev/null @@ -1,103 +0,0 @@ -import { defineFunctionBuilders } from "../defineFunction" -import { getVariant } from "../variant" -import { variantChar, smallCaps } from "../replace" -import mathMLTree from "../mathMLTree" -import * as mml from "../buildMathML" - -// "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in -// src/symbols.js. - -const numberRegEx = /^\d(?:[\d,.]*\d)?$/ // Keep in sync with numberRegEx in Parser.js - -const latinRegEx = /[A-Ba-z]/ - -const italicNumber = (text, variant) => { - const mn = new mathMLTree.MathNode("mn", [text]) - const wrapper = new mathMLTree.MathNode("mstyle", [mn]) - wrapper.style["font-style"] = "italic" - wrapper.style["font-family"] = "Cambria, 'Times New Roman', serif" - if (variant === "bold-italic") { wrapper.style["font-weight"] = "bold" } - return wrapper -} - -defineFunctionBuilders({ - type: "mathord", - mathmlBuilder(group, style) { - const text = mml.makeText(group.text, group.mode, style) - const codePoint = text.text.codePointAt(0) - // Test for upper-case Greek - const defaultVariant = (0x0390 < codePoint && codePoint < 0x03aa) ? "normal" : "italic" - const variant = getVariant(group, style) || defaultVariant - if (variant === "script") { - text.text = variantChar(text.text, variant) - return new mathMLTree.MathNode("mi", [text], [style.font]) - } else if (variant !== "italic") { - text.text = variantChar(text.text, variant) - } - let node = new mathMLTree.MathNode("mi", [text]) - // TODO: Handle U+1D49C - U+1D4CF per https://www.unicode.org/charts/PDF/U1D400.pdf - if (variant === "normal") { - node.setAttribute("mathvariant", "normal") - if (text.text.length === 1) { - // A Firefox bug will apply spacing here, but there should be none. Fix it. - node = new mathMLTree.MathNode("mpadded", [node]) - node.setAttribute("lspace", "0") - node.setAttribute("width", "+0em") - } - } - return node - } -}) - -defineFunctionBuilders({ - type: "textord", - mathmlBuilder(group, style) { - let ch = group.text - const codePoint = ch.codePointAt(0) - if (style.fontFamily === "textsc") { - // Convert small latin letters to small caps. - if (96 < codePoint && codePoint < 123) { - ch = smallCaps[ch] - } - } - const text = mml.makeText(ch, group.mode, style) - const variant = getVariant(group, style) || "normal" - - let node - if (group.mode === "text") { - if (variant === "italic" || variant === "bold-italic") { - if (numberRegEx.test(group.text)) { - return italicNumber(text, variant) - } - } - if (variant !== "normal") { - text.text = variantChar(text.text, variant) - } - node = new mathMLTree.MathNode("mtext", [text]) - } else if (numberRegEx.test(group.text)) { - if (variant === "oldstylenums") { - const ms = new mathMLTree.MathNode("mstyle", [text], ["oldstylenums"]) - node = new mathMLTree.MathNode("mn", [ms]) - } else if (variant === "italic" || variant === "bold-italic") { - return italicNumber(text, variant) - } else { - if (variant !== "normal") { - text.text = text.text.split("").map(c => variantChar(c, variant)).join("") - } - node = new mathMLTree.MathNode("mn", [text]) - } - } else if (group.text === "\\prime") { - node = new mathMLTree.MathNode("mo", [text]) - } else { - const origText = text.text - if (variant !== "italic") { - text.text = variantChar(text.text, variant) - } - node = new mathMLTree.MathNode("mi", [text]) - if (text.text === origText && latinRegEx.test(origText)) { - node.setAttribute("mathvariant", "italic") - } - } - return node - } -}) diff --git a/src/functions/symbolsSpacing.js b/src/functions/symbolsSpacing.js deleted file mode 100644 index 85518b52..00000000 --- a/src/functions/symbolsSpacing.js +++ /dev/null @@ -1,53 +0,0 @@ -import { defineFunctionBuilders } from "../defineFunction" -import mathMLTree from "../mathMLTree" -import ParseError from "../ParseError" - -// A map of CSS-based spacing functions to their CSS class. -const cssSpace = { - "\\nobreak": "nobreak", - "\\allowbreak": "allowbreak" -} - -// A lookup table to determine whether a spacing function/symbol should be -// treated like a regular space character. If a symbol or command is a key -// in this table, then it should be a regular space character. Furthermore, -// the associated value may have a `className` specifying an extra CSS class -// to add to the created `span`. -const regularSpace = { - " ": {}, - "\\ ": {}, - "~": { - className: "nobreak" - }, - "\\space": {}, - "\\nobreakspace": { - className: "nobreak" - } -} - -// ParseNode<"spacing"> created in Parser.js from the "spacing" symbol Groups in -// src/symbols.js. -defineFunctionBuilders({ - type: "spacing", - mathmlBuilder(group, style) { - let node - - if (Object.prototype.hasOwnProperty.call(regularSpace, group.text)) { - // Firefox does not render a space in a . So write a no-break space. - // TODO: If Firefox fixes that bug, uncomment the next line and write ch into the node. - //const ch = (regularSpace[group.text].className === "nobreak") ? "\u00a0" : " " - node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("\u00a0")]) - } else if (Object.prototype.hasOwnProperty.call(cssSpace, group.text)) { - // MathML 3.0 calls for nobreak to occur in an , not an - // Ref: https://www.w3.org/Math/draft-spec/mathml.html#chapter3_presm.lbattrs - node = new mathMLTree.MathNode("mo") - if (group.text === "\\nobreak") { - node.setAttribute("linebreak", "nobreak") - } - } else { - throw new ParseError(`Unknown type of space "${group.text}"`) - } - - return node - } -}) diff --git a/src/functions/tag.js b/src/functions/tag.js deleted file mode 100644 index ddb86ec5..00000000 --- a/src/functions/tag.js +++ /dev/null @@ -1,8 +0,0 @@ -import { defineFunctionBuilders } from "../defineFunction"; - -defineFunctionBuilders({ - type: "tag" -}); - -// For a \tag, the work usually done in a mathmlBuilder is instead done in buildMathML.js. -// That way, a \tag can be pulled out of the parse tree and wrapped around the outer node. diff --git a/src/functions/text.js b/src/functions/text.js deleted file mode 100644 index ad7b2393..00000000 --- a/src/functions/text.js +++ /dev/null @@ -1,76 +0,0 @@ -import defineFunction, { ordargument } from "../defineFunction"; -import * as mml from "../buildMathML"; -import utils from "../utils" - -// Non-mathy text, possibly in a font -const textFontFamilies = { - "\\text": undefined, - "\\textrm": "textrm", - "\\textsf": "textsf", - "\\texttt": "texttt", - "\\textnormal": "textrm", - "\\textsc": "textsc" // small caps -}; - -const textFontWeights = { - "\\textbf": "textbf", - "\\textmd": "textmd" -}; - -const textFontShapes = { - "\\textit": "textit", - "\\textup": "textup" -}; - -const styleWithFont = (group, style) => { - const font = group.font; - // Checks if the argument is a font family or a font style. - if (!font) { - return style; - } else if (textFontFamilies[font]) { - return style.withTextFontFamily(textFontFamilies[font]); - } else if (textFontWeights[font]) { - return style.withTextFontWeight(textFontWeights[font]); - } else { - return style.withTextFontShape(textFontShapes[font]); - } -}; - -defineFunction({ - type: "text", - names: [ - // Font families - "\\text", - "\\textrm", - "\\textsf", - "\\texttt", - "\\textnormal", - "\\textsc", - // Font weights - "\\textbf", - "\\textmd", - // Font Shapes - "\\textit", - "\\textup" - ], - props: { - numArgs: 1, - argTypes: ["text"], - allowedInArgument: true, - allowedInText: true - }, - handler({ parser, funcName }, args) { - const body = args[0]; - return { - type: "text", - mode: parser.mode, - body: ordargument(body), - font: funcName - }; - }, - mathmlBuilder(group, style) { - const newStyle = styleWithFont(group, style) - const mrow = mml.buildExpressionRow(group.body, newStyle) - return utils.consolidateText(mrow) - } -}); diff --git a/src/functions/tip.js b/src/functions/tip.js deleted file mode 100644 index 714f7248..00000000 --- a/src/functions/tip.js +++ /dev/null @@ -1,63 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import * as mml from "../buildMathML"; - -// Two functions included to enable migration from Mathjax. - -defineFunction({ - type: "tip", - names: ["\\mathtip"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "tip", - mode: parser.mode, - body: args[0], - tip: args[1] - }; - }, - mathmlBuilder: (group, style) => { - const math = mml.buildGroup(group.body, style) - const tip = mml.buildGroup(group.tip, style) - // Browsers don't support the tooltip actiontype. - // TODO: Come back and fix \mathtip when it can be done via CSS w/o a JS event. - const node = new mathMLTree.MathNode("maction", [math, tip], ["tml-tip"]) - node.setAttribute("actiontype", "tooltip") - return node - } -}) - -defineFunction({ - type: "tip", - names: ["\\texttip"], - props: { - numArgs: 2, - argTypes: ["math", "text"] - }, - handler({ parser }, args) { - return { - type: "tip", - mode: parser.mode, - body: args[0], - tip: args[1] - }; - }, - mathmlBuilder: (group, style) => { - const math = mml.buildGroup(group.body, style) - const tip = mml.buildGroup(group.tip, style) - // args[1] only accepted text, so tip is a element or a of them. - let str = "" - if (tip.type === "mtext") { - str = tip.children[0].text - } else { - for (const child of tip.children) { - str += child.children[0].text - } - } - // Implement \texttip via a title attribute. - math.setAttribute("title", str) - return math - } -}) diff --git a/src/functions/toggle.js b/src/functions/toggle.js deleted file mode 100644 index 5f0179c7..00000000 --- a/src/functions/toggle.js +++ /dev/null @@ -1,13 +0,0 @@ -import { defineFunctionBuilders } from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import * as mml from "../buildMathML"; - -defineFunctionBuilders({ - type: "toggle", - mathmlBuilder(group, style) { - const expression = mml.buildExpression(group.body, style) - const node = new mathMLTree.MathNode("maction", expression, [], { cursor: "default" }) - node.setAttribute("actiontype", "toggle") - return node - } -}) diff --git a/src/functions/underline.js b/src/functions/underline.js deleted file mode 100644 index 63c444f3..00000000 --- a/src/functions/underline.js +++ /dev/null @@ -1,30 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import * as mml from "../buildMathML"; - -defineFunction({ - type: "underline", - names: ["\\underline"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "underline", - mode: parser.mode, - body: args[0] - }; - }, - mathmlBuilder(group, style) { - const operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u005f")]); - operator.setAttribute("stretchy", "true"); - - const node = new mathMLTree.MathNode("munder", - [mml.buildGroup(group.body, style), operator] - ); - node.setAttribute("accentunder", "true"); - - return node; - } -}); diff --git a/src/functions/verb.js b/src/functions/verb.js deleted file mode 100644 index da6a67a6..00000000 --- a/src/functions/verb.js +++ /dev/null @@ -1,33 +0,0 @@ -import defineFunction from "../defineFunction"; -import mathMLTree from "../mathMLTree"; -import ParseError from "../ParseError"; - -defineFunction({ - type: "verb", - names: ["\\verb"], - props: { - numArgs: 0, - allowedInText: true - }, - handler(context, args, optArgs) { - // \verb and \verb* are dealt with directly in Parser.js. - // If we end up here, it's because of a failure to match the two delimiters - // in the regex in Lexer.js. LaTeX raises the following error when \verb is - // terminated by end of line (or file). - throw new ParseError("\\verb ended by end of line instead of matching delimiter"); - }, - mathmlBuilder(group, style) { - const text = new mathMLTree.TextNode(makeVerb(group)); - const node = new mathMLTree.MathNode("mtext", [text]); - node.setAttribute("mathvariant", "monospace"); - return node; - } -}); - -/** - * Converts verb group into body string. - * - * \verb* replaces each space with an open box \u2423 - * \verb replaces each space with a no-break space \xA0 - */ -const makeVerb = (group) => group.body.replace(/ /g, group.star ? "\u2423" : "\xA0"); diff --git a/src/linebreaking.js b/src/linebreaking.js deleted file mode 100644 index f76b0c21..00000000 --- a/src/linebreaking.js +++ /dev/null @@ -1,145 +0,0 @@ -import mathMLTree from "./mathMLTree" - -/* - * Neither Firefox nor Chrome support hard line breaks or soft line breaks. - * (Despite https://www.w3.org/Math/draft-spec/mathml.html#chapter3_presm.lbattrs) - * So Temml has work-arounds for both hard and soft breaks. - * The work-arounds sadly do not work simultaneously. Any top-level hard - * break makes soft line breaks impossible. - * - * Hard breaks are simulated by creating a and putting each line in its own . - * - * To create soft line breaks, Temml avoids using the and tags. - * Then the top level of a element can be occupied by elements, and the browser - * will break after a if the expression extends beyond the container limit. - * - * We want the expression to render with soft line breaks after each top-level binary or - * relational operator, per TeXbook p. 173. So we gather the expression into s so that - * each ends in a binary or relational operator. - * - * Soft line breaks will not work in Chromium and Safari, only Firefox. - * - * Hopefully browsers will someday do their own linebreaking and we will be able to delete - * much of this module. - */ - -export default function setLineBreaks(expression, isDisplayMode, isAnnotated, color = undefined) { - if (color === undefined) { - // First, make one pass through the expression and split any color nodes. - const upperLimit = expression.length - 1 - for (let i = upperLimit; i >= 0; i--) { - const node = expression[i]; - if (node.type === "mstyle" && node.attributes.mathcolor) { - const color = node.attributes.mathcolor - const fragment = setLineBreaks(node.children, isDisplayMode, isAnnotated, color) - if (!(fragment.type && fragment.type !== "mtable")) { - expression.splice(i, 1, ...fragment.children) - - } - } - } - } - - const tagName = color ? "mstyle" : "mrow" - - const mtrs = []; - let mrows = []; - let block = []; - let canBeBIN = false // The first node cannot be an infix binary operator. - for (let i = 0; i < expression.length; i++) { - const node = expression[i]; - if (node.type && node.type === "mstyle" && node.attributes.mathcolor) { - // Start a new block. (Insert a soft linebreak.) - mrows.push(new mathMLTree.MathNode(tagName, block)) - // Insert the mstyle - mrows.push(node) - block = []; - continue - } - if (node.attributes && node.attributes.linebreak && - node.attributes.linebreak === "newline") { - // A hard line break. Create a for the current block. - if (block.length > 0) { - const element = new mathMLTree.MathNode(tagName, block) - if (color) { element.setAttribute("mathcolor", color) } - mrows.push(new mathMLTree.MathNode(tagName, block)) - } - mrows.push(node) - block = []; - const mtd = new mathMLTree.MathNode("mtd", mrows) - mtrs.push(new mathMLTree.MathNode("mtr", [mtd])) - mrows = []; - continue - } - block.push(node); - if (node.type && node.type === "mo" && !isDisplayMode && !isAnnotated) { - // This may be a place for a soft line break. - if (canBeBIN && !node.attributes.form) { - // Check if the following node is a \nobreak text node, e.g. "~"" - const next = i < expression.length - 1 ? expression[i + 1] : null; - let glueIsFreeOfNobreak = true; - if ( - !( - next && - next.type === "mtext" && - next.attributes.linebreak && - next.attributes.linebreak === "nobreak" - ) - ) { - // We may need to start a new block. - // First, put any post-operator glue on same line as operator. - for (let j = i + 1; j < expression.length; j++) { - const nd = expression[j]; - if ( - nd.type && - nd.type === "mspace" && - !(nd.attributes.linebreak && nd.attributes.linebreak === "newline") - ) { - block.push(nd); - i += 1; - if ( - nd.attributes && - nd.attributes.linebreak && - nd.attributes.linebreak === "nobreak" - ) { - glueIsFreeOfNobreak = false; - } - } else { - break; - } - } - } - if (glueIsFreeOfNobreak) { - // Start a new block. (Insert a soft linebreak.) - const element = new mathMLTree.MathNode(tagName, block) - if (color) { element.setAttribute("mathcolor", color) } - mrows.push(element) - block = []; - } - canBeBIN = false; - } - const isOpenDelimiter = node.attributes.form && node.attributes.form === "prefix"; - // Any operator that follows an open delimiter is unary. - canBeBIN = !(node.attributes.separator || isOpenDelimiter); - } else { - canBeBIN = true; - } - } - if (block.length > 0) { - const element = new mathMLTree.MathNode(tagName, block) - if (color) { element.setAttribute("mathcolor", color) } - mrows.push(element) - } - if (mtrs.length > 0) { - const mtd = new mathMLTree.MathNode("mtd", mrows) - const mtr = new mathMLTree.MathNode("mtr", [mtd]) - mtrs.push(mtr) - const mtable = new mathMLTree.MathNode("mtable", mtrs) - if (!isDisplayMode) { - mtable.setAttribute("columnalign", "left") - mtable.setAttribute("rowspacing", "0em") - } - return mtable - } - return mathMLTree.newDocumentFragment(mrows); -} diff --git a/src/macros.js b/src/macros.js deleted file mode 100644 index bffd6c92..00000000 --- a/src/macros.js +++ /dev/null @@ -1,709 +0,0 @@ -/** - * Predefined macros for Temml. - * This can be used to define some commands in terms of others. - */ - -// Export global macros object from defineMacro -import defineMacro, { _macros } from "./defineMacro"; -const macros = _macros; -export default macros; - -import symbols from "./symbols"; -import utils from "./utils"; -import ParseError from "./ParseError"; - -////////////////////////////////////////////////////////////////////// -// macro tools - -defineMacro("\\noexpand", function(context) { - // The expansion is the token itself; but that token is interpreted - // as if its meaning were ‘\relax’ if it is a control sequence that - // would ordinarily be expanded by TeX’s expansion rules. - const t = context.popToken(); - if (context.isExpandable(t.text)) { - t.noexpand = true; - t.treatAsRelax = true; - } - return { tokens: [t], numArgs: 0 }; -}); - -defineMacro("\\expandafter", function(context) { - // TeX first reads the token that comes immediately after \expandafter, - // without expanding it; let’s call this token t. Then TeX reads the - // token that comes after t (and possibly more tokens, if that token - // has an argument), replacing it by its expansion. Finally TeX puts - // t back in front of that expansion. - const t = context.popToken(); - context.expandOnce(true); // expand only an expandable token - return { tokens: [t], numArgs: 0 }; -}); - -// LaTeX's \@firstoftwo{#1}{#2} expands to #1, skipping #2 -// TeX source: \long\def\@firstoftwo#1#2{#1} -defineMacro("\\@firstoftwo", function(context) { - const args = context.consumeArgs(2); - return { tokens: args[0], numArgs: 0 }; -}); - -// LaTeX's \@secondoftwo{#1}{#2} expands to #2, skipping #1 -// TeX source: \long\def\@secondoftwo#1#2{#2} -defineMacro("\\@secondoftwo", function(context) { - const args = context.consumeArgs(2); - return { tokens: args[1], numArgs: 0 }; -}); - -// LaTeX's \@ifnextchar{#1}{#2}{#3} looks ahead to the next (unexpanded) -// symbol that isn't a space, consuming any spaces but not consuming the -// first nonspace character. If that nonspace character matches #1, then -// the macro expands to #2; otherwise, it expands to #3. -defineMacro("\\@ifnextchar", function(context) { - const args = context.consumeArgs(3); // symbol, if, else - context.consumeSpaces(); - const nextToken = context.future(); - if (args[0].length === 1 && args[0][0].text === nextToken.text) { - return { tokens: args[1], numArgs: 0 }; - } else { - return { tokens: args[2], numArgs: 0 }; - } -}); - -// LaTeX's \@ifstar{#1}{#2} looks ahead to the next (unexpanded) symbol. -// If it is `*`, then it consumes the symbol, and the macro expands to #1; -// otherwise, the macro expands to #2 (without consuming the symbol). -// TeX source: \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}} -defineMacro("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}"); - -// LaTeX's \TextOrMath{#1}{#2} expands to #1 in text mode, #2 in math mode -defineMacro("\\TextOrMath", function(context) { - const args = context.consumeArgs(2); - if (context.mode === "text") { - return { tokens: args[0], numArgs: 0 }; - } else { - return { tokens: args[1], numArgs: 0 }; - } -}); - -const stringFromArg = arg => { - // Reverse the order of the arg and return a string. - let str = "" - for (let i = arg.length - 1; i > -1; i--) { - str += arg[i].text - } - return str -} - -// Lookup table for parsing numbers in base 8 through 16 -const digitToNumber = { - 0: 0, - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9, - a: 10, - A: 10, - b: 11, - B: 11, - c: 12, - C: 12, - d: 13, - D: 13, - e: 14, - E: 14, - f: 15, - F: 15 -}; - -const nextCharNumber = context => { - const numStr = context.future().text - if (numStr === "EOF") { return [null, ""] } - return [digitToNumber[numStr.charAt(0)], numStr] -} - -const appendCharNumbers = (number, numStr, base) => { - for (let i = 1; i < numStr.length; i++) { - const digit = digitToNumber[numStr.charAt(i)] - number *= base; - number += digit; - } - return number -} - -// TeX \char makes a literal character (catcode 12) using the following forms: -// (see The TeXBook, p. 43) -// \char123 -- decimal -// \char'123 -- octal -// \char"123 -- hex -// \char`x -- character that can be written (i.e. isn't active) -// \char`\x -- character that cannot be written (e.g. %) -// These all refer to characters from the font, so we turn them into special -// calls to a function \@char dealt with in the Parser. -defineMacro("\\char", function(context) { - let token = context.popToken(); - let base; - let number = ""; - if (token.text === "'") { - base = 8; - token = context.popToken(); - } else if (token.text === '"') { - base = 16; - token = context.popToken(); - } else if (token.text === "`") { - token = context.popToken(); - if (token.text[0] === "\\") { - number = token.text.charCodeAt(1); - } else if (token.text === "EOF") { - throw new ParseError("\\char` missing argument"); - } else { - number = token.text.charCodeAt(0); - } - } else { - base = 10; - } - if (base) { - // Parse a number in the given base, starting with first `token`. - let numStr = token.text - number = digitToNumber[numStr.charAt(0)]; - if (number == null || number >= base) { - throw new ParseError(`Invalid base-${base} digit ${token.text}`); - } - number = appendCharNumbers(number, numStr, base) - let digit; - [digit, numStr] = nextCharNumber(context) - while (digit != null && digit < base) { - number *= base; - number += digit; - number = appendCharNumbers(number, numStr, base) - context.popToken(); - [digit, numStr] = nextCharNumber(context) - } - } - return `\\@char{${number}}`; -}); - -// The Latin Modern font renders at the wrong vertical alignment. -// This macro provides a better rendering. -defineMacro("\\surd", "\\sqrt{}") - -defineMacro("\\hbox", "\\text{#1}"); - -// Per TeXbook p.122, "/" gets zero operator spacing. -// And MDN recommends using U+2044 instead of / for inline -defineMacro("/", "{\u2044}") - -// Since Temml has no \par, ignore \long. -defineMacro("\\long", "") - -////////////////////////////////////////////////////////////////////// -// Grouping -// \let\bgroup={ \let\egroup=} -defineMacro("\\bgroup", "{"); -defineMacro("\\egroup", "}"); - -// Symbols from latex.ltx: -// \def~{\nobreakspace{}} -// \def\lq{`} -// \def\rq{'} -// \def \aa {\r a} -defineMacro("~", "\\nobreakspace"); -defineMacro("\\lq", "`"); -defineMacro("\\rq", "'"); -defineMacro("\\aa", "\\r a"); - -defineMacro("\\Bbbk", "\\Bbb{k}"); - -// \mathstrut from the TeXbook, p 360 -defineMacro("\\mathstrut", "\\vphantom{(}"); - -// \underbar from TeXbook p 353 -defineMacro("\\underbar", "\\underline{\\text{#1}}"); - -////////////////////////////////////////////////////////////////////// -// LaTeX_2ε - -// \vdots{\vbox{\baselineskip4\p@ \lineskiplimit\z@ -// \kern6\p@\hbox{.}\hbox{.}\hbox{.}}} -// We'll call \varvdots, which gets a glyph from symbols.js. -// The zero-width rule gets us an equivalent to the vertical 6pt kern. -defineMacro("\\vdots", "\\mathord{\\varvdots\\rule{0pt}{15pt}}"); -defineMacro("\u22ee", "\\vdots"); - -////////////////////////////////////////////////////////////////////// -// amsmath.sty -// http://mirrors.concertpass.com/tex-archive/macros/latex/required/amsmath/amsmath.pdf - -//\newcommand{\substack}[1]{\subarray{c}#1\endsubarray} -defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}"); - -// \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}} -defineMacro("\\boxed", "\\fbox{$\\displaystyle{#1}$}"); - -// \def\iff{\DOTSB\;\Longleftrightarrow\;} -// \def\implies{\DOTSB\;\Longrightarrow\;} -// \def\impliedby{\DOTSB\;\Longleftarrow\;} -defineMacro("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;"); -defineMacro("\\implies", "\\DOTSB\\;\\Longrightarrow\\;"); -defineMacro("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;"); - -// AMSMath's automatic \dots, based on \mdots@@ macro. -const dotsByToken = { - ",": "\\dotsc", - "\\not": "\\dotsb", - // \keybin@ checks for the following: - "+": "\\dotsb", - "=": "\\dotsb", - "<": "\\dotsb", - ">": "\\dotsb", - "-": "\\dotsb", - "*": "\\dotsb", - ":": "\\dotsb", - // Symbols whose definition starts with \DOTSB: - "\\DOTSB": "\\dotsb", - "\\coprod": "\\dotsb", - "\\bigvee": "\\dotsb", - "\\bigwedge": "\\dotsb", - "\\biguplus": "\\dotsb", - "\\bigcap": "\\dotsb", - "\\bigcup": "\\dotsb", - "\\prod": "\\dotsb", - "\\sum": "\\dotsb", - "\\bigotimes": "\\dotsb", - "\\bigoplus": "\\dotsb", - "\\bigodot": "\\dotsb", - "\\bigsqcap": "\\dotsb", - "\\bigsqcup": "\\dotsb", - "\\And": "\\dotsb", - "\\longrightarrow": "\\dotsb", - "\\Longrightarrow": "\\dotsb", - "\\longleftarrow": "\\dotsb", - "\\Longleftarrow": "\\dotsb", - "\\longleftrightarrow": "\\dotsb", - "\\Longleftrightarrow": "\\dotsb", - "\\mapsto": "\\dotsb", - "\\longmapsto": "\\dotsb", - "\\hookrightarrow": "\\dotsb", - "\\doteq": "\\dotsb", - // Symbols whose definition starts with \mathbin: - "\\mathbin": "\\dotsb", - // Symbols whose definition starts with \mathrel: - "\\mathrel": "\\dotsb", - "\\relbar": "\\dotsb", - "\\Relbar": "\\dotsb", - "\\xrightarrow": "\\dotsb", - "\\xleftarrow": "\\dotsb", - // Symbols whose definition starts with \DOTSI: - "\\DOTSI": "\\dotsi", - "\\int": "\\dotsi", - "\\oint": "\\dotsi", - "\\iint": "\\dotsi", - "\\iiint": "\\dotsi", - "\\iiiint": "\\dotsi", - "\\idotsint": "\\dotsi", - // Symbols whose definition starts with \DOTSX: - "\\DOTSX": "\\dotsx" -}; - -defineMacro("\\dots", function(context) { - // TODO: If used in text mode, should expand to \textellipsis. - // However, in Temml, \textellipsis and \ldots behave the same - // (in text mode), and it's unlikely we'd see any of the math commands - // that affect the behavior of \dots when in text mode. So fine for now - // (until we support \ifmmode ... \else ... \fi). - let thedots = "\\dotso"; - const next = context.expandAfterFuture().text; - if (next in dotsByToken) { - thedots = dotsByToken[next]; - } else if (next.slice(0, 4) === "\\not") { - thedots = "\\dotsb"; - } else if (next in symbols.math) { - if (utils.contains(["bin", "rel"], symbols.math[next].group)) { - thedots = "\\dotsb"; - } - } - return thedots; -}); - -const spaceAfterDots = { - // \rightdelim@ checks for the following: - ")": true, - "]": true, - "\\rbrack": true, - "\\}": true, - "\\rbrace": true, - "\\rangle": true, - "\\rceil": true, - "\\rfloor": true, - "\\rgroup": true, - "\\rmoustache": true, - "\\right": true, - "\\bigr": true, - "\\biggr": true, - "\\Bigr": true, - "\\Biggr": true, - // \extra@ also tests for the following: - $: true, - // \extrap@ checks for the following: - ";": true, - ".": true, - ",": true -}; - -defineMacro("\\dotso", function(context) { - const next = context.future().text; - if (next in spaceAfterDots) { - return "\\ldots\\,"; - } else { - return "\\ldots"; - } -}); - -defineMacro("\\dotsc", function(context) { - const next = context.future().text; - // \dotsc uses \extra@ but not \extrap@, instead specially checking for - // ';' and '.', but doesn't check for ','. - if (next in spaceAfterDots && next !== ",") { - return "\\ldots\\,"; - } else { - return "\\ldots"; - } -}); - -defineMacro("\\cdots", function(context) { - const next = context.future().text; - if (next in spaceAfterDots) { - return "\\@cdots\\,"; - } else { - return "\\@cdots"; - } -}); - -defineMacro("\\dotsb", "\\cdots"); -defineMacro("\\dotsm", "\\cdots"); -defineMacro("\\dotsi", "\\!\\cdots"); -defineMacro("\\idotsint", "\\dotsi"); -// amsmath doesn't actually define \dotsx, but \dots followed by a macro -// starting with \DOTSX implies \dotso, and then \extra@ detects this case -// and forces the added `\,`. -defineMacro("\\dotsx", "\\ldots\\,"); - -// \let\DOTSI\relax -// \let\DOTSB\relax -// \let\DOTSX\relax -defineMacro("\\DOTSI", "\\relax"); -defineMacro("\\DOTSB", "\\relax"); -defineMacro("\\DOTSX", "\\relax"); - -// Spacing, based on amsmath.sty's override of LaTeX defaults -// \DeclareRobustCommand{\tmspace}[3]{% -// \ifmmode\mskip#1#2\else\kern#1#3\fi\relax} -defineMacro("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"); -// \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}} -// TODO: math mode should use \thinmuskip -defineMacro("\\,", "{\\tmspace+{3mu}{.1667em}}"); -// \let\thinspace\, -defineMacro("\\thinspace", "\\,"); -// \def\>{\mskip\medmuskip} -// \renewcommand{\:}{\tmspace+\medmuskip{.2222em}} -// TODO: \> and math mode of \: should use \medmuskip = 4mu plus 2mu minus 4mu -defineMacro("\\>", "\\mskip{4mu}"); -defineMacro("\\:", "{\\tmspace+{4mu}{.2222em}}"); -// \let\medspace\: -defineMacro("\\medspace", "\\:"); -// \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}} -// TODO: math mode should use \thickmuskip = 5mu plus 5mu -defineMacro("\\;", "{\\tmspace+{5mu}{.2777em}}"); -// \let\thickspace\; -defineMacro("\\thickspace", "\\;"); -// \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}} -// TODO: math mode should use \thinmuskip -defineMacro("\\!", "{\\tmspace-{3mu}{.1667em}}"); -// \let\negthinspace\! -defineMacro("\\negthinspace", "\\!"); -// \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}} -// TODO: math mode should use \medmuskip -defineMacro("\\negmedspace", "{\\tmspace-{4mu}{.2222em}}"); -// \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}} -// TODO: math mode should use \thickmuskip -defineMacro("\\negthickspace", "{\\tmspace-{5mu}{.277em}}"); -// \def\enspace{\kern.5em } -defineMacro("\\enspace", "\\kern.5em "); -// \def\enskip{\hskip.5em\relax} -defineMacro("\\enskip", "\\hskip.5em\\relax"); -// \def\quad{\hskip1em\relax} -defineMacro("\\quad", "\\hskip1em\\relax"); -// \def\qquad{\hskip2em\relax} -defineMacro("\\qquad", "\\hskip2em\\relax"); - -// \tag@in@display form of \tag -defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren"); -defineMacro("\\tag@paren", "\\tag@literal{({#1})}"); -defineMacro("\\tag@literal", (context) => { - if (context.macros.get("\\df@tag")) { - throw new ParseError("Multiple \\tag"); - } - return "\\def\\df@tag{\\text{#1}}"; -}); - -// \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin -// {\operator@font mod}\penalty900 -// \mkern5mu\nonscript\mskip-\medmuskip} -// \newcommand{\pod}[1]{\allowbreak -// \if@display\mkern18mu\else\mkern8mu\fi(#1)} -// \renewcommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}} -// \newcommand{\mod}[1]{\allowbreak\if@display\mkern18mu -// \else\mkern12mu\fi{\operator@font mod}\,\,#1} -// TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu -defineMacro("\\bmod", "\\mathbin{\\text{mod}}"); -defineMacro( - "\\pod", - "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)" -); -defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}"); -defineMacro( - "\\mod", - "\\allowbreak" + - "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + - "{\\rm mod}\\,\\,#1" -); - -////////////////////////////////////////////////////////////////////// -// LaTeX source2e - -// \expandafter\let\expandafter\@normalcr -// \csname\expandafter\@gobble\string\\ \endcsname -// \DeclareRobustCommand\newline{\@normalcr\relax} -defineMacro("\\newline", "\\\\\\relax"); - -// \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@} -// TODO: Doesn't normally work in math mode because \@ fails. -defineMacro("\\TeX", "\\textrm{T}\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125em\\textrm{X}"); - -defineMacro( - "\\LaTeX", - "\\textrm{L}\\kern-.35em\\raisebox{0.2em}{\\scriptstyle A}\\kern-.15em\\TeX" -); - -defineMacro( - "\\Temml", - // eslint-disable-next-line max-len - "\\textrm{T}\\kern-0.2em\\lower{0.2em}\\textrm{E}\\kern-0.08em{\\textrm{M}\\kern-0.08em\\raise{0.2em}\\textrm{M}\\kern-0.08em\\textrm{L}}" -); - -// \DeclareRobustCommand\hspace{\@ifstar\@hspacer\@hspace} -// \def\@hspace#1{\hskip #1\relax} -// \def\@hspacer#1{\vrule \@width\z@\nobreak -// \hskip #1\hskip \z@skip} -defineMacro("\\hspace", "\\@ifstar\\@hspacer\\@hspace"); -defineMacro("\\@hspace", "\\hskip #1\\relax"); -defineMacro("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax"); - -defineMacro("\\colon", `\\mathpunct{\\char"3a}`) - -////////////////////////////////////////////////////////////////////// -// mathtools.sty - -defineMacro("\\prescript", "\\pres@cript{_{#1}^{#2}}{}{#3}") - -//\providecommand\ordinarycolon{:} -defineMacro("\\ordinarycolon", `\\char"3a`); -// Raise to center on the math axis, as closely as possible. -defineMacro("\\vcentcolon", "\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}}"); -// \providecommand*\coloneq{\vcentcolon\mathrel{\mkern-1.2mu}\mathrel{-}} -defineMacro("\\coloneq", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"2212}'); -// \providecommand*\Coloneq{\dblcolon\mathrel{\mkern-1.2mu}\mathrel{-}} -defineMacro("\\Coloneq", '\\mathrel{\\char"2237\\char"2212}'); -// \providecommand*\Eqqcolon{=\mathrel{\mkern-1.2mu}\dblcolon} -defineMacro("\\Eqqcolon", '\\mathrel{\\char"3d\\char"2237}'); -// \providecommand*\Eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\dblcolon} -defineMacro("\\Eqcolon", '\\mathrel{\\char"2212\\char"2237}'); -// \providecommand*\colonapprox{\vcentcolon\mathrel{\mkern-1.2mu}\approx} -defineMacro("\\colonapprox", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"2248}'); -// \providecommand*\Colonapprox{\dblcolon\mathrel{\mkern-1.2mu}\approx} -defineMacro("\\Colonapprox", '\\mathrel{\\char"2237\\char"2248}'); -// \providecommand*\colonsim{\vcentcolon\mathrel{\mkern-1.2mu}\sim} -defineMacro("\\colonsim", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"223c}'); -// \providecommand*\Colonsim{\dblcolon\mathrel{\mkern-1.2mu}\sim} -defineMacro("\\Colonsim", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"223c}'); - -////////////////////////////////////////////////////////////////////// -// colonequals.sty - -// Alternate names for mathtools's macros: -defineMacro("\\ratio", "\\vcentcolon"); -defineMacro("\\coloncolon", "\\dblcolon"); -defineMacro("\\colonequals", "\\coloneqq"); -defineMacro("\\coloncolonequals", "\\Coloneqq"); -defineMacro("\\equalscolon", "\\eqqcolon"); -defineMacro("\\equalscoloncolon", "\\Eqqcolon"); -defineMacro("\\colonminus", "\\coloneq"); -defineMacro("\\coloncolonminus", "\\Coloneq"); -defineMacro("\\minuscolon", "\\eqcolon"); -defineMacro("\\minuscoloncolon", "\\Eqcolon"); -// \colonapprox name is same in mathtools and colonequals. -defineMacro("\\coloncolonapprox", "\\Colonapprox"); -// \colonsim name is same in mathtools and colonequals. -defineMacro("\\coloncolonsim", "\\Colonsim"); - -// Present in newtxmath, pxfonts and txfonts -defineMacro("\\notni", "\\mathrel{\\char`\u220C}"); -defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}"); -defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}"); - -////////////////////////////////////////////////////////////////////// -// From amsopn.sty -defineMacro("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}"); -defineMacro("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}"); -defineMacro("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{\\text{lim}}}"); -defineMacro("\\varliminf", "\\DOTSB\\operatorname*{\\underline{\\text{lim}}}"); -defineMacro("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{\\text{lim}}}"); -defineMacro("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{\\text{lim}}}"); - -defineMacro("\\centerdot", "{\\medspace\\rule{0.167em}{0.189em}\\medspace}") - -////////////////////////////////////////////////////////////////////// -// statmath.sty -// https://ctan.math.illinois.edu/macros/latex/contrib/statmath/statmath.pdf - -defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}"); -defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}"); -defineMacro("\\plim", "\\DOTSB\\operatorname*{plim}"); - -////////////////////////////////////////////////////////////////////// -// braket.sty -// http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf - -defineMacro("\\bra", "\\mathinner{\\langle{#1}|}"); -defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}"); -defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}"); -defineMacro("\\Bra", "\\left\\langle#1\\right|"); -defineMacro("\\Ket", "\\left|#1\\right\\rangle"); -const braketHelper = (one) => (context) => { - const left = context.consumeArg().tokens; - const middle = context.consumeArg().tokens; - const middleDouble = context.consumeArg().tokens; - const right = context.consumeArg().tokens; - const oldMiddle = context.macros.get("|"); - const oldMiddleDouble = context.macros.get("\\|"); - context.macros.beginGroup(); - const midMacro = (double) => (context) => { - if (one) { - // Only modify the first instance of | or \| - context.macros.set("|", oldMiddle); - if (middleDouble.length) { - context.macros.set("\\|", oldMiddleDouble); - } - } - let doubled = double; - if (!double && middleDouble.length) { - // Mimic \@ifnextchar - const nextToken = context.future(); - if (nextToken.text === "|") { - context.popToken(); - doubled = true; - } - } - return { - tokens: doubled ? middleDouble : middle, - numArgs: 0 - }; - }; - context.macros.set("|", midMacro(false)); - if (middleDouble.length) { - context.macros.set("\\|", midMacro(true)); - } - const arg = context.consumeArg().tokens; - const expanded = context.expandTokens([...right, ...arg, ...left]); // reversed - context.macros.endGroup(); - return { - tokens: expanded.reverse(), - numArgs: 0 - }; -}; -defineMacro("\\bra@ket", braketHelper(false)); -defineMacro("\\bra@set", braketHelper(true)); -defineMacro("\\Braket", "\\bra@ket{\\left\\langle}" + - "{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"); -defineMacro("\\Set", "\\bra@set{\\left\\{\\:}" + - "{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"); -defineMacro("\\set", "\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"); - // has no support for special || or \| - -////////////////////////////////////////////////////////////////////// -// actuarialangle.dtx -defineMacro("\\angln", "{\\angl n}"); - -////////////////////////////////////////////////////////////////////// -// derivative.sty -defineMacro("\\odv", "\\@ifstar\\odv@next\\odv@numerator"); -defineMacro("\\odv@numerator", "\\frac{\\mathrm{d}#1}{\\mathrm{d}#2}") -defineMacro("\\odv@next", "\\frac{\\mathrm{d}}{\\mathrm{d}#2}#1") -defineMacro("\\pdv", "\\@ifstar\\pdv@next\\pdv@numerator"); - -const pdvHelper = args => { - const numerator = args[0][0].text - const denoms = stringFromArg(args[1]).split(",") - const power = String(denoms.length) - const numOp = power === "1" ? "\\partial" : `\\partial^${power}` - let denominator = "" - denoms.map(e => { denominator += "\\partial " + e.trim() + "\\,"}) - return [numerator, numOp, denominator.replace(/\\,$/, "")] -} -defineMacro("\\pdv@numerator", function(context) { - const [numerator, numOp, denominator] = pdvHelper(context.consumeArgs(2)) - return `\\frac{${numOp} ${numerator}}{${denominator}}` -}) -defineMacro("\\pdv@next", function(context) { - const [numerator, numOp, denominator] = pdvHelper(context.consumeArgs(2)) - return `\\frac{${numOp}}{${denominator}} ${numerator}` -}) - -////////////////////////////////////////////////////////////////////// -// upgreek.dtx -defineMacro("\\upalpha", "\\up@greek{\\alpha}"); -defineMacro("\\upbeta", "\\up@greek{\\beta}"); -defineMacro("\\upgamma", "\\up@greek{\\gamma}"); -defineMacro("\\updelta", "\\up@greek{\\delta}"); -defineMacro("\\upepsilon", "\\up@greek{\\epsilon}"); -defineMacro("\\upzeta", "\\up@greek{\\zeta}"); -defineMacro("\\upeta", "\\up@greek{\\eta}"); -defineMacro("\\uptheta", "\\up@greek{\\theta}"); -defineMacro("\\upiota", "\\up@greek{\\iota}"); -defineMacro("\\upkappa", "\\up@greek{\\kappa}"); -defineMacro("\\uplambda", "\\up@greek{\\lambda}"); -defineMacro("\\upmu", "\\up@greek{\\mu}"); -defineMacro("\\upnu", "\\up@greek{\\nu}"); -defineMacro("\\upxi", "\\up@greek{\\xi}"); -defineMacro("\\upomicron", "\\up@greek{\\omicron}"); -defineMacro("\\uppi", "\\up@greek{\\pi}"); -defineMacro("\\upalpha", "\\up@greek{\\alpha}"); -defineMacro("\\uprho", "\\up@greek{\\rho}"); -defineMacro("\\upsigma", "\\up@greek{\\sigma}"); -defineMacro("\\uptau", "\\up@greek{\\tau}"); -defineMacro("\\upupsilon", "\\up@greek{\\upsilon}"); -defineMacro("\\upphi", "\\up@greek{\\phi}"); -defineMacro("\\upchi", "\\up@greek{\\chi}"); -defineMacro("\\uppsi", "\\up@greek{\\psi}"); -defineMacro("\\upomega", "\\up@greek{\\omega}"); - -////////////////////////////////////////////////////////////////////// -// cmll package -defineMacro("\\invamp", '\\mathbin{\\char"214b}') -defineMacro("\\parr", '\\mathbin{\\char"214b}') -defineMacro("\\with", '\\mathbin{\\char"26}') -defineMacro("\\multimapinv", '\\mathrel{\\char"27dc}') -defineMacro("\\multimapboth", '\\mathrel{\\char"29df}') -defineMacro("\\scoh", '{\\mkern5mu\\char"2322\\mkern5mu}') -defineMacro("\\sincoh", '{\\mkern5mu\\char"2323\\mkern5mu}') -defineMacro("\\coh", `{\\mkern5mu\\rule{}{0.7em}\\mathrlap{\\smash{\\raise2mu{\\char"2322}}} -{\\smash{\\lower4mu{\\char"2323}}}\\mkern5mu}`) -defineMacro("\\incoh", `{\\mkern5mu\\rule{}{0.7em}\\mathrlap{\\smash{\\raise2mu{\\char"2323}}} -{\\smash{\\lower4mu{\\char"2322}}}\\mkern5mu}`) - - -////////////////////////////////////////////////////////////////////// -// chemstyle package -defineMacro("\\standardstate", "\\text{\\tiny\\char`⦵}"); diff --git a/src/mathMLTree.js b/src/mathMLTree.js deleted file mode 100644 index 4c7bc707..00000000 --- a/src/mathMLTree.js +++ /dev/null @@ -1,175 +0,0 @@ -// -/** - * These objects store data about MathML nodes. - * The `toNode` and `toMarkup` functions create namespaced DOM nodes and - * HTML text markup respectively. - */ - -import utils from "./utils"; -import { DocumentFragment } from "./tree"; -import { createClass } from "./domTree"; - -export function newDocumentFragment(children) { - return new DocumentFragment(children); -} - -/** - * This node represents a general purpose MathML node of any type, - * for example, `"mo"` or `"mspace"`, corresponding to `` and - * `` tags). - */ -export class MathNode { - constructor(type, children, classes, style) { - this.type = type; - this.attributes = {}; - this.children = children || []; - this.classes = classes || []; - this.style = style || {}; // Used for elements - } - - /** - * Sets an attribute on a MathML node. MathML depends on attributes to convey a - * semantic content, so this is used heavily. - */ - setAttribute(name, value) { - this.attributes[name] = value; - } - - /** - * Gets an attribute on a MathML node. - */ - getAttribute(name) { - return this.attributes[name]; - } - - /** - * Converts the math node into a MathML-namespaced DOM element. - */ - toNode() { - const node = document.createElementNS("http://www.w3.org/1998/Math/MathML", this.type); - - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { - node.setAttribute(attr, this.attributes[attr]); - } - } - - if (this.classes.length > 0) { - node.className = createClass(this.classes); - } - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - for (let i = 0; i < this.children.length; i++) { - node.appendChild(this.children[i].toNode()); - } - - return node; - } - - /** - * Converts the math node into an HTML markup string. - */ - toMarkup() { - let markup = "<" + this.type; - - // Add the attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { - markup += " " + attr + '="'; - markup += utils.escape(this.attributes[attr]); - markup += '"'; - } - } - - if (this.classes.length > 0) { - markup += ` class="${utils.escape(createClass(this.classes))}"`; - } - - let styles = ""; - - // Add the styles, after hyphenation - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - styles += `${utils.hyphenate(style)}:${this.style[style]};`; - } - } - - if (styles) { - markup += ` style="${styles}"`; - } - - markup += ">"; - - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - markup += ""; - - return markup; - } - - /** - * Converts the math node into a string, similar to innerText, but escaped. - */ - toText() { - return this.children.map((child) => child.toText()).join(""); - } -} - -/** - * This node represents a piece of text. - */ -export class TextNode { - constructor(text) { - this.text = text; - } - - /** - * Converts the text node into a DOM text node. - */ - toNode() { - return document.createTextNode(this.text); - } - - /** - * Converts the text node into escaped HTML markup - * (representing the text itself). - */ - toMarkup() { - return utils.escape(this.toText()); - } - - /** - * Converts the text node into a string - * (representing the text iteself). - */ - toText() { - return this.text; - } -} - -// Do not make an the only child of a . -// An acts as its own implicit . -export const wrapWithMstyle = expression => { - let node - if (expression.length === 1 && expression[0].type === "mrow") { - node = expression.pop() - node.type = "mstyle" - } else { - node = new MathNode("mstyle", expression); - } - return node -} - -export default { - MathNode, - TextNode, - newDocumentFragment -}; diff --git a/src/parseNode.js b/src/parseNode.js deleted file mode 100644 index 9c3da07e..00000000 --- a/src/parseNode.js +++ /dev/null @@ -1,42 +0,0 @@ -import { NON_ATOMS } from "./symbols"; - -/** - * Asserts that the node is of the given type and returns it with stricter - * typing. Throws if the node's type does not match. - */ -export function assertNodeType(node, type) { - if (!node || node.type !== type) { - throw new Error( - `Expected node of type ${type}, but got ` + - (node ? `node of type ${node.type}` : String(node)) - ); - } - return node; -} - -/** - * Returns the node more strictly typed iff it is of the given type. Otherwise, - * returns null. - */ -export function assertSymbolNodeType(node) { - const typedNode = checkSymbolNodeType(node); - if (!typedNode) { - throw new Error( - `Expected node of symbol group type, but got ` + - (node ? `node of type ${node.type}` : String(node)) - ); - } - return typedNode; -} - -/** - * Returns the node more strictly typed iff it is of the given type. Otherwise, - * returns null. - */ -export function checkSymbolNodeType(node) { - if (node && (node.type === "atom" || - Object.prototype.hasOwnProperty.call(NON_ATOMS, node.type))) { - return node; - } - return null; -} diff --git a/src/parseTree.js b/src/parseTree.js deleted file mode 100644 index f1399ad4..00000000 --- a/src/parseTree.js +++ /dev/null @@ -1,40 +0,0 @@ -import Parser from "./Parser" -import ParseError from "./ParseError" - -/** - * Parses an expression using a Parser, then returns the parsed result. - */ -const parseTree = function(toParse, settings) { - if (!(typeof toParse === "string" || toParse instanceof String)) { - throw new TypeError("Temml can only parse string typed expression") - } - const parser = new Parser(toParse, settings) - // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors - delete parser.gullet.macros.current["\\df@tag"] - - let tree = parser.parse() - - // LaTeX ignores a \tag placed outside an AMS environment. - if (!(tree.length > 0 && tree[0].type && tree[0].type === "array" && tree[0].addEqnNum)) { - // If the input used \tag, it will set the \df@tag macro to the tag. - // In this case, we separately parse the tag and wrap the tree. - if (parser.gullet.macros.get("\\df@tag")) { - if (!settings.displayMode) { - throw new ParseError("\\tag works only in display mode") - } - parser.gullet.feed("\\df@tag") - tree = [ - { - type: "tag", - mode: "text", - body: tree, - tag: parser.parse() - } - ] - } - } - - return tree -} - -export default parseTree diff --git a/src/postProcess.js b/src/postProcess.js deleted file mode 100644 index c86cb268..00000000 --- a/src/postProcess.js +++ /dev/null @@ -1,57 +0,0 @@ -/* Temml Post Process - * Perform two tasks not done by Temml when it created each individual Temml element. - * Given a block of block, - * 1. At each AMS auto-numbered environment, assign an id. - * 2. Populate the text contents of each \ref & \eqref - * - * As with other Temml code, this file is released under terms of the MIT license. - * https://mit-license.org/ - */ - -export const version = "0.6.9"; - -export function postProcess(block) { - const labelMap = {} - let i = 0 - - // Get a collection of the parents of each \tag & auto-numbered equation - const parents = block.getElementsByClassName("tml-tageqn"); - for (const parent of parents) { - const eqns = parent.getElementsByClassName("tml-eqn") - if (eqns. length > 0 ) { - // AMS automatically numbered equation. - // Assign an id. - i += 1; - eqns[0].id = "tml-eqn-" + i - // No need to write a number into the text content of the element. - // A CSS counter does that even if this postProcess() function is not used. - } - // If there is a \label, add it to labelMap - const labels = parent.getElementsByClassName("tml-label") - if (labels.length === 0) { continue } - if (eqns.length > 0) { - labelMap[labels[0].id] = String(i) - } else { - const tags = parent.getElementsByClassName("tml-tag") - if (tags.length > 0) { - labelMap[labels[0].id] = tags[0].textContent - } - } - } - - // Populate \ref & \eqref text content - const refs = block.getElementsByClassName("tml-ref"); - [...refs].forEach(ref => { - let str = labelMap[ref.getAttribute("href").slice(1)]; - if (ref.className.indexOf("tml-eqref") === -1) { - // \ref. Omit parens. - str = str.replace(/^\(/, "") - str = str.replace(/\($/, "") - } { - // \eqref. Include parens - if (str.charAt(0) !== "(") { str = "(" + str } - if (str.slice(-1) !== ")") { str = str + ")" } - } - ref.textContent = str - }) -} diff --git a/src/replace.js b/src/replace.js deleted file mode 100644 index e69131fe..00000000 --- a/src/replace.js +++ /dev/null @@ -1,225 +0,0 @@ -// Chromium does not support the MathML `mathvariant` attribute. -// Instead, we replace ASCII characters with Unicode characters that -// are defined in the font as bold, italic, double-struck, etc. -// This module identifies those Unicode code points. - -// First, a few helpers. -const script = Object.freeze({ - B: 0x20EA, // Offset from ASCII B to Unicode script B - E: 0x20EB, - F: 0x20EB, - H: 0x20C3, - I: 0x20C7, - L: 0x20C6, - M: 0x20E6, - R: 0x20C9, - e: 0x20CA, - g: 0x20A3, - o: 0x20C5 -}) - -const frak = Object.freeze({ - C: 0x20EA, - H: 0x20C4, - I: 0x20C8, - R: 0x20CA, - Z: 0x20CE -}) - -const bbb = Object.freeze({ - C: 0x20BF, // blackboard bold - H: 0x20C5, - N: 0x20C7, - P: 0x20C9, - Q: 0x20C9, - R: 0x20CB, - Z: 0x20CA -}) - -const bold = Object.freeze({ - "\u03f5": 0x1D2E7, // lunate epsilon - "\u03d1": 0x1D30C, // vartheta - "\u03f0": 0x1D2EE, // varkappa - "\u03c6": 0x1D319, // varphi - "\u03f1": 0x1D2EF, // varrho - "\u03d6": 0x1D30B // varpi -}) - -const boldItalic = Object.freeze({ - "\u03f5": 0x1D35B, // lunate epsilon - "\u03d1": 0x1D380, // vartheta - "\u03f0": 0x1D362, // varkappa - "\u03c6": 0x1D38D, // varphi - "\u03f1": 0x1D363, // varrho - "\u03d6": 0x1D37F // varpi -}) - -const boldsf = Object.freeze({ - "\u03f5": 0x1D395, // lunate epsilon - "\u03d1": 0x1D3BA, // vartheta - "\u03f0": 0x1D39C, // varkappa - "\u03c6": 0x1D3C7, // varphi - "\u03f1": 0x1D39D, // varrho - "\u03d6": 0x1D3B9 // varpi -}) - -const bisf = Object.freeze({ - "\u03f5": 0x1D3CF, // lunate epsilon - "\u03d1": 0x1D3F4, // vartheta - "\u03f0": 0x1D3D6, // varkappa - "\u03c6": 0x1D401, // varphi - "\u03f1": 0x1D3D7, // varrho - "\u03d6": 0x1D3F3 // varpi -}) - -// Code point offsets below are derived from https://www.unicode.org/charts/PDF/U1D400.pdf -const offset = Object.freeze({ - upperCaseLatin: { // A-Z - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D3BF }, - "italic": ch => { return 0x1D3F3 }, - "bold-italic": ch => { return 0x1D427 }, - "script": ch => { return script[ch] || 0x1D45B }, - "script-bold": ch => { return 0x1D48F }, - "fraktur": ch => { return frak[ch] || 0x1D4C3 }, - "fraktur-bold": ch => { return 0x1D52B }, - "double-struck": ch => { return bbb[ch] || 0x1D4F7 }, - "sans-serif": ch => { return 0x1D55F }, - "sans-serif-bold": ch => { return 0x1D593 }, - "sans-serif-italic": ch => { return 0x1D5C7 }, - "sans-serif-bold-italic": ch => { return 0x1D63C }, - "monospace": ch => { return 0x1D62F } - }, - lowerCaseLatin: { // a-z - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D3B9 }, - "italic": ch => { return ch === "h" ? 0x20A6 : 0x1D3ED }, - "bold-italic": ch => { return 0x1D421 }, - "script": ch => { return script[ch] || 0x1D455 }, - "script-bold": ch => { return 0x1D489 }, - "fraktur": ch => { return 0x1D4BD }, - "fraktur-bold": ch => { return 0x1D525 }, - "double-struck": ch => { return 0x1D4F1 }, - "sans-serif": ch => { return 0x1D559 }, - "sans-serif-bold": ch => { return 0x1D58D }, - "sans-serif-italic": ch => { return 0x1D5C1 }, - "sans-serif-bold-italic": ch => { return 0x1D5F5 }, - "monospace": ch => { return 0x1D629 } - }, - upperCaseGreek: { // A-Ω ∇ - "normal": ch => { return 0 }, - "bold": ch => { return ch === "∇" ? 0x1B4BA : 0x1D317 }, - "italic": ch => { return ch === "∇" ? 0x1B4F4 : 0x1D351 }, - // \boldsymbol actually returns upright bold for upperCaseGreek - "bold-italic": ch => { return ch === "∇" ? 0x1B4BA : 0x1D317 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - // Unicode has no code points for regular-weight san-serif Greek. Use bold. - "sans-serif": ch => { return ch === "∇" ? 0x1B568 : 0x1D3C5 }, - "sans-serif-bold": ch => { return ch === "∇" ? 0x1B568 : 0x1D3C5 }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return ch === "∇" ? 0x1B5A2 : 0x1D3FF }, - "monospace": ch => { return 0 } - }, - lowerCaseGreek: { // α-ω - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D311 }, - "italic": ch => { return 0x1D34B }, - "bold-italic": ch => { return ch === "\u03d5" ? 0x1D37E : 0x1D385 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - // Unicode has no code points for regular-weight san-serif Greek. Use bold. - "sans-serif": ch => { return 0x1D3BF }, - "sans-serif-bold": ch => { return 0x1D3BF }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return 0x1D3F9 }, - "monospace": ch => { return 0 } - }, - varGreek: { // \varGamma, etc - "normal": ch => { return 0 }, - "bold": ch => { return bold[ch] || -51 }, - "italic": ch => { return 0 }, - "bold-italic": ch => { return boldItalic[ch] || 0x3A }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - "sans-serif": ch => { return boldsf[ch] || 0x74 }, - "sans-serif-bold": ch => { return boldsf[ch] || 0x74 }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return bisf[ch] || 0xAE }, - "monospace": ch => { return 0 } - }, - numeral: { // 0-9 - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D79E }, - "italic": ch => { return 0 }, - "bold-italic": ch => { return 0 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0x1D7A8 }, - "sans-serif": ch => { return 0x1D7B2 }, - "sans-serif-bold": ch => { return 0x1D7BC }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return 0 }, - "monospace": ch => { return 0x1D7C6 } - } -}) - -export const variantChar = (ch, variant) => { - const codePoint = ch.codePointAt(0) - const block = 0x40 < codePoint && codePoint < 0x5b - ? "upperCaseLatin" - : 0x60 < codePoint && codePoint < 0x7b - ? "lowerCaseLatin" - : (0x390 < codePoint && codePoint < 0x3AA) || ch === "∇" - ? "upperCaseGreek" - : 0x3B0 < codePoint && codePoint < 0x3CA || ch === "\u03d5" - ? "lowerCaseGreek" - : 0x1D6E1 < codePoint && codePoint < 0x1D6FC || bold[ch] - ? "varGreek" - : (0x2F < codePoint && codePoint < 0x3A) - ? "numeral" - : "other" - return block === "other" - ? ch - : String.fromCodePoint(codePoint + offset[block][variant](ch)) -} - -export const smallCaps = Object.freeze({ - a: "ᴀ", - b: "ʙ", - c: "ᴄ", - d: "ᴅ", - e: "ᴇ", - f: "ꜰ", - g: "ɢ", - h: "ʜ", - i: "ɪ", - j: "ᴊ", - k: "ᴋ", - l: "ʟ", - m: "ᴍ", - n: "ɴ", - o: "ᴏ", - p: "ᴘ", - q: "ǫ", - r: "ʀ", - s: "s", - t: "ᴛ", - u: "ᴜ", - v: "ᴠ", - w: "ᴡ", - x: "x", - y: "ʏ", - z: "ᴢ" -}) diff --git a/src/stretchy.js b/src/stretchy.js deleted file mode 100644 index 6877835a..00000000 --- a/src/stretchy.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * This file provides support for building horizontal stretchy elements. - */ - -import mathMLTree from "./mathMLTree" - -const stretchyCodePoint = { - widehat: "^", - widecheck: "ˇ", - widetilde: "~", - wideparen: "⏜", // \u23dc - utilde: "~", - overleftarrow: "\u2190", - underleftarrow: "\u2190", - xleftarrow: "\u2190", - overrightarrow: "\u2192", - underrightarrow: "\u2192", - xrightarrow: "\u2192", - underbrace: "\u23df", - overbrace: "\u23de", - overgroup: "\u23e0", - overparen: "⏜", - undergroup: "\u23e1", - underparen: "\u23dd", - overleftrightarrow: "\u2194", - underleftrightarrow: "\u2194", - xleftrightarrow: "\u2194", - Overrightarrow: "\u21d2", - xRightarrow: "\u21d2", - overleftharpoon: "\u21bc", - xleftharpoonup: "\u21bc", - overrightharpoon: "\u21c0", - xrightharpoonup: "\u21c0", - xLeftarrow: "\u21d0", - xLeftrightarrow: "\u21d4", - xhookleftarrow: "\u21a9", - xhookrightarrow: "\u21aa", - xmapsto: "\u21a6", - xrightharpoondown: "\u21c1", - xleftharpoondown: "\u21bd", - xtwoheadleftarrow: "\u219e", - xtwoheadrightarrow: "\u21a0", - xlongequal: "=", - xrightleftarrows: "\u21c4", - yields: "\u2192", - yieldsLeft: "\u2190", - mesomerism: "\u2194", - longrightharpoonup: "\u21c0", - longleftharpoondown: "\u21bd", - eqrightharpoonup: "\u21c0", - eqleftharpoondown: "\u21bd", - "\\cdrightarrow": "\u2192", - "\\cdleftarrow": "\u2190", - "\\cdlongequal": "=" -} - -const mathMLnode = function(label) { - const child = new mathMLTree.TextNode(stretchyCodePoint[label.slice(1)]) - const node = new mathMLTree.MathNode("mo", [child]) - node.setAttribute("stretchy", "true") - return node -} - -export default { - mathMLnode -} diff --git a/src/symbols.js b/src/symbols.js deleted file mode 100644 index 7ce42f9d..00000000 --- a/src/symbols.js +++ /dev/null @@ -1,971 +0,0 @@ -/** - * This file holds a list of all no-argument functions and single-character - * symbols (like 'a' or ';'). - * - * For each of the symbols, there are two properties they can have: - * - group (required): the ParseNode group type the symbol should have (i.e. - "textord", "mathord", etc). - * - replace: the character that this symbol or function should be - * replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi - * character in the main font). - * - * The outermost map in the table indicates what mode the symbols should be - * accepted in (e.g. "math" or "text"). - */ - -// Some of these have a "-token" suffix since these are also used as `ParseNode` -// types for raw text tokens, and we want to avoid conflicts with higher-level -// `ParseNode` types. These `ParseNode`s are constructed within `Parser` by -// looking up the `symbols` map. -export const ATOMS = { - bin: 1, - close: 1, - inner: 1, - open: 1, - punct: 1, - rel: 1 -}; -export const NON_ATOMS = { - "accent-token": 1, - mathord: 1, - "op-token": 1, - spacing: 1, - textord: 1 -}; - -const symbols = { - math: {}, - text: {} -}; -export default symbols; - -/** `acceptUnicodeChar = true` is only applicable if `replace` is set. */ -export function defineSymbol(mode, group, replace, name, acceptUnicodeChar) { - symbols[mode][name] = { group, replace }; - - if (acceptUnicodeChar && replace) { - symbols[mode][replace] = symbols[mode][name]; - } -} - -// Some abbreviations for commonly used strings. -// This helps minify the code, and also spotting typos using jshint. - -// modes: -const math = "math"; -const text = "text"; - -// groups: -const accent = "accent-token"; -const bin = "bin"; -const close = "close"; -const inner = "inner"; -const mathord = "mathord"; -const op = "op-token"; -const open = "open"; -const punct = "punct"; -const rel = "rel"; -const spacing = "spacing"; -const textord = "textord"; - -// Now comes the symbol table - -// Relation Symbols -defineSymbol(math, rel, "\u2261", "\\equiv", true); -defineSymbol(math, rel, "\u227a", "\\prec", true); -defineSymbol(math, rel, "\u227b", "\\succ", true); -defineSymbol(math, rel, "\u223c", "\\sim", true); -defineSymbol(math, rel, "\u27c2", "\\perp", true); -defineSymbol(math, rel, "\u2aaf", "\\preceq", true); -defineSymbol(math, rel, "\u2ab0", "\\succeq", true); -defineSymbol(math, rel, "\u2243", "\\simeq", true); -defineSymbol(math, rel, "\u224c", "\\backcong", true); -defineSymbol(math, rel, "|", "\\mid", true); -defineSymbol(math, rel, "\u226a", "\\ll", true); -defineSymbol(math, rel, "\u226b", "\\gg", true); -defineSymbol(math, rel, "\u224d", "\\asymp", true); -defineSymbol(math, rel, "\u2225", "\\parallel"); -defineSymbol(math, rel, "\u22c8", "\\bowtie", true); -defineSymbol(math, rel, "\u2323", "\\smile", true); -defineSymbol(math, rel, "\u2291", "\\sqsubseteq", true); -defineSymbol(math, rel, "\u2292", "\\sqsupseteq", true); -defineSymbol(math, rel, "\u2250", "\\doteq", true); -defineSymbol(math, rel, "\u2322", "\\frown", true); -defineSymbol(math, rel, "\u220b", "\\ni", true); -defineSymbol(math, rel, "\u220c", "\\notni", true); -defineSymbol(math, rel, "\u221d", "\\propto", true); -defineSymbol(math, rel, "\u22a2", "\\vdash", true); -defineSymbol(math, rel, "\u22a3", "\\dashv", true); -defineSymbol(math, rel, "\u220b", "\\owns"); -defineSymbol(math, rel, "\u2258", "\\arceq", true); -defineSymbol(math, rel, "\u2259", "\\wedgeq", true); -defineSymbol(math, rel, "\u225a", "\\veeeq", true); -defineSymbol(math, rel, "\u225b", "\\stareq", true); -defineSymbol(math, rel, "\u225d", "\\eqdef", true); -defineSymbol(math, rel, "\u225e", "\\measeq", true); -defineSymbol(math, rel, "\u225f", "\\questeq", true); -defineSymbol(math, rel, "\u2260", "\\ne", true); -defineSymbol(math, rel, "\u2260", "\\neq"); -// mathtools.sty -defineSymbol(math, rel, "\u2237", "\\dblcolon", true); -defineSymbol(math, rel, "\u2254", "\\coloneqq", true); -defineSymbol(math, rel, "\u2255", "\\eqqcolon", true); -defineSymbol(math, rel, "\u2239", "\\eqcolon", true); -defineSymbol(math, rel, "\u2A74", "\\Coloneqq", true); - -// Punctuation -defineSymbol(math, punct, "\u002e", "\\ldotp"); -defineSymbol(math, punct, "\u00b7", "\\cdotp"); - -// Misc Symbols -defineSymbol(math, textord, "\u0023", "\\#"); -defineSymbol(text, textord, "\u0023", "\\#"); -defineSymbol(math, textord, "\u0026", "\\&"); -defineSymbol(text, textord, "\u0026", "\\&"); -defineSymbol(math, textord, "\u2135", "\\aleph", true); -defineSymbol(math, textord, "\u2200", "\\forall", true); -defineSymbol(math, textord, "\u210f", "\\hbar", true); -defineSymbol(math, textord, "\u2203", "\\exists", true); -defineSymbol(math, textord, "\u2207", "\\nabla", true); -defineSymbol(math, textord, "\u266d", "\\flat", true); -defineSymbol(math, textord, "\u2113", "\\ell", true); -defineSymbol(math, textord, "\u266e", "\\natural", true); -defineSymbol(math, textord, "Å", "\\AA", true); -defineSymbol(text, textord, "Å", "\\AA", true); -defineSymbol(math, textord, "\u2663", "\\clubsuit", true); -defineSymbol(math, textord, "\u2667", "\\varclubsuit", true); -defineSymbol(math, textord, "\u2118", "\\wp", true); -defineSymbol(math, textord, "\u266f", "\\sharp", true); -defineSymbol(math, textord, "\u2662", "\\diamondsuit", true); -defineSymbol(math, textord, "\u2666", "\\vardiamondsuit", true); -defineSymbol(math, textord, "\u211c", "\\Re", true); -defineSymbol(math, textord, "\u2661", "\\heartsuit", true); -defineSymbol(math, textord, "\u2665", "\\varheartsuit", true); -defineSymbol(math, textord, "\u2111", "\\Im", true); -defineSymbol(math, textord, "\u2660", "\\spadesuit", true); -defineSymbol(math, textord, "\u2664", "\\varspadesuit", true); -defineSymbol(math, textord, "\u2640", "\\female", true); -defineSymbol(math, textord, "\u2642", "\\male", true); -defineSymbol(math, textord, "\u00a7", "\\S", true); -defineSymbol(text, textord, "\u00a7", "\\S"); -defineSymbol(math, textord, "\u00b6", "\\P", true); -defineSymbol(text, textord, "\u00b6", "\\P"); -defineSymbol(text, textord, "\u263a", "\\smiley", true); -defineSymbol(math, textord, "\u263a", "\\smiley", true); - -// Math and Text -defineSymbol(math, textord, "\u2020", "\\dag"); -defineSymbol(text, textord, "\u2020", "\\dag"); -defineSymbol(text, textord, "\u2020", "\\textdagger"); -defineSymbol(math, textord, "\u2021", "\\ddag"); -defineSymbol(text, textord, "\u2021", "\\ddag"); -defineSymbol(text, textord, "\u2021", "\\textdaggerdbl"); - -// Large Delimiters -defineSymbol(math, close, "\u23b1", "\\rmoustache", true); -defineSymbol(math, open, "\u23b0", "\\lmoustache", true); -defineSymbol(math, close, "\u27ef", "\\rgroup", true); -defineSymbol(math, open, "\u27ee", "\\lgroup", true); - -// Binary Operators -defineSymbol(math, bin, "\u2213", "\\mp", true); -defineSymbol(math, bin, "\u2296", "\\ominus", true); -defineSymbol(math, bin, "\u228e", "\\uplus", true); -defineSymbol(math, bin, "\u2293", "\\sqcap", true); -defineSymbol(math, bin, "\u2217", "\\ast"); -defineSymbol(math, bin, "\u2294", "\\sqcup", true); -defineSymbol(math, bin, "\u25ef", "\\bigcirc", true); -defineSymbol(math, bin, "\u2219", "\\bullet", true); -defineSymbol(math, bin, "\u2021", "\\ddagger"); -defineSymbol(math, bin, "\u2240", "\\wr", true); -defineSymbol(math, bin, "\u2a3f", "\\amalg"); -defineSymbol(math, bin, "\u0026", "\\And"); // from amsmath - -// Arrow Symbols -defineSymbol(math, rel, "\u27f5", "\\longleftarrow", true); -defineSymbol(math, rel, "\u21d0", "\\Leftarrow", true); -defineSymbol(math, rel, "\u27f8", "\\Longleftarrow", true); -defineSymbol(math, rel, "\u27f6", "\\longrightarrow", true); -defineSymbol(math, rel, "\u21d2", "\\Rightarrow", true); -defineSymbol(math, rel, "\u27f9", "\\Longrightarrow", true); -defineSymbol(math, rel, "\u2194", "\\leftrightarrow", true); -defineSymbol(math, rel, "\u27f7", "\\longleftrightarrow", true); -defineSymbol(math, rel, "\u21d4", "\\Leftrightarrow", true); -defineSymbol(math, rel, "\u27fa", "\\Longleftrightarrow", true); -defineSymbol(math, rel, "\u21a6", "\\mapsto", true); -defineSymbol(math, rel, "\u27fc", "\\longmapsto", true); -defineSymbol(math, rel, "\u2197", "\\nearrow", true); -defineSymbol(math, rel, "\u21a9", "\\hookleftarrow", true); -defineSymbol(math, rel, "\u21aa", "\\hookrightarrow", true); -defineSymbol(math, rel, "\u2198", "\\searrow", true); -defineSymbol(math, rel, "\u21bc", "\\leftharpoonup", true); -defineSymbol(math, rel, "\u21c0", "\\rightharpoonup", true); -defineSymbol(math, rel, "\u2199", "\\swarrow", true); -defineSymbol(math, rel, "\u21bd", "\\leftharpoondown", true); -defineSymbol(math, rel, "\u21c1", "\\rightharpoondown", true); -defineSymbol(math, rel, "\u2196", "\\nwarrow", true); -defineSymbol(math, rel, "\u21cc", "\\rightleftharpoons", true); -defineSymbol(math, mathord, "\u21af", "\\lightning", true); -defineSymbol(math, mathord, "\u2030", "\\permil", true); -defineSymbol(text, textord, "\u2030", "\\permil"); - -// AMS Negated Binary Relations -defineSymbol(math, rel, "\u226e", "\\nless", true); -// Symbol names preceeded by "@" each have a corresponding macro. -defineSymbol(math, rel, "\u2a87", "\\lneq", true); -defineSymbol(math, rel, "\u2268", "\\lneqq", true); -defineSymbol(math, rel, "\u2268\ufe00", "\\lvertneqq"); -defineSymbol(math, rel, "\u22e6", "\\lnsim", true); -defineSymbol(math, rel, "\u2a89", "\\lnapprox", true); -defineSymbol(math, rel, "\u2280", "\\nprec", true); -// unicode-math maps \u22e0 to \npreccurlyeq. We'll use the AMS synonym. -defineSymbol(math, rel, "\u22e0", "\\npreceq", true); -defineSymbol(math, rel, "\u22e8", "\\precnsim", true); -defineSymbol(math, rel, "\u2ab9", "\\precnapprox", true); -defineSymbol(math, rel, "\u2241", "\\nsim", true); -defineSymbol(math, rel, "\u2224", "\\nmid", true); -defineSymbol(math, rel, "\u2224", "\\nshortmid"); -defineSymbol(math, rel, "\u22ac", "\\nvdash", true); -defineSymbol(math, rel, "\u22ad", "\\nvDash", true); -defineSymbol(math, rel, "\u22ea", "\\ntriangleleft"); -defineSymbol(math, rel, "\u22ec", "\\ntrianglelefteq", true); -defineSymbol(math, rel, "\u2284", "\\nsubset", true); -defineSymbol(math, rel, "\u2285", "\\nsupset", true); -defineSymbol(math, rel, "\u228a", "\\subsetneq", true); -defineSymbol(math, rel, "\u228a\ufe00", "\\varsubsetneq"); -defineSymbol(math, rel, "\u2acb", "\\subsetneqq", true); -defineSymbol(math, rel, "\u2acb\ufe00", "\\varsubsetneqq"); -defineSymbol(math, rel, "\u226f", "\\ngtr", true); -defineSymbol(math, rel, "\u2a88", "\\gneq", true); -defineSymbol(math, rel, "\u2269", "\\gneqq", true); -defineSymbol(math, rel, "\u2269\ufe00", "\\gvertneqq"); -defineSymbol(math, rel, "\u22e7", "\\gnsim", true); -defineSymbol(math, rel, "\u2a8a", "\\gnapprox", true); -defineSymbol(math, rel, "\u2281", "\\nsucc", true); -// unicode-math maps \u22e1 to \nsucccurlyeq. We'll use the AMS synonym. -defineSymbol(math, rel, "\u22e1", "\\nsucceq", true); -defineSymbol(math, rel, "\u22e9", "\\succnsim", true); -defineSymbol(math, rel, "\u2aba", "\\succnapprox", true); -// unicode-math maps \u2246 to \simneqq. We'll use the AMS synonym. -defineSymbol(math, rel, "\u2246", "\\ncong", true); -defineSymbol(math, rel, "\u2226", "\\nparallel", true); -defineSymbol(math, rel, "\u2226", "\\nshortparallel"); -defineSymbol(math, rel, "\u22af", "\\nVDash", true); -defineSymbol(math, rel, "\u22eb", "\\ntriangleright"); -defineSymbol(math, rel, "\u22ed", "\\ntrianglerighteq", true); -defineSymbol(math, rel, "\u228b", "\\supsetneq", true); -defineSymbol(math, rel, "\u228b", "\\varsupsetneq"); -defineSymbol(math, rel, "\u2acc", "\\supsetneqq", true); -defineSymbol(math, rel, "\u2acc\ufe00", "\\varsupsetneqq"); -defineSymbol(math, rel, "\u22ae", "\\nVdash", true); -defineSymbol(math, rel, "\u2ab5", "\\precneqq", true); -defineSymbol(math, rel, "\u2ab6", "\\succneqq", true); -defineSymbol(math, bin, "\u22b4", "\\unlhd"); -defineSymbol(math, bin, "\u22b5", "\\unrhd"); - -// AMS Negated Arrows -defineSymbol(math, rel, "\u219a", "\\nleftarrow", true); -defineSymbol(math, rel, "\u219b", "\\nrightarrow", true); -defineSymbol(math, rel, "\u21cd", "\\nLeftarrow", true); -defineSymbol(math, rel, "\u21cf", "\\nRightarrow", true); -defineSymbol(math, rel, "\u21ae", "\\nleftrightarrow", true); -defineSymbol(math, rel, "\u21ce", "\\nLeftrightarrow", true); - -// AMS Misc -defineSymbol(math, rel, "\u25b3", "\\vartriangle"); -defineSymbol(math, textord, "\u210f", "\\hslash"); -defineSymbol(math, textord, "\u25bd", "\\triangledown"); -defineSymbol(math, textord, "\u25ca", "\\lozenge"); -defineSymbol(math, textord, "\u24c8", "\\circledS"); -defineSymbol(math, textord, "\u00ae", "\\circledR", true); -defineSymbol(text, textord, "\u00ae", "\\circledR"); -defineSymbol(text, textord, "\u00ae", "\\textregistered"); -defineSymbol(math, textord, "\u2221", "\\measuredangle", true); -defineSymbol(math, textord, "\u2204", "\\nexists"); -defineSymbol(math, textord, "\u2127", "\\mho"); -defineSymbol(math, textord, "\u2132", "\\Finv", true); -defineSymbol(math, textord, "\u2141", "\\Game", true); -defineSymbol(math, textord, "\u2035", "\\backprime"); -defineSymbol(math, textord, "\u25b2", "\\blacktriangle"); -defineSymbol(math, textord, "\u25bc", "\\blacktriangledown"); -defineSymbol(math, textord, "\u25a0", "\\blacksquare"); -defineSymbol(math, textord, "\u29eb", "\\blacklozenge"); -defineSymbol(math, textord, "\u2605", "\\bigstar"); -defineSymbol(math, textord, "\u2222", "\\sphericalangle", true); -defineSymbol(math, textord, "\u2201", "\\complement", true); -// unicode-math maps U+F0 to \matheth. We map to AMS function \eth -defineSymbol(math, textord, "\u00f0", "\\eth", true); -defineSymbol(text, textord, "\u00f0", "\u00f0"); -defineSymbol(math, textord, "\u2571", "\\diagup"); -defineSymbol(math, textord, "\u2572", "\\diagdown"); -defineSymbol(math, textord, "\u25a1", "\\square"); -defineSymbol(math, textord, "\u25a1", "\\Box"); -defineSymbol(math, textord, "\u25ca", "\\Diamond"); -// unicode-math maps U+A5 to \mathyen. We map to AMS function \yen -defineSymbol(math, textord, "\u00a5", "\\yen", true); -defineSymbol(text, textord, "\u00a5", "\\yen", true); -defineSymbol(math, textord, "\u2713", "\\checkmark", true); -defineSymbol(text, textord, "\u2713", "\\checkmark"); -defineSymbol(math, textord, "\u2717", "\\ballotx", true); -defineSymbol(text, textord, "\u2717", "\\ballotx"); -defineSymbol(text, textord, "\u2022", "\\textbullet"); - -// AMS Hebrew -defineSymbol(math, textord, "\u2136", "\\beth", true); -defineSymbol(math, textord, "\u2138", "\\daleth", true); -defineSymbol(math, textord, "\u2137", "\\gimel", true); - -// AMS Greek -defineSymbol(math, textord, "\u03dd", "\\digamma", true); -defineSymbol(math, textord, "\u03f0", "\\varkappa"); - -// AMS Delimiters -defineSymbol(math, open, "\u231C", "\\ulcorner", true); -defineSymbol(math, close, "\u231D", "\\urcorner", true); -defineSymbol(math, open, "\u231E", "\\llcorner", true); -defineSymbol(math, close, "\u231F", "\\lrcorner", true); - -// AMS Binary Relations -defineSymbol(math, rel, "\u2266", "\\leqq", true); -defineSymbol(math, rel, "\u2a7d", "\\leqslant", true); -defineSymbol(math, rel, "\u2a95", "\\eqslantless", true); -defineSymbol(math, rel, "\u2272", "\\lesssim", true); -defineSymbol(math, rel, "\u2a85", "\\lessapprox", true); -defineSymbol(math, rel, "\u224a", "\\approxeq", true); -defineSymbol(math, bin, "\u22d6", "\\lessdot"); -defineSymbol(math, rel, "\u22d8", "\\lll", true); -defineSymbol(math, rel, "\u2276", "\\lessgtr", true); -defineSymbol(math, rel, "\u22da", "\\lesseqgtr", true); -defineSymbol(math, rel, "\u2a8b", "\\lesseqqgtr", true); -defineSymbol(math, rel, "\u2251", "\\doteqdot"); -defineSymbol(math, rel, "\u2253", "\\risingdotseq", true); -defineSymbol(math, rel, "\u2252", "\\fallingdotseq", true); -defineSymbol(math, rel, "\u223d", "\\backsim", true); -defineSymbol(math, rel, "\u22cd", "\\backsimeq", true); -defineSymbol(math, rel, "\u2ac5", "\\subseteqq", true); -defineSymbol(math, rel, "\u22d0", "\\Subset", true); -defineSymbol(math, rel, "\u228f", "\\sqsubset", true); -defineSymbol(math, rel, "\u227c", "\\preccurlyeq", true); -defineSymbol(math, rel, "\u22de", "\\curlyeqprec", true); -defineSymbol(math, rel, "\u227e", "\\precsim", true); -defineSymbol(math, rel, "\u2ab7", "\\precapprox", true); -defineSymbol(math, rel, "\u22b2", "\\vartriangleleft"); -defineSymbol(math, rel, "\u22b4", "\\trianglelefteq"); -defineSymbol(math, rel, "\u22a8", "\\vDash", true); -defineSymbol(math, rel, "\u22aa", "\\Vvdash", true); -defineSymbol(math, rel, "\u2323", "\\smallsmile"); -defineSymbol(math, rel, "\u2322", "\\smallfrown"); -defineSymbol(math, rel, "\u224f", "\\bumpeq", true); -defineSymbol(math, rel, "\u224e", "\\Bumpeq", true); -defineSymbol(math, rel, "\u2267", "\\geqq", true); -defineSymbol(math, rel, "\u2a7e", "\\geqslant", true); -defineSymbol(math, rel, "\u2a96", "\\eqslantgtr", true); -defineSymbol(math, rel, "\u2273", "\\gtrsim", true); -defineSymbol(math, rel, "\u2a86", "\\gtrapprox", true); -defineSymbol(math, bin, "\u22d7", "\\gtrdot"); -defineSymbol(math, rel, "\u22d9", "\\ggg", true); -defineSymbol(math, rel, "\u2277", "\\gtrless", true); -defineSymbol(math, rel, "\u22db", "\\gtreqless", true); -defineSymbol(math, rel, "\u2a8c", "\\gtreqqless", true); -defineSymbol(math, rel, "\u2256", "\\eqcirc", true); -defineSymbol(math, rel, "\u2257", "\\circeq", true); -defineSymbol(math, rel, "\u225c", "\\triangleq", true); -defineSymbol(math, rel, "\u223c", "\\thicksim"); -defineSymbol(math, rel, "\u2248", "\\thickapprox"); -defineSymbol(math, rel, "\u2ac6", "\\supseteqq", true); -defineSymbol(math, rel, "\u22d1", "\\Supset", true); -defineSymbol(math, rel, "\u2290", "\\sqsupset", true); -defineSymbol(math, rel, "\u227d", "\\succcurlyeq", true); -defineSymbol(math, rel, "\u22df", "\\curlyeqsucc", true); -defineSymbol(math, rel, "\u227f", "\\succsim", true); -defineSymbol(math, rel, "\u2ab8", "\\succapprox", true); -defineSymbol(math, rel, "\u22b3", "\\vartriangleright"); -defineSymbol(math, rel, "\u22b5", "\\trianglerighteq"); -defineSymbol(math, rel, "\u22a9", "\\Vdash", true); -defineSymbol(math, rel, "\u2223", "\\shortmid"); -defineSymbol(math, rel, "\u2225", "\\shortparallel"); -defineSymbol(math, rel, "\u226c", "\\between", true); -defineSymbol(math, rel, "\u22d4", "\\pitchfork", true); -defineSymbol(math, rel, "\u221d", "\\varpropto"); -defineSymbol(math, rel, "\u25c0", "\\blacktriangleleft"); -// unicode-math says that \therefore is a mathord atom. -// We kept the amssymb atom type, which is rel. -defineSymbol(math, rel, "\u2234", "\\therefore", true); -defineSymbol(math, rel, "\u220d", "\\backepsilon"); -defineSymbol(math, rel, "\u25b6", "\\blacktriangleright"); -// unicode-math says that \because is a mathord atom. -// We kept the amssymb atom type, which is rel. -defineSymbol(math, rel, "\u2235", "\\because", true); -defineSymbol(math, rel, "\u22d8", "\\llless"); -defineSymbol(math, rel, "\u22d9", "\\gggtr"); -defineSymbol(math, bin, "\u22b2", "\\lhd"); -defineSymbol(math, bin, "\u22b3", "\\rhd"); -defineSymbol(math, rel, "\u2242", "\\eqsim", true); -defineSymbol(math, rel, "\u22c8", "\\Join"); -defineSymbol(math, rel, "\u2251", "\\Doteq", true); -defineSymbol(math, rel, "\u297d", "\\strictif", true); -defineSymbol(math, rel, "\u297c", "\\strictfi", true); - -// AMS Binary Operators -defineSymbol(math, bin, "\u2214", "\\dotplus", true); -defineSymbol(math, bin, "\u2216", "\\smallsetminus"); -defineSymbol(math, bin, "\u22d2", "\\Cap", true); -defineSymbol(math, bin, "\u22d3", "\\Cup", true); -defineSymbol(math, bin, "\u2a5e", "\\doublebarwedge", true); -defineSymbol(math, bin, "\u229f", "\\boxminus", true); -defineSymbol(math, bin, "\u229e", "\\boxplus", true); -defineSymbol(math, bin, "\u22c7", "\\divideontimes", true); -defineSymbol(math, bin, "\u22c9", "\\ltimes", true); -defineSymbol(math, bin, "\u22ca", "\\rtimes", true); -defineSymbol(math, bin, "\u22cb", "\\leftthreetimes", true); -defineSymbol(math, bin, "\u22cc", "\\rightthreetimes", true); -defineSymbol(math, bin, "\u22cf", "\\curlywedge", true); -defineSymbol(math, bin, "\u22ce", "\\curlyvee", true); -defineSymbol(math, bin, "\u229d", "\\circleddash", true); -defineSymbol(math, bin, "\u229b", "\\circledast", true); -defineSymbol(math, bin, "\u22ba", "\\intercal", true); -defineSymbol(math, bin, "\u22d2", "\\doublecap"); -defineSymbol(math, bin, "\u22d3", "\\doublecup"); -defineSymbol(math, bin, "\u22a0", "\\boxtimes", true); - -// AMS Arrows -// Note: unicode-math maps \u21e2 to their own function \rightdasharrow. -// We'll map it to AMS function \dashrightarrow. It produces the same atom. -defineSymbol(math, rel, "\u21e2", "\\dashrightarrow", true); -// unicode-math maps \u21e0 to \leftdasharrow. We'll use the AMS synonym. -defineSymbol(math, rel, "\u21e0", "\\dashleftarrow", true); -defineSymbol(math, rel, "\u21c7", "\\leftleftarrows", true); -defineSymbol(math, rel, "\u21c6", "\\leftrightarrows", true); -defineSymbol(math, rel, "\u21da", "\\Lleftarrow", true); -defineSymbol(math, rel, "\u219e", "\\twoheadleftarrow", true); -defineSymbol(math, rel, "\u21a2", "\\leftarrowtail", true); -defineSymbol(math, rel, "\u21ab", "\\looparrowleft", true); -defineSymbol(math, rel, "\u21cb", "\\leftrightharpoons", true); -defineSymbol(math, rel, "\u21b6", "\\curvearrowleft", true); -// unicode-math maps \u21ba to \acwopencirclearrow. We'll use the AMS synonym. -defineSymbol(math, rel, "\u21ba", "\\circlearrowleft", true); -defineSymbol(math, rel, "\u21b0", "\\Lsh", true); -defineSymbol(math, rel, "\u21c8", "\\upuparrows", true); -defineSymbol(math, rel, "\u21bf", "\\upharpoonleft", true); -defineSymbol(math, rel, "\u21c3", "\\downharpoonleft", true); -defineSymbol(math, rel, "\u22b6", "\\origof", true); -defineSymbol(math, rel, "\u22b7", "\\imageof", true); -defineSymbol(math, rel, "\u22b8", "\\multimap", true); -defineSymbol(math, rel, "\u21ad", "\\leftrightsquigarrow", true); -defineSymbol(math, rel, "\u21c9", "\\rightrightarrows", true); -defineSymbol(math, rel, "\u21c4", "\\rightleftarrows", true); -defineSymbol(math, rel, "\u21a0", "\\twoheadrightarrow", true); -defineSymbol(math, rel, "\u21a3", "\\rightarrowtail", true); -defineSymbol(math, rel, "\u21ac", "\\looparrowright", true); -defineSymbol(math, rel, "\u21b7", "\\curvearrowright", true); -// unicode-math maps \u21bb to \cwopencirclearrow. We'll use the AMS synonym. -defineSymbol(math, rel, "\u21bb", "\\circlearrowright", true); -defineSymbol(math, rel, "\u21b1", "\\Rsh", true); -defineSymbol(math, rel, "\u21ca", "\\downdownarrows", true); -defineSymbol(math, rel, "\u21be", "\\upharpoonright", true); -defineSymbol(math, rel, "\u21c2", "\\downharpoonright", true); -defineSymbol(math, rel, "\u21dd", "\\rightsquigarrow", true); -defineSymbol(math, rel, "\u21dd", "\\leadsto"); -defineSymbol(math, rel, "\u21db", "\\Rrightarrow", true); -defineSymbol(math, rel, "\u21be", "\\restriction"); - -defineSymbol(math, textord, "\u2018", "`"); -defineSymbol(math, textord, "$", "\\$"); -defineSymbol(text, textord, "$", "\\$"); -defineSymbol(text, textord, "$", "\\textdollar"); -defineSymbol(math, textord, "%", "\\%"); -defineSymbol(text, textord, "%", "\\%"); -defineSymbol(math, textord, "_", "\\_"); -defineSymbol(text, textord, "_", "\\_"); -defineSymbol(text, textord, "_", "\\textunderscore"); -defineSymbol(text, textord, "\u2423", "\\textvisiblespace", true); -defineSymbol(math, textord, "\u2220", "\\angle", true); -defineSymbol(math, textord, "\u221e", "\\infty", true); -defineSymbol(math, textord, "\u2032", "\\prime"); -defineSymbol(math, textord, "\u25b3", "\\triangle"); -defineSymbol(text, textord, "\u0391", "\\Alpha", true); -defineSymbol(text, textord, "\u0392", "\\Beta", true); -defineSymbol(text, textord, "\u0393", "\\Gamma", true); -defineSymbol(text, textord, "\u0394", "\\Delta", true); -defineSymbol(text, textord, "\u0395", "\\Epsilon", true); -defineSymbol(text, textord, "\u0396", "\\Zeta", true); -defineSymbol(text, textord, "\u0397", "\\Eta", true); -defineSymbol(text, textord, "\u0398", "\\Theta", true); -defineSymbol(text, textord, "\u0399", "\\Iota", true); -defineSymbol(text, textord, "\u039a", "\\Kappa", true); -defineSymbol(text, textord, "\u039b", "\\Lambda", true); -defineSymbol(text, textord, "\u039c", "\\Mu", true); -defineSymbol(text, textord, "\u039d", "\\Nu", true); -defineSymbol(text, textord, "\u039e", "\\Xi", true); -defineSymbol(text, textord, "\u039f", "\\Omicron", true); -defineSymbol(text, textord, "\u03a0", "\\Pi", true); -defineSymbol(text, textord, "\u03a1", "\\Rho", true); -defineSymbol(text, textord, "\u03a3", "\\Sigma", true); -defineSymbol(text, textord, "\u03a4", "\\Tau", true); -defineSymbol(text, textord, "\u03a5", "\\Upsilon", true); -defineSymbol(text, textord, "\u03a6", "\\Phi", true); -defineSymbol(text, textord, "\u03a7", "\\Chi", true); -defineSymbol(text, textord, "\u03a8", "\\Psi", true); -defineSymbol(text, textord, "\u03a9", "\\Omega", true); -defineSymbol(math, mathord, "\u0391", "\\Alpha", true); -defineSymbol(math, mathord, "\u0392", "\\Beta", true); -defineSymbol(math, mathord, "\u0393", "\\Gamma", true); -defineSymbol(math, mathord, "\u0394", "\\Delta", true); -defineSymbol(math, mathord, "\u0395", "\\Epsilon", true); -defineSymbol(math, mathord, "\u0396", "\\Zeta", true); -defineSymbol(math, mathord, "\u0397", "\\Eta", true); -defineSymbol(math, mathord, "\u0398", "\\Theta", true); -defineSymbol(math, mathord, "\u0399", "\\Iota", true); -defineSymbol(math, mathord, "\u039a", "\\Kappa", true); -defineSymbol(math, mathord, "\u039b", "\\Lambda", true); -defineSymbol(math, mathord, "\u039c", "\\Mu", true); -defineSymbol(math, mathord, "\u039d", "\\Nu", true); -defineSymbol(math, mathord, "\u039e", "\\Xi", true); -defineSymbol(math, mathord, "\u039f", "\\Omicron", true); -defineSymbol(math, mathord, "\u03a0", "\\Pi", true); -defineSymbol(math, mathord, "\u03a1", "\\Rho", true); -defineSymbol(math, mathord, "\u03a3", "\\Sigma", true); -defineSymbol(math, mathord, "\u03a4", "\\Tau", true); -defineSymbol(math, mathord, "\u03a5", "\\Upsilon", true); -defineSymbol(math, mathord, "\u03a6", "\\Phi", true); -defineSymbol(math, mathord, "\u03a7", "\\Chi", true); -defineSymbol(math, mathord, "\u03a8", "\\Psi", true); -defineSymbol(math, mathord, "\u03a9", "\\Omega", true); -defineSymbol(math, open, "\u00ac", "\\neg", true); -defineSymbol(math, open, "\u00ac", "\\lnot"); -defineSymbol(math, textord, "\u22a4", "\\top"); -defineSymbol(math, textord, "\u22a5", "\\bot"); -defineSymbol(math, textord, "\u2205", "\\emptyset"); -defineSymbol(math, textord, "\u00f8", "\\varnothing"); -defineSymbol(math, mathord, "\u03b1", "\\alpha", true); -defineSymbol(math, mathord, "\u03b2", "\\beta", true); -defineSymbol(math, mathord, "\u03b3", "\\gamma", true); -defineSymbol(math, mathord, "\u03b4", "\\delta", true); -defineSymbol(math, mathord, "\u03f5", "\\epsilon", true); -defineSymbol(math, mathord, "\u03b6", "\\zeta", true); -defineSymbol(math, mathord, "\u03b7", "\\eta", true); -defineSymbol(math, mathord, "\u03b8", "\\theta", true); -defineSymbol(math, mathord, "\u03b9", "\\iota", true); -defineSymbol(math, mathord, "\u03ba", "\\kappa", true); -defineSymbol(math, mathord, "\u03bb", "\\lambda", true); -defineSymbol(math, mathord, "\u03bc", "\\mu", true); -defineSymbol(math, mathord, "\u03bd", "\\nu", true); -defineSymbol(math, mathord, "\u03be", "\\xi", true); -defineSymbol(math, mathord, "\u03bf", "\\omicron", true); -defineSymbol(math, mathord, "\u03c0", "\\pi", true); -defineSymbol(math, mathord, "\u03c1", "\\rho", true); -defineSymbol(math, mathord, "\u03c3", "\\sigma", true); -defineSymbol(math, mathord, "\u03c4", "\\tau", true); -defineSymbol(math, mathord, "\u03c5", "\\upsilon", true); -defineSymbol(math, mathord, "\u03d5", "\\phi", true); -defineSymbol(math, mathord, "\u03c7", "\\chi", true); -defineSymbol(math, mathord, "\u03c8", "\\psi", true); -defineSymbol(math, mathord, "\u03c9", "\\omega", true); -defineSymbol(math, mathord, "\u03b5", "\\varepsilon", true); -defineSymbol(math, mathord, "\u03d1", "\\vartheta", true); -defineSymbol(math, mathord, "\u03d6", "\\varpi", true); -defineSymbol(math, mathord, "\u03f1", "\\varrho", true); -defineSymbol(math, mathord, "\u03c2", "\\varsigma", true); -defineSymbol(math, mathord, "\u03c6", "\\varphi", true); -defineSymbol(math, mathord, "\u03d8", "\\Coppa", true); -defineSymbol(math, mathord, "\u03d9", "\\coppa", true); -defineSymbol(math, mathord, "\u03d9", "\\varcoppa", true); -defineSymbol(math, mathord, "\u03de", "\\Koppa", true); -defineSymbol(math, mathord, "\u03df", "\\koppa", true); -defineSymbol(math, mathord, "\u03e0", "\\Sampi", true); -defineSymbol(math, mathord, "\u03e1", "\\sampi", true); -defineSymbol(math, mathord, "\u03da", "\\Stigma", true); -defineSymbol(math, mathord, "\u03db", "\\stigma", true); -defineSymbol(math, mathord, "\u2aeb", "\\Bot"); -defineSymbol(math, bin, "\u2217", "\u2217", true); -defineSymbol(math, bin, "+", "+"); -defineSymbol(math, bin, "*", "*"); -defineSymbol(math, bin, "\u2044", "\u2044"); -defineSymbol(math, bin, "\u2212", "-", true); -defineSymbol(math, bin, "\u22c5", "\\cdot", true); -defineSymbol(math, bin, "\u2218", "\\circ", true); -defineSymbol(math, bin, "\u00f7", "\\div", true); -defineSymbol(math, bin, "\u00b1", "\\pm", true); -defineSymbol(math, bin, "\u00d7", "\\times", true); -defineSymbol(math, bin, "\u2229", "\\cap", true); -defineSymbol(math, bin, "\u222a", "\\cup", true); -defineSymbol(math, bin, "\u2216", "\\setminus", true); -defineSymbol(math, bin, "\u2227", "\\land"); -defineSymbol(math, bin, "\u2228", "\\lor"); -defineSymbol(math, bin, "\u2227", "\\wedge", true); -defineSymbol(math, bin, "\u2228", "\\vee", true); -defineSymbol(math, open, "\u27e6", "\\llbracket", true); // stmaryrd/semantic packages -defineSymbol(math, close, "\u27e7", "\\rrbracket", true); -defineSymbol(math, open, "\u27e8", "\\langle", true); -defineSymbol(math, open, "|", "\\lvert"); -defineSymbol(math, open, "\u2016", "\\lVert"); -defineSymbol(math, textord, "!", "\\oc"); // cmll package -defineSymbol(math, textord, "?", "\\wn"); -defineSymbol(math, textord, "\u2193", "\\shpos"); -defineSymbol(math, textord, "\u2195", "\\shift"); -defineSymbol(math, textord, "\u2191", "\\shneg"); -defineSymbol(math, close, "?", "?"); -defineSymbol(math, close, "!", "!"); -defineSymbol(math, close, "‼", "‼"); -defineSymbol(math, close, "\u27e9", "\\rangle", true); -defineSymbol(math, close, "|", "\\rvert"); -defineSymbol(math, close, "\u2016", "\\rVert"); -defineSymbol(math, open, "\u2983", "\\lBrace", true); // stmaryrd/semantic packages -defineSymbol(math, close, "\u2984", "\\rBrace", true); -defineSymbol(math, rel, "=", "\\equal", true); -defineSymbol(math, rel, ":", ":"); -defineSymbol(math, rel, "\u2248", "\\approx", true); -defineSymbol(math, rel, "\u2245", "\\cong", true); -defineSymbol(math, rel, "\u2265", "\\ge"); -defineSymbol(math, rel, "\u2265", "\\geq", true); -defineSymbol(math, rel, "\u2190", "\\gets"); -defineSymbol(math, rel, ">", "\\gt", true); -defineSymbol(math, rel, "\u2208", "\\in", true); -defineSymbol(math, rel, "\u2209", "\\notin", true); -defineSymbol(math, rel, "\ue020", "\\@not"); -defineSymbol(math, rel, "\u2282", "\\subset", true); -defineSymbol(math, rel, "\u2283", "\\supset", true); -defineSymbol(math, rel, "\u2286", "\\subseteq", true); -defineSymbol(math, rel, "\u2287", "\\supseteq", true); -defineSymbol(math, rel, "\u2288", "\\nsubseteq", true); -defineSymbol(math, rel, "\u2288", "\\nsubseteqq"); -defineSymbol(math, rel, "\u2289", "\\nsupseteq", true); -defineSymbol(math, rel, "\u2289", "\\nsupseteqq"); -defineSymbol(math, rel, "\u22a8", "\\models"); -defineSymbol(math, rel, "\u2190", "\\leftarrow", true); -defineSymbol(math, rel, "\u2264", "\\le"); -defineSymbol(math, rel, "\u2264", "\\leq", true); -defineSymbol(math, rel, "<", "\\lt", true); -defineSymbol(math, rel, "\u2192", "\\rightarrow", true); -defineSymbol(math, rel, "\u2192", "\\to"); -defineSymbol(math, rel, "\u2271", "\\ngeq", true); -defineSymbol(math, rel, "\u2271", "\\ngeqq"); -defineSymbol(math, rel, "\u2271", "\\ngeqslant"); -defineSymbol(math, rel, "\u2270", "\\nleq", true); -defineSymbol(math, rel, "\u2270", "\\nleqq"); -defineSymbol(math, rel, "\u2270", "\\nleqslant"); -defineSymbol(math, rel, "\u2aeb", "\\Perp", true); //cmll package -defineSymbol(math, spacing, "\u00a0", "\\ "); -defineSymbol(math, spacing, "\u00a0", "\\space"); -// Ref: LaTeX Source 2e: \DeclareRobustCommand{\nobreakspace}{% -defineSymbol(math, spacing, "\u00a0", "\\nobreakspace"); -defineSymbol(text, spacing, "\u00a0", "\\ "); -defineSymbol(text, spacing, "\u00a0", " "); -defineSymbol(text, spacing, "\u00a0", "\\space"); -defineSymbol(text, spacing, "\u00a0", "\\nobreakspace"); -defineSymbol(math, spacing, null, "\\nobreak"); -defineSymbol(math, spacing, null, "\\allowbreak"); -defineSymbol(math, punct, ",", ","); -defineSymbol(text, punct, ":", ":"); -defineSymbol(math, punct, ";", ";"); -defineSymbol(math, bin, "\u22bc", "\\barwedge", true); -defineSymbol(math, bin, "\u22bb", "\\veebar", true); -defineSymbol(math, bin, "\u2299", "\\odot", true); -defineSymbol(math, bin, "\u2295", "\\oplus", true); -defineSymbol(math, bin, "\u2297", "\\otimes", true); -defineSymbol(math, textord, "\u2202", "\\partial", true); -defineSymbol(math, bin, "\u2298", "\\oslash", true); -defineSymbol(math, bin, "\u229a", "\\circledcirc", true); -defineSymbol(math, bin, "\u22a1", "\\boxdot", true); -defineSymbol(math, bin, "\u25b3", "\\bigtriangleup"); -defineSymbol(math, bin, "\u25bd", "\\bigtriangledown"); -defineSymbol(math, bin, "\u2020", "\\dagger"); -defineSymbol(math, bin, "\u22c4", "\\diamond"); -defineSymbol(math, bin, "\u22c6", "\\star"); -defineSymbol(math, bin, "\u25c3", "\\triangleleft"); -defineSymbol(math, bin, "\u25b9", "\\triangleright"); -defineSymbol(math, open, "{", "\\{"); -defineSymbol(text, textord, "{", "\\{"); -defineSymbol(text, textord, "{", "\\textbraceleft"); -defineSymbol(math, close, "}", "\\}"); -defineSymbol(text, textord, "}", "\\}"); -defineSymbol(text, textord, "}", "\\textbraceright"); -defineSymbol(math, open, "{", "\\lbrace"); -defineSymbol(math, close, "}", "\\rbrace"); -defineSymbol(math, open, "[", "\\lbrack", true); -defineSymbol(text, textord, "[", "\\lbrack", true); -defineSymbol(math, close, "]", "\\rbrack", true); -defineSymbol(text, textord, "]", "\\rbrack", true); -defineSymbol(math, open, "(", "\\lparen", true); -defineSymbol(math, close, ")", "\\rparen", true); -defineSymbol(text, textord, "<", "\\textless", true); // in T1 fontenc -defineSymbol(text, textord, ">", "\\textgreater", true); // in T1 fontenc -defineSymbol(math, open, "\u230a", "\\lfloor", true); -defineSymbol(math, close, "\u230b", "\\rfloor", true); -defineSymbol(math, open, "\u2308", "\\lceil", true); -defineSymbol(math, close, "\u2309", "\\rceil", true); -defineSymbol(math, textord, "\\", "\\backslash"); -defineSymbol(math, textord, "|", "|"); -defineSymbol(math, textord, "|", "\\vert"); -defineSymbol(text, textord, "|", "\\textbar", true); // in T1 fontenc -defineSymbol(math, textord, "\u2016", "\\|"); -defineSymbol(math, textord, "\u2016", "\\Vert"); -defineSymbol(text, textord, "\u2016", "\\textbardbl"); -defineSymbol(text, textord, "~", "\\textasciitilde"); -defineSymbol(text, textord, "\\", "\\textbackslash"); -defineSymbol(text, textord, "^", "\\textasciicircum"); -defineSymbol(math, rel, "\u2191", "\\uparrow", true); -defineSymbol(math, rel, "\u21d1", "\\Uparrow", true); -defineSymbol(math, rel, "\u2193", "\\downarrow", true); -defineSymbol(math, rel, "\u21d3", "\\Downarrow", true); -defineSymbol(math, rel, "\u2195", "\\updownarrow", true); -defineSymbol(math, rel, "\u21d5", "\\Updownarrow", true); -defineSymbol(math, op, "\u2210", "\\coprod"); -defineSymbol(math, op, "\u22c1", "\\bigvee"); -defineSymbol(math, op, "\u22c0", "\\bigwedge"); -defineSymbol(math, op, "\u2a04", "\\biguplus"); -defineSymbol(math, op, "\u22c2", "\\bigcap"); -defineSymbol(math, op, "\u22c3", "\\bigcup"); -defineSymbol(math, op, "\u222b", "\\int"); -defineSymbol(math, op, "\u222b", "\\intop"); -defineSymbol(math, op, "\u222c", "\\iint"); -defineSymbol(math, op, "\u222d", "\\iiint"); -defineSymbol(math, op, "\u220f", "\\prod"); -defineSymbol(math, op, "\u2211", "\\sum"); -defineSymbol(math, op, "\u2a02", "\\bigotimes"); -defineSymbol(math, op, "\u2a01", "\\bigoplus"); -defineSymbol(math, op, "\u2a00", "\\bigodot"); -defineSymbol(math, op, "\u222e", "\\oint"); -defineSymbol(math, op, "\u222f", "\\oiint"); -defineSymbol(math, op, "\u2230", "\\oiiint"); -defineSymbol(math, op, "\u2231", "\\intclockwise"); -defineSymbol(math, op, "\u2232", "\\varointclockwise"); -defineSymbol(math, op, "\u2a0c", "\\iiiint"); -defineSymbol(math, op, "\u2a0d", "\\intbar"); -defineSymbol(math, op, "\u2a0e", "\\intBar"); -defineSymbol(math, op, "\u2a0f", "\\fint"); -defineSymbol(math, op, "\u2a12", "\\rppolint"); -defineSymbol(math, op, "\u2a13", "\\scpolint"); -defineSymbol(math, op, "\u2a15", "\\pointint"); -defineSymbol(math, op, "\u2a16", "\\sqint"); -defineSymbol(math, op, "\u2a17", "\\intlarhk"); -defineSymbol(math, op, "\u2a18", "\\intx"); -defineSymbol(math, op, "\u2a19", "\\intcap"); -defineSymbol(math, op, "\u2a1a", "\\intcup"); -defineSymbol(math, op, "\u2a05", "\\bigsqcap"); -defineSymbol(math, op, "\u2a06", "\\bigsqcup"); -defineSymbol(math, op, "\u222b", "\\smallint"); -defineSymbol(text, inner, "\u2026", "\\textellipsis"); -defineSymbol(math, inner, "\u2026", "\\mathellipsis"); -defineSymbol(text, inner, "\u2026", "\\ldots", true); -defineSymbol(math, inner, "\u2026", "\\ldots", true); -defineSymbol(math, inner, "\u22f0", "\\iddots", true); -defineSymbol(math, inner, "\u22ef", "\\@cdots", true); -defineSymbol(math, inner, "\u22f1", "\\ddots", true); -defineSymbol(math, textord, "\u22ee", "\\varvdots"); // \vdots is a macro -defineSymbol(math, accent, "\u02ca", "\\acute"); -defineSymbol(math, accent, "\u0060", "\\grave"); -defineSymbol(math, accent, "\u00a8", "\\ddot"); -defineSymbol(math, accent, "\u20db", "\\dddot"); -defineSymbol(math, accent, "\u20dc", "\\ddddot"); -defineSymbol(math, accent, "\u007e", "\\tilde"); -defineSymbol(math, accent, "\u203e", "\\bar"); -defineSymbol(math, accent, "\u02d8", "\\breve"); -defineSymbol(math, accent, "\u02c7", "\\check"); -defineSymbol(math, accent, "\u005e", "\\hat"); -defineSymbol(math, accent, "\u20d7", "\\vec"); -defineSymbol(math, accent, "\u02d9", "\\dot"); -defineSymbol(math, accent, "\u02da", "\\mathring"); -defineSymbol(math, mathord, "\u0131", "\\imath", true); -defineSymbol(math, mathord, "\u0237", "\\jmath", true); -defineSymbol(math, textord, "\u0131", "\u0131"); -defineSymbol(math, textord, "\u0237", "\u0237"); -defineSymbol(text, textord, "\u0131", "\\i", true); -defineSymbol(text, textord, "\u0237", "\\j", true); -defineSymbol(text, textord, "\u00df", "\\ss", true); -defineSymbol(text, textord, "\u00e6", "\\ae", true); -defineSymbol(text, textord, "\u0153", "\\oe", true); -defineSymbol(text, textord, "\u00f8", "\\o", true); -defineSymbol(math, mathord, "\u00f8", "\\o", true); -defineSymbol(text, textord, "\u00c6", "\\AE", true); -defineSymbol(text, textord, "\u0152", "\\OE", true); -defineSymbol(text, textord, "\u00d8", "\\O", true); -defineSymbol(math, mathord, "\u00d8", "\\O", true); -defineSymbol(text, accent, "\u02ca", "\\'"); // acute -defineSymbol(text, accent, "\u02cb", "\\`"); // grave -defineSymbol(text, accent, "\u02c6", "\\^"); // circumflex -defineSymbol(text, accent, "\u02dc", "\\~"); // tilde -defineSymbol(text, accent, "\u02c9", "\\="); // macron -defineSymbol(text, accent, "\u02d8", "\\u"); // breve -defineSymbol(text, accent, "\u02d9", "\\."); // dot above -defineSymbol(text, accent, "\u00b8", "\\c"); // cedilla -defineSymbol(text, accent, "\u02da", "\\r"); // ring above -defineSymbol(text, accent, "\u02c7", "\\v"); // caron -defineSymbol(text, accent, "\u00a8", '\\"'); // diaresis -defineSymbol(text, accent, "\u02dd", "\\H"); // double acute -defineSymbol(math, accent, "\u02ca", "\\'"); // acute -defineSymbol(math, accent, "\u02cb", "\\`"); // grave -defineSymbol(math, accent, "\u02c6", "\\^"); // circumflex -defineSymbol(math, accent, "\u02dc", "\\~"); // tilde -defineSymbol(math, accent, "\u02c9", "\\="); // macron -defineSymbol(math, accent, "\u02d8", "\\u"); // breve -defineSymbol(math, accent, "\u02d9", "\\."); // dot above -defineSymbol(math, accent, "\u00b8", "\\c"); // cedilla -defineSymbol(math, accent, "\u02da", "\\r"); // ring above -defineSymbol(math, accent, "\u02c7", "\\v"); // caron -defineSymbol(math, accent, "\u00a8", '\\"'); // diaresis -defineSymbol(math, accent, "\u02dd", "\\H"); // double acute - -// These ligatures are detected and created in Parser.js's `formLigatures`. -export const ligatures = { - "--": true, - "---": true, - "``": true, - "''": true -}; - -defineSymbol(text, textord, "\u2013", "--", true); -defineSymbol(text, textord, "\u2013", "\\textendash"); -defineSymbol(text, textord, "\u2014", "---", true); -defineSymbol(text, textord, "\u2014", "\\textemdash"); -defineSymbol(text, textord, "\u2018", "`", true); -defineSymbol(text, textord, "\u2018", "\\textquoteleft"); -defineSymbol(text, textord, "\u2019", "'", true); -defineSymbol(text, textord, "\u2019", "\\textquoteright"); -defineSymbol(text, textord, "\u201c", "``", true); -defineSymbol(text, textord, "\u201c", "\\textquotedblleft"); -defineSymbol(text, textord, "\u201d", "''", true); -defineSymbol(text, textord, "\u201d", "\\textquotedblright"); -// \degree from gensymb package -defineSymbol(math, textord, "\u00b0", "\\degree", true); -defineSymbol(text, textord, "\u00b0", "\\degree"); -// \textdegree from inputenc package -defineSymbol(text, textord, "\u00b0", "\\textdegree", true); -// TODO: In LaTeX, \pounds can generate a different character in text and math -// mode, but among our fonts, only Main-Regular defines this character "163". -defineSymbol(math, textord, "\u00a3", "\\pounds"); -defineSymbol(math, textord, "\u00a3", "\\mathsterling", true); -defineSymbol(text, textord, "\u00a3", "\\pounds"); -defineSymbol(text, textord, "\u00a3", "\\textsterling", true); -defineSymbol(math, textord, "\u2720", "\\maltese"); -defineSymbol(text, textord, "\u2720", "\\maltese"); -defineSymbol(math, textord, "\u20ac", "\\euro", true); -defineSymbol(text, textord, "\u20ac", "\\euro", true); -defineSymbol(text, textord, "\u20ac", "\\texteuro"); -defineSymbol(math, textord, "\u00a9", "\\copyright", true); -defineSymbol(text, textord, "\u00a9", "\\textcopyright"); - -// Italic Greek -defineSymbol(math, textord, "𝛤", "\\varGamma"); -defineSymbol(math, textord, "𝛥", "\\varDelta"); -defineSymbol(math, textord, "𝛩", "\\varTheta"); -defineSymbol(math, textord, "𝛬", "\\varLambda"); -defineSymbol(math, textord, "𝛯", "\\varXi"); -defineSymbol(math, textord, "𝛱", "\\varPi"); -defineSymbol(math, textord, "𝛴", "\\varSigma"); -defineSymbol(math, textord, "𝛶", "\\varUpsilon"); -defineSymbol(math, textord, "𝛷", "\\varPhi"); -defineSymbol(math, textord, "𝛹", "\\varPsi"); -defineSymbol(math, textord, "𝛺", "\\varOmega"); -defineSymbol(text, textord, "𝛤", "\\varGamma"); -defineSymbol(text, textord, "𝛥", "\\varDelta"); -defineSymbol(text, textord, "𝛩", "\\varTheta"); -defineSymbol(text, textord, "𝛬", "\\varLambda"); -defineSymbol(text, textord, "𝛯", "\\varXi"); -defineSymbol(text, textord, "𝛱", "\\varPi"); -defineSymbol(text, textord, "𝛴", "\\varSigma"); -defineSymbol(text, textord, "𝛶", "\\varUpsilon"); -defineSymbol(text, textord, "𝛷", "\\varPhi"); -defineSymbol(text, textord, "𝛹", "\\varPsi"); -defineSymbol(text, textord, "𝛺", "\\varOmega"); - - -// There are lots of symbols which are the same, so we add them in afterwards. -// All of these are textords in math mode -const mathTextSymbols = '0123456789/@."'; -for (let i = 0; i < mathTextSymbols.length; i++) { - const ch = mathTextSymbols.charAt(i); - defineSymbol(math, textord, ch, ch); -} - -// All of these are textords in text mode -const textSymbols = '0123456789!@*()-=+";:?/.,'; -for (let i = 0; i < textSymbols.length; i++) { - const ch = textSymbols.charAt(i); - defineSymbol(text, textord, ch, ch); -} - -// All of these are textords in text mode, and mathords in math mode -const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -for (let i = 0; i < letters.length; i++) { - const ch = letters.charAt(i); - defineSymbol(math, mathord, ch, ch); - defineSymbol(text, textord, ch, ch); -} - -// Some more letters in Unicode Basic Multilingual Plane. -const narrow = "ÇÐÞçþℂℍℕℙℚℝℤℎℏℊℋℌℐℑℒℓ℘ℛℜℬℰℱℳℭℨ"; -for (let i = 0; i < narrow.length; i++) { - const ch = narrow.charAt(i); - defineSymbol(math, mathord, ch, ch); - defineSymbol(text, textord, ch, ch); -} - -// The next loop loads wide (surrogate pair) characters. -// We support some letters in the Unicode range U+1D400 to U+1D7FF, -// Mathematical Alphanumeric Symbols. -let wideChar = ""; -for (let i = 0; i < letters.length; i++) { - // The hex numbers in the next line are a surrogate pair. - // 0xD835 is the high surrogate for all letters in the range we support. - // 0xDC00 is the low surrogate for bold A. - wideChar = String.fromCharCode(0xd835, 0xdc00 + i); // A-Z a-z bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdc34 + i); // A-Z a-z italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdc68 + i); // A-Z a-z bold italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdd04 + i); // A-Z a-z Fractur - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdda0 + i); // A-Z a-z sans-serif - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xddd4 + i); // A-Z a-z sans bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xde08 + i); // A-Z a-z sans italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xde70 + i); // A-Z a-z monospace - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdd38 + i); // A-Z a-z double struck - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - const ch = letters.charAt(i); - wideChar = String.fromCharCode(0xd835, 0xdc9c + i); // A-Z a-z calligraphic - defineSymbol(math, mathord, ch, wideChar); - defineSymbol(text, textord, ch, wideChar); -} - -// Next, some wide character numerals -for (let i = 0; i < 10; i++) { - wideChar = String.fromCharCode(0xd835, 0xdfce + i); // 0-9 bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdfe2 + i); // 0-9 sans serif - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdfec + i); // 0-9 bold sans - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdff6 + i); // 0-9 monospace - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); -} diff --git a/src/tree.js b/src/tree.js deleted file mode 100644 index 5ae654ba..00000000 --- a/src/tree.js +++ /dev/null @@ -1,52 +0,0 @@ -import utils from "./utils"; - -/** - * This node represents a document fragment, which contains elements, but when - * placed into the DOM doesn't have any representation itself. It only contains - * children and doesn't have any DOM node properties. - */ -export class DocumentFragment { - constructor(children) { - this.children = children; - this.classes = []; - this.style = {}; - } - - hasClass(className) { - return utils.contains(this.classes, className); - } - - /** Convert the fragment into a node. */ - toNode() { - const frag = document.createDocumentFragment(); - - for (let i = 0; i < this.children.length; i++) { - frag.appendChild(this.children[i].toNode()); - } - - return frag; - } - - /** Convert the fragment into HTML markup. */ - toMarkup() { - let markup = ""; - - // Simply concatenate the markup for the children together. - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - return markup; - } - - /** - * Converts the math node into a string, similar to innerText. Applies to - * MathDomNode's only. - */ - toText() { - // To avoid this, we would subclass documentFragment separately for - // MathML, but polyfills for subclassing is expensive per PR 1469. - const toText = (child) => child.toText(); - return this.children.map(toText).join(""); - } -} diff --git a/src/unicodeAccents.js b/src/unicodeAccents.js deleted file mode 100644 index 36844133..00000000 --- a/src/unicodeAccents.js +++ /dev/null @@ -1,16 +0,0 @@ -// Mapping of Unicode accent characters to their LaTeX equivalent in text and -// math mode (when they exist). -export default { - "\u0301": { text: "\\'", math: "\\acute" }, - "\u0300": { text: "\\`", math: "\\grave" }, - "\u0308": { text: '\\"', math: "\\ddot" }, - "\u0303": { text: "\\~", math: "\\tilde" }, - "\u0304": { text: "\\=", math: "\\bar" }, - "\u0306": { text: "\\u", math: "\\breve" }, - "\u030c": { text: "\\v", math: "\\check" }, - "\u0302": { text: "\\^", math: "\\hat" }, - "\u0307": { text: "\\.", math: "\\dot" }, - "\u030a": { text: "\\r", math: "\\mathring" }, - "\u030b": { text: "\\H" }, - '\u0327': { text: '\\c' } -}; diff --git a/src/unicodeScripts.js b/src/unicodeScripts.js deleted file mode 100644 index 13e825af..00000000 --- a/src/unicodeScripts.js +++ /dev/null @@ -1,119 +0,0 @@ -/* - * This file defines the Unicode scripts and script families that we - * support. To add new scripts or families, just add a new entry to the - * scriptData array below. Adding scripts to the scriptData array allows - * characters from that script to appear in \text{} environments. - */ - -/** - * Each script or script family has a name and an array of blocks. - * Each block is an array of two numbers which specify the start and - * end points (inclusive) of a block of Unicode codepoints. - -/** - * Unicode block data for the families of scripts we support in \text{}. - * Scripts only need to appear here if they do not have font metrics. - */ -const scriptData = [ - { - // Latin characters beyond the Latin-1 characters we have metrics for. - // Needed for Czech, Hungarian and Turkish text, for example. - name: "latin", - blocks: [ - [0x0100, 0x024f], // Latin Extended-A and Latin Extended-B - [0x0300, 0x036f] // Combining Diacritical marks - ] - }, - { - // The Cyrillic script used by Russian and related languages. - // A Cyrillic subset used to be supported as explicitly defined - // symbols in symbols.js - name: "cyrillic", - blocks: [[0x0400, 0x04ff]] - }, - { - // Armenian - name: "armenian", - blocks: [[0x0530, 0x058f]] - }, - { - // The Brahmic scripts of South and Southeast Asia - // Devanagari (0900–097F) - // Bengali (0980–09FF) - // Gurmukhi (0A00–0A7F) - // Gujarati (0A80–0AFF) - // Oriya (0B00–0B7F) - // Tamil (0B80–0BFF) - // Telugu (0C00–0C7F) - // Kannada (0C80–0CFF) - // Malayalam (0D00–0D7F) - // Sinhala (0D80–0DFF) - // Thai (0E00–0E7F) - // Lao (0E80–0EFF) - // Tibetan (0F00–0FFF) - // Myanmar (1000–109F) - name: "brahmic", - blocks: [[0x0900, 0x109f]] - }, - { - name: "georgian", - blocks: [[0x10a0, 0x10ff]] - }, - { - // Chinese and Japanese. - // The "k" in cjk is for Korean, but we've separated Korean out - name: "cjk", - blocks: [ - [0x3000, 0x30ff], // CJK symbols and punctuation, Hiragana, Katakana - [0x4e00, 0x9faf], // CJK ideograms - [0xff00, 0xff60] // Fullwidth punctuation - // TODO: add halfwidth Katakana and Romanji glyphs - ] - }, - { - // Korean - name: "hangul", - blocks: [[0xac00, 0xd7af]] - } -]; - -/** - * Given a codepoint, return the name of the script or script family - * it is from, or null if it is not part of a known block - */ -export function scriptFromCodepoint(codepoint) { - for (let i = 0; i < scriptData.length; i++) { - const script = scriptData[i]; - for (let i = 0; i < script.blocks.length; i++) { - const block = script.blocks[i]; - if (codepoint >= block[0] && codepoint <= block[1]) { - return script.name; - } - } - } - return null; -} - -/** - * A flattened version of all the supported blocks in a single array. - * This is an optimization to make supportedCodepoint() fast. - */ -const allBlocks = []; -scriptData.forEach((s) => s.blocks.forEach((b) => allBlocks.push(...b))); - -/** - * Given a codepoint, return true if it falls within one of the - * scripts or script families defined above and false otherwise. - * - * Micro benchmarks shows that this is faster than - * /[\u3000-\u30FF\u4E00-\u9FAF\uFF00-\uFF60\uAC00-\uD7AF\u0900-\u109F]/.test() - * in Firefox, Chrome and Node. - */ -export function supportedCodepoint(codepoint) { - for (let i = 0; i < allBlocks.length; i += 2) { - if (codepoint >= allBlocks[i] && codepoint <= allBlocks[i + 1]) { - return true; - } - } - return false; -} diff --git a/src/unicodeSupOrSub.js b/src/unicodeSupOrSub.js deleted file mode 100644 index 7588582a..00000000 --- a/src/unicodeSupOrSub.js +++ /dev/null @@ -1,108 +0,0 @@ -// Helpers for Parser.js handling of Unicode (sub|super)script characters. - -export const unicodeSubRegEx = /^[₊₋₌₍₎₀₁₂₃₄₅₆₇₈₉ₐₑₕᵢⱼₖₗₘₙₒₚᵣₛₜᵤᵥₓᵦᵧᵨᵩᵪ]/ - -export const uSubsAndSups = Object.freeze({ - '₊': '+', - '₋': '-', - '₌': '=', - '₍': '(', - '₎': ')', - '₀': '0', - '₁': '1', - '₂': '2', - '₃': '3', - '₄': '4', - '₅': '5', - '₆': '6', - '₇': '7', - '₈': '8', - '₉': '9', - '\u2090': 'a', - '\u2091': 'e', - '\u2095': 'h', - '\u1D62': 'i', - '\u2C7C': 'j', - '\u2096': 'k', - '\u2097': 'l', - '\u2098': 'm', - '\u2099': 'n', - '\u2092': 'o', - '\u209A': 'p', - '\u1D63': 'r', - '\u209B': 's', - '\u209C': 't', - '\u1D64': 'u', - '\u1D65': 'v', - '\u2093': 'x', - '\u1D66': 'β', - '\u1D67': 'γ', - '\u1D68': 'ρ', - '\u1D69': '\u03d5', - '\u1D6A': 'χ', - '⁺': '+', - '⁻': '-', - '⁼': '=', - '⁽': '(', - '⁾': ')', - '⁰': '0', - '¹': '1', - '²': '2', - '³': '3', - '⁴': '4', - '⁵': '5', - '⁶': '6', - '⁷': '7', - '⁸': '8', - '⁹': '9', - '\u1D2C': 'A', - '\u1D2E': 'B', - '\u1D30': 'D', - '\u1D31': 'E', - '\u1D33': 'G', - '\u1D34': 'H', - '\u1D35': 'I', - '\u1D36': 'J', - '\u1D37': 'K', - '\u1D38': 'L', - '\u1D39': 'M', - '\u1D3A': 'N', - '\u1D3C': 'O', - '\u1D3E': 'P', - '\u1D3F': 'R', - '\u1D40': 'T', - '\u1D41': 'U', - '\u2C7D': 'V', - '\u1D42': 'W', - '\u1D43': 'a', - '\u1D47': 'b', - '\u1D9C': 'c', - '\u1D48': 'd', - '\u1D49': 'e', - '\u1DA0': 'f', - '\u1D4D': 'g', - '\u02B0': 'h', - '\u2071': 'i', - '\u02B2': 'j', - '\u1D4F': 'k', - '\u02E1': 'l', - '\u1D50': 'm', - '\u207F': 'n', - '\u1D52': 'o', - '\u1D56': 'p', - '\u02B3': 'r', - '\u02E2': 's', - '\u1D57': 't', - '\u1D58': 'u', - '\u1D5B': 'v', - '\u02B7': 'w', - '\u02E3': 'x', - '\u02B8': 'y', - '\u1DBB': 'z', - '\u1D5D': 'β', - '\u1D5E': 'γ', - '\u1D5F': 'δ', - '\u1D60': '\u03d5', - '\u1D61': 'χ', - '\u1DBF': 'θ' -}) diff --git a/src/unicodeSymbolBuilder.js b/src/unicodeSymbolBuilder.js deleted file mode 100644 index 3be3f5a0..00000000 --- a/src/unicodeSymbolBuilder.js +++ /dev/null @@ -1,31 +0,0 @@ -// This is an internal module, not part of the Temml distribution, -// whose purpose is to generate `unicodeSymbols` for Parser.js -// In this way, only this module, and not the distribution/browser, -// needs String's normalize function. -import * as accents from "./unicodeAccents"; - -const result = {}; -const letters = - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + - "αβγδεϵζηθϑικλμνξοπϖρϱςστυφϕχψωΓΔΘΛΞΠΣΥΦΨΩ"; -for (const letter of letters) { - for (const accent of Object.getOwnPropertyNames(accents)) { - const combined = letter + accent; - const normalized = combined.normalize("NFC"); - if (normalized.length === 1) { - result[normalized] = combined; - } - for (const accent2 of Object.getOwnPropertyNames(accents)) { - if (accent === accent2) { - continue; - } - const combined2 = combined + accent2; - const normalized2 = combined2.normalize("NFC"); - if (normalized2.length === 1) { - result[normalized2] = combined2; - } - } - } -} - -export default result; diff --git a/src/unicodeSymbols.js b/src/unicodeSymbols.js deleted file mode 100644 index 56dbcc5d..00000000 --- a/src/unicodeSymbols.js +++ /dev/null @@ -1,320 +0,0 @@ -export default { - "á": "á", - "à": "à", - "ä": "ä", - "ǟ": "ǟ", - "ã": "ã", - "ā": "ā", - "ă": "ă", - "ắ": "ắ", - "ằ": "ằ", - "ẵ": "ẵ", - "ǎ": "ǎ", - "â": "â", - "ấ": "ấ", - "ầ": "ầ", - "ẫ": "ẫ", - "ȧ": "ȧ", - "ǡ": "ǡ", - "å": "å", - "ǻ": "ǻ", - "ḃ": "ḃ", - "ć": "ć", - "č": "č", - "ĉ": "ĉ", - "ċ": "ċ", - "ď": "ď", - "ḋ": "ḋ", - "é": "é", - "è": "è", - "ë": "ë", - "ẽ": "ẽ", - "ē": "ē", - "ḗ": "ḗ", - "ḕ": "ḕ", - "ĕ": "ĕ", - "ě": "ě", - "ê": "ê", - "ế": "ế", - "ề": "ề", - "ễ": "ễ", - "ė": "ė", - "ḟ": "ḟ", - "ǵ": "ǵ", - "ḡ": "ḡ", - "ğ": "ğ", - "ǧ": "ǧ", - "ĝ": "ĝ", - "ġ": "ġ", - "ḧ": "ḧ", - "ȟ": "ȟ", - "ĥ": "ĥ", - "ḣ": "ḣ", - "í": "í", - "ì": "ì", - "ï": "ï", - "ḯ": "ḯ", - "ĩ": "ĩ", - "ī": "ī", - "ĭ": "ĭ", - "ǐ": "ǐ", - "î": "î", - "ǰ": "ǰ", - "ĵ": "ĵ", - "ḱ": "ḱ", - "ǩ": "ǩ", - "ĺ": "ĺ", - "ľ": "ľ", - "ḿ": "ḿ", - "ṁ": "ṁ", - "ń": "ń", - "ǹ": "ǹ", - "ñ": "ñ", - "ň": "ň", - "ṅ": "ṅ", - "ó": "ó", - "ò": "ò", - "ö": "ö", - "ȫ": "ȫ", - "õ": "õ", - "ṍ": "ṍ", - "ṏ": "ṏ", - "ȭ": "ȭ", - "ō": "ō", - "ṓ": "ṓ", - "ṑ": "ṑ", - "ŏ": "ŏ", - "ǒ": "ǒ", - "ô": "ô", - "ố": "ố", - "ồ": "ồ", - "ỗ": "ỗ", - "ȯ": "ȯ", - "ȱ": "ȱ", - "ő": "ő", - "ṕ": "ṕ", - "ṗ": "ṗ", - "ŕ": "ŕ", - "ř": "ř", - "ṙ": "ṙ", - "ś": "ś", - "ṥ": "ṥ", - "š": "š", - "ṧ": "ṧ", - "ŝ": "ŝ", - "ṡ": "ṡ", - "ẗ": "ẗ", - "ť": "ť", - "ṫ": "ṫ", - "ú": "ú", - "ù": "ù", - "ü": "ü", - "ǘ": "ǘ", - "ǜ": "ǜ", - "ǖ": "ǖ", - "ǚ": "ǚ", - "ũ": "ũ", - "ṹ": "ṹ", - "ū": "ū", - "ṻ": "ṻ", - "ŭ": "ŭ", - "ǔ": "ǔ", - "û": "û", - "ů": "ů", - "ű": "ű", - "ṽ": "ṽ", - "ẃ": "ẃ", - "ẁ": "ẁ", - "ẅ": "ẅ", - "ŵ": "ŵ", - "ẇ": "ẇ", - "ẘ": "ẘ", - "ẍ": "ẍ", - "ẋ": "ẋ", - "ý": "ý", - "ỳ": "ỳ", - "ÿ": "ÿ", - "ỹ": "ỹ", - "ȳ": "ȳ", - "ŷ": "ŷ", - "ẏ": "ẏ", - "ẙ": "ẙ", - "ź": "ź", - "ž": "ž", - "ẑ": "ẑ", - "ż": "ż", - "Á": "Á", - "À": "À", - "Ä": "Ä", - "Ǟ": "Ǟ", - "Ã": "Ã", - "Ā": "Ā", - "Ă": "Ă", - "Ắ": "Ắ", - "Ằ": "Ằ", - "Ẵ": "Ẵ", - "Ǎ": "Ǎ", - "Â": "Â", - "Ấ": "Ấ", - "Ầ": "Ầ", - "Ẫ": "Ẫ", - "Ȧ": "Ȧ", - "Ǡ": "Ǡ", - "Å": "Å", - "Ǻ": "Ǻ", - "Ḃ": "Ḃ", - "Ć": "Ć", - "Č": "Č", - "Ĉ": "Ĉ", - "Ċ": "Ċ", - "Ď": "Ď", - "Ḋ": "Ḋ", - "É": "É", - "È": "È", - "Ë": "Ë", - "Ẽ": "Ẽ", - "Ē": "Ē", - "Ḗ": "Ḗ", - "Ḕ": "Ḕ", - "Ĕ": "Ĕ", - "Ě": "Ě", - "Ê": "Ê", - "Ế": "Ế", - "Ề": "Ề", - "Ễ": "Ễ", - "Ė": "Ė", - "Ḟ": "Ḟ", - "Ǵ": "Ǵ", - "Ḡ": "Ḡ", - "Ğ": "Ğ", - "Ǧ": "Ǧ", - "Ĝ": "Ĝ", - "Ġ": "Ġ", - "Ḧ": "Ḧ", - "Ȟ": "Ȟ", - "Ĥ": "Ĥ", - "Ḣ": "Ḣ", - "Í": "Í", - "Ì": "Ì", - "Ï": "Ï", - "Ḯ": "Ḯ", - "Ĩ": "Ĩ", - "Ī": "Ī", - "Ĭ": "Ĭ", - "Ǐ": "Ǐ", - "Î": "Î", - "İ": "İ", - "Ĵ": "Ĵ", - "Ḱ": "Ḱ", - "Ǩ": "Ǩ", - "Ĺ": "Ĺ", - "Ľ": "Ľ", - "Ḿ": "Ḿ", - "Ṁ": "Ṁ", - "Ń": "Ń", - "Ǹ": "Ǹ", - "Ñ": "Ñ", - "Ň": "Ň", - "Ṅ": "Ṅ", - "Ó": "Ó", - "Ò": "Ò", - "Ö": "Ö", - "Ȫ": "Ȫ", - "Õ": "Õ", - "Ṍ": "Ṍ", - "Ṏ": "Ṏ", - "Ȭ": "Ȭ", - "Ō": "Ō", - "Ṓ": "Ṓ", - "Ṑ": "Ṑ", - "Ŏ": "Ŏ", - "Ǒ": "Ǒ", - "Ô": "Ô", - "Ố": "Ố", - "Ồ": "Ồ", - "Ỗ": "Ỗ", - "Ȯ": "Ȯ", - "Ȱ": "Ȱ", - "Ő": "Ő", - "Ṕ": "Ṕ", - "Ṗ": "Ṗ", - "Ŕ": "Ŕ", - "Ř": "Ř", - "Ṙ": "Ṙ", - "Ś": "Ś", - "Ṥ": "Ṥ", - "Š": "Š", - "Ṧ": "Ṧ", - "Ŝ": "Ŝ", - "Ṡ": "Ṡ", - "Ť": "Ť", - "Ṫ": "Ṫ", - "Ú": "Ú", - "Ù": "Ù", - "Ü": "Ü", - "Ǘ": "Ǘ", - "Ǜ": "Ǜ", - "Ǖ": "Ǖ", - "Ǚ": "Ǚ", - "Ũ": "Ũ", - "Ṹ": "Ṹ", - "Ū": "Ū", - "Ṻ": "Ṻ", - "Ŭ": "Ŭ", - "Ǔ": "Ǔ", - "Û": "Û", - "Ů": "Ů", - "Ű": "Ű", - "Ṽ": "Ṽ", - "Ẃ": "Ẃ", - "Ẁ": "Ẁ", - "Ẅ": "Ẅ", - "Ŵ": "Ŵ", - "Ẇ": "Ẇ", - "Ẍ": "Ẍ", - "Ẋ": "Ẋ", - "Ý": "Ý", - "Ỳ": "Ỳ", - "Ÿ": "Ÿ", - "Ỹ": "Ỹ", - "Ȳ": "Ȳ", - "Ŷ": "Ŷ", - "Ẏ": "Ẏ", - "Ź": "Ź", - "Ž": "Ž", - "Ẑ": "Ẑ", - "Ż": "Ż", - "ά": "ά", - "ὰ": "ὰ", - "ᾱ": "ᾱ", - "ᾰ": "ᾰ", - "έ": "έ", - "ὲ": "ὲ", - "ή": "ή", - "ὴ": "ὴ", - "ί": "ί", - "ὶ": "ὶ", - "ϊ": "ϊ", - "ΐ": "ΐ", - "ῒ": "ῒ", - "ῑ": "ῑ", - "ῐ": "ῐ", - "ό": "ό", - "ὸ": "ὸ", - "ύ": "ύ", - "ὺ": "ὺ", - "ϋ": "ϋ", - "ΰ": "ΰ", - "ῢ": "ῢ", - "ῡ": "ῡ", - "ῠ": "ῠ", - "ώ": "ώ", - "ὼ": "ὼ", - "Ύ": "Ύ", - "Ὺ": "Ὺ", - "Ϋ": "Ϋ", - "Ῡ": "Ῡ", - "Ῠ": "Ῠ", - "Ώ": "Ώ", - "Ὼ": "Ὼ" -}; diff --git a/src/units.js b/src/units.js deleted file mode 100644 index 86ca71d0..00000000 --- a/src/units.js +++ /dev/null @@ -1,109 +0,0 @@ -/** - * This file does conversion between units. In particular, it provides - * calculateSize to convert other units into CSS units. - */ - -import ParseError from "./ParseError" -import utils from "./utils" - -const ptPerUnit = { - // Convert to CSS (Postscipt) points, not TeX points - // https://en.wikibooks.org/wiki/LaTeX/Lengths and - // https://tex.stackexchange.com/a/8263 - pt: 800 / 803, // convert TeX point to CSS (Postscript) point - pc: (12 * 800) / 803, // pica - dd: ((1238 / 1157) * 800) / 803, // didot - cc: ((14856 / 1157) * 800) / 803, // cicero (12 didot) - nd: ((685 / 642) * 800) / 803, // new didot - nc: ((1370 / 107) * 800) / 803, // new cicero (12 new didot) - sp: ((1 / 65536) * 800) / 803, // scaled point (TeX's internal smallest unit) - mm: (25.4 / 72), - cm: (2.54 / 72), - in: (1 / 72), - px: (96 / 72) -} - -/** - * Determine whether the specified unit (either a string defining the unit - * or a "size" parse node containing a unit field) is valid. - */ -const validUnits = [ - "em", - "ex", - "mu", - "pt", - "mm", - "cm", - "in", - "px", - "bp", - "pc", - "dd", - "cc", - "nd", - "nc", - "sp" -] - -export const validUnit = function(unit) { - if (typeof unit !== "string") { - unit = unit.unit - } - return validUnits.indexOf(unit) > -1 -} - -export const emScale = styleLevel => { - const scriptLevel = Math.max(styleLevel - 1, 0) - return [1, 0.7, 0.5][scriptLevel] -}; - -/* - * Convert a "size" parse node (with numeric "number" and string "unit" fields, - * as parsed by functions.js argType "size") into a CSS value. - */ -export const calculateSize = function(sizeValue, style) { - let number = sizeValue.number - if (style.maxSize[0] < 0 && number > 0) { - return { number: 0, unit: "em" } - } - const unit = sizeValue.unit - switch (unit) { - case "mm": - case "cm": - case "in": - case "px": { - const numInCssPts = number * ptPerUnit[unit]; - if (numInCssPts > style.maxSize[1]) { - return { number: style.maxSize[1], unit: "pt" } - } - return { number, unit }; // absolute CSS units. - } - case "em": - case "ex": { - // In TeX, em and ex do not change size in \scriptstyle. - if (unit === "ex") { number *= 0.431 } - number = Math.min(number / emScale(style.level), style.maxSize[0]) - return { number: utils.round(number), unit: "em" }; - } - case "bp": { - if (number > style.maxSize[1]) { number = style.maxSize[1] } - return { number, unit: "pt" }; // TeX bp is a CSS pt. (1/72 inch). - } - case "pt": - case "pc": - case "dd": - case "cc": - case "nd": - case "nc": - case "sp": { - number = Math.min(number * ptPerUnit[unit], style.maxSize[1]) - return { number: utils.round(number), unit: "pt" } - } - case "mu": { - number = Math.min(number / 18, style.maxSize[0]) - return { number: utils.round(number), unit: "em" } - } - default: - throw new ParseError("Invalid unit: '" + unit + "'") - } -} diff --git a/src/utils.js b/src/utils.js deleted file mode 100644 index ab6a57ae..00000000 --- a/src/utils.js +++ /dev/null @@ -1,160 +0,0 @@ -// -/** - * This file contains a list of utility functions which are useful in other - * files. - */ - -/** - * Return whether an element is contained in a list - */ -const contains = function(list, elem) { - return list.indexOf(elem) !== -1; -}; - -/** - * Provide a default value if a setting is undefined - */ -const deflt = function(setting, defaultIfUndefined) { - return setting === undefined ? defaultIfUndefined : setting; -}; - -// hyphenate and escape adapted from Facebook's React under Apache 2 license - -const uppercase = /([A-Z])/g; -const hyphenate = function(str) { - return str.replace(uppercase, "-$1").toLowerCase(); -}; - -const ESCAPE_LOOKUP = { - "&": "&", - ">": ">", - "<": "<", - '"': """, - "'": "'" -}; - -const ESCAPE_REGEX = /[&><"']/g; - -/** - * Escapes text to prevent scripting attacks. - */ -function escape(text) { - return String(text).replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]); -} - -/** - * Sometimes we want to pull out the innermost element of a group. In most - * cases, this will just be the group itself, but when ordgroups and colors have - * a single element, we want to pull that out. - */ -const getBaseElem = function(group) { - if (group.type === "ordgroup") { - if (group.body.length === 1) { - return getBaseElem(group.body[0]); - } else { - return group; - } - } else if (group.type === "color") { - if (group.body.length === 1) { - return getBaseElem(group.body[0]); - } else { - return group; - } - } else if (group.type === "font") { - return getBaseElem(group.body); - } else { - return group; - } -}; - -/** - * TeXbook algorithms often reference "character boxes", which are simply groups - * with a single character in them. To decide if something is a character box, - * we find its innermost group, and see if it is a single character. - */ -const isCharacterBox = function(group) { - const baseElem = getBaseElem(group); - - // These are all the types of groups which hold single characters - return baseElem.type === "mathord" || baseElem.type === "textord" || baseElem.type === "atom" -}; - -export const assert = function(value) { - if (!value) { - throw new Error("Expected non-null, but got " + String(value)); - } - return value; -}; - -/** - * Return the protocol of a URL, or "_relative" if the URL does not specify a - * protocol (and thus is relative). - */ -export const protocolFromUrl = function(url) { - const protocol = /^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(url); - return protocol != null ? protocol[1] : "_relative"; -}; - -/** - * Round `n` to 4 decimal places, or to the nearest 1/10,000th em. The TeXbook - * gives an acceptable rounding error of 100sp (which would be the nearest - * 1/6551.6em with our ptPerEm = 10): - * http://www.ctex.org/documents/shredder/src/texbook.pdf#page=69 - */ -const round = function(n) { - return +n.toFixed(4); -}; - -const consolidateText = mrow => { - // If possible, consolidate adjacent elements into a single element. - if (mrow.type !== "mrow") { return mrow } - if (mrow.children.length === 0) { return mrow } // empty group, e.g., \text{} - const mtext = mrow.children[0] - if (!mtext.attributes || mtext.type !== "mtext") { return mrow } - const variant = mtext.attributes.mathvariant || "" - for (let i = 1; i < mrow.children.length; i++) { - // Check each child and, if possible, copy the character into child[0]. - const localVariant = mrow.children[i].attributes.mathvariant || "" - if (mrow.children[i].type === "mrow") { - const childRow = mrow.children[i] - for (let j = 0; j < childRow.children.length; j++) { - // We'll also check the children of a mrow. One level only. No recursion. - const childVariant = childRow.children[j].attributes.mathvariant || "" - if (childVariant !== variant || childRow.children[j].type !== "mtext") { - return mrow // At least one element cannot be consolidated. Get out. - } else { - mtext.children[0].text += childRow.children[j].children[0].text - } - } - } else if (localVariant !== variant || mrow.children[i].type !== "mtext") { - return mrow - } else { - mtext.children[0].text += mrow.children[i].children[0].text - } - } - // Since we have gotten here, the text has been loaded into a single mtext node. - // Next, consolidate the children into a single element. - mtext.children.splice(1, mtext.children.length - 1) - // Firefox does not render a space at either end of an string. - // To get proper rendering, we replace leading or trailing spaces with no-break spaces. - if (mtext.children[0].text.charAt(0) === " ") { - mtext.children[0].text = "\u00a0" + mtext.children[0].text.slice(1) - } - const L = mtext.children[0].text.length - if (L > 0 && mtext.children[0].text.charAt(L - 1) === " ") { - mtext.children[0].text = mtext.children[0].text.slice(0, -1) + "\u00a0" - } - return mtext -} - -export default { - contains, - deflt, - escape, - hyphenate, - getBaseElem, - isCharacterBox, - protocolFromUrl, - round, - consolidateText -}; diff --git a/src/variant.js b/src/variant.js deleted file mode 100644 index aff58e5b..00000000 --- a/src/variant.js +++ /dev/null @@ -1,103 +0,0 @@ -import symbols from "./symbols"; - -/** - * Maps TeX font commands to "mathvariant" attribute in buildMathML.js - */ -const fontMap = { - // styles - mathbf: "bold", - mathrm: "normal", - textit: "italic", - mathit: "italic", - mathnormal: "italic", - - // families - mathbb: "double-struck", - mathcal: "script", - mathfrak: "fraktur", - mathscr: "script", - mathsf: "sans-serif", - mathtt: "monospace", - oldstylenums: "oldstylenums" -} - -/** - * Returns the math variant as a string or null if none is required. - */ -export const getVariant = function(group, style) { - // Handle font specifiers as best we can. - // Chromium does not support the MathML mathvariant attribute. - // So we'll use Unicode replacement characters instead. - // But first, determine the math variant. - - // Deal with the \textit, \textbf, etc., functions. - if (style.fontFamily === "texttt") { - return "monospace" - } else if (style.fontFamily === "textsc") { - return "normal"; // handled via character substitution in symbolsOrd.js. - } else if (style.fontFamily === "textsf") { - if (style.fontShape === "textit" && style.fontWeight === "textbf") { - return "sans-serif-bold-italic" - } else if (style.fontShape === "textit") { - return "sans-serif-italic" - } else if (style.fontWeight === "textbf") { - return "sans-serif-bold" - } else { - return "sans-serif" - } - } else if (style.fontShape === "textit" && style.fontWeight === "textbf") { - return "bold-italic" - } else if (style.fontShape === "textit") { - return "italic" - } else if (style.fontWeight === "textbf") { - return "bold" - } - - // Deal with the \mathit, mathbf, etc, functions. - const font = style.font - if (!font || font === "mathnormal") { - return null - } - - const mode = group.mode; - switch (font) { - case "mathit": - return "italic" - case "mathrm": { - const codePoint = group.text.codePointAt(0) - // LaTeX \mathrm returns italic for Greek characters. - return (0x03ab < codePoint && codePoint < 0x03cf) ? "italic" : "normal" - } - case "greekItalic": - return "italic" - case "up@greek": - return "normal" - case "boldsymbol": - case "mathboldsymbol": - return "bold-italic" - case "mathbf": - return "bold" - case "mathbb": - return "double-struck" - case "mathfrak": - return "fraktur" - case "mathscr": - case "mathcal": - return "script" - case "mathsf": - return "sans-serif" - case "mathtt": - return "monospace" - case "oldstylenums": - return "oldstylenums" - default: - break - } - - let text = group.text; - if (symbols[mode][text] && symbols[mode][text].replace) { - text = symbols[mode][text].replace - } - - return Object.prototype.hasOwnProperty.call(fontMap, font) ? fontMap[font] : null -}; diff --git a/temml.js b/temml.js deleted file mode 100644 index 5e971e32..00000000 --- a/temml.js +++ /dev/null @@ -1,177 +0,0 @@ -/* eslint no-console:0 */ -/** - * This is the main entry point for Temml. Here, we expose functions for - * rendering expressions either to DOM nodes or to markup strings. - * - * We also expose the ParseError class to check if errors thrown from Temml are - * errors in the expression, or errors in javascript handling. - */ - -import ParseError from "./src/ParseError"; -import Settings from "./src/Settings"; - -import Parser from "./src/Parser"; -import parseTree from "./src/parseTree"; -import buildMathML from "./src/buildMathML"; -import { StyleLevel } from "./src/constants"; -import Style from "./src/Style"; -import { Span } from "./src/domTree"; -import { TextNode } from "./src/domTree"; -import { defineSymbol } from "./src/symbols"; -import defineMacro from "./src/defineMacro"; -import { postProcess, version } from "./src/postProcess"; - -/** - * Parse and build an expression, and place that expression in the DOM node - * given. - */ -let render = function(expression, baseNode, options) { - baseNode.textContent = ""; - const math = renderToMathMLTree(expression, options) - if (options.elementIsMath) { - // The element already exists. Populate it. - baseNode.textContent = "" - math.children.forEach(e => { baseNode.appendChild(e.toNode()) }) - } else { - baseNode.appendChild(math.toNode()) - } -}; - -// Temml's styles don't work properly in quirks mode. Print out an error, and -// disable rendering. -if (typeof document !== "undefined") { - if (document.compatMode !== "CSS1Compat") { - typeof console !== "undefined" && - console.warn( - "Warning: Temml doesn't work in quirks mode. Make sure your " + - "website has a suitable doctype." - ); - - render = function() { - throw new ParseError("Temml doesn't work in quirks mode."); - }; - } -} - -/** - * Parse and build an expression, and return the markup for that. - */ -const renderToString = function(expression, options) { - const markup = renderToMathMLTree(expression, options).toMarkup(); - return markup; -}; - -/** - * Parse an expression and return the parse tree. - */ -const generateParseTree = function(expression, options) { - const settings = new Settings(options); - return parseTree(expression, settings); -}; - -/** - * Take an expression which contains a preamble. - * Parse it and return the macros. - */ -const definePreamble = function(expression, options) { - const settings = new Settings(options); - settings.macros = {}; - if (!(typeof expression === "string" || expression instanceof String)) { - throw new TypeError("Temml can only parse string typed expression") - } - const parser = new Parser(expression, settings, true) - // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors - delete parser.gullet.macros.current["\\df@tag"] - const macros = parser.parse() - return macros -}; - -/** - * If the given error is a Temml ParseError, - * renders the invalid LaTeX as a span with hover title giving the Temml - * error message. Otherwise, simply throws the error. - */ -const renderError = function(error, expression, options) { - if (options.throwOnError || !(error instanceof ParseError)) { - throw error; - } - const node = new Span(["temml-error"], [new TextNode(expression + "\n" + error.toString())]); - node.style.color = options.errorColor - node.style.whiteSpace = "pre-line" - return node; -}; - -/** - * Generates and returns the Temml build tree. This is used for advanced - * use cases (like rendering to custom output). - */ -const renderToMathMLTree = function(expression, options) { - const settings = new Settings(options); - try { - const tree = parseTree(expression, settings); - const style = new Style({ - level: settings.displayMode ? StyleLevel.DISPLAY : StyleLevel.TEXT, - maxSize: settings.maxSize - }); - return buildMathML(tree, expression, style, settings); - } catch (error) { - return renderError(error, expression, settings); - } -}; - -export default { - /** - * Current Temml version - */ - version: version, - /** - * Renders the given LaTeX into MathML, and adds - * it as a child to the specified DOM node. - */ - render, - /** - * Renders the given LaTeX into MathML string, - * for sending to the client. - */ - renderToString, - /** - * Post-process an entire HTML block. - * Writes AMS auto-numbers and implements \ref{}. - * Typcally called once, after a loop has rendered many individual spans. - */ - postProcess, - /** - * Temml error, usually during parsing. - */ - ParseError, - /** - * Creates a set of macros with document-wide scope. - */ - definePreamble, - /** - * Parses the given LaTeX into Temml's internal parse tree structure, - * without rendering to HTML or MathML. - * - * NOTE: This method is not currently recommended for public use. - * The internal tree representation is unstable and is very likely - * to change. Use at your own risk. - */ - __parse: generateParseTree, - /** - * Renders the given LaTeX into a MathML internal DOM tree - * representation, without flattening that representation to a string. - * - * NOTE: This method is not currently recommended for public use. - * The internal tree representation is unstable and is very likely - * to change. Use at your own risk. - */ - __renderToMathMLTree: renderToMathMLTree, - /** - * adds a new symbol to builtin symbols table - */ - __defineSymbol: defineSymbol, - /** - * adds a new macro to builtin macro list - */ - __defineMacro: defineMacro -} diff --git a/test/Investigate.html b/test/Investigate.html deleted file mode 100644 index 9dc34889..00000000 --- a/test/Investigate.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - Investigate - - - - - - - -

    - - - a - - b - - - - - a - Γ - b - -

    - - -

    - - - - - M - - - c - - - - - - f - - - c - 2 - - - - - - - - M - g - - 2 - - - - - M - 2 - - - - - - - - f - c - - - - - - -

    - -

    - -

    - - - - - diff --git a/test/LaTeXML-tests.md b/test/LaTeXML-tests.md deleted file mode 100644 index 346cda38..00000000 --- a/test/LaTeXML-tests.md +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - Temml LaTeXML Tests - - - - - - - - -# LaTeXML Test - -This LaTeXML test reproduces math examples from https://latexml.mathweb.org/editor\ -The equations in the first table came originally from http://www.mathjax.org/demos/tex-samples/, which no longer exists. - -### Equations - -+-----+------------------------------------------------+------------------------------------------------+ -| | Source | Temml | -+=====+================================================+================================================+ -| The Lorenz Equations | -+-----+------------------------------------------------+------------------------------------------------+ -| 1 | \\begin{aligned} \ | $$\begin{aligned} | -| | \\dot{x} & = \\sigma(y-x) \\\\ \ | \dot{x} & = \sigma(y-x) \\ | -| | \\dot{y} & = \\rho x - y - xz \\\\ \ | \dot{y} & = \rho x - y - xz \\ | -| | \\dot{z} & = -\\beta z + xy \ | \dot{z} & = -\beta z + xy | -| | \\end{aligned} | \end{aligned}$$ | -+-----+------------------------------------------------+------------------------------------------------+ -| The Cauchy-Schwarz Inequality | -+-----+------------------------------------------------+------------------------------------------------+ -| 2 | \\left( \\sum\_{k=1}^n a_k b_k \\right)^2 \ | $$\left( \sum_{k=1}^n a_k b_k \right)^2 | -| | \\leq \\left( \\sum\_{k=1}^n a_k^2 \\right) \ | \leq \left( \sum_{k=1}^n a_k^2 \right) | -| | \left( \sum\_{k=1}^n b_k^2 \right) \ | \left( \sum_{k=1}^n b_k^2 \right)$$ | -+-----+------------------------------------------------+------------------------------------------------+ -| A Cross Product Formula | -+-----+------------------------------------------------+------------------------------------------------+ -| 3 | \\mathbf{V}\_1 \\times \\mathbf{V}\_2 = \ | $$\mathbf{V}_1 \times \mathbf{V}_2 = | -| | \\begin{vmatrix} \ | \begin{vmatrix} | -| | \\mathbf{i} & \\mathbf{j} & \\mathbf{k} \\\\ \ | \mathbf{i} & \mathbf{j} & \mathbf{k} \\ | -| | \\frac{\\partial X}{\\partial u} & \ | \frac{\partial X}{\partial u} & | -| | \\frac{\\partial Y}{\\partial u} & 0 \\\\ \ | \frac{\partial Y}{\partial u} & 0 \\ | -| | \\frac{\\partial X}{\\partial v} & \ | \frac{\partial X}{\partial v} & | -| | \\frac{\\partial Y}{\\partial v} & 0 \ | \frac{\partial Y}{\partial v} & 0 | -| | \\end{vmatrix} | \end{vmatrix}$$ | -+-----+------------------------------------------------+------------------------------------------------+ -| The probability of getting $`k` heads when flipping $`n` coins is: | -+-----+------------------------------------------------+------------------------------------------------+ -| 4 | P(E) = {n \\choose k} p^k (1-p)^{ n-k} \ | $$P(E) = {n \choose k} p^k (1-p)^{ n-k}$$ | -+-----+------------------------------------------------+------------------------------------------------+ -| An Identity of Ramanujan | -+-----+------------------------------------------------+------------------------------------------------+ -| 5 | \\frac{1}{\\Bigl(\\sqrt{\\phi \\sqrt{5}}- \ | $$\frac{1}{\Bigl(\sqrt{\phi \sqrt{5}}- | -| | \\phi\\Bigr) e^{\\frac25 \\pi}} = \ | \phi\Bigr) e^{\frac25 \pi}} = | -| | 1+\\frac{e^{-2\\pi}} {1+\\frac{e^{-4\\pi}} \ | 1+\frac{e^{-2\pi}} {1+\frac{e^{-4\pi}} | -| | {1+\\frac{e^{-6\\pi}} \ | {1+\frac{e^{-6\pi}} | -| | {1+\\frac{e^{-8\\pi}} {1+\\ldots} } } } | {1+\frac{e^{-8\pi}} {1+\ldots} } } }$$ | -+-----+------------------------------------------------+------------------------------------------------+ -| A Rogers-Ramanujan Identity | -+-----+------------------------------------------------+------------------------------------------------+ -| 6 | 1 + \\frac{q^2}{(1-q)}+ \ | $$1 + \frac{q^2}{(1-q)}+ | -| | \\frac{q^6}{(1-q)(1-q^2)}+\\cdots = \ | \frac{q^6}{(1-q)(1-q^2)}+\cdots = | -| | \\prod\_{j=0}^{\\infty}\frac{1} \ | \prod_{j=0}^{\infty}\frac{1} | -| | {(1-q^{5j+2})(1-q^{5j+3})}, \ | {(1-q^{5j+2})(1-q^{5j+3})}, | -| | \\quad\\quad \\text{for} |q|<1. | \quad\quad \text{for} |q|<1.$$ | -+-----+------------------------------------------------+------------------------------------------------+ -| Maxwell's Equations | -+-----+------------------------------------------------+------------------------------------------------+ -| 7 | \\begin{aligned} \ | $$\begin{aligned} | -| | \\nabla \\times \\vec{\mathbf{B}} -\\\\, \ | \nabla \times \vec{\mathbf{B}} -\, | -| | \\frac1c\\, \\frac{\\partial\\vec{ \ | \frac1c\, \frac{\partial\vec{ | -| | \\mathbf{E}}}{\\partial t} & \ | \mathbf{E}}}{\partial t} & | -| | = \\frac{4\\pi}{c}\\vec{\\mathbf{j}} \\\\ \ | = \frac{4\pi}{c}\vec{\mathbf{j}} \\ | -| | \\nabla \\cdot \\vec{\\mathbf{E}} & \ | \nabla \cdot \vec{\mathbf{E}} & | -| | = 4 \\pi \\rho \\\\ \ | = 4 \pi \rho \\ | -| | \\nabla \\times \\vec{\\mathbf{E}}\\, +\\, \ | \nabla \times \vec{\mathbf{E}}\, +\, | -| | \\frac1c\\, \\frac{\\partial\\vec{ \ | \frac1c\, \frac{\partial\vec{ | -| | \\mathbf{B}}}{\\partial t} & \ | \mathbf{B}}}{\partial t} & | -| | = \\vec{\mathbf{0}} \\\\ \ | = \vec{\mathbf{0}} \\ | -| | \\nabla \\cdot \\vec{\\mathbf{B}} & \ | \nabla \cdot \vec{\mathbf{B}} & | -| | = 0 \ | = 0 | -| | \\end{aligned} \ | \end{aligned}$$ | -+-----+------------------------------------------------+------------------------------------------------+ - -### Boxes - -| Source | Temml | -|:-------|:--------| -| `\raisebox{0pt}[0pt][0pt]{\Large%`
    `\textbf{Aaaa\raisebox{-0.3ex}{a}%`
    `\raisebox{-0.7ex}{aa}\raisebox{-1.2ex}{r}%`
    `\raisebox{-2.2ex}{g}\raisebox{-4.5ex}{h}}}` | $`\raisebox{0pt}{\Large\textbf{Aaaa\raisebox{-0.3ex}{a}\raisebox{-0.7ex}{aa}\raisebox{-1.2ex}{r}\raisebox{-2.2ex}{g}\raisebox{-4.5ex}{h}}}` | - -### Unicode - -The tests below come from https://latexml.mathweb.org/editor\ -They got them from https://trac.edgewall.org/wiki/TracUnicode\ -I have no idea what these lines say. - -All the Unicode characters are written inside `\text{}`. - -| Language | Temml | -|:----------------------|:-------------------------------------------------------------| -| Arabic | $`\dfrac{\text{تراك يقوم بحفظ كل الكلمات باستخدام صيغة}} 2` -| Bulgarian | $`\dfrac{\text{Българският език работи ли?}} 2` -| Česky | $`\dfrac{\text{Čeština v kódování UTF-8, žádný problém.}} 2` -| Chinese (Traditional) | $`\dfrac{\text{繁體中文, 漢字測試}} 2` -| Chinese (Simplified) | $`\dfrac{\text{简体中文,汉字测试}} 2` -| Croatian | $`\left(\begin{array}{l}\text{Ako podržava srpski i slovenski mora podržavati} \\ \text{ i Hrvatski - čćžšđ ČĆŽŠĐ}\end{array}\right)` -| English | $`\dfrac{\text{Yes indeed, Trac supports English. Fully.}} 2` -| Français | $`\dfrac{\text{Il est possible d'écrire en Français : à, ç, û, …}} 2` -| German | $`\left(\begin{array}{l}\text{Trac-Wiki muß auch deutsche Umlaute richtig anzeigen:} \\ \text{ö, ä, ü, Ä, Ö, Ü; und das scharfe ß}\end{array}\right)` -| Greek | $`\dfrac{\text{Τα Ελληνικά υποστηρίζονται επαρκώς επίσης.}} 2` -| Hebrew | $`\dfrac{\text{אני יכול לאכול זכוכית וזה לא מזיק לי}} 2` -| Hindi | $`\dfrac{\text{अब हिन्दी में।}} 2` -| Hungarian | $`\dfrac{\text{Árvíztűrő tükörfúrógép}} 2` -| Icelandic | $`\dfrac{\text{Ævar sagði við ömmu sína: Sjáðu hvað ég er stór!}} 2` -| Japanese | $`\dfrac{\text{漢字 ひらがな カタカナ ハンカクカナ 日本語試験}} 2` -| Korean | $`\dfrac{\text{이번에는 한글로 써보겠습니다. 잘 보이나요? 한글}} 2` -| Latvian | $`\dfrac{\text{Latviešu valoda arī strādā!}} 2` -| Lithuanian | $`\left(\begin{array}{l}\text{Sudalyvaukime ir mes. Ar veikia lietuviškos raidės?} \\ \text{ąčęėįšųūž ĄČĘĖĮŠŲŪŽ Žinoma, kad veikia :) Kas tie mes?}\end{array}\right)` -| Persian (Farsi) | $`\left(\begin{array}{l}\text{ولی امکان نوشتن مستقیم فارسی نیست چون حالت متن از راست به چپ و جود} \\ \text{این یک متن فارسی است ندارد برای فارسی نوشتن باید از HTML استفاده کنید.}\end{array}\right)` -| Polish | $`\left(\begin{array}{l}\text{Pchnąć w tę łódź jeża lub osiem skrzyń fig;} \\ \text{Nocna gżegżółka zawsze dzienną przekuka.}\end{array}\right)` -| Portuguese | $`\left(\begin{array}{l}\text{É possível guardar caracteres especias da língua portuguesa, } \\ \text{incluindo o símbolo da moeda européia '€', trema 'ü', crase 'à', agudos 'áéíóú',} \\ \text{circunflexos 'âêô', til 'ãõ', cedilha 'ç', ordinais 'ªº', grau '°¹²³'.}\end{array}\right)` -| Russian | $`\dfrac{(\text{Проверка русского языка: кажется работает... И буква "ё" есть...}} 2` -| Serbian | $`\left(\begin{array}{l}\text{Podržan, uprkos činjenici da se za njegovo} \\ \text{pisanje koriste чак два алфабета.}\end{array}\right)` -| Slovenian | $`\dfrac{\text{Ta suhi škafec pušča vodo že od nekdaj!}} 2` -| Spanish | $`\left(\begin{array}{l}\text{Esto es un pequeño texto en Español,} \\ \text{donde el veloz murciélago hindú comía cardlllo y kiwi}\end{array}\right)` -| Swedish | $`\dfrac{\text{Räven raskar över isen med luva på.}} 2` -| Thai | $`\dfrac{\text{Trac แสดงภาษาไทยได้อย่างถูกต้อง!}} 2` -| Ukrainian | $`\dfrac{\text{Перевірка української мови...}} 2` -| Urdu | $`\dfrac{\text{ٹریک اردو بھی سپورٹ کرتا ہے۔}} 2` -| Vietnamese | $`\dfrac{\text{Viết tiếng Việt cũng được.}} 2` - -
    - - diff --git a/test/auto-render.js b/test/auto-render.js deleted file mode 100644 index 0b0b00dc..00000000 --- a/test/auto-render.js +++ /dev/null @@ -1,212 +0,0 @@ -var autorender = (function () { - 'use strict'; - - /* eslint no-constant-condition:0 */ - const findEndOfMath = function(delimiter, text, startIndex) { - // Adapted from - // https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx - let index = startIndex; - let braceLevel = 0; - - const delimLength = delimiter.length; - - while (index < text.length) { - const character = text[index]; - - if (braceLevel <= 0 && text.slice(index, index + delimLength) === delimiter) { - return index; - } else if (character === "\\") { - index++; - } else if (character === "{") { - braceLevel++; - } else if (character === "}") { - braceLevel--; - } - - index++; - } - - return -1; - }; - - const escapeRegex = function(string) { - return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"); - }; - - const amsRegex = /^\\begin{/; - - const splitAtDelimiters = function(text, delimiters) { - let index; - const data = []; - - const regexLeft = new RegExp( - "(" + delimiters.map((x) => escapeRegex(x.left)).join("|") + ")" - ); - - while (true) { - index = text.search(regexLeft); - if (index === -1) { - break; - } - if (index > 0) { - data.push({ - type: "text", - data: text.slice(0, index) - }); - text = text.slice(index); // now text starts with delimiter - } - // ... so this always succeeds: - const i = delimiters.findIndex((delim) => text.startsWith(delim.left)); - index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length); - if (index === -1) { - break; - } - const rawData = text.slice(0, index + delimiters[i].right.length); - const math = amsRegex.test(rawData) - ? rawData - : text.slice(delimiters[i].left.length, index); - data.push({ - type: "math", - data: math, - rawData, - display: delimiters[i].display - }); - text = text.slice(index + delimiters[i].right.length); - } - - if (text !== "") { - data.push({ - type: "text", - data: text - }); - } - - return data; - }; - - /* eslint no-console:0 */ - - /* Note: optionsCopy is mutated by this method. If it is ever exposed in the - * API, we should copy it before mutating. - */ - const renderMathInText = function(text, optionsCopy) { - const data = splitAtDelimiters(text, optionsCopy.delimiters); - if (data.length === 1 && data[0].type === "text") { - // There is no formula in the text. - // Let's return null which means there is no need to replace - // the current text node with a new one. - return null; - } - - const fragment = document.createDocumentFragment(); - - for (let i = 0; i < data.length; i++) { - if (data[i].type === "text") { - fragment.appendChild(document.createTextNode(data[i].data)); - } else { - const span = document.createElement("span"); - let math = data[i].data; - // Override any display mode defined in the settings with that - // defined by the text itself - optionsCopy.displayMode = data[i].display; - try { - if (optionsCopy.preProcess) { - math = optionsCopy.preProcess(math); - } - temml.render(math, span, optionsCopy); - } catch (e) { - if (!(e instanceof temml.ParseError)) { - throw e; - } - optionsCopy.errorCallback( - "temml auto-render: Failed to parse `" + data[i].data + "` with ", - e - ); - fragment.appendChild(document.createTextNode(data[i].rawData)); - continue; - } - fragment.appendChild(span); - } - } - - return fragment; - }; - - const renderElem = function(elem, optionsCopy) { - for (let i = 0; i < elem.childNodes.length; i++) { - const childNode = elem.childNodes[i]; - if (childNode.nodeType === 3) { - // Text node - const frag = renderMathInText(childNode.textContent, optionsCopy); - if (frag) { - i += frag.childNodes.length - 1; - elem.replaceChild(frag, childNode); - } - } else if (childNode.nodeType === 1) { - // Element node - const className = " " + childNode.className + " "; - const shouldRender = - optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) === -1 && - optionsCopy.ignoredClasses.every((x) => className.indexOf(" " + x + " ") === -1); - - if (shouldRender) { - renderElem(childNode, optionsCopy); - } - } - // Otherwise, it's something else, and ignore it. - } - }; - - const renderMathInElement = function(elem, options) { - if (!elem) { - throw new Error("No element provided to render"); - } - - const optionsCopy = {}; - - // Object.assign(optionsCopy, option) - for (const option in options) { - if (options.hasOwnProperty(option)) { - optionsCopy[option] = options[option]; - } - } - - // default options - optionsCopy.delimiters = optionsCopy.delimiters || [ - { left: "$$", right: "$$", display: true }, - { left: "\\(", right: "\\)", display: false }, - // LaTeX uses $…$, but it ruins the display of normal `$` in text: - // {left: "$", right: "$", display: false}, - // $ must come after $$ - - // Render AMS environments even if outside $$…$$ delimiters. - { left: "\\begin{equation}", right: "\\end{equation}", display: true }, - { left: "\\begin{align}", right: "\\end{align}", display: true }, - { left: "\\begin{alignat}", right: "\\end{alignat}", display: true }, - { left: "\\begin{gather}", right: "\\end{gather}", display: true }, - { left: "\\begin{CD}", right: "\\end{CD}", display: true }, - - { left: "\\[", right: "\\]", display: true } - ]; - optionsCopy.ignoredTags = optionsCopy.ignoredTags || [ - "script", - "noscript", - "style", - "textarea", - "pre", - "code", - "option" - ]; - optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || []; - optionsCopy.errorCallback = optionsCopy.errorCallback || console.error; - - // Enable sharing of global macros defined via `\gdef` between different - // math elements within a single call to `renderMathInElement`. - optionsCopy.macros = optionsCopy.macros || {}; - - renderElem(elem, optionsCopy); - }; - - return renderMathInElement; - -}()); diff --git a/test/katex-tests.md b/test/katex-tests.md deleted file mode 100644 index 88d4c05a..00000000 --- a/test/katex-tests.md +++ /dev/null @@ -1,1159 +0,0 @@ - - - - - - Temml Screen Tests - - - - - - - - -# Tests from KaTeX - -This file renders examples from KaTeX’s -[screenshotter tests](https://github.com/KaTeX/KaTeX/blob/main/test/screenshotter/ss_data.yaml).\ -Images from LaTeX are also provided for comparison.\ -(Images come from [LaTeX Previewer](http://www.tlhiv.org/ltxpreview/), thanks.) - -#### Accents - -+---------------------------+---------------------------------------+--------------------------------+ -| Source | Temml | LaTeX | -+===========================+=======================================+================================+ -| \vec{A}\vec{x}\vec x^2 \ | $`\vec{A}\vec{x}\vec x^2\vec{x}_2^2 | ![accents](images/accents.svg) | -| \vec{x}_2^2 \vec{A}^2 \ | \vec{A}^2\vec{xA}^2\; \underbar{X}` | | -| \vec{xA}^2\; \underbar{X} | | | -+---------------------------+---------------------------------------+--------------------------------+ - -#### AccentsText - -+---+---------------------------------------------------------------------------------------------------------------+------------------+ -| | $``\begin{array}{lccccc} \text{\'\i} & \text{\.\i} & \text{\`\i} & \text{\"\i} & \text{\H\i} & \text{\r\i} \\ | ![AccentsText][] | -| | \text{\'\j} & \text{\.\j} & \text{\`\j} & \text{\"\j} & \text{\H\j} & \text{\r\j} \\ | | -| | \text{\'a} & \text{\.a} & \text{\`a} & \text{\"a} & \text{\H{a}} & \text{\r{a}} \\ | | -| | \text{\'A} & \text{\.A} & \text{\`A} & \text{\"A} & \text{\H{A}} & \text{\r{A}} \\ | | -| | \text{\.I İ} & \text{\H e e̋} & \text{\i ı} \end{array}`` | | -+---+---------------------------------------------------------------------------------------------------------------+------------------+ - -[AccentsText]: images/AccentsText.svg - -#### Actuarial Angle - -+--------------------------+---------------------------+--------------------------+ -| `a_{\angl n}\; a_\angln` | $`a_{\angl n}\; a_\angln` | ![angl](images/angl.svg) | -+--------------------------+---------------------------+--------------------------+ - -#### Align - -+---------------------------+------------------------------------+ -| \begin{align} \ | $$\begin{align}a &= 1 & b &= 2 \\ | -| a &= 1 & b &= 2 \\\\ \ | 3a &= 3 & 17b &= 34\end{align}$$ | -| 3a &= 3 & 17b &= 34 \ | | -| \end{align} | | -+---------------------------+------------------------------------+ -{colWidths="null 200"} - -#### Alignat - -+--------------------------------------------------+------------------------------------------------+ -| \begin{alignat}{3} \ | $$\begin{alignat}{3} | -| a &= 1\quad & b &= 2 &\quad c &= 3\\\\ \ | a &= 1\quad & b &= 2 &\quad c &= 3\\ | -| 3a &= 3 &\quad 17b &= 34 &\quad 400c &= 1200 \ | 3a &= 3 &\quad 17b &= 34 &\quad 400c &= 1200 | -| \end{alignat} | \end{alignat}$$ | -+--------------------------------------------------+------------------------------------------------+ -{colWidths="null 350"} - -#### Aligned - -+---------------------------+-------------------------------------+--------------------------------+ -| \begin{aligned} \ | $`\begin{aligned}a &= 1 & b &= 2 \\ | ![aligned](images/aligned.svg) | -| a &= 1 & b &= 2 \\\\ \ | 3a &= 3 & 17b &= 34\end{aligned}` | | -| 3a &= 3 & 17b &= 34 \ | | | -| \end{aligned} | | | -+---------------------------+-------------------------------------+--------------------------------+ - -#### Alignedat - -+--------------------------------------------------+------------------------------------------------+----------------+ -| \begin{alignedat}{3} \ | $$\begin{alignedat}{3} | ![alignedat][] | -| a &= 1\quad & b &= 2 &\quad c &= 3\\\\ \ | a &= 1\quad & b &= 2 &\quad c &= 3\\ | | -| 3a &= 3 &\quad 17b &= 34 &\quad 400c &= 1200 \ | 3a &= 3 &\quad 17b &= 34 &\quad 400c &= 1200 | | -| \end{alignedat} | \end{alignedat}$$ | | -+--------------------------------------------------+------------------------------------------------+----------------+ - -[alignedat]: images/alignedat.svg - -#### Arrays - -This LaTeX image does include dashed lines.\ -LaTeX Previewer does not include the `arydshln` package. - -+-------------------------------------------------------------+----------------------------------------------------------+---------------+ -| \left(\begin{array}{|rl:c|} | $`\left(\begin{array}{|rl:c|} | ![Arrays][] | -| 1&2&3\\\\ \hline \ | 1&2&3\\ \hline | | -| 1+1&2+1&3+1\cr1\over2&\scriptstyle 1/2&\frac 1 2\\\\ \ | 1+1&2+1&3+1\cr1\over2&\scriptstyle 1/2&\frac 1 2\\ | | -| \hdashline \ | \hdashline | | -| \begin{pmatrix}x\\\\y\end{pmatrix}&0& \ | \begin{pmatrix}x\\y\end{pmatrix}&0& | | -| \begin{vmatrix}a&b\\\\c&d\end{vmatrix} \ | \begin{vmatrix}a&b\\c&d\end{vmatrix} | | -| \end{array}\right] | \end{array}\right]` | | -+-------------------------------------------------------------+----------------------------------------------------------+---------------+ -| \begin{smallmatrix} a & b \\\\ c & d \end{smallmatrix} \ | $`\begin{smallmatrix} a & b \\ c & d \end{smallmatrix}` | ![subarray][] | -| \begin{subarray}{c}a \\\\ b\end{subarray} | $`\begin{subarray}{c}a \\ b\end{subarray}` | | -+-------------------------------------------------------------+----------------------------------------------------------+---------------+ - -[Arrays]: images/Arrays.svg -[subarray]: images/subarray.svg - -#### ArrayMode - -+---+---------------------------------------------------------------+------------------------------------+ -| | $$\begin{matrix} \frac{\partial^2 f}{\partial x_1^2} & | ![ArrayMode](images/ArrayMode.svg) | -| | \frac{\partial^2 f}{\partial x_1\,\partial x_2} & | | -| | \cdots & \frac{\partial^2 f}{\partial x_1\,\partial x_n} \\ | | -| | \frac{\partial^2 f}{\partial x_2\,\partial x_1} & | | -| | \frac{\partial^2 f}{\partial x_2^2} & | | -| | \cdots & \frac{\partial^2 f}{\partial x_2\,\partial x_n} \\ | | -| | \vdots & \vdots & \ddots & \vdots \\ | | -| | \frac{\partial^2 f}{\partial x_n\,\partial x_1} & | | -| | \frac{\partial^2 f}{\partial x_n\,\partial x_2} & | | -| | \cdots & \frac{\partial^2 f}{\partial x_n^2} | | -| | \end{matrix}$$ | | -+---+---------------------------------------------------------------+------------------------------------+ - -#### ArrayType - -+-------------------------------------+--------------------------------------+------------------------------------+ -| 1\begin{array}{c}2\\\\3\end{array}4 | $`1\begin{array}{c}2\\3\end{array}4` | ![ArrayType](images/ArrayType.svg) | -+-------------------------------------+--------------------------------------+------------------------------------+ - -#### ArrayRemoveEmptyLine - -A `\\` at the end of a matrix should not create another line. - -+---------------------------------------------+--------------------------------------------+ -| \begin{pmatrix} 1 \\\\ 2 \\\\ \end{pmatrix} | $`\begin{pmatrix} 1 \\ 2 \\ \end{pmatrix}` | -+---------------------------------------------+--------------------------------------------+ - -#### Baseline - -+----------------+-------------------+----------------------------------+ -| a+b-c\cdot d/e | $`a+b-c\cdot d/e` | ![Baseline](images/baseline.svg) | -+----------------+-------------------+----------------------------------+ - -#### BasicTest - -$`a` - -#### BinCancellation - -+--------------------------------------------+-------------------------------------------+----------------------+ -| \begin{array}{cccc} \ | $`\begin{array}{cccc} | ![BinCancellation][] | -| +1 & 1+ & 1+1 & (,) \\\\ \ | +1 & 1+ & 1+1 & (,) \\ | | -| 1++1 & 3\times) & 1+, & \left(,\right) \ | 1++1 & 3\times) & 1+, & \left(,\right) | | -| \end{array} | \end{array}` | | -+--------------------------------------------+-------------------------------------------+----------------------+ - -[BinCancellation]: images/BinCancellation.svg - -#### Binom - -+----------------------------------------------+-------------------------------------------------+------------+ -| \dbinom{a}{b}\tbinom{a}{b}^{\binom{a}{b}+17} | $`\dbinom{a}{b}\tbinom{a}{b}^{\binom{a}{b}+17}` | ![binom][] | -+----------------------------------------------+-------------------------------------------------+------------+ - -[binom]: images/binom.svg - -#### BoldSpacing - -+----------------------------------------+-------------------------------------------+ -| \mathbf{A}^2+\mathbf{B}_3*\mathscr{C}' | $`\mathbf{A}^2+\mathbf{B}_3*\mathscr{C}'` | -+----------------------------------------+-------------------------------------------+ - -#### BoldSymbol - -+-----------------------------------------------------+----------------------------------------------------+-----------------+ -| `\sum_{\boldsymbol{\alpha}}^{\boldsymbol{\beta}}` \ | $`\sum_{\boldsymbol{\alpha}}^{\boldsymbol{\beta}} | ![BoldSymbol][] | -| \boldsymbol{\omega}+ \ | \boldsymbol{\omega}+ | | -| `\boldsymbol{\int_\alpha^\beta}` \ | \boldsymbol{\int_\alpha^\beta} | | -| \boldsymbol{\Omega + {}} \\\\ \ | \boldsymbol{\Omega + {}} \\ | | -| \boldsymbol{\lim_{x \to \infty} \ | \boldsymbol{\lim_{x \to \infty} | | -| \log Ax2k\omega\Omega\imath+} \\\\ \ | \log Ax2k\omega\Omega\imath+} \\ | | -| x \boldsymbol{+} y \boldsymbol{=} z | x \boldsymbol{+} y \boldsymbol{=} z` | | -+-----------------------------------------------------+----------------------------------------------------+-----------------+ - -[BoldSymbol]: images/BoldSymbol.svg - -#### Boxed - -+----------------------------------------+-----------------------------------------+------------+ -| \boxed{F=ma} \quad \boxed{ac}\ | $`\boxed{F=ma} \quad \boxed{ac} | ![boxed][] | -| \color{magenta}{\boxed{F}}\boxed{F=mg} | \color{magenta}{\boxed{F}}\boxed{F=mg}` | | -+----------------------------------------+-----------------------------------------+------------+ - -[boxed]: images/boxed.svg - -#### Cases - -+----------------------------------------+------------------------------------+------------------------------+ -| f(a,b)= \ | $`f(a,b)= | ![cases](images/cases.svg) | -| \begin{cases} \ | \begin{cases} | | -| a+1&\text{if }b\text{ is odd} \\\\ \ | a+1&\text{if }b\text{ is odd} \\ | | -| a&\text{if }b=0 \\\\ \ | a&\text{if }b=0 \\ | | -| a-1&\text{otherwise} \ | a-1&\text{otherwise} | | -| \end{cases} | \end{cases}` | | -+----------------------------------------+------------------------------------+------------------------------+ -| \begin{rcases} \ | $`\begin{rcases} | ![rcases](images/rcases.svg) | -| a &\text{if } b \\\\ \ | a &\text{if } b \\ | | -| c &\text{if } d \ | c &\text{if } d | | -| \end{rcases}\Rightarrow\ldots | \end{rcases}\Rightarrow\ldots` | | -+----------------------------------------+------------------------------------+------------------------------+ - -#### CD - -+-----------------------------+-------------------------+----------------------+ -| \begin{CD} \ | $$\begin{CD} | ![CD](images/CD.svg) | -| A @>b> C \\\\ \ | A @>b> C \\ | | -| @| @AcAA @VVdV \\\\ \ | @| @AcAA @VVdV \\ | | -| D @= E @>>> F \ | D @= E @>>> F | | -| \end{CD} | \end{CD}$$ | | -+-----------------------------+-------------------------+----------------------+ - -#### Colors - -+-----------------------+-----------------------+------------------------------+ -| \textcolor{#0f0}{b} \ | $`\textcolor{#0f0}{b} | ![colors](images/colors.svg) | -| \textcolor{red}{c} | \textcolor{red}{c}` | | -+-----------------------+-----------------------+------------------------------+ - -#### ColorImplicit - -+----------------------------------+------------------------------+--------------------------------------------+ -| bl{ack\color{red}red \ | $`bl{ack\color{red}red | ![ColorImplicit](images/ColorImplicit.svg) | -| \textcolor{green}{green} \ | \textcolor{green}{green} | | -| red\color{blue}blue}black \\\\ \ | red\color{blue}blue}black \\ | | -| black\left(black \ | black\left(black | | -| \color{red}red\right)black | \color{red}red\right)black` | | -+----------------------------------+------------------------------+--------------------------------------------+ - -#### ColorSpacing - -+----------------------------+-----------------------------+------------------------------------------+ -| \textcolor{red}{x} + 1 \ | $`\textcolor{red}{x} + 1 | ![ColorSpacing](images/ColorSpacing.svg) | -| {\color{green}+ 2 +} 3 + 4 | {\color{green}+ 2 +} 3 + 4` | | -+----------------------------+-----------------------------+------------------------------------------+ - -#### Colorbox - -+----------------------------+----------------------------+----------------------------------+ -| a \colorbox{teal} B \ | $`a \colorbox{teal} B | ![Colorbox](images/Colorbox.svg) | -| \fcolorbox{blue}{red}{C} \ | \fcolorbox{blue}{red}{C} | | -| e+\colorbox{teal}x | e+\colorbox{teal}x` | | -+----------------------------+----------------------------+----------------------------------+ - -#### DashesAndQuotes - -+-----------------------------------------------------------+------------------------------------------------------+----------------------+ -| \begin{array}{l} \ | $```\begin{array}{l} | ![DashesAndQuotes][] | -| ```\text{``a'' b---c -- d----`e'-{-}-f} -- \\``` \ | \text{``a'' b---c -- d----`e'-{-}-f} -- \\ | | -| ```\text{\it ``a'' b---c -- d----`e'-{-}-f} ``x'' \\``` \ | \text{\it ``a'' b---c -- d----`e'-{-}-f} ``x'' \\ | | -| ```\text{\tt ``a''---} \texttt{``a''---} \mathtt{--}``` \ | \text{\tt ``a''---} \texttt{``a''---} \mathtt{--} \\ | | -| \end{array} | \end{array}``` | | -+-----------------------------------------------------------+------------------------------------------------------+----------------------+ - -[DashesAndQuotes]: images/DashesAndQuotes.svg - -#### DelimiterSizing - -+-----------------------------------+-----------------------------------+-----------------------+ -| \bigl\uparrow\Bigl\downarrow \ | $`\bigl\uparrow\Bigl\downarrow | ![DelimiterSizing1][] | -| \biggl\updownarrow \ | \biggl\updownarrow | | -| \Biggl\Uparrow\Biggr\Downarrow \ | \Biggl\Uparrow\Biggr\Downarrow | | -| \biggr\langle\Bigr\\}\bigr\rfloor | \biggr\langle\Bigr\}\bigr\rfloor` | | -+-----------------------------------+-----------------------------------+-----------------------+ -| \begin{pmatrix} \ | $`\begin{pmatrix} | ![DelimiterSizing2][] | -| a & b & c\\\\ \ | a & b & c\\ | | -| a & b & c\\\\ \ | a & b & c\\ | | -| a & b & c \ | a & b & c\\ | | -| \end{pmatrix} | \end{pmatrix}` | | -+-----------------------------------+-----------------------------------+-----------------------+ - -[DelimiterSizing1]: images/DelimiterSizing1.svg -[DelimiterSizing2]: images/DelimiterSizing2.svg - -#### DisplayMode - -+-------------------------------+-----------------------------------+----------------------------------------+ -| \sum_{i=0}^\infty \frac{1}{i} | $$\sum_{i=0}^\infty \frac{1}{i}$$ | ![DisplayMode](images/DisplayMode.svg) | -+-------------------------------+-----------------------------------+----------------------------------------+ - -#### DisplayStyle - -+----------------------------------------+---------------------------------------+-------------------+ -| {\displaystyle\sqrt{x}}{\sqrt{x}} \ | $`{\displaystyle\sqrt{x}}{\sqrt{x}} | ![displaystyle][] | -| {\displaystyle \frac 1 2}{\frac 1 2} \ | {\displaystyle \frac 1 2}{\frac 1 2} | | -| `{\displaystyle x^1_2}{x^1_2}` | {\displaystyle x^1_2}{x^1_2}` | | -+----------------------------------------+---------------------------------------+-------------------+ - -[displaystyle]: images/displaystyle.svg - -#### Dots - -+---------------------------------------------+-----------------------------------------+--------------------------+ -| \begin{array}{l} \ | $`\begin{array}{l} | ![dots](images/dots.svg) | -| \cdots;\dots+\dots\int\dots,\dots \\\\ \ | \cdots;\dots+\dots\int\dots,\dots \\ | | -| \cdots{};\ldots+\ldots\int\ldots,\ldots \ | \cdots{};\ldots+\ldots\int\ldots,\ldots | | -| \end{array} | \end{array}` | | -+---------------------------------------------+-----------------------------------------+--------------------------+ - -#### Equation - -+---------------------+--------------------+----------------------------------+ -| \begin{equation} \ | $$\begin{equation} | ![equation](images/equation.svg) | -| \begin{split} \ | \begin{split} | | -| a& =b+c-d \\\\ \ | a& =b+c-d \\ | | -| & \quad +e-f \\\\ \ | & \quad +e-f \\ | | -| & =g+h \\\\ \ | & =g+h \\ | | -| & =i \ | & =i | | -| \end{split} \ | \end{split} | | -| \end{equation} | \end{equation}$$ | | -+---------------------+--------------------+----------------------------------+ -{colWidths="null 150"} - -#### Exponents - -+---------------------+----------------------+------------------------------------+ -| `a^{a^a_a}_{a^a_a}` | $`a^{a^a_a}_{a^a_a}` | ![exponents](images/exponents.svg) | -+---------------------+----------------------+------------------------------------+ - -#### ExtensibleArrows - -+------------------------------------+----------------------------------+-----------------------+ -| \begin{array}{l} \ | $`\begin{array}{l} | ![ExtensibleArrows][] | -| \xrightarrow[ab]{ABC} + \ | \xrightarrow[ab]{ABC} + | | -| \xRightarrow{ABC} \\\\ \ | \xRightarrow{ABC} \\ | | -| \xleftrightharpoons[ab]{ABC} + \ | \xleftrightharpoons[ab]{ABC} + | | -| \xhookrightarrow[ab]{ABC} \\\\ \ | \xhookrightarrow[ab]{ABC} \\ | | -| \xmapsto{ABC} + \ | \xmapsto{ABC} + | | -| \frac{\xrightarrow[ab]{ABC}} \ | \frac{\xrightarrow[ab]{ABC}} | | -| {\xrightarrow[ab]{ABC}} + \ | {\xrightarrow[ab]{ABC}} + | | -| \left\lvert\xrightarrow[ab]{ABC} \ | \left\lvert\xrightarrow[ab]{ABC} | | -| \right\rvert \ | \right\rvert | | -| \end{array} | \end{array}` | | -+------------------------------------+----------------------------------+-----------------------+ - -[ExtensibleArrows]: images/ExtensibleArrows.svg - -#### Fractions - -+----------------------------------------------------+--------------------------------------------------+-----------------+ -| \dfrac{a}{b}\frac{a}{b} \ | $`\dfrac{a}{b}\frac{a}{b} | ![Fractions1][] | -| \tfrac{a}{b}\\;- \ | \tfrac{a}{b}\;- | | -| \dfrac 1 2\\;1\tfrac 1 2\\;{1 \atop 2}\\; \ | \dfrac 1 2\;1\tfrac 1 2\;{1 \atop 2}\; | | -| {a \brace b} \\; {a \brack b} | {a \brace b} \; {a \brack b}` | | -+----------------------------------------------------+--------------------------------------------------+-----------------+ -| \genfrac \\{ ]{0.8pt}{0}{a}{b}\\; \ | $`\genfrac \{ ]{0.8pt}{0}{a}{b}\; | ![Fractions2][] | -| {a \above1.0pt b} \\; \ | {a \above1.0pt b} \; | | -| \cfrac{1}{1+\cfrac{1}{x}} \ | \cfrac{1}{1+\cfrac{1}{x}} | | -| \xrightarrow[\dfrac g h]{\displaystyle\frac g h} \ | \xrightarrow[\dfrac g h]{\displaystyle\frac g h} | | -| \\; \xrightarrow [2.\\, \dfrac c d] \ | \; \xrightarrow [2.\, \dfrac c d] | | -| {1.\\, \displaystyle\frac c d} | {1.\, \displaystyle\frac c d}` | | -+----------------------------------------------------+--------------------------------------------------+-----------------+ - -[Fractions1]: images/Fractions1.svg -[Fractions2]: images/Fractions2.svg - -#### Functions - -+---------------------+------------------------+------------------------------------+ -| \sin\cos\tan\ln\log | $`\sin\cos\tan\ln\log` | ![functions](images/functions.svg) | -+---------------------+------------------------+------------------------------------+ - -#### Gather - -+--------------------+------------------+------------------------------+ -| \begin{gather} \ | $$\begin{gather} | ![gather](images/gather.svg) | -| a=\frac 1 2 \\\\ \ | a=\frac 1 2 \\ | | -| e=b+c \ | e=b+c | | -| \end{gather} | \end{gather}$$ | | -+--------------------+------------------+------------------------------+ -{colWidths="null 150 null"} - -#### GreekLetters - -+-------------------------+----------------------------+----------------------------+ -| \alpha\beta\gamma\omega | $`\alpha\beta\gamma\omega` | ![greek](images/greek.svg) | -+-------------------------+----------------------------+----------------------------+ - -#### GreekUnicode - -+--------------------------------------------+-----------------------------------------------+ -| \frac{αβγδεϵζηθϑικλμνξοπϖρϱςστυφϕχψω} \ | $`\frac{αβγδεϵζηθϑικλμνξοπϖρϱςστυφϕχψω} | -| {ΓΔΘΞΠΣΦΨΩϝ\mathbf{Ω}\mathbf{\Omega}} | {ΓΔΘΞΠΣΦΨΩϝ\mathbf{Ω}\mathbf{\Omega}}` | -+--------------------------------------------+-----------------------------------------------+ - -#### HorizontalBraces - -+------------------------------------------------+-----------------------------------------------+-----------------------+ -| \overbrace{\displaystyle{ \ | $`\overbrace{\displaystyle{ | ![HorizontalBraces][] | -| `\oint_S{\vec E\cdot\hat n\,\mathrm d a}}}^` \ | \oint_S{\vec E\cdot\hat n\,\mathrm d a}}}^ | | -| \text{emf} = \ | \text{emf} = | | -| `\underbrace{\frac{q_{` \ | \underbrace{\frac{q_{ | | -| `\text{enc}}}{\varepsilon_0}}_{\text{charge}}` | \text{enc}}}{\varepsilon_0}}_{\text{charge}}` | | -+------------------------------------------------+-----------------------------------------------+-----------------------+ - -[HorizontalBraces]: images/HorizontalBraces.svg - -#### HTML - -+-----------------------------------+--------------------------------------+-----+ -| \id{a}{a+}b\style{color:red;}{+c} | $`\id{a}{a+}b\style{color:red;}{+c}` | N/A | -+-----------------------------------+--------------------------------------+-----+ - -#### Includegraphics - -$`\def\logo{\includegraphics[height=0.8em, totalheight=0.9em, width=0.9em, alt=sphere]{../docs/sphere.jpg}} -\def\logoB{\includegraphics[height=0.4em, totalheight=0.9em, width=0.9em, alt=sphere]{../docs/sphere.jpg}} -\begin{array}{l} \underline{A\logo} + \sqrt{\logo} + \tfrac{A\logo}{\logo}\\[1em] \underline{A\logoB} + \sqrt{x\logoB} + \tfrac{A\logoB}{\logoB} \end{array}` - -#### Integrands - -+------------------------------------+----------------------------------+--------------------------------------+ -| \begin{array}{l} \ | $`\begin{array}{l} | ![Integrands](images/Integrands.svg) | -| \displaystyle \int + \oint + \ | \displaystyle \int + \oint + | | -| `\iint + \oiint_i^n \\` \ | \iint + \oiint_i^n \\ | | -| \displaystyle \iiint + \oiiint + \ | \displaystyle \iiint + \oiiint + | | -| `\textstyle \int + \oint_i^n \\` \ | \textstyle \int + \oint_i^n \\ | | -| \iint + \oiint + \ | \iint + \oiint + | | -| \iiint + \oiiint \end{array} | \iiint + \oiiint \end{array}` | | -+------------------------------------+----------------------------------+--------------------------------------+ - -#### Kern - -+----------------------------+-----------------------------+--------------------------+ -| \frac{a\kern{1em}b}{c}a \ | $`\frac{a\kern{1em}b}{c}a | ![kern](images/kern.svg) | -| \kern{1em}b \ | \kern{1em}b | | -| \kern{1ex}c\kern{-0.25em}d | \kern{1ex}c\kern{-0.25em}d` | | -+----------------------------+-----------------------------+--------------------------+ - - -#### Lap - -+----------------------------------------------------+--------------------------------------------------+----------+ -| \begin{array}{l} \ | $`\begin{array}{l} | ![lap][] | -| ab\mathllap{f}cd\mathrlap{g}hij\mathclap{k}lm \; \ | ab\mathllap{f}cd\mathrlap{g}hij\mathclap{k}lm \; | | -| ab\llap{f}cd\rlap{g}hij\clap{k}lm \\\\ \ | ab\llap{f}cd\rlap{g}hij\clap{k}lm \\ | | -| \mathrlap{\frac a b}\frac a b \\\\ \ | \mathrlap{\frac a b}{\frac a b} \\ | | -| \mathrlap{\overbrace{ \ | \mathrlap{\overbrace{ | | -| `\phantom{a_0+a_1+a_2}}^m}a_0+a_1+a_2` \ | \phantom{a_0+a_1+a_2}}^m}a_0+a_1+a_2 | | -| \end{array} | \end{array}` | | -+----------------------------------------------------+--------------------------------------------------+----------+ - -[lap]: images/lap.svg - -#### LargeRuleNumerator - -+--------------------------+--------------------------+------------------------------------------------------+ -| \frac{\textcolor{blue} \ | $`\frac{\textcolor{blue} | ![LargeRuleNumerator](images/LargeRuleNumerator.svg) | -| {\rule{1em}{2em}}}{x} | {\rule{1em}{2em}}}{x}` | | -+--------------------------+--------------------------+------------------------------------------------------+ - -#### LaTeX - -+----------------------------+-------------------------------+----------------------------+ -| \text{\LaTeX}, \text{\TeX} | $`\text{\LaTeX}, \text{\TeX}` | ![latex](images/latex.svg) | -+----------------------------+-------------------------------+----------------------------+ - -#### LeftRight - -+----------------------------------+----------------------------------+------------------------------------+ -| \left( x^2 \right) \ | $`\left( x^2 \right) | ![LeftRight](images/LeftRight.svg) | -| \left\\{ x^{x^{x^{x^x}}} \right. | \left\{ x^{x^{x^{x^x}}} \right.` | | -+----------------------------------+----------------------------------+------------------------------------+ - -#### LeftRightListStyling - -+----------------------+-------------------------+----------------------------------------------------------+ -| a+\left(x+y\right)-x | $`a+\left(x+y\right)-x` | ![LeftRightListStyling](images/LeftRightListStyling.svg) | -+----------------------+-------------------------+----------------------------------------------------------+ - -#### LeftRightMiddle - -+----------------------------------------+----------------------------------------+----------------------+ -| \left( x^2 \middle/ \right) \ | $`\left( x^2 \middle/ \right) | ![LeftRightMiddle][] | -| \left\\{ x^{x^{x^{x^x}}} \ | \left\{ x^{x^{x^{x^x}}} | | -| \middle/ y \right. \ | \middle/ y \right. | | -| \left(x\middle|y\\,\middle|\\,z\right) | \left(x\middle|y\,\middle|\,z\right)` | | -+----------------------------------------+----------------------------------------+----------------------+ - -[LeftRightMiddle]: images/LeftRightMiddle.svg - -#### LeftRightStyleSizing - -+----------------------------------------+-----------------------------------------+---------------------------+ -| +\left\\{\rule{0.1em}{1em}\right. \ | $`+\left\{\rule{0.1em}{1em}\right. | ![LeftRightStyleSizing][] | -| x^{+\left\\{\rule{0.1em}{1em}\right. \ | x^{+\left\{\rule{0.1em}{1em}\right. | | -| x^{+\left\\{\rule{0.1em}{1em}\right.}} | x^{+\left\{\rule{0.1em}{1em}\right.}}` | | -+----------------------------------------+-----------------------------------------+---------------------------+ - -[LeftRightStyleSizing]: images/LeftRightStyleSizing.svg - -#### LimitControls - -+-------------------------------------------+------------------------------------------+--------------------+ -| `\displaystyle\int\limits_2^3 3x^2\,dx` \ | $`\displaystyle\int\limits_2^3 3x^2\,dx | ![LimitControls][] | -| `+ \sum\nolimits^n_{i=1}i + ` \ | + \sum\nolimits^n_{i=1}i + | | -| `\textstyle\int\limits_x^y z ` | \textstyle\int\limits_x^y z` | | -+-------------------------------------------+------------------------------------------+--------------------+ - -[LimitControls]: images/LimitControls.svg - -#### LineBreak - -Firefox will apply soft lines breaks after relationss and binary operators. - -$`\frac{x^2}{y^2} + z^2 = z^2 + \frac{x^2}{y^2} = \frac{x^2}{y^2} +\nobreak z^2 = z^2 + \frac{x^2}{y^2} = \frac{x^2}{y^2} + ~ z^2 = z^2 + \frac{x^2}{y^2} = \frac{x^2}{y^2} + \hspace{1em} z^2 = z^2 + \frac{x^2}{y^2} = \frac{x^2}{y^2} + z^2 = \hspace*{1em} z^2 + \frac{x^2}{y^2} = \frac{x^2}{y^2} + z^2 = hi \allowbreak there = hi \allowbreak there` - -#### LowerAccent - -+--------------------------------------------------------+------------------------------------------------------+ -| \begin{array}{l} \ | $`\begin{array}{l} | -| \underleftarrow{AB} \quad \underrightarrow{AB} \quad \ | \underleftarrow{AB} \quad \underrightarrow{AB} \quad | -| \underleftrightarrow{AB} \quad \undergroup{AB} \\\\ \ | \underleftrightarrow{AB} \quad \undergroup{AB} \\ | -| \text{\underline{text}} \quad \utilde{AB} \ | \text{\underline{text}} \quad \utilde{AB} | -| \quad \underrightarrow{AB} \\\\ \ | \quad \underrightarrow{AB} \\ | -| \underrightarrow{F} + \underrightarrow{AB} + \ | \underrightarrow{F} + \underrightarrow{AB} + | -| \underrightarrow{AB}^2 + \underrightarrow{AB}_2 \\\\ \ | \underrightarrow{AB}^2 + \underrightarrow{AB}_2 \\ | -| \frac{\underrightarrow{AB}}{\underrightarrow{AB}} + \ | \frac{\underrightarrow{AB}}{\underrightarrow{AB}} + | -| \sqrt{\underrightarrow{AB}} + \ | \sqrt{\underrightarrow{AB}} + | -| \left\lvert\underrightarrow{AB}\right\rvert \ | \left\lvert\underrightarrow{AB}\right\rvert | -| \end{array} | \end{array}` | -+--------------------------------------------------------+------------------------------------------------------+ - -#### MathChoice - -+---------------------------------------------------+------------------------------------------------+-----------------+ -| {\displaystyle\mathchoice{D}{T}{S}{SS}}\\; \ | $`{\displaystyle\mathchoice{D}{T}{S}{SS}}\; | ![MathChoice][] | -| {\textstyle\mathchoice{D}{T}{S}{SS}}\\; \ | {\textstyle\mathchoice{D}{T}{S}{SS}}\; | | -| {\scriptstyle \mathchoice{D}{T}{S}{SS}}\\; \ | {\scriptstyle \mathchoice{D}{T}{S}{SS}}\; | | -| {\scriptscriptstyle\mathchoice{D}{T}{S}{SS}}\\; \ | {\scriptscriptstyle\mathchoice{D}{T}{S}{SS}}\; | | -| \displaystyle X\_{\mathchoice{D}{T}{S}{SS}\_ \ | \displaystyle X_{\mathchoice{D}{T}{S}{SS}_ | | -| {\mathchoice{D}{T}{S}{SS}}} | {\mathchoice{D}{T}{S}{SS}}}` | | -+---------------------------------------------------+------------------------------------------------+-----------------+ - -[MathChoice]: images/MathChoice.svg - -#### MathDefaultFonts - -+---------------------------------+------------------------------------+ -| Ax2k\breve{a}\omega\Omega\imath | $`Ax2k\breve{a}\omega\Omega\imath` | -+---------------------------------+------------------------------------+ - -#### MathBb - -+------------------------------------------+---------------------------------------------+ -| \mathbb{Ax2k\breve{a}\omega\Omega\imath} | $`\mathbb{Ax2k\breve{a}\omega\Omega\imath}` | -+------------------------------------------+---------------------------------------------+ - -#### MathBf - -+------------------------------------------+---------------------------------------------+ -| \mathbf{Ax2k\breve{a}\omega\Omega\imath} | $`\mathbf{Ax2k\breve{a}\omega\Omega\imath}` | -+------------------------------------------+---------------------------------------------+ - -#### MathCal - -+-------------------------------------------+----------------------------------------------+ -| \mathcal{Ax2k\breve{a}\omega\Omega\imath} | $`\mathcal{Ax2k\breve{a}\omega\Omega\imath}` | -+-------------------------------------------+----------------------------------------------+ - -#### MathFrak - -+--------------------------------------------+-----------------------------------------------+ -| \mathfrak{Ax2k\breve{a}\omega\Omega\imath} | $`\mathfrak{Ax2k\breve{a}\omega\Omega\imath}` | -+--------------------------------------------+-----------------------------------------------+ - -#### MathIt - -+------------------------------------------+---------------------------------------------+ -| \mathit{Ax2k\breve{a}\omega\Omega\imath} | $`\mathit{Ax2k\breve{a}\omega\Omega\imath}` | -+------------------------------------------+---------------------------------------------+ - -#### MathNormal - -+----------------------------------------------+-------------------------------------------------+ -| \mathnormal{Ax2k\breve{a}\omega\Omega\imath} | $`\mathnormal{Ax2k\breve{a}\omega\Omega\imath}` | -+----------------------------------------------+-------------------------------------------------+ - -#### MathOp - -+--------------------------------------+--------------------------------------+------------------------------+ -| a\mathop+b\mathop:c\mathop{\delta} \ | $`a\mathop+b\mathop:c\mathop{\delta} | ![mathop](images/mathop.svg) | -| e\mathop{\textrm{and}}f \ | e\mathop{\textrm{and}}f | | -| \mathrel{\mathop{:}}=g\sin h | \mathrel{\mathop{:}}=g\sin h` | | -+--------------------------------------+--------------------------------------+------------------------------+ - -#### MathRm - -+------------------------------------------+---------------------------------------------+ -| \mathrm{Ax2k\breve{a}\omega\Omega\imath} | $`\mathrm{Ax2k\breve{a}\omega\Omega\imath}` | -+------------------------------------------+---------------------------------------------+ - -#### MathSf - -+------------------------------------------+---------------------------------------------+ -| \mathsf{Ax2k\breve{a}\omega\Omega\imath} | $`\mathsf{Ax2k\breve{a}\omega\Omega\imath}` | -+------------------------------------------+---------------------------------------------+ - -#### MathScr - -+-------------------------------------------+----------------------------------------------+ -| \mathscr{Ax2k\breve{a}\omega\Omega\imath} | $`\mathscr{Ax2k\breve{a}\omega\Omega\imath}` | -+-------------------------------------------+----------------------------------------------+ - -#### MathtoolsMatrix - -+-----------------------+----------------------+------------------------------------------------+ -| \begin{matrix*}[l] \ | $`\begin{matrix*}[l] | ![MathtoolsMatrix](images/MathtoolsMatrix.svg) | -| a & -1 \\\\ \ | a & -1 \\ | | -| -1 & d \ | -1 & d | | -| \end{matrix*} \\; \ | \end{matrix*} \; | | -| \begin{pmatrix*}[r] \ | \begin{pmatrix*}[r] | | -| a & -1 \\\\ \ | a & -1 \\ | | -| -1 & d \ | -1 & d | | -| \end{pmatrix*} | \end{pmatrix*}` | | -+-----------------------+----------------------+------------------------------------------------+ - -#### MathTt - -+------------------------------------------+---------------------------------------------+ -| \mathtt{Ax2k\breve{a}\omega\Omega\imath} | $`\mathtt{Ax2k\breve{a}\omega\Omega\imath}` | -+------------------------------------------+---------------------------------------------+ - -#### Mod - -+-------------------------------------------+---------------------------------------+------------------------+ -| \begin{array}{cc} | $`\begin{array}{cc} | ![mod](images/mod.svg) | -| a \bmod 2 & b \pod 3 \\\\ \ | a \bmod 2 & b \pod 3 \\ | | -| c \pmod{4} & d \mod{56} \\\\ \ | c \pmod{4} & d \mod{56} \\ | | -| \displaystyle a\bmod 2 & b \pod 3 \\\\ \ | \displaystyle a\bmod 2 & b \pod 3 \\ | | -| \displaystyle c\pmod{4} & d \mod{56} \ | \displaystyle c\pmod{4} & d \mod{56} | | -| \end{array} | \end{array}` | | -+-------------------------------------------+---------------------------------------+------------------------+ - -#### NegativeSpace - -+-------------------------+----------------------------+--------------------------------------------+ -| \boxed{\$1,\!000,\!000} | $`\boxed{\$1,\!000,\!000}` | ![NegativeSpace](images/NegativeSpace.svg) | -+-------------------------+----------------------------+--------------------------------------------+ - -#### NestedFractions - -+--------------------------------------+-------------------------------------+----------------------+ -| \dfrac{\frac{a}{b}}{\frac{c}{d}} \ | $`\dfrac{\frac{a}{b}}{\frac{c}{d}} | ![NestedFractions][] | -| \dfrac{\dfrac{a}{b}}{\dfrac{c}{d}} \ | \dfrac{\dfrac{a}{b}} {\dfrac{c}{d}} | | -| \frac{\frac{a}{b}}{\frac{c}{d}} | \frac{\frac{a}{b}}{\frac{c}{d}}` | | -+--------------------------------------+-------------------------------------+----------------------+ - -[NestedFractions]: images/NestedFractions.svg - -#### NewLine - -+--------------------------------+--------------------------------+--------------------------------+ -| \frac{a^2+b^2}{c^2} \newline \ | $`\frac{a^2+b^2}{c^2} \newline | ![newline](images/newline.svg) | -| \frac{a^2+b^2}{c^2} \\\\ \ | \frac{a^2+b^2}{c^2} \\ | | -| \begin{pmatrix} a & b \\\\ \ | \begin{pmatrix} a & b \\ | | -| c & d \cr \end{pmatrix} \\\\ \ | c & d \cr \end{pmatrix} \\ | | -| a+b+c+{d+\\\\e}+f+g | a+b+c+{d+\\e}+f+g` | | -+--------------------------------+--------------------------------+--------------------------------+ - -#### Not - -+--------------------------------------------------------+----------------------------------------------------+----------+ -| \not = \begin{array}{l} \ | $`\not = \begin{array}{l} | ![not][] | -| \not=\not>\not\geq\not\in\not<\not\leq\not{abc} \\\\ \ | \not=\not>\not\geq\not\in\not<\not\leq\not{abc} \\ | | -| \not xy + ab \not xy \\\\ \ | \not xy + ab \not xy \\ | | -| a \neq b \notin c \end{array} | a \neq b \notin c \end{array}` | | -+--------------------------------------------------------+----------------------------------------------------+----------+ - -[not]: images/not.svg - -#### NullDelimiterInteraction - -+---------------------------------------+------------------------------------------+-------------------------------+ -| a \bigl. + 2 \quad \left. + a \right) | $`a \bigl. + 2 \quad \left. + a \right)` | ![NullDelimiterInteraction][] | -+---------------------------------------+------------------------------------------+-------------------------------+ - -[NullDelimiterInteraction]: images/NullDelimiterInteraction.svg - -#### OldFont - -+------------------------------------------------------+--------------------------------------------------+--------------+ -| \begin{matrix} \ | $`\begin{matrix} | ![oldfont][] | -| \rm rm & it & \it it & \ | \rm rm & it & \it it & | | -| \bf bf & \sf sf & \tt tt \\\\ \ | \bf bf & \sf sf & \tt tt \\ | | -| \text{\rm rm} & \text{rm} & \text{\it it} & \ | \text{\rm rm} & \text{rm} & \text{\it it} & | | -| \text{\bf bf} & \text{\sf sf} & \text{\tt tt} \\\\ \ | \text{\bf bf} & \text{\sf sf} & \text{\tt tt} \\ | | -| i\rm r\it i & \text{r\it i\rm r} \ | i\rm r\it i & \text{r\it i\rm r} | | -| \end{matrix} | \end{matrix}` | | -+------------------------------------------------------+--------------------------------------------------+--------------+ - -[oldfont]: images/oldfont.svg - -#### OperatorName - -+----------------------------------------------+------------------------------------------+-------------------+ -| \begin{matrix} | $`\begin{matrix} | ![OperatorName][] | -| \operatorname g (z) + 5\operatorname{g}z \ | \operatorname g (z) + 5\operatorname{g}z | | -| + \operatorname{Gam-ma}(z) \\\\ \ | + \operatorname{Gam-ma}(z) \\ | | -| \operatorname{Gam ma}(z) \ | \operatorname{Gam ma}(z) | | -| + \operatorname{\Gamma}(z) \ | + \operatorname{\Gamma}(z) | | -| + \operatorname{}x \\\\ \ | + \operatorname{}x \\ | | -| \operatorname*{asin} x + \ | \operatorname*{asin} x + | | -| \operatorname*{asin}\_y x + \ | \operatorname*{asin}_y x + | | -| \operatorname*{asin}\limits\_y x \\\\ \ | \operatorname*{asin}\limits_y x \\ | | -| {\displaystyle \operatorname*{asin}\_y x} \ | {\displaystyle \operatorname*{asin}_y x} | | -| \end{matrix} | \end{matrix}` | | -+----------------------------------------------+------------------------------------------+-------------------+ - -[OperatorName]: images/OperatorName.svg - -#### OpLimits - -+--------------------------------------------------------------+----------------------------------------------------------+---------------+ -| \begin{matrix} \ | $`\begin{matrix} | | -| {\sin\_2^2 \lim\_2^2 \int\_2^2 \sum\_2^2} \ | {\sin_2^2 \lim_2^2 \int_2^2 \sum_2^2} | ![OpLimits][] | -| `{\displaystyle \lim_2^2 \int_2^2 \intop_2^2 \sum_2^2} \\` \ | {\displaystyle \lim_2^2 \int_2^2 \intop_2^2 \sum_2^2} \\ | | -| \limsup\_{x \rightarrow \infty} x \stackrel{?}= \ | \limsup_{x \rightarrow \infty} x \stackrel{?}= | | -| \liminf\_{x \rightarrow \infty} x \\\\ \ | \liminf_{x \rightarrow \infty} x \\ | | -| {\displaystyle \limsup\_{x \rightarrow \infty} \ | {\displaystyle \limsup_{x \rightarrow \infty} | | -| `x\:\: \sum_{\substack{00}\to0}}\\\\ \ | {\displaystyle\lim_{t\underset{>0}\to0}}\\ | | -| a+b+c+d\overset{b+c=0} \ | a+b+c+d\overset{b+c=0} | | -| \longrightarrow a+d\\\\ \ | \longrightarrow a+d\\ | | -| \overset { x = y } { \sqrt { a b } } \ | \overset { x = y } { \sqrt { a b } } | | -| \end{array} | \end{array}` | | -+------------------------------------------------+--------------------------------------------+-------------------+ - -[OverUnderset]: images/OverUnderset.svg - -#### Phantom - -+-------------------------------------------------------+---------------------------------------------------+--------------+ -| \begin{array}{l} | $`\begin{array}{l} | ![phantom][] | -| \dfrac{1+\phantom{x^{\textcolor{blue}{2}}} = x} \ | \dfrac{1+\phantom{x^{\textcolor{blue}{2}}} = x} | | -| {1+x^{\textcolor{blue}{2}} = x} \ | {1+x^{\textcolor{blue}{2}} = x} | | -| \left(\vphantom{\int_t} zzz \right) \ | \left(\vphantom{\int_t} zzz \right) | | -| \left( X \hphantom{\frac{\frac X X}{X}} \right)\\\\ \ | \left( X \hphantom{\frac{\frac X X}{X}} \right)\\ | | -| \text{a \phantom{123}} b \hphantom{\frac{1}{2}}=c \ | \text{a \phantom{123}} b \hphantom{\frac{1}{2}}=c | | -| \vphantom{101112} d \\\\ \ | \vphantom{101112} d \\ | | -| \sqrt{\mathstrut a} + \sqrt{\mathstrut d} \ | \sqrt{\mathstrut a} + \sqrt{\mathstrut d} | | -| \end{array} | \end{array}` | | -+-------------------------------------------------------+---------------------------------------------------+--------------+ - -[phantom]: images/phantom.svg - -#### Phase - -+------------------------------------+------------------------------------+ -| 120\text{V}\phase{-78.2^\circ}\; \ | $`120\text{V}\phase{-78.2^\circ}\; | -| \Large\phase{78.2^\circ} | \Large\phase{78.2^\circ}` | -+------------------------------------+------------------------------------+ - -#### Pmb - -+----------------------------------+-------------------------------------+------------------------+ -| \mu\pmb{\mu}\pmb{=}\mu\pmb{+}\mu | $`\mu\pmb{\mu}\pmb{=}\mu\pmb{+}\mu` | ![pmb](images/pmb.svg) | -+----------------------------------+-------------------------------------+------------------------+ - -#### PrimeSpacing - -+------------------+-------------------+------------------------------------------+ -| `f'+f_2'+f^{f'}` | $`f'+f_2'+f^{f'}` | ![PrimeSpacing](images/PrimeSpacing.svg) | -+------------------+-------------------+------------------------------------------+ - -#### PrimeSuper - -+-----------------------------+------------------------------+--------------------------------------+ -| `x'^2+x'''^2+x'^2_3+x_3'^2` | $`x'^2+x'''^2+x'^2_3+x_3'^2` | ![PrimeSuper](images/PrimeSuper.svg) | -+-----------------------------+------------------------------+--------------------------------------+ - -#### Raisebox - -+-------------------------------------------------+--------------------------------------------------+---------------+ -| \frac{a}{a\raisebox{0.5em}{b}} \cdot \ | $`\frac{a}{a\raisebox{0.5em}{b}} \cdot | ![raisebox][] | -| \frac{a\raisebox{-0.5em}{b}}{a} \cdot \ | \frac{a\raisebox{-0.5em}{b}}{a} \cdot | | -| \sqrt{a\raisebox{0.5em}{b}} \cdot \ | \sqrt{a\raisebox{0.5em}{b}} \cdot | | -| \sqrt{a\raisebox{-0.5em}{b}} \cdot \ | \sqrt{a\raisebox{-0.5em}{b}} \cdot | | -| \sqrt{a\raisebox{0.5em}{b}\raisebox{-0.5em}{b}} | \sqrt{a\raisebox{0.5em}{b}\raisebox{-0.5em}{b}}` | | -+-------------------------------------------------+--------------------------------------------------+---------------+ - -[raisebox]: images/raisebox.svg - -#### RelativeUnits - -+------------------------------------------------+----------------------------------------------+--------------------+ -| \begin{array}{ll} \ | $`\begin{array}{ll} | ![RelativeUnits][] | -| a\kern1emb^{a\kern1emb^{a\kern1emb}} & \ | a\kern1emb^{a\kern1emb^{a\kern1emb}} & | | -| {\footnotesize a\kern1emb^ \ | {\footnotesize a\kern1emb^ | | -| {a\kern1emb^{a\kern1emb}}} \\\\ \ | {a\kern1emb^{a\kern1emb}}} \\ | | -| a\mkern18mub^{a\mkern18mub^{a\mkern18mub}} & \ | a\mkern18mub^{a\mkern18mub^{a\mkern18mub}} & | | -| {\footnotesize a\mkern18mub^ \ | {\footnotesize a\mkern18mub^{a\mkern18mub^ | | -| {a\mkern18mub^{a\mkern18mub}}} \\\\ \ | {a\mkern18mub}}} \\ | | -| \end{array} | \end{array}` | | -+------------------------------------------------+----------------------------------------------+--------------------+ - -[RelativeUnits]: images/RelativeUnits.svg - -#### RlapBug - -+-------------------------+---------------------------+--------------------------------+ -| \frac{\mathrlap{x}}{2} | $`\frac{\mathrlap{x}}{2}` | ![rlapbug](images/rlapbug.svg) | -+-------------------------+---------------------------+--------------------------------+ - -#### Rule - -+------------------------------------+-------------------------------------+--------------------------+ -| \rule{1em}{0.5em}\rule{1ex}{2ex} \ | $`\rule{1em}{0.5em}\rule{1ex}{2ex} | ![rule](images/rule.svg) | -| \rule{1em}{1ex}\rule{1em}{0.431ex} | \rule{1em}{1ex}\rule{1em}{0.431ex}` | | -+------------------------------------+-------------------------------------+--------------------------+ - -#### SizingBaseline - -+----------------------------------+-------------------------------------+----------------------------------------------+ -| \text{{\tiny a+b}a+b{\Huge a+b}} | $`\text{{\tiny a+b}a+b{\Huge a+b}}` | ![SizingBaseline](images/SizingBaseline.svg) | -+----------------------------------+-------------------------------------+----------------------------------------------+ - -#### Sizing - -+-----------------------------------+---------------------------------+------------------------------+ -| \text{{\Huge x}{\LARGE y} \ | $`\text{{\Huge x}{\LARGE y} | ![sizing](images/sizing.svg) | -| {\normalsize z}{\scriptsize w}} \ | {\normalsize z}{\scriptsize w}} | | -| \sqrt[\text{\small 3}]{x+1} | \sqrt[\text{\small 3}]{x+1}` | | -+-----------------------------------+---------------------------------+------------------------------+ - -#### Smash - -+-------------------------------+-------------------------------+----------------------------+ -| \left( X^{\smash 2} \right) \ | $`\left( X^{\smash 2} \right) | ![smash](images/smash.svg) | -| \sqrt{\smash[b]{y=}} | \sqrt{\smash[b]{y=}}` | | -+-------------------------------+-------------------------------+----------------------------+ - -#### Spacing - -+--------------------------------------------+----------------------------------------+--------------+ -| \begin{matrix} \ | $`\begin{matrix} | ![spacing][] | -| `^3+[-1][1-1]1=1(=1)\lvert a\rvert~b \\` \ | ^3+[-1][1-1]1=1(=1)\lvert a\rvert~b \\ | | -| `\scriptstyle{^3+[-1][1-1]` \ | \scriptstyle{^3+[-1][1-1] | | -| 1=1(=1)\lvert a\rvert~b} \\\\ \ | 1=1(=1)\lvert a\rvert~b} \\ | | -| `\scriptscriptstyle{^3+[-1][1-1]` \ | \scriptscriptstyle{^3+[-1][1-1] | | -| 1=1(=1)\lvert a\rvert~b} \\\\ \ | 1=1(=1)\lvert a\rvert~b} \\ | | -| a : a \colon a \\\\ \ | a : a \colon a \\ | | -| \end{matrix} | \end{matrix}` | | -+--------------------------------------------+----------------------------------------+--------------+ - -[spacing]: images/spacing.svg - -#### Sqrt - -+------------------------------------------------+----------------------------------------------+-----------+ -| \sqrt{\sqrt{\sqrt{x}}}\_ \ | $`\sqrt{\sqrt{\sqrt{x}}}_ | ![sqrt][] | -| {\sqrt{\sqrt{x}}}^ \ | {\sqrt{\sqrt{x}}}^ | | -| {\sqrt{\sqrt{\sqrt{x}}} \ | {\sqrt{\sqrt{\sqrt{x}}} | | -| ^{\sqrt{\sqrt{\sqrt{x}}}}} \\\\ \ | ^{\sqrt{\sqrt{\sqrt{x}}}}} \\ | | -| \sqrt{\frac{\frac{A}{B}}{\frac{A}{B}}} \\; \ | \sqrt{\frac{\frac{A}{B}}{\frac{A}{B}}} \; | | -| \sqrt{\frac{\frac{\frac{A}{B}}{\frac{A}{B}}} \ | \sqrt{\frac{\frac{\frac{A}{B}}{\frac{A}{B}}} | | -| {\frac{\frac{A}{B}}{\frac{A}{B}}}} | {\frac{\frac{A}{B}}{\frac{A}{B}}}}` | | -+------------------------------------------------+----------------------------------------------+-----------+ - -[sqrt]: images/sqrt.svg - -#### SqrtRoot - -+------------------------------------------------------+--------------------------------------------------+---------------+ -| \begin{array}{l} \ | $`\begin{array}{l} | ![SqrtRoot][] | -| 1+\sqrt[3]{2}+\sqrt[1923^234] \ | 1+\sqrt[3]{2}+\sqrt[1923^234] | | -| {2^{2^{2^{2^{2^{2^{2^{2^{2^{2^{2^2}}}}}}}}}}} \\\\ \ | {2^{2^{2^{2^{2^{2^{2^{2^{2^{2^{2^2}}}}}}}}}}} \\ | | -| \Huge \sqrt[3]{M} + x^{\sqrt[3] a} \ | \Huge \sqrt[3]{M} + x^{\sqrt[3] a} | | -| \end{array} | \end{array}` | | -+------------------------------------------------------+--------------------------------------------------+---------------+ - -[SqrtRoot]: images/SqrtRoot.svg - -#### StackRel - -+----------------------------+-----------------------------+----------------------------------+ -| a \stackrel{?}{=} b \ | $`a \stackrel{?}{=} b | ![StackRel](images/StackRel.svg) | -| \stackrel{\text{def}}{=} c | \stackrel{\text{def}}{=} c` | | -+----------------------------+-----------------------------+----------------------------------+ - -#### StretchyAccent - -+---------------------------------------------------------+--------------------------------------------------------+---------------------+ -| \begin{array}{l} \ | $`\begin{array}{l} | ![StretchyAccent][] | -| \overrightarrow{AB} \quad \overleftarrow{AB} \quad \ | \overrightarrow{AB} \quad \overleftarrow{AB} \quad | | -| \overleftrightarrow{AB} \quad \ | \overleftrightarrow{AB} \quad | | -| \left(\underleftarrow{\frac{value}{j}}\right) \\\\ \ | \left(\underleftarrow{\frac{value}{j}}\right) \\ | | -| \widehat{ABC} \quad \ | \widehat{ABC} \quad | | -| \widetilde{AB} \quad \widetilde{ABC} \\\\ \ | \widetilde{AB} \quad \widetilde{ABC} \\ | | -| \overrightarrow{F} + \overrightarrow{AB} + \ | \overrightarrow{F} + \overrightarrow{AB} + | | -| \overrightarrow{F}^2 + \overrightarrow{F}\_2 + \ | \overrightarrow{F}^2 + \overrightarrow{F}_2 + | | -| \overrightarrow{F}\_1^2 \\\\ \ | \overrightarrow{F}_1^2 \\ | | -| \overrightarrow{AB}^2+ \ | \overrightarrow{AB}^2+ | | -| \frac{\overrightarrow{AB}}{\overrightarrow{AB}} + \ | \frac{\overrightarrow{AB}}{\overrightarrow{AB}} + | | -| \sqrt{\overrightarrow{AB}} + \ | \sqrt{\overrightarrow{AB}} + | | -| \left\lvert\overrightarrow{AB}\right\rvert | \left\lvert\overrightarrow{AB}\right\rvert | | -| \end{array} | \end{array}` | | -+---------------------------------------------------------+--------------------------------------------------------+---------------------+ - -[StretchyAccent]: images/StretchyAccent.svg - -#### StrikeThrough - -+-------------------------------------------+----------------------------------------+--------------------+ -| \begin{array}{l} \ | $`\begin{array}{l} | ![StrikeThrough][] | -| \cancel x \quad \cancel{2B} + \ | \cancel x \quad \cancel{2B} + | | -| \bcancel 5 +\bcancel{5ay} \\\\ \ | \bcancel 5 +\bcancel{5ay} \\ | | -| \sout{5ab} + \sout{5ABC} + \ | \sout{5ab} + \sout{5ABC} + | | -| \xcancel{\oint\_S{\vec E\cdot\hat n \ | \xcancel{\oint_S{\vec E\cdot\hat n | | -| \\,\mathrm d a}} \\\\[0.3em] \ | \,\mathrm d a}} \\[0.3em] | | -| \frac{x+\cancel B}{x+\cancel x} + \ | \frac{x+\cancel B}{x+\cancel x} + | | -| \frac{x+\cancel y}{x} + \cancel{B}\_1^2 \ | \frac{x+\cancel y}{x} + \cancel{B}_1^2 | | -| + \cancel{B^2} \\\\[0.2em] \ | + \cancel{B^2} \\[0.2em] | | -| \left\lvert\cancel{ac}\right\rvert \ | \left\lvert\cancel{ac}\right\rvert | | -| \end{array} | \end{array}` | | -+-------------------------------------------+----------------------------------------+--------------------+ - -[StrikeThrough]: images/StrikeThrough.svg - -#### StrikeThroughColor - -+----------------------------------------------------------+------------------------------------------------------+-------------------------+ -| \begin{array}{l} | $`\begin{array}{l} | ![StrikeThroughColor][] | -| \textcolor{red}{\cancel x \quad \cancel{2B}} \\\\ \ | \textcolor{red}{\cancel x \quad \cancel{2B}} \\ | | -| \textcolor{red}{\bcancel{\textcolor{black}{5}}} + \ | \textcolor{red}{\bcancel{\textcolor{black}{5}}} + | | -| \textcolor{red}{\bcancel{\textcolor{black}{5ay}}} \\\\ \ | \textcolor{red}{\bcancel{\textcolor{black}{5ay}}} \\ | | -| \color{green}{\sout{5ABC}} \ | \color{green}{\sout{5ABC}} | | -| \end{array} | \end{array}` | | -+----------------------------------------------------------+------------------------------------------------------+-------------------------+ - -[StrikeThroughColor]: images/StrikeThroughColor.svg - -#### StyleSpacing - -+----------------------+------------------------+------------------------------------------+ -| \scriptstyle ab\\;cd | $`\scriptstyle ab\;cd` | ![StyleSpacing](images/StyleSpacing.svg) | -+----------------------+------------------------+------------------------------------------+ - -#### StyleSwitching - -+---------------------------------------+----------------------------------------+---------------------+ -| a\cdot b\scriptstyle a\cdot ba \ | $`a\cdot b\scriptstyle a\cdot ba | ![StyleSwitching][] | -| \textstyle\cdot ba\scriptstyle\cdot b | \textstyle\cdot ba\scriptstyle\cdot b` | | -+---------------------------------------+----------------------------------------+---------------------+ - -[StyleSwitching]: images/StyleSwitching.svg - -#### SupSubCharacterBox - -+------------------------------------------+-------------------------------------------+-------------------------+ -| `a_2f_2{f}_2{aa}_2{af}_2\mathbf{y}_Ay_A` | $`a_2f_2{f}_2{aa}_2{af}_2\mathbf{y}_Ay_A` | ![SupSubCharacterBox][] | -+------------------------------------------+-------------------------------------------+-------------------------+ - -[SupSubCharacterBox]: images/SupSubCharacterBox.svg - -#### SupSubHorizSpacing - -+------------------------------------+----------------------------------+-------------------------+ -| `x^{x^{x}}\Big|` \ | $`x^{x^{x}}\Big| | ![SupSubHorizSpacing][] | -| `x_{x_{x_{x_{x}}}}\bigg|` \ | x_{x_{x_{x_{x}}}}\bigg| | | -| `x^{x^{x_{x_{x_{x_{x}}}}}}\bigg|` | x^{x^{x_{x_{x_{x_{x}}}}}}\bigg|` | | -+------------------------------------+----------------------------------+-------------------------+ - -[SupSubHorizSpacing]: images/SupSubHorizSpacing.svg - -#### SupSubLeftAlignReset - -+-------------------------------------------+----------------------------------------+---------------------------+ -| \omega^8\_{888} \quad \ | $`\omega^8_{888} \quad | ![SupSubLeftAlignReset][] | -| \frac{1}{\hat{\omega}^{8}\_{888}} \quad \ | \frac{1}{\hat{\omega}^{8}_{888}} \quad | | -| \displaystyle\sum\_{\omega^{8}\_{888}} | \displaystyle\sum_{\omega^{8}_{888}}` | | -+-------------------------------------------+----------------------------------------+---------------------------+ - -[SupSubLeftAlignReset]: images/SupSubLeftAlignReset.svg - -#### SupSubOffsets - -+-------------------------------------+-------------------------------------+--------------------+ -| \displaystyle \int_{2+3}x f^{2+3} \ | $`\displaystyle \int_{2+3}x f^{2+3} | ![SupSubOffsets][] | -| +3\lim\_{2+3+4+5}f | +3\lim_{2+3+4+5}f` | | -+-------------------------------------+-------------------------------------+--------------------+ - -[SupSubOffsets]: images/SupSubOffsets.svg - -#### SurrogatePairs - -| Source | Temml | -|-----------------------|------------------------| -| 𝐀𝐚𝟎𝐴𝑎𝑨𝒂𝔅𝔞𝔸𝒜 | $`𝐀𝐚𝟎𝐴𝑎𝑨𝒂𝔅𝔞𝔸𝒜` | -| 𝖠𝖺𝟢𝗔𝗮𝟬𝘈𝘢𝙰𝚊𝟶 | $`𝖠𝖺𝟢𝗔𝗮𝟬𝘈𝘢𝙰𝚊𝟶` | -| \text{𝐀𝐚𝟎𝐴𝑎𝑨𝒂𝔅𝔞𝔸𝒜} | $`\text{𝐀𝐚𝟎𝐴𝑎𝑨𝒂𝔅𝔞𝔸𝒜}` | -| \text{𝖠𝖺𝟢𝗔𝗮𝟬𝘈𝘢𝙰𝚊𝟶} | $`\text{𝖠𝖺𝟢𝗔𝗮𝟬𝘈𝘢𝙰𝚊𝟶}` | -| \mathrm{𝐀𝐚𝑨𝒂𝔅𝔞𝔸𝒜} | $`\mathrm{𝐀𝐚𝑨𝒂𝔅𝔞𝔸𝒜}` | - -#### Symbols1 - -+-------------------------------------------+-------------------------------------------+ -| \maltese\degree\standardstate\pounds\\$ \ | $`\maltese\degree\standardstate\pounds\$ | -| \text{\maltese\degree\pounds\textdollar} | \text{\maltese\degree\pounds\textdollar}` | -+-------------------------------------------+-------------------------------------------+ - -#### Tag - -+-----------------------------------+---------------------------------------+ -| \tag{$+$hi} \frac{x^2}{y}+x^{2^y} | $$\tag{$+$hi} \frac{x^2}{y}+x^{2^y}$$ | -+-----------------------------------+---------------------------------------+ -{colWidths="null 200"} - -#### Text - -+----------------------------------+-------------------------------------+--------------------------+ -| \frac{a}{b}\text{c~ {ab} \ e}+fg | $`\frac{a}{b}\text{c~ {ab} \ e}+fg` | ![text](images/text.svg) | -+----------------------------------+-------------------------------------+--------------------------+ - -#### TextSpace - -+-------------------------------------+-------------------------------+------------------------------------+ -| \begin{array}{l} \ | $`\begin{array}{l} | ![TextSpace](images/TextSpace.svg) | -| \texttt{12345678901234} \\\\ \ | \texttt{12345678901234} \\ | | -| \texttt{A test 1~~2 \ \\ 3} \\\\ \ | \texttt{A test 1~~2\ \ 3} \\ | | -| \verb|A test 1 2 3| \ | \verb|A test 1 2 3| | | -| \end{array} | \end{array}` | | -+-------------------------------------+-------------------------------+------------------------------------+ - -#### TextStacked - -+------------------------------------+----------------------------------+------------------+ -| \begin{matrix} \ | $`\begin{matrix} | ![TextStacked][] | -| \textsf{abc123 \textbf{abc123} \ | \textsf{abc123 \textbf{abc123} | | -| \textit{abc123}}\\\\ \ | \textit{abc123}}\\ | | -| \text{abc123 \textbf{abc123} \ | \text{abc123 \textbf{abc123} | | -| \textit{abc123}}\\\\ \ | \textit{abc123}}\\ | | -| \textrm{abc123 \textbf{abc123} \ | \textrm{abc123 \textbf{abc123} | | -| \textit{abc123}}\\\\ \ | \textit{abc123}}\\ | | -| \textsf{\textrm{\textbf{abc123}} \ | \textsf{\textrm{\textbf{abc123}} | | -| \textbf{abc123} \ | \textbf{abc123} | | -| \textit{abc123}}\\\\ \ | \textit{abc123}}\\ | | -| \textit{abc123 \textbf{abc123} \ | \textit{abc123 \textbf{abc123} | | -| \textsf{abc123}}\\\\ \ | \textsf{abc123}}\\ | | -| \end{matrix} | \end{matrix}` | | -+------------------------------------+----------------------------------+------------------+ - -[TextStacked]: images/TextStacked.svg - -#### TextWithMath - -+---------------------------------------------------+-----------------------------------------------+-------------------+ -| \begin{matrix} \ | $`\begin{matrix} | ![TextWithMath][] | -| \text{for $a < b$ and $ c < d $}. \\\\ \ | \text{for $a < b$ and $ c < d $}. \\ | | -| \textsf{for $a < b$ and $ c < d $}. \\\\ \ | \textsf{for $a < b$ and $ c < d $}. \\ | | -| \textsf{for $a < b \textbf{ and } c < d $} \\\\ \ | \textsf{for $a < b \textbf{ and } c < d $} \\ | | -| \text{\sf for $a < b$ and $c < d$.} \ | \text{\sf for $a < b$ and $c < d$.} | | -| \end{matrix} | \end{matrix}` | | -+---------------------------------------------------+-----------------------------------------------+-------------------+ - -[TextWithMath]: images/TextWithMath.svg - -#### Unicode - -| Source | Temml | -|----------------------|-------------------------| -| \text{ÀàÇçÉéÏïÖöÛû} | $`\text{ÀàÇçÉéÏïÖöÛû}` | -| \text{БГДЖЗЙЛФЦШЫЮЯ} | $`\text{БГДЖЗЙЛФЦШЫЮЯ}` | -| \text{여보세요} | $`\text{여보세요}` | -| \text{私はバナナです} | $`\text{私はバナナです}` | - -#### Units - -+------------------------------------------------+----------------------------------------------+------------+ -| \begin{array}{ll} \ | $`\begin{array}{ll} | ![units][] | -| \mathrm H\kern 1em\mathrm H \ | \mathrm H\kern 1em\mathrm H | | -| \text{\tiny (1em)} & \ | \text{\tiny (1em)} & | | -| \mathrm H\kern 1ex\mathrm H \ | \mathrm H\kern 1ex\mathrm H | | -| \text{\tiny (1ex)} \\\\ \ | \text{\tiny (1ex)} \\ | | -| \mathrm H{\scriptstyle \kern 1em}\mathrm H \ | \mathrm H{\scriptstyle \kern 1em}\mathrm H | | -| \text{\tiny (ss 1em)} & \ | \text{\tiny (ss 1em)} & | | -| \mathrm H{\scriptstyle \kern 1ex}\mathrm H \ | \mathrm H{\scriptstyle \kern 1ex}\mathrm H | | -| \text{\tiny (ss 1ex)} \\\\ \ | \text{\tiny (ss 1ex)} \\ | | -| \mathrm H{\small \kern 1em}\mathrm H \ | \mathrm H{\small \kern 1em}\mathrm H | | -| \text{\tiny (sm 1em)} & \ | \text{\tiny (sm 1em)} & | | -| \mathrm H{\small \kern 1ex}\mathrm H \ | \mathrm H{\small \kern 1ex}\mathrm H | | -| \text{\tiny (sm 1ex)} \\\\ \ | \text{\tiny (sm 1ex)} \\ | | -| \mathrm H\mkern 18mu\mathrm H \ | \mathrm H\mkern 18mu\mathrm H | | -| \text{\tiny (18mu)} & \ | \text{\tiny (18mu)} & | | -| \mathrm H\kern 1cm\mathrm H \ | \mathrm H\kern 1cm\mathrm H | | -| \text{\tiny (1cm)} \\\\ \ | \text{\tiny (1cm)} \\ | | -| \mathrm H{\scriptstyle \mkern 18mu}\mathrm H \ | \mathrm H{\scriptstyle \mkern 18mu}\mathrm H | | -| \text{\tiny (ss 18mu)} & \ | \text{\tiny (ss 18mu)} & | | -| \mathrm H{\scriptstyle \kern 1cm}\mathrm H \ | \mathrm H{\scriptstyle \kern 1cm}\mathrm H | | -| \text{\tiny (ss 1cm)} \\\\ \ | \text{\tiny (ss 1cm)} \\ | | -| \mathrm H{\small \mkern 18mu}\mathrm H \ | \mathrm H{\small \mkern 18mu}\mathrm H | | -| \text{\tiny (sm 18mu)} & \ | \text{\tiny (sm 18mu)} & | | -| \mathrm H{\small \kern 1cm}\mathrm H \ | \mathrm H{\small \kern 1cm}\mathrm H | | -| \text{\tiny (sm 1cm)} \ | \text{\tiny (sm 1cm)} | | -| \end{array} | \end{array}` | | -+------------------------------------------------+----------------------------------------------+------------+ - -[units]: images/units.svg - -#### UnsupportedCmds - -$`\err\,\frac\fracerr3\,2^\superr_\suberr\,\sqrt\sqrterr` - -deliberately does not compile - -#### Verb - -+-------------------------------------------------------+---------------------------------------------------+-----------+ -| \begin{array}{ll} \ | $`\begin{array}{ll} | ![verb][] | -| \verb \verb , & \verb|\verb |, \\\\ \ | \verb \verb , & \verb|\verb |, \\ | | -| \verb* \verb* , & \verb*|\verb* |, \\\\ \ | \verb* \verb* , & \verb*|\verb* |, \\ | | -| \verb! & ! & \scriptstyle\verb|ss verb| \\\\ \ | \verb! & ! & \scriptstyle\verb|ss verb| \\ | | -| \verb*! & ! & \small\verb|sm verb| \\\\ \ | \verb*! & ! & \small\verb|sm verb| \\ | | -| \verb|``---''~| \ | \verb|``---''~| | | -| \end{array} | \end{array}` | | -+-------------------------------------------------------+---------------------------------------------------+-----------+ - -[verb]: images/verb.svg - - - \ No newline at end of file diff --git a/test/main.css b/test/main.css deleted file mode 100644 index 17df816f..00000000 --- a/test/main.css +++ /dev/null @@ -1,16 +0,0 @@ -body { - margin: 0; - padding: 0; - font-size: 24px; -} - -#math { - font-size: 72px; -} - -#input { - margin: 0; - font-size: 100%; - width: 100%; - box-sizing: border-box; -} diff --git a/test/mhchem-tests.md b/test/mhchem-tests.md deleted file mode 100644 index f988ff1e..00000000 --- a/test/mhchem-tests.md +++ /dev/null @@ -1,279 +0,0 @@ - - - - - - Temml mhchem Tests - - - - - - - - -# mhchem - -This file contains all the examples in the `mhchem` manual.\ -Ref: https://mhchem.github.io/MathJax-mhchem/ - -## Chemical Equations (ce) - -| Source | Temml | -|------------------------------------------------|-------------------------| -| `\ce{CO2 + C -> 2 CO}` | $`\ce{CO2 + C -> 2 CO}` | -| `\ce{Hg^2+ ->[I-] HgI2 ->[I-] [Hg^{II}I4]^2-}` | $`\ce{Hg^2+ ->[I-] HgI2 ->[I-] [Hg^{II}I4]^2-}` | -| `C_p[\ce{H2O(l)}] = \pu{75.3 J // mol K}` | $`C_p[\ce{H2O(l)}] = \pu{75.3 J // mol K}` | - -## Chemical Formulae - -| Source | Temml | -|--------------|---------------| -| `\ce{H2O}` | $`\ce{H2O}` | -| `\ce{Sb2O3}` | $`\ce{Sb2O3}` | - -## Charges - -| Source | Temml | -|-----------------|------------------| -| `\ce{H+}` | $`\ce{H+}` | -| `\ce{CrO4^2-}` | $`\ce{CrO4^2-}` | -| `\ce{[AgCl2]-}` | $`\ce{[AgCl2]-}` | -| `\ce{Y^99+}` | $`\ce{Y^99+}` | -| `\ce{Y^{99+}}` | $`\ce{Y^{99+}}` | - -## Stoichiometric Numbers - -| Source | Temml | -|-----------------|--------------------| -| `\ce{2 H2O}` | $`\ce{2 H2O}` | -| `\ce{2H2O}` | $`\ce{2H2O}` | -| `\ce{0.5 H2O}` | $`\ce{0.5 H2O}` | -| `\ce{1/2 H2O}` | $`\ce{1/2 H2O}` | -| `\ce{(1/2) H2O}` | $`\ce{(1/2) H2O}` | -| `\ce{$n$ H2O}` | $`\ce{$n$ H2O}` | - -## Isotopes - -+-----------------------+------------------------------+ -| `\ce{^{227}_{90}Th+}` | $`\ce{^{227}_{90}Th+}` | -+-----------------------+------------------------------+ -| `\ce{^227_90Th+}` | $`\ce{^227_90Th+}` | -+-----------------------+------------------------------+ -| `\ce{^{0}_{-1}n^{-}}` | $`\ce{^{0}_{-1}n^{-}}` | -+-----------------------+------------------------------+ -| `\ce{^0_-1n-}` | $`\ce{^0_-1n-}` | -+-----------------------+------------------------------+ -| `\ce{H{}^3HO}` | $`\ce{H{}^3HO}` | -+-----------------------+------------------------------+ -| `\ce{H^3HO}` | $`\ce{H^3HO}` | -+-----------------------+------------------------------+ - -## Reaction Arrows - -| Source | Temml | -|------------------|------------------| -| `\ce{A -> B}` | $`\ce{A -> B}` | -| `\ce{A <- B}` | $`\ce{A <- B}` | -| `\ce{A <-> B}` | $`\ce{A <-> B}` | -| `\ce{A <--> B}` | $`\ce{A <--> B}` | -| `\ce{A <=> B}` | $`\ce{A <=> B}` | -| `\ce{A <=>> B}` | $`\ce{A <=>> B}` | -| `\ce{A <<=> B}` | $`\ce{A <<=> B}` | -| `\ce{A ->[H2O] B}` | $`\ce{A ->[H2O] B}` | -| `\ce{A ->[{text above}][{text below}] B}` | $`\ce{A ->[{text above}][{text below}] B}` | -| `\ce{A ->[$x$][$x_i$] B}` | $`\ce{A ->[$x$][$x_i$] B}` | - -## Parentheses, Brackets, Braces - -| Source | Temml | -|------------------------|------------------| -| `\ce{(NH4)2S}` | $`\ce{(NH4)2S}` | -| `\ce{[\{(X2)3\}2]^3+}` | $`\ce{[\{(X2)3\}2]^3+}` | -| `\ce{CH4 + 2 $\left( \ce{O2 + 79/21 N2} \right)$}` | $`\ce{CH4 + 2 $\left( \ce{O2 + 79/21 N2} \right) $}` | - -## States of Aggregation - -| Source | Temml | -|--------------------------|-----------------------------| -| `\ce{H2(aq)}` | $`\ce{H2(aq)}` | -| `\ce{CO3^2-_{(aq)}}` | $`\ce{CO3^2-_{(aq)}}` | -| `\ce{NaOH(aq,$\infty$)}` | $`\ce{NaOH(aq, $\infty $)}` | - -## Crystal Systems - -| Source | Temml | -|--------------------|---------------------| -| `\ce{ZnS($c$)}` | $`\ce{ZnS($c$)}` | -| `\ce{ZnS(\ca$c$)}` | $`\ce{ZnS(\ca$c$)}` | - -## Variables - -+--------------------------------+--------------------------------+ -| Source | Temml | -+================================+================================+ -| `\ce{NO_x}` | $`\ce{NO_x}` | -+--------------------------------+--------------------------------+ -| `\ce{Fe^n+}` | $`\ce{Fe^n+}` | -+--------------------------------+--------------------------------+ -| \ce{x Na(NH4)HPO4 ->[\Delta] \ | $`\ce{x Na(NH4)HPO4 ->[\Delta] | -| (NaPO3)_x + x NH3 ^ + x H2O} | (NaPO3)_x + x NH3 ^ + x H2O}` | -+--------------------------------+--------------------------------+ - -## Greek Characters - -| Source | Temml | -|------------------------------------|---------------------| -| `\ce{\mu-Cl}` | $`\ce{\mu-Cl}` | -| `\ce{[Pt(\eta^2-C2H4)Cl3]-}` | $`\ce{[Pt(\eta^2-C2H4)Cl3]-}` | -| `\ce{\beta +}` | $`\ce{\beta +}` | -| `\ce{^40_18Ar + \gamma{} + \nu_e}` | $`\ce{^40_18Ar + \gamma{} + \nu_e}` | - -## (Italic) Math - -| Source | Temml | -|-------------------------------|------------------| -| `\ce{NaOH(aq,$\infty$)}` | $`\ce{NaOH(aq,$\infty$)}` | -| `\ce{Fe(CN)_{$\frac{6}{2}$}}` | $`\ce{Fe(CN)_{{$\frac{6}{2}$}}}` | -| `\ce{X_{$i$}^{$x$}}` | $`\ce{X_{$i$}^{$x$}}` | -| `\ce{X_$i$^$x$}` | $`\ce{X_{$i$}^{$x$}}` | - -## Italic Text - -| Source | Temml | -|-------------------------------|------------------| -| `\ce{$cis${-}[PtCl2(NH3)2]}` | $`\ce{$cis${-}[PtCl2(NH3)2]}` | -| `\ce{CuS($hP12$)}` | $`\ce{CuS($hP12$)}` | - -## Upright Text, Escape Parsing - -| Source | Temml | -|---------------------------------|------------------| -| `\ce{{Gluconic Acid} + H2O2}` | $`\ce{{Gluconic Acid} + H2O2}` | -| `\ce{X_{{red}}}` | $`\ce{X_{{red}}}` | -| `\ce{{(+)}_589{-}[Co(en)3]Cl3}` | $`\ce{{(+)}_589{-}[Co(en)3]Cl3}` | - -## Bonds - -| Source | Temml | -|------------------------------------------|------------------| -| `\ce{C6H5-CHO}` | $`\ce{C6H5-CHO}` | -| `\ce{A-B=C#D}` | $`\ce{A-B=C#D}` | -| `\ce{A\bond{-}B\bond{=}C\bond{#}D}` | $`\ce{A\bond{-}B\bond{=}C\bond{#}D}` | -| `\ce{A\bond{1}B\bond{2}C\bond{3}D}` | $`\ce{A\bond{1}B\bond{2}C\bond{3}D}` | -| `\ce{A\bond{~}B\bond{~-}C}` | $`\ce{A\bond{~}B\bond{~-}C}` | -| `\ce{A\bond{~--}B\bond{~=}C\bond{-~-}D}` | $`\ce{A\bond{~--}B\bond{~=}C\bond{-~-}D}` | -| `\ce{A\bond{...}B\bond{....}C}` | $`\ce{A\bond{...}B\bond{....}C}` | -| `\ce{A\bond{->}B\bond{<-}C}` | $`\ce{A\bond{->}B\bond{<-}C}` | - -## Addition Compounds - -| Source | Temml | -|---------------------------|------------------| -| `\ce{KCr(SO4)2*12H2O}` | $`\ce{KCr(SO4)2*12H2O}` | -| `\ce{KCr(SO4)2.12H2O}` | $`\ce{KCr(SO4)2.12H2O}` | -| `\ce{KCr(SO4)2 * 12 H2O}` | $`\ce{KCr(SO4)2 * 12 H2O}` | - -## Oxidation States - -| Source | Temml | -|---------------------------|------------------| -| `\ce{Fe^{II}Fe^{III}2O4}` | $`\ce{Fe^{II}Fe^{III}2O4}` | - -## Unpaired Electrons, Radical Dots - -| Source | Temml | -|-------------------|--------------------| -| `\ce{OCO^{.-}}` | $`\ce{OCO^{.-}}` | -| `\ce{NO^{(2.)-}}` | $`\ce{NO^{(2.)-}}` | - -## Kröger-Vink Notation - -+------------------------------------+---------------------------------------+ -| Source | Temml | -+====================================+=======================================+ -| `\ce{Li^x_{Li,1-2x}Mg^._{Li,x}` \ | $``\ce{Li^x_{Li,1-2x}Mg^._{Li,x} | -| ``$V$'_{Li,x}Cl^x_{Cl}}`` | $V$'_{Li,x}Cl^x_{Cl}}`` | -+------------------------------------+---------------------------------------+ -| ```\ce{O''_{i,x}}``` | $```\ce{O''_{i,x}}``` | -+------------------------------------+---------------------------------------+ -| `\ce{M^{..}_i}` | $`\ce{M^{..}_i}` | -+------------------------------------+---------------------------------------+ -| ``\ce{$V$^{4'}_{Ti}}`` | $``\ce{ $V $^{4'}_{Ti}}`` | -+------------------------------------+---------------------------------------+ -| `\ce{V_{V,1}C_{C,0.8}$V$_{C,0.2}}` | $`\ce{V_{V,1}C_{C,0.8} $V $_{C,0.2}}` | -+------------------------------------+---------------------------------------+ - -## Equation Operators - -| Source | Temml | -|----------------|-----------------| -| `\ce{A + B}` | $`\ce{A + B}` | -| `\ce{A - B}` | $`\ce{A - B}` | -| `\ce{A = B}` | $`\ce{A = B}` | -| `\ce{A \pm B}` | $`\ce{A \pm B}` | - -## Precipitate and Gas - -| Source | Temml | -|----------------------------------|------------------| -| `\ce{SO4^2- + Ba^2+ -> BaSO4 v}` | $`\ce{SO4^2- + Ba^2+ -> BaSO4 v}` | -| `\ce{A v B (v) -> B ^ B (^)}` | $`\ce{A v B (v) -> B ^ B (^)}` | - -## Other Symbols and Shortcuts - -| Source | Temml | -|---------------------|----------------| -| `\ce{NO^*}` | $`\ce{NO^*}` | -| `\ce{1s^2-N}` | $`\ce{1s^2-N}` | -| `\ce{n-Pr}` | $`\ce{n-Pr}` | -| `\ce{iPr}` | $`\ce{iPr}` | -| `\ce{\ca Fe}` | $`\ce{\ca Fe}` | -| `\ce{A, B, C; F}` | $`\ce{A, B, C; F}` | -| `\ce{{and others}}` | $`\ce{{and others}}` | - -## Complex Examples - -+------------------------------------------+------------------------------------------+ -| Source | Temml | -+==========================================+==========================================+ -| \ce{Zn^2+ <=>[+ 2OH-][+ 2H+] \ | $`\ce{Zn^2+ <=>[+ 2OH-][+ 2H+] | -| $\underset{\text{amphoteres Hydroxid}} \ | $\underset{\text{amphoteres Hydroxid}} | -| {\ce{Zn(OH)2 v}}$ <=>[+ 2OH-][+ 2H+] \ | {\ce{Zn(OH)2 v}} $ <=>[+ 2OH-][+ 2H+] | -| $\underset{\text{Hydroxozikat}} \ | {$\underset{\text{Hydroxozikat}} | -| {\ce{[Zn(OH)4]^2-}}$} | {\ce{[Zn(OH)4]^2-}}$}}` | -+------------------------------------------+------------------------------------------+ -| \ce{$K = \frac{[\ce{Hg^2+}][\ce{Hg}]} \ | $`\ce{ $K = \frac{[\ce{Hg^2+}][\ce{Hg}]} | -| {[\ce{Hg2^2+}]}$} | {[\ce{Hg2^2+}]} $}` | -+------------------------------------------+------------------------------------------+ -| \ce{$K = \ | $`\ce{ $K = | -| \ce{\frac{[Hg^2+][Hg]}{[Hg2^2+]}}$} | \ce{\frac{[Hg^2+][Hg]}{[Hg2^2+]}} $}` | -+------------------------------------------+------------------------------------------+ -| \ce{Hg^2+ ->[I-] \ | $`\ce{Hg^2+ ->[I-] | -| $\underset{\mathrm{red}}{\ce{HgI2}}$ \ | $\underset{\mathrm{red}}{\ce{HgI2}} $ | -| ->[I-] $\underset{\mathrm{red}} \ | ->[I-] $\underset{\mathrm{red}} | -| {\ce{[Hg^{II}I4]^2-}}$} | {\ce{[Hg^{II}I4]^2-}} $}` | -+------------------------------------------+------------------------------------------+ - -## Physical Units - -| Source | Temml | -|---------------------|-----------------| -| `\pu{123 kJ}` | $`\pu{123 kJ}` | -| `\pu{123 mm2}` | $`\pu{123 mm2}` | -| `\pu{123 J s}` | $`\pu{123 J s}` | -| `\pu{123 J*s}` | $`\pu{123 J*s}` | -| `\pu{123 kJ/mol}` | $`\pu{123 kJ/mol}` | -| `\pu{123 kJ//mol}` | $`\pu{123 kJ//mol}` | -| `\pu{123 kJ mol-1}` | $`\pu{123 kJ mol-1}` | -| `\pu{123 kJ*mol-1}` | $`\pu{123 kJ*mol-1}` | -| `\pu{1.2e3 kJ}` | $`\pu{1.2e3 kJ}` | -| `\pu{1,2e3 kJ}` | $`\pu{1,2e3 kJ}` | -| `\pu{1.2E3 kJ}` | $`\pu{1.2E3 kJ}` | -| `\pu{1,2E3 kJ}` | $`\pu{1,2E3 kJ}` | - - - \ No newline at end of file diff --git a/test/mozilla-tests.md b/test/mozilla-tests.md deleted file mode 100644 index e0e4633c..00000000 --- a/test/mozilla-tests.md +++ /dev/null @@ -1,176 +0,0 @@ - - - - - - Temml Mozilla Tests - - - - - - - - -# Mozilla Torture Test - -This page reproduces the tests from \ -https://www-archive.mozilla.org/projects/mathml/demo/texvsmml.xhtml and \ -https://fred-wang.github.io/MathFonts/mozilla\_mathml\_test/ - -Images from LaTeX are also included for comparison. - -
    - -+----+------------------------------+------------------------------+-----------+--------------+ -| | Source | Temml | LaTeX | Comment | -+====+==============================+==============================+===========+==============+ -| 1 | x^2y^2 | $$x^2y^2$$ | ![ex1][] | TeXbook p128 | -+----+------------------------------+------------------------------+-----------+--------------+ -| 2 | \_2F\_3 | $$_2F_3$$ | ![ex2][] | TeXbook p128 | -+----+------------------------------+------------------------------+-----------+--------------+ -| 3 | x+y^2\over k+1 | $$x+y^2\over k+1$$ | ![ex3][] | TeXbook p139 | -+----+------------------------------+------------------------------+-----------+--------------+ -| 4 | x+y^{2\over k+1} | $$x+y^{2\over k+1}$$ | ![ex4][] | TeXbook p139 | -+----+------------------------------+------------------------------+-----------+--------------+ -| 5 | a\over{b/2} | $$a\over{b/2}$$ | ![ex5][] | TeXbook p139 | -+----+------------------------------+------------------------------+-----------+--------------+ -| 6 | a\_0 + \cfrac{1}{a\_1 + \ | $$a_0 + \cfrac{1}{a_1 + | ![ex6][] | TeXbook p142 | -| | \cfrac{1}{a\_2 + \ | \cfrac{1}{a_2 + | | | -| | \cfrac{1}{a\_3 + \ | \cfrac{1}{a_3 + | | | -| | \cfrac{1}{a\_4}}}} | \cfrac{1}{a_4}}}}$$ | | | -+----+------------------------------+------------------------------+-----------+--------------+ -| 7 | a\_0+{1\over a\_1+{1\over \ | $$a_0+{1\over a_1+{1\over | ![ex7][] | TeXbook p142 | -| | a\_2+{1\over a\_3+ \ | a_2+{1\over a_3+ | | | -| | {1\over a\_4}}}} | {1\over a_4}}}}$$ | | | -+----+------------------------------+------------------------------+-----------+--------------+ -| 8 | n\choose {k / 2} | $$n\choose {k / 2}$$ | ![ex8][] | TeXbook p143 | -+----+------------------------------+------------------------------+-----------+--------------+ -| 9 | {p \choose 2} x^2 y^{p-2} \ | $${p \choose 2} x^2 y^{p-2} | ![ex9][] | TeXbook p143 | -| | - {1\over{1-x}} \ | - {1\over{1-x}} | | | -| | {1\over{1-x^2}} | {1\over{1-x^2}}$$ | | | -+----+------------------------------+------------------------------+-----------+--------------+ -| 10 | \sum\_{\scriptstyle 0 \le\ | $$\sum_{\scriptstyle 0 \le | ![ex10][] | TeXbook p145 | -| | i \le m \atop \scriptstyle\ | i \le m \atop \scriptstyle | | | -| | 0 < j < n} P(i, j) | 0 < j < n} P(i, j)$$ | | | -+----+------------------------------+------------------------------+-----------+--------------+ -| 11 | x^{2y} | $$x^{2y}$$ | ![ex11][] | TeXbook p128 | -+----+------------------------------+------------------------------+-----------+--------------+ -| 12 | \sum\_{i=1}^p \ | $$\sum_{i=1}^p | ![ex12][] | TeXbook p145 | -| | \sum\_{j=1}^q \ | \sum_{j=1}^q | | | -| | \sum\_{k=1}^r \ | \sum_{k=1}^r | | | -| | a\_{ij}b\_{jk}c\_{ki} | a_{ij}b_{jk}c_{ki}$$ | | | -+----+------------------------------+------------------------------+-----------+--------------+ -| 13 | \sqrt{1+\sqrt{1+\sqrt{1+ \ | $$\sqrt{1+\sqrt{1+\sqrt{1+ | ![ex13][] | TeXbook p145 | -| | \sqrt{1+\sqrt{1+\sqrt{1+ \ | \sqrt{1+\sqrt{1+\sqrt{1+ | | | -| | \sqrt{1+x}}}}}}} | \sqrt{1+x}}}}}}}$$ | | | -+----+------------------------------+------------------------------+-----------+--------------+ -| 14 | \bigg(\frac{\partial^2} \ | $$\bigg(\frac{\partial^2} | ![ex14][] | TeXbook p147 | -| | {\partial x^2} + \frac \ | {\partial x^2} + \frac | | | -| | {\partial^2}{\partial y^2}\ | {\partial^2}{\partial y^2} | | | -| | \bigg) \big\lvert\varphi \ | \bigg) \big\lvert\varphi | | | -| | (x+iy)\big\rvert^2 | (x+iy)\big\rvert^2$$ | | | -+----+------------------------------+------------------------------+-----------+--------------+ -| 15 | 2^{2^{2^x}} | $$2^{2^{2^x}}$$ | ![ex15][] | TeXbook p128 | -+----+------------------------------+------------------------------+-----------+--------------+ -| 16 | \int\_1^x {dt\over t} | $$\int_1^x {dt\over t}$$ | ![ex16][] | TeXbook p168 | -+----+------------------------------+------------------------------+-----------+--------------+ -| 17 | \int\\!\\!\\!\int\_D dx\,dy | $$\int\!\!\!\int_D dx\,dy$$ | ![ex17][] | TeXbook p169 | -+----+------------------------------+------------------------------+-----------+--------------+ -| 18 | f(x) = \begin{cases}1/3 & \ | $$f(x) = \begin{cases}1/3 & | ![ex18][] | TeXbook p175 | -| | \text{if }0 \le x \le 1; \ | \text{if }0 \le x \le 1; \\ | | | -| | \\\\ \ | 2/3 & \text{if }3\le x \le | | | -| | 2/3 & \text{if }3\le x \le \ | 4;\\ 0 & \text{elsewhere.} | | | -| | 4;\\\\ 0 &\text{elsewhere.}\ | \end{cases}$$ | | | -| | \end{cases} | | | | -+----+------------------------------+------------------------------+-----------+--------------+ -| 19 | \overbrace{x +\cdots + x} \ | $$\overbrace{x +\cdots + x} | ![ex19][] | TeXbook p176 | -| | ^{k \text{ times}} | ^{k \text{ times}}$$ | | | -+----+------------------------------+------------------------------+-----------+--------------+ -| 20 | y\_{x^2} | $$y_{x^2}$$ | ![ex20][] | TeXbook p128 | -+----+------------------------------+------------------------------+-----------+--------------+ -| 21 | \sum\_{p\text{ prime}} \ | $$\sum_{p\text{ prime}}f(p) | ![ex21][] | TeXbook p181 | -| | f(p)=\int\_{t>1} f(t)d\pi(t) | =\int_{t>1} f(t)d\pi(t)$$ | | | -+----+------------------------------+------------------------------+-----------+--------------+ -| 22 | \{\underbrace{\overbrace{ \ | $$\{\underbrace{\overbrace{ | ![ex22][] | TeXbook p181 | -| | \mathstrut a,\dots,a}^{k \ | \mathstrut a,\dots,a}^{k | | | -| | \,a\rq\text{s}},\overbrace{\ | \,a\rq\text{s}},\overbrace{ | | | -| | \mathstrut b,\dots,b}^{l\,\ | \mathstrut b,\dots,b}^{l\, | | | -| | b\rq\text{s}}}\_{k+l \ | b\rq\text{s}}}_{k+l | | | -| | \text{ elements}}\} | \text{ elements}}\}$$ | | | -+----+------------------------------+------------------------------+-----------+--------------+ -| 23 | \begin{pmatrix} \ | $$\begin{pmatrix} | ![ex23][] | TeXbook p181 | -| | \begin{pmatrix}a&b\\\\c&d \ | \begin{pmatrix}a&b\\c&d | | | -| | \end{pmatrix} & \ | \end{pmatrix} & | | | -| | \begin{pmatrix}e&f\\\\g&h \ | \begin{pmatrix}e&f\\g&h | | | -| | \end{pmatrix} \\\\ 0 & \ | \end{pmatrix} \\ 0 & | | | -| | \begin{pmatrix}i&j\\\\k&l \ | \begin{pmatrix}i&j\\k&l | | | -| | \end{pmatrix} \ | \end{pmatrix} | | | -| | \end{pmatrix} | \end{pmatrix}$$ | | | -+----+------------------------------+------------------------------+-----------+--------------+ -| 24 | `\det\begin{vmatrix}` \ | $$\det\begin{vmatrix} | ![ex24][] | TeXbook p181 | -| | `c_0&c_1&c_2&\dots& c_n\\`\ `| c_0&c_1&c_2&\dots& c_n\\ | | | -| | `c_1 & c_2 & c_3 & \dots &`\ | c_1 & c_2 & c_3 & \dots & | | | -| | `c_{n+1}\\ c_2 & c_3 & c_4`\ | c_{n+1}\\ c_2 & c_3 & c_4 | | | -| | `&\dots & c_{n+2}\\ \vdots`\ | &\dots & c_{n+2}\\ \vdots | | | -| | `&\vdots&\vdots & &\vdots` \ | &\vdots&\vdots & &\vdots | | | -| | `\\c_n & c_{n+1} & c_{n+2}`\ | \\c_n & c_{n+1} & c_{n+2} | | | -| | `&\dots&c_{2n}` \ | &\dots&c_{2n} | | | -| | `\end{vmatrix} > 0` | \end{vmatrix} > 0$$ | | | -+----+------------------------------+------------------------------+-----------+--------------+ -| 25 | y\_{x\_2} | $$y_{x_2}$$ | ![ex25][] | TeXbook p128 | -+----+------------------------------+------------------------------+-----------+--------------+ -| 26 | x\_{92}^{31415} + \pi | $$x_{92}^{31415} + \pi$$ | ![ex26][] | TeXbook p129 | -+----+------------------------------+------------------------------+-----------+--------------+ -| 27 | x\_{y^a\_b}^{z^c\_d} | $$x_{y^a_b}^{z^c_d}$$ | ![ex27][] | TeXbook p129 | -+----+------------------------------+------------------------------+-----------+--------------+ -| 28 | y\_3''' | $$y_3'''$$ | ![ex28][] | TeXbook p130 | -+----+------------------------------+------------------------------+-----------+--------------+ -| 29 | \lim\_{n\rightarrow+\infty}\ | $$\lim_{n\rightarrow+\infty} | ![ex29][] | | -| | {\sqrt{2\pi n}\over n!} \ | {\sqrt{2\pi n}\over n!} | | | -| | {\binom{n}{e}}^n = 1 | {\binom{n}{e}}^n = 1$$ | | | -+----+------------------------------+------------------------------+-----------+--------------+ -| 30 | \det(A) = \sum\_{\sigma \ | $$\det(A) = \sum_{\sigma | ![ex30][] | | -| | \in S_n} \epsilon(\sigma) \ | \in S_n} \epsilon(\sigma) | | | -| | \prod\_{i=1}^n \ | \prod_{i=1}^n | | | -| | a\_{i, \sigma\_i} | a_{i, \sigma_i}$$ | | | -+----+------------------------------+------------------------------+-----------+--------------+ - -[ex1]: images/ex1.gif -[ex2]: images/ex2.gif -[ex3]: images/ex3.gif -[ex4]: images/ex4.gif -[ex5]: images/ex5.gif -[ex6]: images/ex6.gif -[ex7]: images/ex7.gif -[ex8]: images/ex8.gif -[ex9]: images/ex9.gif -[ex10]: images/ex10.gif -[ex11]: images/ex11.gif -[ex12]: images/ex12.gif -[ex13]: images/ex13.gif -[ex14]: images/ex14.gif -[ex15]: images/ex15.gif -[ex16]: images/ex16.gif -[ex17]: images/ex17.gif -[ex18]: images/ex18.gif -[ex19]: images/ex19.gif -[ex20]: images/ex20.gif -[ex21]: images/ex21.gif -[ex22]: images/ex22.gif -[ex23]: images/ex23.gif -[ex24]: images/ex24.gif -[ex25]: images/ex25.gif -[ex26]: images/ex26.gif -[ex27]: images/ex27.gif -[ex28]: images/ex28.gif -[ex29]: images/ex29.png -[ex30]: images/ex30.png - - - diff --git a/test/processTests.js b/test/processTests.js deleted file mode 100644 index 7b0cda00..00000000 --- a/test/processTests.js +++ /dev/null @@ -1,6 +0,0 @@ -const fs = require("fs") // Node.js file system - -let str = fs.readFileSync('./test/katex-spec1.js').toString('utf8') -str = str.replace(/Expect(`[^`]*`)/g, - 'Expect($1)') -fs.writeFileSync('./test/katex-spec2.js', str) diff --git a/test/repl.html b/test/repl.html deleted file mode 100644 index 76468a7f..00000000 --- a/test/repl.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - - Temml REPL - - - - - - - - - - - - - - - -
    - - diff --git a/test/temml.js b/test/temml.js deleted file mode 100644 index 539c035a..00000000 --- a/test/temml.js +++ /dev/null @@ -1,11204 +0,0 @@ -var temml = (function () { - 'use strict'; - - /** - * This is the ParseError class, which is the main error thrown by Temml - * functions when something has gone wrong. This is used to distinguish internal - * errors from errors in the expression that the user provided. - * - * If possible, a caller should provide a Token or ParseNode with information - * about where in the source string the problem occurred. - */ - class ParseError { - constructor( - message, // The error message - token // An object providing position information - ) { - let error = " " + message; - let start; - - const loc = token && token.loc; - if (loc && loc.start <= loc.end) { - // If we have the input and a position, make the error a bit fancier - - // Get the input - const input = loc.lexer.input; - - // Prepend some information - start = loc.start; - const end = loc.end; - if (start === input.length) { - error += " at end of input: "; - } else { - error += " at position " + (start + 1) + ": "; - } - - // Underline token in question using combining underscores - const underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332"); - - // Extract some context from the input and add it to the error - let left; - if (start > 15) { - left = "…" + input.slice(start - 15, start); - } else { - left = input.slice(0, start); - } - let right; - if (end + 15 < input.length) { - right = input.slice(end, end + 15) + "…"; - } else { - right = input.slice(end); - } - error += left + underlined + right; - } - - // Some hackery to make ParseError a prototype of Error - // See http://stackoverflow.com/a/8460753 - const self = new Error(error); - self.name = "ParseError"; - self.__proto__ = ParseError.prototype; - self.position = start; - return self; - } - } - - ParseError.prototype.__proto__ = Error.prototype; - - // - /** - * This file contains a list of utility functions which are useful in other - * files. - */ - - /** - * Return whether an element is contained in a list - */ - const contains = function(list, elem) { - return list.indexOf(elem) !== -1; - }; - - /** - * Provide a default value if a setting is undefined - */ - const deflt = function(setting, defaultIfUndefined) { - return setting === undefined ? defaultIfUndefined : setting; - }; - - // hyphenate and escape adapted from Facebook's React under Apache 2 license - - const uppercase = /([A-Z])/g; - const hyphenate = function(str) { - return str.replace(uppercase, "-$1").toLowerCase(); - }; - - const ESCAPE_LOOKUP = { - "&": "&", - ">": ">", - "<": "<", - '"': """, - "'": "'" - }; - - const ESCAPE_REGEX = /[&><"']/g; - - /** - * Escapes text to prevent scripting attacks. - */ - function escape(text) { - return String(text).replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]); - } - - /** - * Sometimes we want to pull out the innermost element of a group. In most - * cases, this will just be the group itself, but when ordgroups and colors have - * a single element, we want to pull that out. - */ - const getBaseElem = function(group) { - if (group.type === "ordgroup") { - if (group.body.length === 1) { - return getBaseElem(group.body[0]); - } else { - return group; - } - } else if (group.type === "color") { - if (group.body.length === 1) { - return getBaseElem(group.body[0]); - } else { - return group; - } - } else if (group.type === "font") { - return getBaseElem(group.body); - } else { - return group; - } - }; - - /** - * TeXbook algorithms often reference "character boxes", which are simply groups - * with a single character in them. To decide if something is a character box, - * we find its innermost group, and see if it is a single character. - */ - const isCharacterBox = function(group) { - const baseElem = getBaseElem(group); - - // These are all the types of groups which hold single characters - return baseElem.type === "mathord" || baseElem.type === "textord" || baseElem.type === "atom" - }; - - const assert = function(value) { - if (!value) { - throw new Error("Expected non-null, but got " + String(value)); - } - return value; - }; - - /** - * Return the protocol of a URL, or "_relative" if the URL does not specify a - * protocol (and thus is relative). - */ - const protocolFromUrl = function(url) { - const protocol = /^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(url); - return protocol != null ? protocol[1] : "_relative"; - }; - - /** - * Round `n` to 4 decimal places, or to the nearest 1/10,000th em. The TeXbook - * gives an acceptable rounding error of 100sp (which would be the nearest - * 1/6551.6em with our ptPerEm = 10): - * http://www.ctex.org/documents/shredder/src/texbook.pdf#page=69 - */ - const round = function(n) { - return +n.toFixed(4); - }; - - const consolidateText = mrow => { - // If possible, consolidate adjacent elements into a single element. - if (mrow.type !== "mrow") { return mrow } - if (mrow.children.length === 0) { return mrow } // empty group, e.g., \text{} - const mtext = mrow.children[0]; - if (!mtext.attributes || mtext.type !== "mtext") { return mrow } - const variant = mtext.attributes.mathvariant || ""; - for (let i = 1; i < mrow.children.length; i++) { - // Check each child and, if possible, copy the character into child[0]. - const localVariant = mrow.children[i].attributes.mathvariant || ""; - if (mrow.children[i].type === "mrow") { - const childRow = mrow.children[i]; - for (let j = 0; j < childRow.children.length; j++) { - // We'll also check the children of a mrow. One level only. No recursion. - const childVariant = childRow.children[j].attributes.mathvariant || ""; - if (childVariant !== variant || childRow.children[j].type !== "mtext") { - return mrow // At least one element cannot be consolidated. Get out. - } else { - mtext.children[0].text += childRow.children[j].children[0].text; - } - } - } else if (localVariant !== variant || mrow.children[i].type !== "mtext") { - return mrow - } else { - mtext.children[0].text += mrow.children[i].children[0].text; - } - } - // Since we have gotten here, the text has been loaded into a single mtext node. - // Next, consolidate the children into a single element. - mtext.children.splice(1, mtext.children.length - 1); - // Firefox does not render a space at either end of an string. - // To get proper rendering, we replace leading or trailing spaces with no-break spaces. - if (mtext.children[0].text.charAt(0) === " ") { - mtext.children[0].text = "\u00a0" + mtext.children[0].text.slice(1); - } - const L = mtext.children[0].text.length; - if (L > 0 && mtext.children[0].text.charAt(L - 1) === " ") { - mtext.children[0].text = mtext.children[0].text.slice(0, -1) + "\u00a0"; - } - return mtext - }; - - var utils = { - contains, - deflt, - escape, - hyphenate, - getBaseElem, - isCharacterBox, - protocolFromUrl, - round, - consolidateText - }; - - /** - * This is a module for storing settings passed into Temml. It correctly handles - * default settings. - */ - - /** - * The main Settings object - */ - class Settings { - constructor(options) { - // allow null options - options = options || {}; - this.displayMode = utils.deflt(options.displayMode, false); // boolean - this.annotate = utils.deflt(options.annotate, false); // boolean - this.elementIsMath = utils.deflt(options.elementIsMath, false); // boolean - this.leqno = utils.deflt(options.leqno, false); // boolean - this.errorColor = utils.deflt(options.errorColor, "#b22222"); // string - this.preventTagLap = utils.deflt(options.preventTagLap, false); // boolean - this.macros = options.macros || {}; - this.xml = utils.deflt(options.xml, false); // boolean - this.colorIsTextColor = utils.deflt(options.colorIsTextColor, false); // booelean - this.strict = utils.deflt(options.strict, false); // boolean - this.trust = utils.deflt(options.trust, false); // trust context. See html.js. - this.maxSize = (options.maxSize === undefined - ? [Infinity, Infinity] - : Array.isArray(options.maxSize) - ? options.maxSize - : [Infinity, Infinity] - ); - this.maxExpand = Math.max(0, utils.deflt(options.maxExpand, 1000)); // number - } - - /** - * Check whether to test potentially dangerous input, and return - * `true` (trusted) or `false` (untrusted). The sole argument `context` - * should be an object with `command` field specifying the relevant LaTeX - * command (as a string starting with `\`), and any other arguments, etc. - * If `context` has a `url` field, a `protocol` field will automatically - * get added by this function (changing the specified object). - */ - isTrusted(context) { - if (context.url && !context.protocol) { - context.protocol = utils.protocolFromUrl(context.url); - } - const trust = typeof this.trust === "function" ? this.trust(context) : this.trust; - return Boolean(trust); - } - } - - /** - * All registered functions. - * `functions.js` just exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary. - */ - const _functions = {}; - - /** - * All MathML builders. Should be only used in the `define*` and the `build*ML` - * functions. - */ - const _mathmlGroupBuilders = {}; - - function defineFunction({ - type, - names, - props, - handler, - mathmlBuilder - }) { - // Set default values of functions - const data = { - type, - numArgs: props.numArgs, - argTypes: props.argTypes, - allowedInArgument: !!props.allowedInArgument, - allowedInText: !!props.allowedInText, - allowedInMath: props.allowedInMath === undefined ? true : props.allowedInMath, - numOptionalArgs: props.numOptionalArgs || 0, - infix: !!props.infix, - primitive: !!props.primitive, - handler: handler - }; - for (let i = 0; i < names.length; ++i) { - _functions[names[i]] = data; - } - if (type) { - if (mathmlBuilder) { - _mathmlGroupBuilders[type] = mathmlBuilder; - } - } - } - - /** - * Use this to register only the MathML builder for a function(e.g. - * if the function's ParseNode is generated in Parser.js rather than via a - * stand-alone handler provided to `defineFunction`). - */ - function defineFunctionBuilders({ type, mathmlBuilder }) { - defineFunction({ - type, - names: [], - props: { numArgs: 0 }, - handler() { - throw new Error("Should never be called.") - }, - mathmlBuilder - }); - } - - const normalizeArgument = function(arg) { - return arg.type === "ordgroup" && arg.body.length === 1 ? arg.body[0] : arg - }; - - // Since the corresponding buildMathML function expects a - // list of elements, we normalize for different kinds of arguments - const ordargument = function(arg) { - return arg.type === "ordgroup" ? arg.body : [arg] - }; - - /** - * This node represents a document fragment, which contains elements, but when - * placed into the DOM doesn't have any representation itself. It only contains - * children and doesn't have any DOM node properties. - */ - class DocumentFragment { - constructor(children) { - this.children = children; - this.classes = []; - this.style = {}; - } - - hasClass(className) { - return utils.contains(this.classes, className); - } - - /** Convert the fragment into a node. */ - toNode() { - const frag = document.createDocumentFragment(); - - for (let i = 0; i < this.children.length; i++) { - frag.appendChild(this.children[i].toNode()); - } - - return frag; - } - - /** Convert the fragment into HTML markup. */ - toMarkup() { - let markup = ""; - - // Simply concatenate the markup for the children together. - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - return markup; - } - - /** - * Converts the math node into a string, similar to innerText. Applies to - * MathDomNode's only. - */ - toText() { - // To avoid this, we would subclass documentFragment separately for - // MathML, but polyfills for subclassing is expensive per PR 1469. - const toText = (child) => child.toText(); - return this.children.map(toText).join(""); - } - } - - /** - * These objects store the data about the DOM nodes we create, as well as some - * extra data. They can then be transformed into real DOM nodes with the - * `toNode` function or HTML markup using `toMarkup`. They are useful for both - * storing extra properties on the nodes, as well as providing a way to easily - * work with the DOM. - * - * Similar functions for working with MathML nodes exist in mathMLTree.js. - * - */ - - /** - * Create an HTML className based on a list of classes. In addition to joining - * with spaces, we also remove empty classes. - */ - const createClass = function(classes) { - return classes.filter((cls) => cls).join(" "); - }; - - const initNode = function(classes, style) { - this.classes = classes || []; - this.attributes = {}; - this.style = style || {}; - }; - - /** - * Convert into an HTML node - */ - const toNode = function(tagName) { - const node = document.createElement(tagName); - - // Apply the class - node.className = createClass(this.classes); - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - // Apply attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr )) { - node.setAttribute(attr, this.attributes[attr]); - } - } - - // Append the children, also as HTML nodes - for (let i = 0; i < this.children.length; i++) { - node.appendChild(this.children[i].toNode()); - } - - return node; - }; - - /** - * Convert into an HTML markup string - */ - const toMarkup = function(tagName) { - let markup = `<${tagName}`; - - // Add the class - if (this.classes.length) { - markup += ` class="${utils.escape(createClass(this.classes))}"`; - } - - let styles = ""; - - // Add the styles, after hyphenation - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - styles += `${utils.hyphenate(style)}:${this.style[style]};`; - } - } - - if (styles) { - markup += ` style="${styles}"`; - } - - // Add the attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr )) { - markup += ` ${attr}="${utils.escape(this.attributes[attr])}"`; - } - } - - markup += ">"; - - // Add the markup of the children, also as markup - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - markup += ``; - - return markup; - }; - - /** - * This node represents a span node, with a className, a list of children, and - * an inline style. - * - */ - class Span { - constructor(classes, children, style) { - initNode.call(this, classes, style); - this.children = children || []; - } - - setAttribute(attribute, value) { - this.attributes[attribute] = value; - } - - toNode() { - return toNode.call(this, "span"); - } - - toMarkup() { - return toMarkup.call(this, "span"); - } - } - - class TextNode$1 { - constructor(text) { - this.text = text; - } - toNode() { - return document.createTextNode(this.text); - } - toMarkup() { - return utils.escape(this.text); - } - } - - /** - * This node represents an image embed () element. - */ - class Img { - constructor(src, alt, style) { - this.alt = alt; - this.src = src; - this.classes = ["mord"]; - this.style = style; - } - - hasClass(className) { - return utils.contains(this.classes, className); - } - - toNode() { - const node = document.createElement("img"); - node.src = this.src; - node.alt = this.alt; - node.className = "mord"; - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - return node; - } - - toMarkup() { - let markup = `${this.alt}` and - * `` tags). - */ - class MathNode { - constructor(type, children, classes, style) { - this.type = type; - this.attributes = {}; - this.children = children || []; - this.classes = classes || []; - this.style = style || {}; // Used for elements - } - - /** - * Sets an attribute on a MathML node. MathML depends on attributes to convey a - * semantic content, so this is used heavily. - */ - setAttribute(name, value) { - this.attributes[name] = value; - } - - /** - * Gets an attribute on a MathML node. - */ - getAttribute(name) { - return this.attributes[name]; - } - - /** - * Converts the math node into a MathML-namespaced DOM element. - */ - toNode() { - const node = document.createElementNS("http://www.w3.org/1998/Math/MathML", this.type); - - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { - node.setAttribute(attr, this.attributes[attr]); - } - } - - if (this.classes.length > 0) { - node.className = createClass(this.classes); - } - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - for (let i = 0; i < this.children.length; i++) { - node.appendChild(this.children[i].toNode()); - } - - return node; - } - - /** - * Converts the math node into an HTML markup string. - */ - toMarkup() { - let markup = "<" + this.type; - - // Add the attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { - markup += " " + attr + '="'; - markup += utils.escape(this.attributes[attr]); - markup += '"'; - } - } - - if (this.classes.length > 0) { - markup += ` class="${utils.escape(createClass(this.classes))}"`; - } - - let styles = ""; - - // Add the styles, after hyphenation - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - styles += `${utils.hyphenate(style)}:${this.style[style]};`; - } - } - - if (styles) { - markup += ` style="${styles}"`; - } - - markup += ">"; - - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - markup += ""; - - return markup; - } - - /** - * Converts the math node into a string, similar to innerText, but escaped. - */ - toText() { - return this.children.map((child) => child.toText()).join(""); - } - } - - /** - * This node represents a piece of text. - */ - class TextNode { - constructor(text) { - this.text = text; - } - - /** - * Converts the text node into a DOM text node. - */ - toNode() { - return document.createTextNode(this.text); - } - - /** - * Converts the text node into escaped HTML markup - * (representing the text itself). - */ - toMarkup() { - return utils.escape(this.toText()); - } - - /** - * Converts the text node into a string - * (representing the text iteself). - */ - toText() { - return this.text; - } - } - - // Do not make an the only child of a . - // An acts as its own implicit . - const wrapWithMstyle = expression => { - let node; - if (expression.length === 1 && expression[0].type === "mrow") { - node = expression.pop(); - node.type = "mstyle"; - } else { - node = new MathNode("mstyle", expression); - } - return node - }; - - var mathMLTree = { - MathNode, - TextNode, - newDocumentFragment - }; - - /** - * This file provides support for building horizontal stretchy elements. - */ - - const stretchyCodePoint = { - widehat: "^", - widecheck: "ˇ", - widetilde: "~", - wideparen: "⏜", // \u23dc - utilde: "~", - overleftarrow: "\u2190", - underleftarrow: "\u2190", - xleftarrow: "\u2190", - overrightarrow: "\u2192", - underrightarrow: "\u2192", - xrightarrow: "\u2192", - underbrace: "\u23df", - overbrace: "\u23de", - overgroup: "\u23e0", - overparen: "⏜", - undergroup: "\u23e1", - underparen: "\u23dd", - overleftrightarrow: "\u2194", - underleftrightarrow: "\u2194", - xleftrightarrow: "\u2194", - Overrightarrow: "\u21d2", - xRightarrow: "\u21d2", - overleftharpoon: "\u21bc", - xleftharpoonup: "\u21bc", - overrightharpoon: "\u21c0", - xrightharpoonup: "\u21c0", - xLeftarrow: "\u21d0", - xLeftrightarrow: "\u21d4", - xhookleftarrow: "\u21a9", - xhookrightarrow: "\u21aa", - xmapsto: "\u21a6", - xrightharpoondown: "\u21c1", - xleftharpoondown: "\u21bd", - xtwoheadleftarrow: "\u219e", - xtwoheadrightarrow: "\u21a0", - xlongequal: "=", - xrightleftarrows: "\u21c4", - yields: "\u2192", - yieldsLeft: "\u2190", - mesomerism: "\u2194", - longrightharpoonup: "\u21c0", - longleftharpoondown: "\u21bd", - eqrightharpoonup: "\u21c0", - eqleftharpoondown: "\u21bd", - "\\cdrightarrow": "\u2192", - "\\cdleftarrow": "\u2190", - "\\cdlongequal": "=" - }; - - const mathMLnode = function(label) { - const child = new mathMLTree.TextNode(stretchyCodePoint[label.slice(1)]); - const node = new mathMLTree.MathNode("mo", [child]); - node.setAttribute("stretchy", "true"); - return node - }; - - var stretchy = { - mathMLnode - }; - - /** - * This file holds a list of all no-argument functions and single-character - * symbols (like 'a' or ';'). - * - * For each of the symbols, there are two properties they can have: - * - group (required): the ParseNode group type the symbol should have (i.e. - "textord", "mathord", etc). - * - replace: the character that this symbol or function should be - * replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi - * character in the main font). - * - * The outermost map in the table indicates what mode the symbols should be - * accepted in (e.g. "math" or "text"). - */ - - // Some of these have a "-token" suffix since these are also used as `ParseNode` - // types for raw text tokens, and we want to avoid conflicts with higher-level - // `ParseNode` types. These `ParseNode`s are constructed within `Parser` by - // looking up the `symbols` map. - const ATOMS = { - bin: 1, - close: 1, - inner: 1, - open: 1, - punct: 1, - rel: 1 - }; - const NON_ATOMS = { - "accent-token": 1, - mathord: 1, - "op-token": 1, - spacing: 1, - textord: 1 - }; - - const symbols = { - math: {}, - text: {} - }; - - /** `acceptUnicodeChar = true` is only applicable if `replace` is set. */ - function defineSymbol(mode, group, replace, name, acceptUnicodeChar) { - symbols[mode][name] = { group, replace }; - - if (acceptUnicodeChar && replace) { - symbols[mode][replace] = symbols[mode][name]; - } - } - - // Some abbreviations for commonly used strings. - // This helps minify the code, and also spotting typos using jshint. - - // modes: - const math = "math"; - const text = "text"; - - // groups: - const accent = "accent-token"; - const bin = "bin"; - const close = "close"; - const inner = "inner"; - const mathord = "mathord"; - const op = "op-token"; - const open = "open"; - const punct = "punct"; - const rel = "rel"; - const spacing = "spacing"; - const textord = "textord"; - - // Now comes the symbol table - - // Relation Symbols - defineSymbol(math, rel, "\u2261", "\\equiv", true); - defineSymbol(math, rel, "\u227a", "\\prec", true); - defineSymbol(math, rel, "\u227b", "\\succ", true); - defineSymbol(math, rel, "\u223c", "\\sim", true); - defineSymbol(math, rel, "\u27c2", "\\perp", true); - defineSymbol(math, rel, "\u2aaf", "\\preceq", true); - defineSymbol(math, rel, "\u2ab0", "\\succeq", true); - defineSymbol(math, rel, "\u2243", "\\simeq", true); - defineSymbol(math, rel, "\u224c", "\\backcong", true); - defineSymbol(math, rel, "|", "\\mid", true); - defineSymbol(math, rel, "\u226a", "\\ll", true); - defineSymbol(math, rel, "\u226b", "\\gg", true); - defineSymbol(math, rel, "\u224d", "\\asymp", true); - defineSymbol(math, rel, "\u2225", "\\parallel"); - defineSymbol(math, rel, "\u22c8", "\\bowtie", true); - defineSymbol(math, rel, "\u2323", "\\smile", true); - defineSymbol(math, rel, "\u2291", "\\sqsubseteq", true); - defineSymbol(math, rel, "\u2292", "\\sqsupseteq", true); - defineSymbol(math, rel, "\u2250", "\\doteq", true); - defineSymbol(math, rel, "\u2322", "\\frown", true); - defineSymbol(math, rel, "\u220b", "\\ni", true); - defineSymbol(math, rel, "\u220c", "\\notni", true); - defineSymbol(math, rel, "\u221d", "\\propto", true); - defineSymbol(math, rel, "\u22a2", "\\vdash", true); - defineSymbol(math, rel, "\u22a3", "\\dashv", true); - defineSymbol(math, rel, "\u220b", "\\owns"); - defineSymbol(math, rel, "\u2258", "\\arceq", true); - defineSymbol(math, rel, "\u2259", "\\wedgeq", true); - defineSymbol(math, rel, "\u225a", "\\veeeq", true); - defineSymbol(math, rel, "\u225b", "\\stareq", true); - defineSymbol(math, rel, "\u225d", "\\eqdef", true); - defineSymbol(math, rel, "\u225e", "\\measeq", true); - defineSymbol(math, rel, "\u225f", "\\questeq", true); - defineSymbol(math, rel, "\u2260", "\\ne", true); - defineSymbol(math, rel, "\u2260", "\\neq"); - // mathtools.sty - defineSymbol(math, rel, "\u2237", "\\dblcolon", true); - defineSymbol(math, rel, "\u2254", "\\coloneqq", true); - defineSymbol(math, rel, "\u2255", "\\eqqcolon", true); - defineSymbol(math, rel, "\u2239", "\\eqcolon", true); - defineSymbol(math, rel, "\u2A74", "\\Coloneqq", true); - - // Punctuation - defineSymbol(math, punct, "\u002e", "\\ldotp"); - defineSymbol(math, punct, "\u00b7", "\\cdotp"); - - // Misc Symbols - defineSymbol(math, textord, "\u0023", "\\#"); - defineSymbol(text, textord, "\u0023", "\\#"); - defineSymbol(math, textord, "\u0026", "\\&"); - defineSymbol(text, textord, "\u0026", "\\&"); - defineSymbol(math, textord, "\u2135", "\\aleph", true); - defineSymbol(math, textord, "\u2200", "\\forall", true); - defineSymbol(math, textord, "\u210f", "\\hbar", true); - defineSymbol(math, textord, "\u2203", "\\exists", true); - defineSymbol(math, textord, "\u2207", "\\nabla", true); - defineSymbol(math, textord, "\u266d", "\\flat", true); - defineSymbol(math, textord, "\u2113", "\\ell", true); - defineSymbol(math, textord, "\u266e", "\\natural", true); - defineSymbol(math, textord, "Å", "\\AA", true); - defineSymbol(text, textord, "Å", "\\AA", true); - defineSymbol(math, textord, "\u2663", "\\clubsuit", true); - defineSymbol(math, textord, "\u2667", "\\varclubsuit", true); - defineSymbol(math, textord, "\u2118", "\\wp", true); - defineSymbol(math, textord, "\u266f", "\\sharp", true); - defineSymbol(math, textord, "\u2662", "\\diamondsuit", true); - defineSymbol(math, textord, "\u2666", "\\vardiamondsuit", true); - defineSymbol(math, textord, "\u211c", "\\Re", true); - defineSymbol(math, textord, "\u2661", "\\heartsuit", true); - defineSymbol(math, textord, "\u2665", "\\varheartsuit", true); - defineSymbol(math, textord, "\u2111", "\\Im", true); - defineSymbol(math, textord, "\u2660", "\\spadesuit", true); - defineSymbol(math, textord, "\u2664", "\\varspadesuit", true); - defineSymbol(math, textord, "\u2640", "\\female", true); - defineSymbol(math, textord, "\u2642", "\\male", true); - defineSymbol(math, textord, "\u00a7", "\\S", true); - defineSymbol(text, textord, "\u00a7", "\\S"); - defineSymbol(math, textord, "\u00b6", "\\P", true); - defineSymbol(text, textord, "\u00b6", "\\P"); - defineSymbol(text, textord, "\u263a", "\\smiley", true); - defineSymbol(math, textord, "\u263a", "\\smiley", true); - - // Math and Text - defineSymbol(math, textord, "\u2020", "\\dag"); - defineSymbol(text, textord, "\u2020", "\\dag"); - defineSymbol(text, textord, "\u2020", "\\textdagger"); - defineSymbol(math, textord, "\u2021", "\\ddag"); - defineSymbol(text, textord, "\u2021", "\\ddag"); - defineSymbol(text, textord, "\u2021", "\\textdaggerdbl"); - - // Large Delimiters - defineSymbol(math, close, "\u23b1", "\\rmoustache", true); - defineSymbol(math, open, "\u23b0", "\\lmoustache", true); - defineSymbol(math, close, "\u27ef", "\\rgroup", true); - defineSymbol(math, open, "\u27ee", "\\lgroup", true); - - // Binary Operators - defineSymbol(math, bin, "\u2213", "\\mp", true); - defineSymbol(math, bin, "\u2296", "\\ominus", true); - defineSymbol(math, bin, "\u228e", "\\uplus", true); - defineSymbol(math, bin, "\u2293", "\\sqcap", true); - defineSymbol(math, bin, "\u2217", "\\ast"); - defineSymbol(math, bin, "\u2294", "\\sqcup", true); - defineSymbol(math, bin, "\u25ef", "\\bigcirc", true); - defineSymbol(math, bin, "\u2219", "\\bullet", true); - defineSymbol(math, bin, "\u2021", "\\ddagger"); - defineSymbol(math, bin, "\u2240", "\\wr", true); - defineSymbol(math, bin, "\u2a3f", "\\amalg"); - defineSymbol(math, bin, "\u0026", "\\And"); // from amsmath - - // Arrow Symbols - defineSymbol(math, rel, "\u27f5", "\\longleftarrow", true); - defineSymbol(math, rel, "\u21d0", "\\Leftarrow", true); - defineSymbol(math, rel, "\u27f8", "\\Longleftarrow", true); - defineSymbol(math, rel, "\u27f6", "\\longrightarrow", true); - defineSymbol(math, rel, "\u21d2", "\\Rightarrow", true); - defineSymbol(math, rel, "\u27f9", "\\Longrightarrow", true); - defineSymbol(math, rel, "\u2194", "\\leftrightarrow", true); - defineSymbol(math, rel, "\u27f7", "\\longleftrightarrow", true); - defineSymbol(math, rel, "\u21d4", "\\Leftrightarrow", true); - defineSymbol(math, rel, "\u27fa", "\\Longleftrightarrow", true); - defineSymbol(math, rel, "\u21a6", "\\mapsto", true); - defineSymbol(math, rel, "\u27fc", "\\longmapsto", true); - defineSymbol(math, rel, "\u2197", "\\nearrow", true); - defineSymbol(math, rel, "\u21a9", "\\hookleftarrow", true); - defineSymbol(math, rel, "\u21aa", "\\hookrightarrow", true); - defineSymbol(math, rel, "\u2198", "\\searrow", true); - defineSymbol(math, rel, "\u21bc", "\\leftharpoonup", true); - defineSymbol(math, rel, "\u21c0", "\\rightharpoonup", true); - defineSymbol(math, rel, "\u2199", "\\swarrow", true); - defineSymbol(math, rel, "\u21bd", "\\leftharpoondown", true); - defineSymbol(math, rel, "\u21c1", "\\rightharpoondown", true); - defineSymbol(math, rel, "\u2196", "\\nwarrow", true); - defineSymbol(math, rel, "\u21cc", "\\rightleftharpoons", true); - defineSymbol(math, mathord, "\u21af", "\\lightning", true); - defineSymbol(math, mathord, "\u2030", "\\permil", true); - defineSymbol(text, textord, "\u2030", "\\permil"); - - // AMS Negated Binary Relations - defineSymbol(math, rel, "\u226e", "\\nless", true); - // Symbol names preceeded by "@" each have a corresponding macro. - defineSymbol(math, rel, "\u2a87", "\\lneq", true); - defineSymbol(math, rel, "\u2268", "\\lneqq", true); - defineSymbol(math, rel, "\u2268\ufe00", "\\lvertneqq"); - defineSymbol(math, rel, "\u22e6", "\\lnsim", true); - defineSymbol(math, rel, "\u2a89", "\\lnapprox", true); - defineSymbol(math, rel, "\u2280", "\\nprec", true); - // unicode-math maps \u22e0 to \npreccurlyeq. We'll use the AMS synonym. - defineSymbol(math, rel, "\u22e0", "\\npreceq", true); - defineSymbol(math, rel, "\u22e8", "\\precnsim", true); - defineSymbol(math, rel, "\u2ab9", "\\precnapprox", true); - defineSymbol(math, rel, "\u2241", "\\nsim", true); - defineSymbol(math, rel, "\u2224", "\\nmid", true); - defineSymbol(math, rel, "\u2224", "\\nshortmid"); - defineSymbol(math, rel, "\u22ac", "\\nvdash", true); - defineSymbol(math, rel, "\u22ad", "\\nvDash", true); - defineSymbol(math, rel, "\u22ea", "\\ntriangleleft"); - defineSymbol(math, rel, "\u22ec", "\\ntrianglelefteq", true); - defineSymbol(math, rel, "\u2284", "\\nsubset", true); - defineSymbol(math, rel, "\u2285", "\\nsupset", true); - defineSymbol(math, rel, "\u228a", "\\subsetneq", true); - defineSymbol(math, rel, "\u228a\ufe00", "\\varsubsetneq"); - defineSymbol(math, rel, "\u2acb", "\\subsetneqq", true); - defineSymbol(math, rel, "\u2acb\ufe00", "\\varsubsetneqq"); - defineSymbol(math, rel, "\u226f", "\\ngtr", true); - defineSymbol(math, rel, "\u2a88", "\\gneq", true); - defineSymbol(math, rel, "\u2269", "\\gneqq", true); - defineSymbol(math, rel, "\u2269\ufe00", "\\gvertneqq"); - defineSymbol(math, rel, "\u22e7", "\\gnsim", true); - defineSymbol(math, rel, "\u2a8a", "\\gnapprox", true); - defineSymbol(math, rel, "\u2281", "\\nsucc", true); - // unicode-math maps \u22e1 to \nsucccurlyeq. We'll use the AMS synonym. - defineSymbol(math, rel, "\u22e1", "\\nsucceq", true); - defineSymbol(math, rel, "\u22e9", "\\succnsim", true); - defineSymbol(math, rel, "\u2aba", "\\succnapprox", true); - // unicode-math maps \u2246 to \simneqq. We'll use the AMS synonym. - defineSymbol(math, rel, "\u2246", "\\ncong", true); - defineSymbol(math, rel, "\u2226", "\\nparallel", true); - defineSymbol(math, rel, "\u2226", "\\nshortparallel"); - defineSymbol(math, rel, "\u22af", "\\nVDash", true); - defineSymbol(math, rel, "\u22eb", "\\ntriangleright"); - defineSymbol(math, rel, "\u22ed", "\\ntrianglerighteq", true); - defineSymbol(math, rel, "\u228b", "\\supsetneq", true); - defineSymbol(math, rel, "\u228b", "\\varsupsetneq"); - defineSymbol(math, rel, "\u2acc", "\\supsetneqq", true); - defineSymbol(math, rel, "\u2acc\ufe00", "\\varsupsetneqq"); - defineSymbol(math, rel, "\u22ae", "\\nVdash", true); - defineSymbol(math, rel, "\u2ab5", "\\precneqq", true); - defineSymbol(math, rel, "\u2ab6", "\\succneqq", true); - defineSymbol(math, bin, "\u22b4", "\\unlhd"); - defineSymbol(math, bin, "\u22b5", "\\unrhd"); - - // AMS Negated Arrows - defineSymbol(math, rel, "\u219a", "\\nleftarrow", true); - defineSymbol(math, rel, "\u219b", "\\nrightarrow", true); - defineSymbol(math, rel, "\u21cd", "\\nLeftarrow", true); - defineSymbol(math, rel, "\u21cf", "\\nRightarrow", true); - defineSymbol(math, rel, "\u21ae", "\\nleftrightarrow", true); - defineSymbol(math, rel, "\u21ce", "\\nLeftrightarrow", true); - - // AMS Misc - defineSymbol(math, rel, "\u25b3", "\\vartriangle"); - defineSymbol(math, textord, "\u210f", "\\hslash"); - defineSymbol(math, textord, "\u25bd", "\\triangledown"); - defineSymbol(math, textord, "\u25ca", "\\lozenge"); - defineSymbol(math, textord, "\u24c8", "\\circledS"); - defineSymbol(math, textord, "\u00ae", "\\circledR", true); - defineSymbol(text, textord, "\u00ae", "\\circledR"); - defineSymbol(text, textord, "\u00ae", "\\textregistered"); - defineSymbol(math, textord, "\u2221", "\\measuredangle", true); - defineSymbol(math, textord, "\u2204", "\\nexists"); - defineSymbol(math, textord, "\u2127", "\\mho"); - defineSymbol(math, textord, "\u2132", "\\Finv", true); - defineSymbol(math, textord, "\u2141", "\\Game", true); - defineSymbol(math, textord, "\u2035", "\\backprime"); - defineSymbol(math, textord, "\u25b2", "\\blacktriangle"); - defineSymbol(math, textord, "\u25bc", "\\blacktriangledown"); - defineSymbol(math, textord, "\u25a0", "\\blacksquare"); - defineSymbol(math, textord, "\u29eb", "\\blacklozenge"); - defineSymbol(math, textord, "\u2605", "\\bigstar"); - defineSymbol(math, textord, "\u2222", "\\sphericalangle", true); - defineSymbol(math, textord, "\u2201", "\\complement", true); - // unicode-math maps U+F0 to \matheth. We map to AMS function \eth - defineSymbol(math, textord, "\u00f0", "\\eth", true); - defineSymbol(text, textord, "\u00f0", "\u00f0"); - defineSymbol(math, textord, "\u2571", "\\diagup"); - defineSymbol(math, textord, "\u2572", "\\diagdown"); - defineSymbol(math, textord, "\u25a1", "\\square"); - defineSymbol(math, textord, "\u25a1", "\\Box"); - defineSymbol(math, textord, "\u25ca", "\\Diamond"); - // unicode-math maps U+A5 to \mathyen. We map to AMS function \yen - defineSymbol(math, textord, "\u00a5", "\\yen", true); - defineSymbol(text, textord, "\u00a5", "\\yen", true); - defineSymbol(math, textord, "\u2713", "\\checkmark", true); - defineSymbol(text, textord, "\u2713", "\\checkmark"); - defineSymbol(math, textord, "\u2717", "\\ballotx", true); - defineSymbol(text, textord, "\u2717", "\\ballotx"); - defineSymbol(text, textord, "\u2022", "\\textbullet"); - - // AMS Hebrew - defineSymbol(math, textord, "\u2136", "\\beth", true); - defineSymbol(math, textord, "\u2138", "\\daleth", true); - defineSymbol(math, textord, "\u2137", "\\gimel", true); - - // AMS Greek - defineSymbol(math, textord, "\u03dd", "\\digamma", true); - defineSymbol(math, textord, "\u03f0", "\\varkappa"); - - // AMS Delimiters - defineSymbol(math, open, "\u231C", "\\ulcorner", true); - defineSymbol(math, close, "\u231D", "\\urcorner", true); - defineSymbol(math, open, "\u231E", "\\llcorner", true); - defineSymbol(math, close, "\u231F", "\\lrcorner", true); - - // AMS Binary Relations - defineSymbol(math, rel, "\u2266", "\\leqq", true); - defineSymbol(math, rel, "\u2a7d", "\\leqslant", true); - defineSymbol(math, rel, "\u2a95", "\\eqslantless", true); - defineSymbol(math, rel, "\u2272", "\\lesssim", true); - defineSymbol(math, rel, "\u2a85", "\\lessapprox", true); - defineSymbol(math, rel, "\u224a", "\\approxeq", true); - defineSymbol(math, bin, "\u22d6", "\\lessdot"); - defineSymbol(math, rel, "\u22d8", "\\lll", true); - defineSymbol(math, rel, "\u2276", "\\lessgtr", true); - defineSymbol(math, rel, "\u22da", "\\lesseqgtr", true); - defineSymbol(math, rel, "\u2a8b", "\\lesseqqgtr", true); - defineSymbol(math, rel, "\u2251", "\\doteqdot"); - defineSymbol(math, rel, "\u2253", "\\risingdotseq", true); - defineSymbol(math, rel, "\u2252", "\\fallingdotseq", true); - defineSymbol(math, rel, "\u223d", "\\backsim", true); - defineSymbol(math, rel, "\u22cd", "\\backsimeq", true); - defineSymbol(math, rel, "\u2ac5", "\\subseteqq", true); - defineSymbol(math, rel, "\u22d0", "\\Subset", true); - defineSymbol(math, rel, "\u228f", "\\sqsubset", true); - defineSymbol(math, rel, "\u227c", "\\preccurlyeq", true); - defineSymbol(math, rel, "\u22de", "\\curlyeqprec", true); - defineSymbol(math, rel, "\u227e", "\\precsim", true); - defineSymbol(math, rel, "\u2ab7", "\\precapprox", true); - defineSymbol(math, rel, "\u22b2", "\\vartriangleleft"); - defineSymbol(math, rel, "\u22b4", "\\trianglelefteq"); - defineSymbol(math, rel, "\u22a8", "\\vDash", true); - defineSymbol(math, rel, "\u22aa", "\\Vvdash", true); - defineSymbol(math, rel, "\u2323", "\\smallsmile"); - defineSymbol(math, rel, "\u2322", "\\smallfrown"); - defineSymbol(math, rel, "\u224f", "\\bumpeq", true); - defineSymbol(math, rel, "\u224e", "\\Bumpeq", true); - defineSymbol(math, rel, "\u2267", "\\geqq", true); - defineSymbol(math, rel, "\u2a7e", "\\geqslant", true); - defineSymbol(math, rel, "\u2a96", "\\eqslantgtr", true); - defineSymbol(math, rel, "\u2273", "\\gtrsim", true); - defineSymbol(math, rel, "\u2a86", "\\gtrapprox", true); - defineSymbol(math, bin, "\u22d7", "\\gtrdot"); - defineSymbol(math, rel, "\u22d9", "\\ggg", true); - defineSymbol(math, rel, "\u2277", "\\gtrless", true); - defineSymbol(math, rel, "\u22db", "\\gtreqless", true); - defineSymbol(math, rel, "\u2a8c", "\\gtreqqless", true); - defineSymbol(math, rel, "\u2256", "\\eqcirc", true); - defineSymbol(math, rel, "\u2257", "\\circeq", true); - defineSymbol(math, rel, "\u225c", "\\triangleq", true); - defineSymbol(math, rel, "\u223c", "\\thicksim"); - defineSymbol(math, rel, "\u2248", "\\thickapprox"); - defineSymbol(math, rel, "\u2ac6", "\\supseteqq", true); - defineSymbol(math, rel, "\u22d1", "\\Supset", true); - defineSymbol(math, rel, "\u2290", "\\sqsupset", true); - defineSymbol(math, rel, "\u227d", "\\succcurlyeq", true); - defineSymbol(math, rel, "\u22df", "\\curlyeqsucc", true); - defineSymbol(math, rel, "\u227f", "\\succsim", true); - defineSymbol(math, rel, "\u2ab8", "\\succapprox", true); - defineSymbol(math, rel, "\u22b3", "\\vartriangleright"); - defineSymbol(math, rel, "\u22b5", "\\trianglerighteq"); - defineSymbol(math, rel, "\u22a9", "\\Vdash", true); - defineSymbol(math, rel, "\u2223", "\\shortmid"); - defineSymbol(math, rel, "\u2225", "\\shortparallel"); - defineSymbol(math, rel, "\u226c", "\\between", true); - defineSymbol(math, rel, "\u22d4", "\\pitchfork", true); - defineSymbol(math, rel, "\u221d", "\\varpropto"); - defineSymbol(math, rel, "\u25c0", "\\blacktriangleleft"); - // unicode-math says that \therefore is a mathord atom. - // We kept the amssymb atom type, which is rel. - defineSymbol(math, rel, "\u2234", "\\therefore", true); - defineSymbol(math, rel, "\u220d", "\\backepsilon"); - defineSymbol(math, rel, "\u25b6", "\\blacktriangleright"); - // unicode-math says that \because is a mathord atom. - // We kept the amssymb atom type, which is rel. - defineSymbol(math, rel, "\u2235", "\\because", true); - defineSymbol(math, rel, "\u22d8", "\\llless"); - defineSymbol(math, rel, "\u22d9", "\\gggtr"); - defineSymbol(math, bin, "\u22b2", "\\lhd"); - defineSymbol(math, bin, "\u22b3", "\\rhd"); - defineSymbol(math, rel, "\u2242", "\\eqsim", true); - defineSymbol(math, rel, "\u22c8", "\\Join"); - defineSymbol(math, rel, "\u2251", "\\Doteq", true); - defineSymbol(math, rel, "\u297d", "\\strictif", true); - defineSymbol(math, rel, "\u297c", "\\strictfi", true); - - // AMS Binary Operators - defineSymbol(math, bin, "\u2214", "\\dotplus", true); - defineSymbol(math, bin, "\u2216", "\\smallsetminus"); - defineSymbol(math, bin, "\u22d2", "\\Cap", true); - defineSymbol(math, bin, "\u22d3", "\\Cup", true); - defineSymbol(math, bin, "\u2a5e", "\\doublebarwedge", true); - defineSymbol(math, bin, "\u229f", "\\boxminus", true); - defineSymbol(math, bin, "\u229e", "\\boxplus", true); - defineSymbol(math, bin, "\u22c7", "\\divideontimes", true); - defineSymbol(math, bin, "\u22c9", "\\ltimes", true); - defineSymbol(math, bin, "\u22ca", "\\rtimes", true); - defineSymbol(math, bin, "\u22cb", "\\leftthreetimes", true); - defineSymbol(math, bin, "\u22cc", "\\rightthreetimes", true); - defineSymbol(math, bin, "\u22cf", "\\curlywedge", true); - defineSymbol(math, bin, "\u22ce", "\\curlyvee", true); - defineSymbol(math, bin, "\u229d", "\\circleddash", true); - defineSymbol(math, bin, "\u229b", "\\circledast", true); - defineSymbol(math, bin, "\u22ba", "\\intercal", true); - defineSymbol(math, bin, "\u22d2", "\\doublecap"); - defineSymbol(math, bin, "\u22d3", "\\doublecup"); - defineSymbol(math, bin, "\u22a0", "\\boxtimes", true); - - // AMS Arrows - // Note: unicode-math maps \u21e2 to their own function \rightdasharrow. - // We'll map it to AMS function \dashrightarrow. It produces the same atom. - defineSymbol(math, rel, "\u21e2", "\\dashrightarrow", true); - // unicode-math maps \u21e0 to \leftdasharrow. We'll use the AMS synonym. - defineSymbol(math, rel, "\u21e0", "\\dashleftarrow", true); - defineSymbol(math, rel, "\u21c7", "\\leftleftarrows", true); - defineSymbol(math, rel, "\u21c6", "\\leftrightarrows", true); - defineSymbol(math, rel, "\u21da", "\\Lleftarrow", true); - defineSymbol(math, rel, "\u219e", "\\twoheadleftarrow", true); - defineSymbol(math, rel, "\u21a2", "\\leftarrowtail", true); - defineSymbol(math, rel, "\u21ab", "\\looparrowleft", true); - defineSymbol(math, rel, "\u21cb", "\\leftrightharpoons", true); - defineSymbol(math, rel, "\u21b6", "\\curvearrowleft", true); - // unicode-math maps \u21ba to \acwopencirclearrow. We'll use the AMS synonym. - defineSymbol(math, rel, "\u21ba", "\\circlearrowleft", true); - defineSymbol(math, rel, "\u21b0", "\\Lsh", true); - defineSymbol(math, rel, "\u21c8", "\\upuparrows", true); - defineSymbol(math, rel, "\u21bf", "\\upharpoonleft", true); - defineSymbol(math, rel, "\u21c3", "\\downharpoonleft", true); - defineSymbol(math, rel, "\u22b6", "\\origof", true); - defineSymbol(math, rel, "\u22b7", "\\imageof", true); - defineSymbol(math, rel, "\u22b8", "\\multimap", true); - defineSymbol(math, rel, "\u21ad", "\\leftrightsquigarrow", true); - defineSymbol(math, rel, "\u21c9", "\\rightrightarrows", true); - defineSymbol(math, rel, "\u21c4", "\\rightleftarrows", true); - defineSymbol(math, rel, "\u21a0", "\\twoheadrightarrow", true); - defineSymbol(math, rel, "\u21a3", "\\rightarrowtail", true); - defineSymbol(math, rel, "\u21ac", "\\looparrowright", true); - defineSymbol(math, rel, "\u21b7", "\\curvearrowright", true); - // unicode-math maps \u21bb to \cwopencirclearrow. We'll use the AMS synonym. - defineSymbol(math, rel, "\u21bb", "\\circlearrowright", true); - defineSymbol(math, rel, "\u21b1", "\\Rsh", true); - defineSymbol(math, rel, "\u21ca", "\\downdownarrows", true); - defineSymbol(math, rel, "\u21be", "\\upharpoonright", true); - defineSymbol(math, rel, "\u21c2", "\\downharpoonright", true); - defineSymbol(math, rel, "\u21dd", "\\rightsquigarrow", true); - defineSymbol(math, rel, "\u21dd", "\\leadsto"); - defineSymbol(math, rel, "\u21db", "\\Rrightarrow", true); - defineSymbol(math, rel, "\u21be", "\\restriction"); - - defineSymbol(math, textord, "\u2018", "`"); - defineSymbol(math, textord, "$", "\\$"); - defineSymbol(text, textord, "$", "\\$"); - defineSymbol(text, textord, "$", "\\textdollar"); - defineSymbol(math, textord, "%", "\\%"); - defineSymbol(text, textord, "%", "\\%"); - defineSymbol(math, textord, "_", "\\_"); - defineSymbol(text, textord, "_", "\\_"); - defineSymbol(text, textord, "_", "\\textunderscore"); - defineSymbol(text, textord, "\u2423", "\\textvisiblespace", true); - defineSymbol(math, textord, "\u2220", "\\angle", true); - defineSymbol(math, textord, "\u221e", "\\infty", true); - defineSymbol(math, textord, "\u2032", "\\prime"); - defineSymbol(math, textord, "\u25b3", "\\triangle"); - defineSymbol(text, textord, "\u0391", "\\Alpha", true); - defineSymbol(text, textord, "\u0392", "\\Beta", true); - defineSymbol(text, textord, "\u0393", "\\Gamma", true); - defineSymbol(text, textord, "\u0394", "\\Delta", true); - defineSymbol(text, textord, "\u0395", "\\Epsilon", true); - defineSymbol(text, textord, "\u0396", "\\Zeta", true); - defineSymbol(text, textord, "\u0397", "\\Eta", true); - defineSymbol(text, textord, "\u0398", "\\Theta", true); - defineSymbol(text, textord, "\u0399", "\\Iota", true); - defineSymbol(text, textord, "\u039a", "\\Kappa", true); - defineSymbol(text, textord, "\u039b", "\\Lambda", true); - defineSymbol(text, textord, "\u039c", "\\Mu", true); - defineSymbol(text, textord, "\u039d", "\\Nu", true); - defineSymbol(text, textord, "\u039e", "\\Xi", true); - defineSymbol(text, textord, "\u039f", "\\Omicron", true); - defineSymbol(text, textord, "\u03a0", "\\Pi", true); - defineSymbol(text, textord, "\u03a1", "\\Rho", true); - defineSymbol(text, textord, "\u03a3", "\\Sigma", true); - defineSymbol(text, textord, "\u03a4", "\\Tau", true); - defineSymbol(text, textord, "\u03a5", "\\Upsilon", true); - defineSymbol(text, textord, "\u03a6", "\\Phi", true); - defineSymbol(text, textord, "\u03a7", "\\Chi", true); - defineSymbol(text, textord, "\u03a8", "\\Psi", true); - defineSymbol(text, textord, "\u03a9", "\\Omega", true); - defineSymbol(math, mathord, "\u0391", "\\Alpha", true); - defineSymbol(math, mathord, "\u0392", "\\Beta", true); - defineSymbol(math, mathord, "\u0393", "\\Gamma", true); - defineSymbol(math, mathord, "\u0394", "\\Delta", true); - defineSymbol(math, mathord, "\u0395", "\\Epsilon", true); - defineSymbol(math, mathord, "\u0396", "\\Zeta", true); - defineSymbol(math, mathord, "\u0397", "\\Eta", true); - defineSymbol(math, mathord, "\u0398", "\\Theta", true); - defineSymbol(math, mathord, "\u0399", "\\Iota", true); - defineSymbol(math, mathord, "\u039a", "\\Kappa", true); - defineSymbol(math, mathord, "\u039b", "\\Lambda", true); - defineSymbol(math, mathord, "\u039c", "\\Mu", true); - defineSymbol(math, mathord, "\u039d", "\\Nu", true); - defineSymbol(math, mathord, "\u039e", "\\Xi", true); - defineSymbol(math, mathord, "\u039f", "\\Omicron", true); - defineSymbol(math, mathord, "\u03a0", "\\Pi", true); - defineSymbol(math, mathord, "\u03a1", "\\Rho", true); - defineSymbol(math, mathord, "\u03a3", "\\Sigma", true); - defineSymbol(math, mathord, "\u03a4", "\\Tau", true); - defineSymbol(math, mathord, "\u03a5", "\\Upsilon", true); - defineSymbol(math, mathord, "\u03a6", "\\Phi", true); - defineSymbol(math, mathord, "\u03a7", "\\Chi", true); - defineSymbol(math, mathord, "\u03a8", "\\Psi", true); - defineSymbol(math, mathord, "\u03a9", "\\Omega", true); - defineSymbol(math, open, "\u00ac", "\\neg", true); - defineSymbol(math, open, "\u00ac", "\\lnot"); - defineSymbol(math, textord, "\u22a4", "\\top"); - defineSymbol(math, textord, "\u22a5", "\\bot"); - defineSymbol(math, textord, "\u2205", "\\emptyset"); - defineSymbol(math, textord, "\u00f8", "\\varnothing"); - defineSymbol(math, mathord, "\u03b1", "\\alpha", true); - defineSymbol(math, mathord, "\u03b2", "\\beta", true); - defineSymbol(math, mathord, "\u03b3", "\\gamma", true); - defineSymbol(math, mathord, "\u03b4", "\\delta", true); - defineSymbol(math, mathord, "\u03f5", "\\epsilon", true); - defineSymbol(math, mathord, "\u03b6", "\\zeta", true); - defineSymbol(math, mathord, "\u03b7", "\\eta", true); - defineSymbol(math, mathord, "\u03b8", "\\theta", true); - defineSymbol(math, mathord, "\u03b9", "\\iota", true); - defineSymbol(math, mathord, "\u03ba", "\\kappa", true); - defineSymbol(math, mathord, "\u03bb", "\\lambda", true); - defineSymbol(math, mathord, "\u03bc", "\\mu", true); - defineSymbol(math, mathord, "\u03bd", "\\nu", true); - defineSymbol(math, mathord, "\u03be", "\\xi", true); - defineSymbol(math, mathord, "\u03bf", "\\omicron", true); - defineSymbol(math, mathord, "\u03c0", "\\pi", true); - defineSymbol(math, mathord, "\u03c1", "\\rho", true); - defineSymbol(math, mathord, "\u03c3", "\\sigma", true); - defineSymbol(math, mathord, "\u03c4", "\\tau", true); - defineSymbol(math, mathord, "\u03c5", "\\upsilon", true); - defineSymbol(math, mathord, "\u03d5", "\\phi", true); - defineSymbol(math, mathord, "\u03c7", "\\chi", true); - defineSymbol(math, mathord, "\u03c8", "\\psi", true); - defineSymbol(math, mathord, "\u03c9", "\\omega", true); - defineSymbol(math, mathord, "\u03b5", "\\varepsilon", true); - defineSymbol(math, mathord, "\u03d1", "\\vartheta", true); - defineSymbol(math, mathord, "\u03d6", "\\varpi", true); - defineSymbol(math, mathord, "\u03f1", "\\varrho", true); - defineSymbol(math, mathord, "\u03c2", "\\varsigma", true); - defineSymbol(math, mathord, "\u03c6", "\\varphi", true); - defineSymbol(math, mathord, "\u03d8", "\\Coppa", true); - defineSymbol(math, mathord, "\u03d9", "\\coppa", true); - defineSymbol(math, mathord, "\u03d9", "\\varcoppa", true); - defineSymbol(math, mathord, "\u03de", "\\Koppa", true); - defineSymbol(math, mathord, "\u03df", "\\koppa", true); - defineSymbol(math, mathord, "\u03e0", "\\Sampi", true); - defineSymbol(math, mathord, "\u03e1", "\\sampi", true); - defineSymbol(math, mathord, "\u03da", "\\Stigma", true); - defineSymbol(math, mathord, "\u03db", "\\stigma", true); - defineSymbol(math, mathord, "\u2aeb", "\\Bot"); - defineSymbol(math, bin, "\u2217", "\u2217", true); - defineSymbol(math, bin, "+", "+"); - defineSymbol(math, bin, "*", "*"); - defineSymbol(math, bin, "\u2044", "\u2044"); - defineSymbol(math, bin, "\u2212", "-", true); - defineSymbol(math, bin, "\u22c5", "\\cdot", true); - defineSymbol(math, bin, "\u2218", "\\circ", true); - defineSymbol(math, bin, "\u00f7", "\\div", true); - defineSymbol(math, bin, "\u00b1", "\\pm", true); - defineSymbol(math, bin, "\u00d7", "\\times", true); - defineSymbol(math, bin, "\u2229", "\\cap", true); - defineSymbol(math, bin, "\u222a", "\\cup", true); - defineSymbol(math, bin, "\u2216", "\\setminus", true); - defineSymbol(math, bin, "\u2227", "\\land"); - defineSymbol(math, bin, "\u2228", "\\lor"); - defineSymbol(math, bin, "\u2227", "\\wedge", true); - defineSymbol(math, bin, "\u2228", "\\vee", true); - defineSymbol(math, open, "\u27e6", "\\llbracket", true); // stmaryrd/semantic packages - defineSymbol(math, close, "\u27e7", "\\rrbracket", true); - defineSymbol(math, open, "\u27e8", "\\langle", true); - defineSymbol(math, open, "|", "\\lvert"); - defineSymbol(math, open, "\u2016", "\\lVert"); - defineSymbol(math, textord, "!", "\\oc"); // cmll package - defineSymbol(math, textord, "?", "\\wn"); - defineSymbol(math, textord, "\u2193", "\\shpos"); - defineSymbol(math, textord, "\u2195", "\\shift"); - defineSymbol(math, textord, "\u2191", "\\shneg"); - defineSymbol(math, close, "?", "?"); - defineSymbol(math, close, "!", "!"); - defineSymbol(math, close, "‼", "‼"); - defineSymbol(math, close, "\u27e9", "\\rangle", true); - defineSymbol(math, close, "|", "\\rvert"); - defineSymbol(math, close, "\u2016", "\\rVert"); - defineSymbol(math, open, "\u2983", "\\lBrace", true); // stmaryrd/semantic packages - defineSymbol(math, close, "\u2984", "\\rBrace", true); - defineSymbol(math, rel, "=", "\\equal", true); - defineSymbol(math, rel, ":", ":"); - defineSymbol(math, rel, "\u2248", "\\approx", true); - defineSymbol(math, rel, "\u2245", "\\cong", true); - defineSymbol(math, rel, "\u2265", "\\ge"); - defineSymbol(math, rel, "\u2265", "\\geq", true); - defineSymbol(math, rel, "\u2190", "\\gets"); - defineSymbol(math, rel, ">", "\\gt", true); - defineSymbol(math, rel, "\u2208", "\\in", true); - defineSymbol(math, rel, "\u2209", "\\notin", true); - defineSymbol(math, rel, "\ue020", "\\@not"); - defineSymbol(math, rel, "\u2282", "\\subset", true); - defineSymbol(math, rel, "\u2283", "\\supset", true); - defineSymbol(math, rel, "\u2286", "\\subseteq", true); - defineSymbol(math, rel, "\u2287", "\\supseteq", true); - defineSymbol(math, rel, "\u2288", "\\nsubseteq", true); - defineSymbol(math, rel, "\u2288", "\\nsubseteqq"); - defineSymbol(math, rel, "\u2289", "\\nsupseteq", true); - defineSymbol(math, rel, "\u2289", "\\nsupseteqq"); - defineSymbol(math, rel, "\u22a8", "\\models"); - defineSymbol(math, rel, "\u2190", "\\leftarrow", true); - defineSymbol(math, rel, "\u2264", "\\le"); - defineSymbol(math, rel, "\u2264", "\\leq", true); - defineSymbol(math, rel, "<", "\\lt", true); - defineSymbol(math, rel, "\u2192", "\\rightarrow", true); - defineSymbol(math, rel, "\u2192", "\\to"); - defineSymbol(math, rel, "\u2271", "\\ngeq", true); - defineSymbol(math, rel, "\u2271", "\\ngeqq"); - defineSymbol(math, rel, "\u2271", "\\ngeqslant"); - defineSymbol(math, rel, "\u2270", "\\nleq", true); - defineSymbol(math, rel, "\u2270", "\\nleqq"); - defineSymbol(math, rel, "\u2270", "\\nleqslant"); - defineSymbol(math, rel, "\u2aeb", "\\Perp", true); //cmll package - defineSymbol(math, spacing, "\u00a0", "\\ "); - defineSymbol(math, spacing, "\u00a0", "\\space"); - // Ref: LaTeX Source 2e: \DeclareRobustCommand{\nobreakspace}{% - defineSymbol(math, spacing, "\u00a0", "\\nobreakspace"); - defineSymbol(text, spacing, "\u00a0", "\\ "); - defineSymbol(text, spacing, "\u00a0", " "); - defineSymbol(text, spacing, "\u00a0", "\\space"); - defineSymbol(text, spacing, "\u00a0", "\\nobreakspace"); - defineSymbol(math, spacing, null, "\\nobreak"); - defineSymbol(math, spacing, null, "\\allowbreak"); - defineSymbol(math, punct, ",", ","); - defineSymbol(text, punct, ":", ":"); - defineSymbol(math, punct, ";", ";"); - defineSymbol(math, bin, "\u22bc", "\\barwedge", true); - defineSymbol(math, bin, "\u22bb", "\\veebar", true); - defineSymbol(math, bin, "\u2299", "\\odot", true); - defineSymbol(math, bin, "\u2295", "\\oplus", true); - defineSymbol(math, bin, "\u2297", "\\otimes", true); - defineSymbol(math, textord, "\u2202", "\\partial", true); - defineSymbol(math, bin, "\u2298", "\\oslash", true); - defineSymbol(math, bin, "\u229a", "\\circledcirc", true); - defineSymbol(math, bin, "\u22a1", "\\boxdot", true); - defineSymbol(math, bin, "\u25b3", "\\bigtriangleup"); - defineSymbol(math, bin, "\u25bd", "\\bigtriangledown"); - defineSymbol(math, bin, "\u2020", "\\dagger"); - defineSymbol(math, bin, "\u22c4", "\\diamond"); - defineSymbol(math, bin, "\u22c6", "\\star"); - defineSymbol(math, bin, "\u25c3", "\\triangleleft"); - defineSymbol(math, bin, "\u25b9", "\\triangleright"); - defineSymbol(math, open, "{", "\\{"); - defineSymbol(text, textord, "{", "\\{"); - defineSymbol(text, textord, "{", "\\textbraceleft"); - defineSymbol(math, close, "}", "\\}"); - defineSymbol(text, textord, "}", "\\}"); - defineSymbol(text, textord, "}", "\\textbraceright"); - defineSymbol(math, open, "{", "\\lbrace"); - defineSymbol(math, close, "}", "\\rbrace"); - defineSymbol(math, open, "[", "\\lbrack", true); - defineSymbol(text, textord, "[", "\\lbrack", true); - defineSymbol(math, close, "]", "\\rbrack", true); - defineSymbol(text, textord, "]", "\\rbrack", true); - defineSymbol(math, open, "(", "\\lparen", true); - defineSymbol(math, close, ")", "\\rparen", true); - defineSymbol(text, textord, "<", "\\textless", true); // in T1 fontenc - defineSymbol(text, textord, ">", "\\textgreater", true); // in T1 fontenc - defineSymbol(math, open, "\u230a", "\\lfloor", true); - defineSymbol(math, close, "\u230b", "\\rfloor", true); - defineSymbol(math, open, "\u2308", "\\lceil", true); - defineSymbol(math, close, "\u2309", "\\rceil", true); - defineSymbol(math, textord, "\\", "\\backslash"); - defineSymbol(math, textord, "|", "|"); - defineSymbol(math, textord, "|", "\\vert"); - defineSymbol(text, textord, "|", "\\textbar", true); // in T1 fontenc - defineSymbol(math, textord, "\u2016", "\\|"); - defineSymbol(math, textord, "\u2016", "\\Vert"); - defineSymbol(text, textord, "\u2016", "\\textbardbl"); - defineSymbol(text, textord, "~", "\\textasciitilde"); - defineSymbol(text, textord, "\\", "\\textbackslash"); - defineSymbol(text, textord, "^", "\\textasciicircum"); - defineSymbol(math, rel, "\u2191", "\\uparrow", true); - defineSymbol(math, rel, "\u21d1", "\\Uparrow", true); - defineSymbol(math, rel, "\u2193", "\\downarrow", true); - defineSymbol(math, rel, "\u21d3", "\\Downarrow", true); - defineSymbol(math, rel, "\u2195", "\\updownarrow", true); - defineSymbol(math, rel, "\u21d5", "\\Updownarrow", true); - defineSymbol(math, op, "\u2210", "\\coprod"); - defineSymbol(math, op, "\u22c1", "\\bigvee"); - defineSymbol(math, op, "\u22c0", "\\bigwedge"); - defineSymbol(math, op, "\u2a04", "\\biguplus"); - defineSymbol(math, op, "\u22c2", "\\bigcap"); - defineSymbol(math, op, "\u22c3", "\\bigcup"); - defineSymbol(math, op, "\u222b", "\\int"); - defineSymbol(math, op, "\u222b", "\\intop"); - defineSymbol(math, op, "\u222c", "\\iint"); - defineSymbol(math, op, "\u222d", "\\iiint"); - defineSymbol(math, op, "\u220f", "\\prod"); - defineSymbol(math, op, "\u2211", "\\sum"); - defineSymbol(math, op, "\u2a02", "\\bigotimes"); - defineSymbol(math, op, "\u2a01", "\\bigoplus"); - defineSymbol(math, op, "\u2a00", "\\bigodot"); - defineSymbol(math, op, "\u222e", "\\oint"); - defineSymbol(math, op, "\u222f", "\\oiint"); - defineSymbol(math, op, "\u2230", "\\oiiint"); - defineSymbol(math, op, "\u2231", "\\intclockwise"); - defineSymbol(math, op, "\u2232", "\\varointclockwise"); - defineSymbol(math, op, "\u2a0c", "\\iiiint"); - defineSymbol(math, op, "\u2a0d", "\\intbar"); - defineSymbol(math, op, "\u2a0e", "\\intBar"); - defineSymbol(math, op, "\u2a0f", "\\fint"); - defineSymbol(math, op, "\u2a12", "\\rppolint"); - defineSymbol(math, op, "\u2a13", "\\scpolint"); - defineSymbol(math, op, "\u2a15", "\\pointint"); - defineSymbol(math, op, "\u2a16", "\\sqint"); - defineSymbol(math, op, "\u2a17", "\\intlarhk"); - defineSymbol(math, op, "\u2a18", "\\intx"); - defineSymbol(math, op, "\u2a19", "\\intcap"); - defineSymbol(math, op, "\u2a1a", "\\intcup"); - defineSymbol(math, op, "\u2a05", "\\bigsqcap"); - defineSymbol(math, op, "\u2a06", "\\bigsqcup"); - defineSymbol(math, op, "\u222b", "\\smallint"); - defineSymbol(text, inner, "\u2026", "\\textellipsis"); - defineSymbol(math, inner, "\u2026", "\\mathellipsis"); - defineSymbol(text, inner, "\u2026", "\\ldots", true); - defineSymbol(math, inner, "\u2026", "\\ldots", true); - defineSymbol(math, inner, "\u22f0", "\\iddots", true); - defineSymbol(math, inner, "\u22ef", "\\@cdots", true); - defineSymbol(math, inner, "\u22f1", "\\ddots", true); - defineSymbol(math, textord, "\u22ee", "\\varvdots"); // \vdots is a macro - defineSymbol(math, accent, "\u02ca", "\\acute"); - defineSymbol(math, accent, "\u0060", "\\grave"); - defineSymbol(math, accent, "\u00a8", "\\ddot"); - defineSymbol(math, accent, "\u20db", "\\dddot"); - defineSymbol(math, accent, "\u20dc", "\\ddddot"); - defineSymbol(math, accent, "\u007e", "\\tilde"); - defineSymbol(math, accent, "\u203e", "\\bar"); - defineSymbol(math, accent, "\u02d8", "\\breve"); - defineSymbol(math, accent, "\u02c7", "\\check"); - defineSymbol(math, accent, "\u005e", "\\hat"); - defineSymbol(math, accent, "\u20d7", "\\vec"); - defineSymbol(math, accent, "\u02d9", "\\dot"); - defineSymbol(math, accent, "\u02da", "\\mathring"); - defineSymbol(math, mathord, "\u0131", "\\imath", true); - defineSymbol(math, mathord, "\u0237", "\\jmath", true); - defineSymbol(math, textord, "\u0131", "\u0131"); - defineSymbol(math, textord, "\u0237", "\u0237"); - defineSymbol(text, textord, "\u0131", "\\i", true); - defineSymbol(text, textord, "\u0237", "\\j", true); - defineSymbol(text, textord, "\u00df", "\\ss", true); - defineSymbol(text, textord, "\u00e6", "\\ae", true); - defineSymbol(text, textord, "\u0153", "\\oe", true); - defineSymbol(text, textord, "\u00f8", "\\o", true); - defineSymbol(math, mathord, "\u00f8", "\\o", true); - defineSymbol(text, textord, "\u00c6", "\\AE", true); - defineSymbol(text, textord, "\u0152", "\\OE", true); - defineSymbol(text, textord, "\u00d8", "\\O", true); - defineSymbol(math, mathord, "\u00d8", "\\O", true); - defineSymbol(text, accent, "\u02ca", "\\'"); // acute - defineSymbol(text, accent, "\u02cb", "\\`"); // grave - defineSymbol(text, accent, "\u02c6", "\\^"); // circumflex - defineSymbol(text, accent, "\u02dc", "\\~"); // tilde - defineSymbol(text, accent, "\u02c9", "\\="); // macron - defineSymbol(text, accent, "\u02d8", "\\u"); // breve - defineSymbol(text, accent, "\u02d9", "\\."); // dot above - defineSymbol(text, accent, "\u00b8", "\\c"); // cedilla - defineSymbol(text, accent, "\u02da", "\\r"); // ring above - defineSymbol(text, accent, "\u02c7", "\\v"); // caron - defineSymbol(text, accent, "\u00a8", '\\"'); // diaresis - defineSymbol(text, accent, "\u02dd", "\\H"); // double acute - defineSymbol(math, accent, "\u02ca", "\\'"); // acute - defineSymbol(math, accent, "\u02cb", "\\`"); // grave - defineSymbol(math, accent, "\u02c6", "\\^"); // circumflex - defineSymbol(math, accent, "\u02dc", "\\~"); // tilde - defineSymbol(math, accent, "\u02c9", "\\="); // macron - defineSymbol(math, accent, "\u02d8", "\\u"); // breve - defineSymbol(math, accent, "\u02d9", "\\."); // dot above - defineSymbol(math, accent, "\u00b8", "\\c"); // cedilla - defineSymbol(math, accent, "\u02da", "\\r"); // ring above - defineSymbol(math, accent, "\u02c7", "\\v"); // caron - defineSymbol(math, accent, "\u00a8", '\\"'); // diaresis - defineSymbol(math, accent, "\u02dd", "\\H"); // double acute - - // These ligatures are detected and created in Parser.js's `formLigatures`. - const ligatures = { - "--": true, - "---": true, - "``": true, - "''": true - }; - - defineSymbol(text, textord, "\u2013", "--", true); - defineSymbol(text, textord, "\u2013", "\\textendash"); - defineSymbol(text, textord, "\u2014", "---", true); - defineSymbol(text, textord, "\u2014", "\\textemdash"); - defineSymbol(text, textord, "\u2018", "`", true); - defineSymbol(text, textord, "\u2018", "\\textquoteleft"); - defineSymbol(text, textord, "\u2019", "'", true); - defineSymbol(text, textord, "\u2019", "\\textquoteright"); - defineSymbol(text, textord, "\u201c", "``", true); - defineSymbol(text, textord, "\u201c", "\\textquotedblleft"); - defineSymbol(text, textord, "\u201d", "''", true); - defineSymbol(text, textord, "\u201d", "\\textquotedblright"); - // \degree from gensymb package - defineSymbol(math, textord, "\u00b0", "\\degree", true); - defineSymbol(text, textord, "\u00b0", "\\degree"); - // \textdegree from inputenc package - defineSymbol(text, textord, "\u00b0", "\\textdegree", true); - // TODO: In LaTeX, \pounds can generate a different character in text and math - // mode, but among our fonts, only Main-Regular defines this character "163". - defineSymbol(math, textord, "\u00a3", "\\pounds"); - defineSymbol(math, textord, "\u00a3", "\\mathsterling", true); - defineSymbol(text, textord, "\u00a3", "\\pounds"); - defineSymbol(text, textord, "\u00a3", "\\textsterling", true); - defineSymbol(math, textord, "\u2720", "\\maltese"); - defineSymbol(text, textord, "\u2720", "\\maltese"); - defineSymbol(math, textord, "\u20ac", "\\euro", true); - defineSymbol(text, textord, "\u20ac", "\\euro", true); - defineSymbol(text, textord, "\u20ac", "\\texteuro"); - defineSymbol(math, textord, "\u00a9", "\\copyright", true); - defineSymbol(text, textord, "\u00a9", "\\textcopyright"); - - // Italic Greek - defineSymbol(math, textord, "𝛤", "\\varGamma"); - defineSymbol(math, textord, "𝛥", "\\varDelta"); - defineSymbol(math, textord, "𝛩", "\\varTheta"); - defineSymbol(math, textord, "𝛬", "\\varLambda"); - defineSymbol(math, textord, "𝛯", "\\varXi"); - defineSymbol(math, textord, "𝛱", "\\varPi"); - defineSymbol(math, textord, "𝛴", "\\varSigma"); - defineSymbol(math, textord, "𝛶", "\\varUpsilon"); - defineSymbol(math, textord, "𝛷", "\\varPhi"); - defineSymbol(math, textord, "𝛹", "\\varPsi"); - defineSymbol(math, textord, "𝛺", "\\varOmega"); - defineSymbol(text, textord, "𝛤", "\\varGamma"); - defineSymbol(text, textord, "𝛥", "\\varDelta"); - defineSymbol(text, textord, "𝛩", "\\varTheta"); - defineSymbol(text, textord, "𝛬", "\\varLambda"); - defineSymbol(text, textord, "𝛯", "\\varXi"); - defineSymbol(text, textord, "𝛱", "\\varPi"); - defineSymbol(text, textord, "𝛴", "\\varSigma"); - defineSymbol(text, textord, "𝛶", "\\varUpsilon"); - defineSymbol(text, textord, "𝛷", "\\varPhi"); - defineSymbol(text, textord, "𝛹", "\\varPsi"); - defineSymbol(text, textord, "𝛺", "\\varOmega"); - - - // There are lots of symbols which are the same, so we add them in afterwards. - // All of these are textords in math mode - const mathTextSymbols = '0123456789/@."'; - for (let i = 0; i < mathTextSymbols.length; i++) { - const ch = mathTextSymbols.charAt(i); - defineSymbol(math, textord, ch, ch); - } - - // All of these are textords in text mode - const textSymbols = '0123456789!@*()-=+";:?/.,'; - for (let i = 0; i < textSymbols.length; i++) { - const ch = textSymbols.charAt(i); - defineSymbol(text, textord, ch, ch); - } - - // All of these are textords in text mode, and mathords in math mode - const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - for (let i = 0; i < letters.length; i++) { - const ch = letters.charAt(i); - defineSymbol(math, mathord, ch, ch); - defineSymbol(text, textord, ch, ch); - } - - // Some more letters in Unicode Basic Multilingual Plane. - const narrow = "ÇÐÞçþℂℍℕℙℚℝℤℎℏℊℋℌℐℑℒℓ℘ℛℜℬℰℱℳℭℨ"; - for (let i = 0; i < narrow.length; i++) { - const ch = narrow.charAt(i); - defineSymbol(math, mathord, ch, ch); - defineSymbol(text, textord, ch, ch); - } - - // The next loop loads wide (surrogate pair) characters. - // We support some letters in the Unicode range U+1D400 to U+1D7FF, - // Mathematical Alphanumeric Symbols. - let wideChar = ""; - for (let i = 0; i < letters.length; i++) { - // The hex numbers in the next line are a surrogate pair. - // 0xD835 is the high surrogate for all letters in the range we support. - // 0xDC00 is the low surrogate for bold A. - wideChar = String.fromCharCode(0xd835, 0xdc00 + i); // A-Z a-z bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdc34 + i); // A-Z a-z italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdc68 + i); // A-Z a-z bold italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdd04 + i); // A-Z a-z Fractur - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdda0 + i); // A-Z a-z sans-serif - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xddd4 + i); // A-Z a-z sans bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xde08 + i); // A-Z a-z sans italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xde70 + i); // A-Z a-z monospace - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdd38 + i); // A-Z a-z double struck - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - const ch = letters.charAt(i); - wideChar = String.fromCharCode(0xd835, 0xdc9c + i); // A-Z a-z calligraphic - defineSymbol(math, mathord, ch, wideChar); - defineSymbol(text, textord, ch, wideChar); - } - - // Next, some wide character numerals - for (let i = 0; i < 10; i++) { - wideChar = String.fromCharCode(0xd835, 0xdfce + i); // 0-9 bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdfe2 + i); // 0-9 sans serif - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdfec + i); // 0-9 bold sans - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdff6 + i); // 0-9 monospace - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - } - - /* - * Neither Firefox nor Chrome support hard line breaks or soft line breaks. - * (Despite https://www.w3.org/Math/draft-spec/mathml.html#chapter3_presm.lbattrs) - * So Temml has work-arounds for both hard and soft breaks. - * The work-arounds sadly do not work simultaneously. Any top-level hard - * break makes soft line breaks impossible. - * - * Hard breaks are simulated by creating a and putting each line in its own . - * - * To create soft line breaks, Temml avoids using the and tags. - * Then the top level of a element can be occupied by elements, and the browser - * will break after a if the expression extends beyond the container limit. - * - * We want the expression to render with soft line breaks after each top-level binary or - * relational operator, per TeXbook p. 173. So we gather the expression into s so that - * each ends in a binary or relational operator. - * - * Soft line breaks will not work in Chromium and Safari, only Firefox. - * - * Hopefully browsers will someday do their own linebreaking and we will be able to delete - * much of this module. - */ - - function setLineBreaks(expression, isDisplayMode, isAnnotated, color = undefined) { - if (color === undefined) { - // First, make one pass through the expression and split any color nodes. - const upperLimit = expression.length - 1; - for (let i = upperLimit; i >= 0; i--) { - const node = expression[i]; - if (node.type === "mstyle" && node.attributes.mathcolor) { - const color = node.attributes.mathcolor; - const fragment = setLineBreaks(node.children, isDisplayMode, isAnnotated, color); - if (!(fragment.type && fragment.type !== "mtable")) { - expression.splice(i, 1, ...fragment.children); - - } - } - } - } - - const tagName = color ? "mstyle" : "mrow"; - - const mtrs = []; - let mrows = []; - let block = []; - let canBeBIN = false; // The first node cannot be an infix binary operator. - for (let i = 0; i < expression.length; i++) { - const node = expression[i]; - if (node.type && node.type === "mstyle" && node.attributes.mathcolor) { - // Start a new block. (Insert a soft linebreak.) - mrows.push(new mathMLTree.MathNode(tagName, block)); - // Insert the mstyle - mrows.push(node); - block = []; - continue - } - if (node.attributes && node.attributes.linebreak && - node.attributes.linebreak === "newline") { - // A hard line break. Create a for the current block. - if (block.length > 0) { - const element = new mathMLTree.MathNode(tagName, block); - if (color) { element.setAttribute("mathcolor", color); } - mrows.push(new mathMLTree.MathNode(tagName, block)); - } - mrows.push(node); - block = []; - const mtd = new mathMLTree.MathNode("mtd", mrows); - mtrs.push(new mathMLTree.MathNode("mtr", [mtd])); - mrows = []; - continue - } - block.push(node); - if (node.type && node.type === "mo" && !isDisplayMode && !isAnnotated) { - // This may be a place for a soft line break. - if (canBeBIN && !node.attributes.form) { - // Check if the following node is a \nobreak text node, e.g. "~"" - const next = i < expression.length - 1 ? expression[i + 1] : null; - let glueIsFreeOfNobreak = true; - if ( - !( - next && - next.type === "mtext" && - next.attributes.linebreak && - next.attributes.linebreak === "nobreak" - ) - ) { - // We may need to start a new block. - // First, put any post-operator glue on same line as operator. - for (let j = i + 1; j < expression.length; j++) { - const nd = expression[j]; - if ( - nd.type && - nd.type === "mspace" && - !(nd.attributes.linebreak && nd.attributes.linebreak === "newline") - ) { - block.push(nd); - i += 1; - if ( - nd.attributes && - nd.attributes.linebreak && - nd.attributes.linebreak === "nobreak" - ) { - glueIsFreeOfNobreak = false; - } - } else { - break; - } - } - } - if (glueIsFreeOfNobreak) { - // Start a new block. (Insert a soft linebreak.) - const element = new mathMLTree.MathNode(tagName, block); - if (color) { element.setAttribute("mathcolor", color); } - mrows.push(element); - block = []; - } - canBeBIN = false; - } - const isOpenDelimiter = node.attributes.form && node.attributes.form === "prefix"; - // Any operator that follows an open delimiter is unary. - canBeBIN = !(node.attributes.separator || isOpenDelimiter); - } else { - canBeBIN = true; - } - } - if (block.length > 0) { - const element = new mathMLTree.MathNode(tagName, block); - if (color) { element.setAttribute("mathcolor", color); } - mrows.push(element); - } - if (mtrs.length > 0) { - const mtd = new mathMLTree.MathNode("mtd", mrows); - const mtr = new mathMLTree.MathNode("mtr", [mtd]); - mtrs.push(mtr); - const mtable = new mathMLTree.MathNode("mtable", mtrs); - if (!isDisplayMode) { - mtable.setAttribute("columnalign", "left"); - mtable.setAttribute("rowspacing", "0em"); - } - return mtable - } - return mathMLTree.newDocumentFragment(mrows); - } - - /** - * This file converts a parse tree into a cooresponding MathML tree. The main - * entry point is the `buildMathML` function, which takes a parse tree from the - * parser. - */ - - /** - * Takes a symbol and converts it into a MathML text node after performing - * optional replacement from symbols.js. - */ - const makeText = function(text, mode, style) { - if ( - symbols[mode][text] && - symbols[mode][text].replace && - text.charCodeAt(0) !== 0xd835 && - !( - Object.prototype.hasOwnProperty.call(ligatures, text) && - style && - ((style.fontFamily && style.fontFamily.slice(4, 6) === "tt") || - (style.font && style.font.slice(4, 6) === "tt")) - ) - ) { - text = symbols[mode][text].replace; - } - - return new mathMLTree.TextNode(text); - }; - - /** - * Wrap the given array of nodes in an node if needed, i.e., - * unless the array has length 1. Always returns a single node. - */ - const makeRow = function(body) { - if (body.length === 1) { - return body[0]; - } else { - return new mathMLTree.MathNode("mrow", body); - } - }; - - const isRel = item => { - return (item.type === "atom" && item.family === "rel") || - (item.type === "mclass" && item.mclass === "mrel") - }; - - /** - * Takes a list of nodes, builds them, and returns a list of the generated - * MathML nodes. Also do a couple chores along the way: - * (1) Suppress spacing when an author wraps an operator w/braces, as in {=}. - * (2) Suppress spacing between two adjacent relations. - */ - const buildExpression = function(expression, style, isOrdgroup) { - if (expression.length === 1) { - const group = buildGroup$1(expression[0], style); - if (isOrdgroup && group instanceof MathNode && group.type === "mo") { - // When TeX writers want to suppress spacing on an operator, - // they often put the operator by itself inside braces. - group.setAttribute("lspace", "0em"); - group.setAttribute("rspace", "0em"); - } - return [group]; - } - - const groups = []; - for (let i = 0; i < expression.length; i++) { - const group = buildGroup$1(expression[i], style); - // Suppress spacing between adjacent relations - if (i < expression.length - 1 && isRel(expression[i]) && isRel(expression[i + 1])) { - group.setAttribute("rspace", "0em"); - } - if (i > 0 && isRel(expression[i]) && isRel(expression[i - 1])) { - group.setAttribute("lspace", "0em"); - } - groups.push(group); - } - return groups; - }; - - /** - * Equivalent to buildExpression, but wraps the elements in an - * if there's more than one. Returns a single node instead of an array. - */ - const buildExpressionRow = function(expression, style, isOrdgroup) { - return makeRow(buildExpression(expression, style, isOrdgroup)); - }; - - /** - * Takes a group from the parser and calls the appropriate groupBuilders function - * on it to produce a MathML node. - */ - const buildGroup$1 = function(group, style) { - if (!group) { - return new mathMLTree.MathNode("mrow"); - } - - if (_mathmlGroupBuilders[group.type]) { - // Call the groupBuilders function - const result = _mathmlGroupBuilders[group.type](group, style); - return result; - } else { - throw new ParseError("Got group of unknown type: '" + group.type + "'"); - } - }; - - const glue = _ => { - const glueNode = new mathMLTree.MathNode("mtd", []); - glueNode.setAttribute("style", "padding: 0;width: 50%;"); - return glueNode - }; - - const taggedExpression = (expression, tag, style, leqno, preventTagLap) => { - tag = buildExpressionRow(tag[0].body, style); - tag = utils.consolidateText(tag); - tag.classes = ["tml-tag"]; - if (!preventTagLap) { - tag = new mathMLTree.MathNode("mpadded", [tag]); - tag.setAttribute("style", "width:0;"); - tag.setAttribute("width", "0"); - tag.setAttribute((leqno ? "rspace" : "lspace"), "-1width"); - } - tag = new mathMLTree.MathNode("mtd", [tag]); - if (!preventTagLap) { tag.setAttribute("style", "padding: 0; min-width:0"); } - - expression = new mathMLTree.MathNode("mtd", [expression]); - const rowArray = leqno - ? [tag, glue(), expression, glue()] - : [glue(), expression, glue(), tag]; - const mtr = new mathMLTree.MathNode("mtr", rowArray, ["tml-tageqn"]); - const table = new mathMLTree.MathNode("mtable", [mtr]); - table.setAttribute("width", "100%"); - table.setAttribute("displaystyle", "true"); - return table - }; - - /** - * Takes a full parse tree and settings and builds a MathML representation of - * it. - */ - function buildMathML(tree, texExpression, style, settings) { - // Strip off outer tag wrapper for processing below. - let tag = null; - if (tree.length === 1 && tree[0].type === "tag") { - tag = tree[0].tag; - tree = tree[0].body; - } - - const expression = buildExpression(tree, style); - - const n1 = expression.length === 0 ? null : expression[0]; - let wrapper = expression.length === 1 && tag === null && (n1 instanceof MathNode) - && !(n1.type === "mstyle" && n1.attributes.mathcolor) - ? expression[0] - : setLineBreaks(expression, settings.displayMode, settings.annotate); - - if (tag) { - wrapper = taggedExpression(wrapper, tag, style, settings.leqno, settings.preventTagLap); - } - - let semantics; - if (settings.annotate) { - // Build a TeX annotation of the source - const annotation = new mathMLTree.MathNode( - "annotation", [new mathMLTree.TextNode(texExpression)]); - annotation.setAttribute("encoding", "application/x-tex"); - semantics = new mathMLTree.MathNode("semantics", [wrapper, annotation]); - } - - const math = settings.annotate - ? new mathMLTree.MathNode("math", [semantics]) - : new mathMLTree.MathNode("math", [wrapper]); - - if (settings.xml) { - math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML"); - } - if (settings.displayMode) { - math.setAttribute("display", "block"); - } - return math; - } - - const mathmlBuilder$a = (group, style) => { - const accentNode = group.isStretchy - ? stretchy.mathMLnode(group.label) - : new mathMLTree.MathNode("mo", [makeText(group.label, group.mode)]); - - if (!group.isStretchy) { - accentNode.setAttribute("stretchy", "false"); - } - - const node = new mathMLTree.MathNode((group.label === "\\c" ? "munder" : "mover"), - [buildGroup$1(group.base, style), accentNode] - ); - - node.setAttribute("accent", "true"); - return node; - }; - - const NON_STRETCHY_ACCENT_REGEX = new RegExp( - [ - "\\acute", - "\\grave", - "\\ddot", - "\\dddot", - "\\ddddot", - "\\tilde", - "\\bar", - "\\breve", - "\\check", - "\\hat", - "\\vec", - "\\dot", - "\\mathring" - ] - .map((accent) => `\\${accent}`) - .join("|") - ); - - // Accents - defineFunction({ - type: "accent", - names: [ - "\\acute", - "\\grave", - "\\ddot", - "\\dddot", - "\\ddddot", - "\\tilde", - "\\bar", - "\\breve", - "\\check", - "\\hat", - "\\vec", - "\\dot", - "\\mathring", - "\\overparen", - "\\widecheck", - "\\widehat", - "\\wideparen", - "\\widetilde", - "\\overrightarrow", - "\\overleftarrow", - "\\Overrightarrow", - "\\overleftrightarrow", - "\\overgroup", - "\\overleftharpoon", - "\\overrightharpoon" - ], - props: { - numArgs: 1 - }, - handler: (context, args) => { - const base = normalizeArgument(args[0]); - - const isStretchy = !NON_STRETCHY_ACCENT_REGEX.test(context.funcName); - const isShifty = - !isStretchy || - context.funcName === "\\widehat" || - context.funcName === "\\widetilde" || - context.funcName === "\\widecheck"; - - return { - type: "accent", - mode: context.parser.mode, - label: context.funcName, - isStretchy: isStretchy, - isShifty: isShifty, - base: base - }; - }, - mathmlBuilder: mathmlBuilder$a - }); - - // Text-mode accents - defineFunction({ - type: "accent", - names: ["\\'", "\\`", "\\^", "\\~", "\\=", "\\c", "\\u", "\\.", '\\"', "\\r", "\\H", "\\v"], - props: { - numArgs: 1, - allowedInText: true, - allowedInMath: true, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const base = normalizeArgument(args[0]); - const mode = context.parser.mode; - - if (mode === "math" && context.parser.settings.strict) { - // LaTeX only writes a warning. It doesn't stop. We'll issue the same warning. - // eslint-disable-next-line no-console - console.log(`Temml parse error: Command ${context.funcName} is invalid in math mode.`); - } - - return { - type: "accent", - mode: mode, - label: context.funcName, - isStretchy: false, - isShifty: true, - base: base - }; - }, - mathmlBuilder: mathmlBuilder$a - }); - - defineFunction({ - type: "accentUnder", - names: [ - "\\underleftarrow", - "\\underrightarrow", - "\\underleftrightarrow", - "\\undergroup", - "\\underparen", - "\\utilde" - ], - props: { - numArgs: 1 - }, - handler: ({ parser, funcName }, args) => { - const base = args[0]; - return { - type: "accentUnder", - mode: parser.mode, - label: funcName, - base: base - }; - }, - mathmlBuilder: (group, style) => { - const accentNode = stretchy.mathMLnode(group.label); - const node = new mathMLTree.MathNode("munder", [ - buildGroup$1(group.base, style), - accentNode - ]); - node.setAttribute("accentunder", "true"); - return node; - } - }); - - /** - * This file does conversion between units. In particular, it provides - * calculateSize to convert other units into CSS units. - */ - - const ptPerUnit = { - // Convert to CSS (Postscipt) points, not TeX points - // https://en.wikibooks.org/wiki/LaTeX/Lengths and - // https://tex.stackexchange.com/a/8263 - pt: 800 / 803, // convert TeX point to CSS (Postscript) point - pc: (12 * 800) / 803, // pica - dd: ((1238 / 1157) * 800) / 803, // didot - cc: ((14856 / 1157) * 800) / 803, // cicero (12 didot) - nd: ((685 / 642) * 800) / 803, // new didot - nc: ((1370 / 107) * 800) / 803, // new cicero (12 new didot) - sp: ((1 / 65536) * 800) / 803, // scaled point (TeX's internal smallest unit) - mm: (25.4 / 72), - cm: (2.54 / 72), - in: (1 / 72), - px: (96 / 72) - }; - - /** - * Determine whether the specified unit (either a string defining the unit - * or a "size" parse node containing a unit field) is valid. - */ - const validUnits = [ - "em", - "ex", - "mu", - "pt", - "mm", - "cm", - "in", - "px", - "bp", - "pc", - "dd", - "cc", - "nd", - "nc", - "sp" - ]; - - const validUnit = function(unit) { - if (typeof unit !== "string") { - unit = unit.unit; - } - return validUnits.indexOf(unit) > -1 - }; - - const emScale = styleLevel => { - const scriptLevel = Math.max(styleLevel - 1, 0); - return [1, 0.7, 0.5][scriptLevel] - }; - - /* - * Convert a "size" parse node (with numeric "number" and string "unit" fields, - * as parsed by functions.js argType "size") into a CSS value. - */ - const calculateSize = function(sizeValue, style) { - let number = sizeValue.number; - if (style.maxSize[0] < 0 && number > 0) { - return { number: 0, unit: "em" } - } - const unit = sizeValue.unit; - switch (unit) { - case "mm": - case "cm": - case "in": - case "px": { - const numInCssPts = number * ptPerUnit[unit]; - if (numInCssPts > style.maxSize[1]) { - return { number: style.maxSize[1], unit: "pt" } - } - return { number, unit }; // absolute CSS units. - } - case "em": - case "ex": { - // In TeX, em and ex do not change size in \scriptstyle. - if (unit === "ex") { number *= 0.431; } - number = Math.min(number / emScale(style.level), style.maxSize[0]); - return { number: utils.round(number), unit: "em" }; - } - case "bp": { - if (number > style.maxSize[1]) { number = style.maxSize[1]; } - return { number, unit: "pt" }; // TeX bp is a CSS pt. (1/72 inch). - } - case "pt": - case "pc": - case "dd": - case "cc": - case "nd": - case "nc": - case "sp": { - number = Math.min(number * ptPerUnit[unit], style.maxSize[1]); - return { number: utils.round(number), unit: "pt" } - } - case "mu": { - number = Math.min(number / 18, style.maxSize[0]); - return { number: utils.round(number), unit: "em" } - } - default: - throw new ParseError("Invalid unit: '" + unit + "'") - } - }; - - // Helper functions - const paddedNode = (group, width, lspace = "0.3em") => { - const node = new mathMLTree.MathNode("mpadded", group ? [group] : []); - node.setAttribute("width", width); - node.setAttribute("lspace", lspace); - return node; - }; - - const labelSize = (size, scriptLevel) => (size / emScale(scriptLevel)).toFixed(4) + "em"; - - const munderoverNode = (name, body, below, style) => { - const arrowNode = stretchy.mathMLnode(name); - // Is this the short part of a mhchem equilibrium arrow? - const isEq = name.slice(1, 3) === "eq"; - const minWidth = name.charAt(1) === "x" - ? "1.75" // mathtools extensible arrows are 1.75em long - : name.slice(2, 4) === "cd" - ? "3.0" // cd package arrows - : isEq - ? "1.0" // The shorter harpoon of a mhchem equilibrium arrow - : "2.0"; // other mhchem arrows - arrowNode.setAttribute("minsize", String(minWidth) + "em"); - arrowNode.setAttribute("lspace", "0"); - arrowNode.setAttribute("rspace", (isEq ? "0.5em" : "0")); - - // upper and lower labels are set to scriptlevel by MathML - // So we have to adjust our dimensions accordingly. - const labelStyle = style.withLevel(style.level < 2 ? 2 : 3); - const emptyLabelWidth = labelSize(minWidth, labelStyle.level); - const lspace = labelSize((isEq ? 0 : 0.3), labelStyle.level); - let widthAdder = labelSize((isEq ? -0.4 : 0.6), labelStyle.level); - if (widthAdder.charAt(0) !== "-") { widthAdder = "+" + widthAdder; } - - const upperNode = (body && body.body && - // \hphantom visible content - (body.body.body || body.body.length > 0)) - ? paddedNode(buildGroup$1(body, labelStyle), widthAdder, lspace) - // Since Firefox does not recognize minsize set on the arrow, - // create an upper node w/correct width. - : paddedNode(null, emptyLabelWidth, "0"); - const lowerNode = (below && below.body && - (below.body.body || below.body.length > 0)) - ? paddedNode(buildGroup$1(below, labelStyle), widthAdder, lspace) - : paddedNode(null, emptyLabelWidth, "0"); - const node = new mathMLTree.MathNode("munderover", [arrowNode, lowerNode, upperNode]); - return node - }; - - // Stretchy arrows with an optional argument - defineFunction({ - type: "xArrow", - names: [ - "\\xleftarrow", - "\\xrightarrow", - "\\xLeftarrow", - "\\xRightarrow", - "\\xleftrightarrow", - "\\xLeftrightarrow", - "\\xhookleftarrow", - "\\xhookrightarrow", - "\\xmapsto", - "\\xrightharpoondown", - "\\xrightharpoonup", - "\\xleftharpoondown", - "\\xleftharpoonup", - "\\xlongequal", - "\\xtwoheadrightarrow", - "\\xtwoheadleftarrow", - // The next 7 functions are here only to support mhchem - "\\yields", - "\\yieldsLeft", - "\\mesomerism", - "\\longrightharpoonup", - "\\longleftharpoondown", - // The next 3 functions are here only to support the {CD} environment. - "\\\\cdrightarrow", - "\\\\cdleftarrow", - "\\\\cdlongequal" - ], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser, funcName }, args, optArgs) { - return { - type: "xArrow", - mode: parser.mode, - name: funcName, - body: args[0], - below: optArgs[0] - }; - }, - mathmlBuilder(group, style) { - // Build the arrow and its labels. - const node = munderoverNode(group.name, group.body, group.below, style); - // Create operator spacing for a relation. - const wrapper = new mathMLTree.MathNode("mpadded", [node]); - wrapper.setAttribute("lspace", "0.2778em"); - wrapper.setAttribute("width", "+0.5556em"); - return wrapper - } - }); - - const arrowComponent = { - "\\xtofrom": ["\\xrightarrow", "\\xleftarrow"], - "\\xleftrightharpoons": ["\\xleftharpoonup", "\\xrightharpoondown"], - "\\xrightleftharpoons": ["\\xrightharpoonup", "\\xleftharpoondown"], - "\\yieldsLeftRight": ["\\yields", "\\yieldsLeft"], - // The next three all get the same harpoon glyphs. Only the lengths and paddings differ. - "\\equilibrium": ["\\longrightharpoonup", "\\longleftharpoondown"], - "\\equilibriumRight": ["\\longrightharpoonup", "\\eqleftharpoondown"], - "\\equilibriumLeft": ["\\eqrightharpoonup", "\\longleftharpoondown"] - }; - - // Browsers are not good at stretching a glyph that contains a pair of stacked arrows such as ⇄. - // So we stack a pair of single arrows. - defineFunction({ - type: "stackedArrow", - names: [ - "\\xtofrom", // expfeil - "\\xleftrightharpoons", // mathtools - "\\xrightleftharpoons", // mathtools - "\\yieldsLeftRight", // mhchem - "\\equilibrium", // mhchem - "\\equilibriumRight", - "\\equilibriumLeft" - ], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser, funcName }, args, optArgs) { - const lowerArrowBody = args[0] - ? { - type: "hphantom", - mode: parser.mode, - body: args[0] - } - : null; - const upperArrowBelow = optArgs[0] - ? { - type: "hphantom", - mode: parser.mode, - body: optArgs[0] - } - : null; - return { - type: "stackedArrow", - mode: parser.mode, - name: funcName, - body: args[0], - upperArrowBelow, - lowerArrowBody, - below: optArgs[0] - }; - }, - mathmlBuilder(group, style) { - const topLabel = arrowComponent[group.name][0]; - const botLabel = arrowComponent[group.name][1]; - const topArrow = munderoverNode(topLabel, group.body, group.upperArrowBelow, style); - const botArrow = munderoverNode(botLabel, group.lowerArrowBody, group.below, style); - let wrapper; - - const raiseNode = new mathMLTree.MathNode("mpadded", [topArrow]); - raiseNode.setAttribute("voffset", "0.3em"); - raiseNode.setAttribute("height", "+0.3em"); - raiseNode.setAttribute("depth", "-0.3em"); - // One of the arrows is given ~zero width. so the other has the same horzontal alignment. - if (group.name === "\\equilibriumLeft") { - const botNode = new mathMLTree.MathNode("mpadded", [botArrow]); - botNode.setAttribute("width", "0.5em"); - wrapper = new mathMLTree.MathNode("mpadded", [botNode, raiseNode]); - } else { - raiseNode.setAttribute("width", (group.name === "\\equilibriumRight" ? "0.5em" : "0")); - wrapper = new mathMLTree.MathNode("mpadded", [raiseNode, botArrow]); - } - - wrapper.setAttribute("voffset", "-0.18em"); - wrapper.setAttribute("width", "+0.5556em"); - wrapper.setAttribute("height", "-0.18em"); - wrapper.setAttribute("depth", "+0.18em"); - wrapper.setAttribute("lspace", "0.2778em"); - return wrapper - } - }); - - defineFunction({ - type: "cancelto", - names: ["\\cancelto"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "cancelto", - mode: parser.mode, - value: args[0], - expression: args[1] - }; - }, - mathmlBuilder(group, style) { - const value = new mathMLTree.MathNode( - "mpadded", - [buildGroup$1(group.value, style)] - ); - value.setAttribute("depth", `-0.1em`); - value.setAttribute("height", `+0.1em`); - value.setAttribute("voffset", `0.1em`); - - const expression = new mathMLTree.MathNode( - "menclose", - [buildGroup$1(group.expression, style)] - ); - expression.setAttribute("notation", `updiagonalarrow`); - - return new mathMLTree.MathNode("msup", [expression, value]) - } - }); - - /** - * Asserts that the node is of the given type and returns it with stricter - * typing. Throws if the node's type does not match. - */ - function assertNodeType(node, type) { - if (!node || node.type !== type) { - throw new Error( - `Expected node of type ${type}, but got ` + - (node ? `node of type ${node.type}` : String(node)) - ); - } - return node; - } - - /** - * Returns the node more strictly typed iff it is of the given type. Otherwise, - * returns null. - */ - function assertSymbolNodeType(node) { - const typedNode = checkSymbolNodeType(node); - if (!typedNode) { - throw new Error( - `Expected node of symbol group type, but got ` + - (node ? `node of type ${node.type}` : String(node)) - ); - } - return typedNode; - } - - /** - * Returns the node more strictly typed iff it is of the given type. Otherwise, - * returns null. - */ - function checkSymbolNodeType(node) { - if (node && (node.type === "atom" || - Object.prototype.hasOwnProperty.call(NON_ATOMS, node.type))) { - return node; - } - return null; - } - - const cdArrowFunctionName = { - ">": "\\\\cdrightarrow", - "<": "\\\\cdleftarrow", - "=": "\\\\cdlongequal", - A: "\\uparrow", - V: "\\downarrow", - "|": "\\Vert", - ".": "no arrow" - }; - - const newCell = () => { - // Create an empty cell, to be filled below with parse nodes. - return { type: "styling", body: [], mode: "math", scriptLevel: "display" }; - }; - - const isStartOfArrow = (node) => { - return node.type === "textord" && node.text === "@"; - }; - - const isLabelEnd = (node, endChar) => { - return (node.type === "mathord" || node.type === "atom") && node.text === endChar; - }; - - function cdArrow(arrowChar, labels, parser) { - // Return a parse tree of an arrow and its labels. - // This acts in a way similar to a macro expansion. - const funcName = cdArrowFunctionName[arrowChar]; - switch (funcName) { - case "\\\\cdrightarrow": - case "\\\\cdleftarrow": - return parser.callFunction(funcName, [labels[0]], [labels[1]]); - case "\\uparrow": - case "\\downarrow": { - const leftLabel = parser.callFunction("\\\\cdleft", [labels[0]], []); - const bareArrow = { - type: "atom", - text: funcName, - mode: "math", - family: "rel" - }; - const sizedArrow = parser.callFunction("\\Big", [bareArrow], []); - const rightLabel = parser.callFunction("\\\\cdright", [labels[1]], []); - const arrowGroup = { - type: "ordgroup", - mode: "math", - body: [leftLabel, sizedArrow, rightLabel] - }; - return parser.callFunction("\\\\cdparent", [arrowGroup], []); - } - case "\\\\cdlongequal": - return parser.callFunction("\\\\cdlongequal", [], []); - case "\\Vert": { - const arrow = { type: "textord", text: "\\Vert", mode: "math" }; - return parser.callFunction("\\Big", [arrow], []); - } - default: - return { type: "textord", text: " ", mode: "math" }; - } - } - - function parseCD(parser) { - // Get the array's parse nodes with \\ temporarily mapped to \cr. - const parsedRows = []; - parser.gullet.beginGroup(); - parser.gullet.macros.set("\\cr", "\\\\\\relax"); - parser.gullet.beginGroup(); - while (true) { // eslint-disable-line no-constant-condition - // Get the parse nodes for the next row. - parsedRows.push(parser.parseExpression(false, "\\\\")); - parser.gullet.endGroup(); - parser.gullet.beginGroup(); - const next = parser.fetch().text; - if (next === "&" || next === "\\\\") { - parser.consume(); - } else if (next === "\\end") { - if (parsedRows[parsedRows.length - 1].length === 0) { - parsedRows.pop(); // final row ended in \\ - } - break; - } else { - throw new ParseError("Expected \\\\ or \\cr or \\end", parser.nextToken); - } - } - - let row = []; - const body = [row]; - - // Loop thru the parse nodes. Collect them into cells and arrows. - for (let i = 0; i < parsedRows.length; i++) { - // Start a new row. - const rowNodes = parsedRows[i]; - // Create the first cell. - let cell = newCell(); - - for (let j = 0; j < rowNodes.length; j++) { - if (!isStartOfArrow(rowNodes[j])) { - // If a parseNode is not an arrow, it goes into a cell. - cell.body.push(rowNodes[j]); - } else { - // Parse node j is an "@", the start of an arrow. - // Before starting on the arrow, push the cell into `row`. - row.push(cell); - - // Now collect parseNodes into an arrow. - // The character after "@" defines the arrow type. - j += 1; - const arrowChar = assertSymbolNodeType(rowNodes[j]).text; - - // Create two empty label nodes. We may or may not use them. - const labels = new Array(2); - labels[0] = { type: "ordgroup", mode: "math", body: [] }; - labels[1] = { type: "ordgroup", mode: "math", body: [] }; - - // Process the arrow. - if ("=|.".indexOf(arrowChar) > -1) ; else if ("<>AV".indexOf(arrowChar) > -1) { - // Four arrows, `@>>>`, `@<<<`, `@AAA`, and `@VVV`, each take - // two optional labels. E.g. the right-point arrow syntax is - // really: @>{optional label}>{optional label}> - // Collect parseNodes into labels. - for (let labelNum = 0; labelNum < 2; labelNum++) { - let inLabel = true; - for (let k = j + 1; k < rowNodes.length; k++) { - if (isLabelEnd(rowNodes[k], arrowChar)) { - inLabel = false; - j = k; - break; - } - if (isStartOfArrow(rowNodes[k])) { - throw new ParseError( - "Missing a " + arrowChar + " character to complete a CD arrow.", - rowNodes[k] - ); - } - - labels[labelNum].body.push(rowNodes[k]); - } - if (inLabel) { - // isLabelEnd never returned a true. - throw new ParseError( - "Missing a " + arrowChar + " character to complete a CD arrow.", - rowNodes[j] - ); - } - } - } else { - throw new ParseError(`Expected one of "<>AV=|." after @.`); - } - - // Now join the arrow to its labels. - const arrow = cdArrow(arrowChar, labels, parser); - - // Wrap the arrow in a styling node - row.push(arrow); - // In CD's syntax, cells are implicit. That is, everything that - // is not an arrow gets collected into a cell. So create an empty - // cell now. It will collect upcoming parseNodes. - cell = newCell(); - } - } - if (i % 2 === 0) { - // Even-numbered rows consist of: cell, arrow, cell, arrow, ... cell - // The last cell is not yet pushed into `row`, so: - row.push(cell); - } else { - // Odd-numbered rows consist of: vert arrow, empty cell, ... vert arrow - // Remove the empty cell that was placed at the beginning of `row`. - row.shift(); - } - row = []; - body.push(row); - } - - // End row group - parser.gullet.endGroup(); - // End array group defining \\ - parser.gullet.endGroup(); - - // define column separation. - const cols = new Array(body[0].length).fill({ - type: "align", - align: "c" - }); - - return { - type: "array", - mode: "math", - body, - arraystretch: 1, - addJot: true, - rowGaps: [null], - cols, - colSeparationType: "CD", - hLinesBeforeRow: new Array(body.length + 1).fill([]) - }; - } - - // The functions below are not available for general use. - // They are here only for internal use by the {CD} environment in placing labels - // next to vertical arrows. - - // We don't need any such functions for horizontal arrows because we can reuse - // the functionality that already exists for extensible arrows. - - defineFunction({ - type: "cdlabel", - names: ["\\\\cdleft", "\\\\cdright"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - return { - type: "cdlabel", - mode: parser.mode, - side: funcName.slice(4), - label: args[0] - }; - }, - mathmlBuilder(group, style) { - let label = new mathMLTree.MathNode("mrow", [buildGroup$1(group.label, style)]); - label = new mathMLTree.MathNode("mpadded", [label]); - label.setAttribute("width", "0"); - if (group.side === "left") { - label.setAttribute("lspace", "-1width"); - } - // We have to guess at vertical alignment. We know the arrow is 1.8em tall, - // But we don't know the height or depth of the label. - label.setAttribute("voffset", "0.7em"); - label = new mathMLTree.MathNode("mstyle", [label]); - label.setAttribute("displaystyle", "false"); - label.setAttribute("scriptlevel", "1"); - return label; - } - }); - - defineFunction({ - type: "cdlabelparent", - names: ["\\\\cdparent"], - props: { - numArgs: 1 - }, - handler({ parser }, args) { - return { - type: "cdlabelparent", - mode: parser.mode, - fragment: args[0] - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow", [buildGroup$1(group.fragment, style)]); - } - }); - - // \@char is an internal function that takes a grouped decimal argument like - // {123} and converts into symbol with code 123. It is used by the *macro* - // \char defined in macros.js. - defineFunction({ - type: "textord", - names: ["\\@char"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser, token }, args) { - const arg = assertNodeType(args[0], "ordgroup"); - const group = arg.body; - let number = ""; - for (let i = 0; i < group.length; i++) { - const node = assertNodeType(group[i], "textord"); - number += node.text; - } - const code = parseInt(number); - if (isNaN(code)) { - throw new ParseError(`\\@char has non-numeric argument ${number}`, token) - } - return { - type: "textord", - mode: parser.mode, - text: String.fromCodePoint(code) - } - } - }); - - // Helpers - const htmlRegEx = /^(#[a-f0-9]{3}|#?[a-f0-9]{6})$/i; - const htmlOrNameRegEx = /^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i; - const RGBregEx = /^ *\d{1,3} *(?:, *\d{1,3} *){2}$/; - const rgbRegEx = /^ *[10](?:\.\d*)? *(?:, *[10](?:\.\d*)? *){2}$/; - const xcolorHtmlRegEx = /^[a-f0-9]{6}$/i; - const toHex = num => { - let str = num.toString(16); - if (str.length === 1) { str = "0" + str; } - return str - }; - - // Colors from Tables 4.1 and 4.2 of the xcolor package. - // Table 4.1 (lower case) RGB values are taken from chroma and xcolor.dtx. - // Table 4.2 (Capitalizzed) values were sampled, because Chroma contains a unreliable - // conversion from cmyk to RGB. See https://tex.stackexchange.com/a/537274. - const xcolors = JSON.parse(`{ - "Apricot": "#ffb484", - "Aquamarine": "#08b4bc", - "Bittersweet": "#c84c14", - "blue": "#0000FF", - "Blue": "#303494", - "BlueGreen": "#08b4bc", - "BlueViolet": "#503c94", - "BrickRed": "#b8341c", - "brown": "#BF8040", - "Brown": "#802404", - "BurntOrange": "#f8941c", - "CadetBlue": "#78749c", - "CarnationPink": "#f884b4", - "Cerulean": "#08a4e4", - "CornflowerBlue": "#40ace4", - "cyan": "#00FFFF", - "Cyan": "#08acec", - "Dandelion": "#ffbc44", - "darkgray": "#404040", - "DarkOrchid": "#a8548c", - "Emerald": "#08ac9c", - "ForestGreen": "#089c54", - "Fuchsia": "#90348c", - "Goldenrod": "#ffdc44", - "gray": "#808080", - "Gray": "#98949c", - "green": "#00FF00", - "Green": "#08a44c", - "GreenYellow": "#e0e474", - "JungleGreen": "#08ac9c", - "Lavender": "#f89cc4", - "lightgray": "#c0c0c0", - "lime": "#BFFF00", - "LimeGreen": "#90c43c", - "magenta": "#FF00FF", - "Magenta": "#f0048c", - "Mahogany": "#b0341c", - "Maroon": "#b03434", - "Melon": "#f89c7c", - "MidnightBlue": "#086494", - "Mulberry": "#b03c94", - "NavyBlue": "#086cbc", - "olive": "#7F7F00", - "OliveGreen": "#407c34", - "orange": "#FF8000", - "Orange": "#f8843c", - "OrangeRed": "#f0145c", - "Orchid": "#b074ac", - "Peach": "#f8945c", - "Periwinkle": "#8074bc", - "PineGreen": "#088c74", - "pink": "#ff7f7f", - "Plum": "#98248c", - "ProcessBlue": "#08b4ec", - "purple": "#BF0040", - "Purple": "#a0449c", - "RawSienna": "#983c04", - "red": "#ff0000", - "Red": "#f01c24", - "RedOrange": "#f86434", - "RedViolet": "#a0246c", - "Rhodamine": "#f0549c", - "Royallue": "#0874bc", - "RoyalPurple": "#683c9c", - "RubineRed": "#f0047c", - "Salmon": "#f8948c", - "SeaGreen": "#30bc9c", - "Sepia": "#701404", - "SkyBlue": "#48c4dc", - "SpringGreen": "#c8dc64", - "Tan": "#e09c74", - "teal": "#007F7F", - "TealBlue": "#08acb4", - "Thistle": "#d884b4", - "Turquoise": "#08b4cc", - "violet": "#800080", - "Violet": "#60449c", - "VioletRed": "#f054a4", - "WildStrawberry": "#f0246c", - "yellow": "#FFFF00", - "Yellow": "#fff404", - "YellowGreen": "#98cc6c", - "YellowOrange": "#ffa41c" -}`); - - const colorFromSpec = (model, spec) => { - let color = ""; - if (model === "HTML") { - if (!htmlRegEx.test(spec)) { - throw new ParseError("Invalid HTML input.") - } - color = spec; - } else if (model === "RGB") { - if (!RGBregEx.test(spec)) { - throw new ParseError("Invalid RGB input.") - } - spec.split(",").map(e => { color += toHex(Number(e.trim())); }); - } else { - if (!rgbRegEx.test(spec)) { - throw new ParseError("Invalid rbg input.") - } - spec.split(",").map(e => { - const num = Number(e.trim()); - if (num > 1) { throw new ParseError("Color rgb input must be < 1.") } - color += toHex((num * 255)); - }); - } - if (color.charAt(0) !== "#") { color = "#" + color; } - return color - }; - - const validateColor = (color, macros, token) => { - const macroName = `\\\\color@${color}`; // from \defineColor. - const match = htmlOrNameRegEx.exec(color); - if (!match) { throw new ParseError("Invalid color: '" + color + "'", token) } - // We allow a 6-digit HTML color spec without a leading "#". - // This follows the xcolor package's HTML color model. - // Predefined color names are all missed by this RegEx pattern. - if (xcolorHtmlRegEx.test(color)) { - return "#" + color - } else if (color.charAt(0) === "#") { - return color - } else if (macros.has(macroName)) { - color = macros.get(macroName).tokens[0].text; - } else if (xcolors[color]) { - color = xcolors[color]; - } - return color - }; - - const mathmlBuilder$9 = (group, style) => { - const inner = buildExpression(group.body, style.withColor(group.color)); - // Wrap with an element. - const node = wrapWithMstyle(inner); - node.setAttribute("mathcolor", group.color); - // Wrap w/. We get better operator spacing that way. - return new mathMLTree.MathNode("mrow", [node]) - }; - - defineFunction({ - type: "color", - names: ["\\textcolor"], - props: { - numArgs: 2, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "original"] - }, - handler({ parser, token }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let color = ""; - if (model) { - const spec = assertNodeType(args[0], "raw").string; - color = colorFromSpec(model, spec); - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros, token); - } - const body = args[1]; - return { - type: "color", - mode: parser.mode, - color, - body: ordargument(body) - } - }, - mathmlBuilder: mathmlBuilder$9 - }); - - defineFunction({ - type: "color", - names: ["\\color"], - props: { - numArgs: 1, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw"] - }, - handler({ parser, token }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let color = ""; - if (model) { - const spec = assertNodeType(args[0], "raw").string; - color = colorFromSpec(model, spec); - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros, token); - } - - // Set macro \current@color in current namespace to store the current - // color, mimicking the behavior of color.sty. - // This is currently used just to correctly color a \right - // that follows a \color command. - parser.gullet.macros.set("\\current@color", color); - - // Parse out the implicit body that should be colored. - // Since \color nodes should not be nested, break on \color. - const body = parser.parseExpression(true, "\\color"); - - return { - type: "color", - mode: parser.mode, - color, - body - } - }, - mathmlBuilder: mathmlBuilder$9 - }); - - defineFunction({ - type: "color", - names: ["\\definecolor"], - props: { - numArgs: 3, - allowedInText: true, - argTypes: ["raw", "raw", "raw"] - }, - handler({ parser, funcName, token }, args) { - const name = assertNodeType(args[0], "raw").string; - if (!/^[A-Za-z]+$/.test(name)) { - throw new ParseError("Color name must be latin letters.", token) - } - const model = assertNodeType(args[1], "raw").string; - if (!["HTML", "RGB", "rgb"].includes(model)) { - throw new ParseError("Color model must be HTML, RGB, or rgb.", token) - } - const spec = assertNodeType(args[2], "raw").string; - const color = colorFromSpec(model, spec); - parser.gullet.macros.set(`\\\\color@${name}`, { tokens: [{ text: color }], numArgs: 0 }); - return { type: "internal", mode: parser.mode } - } - // No mathmlBuilder. The point of \definecolor is to set a macro. - }); - - // Row breaks within tabular environments, and line breaks at top level - - // \DeclareRobustCommand\\{...\@xnewline} - defineFunction({ - type: "cr", - names: ["\\\\"], - props: { - numArgs: 0, - numOptionalArgs: 1, - argTypes: ["size"], - allowedInText: true - }, - - handler({ parser }, args, optArgs) { - const size = optArgs[0]; - const newLine = !parser.settings.displayMode; - return { - type: "cr", - mode: parser.mode, - newLine, - size: size && assertNodeType(size, "size").value - } - }, - - // The following builder is called only at the top level, - // not within tabular/array environments. - - mathmlBuilder(group, style) { - // MathML 3.0 calls for newline to occur in an or an . - // Ref: https://www.w3.org/TR/MathML3/chapter3.html#presm.linebreaking - const node = new mathMLTree.MathNode("mo"); - if (group.newLine) { - node.setAttribute("linebreak", "newline"); - if (group.size) { - const size = calculateSize(group.size, style); - node.setAttribute("height", size.number + size.unit); - } - } - return node - } - }); - - const checkControlSequence = (tok) => { - const name = tok.text; - if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { - throw new ParseError("Expected a control sequence", tok); - } - return name; - }; - - const getRHS = (parser) => { - let tok = parser.gullet.popToken(); - if (tok.text === "=") { - // consume optional equals - tok = parser.gullet.popToken(); - if (tok.text === " ") { - // consume one optional space - tok = parser.gullet.popToken(); - } - } - return tok; - }; - - const letCommand = (parser, name, tok) => { - let macro = parser.gullet.macros.get(tok.text); - if (macro == null) { - // don't expand it later even if a macro with the same name is defined - // e.g., \let\foo=\frac \def\frac{\relax} \frac12 - tok.noexpand = true; - macro = { - tokens: [tok], - numArgs: 0, - // reproduce the same behavior in expansion - unexpandable: !parser.gullet.isExpandable(tok.text) - }; - } - parser.gullet.macros.set(name, macro); - }; - - // Basic support for macro definitions: \def - // -> - // -> - defineFunction({ - type: "internal", - names: ["\\def", "\\edef"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - let tok = parser.gullet.popToken(); - const name = tok.text; - if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { - throw new ParseError("Expected a control sequence", tok); - } - - let numArgs = 0; - let insert; - const delimiters = [[]]; - // contains no braces - while (parser.gullet.future().text !== "{") { - tok = parser.gullet.popToken(); - if (tok.text === "#") { - // If the very last character of the is #, so that - // this # is immediately followed by {, TeX will behave as if the { - // had been inserted at the right end of both the parameter text - // and the replacement text. - if (parser.gullet.future().text === "{") { - insert = parser.gullet.future(); - delimiters[numArgs].push("{"); - break; - } - - // A parameter, the first appearance of # must be followed by 1, - // the next by 2, and so on; up to nine #’s are allowed - tok = parser.gullet.popToken(); - if (!/^[1-9]$/.test(tok.text)) { - throw new ParseError(`Invalid argument number "${tok.text}"`); - } - if (parseInt(tok.text) !== numArgs + 1) { - throw new ParseError(`Argument number "${tok.text}" out of order`); - } - numArgs++; - delimiters.push([]); - } else if (tok.text === "EOF") { - throw new ParseError("Expected a macro definition"); - } else { - delimiters[numArgs].push(tok.text); - } - } - // replacement text, enclosed in '{' and '}' and properly nested - let { tokens } = parser.gullet.consumeArg(); - if (insert) { - tokens.unshift(insert); - } - - if (funcName === "\\edef") { - tokens = parser.gullet.expandTokens(tokens); - tokens.reverse(); // to fit in with stack order - } - // Final arg is the expansion of the macro - parser.gullet.macros.set(name, { tokens, numArgs, delimiters } - ); - return { type: "internal", mode: parser.mode }; - } - }); - - // -> - // -> \futurelet - // | \let - // -> |= - defineFunction({ - type: "internal", - names: ["\\let"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - const name = checkControlSequence(parser.gullet.popToken()); - parser.gullet.consumeSpaces(); - const tok = getRHS(parser); - letCommand(parser, name, tok); - return { type: "internal", mode: parser.mode }; - } - }); - - // ref: https://www.tug.org/TUGboat/tb09-3/tb22bechtolsheim.pdf - defineFunction({ - type: "internal", - names: ["\\futurelet"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - const name = checkControlSequence(parser.gullet.popToken()); - const middle = parser.gullet.popToken(); - const tok = parser.gullet.popToken(); - letCommand(parser, name, tok); - parser.gullet.pushToken(tok); - parser.gullet.pushToken(middle); - return { type: "internal", mode: parser.mode }; - } - }); - - defineFunction({ - type: "internal", - names: ["\\newcommand", "\\renewcommand", "\\providecommand"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - let name = ""; - const tok = parser.gullet.popToken(); - if (tok.text === "{") { - name = checkControlSequence(parser.gullet.popToken()); - parser.gullet.popToken(); - } else { - name = checkControlSequence(tok); - } - - const exists = parser.gullet.isDefined(name); - if (exists && funcName === "\\newcommand") { - throw new ParseError( - `\\newcommand{${name}} attempting to redefine ${name}; use \\renewcommand` - ); - } - if (!exists && funcName === "\\renewcommand") { - throw new ParseError( - `\\renewcommand{${name}} when command ${name} does not yet exist; use \\newcommand` - ); - } - - let numArgs = 0; - if (parser.gullet.future().text === "[") { - let tok = parser.gullet.popToken(); - tok = parser.gullet.popToken(); - if (!/^[0-9]$/.test(tok.text)) { - throw new ParseError(`Invalid number of arguments: "${tok.text}"`); - } - numArgs = parseInt(tok.text); - tok = parser.gullet.popToken(); - if (tok.text !== "]") { - throw new ParseError(`Invalid argument "${tok.text}"`); - } - } - - // replacement text, enclosed in '{' and '}' and properly nested - const { tokens } = parser.gullet.consumeArg(); - - parser.gullet.macros.set(name, { tokens, numArgs }); - - return { type: "internal", mode: parser.mode }; - - } - }); - - // Extra data needed for the delimiter handler down below - const delimiterSizes = { - "\\bigl": { mclass: "mopen", size: 1 }, - "\\Bigl": { mclass: "mopen", size: 2 }, - "\\biggl": { mclass: "mopen", size: 3 }, - "\\Biggl": { mclass: "mopen", size: 4 }, - "\\bigr": { mclass: "mclose", size: 1 }, - "\\Bigr": { mclass: "mclose", size: 2 }, - "\\biggr": { mclass: "mclose", size: 3 }, - "\\Biggr": { mclass: "mclose", size: 4 }, - "\\bigm": { mclass: "mrel", size: 1 }, - "\\Bigm": { mclass: "mrel", size: 2 }, - "\\biggm": { mclass: "mrel", size: 3 }, - "\\Biggm": { mclass: "mrel", size: 4 }, - "\\big": { mclass: "mord", size: 1 }, - "\\Big": { mclass: "mord", size: 2 }, - "\\bigg": { mclass: "mord", size: 3 }, - "\\Bigg": { mclass: "mord", size: 4 } - }; - - const delimiters = [ - "(", - "\\lparen", - ")", - "\\rparen", - "[", - "\\lbrack", - "]", - "\\rbrack", - "\\{", - "\\lbrace", - "\\}", - "\\rbrace", - "\\lfloor", - "\\rfloor", - "\u230a", - "\u230b", - "\\lceil", - "\\rceil", - "\u2308", - "\u2309", - "<", - ">", - "\\langle", - "\u27e8", - "\\rangle", - "\u27e9", - "\\lt", - "\\gt", - "\\lvert", - "\\rvert", - "\\lVert", - "\\rVert", - "\\lgroup", - "\\rgroup", - "\u27ee", - "\u27ef", - "\\lmoustache", - "\\rmoustache", - "\u23b0", - "\u23b1", - "\\llbracket", - "\\rrbracket", - "\u27e6", - "\u27e6", - "\\lBrace", - "\\rBrace", - "\u2983", - "\u2984", - "/", - "\\backslash", - "|", - "\\vert", - "\\|", - "\\Vert", - "\\uparrow", - "\\Uparrow", - "\\downarrow", - "\\Downarrow", - "\\updownarrow", - "\\Updownarrow", - "." - ]; - - // Metrics of the different sizes. Found by looking at TeX's output of - // $\bigl| // \Bigl| \biggl| \Biggl| \showlists$ - // Used to create stacked delimiters of appropriate sizes in makeSizedDelim. - const sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0]; - - // Delimiter functions - function checkDelimiter(delim, context) { - if (delim.type === "ordgroup" && delim.body.length === 1 && delim.body[0].text === "\u2044") { - // Recover "/" from the zero spacing group. (See macros.js) - delim = { type: "textord", text: "/", mode: "math" }; - } - const symDelim = checkSymbolNodeType(delim); - if (symDelim && utils.contains(delimiters, symDelim.text)) { - // If a character is not in the MathML operator dictionary, it will not stretch. - // Replace such characters w/characters that will stretch. - if (utils.contains(["<", "\\lt"], symDelim.text)) { symDelim.text = "⟨"; } - if (utils.contains([">", "\\gt"], symDelim.text)) { symDelim.text = "⟩"; } - if (symDelim.text === "/") { symDelim.text = "\u2215"; } - if (symDelim.text === "\\backslash") { symDelim.text = "\u2216"; } - return symDelim; - } else if (symDelim) { - throw new ParseError(`Invalid delimiter '${symDelim.text}' after '${context.funcName}'`, delim); - } else { - throw new ParseError(`Invalid delimiter type '${delim.type}'`, delim); - } - } - - defineFunction({ - type: "delimsizing", - names: [ - "\\bigl", - "\\Bigl", - "\\biggl", - "\\Biggl", - "\\bigr", - "\\Bigr", - "\\biggr", - "\\Biggr", - "\\bigm", - "\\Bigm", - "\\biggm", - "\\Biggm", - "\\big", - "\\Big", - "\\bigg", - "\\Bigg" - ], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - - return { - type: "delimsizing", - mode: context.parser.mode, - size: delimiterSizes[context.funcName].size, - mclass: delimiterSizes[context.funcName].mclass, - delim: delim.text - }; - }, - mathmlBuilder: (group) => { - const children = []; - - if (group.delim === ".") { group.delim = ""; } - children.push(makeText(group.delim, group.mode)); - - const node = new mathMLTree.MathNode("mo", children); - - if (group.mclass === "mopen" || group.mclass === "mclose") { - // Only some of the delimsizing functions act as fences, and they - // return "mopen" or "mclose" mclass. - node.setAttribute("fence", "true"); - } else { - // Explicitly disable fencing if it's not a fence, to override the - // defaults. - node.setAttribute("fence", "false"); - } - if (group.delim === "\u2216") { - // \backslash is not in the operator dictionary, - // so we have to explicitly set stretchy to true. - node.setAttribute("stretchy", "true"); - } - - node.setAttribute("symmetric", "true"); // Needed for tall arrows in Firefox. - node.setAttribute("minsize", sizeToMaxHeight[group.size] + "em"); - node.setAttribute("maxsize", sizeToMaxHeight[group.size] + "em"); - - return node; - } - }); - - function assertParsed(group) { - if (!group.body) { - throw new Error("Bug: The leftright ParseNode wasn't fully parsed."); - } - } - - defineFunction({ - type: "leftright-right", - names: ["\\right"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - // \left case below triggers parsing of \right in - // `const right = parser.parseFunction();` - // uses this return value. - const color = context.parser.gullet.macros.get("\\current@color"); - if (color && typeof color !== "string") { - throw new ParseError("\\current@color set to non-string in \\right"); - } - return { - type: "leftright-right", - mode: context.parser.mode, - delim: checkDelimiter(args[0], context).text, - color // undefined if not set via \color - }; - } - }); - - defineFunction({ - type: "leftright", - names: ["\\left"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - - const parser = context.parser; - // Parse out the implicit body - ++parser.leftrightDepth; - // parseExpression stops before '\\right' - const body = parser.parseExpression(false); - --parser.leftrightDepth; - // Check the next token - parser.expect("\\right", false); - const right = assertNodeType(parser.parseFunction(), "leftright-right"); - return { - type: "leftright", - mode: parser.mode, - body, - left: delim.text, - right: right.delim, - rightColor: right.color - }; - }, - mathmlBuilder: (group, style) => { - assertParsed(group); - const inner = buildExpression(group.body, style); - - if (group.left === ".") { group.left = ""; } - const leftNode = new mathMLTree.MathNode("mo", [makeText(group.left, group.mode)]); - leftNode.setAttribute("fence", "true"); - leftNode.setAttribute("form", "prefix"); - if (group.left === "\u2216") { leftNode.setAttribute("stretchy", "true"); } - inner.unshift(leftNode); - - if (group.right === ".") { group.right = ""; } - const rightNode = new mathMLTree.MathNode("mo", [makeText(group.right, group.mode)]); - rightNode.setAttribute("fence", "true"); - rightNode.setAttribute("form", "postfix"); - if (group.right === "\u2216") { rightNode.setAttribute("stretchy", "true"); } - if (group.rightColor) { rightNode.setAttribute("mathcolor", group.rightColor); } - inner.push(rightNode); - - return makeRow(inner); - } - }); - - defineFunction({ - type: "middle", - names: ["\\middle"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - if (!context.parser.leftrightDepth) { - throw new ParseError("\\middle without preceding \\left", delim); - } - - return { - type: "middle", - mode: context.parser.mode, - delim: delim.text - }; - }, - mathmlBuilder: (group, style) => { - const textNode = makeText(group.delim, group.mode); - const middleNode = new mathMLTree.MathNode("mo", [textNode]); - middleNode.setAttribute("fence", "true"); - // MathML gives 5/18em spacing to each element. - // \middle should get delimiter spacing instead. - middleNode.setAttribute("lspace", "0.05em"); - middleNode.setAttribute("rspace", "0.05em"); - return middleNode; - } - }); - - const mathmlBuilder$8 = (group, style) => { - const node = new mathMLTree.MathNode( - group.label.indexOf("colorbox") > -1 ? "mpadded" : "menclose", - [buildGroup$1(group.body, style)] - ); - switch (group.label) { - case "\\cancel": - node.setAttribute("notation", "updiagonalstrike"); - break; - case "\\bcancel": - node.setAttribute("notation", "downdiagonalstrike"); - break; - case "\\longdiv": - node.setAttribute("notation", "longdiv"); - break; - case "\\phase": - node.setAttribute("notation", "phasorangle"); - break; - case "\\sout": - node.setAttribute("notation", "horizontalstrike"); - break; - case "\\fbox": - node.setAttribute("notation", "box"); - break; - case "\\angl": - node.setAttribute("notation", "actuarial"); - break; - case "\\fcolorbox": - case "\\colorbox": { - // doesn't have a good notation option for \colorbox. - // So use instead. Set some attributes that come - // included with . - const fboxsep = 3; // 3 pt from LaTeX source2e - node.setAttribute("width", `+${2 * fboxsep}pt`); - node.setAttribute("height", `+${2 * fboxsep}pt`); - node.setAttribute("lspace", `${fboxsep}pt`); // - node.setAttribute("voffset", `${fboxsep}pt`); - if (group.label === "\\fcolorbox") { - node.setAttribute("style", "border: 0.06em solid " + String(group.borderColor)); - } - break; - } - case "\\xcancel": - node.setAttribute("notation", "updiagonalstrike downdiagonalstrike"); - break; - } - if (group.backgroundColor) { - node.setAttribute("mathbackground", group.backgroundColor); - } - return node; - }; - - defineFunction({ - type: "enclose", - names: ["\\colorbox"], - props: { - numArgs: 2, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "text"] - }, - handler({ parser, funcName }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let color = ""; - if (model) { - const spec = assertNodeType(args[0], "raw").string; - color = colorFromSpec(model, spec); - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros); - } - const body = args[1]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - backgroundColor: color, - body - }; - }, - mathmlBuilder: mathmlBuilder$8 - }); - - defineFunction({ - type: "enclose", - names: ["\\fcolorbox"], - props: { - numArgs: 3, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "raw", "text"] - }, - handler({ parser, funcName }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let borderColor = ""; - let backgroundColor; - if (model) { - const borderSpec = assertNodeType(args[0], "raw").string; - const backgroundSpec = assertNodeType(args[0], "raw").string; - borderColor = colorFromSpec(model, borderSpec); - backgroundColor = colorFromSpec(model, backgroundSpec); - } else { - borderColor = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros); - backgroundColor = validateColor(assertNodeType(args[1], "raw").string, parser.gullet.macros); - } - const body = args[2]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - backgroundColor, - borderColor, - body - }; - }, - mathmlBuilder: mathmlBuilder$8 - }); - - defineFunction({ - type: "enclose", - names: ["\\fbox"], - props: { - numArgs: 1, - argTypes: ["hbox"], - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "enclose", - mode: parser.mode, - label: "\\fbox", - body: args[0] - }; - } - }); - - defineFunction({ - type: "enclose", - names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\angl", "\\phase", "\\longdiv"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - const body = args[0]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - body - }; - }, - mathmlBuilder: mathmlBuilder$8 - }); - - /** - * All registered environments. - * `environments.js` exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary via `environments.js`. - */ - const _environments = {}; - - function defineEnvironment({ type, names, props, handler, mathmlBuilder }) { - // Set default values of environments. - const data = { - type, - numArgs: props.numArgs || 0, - allowedInText: false, - numOptionalArgs: 0, - handler - }; - for (let i = 0; i < names.length; ++i) { - _environments[names[i]] = data; - } - if (mathmlBuilder) { - _mathmlGroupBuilders[type] = mathmlBuilder; - } - } - - // In TeX, there are actually three sets of dimensions, one for each of - - // Math style is not quite the same thing as script level. - const StyleLevel = { - DISPLAY: 0, - TEXT: 1, - SCRIPT: 2, - SCRIPTSCRIPT: 3 - }; - - // Helper functions - function getHLines(parser) { - // Return an array. The array length = number of hlines. - // Each element in the array tells if the line is dashed. - const hlineInfo = []; - parser.consumeSpaces(); - let nxt = parser.fetch().text; - while (nxt === "\\hline" || nxt === "\\hdashline") { - parser.consume(); - hlineInfo.push(nxt === "\\hdashline"); - parser.consumeSpaces(); - nxt = parser.fetch().text; - } - return hlineInfo; - } - - const validateAmsEnvironmentContext = context => { - const settings = context.parser.settings; - if (!settings.displayMode) { - throw new ParseError(`{${context.envName}} can be used only in display mode.`); - } - }; - - const getTag = (group, style, rowNum) => { - let tag; - const tagContents = group.tags.shift(); - if (tagContents) { - // The author has written a \tag or a \notag in this row. - if (tagContents.body) { - tag = buildExpressionRow(tagContents.body, style); - tag.classes = ["tml-tag"]; - } else { - // \notag. Return an empty cell. - tag = new mathMLTree.MathNode("mtd", []); - tag.setAttribute("style", "padding: 0; min-width:0"); - return tag - } - } else if (group.colSeparationType === "multline" && - ((group.leqno && rowNum !== 0) || (!group.leqno && rowNum !== group.body.length - 1))) { - // A multiline that does not receive a tag. Return an empty cell. - tag = new mathMLTree.MathNode("mtd", []); - tag.setAttribute("style", "padding: 0; min-width:0"); - return tag - } else { - // AMS automatcally numbered equaton. - // Insert a class so the element can be populated by a post-processor. - tag = new mathMLTree.MathNode("mtext", [], ["tml-eqn"]); - } - if (!group.preventTagLap) { - tag = new mathMLTree.MathNode("mpadded", [tag]); - tag.setAttribute("style", "width:0;"); - tag.setAttribute("width", "0"); - if (!group.leqno) { tag.setAttribute("lspace", "-1width"); } - } - tag = new mathMLTree.MathNode("mtd", [tag]); - if (!group.preventTagLap) { tag.setAttribute("style", "padding: 0; min-width:0"); } - return tag - }; - - /** - * Parse the body of the environment, with rows delimited by \\ and - * columns delimited by &, and create a nested list in row-major order - * with one group per cell. If given an optional argument scriptLevel - * ("text", "display", etc.), then each cell is cast into that scriptLevel. - */ - function parseArray( - parser, - { - hskipBeforeAndAfter, // boolean - addJot, // boolean - cols, // [{ type: string , align: l|c|r|null }] - arraystretch, // number - colSeparationType, // "align" | "alignat" | "gather" | "small" | "CD" | "multline" - addEqnNum, // boolean - singleRow, // boolean - emptySingleRow, // boolean - maxNumCols, // number - leqno // boolean - }, - scriptLevel - ) { - parser.gullet.beginGroup(); - if (!singleRow) { - // \cr is equivalent to \\ without the optional size argument (see below) - // TODO: provide helpful error when \cr is used outside array environment - parser.gullet.macros.set("\\cr", "\\\\\\relax"); - } - if (addEqnNum) { - parser.gullet.macros.set("\\tag", "\\env@tag{\\text{#1}}"); - parser.gullet.macros.set("\\notag", "\\env@notag"); - parser.gullet.macros.set("\\nonumber", "\\env@notag"); - } - - // Get current arraystretch if it's not set by the environment - if (arraystretch === undefined || Number.isNaN(arraystretch)) { - const stretch = parser.gullet.expandMacroAsText("\\arraystretch"); - if (stretch == null) { - // Default \arraystretch from lttab.dtx - arraystretch = 1; - } else { - arraystretch = parseFloat(stretch); - if (!arraystretch || arraystretch < 0) { - throw new ParseError(`Invalid \\arraystretch: ${stretch}`); - } - } - } - - // Start group for first cell - parser.gullet.beginGroup(); - - let row = []; - const body = [row]; - const rowGaps = []; - const tags = []; - let rowTag; - const hLinesBeforeRow = []; - - // Test for \hline at the top of the array. - hLinesBeforeRow.push(getHLines(parser)); - - // eslint-disable-next-line no-constant-condition - while (true) { - // Parse each cell in its own group (namespace) - let cell = parser.parseExpression(false, singleRow ? "\\end" : "\\\\"); - - if (addEqnNum && !rowTag) { - // Check if the author wrote a \tag{} inside this cell. - for (let i = 0; i < cell.length; i++) { - if (cell[i].type === "envTag" || cell[i].type === "noTag") { - // Get the contents of the \text{} nested inside the \env@Tag{} - rowTag = cell[i].type === "envTag" - ? cell.splice(i, 1)[0].body.body[0] - : { body: null }; - break - } - } - } - parser.gullet.endGroup(); - parser.gullet.beginGroup(); - - cell = { - type: "ordgroup", - mode: parser.mode, - body: cell - }; - row.push(cell); - const next = parser.fetch().text; - if (next === "&") { - if (maxNumCols && row.length === maxNumCols) { - if (colSeparationType === "split") { - throw new ParseError("The split environment accepts no more than two columns", - parser.nextToken); - } else if (colSeparationType === "array") { - if (parser.settings.strict) { - throw new ParseError("Too few columns " + "specified in the {array} column argument.", - parser.nextToken) - } - } else { - throw new ParseError("The equation environment accepts only one column", - parser.nextToken) - } - } - parser.consume(); - } else if (next === "\\end") { - // Arrays terminate newlines with `\crcr` which consumes a `\cr` if - // the last line is empty. However, AMS environments keep the - // empty row if it's the only one. - // NOTE: Currently, `cell` is the last item added into `row`. - if (row.length === 1 && cell.body.length === 0 && (body.length > 1 || !emptySingleRow)) { - body.pop(); - } - if (hLinesBeforeRow.length < body.length + 1) { - hLinesBeforeRow.push([]); - } - break; - } else if (next === "\\\\") { - parser.consume(); - let size; - // \def\Let@{\let\\\math@cr} - // \def\math@cr{...\math@cr@} - // \def\math@cr@{\new@ifnextchar[\math@cr@@{\math@cr@@[\z@]}} - // \def\math@cr@@[#1]{...\math@cr@@@...} - // \def\math@cr@@@{\cr} - if (parser.gullet.future().text !== " ") { - size = parser.parseSizeGroup(true); - } - rowGaps.push(size ? size.value : null); - - tags.push(rowTag); - - // check for \hline(s) following the row separator - hLinesBeforeRow.push(getHLines(parser)); - - row = []; - rowTag = null; - body.push(row); - } else { - throw new ParseError("Expected & or \\\\ or \\cr or \\end", parser.nextToken); - } - } - - // End cell group - parser.gullet.endGroup(); - // End array group defining \cr - parser.gullet.endGroup(); - - tags.push(rowTag); - - return { - type: "array", - mode: parser.mode, - addJot, - arraystretch, - body, - cols, - rowGaps, - hskipBeforeAndAfter, - hLinesBeforeRow, - colSeparationType, - addEqnNum, - scriptLevel, - tags, - leqno, - preventTagLap: parser.settings.preventTagLap - }; - } - - // Decides on a scriptLevel for cells in an array according to whether the given - // environment name starts with the letter 'd'. - function dCellStyle(envName) { - return envName.slice(0, 1) === "d" ? "display" : "text" - } - - const alignMap = { - c: "center ", - l: "left ", - r: "right " - }; - - const mathmlBuilder$7 = function(group, style) { - const tbl = []; - const numRows = group.body.length; - let glue; - if (group.addEqnNum) { - glue = new mathMLTree.MathNode("mtd", [], []); - const glueStyle = "padding: 0;width: " + - (group.colSeparationType === "multline" ? "7.5%" : "50%"); - glue.setAttribute("style", glueStyle); - } - - for (let i = 0; i < numRows; i++) { - const rw = group.body[i]; - const row = []; - const cellStyle = group.scriptLevel === "text" - ? StyleLevel.TEXT - : group.scriptLevel === "script" - ? StyleLevel.SCRIPT - : StyleLevel.DISPLAY; - - for (let j = 0; j < rw.length; j++) { - const mtd = new mathMLTree.MathNode( - "mtd", - [buildGroup$1(rw[j], style.withLevel(cellStyle))] - ); - if (group.colSeparationType === "multline") { - const align = i === 0 ? "left" : i === numRows - 1 ? "right" : "center"; - mtd.setAttribute("columnalign", align); - } - row.push(mtd); - } - if (group.addEqnNum) { - row.unshift(glue); - row.push(glue); - const tag = getTag(group, style.withLevel(cellStyle), i); - if (group.leqno) { - row.unshift(tag); - } else { - row.push(tag); - } - } - // If group.addEqnNum, insert a breadcrumb to be found by temmlPostProcess(). - tbl.push(new mathMLTree.MathNode("mtr", row, group.addEqnNum ? ["tml-tageqn"] : [] )); - } - let table = new mathMLTree.MathNode("mtable", tbl); - if (group.scriptLevel === "display") { table.setAttribute("displaystyle", "true"); } - - // Set column alignment, row spacing, column spacing, and - // array lines by setting attributes on the table element. - - // Set the row spacing. In MathML, we specify a gap distance. - // We do not use rowGap[] because MathML automatically increases - // cell height with the height/depth of the element content. - - // LaTeX \arraystretch multiplies the row baseline-to-baseline distance. - // We simulate this by adding (arraystretch - 1)em to the gap. This - // does a reasonable job of adjusting arrays containing 1 em tall content. - - // The 0.16 and 0.09 values are found emprically. They produce an array - // similar to LaTeX and in which content does not interfere with \hines. - const gap = - group.arraystretch === 0 - ? 0 // {subarray} - : group.arraystretch === 0.5 - ? 0.1 // {smallmatrix} - : 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0); - table.setAttribute("rowspacing", utils.round(gap) + "em"); - - if (group.addEqnNum || group.colSeparationType === "multline") { - table.setAttribute("width", "100%"); - } - - // MathML table lines go only between cells. - // To place a line on an edge we'll use , if necessary. - let menclose = ""; - let align = ""; - - if (group.cols && group.cols.length > 0) { - // Find column alignment, column spacing, and vertical lines. - const cols = group.cols; - let columnLines = ""; - let prevTypeWasAlign = false; - let iStart = 0; - let iEnd = cols.length; - - if (cols[0].type === "separator") { - menclose += "left "; - iStart = 1; - } - if (cols[cols.length - 1].type === "separator") { - menclose += "right "; - iEnd -= 1; - } - - for (let i = iStart; i < iEnd; i++) { - if (cols[i].type === "align") { - align += alignMap[cols[i].align]; - - if (prevTypeWasAlign) { - columnLines += "none "; - } - prevTypeWasAlign = true; - } else if (cols[i].type === "separator") { - // MathML accepts only single lines between cells. - // So we read only the first of consecutive separators. - if (prevTypeWasAlign) { - columnLines += cols[i].separator === "|" ? "solid " : "dashed "; - prevTypeWasAlign = false; - } - } - } - if (group.addEqnNum) { - align = "left " + align + "right "; // allow for glue cells on each side - align = group.leqno ? "left " + align : align += "right"; // eqn num cell - } - - table.setAttribute("columnalign", align.trim()); - - if (/[sd]/.test(columnLines)) { - table.setAttribute("columnlines", columnLines.trim()); - } - } - - // Set column spacing. - switch (group.colSeparationType) { - case "gather": - case "gathered": - case "alignedat": - case "alignat": - case "alignat*": - table.setAttribute("columnspacing", "0em"); - break - case "small": - table.setAttribute("columnspacing", "0.2778em"); - break - case "CD": - table.setAttribute("columnspacing", "0.5em"); - break - case "align": - case "align*": { - const cols = group.cols || []; - let spacing = group.addEqnNum ? "0em " : ""; - for (let i = 1; i < cols.length; i++) { - spacing += i % 2 ? "0em " : "1em "; - } - if (group.addEqnNum) { spacing += "0em"; } - table.setAttribute("columnspacing", spacing.trim()); - break - } - default: - table.setAttribute("columnspacing", "1em"); - } - - // Address \hline and \hdashline - let rowLines = ""; - const hlines = group.hLinesBeforeRow; - - menclose += hlines[0].length > 0 ? "top " : ""; - menclose += hlines[hlines.length - 1].length > 0 ? "bottom " : ""; - - for (let i = 1; i < hlines.length - 1; i++) { - rowLines += - hlines[i].length === 0 - ? "none " - : // MathML accepts only a single line between rows. Read one element. - hlines[i][0] - ? "dashed " - : "solid "; - } - if (/[sd]/.test(rowLines)) { - table.setAttribute("rowlines", rowLines.trim()); - } - - if (menclose !== "") { - table = new mathMLTree.MathNode("menclose", [table]); - table.setAttribute("notation", menclose.trim()); - } - - if (!Number.isNaN(group.arraystretch) && group.arraystretch < 1) { - // A small array. Wrap in scriptstyle so row gap is not too large. - table = new mathMLTree.MathNode("mstyle", [table]); - table.setAttribute("scriptlevel", "1"); - } - - return table; - }; - - // Convenience function for align, align*, aligned, alignat, alignat*, alignedat. - const alignedHandler = function(context, args) { - if (context.envName.indexOf("ed") === -1) { - validateAmsEnvironmentContext(context); - } - const cols = []; - const res = parseArray( - context.parser, - { - cols, - addJot: true, - addEqnNum: context.envName === "align" || context.envName === "alignat", - emptySingleRow: true, - colSeparationType: context.envName, - maxNumCols: context.envName === "split" ? 2 : undefined, - leqno: context.parser.settings.leqno - }, - "display" - ); - - // Determining number of columns. - // 1. If the first argument is given, we use it as a number of columns, - // and makes sure that each row doesn't exceed that number. - // 2. Otherwise, just count number of columns = maximum number - // of cells in each row ("aligned" mode -- isAligned will be true). - // - // At the same time, prepend empty group {} at beginning of every second - // cell in each row (starting with second cell) so that operators become - // binary. This behavior is implemented in amsmath's \start@aligned. - let numMaths; - let numCols = 0; - if (args[0] && args[0].type === "ordgroup") { - let arg0 = ""; - for (let i = 0; i < args[0].body.length; i++) { - const textord = assertNodeType(args[0].body[i], "textord"); - arg0 += textord.text; - } - numMaths = Number(arg0); - numCols = numMaths * 2; - } - const isAligned = !numCols; - res.body.forEach(function(row) { - if (!isAligned) { - // Case 1 - const curMaths = row.length / 2; - if (numMaths < curMaths) { - throw new ParseError( - "Too many math in a row: " + `expected ${numMaths}, but got ${curMaths}`, - row[0] - ); - } - } else if (numCols < row.length) { - // Case 2 - numCols = row.length; - } - }); - - // Adjusting alignment. - // In aligned mode, we add one \qquad between columns; - // otherwise we add nothing. - for (let i = 0; i < numCols; ++i) { - let align = "r"; - if (i % 2 === 1) { - align = "l"; - } - cols[i] = { - type: "align", - align: align - }; - } - res.colSeparationType = isAligned ? "align" : "alignat"; - return res; - }; - - // Arrays are part of LaTeX, defined in lttab.dtx so its documentation - // is part of the source2e.pdf file of LaTeX2e source documentation. - // {darray} is an {array} environment where cells are set in \displaystyle, - // as defined in nccmath.sty. - defineEnvironment({ - type: "array", - names: ["array", "darray"], - props: { - numArgs: 1 - }, - handler(context, args) { - // Since no types are specified above, the two possibilities are - // - The argument is wrapped in {} or [], in which case Parser's - // parseGroup() returns an "ordgroup" wrapping some symbol node. - // - The argument is a bare symbol node. - const symNode = checkSymbolNodeType(args[0]); - const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; - const cols = colalign.map(function(nde) { - const node = assertSymbolNodeType(nde); - const ca = node.text; - if ("lcr".indexOf(ca) !== -1) { - return { - type: "align", - align: ca - }; - } else if (ca === "|") { - return { - type: "separator", - separator: "|" - }; - } else if (ca === ":") { - return { - type: "separator", - separator: ":" - }; - } - throw new ParseError("Unknown column alignment: " + ca, nde); - }); - const res = { - cols, - colSeparationType: "array", - hskipBeforeAndAfter: true, // \@preamble in lttab.dtx - maxNumCols: cols.length - }; - return parseArray(context.parser, res, dCellStyle(context.envName)); - }, - mathmlBuilder: mathmlBuilder$7 - }); - - // The matrix environments of amsmath builds on the array environment - // of LaTeX, which is discussed above. - // The mathtools package adds starred versions of the same environments. - // These have an optional argument to choose left|center|right justification. - defineEnvironment({ - type: "array", - names: [ - "matrix", - "pmatrix", - "bmatrix", - "Bmatrix", - "vmatrix", - "Vmatrix", - "matrix*", - "pmatrix*", - "bmatrix*", - "Bmatrix*", - "vmatrix*", - "Vmatrix*" - ], - props: { - numArgs: 0 - }, - handler(context) { - const delimiters = { - matrix: null, - pmatrix: ["(", ")"], - bmatrix: ["[", "]"], - Bmatrix: ["\\{", "\\}"], - vmatrix: ["|", "|"], - Vmatrix: ["\\Vert", "\\Vert"] - }[context.envName.replace("*", "")]; - // \hskip -\arraycolsep in amsmath - let colAlign = "c"; - const payload = { - hskipBeforeAndAfter: false, - colSeparationType: "matrix", - cols: [{ type: "align", align: colAlign }] - }; - if (context.envName.charAt(context.envName.length - 1) === "*") { - // It's one of the mathtools starred functions. - // Parse the optional alignment argument. - const parser = context.parser; - parser.consumeSpaces(); - if (parser.fetch().text === "[") { - parser.consume(); - parser.consumeSpaces(); - colAlign = parser.fetch().text; - if ("lcr".indexOf(colAlign) === -1) { - throw new ParseError("Expected l or c or r", parser.nextToken); - } - parser.consume(); - parser.consumeSpaces(); - parser.expect("]"); - parser.consume(); - payload.cols = [{ type: "align", align: colAlign }]; - } - } - const res = parseArray(context.parser, payload, "text"); - // Populate cols with the correct number of column alignment specs. - const numCols = Math.max(0, ...res.body.map((row) => row.length)); - res.cols = new Array(numCols).fill({ type: "align", align: colAlign }); - return delimiters - ? { - type: "leftright", - mode: context.mode, - body: [res], - left: delimiters[0], - right: delimiters[1], - rightColor: undefined // \right uninfluenced by \color in array - } - : res; - }, - mathmlBuilder: mathmlBuilder$7 - }); - - defineEnvironment({ - type: "array", - names: ["smallmatrix"], - props: { - numArgs: 0 - }, - handler(context) { - const payload = { arraystretch: 0.5 }; - const res = parseArray(context.parser, payload, "script"); - res.colSeparationType = "small"; - return res; - }, - mathmlBuilder: mathmlBuilder$7 - }); - - defineEnvironment({ - type: "array", - names: ["subarray"], - props: { - numArgs: 1 - }, - handler(context, args) { - // Parsing of {subarray} is similar to {array} - const symNode = checkSymbolNodeType(args[0]); - const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; - const cols = colalign.map(function(nde) { - const node = assertSymbolNodeType(nde); - const ca = node.text; - // {subarray} only recognizes "l" & "c" - if ("lc".indexOf(ca) !== -1) { - return { - type: "align", - align: ca - }; - } - throw new ParseError("Unknown column alignment: " + ca, nde); - }); - if (cols.length > 1) { - throw new ParseError("{subarray} can contain only one column"); - } - let res = { - cols, - hskipBeforeAndAfter: false, - colSeparationType: "array", - arraystretch: 0 - }; - res = parseArray(context.parser, res, "script"); - if (res.body.length > 0 && res.body[0].length > 1) { - throw new ParseError("{subarray} can contain only one column"); - } - return res; - }, - mathmlBuilder: mathmlBuilder$7 - }); - - // A cases environment (in amsmath.sty) is almost equivalent to - // \def - // \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right. - // {dcases} is a {cases} environment where cells are set in \displaystyle, - // as defined in mathtools.sty. - // {rcases} is another mathtools environment. It's brace is on the right side. - defineEnvironment({ - type: "array", - names: ["cases", "dcases", "rcases", "drcases"], - props: { - numArgs: 0 - }, - handler(context) { - const payload = { - cols: [ - { - type: "align", - align: "l" - }, - { - type: "align", - align: "l" - } - ], - colSeparationType: "cases" - }; - const res = parseArray(context.parser, payload, dCellStyle(context.envName)); - return { - type: "leftright", - mode: context.mode, - body: [res], - left: context.envName.indexOf("r") > -1 ? "." : "\\{", - right: context.envName.indexOf("r") > -1 ? "\\}" : ".", - rightColor: undefined - }; - }, - mathmlBuilder: mathmlBuilder$7 - }); - - // In the align environment, one uses ampersands, &, to specify number of - // columns in each row, and to locate spacing between each column. - // align gets automatic numbering. align* and aligned do not. - // The alignedat environment can be used in math mode. - // Note that we assume \nomallineskiplimit to be zero, - // so that \strut@ is the same as \strut. - defineEnvironment({ - type: "array", - names: ["align", "align*", "aligned", "split"], - props: { - numArgs: 0 - }, - handler: alignedHandler, - mathmlBuilder: mathmlBuilder$7 - }); - - // A gathered environment is like an array environment with one centered - // column, but where rows are considered lines so get \jot line spacing - // and contents are set in \displaystyle. - defineEnvironment({ - type: "array", - names: ["gathered", "gather", "gather*"], - props: { - numArgs: 0 - }, - handler(context) { - if (utils.contains(["gather", "gather*"], context.envName)) { - validateAmsEnvironmentContext(context); - } - const res = { - cols: [ - { - type: "align", - align: "c" - } - ], - addJot: true, - colSeparationType: "gather", - addEqnNum: context.envName === "gather", - emptySingleRow: true, - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder: mathmlBuilder$7 - }); - - // alignat environment is like an align environment, but one must explicitly - // specify maximum number of columns in each row, and can adjust spacing between - // each columns. - defineEnvironment({ - type: "array", - names: ["alignat", "alignat*", "alignedat"], - props: { - numArgs: 1 - }, - handler: alignedHandler, - mathmlBuilder: mathmlBuilder$7 - }); - - defineEnvironment({ - type: "array", - names: ["equation", "equation*"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - const res = { - addEqnNum: context.envName === "equation", - emptySingleRow: true, - singleRow: true, - maxNumCols: 1, - colSeparationType: "gather", - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder: mathmlBuilder$7 - }); - - defineEnvironment({ - type: "array", - names: ["multline", "multline*"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - const res = { - addEqnNum: context.envName === "multline", - maxNumCols: 1, - colSeparationType: "multline", - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder: mathmlBuilder$7 - }); - - defineEnvironment({ - type: "array", - names: ["CD"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - return parseCD(context.parser); - }, - mathmlBuilder: mathmlBuilder$7 - }); - - // Catch \hline outside array environment - defineFunction({ - type: "text", // Doesn't matter what this is. - names: ["\\hline", "\\hdashline"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: true - }, - handler(context, args) { - throw new ParseError(`${context.funcName} valid only within array environment`); - } - }); - - const environments = _environments; - - // Environment delimiters. HTML/MathML rendering is defined in the corresponding - // defineEnvironment definitions. - defineFunction({ - type: "environment", - names: ["\\begin", "\\end"], - props: { - numArgs: 1, - argTypes: ["text"] - }, - handler({ parser, funcName }, args) { - const nameGroup = args[0]; - if (nameGroup.type !== "ordgroup") { - throw new ParseError("Invalid environment name", nameGroup); - } - let envName = ""; - for (let i = 0; i < nameGroup.body.length; ++i) { - envName += assertNodeType(nameGroup.body[i], "textord").text; - } - - if (funcName === "\\begin") { - // begin...end is similar to left...right - if (!Object.prototype.hasOwnProperty.call(environments, envName )) { - throw new ParseError("No such environment: " + envName, nameGroup); - } - // Build the environment object. Arguments and other information will - // be made available to the begin and end methods using properties. - const env = environments[envName]; - const { args, optArgs } = parser.parseArguments("\\begin{" + envName + "}", env); - const context = { - mode: parser.mode, - envName, - parser - }; - const result = env.handler(context, args, optArgs); - parser.expect("\\end", false); - const endNameToken = parser.nextToken; - const end = assertNodeType(parser.parseFunction(), "environment"); - if (end.name !== envName) { - throw new ParseError( - `Mismatch: \\begin{${envName}} matched by \\end{${end.name}}`, - endNameToken - ); - } - return result; - } - - return { - type: "environment", - mode: parser.mode, - name: envName, - nameGroup - }; - } - }); - - defineFunction({ - type: "envTag", - names: ["\\env@tag"], - props: { - numArgs: 1, - argTypes: ["math"] - }, - handler({ parser }, args) { - return { - type: "envTag", - mode: parser.mode, - body: args[0] - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow"); - } - }); - - defineFunction({ - type: "noTag", - names: ["\\env@notag"], - props: { - numArgs: 0 - }, - handler({ parser }) { - return { - type: "noTag", - mode: parser.mode - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow"); - } - }); - - const mathmlBuilder$6 = (group, style) => { - const font = group.font; - const newStyle = style.withFont(font); - const mathGroup = buildGroup$1(group.body, newStyle); - - if (mathGroup.children.length === 0) { return mathGroup } // empty group, e.g., \mathrm{} - if (font === "boldsymbol" && ["mo", "mpadded"].includes(mathGroup.type)) { - mathGroup.style.fontWeight = "bold"; - return mathGroup - } - // Check if it is possible to consolidate elements into a single element. - let canConsolidate = mathGroup.children[0].type === "mo"; - for (let i = 1; i < mathGroup.children.length; i++) { - if (mathGroup.children[i].type === "mo" && font === "boldsymbol") { - mathGroup.children[i].style.fontWeight = "bold"; - } - if (mathGroup.children[i].type !== "mi") { canConsolidate = false; } - const localVariant = mathGroup.children[i].attributes && - mathGroup.children[i].attributes.mathvariant || ""; - if (localVariant !== "normal") { canConsolidate = false; } - } - if (!canConsolidate) { return mathGroup } - // Consolidate the elements. - const mi = mathGroup.children[0]; - for (let i = 1; i < mathGroup.children.length; i++) { - mi.children.push(mathGroup.children[i].children[0]); - } - if (mathGroup.attributes.mathcolor) { mi.attributes.mathcolor = mathGroup.attributes.mathcolor; } - if (mi.attributes.mathvariant && mi.attributes.mathvariant === "normal") { - // Workaround for a Firefox bug that renders spurious space around - // a - // Ref: https://bugs.webkit.org/show_bug.cgi?id=129097 - // We insert a text node that contains a zero-width space and wrap in an mrow. - // TODO: Get rid of this workaround when the Firefox bug is fixed. - const bogus = new mathMLTree.MathNode("mtext", new mathMLTree.TextNode("\u200b")); - return new mathMLTree.MathNode("mrow", [bogus, mi]) - } - return mi - }; - - const fontAliases = { - "\\Bbb": "\\mathbb", - "\\bold": "\\mathbf", - "\\frak": "\\mathfrak", - "\\bm": "\\boldsymbol" - }; - - defineFunction({ - type: "font", - names: [ - // styles - "\\mathrm", - "\\mathit", - "\\mathbf", - "\\mathnormal", - "\\up@greek", - "\\boldsymbol", - - // families - "\\mathbb", - "\\mathcal", - "\\mathfrak", - "\\mathscr", - "\\mathsf", - "\\mathtt", - "\\oldstylenums", - - // aliases - "\\Bbb", - "\\bm", - "\\bold", - "\\frak" - ], - props: { - numArgs: 1, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const body = normalizeArgument(args[0]); - let func = funcName; - if (func in fontAliases) { - func = fontAliases[func]; - } - return { - type: "font", - mode: parser.mode, - font: func.slice(1), - body - }; - }, - mathmlBuilder: mathmlBuilder$6 - }); - - // Old font changing functions - defineFunction({ - type: "font", - names: ["\\rm", "\\sf", "\\tt", "\\bf", "\\it", "\\cal"], - props: { - numArgs: 0, - allowedInText: true - }, - handler: ({ parser, funcName, breakOnTokenText }, args) => { - const { mode } = parser; - const body = parser.parseExpression(true, breakOnTokenText); - const fontStyle = `math${funcName.slice(1)}`; - - return { - type: "font", - mode: mode, - font: fontStyle, - body: { - type: "ordgroup", - mode: parser.mode, - body - } - }; - }, - mathmlBuilder: mathmlBuilder$6 - }); - - const stylArray = ["display", "text", "script", "scriptscript"]; - const scriptLevel = { auto: -1, display: 0, text: 0, script: 1, scriptscript: 2 }; - - const mathmlBuilder$5 = (group, style) => { - // Track the scriptLevel of the numerator and denominator. - // We may need that info for \mathchoice or for adjusting em dimensions. - const childOptions = group.scriptLevel === "auto" - ? style.incrementLevel() - : group.scriptLevel === "display" - ? style.withLevel(StyleLevel.TEXT) - : group.scriptLevel === "text" - ? style.withLevel(StyleLevel.SCRIPT) - : style.withLevel(StyleLevel.SCRIPTSCRIPT); - - let node = new mathMLTree.MathNode("mfrac", [ - buildGroup$1(group.numer, childOptions), - buildGroup$1(group.denom, childOptions) - ]); - - if (!group.hasBarLine) { - node.setAttribute("linethickness", "0px"); - } else if (group.barSize) { - const ruleWidth = calculateSize(group.barSize, style); - node.setAttribute("linethickness", ruleWidth.number + ruleWidth.unit); - } - - if (group.leftDelim != null || group.rightDelim != null) { - const withDelims = []; - - if (group.leftDelim != null) { - const leftOp = new mathMLTree.MathNode("mo", [ - new mathMLTree.TextNode(group.leftDelim.replace("\\", "")) - ]); - leftOp.setAttribute("fence", "true"); - withDelims.push(leftOp); - } - - withDelims.push(node); - - if (group.rightDelim != null) { - const rightOp = new mathMLTree.MathNode("mo", [ - new mathMLTree.TextNode(group.rightDelim.replace("\\", "")) - ]); - rightOp.setAttribute("fence", "true"); - withDelims.push(rightOp); - } - - node = makeRow(withDelims); - } - - if (group.scriptLevel !== "auto") { - node = new mathMLTree.MathNode("mstyle", [node]); - node.setAttribute("displaystyle", String(group.scriptLevel === "display")); - node.setAttribute("scriptlevel", scriptLevel[group.scriptLevel]); - } - - return node; - }; - - defineFunction({ - type: "genfrac", - names: [ - "\\dfrac", - "\\frac", - "\\tfrac", - "\\dbinom", - "\\binom", - "\\tbinom", - "\\\\atopfrac", // can’t be entered directly - "\\\\bracefrac", - "\\\\brackfrac" // ditto - ], - props: { - numArgs: 2, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const denom = args[1]; - let hasBarLine = false; - let leftDelim = null; - let rightDelim = null; - let scriptLevel = "auto"; - - switch (funcName) { - case "\\dfrac": - case "\\frac": - case "\\tfrac": - hasBarLine = true; - break; - case "\\\\atopfrac": - hasBarLine = false; - break; - case "\\dbinom": - case "\\binom": - case "\\tbinom": - leftDelim = "("; - rightDelim = ")"; - break; - case "\\\\bracefrac": - leftDelim = "\\{"; - rightDelim = "\\}"; - break; - case "\\\\brackfrac": - leftDelim = "["; - rightDelim = "]"; - break; - default: - throw new Error("Unrecognized genfrac command"); - } - - switch (funcName) { - case "\\dfrac": - case "\\dbinom": - scriptLevel = "display"; - break; - case "\\tfrac": - case "\\tbinom": - scriptLevel = "text"; - break; - } - - return { - type: "genfrac", - mode: parser.mode, - continued: false, - numer, - denom, - hasBarLine, - leftDelim, - rightDelim, - scriptLevel, - barSize: null - }; - }, - mathmlBuilder: mathmlBuilder$5 - }); - - defineFunction({ - type: "genfrac", - names: ["\\cfrac"], - props: { - numArgs: 2 - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const denom = args[1]; - - return { - type: "genfrac", - mode: parser.mode, - continued: true, - numer, - denom, - hasBarLine: true, - leftDelim: null, - rightDelim: null, - scriptLevel: "display", - barSize: null - }; - } - }); - - // Infix generalized fractions -- these are not rendered directly, but replaced - // immediately by one of the variants above. - defineFunction({ - type: "infix", - names: ["\\over", "\\choose", "\\atop", "\\brace", "\\brack"], - props: { - numArgs: 0, - infix: true - }, - handler({ parser, funcName, token }) { - let replaceWith; - switch (funcName) { - case "\\over": - replaceWith = "\\frac"; - break; - case "\\choose": - replaceWith = "\\binom"; - break; - case "\\atop": - replaceWith = "\\\\atopfrac"; - break; - case "\\brace": - replaceWith = "\\\\bracefrac"; - break; - case "\\brack": - replaceWith = "\\\\brackfrac"; - break; - default: - throw new Error("Unrecognized infix genfrac command"); - } - return { - type: "infix", - mode: parser.mode, - replaceWith, - token - }; - } - }); - - const delimFromValue = function(delimString) { - let delim = null; - if (delimString.length > 0) { - delim = delimString; - delim = delim === "." ? null : delim; - } - return delim; - }; - - defineFunction({ - type: "genfrac", - names: ["\\genfrac"], - props: { - numArgs: 6, - allowedInArgument: true, - argTypes: ["math", "math", "size", "text", "math", "math"] - }, - handler({ parser }, args) { - const numer = args[4]; - const denom = args[5]; - - // Look into the parse nodes to get the desired delimiters. - const leftNode = normalizeArgument(args[0]); - const leftDelim = leftNode.type === "atom" && leftNode.family === "open" - ? delimFromValue(leftNode.text) - : null; - const rightNode = normalizeArgument(args[1]); - const rightDelim = - rightNode.type === "atom" && rightNode.family === "close" - ? delimFromValue(rightNode.text) - : null; - - const barNode = assertNodeType(args[2], "size"); - let hasBarLine; - let barSize = null; - if (barNode.isBlank) { - // \genfrac acts differently than \above. - // \genfrac treats an empty size group as a signal to use a - // standard bar size. \above would see size = 0 and omit the bar. - hasBarLine = true; - } else { - barSize = barNode.value; - hasBarLine = barSize.number > 0; - } - - // Find out if we want displaystyle, textstyle, etc. - let scriptLevel = "auto"; - let styl = args[3]; - if (styl.type === "ordgroup") { - if (styl.body.length > 0) { - const textOrd = assertNodeType(styl.body[0], "textord"); - scriptLevel = stylArray[Number(textOrd.text)]; - } - } else { - styl = assertNodeType(styl, "textord"); - scriptLevel = stylArray[Number(styl.text)]; - } - - return { - type: "genfrac", - mode: parser.mode, - numer, - denom, - continued: false, - hasBarLine, - barSize, - leftDelim, - rightDelim, - scriptLevel - }; - }, - mathmlBuilder: mathmlBuilder$5 - }); - - // \above is an infix fraction that also defines a fraction bar size. - defineFunction({ - type: "infix", - names: ["\\above"], - props: { - numArgs: 1, - argTypes: ["size"], - infix: true - }, - handler({ parser, funcName, token }, args) { - return { - type: "infix", - mode: parser.mode, - replaceWith: "\\\\abovefrac", - barSize: assertNodeType(args[0], "size").value, - token - }; - } - }); - - defineFunction({ - type: "genfrac", - names: ["\\\\abovefrac"], - props: { - numArgs: 3, - argTypes: ["math", "size", "math"] - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const barSize = assert(assertNodeType(args[1], "infix").barSize); - const denom = args[2]; - - const hasBarLine = barSize.number > 0; - return { - type: "genfrac", - mode: parser.mode, - numer, - denom, - continued: false, - hasBarLine, - barSize, - leftDelim: null, - rightDelim: null, - scriptLevel: "auto" - }; - }, - - mathmlBuilder: mathmlBuilder$5 - }); - - const mathmlBuilder$4 = (group, style) => { - const accentNode = stretchy.mathMLnode(group.label); - return new mathMLTree.MathNode(group.isOver ? "mover" : "munder", [ - buildGroup$1(group.base, style), - accentNode - ]); - }; - - // Horizontal stretchy braces - defineFunction({ - type: "horizBrace", - names: ["\\overbrace", "\\underbrace"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - return { - type: "horizBrace", - mode: parser.mode, - label: funcName, - isOver: /^\\over/.test(funcName), - base: args[0] - }; - }, - mathmlBuilder: mathmlBuilder$4 - }); - - defineFunction({ - type: "href", - names: ["\\href"], - props: { - numArgs: 2, - argTypes: ["url", "original"], - allowedInText: true - }, - handler: ({ parser, token }, args) => { - const body = args[1]; - const href = assertNodeType(args[0], "url").url; - - if ( - !parser.settings.isTrusted({ - command: "\\href", - url: href - }) - ) { - throw new ParseError(`Function "\\href" is not trusted`, token) - } - - return { - type: "href", - mode: parser.mode, - href, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - let math = buildExpressionRow(group.body, style); - if (!(math instanceof MathNode)) { - math = new MathNode("mrow", [math]); - } - math.setAttribute("href", group.href); - return math; - } - }); - - defineFunction({ - type: "href", - names: ["\\url"], - props: { - numArgs: 1, - argTypes: ["url"], - allowedInText: true - }, - handler: ({ parser, token }, args) => { - const href = assertNodeType(args[0], "url").url; - - if ( - !parser.settings.isTrusted({ - command: "\\url", - url: href - }) - ) { - throw new ParseError(`Function "\\url" is not trusted`, token) - } - - const chars = []; - for (let i = 0; i < href.length; i++) { - let c = href[i]; - if (c === "~") { - c = "\\textasciitilde"; - } - chars.push({ - type: "textord", - mode: "text", - text: c - }); - } - const body = { - type: "text", - mode: parser.mode, - font: "\\texttt", - body: chars - }; - return { - type: "href", - mode: parser.mode, - href, - body: ordargument(body) - }; - } - }); - - defineFunction({ - type: "html", - names: ["\\class", "\\id", "\\style", "\\data"], - props: { - numArgs: 2, - argTypes: ["raw", "original"], - allowedInText: true - }, - handler: ({ parser, funcName, token }, args) => { - const value = assertNodeType(args[0], "raw").string; - const body = args[1]; - - if (parser.settings.strict) { - throw new ParseError(`Function "${funcName}" is disabled in strict mode`, token) - } - - let trustContext; - const attributes = {}; - - switch (funcName) { - case "\\class": - attributes.class = value; - trustContext = { - command: "\\class", - class: value - }; - break; - case "\\id": - attributes.id = value; - trustContext = { - command: "\\id", - id: value - }; - break; - case "\\style": - attributes.style = value; - trustContext = { - command: "\\style", - style: value - }; - break; - case "\\data": { - const data = value.split(","); - for (let i = 0; i < data.length; i++) { - const keyVal = data[i].split("="); - if (keyVal.length !== 2) { - throw new ParseError("Error parsing key-value for \\data"); - } - attributes["data-" + keyVal[0].trim()] = keyVal[1].trim(); - } - - trustContext = { - command: "\\data", - attributes - }; - break; - } - default: - throw new Error("Unrecognized html command"); - } - - if (!parser.settings.isTrusted(trustContext)) { - throw new ParseError(`Function "${funcName}" is not trusted`, token) - } - return { - type: "html", - mode: parser.mode, - attributes, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - const element = buildExpressionRow(group.body, style); - - const classes = []; - if (group.attributes.class) { - classes.push(...group.attributes.class.trim().split(/\s+/)); - } - element.classes = classes; - - for (const attr in group.attributes) { - if (attr !== "class" && Object.prototype.hasOwnProperty.call(group.attributes, attr)) { - element.setAttribute(attr, group.attributes[attr]); - } - } - - return element; - } - }); - - const sizeData = function(str) { - if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(str)) { - // str is a number with no unit specified. - // default unit is bp, per graphix package. - return { number: +str, unit: "bp" } - } else { - const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(str); - if (!match) { - throw new ParseError("Invalid size: '" + str + "' in \\includegraphics"); - } - const data = { - number: +(match[1] + match[2]), // sign + magnitude, cast to number - unit: match[3] - }; - if (!validUnit(data)) { - throw new ParseError("Invalid unit: '" + data.unit + "' in \\includegraphics."); - } - return data - } - }; - - defineFunction({ - type: "includegraphics", - names: ["\\includegraphics"], - props: { - numArgs: 1, - numOptionalArgs: 1, - argTypes: ["raw", "url"], - allowedInText: false - }, - handler: ({ parser, token }, args, optArgs) => { - let width = { number: 0, unit: "em" }; - let height = { number: 0.9, unit: "em" }; // sorta character sized. - let totalheight = { number: 0, unit: "em" }; - let alt = ""; - - if (optArgs[0]) { - const attributeStr = assertNodeType(optArgs[0], "raw").string; - - // Parser.js does not parse key/value pairs. We get a string. - const attributes = attributeStr.split(","); - for (let i = 0; i < attributes.length; i++) { - const keyVal = attributes[i].split("="); - if (keyVal.length === 2) { - const str = keyVal[1].trim(); - switch (keyVal[0].trim()) { - case "alt": - alt = str; - break - case "width": - width = sizeData(str); - break - case "height": - height = sizeData(str); - break - case "totalheight": - totalheight = sizeData(str); - break - default: - throw new ParseError("Invalid key: '" + keyVal[0] + "' in \\includegraphics.") - } - } - } - } - - const src = assertNodeType(args[0], "url").url; - - if (alt === "") { - // No alt given. Use the file name. Strip away the path. - alt = src; - alt = alt.replace(/^.*[\\/]/, ""); - alt = alt.substring(0, alt.lastIndexOf(".")); - } - - if ( - !parser.settings.isTrusted({ - command: "\\includegraphics", - url: src - }) - ) { - throw new ParseError(`Function "\\includegraphics" is not trusted`, token) - } - - return { - type: "includegraphics", - mode: parser.mode, - alt: alt, - width: width, - height: height, - totalheight: totalheight, - src: src - } - }, - mathmlBuilder: (group, style) => { - const height = calculateSize(group.height, style); - const depth = { number: 0, unit: "em" }; - - if (group.totalheight.number > 0) { - if (group.totalheight.unit === height.unit && - group.totalheight.number > height.number) { - depth.number = group.totalheight.number - height.number; - depth.unit = height.unit; - } - } - - let width = 0; - if (group.width.number > 0) { - width = calculateSize(group.width, style); - } - - const graphicStyle = { height: height.number + depth.number + "em" }; - if (width.number > 0) { - graphicStyle.width = width.number + width.unit; - } - if (depth.number > 0) { - graphicStyle.verticalAlign = -depth.number + depth.unit; - } - - const node = new Img(group.src, group.alt, graphicStyle); - node.height = height; - node.depth = depth; - return new mathMLTree.MathNode("mtext", [node]) - } - }); - - // Horizontal spacing commands - - // TODO: \hskip and \mskip should support plus and minus in lengths - - defineFunction({ - type: "kern", - names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"], - props: { - numArgs: 1, - argTypes: ["size"], - primitive: true, - allowedInText: true - }, - handler({ parser, funcName, token }, args) { - const size = assertNodeType(args[0], "size"); - if (parser.settings.strict) { - const mathFunction = funcName[1] === "m"; // \mkern, \mskip - const muUnit = size.value.unit === "mu"; - if (mathFunction) { - if (!muUnit) { - throw new ParseError(`LaTeX's ${funcName} supports only mu units, ` + - `not ${size.value.unit} units`, token) - } - if (parser.mode !== "math") { - throw new ParseError(`LaTeX's ${funcName} works only in math mode`, token) - } - } else { - // !mathFunction - if (muUnit) { - throw new ParseError(`LaTeX's ${funcName} doesn't support mu units`, token) - } - } - } - return { - type: "kern", - mode: parser.mode, - dimension: size.value - }; - }, - mathmlBuilder(group, style) { - const dimension = calculateSize(group.dimension, style); - const ch = dimension.unit === "em" ? spaceCharacter(dimension.number) : ""; - if (group.mode === "text" && ch.length > 0) { - const character = new mathMLTree.TextNode(ch); - return new mathMLTree.MathNode("mtext", [character]); - } else { - const node = new mathMLTree.MathNode("mspace"); - node.setAttribute("width", dimension.number + dimension.unit); - return node; - } - } - }); - - const spaceCharacter = function(width) { - if (width >= 0.05555 && width <= 0.05556) { - return "\u200a"; //   - } else if (width >= 0.1666 && width <= 0.1667) { - return "\u2009"; //   - } else if (width >= 0.2222 && width <= 0.2223) { - return "\u2005"; //   - } else if (width >= 0.2777 && width <= 0.2778) { - return "\u2005\u200a"; //    - } else { - return ""; - } - }; - - // Limit valid characters to a small set, for safety. - const invalidIdRegEx = /[^A-Za-z_0-9-]/g; - - defineFunction({ - type: "label", - names: ["\\label"], - props: { - numArgs: 1, - argTypes: ["raw"] - }, - handler({ parser }, args) { - return { - type: "label", - mode: parser.mode, - string: args[0].string.replace(invalidIdRegEx, "") - }; - }, - mathmlBuilder(group, style) { - // Return a no-width, no-ink element with an HTML id. - const node = new mathMLTree.MathNode("mrow", [], ["tml-label"]); - if (group.string.length > 0) { - node.setAttribute("id", group.string); - } - return node - } - }); - - // Horizontal overlap functions - - const textModeLap = ["\\clap", "\\llap", "\\rlap"]; - - defineFunction({ - type: "lap", - names: ["\\mathllap", "\\mathrlap", "\\mathclap", "\\clap", "\\llap", "\\rlap"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser, funcName, token }, args) => { - if (textModeLap.includes(funcName)) { - if (parser.settings.strict && parser.mode !== "text") { - throw new ParseError(`{${funcName}} can be used only in text mode. - Try \\math${funcName.slice(1)}`, token) - } - funcName = funcName.slice(1); - } else { - funcName = funcName.slice(5); - } - const body = args[0]; - return { - type: "lap", - mode: parser.mode, - alignment: funcName, - body - } - }, - mathmlBuilder: (group, style) => { - // mathllap, mathrlap, mathclap - const node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, style)]); - - if (group.alignment === "rlap") { - if (group.body.body.length > 0 && group.body.body[0].type === "genfrac") { - // In Firefox, a squashes the 3/18em padding of a child \frac. Put it back. - node.setAttribute("lspace", "0.16667em"); - } - } else { - const offset = group.alignment === "llap" ? "-1" : "-0.5"; - node.setAttribute("lspace", offset + "width"); - } - node.setAttribute("width", "0px"); - return node - } - }); - - // Switching from text mode back to math mode - defineFunction({ - type: "ordgroup", - names: ["\\(", "$"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: false - }, - handler({ funcName, parser }, args) { - const outerMode = parser.mode; - parser.switchMode("math"); - const close = funcName === "\\(" ? "\\)" : "$"; - const body = parser.parseExpression(false, close); - parser.expect(close); - parser.switchMode(outerMode); - return { - type: "ordgroup", - mode: parser.mode, - body - }; - } - }); - - // Check for extra closing math delimiters - defineFunction({ - type: "text", // Doesn't matter what this is. - names: ["\\)", "\\]"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: false - }, - handler(context, token) { - throw new ParseError(`Mismatched ${context.funcName}`, token); - } - }); - - const chooseStyle = (group, style) => { - switch (style.level) { - case StyleLevel.DISPLAY: // 0 - return group.display; - case StyleLevel.TEXT: // 1 - return group.text; - case StyleLevel.SCRIPT: // 2 - return group.script; - case StyleLevel.SCRIPTSCRIPT: // 3 - return group.scriptscript; - default: - return group.text; - } - }; - - defineFunction({ - type: "mathchoice", - names: ["\\mathchoice"], - props: { - numArgs: 4, - primitive: true - }, - handler: ({ parser }, args) => { - return { - type: "mathchoice", - mode: parser.mode, - display: ordargument(args[0]), - text: ordargument(args[1]), - script: ordargument(args[2]), - scriptscript: ordargument(args[3]) - }; - }, - mathmlBuilder: (group, style) => { - const body = chooseStyle(group, style); - return buildExpressionRow(body, style); - } - }); - - const textAtomTypes = ["text", "textord", "mathord", "atom"]; - - function mathmlBuilder$3(group, style) { - let node; - const inner = buildExpression(group.body, style); - - if (group.mclass === "minner") { - node = new mathMLTree.MathNode("mpadded", inner); - } else if (group.mclass === "mord") { - if (group.isCharacterBox || inner[0].type === "mathord") { - node = inner[0]; - node.type = "mi"; - } else { - node = new mathMLTree.MathNode("mi", inner); - } - } else { - if (group.mustPromote) { - node = inner[0]; - node.type = "mo"; - if (group.isCharacterBox && group.body[0].text && /[A-Za-z]/.test(group.body[0].text)) { - node.setAttribute("mathvariant", "italic"); - } - } else { - node = new mathMLTree.MathNode("mo", inner); - } - - // Set spacing based on what is the most likely adjacent atom type. - // See TeXbook p170. - const doSpacing = style.level < 2; // Operator spacing is zero inside a (sub|super)script. - if (group.mclass === "mbin") { - // medium space - node.attributes.lspace = (doSpacing ? "0.2222em" : "0"); - node.attributes.rspace = (doSpacing ? "0.2222em" : "0"); - } else if (group.mclass === "mrel") { - // thickspace - node.attributes.lspace = (doSpacing ? "0.2778em" : "0"); - node.attributes.rspace = (doSpacing ? "0.2778em" : "0"); - } else if (group.mclass === "mpunct") { - node.attributes.lspace = "0em"; - node.attributes.rspace = (doSpacing ? "0.1667em" : "0"); - } else if (group.mclass === "mopen" || group.mclass === "mclose") { - node.attributes.lspace = "0em"; - node.attributes.rspace = "0em"; - } else if (group.mclass === "minner" && doSpacing) { - node.attributes.lspace = "0.0556em"; // 1 mu is the most likely option - node.attributes.width = "+0.1111em"; - } - if (!(group.mclass === "mopen" || group.mclass === "mclose")) { - delete node.attributes.stretchy; - delete node.attributes.form; - } - } - return node; - } - - // Math class commands except \mathop - defineFunction({ - type: "mclass", - names: [ - "\\mathord", - "\\mathbin", - "\\mathrel", - "\\mathopen", - "\\mathclose", - "\\mathpunct", - "\\mathinner" - ], - props: { - numArgs: 1, - primitive: true - }, - handler({ parser, funcName }, args) { - const body = args[0]; - const isCharacterBox = utils.isCharacterBox(body); - // We should not wrap a around a or . That would be invalid MathML. - // In that case, we instead promote the text contents of the body to the parent. - let mustPromote = true; - const mord = { type: "mathord", text: "", mode: parser.mode }; - const arr = (body.body) ? body.body : [body]; - for (const arg of arr) { - if (textAtomTypes.includes(arg.type)) { - if (arg.text) { - mord.text += arg.text; - } else if (arg.body) { - arg.body.map(e => { mord.text += e.text; }); - } - } else { - mustPromote = false; - break - } - } - return { - type: "mclass", - mode: parser.mode, - mclass: "m" + funcName.slice(5), - body: ordargument(mustPromote ? mord : body), - isCharacterBox, - mustPromote - }; - }, - mathmlBuilder: mathmlBuilder$3 - }); - - const binrelClass = (arg) => { - // \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument. - // (by rendering separately and with {}s before and after, and measuring - // the change in spacing). We'll do roughly the same by detecting the - // atom type directly. - const atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg; - if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) { - return "m" + atom.family; - } else { - return "mord"; - } - }; - - // \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord. - // This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX. - defineFunction({ - type: "mclass", - names: ["\\@binrel"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "mclass", - mode: parser.mode, - mclass: binrelClass(args[0]), - body: ordargument(args[1]), - isCharacterBox: utils.isCharacterBox(args[1]) - }; - } - }); - - // Build a relation or stacked op by placing one symbol on top of another - defineFunction({ - type: "mclass", - names: ["\\stackrel", "\\overset", "\\underset"], - props: { - numArgs: 2 - }, - handler({ parser, funcName }, args) { - const baseArg = args[1]; - const shiftedArg = args[0]; - - const baseOp = { - type: "op", - mode: baseArg.mode, - limits: true, - alwaysHandleSupSub: true, - parentIsSupSub: false, - symbol: false, - stack: true, - suppressBaseShift: funcName !== "\\stackrel", - body: ordargument(baseArg) - }; - - return { - type: "supsub", - mode: shiftedArg.mode, - base: baseOp, - sup: funcName === "\\underset" ? null : shiftedArg, - sub: funcName === "\\underset" ? shiftedArg : null - }; - }, - mathmlBuilder: mathmlBuilder$3 - }); - - // Helper function - const buildGroup = (el, style, noneNode) => { - if (!el) { return noneNode } - const node = buildGroup$1(el, style); - if (node.type === "mrow" && node.children.length === 0) { return noneNode } - return node - }; - - defineFunction({ - type: "multiscript", - names: ["\\sideset", "\\pres@cript"], // See macros.js for \prescript - props: { - numArgs: 3 - }, - handler({ parser, funcName, token }, args) { - if (args[2].body.length === 0) { - throw new ParseError(funcName + `cannot parse an empty base.`) - } - const base = args[2].body[0]; - if (parser.settings.strict && funcName === "\\sideset" && !base.symbol) { - throw new ParseError(`The base of \\sideset must be a big operator. Try \\prescript.`) - } - - if ((args[0].body.length > 0 && args[0].body[0].type !== "supsub") || - (args[1].body.length > 0 && args[1].body[0].type !== "supsub")) { - throw new ParseError("\\sideset can parse only subscripts and " + - "superscripts in its first two arguments", token) - } - - // The prescripts and postscripts come wrapped in a supsub. - const prescripts = args[0].body.length > 0 ? args[0].body[0] : null; - const postscripts = args[1].body.length > 0 ? args[1].body[0] : null; - - if (!prescripts && !postscripts) { - return base - } else if (!prescripts) { - // It's not a multi-script. Get a \textstyle supsub. - return { - type: "styling", - mode: parser.mode, - scriptLevel: "text", - body: [{ - type: "supsub", - mode: parser.mode, - base, - sup: postscripts.sup, - sub: postscripts.sub - }] - } - } else { - return { - type: "multiscript", - mode: parser.mode, - isSideset: funcName === "\\sideset", - prescripts, - postscripts, - base - } - } - }, - mathmlBuilder(group, style) { - const base = buildGroup$1(group.base, style); - - const prescriptsNode = new mathMLTree.MathNode("mprescripts"); - const noneNode = new mathMLTree.MathNode("none"); - let children = []; - - const preSub = buildGroup(group.prescripts.sub, style, noneNode); - const preSup = buildGroup(group.prescripts.sup, style, noneNode); - if (group.isSideset) { - // This seems silly, but LaTeX does this. Firefox ignores it, which does not make me sad. - preSub.setAttribute("style", "text-align: left;"); - preSup.setAttribute("style", "text-align: left;"); - } - - if (group.postscripts) { - const postSub = buildGroup(group.postscripts.sub, style, noneNode); - const postSup = buildGroup(group.postscripts.sup, style, noneNode); - children = [base, postSub, postSup, prescriptsNode, preSub, preSup]; - } else { - children = [base, prescriptsNode, preSub, preSup]; - } - - return new mathMLTree.MathNode("mmultiscripts", children); - } - }); - - defineFunction({ - type: "not", - names: ["\\not"], - props: { - numArgs: 1, - primitive: true, - allowedInText: false - }, - handler({ parser }, args) { - const isCharacterBox = utils.isCharacterBox(args[0]); - let body; - if (isCharacterBox) { - body = ordargument(args[0]); - if (body[0].text.charAt(0) === "\\") { - body[0].text = symbols.math[body[0].text].replace; - } - // \u0338 is the Unicode Combining Long Solidus Overlay - body[0].text = body[0].text.slice(0, 1) + "\u0338" + body[0].text.slice(1); - } else { - // When the argument is not a character box, TeX does an awkward, poorly placed overlay. - // We'll do the same. - const notNode = { type: "textord", mode: "math", text: "\u0338" }; - const kernNode = { type: "kern", mode: "math", dimension: { number: -0.6, unit: "em" } }; - body = [notNode, kernNode, args[0]]; - } - return { - type: "not", - mode: parser.mode, - body, - isCharacterBox - }; - }, - mathmlBuilder(group, style) { - if (group.isCharacterBox) { - const inner = buildExpression(group.body, style); - return inner[0] - } else { - return buildExpressionRow(group.body, style, true) - } - } - }); - - // Limits, symbols - - // Some helpers - - const ordAtomTypes = ["textord", "mathord", "atom"]; - - // Most operators have a large successor symbol, but these don't. - const noSuccessor = ["\\smallint"]; - - // Math operators (e.g. \sin) need a space between these types and themselves: - const ordTypes = ["textord", "mathord", "ordgroup", "close", "leftright"]; - - const dels = ["}", "\\left", "\\middle", "\\right"]; - const isDelimiter = str => str.length > 0 && - (delimiters.includes(str) || delimiterSizes[str] || dels.includes(str)); - - // NOTE: Unlike most `builders`s, this one handles not only "op", but also - // "supsub" since some of them (like \int) can affect super/subscripting. - - const mathmlBuilder$2 = (group, style) => { - let node; - - if (group.symbol) { - // This is a symbol. Just add the symbol. - node = new MathNode("mo", [makeText(group.name, group.mode)]); - if (utils.contains(noSuccessor, group.name)) { - node.setAttribute("largeop", "false"); - } else { - node.setAttribute("movablelimits", "false"); - } - } else if (group.body) { - // This is an operator with children. Add them. - node = new MathNode("mo", buildExpression(group.body, style)); - } else { - // This is a text operator. Add all of the characters from the operator's name. - node = new MathNode("mi", [new TextNode(group.name.slice(1))]); - - if (!group.parentIsSupSub) { - // Append an invisible . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new MathNode("mo", [makeText("\u2061", "text")]); - node = new MathNode("mpadded", [node, operator]); - const lSpace = group.needsLeadingSpace ? 0.1667 : 0; - const rSpace = group.isFollowedByDelimiter ? 0 : 0.1666; - if (group.needsLeadingSpace) { - node.setAttribute("lspace", "0.1667em"); // thin space. - } - if ((lSpace + rSpace) > 0) { - node.setAttribute("width", `+${lSpace + rSpace}em`); - } - } - } - - return node; - }; - - const singleCharBigOps = { - "\u220F": "\\prod", - "\u2210": "\\coprod", - "\u2211": "\\sum", - "\u22c0": "\\bigwedge", - "\u22c1": "\\bigvee", - "\u22c2": "\\bigcap", - "\u22c3": "\\bigcup", - "\u2a00": "\\bigodot", - "\u2a01": "\\bigoplus", - "\u2a02": "\\bigotimes", - "\u2a04": "\\biguplus", - "\u2a05": "\\bigsqcap", - "\u2a06": "\\bigsqcup" - }; - - defineFunction({ - type: "op", - names: [ - "\\coprod", - "\\bigvee", - "\\bigwedge", - "\\biguplus", - "\\bigcap", - "\\bigcup", - "\\intop", - "\\prod", - "\\sum", - "\\bigotimes", - "\\bigoplus", - "\\bigodot", - "\\bigsqcap", - "\\bigsqcup", - "\\smallint", - "\u220F", - "\u2210", - "\u2211", - "\u22c0", - "\u22c1", - "\u22c2", - "\u22c3", - "\u2a00", - "\u2a01", - "\u2a02", - "\u2a04", - "\u2a06" - ], - props: { - numArgs: 0 - }, - handler: ({ parser, funcName }, args) => { - let fName = funcName; - if (fName.length === 1) { - fName = singleCharBigOps[fName]; - } - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: true, - stack: false, // This is true for \stackrel{}, not here. - name: fName - }; - }, - mathmlBuilder: mathmlBuilder$2 - }); - - // Note: calling defineFunction with a type that's already been defined only - // works because the same mathmlBuilder is being used. - defineFunction({ - type: "op", - names: ["\\mathop"], - props: { - numArgs: 1, - primitive: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - // It would be convienient to just wrap a around the argument. - // But if the argument is a or , that would be invalid MathML. - // In that case, we instead promote the text contents of the body to the parent. - const arr = (body.body) ? body.body : [body]; - const isSymbol = arr.length === 1 && ordAtomTypes.includes(arr[0].type); - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: isSymbol, - stack: false, - name: isSymbol ? arr[0].text : null, - body: isSymbol ? null : ordargument(body) - }; - }, - mathmlBuilder: mathmlBuilder$2 - }); - - // There are 2 flags for operators; whether they produce limits in - // displaystyle, and whether they are symbols and should grow in - // displaystyle. These four groups cover the four possible choices. - - const singleCharIntegrals = { - "\u222b": "\\int", - "\u222c": "\\iint", - "\u222d": "\\iiint", - "\u222e": "\\oint", - "\u222f": "\\oiint", - "\u2230": "\\oiiint", - "\u2231": "\\intclockwise", - "\u2232": "\\varointclockwise", - "\u2a0c": "\\iiiint", - "\u2a0d": "\\intbar", - "\u2a0e": "\\intBar", - "\u2a0f": "\\fint", - "\u2a12": "\\rppolint", - "\u2a13": "\\scpolint", - "\u2a15": "\\pointint", - "\u2a16": "\\sqint", - "\u2a17": "\\intlarhk", - "\u2a18": "\\intx", - "\u2a19": "\\intcap", - "\u2a1a": "\\intcup" - }; - - // No limits, not symbols - defineFunction({ - type: "op", - names: [ - "\\arcsin", - "\\arccos", - "\\arctan", - "\\arctg", - "\\arcctg", - "\\arg", - "\\ch", - "\\cos", - "\\cosec", - "\\cosh", - "\\cot", - "\\cotg", - "\\coth", - "\\csc", - "\\ctg", - "\\cth", - "\\deg", - "\\dim", - "\\exp", - "\\hom", - "\\ker", - "\\lg", - "\\ln", - "\\log", - "\\sec", - "\\sin", - "\\sinh", - "\\sh", - "\\sgn", - "\\tan", - "\\tanh", - "\\tg", - "\\th" - ], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - const prevAtomType = parser.prevAtomType; - const next = parser.gullet.future().text; - return { - type: "op", - mode: parser.mode, - limits: false, - parentIsSupSub: false, - symbol: false, - stack: false, - isFollowedByDelimiter: isDelimiter(next), - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType), - name: funcName - }; - }, - mathmlBuilder: mathmlBuilder$2 - }); - - // Limits, not symbols - defineFunction({ - type: "op", - names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - const prevAtomType = parser.prevAtomType; - const next = parser.gullet.future().text; - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: false, - stack: false, - isFollowedByDelimiter: isDelimiter(next), - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType), - name: funcName - }; - }, - mathmlBuilder: mathmlBuilder$2 - }); - - // No limits, symbols - defineFunction({ - type: "op", - names: [ - "\\int", - "\\iint", - "\\iiint", - "\\iiiint", - "\\oint", - "\\oiint", - "\\oiiint", - "\\intclockwise", - "\\varointclockwise", - "\\intbar", - "\\intBar", - "\\fint", - "\\rppolint", - "\\scpolint", - "\\pointint", - "\\sqint", - "\\intlarhk", - "\\intx", - "\\intcap", - "\\intcup", - "\u222b", - "\u222c", - "\u222d", - "\u222e", - "\u222f", - "\u2230", - "\u2231", - "\u2232", - "\u2a0c", - "\u2a0d", - "\u2a0e", - "\u2a0f", - "\u2a12", - "\u2a13", - "\u2a15", - "\u2a16", - "\u2a17", - "\u2a18", - "\u2a19", - "\u2a1a" - ], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - let fName = funcName; - if (fName.length === 1) { - fName = singleCharIntegrals[fName]; - } - return { - type: "op", - mode: parser.mode, - limits: false, - parentIsSupSub: false, - symbol: true, - stack: false, - name: fName - }; - }, - mathmlBuilder: mathmlBuilder$2 - }); - - /** - * All registered global/built-in macros. - * `macros.js` exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary via `macros.js`. - */ - const _macros = {}; - - // This function might one day accept an additional argument and do more things. - function defineMacro(name, body) { - _macros[name] = body; - } - - // NOTE: Unlike most builders, this one handles not only - // "operatorname", but also "supsub" since \operatorname* can - // affect super/subscripting. - - const mathmlBuilder$1 = (group, style) => { - let expression = buildExpression(group.body, style.withFont("mathrm")); - - // Is expression a string or has it something like a fraction? - let isAllString = true; // default - for (let i = 0; i < expression.length; i++) { - const node = expression[i]; - if (node instanceof mathMLTree.MathNode) { - switch (node.type) { - case "mi": - case "mn": - case "ms": - case "mtext": - break; // Do nothing yet. - case "mspace": - { - if (node.attributes.width) { - const width = node.attributes.width.replace("em", ""); - const ch = spaceCharacter(Number(width)); - if (ch === "") { - isAllString = false; - } else { - expression[i] = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode(ch)]); - } - } - } - break - case "mo": { - const child = node.children[0]; - if (node.children.length === 1 && child instanceof mathMLTree.TextNode) { - child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*"); - } else { - isAllString = false; - } - break - } - default: - isAllString = false; - } - } else { - isAllString = false; - } - } - - if (isAllString) { - // Write a single TextNode instead of multiple nested tags. - const word = expression.map((node) => node.toText()).join(""); - expression = [new mathMLTree.TextNode(word)]; - } else if ( - expression.length === 1 - && utils.contains(["mover", "munder"], expression[0].type) && - (expression[0].children[0].type === "mi" || expression[0].children[0].type === "mtext") - ) { - expression[0].children[0].type = "mi"; - if (group.parentIsSupSub) { - return new mathMLTree.MathNode("mrow", expression) - } else { - const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); - return mathMLTree.newDocumentFragment([expression[0], operator]) - } - } - - let wrapper; - if (isAllString) { - wrapper = new mathMLTree.MathNode("mi", expression); - wrapper.setAttribute("mathvariant", "normal"); - } else { - wrapper = new mathMLTree.MathNode("mrow", expression); - } - - if (!group.parentIsSupSub) { - // Append an . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); - if (group.needsLeadingSpace) { - // LaTeX gives operator spacing, but a gets ord spacing. - // So add a leading space. - const space = new mathMLTree.MathNode("mspace"); - space.setAttribute("width", "0.1667em"); // thin space. - return mathMLTree.newDocumentFragment([space, wrapper, operator]) - } else { - return mathMLTree.newDocumentFragment([wrapper, operator]) - } - } - - return wrapper - }; - - // \operatorname - // amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@ - defineFunction({ - type: "operatorname", - names: ["\\operatorname@", "\\operatornamewithlimits"], - props: { - numArgs: 1, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const body = args[0]; - const prevAtomType = parser.prevAtomType; - return { - type: "operatorname", - mode: parser.mode, - body: ordargument(body), - alwaysHandleSupSub: (funcName === "\\operatornamewithlimits"), - limits: false, - parentIsSupSub: false, - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType) - }; - }, - mathmlBuilder: mathmlBuilder$1 - }); - - defineMacro("\\operatorname", - "\\@ifstar\\operatornamewithlimits\\operatorname@"); - - defineFunctionBuilders({ - type: "ordgroup", - mathmlBuilder(group, style) { - return buildExpressionRow(group.body, style, true); - } - }); - - defineFunction({ - type: "overline", - names: ["\\overline"], - props: { - numArgs: 1 - }, - handler({ parser }, args) { - const body = args[0]; - return { - type: "overline", - mode: parser.mode, - body - }; - }, - mathmlBuilder(group, style) { - const operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u005F")]); - operator.setAttribute("stretchy", "true"); - - const node = new mathMLTree.MathNode( - "mover", - [buildGroup$1(group.body, style), operator] - ); - node.setAttribute("accent", "true"); - - return node; - } - }); - - defineFunction({ - type: "phantom", - names: ["\\phantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "phantom", - mode: parser.mode, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(group.body, style); - return new mathMLTree.MathNode("mphantom", inner); - } - }); - - defineFunction({ - type: "hphantom", - names: ["\\hphantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "hphantom", - mode: parser.mode, - body - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(ordargument(group.body), style); - const phantom = new mathMLTree.MathNode("mphantom", inner); - const node = new mathMLTree.MathNode("mpadded", [phantom]); - node.setAttribute("height", "0px"); - node.setAttribute("depth", "0px"); - return node; - } - }); - - defineFunction({ - type: "vphantom", - names: ["\\vphantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "vphantom", - mode: parser.mode, - body - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(ordargument(group.body), style); - const phantom = new mathMLTree.MathNode("mphantom", inner); - const node = new mathMLTree.MathNode("mpadded", [phantom]); - node.setAttribute("width", "0px"); - return node; - } - }); - - // \pmb is a simulation of bold font. - // The version of \pmb in ambsy.sty works by typesetting three copies of the argument - // with small offsets. We use CSS text-shadow. - // It's a hack. Not as good as a real bold font. Better than nothing. - - defineFunction({ - type: "pmb", - names: ["\\pmb"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "pmb", - mode: parser.mode, - body: ordargument(args[0]) - } - }, - mathmlBuilder(group, style) { - const inner = buildExpression(group.body, style); - // Wrap with an element. - const node = wrapWithMstyle(inner); - node.setAttribute("style", "text-shadow: 0.02em 0.01em 0.04px"); - return node - } - }); - - const sign = num => num >= 0 ? "+" : "-"; - - // \raise, \lower, and \raisebox - - const mathmlBuilder = (group, style) => { - const newStyle = style.withLevel(StyleLevel.TEXT); - const node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, newStyle)]); - const dy = calculateSize(group.dy, style); - node.setAttribute("voffset", dy.number + dy.unit); - const dyAbs = Math.abs(dy.number); - node.setAttribute("height", sign(dy.number) + dyAbs + dy.unit); - node.setAttribute("depth", sign(-dy.number) + dyAbs + dy.unit); - return node - }; - - defineFunction({ - type: "raise", - names: ["\\raise", "\\lower"], - props: { - numArgs: 2, - argTypes: ["size", "primitive"], - primitive: true - }, - handler({ parser, funcName }, args) { - const amount = assertNodeType(args[0], "size").value; - if (funcName === "\\lower") { amount.number *= -1; } - const body = args[1]; - return { - type: "raise", - mode: parser.mode, - dy: amount, - body - }; - }, - mathmlBuilder - }); - - - defineFunction({ - type: "raise", - names: ["\\raisebox"], - props: { - numArgs: 2, - argTypes: ["size", "hbox"], - allowedInText: true - }, - handler({ parser, funcName }, args) { - const amount = assertNodeType(args[0], "size").value; - const body = args[1]; - return { - type: "raise", - mode: parser.mode, - dy: amount, - body - }; - }, - mathmlBuilder - }); - - defineFunction({ - type: "ref", - names: ["\\ref", "\\eqref"], - props: { - numArgs: 1, - argTypes: ["raw"] - }, - handler({ parser, funcName }, args) { - return { - type: "ref", - mode: parser.mode, - funcName, - string: args[0].string.replace(invalidIdRegEx, "") - }; - }, - mathmlBuilder(group, style) { - // Create an empty text node. Set a class and an href. - // The post-processor will populate with the target's tag or equation number. - const classes = group.funcName === "\\ref" ? ["tml-ref"] : ["tml-ref", "tml-eqref"]; - const node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("")], classes); - node.setAttribute("href", "#" + group.string); - return node - } - }); - - defineFunction({ - type: "internal", - names: ["\\relax"], - props: { - numArgs: 0, - allowedInText: true - }, - handler({ parser }) { - return { - type: "internal", - mode: parser.mode - }; - } - }); - - defineFunction({ - type: "rule", - names: ["\\rule"], - props: { - numArgs: 2, - numOptionalArgs: 1, - argTypes: ["size", "size", "size"] - }, - handler({ parser }, args, optArgs) { - const shift = optArgs[0]; - const width = assertNodeType(args[0], "size"); - const height = assertNodeType(args[1], "size"); - return { - type: "rule", - mode: parser.mode, - shift: shift && assertNodeType(shift, "size").value, - width: width.value, - height: height.value - }; - }, - mathmlBuilder(group, style) { - const width = calculateSize(group.width, style); - const height = calculateSize(group.height, style); - const shift = group.shift - ? calculateSize(group.shift, style) - : { number: 0, unit: "em" }; - const color = (style.color && style.getColor()) || "black"; - - const rule = new mathMLTree.MathNode("mspace"); - if (width.number > 0 && height.number > 0) { - rule.setAttribute("mathbackground", color); - } - rule.setAttribute("width", width.number + width.unit); - rule.setAttribute("height", height.number + height.unit); - if (shift.number === 0) { return rule } - - const wrapper = new mathMLTree.MathNode("mpadded", [rule]); - if (shift.number >= 0) { - wrapper.setAttribute("height", "+" + shift.number + shift.unit); - } else { - wrapper.setAttribute("height", shift.number + shift.unit); - wrapper.setAttribute("depth", "+" + -shift.number + shift.unit); - } - wrapper.setAttribute("voffset", shift.number + shift.unit); - return wrapper; - } - }); - - // The size mappings are taken from TeX with \normalsize=10pt. - // We don't have to track script level. MathML does that. - const sizeMap = { - "\\tiny": 0.5, - "\\sixptsize": 0.6, - "\\Tiny": 0.6, - "\\scriptsize": 0.7, - "\\footnotesize": 0.8, - "\\small": 0.9, - "\\normalsize": 1.0, - "\\large": 1.2, - "\\Large": 1.44, - "\\LARGE": 1.728, - "\\huge": 2.074, - "\\Huge": 2.488 - }; - - defineFunction({ - type: "sizing", - names: [ - "\\tiny", - "\\sixptsize", - "\\Tiny", - "\\scriptsize", - "\\footnotesize", - "\\small", - "\\normalsize", - "\\large", - "\\Large", - "\\LARGE", - "\\huge", - "\\Huge" - ], - props: { - numArgs: 0, - allowedInText: true - }, - handler: ({ breakOnTokenText, funcName, parser }, args) => { - if (parser.settings.strict && parser.mode === "math") { - // eslint-disable-next-line no-console - console.log(`Temml strict-mode warning: Command ${funcName} is invalid in math mode.`); - } - const body = parser.parseExpression(false, breakOnTokenText); - return { - type: "sizing", - mode: parser.mode, - funcName, - body - }; - }, - mathmlBuilder: (group, style) => { - const newStyle = style.withFontSize(sizeMap[group.funcName]); - const inner = buildExpression(group.body, newStyle); - // Wrap with an element. - const node = wrapWithMstyle(inner); - const factor = (sizeMap[group.funcName] / style.fontSize).toFixed(4); - node.setAttribute("mathsize", factor + "em"); - return node; - } - }); - - // smash, with optional [tb], as in AMS - - defineFunction({ - type: "smash", - names: ["\\smash"], - props: { - numArgs: 1, - numOptionalArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args, optArgs) => { - let smashHeight = false; - let smashDepth = false; - const tbArg = optArgs[0] && assertNodeType(optArgs[0], "ordgroup"); - if (tbArg) { - // Optional [tb] argument is engaged. - // ref: amsmath: \renewcommand{\smash}[1][tb]{% - // def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}% - let letter = ""; - for (let i = 0; i < tbArg.body.length; ++i) { - const node = tbArg.body[i]; - // TODO: Write an AssertSymbolNode - letter = node.text; - if (letter === "t") { - smashHeight = true; - } else if (letter === "b") { - smashDepth = true; - } else { - smashHeight = false; - smashDepth = false; - break; - } - } - } else { - smashHeight = true; - smashDepth = true; - } - - const body = args[0]; - return { - type: "smash", - mode: parser.mode, - body, - smashHeight, - smashDepth - }; - }, - mathmlBuilder: (group, style) => { - const node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, style)]); - - if (group.smashHeight) { - node.setAttribute("height", "0px"); - } - - if (group.smashDepth) { - node.setAttribute("depth", "0px"); - } - - return node; - } - }); - - defineFunction({ - type: "sqrt", - names: ["\\sqrt"], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser }, args, optArgs) { - const index = optArgs[0]; - const body = args[0]; - return { - type: "sqrt", - mode: parser.mode, - body, - index - }; - }, - mathmlBuilder(group, style) { - const { body, index } = group; - return index - ? new mathMLTree.MathNode("mroot", [ - buildGroup$1(body, style), - buildGroup$1(index, style.incrementLevel()) - ]) - : new mathMLTree.MathNode("msqrt", [buildGroup$1(body, style)]); - } - }); - - const styleMap = { - display: 0, - text: 1, - script: 2, - scriptscript: 3 - }; - - const styleAttributes = { - display: ["0", "true"], - text: ["0", "false"], - script: ["1", "false"], - scriptscript: ["2", "false"] - }; - - defineFunction({ - type: "styling", - names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ breakOnTokenText, funcName, parser }, args) { - // parse out the implicit body - const body = parser.parseExpression(true, breakOnTokenText); - - const scriptLevel = funcName.slice(1, funcName.length - 5); - return { - type: "styling", - mode: parser.mode, - // Figure out what scriptLevel to use by pulling out the scriptLevel from - // the function name - scriptLevel, - body - }; - }, - mathmlBuilder(group, style) { - // Figure out what scriptLevel we're changing to. - const newStyle = style.withLevel(styleMap[group.scriptLevel]); - // The style argument in the next line does NOT directly set a MathML script level. - // It just tracks the style level, in case we need to know it for supsub or mathchoice. - const inner = buildExpression(group.body, newStyle); - // Wrap with an element. - const node = wrapWithMstyle(inner); - - const attr = styleAttributes[group.scriptLevel]; - - // Here is where we set the MathML script level. - node.setAttribute("scriptlevel", attr[0]); - node.setAttribute("displaystyle", attr[1]); - - return node; - } - }); - - /** - * Sometimes, groups perform special rules when they have superscripts or - * subscripts attached to them. This function lets the `supsub` group know that - * Sometimes, groups perform special rules when they have superscripts or - * its inner element should handle the superscripts and subscripts instead of - * handling them itself. - */ - - // Helpers - const symbolRegEx = /^m(over|under|underover)$/; - - // Super scripts and subscripts, whose precise placement can depend on other - // functions that precede them. - defineFunctionBuilders({ - type: "supsub", - mathmlBuilder(group, style) { - // Is the inner group a relevant horizonal brace? - let isBrace = false; - let isOver; - let isSup; - let appendApplyFunction = false; - let needsLeadingSpace = false; - - if (group.base && group.base.type === "horizBrace") { - isSup = !!group.sup; - if (isSup === group.base.isOver) { - isBrace = true; - isOver = group.base.isOver; - } - } - - if (group.base && !group.base.stack && - (group.base.type === "op" || group.base.type === "operatorname")) { - group.base.parentIsSupSub = true; - appendApplyFunction = !group.base.symbol; - needsLeadingSpace = group.base.needsLeadingSpace; - } - - const children = group.base && group.base.stack - ? [buildGroup$1(group.base.body[0], style)] - : [buildGroup$1(group.base, style)]; - - const childStyle = style.inSubOrSup(); - if (group.sub) { - children.push(buildGroup$1(group.sub, childStyle)); - } - - if (group.sup) { - children.push(buildGroup$1(group.sup, childStyle)); - } - - let nodeType; - if (isBrace) { - nodeType = isOver ? "mover" : "munder"; - } else if (!group.sub) { - const base = group.base; - if ( - base && - base.type === "op" && - base.limits && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "mover"; - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (base.limits || style.level === StyleLevel.DISPLAY) - ) { - nodeType = "mover"; - } else { - nodeType = "msup"; - } - } else if (!group.sup) { - const base = group.base; - if ( - base && - base.type === "op" && - base.limits && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "munder"; - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (base.limits || style.level === StyleLevel.DISPLAY) - ) { - nodeType = "munder"; - } else { - nodeType = "msub"; - } - } else { - const base = group.base; - if (base && ((base.type === "op" && base.limits) || base.type === "multiscript") && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "munderover"; - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (style.level === StyleLevel.DISPLAY || base.limits) - ) { - nodeType = "munderover"; - } else { - nodeType = "msubsup"; - } - } - - let node = new mathMLTree.MathNode(nodeType, children); - if (appendApplyFunction) { - // Append an . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); - if (needsLeadingSpace) { - const space = new mathMLTree.MathNode("mspace"); - space.setAttribute("width", "0.1667em"); // thin space. - node = mathMLTree.newDocumentFragment([space, node, operator]); - } else { - node = mathMLTree.newDocumentFragment([node, operator]); - } - } else if (symbolRegEx.test(nodeType)) { - // Wrap in a . Otherwise Firefox stretchy parens will not stretch to include limits. - node = new mathMLTree.MathNode("mrow", [node]); - } - - return node - } - }); - - // Operator ParseNodes created in Parser.js from symbol Groups in src/symbols.js. - - const short = ["\\shortmid", "\\nshortmid", "\\shortparallel", - "\\nshortparallel", "\\smallsetminus"]; - - defineFunctionBuilders({ - type: "atom", - mathmlBuilder(group, style) { - const node = new mathMLTree.MathNode("mo", [makeText(group.text, group.mode)]); - if (group.family === "punct") { - node.setAttribute("separator", "true"); - } else if (group.family === "open" || group.family === "close") { - // Delims built here should not stretch vertically. - // See delimsizing.js for stretchy delims. - if (group.family === "open") { - node.setAttribute("form", "prefix"); - // Set an explicit attribute for stretch. Otherwise Firefox may do it wrong. - node.setAttribute("stretchy", "false"); - } else if (group.family === "close") { - node.setAttribute("form", "postfix"); - node.setAttribute("stretchy", "false"); - } - } else if (group.text === "\\mid") { - // Firefox messes up this spacing if at the end of an . See it explicitly. - node.setAttribute("lspace", "0.22em"); // medium space - node.setAttribute("rspace", "0.22em"); - node.setAttribute("stretchy", "false"); - } else if (short.includes(group.text)) { - node.setAttribute("mathsize", "70%"); - } else if (group.text === ":") { - // ":" is not in the MathML operator dictionary. Give it BIN spacing. - node.attributes.lspace = "0.2222em"; - node.attributes.rspace = "0.2222em"; - } - return node; - } - }); - - /** - * Maps TeX font commands to "mathvariant" attribute in buildMathML.js - */ - const fontMap = { - // styles - mathbf: "bold", - mathrm: "normal", - textit: "italic", - mathit: "italic", - mathnormal: "italic", - - // families - mathbb: "double-struck", - mathcal: "script", - mathfrak: "fraktur", - mathscr: "script", - mathsf: "sans-serif", - mathtt: "monospace", - oldstylenums: "oldstylenums" - }; - - /** - * Returns the math variant as a string or null if none is required. - */ - const getVariant = function(group, style) { - // Handle font specifiers as best we can. - // Chromium does not support the MathML mathvariant attribute. - // So we'll use Unicode replacement characters instead. - // But first, determine the math variant. - - // Deal with the \textit, \textbf, etc., functions. - if (style.fontFamily === "texttt") { - return "monospace" - } else if (style.fontFamily === "textsc") { - return "normal"; // handled via character substitution in symbolsOrd.js. - } else if (style.fontFamily === "textsf") { - if (style.fontShape === "textit" && style.fontWeight === "textbf") { - return "sans-serif-bold-italic" - } else if (style.fontShape === "textit") { - return "sans-serif-italic" - } else if (style.fontWeight === "textbf") { - return "sans-serif-bold" - } else { - return "sans-serif" - } - } else if (style.fontShape === "textit" && style.fontWeight === "textbf") { - return "bold-italic" - } else if (style.fontShape === "textit") { - return "italic" - } else if (style.fontWeight === "textbf") { - return "bold" - } - - // Deal with the \mathit, mathbf, etc, functions. - const font = style.font; - if (!font || font === "mathnormal") { - return null - } - - const mode = group.mode; - switch (font) { - case "mathit": - return "italic" - case "mathrm": { - const codePoint = group.text.codePointAt(0); - // LaTeX \mathrm returns italic for Greek characters. - return (0x03ab < codePoint && codePoint < 0x03cf) ? "italic" : "normal" - } - case "greekItalic": - return "italic" - case "up@greek": - return "normal" - case "boldsymbol": - case "mathboldsymbol": - return "bold-italic" - case "mathbf": - return "bold" - case "mathbb": - return "double-struck" - case "mathfrak": - return "fraktur" - case "mathscr": - case "mathcal": - return "script" - case "mathsf": - return "sans-serif" - case "mathtt": - return "monospace" - case "oldstylenums": - return "oldstylenums" - } - - let text = group.text; - if (symbols[mode][text] && symbols[mode][text].replace) { - text = symbols[mode][text].replace; - } - - return Object.prototype.hasOwnProperty.call(fontMap, font) ? fontMap[font] : null - }; - - // Chromium does not support the MathML `mathvariant` attribute. - // Instead, we replace ASCII characters with Unicode characters that - // are defined in the font as bold, italic, double-struck, etc. - // This module identifies those Unicode code points. - - // First, a few helpers. - const script = Object.freeze({ - B: 0x20EA, // Offset from ASCII B to Unicode script B - E: 0x20EB, - F: 0x20EB, - H: 0x20C3, - I: 0x20C7, - L: 0x20C6, - M: 0x20E6, - R: 0x20C9, - e: 0x20CA, - g: 0x20A3, - o: 0x20C5 - }); - - const frak = Object.freeze({ - C: 0x20EA, - H: 0x20C4, - I: 0x20C8, - R: 0x20CA, - Z: 0x20CE - }); - - const bbb = Object.freeze({ - C: 0x20BF, // blackboard bold - H: 0x20C5, - N: 0x20C7, - P: 0x20C9, - Q: 0x20C9, - R: 0x20CB, - Z: 0x20CA - }); - - const bold = Object.freeze({ - "\u03f5": 0x1D2E7, // lunate epsilon - "\u03d1": 0x1D30C, // vartheta - "\u03f0": 0x1D2EE, // varkappa - "\u03c6": 0x1D319, // varphi - "\u03f1": 0x1D2EF, // varrho - "\u03d6": 0x1D30B // varpi - }); - - const boldItalic = Object.freeze({ - "\u03f5": 0x1D35B, // lunate epsilon - "\u03d1": 0x1D380, // vartheta - "\u03f0": 0x1D362, // varkappa - "\u03c6": 0x1D38D, // varphi - "\u03f1": 0x1D363, // varrho - "\u03d6": 0x1D37F // varpi - }); - - const boldsf = Object.freeze({ - "\u03f5": 0x1D395, // lunate epsilon - "\u03d1": 0x1D3BA, // vartheta - "\u03f0": 0x1D39C, // varkappa - "\u03c6": 0x1D3C7, // varphi - "\u03f1": 0x1D39D, // varrho - "\u03d6": 0x1D3B9 // varpi - }); - - const bisf = Object.freeze({ - "\u03f5": 0x1D3CF, // lunate epsilon - "\u03d1": 0x1D3F4, // vartheta - "\u03f0": 0x1D3D6, // varkappa - "\u03c6": 0x1D401, // varphi - "\u03f1": 0x1D3D7, // varrho - "\u03d6": 0x1D3F3 // varpi - }); - - // Code point offsets below are derived from https://www.unicode.org/charts/PDF/U1D400.pdf - const offset = Object.freeze({ - upperCaseLatin: { // A-Z - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D3BF }, - "italic": ch => { return 0x1D3F3 }, - "bold-italic": ch => { return 0x1D427 }, - "script": ch => { return script[ch] || 0x1D45B }, - "script-bold": ch => { return 0x1D48F }, - "fraktur": ch => { return frak[ch] || 0x1D4C3 }, - "fraktur-bold": ch => { return 0x1D52B }, - "double-struck": ch => { return bbb[ch] || 0x1D4F7 }, - "sans-serif": ch => { return 0x1D55F }, - "sans-serif-bold": ch => { return 0x1D593 }, - "sans-serif-italic": ch => { return 0x1D5C7 }, - "sans-serif-bold-italic": ch => { return 0x1D63C }, - "monospace": ch => { return 0x1D62F } - }, - lowerCaseLatin: { // a-z - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D3B9 }, - "italic": ch => { return ch === "h" ? 0x20A6 : 0x1D3ED }, - "bold-italic": ch => { return 0x1D421 }, - "script": ch => { return script[ch] || 0x1D455 }, - "script-bold": ch => { return 0x1D489 }, - "fraktur": ch => { return 0x1D4BD }, - "fraktur-bold": ch => { return 0x1D525 }, - "double-struck": ch => { return 0x1D4F1 }, - "sans-serif": ch => { return 0x1D559 }, - "sans-serif-bold": ch => { return 0x1D58D }, - "sans-serif-italic": ch => { return 0x1D5C1 }, - "sans-serif-bold-italic": ch => { return 0x1D5F5 }, - "monospace": ch => { return 0x1D629 } - }, - upperCaseGreek: { // A-Ω ∇ - "normal": ch => { return 0 }, - "bold": ch => { return ch === "∇" ? 0x1B4BA : 0x1D317 }, - "italic": ch => { return ch === "∇" ? 0x1B4F4 : 0x1D351 }, - // \boldsymbol actually returns upright bold for upperCaseGreek - "bold-italic": ch => { return ch === "∇" ? 0x1B4BA : 0x1D317 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - // Unicode has no code points for regular-weight san-serif Greek. Use bold. - "sans-serif": ch => { return ch === "∇" ? 0x1B568 : 0x1D3C5 }, - "sans-serif-bold": ch => { return ch === "∇" ? 0x1B568 : 0x1D3C5 }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return ch === "∇" ? 0x1B5A2 : 0x1D3FF }, - "monospace": ch => { return 0 } - }, - lowerCaseGreek: { // α-ω - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D311 }, - "italic": ch => { return 0x1D34B }, - "bold-italic": ch => { return ch === "\u03d5" ? 0x1D37E : 0x1D385 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - // Unicode has no code points for regular-weight san-serif Greek. Use bold. - "sans-serif": ch => { return 0x1D3BF }, - "sans-serif-bold": ch => { return 0x1D3BF }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return 0x1D3F9 }, - "monospace": ch => { return 0 } - }, - varGreek: { // \varGamma, etc - "normal": ch => { return 0 }, - "bold": ch => { return bold[ch] || -51 }, - "italic": ch => { return 0 }, - "bold-italic": ch => { return boldItalic[ch] || 0x3A }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - "sans-serif": ch => { return boldsf[ch] || 0x74 }, - "sans-serif-bold": ch => { return boldsf[ch] || 0x74 }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return bisf[ch] || 0xAE }, - "monospace": ch => { return 0 } - }, - numeral: { // 0-9 - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D79E }, - "italic": ch => { return 0 }, - "bold-italic": ch => { return 0 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0x1D7A8 }, - "sans-serif": ch => { return 0x1D7B2 }, - "sans-serif-bold": ch => { return 0x1D7BC }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return 0 }, - "monospace": ch => { return 0x1D7C6 } - } - }); - - const variantChar = (ch, variant) => { - const codePoint = ch.codePointAt(0); - const block = 0x40 < codePoint && codePoint < 0x5b - ? "upperCaseLatin" - : 0x60 < codePoint && codePoint < 0x7b - ? "lowerCaseLatin" - : (0x390 < codePoint && codePoint < 0x3AA) || ch === "∇" - ? "upperCaseGreek" - : 0x3B0 < codePoint && codePoint < 0x3CA || ch === "\u03d5" - ? "lowerCaseGreek" - : 0x1D6E1 < codePoint && codePoint < 0x1D6FC || bold[ch] - ? "varGreek" - : (0x2F < codePoint && codePoint < 0x3A) - ? "numeral" - : "other"; - return block === "other" - ? ch - : String.fromCodePoint(codePoint + offset[block][variant](ch)) - }; - - const smallCaps = Object.freeze({ - a: "ᴀ", - b: "ʙ", - c: "ᴄ", - d: "ᴅ", - e: "ᴇ", - f: "ꜰ", - g: "ɢ", - h: "ʜ", - i: "ɪ", - j: "ᴊ", - k: "ᴋ", - l: "ʟ", - m: "ᴍ", - n: "ɴ", - o: "ᴏ", - p: "ᴘ", - q: "ǫ", - r: "ʀ", - s: "s", - t: "ᴛ", - u: "ᴜ", - v: "ᴠ", - w: "ᴡ", - x: "x", - y: "ʏ", - z: "ᴢ" - }); - - // "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in - // src/symbols.js. - - const numberRegEx$1 = /^\d(?:[\d,.]*\d)?$/; // Keep in sync with numberRegEx in Parser.js - - const latinRegEx = /[A-Ba-z]/; - - const italicNumber = (text, variant) => { - const mn = new mathMLTree.MathNode("mn", [text]); - const wrapper = new mathMLTree.MathNode("mstyle", [mn]); - wrapper.style["font-style"] = "italic"; - wrapper.style["font-family"] = "Cambria, 'Times New Roman', serif"; - if (variant === "bold-italic") { wrapper.style["font-weight"] = "bold"; } - return wrapper - }; - - defineFunctionBuilders({ - type: "mathord", - mathmlBuilder(group, style) { - const text = makeText(group.text, group.mode, style); - const codePoint = text.text.codePointAt(0); - // Test for upper-case Greek - const defaultVariant = (0x0390 < codePoint && codePoint < 0x03aa) ? "normal" : "italic"; - const variant = getVariant(group, style) || defaultVariant; - if (variant === "script") { - text.text = variantChar(text.text, variant); - return new mathMLTree.MathNode("mi", [text], [style.font]) - } else if (variant !== "italic") { - text.text = variantChar(text.text, variant); - } - let node = new mathMLTree.MathNode("mi", [text]); - // TODO: Handle U+1D49C - U+1D4CF per https://www.unicode.org/charts/PDF/U1D400.pdf - if (variant === "normal") { - node.setAttribute("mathvariant", "normal"); - if (text.text.length === 1) { - // A Firefox bug will apply spacing here, but there should be none. Fix it. - node = new mathMLTree.MathNode("mpadded", [node]); - node.setAttribute("lspace", "0"); - node.setAttribute("width", "+0em"); - } - } - return node - } - }); - - defineFunctionBuilders({ - type: "textord", - mathmlBuilder(group, style) { - let ch = group.text; - const codePoint = ch.codePointAt(0); - if (style.fontFamily === "textsc") { - // Convert small latin letters to small caps. - if (96 < codePoint && codePoint < 123) { - ch = smallCaps[ch]; - } - } - const text = makeText(ch, group.mode, style); - const variant = getVariant(group, style) || "normal"; - - let node; - if (group.mode === "text") { - if (variant === "italic" || variant === "bold-italic") { - if (numberRegEx$1.test(group.text)) { - return italicNumber(text, variant) - } - } - if (variant !== "normal") { - text.text = variantChar(text.text, variant); - } - node = new mathMLTree.MathNode("mtext", [text]); - } else if (numberRegEx$1.test(group.text)) { - if (variant === "oldstylenums") { - const ms = new mathMLTree.MathNode("mstyle", [text], ["oldstylenums"]); - node = new mathMLTree.MathNode("mn", [ms]); - } else if (variant === "italic" || variant === "bold-italic") { - return italicNumber(text, variant) - } else { - if (variant !== "normal") { - text.text = text.text.split("").map(c => variantChar(c, variant)).join(""); - } - node = new mathMLTree.MathNode("mn", [text]); - } - } else if (group.text === "\\prime") { - node = new mathMLTree.MathNode("mo", [text]); - } else { - const origText = text.text; - if (variant !== "italic") { - text.text = variantChar(text.text, variant); - } - node = new mathMLTree.MathNode("mi", [text]); - if (text.text === origText && latinRegEx.test(origText)) { - node.setAttribute("mathvariant", "italic"); - } - } - return node - } - }); - - // A map of CSS-based spacing functions to their CSS class. - const cssSpace = { - "\\nobreak": "nobreak", - "\\allowbreak": "allowbreak" - }; - - // A lookup table to determine whether a spacing function/symbol should be - // treated like a regular space character. If a symbol or command is a key - // in this table, then it should be a regular space character. Furthermore, - // the associated value may have a `className` specifying an extra CSS class - // to add to the created `span`. - const regularSpace = { - " ": {}, - "\\ ": {}, - "~": { - className: "nobreak" - }, - "\\space": {}, - "\\nobreakspace": { - className: "nobreak" - } - }; - - // ParseNode<"spacing"> created in Parser.js from the "spacing" symbol Groups in - // src/symbols.js. - defineFunctionBuilders({ - type: "spacing", - mathmlBuilder(group, style) { - let node; - - if (Object.prototype.hasOwnProperty.call(regularSpace, group.text)) { - // Firefox does not render a space in a . So write a no-break space. - // TODO: If Firefox fixes that bug, uncomment the next line and write ch into the node. - //const ch = (regularSpace[group.text].className === "nobreak") ? "\u00a0" : " " - node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("\u00a0")]); - } else if (Object.prototype.hasOwnProperty.call(cssSpace, group.text)) { - // MathML 3.0 calls for nobreak to occur in an , not an - // Ref: https://www.w3.org/Math/draft-spec/mathml.html#chapter3_presm.lbattrs - node = new mathMLTree.MathNode("mo"); - if (group.text === "\\nobreak") { - node.setAttribute("linebreak", "nobreak"); - } - } else { - throw new ParseError(`Unknown type of space "${group.text}"`) - } - - return node - } - }); - - defineFunctionBuilders({ - type: "tag" - }); - - // For a \tag, the work usually done in a mathmlBuilder is instead done in buildMathML.js. - // That way, a \tag can be pulled out of the parse tree and wrapped around the outer node. - - // Non-mathy text, possibly in a font - const textFontFamilies = { - "\\text": undefined, - "\\textrm": "textrm", - "\\textsf": "textsf", - "\\texttt": "texttt", - "\\textnormal": "textrm", - "\\textsc": "textsc" // small caps - }; - - const textFontWeights = { - "\\textbf": "textbf", - "\\textmd": "textmd" - }; - - const textFontShapes = { - "\\textit": "textit", - "\\textup": "textup" - }; - - const styleWithFont = (group, style) => { - const font = group.font; - // Checks if the argument is a font family or a font style. - if (!font) { - return style; - } else if (textFontFamilies[font]) { - return style.withTextFontFamily(textFontFamilies[font]); - } else if (textFontWeights[font]) { - return style.withTextFontWeight(textFontWeights[font]); - } else { - return style.withTextFontShape(textFontShapes[font]); - } - }; - - defineFunction({ - type: "text", - names: [ - // Font families - "\\text", - "\\textrm", - "\\textsf", - "\\texttt", - "\\textnormal", - "\\textsc", - // Font weights - "\\textbf", - "\\textmd", - // Font Shapes - "\\textit", - "\\textup" - ], - props: { - numArgs: 1, - argTypes: ["text"], - allowedInArgument: true, - allowedInText: true - }, - handler({ parser, funcName }, args) { - const body = args[0]; - return { - type: "text", - mode: parser.mode, - body: ordargument(body), - font: funcName - }; - }, - mathmlBuilder(group, style) { - const newStyle = styleWithFont(group, style); - const mrow = buildExpressionRow(group.body, newStyle); - return utils.consolidateText(mrow) - } - }); - - // Two functions included to enable migration from Mathjax. - - defineFunction({ - type: "tip", - names: ["\\mathtip"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "tip", - mode: parser.mode, - body: args[0], - tip: args[1] - }; - }, - mathmlBuilder: (group, style) => { - const math = buildGroup$1(group.body, style); - const tip = buildGroup$1(group.tip, style); - // Browsers don't support the tooltip actiontype. - // TODO: Come back and fix \mathtip when it can be done via CSS w/o a JS event. - const node = new mathMLTree.MathNode("maction", [math, tip], ["tml-tip"]); - node.setAttribute("actiontype", "tooltip"); - return node - } - }); - - defineFunction({ - type: "tip", - names: ["\\texttip"], - props: { - numArgs: 2, - argTypes: ["math", "text"] - }, - handler({ parser }, args) { - return { - type: "tip", - mode: parser.mode, - body: args[0], - tip: args[1] - }; - }, - mathmlBuilder: (group, style) => { - const math = buildGroup$1(group.body, style); - const tip = buildGroup$1(group.tip, style); - // args[1] only accepted text, so tip is a element or a of them. - let str = ""; - if (tip.type === "mtext") { - str = tip.children[0].text; - } else { - for (const child of tip.children) { - str += child.children[0].text; - } - } - // Implement \texttip via a title attribute. - math.setAttribute("title", str); - return math - } - }); - - defineFunctionBuilders({ - type: "toggle", - mathmlBuilder(group, style) { - const expression = buildExpression(group.body, style); - const node = new mathMLTree.MathNode("maction", expression, [], { cursor: "default" }); - node.setAttribute("actiontype", "toggle"); - return node - } - }); - - defineFunction({ - type: "underline", - names: ["\\underline"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "underline", - mode: parser.mode, - body: args[0] - }; - }, - mathmlBuilder(group, style) { - const operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u005f")]); - operator.setAttribute("stretchy", "true"); - - const node = new mathMLTree.MathNode("munder", - [buildGroup$1(group.body, style), operator] - ); - node.setAttribute("accentunder", "true"); - - return node; - } - }); - - defineFunction({ - type: "verb", - names: ["\\verb"], - props: { - numArgs: 0, - allowedInText: true - }, - handler(context, args, optArgs) { - // \verb and \verb* are dealt with directly in Parser.js. - // If we end up here, it's because of a failure to match the two delimiters - // in the regex in Lexer.js. LaTeX raises the following error when \verb is - // terminated by end of line (or file). - throw new ParseError("\\verb ended by end of line instead of matching delimiter"); - }, - mathmlBuilder(group, style) { - const text = new mathMLTree.TextNode(makeVerb(group)); - const node = new mathMLTree.MathNode("mtext", [text]); - node.setAttribute("mathvariant", "monospace"); - return node; - } - }); - - /** - * Converts verb group into body string. - * - * \verb* replaces each space with an open box \u2423 - * \verb replaces each space with a no-break space \xA0 - */ - const makeVerb = (group) => group.body.replace(/ /g, group.star ? "\u2423" : "\xA0"); - - /** Include this to ensure that all functions are defined. */ - - const functions = _functions; - - /** - * Lexing or parsing positional information for error reporting. - * This object is immutable. - */ - class SourceLocation { - constructor(lexer, start, end) { - this.lexer = lexer; // Lexer holding the input string. - this.start = start; // Start offset, zero-based inclusive. - this.end = end; // End offset, zero-based exclusive. - } - - /** - * Merges two `SourceLocation`s from location providers, given they are - * provided in order of appearance. - * - Returns the first one's location if only the first is provided. - * - Returns a merged range of the first and the last if both are provided - * and their lexers match. - * - Otherwise, returns null. - */ - static range(first, second) { - if (!second) { - return first && first.loc; - } else if (!first || !first.loc || !second.loc || first.loc.lexer !== second.loc.lexer) { - return null; - } else { - return new SourceLocation(first.loc.lexer, first.loc.start, second.loc.end); - } - } - } - - /** - * Interface required to break circular dependency between Token, Lexer, and - * ParseError. - */ - - /** - * The resulting token returned from `lex`. - * - * It consists of the token text plus some position information. - * The position information is essentially a range in an input string, - * but instead of referencing the bare input string, we refer to the lexer. - * That way it is possible to attach extra metadata to the input string, - * like for example a file name or similar. - * - * The position information is optional, so it is OK to construct synthetic - * tokens if appropriate. Not providing available position information may - * lead to degraded error reporting, though. - */ - class Token { - constructor( - text, // the text of this token - loc - ) { - this.text = text; - this.loc = loc; - } - - /** - * Given a pair of tokens (this and endToken), compute a `Token` encompassing - * the whole input range enclosed by these two. - */ - range( - endToken, // last token of the range, inclusive - text // the text of the newly constructed token - ) { - return new Token(text, SourceLocation.range(this, endToken)); - } - } - - /** - * The Lexer class handles tokenizing the input in various ways. Since our - * parser expects us to be able to backtrack, the lexer allows lexing from any - * given starting point. - * - * Its main exposed function is the `lex` function, which takes a position to - * lex from and a type of token to lex. It defers to the appropriate `_innerLex` - * function. - * - * The various `_innerLex` functions perform the actual lexing of different - * kinds. - */ - - /* The following tokenRegex - * - matches typical whitespace (but not NBSP etc.) using its first two groups - * - does not match any control character \x00-\x1f except whitespace - * - does not match a bare backslash - * - matches any ASCII character except those just mentioned - * - does not match the BMP private use area \uE000-\uF8FF - * - does not match bare surrogate code units - * - matches any BMP character except for those just described - * - matches any valid Unicode surrogate pair - * - mathches numerals - * - matches a backslash followed by one or more whitespace characters - * - matches a backslash followed by one or more letters then whitespace - * - matches a backslash followed by any BMP character - * Capturing groups: - * [1] regular whitespace - * [2] backslash followed by whitespace - * [3] anything else, which may include: - * [4] left character of \verb* - * [5] left character of \verb - * [6] backslash followed by word, excluding any trailing whitespace - * Just because the Lexer matches something doesn't mean it's valid input: - * If there is no matching function or symbol definition, the Parser will - * still reject the input. - */ - const spaceRegexString = "[ \r\n\t]"; - const controlWordRegexString = "\\\\[a-zA-Z@]+"; - const controlSymbolRegexString = "\\\\[^\uD800-\uDFFF]"; - const controlWordWhitespaceRegexString = `(${controlWordRegexString})${spaceRegexString}*`; - const controlSpaceRegexString = "\\\\(\n|[ \r\t]+\n?)[ \r\t]*"; - const combiningDiacriticalMarkString = "[\u0300-\u036f]"; - const combiningDiacriticalMarksEndRegex = new RegExp(`${combiningDiacriticalMarkString}+$`); - const tokenRegexString = - `(${spaceRegexString}+)|` + // whitespace - `${controlSpaceRegexString}|` + // whitespace - "(number" + // numbers (in non-strict mode) - "|[!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + // single codepoint - `${combiningDiacriticalMarkString}*` + // ...plus accents - "|[\uD800-\uDBFF][\uDC00-\uDFFF]" + // surrogate pair - `${combiningDiacriticalMarkString}*` + // ...plus accents - "|\\\\verb\\*([^]).*?\\4" + // \verb* - "|\\\\verb([^*a-zA-Z]).*?\\5" + // \verb unstarred - `|${controlWordWhitespaceRegexString}` + // \macroName + spaces - `|${controlSymbolRegexString})`; // \\, \', etc. - - /** Main Lexer class */ - class Lexer { - constructor(input, settings) { - // Separate accents from characters - this.input = input; - this.settings = settings; - this.tokenRegex = new RegExp( - // Strict Temml, like TeX, lexes one numeral at a time. - // Default Temml lexes contiguous numerals into a single element. - tokenRegexString.replace("number|", settings.strict ? "" : "\\d(?:[\\d,.]*\\d)?|"), - "g" - ); - // Category codes. The lexer only supports comment characters (14) for now. - // MacroExpander additionally distinguishes active (13). - this.catcodes = { - "%": 14, // comment character - "~": 13 // active character - }; - } - - setCatcode(char, code) { - this.catcodes[char] = code; - } - - /** - * This function lexes a single token. - */ - lex() { - const input = this.input; - const pos = this.tokenRegex.lastIndex; - if (pos === input.length) { - return new Token("EOF", new SourceLocation(this, pos, pos)); - } - const match = this.tokenRegex.exec(input); - if (match === null || match.index !== pos) { - throw new ParseError( - `Unexpected character: '${input[pos]}'`, - new Token(input[pos], new SourceLocation(this, pos, pos + 1)) - ); - } - const text = match[6] || match[3] || (match[2] ? "\\ " : " "); - - if (this.catcodes[text] === 14) { - // comment character - const nlIndex = input.indexOf("\n", this.tokenRegex.lastIndex); - if (nlIndex === -1) { - this.tokenRegex.lastIndex = input.length; // EOF - if (this.settings.strict) { - throw new ParseError("% comment has no terminating newline; LaTeX would " + - "fail because of commenting the end of math mode") - } - } else { - this.tokenRegex.lastIndex = nlIndex + 1; - } - return this.lex(); - } - - return new Token(text, new SourceLocation(this, pos, this.tokenRegex.lastIndex)); - } - } - - /** - * A `Namespace` refers to a space of nameable things like macros or lengths, - * which can be `set` either globally or local to a nested group, using an - * undo stack similar to how TeX implements this functionality. - * Performance-wise, `get` and `set` take constant time. - */ - - class Namespace { - /** - * Both arguments are optional. The first argument is an object of - * built-in mappings which never change. The second argument is an object - * of initial (global-level) mappings, which will constantly change - * according to any global/top-level `set`s done. - */ - constructor(builtins = {}, globalMacros = {}) { - this.current = globalMacros; - this.builtins = builtins; - this.undefStack = []; - } - - /** - * Start a new nested group, affecting future local `set`s. - */ - beginGroup() { - this.undefStack.push({}); - } - - /** - * End current nested group, restoring values before the group began. - */ - endGroup() { - if (this.undefStack.length === 0) { - throw new ParseError( - "Unbalanced namespace destruction: attempt " + - "to pop global namespace; please report this as a bug" - ); - } - const undefs = this.undefStack.pop(); - for (const undef in undefs) { - if (Object.prototype.hasOwnProperty.call(undefs, undef )) { - if (undefs[undef] === undefined) { - delete this.current[undef]; - } else { - this.current[undef] = undefs[undef]; - } - } - } - } - - /** - * Detect whether `name` has a definition. Equivalent to - * `get(name) != null`. - */ - has(name) { - return Object.prototype.hasOwnProperty.call(this.current, name ) || - Object.prototype.hasOwnProperty.call(this.builtins, name ); - } - - /** - * Get the current value of a name, or `undefined` if there is no value. - * - * Note: Do not use `if (namespace.get(...))` to detect whether a macro - * is defined, as the definition may be the empty string which evaluates - * to `false` in JavaScript. Use `if (namespace.get(...) != null)` or - * `if (namespace.has(...))`. - */ - get(name) { - if (Object.prototype.hasOwnProperty.call(this.current, name )) { - return this.current[name]; - } else { - return this.builtins[name]; - } - } - - /** - * Set the current value of a name, and adds an undo - * operation to the undo stack. - */ - set(name, value) { - // Undo this set at end of this group (possibly to `undefined`), - // unless an undo is already in place, in which case that older - // value is the correct one. - const top = this.undefStack[this.undefStack.length - 1]; - if (top && !Object.prototype.hasOwnProperty.call(top, name )) { - top[name] = this.current[name]; - } - this.current[name] = value; - } - } - - /** - * Predefined macros for Temml. - * This can be used to define some commands in terms of others. - */ - const macros = _macros; - - ////////////////////////////////////////////////////////////////////// - // macro tools - - defineMacro("\\noexpand", function(context) { - // The expansion is the token itself; but that token is interpreted - // as if its meaning were ‘\relax’ if it is a control sequence that - // would ordinarily be expanded by TeX’s expansion rules. - const t = context.popToken(); - if (context.isExpandable(t.text)) { - t.noexpand = true; - t.treatAsRelax = true; - } - return { tokens: [t], numArgs: 0 }; - }); - - defineMacro("\\expandafter", function(context) { - // TeX first reads the token that comes immediately after \expandafter, - // without expanding it; let’s call this token t. Then TeX reads the - // token that comes after t (and possibly more tokens, if that token - // has an argument), replacing it by its expansion. Finally TeX puts - // t back in front of that expansion. - const t = context.popToken(); - context.expandOnce(true); // expand only an expandable token - return { tokens: [t], numArgs: 0 }; - }); - - // LaTeX's \@firstoftwo{#1}{#2} expands to #1, skipping #2 - // TeX source: \long\def\@firstoftwo#1#2{#1} - defineMacro("\\@firstoftwo", function(context) { - const args = context.consumeArgs(2); - return { tokens: args[0], numArgs: 0 }; - }); - - // LaTeX's \@secondoftwo{#1}{#2} expands to #2, skipping #1 - // TeX source: \long\def\@secondoftwo#1#2{#2} - defineMacro("\\@secondoftwo", function(context) { - const args = context.consumeArgs(2); - return { tokens: args[1], numArgs: 0 }; - }); - - // LaTeX's \@ifnextchar{#1}{#2}{#3} looks ahead to the next (unexpanded) - // symbol that isn't a space, consuming any spaces but not consuming the - // first nonspace character. If that nonspace character matches #1, then - // the macro expands to #2; otherwise, it expands to #3. - defineMacro("\\@ifnextchar", function(context) { - const args = context.consumeArgs(3); // symbol, if, else - context.consumeSpaces(); - const nextToken = context.future(); - if (args[0].length === 1 && args[0][0].text === nextToken.text) { - return { tokens: args[1], numArgs: 0 }; - } else { - return { tokens: args[2], numArgs: 0 }; - } - }); - - // LaTeX's \@ifstar{#1}{#2} looks ahead to the next (unexpanded) symbol. - // If it is `*`, then it consumes the symbol, and the macro expands to #1; - // otherwise, the macro expands to #2 (without consuming the symbol). - // TeX source: \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}} - defineMacro("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}"); - - // LaTeX's \TextOrMath{#1}{#2} expands to #1 in text mode, #2 in math mode - defineMacro("\\TextOrMath", function(context) { - const args = context.consumeArgs(2); - if (context.mode === "text") { - return { tokens: args[0], numArgs: 0 }; - } else { - return { tokens: args[1], numArgs: 0 }; - } - }); - - const stringFromArg = arg => { - // Reverse the order of the arg and return a string. - let str = ""; - for (let i = arg.length - 1; i > -1; i--) { - str += arg[i].text; - } - return str - }; - - // Lookup table for parsing numbers in base 8 through 16 - const digitToNumber = { - 0: 0, - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9, - a: 10, - A: 10, - b: 11, - B: 11, - c: 12, - C: 12, - d: 13, - D: 13, - e: 14, - E: 14, - f: 15, - F: 15 - }; - - const nextCharNumber = context => { - const numStr = context.future().text; - if (numStr === "EOF") { return [null, ""] } - return [digitToNumber[numStr.charAt(0)], numStr] - }; - - const appendCharNumbers = (number, numStr, base) => { - for (let i = 1; i < numStr.length; i++) { - const digit = digitToNumber[numStr.charAt(i)]; - number *= base; - number += digit; - } - return number - }; - - // TeX \char makes a literal character (catcode 12) using the following forms: - // (see The TeXBook, p. 43) - // \char123 -- decimal - // \char'123 -- octal - // \char"123 -- hex - // \char`x -- character that can be written (i.e. isn't active) - // \char`\x -- character that cannot be written (e.g. %) - // These all refer to characters from the font, so we turn them into special - // calls to a function \@char dealt with in the Parser. - defineMacro("\\char", function(context) { - let token = context.popToken(); - let base; - let number = ""; - if (token.text === "'") { - base = 8; - token = context.popToken(); - } else if (token.text === '"') { - base = 16; - token = context.popToken(); - } else if (token.text === "`") { - token = context.popToken(); - if (token.text[0] === "\\") { - number = token.text.charCodeAt(1); - } else if (token.text === "EOF") { - throw new ParseError("\\char` missing argument"); - } else { - number = token.text.charCodeAt(0); - } - } else { - base = 10; - } - if (base) { - // Parse a number in the given base, starting with first `token`. - let numStr = token.text; - number = digitToNumber[numStr.charAt(0)]; - if (number == null || number >= base) { - throw new ParseError(`Invalid base-${base} digit ${token.text}`); - } - number = appendCharNumbers(number, numStr, base); - let digit; - [digit, numStr] = nextCharNumber(context); - while (digit != null && digit < base) { - number *= base; - number += digit; - number = appendCharNumbers(number, numStr, base); - context.popToken(); - [digit, numStr] = nextCharNumber(context); - } - } - return `\\@char{${number}}`; - }); - - // The Latin Modern font renders at the wrong vertical alignment. - // This macro provides a better rendering. - defineMacro("\\surd", "\\sqrt{}"); - - defineMacro("\\hbox", "\\text{#1}"); - - // Per TeXbook p.122, "/" gets zero operator spacing. - // And MDN recommends using U+2044 instead of / for inline - defineMacro("/", "{\u2044}"); - - // Since Temml has no \par, ignore \long. - defineMacro("\\long", ""); - - ////////////////////////////////////////////////////////////////////// - // Grouping - // \let\bgroup={ \let\egroup=} - defineMacro("\\bgroup", "{"); - defineMacro("\\egroup", "}"); - - // Symbols from latex.ltx: - // \def~{\nobreakspace{}} - // \def\lq{`} - // \def\rq{'} - // \def \aa {\r a} - defineMacro("~", "\\nobreakspace"); - defineMacro("\\lq", "`"); - defineMacro("\\rq", "'"); - defineMacro("\\aa", "\\r a"); - - defineMacro("\\Bbbk", "\\Bbb{k}"); - - // \mathstrut from the TeXbook, p 360 - defineMacro("\\mathstrut", "\\vphantom{(}"); - - // \underbar from TeXbook p 353 - defineMacro("\\underbar", "\\underline{\\text{#1}}"); - - ////////////////////////////////////////////////////////////////////// - // LaTeX_2ε - - // \vdots{\vbox{\baselineskip4\p@ \lineskiplimit\z@ - // \kern6\p@\hbox{.}\hbox{.}\hbox{.}}} - // We'll call \varvdots, which gets a glyph from symbols.js. - // The zero-width rule gets us an equivalent to the vertical 6pt kern. - defineMacro("\\vdots", "\\mathord{\\varvdots\\rule{0pt}{15pt}}"); - defineMacro("\u22ee", "\\vdots"); - - ////////////////////////////////////////////////////////////////////// - // amsmath.sty - // http://mirrors.concertpass.com/tex-archive/macros/latex/required/amsmath/amsmath.pdf - - //\newcommand{\substack}[1]{\subarray{c}#1\endsubarray} - defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}"); - - // \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}} - defineMacro("\\boxed", "\\fbox{$\\displaystyle{#1}$}"); - - // \def\iff{\DOTSB\;\Longleftrightarrow\;} - // \def\implies{\DOTSB\;\Longrightarrow\;} - // \def\impliedby{\DOTSB\;\Longleftarrow\;} - defineMacro("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;"); - defineMacro("\\implies", "\\DOTSB\\;\\Longrightarrow\\;"); - defineMacro("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;"); - - // AMSMath's automatic \dots, based on \mdots@@ macro. - const dotsByToken = { - ",": "\\dotsc", - "\\not": "\\dotsb", - // \keybin@ checks for the following: - "+": "\\dotsb", - "=": "\\dotsb", - "<": "\\dotsb", - ">": "\\dotsb", - "-": "\\dotsb", - "*": "\\dotsb", - ":": "\\dotsb", - // Symbols whose definition starts with \DOTSB: - "\\DOTSB": "\\dotsb", - "\\coprod": "\\dotsb", - "\\bigvee": "\\dotsb", - "\\bigwedge": "\\dotsb", - "\\biguplus": "\\dotsb", - "\\bigcap": "\\dotsb", - "\\bigcup": "\\dotsb", - "\\prod": "\\dotsb", - "\\sum": "\\dotsb", - "\\bigotimes": "\\dotsb", - "\\bigoplus": "\\dotsb", - "\\bigodot": "\\dotsb", - "\\bigsqcap": "\\dotsb", - "\\bigsqcup": "\\dotsb", - "\\And": "\\dotsb", - "\\longrightarrow": "\\dotsb", - "\\Longrightarrow": "\\dotsb", - "\\longleftarrow": "\\dotsb", - "\\Longleftarrow": "\\dotsb", - "\\longleftrightarrow": "\\dotsb", - "\\Longleftrightarrow": "\\dotsb", - "\\mapsto": "\\dotsb", - "\\longmapsto": "\\dotsb", - "\\hookrightarrow": "\\dotsb", - "\\doteq": "\\dotsb", - // Symbols whose definition starts with \mathbin: - "\\mathbin": "\\dotsb", - // Symbols whose definition starts with \mathrel: - "\\mathrel": "\\dotsb", - "\\relbar": "\\dotsb", - "\\Relbar": "\\dotsb", - "\\xrightarrow": "\\dotsb", - "\\xleftarrow": "\\dotsb", - // Symbols whose definition starts with \DOTSI: - "\\DOTSI": "\\dotsi", - "\\int": "\\dotsi", - "\\oint": "\\dotsi", - "\\iint": "\\dotsi", - "\\iiint": "\\dotsi", - "\\iiiint": "\\dotsi", - "\\idotsint": "\\dotsi", - // Symbols whose definition starts with \DOTSX: - "\\DOTSX": "\\dotsx" - }; - - defineMacro("\\dots", function(context) { - // TODO: If used in text mode, should expand to \textellipsis. - // However, in Temml, \textellipsis and \ldots behave the same - // (in text mode), and it's unlikely we'd see any of the math commands - // that affect the behavior of \dots when in text mode. So fine for now - // (until we support \ifmmode ... \else ... \fi). - let thedots = "\\dotso"; - const next = context.expandAfterFuture().text; - if (next in dotsByToken) { - thedots = dotsByToken[next]; - } else if (next.slice(0, 4) === "\\not") { - thedots = "\\dotsb"; - } else if (next in symbols.math) { - if (utils.contains(["bin", "rel"], symbols.math[next].group)) { - thedots = "\\dotsb"; - } - } - return thedots; - }); - - const spaceAfterDots = { - // \rightdelim@ checks for the following: - ")": true, - "]": true, - "\\rbrack": true, - "\\}": true, - "\\rbrace": true, - "\\rangle": true, - "\\rceil": true, - "\\rfloor": true, - "\\rgroup": true, - "\\rmoustache": true, - "\\right": true, - "\\bigr": true, - "\\biggr": true, - "\\Bigr": true, - "\\Biggr": true, - // \extra@ also tests for the following: - $: true, - // \extrap@ checks for the following: - ";": true, - ".": true, - ",": true - }; - - defineMacro("\\dotso", function(context) { - const next = context.future().text; - if (next in spaceAfterDots) { - return "\\ldots\\,"; - } else { - return "\\ldots"; - } - }); - - defineMacro("\\dotsc", function(context) { - const next = context.future().text; - // \dotsc uses \extra@ but not \extrap@, instead specially checking for - // ';' and '.', but doesn't check for ','. - if (next in spaceAfterDots && next !== ",") { - return "\\ldots\\,"; - } else { - return "\\ldots"; - } - }); - - defineMacro("\\cdots", function(context) { - const next = context.future().text; - if (next in spaceAfterDots) { - return "\\@cdots\\,"; - } else { - return "\\@cdots"; - } - }); - - defineMacro("\\dotsb", "\\cdots"); - defineMacro("\\dotsm", "\\cdots"); - defineMacro("\\dotsi", "\\!\\cdots"); - defineMacro("\\idotsint", "\\dotsi"); - // amsmath doesn't actually define \dotsx, but \dots followed by a macro - // starting with \DOTSX implies \dotso, and then \extra@ detects this case - // and forces the added `\,`. - defineMacro("\\dotsx", "\\ldots\\,"); - - // \let\DOTSI\relax - // \let\DOTSB\relax - // \let\DOTSX\relax - defineMacro("\\DOTSI", "\\relax"); - defineMacro("\\DOTSB", "\\relax"); - defineMacro("\\DOTSX", "\\relax"); - - // Spacing, based on amsmath.sty's override of LaTeX defaults - // \DeclareRobustCommand{\tmspace}[3]{% - // \ifmmode\mskip#1#2\else\kern#1#3\fi\relax} - defineMacro("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"); - // \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}} - // TODO: math mode should use \thinmuskip - defineMacro("\\,", "{\\tmspace+{3mu}{.1667em}}"); - // \let\thinspace\, - defineMacro("\\thinspace", "\\,"); - // \def\>{\mskip\medmuskip} - // \renewcommand{\:}{\tmspace+\medmuskip{.2222em}} - // TODO: \> and math mode of \: should use \medmuskip = 4mu plus 2mu minus 4mu - defineMacro("\\>", "\\mskip{4mu}"); - defineMacro("\\:", "{\\tmspace+{4mu}{.2222em}}"); - // \let\medspace\: - defineMacro("\\medspace", "\\:"); - // \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}} - // TODO: math mode should use \thickmuskip = 5mu plus 5mu - defineMacro("\\;", "{\\tmspace+{5mu}{.2777em}}"); - // \let\thickspace\; - defineMacro("\\thickspace", "\\;"); - // \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}} - // TODO: math mode should use \thinmuskip - defineMacro("\\!", "{\\tmspace-{3mu}{.1667em}}"); - // \let\negthinspace\! - defineMacro("\\negthinspace", "\\!"); - // \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}} - // TODO: math mode should use \medmuskip - defineMacro("\\negmedspace", "{\\tmspace-{4mu}{.2222em}}"); - // \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}} - // TODO: math mode should use \thickmuskip - defineMacro("\\negthickspace", "{\\tmspace-{5mu}{.277em}}"); - // \def\enspace{\kern.5em } - defineMacro("\\enspace", "\\kern.5em "); - // \def\enskip{\hskip.5em\relax} - defineMacro("\\enskip", "\\hskip.5em\\relax"); - // \def\quad{\hskip1em\relax} - defineMacro("\\quad", "\\hskip1em\\relax"); - // \def\qquad{\hskip2em\relax} - defineMacro("\\qquad", "\\hskip2em\\relax"); - - // \tag@in@display form of \tag - defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren"); - defineMacro("\\tag@paren", "\\tag@literal{({#1})}"); - defineMacro("\\tag@literal", (context) => { - if (context.macros.get("\\df@tag")) { - throw new ParseError("Multiple \\tag"); - } - return "\\def\\df@tag{\\text{#1}}"; - }); - - // \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin - // {\operator@font mod}\penalty900 - // \mkern5mu\nonscript\mskip-\medmuskip} - // \newcommand{\pod}[1]{\allowbreak - // \if@display\mkern18mu\else\mkern8mu\fi(#1)} - // \renewcommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}} - // \newcommand{\mod}[1]{\allowbreak\if@display\mkern18mu - // \else\mkern12mu\fi{\operator@font mod}\,\,#1} - // TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu - defineMacro("\\bmod", "\\mathbin{\\text{mod}}"); - defineMacro( - "\\pod", - "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)" - ); - defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}"); - defineMacro( - "\\mod", - "\\allowbreak" + - "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + - "{\\rm mod}\\,\\,#1" - ); - - ////////////////////////////////////////////////////////////////////// - // LaTeX source2e - - // \expandafter\let\expandafter\@normalcr - // \csname\expandafter\@gobble\string\\ \endcsname - // \DeclareRobustCommand\newline{\@normalcr\relax} - defineMacro("\\newline", "\\\\\\relax"); - - // \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@} - // TODO: Doesn't normally work in math mode because \@ fails. - defineMacro("\\TeX", "\\textrm{T}\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125em\\textrm{X}"); - - defineMacro( - "\\LaTeX", - "\\textrm{L}\\kern-.35em\\raisebox{0.2em}{\\scriptstyle A}\\kern-.15em\\TeX" - ); - - defineMacro( - "\\Temml", - // eslint-disable-next-line max-len - "\\textrm{T}\\kern-0.2em\\lower{0.2em}\\textrm{E}\\kern-0.08em{\\textrm{M}\\kern-0.08em\\raise{0.2em}\\textrm{M}\\kern-0.08em\\textrm{L}}" - ); - - // \DeclareRobustCommand\hspace{\@ifstar\@hspacer\@hspace} - // \def\@hspace#1{\hskip #1\relax} - // \def\@hspacer#1{\vrule \@width\z@\nobreak - // \hskip #1\hskip \z@skip} - defineMacro("\\hspace", "\\@ifstar\\@hspacer\\@hspace"); - defineMacro("\\@hspace", "\\hskip #1\\relax"); - defineMacro("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax"); - - defineMacro("\\colon", `\\mathpunct{\\char"3a}`); - - ////////////////////////////////////////////////////////////////////// - // mathtools.sty - - defineMacro("\\prescript", "\\pres@cript{_{#1}^{#2}}{}{#3}"); - - //\providecommand\ordinarycolon{:} - defineMacro("\\ordinarycolon", `\\char"3a`); - // Raise to center on the math axis, as closely as possible. - defineMacro("\\vcentcolon", "\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}}"); - // \providecommand*\coloneq{\vcentcolon\mathrel{\mkern-1.2mu}\mathrel{-}} - defineMacro("\\coloneq", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"2212}'); - // \providecommand*\Coloneq{\dblcolon\mathrel{\mkern-1.2mu}\mathrel{-}} - defineMacro("\\Coloneq", '\\mathrel{\\char"2237\\char"2212}'); - // \providecommand*\Eqqcolon{=\mathrel{\mkern-1.2mu}\dblcolon} - defineMacro("\\Eqqcolon", '\\mathrel{\\char"3d\\char"2237}'); - // \providecommand*\Eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\dblcolon} - defineMacro("\\Eqcolon", '\\mathrel{\\char"2212\\char"2237}'); - // \providecommand*\colonapprox{\vcentcolon\mathrel{\mkern-1.2mu}\approx} - defineMacro("\\colonapprox", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"2248}'); - // \providecommand*\Colonapprox{\dblcolon\mathrel{\mkern-1.2mu}\approx} - defineMacro("\\Colonapprox", '\\mathrel{\\char"2237\\char"2248}'); - // \providecommand*\colonsim{\vcentcolon\mathrel{\mkern-1.2mu}\sim} - defineMacro("\\colonsim", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"223c}'); - // \providecommand*\Colonsim{\dblcolon\mathrel{\mkern-1.2mu}\sim} - defineMacro("\\Colonsim", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"223c}'); - - ////////////////////////////////////////////////////////////////////// - // colonequals.sty - - // Alternate names for mathtools's macros: - defineMacro("\\ratio", "\\vcentcolon"); - defineMacro("\\coloncolon", "\\dblcolon"); - defineMacro("\\colonequals", "\\coloneqq"); - defineMacro("\\coloncolonequals", "\\Coloneqq"); - defineMacro("\\equalscolon", "\\eqqcolon"); - defineMacro("\\equalscoloncolon", "\\Eqqcolon"); - defineMacro("\\colonminus", "\\coloneq"); - defineMacro("\\coloncolonminus", "\\Coloneq"); - defineMacro("\\minuscolon", "\\eqcolon"); - defineMacro("\\minuscoloncolon", "\\Eqcolon"); - // \colonapprox name is same in mathtools and colonequals. - defineMacro("\\coloncolonapprox", "\\Colonapprox"); - // \colonsim name is same in mathtools and colonequals. - defineMacro("\\coloncolonsim", "\\Colonsim"); - - // Present in newtxmath, pxfonts and txfonts - defineMacro("\\notni", "\\mathrel{\\char`\u220C}"); - defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}"); - defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}"); - - ////////////////////////////////////////////////////////////////////// - // From amsopn.sty - defineMacro("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}"); - defineMacro("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}"); - defineMacro("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{\\text{lim}}}"); - defineMacro("\\varliminf", "\\DOTSB\\operatorname*{\\underline{\\text{lim}}}"); - defineMacro("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{\\text{lim}}}"); - defineMacro("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{\\text{lim}}}"); - - defineMacro("\\centerdot", "{\\medspace\\rule{0.167em}{0.189em}\\medspace}"); - - ////////////////////////////////////////////////////////////////////// - // statmath.sty - // https://ctan.math.illinois.edu/macros/latex/contrib/statmath/statmath.pdf - - defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}"); - defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}"); - defineMacro("\\plim", "\\DOTSB\\operatorname*{plim}"); - - ////////////////////////////////////////////////////////////////////// - // braket.sty - // http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf - - defineMacro("\\bra", "\\mathinner{\\langle{#1}|}"); - defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}"); - defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}"); - defineMacro("\\Bra", "\\left\\langle#1\\right|"); - defineMacro("\\Ket", "\\left|#1\\right\\rangle"); - const braketHelper = (one) => (context) => { - const left = context.consumeArg().tokens; - const middle = context.consumeArg().tokens; - const middleDouble = context.consumeArg().tokens; - const right = context.consumeArg().tokens; - const oldMiddle = context.macros.get("|"); - const oldMiddleDouble = context.macros.get("\\|"); - context.macros.beginGroup(); - const midMacro = (double) => (context) => { - if (one) { - // Only modify the first instance of | or \| - context.macros.set("|", oldMiddle); - if (middleDouble.length) { - context.macros.set("\\|", oldMiddleDouble); - } - } - let doubled = double; - if (!double && middleDouble.length) { - // Mimic \@ifnextchar - const nextToken = context.future(); - if (nextToken.text === "|") { - context.popToken(); - doubled = true; - } - } - return { - tokens: doubled ? middleDouble : middle, - numArgs: 0 - }; - }; - context.macros.set("|", midMacro(false)); - if (middleDouble.length) { - context.macros.set("\\|", midMacro(true)); - } - const arg = context.consumeArg().tokens; - const expanded = context.expandTokens([...right, ...arg, ...left]); // reversed - context.macros.endGroup(); - return { - tokens: expanded.reverse(), - numArgs: 0 - }; - }; - defineMacro("\\bra@ket", braketHelper(false)); - defineMacro("\\bra@set", braketHelper(true)); - defineMacro("\\Braket", "\\bra@ket{\\left\\langle}" + - "{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"); - defineMacro("\\Set", "\\bra@set{\\left\\{\\:}" + - "{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"); - defineMacro("\\set", "\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"); - // has no support for special || or \| - - ////////////////////////////////////////////////////////////////////// - // actuarialangle.dtx - defineMacro("\\angln", "{\\angl n}"); - - ////////////////////////////////////////////////////////////////////// - // derivative.sty - defineMacro("\\odv", "\\@ifstar\\odv@next\\odv@numerator"); - defineMacro("\\odv@numerator", "\\frac{\\mathrm{d}#1}{\\mathrm{d}#2}"); - defineMacro("\\odv@next", "\\frac{\\mathrm{d}}{\\mathrm{d}#2}#1"); - defineMacro("\\pdv", "\\@ifstar\\pdv@next\\pdv@numerator"); - - const pdvHelper = args => { - const numerator = args[0][0].text; - const denoms = stringFromArg(args[1]).split(","); - const power = String(denoms.length); - const numOp = power === "1" ? "\\partial" : `\\partial^${power}`; - let denominator = ""; - denoms.map(e => { denominator += "\\partial " + e.trim() + "\\,";}); - return [numerator, numOp, denominator.replace(/\\,$/, "")] - }; - defineMacro("\\pdv@numerator", function(context) { - const [numerator, numOp, denominator] = pdvHelper(context.consumeArgs(2)); - return `\\frac{${numOp} ${numerator}}{${denominator}}` - }); - defineMacro("\\pdv@next", function(context) { - const [numerator, numOp, denominator] = pdvHelper(context.consumeArgs(2)); - return `\\frac{${numOp}}{${denominator}} ${numerator}` - }); - - ////////////////////////////////////////////////////////////////////// - // upgreek.dtx - defineMacro("\\upalpha", "\\up@greek{\\alpha}"); - defineMacro("\\upbeta", "\\up@greek{\\beta}"); - defineMacro("\\upgamma", "\\up@greek{\\gamma}"); - defineMacro("\\updelta", "\\up@greek{\\delta}"); - defineMacro("\\upepsilon", "\\up@greek{\\epsilon}"); - defineMacro("\\upzeta", "\\up@greek{\\zeta}"); - defineMacro("\\upeta", "\\up@greek{\\eta}"); - defineMacro("\\uptheta", "\\up@greek{\\theta}"); - defineMacro("\\upiota", "\\up@greek{\\iota}"); - defineMacro("\\upkappa", "\\up@greek{\\kappa}"); - defineMacro("\\uplambda", "\\up@greek{\\lambda}"); - defineMacro("\\upmu", "\\up@greek{\\mu}"); - defineMacro("\\upnu", "\\up@greek{\\nu}"); - defineMacro("\\upxi", "\\up@greek{\\xi}"); - defineMacro("\\upomicron", "\\up@greek{\\omicron}"); - defineMacro("\\uppi", "\\up@greek{\\pi}"); - defineMacro("\\upalpha", "\\up@greek{\\alpha}"); - defineMacro("\\uprho", "\\up@greek{\\rho}"); - defineMacro("\\upsigma", "\\up@greek{\\sigma}"); - defineMacro("\\uptau", "\\up@greek{\\tau}"); - defineMacro("\\upupsilon", "\\up@greek{\\upsilon}"); - defineMacro("\\upphi", "\\up@greek{\\phi}"); - defineMacro("\\upchi", "\\up@greek{\\chi}"); - defineMacro("\\uppsi", "\\up@greek{\\psi}"); - defineMacro("\\upomega", "\\up@greek{\\omega}"); - - ////////////////////////////////////////////////////////////////////// - // cmll package - defineMacro("\\invamp", '\\mathbin{\\char"214b}'); - defineMacro("\\parr", '\\mathbin{\\char"214b}'); - defineMacro("\\with", '\\mathbin{\\char"26}'); - defineMacro("\\multimapinv", '\\mathrel{\\char"27dc}'); - defineMacro("\\multimapboth", '\\mathrel{\\char"29df}'); - defineMacro("\\scoh", '{\\mkern5mu\\char"2322\\mkern5mu}'); - defineMacro("\\sincoh", '{\\mkern5mu\\char"2323\\mkern5mu}'); - defineMacro("\\coh", `{\\mkern5mu\\rule{}{0.7em}\\mathrlap{\\smash{\\raise2mu{\\char"2322}}} -{\\smash{\\lower4mu{\\char"2323}}}\\mkern5mu}`); - defineMacro("\\incoh", `{\\mkern5mu\\rule{}{0.7em}\\mathrlap{\\smash{\\raise2mu{\\char"2323}}} -{\\smash{\\lower4mu{\\char"2322}}}\\mkern5mu}`); - - - ////////////////////////////////////////////////////////////////////// - // chemstyle package - defineMacro("\\standardstate", "\\text{\\tiny\\char`⦵}"); - - /** - * This file contains the “gullet” where macros are expanded - * until only non-macro tokens remain. - */ - - // List of commands that act like macros but aren't defined as a macro, - // function, or symbol. Used in `isDefined`. - const implicitCommands = { - "^": true, // Parser.js - _: true, // Parser.js - "\\limits": true, // Parser.js - "\\nolimits": true // Parser.js - }; - - class MacroExpander { - constructor(input, settings, mode) { - this.settings = settings; - this.expansionCount = 0; - this.feed(input); - // Make new global namespace - this.macros = new Namespace(macros, settings.macros); - this.mode = mode; - this.stack = []; // contains tokens in REVERSE order - } - - /** - * Feed a new input string to the same MacroExpander - * (with existing macros etc.). - */ - feed(input) { - this.lexer = new Lexer(input, this.settings); - } - - /** - * Switches between "text" and "math" modes. - */ - switchMode(newMode) { - this.mode = newMode; - } - - /** - * Start a new group nesting within all namespaces. - */ - beginGroup() { - this.macros.beginGroup(); - } - - /** - * End current group nesting within all namespaces. - */ - endGroup() { - this.macros.endGroup(); - } - - /** - * Returns the topmost token on the stack, without expanding it. - * Similar in behavior to TeX's `\futurelet`. - */ - future() { - if (this.stack.length === 0) { - this.pushToken(this.lexer.lex()); - } - return this.stack[this.stack.length - 1] - } - - /** - * Remove and return the next unexpanded token. - */ - popToken() { - this.future(); // ensure non-empty stack - return this.stack.pop(); - } - - /** - * Add a given token to the token stack. In particular, this get be used - * to put back a token returned from one of the other methods. - */ - pushToken(token) { - this.stack.push(token); - } - - /** - * Append an array of tokens to the token stack. - */ - pushTokens(tokens) { - this.stack.push(...tokens); - } - - /** - * Find an macro argument without expanding tokens and append the array of - * tokens to the token stack. Uses Token as a container for the result. - */ - scanArgument(isOptional) { - let start; - let end; - let tokens; - if (isOptional) { - this.consumeSpaces(); // \@ifnextchar gobbles any space following it - if (this.future().text !== "[") { - return null; - } - start = this.popToken(); // don't include [ in tokens - ({ tokens, end } = this.consumeArg(["]"])); - } else { - ({ tokens, start, end } = this.consumeArg()); - } - - // indicate the end of an argument - this.pushToken(new Token("EOF", end.loc)); - - this.pushTokens(tokens); - return start.range(end, ""); - } - - /** - * Consume all following space tokens, without expansion. - */ - consumeSpaces() { - for (;;) { - const token = this.future(); - if (token.text === " ") { - this.stack.pop(); - } else { - break; - } - } - } - - /** - * Consume an argument from the token stream, and return the resulting array - * of tokens and start/end token. - */ - consumeArg(delims) { - // The argument for a delimited parameter is the shortest (possibly - // empty) sequence of tokens with properly nested {...} groups that is - // followed ... by this particular list of non-parameter tokens. - // The argument for an undelimited parameter is the next nonblank - // token, unless that token is ‘{’, when the argument will be the - // entire {...} group that follows. - const tokens = []; - const isDelimited = delims && delims.length > 0; - if (!isDelimited) { - // Ignore spaces between arguments. As the TeXbook says: - // "After you have said ‘\def\row#1#2{...}’, you are allowed to - // put spaces between the arguments (e.g., ‘\row x n’), because - // TeX doesn’t use single spaces as undelimited arguments." - this.consumeSpaces(); - } - const start = this.future(); - let tok; - let depth = 0; - let match = 0; - do { - tok = this.popToken(); - tokens.push(tok); - if (tok.text === "{") { - ++depth; - } else if (tok.text === "}") { - --depth; - if (depth === -1) { - throw new ParseError("Extra }", tok); - } - } else if (tok.text === "EOF") { - throw new ParseError( - "Unexpected end of input in a macro argument" + - ", expected '" + - (delims && isDelimited ? delims[match] : "}") + - "'", - tok - ); - } - if (delims && isDelimited) { - if ((depth === 0 || (depth === 1 && delims[match] === "{")) && tok.text === delims[match]) { - ++match; - if (match === delims.length) { - // don't include delims in tokens - tokens.splice(-match, match); - break; - } - } else { - match = 0; - } - } - } while (depth !== 0 || isDelimited); - // If the argument found ... has the form ‘{}’, - // ... the outermost braces enclosing the argument are removed - if (start.text === "{" && tokens[tokens.length - 1].text === "}") { - tokens.pop(); - tokens.shift(); - } - tokens.reverse(); // to fit in with stack order - return { tokens, start, end: tok }; - } - - /** - * Consume the specified number of (delimited) arguments from the token - * stream and return the resulting array of arguments. - */ - consumeArgs(numArgs, delimiters) { - if (delimiters) { - if (delimiters.length !== numArgs + 1) { - throw new ParseError("The length of delimiters doesn't match the number of args!"); - } - const delims = delimiters[0]; - for (let i = 0; i < delims.length; i++) { - const tok = this.popToken(); - if (delims[i] !== tok.text) { - throw new ParseError("Use of the macro doesn't match its definition", tok); - } - } - } - - const args = []; - for (let i = 0; i < numArgs; i++) { - args.push(this.consumeArg(delimiters && delimiters[i + 1]).tokens); - } - return args; - } - - /** - * Expand the next token only once if possible. - * - * If the token is expanded, the resulting tokens will be pushed onto - * the stack in reverse order and will be returned as an array, - * also in reverse order. - * - * If not, the next token will be returned without removing it - * from the stack. This case can be detected by a `Token` return value - * instead of an `Array` return value. - * - * In either case, the next token will be on the top of the stack, - * or the stack will be empty. - * - * Used to implement `expandAfterFuture` and `expandNextToken`. - * - * If expandableOnly, only expandable tokens are expanded and - * an undefined control sequence results in an error. - */ - expandOnce(expandableOnly) { - const topToken = this.popToken(); - const name = topToken.text; - const expansion = !topToken.noexpand ? this._getExpansion(name) : null; - if (expansion == null || (expandableOnly && expansion.unexpandable)) { - if (expandableOnly && expansion == null && name[0] === "\\" && !this.isDefined(name)) { - throw new ParseError("Undefined control sequence: " + name); - } - this.pushToken(topToken); - return topToken; - } - this.expansionCount++; - if (this.expansionCount > this.settings.maxExpand) { - throw new ParseError( - "Too many expansions: infinite loop or " + "need to increase maxExpand setting" - ); - } - let tokens = expansion.tokens; - const args = this.consumeArgs(expansion.numArgs, expansion.delimiters); - if (expansion.numArgs) { - // paste arguments in place of the placeholders - tokens = tokens.slice(); // make a shallow copy - for (let i = tokens.length - 1; i >= 0; --i) { - let tok = tokens[i]; - if (tok.text === "#") { - if (i === 0) { - throw new ParseError("Incomplete placeholder at end of macro body", tok); - } - tok = tokens[--i]; // next token on stack - if (tok.text === "#") { - // ## → # - tokens.splice(i + 1, 1); // drop first # - } else if (/^[1-9]$/.test(tok.text)) { - // replace the placeholder with the indicated argument - tokens.splice(i, 2, ...args[+tok.text - 1]); - } else { - throw new ParseError("Not a valid argument number", tok); - } - } - } - } - // Concatenate expansion onto top of stack. - this.pushTokens(tokens); - return tokens; - } - - /** - * Expand the next token only once (if possible), and return the resulting - * top token on the stack (without removing anything from the stack). - * Similar in behavior to TeX's `\expandafter\futurelet`. - * Equivalent to expandOnce() followed by future(). - */ - expandAfterFuture() { - this.expandOnce(); - return this.future(); - } - - /** - * Recursively expand first token, then return first non-expandable token. - */ - expandNextToken() { - for (;;) { - const expanded = this.expandOnce(); - // expandOnce returns Token if and only if it's fully expanded. - if (expanded instanceof Token) { - // The token after \noexpand is interpreted as if its meaning were ‘\relax’ - if (expanded.treatAsRelax) { - expanded.text = "\\relax"; - } - return this.stack.pop(); // === expanded - } - } - - // This pathway is impossible. - throw new Error(); // eslint-disable-line no-unreachable - } - - /** - * Fully expand the given macro name and return the resulting list of - * tokens, or return `undefined` if no such macro is defined. - */ - expandMacro(name) { - return this.macros.has(name) ? this.expandTokens([new Token(name)]) : undefined; - } - - /** - * Fully expand the given token stream and return the resulting list of - * tokens. Note that the input tokens are in reverse order, but the - * output tokens are in forward order. - */ - expandTokens(tokens) { - const output = []; - const oldStackLength = this.stack.length; - this.pushTokens(tokens); - while (this.stack.length > oldStackLength) { - const expanded = this.expandOnce(true); // expand only expandable tokens - // expandOnce returns Token if and only if it's fully expanded. - if (expanded instanceof Token) { - if (expanded.treatAsRelax) { - // the expansion of \noexpand is the token itself - expanded.noexpand = false; - expanded.treatAsRelax = false; - } - output.push(this.stack.pop()); - } - } - return output; - } - - /** - * Fully expand the given macro name and return the result as a string, - * or return `undefined` if no such macro is defined. - */ - expandMacroAsText(name) { - const tokens = this.expandMacro(name); - if (tokens) { - return tokens.map((token) => token.text).join(""); - } else { - return tokens; - } - } - - /** - * Returns the expanded macro as a reversed array of tokens and a macro - * argument count. Or returns `null` if no such macro. - */ - _getExpansion(name) { - const definition = this.macros.get(name); - if (definition == null) { - // mainly checking for undefined here - return definition; - } - // If a single character has an associated catcode other than 13 - // (active character), then don't expand it. - if (name.length === 1) { - const catcode = this.lexer.catcodes[name]; - if (catcode != null && catcode !== 13) { - return - } - } - const expansion = typeof definition === "function" ? definition(this) : definition; - if (typeof expansion === "string") { - let numArgs = 0; - if (expansion.indexOf("#") !== -1) { - const stripped = expansion.replace(/##/g, ""); - while (stripped.indexOf("#" + (numArgs + 1)) !== -1) { - ++numArgs; - } - } - const bodyLexer = new Lexer(expansion, this.settings); - const tokens = []; - let tok = bodyLexer.lex(); - while (tok.text !== "EOF") { - tokens.push(tok); - tok = bodyLexer.lex(); - } - tokens.reverse(); // to fit in with stack using push and pop - const expanded = { tokens, numArgs }; - return expanded; - } - - return expansion; - } - - /** - * Determine whether a command is currently "defined" (has some - * functionality), meaning that it's a macro (in the current group), - * a function, a symbol, or one of the special commands listed in - * `implicitCommands`. - */ - isDefined(name) { - return ( - this.macros.has(name) || - Object.prototype.hasOwnProperty.call(functions, name ) || - Object.prototype.hasOwnProperty.call(symbols.math, name ) || - Object.prototype.hasOwnProperty.call(symbols.text, name ) || - Object.prototype.hasOwnProperty.call(implicitCommands, name ) - ); - } - - /** - * Determine whether a command is expandable. - */ - isExpandable(name) { - const macro = this.macros.get(name); - return macro != null - ? typeof macro === "string" || typeof macro === "function" || !macro.unexpandable - : Object.prototype.hasOwnProperty.call(functions, name ) && !functions[name].primitive; - } - } - - /* - * This file defines the Unicode scripts and script families that we - * support. To add new scripts or families, just add a new entry to the - * scriptData array below. Adding scripts to the scriptData array allows - * characters from that script to appear in \text{} environments. - */ - - /** - * Each script or script family has a name and an array of blocks. - * Each block is an array of two numbers which specify the start and - * end points (inclusive) of a block of Unicode codepoints. - - /** - * Unicode block data for the families of scripts we support in \text{}. - * Scripts only need to appear here if they do not have font metrics. - */ - const scriptData = [ - { - // Latin characters beyond the Latin-1 characters we have metrics for. - // Needed for Czech, Hungarian and Turkish text, for example. - name: "latin", - blocks: [ - [0x0100, 0x024f], // Latin Extended-A and Latin Extended-B - [0x0300, 0x036f] // Combining Diacritical marks - ] - }, - { - // The Cyrillic script used by Russian and related languages. - // A Cyrillic subset used to be supported as explicitly defined - // symbols in symbols.js - name: "cyrillic", - blocks: [[0x0400, 0x04ff]] - }, - { - // Armenian - name: "armenian", - blocks: [[0x0530, 0x058f]] - }, - { - // The Brahmic scripts of South and Southeast Asia - // Devanagari (0900–097F) - // Bengali (0980–09FF) - // Gurmukhi (0A00–0A7F) - // Gujarati (0A80–0AFF) - // Oriya (0B00–0B7F) - // Tamil (0B80–0BFF) - // Telugu (0C00–0C7F) - // Kannada (0C80–0CFF) - // Malayalam (0D00–0D7F) - // Sinhala (0D80–0DFF) - // Thai (0E00–0E7F) - // Lao (0E80–0EFF) - // Tibetan (0F00–0FFF) - // Myanmar (1000–109F) - name: "brahmic", - blocks: [[0x0900, 0x109f]] - }, - { - name: "georgian", - blocks: [[0x10a0, 0x10ff]] - }, - { - // Chinese and Japanese. - // The "k" in cjk is for Korean, but we've separated Korean out - name: "cjk", - blocks: [ - [0x3000, 0x30ff], // CJK symbols and punctuation, Hiragana, Katakana - [0x4e00, 0x9faf], // CJK ideograms - [0xff00, 0xff60] // Fullwidth punctuation - // TODO: add halfwidth Katakana and Romanji glyphs - ] - }, - { - // Korean - name: "hangul", - blocks: [[0xac00, 0xd7af]] - } - ]; - - /** - * A flattened version of all the supported blocks in a single array. - * This is an optimization to make supportedCodepoint() fast. - */ - const allBlocks = []; - scriptData.forEach((s) => s.blocks.forEach((b) => allBlocks.push(...b))); - - /** - * Given a codepoint, return true if it falls within one of the - * scripts or script families defined above and false otherwise. - * - * Micro benchmarks shows that this is faster than - * /[\u3000-\u30FF\u4E00-\u9FAF\uFF00-\uFF60\uAC00-\uD7AF\u0900-\u109F]/.test() - * in Firefox, Chrome and Node. - */ - function supportedCodepoint(codepoint) { - for (let i = 0; i < allBlocks.length; i += 2) { - if (codepoint >= allBlocks[i] && codepoint <= allBlocks[i + 1]) { - return true; - } - } - return false; - } - - // Helpers for Parser.js handling of Unicode (sub|super)script characters. - - const unicodeSubRegEx = /^[₊₋₌₍₎₀₁₂₃₄₅₆₇₈₉ₐₑₕᵢⱼₖₗₘₙₒₚᵣₛₜᵤᵥₓᵦᵧᵨᵩᵪ]/; - - const uSubsAndSups = Object.freeze({ - '₊': '+', - '₋': '-', - '₌': '=', - '₍': '(', - '₎': ')', - '₀': '0', - '₁': '1', - '₂': '2', - '₃': '3', - '₄': '4', - '₅': '5', - '₆': '6', - '₇': '7', - '₈': '8', - '₉': '9', - '\u2090': 'a', - '\u2091': 'e', - '\u2095': 'h', - '\u1D62': 'i', - '\u2C7C': 'j', - '\u2096': 'k', - '\u2097': 'l', - '\u2098': 'm', - '\u2099': 'n', - '\u2092': 'o', - '\u209A': 'p', - '\u1D63': 'r', - '\u209B': 's', - '\u209C': 't', - '\u1D64': 'u', - '\u1D65': 'v', - '\u2093': 'x', - '\u1D66': 'β', - '\u1D67': 'γ', - '\u1D68': 'ρ', - '\u1D69': '\u03d5', - '\u1D6A': 'χ', - '⁺': '+', - '⁻': '-', - '⁼': '=', - '⁽': '(', - '⁾': ')', - '⁰': '0', - '¹': '1', - '²': '2', - '³': '3', - '⁴': '4', - '⁵': '5', - '⁶': '6', - '⁷': '7', - '⁸': '8', - '⁹': '9', - '\u1D2C': 'A', - '\u1D2E': 'B', - '\u1D30': 'D', - '\u1D31': 'E', - '\u1D33': 'G', - '\u1D34': 'H', - '\u1D35': 'I', - '\u1D36': 'J', - '\u1D37': 'K', - '\u1D38': 'L', - '\u1D39': 'M', - '\u1D3A': 'N', - '\u1D3C': 'O', - '\u1D3E': 'P', - '\u1D3F': 'R', - '\u1D40': 'T', - '\u1D41': 'U', - '\u2C7D': 'V', - '\u1D42': 'W', - '\u1D43': 'a', - '\u1D47': 'b', - '\u1D9C': 'c', - '\u1D48': 'd', - '\u1D49': 'e', - '\u1DA0': 'f', - '\u1D4D': 'g', - '\u02B0': 'h', - '\u2071': 'i', - '\u02B2': 'j', - '\u1D4F': 'k', - '\u02E1': 'l', - '\u1D50': 'm', - '\u207F': 'n', - '\u1D52': 'o', - '\u1D56': 'p', - '\u02B3': 'r', - '\u02E2': 's', - '\u1D57': 't', - '\u1D58': 'u', - '\u1D5B': 'v', - '\u02B7': 'w', - '\u02E3': 'x', - '\u02B8': 'y', - '\u1DBB': 'z', - '\u1D5D': 'β', - '\u1D5E': 'γ', - '\u1D5F': 'δ', - '\u1D60': '\u03d5', - '\u1D61': 'χ', - '\u1DBF': 'θ' - }); - - // Mapping of Unicode accent characters to their LaTeX equivalent in text and - // math mode (when they exist). - var unicodeAccents = { - "\u0301": { text: "\\'", math: "\\acute" }, - "\u0300": { text: "\\`", math: "\\grave" }, - "\u0308": { text: '\\"', math: "\\ddot" }, - "\u0303": { text: "\\~", math: "\\tilde" }, - "\u0304": { text: "\\=", math: "\\bar" }, - "\u0306": { text: "\\u", math: "\\breve" }, - "\u030c": { text: "\\v", math: "\\check" }, - "\u0302": { text: "\\^", math: "\\hat" }, - "\u0307": { text: "\\.", math: "\\dot" }, - "\u030a": { text: "\\r", math: "\\mathring" }, - "\u030b": { text: "\\H" }, - '\u0327': { text: '\\c' } - }; - - var unicodeSymbols = { - "á": "á", - "à": "à", - "ä": "ä", - "ǟ": "ǟ", - "ã": "ã", - "ā": "ā", - "ă": "ă", - "ắ": "ắ", - "ằ": "ằ", - "ẵ": "ẵ", - "ǎ": "ǎ", - "â": "â", - "ấ": "ấ", - "ầ": "ầ", - "ẫ": "ẫ", - "ȧ": "ȧ", - "ǡ": "ǡ", - "å": "å", - "ǻ": "ǻ", - "ḃ": "ḃ", - "ć": "ć", - "č": "č", - "ĉ": "ĉ", - "ċ": "ċ", - "ď": "ď", - "ḋ": "ḋ", - "é": "é", - "è": "è", - "ë": "ë", - "ẽ": "ẽ", - "ē": "ē", - "ḗ": "ḗ", - "ḕ": "ḕ", - "ĕ": "ĕ", - "ě": "ě", - "ê": "ê", - "ế": "ế", - "ề": "ề", - "ễ": "ễ", - "ė": "ė", - "ḟ": "ḟ", - "ǵ": "ǵ", - "ḡ": "ḡ", - "ğ": "ğ", - "ǧ": "ǧ", - "ĝ": "ĝ", - "ġ": "ġ", - "ḧ": "ḧ", - "ȟ": "ȟ", - "ĥ": "ĥ", - "ḣ": "ḣ", - "í": "í", - "ì": "ì", - "ï": "ï", - "ḯ": "ḯ", - "ĩ": "ĩ", - "ī": "ī", - "ĭ": "ĭ", - "ǐ": "ǐ", - "î": "î", - "ǰ": "ǰ", - "ĵ": "ĵ", - "ḱ": "ḱ", - "ǩ": "ǩ", - "ĺ": "ĺ", - "ľ": "ľ", - "ḿ": "ḿ", - "ṁ": "ṁ", - "ń": "ń", - "ǹ": "ǹ", - "ñ": "ñ", - "ň": "ň", - "ṅ": "ṅ", - "ó": "ó", - "ò": "ò", - "ö": "ö", - "ȫ": "ȫ", - "õ": "õ", - "ṍ": "ṍ", - "ṏ": "ṏ", - "ȭ": "ȭ", - "ō": "ō", - "ṓ": "ṓ", - "ṑ": "ṑ", - "ŏ": "ŏ", - "ǒ": "ǒ", - "ô": "ô", - "ố": "ố", - "ồ": "ồ", - "ỗ": "ỗ", - "ȯ": "ȯ", - "ȱ": "ȱ", - "ő": "ő", - "ṕ": "ṕ", - "ṗ": "ṗ", - "ŕ": "ŕ", - "ř": "ř", - "ṙ": "ṙ", - "ś": "ś", - "ṥ": "ṥ", - "š": "š", - "ṧ": "ṧ", - "ŝ": "ŝ", - "ṡ": "ṡ", - "ẗ": "ẗ", - "ť": "ť", - "ṫ": "ṫ", - "ú": "ú", - "ù": "ù", - "ü": "ü", - "ǘ": "ǘ", - "ǜ": "ǜ", - "ǖ": "ǖ", - "ǚ": "ǚ", - "ũ": "ũ", - "ṹ": "ṹ", - "ū": "ū", - "ṻ": "ṻ", - "ŭ": "ŭ", - "ǔ": "ǔ", - "û": "û", - "ů": "ů", - "ű": "ű", - "ṽ": "ṽ", - "ẃ": "ẃ", - "ẁ": "ẁ", - "ẅ": "ẅ", - "ŵ": "ŵ", - "ẇ": "ẇ", - "ẘ": "ẘ", - "ẍ": "ẍ", - "ẋ": "ẋ", - "ý": "ý", - "ỳ": "ỳ", - "ÿ": "ÿ", - "ỹ": "ỹ", - "ȳ": "ȳ", - "ŷ": "ŷ", - "ẏ": "ẏ", - "ẙ": "ẙ", - "ź": "ź", - "ž": "ž", - "ẑ": "ẑ", - "ż": "ż", - "Á": "Á", - "À": "À", - "Ä": "Ä", - "Ǟ": "Ǟ", - "Ã": "Ã", - "Ā": "Ā", - "Ă": "Ă", - "Ắ": "Ắ", - "Ằ": "Ằ", - "Ẵ": "Ẵ", - "Ǎ": "Ǎ", - "Â": "Â", - "Ấ": "Ấ", - "Ầ": "Ầ", - "Ẫ": "Ẫ", - "Ȧ": "Ȧ", - "Ǡ": "Ǡ", - "Å": "Å", - "Ǻ": "Ǻ", - "Ḃ": "Ḃ", - "Ć": "Ć", - "Č": "Č", - "Ĉ": "Ĉ", - "Ċ": "Ċ", - "Ď": "Ď", - "Ḋ": "Ḋ", - "É": "É", - "È": "È", - "Ë": "Ë", - "Ẽ": "Ẽ", - "Ē": "Ē", - "Ḗ": "Ḗ", - "Ḕ": "Ḕ", - "Ĕ": "Ĕ", - "Ě": "Ě", - "Ê": "Ê", - "Ế": "Ế", - "Ề": "Ề", - "Ễ": "Ễ", - "Ė": "Ė", - "Ḟ": "Ḟ", - "Ǵ": "Ǵ", - "Ḡ": "Ḡ", - "Ğ": "Ğ", - "Ǧ": "Ǧ", - "Ĝ": "Ĝ", - "Ġ": "Ġ", - "Ḧ": "Ḧ", - "Ȟ": "Ȟ", - "Ĥ": "Ĥ", - "Ḣ": "Ḣ", - "Í": "Í", - "Ì": "Ì", - "Ï": "Ï", - "Ḯ": "Ḯ", - "Ĩ": "Ĩ", - "Ī": "Ī", - "Ĭ": "Ĭ", - "Ǐ": "Ǐ", - "Î": "Î", - "İ": "İ", - "Ĵ": "Ĵ", - "Ḱ": "Ḱ", - "Ǩ": "Ǩ", - "Ĺ": "Ĺ", - "Ľ": "Ľ", - "Ḿ": "Ḿ", - "Ṁ": "Ṁ", - "Ń": "Ń", - "Ǹ": "Ǹ", - "Ñ": "Ñ", - "Ň": "Ň", - "Ṅ": "Ṅ", - "Ó": "Ó", - "Ò": "Ò", - "Ö": "Ö", - "Ȫ": "Ȫ", - "Õ": "Õ", - "Ṍ": "Ṍ", - "Ṏ": "Ṏ", - "Ȭ": "Ȭ", - "Ō": "Ō", - "Ṓ": "Ṓ", - "Ṑ": "Ṑ", - "Ŏ": "Ŏ", - "Ǒ": "Ǒ", - "Ô": "Ô", - "Ố": "Ố", - "Ồ": "Ồ", - "Ỗ": "Ỗ", - "Ȯ": "Ȯ", - "Ȱ": "Ȱ", - "Ő": "Ő", - "Ṕ": "Ṕ", - "Ṗ": "Ṗ", - "Ŕ": "Ŕ", - "Ř": "Ř", - "Ṙ": "Ṙ", - "Ś": "Ś", - "Ṥ": "Ṥ", - "Š": "Š", - "Ṧ": "Ṧ", - "Ŝ": "Ŝ", - "Ṡ": "Ṡ", - "Ť": "Ť", - "Ṫ": "Ṫ", - "Ú": "Ú", - "Ù": "Ù", - "Ü": "Ü", - "Ǘ": "Ǘ", - "Ǜ": "Ǜ", - "Ǖ": "Ǖ", - "Ǚ": "Ǚ", - "Ũ": "Ũ", - "Ṹ": "Ṹ", - "Ū": "Ū", - "Ṻ": "Ṻ", - "Ŭ": "Ŭ", - "Ǔ": "Ǔ", - "Û": "Û", - "Ů": "Ů", - "Ű": "Ű", - "Ṽ": "Ṽ", - "Ẃ": "Ẃ", - "Ẁ": "Ẁ", - "Ẅ": "Ẅ", - "Ŵ": "Ŵ", - "Ẇ": "Ẇ", - "Ẍ": "Ẍ", - "Ẋ": "Ẋ", - "Ý": "Ý", - "Ỳ": "Ỳ", - "Ÿ": "Ÿ", - "Ỹ": "Ỹ", - "Ȳ": "Ȳ", - "Ŷ": "Ŷ", - "Ẏ": "Ẏ", - "Ź": "Ź", - "Ž": "Ž", - "Ẑ": "Ẑ", - "Ż": "Ż", - "ά": "ά", - "ὰ": "ὰ", - "ᾱ": "ᾱ", - "ᾰ": "ᾰ", - "έ": "έ", - "ὲ": "ὲ", - "ή": "ή", - "ὴ": "ὴ", - "ί": "ί", - "ὶ": "ὶ", - "ϊ": "ϊ", - "ΐ": "ΐ", - "ῒ": "ῒ", - "ῑ": "ῑ", - "ῐ": "ῐ", - "ό": "ό", - "ὸ": "ὸ", - "ύ": "ύ", - "ὺ": "ὺ", - "ϋ": "ϋ", - "ΰ": "ΰ", - "ῢ": "ῢ", - "ῡ": "ῡ", - "ῠ": "ῠ", - "ώ": "ώ", - "ὼ": "ὼ", - "Ύ": "Ύ", - "Ὺ": "Ὺ", - "Ϋ": "Ϋ", - "Ῡ": "Ῡ", - "Ῠ": "Ῠ", - "Ώ": "Ώ", - "Ὼ": "Ὼ" - }; - - /* eslint no-constant-condition:0 */ - - const numberRegEx = /^\d(?:[\d,.]*\d)?$/; // Keep in sync with numberRegEx in symbolsOrd.js - - /** - * This file contains the parser used to parse out a TeX expression from the - * input. Since TeX isn't context-free, standard parsers don't work particularly - * well. - * - * The strategy of this parser is as such: - * - * The main functions (the `.parse...` ones) take a position in the current - * parse string to parse tokens from. The lexer (found in Lexer.js, stored at - * this.gullet.lexer) also supports pulling out tokens at arbitrary places. When - * individual tokens are needed at a position, the lexer is called to pull out a - * token, which is then used. - * - * The parser has a property called "mode" indicating the mode that - * the parser is currently in. Currently it has to be one of "math" or - * "text", which denotes whether the current environment is a math-y - * one or a text-y one (e.g. inside \text). Currently, this serves to - * limit the functions which can be used in text mode. - * - * The main functions then return an object which contains the useful data that - * was parsed at its given point, and a new position at the end of the parsed - * data. The main functions can call each other and continue the parsing by - * using the returned position as a new starting point. - * - * There are also extra `.handle...` functions, which pull out some reused - * functionality into self-contained functions. - * - * The functions return ParseNodes. - */ - - class Parser { - constructor(input, settings, isPreamble = false) { - // Start in math mode - this.mode = "math"; - // Create a new macro expander (gullet) and (indirectly via that) also a - // new lexer (mouth) for this parser (stomach, in the language of TeX) - this.gullet = new MacroExpander(input, settings, this.mode); - // Store the settings for use in parsing - this.settings = settings; - // Are we defining a preamble? - this.isPreamble = isPreamble; - // Count leftright depth (for \middle errors) - this.leftrightDepth = 0; - this.prevAtomType = ""; - } - - /** - * Checks a result to make sure it has the right type, and throws an - * appropriate error otherwise. - */ - expect(text, consume = true) { - if (this.fetch().text !== text) { - throw new ParseError(`Expected '${text}', got '${this.fetch().text}'`, this.fetch()); - } - if (consume) { - this.consume(); - } - } - - /** - * Discards the current lookahead token, considering it consumed. - */ - consume() { - this.nextToken = null; - } - - /** - * Return the current lookahead token, or if there isn't one (at the - * beginning, or if the previous lookahead token was consume()d), - * fetch the next token as the new lookahead token and return it. - */ - fetch() { - if (this.nextToken == null) { - this.nextToken = this.gullet.expandNextToken(); - } - return this.nextToken; - } - - /** - * Switches between "text" and "math" modes. - */ - switchMode(newMode) { - this.mode = newMode; - this.gullet.switchMode(newMode); - } - - /** - * Main parsing function, which parses an entire input. - */ - parse() { - // Create a group namespace for every $...$, $$...$$, \[...\].) - // A \def is then valid only within that pair of delimiters. - this.gullet.beginGroup(); - - if (this.settings.colorIsTextColor) { - // Use old \color behavior (same as LaTeX's \textcolor) if requested. - // We do this within the group for the math expression, so it doesn't - // pollute settings.macros. - this.gullet.macros.set("\\color", "\\textcolor"); - } - - // Try to parse the input - const parse = this.parseExpression(false); - - // If we succeeded, make sure there's an EOF at the end - this.expect("EOF"); - - if (this.isPreamble) { - const macros = Object.create(null); - Object.entries(this.gullet.macros.current).forEach(([key, value]) => { - macros[key] = value; - }); - this.gullet.endGroup(); - return macros - } - - // The only local macro that we want to save is from \tag. - const tag = this.gullet.macros.get("\\df@tag"); - - // End the group namespace for the expression - this.gullet.endGroup(); - - if (tag) { this.gullet.macros.current["\\df@tag"] = tag; } - - return parse; - } - - static get endOfExpression() { - return ["}", "\\endgroup", "\\end", "\\right", "\\endtoggle", "&"]; - } - - /** - * Parses an "expression", which is a list of atoms. - * - * `breakOnInfix`: Should the parsing stop when we hit infix nodes? This - * happens when functions have higher precendence han infix - * nodes in implicit parses. - * - * `breakOnTokenText`: The text of the token that the expression should end - * with, or `null` if something else should end the - * expression. - */ - parseExpression(breakOnInfix, breakOnTokenText) { - const body = []; - // Keep adding atoms to the body until we can't parse any more atoms (either - // we reached the end, a }, or a \right) - while (true) { - // Ignore spaces in math mode - if (this.mode === "math") { - this.consumeSpaces(); - } - const lex = this.fetch(); - if (Parser.endOfExpression.indexOf(lex.text) !== -1) { - break; - } - if (breakOnTokenText && lex.text === breakOnTokenText) { - break; - } - if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) { - break; - } - const atom = this.parseAtom(breakOnTokenText); - if (!atom) { - break; - } else if (atom.type === "internal") { - continue; - } - body.push(atom); - // Keep a record of the atom type, so that op.js can set correct spacing. - this.prevAtomType = atom.type === "atom" ? atom.family : atom.type; - } - if (this.mode === "text") { - this.formLigatures(body); - } - return this.handleInfixNodes(body); - } - - /** - * Rewrites infix operators such as \over with corresponding commands such - * as \frac. - * - * There can only be one infix operator per group. If there's more than one - * then the expression is ambiguous. This can be resolved by adding {}. - */ - handleInfixNodes(body) { - let overIndex = -1; - let funcName; - - for (let i = 0; i < body.length; i++) { - if (body[i].type === "infix") { - if (overIndex !== -1) { - throw new ParseError("only one infix operator per group", body[i].token); - } - overIndex = i; - funcName = body[i].replaceWith; - } - } - - if (overIndex !== -1 && funcName) { - let numerNode; - let denomNode; - - const numerBody = body.slice(0, overIndex); - const denomBody = body.slice(overIndex + 1); - - if (numerBody.length === 1 && numerBody[0].type === "ordgroup") { - numerNode = numerBody[0]; - } else { - numerNode = { type: "ordgroup", mode: this.mode, body: numerBody }; - } - - if (denomBody.length === 1 && denomBody[0].type === "ordgroup") { - denomNode = denomBody[0]; - } else { - denomNode = { type: "ordgroup", mode: this.mode, body: denomBody }; - } - - let node; - if (funcName === "\\\\abovefrac") { - node = this.callFunction(funcName, [numerNode, body[overIndex], denomNode], []); - } else { - node = this.callFunction(funcName, [numerNode, denomNode], []); - } - return [node]; - } else { - return body; - } - } - - /** - * Handle a subscript or superscript with nice errors. - */ - handleSupSubscript( - name // For error reporting. - ) { - const symbolToken = this.fetch(); - const symbol = symbolToken.text; - this.consume(); - this.consumeSpaces(); // ignore spaces before sup/subscript argument - const group = this.parseGroup(name); - - if (!group) { - throw new ParseError("Expected group after '" + symbol + "'", symbolToken); - } - - return group; - } - - /** - * Converts the textual input of an unsupported command into a text node - * contained within a color node whose color is determined by errorColor - */ - formatUnsupportedCmd(text) { - const textordArray = []; - - for (let i = 0; i < text.length; i++) { - textordArray.push({ type: "textord", mode: "text", text: text[i] }); - } - - const textNode = { - type: "text", - mode: this.mode, - body: textordArray - }; - - const colorNode = { - type: "color", - mode: this.mode, - color: this.settings.errorColor, - body: [textNode] - }; - - return colorNode; - } - - /** - * Parses a group with optional super/subscripts. - */ - parseAtom(breakOnTokenText) { - // The body of an atom is an implicit group, so that things like - // \left(x\right)^2 work correctly. - const base = this.parseGroup("atom", breakOnTokenText); - - // In text mode, we don't have superscripts or subscripts - if (this.mode === "text") { - return base; - } - - // Note that base may be empty (i.e. null) at this point. - - let superscript; - let subscript; - while (true) { - // Guaranteed in math mode, so eat any spaces first. - this.consumeSpaces(); - - // Lex the first token - const lex = this.fetch(); - - if (lex.text === "\\limits" || lex.text === "\\nolimits") { - // We got a limit control - if (base && base.type === "op") { - const limits = lex.text === "\\limits"; - base.limits = limits; - base.alwaysHandleSupSub = true; - } else if (base && base.type === "operatorname") { - if (base.alwaysHandleSupSub) { - base.limits = lex.text === "\\limits"; - } - } else { - throw new ParseError("Limit controls must follow a math operator", lex); - } - this.consume(); - } else if (lex.text === "^") { - // We got a superscript start - if (superscript) { - throw new ParseError("Double superscript", lex); - } - superscript = this.handleSupSubscript("superscript"); - } else if (lex.text === "_") { - // We got a subscript start - if (subscript) { - throw new ParseError("Double subscript", lex); - } - subscript = this.handleSupSubscript("subscript"); - } else if (lex.text === "'") { - // We got a prime - if (superscript) { - throw new ParseError("Double superscript", lex); - } - const prime = { type: "textord", mode: this.mode, text: "\\prime" }; - - // Many primes can be grouped together, so we handle this here - const primes = [prime]; - this.consume(); - // Keep lexing tokens until we get something that's not a prime - while (this.fetch().text === "'") { - // For each one, add another prime to the list - primes.push(prime); - this.consume(); - } - // If there's a superscript following the primes, combine that - // superscript in with the primes. - if (this.fetch().text === "^") { - primes.push(this.handleSupSubscript("superscript")); - } - // Put everything into an ordgroup as the superscript - superscript = { type: "ordgroup", mode: this.mode, body: primes }; - } else if (uSubsAndSups[lex.text]) { - // A Unicode subscript or superscript character. - // We treat these similarly to the unicode-math package. - // So we render a string of Unicode (sub|super)scripts the - // same as a (sub|super)script of regular characters. - let str = uSubsAndSups[lex.text]; - const isSub = unicodeSubRegEx.test(lex.text); - this.consume(); - // Continue fetching tokens to fill out the string. - while (true) { - const token = this.fetch().text; - if (!(uSubsAndSups[token])) { break } - if (unicodeSubRegEx.test(token) !== isSub) { break } - this.consume(); - str += uSubsAndSups[token]; - } - // Now create a (sub|super)script. - const body = (new Parser(str, this.settings)).parse(); - if (isSub) { - subscript = { type: "ordgroup", mode: "math", body }; - } else { - superscript = { type: "ordgroup", mode: "math", body }; - } - } else { - // If it wasn't ^, _, a Unicode (sub|super)script, or ', stop parsing super/subscripts - break; - } - } - - if (superscript || subscript) { - if (base && base.type === "multiscript" && !base.postscripts) { - // base is the result of a \prescript function. - // Write the sub- & superscripts into the multiscript element. - base.postscripts = { sup: superscript, sub: subscript }; - return base - } else { - // We got either a superscript or subscript, create a supsub - return { - type: "supsub", - mode: this.mode, - base: base, - sup: superscript, - sub: subscript - } - } - } else { - // Otherwise return the original body - return base; - } - } - - /** - * Parses an entire function, including its base and all of its arguments. - */ - parseFunction( - breakOnTokenText, - name // For determining its context - ) { - const token = this.fetch(); - const func = token.text; - const funcData = functions[func]; - if (!funcData) { - return null; - } - this.consume(); // consume command token - - if (name && name !== "atom" && !funcData.allowedInArgument) { - throw new ParseError( - "Got function '" + func + "' with no arguments" + (name ? " as " + name : ""), - token - ); - } else if (this.mode === "text" && !funcData.allowedInText) { - throw new ParseError("Can't use function '" + func + "' in text mode", token); - } else if (this.mode === "math" && funcData.allowedInMath === false) { - throw new ParseError("Can't use function '" + func + "' in math mode", token); - } - - const prevAtomType = this.prevAtomType; - const { args, optArgs } = this.parseArguments(func, funcData); - this.prevAtomType = prevAtomType; - return this.callFunction(func, args, optArgs, token, breakOnTokenText); - } - - /** - * Call a function handler with a suitable context and arguments. - */ - callFunction(name, args, optArgs, token, breakOnTokenText) { - const context = { - funcName: name, - parser: this, - token, - breakOnTokenText - }; - const func = functions[name]; - if (func && func.handler) { - return func.handler(context, args, optArgs); - } else { - throw new ParseError(`No function handler for ${name}`); - } - } - - /** - * Parses the arguments of a function or environment - */ - parseArguments( - func, // Should look like "\name" or "\begin{name}". - funcData - ) { - const totalArgs = funcData.numArgs + funcData.numOptionalArgs; - if (totalArgs === 0) { - return { args: [], optArgs: [] }; - } - - const args = []; - const optArgs = []; - - for (let i = 0; i < totalArgs; i++) { - let argType = funcData.argTypes && funcData.argTypes[i]; - const isOptional = i < funcData.numOptionalArgs; - - if ( - (funcData.primitive && argType == null) || - // \sqrt expands into primitive if optional argument doesn't exist - (funcData.type === "sqrt" && i === 1 && optArgs[0] == null) - ) { - argType = "primitive"; - } - - const arg = this.parseGroupOfType(`argument to '${func}'`, argType, isOptional); - if (isOptional) { - optArgs.push(arg); - } else if (arg != null) { - args.push(arg); - } else { - // should be unreachable - throw new ParseError("Null argument, please report this as a bug"); - } - } - - return { args, optArgs }; - } - - /** - * Parses a group when the mode is changing. - */ - parseGroupOfType(name, type, optional) { - switch (type) { - case "size": - return this.parseSizeGroup(optional); - case "url": - return this.parseUrlGroup(optional); - case "math": - case "text": - return this.parseArgumentGroup(optional, type); - case "hbox": { - // hbox argument type wraps the argument in the equivalent of - // \hbox, which is like \text but switching to \textstyle size. - const group = this.parseArgumentGroup(optional, "text"); - return group != null - ? { - type: "styling", - mode: group.mode, - body: [group], - scriptLevel: "text" // simulate \textstyle - } - : null; - } - case "raw": { - const token = this.parseStringGroup("raw", optional); - return token != null - ? { - type: "raw", - mode: "text", - string: token.text - } - : null; - } - case "primitive": { - if (optional) { - throw new ParseError("A primitive argument cannot be optional"); - } - const group = this.parseGroup(name); - if (group == null) { - throw new ParseError("Expected group as " + name, this.fetch()); - } - return group; - } - case "original": - case null: - case undefined: - return this.parseArgumentGroup(optional); - default: - throw new ParseError("Unknown group type as " + name, this.fetch()); - } - } - - /** - * Discard any space tokens, fetching the next non-space token. - */ - consumeSpaces() { - while (this.fetch().text === " ") { - this.consume(); - } - } - - /** - * Parses a group, essentially returning the string formed by the - * brace-enclosed tokens plus some position information. - */ - parseStringGroup( - modeName, // Used to describe the mode in error messages. - optional - ) { - const argToken = this.gullet.scanArgument(optional); - if (argToken == null) { - return null; - } - let str = ""; - let nextToken; - while ((nextToken = this.fetch()).text !== "EOF") { - str += nextToken.text; - this.consume(); - } - this.consume(); // consume the end of the argument - argToken.text = str; - return argToken; - } - - /** - * Parses a regex-delimited group: the largest sequence of tokens - * whose concatenated strings match `regex`. Returns the string - * formed by the tokens plus some position information. - */ - parseRegexGroup( - regex, - modeName // Used to describe the mode in error messages. - ) { - const firstToken = this.fetch(); - let lastToken = firstToken; - let str = ""; - let nextToken; - while ((nextToken = this.fetch()).text !== "EOF" && regex.test(str + nextToken.text)) { - lastToken = nextToken; - str += lastToken.text; - this.consume(); - } - if (str === "") { - throw new ParseError("Invalid " + modeName + ": '" + firstToken.text + "'", firstToken); - } - return firstToken.range(lastToken, str); - } - - /** - * Parses a size specification, consisting of magnitude and unit. - */ - parseSizeGroup(optional) { - let res; - let isBlank = false; - // don't expand before parseStringGroup - this.gullet.consumeSpaces(); - if (!optional && this.gullet.future().text !== "{") { - res = this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size"); - } else { - res = this.parseStringGroup("size", optional); - } - if (!res) { - return null; - } - if (!optional && res.text.length === 0) { - // Because we've tested for what is !optional, this block won't - // affect \kern, \hspace, etc. It will capture the mandatory arguments - // to \genfrac and \above. - res.text = "0pt"; // Enable \above{} - isBlank = true; // This is here specifically for \genfrac - } - const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(res.text); - if (!match) { - throw new ParseError("Invalid size: '" + res.text + "'", res); - } - const data = { - number: +(match[1] + match[2]), // sign + magnitude, cast to number - unit: match[3] - }; - if (!validUnit(data)) { - throw new ParseError("Invalid unit: '" + data.unit + "'", res); - } - return { - type: "size", - mode: this.mode, - value: data, - isBlank - }; - } - - /** - * Parses an URL, checking escaped letters and allowed protocols, - * and setting the catcode of % as an active character (as in \hyperref). - */ - parseUrlGroup(optional) { - this.gullet.lexer.setCatcode("%", 13); // active character - this.gullet.lexer.setCatcode("~", 12); // other character - const res = this.parseStringGroup("url", optional); - this.gullet.lexer.setCatcode("%", 14); // comment character - this.gullet.lexer.setCatcode("~", 13); // active character - if (res == null) { - return null; - } - // hyperref package allows backslashes alone in href, but doesn't - // generate valid links in such cases; we interpret this as - // "undefined" behaviour, and keep them as-is. Some browser will - // replace backslashes with forward slashes. - let url = res.text.replace(/\\([#$%&~_^{}])/g, "$1"); - url = res.text.replace(/{\u2044}/g, "/"); - return { - type: "url", - mode: this.mode, - url - }; - } - - /** - * Parses an argument with the mode specified. - */ - parseArgumentGroup(optional, mode) { - const argToken = this.gullet.scanArgument(optional); - if (argToken == null) { - return null; - } - const outerMode = this.mode; - if (mode) { - // Switch to specified mode - this.switchMode(mode); - } - - this.gullet.beginGroup(); - const expression = this.parseExpression(false, "EOF"); - // TODO: find an alternative way to denote the end - this.expect("EOF"); // expect the end of the argument - this.gullet.endGroup(); - const result = { - type: "ordgroup", - mode: this.mode, - loc: argToken.loc, - body: expression - }; - - if (mode) { - // Switch mode back - this.switchMode(outerMode); - } - return result; - } - - /** - * Parses an ordinary group, which is either a single nucleus (like "x") - * or an expression in braces (like "{x+y}") or an implicit group, a group - * that starts at the current position, and ends right before a higher explicit - * group ends, or at EOF. - */ - parseGroup( - name, // For error reporting. - breakOnTokenText - ) { - const firstToken = this.fetch(); - const text = firstToken.text; - - let result; - // Try to parse an open brace or \begingroup - if (text === "{" || text === "\\begingroup" || text === "\\toggle") { - this.consume(); - const groupEnd = text === "{" - ? "}" - : text === "\\begingroup" - ? "\\endgroup" - : "\\endtoggle"; - - this.gullet.beginGroup(); - // If we get a brace, parse an expression - const expression = this.parseExpression(false, groupEnd); - const lastToken = this.fetch(); - this.expect(groupEnd); // Check that we got a matching closing brace - this.gullet.endGroup(); - result = { - type: (lastToken.text === "\\endtoggle" ? "toggle" : "ordgroup"), - mode: this.mode, - loc: SourceLocation.range(firstToken, lastToken), - body: expression, - // A group formed by \begingroup...\endgroup is a semi-simple group - // which doesn't affect spacing in math mode, i.e., is transparent. - // https://tex.stackexchange.com/questions/1930/when-should-one- - // use-begingroup-instead-of-bgroup - semisimple: text === "\\begingroup" || undefined - }; - } else { - // If there exists a function with this name, parse the function. - // Otherwise, just return a nucleus - result = this.parseFunction(breakOnTokenText, name) || this.parseSymbol(); - if (result == null && text[0] === "\\" && - !Object.prototype.hasOwnProperty.call(implicitCommands, text )) { - result = this.formatUnsupportedCmd(text); - this.consume(); - } - } - return result; - } - - /** - * Form ligature-like combinations of characters for text mode. - * This includes inputs like "--", "---", "``" and "''". - * The result will simply replace multiple textord nodes with a single - * character in each value by a single textord node having multiple - * characters in its value. The representation is still ASCII source. - * The group will be modified in place. - */ - formLigatures(group) { - let n = group.length - 1; - for (let i = 0; i < n; ++i) { - const a = group[i]; - const v = a.text; - if (v === "-" && group[i + 1].text === "-") { - if (i + 1 < n && group[i + 2].text === "-") { - group.splice(i, 3, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 2]), - text: "---" - }); - n -= 2; - } else { - group.splice(i, 2, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 1]), - text: "--" - }); - n -= 1; - } - } - if ((v === "'" || v === "`") && group[i + 1].text === v) { - group.splice(i, 2, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 1]), - text: v + v - }); - n -= 1; - } - } - } - - /** - * Parse a single symbol out of the string. Here, we handle single character - * symbols and special functions like \verb. - */ - parseSymbol() { - const nucleus = this.fetch(); - let text = nucleus.text; - - if (/^\\verb[^a-zA-Z]/.test(text)) { - this.consume(); - let arg = text.slice(5); - const star = arg.charAt(0) === "*"; - if (star) { - arg = arg.slice(1); - } - // Lexer's tokenRegex is constructed to always have matching - // first/last characters. - if (arg.length < 2 || arg.charAt(0) !== arg.slice(-1)) { - throw new ParseError(`\\verb assertion failed -- - please report what input caused this bug`); - } - arg = arg.slice(1, -1); // remove first and last char - return { - type: "verb", - mode: "text", - body: arg, - star - }; - } - // At this point, we should have a symbol, possibly with accents. - // First expand any accented base symbol according to unicodeSymbols. - if (Object.prototype.hasOwnProperty.call(unicodeSymbols, text[0]) && - !symbols[this.mode][text[0]]) { - // This behavior is not strict (XeTeX-compatible) in math mode. - if (this.settings.strict && this.mode === "math") { - throw new ParseError(`Accented Unicode text character "${text[0]}" used in ` + `math mode`, - nucleus - ); - } - text = unicodeSymbols[text[0]] + text.slice(1); - } - // Strip off any combining characters - const match = combiningDiacriticalMarksEndRegex.exec(text); - if (match) { - text = text.substring(0, match.index); - if (text === "i") { - text = "\u0131"; // dotless i, in math and text mode - } else if (text === "j") { - text = "\u0237"; // dotless j, in math and text mode - } - } - // Recognize base symbol - let symbol; - if (symbols[this.mode][text]) { - const group = symbols[this.mode][text].group; - const loc = SourceLocation.range(nucleus); - let s; - if (Object.prototype.hasOwnProperty.call(ATOMS, group )) { - const family = group; - s = { - type: "atom", - mode: this.mode, - family, - loc, - text - }; - } else { - s = { - type: group, - mode: this.mode, - loc, - text - }; - } - symbol = s; - } else if (!this.strict && numberRegEx.test(text)) { - // A number. Wrap in a if in math mode; otherwise. - this.consume(); - return { - type: "textord", - mode: this.mode, - loc: SourceLocation.range(nucleus), - text - } - } else if (text.charCodeAt(0) >= 0x80) { - // no symbol for e.g. ^ - if (this.settings.strict) { - if (!supportedCodepoint(text.charCodeAt(0))) { - throw new ParseError(`Unrecognized Unicode character "${text[0]}"` + - ` (${text.charCodeAt(0)})`, nucleus); - } else if (this.mode === "math") { - throw new ParseError(`Unicode text character "${text[0]}" used in math mode`, nucleus) - } - } - // All nonmathematical Unicode characters are rendered as if they - // are in text mode (wrapped in \text) because that's what it - // takes to render them in LaTeX. - symbol = { - type: "textord", - mode: "text", - loc: SourceLocation.range(nucleus), - text - }; - } else { - return null; // EOF, ^, _, {, }, etc. - } - this.consume(); - // Transform combining characters into accents - if (match) { - for (let i = 0; i < match[0].length; i++) { - const accent = match[0][i]; - if (!unicodeAccents[accent]) { - throw new ParseError(`Unknown accent ' ${accent}'`, nucleus); - } - const command = unicodeAccents[accent][this.mode] || - unicodeAccents[accent].text; - if (!command) { - throw new ParseError(`Accent ${accent} unsupported in ${this.mode} mode`, nucleus); - } - symbol = { - type: "accent", - mode: this.mode, - loc: SourceLocation.range(nucleus), - label: command, - isStretchy: false, - isShifty: true, - base: symbol - }; - } - } - return symbol; - } - } - - /** - * Parses an expression using a Parser, then returns the parsed result. - */ - const parseTree = function(toParse, settings) { - if (!(typeof toParse === "string" || toParse instanceof String)) { - throw new TypeError("Temml can only parse string typed expression") - } - const parser = new Parser(toParse, settings); - // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors - delete parser.gullet.macros.current["\\df@tag"]; - - let tree = parser.parse(); - - // LaTeX ignores a \tag placed outside an AMS environment. - if (!(tree.length > 0 && tree[0].type && tree[0].type === "array" && tree[0].addEqnNum)) { - // If the input used \tag, it will set the \df@tag macro to the tag. - // In this case, we separately parse the tag and wrap the tree. - if (parser.gullet.macros.get("\\df@tag")) { - if (!settings.displayMode) { - throw new ParseError("\\tag works only in display mode") - } - parser.gullet.feed("\\df@tag"); - tree = [ - { - type: "tag", - mode: "text", - body: tree, - tag: parser.parse() - } - ]; - } - } - - return tree - }; - - /** - * This file contains information about the style that the mathmlBuilder carries - * around with it. Data is held in an `Style` object, and when - * recursing, a new `Style` object can be created with the `.with*` functions. - */ - - const subOrSupLevel = [2, 2, 3, 3]; - - /** - * This is the main Style class. It contains the current style.level, color, and font. - * - * Style objects should not be modified. To create a new Style with - * different properties, call a `.with*` method. - */ - class Style { - constructor(data) { - // Style.level can be 0 | 1 | 2 | 3, which correspond to - // displaystyle, textstyle, scriptstyle, and scriptscriptstyle. - // style.level does not directly set MathML's script level. MathML does that itself. - // We use style.level to track, not set, math style so that we can get the - // correct scriptlevel when needed in supsub.js, mathchoice.js, or for dimensions in em. - this.level = data.level; - this.color = data.color; // string | void - // A font family applies to a group of fonts (i.e. SansSerif), while a font - // represents a specific font (i.e. SansSerif Bold). - // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm - this.font = data.font || ""; // string - this.fontFamily = data.fontFamily || ""; // string - this.fontSize = data.fontSize || 1.0; // number - this.fontWeight = data.fontWeight || ""; - this.fontShape = data.fontShape || ""; - this.maxSize = data.maxSize; // [number, number] - } - - /** - * Returns a new style object with the same properties as "this". Properties - * from "extension" will be copied to the new style object. - */ - extend(extension) { - const data = { - level: this.level, - color: this.color, - font: this.font, - fontFamily: this.fontFamily, - fontSize: this.fontSize, - fontWeight: this.fontWeight, - fontShape: this.fontShape, - maxSize: this.maxSize - }; - - for (const key in extension) { - if (Object.prototype.hasOwnProperty.call(extension, key)) { - data[key] = extension[key]; - } - } - - return new Style(data); - } - - withLevel(n) { - return this.extend({ - level: n - }); - } - - incrementLevel() { - return this.extend({ - level: Math.min(this.level + 1, 3) - }); - } - - inSubOrSup() { - return this.extend({ - level: subOrSupLevel[this.level] - }) - } - - /** - * Create a new style object with the given color. - */ - withColor(color) { - return this.extend({ - color: color - }); - } - - /** - * Creates a new style object with the given math font or old text font. - * @type {[type]} - */ - withFont(font) { - return this.extend({ - font - }); - } - - /** - * Create a new style objects with the given fontFamily. - */ - withTextFontFamily(fontFamily) { - return this.extend({ - fontFamily, - font: "" - }); - } - - /** - * Creates a new style object with the given font size - */ - withFontSize(num) { - return this.extend({ - fontSize: num - }); - } - - /** - * Creates a new style object with the given font weight - */ - withTextFontWeight(fontWeight) { - return this.extend({ - fontWeight, - font: "" - }); - } - - /** - * Creates a new style object with the given font weight - */ - withTextFontShape(fontShape) { - return this.extend({ - fontShape, - font: "" - }); - } - - /** - * Gets the CSS color of the current style object - */ - getColor() { - return this.color; - } - } - - /* Temml Post Process - * Perform two tasks not done by Temml when it created each individual Temml element. - * Given a block of block, - * 1. At each AMS auto-numbered environment, assign an id. - * 2. Populate the text contents of each \ref & \eqref - * - * As with other Temml code, this file is released under terms of the MIT license. - * https://mit-license.org/ - */ - - const version = "0.6.9"; - - function postProcess(block) { - const labelMap = {}; - let i = 0; - - // Get a collection of the parents of each \tag & auto-numbered equation - const parents = block.getElementsByClassName("tml-tageqn"); - for (const parent of parents) { - const eqns = parent.getElementsByClassName("tml-eqn"); - if (eqns. length > 0 ) { - // AMS automatically numbered equation. - // Assign an id. - i += 1; - eqns[0].id = "tml-eqn-" + i; - // No need to write a number into the text content of the element. - // A CSS counter does that even if this postProcess() function is not used. - } - // If there is a \label, add it to labelMap - const labels = parent.getElementsByClassName("tml-label"); - if (labels.length === 0) { continue } - if (eqns.length > 0) { - labelMap[labels[0].id] = String(i); - } else { - const tags = parent.getElementsByClassName("tml-tag"); - if (tags.length > 0) { - labelMap[labels[0].id] = tags[0].textContent; - } - } - } - - // Populate \ref & \eqref text content - const refs = block.getElementsByClassName("tml-ref"); - [...refs].forEach(ref => { - let str = labelMap[ref.getAttribute("href").slice(1)]; - if (ref.className.indexOf("tml-eqref") === -1) { - // \ref. Omit parens. - str = str.replace(/^\(/, ""); - str = str.replace(/\($/, ""); - } { - // \eqref. Include parens - if (str.charAt(0) !== "(") { str = "(" + str; } - if (str.slice(-1) !== ")") { str = str + ")"; } - } - ref.textContent = str; - }); - } - - /* eslint no-console:0 */ - - /** - * Parse and build an expression, and place that expression in the DOM node - * given. - */ - let render = function(expression, baseNode, options) { - baseNode.textContent = ""; - const math = renderToMathMLTree(expression, options); - if (options.elementIsMath) { - // The element already exists. Populate it. - baseNode.textContent = ""; - math.children.forEach(e => { baseNode.appendChild(e.toNode()); }); - } else { - baseNode.appendChild(math.toNode()); - } - }; - - // Temml's styles don't work properly in quirks mode. Print out an error, and - // disable rendering. - if (typeof document !== "undefined") { - if (document.compatMode !== "CSS1Compat") { - typeof console !== "undefined" && - console.warn( - "Warning: Temml doesn't work in quirks mode. Make sure your " + - "website has a suitable doctype." - ); - - render = function() { - throw new ParseError("Temml doesn't work in quirks mode."); - }; - } - } - - /** - * Parse and build an expression, and return the markup for that. - */ - const renderToString = function(expression, options) { - const markup = renderToMathMLTree(expression, options).toMarkup(); - return markup; - }; - - /** - * Parse an expression and return the parse tree. - */ - const generateParseTree = function(expression, options) { - const settings = new Settings(options); - return parseTree(expression, settings); - }; - - /** - * Take an expression which contains a preamble. - * Parse it and return the macros. - */ - const definePreamble = function(expression, options) { - const settings = new Settings(options); - settings.macros = {}; - if (!(typeof expression === "string" || expression instanceof String)) { - throw new TypeError("Temml can only parse string typed expression") - } - const parser = new Parser(expression, settings, true); - // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors - delete parser.gullet.macros.current["\\df@tag"]; - const macros = parser.parse(); - return macros - }; - - /** - * If the given error is a Temml ParseError, - * renders the invalid LaTeX as a span with hover title giving the Temml - * error message. Otherwise, simply throws the error. - */ - const renderError = function(error, expression, options) { - if (options.throwOnError || !(error instanceof ParseError)) { - throw error; - } - const node = new Span(["temml-error"], [new TextNode$1(expression + "\n" + error.toString())]); - node.style.color = options.errorColor; - node.style.whiteSpace = "pre-line"; - return node; - }; - - /** - * Generates and returns the Temml build tree. This is used for advanced - * use cases (like rendering to custom output). - */ - const renderToMathMLTree = function(expression, options) { - const settings = new Settings(options); - try { - const tree = parseTree(expression, settings); - const style = new Style({ - level: settings.displayMode ? StyleLevel.DISPLAY : StyleLevel.TEXT, - maxSize: settings.maxSize - }); - return buildMathML(tree, expression, style, settings); - } catch (error) { - return renderError(error, expression, settings); - } - }; - - var temml = { - /** - * Current Temml version - */ - version: version, - /** - * Renders the given LaTeX into MathML, and adds - * it as a child to the specified DOM node. - */ - render, - /** - * Renders the given LaTeX into MathML string, - * for sending to the client. - */ - renderToString, - /** - * Post-process an entire HTML block. - * Writes AMS auto-numbers and implements \ref{}. - * Typcally called once, after a loop has rendered many individual spans. - */ - postProcess, - /** - * Temml error, usually during parsing. - */ - ParseError, - /** - * Creates a set of macros with document-wide scope. - */ - definePreamble, - /** - * Parses the given LaTeX into Temml's internal parse tree structure, - * without rendering to HTML or MathML. - * - * NOTE: This method is not currently recommended for public use. - * The internal tree representation is unstable and is very likely - * to change. Use at your own risk. - */ - __parse: generateParseTree, - /** - * Renders the given LaTeX into a MathML internal DOM tree - * representation, without flattening that representation to a string. - * - * NOTE: This method is not currently recommended for public use. - * The internal tree representation is unstable and is very likely - * to change. Use at your own risk. - */ - __renderToMathMLTree: renderToMathMLTree, - /** - * adds a new symbol to builtin symbols table - */ - __defineSymbol: defineSymbol, - /** - * adds a new macro to builtin macro list - */ - __defineMacro: defineMacro - }; - - return temml; - -})(); diff --git a/test/temmlPostProcess.js b/test/temmlPostProcess.js deleted file mode 100644 index 51122a14..00000000 --- a/test/temmlPostProcess.js +++ /dev/null @@ -1,70 +0,0 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.temml = {})); -})(this, (function (exports) { 'use strict'; - - /* Temml Post Process - * Perform two tasks not done by Temml when it created each individual Temml element. - * Given a block of block, - * 1. At each AMS auto-numbered environment, assign an id. - * 2. Populate the text contents of each \ref & \eqref - * - * As with other Temml code, this file is released under terms of the MIT license. - * https://mit-license.org/ - */ - - const version = "0.6.9"; - - function postProcess(block) { - const labelMap = {}; - let i = 0; - - // Get a collection of the parents of each \tag & auto-numbered equation - const parents = block.getElementsByClassName("tml-tageqn"); - for (const parent of parents) { - const eqns = parent.getElementsByClassName("tml-eqn"); - if (eqns. length > 0 ) { - // AMS automatically numbered equation. - // Assign an id. - i += 1; - eqns[0].id = "tml-eqn-" + i; - // No need to write a number into the text content of the element. - // A CSS counter does that even if this postProcess() function is not used. - } - // If there is a \label, add it to labelMap - const labels = parent.getElementsByClassName("tml-label"); - if (labels.length === 0) { continue } - if (eqns.length > 0) { - labelMap[labels[0].id] = String(i); - } else { - const tags = parent.getElementsByClassName("tml-tag"); - if (tags.length > 0) { - labelMap[labels[0].id] = tags[0].textContent; - } - } - } - - // Populate \ref & \eqref text content - const refs = block.getElementsByClassName("tml-ref"); - [...refs].forEach(ref => { - let str = labelMap[ref.getAttribute("href").slice(1)]; - if (ref.className.indexOf("tml-eqref") === -1) { - // \ref. Omit parens. - str = str.replace(/^\(/, ""); - str = str.replace(/\($/, ""); - } { - // \eqref. Include parens - if (str.charAt(0) !== "(") { str = "(" + str; } - if (str.slice(-1) !== ")") { str = str + ")"; } - } - ref.textContent = str; - }); - } - - exports.postProcess = postProcess; - exports.version = version; - - Object.defineProperty(exports, '__esModule', { value: true }); - -})); diff --git a/test/unit-test.js b/test/unit-test.js deleted file mode 100644 index ec7e31ff..00000000 --- a/test/unit-test.js +++ /dev/null @@ -1,2146 +0,0 @@ -import temml from "../utils/temml.cjs"; // includess mhchem & physics extensions -import ParseError from "../src/ParseError"; -import parseTree from "../src/parseTree"; -import Settings from "../src/Settings"; -//import splitAtDelimiters from "../contrib/auto-render/splitAtDelimiters.js"; -// import renderMathInElement from "../contrib/auto-render/auto-render"; - -/* - * Unit tests for Temml. - * This file contains more than 1000 tests of various Temml functions. - * - * Sidenote: - * Temml aims to minimize dependency hell by minimizing dependencies. - * When Jest is installed, it adds several thousand files, so I don't use it. - * Instead, I use this roll-your-own testing class. - * - * Many of the tests in this file have been ported from the Jest tests in KaTeX. - */ - -// First, a few helpers. -const defaultSettings = _ => new Settings(); -const strictSettings = _ => new Settings({ strict: true }); -const displayMode = _ => new Settings({ displayMode: true }); -const trustSettings = _ => new Settings({ trust: true }); -const mathTagRegEx = /<\/?math>/g; - -// tagging literal -const r = x => x != null && Object.prototype.hasOwnProperty.call(x, 'raw') ? x.raw[0] : x; - -// Strip positions from ParseNodes. -const stripPositions = expr => { - if (typeof expr !== "object" || expr === null) { return expr } - if (expr.loc && expr.loc.lexer && typeof expr.loc.start === "number") { delete expr.loc } - Object.keys(expr).forEach(function(key) { stripPositions(expr[key]) }); - return expr; -}; - -const parse = (expr, settings = defaultSettings()) => { - const tree = parseTree(expr, settings) - return stripPositions(tree) -} - -function build(expr, settings) { - const builtMathML = temml.__renderToMathMLTree(expr, settings); - if (builtMathML.classes.indexOf('temml-error') >= 0) { return builtMathML } - return builtMathML.children; -} - -// This is the main testing function. -const test = () => { - // Before we write any tests, write an Expect class that mimics Jest expect(). - // The Expect class and the say() helper function are inside this closure - // so that they will have access to the `assertion` variable. - const say = problem => { - numFailures += 1 - console.log(assertion + ", but " + problem) - console.log("") - } - - class Expect { - constructor(input) { - this.input = input; - } - - toBe(x) { - numTests += 1 - if (this.input !== x) { say(this.input + " does not equal " + x) } - } - - toNotBe(x) { - numTests += 1 - if (this.input === x) { say(this.input + " equals " + x + "!") } - } - - toMatch(regEx) { - numTests += 1 - if (!regEx.test(this.input)) { say(this.input + " does not match the RegEx!") } - } - - toMatchSnapshot(str) { - numTests += 1 - const flattened = JSON.stringify(this.input) - if (flattened !== str) { say(flattened + " is not " + str) } - } - - toBeDefined() { - numTests += 1 - if (this.input === undefined) { say(this.input + " is undefinded") } - } - - toBeUndefined() { - numTests += 1 - if (this.input !== undefined) { say(this.input + " is defined.") } - } - - toHaveLength(expectedNum) { - numTests += 1 - if (!this.input.length) { say("No length!") } - if (this.input.length !== expectedNum) { say(this.input.length + " is not " + expectedNum) } - } - - toBeTruthy() { - numTests += 1 - if (!this.input) { say(this.input + " is not truthy.") } - } - - toBeCloseTo(expected) { - numTests += 1 - if (Math.abs(expected - this.input) >= 0.005) { - say(this.input + " is not close to " + expected) - } - } - - toContain(fragment) { - numTests += 1 - if (this.input.indexOf(fragment) === -1) { - say(this.input + " does not contain " + fragment) - } - } - - toNotContain(fragment) { - numTests += 1 - if (this.input.indexOf(fragment) !== -1) { - say(this.input + " contains " + fragment + "!") - } - } - - toParse(settings = defaultSettings()) { - numTests += 1 - let result = true - try { - const tree = parse(this.input, settings) - if (tree instanceof ParseError) { result = false } - if (tree.length === 1 && tree[0].color && tree[0].color === "#b22222") { result = false } - } catch (e) { - result = false - } - if (!result) { say(this.input + " does not parse.") } - } - - toNotParse(settings = defaultSettings()) { - numTests += 1 - let result = true - try { - const tree = parse(this.input, settings) - if (tree instanceof ParseError) { result = false } - if (tree.length === 1 && tree[0].color && tree[0].color === "#b22222") { result = false } - } catch (e) { - result = false - } - if (result) { say(this.input + " parses!") } - } - - toParseLike(str, settings = defaultSettings()) { - numTests += 1 - let result = true - try { - const tree = parse(this.input, settings) - if (tree instanceof ParseError) { result = false } - const comp = parse(str, settings) - if (comp instanceof ParseError) { result = false } - result = JSON.stringify(tree) === JSON.stringify(comp) - } catch (e) { - result = false - } - if (!result) { - say(this.input + " does not parse like " + str) - } - } - - toBuild(settings = defaultSettings()) { - numTests += 1 - let result = true - try { - const tree = build(this.input, settings) - if (tree.classes && tree.classes[0] === "temml-error") { result = false } - } catch (e) { - result = false - console.log(e) - } - if (!result) { - say(this.input + " does not build.") - } - } - - toNotBuild(settings = defaultSettings()) { - numTests += 1 - let result = true - try { - const tree = build(this.input, settings) - if (tree.classes && tree.classes[0] === "temml-error") { result = false } - } catch (e) { - result = false - } - if (result) { say(this.input + " builds!") } - } - - toBuildLike(str, settings = defaultSettings()) { - numTests += 1 - let result = true - try { - const tree = build(this.input, settings) - if (tree instanceof ParseError) { result = false } - const comp = build(str, settings) - if (comp instanceof ParseError) { result = false } - result = JSON.stringify(tree) === JSON.stringify(comp) - } catch (e) { - result = false - } - if (!result) { say(this.input + " does not build like " + str) } - } - } - - // Now we have an Expect class. Here come lots of tests. - - let numTests = 0 - let numFailures = 0 - console.log("") - - let assertion = "Parser should work" - new Expect("").toParse() - new Expect("1234|/@.`abcdefgzABCDEFGZ").toParse() - - assertion = "Parser should ignore whitespace" - new Expect(` x y `).toParseLike("xy") - new Expect(` x ^ y `).toParseLike("x^y") - - assertion = "Parser should build a list of ords" - const ords = parse("1234|@.`abcdefgzABCDEFGZ"); - for (let i = 0; i < ords.length; i++) { - new Expect(ords[i].type.slice(4)).toBe("ord"); - } - - assertion = "Parser should build a list of bins" - let nodes = parse(r`+-*\cdot\pm\div`) - for (let i = 0; i < nodes.length; i++) { - new Expect(nodes[i].type).toBe("atom"); - new Expect(nodes[i].family).toBe("bin"); - } - - assertion = "Parser should build a list of rels" - nodes = parse(r`=<>\leq\geq\neq\nleq\ngeq\cong\in`) - for (let i = 0; i < nodes.length; i++) { - new Expect(nodes[i].type).toBe("atom"); - new Expect(nodes[i].family).toBe("rel"); - } - - assertion = "Parser should parse a \\mathinner" - new Expect(r`\mathinner{\langle{\psi}\rangle}`).toParse() - new Expect(r`\frac 1 {\mathinner{\langle{\psi}\rangle}}`).toParse() - assertion = "\\mathinner should return a group, not a fragment" - new Expect(build(r`\mathinner{\langle{\psi}\rangle}`).length).toBe(1) - - assertion = "Parse should build a list of puncts" - nodes = parse(",;") - for (let i = 0; i < nodes.length; i++) { - new Expect(nodes[i].type).toBe("atom"); - new Expect(nodes[i].family).toBe("punct"); - } - - assertion = "Parser should build a list of opens" - nodes = parse("([") - for (let i = 0; i < nodes.length; i++) { - new Expect(nodes[i].type).toBe("atom"); - new Expect(nodes[i].family).toBe("open"); - } - - assertion = "Parser should build a list of closes" - nodes = parse("])") - for (let i = 0; i < nodes.length; i++) { - new Expect(nodes[i].type).toBe("atom"); - new Expect(nodes[i].family).toBe("close"); - } - - assertion = "\\Temml should parse" - new Expect("\\Temml").toParse() - - assertion = "Subscripts and superscripts should parse" - new Expect(`x^2`).toParse() - new Expect(`x_3`).toParse() - new Expect(`x^2_3`).toParse() - new Expect(`x_2^3`).toParse() - new Expect(`^3`).toParse(); - new Expect(`^3+`).toParse(); - new Expect(`_2`).toParse(); - new Expect(`^3_2`).toParse(); - new Expect(`_2^3`).toParse(); - - let node = parse("x^2")[0] - new Expect(node.type).toBe("supsub"); - new Expect(node.base).toBeDefined(); - new Expect(node.sup).toBeDefined(); - new Expect(node.sub).toBeUndefined(); - - node = parse("x_3")[0] - new Expect(node.type).toBe("supsub"); - new Expect(node.base).toBeDefined(); - new Expect(node.sub).toBeDefined(); - new Expect(node.sup).toBeUndefined(); - - node = parse("x^2_3")[0] - new Expect(node.type).toBe("supsub"); - new Expect(node.base).toBeDefined(); - new Expect(node.sub).toBeDefined(); - new Expect(node.sup).toBeDefined(); - - new Expect(`x^2_3`).toParseLike(`x_3^2`) - - assertion = "Double exponents should not parse" - new Expect(`x^x^x`).toNotParse(); - new Expect(`x_x_x`).toNotParse(); - new Expect(`x_x^x_x`).toNotParse(); - new Expect(`x_x^x^x`).toNotParse(); - new Expect(`x^x_x_x`).toNotParse(); - new Expect(`x^x_x^x`).toNotParse(); - - assertion = "A subsup parser should work correctly with {}s" - new Expect(`x^{2+3}`).toParse(); - new Expect(`x_{3-2}`).toParse(); - new Expect(`x^{2+3}_3`).toParse(); - new Expect(`x^2_{3-2}`).toParse(); - new Expect(`x^{2+3}_{3-2}`).toParse(); - new Expect(`x_{3-2}^{2+3}`).toParse(); - new Expect(`x_3^{2+3}`).toParse(); - new Expect(`x_{3-2}^2`).toParse(); - - assertion = "A subsup parser should work with nested super/subscripts" - new Expect(`x^{x^x}`).toParse(); - new Expect(`x^{x_x}`).toParse(); - new Expect(`x_{x^x}`).toParse(); - new Expect(`x_{x_x}`).toParse(); - - assertion = "A subscript and superscript tree-builder should not fail when there is no nucleus" - new Expect(`^3`).toParse(); - new Expect(`_2`).toParse(); - new Expect(`^3_2`).toParse(); - new Expect(`_2^3`).toParse(); - new Expect(`^3`).toBuild(); - new Expect(`_2`).toBuild(); - new Expect(`^3_2`).toBuild(); - new Expect(`_2^3`).toBuild(); - - assertion = "A subsup parser should work with Unicode (sub|super)script characters" - new Expect(`A² + B²⁺³ + ¹²C + E₂³ + F₂₊₃`).toBuildLike("A^{2} + B^{2+3} + ^{12}C + E_{2}^{3} + F_{2+3}") - new Expect(r`\text{B²⁺³}`).toParse() - new Expect(r`\text{B²⁺³}`).toBuild() - - assertion = "A parser with limit controls should fail when the limit control is not preceded by an op node" - new Expect(r`3\nolimits_2^2`).toNotParse(); - new Expect(r`\sqrt\limits_2^2`).toNotParse(); - new Expect(r`45 +\nolimits 45`).toNotParse(); - - assertion = "A parser with limit controls should parse when the limit control directly follows an op node" - new Expect(r`\int\limits_2^2 3`).toParse(); - new Expect(r`\sum\nolimits_3^4 4`).toParse(); - - assertion = "A parser with limit controls should parse when the limit control is in the sup/sub area of an op node" - new Expect(r`\int_2^2\limits`).toParse(); - new Expect(r`\int^2\nolimits_2`).toParse(); - new Expect(r`\int_2\limits^2`).toParse(); - - assertion = "A parser with limit controls should allow multiple limit controls in the sup/sub area of an op node" - new Expect(r`\int_2\nolimits^2\limits 3`).toParse(); - new Expect(r`\int\nolimits\limits_2^2`).toParse(); - new Expect(r`\int\limits\limits\limits_2^2`).toParse(); - - assertion = "A parser with limit controls should have the rightmost limit control determine the limits property of the preceding op node" - new Expect(parse(r`\int\nolimits\limits_2^2`)[0].base.limits).toBe(true) - new Expect(parse(r`\int\limits_2\nolimits^2`)[0].base.limits).toBe(false) - - assertion = "A group parser should work" - new Expect(`{xy}`).toParse(); - nodes = parse(`{xy}`) - new Expect(nodes).toHaveLength(1); - new Expect(nodes[0].type).toBe("ordgroup"); - new Expect(nodes[0].body).toBeTruthy(); - new Expect(r`\begingroup xy \endgroup`).toParse(); - new Expect(r`\begingroup xy`).toNotParse(); - new Expect(r`\begingroup xy }`).toNotParse(); - nodes = parse(r`\begingroup xy \endgroup`) - new Expect(nodes).toHaveLength(1) - new Expect(nodes[0].type).toBe("ordgroup"); - new Expect(nodes[0].body).toBeTruthy(); - new Expect(nodes[0].semisimple).toBeTruthy(); - - assertion = "An implicit group parser should work" - new Expect(r`\Large x`).toParse(); - new Expect(r`abc {abc \Large xyz} abc`).toParse(); - nodes = parse(r`\Large abc`) - new Expect(nodes).toHaveLength(1); - new Expect(nodes[0].type).toBe("sizing"); - new Expect(nodes[0].body).toBeTruthy(); - nodes = parse(r`a \Large abc`) - new Expect(nodes).toHaveLength(2); - new Expect(nodes[1].type).toBe("sizing"); - new Expect(nodes[1].body).toHaveLength(3); - nodes = parse(r`a { b \Large c } d`) - new Expect(nodes[1].body[1].type).toBe("sizing"); - new Expect(nodes[1].body[1].body).toHaveLength(1); - - assertion = "An implicit group parser should work within optional groups" - new Expect(r`\sqrt[\small 3]{x}`).toParse(); - new Expect(r`\sqrt[\color{red} 3]{x}`).toParse() - new Expect(r`\sqrt[\textstyle 3]{x}`).toParse() - new Expect(r`\sqrt[\tt 3]{x}`).toParse() - - assertion = "A function parser should work" - new Expect(r`\div`).toParse(); - new Expect(r`\blue x`).toParse(); - new Expect(r`\frac 1 2`).toParse(); - new Expect(r`\tilde`).toNotParse(); - new Expect(r`\frac`).toNotParse(); - new Expect(r`\frac 1`).toNotParse(); - new Expect(parse(r`\tildex`)[0].color).toBe("#b22222"); - new Expect(r`\frac12`).toParse(strictSettings()); - new Expect(r`\;x`).toParse(); - - assertion = "A frac parser should work" - const expression = r`\frac{x}{y}`; - const dfracExpression = r`\dfrac{x}{y}`; - const tfracExpression = r`\tfrac{x}{y}`; - const cfracExpression = r`\cfrac{x}{y}`; - const genfrac1 = r`\genfrac ( ] {0.06em}{0}{a}{b+c}`; - const genfrac2 = r`\genfrac ( ] {0.8pt}{}{a}{b+c}`; - new Expect(expression).toParse(); - node = parse(expression)[0]; - new Expect(node.type).toBe("genfrac"); - new Expect(node.numer).toBeDefined(); - new Expect(node.denom).toBeDefined(); - new Expect(cfracExpression).toParse(); - new Expect(dfracExpression).toParse(); - new Expect(tfracExpression).toParse(); - new Expect(genfrac1).toParse(); - new Expect(genfrac2).toParse(); - const dfracParse = parse(dfracExpression)[0]; - new Expect(dfracParse.type).toBe("genfrac"); - new Expect(dfracParse.numer).toBeDefined(); - new Expect(dfracParse.denom).toBeDefined(); - const tfracParse = parse(tfracExpression)[0]; - new Expect(tfracParse.type).toBe("genfrac"); - new Expect(tfracParse.numer).toBeDefined(); - new Expect(tfracParse.denom).toBeDefined(); - const cfracParse = parse(cfracExpression)[0]; - new Expect(cfracParse.type).toBe("genfrac"); - new Expect(cfracParse.numer).toBeDefined(); - new Expect(cfracParse.denom).toBeDefined(); - const genfracParse = parse(genfrac1)[0]; - new Expect(genfracParse.type).toBe("genfrac"); - new Expect(genfracParse.numer).toBeDefined(); - new Expect(genfracParse.denom).toBeDefined(); - new Expect(genfracParse.leftDelim).toBeDefined(); - new Expect(genfracParse.rightDelim).toBeDefined(); - let badGenFrac = r`\genfrac ( ] {b+c}{0}{a}{b+c}`; - new Expect(badGenFrac).toNotParse(); - badGenFrac = r`\genfrac ( ] {0.06em}{0}{a}`; - new Expect(badGenFrac).toNotParse(); - node = parse(r`x \atop y`)[0]; - new Expect(node.type).toBe("genfrac"); - new Expect(node.numer).toBeDefined(); - new Expect(node.denom).toBeDefined(); - new Expect(node.hasBarLine).toBe(false); - - assertion = "An over/brace/brack parser should work" - const simpleOver = r`1 \over x`; - const complexOver = r`1+2i \over 3+4i`; - const braceFrac = r`a+b \brace c+d`; - const brackFrac = r`a+b \brack c+d`; - new Expect(simpleOver).toParse(); - new Expect(complexOver).toParse(); - new Expect(braceFrac).toParse(); - new Expect(brackFrac).toParse(); - - node = parse(simpleOver)[0]; - new Expect(node.type).toBe("genfrac"); - new Expect(node.numer).toBeDefined(); - new Expect(node.denom).toBeDefined(); - - node = parse(complexOver)[0]; - new Expect(node.type).toBe("genfrac"); - new Expect(node.numer).toBeDefined(); - new Expect(node.denom).toBeDefined(); - - const parseBraceFrac = parse(braceFrac)[0]; - new Expect(parseBraceFrac.type).toBe("genfrac"); - new Expect(parseBraceFrac.numer).toBeDefined(); - new Expect(parseBraceFrac.denom).toBeDefined(); - new Expect(parseBraceFrac.leftDelim).toBeDefined(); - new Expect(parseBraceFrac.rightDelim).toBeDefined(); - - const parseBrackFrac = parse(brackFrac)[0]; - new Expect(parseBrackFrac.type).toBe("genfrac"); - new Expect(parseBrackFrac.numer).toBeDefined(); - new Expect(parseBrackFrac.denom).toBeDefined(); - new Expect(parseBrackFrac.leftDelim).toBeDefined(); - new Expect(parseBrackFrac.rightDelim).toBeDefined(); - node = parse(complexOver)[0]; - - const numer = node.numer; - new Expect(numer.body).toHaveLength(4); - node = parse(complexOver)[0]; - - const denom = node.denom; - new Expect(denom.body).toHaveLength(4); - const emptyNumerator = r`\over x`; - node = parse(emptyNumerator)[0]; - new Expect(node.type).toBe("genfrac"); - new Expect(node.numer).toBeDefined(); - new Expect(node.denom).toBeDefined(); - const emptyDenominator = r`1 \over`; - node = parse(emptyDenominator)[0]; - new Expect(node.type).toBe("genfrac"); - new Expect(node.numer).toBeDefined(); - new Expect(node.denom).toBeDefined(); - const displaystyleExpression = r`\displaystyle 1 \over 2`; - node = parse(displaystyleExpression)[0]; - new Expect(node.type).toBe("genfrac"); - new Expect(node.numer.body[0].type).toBe("styling"); - new Expect(node.denom).toBeDefined(); - new Expect(r`\textstyle 1 \over 2`).toParseLike(r`\frac{\textstyle 1}{2}`); - new Expect(r`{\textstyle 1} \over 2`).toParseLike(r`\frac{\textstyle 1}{2}`); - const nestedOverExpression = r`{1 \over 2} \over 3`; - node = parse(nestedOverExpression)[0]; - new Expect(node.type).toBe("genfrac"); - new Expect(node.numer.body[0].type).toBe("genfrac"); - new Expect(node.numer.body[0].numer.body[0].text).toBe("1"); - new Expect(node.numer.body[0].denom.body[0].text).toBe("2"); - new Expect(node.denom).toBeDefined(); - new Expect(node.denom.body[0].text).toBe("3"); - const badMultipleOvers = r`1 \over 2 + 3 \over 4`; - new Expect(badMultipleOvers).toNotParse(); - const badOverChoose = r`1 \over 2 \choose 3`; - new Expect(badOverChoose).toNotParse(); - - assertion = `A genfrac builder should work` - new Expect(r`\frac{x}{y}`).toParse(); - new Expect(r`\dfrac{x}{y}`).toParse(); - new Expect(r`\tfrac{x}{y}`).toParse(); - new Expect(r`\cfrac{x}{y}`).toParse(); - new Expect(r`\genfrac ( ] {0.06em}{0}{a}{b+c}`).toParse(); - new Expect(r`\genfrac ( ] {0.8pt}{}{a}{b+c}`).toParse(); - new Expect(r`\genfrac {} {} {0.8pt}{}{a}{b+c}`).toParse(); - new Expect(r`\genfrac [ {} {0.8pt}{}{a}{b+c}`).toParse(); - new Expect(r`\frac{x}{y}`).toBuild(); - new Expect(r`\dfrac{x}{y}`).toBuild(); - new Expect(r`\tfrac{x}{y}`).toBuild(); - new Expect(r`\cfrac{x}{y}`).toBuild(); - new Expect(r`\genfrac ( ] {0.06em}{0}{a}{b+c}`).toBuild(); - new Expect(r`\genfrac ( ] {0.8pt}{}{a}{b+c}`).toBuild(); - new Expect(r`\genfrac {} {} {0.8pt}{}{a}{b+c}`).toBuild(); - new Expect(r`\genfrac [ {} {0.8pt}{}{a}{b+c}`).toBuild(); - - assertion = `A infix builder should not fail` - new Expect(r`a \over b`).toParse(); - new Expect(r`a \atop b`).toParse(); - new Expect(r`a \choose b`).toParse(); - new Expect(r`a \brace b`).toParse(); - new Expect(r`a \brack b`).toParse(); - new Expect(r`a \over b`).toBuild(); - new Expect(r`a \atop b`).toBuild(); - new Expect(r`a \choose b`).toBuild(); - new Expect(r`a \brace b`).toBuild(); - new Expect(r`a \brack b`).toBuild(); - - assertion = "A sizing parser should work" - const sizeExpression = r`\Huge{x}\small{x}`; - new Expect(sizeExpression).toParse(); - node = parse(sizeExpression)[0]; - new Expect(node.type).toBe("sizing"); - new Expect(node.body).toBeDefined(); - - assertion = "A text parser should work" - const textExpression = r`\text{a b}`; - const noBraceTextExpression = r`\text x`; - const nestedTextExpression = r`\text{a {b} \blue{c} \textcolor{#fff}{x} \llap{x}}`; - const spaceTextExpression = r`\text{ a \ }`; - const leadingSpaceTextExpression = r`\text {moo}`; - const badTextExpression = r`\text{a b%}`; - const badFunctionExpression = r`\text{\sqrt{x}}`; - const mathTokenAfterText = r`\text{sin}^2`; - new Expect(textExpression).toParse(); - node = parse(textExpression)[0]; - - new Expect(node.type).toBe("text"); - new Expect(node.body).toBeDefined(); - - new Expect(parse(textExpression)[0].body[0].type).toBe("textord"); - new Expect(badTextExpression).toNotParse(); - new Expect(badFunctionExpression).toNotParse(); - new Expect(noBraceTextExpression).toParse(); - new Expect(nestedTextExpression).toParse(); - node = parse(spaceTextExpression)[0]; - new Expect(node.body[0].type).toBe("spacing"); - new Expect(node.body[1].type).toBe("textord"); - new Expect(node.body[2].type).toBe("spacing"); - new Expect(node.body[3].type).toBe("spacing"); - new Expect(mathTokenAfterText).toParse(); - node = parse(leadingSpaceTextExpression)[0]; - // [m, o, o] - new Expect(node.body).toHaveLength(3); - new Expect(node.body.map(n => n.text).join("")).toBe("moo"); - new Expect(r`\text{graph: $y = mx + b$}`).toParse(); - new Expect(r`\text{graph: \(y = mx + b\)}`).toParse(); - new Expect(r`\text{hello $x + \text{world $y$} + z$}`).toParse(); - new Expect(r`\text{hello \(x + \text{world $y$} + z\)}`).toParse(); - new Expect(r`\text{hello $x + \text{world \(y\)} + z$}`).toParse(); - new Expect(r`\text{hello \(x + \text{world \(y\)} + z\)}`).toParse(); - new Expect(r`\(`).toNotParse(); - new Expect(r`\text{$\(x\)$}`).toNotParse(); - new Expect(r`$x$`).toNotParse(); - new Expect(r`\text{\($x$\)}`).toNotParse(); - new Expect(r`\)`).toNotParse(); - new Expect(r`\text{\)}`).toNotParse(); - new Expect(r`$`).toNotParse(); - new Expect(r`\text{$}`).toNotParse(); - new Expect(r`\text{$x\)}`).toNotParse(); - new Expect(r`\text{\(x$}`).toNotParse(); - new Expect(r`a b\, \; \! \: \> ~ \thinspace \medspace \quad \ `).toParse(); - new Expect(r`\enspace \thickspace \qquad \space \nobreakspace`).toParse(); - new Expect(r`a b\, \; \! \: \> ~ \thinspace \medspace \quad \ `).toBuild(); - new Expect(r`\enspace \thickspace \qquad \space \nobreakspace`).toBuild(); - new Expect(r`\text{\textellipsis !}`).toParseLike(r`\text{\textellipsis!}`); - new Expect(r`\:_*`).toParse(); - new Expect(r`\:_*`).toBuild(); - - assertion = `A texvc builder should not fail` - new Expect(r`\lang\N\darr\R\dArr\Z\Darr\alef\rang`).toParse(); - new Expect(r`\alefsym\uarr\Alpha\uArr\Beta\Uarr\Chi`).toParse(); - new Expect(r`\clubs\diamonds\hearts\spades\cnums\Complex`).toParse(); - new Expect(r`\Dagger\empty\harr\Epsilon\hArr\Eta\Harr\exist`).toParse(); - new Expect(r`\image\larr\infin\lArr\Iota\Larr\isin\Kappa`).toParse(); - new Expect(r`\Mu\lrarr\natnums\lrArr\Nu\Lrarr\Omicron`).toParse(); - new Expect(r`\real\rarr\plusmn\rArr\reals\Rarr\Reals\Rho`).toParse(); - new Expect(r`\text{\sect}\sdot\sub\sube\supe`).toParse(); - new Expect(r`\Tau\thetasym\weierp\Zeta`).toParse(); - new Expect(r`\lang\N\darr\R\dArr\Z\Darr\alef\rang`).toBuild(); - new Expect(r`\alefsym\uarr\Alpha\uArr\Beta\Uarr\Chi`).toBuild(); - new Expect(r`\clubs\diamonds\hearts\spades\cnums\Complex`).toBuild(); - new Expect(r`\Dagger\empty\harr\Epsilon\hArr\Eta\Harr\exist`).toBuild(); - new Expect(r`\image\larr\infin\lArr\Iota\Larr\isin\Kappa`).toBuild(); - new Expect(r`\Mu\lrarr\natnums\lrArr\Nu\Lrarr\Omicron`).toBuild(); - new Expect(r`\real\rarr\plusmn\rArr\reals\Rarr\Reals\Rho`).toBuild(); - new Expect(r`\text{\sect}\sdot\sub\sube\supe`).toBuild(); - new Expect(r`\Tau\thetasym\weierp\Zeta`).toBuild(); - - assertion = "A tie parser should work" - const mathTie = "a~b"; - const textTie = r`\text{a~ b}`; - new Expect(mathTie).toParse(); - new Expect(textTie).toParse(); - new Expect(parse(mathTie)[1].type).toBe("spacing"); - node = parse(textTie)[0]; - new Expect(node.body[1].type).toBe("spacing"); - node = parse(textTie)[0]; - new Expect(node.body[2].type).toBe("spacing"); - - assertion = "A delimiter sizing parser should work" - const normalDelim = r`\bigl |`; - const notDelim = r`\bigl x`; - const bigDelim = r`\Biggr \langle`; - new Expect(normalDelim).toParse(); - new Expect(bigDelim).toParse(); - new Expect(notDelim).toNotParse(); - node = parse(normalDelim)[0]; - new Expect(node.type).toBe("delimsizing"); - const leftParse = parse(normalDelim)[0]; - const rightParse = parse(bigDelim)[0]; - new Expect(leftParse.mclass).toBe("mopen"); - new Expect(rightParse.mclass).toBe("mclose"); - const smallParse = parse(normalDelim)[0]; - const bigParse = parse(bigDelim)[0]; - new Expect(smallParse.size).toBe(1); - new Expect(bigParse.size).toBe(4); - - assertion = "An overline parser should work" - const overline = r`\overline{x}`; - new Expect(overline).toParse(); - node = parse(overline)[0]; - new Expect(node.type).toBe("overline"); - - assertion = "A lap parser should work" - new Expect(r`\rlap{\,/}{=}`).toParse(); - new Expect(r`\mathrlap{\,/}{=}`).toParse(); - new Expect(r`{=}\llap{/\,}`).toParse(); - new Expect(r`{=}\mathllap{/\,}`).toParse(); - new Expect(r`\sum_{\clap{ABCDEFG}}`).toParse(); - new Expect(r`\sum_{\mathclap{ABCDEFG}}`).toParse(); - new Expect(r`\mathrlap{\frac{a}{b}}{=}`).toParse(); - new Expect(r`{=}\mathllap{\frac{a}{b}}`).toParse(); - new Expect(r`\sum_{\mathclap{\frac{a}{b}}}`).toParse(); - new Expect(r`\rlap{\frac{a}{b}}{=}`).toNotParse(strictSettings()); - new Expect(r`{=}\llap{\frac{a}{b}}`).toNotParse(strictSettings()); - new Expect(r`\sum_{\clap{\frac{a}{b}}}`).toNotParse(strictSettings()); - node = parse(r`\mathrlap{\,/}`)[0]; - new Expect(node.type).toBe("lap"); - - assertion = "A rule parser should work" - const emRule = r`\rule{1em}{2em}`; - const exRule = r`\rule{1ex}{2em}`; - let badUnitRule = r`\rule{1au}{2em}`; - let noNumberRule = r`\rule{1em}{em}`; - const incompleteRule = r`\rule{1em}`; - const hardNumberRule = r`\rule{ 01.24ex}{2.450 em }`; - new Expect(emRule).toParse(); - new Expect(exRule).toParse(); - new Expect(badUnitRule).toNotParse(); - new Expect(noNumberRule).toNotParse(); - new Expect(incompleteRule).toNotParse(); - node = parse(emRule)[0]; - new Expect(node.type).toBe("rule"); - let emParse = parse(emRule)[0]; - let exParse = parse(exRule)[0]; - new Expect(emParse.width.unit).toBe("em"); - new Expect(emParse.height.unit).toBe("em"); - new Expect(exParse.width.unit).toBe("ex"); - new Expect(exParse.height.unit).toBe("em"); - const hardNumberParse = parse(hardNumberRule)[0]; - new Expect(hardNumberParse.width.number).toBeCloseTo(1.24); - new Expect(hardNumberParse.height.number).toBeCloseTo(2.45); - node = parse(r`\rule{-1em}{- 0.2em}`)[0]; - new Expect(node.width.number).toBeCloseTo(-1); - new Expect(node.height.number).toBeCloseTo(-0.2); - - assertion = "A kern parser should work" - let emKern = r`\kern{1em}`; - let exKern = r`\kern{1ex}`; - let muKern = r`\mkern{1mu}`; - let abKern = r`a\kern{1em}b`; - badUnitRule = r`\kern{1au}`; - noNumberRule = r`\kern{em}`; - emParse = parse(emKern)[0]; - exParse = parse(exKern)[0]; - let muParse = parse(muKern)[0]; - let abParse = parse(abKern)[1]; - new Expect(emParse.dimension.unit).toBe("em"); - new Expect(exParse.dimension.unit).toBe("ex"); - new Expect(muParse.dimension.unit).toBe("mu"); - new Expect(abParse.dimension.unit).toBe("em"); - new Expect(badUnitRule).toNotParse(); - new Expect(noNumberRule).toNotParse(); - node = parse(r`\kern{-1em}`)[0]; - new Expect(node.dimension.number).toBeCloseTo(-1); - node = parse(r`\kern{+1em}`)[0]; - new Expect(node.dimension.number).toBeCloseTo(1); - - assertion = "A non-braced kern parser should work" - emKern = r`\kern1em`; - exKern = r`\kern 1 ex`; - muKern = r`\mkern 1mu`; - const abKern1 = r`a\mkern1mub`; - const abKern2 = r`a\mkern-1mub`; - const abKern3 = r`a\mkern-1mu b`; - badUnitRule = r`\kern1au`; - noNumberRule = r`\kern em`; - emParse = parse(emKern)[0]; - exParse = parse(exKern)[0]; - muParse = parse(muKern)[0]; - let abParse1 = parse(abKern1)[1]; - let abParse2 = parse(abKern2)[1]; - let abParse3 = parse(abKern3)[1]; - new Expect(emParse.dimension.unit).toBe("em"); - new Expect(exParse.dimension.unit).toBe("ex"); - new Expect(muParse.dimension.unit).toBe("mu"); - new Expect(abParse1.dimension.unit).toBe("mu"); - new Expect(abParse2.dimension.unit).toBe("mu"); - new Expect(abParse3.dimension.unit).toBe("mu"); - abParse1 = parse(abKern1); - abParse2 = parse(abKern2); - abParse3 = parse(abKern3); - new Expect(abParse1).toHaveLength(3); - new Expect(abParse1[0].text).toBe("a"); - new Expect(abParse1[2].text).toBe("b"); - new Expect(abParse2).toHaveLength(3); - new Expect(abParse2[0].text).toBe("a"); - new Expect(abParse2[2].text).toBe("b"); - new Expect(abParse3).toHaveLength(3); - new Expect(abParse3[0].text).toBe("a"); - new Expect(abParse3[2].text).toBe("b"); - new Expect(badUnitRule).toNotParse(); - new Expect(noNumberRule).toNotParse(); - node = parse(r`\kern-1em`)[0]; - new Expect(node.dimension.number).toBeCloseTo(-1); - node = parse(r`\kern+1em`)[0]; - new Expect(node.dimension.number).toBeCloseTo(1); - abKern = "a\\mkern\t-\r1 \n mu\nb"; - abParse = parse("a\\mkern\t-\r1 \n mu\nb"); - new Expect(abParse).toHaveLength(3); - new Expect(abParse[0].text).toBe("a"); - new Expect(abParse[1].dimension.unit).toBe("mu"); - new Expect(abParse[2].text).toBe("b"); - - assertion = "A left/right parser should work" - const normalLeftRight = r`\left( \dfrac{x}{y} \right)`; - const emptyRight = r`\left( \dfrac{x}{y} \right.`; - new Expect(normalLeftRight).toParse(); - node = parse(normalLeftRight)[0]; - new Expect(node.type).toBe("leftright"); - new Expect(node.left).toBe("("); - new Expect(node.right).toBe(")"); - const unmatchedLeft = r`\left( \dfrac{x}{y}`; - const unmatchedRight = r`\dfrac{x}{y} \right)`; - new Expect(unmatchedLeft).toNotParse(); - new Expect(unmatchedRight).toNotParse(); - const unmatched = r`{ \left( \dfrac{x}{y} } \right)`; - new Expect(unmatched).toNotParse(); - const nonDelimiter = r`\left$ \dfrac{x}{y} \right)`; - new Expect(nonDelimiter).toNotParse(); - new Expect(emptyRight).toParse(); - const normalEmpty = r`\Bigl .`; - new Expect(normalEmpty).toParse(); - const normalMiddle = r`\left( \dfrac{x}{y} \middle| \dfrac{y}{z} \right)`; - new Expect(normalMiddle).toParse(); - const multiMiddle = r`\left( \dfrac{x}{y} \middle| \dfrac{y}{z} \middle/ \dfrac{z}{q} \right)`; - new Expect(multiMiddle).toParse(); - const nestedMiddle = r`\left( a^2 \middle| \left( b \middle/ c \right) \right)`; - new Expect(nestedMiddle).toParse(); - const unmatchedMiddle = r`(\middle|\dfrac{x}{y})`; - new Expect(unmatchedMiddle).toNotParse(); - new Expect(r`\left\langle \right\rangle`).toBuildLike(r`\left< \right>`); - new Expect(r`\left\langle \right\rangle`).toBuildLike("\\left\u27e8 \\right\u27e9"); - new Expect(r`\left\lparen \right\rparen`).toBuildLike(r`\left( \right)`); - - assertion = "A begin/end parser should work" - new Expect(r`\begin{matrix}a&b\\c&d\end{matrix}`).toParse(); - new Expect(r`\begin{array}{cc}a&b\\c&d\end{array}`).toParse(); - new Expect(r`\begin{aligned}\end{aligned}`).toParse(); - new Expect(r`\begin{matrix}\hline a&b\\ \hline c&d\end{matrix}`).toParse(); - new Expect(r`\begin{matrix}\hdashline a&b\\ \hdashline c&d\end{matrix}`).toParse(); - new Expect(r`\hline`).toNotParse(); - new Expect(r`\begin{matrix}a&b\\c&d\end{pmatrix}`).toNotParse(); - new Expect(r`\begin{matrix}a&b\\c&d\right{pmatrix}`).toNotParse(); - new Expect(r`\begin{matrix}a&b\\c&d`).toNotParse(); - new Expect(r`{\begin{matrix}a&b\\c&d}\end{matrix}`).toNotParse(); - new Expect(r`\begin{matrix}0&1\over2&3\\4&5&6\end{matrix}`).toParse(); - const m1 = `\\begin{pmatrix}1&2\\\\3&4\\end{pmatrix}`; - const m2 = `\\begin{array}{rl}${m1}&0\\\\0&${m1}\\end{array}`; - new Expect(m2).toParse(); - new Expect(r`\begin{matrix}a&b\cr c&d\end{matrix}`).toParse(); - new Expect(r`\begin{matrix}a&b\\c&d\end{matrix}`).toParse(); - new Expect(r`\begin{matrix}a&b\cr[c]&d\end{matrix}`).toParse(); - const m3 = parse(r`\begin{matrix}a&b\\ c&d \\ \end{matrix}`)[0]; - new Expect(m3.body).toHaveLength(2); - new Expect(r`\begin{matrix*}[r] a & -1 \\ -1 & d \end{matrix*}`).toParse(); - new Expect(r`\begin{pmatrix*}[r] a & -1 \\ -1 & d \end{pmatrix*}`).toParse(); - new Expect(r`\begin{bmatrix*}[r] a & -1 \\ -1 & d \end{bmatrix*}`).toParse(); - new Expect(r`\begin{Bmatrix*}[r] a & -1 \\ -1 & d \end{Bmatrix*}`).toParse(); - new Expect(r`\begin{vmatrix*}[r] a & -1 \\ -1 & d \end{vmatrix*}`).toParse(); - new Expect(r`\begin{Vmatrix*}[r] a & -1 \\ -1 & d \end{Vmatrix*}`).toParse(); - new Expect(r`\begin{matrix*} a & -1 \\ -1 & d \end{matrix*}`).toParse(); - new Expect(r`\begin{matrix*}[r] a & -1 \\ -1 & d \end{matrix*}`).toBuild(); - new Expect(r`\begin{pmatrix*}[r] a & -1 \\ -1 & d \end{pmatrix*}`).toBuild(); - new Expect(r`\begin{bmatrix*}[r] a & -1 \\ -1 & d \end{bmatrix*}`).toBuild(); - new Expect(r`\begin{Bmatrix*}[r] a & -1 \\ -1 & d \end{Bmatrix*}`).toBuild(); - new Expect(r`\begin{vmatrix*}[r] a & -1 \\ -1 & d \end{vmatrix*}`).toBuild(); - new Expect(r`\begin{Vmatrix*}[r] a & -1 \\ -1 & d \end{Vmatrix*}`).toBuild(); - new Expect(r`\begin{matrix*} a & -1 \\ -1 & d \end{matrix*}`).toBuild(); - new Expect(r`\begin{matrix*}[] a & -1 \\ -1 & d \end{matrix*}`).toNotParse(); - - assertion = "A sqrt parser should work" - const sqrt = r`\sqrt{x}`; - const missingGroup = r`\sqrt`; - new Expect(sqrt).toParse(); - new Expect(missingGroup).toNotParse(); - new Expect(parse(sqrt)[0].type).toBe("sqrt"); - new Expect("\\Large\\sqrt[3]{x}").toParse(); - new Expect("\\sqrt\\foo").toParseLike("\\sqrt123", new Settings({ macros: { "\\foo": "123" } })); - new Expect("\\sqrt[2]\\foo").toParseLike("\\sqrt[2]{123}", new Settings({ macros: { "\\foo": "123" } })); - - assertion = "A TeX-compliant parser should work" - new Expect(r`\frac 2 3`).toParse(); - const missingGroups = [ - r`\frac{x}`, - r`\textcolor{#fff}`, - r`\rule{1em}`, - r`\llap`, - r`\bigl`, - r`\text` - ]; - for (let i = 0; i < missingGroups.length; i++) { - new Expect(missingGroups[i]).toNotParse(); - } - new Expect(r`x^`).toNotParse(); - new Expect(r`x_`).toNotParse(); - const badArguments = [ - r`\frac \frac x y z`, - r`\frac x \frac y z`, - r`\frac \sqrt x y`, - r`\frac x \sqrt y`, - r`\frac \mathllap x y`, - r`\frac x \mathllap y`, - // This actually doesn't work in real TeX, but it is suprisingly - // hard to get this to correctly work. So, we take hit of very small - // amounts of non-compatiblity in order for the rest of the tests to - // work - // r`\llap \frac x y`, - r`\mathllap \mathllap x`, - r`\sqrt \mathllap x` - ]; - for (let i = 0; i < badArguments.length; i++) { - new Expect(badArguments[i]).toNotParse(); - } - const goodArguments = [ - r`\frac {\frac x y} z`, - r`\frac x {\frac y z}`, - r`\frac {\sqrt x} y`, - r`\frac x {\sqrt y}`, - r`\frac {\mathllap x} y`, - r`\frac x {\mathllap y}`, - r`\mathllap {\frac x y}`, - r`\mathllap {\mathllap x}`, - r`\sqrt {\mathllap x}` - ]; - for (let i = 0; i < goodArguments.length; i++) { - new Expect(goodArguments[i]).toParse(); - } - const badSupSubscripts = [ - r`x^\sqrt x`, - r`x^\mathllap x`, - r`x_\sqrt x`, - r`x_\mathllap x` - ]; - for (let i = 0; i < badSupSubscripts.length; i++) { - new Expect(badSupSubscripts[i]).toNotParse(); - } - const goodSupSubscripts = [ - r`x^{\sqrt x}`, - r`x^{\mathllap x}`, - r`x_{\sqrt x}`, - r`x_{\mathllap x}` - ]; - for (let i = 0; i < goodSupSubscripts.length; i++) { - new Expect(goodSupSubscripts[i]).toParse(); - } - new Expect(r`x''''`).toParse(); - new Expect(r`x_2''`).toParse(); - new Expect(r`x''_2`).toParse(); - new Expect(r`\sqrt^23`).toNotParse(); - new Expect(r`\frac^234`).toNotParse(); - new Expect(r`\frac2^34`).toNotParse(); - new Expect(r`\sqrt2^3`).toParse(); - new Expect(r`\frac23^4`).toParse(strictSettings()); - new Expect(r`\sqrt \frac x y`).toParse(); - new Expect(r`\sqrt \text x`).toParse(); - new Expect(r`x^\frac x y`).toParse(); - new Expect(r`x_\text x`).toParse(); - const badLeftArguments = [ - r`\frac \left( x \right) y`, - r`\frac x \left( y \right)`, - r`\mathllap \left( x \right)`, - r`\sqrt \left( x \right)`, - r`x^\left( x \right)` - ]; - for (let i = 0; i < badLeftArguments.length; i++) { - new Expect(badLeftArguments[i]).toNotParse(); - } - const goodLeftArguments = [ - r`\frac {\left( x \right)} y`, - r`\frac x {\left( y \right)}`, - r`\mathllap {\left( x \right)}`, - r`\sqrt {\left( x \right)}`, - r`x^{\left( x \right)}` - ]; - for (let i = 0; i < goodLeftArguments.length; i++) { - new Expect(goodLeftArguments[i]).toParse(); - } - - assertion = "An op symbol builder should build" - new Expect(r`\int_i^n`).toParse(); - new Expect(r`\iint_i^n`).toParse(); - new Expect(r`\iiint_i^n`).toParse(); - new Expect(r`\int\nolimits_i^n`).toParse(); - new Expect(r`\iint\nolimits_i^n`).toParse(); - new Expect(r`\iiint\nolimits_i^n`).toParse(); - new Expect(r`\oint_i^n`).toParse(); - new Expect(r`\oiint_i^n`).toParse(); - new Expect(r`\oiiint_i^n`).toParse(); - new Expect(r`\oint\nolimits_i^n`).toParse(); - new Expect(r`\oiint\nolimits_i^n`).toParse(); - new Expect(r`\oiiint\nolimits_i^n`).toParse(); - new Expect(r`\int_i^n`).toBuild(); - new Expect(r`\iint_i^n`).toBuild(); - new Expect(r`\iiint_i^n`).toBuild(); - new Expect(r`\int\nolimits_i^n`).toBuild(); - new Expect(r`\iint\nolimits_i^n`).toBuild(); - new Expect(r`\iiint\nolimits_i^n`).toBuild(); - new Expect(r`\oint_i^n`).toBuild(); - new Expect(r`\oiint_i^n`).toBuild(); - new Expect(r`\oiiint_i^n`).toBuild(); - new Expect(r`\oint\nolimits_i^n`).toBuild(); - new Expect(r`\oiint\nolimits_i^n`).toBuild(); - new Expect(r`\oiiint\nolimits_i^n`).toBuild(); - - assertion = "A style change parser should work" - new Expect(r`\displaystyle x`).toParse(); - new Expect(r`\textstyle x`).toParse(); - new Expect(r`\scriptstyle x`).toParse(); - new Expect(r`\scriptscriptstyle x`).toParse(); - const displayParse = parse(r`\displaystyle x`)[0]; - new Expect(displayParse.scriptLevel).toBe("display"); - const scriptscriptParse = parse(r`\scriptscriptstyle x`)[0]; - new Expect(scriptscriptParse.scriptLevel).toBe("scriptscript"); - const text = r`a b { c d \displaystyle e f } g h`; - const displayNode = parse(text)[2].body[2]; - new Expect(displayNode.type).toBe("styling"); - const displayBody = displayNode.body; - new Expect(displayBody).toHaveLength(2); - new Expect(displayBody[0].text).toBe("e"); - - assertion = "A font parser should work" - new Expect(r`\mathrm x`).toParse(); - new Expect(r`\mathbb x`).toParse(); - new Expect(r`\mathit x`).toParse(); - new Expect(r`\mathnormal x`).toParse(); - new Expect(r`\mathrm {x + 1}`).toParse(); - new Expect(r`\mathbb {x + 1}`).toParse(); - new Expect(r`\mathit {x + 1}`).toParse(); - new Expect(r`\mathnormal {x + 1}`).toParse(); - new Expect(r`\mathcal{ABC123}`).toParse(); - new Expect(r`\mathfrak{abcABC123}`).toParse(); - const mathbbParse = parse(r`\mathbb x`)[0]; - new Expect(mathbbParse.font).toBe("mathbb"); - new Expect(mathbbParse.type).toBe("font"); - const mathrmParse = parse(r`\mathrm x`)[0]; - new Expect(mathrmParse.font).toBe("mathrm"); - new Expect(mathrmParse.type).toBe("font"); - const mathitParse = parse(r`\mathit x`)[0]; - new Expect(mathitParse.font).toBe("mathit"); - new Expect(mathitParse.type).toBe("font"); - const mathnormalParse = parse(r`\mathnormal x`)[0]; - new Expect(mathnormalParse.font).toBe("mathnormal"); - new Expect(mathnormalParse.type).toBe("font"); - const mathcalParse = parse(r`\mathcal C`)[0]; - new Expect(mathcalParse.font).toBe("mathcal"); - new Expect(mathcalParse.type).toBe("font"); - const mathfrakParse = parse(r`\mathfrak C`)[0]; - new Expect(mathfrakParse.font).toBe("mathfrak"); - new Expect(mathfrakParse.type).toBe("font"); - const nestedParse = parse(r`\mathbb{R \neq \mathrm{R}}`)[0]; - new Expect(nestedParse.font).toBe("mathbb"); - new Expect(nestedParse.type).toBe("font"); - const bbBody = nestedParse.body.body; - new Expect(bbBody).toHaveLength(3); - new Expect(bbBody[0].type).toBe("mathord"); - new Expect(bbBody[2].type).toBe("font"); - new Expect(bbBody[2].font).toBe("mathrm"); - new Expect(bbBody[2].type).toBe("font"); - const colorMathbbParse = parse(r`\textcolor{blue}{\mathbb R}`)[0]; - new Expect(colorMathbbParse.type).toBe("color"); - new Expect(colorMathbbParse.color).toBe("#0000FF"); - const cbody = colorMathbbParse.body; - new Expect(cbody).toHaveLength(1); - new Expect(cbody[0].type).toBe("font"); - new Expect(cbody[0].font).toBe("mathbb"); - const bf = parse(r`\mathbf{a\mathrm{b}c}`)[0]; - new Expect(bf.type).toBe("font"); - new Expect(bf.font).toBe("mathbf"); - new Expect(bf.body.body).toHaveLength(3); - new Expect(bf.body.body[0].text).toBe("a"); - new Expect(bf.body.body[1].type).toBe("font"); - new Expect(bf.body.body[1].font).toBe("mathrm"); - new Expect(bf.body.body[2].text).toBe("c"); - new Expect(r`e^\mathbf{x}`).toParse(); - new Expect(r`\rm xyz`).toParseLike(r`\mathrm{xyz}`); - new Expect(r`\sf xyz`).toParseLike(r`\mathsf{xyz}`); - new Expect(r`\tt xyz`).toParseLike(r`\mathtt{xyz}`); - new Expect(r`\bf xyz`).toParseLike(r`\mathbf{xyz}`); - new Expect(r`\it xyz`).toParseLike(r`\mathit{xyz}`); - new Expect(r`\cal xyz`).toParseLike(r`\mathcal{xyz}`); - new Expect(r`\uptheta\varDelta`).toParse(strictSettings) - new Expect(r`\uptheta\varDelta`).toBuild() - - assertion = "A \\pmb builder should work" - new Expect(r`\pmb{\mu}`).toParse(); - new Expect(r`\pmb{=}`).toParse(); - new Expect(r`\pmb{+}`).toParse(); - new Expect(r`\pmb{\frac{x^2}{x_1}}`).toParse(); - new Expect(r`\pmb{}`).toParse(); - new Expect(r`\pmb{\mu}`).toBuild(); - new Expect(r`\pmb{=}`).toBuild(); - new Expect(r`\pmb{+}`).toBuild(); - new Expect(r`\pmb{\frac{x^2}{x_1}}`).toBuild(); - new Expect(r`\pmb{}`).toBuild(); - new Expect(r`\def\x{1}\pmb{\x\def\x{2}}`).toParseLike(r`\pmb{1}`); - - assertion = `A raise parser should work` - new Expect(r`\raisebox{5pt}{text}`).toParse(strictSettings()); - new Expect(r`\raisebox{-5pt}{text}`).toParse(strictSettings()); - new Expect(r`\vcenter{\frac a b}`).toParse(); - new Expect(r`\raisebox{5pt}{text}`).toBuild(strictSettings()); - new Expect(r`\raisebox{-5pt}{text}`).toBuild(strictSettings()); - new Expect(r`\vcenter{\frac a b}`).toBuild(); - new Expect(r`\raisebox{5pt}{\frac a b}`).toNotParse(); - new Expect(r`\raisebox{-5pt}{\frac a b}`).toNotParse(); - new Expect(r`\hbox{\frac a b}`).toNotParse(); - new Expect(r`\raisebox5pt{text}`).toNotParse(); - new Expect(r`\raisebox5pt{text}`).toNotParse(); - new Expect(r`\raisebox-5pt{text}`).toNotParse(); - - assertion = "A comment parser should work" - new Expect("a^2 + b^2 = c^2 % Pythagoras' Theorem\n").toParse(); - new Expect("% comment\n").toParse(); - new Expect("% comment 1\n% comment 2\n").toParse(); - new Expect("x_3 %comment\n^2").toParseLike(`x_3^2`); - new Expect("x^ %comment\n{2}").toParseLike(`x^{2}`); - new Expect("x^ %comment\n\\frac{1}{2}").toParseLike(r`x^\frac{1}{2}`); - new Expect("\\kern{1 %kern\nem}").toParse(); - new Expect("\\kern1 %kern\nem").toParse(); - new Expect("\\color{#f00%red\n}").toParse(); - new Expect("%comment\n{2}").toParseLike(`{2}`); - new Expect("\\begin{matrix}a&b\\\\ %hline\n\\hline %hline\n\\hline c&d\\end{matrix}").toParse(); - new Expect("\\def\\foo{a %}\nb}\n\\foo").toParseLike(`ab`); - new Expect("\\def\\foo{1\n2}\nx %\\foo\n").toParseLike(`x`); - new Expect(`x%y`).toNotParse(strictSettings()); - new Expect(`x%y`).toParse(); - new Expect("\\text{hello% comment 1\nworld}").toParseLike(r`\text{helloworld}`); - new Expect("\\text{hello% comment\n\nworld}").toParseLike(r`\text{hello world}`); - new Expect("5 % comment\n").toParseLike(`5`); - - assertion = "A font tree-builder should work" - let markup = temml.renderToString(r`\mathbb{R}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe(''); - markup = temml.renderToString(r`\mathrm{R}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe('R'); - markup = temml.renderToString(r`\mathcal{R}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe(''); - markup = temml.renderToString(r`\mathfrak{R}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe(''); - markup = temml.renderToString(r`\text{R}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe('R'); - markup = temml.renderToString(r`\textit{R}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe('𝑅'); - markup = temml.renderToString(r`\text{\textit{R}}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe('𝑅'); - let markup1 = temml.renderToString(r`\textup{R}`).replace(mathTagRegEx, ""); - new Expect(markup1).toBe('R'); - let markup2 = temml.renderToString(r`\textit{\textup{R}}`).replace(mathTagRegEx, ""); - new Expect(markup2).toBe('R'); - let markup3 = temml.renderToString(r`\textup{\textit{R}}`).replace(mathTagRegEx, ""); - new Expect(markup3).toBe('𝑅'); - markup = temml.renderToString(r`\text{R\textit{S}T}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe('R𝑆T'); - markup1 = temml.renderToString(r`\textmd{R}`).replace(mathTagRegEx, ""); - new Expect(markup1).toBe('R'); - markup2 = temml.renderToString(r`\textbf{\textmd{R}}`).replace(mathTagRegEx, ""); - new Expect(markup2).toBe('R'); - markup3 = temml.renderToString(r`\textmd{\textbf{R}}`).replace(mathTagRegEx, ""); - new Expect(markup3).toBe('𝐑'); - markup = temml.renderToString(r`\textsf{R}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe('𝖱'); - markup = temml.renderToString(r`\textsf{\textit{R}G\textbf{B}}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe('𝘙𝖦𝗕'); - markup = temml.renderToString(r`\texttt{R}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe('𝚁'); - assertion = "A font tree-builder should render a combination of font and color changes" - markup = temml.renderToString(r`\textcolor{blue}{\mathbb R}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe(''); - markup = temml.renderToString(r`\mathbb{\textcolor{blue}{R}}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe(''); - assertion = "A font tree-builder should render wide characters with and with the correct font" - markup = temml.renderToString("𝐀").replace(mathTagRegEx, ""); - new Expect(markup).toBe('𝐀'); - - assertion = "A parser should throw an error when the expression is of the wrong type" - new Expect([1, 2]).toNotParse() - new Expect({ badInputType: "yes" }).toNotParse() - new Expect(undefined).toNotParse() - new Expect(null).toNotParse() - new Expect(1.234).toNotParse() - assertion = "A parser should work when the expression is of the correct type" - new Expect(r`\sqrt{123}`).toParse() - new Expect(new String(r`\sqrt{123}`)).toParse() - - assertion = "A font tree-builder should render the correct mathvariants" - markup = temml.renderToString(r`Ax2k\omega\Omega\imath+`).replace(mathTagRegEx, ""); - new Expect(markup).toContain("A"); - new Expect(markup).toContain("x"); - new Expect(markup).toContain("2"); - new Expect(markup).toContain("ω"); // \omega - new Expect(markup).toContain('Ω'); // \Omega - new Expect(markup).toContain('ı'); // \imath - new Expect(markup).toContain("+"); - markup = temml.renderToString(r`\mathbb{Ax2k\omega\Omega\imath+}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe("𝔸𝕩𝟚𝕜ωΩı+"); - markup = temml.renderToString(r`\mathrm{Ax2k\omega\Omega\imath+}`).replace(mathTagRegEx, ""); - new Expect(markup).toContain("A"); - new Expect(markup).toContain("x"); - new Expect(markup).toContain("2"); - new Expect(markup).toContain("ω"); // \omega - new Expect(markup).toContain("Ω"); // \Omega - new Expect(markup).toContain("ı"); // \imath - new Expect(markup).toContain("+"); - markup = temml.renderToString(r`\mathit{Ax2k\omega\Omega\imath+}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe(`Ax2kωΩı+`); - markup = temml.renderToString(r`\mathnormal{Ax2k\omega\Omega\imath+}`).replace(mathTagRegEx, ""); - new Expect(markup).toContain("A"); - new Expect(markup).toContain("x"); - new Expect(markup).toContain("2"); - new Expect(markup).toContain("ω"); // \omega - new Expect(markup).toContain("Ω"); // \Omega - new Expect(markup).toContain("ı"); // \imath - new Expect(markup).toContain("+"); - markup = temml.renderToString(r`\mathbf{Ax2k\omega\Omega\imath+}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe(`𝐀𝐱𝟐𝐤𝛚𝛀ı+`); - markup = temml.renderToString(r`\mathcal{Ax2k\omega\Omega\imath+}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe(`𝒜𝓍2𝓀ωΩı+`); - markup = temml.renderToString(r`\mathfrak{Ax2k\omega\Omega\imath+}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe(`𝔄𝔵2𝔨ωΩı+`); - markup = temml.renderToString(r`\mathscr{A}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe(`𝒜`); - markup = temml.renderToString(r`\mathsf{Ax2k\omega\Omega\imath+}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe(`𝖠𝗑𝟤𝗄𝞈𝝮ı+`); - - assertion = "A font tree-builder should render a combination of font and color changes" - markup = temml.renderToString(r`\textcolor{blue}{\mathbb R}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe(``); - // reverse the order of the commands - markup = temml.renderToString(r`\mathbb{\textcolor{blue}{R}}`).replace(mathTagRegEx, ""); - new Expect(markup).toBe(``); - - assertion = "A font tree-builder should render text as " - markup = temml.renderToString(r`\text{for }`); - new Expect(markup).toContain("for\u00a0"); - - assertion = "A font tree-builder should render math within text as side-by-side children" - markup = temml.renderToString(r`\text{graph: $y = mx + b$}`); - new Expect(markup).toContain("y=mx+b"); - - assertion = "An includegraphics builder should work" - const img = "\\includegraphics[height=0.9em, totalheight=0.9em, width=0.9em, alt=KA logo]{https://cdn.kastatic.org/images/apple-touch-icon-57x57-precomposed.new.png}"; - new Expect(img).toNotParse() // no trust - new Expect(img, trustSettings()).toNotBuild(); - new Expect(img).toParse(trustSettings()) // no trust - markup = temml.renderToString(img, trustSettings()).replace(mathTagRegEx, ""); - new Expect(markup).toBe(`KA logo`); - - assertion = "An HTML extension builder should work" - const html = r`\id{bar}{x}\class{foo}{x}\style{color: red;}{x}\data{foo=a, bar=b}{x}`; - new Expect(html).toParse(trustSettings()); - new Expect(html).toBuild(trustSettings()); - let built = build(html, trustSettings())[0].children[0].children; - new Expect(built[0].attributes.id).toBe("bar"); - new Expect(built[1].classes).toContain("foo"); - new Expect(built[2].attributes.style).toBe("color: red;"); - - assertion = "A bin parser should work" - new Expect(parse('x + y')[1].family).toBe("bin") - new Expect(parse('+ x')[0].family).toBe("bin") - new Expect(parse(r`x + + 2`)[3].type).toBe("textord"); - new Expect(parse(r`( + 2`)[2].type).toBe("textord"); - new Expect(parse(r`= + 2`)[2].type).toBe("textord"); - new Expect(parse(r`\sin + 2`)[2].type).toBe("textord"); - new Expect(parse(r`, + 2`)[2].type).toBe("textord"); - new Expect(parse(r`\textcolor{blue}{x}+y`)[1].family).toBe("bin"); - new Expect(parse(r`\textcolor{blue}{x+}+y`)[2].type).toBe("mathord"); - - assertion = "A phantom and smash parser should work" - new Expect(parse(r`\hphantom{a}`)[0].type).toBe("hphantom"); - new Expect(parse(r`a\hphantom{=}b`)[2].type).toBe("mathord"); - new Expect(parse(r`\smash{a}`)[0].type).toBe("smash"); - new Expect(parse(r`a\smash{+}b`)[2].type).toBe("mathord"); - - assertion = "A markup generator should work" - // Just a few quick sanity checks here... - markup = temml.renderToString(r`\sigma^2`); - new Expect(markup.indexOf(" context.protocol === "ftp"})) - new Expect("\\href{ftp://x}{foo}").toBuild(new Settings({trust: (context) => context.protocol === "ftp"})) - assertion = "href and url commands should allow all protocols when trust option is true" - new Expect("\\href{ftp://x}{foo}").toParse(trustSettings()) - new Expect("\\href{ftp://x}{foo}").toBuild(trustSettings()) - assertion = "href and url commands should not allow explicitly disallowed protocols" - new Expect("\\href{javascript:alert('x')}{foo}").toNotParse(new Settings({trust: context => context.protocol !== "javascript"})) - - assertion = "The symbol table integrity should treat certain symbols as synonyms" - new Expect(`<`).toBuildLike(r`\lt`) - new Expect(`>`).toBuildLike(r`\gt`) - new Expect(r`\left<\frac{1}{x}\right>`).toBuildLike(r`\left\lt\frac{1}{x}\right\gt`) - - assertion = "Symbols should support AMS symbols in both text and math mode" - new Expect(r`\yen\checkmark\circledR\maltese`).toBuild(strictSettings()) - new Expect(r`\text{\yen\checkmark\circledR\maltese}`).toBuild(strictSettings()) - new Expect(r`\yen\checkmark\circledR\maltese`).toParse(strictSettings()) - new Expect(r`\text{\yen\checkmark\circledR\maltese}`).toParse(strictSettings()) - - assertion = "A macro expander should produce individual tokens" - new Expect(r`e^\foo`).toParseLike("e^a 23", new Settings({macros: {"\\foo": "a23"}})) - new Expect(r`e^\foo`).toParseLike("e^1 23", new Settings({strict: true, macros: {"\\foo": "123"}})) - assertion = "A macro expander should preserve leading spaces inside macro definition" - new Expect(r`\text{\foo}`).toParseLike(r`\text{ x}`, new Settings({macros: {"\\foo": " x"}})) - assertion = "A macro expander should preserve leading spaces inside macro argument" - new Expect(r`\text{\foo{ x}}`).toParseLike(r`\text{ x}`, new Settings({macros: {"\\foo": "#1"}})) - assertion = "A macro expander should ignore expanded spaces in math mode" - new Expect(r`\foo`).toParseLike("x", new Settings({macros: {"\\foo": " x"}})) - assertion = "A macro expander should consume spaces after control-word macro" - new Expect(r`\text{\foo }`).toParseLike(r`\text{x}`, new Settings({macros: {"\\foo": "x"}})) - assertion = "A macro expander should consume spaces after macro with \\relax" - new Expect(r`\text{\foo }`).toParseLike(r`\text{}`, new Settings({macros: {"\\foo": "\\relax"}})) - assertion = "A macro expander not should consume spaces after control-word expansion" - new Expect(r`\text{\\ }`).toParseLike(r`\text{ }`, new Settings({macros: {"\\\\": "\\relax"}})) - assertion = "A macro expander should consume spaces after \\relax" - new Expect(r`\text{\relax }`).toParseLike(r`\text{}`) - assertion = "A macro expander should consume spaces after control-word function" - new Expect(r`\text{\yen }`).toParseLike(r`\text{\yen}`) - assertion = "A macro expander should preserve spaces after control-symbol macro" - new Expect(r`\text{\% y}`).toParseLike(r`\text{x y}`, new Settings({macros: {"\\%": "x"}})) - assertion = "A macro expander should preserve spaces after control-symbol function" - new Expect(r`\text{\' }`).toParse() - assertion = "A macro expander should consume spaces between arguments" - new Expect(r`\text{\foo a 2}`).toParseLike(r`\text{a2end}`, new Settings({macros: {"\\foo": "#1#2end"}})) - new Expect(r`\text{\foo {a} {2}}`).toParseLike(r`\text{a2end}`, new Settings({macros: {"\\foo": "#1#2end"}})) - assertion = "A macro expander should allow for multiple expansion" - new Expect(r`1\foo2`).toParseLike("1aa2", new Settings({macros: { - "\\foo": "\\bar\\bar", - "\\bar": "a", - }})) - assertion = "A macro expander should allow for multiple expansion with argument" - new Expect(r`1\foo2`).toParseLike("1 2 2 2 2", new Settings({macros: { - "\\foo": "\\bar{#1}\\bar{#1}", - "\\bar": "#1#1", - }})) - assertion = "A macro expander should allow for macro argument" - new Expect(r`\foo\bar`).toParseLike("(xyz)", new Settings({macros: { - "\\foo": "(#1)", - "\\bar": "xyz", - }})) - assertion = "A macro expander should allow properly nested group for macro argument" - new Expect(r`\foo{e^{x_{12}+3}}`).toParseLike("(e^{x_{12}+3})", new Settings({macros: {"\\foo": "(#1)"}})) - - assertion = "A macro expander should delay expansion if preceded by \\expandafter" - new Expect(r`\expandafter\foo\bar`).toParseLike("x+y", new Settings({macros: { - "\\foo": "#1+#2", - "\\bar": "xy", - }})) - // \def is not expandable, i.e., \expandafter doesn't define the macro - new Expect(r`\def\foo{x}\def\bar{\def\foo{y}}\expandafter\bar\foo`).toParseLike(`x`) - - assertion = "A macro expander should not expand if preceded by \\noexpand" - // \foo is not expanded and interpreted as if its meaning were \relax - new Expect(r`\noexpand\foo y`).toParseLike(r`y`, new Settings({macros: {"\\foo": "x"}})) - new Expect(r`\expandafter\foo\noexpand\foo`).toParseLike("x", new Settings({macros: {"\\foo": "x"}})) - new Expect(r`\noexpand\frac xy`).toParseLike(`xy`) - new Expect(r`\noexpand\def\foo{xy}\foo`).toParseLike(`xy`) - - assertion = "A macro expander should allow for space macro argument (text version)" - new Expect(r`\text{\foo\bar}`).toParseLike(r`\text{( )}`, new Settings({macros: { - "\\foo": "(#1)", - "\\bar": " ", - }})) - - assertion = "A macro expander should allow for space macro argument (math version)" - new Expect(r`\foo\bar`).toParseLike("()", new Settings({macros: { - "\\foo": "(#1)", - "\\bar": " ", - }})) - - assertion = "A macro expander should allow for second argument (text version)" - new Expect(r`\text{\foo\bar\bar}`).toParseLike(r`\text{( , )}`, new Settings({macros: { - "\\foo": "(#1,#2)", - "\\bar": " ", - }})) - - assertion = "A macro expander should allow for second argument (math version)" - new Expect(r`\foo\bar\bar`).toParseLike("(,)", new Settings({macros: { - "\\foo": "(#1,#2)", - "\\bar": " ", - }})) - - assertion = "A macro expander should allow for empty macro argument" - new Expect(r`\foo\bar`).toParseLike("()", new Settings({macros: { - "\\foo": "(#1)", - "\\bar": "", - }})) - - assertion = "A macro expander should allow for space function arguments" - new Expect(r`\frac\bar\bar`).toParseLike(r`\frac{}{}`, new Settings({macros: { "\\bar": " " }})) - - assertion = "A macro expander should allow aliasing characters" - new Expect(r`x’=c`).toParseLike("x'=c", new Settings({macros: { "’": "'" }})) - - assertion = "In a macro expander, \\@firstoftwo should consume both, and avoid errors" - new Expect(r`\@firstoftwo{yes}{no}`).toParseLike("yes") - new Expect(r`\@firstoftwo{yes}{1'_2^3}`).toParseLike("yes") - - assertion = "In a macro expander, \\@ifstar should consume star but nothing else" - new Expect(r`\@ifstar{yes}{no}*!`).toParseLike("yes!") - new Expect(r`\@ifstar{yes}{no}?!`).toParseLike("no?!") - - assertion = "In a macro expander, \\@ifnextchar should not consume nonspaces" - new Expect(r`\@ifnextchar!{yes}{no}!!`).toParseLike("yes!!") - new Expect(r`\@ifnextchar!{yes}{no}?!`).toParseLike("no?!") - - assertion = "In a macro expander, \\@ifnextchar should consume spaces" - new Expect(r`\def\x#1{\@ifnextchar x{yes}{no}}\x{}x\x{} x`).toParseLike("yesxyesx") - - assertion = "In a macro expander, \\@ifstar should consume star but nothing else" - new Expect(r`\@ifstar{yes}{no}*!`).toParseLike("yes!") - new Expect(r`\@ifstar{yes}{no}?!`).toParseLike("no?!") - - assertion = "In a macro expander, \\def defines macros" - new Expect(r`\def\foo{x^2}\foo+\foo`).toParseLike(`x^2+x^2`) - new Expect(r`\def\foo{hi}\foo+\text\foo`).toParseLike(r`hi+\text{hi}`) - new Expect(r`\def\foo#1{hi #1}\text{\foo{Alice}, \foo{Bob}}`).toParseLike(r`\text{hi Alice, hi Bob}`) - new Expect(r`\def\foo#1#2{(#1,#2)}\foo 1 2+\foo 3 4`).toParseLike(r`(1, 2)+(3, 4)`) - new Expect(r`\def\foo#a{}`).toNotParse() - new Expect(r`\def\foo#1#2#3#4#5#6#7#8#9{}`).toParse() - new Expect(r`\def\foo#2{}`).toNotParse() - new Expect(r`\def\foo#1#2#3#4#5#6#7#8#9#10{}`).toNotParse() - new Expect(r`\def\foo1`).toNotParse() - new Expect(r`\def{\foo}{}`).toNotParse() - new Expect(r`\def\foo\bar`).toNotParse() - new Expect(r`\def{\foo\bar}{}`).toNotParse() - new Expect(r`\def{}{}`).toNotParse() - - assertion = "In a macro expander, \\def defines macros with delimited parameter" - new Expect(r`\def\foo|#1||{#1}\text{\foo| x y ||}`).toParseLike(r`\text{ x y }`) - new Expect(r`\def\foo#1|#2{#1+#2}\foo a 2 |34`).toParseLike(r`a2+34`) - new Expect(r`\def\foo#1#{#1}\foo1^{23}`).toParseLike(r`1^{23}`) - new Expect(r`\def\foo|{}\foo`).toNotParse() - new Expect(r`\def\foo#1|{#1}\foo1`).toNotParse() - new Expect(r`\def\foo#1|{#1}\foo1}|`).toNotParse() - - assertion = "In a macro expander, \\edef should expand definition" - new Expect(r`\def\foo{a}\edef\bar{\foo}\def\foo{}\bar`).toParseLike(`a`) - // \def\noexpand\foo{} expands into \def\foo{} - new Expect(r`\def\foo{a}\edef\bar{\def\noexpand\foo{}}\foo\bar\foo`).toParseLike(r`a`) - // \foo\noexpand\foo expands into a\foo - new Expect(r`\def\foo{a}\edef\bar{\foo\noexpand\foo}\def\foo{b}\bar`).toParseLike(r`ab`) - // \foo is not defined - new Expect(r`\edef\bar{\foo}`).toNotParse(strictSettings()) - - assertion = "In a macro expander, \\long needs to be followed by macro prefixes, \\def or \\edef" - new Expect(r`\long\def\foo{}\foo`).toParseLike("") - new Expect(r`\long\edef\foo{}\foo`).toParseLike("") - new Expect(r`\long\foo`).toNotParse() - - assertion = "In a macro expander, \\let copies the definition" - new Expect(r`\let\foo=\frac\def\frac{}\foo1a`).toParseLike(r`\frac1a`) - new Expect(r`\def\foo{1}\let\bar\foo\def\foo{2}\bar`).toParseLike(r`1`) - new Expect(r`\let\foo=\kern\edef\bar{\foo1em}\let\kern=\relax\bar`).toParseLike(r`\kern1em`) - // \foo = { (left brace) - new Expect(r`\let\foo{\sqrt\foo1}`).toParseLike(r`\sqrt{1}`) - // \equals = = (equal sign) - new Expect(r`\let\equals==a\equals b`).toParseLike(r`a=b`) - // \foo should not be expandable and not affected by \noexpand or \edef - new Expect(r`\let\foo=x\noexpand\foo`).toParseLike(r`x`) - new Expect(r`\let\foo=x\edef\bar{\foo}\def\foo{y}\bar`).toParseLike(r`y`) - - assertion = "In a macro expander, \\let should consume one optional space after equals sign" - // https://tex.stackexchange.com/questions/141166/let-foo-bar-vs-let-foo-bar-let-with-equals-sign - new Expect(r`\def\:{\let\space= }\: \text{\space}`).toParseLike(r`\text{ }`) - - assertion = "In a macro expander, \\futurelet should parse correctly" - new Expect(r`\futurelet\foo\frac1{2+\foo}`).toParseLike(r`\frac1{2+1}`) - - assertion = "In a macro expander, \\newcommand defines new macros" - new Expect(r`\newcommand\foo{x^2}\foo+\foo`).toParseLike(`x^2+x^2`, strictSettings()) - new Expect(r`\newcommand{\foo}{x^2}\foo+\foo`).toParseLike(`x^2+x^2`, strictSettings()) - // Function detection - new Expect(r`\newcommand\bar{x^2}\bar+\bar`).toNotParse() - new Expect(r`\newcommand{\bar}{x^2}\bar+\bar`).toNotParse() - // Symbol detection - new Expect(r`\newcommand\lambda{x^2}\lambda`).toNotParse() - new Expect(r`\newcommand\textdollar{x^2}\textdollar`).toNotParse() - // Macro detection - new Expect(r`\newcommand{\foo}{1}\foo\newcommand{\foo}{2}\foo`).toNotParse() - // Implicit detection - new Expect(r`\newcommand\limits{}`).toNotParse() - - assertion = "In a macro expander, \\renewcommand redefines macro" - new Expect(r`\renewcommand\foo{x^2}\foo+\foo`).toNotParse(strictSettings()) - new Expect(r`\renewcommand{\foo}{x^2}\foo+\foo`).toNotParse(strictSettings()) - new Expect(r`\renewcommand\bar{x^2}\bar+\bar`).toParseLike(r`x^2+x^2`, strictSettings()) - new Expect(r`\renewcommand{\bar}{x^2}\bar+\bar`).toParseLike(r`x^2+x^2`, strictSettings()) - new Expect(r`\newcommand{\foo}{1}\foo\renewcommand{\foo}{a}\foo`).toParseLike(r`1a`, strictSettings()) - - assertion = "In a macro expander, \\providecommand (re)defines macros" - new Expect(r`\providecommand\foo{x^2}\foo+\foo`).toParseLike(r`x^2+x^2`, strictSettings()) - new Expect(r`\providecommand{\foo}{x^2}\foo+\foo`).toParseLike(r`x^2+x^2`, strictSettings()) - new Expect(r`\providecommand\bar{x^2}\bar+\bar`).toParseLike(r`x^2+x^2`, strictSettings()) - new Expect(r`\providecommand{\bar}{x^2}\bar+\bar`).toParseLike(r`x^2+x^2`, strictSettings()) - new Expect(r`\newcommand{\foo}{1}\foo\providecommand{\foo}{b}\foo`).toParseLike(r`1b`, strictSettings()) - new Expect(r`\providecommand{\foo}{1}\foo\renewcommand{\foo}{b}\foo`).toParseLike(r`1b`, strictSettings()) - new Expect(r`\providecommand{\foo}{1}\foo\providecommand{\foo}{b}\foo`).toParseLike(r`1b`, strictSettings()) - - assertion = "In a macro expander, \\newcommand accepts number of arguments" - new Expect(r`\newcommand\foo[1]{#1^2}\foo x+\foo{y}`).toParseLike(r`x^2+y^2`, strictSettings()) - new Expect(r`\newcommand\foo[9]{#1^2}\foo abcdefghi`).toParseLike(r`a^2`, strictSettings()) - new Expect(r`\newcommand\foo[x]{}`).toNotParse(strictSettings()) - new Expect(r`\newcommand\foo[1.5]{}`).toNotParse(strictSettings()) - - // This may change in the future, if we support the extra features of \hspace. - assertion = "A macro expander should treat \\hspace, \\hskip like \\kern" - new Expect(r`\hspace{1em}`).toParseLike(r`\kern1em`) - new Expect(r`\hskip{1em}`).toParseLike(r`\kern1em`) - - assertion = "A macro expander should expand \\limsup and \\liminf as expected" - new Expect(r`\limsup`).toParseLike(r`\operatorname*{lim\,sup}`) - new Expect(r`\liminf`).toParseLike(r`\operatorname*{lim\,inf}`) - - assertion = "A macro expander should expand AMS log-like symbols as expected" - new Expect(r`\injlim`).toParseLike(r`\operatorname*{inj\,lim}`) - new Expect(r`\projlim`).toParseLike(r`\operatorname*{proj\,lim}`) - new Expect(r`\varlimsup`).toParseLike(r`\operatorname*{\overline{\text{lim}}}`) - new Expect(r`\varliminf`).toParseLike(r`\operatorname*{\underline{\text{lim}}}`) - new Expect(r`\varinjlim`).toParseLike(r`\operatorname*{\underrightarrow{\text{lim}}}`) - new Expect(r`\varinjlim`).toParseLike(r`\operatorname*{\underrightarrow{\text{lim}}}`) - new Expect(r`\varprojlim`).toParseLike(r`\operatorname*{\underleftarrow{\text{lim}}}`) - - assertion = "A macro expander should expand \\plim and \\argmin and \\argmax as expected" - new Expect(r`\plim`).toParseLike(r`\operatorname*{plim}`) - new Expect(r`\argmin`).toParseLike(r`\operatorname*{arg\,min}`) - new Expect(r`\argmax`).toParseLike(r`\operatorname*{arg\,max}`) - - assertion = "A macro expander should expand \\bra and \ket as expected" - new Expect(r`\bra{\phi}`).toParseLike(r`\mathinner{\langle{\phi}|}`) - new Expect(r`\ket{\psi}`).toParseLike(r`\mathinner{|{\psi}\rangle}`) - new Expect(r`\braket{\phi|\psi}`).toParseLike(r`\mathinner{\langle{\phi|\psi}\rangle}`) - new Expect(r`\Bra{\phi}`).toParseLike(r`\left\langle\phi\right|`) - new Expect(r`\Ket{\psi}`).toParseLike(r`\left|\psi\right\rangle`) - - assertion = "Macro arguments do not generate groups" - new Expect("\\def\\x{a}\\x\\def\\foo#1{#1}\\foo{\\x\\def\\x{b}\\x}\\x").toParseLike(`aabb`) - - assertion = "\\gdef or \\xdef should produce an error" - new Expect(temml.renderToString("\gdef\foo{Nope}")).toContain("#b22222") // color of error message - new Expect(temml.renderToString("\xdef\foo{Nope}")).toContain("#b22222") - - assertion = "A preamble should capture viable macros and definecolor." - let macros = temml.definePreamble(r`\definecolor{sortaGreen}{RGB}{128,128,0}`) - new Expect(r`\color{sortaGreen} F=ma`).toParse(new Settings({macros})) - macros = temml.definePreamble(r`\def\foo{x^2}`) - markup = temml.renderToString(r`\foo + \foo`, new Settings({macros})) - new Expect(markup).toContain(``) - macros = temml.definePreamble(r`\newcommand\d[0]{\operatorname{d}\!}`) - markup = temml.renderToString(r`\d x`, new Settings({macros})) - new Expect(markup).toContain(``) - - assertion = "\\textbf arguments do generate groups" - new Expect("\\def\\x{a}\\x\\textbf{\\x\\def\\x{b}\\x}\\x").toParseLike(r`a\textbf{ab}a`) - - assertion = "\\sqrt optional arguments generate groups" - new Expect("\\def\\x{a}\\def\\y{a}\\x\\y" + "\\sqrt[\\def\\x{b}\\x]{\\def\\y{b}\\y}\\x\\y").toParseLike(r`aa\sqrt[b]{b}aa`) - - assertion = "Array cells generate groups" - new Expect(r`\def\x{a}\begin{matrix}\x&\def\x{b}\x&\x\end{matrix}\x`).toParseLike(r`\begin{matrix}a&b&a\end{matrix}a`) - new Expect(r`\def\x{1}\begin{matrix}\def\x{2}\x&\x\end{matrix}\x`).toParseLike(r`\begin{matrix}2&1\end{matrix}1`) - - assertion = "\\char produces literal characters" - new Expect("\\char`a").toParseLike("\\char`\\a"); - new Expect("\\char`\\%").toParseLike("\\char37"); - new Expect("\\char`\\%").toParseLike("\\char'45"); - new Expect("\\char`\\%").toParseLike('\\char"25'); - new Expect("\\char").toNotParse(); - new Expect("\\char`").toNotParse(); - new Expect("\\char'").toNotParse(); - new Expect('\\char"').toNotParse(); - new Expect("\\char'a").toNotParse(); - new Expect('\\char"g').toNotParse(); - new Expect('\\char"g').toNotParse(); - - assertion = "Unicode private area characters should build" - new Expect(r`\gvertneqq\lvertneqq\ngeqq\ngeqslant\nleqq`).toParse() - new Expect(r`\nleqslant\nshortmid\nshortparallel\varsubsetneq`).toParse() - new Expect(r`\varsubsetneqq\varsupsetneq\varsupsetneqq`).toParse() - new Expect(r`\gvertneqq\lvertneqq\ngeqq\ngeqslant\nleqq`).toBuild() - new Expect(r`\nleqslant\nshortmid\nshortparallel\varsubsetneq`).toBuild() - new Expect(r`\varsubsetneqq\varsupsetneq\varsupsetneqq`).toBuild() - - assertion = "\\overset and \\underset should work" - new Expect(r`\overset{f}{\rightarrow} Y`).toParse() - new Expect("\\underset{f}{\\rightarrow} Y").toParse() - new Expect(r`\overset{f}{\rightarrow} Y`).toBuild() - new Expect("\\underset{f}{\\rightarrow} Y").toBuild() - - assertion = "\\iff, \\implies, and \\impliedby should work" - new Expect(r`X \iff Y`).toParse() - new Expect(r`X \implies Y`).toParse() - new Expect(r`X \impliedby Y`).toParse() - new Expect(r`X \iff Y`).toBuild() - new Expect(r`X \implies Y`).toBuild() - new Expect(r`X \impliedby Y`).toBuild() - - assertion = "\\tag support should fail outside display mode" - new Expect(r`\tag{hi}x+y`).toNotParse() - assertion = "\\tag support should fail with multiple tags" - new Expect(r`\tag{1}\tag{2}x+y`).toNotParse(displayMode()) - assertion = "\\tag should build" - new Expect(r`\tag{hi}x+y`).toParse(displayMode()); - new Expect(r`\tag{hi}x+y`).toBuild(displayMode()); - assertion = "\\tag support should ignore location of \\tag" - new Expect(r`\tag{hi}x+y`).toParseLike(r`x+y\tag{hi}`, displayMode()); - assertion = "\\tag support should handle \\tag* like \\tag" - new Expect(r`\tag{hi}x+y`).toParseLike(r`\tag*{({hi})}x+y`, displayMode()); - assertion = "\\tag support should add tml-tageqn class" - new Expect(temml.renderToString(r`\tag{hi}x+y`, displayMode())).toContain("tml-tageqn") - assertion = "leqno rendering option should differ from default" - new Expect(temml.renderToString(r`\tag{hi}x+y`, new Settings({ displayMode: true, leqno: true }))).toContain("rspace") - new Expect(temml.renderToString(r`\tag{hi}x+y`,displayMode())).toNotContain("rspace") - - assertion = "\\@binrel automatic bin/rel/ord should generate proper class" - new Expect(parse("L\\@binrel+xR")[1].mclass).toBe("mbin") - new Expect(parse("L\\@binrel=xR")[1].mclass).toBe("mrel") - new Expect(parse("L\\@binrel xxR")[1].mclass).toBe("mord") - new Expect(parse("L\\@binrel=xR")[1].mclass).toBe("mrel") - new Expect(parse("L\\@binrel{+}{x}R")[1].mclass).toBe("mbin") - new Expect(parse("L\\@binrel{=}{x}R")[1].mclass).toBe("mrel") - new Expect(parse("L\\@binrel{z}{x}R")[1].mclass).toBe("mord") - assertion = "\\@binrel automatic bin/rel/ord should base on just first character in group" - new Expect(parse("L\\@binrel{+x}xR")[1].mclass).toBe("mbin") - new Expect(parse("L\\@binrel{=x}xR")[1].mclass).toBe("mrel") - new Expect(parse("L\\@binrel{xx}xR")[1].mclass).toBe("mord") - - assertion = "A parser taking String objects should not fail on an empty String object" - new Expect(new String("")).toParse() - new Expect(new String("")).toBuild() - assertion = "A parser taking String objects should parse the same as a regular string" - new Expect(new String("xy")).toParseLike(`xy`) - new Expect(new String(r`\div`)).toParseLike(r`\div`) - new Expect(new String(r`\frac 1 2`)).toParseLike(r`\frac 1 2`) - - assertion = "Unicode accents should parse Latin-1 letters in math mode" - new Expect(`ÀÁÂÃÄÅÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝàáâãäåèéêëìíîïñòóôõöùúûüýÿ`).toParseLike( - r`\grave A\acute A\hat A\tilde A\ddot A\mathring A` + - r`\grave E\acute E\hat E\ddot E` + - r`\grave I\acute I\hat I\ddot I` + - r`\tilde N` + - r`\grave O\acute O\hat O\tilde O\ddot O` + - r`\grave U\acute U\hat U\ddot U` + - r`\acute Y` + - r`\grave a\acute a\hat a\tilde a\ddot a\mathring a` + - r`\grave e\acute e\hat e\ddot e` + - r`\grave ı\acute ı\hat ı\ddot ı` + - r`\tilde n` + - r`\grave o\acute o\hat o\tilde o\ddot o` + - r`\grave u\acute u\hat u\ddot u` + - r`\acute y\ddot y` - ) - - assertion = "Unicode accents should parse Latin-1 letters in text mode" - new Expect(`\\text{ÀÁÂÃÄÅÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝàáâãäåèéêëìíîïñòóôõöùúûüýÿ}`).toParseLike( - r`\text{\`A\'A\^A\~A\"A\r A` + - r`\`E\'E\^E\"E` + - r`\`I\'I\^I\"I` + - r`\~N` + - r`\`O\'O\^O\~O\"O` + - r`\`U\'U\^U\"U` + - r`\'Y` + - r`\`a\'a\^a\~a\"a\r a` + - r`\`e\'e\^e\"e` + - r`\`ı\'ı\^ı\"ı` + - r`\~n` + - r`\`o\'o\^o\~o\"o` + - r`\`u\'u\^u\"u` + - r`\'y\"y}` - ) - - assertion = "Unicode accents should parse combining characters" - new Expect("A\u0301C\u0301").toParseLike(r`Á\acute C`); - new Expect("\\text{A\u0301C\u0301}").toParseLike(r`\text{Á\'C}`, strictSettings()); - - assertion = "Unicode accents should build multi-accented characters" - new Expect(`ấā́ắ\text{ấā́ắ}`).toParse() - new Expect(`ấā́ắ\text{ấā́ắ}`).toBuild() - - assertion = "Unicode accents should parse accented i's and j's" - new Expect(`íȷ́`).toParseLike(r`\acute ı\acute ȷ`); - new Expect(`ấā́ắ\text{ấā́ắ}`).toParse(); - new Expect(`ấā́ắ\text{ấā́ắ}`).toBuild(); - - assertion = "Temml should build Unicode relations" - new Expect(`∈∋∝∼∽≂≃≅≈≊≍≎≏≐≑≒≓≖≗≜≡≤≥≦≧≪≫≬≳≷≺≻≼≽≾≿∴∵∣≔≕⩴⋘⋙⟂⊨∌⊶⊷⊂⊃⊆⊇⊏⊐⊑⊒⊢⊣⊩⊪⊸⋈⋍⋐⋑⋔⋛⋞⋟⌢⌣⩾⪆⪌⪕⪖⪯⪰⪷⪸⫅⫆≘≙≚≛≝≞≟≲⩽⪅≶⋚⪋`).toParse() - new Expect(`∈∋∝∼∽≂≃≅≈≊≍≎≏≐≑≒≓≖≗≜≡≤≥≦≧≪≫≬≳≷≺≻≼≽≾≿∴∵∣≔≕⩴⋘⋙⟂⊨∌⊶⊷⊂⊃⊆⊇⊏⊐⊑⊒⊢⊣⊩⊪⊸⋈⋍⋐⋑⋔⋛⋞⋟⌢⌣⩾⪆⪌⪕⪖⪯⪰⪷⪸⫅⫆≘≙≚≛≝≞≟≲⩽⪅≶⋚⪋`).toBuild() - assertion = "Temml should build Unicode negated relations" - new Expect(`∉∤∦≁≆≠≨≩≮≯≰≱⊀⊁⊈⊉⊊⊋⊬⊭⊮⊯⋠⋡⋦⋧⋨⋩⋬⋭⪇⪈⪉⪊⪵⪶⪹⪺⫋⫌`).toParse() - new Expect(`∉∤∦≁≆≠≨≩≮≯≰≱⊀⊁⊈⊉⊊⊋⊬⊭⊮⊯⋠⋡⋦⋧⋨⋩⋬⋭⪇⪈⪉⪊⪵⪶⪹⪺⫋⫌`).toBuild() - assertion = "Temml should build Unicode big operators" - new Expect(`∏∐∑∫∬∭∮⋀⋁⋂⋃⨀⨁⨂⨄⨆`).toParse() - new Expect(`∏∐∑∫∬∭∮⋀⋁⋂⋃⨀⨁⨂⨄⨆`).toBuild() - assertion = "Temml should build Unicode symbols" - new Expect(`£¥ℂℍℑℎℓℕ℘ℙℚℜℝℤℲℵðℶℷℸ⅁∀∁∂∃∇∞∠∡∢♠♡♢♣♭♮♯✓°¬‼⋮\u00B7\u00A9\\text{£¥ℂℍℎ\u00A9\u00AE\uFE0F}`).toParse() - new Expect(`£¥ℂℍℑℎℓℕ℘ℙℚℜℝℤℲℵðℶℷℸ⅁∀∁∂∃∇∞∠∡∢♠♡♢♣♭♮♯✓°¬‼⋮\u00B7\u00A9\\text{£¥ℂℍℎ\u00A9\u00AE\uFE0F}`).toBuild() - assertion = "Temml should build capital Greek letters" - new Expect(`\u0391\u0392\u0395\u0396\u0397\u0399\u039A\u039C\u039D\u039F\u03A1\u03A4\u03A7\u03DD`).toParse(strictSettings()) - new Expect(`\u0391\u0392\u0395\u0396\u0397\u0399\u039A\u039C\u039D\u039F\u03A1\u03A4\u03A7\u03DD`).toBuild(strictSettings()) - assertion = "Temml should build Unicode arrows" - new Expect(`←↑→↓↔↕↖↗↘↙↚↛↞↠↢↣↦↩↪↫↬↭↮↰↱↶↷↼↽↾↾↿⇀⇁⇂⇃⇄⇆⇇⇈⇉⇊⇋⇌⇍⇎⇏⇐⇑⇒⇓⇔⇕⇚⇛⇝⟵⟶⟷⟸⟹⟺⟼`).toParse() - new Expect(`←↑→↓↔↕↖↗↘↙↚↛↞↠↢↣↦↩↪↫↬↭↮↰↱↶↷↼↽↾↾↿⇀⇁⇂⇃⇄⇆⇇⇈⇉⇊⇋⇌⇍⇎⇏⇐⇑⇒⇓⇔⇕⇚⇛⇝⟵⟶⟷⟸⟹⟺⟼`).toBuild() - assertion = "Temml should build Unicode binary operators" - new Expect(`±×÷∓∔∧∨∩∪≀⊎⊓⊔⊕⊖⊗⊘⊙⊚⊛⊝◯⊞⊟⊠⊡⊺⊻⊼⋇⋉⋊⋋⋌⋎⋏⋒⋓⩞\u22C5\u2216\u2218\u2219`).toParse() - new Expect(`±×÷∓∔∧∨∩∪≀⊎⊓⊔⊕⊖⊗⊘⊙⊚⊛⊝◯⊞⊟⊠⊡⊺⊻⊼⋇⋉⋊⋋⋌⋎⋏⋒⋓⩞\u22C5\u2216\u2218\u2219`).toBuild() - assertion = "Temml should build Unicode delimiters" - new Expect("\\left\u230A\\frac{a}{b}\\right\u230B").toParse() - new Expect("\\left\u2308\\frac{a}{b}\\right\u2308").toParse() - new Expect("\\left\u27ee\\frac{a}{b}\\right\u27ef").toParse() - new Expect("\\left\u27e8\\frac{a}{b}\\right\u27e9").toParse() - new Expect("\\left\u23b0\\frac{a}{b}\\right\u23b1").toParse() - new Expect(`┌x┐ └x┘`).toParse() - new Expect("\u231Cx\u231D \u231Ex\u231F").toParse() - new Expect("\u27E6x\u27E7").toParse() - new Expect("\\llbracket \\rrbracket").toParse() - new Expect("\\lBrace \\rBrace").toParse() - new Expect("\\left\u230A\\frac{a}{b}\\right\u230B").toBuild() - new Expect("\\left\u2308\\frac{a}{b}\\right\u2308").toBuild() - new Expect("\\left\u27ee\\frac{a}{b}\\right\u27ef").toBuild() - new Expect("\\left\u27e8\\frac{a}{b}\\right\u27e9").toBuild() - new Expect("\\left\u23b0\\frac{a}{b}\\right\u23b1").toBuild() - new Expect(`┌x┐ └x┘`).toBuild() - new Expect("\u231Cx\u231D \u231Ex\u231F").toBuild() - new Expect("\u27E6x\u27E7").toBuild() - new Expect("\\llbracket \\rrbracket").toBuild() - new Expect("\\lBrace \\rBrace").toBuild() - assertion = "Temml should build some Unicode surrogate pairs" - let wideCharStr = ""; - wideCharStr += String.fromCharCode(0xD835, 0xDC00); // bold A - wideCharStr += String.fromCharCode(0xD835, 0xDC68); // bold italic A - wideCharStr += String.fromCharCode(0xD835, 0xDD04); // Fraktur A - wideCharStr += String.fromCharCode(0xD835, 0xDD38); // double-struck - wideCharStr += String.fromCharCode(0xD835, 0xDC9C); // script A - wideCharStr += String.fromCharCode(0xD835, 0xDDA0); // sans serif A - wideCharStr += String.fromCharCode(0xD835, 0xDDD4); // bold sans A - wideCharStr += String.fromCharCode(0xD835, 0xDE08); // italic sans A - wideCharStr += String.fromCharCode(0xD835, 0xDE70); // monospace A - wideCharStr += String.fromCharCode(0xD835, 0xDFCE); // bold zero - wideCharStr += String.fromCharCode(0xD835, 0xDFE2); // sans serif zero - wideCharStr += String.fromCharCode(0xD835, 0xDFEC); // bold sans zero - wideCharStr += String.fromCharCode(0xD835, 0xDFF6); // monospace zero - new Expect(wideCharStr).toParse(strictSettings()); - new Expect(wideCharStr).toBuild(strictSettings()); - let wideCharText = "\text{"; - wideCharText += String.fromCharCode(0xD835, 0xDC00); // bold A - wideCharText += String.fromCharCode(0xD835, 0xDC68); // bold italic A - wideCharText += String.fromCharCode(0xD835, 0xDD04); // Fraktur A - wideCharText += String.fromCharCode(0xD835, 0xDD38); // double-struck - wideCharText += String.fromCharCode(0xD835, 0xDC9C); // script A - wideCharText += String.fromCharCode(0xD835, 0xDDA0); // sans serif A - wideCharText += String.fromCharCode(0xD835, 0xDDD4); // bold sans A - wideCharText += String.fromCharCode(0xD835, 0xDE08); // italic sans A - wideCharText += String.fromCharCode(0xD835, 0xDE70); // monospace A - wideCharText += String.fromCharCode(0xD835, 0xDFCE); // bold zero - wideCharText += String.fromCharCode(0xD835, 0xDFE2); // sans serif zero - wideCharText += String.fromCharCode(0xD835, 0xDFEC); // bold sans zero - wideCharText += String.fromCharCode(0xD835, 0xDFF6); // monospace zero - wideCharText += "}"; - new Expect(wideCharText).toParse(strictSettings()); - new Expect(wideCharText).toBuild(strictSettings()); - - assertion = "The maxSize setting should clamp size when set" - const rule = r`\rule{999em}{999em}` - markup = temml.renderToString(rule, new Settings({ maxSize: [5, 80] })) - new Expect(markup).toContain(`width="5em"`) - new Expect(markup).toContain(`height="5em"`) - assertion = "The maxSize setting should not clamp size when not set" - markup = temml.renderToString(rule) - new Expect(markup).toNotContain(`width="5em"`) - new Expect(markup).toNotContain(`height="5em"`) - assertion = "The maxSize setting should make zero-width rules if a negative maxSize is passed" - markup = temml.renderToString(rule, new Settings({ maxSize: [-5, -80] })) - new Expect(markup).toContain(`width="0em"`) - new Expect(markup).toContain(`height="0em"`) - - assertion = "The maxExpand setting should prevent expansion" - new Expect(r`\def\foo{1}\foo`).toParse() - new Expect(r`\def\foo{1}\foo`).toBuild() - new Expect(r`\def\foo{1}\foo`).toParse(new Settings({maxExpand: 1})) - new Expect(r`\def\foo{1}\foo`).toNotParse(new Settings({maxExpand: 0})) - assertion = "The maxExpand setting should prevent infinite loops" - new Expect(r`\def\foo{\foo}\foo`).toNotParse(new Settings({maxExpand: 10})) - - assertion = "The \\mathchoice function should render as if there is nothing other in display math" - const cmd = r`\sum_{k = 0}^{\infty} x^k` - new Expect(`\\displaystyle\\mathchoice{${cmd}}{T}{S}{SS}`).toBuildLike(`\\displaystyle${cmd}`) - assertion = "The \\mathchoice function should render as if there is nothing other in text" - new Expect(`\\textstyle\\mathchoice{D}{${cmd}}{S}{SS}`).toBuildLike(`\\textstyle${cmd}`) - assertion = "The \\mathchoice function should render as if there is nothing other in scriptstyle" - new Expect(`\\scriptstyle\\mathchoice{D}{T}{${cmd}}{SS}`).toBuildLike(`\\scriptstyle${cmd}`) - assertion = "The \\mathchoice function should render as if there is nothing other in scriptscriptstyle" - new Expect(`\\scriptscriptstyle\\mathchoice{D}{T}{S}{${cmd}}`).toBuildLike(`\\scriptscriptstyle${cmd}`) - - assertion = "Newlines via \\\\ and \\newline should build \\\\ without the optional argument and \\newline the same" - new Expect(r`hello \\ world`).toBuildLike(r`hello \newline world`) - assertion = "Newlines via \\\\ and \\newline should not allow \\newline to scan for an optional size argument" - new Expect(r`hello \newline[w]orld`).toParse() - new Expect(r`hello \newline[w]orld`).toBuild() - assertion = "Newlines via \\\\ and \\newline should not allow \\cr at top level" - new Expect(temml.renderToString(r`hello \cr world`)).toContain("#b22222") // color of error message - assertion = "Newlines via \\\\ and \\newline: \\\\ causes newline, even after mrel and mop" - markup = temml.renderToString(r`M = \\ a + \\ b \\ c`) - new Expect(markup).toMatch(/=.+mo linebreak.+\+.+mo linebreak.+b.+mo linebreak/) - - assertion = "Symbols should build" - new Expect(r`\text{\i\j}`).toParse(strictSettings()) - new Expect(r`A\;B\,C\nobreakspace \text{A\;B\,C\nobreakspace}`).toParse(strictSettings()) - new Expect(r`\standardstate`).toParse(strictSettings()) - new Expect(r`\text{\i\j}`).toBuild(strictSettings()) - new Expect(r`A\;B\,C\nobreakspace \text{A\;B\,C\nobreakspace}`).toBuild(strictSettings()) - new Expect(r`\standardstate`).toBuild(strictSettings()) - new Expect(r`\text{\ae\AE\oe\OE\o\O\ss}`).toBuildLike(r`\text{æÆœŒøØß}`, strictSettings()) - - assertion = "Settings should allow unicode text when not strict" - new Expect(`é`).toParse() - new Expect(`試`).toParse() - - assertion = "Settings should forbid unicode text when strict" - new Expect(`é`).toNotParse(strictSettings()) - new Expect(`試`).toNotParse(strictSettings()); - - - console.log("Number of tests: " + numTests) - console.log("Number of failures: " + numFailures) -} - -test() diff --git a/test/wiki-tests.md b/test/wiki-tests.md deleted file mode 100644 index 3f0f8ab4..00000000 --- a/test/wiki-tests.md +++ /dev/null @@ -1,928 +0,0 @@ - - - - - - Temml Wiki Tests - - - - - - - - -# Wiki Test - -Rows 1 thru 261 on this page reproduce the math examples from \ -https://en.wikipedia.org/wiki/Help:Displaying\_a\_formula - -A few of the functions on this page require Temml’s _texvc_ extension. - -
    - -+-----+--------------------------------------------+------------------------------------------------+ -| | Source | Temml | -+=====+============================================+================================================+ -| 1 | \alpha | $`\alpha` | -+-----+--------------------------------------------+------------------------------------------------+ -| 2 | f(x) = x^2 | $`f(x) = x^2` | -+-----+--------------------------------------------+------------------------------------------------+ -| 3 | \\{1,e,\pi\\} | $`\{1,e,\pi\}` | -+-----+--------------------------------------------+------------------------------------------------+ -| 4 | |z + 1| \leq 2 | $`|z + 1| \leq 2` | -+-----+--------------------------------------------+------------------------------------------------+ -| 5 | `\# \$ \% ^\wedge \& \_ \{ \} \sim` \ | $`\# \$ \% ^\wedge \& \_ \{ \} \sim | -| | `\backslash` | \backslash` | -+-----+--------------------------------------------+------------------------------------------------+ -| **Accents** | -+-----+--------------------------------------------+------------------------------------------------+ -| 6 | \dot{a}, \ddot{a}, \acute{a}, \grave{a} | $`\dot{a}, \ddot{a}, \acute{a}, \grave{a}` | -+-----+--------------------------------------------+------------------------------------------------+ -| 7 | \dot{a}, \ddot{a}, \acute{a}, \grave{a} | $`\dot{a}, \ddot{a}, \acute{a}, \grave{a}` | -+-----+--------------------------------------------+------------------------------------------------+ -| 8 | \check{a}, \breve{a}, \tilde{a}, \bar{a} | $`\check{a}, \breve{a}, \tilde{a}, \bar{a}` | -+-----+--------------------------------------------+------------------------------------------------+ -| 9 | \hat{a}, \widehat{a}, \vec{a} | $`\hat{a}, \widehat{a}, \vec{a}` | -+-----+--------------------------------------------+------------------------------------------------+ -| **Functions** | -+-----+--------------------------------------------+------------------------------------------------+ -| 10 | \exp_a b = a^b, \exp b = e^b, 10^m | $`\exp_a b = a^b, \exp b = e^b, 10^m` | -+-----+--------------------------------------------+------------------------------------------------+ -| 11 | \ln c, \lg d = \log e, \log_{10} f | $`\ln c, \lg d = \log e, \log_{10} f` | -+-----+--------------------------------------------+------------------------------------------------+ -| 12 | \sin a, \cos b, \tan c, \cot d, \sec e, \ | $`\sin a, \cos b, \tan c, \cot d, \sec e, | -| | \csc f | \csc f` | -+-----+--------------------------------------------+------------------------------------------------+ -| 13 | \arcsin h, \arccos i, \arctan j | $`\arcsin h, \arccos i, \arctan j` | -+-----+--------------------------------------------+------------------------------------------------+ -| 14 | \sinh k, \cosh l, \tanh m, \coth n | $`\sinh k, \cosh l, \tanh m, \coth n` | -+-----+--------------------------------------------+------------------------------------------------+ -| 15 | \operatorname{sh}k, \operatorname{ch}l, \ | $`\operatorname{sh}k, \operatorname{ch}l, | -| | \operatorname{th}m, \operatorname{coth}n | \operatorname{th}m, \operatorname{coth}n` | -+-----+--------------------------------------------+------------------------------------------------+ -| 16 | \sgn r, \left\vert s \right\vert | $`\sgn r, \left\vert s \right\vert` | -+-----+--------------------------------------------+------------------------------------------------+ -| 17 | \min(x,y), \max(x,y) | $`\min(x,y), \max(x,y)` | -+-----+--------------------------------------------+------------------------------------------------+ -| **Bounds** | -+-----+--------------------------------------------+------------------------------------------------+ -| 18 | \min x, \max y, \inf s, \sup t | $`\min x, \max y, \inf s, \sup t` | -+-----+--------------------------------------------+------------------------------------------------+ -| 19 | \lim u, \liminf v, \limsup w | $`\lim u, \liminf v, \limsup w` | -+-----+--------------------------------------------+------------------------------------------------+ -| 20 | \dim p, \deg q, \det m, \ker\phi | $`\dim p, \deg q, \det m, \ker\phi` | -+-----+--------------------------------------------+------------------------------------------------+ -| **Projections** | -+-----+--------------------------------------------+------------------------------------------------+ -| 21 | \Pr j, \hom l, \lVert z \rVert, \arg z | $`\Pr j, \hom l, \lVert z \rVert, \arg z` | -+-----+--------------------------------------------+------------------------------------------------+ -| **Differentials and derivatives** | -+-----+--------------------------------------------+------------------------------------------------+ -| 22 | dt, \mathrm{d}t, \partial t, \nabla\psi | $`dt, \mathrm{d}t, \partial t, \nabla\psi` | -+-----+--------------------------------------------+------------------------------------------------+ -| 23 | dy/dx, \mathrm{d}y/\mathrm{d}x, \ | $`dy/dx, \mathrm{d}y/\mathrm{d}x, | -| | \frac{dy}{dx}, \ | \frac{dy}{dx}, | -| | \frac{\mathrm{d}y}{\mathrm{d}x}, \ | \frac{\mathrm{d}y}{\mathrm{d}x}, | -| | \frac{\partial^2}\ | \frac{\partial^2} | -| | {\partial x\_1\partial x\_2}y | {\partial x_1\partial x_2}y` | -+-----+--------------------------------------------+------------------------------------------------+ -| 24 | \prime, \backprime, f^\prime, f', f'', \ | $`\prime, \backprime, f^\prime, f', f'', | -| | f^{(3)}, \dot y, \ddot y | f^{(3)}, \dot y, \ddot y` | -+-----+--------------------------------------------+------------------------------------------------+ -| **Letter-like symbols or constants** | -+-----+--------------------------------------------+------------------------------------------------+ -| 25 | \infty, \aleph, \complement,\backepsilon,\ | $`\infty, \aleph, \complement,\backepsilon, | -| | \eth, \Finv, \hbar | \eth, \Finv, \hbar` | -+-----+--------------------------------------------+------------------------------------------------+ -| 26 | \Im, \imath, \jmath, \Bbbk, \ell, \mho, \ | $`\Im, \imath, \jmath, \Bbbk, \ell, \mho, | -| | \wp, \Re, \circledS, \S, \P, \AA | \wp, \Re, \circledS, \S, \P, \AA` | -+-----+--------------------------------------------+------------------------------------------------+ -| **Modular arithmetic** | -+-----+--------------------------------------------+------------------------------------------------+ -| 27 | s_k \equiv 0 \pmod{m} | $`s_k \equiv 0 \pmod{m}` | -+-----+--------------------------------------------+------------------------------------------------+ -| 28 | a \bmod b | $`a \bmod b` | -+-----+--------------------------------------------+------------------------------------------------+ -| 29 | \gcd(m, n), \operatorname{lcm}(m, n) | $`\gcd(m, n), \operatorname{lcm}(m, n)` | -+-----+--------------------------------------------+------------------------------------------------+ -| 30 | \mid, \nmid, \shortmid, \nshortmid | $`\mid, \nmid, \shortmid, \nshortmid` | -+-----+--------------------------------------------+------------------------------------------------+ -| **Radicals** | -+-----+--------------------------------------------+------------------------------------------------+ -| 31 | \surd, \sqrt{2}, \sqrt[n]{2}, \ | $`\surd, \sqrt{2}, \sqrt[n]{2}, | -| | \sqrt[3]{\frac{x^3+y^3}{2}} | \sqrt[3]{\frac{x^3+y^3}{2}}` | -+-----+--------------------------------------------+------------------------------------------------+ -| **Operators** | -+-----+--------------------------------------------+------------------------------------------------+ -| 32 | +, -, \pm, \mp, \dotplus | $`+, -, \pm, \mp, \dotplus` | -+-----+--------------------------------------------+------------------------------------------------+ -| 33 | \times, \div, \divideontimes, /,\backslash | $`\times, \div, \divideontimes, /, \backslash` | -+-----+--------------------------------------------+------------------------------------------------+ -| 34 | \cdot, * \ast, \star, \circ, \bullet | $`\cdot, * \ast, \star, \circ, \bullet` | -+-----+--------------------------------------------+------------------------------------------------+ -| 35 | \boxplus, \boxminus, \boxtimes, \boxdot | $`\boxplus, \boxminus, \boxtimes, \boxdot` | -+-----+--------------------------------------------+------------------------------------------------+ -| 36 | \oplus, \ominus, \otimes, \oslash, \odot | $`\oplus, \ominus, \otimes, \oslash, \odot` | -+-----+--------------------------------------------+------------------------------------------------+ -| 37 | \circleddash, \circledcirc, \circledast | $`\circleddash, \circledcirc, \circledast` | -+-----+--------------------------------------------+------------------------------------------------+ -| 38 | \bigoplus, \bigotimes, \bigodot | $`\bigoplus, \bigotimes, \bigodot` | -+-----+--------------------------------------------+------------------------------------------------+ -| **Sets** | -+-----+--------------------------------------------+------------------------------------------------+ -| 39 | \{ \}, \O \empty \emptyset, \varnothing | $`\{ \}, \O \empty \emptyset, \varnothing` | -+-----+--------------------------------------------+------------------------------------------------+ -| 40 | \in, \notin \not\in, \ni, \not\ni | $`\in, \notin \not\in, \ni, \not\ni` | -+-----+--------------------------------------------+------------------------------------------------+ -| 41 | \cap, \Cap, \sqcap, \bigcap | $`\cap, \Cap, \sqcap, \bigcap` | -+-----+--------------------------------------------+------------------------------------------------+ -| 42 | \cup, \Cup, \sqcup, \bigcup, \bigsqcup, \ | $`\cup, \Cup, \sqcup, \bigcup, \bigsqcup, | -| | \uplus, \biguplus | \uplus, \biguplus` | -+-----+--------------------------------------------+------------------------------------------------+ -| 43 | \setminus, \smallsetminus, \times | $`\setminus, \smallsetminus, \times` | -+-----+--------------------------------------------+------------------------------------------------+ -| 44 | \subset, \Subset, \sqsubset | $`\subset, \Subset, \sqsubset` | -+-----+--------------------------------------------+------------------------------------------------+ -| 45 | \supset, \Supset, \sqsupset | $`\supset, \Supset, \sqsupset` | -+-----+--------------------------------------------+------------------------------------------------+ -| 46 | \subseteq, \nsubseteq, \subsetneq, \ | $`\subseteq, \nsubseteq, \subsetneq, | -| | \varsubsetneq, \sqsubseteq | \varsubsetneq, \sqsubseteq` | -+-----+--------------------------------------------+------------------------------------------------+ -| 47 | \supseteq, \nsupseteq, \supsetneq, \ | $`\supseteq, \nsupseteq, \supsetneq, | -| | \varsupsetneq, \sqsupseteq | \varsupsetneq, \sqsupseteq` | -+-----+--------------------------------------------+------------------------------------------------+ -| 48 | \subseteqq, \nsubseteqq, \subsetneqq, \ | $`\subseteqq, \nsubseteqq, \subsetneqq, | -| | \varsubsetneqq | \varsubsetneqq` | -+-----+--------------------------------------------+------------------------------------------------+ -| 49 | \supseteqq, \nsupseteqq, \supsetneqq, \ | $`\supseteqq, \nsupseteqq, \supsetneqq, | -| | \varsupsetneqq | \varsupsetneqq` | -+-----+--------------------------------------------+------------------------------------------------+ -| **Relations** | -+-----+--------------------------------------------+------------------------------------------------+ -| 50 | =, \ne, \neq, \equiv, \not\equiv | $`=, \ne, \neq, \equiv, \not\equiv` | -+-----+--------------------------------------------+------------------------------------------------+ -| 51 | \doteq, \doteqdot, \ | $`\doteq, \doteqdot, | -| | \overset{\underset{\mathrm{def}}{}}{=}, := | \overset{\underset{\mathrm{def}}{}}{=}, :=` | -+-----+--------------------------------------------+------------------------------------------------+ -| 52 | \sim, \nsim, \backsim, \thicksim, \simeq,\ | $`\sim, \nsim, \backsim, \thicksim, \simeq, | -| | \backsimeq, \eqsim, \cong, \ncong | \backsimeq, \eqsim, \cong, \ncong` | -+-----+--------------------------------------------+------------------------------------------------+ -| 53 | \approx, \thickapprox, \approxeq, \asymp,\ | $`\approx, \thickapprox, \approxeq, \asymp, | -| | \propto, \varpropto | \propto, \varpropto` | -+-----+--------------------------------------------+------------------------------------------------+ -| 54 | <, \nless, \ll, \not\ll, \lll, \not\lll, \ | $`<, \nless, \ll, \not\ll, \lll, \not\lll, | -| | \lessdot | \lessdot` | -+-----+--------------------------------------------+------------------------------------------------+ -| 55 | \le, \leq, \lneq, \leqq, \nleq, \nleqq, \ | $`\le, \leq, \lneq, \leqq, \nleq, \nleqq, | -| | \lneqq, \lvertneqq | \lneqq, \lvertneqq` | -+-----+--------------------------------------------+------------------------------------------------+ -| 56 | \ge, \geq, \gneq, \geqq, \ngeq, \ngeqq, \ | $`\ge, \geq, \gneq, \geqq, \ngeq, \ngeqq, | -| | \gneqq, \gvertneqq | \gneqq, \gvertneqq` | -+-----+--------------------------------------------+------------------------------------------------+ -| 57 | \lessgtr, \lesseqgtr, \lesseqqgtr, \ | $`\lessgtr, \lesseqgtr, \lesseqqgtr, | -| | \gtrless, \gtreqless, \gtreqqless | \gtrless, \gtreqless, \gtreqqless` | -+-----+--------------------------------------------+------------------------------------------------+ -| 58 | \leqslant, \nleqslant, \eqslantless | $`\leqslant, \nleqslant, \eqslantless` | -+-----+--------------------------------------------+------------------------------------------------+ -| 59 | \geqslant, \ngeqslant, \eqslantgtr | $`\geqslant, \ngeqslant, \eqslantgtr` | -+-----+--------------------------------------------+------------------------------------------------+ -| 60 | \lesssim, \lnsim, \lessapprox, \lnapprox | $`\lesssim, \lnsim, \lessapprox, \lnapprox` | -+-----+--------------------------------------------+------------------------------------------------+ -| 61 | \gtrsim, \gnsim, \gtrapprox, \gnapprox | $`\gtrsim, \gnsim, \gtrapprox, \gnapprox` | -+-----+--------------------------------------------+------------------------------------------------+ -| 62 | \prec, \nprec, \preceq, \npreceq,\precneqq | $`\prec, \nprec, \preceq, \npreceq, \precneqq` | -+-----+--------------------------------------------+------------------------------------------------+ -| 63 | \succ, \nsucc, \succeq, \nsucceq,\succneqq | $`\succ, \nsucc, \succeq, \nsucceq, \succneqq` | -+-----+--------------------------------------------+------------------------------------------------+ -| 64 | \preccurlyeq, \curlyeqprec | $`\preccurlyeq, \curlyeqprec` | -+-----+--------------------------------------------+------------------------------------------------+ -| 65 | \succcurlyeq, \curlyeqsucc | $`\succcurlyeq, \curlyeqsucc` | -+-----+--------------------------------------------+------------------------------------------------+ -| 66 | \precsim, \precnsim, \precapprox, \ | $`\precsim, \precnsim, \precapprox, | -| | \precnapprox | \precnapprox` | -+-----+--------------------------------------------+------------------------------------------------+ -| 67 | \succsim, \succnsim, \succapprox, \ | $`\succsim, \succnsim, \succapprox, | -| | \succnapprox | \succnapprox` | -+-----+--------------------------------------------+------------------------------------------------+ -| **Geometric** | -+-----+--------------------------------------------+------------------------------------------------+ -| 68 | \parallel, \nparallel, \shortparallel, \ | $`\parallel, \nparallel, \shortparallel, | -| | \nshortparallel | \nshortparallel` | -+-----+--------------------------------------------+------------------------------------------------+ -| 69 | \perp, \angle, \sphericalangle, \ | $`\perp, \angle, \sphericalangle, | -| | \measuredangle, 45^\circ | \measuredangle, 45^\circ` | -+-----+--------------------------------------------+------------------------------------------------+ -| 70 | \Box, \square, \blacksquare, \diamond, \ | $`\Box, \square, \blacksquare, \diamond, | -| | \Diamond, \lozenge, \blacklozenge,\bigstar | \Diamond, \lozenge, \blacklozenge,\bigstar` | -+-----+--------------------------------------------+------------------------------------------------+ -| 71 | \bigcirc, \triangle, \bigtriangleup, \ | $`\bigcirc, \triangle, \bigtriangleup, | -| | \bigtriangledown | \bigtriangledown` | -+-----+--------------------------------------------+------------------------------------------------+ -| 72 | \vartriangle, \triangledown | $`\vartriangle, \triangledown` | -+-----+--------------------------------------------+------------------------------------------------+ -| 73 | \blacktriangle, \blacktriangledown, \ | $`\blacktriangle, \blacktriangledown, | -| | \blacktriangleleft, \blacktriangleright | \blacktriangleleft, \blacktriangleright` | -+-----+--------------------------------------------+------------------------------------------------+ -| **Logic** | -+-----+--------------------------------------------+------------------------------------------------+ -| 74 | \forall, \exists, \nexists | $`\forall, \exists, \nexists` | -+-----+--------------------------------------------+------------------------------------------------+ -| 75 | \therefore, \because, \And | $`\therefore, \because, \And` | -+-----+--------------------------------------------+------------------------------------------------+ -| 76 | \lor \vee, \curlyvee, \bigvee | $`\lor \vee, \curlyvee, \bigvee` | -+-----+--------------------------------------------+------------------------------------------------+ -| 77 | \land \wedge, \curlywedge, \bigwedge | $`\land \wedge, \curlywedge, \bigwedge` | -+-----+--------------------------------------------+------------------------------------------------+ -| 78 | \bar{q}, \bar{abc}, \overline{q}, \ | $`\bar{q}, \bar{abc}, \overline{q}, | -| | \overline{abc},\\\\ \ | \overline{abc}, \\ | -| | \lnot \neg, \not\operatorname{R},\bot,\top | \lnot \neg, \not\operatorname{R},\bot,\top` | -+-----+--------------------------------------------+------------------------------------------------+ -| 79 | \vdash \dashv, \vDash, \Vdash, \models | $`\vdash \dashv, \vDash, \Vdash, \models` | -+-----+--------------------------------------------+------------------------------------------------+ -| 80 | \Vvdash \nvdash \nVdash \nvDash \nVDash | $`\Vvdash \nvdash \nVdash \nvDash \nVDash` | -+-----+--------------------------------------------+------------------------------------------------+ -| 81 | \ulcorner \urcorner \llcorner \lrcorner | $`\ulcorner \urcorner \llcorner \lrcorner` | -+-----+--------------------------------------------+------------------------------------------------+ -| **Arrows** | -+-----+--------------------------------------------+------------------------------------------------+ -| 82 | \Rrightarrow, \Lleftarrow | $`\Rrightarrow, \Lleftarrow` | -+-----+--------------------------------------------+------------------------------------------------+ -| 83 | \Rightarrow, \nRightarrow, \ | $`\Rightarrow, \nRightarrow, | -| | \Longrightarrow, \implies | \Longrightarrow, \implies` | -+-----+--------------------------------------------+------------------------------------------------+ -| 84 | \Leftarrow, \nLeftarrow, \Longleftarrow | $`\Leftarrow, \nLeftarrow, \Longleftarrow` | -+-----+--------------------------------------------+------------------------------------------------+ -| 85 | \Leftrightarrow, \nLeftrightarrow, \ | $`\Leftrightarrow, \nLeftrightarrow, | -| | \Longleftrightarrow, \iff | \Longleftrightarrow, \iff` | -+-----+--------------------------------------------+------------------------------------------------+ -| 86 | \Uparrow, \Downarrow, \Updownarrow | $`\Uparrow, \Downarrow, \Updownarrow` | -+-----+--------------------------------------------+------------------------------------------------+ -| 87 | \rightarrow \to, \nrightarrow, \ | $`\rightarrow \to, \nrightarrow, | -| | \longrightarrow | \longrightarrow` | -+-----+--------------------------------------------+------------------------------------------------+ -| 88 | \leftarrow \gets, \nleftarrow, \ | $`\leftarrow \gets, \nleftarrow, | -| | \longleftarrow | \longleftarrow` | -+-----+--------------------------------------------+------------------------------------------------+ -| 89 | \leftrightarrow, \nleftrightarrow, \ | $`\leftrightarrow, \nleftrightarrow, | -| | \longleftrightarrow | \longleftrightarrow` | -+-----+--------------------------------------------+------------------------------------------------+ -| 90 | \uparrow, \downarrow, \updownarrow | $`\uparrow, \downarrow, \updownarrow` | -+-----+--------------------------------------------+------------------------------------------------+ -| 91 | \nearrow, \swarrow, \nwarrow, \searrow | $`\nearrow, \swarrow, \nwarrow, \searrow` | -+-----+--------------------------------------------+------------------------------------------------+ -| 92 | \mapsto, \longmapsto | $`\mapsto, \longmapsto` | -+-----+--------------------------------------------+------------------------------------------------+ -| 93 | \rightharpoonup \rightharpoondown \ | $`\rightharpoonup \rightharpoondown | -| | \leftharpoonup \leftharpoondown \ | \leftharpoonup \leftharpoondown | -| | \upharpoonleft \upharpoonright \ | \upharpoonleft \upharpoonright | -| | \downharpoonleft \downharpoonright \ | \downharpoonleft \downharpoonright | -| | \rightleftharpoons \leftrightharpoons | \rightleftharpoons \leftrightharpoons` | -+-----+--------------------------------------------+------------------------------------------------+ -| 94 | \curvearrowleft \circlearrowleft \Lsh \ | $`\curvearrowleft \circlearrowleft \Lsh | -| | \upuparrows \rightrightarrows \ | \upuparrows \rightrightarrows | -| | \rightleftarrows \rightarrowtail \ | \rightleftarrows \rightarrowtail | -| | \looparrowright | \looparrowright` | -+-----+--------------------------------------------+------------------------------------------------+ -| 95 | \curvearrowright \circlearrowright \Rsh \ | $`\curvearrowright \circlearrowright \Rsh | -| | \downdownarrows \leftleftarrows \ | \downdownarrows \leftleftarrows | -| | \leftrightarrows \leftarrowtail \ | \leftrightarrows \leftarrowtail | -| | \looparrowleft | \looparrowleft` | -+-----+--------------------------------------------+------------------------------------------------+ -| 96 | \hookrightarrow \hookleftarrow \multimap \ | $`\hookrightarrow \hookleftarrow \multimap | -| | \leftrightsquigarrow \rightsquigarrow \ | \leftrightsquigarrow \rightsquigarrow | -| | \twoheadrightarrow \twoheadleftarrow | \twoheadrightarrow \twoheadleftarrow` | -+-----+--------------------------------------------+------------------------------------------------+ -| **Special** | -+-----+--------------------------------------------+------------------------------------------------+ -| 97 | \amalg \P \S \%\dagger\ddagger\ldots\cdots | $`\amalg \P \S \% \dagger\ddagger\ldots\cdots` | -+-----+--------------------------------------------+------------------------------------------------+ -| 98 | \smile \frown \wr \triangleleft \ | $`\smile \frown \wr \triangleleft | -| | \triangleright | \triangleright` | -+-----+--------------------------------------------+------------------------------------------------+ -| 99 | \diamondsuit, \heartsuit, \clubsuit, \ | $`\diamondsuit, \heartsuit, \clubsuit, | -| | \spadesuit, \Game, \flat, \natural, \sharp | \spadesuit, \Game, \flat, \natural, \sharp` | -+-----+--------------------------------------------+------------------------------------------------+ -| **Unsorted** | -+-----+--------------------------------------------+------------------------------------------------+ -| 100 | \diagup \diagdown \centerdot \ltimes \ | $`\diagup \diagdown \centerdot \ltimes | -| | \rtimes \leftthreetimes \rightthreetimes | \rtimes \leftthreetimes \rightthreetimes` | -+-----+--------------------------------------------+------------------------------------------------+ -| 101 | \eqcirc \circeq \triangleq \bumpeq\Bumpeq\ | $`\eqcirc \circeq \triangleq \bumpeq\Bumpeq | -| | \doteqdot \risingdotseq \fallingdotseq | \doteqdot \risingdotseq \fallingdotseq` | -+-----+--------------------------------------------+------------------------------------------------+ -| 102 | \intercal \barwedge \veebar \ | $`\intercal \barwedge \veebar | -| | \doublebarwedge \between \pitchfork | \doublebarwedge \between \pitchfork` | -+-----+--------------------------------------------+------------------------------------------------+ -| 103 | \vartriangleleft \ntriangleleft \ | $`\vartriangleleft \ntriangleleft | -| | \vartriangleright \ntriangleright | \vartriangleright \ntriangleright` | -+-----+--------------------------------------------+------------------------------------------------+ -| 104 | \trianglelefteq \ntrianglelefteq \ | $`\trianglelefteq \ntrianglelefteq | -| | \trianglerighteq \ntrianglerighteq | \trianglerighteq \ntrianglerighteq` | -+-----+--------------------------------------------+------------------------------------------------+ - -
    - -+-----+----------------------------------------------+------------------------------------------------+ -| Larger expressions | -+-----+----------------------------------------------+------------------------------------------------+ -| | Source | Temml | -+=====+==============================================+================================================+ -| 105 | a^2, a^{x+3} | $`a^2, a^{x+3}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 106 | a\_2 | $`a_2` | -+-----+----------------------------------------------+------------------------------------------------+ -| 107 | 10^{30} a^{2+2} \ | $`10^{30} a^{2+2} \\ | -| | a\_{i,j} b\_{f'} | a_{i,j} b_{f'}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 108 | x\_2^3 \ | $`x_2^3 \\ | -| | {x\_2}^3 | {x_2}^3` | -+-----+----------------------------------------------+------------------------------------------------+ -| 109 | 10^{10^{8}} | $`10^{10^{8}}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 110 | \sideset{\_1^2}{\_3^4}\prod\_a^b \ | $$\sideset{_1^2}{_3^4}\prod_a^b$$ | -| | {}\_1^2\\!\Omega\_3^4 | $${}_1^2\!\Omega_3^4$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 111 | \overset{\alpha}{\omega} \ | $`\overset{\alpha}{\omega} \\ | -| | \underset{\alpha}{\omega} \ | \underset{\alpha}{\omega} \\ | -| | \overset{\alpha}{\underset{\gamma}{\omega}}\ | \overset{\alpha}{\underset{\gamma}{\omega}}\\ | -| | \stackrel{\alpha}{\omega} | \stackrel{\alpha}{\omega}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 112 | x', y'', f', f'' \ | $`x', y'', f', f'' \\ | -| | x^\prime, y^{\prime\prime} | x^\prime, y^{\prime\prime}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 113 | \dot{x}, \ddot{x} | $`\dot{x}, \ddot{x}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 114 | \hat a \\ \bar b \\ \vec c \ | $`\hat a \ \bar b \ \vec c \\ | -| | \overrightarrow{a b} \\ \overleftarrow{c d}\ | \overrightarrow{a b} \ \overleftarrow{c d}\\ | -| | \widehat{d e f} \ | \widehat{d e f} \\ | -| | \overline{g h i} \\ \underline{j k l} | \overline{g h i} \ \underline{j k l}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 115 | \overset{\frown} {AB} | $`\overset{\frown} {AB}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 116 | A \xleftarrow{n+\mu-1} B \ | $`A \xleftarrow{n+\mu-1} B | -| | \xrightarrow[T]{n\pm i-1} C | \xrightarrow[T]{n\pm i-1} C` | -+-----+----------------------------------------------+------------------------------------------------+ -| 117 | \overbrace{ 1+2+\cdots+100 }^{5050} | $`\overbrace{ 1+2+\cdots+100 }^{5050}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 118 | \underbrace{ a+b+\cdots+z }\_{26} | $`\underbrace{ a+b+\cdots+z }_{26}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 119 | \sum\_{k=1}^N k^2 | $$\sum_{k=1}^N k^2$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 120 | \textstyle \sum\_{k=1}^N k^2 | $$\textstyle \sum_{k=1}^N k^2$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 121 | \frac{\sum\_{k=1}^N k^2}{a} | $$\frac{\sum_{k=1}^N k^2}{a}$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 122 | \frac{\sum\limits^{^N}\_{k=1} k^2}{a} | $$\frac{\sum\limits^{^N}_{k=1} k^2}{a}$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 123 | \prod\_{i=1}^N x\_i | $$\prod_{i=1}^N x_i$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 124 | \textstyle \prod\_{i=1}^N x\_i | $$\textstyle \prod_{i=1}^N x_i$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 125 | \coprod\_{i=1}^N x\_i | $$\coprod_{i=1}^N x_i$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 126 | \textstyle \coprod\_{i=1}^N x\_i | $$\textstyle \coprod_{i=1}^N x_i$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 127 | \lim\_{n \to \infty}x\_n | $$\lim_{n \to \infty}x_n$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 128 | \textstyle \lim\_{n \to \infty}x\_n | $$\textstyle \lim_{n \to \infty}x_n$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 129 | \int\limits\_{1}^{3}\frac{e^3/x}{x^2}\\, dx | $$\int\limits_{1}^{3}\frac{e^3/x}{x^2}\, dx$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 130 | \int\_{1}^{3}\frac{e^3/x}{x^2}\\, dx | $$\int_{1}^{3}\frac{e^3/x}{x^2}\, dx$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 131 | \textstyle \int\limits\_{-N}^{N} e^x dx | $$\textstyle \int\limits_{-N}^{N} e^x dx$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 132 | \textstyle \int\_{-N}^{N} e^x dx | $$\textstyle \int_{-N}^{N} e^x dx$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 133 | \iint\limits\_D dx\\,dy | $$\iint\limits_D dx\,dy$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 134 | \iiint\limits\_E dx\\,dy\\,dz | $$\iiint\limits_E dx\,dy\,dz$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 135 | \iiiint\limits\_F dx\\,dy\\,dz\\,dt | $$\iiiint\limits_F dx\,dy\,dz\,dt$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 136 | \int\_{(x,y)\in C} x^3\\, dx + 4y^2\\, dy | $$\int_{(x,y)\in C} x^3\, dx + 4y^2\, dy$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 137 | \oint\_{(x,y)\in C} x^3\\, dx + 4y^2\\, dy | $$\oint_{(x,y)\in C} x^3\, dx + 4y^2\, dy$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 138 | \bigcap\_{i=1}^n E\_i | $$\bigcap_{i=1}^n E_i$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 139 | \bigcup\_{i=1}^n E\_i | $$\bigcup_{i=1}^n E_i$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| **Fractions, matrices, multiline** | -+-----+----------------------------------------------+------------------------------------------------+ -| 140 | \frac{2}{4}=0.5 or {2 \over 4}=0.5 | $`\frac{2}{4}=0.5` or $`{2 \over 4}=0.5` | -+-----+----------------------------------------------+------------------------------------------------+ -| 141 | \tfrac{2}{4} = 0.5 | $$\tfrac{2}{4} = 0.5$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 142 | \dfrac{2}{4} = 0.5 \qquad \dfrac{2}{c + \ | $`\dfrac{2}{4} = 0.5 \qquad \dfrac{2}{c + | -| | \dfrac{2}{d + \dfrac{2}{4}}} = a | \dfrac{2}{d + \dfrac{2}{4}}} = a` | -+-----+----------------------------------------------+------------------------------------------------+ -| 143 | \cfrac{2}{c +\cfrac{2}{d +\cfrac{2}{4}}} = a | $$\cfrac{2}{c+\cfrac{2}{d+\cfrac{2}{4}}} = a$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 144 | \cfrac{x}{1 + \cfrac{\cancel{y}}\ | $`\cfrac{x}{1 + \cfrac{\cancel{y}} | -| | {\cancel{y}}} = \cfrac{x}{2} | {\cancel{y}}} = \cfrac{x}{2}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 145 | \binom{n}{k} | $`\binom{n}{k}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 146 | \tbinom{n}{k} | $$\tbinom{n}{k}$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 147 | \dbinom{n}{k} | $`\dbinom{n}{k}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 148 | \begin{matrix} \ | $`\begin{matrix} | -| | x & y \\\\ \ | x & y \\ | -| | z & v \ | z & v | -| | \end{matrix} | \end{matrix}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 149 | \begin{vmatrix} \ | $`\begin{vmatrix} | -| | x & y \\\\ \ | x & y \\ | -| | z & v \ | z & v | -| | \end{vmatrix} | \end{vmatrix}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 150 | \begin{Vmatrix} \ | $`\begin{Vmatrix} | -| | x & y \\\\ \ | x & y \\ | -| | z & v \ | z & v | -| | \end{Vmatrix} | \end{Vmatrix}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 151 | \begin{bmatrix} \ | $`\begin{bmatrix} | -| | 0 & \cdots & 0 \\\\ \ | 0 & \cdots & 0 \\ | -| | \vdots & \ddots & \vdots \\\\ \ | \vdots & \ddots & \vdots \\ | -| | 0 & \cdots & 0 \ | 0 & \cdots & 0 | -| | \end{bmatrix} | \end{bmatrix}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 152 | \begin{Bmatrix} \ | $`\begin{Bmatrix} | -| | x & y \\\\ \ | x & y \\ | -| | z & v \ | z & v | -| | \end{Bmatrix} | \end{Bmatrix}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 153 | \begin{pmatrix} \ | $`\begin{pmatrix} | -| | x & y \\\\ \ | x & y \\ | -| | z & v \ | z & v | -| | \end{pmatrix} | \end{pmatrix}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 154 | \bigl( \begin{smallmatrix} \ | $`\bigl( \begin{smallmatrix} | -| | a&b\\\\ c&d \ | a&b\\ c&d | -| | \end{smallmatrix} \bigr) | \end{smallmatrix} \bigr)` | -+-----+----------------------------------------------+------------------------------------------------+ -| 155 | f(n) = \begin{cases} \ | $`f(n) = \begin{cases} | -| | n/2, & \text{if }n\text{ is even} \\\\ \ | n/2, & \text{if }n\text{ is even} \\ | -| | 3n+1, & \text{if }n\text{ is odd} | 3n+1, & \text{if }n\text{ is odd} | -| | \end{cases} | \end{cases}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 156 | \begin{cases} \ | $`\begin{cases} | -| | 3x + 5y + z \\\\ \ | 3x + 5y + z \\ | -| | 7x - 2y + 4z \\\\ \ | 7x - 2y + 4z \\ | -| | -6x + 3y + 2z | -6x + 3y + 2z | -| | \end{cases} | \end{cases}` | -+-----+----------------------------------------------+------------------------------------------------+ -| 157 | \begin{align} \ | $$\begin{align} | -| | f(x) & = (a+b)^2 \\\\ \ | f(x) & = (a+b)^2 \\ | -| | & = a^2+2ab+b^2 \\\\ \ | & = a^2+2ab+b^2 \\ | -| | \end{align} | \end{align}$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 158 | \begin{alignat}{2} \ | $$\begin{alignat}{2} | -| | f(x) & = (a+b)^2 \\\\ \ | f(x) & = (a+b)^2 \\ | -| | & = a^2+2ab+b^2 \\\\ \ | & = a^2+2ab+b^2 \\ | -| | \end{alignat} | \end{alignat}$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 159 | \begin{align} \ | $$\begin{align} | -| | f(a,b) & = (a+b)^2 && = (a+b)(a+b) \\\\ \ | f(a,b) & = (a+b)^2 && = (a+b)(a+b) \\ | -| | & = a^2+ab+ba+b^2 && = a^2+2ab+b^2 \\\\ \ | & = a^2+ab+ba+b^2 && = a^2+2ab+b^2 \\ | -| | \end{align} | \end{align}$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 159 | \begin{alignat}{3} \ | $$\begin{alignat}{3} | -| | f(a,b) & = (a+b)^2 && = (a+b)(a+b) \\\\ \ | f(a,b) & = (a+b)^2 && = (a+b)(a+b) \\ | -| | & = a^2+ab+ba+b^2 && = a^2+2ab+b^2 \\\\ \ | & = a^2+ab+ba+b^2 && = a^2+2ab+b^2 \\ | -| | \end{alignat} | \end{alignat}$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 160 | \begin{array}{lcl} \ | $$\begin{array}{lcl} | -| | z & = & a \\\\ \ | z & = & a \\ | -| | f(x,y,z) & = & x + y + z | f(x,y,z) & = & x + y + z | -| | \end{array} | \end{array}$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 161 | \begin{array}{lcr} \ | $$\begin{array}{lcr} | -| | z & = & a \\\\ \ | z & = & a \\ | -| | f(x,y,z) & = & x + y + z | f(x,y,z) & = & x + y + z | -| | \end{array} | \end{array}$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 162 | \begin{alignat}{4} \ | $$\begin{alignat}{4} | -| | F:\\; && C(X) && \\;\to\\; & C(X) \\\\ \ | F:\; && C(X) && \;\to\; & C(X) \\ | -| | && g && \\;\mapsto\\; & g^2 | && g && \;\mapsto\; & g^2 | -| | \end{alignat} | \end{alignat}$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 163 | \begin{alignat}{4} \ | $$\begin{alignat}{4} | -| | F:\\; && C(X) && \\;\to\\; && C(X) \\\\ \ | F:\; && C(X) && \;\to\; && C(X) \\ | -| | && g && \\;\mapsto\\; && g^2 | && g && \;\mapsto\; && g^2 | -| | \end{alignat} | \end{alignat}$$ | -+-----+----------------------------------------------+------------------------------------------------+ -| 164 | `f(x) \,\!` `\sum_{n=0}^\infty a_n x^n` \ | $`f(x) \,\!` $` = \sum_{n=0}^\infty a_n x^n` | -| | `= a_0+a_1x+a_2x^2+\cdots` | $`= a_0+a_1x+a_2x^2+\cdots` | -+-----+----------------------------------------------+------------------------------------------------+ -| 165 | \begin{array}{|c|c|c|} \ | $`\begin{array}{|c|c|c|} | -| | a & b & S \\\\ \ | a & b & S \\ | -| | \hline \ | \hline | -| | 0 & 0 & 1 \\\\ \ | 0 & 0 & 1 \\ | -| | 0 & 1 & 1 \\\\ \ | 0 & 1 & 1 \\ | -| | 1 & 0 & 1 \\\\ \ | 1 & 0 & 1 \\ | -| | 1 & 1 & 0 \\\\ \ | 1 & 1 & 0 \\ | -| | \end{array} | \end{array}` | -+-----+----------------------------------------------+------------------------------------------------+ -{colWidths="null null 400"} - -+-----+-----------------------------------------------+--------------------------------------------------+ -| Delimiters | -+=====+===============================================+==================================================+ -| 166 | ( \frac{1}{2} )^n | $`( \frac{1}{2} )^n` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 167 | \left ( \frac{1}{2} \right )^n | $`\left ( \frac{1}{2} \right )^n` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 168 | \left ( \frac{a}{b} \right ) | $`\left ( \frac{a}{b} \right )` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 169 | \left [ \frac{a}{b} \right ] \quad \ | $`\left [ \frac{a}{b} \right ] \quad | -| | \left \lbrack \frac{a}{b} \right \rbrack | \left \lbrack \frac{a}{b} \right \rbrack` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 170 | \left \{ \frac{a}{b} \right \} \quad \ | $`\left \{ \frac{a}{b} \right \} \quad | -| | \left \lbrace \frac{a}{b} \right \rbrace | \left \lbrace \frac{a}{b} \right \rbrace` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 171 | \left \langle \frac{a}{b} \right \rangle | $`\left \langle \frac{a}{b} \right \rangle` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 172 | \left | \frac{a}{b} \right \vert \quad \ | $`\left | \frac{a}{b} \right \vert \quad | -| | \left \Vert \frac{c}{d} \right \| | \left \Vert \frac{c}{d} \right \|` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 173 | \left \lfloor \frac{a}{b} \right \rfloor \ | $`\left \lfloor \frac{a}{b} \right \rfloor | -| | \quad \left \lceil \frac{c}{d} \right \rceil | \quad \left \lceil \frac{c}{d} \right \rceil` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 174 | \left / \frac{a}{b} \right \backslash | $`\left / \frac{a}{b} \right \backslash` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 175 | \left\uparrow\frac{a}{b}\right\downarrow\\; \ | $`\left\uparrow\frac{a}{b}\right\downarrow\; | -| | \left\Uparrow\frac{a}{b}\right\Downarrow\\; \ | \left\Uparrow\frac{a}{b}\right\Downarrow\; | -| | \left \updownarrow \frac{a}{b} \right \ | \left \updownarrow \frac{a}{b} \right | -| | \Updownarrow | \Updownarrow` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 176 | \left [ 0,1 \right ) \ | $`\left [ 0,1 \right ) | -| | \left \langle \psi \right | | \left \langle \psi \right |` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 177 | \left . \frac{A}{B} \right \} \to X | $`\left . \frac{A}{B} \right \} \to X` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 178 | ( \bigl( \Bigl( \biggl( \Biggl( \dots \ | $`( \bigl( \Bigl( \biggl( \Biggl( \dots | -| | \Biggr] \biggr] \Bigr] \bigr] ] | \Biggr] \biggr] \Bigr] \bigr] ]` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 179 | \{ \bigl\{ \Bigl\{ \biggl\{ \Biggl\{ \dots \ | $`\{ \bigl\{ \Bigl\{ \biggl\{ \Biggl\{ \dots | -| | \Biggr\rangle \biggr\rangle \Bigr\rangle \ | \Biggr\rangle \biggr\rangle \Bigr\rangle | -| | \bigr\rangle \rangle | \bigr\rangle \rangle` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 180 | \| \big\| \Big\| \bigg\| \Bigg\| \dots \ | $`\| \big\| \Big\| \bigg\| \Bigg\| \dots | -| | \Bigg| \bigg| \Big| \big| | | \Bigg| \bigg| \Big| \big| |` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 181 | \lfloor \bigl\lfloor \Bigl\lfloor \ | $`\lfloor \bigl\lfloor \Bigl\lfloor | -| | \biggl\lfloor \Biggl\lfloor \dots \ | \biggl\lfloor \Biggl\lfloor \dots | -| | \Biggr\rceil \biggr\rceil \Bigr\rceil \ | \Biggr\rceil \biggr\rceil \Bigr\rceil | -| | \bigr\rceil \ceil | \bigr\rceil \rceil` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 182 | \uparrow \big\uparrow \Big\uparrow \ | $`\uparrow \big\uparrow \Big\uparrow | -| | \bigg\uparrow \Bigg\uparrow \dots \ | \bigg\uparrow \Bigg\uparrow \dots | -| | \Bigg\Downarrow \bigg\Downarrow \ | \Bigg\Downarrow \bigg\Downarrow | -| | \Big\Downarrow \big\Downarrow \Downarrow | \Big\Downarrow \big\Downarrow \Downarrow` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 183 | \updownarrow\big\updownarrow\Big\updownarrow\ | $`\updownarrow\big\updownarrow\Big\updownarrow | -| | \bigg\updownarrow \Bigg\updownarrow \dots \ | \bigg\updownarrow \Bigg\updownarrow \dots | -| | \Bigg\Updownarrow \bigg\Updownarrow \Big \ | \Bigg\Updownarrow \bigg\Updownarrow \Big | -| | \Updownarrow \big\Updownarrow \Updownarrow | \Updownarrow \big\Updownarrow \Updownarrow` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 184 | / \big/ \Big/ \bigg/ \Bigg/ \dots \ | $`/ \big/ \Big/ \bigg/ \Bigg/ \dots | -| | \Bigg\backslash \bigg\backslash \Big \ | \Bigg\backslash \bigg\backslash \Big | -| | \backslash \big\backslash \backslash | \backslash \big\backslash \backslash` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Greek Alphabet** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 185 | \Alpha \Beta \Gamma \Delta \Epsilon \Zeta \ | $`\Alpha \Beta \Gamma \Delta \Epsilon \Zeta | -| | \Eta \Theta | \Eta \Theta` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 186 | \Iota \Kappa \Lambda \Mu \Nu \Xi \Omicron \Pi | $`\Iota \Kappa \Lambda \Mu \Nu \Xi \Omicron \Pi` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 187 | \Rho \Sigma \Tau \Upsilon \Phi \Chi \Psi \ | $`\Rho \Sigma \Tau \Upsilon \Phi \Chi \Psi | -| | \Omega | \Omega` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 188 | \alpha \beta \gamma \delta \epsilon \zeta \ | $`\alpha \beta \gamma \delta \epsilon \zeta | -| | \eta \theta | \eta \theta` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 189 | \iota \kappa \lambda \mu \nu \xi \omicron \pi | $`\iota \kappa \lambda \mu \nu \xi \omicron \pi` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 190 | \rho \sigma \tau \upsilon \phi \chi \psi \ | $`\rho \sigma \tau \upsilon \phi \chi \psi | -| | \omega | \omega` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 191 | \varGamma \varDelta \varTheta \varLambda \ | $`\varGamma \varDelta \varTheta \varLambda | -| | \varXi \varPi \varSigma \varPhi \varUpsilon \ | \varXi \varPi \varSigma \varPhi \varUpsilon | -| | \varOmega | \varOmega` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 192 | \varepsilon \digamma \varkappa \varpi \ | $`\varepsilon \digamma \varkappa \varpi | -| | \varrho \varsigma \vartheta \varphi | \varrho \varsigma \vartheta \varphi` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Hebrew symbols** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 193 | \aleph \beth \gimel \daleth | $`\aleph \beth \gimel \daleth` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Blackboard bold** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 194 | \mathbb{ABCDEFGHI} \ | $`\mathbb{ABCDEFGHI} \\ | -| | \mathbb{JKLMNOPQR} \ | \mathbb{JKLMNOPQR} \\ | -| | \mathbb{STUVWXYZ} | \mathbb{STUVWXYZ}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Boldface** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 195 | \mathbf{ABCDEFGHI} \ | $`\mathbf{ABCDEFGHI} \\ | -| | \mathbf{JKLMNOPQR} \ | \mathbf{JKLMNOPQR} \\ | -| | \mathbf{STUVWXYZ} \ | \mathbf{STUVWXYZ} \\ | -| | \mathbf{abcdefghijklm} \ | \mathbf{abcdefghijklm} \\ | -| | \mathbf{nopqrstuvwxyz} \ | \mathbf{nopqrstuvwxyz} \\ | -| | \mathbf{0123456789} | \mathbf{0123456789}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Boldface Greek** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 196 | \boldsymbol{\Alpha \Beta \Gamma \Delta \ | $`\boldsymbol{\Alpha \Beta \Gamma \Delta | -| | \Epsilon \Zeta \Eta \Theta} | \Epsilon \Zeta \Eta \Theta}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 197 | \boldsymbol{\Iota \Kappa \Lambda \Mu \Nu \Xi\ | $`\boldsymbol{\Iota \Kappa \Lambda \Mu \Nu \Xi | -| | \Omicron \Pi} | \Omicron \Pi}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 198 | \boldsymbol{\Rho \Sigma \Tau \Upsilon \Phi \ | $`\boldsymbol{\Rho \Sigma \Tau \Upsilon \Phi | -| | \Chi \Psi \Omega} | \Chi \Psi \Omega}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 199 | \boldsymbol{\alpha \beta \gamma \delta \ | $`\boldsymbol{\alpha \beta \gamma \delta | -| | \epsilon \zeta \eta \theta} | \epsilon \zeta \eta \theta}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 200 | \boldsymbol{\iota \kappa \lambda \mu \nu \xi\ | $`\boldsymbol{\iota \kappa \lambda \mu \nu \xi | -| | \omicron \pi} | \omicron \pi}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 201 | \boldsymbol{\rho \sigma \tau \upsilon \phi \ | $`\boldsymbol{\rho \sigma \tau \upsilon \phi | -| | \chi \psi \omega} | \chi \psi \omega}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 202 | \boldsymbol{\varepsilon\digamma\varkappa\ | $`\boldsymbol{\varepsilon\digamma\varkappa | -| | \varpi} | \varpi}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 203 | \boldsymbol{\varrho\varsigma\vartheta\varphi} | $`\boldsymbol{\varrho\varsigma\vartheta\varphi}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Italics** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 204 | \mathit{0123456789} | $`\mathit{0123456789}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Greek Italics** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 205 | \mathit{\Alpha \Beta \Gamma \Delta \Epsilon \ | $`\mathit{\Alpha \Beta \Gamma \Delta \Epsilon | -| | \Zeta \Eta \Theta} | \Zeta \Eta \Theta}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 206 | \mathit{\Iota \Kappa \Lambda \Mu \Nu \Xi \ | $`\mathit{\Iota \Kappa \Lambda \Mu \Nu \Xi | -| | \Omicron \Pi} | \Omicron \Pi}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 207 | \mathit{\Rho \Sigma \Tau \Upsilon \Phi \Chi \ | $`\mathit{\Rho \Sigma \Tau \Upsilon \Phi \Chi | -| | \Psi \Omega} | \Psi \Omega}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Greek uppercase boldface italics** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 208 | \boldsymbol{\varGamma \varDelta \varTheta \ | $`\boldsymbol{\varGamma \varDelta \varTheta | -| | \varLambda} | \varLambda}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 209 | \boldsymbol{\varXi \varPi \varSigma \ | $`\boldsymbol{\varXi \varPi \varSigma | -| | \varUpsilon \varOmega} | \varUpsilon \varOmega}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Roman typeface** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 210 | \mathrm{ABCDEFGHI} \ | $`\mathrm{ABCDEFGHI} \\ | -| | \mathrm{JKLMNOPQR} \ | \mathrm{JKLMNOPQR} \\ | -| | \mathrm{STUVWXYZ} \ | \mathrm{STUVWXYZ} \\ | -| | \mathrm{abcdefghijklm} \ | \mathrm{abcdefghijklm} \\ | -| | \mathrm{nopqrstuvwxyz} \ | \mathrm{nopqrstuvwxyz} \\ | -| | \mathrm{0123456789} | \mathrm{0123456789}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Sans serif** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 211 | \mathsf{ABCDEFGHI} \ | $`\mathsf{ABCDEFGHI} \\ | -| | \mathsf{JKLMNOPQR} \ | \mathsf{JKLMNOPQR} \\ | -| | \mathsf{STUVWXYZ} \ | \mathsf{STUVWXYZ} \\ | -| | \mathsf{abcdefghijklm} \ | \mathsf{abcdefghijklm} \\ | -| | \mathsf{nopqrstuvwxyz} \ | \mathsf{nopqrstuvwxyz} \\ | -| | \mathsf{0123456789} | \mathsf{0123456789}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Sans serif Greek** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 212 | \mathsf{\Alpha \Beta \Gamma \Delta \Epsilon \ | $`\mathsf{\Alpha \Beta \Gamma \Delta \Epsilon | -| | \Zeta \Eta \Theta} | \Zeta \Eta \Theta}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 213 | \mathsf{\Iota \Kappa \Lambda \Mu \Nu \Xi \ | $`\mathsf{\Iota \Kappa \Lambda \Mu \Nu \Xi | -| | \Omicron \Pi} | \Omicron \Pi}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 214 | \mathsf{\Rho \Sigma \Tau \Upsilon \Phi \Chi \ | $`\mathsf{\Rho \Sigma \Tau \Upsilon \Phi \Chi | -| | \Psi \Omega} | \Psi \Omega}` | -+-----+-----------------------------------------------+--------------------------------------------------+ - -Unicode has special code points for bold Greek sans-serif, but no code points for\ -regular-weight Greek sans-serif. Since Chromium is not going to support the `math-variant`\ -attribute, these bold Greek sans-serif glyphs are the best approximation I can make to\ -sans-serif Greek. - -
    - -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Calligraphy** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 215 | \mathcal{ABCDEFGHI} \ | $`\mathcal{ABCDEFGHI} \\ | -| | \mathcal{JKLMNOPQR} \ | \mathcal{JKLMNOPQR} \\ | -| | \mathcal{STUVWXYZ} \ | \mathcal{STUVWXYZ} \\ | -| | \mathcal{abcdefghi} \ | \mathcal{abcdefghi} \\ | -| | \mathcal{jklmnopqr} \ | \mathcal{jklmnopqr} \\ | -| | \mathcal{stuvwxyz} | \mathcal{stuvwxyz}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Fraktur** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 216 | \mathfrak{ABCDEFGHI} \ | $`\mathfrak{ABCDEFGHI} \\ | -| | \mathfrak{JKLMNOPQR} \ | \mathfrak{JKLMNOPQR} \\ | -| | \mathfrak{STUVWXYZ} \ | \mathfrak{STUVWXYZ} \\ | -| | \mathfrak{abcdefghi} \ | \mathfrak{abcdefghi} \\ | -| | \mathfrak{jklmnopqr} \ | \mathfrak{jklmnopqr} \\ | -| | \mathfrak{stuvwxyz} | \mathfrak{stuvwxyz}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Scriptstyle text** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 217 | {\scriptstyle\text{abcdefghijklm}} | $`{\scriptstyle\text{abcdefghijklm}}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Mixed text faces** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 218 | x y z | $`x y z` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 219 | \text{x y z} | $`\text{x y z}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 220 | \text{if} n \text{is even} | $`\text{if} n \text{is even}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 221 | \text{if }n\text{ is even} | $`\text{if }n\text{ is even}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 222 | \text{if}~n\ \text{is even} | $`\text{if}~n\ \text{is even}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Color** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 223 | {\color{Blue}x^2}+{\color{Orange}2x}-\ | $`{\color{Blue}x^2}+{\color{Orange}2x}- | -| | {\color{LimeGreen}1} | {\color{LimeGreen}1}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 224 | x_{1,2}=\frac{{\color{Blue}-b}\pm\ | $`x_{1,2}=\frac{{\color{Blue}-b}\pm | -| | \sqrt{\color{Red}b^2-4ac}}{\color{Green}2a } | \sqrt{\color{Red}b^2-4ac}}{\color{Green}2a }` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 225 | {\color{Blue}x^2}+{\color{Orange}2x}-\ | $`{\color{Blue}x^2}+{\color{Orange}2x}- | -| | {\color{LimeGreen}1} | {\color{LimeGreen}1}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 226 | \color{Blue}x^2\color{Black}+\color{Orange}\ | $`\color{Blue}x^2\color{Black}+\color{Orange} | -| | 2x\color{Black}-\color{LimeGreen}1 | 2x\color{Black}-\color{LimeGreen}1` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 227 | \color{Blue}{x^2}+\color{Orange}{2x}-\ | $`\color{Blue}{x^2}+\color{Orange}{2x}- | -| | \color{LimeGreen}{1} | \color{LimeGreen}{1}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 228 | \definecolor{myorange}{rgb}{1,0.65,0.4}\ | $`\definecolor{myorange}{rgb}{1,0.65,0.4} | -| | \color{myorange}e^{i \pi}\color{Black} + 1= 0 | \color{myorange}e^{i \pi}\color{Black} + 1= 0` | -+-----+-----------------------------------------------+--------------------------------------------------+ - -For color names, see the [color section](https://temml.org/docs/en/supported.html#color) -in the Temml function support page. - -
    - -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Spacing** | -+=====+===============================================+==================================================+ -| 229 | a \qquad b \ | $`a \qquad b \\ | -| | a \quad b \ | a \quad b \\ | -| | a\ b \ | a\ b \\ | -| | a \text{ } b \ | a \text{ } b \\ | -| | a\\;b \ | a\;b \\ | -| | a\\,b \ | a\,b \\ | -| | ab \ | ab \\ | -| | a b \ | a b \\ | -| | \mathit{ab} \ | \mathit{ab} \\ | -| | a\\!b | a\!b` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 230 | | \uparrow \rangle | $`| \uparrow \rangle` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 231 | \left| \uparrow \right\rangle | $`\left| \uparrow \right\rangle` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 232 | | {\uparrow} \rangle | $`| {\uparrow} \rangle` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 233 | | \mathord\uparrow \rangle | $`| \mathord\uparrow \rangle` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Temml replacements for wiki workarounds** | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 234 | \oiint\limits\_D dx\\,dy \ | $$\oiint\limits_D dx\,dy$$ | -| | \oiiint\limits\_E dx\\,dy\\,dz | $$\oiiint\limits_E dx\,dy\,dz$$ | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 234 | \wideparen{AB} | $`\wideparen{AB}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 235 | \dddot{x} | $`\dddot{x}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 236 | \operatorname*{median}\_\ | $$\operatorname*{median}_{j\,\ne\,i} X_{i,j}$$ | -| | {j\\,\ne\\,i} X\_{i,j} | | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 237 | \sout{q} | $`\sout{q}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 238 | \mathrlap{\\,/}{=} | $`\mathrlap{\,/}{=}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 239 | \text{\textsf{textual description}} | $`\text{\textsf{textual description}}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 240 | α π | $`α π` | -+-----+-----------------------------------------------+--------------------------------------------------+ - -`mhchem` examples are displayed on their own [test page](https://temml.org/tests/mhchem-tests.html). - -
    - -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Examples of implemented TeX formulas** | -+=====+===============================================+==================================================+ -| 241 | ax^2 + bx + c = 0 | $`ax^2 + bx + c = 0` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 242 | x=\frac{-b\pm\sqrt{b^2-4ac}}{2a} | $`x=\frac{-b\pm\sqrt{b^2-4ac}}{2a}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 243 | \left( \frac{\left(3-x\right) \ | $`\left( \frac{\left(3-x\right) | -| | \times 2}{3-x} \right) | \times 2}{3-x} \right)` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 244 | S\_{\text{new}} = S\_{\text{old}} - \ | $$S_{\text{new}} = S_{\text{old}} - | -| | \frac{ \left( 5-T \right) ^2} {2} | \frac{ \left( 5-T \right) ^2} {2}$$ | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 245 | \int\_a^x \int\_a^s f(y)\\,dy\\,ds = \ | $$\int_a^x \int_a^s f(y)\,dy\,ds = | -| | \int\_a^x f(y)(x-y)\\,dy | \int_a^x f(y)(x-y)\,dy$$ | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 246 | \int\_e^{\infty}\frac {1}{t(\ln t)^2}dt = \ | $$\int_e^{\infty}\frac {1}{t(\ln t)^2}dt = | -| | \left. \frac{-1}{\ln t}\right\vert\_e^\infty\ | \left. \frac{-1}{\ln t} \right\vert_e^\infty | -| | = 1 | = 1$$ | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 247 | \det(\mathsf{A}-\lambda\mathsf{I}) = 0 | $`\det(\mathsf{A}-\lambda\mathsf{I}) = 0` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 248 | \sum\_{i=0}^{n-1} i | $$\sum_{i=0}^{n-1} i$$ | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 249 | \sum\_{m=1}^\infty\sum\_{n=1}^\infty \ | $$\sum_{m=1}^\infty\sum_{n=1}^\infty | -| | \frac{m^2 n}{3^m\left(m 3^n + n 3^m\right)} | \frac{m^2 n}{3^m\left(m 3^n + n 3^m\right)}$$ | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 250 | u'' + p(x)u' + q(x)u=f(x),\quad x>a | $`u'' + p(x)u' + q(x)u=f(x),\quad x>a` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 251 | |\bar{z}| = |z|, |(\bar{z})^n| = |z|^n, \ | $`|\bar{z}| = |z|, |(\bar{z})^n| = |z|^n, | -| | \arg(z^n) = n \arg(z) | \arg(z^n) = n \arg(z)` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 252 | \lim\_{z\to z\_0} f(z)=f(z\_0) | $$\lim_{z\to z_0} f(z)=f(z_0)$$ | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 253 | \phi_n(\kappa) = \ | $$\phi_n(\kappa) = | -| | \frac{1}{4\pi^2\kappa^2} \int\_0^\infty \ | \frac{1}{4\pi^2\kappa^2} \int_0^\infty | -| | \frac{\sin(\kappa R)}{\kappa R} \ | \frac{\sin(\kappa R)}{\kappa R} | -| | \frac{\partial}{\partial R} \ | \frac{\partial}{\partial R} | -| | \left [ R^2\frac{\partial D\_n(R)}\ | \left [ R^2\frac{\partial D_n(R)} | -| | {\partial R} \right ] \\,dR | {\partial R} \right ] \,dR$$ | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 254 | \phi\_n(\kappa) = 0.033C\_n^2\kappa^{-11/3},\ | $`\phi_n(\kappa) = 0.033C_n^2\kappa^{-11/3}, | -| | \quad\frac{1}{L\_0}\ll\kappa\ll\frac{1}{l\_0} | \quad\frac{1}{L_0}\ll\kappa\ll\frac{1}{l_0}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 255 | f(x) = \begin{cases} \ | $`f(x) = \begin{cases} | -| | 1 & -1 \le x < 0 \\\\ \ | 1 & -1 \le x < 0 \\ | -| | \frac{1}{2} & x = 0 \\\\ \ | \frac{1}{2} & x = 0 \\ | -| | 1 - x^2 & \text{otherwise} \ | 1 - x^2 & \text{otherwise} | -| | \end{cases} | \end{cases}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 256 | {}\_pF\_q(a\_1,\dots,a\_p;c\_1,\dots,c\_q;z)\ | $`{}_pF_q(a_1,\dots,a_p;c_1,\dots,c_q;z) | -| | = \sum\_{n=0}^\infty \ | = \sum_{n=0}^\infty | -| | \frac{(a_1)\_n\cdots(a_p)\_n}\ | \frac{(a_1)_n\cdots(a_p)_n} | -| | {(c\_1)\_n\cdots(c\_q)_n}\frac{z^n}{n!} | {(c_1)_n\cdots(c_q)_n}\frac{z^n}{n!}` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 258 | \frac{a}{b}\ \tfrac{a}{b} | $$\frac{a}{b}\ \tfrac{a}{b}$$ | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 259 | S=dD\sin\alpha | $`S=dD\sin\alpha` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 260 | V = \frac{1}{6} \pi h \left [ 3 \left \ | $`V = \frac{1}{6} \pi h \left [ 3 \left | -| | ( r_1^2 + r_2^2 \right ) + h^2 \right ] | ( r_1^2 + r_2^2 \right ) + h^2 \right ]` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 261 | \begin{align} \ | $$\begin{align} | -| | u & = \tfrac{1}{\sqrt{2}}(x+y) \qquad & \ | u & = \tfrac{1}{\sqrt{2}}(x+y) \qquad & | -| | x &= \tfrac{1}{\sqrt{2}}(u+v) \\\\[0.6ex] \ | x &= \tfrac{1}{\sqrt{2}}(u+v) \\[0.6ex] | -| | v & = \tfrac{1}{\sqrt{2}}(x-y) \qquad & \ | v & = \tfrac{1}{\sqrt{2}}(x-y) \qquad & | -| | y &= \tfrac{1}{\sqrt{2}}(u-v) \ | y &= \tfrac{1}{\sqrt{2}}(u-v) | -| | \end{align} | \end{align}$$ | -+-----+-----------------------------------------------+--------------------------------------------------+ - -That concludes the tests from Wikipedia. Now a few more tests. - -
    - -+-----+-----------------------------------------------+--------------------------------------------------+ -| **Linear Logic** | -+=====+===============================================+==================================================+ -| 262 | A \with B \parr C | $`A \with B \parr C` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 263 | a \coh \oc b \incoh \wn c \scoh d \sincoh e | $`a \coh \oc b \incoh \wn c \scoh d \sincoh e` | -+-----+-----------------------------------------------+--------------------------------------------------+ -| 264 | a \Perp \shpos b \multimapinv \shneg c | $`a \Perp \shpos b \multimapinv \shneg c` | -+-----+-----------------------------------------------+--------------------------------------------------+ - -+-----+----------------------------------------------+-------------------------------------------------+ -| **Nested font size** | -+=====+==============================================+=================================================+ -| 265 | \mathrm{f{\large f{\normalsize f{\tiny f}}}} | $`\mathrm{f{\large f{\normalsize f{\tiny f}}}}` | -+-----+----------------------------------------------+-------------------------------------------------+ - -
    - - diff --git a/utils/TeXZilla.js b/utils/TeXZilla.js deleted file mode 100644 index 84d96fa6..00000000 --- a/utils/TeXZilla.js +++ /dev/null @@ -1,4220 +0,0 @@ -/* THIS IS A GENERATED FILE. DO NOT EDIT THIS DIRECTLY. */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; -/* parser generated by jison 0.4.18 */ -/* - Returns a Parser object of the following structure: - - Parser: { - yy: {} - } - - Parser.prototype: { - yy: {}, - trace: function(), - symbols_: {associative list: name ==> number}, - terminals_: {associative list: number ==> name}, - productions_: [...], - performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$), - table: [...], - defaultActions: {...}, - parseError: function(str, hash), - parse: function(input), - - lexer: { - EOF: 1, - parseError: function(str, hash), - setInput: function(input), - input: function(), - unput: function(str), - more: function(), - less: function(n), - pastInput: function(), - upcomingInput: function(), - showPosition: function(), - test_match: function(regex_match_array, rule_index), - next: function(), - lex: function(), - begin: function(condition), - popState: function(), - _currentRules: function(), - topState: function(), - pushState: function(condition), - - options: { - ranges: boolean (optional: true ==> token location info will include a .range[] member) - flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match) - backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code) - }, - - performAction: function(yy, yy_, $avoiding_name_collisions, YY_START), - rules: [...], - conditions: {associative list: name ==> set}, - } - } - - - token location info (@$, _$, etc.): { - first_line: n, - last_line: n, - first_column: n, - last_column: n, - range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based) - } - - - the parseError function receives a 'hash' object with these members for lexer and parser errors: { - text: (matched text) - token: (the produced terminal token, if any) - line: (yylineno) - } - while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: { - loc: (yylloc) - expected: (string describing the set of expected tokens) - recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error) - } -*/ -var TeXZilla = (function(){ -var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,4],$V1=[1,6],$V2=[1,7],$V3=[1,8],$V4=[1,9],$V5=[68,195,198,200,202,204],$V6=[1,27],$V7=[1,124],$V8=[1,52],$V9=[1,48],$Va=[1,28],$Vb=[1,29],$Vc=[1,30],$Vd=[1,31],$Ve=[1,32],$Vf=[1,33],$Vg=[1,34],$Vh=[1,35],$Vi=[1,37],$Vj=[1,38],$Vk=[1,39],$Vl=[1,40],$Vm=[1,41],$Vn=[1,42],$Vo=[1,43],$Vp=[1,44],$Vq=[1,45],$Vr=[1,46],$Vs=[1,47],$Vt=[1,49],$Vu=[1,50],$Vv=[1,51],$Vw=[1,53],$Vx=[1,54],$Vy=[1,55],$Vz=[1,56],$VA=[1,57],$VB=[1,58],$VC=[1,59],$VD=[1,60],$VE=[1,61],$VF=[1,62],$VG=[1,63],$VH=[1,64],$VI=[1,65],$VJ=[1,66],$VK=[1,67],$VL=[1,68],$VM=[1,69],$VN=[1,70],$VO=[1,71],$VP=[1,72],$VQ=[1,73],$VR=[1,74],$VS=[1,75],$VT=[1,76],$VU=[1,77],$VV=[1,78],$VW=[1,79],$VX=[1,80],$VY=[1,81],$VZ=[1,82],$V_=[1,83],$V$=[1,84],$V01=[1,85],$V11=[1,86],$V21=[1,87],$V31=[1,88],$V41=[1,89],$V51=[1,90],$V61=[1,91],$V71=[1,92],$V81=[1,93],$V91=[1,94],$Va1=[1,95],$Vb1=[1,96],$Vc1=[1,97],$Vd1=[1,98],$Ve1=[1,99],$Vf1=[1,100],$Vg1=[1,101],$Vh1=[1,102],$Vi1=[1,103],$Vj1=[1,104],$Vk1=[1,105],$Vl1=[1,106],$Vm1=[1,107],$Vn1=[1,24],$Vo1=[1,108],$Vp1=[1,109],$Vq1=[1,110],$Vr1=[1,111],$Vs1=[1,112],$Vt1=[1,113],$Vu1=[1,114],$Vv1=[1,115],$Vw1=[1,116],$Vx1=[1,117],$Vy1=[1,118],$Vz1=[1,119],$VA1=[1,120],$VB1=[1,121],$VC1=[1,122],$VD1=[1,123],$VE1=[1,16],$VF1=[1,17],$VG1=[1,18],$VH1=[1,19],$VI1=[1,20],$VJ1=[1,21],$VK1=[1,22],$VL1=[6,10,53,64,65,66,144,146,148,150,152,154,156,158,160,162,164,189,192,199,201,203,205],$VM1=[8,49,50,51,56,57,58,59,60,61,62,63,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,139,141,142,145,147,149,151,153,155,157,159,161,163,165,166,173,174,179,180,181,182,183,184,185],$VN1=[1,134],$VO1=[6,8,10,49,50,51,53,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,139,141,142,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,173,174,189,192,199,201,203,205],$VP1=[1,137],$VQ1=[6,8,10,49,50,51,53,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,141,142,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,169,170,171,173,174,189,192,199,201,203,205],$VR1=[1,161],$VS1=[2,197],$VT1=[1,217],$VU1=[1,214],$VV1=[6,8,10,49,50,51,53,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,139,141,142,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,169,170,173,174,189,192,199,201,203,205],$VW1=[1,241],$VX1=[1,243],$VY1=[1,244],$VZ1=[1,259],$V_1=[4,8],$V$1=[1,275],$V02=[8,49,50,51,56,57,58,59,60,61,62,63,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,141,142,145,147,149,151,153,155,157,159,161,163,165,166],$V12=[1,286],$V22=[10,144,146,148,150,152,154,156,158,160,162,164,192],$V32=[1,288],$V42=[10,144,146,148,150,152,154,156,158,160,162,164,189,192],$V52=[164,189,192],$V62=[10,189,192],$V72=[1,343],$V82=[1,344],$V92=[1,352],$Va2=[1,353],$Vb2=[4,8,49,50,51,56,57,58,59,60,61,62,63,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,139,141,142,145,147,149,151,153,155,157,159,161,163,165,166],$Vc2=[10,21,23],$Vd2=[10,21,23,25,27],$Ve2=[1,399],$Vf2=[1,400],$Vg2=[1,401],$Vh2=[1,402],$Vi2=[1,403],$Vj2=[1,404],$Vk2=[1,405],$Vl2=[1,406],$Vm2=[10,19,21,23,25,27,29,31,33,35,37,39,41],$Vn2=[10,19,21,23,29,31,33,35,37,39,41]; -var parser = {trace: function trace () { }, -yy: {}, -symbols_: {"error":2,"textOptArg":3,"[":4,"TEXTOPTARG":5,"]":6,"textArg":7,"{":8,"TEXTARG":9,"}":10,"lengthOptArg":11,"lengthArg":12,"attrOptArg":13,"attrArg":14,"tokenContent":15,"arrayAlign":16,"columnAlign":17,"collayout":18,"COLLAYOUT":19,"colalign":20,"COLALIGN":21,"rowalign":22,"ROWALIGN":23,"rowspan":24,"ROWSPAN":25,"colspan":26,"COLSPAN":27,"align":28,"ALIGN":29,"eqrows":30,"EQROWS":31,"eqcols":32,"EQCOLS":33,"rowlines":34,"ROWLINES":35,"collines":36,"COLLINES":37,"frame":38,"FRAME":39,"padding":40,"PADDING":41,"cellopt":42,"celloptList":43,"rowopt":44,"arrayopt":45,"arrayoptList":46,"rowoptList":47,"left":48,"LEFT":49,"OPFS":50,".":51,"right":52,"RIGHT":53,"closedTerm":54,"styledExpression":55,"BIG":56,"BBIG":57,"BIGG":58,"BBIGG":59,"BIGL":60,"BBIGL":61,"BIGGL":62,"BBIGGL":63,"TEXATOP":64,"TEXOVER":65,"TEXCHOOSE":66,"NUM":67,"TEXT":68,"A":69,"AILL":70,"AIUL":71,"AILG":72,"AIUG":73,"F":74,"MI":75,"MN":76,"MO":77,"OP":78,"OPS":79,"OPAS":80,"MS":81,"MTEXT":82,"HIGH_SURROGATE":83,"LOW_SURROGATE":84,"BMP_CHARACTER":85,"OPERATORNAME":86,"MATHOP":87,"MATHBIN":88,"MATHREL":89,"FRAC":90,"ROOT":91,"SQRT":92,"UNDERSET":93,"OVERSET":94,"UNDEROVERSET":95,"XARROW":96,"MATHRLAP":97,"MATHLLAP":98,"MATHCLAP":99,"PHANTOM":100,"TFRAC":101,"BINOM":102,"TBINOM":103,"PMOD":104,"UNDERBRACE":105,"UNDERLINE":106,"OVERBRACE":107,"ACCENT":108,"ACCENTNS":109,"BOXED":110,"SLASH":111,"QUAD":112,"QQUAD":113,"NEGSPACE":114,"NEGMEDSPACE":115,"NEGTHICKSPACE":116,"THINSPACE":117,"MEDSPACE":118,"THICKSPACE":119,"SPACE":120,"MATHRAISEBOX":121,"MATHBB":122,"MATHBF":123,"MATHBIT":124,"MATHSCR":125,"MATHBSCR":126,"MATHSF":127,"MATHFRAK":128,"MATHIT":129,"MATHTT":130,"MATHRM":131,"HREF":132,"STATUSLINE":133,"TOOLTIP":134,"TOGGLE":135,"BTOGGLE":136,"closedTermList":137,"ETOGGLE":138,"TENSOR":139,"subsupList":140,"MULTI":141,"BMATRIX":142,"tableRowList":143,"EMATRIX":144,"BGATHERED":145,"EGATHERED":146,"BPMATRIX":147,"EPMATRIX":148,"BBMATRIX":149,"EBMATRIX":150,"BVMATRIX":151,"EVMATRIX":152,"BBBMATRIX":153,"EBBMATRIX":154,"BVVMATRIX":155,"EVVMATRIX":156,"BSMALLMATRIX":157,"ESMALLMATRIX":158,"BCASES":159,"ECASES":160,"BALIGNED":161,"EALIGNED":162,"BARRAY":163,"EARRAY":164,"SUBSTACK":165,"ARRAY":166,"ARRAYOPTS":167,"compoundTerm":168,"_":169,"^":170,"OPP":171,"opm":172,"OPM":173,"FM":174,"compoundTermList":175,"subsupTermScript":176,"subsupTerm":177,"textstyle":178,"DISPLAYSTYLE":179,"TEXTSTYLE":180,"TEXTSIZE":181,"SCRIPTSIZE":182,"SCRIPTSCRIPTSIZE":183,"COLOR":184,"BGCOLOR":185,"tableCell":186,"CELLOPTS":187,"tableCellList":188,"COLSEP":189,"tableRow":190,"ROWOPTS":191,"ROWSEP":192,"document":193,"documentItemList":194,"EOF":195,"documentItem":196,"mathItem":197,"STARTMATH0":198,"ENDMATH0":199,"STARTMATH1":200,"ENDMATH1":201,"STARTMATH2":202,"ENDMATH2":203,"STARTMATH3":204,"ENDMATH3":205,"$accept":0,"$end":1}, -terminals_: {2:"error",4:"[",5:"TEXTOPTARG",6:"]",8:"{",9:"TEXTARG",10:"}",19:"COLLAYOUT",21:"COLALIGN",23:"ROWALIGN",25:"ROWSPAN",27:"COLSPAN",29:"ALIGN",31:"EQROWS",33:"EQCOLS",35:"ROWLINES",37:"COLLINES",39:"FRAME",41:"PADDING",49:"LEFT",50:"OPFS",51:".",53:"RIGHT",56:"BIG",57:"BBIG",58:"BIGG",59:"BBIGG",60:"BIGL",61:"BBIGL",62:"BIGGL",63:"BBIGGL",64:"TEXATOP",65:"TEXOVER",66:"TEXCHOOSE",67:"NUM",68:"TEXT",69:"A",70:"AILL",71:"AIUL",72:"AILG",73:"AIUG",74:"F",75:"MI",76:"MN",77:"MO",78:"OP",79:"OPS",80:"OPAS",81:"MS",82:"MTEXT",83:"HIGH_SURROGATE",84:"LOW_SURROGATE",85:"BMP_CHARACTER",86:"OPERATORNAME",87:"MATHOP",88:"MATHBIN",89:"MATHREL",90:"FRAC",91:"ROOT",92:"SQRT",93:"UNDERSET",94:"OVERSET",95:"UNDEROVERSET",96:"XARROW",97:"MATHRLAP",98:"MATHLLAP",99:"MATHCLAP",100:"PHANTOM",101:"TFRAC",102:"BINOM",103:"TBINOM",104:"PMOD",105:"UNDERBRACE",106:"UNDERLINE",107:"OVERBRACE",108:"ACCENT",109:"ACCENTNS",110:"BOXED",111:"SLASH",112:"QUAD",113:"QQUAD",114:"NEGSPACE",115:"NEGMEDSPACE",116:"NEGTHICKSPACE",117:"THINSPACE",118:"MEDSPACE",119:"THICKSPACE",120:"SPACE",121:"MATHRAISEBOX",122:"MATHBB",123:"MATHBF",124:"MATHBIT",125:"MATHSCR",126:"MATHBSCR",127:"MATHSF",128:"MATHFRAK",129:"MATHIT",130:"MATHTT",131:"MATHRM",132:"HREF",133:"STATUSLINE",134:"TOOLTIP",135:"TOGGLE",136:"BTOGGLE",138:"ETOGGLE",139:"TENSOR",141:"MULTI",142:"BMATRIX",144:"EMATRIX",145:"BGATHERED",146:"EGATHERED",147:"BPMATRIX",148:"EPMATRIX",149:"BBMATRIX",150:"EBMATRIX",151:"BVMATRIX",152:"EVMATRIX",153:"BBBMATRIX",154:"EBBMATRIX",155:"BVVMATRIX",156:"EVVMATRIX",157:"BSMALLMATRIX",158:"ESMALLMATRIX",159:"BCASES",160:"ECASES",161:"BALIGNED",162:"EALIGNED",163:"BARRAY",164:"EARRAY",165:"SUBSTACK",166:"ARRAY",167:"ARRAYOPTS",169:"_",170:"^",171:"OPP",173:"OPM",174:"FM",179:"DISPLAYSTYLE",180:"TEXTSTYLE",181:"TEXTSIZE",182:"SCRIPTSIZE",183:"SCRIPTSCRIPTSIZE",184:"COLOR",185:"BGCOLOR",187:"CELLOPTS",189:"COLSEP",191:"ROWOPTS",192:"ROWSEP",195:"EOF",198:"STARTMATH0",199:"ENDMATH0",200:"STARTMATH1",201:"ENDMATH1",202:"STARTMATH2",203:"ENDMATH2",204:"STARTMATH3",205:"ENDMATH3"}, -productions_: [0,[3,3],[7,3],[11,3],[12,3],[13,1],[14,1],[15,1],[16,1],[17,1],[18,2],[20,2],[22,2],[24,2],[26,2],[28,2],[30,2],[32,2],[34,2],[36,2],[38,2],[40,2],[42,1],[42,1],[42,1],[42,1],[43,1],[43,2],[44,1],[44,1],[45,1],[45,1],[45,1],[45,1],[45,1],[45,1],[45,1],[45,1],[45,1],[45,1],[46,1],[46,2],[47,1],[47,2],[48,2],[48,2],[52,2],[52,2],[54,2],[54,3],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,3],[54,5],[54,5],[54,5],[54,5],[54,5],[54,5],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,2],[54,2],[54,2],[54,1],[54,1],[54,1],[54,1],[54,1],[54,2],[54,4],[54,2],[54,2],[54,1],[54,2],[54,2],[54,2],[54,2],[54,3],[54,3],[54,2],[54,5],[54,3],[54,3],[54,4],[54,5],[54,2],[54,2],[54,2],[54,2],[54,2],[54,3],[54,3],[54,3],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,4],[54,5],[54,4],[54,3],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,3],[54,3],[54,3],[54,3],[54,3],[54,5],[54,8],[54,7],[54,7],[54,3],[54,3],[54,3],[54,3],[54,3],[54,3],[54,3],[54,3],[54,3],[54,3],[54,5],[54,4],[54,4],[54,4],[54,8],[137,1],[137,2],[168,3],[168,5],[168,4],[168,5],[168,4],[168,3],[168,3],[168,2],[168,1],[168,5],[168,5],[168,3],[168,3],[168,1],[172,1],[172,1],[175,1],[175,2],[176,1],[176,1],[177,4],[177,2],[177,2],[177,3],[140,1],[140,2],[178,1],[178,1],[178,1],[178,1],[178,1],[178,2],[178,2],[55,2],[55,1],[186,0],[186,5],[186,1],[188,1],[188,3],[190,5],[190,1],[143,1],[143,3],[193,2],[194,1],[194,2],[196,1],[196,1],[197,2],[197,3],[197,2],[197,3],[197,3],[197,3]], -performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) { -/* this == yyval */ - -var $0 = $$.length - 1; -switch (yystate) { -case 1: - - /* Unescape \] and \\. */ - this.$ = $$[$0-1].replace(/\\[\\\]]/g, function(match) { return match.slice(1); }); - /* Escape some XML characters. */ - this.$ = escapeText(this.$); - -break; -case 2: - - /* Unescape \} and \\. */ - this.$ = $$[$0-1].replace(/\\[\\\}]/g, function(match) { return match.slice(1); }); - /* Escape some XML characters. */ - this.$ = escapeText(this.$); - -break; -case 3: case 4: - - this.$ = parseLength($$[$0-1]); - -break; -case 5: case 6: - this.$ = escapeQuote($$[$0]); -break; -case 7: - - /* The MathML specification indicates that trailing/leading whitespaces - should be removed and that inner whitespace should be collapsed. Let's - replace trailing/leading whitespace by no-break space so that people can - write e.g. \text{ if }. We also collapse internal whitespace here. - See https://github.com/fred-wang/TeXZilla/issues/25. */ - this.$ = $$[$0].replace(/\s+/g, " ").replace(/^ | $/g, "\u00A0"); - -break; -case 8: - - $$[$0] = $$[$0].trim(); - if ($$[$0] === "t") { - this.$ = "axis 1"; - } else if ($$[$0] === "c") { - this.$ = "center"; - } else if ($$[$0] === "b") { - this.$ = "axis -1"; - } else { - throw "Unknown array alignment"; - } - -break; -case 9: - - this.$ = ""; - $$[$0] = $$[$0].replace(/\s+/g, "");; - for (var i = 0; i < $$[$0].length; i++) { - if ($$[$0][i] === "c") { - this.$ += " center"; - } else if ($$[$0][i] === "l") { - this.$ += " left"; - } else if ($$[$0][i] === "r") { - this.$ += " right"; - } - } - if (this.$.length) { - this.$ = this.$.slice(1); - } else { - throw "Invalid column alignments"; - } - -break; -case 10: case 11: - this.$ = {"columnalign": $$[$0]}; -break; -case 12: - this.$ = {"rowalign": $$[$0]}; -break; -case 13: - this.$ = {"rowspan": $$[$0]}; -break; -case 14: - this.$ = {"colspan": $$[$0]}; -break; -case 15: - this.$ = {"align": $$[$0]}; -break; -case 16: - this.$ = {"equalrows": $$[$0]}; -break; -case 17: - this.$ = {"equalcolumns": $$[$0]}; -break; -case 18: - this.$ = {"rowlines": $$[$0]}; -break; -case 19: - this.$ = {"columnlines": $$[$0]}; -break; -case 20: - this.$ = {"frame": $$[$0]}; -break; -case 21: - this.$ = {"rowspacing": $$[$0], "columnspacing": $$[$0]}; -break; -case 22: case 23: case 24: case 25: case 26: case 28: case 29: case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: case 40: case 42: case 170: case 175: case 180: case 181: case 186: case 196: case 207: case 209: - this.$ = $$[$0]; -break; -case 27: case 41: case 43: - this.$ = Object.assign($$[$0-1], $$[$0]); -break; -case 44: case 46: - - this.$ = newMo($$[$0]); - -break; -case 45: case 47: - - this.$ = ""; - -break; -case 48: - this.$ = newTag("mrow"); -break; -case 49: - this.$ = newMrow($$[$0-1]); -break; -case 50: case 54: - - this.$ = newTag("mo", $$[$0], {"maxsize": "1.2em", "minsize": "1.2em"}); - -break; -case 51: case 55: - - this.$ = newTag("mo", $$[$0], {"maxsize": "1.8em", "minsize": "1.8em"}); - -break; -case 52: case 56: - - this.$ = newTag("mo", $$[$0], {"maxsize": "2.4em", "minsize": "2.4em"}); - -break; -case 53: case 57: - - this.$ = newTag("mo", $$[$0], {"maxsize": "3em", "minsize": "3em"}); - -break; -case 58: - - this.$ = newTag("mrow", [$$[$0-2], newMrow($$[$0-1]), $$[$0]]); - -break; -case 59: - - this.$ = newTag("mfrac", [newMrow($$[$0-3]), newMrow($$[$0-1])], {"linethickness": "0px"}); - -break; -case 60: - - this.$ = newTag("mfrac", [newMrow($$[$0-3]), newMrow($$[$0-1])], {"linethickness": "0px"}); - this.$ = newTag("mrow", [$$[$0-4], this.$, $$[$0]]); - -break; -case 61: - - this.$ = newTag("mfrac", [newMrow($$[$0-3]), newMrow($$[$0-1])]); - -break; -case 62: - - this.$ = newTag("mfrac", [newMrow($$[$0-3]), newMrow($$[$0-1])]); - this.$ = newTag("mrow", [$$[$0-4], this.$, $$[$0]]); - -break; -case 63: - - this.$ = newTag("mfrac", [newMrow($$[$0-3]), newMrow($$[$0-1])], {"linethickness": "0px"}); - this.$ = newTag("mrow", [newMo("("), this.$, newMo(")")]); - -break; -case 64: - - this.$ = newTag("mfrac", [newMrow($$[$0-3]), newMrow($$[$0-1])], {"linethickness": "0px"}); - this.$ = newTag("mrow", [$$[$0-4], this.$, $$[$0]]); - this.$ = newTag("mrow", [newMo("("), this.$, newMo(")")]); - -break; -case 65: case 74: - this.$ = newTag("mn", $$[$0]); -break; -case 66: case 83: case 85: - this.$ = newTag("mtext", $$[$0]); -break; -case 67: case 68: case 69: case 70: - this.$ = newMi($$[$0]); -break; -case 71: - this.$ = newMi($$[$0], true); -break; -case 72: case 177: - this.$ = newMo($$[$0], 0, 0); -break; -case 73: - this.$ = newTag("mi", $$[$0]); -break; -case 75: case 76: case 77: case 176: - this.$ = newMo($$[$0]); -break; -case 78: case 79: case 80: - this.$ = newTag("mo", $$[$0], {"stretchy": "false"}); -break; -case 81: - this.$ = newTag("ms", $$[$0]); -break; -case 82: - - this.$ = newTag("ms", $$[$0], {"lquote": $$[$0-2], "rquote": $$[$0-1]}); - -break; -case 84: - this.$ = newTag("mtext", $$[$0-1] + $$[$0]); -break; -case 86: - - this.$ = newMo($$[$0], 0, namedSpaceToEm("thinmathspace")); - -break; -case 87: - - this.$ = newMo($$[$0], namedSpaceToEm("thinmathspace"), - namedSpaceToEm("thinmathspace")); - -break; -case 88: - - this.$ = newMo($$[$0], namedSpaceToEm("mediummathspace"), - namedSpaceToEm("mediummathspace")); - -break; -case 89: - - this.$ = newMo($$[$0], namedSpaceToEm("thickmathspace"), - namedSpaceToEm("thickmathspace")); - -break; -case 90: - this.$ = newTag("mfrac", [$$[$0-1], $$[$0]]); -break; -case 91: - this.$ = newTag("mroot", [$$[$0], $$[$0-1]]); -break; -case 92: - this.$ = newTag("msqrt", [$$[$0]]); -break; -case 93: - - this.$ = newTag("mroot", [$$[$0], newMrow($$[$0-2])]); - -break; -case 94: - this.$ = newTag("munder", [$$[$0], $$[$0-1]]); -break; -case 95: - this.$ = newTag("mover", [$$[$0], $$[$0-1]]); -break; -case 96: - - this.$ = newTag("munderover", [$$[$0], $$[$0-2], $$[$0-1]]); -break; -case 97: - - this.$ = (isEmptyMrow($$[$0]) ? - newTag("munder", [newMo($$[$0-4]), newMrow($$[$0-2])]) : - newTag("munderover", [newMo($$[$0-4]), newMrow($$[$0-2]), $$[$0]])); - -break; -case 98: - - this.$ = newTag("mover", [newMo($$[$0-1]), $$[$0]]); - -break; -case 99: - this.$ = newTag("mpadded", [$$[$0]], {"width": "0em"}); -break; -case 100: - - this.$ = newTag("mpadded", [$$[$0]], {"width": "0em", "lspace": "-100%width"}); - -break; -case 101: - - this.$ = newTag("mpadded", [$$[$0]], {"width": "0em", "lspace": "-50%width"}); - -break; -case 102: - this.$ = newTag("mphantom", [$$[$0]]); -break; -case 103: - - this.$ = newTag("mfrac", [$$[$0-1], $$[$0]]); - this.$ = newMrow([this.$], "mstyle", {"displaystyle": "false"}); - -break; -case 104: - - this.$ = newTag("mfrac", [$$[$0-1], $$[$0]], {"linethickness": "0px"}); - this.$ = newTag("mrow", [newMo("("), this.$, newMo(")")]); - -break; -case 105: - - this.$ = newTag("mfrac", [$$[$0-1], $$[$0]], {"linethickness": "0px"}); - this.$ = newMrow([this.$], "mstyle", {"displaystyle": "false"}); - this.$ = newTag("mrow", [newMo("("), this.$, newMo(")")]); - -break; -case 106: - - this.$ = newTag("mrow", - [newMo("(", namedSpaceToEm("mediummathspace")), - newMo("mod", undefined, namedSpaceToEm("thinmathspace")), $$[$0], - newMo(")", undefined, namedSpaceToEm("mediummathspace"))]); - -break; -case 107: - this.$ = newTag("munder", [$$[$0], newMo("\u23DF")]); -break; -case 108: - this.$ = newTag("munder", [$$[$0], newMo("_")]); -break; -case 109: - this.$ = newTag("mover", [$$[$0], newMo("\u23DE")]); -break; -case 110: - - this.$ = newTag("mover", [$$[$0], newMo($$[$0-1])]); - -break; -case 111: - - this.$ = newTag("mover", [$$[$0], newTag("mo", $$[$0-1], {"stretchy": "false"})]); - -break; -case 112: - this.$ = newTag("menclose", [$$[$0]], {"notation": "box"}); -break; -case 113: - - this.$ = newTag("menclose", [$$[$0]], {"notation": "updiagonalstrike"}); - -break; -case 114: - this.$ = newSpace(1); -break; -case 115: - this.$ = newSpace(2); -break; -case 116: - this.$ = newSpace(namedSpaceToEm("negativethinmathspace")); -break; -case 117: - this.$ = newSpace(namedSpaceToEm("negativemediummathspace")); -break; -case 118: - this.$ = newSpace(namedSpaceToEm("negativethickmathspace")); -break; -case 119: - this.$ = newSpace(namedSpaceToEm("thinmathspace")); -break; -case 120: - this.$ = newSpace(namedSpaceToEm("mediummathspace")); -break; -case 121: - this.$ = newSpace(namedSpaceToEm("thickmathspace")); -break; -case 122: - - this.$ = newTag("mspace", null, - {"height": "." + $$[$0-2] + "ex", - "depth": "." + $$[$0-1] + "ex", - "width": "." + $$[$0] + "em"}); - -break; -case 123: - - this.$ = newTag("mpadded", [$$[$0]], - {"voffset": $$[$0-3].l + $$[$0-3].u, - "height": $$[$0-2].l + $$[$0-2].u, - "depth": $$[$0-1].l + $$[$0-1].u}); - -break; -case 124: - - this.$ = newTag("mpadded", [$$[$0]], - {"voffset": $$[$0-2].l + $$[$0-2].u, - "height": $$[$0-1].l + $$[$0-1].u, - "depth": ($$[$0-2].l < 0 ? "+" + (-$$[$0-2].l) + $$[$0-2].u : "depth")}); - -break; -case 125: - - var attributes = {"voffset": $$[$0-1].l + $$[$0-1].u}; - if ($$[$0-1].l >= 0) - attributes.height = "+" + $$[$0-1].l + $$[$0-1].u; - else { - attributes.height = "0pt"; - attributes.depth = "+" + (-$$[$0-1].l) + $$[$0-1].u; - } - this.$ = newTag("mpadded", [$$[$0]], attributes); - -break; -case 126: - - this.$ = newMrow([$$[$0]], "mstyle", {"mathvariant": "double-struck"}); - -break; -case 127: - this.$ = newMrow([$$[$0]], "mstyle", {"mathvariant": "bold"}); -break; -case 128: - this.$ = newMrow([$$[$0]], "mstyle", - {"mathvariant": "bold-italic"}); -break; -case 129: - this.$ = newMrow([$$[$0]], "mstyle", - {"mathvariant": "script"}); -break; -case 130: - - this.$ = newMrow([$$[$0]], "mstyle", {"mathvariant": "bold-script"}); - -break; -case 131: - - this.$ = newMrow([$$[$0]], "mstyle", {"mathvariant": "sans-serif"}); - -break; -case 132: - this.$ = newMrow([$$[$0]], "mstyle", - {"mathvariant": "fraktur"}); -break; -case 133: - this.$ = newMrow([$$[$0]], "mstyle", - {"mathvariant": "italic"}); -break; -case 134: - this.$ = newMrow([$$[$0]], "mstyle", - {"mathvariant": "monospace"}); -break; -case 135: - this.$ = newMrow([$$[$0]], "mstyle", - {"mathvariant": "normal"}); -break; -case 136: - - this.$ = newTag("mrow", [$$[$0]], yy.mSafeMode ? null : {"href": $$[$0-1]}); - -break; -case 137: - - this.$ = yy.mSafeMode ? $$[$0] : - newTag("maction", - [$$[$0], newTag("mtext", $$[$0-1])], {"actiontype": "statusline"}); - -break; -case 138: - - this.$ = yy.mSafeMode ? $$[$0] : - newTag("maction", - [$$[$0], newTag("mtext", $$[$0-1])], {"actiontype": "tooltip"}); - -break; -case 139: - - /* Backward compatibility with itex2MML */ - this.$ = yy.mSafeMode ? $$[$0] : - newTag("maction", [$$[$0-1], $$[$0]], {"actiontype": "toggle", selection: "2"}); - -break; -case 140: - - this.$ = yy.mSafeMode ? newTag("mrow", $$[$0-1]) : - newTag("maction", $$[$0-1], {"actiontype": "toggle"}); - -break; -case 141: case 144: - - this.$ = newTag("mmultiscripts", [$$[$0-3]].concat($$[$0-1])); - -break; -case 142: - - this.$ = newTag("mmultiscripts", [$$[$0-3]].concat($$[$0-1]).concat(newTag("mprescripts")).concat($$[$0-5])); - -break; -case 143: - - this.$ = newTag("mmultiscripts", [$$[$0-2], newTag("mprescripts")].concat($$[$0-4])); - -break; -case 145: - - this.$ = newTag("mtable", $$[$0-1], {"displaystyle": "false", "rowspacing": "0.5ex"}); - -break; -case 146: - - this.$ = newTag("mtable", $$[$0-1], {"displaystyle": "true", "rowspacing": "1.0ex"}); - -break; -case 147: - - this.$ = newTag("mtable", $$[$0-1], {"displaystyle": "false", "rowspacing": "0.5ex"}); - this.$ = newTag("mrow", [newMo("("), this.$, newMo(")")]); - -break; -case 148: - - this.$ = newTag("mtable", $$[$0-1], {"displaystyle": "false", "rowspacing": "0.5ex"}); - this.$ = newTag("mrow", [newMo("["), this.$, newMo("]")]); - -break; -case 149: - - this.$ = newTag("mtable", $$[$0-1], {"displaystyle": "false", "rowspacing": "0.5ex"}); - this.$ = newTag("mrow", [newMo("|"), this.$, newMo("|")]); - -break; -case 150: - - this.$ = newTag("mtable", $$[$0-1], {"displaystyle": "false", "rowspacing": "0.5ex"}); - this.$ = newTag("mrow", [newMo("{"), this.$, newMo("}")]); - -break; -case 151: - - this.$ = newTag("mtable", $$[$0-1], {"displaystyle": "false", "rowspacing": "0.5ex"}); - this.$ = newTag("mrow", [newMo("\u2016"), this.$, newMo("\u2016")]); - -break; -case 152: - - this.$ = newTag("mtable", $$[$0-1], {"displaystyle": "false", "rowspacing": "0.5ex"}); - this.$ = newMrow([this.$], "mstyle", {"scriptlevel": "2"}); - -break; -case 153: - - this.$ = newTag("mtable", $$[$0-1], {"displaystyle": "false", - "columnalign": "left left"}); - this.$ = newTag("mrow", [newMo("{"), this.$]); - -break; -case 154: - - this.$ = newTag("mtable", $$[$0-1], {"displaystyle": "true", - "columnalign": "right left right left right left right left right left", - "columnspacing": "0em"}); - -break; -case 155: - - this.$ = newTag("mtable", $$[$0-1], - {"displaystyle": "false", "rowspacing": "0.5ex", "align": $$[$0-3], - "columnalign": $$[$0-2]}); - -break; -case 156: - - this.$ = newTag("mtable", $$[$0-1], - {"displaystyle": "false", "rowspacing": "0.5ex", - "columnalign": $$[$0-2]}); - -break; -case 157: - - this.$ = newTag("mtable", $$[$0-1], - {"displaystyle": "false", "columnalign": "center", - "rowspacing": "0.5ex"}); - -break; -case 158: - - this.$ = newTag("mtable", $$[$0-1], {"displaystyle": "false"}); - -break; -case 159: - - this.$ = newTag("mtable", $$[$0-1], Object.assign($$[$0-3], {"displaystyle": "false"})); - -break; -case 160: - - this.$ = [$$[$0]]; - -break; -case 161: - - this.$ = $$[$0-1].concat([$$[$0]]); - -break; -case 162: - - this.$ = newTag("mmultiscripts", [$$[$0-1]].concat($$[$0])); - -break; -case 163: - - this.$ = newTag("msubsup", [$$[$0-4], $$[$0-2], $$[$0]]); - -break; -case 164: - - this.$ = newTag("msubsup", [$$[$0-3], $$[$0-1], newMo($$[$0])]); - -break; -case 165: - - this.$ = newTag("msubsup", [$$[$0-4], $$[$0], $$[$0-2]]); - -break; -case 166: - - this.$ = newTag("msubsup", [$$[$0-3], $$[$0], newMo($$[$0-2])]); - -break; -case 167: - - this.$ = newTag("msub", [$$[$0-2], $$[$0]]); - -break; -case 168: - - this.$ = newTag("msup", [$$[$0-2], $$[$0]]); - -break; -case 169: - - this.$ = newTag("msup", [$$[$0-1], newMo($$[$0])]); - -break; -case 171: - - this.$ = newTag("munderover", [$$[$0-4], $$[$0-2], $$[$0]]); - -break; -case 172: - - this.$ = newTag("munderover", [$$[$0-4], $$[$0], $$[$0-2]]); - -break; -case 173: - - this.$ = newTag("munder", [$$[$0-2], $$[$0]]); - -break; -case 174: - - this.$ = newTag("mover", [$$[$0-2], $$[$0]]); - -break; -case 178: case 200: case 204: - this.$ = [$$[$0]]; -break; -case 179: - this.$ = $$[$0-1].concat([$$[$0]]); -break; -case 182: - this.$ = [$$[$0-2], $$[$0]]; -break; -case 183: - this.$ = [$$[$0], newTag("none")]; -break; -case 184: case 185: - this.$ = [newTag("none"), $$[$0]]; -break; -case 187: - this.$ = $$[$0-1].concat($$[$0]); -break; -case 188: - this.$ = {"displaystyle": "true"}; -break; -case 189: - this.$ = {"displaystyle": "false"}; -break; -case 190: - this.$ = {"scriptlevel": "0"}; -break; -case 191: - this.$ = {"scriptlevel": "1"}; -break; -case 192: - this.$ = {"scriptlevel": "2"}; -break; -case 193: - this.$ = {"mathcolor": $$[$0]}; -break; -case 194: - this.$ = {"mathbackground": $$[$0]}; -break; -case 195: - this.$ = [newMrow($$[$0], "mstyle", $$[$0-1])]; -break; -case 197: - this.$ = newTag("mtd", []); -break; -case 198: - - this.$ = newMrow($$[$0], "mtd", $$[$0-2]); - -break; -case 199: - this.$ = newMrow($$[$0], "mtd"); -break; -case 201: case 205: - this.$ = $$[$0-2].concat([$$[$0]]); -break; -case 202: - - this.$ = this.$ = newTag("mtr", $$[$0], $$[$0-2]); - -break; -case 203: - this.$ = newTag("mtr", $$[$0]); -break; -case 206: - - this.$ = $$[$0-1] - return this.$; - -break; -case 208: - this.$ = $$[$0-1] + $$[$0] -break; -case 210: - - this.$ = serializeTree($$[$0]); - -break; -case 211: - - // \( \) - this.$ = newMath([newTag("mrow")], false, false, yy.tex); - -break; -case 212: - - // \( ... \) - this.$ = newMath($$[$0-1], false, false, yy.tex); - -break; -case 213: - - // \[ \] - this.$ = newMath([newTag("mrow")], true, false, yy.tex); - -break; -case 214: - - // \[ ... \] - this.$ = newMath($$[$0-1], true, false, yy.tex); - -break; -case 215: - - // $ ... $ - this.$ = newMath($$[$0-1], false, false, yy.tex); - -break; -case 216: - - // this.$ ... this.$ - this.$ = newMath($$[$0-1], true, false, yy.tex); - -break; -} -}, -table: [{68:$V0,193:1,194:2,196:3,197:5,198:$V1,200:$V2,202:$V3,204:$V4},{1:[3]},{68:$V0,195:[1,10],196:11,197:5,198:$V1,200:$V2,202:$V3,204:$V4},o($V5,[2,207]),o($V5,[2,209]),o($V5,[2,210]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:25,55:13,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,168:23,172:26,173:$VC1,174:$VD1,175:15,178:14,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,199:[1,12]},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:25,55:126,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,168:23,172:26,173:$VC1,174:$VD1,175:15,178:14,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,201:[1,125]},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:25,55:127,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,168:23,172:26,173:$VC1,174:$VD1,175:15,178:14,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:25,55:128,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,168:23,172:26,173:$VC1,174:$VD1,175:15,178:14,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1},{1:[2,206]},o($V5,[2,208]),o($V5,[2,211]),{199:[1,129]},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:25,55:130,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,168:23,172:26,173:$VC1,174:$VD1,175:15,178:14,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1},o($VL1,[2,196],{54:25,172:26,48:36,168:131,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1}),o($VM1,[2,188]),o($VM1,[2,189]),o($VM1,[2,190]),o($VM1,[2,191]),o($VM1,[2,192]),{7:133,8:$VN1,14:132},{7:133,8:$VN1,14:135},o($VO1,[2,178]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:136,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},o($VO1,[2,170],{169:[1,138],170:[1,139],171:[1,140]}),o($VO1,[2,175],{169:[1,141],170:[1,142]}),{8:$V6,10:[1,143],48:36,49:$V7,50:$V8,51:$V9,54:25,55:144,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,168:23,172:26,173:$VC1,174:$VD1,175:15,178:14,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1},{50:[1,145]},{50:[1,146]},{50:[1,147]},{50:[1,148]},{50:[1,149]},{50:[1,150]},{50:[1,151]},{50:[1,152]},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:25,55:153,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,168:23,172:26,173:$VC1,174:$VD1,175:15,178:14,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1},o($VQ1,[2,65]),o($VQ1,[2,66]),o($VQ1,[2,67]),o($VQ1,[2,68]),o($VQ1,[2,69]),o($VQ1,[2,70]),o($VQ1,[2,71]),o($VQ1,[2,72]),{7:155,8:$VN1,15:154},{7:155,8:$VN1,15:156},{7:155,8:$VN1,15:157},o($VQ1,[2,76]),o($VQ1,[2,77]),o($VQ1,[2,78]),o($VQ1,[2,79]),o($VQ1,[2,80]),{3:160,4:$VR1,7:155,8:$VN1,13:159,15:158},{7:155,8:$VN1,15:162},{84:[1,163]},o($VQ1,[2,85]),{7:164,8:$VN1},{7:165,8:$VN1},{7:166,8:$VN1},{7:167,8:$VN1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:168,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:169,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{4:[1,171],8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:170,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:172,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:173,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:174,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{4:[1,175],8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:176,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:177,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:178,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:179,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:180,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:181,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:182,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:183,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:184,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:185,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:186,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:187,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:188,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:189,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:190,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:191,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},o($VQ1,[2,114]),o($VQ1,[2,115]),o($VQ1,[2,116]),o($VQ1,[2,117]),o($VQ1,[2,118]),o($VQ1,[2,119]),o($VQ1,[2,120]),o($VQ1,[2,121]),{7:192,8:$VN1},{8:[1,194],12:193},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:195,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:196,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:197,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:198,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:199,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:200,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:201,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:202,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:203,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:204,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{7:133,8:$VN1,14:205},{7:206,8:$VN1},{7:207,8:$VN1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:208,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:210,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,137:209,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:[1,211]},o([144,189,192],$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,143:212,190:213,188:215,186:216,55:218,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1,191:$VU1}),o([146,189,192],$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,190:213,188:215,186:216,55:218,143:219,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1,191:$VU1}),o([148,189,192],$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,190:213,188:215,186:216,55:218,143:220,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1,191:$VU1}),o([150,189,192],$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,190:213,188:215,186:216,55:218,143:221,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1,191:$VU1}),o([152,189,192],$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,190:213,188:215,186:216,55:218,143:222,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1,191:$VU1}),o([154,189,192],$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,190:213,188:215,186:216,55:218,143:223,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1,191:$VU1}),o([156,189,192],$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,190:213,188:215,186:216,55:218,143:224,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1,191:$VU1}),o([158,189,192],$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,190:213,188:215,186:216,55:218,143:225,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1,191:$VU1}),o([160,189,192],$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,190:213,188:215,186:216,55:218,143:226,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1,191:$VU1}),o([162,189,192],$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,190:213,188:215,186:216,55:218,143:227,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1,191:$VU1}),{3:230,4:$VR1,7:231,8:$VN1,16:228,17:229},{8:[1,232]},{8:[1,233]},o($VV1,[2,176]),o($VV1,[2,177]),{50:[1,234],51:[1,235]},o($V5,[2,213]),{201:[1,236]},{203:[1,237]},{205:[1,238]},o($V5,[2,212]),o($VL1,[2,195]),o($VO1,[2,179]),o($VM1,[2,193]),o([8,10,19,21,23,25,27,29,31,33,35,37,39,41,49,50,51,56,57,58,59,60,61,62,63,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,139,141,142,145,147,149,151,153,155,157,159,161,163,165,166,173,174,179,180,181,182,183,184,185],[2,6]),{9:[1,239]},o($VM1,[2,194]),{8:$VW1,140:240,169:$VX1,170:$VY1,177:242},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:245,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:246,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:247,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},o($VO1,[2,169],{169:[1,248]}),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:249,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:250,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},o($VQ1,[2,48]),{10:[1,251],64:[1,252],65:[1,253],66:[1,254]},o($VQ1,[2,50]),o($VQ1,[2,51]),o($VQ1,[2,52]),o($VQ1,[2,53]),o($VQ1,[2,54]),o($VQ1,[2,55]),o($VQ1,[2,56]),o($VQ1,[2,57]),{52:255,53:$VZ1,64:[1,256],65:[1,257],66:[1,258]},o($VQ1,[2,73]),o($VQ1,[2,7]),o($VQ1,[2,74]),o($VQ1,[2,75]),o($VQ1,[2,81]),{3:160,4:$VR1,13:260},o($V_1,[2,5]),{5:[1,261]},o($VQ1,[2,83]),o($VQ1,[2,84]),o($VQ1,[2,86]),o($VQ1,[2,87]),o($VQ1,[2,88]),o($VQ1,[2,89]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:262,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:263,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},o($VQ1,[2,92]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:25,55:264,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,168:23,172:26,173:$VC1,174:$VD1,175:15,178:14,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:265,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:266,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:267,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:25,55:268,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,168:23,172:26,173:$VC1,174:$VD1,175:15,178:14,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1},o($VQ1,[2,98]),o($VQ1,[2,99]),o($VQ1,[2,100]),o($VQ1,[2,101]),o($VQ1,[2,102]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:269,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:270,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:271,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},o($VQ1,[2,106]),o($VQ1,[2,107]),o($VQ1,[2,108]),o($VQ1,[2,109]),o($VQ1,[2,110]),o($VQ1,[2,111]),o($VQ1,[2,112]),o($VQ1,[2,113]),{7:272,8:$VN1},{4:$V$1,8:$V6,11:273,48:36,49:$V7,50:$V8,51:$V9,54:274,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{9:[1,276]},o($VQ1,[2,126]),o($VQ1,[2,127]),o($VQ1,[2,128]),o($VQ1,[2,129]),o($VQ1,[2,130]),o($VQ1,[2,131]),o($VQ1,[2,132]),o($VQ1,[2,133]),o($VQ1,[2,134]),o($VQ1,[2,135]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:277,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:278,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:279,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:280,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:282,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,138:[1,281],139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},o($V02,[2,160]),{10:[1,284],140:283,169:$VX1,170:$VY1,177:242},{144:[1,285],192:$V12},o($V22,[2,204]),{8:[1,287]},o($V22,[2,203],{189:$V32}),o($V42,[2,200]),{8:[1,289]},o($V42,[2,199]),{146:[1,290],192:$V12},{148:[1,291],192:$V12},{150:[1,292],192:$V12},{152:[1,293],192:$V12},{154:[1,294],192:$V12},{156:[1,295],192:$V12},{158:[1,296],192:$V12},{160:[1,297],192:$V12},{162:[1,298],192:$V12},{7:231,8:$VN1,17:299},o($V52,$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,190:213,188:215,186:216,55:218,143:300,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1,191:$VU1}),{8:[2,8]},o([8,49,50,51,56,57,58,59,60,61,62,63,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,139,141,142,145,147,149,151,153,155,157,159,161,163,164,165,166,173,174,179,180,181,182,183,184,185,187,189,191,192],[2,9]),o($V62,$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,190:213,188:215,186:216,55:218,143:301,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1,191:$VU1}),o($V62,$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,190:213,188:215,186:216,55:218,143:302,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,167:[1,303],173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1,191:$VU1}),o($VM1,[2,44]),o($VM1,[2,45]),o($V5,[2,214]),o($V5,[2,215]),o($V5,[2,216]),{10:[1,304]},o($VO1,[2,162],{177:305,169:$VX1,170:$VY1}),{140:306,169:$VX1,170:$VY1,177:242},o($VV1,[2,186]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:309,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,170:[1,308],172:310,173:$VC1,174:$VD1,176:307},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:309,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,172:310,173:$VC1,174:$VD1,176:311},{8:$VW1},o($VO1,[2,167],{170:[1,312],171:[1,313]}),o($VO1,[2,168],{169:[1,314]}),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:315,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},o($VO1,[2,173],{170:[1,316]}),o($VO1,[2,174],{169:[1,317]}),o($VQ1,[2,49]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:25,55:318,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,168:23,172:26,173:$VC1,174:$VD1,175:15,178:14,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:25,55:319,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,168:23,172:26,173:$VC1,174:$VD1,175:15,178:14,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:25,55:320,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,168:23,172:26,173:$VC1,174:$VD1,175:15,178:14,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1},o($VQ1,[2,58]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:25,55:321,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,168:23,172:26,173:$VC1,174:$VD1,175:15,178:14,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:25,55:322,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,168:23,172:26,173:$VC1,174:$VD1,175:15,178:14,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:25,55:323,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,168:23,172:26,173:$VC1,174:$VD1,175:15,178:14,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1},{50:[1,324],51:[1,325]},{7:155,8:$VN1,15:326},{6:[1,327]},o($VQ1,[2,90]),o($VQ1,[2,91]),{6:[1,328]},o($VQ1,[2,94]),o($VQ1,[2,95]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:329,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{6:[1,330]},o($VQ1,[2,103]),o($VQ1,[2,104]),o($VQ1,[2,105]),{7:331,8:$VN1},{4:$V$1,8:$V6,11:332,48:36,49:$V7,50:$V8,51:$V9,54:333,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},o($VQ1,[2,125]),{5:[1,334]},{10:[1,335]},o($VQ1,[2,136]),o($VQ1,[2,137]),o($VQ1,[2,138]),o($VQ1,[2,139]),o($VQ1,[2,140]),o($V02,[2,161]),{10:[1,336],169:$VX1,170:$VY1,177:305},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:337,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},o($VQ1,[2,145]),o($V42,$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,188:215,186:216,55:218,190:338,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1,191:$VU1}),{20:341,21:$V72,22:342,23:$V82,44:340,47:339},o($V42,$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,55:218,186:345,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1}),{20:348,21:$V72,22:349,23:$V82,24:350,25:$V92,26:351,27:$Va2,42:347,43:346},o($VQ1,[2,146]),o($VQ1,[2,147]),o($VQ1,[2,148]),o($VQ1,[2,149]),o($VQ1,[2,150]),o($VQ1,[2,151]),o($VQ1,[2,152]),o($VQ1,[2,153]),o($VQ1,[2,154]),o($V52,$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,190:213,188:215,186:216,55:218,143:354,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1,191:$VU1}),{164:[1,355],192:$V12},{10:[1,356],192:$V12},{10:[1,357],192:$V12},{8:[1,358]},o([6,8,10,19,21,23,25,27,29,31,33,35,37,39,41,49,50,51,53,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,138,139,141,142,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,169,170,171,173,174,179,180,181,182,183,184,185,187,189,191,192,199,201,203,205],[2,2]),o($VV1,[2,187]),{10:[1,359],169:$VX1,170:$VY1,177:305},o([6,8,10,49,50,51,53,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,139,141,142,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,169,173,174,189,192,199,201,203,205],[2,183],{170:[1,360]}),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:309,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,172:310,173:$VC1,174:$VD1,176:361},o($VV1,[2,180]),o($VV1,[2,181]),o($VV1,[2,184]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:362,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},o($VO1,[2,164]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:363,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},o($VO1,[2,166]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:364,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:365,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{10:[1,366]},{10:[1,367]},{10:[1,368]},{52:369,53:$VZ1},{52:370,53:$VZ1},{52:371,53:$VZ1},o($VQ1,[2,46]),o($VQ1,[2,47]),o($VQ1,[2,82]),o($V_1,[2,1]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:372,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},o($VQ1,[2,96]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:373,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},o($VQ1,[2,122]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:374,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},o($VQ1,[2,124]),{6:[1,375]},o($Vb2,[2,4]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:376,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1},{8:[1,377]},o($V22,[2,205]),{10:[1,378],20:341,21:$V72,22:342,23:$V82,44:379},o($Vc2,[2,42]),o($Vc2,[2,28]),o($Vc2,[2,29]),{7:133,8:$VN1,14:380},{7:133,8:$VN1,14:381},o($V42,[2,201]),{10:[1,382],20:348,21:$V72,22:349,23:$V82,24:350,25:$V92,26:351,27:$Va2,42:383},o($Vd2,[2,26]),o($Vd2,[2,22]),o($Vd2,[2,23]),o($Vd2,[2,24]),o($Vd2,[2,25]),{7:133,8:$VN1,14:384},{7:133,8:$VN1,14:385},{164:[1,386],192:$V12},o($VQ1,[2,156]),o($VQ1,[2,157]),o($VQ1,[2,158]),{18:389,19:$Ve2,20:390,21:$V72,22:391,23:$V82,28:392,29:$Vf2,30:393,31:$Vg2,32:394,33:$Vh2,34:395,35:$Vi2,36:396,37:$Vj2,38:397,39:$Vk2,40:398,41:$Vl2,45:388,46:387},o($VQ1,[2,141]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:309,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$VP1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,172:310,173:$VC1,174:$VD1,176:407},o($VV1,[2,185]),o($VO1,[2,163]),o($VO1,[2,165]),o($VO1,[2,171]),o($VO1,[2,172]),o($VQ1,[2,59]),o($VQ1,[2,61]),o($VQ1,[2,63]),o($VQ1,[2,60]),o($VQ1,[2,62]),o($VQ1,[2,64]),o($VQ1,[2,93]),o($VQ1,[2,97]),o($VQ1,[2,123]),o($Vb2,[2,3]),{8:[1,408]},{140:409,169:$VX1,170:$VY1,177:242},o($V42,$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,186:216,55:218,188:410,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1}),o($Vc2,[2,43]),o($Vm2,[2,11]),o($Vm2,[2,12]),{8:$V6,48:36,49:$V7,50:$V8,51:$V9,54:25,55:411,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,168:23,172:26,173:$VC1,174:$VD1,175:15,178:14,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1},o($Vd2,[2,27]),o($Vd2,[2,13]),o($Vd2,[2,14]),o($VQ1,[2,155]),{10:[1,412],18:389,19:$Ve2,20:390,21:$V72,22:391,23:$V82,28:392,29:$Vf2,30:393,31:$Vg2,32:394,33:$Vh2,34:395,35:$Vi2,36:396,37:$Vj2,38:397,39:$Vk2,40:398,41:$Vl2,45:413},o($Vn2,[2,40]),o($Vn2,[2,30]),o($Vn2,[2,31]),o($Vn2,[2,32]),o($Vn2,[2,33]),o($Vn2,[2,34]),o($Vn2,[2,35]),o($Vn2,[2,36]),o($Vn2,[2,37]),o($Vn2,[2,38]),o($Vn2,[2,39]),{7:133,8:$VN1,14:414},{7:133,8:$VN1,14:415},{7:133,8:$VN1,14:416},{7:133,8:$VN1,14:417},{7:133,8:$VN1,14:418},{7:133,8:$VN1,14:419},{7:133,8:$VN1,14:420},{7:133,8:$VN1,14:421},o($VV1,[2,182]),{10:[1,423],140:422,169:$VX1,170:$VY1,177:242},{10:[1,424],169:$VX1,170:$VY1,177:305},o($V22,[2,202],{189:$V32}),o($V42,[2,198]),o($V62,$VS1,{178:14,175:15,168:23,54:25,172:26,48:36,190:213,188:215,186:216,55:218,143:425,8:$V6,49:$V7,50:$V8,51:$V9,56:$Va,57:$Vb,58:$Vc,59:$Vd,60:$Ve,61:$Vf,62:$Vg,63:$Vh,67:$Vi,68:$Vj,69:$Vk,70:$Vl,71:$Vm,72:$Vn,73:$Vo,74:$Vp,75:$Vq,76:$Vr,77:$Vs,78:$Vt,79:$Vu,80:$Vv,81:$Vw,82:$Vx,83:$Vy,85:$Vz,86:$VA,87:$VB,88:$VC,89:$VD,90:$VE,91:$VF,92:$VG,93:$VH,94:$VI,95:$VJ,96:$VK,97:$VL,98:$VM,99:$VN,100:$VO,101:$VP,102:$VQ,103:$VR,104:$VS,105:$VT,106:$VU,107:$VV,108:$VW,109:$VX,110:$VY,111:$VZ,112:$V_,113:$V$,114:$V01,115:$V11,116:$V21,117:$V31,118:$V41,119:$V51,120:$V61,121:$V71,122:$V81,123:$V91,124:$Va1,125:$Vb1,126:$Vc1,127:$Vd1,128:$Ve1,129:$Vf1,130:$Vg1,131:$Vh1,132:$Vi1,133:$Vj1,134:$Vk1,135:$Vl1,136:$Vm1,139:$Vn1,141:$Vo1,142:$Vp1,145:$Vq1,147:$Vr1,149:$Vs1,151:$Vt1,153:$Vu1,155:$Vv1,157:$Vw1,159:$Vx1,161:$Vy1,163:$Vz1,165:$VA1,166:$VB1,173:$VC1,174:$VD1,179:$VE1,180:$VF1,181:$VG1,182:$VH1,183:$VI1,184:$VJ1,185:$VK1,187:$VT1,191:$VU1}),o($Vn2,[2,41]),o($Vn2,[2,10]),o($Vn2,[2,15]),o($Vn2,[2,16]),o($Vn2,[2,17]),o($Vn2,[2,18]),o($Vn2,[2,19]),o($Vn2,[2,20]),o($Vn2,[2,21]),{10:[1,426],169:$VX1,170:$VY1,177:305},o($VQ1,[2,143]),o($VQ1,[2,144]),{10:[1,427],192:$V12},o($VQ1,[2,142]),o($VQ1,[2,159])], -defaultActions: {10:[2,206],230:[2,8]}, -parseError: function parseError (str, hash) { - if (hash.recoverable) { - this.trace(str); - } else { - var error = new Error(str); - error.hash = hash; - throw error; - } -}, -parse: function parse(input) { - var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; - var args = lstack.slice.call(arguments, 1); - var lexer = Object.create(this.lexer); - var sharedState = { yy: {} }; - for (var k in this.yy) { - if (Object.prototype.hasOwnProperty.call(this.yy, k)) { - sharedState.yy[k] = this.yy[k]; - } - } - lexer.setInput(input, sharedState.yy); - sharedState.yy.lexer = lexer; - sharedState.yy.parser = this; - if (typeof lexer.yylloc == 'undefined') { - lexer.yylloc = {}; - } - var yyloc = lexer.yylloc; - lstack.push(yyloc); - var ranges = lexer.options && lexer.options.ranges; - if (typeof sharedState.yy.parseError === 'function') { - this.parseError = sharedState.yy.parseError; - } else { - this.parseError = Object.getPrototypeOf(this).parseError; - } - function popStack(n) { - stack.length = stack.length - 2 * n; - vstack.length = vstack.length - n; - lstack.length = lstack.length - n; - } - _token_stack: - var lex = function () { - var token; - token = lexer.lex() || EOF; - if (typeof token !== 'number') { - token = self.symbols_[token] || token; - } - return token; - }; - var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; - while (true) { - state = stack[stack.length - 1]; - if (this.defaultActions[state]) { - action = this.defaultActions[state]; - } else { - if (symbol === null || typeof symbol == 'undefined') { - symbol = lex(); - } - action = table[state] && table[state][symbol]; - } - if (typeof action === 'undefined' || !action.length || !action[0]) { - var errStr = ''; - expected = []; - for (p in table[state]) { - if (this.terminals_[p] && p > TERROR) { - expected.push('\'' + this.terminals_[p] + '\''); - } - } - if (lexer.showPosition) { - errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\''; - } else { - errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\''); - } - this.parseError(errStr, { - text: lexer.match, - token: this.terminals_[symbol] || symbol, - line: lexer.yylineno, - loc: yyloc, - expected: expected - }); - } - if (action[0] instanceof Array && action.length > 1) { - throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol); - } - switch (action[0]) { - case 1: - stack.push(symbol); - vstack.push(lexer.yytext); - lstack.push(lexer.yylloc); - stack.push(action[1]); - symbol = null; - if (!preErrorSymbol) { - yyleng = lexer.yyleng; - yytext = lexer.yytext; - yylineno = lexer.yylineno; - yyloc = lexer.yylloc; - if (recovering > 0) { - recovering--; - } - } else { - symbol = preErrorSymbol; - preErrorSymbol = null; - } - break; - case 2: - len = this.productions_[action[1]][1]; - yyval.$ = vstack[vstack.length - len]; - yyval._$ = { - first_line: lstack[lstack.length - (len || 1)].first_line, - last_line: lstack[lstack.length - 1].last_line, - first_column: lstack[lstack.length - (len || 1)].first_column, - last_column: lstack[lstack.length - 1].last_column - }; - if (ranges) { - yyval._$.range = [ - lstack[lstack.length - (len || 1)].range[0], - lstack[lstack.length - 1].range[1] - ]; - } - r = this.performAction.apply(yyval, [ - yytext, - yyleng, - yylineno, - sharedState.yy, - action[1], - vstack, - lstack - ].concat(args)); - if (typeof r !== 'undefined') { - return r; - } - if (len) { - stack = stack.slice(0, -1 * len * 2); - vstack = vstack.slice(0, -1 * len); - lstack = lstack.slice(0, -1 * len); - } - stack.push(this.productions_[action[1]][0]); - vstack.push(yyval.$); - lstack.push(yyval._$); - newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; - stack.push(newState); - break; - case 3: - return true; - } - } - return true; -}}; - -var MathMLNameSpace = "http://www.w3.org/1998/Math/MathML", - SVGNameSpace = "http://www.w3.org/2000/svg", - TeXMimeTypes = ["TeX", "LaTeX", "text/x-tex", "text/x-latex", - "application/x-tex", "application/x-latex"]; - -function escapeText(aString) { - /* Escape reserved XML characters for use as text nodes. */ - return aString.replace(/&/g, "&").replace(//g, ">"); -} - -function escapeQuote(aString) { - /* Escape the double quote characters for use as attribute. */ - return aString.replace(/"/g, """); -} - -function namedSpaceToEm(aString) { - var index = [ - "negativeveryverythinmathspace", - "negativeverythinmathspace", - "negativemediummathspace", - "negativethickmathspace", - "negativeverythickmathspace", - "negativeveryverythickmathspace", - "", - "veryverythinmathspace", - "verythinmathspace", - "thinmathspace", - "mediummathspace", - "thickmathspace", - "verythickmathspace", - "veryverythickmathspace" - ].indexOf(aString); - return (index === -1 ? 0 : index - 6) / 18.0; -} - -function parseLength(aString) { - /* See http://www.w3.org/TR/MathML3/appendixa.html#parsing_length */ - aString = aString.trim(); - var lengthRegexp = /(-?[0-9]*(?:[0-9]\.?|\.[0-9])[0-9]*)(e[mx]|in|cm|mm|p[xtc]|%)?/, result = lengthRegexp.exec(aString); - if (result) { - result[1] = parseFloat(result[1]); - if (!result[2]) { - /* Unitless values are treated as a percent */ - result[1] *= 100; - result[2] = "%"; - } - return { l: result[1], u: result[2] }; - } - return { l: namedSpaceToEm(aString), u: "em" }; -} - -function serializeTree(aTree) { - var output = "<" + aTree["tag"]; - for (var name in aTree["attributes"]) { - if (aTree["attributes"][name] !== undefined) - output += " " + name + "=\"" + aTree["attributes"][name] + "\""; - } - if (aTree["content"]) { - output += ">"; - if (Array.isArray(aTree["content"])) { - aTree["content"].forEach(function(child) { - output += serializeTree(child); - }); - } else - output += aTree["content"]; - output += ""; - } else { - output += "/>"; - } - return output; -} - -function newTag(aTag, aChildren, aAttributes) { - return { - "tag": aTag, - "content": aChildren, - "attributes": aAttributes - }; -} - -function isEmptyMrow(aTree) { - return aTree["tag"] === "mrow" && !aTree["content"] && !aTree["attributes"]; -} - -function newMo(aContent, aLeftSpace, aRightSpace) { - return newTag("mo", escapeText(aContent), { - "lspace": aLeftSpace !== undefined ? aLeftSpace + "em" : undefined, - "rspace": aRightSpace !== undefined ? aRightSpace + "em" : undefined - }); -} - -function newMi(aContent, aNormal) { - return newTag("mi", escapeText(aContent), - aNormal ? { "mathvariant": "normal" } : undefined); -} - -function newSpace(aWidth) { - return newTag("mspace", null, {"width": aWidth + "em"}); -} - -function applyMathVariantToCharacter(codePoint, aMathVariant) { - // FIXME: We should have LaTeX commmands for all these variants. - // See https://github.com/fred-wang/TeXZilla/issues/64 - var mathvariant = [ - "bold", - "italic", - "bold-italic", - "script", - "bold-script", - "fraktur", - "double-struck", - "bold-fraktur", - "sans-serif", - "bold-sans-serif", - "sans-serif-italic", - "sans-serif-bold-italic", - "monospace", - "initial", - "tailed", - "looped", - "stretched" - ].indexOf(aMathVariant); - var Bold = 0; - var Italic = 1; - var BoldItalic = 2; - var Script = 3; - var BoldScript = 4; - var Fraktur = 5; - var DoubleStruck = 6; - var BoldFraktur = 7; - var SansSerif = 8; - var BoldSansSerif = 9; - var SansSerifItalic = 10; - var SansSerifBoldItalic = 11; - var Monospace = 12; - var Initial = 13; - var Tailed = 14; - var Looped = 15; - var Stretched = 16; - - var greekUpperTheta = 0x03F4; - var holeGreekUpperTheta = 0x03A2; - var nabla = 0x2207; - var partialDifferential = 0x2202; - var greekUpperAlpha = 0x0391; - var greekUpperOmega = 0x03A9; - var greekLowerAlpha = 0x03B1; - var greekLowerOmega = 0x03C9; - var greekLunateEpsilonSymbol = 0x03F5; - var greekThetaSymbol = 0x03D1; - var greekKappaSymbol = 0x03F0; - var greekPhiSymbol = 0x03D5; - var greekRhoSymbol = 0x03F1; - var greekPiSymbol = 0x03D6; - var greekLetterDigamma = 0x03DC; - var greekSmallLetterDigamma = 0x03DD; - var mathBoldCapitalDigamma = 0x1D7CA; - var mathBoldSmallDigamma = 0x1D7CB; - - var latinSmallLetterDotlessI = 0x0131; - var latinSmallLetterDotlessJ = 0x0237; - - var mathItalicSmallDotlessI = 0x1D6A4; - var mathItalicSmallDotlessJ = 0x1D6A5; - - var digit0 = 0x30; - var digit9 = 0x39; - var upperA = 0x41; - var upperZ = 0x5A; - var smallA = 0x61; - var smallZ = 0x7A; - - var mathBoldUpperA = 0x1D400; - var mathItalicUpperA = 0x1D434; - var mathBoldSmallA = 0x1D41A; - var mathBoldUpperAlpha = 0x1D6A8; - var mathBoldSmallAlpha = 0x1D6C2; - var mathItalicUpperAlpha = 0x1D6E2; - var mathBoldDigitZero = 0x1D7CE; - var mathDoubleStruckZero = 0x1D7D8; - - var mathBoldUpperTheta = 0x1D6B9; - var mathBoldNabla = 0x1D6C1; - var mathBoldPartialDifferential = 0x1D6DB; - var mathBoldEpsilonSymbol = 0x1D6DC; - var mathBoldThetaSymbol = 0x1D6DD; - var mathBoldKappaSymbol = 0x1D6DE; - var mathBoldPhiSymbol = 0x1D6DF; - var mathBoldRhoSymbol = 0x1D6E0; - var mathBoldPiSymbol = 0x1D6E1; - - /* Exceptional characters with at most one possible transformation. */ - if (codePoint == holeGreekUpperTheta) - return codePoint; - if (codePoint == greekLetterDigamma) { - if (mathvariant == Bold) - return mathBoldCapitalDigamma; - return codePoint; - } - if (codePoint == greekSmallLetterDigamma) { - if (mathvariant == Bold) - return mathBoldSmallDigamma; - return codePoint; - } - if (codePoint == latinSmallLetterDotlessI) { - if (mathvariant == Italic) - return mathItalicSmallDotlessI; - return codePoint; - } - if (codePoint == latinSmallLetterDotlessJ) { - if (mathvariant == Italic) - return mathItalicSmallDotlessJ; - return codePoint; - } - - var baseChar, multiplier, map; - - /* Latin */ - if (upperA <= codePoint && codePoint <= upperZ || - smallA <= codePoint && codePoint <= smallZ) { - baseChar = codePoint <= upperZ ? codePoint - upperA : - mathBoldSmallA - mathBoldUpperA + codePoint - smallA; - multiplier = mathvariant; - if (mathvariant > Monospace) - return codePoint; // Latin doesn't support the Arabic mathvariants - var transformedChar = baseChar + mathBoldUpperA + - multiplier * (mathItalicUpperA - mathBoldUpperA); - map = { - 0x1D455: 0x210E, - 0x1D49D: 0x212C, - 0x1D4A0: 0x2130, - 0x1D4A1: 0x2131, - 0x1D4A3: 0x210B, - 0x1D4A4: 0x2110, - 0x1D4A7: 0x2112, - 0x1D4A8: 0x2133, - 0x1D4AD: 0x211B, - 0x1D4BA: 0x212F, - 0x1D4BC: 0x210A, - 0x1D4C4: 0x2134, - 0x1D506: 0x212D, - 0x1D50B: 0x210C, - 0x1D50C: 0x2111, - 0x1D515: 0x211C, - 0x1D51D: 0x2128, - 0x1D53A: 0x2102, - 0x1D53F: 0x210D, - 0x1D545: 0x2115, - 0x1D547: 0x2119, - 0x1D548: 0x211A, - 0x1D549: 0x211D, - 0x1D551: 0x2124 - }; - return map[transformedChar] ? map[transformedChar] : transformedChar; - } - - /* Digits */ - if (digit0 <= codePoint && codePoint <= digit9) { - baseChar = codePoint - digit0; - switch (mathvariant) { - case Bold: - multiplier = 0; - break; - case DoubleStruck: - multiplier = 1; - break; - case SansSerif: - multiplier = 2; - break; - case BoldSansSerif: - multiplier = 3; - break; - case Monospace: - multiplier = 4; - break; - default: - return codePoint; - } - return baseChar + multiplier * (mathDoubleStruckZero - mathBoldDigitZero) + - mathBoldDigitZero; - } - - // Arabic characters are defined within this range - if (0x0600 <= codePoint && codePoint <= 0x06FF) { - // The Arabic mathematical block is not continuous, nor does it have a - // monotonic mapping to the unencoded characters, requiring the use of a - // lookup table. - switch (mathvariant) { - case Initial: - map = { - 0x628: 0x1EE21, - 0x62A: 0x1EE35, - 0x62B: 0x1EE36, - 0x62C: 0x1EE22, - 0x62D: 0x1EE27, - 0x62E: 0x1EE37, - 0x633: 0x1EE2E, - 0x634: 0x1EE34, - 0x635: 0x1EE31, - 0x636: 0x1EE39, - 0x639: 0x1EE2F, - 0x63A: 0x1EE3B, - 0x641: 0x1EE30, - 0x642: 0x1EE32, - 0x643: 0x1EE2A, - 0x644: 0x1EE2B, - 0x645: 0x1EE2C, - 0x646: 0x1EE2D, - 0x647: 0x1EE24, - 0x64A: 0x1EE29 - }; - break; - case Tailed: - map = { - 0x62C: 0x1EE42, - 0x62D: 0x1EE47, - 0x62E: 0x1EE57, - 0x633: 0x1EE4E, - 0x634: 0x1EE54, - 0x635: 0x1EE51, - 0x636: 0x1EE59, - 0x639: 0x1EE4F, - 0x63A: 0x1EE5B, - 0x642: 0x1EE52, - 0x644: 0x1EE4B, - 0x646: 0x1EE4D, - 0x64A: 0x1EE49, - 0x66F: 0x1EE5F, - 0x6BA: 0x1EE5D - }; - break; - case Stretched: - map = { - 0x628: 0x1EE61, - 0x62A: 0x1EE75, - 0x62B: 0x1EE76, - 0x62C: 0x1EE62, - 0x62D: 0x1EE67, - 0x62E: 0x1EE77, - 0x633: 0x1EE6E, - 0x634: 0x1EE74, - 0x635: 0x1EE71, - 0x636: 0x1EE79, - 0x637: 0x1EE68, - 0x638: 0x1EE7A, - 0x639: 0x1EE6F, - 0x63A: 0x1EE7B, - 0x641: 0x1EE70, - 0x642: 0x1EE72, - 0x643: 0x1EE6A, - 0x645: 0x1EE6C, - 0x646: 0x1EE6D, - 0x647: 0x1EE64, - 0x64A: 0x1EE69, - 0x66E: 0x1EE7C, - 0x6A1: 0x1EE7E - }; - break; - case Looped: - map = { - 0x627: 0x1EE80, - 0x628: 0x1EE81, - 0x62A: 0x1EE95, - 0x62B: 0x1EE96, - 0x62C: 0x1EE82, - 0x62D: 0x1EE87, - 0x62E: 0x1EE97, - 0x62F: 0x1EE83, - 0x630: 0x1EE98, - 0x631: 0x1EE93, - 0x632: 0x1EE86, - 0x633: 0x1EE8E, - 0x634: 0x1EE94, - 0x635: 0x1EE91, - 0x636: 0x1EE99, - 0x637: 0x1EE88, - 0x638: 0x1EE9A, - 0x639: 0x1EE8F, - 0x63A: 0x1EE9B, - 0x641: 0x1EE90, - 0x642: 0x1EE92, - 0x644: 0x1EE8B, - 0x645: 0x1EE8C, - 0x646: 0x1EE8D, - 0x647: 0x1EE84, - 0x648: 0x1EE85, - 0x64A: 0x1EE89 - }; - break; - case DoubleStruck: - map = { - 0x628: 0x1EEA1, - 0x62A: 0x1EEB5, - 0x62B: 0x1EEB6, - 0x62C: 0x1EEA2, - 0x62D: 0x1EEA7, - 0x62E: 0x1EEB7, - 0x62F: 0x1EEA3, - 0x630: 0x1EEB8, - 0x631: 0x1EEB3, - 0x632: 0x1EEA6, - 0x633: 0x1EEAE, - 0x634: 0x1EEB4, - 0x635: 0x1EEB1, - 0x636: 0x1EEB9, - 0x637: 0x1EEA8, - 0x638: 0x1EEBA, - 0x639: 0x1EEAF, - 0x63A: 0x1EEBB, - 0x641: 0x1EEB0, - 0x642: 0x1EEB2, - 0x644: 0x1EEAB, - 0x645: 0x1EEAC, - 0x646: 0x1EEAD, - 0x648: 0x1EEA5, - 0x64A: 0x1EEA9 - }; - break; - default: - return codePoint; - } - return map[codePoint] ? map[codePoint] : codePoint; - } - - // Greek - if (greekUpperAlpha <= codePoint && codePoint <= greekUpperOmega) { - baseChar = codePoint - greekUpperAlpha; - } else if (greekLowerAlpha <= codePoint && codePoint <= greekLowerOmega) { - baseChar = mathBoldSmallAlpha - mathBoldUpperAlpha + codePoint - greekLowerAlpha; - } else { - switch (codePoint) { - case greekUpperTheta: - baseChar = mathBoldUpperTheta - mathBoldUpperAlpha; - break; - case nabla: - baseChar = mathBoldNabla - mathBoldUpperAlpha; - break; - case partialDifferential: - baseChar = mathBoldPartialDifferential - mathBoldUpperAlpha; - break; - case greekLunateEpsilonSymbol: - baseChar = mathBoldEpsilonSymbol - mathBoldUpperAlpha; - break; - case greekThetaSymbol: - baseChar = mathBoldThetaSymbol - mathBoldUpperAlpha; - break; - case greekKappaSymbol: - baseChar = mathBoldKappaSymbol - mathBoldUpperAlpha; - break; - case greekPhiSymbol: - baseChar = mathBoldPhiSymbol - mathBoldUpperAlpha; - break; - case greekRhoSymbol: - baseChar = mathBoldRhoSymbol - mathBoldUpperAlpha; - break; - case greekPiSymbol: - baseChar = mathBoldPiSymbol - mathBoldUpperAlpha; - break; - default: - return codePoint; - } - } - - switch (mathvariant) { - case Bold: - multiplier = 0; - break; - case Italic: - multiplier = 1; - break; - case BoldItalic: - multiplier = 2; - break; - case BoldSansSerif: - multiplier = 3; - break; - case SansSerifBoldItalic: - multiplier = 4; - break; - default: - // This mathvariant isn't defined for Greek or is otherwise normal. - return codePoint; - } - - return baseChar + mathBoldUpperAlpha + multiplier * (mathItalicUpperAlpha - mathBoldUpperAlpha); -} - -function applyMathVariant(aToken, aMathVariant) { - if (aMathVariant === "normal") - return; - var content = aToken["content"]; - var transformedText = ""; - for (var i = 0; i < content.length; i++) { - var c = content["codePointAt"](i); - if (c > 0xFFFF) { - transformedText += content[i]; i++; - transformedText += content[i]; - } else { - transformedText += String["fromCodePoint"]( - applyMathVariantToCharacter(c, aMathVariant) - ); - } - } - aToken["content"] = transformedText; -} - -function isToken(aTree) { - return ["mi", "mn", "mo", "mtext", "ms"].indexOf(aTree["tag"]) !== -1; -} - -function isSingleCharMi(aTree) { - if (aTree["tag"] !== "mi") - return false; - var content = aTree["content"]; - var c = content["codePointAt"](0); - return content.length === 1 && c <= 0xFFFF || - content.length === 2 && c > 0xFFFF; -} - -function isTokenAttribute(aAttribute) { - return ["mathcolor", "mathbackground", "mathvariant"].indexOf(aAttribute) !== -1; -} - -function applyTokenAttributes(aChildren, aAttributes) { - var allAttributesAppliedToAllChildren = true; - for (var name in aAttributes) { - // Only consider mstyle attributes that apply to token elements. - if (!isTokenAttribute(name)) { - allAttributesAppliedToAllChildren = false; - continue; - } - // In general, keep mstyle element if there are multiple children. - if (name !== "mathvariant" && aChildren.length != 1) { - allAttributesAppliedToAllChildren = false; - continue; - } - aChildren.forEach(function(child) { - if (!isToken(child)) { - allAttributesAppliedToAllChildren = false; - return; - } - if (!child["attributes"]) - child["attributes"] = {}; - if (child["attributes"][name]) - return; - if (name === "mathvariant") { - // Transform the text instead of using a mathvariant attribute. - // Explicit "normal" attribute is only needed on single-char 's. - if (aAttributes[name] !== "normal" || !isSingleCharMi(child)) - applyMathVariant(child, aAttributes[name]) - else - child["attributes"][name] = aAttributes[name]; - } else { - // Apply the token attribute to the child. - child["attributes"][name] = aAttributes[name]; - } - }); - } - return allAttributesAppliedToAllChildren; -} - -/* FIXME: try to restore the operator grouping when compoundTermList does not - contain any fences. - https://github.com/fred-wang/TeXZilla/issues/9 */ -function newMrow(aChildren, aTag, aAttributes) { - aTag = aTag || "mrow"; - if (aTag === "mstyle") { - // Mstyle with one mrow child that does not have any attribute. - if (aChildren.length == 1 && - aChildren[0]["tag"] === "mrow" && !aChildren[0]["attributes"]) - return newMrow(aChildren[0]["content"], aTag, aAttributes); - - // Try an apply all the attributes to chidren and replace mstyle with mrow. - if (applyTokenAttributes(aChildren, aAttributes)) - return newMrow(aChildren); - } - // Mrow with one child and no attributes: return the child. - if (aChildren.length == 1 && aTag === "mrow" && !aAttributes) - return aChildren[0]; - return newTag(aTag, aChildren, aAttributes); -} - -function newMath(aChildren, aDisplay, aRTL, aTeX) -{ - return newTag("math", [ - newTag("semantics", [ - newMrow(aChildren), - newTag("annotation", escapeText(aTeX), {"encoding": "TeX"}) - ]) - ], { - "xmlns": MathMLNameSpace, - "display": aDisplay ? "block" : undefined, - "dir": aRTL ? "rtl" : undefined - }); -} - -function getTeXSourceInternal(aMathMLElement) { - var child; - if (!aMathMLElement || - aMathMLElement.namespaceURI !== MathMLNameSpace) { - return null; - } - - if (aMathMLElement.tagName === "semantics") { - // Note: we can't use aMathMLElement.children on WebKit/Blink because of - // https://bugs.webkit.org/show_bug.cgi?id=109556. - for (child = aMathMLElement.firstElementChild; child; - child = child.nextElementSibling) { - if (child.namespaceURI === MathMLNameSpace && - child.localName === "annotation" && - TeXMimeTypes.indexOf(child.getAttribute("encoding")) !== -1) { - return child.textContent; - } - } - } else if (aMathMLElement.childElementCount === 1) { - return getTeXSourceInternal(aMathMLElement.firstElementChild); - } - - return null; -} - -try { - // Try to create a DOM Parser object if it exists (e.g. in a Web page, - // in a chrome script running in a window etc) - parser.mDOMParser = new DOMParser(); -} catch (e) { - // Make the DOMParser throw an exception if used. - parser.mDOMParser = { - parseFromString: function() { - throw "DOMParser undefined. Did you call TeXZilla.setDOMParser?"; - } - }; -} - -parser.setDOMParser = function(aDOMParser) -{ - this.mDOMParser = aDOMParser; -} - -try { - // Try to create a XMLSerializer object if it exists (e.g. in a Web page, - // in a chrome script running in a window etc) - parser.mXMLSerializer = new XMLSerializer(); -} catch (e) { - // Make the XMLSerializer throw an exception if used. - parser.mXMLSerializer = { - serializeToString: function() { - throw "XMLSerializer undefined. Did you call TeXZilla.setXMLSerializer?"; - } - }; -} - -parser.setXMLSerializer = function(aXMLSerializer) -{ - this.mXMLSerializer = aXMLSerializer; -} - -parser.parseMathMLDocument = function (aString) { - // Parse the string into a MathML document and return the root. - return this.mDOMParser. - parseFromString(aString, "application/xml").documentElement; -} - -parser.setSafeMode = function(aEnable) -{ - this.yy.mSafeMode = aEnable; -} - -parser.setItexIdentifierMode = function(aEnable) -{ - this.yy.mItexIdentifierMode = aEnable; -} - -parser.getTeXSource = function(aMathMLElement) { - if (typeof aMathMLElement === "string") { - aMathMLElement = this.parseMathMLDocument(aMathMLElement); - } - - return getTeXSourceInternal(aMathMLElement); -} - -parser.toMathMLString = function(aTeX, aDisplay, aRTL, aThrowExceptionOnError) { - var output, mathml; - /* Parse the TeX source and get the main MathML node. */ - try { - output = this.parse("\\(" + aTeX + "\\)"); - if (aRTL) { - /* Set the RTL mode if specified. */ - output = output.replace(/^ element. */ - return this.parseMathMLDocument(this.toMathMLString(aTeX, aDisplay, aRTL, aThrowExceptionOnError)); -} - -function escapeHTML(aString) -{ - var rv = "", code1, code2; - for (var i = 0; i < aString.length; i++) { - var code1 = aString.charCodeAt(i); - if (code1 < 0x80) { - rv += aString.charAt(i); - continue; - } - if (0xD800 <= code1 && code1 <= 0xDBFF) { - i++; - code2 = aString.charCodeAt(i); - rv += "&#x" + - ((code1-0xD800)*0x400 + code2-0xDC00 + 0x10000).toString(16) + ";"; - continue; - } - rv += "&#x" + code1.toString(16) + ";"; - } - return rv; -} - -parser.toImage = function(aTeX, aRTL, aRoundToPowerOfTwo, aSize, aDocument) { - var math, el, box, svgWidth, svgHeight, svg, image; - - // Set default values. - if (aSize === undefined) { - aSize = 64; - } - if (aDocument === undefined) { - aDocument = window.document; - } - - // Create the MathML element. - math = this.toMathML(aTeX, true, aRTL); - math.setAttribute("mathsize", aSize + "px"); - - // Temporarily insert the MathML element in the document to measure it. - el = document.createElement("div"); - el.style.visibility = "hidden"; - el.style.position = "absolute"; - el.appendChild(math); - aDocument.body.appendChild(el); - box = math.getBoundingClientRect(); - aDocument.body.removeChild(el); - el.removeChild(math); - - // Round up the computed sizes. - if (aRoundToPowerOfTwo) { - // Harmony's Math.log2() is not supported by all rendering engines and is - // removed by closure-compiler, so we use Math.log() / Math.LN2 instead. - svgWidth = Math.pow(2, Math.ceil(Math.log(box.width) / Math.LN2)); - svgHeight = Math.pow(2, Math.ceil(Math.log(box.height) / Math.LN2)); - } else { - svgWidth = Math.ceil(box.width); - svgHeight = Math.ceil(box.height); - } - - // Embed the MathML in an SVG element. - svg = document.createElementNS(SVGNameSpace, "svg"); - svg.setAttribute("width", svgWidth + "px"); - svg.setAttribute("height", svgHeight + "px"); - el = document.createElementNS(SVGNameSpace, "g"); - el.setAttribute("transform", "translate(" + - (svgWidth - box.width) / 2.0 + "," + (svgHeight - box.height) / 2.0 + ")"); - svg.appendChild(el); - el = document.createElementNS(SVGNameSpace, "foreignObject"); - el.setAttribute("width", box.width); - el.setAttribute("height", box.height); - el.appendChild(math); - svg.firstChild.appendChild(el); - - // Create the image element. - image = new Image(); - image.src = "data:image/svg+xml;base64," + - window.btoa(escapeHTML(this.mXMLSerializer.serializeToString(svg))); - image.width = svgWidth; - image.height = svgHeight; - image.alt = escapeText(aTeX); - - return image; -} - -parser.filterString = function(aString, aThrowExceptionOnError) { - try { - return this.parse(aString); - } catch (e) { - if (aThrowExceptionOnError) { - throw e; - } - return aString; - } -} - -parser.filterElement = function(aElement, aThrowExceptionOnError) { - var root, child, node; - for (var node = aElement.firstChild; node; node = node.nextSibling) { - switch(node.nodeType) { - case 1: // Node.ELEMENT_NODE - this.filterElement(node, aThrowExceptionOnError); - break; - case 3: // Node.TEXT_NODE - this.yy.escapeXML = true; - root = this.mDOMParser.parseFromString("" + - TeXZilla.filterString(node.data, aThrowExceptionOnError) + - "", "application/xml").documentElement; - this.yy.escapeXML = false; - while (child = root.firstChild) { - aElement.insertBefore(root.removeChild(child), node); - } - child = node.previousSibling; - aElement.removeChild(node); node = child; - break; - default: - } - } -} - -function parseError(aString, aHash) { - // We delete the last line, which contains token names that are obscure - // to the users. See issue #16 - throw new Error(aString.replace(/\nExpecting [^\n]*$/, "\n")); -} - -/* generated by jison-lex 0.3.4 */ -var lexer = (function(){ -var lexer = ({ - -EOF:1, - -parseError:function parseError(str, hash) { - if (this.yy.parser) { - this.yy.parser.parseError(str, hash); - } else { - throw new Error(str); - } - }, - -// resets the lexer, sets new input -setInput:function (input, yy) { - this.yy = yy || this.yy || {}; - this._input = input; - this._more = this._backtrack = this.done = false; - this.yylineno = this.yyleng = 0; - this.yytext = this.matched = this.match = ''; - this.conditionStack = ['INITIAL']; - this.yylloc = { - first_line: 1, - first_column: 0, - last_line: 1, - last_column: 0 - }; - if (this.options.ranges) { - this.yylloc.range = [0,0]; - } - this.offset = 0; - return this; - }, - -// consumes and returns one char from the input -input:function () { - var ch = this._input[0]; - this.yytext += ch; - this.yyleng++; - this.offset++; - this.match += ch; - this.matched += ch; - var lines = ch.match(/(?:\r\n?|\n).*/g); - if (lines) { - this.yylineno++; - this.yylloc.last_line++; - } else { - this.yylloc.last_column++; - } - if (this.options.ranges) { - this.yylloc.range[1]++; - } - - this._input = this._input.slice(1); - return ch; - }, - -// unshifts one char (or a string) into the input -unput:function (ch) { - var len = ch.length; - var lines = ch.split(/(?:\r\n?|\n)/g); - - this._input = ch + this._input; - this.yytext = this.yytext.substr(0, this.yytext.length - len); - //this.yyleng -= len; - this.offset -= len; - var oldLines = this.match.split(/(?:\r\n?|\n)/g); - this.match = this.match.substr(0, this.match.length - 1); - this.matched = this.matched.substr(0, this.matched.length - 1); - - if (lines.length - 1) { - this.yylineno -= lines.length - 1; - } - var r = this.yylloc.range; - - this.yylloc = { - first_line: this.yylloc.first_line, - last_line: this.yylineno + 1, - first_column: this.yylloc.first_column, - last_column: lines ? - (lines.length === oldLines.length ? this.yylloc.first_column : 0) - + oldLines[oldLines.length - lines.length].length - lines[0].length : - this.yylloc.first_column - len - }; - - if (this.options.ranges) { - this.yylloc.range = [r[0], r[0] + this.yyleng - len]; - } - this.yyleng = this.yytext.length; - return this; - }, - -// When called from action, caches matched text and appends it on next action -more:function () { - this._more = true; - return this; - }, - -// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead. -reject:function () { - if (this.options.backtrack_lexer) { - this._backtrack = true; - } else { - return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), { - text: "", - token: null, - line: this.yylineno - }); - - } - return this; - }, - -// retain first n characters of the match -less:function (n) { - this.unput(this.match.slice(n)); - }, - -// displays already matched input, i.e. for error messages -pastInput:function () { - var past = this.matched.substr(0, this.matched.length - this.match.length); - return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); - }, - -// displays upcoming input, i.e. for error messages -upcomingInput:function () { - var next = this.match; - if (next.length < 20) { - next += this._input.substr(0, 20-next.length); - } - return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); - }, - -// displays the character position where the lexing error occurred, i.e. for error messages -showPosition:function () { - var pre = this.pastInput(); - var c = new Array(pre.length + 1).join("-"); - return pre + this.upcomingInput() + "\n" + c + "^"; - }, - -// test the lexed token: return FALSE when not a match, otherwise return token -test_match:function(match, indexed_rule) { - var token, - lines, - backup; - - if (this.options.backtrack_lexer) { - // save context - backup = { - yylineno: this.yylineno, - yylloc: { - first_line: this.yylloc.first_line, - last_line: this.last_line, - first_column: this.yylloc.first_column, - last_column: this.yylloc.last_column - }, - yytext: this.yytext, - match: this.match, - matches: this.matches, - matched: this.matched, - yyleng: this.yyleng, - offset: this.offset, - _more: this._more, - _input: this._input, - yy: this.yy, - conditionStack: this.conditionStack.slice(0), - done: this.done - }; - if (this.options.ranges) { - backup.yylloc.range = this.yylloc.range.slice(0); - } - } - - lines = match[0].match(/(?:\r\n?|\n).*/g); - if (lines) { - this.yylineno += lines.length; - } - this.yylloc = { - first_line: this.yylloc.last_line, - last_line: this.yylineno + 1, - first_column: this.yylloc.last_column, - last_column: lines ? - lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : - this.yylloc.last_column + match[0].length - }; - this.yytext += match[0]; - this.match += match[0]; - this.matches = match; - this.yyleng = this.yytext.length; - if (this.options.ranges) { - this.yylloc.range = [this.offset, this.offset += this.yyleng]; - } - this._more = false; - this._backtrack = false; - this._input = this._input.slice(match[0].length); - this.matched += match[0]; - token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]); - if (this.done && this._input) { - this.done = false; - } - if (token) { - return token; - } else if (this._backtrack) { - // recover context - for (var k in backup) { - this[k] = backup[k]; - } - return false; // rule action called reject() implying the next rule should be tested instead. - } - return false; - }, - -// return next match in input -next:function () { - if (this.done) { - return this.EOF; - } - if (!this._input) { - this.done = true; - } - - var token, - match, - tempMatch, - index; - if (!this._more) { - this.yytext = ''; - this.match = ''; - } - var rules = this._currentRules(); - for (var i = 0; i < rules.length; i++) { - tempMatch = this._input.match(this.rules[rules[i]]); - if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { - match = tempMatch; - index = i; - if (this.options.backtrack_lexer) { - token = this.test_match(tempMatch, rules[i]); - if (token !== false) { - return token; - } else if (this._backtrack) { - match = false; - continue; // rule action called reject() implying a rule MISmatch. - } else { - // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) - return false; - } - } else if (!this.options.flex) { - break; - } - } - } - if (match) { - token = this.test_match(match, rules[index]); - if (token !== false) { - return token; - } - // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace) - return false; - } - if (this._input === "") { - return this.EOF; - } else { - return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { - text: "", - token: null, - line: this.yylineno - }); - } - }, - -// return next match that has a token -lex:function lex () { - var r = this.next(); - if (r) { - return r; - } else { - return this.lex(); - } - }, - -// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack) -begin:function begin (condition) { - this.conditionStack.push(condition); - }, - -// pop the previously active lexer condition state off the condition stack -popState:function popState () { - var n = this.conditionStack.length - 1; - if (n > 0) { - return this.conditionStack.pop(); - } else { - return this.conditionStack[0]; - } - }, - -// produce the lexer rule set which is active for the currently active lexer condition state -_currentRules:function _currentRules () { - if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) { - return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; - } else { - return this.conditions["INITIAL"].rules; - } - }, - -// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available -topState:function topState (n) { - n = this.conditionStack.length - 1 - Math.abs(n || 0); - if (n >= 0) { - return this.conditionStack[n]; - } else { - return "INITIAL"; - } - }, - -// alias for begin(condition) -pushState:function pushState (condition) { - this.begin(condition); - }, - -// return the number of states currently on the stack -stateStackSize:function stateStackSize() { - return this.conditionStack.length; - }, -options: {}, -performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { -var YYSTATE=YY_START; -switch($avoiding_name_collisions) { -case 0: this.unput(yy_.yytext); this.pushState("DOCUMENT"); -break; -case 1: - this.pushState("MATH" + (0+!!yy.mItexIdentifierMode)); - yy.startMath = this.matched.length; - return "STARTMATH" + (2 * (yy_.yytext[0] == "$") + - (yy_.yytext[1] == "$" || yy_.yytext[1] == "[")); - -break; -case 2: this.popState(); return "EOF"; -break; -case 3: yy_.yytext = yy_.yytext[1]; return "TEXT"; -break; -case 4: - if (yy.escapeXML) { - yy_.yytext = escapeText(yy_.yytext); - } - return "TEXT"; - -break; -case 5:return "TEXT"; -break; -case 6: this.popState(); return "["; -break; -case 7: this.unput(yy_.yytext); this.popState(); this.popState(); -break; -case 8: return "TEXTOPTARG"; -break; -case 9: this.popState(); return "]"; -break; -case 10:return "{"; -break; -case 11:return "TEXTARG"; -break; -case 12: this.popState(); return "}"; -break; -case 13: this.popState(); return "]"; -break; -case 14:/* skip whitespace */ -break; -case 15: - this.popState(); - yy.endMath = this.matched.length - this.match.length; - yy.tex = this.matched.substring(yy.startMath, yy.endMath); - return "ENDMATH" + (2 * (yy_.yytext[0] == "$") + - (yy_.yytext[1] == "$" || yy_.yytext[1] == "]")); - -break; -case 16:return "{"; -break; -case 17:return "}"; -break; -case 18:return "^"; -break; -case 19:return "_"; -break; -case 20:return "."; -break; -case 21:return "COLSEP"; -break; -case 22:return "ROWSEP" -break; -case 23:return "NUM"; -break; -case 24: return "A"; -break; -case 25: yy_.yytext = "\u0396"; return "AIUG"; -break; -case 26: yy_.yytext = "\u03B6"; return "AILG"; -break; -case 27: this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yy_.yytext = "\u21CC"; return "XARROW"; -break; -case 28: this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yy_.yytext = "\u21D2"; return "XARROW"; -break; -case 29: this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yy_.yytext = "\u2192"; return "XARROW"; -break; -case 30: this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yy_.yytext = "\u21A6"; return "XARROW"; -break; -case 31: this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yy_.yytext = "\u21CB"; return "XARROW"; -break; -case 32: this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yy_.yytext = "\u21D4"; return "XARROW"; -break; -case 33: this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yy_.yytext = "\u2194"; return "XARROW"; -break; -case 34: this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yy_.yytext = "\u21D0"; return "XARROW"; -break; -case 35: this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yy_.yytext = "\u2190"; return "XARROW"; -break; -case 36: yy_.yytext = "\u039E"; return "AIUG"; -break; -case 37: yy_.yytext = "\u03BE"; return "AILG"; -break; -case 38: this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yy_.yytext = "\u21AA"; return "XARROW"; -break; -case 39: this.pushState("OPTARG"); this.pushState("TRYOPTARG"); yy_.yytext = "\u21A9"; return "XARROW"; -break; -case 40: yy_.yytext = "\u2240"; return "OP"; -break; -case 41: yy_.yytext = "\u2118"; return "A"; -break; -case 42: yy_.yytext = "\u21C0"; return "ACCENT"; -break; -case 43: yy_.yytext = "\u02DC"; return "ACCENT"; -break; -case 44: yy_.yytext = "\u005E"; return "ACCENT"; -break; -case 45: yy_.yytext = "\u02C7"; return "ACCENT"; -break; -case 46: yy_.yytext = "\u00AF"; return "ACCENT"; -break; -case 47: yy_.yytext = "\u2259"; return "OP"; -break; -case 48: yy_.yytext = "\u22C0"; return "OPM"; -break; -case 49: yy_.yytext = "\u2227"; return "OP"; -break; -case 50: yy_.yytext = "\u2980"; return "OPFS"; -break; -case 51: yy_.yytext = "\u22AA"; return "OP"; -break; -case 52: yy_.yytext = "\u2016"; return "OPFS"; -break; -case 53: yy_.yytext = "\u007C"; return "OPFS"; -break; -case 54: yy_.yytext = "\u22BB"; return "OP"; -break; -case 55: yy_.yytext = "\u22C1"; return "OPM"; -break; -case 56: yy_.yytext = "\u2228"; return "OP"; -break; -case 57: yy_.yytext = "\u21C0"; return "ACCENTNS"; -break; -case 58: yy_.yytext = "\u22EE"; return "OP"; -break; -case 59: yy_.yytext = "\u22AB"; return "OP"; -break; -case 60: yy_.yytext = "\u22A9"; return "OP"; -break; -case 61: yy_.yytext = "\u22A8"; return "OP"; -break; -case 62: yy_.yytext = "\u22A2"; return "OP"; -break; -case 63: yy_.yytext = "\u2AEB"; return "OP"; -break; -case 64: yy_.yytext = "\u22B3"; return "OP"; -break; -case 65: yy_.yytext = "\u22B2"; return "OP"; -break; -case 66: yy_.yytext = "\u25B5"; return "OP"; -break; -case 67: yy_.yytext = "\u03D1"; return "AILG"; -break; -case 68: yy_.yytext = "\u2ACC\uFE00"; return "OP"; -break; -case 69: yy_.yytext = "\u228B\uFE00"; return "OP"; -break; -case 70: yy_.yytext = "\u2ACB\uFE00"; return "OP"; -break; -case 71: yy_.yytext = "\u228A\uFE00"; return "OP"; -break; -case 72: yy_.yytext = "\u228A\uFE00"; return "OP"; -break; -case 73: yy_.yytext = "\u03C2"; return "A"; -break; -case 74: yy_.yytext = "\u03F1"; return "AILG"; -break; -case 75: yy_.yytext = "\u221D"; return "OP"; -break; -case 76: yy_.yytext = "\u03D6"; return "AILG"; -break; -case 77: yy_.yytext = "\u03C6"; return "AILG"; -break; -case 78: yy_.yytext = "\u2205"; return "A"; -break; -case 79: yy_.yytext = "\u03F0"; return "AILG"; -break; -case 80: yy_.yytext = "\u03B5"; return "AILG"; -break; -case 81: yy_.yytext = "\u290A"; return "OPS"; -break; -case 82: yy_.yytext = "\u21C8"; return "OPS"; -break; -case 83: yy_.yytext = "\u03D2"; return "A"; -break; -case 84: yy_.yytext = "\u03C5"; return "AILG"; -break; -case 85: yy_.yytext = "\u03D2"; return "A"; -break; -case 86: yy_.yytext = "\u228E"; return "OP"; -break; -case 87: yy_.yytext = "\u2A1B"; return "OP"; -break; -case 88: yy_.yytext = "\u21BF"; return "OPS"; -break; -case 89: yy_.yytext = "\u21BE"; return "OPS"; -break; -case 90: yy_.yytext = "\u21D5"; return "OPS"; -break; -case 91: yy_.yytext = "\u2195"; return "OPS"; -break; -case 92: yy_.yytext = "\u2195"; return "OPS"; -break; -case 93: yy_.yytext = "\u21D1"; return "OPS"; -break; -case 94: yy_.yytext = "\u2191"; return "OPS"; -break; -case 95: yy_.yytext = "\u2191"; return "OPS"; -break; -case 96: yy_.yytext = "\u22B5"; return "OP"; -break; -case 97: yy_.yytext = "\u22B4"; return "OP"; -break; -case 98: yy_.yytext = "\u22C3"; return "OPM"; -break; -case 99: yy_.yytext = "\u222A"; return "OP"; -break; -case 100:return "UNDERSET"; -break; -case 101:return "UNDEROVERSET"; -break; -case 102:return "UNDERLINE"; -break; -case 103:return "UNDERBRACE"; -break; -case 104: yy_.yytext = "\u22F0"; return "OP"; -break; -case 105:return "OP"; -break; -case 106:return "OP"; -break; -case 107:return "OP"; -break; -case 108:return "OP"; -break; -case 109:return "OP"; -break; -case 110:return "OP"; -break; -case 111:return "OP"; -break; -case 112:return "OP"; -break; -case 113:return "OP"; -break; -case 114:return "OP"; -break; -case 115:return "OP"; -break; -case 116:return "OP"; -break; -case 117:return "OP"; -break; -case 118:return "OP"; -break; -case 119:return "OP"; -break; -case 120:return "OP"; -break; -case 121:return "OP"; -break; -case 122:return "OP"; -break; -case 123:return "OP"; -break; -case 124:return "OP"; -break; -case 125:return "OP"; -break; -case 126:return "OP"; -break; -case 127:return "OP"; -break; -case 128:return "OP"; -break; -case 129:return "OP"; -break; -case 130:return "OP"; -break; -case 131:return "OP"; -break; -case 132:return "OP"; -break; -case 133:return "OP"; -break; -case 134:return "OP"; -break; -case 135:return "OP"; -break; -case 136:return "OP"; -break; -case 137:return "OP"; -break; -case 138:return "OPFS"; -break; -case 139:return "OPFS"; -break; -case 140:return "OP"; -break; -case 141:return "OP"; -break; -case 142:return "OP"; -break; -case 143:return "OP"; -break; -case 144:return "OP"; -break; -case 145:return "OP"; -break; -case 146:return "OP"; -break; -case 147:return "OP"; -break; -case 148:return "OP"; -break; -case 149:return "OP"; -break; -case 150:return "OP"; -break; -case 151:return "OP"; -break; -case 152:return "OP"; -break; -case 153:return "OP"; -break; -case 154:return "OP"; -break; -case 155:return "OP"; -break; -case 156:return "OP"; -break; -case 157:return "OP"; -break; -case 158:return "OP"; -break; -case 159:return "OP"; -break; -case 160:return "OP"; -break; -case 161: yy_.yytext = "\u2916"; return "OP"; -break; -case 162: yy_.yytext = "\u21A0"; return "OPS"; -break; -case 163: yy_.yytext = "\u219E"; return "OPS"; -break; -case 164: yy_.yytext = "\u222D"; return "OP"; -break; -case 165: yy_.yytext = "\u22B5"; return "OP"; -break; -case 166: yy_.yytext = "\u25B9"; return "OP"; -break; -case 167: yy_.yytext = "\u225C"; return "OP"; -break; -case 168: yy_.yytext = "\u22B4"; return "OP"; -break; -case 169: yy_.yytext = "\u25C3"; return "OP"; -break; -case 170: yy_.yytext = "\u25BF"; return "OP"; -break; -case 171: yy_.yytext = "\u25B5"; return "OP"; -break; -case 172: yy_.yytext = "\u292A"; return "OP"; -break; -case 173: yy_.yytext = "\u2929"; return "OP"; -break; -case 174: yy_.yytext = "\u22A4"; return "OP"; -break; -case 175: this.pushState("TEXTARG"); return "TOOLTIP"; -break; -case 176: yy_.yytext = "\u2927"; return "OP"; -break; -case 177: return "TOGGLE"; -break; -case 178: yy_.yytext = "\u2928"; return "OP"; -break; -case 179: yy_.yytext = "\u2192"; return "OPS"; -break; -case 180: yy_.yytext = "\u22A0"; return "OP"; -break; -case 181: yy_.yytext = "\u00D7"; return "OP"; -break; -case 182: yy_.yytext = "\u02DC"; return "ACCENTNS"; -break; -case 183:return "THINSPACE"; -break; -case 184:return "THICKSPACE"; -break; -case 185: yy_.yytext = "\u223C"; return "OP"; -break; -case 186: yy_.yytext = "\u2248"; return "OP"; -break; -case 187: yy_.yytext = "\u0398"; return "AIUG"; -break; -case 188: yy_.yytext = "\u03B8"; return "AILG"; -break; -case 189: yy_.yytext = "\u2234"; return "OP"; -break; -case 190:return "TFRAC"; -break; -case 191:return "TEXTSTYLE"; -break; -case 192:return "TEXTSIZE"; -break; -case 193: yy_.yytext = "\u201D"; return "OPF"; -break; -case 194: yy_.yytext = "\u201C"; return "OPF"; -break; -case 195: yy_.yytext = "\u007E"; return "OPS"; -break; -case 196: yy_.yytext = "\u0060"; return "OP"; -break; -case 197: yy_.yytext = "\u005E"; return "OPS"; -break; -case 198: yy_.yytext = "\u00B4"; return "OP"; -break; -case 199: this.begin("TEXTARG"); return "MTEXT"; -break; -case 200:return "TENSOR"; -break; -case 201:return "TBINOM"; -break; -case 202: yy_.yytext = "\u03A4"; return "AIUG"; -break; -case 203: yy_.yytext = "\u03C4"; return "AILG"; -break; -case 204: yy_.yytext = "\u21D9"; return "OPS"; -break; -case 205: yy_.yytext = "\u2199"; return "OPS"; -break; -case 206: yy_.yytext = "\u21D9"; return "OPS"; -break; -case 207: yy_.yytext = "\u2199"; return "OPS"; -break; -case 208: yy_.yytext = "\u221A"; return "OPS"; -break; -case 209: yy_.yytext = "\u2ACC"; return "OP"; -break; -case 210: yy_.yytext = "\u228B"; return "OP"; -break; -case 211: yy_.yytext = "\u2AC6"; return "OP"; -break; -case 212: yy_.yytext = "\u2287"; return "OP"; -break; -case 213: yy_.yytext = "\u22D1"; return "OP"; -break; -case 214: yy_.yytext = "\u2283"; return "OP"; -break; -case 215: yy_.yytext = "\u2211"; return "OPM"; -break; -case 216: yy_.yytext = "\u227F"; return "OP"; -break; -case 217: yy_.yytext = "\u22E9"; return "OP"; -break; -case 218: yy_.yytext = "\u2AB6"; return "OP"; -break; -case 219: yy_.yytext = "\u2ABA"; return "OP"; -break; -case 220: yy_.yytext = "\u2AB0"; return "OP"; -break; -case 221: yy_.yytext = "\u227D"; return "OP"; -break; -case 222: yy_.yytext = "\u2AB8"; return "OP"; -break; -case 223: yy_.yytext = "\u227B"; return "OP"; -break; -case 224:return "SUBSTACK"; -break; -case 225: yy_.yytext = "\u2ACB"; return "OP"; -break; -case 226: yy_.yytext = "\u228A"; return "OP"; -break; -case 227: yy_.yytext = "\u2AC5"; return "OP"; -break; -case 228: yy_.yytext = "\u2286"; return "OP"; -break; -case 229: yy_.yytext = "\u22D0"; return "OP"; -break; -case 230: yy_.yytext = "\u2282"; return "OP"; -break; -case 231: this.pushState("TEXTARG"); return "STATUSLINE"; -break; -case 232: yy_.yytext = "\u22C6"; return "OP"; -break; -case 233:return "OVERSET"; -break; -case 234: yy_.yytext = "\u2AFD"; return "OP"; -break; -case 235: yy_.yytext = "\u25A1"; return "OP"; -break; -case 236: yy_.yytext = "\u2292"; return "OP"; -break; -case 237: yy_.yytext = "\u2290"; return "OP"; -break; -case 238: yy_.yytext = "\u2291"; return "OP"; -break; -case 239: yy_.yytext = "\u228F"; return "OP"; -break; -case 240: this.pushState("OPTARG"); this.pushState("TRYOPTARG"); return "SQRT"; -break; -case 241: yy_.yytext = "\u2294"; return "OP"; -break; -case 242: yy_.yytext = "\u2293"; return "OP"; -break; -case 243: yy_.yytext = "\u2222"; return "OP"; -break; -case 244: yy_.yytext = "\u2660"; return "OP"; -break; -case 245: this.pushState("TEXTARG"); this.pushState("TEXTARG"); this.pushState("TEXTARG"); return "SPACE"; -break; -case 246: yy_.yytext = "\u2323"; return "OP"; -break; -case 247: yy_.yytext = "\u2323"; return "OP"; -break; -case 248: yy_.yytext = "\u2216"; return "OP"; -break; -case 249: yy_.yytext = "\u2322"; return "OP"; -break; -case 250:return "SLASH"; -break; -case 251: yy_.yytext = "\u2243"; return "OP"; -break; -case 252: yy_.yytext = "\u223C"; return "OP"; -break; -case 253: yy_.yytext = "\u03A3"; return "AIUG"; -break; -case 254: yy_.yytext = "\u03C3"; return "AILG"; -break; -case 255: yy_.yytext = "\u29E2"; return "OP"; -break; -case 256: yy_.yytext = "\u2225"; return "OP"; -break; -case 257: yy_.yytext = "\u2223"; return "OP"; -break; -case 258: yy_.yytext = "\u266F"; return "OP"; -break; -case 259: yy_.yytext = "\u2216"; return "OP"; -break; -case 260: yy_.yytext = "\u292D"; return "OP"; -break; -case 261: yy_.yytext = "\u21D8"; return "OPS"; -break; -case 262: yy_.yytext = "\u2198"; return "OPS"; -break; -case 263: yy_.yytext = "\u21D8"; return "OPS"; -break; -case 264: yy_.yytext = "\u2198"; return "OPS"; -break; -case 265:return "SCRIPTSIZE"; -break; -case 266:return "SCRIPTSCRIPTSIZE"; -break; -case 267: yy_.yytext = "\u22CA"; return "OP"; -break; -case 268: yy_.yytext = "\u21B1"; return "OPS"; -break; -case 269: yy_.yytext = "\u21DB"; return "OPS"; -break; -case 270: yy_.yytext = "\u27EB"; return "OPFS"; -break; -case 271: yy_.yytext = "\u2019"; return "OPF"; -break; -case 272: this.begin("TEXTARG"); return "ROWSPAN"; -break; -case 273:return "ROWOPTS"; -break; -case 274: this.pushState("TEXTARG"); return "ROWLINES"; -break; -case 275: this.begin("TEXTARG"); return "ROWALIGN"; -break; -case 276:return "ROOT"; -break; -case 277: yy_.yytext = "\u23B1"; return "OP"; -break; -case 278: yy_.yytext = "\u2253"; return "OP"; -break; -case 279: yy_.yytext = "\u27F2"; return "OP"; -break; -case 280: yy_.yytext = "\u22CC"; return "OP"; -break; -case 281: yy_.yytext = "\u219D"; return "OPS"; -break; -case 282: yy_.yytext = "\u21C9"; return "OPS"; -break; -case 283: yy_.yytext = "\u21CC"; return "OPS"; -break; -case 284: yy_.yytext = "\u21C4"; return "OPS"; -break; -case 285: yy_.yytext = "\u21C0"; return "OPS"; -break; -case 286: yy_.yytext = "\u21C1"; return "OPS"; -break; -case 287: yy_.yytext = "\u21FE"; return "OPS"; -break; -case 288: yy_.yytext = "\u21A3"; return "OPS"; -break; -case 289: yy_.yytext = "\u21D2"; return "OPS"; -break; -case 290: yy_.yytext = "\u2192"; return "OPS"; -break; -case 291:return "RIGHT"; -break; -case 292: yy_.yytext = "\u03A1"; return "AIUG"; -break; -case 293: yy_.yytext = "\u03C1"; return "AILG"; -break; -case 294: yy_.yytext = "\u22B3"; return "OP"; -break; -case 295: yy_.yytext = "\u230B"; return "OPFS"; -break; -case 296: yy_.yytext = "\u211C"; return "A"; -break; -case 297: yy_.yytext = "\u2930"; return "OP"; -break; -case 298: yy_.yytext = "\u292B"; return "OP"; -break; -case 299: yy_.yytext = "\u2309"; return "OPFS"; -break; -case 300: yy_.yytext = "\u005D"; return "OPFS"; -break; -case 301: yy_.yytext = "\u007D"; return "OPFS"; -break; -case 302: yy_.yytext = "\u27E9"; return "OPFS"; -break; -case 303: yy_.yytext = "\u27E9"; return "OPFS"; -break; -case 304: yy_.yytext = "\u225F"; return "OP"; -break; -case 305: yy_.yytext = "\u2A0C"; return "OP"; -break; -case 306:return "QUAD"; -break; -case 307:return "QQUAD"; -break; -case 308: yy_.yytext = "\u25AA"; return "OP"; -break; -case 309: yy_.yytext = "\u03A8"; return "AIUG"; -break; -case 310: yy_.yytext = "\u03C8"; return "AILG"; -break; -case 311: yy_.yytext = "\u221D"; return "OP"; -break; -case 312: yy_.yytext = "\u220F"; return "OPM"; -break; -case 313: yy_.yytext = "\u220F"; return "OPM"; -break; -case 314: yy_.yytext = "\u2032"; return "OPP"; -break; -case 315: yy_.yytext = "\u227E"; return "OP"; -break; -case 316: yy_.yytext = "\u22E8"; return "OP"; -break; -case 317: yy_.yytext = "\u2AB5"; return "OP"; -break; -case 318: yy_.yytext = "\u2AB9"; return "OP"; -break; -case 319: yy_.yytext = "\u2AAF"; return "OP"; -break; -case 320: yy_.yytext = "\u227C"; return "OP"; -break; -case 321: yy_.yytext = "\u2AB7"; return "OP"; -break; -case 322: yy_.yytext = "\u227A"; return "OP"; -break; -case 323:return "PMOD"; -break; -case 324: yy_.yytext = "\u00B1"; return "OP"; -break; -case 325: yy_.yytext = "\u2A25"; return "OP"; -break; -case 326: yy_.yytext = "\u229E"; return "OP"; -break; -case 327: yy_.yytext = "\u22D4"; return "OP"; -break; -case 328: yy_.yytext = "\u03A0"; return "AIUG"; -break; -case 329: yy_.yytext = "\u03C0"; return "AILG"; -break; -case 330: yy_.yytext = "\u03A6"; return "AIUG"; -break; -case 331: yy_.yytext = "\u03D5"; return "AILG"; -break; -case 332:return "PHANTOM"; -break; -case 333: yy_.yytext = "\u2AEB"; return "OP"; -break; -case 334: yy_.yytext = "\u22A5"; return "OP"; -break; -case 335: yy_.yytext = "\u2AA3"; return "OP"; -break; -case 336: yy_.yytext = "\u2202"; return "OP"; -break; -case 337: yy_.yytext = "\u214B"; return "OP"; -break; -case 338: yy_.yytext = "\u2225"; return "OP"; -break; -case 339: this.pushState("TEXTARG"); return "PADDING"; -break; -case 340:return "OVERSET"; -break; -case 341: yy_.yytext = "\u00AF"; return "ACCENT"; -break; -case 342:return "OVERBRACE"; -break; -case 343:return "TEXOVER"; -break; -case 344: yy_.yytext = "\u2A34"; return "OP"; -break; -case 345: yy_.yytext = "\u2297"; return "OP"; -break; -case 346: yy_.yytext = "\u2298"; return "OP"; -break; -case 347:return "OPS"; -break; -case 348:return "OPP"; -break; -case 349:return "OPM"; -break; -case 350: yy_.yytext = "\u2A2D"; return "OP"; -break; -case 351: yy_.yytext = "\u2295"; return "OP"; -break; -case 352:return "OPFS"; -break; -case 353:return "OPF"; -break; -case 354: this.begin("TEXTARG"); return "OPERATORNAME"; -break; -case 355:return "OP"; -break; -case 356: yy_.yytext = "\u2296"; return "OP"; -break; -case 357: yy_.yytext = "\u2134"; return "A"; -break; -case 358: yy_.yytext = "\u03A9"; return "AIUG"; -break; -case 359: yy_.yytext = "\u03C9"; return "AILG"; -break; -case 360: yy_.yytext = "\u222E"; return "OP"; -break; -case 361: yy_.yytext = "\u222F"; return "OP"; -break; -case 362: yy_.yytext = "\u2230"; return "OP"; -break; -case 363: yy_.yytext = "\u2299"; return "OP"; -break; -case 364: yy_.yytext = "\u229D"; return "OP"; -break; -case 365: yy_.yytext = "\u29B8"; return "OP"; -break; -case 366: yy_.yytext = "\u2932"; return "OP"; -break; -case 367: yy_.yytext = "\u21D6"; return "OPS"; -break; -case 368: yy_.yytext = "\u2196"; return "OPS"; -break; -case 369: yy_.yytext = "\u21D6"; return "OPS"; -break; -case 370: yy_.yytext = "\u2196"; return "OPS"; -break; -case 371: yy_.yytext = "\u22AF"; return "OP"; -break; -case 372: yy_.yytext = "\u22AE"; return "OP"; -break; -case 373: yy_.yytext = "\u22AD"; return "OP"; -break; -case 374: yy_.yytext = "\u22AC"; return "OP"; -break; -case 375:return "NUM"; -break; -case 376: yy_.yytext = "\u039D"; return "AIUG"; -break; -case 377: yy_.yytext = "\u03BD"; return "AILG"; -break; -case 378: yy_.yytext = "\u22ED"; return "OP"; -break; -case 379: yy_.yytext = "\u22EB"; return "OP"; -break; -case 380: yy_.yytext = "\u22EC"; return "OP"; -break; -case 381: yy_.yytext = "\u22EA"; return "OP"; -break; -case 382: yy_.yytext = "\u2289"; return "OP"; -break; -case 383: yy_.yytext = "\u2285"; return "OP"; -break; -case 384: yy_.yytext = "\u227F\u0338"; return "OP"; -break; -case 385: yy_.yytext = "\u2AB0\u0338"; return "OP"; -break; -case 386: yy_.yytext = "\u2281"; return "OP"; -break; -case 387: yy_.yytext = "\u2288"; return "OP"; -break; -case 388: yy_.yytext = "\u2288"; return "OP"; -break; -case 389: yy_.yytext = "\u2284"; return "OP"; -break; -case 390: yy_.yytext = "\u2244"; return "OP"; -break; -case 391: yy_.yytext = "\u2241"; return "OP"; -break; -case 392: yy_.yytext = "\u2226"; return "OP"; -break; -case 393: yy_.yytext = "\u2224"; return "OP"; -break; -case 394: yy_.yytext = "\u21CF"; return "OP"; -break; -case 395: yy_.yytext = "\u219B"; return "OP"; -break; -case 396: yy_.yytext = "\u2AAF\u0338"; return "OP"; -break; -case 397: yy_.yytext = "\u2280"; return "OP"; -break; -case 398: yy_.yytext = "\u2226"; return "OP"; -break; -case 399: yy_.yytext = "\u220C"; return "OP"; -break; -case 400: yy_.yytext = "\u2209"; return "OP"; -break; -case 401: yy_.yytext = "\u00AC"; return "OP"; -break; -case 402: yy_.yytext = "\u2224"; return "OP"; -break; -case 403: yy_.yytext = "\u226E"; return "OP"; -break; -case 404: yy_.yytext = "\u2A7D\u0338"; return "OP"; -break; -case 405: yy_.yytext = "\u2A7D\u0338"; return "OP"; -break; -case 406: yy_.yytext = "\u2270"; return "OP"; -break; -case 407: yy_.yytext = "\u21CE"; return "OP"; -break; -case 408: yy_.yytext = "\u21AE"; return "OP"; -break; -case 409: yy_.yytext = "\u21CD"; return "OP"; -break; -case 410: yy_.yytext = "\u219A"; return "OP"; -break; -case 411: yy_.yytext = "\u220B"; return "OP"; -break; -case 412: yy_.yytext = "\u226F"; return "OP"; -break; -case 413: yy_.yytext = "\u2A7E\u0338"; return "OP"; -break; -case 414: yy_.yytext = "\u2A7E\u0338"; return "OP"; -break; -case 415: yy_.yytext = "\u2271"; return "OP"; -break; -case 416: yy_.yytext = "\u2204"; return "OP"; -break; -case 417: yy_.yytext = "\u2262"; return "OP"; -break; -case 418: yy_.yytext = "\u2242\u0338"; return "OP"; -break; -case 419: yy_.yytext = "\u2260"; return "OP"; -break; -case 420: yy_.yytext = "\u292E"; return "OP"; -break; -case 421: yy_.yytext = "\u2931"; return "OP"; -break; -case 422:return "NEGTHICKSPACE"; -break; -case 423:return "NEGSPACE"; -break; -case 424:return "NEGMEDSPACE"; -break; -case 425: yy_.yytext = "\u00AC"; return "OP"; -break; -case 426: yy_.yytext = "\u21D7"; return "OPS"; -break; -case 427: yy_.yytext = "\u2197"; return "OPS"; -break; -case 428: yy_.yytext = "\u21D7"; return "OPS"; -break; -case 429: yy_.yytext = "\u2197"; return "OPS"; -break; -case 430: yy_.yytext = "\u2260"; return "OP"; -break; -case 431: yy_.yytext = "\u2247"; return "OP"; -break; -case 432: yy_.yytext = "\u224E\u0338"; return "OP"; -break; -case 433: yy_.yytext = "\u224F\u0338"; return "OP"; -break; -case 434: yy_.yytext = "\u266E"; return "OP"; -break; -case 435: yy_.yytext = "\u2249"; return "OP"; -break; -case 436: yy_.yytext = "\u2207"; return "OP"; -break; -case 437:return "MULTI"; -break; -case 438: yy_.yytext = "\u22B8"; return "OP"; -break; -case 439: yy_.yytext = "\u039C"; return "AIUG"; -break; -case 440: yy_.yytext = "\u03BC"; return "AILG"; -break; -case 441: this.begin("TEXTARG"); return "MTEXT"; -break; -case 442: this.pushState("TEXTARG"); this.pushState("TEXTOPTARG"); this.pushState("TRYOPTARG"); this.pushState("TEXTOPTARG"); this.pushState("TRYOPTARG"); return "MS"; -break; -case 443: yy_.yytext = "\u2213"; return "OP"; -break; -case 444: yy_.yytext = "\u22A7"; return "OP"; -break; -case 445: yy_.yytext = "mod"; return "MO"; -break; -case 446: this.pushState("TEXTARG"); return "MO"; -break; -case 447: this.pushState("TEXTARG"); return "MN"; -break; -case 448: yy_.yytext = "\u2ADB"; return "OP"; -break; -case 449: yy_.yytext = "\u2A2A"; return "OP"; -break; -case 450: yy_.yytext = "\u229F"; return "OP"; -break; -case 451: yy_.yytext = "\u2212"; return "OP"; -break; -case 452: yy_.yytext = yy_.yytext.slice(1); return "FM"; -break; -case 453: yy_.yytext = "\u2223"; return "OP"; -break; -case 454: this.pushState("TEXTARG"); return "MI"; -break; -case 455: yy_.yytext = "\u2127"; return "A"; -break; -case 456: yy_.yytext = "\u2127"; return "A"; -break; -case 457:return "MEDSPACE"; -break; -case 458: yy_.yytext = "\u2221"; return "OP"; -break; -case 459:return "MATHTT"; -break; -case 460:return "MATHSF"; -break; -case 461:return "MATHSCR"; -break; -case 462:return "MATHRM"; -break; -case 463:return "MATHRLAP"; -break; -case 464: this.begin("TEXTARG"); return "MATHREL"; -break; -case 465: this.pushState("TEXTOPTARG"); this.pushState("TRYOPTARG"); this.pushState("TEXTOPTARG"); this.pushState("TRYOPTARG"); this.pushState("TEXTARG"); return "MATHRAISEBOX"; -break; -case 466: this.begin("TEXTARG"); return "MATHOP"; -break; -case 467:return "MATHIT"; -break; -case 468:return "MATHLLAP"; -break; -case 469:return "MATHIT"; -break; -case 470:return "MATHFRAK"; -break; -case 471:return "MATHFRAK"; -break; -case 472:return "MATHCLAP"; -break; -case 473:return "MATHSCR"; -break; -case 474:return "MATHBSCR"; -break; -case 475:return "MATHBIT"; -break; -case 476: this.begin("TEXTARG"); return "MATHBIN"; -break; -case 477:return "MATHBF"; -break; -case 478:return "MATHBSCR"; -break; -case 479:return "MATHBB"; -break; -case 480: yy_.yytext = "\u2907"; return "OP"; -break; -case 481: yy_.yytext = "\u21A6"; return "OPS"; -break; -case 482: yy_.yytext = "\u2906"; return "OP"; -break; -case 483: yy_.yytext = "\u21A6"; return "OPS"; -break; -case 484: yy_.yytext = "\u2268\uFE00"; return "OP"; -break; -case 485: yy_.yytext = "\u2268\uFE00"; return "OP"; -break; -case 486: yy_.yytext = "\u22C9"; return "OP"; -break; -case 487: yy_.yytext = "\u003C"; return "OP"; -break; -case 488: yy_.yytext = "\u21B0"; return "OPS"; -break; -case 489: yy_.yytext = "\u2018"; return "OPF"; -break; -case 490: yy_.yytext = "\u25CA"; return "OP"; -break; -case 491: yy_.yytext = "\u2A1C"; return "OP"; -break; -case 492: yy_.yytext = "\u21AC"; return "OPS"; -break; -case 493: yy_.yytext = "\u21AB"; return "OPS"; -break; -case 494: yy_.yytext = "\u27F9"; return "OPS"; -break; -case 495: yy_.yytext = "\u27F6"; return "OPS"; -break; -case 496: yy_.yytext = "\u27FC"; return "OPS"; -break; -case 497: yy_.yytext = "\u27FA"; return "OPS"; -break; -case 498: yy_.yytext = "\u27F7"; return "OPS"; -break; -case 499: yy_.yytext = "\u27F8"; return "OPS"; -break; -case 500: yy_.yytext = "\u27F5"; return "OPS"; -break; -case 501: yy_.yytext = "\u22E6"; return "OP"; -break; -case 502: yy_.yytext = "\u2268"; return "OP"; -break; -case 503: yy_.yytext = "\u2A87"; return "OP"; -break; -case 504: yy_.yytext = "\u2A89"; return "OP"; -break; -case 505: yy_.yytext = "\u23B0"; return "OP"; -break; -case 506: yy_.yytext = "\u22D8"; return "OP"; -break; -case 507: yy_.yytext = "\u21DA"; return "OPS"; -break; -case 508: yy_.yytext = "\u27EA"; return "OPFS"; -break; -case 509: yy_.yytext = "\u226A"; return "OP"; -break; -case 510: yy_.yytext = "\u22B2"; return "OP"; -break; -case 511: yy_.yytext = "\u230A"; return "OPFS"; -break; -case 512: yy_.yytext = "\u2272"; return "OP"; -break; -case 513: yy_.yytext = "\u2276"; return "OP"; -break; -case 514: yy_.yytext = "\u2A8B"; return "OP"; -break; -case 515: yy_.yytext = "\u22DA"; return "OP"; -break; -case 516: yy_.yytext = "\u22D6"; return "OP"; -break; -case 517: yy_.yytext = "\u2A85"; return "OP"; -break; -case 518: yy_.yytext = "\u003C"; return "OP"; -break; -case 519: yy_.yytext = "\u2A7D"; return "OP"; -break; -case 520: yy_.yytext = "\u2266"; return "OP"; -break; -case 521: yy_.yytext = "\u2264"; return "OP"; -break; -case 522: yy_.yytext = "\u27F3"; return "OP"; -break; -case 523: yy_.yytext = "\u22CB"; return "OP"; -break; -case 524: yy_.yytext = "\u219C"; return "OPS"; -break; -case 525: yy_.yytext = "\u21AD"; return "OPS"; -break; -case 526: yy_.yytext = "\u21CB"; return "OPS"; -break; -case 527: yy_.yytext = "\u21FF"; return "OPS"; -break; -case 528: yy_.yytext = "\u21C6"; return "OPS"; -break; -case 529: yy_.yytext = "\u21D4"; return "OPS"; -break; -case 530: yy_.yytext = "\u2194"; return "OPS"; -break; -case 531: yy_.yytext = "\u21C7"; return "OPS"; -break; -case 532: yy_.yytext = "\u21BC"; return "OPS"; -break; -case 533: yy_.yytext = "\u21BD"; return "OPS"; -break; -case 534: yy_.yytext = "\u21FD"; return "OPS"; -break; -case 535: yy_.yytext = "\u21A2"; return "OPS"; -break; -case 536: yy_.yytext = "\u21D0"; return "OPS"; -break; -case 537: yy_.yytext = "\u2190"; return "OPS"; -break; -case 538:return "LEFT"; -break; -case 539: yy_.yytext = "\u2264"; return "OP"; -break; -case 540: yy_.yytext = "\u2026"; return "OP"; -break; -case 541: yy_.yytext = "\u2308"; return "OPFS"; -break; -case 542: yy_.yytext = "\u005B"; return "OPFS"; -break; -case 543: yy_.yytext = "\u007B"; return "OPFS"; -break; -case 544: yy_.yytext = "\u27E8"; return "OPFS"; -break; -case 545: yy_.yytext = "\u27E8"; return "OPFS"; -break; -case 546: yy_.yytext = "\u039B"; return "AIUG"; -break; -case 547: yy_.yytext = "\u03BB"; return "AILG"; -break; -case 548: yy_.yytext = "\u223B"; return "OP"; -break; -case 549: yy_.yytext = "\u039A"; return "AIUG"; -break; -case 550: yy_.yytext = "\u03BA"; return "AILG"; -break; -case 551: yy_.yytext = "\u0237"; return "AILL"; -break; -case 552: this.pushState("TEXTARG"); return "MN"; -break; -case 553: yy_.yytext = "\u0399"; return "AIUG"; -break; -case 554: yy_.yytext = "\u03B9"; return "AILG"; -break; -case 555: yy_.yytext = "\u214B"; return "OP"; -break; -case 556: yy_.yytext = "\u2A18"; return "OP"; -break; -case 557: yy_.yytext = "\u2A3D"; return "OP"; -break; -case 558: yy_.yytext = "\u2A3C"; return "OP"; -break; -case 559: yy_.yytext = "\u22C2"; return "OPM"; -break; -case 560: yy_.yytext = "\u2229"; return "OP"; -break; -case 561: yy_.yytext = "\u2AF4"; return "OP"; -break; -case 562: yy_.yytext = "\u22BA"; return "OP"; -break; -case 563: yy_.yytext = "\u222B"; return "OP"; -break; -case 564: yy_.yytext = "\u2A1A"; return "OP"; -break; -case 565: yy_.yytext = "\u2A19"; return "OP"; -break; -case 566: yy_.yytext = "\u2A0E"; return "OP"; -break; -case 567: yy_.yytext = "\u2A0D"; return "OP"; -break; -case 568: yy_.yytext = "\u222B"; return "OP"; -break; -case 569: yy_.yytext = "\u221E"; return "NUM"; -break; -case 570: yy_.yytext = "\u221E"; return "NUM"; -break; -case 571: yy_.yytext = yy_.yytext.slice(1); return "FM"; -break; -case 572: yy_.yytext = "\u220A"; return "OP"; -break; -case 573: yy_.yytext = "\u21D2"; return "OPS"; -break; -case 574: yy_.yytext = "\u21D0"; return "OPS"; -break; -case 575: yy_.yytext = "\u0131"; return "AILL"; -break; -case 576: yy_.yytext = "\u2111"; return "A"; -break; -case 577: yy_.yytext = "\u222C"; return "OP"; -break; -case 578: yy_.yytext = "\u222D"; return "OP"; -break; -case 579: yy_.yytext = "\u2A0C"; return "OP"; -break; -case 580: yy_.yytext = "\u27FA"; return "OPS"; -break; -case 581: yy_.yytext = "\u210F"; return "A"; -break; -case 582: this.pushState("TEXTARG"); return "HREF"; -break; -case 583: yy_.yytext = "\u21AA"; return "OPS"; -break; -case 584: yy_.yytext = "\u21A9"; return "OPS"; -break; -case 585: yy_.yytext = "\u2926"; return "OP"; -break; -case 586: yy_.yytext = "\u2925"; return "OP"; -break; -case 587: yy_.yytext = "\u2661"; return "OP"; -break; -case 588: yy_.yytext = "\u210F"; return "A"; -break; -case 589: yy_.yytext = "\u005E"; return "ACCENTNS"; -break; -case 590: yy_.yytext = "\u2269\uFE00"; return "OP"; -break; -case 591: yy_.yytext = "\u2269\uFE00"; return "OP"; -break; -case 592: yy_.yytext = "\u2273"; return "OP"; -break; -case 593: yy_.yytext = "\u2277"; return "OP"; -break; -case 594: yy_.yytext = "\u2A8C"; return "OP"; -break; -case 595: yy_.yytext = "\u22DB"; return "OP"; -break; -case 596: yy_.yytext = "\u22D7"; return "OP"; -break; -case 597: yy_.yytext = "\u2A86"; return "OP"; -break; -case 598: yy_.yytext = "\u003E"; return "OP"; -break; -case 599: yy_.yytext = "\u003E"; return "OP"; -break; -case 600: yy_.yytext = "\u22E7"; return "OP"; -break; -case 601: yy_.yytext = "\u2269"; return "OP"; -break; -case 602: yy_.yytext = "\u2A88"; return "OP"; -break; -case 603: yy_.yytext = "\u2A8A"; return "OP"; -break; -case 604: yy_.yytext = "\u2137"; return "A"; -break; -case 605: yy_.yytext = "\u22D9"; return "OP"; -break; -case 606: yy_.yytext = "\u226B"; return "OP"; -break; -case 607: yy_.yytext = "\u2A7E"; return "OP"; -break; -case 608: yy_.yytext = "\u2267"; return "OP"; -break; -case 609: yy_.yytext = "\u2265"; return "OP"; -break; -case 610: yy_.yytext = "\u2265"; return "OP"; -break; -case 611: yy_.yytext = "\u0393"; return "AIUG"; -break; -case 612: yy_.yytext = "\u03B3"; return "AILG"; -break; -case 613: yy_.yytext = "\u2322"; return "OP"; -break; -case 614: this.pushState("TEXTARG"); return "FRAME"; -break; -case 615:return "FRAC"; -break; -case 616: yy_.yytext = "\u2ADD"; return "OP"; -break; -case 617: yy_.yytext = "\u2ADD\u0338"; return "OP"; -break; -case 618: yy_.yytext = "\u2200"; return "OP"; -break; -case 619: yy_.yytext = "\u266D"; return "OP"; -break; -case 620: yy_.yytext = "\u292C"; return "OP"; -break; -case 621: yy_.yytext = "\u292F"; return "OP"; -break; -case 622: yy_.yytext = "\u2252"; return "OP"; -break; -case 623: yy_.yytext = "\u2203"; return "OP"; -break; -case 624: yy_.yytext = "\u00F0"; return "A"; -break; -case 625: yy_.yytext = "\u00F0"; return "A"; -break; -case 626: yy_.yytext = "\u0397"; return "AIUG"; -break; -case 627: yy_.yytext = "\u03B7"; return "AILG"; -break; -case 628: yy_.yytext = "\u2261"; return "OP"; -break; -case 629: this.pushState("TEXTARG"); return "EQROWS"; -break; -case 630: this.pushState("TEXTARG"); return "EQCOLS"; -break; -case 631: yy_.yytext = "\u2A95"; return "OP"; -break; -case 632: yy_.yytext = "\u2A96"; return "OP"; -break; -case 633: yy_.yytext = "\u2242"; return "OP"; -break; -case 634: yy_.yytext = "\u003D\u2237"; return "OP"; -break; -case 635: yy_.yytext = "\u2255"; return "OP"; -break; -case 636: yy_.yytext = "\u2212\u2237"; return "OP"; -break; -case 637: yy_.yytext = "\u003D\u2237"; return "OP"; -break; -case 638: yy_.yytext = "\u003D\u2237"; return "OP"; -break; -case 639: yy_.yytext = "\u003D\u2237"; return "OP"; -break; -case 640: yy_.yytext = "\u2255"; return "OP"; -break; -case 641: yy_.yytext = "\u2256"; return "OP"; -break; -case 642: yy_.yytext = "\u03F5"; return "AILG"; -break; -case 643:return "EVVMATRIX"; -break; -case 644:return "EVMATRIX"; -break; -case 645: return "ETOGGLE"; -break; -case 646:return "EALIGNED"; -break; -case 647:return "ESMALLMATRIX"; -break; -case 648:return "EPMATRIX"; -break; -case 649:return "EMATRIX"; -break; -case 650:return "EGATHERED"; -break; -case 651:return "ECASES"; -break; -case 652:return "EBBMATRIX"; -break; -case 653:return "EBMATRIX"; -break; -case 654:return "EARRAY"; -break; -case 655:return "EALIGNED"; -break; -case 656: yy_.yytext = "\u2205"; return "A"; -break; -case 657: yy_.yytext = "\u2205"; return "A"; -break; -case 658: yy_.yytext = "\u21AA"; return "OPS"; -break; -case 659: yy_.yytext = "\u2113"; return "A"; -break; -case 660: yy_.yytext = "\u2195"; return "OPS"; -break; -case 661: yy_.yytext = "\u29DF"; return "OP"; -break; -case 662: yy_.yytext = "\u2910"; return "OPS"; -break; -case 663: yy_.yytext = "\u2195"; return "OPS"; -break; -case 664: yy_.yytext = "\u21C2"; return "OPS"; -break; -case 665: yy_.yytext = "\u21C3"; return "OPS"; -break; -case 666: yy_.yytext = "\u21CA"; return "OPS"; -break; -case 667: yy_.yytext = "\u21D3"; return "OPS"; -break; -case 668: yy_.yytext = "\u2193"; return "OPS"; -break; -case 669: yy_.yytext = "\u222C"; return "OP"; -break; -case 670: yy_.yytext = "\u2A5E"; return "OP"; -break; -case 671: yy_.yytext = "\u2306"; return "OP"; -break; -case 672: yy_.yytext = "\u2026"; return "OP"; -break; -case 673: yy_.yytext = "\u2214"; return "OP"; -break; -case 674: yy_.yytext = "\u2238"; return "OP"; -break; -case 675: yy_.yytext = "\u2251"; return "OP"; -break; -case 676: yy_.yytext = "\u2251"; return "OP"; -break; -case 677: yy_.yytext = "\u2250"; return "OP"; -break; -case 678: yy_.yytext = "\u02D9"; return "ACCENT"; -break; -case 679: yy_.yytext = "\u22C7"; return "OP"; -break; -case 680: yy_.yytext = "\u00F7"; return "OP"; -break; -case 681:return "DISPLAYSTYLE"; -break; -case 682: yy_.yytext = "\u2A08"; return "OPM"; -break; -case 683: yy_.yytext = "\u03DD"; return "A"; -break; -case 684: yy_.yytext = "\u2662"; return "OP"; -break; -case 685: yy_.yytext = "\u22C4"; return "OP"; -break; -case 686: yy_.yytext = "\u22C4"; return "OP"; -break; -case 687: yy_.yytext = yy_.yytext.slice(1); return "FM"; -break; -case 688: yy_.yytext = "\u0394"; return "AIUG"; -break; -case 689: yy_.yytext = "\u03B4"; return "AILG"; -break; -case 690: yy_.yytext = "\u2207"; return "OP"; -break; -case 691: yy_.yytext = "\u00B0"; return "OP"; -break; -case 692: yy_.yytext = "\u290B"; return "OPS"; -break; -case 693: yy_.yytext = "\u2A77"; return "OP"; -break; -case 694: yy_.yytext = "\u22F1"; return "OP"; -break; -case 695: yy_.yytext = "\u0308"; return "ACCENT"; -break; -case 696: yy_.yytext = "\u20DB"; return "OP"; -break; -case 697: yy_.yytext = "\u20DB"; return "ACCENT"; -break; -case 698: yy_.yytext = "\u20DC"; return "OP"; -break; -case 699: yy_.yytext = "\u20DC"; return "ACCENT"; -break; -case 700: yy_.yytext = "\u2021"; return "OP"; -break; -case 701: yy_.yytext = "\u2237"; return "OP"; -break; -case 702: yy_.yytext = "\u290F"; return "OPS"; -break; -case 703: yy_.yytext = "\u2AE4"; return "OP"; -break; -case 704: yy_.yytext = "\u2AE3"; return "OP"; -break; -case 705: yy_.yytext = "\u22A3"; return "OP"; -break; -case 706: yy_.yytext = "\u290F"; return "OPS"; -break; -case 707: yy_.yytext = "\u290E"; return "OPS"; -break; -case 708: yy_.yytext = "\u2193"; return "OPS"; -break; -case 709: yy_.yytext = "\u2138"; return "A"; -break; -case 710: yy_.yytext = "\u2020"; return "OP"; -break; -case 711: yy_.yytext = "\u21B7"; return "OP"; -break; -case 712: yy_.yytext = "\u21B6"; return "OP"; -break; -case 713: yy_.yytext = "\u293B"; return "OP"; -break; -case 714: yy_.yytext = "\u22CF"; return "OP"; -break; -case 715: yy_.yytext = "\u22CE"; return "OP"; -break; -case 716: yy_.yytext = "\u22DF"; return "OP"; -break; -case 717: yy_.yytext = "\u22DE"; return "OP"; -break; -case 718: yy_.yytext = "\u228D"; return "OP"; -break; -case 719: yy_.yytext = "\u22D3"; return "OP"; -break; -case 720: yy_.yytext = "\u222A"; return "OP"; -break; -case 721: yy_.yytext = "\u2210"; return "OPM"; -break; -case 722: yy_.yytext = "\u2210"; return "OPM"; -break; -case 723: yy_.yytext = "\u222E"; return "OP"; -break; -case 724: yy_.yytext = "\u2A07"; return "OPM"; -break; -case 725: yy_.yytext = "\u222E"; return "OP"; -break; -case 726: yy_.yytext = "\u2245"; return "OP"; -break; -case 727: yy_.yytext = "\u2201"; return "OP"; -break; -case 728: this.begin("TEXTARG"); return "COLSPAN"; -break; -case 729: this.pushState("TEXTARG"); return "COLOR"; -break; -case 730: yy_.yytext = "\u2237\u223C"; return "OP"; -break; -case 731: yy_.yytext = "\u2236\u223C"; return "OP"; -break; -case 732: yy_.yytext = "\u2A74"; return "OP"; -break; -case 733: yy_.yytext = "\u2254"; return "OP"; -break; -case 734: yy_.yytext = "\u2237\u2212"; return "OP"; -break; -case 735: yy_.yytext = "\u2254"; return "OP"; -break; -case 736: yy_.yytext = "\u2237\u2248"; return "OP"; -break; -case 737: yy_.yytext = "\u2236\u2248"; return "OP"; -break; -case 738: yy_.yytext = "\u2237"; return "OP"; -break; -case 739: yy_.yytext = "\u003A"; return "OP"; -break; -case 740: this.pushState("TEXTARG"); return "COLLINES"; -break; -case 741: this.pushState("TEXTARG"); return "COLLAYOUT"; -break; -case 742: this.begin("TEXTARG"); return "COLALIGN"; -break; -case 743: yy_.yytext = "\u2663"; return "OP"; -break; -case 744: yy_.yytext = "\u00AF"; return "ACCENT"; -break; -case 745: yy_.yytext = "\u229D"; return "OP"; -break; -case 746: yy_.yytext = "\u229A"; return "OP"; -break; -case 747: yy_.yytext = "\u229B"; return "OP"; -break; -case 748: yy_.yytext = "\u2941"; return "OP"; -break; -case 749: yy_.yytext = "\u2940"; return "OP"; -break; -case 750: yy_.yytext = "\u2257"; return "OP"; -break; -case 751: yy_.yytext = "\u2218"; return "OP"; -break; -case 752:return "TEXCHOOSE"; -break; -case 753: yy_.yytext = "\u03C7"; return "AILG"; -break; -case 754: yy_.yytext = "\u02C7"; return "ACCENTNS"; -break; -case 755:return "CELLOPTS"; -break; -case 756: yy_.yytext = "\u22EF"; return "OP"; -break; -case 757: yy_.yytext = "\u00B7"; return "OP"; -break; -case 758: yy_.yytext = "\u22C5"; return "OP"; -break; -case 759: yy_.yytext = "\u22D2"; return "OP"; -break; -case 760: yy_.yytext = "\u2229"; return "OP"; -break; -case 761: yy_.yytext = "\u2AAE"; return "OP"; -break; -case 762: yy_.yytext = "\u224E"; return "OP"; -break; -case 763: yy_.yytext = "\u224F"; return "OP"; -break; -case 764: yy_.yytext = "\u2022"; return "OP"; -break; -case 765: yy_.yytext = "\u2A32"; return "OP"; -break; -case 766: yy_.yytext = "\u22A0"; return "OP"; -break; -case 767: yy_.yytext = "\u229E"; return "OP"; -break; -case 768: yy_.yytext = "\u229F"; return "OP"; -break; -case 769:return "BOXED"; -break; -case 770: yy_.yytext = "\u22A1"; return "OP"; -break; -case 771: yy_.yytext = "\u29C4"; return "OP"; -break; -case 772: yy_.yytext = "\u29C7"; return "OP"; -break; -case 773: yy_.yytext = "\u29C5"; return "OP"; -break; -case 774: yy_.yytext = "\u29C6"; return "OP"; -break; -case 775: yy_.yytext = "\u25A1"; return "OP"; -break; -case 776: yy_.yytext = "\u22C8"; return "OP"; -break; -case 777: yy_.yytext = "\u22A5"; return "OP"; -break; -case 778: yy_.yytext = "\u22A5"; return "OP"; -break; -case 779:return "MATHBF"; -break; -case 780: yy_.yytext = "\u25B8"; return "OP"; -break; -case 781: yy_.yytext = "\u25C2"; return "OP"; -break; -case 782: yy_.yytext = "\u25BE"; return "OP"; -break; -case 783: yy_.yytext = "\u25B4"; return "OP"; -break; -case 784: yy_.yytext = "\u25A0"; return "OP"; -break; -case 785: yy_.yytext = "\u29EB"; return "OP"; -break; -case 786: yy_.yytext = "\u290D"; return "OPS"; -break; -case 787:return "BINOM"; -break; -case 788: yy_.yytext = "\u22C0"; return "OPM"; -break; -case 789: yy_.yytext = "\u22C1"; return "OPM"; -break; -case 790: yy_.yytext = "\u2A04"; return "OPM"; -break; -case 791: yy_.yytext = "\u25B3"; return "OP"; -break; -case 792: yy_.yytext = "\u25BD"; return "OP"; -break; -case 793: yy_.yytext = "\u2A09"; return "OPM"; -break; -case 794: yy_.yytext = "\u2605"; return "OP"; -break; -case 795: yy_.yytext = "\u2A06"; return "OPM"; -break; -case 796: yy_.yytext = "\u2A05"; return "OPM"; -break; -case 797:return "BBIG"; -break; -case 798:return "BIG"; -break; -case 799: yy_.yytext = "\u2A02"; return "OPM"; -break; -case 800: yy_.yytext = "\u2A01"; return "OPM"; -break; -case 801: yy_.yytext = "\u2A00"; return "OPM"; -break; -case 802:return "BBIGL"; -break; -case 803:return "BIGL"; -break; -case 804: yy_.yytext = "\u2AFC"; return "OPM"; -break; -case 805:return "BBIGG"; -break; -case 806:return "BIGG"; -break; -case 807:return "BBIGGL"; -break; -case 808:return "BIGGL"; -break; -case 809:return "BBIGG"; -break; -case 810:return "BIGG"; -break; -case 811: yy_.yytext = "\u2A03"; return "OPM"; -break; -case 812: yy_.yytext = "\u22C3"; return "OPM"; -break; -case 813: yy_.yytext = "\u25CB"; return "OP"; -break; -case 814: yy_.yytext = "\u22C2"; return "OPM"; -break; -case 815:return "BBIG"; -break; -case 816:return "BIG"; -break; -case 817: this.pushState("TEXTARG"); return "BGCOLOR"; -break; -case 818: yy_.yytext = "\u226C"; return "OP"; -break; -case 819: yy_.yytext = "\u2136"; return "A"; -break; -case 820: yy_.yytext = "\u0392"; return "AIUG"; -break; -case 821: yy_.yytext = "\u03B2"; return "AILG"; -break; -case 822:return "BVVMATRIX"; -break; -case 823:return "BVMATRIX"; -break; -case 824: return "BTOGGLE"; -break; -case 825:return "BALIGNED"; -break; -case 826:return "BSMALLMATRIX"; -break; -case 827:return "BPMATRIX"; -break; -case 828:return "BMATRIX"; -break; -case 829:return "BGATHERED"; -break; -case 830:return "BCASES"; -break; -case 831:return "BBBMATRIX"; -break; -case 832:return "BBMATRIX"; -break; -case 833: this.pushState("TEXTARG"); this.pushState("TEXTOPTARG"); this.pushState("TRYOPTARG"); return "BARRAY"; -break; -case 834:return "BALIGNED"; -break; -case 835: yy_.yytext = "\u2235"; return "OP"; -break; -case 836: yy_.yytext = "\u213F"; return "A"; -break; -case 837: yy_.yytext = "\u2305"; return "OP"; -break; -case 838: yy_.yytext = "\u00AF"; return "ACCENTNS"; -break; -case 839: yy_.yytext = "\u005C"; return "OP"; -break; -case 840: yy_.yytext = "\u22CD"; return "OP"; -break; -case 841: yy_.yytext = "\u223D"; return "OP"; -break; -case 842: yy_.yytext = "\u2035"; return "OPP"; -break; -case 843: yy_.yytext = "\u03F6"; return "OP"; -break; -case 844:return "TEXATOP"; -break; -case 845: yy_.yytext = "\u224D"; return "OP"; -break; -case 846: yy_.yytext = "\u2217"; return "OP"; -break; -case 847:return "ARRAYOPTS"; -break; -case 848:return "ARRAY"; -break; -case 849: yy_.yytext = yy_.yytext.slice(1); return "F"; -break; -case 850: yy_.yytext = "\u224A"; return "OP"; -break; -case 851: yy_.yytext = "\u2248"; return "OP"; -break; -case 852: yy_.yytext = "\u2220"; return "OP"; -break; -case 853: yy_.yytext = "\u2A3F"; return "OP"; -break; -case 854: yy_.yytext = "\u0391"; return "AIUG"; -break; -case 855: yy_.yytext = "\u03B1"; return "AILG"; -break; -case 856: this.pushState("TEXTARG"); return "ALIGN"; -break; -case 857: yy_.yytext = "\u2135"; return "A"; -break; -case 858:return "AIUL"; -break; -case 859:return "AIUG"; -break; -case 860:return "AILL"; -break; -case 861:return "AILG"; -break; -case 862: yy_.yytext = "\u22F0"; return "OP"; -break; -case 863: yy_.yytext = "\u212B"; return "A"; -break; -case 864:return "A"; -break; -case 865: yy_.yytext = "\u0024"; return "A"; -break; -case 866: yy_.yytext = "\u007D"; return "OPFS"; -break; -case 867: yy_.yytext = "\u2016"; return "OPFS"; -break; -case 868: yy_.yytext = "\u007B"; return "OPFS"; -break; -case 869:return "THICKSPACE"; -break; -case 870:return "MEDSPACE"; -break; -case 871:return "THINSPACE"; -break; -case 872: yy_.yytext = "\u0026"; return "A"; -break; -case 873: yy_.yytext = "\u0025"; return "A"; -break; -case 874: yy_.yytext = "\u0023"; return "OP"; -break; -case 875:return "NEGSPACE"; -break; -case 876: yy_.yytext = "\u2212"; return "OP"; -break; -case 877: yy_.yytext = "\u2057"; return "OPP"; -break; -case 878: yy_.yytext = "\u2034"; return "OPP"; -break; -case 879: yy_.yytext = "\u2033"; return "OPP"; -break; -case 880: yy_.yytext = "\u2032"; return "OPP"; -break; -case 881:return "HIGH_SURROGATE"; -break; -case 882:return "LOW_SURROGATE"; -break; -case 883:return "BMP_CHARACTER"; -break; -} -}, -rules: [/^(?:.)/,/^(?:\$\$|\\\[|\$|\\\()/,/^(?:$)/,/^(?:\\[$\\])/,/^(?:[<&>])/,/^(?:[^])/,/^(?:\s*\[)/,/^(?:.)/,/^(?:([^\\\]]|(\\[\\\]]))+)/,/^(?:\])/,/^(?:\s*\{)/,/^(?:([^\\\}]|(\\[\\\}]))+)/,/^(?:\})/,/^(?:\])/,/^(?:\s+)/,/^(?:\$\$|\\\]|\$|\\\))/,/^(?:\{)/,/^(?:\})/,/^(?:\^)/,/^(?:_)/,/^(?:\.)/,/^(?:&)/,/^(?:\\\\)/,/^(?:[0-9]+(?:\.[0-9]+)?|[\u0660-\u0669]+(?:\u066B[\u0660-\u0669]+)?|(?:\uD835[\uDFCE-\uDFD7])+|(?:\uD835[\uDFD8-\uDFE1])+|(?:\uD835[\uDFE2-\uDFEB])+|(?:\uD835[\uDFEC-\uDFF5])+|(?:\uD835[\uDFF6-\uDFFF])+)/,/^(?:[a-zA-Z]+)/,/^(?:\\Zeta)/,/^(?:\\zeta)/,/^(?:\\xrightleftharpoons)/,/^(?:\\xRightarrow)/,/^(?:\\xrightarrow)/,/^(?:\\xmapsto)/,/^(?:\\xleftrightharpoons)/,/^(?:\\xLeftrightarrow)/,/^(?:\\xleftrightarrow)/,/^(?:\\xLeftarrow)/,/^(?:\\xleftarrow)/,/^(?:\\Xi)/,/^(?:\\xi)/,/^(?:\\xhookrightarrow)/,/^(?:\\xhookleftarrow)/,/^(?:\\wr)/,/^(?:\\wp)/,/^(?:\\widevec)/,/^(?:\\widetilde)/,/^(?:\\widehat)/,/^(?:\\widecheck)/,/^(?:\\widebar)/,/^(?:\\wedgeq)/,/^(?:\\Wedge)/,/^(?:\\wedge)/,/^(?:\\Vvert)/,/^(?:\\Vvdash)/,/^(?:\\Vert)/,/^(?:\\vert)/,/^(?:\\veebar)/,/^(?:\\Vee)/,/^(?:\\vee)/,/^(?:\\vec)/,/^(?:\\vdots)/,/^(?:\\VDash)/,/^(?:\\Vdash)/,/^(?:\\vDash)/,/^(?:\\vdash)/,/^(?:\\Vbar)/,/^(?:\\vartriangleright)/,/^(?:\\vartriangleleft)/,/^(?:\\vartriangle)/,/^(?:\\vartheta)/,/^(?:\\varsupsetneqq)/,/^(?:\\varsupsetneq)/,/^(?:\\varsubsetneqq)/,/^(?:\\varsubsetneqq)/,/^(?:\\varsubsetneq)/,/^(?:\\varsigma)/,/^(?:\\varrho)/,/^(?:\\varpropto)/,/^(?:\\varpi)/,/^(?:\\varphi)/,/^(?:\\varnothing)/,/^(?:\\varkappa)/,/^(?:\\varepsilon)/,/^(?:\\Uuparrow)/,/^(?:\\upuparrows)/,/^(?:\\Upsilon)/,/^(?:\\upsilon)/,/^(?:\\Upsi)/,/^(?:\\uplus)/,/^(?:\\upint)/,/^(?:\\upharpoonright)/,/^(?:\\upharpoonleft)/,/^(?:\\Updownarrow)/,/^(?:\\updownarrow)/,/^(?:\\updarr)/,/^(?:\\Uparrow)/,/^(?:\\uparrow)/,/^(?:\\uparr)/,/^(?:\\unrhd)/,/^(?:\\unlhd)/,/^(?:\\Union)/,/^(?:\\union)/,/^(?:\\underset)/,/^(?:\\underoverset)/,/^(?:\\underline)/,/^(?:\\underbrace)/,/^(?:\\udots)/,/^(?:\u2ADD\u0338)/,/^(?:\u2ACC\uFE00)/,/^(?:\u2ACB\uFE00)/,/^(?:\u2AB0\u0338)/,/^(?:\u2AAF\u0338)/,/^(?:\u2AA2\u0338)/,/^(?:\u2AA1\u0338)/,/^(?:\u2A7E\u0338)/,/^(?:\u2A7D\u0338)/,/^(?:\u29D0\u0338)/,/^(?:\u29CF\u0338)/,/^(?:\u2290\u0338)/,/^(?:\u228F\u0338)/,/^(?:\u228B\uFE00)/,/^(?:\u228A\uFE00)/,/^(?:\u2283\u20D2)/,/^(?:\u2282\u20D2)/,/^(?:\u227F\u0338)/,/^(?:\u226B\u0338)/,/^(?:\u226A\u0338)/,/^(?:\u2269\uFE00)/,/^(?:\u2268\uFE00)/,/^(?:\u2266\u0338)/,/^(?:\u224F\u0338)/,/^(?:\u224E\u0338)/,/^(?:\u2242\u0338)/,/^(?:\u223D\u0331)/,/^(?:\u2237\u2248)/,/^(?:\u2237\u223C)/,/^(?:\u2237\u2212)/,/^(?:\u2236\u2248)/,/^(?:\u2236\u223C)/,/^(?:\u2212\u2237)/,/^(?:\u007C\u007C\u007C)/,/^(?:\u007C\u007C)/,/^(?:\u003E\u003D)/,/^(?:\u003D\u2237)/,/^(?:\u003D\u2237)/,/^(?:\u003D\u003D)/,/^(?:\u003C\u003E)/,/^(?:\u003C\u003D)/,/^(?:\u003A\u003D)/,/^(?:\u002F\u003D)/,/^(?:\u002F\u002F)/,/^(?:\u002E\u002E\u002E)/,/^(?:\u002E\u002E)/,/^(?:\u002D\u003E)/,/^(?:\u002D\u003D)/,/^(?:\u002D\u002D)/,/^(?:\u002B\u003D)/,/^(?:\u002B\u002B)/,/^(?:\u002A\u003D)/,/^(?:\u002A\u002A)/,/^(?:\u0026\u0026)/,/^(?:\u0021\u003D)/,/^(?:\u0021\u0021)/,/^(?:\\twoheadrightarrowtail)/,/^(?:\\twoheadrightarrow)/,/^(?:\\twoheadleftarrow)/,/^(?:\\tripleintegral)/,/^(?:\\trianglerighteq)/,/^(?:\\triangleright)/,/^(?:\\triangleq)/,/^(?:\\trianglelefteq)/,/^(?:\\triangleleft)/,/^(?:\\triangledown)/,/^(?:\\triangle)/,/^(?:\\towa)/,/^(?:\\tosa)/,/^(?:\\top)/,/^(?:\\tooltip)/,/^(?:\\tona)/,/^(?:\\toggle)/,/^(?:\\toea)/,/^(?:\\to)/,/^(?:\\timesb)/,/^(?:\\times)/,/^(?:\\tilde)/,/^(?:\\thinspace)/,/^(?:\\thickspace)/,/^(?:\\thicksim)/,/^(?:\\thickapprox)/,/^(?:\\Theta)/,/^(?:\\theta)/,/^(?:\\therefore)/,/^(?:\\tfrac)/,/^(?:\\textstyle)/,/^(?:\\textsize)/,/^(?:\\textquotedblright)/,/^(?:\\textquotedblleft)/,/^(?:\\textasciitilde)/,/^(?:\\textasciigrave)/,/^(?:\\textasciicircumflex)/,/^(?:\\textasciiacute)/,/^(?:\\text)/,/^(?:\\tensor)/,/^(?:\\tbinom)/,/^(?:\\Tau)/,/^(?:\\tau)/,/^(?:\\swArrow)/,/^(?:\\swarrow)/,/^(?:\\swArr)/,/^(?:\\swarr)/,/^(?:\\surd)/,/^(?:\\supsetneqq)/,/^(?:\\supsetneq)/,/^(?:\\supseteqq)/,/^(?:\\supseteq)/,/^(?:\\Supset)/,/^(?:\\supset)/,/^(?:\\sum)/,/^(?:\\succsim)/,/^(?:\\succnsim)/,/^(?:\\succneqq)/,/^(?:\\succnapprox)/,/^(?:\\succeq)/,/^(?:\\succcurlyeq)/,/^(?:\\succapprox)/,/^(?:\\succ)/,/^(?:\\substack)/,/^(?:\\subsetneqq)/,/^(?:\\subsetneq)/,/^(?:\\subseteqq)/,/^(?:\\subseteq)/,/^(?:\\Subset)/,/^(?:\\subset)/,/^(?:\\statusline)/,/^(?:\\star)/,/^(?:\\stackrel)/,/^(?:\\sslash)/,/^(?:\\square)/,/^(?:\\sqsupseteq)/,/^(?:\\sqsupset)/,/^(?:\\sqsubseteq)/,/^(?:\\sqsubset)/,/^(?:\\sqrt)/,/^(?:\\sqcup)/,/^(?:\\sqcap)/,/^(?:\\sphericalangle)/,/^(?:\\spadesuit)/,/^(?:\\space)/,/^(?:\\smile)/,/^(?:\\smallsmile)/,/^(?:\\smallsetminus)/,/^(?:\\smallfrown)/,/^(?:\\slash)/,/^(?:\\simeq)/,/^(?:\\sim)/,/^(?:\\Sigma)/,/^(?:\\sigma)/,/^(?:\\shuffle)/,/^(?:\\shortparallel)/,/^(?:\\shortmid)/,/^(?:\\sharp)/,/^(?:\\setminus)/,/^(?:\\seovnearrow)/,/^(?:\\seArrow)/,/^(?:\\searrow)/,/^(?:\\seArr)/,/^(?:\\searr)/,/^(?:\\scriptsize)/,/^(?:\\scriptscriptsize)/,/^(?:\\rtimes)/,/^(?:\\Rsh)/,/^(?:\\Rrightarrow)/,/^(?:\\rrangle)/,/^(?:\\rq)/,/^(?:\\rowspan)/,/^(?:\\rowopts)/,/^(?:\\rowlines)/,/^(?:\\rowalign)/,/^(?:\\root)/,/^(?:\\rmoustache)/,/^(?:\\risingdotseq)/,/^(?:\\righttoleftarrow)/,/^(?:\\rightthreetimes)/,/^(?:\\rightsquigarrow)/,/^(?:\\rightrightarrows)/,/^(?:\\rightleftharpoons)/,/^(?:\\rightleftarrows)/,/^(?:\\rightharpoonup)/,/^(?:\\rightharpoondown)/,/^(?:\\rightarrowtriangle)/,/^(?:\\rightarrowtail)/,/^(?:\\Rightarrow)/,/^(?:\\rightarrow)/,/^(?:\\right)/,/^(?:\\Rho)/,/^(?:\\rho)/,/^(?:\\rhd)/,/^(?:\\rfloor)/,/^(?:\\Re)/,/^(?:\\rdiagovsearrow)/,/^(?:\\rdiagovfdiag)/,/^(?:\\rceil)/,/^(?:\\rbrack)/,/^(?:\\rbrace)/,/^(?:\\rangle)/,/^(?:\\rang)/,/^(?:\\questeq)/,/^(?:\\quadrupleintegral)/,/^(?:\\quad)/,/^(?:\\qquad)/,/^(?:\\qed)/,/^(?:\\Psi)/,/^(?:\\psi)/,/^(?:\\propto)/,/^(?:\\product)/,/^(?:\\prod)/,/^(?:\\prime)/,/^(?:\\precsim)/,/^(?:\\precnsim)/,/^(?:\\precneqq)/,/^(?:\\precnapprox)/,/^(?:\\preceq)/,/^(?:\\preccurlyeq)/,/^(?:\\precapprox)/,/^(?:\\prec)/,/^(?:\\pmod)/,/^(?:\\pm)/,/^(?:\\plusdot)/,/^(?:\\plusb)/,/^(?:\\pitchfork)/,/^(?:\\Pi)/,/^(?:\\pi)/,/^(?:\\Phi)/,/^(?:\\phi)/,/^(?:\\phantom)/,/^(?:\\Perp)/,/^(?:\\perp)/,/^(?:\\partialmeetcontraction)/,/^(?:\\partial)/,/^(?:\\parr)/,/^(?:\\parallel)/,/^(?:\\padding)/,/^(?:\\overset)/,/^(?:\\overline)/,/^(?:\\overbrace)/,/^(?:\\over)/,/^(?:\\Otimes)/,/^(?:\\otimes)/,/^(?:\\oslash)/,/^(?:[\u007E\u00AF\u02C6\u02C7\u02C9\u02CD\u02DC\u02F7\u0302\u203E\u2044\u2190-\u2199\u219C-\u21AD\u21AF-\u21B5\u21B9\u21BC-\u21CC\u21D0-\u21DD\u21E0-\u21F0\u21F3\u21F5\u21F6\u21FD-\u21FF\u2215\u221A\u23B4\u23B5\u23DC-\u23E1\u27F0\u27F1\u27F5-\u27FF\u290A-\u2910\u2912\u2913\u2921\u2922\u294E-\u2961\u296E\u296F\u2B45\u2B46])/,/^(?:[\u2032-\u2035\u2057])/,/^(?:[\u220F-\u2211\u22C0-\u22C3\u2A00-\u2A0A\u2A10-\u2A14\u2AFC\u2AFF])/,/^(?:\\Oplus)/,/^(?:\\oplus)/,/^(?:[\u0028\u0029\u005B\u005D\u007C\u2016\u2308-\u230B\u2329\u232A\u2772\u2773\u27E6-\u27EF\u2980\u2983-\u2998\u29FC\u29FD])/,/^(?:[\u2018\u2019\u201C\u201D])/,/^(?:\\operatorname)/,/^(?:[\u0021-\u0023\u002A-\u002C\u002F\u003A-\u0040\u0060\u00A8\u00AA\u00AC\u00B0-\u00B4\u00B7-\u00BA\u00D7\u00F7\u02CA\u02CB\u02D8-\u02DA\u02DD\u0311\u03F6\u201A\u201B\u201E-\u2022\u2026\u2036\u2037\u2043\u2061-\u2064\u20DB\u20DC\u2145\u2146\u214B\u219A\u219B\u21AE\u21B6-\u21B8\u21BA\u21BB\u21CD-\u21CF\u21DE\u21DF\u21F1\u21F2\u21F4\u21F7-\u21FC\u2200-\u2204\u2206-\u220E\u2212-\u2214\u2216-\u2219\u221B-\u221D\u221F-\u22BF\u22C4-\u22FF\u2305\u2306\u2322\u2323\u23B0\u23B1\u25A0\u25A1\u25AA\u25AB\u25AD-\u25B9\u25BC-\u25CF\u25D6\u25D7\u25E6\u2605\u2660-\u2663\u266D-\u266F\u2758\u27F2\u27F3\u2900-\u2909\u2911\u2914-\u2920\u2923-\u294D\u2962-\u296D\u2970-\u297F\u2981\u2982\u2999-\u29D9\u29DB-\u29FB\u29FE\u29FF\u2A0B-\u2A0F\u2A15-\u2ADB\u2ADD-\u2AFB\u2AFD\u2AFE])/,/^(?:\\ominus)/,/^(?:\\omicron)/,/^(?:\\Omega)/,/^(?:\\omega)/,/^(?:\\oint)/,/^(?:\\oiint)/,/^(?:\\oiiint)/,/^(?:\\odot)/,/^(?:\\odash)/,/^(?:\\obslash)/,/^(?:\\nwovnearrow)/,/^(?:\\nwArrow)/,/^(?:\\nwarrow)/,/^(?:\\nwArr)/,/^(?:\\nwarr)/,/^(?:\\nVDash)/,/^(?:\\nVdash)/,/^(?:\\nvDash)/,/^(?:\\nvdash)/,/^(?:\u221E)/,/^(?:\\Nu)/,/^(?:\\nu)/,/^(?:\\ntrianglerighteq)/,/^(?:\\ntriangleright)/,/^(?:\\ntrianglelefteq)/,/^(?:\\ntriangleleft)/,/^(?:\\nsupseteq)/,/^(?:\\nsupset)/,/^(?:\\nsuccsim)/,/^(?:\\nsucceq)/,/^(?:\\nsucc)/,/^(?:\\nsubseteqq)/,/^(?:\\nsubseteq)/,/^(?:\\nsubset)/,/^(?:\\nsime)/,/^(?:\\nsim)/,/^(?:\\nshortparallel)/,/^(?:\\nshortmid)/,/^(?:\\nRightarrow)/,/^(?:\\nrightarrow)/,/^(?:\\npreceq)/,/^(?:\\nprec)/,/^(?:\\nparallel)/,/^(?:\\notni)/,/^(?:\\notin)/,/^(?:\\not)/,/^(?:\\nmid)/,/^(?:\\nless)/,/^(?:\\nleqslant)/,/^(?:\\nleqq)/,/^(?:\\nleq)/,/^(?:\\nLeftrightarrow)/,/^(?:\\nleftrightarrow)/,/^(?:\\nLeftarrow)/,/^(?:\\nleftarrow)/,/^(?:\\ni)/,/^(?:\\ngtr)/,/^(?:\\ngeqslant)/,/^(?:\\ngeqq)/,/^(?:\\ngeq)/,/^(?:\\nexists)/,/^(?:\\nequiv)/,/^(?:\\neqsim)/,/^(?:\\neq)/,/^(?:\\neovsearrow)/,/^(?:\\neovnwarrow)/,/^(?:\\negthickspace)/,/^(?:\\negspace)/,/^(?:\\negmedspace)/,/^(?:\\neg)/,/^(?:\\neArrow)/,/^(?:\\nearrow)/,/^(?:\\neArr)/,/^(?:\\nearr)/,/^(?:\\ne)/,/^(?:\\ncong)/,/^(?:\\nBumpeq)/,/^(?:\\nbumpeq)/,/^(?:\\natural)/,/^(?:\\napprox)/,/^(?:\\nabla)/,/^(?:\\multiscripts)/,/^(?:\\multimap)/,/^(?:\\Mu)/,/^(?:\\mu)/,/^(?:\\mtext)/,/^(?:\\ms)/,/^(?:\\mp)/,/^(?:\\models)/,/^(?:\\mod)/,/^(?:\\mo)/,/^(?:\\mn)/,/^(?:\\mlcp)/,/^(?:\\minusdot)/,/^(?:\\minusb)/,/^(?:\\minus)/,/^(?:\\min)/,/^(?:\\mid)/,/^(?:\\mi)/,/^(?:\\mho)/,/^(?:\\mho)/,/^(?:\\medspace)/,/^(?:\\measuredangle)/,/^(?:\\mathtt)/,/^(?:\\mathsf)/,/^(?:\\mathscr)/,/^(?:\\mathrm)/,/^(?:\\mathrlap)/,/^(?:\\mathrel)/,/^(?:\\mathraisebox)/,/^(?:\\mathop)/,/^(?:\\mathmit)/,/^(?:\\mathllap)/,/^(?:\\mathit)/,/^(?:\\mathfrak)/,/^(?:\\mathfr)/,/^(?:\\mathclap)/,/^(?:\\mathcal)/,/^(?:\\mathbscr)/,/^(?:\\mathbit)/,/^(?:\\mathbin)/,/^(?:\\mathbf)/,/^(?:\\mathbcal)/,/^(?:\\mathbb)/,/^(?:\\Mapsto)/,/^(?:\\mapsto)/,/^(?:\\Mapsfrom)/,/^(?:\\map)/,/^(?:\\lvertneqq)/,/^(?:\\lvertneqq)/,/^(?:\\ltimes)/,/^(?:\\lt)/,/^(?:\\Lsh)/,/^(?:\\lq)/,/^(?:\\lozenge)/,/^(?:\\lowint)/,/^(?:\\looparrowright)/,/^(?:\\looparrowleft)/,/^(?:\\Longrightarrow)/,/^(?:\\longrightarrow)/,/^(?:\\longmapsto)/,/^(?:\\Longleftrightarrow)/,/^(?:\\longleftrightarrow)/,/^(?:\\Longleftarrow)/,/^(?:\\longleftarrow)/,/^(?:\\lnsim)/,/^(?:\\lneqq)/,/^(?:\\lneq)/,/^(?:\\lnapprox)/,/^(?:\\lmoustache)/,/^(?:\\lll)/,/^(?:\\Lleftarrow)/,/^(?:\\llangle)/,/^(?:\\ll)/,/^(?:\\lhd)/,/^(?:\\lfloor)/,/^(?:\\lesssim)/,/^(?:\\lessgtr)/,/^(?:\\lesseqqgtr)/,/^(?:\\lesseqgtr)/,/^(?:\\lessdot)/,/^(?:\\lessapprox)/,/^(?:\\less)/,/^(?:\\leqslant)/,/^(?:\\leqq)/,/^(?:\\leq)/,/^(?:\\lefttorightarrow)/,/^(?:\\leftthreetimes)/,/^(?:\\leftsquigarrow)/,/^(?:\\leftrightsquigarrow)/,/^(?:\\leftrightharpoons)/,/^(?:\\leftrightarrowtria\*)/,/^(?:\\leftrightarrows)/,/^(?:\\Leftrightarrow)/,/^(?:\\leftrightarrow)/,/^(?:\\leftleftarrows)/,/^(?:\\leftharpoonup)/,/^(?:\\leftharpoondown)/,/^(?:\\leftarrowtriangle)/,/^(?:\\leftarrowtail)/,/^(?:\\Leftarrow)/,/^(?:\\leftarrow)/,/^(?:\\left)/,/^(?:\\le)/,/^(?:\\ldots)/,/^(?:\\lceil)/,/^(?:\\lbrack)/,/^(?:\\lbrace)/,/^(?:\\langle)/,/^(?:\\lang)/,/^(?:\\Lambda)/,/^(?:\\lambda)/,/^(?:\\kernelcontraction)/,/^(?:\\Kappa)/,/^(?:\\kappa)/,/^(?:\\jmath)/,/^(?:\\itexnum)/,/^(?:\\Iota)/,/^(?:\\iota)/,/^(?:\\invamp)/,/^(?:\\intx)/,/^(?:\\intprodr)/,/^(?:\\intprod)/,/^(?:\\Intersection)/,/^(?:\\intersection)/,/^(?:\\interleave)/,/^(?:\\intercal)/,/^(?:\\integral)/,/^(?:\\intcup)/,/^(?:\\intcap)/,/^(?:\\intBar)/,/^(?:\\intbar)/,/^(?:\\int)/,/^(?:\\infty)/,/^(?:\\infinity)/,/^(?:\\inf)/,/^(?:\\in)/,/^(?:\\implies)/,/^(?:\\impliedby)/,/^(?:\\imath)/,/^(?:\\Im)/,/^(?:\\iint)/,/^(?:\\iiint)/,/^(?:\\iiiint)/,/^(?:\\iff)/,/^(?:\\hslash)/,/^(?:\\href)/,/^(?:\\hookrightarrow)/,/^(?:\\hookleftarrow)/,/^(?:\\hkswarow)/,/^(?:\\hksearow)/,/^(?:\\heartsuit)/,/^(?:\\hbar)/,/^(?:\\hat)/,/^(?:\\gvertneqq)/,/^(?:\\gvertneqq)/,/^(?:\\gtrsim)/,/^(?:\\gtrless)/,/^(?:\\gtreqqless)/,/^(?:\\gtreqless)/,/^(?:\\gtrdot)/,/^(?:\\gtrapprox)/,/^(?:\\gt)/,/^(?:\\greater)/,/^(?:\\gnsim)/,/^(?:\\gneqq)/,/^(?:\\gneq)/,/^(?:\\gnapprox)/,/^(?:\\gimel)/,/^(?:\\ggg)/,/^(?:\\gg)/,/^(?:\\geqslant)/,/^(?:\\geqq)/,/^(?:\\geq)/,/^(?:\\ge)/,/^(?:\\Gamma)/,/^(?:\\gamma)/,/^(?:\\frown)/,/^(?:\\frame)/,/^(?:\\frac)/,/^(?:\\forksnot)/,/^(?:\\forks)/,/^(?:\\forall)/,/^(?:\\flat)/,/^(?:\\fdiagovrdiag)/,/^(?:\\fdiagovnearrow)/,/^(?:\\fallingdotseq)/,/^(?:\\exists)/,/^(?:\\eth)/,/^(?:\\eth)/,/^(?:\\Eta)/,/^(?:\\eta)/,/^(?:\\equiv)/,/^(?:\\equalrows)/,/^(?:\\equalcols)/,/^(?:\\eqslantless)/,/^(?:\\eqslantgtr)/,/^(?:\\eqsim)/,/^(?:\\Eqqcolon)/,/^(?:\\eqqcolon)/,/^(?:\\Eqcolon)/,/^(?:\\Eqcolon)/,/^(?:\\Eqcolon)/,/^(?:\\Eqcolon)/,/^(?:\\eqcolon)/,/^(?:\\eqcirc)/,/^(?:\\epsilon)/,/^(?:\\end\{Vmatrix\})/,/^(?:\\end\{vmatrix\})/,/^(?:\\endtoggle)/,/^(?:\\end\{split\})/,/^(?:\\end\{smallmatrix\})/,/^(?:\\end\{pmatrix\})/,/^(?:\\end\{matrix\})/,/^(?:\\end\{gathered\})/,/^(?:\\end\{cases\})/,/^(?:\\end\{Bmatrix\})/,/^(?:\\end\{bmatrix\})/,/^(?:\\end\{array\})/,/^(?:\\end\{aligned\})/,/^(?:\\emptyset)/,/^(?:\\empty)/,/^(?:\\embedsin)/,/^(?:\\ell)/,/^(?:\\duparr)/,/^(?:\\dualmap)/,/^(?:\\drbkarrow)/,/^(?:\\downuparrow)/,/^(?:\\downharpoonright)/,/^(?:\\downharpoonleft)/,/^(?:\\downdownarrows)/,/^(?:\\Downarrow)/,/^(?:\\downarrow)/,/^(?:\\doubleintegral)/,/^(?:\\doublebarwedge)/,/^(?:\\doublebarwedge)/,/^(?:\\dots)/,/^(?:\\dotplus)/,/^(?:\\dotminus)/,/^(?:\\doteqdot)/,/^(?:\\Doteq)/,/^(?:\\doteq)/,/^(?:\\dot)/,/^(?:\\divideontimes)/,/^(?:\\div)/,/^(?:\\displaystyle)/,/^(?:\\disjquant)/,/^(?:\\digamma)/,/^(?:\\diamondsuit)/,/^(?:\\Diamond)/,/^(?:\\diamond)/,/^(?:\\det|\\gcd|\\liminf|\\limsup|\\lim|\\max|\\Pr|\\sup)/,/^(?:\\Delta)/,/^(?:\\delta)/,/^(?:\\Del)/,/^(?:\\degree)/,/^(?:\\Ddownarrow)/,/^(?:\\ddotseq)/,/^(?:\\ddots)/,/^(?:\\ddot)/,/^(?:\\dddot)/,/^(?:\\dddot)/,/^(?:\\ddddot)/,/^(?:\\ddddot)/,/^(?:\\ddagger)/,/^(?:\\dblcolon)/,/^(?:\\dbkarow)/,/^(?:\\Dashv)/,/^(?:\\dashV)/,/^(?:\\dashv)/,/^(?:\\dashrightarrow)/,/^(?:\\dashleftarrow)/,/^(?:\\darr)/,/^(?:\\daleth)/,/^(?:\\dagger)/,/^(?:\\curvearrowright)/,/^(?:\\curvearrowleft)/,/^(?:\\curvearrowbotright)/,/^(?:\\curlywedge)/,/^(?:\\curlyvee)/,/^(?:\\curlyeqsucc)/,/^(?:\\curlyeqprec)/,/^(?:\\cupdot)/,/^(?:\\Cup)/,/^(?:\\cup)/,/^(?:\\coproduct)/,/^(?:\\coprod)/,/^(?:\\contourintegral)/,/^(?:\\conjquant)/,/^(?:\\conint)/,/^(?:\\cong)/,/^(?:\\complement)/,/^(?:\\colspan)/,/^(?:\\color)/,/^(?:\\Colonsim)/,/^(?:\\colonsim)/,/^(?:\\Coloneqq)/,/^(?:\\coloneqq)/,/^(?:\\Coloneq)/,/^(?:\\coloneq)/,/^(?:\\Colonapprox)/,/^(?:\\colonapprox)/,/^(?:\\Colon)/,/^(?:\\colon)/,/^(?:\\collines)/,/^(?:\\collayout)/,/^(?:\\colalign)/,/^(?:\\clubsuit)/,/^(?:\\closure)/,/^(?:\\circleddash)/,/^(?:\\circledcirc)/,/^(?:\\circledast)/,/^(?:\\circlearrowright)/,/^(?:\\circlearrowleft)/,/^(?:\\circeq)/,/^(?:\\circ)/,/^(?:\\choose)/,/^(?:\\chi)/,/^(?:\\check)/,/^(?:\\cellopts)/,/^(?:\\cdots)/,/^(?:\\cdotp)/,/^(?:\\cdot)/,/^(?:\\Cap)/,/^(?:\\cap)/,/^(?:\\bumpeqq)/,/^(?:\\Bumpeq)/,/^(?:\\bumpeq)/,/^(?:\\bullet)/,/^(?:\\btimes)/,/^(?:\\boxtimes)/,/^(?:\\boxplus)/,/^(?:\\boxminus)/,/^(?:\\boxed)/,/^(?:\\boxdot)/,/^(?:\\boxdiag)/,/^(?:\\boxcircle)/,/^(?:\\boxbslash)/,/^(?:\\boxast)/,/^(?:\\Box)/,/^(?:\\bowtie)/,/^(?:\\bottom)/,/^(?:\\bot)/,/^(?:\\boldsymbol)/,/^(?:\\blacktriangleright)/,/^(?:\\blacktriangleleft)/,/^(?:\\blacktriangledown)/,/^(?:\\blacktriangle)/,/^(?:\\blacksquare)/,/^(?:\\blacklozenge)/,/^(?:\\bkarow)/,/^(?:\\binom)/,/^(?:\\bigwedge)/,/^(?:\\bigvee)/,/^(?:\\biguplus)/,/^(?:\\bigtriangleup)/,/^(?:\\bigtriangledown)/,/^(?:\\bigtimes)/,/^(?:\\bigstar)/,/^(?:\\bigsqcup)/,/^(?:\\bigsqcap)/,/^(?:\\Bigr)/,/^(?:\\bigr)/,/^(?:\\bigotimes)/,/^(?:\\bigoplus)/,/^(?:\\bigodot)/,/^(?:\\Bigl)/,/^(?:\\bigl)/,/^(?:\\biginterleave)/,/^(?:\\Biggr)/,/^(?:\\biggr)/,/^(?:\\Biggl)/,/^(?:\\biggl)/,/^(?:\\Bigg)/,/^(?:\\bigg)/,/^(?:\\bigcupdot)/,/^(?:\\bigcup)/,/^(?:\\bigcirc)/,/^(?:\\bigcap)/,/^(?:\\Big)/,/^(?:\\big)/,/^(?:\\bgcolor)/,/^(?:\\between)/,/^(?:\\beth)/,/^(?:\\Beta)/,/^(?:\\beta)/,/^(?:\\begin\{Vmatrix\})/,/^(?:\\begin\{vmatrix\})/,/^(?:\\begintoggle)/,/^(?:\\begin\{split\})/,/^(?:\\begin\{smallmatrix\})/,/^(?:\\begin\{pmatrix\})/,/^(?:\\begin\{matrix\})/,/^(?:\\begin\{gathered\})/,/^(?:\\begin\{cases\})/,/^(?:\\begin\{Bmatrix\})/,/^(?:\\begin\{bmatrix\})/,/^(?:\\begin\{array\})/,/^(?:\\begin\{aligned\})/,/^(?:\\because)/,/^(?:\\BbbPi)/,/^(?:\\barwedge)/,/^(?:\\bar)/,/^(?:\\backslash)/,/^(?:\\backsimeq)/,/^(?:\\backsim)/,/^(?:\\backprime)/,/^(?:\\backepsilon)/,/^(?:\\atop)/,/^(?:\\asymp)/,/^(?:\\ast)/,/^(?:\\arrayopts)/,/^(?:\\array)/,/^(?:\\arccos|\\arcsin|\\arctan|\\arg|\\cosh|\\cos|\\coth|\\cot|\\csc|\\deg|\\dim|\\exp|\\hom|\\ker|\\lg|\\ln|\\log|\\sec|\\sinh|\\sin|\\tanh|\\tan)/,/^(?:\\approxeq)/,/^(?:\\approx)/,/^(?:\\angle)/,/^(?:\\amalg)/,/^(?:\\Alpha)/,/^(?:\\alpha)/,/^(?:\\align)/,/^(?:\\aleph)/,/^(?:[\u0041-\u005A])/,/^(?:[\u0391-\u03A1\u03A3\u03A4\u03A6-\u03A9])/,/^(?:[\u0061-\u007A\u0131\u0237])/,/^(?:[\u03B1-\u03C1\u03C3-\u03C9\u03D1\u03D5\u03D6\u03F0\u03F1\u03F4\u03F5])/,/^(?:\\adots)/,/^(?:\\AA)/,/^(?:[\u00F0\u03C2\u03D0\u03D2\u03DA-\u03DD\u03E0\u03E1\u0428\u0608\u0627-\u063A\u2102\u210A-\u210D\u210F-\u2113\u2115\u2118-\u211D\u2124\u2127\u2128\u212B-\u212D\u212F-\u2131\u2133-\u2138\u213C\u213D\u213F\u2205]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB\uDEF0\uDEF1]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDFCB])/,/^(?:\\\$)/,/^(?:\\\})/,/^(?:\\\|)/,/^(?:\\\{)/,/^(?:\\;)/,/^(?:\\:)/,/^(?:\\,)/,/^(?:\\&)/,/^(?:\\%)/,/^(?:\\#)/,/^(?:\\!)/,/^(?:-)/,/^(?:'''')/,/^(?:''')/,/^(?:'')/,/^(?:')/,/^(?:[\uD800-\uDBFF])/,/^(?:[\uDC00-\uDFFF])/,/^(?:.)/], -conditions: {"MATH0":{"rules":[14,15,16,17,18,19,20,21,22,23,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883],"inclusive":true},"MATH1":{"rules":[14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883],"inclusive":true},"OPTARG":{"rules":[13,14,15,16,17,18,19,20,21,22,23,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883],"inclusive":true},"DOCUMENT":{"rules":[1,2,3,4,5],"inclusive":false},"TRYOPTARG":{"rules":[6,7],"inclusive":false},"TEXTOPTARG":{"rules":[8,9],"inclusive":false},"TEXTARG":{"rules":[10,11,12],"inclusive":false},"INITIAL":{"rules":[0,14,15,16,17,18,19,20,21,22,23,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883],"inclusive":true}} -}); -return lexer; -})(); -parser.lexer = lexer; -function Parser () { - this.yy = {}; -} -Parser.prototype = parser;parser.Parser = Parser; -return new Parser; -})(); -//////////////////////////////////////////////////////////////////////////////// -// Export the public API to commonJS programs. -//////////////////////////////////////////////////////////////////////////////// -if (typeof require !== "undefined" && typeof exports !== "undefined") { - exports.setDOMParser = function (aDOMParser) { - TeXZilla.setDOMParser(aDOMParser); - }; - exports.setXMLSerializer = function (aXMLSerializer) { - TeXZilla.setXMLSerializer(aXMLSerializer); - }; - exports.setSafeMode = function (aEnable) { - TeXZilla.setSafeMode(aEnable); - }; - exports.setItexIdentifierMode = function (aEnable) { - TeXZilla.setItexIdentifierMode(aEnable); - }; - exports.getTeXSource = function () { - return TeXZilla.getTeXSource.apply(TeXZilla, arguments); - }; - exports.toMathMLString = function () { - return TeXZilla.toMathMLString.apply(TeXZilla, arguments); - }; - exports.toMathML = function () { - return TeXZilla.toMathML.apply(TeXZilla, arguments); - }; - exports.toImage = function () { - return TeXZilla.toImage.apply(TeXZilla, arguments); - }; - exports.filterString = function () { - return TeXZilla.filterString.apply(TeXZilla, arguments); - }; - exports.filterElement = function () { - return TeXZilla.filterElement.apply(TeXZilla, arguments); - }; -} - -//////////////////////////////////////////////////////////////////////////////// -// Export the command-line API to commonJS programs. -//////////////////////////////////////////////////////////////////////////////// -if (typeof require !== "undefined") { - - // FIXME: This tries to work with slimerjs, phantomjs and nodejs. Ideally, - // we should have a standard commonJS interface. - // https://github.com/fred-wang/TeXZilla/issues/6 - - var exitCommonJS = function (aStatus) { - if (typeof process !== "undefined") { - process.exit(aStatus); - } else if (typeof slimer !== "undefined") { - slimer.exit(aStatus); - } else if (typeof phantom !== "undefined") { - phantom.exit(aStatus); - } - }; - - var usage = function () { - // Display the usage information. - console.log("\nUsage:\n"); - console.log("commonjs TeXZilla.js [help]"); - console.log(" Print this help message.\n"); - console.log("commonjs TeXZilla.js parser aTeX [aDisplay] [aRTL] [aThrowExceptionOnError]"); - console.log(" Print TeXZilla.toMathMLString(aTeX, aDisplay, aRTL, aThrowExceptionOnError)"); - console.log(" The interpretation of arguments and the default values are the same.\n"); - console.log("commonjs TeXZilla.js webserver [port] [safe] [itexId]"); - console.log(" Start a Web server on the specified port (default:3141)"); - console.log(" See the TeXZilla wiki for details.\n"); - console.log("cat input | commonjs TeXZilla.js streamfilter [safe] [itexId] > output"); - console.log(" Make TeXZilla behaves as a stream filter. The TeX fragments are"); - console.log(" converted into MathML."); - console.log(" See the TeXZilla wiki for details.\n"); - console.log(" where commonjs is slimerjs, nodejs or phantomjs."); - }; - - var setParamValue = function (aParam, aKey, aString) { - // Set the param value from the string value. - if (aKey === "tex") { - aParam[aKey] = aString; - } else if (aKey === "display" || aKey === "rtl" || aKey === "exception" || - aKey === "safe" || aKey === "itexId") { - aParam[aKey] = (aString === "true"); - } - }; - - var getMathMLString = function (aParam) { - // Call the TeXZilla parser with the specified parameters and - // return the MathML output. - return TeXZilla.toMathMLString(aParam.tex, aParam.display, - aParam.rtl, aParam.exception); - }; - - var getParametersFromURL = function (aURL) { - // Get the param values from the GET URL. - var param, query, vars, i, pair, key, value; - param = {}; - query = aURL.split("?")[1]; - if (query) { - vars = query.split("&"); - for (i = 0; i < vars.length; i++) { - pair = vars[i].split("="); - key = decodeURIComponent(pair[0]).toLowerCase(); - value = decodeURIComponent(pair[1]); - setParamValue(param, key, value); - } - } - return param; - }; - - var getParametersFromPOSTData = function (aPOSTData) { - // Get the param values from the POST JSON data. - var param = {}, json = JSON.parse(aPOSTData), key; - for (key in json) { - setParamValue(param, key, json[key]); - } - return param; - }; - - var getServerResponseFromParam = function (aParam) { - // Get the JSON data to send back. - var data = { tex: aParam.tex }; - try { - data.mathml = getMathMLString(aParam); - data.exception = null; - } catch (e) { - data.exception = e.message; - } - return JSON.stringify(data); - }; - - var webserverListener = function (aRequest, aResponse) { - // Listener for the "webserver" module (phantomjs, slimerjs). - var param = {}, json = {}, response; - if (aRequest.method === "GET") { - param = getParametersFromURL(aRequest.url); - } else if (aRequest.method === "POST") { - param = getParametersFromPOSTData(aRequest.post); - } - if (param.tex !== undefined) { - json = getServerResponseFromParam(param); - } - response = JSON.stringify(json); - aResponse.statusCode = 200; - aResponse.setHeader("Content-Type", "application/json"); - aResponse.write(response); - aResponse.close(); - }; - - var httpListener = function (aRequest, aResponse) { - // Listener for the "http" module (nodejs). - var param = {}, json = {}, response, body = ""; - aRequest.setEncoding("utf8"); - aRequest.on("data", function (aChunk) { - body += aChunk; - }); - aRequest.on("end", function () { - aResponse.writeHead(200, {"Content-Type": ""}); - if (aRequest.method === "GET") { - param = getParametersFromURL(aRequest.url); - } else if (aRequest.method === "POST") { - param = getParametersFromPOSTData(body); - } - if (param.tex !== undefined) { - json = getServerResponseFromParam(param); - } - response = JSON.stringify(json); - aResponse.writeHead(200, { "Content-Type": "application/json" }); - aResponse.write(response); - aResponse.end(); - }); - }; - - var startWebServer = function (aPort) - { - try { - require("webserver").create().listen(aPort, webserverListener); - } catch (e) { - require("http").createServer(httpListener).listen(aPort); - } - console.log("Web server started on http://localhost:" + aPort); - } - - var main = function (aArgs, aStdinContent) { - // Main command line function. - var param = {}; - if (aArgs.length >= 3 && aArgs[1] === "parser") { - // Parse the string and print the output. - setParamValue(param, "tex", aArgs[2]); - setParamValue(param, "display", aArgs[3]); - setParamValue(param, "rtl", aArgs[4]); - setParamValue(param, "exception", aArgs[5]); - try { - console.log(getMathMLString(param)); - exitCommonJS(0); - } catch (e) { - console.log(e); - exitCommonJS(1); - } - } else if (aArgs.length >= 2 && aArgs[1] === "webserver") { - setParamValue(param, "safe", aArgs[2]); - TeXZilla.setSafeMode(param.safe); - setParamValue(param, "itexId", aArgs[3]); - TeXZilla.setItexIdentifierMode(param.itexId); - // Run a Web server. - try { - startWebServer(aArgs.length >= 3 ? parseInt(aArgs[2], 10) : 3141); - } catch (e) { - console.log(e); - exitCommonJS(1); - } - } else if (aArgs.length >= 2 && aArgs[1] === "streamfilter") { - setParamValue(param, "safe", aArgs[2]); - TeXZilla.setSafeMode(param.safe); - setParamValue(param, "itexId", aArgs[3]); - TeXZilla.setItexIdentifierMode(param.itexId); - if (typeof process !== "undefined") { - var stdinContent = ""; - process.stdin.resume(); - process.stdin.setEncoding("utf-8"); - process.stdin.on("data", function(aData) { stdinContent += aData; }); - process.stdin.on("end", function() { - console.log(TeXZilla.filterString(stdinContent, true)); - exitCommonJS(0); - }); - } else { - // FIXME: Slimerjs does not seem to support stdin. - console.log(TeXZilla. - filterString(require("system").stdin.read(), true)); - exitCommonJS(0); - } - } else { - usage(); - exitCommonJS(0); - } - }; - - if (typeof exports === "undefined" || - (typeof module !== "undefined" && require.main === module)) { - // Process the command line arguments, the stdin content and execute the - // main program. - if (typeof process !== "undefined") { - main(process.argv.slice(1)); - } else { - main(require("system").args); - } - } -} diff --git a/utils/buildDocs.js b/utils/buildDocs.js deleted file mode 100644 index 3c1d0b38..00000000 --- a/utils/buildDocs.js +++ /dev/null @@ -1,92 +0,0 @@ -const fs = require("fs") // Node.js file system -const hurmetMark = require("./hurmetMark.cjs") -const temml = require('./temml.cjs'); -const katex = require('./katex.min.js'); -const TeXZilla = require("./TeXZilla.js"); - -// Build supported.html. -let supported = fs.readFileSync('./docs/supported.md').toString('utf8') -// convert Markdown to HTML -supported = hurmetMark.hmd.md2html(supported, true) -fs.writeFileSync('./site/docs/en/supported.html', supported) - -let table = fs.readFileSync('./docs/support_table.md').toString('utf8') -// convert Markdown to HTML -table = hurmetMark.hmd.md2html(table, true) -table = table.replace(/\(Not supported\)/g, `Not supported`) -fs.writeFileSync('./site/docs/en/support_table.html', table) - -let admin = fs.readFileSync('./docs/administration.md').toString('utf8') -// convert Markdown to HTML -admin = hurmetMark.hmd.md2html(admin, true) -fs.writeFileSync('./site/docs/en/administration.html', admin) - -// helper function for comparison page. -const arrayOfRegExMatches = (regex, text) => { - if (regex.constructor !== RegExp) { throw new Error('not RegExp') } - const result = [] - let match = null - // eslint-disable-next-line no-cond-assign - while (match = regex.exec(text)) { - result.push({ - value: match[0], - index: match.index, - lastindex: match.index + match[0].length - }) - } - return result -} - -// Comparison page -const temmlRegEx = /₮{1,2}[^₮]+₮{1,2}/g -let comp = fs.readFileSync('./docs/comparison.html').toString('utf8') -let macros = {}; -let matches = arrayOfRegExMatches(temmlRegEx, comp) -for (let i = matches.length - 1; i >= 0; i--) { - const displayMode = matches[i].value.charAt(1) === "₮" - let tex = displayMode - ? matches[i].value.slice(2, -2).trim() - : matches[i].value.slice(1, -1).trim(); - tex = tex.replace(/</g, "<").replace(/>/g, ">") - let math = temml.renderToString(tex, { displayMode, trust: true, macros }); - if (math.indexOf("#b22222") > -1) { - math = 'Not supported' - } - comp = comp.slice(0, matches[i].index) + math + comp.slice(matches[i].lastindex); -} - -const katexRegEx = /₭{1,2}[^₭]+₭{1,2}/g -macros = {}; -matches = arrayOfRegExMatches(katexRegEx, comp) -for (let i = matches.length - 1; i >= 0; i--) { - const displayMode = matches[i].value.charAt(1) === "₭" - let tex = displayMode - ? matches[i].value.slice(2, -2).trim() - : matches[i].value.slice(1, -1).trim(); - tex = tex.replace(/</g, "<").replace(/>/g, ">") - let math = katex.renderToString( - tex, - { displayMode, output: "mathml", trust: true, strict: false, throwOnError: false, macros } - ); - if (math.indexOf("#cc0000") > -1) { - math = 'Not supported' - } - comp = comp.slice(0, matches[i].index) + math + comp.slice(matches[i].lastindex); -} - -const texzillaRegEx = /₸{1,2}[^₸]+₸{1,2}/g -matches = arrayOfRegExMatches(texzillaRegEx, comp) -for (let i = matches.length - 1; i >= 0; i--) { - const displayMode = matches[i].value.charAt(1) === "₸" - let tex = displayMode - ? matches[i].value.slice(2, -2).trim() - : matches[i].value.slice(1, -1).trim(); - tex = tex.replace(/</g, "<").replace(/>/g, ">") - let math = TeXZilla.toMathMLString(tex) - if (math.indexOf("error") > -1) { - math = 'Not supported' - } - comp = comp.slice(0, matches[i].index) + math + comp.slice(matches[i].lastindex); -} - -fs.writeFileSync('./site/docs/en/comparison.html', comp) diff --git a/utils/buildTests.js b/utils/buildTests.js deleted file mode 100644 index ade5f3e4..00000000 --- a/utils/buildTests.js +++ /dev/null @@ -1,23 +0,0 @@ -const fs = require("fs") // Node.js file system -const hurmetMark = require("./hurmetMark.cjs") - -let katexTests = fs.readFileSync('./test/katex-tests.md').toString('utf8') -// convert Markdown to HTML -katexTests = hurmetMark.hmd.md2html(katexTests, true) -fs.writeFileSync('./site/tests/katex-tests.html', katexTests) - -let mhchemTests = fs.readFileSync('./test/mhchem-tests.md').toString('utf8') -mhchemTests = hurmetMark.hmd.md2html(mhchemTests, true) -fs.writeFileSync('./site/tests/mhchem-tests.html', mhchemTests) - -let mozillaTests = fs.readFileSync('./test/mozilla-tests.md').toString('utf8') -mozillaTests = hurmetMark.hmd.md2html(mozillaTests, true) -fs.writeFileSync('./site/tests/mozilla-tests.html', mozillaTests) - -let wikiTests = fs.readFileSync('./test/wiki-tests.md').toString('utf8') -wikiTests = hurmetMark.hmd.md2html(wikiTests, true) -fs.writeFileSync('./site/tests/wiki-tests.html', wikiTests) - -let latexmlTests = fs.readFileSync('./test/LaTeXML-tests.md').toString('utf8') -latexmlTests = hurmetMark.hmd.md2html(latexmlTests, true) -fs.writeFileSync('./site/tests/LaTeXML-tests.html', latexmlTests) diff --git a/utils/copyfiles.js b/utils/copyfiles.js deleted file mode 100644 index e1b4b4c1..00000000 --- a/utils/copyfiles.js +++ /dev/null @@ -1,56 +0,0 @@ -const fs = require('fs'); - -// Populate the `dist` folder. - -fs.copyFile('site/assets/Temml-Local.css', 'dist/Temml-Local.css', (err) => { - if (err) { throw err } -}) - -fs.copyFile('site/assets/Temml-Latin-Modern.css', 'dist/Temml-Latin-Modern.css', (err) => { - if (err) { throw err } -}) - -fs.copyFile('site/assets/Temml-Asana.css', 'dist/Temml-Asana.css', (err) => { - if (err) { throw err } -}) - -fs.copyFile('site/assets/Temml-STIX2.css', 'dist/Temml-STIX2.css', (err) => { - if (err) { throw err } -}) - -fs.copyFile('site/assets/Temml-XITS.css', 'dist/Temml-XITS.css', (err) => { - if (err) { throw err } -}) - -fs.copyFile('site/assets/temml.min.js', 'dist/temml.min.js', (err) => { - if (err) { throw err } -}) - -fs.copyFile('test/temml.js', 'dist/temml.js', (err) => { - if (err) { throw err } -}) - -fs.copyFile('utils/temml.cjs', 'dist/temml.cjs', (err) => { - if (err) { throw err } -}) - -fs.copyFile('utils/temml.mjs', 'dist/temml.mjs', (err) => { - if (err) { throw err } -}) - -fs.copyFile('test/temmlPostProcess.js', 'dist/temmlPostProcess.js', (err) => { - if (err) { throw err } -}) - -fs.copyFile('site/assets/Temml.woff2', 'dist/Temml.woff2', (err) => { - if (err) { throw err } -}) - -fs.copyFile('site/assets/mhchem.min.js', 'contrib/mhchem/mhchem.min.js', (err) => { - if (err) { throw err } -}) - -fs.copyFile('contrib/auto-render/test/auto-render.js', 'contrib/auto-render/dist/auto-render.js', -(err) => { - if (err) { throw err } -}) diff --git a/utils/hurmetMark.cjs b/utils/hurmetMark.cjs deleted file mode 100644 index 06b67c89..00000000 --- a/utils/hurmetMark.cjs +++ /dev/null @@ -1,1160 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { value: true }); - -/** - * # hurmetMark.js - * - * Hurmet.app uses a version of Markdown as a plain text file format. - * This version of Markdown is stricter in some ways than CommonMark or - * Gruber's original Markdown. So the parser can be considerably simplified. - * md2ast() returns an AST that matches the memory structure of a Hurmet.app document. - * - * ## Ways in which this syntax is more strict than Markdown. - * - * 1. Emphasis: _emphasis_ only. Asterisks do not create standard emphasis. - * 2. Strong emphasis: **strong emphasis** only. Underlines do not create strong emphasis. - * 3. Code blocks must be fenced by triple backticks. - * Indented text does not indicate a code block. - * 4. A blank line must precede the beginning of a list, even a nested list. - * 5. A hard line break is indicated when a line ends with "\". Double spaces do not count. - * 6. "Shortcut" reference links [ref] are not recognized. - * See below for implicit reference links. - * - * ## Extensions - * - * 1. Hurmet inline calculation is delimited ¢`…`. - * Hurmet display calculation is fenced ¢¢\n … \n¢¢. - * 2. LaTeX inline math is delimited $`…`. - * LaTeX display math is fenced $$\n … \n$$. - * 3. ~~strikethrough~~ - * 4. Pipe tables as per GFM. - * 5. Grid tables as per reStructuredText, with two exceptions: - * a. The top border contains ":" characters to indicate column justtification. - * b. Top & left borders contain "*" characters to indicate the location - * of a table column or rows boundary. - * 6. Implicit reference links [title][] and implicit reference images ![alt][] - * ⋮ - * [alt]: path - * Reference images can have captions and directives. Format is: - * ![alt text][ref]{caption} or [alt][]{caption} - * ⋮ - * [ref]: filepath - * {.class #id width=number} - * 7. Table directives. They are placed on the line after the table. The format is: - * {.class #id width=num widths="num1 num2 …"} - * 8. Lists that allow the user to pick list ordering. - * 1. → 1. 2. 3. etc. - * A. → A. B. C. etc. (future) - * a) → (a) (b) (c) etc. (future) - * 9. Definition lists, per Pandoc. (future) - * 10. Blurbs set an attribute on a block element, as in Markua. - * Blurbs are denoted by a symbol in the left margin. - * Subsequent indented text blocks are children of the blurb. - * Blurb symbols: - * i> indented block - * C> Centered block - * H> print header element,
    - * I> Information admonition (future) - * W> Warning admonition (future) - * T> Tip admonition (future) - * c> Comment admonition (future) - * 11. [^1] is a reference to a footnote. (future) - * [^1]: The body of the footnote is deferred, similar to reference links. - * 12. [#1] is a reference to a citation. (future) - * [#1]: The body of the citation is deferred, similar to reference links. - * 13. Line blocks begin with "| ", as per Pandoc. (future) - * - * hurmetMark.js copyright (c) 2021 Ron Kok - * - * This file has been adapted (and heavily modified) from Simple-Markdown. - * Simple-Markdown copyright (c) 2014-2019 Khan Academy & Aria Buckles. - * - * Portions of Simple-Markdown were adapted from marked.js copyright (c) 2011-2014 - * Christopher Jeffrey (https://github.com/chjj/). - * - * LICENSE (MIT): - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - -const CR_NEWLINE_R = /\r\n?/g; -const TAB_R = /\t/g; -const FORMFEED_R = /\f/g; -const CLASS_R = /(?:^| )\.([a-z-]+)(?: |$)/; -const WIDTH_R = /(?:^| )width="?([\d.a-z]+"?)(?: |$)/; -const COL_WIDTHS_R = /(?:^| )colWidths="([^"]*)"/; -const ID_R = /(?:^| )#([a-z-]+)(?: |$)/; - -// Turn various whitespace into easy-to-process whitespace -const preprocess = function(source) { - return source.replace(CR_NEWLINE_R, "\n").replace(FORMFEED_R, "").replace(TAB_R, " "); -}; - -// Creates a match function for an inline scoped element from a regex -const inlineRegex = function(regex) { - const match = function(source, state) { - return state.inline ? regex.exec(source) : null - }; - match.regex = regex; - return match; -}; - -// Creates a match function for a block scoped element from a regex -const blockRegex = function(regex) { - const match = function(source, state) { - return state.inline ? null : regex.exec(source) - }; - match.regex = regex; - return match; -}; - -// Creates a match function from a regex, ignoring block/inline scope -const anyScopeRegex = function(regex) { - const match = function(source, state) { - return regex.exec(source); - }; - match.regex = regex; - return match; -}; - -const UNESCAPE_URL_R = /\\([^0-9A-Za-z\s])/g; -const unescapeUrl = function(rawUrlString) { - return rawUrlString.replace(UNESCAPE_URL_R, "$1"); -}; - -const parseList = (str, state) => { - const items = str.replace(LIST_BLOCK_END_R, "\n").match(LIST_ITEM_R); - const isTight = state.inHtml && !/\n\n(?!$)/.test(str); - const itemContent = items.map(function(item, i) { - // We need to see how far indented this item is: - const prefixCapture = LIST_ITEM_PREFIX_R.exec(item); - const space = prefixCapture ? prefixCapture[0].length : 0; - // And then we construct a regex to "unindent" the subsequent - // lines of the items by that amount: - const spaceRegex = new RegExp("^ {1," + space + "}", "gm"); - - // Before processing the item, we need a couple things - const content = item - // remove indents on trailing lines: - .replace(spaceRegex, "") - // remove the bullet: - .replace(LIST_ITEM_PREFIX_R, ""); - - // backup our state for restoration afterwards. We're going to - // want to set state._list to true, and state.inline depending - // on our list's looseness. - const oldStateInline = state.inline; - const oldStateList = state._list; - state._list = true; - const oldStateTightness = state.isTight; - state.isTight = isTight; - - // Parse the list item - state.inline = isTight; - const adjustedContent = content.replace(LIST_ITEM_END_R, ""); - const result = isTight - ? { type: "list_item", content: parseInline(adjustedContent, state) } - : { type: "list_item", content: parse(adjustedContent, state) }; - - // Restore our state before returning - state.inline = oldStateInline; - state._list = oldStateList; - state.isTight = oldStateTightness; - return result; - }); - - return itemContent -}; - -const TABLES = (function() { - const TABLE_ROW_SEPARATOR_TRIM = /^ *\| *| *\| *$/g; - const TABLE_RIGHT_ALIGN = /^[-=]+:$/; - const TABLE_CENTER_ALIGN = /^:[-=]+:$/; - - const parseTableAlign = function(source) { - // Inspect ":" characters to set column justification. - // Return class names that specify center or right justification on specific columns. - source = source.replace(TABLE_ROW_SEPARATOR_TRIM, ""); - const alignArr = source.trim().split(/[|+*]/); - let alignStr = ""; - for (let i = 0; i < alignArr.length; i++) { - alignStr += TABLE_CENTER_ALIGN.test(alignArr[i]) - ? ` c${String(i + 1)}c` - : (TABLE_RIGHT_ALIGN.test(alignArr[i]) - ? ` c${String(i + 1)}r` - : ""); - } - return alignStr.trim() - }; - - const tableDirectives = (directives, align) => { - // Get CSS class, ID, and column widths, if any. - if (!directives && align === "") { return ["", "", null] } - const userDefClass = CLASS_R.exec(directives); - let myClass = (userDefClass) ? userDefClass[1] : ""; - if (align.length > 0) { myClass += (myClass.length > 0 ? " " : "") + align; } - const userDefId = ID_R.exec(directives); - const myID = (userDefId) ? userDefId[1] : ""; - const colWidthMatch = COL_WIDTHS_R.exec(directives); - const colWidths = (colWidthMatch) ? colWidthMatch[1].split(" ") : null; - return [myClass, myID, colWidths] - }; - - const parsePipeTableRow = function(source, parse, state, colWidths, inHeader) { - const prevInTable = state.inTable; - state.inTable = true; - const tableRow = parse(source.trim(), state); - consolidate(tableRow); - state.inTable = prevInTable; - - const row = { - type: "table_row", - content: [] - }; - let j = -1; - tableRow.forEach(function(node, i) { - if (node.type === "tableSeparator") { - if (i !== tableRow.length - 1) { // Filter out the row's last table separator - // Create a new cell - j += 1; - row.content.push({ - "type": inHeader ? "table_header" : "table_cell", - "attrs": { - "colspan": 1, - "rowspan": 1, - "colwidth": (colWidths) ? [Number(colWidths[j])] : null, - "background": null - }, - content: (state.inHtml ? [] : [{ "type": "paragraph", "content": [] }]) - }); - } - } else if (state.inHtml) { - // For direct to HTML, write the inline contents directly into the element. - // row cell content text - row.content[j].content.push(node); - } else { - // Hurmet.app table cells always contain a paragraph. - // row cell paragraph content text - row.content[j].content[0].content.push(node); - } - }); - - return row; - }; - - const parsePipeTable = function() { - return function(capture, state) { - state.inline = true; - const align = parseTableAlign(capture[2]); - const [myClass, myID, colWidths] = tableDirectives(capture[4], align); - const table = { - type: "table", - attrs: {}, - content: [] - }; - if (myID) { table.attrs.id = myID; } - if (myClass) { table.attrs.class = myClass; } - table.content.push(parsePipeTableRow(capture[1], parse, state, colWidths, true)); - const tableBody = capture[3].trim().split("\n"); - tableBody.forEach(row => { - table.content.push(parsePipeTableRow(row, parse, state, colWidths, false)); - }); - state.inline = false; - return table - }; - }; - - const headerRegEx = /^\+:?=/ - - const parseGridTable = function() { - return function(capture, state) { - const topBorder = capture[2]; - const align = parseTableAlign(topBorder.slice(1)); - const [myClass, myID, colWidths] = tableDirectives(capture[3], align); - const lines = capture[1].slice(0, -1).split("\n"); - - // Does the grid table contain a line separating header from table body? - let headerExists = false; - let headerSepLine = lines.length + 10; - for (let i = 0; i < lines.length; i++) { - if (headerRegEx.test(lines[i])) { - headerExists = true; - headerSepLine = i; - break - } - } - - // Read the top & left borders to find the locations of the cell corners. - const xCorners = [0]; - for (let j = 1; j < topBorder.length; j++) { - const ch = topBorder.charAt(j); - // A "*" character indicates a column border, but the top row - // contains a merged cell, so the column border does not extend - // all the way to the top of the table. - if (ch === "+" || ch === "*") { xCorners.push(j); } - } - const yCorners = [0]; - for (let i = 1; i < lines.length; i++) { - const ch = lines[i].charAt(0); - if (ch === "+" || ch === "*") { yCorners.push(i); } - } - - const numCols = xCorners.length - 1; - const numRows = yCorners.length - 1; - const gridTable = []; - - // Create default rows and cells. They may be merged later. - for (let i = 0; i < numRows; i++) { - const row = new Array(numCols); - for (let j = 0; j < numCols; j++) { row[j] = { rowspan: 1 }; } - gridTable.push(row); - } - - for (let i = 0; i < numRows; i++) { - const row = gridTable[i]; - // Determine the actual rowspan and colspan of each cell. - for (let j = 0; j < numCols; j++) { - const cell = row[j]; - if (cell.rowspan === 0) { continue } - cell.colspan = 1; - const lastTextRow = lines[yCorners[i + 1] - 1]; - for (let k = j + 1; k < xCorners.length; k++) { - if (lastTextRow.charAt(xCorners[k]) === "|") { break } - cell.colspan += 1; - row[k].rowspan = 0; - } - for (let k = i + 1; k < yCorners.length; k++) { - const ch = lines[yCorners[k]].charAt(xCorners[j] + 1); - if (ch === "-" || ch === "=") { break } - cell.rowspan += 1; - for (let jj = 0; jj < cell.colspan; jj++) { - gridTable[k][j + jj].rowspan = 0; - } - } - // Now that we know the cell extents, get the cell contents. - const xStart = xCorners[j] + 2; - const xEnd = xCorners[j + cell.colspan] - 1; - const yStart = yCorners[i] + 1; - const yEnd = yCorners[i + cell.rowspan]; - let str = ""; - for (let ii = yStart; ii < yEnd; ii++) { - str += lines[ii].slice(xStart, xEnd).replace(/ +$/, "") + "\n"; - } - cell.blob = str.slice(0, -1).replace(/^\n+/, ""); - - cell.inHeader = (headerExists && yStart < headerSepLine); - - if (colWidths) { - // Set an attribute used by ProseMirror. - let cellWidth = 0; - for (let k = 0; k < cell.colspan; k++) { - cellWidth += Number(colWidths[j + k]); - } - cell.width = cellWidth; - } - } - } - - const table = { - type: "table", - attrs: {}, - content: [] - }; - if (myID) { table.attrs.id = myID; } - if (myClass) { table.attrs.class = myClass; } - for (let i = 0; i < numRows; i++) { - table.content.push({ type: "table_row", content: [] } ); - for (let j = 0; j < numCols; j++) { - if (gridTable[i][j].rowspan === 0) { continue } - const cell = gridTable[i][j]; - state.inline = false; - let content = state.inHtml && cell.blob.indexOf("```") === -1 && !/\n\n/.test(cell.blob.replace(/\n+$/g, "")) - ? parseInline(cell.blob, state) // Write inline content directly into each - : parse(cell.blob, state); // Hurmet.app has a paragraph in each cell. - if (content.length === 1 && content[0].type === "null") { - content = state.inHtml - ? [{ type: "text", text: "" }] - : [{ type: "paragraph", content: [] }]; - } - table.content[i].content.push({ - "type": cell.inHeader ? "table_header" : "table_cell", - "attrs": { - "colspan": cell.colspan, - "rowspan": cell.rowspan, - "colwidth": (colWidths) ? [cell.width] : null, - "background": null - }, - content: content - }); - } - } - state.inline = false; - return table - }; - }; - - return { - parsePipeTable: parsePipeTable(), - PIPE_TABLE_REGEX: /^(\|.+)\n\|([-:]+[-| :]*)\n((?:\|.*(?:\n|$))*)(?:\{([^\n}]+)\}\n)?\n*/, - parseGridTable: parseGridTable(), - GRID_TABLE_REGEX: /^((\+(?:[-:*=]+\+)+)\n(?:[+|*][^\n]+[+|]\n)+)(?:\{([^\n}]+)\}\n)?\n*/ - }; -})(); - -const LINK_INSIDE = "(?:\\[[^\\]]*\\]|[^\\[\\]]|\\](?=[^\\[]*\\]))*"; -const LINK_HREF_AND_TITLE = - "\\s*?(?:\\s+['\"]([\\s\\S]*?)['\"])?\\s*"; - -const linkIndex = marks => { - for (let i = 0; i < marks.length; i++) { - if (marks[i].type === "link") { return i } - } -}; - -const parseRef = function(capture, state, refNode) { - let ref = capture[2] ? capture[2] : capture[1]; - ref = ref.replace(/\s+/g, " "); - - // We store information about previously seen defs on - // state._defs (_ to deconflict with client-defined - // state). If the def for this reflink/refimage has - // already been seen, we can use its target/source - // and title here: - if (state._defs && state._defs[ref]) { - const def = state._defs[ref]; - if (refNode.type === "image") { - refNode.attrs.src = def.target; - refNode.attrs.width = null; - } else { - // refNode is a link - refNode.attrs.href = def.target; - } - } - - // In case we haven't seen our def yet (or if someone - // overwrites that def later on), we add this node - // to the list of ref nodes for that def. Then, when - // we find the def, we can modify this link/image AST - // node :). - state._refs = state._refs || {}; - state._refs[ref] = state._refs[ref] || []; - state._refs[ref].push(refNode); - - return refNode; -}; - -const parseTextMark = (capture, state, mark) => { - const text = parseInline(capture, state); - if (Array.isArray(text) && text.length === 0) { return text } - consolidate(text); - if (text[0].marks) { - text[0].marks.push({ type: mark }); - } else { - text[0].marks = [{ type: mark }]; - } - return text -}; - -const BLOCK_HTML = /^ *(?:<(head|h[1-6]|p|pre|script|style|table)[\s>][\s\S]*?(?:<\/\1>[^\n]*\n)|[^\n]*\n|<\/?(?:body|details|(div|input|label)(?: [^>]+)?|!DOCTYPE[a-z ]*|html[a-z ="]*|br|dl(?: class="[a-z-]+")?|li|main[a-z\- ="]*|nav|ol|ul(?: [^>]+)?)\/?>[^\n]*?(?:\n|$))/ -const divType = { C: "centered_div", H: "header", "i": "indented_div" }; - -// Rules must be applied in a specific order, so use a Map instead of an object. -const rules = new Map(); -rules.set("html", { - isLeaf: true, - match: blockRegex(BLOCK_HTML), - parse: function(capture, state) { - if (!state.inHtml) { return null } - return { type: "html", text: capture[0] } - } -}); -rules.set("heading", { - isLeaf: false, - match: blockRegex(/^ *(#{1,6})([^\n]+?)#* *(?:\n *)+\n/), - parse: function(capture, state) { - return { - attrs: { level: capture[1].length }, - content: parseInline(capture[2].trim(), state) - }; - } -}); -rules.set("dt", { // description term - isLeaf: false, - match: blockRegex(/^(([^\n]*)\n)(?=
    |\n:)/), - parse: function(capture, state) { - return { content: parseInline(capture[2].trim(), state) } - } -}); -rules.set("horizontal_rule", { - isLeaf: true, - match: blockRegex(/^( *[-*_]){3,} *(?:\n *)+\n/), - parse: function(capture, parse, state) { - return { type: "horizontal_rule" }; - } -}); -rules.set("lheading", { - isLeaf: false, - match: blockRegex(/^([^\n]+)\n *(=|-){3,} *(?:\n *)+\n/), - parse: function(capture, parse, state) { - return { - type: "heading", - level: capture[2] === '=' ? 1 : 2, - content: parseInline(parse, capture[1]) - }; - } -}); -rules.set("fence", { - isLeaf: true, - match: blockRegex(/^(`{3,}) *(?:(\S+) *)?\n([\s\S]+?)\n?\1 *(?:\n *)+\n/), - parse: function(capture, state) { - return { - type: "code_block", -// lang: capture[2] || undefined, - content: [{ type: "text", text: capture[3] }] - }; - } -}); -rules.set("blockquote", { - isLeaf: false, - match: blockRegex(/^( *>[^\n]+(\n[^\n]+)*\n*)+\n{2,}/), - parse: function(capture, state) { - const content = capture[0].replace(/^ *> ?/gm, ""); - return { content: parse(content, state) }; - } -}); -rules.set("ordered_list", { - isLeaf: false, - match: blockRegex(/^( {0,3})(\d{1,9}\.) [\s\S]+?(?:\n{2,}(?! )(?!\1(?:\d{1,9}\.) )\n*|\s*$)/), - parse: function(capture, state) { - const start = Number(capture[2].trim()); - return { attrs: { order: start }, content: parseList(capture[0], state, capture[1]) } - } -}); -rules.set("bullet_list", { - isLeaf: false, - match: blockRegex(/^( {0,3})([*+-]) [\s\S]+?(?:\n{2,}(?! )(?!\1(?:[*+-]) )\n*|\s*$)/), - parse: function(capture, state) { - return { content: parseList(capture[0], state, capture[1]) } - } -}); -rules.set("dd", { // description details - isLeaf: false, - match: blockRegex(/^:( +)[\s\S]+?(?:\n{2,}(?! |:)(?!\1)\n*|\s*$)/), - parse: function(capture, state) { - let div = " " + capture[0].slice(1); - const indent = 1 + capture[1].length; - const spaceRegex = new RegExp("^ {" + indent + "," + indent + "}", "gm"); - div = div.replace(spaceRegex, ""); // remove indents on trailing lines: - return { content: parse(div, state) }; - } -}); -rules.set("special_div", { - isLeaf: false, - match: blockRegex(/^(C|H|i)>( {1,})[\s\S]+?(?:\n{2,}(?! {2,2}\2)\n*|\s*$)/), - parse: function(capture, state) { - const type = divType[capture[1]]; - let div = " " + capture[0].slice(2); - const indent = 2 + capture[2].length; - const spaceRegex = new RegExp("^ {" + indent + "," + indent + "}", "gm"); - div = div.replace(spaceRegex, ""); // remove indents on trailing lines: - return { type, content: parse(div, state) }; - } -}); -rules.set("def", { - // TODO(aria): This will match without a blank line before the next - // block element, which is inconsistent with most of the rest of - // simple-markdown. - isLeaf: true, - match: blockRegex(/^\[([^\]]+)\]: *]*)>? *\n(?:\{([^\n}]*)\}\n)?/), - parse: function(capture, state) { - const def = capture[1].replace(/\s+/g, " "); - const target = capture[2]; - const directives = capture[3] || ""; - const attrs = {}; - - // Look for previous links/images using this def - // If any links/images using this def have already been declared, - // they will have added themselves to the state._refs[def] list - // (_ to deconflict with client-defined state). We look through - // that list of reflinks for this def, and modify those AST nodes - // with our newly found information now. - // Sorry :(. - if (state._refs && state._refs[def]) { - // `refNode` can be a link or an image - state._refs[def].forEach(function(refNode) { - if (refNode.type === "image") { - refNode.attrs.src = target; - if (directives) { - const matchClass = CLASS_R.exec(directives); - if (matchClass) { - refNode.attrs.class = matchClass[1]; - attrs.class = matchClass[1]; - } - const matchWidth = WIDTH_R.exec(directives); - if (matchWidth) { - refNode.attrs.width = matchWidth[1]; - attrs.width = matchWidth[1]; - } - const matchID = ID_R.exec(directives); - if (matchID) { - refNode.attrs.id = matchID[1]; - attrs.id = matchID[1]; - } - } - } else { - refNode.attrs.href = target; - } - }); - } - - // Add this def to our map of defs for any future links/images - // In case we haven't found any or all of the refs referring to - // this def yet, we add our def to the table of known defs, so - // that future reflinks can modify themselves appropriately with - // this information. - state._defs = state._defs || {}; - state._defs[def] = { target, attrs }; - - // return the relevant parsed information - // for debugging only. - return { - def: def, - target: target, - directives: directives - }; - } -}); -rules.set("pipeTable", { - isLeaf: false, - match: blockRegex(TABLES.PIPE_TABLE_REGEX), - parse: TABLES.parsePipeTable -}); -rules.set("gridTable", { - isLeaf: false, - match: blockRegex(TABLES.GRID_TABLE_REGEX), - parse: TABLES.parseGridTable -}); -rules.set("newline", { - isLeaf: true, - match: blockRegex(/^(?:\n *)*\n/), - parse: function() { return { type: "null" } } -}); -rules.set("paragraph", { - isLeaf: false, - match: blockRegex(/^((?:[^\n]|\n(?! *\n))+)(?:\n *)+\n/), - parse: function(capture, state) { - return { content: parseInline(capture[1], state) }; - } -}); -rules.set("escape", { - // We don't allow escaping numbers, letters, or spaces here so that - // backslashes used in plain text still get rendered. But allowing - // escaping anything else provides a very flexible escape mechanism, - // regardless of how this grammar is extended. - isLeaf: true, - match: inlineRegex(/^\\([^0-9A-Za-z\s])/), - parse: function(capture, state) { - return { - type: "text", - text: capture[1] - }; - } -}); -rules.set("tableSeparator", { - isLeaf: true, - match: function(source, state) { - if (!state.inTable) { - return null; - } - return /^ *\| */.exec(source); - }, - parse: function() { - return { type: "tableSeparator" }; - } -}); -rules.set("calculation", { - isLeaf: true, - match: anyScopeRegex(/^(?:¢(`+)([\s\S]*?[^`])\1(?!`)|¢¢\n((?:\\[\s\S]|[^\\])+?)\n¢¢)/), - parse: function(capture, state) { - if (capture[2]) { - let entry = capture[2].trim(); - if (!/^function/.test(entry) && entry.indexOf("``") === -1) { - entry = entry.replace(/\n/g, " "); - } - return { content: "", attrs: { entry } } - } else { - const entry = capture[3].trim(); - return { content: "", attrs: { entry, displayMode: true } } - } - } -}); -rules.set("tex", { - isLeaf: true, - match: anyScopeRegex(/^(?:\$(`+)([\s\S]*?[^`])\1(?!`)|\$\$\n?((?:\\[\s\S]|[^\\])+?)\n?\$\$)/), - parse: function(capture, state) { - if (capture[2]) { - const tex = capture[2].trim().replace(/\n/g, " "); - return { content: "", attrs: { tex } } - } else { - return { content: "", attrs: { tex: capture[3].trim(), displayMode: true } } - } - } -}); -rules.set("link", { - isLeaf: true, - match: inlineRegex( - new RegExp("^\\[(" + LINK_INSIDE + ")\\]\\(" + LINK_HREF_AND_TITLE + "\\)") - ), - parse: function(capture, state) { - const textNode = parseTextMark(capture[1], state, "link" )[0]; - const i = linkIndex(textNode.marks); - textNode.marks[i].attrs = { href: unescapeUrl(capture[2]) }; - return textNode - } -}); -rules.set("image", { - isLeaf: true, - match: inlineRegex( - new RegExp("^!\\[(" + LINK_INSIDE + ")\\]\\(" + LINK_HREF_AND_TITLE + "\\)") - ), - parse: function(capture, state) { - return { attrs: { alt: capture[1], src: unescapeUrl(capture[2]) } } - } -}); -rules.set("reflink", { - isLeaf: true, - match: inlineRegex(/^\[((?:(?:\\[\s\S]|[^\\])+?)?)\]\[([^\]]*)\]/), - parse: function(capture, state) { - const textNode = parseTextMark(capture[1], state, "link" )[0]; - const i = linkIndex(textNode.marks); - textNode.marks[i].attrs = { href: null }; - if (capture[2]) { - textNode.marks[i].attrs.title = capture[2]; - } - parseRef(capture, state, textNode.marks[i]); - return textNode - } -}); -rules.set("refimage", { - isLeaf: true, - match: inlineRegex(/^!\[((?:(?:\\[\s\S]|[^\\])+?)?)\]\[([^\]]*)\]/), - parse: function(capture, state) { - return parseRef(capture, state, { - type: "image", - attrs: { alt: capture[1] } - }); - } -}); -rules.set("code", { - isLeaf: true, - match: inlineRegex(/^(`+)([\s\S]*?[^`])\1(?!`)/), - parse: function(capture, state) { - const text = capture[2].trim(); - return [{ type: "text", text, marks: [{ type: "code" }] }] -/* state.inCode = true; - const code = parseTextMark(text, state, "code" ); - state.inCode = false; - console.log(code) - return code */ - } -}); -rules.set("em", { - isLeaf: true, - match: inlineRegex(/^_((?:\\[\s\S]|[^\\])+?)_/), - parse: function(capture, state) { - return parseTextMark(capture[1], state, "em" ) - } -}); -rules.set("strong", { - isLeaf: true, - match: inlineRegex(/^\*\*(?=\S)((?:\\[\s\S]|\*(?!\*)|[^\s*\\]|\s(?!\*\*))+?)\*\*/), - parse: function(capture, state) { - return parseTextMark(capture[1], state, "strong" ) - } -}); -rules.set("strikethru", { - isLeaf: true, - match: inlineRegex(/^~~(?=\S)((?:\\[\s\S]|~(?!~)|[^\s~\\]|\s(?!~~))+?)~~/), - parse: function(capture, state) { - return parseTextMark(capture[1], state, "strikethru" ) - } -}); -rules.set("superscript", { - isLeaf: true, - match: inlineRegex(/^([\s\S]*?)<\/sup>/), - parse: function(capture, state) { - return parseTextMark(capture[1], state, "superscript" ) - } -}); -rules.set("subscript", { - isLeaf: true, - match: inlineRegex(/^([\s\S]*?)<\/sub>/), - parse: function(capture, state) { - return parseTextMark(capture[1], state, "subscript" ) - } -}); -rules.set("underline", { - isLeaf: true, - match: inlineRegex(/^([\s\S]*?)<\/u>/), - parse: function(capture, state) { - return parseTextMark(capture[1], state, "underline" ) - } -}); -rules.set("highlight", { - isLeaf: true, - match: inlineRegex(/^([\s\S]*?)<\/mark>/), - parse: function(capture, state) { - return parseTextMark(capture[1], state, "highlight" ) - } -}); -rules.set("hard_break", { - isLeaf: true, - match: anyScopeRegex(/^\\\n/), - parse: function() { return { text: "\n" } } -}); -rules.set("inline_break", { - isLeaf: true, - match: anyScopeRegex(/^
    /), - parse: function() { return { type: "hard_break", text: "\n" } } -}); -rules.set("span", { - isLeaf: true, - match: inlineRegex(/^ { - if (!state.inline) { source += "\n\n"; } - source = preprocess(source); - const result = []; - while (source) { - // store the best match and its rule: - let capture = null; - let ruleName = null; - let rule = null; - for (const [currRuleName, currRule] of rules) { - if (state.inCode && doNotEscape.includes(currRuleName)) { continue } - capture = currRule.match(source, state); - if (capture) { - rule = currRule; - ruleName = currRuleName; - break - } - } - const parsed = rule.parse(capture, state); - if (Array.isArray(parsed)) { - Array.prototype.push.apply(result, parsed); - } else { - if (parsed.type == null) { parsed.type = ruleName; } - result.push(parsed); - } - source = source.substring(capture[0].length); - } - return result -}; - - - -/** - * Parse some content with the parser `parse`, with state.inline - * set to true. Useful for block elements; not generally necessary - * to be used by inline elements (where state.inline is already true. - */ -const parseInline = function(content, state) { - const isCurrentlyInline = state.inline || false; - state.inline = true; - const result = parse(content, state); - state.inline = isCurrentlyInline; - return result; -}; - - -// recognize a `*` `-`, `+`, `1.`, `2.`... list bullet -const LIST_BULLET = "(?:[*+-]|\\d+\\.)"; -// recognize the start of a list item: -// leading space plus a bullet plus a space (` * `) -const LIST_ITEM_PREFIX = "( *)(" + LIST_BULLET + ") +"; -const LIST_ITEM_PREFIX_R = new RegExp("^" + LIST_ITEM_PREFIX); -// recognize an individual list item: -// * hi -// this is part of the same item -// -// as is this, which is a new paragraph in the same item -// -// * but this is not part of the same item -const LIST_ITEM_R = new RegExp( - LIST_ITEM_PREFIX + "[^\\n]*(?:\\n" + "(?!\\1" + LIST_BULLET + " )[^\\n]*)*(\n|$)", - "gm" -); -const BLOCK_END_R = /\n{2,}$/; -// recognize the end of a paragraph block inside a list item: -// two or more newlines at end end of the item -const LIST_BLOCK_END_R = BLOCK_END_R; -const LIST_ITEM_END_R = / *\n+$/; - -const ignore = ["def", "newline", "null"]; - -const consolidate = arr => { - if (Array.isArray(arr) && arr.length > 0) { - // Group any text nodes together into a single string output. - for (let i = arr.length - 1; i > 0; i--) { - const node = arr[i]; - const prevNode = arr[i - 1]; - if (node.type === 'text' && prevNode.type === 'text' && - !node.marks && !prevNode.marks) { - prevNode.text += node.text; - arr.splice(i, 1); - } else if (ignore.includes(node.type)) { - arr.splice(i, 1); - } else if (!rules.has(node.type) || !rules.get(node.type).isLeaf) { - consolidate(node.content); - } - } - - if (!rules.has(arr[0].type) || !rules.get(arr[0].type).isLeaf) { - consolidate(arr[0].content); - } - } -}; - -const md2ast = (md, inHtml = false) => { - const ast = parse(md, { inline: false, inHtml }); - consolidate(ast); - return ast -}; - -// const hurmet = require("./hurmet.js"); -const temml = require('./temml.cjs'); - -const sanitizeUrl = function(url) { - if (url == null) { - return null; - } - try { - const prot = decodeURIComponent(url) - .replace(/[^A-Za-z0-9/:]/g, "") - .toLowerCase(); - if ( - prot.indexOf("javascript:") === 0 || - prot.indexOf("vbscript:") === 0 || - prot.indexOf("data:") === 0 - ) { - return null; - } - } catch (e) { - // decodeURIComponent sometimes throws a URIError - // See `decodeURIComponent('a%AFc');` - // http://stackoverflow.com/questions/9064536/javascript-decodeuricomponent-malformed-uri-exception - return null; - } - return url; -}; - -const SANITIZE_TEXT_R = /[<>&"']/g; -const SANITIZE_TEXT_CODES = { - "<": "<", - ">": ">", - "&": "&", - '"': """, - "'": "'", - "/": "/", - "`": "`" -}; -const sanitizeText = function(text /* : Attr */) { - return String(text).replace(SANITIZE_TEXT_R, function(chr) { - return SANITIZE_TEXT_CODES[chr]; - }); -}; - -const htmlTag = (tagName, content, attributes = {}, isClosed = true) => { - let attributeString = ""; - for (const attr in attributes) { - if (Object.prototype.hasOwnProperty.call(attributes, attr)) { - const attribute = attributes[attr]; - // Removes falsey attributes - if (attribute) { - attributeString += " " + sanitizeText(attr) + '="' + sanitizeText(attribute) + '"'; - } - } - } - - const unclosedTag = "<" + tagName + attributeString + ">"; - - if (isClosed) { - return unclosedTag + content + ""; - } else { - return unclosedTag; - } -}; - -const tagName = { - em: "em", - strong: "strong", - code: "code", - strikethru: "del", - subscript: "sub", - superscript: "sup", - underline: "u", - highlight: "mark" -}; - -const nodes = { - html(node) { return node.text }, - heading(node) { - const text = output(node.content); - let tag = "h" + node.attrs.level; - tag = htmlTag(tag, text); - // Add id so others can link to it. - tag = tag.slice(0, 3) + " id='" + text.toLowerCase().replace(/,/g, "").replace(/\s+/g, '-') + "'" + tag.slice(3); - return tag + "\n" - }, - paragraph(node) { return htmlTag("p", output(node.content)) + "\n" }, - blockquote(node) {return htmlTag("blockquote", output(node.content)) }, - code_block(node) { - return htmlTag("pre", htmlTag("code", sanitizeText(node.content[0].text))) - }, - hard_break(node) { return "
    " }, - def(node) { return "" }, - newline(node) { return "\n" }, - horizontal_rule(node) { return "
    \n" }, - ordered_list(node) { - const attributes = node.attrs.order !== 1 ? { start: node.attrs.order } : undefined; - return htmlTag("ol", output(node.content), attributes) + "\n" - }, - bullet_list(node) { return htmlTag("ul", output(node.content)) + "\n" }, - list_item(node) { return htmlTag("li", output(node.content)) + "\n" }, - table(node) { return htmlTag("table", output(node.content), node.attrs) + "\n" }, - table_row(node) { return htmlTag("tr", output(node.content)) + "\n" }, - table_header(node) { - const attributes = {}; - if (node.attrs.colspan !== 1) { attributes.colspan = node.attrs.colspan; } - if (node.attrs.rowspan !== 1) { attributes.rowspan = node.attrs.rowspan; } - if (node.attrs.colwidth !== null && !isNaN(node.attrs.colwidth) ) { - attributes.style = `width: ${node.attrs.colwidth}px` - } - return htmlTag("th", output(node.content), attributes) + "\n" - }, - table_cell(node) { - const attributes = {}; - if (node.attrs.colspan !== 1) { attributes.colspan = node.attrs.colspan; } - if (node.attrs.rowspan !== 1) { attributes.rowspan = node.attrs.rowspan; } - if (node.attrs.colwidth !== null && !isNaN(node.attrs.colwidth) ) { - attributes.style = `width: ${node.attrs.colwidth}px` - } - return htmlTag("td", output(node.content), attributes) - }, - link(node) { - const attributes = { href: sanitizeUrl(node.attrs.href), title: node.attrs.title }; - return htmlTag("a", output(node.content), attributes); - }, - image(node) { - const attributes = { src: sanitizeUrl(node.attrs.src), alt: node.attrs.alt }; - if (node.attrs.class) { attributes.class = node.attrs.class; } - if (node.attrs.id) { attributes.id = node.attrs.id; } - if (node.attrs.width) { attributes.width = node.attrs.width; } - return htmlTag("img", "", attributes, false); - }, -/* calculation(node) { - const tex = hurmet.parse(node.attrs.entry); - return htmlTag("span", "", { class: "tex", "data-tex": tex }) - },*/ - tex(node) { - return temml.renderToString( - node.attrs.tex, - { trust: true, displayMode: (node.attrs.displayMode || false) } - ) - }, - indented_div(node) { return htmlTag("div", output(node.content), { class: 'indented' }) }, - centered_div(node) { - return htmlTag("div", output(node.content), { class: 'centered' } ) - }, - dt(node) { - let text = output(node.content); - let tag = htmlTag("dt", text); - // Add id so others can link to it. - const pos = text.indexOf("("); - if (pos > -1) { text = text.slice(0, pos).replace("_", "-"); } - tag = tag.slice(0, 3) + " id='" + text.toLowerCase().replace(/\s+/g, '-') + "'" + tag.slice(3); - return tag + "\n" - }, - dd(node) { return htmlTag("dd", output(node.content)) + "\n" }, - text(node) { - const text = sanitizeText(node.text); - if (!node.marks) { - return text - } else { - let span = text; - for (const mark of node.marks) { - if (mark.type === "link") { - let tag = `" + span + ""; - } else { - const tag = tagName[mark.type]; - span = `<${tag}>${span}`; - } - } - return span - } - } -}; - -const output = (ast) => { - // Return HTML. - let html = ""; - if (Array.isArray(ast)) { - for (let i = 0; i < ast.length; i++) { - html += output(ast[i]); - } - } else if (ast.type !== "null") { - html += nodes[ast.type](ast); - } - return html -}; - -const md2html = (md, inHtml = false) => { - const ast = md2ast(md, inHtml); - return output(ast) -}; - -const hmd = { - md2ast, - md2html -}; - -exports.hmd = hmd; diff --git a/utils/insertPlugins.js b/utils/insertPlugins.js deleted file mode 100644 index 423016e7..00000000 --- a/utils/insertPlugins.js +++ /dev/null @@ -1,22 +0,0 @@ -// Embed extensions into the cjs and mjs version of Temml. - -const fs = require("fs") // Node.js file system - -// Get the temml.cjs and mjs code -let cjs = fs.readFileSync('./utils/temml.cjs').toString('utf8') -let mjs = fs.readFileSync('./utils/temml.mjs').toString('utf8') - -// Get the extension macros -const regex = /temml\.__/g; -const mhchem = fs.readFileSync('./contrib/mhchem/mhchem.js').toString('utf8').replace(regex, "") -const texvc = fs.readFileSync('./contrib/texvc/texvc.js').toString('utf8').replace(regex, "") -const physics = fs.readFileSync('./contrib/physics/physics.js').toString('utf8').replace(regex, "") - -// Insert the extension macros into temml.cjs and temml.mjs -let pos = cjs.indexOf("⦵") + 6 -cjs = cjs.slice(0, pos) + "\n" + mhchem + "\n" + texvc + "\n" + physics + "\n" + cjs.slice(pos + 1) -fs.writeFileSync('./utils/temml.cjs', cjs) - -pos = mjs.indexOf("⦵") + 6 -mjs = mjs.slice(0, pos) + "\n" + mhchem + "\n" + texvc + "\n" + physics + "\n" + mjs.slice(pos + 1) -fs.writeFileSync('./utils/temml.mjs', mjs) diff --git a/utils/katex.min.js b/utils/katex.min.js deleted file mode 100644 index dec14608..00000000 --- a/utils/katex.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.katex=t():e.katex=t()}("undefined"!=typeof self?self:this,(function(){return function(){"use strict";var e={d:function(t,r){for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:r[n]})},o:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}},t={};e.d(t,{default:function(){return Zn}});var r=function e(t,r){this.position=void 0;var n,a="KaTeX parse error: "+t,i=r&&r.loc;if(i&&i.start<=i.end){var o=i.lexer.input;n=i.start;var s=i.end;n===o.length?a+=" at end of input: ":a+=" at position "+(n+1)+": ";var l=o.slice(n,s).replace(/[^]/g,"$&\u0332");a+=(n>15?"\u2026"+o.slice(n-15,n):o.slice(0,n))+l+(s+15":">","<":"<",'"':""","'":"'"},o=/[&><"']/g;var s=function e(t){return"ordgroup"===t.type||"color"===t.type?1===t.body.length?e(t.body[0]):t:"font"===t.type?e(t.body):t},l={contains:function(e,t){return-1!==e.indexOf(t)},deflt:function(e,t){return void 0===e?t:e},escape:function(e){return String(e).replace(o,(function(e){return i[e]}))},hyphenate:function(e){return e.replace(a,"-$1").toLowerCase()},getBaseElem:s,isCharacterBox:function(e){var t=s(e);return"mathord"===t.type||"textord"===t.type||"atom"===t.type},protocolFromUrl:function(e){var t=/^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(e);return null!=t?t[1]:"_relative"}},h=function(){function e(e){this.displayMode=void 0,this.output=void 0,this.leqno=void 0,this.fleqn=void 0,this.throwOnError=void 0,this.errorColor=void 0,this.macros=void 0,this.minRuleThickness=void 0,this.colorIsTextColor=void 0,this.strict=void 0,this.trust=void 0,this.maxSize=void 0,this.maxExpand=void 0,this.globalGroup=void 0,e=e||{},this.displayMode=l.deflt(e.displayMode,!1),this.output=l.deflt(e.output,"htmlAndMathml"),this.leqno=l.deflt(e.leqno,!1),this.fleqn=l.deflt(e.fleqn,!1),this.throwOnError=l.deflt(e.throwOnError,!0),this.errorColor=l.deflt(e.errorColor,"#cc0000"),this.macros=e.macros||{},this.minRuleThickness=Math.max(0,l.deflt(e.minRuleThickness,0)),this.colorIsTextColor=l.deflt(e.colorIsTextColor,!1),this.strict=l.deflt(e.strict,"warn"),this.trust=l.deflt(e.trust,!1),this.maxSize=Math.max(0,l.deflt(e.maxSize,1/0)),this.maxExpand=Math.max(0,l.deflt(e.maxExpand,1e3)),this.globalGroup=l.deflt(e.globalGroup,!1)}var t=e.prototype;return t.reportNonstrict=function(e,t,r){var a=this.strict;if("function"==typeof a&&(a=a(e,t,r)),a&&"ignore"!==a){if(!0===a||"error"===a)throw new n("LaTeX-incompatible input and strict mode is set to 'error': "+t+" ["+e+"]",r);"warn"===a?"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+t+" ["+e+"]"):"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '"+a+"': "+t+" ["+e+"]")}},t.useStrictBehavior=function(e,t,r){var n=this.strict;if("function"==typeof n)try{n=n(e,t,r)}catch(e){n="error"}return!(!n||"ignore"===n)&&(!0===n||"error"===n||("warn"===n?("undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+t+" ["+e+"]"),!1):("undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '"+n+"': "+t+" ["+e+"]"),!1)))},t.isTrusted=function(e){e.url&&!e.protocol&&(e.protocol=l.protocolFromUrl(e.url));var t="function"==typeof this.trust?this.trust(e):this.trust;return Boolean(t)},e}(),m=function(){function e(e,t,r){this.id=void 0,this.size=void 0,this.cramped=void 0,this.id=e,this.size=t,this.cramped=r}var t=e.prototype;return t.sup=function(){return c[u[this.id]]},t.sub=function(){return c[p[this.id]]},t.fracNum=function(){return c[d[this.id]]},t.fracDen=function(){return c[f[this.id]]},t.cramp=function(){return c[g[this.id]]},t.text=function(){return c[v[this.id]]},t.isTight=function(){return this.size>=2},e}(),c=[new m(0,0,!1),new m(1,0,!0),new m(2,1,!1),new m(3,1,!0),new m(4,2,!1),new m(5,2,!0),new m(6,3,!1),new m(7,3,!0)],u=[4,5,4,5,6,7,6,7],p=[5,5,5,5,7,7,7,7],d=[2,3,4,5,6,7,6,7],f=[3,3,5,5,7,7,7,7],g=[1,1,3,3,5,5,7,7],v=[0,1,2,3,2,3,2,3],b={DISPLAY:c[0],TEXT:c[2],SCRIPT:c[4],SCRIPTSCRIPT:c[6]},y=[{name:"latin",blocks:[[256,591],[768,879]]},{name:"cyrillic",blocks:[[1024,1279]]},{name:"armenian",blocks:[[1328,1423]]},{name:"brahmic",blocks:[[2304,4255]]},{name:"georgian",blocks:[[4256,4351]]},{name:"cjk",blocks:[[12288,12543],[19968,40879],[65280,65376]]},{name:"hangul",blocks:[[44032,55215]]}];var x=[];function w(e){for(var t=0;t=x[t]&&e<=x[t+1])return!0;return!1}y.forEach((function(e){return e.blocks.forEach((function(e){return x.push.apply(x,e)}))}));var k=80,S={doubleleftarrow:"M262 157\nl10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3\n 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28\n 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5\nc2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5\n 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87\n-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7\n-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z\nm8 0v40h399730v-40zm0 194v40h399730v-40z",doublerightarrow:"M399738 392l\n-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5\n 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88\n-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68\n-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18\n-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782\nc-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3\n-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z",leftarrow:"M400000 241H110l3-3c68.7-52.7 113.7-120\n 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8\n-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247\nc-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208\n 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3\n 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202\n l-3-3h399890zM100 241v40h399900v-40z",leftbrace:"M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117\n-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7\n 5-6 9-10 13-.7 1-7.3 1-20 1H6z",leftbraceunder:"M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13\n 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688\n 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7\n-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z",leftgroup:"M400000 80\nH435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0\n 435 0h399565z",leftgroupunder:"M400000 262\nH435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219\n 435 219h399565z",leftharpoon:"M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3\n-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5\n-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7\n-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z",leftharpoonplus:"M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5\n 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3\n-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7\n-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z\nm0 0v40h400000v-40z",leftharpoondown:"M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333\n 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5\n 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667\n-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z",leftharpoondownplus:"M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z",lefthook:"M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z",leftlinesegment:"M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z",leftmapsto:"M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z",leftToFrom:"M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z",longequal:"M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z",midbrace:"M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z",midbraceunder:"M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z",oiintSize1:"M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z",oiintSize2:"M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\nc0 110 84 276 504 276s502.4-166 502.4-276z",oiiintSize1:"M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z",oiiintSize2:"M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z",rightarrow:"M0 241v40h399891c-47.3 35.3-84 78-110 128\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n 151.7 139 205zm0 0v40h399900v-40z",rightbrace:"M400000 542l\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z",rightbraceunder:"M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z",rightgroup:"M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\n 3-1 3-3v-38c-76-158-257-219-435-219H0z",rightgroupunder:"M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z",rightharpoon:"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\n 69.2 92 94.5zm0 0v40h399900v-40z",rightharpoonplus:"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z",rightharpoondown:"M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z",rightharpoondownplus:"M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z",righthook:"M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z",rightlinesegment:"M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z",rightToFrom:"M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z",twoheadleftarrow:"M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z",twoheadrightarrow:"M400000 167\nc-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3\n 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42\n 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333\n-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70\n 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z",tilde1:"M200 55.538c-77 0-168 73.953-177 73.953-3 0-7\n-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0\n 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0\n 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128\n-68.267.847-113-73.952-191-73.952z",tilde2:"M344 55.266c-142 0-300.638 81.316-311.5 86.418\n-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9\n 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114\nc1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751\n 181.476 676 181.476c-149 0-189-126.21-332-126.21z",tilde3:"M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457\n-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0\n 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697\n 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696\n -338 0-409-156.573-744-156.573z",tilde4:"M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345\n-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409\n 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9\n 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409\n -175.236-744-175.236z",vec:"M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z",widehat1:"M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22\nc-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z",widehat2:"M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widehat3:"M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widehat4:"M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widecheck1:"M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,\n-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z",widecheck2:"M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",widecheck3:"M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",widecheck4:"M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",baraboveleftarrow:"M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202\nc4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5\nc-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130\ns-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47\n121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6\ns2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11\nc0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z\nM100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z",rightarrowabovebar:"M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32\n-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0\n13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39\n-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5\n-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z",baraboveshortleftharpoon:"M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17\nc2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21\nc-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40\nc-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z\nM0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z",rightharpoonaboveshortbar:"M0,241 l0,40c399126,0,399993,0,399993,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z",shortbaraboveleftharpoon:"M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z",shortrightharpoonabovebar:"M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z"},M=function(){function e(e){this.children=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.children=e,this.classes=[],this.height=0,this.depth=0,this.maxFontSize=0,this.style={}}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){for(var e=document.createDocumentFragment(),t=0;t"},q=function(){function e(e,t,r,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.width=void 0,this.maxFontSize=void 0,this.style=void 0,A.call(this,e,r,n),this.children=t||[]}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){return T.call(this,"span")},t.toMarkup=function(){return B.call(this,"span")},e}(),N=function(){function e(e,t,r,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,A.call(this,t,n),this.children=r||[],this.setAttribute("href",e)}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){return T.call(this,"a")},t.toMarkup=function(){return B.call(this,"a")},e}(),C=function(){function e(e,t,r){this.src=void 0,this.alt=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.alt=t,this.src=e,this.classes=["mord"],this.style=r}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){var e=document.createElement("img");for(var t in e.src=this.src,e.alt=this.alt,e.className="mord",this.style)this.style.hasOwnProperty(t)&&(e.style[t]=this.style[t]);return e},t.toMarkup=function(){var e=""+this.alt+"=a[0]&&e<=a[1])return r.name}return null}(this.text.charCodeAt(0));l&&this.classes.push(l+"_fallback"),/[\xee\xef\xed\xec]/.test(this.text)&&(this.text=I[this.text])}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){var e=document.createTextNode(this.text),t=null;for(var r in this.italic>0&&((t=document.createElement("span")).style.marginRight=this.italic+"em"),this.classes.length>0&&((t=t||document.createElement("span")).className=z(this.classes)),this.style)this.style.hasOwnProperty(r)&&((t=t||document.createElement("span")).style[r]=this.style[r]);return t?(t.appendChild(e),t):e},t.toMarkup=function(){var e=!1,t="0&&(r+="margin-right:"+this.italic+"em;"),this.style)this.style.hasOwnProperty(n)&&(r+=l.hyphenate(n)+":"+this.style[n]+";");r&&(e=!0,t+=' style="'+l.escape(r)+'"');var a=l.escape(this.text);return e?(t+=">",t+=a,t+="
    "):a},e}(),O=function(){function e(e,t){this.children=void 0,this.attributes=void 0,this.children=e||[],this.attributes=t||{}}var t=e.prototype;return t.toNode=function(){var e=document.createElementNS("http://www.w3.org/2000/svg","svg");for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);for(var r=0;r":""},e}(),H=function(){function e(e){this.attributes=void 0,this.attributes=e||{}}var t=e.prototype;return t.toNode=function(){var e=document.createElementNS("http://www.w3.org/2000/svg","line");for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);return e},t.toMarkup=function(){var e="","\\gt",!0),_(j,Z,oe,"\u2208","\\in",!0),_(j,Z,oe,"\ue020","\\@not"),_(j,Z,oe,"\u2282","\\subset",!0),_(j,Z,oe,"\u2283","\\supset",!0),_(j,Z,oe,"\u2286","\\subseteq",!0),_(j,Z,oe,"\u2287","\\supseteq",!0),_(j,K,oe,"\u2288","\\nsubseteq",!0),_(j,K,oe,"\u2289","\\nsupseteq",!0),_(j,Z,oe,"\u22a8","\\models"),_(j,Z,oe,"\u2190","\\leftarrow",!0),_(j,Z,oe,"\u2264","\\le"),_(j,Z,oe,"\u2264","\\leq",!0),_(j,Z,oe,"<","\\lt",!0),_(j,Z,oe,"\u2192","\\rightarrow",!0),_(j,Z,oe,"\u2192","\\to"),_(j,K,oe,"\u2271","\\ngeq",!0),_(j,K,oe,"\u2270","\\nleq",!0),_(j,Z,se,"\xa0","\\ "),_(j,Z,se,"\xa0","\\space"),_(j,Z,se,"\xa0","\\nobreakspace"),_($,Z,se,"\xa0","\\ "),_($,Z,se,"\xa0"," "),_($,Z,se,"\xa0","\\space"),_($,Z,se,"\xa0","\\nobreakspace"),_(j,Z,se,null,"\\nobreak"),_(j,Z,se,null,"\\allowbreak"),_(j,Z,ie,",",","),_(j,Z,ie,";",";"),_(j,K,Q,"\u22bc","\\barwedge",!0),_(j,K,Q,"\u22bb","\\veebar",!0),_(j,Z,Q,"\u2299","\\odot",!0),_(j,Z,Q,"\u2295","\\oplus",!0),_(j,Z,Q,"\u2297","\\otimes",!0),_(j,Z,le,"\u2202","\\partial",!0),_(j,Z,Q,"\u2298","\\oslash",!0),_(j,K,Q,"\u229a","\\circledcirc",!0),_(j,K,Q,"\u22a1","\\boxdot",!0),_(j,Z,Q,"\u25b3","\\bigtriangleup"),_(j,Z,Q,"\u25bd","\\bigtriangledown"),_(j,Z,Q,"\u2020","\\dagger"),_(j,Z,Q,"\u22c4","\\diamond"),_(j,Z,Q,"\u22c6","\\star"),_(j,Z,Q,"\u25c3","\\triangleleft"),_(j,Z,Q,"\u25b9","\\triangleright"),_(j,Z,ae,"{","\\{"),_($,Z,le,"{","\\{"),_($,Z,le,"{","\\textbraceleft"),_(j,Z,ee,"}","\\}"),_($,Z,le,"}","\\}"),_($,Z,le,"}","\\textbraceright"),_(j,Z,ae,"{","\\lbrace"),_(j,Z,ee,"}","\\rbrace"),_(j,Z,ae,"[","\\lbrack",!0),_($,Z,le,"[","\\lbrack",!0),_(j,Z,ee,"]","\\rbrack",!0),_($,Z,le,"]","\\rbrack",!0),_(j,Z,ae,"(","\\lparen",!0),_(j,Z,ee,")","\\rparen",!0),_($,Z,le,"<","\\textless",!0),_($,Z,le,">","\\textgreater",!0),_(j,Z,ae,"\u230a","\\lfloor",!0),_(j,Z,ee,"\u230b","\\rfloor",!0),_(j,Z,ae,"\u2308","\\lceil",!0),_(j,Z,ee,"\u2309","\\rceil",!0),_(j,Z,le,"\\","\\backslash"),_(j,Z,le,"\u2223","|"),_(j,Z,le,"\u2223","\\vert"),_($,Z,le,"|","\\textbar",!0),_(j,Z,le,"\u2225","\\|"),_(j,Z,le,"\u2225","\\Vert"),_($,Z,le,"\u2225","\\textbardbl"),_($,Z,le,"~","\\textasciitilde"),_($,Z,le,"\\","\\textbackslash"),_($,Z,le,"^","\\textasciicircum"),_(j,Z,oe,"\u2191","\\uparrow",!0),_(j,Z,oe,"\u21d1","\\Uparrow",!0),_(j,Z,oe,"\u2193","\\downarrow",!0),_(j,Z,oe,"\u21d3","\\Downarrow",!0),_(j,Z,oe,"\u2195","\\updownarrow",!0),_(j,Z,oe,"\u21d5","\\Updownarrow",!0),_(j,Z,ne,"\u2210","\\coprod"),_(j,Z,ne,"\u22c1","\\bigvee"),_(j,Z,ne,"\u22c0","\\bigwedge"),_(j,Z,ne,"\u2a04","\\biguplus"),_(j,Z,ne,"\u22c2","\\bigcap"),_(j,Z,ne,"\u22c3","\\bigcup"),_(j,Z,ne,"\u222b","\\int"),_(j,Z,ne,"\u222b","\\intop"),_(j,Z,ne,"\u222c","\\iint"),_(j,Z,ne,"\u222d","\\iiint"),_(j,Z,ne,"\u220f","\\prod"),_(j,Z,ne,"\u2211","\\sum"),_(j,Z,ne,"\u2a02","\\bigotimes"),_(j,Z,ne,"\u2a01","\\bigoplus"),_(j,Z,ne,"\u2a00","\\bigodot"),_(j,Z,ne,"\u222e","\\oint"),_(j,Z,ne,"\u222f","\\oiint"),_(j,Z,ne,"\u2230","\\oiiint"),_(j,Z,ne,"\u2a06","\\bigsqcup"),_(j,Z,ne,"\u222b","\\smallint"),_($,Z,te,"\u2026","\\textellipsis"),_(j,Z,te,"\u2026","\\mathellipsis"),_($,Z,te,"\u2026","\\ldots",!0),_(j,Z,te,"\u2026","\\ldots",!0),_(j,Z,te,"\u22ef","\\@cdots",!0),_(j,Z,te,"\u22f1","\\ddots",!0),_(j,Z,le,"\u22ee","\\varvdots"),_(j,Z,J,"\u02ca","\\acute"),_(j,Z,J,"\u02cb","\\grave"),_(j,Z,J,"\xa8","\\ddot"),_(j,Z,J,"~","\\tilde"),_(j,Z,J,"\u02c9","\\bar"),_(j,Z,J,"\u02d8","\\breve"),_(j,Z,J,"\u02c7","\\check"),_(j,Z,J,"^","\\hat"),_(j,Z,J,"\u20d7","\\vec"),_(j,Z,J,"\u02d9","\\dot"),_(j,Z,J,"\u02da","\\mathring"),_(j,Z,re,"\ue131","\\@imath"),_(j,Z,re,"\ue237","\\@jmath"),_(j,Z,le,"\u0131","\u0131"),_(j,Z,le,"\u0237","\u0237"),_($,Z,le,"\u0131","\\i",!0),_($,Z,le,"\u0237","\\j",!0),_($,Z,le,"\xdf","\\ss",!0),_($,Z,le,"\xe6","\\ae",!0),_($,Z,le,"\u0153","\\oe",!0),_($,Z,le,"\xf8","\\o",!0),_($,Z,le,"\xc6","\\AE",!0),_($,Z,le,"\u0152","\\OE",!0),_($,Z,le,"\xd8","\\O",!0),_($,Z,J,"\u02ca","\\'"),_($,Z,J,"\u02cb","\\`"),_($,Z,J,"\u02c6","\\^"),_($,Z,J,"\u02dc","\\~"),_($,Z,J,"\u02c9","\\="),_($,Z,J,"\u02d8","\\u"),_($,Z,J,"\u02d9","\\."),_($,Z,J,"\u02da","\\r"),_($,Z,J,"\u02c7","\\v"),_($,Z,J,"\xa8",'\\"'),_($,Z,J,"\u02dd","\\H"),_($,Z,J,"\u25ef","\\textcircled");var he={"--":!0,"---":!0,"``":!0,"''":!0};_($,Z,le,"\u2013","--",!0),_($,Z,le,"\u2013","\\textendash"),_($,Z,le,"\u2014","---",!0),_($,Z,le,"\u2014","\\textemdash"),_($,Z,le,"\u2018","`",!0),_($,Z,le,"\u2018","\\textquoteleft"),_($,Z,le,"\u2019","'",!0),_($,Z,le,"\u2019","\\textquoteright"),_($,Z,le,"\u201c","``",!0),_($,Z,le,"\u201c","\\textquotedblleft"),_($,Z,le,"\u201d","''",!0),_($,Z,le,"\u201d","\\textquotedblright"),_(j,Z,le,"\xb0","\\degree",!0),_($,Z,le,"\xb0","\\degree"),_($,Z,le,"\xb0","\\textdegree",!0),_(j,Z,le,"\xa3","\\pounds"),_(j,Z,le,"\xa3","\\mathsterling",!0),_($,Z,le,"\xa3","\\pounds"),_($,Z,le,"\xa3","\\textsterling",!0),_(j,K,le,"\u2720","\\maltese"),_($,K,le,"\u2720","\\maltese");for(var me='0123456789/@."',ce=0;ce=5?0:e>=3?1:2]){var r=G[t]={cssEmPerMu:P.quad[t]/18};for(var n in P)P.hasOwnProperty(n)&&(r[n]=P[n][t])}return G[t]}(this.size)),this._fontMetrics},t.getColor=function(){return this.phantom?"transparent":this.color},e}();Ie.BASESIZE=6;var Re=Ie,Oe={pt:1,mm:7227/2540,cm:7227/254,in:72.27,bp:1.00375,pc:12,dd:1238/1157,cc:14856/1157,nd:685/642,nc:1370/107,sp:1/65536,px:1.00375},Ee={ex:!0,em:!0,mu:!0},He=function(e){return"string"!=typeof e&&(e=e.unit),e in Oe||e in Ee||"ex"===e},Le=function(e,t){var r;if(e.unit in Oe)r=Oe[e.unit]/t.fontMetrics().ptPerEm/t.sizeMultiplier;else if("mu"===e.unit)r=t.fontMetrics().cssEmPerMu;else{var a;if(a=t.style.isTight()?t.havingStyle(t.style.text()):t,"ex"===e.unit)r=a.fontMetrics().xHeight;else{if("em"!==e.unit)throw new n("Invalid unit: '"+e.unit+"'");r=a.fontMetrics().quad}a!==t&&(r*=a.sizeMultiplier/t.sizeMultiplier)}return Math.min(e.number*r,t.maxSize)},De=function(e,t,r){return X[r][e]&&X[r][e].replace&&(e=X[r][e].replace),{value:e,metrics:V(e,t,r)}},Pe=function(e,t,r,n,a){var i,o=De(e,t,r),s=o.metrics;if(e=o.value,s){var l=s.italic;("text"===r||n&&"mathit"===n.font)&&(l=0),i=new R(e,s.height,s.depth,l,s.skew,s.width,a)}else"undefined"!=typeof console&&console.warn("No character metrics for '"+e+"' in style '"+t+"' and mode '"+r+"'"),i=new R(e,0,0,0,0,0,a);if(n){i.maxFontSize=n.sizeMultiplier,n.style.isTight()&&i.classes.push("mtight");var h=n.getColor();h&&(i.style.color=h)}return i},Fe=function(e,t){if(z(e.classes)!==z(t.classes)||e.skew!==t.skew||e.maxFontSize!==t.maxFontSize)return!1;if(1===e.classes.length){var r=e.classes[0];if("mbin"===r||"mord"===r)return!1}for(var n in e.style)if(e.style.hasOwnProperty(n)&&e.style[n]!==t.style[n])return!1;for(var a in t.style)if(t.style.hasOwnProperty(a)&&e.style[a]!==t.style[a])return!1;return!0},Ve=function(e){for(var t=0,r=0,n=0,a=0;at&&(t=i.height),i.depth>r&&(r=i.depth),i.maxFontSize>n&&(n=i.maxFontSize)}e.height=t,e.depth=r,e.maxFontSize=n},Ge=function(e,t,r,n){var a=new q(e,t,r,n);return Ve(a),a},Ue=function(e,t,r,n){return new q(e,t,r,n)},Ye=function(e){var t=new M(e);return Ve(t),t},We=function(e,t,r){var n="";switch(e){case"amsrm":n="AMS";break;case"textrm":n="Main";break;case"textsf":n="SansSerif";break;case"texttt":n="Typewriter";break;default:n=e}return n+"-"+("textbf"===t&&"textit"===r?"BoldItalic":"textbf"===t?"Bold":"textit"===t?"Italic":"Regular")},Xe={mathbf:{variant:"bold",fontName:"Main-Bold"},mathrm:{variant:"normal",fontName:"Main-Regular"},textit:{variant:"italic",fontName:"Main-Italic"},mathit:{variant:"italic",fontName:"Main-Italic"},mathnormal:{variant:"italic",fontName:"Math-Italic"},mathbb:{variant:"double-struck",fontName:"AMS-Regular"},mathcal:{variant:"script",fontName:"Caligraphic-Regular"},mathfrak:{variant:"fraktur",fontName:"Fraktur-Regular"},mathscr:{variant:"script",fontName:"Script-Regular"},mathsf:{variant:"sans-serif",fontName:"SansSerif-Regular"},mathtt:{variant:"monospace",fontName:"Typewriter-Regular"}},_e={vec:["vec",.471,.714],oiintSize1:["oiintSize1",.957,.499],oiintSize2:["oiintSize2",1.472,.659],oiiintSize1:["oiiintSize1",1.304,.499],oiiintSize2:["oiiintSize2",1.98,.659]},je={fontMap:Xe,makeSymbol:Pe,mathsym:function(e,t,r,n){return void 0===n&&(n=[]),"boldsymbol"===r.font&&De(e,"Main-Bold",t).metrics?Pe(e,"Main-Bold",t,r,n.concat(["mathbf"])):"\\"===e||"main"===X[t][e].font?Pe(e,"Main-Regular",t,r,n):Pe(e,"AMS-Regular",t,r,n.concat(["amsrm"]))},makeSpan:Ge,makeSvgSpan:Ue,makeLineSpan:function(e,t,r){var n=Ge([e],[],t);return n.height=Math.max(r||t.fontMetrics().defaultRuleThickness,t.minRuleThickness),n.style.borderBottomWidth=n.height+"em",n.maxFontSize=1,n},makeAnchor:function(e,t,r,n){var a=new N(e,t,r,n);return Ve(a),a},makeFragment:Ye,wrapFragment:function(e,t){return e instanceof M?Ge([],[e],t):e},makeVList:function(e,t){for(var r=function(e){if("individualShift"===e.positionType){for(var t=e.children,r=[t[0]],n=-t[0].shift-t[0].elem.depth,a=n,i=1;i0&&(o.push(yt(s,t)),s=[]),o.push(a[l]));s.length>0&&o.push(yt(s,t)),r?((i=yt(ut(r,t,!0))).classes=["tag"],o.push(i)):n&&o.push(n);var m=st(["katex-html"],o);if(m.setAttribute("aria-hidden","true"),i){var c=i.children[0];c.style.height=m.height+m.depth+"em",c.style.verticalAlign=-m.depth+"em"}return m}function wt(e){return new M(e)}var kt=function(){function e(e,t,r){this.type=void 0,this.attributes=void 0,this.children=void 0,this.classes=void 0,this.type=e,this.attributes={},this.children=t||[],this.classes=r||[]}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.getAttribute=function(e){return this.attributes[e]},t.toNode=function(){var e=document.createElementNS("http://www.w3.org/1998/Math/MathML",this.type);for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);this.classes.length>0&&(e.className=z(this.classes));for(var r=0;r0&&(e+=' class ="'+l.escape(z(this.classes))+'"'),e+=">";for(var r=0;r"},t.toText=function(){return this.children.map((function(e){return e.toText()})).join("")},e}(),St=function(){function e(e){this.text=void 0,this.text=e}var t=e.prototype;return t.toNode=function(){return document.createTextNode(this.text)},t.toMarkup=function(){return l.escape(this.toText())},t.toText=function(){return this.text},e}(),Mt={MathNode:kt,TextNode:St,SpaceNode:function(){function e(e){this.width=void 0,this.character=void 0,this.width=e,this.character=e>=.05555&&e<=.05556?"\u200a":e>=.1666&&e<=.1667?"\u2009":e>=.2222&&e<=.2223?"\u2005":e>=.2777&&e<=.2778?"\u2005\u200a":e>=-.05556&&e<=-.05555?"\u200a\u2063":e>=-.1667&&e<=-.1666?"\u2009\u2063":e>=-.2223&&e<=-.2222?"\u205f\u2063":e>=-.2778&&e<=-.2777?"\u2005\u2063":null}var t=e.prototype;return t.toNode=function(){if(this.character)return document.createTextNode(this.character);var e=document.createElementNS("http://www.w3.org/1998/Math/MathML","mspace");return e.setAttribute("width",this.width+"em"),e},t.toMarkup=function(){return this.character?""+this.character+"":''},t.toText=function(){return this.character?this.character:" "},e}(),newDocumentFragment:wt},zt=function(e,t,r){return!X[t][e]||!X[t][e].replace||55349===e.charCodeAt(0)||he.hasOwnProperty(e)&&r&&(r.fontFamily&&"tt"===r.fontFamily.substr(4,2)||r.font&&"tt"===r.font.substr(4,2))||(e=X[t][e].replace),new Mt.TextNode(e)},At=function(e){return 1===e.length?e[0]:new Mt.MathNode("mrow",e)},Tt=function(e,t){if("texttt"===t.fontFamily)return"monospace";if("textsf"===t.fontFamily)return"textit"===t.fontShape&&"textbf"===t.fontWeight?"sans-serif-bold-italic":"textit"===t.fontShape?"sans-serif-italic":"textbf"===t.fontWeight?"bold-sans-serif":"sans-serif";if("textit"===t.fontShape&&"textbf"===t.fontWeight)return"bold-italic";if("textit"===t.fontShape)return"italic";if("textbf"===t.fontWeight)return"bold";var r=t.font;if(!r||"mathnormal"===r)return null;var n=e.mode;if("mathit"===r)return"italic";if("boldsymbol"===r)return"textord"===e.type?"bold":"bold-italic";if("mathbf"===r)return"bold";if("mathbb"===r)return"double-struck";if("mathfrak"===r)return"fraktur";if("mathscr"===r||"mathcal"===r)return"script";if("mathsf"===r)return"sans-serif";if("mathtt"===r)return"monospace";var a=e.text;return l.contains(["\\imath","\\jmath"],a)?null:(X[n][a]&&X[n][a].replace&&(a=X[n][a].replace),V(a,je.fontMap[r].fontName,n)?je.fontMap[r].variant:null)},Bt=function(e,t,r){if(1===e.length){var n=Nt(e[0],t);return r&&n instanceof kt&&"mo"===n.type&&(n.setAttribute("lspace","0em"),n.setAttribute("rspace","0em")),[n]}for(var a,i=[],o=0;o0&&(p.text=p.text.slice(0,1)+"\u0338"+p.text.slice(1),i.pop())}}}i.push(s),a=s}return i},qt=function(e,t,r){return At(Bt(e,t,r))},Nt=function(e,t){if(!e)return new Mt.MathNode("mrow");if(rt[e.type])return rt[e.type](e,t);throw new n("Got group of unknown type: '"+e.type+"'")};function Ct(e,t,r,n,a){var i,o=Bt(e,r);i=1===o.length&&o[0]instanceof kt&&l.contains(["mrow","mtable"],o[0].type)?o[0]:new Mt.MathNode("mrow",o);var s=new Mt.MathNode("annotation",[new Mt.TextNode(t)]);s.setAttribute("encoding","application/x-tex");var h=new Mt.MathNode("semantics",[i,s]),m=new Mt.MathNode("math",[h]);m.setAttribute("xmlns","http://www.w3.org/1998/Math/MathML"),n&&m.setAttribute("display","block");var c=a?"katex":"katex-mathml";return je.makeSpan([c],[m])}var It=function(e){return new Re({style:e.displayMode?b.DISPLAY:b.TEXT,maxSize:e.maxSize,minRuleThickness:e.minRuleThickness})},Rt=function(e,t){if(t.displayMode){var r=["katex-display"];t.leqno&&r.push("leqno"),t.fleqn&&r.push("fleqn"),e=je.makeSpan(r,[e])}return e},Ot=function(e,t,r){var n,a=It(r);if("mathml"===r.output)return Ct(e,t,a,r.displayMode,!0);if("html"===r.output){var i=xt(e,a);n=je.makeSpan(["katex"],[i])}else{var o=Ct(e,t,a,r.displayMode,!1),s=xt(e,a);n=je.makeSpan(["katex"],[o,s])}return Rt(n,r)},Et={widehat:"^",widecheck:"\u02c7",widetilde:"~",utilde:"~",overleftarrow:"\u2190",underleftarrow:"\u2190",xleftarrow:"\u2190",overrightarrow:"\u2192",underrightarrow:"\u2192",xrightarrow:"\u2192",underbrace:"\u23df",overbrace:"\u23de",overgroup:"\u23e0",undergroup:"\u23e1",overleftrightarrow:"\u2194",underleftrightarrow:"\u2194",xleftrightarrow:"\u2194",Overrightarrow:"\u21d2",xRightarrow:"\u21d2",overleftharpoon:"\u21bc",xleftharpoonup:"\u21bc",overrightharpoon:"\u21c0",xrightharpoonup:"\u21c0",xLeftarrow:"\u21d0",xLeftrightarrow:"\u21d4",xhookleftarrow:"\u21a9",xhookrightarrow:"\u21aa",xmapsto:"\u21a6",xrightharpoondown:"\u21c1",xleftharpoondown:"\u21bd",xrightleftharpoons:"\u21cc",xleftrightharpoons:"\u21cb",xtwoheadleftarrow:"\u219e",xtwoheadrightarrow:"\u21a0",xlongequal:"=",xtofrom:"\u21c4",xrightleftarrows:"\u21c4",xrightequilibrium:"\u21cc",xleftequilibrium:"\u21cb","\\cdrightarrow":"\u2192","\\cdleftarrow":"\u2190","\\cdlongequal":"="},Ht={overrightarrow:[["rightarrow"],.888,522,"xMaxYMin"],overleftarrow:[["leftarrow"],.888,522,"xMinYMin"],underrightarrow:[["rightarrow"],.888,522,"xMaxYMin"],underleftarrow:[["leftarrow"],.888,522,"xMinYMin"],xrightarrow:[["rightarrow"],1.469,522,"xMaxYMin"],"\\cdrightarrow":[["rightarrow"],3,522,"xMaxYMin"],xleftarrow:[["leftarrow"],1.469,522,"xMinYMin"],"\\cdleftarrow":[["leftarrow"],3,522,"xMinYMin"],Overrightarrow:[["doublerightarrow"],.888,560,"xMaxYMin"],xRightarrow:[["doublerightarrow"],1.526,560,"xMaxYMin"],xLeftarrow:[["doubleleftarrow"],1.526,560,"xMinYMin"],overleftharpoon:[["leftharpoon"],.888,522,"xMinYMin"],xleftharpoonup:[["leftharpoon"],.888,522,"xMinYMin"],xleftharpoondown:[["leftharpoondown"],.888,522,"xMinYMin"],overrightharpoon:[["rightharpoon"],.888,522,"xMaxYMin"],xrightharpoonup:[["rightharpoon"],.888,522,"xMaxYMin"],xrightharpoondown:[["rightharpoondown"],.888,522,"xMaxYMin"],xlongequal:[["longequal"],.888,334,"xMinYMin"],"\\cdlongequal":[["longequal"],3,334,"xMinYMin"],xtwoheadleftarrow:[["twoheadleftarrow"],.888,334,"xMinYMin"],xtwoheadrightarrow:[["twoheadrightarrow"],.888,334,"xMaxYMin"],overleftrightarrow:[["leftarrow","rightarrow"],.888,522],overbrace:[["leftbrace","midbrace","rightbrace"],1.6,548],underbrace:[["leftbraceunder","midbraceunder","rightbraceunder"],1.6,548],underleftrightarrow:[["leftarrow","rightarrow"],.888,522],xleftrightarrow:[["leftarrow","rightarrow"],1.75,522],xLeftrightarrow:[["doubleleftarrow","doublerightarrow"],1.75,560],xrightleftharpoons:[["leftharpoondownplus","rightharpoonplus"],1.75,716],xleftrightharpoons:[["leftharpoonplus","rightharpoondownplus"],1.75,716],xhookleftarrow:[["leftarrow","righthook"],1.08,522],xhookrightarrow:[["lefthook","rightarrow"],1.08,522],overlinesegment:[["leftlinesegment","rightlinesegment"],.888,522],underlinesegment:[["leftlinesegment","rightlinesegment"],.888,522],overgroup:[["leftgroup","rightgroup"],.888,342],undergroup:[["leftgroupunder","rightgroupunder"],.888,342],xmapsto:[["leftmapsto","rightarrow"],1.5,522],xtofrom:[["leftToFrom","rightToFrom"],1.75,528],xrightleftarrows:[["baraboveleftarrow","rightarrowabovebar"],1.75,901],xrightequilibrium:[["baraboveshortleftharpoon","rightharpoonaboveshortbar"],1.75,716],xleftequilibrium:[["shortbaraboveleftharpoon","shortrightharpoonabovebar"],1.75,716]},Lt=function(e,t,r,n,a){var i,o=e.height+e.depth+r+n;if(/fbox|color|angl/.test(t)){if(i=je.makeSpan(["stretchy",t],[],a),"fbox"===t){var s=a.color&&a.getColor();s&&(i.style.borderColor=s)}}else{var l=[];/^[bx]cancel$/.test(t)&&l.push(new H({x1:"0",y1:"0",x2:"100%",y2:"100%","stroke-width":"0.046em"})),/^x?cancel$/.test(t)&&l.push(new H({x1:"0",y1:"100%",x2:"100%",y2:"0","stroke-width":"0.046em"}));var h=new O(l,{width:"100%",height:o+"em"});i=je.makeSvgSpan([],[h],a)}return i.height=o,i.style.height=o+"em",i},Dt=function(e){var t=new Mt.MathNode("mo",[new Mt.TextNode(Et[e.replace(/^\\/,"")])]);return t.setAttribute("stretchy","true"),t},Pt=function(e,t){var r=function(){var r=4e5,n=e.label.substr(1);if(l.contains(["widehat","widecheck","widetilde","utilde"],n)){var a,i,o,s="ordgroup"===(d=e.base).type?d.body.length:1;if(s>5)"widehat"===n||"widecheck"===n?(a=420,r=2364,o=.42,i=n+"4"):(a=312,r=2340,o=.34,i="tilde4");else{var h=[1,1,2,2,3,3][s];"widehat"===n||"widecheck"===n?(r=[0,1062,2364,2364,2364][h],a=[0,239,300,360,420][h],o=[0,.24,.3,.3,.36,.42][h],i=n+h):(r=[0,600,1033,2339,2340][h],a=[0,260,286,306,312][h],o=[0,.26,.286,.3,.306,.34][h],i="tilde"+h)}var m=new E(i),c=new O([m],{width:"100%",height:o+"em",viewBox:"0 0 "+r+" "+a,preserveAspectRatio:"none"});return{span:je.makeSvgSpan([],[c],t),minWidth:0,height:o}}var u,p,d,f=[],g=Ht[n],v=g[0],b=g[1],y=g[2],x=y/1e3,w=v.length;if(1===w)u=["hide-tail"],p=[g[3]];else if(2===w)u=["halfarrow-left","halfarrow-right"],p=["xMinYMin","xMaxYMin"];else{if(3!==w)throw new Error("Correct katexImagesData or update code here to support\n "+w+" children.");u=["brace-left","brace-center","brace-right"],p=["xMinYMin","xMidYMin","xMaxYMin"]}for(var k=0;k0&&(n.style.minWidth=a+"em"),n};function Ft(e,t){if(!e||e.type!==t)throw new Error("Expected node of type "+t+", but got "+(e?"node of type "+e.type:String(e)));return e}function Vt(e){var t=Gt(e);if(!t)throw new Error("Expected node of symbol group type, but got "+(e?"node of type "+e.type:String(e)));return t}function Gt(e){return e&&("atom"===e.type||Y.hasOwnProperty(e.type))?e:null}var Ut=function(e,t){var r,n,a;e&&"supsub"===e.type?(r=(n=Ft(e.base,"accent")).base,e.base=r,a=function(e){if(e instanceof q)return e;throw new Error("Expected span but got "+String(e)+".")}(bt(e,t)),e.base=n):r=(n=Ft(e,"accent")).base;var i=bt(r,t.havingCrampedStyle()),o=0;if(n.isShifty&&l.isCharacterBox(r)){var s=l.getBaseElem(r);o=L(bt(s,t.havingCrampedStyle())).skew}var h,m=Math.min(i.height,t.fontMetrics().xHeight);if(n.isStretchy)h=Pt(n,t),h=je.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:i},{type:"elem",elem:h,wrapperClasses:["svg-align"],wrapperStyle:o>0?{width:"calc(100% - "+2*o+"em)",marginLeft:2*o+"em"}:void 0}]},t);else{var c,u;"\\vec"===n.label?(c=je.staticSvg("vec",t),u=je.svgData.vec[1]):((c=L(c=je.makeOrd({mode:n.mode,text:n.label},t,"textord"))).italic=0,u=c.width),h=je.makeSpan(["accent-body"],[c]);var p="\\textcircled"===n.label;p&&(h.classes.push("accent-full"),m=i.height);var d=o;p||(d-=u/2),h.style.left=d+"em","\\textcircled"===n.label&&(h.style.top=".2em"),h=je.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:i},{type:"kern",size:-m},{type:"elem",elem:h}]},t)}var f=je.makeSpan(["mord","accent"],[h],t);return a?(a.children[0]=f,a.height=Math.max(f.height,a.height),a.classes[0]="mord",a):f},Yt=function(e,t){var r=e.isStretchy?Dt(e.label):new Mt.MathNode("mo",[zt(e.label,e.mode)]),n=new Mt.MathNode("mover",[Nt(e.base,t),r]);return n.setAttribute("accent","true"),n},Wt=new RegExp(["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring"].map((function(e){return"\\"+e})).join("|"));nt({type:"accent",names:["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring","\\widecheck","\\widehat","\\widetilde","\\overrightarrow","\\overleftarrow","\\Overrightarrow","\\overleftrightarrow","\\overgroup","\\overlinesegment","\\overleftharpoon","\\overrightharpoon"],props:{numArgs:1},handler:function(e,t){var r=it(t[0]),n=!Wt.test(e.funcName),a=!n||"\\widehat"===e.funcName||"\\widetilde"===e.funcName||"\\widecheck"===e.funcName;return{type:"accent",mode:e.parser.mode,label:e.funcName,isStretchy:n,isShifty:a,base:r}},htmlBuilder:Ut,mathmlBuilder:Yt}),nt({type:"accent",names:["\\'","\\`","\\^","\\~","\\=","\\u","\\.",'\\"',"\\r","\\H","\\v","\\textcircled"],props:{numArgs:1,allowedInText:!0,allowedInMath:!1,argTypes:["primitive"]},handler:function(e,t){var r=t[0];return{type:"accent",mode:e.parser.mode,label:e.funcName,isStretchy:!1,isShifty:!0,base:r}},htmlBuilder:Ut,mathmlBuilder:Yt}),nt({type:"accentUnder",names:["\\underleftarrow","\\underrightarrow","\\underleftrightarrow","\\undergroup","\\underlinesegment","\\utilde"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"accentUnder",mode:r.mode,label:n,base:a}},htmlBuilder:function(e,t){var r=bt(e.base,t),n=Pt(e,t),a="\\utilde"===e.label?.12:0,i=je.makeVList({positionType:"top",positionData:r.height,children:[{type:"elem",elem:n,wrapperClasses:["svg-align"]},{type:"kern",size:a},{type:"elem",elem:r}]},t);return je.makeSpan(["mord","accentunder"],[i],t)},mathmlBuilder:function(e,t){var r=Dt(e.label),n=new Mt.MathNode("munder",[Nt(e.base,t),r]);return n.setAttribute("accentunder","true"),n}});var Xt=function(e){var t=new Mt.MathNode("mpadded",e?[e]:[]);return t.setAttribute("width","+0.6em"),t.setAttribute("lspace","0.3em"),t};nt({type:"xArrow",names:["\\xleftarrow","\\xrightarrow","\\xLeftarrow","\\xRightarrow","\\xleftrightarrow","\\xLeftrightarrow","\\xhookleftarrow","\\xhookrightarrow","\\xmapsto","\\xrightharpoondown","\\xrightharpoonup","\\xleftharpoondown","\\xleftharpoonup","\\xrightleftharpoons","\\xleftrightharpoons","\\xlongequal","\\xtwoheadrightarrow","\\xtwoheadleftarrow","\\xtofrom","\\xrightleftarrows","\\xrightequilibrium","\\xleftequilibrium","\\\\cdrightarrow","\\\\cdleftarrow","\\\\cdlongequal"],props:{numArgs:1,numOptionalArgs:1},handler:function(e,t,r){var n=e.parser,a=e.funcName;return{type:"xArrow",mode:n.mode,label:a,body:t[0],below:r[0]}},htmlBuilder:function(e,t){var r,n=t.style,a=t.havingStyle(n.sup()),i=je.wrapFragment(bt(e.body,a,t),t),o="\\x"===e.label.slice(0,2)?"x":"cd";i.classes.push(o+"-arrow-pad"),e.below&&(a=t.havingStyle(n.sub()),(r=je.wrapFragment(bt(e.below,a,t),t)).classes.push(o+"-arrow-pad"));var s,l=Pt(e,t),h=-t.fontMetrics().axisHeight+.5*l.height,m=-t.fontMetrics().axisHeight-.5*l.height-.111;if((i.depth>.25||"\\xleftequilibrium"===e.label)&&(m-=i.depth),r){var c=-t.fontMetrics().axisHeight+r.height+.5*l.height+.111;s=je.makeVList({positionType:"individualShift",children:[{type:"elem",elem:i,shift:m},{type:"elem",elem:l,shift:h},{type:"elem",elem:r,shift:c}]},t)}else s=je.makeVList({positionType:"individualShift",children:[{type:"elem",elem:i,shift:m},{type:"elem",elem:l,shift:h}]},t);return s.children[0].children[0].children[1].classes.push("svg-align"),je.makeSpan(["mrel","x-arrow"],[s],t)},mathmlBuilder:function(e,t){var r,n=Dt(e.label);if(n.setAttribute("minsize","x"===e.label.charAt(0)?"1.75em":"3.0em"),e.body){var a=Xt(Nt(e.body,t));if(e.below){var i=Xt(Nt(e.below,t));r=new Mt.MathNode("munderover",[n,i,a])}else r=new Mt.MathNode("mover",[n,a])}else if(e.below){var o=Xt(Nt(e.below,t));r=new Mt.MathNode("munder",[n,o])}else r=Xt(),r=new Mt.MathNode("mover",[n,r]);return r}});var _t={">":"\\\\cdrightarrow","<":"\\\\cdleftarrow","=":"\\\\cdlongequal",A:"\\uparrow",V:"\\downarrow","|":"\\Vert",".":"no arrow"},jt=function(e){return"textord"===e.type&&"@"===e.text};function $t(e,t,r){var n=_t[e];switch(n){case"\\\\cdrightarrow":case"\\\\cdleftarrow":return r.callFunction(n,[t[0]],[t[1]]);case"\\uparrow":case"\\downarrow":var a={type:"atom",text:n,mode:"math",family:"rel"},i={type:"ordgroup",mode:"math",body:[r.callFunction("\\\\cdleft",[t[0]],[]),r.callFunction("\\Big",[a],[]),r.callFunction("\\\\cdright",[t[1]],[])]};return r.callFunction("\\\\cdparent",[i],[]);case"\\\\cdlongequal":return r.callFunction("\\\\cdlongequal",[],[]);case"\\Vert":return r.callFunction("\\Big",[{type:"textord",text:"\\Vert",mode:"math"}],[]);default:return{type:"textord",text:" ",mode:"math"}}}nt({type:"cdlabel",names:["\\\\cdleft","\\\\cdright"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName;return{type:"cdlabel",mode:r.mode,side:n.slice(4),label:t[0]}},htmlBuilder:function(e,t){var r=t.havingStyle(t.style.sup()),n=je.wrapFragment(bt(e.label,r,t),t);return n.classes.push("cd-label-"+e.side),n.style.bottom=.8-n.depth+"em",n.height=0,n.depth=0,n},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mrow",[Nt(e.label,t)]);return(r=new Mt.MathNode("mpadded",[r])).setAttribute("width","0"),"left"===e.side&&r.setAttribute("lspace","-1width"),r.setAttribute("voffset","0.7em"),(r=new Mt.MathNode("mstyle",[r])).setAttribute("displaystyle","false"),r.setAttribute("scriptlevel","1"),r}}),nt({type:"cdlabelparent",names:["\\\\cdparent"],props:{numArgs:1},handler:function(e,t){return{type:"cdlabelparent",mode:e.parser.mode,fragment:t[0]}},htmlBuilder:function(e,t){var r=je.wrapFragment(bt(e.fragment,t),t);return r.classes.push("cd-vert-arrow"),r},mathmlBuilder:function(e,t){return new Mt.MathNode("mrow",[Nt(e.fragment,t)])}}),nt({type:"textord",names:["\\@char"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){for(var r=e.parser,a=Ft(t[0],"ordgroup").body,i="",o=0;o","\\langle","\\rangle","/","\\backslash","\\lt","\\gt"],gr=[0,1.2,1.8,2.4,3],vr=[{type:"small",style:b.SCRIPTSCRIPT},{type:"small",style:b.SCRIPT},{type:"small",style:b.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4}],br=[{type:"small",style:b.SCRIPTSCRIPT},{type:"small",style:b.SCRIPT},{type:"small",style:b.TEXT},{type:"stack"}],yr=[{type:"small",style:b.SCRIPTSCRIPT},{type:"small",style:b.SCRIPT},{type:"small",style:b.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4},{type:"stack"}],xr=function(e){if("small"===e.type)return"Main-Regular";if("large"===e.type)return"Size"+e.size+"-Regular";if("stack"===e.type)return"Size4-Regular";throw new Error("Add support for delim type '"+e.type+"' here.")},wr=function(e,t,r,n){for(var a=Math.min(2,3-n.style.size);at)return r[a]}return r[r.length-1]},kr=function(e,t,r,n,a,i){var o;"<"===e||"\\lt"===e||"\u27e8"===e?e="\\langle":">"!==e&&"\\gt"!==e&&"\u27e9"!==e||(e="\\rangle"),o=l.contains(fr,e)?vr:l.contains(pr,e)?yr:br;var s=wr(e,t,o,n);return"small"===s.type?function(e,t,r,n,a,i){var o=je.makeSymbol(e,"Main-Regular",a,n),s=rr(o,t,n,i);return r&&nr(s,n,t),s}(e,s.style,r,n,a,i):"large"===s.type?ar(e,s.size,r,n,a,i):mr(e,t,r,n,a,i)},Sr=function(e,t){var r,n,a=t.havingBaseSizing(),i=wr("\\surd",e*a.sizeMultiplier,yr,a),o=a.sizeMultiplier,s=Math.max(0,t.minRuleThickness-t.fontMetrics().sqrtRuleThickness),l=0,h=0,m=0;return"small"===i.type?(e<1?o=1:e<1.4&&(o=.7),h=(1+s)/o,(r=ur("sqrtMain",l=(1+s+cr)/o,m=1e3+1e3*s+80,s,t)).style.minWidth="0.853em",n=.833/o):"large"===i.type?(m=1080*gr[i.size],h=(gr[i.size]+s)/o,l=(gr[i.size]+s+cr)/o,(r=ur("sqrtSize"+i.size,l,m,s,t)).style.minWidth="1.02em",n=1/o):(l=e+s+cr,h=e+s,m=Math.floor(1e3*e+s)+80,(r=ur("sqrtTall",l,m,s,t)).style.minWidth="0.742em",n=1.056),r.height=h,r.style.height=l+"em",{span:r,advanceWidth:n,ruleWidth:(t.fontMetrics().sqrtRuleThickness+s)*o}},Mr=function(e,t,r,a,i){if("<"===e||"\\lt"===e||"\u27e8"===e?e="\\langle":">"!==e&&"\\gt"!==e&&"\u27e9"!==e||(e="\\rangle"),l.contains(pr,e)||l.contains(fr,e))return ar(e,t,!1,r,a,i);if(l.contains(dr,e))return mr(e,gr[t],!1,r,a,i);throw new n("Illegal delimiter: '"+e+"'")},zr=gr,Ar=kr,Tr=function(e,t,r,n,a,i){var o=n.fontMetrics().axisHeight*n.sizeMultiplier,s=5/n.fontMetrics().ptPerEm,l=Math.max(t-o,r+o),h=Math.max(l/500*901,2*l-s);return kr(e,h,!0,n,a,i)},Br={"\\bigl":{mclass:"mopen",size:1},"\\Bigl":{mclass:"mopen",size:2},"\\biggl":{mclass:"mopen",size:3},"\\Biggl":{mclass:"mopen",size:4},"\\bigr":{mclass:"mclose",size:1},"\\Bigr":{mclass:"mclose",size:2},"\\biggr":{mclass:"mclose",size:3},"\\Biggr":{mclass:"mclose",size:4},"\\bigm":{mclass:"mrel",size:1},"\\Bigm":{mclass:"mrel",size:2},"\\biggm":{mclass:"mrel",size:3},"\\Biggm":{mclass:"mrel",size:4},"\\big":{mclass:"mord",size:1},"\\Big":{mclass:"mord",size:2},"\\bigg":{mclass:"mord",size:3},"\\Bigg":{mclass:"mord",size:4}},qr=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","\u230a","\u230b","\\lceil","\\rceil","\u2308","\u2309","<",">","\\langle","\u27e8","\\rangle","\u27e9","\\lt","\\gt","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","\u27ee","\u27ef","\\lmoustache","\\rmoustache","\u23b0","\u23b1","/","\\backslash","|","\\vert","\\|","\\Vert","\\uparrow","\\Uparrow","\\downarrow","\\Downarrow","\\updownarrow","\\Updownarrow","."];function Nr(e,t){var r=Gt(e);if(r&&l.contains(qr,r.text))return r;throw new n(r?"Invalid delimiter '"+r.text+"' after '"+t.funcName+"'":"Invalid delimiter type '"+e.type+"'",e)}function Cr(e){if(!e.body)throw new Error("Bug: The leftright ParseNode wasn't fully parsed.")}nt({type:"delimsizing",names:["\\bigl","\\Bigl","\\biggl","\\Biggl","\\bigr","\\Bigr","\\biggr","\\Biggr","\\bigm","\\Bigm","\\biggm","\\Biggm","\\big","\\Big","\\bigg","\\Bigg"],props:{numArgs:1,argTypes:["primitive"]},handler:function(e,t){var r=Nr(t[0],e);return{type:"delimsizing",mode:e.parser.mode,size:Br[e.funcName].size,mclass:Br[e.funcName].mclass,delim:r.text}},htmlBuilder:function(e,t){return"."===e.delim?je.makeSpan([e.mclass]):Mr(e.delim,e.size,t,e.mode,[e.mclass])},mathmlBuilder:function(e){var t=[];"."!==e.delim&&t.push(zt(e.delim,e.mode));var r=new Mt.MathNode("mo",t);return"mopen"===e.mclass||"mclose"===e.mclass?r.setAttribute("fence","true"):r.setAttribute("fence","false"),r.setAttribute("stretchy","true"),r.setAttribute("minsize",zr[e.size]+"em"),r.setAttribute("maxsize",zr[e.size]+"em"),r}}),nt({type:"leftright-right",names:["\\right"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=e.parser.gullet.macros.get("\\current@color");if(r&&"string"!=typeof r)throw new n("\\current@color set to non-string in \\right");return{type:"leftright-right",mode:e.parser.mode,delim:Nr(t[0],e).text,color:r}}}),nt({type:"leftright",names:["\\left"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=Nr(t[0],e),n=e.parser;++n.leftrightDepth;var a=n.parseExpression(!1);--n.leftrightDepth,n.expect("\\right",!1);var i=Ft(n.parseFunction(),"leftright-right");return{type:"leftright",mode:n.mode,body:a,left:r.text,right:i.delim,rightColor:i.color}},htmlBuilder:function(e,t){Cr(e);for(var r,n,a=ut(e.body,t,!0,["mopen","mclose"]),i=0,o=0,s=!1,l=0;l-1?"mpadded":"menclose",[Nt(e.body,t)]);switch(e.label){case"\\cancel":n.setAttribute("notation","updiagonalstrike");break;case"\\bcancel":n.setAttribute("notation","downdiagonalstrike");break;case"\\phase":n.setAttribute("notation","phasorangle");break;case"\\sout":n.setAttribute("notation","horizontalstrike");break;case"\\fbox":n.setAttribute("notation","box");break;case"\\angl":n.setAttribute("notation","actuarial");break;case"\\fcolorbox":case"\\colorbox":if(r=t.fontMetrics().fboxsep*t.fontMetrics().ptPerEm,n.setAttribute("width","+"+2*r+"pt"),n.setAttribute("height","+"+2*r+"pt"),n.setAttribute("lspace",r+"pt"),n.setAttribute("voffset",r+"pt"),"\\fcolorbox"===e.label){var a=Math.max(t.fontMetrics().fboxrule,t.minRuleThickness);n.setAttribute("style","border: "+a+"em solid "+String(e.borderColor))}break;case"\\xcancel":n.setAttribute("notation","updiagonalstrike downdiagonalstrike")}return e.backgroundColor&&n.setAttribute("mathbackground",e.backgroundColor),n};nt({type:"enclose",names:["\\colorbox"],props:{numArgs:2,allowedInText:!0,argTypes:["color","text"]},handler:function(e,t,r){var n=e.parser,a=e.funcName,i=Ft(t[0],"color-token").color,o=t[1];return{type:"enclose",mode:n.mode,label:a,backgroundColor:i,body:o}},htmlBuilder:Ir,mathmlBuilder:Rr}),nt({type:"enclose",names:["\\fcolorbox"],props:{numArgs:3,allowedInText:!0,argTypes:["color","color","text"]},handler:function(e,t,r){var n=e.parser,a=e.funcName,i=Ft(t[0],"color-token").color,o=Ft(t[1],"color-token").color,s=t[2];return{type:"enclose",mode:n.mode,label:a,backgroundColor:o,borderColor:i,body:s}},htmlBuilder:Ir,mathmlBuilder:Rr}),nt({type:"enclose",names:["\\fbox"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!0},handler:function(e,t){return{type:"enclose",mode:e.parser.mode,label:"\\fbox",body:t[0]}}}),nt({type:"enclose",names:["\\cancel","\\bcancel","\\xcancel","\\sout","\\phase"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"enclose",mode:r.mode,label:n,body:a}},htmlBuilder:Ir,mathmlBuilder:Rr}),nt({type:"enclose",names:["\\angl"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!1},handler:function(e,t){return{type:"enclose",mode:e.parser.mode,label:"\\angl",body:t[0]}}});var Or={};function Er(e){for(var t=e.type,r=e.names,n=e.props,a=e.handler,i=e.htmlBuilder,o=e.mathmlBuilder,s={type:t,numArgs:n.numArgs||0,allowedInText:!1,numOptionalArgs:0,handler:a},l=0;l1||!c)&&g.pop(),b.length0&&(x+=.25),m.push({pos:x,isDashed:e[t]})}for(w(o[0]),r=0;r0&&(M<(B+=y)&&(M=B),B=0),e.addJot&&(M+=f),z.height=S,z.depth=M,x+=S,z.pos=x,x+=M+B,h[r]=z,w(o[r+1])}var q,N,C=x/2+t.fontMetrics().axisHeight,I=e.cols||[],R=[],O=[];if(e.addEqnNum)for(r=0;r=s)){var G=void 0;(a>0||e.hskipBeforeAndAfter)&&0!==(G=l.deflt(D.pregap,p))&&((q=je.makeSpan(["arraycolsep"],[])).style.width=G+"em",R.push(q));var U=[];for(r=0;r0){for(var _=je.makeLineSpan("hline",t,c),j=je.makeLineSpan("hdashline",t,c),$=[{type:"elem",elem:h,shift:0}];m.length>0;){var Z=m.pop(),K=Z.pos-C;Z.isDashed?$.push({type:"elem",elem:j,shift:K}):$.push({type:"elem",elem:_,shift:K})}h=je.makeVList({positionType:"individualShift",children:$},t)}if(e.addEqnNum){var J=je.makeVList({positionType:"individualShift",children:O},t);return J=je.makeSpan(["tag"],[J],t),je.makeFragment([h,J])}return je.makeSpan(["mord"],[h],t)},Vr={c:"center ",l:"left ",r:"right "},Gr=function(e,t){for(var r=[],n=new Mt.MathNode("mtd",[],["mtr-glue"]),a=new Mt.MathNode("mtd",[],["mml-eqn-num"]),i=0;i0){var p=e.cols,d="",f=!1,g=0,v=p.length;"separator"===p[0].type&&(c+="top ",g=1),"separator"===p[p.length-1].type&&(c+="bottom ",v-=1);for(var b=g;b0?"left ":"",c+=S[S.length-1].length>0?"right ":"";for(var M=1;M-1?"alignat":"align",o=Dr(e.parser,{cols:a,addJot:!0,addEqnNum:"align"===e.envName||"alignat"===e.envName,emptySingleRow:!0,colSeparationType:i,maxNumCols:"split"===e.envName?2:void 0,leqno:e.parser.settings.leqno},"display"),s=0,l={type:"ordgroup",mode:e.mode,body:[]};if(t[0]&&"ordgroup"===t[0].type){for(var h="",m=0;m0&&c&&(d=1),a[u]={type:"align",align:p,pregap:d,postgap:0}}return o.colSeparationType=c?"align":"alignat",o};Er({type:"array",names:["array","darray"],props:{numArgs:1},handler:function(e,t){var r=(Gt(t[0])?[t[0]]:Ft(t[0],"ordgroup").body).map((function(e){var t=Vt(e).text;if(-1!=="lcr".indexOf(t))return{type:"align",align:t};if("|"===t)return{type:"separator",separator:"|"};if(":"===t)return{type:"separator",separator:":"};throw new n("Unknown column alignment: "+t,e)})),a={cols:r,hskipBeforeAndAfter:!0,maxNumCols:r.length};return Dr(e.parser,a,Pr(e.envName))},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix","matrix*","pmatrix*","bmatrix*","Bmatrix*","vmatrix*","Vmatrix*"],props:{numArgs:0},handler:function(e){var t={matrix:null,pmatrix:["(",")"],bmatrix:["[","]"],Bmatrix:["\\{","\\}"],vmatrix:["|","|"],Vmatrix:["\\Vert","\\Vert"]}[e.envName.replace("*","")],r="c",a={hskipBeforeAndAfter:!1,cols:[{type:"align",align:r}]};if("*"===e.envName.charAt(e.envName.length-1)){var i=e.parser;if(i.consumeSpaces(),"["===i.fetch().text){if(i.consume(),i.consumeSpaces(),r=i.fetch().text,-1==="lcr".indexOf(r))throw new n("Expected l or c or r",i.nextToken);i.consume(),i.consumeSpaces(),i.expect("]"),i.consume(),a.cols=[{type:"align",align:r}]}}var o=Dr(e.parser,a,Pr(e.envName));return o.cols=new Array(o.body[0].length).fill({type:"align",align:r}),t?{type:"leftright",mode:e.mode,body:[o],left:t[0],right:t[1],rightColor:void 0}:o},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["smallmatrix"],props:{numArgs:0},handler:function(e){var t=Dr(e.parser,{arraystretch:.5},"script");return t.colSeparationType="small",t},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["subarray"],props:{numArgs:1},handler:function(e,t){var r=(Gt(t[0])?[t[0]]:Ft(t[0],"ordgroup").body).map((function(e){var t=Vt(e).text;if(-1!=="lc".indexOf(t))return{type:"align",align:t};throw new n("Unknown column alignment: "+t,e)}));if(r.length>1)throw new n("{subarray} can contain only one column");var a={cols:r,hskipBeforeAndAfter:!1,arraystretch:.5};if((a=Dr(e.parser,a,"script")).body.length>0&&a.body[0].length>1)throw new n("{subarray} can contain only one column");return a},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["cases","dcases","rcases","drcases"],props:{numArgs:0},handler:function(e){var t=Dr(e.parser,{arraystretch:1.2,cols:[{type:"align",align:"l",pregap:0,postgap:1},{type:"align",align:"l",pregap:0,postgap:0}]},Pr(e.envName));return{type:"leftright",mode:e.mode,body:[t],left:e.envName.indexOf("r")>-1?".":"\\{",right:e.envName.indexOf("r")>-1?"\\}":".",rightColor:void 0}},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["align","align*","aligned","split"],props:{numArgs:0},handler:Ur,htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["gathered","gather","gather*"],props:{numArgs:0},handler:function(e){l.contains(["gather","gather*"],e.envName)&&Lr(e);var t={cols:[{type:"align",align:"c"}],addJot:!0,colSeparationType:"gather",addEqnNum:"gather"===e.envName,emptySingleRow:!0,leqno:e.parser.settings.leqno};return Dr(e.parser,t,"display")},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["alignat","alignat*","alignedat"],props:{numArgs:1},handler:Ur,htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["equation","equation*"],props:{numArgs:0},handler:function(e){Lr(e);var t={addEqnNum:"equation"===e.envName,emptySingleRow:!0,singleRow:!0,maxNumCols:1,leqno:e.parser.settings.leqno};return Dr(e.parser,t,"display")},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["CD"],props:{numArgs:0},handler:function(e){return Lr(e),function(e){var t=[];for(e.gullet.beginGroup(),e.gullet.macros.set("\\cr","\\\\\\relax"),e.gullet.beginGroup();;){t.push(e.parseExpression(!1,"\\\\")),e.gullet.endGroup(),e.gullet.beginGroup();var r=e.fetch().text;if("&"!==r&&"\\\\"!==r){if("\\end"===r){0===t[t.length-1].length&&t.pop();break}throw new n("Expected \\\\ or \\cr or \\end",e.nextToken)}e.consume()}for(var a,i,o=[],s=[o],l=0;l-1);else{if(!("<>AV".indexOf(u)>-1))throw new n('Expected one of "<>AV=|." after @',h[c]);for(var d=0;d<2;d++){for(var f=!0,g=c+1;g=b.SCRIPT.id?r.text():b.DISPLAY:"text"===e&&r.size===b.DISPLAY.size?r=b.TEXT:"script"===e?r=b.SCRIPT:"scriptscript"===e&&(r=b.SCRIPTSCRIPT),r},Qr=function(e,t){var r,n=Jr(e.size,t.style),a=n.fracNum(),i=n.fracDen();r=t.havingStyle(a);var o=bt(e.numer,r,t);if(e.continued){var s=8.5/t.fontMetrics().ptPerEm,l=3.5/t.fontMetrics().ptPerEm;o.height=o.height0?3*c:7*c,d=t.fontMetrics().denom1):(m>0?(u=t.fontMetrics().num2,p=c):(u=t.fontMetrics().num3,p=3*c),d=t.fontMetrics().denom2),h){var w=t.fontMetrics().axisHeight;u-o.depth-(w+.5*m)0&&(t="."===(t=e)?null:t),t};nt({type:"genfrac",names:["\\genfrac"],props:{numArgs:6,allowedInArgument:!0,argTypes:["math","math","size","text","math","math"]},handler:function(e,t){var r,n=e.parser,a=t[4],i=t[5],o=it(t[0]),s="atom"===o.type&&"open"===o.family?rn(o.text):null,l=it(t[1]),h="atom"===l.type&&"close"===l.family?rn(l.text):null,m=Ft(t[2],"size"),c=null;r=!!m.isBlank||(c=m.value).number>0;var u="auto",p=t[3];if("ordgroup"===p.type){if(p.body.length>0){var d=Ft(p.body[0],"textord");u=tn[Number(d.text)]}}else p=Ft(p,"textord"),u=tn[Number(p.text)];return{type:"genfrac",mode:n.mode,numer:a,denom:i,continued:!1,hasBarLine:r,barSize:c,leftDelim:s,rightDelim:h,size:u}},htmlBuilder:Qr,mathmlBuilder:en}),nt({type:"infix",names:["\\above"],props:{numArgs:1,argTypes:["size"],infix:!0},handler:function(e,t){var r=e.parser,n=(e.funcName,e.token);return{type:"infix",mode:r.mode,replaceWith:"\\\\abovefrac",size:Ft(t[0],"size").value,token:n}}}),nt({type:"genfrac",names:["\\\\abovefrac"],props:{numArgs:3,argTypes:["math","size","math"]},handler:function(e,t){var r=e.parser,n=(e.funcName,t[0]),a=function(e){if(!e)throw new Error("Expected non-null, but got "+String(e));return e}(Ft(t[1],"infix").size),i=t[2],o=a.number>0;return{type:"genfrac",mode:r.mode,numer:n,denom:i,continued:!1,hasBarLine:o,barSize:a,leftDelim:null,rightDelim:null,size:"auto"}},htmlBuilder:Qr,mathmlBuilder:en});var nn=function(e,t){var r,n,a=t.style;"supsub"===e.type?(r=e.sup?bt(e.sup,t.havingStyle(a.sup()),t):bt(e.sub,t.havingStyle(a.sub()),t),n=Ft(e.base,"horizBrace")):n=Ft(e,"horizBrace");var i,o=bt(n.base,t.havingBaseStyle(b.DISPLAY)),s=Pt(n,t);if(n.isOver?(i=je.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:o},{type:"kern",size:.1},{type:"elem",elem:s}]},t)).children[0].children[0].children[1].classes.push("svg-align"):(i=je.makeVList({positionType:"bottom",positionData:o.depth+.1+s.height,children:[{type:"elem",elem:s},{type:"kern",size:.1},{type:"elem",elem:o}]},t)).children[0].children[0].children[0].classes.push("svg-align"),r){var l=je.makeSpan(["mord",n.isOver?"mover":"munder"],[i],t);i=n.isOver?je.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:l},{type:"kern",size:.2},{type:"elem",elem:r}]},t):je.makeVList({positionType:"bottom",positionData:l.depth+.2+r.height+r.depth,children:[{type:"elem",elem:r},{type:"kern",size:.2},{type:"elem",elem:l}]},t)}return je.makeSpan(["mord",n.isOver?"mover":"munder"],[i],t)};nt({type:"horizBrace",names:["\\overbrace","\\underbrace"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName;return{type:"horizBrace",mode:r.mode,label:n,isOver:/^\\over/.test(n),base:t[0]}},htmlBuilder:nn,mathmlBuilder:function(e,t){var r=Dt(e.label);return new Mt.MathNode(e.isOver?"mover":"munder",[Nt(e.base,t),r])}}),nt({type:"href",names:["\\href"],props:{numArgs:2,argTypes:["url","original"],allowedInText:!0},handler:function(e,t){var r=e.parser,n=t[1],a=Ft(t[0],"url").url;return r.settings.isTrusted({command:"\\href",url:a})?{type:"href",mode:r.mode,href:a,body:ot(n)}:r.formatUnsupportedCmd("\\href")},htmlBuilder:function(e,t){var r=ut(e.body,t,!1);return je.makeAnchor(e.href,[],r,t)},mathmlBuilder:function(e,t){var r=qt(e.body,t);return r instanceof kt||(r=new kt("mrow",[r])),r.setAttribute("href",e.href),r}}),nt({type:"href",names:["\\url"],props:{numArgs:1,argTypes:["url"],allowedInText:!0},handler:function(e,t){var r=e.parser,n=Ft(t[0],"url").url;if(!r.settings.isTrusted({command:"\\url",url:n}))return r.formatUnsupportedCmd("\\url");for(var a=[],i=0;i0&&(n=Le(e.totalheight,t)-r,n=Number(n.toFixed(2)));var a=0;e.width.number>0&&(a=Le(e.width,t));var i={height:r+n+"em"};a>0&&(i.width=a+"em"),n>0&&(i.verticalAlign=-n+"em");var o=new C(e.src,e.alt,i);return o.height=r,o.depth=n,o},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mglyph",[]);r.setAttribute("alt",e.alt);var n=Le(e.height,t),a=0;if(e.totalheight.number>0&&(a=(a=Le(e.totalheight,t)-n).toFixed(2),r.setAttribute("valign","-"+a+"em")),r.setAttribute("height",n+a+"em"),e.width.number>0){var i=Le(e.width,t);r.setAttribute("width",i+"em")}return r.setAttribute("src",e.src),r}}),nt({type:"kern",names:["\\kern","\\mkern","\\hskip","\\mskip"],props:{numArgs:1,argTypes:["size"],primitive:!0,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=Ft(t[0],"size");if(r.settings.strict){var i="m"===n[1],o="mu"===a.value.unit;i?(o||r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" supports only mu units, not "+a.value.unit+" units"),"math"!==r.mode&&r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" works only in math mode")):o&&r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" doesn't support mu units")}return{type:"kern",mode:r.mode,dimension:a.value}},htmlBuilder:function(e,t){return je.makeGlue(e.dimension,t)},mathmlBuilder:function(e,t){var r=Le(e.dimension,t);return new Mt.SpaceNode(r)}}),nt({type:"lap",names:["\\mathllap","\\mathrlap","\\mathclap"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"lap",mode:r.mode,alignment:n.slice(5),body:a}},htmlBuilder:function(e,t){var r;"clap"===e.alignment?(r=je.makeSpan([],[bt(e.body,t)]),r=je.makeSpan(["inner"],[r],t)):r=je.makeSpan(["inner"],[bt(e.body,t)]);var n=je.makeSpan(["fix"],[]),a=je.makeSpan([e.alignment],[r,n],t),i=je.makeSpan(["strut"]);return i.style.height=a.height+a.depth+"em",i.style.verticalAlign=-a.depth+"em",a.children.unshift(i),a=je.makeSpan(["thinbox"],[a],t),je.makeSpan(["mord","vbox"],[a],t)},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mpadded",[Nt(e.body,t)]);if("rlap"!==e.alignment){var n="llap"===e.alignment?"-1":"-0.5";r.setAttribute("lspace",n+"width")}return r.setAttribute("width","0px"),r}}),nt({type:"styling",names:["\\(","$"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler:function(e,t){var r=e.funcName,n=e.parser,a=n.mode;n.switchMode("math");var i="\\("===r?"\\)":"$",o=n.parseExpression(!1,i);return n.expect(i),n.switchMode(a),{type:"styling",mode:n.mode,style:"text",body:o}}}),nt({type:"text",names:["\\)","\\]"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler:function(e,t){throw new n("Mismatched "+e.funcName)}});var on=function(e,t){switch(t.style.size){case b.DISPLAY.size:return e.display;case b.TEXT.size:return e.text;case b.SCRIPT.size:return e.script;case b.SCRIPTSCRIPT.size:return e.scriptscript;default:return e.text}};nt({type:"mathchoice",names:["\\mathchoice"],props:{numArgs:4,primitive:!0},handler:function(e,t){return{type:"mathchoice",mode:e.parser.mode,display:ot(t[0]),text:ot(t[1]),script:ot(t[2]),scriptscript:ot(t[3])}},htmlBuilder:function(e,t){var r=on(e,t),n=ut(r,t,!1);return je.makeFragment(n)},mathmlBuilder:function(e,t){var r=on(e,t);return qt(r,t)}});var sn=function(e,t,r,n,a,i,o){var s,l,h;if(e=je.makeSpan([],[e]),t){var m=bt(t,n.havingStyle(a.sup()),n);l={elem:m,kern:Math.max(n.fontMetrics().bigOpSpacing1,n.fontMetrics().bigOpSpacing3-m.depth)}}if(r){var c=bt(r,n.havingStyle(a.sub()),n);s={elem:c,kern:Math.max(n.fontMetrics().bigOpSpacing2,n.fontMetrics().bigOpSpacing4-c.height)}}if(l&&s){var u=n.fontMetrics().bigOpSpacing5+s.elem.height+s.elem.depth+s.kern+e.depth+o;h=je.makeVList({positionType:"bottom",positionData:u,children:[{type:"kern",size:n.fontMetrics().bigOpSpacing5},{type:"elem",elem:s.elem,marginLeft:-i+"em"},{type:"kern",size:s.kern},{type:"elem",elem:e},{type:"kern",size:l.kern},{type:"elem",elem:l.elem,marginLeft:i+"em"},{type:"kern",size:n.fontMetrics().bigOpSpacing5}]},n)}else if(s){var p=e.height-o;h=je.makeVList({positionType:"top",positionData:p,children:[{type:"kern",size:n.fontMetrics().bigOpSpacing5},{type:"elem",elem:s.elem,marginLeft:-i+"em"},{type:"kern",size:s.kern},{type:"elem",elem:e}]},n)}else{if(!l)return e;var d=e.depth+o;h=je.makeVList({positionType:"bottom",positionData:d,children:[{type:"elem",elem:e},{type:"kern",size:l.kern},{type:"elem",elem:l.elem,marginLeft:i+"em"},{type:"kern",size:n.fontMetrics().bigOpSpacing5}]},n)}return je.makeSpan(["mop","op-limits"],[h],n)},ln=["\\smallint"],hn=function(e,t){var r,n,a,i=!1;"supsub"===e.type?(r=e.sup,n=e.sub,a=Ft(e.base,"op"),i=!0):a=Ft(e,"op");var o,s=t.style,h=!1;if(s.size===b.DISPLAY.size&&a.symbol&&!l.contains(ln,a.name)&&(h=!0),a.symbol){var m=h?"Size2-Regular":"Size1-Regular",c="";if("\\oiint"!==a.name&&"\\oiiint"!==a.name||(c=a.name.substr(1),a.name="oiint"===c?"\\iint":"\\iiint"),o=je.makeSymbol(a.name,m,"math",t,["mop","op-symbol",h?"large-op":"small-op"]),c.length>0){var u=o.italic,p=je.staticSvg(c+"Size"+(h?"2":"1"),t);o=je.makeVList({positionType:"individualShift",children:[{type:"elem",elem:o,shift:0},{type:"elem",elem:p,shift:h?.08:0}]},t),a.name="\\"+c,o.classes.unshift("mop"),o.italic=u}}else if(a.body){var d=ut(a.body,t,!0);1===d.length&&d[0]instanceof R?(o=d[0]).classes[0]="mop":o=je.makeSpan(["mop"],d,t)}else{for(var f=[],g=1;g=t)throw new n("Invalid base-"+t+" digit "+r.text);for(var i;null!=(i=gn[e.future().text])&&i":"\\dotsb","-":"\\dotsb","*":"\\dotsb",":":"\\dotsb","\\DOTSB":"\\dotsb","\\coprod":"\\dotsb","\\bigvee":"\\dotsb","\\bigwedge":"\\dotsb","\\biguplus":"\\dotsb","\\bigcap":"\\dotsb","\\bigcup":"\\dotsb","\\prod":"\\dotsb","\\sum":"\\dotsb","\\bigotimes":"\\dotsb","\\bigoplus":"\\dotsb","\\bigodot":"\\dotsb","\\bigsqcup":"\\dotsb","\\And":"\\dotsb","\\longrightarrow":"\\dotsb","\\Longrightarrow":"\\dotsb","\\longleftarrow":"\\dotsb","\\Longleftarrow":"\\dotsb","\\longleftrightarrow":"\\dotsb","\\Longleftrightarrow":"\\dotsb","\\mapsto":"\\dotsb","\\longmapsto":"\\dotsb","\\hookrightarrow":"\\dotsb","\\doteq":"\\dotsb","\\mathbin":"\\dotsb","\\mathrel":"\\dotsb","\\relbar":"\\dotsb","\\Relbar":"\\dotsb","\\xrightarrow":"\\dotsb","\\xleftarrow":"\\dotsb","\\DOTSI":"\\dotsi","\\int":"\\dotsi","\\oint":"\\dotsi","\\iint":"\\dotsi","\\iiint":"\\dotsi","\\iiiint":"\\dotsi","\\idotsint":"\\dotsi","\\DOTSX":"\\dotsx"};fn("\\dots",(function(e){var t="\\dotso",r=e.expandAfterFuture().text;return r in bn?t=bn[r]:("\\not"===r.substr(0,4)||r in X.math&&l.contains(["bin","rel"],X.math[r].group))&&(t="\\dotsb"),t}));var yn={")":!0,"]":!0,"\\rbrack":!0,"\\}":!0,"\\rbrace":!0,"\\rangle":!0,"\\rceil":!0,"\\rfloor":!0,"\\rgroup":!0,"\\rmoustache":!0,"\\right":!0,"\\bigr":!0,"\\biggr":!0,"\\Bigr":!0,"\\Biggr":!0,$:!0,";":!0,".":!0,",":!0};fn("\\dotso",(function(e){return e.future().text in yn?"\\ldots\\,":"\\ldots"})),fn("\\dotsc",(function(e){var t=e.future().text;return t in yn&&","!==t?"\\ldots\\,":"\\ldots"})),fn("\\cdots",(function(e){return e.future().text in yn?"\\@cdots\\,":"\\@cdots"})),fn("\\dotsb","\\cdots"),fn("\\dotsm","\\cdots"),fn("\\dotsi","\\!\\cdots"),fn("\\dotsx","\\ldots\\,"),fn("\\DOTSI","\\relax"),fn("\\DOTSB","\\relax"),fn("\\DOTSX","\\relax"),fn("\\tmspace","\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"),fn("\\,","\\tmspace+{3mu}{.1667em}"),fn("\\thinspace","\\,"),fn("\\>","\\mskip{4mu}"),fn("\\:","\\tmspace+{4mu}{.2222em}"),fn("\\medspace","\\:"),fn("\\;","\\tmspace+{5mu}{.2777em}"),fn("\\thickspace","\\;"),fn("\\!","\\tmspace-{3mu}{.1667em}"),fn("\\negthinspace","\\!"),fn("\\negmedspace","\\tmspace-{4mu}{.2222em}"),fn("\\negthickspace","\\tmspace-{5mu}{.277em}"),fn("\\enspace","\\kern.5em "),fn("\\enskip","\\hskip.5em\\relax"),fn("\\quad","\\hskip1em\\relax"),fn("\\qquad","\\hskip2em\\relax"),fn("\\tag","\\@ifstar\\tag@literal\\tag@paren"),fn("\\tag@paren","\\tag@literal{({#1})}"),fn("\\tag@literal",(function(e){if(e.macros.get("\\df@tag"))throw new n("Multiple \\tag");return"\\gdef\\df@tag{\\text{#1}}"})),fn("\\bmod","\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}\\mathbin{\\rm mod}\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}"),fn("\\pod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"),fn("\\pmod","\\pod{{\\rm mod}\\mkern6mu#1}"),fn("\\mod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}{\\rm mod}\\,\\,#1"),fn("\\pmb","\\html@mathml{\\@binrel{#1}{\\mathrlap{#1}\\kern0.5px#1}}{\\mathbf{#1}}"),fn("\\newline","\\\\\\relax"),fn("\\TeX","\\textrm{\\html@mathml{T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX}{TeX}}");var xn=D["Main-Regular"]["T".charCodeAt(0)][1]-.7*D["Main-Regular"]["A".charCodeAt(0)][1]+"em";fn("\\LaTeX","\\textrm{\\html@mathml{L\\kern-.36em\\raisebox{"+xn+"}{\\scriptstyle A}\\kern-.15em\\TeX}{LaTeX}}"),fn("\\KaTeX","\\textrm{\\html@mathml{K\\kern-.17em\\raisebox{"+xn+"}{\\scriptstyle A}\\kern-.15em\\TeX}{KaTeX}}"),fn("\\hspace","\\@ifstar\\@hspacer\\@hspace"),fn("\\@hspace","\\hskip #1\\relax"),fn("\\@hspacer","\\rule{0pt}{0pt}\\hskip #1\\relax"),fn("\\ordinarycolon",":"),fn("\\vcentcolon","\\mathrel{\\mathop\\ordinarycolon}"),fn("\\dblcolon",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}{\\mathop{\\char"2237}}'),fn("\\coloneqq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2254}}'),fn("\\Coloneqq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2237\\char"3d}}'),fn("\\coloneq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"3a\\char"2212}}'),fn("\\Coloneq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"2237\\char"2212}}'),fn("\\eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2255}}'),fn("\\Eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"3d\\char"2237}}'),fn("\\eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2239}}'),fn("\\Eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"2212\\char"2237}}'),fn("\\colonapprox",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"3a\\char"2248}}'),fn("\\Colonapprox",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"2237\\char"2248}}'),fn("\\colonsim",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"3a\\char"223c}}'),fn("\\Colonsim",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"2237\\char"223c}}'),fn("\u2237","\\dblcolon"),fn("\u2239","\\eqcolon"),fn("\u2254","\\coloneqq"),fn("\u2255","\\eqqcolon"),fn("\u2a74","\\Coloneqq"),fn("\\ratio","\\vcentcolon"),fn("\\coloncolon","\\dblcolon"),fn("\\colonequals","\\coloneqq"),fn("\\coloncolonequals","\\Coloneqq"),fn("\\equalscolon","\\eqqcolon"),fn("\\equalscoloncolon","\\Eqqcolon"),fn("\\colonminus","\\coloneq"),fn("\\coloncolonminus","\\Coloneq"),fn("\\minuscolon","\\eqcolon"),fn("\\minuscoloncolon","\\Eqcolon"),fn("\\coloncolonapprox","\\Colonapprox"),fn("\\coloncolonsim","\\Colonsim"),fn("\\simcolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),fn("\\simcoloncolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}"),fn("\\approxcolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),fn("\\approxcoloncolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"),fn("\\notni","\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220c}}"),fn("\\limsup","\\DOTSB\\operatorname*{lim\\,sup}"),fn("\\liminf","\\DOTSB\\operatorname*{lim\\,inf}"),fn("\\injlim","\\DOTSB\\operatorname*{inj\\,lim}"),fn("\\projlim","\\DOTSB\\operatorname*{proj\\,lim}"),fn("\\varlimsup","\\DOTSB\\operatorname*{\\overline{lim}}"),fn("\\varliminf","\\DOTSB\\operatorname*{\\underline{lim}}"),fn("\\varinjlim","\\DOTSB\\operatorname*{\\underrightarrow{lim}}"),fn("\\varprojlim","\\DOTSB\\operatorname*{\\underleftarrow{lim}}"),fn("\\gvertneqq","\\html@mathml{\\@gvertneqq}{\u2269}"),fn("\\lvertneqq","\\html@mathml{\\@lvertneqq}{\u2268}"),fn("\\ngeqq","\\html@mathml{\\@ngeqq}{\u2271}"),fn("\\ngeqslant","\\html@mathml{\\@ngeqslant}{\u2271}"),fn("\\nleqq","\\html@mathml{\\@nleqq}{\u2270}"),fn("\\nleqslant","\\html@mathml{\\@nleqslant}{\u2270}"),fn("\\nshortmid","\\html@mathml{\\@nshortmid}{\u2224}"),fn("\\nshortparallel","\\html@mathml{\\@nshortparallel}{\u2226}"),fn("\\nsubseteqq","\\html@mathml{\\@nsubseteqq}{\u2288}"),fn("\\nsupseteqq","\\html@mathml{\\@nsupseteqq}{\u2289}"),fn("\\varsubsetneq","\\html@mathml{\\@varsubsetneq}{\u228a}"),fn("\\varsubsetneqq","\\html@mathml{\\@varsubsetneqq}{\u2acb}"),fn("\\varsupsetneq","\\html@mathml{\\@varsupsetneq}{\u228b}"),fn("\\varsupsetneqq","\\html@mathml{\\@varsupsetneqq}{\u2acc}"),fn("\\imath","\\html@mathml{\\@imath}{\u0131}"),fn("\\jmath","\\html@mathml{\\@jmath}{\u0237}"),fn("\\llbracket","\\html@mathml{\\mathopen{[\\mkern-3.2mu[}}{\\mathopen{\\char`\u27e6}}"),fn("\\rrbracket","\\html@mathml{\\mathclose{]\\mkern-3.2mu]}}{\\mathclose{\\char`\u27e7}}"),fn("\u27e6","\\llbracket"),fn("\u27e7","\\rrbracket"),fn("\\lBrace","\\html@mathml{\\mathopen{\\{\\mkern-3.2mu[}}{\\mathopen{\\char`\u2983}}"),fn("\\rBrace","\\html@mathml{\\mathclose{]\\mkern-3.2mu\\}}}{\\mathclose{\\char`\u2984}}"),fn("\u2983","\\lBrace"),fn("\u2984","\\rBrace"),fn("\\minuso","\\mathbin{\\html@mathml{{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}{\\char`\u29b5}}"),fn("\u29b5","\\minuso"),fn("\\darr","\\downarrow"),fn("\\dArr","\\Downarrow"),fn("\\Darr","\\Downarrow"),fn("\\lang","\\langle"),fn("\\rang","\\rangle"),fn("\\uarr","\\uparrow"),fn("\\uArr","\\Uparrow"),fn("\\Uarr","\\Uparrow"),fn("\\N","\\mathbb{N}"),fn("\\R","\\mathbb{R}"),fn("\\Z","\\mathbb{Z}"),fn("\\alef","\\aleph"),fn("\\alefsym","\\aleph"),fn("\\Alpha","\\mathrm{A}"),fn("\\Beta","\\mathrm{B}"),fn("\\bull","\\bullet"),fn("\\Chi","\\mathrm{X}"),fn("\\clubs","\\clubsuit"),fn("\\cnums","\\mathbb{C}"),fn("\\Complex","\\mathbb{C}"),fn("\\Dagger","\\ddagger"),fn("\\diamonds","\\diamondsuit"),fn("\\empty","\\emptyset"),fn("\\Epsilon","\\mathrm{E}"),fn("\\Eta","\\mathrm{H}"),fn("\\exist","\\exists"),fn("\\harr","\\leftrightarrow"),fn("\\hArr","\\Leftrightarrow"),fn("\\Harr","\\Leftrightarrow"),fn("\\hearts","\\heartsuit"),fn("\\image","\\Im"),fn("\\infin","\\infty"),fn("\\Iota","\\mathrm{I}"),fn("\\isin","\\in"),fn("\\Kappa","\\mathrm{K}"),fn("\\larr","\\leftarrow"),fn("\\lArr","\\Leftarrow"),fn("\\Larr","\\Leftarrow"),fn("\\lrarr","\\leftrightarrow"),fn("\\lrArr","\\Leftrightarrow"),fn("\\Lrarr","\\Leftrightarrow"),fn("\\Mu","\\mathrm{M}"),fn("\\natnums","\\mathbb{N}"),fn("\\Nu","\\mathrm{N}"),fn("\\Omicron","\\mathrm{O}"),fn("\\plusmn","\\pm"),fn("\\rarr","\\rightarrow"),fn("\\rArr","\\Rightarrow"),fn("\\Rarr","\\Rightarrow"),fn("\\real","\\Re"),fn("\\reals","\\mathbb{R}"),fn("\\Reals","\\mathbb{R}"),fn("\\Rho","\\mathrm{P}"),fn("\\sdot","\\cdot"),fn("\\sect","\\S"),fn("\\spades","\\spadesuit"),fn("\\sub","\\subset"),fn("\\sube","\\subseteq"),fn("\\supe","\\supseteq"),fn("\\Tau","\\mathrm{T}"),fn("\\thetasym","\\vartheta"),fn("\\weierp","\\wp"),fn("\\Zeta","\\mathrm{Z}"),fn("\\argmin","\\DOTSB\\operatorname*{arg\\,min}"),fn("\\argmax","\\DOTSB\\operatorname*{arg\\,max}"),fn("\\plim","\\DOTSB\\mathop{\\operatorname{plim}}\\limits"),fn("\\bra","\\mathinner{\\langle{#1}|}"),fn("\\ket","\\mathinner{|{#1}\\rangle}"),fn("\\braket","\\mathinner{\\langle{#1}\\rangle}"),fn("\\Bra","\\left\\langle#1\\right|"),fn("\\Ket","\\left|#1\\right\\rangle"),fn("\\angln","{\\angl n}"),fn("\\blue","\\textcolor{##6495ed}{#1}"),fn("\\orange","\\textcolor{##ffa500}{#1}"),fn("\\pink","\\textcolor{##ff00af}{#1}"),fn("\\red","\\textcolor{##df0030}{#1}"),fn("\\green","\\textcolor{##28ae7b}{#1}"),fn("\\gray","\\textcolor{gray}{#1}"),fn("\\purple","\\textcolor{##9d38bd}{#1}"),fn("\\blueA","\\textcolor{##ccfaff}{#1}"),fn("\\blueB","\\textcolor{##80f6ff}{#1}"),fn("\\blueC","\\textcolor{##63d9ea}{#1}"),fn("\\blueD","\\textcolor{##11accd}{#1}"),fn("\\blueE","\\textcolor{##0c7f99}{#1}"),fn("\\tealA","\\textcolor{##94fff5}{#1}"),fn("\\tealB","\\textcolor{##26edd5}{#1}"),fn("\\tealC","\\textcolor{##01d1c1}{#1}"),fn("\\tealD","\\textcolor{##01a995}{#1}"),fn("\\tealE","\\textcolor{##208170}{#1}"),fn("\\greenA","\\textcolor{##b6ffb0}{#1}"),fn("\\greenB","\\textcolor{##8af281}{#1}"),fn("\\greenC","\\textcolor{##74cf70}{#1}"),fn("\\greenD","\\textcolor{##1fab54}{#1}"),fn("\\greenE","\\textcolor{##0d923f}{#1}"),fn("\\goldA","\\textcolor{##ffd0a9}{#1}"),fn("\\goldB","\\textcolor{##ffbb71}{#1}"),fn("\\goldC","\\textcolor{##ff9c39}{#1}"),fn("\\goldD","\\textcolor{##e07d10}{#1}"),fn("\\goldE","\\textcolor{##a75a05}{#1}"),fn("\\redA","\\textcolor{##fca9a9}{#1}"),fn("\\redB","\\textcolor{##ff8482}{#1}"),fn("\\redC","\\textcolor{##f9685d}{#1}"),fn("\\redD","\\textcolor{##e84d39}{#1}"),fn("\\redE","\\textcolor{##bc2612}{#1}"),fn("\\maroonA","\\textcolor{##ffbde0}{#1}"),fn("\\maroonB","\\textcolor{##ff92c6}{#1}"),fn("\\maroonC","\\textcolor{##ed5fa6}{#1}"),fn("\\maroonD","\\textcolor{##ca337c}{#1}"),fn("\\maroonE","\\textcolor{##9e034e}{#1}"),fn("\\purpleA","\\textcolor{##ddd7ff}{#1}"),fn("\\purpleB","\\textcolor{##c6b9fc}{#1}"),fn("\\purpleC","\\textcolor{##aa87ff}{#1}"),fn("\\purpleD","\\textcolor{##7854ab}{#1}"),fn("\\purpleE","\\textcolor{##543b78}{#1}"),fn("\\mintA","\\textcolor{##f5f9e8}{#1}"),fn("\\mintB","\\textcolor{##edf2df}{#1}"),fn("\\mintC","\\textcolor{##e0e5cc}{#1}"),fn("\\grayA","\\textcolor{##f6f7f7}{#1}"),fn("\\grayB","\\textcolor{##f0f1f2}{#1}"),fn("\\grayC","\\textcolor{##e3e5e6}{#1}"),fn("\\grayD","\\textcolor{##d6d8da}{#1}"),fn("\\grayE","\\textcolor{##babec2}{#1}"),fn("\\grayF","\\textcolor{##888d93}{#1}"),fn("\\grayG","\\textcolor{##626569}{#1}"),fn("\\grayH","\\textcolor{##3b3e40}{#1}"),fn("\\grayI","\\textcolor{##21242c}{#1}"),fn("\\kaBlue","\\textcolor{##314453}{#1}"),fn("\\kaGreen","\\textcolor{##71B307}{#1}");var wn=function(e,t){var r,n,a,i,o=!1;if("supsub"===e.type?(r=e.sup,n=e.sub,a=Ft(e.base,"operatorname"),o=!0):a=Ft(e,"operatorname"),a.body.length>0){for(var s=a.body.map((function(e){var t=e.text;return"string"==typeof t?{type:"textord",mode:e.mode,text:t}:e})),l=ut(s,t.withFont("mathrm"),!0),h=0;h=0?s.setAttribute("height","+"+a+"em"):(s.setAttribute("height",a+"em"),s.setAttribute("depth","+"+-a+"em")),s.setAttribute("voffset",a+"em"),s}});var Sn=["\\tiny","\\sixptsize","\\scriptsize","\\footnotesize","\\small","\\normalsize","\\large","\\Large","\\LARGE","\\huge","\\Huge"];nt({type:"sizing",names:Sn,props:{numArgs:0,allowedInText:!0},handler:function(e,t){var r=e.breakOnTokenText,n=e.funcName,a=e.parser,i=a.parseExpression(!1,r);return{type:"sizing",mode:a.mode,size:Sn.indexOf(n)+1,body:i}},htmlBuilder:function(e,t){var r=t.havingSize(e.size);return kn(e.body,r,t)},mathmlBuilder:function(e,t){var r=t.havingSize(e.size),n=Bt(e.body,r),a=new Mt.MathNode("mstyle",n);return a.setAttribute("mathsize",r.sizeMultiplier+"em"),a}}),nt({type:"smash",names:["\\smash"],props:{numArgs:1,numOptionalArgs:1,allowedInText:!0},handler:function(e,t,r){var n=e.parser,a=!1,i=!1,o=r[0]&&Ft(r[0],"ordgroup");if(o)for(var s="",l=0;lr.height+r.depth+i&&(i=(i+c-r.height-r.depth)/2);var u=l.height-r.height-i-h;r.style.paddingLeft=m+"em";var p=je.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:r,wrapperClasses:["svg-align"]},{type:"kern",size:-(r.height+u)},{type:"elem",elem:l},{type:"kern",size:h}]},t);if(e.index){var d=t.havingStyle(b.SCRIPTSCRIPT),f=bt(e.index,d,t),g=.6*(p.height-p.depth),v=je.makeVList({positionType:"shift",positionData:-g,children:[{type:"elem",elem:f}]},t),y=je.makeSpan(["root"],[v]);return je.makeSpan(["mord","sqrt"],[y,p],t)}return je.makeSpan(["mord","sqrt"],[p],t)},mathmlBuilder:function(e,t){var r=e.body,n=e.index;return n?new Mt.MathNode("mroot",[Nt(r,t),Nt(n,t)]):new Mt.MathNode("msqrt",[Nt(r,t)])}});var Mn={display:b.DISPLAY,text:b.TEXT,script:b.SCRIPT,scriptscript:b.SCRIPTSCRIPT};nt({type:"styling",names:["\\displaystyle","\\textstyle","\\scriptstyle","\\scriptscriptstyle"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e,t){var r=e.breakOnTokenText,n=e.funcName,a=e.parser,i=a.parseExpression(!0,r),o=n.slice(1,n.length-5);return{type:"styling",mode:a.mode,style:o,body:i}},htmlBuilder:function(e,t){var r=Mn[e.style],n=t.havingStyle(r).withFont("");return kn(e.body,n,t)},mathmlBuilder:function(e,t){var r=Mn[e.style],n=t.havingStyle(r),a=Bt(e.body,n),i=new Mt.MathNode("mstyle",a),o={display:["0","true"],text:["0","false"],script:["1","false"],scriptscript:["2","false"]}[e.style];return i.setAttribute("scriptlevel",o[0]),i.setAttribute("displaystyle",o[1]),i}});var zn=function(e,t){var r=e.base;return r?"op"===r.type?r.limits&&(t.style.size===b.DISPLAY.size||r.alwaysHandleSupSub)?hn:null:"operatorname"===r.type?r.alwaysHandleSupSub&&(t.style.size===b.DISPLAY.size||r.limits)?wn:null:"accent"===r.type?l.isCharacterBox(r.base)?Ut:null:"horizBrace"===r.type&&!e.sub===r.isOver?nn:null:null};at({type:"supsub",htmlBuilder:function(e,t){var r=zn(e,t);if(r)return r(e,t);var n,a,i,o=e.base,s=e.sup,h=e.sub,m=bt(o,t),c=t.fontMetrics(),u=0,p=0,d=o&&l.isCharacterBox(o);if(s){var f=t.havingStyle(t.style.sup());n=bt(s,f,t),d||(u=m.height-f.fontMetrics().supDrop*f.sizeMultiplier/t.sizeMultiplier)}if(h){var g=t.havingStyle(t.style.sub());a=bt(h,g,t),d||(p=m.depth+g.fontMetrics().subDrop*g.sizeMultiplier/t.sizeMultiplier)}i=t.style===b.DISPLAY?c.sup1:t.style.cramped?c.sup3:c.sup2;var v,y=t.sizeMultiplier,x=.5/c.ptPerEm/y+"em",w=null;if(a){var k=e.base&&"op"===e.base.type&&e.base.name&&("\\oiint"===e.base.name||"\\oiiint"===e.base.name);(m instanceof R||k)&&(w=-m.italic+"em")}if(n&&a){u=Math.max(u,i,n.depth+.25*c.xHeight),p=Math.max(p,c.sub2);var S=4*c.defaultRuleThickness;if(u-n.depth-(a.height-p)0&&(u+=M,p-=M)}var z=[{type:"elem",elem:a,shift:p,marginRight:x,marginLeft:w},{type:"elem",elem:n,shift:-u,marginRight:x}];v=je.makeVList({positionType:"individualShift",children:z},t)}else if(a){p=Math.max(p,c.sub1,a.height-.8*c.xHeight);var A=[{type:"elem",elem:a,marginLeft:w,marginRight:x}];v=je.makeVList({positionType:"shift",positionData:p,children:A},t)}else{if(!n)throw new Error("supsub must have either sup or sub.");u=Math.max(u,i,n.depth+.25*c.xHeight),v=je.makeVList({positionType:"shift",positionData:-u,children:[{type:"elem",elem:n,marginRight:x}]},t)}var T=gt(m,"right")||"mord";return je.makeSpan([T],[m,je.makeSpan(["msupsub"],[v])],t)},mathmlBuilder:function(e,t){var r,n=!1;e.base&&"horizBrace"===e.base.type&&!!e.sup===e.base.isOver&&(n=!0,r=e.base.isOver),!e.base||"op"!==e.base.type&&"operatorname"!==e.base.type||(e.base.parentIsSupSub=!0);var a,i=[Nt(e.base,t)];if(e.sub&&i.push(Nt(e.sub,t)),e.sup&&i.push(Nt(e.sup,t)),n)a=r?"mover":"munder";else if(e.sub)if(e.sup){var o=e.base;a=o&&"op"===o.type&&o.limits&&t.style===b.DISPLAY||o&&"operatorname"===o.type&&o.alwaysHandleSupSub&&(t.style===b.DISPLAY||o.limits)?"munderover":"msubsup"}else{var s=e.base;a=s&&"op"===s.type&&s.limits&&(t.style===b.DISPLAY||s.alwaysHandleSupSub)||s&&"operatorname"===s.type&&s.alwaysHandleSupSub&&(s.limits||t.style===b.DISPLAY)?"munder":"msub"}else{var l=e.base;a=l&&"op"===l.type&&l.limits&&(t.style===b.DISPLAY||l.alwaysHandleSupSub)||l&&"operatorname"===l.type&&l.alwaysHandleSupSub&&(l.limits||t.style===b.DISPLAY)?"mover":"msup"}return new Mt.MathNode(a,i)}}),at({type:"atom",htmlBuilder:function(e,t){return je.mathsym(e.text,e.mode,t,["m"+e.family])},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mo",[zt(e.text,e.mode)]);if("bin"===e.family){var n=Tt(e,t);"bold-italic"===n&&r.setAttribute("mathvariant",n)}else"punct"===e.family?r.setAttribute("separator","true"):"open"!==e.family&&"close"!==e.family||r.setAttribute("stretchy","false");return r}});var An={mi:"italic",mn:"normal",mtext:"normal"};at({type:"mathord",htmlBuilder:function(e,t){return je.makeOrd(e,t,"mathord")},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mi",[zt(e.text,e.mode,t)]),n=Tt(e,t)||"italic";return n!==An[r.type]&&r.setAttribute("mathvariant",n),r}}),at({type:"textord",htmlBuilder:function(e,t){return je.makeOrd(e,t,"textord")},mathmlBuilder:function(e,t){var r,n=zt(e.text,e.mode,t),a=Tt(e,t)||"normal";return r="text"===e.mode?new Mt.MathNode("mtext",[n]):/[0-9]/.test(e.text)?new Mt.MathNode("mn",[n]):"\\prime"===e.text?new Mt.MathNode("mo",[n]):new Mt.MathNode("mi",[n]),a!==An[r.type]&&r.setAttribute("mathvariant",a),r}});var Tn={"\\nobreak":"nobreak","\\allowbreak":"allowbreak"},Bn={" ":{},"\\ ":{},"~":{className:"nobreak"},"\\space":{},"\\nobreakspace":{className:"nobreak"}};at({type:"spacing",htmlBuilder:function(e,t){if(Bn.hasOwnProperty(e.text)){var r=Bn[e.text].className||"";if("text"===e.mode){var a=je.makeOrd(e,t,"textord");return a.classes.push(r),a}return je.makeSpan(["mspace",r],[je.mathsym(e.text,e.mode,t)],t)}if(Tn.hasOwnProperty(e.text))return je.makeSpan(["mspace",Tn[e.text]],[],t);throw new n('Unknown type of space "'+e.text+'"')},mathmlBuilder:function(e,t){if(!Bn.hasOwnProperty(e.text)){if(Tn.hasOwnProperty(e.text))return new Mt.MathNode("mspace");throw new n('Unknown type of space "'+e.text+'"')}return new Mt.MathNode("mtext",[new Mt.TextNode("\xa0")])}});var qn=function(){var e=new Mt.MathNode("mtd",[]);return e.setAttribute("width","50%"),e};at({type:"tag",mathmlBuilder:function(e,t){var r=new Mt.MathNode("mtable",[new Mt.MathNode("mtr",[qn(),new Mt.MathNode("mtd",[qt(e.body,t)]),qn(),new Mt.MathNode("mtd",[qt(e.tag,t)])])]);return r.setAttribute("width","100%"),r}});var Nn={"\\text":void 0,"\\textrm":"textrm","\\textsf":"textsf","\\texttt":"texttt","\\textnormal":"textrm"},Cn={"\\textbf":"textbf","\\textmd":"textmd"},In={"\\textit":"textit","\\textup":"textup"},Rn=function(e,t){var r=e.font;return r?Nn[r]?t.withTextFontFamily(Nn[r]):Cn[r]?t.withTextFontWeight(Cn[r]):t.withTextFontShape(In[r]):t};nt({type:"text",names:["\\text","\\textrm","\\textsf","\\texttt","\\textnormal","\\textbf","\\textmd","\\textit","\\textup"],props:{numArgs:1,argTypes:["text"],allowedInArgument:!0,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"text",mode:r.mode,body:ot(a),font:n}},htmlBuilder:function(e,t){var r=Rn(e,t),n=ut(e.body,r,!0);return je.makeSpan(["mord","text"],n,r)},mathmlBuilder:function(e,t){var r=Rn(e,t);return qt(e.body,r)}}),nt({type:"underline",names:["\\underline"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){return{type:"underline",mode:e.parser.mode,body:t[0]}},htmlBuilder:function(e,t){var r=bt(e.body,t),n=je.makeLineSpan("underline-line",t),a=t.fontMetrics().defaultRuleThickness,i=je.makeVList({positionType:"top",positionData:r.height,children:[{type:"kern",size:a},{type:"elem",elem:n},{type:"kern",size:3*a},{type:"elem",elem:r}]},t);return je.makeSpan(["mord","underline"],[i],t)},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mo",[new Mt.TextNode("\u203e")]);r.setAttribute("stretchy","true");var n=new Mt.MathNode("munder",[Nt(e.body,t),r]);return n.setAttribute("accentunder","true"),n}}),nt({type:"vcenter",names:["\\vcenter"],props:{numArgs:1,argTypes:["original"],allowedInText:!1},handler:function(e,t){return{type:"vcenter",mode:e.parser.mode,body:t[0]}},htmlBuilder:function(e,t){var r=bt(e.body,t),n=t.fontMetrics().axisHeight,a=.5*(r.height-n-(r.depth+n));return je.makeVList({positionType:"shift",positionData:a,children:[{type:"elem",elem:r}]},t)},mathmlBuilder:function(e,t){return new Mt.MathNode("mpadded",[Nt(e.body,t)],["vcenter"])}}),nt({type:"verb",names:["\\verb"],props:{numArgs:0,allowedInText:!0},handler:function(e,t,r){throw new n("\\verb ended by end of line instead of matching delimiter")},htmlBuilder:function(e,t){for(var r=On(e),n=[],a=t.havingStyle(t.style.text()),i=0;i0&&(this.undefStack[this.undefStack.length-1][e]=t)}else{var a=this.undefStack[this.undefStack.length-1];a&&!a.hasOwnProperty(e)&&(a[e]=this.current[e])}this.current[e]=t},e}(),Vn={"\\relax":!0,"^":!0,_:!0,"\\limits":!0,"\\nolimits":!0},Gn=function(){function e(e,t,r){this.settings=void 0,this.expansionCount=void 0,this.lexer=void 0,this.macros=void 0,this.stack=void 0,this.mode=void 0,this.settings=t,this.expansionCount=0,this.feed(e),this.macros=new Fn(dn,t.macros),this.mode=r,this.stack=[]}var t=e.prototype;return t.feed=function(e){this.lexer=new Pn(e,this.settings)},t.switchMode=function(e){this.mode=e},t.beginGroup=function(){this.macros.beginGroup()},t.endGroup=function(){this.macros.endGroup()},t.future=function(){return 0===this.stack.length&&this.pushToken(this.lexer.lex()),this.stack[this.stack.length-1]},t.popToken=function(){return this.future(),this.stack.pop()},t.pushToken=function(e){this.stack.push(e)},t.pushTokens=function(e){var t;(t=this.stack).push.apply(t,e)},t.scanArgument=function(e){var t,r,n;if(e){if(this.consumeSpaces(),"["!==this.future().text)return null;t=this.popToken();var a=this.consumeArg(["]"]);n=a.tokens,r=a.end}else{var i=this.consumeArg();n=i.tokens,t=i.start,r=i.end}return this.pushToken(new Ln("EOF",r.loc)),this.pushTokens(n),t.range(r,"")},t.consumeSpaces=function(){for(;;){if(" "!==this.future().text)break;this.stack.pop()}},t.consumeArg=function(e){var t=[],r=e&&e.length>0;r||this.consumeSpaces();var a,i=this.future(),o=0,s=0;do{if(a=this.popToken(),t.push(a),"{"===a.text)++o;else if("}"===a.text){if(-1===--o)throw new n("Extra }",a)}else if("EOF"===a.text)throw new n("Unexpected end of input in a macro argument, expected '"+(e&&r?e[s]:"}")+"'",a);if(e&&r)if((0===o||1===o&&"{"===e[s])&&a.text===e[s]){if(++s===e.length){t.splice(-s,s);break}}else s=0}while(0!==o||r);return"{"===i.text&&"}"===t[t.length-1].text&&(t.pop(),t.shift()),t.reverse(),{tokens:t,start:i,end:a}},t.consumeArgs=function(e,t){if(t){if(t.length!==e+1)throw new n("The length of delimiters doesn't match the number of args!");for(var r=t[0],a=0;athis.settings.maxExpand)throw new n("Too many expansions: infinite loop or need to increase maxExpand setting");var i=a.tokens,o=this.consumeArgs(a.numArgs,a.delimiters);if(a.numArgs)for(var s=(i=i.slice()).length-1;s>=0;--s){var l=i[s];if("#"===l.text){if(0===s)throw new n("Incomplete placeholder at end of macro body",l);if("#"===(l=i[--s]).text)i.splice(s+1,1);else{if(!/^[1-9]$/.test(l.text))throw new n("Not a valid argument number",l);var h;(h=i).splice.apply(h,[s,2].concat(o[+l.text-1]))}}}return this.pushTokens(i),i},t.expandAfterFuture=function(){return this.expandOnce(),this.future()},t.expandNextToken=function(){for(;;){var e=this.expandOnce();if(e instanceof Ln){if("\\relax"!==e.text&&!e.treatAsRelax)return this.stack.pop();this.stack.pop()}}throw new Error},t.expandMacro=function(e){return this.macros.has(e)?this.expandTokens([new Ln(e)]):void 0},t.expandTokens=function(e){var t=[],r=this.stack.length;for(this.pushTokens(e);this.stack.length>r;){var n=this.expandOnce(!0);n instanceof Ln&&(n.treatAsRelax&&(n.noexpand=!1,n.treatAsRelax=!1),t.push(this.stack.pop()))}return t},t.expandMacroAsText=function(e){var t=this.expandMacro(e);return t?t.map((function(e){return e.text})).join(""):t},t._getExpansion=function(e){var t=this.macros.get(e);if(null==t)return t;if(1===e.length){var r=this.lexer.catcodes[e];if(null!=r&&13!==r)return}var n="function"==typeof t?t(this):t;if("string"==typeof n){var a=0;if(-1!==n.indexOf("#"))for(var i=n.replace(/##/g,"");-1!==i.indexOf("#"+(a+1));)++a;for(var o=new Pn(n,this.settings),s=[],l=o.lex();"EOF"!==l.text;)s.push(l),l=o.lex();return s.reverse(),{tokens:s,numArgs:a}}return n},t.isDefined=function(e){return this.macros.has(e)||En.hasOwnProperty(e)||X.math.hasOwnProperty(e)||X.text.hasOwnProperty(e)||Vn.hasOwnProperty(e)},t.isExpandable=function(e){var t=this.macros.get(e);return null!=t?"string"==typeof t||"function"==typeof t||!t.unexpandable:En.hasOwnProperty(e)&&!En[e].primitive},e}(),Un={"\u0301":{text:"\\'",math:"\\acute"},"\u0300":{text:"\\`",math:"\\grave"},"\u0308":{text:'\\"',math:"\\ddot"},"\u0303":{text:"\\~",math:"\\tilde"},"\u0304":{text:"\\=",math:"\\bar"},"\u0306":{text:"\\u",math:"\\breve"},"\u030c":{text:"\\v",math:"\\check"},"\u0302":{text:"\\^",math:"\\hat"},"\u0307":{text:"\\.",math:"\\dot"},"\u030a":{text:"\\r",math:"\\mathring"},"\u030b":{text:"\\H"}},Yn={"\xe1":"a\u0301","\xe0":"a\u0300","\xe4":"a\u0308","\u01df":"a\u0308\u0304","\xe3":"a\u0303","\u0101":"a\u0304","\u0103":"a\u0306","\u1eaf":"a\u0306\u0301","\u1eb1":"a\u0306\u0300","\u1eb5":"a\u0306\u0303","\u01ce":"a\u030c","\xe2":"a\u0302","\u1ea5":"a\u0302\u0301","\u1ea7":"a\u0302\u0300","\u1eab":"a\u0302\u0303","\u0227":"a\u0307","\u01e1":"a\u0307\u0304","\xe5":"a\u030a","\u01fb":"a\u030a\u0301","\u1e03":"b\u0307","\u0107":"c\u0301","\u010d":"c\u030c","\u0109":"c\u0302","\u010b":"c\u0307","\u010f":"d\u030c","\u1e0b":"d\u0307","\xe9":"e\u0301","\xe8":"e\u0300","\xeb":"e\u0308","\u1ebd":"e\u0303","\u0113":"e\u0304","\u1e17":"e\u0304\u0301","\u1e15":"e\u0304\u0300","\u0115":"e\u0306","\u011b":"e\u030c","\xea":"e\u0302","\u1ebf":"e\u0302\u0301","\u1ec1":"e\u0302\u0300","\u1ec5":"e\u0302\u0303","\u0117":"e\u0307","\u1e1f":"f\u0307","\u01f5":"g\u0301","\u1e21":"g\u0304","\u011f":"g\u0306","\u01e7":"g\u030c","\u011d":"g\u0302","\u0121":"g\u0307","\u1e27":"h\u0308","\u021f":"h\u030c","\u0125":"h\u0302","\u1e23":"h\u0307","\xed":"i\u0301","\xec":"i\u0300","\xef":"i\u0308","\u1e2f":"i\u0308\u0301","\u0129":"i\u0303","\u012b":"i\u0304","\u012d":"i\u0306","\u01d0":"i\u030c","\xee":"i\u0302","\u01f0":"j\u030c","\u0135":"j\u0302","\u1e31":"k\u0301","\u01e9":"k\u030c","\u013a":"l\u0301","\u013e":"l\u030c","\u1e3f":"m\u0301","\u1e41":"m\u0307","\u0144":"n\u0301","\u01f9":"n\u0300","\xf1":"n\u0303","\u0148":"n\u030c","\u1e45":"n\u0307","\xf3":"o\u0301","\xf2":"o\u0300","\xf6":"o\u0308","\u022b":"o\u0308\u0304","\xf5":"o\u0303","\u1e4d":"o\u0303\u0301","\u1e4f":"o\u0303\u0308","\u022d":"o\u0303\u0304","\u014d":"o\u0304","\u1e53":"o\u0304\u0301","\u1e51":"o\u0304\u0300","\u014f":"o\u0306","\u01d2":"o\u030c","\xf4":"o\u0302","\u1ed1":"o\u0302\u0301","\u1ed3":"o\u0302\u0300","\u1ed7":"o\u0302\u0303","\u022f":"o\u0307","\u0231":"o\u0307\u0304","\u0151":"o\u030b","\u1e55":"p\u0301","\u1e57":"p\u0307","\u0155":"r\u0301","\u0159":"r\u030c","\u1e59":"r\u0307","\u015b":"s\u0301","\u1e65":"s\u0301\u0307","\u0161":"s\u030c","\u1e67":"s\u030c\u0307","\u015d":"s\u0302","\u1e61":"s\u0307","\u1e97":"t\u0308","\u0165":"t\u030c","\u1e6b":"t\u0307","\xfa":"u\u0301","\xf9":"u\u0300","\xfc":"u\u0308","\u01d8":"u\u0308\u0301","\u01dc":"u\u0308\u0300","\u01d6":"u\u0308\u0304","\u01da":"u\u0308\u030c","\u0169":"u\u0303","\u1e79":"u\u0303\u0301","\u016b":"u\u0304","\u1e7b":"u\u0304\u0308","\u016d":"u\u0306","\u01d4":"u\u030c","\xfb":"u\u0302","\u016f":"u\u030a","\u0171":"u\u030b","\u1e7d":"v\u0303","\u1e83":"w\u0301","\u1e81":"w\u0300","\u1e85":"w\u0308","\u0175":"w\u0302","\u1e87":"w\u0307","\u1e98":"w\u030a","\u1e8d":"x\u0308","\u1e8b":"x\u0307","\xfd":"y\u0301","\u1ef3":"y\u0300","\xff":"y\u0308","\u1ef9":"y\u0303","\u0233":"y\u0304","\u0177":"y\u0302","\u1e8f":"y\u0307","\u1e99":"y\u030a","\u017a":"z\u0301","\u017e":"z\u030c","\u1e91":"z\u0302","\u017c":"z\u0307","\xc1":"A\u0301","\xc0":"A\u0300","\xc4":"A\u0308","\u01de":"A\u0308\u0304","\xc3":"A\u0303","\u0100":"A\u0304","\u0102":"A\u0306","\u1eae":"A\u0306\u0301","\u1eb0":"A\u0306\u0300","\u1eb4":"A\u0306\u0303","\u01cd":"A\u030c","\xc2":"A\u0302","\u1ea4":"A\u0302\u0301","\u1ea6":"A\u0302\u0300","\u1eaa":"A\u0302\u0303","\u0226":"A\u0307","\u01e0":"A\u0307\u0304","\xc5":"A\u030a","\u01fa":"A\u030a\u0301","\u1e02":"B\u0307","\u0106":"C\u0301","\u010c":"C\u030c","\u0108":"C\u0302","\u010a":"C\u0307","\u010e":"D\u030c","\u1e0a":"D\u0307","\xc9":"E\u0301","\xc8":"E\u0300","\xcb":"E\u0308","\u1ebc":"E\u0303","\u0112":"E\u0304","\u1e16":"E\u0304\u0301","\u1e14":"E\u0304\u0300","\u0114":"E\u0306","\u011a":"E\u030c","\xca":"E\u0302","\u1ebe":"E\u0302\u0301","\u1ec0":"E\u0302\u0300","\u1ec4":"E\u0302\u0303","\u0116":"E\u0307","\u1e1e":"F\u0307","\u01f4":"G\u0301","\u1e20":"G\u0304","\u011e":"G\u0306","\u01e6":"G\u030c","\u011c":"G\u0302","\u0120":"G\u0307","\u1e26":"H\u0308","\u021e":"H\u030c","\u0124":"H\u0302","\u1e22":"H\u0307","\xcd":"I\u0301","\xcc":"I\u0300","\xcf":"I\u0308","\u1e2e":"I\u0308\u0301","\u0128":"I\u0303","\u012a":"I\u0304","\u012c":"I\u0306","\u01cf":"I\u030c","\xce":"I\u0302","\u0130":"I\u0307","\u0134":"J\u0302","\u1e30":"K\u0301","\u01e8":"K\u030c","\u0139":"L\u0301","\u013d":"L\u030c","\u1e3e":"M\u0301","\u1e40":"M\u0307","\u0143":"N\u0301","\u01f8":"N\u0300","\xd1":"N\u0303","\u0147":"N\u030c","\u1e44":"N\u0307","\xd3":"O\u0301","\xd2":"O\u0300","\xd6":"O\u0308","\u022a":"O\u0308\u0304","\xd5":"O\u0303","\u1e4c":"O\u0303\u0301","\u1e4e":"O\u0303\u0308","\u022c":"O\u0303\u0304","\u014c":"O\u0304","\u1e52":"O\u0304\u0301","\u1e50":"O\u0304\u0300","\u014e":"O\u0306","\u01d1":"O\u030c","\xd4":"O\u0302","\u1ed0":"O\u0302\u0301","\u1ed2":"O\u0302\u0300","\u1ed6":"O\u0302\u0303","\u022e":"O\u0307","\u0230":"O\u0307\u0304","\u0150":"O\u030b","\u1e54":"P\u0301","\u1e56":"P\u0307","\u0154":"R\u0301","\u0158":"R\u030c","\u1e58":"R\u0307","\u015a":"S\u0301","\u1e64":"S\u0301\u0307","\u0160":"S\u030c","\u1e66":"S\u030c\u0307","\u015c":"S\u0302","\u1e60":"S\u0307","\u0164":"T\u030c","\u1e6a":"T\u0307","\xda":"U\u0301","\xd9":"U\u0300","\xdc":"U\u0308","\u01d7":"U\u0308\u0301","\u01db":"U\u0308\u0300","\u01d5":"U\u0308\u0304","\u01d9":"U\u0308\u030c","\u0168":"U\u0303","\u1e78":"U\u0303\u0301","\u016a":"U\u0304","\u1e7a":"U\u0304\u0308","\u016c":"U\u0306","\u01d3":"U\u030c","\xdb":"U\u0302","\u016e":"U\u030a","\u0170":"U\u030b","\u1e7c":"V\u0303","\u1e82":"W\u0301","\u1e80":"W\u0300","\u1e84":"W\u0308","\u0174":"W\u0302","\u1e86":"W\u0307","\u1e8c":"X\u0308","\u1e8a":"X\u0307","\xdd":"Y\u0301","\u1ef2":"Y\u0300","\u0178":"Y\u0308","\u1ef8":"Y\u0303","\u0232":"Y\u0304","\u0176":"Y\u0302","\u1e8e":"Y\u0307","\u0179":"Z\u0301","\u017d":"Z\u030c","\u1e90":"Z\u0302","\u017b":"Z\u0307","\u03ac":"\u03b1\u0301","\u1f70":"\u03b1\u0300","\u1fb1":"\u03b1\u0304","\u1fb0":"\u03b1\u0306","\u03ad":"\u03b5\u0301","\u1f72":"\u03b5\u0300","\u03ae":"\u03b7\u0301","\u1f74":"\u03b7\u0300","\u03af":"\u03b9\u0301","\u1f76":"\u03b9\u0300","\u03ca":"\u03b9\u0308","\u0390":"\u03b9\u0308\u0301","\u1fd2":"\u03b9\u0308\u0300","\u1fd1":"\u03b9\u0304","\u1fd0":"\u03b9\u0306","\u03cc":"\u03bf\u0301","\u1f78":"\u03bf\u0300","\u03cd":"\u03c5\u0301","\u1f7a":"\u03c5\u0300","\u03cb":"\u03c5\u0308","\u03b0":"\u03c5\u0308\u0301","\u1fe2":"\u03c5\u0308\u0300","\u1fe1":"\u03c5\u0304","\u1fe0":"\u03c5\u0306","\u03ce":"\u03c9\u0301","\u1f7c":"\u03c9\u0300","\u038e":"\u03a5\u0301","\u1fea":"\u03a5\u0300","\u03ab":"\u03a5\u0308","\u1fe9":"\u03a5\u0304","\u1fe8":"\u03a5\u0306","\u038f":"\u03a9\u0301","\u1ffa":"\u03a9\u0300"},Wn=function(){function e(e,t){this.mode=void 0,this.gullet=void 0,this.settings=void 0,this.leftrightDepth=void 0,this.nextToken=void 0,this.mode="math",this.gullet=new Gn(e,t,this.mode),this.settings=t,this.leftrightDepth=0}var t=e.prototype;return t.expect=function(e,t){if(void 0===t&&(t=!0),this.fetch().text!==e)throw new n("Expected '"+e+"', got '"+this.fetch().text+"'",this.fetch());t&&this.consume()},t.consume=function(){this.nextToken=null},t.fetch=function(){return null==this.nextToken&&(this.nextToken=this.gullet.expandNextToken()),this.nextToken},t.switchMode=function(e){this.mode=e,this.gullet.switchMode(e)},t.parse=function(){this.settings.globalGroup||this.gullet.beginGroup(),this.settings.colorIsTextColor&&this.gullet.macros.set("\\color","\\textcolor");var e=this.parseExpression(!1);return this.expect("EOF"),this.settings.globalGroup||this.gullet.endGroup(),e},t.parseExpression=function(t,r){for(var n=[];;){"math"===this.mode&&this.consumeSpaces();var a=this.fetch();if(-1!==e.endOfExpression.indexOf(a.text))break;if(r&&a.text===r)break;if(t&&En[a.text]&&En[a.text].infix)break;var i=this.parseAtom(r);if(!i)break;"internal"!==i.type&&n.push(i)}return"text"===this.mode&&this.formLigatures(n),this.handleInfixNodes(n)},t.handleInfixNodes=function(e){for(var t,r=-1,a=0;a=0&&this.settings.reportNonstrict("unicodeTextInMathMode",'Latin-1/Unicode text character "'+t[0]+'" used in math mode',e);var s,l=X[this.mode][t].group,h=Hn.range(e);if(U.hasOwnProperty(l)){var m=l;s={type:"atom",mode:this.mode,family:m,loc:h,text:t}}else s={type:l,mode:this.mode,loc:h,text:t};i=s}else{if(!(t.charCodeAt(0)>=128))return null;this.settings.strict&&(w(t.charCodeAt(0))?"math"===this.mode&&this.settings.reportNonstrict("unicodeTextInMathMode",'Unicode text character "'+t[0]+'" used in math mode',e):this.settings.reportNonstrict("unknownSymbol",'Unrecognized Unicode character "'+t[0]+'" ('+t.charCodeAt(0)+")",e)),i={type:"textord",mode:"text",loc:Hn.range(e),text:t}}if(this.consume(),o)for(var c=0;c 15) { - left = "…" + input.slice(start - 15, start); - } else { - left = input.slice(0, start); - } - let right; - if (end + 15 < input.length) { - right = input.slice(end, end + 15) + "…"; - } else { - right = input.slice(end); - } - error += left + underlined + right; - } - - // Some hackery to make ParseError a prototype of Error - // See http://stackoverflow.com/a/8460753 - const self = new Error(error); - self.name = "ParseError"; - self.__proto__ = ParseError.prototype; - self.position = start; - return self; - } -} - -ParseError.prototype.__proto__ = Error.prototype; - -// -/** - * This file contains a list of utility functions which are useful in other - * files. - */ - -/** - * Return whether an element is contained in a list - */ -const contains = function(list, elem) { - return list.indexOf(elem) !== -1; -}; - -/** - * Provide a default value if a setting is undefined - */ -const deflt = function(setting, defaultIfUndefined) { - return setting === undefined ? defaultIfUndefined : setting; -}; - -// hyphenate and escape adapted from Facebook's React under Apache 2 license - -const uppercase = /([A-Z])/g; -const hyphenate = function(str) { - return str.replace(uppercase, "-$1").toLowerCase(); -}; - -const ESCAPE_LOOKUP = { - "&": "&", - ">": ">", - "<": "<", - '"': """, - "'": "'" -}; - -const ESCAPE_REGEX = /[&><"']/g; - -/** - * Escapes text to prevent scripting attacks. - */ -function escape(text) { - return String(text).replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]); -} - -/** - * Sometimes we want to pull out the innermost element of a group. In most - * cases, this will just be the group itself, but when ordgroups and colors have - * a single element, we want to pull that out. - */ -const getBaseElem = function(group) { - if (group.type === "ordgroup") { - if (group.body.length === 1) { - return getBaseElem(group.body[0]); - } else { - return group; - } - } else if (group.type === "color") { - if (group.body.length === 1) { - return getBaseElem(group.body[0]); - } else { - return group; - } - } else if (group.type === "font") { - return getBaseElem(group.body); - } else { - return group; - } -}; - -/** - * TeXbook algorithms often reference "character boxes", which are simply groups - * with a single character in them. To decide if something is a character box, - * we find its innermost group, and see if it is a single character. - */ -const isCharacterBox = function(group) { - const baseElem = getBaseElem(group); - - // These are all the types of groups which hold single characters - return baseElem.type === "mathord" || baseElem.type === "textord" || baseElem.type === "atom" -}; - -const assert = function(value) { - if (!value) { - throw new Error("Expected non-null, but got " + String(value)); - } - return value; -}; - -/** - * Return the protocol of a URL, or "_relative" if the URL does not specify a - * protocol (and thus is relative). - */ -const protocolFromUrl = function(url) { - const protocol = /^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(url); - return protocol != null ? protocol[1] : "_relative"; -}; - -/** - * Round `n` to 4 decimal places, or to the nearest 1/10,000th em. The TeXbook - * gives an acceptable rounding error of 100sp (which would be the nearest - * 1/6551.6em with our ptPerEm = 10): - * http://www.ctex.org/documents/shredder/src/texbook.pdf#page=69 - */ -const round = function(n) { - return +n.toFixed(4); -}; - -const consolidateText = mrow => { - // If possible, consolidate adjacent elements into a single element. - if (mrow.type !== "mrow") { return mrow } - if (mrow.children.length === 0) { return mrow } // empty group, e.g., \text{} - const mtext = mrow.children[0]; - if (!mtext.attributes || mtext.type !== "mtext") { return mrow } - const variant = mtext.attributes.mathvariant || ""; - for (let i = 1; i < mrow.children.length; i++) { - // Check each child and, if possible, copy the character into child[0]. - const localVariant = mrow.children[i].attributes.mathvariant || ""; - if (mrow.children[i].type === "mrow") { - const childRow = mrow.children[i]; - for (let j = 0; j < childRow.children.length; j++) { - // We'll also check the children of a mrow. One level only. No recursion. - const childVariant = childRow.children[j].attributes.mathvariant || ""; - if (childVariant !== variant || childRow.children[j].type !== "mtext") { - return mrow // At least one element cannot be consolidated. Get out. - } else { - mtext.children[0].text += childRow.children[j].children[0].text; - } - } - } else if (localVariant !== variant || mrow.children[i].type !== "mtext") { - return mrow - } else { - mtext.children[0].text += mrow.children[i].children[0].text; - } - } - // Since we have gotten here, the text has been loaded into a single mtext node. - // Next, consolidate the children into a single element. - mtext.children.splice(1, mtext.children.length - 1); - // Firefox does not render a space at either end of an string. - // To get proper rendering, we replace leading or trailing spaces with no-break spaces. - if (mtext.children[0].text.charAt(0) === " ") { - mtext.children[0].text = "\u00a0" + mtext.children[0].text.slice(1); - } - const L = mtext.children[0].text.length; - if (L > 0 && mtext.children[0].text.charAt(L - 1) === " ") { - mtext.children[0].text = mtext.children[0].text.slice(0, -1) + "\u00a0"; - } - return mtext -}; - -var utils = { - contains, - deflt, - escape, - hyphenate, - getBaseElem, - isCharacterBox, - protocolFromUrl, - round, - consolidateText -}; - -/** - * This is a module for storing settings passed into Temml. It correctly handles - * default settings. - */ - -/** - * The main Settings object - */ -class Settings { - constructor(options) { - // allow null options - options = options || {}; - this.displayMode = utils.deflt(options.displayMode, false); // boolean - this.annotate = utils.deflt(options.annotate, false); // boolean - this.elementIsMath = utils.deflt(options.elementIsMath, false); // boolean - this.leqno = utils.deflt(options.leqno, false); // boolean - this.errorColor = utils.deflt(options.errorColor, "#b22222"); // string - this.preventTagLap = utils.deflt(options.preventTagLap, false); // boolean - this.macros = options.macros || {}; - this.xml = utils.deflt(options.xml, false); // boolean - this.colorIsTextColor = utils.deflt(options.colorIsTextColor, false); // booelean - this.strict = utils.deflt(options.strict, false); // boolean - this.trust = utils.deflt(options.trust, false); // trust context. See html.js. - this.maxSize = (options.maxSize === undefined - ? [Infinity, Infinity] - : Array.isArray(options.maxSize) - ? options.maxSize - : [Infinity, Infinity] - ); - this.maxExpand = Math.max(0, utils.deflt(options.maxExpand, 1000)); // number - } - - /** - * Check whether to test potentially dangerous input, and return - * `true` (trusted) or `false` (untrusted). The sole argument `context` - * should be an object with `command` field specifying the relevant LaTeX - * command (as a string starting with `\`), and any other arguments, etc. - * If `context` has a `url` field, a `protocol` field will automatically - * get added by this function (changing the specified object). - */ - isTrusted(context) { - if (context.url && !context.protocol) { - context.protocol = utils.protocolFromUrl(context.url); - } - const trust = typeof this.trust === "function" ? this.trust(context) : this.trust; - return Boolean(trust); - } -} - -/** - * All registered functions. - * `functions.js` just exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary. - */ -const _functions = {}; - -/** - * All MathML builders. Should be only used in the `define*` and the `build*ML` - * functions. - */ -const _mathmlGroupBuilders = {}; - -function defineFunction({ - type, - names, - props, - handler, - mathmlBuilder -}) { - // Set default values of functions - const data = { - type, - numArgs: props.numArgs, - argTypes: props.argTypes, - allowedInArgument: !!props.allowedInArgument, - allowedInText: !!props.allowedInText, - allowedInMath: props.allowedInMath === undefined ? true : props.allowedInMath, - numOptionalArgs: props.numOptionalArgs || 0, - infix: !!props.infix, - primitive: !!props.primitive, - handler: handler - }; - for (let i = 0; i < names.length; ++i) { - _functions[names[i]] = data; - } - if (type) { - if (mathmlBuilder) { - _mathmlGroupBuilders[type] = mathmlBuilder; - } - } -} - -/** - * Use this to register only the MathML builder for a function(e.g. - * if the function's ParseNode is generated in Parser.js rather than via a - * stand-alone handler provided to `defineFunction`). - */ -function defineFunctionBuilders({ type, mathmlBuilder }) { - defineFunction({ - type, - names: [], - props: { numArgs: 0 }, - handler() { - throw new Error("Should never be called.") - }, - mathmlBuilder - }); -} - -const normalizeArgument = function(arg) { - return arg.type === "ordgroup" && arg.body.length === 1 ? arg.body[0] : arg -}; - -// Since the corresponding buildMathML function expects a -// list of elements, we normalize for different kinds of arguments -const ordargument = function(arg) { - return arg.type === "ordgroup" ? arg.body : [arg] -}; - -/** - * This node represents a document fragment, which contains elements, but when - * placed into the DOM doesn't have any representation itself. It only contains - * children and doesn't have any DOM node properties. - */ -class DocumentFragment { - constructor(children) { - this.children = children; - this.classes = []; - this.style = {}; - } - - hasClass(className) { - return utils.contains(this.classes, className); - } - - /** Convert the fragment into a node. */ - toNode() { - const frag = document.createDocumentFragment(); - - for (let i = 0; i < this.children.length; i++) { - frag.appendChild(this.children[i].toNode()); - } - - return frag; - } - - /** Convert the fragment into HTML markup. */ - toMarkup() { - let markup = ""; - - // Simply concatenate the markup for the children together. - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - return markup; - } - - /** - * Converts the math node into a string, similar to innerText. Applies to - * MathDomNode's only. - */ - toText() { - // To avoid this, we would subclass documentFragment separately for - // MathML, but polyfills for subclassing is expensive per PR 1469. - const toText = (child) => child.toText(); - return this.children.map(toText).join(""); - } -} - -/** - * These objects store the data about the DOM nodes we create, as well as some - * extra data. They can then be transformed into real DOM nodes with the - * `toNode` function or HTML markup using `toMarkup`. They are useful for both - * storing extra properties on the nodes, as well as providing a way to easily - * work with the DOM. - * - * Similar functions for working with MathML nodes exist in mathMLTree.js. - * - */ - -/** - * Create an HTML className based on a list of classes. In addition to joining - * with spaces, we also remove empty classes. - */ -const createClass = function(classes) { - return classes.filter((cls) => cls).join(" "); -}; - -const initNode = function(classes, style) { - this.classes = classes || []; - this.attributes = {}; - this.style = style || {}; -}; - -/** - * Convert into an HTML node - */ -const toNode = function(tagName) { - const node = document.createElement(tagName); - - // Apply the class - node.className = createClass(this.classes); - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - // Apply attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr )) { - node.setAttribute(attr, this.attributes[attr]); - } - } - - // Append the children, also as HTML nodes - for (let i = 0; i < this.children.length; i++) { - node.appendChild(this.children[i].toNode()); - } - - return node; -}; - -/** - * Convert into an HTML markup string - */ -const toMarkup = function(tagName) { - let markup = `<${tagName}`; - - // Add the class - if (this.classes.length) { - markup += ` class="${utils.escape(createClass(this.classes))}"`; - } - - let styles = ""; - - // Add the styles, after hyphenation - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - styles += `${utils.hyphenate(style)}:${this.style[style]};`; - } - } - - if (styles) { - markup += ` style="${styles}"`; - } - - // Add the attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr )) { - markup += ` ${attr}="${utils.escape(this.attributes[attr])}"`; - } - } - - markup += ">"; - - // Add the markup of the children, also as markup - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - markup += ``; - - return markup; -}; - -/** - * This node represents a span node, with a className, a list of children, and - * an inline style. - * - */ -class Span { - constructor(classes, children, style) { - initNode.call(this, classes, style); - this.children = children || []; - } - - setAttribute(attribute, value) { - this.attributes[attribute] = value; - } - - toNode() { - return toNode.call(this, "span"); - } - - toMarkup() { - return toMarkup.call(this, "span"); - } -} - -class TextNode$1 { - constructor(text) { - this.text = text; - } - toNode() { - return document.createTextNode(this.text); - } - toMarkup() { - return utils.escape(this.text); - } -} - -/** - * This node represents an image embed () element. - */ -class Img { - constructor(src, alt, style) { - this.alt = alt; - this.src = src; - this.classes = ["mord"]; - this.style = style; - } - - hasClass(className) { - return utils.contains(this.classes, className); - } - - toNode() { - const node = document.createElement("img"); - node.src = this.src; - node.alt = this.alt; - node.className = "mord"; - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - return node; - } - - toMarkup() { - let markup = `${this.alt}` and - * `` tags). - */ -class MathNode { - constructor(type, children, classes, style) { - this.type = type; - this.attributes = {}; - this.children = children || []; - this.classes = classes || []; - this.style = style || {}; // Used for elements - } - - /** - * Sets an attribute on a MathML node. MathML depends on attributes to convey a - * semantic content, so this is used heavily. - */ - setAttribute(name, value) { - this.attributes[name] = value; - } - - /** - * Gets an attribute on a MathML node. - */ - getAttribute(name) { - return this.attributes[name]; - } - - /** - * Converts the math node into a MathML-namespaced DOM element. - */ - toNode() { - const node = document.createElementNS("http://www.w3.org/1998/Math/MathML", this.type); - - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { - node.setAttribute(attr, this.attributes[attr]); - } - } - - if (this.classes.length > 0) { - node.className = createClass(this.classes); - } - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - for (let i = 0; i < this.children.length; i++) { - node.appendChild(this.children[i].toNode()); - } - - return node; - } - - /** - * Converts the math node into an HTML markup string. - */ - toMarkup() { - let markup = "<" + this.type; - - // Add the attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { - markup += " " + attr + '="'; - markup += utils.escape(this.attributes[attr]); - markup += '"'; - } - } - - if (this.classes.length > 0) { - markup += ` class="${utils.escape(createClass(this.classes))}"`; - } - - let styles = ""; - - // Add the styles, after hyphenation - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - styles += `${utils.hyphenate(style)}:${this.style[style]};`; - } - } - - if (styles) { - markup += ` style="${styles}"`; - } - - markup += ">"; - - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - markup += ""; - - return markup; - } - - /** - * Converts the math node into a string, similar to innerText, but escaped. - */ - toText() { - return this.children.map((child) => child.toText()).join(""); - } -} - -/** - * This node represents a piece of text. - */ -class TextNode { - constructor(text) { - this.text = text; - } - - /** - * Converts the text node into a DOM text node. - */ - toNode() { - return document.createTextNode(this.text); - } - - /** - * Converts the text node into escaped HTML markup - * (representing the text itself). - */ - toMarkup() { - return utils.escape(this.toText()); - } - - /** - * Converts the text node into a string - * (representing the text iteself). - */ - toText() { - return this.text; - } -} - -// Do not make an the only child of a . -// An acts as its own implicit . -const wrapWithMstyle = expression => { - let node; - if (expression.length === 1 && expression[0].type === "mrow") { - node = expression.pop(); - node.type = "mstyle"; - } else { - node = new MathNode("mstyle", expression); - } - return node -}; - -var mathMLTree = { - MathNode, - TextNode, - newDocumentFragment -}; - -/** - * This file provides support for building horizontal stretchy elements. - */ - -const stretchyCodePoint = { - widehat: "^", - widecheck: "ˇ", - widetilde: "~", - wideparen: "⏜", // \u23dc - utilde: "~", - overleftarrow: "\u2190", - underleftarrow: "\u2190", - xleftarrow: "\u2190", - overrightarrow: "\u2192", - underrightarrow: "\u2192", - xrightarrow: "\u2192", - underbrace: "\u23df", - overbrace: "\u23de", - overgroup: "\u23e0", - overparen: "⏜", - undergroup: "\u23e1", - underparen: "\u23dd", - overleftrightarrow: "\u2194", - underleftrightarrow: "\u2194", - xleftrightarrow: "\u2194", - Overrightarrow: "\u21d2", - xRightarrow: "\u21d2", - overleftharpoon: "\u21bc", - xleftharpoonup: "\u21bc", - overrightharpoon: "\u21c0", - xrightharpoonup: "\u21c0", - xLeftarrow: "\u21d0", - xLeftrightarrow: "\u21d4", - xhookleftarrow: "\u21a9", - xhookrightarrow: "\u21aa", - xmapsto: "\u21a6", - xrightharpoondown: "\u21c1", - xleftharpoondown: "\u21bd", - xtwoheadleftarrow: "\u219e", - xtwoheadrightarrow: "\u21a0", - xlongequal: "=", - xrightleftarrows: "\u21c4", - yields: "\u2192", - yieldsLeft: "\u2190", - mesomerism: "\u2194", - longrightharpoonup: "\u21c0", - longleftharpoondown: "\u21bd", - eqrightharpoonup: "\u21c0", - eqleftharpoondown: "\u21bd", - "\\cdrightarrow": "\u2192", - "\\cdleftarrow": "\u2190", - "\\cdlongequal": "=" -}; - -const mathMLnode = function(label) { - const child = new mathMLTree.TextNode(stretchyCodePoint[label.slice(1)]); - const node = new mathMLTree.MathNode("mo", [child]); - node.setAttribute("stretchy", "true"); - return node -}; - -var stretchy = { - mathMLnode -}; - -/** - * This file holds a list of all no-argument functions and single-character - * symbols (like 'a' or ';'). - * - * For each of the symbols, there are two properties they can have: - * - group (required): the ParseNode group type the symbol should have (i.e. - "textord", "mathord", etc). - * - replace: the character that this symbol or function should be - * replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi - * character in the main font). - * - * The outermost map in the table indicates what mode the symbols should be - * accepted in (e.g. "math" or "text"). - */ - -// Some of these have a "-token" suffix since these are also used as `ParseNode` -// types for raw text tokens, and we want to avoid conflicts with higher-level -// `ParseNode` types. These `ParseNode`s are constructed within `Parser` by -// looking up the `symbols` map. -const ATOMS = { - bin: 1, - close: 1, - inner: 1, - open: 1, - punct: 1, - rel: 1 -}; -const NON_ATOMS = { - "accent-token": 1, - mathord: 1, - "op-token": 1, - spacing: 1, - textord: 1 -}; - -const symbols = { - math: {}, - text: {} -}; - -/** `acceptUnicodeChar = true` is only applicable if `replace` is set. */ -function defineSymbol(mode, group, replace, name, acceptUnicodeChar) { - symbols[mode][name] = { group, replace }; - - if (acceptUnicodeChar && replace) { - symbols[mode][replace] = symbols[mode][name]; - } -} - -// Some abbreviations for commonly used strings. -// This helps minify the code, and also spotting typos using jshint. - -// modes: -const math = "math"; -const text = "text"; - -// groups: -const accent = "accent-token"; -const bin = "bin"; -const close = "close"; -const inner = "inner"; -const mathord = "mathord"; -const op = "op-token"; -const open = "open"; -const punct = "punct"; -const rel = "rel"; -const spacing = "spacing"; -const textord = "textord"; - -// Now comes the symbol table - -// Relation Symbols -defineSymbol(math, rel, "\u2261", "\\equiv", true); -defineSymbol(math, rel, "\u227a", "\\prec", true); -defineSymbol(math, rel, "\u227b", "\\succ", true); -defineSymbol(math, rel, "\u223c", "\\sim", true); -defineSymbol(math, rel, "\u27c2", "\\perp", true); -defineSymbol(math, rel, "\u2aaf", "\\preceq", true); -defineSymbol(math, rel, "\u2ab0", "\\succeq", true); -defineSymbol(math, rel, "\u2243", "\\simeq", true); -defineSymbol(math, rel, "\u224c", "\\backcong", true); -defineSymbol(math, rel, "|", "\\mid", true); -defineSymbol(math, rel, "\u226a", "\\ll", true); -defineSymbol(math, rel, "\u226b", "\\gg", true); -defineSymbol(math, rel, "\u224d", "\\asymp", true); -defineSymbol(math, rel, "\u2225", "\\parallel"); -defineSymbol(math, rel, "\u22c8", "\\bowtie", true); -defineSymbol(math, rel, "\u2323", "\\smile", true); -defineSymbol(math, rel, "\u2291", "\\sqsubseteq", true); -defineSymbol(math, rel, "\u2292", "\\sqsupseteq", true); -defineSymbol(math, rel, "\u2250", "\\doteq", true); -defineSymbol(math, rel, "\u2322", "\\frown", true); -defineSymbol(math, rel, "\u220b", "\\ni", true); -defineSymbol(math, rel, "\u220c", "\\notni", true); -defineSymbol(math, rel, "\u221d", "\\propto", true); -defineSymbol(math, rel, "\u22a2", "\\vdash", true); -defineSymbol(math, rel, "\u22a3", "\\dashv", true); -defineSymbol(math, rel, "\u220b", "\\owns"); -defineSymbol(math, rel, "\u2258", "\\arceq", true); -defineSymbol(math, rel, "\u2259", "\\wedgeq", true); -defineSymbol(math, rel, "\u225a", "\\veeeq", true); -defineSymbol(math, rel, "\u225b", "\\stareq", true); -defineSymbol(math, rel, "\u225d", "\\eqdef", true); -defineSymbol(math, rel, "\u225e", "\\measeq", true); -defineSymbol(math, rel, "\u225f", "\\questeq", true); -defineSymbol(math, rel, "\u2260", "\\ne", true); -defineSymbol(math, rel, "\u2260", "\\neq"); -// mathtools.sty -defineSymbol(math, rel, "\u2237", "\\dblcolon", true); -defineSymbol(math, rel, "\u2254", "\\coloneqq", true); -defineSymbol(math, rel, "\u2255", "\\eqqcolon", true); -defineSymbol(math, rel, "\u2239", "\\eqcolon", true); -defineSymbol(math, rel, "\u2A74", "\\Coloneqq", true); - -// Punctuation -defineSymbol(math, punct, "\u002e", "\\ldotp"); -defineSymbol(math, punct, "\u00b7", "\\cdotp"); - -// Misc Symbols -defineSymbol(math, textord, "\u0023", "\\#"); -defineSymbol(text, textord, "\u0023", "\\#"); -defineSymbol(math, textord, "\u0026", "\\&"); -defineSymbol(text, textord, "\u0026", "\\&"); -defineSymbol(math, textord, "\u2135", "\\aleph", true); -defineSymbol(math, textord, "\u2200", "\\forall", true); -defineSymbol(math, textord, "\u210f", "\\hbar", true); -defineSymbol(math, textord, "\u2203", "\\exists", true); -defineSymbol(math, textord, "\u2207", "\\nabla", true); -defineSymbol(math, textord, "\u266d", "\\flat", true); -defineSymbol(math, textord, "\u2113", "\\ell", true); -defineSymbol(math, textord, "\u266e", "\\natural", true); -defineSymbol(math, textord, "Å", "\\AA", true); -defineSymbol(text, textord, "Å", "\\AA", true); -defineSymbol(math, textord, "\u2663", "\\clubsuit", true); -defineSymbol(math, textord, "\u2667", "\\varclubsuit", true); -defineSymbol(math, textord, "\u2118", "\\wp", true); -defineSymbol(math, textord, "\u266f", "\\sharp", true); -defineSymbol(math, textord, "\u2662", "\\diamondsuit", true); -defineSymbol(math, textord, "\u2666", "\\vardiamondsuit", true); -defineSymbol(math, textord, "\u211c", "\\Re", true); -defineSymbol(math, textord, "\u2661", "\\heartsuit", true); -defineSymbol(math, textord, "\u2665", "\\varheartsuit", true); -defineSymbol(math, textord, "\u2111", "\\Im", true); -defineSymbol(math, textord, "\u2660", "\\spadesuit", true); -defineSymbol(math, textord, "\u2664", "\\varspadesuit", true); -defineSymbol(math, textord, "\u2640", "\\female", true); -defineSymbol(math, textord, "\u2642", "\\male", true); -defineSymbol(math, textord, "\u00a7", "\\S", true); -defineSymbol(text, textord, "\u00a7", "\\S"); -defineSymbol(math, textord, "\u00b6", "\\P", true); -defineSymbol(text, textord, "\u00b6", "\\P"); -defineSymbol(text, textord, "\u263a", "\\smiley", true); -defineSymbol(math, textord, "\u263a", "\\smiley", true); - -// Math and Text -defineSymbol(math, textord, "\u2020", "\\dag"); -defineSymbol(text, textord, "\u2020", "\\dag"); -defineSymbol(text, textord, "\u2020", "\\textdagger"); -defineSymbol(math, textord, "\u2021", "\\ddag"); -defineSymbol(text, textord, "\u2021", "\\ddag"); -defineSymbol(text, textord, "\u2021", "\\textdaggerdbl"); - -// Large Delimiters -defineSymbol(math, close, "\u23b1", "\\rmoustache", true); -defineSymbol(math, open, "\u23b0", "\\lmoustache", true); -defineSymbol(math, close, "\u27ef", "\\rgroup", true); -defineSymbol(math, open, "\u27ee", "\\lgroup", true); - -// Binary Operators -defineSymbol(math, bin, "\u2213", "\\mp", true); -defineSymbol(math, bin, "\u2296", "\\ominus", true); -defineSymbol(math, bin, "\u228e", "\\uplus", true); -defineSymbol(math, bin, "\u2293", "\\sqcap", true); -defineSymbol(math, bin, "\u2217", "\\ast"); -defineSymbol(math, bin, "\u2294", "\\sqcup", true); -defineSymbol(math, bin, "\u25ef", "\\bigcirc", true); -defineSymbol(math, bin, "\u2219", "\\bullet", true); -defineSymbol(math, bin, "\u2021", "\\ddagger"); -defineSymbol(math, bin, "\u2240", "\\wr", true); -defineSymbol(math, bin, "\u2a3f", "\\amalg"); -defineSymbol(math, bin, "\u0026", "\\And"); // from amsmath - -// Arrow Symbols -defineSymbol(math, rel, "\u27f5", "\\longleftarrow", true); -defineSymbol(math, rel, "\u21d0", "\\Leftarrow", true); -defineSymbol(math, rel, "\u27f8", "\\Longleftarrow", true); -defineSymbol(math, rel, "\u27f6", "\\longrightarrow", true); -defineSymbol(math, rel, "\u21d2", "\\Rightarrow", true); -defineSymbol(math, rel, "\u27f9", "\\Longrightarrow", true); -defineSymbol(math, rel, "\u2194", "\\leftrightarrow", true); -defineSymbol(math, rel, "\u27f7", "\\longleftrightarrow", true); -defineSymbol(math, rel, "\u21d4", "\\Leftrightarrow", true); -defineSymbol(math, rel, "\u27fa", "\\Longleftrightarrow", true); -defineSymbol(math, rel, "\u21a6", "\\mapsto", true); -defineSymbol(math, rel, "\u27fc", "\\longmapsto", true); -defineSymbol(math, rel, "\u2197", "\\nearrow", true); -defineSymbol(math, rel, "\u21a9", "\\hookleftarrow", true); -defineSymbol(math, rel, "\u21aa", "\\hookrightarrow", true); -defineSymbol(math, rel, "\u2198", "\\searrow", true); -defineSymbol(math, rel, "\u21bc", "\\leftharpoonup", true); -defineSymbol(math, rel, "\u21c0", "\\rightharpoonup", true); -defineSymbol(math, rel, "\u2199", "\\swarrow", true); -defineSymbol(math, rel, "\u21bd", "\\leftharpoondown", true); -defineSymbol(math, rel, "\u21c1", "\\rightharpoondown", true); -defineSymbol(math, rel, "\u2196", "\\nwarrow", true); -defineSymbol(math, rel, "\u21cc", "\\rightleftharpoons", true); -defineSymbol(math, mathord, "\u21af", "\\lightning", true); -defineSymbol(math, mathord, "\u2030", "\\permil", true); -defineSymbol(text, textord, "\u2030", "\\permil"); - -// AMS Negated Binary Relations -defineSymbol(math, rel, "\u226e", "\\nless", true); -// Symbol names preceeded by "@" each have a corresponding macro. -defineSymbol(math, rel, "\u2a87", "\\lneq", true); -defineSymbol(math, rel, "\u2268", "\\lneqq", true); -defineSymbol(math, rel, "\u2268\ufe00", "\\lvertneqq"); -defineSymbol(math, rel, "\u22e6", "\\lnsim", true); -defineSymbol(math, rel, "\u2a89", "\\lnapprox", true); -defineSymbol(math, rel, "\u2280", "\\nprec", true); -// unicode-math maps \u22e0 to \npreccurlyeq. We'll use the AMS synonym. -defineSymbol(math, rel, "\u22e0", "\\npreceq", true); -defineSymbol(math, rel, "\u22e8", "\\precnsim", true); -defineSymbol(math, rel, "\u2ab9", "\\precnapprox", true); -defineSymbol(math, rel, "\u2241", "\\nsim", true); -defineSymbol(math, rel, "\u2224", "\\nmid", true); -defineSymbol(math, rel, "\u2224", "\\nshortmid"); -defineSymbol(math, rel, "\u22ac", "\\nvdash", true); -defineSymbol(math, rel, "\u22ad", "\\nvDash", true); -defineSymbol(math, rel, "\u22ea", "\\ntriangleleft"); -defineSymbol(math, rel, "\u22ec", "\\ntrianglelefteq", true); -defineSymbol(math, rel, "\u2284", "\\nsubset", true); -defineSymbol(math, rel, "\u2285", "\\nsupset", true); -defineSymbol(math, rel, "\u228a", "\\subsetneq", true); -defineSymbol(math, rel, "\u228a\ufe00", "\\varsubsetneq"); -defineSymbol(math, rel, "\u2acb", "\\subsetneqq", true); -defineSymbol(math, rel, "\u2acb\ufe00", "\\varsubsetneqq"); -defineSymbol(math, rel, "\u226f", "\\ngtr", true); -defineSymbol(math, rel, "\u2a88", "\\gneq", true); -defineSymbol(math, rel, "\u2269", "\\gneqq", true); -defineSymbol(math, rel, "\u2269\ufe00", "\\gvertneqq"); -defineSymbol(math, rel, "\u22e7", "\\gnsim", true); -defineSymbol(math, rel, "\u2a8a", "\\gnapprox", true); -defineSymbol(math, rel, "\u2281", "\\nsucc", true); -// unicode-math maps \u22e1 to \nsucccurlyeq. We'll use the AMS synonym. -defineSymbol(math, rel, "\u22e1", "\\nsucceq", true); -defineSymbol(math, rel, "\u22e9", "\\succnsim", true); -defineSymbol(math, rel, "\u2aba", "\\succnapprox", true); -// unicode-math maps \u2246 to \simneqq. We'll use the AMS synonym. -defineSymbol(math, rel, "\u2246", "\\ncong", true); -defineSymbol(math, rel, "\u2226", "\\nparallel", true); -defineSymbol(math, rel, "\u2226", "\\nshortparallel"); -defineSymbol(math, rel, "\u22af", "\\nVDash", true); -defineSymbol(math, rel, "\u22eb", "\\ntriangleright"); -defineSymbol(math, rel, "\u22ed", "\\ntrianglerighteq", true); -defineSymbol(math, rel, "\u228b", "\\supsetneq", true); -defineSymbol(math, rel, "\u228b", "\\varsupsetneq"); -defineSymbol(math, rel, "\u2acc", "\\supsetneqq", true); -defineSymbol(math, rel, "\u2acc\ufe00", "\\varsupsetneqq"); -defineSymbol(math, rel, "\u22ae", "\\nVdash", true); -defineSymbol(math, rel, "\u2ab5", "\\precneqq", true); -defineSymbol(math, rel, "\u2ab6", "\\succneqq", true); -defineSymbol(math, bin, "\u22b4", "\\unlhd"); -defineSymbol(math, bin, "\u22b5", "\\unrhd"); - -// AMS Negated Arrows -defineSymbol(math, rel, "\u219a", "\\nleftarrow", true); -defineSymbol(math, rel, "\u219b", "\\nrightarrow", true); -defineSymbol(math, rel, "\u21cd", "\\nLeftarrow", true); -defineSymbol(math, rel, "\u21cf", "\\nRightarrow", true); -defineSymbol(math, rel, "\u21ae", "\\nleftrightarrow", true); -defineSymbol(math, rel, "\u21ce", "\\nLeftrightarrow", true); - -// AMS Misc -defineSymbol(math, rel, "\u25b3", "\\vartriangle"); -defineSymbol(math, textord, "\u210f", "\\hslash"); -defineSymbol(math, textord, "\u25bd", "\\triangledown"); -defineSymbol(math, textord, "\u25ca", "\\lozenge"); -defineSymbol(math, textord, "\u24c8", "\\circledS"); -defineSymbol(math, textord, "\u00ae", "\\circledR", true); -defineSymbol(text, textord, "\u00ae", "\\circledR"); -defineSymbol(text, textord, "\u00ae", "\\textregistered"); -defineSymbol(math, textord, "\u2221", "\\measuredangle", true); -defineSymbol(math, textord, "\u2204", "\\nexists"); -defineSymbol(math, textord, "\u2127", "\\mho"); -defineSymbol(math, textord, "\u2132", "\\Finv", true); -defineSymbol(math, textord, "\u2141", "\\Game", true); -defineSymbol(math, textord, "\u2035", "\\backprime"); -defineSymbol(math, textord, "\u25b2", "\\blacktriangle"); -defineSymbol(math, textord, "\u25bc", "\\blacktriangledown"); -defineSymbol(math, textord, "\u25a0", "\\blacksquare"); -defineSymbol(math, textord, "\u29eb", "\\blacklozenge"); -defineSymbol(math, textord, "\u2605", "\\bigstar"); -defineSymbol(math, textord, "\u2222", "\\sphericalangle", true); -defineSymbol(math, textord, "\u2201", "\\complement", true); -// unicode-math maps U+F0 to \matheth. We map to AMS function \eth -defineSymbol(math, textord, "\u00f0", "\\eth", true); -defineSymbol(text, textord, "\u00f0", "\u00f0"); -defineSymbol(math, textord, "\u2571", "\\diagup"); -defineSymbol(math, textord, "\u2572", "\\diagdown"); -defineSymbol(math, textord, "\u25a1", "\\square"); -defineSymbol(math, textord, "\u25a1", "\\Box"); -defineSymbol(math, textord, "\u25ca", "\\Diamond"); -// unicode-math maps U+A5 to \mathyen. We map to AMS function \yen -defineSymbol(math, textord, "\u00a5", "\\yen", true); -defineSymbol(text, textord, "\u00a5", "\\yen", true); -defineSymbol(math, textord, "\u2713", "\\checkmark", true); -defineSymbol(text, textord, "\u2713", "\\checkmark"); -defineSymbol(math, textord, "\u2717", "\\ballotx", true); -defineSymbol(text, textord, "\u2717", "\\ballotx"); -defineSymbol(text, textord, "\u2022", "\\textbullet"); - -// AMS Hebrew -defineSymbol(math, textord, "\u2136", "\\beth", true); -defineSymbol(math, textord, "\u2138", "\\daleth", true); -defineSymbol(math, textord, "\u2137", "\\gimel", true); - -// AMS Greek -defineSymbol(math, textord, "\u03dd", "\\digamma", true); -defineSymbol(math, textord, "\u03f0", "\\varkappa"); - -// AMS Delimiters -defineSymbol(math, open, "\u231C", "\\ulcorner", true); -defineSymbol(math, close, "\u231D", "\\urcorner", true); -defineSymbol(math, open, "\u231E", "\\llcorner", true); -defineSymbol(math, close, "\u231F", "\\lrcorner", true); - -// AMS Binary Relations -defineSymbol(math, rel, "\u2266", "\\leqq", true); -defineSymbol(math, rel, "\u2a7d", "\\leqslant", true); -defineSymbol(math, rel, "\u2a95", "\\eqslantless", true); -defineSymbol(math, rel, "\u2272", "\\lesssim", true); -defineSymbol(math, rel, "\u2a85", "\\lessapprox", true); -defineSymbol(math, rel, "\u224a", "\\approxeq", true); -defineSymbol(math, bin, "\u22d6", "\\lessdot"); -defineSymbol(math, rel, "\u22d8", "\\lll", true); -defineSymbol(math, rel, "\u2276", "\\lessgtr", true); -defineSymbol(math, rel, "\u22da", "\\lesseqgtr", true); -defineSymbol(math, rel, "\u2a8b", "\\lesseqqgtr", true); -defineSymbol(math, rel, "\u2251", "\\doteqdot"); -defineSymbol(math, rel, "\u2253", "\\risingdotseq", true); -defineSymbol(math, rel, "\u2252", "\\fallingdotseq", true); -defineSymbol(math, rel, "\u223d", "\\backsim", true); -defineSymbol(math, rel, "\u22cd", "\\backsimeq", true); -defineSymbol(math, rel, "\u2ac5", "\\subseteqq", true); -defineSymbol(math, rel, "\u22d0", "\\Subset", true); -defineSymbol(math, rel, "\u228f", "\\sqsubset", true); -defineSymbol(math, rel, "\u227c", "\\preccurlyeq", true); -defineSymbol(math, rel, "\u22de", "\\curlyeqprec", true); -defineSymbol(math, rel, "\u227e", "\\precsim", true); -defineSymbol(math, rel, "\u2ab7", "\\precapprox", true); -defineSymbol(math, rel, "\u22b2", "\\vartriangleleft"); -defineSymbol(math, rel, "\u22b4", "\\trianglelefteq"); -defineSymbol(math, rel, "\u22a8", "\\vDash", true); -defineSymbol(math, rel, "\u22aa", "\\Vvdash", true); -defineSymbol(math, rel, "\u2323", "\\smallsmile"); -defineSymbol(math, rel, "\u2322", "\\smallfrown"); -defineSymbol(math, rel, "\u224f", "\\bumpeq", true); -defineSymbol(math, rel, "\u224e", "\\Bumpeq", true); -defineSymbol(math, rel, "\u2267", "\\geqq", true); -defineSymbol(math, rel, "\u2a7e", "\\geqslant", true); -defineSymbol(math, rel, "\u2a96", "\\eqslantgtr", true); -defineSymbol(math, rel, "\u2273", "\\gtrsim", true); -defineSymbol(math, rel, "\u2a86", "\\gtrapprox", true); -defineSymbol(math, bin, "\u22d7", "\\gtrdot"); -defineSymbol(math, rel, "\u22d9", "\\ggg", true); -defineSymbol(math, rel, "\u2277", "\\gtrless", true); -defineSymbol(math, rel, "\u22db", "\\gtreqless", true); -defineSymbol(math, rel, "\u2a8c", "\\gtreqqless", true); -defineSymbol(math, rel, "\u2256", "\\eqcirc", true); -defineSymbol(math, rel, "\u2257", "\\circeq", true); -defineSymbol(math, rel, "\u225c", "\\triangleq", true); -defineSymbol(math, rel, "\u223c", "\\thicksim"); -defineSymbol(math, rel, "\u2248", "\\thickapprox"); -defineSymbol(math, rel, "\u2ac6", "\\supseteqq", true); -defineSymbol(math, rel, "\u22d1", "\\Supset", true); -defineSymbol(math, rel, "\u2290", "\\sqsupset", true); -defineSymbol(math, rel, "\u227d", "\\succcurlyeq", true); -defineSymbol(math, rel, "\u22df", "\\curlyeqsucc", true); -defineSymbol(math, rel, "\u227f", "\\succsim", true); -defineSymbol(math, rel, "\u2ab8", "\\succapprox", true); -defineSymbol(math, rel, "\u22b3", "\\vartriangleright"); -defineSymbol(math, rel, "\u22b5", "\\trianglerighteq"); -defineSymbol(math, rel, "\u22a9", "\\Vdash", true); -defineSymbol(math, rel, "\u2223", "\\shortmid"); -defineSymbol(math, rel, "\u2225", "\\shortparallel"); -defineSymbol(math, rel, "\u226c", "\\between", true); -defineSymbol(math, rel, "\u22d4", "\\pitchfork", true); -defineSymbol(math, rel, "\u221d", "\\varpropto"); -defineSymbol(math, rel, "\u25c0", "\\blacktriangleleft"); -// unicode-math says that \therefore is a mathord atom. -// We kept the amssymb atom type, which is rel. -defineSymbol(math, rel, "\u2234", "\\therefore", true); -defineSymbol(math, rel, "\u220d", "\\backepsilon"); -defineSymbol(math, rel, "\u25b6", "\\blacktriangleright"); -// unicode-math says that \because is a mathord atom. -// We kept the amssymb atom type, which is rel. -defineSymbol(math, rel, "\u2235", "\\because", true); -defineSymbol(math, rel, "\u22d8", "\\llless"); -defineSymbol(math, rel, "\u22d9", "\\gggtr"); -defineSymbol(math, bin, "\u22b2", "\\lhd"); -defineSymbol(math, bin, "\u22b3", "\\rhd"); -defineSymbol(math, rel, "\u2242", "\\eqsim", true); -defineSymbol(math, rel, "\u22c8", "\\Join"); -defineSymbol(math, rel, "\u2251", "\\Doteq", true); -defineSymbol(math, rel, "\u297d", "\\strictif", true); -defineSymbol(math, rel, "\u297c", "\\strictfi", true); - -// AMS Binary Operators -defineSymbol(math, bin, "\u2214", "\\dotplus", true); -defineSymbol(math, bin, "\u2216", "\\smallsetminus"); -defineSymbol(math, bin, "\u22d2", "\\Cap", true); -defineSymbol(math, bin, "\u22d3", "\\Cup", true); -defineSymbol(math, bin, "\u2a5e", "\\doublebarwedge", true); -defineSymbol(math, bin, "\u229f", "\\boxminus", true); -defineSymbol(math, bin, "\u229e", "\\boxplus", true); -defineSymbol(math, bin, "\u22c7", "\\divideontimes", true); -defineSymbol(math, bin, "\u22c9", "\\ltimes", true); -defineSymbol(math, bin, "\u22ca", "\\rtimes", true); -defineSymbol(math, bin, "\u22cb", "\\leftthreetimes", true); -defineSymbol(math, bin, "\u22cc", "\\rightthreetimes", true); -defineSymbol(math, bin, "\u22cf", "\\curlywedge", true); -defineSymbol(math, bin, "\u22ce", "\\curlyvee", true); -defineSymbol(math, bin, "\u229d", "\\circleddash", true); -defineSymbol(math, bin, "\u229b", "\\circledast", true); -defineSymbol(math, bin, "\u22ba", "\\intercal", true); -defineSymbol(math, bin, "\u22d2", "\\doublecap"); -defineSymbol(math, bin, "\u22d3", "\\doublecup"); -defineSymbol(math, bin, "\u22a0", "\\boxtimes", true); - -// AMS Arrows -// Note: unicode-math maps \u21e2 to their own function \rightdasharrow. -// We'll map it to AMS function \dashrightarrow. It produces the same atom. -defineSymbol(math, rel, "\u21e2", "\\dashrightarrow", true); -// unicode-math maps \u21e0 to \leftdasharrow. We'll use the AMS synonym. -defineSymbol(math, rel, "\u21e0", "\\dashleftarrow", true); -defineSymbol(math, rel, "\u21c7", "\\leftleftarrows", true); -defineSymbol(math, rel, "\u21c6", "\\leftrightarrows", true); -defineSymbol(math, rel, "\u21da", "\\Lleftarrow", true); -defineSymbol(math, rel, "\u219e", "\\twoheadleftarrow", true); -defineSymbol(math, rel, "\u21a2", "\\leftarrowtail", true); -defineSymbol(math, rel, "\u21ab", "\\looparrowleft", true); -defineSymbol(math, rel, "\u21cb", "\\leftrightharpoons", true); -defineSymbol(math, rel, "\u21b6", "\\curvearrowleft", true); -// unicode-math maps \u21ba to \acwopencirclearrow. We'll use the AMS synonym. -defineSymbol(math, rel, "\u21ba", "\\circlearrowleft", true); -defineSymbol(math, rel, "\u21b0", "\\Lsh", true); -defineSymbol(math, rel, "\u21c8", "\\upuparrows", true); -defineSymbol(math, rel, "\u21bf", "\\upharpoonleft", true); -defineSymbol(math, rel, "\u21c3", "\\downharpoonleft", true); -defineSymbol(math, rel, "\u22b6", "\\origof", true); -defineSymbol(math, rel, "\u22b7", "\\imageof", true); -defineSymbol(math, rel, "\u22b8", "\\multimap", true); -defineSymbol(math, rel, "\u21ad", "\\leftrightsquigarrow", true); -defineSymbol(math, rel, "\u21c9", "\\rightrightarrows", true); -defineSymbol(math, rel, "\u21c4", "\\rightleftarrows", true); -defineSymbol(math, rel, "\u21a0", "\\twoheadrightarrow", true); -defineSymbol(math, rel, "\u21a3", "\\rightarrowtail", true); -defineSymbol(math, rel, "\u21ac", "\\looparrowright", true); -defineSymbol(math, rel, "\u21b7", "\\curvearrowright", true); -// unicode-math maps \u21bb to \cwopencirclearrow. We'll use the AMS synonym. -defineSymbol(math, rel, "\u21bb", "\\circlearrowright", true); -defineSymbol(math, rel, "\u21b1", "\\Rsh", true); -defineSymbol(math, rel, "\u21ca", "\\downdownarrows", true); -defineSymbol(math, rel, "\u21be", "\\upharpoonright", true); -defineSymbol(math, rel, "\u21c2", "\\downharpoonright", true); -defineSymbol(math, rel, "\u21dd", "\\rightsquigarrow", true); -defineSymbol(math, rel, "\u21dd", "\\leadsto"); -defineSymbol(math, rel, "\u21db", "\\Rrightarrow", true); -defineSymbol(math, rel, "\u21be", "\\restriction"); - -defineSymbol(math, textord, "\u2018", "`"); -defineSymbol(math, textord, "$", "\\$"); -defineSymbol(text, textord, "$", "\\$"); -defineSymbol(text, textord, "$", "\\textdollar"); -defineSymbol(math, textord, "%", "\\%"); -defineSymbol(text, textord, "%", "\\%"); -defineSymbol(math, textord, "_", "\\_"); -defineSymbol(text, textord, "_", "\\_"); -defineSymbol(text, textord, "_", "\\textunderscore"); -defineSymbol(text, textord, "\u2423", "\\textvisiblespace", true); -defineSymbol(math, textord, "\u2220", "\\angle", true); -defineSymbol(math, textord, "\u221e", "\\infty", true); -defineSymbol(math, textord, "\u2032", "\\prime"); -defineSymbol(math, textord, "\u25b3", "\\triangle"); -defineSymbol(text, textord, "\u0391", "\\Alpha", true); -defineSymbol(text, textord, "\u0392", "\\Beta", true); -defineSymbol(text, textord, "\u0393", "\\Gamma", true); -defineSymbol(text, textord, "\u0394", "\\Delta", true); -defineSymbol(text, textord, "\u0395", "\\Epsilon", true); -defineSymbol(text, textord, "\u0396", "\\Zeta", true); -defineSymbol(text, textord, "\u0397", "\\Eta", true); -defineSymbol(text, textord, "\u0398", "\\Theta", true); -defineSymbol(text, textord, "\u0399", "\\Iota", true); -defineSymbol(text, textord, "\u039a", "\\Kappa", true); -defineSymbol(text, textord, "\u039b", "\\Lambda", true); -defineSymbol(text, textord, "\u039c", "\\Mu", true); -defineSymbol(text, textord, "\u039d", "\\Nu", true); -defineSymbol(text, textord, "\u039e", "\\Xi", true); -defineSymbol(text, textord, "\u039f", "\\Omicron", true); -defineSymbol(text, textord, "\u03a0", "\\Pi", true); -defineSymbol(text, textord, "\u03a1", "\\Rho", true); -defineSymbol(text, textord, "\u03a3", "\\Sigma", true); -defineSymbol(text, textord, "\u03a4", "\\Tau", true); -defineSymbol(text, textord, "\u03a5", "\\Upsilon", true); -defineSymbol(text, textord, "\u03a6", "\\Phi", true); -defineSymbol(text, textord, "\u03a7", "\\Chi", true); -defineSymbol(text, textord, "\u03a8", "\\Psi", true); -defineSymbol(text, textord, "\u03a9", "\\Omega", true); -defineSymbol(math, mathord, "\u0391", "\\Alpha", true); -defineSymbol(math, mathord, "\u0392", "\\Beta", true); -defineSymbol(math, mathord, "\u0393", "\\Gamma", true); -defineSymbol(math, mathord, "\u0394", "\\Delta", true); -defineSymbol(math, mathord, "\u0395", "\\Epsilon", true); -defineSymbol(math, mathord, "\u0396", "\\Zeta", true); -defineSymbol(math, mathord, "\u0397", "\\Eta", true); -defineSymbol(math, mathord, "\u0398", "\\Theta", true); -defineSymbol(math, mathord, "\u0399", "\\Iota", true); -defineSymbol(math, mathord, "\u039a", "\\Kappa", true); -defineSymbol(math, mathord, "\u039b", "\\Lambda", true); -defineSymbol(math, mathord, "\u039c", "\\Mu", true); -defineSymbol(math, mathord, "\u039d", "\\Nu", true); -defineSymbol(math, mathord, "\u039e", "\\Xi", true); -defineSymbol(math, mathord, "\u039f", "\\Omicron", true); -defineSymbol(math, mathord, "\u03a0", "\\Pi", true); -defineSymbol(math, mathord, "\u03a1", "\\Rho", true); -defineSymbol(math, mathord, "\u03a3", "\\Sigma", true); -defineSymbol(math, mathord, "\u03a4", "\\Tau", true); -defineSymbol(math, mathord, "\u03a5", "\\Upsilon", true); -defineSymbol(math, mathord, "\u03a6", "\\Phi", true); -defineSymbol(math, mathord, "\u03a7", "\\Chi", true); -defineSymbol(math, mathord, "\u03a8", "\\Psi", true); -defineSymbol(math, mathord, "\u03a9", "\\Omega", true); -defineSymbol(math, open, "\u00ac", "\\neg", true); -defineSymbol(math, open, "\u00ac", "\\lnot"); -defineSymbol(math, textord, "\u22a4", "\\top"); -defineSymbol(math, textord, "\u22a5", "\\bot"); -defineSymbol(math, textord, "\u2205", "\\emptyset"); -defineSymbol(math, textord, "\u00f8", "\\varnothing"); -defineSymbol(math, mathord, "\u03b1", "\\alpha", true); -defineSymbol(math, mathord, "\u03b2", "\\beta", true); -defineSymbol(math, mathord, "\u03b3", "\\gamma", true); -defineSymbol(math, mathord, "\u03b4", "\\delta", true); -defineSymbol(math, mathord, "\u03f5", "\\epsilon", true); -defineSymbol(math, mathord, "\u03b6", "\\zeta", true); -defineSymbol(math, mathord, "\u03b7", "\\eta", true); -defineSymbol(math, mathord, "\u03b8", "\\theta", true); -defineSymbol(math, mathord, "\u03b9", "\\iota", true); -defineSymbol(math, mathord, "\u03ba", "\\kappa", true); -defineSymbol(math, mathord, "\u03bb", "\\lambda", true); -defineSymbol(math, mathord, "\u03bc", "\\mu", true); -defineSymbol(math, mathord, "\u03bd", "\\nu", true); -defineSymbol(math, mathord, "\u03be", "\\xi", true); -defineSymbol(math, mathord, "\u03bf", "\\omicron", true); -defineSymbol(math, mathord, "\u03c0", "\\pi", true); -defineSymbol(math, mathord, "\u03c1", "\\rho", true); -defineSymbol(math, mathord, "\u03c3", "\\sigma", true); -defineSymbol(math, mathord, "\u03c4", "\\tau", true); -defineSymbol(math, mathord, "\u03c5", "\\upsilon", true); -defineSymbol(math, mathord, "\u03d5", "\\phi", true); -defineSymbol(math, mathord, "\u03c7", "\\chi", true); -defineSymbol(math, mathord, "\u03c8", "\\psi", true); -defineSymbol(math, mathord, "\u03c9", "\\omega", true); -defineSymbol(math, mathord, "\u03b5", "\\varepsilon", true); -defineSymbol(math, mathord, "\u03d1", "\\vartheta", true); -defineSymbol(math, mathord, "\u03d6", "\\varpi", true); -defineSymbol(math, mathord, "\u03f1", "\\varrho", true); -defineSymbol(math, mathord, "\u03c2", "\\varsigma", true); -defineSymbol(math, mathord, "\u03c6", "\\varphi", true); -defineSymbol(math, mathord, "\u03d8", "\\Coppa", true); -defineSymbol(math, mathord, "\u03d9", "\\coppa", true); -defineSymbol(math, mathord, "\u03d9", "\\varcoppa", true); -defineSymbol(math, mathord, "\u03de", "\\Koppa", true); -defineSymbol(math, mathord, "\u03df", "\\koppa", true); -defineSymbol(math, mathord, "\u03e0", "\\Sampi", true); -defineSymbol(math, mathord, "\u03e1", "\\sampi", true); -defineSymbol(math, mathord, "\u03da", "\\Stigma", true); -defineSymbol(math, mathord, "\u03db", "\\stigma", true); -defineSymbol(math, mathord, "\u2aeb", "\\Bot"); -defineSymbol(math, bin, "\u2217", "\u2217", true); -defineSymbol(math, bin, "+", "+"); -defineSymbol(math, bin, "*", "*"); -defineSymbol(math, bin, "\u2044", "\u2044"); -defineSymbol(math, bin, "\u2212", "-", true); -defineSymbol(math, bin, "\u22c5", "\\cdot", true); -defineSymbol(math, bin, "\u2218", "\\circ", true); -defineSymbol(math, bin, "\u00f7", "\\div", true); -defineSymbol(math, bin, "\u00b1", "\\pm", true); -defineSymbol(math, bin, "\u00d7", "\\times", true); -defineSymbol(math, bin, "\u2229", "\\cap", true); -defineSymbol(math, bin, "\u222a", "\\cup", true); -defineSymbol(math, bin, "\u2216", "\\setminus", true); -defineSymbol(math, bin, "\u2227", "\\land"); -defineSymbol(math, bin, "\u2228", "\\lor"); -defineSymbol(math, bin, "\u2227", "\\wedge", true); -defineSymbol(math, bin, "\u2228", "\\vee", true); -defineSymbol(math, open, "\u27e6", "\\llbracket", true); // stmaryrd/semantic packages -defineSymbol(math, close, "\u27e7", "\\rrbracket", true); -defineSymbol(math, open, "\u27e8", "\\langle", true); -defineSymbol(math, open, "|", "\\lvert"); -defineSymbol(math, open, "\u2016", "\\lVert"); -defineSymbol(math, textord, "!", "\\oc"); // cmll package -defineSymbol(math, textord, "?", "\\wn"); -defineSymbol(math, textord, "\u2193", "\\shpos"); -defineSymbol(math, textord, "\u2195", "\\shift"); -defineSymbol(math, textord, "\u2191", "\\shneg"); -defineSymbol(math, close, "?", "?"); -defineSymbol(math, close, "!", "!"); -defineSymbol(math, close, "‼", "‼"); -defineSymbol(math, close, "\u27e9", "\\rangle", true); -defineSymbol(math, close, "|", "\\rvert"); -defineSymbol(math, close, "\u2016", "\\rVert"); -defineSymbol(math, open, "\u2983", "\\lBrace", true); // stmaryrd/semantic packages -defineSymbol(math, close, "\u2984", "\\rBrace", true); -defineSymbol(math, rel, "=", "\\equal", true); -defineSymbol(math, rel, ":", ":"); -defineSymbol(math, rel, "\u2248", "\\approx", true); -defineSymbol(math, rel, "\u2245", "\\cong", true); -defineSymbol(math, rel, "\u2265", "\\ge"); -defineSymbol(math, rel, "\u2265", "\\geq", true); -defineSymbol(math, rel, "\u2190", "\\gets"); -defineSymbol(math, rel, ">", "\\gt", true); -defineSymbol(math, rel, "\u2208", "\\in", true); -defineSymbol(math, rel, "\u2209", "\\notin", true); -defineSymbol(math, rel, "\ue020", "\\@not"); -defineSymbol(math, rel, "\u2282", "\\subset", true); -defineSymbol(math, rel, "\u2283", "\\supset", true); -defineSymbol(math, rel, "\u2286", "\\subseteq", true); -defineSymbol(math, rel, "\u2287", "\\supseteq", true); -defineSymbol(math, rel, "\u2288", "\\nsubseteq", true); -defineSymbol(math, rel, "\u2288", "\\nsubseteqq"); -defineSymbol(math, rel, "\u2289", "\\nsupseteq", true); -defineSymbol(math, rel, "\u2289", "\\nsupseteqq"); -defineSymbol(math, rel, "\u22a8", "\\models"); -defineSymbol(math, rel, "\u2190", "\\leftarrow", true); -defineSymbol(math, rel, "\u2264", "\\le"); -defineSymbol(math, rel, "\u2264", "\\leq", true); -defineSymbol(math, rel, "<", "\\lt", true); -defineSymbol(math, rel, "\u2192", "\\rightarrow", true); -defineSymbol(math, rel, "\u2192", "\\to"); -defineSymbol(math, rel, "\u2271", "\\ngeq", true); -defineSymbol(math, rel, "\u2271", "\\ngeqq"); -defineSymbol(math, rel, "\u2271", "\\ngeqslant"); -defineSymbol(math, rel, "\u2270", "\\nleq", true); -defineSymbol(math, rel, "\u2270", "\\nleqq"); -defineSymbol(math, rel, "\u2270", "\\nleqslant"); -defineSymbol(math, rel, "\u2aeb", "\\Perp", true); //cmll package -defineSymbol(math, spacing, "\u00a0", "\\ "); -defineSymbol(math, spacing, "\u00a0", "\\space"); -// Ref: LaTeX Source 2e: \DeclareRobustCommand{\nobreakspace}{% -defineSymbol(math, spacing, "\u00a0", "\\nobreakspace"); -defineSymbol(text, spacing, "\u00a0", "\\ "); -defineSymbol(text, spacing, "\u00a0", " "); -defineSymbol(text, spacing, "\u00a0", "\\space"); -defineSymbol(text, spacing, "\u00a0", "\\nobreakspace"); -defineSymbol(math, spacing, null, "\\nobreak"); -defineSymbol(math, spacing, null, "\\allowbreak"); -defineSymbol(math, punct, ",", ","); -defineSymbol(text, punct, ":", ":"); -defineSymbol(math, punct, ";", ";"); -defineSymbol(math, bin, "\u22bc", "\\barwedge", true); -defineSymbol(math, bin, "\u22bb", "\\veebar", true); -defineSymbol(math, bin, "\u2299", "\\odot", true); -defineSymbol(math, bin, "\u2295", "\\oplus", true); -defineSymbol(math, bin, "\u2297", "\\otimes", true); -defineSymbol(math, textord, "\u2202", "\\partial", true); -defineSymbol(math, bin, "\u2298", "\\oslash", true); -defineSymbol(math, bin, "\u229a", "\\circledcirc", true); -defineSymbol(math, bin, "\u22a1", "\\boxdot", true); -defineSymbol(math, bin, "\u25b3", "\\bigtriangleup"); -defineSymbol(math, bin, "\u25bd", "\\bigtriangledown"); -defineSymbol(math, bin, "\u2020", "\\dagger"); -defineSymbol(math, bin, "\u22c4", "\\diamond"); -defineSymbol(math, bin, "\u22c6", "\\star"); -defineSymbol(math, bin, "\u25c3", "\\triangleleft"); -defineSymbol(math, bin, "\u25b9", "\\triangleright"); -defineSymbol(math, open, "{", "\\{"); -defineSymbol(text, textord, "{", "\\{"); -defineSymbol(text, textord, "{", "\\textbraceleft"); -defineSymbol(math, close, "}", "\\}"); -defineSymbol(text, textord, "}", "\\}"); -defineSymbol(text, textord, "}", "\\textbraceright"); -defineSymbol(math, open, "{", "\\lbrace"); -defineSymbol(math, close, "}", "\\rbrace"); -defineSymbol(math, open, "[", "\\lbrack", true); -defineSymbol(text, textord, "[", "\\lbrack", true); -defineSymbol(math, close, "]", "\\rbrack", true); -defineSymbol(text, textord, "]", "\\rbrack", true); -defineSymbol(math, open, "(", "\\lparen", true); -defineSymbol(math, close, ")", "\\rparen", true); -defineSymbol(text, textord, "<", "\\textless", true); // in T1 fontenc -defineSymbol(text, textord, ">", "\\textgreater", true); // in T1 fontenc -defineSymbol(math, open, "\u230a", "\\lfloor", true); -defineSymbol(math, close, "\u230b", "\\rfloor", true); -defineSymbol(math, open, "\u2308", "\\lceil", true); -defineSymbol(math, close, "\u2309", "\\rceil", true); -defineSymbol(math, textord, "\\", "\\backslash"); -defineSymbol(math, textord, "|", "|"); -defineSymbol(math, textord, "|", "\\vert"); -defineSymbol(text, textord, "|", "\\textbar", true); // in T1 fontenc -defineSymbol(math, textord, "\u2016", "\\|"); -defineSymbol(math, textord, "\u2016", "\\Vert"); -defineSymbol(text, textord, "\u2016", "\\textbardbl"); -defineSymbol(text, textord, "~", "\\textasciitilde"); -defineSymbol(text, textord, "\\", "\\textbackslash"); -defineSymbol(text, textord, "^", "\\textasciicircum"); -defineSymbol(math, rel, "\u2191", "\\uparrow", true); -defineSymbol(math, rel, "\u21d1", "\\Uparrow", true); -defineSymbol(math, rel, "\u2193", "\\downarrow", true); -defineSymbol(math, rel, "\u21d3", "\\Downarrow", true); -defineSymbol(math, rel, "\u2195", "\\updownarrow", true); -defineSymbol(math, rel, "\u21d5", "\\Updownarrow", true); -defineSymbol(math, op, "\u2210", "\\coprod"); -defineSymbol(math, op, "\u22c1", "\\bigvee"); -defineSymbol(math, op, "\u22c0", "\\bigwedge"); -defineSymbol(math, op, "\u2a04", "\\biguplus"); -defineSymbol(math, op, "\u22c2", "\\bigcap"); -defineSymbol(math, op, "\u22c3", "\\bigcup"); -defineSymbol(math, op, "\u222b", "\\int"); -defineSymbol(math, op, "\u222b", "\\intop"); -defineSymbol(math, op, "\u222c", "\\iint"); -defineSymbol(math, op, "\u222d", "\\iiint"); -defineSymbol(math, op, "\u220f", "\\prod"); -defineSymbol(math, op, "\u2211", "\\sum"); -defineSymbol(math, op, "\u2a02", "\\bigotimes"); -defineSymbol(math, op, "\u2a01", "\\bigoplus"); -defineSymbol(math, op, "\u2a00", "\\bigodot"); -defineSymbol(math, op, "\u222e", "\\oint"); -defineSymbol(math, op, "\u222f", "\\oiint"); -defineSymbol(math, op, "\u2230", "\\oiiint"); -defineSymbol(math, op, "\u2231", "\\intclockwise"); -defineSymbol(math, op, "\u2232", "\\varointclockwise"); -defineSymbol(math, op, "\u2a0c", "\\iiiint"); -defineSymbol(math, op, "\u2a0d", "\\intbar"); -defineSymbol(math, op, "\u2a0e", "\\intBar"); -defineSymbol(math, op, "\u2a0f", "\\fint"); -defineSymbol(math, op, "\u2a12", "\\rppolint"); -defineSymbol(math, op, "\u2a13", "\\scpolint"); -defineSymbol(math, op, "\u2a15", "\\pointint"); -defineSymbol(math, op, "\u2a16", "\\sqint"); -defineSymbol(math, op, "\u2a17", "\\intlarhk"); -defineSymbol(math, op, "\u2a18", "\\intx"); -defineSymbol(math, op, "\u2a19", "\\intcap"); -defineSymbol(math, op, "\u2a1a", "\\intcup"); -defineSymbol(math, op, "\u2a05", "\\bigsqcap"); -defineSymbol(math, op, "\u2a06", "\\bigsqcup"); -defineSymbol(math, op, "\u222b", "\\smallint"); -defineSymbol(text, inner, "\u2026", "\\textellipsis"); -defineSymbol(math, inner, "\u2026", "\\mathellipsis"); -defineSymbol(text, inner, "\u2026", "\\ldots", true); -defineSymbol(math, inner, "\u2026", "\\ldots", true); -defineSymbol(math, inner, "\u22f0", "\\iddots", true); -defineSymbol(math, inner, "\u22ef", "\\@cdots", true); -defineSymbol(math, inner, "\u22f1", "\\ddots", true); -defineSymbol(math, textord, "\u22ee", "\\varvdots"); // \vdots is a macro -defineSymbol(math, accent, "\u02ca", "\\acute"); -defineSymbol(math, accent, "\u0060", "\\grave"); -defineSymbol(math, accent, "\u00a8", "\\ddot"); -defineSymbol(math, accent, "\u20db", "\\dddot"); -defineSymbol(math, accent, "\u20dc", "\\ddddot"); -defineSymbol(math, accent, "\u007e", "\\tilde"); -defineSymbol(math, accent, "\u203e", "\\bar"); -defineSymbol(math, accent, "\u02d8", "\\breve"); -defineSymbol(math, accent, "\u02c7", "\\check"); -defineSymbol(math, accent, "\u005e", "\\hat"); -defineSymbol(math, accent, "\u20d7", "\\vec"); -defineSymbol(math, accent, "\u02d9", "\\dot"); -defineSymbol(math, accent, "\u02da", "\\mathring"); -defineSymbol(math, mathord, "\u0131", "\\imath", true); -defineSymbol(math, mathord, "\u0237", "\\jmath", true); -defineSymbol(math, textord, "\u0131", "\u0131"); -defineSymbol(math, textord, "\u0237", "\u0237"); -defineSymbol(text, textord, "\u0131", "\\i", true); -defineSymbol(text, textord, "\u0237", "\\j", true); -defineSymbol(text, textord, "\u00df", "\\ss", true); -defineSymbol(text, textord, "\u00e6", "\\ae", true); -defineSymbol(text, textord, "\u0153", "\\oe", true); -defineSymbol(text, textord, "\u00f8", "\\o", true); -defineSymbol(math, mathord, "\u00f8", "\\o", true); -defineSymbol(text, textord, "\u00c6", "\\AE", true); -defineSymbol(text, textord, "\u0152", "\\OE", true); -defineSymbol(text, textord, "\u00d8", "\\O", true); -defineSymbol(math, mathord, "\u00d8", "\\O", true); -defineSymbol(text, accent, "\u02ca", "\\'"); // acute -defineSymbol(text, accent, "\u02cb", "\\`"); // grave -defineSymbol(text, accent, "\u02c6", "\\^"); // circumflex -defineSymbol(text, accent, "\u02dc", "\\~"); // tilde -defineSymbol(text, accent, "\u02c9", "\\="); // macron -defineSymbol(text, accent, "\u02d8", "\\u"); // breve -defineSymbol(text, accent, "\u02d9", "\\."); // dot above -defineSymbol(text, accent, "\u00b8", "\\c"); // cedilla -defineSymbol(text, accent, "\u02da", "\\r"); // ring above -defineSymbol(text, accent, "\u02c7", "\\v"); // caron -defineSymbol(text, accent, "\u00a8", '\\"'); // diaresis -defineSymbol(text, accent, "\u02dd", "\\H"); // double acute -defineSymbol(math, accent, "\u02ca", "\\'"); // acute -defineSymbol(math, accent, "\u02cb", "\\`"); // grave -defineSymbol(math, accent, "\u02c6", "\\^"); // circumflex -defineSymbol(math, accent, "\u02dc", "\\~"); // tilde -defineSymbol(math, accent, "\u02c9", "\\="); // macron -defineSymbol(math, accent, "\u02d8", "\\u"); // breve -defineSymbol(math, accent, "\u02d9", "\\."); // dot above -defineSymbol(math, accent, "\u00b8", "\\c"); // cedilla -defineSymbol(math, accent, "\u02da", "\\r"); // ring above -defineSymbol(math, accent, "\u02c7", "\\v"); // caron -defineSymbol(math, accent, "\u00a8", '\\"'); // diaresis -defineSymbol(math, accent, "\u02dd", "\\H"); // double acute - -// These ligatures are detected and created in Parser.js's `formLigatures`. -const ligatures = { - "--": true, - "---": true, - "``": true, - "''": true -}; - -defineSymbol(text, textord, "\u2013", "--", true); -defineSymbol(text, textord, "\u2013", "\\textendash"); -defineSymbol(text, textord, "\u2014", "---", true); -defineSymbol(text, textord, "\u2014", "\\textemdash"); -defineSymbol(text, textord, "\u2018", "`", true); -defineSymbol(text, textord, "\u2018", "\\textquoteleft"); -defineSymbol(text, textord, "\u2019", "'", true); -defineSymbol(text, textord, "\u2019", "\\textquoteright"); -defineSymbol(text, textord, "\u201c", "``", true); -defineSymbol(text, textord, "\u201c", "\\textquotedblleft"); -defineSymbol(text, textord, "\u201d", "''", true); -defineSymbol(text, textord, "\u201d", "\\textquotedblright"); -// \degree from gensymb package -defineSymbol(math, textord, "\u00b0", "\\degree", true); -defineSymbol(text, textord, "\u00b0", "\\degree"); -// \textdegree from inputenc package -defineSymbol(text, textord, "\u00b0", "\\textdegree", true); -// TODO: In LaTeX, \pounds can generate a different character in text and math -// mode, but among our fonts, only Main-Regular defines this character "163". -defineSymbol(math, textord, "\u00a3", "\\pounds"); -defineSymbol(math, textord, "\u00a3", "\\mathsterling", true); -defineSymbol(text, textord, "\u00a3", "\\pounds"); -defineSymbol(text, textord, "\u00a3", "\\textsterling", true); -defineSymbol(math, textord, "\u2720", "\\maltese"); -defineSymbol(text, textord, "\u2720", "\\maltese"); -defineSymbol(math, textord, "\u20ac", "\\euro", true); -defineSymbol(text, textord, "\u20ac", "\\euro", true); -defineSymbol(text, textord, "\u20ac", "\\texteuro"); -defineSymbol(math, textord, "\u00a9", "\\copyright", true); -defineSymbol(text, textord, "\u00a9", "\\textcopyright"); - -// Italic Greek -defineSymbol(math, textord, "𝛤", "\\varGamma"); -defineSymbol(math, textord, "𝛥", "\\varDelta"); -defineSymbol(math, textord, "𝛩", "\\varTheta"); -defineSymbol(math, textord, "𝛬", "\\varLambda"); -defineSymbol(math, textord, "𝛯", "\\varXi"); -defineSymbol(math, textord, "𝛱", "\\varPi"); -defineSymbol(math, textord, "𝛴", "\\varSigma"); -defineSymbol(math, textord, "𝛶", "\\varUpsilon"); -defineSymbol(math, textord, "𝛷", "\\varPhi"); -defineSymbol(math, textord, "𝛹", "\\varPsi"); -defineSymbol(math, textord, "𝛺", "\\varOmega"); -defineSymbol(text, textord, "𝛤", "\\varGamma"); -defineSymbol(text, textord, "𝛥", "\\varDelta"); -defineSymbol(text, textord, "𝛩", "\\varTheta"); -defineSymbol(text, textord, "𝛬", "\\varLambda"); -defineSymbol(text, textord, "𝛯", "\\varXi"); -defineSymbol(text, textord, "𝛱", "\\varPi"); -defineSymbol(text, textord, "𝛴", "\\varSigma"); -defineSymbol(text, textord, "𝛶", "\\varUpsilon"); -defineSymbol(text, textord, "𝛷", "\\varPhi"); -defineSymbol(text, textord, "𝛹", "\\varPsi"); -defineSymbol(text, textord, "𝛺", "\\varOmega"); - - -// There are lots of symbols which are the same, so we add them in afterwards. -// All of these are textords in math mode -const mathTextSymbols = '0123456789/@."'; -for (let i = 0; i < mathTextSymbols.length; i++) { - const ch = mathTextSymbols.charAt(i); - defineSymbol(math, textord, ch, ch); -} - -// All of these are textords in text mode -const textSymbols = '0123456789!@*()-=+";:?/.,'; -for (let i = 0; i < textSymbols.length; i++) { - const ch = textSymbols.charAt(i); - defineSymbol(text, textord, ch, ch); -} - -// All of these are textords in text mode, and mathords in math mode -const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -for (let i = 0; i < letters.length; i++) { - const ch = letters.charAt(i); - defineSymbol(math, mathord, ch, ch); - defineSymbol(text, textord, ch, ch); -} - -// Some more letters in Unicode Basic Multilingual Plane. -const narrow = "ÇÐÞçþℂℍℕℙℚℝℤℎℏℊℋℌℐℑℒℓ℘ℛℜℬℰℱℳℭℨ"; -for (let i = 0; i < narrow.length; i++) { - const ch = narrow.charAt(i); - defineSymbol(math, mathord, ch, ch); - defineSymbol(text, textord, ch, ch); -} - -// The next loop loads wide (surrogate pair) characters. -// We support some letters in the Unicode range U+1D400 to U+1D7FF, -// Mathematical Alphanumeric Symbols. -let wideChar = ""; -for (let i = 0; i < letters.length; i++) { - // The hex numbers in the next line are a surrogate pair. - // 0xD835 is the high surrogate for all letters in the range we support. - // 0xDC00 is the low surrogate for bold A. - wideChar = String.fromCharCode(0xd835, 0xdc00 + i); // A-Z a-z bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdc34 + i); // A-Z a-z italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdc68 + i); // A-Z a-z bold italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdd04 + i); // A-Z a-z Fractur - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdda0 + i); // A-Z a-z sans-serif - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xddd4 + i); // A-Z a-z sans bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xde08 + i); // A-Z a-z sans italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xde70 + i); // A-Z a-z monospace - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdd38 + i); // A-Z a-z double struck - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - const ch = letters.charAt(i); - wideChar = String.fromCharCode(0xd835, 0xdc9c + i); // A-Z a-z calligraphic - defineSymbol(math, mathord, ch, wideChar); - defineSymbol(text, textord, ch, wideChar); -} - -// Next, some wide character numerals -for (let i = 0; i < 10; i++) { - wideChar = String.fromCharCode(0xd835, 0xdfce + i); // 0-9 bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdfe2 + i); // 0-9 sans serif - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdfec + i); // 0-9 bold sans - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdff6 + i); // 0-9 monospace - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); -} - -/* - * Neither Firefox nor Chrome support hard line breaks or soft line breaks. - * (Despite https://www.w3.org/Math/draft-spec/mathml.html#chapter3_presm.lbattrs) - * So Temml has work-arounds for both hard and soft breaks. - * The work-arounds sadly do not work simultaneously. Any top-level hard - * break makes soft line breaks impossible. - * - * Hard breaks are simulated by creating a and putting each line in its own . - * - * To create soft line breaks, Temml avoids using the and tags. - * Then the top level of a element can be occupied by elements, and the browser - * will break after a if the expression extends beyond the container limit. - * - * We want the expression to render with soft line breaks after each top-level binary or - * relational operator, per TeXbook p. 173. So we gather the expression into s so that - * each ends in a binary or relational operator. - * - * Soft line breaks will not work in Chromium and Safari, only Firefox. - * - * Hopefully browsers will someday do their own linebreaking and we will be able to delete - * much of this module. - */ - -function setLineBreaks(expression, isDisplayMode, isAnnotated, color = undefined) { - if (color === undefined) { - // First, make one pass through the expression and split any color nodes. - const upperLimit = expression.length - 1; - for (let i = upperLimit; i >= 0; i--) { - const node = expression[i]; - if (node.type === "mstyle" && node.attributes.mathcolor) { - const color = node.attributes.mathcolor; - const fragment = setLineBreaks(node.children, isDisplayMode, isAnnotated, color); - if (!(fragment.type && fragment.type !== "mtable")) { - expression.splice(i, 1, ...fragment.children); - - } - } - } - } - - const tagName = color ? "mstyle" : "mrow"; - - const mtrs = []; - let mrows = []; - let block = []; - let canBeBIN = false; // The first node cannot be an infix binary operator. - for (let i = 0; i < expression.length; i++) { - const node = expression[i]; - if (node.type && node.type === "mstyle" && node.attributes.mathcolor) { - // Start a new block. (Insert a soft linebreak.) - mrows.push(new mathMLTree.MathNode(tagName, block)); - // Insert the mstyle - mrows.push(node); - block = []; - continue - } - if (node.attributes && node.attributes.linebreak && - node.attributes.linebreak === "newline") { - // A hard line break. Create a for the current block. - if (block.length > 0) { - const element = new mathMLTree.MathNode(tagName, block); - if (color) { element.setAttribute("mathcolor", color); } - mrows.push(new mathMLTree.MathNode(tagName, block)); - } - mrows.push(node); - block = []; - const mtd = new mathMLTree.MathNode("mtd", mrows); - mtrs.push(new mathMLTree.MathNode("mtr", [mtd])); - mrows = []; - continue - } - block.push(node); - if (node.type && node.type === "mo" && !isDisplayMode && !isAnnotated) { - // This may be a place for a soft line break. - if (canBeBIN && !node.attributes.form) { - // Check if the following node is a \nobreak text node, e.g. "~"" - const next = i < expression.length - 1 ? expression[i + 1] : null; - let glueIsFreeOfNobreak = true; - if ( - !( - next && - next.type === "mtext" && - next.attributes.linebreak && - next.attributes.linebreak === "nobreak" - ) - ) { - // We may need to start a new block. - // First, put any post-operator glue on same line as operator. - for (let j = i + 1; j < expression.length; j++) { - const nd = expression[j]; - if ( - nd.type && - nd.type === "mspace" && - !(nd.attributes.linebreak && nd.attributes.linebreak === "newline") - ) { - block.push(nd); - i += 1; - if ( - nd.attributes && - nd.attributes.linebreak && - nd.attributes.linebreak === "nobreak" - ) { - glueIsFreeOfNobreak = false; - } - } else { - break; - } - } - } - if (glueIsFreeOfNobreak) { - // Start a new block. (Insert a soft linebreak.) - const element = new mathMLTree.MathNode(tagName, block); - if (color) { element.setAttribute("mathcolor", color); } - mrows.push(element); - block = []; - } - canBeBIN = false; - } - const isOpenDelimiter = node.attributes.form && node.attributes.form === "prefix"; - // Any operator that follows an open delimiter is unary. - canBeBIN = !(node.attributes.separator || isOpenDelimiter); - } else { - canBeBIN = true; - } - } - if (block.length > 0) { - const element = new mathMLTree.MathNode(tagName, block); - if (color) { element.setAttribute("mathcolor", color); } - mrows.push(element); - } - if (mtrs.length > 0) { - const mtd = new mathMLTree.MathNode("mtd", mrows); - const mtr = new mathMLTree.MathNode("mtr", [mtd]); - mtrs.push(mtr); - const mtable = new mathMLTree.MathNode("mtable", mtrs); - if (!isDisplayMode) { - mtable.setAttribute("columnalign", "left"); - mtable.setAttribute("rowspacing", "0em"); - } - return mtable - } - return mathMLTree.newDocumentFragment(mrows); -} - -/** - * This file converts a parse tree into a cooresponding MathML tree. The main - * entry point is the `buildMathML` function, which takes a parse tree from the - * parser. - */ - -/** - * Takes a symbol and converts it into a MathML text node after performing - * optional replacement from symbols.js. - */ -const makeText = function(text, mode, style) { - if ( - symbols[mode][text] && - symbols[mode][text].replace && - text.charCodeAt(0) !== 0xd835 && - !( - Object.prototype.hasOwnProperty.call(ligatures, text) && - style && - ((style.fontFamily && style.fontFamily.slice(4, 6) === "tt") || - (style.font && style.font.slice(4, 6) === "tt")) - ) - ) { - text = symbols[mode][text].replace; - } - - return new mathMLTree.TextNode(text); -}; - -/** - * Wrap the given array of nodes in an node if needed, i.e., - * unless the array has length 1. Always returns a single node. - */ -const makeRow = function(body) { - if (body.length === 1) { - return body[0]; - } else { - return new mathMLTree.MathNode("mrow", body); - } -}; - -const isRel = item => { - return (item.type === "atom" && item.family === "rel") || - (item.type === "mclass" && item.mclass === "mrel") -}; - -/** - * Takes a list of nodes, builds them, and returns a list of the generated - * MathML nodes. Also do a couple chores along the way: - * (1) Suppress spacing when an author wraps an operator w/braces, as in {=}. - * (2) Suppress spacing between two adjacent relations. - */ -const buildExpression = function(expression, style, isOrdgroup) { - if (expression.length === 1) { - const group = buildGroup$1(expression[0], style); - if (isOrdgroup && group instanceof MathNode && group.type === "mo") { - // When TeX writers want to suppress spacing on an operator, - // they often put the operator by itself inside braces. - group.setAttribute("lspace", "0em"); - group.setAttribute("rspace", "0em"); - } - return [group]; - } - - const groups = []; - for (let i = 0; i < expression.length; i++) { - const group = buildGroup$1(expression[i], style); - // Suppress spacing between adjacent relations - if (i < expression.length - 1 && isRel(expression[i]) && isRel(expression[i + 1])) { - group.setAttribute("rspace", "0em"); - } - if (i > 0 && isRel(expression[i]) && isRel(expression[i - 1])) { - group.setAttribute("lspace", "0em"); - } - groups.push(group); - } - return groups; -}; - -/** - * Equivalent to buildExpression, but wraps the elements in an - * if there's more than one. Returns a single node instead of an array. - */ -const buildExpressionRow = function(expression, style, isOrdgroup) { - return makeRow(buildExpression(expression, style, isOrdgroup)); -}; - -/** - * Takes a group from the parser and calls the appropriate groupBuilders function - * on it to produce a MathML node. - */ -const buildGroup$1 = function(group, style) { - if (!group) { - return new mathMLTree.MathNode("mrow"); - } - - if (_mathmlGroupBuilders[group.type]) { - // Call the groupBuilders function - const result = _mathmlGroupBuilders[group.type](group, style); - return result; - } else { - throw new ParseError("Got group of unknown type: '" + group.type + "'"); - } -}; - -const glue = _ => { - const glueNode = new mathMLTree.MathNode("mtd", []); - glueNode.setAttribute("style", "padding: 0;width: 50%;"); - return glueNode -}; - -const taggedExpression = (expression, tag, style, leqno, preventTagLap) => { - tag = buildExpressionRow(tag[0].body, style); - tag = utils.consolidateText(tag); - tag.classes = ["tml-tag"]; - if (!preventTagLap) { - tag = new mathMLTree.MathNode("mpadded", [tag]); - tag.setAttribute("style", "width:0;"); - tag.setAttribute("width", "0"); - tag.setAttribute((leqno ? "rspace" : "lspace"), "-1width"); - } - tag = new mathMLTree.MathNode("mtd", [tag]); - if (!preventTagLap) { tag.setAttribute("style", "padding: 0; min-width:0"); } - - expression = new mathMLTree.MathNode("mtd", [expression]); - const rowArray = leqno - ? [tag, glue(), expression, glue()] - : [glue(), expression, glue(), tag]; - const mtr = new mathMLTree.MathNode("mtr", rowArray, ["tml-tageqn"]); - const table = new mathMLTree.MathNode("mtable", [mtr]); - table.setAttribute("width", "100%"); - table.setAttribute("displaystyle", "true"); - return table -}; - -/** - * Takes a full parse tree and settings and builds a MathML representation of - * it. - */ -function buildMathML(tree, texExpression, style, settings) { - // Strip off outer tag wrapper for processing below. - let tag = null; - if (tree.length === 1 && tree[0].type === "tag") { - tag = tree[0].tag; - tree = tree[0].body; - } - - const expression = buildExpression(tree, style); - - const n1 = expression.length === 0 ? null : expression[0]; - let wrapper = expression.length === 1 && tag === null && (n1 instanceof MathNode) - && !(n1.type === "mstyle" && n1.attributes.mathcolor) - ? expression[0] - : setLineBreaks(expression, settings.displayMode, settings.annotate); - - if (tag) { - wrapper = taggedExpression(wrapper, tag, style, settings.leqno, settings.preventTagLap); - } - - let semantics; - if (settings.annotate) { - // Build a TeX annotation of the source - const annotation = new mathMLTree.MathNode( - "annotation", [new mathMLTree.TextNode(texExpression)]); - annotation.setAttribute("encoding", "application/x-tex"); - semantics = new mathMLTree.MathNode("semantics", [wrapper, annotation]); - } - - const math = settings.annotate - ? new mathMLTree.MathNode("math", [semantics]) - : new mathMLTree.MathNode("math", [wrapper]); - - if (settings.xml) { - math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML"); - } - if (settings.displayMode) { - math.setAttribute("display", "block"); - } - return math; -} - -const mathmlBuilder$a = (group, style) => { - const accentNode = group.isStretchy - ? stretchy.mathMLnode(group.label) - : new mathMLTree.MathNode("mo", [makeText(group.label, group.mode)]); - - if (!group.isStretchy) { - accentNode.setAttribute("stretchy", "false"); - } - - const node = new mathMLTree.MathNode((group.label === "\\c" ? "munder" : "mover"), - [buildGroup$1(group.base, style), accentNode] - ); - - node.setAttribute("accent", "true"); - return node; -}; - -const NON_STRETCHY_ACCENT_REGEX = new RegExp( - [ - "\\acute", - "\\grave", - "\\ddot", - "\\dddot", - "\\ddddot", - "\\tilde", - "\\bar", - "\\breve", - "\\check", - "\\hat", - "\\vec", - "\\dot", - "\\mathring" - ] - .map((accent) => `\\${accent}`) - .join("|") -); - -// Accents -defineFunction({ - type: "accent", - names: [ - "\\acute", - "\\grave", - "\\ddot", - "\\dddot", - "\\ddddot", - "\\tilde", - "\\bar", - "\\breve", - "\\check", - "\\hat", - "\\vec", - "\\dot", - "\\mathring", - "\\overparen", - "\\widecheck", - "\\widehat", - "\\wideparen", - "\\widetilde", - "\\overrightarrow", - "\\overleftarrow", - "\\Overrightarrow", - "\\overleftrightarrow", - "\\overgroup", - "\\overleftharpoon", - "\\overrightharpoon" - ], - props: { - numArgs: 1 - }, - handler: (context, args) => { - const base = normalizeArgument(args[0]); - - const isStretchy = !NON_STRETCHY_ACCENT_REGEX.test(context.funcName); - const isShifty = - !isStretchy || - context.funcName === "\\widehat" || - context.funcName === "\\widetilde" || - context.funcName === "\\widecheck"; - - return { - type: "accent", - mode: context.parser.mode, - label: context.funcName, - isStretchy: isStretchy, - isShifty: isShifty, - base: base - }; - }, - mathmlBuilder: mathmlBuilder$a -}); - -// Text-mode accents -defineFunction({ - type: "accent", - names: ["\\'", "\\`", "\\^", "\\~", "\\=", "\\c", "\\u", "\\.", '\\"', "\\r", "\\H", "\\v"], - props: { - numArgs: 1, - allowedInText: true, - allowedInMath: true, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const base = normalizeArgument(args[0]); - const mode = context.parser.mode; - - if (mode === "math" && context.parser.settings.strict) { - // LaTeX only writes a warning. It doesn't stop. We'll issue the same warning. - // eslint-disable-next-line no-console - console.log(`Temml parse error: Command ${context.funcName} is invalid in math mode.`); - } - - return { - type: "accent", - mode: mode, - label: context.funcName, - isStretchy: false, - isShifty: true, - base: base - }; - }, - mathmlBuilder: mathmlBuilder$a -}); - -defineFunction({ - type: "accentUnder", - names: [ - "\\underleftarrow", - "\\underrightarrow", - "\\underleftrightarrow", - "\\undergroup", - "\\underparen", - "\\utilde" - ], - props: { - numArgs: 1 - }, - handler: ({ parser, funcName }, args) => { - const base = args[0]; - return { - type: "accentUnder", - mode: parser.mode, - label: funcName, - base: base - }; - }, - mathmlBuilder: (group, style) => { - const accentNode = stretchy.mathMLnode(group.label); - const node = new mathMLTree.MathNode("munder", [ - buildGroup$1(group.base, style), - accentNode - ]); - node.setAttribute("accentunder", "true"); - return node; - } -}); - -/** - * This file does conversion between units. In particular, it provides - * calculateSize to convert other units into CSS units. - */ - -const ptPerUnit = { - // Convert to CSS (Postscipt) points, not TeX points - // https://en.wikibooks.org/wiki/LaTeX/Lengths and - // https://tex.stackexchange.com/a/8263 - pt: 800 / 803, // convert TeX point to CSS (Postscript) point - pc: (12 * 800) / 803, // pica - dd: ((1238 / 1157) * 800) / 803, // didot - cc: ((14856 / 1157) * 800) / 803, // cicero (12 didot) - nd: ((685 / 642) * 800) / 803, // new didot - nc: ((1370 / 107) * 800) / 803, // new cicero (12 new didot) - sp: ((1 / 65536) * 800) / 803, // scaled point (TeX's internal smallest unit) - mm: (25.4 / 72), - cm: (2.54 / 72), - in: (1 / 72), - px: (96 / 72) -}; - -/** - * Determine whether the specified unit (either a string defining the unit - * or a "size" parse node containing a unit field) is valid. - */ -const validUnits = [ - "em", - "ex", - "mu", - "pt", - "mm", - "cm", - "in", - "px", - "bp", - "pc", - "dd", - "cc", - "nd", - "nc", - "sp" -]; - -const validUnit = function(unit) { - if (typeof unit !== "string") { - unit = unit.unit; - } - return validUnits.indexOf(unit) > -1 -}; - -const emScale = styleLevel => { - const scriptLevel = Math.max(styleLevel - 1, 0); - return [1, 0.7, 0.5][scriptLevel] -}; - -/* - * Convert a "size" parse node (with numeric "number" and string "unit" fields, - * as parsed by functions.js argType "size") into a CSS value. - */ -const calculateSize = function(sizeValue, style) { - let number = sizeValue.number; - if (style.maxSize[0] < 0 && number > 0) { - return { number: 0, unit: "em" } - } - const unit = sizeValue.unit; - switch (unit) { - case "mm": - case "cm": - case "in": - case "px": { - const numInCssPts = number * ptPerUnit[unit]; - if (numInCssPts > style.maxSize[1]) { - return { number: style.maxSize[1], unit: "pt" } - } - return { number, unit }; // absolute CSS units. - } - case "em": - case "ex": { - // In TeX, em and ex do not change size in \scriptstyle. - if (unit === "ex") { number *= 0.431; } - number = Math.min(number / emScale(style.level), style.maxSize[0]); - return { number: utils.round(number), unit: "em" }; - } - case "bp": { - if (number > style.maxSize[1]) { number = style.maxSize[1]; } - return { number, unit: "pt" }; // TeX bp is a CSS pt. (1/72 inch). - } - case "pt": - case "pc": - case "dd": - case "cc": - case "nd": - case "nc": - case "sp": { - number = Math.min(number * ptPerUnit[unit], style.maxSize[1]); - return { number: utils.round(number), unit: "pt" } - } - case "mu": { - number = Math.min(number / 18, style.maxSize[0]); - return { number: utils.round(number), unit: "em" } - } - default: - throw new ParseError("Invalid unit: '" + unit + "'") - } -}; - -// Helper functions -const paddedNode = (group, width, lspace = "0.3em") => { - const node = new mathMLTree.MathNode("mpadded", group ? [group] : []); - node.setAttribute("width", width); - node.setAttribute("lspace", lspace); - return node; -}; - -const labelSize = (size, scriptLevel) => (size / emScale(scriptLevel)).toFixed(4) + "em"; - -const munderoverNode = (name, body, below, style) => { - const arrowNode = stretchy.mathMLnode(name); - // Is this the short part of a mhchem equilibrium arrow? - const isEq = name.slice(1, 3) === "eq"; - const minWidth = name.charAt(1) === "x" - ? "1.75" // mathtools extensible arrows are 1.75em long - : name.slice(2, 4) === "cd" - ? "3.0" // cd package arrows - : isEq - ? "1.0" // The shorter harpoon of a mhchem equilibrium arrow - : "2.0"; // other mhchem arrows - arrowNode.setAttribute("minsize", String(minWidth) + "em"); - arrowNode.setAttribute("lspace", "0"); - arrowNode.setAttribute("rspace", (isEq ? "0.5em" : "0")); - - // upper and lower labels are set to scriptlevel by MathML - // So we have to adjust our dimensions accordingly. - const labelStyle = style.withLevel(style.level < 2 ? 2 : 3); - const emptyLabelWidth = labelSize(minWidth, labelStyle.level); - const lspace = labelSize((isEq ? 0 : 0.3), labelStyle.level); - let widthAdder = labelSize((isEq ? -0.4 : 0.6), labelStyle.level); - if (widthAdder.charAt(0) !== "-") { widthAdder = "+" + widthAdder; } - - const upperNode = (body && body.body && - // \hphantom visible content - (body.body.body || body.body.length > 0)) - ? paddedNode(buildGroup$1(body, labelStyle), widthAdder, lspace) - // Since Firefox does not recognize minsize set on the arrow, - // create an upper node w/correct width. - : paddedNode(null, emptyLabelWidth, "0"); - const lowerNode = (below && below.body && - (below.body.body || below.body.length > 0)) - ? paddedNode(buildGroup$1(below, labelStyle), widthAdder, lspace) - : paddedNode(null, emptyLabelWidth, "0"); - const node = new mathMLTree.MathNode("munderover", [arrowNode, lowerNode, upperNode]); - return node -}; - -// Stretchy arrows with an optional argument -defineFunction({ - type: "xArrow", - names: [ - "\\xleftarrow", - "\\xrightarrow", - "\\xLeftarrow", - "\\xRightarrow", - "\\xleftrightarrow", - "\\xLeftrightarrow", - "\\xhookleftarrow", - "\\xhookrightarrow", - "\\xmapsto", - "\\xrightharpoondown", - "\\xrightharpoonup", - "\\xleftharpoondown", - "\\xleftharpoonup", - "\\xlongequal", - "\\xtwoheadrightarrow", - "\\xtwoheadleftarrow", - // The next 7 functions are here only to support mhchem - "\\yields", - "\\yieldsLeft", - "\\mesomerism", - "\\longrightharpoonup", - "\\longleftharpoondown", - // The next 3 functions are here only to support the {CD} environment. - "\\\\cdrightarrow", - "\\\\cdleftarrow", - "\\\\cdlongequal" - ], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser, funcName }, args, optArgs) { - return { - type: "xArrow", - mode: parser.mode, - name: funcName, - body: args[0], - below: optArgs[0] - }; - }, - mathmlBuilder(group, style) { - // Build the arrow and its labels. - const node = munderoverNode(group.name, group.body, group.below, style); - // Create operator spacing for a relation. - const wrapper = new mathMLTree.MathNode("mpadded", [node]); - wrapper.setAttribute("lspace", "0.2778em"); - wrapper.setAttribute("width", "+0.5556em"); - return wrapper - } -}); - -const arrowComponent = { - "\\xtofrom": ["\\xrightarrow", "\\xleftarrow"], - "\\xleftrightharpoons": ["\\xleftharpoonup", "\\xrightharpoondown"], - "\\xrightleftharpoons": ["\\xrightharpoonup", "\\xleftharpoondown"], - "\\yieldsLeftRight": ["\\yields", "\\yieldsLeft"], - // The next three all get the same harpoon glyphs. Only the lengths and paddings differ. - "\\equilibrium": ["\\longrightharpoonup", "\\longleftharpoondown"], - "\\equilibriumRight": ["\\longrightharpoonup", "\\eqleftharpoondown"], - "\\equilibriumLeft": ["\\eqrightharpoonup", "\\longleftharpoondown"] -}; - -// Browsers are not good at stretching a glyph that contains a pair of stacked arrows such as ⇄. -// So we stack a pair of single arrows. -defineFunction({ - type: "stackedArrow", - names: [ - "\\xtofrom", // expfeil - "\\xleftrightharpoons", // mathtools - "\\xrightleftharpoons", // mathtools - "\\yieldsLeftRight", // mhchem - "\\equilibrium", // mhchem - "\\equilibriumRight", - "\\equilibriumLeft" - ], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser, funcName }, args, optArgs) { - const lowerArrowBody = args[0] - ? { - type: "hphantom", - mode: parser.mode, - body: args[0] - } - : null; - const upperArrowBelow = optArgs[0] - ? { - type: "hphantom", - mode: parser.mode, - body: optArgs[0] - } - : null; - return { - type: "stackedArrow", - mode: parser.mode, - name: funcName, - body: args[0], - upperArrowBelow, - lowerArrowBody, - below: optArgs[0] - }; - }, - mathmlBuilder(group, style) { - const topLabel = arrowComponent[group.name][0]; - const botLabel = arrowComponent[group.name][1]; - const topArrow = munderoverNode(topLabel, group.body, group.upperArrowBelow, style); - const botArrow = munderoverNode(botLabel, group.lowerArrowBody, group.below, style); - let wrapper; - - const raiseNode = new mathMLTree.MathNode("mpadded", [topArrow]); - raiseNode.setAttribute("voffset", "0.3em"); - raiseNode.setAttribute("height", "+0.3em"); - raiseNode.setAttribute("depth", "-0.3em"); - // One of the arrows is given ~zero width. so the other has the same horzontal alignment. - if (group.name === "\\equilibriumLeft") { - const botNode = new mathMLTree.MathNode("mpadded", [botArrow]); - botNode.setAttribute("width", "0.5em"); - wrapper = new mathMLTree.MathNode("mpadded", [botNode, raiseNode]); - } else { - raiseNode.setAttribute("width", (group.name === "\\equilibriumRight" ? "0.5em" : "0")); - wrapper = new mathMLTree.MathNode("mpadded", [raiseNode, botArrow]); - } - - wrapper.setAttribute("voffset", "-0.18em"); - wrapper.setAttribute("width", "+0.5556em"); - wrapper.setAttribute("height", "-0.18em"); - wrapper.setAttribute("depth", "+0.18em"); - wrapper.setAttribute("lspace", "0.2778em"); - return wrapper - } -}); - -defineFunction({ - type: "cancelto", - names: ["\\cancelto"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "cancelto", - mode: parser.mode, - value: args[0], - expression: args[1] - }; - }, - mathmlBuilder(group, style) { - const value = new mathMLTree.MathNode( - "mpadded", - [buildGroup$1(group.value, style)] - ); - value.setAttribute("depth", `-0.1em`); - value.setAttribute("height", `+0.1em`); - value.setAttribute("voffset", `0.1em`); - - const expression = new mathMLTree.MathNode( - "menclose", - [buildGroup$1(group.expression, style)] - ); - expression.setAttribute("notation", `updiagonalarrow`); - - return new mathMLTree.MathNode("msup", [expression, value]) - } -}); - -/** - * Asserts that the node is of the given type and returns it with stricter - * typing. Throws if the node's type does not match. - */ -function assertNodeType(node, type) { - if (!node || node.type !== type) { - throw new Error( - `Expected node of type ${type}, but got ` + - (node ? `node of type ${node.type}` : String(node)) - ); - } - return node; -} - -/** - * Returns the node more strictly typed iff it is of the given type. Otherwise, - * returns null. - */ -function assertSymbolNodeType(node) { - const typedNode = checkSymbolNodeType(node); - if (!typedNode) { - throw new Error( - `Expected node of symbol group type, but got ` + - (node ? `node of type ${node.type}` : String(node)) - ); - } - return typedNode; -} - -/** - * Returns the node more strictly typed iff it is of the given type. Otherwise, - * returns null. - */ -function checkSymbolNodeType(node) { - if (node && (node.type === "atom" || - Object.prototype.hasOwnProperty.call(NON_ATOMS, node.type))) { - return node; - } - return null; -} - -const cdArrowFunctionName = { - ">": "\\\\cdrightarrow", - "<": "\\\\cdleftarrow", - "=": "\\\\cdlongequal", - A: "\\uparrow", - V: "\\downarrow", - "|": "\\Vert", - ".": "no arrow" -}; - -const newCell = () => { - // Create an empty cell, to be filled below with parse nodes. - return { type: "styling", body: [], mode: "math", scriptLevel: "display" }; -}; - -const isStartOfArrow = (node) => { - return node.type === "textord" && node.text === "@"; -}; - -const isLabelEnd = (node, endChar) => { - return (node.type === "mathord" || node.type === "atom") && node.text === endChar; -}; - -function cdArrow(arrowChar, labels, parser) { - // Return a parse tree of an arrow and its labels. - // This acts in a way similar to a macro expansion. - const funcName = cdArrowFunctionName[arrowChar]; - switch (funcName) { - case "\\\\cdrightarrow": - case "\\\\cdleftarrow": - return parser.callFunction(funcName, [labels[0]], [labels[1]]); - case "\\uparrow": - case "\\downarrow": { - const leftLabel = parser.callFunction("\\\\cdleft", [labels[0]], []); - const bareArrow = { - type: "atom", - text: funcName, - mode: "math", - family: "rel" - }; - const sizedArrow = parser.callFunction("\\Big", [bareArrow], []); - const rightLabel = parser.callFunction("\\\\cdright", [labels[1]], []); - const arrowGroup = { - type: "ordgroup", - mode: "math", - body: [leftLabel, sizedArrow, rightLabel] - }; - return parser.callFunction("\\\\cdparent", [arrowGroup], []); - } - case "\\\\cdlongequal": - return parser.callFunction("\\\\cdlongequal", [], []); - case "\\Vert": { - const arrow = { type: "textord", text: "\\Vert", mode: "math" }; - return parser.callFunction("\\Big", [arrow], []); - } - default: - return { type: "textord", text: " ", mode: "math" }; - } -} - -function parseCD(parser) { - // Get the array's parse nodes with \\ temporarily mapped to \cr. - const parsedRows = []; - parser.gullet.beginGroup(); - parser.gullet.macros.set("\\cr", "\\\\\\relax"); - parser.gullet.beginGroup(); - while (true) { // eslint-disable-line no-constant-condition - // Get the parse nodes for the next row. - parsedRows.push(parser.parseExpression(false, "\\\\")); - parser.gullet.endGroup(); - parser.gullet.beginGroup(); - const next = parser.fetch().text; - if (next === "&" || next === "\\\\") { - parser.consume(); - } else if (next === "\\end") { - if (parsedRows[parsedRows.length - 1].length === 0) { - parsedRows.pop(); // final row ended in \\ - } - break; - } else { - throw new ParseError("Expected \\\\ or \\cr or \\end", parser.nextToken); - } - } - - let row = []; - const body = [row]; - - // Loop thru the parse nodes. Collect them into cells and arrows. - for (let i = 0; i < parsedRows.length; i++) { - // Start a new row. - const rowNodes = parsedRows[i]; - // Create the first cell. - let cell = newCell(); - - for (let j = 0; j < rowNodes.length; j++) { - if (!isStartOfArrow(rowNodes[j])) { - // If a parseNode is not an arrow, it goes into a cell. - cell.body.push(rowNodes[j]); - } else { - // Parse node j is an "@", the start of an arrow. - // Before starting on the arrow, push the cell into `row`. - row.push(cell); - - // Now collect parseNodes into an arrow. - // The character after "@" defines the arrow type. - j += 1; - const arrowChar = assertSymbolNodeType(rowNodes[j]).text; - - // Create two empty label nodes. We may or may not use them. - const labels = new Array(2); - labels[0] = { type: "ordgroup", mode: "math", body: [] }; - labels[1] = { type: "ordgroup", mode: "math", body: [] }; - - // Process the arrow. - if ("=|.".indexOf(arrowChar) > -1) ; else if ("<>AV".indexOf(arrowChar) > -1) { - // Four arrows, `@>>>`, `@<<<`, `@AAA`, and `@VVV`, each take - // two optional labels. E.g. the right-point arrow syntax is - // really: @>{optional label}>{optional label}> - // Collect parseNodes into labels. - for (let labelNum = 0; labelNum < 2; labelNum++) { - let inLabel = true; - for (let k = j + 1; k < rowNodes.length; k++) { - if (isLabelEnd(rowNodes[k], arrowChar)) { - inLabel = false; - j = k; - break; - } - if (isStartOfArrow(rowNodes[k])) { - throw new ParseError( - "Missing a " + arrowChar + " character to complete a CD arrow.", - rowNodes[k] - ); - } - - labels[labelNum].body.push(rowNodes[k]); - } - if (inLabel) { - // isLabelEnd never returned a true. - throw new ParseError( - "Missing a " + arrowChar + " character to complete a CD arrow.", - rowNodes[j] - ); - } - } - } else { - throw new ParseError(`Expected one of "<>AV=|." after @.`); - } - - // Now join the arrow to its labels. - const arrow = cdArrow(arrowChar, labels, parser); - - // Wrap the arrow in a styling node - row.push(arrow); - // In CD's syntax, cells are implicit. That is, everything that - // is not an arrow gets collected into a cell. So create an empty - // cell now. It will collect upcoming parseNodes. - cell = newCell(); - } - } - if (i % 2 === 0) { - // Even-numbered rows consist of: cell, arrow, cell, arrow, ... cell - // The last cell is not yet pushed into `row`, so: - row.push(cell); - } else { - // Odd-numbered rows consist of: vert arrow, empty cell, ... vert arrow - // Remove the empty cell that was placed at the beginning of `row`. - row.shift(); - } - row = []; - body.push(row); - } - - // End row group - parser.gullet.endGroup(); - // End array group defining \\ - parser.gullet.endGroup(); - - // define column separation. - const cols = new Array(body[0].length).fill({ - type: "align", - align: "c" - }); - - return { - type: "array", - mode: "math", - body, - arraystretch: 1, - addJot: true, - rowGaps: [null], - cols, - colSeparationType: "CD", - hLinesBeforeRow: new Array(body.length + 1).fill([]) - }; -} - -// The functions below are not available for general use. -// They are here only for internal use by the {CD} environment in placing labels -// next to vertical arrows. - -// We don't need any such functions for horizontal arrows because we can reuse -// the functionality that already exists for extensible arrows. - -defineFunction({ - type: "cdlabel", - names: ["\\\\cdleft", "\\\\cdright"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - return { - type: "cdlabel", - mode: parser.mode, - side: funcName.slice(4), - label: args[0] - }; - }, - mathmlBuilder(group, style) { - let label = new mathMLTree.MathNode("mrow", [buildGroup$1(group.label, style)]); - label = new mathMLTree.MathNode("mpadded", [label]); - label.setAttribute("width", "0"); - if (group.side === "left") { - label.setAttribute("lspace", "-1width"); - } - // We have to guess at vertical alignment. We know the arrow is 1.8em tall, - // But we don't know the height or depth of the label. - label.setAttribute("voffset", "0.7em"); - label = new mathMLTree.MathNode("mstyle", [label]); - label.setAttribute("displaystyle", "false"); - label.setAttribute("scriptlevel", "1"); - return label; - } -}); - -defineFunction({ - type: "cdlabelparent", - names: ["\\\\cdparent"], - props: { - numArgs: 1 - }, - handler({ parser }, args) { - return { - type: "cdlabelparent", - mode: parser.mode, - fragment: args[0] - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow", [buildGroup$1(group.fragment, style)]); - } -}); - -// \@char is an internal function that takes a grouped decimal argument like -// {123} and converts into symbol with code 123. It is used by the *macro* -// \char defined in macros.js. -defineFunction({ - type: "textord", - names: ["\\@char"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser, token }, args) { - const arg = assertNodeType(args[0], "ordgroup"); - const group = arg.body; - let number = ""; - for (let i = 0; i < group.length; i++) { - const node = assertNodeType(group[i], "textord"); - number += node.text; - } - const code = parseInt(number); - if (isNaN(code)) { - throw new ParseError(`\\@char has non-numeric argument ${number}`, token) - } - return { - type: "textord", - mode: parser.mode, - text: String.fromCodePoint(code) - } - } -}); - -// Helpers -const htmlRegEx = /^(#[a-f0-9]{3}|#?[a-f0-9]{6})$/i; -const htmlOrNameRegEx = /^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i; -const RGBregEx = /^ *\d{1,3} *(?:, *\d{1,3} *){2}$/; -const rgbRegEx = /^ *[10](?:\.\d*)? *(?:, *[10](?:\.\d*)? *){2}$/; -const xcolorHtmlRegEx = /^[a-f0-9]{6}$/i; -const toHex = num => { - let str = num.toString(16); - if (str.length === 1) { str = "0" + str; } - return str -}; - -// Colors from Tables 4.1 and 4.2 of the xcolor package. -// Table 4.1 (lower case) RGB values are taken from chroma and xcolor.dtx. -// Table 4.2 (Capitalizzed) values were sampled, because Chroma contains a unreliable -// conversion from cmyk to RGB. See https://tex.stackexchange.com/a/537274. -const xcolors = JSON.parse(`{ - "Apricot": "#ffb484", - "Aquamarine": "#08b4bc", - "Bittersweet": "#c84c14", - "blue": "#0000FF", - "Blue": "#303494", - "BlueGreen": "#08b4bc", - "BlueViolet": "#503c94", - "BrickRed": "#b8341c", - "brown": "#BF8040", - "Brown": "#802404", - "BurntOrange": "#f8941c", - "CadetBlue": "#78749c", - "CarnationPink": "#f884b4", - "Cerulean": "#08a4e4", - "CornflowerBlue": "#40ace4", - "cyan": "#00FFFF", - "Cyan": "#08acec", - "Dandelion": "#ffbc44", - "darkgray": "#404040", - "DarkOrchid": "#a8548c", - "Emerald": "#08ac9c", - "ForestGreen": "#089c54", - "Fuchsia": "#90348c", - "Goldenrod": "#ffdc44", - "gray": "#808080", - "Gray": "#98949c", - "green": "#00FF00", - "Green": "#08a44c", - "GreenYellow": "#e0e474", - "JungleGreen": "#08ac9c", - "Lavender": "#f89cc4", - "lightgray": "#c0c0c0", - "lime": "#BFFF00", - "LimeGreen": "#90c43c", - "magenta": "#FF00FF", - "Magenta": "#f0048c", - "Mahogany": "#b0341c", - "Maroon": "#b03434", - "Melon": "#f89c7c", - "MidnightBlue": "#086494", - "Mulberry": "#b03c94", - "NavyBlue": "#086cbc", - "olive": "#7F7F00", - "OliveGreen": "#407c34", - "orange": "#FF8000", - "Orange": "#f8843c", - "OrangeRed": "#f0145c", - "Orchid": "#b074ac", - "Peach": "#f8945c", - "Periwinkle": "#8074bc", - "PineGreen": "#088c74", - "pink": "#ff7f7f", - "Plum": "#98248c", - "ProcessBlue": "#08b4ec", - "purple": "#BF0040", - "Purple": "#a0449c", - "RawSienna": "#983c04", - "red": "#ff0000", - "Red": "#f01c24", - "RedOrange": "#f86434", - "RedViolet": "#a0246c", - "Rhodamine": "#f0549c", - "Royallue": "#0874bc", - "RoyalPurple": "#683c9c", - "RubineRed": "#f0047c", - "Salmon": "#f8948c", - "SeaGreen": "#30bc9c", - "Sepia": "#701404", - "SkyBlue": "#48c4dc", - "SpringGreen": "#c8dc64", - "Tan": "#e09c74", - "teal": "#007F7F", - "TealBlue": "#08acb4", - "Thistle": "#d884b4", - "Turquoise": "#08b4cc", - "violet": "#800080", - "Violet": "#60449c", - "VioletRed": "#f054a4", - "WildStrawberry": "#f0246c", - "yellow": "#FFFF00", - "Yellow": "#fff404", - "YellowGreen": "#98cc6c", - "YellowOrange": "#ffa41c" -}`); - -const colorFromSpec = (model, spec) => { - let color = ""; - if (model === "HTML") { - if (!htmlRegEx.test(spec)) { - throw new ParseError("Invalid HTML input.") - } - color = spec; - } else if (model === "RGB") { - if (!RGBregEx.test(spec)) { - throw new ParseError("Invalid RGB input.") - } - spec.split(",").map(e => { color += toHex(Number(e.trim())); }); - } else { - if (!rgbRegEx.test(spec)) { - throw new ParseError("Invalid rbg input.") - } - spec.split(",").map(e => { - const num = Number(e.trim()); - if (num > 1) { throw new ParseError("Color rgb input must be < 1.") } - color += toHex((num * 255)); - }); - } - if (color.charAt(0) !== "#") { color = "#" + color; } - return color -}; - -const validateColor = (color, macros, token) => { - const macroName = `\\\\color@${color}`; // from \defineColor. - const match = htmlOrNameRegEx.exec(color); - if (!match) { throw new ParseError("Invalid color: '" + color + "'", token) } - // We allow a 6-digit HTML color spec without a leading "#". - // This follows the xcolor package's HTML color model. - // Predefined color names are all missed by this RegEx pattern. - if (xcolorHtmlRegEx.test(color)) { - return "#" + color - } else if (color.charAt(0) === "#") { - return color - } else if (macros.has(macroName)) { - color = macros.get(macroName).tokens[0].text; - } else if (xcolors[color]) { - color = xcolors[color]; - } - return color -}; - -const mathmlBuilder$9 = (group, style) => { - const inner = buildExpression(group.body, style.withColor(group.color)); - // Wrap with an element. - const node = wrapWithMstyle(inner); - node.setAttribute("mathcolor", group.color); - // Wrap w/. We get better operator spacing that way. - return new mathMLTree.MathNode("mrow", [node]) -}; - -defineFunction({ - type: "color", - names: ["\\textcolor"], - props: { - numArgs: 2, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "original"] - }, - handler({ parser, token }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let color = ""; - if (model) { - const spec = assertNodeType(args[0], "raw").string; - color = colorFromSpec(model, spec); - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros, token); - } - const body = args[1]; - return { - type: "color", - mode: parser.mode, - color, - body: ordargument(body) - } - }, - mathmlBuilder: mathmlBuilder$9 -}); - -defineFunction({ - type: "color", - names: ["\\color"], - props: { - numArgs: 1, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw"] - }, - handler({ parser, token }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let color = ""; - if (model) { - const spec = assertNodeType(args[0], "raw").string; - color = colorFromSpec(model, spec); - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros, token); - } - - // Set macro \current@color in current namespace to store the current - // color, mimicking the behavior of color.sty. - // This is currently used just to correctly color a \right - // that follows a \color command. - parser.gullet.macros.set("\\current@color", color); - - // Parse out the implicit body that should be colored. - // Since \color nodes should not be nested, break on \color. - const body = parser.parseExpression(true, "\\color"); - - return { - type: "color", - mode: parser.mode, - color, - body - } - }, - mathmlBuilder: mathmlBuilder$9 -}); - -defineFunction({ - type: "color", - names: ["\\definecolor"], - props: { - numArgs: 3, - allowedInText: true, - argTypes: ["raw", "raw", "raw"] - }, - handler({ parser, funcName, token }, args) { - const name = assertNodeType(args[0], "raw").string; - if (!/^[A-Za-z]+$/.test(name)) { - throw new ParseError("Color name must be latin letters.", token) - } - const model = assertNodeType(args[1], "raw").string; - if (!["HTML", "RGB", "rgb"].includes(model)) { - throw new ParseError("Color model must be HTML, RGB, or rgb.", token) - } - const spec = assertNodeType(args[2], "raw").string; - const color = colorFromSpec(model, spec); - parser.gullet.macros.set(`\\\\color@${name}`, { tokens: [{ text: color }], numArgs: 0 }); - return { type: "internal", mode: parser.mode } - } - // No mathmlBuilder. The point of \definecolor is to set a macro. -}); - -// Row breaks within tabular environments, and line breaks at top level - -// \DeclareRobustCommand\\{...\@xnewline} -defineFunction({ - type: "cr", - names: ["\\\\"], - props: { - numArgs: 0, - numOptionalArgs: 1, - argTypes: ["size"], - allowedInText: true - }, - - handler({ parser }, args, optArgs) { - const size = optArgs[0]; - const newLine = !parser.settings.displayMode; - return { - type: "cr", - mode: parser.mode, - newLine, - size: size && assertNodeType(size, "size").value - } - }, - - // The following builder is called only at the top level, - // not within tabular/array environments. - - mathmlBuilder(group, style) { - // MathML 3.0 calls for newline to occur in an or an . - // Ref: https://www.w3.org/TR/MathML3/chapter3.html#presm.linebreaking - const node = new mathMLTree.MathNode("mo"); - if (group.newLine) { - node.setAttribute("linebreak", "newline"); - if (group.size) { - const size = calculateSize(group.size, style); - node.setAttribute("height", size.number + size.unit); - } - } - return node - } -}); - -const checkControlSequence = (tok) => { - const name = tok.text; - if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { - throw new ParseError("Expected a control sequence", tok); - } - return name; -}; - -const getRHS = (parser) => { - let tok = parser.gullet.popToken(); - if (tok.text === "=") { - // consume optional equals - tok = parser.gullet.popToken(); - if (tok.text === " ") { - // consume one optional space - tok = parser.gullet.popToken(); - } - } - return tok; -}; - -const letCommand = (parser, name, tok) => { - let macro = parser.gullet.macros.get(tok.text); - if (macro == null) { - // don't expand it later even if a macro with the same name is defined - // e.g., \let\foo=\frac \def\frac{\relax} \frac12 - tok.noexpand = true; - macro = { - tokens: [tok], - numArgs: 0, - // reproduce the same behavior in expansion - unexpandable: !parser.gullet.isExpandable(tok.text) - }; - } - parser.gullet.macros.set(name, macro); -}; - -// Basic support for macro definitions: \def -// -> -// -> -defineFunction({ - type: "internal", - names: ["\\def", "\\edef"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - let tok = parser.gullet.popToken(); - const name = tok.text; - if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { - throw new ParseError("Expected a control sequence", tok); - } - - let numArgs = 0; - let insert; - const delimiters = [[]]; - // contains no braces - while (parser.gullet.future().text !== "{") { - tok = parser.gullet.popToken(); - if (tok.text === "#") { - // If the very last character of the is #, so that - // this # is immediately followed by {, TeX will behave as if the { - // had been inserted at the right end of both the parameter text - // and the replacement text. - if (parser.gullet.future().text === "{") { - insert = parser.gullet.future(); - delimiters[numArgs].push("{"); - break; - } - - // A parameter, the first appearance of # must be followed by 1, - // the next by 2, and so on; up to nine #’s are allowed - tok = parser.gullet.popToken(); - if (!/^[1-9]$/.test(tok.text)) { - throw new ParseError(`Invalid argument number "${tok.text}"`); - } - if (parseInt(tok.text) !== numArgs + 1) { - throw new ParseError(`Argument number "${tok.text}" out of order`); - } - numArgs++; - delimiters.push([]); - } else if (tok.text === "EOF") { - throw new ParseError("Expected a macro definition"); - } else { - delimiters[numArgs].push(tok.text); - } - } - // replacement text, enclosed in '{' and '}' and properly nested - let { tokens } = parser.gullet.consumeArg(); - if (insert) { - tokens.unshift(insert); - } - - if (funcName === "\\edef") { - tokens = parser.gullet.expandTokens(tokens); - tokens.reverse(); // to fit in with stack order - } - // Final arg is the expansion of the macro - parser.gullet.macros.set(name, { tokens, numArgs, delimiters } - ); - return { type: "internal", mode: parser.mode }; - } -}); - -// -> -// -> \futurelet -// | \let -// -> |= -defineFunction({ - type: "internal", - names: ["\\let"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - const name = checkControlSequence(parser.gullet.popToken()); - parser.gullet.consumeSpaces(); - const tok = getRHS(parser); - letCommand(parser, name, tok); - return { type: "internal", mode: parser.mode }; - } -}); - -// ref: https://www.tug.org/TUGboat/tb09-3/tb22bechtolsheim.pdf -defineFunction({ - type: "internal", - names: ["\\futurelet"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - const name = checkControlSequence(parser.gullet.popToken()); - const middle = parser.gullet.popToken(); - const tok = parser.gullet.popToken(); - letCommand(parser, name, tok); - parser.gullet.pushToken(tok); - parser.gullet.pushToken(middle); - return { type: "internal", mode: parser.mode }; - } -}); - -defineFunction({ - type: "internal", - names: ["\\newcommand", "\\renewcommand", "\\providecommand"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - let name = ""; - const tok = parser.gullet.popToken(); - if (tok.text === "{") { - name = checkControlSequence(parser.gullet.popToken()); - parser.gullet.popToken(); - } else { - name = checkControlSequence(tok); - } - - const exists = parser.gullet.isDefined(name); - if (exists && funcName === "\\newcommand") { - throw new ParseError( - `\\newcommand{${name}} attempting to redefine ${name}; use \\renewcommand` - ); - } - if (!exists && funcName === "\\renewcommand") { - throw new ParseError( - `\\renewcommand{${name}} when command ${name} does not yet exist; use \\newcommand` - ); - } - - let numArgs = 0; - if (parser.gullet.future().text === "[") { - let tok = parser.gullet.popToken(); - tok = parser.gullet.popToken(); - if (!/^[0-9]$/.test(tok.text)) { - throw new ParseError(`Invalid number of arguments: "${tok.text}"`); - } - numArgs = parseInt(tok.text); - tok = parser.gullet.popToken(); - if (tok.text !== "]") { - throw new ParseError(`Invalid argument "${tok.text}"`); - } - } - - // replacement text, enclosed in '{' and '}' and properly nested - const { tokens } = parser.gullet.consumeArg(); - - parser.gullet.macros.set(name, { tokens, numArgs }); - - return { type: "internal", mode: parser.mode }; - - } -}); - -// Extra data needed for the delimiter handler down below -const delimiterSizes = { - "\\bigl": { mclass: "mopen", size: 1 }, - "\\Bigl": { mclass: "mopen", size: 2 }, - "\\biggl": { mclass: "mopen", size: 3 }, - "\\Biggl": { mclass: "mopen", size: 4 }, - "\\bigr": { mclass: "mclose", size: 1 }, - "\\Bigr": { mclass: "mclose", size: 2 }, - "\\biggr": { mclass: "mclose", size: 3 }, - "\\Biggr": { mclass: "mclose", size: 4 }, - "\\bigm": { mclass: "mrel", size: 1 }, - "\\Bigm": { mclass: "mrel", size: 2 }, - "\\biggm": { mclass: "mrel", size: 3 }, - "\\Biggm": { mclass: "mrel", size: 4 }, - "\\big": { mclass: "mord", size: 1 }, - "\\Big": { mclass: "mord", size: 2 }, - "\\bigg": { mclass: "mord", size: 3 }, - "\\Bigg": { mclass: "mord", size: 4 } -}; - -const delimiters = [ - "(", - "\\lparen", - ")", - "\\rparen", - "[", - "\\lbrack", - "]", - "\\rbrack", - "\\{", - "\\lbrace", - "\\}", - "\\rbrace", - "\\lfloor", - "\\rfloor", - "\u230a", - "\u230b", - "\\lceil", - "\\rceil", - "\u2308", - "\u2309", - "<", - ">", - "\\langle", - "\u27e8", - "\\rangle", - "\u27e9", - "\\lt", - "\\gt", - "\\lvert", - "\\rvert", - "\\lVert", - "\\rVert", - "\\lgroup", - "\\rgroup", - "\u27ee", - "\u27ef", - "\\lmoustache", - "\\rmoustache", - "\u23b0", - "\u23b1", - "\\llbracket", - "\\rrbracket", - "\u27e6", - "\u27e6", - "\\lBrace", - "\\rBrace", - "\u2983", - "\u2984", - "/", - "\\backslash", - "|", - "\\vert", - "\\|", - "\\Vert", - "\\uparrow", - "\\Uparrow", - "\\downarrow", - "\\Downarrow", - "\\updownarrow", - "\\Updownarrow", - "." -]; - -// Metrics of the different sizes. Found by looking at TeX's output of -// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$ -// Used to create stacked delimiters of appropriate sizes in makeSizedDelim. -const sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0]; - -// Delimiter functions -function checkDelimiter(delim, context) { - if (delim.type === "ordgroup" && delim.body.length === 1 && delim.body[0].text === "\u2044") { - // Recover "/" from the zero spacing group. (See macros.js) - delim = { type: "textord", text: "/", mode: "math" }; - } - const symDelim = checkSymbolNodeType(delim); - if (symDelim && utils.contains(delimiters, symDelim.text)) { - // If a character is not in the MathML operator dictionary, it will not stretch. - // Replace such characters w/characters that will stretch. - if (utils.contains(["<", "\\lt"], symDelim.text)) { symDelim.text = "⟨"; } - if (utils.contains([">", "\\gt"], symDelim.text)) { symDelim.text = "⟩"; } - if (symDelim.text === "/") { symDelim.text = "\u2215"; } - if (symDelim.text === "\\backslash") { symDelim.text = "\u2216"; } - return symDelim; - } else if (symDelim) { - throw new ParseError(`Invalid delimiter '${symDelim.text}' after '${context.funcName}'`, delim); - } else { - throw new ParseError(`Invalid delimiter type '${delim.type}'`, delim); - } -} - -defineFunction({ - type: "delimsizing", - names: [ - "\\bigl", - "\\Bigl", - "\\biggl", - "\\Biggl", - "\\bigr", - "\\Bigr", - "\\biggr", - "\\Biggr", - "\\bigm", - "\\Bigm", - "\\biggm", - "\\Biggm", - "\\big", - "\\Big", - "\\bigg", - "\\Bigg" - ], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - - return { - type: "delimsizing", - mode: context.parser.mode, - size: delimiterSizes[context.funcName].size, - mclass: delimiterSizes[context.funcName].mclass, - delim: delim.text - }; - }, - mathmlBuilder: (group) => { - const children = []; - - if (group.delim === ".") { group.delim = ""; } - children.push(makeText(group.delim, group.mode)); - - const node = new mathMLTree.MathNode("mo", children); - - if (group.mclass === "mopen" || group.mclass === "mclose") { - // Only some of the delimsizing functions act as fences, and they - // return "mopen" or "mclose" mclass. - node.setAttribute("fence", "true"); - } else { - // Explicitly disable fencing if it's not a fence, to override the - // defaults. - node.setAttribute("fence", "false"); - } - if (group.delim === "\u2216") { - // \backslash is not in the operator dictionary, - // so we have to explicitly set stretchy to true. - node.setAttribute("stretchy", "true"); - } - - node.setAttribute("symmetric", "true"); // Needed for tall arrows in Firefox. - node.setAttribute("minsize", sizeToMaxHeight[group.size] + "em"); - node.setAttribute("maxsize", sizeToMaxHeight[group.size] + "em"); - - return node; - } -}); - -function assertParsed(group) { - if (!group.body) { - throw new Error("Bug: The leftright ParseNode wasn't fully parsed."); - } -} - -defineFunction({ - type: "leftright-right", - names: ["\\right"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - // \left case below triggers parsing of \right in - // `const right = parser.parseFunction();` - // uses this return value. - const color = context.parser.gullet.macros.get("\\current@color"); - if (color && typeof color !== "string") { - throw new ParseError("\\current@color set to non-string in \\right"); - } - return { - type: "leftright-right", - mode: context.parser.mode, - delim: checkDelimiter(args[0], context).text, - color // undefined if not set via \color - }; - } -}); - -defineFunction({ - type: "leftright", - names: ["\\left"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - - const parser = context.parser; - // Parse out the implicit body - ++parser.leftrightDepth; - // parseExpression stops before '\\right' - const body = parser.parseExpression(false); - --parser.leftrightDepth; - // Check the next token - parser.expect("\\right", false); - const right = assertNodeType(parser.parseFunction(), "leftright-right"); - return { - type: "leftright", - mode: parser.mode, - body, - left: delim.text, - right: right.delim, - rightColor: right.color - }; - }, - mathmlBuilder: (group, style) => { - assertParsed(group); - const inner = buildExpression(group.body, style); - - if (group.left === ".") { group.left = ""; } - const leftNode = new mathMLTree.MathNode("mo", [makeText(group.left, group.mode)]); - leftNode.setAttribute("fence", "true"); - leftNode.setAttribute("form", "prefix"); - if (group.left === "\u2216") { leftNode.setAttribute("stretchy", "true"); } - inner.unshift(leftNode); - - if (group.right === ".") { group.right = ""; } - const rightNode = new mathMLTree.MathNode("mo", [makeText(group.right, group.mode)]); - rightNode.setAttribute("fence", "true"); - rightNode.setAttribute("form", "postfix"); - if (group.right === "\u2216") { rightNode.setAttribute("stretchy", "true"); } - if (group.rightColor) { rightNode.setAttribute("mathcolor", group.rightColor); } - inner.push(rightNode); - - return makeRow(inner); - } -}); - -defineFunction({ - type: "middle", - names: ["\\middle"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - if (!context.parser.leftrightDepth) { - throw new ParseError("\\middle without preceding \\left", delim); - } - - return { - type: "middle", - mode: context.parser.mode, - delim: delim.text - }; - }, - mathmlBuilder: (group, style) => { - const textNode = makeText(group.delim, group.mode); - const middleNode = new mathMLTree.MathNode("mo", [textNode]); - middleNode.setAttribute("fence", "true"); - // MathML gives 5/18em spacing to each element. - // \middle should get delimiter spacing instead. - middleNode.setAttribute("lspace", "0.05em"); - middleNode.setAttribute("rspace", "0.05em"); - return middleNode; - } -}); - -const mathmlBuilder$8 = (group, style) => { - const node = new mathMLTree.MathNode( - group.label.indexOf("colorbox") > -1 ? "mpadded" : "menclose", - [buildGroup$1(group.body, style)] - ); - switch (group.label) { - case "\\cancel": - node.setAttribute("notation", "updiagonalstrike"); - break; - case "\\bcancel": - node.setAttribute("notation", "downdiagonalstrike"); - break; - case "\\longdiv": - node.setAttribute("notation", "longdiv"); - break; - case "\\phase": - node.setAttribute("notation", "phasorangle"); - break; - case "\\sout": - node.setAttribute("notation", "horizontalstrike"); - break; - case "\\fbox": - node.setAttribute("notation", "box"); - break; - case "\\angl": - node.setAttribute("notation", "actuarial"); - break; - case "\\fcolorbox": - case "\\colorbox": { - // doesn't have a good notation option for \colorbox. - // So use instead. Set some attributes that come - // included with . - const fboxsep = 3; // 3 pt from LaTeX source2e - node.setAttribute("width", `+${2 * fboxsep}pt`); - node.setAttribute("height", `+${2 * fboxsep}pt`); - node.setAttribute("lspace", `${fboxsep}pt`); // - node.setAttribute("voffset", `${fboxsep}pt`); - if (group.label === "\\fcolorbox") { - node.setAttribute("style", "border: 0.06em solid " + String(group.borderColor)); - } - break; - } - case "\\xcancel": - node.setAttribute("notation", "updiagonalstrike downdiagonalstrike"); - break; - } - if (group.backgroundColor) { - node.setAttribute("mathbackground", group.backgroundColor); - } - return node; -}; - -defineFunction({ - type: "enclose", - names: ["\\colorbox"], - props: { - numArgs: 2, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "text"] - }, - handler({ parser, funcName }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let color = ""; - if (model) { - const spec = assertNodeType(args[0], "raw").string; - color = colorFromSpec(model, spec); - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros); - } - const body = args[1]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - backgroundColor: color, - body - }; - }, - mathmlBuilder: mathmlBuilder$8 -}); - -defineFunction({ - type: "enclose", - names: ["\\fcolorbox"], - props: { - numArgs: 3, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "raw", "text"] - }, - handler({ parser, funcName }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let borderColor = ""; - let backgroundColor; - if (model) { - const borderSpec = assertNodeType(args[0], "raw").string; - const backgroundSpec = assertNodeType(args[0], "raw").string; - borderColor = colorFromSpec(model, borderSpec); - backgroundColor = colorFromSpec(model, backgroundSpec); - } else { - borderColor = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros); - backgroundColor = validateColor(assertNodeType(args[1], "raw").string, parser.gullet.macros); - } - const body = args[2]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - backgroundColor, - borderColor, - body - }; - }, - mathmlBuilder: mathmlBuilder$8 -}); - -defineFunction({ - type: "enclose", - names: ["\\fbox"], - props: { - numArgs: 1, - argTypes: ["hbox"], - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "enclose", - mode: parser.mode, - label: "\\fbox", - body: args[0] - }; - } -}); - -defineFunction({ - type: "enclose", - names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\angl", "\\phase", "\\longdiv"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - const body = args[0]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - body - }; - }, - mathmlBuilder: mathmlBuilder$8 -}); - -/** - * All registered environments. - * `environments.js` exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary via `environments.js`. - */ -const _environments = {}; - -function defineEnvironment({ type, names, props, handler, mathmlBuilder }) { - // Set default values of environments. - const data = { - type, - numArgs: props.numArgs || 0, - allowedInText: false, - numOptionalArgs: 0, - handler - }; - for (let i = 0; i < names.length; ++i) { - _environments[names[i]] = data; - } - if (mathmlBuilder) { - _mathmlGroupBuilders[type] = mathmlBuilder; - } -} - -// In TeX, there are actually three sets of dimensions, one for each of - -// Math style is not quite the same thing as script level. -const StyleLevel = { - DISPLAY: 0, - TEXT: 1, - SCRIPT: 2, - SCRIPTSCRIPT: 3 -}; - -// Helper functions -function getHLines(parser) { - // Return an array. The array length = number of hlines. - // Each element in the array tells if the line is dashed. - const hlineInfo = []; - parser.consumeSpaces(); - let nxt = parser.fetch().text; - while (nxt === "\\hline" || nxt === "\\hdashline") { - parser.consume(); - hlineInfo.push(nxt === "\\hdashline"); - parser.consumeSpaces(); - nxt = parser.fetch().text; - } - return hlineInfo; -} - -const validateAmsEnvironmentContext = context => { - const settings = context.parser.settings; - if (!settings.displayMode) { - throw new ParseError(`{${context.envName}} can be used only in display mode.`); - } -}; - -const getTag = (group, style, rowNum) => { - let tag; - const tagContents = group.tags.shift(); - if (tagContents) { - // The author has written a \tag or a \notag in this row. - if (tagContents.body) { - tag = buildExpressionRow(tagContents.body, style); - tag.classes = ["tml-tag"]; - } else { - // \notag. Return an empty cell. - tag = new mathMLTree.MathNode("mtd", []); - tag.setAttribute("style", "padding: 0; min-width:0"); - return tag - } - } else if (group.colSeparationType === "multline" && - ((group.leqno && rowNum !== 0) || (!group.leqno && rowNum !== group.body.length - 1))) { - // A multiline that does not receive a tag. Return an empty cell. - tag = new mathMLTree.MathNode("mtd", []); - tag.setAttribute("style", "padding: 0; min-width:0"); - return tag - } else { - // AMS automatcally numbered equaton. - // Insert a class so the element can be populated by a post-processor. - tag = new mathMLTree.MathNode("mtext", [], ["tml-eqn"]); - } - if (!group.preventTagLap) { - tag = new mathMLTree.MathNode("mpadded", [tag]); - tag.setAttribute("style", "width:0;"); - tag.setAttribute("width", "0"); - if (!group.leqno) { tag.setAttribute("lspace", "-1width"); } - } - tag = new mathMLTree.MathNode("mtd", [tag]); - if (!group.preventTagLap) { tag.setAttribute("style", "padding: 0; min-width:0"); } - return tag -}; - -/** - * Parse the body of the environment, with rows delimited by \\ and - * columns delimited by &, and create a nested list in row-major order - * with one group per cell. If given an optional argument scriptLevel - * ("text", "display", etc.), then each cell is cast into that scriptLevel. - */ -function parseArray( - parser, - { - hskipBeforeAndAfter, // boolean - addJot, // boolean - cols, // [{ type: string , align: l|c|r|null }] - arraystretch, // number - colSeparationType, // "align" | "alignat" | "gather" | "small" | "CD" | "multline" - addEqnNum, // boolean - singleRow, // boolean - emptySingleRow, // boolean - maxNumCols, // number - leqno // boolean - }, - scriptLevel -) { - parser.gullet.beginGroup(); - if (!singleRow) { - // \cr is equivalent to \\ without the optional size argument (see below) - // TODO: provide helpful error when \cr is used outside array environment - parser.gullet.macros.set("\\cr", "\\\\\\relax"); - } - if (addEqnNum) { - parser.gullet.macros.set("\\tag", "\\env@tag{\\text{#1}}"); - parser.gullet.macros.set("\\notag", "\\env@notag"); - parser.gullet.macros.set("\\nonumber", "\\env@notag"); - } - - // Get current arraystretch if it's not set by the environment - if (arraystretch === undefined || Number.isNaN(arraystretch)) { - const stretch = parser.gullet.expandMacroAsText("\\arraystretch"); - if (stretch == null) { - // Default \arraystretch from lttab.dtx - arraystretch = 1; - } else { - arraystretch = parseFloat(stretch); - if (!arraystretch || arraystretch < 0) { - throw new ParseError(`Invalid \\arraystretch: ${stretch}`); - } - } - } - - // Start group for first cell - parser.gullet.beginGroup(); - - let row = []; - const body = [row]; - const rowGaps = []; - const tags = []; - let rowTag; - const hLinesBeforeRow = []; - - // Test for \hline at the top of the array. - hLinesBeforeRow.push(getHLines(parser)); - - // eslint-disable-next-line no-constant-condition - while (true) { - // Parse each cell in its own group (namespace) - let cell = parser.parseExpression(false, singleRow ? "\\end" : "\\\\"); - - if (addEqnNum && !rowTag) { - // Check if the author wrote a \tag{} inside this cell. - for (let i = 0; i < cell.length; i++) { - if (cell[i].type === "envTag" || cell[i].type === "noTag") { - // Get the contents of the \text{} nested inside the \env@Tag{} - rowTag = cell[i].type === "envTag" - ? cell.splice(i, 1)[0].body.body[0] - : { body: null }; - break - } - } - } - parser.gullet.endGroup(); - parser.gullet.beginGroup(); - - cell = { - type: "ordgroup", - mode: parser.mode, - body: cell - }; - row.push(cell); - const next = parser.fetch().text; - if (next === "&") { - if (maxNumCols && row.length === maxNumCols) { - if (colSeparationType === "split") { - throw new ParseError("The split environment accepts no more than two columns", - parser.nextToken); - } else if (colSeparationType === "array") { - if (parser.settings.strict) { - throw new ParseError("Too few columns " + "specified in the {array} column argument.", - parser.nextToken) - } - } else { - throw new ParseError("The equation environment accepts only one column", - parser.nextToken) - } - } - parser.consume(); - } else if (next === "\\end") { - // Arrays terminate newlines with `\crcr` which consumes a `\cr` if - // the last line is empty. However, AMS environments keep the - // empty row if it's the only one. - // NOTE: Currently, `cell` is the last item added into `row`. - if (row.length === 1 && cell.body.length === 0 && (body.length > 1 || !emptySingleRow)) { - body.pop(); - } - if (hLinesBeforeRow.length < body.length + 1) { - hLinesBeforeRow.push([]); - } - break; - } else if (next === "\\\\") { - parser.consume(); - let size; - // \def\Let@{\let\\\math@cr} - // \def\math@cr{...\math@cr@} - // \def\math@cr@{\new@ifnextchar[\math@cr@@{\math@cr@@[\z@]}} - // \def\math@cr@@[#1]{...\math@cr@@@...} - // \def\math@cr@@@{\cr} - if (parser.gullet.future().text !== " ") { - size = parser.parseSizeGroup(true); - } - rowGaps.push(size ? size.value : null); - - tags.push(rowTag); - - // check for \hline(s) following the row separator - hLinesBeforeRow.push(getHLines(parser)); - - row = []; - rowTag = null; - body.push(row); - } else { - throw new ParseError("Expected & or \\\\ or \\cr or \\end", parser.nextToken); - } - } - - // End cell group - parser.gullet.endGroup(); - // End array group defining \cr - parser.gullet.endGroup(); - - tags.push(rowTag); - - return { - type: "array", - mode: parser.mode, - addJot, - arraystretch, - body, - cols, - rowGaps, - hskipBeforeAndAfter, - hLinesBeforeRow, - colSeparationType, - addEqnNum, - scriptLevel, - tags, - leqno, - preventTagLap: parser.settings.preventTagLap - }; -} - -// Decides on a scriptLevel for cells in an array according to whether the given -// environment name starts with the letter 'd'. -function dCellStyle(envName) { - return envName.slice(0, 1) === "d" ? "display" : "text" -} - -const alignMap = { - c: "center ", - l: "left ", - r: "right " -}; - -const mathmlBuilder$7 = function(group, style) { - const tbl = []; - const numRows = group.body.length; - let glue; - if (group.addEqnNum) { - glue = new mathMLTree.MathNode("mtd", [], []); - const glueStyle = "padding: 0;width: " + - (group.colSeparationType === "multline" ? "7.5%" : "50%"); - glue.setAttribute("style", glueStyle); - } - - for (let i = 0; i < numRows; i++) { - const rw = group.body[i]; - const row = []; - const cellStyle = group.scriptLevel === "text" - ? StyleLevel.TEXT - : group.scriptLevel === "script" - ? StyleLevel.SCRIPT - : StyleLevel.DISPLAY; - - for (let j = 0; j < rw.length; j++) { - const mtd = new mathMLTree.MathNode( - "mtd", - [buildGroup$1(rw[j], style.withLevel(cellStyle))] - ); - if (group.colSeparationType === "multline") { - const align = i === 0 ? "left" : i === numRows - 1 ? "right" : "center"; - mtd.setAttribute("columnalign", align); - } - row.push(mtd); - } - if (group.addEqnNum) { - row.unshift(glue); - row.push(glue); - const tag = getTag(group, style.withLevel(cellStyle), i); - if (group.leqno) { - row.unshift(tag); - } else { - row.push(tag); - } - } - // If group.addEqnNum, insert a breadcrumb to be found by temmlPostProcess(). - tbl.push(new mathMLTree.MathNode("mtr", row, group.addEqnNum ? ["tml-tageqn"] : [] )); - } - let table = new mathMLTree.MathNode("mtable", tbl); - if (group.scriptLevel === "display") { table.setAttribute("displaystyle", "true"); } - - // Set column alignment, row spacing, column spacing, and - // array lines by setting attributes on the table element. - - // Set the row spacing. In MathML, we specify a gap distance. - // We do not use rowGap[] because MathML automatically increases - // cell height with the height/depth of the element content. - - // LaTeX \arraystretch multiplies the row baseline-to-baseline distance. - // We simulate this by adding (arraystretch - 1)em to the gap. This - // does a reasonable job of adjusting arrays containing 1 em tall content. - - // The 0.16 and 0.09 values are found emprically. They produce an array - // similar to LaTeX and in which content does not interfere with \hines. - const gap = - group.arraystretch === 0 - ? 0 // {subarray} - : group.arraystretch === 0.5 - ? 0.1 // {smallmatrix} - : 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0); - table.setAttribute("rowspacing", utils.round(gap) + "em"); - - if (group.addEqnNum || group.colSeparationType === "multline") { - table.setAttribute("width", "100%"); - } - - // MathML table lines go only between cells. - // To place a line on an edge we'll use , if necessary. - let menclose = ""; - let align = ""; - - if (group.cols && group.cols.length > 0) { - // Find column alignment, column spacing, and vertical lines. - const cols = group.cols; - let columnLines = ""; - let prevTypeWasAlign = false; - let iStart = 0; - let iEnd = cols.length; - - if (cols[0].type === "separator") { - menclose += "left "; - iStart = 1; - } - if (cols[cols.length - 1].type === "separator") { - menclose += "right "; - iEnd -= 1; - } - - for (let i = iStart; i < iEnd; i++) { - if (cols[i].type === "align") { - align += alignMap[cols[i].align]; - - if (prevTypeWasAlign) { - columnLines += "none "; - } - prevTypeWasAlign = true; - } else if (cols[i].type === "separator") { - // MathML accepts only single lines between cells. - // So we read only the first of consecutive separators. - if (prevTypeWasAlign) { - columnLines += cols[i].separator === "|" ? "solid " : "dashed "; - prevTypeWasAlign = false; - } - } - } - if (group.addEqnNum) { - align = "left " + align + "right "; // allow for glue cells on each side - align = group.leqno ? "left " + align : align += "right"; // eqn num cell - } - - table.setAttribute("columnalign", align.trim()); - - if (/[sd]/.test(columnLines)) { - table.setAttribute("columnlines", columnLines.trim()); - } - } - - // Set column spacing. - switch (group.colSeparationType) { - case "gather": - case "gathered": - case "alignedat": - case "alignat": - case "alignat*": - table.setAttribute("columnspacing", "0em"); - break - case "small": - table.setAttribute("columnspacing", "0.2778em"); - break - case "CD": - table.setAttribute("columnspacing", "0.5em"); - break - case "align": - case "align*": { - const cols = group.cols || []; - let spacing = group.addEqnNum ? "0em " : ""; - for (let i = 1; i < cols.length; i++) { - spacing += i % 2 ? "0em " : "1em "; - } - if (group.addEqnNum) { spacing += "0em"; } - table.setAttribute("columnspacing", spacing.trim()); - break - } - default: - table.setAttribute("columnspacing", "1em"); - } - - // Address \hline and \hdashline - let rowLines = ""; - const hlines = group.hLinesBeforeRow; - - menclose += hlines[0].length > 0 ? "top " : ""; - menclose += hlines[hlines.length - 1].length > 0 ? "bottom " : ""; - - for (let i = 1; i < hlines.length - 1; i++) { - rowLines += - hlines[i].length === 0 - ? "none " - : // MathML accepts only a single line between rows. Read one element. - hlines[i][0] - ? "dashed " - : "solid "; - } - if (/[sd]/.test(rowLines)) { - table.setAttribute("rowlines", rowLines.trim()); - } - - if (menclose !== "") { - table = new mathMLTree.MathNode("menclose", [table]); - table.setAttribute("notation", menclose.trim()); - } - - if (!Number.isNaN(group.arraystretch) && group.arraystretch < 1) { - // A small array. Wrap in scriptstyle so row gap is not too large. - table = new mathMLTree.MathNode("mstyle", [table]); - table.setAttribute("scriptlevel", "1"); - } - - return table; -}; - -// Convenience function for align, align*, aligned, alignat, alignat*, alignedat. -const alignedHandler = function(context, args) { - if (context.envName.indexOf("ed") === -1) { - validateAmsEnvironmentContext(context); - } - const cols = []; - const res = parseArray( - context.parser, - { - cols, - addJot: true, - addEqnNum: context.envName === "align" || context.envName === "alignat", - emptySingleRow: true, - colSeparationType: context.envName, - maxNumCols: context.envName === "split" ? 2 : undefined, - leqno: context.parser.settings.leqno - }, - "display" - ); - - // Determining number of columns. - // 1. If the first argument is given, we use it as a number of columns, - // and makes sure that each row doesn't exceed that number. - // 2. Otherwise, just count number of columns = maximum number - // of cells in each row ("aligned" mode -- isAligned will be true). - // - // At the same time, prepend empty group {} at beginning of every second - // cell in each row (starting with second cell) so that operators become - // binary. This behavior is implemented in amsmath's \start@aligned. - let numMaths; - let numCols = 0; - if (args[0] && args[0].type === "ordgroup") { - let arg0 = ""; - for (let i = 0; i < args[0].body.length; i++) { - const textord = assertNodeType(args[0].body[i], "textord"); - arg0 += textord.text; - } - numMaths = Number(arg0); - numCols = numMaths * 2; - } - const isAligned = !numCols; - res.body.forEach(function(row) { - if (!isAligned) { - // Case 1 - const curMaths = row.length / 2; - if (numMaths < curMaths) { - throw new ParseError( - "Too many math in a row: " + `expected ${numMaths}, but got ${curMaths}`, - row[0] - ); - } - } else if (numCols < row.length) { - // Case 2 - numCols = row.length; - } - }); - - // Adjusting alignment. - // In aligned mode, we add one \qquad between columns; - // otherwise we add nothing. - for (let i = 0; i < numCols; ++i) { - let align = "r"; - if (i % 2 === 1) { - align = "l"; - } - cols[i] = { - type: "align", - align: align - }; - } - res.colSeparationType = isAligned ? "align" : "alignat"; - return res; -}; - -// Arrays are part of LaTeX, defined in lttab.dtx so its documentation -// is part of the source2e.pdf file of LaTeX2e source documentation. -// {darray} is an {array} environment where cells are set in \displaystyle, -// as defined in nccmath.sty. -defineEnvironment({ - type: "array", - names: ["array", "darray"], - props: { - numArgs: 1 - }, - handler(context, args) { - // Since no types are specified above, the two possibilities are - // - The argument is wrapped in {} or [], in which case Parser's - // parseGroup() returns an "ordgroup" wrapping some symbol node. - // - The argument is a bare symbol node. - const symNode = checkSymbolNodeType(args[0]); - const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; - const cols = colalign.map(function(nde) { - const node = assertSymbolNodeType(nde); - const ca = node.text; - if ("lcr".indexOf(ca) !== -1) { - return { - type: "align", - align: ca - }; - } else if (ca === "|") { - return { - type: "separator", - separator: "|" - }; - } else if (ca === ":") { - return { - type: "separator", - separator: ":" - }; - } - throw new ParseError("Unknown column alignment: " + ca, nde); - }); - const res = { - cols, - colSeparationType: "array", - hskipBeforeAndAfter: true, // \@preamble in lttab.dtx - maxNumCols: cols.length - }; - return parseArray(context.parser, res, dCellStyle(context.envName)); - }, - mathmlBuilder: mathmlBuilder$7 -}); - -// The matrix environments of amsmath builds on the array environment -// of LaTeX, which is discussed above. -// The mathtools package adds starred versions of the same environments. -// These have an optional argument to choose left|center|right justification. -defineEnvironment({ - type: "array", - names: [ - "matrix", - "pmatrix", - "bmatrix", - "Bmatrix", - "vmatrix", - "Vmatrix", - "matrix*", - "pmatrix*", - "bmatrix*", - "Bmatrix*", - "vmatrix*", - "Vmatrix*" - ], - props: { - numArgs: 0 - }, - handler(context) { - const delimiters = { - matrix: null, - pmatrix: ["(", ")"], - bmatrix: ["[", "]"], - Bmatrix: ["\\{", "\\}"], - vmatrix: ["|", "|"], - Vmatrix: ["\\Vert", "\\Vert"] - }[context.envName.replace("*", "")]; - // \hskip -\arraycolsep in amsmath - let colAlign = "c"; - const payload = { - hskipBeforeAndAfter: false, - colSeparationType: "matrix", - cols: [{ type: "align", align: colAlign }] - }; - if (context.envName.charAt(context.envName.length - 1) === "*") { - // It's one of the mathtools starred functions. - // Parse the optional alignment argument. - const parser = context.parser; - parser.consumeSpaces(); - if (parser.fetch().text === "[") { - parser.consume(); - parser.consumeSpaces(); - colAlign = parser.fetch().text; - if ("lcr".indexOf(colAlign) === -1) { - throw new ParseError("Expected l or c or r", parser.nextToken); - } - parser.consume(); - parser.consumeSpaces(); - parser.expect("]"); - parser.consume(); - payload.cols = [{ type: "align", align: colAlign }]; - } - } - const res = parseArray(context.parser, payload, "text"); - // Populate cols with the correct number of column alignment specs. - const numCols = Math.max(0, ...res.body.map((row) => row.length)); - res.cols = new Array(numCols).fill({ type: "align", align: colAlign }); - return delimiters - ? { - type: "leftright", - mode: context.mode, - body: [res], - left: delimiters[0], - right: delimiters[1], - rightColor: undefined // \right uninfluenced by \color in array - } - : res; - }, - mathmlBuilder: mathmlBuilder$7 -}); - -defineEnvironment({ - type: "array", - names: ["smallmatrix"], - props: { - numArgs: 0 - }, - handler(context) { - const payload = { arraystretch: 0.5 }; - const res = parseArray(context.parser, payload, "script"); - res.colSeparationType = "small"; - return res; - }, - mathmlBuilder: mathmlBuilder$7 -}); - -defineEnvironment({ - type: "array", - names: ["subarray"], - props: { - numArgs: 1 - }, - handler(context, args) { - // Parsing of {subarray} is similar to {array} - const symNode = checkSymbolNodeType(args[0]); - const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; - const cols = colalign.map(function(nde) { - const node = assertSymbolNodeType(nde); - const ca = node.text; - // {subarray} only recognizes "l" & "c" - if ("lc".indexOf(ca) !== -1) { - return { - type: "align", - align: ca - }; - } - throw new ParseError("Unknown column alignment: " + ca, nde); - }); - if (cols.length > 1) { - throw new ParseError("{subarray} can contain only one column"); - } - let res = { - cols, - hskipBeforeAndAfter: false, - colSeparationType: "array", - arraystretch: 0 - }; - res = parseArray(context.parser, res, "script"); - if (res.body.length > 0 && res.body[0].length > 1) { - throw new ParseError("{subarray} can contain only one column"); - } - return res; - }, - mathmlBuilder: mathmlBuilder$7 -}); - -// A cases environment (in amsmath.sty) is almost equivalent to -// \def -// \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right. -// {dcases} is a {cases} environment where cells are set in \displaystyle, -// as defined in mathtools.sty. -// {rcases} is another mathtools environment. It's brace is on the right side. -defineEnvironment({ - type: "array", - names: ["cases", "dcases", "rcases", "drcases"], - props: { - numArgs: 0 - }, - handler(context) { - const payload = { - cols: [ - { - type: "align", - align: "l" - }, - { - type: "align", - align: "l" - } - ], - colSeparationType: "cases" - }; - const res = parseArray(context.parser, payload, dCellStyle(context.envName)); - return { - type: "leftright", - mode: context.mode, - body: [res], - left: context.envName.indexOf("r") > -1 ? "." : "\\{", - right: context.envName.indexOf("r") > -1 ? "\\}" : ".", - rightColor: undefined - }; - }, - mathmlBuilder: mathmlBuilder$7 -}); - -// In the align environment, one uses ampersands, &, to specify number of -// columns in each row, and to locate spacing between each column. -// align gets automatic numbering. align* and aligned do not. -// The alignedat environment can be used in math mode. -// Note that we assume \nomallineskiplimit to be zero, -// so that \strut@ is the same as \strut. -defineEnvironment({ - type: "array", - names: ["align", "align*", "aligned", "split"], - props: { - numArgs: 0 - }, - handler: alignedHandler, - mathmlBuilder: mathmlBuilder$7 -}); - -// A gathered environment is like an array environment with one centered -// column, but where rows are considered lines so get \jot line spacing -// and contents are set in \displaystyle. -defineEnvironment({ - type: "array", - names: ["gathered", "gather", "gather*"], - props: { - numArgs: 0 - }, - handler(context) { - if (utils.contains(["gather", "gather*"], context.envName)) { - validateAmsEnvironmentContext(context); - } - const res = { - cols: [ - { - type: "align", - align: "c" - } - ], - addJot: true, - colSeparationType: "gather", - addEqnNum: context.envName === "gather", - emptySingleRow: true, - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder: mathmlBuilder$7 -}); - -// alignat environment is like an align environment, but one must explicitly -// specify maximum number of columns in each row, and can adjust spacing between -// each columns. -defineEnvironment({ - type: "array", - names: ["alignat", "alignat*", "alignedat"], - props: { - numArgs: 1 - }, - handler: alignedHandler, - mathmlBuilder: mathmlBuilder$7 -}); - -defineEnvironment({ - type: "array", - names: ["equation", "equation*"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - const res = { - addEqnNum: context.envName === "equation", - emptySingleRow: true, - singleRow: true, - maxNumCols: 1, - colSeparationType: "gather", - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder: mathmlBuilder$7 -}); - -defineEnvironment({ - type: "array", - names: ["multline", "multline*"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - const res = { - addEqnNum: context.envName === "multline", - maxNumCols: 1, - colSeparationType: "multline", - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder: mathmlBuilder$7 -}); - -defineEnvironment({ - type: "array", - names: ["CD"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - return parseCD(context.parser); - }, - mathmlBuilder: mathmlBuilder$7 -}); - -// Catch \hline outside array environment -defineFunction({ - type: "text", // Doesn't matter what this is. - names: ["\\hline", "\\hdashline"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: true - }, - handler(context, args) { - throw new ParseError(`${context.funcName} valid only within array environment`); - } -}); - -const environments = _environments; - -// Environment delimiters. HTML/MathML rendering is defined in the corresponding -// defineEnvironment definitions. -defineFunction({ - type: "environment", - names: ["\\begin", "\\end"], - props: { - numArgs: 1, - argTypes: ["text"] - }, - handler({ parser, funcName }, args) { - const nameGroup = args[0]; - if (nameGroup.type !== "ordgroup") { - throw new ParseError("Invalid environment name", nameGroup); - } - let envName = ""; - for (let i = 0; i < nameGroup.body.length; ++i) { - envName += assertNodeType(nameGroup.body[i], "textord").text; - } - - if (funcName === "\\begin") { - // begin...end is similar to left...right - if (!Object.prototype.hasOwnProperty.call(environments, envName )) { - throw new ParseError("No such environment: " + envName, nameGroup); - } - // Build the environment object. Arguments and other information will - // be made available to the begin and end methods using properties. - const env = environments[envName]; - const { args, optArgs } = parser.parseArguments("\\begin{" + envName + "}", env); - const context = { - mode: parser.mode, - envName, - parser - }; - const result = env.handler(context, args, optArgs); - parser.expect("\\end", false); - const endNameToken = parser.nextToken; - const end = assertNodeType(parser.parseFunction(), "environment"); - if (end.name !== envName) { - throw new ParseError( - `Mismatch: \\begin{${envName}} matched by \\end{${end.name}}`, - endNameToken - ); - } - return result; - } - - return { - type: "environment", - mode: parser.mode, - name: envName, - nameGroup - }; - } -}); - -defineFunction({ - type: "envTag", - names: ["\\env@tag"], - props: { - numArgs: 1, - argTypes: ["math"] - }, - handler({ parser }, args) { - return { - type: "envTag", - mode: parser.mode, - body: args[0] - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow"); - } -}); - -defineFunction({ - type: "noTag", - names: ["\\env@notag"], - props: { - numArgs: 0 - }, - handler({ parser }) { - return { - type: "noTag", - mode: parser.mode - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow"); - } -}); - -const mathmlBuilder$6 = (group, style) => { - const font = group.font; - const newStyle = style.withFont(font); - const mathGroup = buildGroup$1(group.body, newStyle); - - if (mathGroup.children.length === 0) { return mathGroup } // empty group, e.g., \mathrm{} - if (font === "boldsymbol" && ["mo", "mpadded"].includes(mathGroup.type)) { - mathGroup.style.fontWeight = "bold"; - return mathGroup - } - // Check if it is possible to consolidate elements into a single element. - let canConsolidate = mathGroup.children[0].type === "mo"; - for (let i = 1; i < mathGroup.children.length; i++) { - if (mathGroup.children[i].type === "mo" && font === "boldsymbol") { - mathGroup.children[i].style.fontWeight = "bold"; - } - if (mathGroup.children[i].type !== "mi") { canConsolidate = false; } - const localVariant = mathGroup.children[i].attributes && - mathGroup.children[i].attributes.mathvariant || ""; - if (localVariant !== "normal") { canConsolidate = false; } - } - if (!canConsolidate) { return mathGroup } - // Consolidate the elements. - const mi = mathGroup.children[0]; - for (let i = 1; i < mathGroup.children.length; i++) { - mi.children.push(mathGroup.children[i].children[0]); - } - if (mathGroup.attributes.mathcolor) { mi.attributes.mathcolor = mathGroup.attributes.mathcolor; } - if (mi.attributes.mathvariant && mi.attributes.mathvariant === "normal") { - // Workaround for a Firefox bug that renders spurious space around - // a - // Ref: https://bugs.webkit.org/show_bug.cgi?id=129097 - // We insert a text node that contains a zero-width space and wrap in an mrow. - // TODO: Get rid of this workaround when the Firefox bug is fixed. - const bogus = new mathMLTree.MathNode("mtext", new mathMLTree.TextNode("\u200b")); - return new mathMLTree.MathNode("mrow", [bogus, mi]) - } - return mi -}; - -const fontAliases = { - "\\Bbb": "\\mathbb", - "\\bold": "\\mathbf", - "\\frak": "\\mathfrak", - "\\bm": "\\boldsymbol" -}; - -defineFunction({ - type: "font", - names: [ - // styles - "\\mathrm", - "\\mathit", - "\\mathbf", - "\\mathnormal", - "\\up@greek", - "\\boldsymbol", - - // families - "\\mathbb", - "\\mathcal", - "\\mathfrak", - "\\mathscr", - "\\mathsf", - "\\mathtt", - "\\oldstylenums", - - // aliases - "\\Bbb", - "\\bm", - "\\bold", - "\\frak" - ], - props: { - numArgs: 1, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const body = normalizeArgument(args[0]); - let func = funcName; - if (func in fontAliases) { - func = fontAliases[func]; - } - return { - type: "font", - mode: parser.mode, - font: func.slice(1), - body - }; - }, - mathmlBuilder: mathmlBuilder$6 -}); - -// Old font changing functions -defineFunction({ - type: "font", - names: ["\\rm", "\\sf", "\\tt", "\\bf", "\\it", "\\cal"], - props: { - numArgs: 0, - allowedInText: true - }, - handler: ({ parser, funcName, breakOnTokenText }, args) => { - const { mode } = parser; - const body = parser.parseExpression(true, breakOnTokenText); - const fontStyle = `math${funcName.slice(1)}`; - - return { - type: "font", - mode: mode, - font: fontStyle, - body: { - type: "ordgroup", - mode: parser.mode, - body - } - }; - }, - mathmlBuilder: mathmlBuilder$6 -}); - -const stylArray = ["display", "text", "script", "scriptscript"]; -const scriptLevel = { auto: -1, display: 0, text: 0, script: 1, scriptscript: 2 }; - -const mathmlBuilder$5 = (group, style) => { - // Track the scriptLevel of the numerator and denominator. - // We may need that info for \mathchoice or for adjusting em dimensions. - const childOptions = group.scriptLevel === "auto" - ? style.incrementLevel() - : group.scriptLevel === "display" - ? style.withLevel(StyleLevel.TEXT) - : group.scriptLevel === "text" - ? style.withLevel(StyleLevel.SCRIPT) - : style.withLevel(StyleLevel.SCRIPTSCRIPT); - - let node = new mathMLTree.MathNode("mfrac", [ - buildGroup$1(group.numer, childOptions), - buildGroup$1(group.denom, childOptions) - ]); - - if (!group.hasBarLine) { - node.setAttribute("linethickness", "0px"); - } else if (group.barSize) { - const ruleWidth = calculateSize(group.barSize, style); - node.setAttribute("linethickness", ruleWidth.number + ruleWidth.unit); - } - - if (group.leftDelim != null || group.rightDelim != null) { - const withDelims = []; - - if (group.leftDelim != null) { - const leftOp = new mathMLTree.MathNode("mo", [ - new mathMLTree.TextNode(group.leftDelim.replace("\\", "")) - ]); - leftOp.setAttribute("fence", "true"); - withDelims.push(leftOp); - } - - withDelims.push(node); - - if (group.rightDelim != null) { - const rightOp = new mathMLTree.MathNode("mo", [ - new mathMLTree.TextNode(group.rightDelim.replace("\\", "")) - ]); - rightOp.setAttribute("fence", "true"); - withDelims.push(rightOp); - } - - node = makeRow(withDelims); - } - - if (group.scriptLevel !== "auto") { - node = new mathMLTree.MathNode("mstyle", [node]); - node.setAttribute("displaystyle", String(group.scriptLevel === "display")); - node.setAttribute("scriptlevel", scriptLevel[group.scriptLevel]); - } - - return node; -}; - -defineFunction({ - type: "genfrac", - names: [ - "\\dfrac", - "\\frac", - "\\tfrac", - "\\dbinom", - "\\binom", - "\\tbinom", - "\\\\atopfrac", // can’t be entered directly - "\\\\bracefrac", - "\\\\brackfrac" // ditto - ], - props: { - numArgs: 2, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const denom = args[1]; - let hasBarLine = false; - let leftDelim = null; - let rightDelim = null; - let scriptLevel = "auto"; - - switch (funcName) { - case "\\dfrac": - case "\\frac": - case "\\tfrac": - hasBarLine = true; - break; - case "\\\\atopfrac": - hasBarLine = false; - break; - case "\\dbinom": - case "\\binom": - case "\\tbinom": - leftDelim = "("; - rightDelim = ")"; - break; - case "\\\\bracefrac": - leftDelim = "\\{"; - rightDelim = "\\}"; - break; - case "\\\\brackfrac": - leftDelim = "["; - rightDelim = "]"; - break; - default: - throw new Error("Unrecognized genfrac command"); - } - - switch (funcName) { - case "\\dfrac": - case "\\dbinom": - scriptLevel = "display"; - break; - case "\\tfrac": - case "\\tbinom": - scriptLevel = "text"; - break; - } - - return { - type: "genfrac", - mode: parser.mode, - continued: false, - numer, - denom, - hasBarLine, - leftDelim, - rightDelim, - scriptLevel, - barSize: null - }; - }, - mathmlBuilder: mathmlBuilder$5 -}); - -defineFunction({ - type: "genfrac", - names: ["\\cfrac"], - props: { - numArgs: 2 - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const denom = args[1]; - - return { - type: "genfrac", - mode: parser.mode, - continued: true, - numer, - denom, - hasBarLine: true, - leftDelim: null, - rightDelim: null, - scriptLevel: "display", - barSize: null - }; - } -}); - -// Infix generalized fractions -- these are not rendered directly, but replaced -// immediately by one of the variants above. -defineFunction({ - type: "infix", - names: ["\\over", "\\choose", "\\atop", "\\brace", "\\brack"], - props: { - numArgs: 0, - infix: true - }, - handler({ parser, funcName, token }) { - let replaceWith; - switch (funcName) { - case "\\over": - replaceWith = "\\frac"; - break; - case "\\choose": - replaceWith = "\\binom"; - break; - case "\\atop": - replaceWith = "\\\\atopfrac"; - break; - case "\\brace": - replaceWith = "\\\\bracefrac"; - break; - case "\\brack": - replaceWith = "\\\\brackfrac"; - break; - default: - throw new Error("Unrecognized infix genfrac command"); - } - return { - type: "infix", - mode: parser.mode, - replaceWith, - token - }; - } -}); - -const delimFromValue = function(delimString) { - let delim = null; - if (delimString.length > 0) { - delim = delimString; - delim = delim === "." ? null : delim; - } - return delim; -}; - -defineFunction({ - type: "genfrac", - names: ["\\genfrac"], - props: { - numArgs: 6, - allowedInArgument: true, - argTypes: ["math", "math", "size", "text", "math", "math"] - }, - handler({ parser }, args) { - const numer = args[4]; - const denom = args[5]; - - // Look into the parse nodes to get the desired delimiters. - const leftNode = normalizeArgument(args[0]); - const leftDelim = leftNode.type === "atom" && leftNode.family === "open" - ? delimFromValue(leftNode.text) - : null; - const rightNode = normalizeArgument(args[1]); - const rightDelim = - rightNode.type === "atom" && rightNode.family === "close" - ? delimFromValue(rightNode.text) - : null; - - const barNode = assertNodeType(args[2], "size"); - let hasBarLine; - let barSize = null; - if (barNode.isBlank) { - // \genfrac acts differently than \above. - // \genfrac treats an empty size group as a signal to use a - // standard bar size. \above would see size = 0 and omit the bar. - hasBarLine = true; - } else { - barSize = barNode.value; - hasBarLine = barSize.number > 0; - } - - // Find out if we want displaystyle, textstyle, etc. - let scriptLevel = "auto"; - let styl = args[3]; - if (styl.type === "ordgroup") { - if (styl.body.length > 0) { - const textOrd = assertNodeType(styl.body[0], "textord"); - scriptLevel = stylArray[Number(textOrd.text)]; - } - } else { - styl = assertNodeType(styl, "textord"); - scriptLevel = stylArray[Number(styl.text)]; - } - - return { - type: "genfrac", - mode: parser.mode, - numer, - denom, - continued: false, - hasBarLine, - barSize, - leftDelim, - rightDelim, - scriptLevel - }; - }, - mathmlBuilder: mathmlBuilder$5 -}); - -// \above is an infix fraction that also defines a fraction bar size. -defineFunction({ - type: "infix", - names: ["\\above"], - props: { - numArgs: 1, - argTypes: ["size"], - infix: true - }, - handler({ parser, funcName, token }, args) { - return { - type: "infix", - mode: parser.mode, - replaceWith: "\\\\abovefrac", - barSize: assertNodeType(args[0], "size").value, - token - }; - } -}); - -defineFunction({ - type: "genfrac", - names: ["\\\\abovefrac"], - props: { - numArgs: 3, - argTypes: ["math", "size", "math"] - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const barSize = assert(assertNodeType(args[1], "infix").barSize); - const denom = args[2]; - - const hasBarLine = barSize.number > 0; - return { - type: "genfrac", - mode: parser.mode, - numer, - denom, - continued: false, - hasBarLine, - barSize, - leftDelim: null, - rightDelim: null, - scriptLevel: "auto" - }; - }, - - mathmlBuilder: mathmlBuilder$5 -}); - -const mathmlBuilder$4 = (group, style) => { - const accentNode = stretchy.mathMLnode(group.label); - return new mathMLTree.MathNode(group.isOver ? "mover" : "munder", [ - buildGroup$1(group.base, style), - accentNode - ]); -}; - -// Horizontal stretchy braces -defineFunction({ - type: "horizBrace", - names: ["\\overbrace", "\\underbrace"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - return { - type: "horizBrace", - mode: parser.mode, - label: funcName, - isOver: /^\\over/.test(funcName), - base: args[0] - }; - }, - mathmlBuilder: mathmlBuilder$4 -}); - -defineFunction({ - type: "href", - names: ["\\href"], - props: { - numArgs: 2, - argTypes: ["url", "original"], - allowedInText: true - }, - handler: ({ parser, token }, args) => { - const body = args[1]; - const href = assertNodeType(args[0], "url").url; - - if ( - !parser.settings.isTrusted({ - command: "\\href", - url: href - }) - ) { - throw new ParseError(`Function "\\href" is not trusted`, token) - } - - return { - type: "href", - mode: parser.mode, - href, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - let math = buildExpressionRow(group.body, style); - if (!(math instanceof MathNode)) { - math = new MathNode("mrow", [math]); - } - math.setAttribute("href", group.href); - return math; - } -}); - -defineFunction({ - type: "href", - names: ["\\url"], - props: { - numArgs: 1, - argTypes: ["url"], - allowedInText: true - }, - handler: ({ parser, token }, args) => { - const href = assertNodeType(args[0], "url").url; - - if ( - !parser.settings.isTrusted({ - command: "\\url", - url: href - }) - ) { - throw new ParseError(`Function "\\url" is not trusted`, token) - } - - const chars = []; - for (let i = 0; i < href.length; i++) { - let c = href[i]; - if (c === "~") { - c = "\\textasciitilde"; - } - chars.push({ - type: "textord", - mode: "text", - text: c - }); - } - const body = { - type: "text", - mode: parser.mode, - font: "\\texttt", - body: chars - }; - return { - type: "href", - mode: parser.mode, - href, - body: ordargument(body) - }; - } -}); - -defineFunction({ - type: "html", - names: ["\\class", "\\id", "\\style", "\\data"], - props: { - numArgs: 2, - argTypes: ["raw", "original"], - allowedInText: true - }, - handler: ({ parser, funcName, token }, args) => { - const value = assertNodeType(args[0], "raw").string; - const body = args[1]; - - if (parser.settings.strict) { - throw new ParseError(`Function "${funcName}" is disabled in strict mode`, token) - } - - let trustContext; - const attributes = {}; - - switch (funcName) { - case "\\class": - attributes.class = value; - trustContext = { - command: "\\class", - class: value - }; - break; - case "\\id": - attributes.id = value; - trustContext = { - command: "\\id", - id: value - }; - break; - case "\\style": - attributes.style = value; - trustContext = { - command: "\\style", - style: value - }; - break; - case "\\data": { - const data = value.split(","); - for (let i = 0; i < data.length; i++) { - const keyVal = data[i].split("="); - if (keyVal.length !== 2) { - throw new ParseError("Error parsing key-value for \\data"); - } - attributes["data-" + keyVal[0].trim()] = keyVal[1].trim(); - } - - trustContext = { - command: "\\data", - attributes - }; - break; - } - default: - throw new Error("Unrecognized html command"); - } - - if (!parser.settings.isTrusted(trustContext)) { - throw new ParseError(`Function "${funcName}" is not trusted`, token) - } - return { - type: "html", - mode: parser.mode, - attributes, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - const element = buildExpressionRow(group.body, style); - - const classes = []; - if (group.attributes.class) { - classes.push(...group.attributes.class.trim().split(/\s+/)); - } - element.classes = classes; - - for (const attr in group.attributes) { - if (attr !== "class" && Object.prototype.hasOwnProperty.call(group.attributes, attr)) { - element.setAttribute(attr, group.attributes[attr]); - } - } - - return element; - } -}); - -const sizeData = function(str) { - if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(str)) { - // str is a number with no unit specified. - // default unit is bp, per graphix package. - return { number: +str, unit: "bp" } - } else { - const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(str); - if (!match) { - throw new ParseError("Invalid size: '" + str + "' in \\includegraphics"); - } - const data = { - number: +(match[1] + match[2]), // sign + magnitude, cast to number - unit: match[3] - }; - if (!validUnit(data)) { - throw new ParseError("Invalid unit: '" + data.unit + "' in \\includegraphics."); - } - return data - } -}; - -defineFunction({ - type: "includegraphics", - names: ["\\includegraphics"], - props: { - numArgs: 1, - numOptionalArgs: 1, - argTypes: ["raw", "url"], - allowedInText: false - }, - handler: ({ parser, token }, args, optArgs) => { - let width = { number: 0, unit: "em" }; - let height = { number: 0.9, unit: "em" }; // sorta character sized. - let totalheight = { number: 0, unit: "em" }; - let alt = ""; - - if (optArgs[0]) { - const attributeStr = assertNodeType(optArgs[0], "raw").string; - - // Parser.js does not parse key/value pairs. We get a string. - const attributes = attributeStr.split(","); - for (let i = 0; i < attributes.length; i++) { - const keyVal = attributes[i].split("="); - if (keyVal.length === 2) { - const str = keyVal[1].trim(); - switch (keyVal[0].trim()) { - case "alt": - alt = str; - break - case "width": - width = sizeData(str); - break - case "height": - height = sizeData(str); - break - case "totalheight": - totalheight = sizeData(str); - break - default: - throw new ParseError("Invalid key: '" + keyVal[0] + "' in \\includegraphics.") - } - } - } - } - - const src = assertNodeType(args[0], "url").url; - - if (alt === "") { - // No alt given. Use the file name. Strip away the path. - alt = src; - alt = alt.replace(/^.*[\\/]/, ""); - alt = alt.substring(0, alt.lastIndexOf(".")); - } - - if ( - !parser.settings.isTrusted({ - command: "\\includegraphics", - url: src - }) - ) { - throw new ParseError(`Function "\\includegraphics" is not trusted`, token) - } - - return { - type: "includegraphics", - mode: parser.mode, - alt: alt, - width: width, - height: height, - totalheight: totalheight, - src: src - } - }, - mathmlBuilder: (group, style) => { - const height = calculateSize(group.height, style); - const depth = { number: 0, unit: "em" }; - - if (group.totalheight.number > 0) { - if (group.totalheight.unit === height.unit && - group.totalheight.number > height.number) { - depth.number = group.totalheight.number - height.number; - depth.unit = height.unit; - } - } - - let width = 0; - if (group.width.number > 0) { - width = calculateSize(group.width, style); - } - - const graphicStyle = { height: height.number + depth.number + "em" }; - if (width.number > 0) { - graphicStyle.width = width.number + width.unit; - } - if (depth.number > 0) { - graphicStyle.verticalAlign = -depth.number + depth.unit; - } - - const node = new Img(group.src, group.alt, graphicStyle); - node.height = height; - node.depth = depth; - return new mathMLTree.MathNode("mtext", [node]) - } -}); - -// Horizontal spacing commands - -// TODO: \hskip and \mskip should support plus and minus in lengths - -defineFunction({ - type: "kern", - names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"], - props: { - numArgs: 1, - argTypes: ["size"], - primitive: true, - allowedInText: true - }, - handler({ parser, funcName, token }, args) { - const size = assertNodeType(args[0], "size"); - if (parser.settings.strict) { - const mathFunction = funcName[1] === "m"; // \mkern, \mskip - const muUnit = size.value.unit === "mu"; - if (mathFunction) { - if (!muUnit) { - throw new ParseError(`LaTeX's ${funcName} supports only mu units, ` + - `not ${size.value.unit} units`, token) - } - if (parser.mode !== "math") { - throw new ParseError(`LaTeX's ${funcName} works only in math mode`, token) - } - } else { - // !mathFunction - if (muUnit) { - throw new ParseError(`LaTeX's ${funcName} doesn't support mu units`, token) - } - } - } - return { - type: "kern", - mode: parser.mode, - dimension: size.value - }; - }, - mathmlBuilder(group, style) { - const dimension = calculateSize(group.dimension, style); - const ch = dimension.unit === "em" ? spaceCharacter(dimension.number) : ""; - if (group.mode === "text" && ch.length > 0) { - const character = new mathMLTree.TextNode(ch); - return new mathMLTree.MathNode("mtext", [character]); - } else { - const node = new mathMLTree.MathNode("mspace"); - node.setAttribute("width", dimension.number + dimension.unit); - return node; - } - } -}); - -const spaceCharacter = function(width) { - if (width >= 0.05555 && width <= 0.05556) { - return "\u200a"; //   - } else if (width >= 0.1666 && width <= 0.1667) { - return "\u2009"; //   - } else if (width >= 0.2222 && width <= 0.2223) { - return "\u2005"; //   - } else if (width >= 0.2777 && width <= 0.2778) { - return "\u2005\u200a"; //    - } else { - return ""; - } -}; - -// Limit valid characters to a small set, for safety. -const invalidIdRegEx = /[^A-Za-z_0-9-]/g; - -defineFunction({ - type: "label", - names: ["\\label"], - props: { - numArgs: 1, - argTypes: ["raw"] - }, - handler({ parser }, args) { - return { - type: "label", - mode: parser.mode, - string: args[0].string.replace(invalidIdRegEx, "") - }; - }, - mathmlBuilder(group, style) { - // Return a no-width, no-ink element with an HTML id. - const node = new mathMLTree.MathNode("mrow", [], ["tml-label"]); - if (group.string.length > 0) { - node.setAttribute("id", group.string); - } - return node - } -}); - -// Horizontal overlap functions - -const textModeLap = ["\\clap", "\\llap", "\\rlap"]; - -defineFunction({ - type: "lap", - names: ["\\mathllap", "\\mathrlap", "\\mathclap", "\\clap", "\\llap", "\\rlap"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser, funcName, token }, args) => { - if (textModeLap.includes(funcName)) { - if (parser.settings.strict && parser.mode !== "text") { - throw new ParseError(`{${funcName}} can be used only in text mode. - Try \\math${funcName.slice(1)}`, token) - } - funcName = funcName.slice(1); - } else { - funcName = funcName.slice(5); - } - const body = args[0]; - return { - type: "lap", - mode: parser.mode, - alignment: funcName, - body - } - }, - mathmlBuilder: (group, style) => { - // mathllap, mathrlap, mathclap - const node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, style)]); - - if (group.alignment === "rlap") { - if (group.body.body.length > 0 && group.body.body[0].type === "genfrac") { - // In Firefox, a squashes the 3/18em padding of a child \frac. Put it back. - node.setAttribute("lspace", "0.16667em"); - } - } else { - const offset = group.alignment === "llap" ? "-1" : "-0.5"; - node.setAttribute("lspace", offset + "width"); - } - node.setAttribute("width", "0px"); - return node - } -}); - -// Switching from text mode back to math mode -defineFunction({ - type: "ordgroup", - names: ["\\(", "$"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: false - }, - handler({ funcName, parser }, args) { - const outerMode = parser.mode; - parser.switchMode("math"); - const close = funcName === "\\(" ? "\\)" : "$"; - const body = parser.parseExpression(false, close); - parser.expect(close); - parser.switchMode(outerMode); - return { - type: "ordgroup", - mode: parser.mode, - body - }; - } -}); - -// Check for extra closing math delimiters -defineFunction({ - type: "text", // Doesn't matter what this is. - names: ["\\)", "\\]"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: false - }, - handler(context, token) { - throw new ParseError(`Mismatched ${context.funcName}`, token); - } -}); - -const chooseStyle = (group, style) => { - switch (style.level) { - case StyleLevel.DISPLAY: // 0 - return group.display; - case StyleLevel.TEXT: // 1 - return group.text; - case StyleLevel.SCRIPT: // 2 - return group.script; - case StyleLevel.SCRIPTSCRIPT: // 3 - return group.scriptscript; - default: - return group.text; - } -}; - -defineFunction({ - type: "mathchoice", - names: ["\\mathchoice"], - props: { - numArgs: 4, - primitive: true - }, - handler: ({ parser }, args) => { - return { - type: "mathchoice", - mode: parser.mode, - display: ordargument(args[0]), - text: ordargument(args[1]), - script: ordargument(args[2]), - scriptscript: ordargument(args[3]) - }; - }, - mathmlBuilder: (group, style) => { - const body = chooseStyle(group, style); - return buildExpressionRow(body, style); - } -}); - -const textAtomTypes = ["text", "textord", "mathord", "atom"]; - -function mathmlBuilder$3(group, style) { - let node; - const inner = buildExpression(group.body, style); - - if (group.mclass === "minner") { - node = new mathMLTree.MathNode("mpadded", inner); - } else if (group.mclass === "mord") { - if (group.isCharacterBox || inner[0].type === "mathord") { - node = inner[0]; - node.type = "mi"; - } else { - node = new mathMLTree.MathNode("mi", inner); - } - } else { - if (group.mustPromote) { - node = inner[0]; - node.type = "mo"; - if (group.isCharacterBox && group.body[0].text && /[A-Za-z]/.test(group.body[0].text)) { - node.setAttribute("mathvariant", "italic"); - } - } else { - node = new mathMLTree.MathNode("mo", inner); - } - - // Set spacing based on what is the most likely adjacent atom type. - // See TeXbook p170. - const doSpacing = style.level < 2; // Operator spacing is zero inside a (sub|super)script. - if (group.mclass === "mbin") { - // medium space - node.attributes.lspace = (doSpacing ? "0.2222em" : "0"); - node.attributes.rspace = (doSpacing ? "0.2222em" : "0"); - } else if (group.mclass === "mrel") { - // thickspace - node.attributes.lspace = (doSpacing ? "0.2778em" : "0"); - node.attributes.rspace = (doSpacing ? "0.2778em" : "0"); - } else if (group.mclass === "mpunct") { - node.attributes.lspace = "0em"; - node.attributes.rspace = (doSpacing ? "0.1667em" : "0"); - } else if (group.mclass === "mopen" || group.mclass === "mclose") { - node.attributes.lspace = "0em"; - node.attributes.rspace = "0em"; - } else if (group.mclass === "minner" && doSpacing) { - node.attributes.lspace = "0.0556em"; // 1 mu is the most likely option - node.attributes.width = "+0.1111em"; - } - if (!(group.mclass === "mopen" || group.mclass === "mclose")) { - delete node.attributes.stretchy; - delete node.attributes.form; - } - } - return node; -} - -// Math class commands except \mathop -defineFunction({ - type: "mclass", - names: [ - "\\mathord", - "\\mathbin", - "\\mathrel", - "\\mathopen", - "\\mathclose", - "\\mathpunct", - "\\mathinner" - ], - props: { - numArgs: 1, - primitive: true - }, - handler({ parser, funcName }, args) { - const body = args[0]; - const isCharacterBox = utils.isCharacterBox(body); - // We should not wrap a around a or . That would be invalid MathML. - // In that case, we instead promote the text contents of the body to the parent. - let mustPromote = true; - const mord = { type: "mathord", text: "", mode: parser.mode }; - const arr = (body.body) ? body.body : [body]; - for (const arg of arr) { - if (textAtomTypes.includes(arg.type)) { - if (arg.text) { - mord.text += arg.text; - } else if (arg.body) { - arg.body.map(e => { mord.text += e.text; }); - } - } else { - mustPromote = false; - break - } - } - return { - type: "mclass", - mode: parser.mode, - mclass: "m" + funcName.slice(5), - body: ordargument(mustPromote ? mord : body), - isCharacterBox, - mustPromote - }; - }, - mathmlBuilder: mathmlBuilder$3 -}); - -const binrelClass = (arg) => { - // \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument. - // (by rendering separately and with {}s before and after, and measuring - // the change in spacing). We'll do roughly the same by detecting the - // atom type directly. - const atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg; - if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) { - return "m" + atom.family; - } else { - return "mord"; - } -}; - -// \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord. -// This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX. -defineFunction({ - type: "mclass", - names: ["\\@binrel"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "mclass", - mode: parser.mode, - mclass: binrelClass(args[0]), - body: ordargument(args[1]), - isCharacterBox: utils.isCharacterBox(args[1]) - }; - } -}); - -// Build a relation or stacked op by placing one symbol on top of another -defineFunction({ - type: "mclass", - names: ["\\stackrel", "\\overset", "\\underset"], - props: { - numArgs: 2 - }, - handler({ parser, funcName }, args) { - const baseArg = args[1]; - const shiftedArg = args[0]; - - const baseOp = { - type: "op", - mode: baseArg.mode, - limits: true, - alwaysHandleSupSub: true, - parentIsSupSub: false, - symbol: false, - stack: true, - suppressBaseShift: funcName !== "\\stackrel", - body: ordargument(baseArg) - }; - - return { - type: "supsub", - mode: shiftedArg.mode, - base: baseOp, - sup: funcName === "\\underset" ? null : shiftedArg, - sub: funcName === "\\underset" ? shiftedArg : null - }; - }, - mathmlBuilder: mathmlBuilder$3 -}); - -// Helper function -const buildGroup = (el, style, noneNode) => { - if (!el) { return noneNode } - const node = buildGroup$1(el, style); - if (node.type === "mrow" && node.children.length === 0) { return noneNode } - return node -}; - -defineFunction({ - type: "multiscript", - names: ["\\sideset", "\\pres@cript"], // See macros.js for \prescript - props: { - numArgs: 3 - }, - handler({ parser, funcName, token }, args) { - if (args[2].body.length === 0) { - throw new ParseError(funcName + `cannot parse an empty base.`) - } - const base = args[2].body[0]; - if (parser.settings.strict && funcName === "\\sideset" && !base.symbol) { - throw new ParseError(`The base of \\sideset must be a big operator. Try \\prescript.`) - } - - if ((args[0].body.length > 0 && args[0].body[0].type !== "supsub") || - (args[1].body.length > 0 && args[1].body[0].type !== "supsub")) { - throw new ParseError("\\sideset can parse only subscripts and " + - "superscripts in its first two arguments", token) - } - - // The prescripts and postscripts come wrapped in a supsub. - const prescripts = args[0].body.length > 0 ? args[0].body[0] : null; - const postscripts = args[1].body.length > 0 ? args[1].body[0] : null; - - if (!prescripts && !postscripts) { - return base - } else if (!prescripts) { - // It's not a multi-script. Get a \textstyle supsub. - return { - type: "styling", - mode: parser.mode, - scriptLevel: "text", - body: [{ - type: "supsub", - mode: parser.mode, - base, - sup: postscripts.sup, - sub: postscripts.sub - }] - } - } else { - return { - type: "multiscript", - mode: parser.mode, - isSideset: funcName === "\\sideset", - prescripts, - postscripts, - base - } - } - }, - mathmlBuilder(group, style) { - const base = buildGroup$1(group.base, style); - - const prescriptsNode = new mathMLTree.MathNode("mprescripts"); - const noneNode = new mathMLTree.MathNode("none"); - let children = []; - - const preSub = buildGroup(group.prescripts.sub, style, noneNode); - const preSup = buildGroup(group.prescripts.sup, style, noneNode); - if (group.isSideset) { - // This seems silly, but LaTeX does this. Firefox ignores it, which does not make me sad. - preSub.setAttribute("style", "text-align: left;"); - preSup.setAttribute("style", "text-align: left;"); - } - - if (group.postscripts) { - const postSub = buildGroup(group.postscripts.sub, style, noneNode); - const postSup = buildGroup(group.postscripts.sup, style, noneNode); - children = [base, postSub, postSup, prescriptsNode, preSub, preSup]; - } else { - children = [base, prescriptsNode, preSub, preSup]; - } - - return new mathMLTree.MathNode("mmultiscripts", children); - } -}); - -defineFunction({ - type: "not", - names: ["\\not"], - props: { - numArgs: 1, - primitive: true, - allowedInText: false - }, - handler({ parser }, args) { - const isCharacterBox = utils.isCharacterBox(args[0]); - let body; - if (isCharacterBox) { - body = ordargument(args[0]); - if (body[0].text.charAt(0) === "\\") { - body[0].text = symbols.math[body[0].text].replace; - } - // \u0338 is the Unicode Combining Long Solidus Overlay - body[0].text = body[0].text.slice(0, 1) + "\u0338" + body[0].text.slice(1); - } else { - // When the argument is not a character box, TeX does an awkward, poorly placed overlay. - // We'll do the same. - const notNode = { type: "textord", mode: "math", text: "\u0338" }; - const kernNode = { type: "kern", mode: "math", dimension: { number: -0.6, unit: "em" } }; - body = [notNode, kernNode, args[0]]; - } - return { - type: "not", - mode: parser.mode, - body, - isCharacterBox - }; - }, - mathmlBuilder(group, style) { - if (group.isCharacterBox) { - const inner = buildExpression(group.body, style); - return inner[0] - } else { - return buildExpressionRow(group.body, style, true) - } - } -}); - -// Limits, symbols - -// Some helpers - -const ordAtomTypes = ["textord", "mathord", "atom"]; - -// Most operators have a large successor symbol, but these don't. -const noSuccessor = ["\\smallint"]; - -// Math operators (e.g. \sin) need a space between these types and themselves: -const ordTypes = ["textord", "mathord", "ordgroup", "close", "leftright"]; - -const dels = ["}", "\\left", "\\middle", "\\right"]; -const isDelimiter = str => str.length > 0 && - (delimiters.includes(str) || delimiterSizes[str] || dels.includes(str)); - -// NOTE: Unlike most `builders`s, this one handles not only "op", but also -// "supsub" since some of them (like \int) can affect super/subscripting. - -const mathmlBuilder$2 = (group, style) => { - let node; - - if (group.symbol) { - // This is a symbol. Just add the symbol. - node = new MathNode("mo", [makeText(group.name, group.mode)]); - if (utils.contains(noSuccessor, group.name)) { - node.setAttribute("largeop", "false"); - } else { - node.setAttribute("movablelimits", "false"); - } - } else if (group.body) { - // This is an operator with children. Add them. - node = new MathNode("mo", buildExpression(group.body, style)); - } else { - // This is a text operator. Add all of the characters from the operator's name. - node = new MathNode("mi", [new TextNode(group.name.slice(1))]); - - if (!group.parentIsSupSub) { - // Append an invisible . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new MathNode("mo", [makeText("\u2061", "text")]); - node = new MathNode("mpadded", [node, operator]); - const lSpace = group.needsLeadingSpace ? 0.1667 : 0; - const rSpace = group.isFollowedByDelimiter ? 0 : 0.1666; - if (group.needsLeadingSpace) { - node.setAttribute("lspace", "0.1667em"); // thin space. - } - if ((lSpace + rSpace) > 0) { - node.setAttribute("width", `+${lSpace + rSpace}em`); - } - } - } - - return node; -}; - -const singleCharBigOps = { - "\u220F": "\\prod", - "\u2210": "\\coprod", - "\u2211": "\\sum", - "\u22c0": "\\bigwedge", - "\u22c1": "\\bigvee", - "\u22c2": "\\bigcap", - "\u22c3": "\\bigcup", - "\u2a00": "\\bigodot", - "\u2a01": "\\bigoplus", - "\u2a02": "\\bigotimes", - "\u2a04": "\\biguplus", - "\u2a05": "\\bigsqcap", - "\u2a06": "\\bigsqcup" -}; - -defineFunction({ - type: "op", - names: [ - "\\coprod", - "\\bigvee", - "\\bigwedge", - "\\biguplus", - "\\bigcap", - "\\bigcup", - "\\intop", - "\\prod", - "\\sum", - "\\bigotimes", - "\\bigoplus", - "\\bigodot", - "\\bigsqcap", - "\\bigsqcup", - "\\smallint", - "\u220F", - "\u2210", - "\u2211", - "\u22c0", - "\u22c1", - "\u22c2", - "\u22c3", - "\u2a00", - "\u2a01", - "\u2a02", - "\u2a04", - "\u2a06" - ], - props: { - numArgs: 0 - }, - handler: ({ parser, funcName }, args) => { - let fName = funcName; - if (fName.length === 1) { - fName = singleCharBigOps[fName]; - } - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: true, - stack: false, // This is true for \stackrel{}, not here. - name: fName - }; - }, - mathmlBuilder: mathmlBuilder$2 -}); - -// Note: calling defineFunction with a type that's already been defined only -// works because the same mathmlBuilder is being used. -defineFunction({ - type: "op", - names: ["\\mathop"], - props: { - numArgs: 1, - primitive: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - // It would be convienient to just wrap a around the argument. - // But if the argument is a or , that would be invalid MathML. - // In that case, we instead promote the text contents of the body to the parent. - const arr = (body.body) ? body.body : [body]; - const isSymbol = arr.length === 1 && ordAtomTypes.includes(arr[0].type); - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: isSymbol, - stack: false, - name: isSymbol ? arr[0].text : null, - body: isSymbol ? null : ordargument(body) - }; - }, - mathmlBuilder: mathmlBuilder$2 -}); - -// There are 2 flags for operators; whether they produce limits in -// displaystyle, and whether they are symbols and should grow in -// displaystyle. These four groups cover the four possible choices. - -const singleCharIntegrals = { - "\u222b": "\\int", - "\u222c": "\\iint", - "\u222d": "\\iiint", - "\u222e": "\\oint", - "\u222f": "\\oiint", - "\u2230": "\\oiiint", - "\u2231": "\\intclockwise", - "\u2232": "\\varointclockwise", - "\u2a0c": "\\iiiint", - "\u2a0d": "\\intbar", - "\u2a0e": "\\intBar", - "\u2a0f": "\\fint", - "\u2a12": "\\rppolint", - "\u2a13": "\\scpolint", - "\u2a15": "\\pointint", - "\u2a16": "\\sqint", - "\u2a17": "\\intlarhk", - "\u2a18": "\\intx", - "\u2a19": "\\intcap", - "\u2a1a": "\\intcup" -}; - -// No limits, not symbols -defineFunction({ - type: "op", - names: [ - "\\arcsin", - "\\arccos", - "\\arctan", - "\\arctg", - "\\arcctg", - "\\arg", - "\\ch", - "\\cos", - "\\cosec", - "\\cosh", - "\\cot", - "\\cotg", - "\\coth", - "\\csc", - "\\ctg", - "\\cth", - "\\deg", - "\\dim", - "\\exp", - "\\hom", - "\\ker", - "\\lg", - "\\ln", - "\\log", - "\\sec", - "\\sin", - "\\sinh", - "\\sh", - "\\sgn", - "\\tan", - "\\tanh", - "\\tg", - "\\th" - ], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - const prevAtomType = parser.prevAtomType; - const next = parser.gullet.future().text; - return { - type: "op", - mode: parser.mode, - limits: false, - parentIsSupSub: false, - symbol: false, - stack: false, - isFollowedByDelimiter: isDelimiter(next), - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType), - name: funcName - }; - }, - mathmlBuilder: mathmlBuilder$2 -}); - -// Limits, not symbols -defineFunction({ - type: "op", - names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - const prevAtomType = parser.prevAtomType; - const next = parser.gullet.future().text; - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: false, - stack: false, - isFollowedByDelimiter: isDelimiter(next), - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType), - name: funcName - }; - }, - mathmlBuilder: mathmlBuilder$2 -}); - -// No limits, symbols -defineFunction({ - type: "op", - names: [ - "\\int", - "\\iint", - "\\iiint", - "\\iiiint", - "\\oint", - "\\oiint", - "\\oiiint", - "\\intclockwise", - "\\varointclockwise", - "\\intbar", - "\\intBar", - "\\fint", - "\\rppolint", - "\\scpolint", - "\\pointint", - "\\sqint", - "\\intlarhk", - "\\intx", - "\\intcap", - "\\intcup", - "\u222b", - "\u222c", - "\u222d", - "\u222e", - "\u222f", - "\u2230", - "\u2231", - "\u2232", - "\u2a0c", - "\u2a0d", - "\u2a0e", - "\u2a0f", - "\u2a12", - "\u2a13", - "\u2a15", - "\u2a16", - "\u2a17", - "\u2a18", - "\u2a19", - "\u2a1a" - ], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - let fName = funcName; - if (fName.length === 1) { - fName = singleCharIntegrals[fName]; - } - return { - type: "op", - mode: parser.mode, - limits: false, - parentIsSupSub: false, - symbol: true, - stack: false, - name: fName - }; - }, - mathmlBuilder: mathmlBuilder$2 -}); - -/** - * All registered global/built-in macros. - * `macros.js` exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary via `macros.js`. - */ -const _macros = {}; - -// This function might one day accept an additional argument and do more things. -function defineMacro(name, body) { - _macros[name] = body; -} - -// NOTE: Unlike most builders, this one handles not only -// "operatorname", but also "supsub" since \operatorname* can -// affect super/subscripting. - -const mathmlBuilder$1 = (group, style) => { - let expression = buildExpression(group.body, style.withFont("mathrm")); - - // Is expression a string or has it something like a fraction? - let isAllString = true; // default - for (let i = 0; i < expression.length; i++) { - const node = expression[i]; - if (node instanceof mathMLTree.MathNode) { - switch (node.type) { - case "mi": - case "mn": - case "ms": - case "mtext": - break; // Do nothing yet. - case "mspace": - { - if (node.attributes.width) { - const width = node.attributes.width.replace("em", ""); - const ch = spaceCharacter(Number(width)); - if (ch === "") { - isAllString = false; - } else { - expression[i] = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode(ch)]); - } - } - } - break - case "mo": { - const child = node.children[0]; - if (node.children.length === 1 && child instanceof mathMLTree.TextNode) { - child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*"); - } else { - isAllString = false; - } - break - } - default: - isAllString = false; - } - } else { - isAllString = false; - } - } - - if (isAllString) { - // Write a single TextNode instead of multiple nested tags. - const word = expression.map((node) => node.toText()).join(""); - expression = [new mathMLTree.TextNode(word)]; - } else if ( - expression.length === 1 - && utils.contains(["mover", "munder"], expression[0].type) && - (expression[0].children[0].type === "mi" || expression[0].children[0].type === "mtext") - ) { - expression[0].children[0].type = "mi"; - if (group.parentIsSupSub) { - return new mathMLTree.MathNode("mrow", expression) - } else { - const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); - return mathMLTree.newDocumentFragment([expression[0], operator]) - } - } - - let wrapper; - if (isAllString) { - wrapper = new mathMLTree.MathNode("mi", expression); - wrapper.setAttribute("mathvariant", "normal"); - } else { - wrapper = new mathMLTree.MathNode("mrow", expression); - } - - if (!group.parentIsSupSub) { - // Append an . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); - if (group.needsLeadingSpace) { - // LaTeX gives operator spacing, but a gets ord spacing. - // So add a leading space. - const space = new mathMLTree.MathNode("mspace"); - space.setAttribute("width", "0.1667em"); // thin space. - return mathMLTree.newDocumentFragment([space, wrapper, operator]) - } else { - return mathMLTree.newDocumentFragment([wrapper, operator]) - } - } - - return wrapper -}; - -// \operatorname -// amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@ -defineFunction({ - type: "operatorname", - names: ["\\operatorname@", "\\operatornamewithlimits"], - props: { - numArgs: 1, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const body = args[0]; - const prevAtomType = parser.prevAtomType; - return { - type: "operatorname", - mode: parser.mode, - body: ordargument(body), - alwaysHandleSupSub: (funcName === "\\operatornamewithlimits"), - limits: false, - parentIsSupSub: false, - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType) - }; - }, - mathmlBuilder: mathmlBuilder$1 -}); - -defineMacro("\\operatorname", - "\\@ifstar\\operatornamewithlimits\\operatorname@"); - -defineFunctionBuilders({ - type: "ordgroup", - mathmlBuilder(group, style) { - return buildExpressionRow(group.body, style, true); - } -}); - -defineFunction({ - type: "overline", - names: ["\\overline"], - props: { - numArgs: 1 - }, - handler({ parser }, args) { - const body = args[0]; - return { - type: "overline", - mode: parser.mode, - body - }; - }, - mathmlBuilder(group, style) { - const operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u005F")]); - operator.setAttribute("stretchy", "true"); - - const node = new mathMLTree.MathNode( - "mover", - [buildGroup$1(group.body, style), operator] - ); - node.setAttribute("accent", "true"); - - return node; - } -}); - -defineFunction({ - type: "phantom", - names: ["\\phantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "phantom", - mode: parser.mode, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(group.body, style); - return new mathMLTree.MathNode("mphantom", inner); - } -}); - -defineFunction({ - type: "hphantom", - names: ["\\hphantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "hphantom", - mode: parser.mode, - body - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(ordargument(group.body), style); - const phantom = new mathMLTree.MathNode("mphantom", inner); - const node = new mathMLTree.MathNode("mpadded", [phantom]); - node.setAttribute("height", "0px"); - node.setAttribute("depth", "0px"); - return node; - } -}); - -defineFunction({ - type: "vphantom", - names: ["\\vphantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "vphantom", - mode: parser.mode, - body - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(ordargument(group.body), style); - const phantom = new mathMLTree.MathNode("mphantom", inner); - const node = new mathMLTree.MathNode("mpadded", [phantom]); - node.setAttribute("width", "0px"); - return node; - } -}); - -// \pmb is a simulation of bold font. -// The version of \pmb in ambsy.sty works by typesetting three copies of the argument -// with small offsets. We use CSS text-shadow. -// It's a hack. Not as good as a real bold font. Better than nothing. - -defineFunction({ - type: "pmb", - names: ["\\pmb"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "pmb", - mode: parser.mode, - body: ordargument(args[0]) - } - }, - mathmlBuilder(group, style) { - const inner = buildExpression(group.body, style); - // Wrap with an element. - const node = wrapWithMstyle(inner); - node.setAttribute("style", "text-shadow: 0.02em 0.01em 0.04px"); - return node - } -}); - -const sign = num => num >= 0 ? "+" : "-"; - -// \raise, \lower, and \raisebox - -const mathmlBuilder = (group, style) => { - const newStyle = style.withLevel(StyleLevel.TEXT); - const node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, newStyle)]); - const dy = calculateSize(group.dy, style); - node.setAttribute("voffset", dy.number + dy.unit); - const dyAbs = Math.abs(dy.number); - node.setAttribute("height", sign(dy.number) + dyAbs + dy.unit); - node.setAttribute("depth", sign(-dy.number) + dyAbs + dy.unit); - return node -}; - -defineFunction({ - type: "raise", - names: ["\\raise", "\\lower"], - props: { - numArgs: 2, - argTypes: ["size", "primitive"], - primitive: true - }, - handler({ parser, funcName }, args) { - const amount = assertNodeType(args[0], "size").value; - if (funcName === "\\lower") { amount.number *= -1; } - const body = args[1]; - return { - type: "raise", - mode: parser.mode, - dy: amount, - body - }; - }, - mathmlBuilder -}); - - -defineFunction({ - type: "raise", - names: ["\\raisebox"], - props: { - numArgs: 2, - argTypes: ["size", "hbox"], - allowedInText: true - }, - handler({ parser, funcName }, args) { - const amount = assertNodeType(args[0], "size").value; - const body = args[1]; - return { - type: "raise", - mode: parser.mode, - dy: amount, - body - }; - }, - mathmlBuilder -}); - -defineFunction({ - type: "ref", - names: ["\\ref", "\\eqref"], - props: { - numArgs: 1, - argTypes: ["raw"] - }, - handler({ parser, funcName }, args) { - return { - type: "ref", - mode: parser.mode, - funcName, - string: args[0].string.replace(invalidIdRegEx, "") - }; - }, - mathmlBuilder(group, style) { - // Create an empty text node. Set a class and an href. - // The post-processor will populate with the target's tag or equation number. - const classes = group.funcName === "\\ref" ? ["tml-ref"] : ["tml-ref", "tml-eqref"]; - const node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("")], classes); - node.setAttribute("href", "#" + group.string); - return node - } -}); - -defineFunction({ - type: "internal", - names: ["\\relax"], - props: { - numArgs: 0, - allowedInText: true - }, - handler({ parser }) { - return { - type: "internal", - mode: parser.mode - }; - } -}); - -defineFunction({ - type: "rule", - names: ["\\rule"], - props: { - numArgs: 2, - numOptionalArgs: 1, - argTypes: ["size", "size", "size"] - }, - handler({ parser }, args, optArgs) { - const shift = optArgs[0]; - const width = assertNodeType(args[0], "size"); - const height = assertNodeType(args[1], "size"); - return { - type: "rule", - mode: parser.mode, - shift: shift && assertNodeType(shift, "size").value, - width: width.value, - height: height.value - }; - }, - mathmlBuilder(group, style) { - const width = calculateSize(group.width, style); - const height = calculateSize(group.height, style); - const shift = group.shift - ? calculateSize(group.shift, style) - : { number: 0, unit: "em" }; - const color = (style.color && style.getColor()) || "black"; - - const rule = new mathMLTree.MathNode("mspace"); - if (width.number > 0 && height.number > 0) { - rule.setAttribute("mathbackground", color); - } - rule.setAttribute("width", width.number + width.unit); - rule.setAttribute("height", height.number + height.unit); - if (shift.number === 0) { return rule } - - const wrapper = new mathMLTree.MathNode("mpadded", [rule]); - if (shift.number >= 0) { - wrapper.setAttribute("height", "+" + shift.number + shift.unit); - } else { - wrapper.setAttribute("height", shift.number + shift.unit); - wrapper.setAttribute("depth", "+" + -shift.number + shift.unit); - } - wrapper.setAttribute("voffset", shift.number + shift.unit); - return wrapper; - } -}); - -// The size mappings are taken from TeX with \normalsize=10pt. -// We don't have to track script level. MathML does that. -const sizeMap = { - "\\tiny": 0.5, - "\\sixptsize": 0.6, - "\\Tiny": 0.6, - "\\scriptsize": 0.7, - "\\footnotesize": 0.8, - "\\small": 0.9, - "\\normalsize": 1.0, - "\\large": 1.2, - "\\Large": 1.44, - "\\LARGE": 1.728, - "\\huge": 2.074, - "\\Huge": 2.488 -}; - -defineFunction({ - type: "sizing", - names: [ - "\\tiny", - "\\sixptsize", - "\\Tiny", - "\\scriptsize", - "\\footnotesize", - "\\small", - "\\normalsize", - "\\large", - "\\Large", - "\\LARGE", - "\\huge", - "\\Huge" - ], - props: { - numArgs: 0, - allowedInText: true - }, - handler: ({ breakOnTokenText, funcName, parser }, args) => { - if (parser.settings.strict && parser.mode === "math") { - // eslint-disable-next-line no-console - console.log(`Temml strict-mode warning: Command ${funcName} is invalid in math mode.`); - } - const body = parser.parseExpression(false, breakOnTokenText); - return { - type: "sizing", - mode: parser.mode, - funcName, - body - }; - }, - mathmlBuilder: (group, style) => { - const newStyle = style.withFontSize(sizeMap[group.funcName]); - const inner = buildExpression(group.body, newStyle); - // Wrap with an element. - const node = wrapWithMstyle(inner); - const factor = (sizeMap[group.funcName] / style.fontSize).toFixed(4); - node.setAttribute("mathsize", factor + "em"); - return node; - } -}); - -// smash, with optional [tb], as in AMS - -defineFunction({ - type: "smash", - names: ["\\smash"], - props: { - numArgs: 1, - numOptionalArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args, optArgs) => { - let smashHeight = false; - let smashDepth = false; - const tbArg = optArgs[0] && assertNodeType(optArgs[0], "ordgroup"); - if (tbArg) { - // Optional [tb] argument is engaged. - // ref: amsmath: \renewcommand{\smash}[1][tb]{% - // def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}% - let letter = ""; - for (let i = 0; i < tbArg.body.length; ++i) { - const node = tbArg.body[i]; - // TODO: Write an AssertSymbolNode - letter = node.text; - if (letter === "t") { - smashHeight = true; - } else if (letter === "b") { - smashDepth = true; - } else { - smashHeight = false; - smashDepth = false; - break; - } - } - } else { - smashHeight = true; - smashDepth = true; - } - - const body = args[0]; - return { - type: "smash", - mode: parser.mode, - body, - smashHeight, - smashDepth - }; - }, - mathmlBuilder: (group, style) => { - const node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, style)]); - - if (group.smashHeight) { - node.setAttribute("height", "0px"); - } - - if (group.smashDepth) { - node.setAttribute("depth", "0px"); - } - - return node; - } -}); - -defineFunction({ - type: "sqrt", - names: ["\\sqrt"], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser }, args, optArgs) { - const index = optArgs[0]; - const body = args[0]; - return { - type: "sqrt", - mode: parser.mode, - body, - index - }; - }, - mathmlBuilder(group, style) { - const { body, index } = group; - return index - ? new mathMLTree.MathNode("mroot", [ - buildGroup$1(body, style), - buildGroup$1(index, style.incrementLevel()) - ]) - : new mathMLTree.MathNode("msqrt", [buildGroup$1(body, style)]); - } -}); - -const styleMap = { - display: 0, - text: 1, - script: 2, - scriptscript: 3 -}; - -const styleAttributes = { - display: ["0", "true"], - text: ["0", "false"], - script: ["1", "false"], - scriptscript: ["2", "false"] -}; - -defineFunction({ - type: "styling", - names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ breakOnTokenText, funcName, parser }, args) { - // parse out the implicit body - const body = parser.parseExpression(true, breakOnTokenText); - - const scriptLevel = funcName.slice(1, funcName.length - 5); - return { - type: "styling", - mode: parser.mode, - // Figure out what scriptLevel to use by pulling out the scriptLevel from - // the function name - scriptLevel, - body - }; - }, - mathmlBuilder(group, style) { - // Figure out what scriptLevel we're changing to. - const newStyle = style.withLevel(styleMap[group.scriptLevel]); - // The style argument in the next line does NOT directly set a MathML script level. - // It just tracks the style level, in case we need to know it for supsub or mathchoice. - const inner = buildExpression(group.body, newStyle); - // Wrap with an element. - const node = wrapWithMstyle(inner); - - const attr = styleAttributes[group.scriptLevel]; - - // Here is where we set the MathML script level. - node.setAttribute("scriptlevel", attr[0]); - node.setAttribute("displaystyle", attr[1]); - - return node; - } -}); - -/** - * Sometimes, groups perform special rules when they have superscripts or - * subscripts attached to them. This function lets the `supsub` group know that - * Sometimes, groups perform special rules when they have superscripts or - * its inner element should handle the superscripts and subscripts instead of - * handling them itself. - */ - -// Helpers -const symbolRegEx = /^m(over|under|underover)$/; - -// Super scripts and subscripts, whose precise placement can depend on other -// functions that precede them. -defineFunctionBuilders({ - type: "supsub", - mathmlBuilder(group, style) { - // Is the inner group a relevant horizonal brace? - let isBrace = false; - let isOver; - let isSup; - let appendApplyFunction = false; - let needsLeadingSpace = false; - - if (group.base && group.base.type === "horizBrace") { - isSup = !!group.sup; - if (isSup === group.base.isOver) { - isBrace = true; - isOver = group.base.isOver; - } - } - - if (group.base && !group.base.stack && - (group.base.type === "op" || group.base.type === "operatorname")) { - group.base.parentIsSupSub = true; - appendApplyFunction = !group.base.symbol; - needsLeadingSpace = group.base.needsLeadingSpace; - } - - const children = group.base && group.base.stack - ? [buildGroup$1(group.base.body[0], style)] - : [buildGroup$1(group.base, style)]; - - const childStyle = style.inSubOrSup(); - if (group.sub) { - children.push(buildGroup$1(group.sub, childStyle)); - } - - if (group.sup) { - children.push(buildGroup$1(group.sup, childStyle)); - } - - let nodeType; - if (isBrace) { - nodeType = isOver ? "mover" : "munder"; - } else if (!group.sub) { - const base = group.base; - if ( - base && - base.type === "op" && - base.limits && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "mover"; - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (base.limits || style.level === StyleLevel.DISPLAY) - ) { - nodeType = "mover"; - } else { - nodeType = "msup"; - } - } else if (!group.sup) { - const base = group.base; - if ( - base && - base.type === "op" && - base.limits && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "munder"; - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (base.limits || style.level === StyleLevel.DISPLAY) - ) { - nodeType = "munder"; - } else { - nodeType = "msub"; - } - } else { - const base = group.base; - if (base && ((base.type === "op" && base.limits) || base.type === "multiscript") && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "munderover"; - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (style.level === StyleLevel.DISPLAY || base.limits) - ) { - nodeType = "munderover"; - } else { - nodeType = "msubsup"; - } - } - - let node = new mathMLTree.MathNode(nodeType, children); - if (appendApplyFunction) { - // Append an . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); - if (needsLeadingSpace) { - const space = new mathMLTree.MathNode("mspace"); - space.setAttribute("width", "0.1667em"); // thin space. - node = mathMLTree.newDocumentFragment([space, node, operator]); - } else { - node = mathMLTree.newDocumentFragment([node, operator]); - } - } else if (symbolRegEx.test(nodeType)) { - // Wrap in a . Otherwise Firefox stretchy parens will not stretch to include limits. - node = new mathMLTree.MathNode("mrow", [node]); - } - - return node - } -}); - -// Operator ParseNodes created in Parser.js from symbol Groups in src/symbols.js. - -const short = ["\\shortmid", "\\nshortmid", "\\shortparallel", - "\\nshortparallel", "\\smallsetminus"]; - -defineFunctionBuilders({ - type: "atom", - mathmlBuilder(group, style) { - const node = new mathMLTree.MathNode("mo", [makeText(group.text, group.mode)]); - if (group.family === "punct") { - node.setAttribute("separator", "true"); - } else if (group.family === "open" || group.family === "close") { - // Delims built here should not stretch vertically. - // See delimsizing.js for stretchy delims. - if (group.family === "open") { - node.setAttribute("form", "prefix"); - // Set an explicit attribute for stretch. Otherwise Firefox may do it wrong. - node.setAttribute("stretchy", "false"); - } else if (group.family === "close") { - node.setAttribute("form", "postfix"); - node.setAttribute("stretchy", "false"); - } - } else if (group.text === "\\mid") { - // Firefox messes up this spacing if at the end of an . See it explicitly. - node.setAttribute("lspace", "0.22em"); // medium space - node.setAttribute("rspace", "0.22em"); - node.setAttribute("stretchy", "false"); - } else if (short.includes(group.text)) { - node.setAttribute("mathsize", "70%"); - } else if (group.text === ":") { - // ":" is not in the MathML operator dictionary. Give it BIN spacing. - node.attributes.lspace = "0.2222em"; - node.attributes.rspace = "0.2222em"; - } - return node; - } -}); - -/** - * Maps TeX font commands to "mathvariant" attribute in buildMathML.js - */ -const fontMap = { - // styles - mathbf: "bold", - mathrm: "normal", - textit: "italic", - mathit: "italic", - mathnormal: "italic", - - // families - mathbb: "double-struck", - mathcal: "script", - mathfrak: "fraktur", - mathscr: "script", - mathsf: "sans-serif", - mathtt: "monospace", - oldstylenums: "oldstylenums" -}; - -/** - * Returns the math variant as a string or null if none is required. - */ -const getVariant = function(group, style) { - // Handle font specifiers as best we can. - // Chromium does not support the MathML mathvariant attribute. - // So we'll use Unicode replacement characters instead. - // But first, determine the math variant. - - // Deal with the \textit, \textbf, etc., functions. - if (style.fontFamily === "texttt") { - return "monospace" - } else if (style.fontFamily === "textsc") { - return "normal"; // handled via character substitution in symbolsOrd.js. - } else if (style.fontFamily === "textsf") { - if (style.fontShape === "textit" && style.fontWeight === "textbf") { - return "sans-serif-bold-italic" - } else if (style.fontShape === "textit") { - return "sans-serif-italic" - } else if (style.fontWeight === "textbf") { - return "sans-serif-bold" - } else { - return "sans-serif" - } - } else if (style.fontShape === "textit" && style.fontWeight === "textbf") { - return "bold-italic" - } else if (style.fontShape === "textit") { - return "italic" - } else if (style.fontWeight === "textbf") { - return "bold" - } - - // Deal with the \mathit, mathbf, etc, functions. - const font = style.font; - if (!font || font === "mathnormal") { - return null - } - - const mode = group.mode; - switch (font) { - case "mathit": - return "italic" - case "mathrm": { - const codePoint = group.text.codePointAt(0); - // LaTeX \mathrm returns italic for Greek characters. - return (0x03ab < codePoint && codePoint < 0x03cf) ? "italic" : "normal" - } - case "greekItalic": - return "italic" - case "up@greek": - return "normal" - case "boldsymbol": - case "mathboldsymbol": - return "bold-italic" - case "mathbf": - return "bold" - case "mathbb": - return "double-struck" - case "mathfrak": - return "fraktur" - case "mathscr": - case "mathcal": - return "script" - case "mathsf": - return "sans-serif" - case "mathtt": - return "monospace" - case "oldstylenums": - return "oldstylenums" - } - - let text = group.text; - if (symbols[mode][text] && symbols[mode][text].replace) { - text = symbols[mode][text].replace; - } - - return Object.prototype.hasOwnProperty.call(fontMap, font) ? fontMap[font] : null -}; - -// Chromium does not support the MathML `mathvariant` attribute. -// Instead, we replace ASCII characters with Unicode characters that -// are defined in the font as bold, italic, double-struck, etc. -// This module identifies those Unicode code points. - -// First, a few helpers. -const script = Object.freeze({ - B: 0x20EA, // Offset from ASCII B to Unicode script B - E: 0x20EB, - F: 0x20EB, - H: 0x20C3, - I: 0x20C7, - L: 0x20C6, - M: 0x20E6, - R: 0x20C9, - e: 0x20CA, - g: 0x20A3, - o: 0x20C5 -}); - -const frak = Object.freeze({ - C: 0x20EA, - H: 0x20C4, - I: 0x20C8, - R: 0x20CA, - Z: 0x20CE -}); - -const bbb = Object.freeze({ - C: 0x20BF, // blackboard bold - H: 0x20C5, - N: 0x20C7, - P: 0x20C9, - Q: 0x20C9, - R: 0x20CB, - Z: 0x20CA -}); - -const bold = Object.freeze({ - "\u03f5": 0x1D2E7, // lunate epsilon - "\u03d1": 0x1D30C, // vartheta - "\u03f0": 0x1D2EE, // varkappa - "\u03c6": 0x1D319, // varphi - "\u03f1": 0x1D2EF, // varrho - "\u03d6": 0x1D30B // varpi -}); - -const boldItalic = Object.freeze({ - "\u03f5": 0x1D35B, // lunate epsilon - "\u03d1": 0x1D380, // vartheta - "\u03f0": 0x1D362, // varkappa - "\u03c6": 0x1D38D, // varphi - "\u03f1": 0x1D363, // varrho - "\u03d6": 0x1D37F // varpi -}); - -const boldsf = Object.freeze({ - "\u03f5": 0x1D395, // lunate epsilon - "\u03d1": 0x1D3BA, // vartheta - "\u03f0": 0x1D39C, // varkappa - "\u03c6": 0x1D3C7, // varphi - "\u03f1": 0x1D39D, // varrho - "\u03d6": 0x1D3B9 // varpi -}); - -const bisf = Object.freeze({ - "\u03f5": 0x1D3CF, // lunate epsilon - "\u03d1": 0x1D3F4, // vartheta - "\u03f0": 0x1D3D6, // varkappa - "\u03c6": 0x1D401, // varphi - "\u03f1": 0x1D3D7, // varrho - "\u03d6": 0x1D3F3 // varpi -}); - -// Code point offsets below are derived from https://www.unicode.org/charts/PDF/U1D400.pdf -const offset = Object.freeze({ - upperCaseLatin: { // A-Z - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D3BF }, - "italic": ch => { return 0x1D3F3 }, - "bold-italic": ch => { return 0x1D427 }, - "script": ch => { return script[ch] || 0x1D45B }, - "script-bold": ch => { return 0x1D48F }, - "fraktur": ch => { return frak[ch] || 0x1D4C3 }, - "fraktur-bold": ch => { return 0x1D52B }, - "double-struck": ch => { return bbb[ch] || 0x1D4F7 }, - "sans-serif": ch => { return 0x1D55F }, - "sans-serif-bold": ch => { return 0x1D593 }, - "sans-serif-italic": ch => { return 0x1D5C7 }, - "sans-serif-bold-italic": ch => { return 0x1D63C }, - "monospace": ch => { return 0x1D62F } - }, - lowerCaseLatin: { // a-z - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D3B9 }, - "italic": ch => { return ch === "h" ? 0x20A6 : 0x1D3ED }, - "bold-italic": ch => { return 0x1D421 }, - "script": ch => { return script[ch] || 0x1D455 }, - "script-bold": ch => { return 0x1D489 }, - "fraktur": ch => { return 0x1D4BD }, - "fraktur-bold": ch => { return 0x1D525 }, - "double-struck": ch => { return 0x1D4F1 }, - "sans-serif": ch => { return 0x1D559 }, - "sans-serif-bold": ch => { return 0x1D58D }, - "sans-serif-italic": ch => { return 0x1D5C1 }, - "sans-serif-bold-italic": ch => { return 0x1D5F5 }, - "monospace": ch => { return 0x1D629 } - }, - upperCaseGreek: { // A-Ω ∇ - "normal": ch => { return 0 }, - "bold": ch => { return ch === "∇" ? 0x1B4BA : 0x1D317 }, - "italic": ch => { return ch === "∇" ? 0x1B4F4 : 0x1D351 }, - // \boldsymbol actually returns upright bold for upperCaseGreek - "bold-italic": ch => { return ch === "∇" ? 0x1B4BA : 0x1D317 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - // Unicode has no code points for regular-weight san-serif Greek. Use bold. - "sans-serif": ch => { return ch === "∇" ? 0x1B568 : 0x1D3C5 }, - "sans-serif-bold": ch => { return ch === "∇" ? 0x1B568 : 0x1D3C5 }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return ch === "∇" ? 0x1B5A2 : 0x1D3FF }, - "monospace": ch => { return 0 } - }, - lowerCaseGreek: { // α-ω - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D311 }, - "italic": ch => { return 0x1D34B }, - "bold-italic": ch => { return ch === "\u03d5" ? 0x1D37E : 0x1D385 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - // Unicode has no code points for regular-weight san-serif Greek. Use bold. - "sans-serif": ch => { return 0x1D3BF }, - "sans-serif-bold": ch => { return 0x1D3BF }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return 0x1D3F9 }, - "monospace": ch => { return 0 } - }, - varGreek: { // \varGamma, etc - "normal": ch => { return 0 }, - "bold": ch => { return bold[ch] || -51 }, - "italic": ch => { return 0 }, - "bold-italic": ch => { return boldItalic[ch] || 0x3A }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - "sans-serif": ch => { return boldsf[ch] || 0x74 }, - "sans-serif-bold": ch => { return boldsf[ch] || 0x74 }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return bisf[ch] || 0xAE }, - "monospace": ch => { return 0 } - }, - numeral: { // 0-9 - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D79E }, - "italic": ch => { return 0 }, - "bold-italic": ch => { return 0 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0x1D7A8 }, - "sans-serif": ch => { return 0x1D7B2 }, - "sans-serif-bold": ch => { return 0x1D7BC }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return 0 }, - "monospace": ch => { return 0x1D7C6 } - } -}); - -const variantChar = (ch, variant) => { - const codePoint = ch.codePointAt(0); - const block = 0x40 < codePoint && codePoint < 0x5b - ? "upperCaseLatin" - : 0x60 < codePoint && codePoint < 0x7b - ? "lowerCaseLatin" - : (0x390 < codePoint && codePoint < 0x3AA) || ch === "∇" - ? "upperCaseGreek" - : 0x3B0 < codePoint && codePoint < 0x3CA || ch === "\u03d5" - ? "lowerCaseGreek" - : 0x1D6E1 < codePoint && codePoint < 0x1D6FC || bold[ch] - ? "varGreek" - : (0x2F < codePoint && codePoint < 0x3A) - ? "numeral" - : "other"; - return block === "other" - ? ch - : String.fromCodePoint(codePoint + offset[block][variant](ch)) -}; - -const smallCaps = Object.freeze({ - a: "ᴀ", - b: "ʙ", - c: "ᴄ", - d: "ᴅ", - e: "ᴇ", - f: "ꜰ", - g: "ɢ", - h: "ʜ", - i: "ɪ", - j: "ᴊ", - k: "ᴋ", - l: "ʟ", - m: "ᴍ", - n: "ɴ", - o: "ᴏ", - p: "ᴘ", - q: "ǫ", - r: "ʀ", - s: "s", - t: "ᴛ", - u: "ᴜ", - v: "ᴠ", - w: "ᴡ", - x: "x", - y: "ʏ", - z: "ᴢ" -}); - -// "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in -// src/symbols.js. - -const numberRegEx$1 = /^\d(?:[\d,.]*\d)?$/; // Keep in sync with numberRegEx in Parser.js - -const latinRegEx = /[A-Ba-z]/; - -const italicNumber = (text, variant) => { - const mn = new mathMLTree.MathNode("mn", [text]); - const wrapper = new mathMLTree.MathNode("mstyle", [mn]); - wrapper.style["font-style"] = "italic"; - wrapper.style["font-family"] = "Cambria, 'Times New Roman', serif"; - if (variant === "bold-italic") { wrapper.style["font-weight"] = "bold"; } - return wrapper -}; - -defineFunctionBuilders({ - type: "mathord", - mathmlBuilder(group, style) { - const text = makeText(group.text, group.mode, style); - const codePoint = text.text.codePointAt(0); - // Test for upper-case Greek - const defaultVariant = (0x0390 < codePoint && codePoint < 0x03aa) ? "normal" : "italic"; - const variant = getVariant(group, style) || defaultVariant; - if (variant === "script") { - text.text = variantChar(text.text, variant); - return new mathMLTree.MathNode("mi", [text], [style.font]) - } else if (variant !== "italic") { - text.text = variantChar(text.text, variant); - } - let node = new mathMLTree.MathNode("mi", [text]); - // TODO: Handle U+1D49C - U+1D4CF per https://www.unicode.org/charts/PDF/U1D400.pdf - if (variant === "normal") { - node.setAttribute("mathvariant", "normal"); - if (text.text.length === 1) { - // A Firefox bug will apply spacing here, but there should be none. Fix it. - node = new mathMLTree.MathNode("mpadded", [node]); - node.setAttribute("lspace", "0"); - node.setAttribute("width", "+0em"); - } - } - return node - } -}); - -defineFunctionBuilders({ - type: "textord", - mathmlBuilder(group, style) { - let ch = group.text; - const codePoint = ch.codePointAt(0); - if (style.fontFamily === "textsc") { - // Convert small latin letters to small caps. - if (96 < codePoint && codePoint < 123) { - ch = smallCaps[ch]; - } - } - const text = makeText(ch, group.mode, style); - const variant = getVariant(group, style) || "normal"; - - let node; - if (group.mode === "text") { - if (variant === "italic" || variant === "bold-italic") { - if (numberRegEx$1.test(group.text)) { - return italicNumber(text, variant) - } - } - if (variant !== "normal") { - text.text = variantChar(text.text, variant); - } - node = new mathMLTree.MathNode("mtext", [text]); - } else if (numberRegEx$1.test(group.text)) { - if (variant === "oldstylenums") { - const ms = new mathMLTree.MathNode("mstyle", [text], ["oldstylenums"]); - node = new mathMLTree.MathNode("mn", [ms]); - } else if (variant === "italic" || variant === "bold-italic") { - return italicNumber(text, variant) - } else { - if (variant !== "normal") { - text.text = text.text.split("").map(c => variantChar(c, variant)).join(""); - } - node = new mathMLTree.MathNode("mn", [text]); - } - } else if (group.text === "\\prime") { - node = new mathMLTree.MathNode("mo", [text]); - } else { - const origText = text.text; - if (variant !== "italic") { - text.text = variantChar(text.text, variant); - } - node = new mathMLTree.MathNode("mi", [text]); - if (text.text === origText && latinRegEx.test(origText)) { - node.setAttribute("mathvariant", "italic"); - } - } - return node - } -}); - -// A map of CSS-based spacing functions to their CSS class. -const cssSpace = { - "\\nobreak": "nobreak", - "\\allowbreak": "allowbreak" -}; - -// A lookup table to determine whether a spacing function/symbol should be -// treated like a regular space character. If a symbol or command is a key -// in this table, then it should be a regular space character. Furthermore, -// the associated value may have a `className` specifying an extra CSS class -// to add to the created `span`. -const regularSpace = { - " ": {}, - "\\ ": {}, - "~": { - className: "nobreak" - }, - "\\space": {}, - "\\nobreakspace": { - className: "nobreak" - } -}; - -// ParseNode<"spacing"> created in Parser.js from the "spacing" symbol Groups in -// src/symbols.js. -defineFunctionBuilders({ - type: "spacing", - mathmlBuilder(group, style) { - let node; - - if (Object.prototype.hasOwnProperty.call(regularSpace, group.text)) { - // Firefox does not render a space in a . So write a no-break space. - // TODO: If Firefox fixes that bug, uncomment the next line and write ch into the node. - //const ch = (regularSpace[group.text].className === "nobreak") ? "\u00a0" : " " - node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("\u00a0")]); - } else if (Object.prototype.hasOwnProperty.call(cssSpace, group.text)) { - // MathML 3.0 calls for nobreak to occur in an , not an - // Ref: https://www.w3.org/Math/draft-spec/mathml.html#chapter3_presm.lbattrs - node = new mathMLTree.MathNode("mo"); - if (group.text === "\\nobreak") { - node.setAttribute("linebreak", "nobreak"); - } - } else { - throw new ParseError(`Unknown type of space "${group.text}"`) - } - - return node - } -}); - -defineFunctionBuilders({ - type: "tag" -}); - -// For a \tag, the work usually done in a mathmlBuilder is instead done in buildMathML.js. -// That way, a \tag can be pulled out of the parse tree and wrapped around the outer node. - -// Non-mathy text, possibly in a font -const textFontFamilies = { - "\\text": undefined, - "\\textrm": "textrm", - "\\textsf": "textsf", - "\\texttt": "texttt", - "\\textnormal": "textrm", - "\\textsc": "textsc" // small caps -}; - -const textFontWeights = { - "\\textbf": "textbf", - "\\textmd": "textmd" -}; - -const textFontShapes = { - "\\textit": "textit", - "\\textup": "textup" -}; - -const styleWithFont = (group, style) => { - const font = group.font; - // Checks if the argument is a font family or a font style. - if (!font) { - return style; - } else if (textFontFamilies[font]) { - return style.withTextFontFamily(textFontFamilies[font]); - } else if (textFontWeights[font]) { - return style.withTextFontWeight(textFontWeights[font]); - } else { - return style.withTextFontShape(textFontShapes[font]); - } -}; - -defineFunction({ - type: "text", - names: [ - // Font families - "\\text", - "\\textrm", - "\\textsf", - "\\texttt", - "\\textnormal", - "\\textsc", - // Font weights - "\\textbf", - "\\textmd", - // Font Shapes - "\\textit", - "\\textup" - ], - props: { - numArgs: 1, - argTypes: ["text"], - allowedInArgument: true, - allowedInText: true - }, - handler({ parser, funcName }, args) { - const body = args[0]; - return { - type: "text", - mode: parser.mode, - body: ordargument(body), - font: funcName - }; - }, - mathmlBuilder(group, style) { - const newStyle = styleWithFont(group, style); - const mrow = buildExpressionRow(group.body, newStyle); - return utils.consolidateText(mrow) - } -}); - -// Two functions included to enable migration from Mathjax. - -defineFunction({ - type: "tip", - names: ["\\mathtip"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "tip", - mode: parser.mode, - body: args[0], - tip: args[1] - }; - }, - mathmlBuilder: (group, style) => { - const math = buildGroup$1(group.body, style); - const tip = buildGroup$1(group.tip, style); - // Browsers don't support the tooltip actiontype. - // TODO: Come back and fix \mathtip when it can be done via CSS w/o a JS event. - const node = new mathMLTree.MathNode("maction", [math, tip], ["tml-tip"]); - node.setAttribute("actiontype", "tooltip"); - return node - } -}); - -defineFunction({ - type: "tip", - names: ["\\texttip"], - props: { - numArgs: 2, - argTypes: ["math", "text"] - }, - handler({ parser }, args) { - return { - type: "tip", - mode: parser.mode, - body: args[0], - tip: args[1] - }; - }, - mathmlBuilder: (group, style) => { - const math = buildGroup$1(group.body, style); - const tip = buildGroup$1(group.tip, style); - // args[1] only accepted text, so tip is a element or a of them. - let str = ""; - if (tip.type === "mtext") { - str = tip.children[0].text; - } else { - for (const child of tip.children) { - str += child.children[0].text; - } - } - // Implement \texttip via a title attribute. - math.setAttribute("title", str); - return math - } -}); - -defineFunctionBuilders({ - type: "toggle", - mathmlBuilder(group, style) { - const expression = buildExpression(group.body, style); - const node = new mathMLTree.MathNode("maction", expression, [], { cursor: "default" }); - node.setAttribute("actiontype", "toggle"); - return node - } -}); - -defineFunction({ - type: "underline", - names: ["\\underline"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "underline", - mode: parser.mode, - body: args[0] - }; - }, - mathmlBuilder(group, style) { - const operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u005f")]); - operator.setAttribute("stretchy", "true"); - - const node = new mathMLTree.MathNode("munder", - [buildGroup$1(group.body, style), operator] - ); - node.setAttribute("accentunder", "true"); - - return node; - } -}); - -defineFunction({ - type: "verb", - names: ["\\verb"], - props: { - numArgs: 0, - allowedInText: true - }, - handler(context, args, optArgs) { - // \verb and \verb* are dealt with directly in Parser.js. - // If we end up here, it's because of a failure to match the two delimiters - // in the regex in Lexer.js. LaTeX raises the following error when \verb is - // terminated by end of line (or file). - throw new ParseError("\\verb ended by end of line instead of matching delimiter"); - }, - mathmlBuilder(group, style) { - const text = new mathMLTree.TextNode(makeVerb(group)); - const node = new mathMLTree.MathNode("mtext", [text]); - node.setAttribute("mathvariant", "monospace"); - return node; - } -}); - -/** - * Converts verb group into body string. - * - * \verb* replaces each space with an open box \u2423 - * \verb replaces each space with a no-break space \xA0 - */ -const makeVerb = (group) => group.body.replace(/ /g, group.star ? "\u2423" : "\xA0"); - -/** Include this to ensure that all functions are defined. */ - -const functions = _functions; - -/** - * Lexing or parsing positional information for error reporting. - * This object is immutable. - */ -class SourceLocation { - constructor(lexer, start, end) { - this.lexer = lexer; // Lexer holding the input string. - this.start = start; // Start offset, zero-based inclusive. - this.end = end; // End offset, zero-based exclusive. - } - - /** - * Merges two `SourceLocation`s from location providers, given they are - * provided in order of appearance. - * - Returns the first one's location if only the first is provided. - * - Returns a merged range of the first and the last if both are provided - * and their lexers match. - * - Otherwise, returns null. - */ - static range(first, second) { - if (!second) { - return first && first.loc; - } else if (!first || !first.loc || !second.loc || first.loc.lexer !== second.loc.lexer) { - return null; - } else { - return new SourceLocation(first.loc.lexer, first.loc.start, second.loc.end); - } - } -} - -/** - * Interface required to break circular dependency between Token, Lexer, and - * ParseError. - */ - -/** - * The resulting token returned from `lex`. - * - * It consists of the token text plus some position information. - * The position information is essentially a range in an input string, - * but instead of referencing the bare input string, we refer to the lexer. - * That way it is possible to attach extra metadata to the input string, - * like for example a file name or similar. - * - * The position information is optional, so it is OK to construct synthetic - * tokens if appropriate. Not providing available position information may - * lead to degraded error reporting, though. - */ -class Token { - constructor( - text, // the text of this token - loc - ) { - this.text = text; - this.loc = loc; - } - - /** - * Given a pair of tokens (this and endToken), compute a `Token` encompassing - * the whole input range enclosed by these two. - */ - range( - endToken, // last token of the range, inclusive - text // the text of the newly constructed token - ) { - return new Token(text, SourceLocation.range(this, endToken)); - } -} - -/** - * The Lexer class handles tokenizing the input in various ways. Since our - * parser expects us to be able to backtrack, the lexer allows lexing from any - * given starting point. - * - * Its main exposed function is the `lex` function, which takes a position to - * lex from and a type of token to lex. It defers to the appropriate `_innerLex` - * function. - * - * The various `_innerLex` functions perform the actual lexing of different - * kinds. - */ - -/* The following tokenRegex - * - matches typical whitespace (but not NBSP etc.) using its first two groups - * - does not match any control character \x00-\x1f except whitespace - * - does not match a bare backslash - * - matches any ASCII character except those just mentioned - * - does not match the BMP private use area \uE000-\uF8FF - * - does not match bare surrogate code units - * - matches any BMP character except for those just described - * - matches any valid Unicode surrogate pair - * - mathches numerals - * - matches a backslash followed by one or more whitespace characters - * - matches a backslash followed by one or more letters then whitespace - * - matches a backslash followed by any BMP character - * Capturing groups: - * [1] regular whitespace - * [2] backslash followed by whitespace - * [3] anything else, which may include: - * [4] left character of \verb* - * [5] left character of \verb - * [6] backslash followed by word, excluding any trailing whitespace - * Just because the Lexer matches something doesn't mean it's valid input: - * If there is no matching function or symbol definition, the Parser will - * still reject the input. - */ -const spaceRegexString = "[ \r\n\t]"; -const controlWordRegexString = "\\\\[a-zA-Z@]+"; -const controlSymbolRegexString = "\\\\[^\uD800-\uDFFF]"; -const controlWordWhitespaceRegexString = `(${controlWordRegexString})${spaceRegexString}*`; -const controlSpaceRegexString = "\\\\(\n|[ \r\t]+\n?)[ \r\t]*"; -const combiningDiacriticalMarkString = "[\u0300-\u036f]"; -const combiningDiacriticalMarksEndRegex = new RegExp(`${combiningDiacriticalMarkString}+$`); -const tokenRegexString = - `(${spaceRegexString}+)|` + // whitespace - `${controlSpaceRegexString}|` + // whitespace - "(number" + // numbers (in non-strict mode) - "|[!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + // single codepoint - `${combiningDiacriticalMarkString}*` + // ...plus accents - "|[\uD800-\uDBFF][\uDC00-\uDFFF]" + // surrogate pair - `${combiningDiacriticalMarkString}*` + // ...plus accents - "|\\\\verb\\*([^]).*?\\4" + // \verb* - "|\\\\verb([^*a-zA-Z]).*?\\5" + // \verb unstarred - `|${controlWordWhitespaceRegexString}` + // \macroName + spaces - `|${controlSymbolRegexString})`; // \\, \', etc. - -/** Main Lexer class */ -class Lexer { - constructor(input, settings) { - // Separate accents from characters - this.input = input; - this.settings = settings; - this.tokenRegex = new RegExp( - // Strict Temml, like TeX, lexes one numeral at a time. - // Default Temml lexes contiguous numerals into a single element. - tokenRegexString.replace("number|", settings.strict ? "" : "\\d(?:[\\d,.]*\\d)?|"), - "g" - ); - // Category codes. The lexer only supports comment characters (14) for now. - // MacroExpander additionally distinguishes active (13). - this.catcodes = { - "%": 14, // comment character - "~": 13 // active character - }; - } - - setCatcode(char, code) { - this.catcodes[char] = code; - } - - /** - * This function lexes a single token. - */ - lex() { - const input = this.input; - const pos = this.tokenRegex.lastIndex; - if (pos === input.length) { - return new Token("EOF", new SourceLocation(this, pos, pos)); - } - const match = this.tokenRegex.exec(input); - if (match === null || match.index !== pos) { - throw new ParseError( - `Unexpected character: '${input[pos]}'`, - new Token(input[pos], new SourceLocation(this, pos, pos + 1)) - ); - } - const text = match[6] || match[3] || (match[2] ? "\\ " : " "); - - if (this.catcodes[text] === 14) { - // comment character - const nlIndex = input.indexOf("\n", this.tokenRegex.lastIndex); - if (nlIndex === -1) { - this.tokenRegex.lastIndex = input.length; // EOF - if (this.settings.strict) { - throw new ParseError("% comment has no terminating newline; LaTeX would " + - "fail because of commenting the end of math mode") - } - } else { - this.tokenRegex.lastIndex = nlIndex + 1; - } - return this.lex(); - } - - return new Token(text, new SourceLocation(this, pos, this.tokenRegex.lastIndex)); - } -} - -/** - * A `Namespace` refers to a space of nameable things like macros or lengths, - * which can be `set` either globally or local to a nested group, using an - * undo stack similar to how TeX implements this functionality. - * Performance-wise, `get` and `set` take constant time. - */ - -class Namespace { - /** - * Both arguments are optional. The first argument is an object of - * built-in mappings which never change. The second argument is an object - * of initial (global-level) mappings, which will constantly change - * according to any global/top-level `set`s done. - */ - constructor(builtins = {}, globalMacros = {}) { - this.current = globalMacros; - this.builtins = builtins; - this.undefStack = []; - } - - /** - * Start a new nested group, affecting future local `set`s. - */ - beginGroup() { - this.undefStack.push({}); - } - - /** - * End current nested group, restoring values before the group began. - */ - endGroup() { - if (this.undefStack.length === 0) { - throw new ParseError( - "Unbalanced namespace destruction: attempt " + - "to pop global namespace; please report this as a bug" - ); - } - const undefs = this.undefStack.pop(); - for (const undef in undefs) { - if (Object.prototype.hasOwnProperty.call(undefs, undef )) { - if (undefs[undef] === undefined) { - delete this.current[undef]; - } else { - this.current[undef] = undefs[undef]; - } - } - } - } - - /** - * Detect whether `name` has a definition. Equivalent to - * `get(name) != null`. - */ - has(name) { - return Object.prototype.hasOwnProperty.call(this.current, name ) || - Object.prototype.hasOwnProperty.call(this.builtins, name ); - } - - /** - * Get the current value of a name, or `undefined` if there is no value. - * - * Note: Do not use `if (namespace.get(...))` to detect whether a macro - * is defined, as the definition may be the empty string which evaluates - * to `false` in JavaScript. Use `if (namespace.get(...) != null)` or - * `if (namespace.has(...))`. - */ - get(name) { - if (Object.prototype.hasOwnProperty.call(this.current, name )) { - return this.current[name]; - } else { - return this.builtins[name]; - } - } - - /** - * Set the current value of a name, and adds an undo - * operation to the undo stack. - */ - set(name, value) { - // Undo this set at end of this group (possibly to `undefined`), - // unless an undo is already in place, in which case that older - // value is the correct one. - const top = this.undefStack[this.undefStack.length - 1]; - if (top && !Object.prototype.hasOwnProperty.call(top, name )) { - top[name] = this.current[name]; - } - this.current[name] = value; - } -} - -/** - * Predefined macros for Temml. - * This can be used to define some commands in terms of others. - */ -const macros = _macros; - -////////////////////////////////////////////////////////////////////// -// macro tools - -defineMacro("\\noexpand", function(context) { - // The expansion is the token itself; but that token is interpreted - // as if its meaning were ‘\relax’ if it is a control sequence that - // would ordinarily be expanded by TeX’s expansion rules. - const t = context.popToken(); - if (context.isExpandable(t.text)) { - t.noexpand = true; - t.treatAsRelax = true; - } - return { tokens: [t], numArgs: 0 }; -}); - -defineMacro("\\expandafter", function(context) { - // TeX first reads the token that comes immediately after \expandafter, - // without expanding it; let’s call this token t. Then TeX reads the - // token that comes after t (and possibly more tokens, if that token - // has an argument), replacing it by its expansion. Finally TeX puts - // t back in front of that expansion. - const t = context.popToken(); - context.expandOnce(true); // expand only an expandable token - return { tokens: [t], numArgs: 0 }; -}); - -// LaTeX's \@firstoftwo{#1}{#2} expands to #1, skipping #2 -// TeX source: \long\def\@firstoftwo#1#2{#1} -defineMacro("\\@firstoftwo", function(context) { - const args = context.consumeArgs(2); - return { tokens: args[0], numArgs: 0 }; -}); - -// LaTeX's \@secondoftwo{#1}{#2} expands to #2, skipping #1 -// TeX source: \long\def\@secondoftwo#1#2{#2} -defineMacro("\\@secondoftwo", function(context) { - const args = context.consumeArgs(2); - return { tokens: args[1], numArgs: 0 }; -}); - -// LaTeX's \@ifnextchar{#1}{#2}{#3} looks ahead to the next (unexpanded) -// symbol that isn't a space, consuming any spaces but not consuming the -// first nonspace character. If that nonspace character matches #1, then -// the macro expands to #2; otherwise, it expands to #3. -defineMacro("\\@ifnextchar", function(context) { - const args = context.consumeArgs(3); // symbol, if, else - context.consumeSpaces(); - const nextToken = context.future(); - if (args[0].length === 1 && args[0][0].text === nextToken.text) { - return { tokens: args[1], numArgs: 0 }; - } else { - return { tokens: args[2], numArgs: 0 }; - } -}); - -// LaTeX's \@ifstar{#1}{#2} looks ahead to the next (unexpanded) symbol. -// If it is `*`, then it consumes the symbol, and the macro expands to #1; -// otherwise, the macro expands to #2 (without consuming the symbol). -// TeX source: \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}} -defineMacro("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}"); - -// LaTeX's \TextOrMath{#1}{#2} expands to #1 in text mode, #2 in math mode -defineMacro("\\TextOrMath", function(context) { - const args = context.consumeArgs(2); - if (context.mode === "text") { - return { tokens: args[0], numArgs: 0 }; - } else { - return { tokens: args[1], numArgs: 0 }; - } -}); - -const stringFromArg = arg => { - // Reverse the order of the arg and return a string. - let str = ""; - for (let i = arg.length - 1; i > -1; i--) { - str += arg[i].text; - } - return str -}; - -// Lookup table for parsing numbers in base 8 through 16 -const digitToNumber = { - 0: 0, - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9, - a: 10, - A: 10, - b: 11, - B: 11, - c: 12, - C: 12, - d: 13, - D: 13, - e: 14, - E: 14, - f: 15, - F: 15 -}; - -const nextCharNumber = context => { - const numStr = context.future().text; - if (numStr === "EOF") { return [null, ""] } - return [digitToNumber[numStr.charAt(0)], numStr] -}; - -const appendCharNumbers = (number, numStr, base) => { - for (let i = 1; i < numStr.length; i++) { - const digit = digitToNumber[numStr.charAt(i)]; - number *= base; - number += digit; - } - return number -}; - -// TeX \char makes a literal character (catcode 12) using the following forms: -// (see The TeXBook, p. 43) -// \char123 -- decimal -// \char'123 -- octal -// \char"123 -- hex -// \char`x -- character that can be written (i.e. isn't active) -// \char`\x -- character that cannot be written (e.g. %) -// These all refer to characters from the font, so we turn them into special -// calls to a function \@char dealt with in the Parser. -defineMacro("\\char", function(context) { - let token = context.popToken(); - let base; - let number = ""; - if (token.text === "'") { - base = 8; - token = context.popToken(); - } else if (token.text === '"') { - base = 16; - token = context.popToken(); - } else if (token.text === "`") { - token = context.popToken(); - if (token.text[0] === "\\") { - number = token.text.charCodeAt(1); - } else if (token.text === "EOF") { - throw new ParseError("\\char` missing argument"); - } else { - number = token.text.charCodeAt(0); - } - } else { - base = 10; - } - if (base) { - // Parse a number in the given base, starting with first `token`. - let numStr = token.text; - number = digitToNumber[numStr.charAt(0)]; - if (number == null || number >= base) { - throw new ParseError(`Invalid base-${base} digit ${token.text}`); - } - number = appendCharNumbers(number, numStr, base); - let digit; - [digit, numStr] = nextCharNumber(context); - while (digit != null && digit < base) { - number *= base; - number += digit; - number = appendCharNumbers(number, numStr, base); - context.popToken(); - [digit, numStr] = nextCharNumber(context); - } - } - return `\\@char{${number}}`; -}); - -// The Latin Modern font renders at the wrong vertical alignment. -// This macro provides a better rendering. -defineMacro("\\surd", "\\sqrt{}"); - -defineMacro("\\hbox", "\\text{#1}"); - -// Per TeXbook p.122, "/" gets zero operator spacing. -// And MDN recommends using U+2044 instead of / for inline -defineMacro("/", "{\u2044}"); - -// Since Temml has no \par, ignore \long. -defineMacro("\\long", ""); - -////////////////////////////////////////////////////////////////////// -// Grouping -// \let\bgroup={ \let\egroup=} -defineMacro("\\bgroup", "{"); -defineMacro("\\egroup", "}"); - -// Symbols from latex.ltx: -// \def~{\nobreakspace{}} -// \def\lq{`} -// \def\rq{'} -// \def \aa {\r a} -defineMacro("~", "\\nobreakspace"); -defineMacro("\\lq", "`"); -defineMacro("\\rq", "'"); -defineMacro("\\aa", "\\r a"); - -defineMacro("\\Bbbk", "\\Bbb{k}"); - -// \mathstrut from the TeXbook, p 360 -defineMacro("\\mathstrut", "\\vphantom{(}"); - -// \underbar from TeXbook p 353 -defineMacro("\\underbar", "\\underline{\\text{#1}}"); - -////////////////////////////////////////////////////////////////////// -// LaTeX_2ε - -// \vdots{\vbox{\baselineskip4\p@ \lineskiplimit\z@ -// \kern6\p@\hbox{.}\hbox{.}\hbox{.}}} -// We'll call \varvdots, which gets a glyph from symbols.js. -// The zero-width rule gets us an equivalent to the vertical 6pt kern. -defineMacro("\\vdots", "\\mathord{\\varvdots\\rule{0pt}{15pt}}"); -defineMacro("\u22ee", "\\vdots"); - -////////////////////////////////////////////////////////////////////// -// amsmath.sty -// http://mirrors.concertpass.com/tex-archive/macros/latex/required/amsmath/amsmath.pdf - -//\newcommand{\substack}[1]{\subarray{c}#1\endsubarray} -defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}"); - -// \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}} -defineMacro("\\boxed", "\\fbox{$\\displaystyle{#1}$}"); - -// \def\iff{\DOTSB\;\Longleftrightarrow\;} -// \def\implies{\DOTSB\;\Longrightarrow\;} -// \def\impliedby{\DOTSB\;\Longleftarrow\;} -defineMacro("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;"); -defineMacro("\\implies", "\\DOTSB\\;\\Longrightarrow\\;"); -defineMacro("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;"); - -// AMSMath's automatic \dots, based on \mdots@@ macro. -const dotsByToken = { - ",": "\\dotsc", - "\\not": "\\dotsb", - // \keybin@ checks for the following: - "+": "\\dotsb", - "=": "\\dotsb", - "<": "\\dotsb", - ">": "\\dotsb", - "-": "\\dotsb", - "*": "\\dotsb", - ":": "\\dotsb", - // Symbols whose definition starts with \DOTSB: - "\\DOTSB": "\\dotsb", - "\\coprod": "\\dotsb", - "\\bigvee": "\\dotsb", - "\\bigwedge": "\\dotsb", - "\\biguplus": "\\dotsb", - "\\bigcap": "\\dotsb", - "\\bigcup": "\\dotsb", - "\\prod": "\\dotsb", - "\\sum": "\\dotsb", - "\\bigotimes": "\\dotsb", - "\\bigoplus": "\\dotsb", - "\\bigodot": "\\dotsb", - "\\bigsqcap": "\\dotsb", - "\\bigsqcup": "\\dotsb", - "\\And": "\\dotsb", - "\\longrightarrow": "\\dotsb", - "\\Longrightarrow": "\\dotsb", - "\\longleftarrow": "\\dotsb", - "\\Longleftarrow": "\\dotsb", - "\\longleftrightarrow": "\\dotsb", - "\\Longleftrightarrow": "\\dotsb", - "\\mapsto": "\\dotsb", - "\\longmapsto": "\\dotsb", - "\\hookrightarrow": "\\dotsb", - "\\doteq": "\\dotsb", - // Symbols whose definition starts with \mathbin: - "\\mathbin": "\\dotsb", - // Symbols whose definition starts with \mathrel: - "\\mathrel": "\\dotsb", - "\\relbar": "\\dotsb", - "\\Relbar": "\\dotsb", - "\\xrightarrow": "\\dotsb", - "\\xleftarrow": "\\dotsb", - // Symbols whose definition starts with \DOTSI: - "\\DOTSI": "\\dotsi", - "\\int": "\\dotsi", - "\\oint": "\\dotsi", - "\\iint": "\\dotsi", - "\\iiint": "\\dotsi", - "\\iiiint": "\\dotsi", - "\\idotsint": "\\dotsi", - // Symbols whose definition starts with \DOTSX: - "\\DOTSX": "\\dotsx" -}; - -defineMacro("\\dots", function(context) { - // TODO: If used in text mode, should expand to \textellipsis. - // However, in Temml, \textellipsis and \ldots behave the same - // (in text mode), and it's unlikely we'd see any of the math commands - // that affect the behavior of \dots when in text mode. So fine for now - // (until we support \ifmmode ... \else ... \fi). - let thedots = "\\dotso"; - const next = context.expandAfterFuture().text; - if (next in dotsByToken) { - thedots = dotsByToken[next]; - } else if (next.slice(0, 4) === "\\not") { - thedots = "\\dotsb"; - } else if (next in symbols.math) { - if (utils.contains(["bin", "rel"], symbols.math[next].group)) { - thedots = "\\dotsb"; - } - } - return thedots; -}); - -const spaceAfterDots = { - // \rightdelim@ checks for the following: - ")": true, - "]": true, - "\\rbrack": true, - "\\}": true, - "\\rbrace": true, - "\\rangle": true, - "\\rceil": true, - "\\rfloor": true, - "\\rgroup": true, - "\\rmoustache": true, - "\\right": true, - "\\bigr": true, - "\\biggr": true, - "\\Bigr": true, - "\\Biggr": true, - // \extra@ also tests for the following: - $: true, - // \extrap@ checks for the following: - ";": true, - ".": true, - ",": true -}; - -defineMacro("\\dotso", function(context) { - const next = context.future().text; - if (next in spaceAfterDots) { - return "\\ldots\\,"; - } else { - return "\\ldots"; - } -}); - -defineMacro("\\dotsc", function(context) { - const next = context.future().text; - // \dotsc uses \extra@ but not \extrap@, instead specially checking for - // ';' and '.', but doesn't check for ','. - if (next in spaceAfterDots && next !== ",") { - return "\\ldots\\,"; - } else { - return "\\ldots"; - } -}); - -defineMacro("\\cdots", function(context) { - const next = context.future().text; - if (next in spaceAfterDots) { - return "\\@cdots\\,"; - } else { - return "\\@cdots"; - } -}); - -defineMacro("\\dotsb", "\\cdots"); -defineMacro("\\dotsm", "\\cdots"); -defineMacro("\\dotsi", "\\!\\cdots"); -defineMacro("\\idotsint", "\\dotsi"); -// amsmath doesn't actually define \dotsx, but \dots followed by a macro -// starting with \DOTSX implies \dotso, and then \extra@ detects this case -// and forces the added `\,`. -defineMacro("\\dotsx", "\\ldots\\,"); - -// \let\DOTSI\relax -// \let\DOTSB\relax -// \let\DOTSX\relax -defineMacro("\\DOTSI", "\\relax"); -defineMacro("\\DOTSB", "\\relax"); -defineMacro("\\DOTSX", "\\relax"); - -// Spacing, based on amsmath.sty's override of LaTeX defaults -// \DeclareRobustCommand{\tmspace}[3]{% -// \ifmmode\mskip#1#2\else\kern#1#3\fi\relax} -defineMacro("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"); -// \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}} -// TODO: math mode should use \thinmuskip -defineMacro("\\,", "{\\tmspace+{3mu}{.1667em}}"); -// \let\thinspace\, -defineMacro("\\thinspace", "\\,"); -// \def\>{\mskip\medmuskip} -// \renewcommand{\:}{\tmspace+\medmuskip{.2222em}} -// TODO: \> and math mode of \: should use \medmuskip = 4mu plus 2mu minus 4mu -defineMacro("\\>", "\\mskip{4mu}"); -defineMacro("\\:", "{\\tmspace+{4mu}{.2222em}}"); -// \let\medspace\: -defineMacro("\\medspace", "\\:"); -// \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}} -// TODO: math mode should use \thickmuskip = 5mu plus 5mu -defineMacro("\\;", "{\\tmspace+{5mu}{.2777em}}"); -// \let\thickspace\; -defineMacro("\\thickspace", "\\;"); -// \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}} -// TODO: math mode should use \thinmuskip -defineMacro("\\!", "{\\tmspace-{3mu}{.1667em}}"); -// \let\negthinspace\! -defineMacro("\\negthinspace", "\\!"); -// \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}} -// TODO: math mode should use \medmuskip -defineMacro("\\negmedspace", "{\\tmspace-{4mu}{.2222em}}"); -// \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}} -// TODO: math mode should use \thickmuskip -defineMacro("\\negthickspace", "{\\tmspace-{5mu}{.277em}}"); -// \def\enspace{\kern.5em } -defineMacro("\\enspace", "\\kern.5em "); -// \def\enskip{\hskip.5em\relax} -defineMacro("\\enskip", "\\hskip.5em\\relax"); -// \def\quad{\hskip1em\relax} -defineMacro("\\quad", "\\hskip1em\\relax"); -// \def\qquad{\hskip2em\relax} -defineMacro("\\qquad", "\\hskip2em\\relax"); - -// \tag@in@display form of \tag -defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren"); -defineMacro("\\tag@paren", "\\tag@literal{({#1})}"); -defineMacro("\\tag@literal", (context) => { - if (context.macros.get("\\df@tag")) { - throw new ParseError("Multiple \\tag"); - } - return "\\def\\df@tag{\\text{#1}}"; -}); - -// \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin -// {\operator@font mod}\penalty900 -// \mkern5mu\nonscript\mskip-\medmuskip} -// \newcommand{\pod}[1]{\allowbreak -// \if@display\mkern18mu\else\mkern8mu\fi(#1)} -// \renewcommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}} -// \newcommand{\mod}[1]{\allowbreak\if@display\mkern18mu -// \else\mkern12mu\fi{\operator@font mod}\,\,#1} -// TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu -defineMacro("\\bmod", "\\mathbin{\\text{mod}}"); -defineMacro( - "\\pod", - "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)" -); -defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}"); -defineMacro( - "\\mod", - "\\allowbreak" + - "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + - "{\\rm mod}\\,\\,#1" -); - -////////////////////////////////////////////////////////////////////// -// LaTeX source2e - -// \expandafter\let\expandafter\@normalcr -// \csname\expandafter\@gobble\string\\ \endcsname -// \DeclareRobustCommand\newline{\@normalcr\relax} -defineMacro("\\newline", "\\\\\\relax"); - -// \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@} -// TODO: Doesn't normally work in math mode because \@ fails. -defineMacro("\\TeX", "\\textrm{T}\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125em\\textrm{X}"); - -defineMacro( - "\\LaTeX", - "\\textrm{L}\\kern-.35em\\raisebox{0.2em}{\\scriptstyle A}\\kern-.15em\\TeX" -); - -defineMacro( - "\\Temml", - // eslint-disable-next-line max-len - "\\textrm{T}\\kern-0.2em\\lower{0.2em}\\textrm{E}\\kern-0.08em{\\textrm{M}\\kern-0.08em\\raise{0.2em}\\textrm{M}\\kern-0.08em\\textrm{L}}" -); - -// \DeclareRobustCommand\hspace{\@ifstar\@hspacer\@hspace} -// \def\@hspace#1{\hskip #1\relax} -// \def\@hspacer#1{\vrule \@width\z@\nobreak -// \hskip #1\hskip \z@skip} -defineMacro("\\hspace", "\\@ifstar\\@hspacer\\@hspace"); -defineMacro("\\@hspace", "\\hskip #1\\relax"); -defineMacro("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax"); - -defineMacro("\\colon", `\\mathpunct{\\char"3a}`); - -////////////////////////////////////////////////////////////////////// -// mathtools.sty - -defineMacro("\\prescript", "\\pres@cript{_{#1}^{#2}}{}{#3}"); - -//\providecommand\ordinarycolon{:} -defineMacro("\\ordinarycolon", `\\char"3a`); -// Raise to center on the math axis, as closely as possible. -defineMacro("\\vcentcolon", "\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}}"); -// \providecommand*\coloneq{\vcentcolon\mathrel{\mkern-1.2mu}\mathrel{-}} -defineMacro("\\coloneq", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"2212}'); -// \providecommand*\Coloneq{\dblcolon\mathrel{\mkern-1.2mu}\mathrel{-}} -defineMacro("\\Coloneq", '\\mathrel{\\char"2237\\char"2212}'); -// \providecommand*\Eqqcolon{=\mathrel{\mkern-1.2mu}\dblcolon} -defineMacro("\\Eqqcolon", '\\mathrel{\\char"3d\\char"2237}'); -// \providecommand*\Eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\dblcolon} -defineMacro("\\Eqcolon", '\\mathrel{\\char"2212\\char"2237}'); -// \providecommand*\colonapprox{\vcentcolon\mathrel{\mkern-1.2mu}\approx} -defineMacro("\\colonapprox", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"2248}'); -// \providecommand*\Colonapprox{\dblcolon\mathrel{\mkern-1.2mu}\approx} -defineMacro("\\Colonapprox", '\\mathrel{\\char"2237\\char"2248}'); -// \providecommand*\colonsim{\vcentcolon\mathrel{\mkern-1.2mu}\sim} -defineMacro("\\colonsim", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"223c}'); -// \providecommand*\Colonsim{\dblcolon\mathrel{\mkern-1.2mu}\sim} -defineMacro("\\Colonsim", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"223c}'); - -////////////////////////////////////////////////////////////////////// -// colonequals.sty - -// Alternate names for mathtools's macros: -defineMacro("\\ratio", "\\vcentcolon"); -defineMacro("\\coloncolon", "\\dblcolon"); -defineMacro("\\colonequals", "\\coloneqq"); -defineMacro("\\coloncolonequals", "\\Coloneqq"); -defineMacro("\\equalscolon", "\\eqqcolon"); -defineMacro("\\equalscoloncolon", "\\Eqqcolon"); -defineMacro("\\colonminus", "\\coloneq"); -defineMacro("\\coloncolonminus", "\\Coloneq"); -defineMacro("\\minuscolon", "\\eqcolon"); -defineMacro("\\minuscoloncolon", "\\Eqcolon"); -// \colonapprox name is same in mathtools and colonequals. -defineMacro("\\coloncolonapprox", "\\Colonapprox"); -// \colonsim name is same in mathtools and colonequals. -defineMacro("\\coloncolonsim", "\\Colonsim"); - -// Present in newtxmath, pxfonts and txfonts -defineMacro("\\notni", "\\mathrel{\\char`\u220C}"); -defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}"); -defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}"); - -////////////////////////////////////////////////////////////////////// -// From amsopn.sty -defineMacro("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}"); -defineMacro("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}"); -defineMacro("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{\\text{lim}}}"); -defineMacro("\\varliminf", "\\DOTSB\\operatorname*{\\underline{\\text{lim}}}"); -defineMacro("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{\\text{lim}}}"); -defineMacro("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{\\text{lim}}}"); - -defineMacro("\\centerdot", "{\\medspace\\rule{0.167em}{0.189em}\\medspace}"); - -////////////////////////////////////////////////////////////////////// -// statmath.sty -// https://ctan.math.illinois.edu/macros/latex/contrib/statmath/statmath.pdf - -defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}"); -defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}"); -defineMacro("\\plim", "\\DOTSB\\operatorname*{plim}"); - -////////////////////////////////////////////////////////////////////// -// braket.sty -// http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf - -defineMacro("\\bra", "\\mathinner{\\langle{#1}|}"); -defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}"); -defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}"); -defineMacro("\\Bra", "\\left\\langle#1\\right|"); -defineMacro("\\Ket", "\\left|#1\\right\\rangle"); -const braketHelper = (one) => (context) => { - const left = context.consumeArg().tokens; - const middle = context.consumeArg().tokens; - const middleDouble = context.consumeArg().tokens; - const right = context.consumeArg().tokens; - const oldMiddle = context.macros.get("|"); - const oldMiddleDouble = context.macros.get("\\|"); - context.macros.beginGroup(); - const midMacro = (double) => (context) => { - if (one) { - // Only modify the first instance of | or \| - context.macros.set("|", oldMiddle); - if (middleDouble.length) { - context.macros.set("\\|", oldMiddleDouble); - } - } - let doubled = double; - if (!double && middleDouble.length) { - // Mimic \@ifnextchar - const nextToken = context.future(); - if (nextToken.text === "|") { - context.popToken(); - doubled = true; - } - } - return { - tokens: doubled ? middleDouble : middle, - numArgs: 0 - }; - }; - context.macros.set("|", midMacro(false)); - if (middleDouble.length) { - context.macros.set("\\|", midMacro(true)); - } - const arg = context.consumeArg().tokens; - const expanded = context.expandTokens([...right, ...arg, ...left]); // reversed - context.macros.endGroup(); - return { - tokens: expanded.reverse(), - numArgs: 0 - }; -}; -defineMacro("\\bra@ket", braketHelper(false)); -defineMacro("\\bra@set", braketHelper(true)); -defineMacro("\\Braket", "\\bra@ket{\\left\\langle}" + - "{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"); -defineMacro("\\Set", "\\bra@set{\\left\\{\\:}" + - "{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"); -defineMacro("\\set", "\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"); - // has no support for special || or \| - -////////////////////////////////////////////////////////////////////// -// actuarialangle.dtx -defineMacro("\\angln", "{\\angl n}"); - -////////////////////////////////////////////////////////////////////// -// derivative.sty -defineMacro("\\odv", "\\@ifstar\\odv@next\\odv@numerator"); -defineMacro("\\odv@numerator", "\\frac{\\mathrm{d}#1}{\\mathrm{d}#2}"); -defineMacro("\\odv@next", "\\frac{\\mathrm{d}}{\\mathrm{d}#2}#1"); -defineMacro("\\pdv", "\\@ifstar\\pdv@next\\pdv@numerator"); - -const pdvHelper = args => { - const numerator = args[0][0].text; - const denoms = stringFromArg(args[1]).split(","); - const power = String(denoms.length); - const numOp = power === "1" ? "\\partial" : `\\partial^${power}`; - let denominator = ""; - denoms.map(e => { denominator += "\\partial " + e.trim() + "\\,";}); - return [numerator, numOp, denominator.replace(/\\,$/, "")] -}; -defineMacro("\\pdv@numerator", function(context) { - const [numerator, numOp, denominator] = pdvHelper(context.consumeArgs(2)); - return `\\frac{${numOp} ${numerator}}{${denominator}}` -}); -defineMacro("\\pdv@next", function(context) { - const [numerator, numOp, denominator] = pdvHelper(context.consumeArgs(2)); - return `\\frac{${numOp}}{${denominator}} ${numerator}` -}); - -////////////////////////////////////////////////////////////////////// -// upgreek.dtx -defineMacro("\\upalpha", "\\up@greek{\\alpha}"); -defineMacro("\\upbeta", "\\up@greek{\\beta}"); -defineMacro("\\upgamma", "\\up@greek{\\gamma}"); -defineMacro("\\updelta", "\\up@greek{\\delta}"); -defineMacro("\\upepsilon", "\\up@greek{\\epsilon}"); -defineMacro("\\upzeta", "\\up@greek{\\zeta}"); -defineMacro("\\upeta", "\\up@greek{\\eta}"); -defineMacro("\\uptheta", "\\up@greek{\\theta}"); -defineMacro("\\upiota", "\\up@greek{\\iota}"); -defineMacro("\\upkappa", "\\up@greek{\\kappa}"); -defineMacro("\\uplambda", "\\up@greek{\\lambda}"); -defineMacro("\\upmu", "\\up@greek{\\mu}"); -defineMacro("\\upnu", "\\up@greek{\\nu}"); -defineMacro("\\upxi", "\\up@greek{\\xi}"); -defineMacro("\\upomicron", "\\up@greek{\\omicron}"); -defineMacro("\\uppi", "\\up@greek{\\pi}"); -defineMacro("\\upalpha", "\\up@greek{\\alpha}"); -defineMacro("\\uprho", "\\up@greek{\\rho}"); -defineMacro("\\upsigma", "\\up@greek{\\sigma}"); -defineMacro("\\uptau", "\\up@greek{\\tau}"); -defineMacro("\\upupsilon", "\\up@greek{\\upsilon}"); -defineMacro("\\upphi", "\\up@greek{\\phi}"); -defineMacro("\\upchi", "\\up@greek{\\chi}"); -defineMacro("\\uppsi", "\\up@greek{\\psi}"); -defineMacro("\\upomega", "\\up@greek{\\omega}"); - -////////////////////////////////////////////////////////////////////// -// cmll package -defineMacro("\\invamp", '\\mathbin{\\char"214b}'); -defineMacro("\\parr", '\\mathbin{\\char"214b}'); -defineMacro("\\with", '\\mathbin{\\char"26}'); -defineMacro("\\multimapinv", '\\mathrel{\\char"27dc}'); -defineMacro("\\multimapboth", '\\mathrel{\\char"29df}'); -defineMacro("\\scoh", '{\\mkern5mu\\char"2322\\mkern5mu}'); -defineMacro("\\sincoh", '{\\mkern5mu\\char"2323\\mkern5mu}'); -defineMacro("\\coh", `{\\mkern5mu\\rule{}{0.7em}\\mathrlap{\\smash{\\raise2mu{\\char"2322}}} -{\\smash{\\lower4mu{\\char"2323}}}\\mkern5mu}`); -defineMacro("\\incoh", `{\\mkern5mu\\rule{}{0.7em}\\mathrlap{\\smash{\\raise2mu{\\char"2323}}} -{\\smash{\\lower4mu{\\char"2322}}}\\mkern5mu}`); - - -////////////////////////////////////////////////////////////////////// -// chemstyle package -defineMacro("\\standardstate", "\\text{\\tiny\\char`⦵}"); - -/* eslint-disable */ -/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ - -/************************************************************* - * - * Temml mhchem.js - * - * This file implements a Temml version of mhchem version 3.3.0. - * It is adapted from MathJax/extensions/TeX/mhchem.js - * It differs from the MathJax version as follows: - * 1. The interface is changed so that it can be called from Temml, not MathJax. - * 2. \rlap and \llap are replaced with \mathrlap and \mathllap. - * 3. The reaction arrow code is simplified. All reaction arrows are rendered - * using Temml extensible arrows instead of building non-extensible arrows. - * 4. The ~bond forms are composed entirely of \rule elements. - * 5. Two dashes in _getBond are wrapped in braces to suppress spacing. i.e., {-} - * 6. The electron dot uses \textbullet instead of \bullet. - * - * This code, as other Temml code, is released under the MIT license. - * - * /************************************************************* - * - * MathJax/extensions/TeX/mhchem.js - * - * Implements the \ce command for handling chemical formulas - * from the mhchem LaTeX package. - * - * --------------------------------------------------------------------- - * - * Copyright (c) 2011-2015 The MathJax Consortium - * Copyright (c) 2015-2018 Martin Hensel - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Coding Style -// - use '' for identifiers that can by minified/uglified -// - use "" for strings that need to stay untouched - -// version: "3.3.0" for MathJax and Temml - - -// Add \ce, \pu, and \tripleDash to the Temml macros. - -defineMacro("\\ce", function(context) { - return chemParse(context.consumeArgs(1)[0], "ce") -}); - -defineMacro("\\pu", function(context) { - return chemParse(context.consumeArgs(1)[0], "pu"); -}); - -// Math fonts do not include glyphs for the ~ form of bonds. So we'll send path geometry -// So we'll compose characters built from \rule elements. -defineMacro("\\uniDash", `{\\rule{0.672em}{0.06em}}`) -defineMacro("\\triDash", `{\\rule{0.15em}{0.06em}\\kern2mu\\rule{0.15em}{0.06em}\\kern2mu\\rule{0.15em}{0.06em}}`) -defineMacro("\\tripleDash", `\\kern0.075em\\raise0.25em{\\triDash}\\kern0.075em`) -defineMacro("\\tripleDashOverLine", `\\kern0.075em\\mathrlap{\\raise0.125em{\\uniDash}}\\raise0.34em{\\triDash}\\kern0.075em`) -defineMacro("\\tripleDashOverDoubleLine", `\\kern0.075em\\mathrlap{\\mathrlap{\\raise0.48em{\\triDash}}\\raise0.27em{\\uniDash}}{\\raise0.05em{\\uniDash}}\\kern0.075em`) -defineMacro("\\tripleDashBetweenDoubleLine", `\\kern0.075em\\mathrlap{\\mathrlap{\\raise0.48em{\\uniDash}}\\raise0.27em{\\triDash}}{\\raise0.05em{\\uniDash}}\\kern0.075em`) - - // - // This is the main function for handing the \ce and \pu commands. - // It takes the argument to \ce or \pu and returns the corresponding TeX string. - // - - var chemParse = function (tokens, stateMachine) { - // Recreate the argument string from Temml's array of tokens. - var str = ""; - var expectedLoc = tokens.length && tokens[tokens.length - 1].loc.start - for (var i = tokens.length - 1; i >= 0; i--) { - if(tokens[i].loc.start > expectedLoc) { - // context.consumeArgs has eaten a space. - str += " "; - expectedLoc = tokens[i].loc.start; - } - str += tokens[i].text; - expectedLoc += tokens[i].text.length; - } - // Call the mhchem core parser. - var tex = texify.go(mhchemParser.go(str, stateMachine)); - return tex; - }; - - // - // Core parser for mhchem syntax (recursive) - // - /** @type {MhchemParser} */ - var mhchemParser = { - // - // Parses mchem \ce syntax - // - // Call like - // go("H2O"); - // - go: function (input, stateMachine) { - if (!input) { return []; } - if (stateMachine === undefined) { stateMachine = 'ce'; } - var state = '0'; - - // - // String buffers for parsing: - // - // buffer.a == amount - // buffer.o == element - // buffer.b == left-side superscript - // buffer.p == left-side subscript - // buffer.q == right-side subscript - // buffer.d == right-side superscript - // - // buffer.r == arrow - // buffer.rdt == arrow, script above, type - // buffer.rd == arrow, script above, content - // buffer.rqt == arrow, script below, type - // buffer.rq == arrow, script below, content - // - // buffer.text_ - // buffer.rm - // etc. - // - // buffer.parenthesisLevel == int, starting at 0 - // buffer.sb == bool, space before - // buffer.beginsWithBond == bool - // - // These letters are also used as state names. - // - // Other states: - // 0 == begin of main part (arrow/operator unlikely) - // 1 == next entity - // 2 == next entity (arrow/operator unlikely) - // 3 == next atom - // c == macro - // - /** @type {Buffer} */ - var buffer = {}; - buffer['parenthesisLevel'] = 0; - - input = input.replace(/\n/g, " "); - input = input.replace(/[\u2212\u2013\u2014\u2010]/g, "-"); - input = input.replace(/[\u2026]/g, "..."); - - // - // Looks through mhchemParser.transitions, to execute a matching action - // (recursive) - // - var lastInput; - var watchdog = 10; - /** @type {ParserOutput[]} */ - var output = []; - while (true) { - if (lastInput !== input) { - watchdog = 10; - lastInput = input; - } else { - watchdog--; - } - // - // Find actions in transition table - // - var machine = mhchemParser.stateMachines[stateMachine]; - var t = machine.transitions[state] || machine.transitions['*']; - iterateTransitions: - for (var i=0; i 0) { - if (!task.revisit) { - input = matches.remainder; - } - if (!task.toContinue) { - break iterateTransitions; - } - } else { - return output; - } - } - } - // - // Prevent infinite loop - // - if (watchdog <= 0) { - throw ["MhchemBugU", "mhchem bug U. Please report."]; // Unexpected character - } - } - }, - concatArray: function (a, b) { - if (b) { - if (Array.isArray(b)) { - for (var iB=0; iB': /^[=<>]/, - '#': /^[#\u2261]/, - '+': /^\+/, - '-$': /^-(?=[\s_},;\]/]|$|\([a-z]+\))/, // -space -, -; -] -/ -$ -state-of-aggregation - '-9': /^-(?=[0-9])/, - '- orbital overlap': /^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/, - '-': /^-/, - 'pm-operator': /^(?:\\pm|\$\\pm\$|\+-|\+\/-)/, - 'operator': /^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/, - 'arrowUpDown': /^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/, - '\\bond{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\bond{", "", "", "}"); }, - '->': /^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/, - 'CMT': /^[CMT](?=\[)/, - '[(...)]': function (input) { return mhchemParser.patterns.findObserveGroups(input, "[", "", "", "]"); }, - '1st-level escape': /^(&|\\\\|\\hline)\s*/, - '\\,': /^(?:\\[,\ ;:])/, // \\x - but output no space before - '\\x{}{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); }, - '\\x{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", ""); }, - '\\ca': /^\\ca(?:\s+|(?![a-zA-Z]))/, - '\\x': /^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/, - 'orbital': /^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/, // only those with numbers in front, because the others will be formatted correctly anyway - 'others': /^[\/~|]/, - '\\frac{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\frac{", "", "", "}", "{", "", "", "}"); }, - '\\overset{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\overset{", "", "", "}", "{", "", "", "}"); }, - '\\underset{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\underset{", "", "", "}", "{", "", "", "}"); }, - '\\underbrace{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\underbrace{", "", "", "}_", "{", "", "", "}"); }, - '\\color{(...)}0': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}"); }, - '\\color{(...)}{(...)}1': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}", "{", "", "", "}"); }, - '\\color(...){(...)}2': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color", "\\", "", /^(?=\{)/, "{", "", "", "}"); }, - '\\ce{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\ce{", "", "", "}"); }, - 'oxidation$': /^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, - 'd-oxidation$': /^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, // 0 could be oxidation or charge - 'roman numeral': /^[IVX]+/, - '1/2$': /^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/, - 'amount': function (input) { - var match; - // e.g. 2, 0.5, 1/2, -2, n/2, +; $a$ could be added later in parsing - match = input.match(/^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/); - if (match) { - return { match_: match[0], remainder: input.substr(match[0].length) }; - } - var a = mhchemParser.patterns.findObserveGroups(input, "", "$", "$", ""); - if (a) { // e.g. $2n-1$, $-$ - match = a.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/); - if (match) { - return { match_: match[0], remainder: input.substr(match[0].length) }; - } - } - return null; - }, - 'amount2': function (input) { return this['amount'](input); }, - '(KV letters),': /^(?:[A-Z][a-z]{0,2}|i)(?=,)/, - 'formula$': function (input) { - if (input.match(/^\([a-z]+\)$/)) { return null; } // state of aggregation = no formula - var match = input.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/); - if (match) { - return { match_: match[0], remainder: input.substr(match[0].length) }; - } - return null; - }, - 'uprightEntities': /^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/, - '/': /^\s*(\/)\s*/, - '//': /^\s*(\/\/)\s*/, - '*': /^\s*[*.]\s*/ - }, - findObserveGroups: function (input, begExcl, begIncl, endIncl, endExcl, beg2Excl, beg2Incl, end2Incl, end2Excl, combine) { - /** @type {{(input: string, pattern: string | RegExp): string | string[] | null;}} */ - var _match = function (input, pattern) { - if (typeof pattern === "string") { - if (input.indexOf(pattern) !== 0) { return null; } - return pattern; - } else { - var match = input.match(pattern); - if (!match) { return null; } - return match[0]; - } - }; - /** @type {{(input: string, i: number, endChars: string | RegExp): {endMatchBegin: number, endMatchEnd: number} | null;}} */ - var _findObserveGroups = function (input, i, endChars) { - var braces = 0; - while (i < input.length) { - var a = input.charAt(i); - var match = _match(input.substr(i), endChars); - if (match !== null && braces === 0) { - return { endMatchBegin: i, endMatchEnd: i + match.length }; - } else if (a === "{") { - braces++; - } else if (a === "}") { - if (braces === 0) { - throw ["ExtraCloseMissingOpen", "Extra close brace or missing open brace"]; - } else { - braces--; - } - } - i++; - } - if (braces > 0) { - return null; - } - return null; - }; - var match = _match(input, begExcl); - if (match === null) { return null; } - input = input.substr(match.length); - match = _match(input, begIncl); - if (match === null) { return null; } - var e = _findObserveGroups(input, match.length, endIncl || endExcl); - if (e === null) { return null; } - var match1 = input.substring(0, (endIncl ? e.endMatchEnd : e.endMatchBegin)); - if (!(beg2Excl || beg2Incl)) { - return { - match_: match1, - remainder: input.substr(e.endMatchEnd) - }; - } else { - var group2 = this.findObserveGroups(input.substr(e.endMatchEnd), beg2Excl, beg2Incl, end2Incl, end2Excl); - if (group2 === null) { return null; } - /** @type {string[]} */ - var matchRet = [match1, group2.match_]; - return { - match_: (combine ? matchRet.join("") : matchRet), - remainder: group2.remainder - }; - } - }, - - // - // Matching function - // e.g. match("a", input) will look for the regexp called "a" and see if it matches - // returns null or {match_:"a", remainder:"bc"} - // - match_: function (m, input) { - var pattern = mhchemParser.patterns.patterns[m]; - if (pattern === undefined) { - throw ["MhchemBugP", "mhchem bug P. Please report. (" + m + ")"]; // Trying to use non-existing pattern - } else if (typeof pattern === "function") { - return mhchemParser.patterns.patterns[m](input); // cannot use cached var pattern here, because some pattern functions need this===mhchemParser - } else { // RegExp - var match = input.match(pattern); - if (match) { - var mm; - if (match[2]) { - mm = [ match[1], match[2] ]; - } else if (match[1]) { - mm = match[1]; - } else { - mm = match[0]; - } - return { match_: mm, remainder: input.substr(match[0].length) }; - } - return null; - } - } - }, - - // - // Generic state machine actions - // - actions: { - 'a=': function (buffer, m) { buffer.a = (buffer.a || "") + m; }, - 'b=': function (buffer, m) { buffer.b = (buffer.b || "") + m; }, - 'p=': function (buffer, m) { buffer.p = (buffer.p || "") + m; }, - 'o=': function (buffer, m) { buffer.o = (buffer.o || "") + m; }, - 'q=': function (buffer, m) { buffer.q = (buffer.q || "") + m; }, - 'd=': function (buffer, m) { buffer.d = (buffer.d || "") + m; }, - 'rm=': function (buffer, m) { buffer.rm = (buffer.rm || "") + m; }, - 'text=': function (buffer, m) { buffer.text_ = (buffer.text_ || "") + m; }, - 'insert': function (buffer, m, a) { return { type_: a }; }, - 'insert+p1': function (buffer, m, a) { return { type_: a, p1: m }; }, - 'insert+p1+p2': function (buffer, m, a) { return { type_: a, p1: m[0], p2: m[1] }; }, - 'copy': function (buffer, m) { return m; }, - 'rm': function (buffer, m) { return { type_: 'rm', p1: m || ""}; }, - 'text': function (buffer, m) { return mhchemParser.go(m, 'text'); }, - '{text}': function (buffer, m) { - var ret = [ "{" ]; - mhchemParser.concatArray(ret, mhchemParser.go(m, 'text')); - ret.push("}"); - return ret; - }, - 'tex-math': function (buffer, m) { return mhchemParser.go(m, 'tex-math'); }, - 'tex-math tight': function (buffer, m) { return mhchemParser.go(m, 'tex-math tight'); }, - 'bond': function (buffer, m, k) { return { type_: 'bond', kind_: k || m }; }, - 'color0-output': function (buffer, m) { return { type_: 'color0', color: m[0] }; }, - 'ce': function (buffer, m) { return mhchemParser.go(m); }, - '1/2': function (buffer, m) { - /** @type {ParserOutput[]} */ - var ret = []; - if (m.match(/^[+\-]/)) { - ret.push(m.substr(0, 1)); - m = m.substr(1); - } - var n = m.match(/^([0-9]+|\$[a-z]\$|[a-z])\/([0-9]+)(\$[a-z]\$|[a-z])?$/); - n[1] = n[1].replace(/\$/g, ""); - ret.push({ type_: 'frac', p1: n[1], p2: n[2] }); - if (n[3]) { - n[3] = n[3].replace(/\$/g, ""); - ret.push({ type_: 'tex-math', p1: n[3] }); - } - return ret; - }, - '9,9': function (buffer, m) { return mhchemParser.go(m, '9,9'); } - }, - // - // createTransitions - // convert { 'letter': { 'state': { action_: 'output' } } } to { 'state' => [ { pattern: 'letter', task: { action_: [{type_: 'output'}] } } ] } - // with expansion of 'a|b' to 'a' and 'b' (at 2 places) - // - createTransitions: function (o) { - var pattern, state; - /** @type {string[]} */ - var stateArray; - var i; - // - // 1. Collect all states - // - /** @type {Transitions} */ - var transitions = {}; - for (pattern in o) { - for (state in o[pattern]) { - stateArray = state.split("|"); - o[pattern][state].stateArray = stateArray; - for (i=0; i': { - '0|1|2|3': { action_: 'r=', nextState: 'r' }, - 'a|as': { action_: [ 'output', 'r=' ], nextState: 'r' }, - '*': { action_: [ 'output', 'r=' ], nextState: 'r' } }, - '+': { - 'o': { action_: 'd= kv', nextState: 'd' }, - 'd|D': { action_: 'd=', nextState: 'd' }, - 'q': { action_: 'd=', nextState: 'qd' }, - 'qd|qD': { action_: 'd=', nextState: 'qd' }, - 'dq': { action_: [ 'output', 'd=' ], nextState: 'd' }, - '3': { action_: [ 'sb=false', 'output', 'operator' ], nextState: '0' } }, - 'amount': { - '0|2': { action_: 'a=', nextState: 'a' } }, - 'pm-operator': { - '0|1|2|a|as': { action_: [ 'sb=false', 'output', { type_: 'operator', option: '\\pm' } ], nextState: '0' } }, - 'operator': { - '0|1|2|a|as': { action_: [ 'sb=false', 'output', 'operator' ], nextState: '0' } }, - '-$': { - 'o|q': { action_: [ 'charge or bond', 'output' ], nextState: 'qd' }, - 'd': { action_: 'd=', nextState: 'd' }, - 'D': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' }, - 'q': { action_: 'd=', nextState: 'qd' }, - 'qd': { action_: 'd=', nextState: 'qd' }, - 'qD|dq': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' } }, - '-9': { - '3|o': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '3' } }, - '- orbital overlap': { - 'o': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' }, - 'd': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' } }, - '-': { - '0|1|2': { action_: [ { type_: 'output', option: 1 }, 'beginsWithBond=true', { type_: 'bond', option: "-" } ], nextState: '3' }, - '3': { action_: { type_: 'bond', option: "-" } }, - 'a': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' }, - 'as': { action_: [ { type_: 'output', option: 2 }, { type_: 'bond', option: "-" } ], nextState: '3' }, - 'b': { action_: 'b=' }, - 'o': { action_: { type_: '- after o/d', option: false }, nextState: '2' }, - 'q': { action_: { type_: '- after o/d', option: false }, nextState: '2' }, - 'd|qd|dq': { action_: { type_: '- after o/d', option: true }, nextState: '2' }, - 'D|qD|p': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' } }, - 'amount2': { - '1|3': { action_: 'a=', nextState: 'a' } }, - 'letters': { - '0|1|2|3|a|as|b|p|bp|o': { action_: 'o=', nextState: 'o' }, - 'q|dq': { action_: ['output', 'o='], nextState: 'o' }, - 'd|D|qd|qD': { action_: 'o after d', nextState: 'o' } }, - 'digits': { - 'o': { action_: 'q=', nextState: 'q' }, - 'd|D': { action_: 'q=', nextState: 'dq' }, - 'q': { action_: [ 'output', 'o=' ], nextState: 'o' }, - 'a': { action_: 'o=', nextState: 'o' } }, - 'space A': { - 'b|p|bp': {} }, - 'space': { - 'a': { nextState: 'as' }, - '0': { action_: 'sb=false' }, - '1|2': { action_: 'sb=true' }, - 'r|rt|rd|rdt|rdq': { action_: 'output', nextState: '0' }, - '*': { action_: [ 'output', 'sb=true' ], nextState: '1'} }, - '1st-level escape': { - '1|2': { action_: [ 'output', { type_: 'insert+p1', option: '1st-level escape' } ] }, - '*': { action_: [ 'output', { type_: 'insert+p1', option: '1st-level escape' } ], nextState: '0' } }, - '[(...)]': { - 'r|rt': { action_: 'rd=', nextState: 'rd' }, - 'rd|rdt': { action_: 'rq=', nextState: 'rdq' } }, - '...': { - 'o|d|D|dq|qd|qD': { action_: [ 'output', { type_: 'bond', option: "..." } ], nextState: '3' }, - '*': { action_: [ { type_: 'output', option: 1 }, { type_: 'insert', option: 'ellipsis' } ], nextState: '1' } }, - '. |* ': { - '*': { action_: [ 'output', { type_: 'insert', option: 'addition compound' } ], nextState: '1' } }, - 'state of aggregation $': { - '*': { action_: [ 'output', 'state of aggregation' ], nextState: '1' } }, - '{[(': { - 'a|as|o': { action_: [ 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' }, - '0|1|2|3': { action_: [ 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' }, - '*': { action_: [ 'output', 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' } }, - ')]}': { - '0|1|2|3|b|p|bp|o': { action_: [ 'o=', 'parenthesisLevel--' ], nextState: 'o' }, - 'a|as|d|D|q|qd|qD|dq': { action_: [ 'output', 'o=', 'parenthesisLevel--' ], nextState: 'o' } }, - ', ': { - '*': { action_: [ 'output', 'comma' ], nextState: '0' } }, - '^_': { // ^ and _ without a sensible argument - '*': { } }, - '^{(...)}|^($...$)': { - '0|1|2|as': { action_: 'b=', nextState: 'b' }, - 'p': { action_: 'b=', nextState: 'bp' }, - '3|o': { action_: 'd= kv', nextState: 'D' }, - 'q': { action_: 'd=', nextState: 'qD' }, - 'd|D|qd|qD|dq': { action_: [ 'output', 'd=' ], nextState: 'D' } }, - '^a|^\\x{}{}|^\\x{}|^\\x|\'': { - '0|1|2|as': { action_: 'b=', nextState: 'b' }, - 'p': { action_: 'b=', nextState: 'bp' }, - '3|o': { action_: 'd= kv', nextState: 'd' }, - 'q': { action_: 'd=', nextState: 'qd' }, - 'd|qd|D|qD': { action_: 'd=' }, - 'dq': { action_: [ 'output', 'd=' ], nextState: 'd' } }, - '_{(state of aggregation)}$': { - 'd|D|q|qd|qD|dq': { action_: [ 'output', 'q=' ], nextState: 'q' } }, - '_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x': { - '0|1|2|as': { action_: 'p=', nextState: 'p' }, - 'b': { action_: 'p=', nextState: 'bp' }, - '3|o': { action_: 'q=', nextState: 'q' }, - 'd|D': { action_: 'q=', nextState: 'dq' }, - 'q|qd|qD|dq': { action_: [ 'output', 'q=' ], nextState: 'q' } }, - '=<>': { - '0|1|2|3|a|as|o|q|d|D|qd|qD|dq': { action_: [ { type_: 'output', option: 2 }, 'bond' ], nextState: '3' } }, - '#': { - '0|1|2|3|a|as|o': { action_: [ { type_: 'output', option: 2 }, { type_: 'bond', option: "#" } ], nextState: '3' } }, - '{}': { - '*': { action_: { type_: 'output', option: 1 }, nextState: '1' } }, - '{...}': { - '0|1|2|3|a|as|b|p|bp': { action_: 'o=', nextState: 'o' }, - 'o|d|D|q|qd|qD|dq': { action_: [ 'output', 'o=' ], nextState: 'o' } }, - '$...$': { - 'a': { action_: 'a=' }, // 2$n$ - '0|1|2|3|as|b|p|bp|o': { action_: 'o=', nextState: 'o' }, // not 'amount' - 'as|o': { action_: 'o=' }, - 'q|d|D|qd|qD|dq': { action_: [ 'output', 'o=' ], nextState: 'o' } }, - '\\bond{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'bond' ], nextState: "3" } }, - '\\frac{(...)}': { - '*': { action_: [ { type_: 'output', option: 1 }, 'frac-output' ], nextState: '3' } }, - '\\overset{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'overset-output' ], nextState: '3' } }, - '\\underset{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'underset-output' ], nextState: '3' } }, - '\\underbrace{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'underbrace-output' ], nextState: '3' } }, - '\\color{(...)}{(...)}1|\\color(...){(...)}2': { - '*': { action_: [ { type_: 'output', option: 2 }, 'color-output' ], nextState: '3' } }, - '\\color{(...)}0': { - '*': { action_: [ { type_: 'output', option: 2 }, 'color0-output' ] } }, - '\\ce{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'ce' ], nextState: '3' } }, - '\\,': { - '*': { action_: [ { type_: 'output', option: 1 }, 'copy' ], nextState: '1' } }, - '\\x{}{}|\\x{}|\\x': { - '0|1|2|3|a|as|b|p|bp|o|c0': { action_: [ 'o=', 'output' ], nextState: '3' }, - '*': { action_: ['output', 'o=', 'output' ], nextState: '3' } }, - 'others': { - '*': { action_: [ { type_: 'output', option: 1 }, 'copy' ], nextState: '3' } }, - 'else2': { - 'a': { action_: 'a to o', nextState: 'o', revisit: true }, - 'as': { action_: [ 'output', 'sb=true' ], nextState: '1', revisit: true }, - 'r|rt|rd|rdt|rdq': { action_: [ 'output' ], nextState: '0', revisit: true }, - '*': { action_: [ 'output', 'copy' ], nextState: '3' } } - }), - actions: { - 'o after d': function (buffer, m) { - var ret; - if ((buffer.d || "").match(/^[0-9]+$/)) { - var tmp = buffer.d; - buffer.d = undefined; - ret = this['output'](buffer); - buffer.b = tmp; - } else { - ret = this['output'](buffer); - } - mhchemParser.actions['o='](buffer, m); - return ret; - }, - 'd= kv': function (buffer, m) { - buffer.d = m; - buffer.dType = 'kv'; - }, - 'charge or bond': function (buffer, m) { - if (buffer['beginsWithBond']) { - /** @type {ParserOutput[]} */ - var ret = []; - mhchemParser.concatArray(ret, this['output'](buffer)); - mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-")); - return ret; - } else { - buffer.d = m; - } - }, - '- after o/d': function (buffer, m, isAfterD) { - var c1 = mhchemParser.patterns.match_('orbital', buffer.o || ""); - var c2 = mhchemParser.patterns.match_('one lowercase greek letter $', buffer.o || ""); - var c3 = mhchemParser.patterns.match_('one lowercase latin letter $', buffer.o || ""); - var c4 = mhchemParser.patterns.match_('$one lowercase latin letter$ $', buffer.o || ""); - var hyphenFollows = m==="-" && ( c1 && c1.remainder==="" || c2 || c3 || c4 ); - if (hyphenFollows && !buffer.a && !buffer.b && !buffer.p && !buffer.d && !buffer.q && !c1 && c3) { - buffer.o = '$' + buffer.o + '$'; - } - /** @type {ParserOutput[]} */ - var ret = []; - if (hyphenFollows) { - mhchemParser.concatArray(ret, this['output'](buffer)); - ret.push({ type_: 'hyphen' }); - } else { - c1 = mhchemParser.patterns.match_('digits', buffer.d || ""); - if (isAfterD && c1 && c1.remainder==='') { - mhchemParser.concatArray(ret, mhchemParser.actions['d='](buffer, m)); - mhchemParser.concatArray(ret, this['output'](buffer)); - } else { - mhchemParser.concatArray(ret, this['output'](buffer)); - mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-")); - } - } - return ret; - }, - 'a to o': function (buffer) { - buffer.o = buffer.a; - buffer.a = undefined; - }, - 'sb=true': function (buffer) { buffer.sb = true; }, - 'sb=false': function (buffer) { buffer.sb = false; }, - 'beginsWithBond=true': function (buffer) { buffer['beginsWithBond'] = true; }, - 'beginsWithBond=false': function (buffer) { buffer['beginsWithBond'] = false; }, - 'parenthesisLevel++': function (buffer) { buffer['parenthesisLevel']++; }, - 'parenthesisLevel--': function (buffer) { buffer['parenthesisLevel']--; }, - 'state of aggregation': function (buffer, m) { - return { type_: 'state of aggregation', p1: mhchemParser.go(m, 'o') }; - }, - 'comma': function (buffer, m) { - var a = m.replace(/\s*$/, ''); - var withSpace = (a !== m); - if (withSpace && buffer['parenthesisLevel'] === 0) { - return { type_: 'comma enumeration L', p1: a }; - } else { - return { type_: 'comma enumeration M', p1: a }; - } - }, - 'output': function (buffer, m, entityFollows) { - // entityFollows: - // undefined = if we have nothing else to output, also ignore the just read space (buffer.sb) - // 1 = an entity follows, never omit the space if there was one just read before (can only apply to state 1) - // 2 = 1 + the entity can have an amount, so output a\, instead of converting it to o (can only apply to states a|as) - /** @type {ParserOutput | ParserOutput[]} */ - var ret; - if (!buffer.r) { - ret = []; - if (!buffer.a && !buffer.b && !buffer.p && !buffer.o && !buffer.q && !buffer.d && !entityFollows) { - //ret = []; - } else { - if (buffer.sb) { - ret.push({ type_: 'entitySkip' }); - } - if (!buffer.o && !buffer.q && !buffer.d && !buffer.b && !buffer.p && entityFollows!==2) { - buffer.o = buffer.a; - buffer.a = undefined; - } else if (!buffer.o && !buffer.q && !buffer.d && (buffer.b || buffer.p)) { - buffer.o = buffer.a; - buffer.d = buffer.b; - buffer.q = buffer.p; - buffer.a = buffer.b = buffer.p = undefined; - } else { - if (buffer.o && buffer.dType==='kv' && mhchemParser.patterns.match_('d-oxidation$', buffer.d || "")) { - buffer.dType = 'oxidation'; - } else if (buffer.o && buffer.dType==='kv' && !buffer.q) { - buffer.dType = undefined; - } - } - ret.push({ - type_: 'chemfive', - a: mhchemParser.go(buffer.a, 'a'), - b: mhchemParser.go(buffer.b, 'bd'), - p: mhchemParser.go(buffer.p, 'pq'), - o: mhchemParser.go(buffer.o, 'o'), - q: mhchemParser.go(buffer.q, 'pq'), - d: mhchemParser.go(buffer.d, (buffer.dType === 'oxidation' ? 'oxidation' : 'bd')), - dType: buffer.dType - }); - } - } else { // r - /** @type {ParserOutput[]} */ - var rd; - if (buffer.rdt === 'M') { - rd = mhchemParser.go(buffer.rd, 'tex-math'); - } else if (buffer.rdt === 'T') { - rd = [ { type_: 'text', p1: buffer.rd || "" } ]; - } else { - rd = mhchemParser.go(buffer.rd); - } - /** @type {ParserOutput[]} */ - var rq; - if (buffer.rqt === 'M') { - rq = mhchemParser.go(buffer.rq, 'tex-math'); - } else if (buffer.rqt === 'T') { - rq = [ { type_: 'text', p1: buffer.rq || ""} ]; - } else { - rq = mhchemParser.go(buffer.rq); - } - ret = { - type_: 'arrow', - r: buffer.r, - rd: rd, - rq: rq - }; - } - for (var p in buffer) { - if (p !== 'parenthesisLevel' && p !== 'beginsWithBond') { - delete buffer[p]; - } - } - return ret; - }, - 'oxidation-output': function (buffer, m) { - var ret = [ "{" ]; - mhchemParser.concatArray(ret, mhchemParser.go(m, 'oxidation')); - ret.push("}"); - return ret; - }, - 'frac-output': function (buffer, m) { - return { type_: 'frac-ce', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'overset-output': function (buffer, m) { - return { type_: 'overset', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'underset-output': function (buffer, m) { - return { type_: 'underset', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'underbrace-output': function (buffer, m) { - return { type_: 'underbrace', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'color-output': function (buffer, m) { - return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1]) }; - }, - 'r=': function (buffer, m) { buffer.r = m; }, - 'rdt=': function (buffer, m) { buffer.rdt = m; }, - 'rd=': function (buffer, m) { buffer.rd = m; }, - 'rqt=': function (buffer, m) { buffer.rqt = m; }, - 'rq=': function (buffer, m) { buffer.rq = m; }, - 'operator': function (buffer, m, p1) { return { type_: 'operator', kind_: (p1 || m) }; } - } - }, - 'a': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - '1/2$': { - '0': { action_: '1/2' } }, - 'else': { - '0': { nextState: '1', revisit: true } }, - '$(...)$': { - '*': { action_: 'tex-math tight', nextState: '1' } }, - ',': { - '*': { action_: { type_: 'insert', option: 'commaDecimal' } } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: {} - }, - 'o': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - '1/2$': { - '0': { action_: '1/2' } }, - 'else': { - '0': { nextState: '1', revisit: true } }, - 'letters': { - '*': { action_: 'rm' } }, - '\\ca': { - '*': { action_: { type_: 'insert', option: 'circa' } } }, - '\\x{}{}|\\x{}|\\x': { - '*': { action_: 'copy' } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '{(...)}': { - '*': { action_: '{text}' } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: {} - }, - 'text': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '{...}': { - '*': { action_: 'text=' } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '\\greek': { - '*': { action_: [ 'output', 'rm' ] } }, - '\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: [ 'output', 'copy' ] } }, - 'else': { - '*': { action_: 'text=' } } - }), - actions: { - 'output': function (buffer) { - if (buffer.text_) { - /** @type {ParserOutput} */ - var ret = { type_: 'text', p1: buffer.text_ }; - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - } - }, - 'pq': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - 'state of aggregation $': { - '*': { action_: 'state of aggregation' } }, - 'i$': { - '0': { nextState: '!f', revisit: true } }, - '(KV letters),': { - '0': { action_: 'rm', nextState: '0' } }, - 'formula$': { - '0': { nextState: 'f', revisit: true } }, - '1/2$': { - '0': { action_: '1/2' } }, - 'else': { - '0': { nextState: '!f', revisit: true } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '{(...)}': { - '*': { action_: 'text' } }, - 'a-z': { - 'f': { action_: 'tex-math' } }, - 'letters': { - '*': { action_: 'rm' } }, - '-9.,9': { - '*': { action_: '9,9' } }, - ',': { - '*': { action_: { type_: 'insert+p1', option: 'comma enumeration S' } } }, - '\\color{(...)}{(...)}1|\\color(...){(...)}2': { - '*': { action_: 'color-output' } }, - '\\color{(...)}0': { - '*': { action_: 'color0-output' } }, - '\\ce{(...)}': { - '*': { action_: 'ce' } }, - '\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'copy' } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: { - 'state of aggregation': function (buffer, m) { - return { type_: 'state of aggregation subscript', p1: mhchemParser.go(m, 'o') }; - }, - 'color-output': function (buffer, m) { - return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1], 'pq') }; - } - } - }, - 'bd': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - 'x$': { - '0': { nextState: '!f', revisit: true } }, - 'formula$': { - '0': { nextState: 'f', revisit: true } }, - 'else': { - '0': { nextState: '!f', revisit: true } }, - '-9.,9 no missing 0': { - '*': { action_: '9,9' } }, - '.': { - '*': { action_: { type_: 'insert', option: 'electron dot' } } }, - 'a-z': { - 'f': { action_: 'tex-math' } }, - 'x': { - '*': { action_: { type_: 'insert', option: 'KV x' } } }, - 'letters': { - '*': { action_: 'rm' } }, - '\'': { - '*': { action_: { type_: 'insert', option: 'prime' } } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '{(...)}': { - '*': { action_: 'text' } }, - '\\color{(...)}{(...)}1|\\color(...){(...)}2': { - '*': { action_: 'color-output' } }, - '\\color{(...)}0': { - '*': { action_: 'color0-output' } }, - '\\ce{(...)}': { - '*': { action_: 'ce' } }, - '\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'copy' } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: { - 'color-output': function (buffer, m) { - return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1], 'bd') }; - } - } - }, - 'oxidation': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - 'roman numeral': { - '*': { action_: 'roman-numeral' } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - 'else': { - '*': { action_: 'copy' } } - }), - actions: { - 'roman-numeral': function (buffer, m) { return { type_: 'roman numeral', p1: m || "" }; } - } - }, - 'tex-math': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '\\ce{(...)}': { - '*': { action_: [ 'output', 'ce' ] } }, - '{...}|\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'o=' } }, - 'else': { - '*': { action_: 'o=' } } - }), - actions: { - 'output': function (buffer) { - if (buffer.o) { - /** @type {ParserOutput} */ - var ret = { type_: 'tex-math', p1: buffer.o }; - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - } - }, - 'tex-math tight': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '\\ce{(...)}': { - '*': { action_: [ 'output', 'ce' ] } }, - '{...}|\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'o=' } }, - '-|+': { - '*': { action_: 'tight operator' } }, - 'else': { - '*': { action_: 'o=' } } - }), - actions: { - 'tight operator': function (buffer, m) { buffer.o = (buffer.o || "") + "{"+m+"}"; }, - 'output': function (buffer) { - if (buffer.o) { - /** @type {ParserOutput} */ - var ret = { type_: 'tex-math', p1: buffer.o }; - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - } - }, - '9,9': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - ',': { - '*': { action_: 'comma' } }, - 'else': { - '*': { action_: 'copy' } } - }), - actions: { - 'comma': function () { return { type_: 'commaDecimal' }; } - } - }, - //#endregion - // - // \pu state machines - // - //#region pu - 'pu': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - 'space$': { - '*': { action_: [ 'output', 'space' ] } }, - '{[(|)]}': { - '0|a': { action_: 'copy' } }, - '(-)(9)^(-9)': { - '0': { action_: 'number^', nextState: 'a' } }, - '(-)(9.,9)(e)(99)': { - '0': { action_: 'enumber', nextState: 'a' } }, - 'space': { - '0|a': {} }, - 'pm-operator': { - '0|a': { action_: { type_: 'operator', option: '\\pm' }, nextState: '0' } }, - 'operator': { - '0|a': { action_: 'copy', nextState: '0' } }, - '//': { - 'd': { action_: 'o=', nextState: '/' } }, - '/': { - 'd': { action_: 'o=', nextState: '/' } }, - '{...}|else': { - '0|d': { action_: 'd=', nextState: 'd' }, - 'a': { action_: [ 'space', 'd=' ], nextState: 'd' }, - '/|q': { action_: 'q=', nextState: 'q' } } - }), - actions: { - 'enumber': function (buffer, m) { - /** @type {ParserOutput[]} */ - var ret = []; - if (m[0] === "+-" || m[0] === "+/-") { - ret.push("\\pm "); - } else if (m[0]) { - ret.push(m[0]); - } - if (m[1]) { - mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9')); - if (m[2]) { - if (m[2].match(/[,.]/)) { - mhchemParser.concatArray(ret, mhchemParser.go(m[2], 'pu-9,9')); - } else { - ret.push(m[2]); - } - } - m[3] = m[4] || m[3]; - if (m[3]) { - m[3] = m[3].trim(); - if (m[3] === "e" || m[3].substr(0, 1) === "*") { - ret.push({ type_: 'cdot' }); - } else { - ret.push({ type_: 'times' }); - } - } - } - if (m[3]) { - ret.push("10^{"+m[5]+"}"); - } - return ret; - }, - 'number^': function (buffer, m) { - /** @type {ParserOutput[]} */ - var ret = []; - if (m[0] === "+-" || m[0] === "+/-") { - ret.push("\\pm "); - } else if (m[0]) { - ret.push(m[0]); - } - mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9')); - ret.push("^{"+m[2]+"}"); - return ret; - }, - 'operator': function (buffer, m, p1) { return { type_: 'operator', kind_: (p1 || m) }; }, - 'space': function () { return { type_: 'pu-space-1' }; }, - 'output': function (buffer) { - /** @type {ParserOutput | ParserOutput[]} */ - var ret; - var md = mhchemParser.patterns.match_('{(...)}', buffer.d || ""); - if (md && md.remainder === '') { buffer.d = md.match_; } - var mq = mhchemParser.patterns.match_('{(...)}', buffer.q || ""); - if (mq && mq.remainder === '') { buffer.q = mq.match_; } - if (buffer.d) { - buffer.d = buffer.d.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C"); - buffer.d = buffer.d.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F"); - } - if (buffer.q) { // fraction - buffer.q = buffer.q.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C"); - buffer.q = buffer.q.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F"); - var b5 = { - d: mhchemParser.go(buffer.d, 'pu'), - q: mhchemParser.go(buffer.q, 'pu') - }; - if (buffer.o === '//') { - ret = { type_: 'pu-frac', p1: b5.d, p2: b5.q }; - } else { - ret = b5.d; - if (b5.d.length > 1 || b5.q.length > 1) { - ret.push({ type_: ' / ' }); - } else { - ret.push({ type_: '/' }); - } - mhchemParser.concatArray(ret, b5.q); - } - } else { // no fraction - ret = mhchemParser.go(buffer.d, 'pu-2'); - } - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - }, - 'pu-2': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '*': { - '*': { action_: [ 'output', 'cdot' ], nextState: '0' } }, - '\\x': { - '*': { action_: 'rm=' } }, - 'space': { - '*': { action_: [ 'output', 'space' ], nextState: '0' } }, - '^{(...)}|^(-1)': { - '1': { action_: '^(-1)' } }, - '-9.,9': { - '0': { action_: 'rm=', nextState: '0' }, - '1': { action_: '^(-1)', nextState: '0' } }, - '{...}|else': { - '*': { action_: 'rm=', nextState: '1' } } - }), - actions: { - 'cdot': function () { return { type_: 'tight cdot' }; }, - '^(-1)': function (buffer, m) { buffer.rm += "^{"+m+"}"; }, - 'space': function () { return { type_: 'pu-space-2' }; }, - 'output': function (buffer) { - /** @type {ParserOutput | ParserOutput[]} */ - var ret = []; - if (buffer.rm) { - var mrm = mhchemParser.patterns.match_('{(...)}', buffer.rm || ""); - if (mrm && mrm.remainder === '') { - ret = mhchemParser.go(mrm.match_, 'pu'); - } else { - ret = { type_: 'rm', p1: buffer.rm }; - } - } - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - }, - 'pu-9,9': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '0': { action_: 'output-0' }, - 'o': { action_: 'output-o' } }, - ',': { - '0': { action_: [ 'output-0', 'comma' ], nextState: 'o' } }, - '.': { - '0': { action_: [ 'output-0', 'copy' ], nextState: 'o' } }, - 'else': { - '*': { action_: 'text=' } } - }), - actions: { - 'comma': function () { return { type_: 'commaDecimal' }; }, - 'output-0': function (buffer) { - /** @type {ParserOutput[]} */ - var ret = []; - buffer.text_ = buffer.text_ || ""; - if (buffer.text_.length > 4) { - var a = buffer.text_.length % 3; - if (a === 0) { a = 3; } - for (var i=buffer.text_.length-3; i>0; i-=3) { - ret.push(buffer.text_.substr(i, 3)); - ret.push({ type_: '1000 separator' }); - } - ret.push(buffer.text_.substr(0, a)); - ret.reverse(); - } else { - ret.push(buffer.text_); - } - for (var p in buffer) { delete buffer[p]; } - return ret; - }, - 'output-o': function (buffer) { - /** @type {ParserOutput[]} */ - var ret = []; - buffer.text_ = buffer.text_ || ""; - if (buffer.text_.length > 4) { - var a = buffer.text_.length - 3; - for (var i=0; i, so we change \vphantom{X} to {} - // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed. -// res += "{\\vphantom{X}}"; - res += "{{}}"; - res += "_{\\smash[t]{"+b5.q+"}}"; - } - } else { - if (b5.q) { - // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed. -// res += "{\\vphantom{X}}"; - res += "{{}}"; - res += "_{\\smash[t]{"+b5.q+"}}"; - } - if (b5.d) { - // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed. -// res += "{\\vphantom{X}}"; - res += "{{}}"; - res += "^{"+b5.d+"}"; - } - } - break; - case 'rm': - res = "\\mathrm{"+buf.p1+"}"; - break; - case 'text': - if (buf.p1.match(/[\^_]/)) { - buf.p1 = buf.p1.replace(" ", "~").replace("-", "\\text{-}"); - res = "\\mathrm{"+buf.p1+"}"; - } else { - res = "\\text{"+buf.p1+"}"; - } - break; - case 'roman numeral': - res = "\\mathrm{"+buf.p1+"}"; - break; - case 'state of aggregation': - res = "\\mskip2mu "+texify._goInner(buf.p1); - break; - case 'state of aggregation subscript': - res = "\\mskip1mu "+texify._goInner(buf.p1); - break; - case 'bond': - res = texify._getBond(buf.kind_); - if (!res) { - throw ["MhchemErrorBond", "mhchem Error. Unknown bond type (" + buf.kind_ + ")"]; - } - break; - case 'frac': - var c = "\\frac{" + buf.p1 + "}{" + buf.p2 + "}"; - res = "\\mathchoice{\\textstyle"+c+"}{"+c+"}{"+c+"}{"+c+"}"; - break; - case 'pu-frac': - var d = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - res = "\\mathchoice{\\textstyle"+d+"}{"+d+"}{"+d+"}{"+d+"}"; - break; - case 'tex-math': - res = buf.p1 + " "; - break; - case 'frac-ce': - res = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - break; - case 'overset': - res = "\\overset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - break; - case 'underset': - res = "\\underset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - break; - case 'underbrace': - res = "\\underbrace{" + texify._goInner(buf.p1) + "}_{" + texify._goInner(buf.p2) + "}"; - break; - case 'color': - res = "{\\color{" + buf.color1 + "}{" + texify._goInner(buf.color2) + "}}"; - break; - case 'color0': - res = "\\color{" + buf.color + "}"; - break; - case 'arrow': - var b6 = { - rd: texify._goInner(buf.rd), - rq: texify._goInner(buf.rq) - }; - var arrow = texify._getArrow(buf.r); - if (b6.rq) { arrow += "[{\\rm " + b6.rq + "}]"; } - if (b6.rd) { - arrow += "{\\rm " + b6.rd + "}"; - } else { - arrow += "{}"; - } - res = arrow; - break; - case 'operator': - res = texify._getOperator(buf.kind_); - break; - case '1st-level escape': - res = buf.p1+" "; // &, \\\\, \\hlin - break; - case 'space': - res = " "; - break; - case 'entitySkip': - res = "~"; - break; - case 'pu-space-1': - res = "~"; - break; - case 'pu-space-2': - res = "\\mkern3mu "; - break; - case '1000 separator': - res = "\\mkern2mu "; - break; - case 'commaDecimal': - res = "{,}"; - break; - case 'comma enumeration L': - res = "{"+buf.p1+"}\\mkern6mu "; - break; - case 'comma enumeration M': - res = "{"+buf.p1+"}\\mkern3mu "; - break; - case 'comma enumeration S': - res = "{"+buf.p1+"}\\mkern1mu "; - break; - case 'hyphen': - res = "\\text{-}"; - break; - case 'addition compound': - res = "\\,{\\cdot}\\,"; - break; - case 'electron dot': - res = "\\mkern1mu \\text{\\textbullet}\\mkern1mu "; - break; - case 'KV x': - res = "{\\times}"; - break; - case 'prime': - res = "\\prime "; - break; - case 'cdot': - res = "\\cdot "; - break; - case 'tight cdot': - res = "\\mkern1mu{\\cdot}\\mkern1mu "; - break; - case 'times': - res = "\\times "; - break; - case 'circa': - res = "{\\sim}"; - break; - case '^': - res = "uparrow"; - break; - case 'v': - res = "downarrow"; - break; - case 'ellipsis': - res = "\\ldots "; - break; - case '/': - res = "/"; - break; - case ' / ': - res = "\\,/\\,"; - break; - default: - assertNever(buf); - throw ["MhchemBugT", "mhchem bug T. Please report."]; // Missing texify rule or unknown MhchemParser output - } - assertString(res); - return res; - }, - _getArrow: function (a) { - switch (a) { - case "->": return "\\yields"; - case "\u2192": return "\\yields"; - case "\u27F6": return "\\yields"; - case "<-": return "\\yieldsLeft"; - case "<->": return "\\mesomerism"; - case "<-->": return "\\yieldsLeftRight"; - case "<=>": return "\\equilibrium"; - case "\u21CC": return "\\equilibrium"; - case "<=>>": return "\\equilibriumRight"; - case "<<=>": return "\\equilibriumLeft"; - default: - assertNever(a); - throw ["MhchemBugT", "mhchem bug T. Please report."]; - } - }, - _getBond: function (a) { - switch (a) { - case "-": return "{-}"; - case "1": return "{-}"; - case "=": return "{=}"; - case "2": return "{=}"; - case "#": return "{\\equiv}"; - case "3": return "{\\equiv}"; - case "~": return "{\\tripleDash}"; - case "~-": return "{\\tripleDashOverLine}"; - case "~=": return "{\\tripleDashOverDoubleLine}"; - case "~--": return "{\\tripleDashOverDoubleLine}"; - case "-~-": return "{\\tripleDashBetweenDoubleLine}"; - case "...": return "{{\\cdot}{\\cdot}{\\cdot}}"; - case "....": return "{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}"; - case "->": return "{\\rightarrow}"; - case "<-": return "{\\leftarrow}"; - case "<": return "{<}"; - case ">": return "{>}"; - default: - assertNever(a); - throw ["MhchemBugT", "mhchem bug T. Please report."]; - } - }, - _getOperator: function (a) { - switch (a) { - case "+": return " {}+{} "; - case "-": return " {}-{} "; - case "=": return " {}={} "; - case "<": return " {}<{} "; - case ">": return " {}>{} "; - case "<<": return " {}\\ll{} "; - case ">>": return " {}\\gg{} "; - case "\\pm": return " {}\\pm{} "; - case "\\approx": return " {}\\approx{} "; - case "$\\approx$": return " {}\\approx{} "; - case "v": return " \\downarrow{} "; - case "(v)": return " \\downarrow{} "; - case "^": return " \\uparrow{} "; - case "(^)": return " \\uparrow{} "; - default: - assertNever(a); - throw ["MhchemBugT", "mhchem bug T. Please report."]; - } - } - }; - - // - // Helpers for code anaylsis - // Will show type error at calling position - // - /** @param {number} a */ - function assertNever(a) {} - /** @param {string} a */ - function assertString(a) {} - -/* eslint-disable no-undef */ - -////////////////////////////////////////////////////////////////////// -// texvc.sty - -// The texvc package contains macros available in mediawiki pages. -// We omit the functions deprecated at -// https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax - -// We also omit texvc's \O, which conflicts with \text{\O} - -defineMacro("\\darr", "\\downarrow"); -defineMacro("\\dArr", "\\Downarrow"); -defineMacro("\\Darr", "\\Downarrow"); -defineMacro("\\lang", "\\langle"); -defineMacro("\\rang", "\\rangle"); -defineMacro("\\uarr", "\\uparrow"); -defineMacro("\\uArr", "\\Uparrow"); -defineMacro("\\Uarr", "\\Uparrow"); -defineMacro("\\N", "\\mathbb{N}"); -defineMacro("\\R", "\\mathbb{R}"); -defineMacro("\\Z", "\\mathbb{Z}"); -defineMacro("\\alef", "\\aleph"); -defineMacro("\\alefsym", "\\aleph"); -defineMacro("\\bull", "\\bullet"); -defineMacro("\\clubs", "\\clubsuit"); -defineMacro("\\cnums", "\\mathbb{C}"); -defineMacro("\\Complex", "\\mathbb{C}"); -defineMacro("\\Dagger", "\\ddagger"); -defineMacro("\\diamonds", "\\diamondsuit"); -defineMacro("\\empty", "\\emptyset"); -defineMacro("\\exist", "\\exists"); -defineMacro("\\harr", "\\leftrightarrow"); -defineMacro("\\hArr", "\\Leftrightarrow"); -defineMacro("\\Harr", "\\Leftrightarrow"); -defineMacro("\\hearts", "\\heartsuit"); -defineMacro("\\image", "\\Im"); -defineMacro("\\infin", "\\infty"); -defineMacro("\\isin", "\\in"); -defineMacro("\\larr", "\\leftarrow"); -defineMacro("\\lArr", "\\Leftarrow"); -defineMacro("\\Larr", "\\Leftarrow"); -defineMacro("\\lrarr", "\\leftrightarrow"); -defineMacro("\\lrArr", "\\Leftrightarrow"); -defineMacro("\\Lrarr", "\\Leftrightarrow"); -defineMacro("\\natnums", "\\mathbb{N}"); -defineMacro("\\plusmn", "\\pm"); -defineMacro("\\rarr", "\\rightarrow"); -defineMacro("\\rArr", "\\Rightarrow"); -defineMacro("\\Rarr", "\\Rightarrow"); -defineMacro("\\real", "\\Re"); -defineMacro("\\reals", "\\mathbb{R}"); -defineMacro("\\Reals", "\\mathbb{R}"); -defineMacro("\\sdot", "\\cdot"); -defineMacro("\\sect", "\\S"); -defineMacro("\\spades", "\\spadesuit"); -defineMacro("\\sub", "\\subset"); -defineMacro("\\sube", "\\subseteq"); -defineMacro("\\supe", "\\supseteq"); -defineMacro("\\thetasym", "\\vartheta"); -defineMacro("\\weierp", "\\wp"); - -/* eslint-disable no-undef */ - -/**************************************************** - * - * physics.js - * - * Implements the Physics Package for LaTeX input. - * - * --------------------------------------------------------------------- - * - * The original version of this file is licensed as follows: - * Copyright (c) 2015-2016 Kolen Cheung . - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * --------------------------------------------------------------------- - * - * This file has been revised from the original in the following ways: - * 1. The interface is changed so that it can be called from Temml, not MathJax. - * 2. \Re and \Im are not used, to avoid conflict with existing LaTeX letters. - * - * This revision of the file is released under the MIT license. - * https://mit-license.org/ - */ -defineMacro("\\quantity", "{\\left\\{ #1 \\right\\}}"); -defineMacro("\\qty", "{\\left\\{ #1 \\right\\}}"); -defineMacro("\\pqty", "{\\left( #1 \\right)}"); -defineMacro("\\bqty", "{\\left[ #1 \\right]}"); -defineMacro("\\vqty", "{\\left\\vert #1 \\right\\vert}"); -defineMacro("\\Bqty", "{\\left\\{ #1 \\right\\}}"); -defineMacro("\\absolutevalue", "{\\left\\vert #1 \\right\\vert}"); -defineMacro("\\abs", "{\\left\\vert #1 \\right\\vert}"); -defineMacro("\\norm", "{\\left\\Vert #1 \\right\\Vert}"); -defineMacro("\\evaluated", "{\\left.#1 \\right\\vert}"); -defineMacro("\\eval", "{\\left.#1 \\right\\vert}"); -defineMacro("\\order", "{\\mathcal{O} \\left( #1 \\right)}"); -defineMacro("\\commutator", "{\\left[ #1 , #2 \\right]}"); -defineMacro("\\comm", "{\\left[ #1 , #2 \\right]}"); -defineMacro("\\anticommutator", "{\\left\\{ #1 , #2 \\right\\}}"); -defineMacro("\\acomm", "{\\left\\{ #1 , #2 \\right\\}}"); -defineMacro("\\poissonbracket", "{\\left\\{ #1 , #2 \\right\\}}"); -defineMacro("\\pb", "{\\left\\{ #1 , #2 \\right\\}}"); -defineMacro("\\vectorbold", "{\\boldsymbol{ #1 }}"); -defineMacro("\\vb", "{\\boldsymbol{ #1 }}"); -defineMacro("\\vectorarrow", "{\\vec{\\boldsymbol{ #1 }}}"); -defineMacro("\\va", "{\\vec{\\boldsymbol{ #1 }}}"); -defineMacro("\\vectorunit", "{{\\boldsymbol{\\hat{ #1 }}}}"); -defineMacro("\\vu", "{{\\boldsymbol{\\hat{ #1 }}}}"); -defineMacro("\\dotproduct", "\\mathbin{\\boldsymbol\\cdot}"); -defineMacro("\\vdot", "{\\boldsymbol\\cdot}"); -defineMacro("\\crossproduct", "\\mathbin{\\boldsymbol\\times}"); -defineMacro("\\cross", "\\mathbin{\\boldsymbol\\times}"); -defineMacro("\\cp", "\\mathbin{\\boldsymbol\\times}"); -defineMacro("\\gradient", "{\\boldsymbol\\nabla}"); -defineMacro("\\grad", "{\\boldsymbol\\nabla}"); -defineMacro("\\divergence", "{\\grad\\vdot}"); -//defineMacro("\\div", "{\\grad\\vdot}"); Not included in Temml. Conflicts w/LaTeX \div -defineMacro("\\curl", "{\\grad\\cross}"); -defineMacro("\\laplacian", "\\nabla^2"); -defineMacro("\\tr", "{\\operatorname{tr}}"); -defineMacro("\\Tr", "{\\operatorname{Tr}}"); -defineMacro("\\rank", "{\\operatorname{rank}}"); -defineMacro("\\erf", "{\\operatorname{erf}}"); -defineMacro("\\Res", "{\\operatorname{Res}}"); -defineMacro("\\principalvalue", "{\\mathcal{P}}"); -defineMacro("\\pv", "{\\mathcal{P}}"); -defineMacro("\\PV", "{\\operatorname{P.V.}}"); -// Temml does not use the next two lines. They conflict with LaTeX letters. -//defineMacro("\\Re", "{\\operatorname{Re} \\left\\{ #1 \\right\\}}"); -//defineMacro("\\Im", "{\\operatorname{Im} \\left\\{ #1 \\right\\}}"); -defineMacro("\\qqtext", "{\\quad\\text{ #1 }\\quad}"); -defineMacro("\\qq", "{\\quad\\text{ #1 }\\quad}"); -defineMacro("\\qcomma", "{\\text{,}\\quad}"); -defineMacro("\\qc", "{\\text{,}\\quad}"); -defineMacro("\\qcc", "{\\quad\\text{c.c.}\\quad}"); -defineMacro("\\qif", "{\\quad\\text{if}\\quad}"); -defineMacro("\\qthen", "{\\quad\\text{then}\\quad}"); -defineMacro("\\qelse", "{\\quad\\text{else}\\quad}"); -defineMacro("\\qotherwise", "{\\quad\\text{otherwise}\\quad}"); -defineMacro("\\qunless", "{\\quad\\text{unless}\\quad}"); -defineMacro("\\qgiven", "{\\quad\\text{given}\\quad}"); -defineMacro("\\qusing", "{\\quad\\text{using}\\quad}"); -defineMacro("\\qassume", "{\\quad\\text{assume}\\quad}"); -defineMacro("\\qsince", "{\\quad\\text{since}\\quad}"); -defineMacro("\\qlet", "{\\quad\\text{let}\\quad}"); -defineMacro("\\qfor", "{\\quad\\text{for}\\quad}"); -defineMacro("\\qall", "{\\quad\\text{all}\\quad}"); -defineMacro("\\qeven", "{\\quad\\text{even}\\quad}"); -defineMacro("\\qodd", "{\\quad\\text{odd}\\quad}"); -defineMacro("\\qinteger", "{\\quad\\text{integer}\\quad}"); -defineMacro("\\qand", "{\\quad\\text{and}\\quad}"); -defineMacro("\\qor", "{\\quad\\text{or}\\quad}"); -defineMacro("\\qas", "{\\quad\\text{as}\\quad}"); -defineMacro("\\qin", "{\\quad\\text{in}\\quad}"); -defineMacro("\\differential", "{\\text{d}}"); -defineMacro("\\dd", "{\\text{d}}"); -defineMacro("\\derivative", "{\\frac{\\text{d}{ #1 }}{\\text{d}{ #2 }}}"); -defineMacro("\\dv", "{\\frac{\\text{d}{ #1 }}{\\text{d}{ #2 }}}"); -defineMacro("\\partialderivative", "{\\frac{\\partial{ #1 }}{\\partial{ #2 }}}"); -defineMacro("\\variation", "{\\delta}"); -defineMacro("\\var", "{\\delta}"); -defineMacro("\\functionalderivative", "{\\frac{\\delta{ #1 }}{\\delta{ #2 }}}"); -defineMacro("\\fdv", "{\\frac{\\delta{ #1 }}{\\delta{ #2 }}}"); -defineMacro("\\innerproduct", "{\\left\\langle {#1} \\mid { #2} \\right\\rangle}"); -defineMacro("\\outerproduct", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -defineMacro("\\dyad", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -defineMacro("\\ketbra", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -defineMacro("\\op", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -defineMacro("\\expectationvalue", "{\\left\\langle {#1 } \\right\\rangle}"); -defineMacro("\\expval", "{\\left\\langle {#1 } \\right\\rangle}"); -defineMacro("\\ev", "{\\left\\langle {#1 } \\right\\rangle}"); -defineMacro("\\matrixelement", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); -defineMacro("\\matrixel", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); -defineMacro("\\mel", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); - -/** - * This file contains the “gullet” where macros are expanded - * until only non-macro tokens remain. - */ - -// List of commands that act like macros but aren't defined as a macro, -// function, or symbol. Used in `isDefined`. -const implicitCommands = { - "^": true, // Parser.js - _: true, // Parser.js - "\\limits": true, // Parser.js - "\\nolimits": true // Parser.js -}; - -class MacroExpander { - constructor(input, settings, mode) { - this.settings = settings; - this.expansionCount = 0; - this.feed(input); - // Make new global namespace - this.macros = new Namespace(macros, settings.macros); - this.mode = mode; - this.stack = []; // contains tokens in REVERSE order - } - - /** - * Feed a new input string to the same MacroExpander - * (with existing macros etc.). - */ - feed(input) { - this.lexer = new Lexer(input, this.settings); - } - - /** - * Switches between "text" and "math" modes. - */ - switchMode(newMode) { - this.mode = newMode; - } - - /** - * Start a new group nesting within all namespaces. - */ - beginGroup() { - this.macros.beginGroup(); - } - - /** - * End current group nesting within all namespaces. - */ - endGroup() { - this.macros.endGroup(); - } - - /** - * Returns the topmost token on the stack, without expanding it. - * Similar in behavior to TeX's `\futurelet`. - */ - future() { - if (this.stack.length === 0) { - this.pushToken(this.lexer.lex()); - } - return this.stack[this.stack.length - 1] - } - - /** - * Remove and return the next unexpanded token. - */ - popToken() { - this.future(); // ensure non-empty stack - return this.stack.pop(); - } - - /** - * Add a given token to the token stack. In particular, this get be used - * to put back a token returned from one of the other methods. - */ - pushToken(token) { - this.stack.push(token); - } - - /** - * Append an array of tokens to the token stack. - */ - pushTokens(tokens) { - this.stack.push(...tokens); - } - - /** - * Find an macro argument without expanding tokens and append the array of - * tokens to the token stack. Uses Token as a container for the result. - */ - scanArgument(isOptional) { - let start; - let end; - let tokens; - if (isOptional) { - this.consumeSpaces(); // \@ifnextchar gobbles any space following it - if (this.future().text !== "[") { - return null; - } - start = this.popToken(); // don't include [ in tokens - ({ tokens, end } = this.consumeArg(["]"])); - } else { - ({ tokens, start, end } = this.consumeArg()); - } - - // indicate the end of an argument - this.pushToken(new Token("EOF", end.loc)); - - this.pushTokens(tokens); - return start.range(end, ""); - } - - /** - * Consume all following space tokens, without expansion. - */ - consumeSpaces() { - for (;;) { - const token = this.future(); - if (token.text === " ") { - this.stack.pop(); - } else { - break; - } - } - } - - /** - * Consume an argument from the token stream, and return the resulting array - * of tokens and start/end token. - */ - consumeArg(delims) { - // The argument for a delimited parameter is the shortest (possibly - // empty) sequence of tokens with properly nested {...} groups that is - // followed ... by this particular list of non-parameter tokens. - // The argument for an undelimited parameter is the next nonblank - // token, unless that token is ‘{’, when the argument will be the - // entire {...} group that follows. - const tokens = []; - const isDelimited = delims && delims.length > 0; - if (!isDelimited) { - // Ignore spaces between arguments. As the TeXbook says: - // "After you have said ‘\def\row#1#2{...}’, you are allowed to - // put spaces between the arguments (e.g., ‘\row x n’), because - // TeX doesn’t use single spaces as undelimited arguments." - this.consumeSpaces(); - } - const start = this.future(); - let tok; - let depth = 0; - let match = 0; - do { - tok = this.popToken(); - tokens.push(tok); - if (tok.text === "{") { - ++depth; - } else if (tok.text === "}") { - --depth; - if (depth === -1) { - throw new ParseError("Extra }", tok); - } - } else if (tok.text === "EOF") { - throw new ParseError( - "Unexpected end of input in a macro argument" + - ", expected '" + - (delims && isDelimited ? delims[match] : "}") + - "'", - tok - ); - } - if (delims && isDelimited) { - if ((depth === 0 || (depth === 1 && delims[match] === "{")) && tok.text === delims[match]) { - ++match; - if (match === delims.length) { - // don't include delims in tokens - tokens.splice(-match, match); - break; - } - } else { - match = 0; - } - } - } while (depth !== 0 || isDelimited); - // If the argument found ... has the form ‘{}’, - // ... the outermost braces enclosing the argument are removed - if (start.text === "{" && tokens[tokens.length - 1].text === "}") { - tokens.pop(); - tokens.shift(); - } - tokens.reverse(); // to fit in with stack order - return { tokens, start, end: tok }; - } - - /** - * Consume the specified number of (delimited) arguments from the token - * stream and return the resulting array of arguments. - */ - consumeArgs(numArgs, delimiters) { - if (delimiters) { - if (delimiters.length !== numArgs + 1) { - throw new ParseError("The length of delimiters doesn't match the number of args!"); - } - const delims = delimiters[0]; - for (let i = 0; i < delims.length; i++) { - const tok = this.popToken(); - if (delims[i] !== tok.text) { - throw new ParseError("Use of the macro doesn't match its definition", tok); - } - } - } - - const args = []; - for (let i = 0; i < numArgs; i++) { - args.push(this.consumeArg(delimiters && delimiters[i + 1]).tokens); - } - return args; - } - - /** - * Expand the next token only once if possible. - * - * If the token is expanded, the resulting tokens will be pushed onto - * the stack in reverse order and will be returned as an array, - * also in reverse order. - * - * If not, the next token will be returned without removing it - * from the stack. This case can be detected by a `Token` return value - * instead of an `Array` return value. - * - * In either case, the next token will be on the top of the stack, - * or the stack will be empty. - * - * Used to implement `expandAfterFuture` and `expandNextToken`. - * - * If expandableOnly, only expandable tokens are expanded and - * an undefined control sequence results in an error. - */ - expandOnce(expandableOnly) { - const topToken = this.popToken(); - const name = topToken.text; - const expansion = !topToken.noexpand ? this._getExpansion(name) : null; - if (expansion == null || (expandableOnly && expansion.unexpandable)) { - if (expandableOnly && expansion == null && name[0] === "\\" && !this.isDefined(name)) { - throw new ParseError("Undefined control sequence: " + name); - } - this.pushToken(topToken); - return topToken; - } - this.expansionCount++; - if (this.expansionCount > this.settings.maxExpand) { - throw new ParseError( - "Too many expansions: infinite loop or " + "need to increase maxExpand setting" - ); - } - let tokens = expansion.tokens; - const args = this.consumeArgs(expansion.numArgs, expansion.delimiters); - if (expansion.numArgs) { - // paste arguments in place of the placeholders - tokens = tokens.slice(); // make a shallow copy - for (let i = tokens.length - 1; i >= 0; --i) { - let tok = tokens[i]; - if (tok.text === "#") { - if (i === 0) { - throw new ParseError("Incomplete placeholder at end of macro body", tok); - } - tok = tokens[--i]; // next token on stack - if (tok.text === "#") { - // ## → # - tokens.splice(i + 1, 1); // drop first # - } else if (/^[1-9]$/.test(tok.text)) { - // replace the placeholder with the indicated argument - tokens.splice(i, 2, ...args[+tok.text - 1]); - } else { - throw new ParseError("Not a valid argument number", tok); - } - } - } - } - // Concatenate expansion onto top of stack. - this.pushTokens(tokens); - return tokens; - } - - /** - * Expand the next token only once (if possible), and return the resulting - * top token on the stack (without removing anything from the stack). - * Similar in behavior to TeX's `\expandafter\futurelet`. - * Equivalent to expandOnce() followed by future(). - */ - expandAfterFuture() { - this.expandOnce(); - return this.future(); - } - - /** - * Recursively expand first token, then return first non-expandable token. - */ - expandNextToken() { - for (;;) { - const expanded = this.expandOnce(); - // expandOnce returns Token if and only if it's fully expanded. - if (expanded instanceof Token) { - // The token after \noexpand is interpreted as if its meaning were ‘\relax’ - if (expanded.treatAsRelax) { - expanded.text = "\\relax"; - } - return this.stack.pop(); // === expanded - } - } - - // This pathway is impossible. - throw new Error(); // eslint-disable-line no-unreachable - } - - /** - * Fully expand the given macro name and return the resulting list of - * tokens, or return `undefined` if no such macro is defined. - */ - expandMacro(name) { - return this.macros.has(name) ? this.expandTokens([new Token(name)]) : undefined; - } - - /** - * Fully expand the given token stream and return the resulting list of - * tokens. Note that the input tokens are in reverse order, but the - * output tokens are in forward order. - */ - expandTokens(tokens) { - const output = []; - const oldStackLength = this.stack.length; - this.pushTokens(tokens); - while (this.stack.length > oldStackLength) { - const expanded = this.expandOnce(true); // expand only expandable tokens - // expandOnce returns Token if and only if it's fully expanded. - if (expanded instanceof Token) { - if (expanded.treatAsRelax) { - // the expansion of \noexpand is the token itself - expanded.noexpand = false; - expanded.treatAsRelax = false; - } - output.push(this.stack.pop()); - } - } - return output; - } - - /** - * Fully expand the given macro name and return the result as a string, - * or return `undefined` if no such macro is defined. - */ - expandMacroAsText(name) { - const tokens = this.expandMacro(name); - if (tokens) { - return tokens.map((token) => token.text).join(""); - } else { - return tokens; - } - } - - /** - * Returns the expanded macro as a reversed array of tokens and a macro - * argument count. Or returns `null` if no such macro. - */ - _getExpansion(name) { - const definition = this.macros.get(name); - if (definition == null) { - // mainly checking for undefined here - return definition; - } - // If a single character has an associated catcode other than 13 - // (active character), then don't expand it. - if (name.length === 1) { - const catcode = this.lexer.catcodes[name]; - if (catcode != null && catcode !== 13) { - return - } - } - const expansion = typeof definition === "function" ? definition(this) : definition; - if (typeof expansion === "string") { - let numArgs = 0; - if (expansion.indexOf("#") !== -1) { - const stripped = expansion.replace(/##/g, ""); - while (stripped.indexOf("#" + (numArgs + 1)) !== -1) { - ++numArgs; - } - } - const bodyLexer = new Lexer(expansion, this.settings); - const tokens = []; - let tok = bodyLexer.lex(); - while (tok.text !== "EOF") { - tokens.push(tok); - tok = bodyLexer.lex(); - } - tokens.reverse(); // to fit in with stack using push and pop - const expanded = { tokens, numArgs }; - return expanded; - } - - return expansion; - } - - /** - * Determine whether a command is currently "defined" (has some - * functionality), meaning that it's a macro (in the current group), - * a function, a symbol, or one of the special commands listed in - * `implicitCommands`. - */ - isDefined(name) { - return ( - this.macros.has(name) || - Object.prototype.hasOwnProperty.call(functions, name ) || - Object.prototype.hasOwnProperty.call(symbols.math, name ) || - Object.prototype.hasOwnProperty.call(symbols.text, name ) || - Object.prototype.hasOwnProperty.call(implicitCommands, name ) - ); - } - - /** - * Determine whether a command is expandable. - */ - isExpandable(name) { - const macro = this.macros.get(name); - return macro != null - ? typeof macro === "string" || typeof macro === "function" || !macro.unexpandable - : Object.prototype.hasOwnProperty.call(functions, name ) && !functions[name].primitive; - } -} - -/* - * This file defines the Unicode scripts and script families that we - * support. To add new scripts or families, just add a new entry to the - * scriptData array below. Adding scripts to the scriptData array allows - * characters from that script to appear in \text{} environments. - */ - -/** - * Each script or script family has a name and an array of blocks. - * Each block is an array of two numbers which specify the start and - * end points (inclusive) of a block of Unicode codepoints. - -/** - * Unicode block data for the families of scripts we support in \text{}. - * Scripts only need to appear here if they do not have font metrics. - */ -const scriptData = [ - { - // Latin characters beyond the Latin-1 characters we have metrics for. - // Needed for Czech, Hungarian and Turkish text, for example. - name: "latin", - blocks: [ - [0x0100, 0x024f], // Latin Extended-A and Latin Extended-B - [0x0300, 0x036f] // Combining Diacritical marks - ] - }, - { - // The Cyrillic script used by Russian and related languages. - // A Cyrillic subset used to be supported as explicitly defined - // symbols in symbols.js - name: "cyrillic", - blocks: [[0x0400, 0x04ff]] - }, - { - // Armenian - name: "armenian", - blocks: [[0x0530, 0x058f]] - }, - { - // The Brahmic scripts of South and Southeast Asia - // Devanagari (0900–097F) - // Bengali (0980–09FF) - // Gurmukhi (0A00–0A7F) - // Gujarati (0A80–0AFF) - // Oriya (0B00–0B7F) - // Tamil (0B80–0BFF) - // Telugu (0C00–0C7F) - // Kannada (0C80–0CFF) - // Malayalam (0D00–0D7F) - // Sinhala (0D80–0DFF) - // Thai (0E00–0E7F) - // Lao (0E80–0EFF) - // Tibetan (0F00–0FFF) - // Myanmar (1000–109F) - name: "brahmic", - blocks: [[0x0900, 0x109f]] - }, - { - name: "georgian", - blocks: [[0x10a0, 0x10ff]] - }, - { - // Chinese and Japanese. - // The "k" in cjk is for Korean, but we've separated Korean out - name: "cjk", - blocks: [ - [0x3000, 0x30ff], // CJK symbols and punctuation, Hiragana, Katakana - [0x4e00, 0x9faf], // CJK ideograms - [0xff00, 0xff60] // Fullwidth punctuation - // TODO: add halfwidth Katakana and Romanji glyphs - ] - }, - { - // Korean - name: "hangul", - blocks: [[0xac00, 0xd7af]] - } -]; - -/** - * A flattened version of all the supported blocks in a single array. - * This is an optimization to make supportedCodepoint() fast. - */ -const allBlocks = []; -scriptData.forEach((s) => s.blocks.forEach((b) => allBlocks.push(...b))); - -/** - * Given a codepoint, return true if it falls within one of the - * scripts or script families defined above and false otherwise. - * - * Micro benchmarks shows that this is faster than - * /[\u3000-\u30FF\u4E00-\u9FAF\uFF00-\uFF60\uAC00-\uD7AF\u0900-\u109F]/.test() - * in Firefox, Chrome and Node. - */ -function supportedCodepoint(codepoint) { - for (let i = 0; i < allBlocks.length; i += 2) { - if (codepoint >= allBlocks[i] && codepoint <= allBlocks[i + 1]) { - return true; - } - } - return false; -} - -// Helpers for Parser.js handling of Unicode (sub|super)script characters. - -const unicodeSubRegEx = /^[₊₋₌₍₎₀₁₂₃₄₅₆₇₈₉ₐₑₕᵢⱼₖₗₘₙₒₚᵣₛₜᵤᵥₓᵦᵧᵨᵩᵪ]/; - -const uSubsAndSups = Object.freeze({ - '₊': '+', - '₋': '-', - '₌': '=', - '₍': '(', - '₎': ')', - '₀': '0', - '₁': '1', - '₂': '2', - '₃': '3', - '₄': '4', - '₅': '5', - '₆': '6', - '₇': '7', - '₈': '8', - '₉': '9', - '\u2090': 'a', - '\u2091': 'e', - '\u2095': 'h', - '\u1D62': 'i', - '\u2C7C': 'j', - '\u2096': 'k', - '\u2097': 'l', - '\u2098': 'm', - '\u2099': 'n', - '\u2092': 'o', - '\u209A': 'p', - '\u1D63': 'r', - '\u209B': 's', - '\u209C': 't', - '\u1D64': 'u', - '\u1D65': 'v', - '\u2093': 'x', - '\u1D66': 'β', - '\u1D67': 'γ', - '\u1D68': 'ρ', - '\u1D69': '\u03d5', - '\u1D6A': 'χ', - '⁺': '+', - '⁻': '-', - '⁼': '=', - '⁽': '(', - '⁾': ')', - '⁰': '0', - '¹': '1', - '²': '2', - '³': '3', - '⁴': '4', - '⁵': '5', - '⁶': '6', - '⁷': '7', - '⁸': '8', - '⁹': '9', - '\u1D2C': 'A', - '\u1D2E': 'B', - '\u1D30': 'D', - '\u1D31': 'E', - '\u1D33': 'G', - '\u1D34': 'H', - '\u1D35': 'I', - '\u1D36': 'J', - '\u1D37': 'K', - '\u1D38': 'L', - '\u1D39': 'M', - '\u1D3A': 'N', - '\u1D3C': 'O', - '\u1D3E': 'P', - '\u1D3F': 'R', - '\u1D40': 'T', - '\u1D41': 'U', - '\u2C7D': 'V', - '\u1D42': 'W', - '\u1D43': 'a', - '\u1D47': 'b', - '\u1D9C': 'c', - '\u1D48': 'd', - '\u1D49': 'e', - '\u1DA0': 'f', - '\u1D4D': 'g', - '\u02B0': 'h', - '\u2071': 'i', - '\u02B2': 'j', - '\u1D4F': 'k', - '\u02E1': 'l', - '\u1D50': 'm', - '\u207F': 'n', - '\u1D52': 'o', - '\u1D56': 'p', - '\u02B3': 'r', - '\u02E2': 's', - '\u1D57': 't', - '\u1D58': 'u', - '\u1D5B': 'v', - '\u02B7': 'w', - '\u02E3': 'x', - '\u02B8': 'y', - '\u1DBB': 'z', - '\u1D5D': 'β', - '\u1D5E': 'γ', - '\u1D5F': 'δ', - '\u1D60': '\u03d5', - '\u1D61': 'χ', - '\u1DBF': 'θ' -}); - -// Mapping of Unicode accent characters to their LaTeX equivalent in text and -// math mode (when they exist). -var unicodeAccents = { - "\u0301": { text: "\\'", math: "\\acute" }, - "\u0300": { text: "\\`", math: "\\grave" }, - "\u0308": { text: '\\"', math: "\\ddot" }, - "\u0303": { text: "\\~", math: "\\tilde" }, - "\u0304": { text: "\\=", math: "\\bar" }, - "\u0306": { text: "\\u", math: "\\breve" }, - "\u030c": { text: "\\v", math: "\\check" }, - "\u0302": { text: "\\^", math: "\\hat" }, - "\u0307": { text: "\\.", math: "\\dot" }, - "\u030a": { text: "\\r", math: "\\mathring" }, - "\u030b": { text: "\\H" }, - '\u0327': { text: '\\c' } -}; - -var unicodeSymbols = { - "á": "á", - "à": "à", - "ä": "ä", - "ǟ": "ǟ", - "ã": "ã", - "ā": "ā", - "ă": "ă", - "ắ": "ắ", - "ằ": "ằ", - "ẵ": "ẵ", - "ǎ": "ǎ", - "â": "â", - "ấ": "ấ", - "ầ": "ầ", - "ẫ": "ẫ", - "ȧ": "ȧ", - "ǡ": "ǡ", - "å": "å", - "ǻ": "ǻ", - "ḃ": "ḃ", - "ć": "ć", - "č": "č", - "ĉ": "ĉ", - "ċ": "ċ", - "ď": "ď", - "ḋ": "ḋ", - "é": "é", - "è": "è", - "ë": "ë", - "ẽ": "ẽ", - "ē": "ē", - "ḗ": "ḗ", - "ḕ": "ḕ", - "ĕ": "ĕ", - "ě": "ě", - "ê": "ê", - "ế": "ế", - "ề": "ề", - "ễ": "ễ", - "ė": "ė", - "ḟ": "ḟ", - "ǵ": "ǵ", - "ḡ": "ḡ", - "ğ": "ğ", - "ǧ": "ǧ", - "ĝ": "ĝ", - "ġ": "ġ", - "ḧ": "ḧ", - "ȟ": "ȟ", - "ĥ": "ĥ", - "ḣ": "ḣ", - "í": "í", - "ì": "ì", - "ï": "ï", - "ḯ": "ḯ", - "ĩ": "ĩ", - "ī": "ī", - "ĭ": "ĭ", - "ǐ": "ǐ", - "î": "î", - "ǰ": "ǰ", - "ĵ": "ĵ", - "ḱ": "ḱ", - "ǩ": "ǩ", - "ĺ": "ĺ", - "ľ": "ľ", - "ḿ": "ḿ", - "ṁ": "ṁ", - "ń": "ń", - "ǹ": "ǹ", - "ñ": "ñ", - "ň": "ň", - "ṅ": "ṅ", - "ó": "ó", - "ò": "ò", - "ö": "ö", - "ȫ": "ȫ", - "õ": "õ", - "ṍ": "ṍ", - "ṏ": "ṏ", - "ȭ": "ȭ", - "ō": "ō", - "ṓ": "ṓ", - "ṑ": "ṑ", - "ŏ": "ŏ", - "ǒ": "ǒ", - "ô": "ô", - "ố": "ố", - "ồ": "ồ", - "ỗ": "ỗ", - "ȯ": "ȯ", - "ȱ": "ȱ", - "ő": "ő", - "ṕ": "ṕ", - "ṗ": "ṗ", - "ŕ": "ŕ", - "ř": "ř", - "ṙ": "ṙ", - "ś": "ś", - "ṥ": "ṥ", - "š": "š", - "ṧ": "ṧ", - "ŝ": "ŝ", - "ṡ": "ṡ", - "ẗ": "ẗ", - "ť": "ť", - "ṫ": "ṫ", - "ú": "ú", - "ù": "ù", - "ü": "ü", - "ǘ": "ǘ", - "ǜ": "ǜ", - "ǖ": "ǖ", - "ǚ": "ǚ", - "ũ": "ũ", - "ṹ": "ṹ", - "ū": "ū", - "ṻ": "ṻ", - "ŭ": "ŭ", - "ǔ": "ǔ", - "û": "û", - "ů": "ů", - "ű": "ű", - "ṽ": "ṽ", - "ẃ": "ẃ", - "ẁ": "ẁ", - "ẅ": "ẅ", - "ŵ": "ŵ", - "ẇ": "ẇ", - "ẘ": "ẘ", - "ẍ": "ẍ", - "ẋ": "ẋ", - "ý": "ý", - "ỳ": "ỳ", - "ÿ": "ÿ", - "ỹ": "ỹ", - "ȳ": "ȳ", - "ŷ": "ŷ", - "ẏ": "ẏ", - "ẙ": "ẙ", - "ź": "ź", - "ž": "ž", - "ẑ": "ẑ", - "ż": "ż", - "Á": "Á", - "À": "À", - "Ä": "Ä", - "Ǟ": "Ǟ", - "Ã": "Ã", - "Ā": "Ā", - "Ă": "Ă", - "Ắ": "Ắ", - "Ằ": "Ằ", - "Ẵ": "Ẵ", - "Ǎ": "Ǎ", - "Â": "Â", - "Ấ": "Ấ", - "Ầ": "Ầ", - "Ẫ": "Ẫ", - "Ȧ": "Ȧ", - "Ǡ": "Ǡ", - "Å": "Å", - "Ǻ": "Ǻ", - "Ḃ": "Ḃ", - "Ć": "Ć", - "Č": "Č", - "Ĉ": "Ĉ", - "Ċ": "Ċ", - "Ď": "Ď", - "Ḋ": "Ḋ", - "É": "É", - "È": "È", - "Ë": "Ë", - "Ẽ": "Ẽ", - "Ē": "Ē", - "Ḗ": "Ḗ", - "Ḕ": "Ḕ", - "Ĕ": "Ĕ", - "Ě": "Ě", - "Ê": "Ê", - "Ế": "Ế", - "Ề": "Ề", - "Ễ": "Ễ", - "Ė": "Ė", - "Ḟ": "Ḟ", - "Ǵ": "Ǵ", - "Ḡ": "Ḡ", - "Ğ": "Ğ", - "Ǧ": "Ǧ", - "Ĝ": "Ĝ", - "Ġ": "Ġ", - "Ḧ": "Ḧ", - "Ȟ": "Ȟ", - "Ĥ": "Ĥ", - "Ḣ": "Ḣ", - "Í": "Í", - "Ì": "Ì", - "Ï": "Ï", - "Ḯ": "Ḯ", - "Ĩ": "Ĩ", - "Ī": "Ī", - "Ĭ": "Ĭ", - "Ǐ": "Ǐ", - "Î": "Î", - "İ": "İ", - "Ĵ": "Ĵ", - "Ḱ": "Ḱ", - "Ǩ": "Ǩ", - "Ĺ": "Ĺ", - "Ľ": "Ľ", - "Ḿ": "Ḿ", - "Ṁ": "Ṁ", - "Ń": "Ń", - "Ǹ": "Ǹ", - "Ñ": "Ñ", - "Ň": "Ň", - "Ṅ": "Ṅ", - "Ó": "Ó", - "Ò": "Ò", - "Ö": "Ö", - "Ȫ": "Ȫ", - "Õ": "Õ", - "Ṍ": "Ṍ", - "Ṏ": "Ṏ", - "Ȭ": "Ȭ", - "Ō": "Ō", - "Ṓ": "Ṓ", - "Ṑ": "Ṑ", - "Ŏ": "Ŏ", - "Ǒ": "Ǒ", - "Ô": "Ô", - "Ố": "Ố", - "Ồ": "Ồ", - "Ỗ": "Ỗ", - "Ȯ": "Ȯ", - "Ȱ": "Ȱ", - "Ő": "Ő", - "Ṕ": "Ṕ", - "Ṗ": "Ṗ", - "Ŕ": "Ŕ", - "Ř": "Ř", - "Ṙ": "Ṙ", - "Ś": "Ś", - "Ṥ": "Ṥ", - "Š": "Š", - "Ṧ": "Ṧ", - "Ŝ": "Ŝ", - "Ṡ": "Ṡ", - "Ť": "Ť", - "Ṫ": "Ṫ", - "Ú": "Ú", - "Ù": "Ù", - "Ü": "Ü", - "Ǘ": "Ǘ", - "Ǜ": "Ǜ", - "Ǖ": "Ǖ", - "Ǚ": "Ǚ", - "Ũ": "Ũ", - "Ṹ": "Ṹ", - "Ū": "Ū", - "Ṻ": "Ṻ", - "Ŭ": "Ŭ", - "Ǔ": "Ǔ", - "Û": "Û", - "Ů": "Ů", - "Ű": "Ű", - "Ṽ": "Ṽ", - "Ẃ": "Ẃ", - "Ẁ": "Ẁ", - "Ẅ": "Ẅ", - "Ŵ": "Ŵ", - "Ẇ": "Ẇ", - "Ẍ": "Ẍ", - "Ẋ": "Ẋ", - "Ý": "Ý", - "Ỳ": "Ỳ", - "Ÿ": "Ÿ", - "Ỹ": "Ỹ", - "Ȳ": "Ȳ", - "Ŷ": "Ŷ", - "Ẏ": "Ẏ", - "Ź": "Ź", - "Ž": "Ž", - "Ẑ": "Ẑ", - "Ż": "Ż", - "ά": "ά", - "ὰ": "ὰ", - "ᾱ": "ᾱ", - "ᾰ": "ᾰ", - "έ": "έ", - "ὲ": "ὲ", - "ή": "ή", - "ὴ": "ὴ", - "ί": "ί", - "ὶ": "ὶ", - "ϊ": "ϊ", - "ΐ": "ΐ", - "ῒ": "ῒ", - "ῑ": "ῑ", - "ῐ": "ῐ", - "ό": "ό", - "ὸ": "ὸ", - "ύ": "ύ", - "ὺ": "ὺ", - "ϋ": "ϋ", - "ΰ": "ΰ", - "ῢ": "ῢ", - "ῡ": "ῡ", - "ῠ": "ῠ", - "ώ": "ώ", - "ὼ": "ὼ", - "Ύ": "Ύ", - "Ὺ": "Ὺ", - "Ϋ": "Ϋ", - "Ῡ": "Ῡ", - "Ῠ": "Ῠ", - "Ώ": "Ώ", - "Ὼ": "Ὼ" -}; - -/* eslint no-constant-condition:0 */ - -const numberRegEx = /^\d(?:[\d,.]*\d)?$/; // Keep in sync with numberRegEx in symbolsOrd.js - -/** - * This file contains the parser used to parse out a TeX expression from the - * input. Since TeX isn't context-free, standard parsers don't work particularly - * well. - * - * The strategy of this parser is as such: - * - * The main functions (the `.parse...` ones) take a position in the current - * parse string to parse tokens from. The lexer (found in Lexer.js, stored at - * this.gullet.lexer) also supports pulling out tokens at arbitrary places. When - * individual tokens are needed at a position, the lexer is called to pull out a - * token, which is then used. - * - * The parser has a property called "mode" indicating the mode that - * the parser is currently in. Currently it has to be one of "math" or - * "text", which denotes whether the current environment is a math-y - * one or a text-y one (e.g. inside \text). Currently, this serves to - * limit the functions which can be used in text mode. - * - * The main functions then return an object which contains the useful data that - * was parsed at its given point, and a new position at the end of the parsed - * data. The main functions can call each other and continue the parsing by - * using the returned position as a new starting point. - * - * There are also extra `.handle...` functions, which pull out some reused - * functionality into self-contained functions. - * - * The functions return ParseNodes. - */ - -class Parser { - constructor(input, settings, isPreamble = false) { - // Start in math mode - this.mode = "math"; - // Create a new macro expander (gullet) and (indirectly via that) also a - // new lexer (mouth) for this parser (stomach, in the language of TeX) - this.gullet = new MacroExpander(input, settings, this.mode); - // Store the settings for use in parsing - this.settings = settings; - // Are we defining a preamble? - this.isPreamble = isPreamble; - // Count leftright depth (for \middle errors) - this.leftrightDepth = 0; - this.prevAtomType = ""; - } - - /** - * Checks a result to make sure it has the right type, and throws an - * appropriate error otherwise. - */ - expect(text, consume = true) { - if (this.fetch().text !== text) { - throw new ParseError(`Expected '${text}', got '${this.fetch().text}'`, this.fetch()); - } - if (consume) { - this.consume(); - } - } - - /** - * Discards the current lookahead token, considering it consumed. - */ - consume() { - this.nextToken = null; - } - - /** - * Return the current lookahead token, or if there isn't one (at the - * beginning, or if the previous lookahead token was consume()d), - * fetch the next token as the new lookahead token and return it. - */ - fetch() { - if (this.nextToken == null) { - this.nextToken = this.gullet.expandNextToken(); - } - return this.nextToken; - } - - /** - * Switches between "text" and "math" modes. - */ - switchMode(newMode) { - this.mode = newMode; - this.gullet.switchMode(newMode); - } - - /** - * Main parsing function, which parses an entire input. - */ - parse() { - // Create a group namespace for every $...$, $$...$$, \[...\].) - // A \def is then valid only within that pair of delimiters. - this.gullet.beginGroup(); - - if (this.settings.colorIsTextColor) { - // Use old \color behavior (same as LaTeX's \textcolor) if requested. - // We do this within the group for the math expression, so it doesn't - // pollute settings.macros. - this.gullet.macros.set("\\color", "\\textcolor"); - } - - // Try to parse the input - const parse = this.parseExpression(false); - - // If we succeeded, make sure there's an EOF at the end - this.expect("EOF"); - - if (this.isPreamble) { - const macros = Object.create(null); - Object.entries(this.gullet.macros.current).forEach(([key, value]) => { - macros[key] = value; - }); - this.gullet.endGroup(); - return macros - } - - // The only local macro that we want to save is from \tag. - const tag = this.gullet.macros.get("\\df@tag"); - - // End the group namespace for the expression - this.gullet.endGroup(); - - if (tag) { this.gullet.macros.current["\\df@tag"] = tag; } - - return parse; - } - - static get endOfExpression() { - return ["}", "\\endgroup", "\\end", "\\right", "\\endtoggle", "&"]; - } - - /** - * Parses an "expression", which is a list of atoms. - * - * `breakOnInfix`: Should the parsing stop when we hit infix nodes? This - * happens when functions have higher precendence han infix - * nodes in implicit parses. - * - * `breakOnTokenText`: The text of the token that the expression should end - * with, or `null` if something else should end the - * expression. - */ - parseExpression(breakOnInfix, breakOnTokenText) { - const body = []; - // Keep adding atoms to the body until we can't parse any more atoms (either - // we reached the end, a }, or a \right) - while (true) { - // Ignore spaces in math mode - if (this.mode === "math") { - this.consumeSpaces(); - } - const lex = this.fetch(); - if (Parser.endOfExpression.indexOf(lex.text) !== -1) { - break; - } - if (breakOnTokenText && lex.text === breakOnTokenText) { - break; - } - if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) { - break; - } - const atom = this.parseAtom(breakOnTokenText); - if (!atom) { - break; - } else if (atom.type === "internal") { - continue; - } - body.push(atom); - // Keep a record of the atom type, so that op.js can set correct spacing. - this.prevAtomType = atom.type === "atom" ? atom.family : atom.type; - } - if (this.mode === "text") { - this.formLigatures(body); - } - return this.handleInfixNodes(body); - } - - /** - * Rewrites infix operators such as \over with corresponding commands such - * as \frac. - * - * There can only be one infix operator per group. If there's more than one - * then the expression is ambiguous. This can be resolved by adding {}. - */ - handleInfixNodes(body) { - let overIndex = -1; - let funcName; - - for (let i = 0; i < body.length; i++) { - if (body[i].type === "infix") { - if (overIndex !== -1) { - throw new ParseError("only one infix operator per group", body[i].token); - } - overIndex = i; - funcName = body[i].replaceWith; - } - } - - if (overIndex !== -1 && funcName) { - let numerNode; - let denomNode; - - const numerBody = body.slice(0, overIndex); - const denomBody = body.slice(overIndex + 1); - - if (numerBody.length === 1 && numerBody[0].type === "ordgroup") { - numerNode = numerBody[0]; - } else { - numerNode = { type: "ordgroup", mode: this.mode, body: numerBody }; - } - - if (denomBody.length === 1 && denomBody[0].type === "ordgroup") { - denomNode = denomBody[0]; - } else { - denomNode = { type: "ordgroup", mode: this.mode, body: denomBody }; - } - - let node; - if (funcName === "\\\\abovefrac") { - node = this.callFunction(funcName, [numerNode, body[overIndex], denomNode], []); - } else { - node = this.callFunction(funcName, [numerNode, denomNode], []); - } - return [node]; - } else { - return body; - } - } - - /** - * Handle a subscript or superscript with nice errors. - */ - handleSupSubscript( - name // For error reporting. - ) { - const symbolToken = this.fetch(); - const symbol = symbolToken.text; - this.consume(); - this.consumeSpaces(); // ignore spaces before sup/subscript argument - const group = this.parseGroup(name); - - if (!group) { - throw new ParseError("Expected group after '" + symbol + "'", symbolToken); - } - - return group; - } - - /** - * Converts the textual input of an unsupported command into a text node - * contained within a color node whose color is determined by errorColor - */ - formatUnsupportedCmd(text) { - const textordArray = []; - - for (let i = 0; i < text.length; i++) { - textordArray.push({ type: "textord", mode: "text", text: text[i] }); - } - - const textNode = { - type: "text", - mode: this.mode, - body: textordArray - }; - - const colorNode = { - type: "color", - mode: this.mode, - color: this.settings.errorColor, - body: [textNode] - }; - - return colorNode; - } - - /** - * Parses a group with optional super/subscripts. - */ - parseAtom(breakOnTokenText) { - // The body of an atom is an implicit group, so that things like - // \left(x\right)^2 work correctly. - const base = this.parseGroup("atom", breakOnTokenText); - - // In text mode, we don't have superscripts or subscripts - if (this.mode === "text") { - return base; - } - - // Note that base may be empty (i.e. null) at this point. - - let superscript; - let subscript; - while (true) { - // Guaranteed in math mode, so eat any spaces first. - this.consumeSpaces(); - - // Lex the first token - const lex = this.fetch(); - - if (lex.text === "\\limits" || lex.text === "\\nolimits") { - // We got a limit control - if (base && base.type === "op") { - const limits = lex.text === "\\limits"; - base.limits = limits; - base.alwaysHandleSupSub = true; - } else if (base && base.type === "operatorname") { - if (base.alwaysHandleSupSub) { - base.limits = lex.text === "\\limits"; - } - } else { - throw new ParseError("Limit controls must follow a math operator", lex); - } - this.consume(); - } else if (lex.text === "^") { - // We got a superscript start - if (superscript) { - throw new ParseError("Double superscript", lex); - } - superscript = this.handleSupSubscript("superscript"); - } else if (lex.text === "_") { - // We got a subscript start - if (subscript) { - throw new ParseError("Double subscript", lex); - } - subscript = this.handleSupSubscript("subscript"); - } else if (lex.text === "'") { - // We got a prime - if (superscript) { - throw new ParseError("Double superscript", lex); - } - const prime = { type: "textord", mode: this.mode, text: "\\prime" }; - - // Many primes can be grouped together, so we handle this here - const primes = [prime]; - this.consume(); - // Keep lexing tokens until we get something that's not a prime - while (this.fetch().text === "'") { - // For each one, add another prime to the list - primes.push(prime); - this.consume(); - } - // If there's a superscript following the primes, combine that - // superscript in with the primes. - if (this.fetch().text === "^") { - primes.push(this.handleSupSubscript("superscript")); - } - // Put everything into an ordgroup as the superscript - superscript = { type: "ordgroup", mode: this.mode, body: primes }; - } else if (uSubsAndSups[lex.text]) { - // A Unicode subscript or superscript character. - // We treat these similarly to the unicode-math package. - // So we render a string of Unicode (sub|super)scripts the - // same as a (sub|super)script of regular characters. - let str = uSubsAndSups[lex.text]; - const isSub = unicodeSubRegEx.test(lex.text); - this.consume(); - // Continue fetching tokens to fill out the string. - while (true) { - const token = this.fetch().text; - if (!(uSubsAndSups[token])) { break } - if (unicodeSubRegEx.test(token) !== isSub) { break } - this.consume(); - str += uSubsAndSups[token]; - } - // Now create a (sub|super)script. - const body = (new Parser(str, this.settings)).parse(); - if (isSub) { - subscript = { type: "ordgroup", mode: "math", body }; - } else { - superscript = { type: "ordgroup", mode: "math", body }; - } - } else { - // If it wasn't ^, _, a Unicode (sub|super)script, or ', stop parsing super/subscripts - break; - } - } - - if (superscript || subscript) { - if (base && base.type === "multiscript" && !base.postscripts) { - // base is the result of a \prescript function. - // Write the sub- & superscripts into the multiscript element. - base.postscripts = { sup: superscript, sub: subscript }; - return base - } else { - // We got either a superscript or subscript, create a supsub - return { - type: "supsub", - mode: this.mode, - base: base, - sup: superscript, - sub: subscript - } - } - } else { - // Otherwise return the original body - return base; - } - } - - /** - * Parses an entire function, including its base and all of its arguments. - */ - parseFunction( - breakOnTokenText, - name // For determining its context - ) { - const token = this.fetch(); - const func = token.text; - const funcData = functions[func]; - if (!funcData) { - return null; - } - this.consume(); // consume command token - - if (name && name !== "atom" && !funcData.allowedInArgument) { - throw new ParseError( - "Got function '" + func + "' with no arguments" + (name ? " as " + name : ""), - token - ); - } else if (this.mode === "text" && !funcData.allowedInText) { - throw new ParseError("Can't use function '" + func + "' in text mode", token); - } else if (this.mode === "math" && funcData.allowedInMath === false) { - throw new ParseError("Can't use function '" + func + "' in math mode", token); - } - - const prevAtomType = this.prevAtomType; - const { args, optArgs } = this.parseArguments(func, funcData); - this.prevAtomType = prevAtomType; - return this.callFunction(func, args, optArgs, token, breakOnTokenText); - } - - /** - * Call a function handler with a suitable context and arguments. - */ - callFunction(name, args, optArgs, token, breakOnTokenText) { - const context = { - funcName: name, - parser: this, - token, - breakOnTokenText - }; - const func = functions[name]; - if (func && func.handler) { - return func.handler(context, args, optArgs); - } else { - throw new ParseError(`No function handler for ${name}`); - } - } - - /** - * Parses the arguments of a function or environment - */ - parseArguments( - func, // Should look like "\name" or "\begin{name}". - funcData - ) { - const totalArgs = funcData.numArgs + funcData.numOptionalArgs; - if (totalArgs === 0) { - return { args: [], optArgs: [] }; - } - - const args = []; - const optArgs = []; - - for (let i = 0; i < totalArgs; i++) { - let argType = funcData.argTypes && funcData.argTypes[i]; - const isOptional = i < funcData.numOptionalArgs; - - if ( - (funcData.primitive && argType == null) || - // \sqrt expands into primitive if optional argument doesn't exist - (funcData.type === "sqrt" && i === 1 && optArgs[0] == null) - ) { - argType = "primitive"; - } - - const arg = this.parseGroupOfType(`argument to '${func}'`, argType, isOptional); - if (isOptional) { - optArgs.push(arg); - } else if (arg != null) { - args.push(arg); - } else { - // should be unreachable - throw new ParseError("Null argument, please report this as a bug"); - } - } - - return { args, optArgs }; - } - - /** - * Parses a group when the mode is changing. - */ - parseGroupOfType(name, type, optional) { - switch (type) { - case "size": - return this.parseSizeGroup(optional); - case "url": - return this.parseUrlGroup(optional); - case "math": - case "text": - return this.parseArgumentGroup(optional, type); - case "hbox": { - // hbox argument type wraps the argument in the equivalent of - // \hbox, which is like \text but switching to \textstyle size. - const group = this.parseArgumentGroup(optional, "text"); - return group != null - ? { - type: "styling", - mode: group.mode, - body: [group], - scriptLevel: "text" // simulate \textstyle - } - : null; - } - case "raw": { - const token = this.parseStringGroup("raw", optional); - return token != null - ? { - type: "raw", - mode: "text", - string: token.text - } - : null; - } - case "primitive": { - if (optional) { - throw new ParseError("A primitive argument cannot be optional"); - } - const group = this.parseGroup(name); - if (group == null) { - throw new ParseError("Expected group as " + name, this.fetch()); - } - return group; - } - case "original": - case null: - case undefined: - return this.parseArgumentGroup(optional); - default: - throw new ParseError("Unknown group type as " + name, this.fetch()); - } - } - - /** - * Discard any space tokens, fetching the next non-space token. - */ - consumeSpaces() { - while (this.fetch().text === " ") { - this.consume(); - } - } - - /** - * Parses a group, essentially returning the string formed by the - * brace-enclosed tokens plus some position information. - */ - parseStringGroup( - modeName, // Used to describe the mode in error messages. - optional - ) { - const argToken = this.gullet.scanArgument(optional); - if (argToken == null) { - return null; - } - let str = ""; - let nextToken; - while ((nextToken = this.fetch()).text !== "EOF") { - str += nextToken.text; - this.consume(); - } - this.consume(); // consume the end of the argument - argToken.text = str; - return argToken; - } - - /** - * Parses a regex-delimited group: the largest sequence of tokens - * whose concatenated strings match `regex`. Returns the string - * formed by the tokens plus some position information. - */ - parseRegexGroup( - regex, - modeName // Used to describe the mode in error messages. - ) { - const firstToken = this.fetch(); - let lastToken = firstToken; - let str = ""; - let nextToken; - while ((nextToken = this.fetch()).text !== "EOF" && regex.test(str + nextToken.text)) { - lastToken = nextToken; - str += lastToken.text; - this.consume(); - } - if (str === "") { - throw new ParseError("Invalid " + modeName + ": '" + firstToken.text + "'", firstToken); - } - return firstToken.range(lastToken, str); - } - - /** - * Parses a size specification, consisting of magnitude and unit. - */ - parseSizeGroup(optional) { - let res; - let isBlank = false; - // don't expand before parseStringGroup - this.gullet.consumeSpaces(); - if (!optional && this.gullet.future().text !== "{") { - res = this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size"); - } else { - res = this.parseStringGroup("size", optional); - } - if (!res) { - return null; - } - if (!optional && res.text.length === 0) { - // Because we've tested for what is !optional, this block won't - // affect \kern, \hspace, etc. It will capture the mandatory arguments - // to \genfrac and \above. - res.text = "0pt"; // Enable \above{} - isBlank = true; // This is here specifically for \genfrac - } - const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(res.text); - if (!match) { - throw new ParseError("Invalid size: '" + res.text + "'", res); - } - const data = { - number: +(match[1] + match[2]), // sign + magnitude, cast to number - unit: match[3] - }; - if (!validUnit(data)) { - throw new ParseError("Invalid unit: '" + data.unit + "'", res); - } - return { - type: "size", - mode: this.mode, - value: data, - isBlank - }; - } - - /** - * Parses an URL, checking escaped letters and allowed protocols, - * and setting the catcode of % as an active character (as in \hyperref). - */ - parseUrlGroup(optional) { - this.gullet.lexer.setCatcode("%", 13); // active character - this.gullet.lexer.setCatcode("~", 12); // other character - const res = this.parseStringGroup("url", optional); - this.gullet.lexer.setCatcode("%", 14); // comment character - this.gullet.lexer.setCatcode("~", 13); // active character - if (res == null) { - return null; - } - // hyperref package allows backslashes alone in href, but doesn't - // generate valid links in such cases; we interpret this as - // "undefined" behaviour, and keep them as-is. Some browser will - // replace backslashes with forward slashes. - let url = res.text.replace(/\\([#$%&~_^{}])/g, "$1"); - url = res.text.replace(/{\u2044}/g, "/"); - return { - type: "url", - mode: this.mode, - url - }; - } - - /** - * Parses an argument with the mode specified. - */ - parseArgumentGroup(optional, mode) { - const argToken = this.gullet.scanArgument(optional); - if (argToken == null) { - return null; - } - const outerMode = this.mode; - if (mode) { - // Switch to specified mode - this.switchMode(mode); - } - - this.gullet.beginGroup(); - const expression = this.parseExpression(false, "EOF"); - // TODO: find an alternative way to denote the end - this.expect("EOF"); // expect the end of the argument - this.gullet.endGroup(); - const result = { - type: "ordgroup", - mode: this.mode, - loc: argToken.loc, - body: expression - }; - - if (mode) { - // Switch mode back - this.switchMode(outerMode); - } - return result; - } - - /** - * Parses an ordinary group, which is either a single nucleus (like "x") - * or an expression in braces (like "{x+y}") or an implicit group, a group - * that starts at the current position, and ends right before a higher explicit - * group ends, or at EOF. - */ - parseGroup( - name, // For error reporting. - breakOnTokenText - ) { - const firstToken = this.fetch(); - const text = firstToken.text; - - let result; - // Try to parse an open brace or \begingroup - if (text === "{" || text === "\\begingroup" || text === "\\toggle") { - this.consume(); - const groupEnd = text === "{" - ? "}" - : text === "\\begingroup" - ? "\\endgroup" - : "\\endtoggle"; - - this.gullet.beginGroup(); - // If we get a brace, parse an expression - const expression = this.parseExpression(false, groupEnd); - const lastToken = this.fetch(); - this.expect(groupEnd); // Check that we got a matching closing brace - this.gullet.endGroup(); - result = { - type: (lastToken.text === "\\endtoggle" ? "toggle" : "ordgroup"), - mode: this.mode, - loc: SourceLocation.range(firstToken, lastToken), - body: expression, - // A group formed by \begingroup...\endgroup is a semi-simple group - // which doesn't affect spacing in math mode, i.e., is transparent. - // https://tex.stackexchange.com/questions/1930/when-should-one- - // use-begingroup-instead-of-bgroup - semisimple: text === "\\begingroup" || undefined - }; - } else { - // If there exists a function with this name, parse the function. - // Otherwise, just return a nucleus - result = this.parseFunction(breakOnTokenText, name) || this.parseSymbol(); - if (result == null && text[0] === "\\" && - !Object.prototype.hasOwnProperty.call(implicitCommands, text )) { - result = this.formatUnsupportedCmd(text); - this.consume(); - } - } - return result; - } - - /** - * Form ligature-like combinations of characters for text mode. - * This includes inputs like "--", "---", "``" and "''". - * The result will simply replace multiple textord nodes with a single - * character in each value by a single textord node having multiple - * characters in its value. The representation is still ASCII source. - * The group will be modified in place. - */ - formLigatures(group) { - let n = group.length - 1; - for (let i = 0; i < n; ++i) { - const a = group[i]; - const v = a.text; - if (v === "-" && group[i + 1].text === "-") { - if (i + 1 < n && group[i + 2].text === "-") { - group.splice(i, 3, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 2]), - text: "---" - }); - n -= 2; - } else { - group.splice(i, 2, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 1]), - text: "--" - }); - n -= 1; - } - } - if ((v === "'" || v === "`") && group[i + 1].text === v) { - group.splice(i, 2, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 1]), - text: v + v - }); - n -= 1; - } - } - } - - /** - * Parse a single symbol out of the string. Here, we handle single character - * symbols and special functions like \verb. - */ - parseSymbol() { - const nucleus = this.fetch(); - let text = nucleus.text; - - if (/^\\verb[^a-zA-Z]/.test(text)) { - this.consume(); - let arg = text.slice(5); - const star = arg.charAt(0) === "*"; - if (star) { - arg = arg.slice(1); - } - // Lexer's tokenRegex is constructed to always have matching - // first/last characters. - if (arg.length < 2 || arg.charAt(0) !== arg.slice(-1)) { - throw new ParseError(`\\verb assertion failed -- - please report what input caused this bug`); - } - arg = arg.slice(1, -1); // remove first and last char - return { - type: "verb", - mode: "text", - body: arg, - star - }; - } - // At this point, we should have a symbol, possibly with accents. - // First expand any accented base symbol according to unicodeSymbols. - if (Object.prototype.hasOwnProperty.call(unicodeSymbols, text[0]) && - !symbols[this.mode][text[0]]) { - // This behavior is not strict (XeTeX-compatible) in math mode. - if (this.settings.strict && this.mode === "math") { - throw new ParseError(`Accented Unicode text character "${text[0]}" used in ` + `math mode`, - nucleus - ); - } - text = unicodeSymbols[text[0]] + text.slice(1); - } - // Strip off any combining characters - const match = combiningDiacriticalMarksEndRegex.exec(text); - if (match) { - text = text.substring(0, match.index); - if (text === "i") { - text = "\u0131"; // dotless i, in math and text mode - } else if (text === "j") { - text = "\u0237"; // dotless j, in math and text mode - } - } - // Recognize base symbol - let symbol; - if (symbols[this.mode][text]) { - const group = symbols[this.mode][text].group; - const loc = SourceLocation.range(nucleus); - let s; - if (Object.prototype.hasOwnProperty.call(ATOMS, group )) { - const family = group; - s = { - type: "atom", - mode: this.mode, - family, - loc, - text - }; - } else { - s = { - type: group, - mode: this.mode, - loc, - text - }; - } - symbol = s; - } else if (!this.strict && numberRegEx.test(text)) { - // A number. Wrap in a if in math mode; otherwise. - this.consume(); - return { - type: "textord", - mode: this.mode, - loc: SourceLocation.range(nucleus), - text - } - } else if (text.charCodeAt(0) >= 0x80) { - // no symbol for e.g. ^ - if (this.settings.strict) { - if (!supportedCodepoint(text.charCodeAt(0))) { - throw new ParseError(`Unrecognized Unicode character "${text[0]}"` + - ` (${text.charCodeAt(0)})`, nucleus); - } else if (this.mode === "math") { - throw new ParseError(`Unicode text character "${text[0]}" used in math mode`, nucleus) - } - } - // All nonmathematical Unicode characters are rendered as if they - // are in text mode (wrapped in \text) because that's what it - // takes to render them in LaTeX. - symbol = { - type: "textord", - mode: "text", - loc: SourceLocation.range(nucleus), - text - }; - } else { - return null; // EOF, ^, _, {, }, etc. - } - this.consume(); - // Transform combining characters into accents - if (match) { - for (let i = 0; i < match[0].length; i++) { - const accent = match[0][i]; - if (!unicodeAccents[accent]) { - throw new ParseError(`Unknown accent ' ${accent}'`, nucleus); - } - const command = unicodeAccents[accent][this.mode] || - unicodeAccents[accent].text; - if (!command) { - throw new ParseError(`Accent ${accent} unsupported in ${this.mode} mode`, nucleus); - } - symbol = { - type: "accent", - mode: this.mode, - loc: SourceLocation.range(nucleus), - label: command, - isStretchy: false, - isShifty: true, - base: symbol - }; - } - } - return symbol; - } -} - -/** - * Parses an expression using a Parser, then returns the parsed result. - */ -const parseTree = function(toParse, settings) { - if (!(typeof toParse === "string" || toParse instanceof String)) { - throw new TypeError("Temml can only parse string typed expression") - } - const parser = new Parser(toParse, settings); - // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors - delete parser.gullet.macros.current["\\df@tag"]; - - let tree = parser.parse(); - - // LaTeX ignores a \tag placed outside an AMS environment. - if (!(tree.length > 0 && tree[0].type && tree[0].type === "array" && tree[0].addEqnNum)) { - // If the input used \tag, it will set the \df@tag macro to the tag. - // In this case, we separately parse the tag and wrap the tree. - if (parser.gullet.macros.get("\\df@tag")) { - if (!settings.displayMode) { - throw new ParseError("\\tag works only in display mode") - } - parser.gullet.feed("\\df@tag"); - tree = [ - { - type: "tag", - mode: "text", - body: tree, - tag: parser.parse() - } - ]; - } - } - - return tree -}; - -/** - * This file contains information about the style that the mathmlBuilder carries - * around with it. Data is held in an `Style` object, and when - * recursing, a new `Style` object can be created with the `.with*` functions. - */ - -const subOrSupLevel = [2, 2, 3, 3]; - -/** - * This is the main Style class. It contains the current style.level, color, and font. - * - * Style objects should not be modified. To create a new Style with - * different properties, call a `.with*` method. - */ -class Style { - constructor(data) { - // Style.level can be 0 | 1 | 2 | 3, which correspond to - // displaystyle, textstyle, scriptstyle, and scriptscriptstyle. - // style.level does not directly set MathML's script level. MathML does that itself. - // We use style.level to track, not set, math style so that we can get the - // correct scriptlevel when needed in supsub.js, mathchoice.js, or for dimensions in em. - this.level = data.level; - this.color = data.color; // string | void - // A font family applies to a group of fonts (i.e. SansSerif), while a font - // represents a specific font (i.e. SansSerif Bold). - // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm - this.font = data.font || ""; // string - this.fontFamily = data.fontFamily || ""; // string - this.fontSize = data.fontSize || 1.0; // number - this.fontWeight = data.fontWeight || ""; - this.fontShape = data.fontShape || ""; - this.maxSize = data.maxSize; // [number, number] - } - - /** - * Returns a new style object with the same properties as "this". Properties - * from "extension" will be copied to the new style object. - */ - extend(extension) { - const data = { - level: this.level, - color: this.color, - font: this.font, - fontFamily: this.fontFamily, - fontSize: this.fontSize, - fontWeight: this.fontWeight, - fontShape: this.fontShape, - maxSize: this.maxSize - }; - - for (const key in extension) { - if (Object.prototype.hasOwnProperty.call(extension, key)) { - data[key] = extension[key]; - } - } - - return new Style(data); - } - - withLevel(n) { - return this.extend({ - level: n - }); - } - - incrementLevel() { - return this.extend({ - level: Math.min(this.level + 1, 3) - }); - } - - inSubOrSup() { - return this.extend({ - level: subOrSupLevel[this.level] - }) - } - - /** - * Create a new style object with the given color. - */ - withColor(color) { - return this.extend({ - color: color - }); - } - - /** - * Creates a new style object with the given math font or old text font. - * @type {[type]} - */ - withFont(font) { - return this.extend({ - font - }); - } - - /** - * Create a new style objects with the given fontFamily. - */ - withTextFontFamily(fontFamily) { - return this.extend({ - fontFamily, - font: "" - }); - } - - /** - * Creates a new style object with the given font size - */ - withFontSize(num) { - return this.extend({ - fontSize: num - }); - } - - /** - * Creates a new style object with the given font weight - */ - withTextFontWeight(fontWeight) { - return this.extend({ - fontWeight, - font: "" - }); - } - - /** - * Creates a new style object with the given font weight - */ - withTextFontShape(fontShape) { - return this.extend({ - fontShape, - font: "" - }); - } - - /** - * Gets the CSS color of the current style object - */ - getColor() { - return this.color; - } -} - -/* Temml Post Process - * Perform two tasks not done by Temml when it created each individual Temml element. - * Given a block of block, - * 1. At each AMS auto-numbered environment, assign an id. - * 2. Populate the text contents of each \ref & \eqref - * - * As with other Temml code, this file is released under terms of the MIT license. - * https://mit-license.org/ - */ - -const version = "0.6.9"; - -function postProcess(block) { - const labelMap = {}; - let i = 0; - - // Get a collection of the parents of each \tag & auto-numbered equation - const parents = block.getElementsByClassName("tml-tageqn"); - for (const parent of parents) { - const eqns = parent.getElementsByClassName("tml-eqn"); - if (eqns. length > 0 ) { - // AMS automatically numbered equation. - // Assign an id. - i += 1; - eqns[0].id = "tml-eqn-" + i; - // No need to write a number into the text content of the element. - // A CSS counter does that even if this postProcess() function is not used. - } - // If there is a \label, add it to labelMap - const labels = parent.getElementsByClassName("tml-label"); - if (labels.length === 0) { continue } - if (eqns.length > 0) { - labelMap[labels[0].id] = String(i); - } else { - const tags = parent.getElementsByClassName("tml-tag"); - if (tags.length > 0) { - labelMap[labels[0].id] = tags[0].textContent; - } - } - } - - // Populate \ref & \eqref text content - const refs = block.getElementsByClassName("tml-ref"); - [...refs].forEach(ref => { - let str = labelMap[ref.getAttribute("href").slice(1)]; - if (ref.className.indexOf("tml-eqref") === -1) { - // \ref. Omit parens. - str = str.replace(/^\(/, ""); - str = str.replace(/\($/, ""); - } { - // \eqref. Include parens - if (str.charAt(0) !== "(") { str = "(" + str; } - if (str.slice(-1) !== ")") { str = str + ")"; } - } - ref.textContent = str; - }); -} - -/* eslint no-console:0 */ - -/** - * Parse and build an expression, and place that expression in the DOM node - * given. - */ -let render = function(expression, baseNode, options) { - baseNode.textContent = ""; - const math = renderToMathMLTree(expression, options); - if (options.elementIsMath) { - // The element already exists. Populate it. - baseNode.textContent = ""; - math.children.forEach(e => { baseNode.appendChild(e.toNode()); }); - } else { - baseNode.appendChild(math.toNode()); - } -}; - -// Temml's styles don't work properly in quirks mode. Print out an error, and -// disable rendering. -if (typeof document !== "undefined") { - if (document.compatMode !== "CSS1Compat") { - typeof console !== "undefined" && - console.warn( - "Warning: Temml doesn't work in quirks mode. Make sure your " + - "website has a suitable doctype." - ); - - render = function() { - throw new ParseError("Temml doesn't work in quirks mode."); - }; - } -} - -/** - * Parse and build an expression, and return the markup for that. - */ -const renderToString = function(expression, options) { - const markup = renderToMathMLTree(expression, options).toMarkup(); - return markup; -}; - -/** - * Parse an expression and return the parse tree. - */ -const generateParseTree = function(expression, options) { - const settings = new Settings(options); - return parseTree(expression, settings); -}; - -/** - * Take an expression which contains a preamble. - * Parse it and return the macros. - */ -const definePreamble = function(expression, options) { - const settings = new Settings(options); - settings.macros = {}; - if (!(typeof expression === "string" || expression instanceof String)) { - throw new TypeError("Temml can only parse string typed expression") - } - const parser = new Parser(expression, settings, true); - // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors - delete parser.gullet.macros.current["\\df@tag"]; - const macros = parser.parse(); - return macros -}; - -/** - * If the given error is a Temml ParseError, - * renders the invalid LaTeX as a span with hover title giving the Temml - * error message. Otherwise, simply throws the error. - */ -const renderError = function(error, expression, options) { - if (options.throwOnError || !(error instanceof ParseError)) { - throw error; - } - const node = new Span(["temml-error"], [new TextNode$1(expression + "\n" + error.toString())]); - node.style.color = options.errorColor; - node.style.whiteSpace = "pre-line"; - return node; -}; - -/** - * Generates and returns the Temml build tree. This is used for advanced - * use cases (like rendering to custom output). - */ -const renderToMathMLTree = function(expression, options) { - const settings = new Settings(options); - try { - const tree = parseTree(expression, settings); - const style = new Style({ - level: settings.displayMode ? StyleLevel.DISPLAY : StyleLevel.TEXT, - maxSize: settings.maxSize - }); - return buildMathML(tree, expression, style, settings); - } catch (error) { - return renderError(error, expression, settings); - } -}; - -var temml = { - /** - * Current Temml version - */ - version: version, - /** - * Renders the given LaTeX into MathML, and adds - * it as a child to the specified DOM node. - */ - render, - /** - * Renders the given LaTeX into MathML string, - * for sending to the client. - */ - renderToString, - /** - * Post-process an entire HTML block. - * Writes AMS auto-numbers and implements \ref{}. - * Typcally called once, after a loop has rendered many individual spans. - */ - postProcess, - /** - * Temml error, usually during parsing. - */ - ParseError, - /** - * Creates a set of macros with document-wide scope. - */ - definePreamble, - /** - * Parses the given LaTeX into Temml's internal parse tree structure, - * without rendering to HTML or MathML. - * - * NOTE: This method is not currently recommended for public use. - * The internal tree representation is unstable and is very likely - * to change. Use at your own risk. - */ - __parse: generateParseTree, - /** - * Renders the given LaTeX into a MathML internal DOM tree - * representation, without flattening that representation to a string. - * - * NOTE: This method is not currently recommended for public use. - * The internal tree representation is unstable and is very likely - * to change. Use at your own risk. - */ - __renderToMathMLTree: renderToMathMLTree, - /** - * adds a new symbol to builtin symbols table - */ - __defineSymbol: defineSymbol, - /** - * adds a new macro to builtin macro list - */ - __defineMacro: defineMacro -}; - -module.exports = temml; diff --git a/utils/temml.cjs.js b/utils/temml.cjs.js deleted file mode 100644 index 7423c084..00000000 --- a/utils/temml.cjs.js +++ /dev/null @@ -1,13022 +0,0 @@ -'use strict'; - -/** - * This is the ParseError class, which is the main error thrown by Temml - * functions when something has gone wrong. This is used to distinguish internal - * errors from errors in the expression that the user provided. - * - * If possible, a caller should provide a Token or ParseNode with information - * about where in the source string the problem occurred. - */ -class ParseError { - constructor( - message, // The error message - token // An object providing position information - ) { - let error = " " + message; - let start; - - const loc = token && token.loc; - if (loc && loc.start <= loc.end) { - // If we have the input and a position, make the error a bit fancier - - // Get the input - const input = loc.lexer.input; - - // Prepend some information - start = loc.start; - const end = loc.end; - if (start === input.length) { - error += " at end of input: "; - } else { - error += " at position " + (start + 1) + ": "; - } - - // Underline token in question using combining underscores - const underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332"); - - // Extract some context from the input and add it to the error - let left; - if (start > 15) { - left = "…" + input.slice(start - 15, start); - } else { - left = input.slice(0, start); - } - let right; - if (end + 15 < input.length) { - right = input.slice(end, end + 15) + "…"; - } else { - right = input.slice(end); - } - error += left + underlined + right; - } - - // Some hackery to make ParseError a prototype of Error - // See http://stackoverflow.com/a/8460753 - const self = new Error(error); - self.name = "TemmlParseError"; - self.__proto__ = ParseError.prototype; - self.position = start; - return self; - } -} - -ParseError.prototype.__proto__ = Error.prototype; - -// -/** - * This file contains a list of utility functions which are useful in other - * files. - */ - -/** - * Return whether an element is contained in a list - */ -const contains = function(list, elem) { - return list.indexOf(elem) !== -1; -}; - -/** - * Provide a default value if a setting is undefined - */ -const deflt = function(setting, defaultIfUndefined) { - return setting === undefined ? defaultIfUndefined : setting; -}; - -// hyphenate and escape adapted from Facebook's React under Apache 2 license - -const uppercase = /([A-Z])/g; -const hyphenate = function(str) { - return str.replace(uppercase, "-$1").toLowerCase(); -}; - -const ESCAPE_LOOKUP = { - "&": "&", - ">": ">", - "<": "<", - '"': """, - "'": "'" -}; - -const ESCAPE_REGEX = /[&><"']/g; - -/** - * Escapes text to prevent scripting attacks. - */ -function escape(text) { - return String(text).replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]); -} - -/** - * Sometimes we want to pull out the innermost element of a group. In most - * cases, this will just be the group itself, but when ordgroups and colors have - * a single element, we want to pull that out. - */ -const getBaseElem = function(group) { - if (group.type === "ordgroup") { - if (group.body.length === 1) { - return getBaseElem(group.body[0]); - } else { - return group; - } - } else if (group.type === "color") { - if (group.body.length === 1) { - return getBaseElem(group.body[0]); - } else { - return group; - } - } else if (group.type === "font") { - return getBaseElem(group.body); - } else { - return group; - } -}; - -/** - * TeXbook algorithms often reference "character boxes", which are simply groups - * with a single character in them. To decide if something is a character box, - * we find its innermost group, and see if it is a single character. - */ -const isCharacterBox = function(group) { - const baseElem = getBaseElem(group); - - // These are all the types of groups which hold single characters - return baseElem.type === "mathord" || baseElem.type === "textord" || baseElem.type === "atom" -}; - -const assert = function(value) { - if (!value) { - throw new Error("Expected non-null, but got " + String(value)); - } - return value; -}; - -/** - * Return the protocol of a URL, or "_relative" if the URL does not specify a - * protocol (and thus is relative). - */ -const protocolFromUrl = function(url) { - const protocol = /^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(url); - return protocol != null ? protocol[1] : "_relative"; -}; - -/** - * Round `n` to 4 decimal places, or to the nearest 1/10,000th em. The TeXbook - * gives an acceptable rounding error of 100sp (which would be the nearest - * 1/6551.6em with our ptPerEm = 10): - * http://www.ctex.org/documents/shredder/src/texbook.pdf#page=69 - */ -const round = function(n) { - return +n.toFixed(4); -}; - -var utils = { - contains, - deflt, - escape, - hyphenate, - getBaseElem, - isCharacterBox, - protocolFromUrl, - round -}; - -/** - * This is a module for storing settings passed into Temml. It correctly handles - * default settings. - */ - -/** - * The main Settings object - */ -class Settings { - constructor(options) { - // allow null options - options = options || {}; - this.displayMode = utils.deflt(options.displayMode, false); // boolean - this.annotate = utils.deflt(options.annotate, false); // boolean - this.elementIsMath = utils.deflt(options.elementIsMath, false); // boolean - this.leqno = utils.deflt(options.leqno, false); // boolean - this.errorColor = utils.deflt(options.errorColor, "#b22222"); // string - this.preventTagLap = utils.deflt(options.preventTagLap, false); // boolean - this.macros = options.macros || {}; - this.xml = utils.deflt(options.xml, false); // boolean - this.colorIsTextColor = utils.deflt(options.colorIsTextColor, false); // booelean - this.strict = utils.deflt(options.strict, false); // boolean - this.trust = utils.deflt(options.trust, false); // trust context. See html.js. - this.maxSize = Math.max(0, utils.deflt(options.maxSize, Infinity)); // number - this.maxExpand = Math.max(0, utils.deflt(options.maxExpand, 1000)); // number - } - - /** - * Report nonstrict (non-LaTeX-compatible) input. - * Can safely not be called if `this.strict` is false in JavaScript. - */ - reportNonstrict(errorCode, errorMsg, token) { - const strict = this.strict; - if (strict === false) { - return; - } else if (strict === true) { - throw new ParseError( - "LaTeX-incompatible input and strict mode is set to 'error': " + - `${errorMsg} [${errorCode}]`, - token - ); - } else { - // won't happen in type-safe code - return; - } - } - - /** - * Check whether to test potentially dangerous input, and return - * `true` (trusted) or `false` (untrusted). The sole argument `context` - * should be an object with `command` field specifying the relevant LaTeX - * command (as a string starting with `\`), and any other arguments, etc. - * If `context` has a `url` field, a `protocol` field will automatically - * get added by this function (changing the specified object). - */ - isTrusted(context) { - if (context.url && !context.protocol) { - context.protocol = utils.protocolFromUrl(context.url); - } - const trust = typeof this.trust === "function" ? this.trust(context) : this.trust; - return Boolean(trust); - } -} - -/** - * All registered functions. - * `functions.js` just exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary. - */ -const _functions = {}; - -/** - * All MathML builders. Should be only used in the `define*` and the `build*ML` - * functions. - */ -const _mathmlGroupBuilders = {}; - -function defineFunction({ - type, - names, - props, - handler, - mathmlBuilder -}) { - // Set default values of functions - const data = { - type, - numArgs: props.numArgs, - argTypes: props.argTypes, - allowedInArgument: !!props.allowedInArgument, - allowedInText: !!props.allowedInText, - allowedInMath: props.allowedInMath === undefined ? true : props.allowedInMath, - numOptionalArgs: props.numOptionalArgs || 0, - infix: !!props.infix, - primitive: !!props.primitive, - handler: handler - }; - for (let i = 0; i < names.length; ++i) { - _functions[names[i]] = data; - } - if (type) { - if (mathmlBuilder) { - _mathmlGroupBuilders[type] = mathmlBuilder; - } - } -} - -/** - * Use this to register only the MathML builder for a function(e.g. - * if the function's ParseNode is generated in Parser.js rather than via a - * stand-alone handler provided to `defineFunction`). - */ -function defineFunctionBuilders({ type, mathmlBuilder }) { - defineFunction({ - type, - names: [], - props: { numArgs: 0 }, - handler() { - throw new Error("Should never be called.") - }, - mathmlBuilder - }); -} - -const normalizeArgument = function(arg) { - return arg.type === "ordgroup" && arg.body.length === 1 ? arg.body[0] : arg -}; - -// Since the corresponding buildMathML function expects a -// list of elements, we normalize for different kinds of arguments -const ordargument = function(arg) { - return arg.type === "ordgroup" ? arg.body : [arg] -}; - -/** - * This node represents a document fragment, which contains elements, but when - * placed into the DOM doesn't have any representation itself. It only contains - * children and doesn't have any DOM node properties. - */ -class DocumentFragment { - constructor(children) { - this.children = children; - this.classes = []; - this.style = {}; - } - - hasClass(className) { - return utils.contains(this.classes, className); - } - - /** Convert the fragment into a node. */ - toNode() { - const frag = document.createDocumentFragment(); - - for (let i = 0; i < this.children.length; i++) { - frag.appendChild(this.children[i].toNode()); - } - - return frag; - } - - /** Convert the fragment into HTML markup. */ - toMarkup() { - let markup = ""; - - // Simply concatenate the markup for the children together. - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - return markup; - } - - /** - * Converts the math node into a string, similar to innerText. Applies to - * MathDomNode's only. - */ - toText() { - // To avoid this, we would subclass documentFragment separately for - // MathML, but polyfills for subclassing is expensive per PR 1469. - const toText = (child) => child.toText(); - return this.children.map(toText).join(""); - } -} - -/** - * These objects store the data about the DOM nodes we create, as well as some - * extra data. They can then be transformed into real DOM nodes with the - * `toNode` function or HTML markup using `toMarkup`. They are useful for both - * storing extra properties on the nodes, as well as providing a way to easily - * work with the DOM. - * - * Similar functions for working with MathML nodes exist in mathMLTree.js. - * - */ - -/** - * Create an HTML className based on a list of classes. In addition to joining - * with spaces, we also remove empty classes. - */ -const createClass = function(classes) { - return classes.filter((cls) => cls).join(" "); -}; - -const initNode = function(classes, style) { - this.classes = classes || []; - this.attributes = {}; - this.style = style || {}; -}; - -/** - * Convert into an HTML node - */ -const toNode = function(tagName) { - const node = document.createElement(tagName); - - // Apply the class - node.className = createClass(this.classes); - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - // Apply attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr )) { - node.setAttribute(attr, this.attributes[attr]); - } - } - - // Append the children, also as HTML nodes - for (let i = 0; i < this.children.length; i++) { - node.appendChild(this.children[i].toNode()); - } - - return node; -}; - -/** - * Convert into an HTML markup string - */ -const toMarkup = function(tagName) { - let markup = `<${tagName}`; - - // Add the class - if (this.classes.length) { - markup += ` class="${utils.escape(createClass(this.classes))}"`; - } - - let styles = ""; - - // Add the styles, after hyphenation - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - styles += `${utils.hyphenate(style)}:${this.style[style]};`; - } - } - - if (styles) { - markup += ` style="${styles}"`; - } - - // Add the attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr )) { - markup += ` ${attr}="${utils.escape(this.attributes[attr])}"`; - } - } - - markup += ">"; - - // Add the markup of the children, also as markup - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - markup += ``; - - return markup; -}; - -/** - * This node represents a span node, with a className, a list of children, and - * an inline style. - * - */ -class Span { - constructor(classes, children, style) { - initNode.call(this, classes, style); - this.children = children || []; - } - - setAttribute(attribute, value) { - this.attributes[attribute] = value; - } - - toNode() { - return toNode.call(this, "span"); - } - - toMarkup() { - return toMarkup.call(this, "span"); - } -} - -class TextNode { - constructor(text) { - this.text = text; - } - toNode() { - return document.createTextNode(this.text); - } - toMarkup() { - return utils.escape(this.text); - } -} - -/** - * This node represents an image embed () element. - */ -class Img { - constructor(src, alt, style) { - this.alt = alt; - this.src = src; - this.classes = ["mord"]; - this.style = style; - } - - hasClass(className) { - return utils.contains(this.classes, className); - } - - toNode() { - const node = document.createElement("img"); - node.src = this.src; - node.alt = this.alt; - node.className = "mord"; - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - return node; - } - - toMarkup() { - let markup = `${this.alt}` and - * `` tags). - */ -class MathNode { - constructor(type, children, classes, style, isSVG) { - this.type = type; - this.attributes = {}; - this.children = children || []; - this.classes = classes || []; - this.style = style || {}; // Used for elements - this.isSVG = isSVG || false; - } - - /** - * Sets an attribute on a MathML node. MathML depends on attributes to convey a - * semantic content, so this is used heavily. - */ - setAttribute(name, value) { - this.attributes[name] = value; - } - - /** - * Gets an attribute on a MathML node. - */ - getAttribute(name) { - return this.attributes[name]; - } - - /** - * Converts the math node into a MathML-namespaced DOM element. - */ - toNode() { - const node = this.isSVG - ? document.createElementNS("http://www.w3.org/2000/svg", this.type) - : document.createElementNS("http://www.w3.org/1998/Math/MathML", this.type); - - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { - node.setAttribute(attr, this.attributes[attr]); - } - } - - if (this.classes.length > 0) { - node.className = createClass(this.classes); - } - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - for (let i = 0; i < this.children.length; i++) { - node.appendChild(this.children[i].toNode()); - } - - return node; - } - - /** - * Converts the math node into an HTML markup string. - */ - toMarkup() { - let markup = "<" + this.type; - - // Add the attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { - markup += " " + attr + '="'; - markup += utils.escape(this.attributes[attr]); - markup += '"'; - } - } - - if (this.classes.length > 0) { - markup += ` class ="${utils.escape(createClass(this.classes))}"`; - } - - let styles = ""; - - // Add the styles, after hyphenation - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - styles += `${utils.hyphenate(style)}:${this.style[style]};`; - } - } - - if (styles) { - markup += ` style="${styles}"`; - } - - markup += ">"; - - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - markup += ""; - - return markup; - } - - /** - * Converts the math node into a string, similar to innerText, but escaped. - */ - toText() { - return this.children.map((child) => child.toText()).join(""); - } -} - -/** - * This node represents a piece of text. - */ -class TextNode$1 { - constructor(text) { - this.text = text; - } - - /** - * Converts the text node into a DOM text node. - */ - toNode() { - return document.createTextNode(this.text); - } - - /** - * Converts the text node into escaped HTML markup - * (representing the text itself). - */ - toMarkup() { - return utils.escape(this.toText()); - } - - /** - * Converts the text node into a string - * (representing the text iteself). - */ - toText() { - return this.text; - } -} - -// Do not make an the only child of a . -// An acts as its own implicit . -const wrapWithMstyle = expression => { - let node; - if (expression.length === 1 && expression[0].type === "mrow") { - node = expression.pop(); - node.type = "mstyle"; - } else { - node = new MathNode("mstyle", expression); - } - return node -}; - -var mathMLTree = { - MathNode, - TextNode: TextNode$1, - newDocumentFragment -}; - -/** - * This file provides support for building horizontal stretchy elements. - */ - -// From mhchem reaction arrows \ce{A <=>> B} and \ce{A <<=> B} -const keysWithoutUnicodePoints = ["equilibriumRight", "equilibriumLeft"]; - -const stretchyCodePoint = { - widehat: "^", - widecheck: "ˇ", - widetilde: "~", - wideparen: "⏜", // \u23dc - utilde: "~", - overleftarrow: "\u2190", - underleftarrow: "\u2190", - xleftarrow: "\u2190", - overrightarrow: "\u2192", - underrightarrow: "\u2192", - xrightarrow: "\u2192", - underbrace: "\u23df", - overbrace: "\u23de", - overgroup: "\u23e0", - overparen: "⏜", - undergroup: "\u23e1", - underparen: "\u23dd", - overleftrightarrow: "\u2194", - underleftrightarrow: "\u2194", - xleftrightarrow: "\u2194", - Overrightarrow: "\u21d2", - xRightarrow: "\u21d2", - overleftharpoon: "\u21bc", - xleftharpoonup: "\u21bc", - overrightharpoon: "\u21c0", - xrightharpoonup: "\u21c0", - xLeftarrow: "\u21d0", - xLeftrightarrow: "\u21d4", - xhookleftarrow: "\u21a9", - xhookrightarrow: "\u21aa", - xmapsto: "\u21a6", - xrightharpoondown: "\u21c1", - xleftharpoondown: "\u21bd", - xtwoheadleftarrow: "\u219e", - xtwoheadrightarrow: "\u21a0", - xlongequal: "=", - xrightleftarrows: "\u21c4", - yields: "\u2192", - yieldsLeft: "\u2190", - mesomerism: "\u2194", - longrightharpoonup: "\u21c0", - longleftharpoondown: "\u21bd", - "\\cdrightarrow": "\u2192", - "\\cdleftarrow": "\u2190", - "\\cdlongequal": "=" -}; - -const nodeFromObject = (obj) => { - // Build a stretchy arrow from two SVGs. - const children = []; - if (obj.children) { - obj.children.map(child => { children.push(nodeFromObject(child)); }); - } - const node = obj.type === "span" - ? new Span(null, children, obj.style) - : new mathMLTree.MathNode(obj.type, children, [], obj.style, true); - Object.entries(obj.attributes).forEach(([key, value]) => { - node.setAttribute(key, value); - }); - return node -}; - -const mathMLnode = function(label, macros = {}) { - const key = label.slice(1); - let child; - if (!keysWithoutUnicodePoints.includes(key)) { - child = new mathMLTree.TextNode(stretchyCodePoint[key]); - } else { - const atKey = "\\@" + key; - if (!macros.has(atKey)) { - throw new ParseError("Arrow not available. The mhchem package is needed.") - } - child = nodeFromObject(JSON.parse(macros.get(atKey))); - } - const node = new mathMLTree.MathNode("mo", [child]); - node.setAttribute("stretchy", "true"); - return node -}; - -var stretchy = { - mathMLnode -}; - -/** - * This file holds a list of all no-argument functions and single-character - * symbols (like 'a' or ';'). - * - * For each of the symbols, there are two properties they can have: - * - group (required): the ParseNode group type the symbol should have (i.e. - "textord", "mathord", etc). - * - replace: the character that this symbol or function should be - * replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi - * character in the main font). - * - * The outermost map in the table indicates what mode the symbols should be - * accepted in (e.g. "math" or "text"). - */ - -// Some of these have a "-token" suffix since these are also used as `ParseNode` -// types for raw text tokens, and we want to avoid conflicts with higher-level -// `ParseNode` types. These `ParseNode`s are constructed within `Parser` by -// looking up the `symbols` map. -const ATOMS = { - bin: 1, - close: 1, - inner: 1, - open: 1, - punct: 1, - rel: 1 -}; -const NON_ATOMS = { - "accent-token": 1, - mathord: 1, - "op-token": 1, - spacing: 1, - textord: 1 -}; - -const symbols = { - math: {}, - text: {} -}; - -/** `acceptUnicodeChar = true` is only applicable if `replace` is set. */ -function defineSymbol(mode, group, replace, name, acceptUnicodeChar) { - symbols[mode][name] = { group, replace }; - - if (acceptUnicodeChar && replace) { - symbols[mode][replace] = symbols[mode][name]; - } -} - -// Some abbreviations for commonly used strings. -// This helps minify the code, and also spotting typos using jshint. - -// modes: -const math = "math"; -const text = "text"; - -// groups: -const accent = "accent-token"; -const bin = "bin"; -const close = "close"; -const inner = "inner"; -const mathord = "mathord"; -const op = "op-token"; -const open = "open"; -const punct = "punct"; -const rel = "rel"; -const spacing = "spacing"; -const textord = "textord"; - -// Now comes the symbol table - -// Relation Symbols -defineSymbol(math, rel, "\u2261", "\\equiv", true); -defineSymbol(math, rel, "\u227a", "\\prec", true); -defineSymbol(math, rel, "\u227b", "\\succ", true); -defineSymbol(math, rel, "\u223c", "\\sim", true); -defineSymbol(math, rel, "\u27c2", "\\perp", true); -defineSymbol(math, rel, "\u2aaf", "\\preceq", true); -defineSymbol(math, rel, "\u2ab0", "\\succeq", true); -defineSymbol(math, rel, "\u2243", "\\simeq", true); -defineSymbol(math, rel, "\u224c", "\\backcong", true); -defineSymbol(math, rel, "|", "\\mid", true); -defineSymbol(math, rel, "\u226a", "\\ll", true); -defineSymbol(math, rel, "\u226b", "\\gg", true); -defineSymbol(math, rel, "\u224d", "\\asymp", true); -defineSymbol(math, rel, "\u2225", "\\parallel"); -defineSymbol(math, rel, "\u22c8", "\\bowtie", true); -defineSymbol(math, rel, "\u2323", "\\smile", true); -defineSymbol(math, rel, "\u2291", "\\sqsubseteq", true); -defineSymbol(math, rel, "\u2292", "\\sqsupseteq", true); -defineSymbol(math, rel, "\u2250", "\\doteq", true); -defineSymbol(math, rel, "\u2322", "\\frown", true); -defineSymbol(math, rel, "\u220b", "\\ni", true); -defineSymbol(math, rel, "\u220c", "\\notni", true); -defineSymbol(math, rel, "\u221d", "\\propto", true); -defineSymbol(math, rel, "\u22a2", "\\vdash", true); -defineSymbol(math, rel, "\u22a3", "\\dashv", true); -defineSymbol(math, rel, "\u220b", "\\owns"); -defineSymbol(math, rel, "\u2258", "\\arceq", true); -defineSymbol(math, rel, "\u2259", "\\wedgeq", true); -defineSymbol(math, rel, "\u225a", "\\veeeq", true); -defineSymbol(math, rel, "\u225b", "\\stareq", true); -defineSymbol(math, rel, "\u225d", "\\eqdef", true); -defineSymbol(math, rel, "\u225e", "\\measeq", true); -defineSymbol(math, rel, "\u225f", "\\questeq", true); -defineSymbol(math, rel, "\u2260", "\\ne", true); -defineSymbol(math, rel, "\u2260", "\\neq"); -// mathtools.sty -defineSymbol(math, rel, "\u2237", "\\dblcolon", true); -defineSymbol(math, rel, "\u2254", "\\coloneqq", true); -defineSymbol(math, rel, "\u2255", "\\eqqcolon", true); -defineSymbol(math, rel, "\u2239", "\\eqcolon", true); -defineSymbol(math, rel, "\u2A74", "\\Coloneqq", true); - -// Punctuation -defineSymbol(math, punct, "\u002e", "\\ldotp"); -defineSymbol(math, punct, "\u00b7", "\\cdotp"); - -// Misc Symbols -defineSymbol(math, textord, "\u0023", "\\#"); -defineSymbol(text, textord, "\u0023", "\\#"); -defineSymbol(math, textord, "\u0026", "\\&"); -defineSymbol(text, textord, "\u0026", "\\&"); -defineSymbol(math, textord, "\u2135", "\\aleph", true); -defineSymbol(math, textord, "\u2200", "\\forall", true); -defineSymbol(math, textord, "\u210f", "\\hbar", true); -defineSymbol(math, textord, "\u2203", "\\exists", true); -defineSymbol(math, textord, "\u2207", "\\nabla", true); -defineSymbol(math, textord, "\u266d", "\\flat", true); -defineSymbol(math, textord, "\u2113", "\\ell", true); -defineSymbol(math, textord, "\u266e", "\\natural", true); -defineSymbol(math, textord, "Å", "\\AA", true); -defineSymbol(text, textord, "Å", "\\AA", true); -defineSymbol(math, textord, "\u2663", "\\clubsuit", true); -defineSymbol(math, textord, "\u2667", "\\varclubsuit", true); -defineSymbol(math, textord, "\u2118", "\\wp", true); -defineSymbol(math, textord, "\u266f", "\\sharp", true); -defineSymbol(math, textord, "\u2662", "\\diamondsuit", true); -defineSymbol(math, textord, "\u2666", "\\vardiamondsuit", true); -defineSymbol(math, textord, "\u211c", "\\Re", true); -defineSymbol(math, textord, "\u2661", "\\heartsuit", true); -defineSymbol(math, textord, "\u2665", "\\varheartsuit", true); -defineSymbol(math, textord, "\u2111", "\\Im", true); -defineSymbol(math, textord, "\u2660", "\\spadesuit", true); -defineSymbol(math, textord, "\u2664", "\\varspadesuit", true); -defineSymbol(math, textord, "\u2640", "\\female", true); -defineSymbol(math, textord, "\u2642", "\\male", true); -defineSymbol(math, textord, "\u00a7", "\\S", true); -defineSymbol(text, textord, "\u00a7", "\\S"); -defineSymbol(math, textord, "\u00b6", "\\P", true); -defineSymbol(text, textord, "\u00b6", "\\P"); -defineSymbol(text, textord, "\u263a", "\\smiley", true); -defineSymbol(math, textord, "\u263a", "\\smiley", true); - -// Math and Text -defineSymbol(math, textord, "\u2020", "\\dag"); -defineSymbol(text, textord, "\u2020", "\\dag"); -defineSymbol(text, textord, "\u2020", "\\textdagger"); -defineSymbol(math, textord, "\u2021", "\\ddag"); -defineSymbol(text, textord, "\u2021", "\\ddag"); -defineSymbol(text, textord, "\u2021", "\\textdaggerdbl"); - -// Large Delimiters -defineSymbol(math, close, "\u23b1", "\\rmoustache", true); -defineSymbol(math, open, "\u23b0", "\\lmoustache", true); -defineSymbol(math, close, "\u27ef", "\\rgroup", true); -defineSymbol(math, open, "\u27ee", "\\lgroup", true); - -// Binary Operators -defineSymbol(math, bin, "\u2213", "\\mp", true); -defineSymbol(math, bin, "\u2296", "\\ominus", true); -defineSymbol(math, bin, "\u228e", "\\uplus", true); -defineSymbol(math, bin, "\u2293", "\\sqcap", true); -defineSymbol(math, bin, "\u2217", "\\ast"); -defineSymbol(math, bin, "\u2294", "\\sqcup", true); -defineSymbol(math, bin, "\u25ef", "\\bigcirc", true); -defineSymbol(math, bin, "\u2219", "\\bullet"); -defineSymbol(math, bin, "\u2021", "\\ddagger"); -defineSymbol(math, bin, "\u2240", "\\wr", true); -defineSymbol(math, bin, "\u2a3f", "\\amalg"); -defineSymbol(math, bin, "\u0026", "\\And"); // from amsmath - -// Arrow Symbols -defineSymbol(math, rel, "\u27f5", "\\longleftarrow", true); -defineSymbol(math, rel, "\u21d0", "\\Leftarrow", true); -defineSymbol(math, rel, "\u27f8", "\\Longleftarrow", true); -defineSymbol(math, rel, "\u27f6", "\\longrightarrow", true); -defineSymbol(math, rel, "\u21d2", "\\Rightarrow", true); -defineSymbol(math, rel, "\u27f9", "\\Longrightarrow", true); -defineSymbol(math, rel, "\u2194", "\\leftrightarrow", true); -defineSymbol(math, rel, "\u27f7", "\\longleftrightarrow", true); -defineSymbol(math, rel, "\u21d4", "\\Leftrightarrow", true); -defineSymbol(math, rel, "\u27fa", "\\Longleftrightarrow", true); -defineSymbol(math, rel, "\u21a6", "\\mapsto", true); -defineSymbol(math, rel, "\u27fc", "\\longmapsto", true); -defineSymbol(math, rel, "\u2197", "\\nearrow", true); -defineSymbol(math, rel, "\u21a9", "\\hookleftarrow", true); -defineSymbol(math, rel, "\u21aa", "\\hookrightarrow", true); -defineSymbol(math, rel, "\u2198", "\\searrow", true); -defineSymbol(math, rel, "\u21bc", "\\leftharpoonup", true); -defineSymbol(math, rel, "\u21c0", "\\rightharpoonup", true); -defineSymbol(math, rel, "\u2199", "\\swarrow", true); -defineSymbol(math, rel, "\u21bd", "\\leftharpoondown", true); -defineSymbol(math, rel, "\u21c1", "\\rightharpoondown", true); -defineSymbol(math, rel, "\u2196", "\\nwarrow", true); -defineSymbol(math, rel, "\u21cc", "\\rightleftharpoons", true); -defineSymbol(math, mathord, "\u21af", "\\lightning", true); -defineSymbol(math, mathord, "\u2030", "\\permil", true); -defineSymbol(text, textord, "\u2030", "\\permil"); - -// AMS Negated Binary Relations -defineSymbol(math, rel, "\u226e", "\\nless", true); -// Symbol names preceeded by "@" each have a corresponding macro. -defineSymbol(math, rel, "\u2a87", "\\lneq", true); -defineSymbol(math, rel, "\u2268", "\\lneqq", true); -defineSymbol(math, rel, "\u2268\ufe00", "\\lvertneqq"); -defineSymbol(math, rel, "\u22e6", "\\lnsim", true); -defineSymbol(math, rel, "\u2a89", "\\lnapprox", true); -defineSymbol(math, rel, "\u2280", "\\nprec", true); -// unicode-math maps \u22e0 to \npreccurlyeq. We'll use the AMS synonym. -defineSymbol(math, rel, "\u22e0", "\\npreceq", true); -defineSymbol(math, rel, "\u22e8", "\\precnsim", true); -defineSymbol(math, rel, "\u2ab9", "\\precnapprox", true); -defineSymbol(math, rel, "\u2241", "\\nsim", true); -defineSymbol(math, rel, "\u2224", "\\nmid", true); -defineSymbol(math, rel, "\u2224", "\\nshortmid"); -defineSymbol(math, rel, "\u22ac", "\\nvdash", true); -defineSymbol(math, rel, "\u22ad", "\\nvDash", true); -defineSymbol(math, rel, "\u22ea", "\\ntriangleleft"); -defineSymbol(math, rel, "\u22ec", "\\ntrianglelefteq", true); -defineSymbol(math, rel, "\u2284", "\\nsubset", true); -defineSymbol(math, rel, "\u2285", "\\nsupset", true); -defineSymbol(math, rel, "\u228a", "\\subsetneq", true); -defineSymbol(math, rel, "\u228a\ufe00", "\\varsubsetneq"); -defineSymbol(math, rel, "\u2acb", "\\subsetneqq", true); -defineSymbol(math, rel, "\u2acb\ufe00", "\\varsubsetneqq"); -defineSymbol(math, rel, "\u226f", "\\ngtr", true); -defineSymbol(math, rel, "\u2a88", "\\gneq", true); -defineSymbol(math, rel, "\u2269", "\\gneqq", true); -defineSymbol(math, rel, "\u2269\ufe00", "\\gvertneqq"); -defineSymbol(math, rel, "\u22e7", "\\gnsim", true); -defineSymbol(math, rel, "\u2a8a", "\\gnapprox", true); -defineSymbol(math, rel, "\u2281", "\\nsucc", true); -// unicode-math maps \u22e1 to \nsucccurlyeq. We'll use the AMS synonym. -defineSymbol(math, rel, "\u22e1", "\\nsucceq", true); -defineSymbol(math, rel, "\u22e9", "\\succnsim", true); -defineSymbol(math, rel, "\u2aba", "\\succnapprox", true); -// unicode-math maps \u2246 to \simneqq. We'll use the AMS synonym. -defineSymbol(math, rel, "\u2246", "\\ncong", true); -defineSymbol(math, rel, "\u2226", "\\nparallel", true); -defineSymbol(math, rel, "\u2226", "\\nshortparallel"); -defineSymbol(math, rel, "\u22af", "\\nVDash", true); -defineSymbol(math, rel, "\u22eb", "\\ntriangleright"); -defineSymbol(math, rel, "\u22ed", "\\ntrianglerighteq", true); -defineSymbol(math, rel, "\u228b", "\\supsetneq", true); -defineSymbol(math, rel, "\u228b", "\\varsupsetneq"); -defineSymbol(math, rel, "\u2acc", "\\supsetneqq", true); -defineSymbol(math, rel, "\u2acc\ufe00", "\\varsupsetneqq"); -defineSymbol(math, rel, "\u22ae", "\\nVdash", true); -defineSymbol(math, rel, "\u2ab5", "\\precneqq", true); -defineSymbol(math, rel, "\u2ab6", "\\succneqq", true); -defineSymbol(math, bin, "\u22b4", "\\unlhd"); -defineSymbol(math, bin, "\u22b5", "\\unrhd"); - -// AMS Negated Arrows -defineSymbol(math, rel, "\u219a", "\\nleftarrow", true); -defineSymbol(math, rel, "\u219b", "\\nrightarrow", true); -defineSymbol(math, rel, "\u21cd", "\\nLeftarrow", true); -defineSymbol(math, rel, "\u21cf", "\\nRightarrow", true); -defineSymbol(math, rel, "\u21ae", "\\nleftrightarrow", true); -defineSymbol(math, rel, "\u21ce", "\\nLeftrightarrow", true); - -// AMS Misc -defineSymbol(math, rel, "\u25b3", "\\vartriangle"); -defineSymbol(math, textord, "\u210f", "\\hslash"); -defineSymbol(math, textord, "\u25bd", "\\triangledown"); -defineSymbol(math, textord, "\u25ca", "\\lozenge"); -defineSymbol(math, textord, "\u24c8", "\\circledS"); -defineSymbol(math, textord, "\u00ae", "\\circledR", true); -defineSymbol(text, textord, "\u00ae", "\\circledR"); -defineSymbol(text, textord, "\u00ae", "\\textregistered"); -defineSymbol(math, textord, "\u2221", "\\measuredangle", true); -defineSymbol(math, textord, "\u2204", "\\nexists"); -defineSymbol(math, textord, "\u2127", "\\mho"); -defineSymbol(math, textord, "\u2132", "\\Finv", true); -defineSymbol(math, textord, "\u2141", "\\Game", true); -defineSymbol(math, textord, "\u2035", "\\backprime"); -defineSymbol(math, textord, "\u25b2", "\\blacktriangle"); -defineSymbol(math, textord, "\u25bc", "\\blacktriangledown"); -defineSymbol(math, textord, "\u25a0", "\\blacksquare"); -defineSymbol(math, textord, "\u29eb", "\\blacklozenge"); -defineSymbol(math, textord, "\u2605", "\\bigstar"); -defineSymbol(math, textord, "\u2222", "\\sphericalangle", true); -defineSymbol(math, textord, "\u2201", "\\complement", true); -// unicode-math maps U+F0 to \matheth. We map to AMS function \eth -defineSymbol(math, textord, "\u00f0", "\\eth", true); -defineSymbol(text, textord, "\u00f0", "\u00f0"); -defineSymbol(math, textord, "\u2571", "\\diagup"); -defineSymbol(math, textord, "\u2572", "\\diagdown"); -defineSymbol(math, textord, "\u25a1", "\\square"); -defineSymbol(math, textord, "\u25a1", "\\Box"); -defineSymbol(math, textord, "\u25ca", "\\Diamond"); -// unicode-math maps U+A5 to \mathyen. We map to AMS function \yen -defineSymbol(math, textord, "\u00a5", "\\yen", true); -defineSymbol(text, textord, "\u00a5", "\\yen", true); -defineSymbol(math, textord, "\u2713", "\\checkmark", true); -defineSymbol(text, textord, "\u2713", "\\checkmark"); -defineSymbol(math, textord, "\u2717", "\\ballotx", true); -defineSymbol(text, textord, "\u2717", "\\ballotx"); -defineSymbol(text, textord, "\u2022", "\\textbullet"); - -// AMS Hebrew -defineSymbol(math, textord, "\u2136", "\\beth", true); -defineSymbol(math, textord, "\u2138", "\\daleth", true); -defineSymbol(math, textord, "\u2137", "\\gimel", true); - -// AMS Greek -defineSymbol(math, textord, "\u03dd", "\\digamma", true); -defineSymbol(math, textord, "\u03f0", "\\varkappa"); - -// AMS Delimiters -defineSymbol(math, open, "\u231C", "\\ulcorner", true); -defineSymbol(math, close, "\u231D", "\\urcorner", true); -defineSymbol(math, open, "\u231E", "\\llcorner", true); -defineSymbol(math, close, "\u231F", "\\lrcorner", true); - -// AMS Binary Relations -defineSymbol(math, rel, "\u2266", "\\leqq", true); -defineSymbol(math, rel, "\u2a7d", "\\leqslant", true); -defineSymbol(math, rel, "\u2a95", "\\eqslantless", true); -defineSymbol(math, rel, "\u2272", "\\lesssim", true); -defineSymbol(math, rel, "\u2a85", "\\lessapprox", true); -defineSymbol(math, rel, "\u224a", "\\approxeq", true); -defineSymbol(math, bin, "\u22d6", "\\lessdot"); -defineSymbol(math, rel, "\u22d8", "\\lll", true); -defineSymbol(math, rel, "\u2276", "\\lessgtr", true); -defineSymbol(math, rel, "\u22da", "\\lesseqgtr", true); -defineSymbol(math, rel, "\u2a8b", "\\lesseqqgtr", true); -defineSymbol(math, rel, "\u2251", "\\doteqdot"); -defineSymbol(math, rel, "\u2253", "\\risingdotseq", true); -defineSymbol(math, rel, "\u2252", "\\fallingdotseq", true); -defineSymbol(math, rel, "\u223d", "\\backsim", true); -defineSymbol(math, rel, "\u22cd", "\\backsimeq", true); -defineSymbol(math, rel, "\u2ac5", "\\subseteqq", true); -defineSymbol(math, rel, "\u22d0", "\\Subset", true); -defineSymbol(math, rel, "\u228f", "\\sqsubset", true); -defineSymbol(math, rel, "\u227c", "\\preccurlyeq", true); -defineSymbol(math, rel, "\u22de", "\\curlyeqprec", true); -defineSymbol(math, rel, "\u227e", "\\precsim", true); -defineSymbol(math, rel, "\u2ab7", "\\precapprox", true); -defineSymbol(math, rel, "\u22b2", "\\vartriangleleft"); -defineSymbol(math, rel, "\u22b4", "\\trianglelefteq"); -defineSymbol(math, rel, "\u22a8", "\\vDash", true); -defineSymbol(math, rel, "\u22aa", "\\Vvdash", true); -defineSymbol(math, rel, "\u2323", "\\smallsmile"); -defineSymbol(math, rel, "\u2322", "\\smallfrown"); -defineSymbol(math, rel, "\u224f", "\\bumpeq", true); -defineSymbol(math, rel, "\u224e", "\\Bumpeq", true); -defineSymbol(math, rel, "\u2267", "\\geqq", true); -defineSymbol(math, rel, "\u2a7e", "\\geqslant", true); -defineSymbol(math, rel, "\u2a96", "\\eqslantgtr", true); -defineSymbol(math, rel, "\u2273", "\\gtrsim", true); -defineSymbol(math, rel, "\u2a86", "\\gtrapprox", true); -defineSymbol(math, bin, "\u22d7", "\\gtrdot"); -defineSymbol(math, rel, "\u22d9", "\\ggg", true); -defineSymbol(math, rel, "\u2277", "\\gtrless", true); -defineSymbol(math, rel, "\u22db", "\\gtreqless", true); -defineSymbol(math, rel, "\u2a8c", "\\gtreqqless", true); -defineSymbol(math, rel, "\u2256", "\\eqcirc", true); -defineSymbol(math, rel, "\u2257", "\\circeq", true); -defineSymbol(math, rel, "\u225c", "\\triangleq", true); -defineSymbol(math, rel, "\u223c", "\\thicksim"); -defineSymbol(math, rel, "\u2248", "\\thickapprox"); -defineSymbol(math, rel, "\u2ac6", "\\supseteqq", true); -defineSymbol(math, rel, "\u22d1", "\\Supset", true); -defineSymbol(math, rel, "\u2290", "\\sqsupset", true); -defineSymbol(math, rel, "\u227d", "\\succcurlyeq", true); -defineSymbol(math, rel, "\u22df", "\\curlyeqsucc", true); -defineSymbol(math, rel, "\u227f", "\\succsim", true); -defineSymbol(math, rel, "\u2ab8", "\\succapprox", true); -defineSymbol(math, rel, "\u22b3", "\\vartriangleright"); -defineSymbol(math, rel, "\u22b5", "\\trianglerighteq"); -defineSymbol(math, rel, "\u22a9", "\\Vdash", true); -defineSymbol(math, rel, "\u2223", "\\shortmid"); -defineSymbol(math, rel, "\u2225", "\\shortparallel"); -defineSymbol(math, rel, "\u226c", "\\between", true); -defineSymbol(math, rel, "\u22d4", "\\pitchfork", true); -defineSymbol(math, rel, "\u221d", "\\varpropto"); -defineSymbol(math, rel, "\u25c0", "\\blacktriangleleft"); -// unicode-math says that \therefore is a mathord atom. -// We kept the amssymb atom type, which is rel. -defineSymbol(math, rel, "\u2234", "\\therefore", true); -defineSymbol(math, rel, "\u220d", "\\backepsilon"); -defineSymbol(math, rel, "\u25b6", "\\blacktriangleright"); -// unicode-math says that \because is a mathord atom. -// We kept the amssymb atom type, which is rel. -defineSymbol(math, rel, "\u2235", "\\because", true); -defineSymbol(math, rel, "\u22d8", "\\llless"); -defineSymbol(math, rel, "\u22d9", "\\gggtr"); -defineSymbol(math, bin, "\u22b2", "\\lhd"); -defineSymbol(math, bin, "\u22b3", "\\rhd"); -defineSymbol(math, rel, "\u2242", "\\eqsim", true); -defineSymbol(math, rel, "\u22c8", "\\Join"); -defineSymbol(math, rel, "\u2251", "\\Doteq", true); - -// AMS Binary Operators -defineSymbol(math, bin, "\u2214", "\\dotplus", true); -defineSymbol(math, bin, "\u2216", "\\smallsetminus"); -defineSymbol(math, bin, "\u22d2", "\\Cap", true); -defineSymbol(math, bin, "\u22d3", "\\Cup", true); -defineSymbol(math, bin, "\u2a5e", "\\doublebarwedge", true); -defineSymbol(math, bin, "\u229f", "\\boxminus", true); -defineSymbol(math, bin, "\u229e", "\\boxplus", true); -defineSymbol(math, bin, "\u22c7", "\\divideontimes", true); -defineSymbol(math, bin, "\u22c9", "\\ltimes", true); -defineSymbol(math, bin, "\u22ca", "\\rtimes", true); -defineSymbol(math, bin, "\u22cb", "\\leftthreetimes", true); -defineSymbol(math, bin, "\u22cc", "\\rightthreetimes", true); -defineSymbol(math, bin, "\u22cf", "\\curlywedge", true); -defineSymbol(math, bin, "\u22ce", "\\curlyvee", true); -defineSymbol(math, bin, "\u229d", "\\circleddash", true); -defineSymbol(math, bin, "\u229b", "\\circledast", true); -defineSymbol(math, bin, "\u22ba", "\\intercal", true); -defineSymbol(math, bin, "\u22d2", "\\doublecap"); -defineSymbol(math, bin, "\u22d3", "\\doublecup"); -defineSymbol(math, bin, "\u22a0", "\\boxtimes", true); - -// AMS Arrows -// Note: unicode-math maps \u21e2 to their own function \rightdasharrow. -// We'll map it to AMS function \dashrightarrow. It produces the same atom. -defineSymbol(math, rel, "\u21e2", "\\dashrightarrow", true); -// unicode-math maps \u21e0 to \leftdasharrow. We'll use the AMS synonym. -defineSymbol(math, rel, "\u21e0", "\\dashleftarrow", true); -defineSymbol(math, rel, "\u21c7", "\\leftleftarrows", true); -defineSymbol(math, rel, "\u21c6", "\\leftrightarrows", true); -defineSymbol(math, rel, "\u21da", "\\Lleftarrow", true); -defineSymbol(math, rel, "\u219e", "\\twoheadleftarrow", true); -defineSymbol(math, rel, "\u21a2", "\\leftarrowtail", true); -defineSymbol(math, rel, "\u21ab", "\\looparrowleft", true); -defineSymbol(math, rel, "\u21cb", "\\leftrightharpoons", true); -defineSymbol(math, rel, "\u21b6", "\\curvearrowleft", true); -// unicode-math maps \u21ba to \acwopencirclearrow. We'll use the AMS synonym. -defineSymbol(math, rel, "\u21ba", "\\circlearrowleft", true); -defineSymbol(math, rel, "\u21b0", "\\Lsh", true); -defineSymbol(math, rel, "\u21c8", "\\upuparrows", true); -defineSymbol(math, rel, "\u21bf", "\\upharpoonleft", true); -defineSymbol(math, rel, "\u21c3", "\\downharpoonleft", true); -defineSymbol(math, rel, "\u22b6", "\\origof", true); -defineSymbol(math, rel, "\u22b7", "\\imageof", true); -defineSymbol(math, rel, "\u22b8", "\\multimap", true); -defineSymbol(math, rel, "\u21ad", "\\leftrightsquigarrow", true); -defineSymbol(math, rel, "\u21c9", "\\rightrightarrows", true); -defineSymbol(math, rel, "\u21c4", "\\rightleftarrows", true); -defineSymbol(math, rel, "\u21a0", "\\twoheadrightarrow", true); -defineSymbol(math, rel, "\u21a3", "\\rightarrowtail", true); -defineSymbol(math, rel, "\u21ac", "\\looparrowright", true); -defineSymbol(math, rel, "\u21b7", "\\curvearrowright", true); -// unicode-math maps \u21bb to \cwopencirclearrow. We'll use the AMS synonym. -defineSymbol(math, rel, "\u21bb", "\\circlearrowright", true); -defineSymbol(math, rel, "\u21b1", "\\Rsh", true); -defineSymbol(math, rel, "\u21ca", "\\downdownarrows", true); -defineSymbol(math, rel, "\u21be", "\\upharpoonright", true); -defineSymbol(math, rel, "\u21c2", "\\downharpoonright", true); -defineSymbol(math, rel, "\u21dd", "\\rightsquigarrow", true); -defineSymbol(math, rel, "\u21dd", "\\leadsto"); -defineSymbol(math, rel, "\u21db", "\\Rrightarrow", true); -defineSymbol(math, rel, "\u21be", "\\restriction"); - -defineSymbol(math, textord, "\u2018", "`"); -defineSymbol(math, textord, "$", "\\$"); -defineSymbol(text, textord, "$", "\\$"); -defineSymbol(text, textord, "$", "\\textdollar"); -defineSymbol(math, textord, "%", "\\%"); -defineSymbol(text, textord, "%", "\\%"); -defineSymbol(math, textord, "_", "\\_"); -defineSymbol(text, textord, "_", "\\_"); -defineSymbol(text, textord, "_", "\\textunderscore"); -defineSymbol(text, textord, "\u2423", "\\textvisiblespace", true); -defineSymbol(math, textord, "\u2220", "\\angle", true); -defineSymbol(math, textord, "\u221e", "\\infty", true); -defineSymbol(math, textord, "\u2032", "\\prime"); -defineSymbol(math, textord, "\u25b3", "\\triangle"); -defineSymbol(text, textord, "\u0391", "\\Alpha", true); -defineSymbol(text, textord, "\u0392", "\\Beta", true); -defineSymbol(text, textord, "\u0393", "\\Gamma", true); -defineSymbol(text, textord, "\u0394", "\\Delta", true); -defineSymbol(text, textord, "\u0395", "\\Epsilon", true); -defineSymbol(text, textord, "\u0396", "\\Zeta", true); -defineSymbol(text, textord, "\u0397", "\\Eta", true); -defineSymbol(text, textord, "\u0398", "\\Theta", true); -defineSymbol(text, textord, "\u0399", "\\Iota", true); -defineSymbol(text, textord, "\u039a", "\\Kappa", true); -defineSymbol(text, textord, "\u039b", "\\Lambda", true); -defineSymbol(text, textord, "\u039c", "\\Mu", true); -defineSymbol(text, textord, "\u039d", "\\Nu", true); -defineSymbol(text, textord, "\u039e", "\\Xi", true); -defineSymbol(text, textord, "\u039f", "\\Omicron", true); -defineSymbol(text, textord, "\u03a0", "\\Pi", true); -defineSymbol(text, textord, "\u03a1", "\\Rho", true); -defineSymbol(text, textord, "\u03a3", "\\Sigma", true); -defineSymbol(text, textord, "\u03a4", "\\Tau", true); -defineSymbol(text, textord, "\u03a5", "\\Upsilon", true); -defineSymbol(text, textord, "\u03a6", "\\Phi", true); -defineSymbol(text, textord, "\u03a7", "\\Chi", true); -defineSymbol(text, textord, "\u03a8", "\\Psi", true); -defineSymbol(text, textord, "\u03a9", "\\Omega", true); -defineSymbol(math, mathord, "\u0391", "\\Alpha", true); -defineSymbol(math, mathord, "\u0392", "\\Beta", true); -defineSymbol(math, mathord, "\u0393", "\\Gamma", true); -defineSymbol(math, mathord, "\u0394", "\\Delta", true); -defineSymbol(math, mathord, "\u0395", "\\Epsilon", true); -defineSymbol(math, mathord, "\u0396", "\\Zeta", true); -defineSymbol(math, mathord, "\u0397", "\\Eta", true); -defineSymbol(math, mathord, "\u0398", "\\Theta", true); -defineSymbol(math, mathord, "\u0399", "\\Iota", true); -defineSymbol(math, mathord, "\u039a", "\\Kappa", true); -defineSymbol(math, mathord, "\u039b", "\\Lambda", true); -defineSymbol(math, mathord, "\u039c", "\\Mu", true); -defineSymbol(math, mathord, "\u039d", "\\Nu", true); -defineSymbol(math, mathord, "\u039e", "\\Xi", true); -defineSymbol(math, mathord, "\u039f", "\\Omicron", true); -defineSymbol(math, mathord, "\u03a0", "\\Pi", true); -defineSymbol(math, mathord, "\u03a1", "\\Rho", true); -defineSymbol(math, mathord, "\u03a3", "\\Sigma", true); -defineSymbol(math, mathord, "\u03a4", "\\Tau", true); -defineSymbol(math, mathord, "\u03a5", "\\Upsilon", true); -defineSymbol(math, mathord, "\u03a6", "\\Phi", true); -defineSymbol(math, mathord, "\u03a7", "\\Chi", true); -defineSymbol(math, mathord, "\u03a8", "\\Psi", true); -defineSymbol(math, mathord, "\u03a9", "\\Omega", true); -defineSymbol(math, textord, "\u00ac", "\\neg", true); -defineSymbol(math, textord, "\u00ac", "\\lnot"); -defineSymbol(math, textord, "\u22a4", "\\top"); -defineSymbol(math, textord, "\u22a5", "\\bot"); -defineSymbol(math, textord, "\u2205", "\\emptyset"); -defineSymbol(math, textord, "\u00f8", "\\varnothing"); -defineSymbol(math, mathord, "\u03b1", "\\alpha", true); -defineSymbol(math, mathord, "\u03b2", "\\beta", true); -defineSymbol(math, mathord, "\u03b3", "\\gamma", true); -defineSymbol(math, mathord, "\u03b4", "\\delta", true); -defineSymbol(math, mathord, "\u03f5", "\\epsilon", true); -defineSymbol(math, mathord, "\u03b6", "\\zeta", true); -defineSymbol(math, mathord, "\u03b7", "\\eta", true); -defineSymbol(math, mathord, "\u03b8", "\\theta", true); -defineSymbol(math, mathord, "\u03b9", "\\iota", true); -defineSymbol(math, mathord, "\u03ba", "\\kappa", true); -defineSymbol(math, mathord, "\u03bb", "\\lambda", true); -defineSymbol(math, mathord, "\u03bc", "\\mu", true); -defineSymbol(math, mathord, "\u03bd", "\\nu", true); -defineSymbol(math, mathord, "\u03be", "\\xi", true); -defineSymbol(math, mathord, "\u03bf", "\\omicron", true); -defineSymbol(math, mathord, "\u03c0", "\\pi", true); -defineSymbol(math, mathord, "\u03c1", "\\rho", true); -defineSymbol(math, mathord, "\u03c3", "\\sigma", true); -defineSymbol(math, mathord, "\u03c4", "\\tau", true); -defineSymbol(math, mathord, "\u03c5", "\\upsilon", true); -defineSymbol(math, mathord, "\u03d5", "\\phi", true); -defineSymbol(math, mathord, "\u03c7", "\\chi", true); -defineSymbol(math, mathord, "\u03c8", "\\psi", true); -defineSymbol(math, mathord, "\u03c9", "\\omega", true); -defineSymbol(math, mathord, "\u03b5", "\\varepsilon", true); -defineSymbol(math, mathord, "\u03d1", "\\vartheta", true); -defineSymbol(math, mathord, "\u03d6", "\\varpi", true); -defineSymbol(math, mathord, "\u03f1", "\\varrho", true); -defineSymbol(math, mathord, "\u03c2", "\\varsigma", true); -defineSymbol(math, mathord, "\u03c6", "\\varphi", true); -defineSymbol(math, mathord, "\u03d8", "\\Coppa", true); -defineSymbol(math, mathord, "\u03d9", "\\coppa", true); -defineSymbol(math, mathord, "\u03d9", "\\varcoppa", true); -defineSymbol(math, mathord, "\u03de", "\\Koppa", true); -defineSymbol(math, mathord, "\u03df", "\\koppa", true); -defineSymbol(math, mathord, "\u03e0", "\\Sampi", true); -defineSymbol(math, mathord, "\u03e1", "\\sampi", true); -defineSymbol(math, mathord, "\u03da", "\\Stigma", true); -defineSymbol(math, mathord, "\u03db", "\\stigma", true); -defineSymbol(math, bin, "\u2217", "\u2217", true); -defineSymbol(math, bin, "+", "+"); -defineSymbol(math, bin, "*", "*"); -defineSymbol(math, bin, "\u2044", "\u2044"); -defineSymbol(math, bin, "\u2212", "-", true); -defineSymbol(math, bin, "\u22c5", "\\cdot", true); -defineSymbol(math, bin, "\u2218", "\\circ"); -defineSymbol(math, bin, "\u00f7", "\\div", true); -defineSymbol(math, bin, "\u00b1", "\\pm", true); -defineSymbol(math, bin, "\u00d7", "\\times", true); -defineSymbol(math, bin, "\u2229", "\\cap", true); -defineSymbol(math, bin, "\u222a", "\\cup", true); -defineSymbol(math, bin, "\u2216", "\\setminus"); -defineSymbol(math, bin, "\u2227", "\\land"); -defineSymbol(math, bin, "\u2228", "\\lor"); -defineSymbol(math, bin, "\u2227", "\\wedge", true); -defineSymbol(math, bin, "\u2228", "\\vee", true); -defineSymbol(math, textord, "\u221a", "\\surd"); -defineSymbol(math, open, "\u27e6", "\\llbracket", true); // stmaryrd/semantic packages -defineSymbol(math, close, "\u27e7", "\\rrbracket", true); -defineSymbol(math, open, "\u27e8", "\\langle", true); -defineSymbol(math, open, "|", "\\lvert"); -defineSymbol(math, open, "\u2016", "\\lVert"); -defineSymbol(math, close, "?", "?"); -defineSymbol(math, close, "!", "!"); -defineSymbol(math, close, "‼", "‼"); -defineSymbol(math, close, "\u27e9", "\\rangle", true); -defineSymbol(math, close, "|", "\\rvert"); -defineSymbol(math, close, "\u2016", "\\rVert"); -defineSymbol(math, open, "\u2983", "\\lBrace", true); // stmaryrd/semantic packages -defineSymbol(math, close, "\u2984", "\\rBrace", true); -defineSymbol(math, rel, "=", "="); -defineSymbol(math, rel, "\u2248", "\\approx", true); -defineSymbol(math, rel, "\u2245", "\\cong", true); -defineSymbol(math, rel, "\u2265", "\\ge"); -defineSymbol(math, rel, "\u2265", "\\geq", true); -defineSymbol(math, rel, "\u2190", "\\gets"); -defineSymbol(math, rel, ">", "\\gt", true); -defineSymbol(math, rel, "\u2208", "\\in", true); -defineSymbol(math, rel, "\u2209", "\\notin", true); -defineSymbol(math, rel, "\ue020", "\\@not"); -defineSymbol(math, rel, "\u2282", "\\subset", true); -defineSymbol(math, rel, "\u2283", "\\supset", true); -defineSymbol(math, rel, "\u2286", "\\subseteq", true); -defineSymbol(math, rel, "\u2287", "\\supseteq", true); -defineSymbol(math, rel, "\u2288", "\\nsubseteq", true); -defineSymbol(math, rel, "\u2288", "\\nsubseteqq"); -defineSymbol(math, rel, "\u2289", "\\nsupseteq", true); -defineSymbol(math, rel, "\u2289", "\\nsupseteqq"); -defineSymbol(math, rel, "\u22a8", "\\models"); -defineSymbol(math, rel, "\u2190", "\\leftarrow", true); -defineSymbol(math, rel, "\u2264", "\\le"); -defineSymbol(math, rel, "\u2264", "\\leq", true); -defineSymbol(math, rel, "<", "\\lt", true); -defineSymbol(math, rel, "\u2192", "\\rightarrow", true); -defineSymbol(math, rel, "\u2192", "\\to"); -defineSymbol(math, rel, "\u2271", "\\ngeq", true); -defineSymbol(math, rel, "\u2271", "\\ngeqq"); -defineSymbol(math, rel, "\u2271", "\\ngeqslant"); -defineSymbol(math, rel, "\u2270", "\\nleq", true); -defineSymbol(math, rel, "\u2270", "\\nleqq"); -defineSymbol(math, rel, "\u2270", "\\nleqslant"); -defineSymbol(math, spacing, "\u00a0", "\\ "); -defineSymbol(math, spacing, "\u00a0", "\\space"); -// Ref: LaTeX Source 2e: \DeclareRobustCommand{\nobreakspace}{% -defineSymbol(math, spacing, "\u00a0", "\\nobreakspace"); -defineSymbol(text, spacing, "\u00a0", "\\ "); -defineSymbol(text, spacing, "\u00a0", " "); -defineSymbol(text, spacing, "\u00a0", "\\space"); -defineSymbol(text, spacing, "\u00a0", "\\nobreakspace"); -defineSymbol(math, spacing, null, "\\nobreak"); -defineSymbol(math, spacing, null, "\\allowbreak"); -defineSymbol(math, punct, ",", ","); -defineSymbol(math, punct, ";", ";"); -defineSymbol(math, bin, "\u22bc", "\\barwedge", true); -defineSymbol(math, bin, "\u22bb", "\\veebar", true); -defineSymbol(math, bin, "\u2299", "\\odot", true); -defineSymbol(math, bin, "\u2295", "\\oplus", true); -defineSymbol(math, bin, "\u2297", "\\otimes", true); -defineSymbol(math, textord, "\u2202", "\\partial", true); -defineSymbol(math, bin, "\u2298", "\\oslash", true); -defineSymbol(math, bin, "\u229a", "\\circledcirc", true); -defineSymbol(math, bin, "\u22a1", "\\boxdot", true); -defineSymbol(math, bin, "\u25b3", "\\bigtriangleup"); -defineSymbol(math, bin, "\u25bd", "\\bigtriangledown"); -defineSymbol(math, bin, "\u2020", "\\dagger"); -defineSymbol(math, bin, "\u22c4", "\\diamond"); -defineSymbol(math, bin, "\u22c6", "\\star"); -defineSymbol(math, bin, "\u25c3", "\\triangleleft"); -defineSymbol(math, bin, "\u25b9", "\\triangleright"); -defineSymbol(math, open, "{", "\\{"); -defineSymbol(text, textord, "{", "\\{"); -defineSymbol(text, textord, "{", "\\textbraceleft"); -defineSymbol(math, close, "}", "\\}"); -defineSymbol(text, textord, "}", "\\}"); -defineSymbol(text, textord, "}", "\\textbraceright"); -defineSymbol(math, open, "{", "\\lbrace"); -defineSymbol(math, close, "}", "\\rbrace"); -defineSymbol(math, open, "[", "\\lbrack", true); -defineSymbol(text, textord, "[", "\\lbrack", true); -defineSymbol(math, close, "]", "\\rbrack", true); -defineSymbol(text, textord, "]", "\\rbrack", true); -defineSymbol(math, open, "(", "\\lparen", true); -defineSymbol(math, close, ")", "\\rparen", true); -defineSymbol(text, textord, "<", "\\textless", true); // in T1 fontenc -defineSymbol(text, textord, ">", "\\textgreater", true); // in T1 fontenc -defineSymbol(math, open, "\u230a", "\\lfloor", true); -defineSymbol(math, close, "\u230b", "\\rfloor", true); -defineSymbol(math, open, "\u2308", "\\lceil", true); -defineSymbol(math, close, "\u2309", "\\rceil", true); -defineSymbol(math, textord, "\\", "\\backslash"); -defineSymbol(math, textord, "|", "|"); -defineSymbol(math, textord, "|", "\\vert"); -defineSymbol(text, textord, "|", "\\textbar", true); // in T1 fontenc -defineSymbol(math, textord, "\u2016", "\\|"); -defineSymbol(math, textord, "\u2016", "\\Vert"); -defineSymbol(text, textord, "\u2016", "\\textbardbl"); -defineSymbol(text, textord, "~", "\\textasciitilde"); -defineSymbol(text, textord, "\\", "\\textbackslash"); -defineSymbol(text, textord, "^", "\\textasciicircum"); -defineSymbol(math, rel, "\u2191", "\\uparrow", true); -defineSymbol(math, rel, "\u21d1", "\\Uparrow", true); -defineSymbol(math, rel, "\u2193", "\\downarrow", true); -defineSymbol(math, rel, "\u21d3", "\\Downarrow", true); -defineSymbol(math, rel, "\u2195", "\\updownarrow", true); -defineSymbol(math, rel, "\u21d5", "\\Updownarrow", true); -defineSymbol(math, op, "\u2210", "\\coprod"); -defineSymbol(math, op, "\u22c1", "\\bigvee"); -defineSymbol(math, op, "\u22c0", "\\bigwedge"); -defineSymbol(math, op, "\u2a04", "\\biguplus"); -defineSymbol(math, op, "\u22c2", "\\bigcap"); -defineSymbol(math, op, "\u22c3", "\\bigcup"); -defineSymbol(math, op, "\u222b", "\\int"); -defineSymbol(math, op, "\u222b", "\\intop"); -defineSymbol(math, op, "\u222c", "\\iint"); -defineSymbol(math, op, "\u222d", "\\iiint"); -defineSymbol(math, op, "\u220f", "\\prod"); -defineSymbol(math, op, "\u2211", "\\sum"); -defineSymbol(math, op, "\u2a02", "\\bigotimes"); -defineSymbol(math, op, "\u2a01", "\\bigoplus"); -defineSymbol(math, op, "\u2a00", "\\bigodot"); -defineSymbol(math, op, "\u222e", "\\oint"); -defineSymbol(math, op, "\u222f", "\\oiint"); -defineSymbol(math, op, "\u2230", "\\oiiint"); -defineSymbol(math, op, "\u2231", "\\intclockwise"); -defineSymbol(math, op, "\u2232", "\\varointclockwise"); -defineSymbol(math, op, "\u2a0c", "\\iiiint"); -defineSymbol(math, op, "\u2a0d", "\\intbar"); -defineSymbol(math, op, "\u2a0e", "\\intBar"); -defineSymbol(math, op, "\u2a0f", "\\fint"); -defineSymbol(math, op, "\u2a12", "\\rppolint"); -defineSymbol(math, op, "\u2a13", "\\scpolint"); -defineSymbol(math, op, "\u2a15", "\\pointint"); -defineSymbol(math, op, "\u2a16", "\\sqint"); -defineSymbol(math, op, "\u2a17", "\\intlarhk"); -defineSymbol(math, op, "\u2a18", "\\intx"); -defineSymbol(math, op, "\u2a19", "\\intcap"); -defineSymbol(math, op, "\u2a1a", "\\intcup"); -defineSymbol(math, op, "\u2a05", "\\bigsqcap"); -defineSymbol(math, op, "\u2a06", "\\bigsqcup"); -defineSymbol(math, op, "\u222b", "\\smallint"); -defineSymbol(text, inner, "\u2026", "\\textellipsis"); -defineSymbol(math, inner, "\u2026", "\\mathellipsis"); -defineSymbol(text, inner, "\u2026", "\\ldots", true); -defineSymbol(math, inner, "\u2026", "\\ldots", true); -defineSymbol(math, inner, "\u22f0", "\\iddots", true); -defineSymbol(math, inner, "\u22ef", "\\@cdots", true); -defineSymbol(math, inner, "\u22f1", "\\ddots", true); -defineSymbol(math, textord, "\u22ee", "\\varvdots"); // \vdots is a macro -defineSymbol(math, accent, "\u02ca", "\\acute"); -defineSymbol(math, accent, "\u0060", "\\grave"); -defineSymbol(math, accent, "\u00a8", "\\ddot"); -defineSymbol(math, accent, "\u20db", "\\dddot"); -defineSymbol(math, accent, "\u20dc", "\\ddddot"); -defineSymbol(math, accent, "\u007e", "\\tilde"); -defineSymbol(math, accent, "\u00af", "\\bar"); -defineSymbol(math, accent, "\u02d8", "\\breve"); -defineSymbol(math, accent, "\u02c7", "\\check"); -defineSymbol(math, accent, "\u005e", "\\hat"); -defineSymbol(math, accent, "\u20d7", "\\vec"); -defineSymbol(math, accent, "\u02d9", "\\dot"); -defineSymbol(math, accent, "\u02da", "\\mathring"); -defineSymbol(math, mathord, "\u0131", "\\imath", true); -defineSymbol(math, mathord, "\u0237", "\\jmath", true); -defineSymbol(math, textord, "\u0131", "\u0131"); -defineSymbol(math, textord, "\u0237", "\u0237"); -defineSymbol(text, textord, "\u0131", "\\i", true); -defineSymbol(text, textord, "\u0237", "\\j", true); -defineSymbol(text, textord, "\u00df", "\\ss", true); -defineSymbol(text, textord, "\u00e6", "\\ae", true); -defineSymbol(text, textord, "\u0153", "\\oe", true); -defineSymbol(text, textord, "\u00f8", "\\o", true); -defineSymbol(math, mathord, "\u00f8", "\\o", true); -defineSymbol(text, textord, "\u00c6", "\\AE", true); -defineSymbol(text, textord, "\u0152", "\\OE", true); -defineSymbol(text, textord, "\u00d8", "\\O", true); -defineSymbol(math, mathord, "\u00d8", "\\O", true); -defineSymbol(text, accent, "\u02ca", "\\'"); // acute -defineSymbol(text, accent, "\u02cb", "\\`"); // grave -defineSymbol(text, accent, "\u02c6", "\\^"); // circumflex -defineSymbol(text, accent, "\u02dc", "\\~"); // tilde -defineSymbol(text, accent, "\u02c9", "\\="); // macron -defineSymbol(text, accent, "\u02d8", "\\u"); // breve -defineSymbol(text, accent, "\u02d9", "\\."); // dot above -defineSymbol(text, accent, "\u00b8", "\\c"); // cedilla -defineSymbol(text, accent, "\u02da", "\\r"); // ring above -defineSymbol(text, accent, "\u02c7", "\\v"); // caron -defineSymbol(text, accent, "\u00a8", '\\"'); // diaresis -defineSymbol(text, accent, "\u02dd", "\\H"); // double acute -defineSymbol(math, accent, "\u02ca", "\\'"); // acute -defineSymbol(math, accent, "\u02cb", "\\`"); // grave -defineSymbol(math, accent, "\u02c6", "\\^"); // circumflex -defineSymbol(math, accent, "\u02dc", "\\~"); // tilde -defineSymbol(math, accent, "\u02c9", "\\="); // macron -defineSymbol(math, accent, "\u02d8", "\\u"); // breve -defineSymbol(math, accent, "\u02d9", "\\."); // dot above -defineSymbol(math, accent, "\u00b8", "\\c"); // cedilla -defineSymbol(math, accent, "\u02da", "\\r"); // ring above -defineSymbol(math, accent, "\u02c7", "\\v"); // caron -defineSymbol(math, accent, "\u00a8", '\\"'); // diaresis -defineSymbol(math, accent, "\u02dd", "\\H"); // double acute - -// These ligatures are detected and created in Parser.js's `formLigatures`. -const ligatures = { - "--": true, - "---": true, - "``": true, - "''": true -}; - -defineSymbol(text, textord, "\u2013", "--", true); -defineSymbol(text, textord, "\u2013", "\\textendash"); -defineSymbol(text, textord, "\u2014", "---", true); -defineSymbol(text, textord, "\u2014", "\\textemdash"); -defineSymbol(text, textord, "\u2018", "`", true); -defineSymbol(text, textord, "\u2018", "\\textquoteleft"); -defineSymbol(text, textord, "\u2019", "'", true); -defineSymbol(text, textord, "\u2019", "\\textquoteright"); -defineSymbol(text, textord, "\u201c", "``", true); -defineSymbol(text, textord, "\u201c", "\\textquotedblleft"); -defineSymbol(text, textord, "\u201d", "''", true); -defineSymbol(text, textord, "\u201d", "\\textquotedblright"); -// \degree from gensymb package -defineSymbol(math, textord, "\u00b0", "\\degree", true); -defineSymbol(text, textord, "\u00b0", "\\degree"); -// \textdegree from inputenc package -defineSymbol(text, textord, "\u00b0", "\\textdegree", true); -// TODO: In LaTeX, \pounds can generate a different character in text and math -// mode, but among our fonts, only Main-Regular defines this character "163". -defineSymbol(math, textord, "\u00a3", "\\pounds"); -defineSymbol(math, textord, "\u00a3", "\\mathsterling", true); -defineSymbol(text, textord, "\u00a3", "\\pounds"); -defineSymbol(text, textord, "\u00a3", "\\textsterling", true); -defineSymbol(math, textord, "\u2720", "\\maltese"); -defineSymbol(text, textord, "\u2720", "\\maltese"); -defineSymbol(math, textord, "\u20ac", "\\euro", true); -defineSymbol(text, textord, "\u20ac", "\\euro", true); -defineSymbol(text, textord, "\u20ac", "\\texteuro"); -defineSymbol(math, textord, "\u00a9", "\\copyright", true); -defineSymbol(text, textord, "\u00a9", "\\textcopyright"); - -// Italic Greek -defineSymbol(math, textord, "𝛤", "\\varGamma"); -defineSymbol(math, textord, "𝛥", "\\varDelta"); -defineSymbol(math, textord, "𝛩", "\\varTheta"); -defineSymbol(math, textord, "𝛬", "\\varLambda"); -defineSymbol(math, textord, "𝛯", "\\varXi"); -defineSymbol(math, textord, "𝛱", "\\varPi"); -defineSymbol(math, textord, "𝛴", "\\varSigma"); -defineSymbol(math, textord, "𝛶", "\\varUpsilon"); -defineSymbol(math, textord, "𝛷", "\\varPhi"); -defineSymbol(math, textord, "𝛹", "\\varPsi"); -defineSymbol(math, textord, "𝛺", "\\varOmega"); -defineSymbol(text, textord, "𝛤", "\\varGamma"); -defineSymbol(text, textord, "𝛥", "\\varDelta"); -defineSymbol(text, textord, "𝛩", "\\varTheta"); -defineSymbol(text, textord, "𝛬", "\\varLambda"); -defineSymbol(text, textord, "𝛯", "\\varXi"); -defineSymbol(text, textord, "𝛱", "\\varPi"); -defineSymbol(text, textord, "𝛴", "\\varSigma"); -defineSymbol(text, textord, "𝛶", "\\varUpsilon"); -defineSymbol(text, textord, "𝛷", "\\varPhi"); -defineSymbol(text, textord, "𝛹", "\\varPsi"); -defineSymbol(text, textord, "𝛺", "\\varOmega"); - - -// There are lots of symbols which are the same, so we add them in afterwards. -// All of these are textords in math mode -const mathTextSymbols = '0123456789/@."'; -for (let i = 0; i < mathTextSymbols.length; i++) { - const ch = mathTextSymbols.charAt(i); - defineSymbol(math, textord, ch, ch); -} - -// All of these are textords in text mode -const textSymbols = '0123456789!@*()-=+";:?/.,'; -for (let i = 0; i < textSymbols.length; i++) { - const ch = textSymbols.charAt(i); - defineSymbol(text, textord, ch, ch); -} - -// All of these are textords in text mode, and mathords in math mode -const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -for (let i = 0; i < letters.length; i++) { - const ch = letters.charAt(i); - defineSymbol(math, mathord, ch, ch); - defineSymbol(text, textord, ch, ch); -} - -// Some more letters in Unicode Basic Multilingual Plane. -const narrow = "ÇÐÞçþℂℍℕℙℚℝℤℎℏℊℋℌℐℑℒℓ℘ℛℜℬℰℱℳℭℨ"; -for (let i = 0; i < narrow.length; i++) { - const ch = narrow.charAt(i); - defineSymbol(math, mathord, ch, ch); - defineSymbol(text, textord, ch, ch); -} - -// The next loop loads wide (surrogate pair) characters. -// We support some letters in the Unicode range U+1D400 to U+1D7FF, -// Mathematical Alphanumeric Symbols. -let wideChar = ""; -for (let i = 0; i < letters.length; i++) { - // The hex numbers in the next line are a surrogate pair. - // 0xD835 is the high surrogate for all letters in the range we support. - // 0xDC00 is the low surrogate for bold A. - wideChar = String.fromCharCode(0xd835, 0xdc00 + i); // A-Z a-z bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdc34 + i); // A-Z a-z italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdc68 + i); // A-Z a-z bold italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdd04 + i); // A-Z a-z Fractur - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdda0 + i); // A-Z a-z sans-serif - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xddd4 + i); // A-Z a-z sans bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xde08 + i); // A-Z a-z sans italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xde70 + i); // A-Z a-z monospace - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdd38 + i); // A-Z a-z double struck - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - const ch = letters.charAt(i); - wideChar = String.fromCharCode(0xd835, 0xdc9c + i); // A-Z a-z calligraphic - defineSymbol(math, mathord, ch, wideChar); - defineSymbol(text, textord, ch, wideChar); -} - -// Next, some wide character numerals -for (let i = 0; i < 10; i++) { - wideChar = String.fromCharCode(0xd835, 0xdfce + i); // 0-9 bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdfe2 + i); // 0-9 sans serif - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdfec + i); // 0-9 bold sans - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdff6 + i); // 0-9 monospace - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); -} - -/* - * Neither Firefox nor Chrome support hard line breaks or soft line breaks. - * (Despite https://www.w3.org/Math/draft-spec/mathml.html#chapter3_presm.lbattrs) - * So Temml has work-arounds for both hard and soft breaks. - * The work-arounds sadly do not work simultaneously. Any top-level hard - * break makes soft line breaks impossible. - * - * Hard breaks are simulated by creating a and putting each line in its own . - * - * To create soft line breaks, Temml avoids using the and tags. - * Then the top level of a element can be occupied by elements, and the browser - * will break after a if the expression extends beyond the container limit. - * - * We want the expression to render with soft line breaks after each top-level binary or - * relational operator, per TeXbook p. 173. So we gather the expression into s so that - * each ends in a binary or relational operator. - * - * Soft line breaks will not work in Chromium and Safari, only Firefox. - * - * Hopefully browsers will someday do their own linebreaking and we will be able to delete - * much of this module. - */ - -function setLineBreaks(expression, isDisplayMode, isAnnotated, color = undefined) { - if (color === undefined) { - // First, make one pass through the expression and split any color nodes. - const upperLimit = expression.length - 1; - for (let i = upperLimit; i >= 0; i--) { - const node = expression[i]; - if (node.type === "mstyle" && node.attributes.mathcolor) { - const color = node.attributes.mathcolor; - const fragment = setLineBreaks(node.children, isDisplayMode, isAnnotated, color); - if (!(fragment.type && fragment.type !== "mtable")) { - expression.splice(i, 1, ...fragment.children); - - } - } - } - } - - const tagName = color ? "mstyle" : "mrow"; - - const mtrs = []; - let mrows = []; - let block = []; - let canBeBIN = false; // The first node cannot be an infix binary operator. - for (let i = 0; i < expression.length; i++) { - const node = expression[i]; - if (node.type && node.type === "mstyle" && node.attributes.mathcolor) { - // Start a new block. (Insert a soft linebreak.) - mrows.push(new mathMLTree.MathNode(tagName, block)); - // Insert the mstyle - mrows.push(node); - block = []; - continue - } - if (node.attributes && node.attributes.linebreak && - node.attributes.linebreak === "newline") { - // A hard line break. Create a for the current block. - if (block.length > 0) { - const element = new mathMLTree.MathNode(tagName, block); - if (color) { element.setAttribute("mathcolor", color); } - mrows.push(new mathMLTree.MathNode(tagName, block)); - } - mrows.push(node); - block = []; - const mtd = new mathMLTree.MathNode("mtd", mrows); - mtrs.push(new mathMLTree.MathNode("mtr", [mtd])); - mrows = []; - continue - } - block.push(node); - if (node.type && node.type === "mo" && !isDisplayMode && !isAnnotated) { - // This may be a place for a soft line break. - if (canBeBIN && !node.attributes.form) { - // Check if the following node is a \nobreak text node, e.g. "~"" - const next = i < expression.length - 1 ? expression[i + 1] : null; - let glueIsFreeOfNobreak = true; - if ( - !( - next && - next.type === "mtext" && - next.attributes.linebreak && - next.attributes.linebreak === "nobreak" - ) - ) { - // We may need to start a new block. - // First, put any post-operator glue on same line as operator. - for (let j = i + 1; j < expression.length; j++) { - const nd = expression[j]; - if ( - nd.type && - nd.type === "mspace" && - !(nd.attributes.linebreak && nd.attributes.linebreak === "newline") - ) { - block.push(nd); - i += 1; - if ( - nd.attributes && - nd.attributes.linebreak && - nd.attributes.linebreak === "nobreak" - ) { - glueIsFreeOfNobreak = false; - } - } else { - break; - } - } - } - if (glueIsFreeOfNobreak) { - // Start a new block. (Insert a soft linebreak.) - const element = new mathMLTree.MathNode(tagName, block); - if (color) { element.setAttribute("mathcolor", color); } - mrows.push(element); - block = []; - } - canBeBIN = false; - } - const isOpenDelimiter = node.attributes.form && node.attributes.form === "prefix"; - // Any operator that follows an open delimiter is unary. - canBeBIN = !(node.attributes.separator || isOpenDelimiter); - } else { - canBeBIN = true; - } - } - if (block.length > 0) { - const element = new mathMLTree.MathNode(tagName, block); - if (color) { element.setAttribute("mathcolor", color); } - mrows.push(element); - } - if (mtrs.length > 0) { - const mtd = new mathMLTree.MathNode("mtd", mrows); - const mtr = new mathMLTree.MathNode("mtr", [mtd]); - mtrs.push(mtr); - const mtable = new mathMLTree.MathNode("mtable", mtrs); - if (!isDisplayMode) { - mtable.setAttribute("columnalign", "left"); - mtable.setAttribute("rowspacing", "0em"); - } - return mtable - } - return mathMLTree.newDocumentFragment(mrows); -} - -/** - * This file converts a parse tree into a cooresponding MathML tree. The main - * entry point is the `buildMathML` function, which takes a parse tree from the - * parser. - */ - -/** - * Takes a symbol and converts it into a MathML text node after performing - * optional replacement from symbols.js. - */ -const makeText = function(text, mode, style) { - if ( - symbols[mode][text] && - symbols[mode][text].replace && - text.charCodeAt(0) !== 0xd835 && - !( - Object.prototype.hasOwnProperty.call(ligatures, text) && - style && - ((style.fontFamily && style.fontFamily.substr(4, 2) === "tt") || - (style.font && style.font.substr(4, 2) === "tt")) - ) - ) { - text = symbols[mode][text].replace; - } - - return new mathMLTree.TextNode(text); -}; - -/** - * Wrap the given array of nodes in an node if needed, i.e., - * unless the array has length 1. Always returns a single node. - */ -const makeRow = function(body) { - if (body.length === 1) { - return body[0]; - } else { - return new mathMLTree.MathNode("mrow", body); - } -}; - -/** - * Takes a list of nodes, builds them, and returns a list of the generated - * MathML nodes. Also combine consecutive outputs into a single - * tag. - */ -const buildExpression = function(expression, style, isOrdgroup) { - if (expression.length === 1) { - const group = buildGroup(expression[0], style); - if (isOrdgroup && group instanceof MathNode && group.type === "mo") { - // When TeX writers want to suppress spacing on an operator, - // they often put the operator by itself inside braces. - group.setAttribute("lspace", "0em"); - group.setAttribute("rspace", "0em"); - } - return [group]; - } - - const groups = []; - for (let i = 0; i < expression.length; i++) { - const group = buildGroup(expression[i], style); - groups.push(group); - } - return groups; -}; - -/** - * Equivalent to buildExpression, but wraps the elements in an - * if there's more than one. Returns a single node instead of an array. - */ -const buildExpressionRow = function(expression, style, isOrdgroup) { - return makeRow(buildExpression(expression, style, isOrdgroup)); -}; - -/** - * Takes a group from the parser and calls the appropriate groupBuilders function - * on it to produce a MathML node. - */ -const buildGroup = function(group, style) { - if (!group) { - return new mathMLTree.MathNode("mrow"); - } - - if (_mathmlGroupBuilders[group.type]) { - // Call the groupBuilders function - const result = _mathmlGroupBuilders[group.type](group, style); - return result; - } else { - throw new ParseError("Got group of unknown type: '" + group.type + "'"); - } -}; - - -const taggedExpression = (expression, tag, style, leqno, preventTagLap) => { - const glue = new mathMLTree.MathNode("mtd", []); - glue.setAttribute("style", "padding: 0;width: 50%;"); - tag = buildExpressionRow(tag[0].body, style); - tag.classes = ["tml-tag"]; - if (!preventTagLap) { - tag = new mathMLTree.MathNode("mpadded", [tag]); - tag.setAttribute("style", "width:0;"); - tag.setAttribute("width", "0"); - tag.setAttribute((leqno ? "rspace" : "lspace"), "-1width"); - } - tag = new mathMLTree.MathNode("mtd", [tag]); - if (!preventTagLap) { tag.setAttribute("style", "padding: 0; min-width:0"); } - - expression = new mathMLTree.MathNode("mtd", [expression]); - const rowArray = leqno - ? [tag, glue, expression, glue] - : [glue, expression, glue, tag]; - const mtr = new mathMLTree.MathNode("mtr", rowArray, ["tml-tageqn"]); - const table = new mathMLTree.MathNode("mtable", [mtr]); - table.setAttribute("width", "100%"); - return table -}; - -/** - * Takes a full parse tree and settings and builds a MathML representation of - * it. - */ -function buildMathML(tree, texExpression, style, settings) { - // Strip off outer tag wrapper for processing below. - let tag = null; - if (tree.length === 1 && tree[0].type === "tag") { - tag = tree[0].tag; - tree = tree[0].body; - } - - const expression = buildExpression(tree, style); - - const n1 = expression.length === 0 ? null : expression[0]; - let wrapper = expression.length === 1 && tag === null && (n1 instanceof MathNode) - && !(n1.type === "mstyle" && n1.attributes.mathcolor) - ? expression[0] - : setLineBreaks(expression, settings.displayMode, settings.annotate); - - if (tag) { - wrapper = taggedExpression(wrapper, tag, style, settings.leqno, settings.preventTagLap); - } - - let semantics; - if (settings.annotate) { - // Build a TeX annotation of the source - const annotation = new mathMLTree.MathNode( - "annotation", [new mathMLTree.TextNode(texExpression)]); - annotation.setAttribute("encoding", "application/x-tex"); - semantics = new mathMLTree.MathNode("semantics", [wrapper, annotation]); - } - - const math = settings.annotate - ? new mathMLTree.MathNode("math", [semantics]) - : new mathMLTree.MathNode("math", [wrapper]); - - if (settings.xml) { - math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML"); - } - if (settings.displayMode) { - math.setAttribute("display", "block"); - } - return math; -} - -const mathmlBuilder = (group, style) => { - const accentNode = group.isStretchy - ? stretchy.mathMLnode(group.label) - : new mathMLTree.MathNode("mo", [makeText(group.label, group.mode)]); - - if (!group.isStretchy) { - accentNode.setAttribute("stretchy", "false"); - } - - const node = new mathMLTree.MathNode((group.label === "\\c" ? "munder" : "mover"), - [buildGroup(group.base, style), accentNode] - ); - - node.setAttribute("accent", "true"); - return node; -}; - -const NON_STRETCHY_ACCENT_REGEX = new RegExp( - [ - "\\acute", - "\\grave", - "\\ddot", - "\\dddot", - "\\ddddot", - "\\tilde", - "\\bar", - "\\breve", - "\\check", - "\\hat", - "\\vec", - "\\dot", - "\\mathring" - ] - .map((accent) => `\\${accent}`) - .join("|") -); - -// Accents -defineFunction({ - type: "accent", - names: [ - "\\acute", - "\\grave", - "\\ddot", - "\\dddot", - "\\ddddot", - "\\tilde", - "\\bar", - "\\breve", - "\\check", - "\\hat", - "\\vec", - "\\dot", - "\\mathring", - "\\overparen", - "\\widecheck", - "\\widehat", - "\\wideparen", - "\\widetilde", - "\\overrightarrow", - "\\overleftarrow", - "\\Overrightarrow", - "\\overleftrightarrow", - "\\overgroup", - "\\overleftharpoon", - "\\overrightharpoon" - ], - props: { - numArgs: 1 - }, - handler: (context, args) => { - const base = normalizeArgument(args[0]); - - const isStretchy = !NON_STRETCHY_ACCENT_REGEX.test(context.funcName); - const isShifty = - !isStretchy || - context.funcName === "\\widehat" || - context.funcName === "\\widetilde" || - context.funcName === "\\widecheck"; - - return { - type: "accent", - mode: context.parser.mode, - label: context.funcName, - isStretchy: isStretchy, - isShifty: isShifty, - base: base - }; - }, - mathmlBuilder -}); - -// Text-mode accents -defineFunction({ - type: "accent", - names: ["\\'", "\\`", "\\^", "\\~", "\\=", "\\c", "\\u", "\\.", '\\"', "\\r", "\\H", "\\v"], - props: { - numArgs: 1, - allowedInText: true, - allowedInMath: true, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const base = normalizeArgument(args[0]); - const mode = context.parser.mode; - - if (mode === "math" && context.parser.settings.strict) { - // LaTeX only writes a warning. It doesn't stop. We'll issue the same warning. - // eslint-disable-next-line no-console - console.log(`Temml parse error: Command ${context.funcName} is invalid in math mode.`); - } - - return { - type: "accent", - mode: mode, - label: context.funcName, - isStretchy: false, - isShifty: true, - base: base - }; - }, - mathmlBuilder -}); - -defineFunction({ - type: "accentUnder", - names: [ - "\\underleftarrow", - "\\underrightarrow", - "\\underleftrightarrow", - "\\undergroup", - "\\underparen", - "\\utilde" - ], - props: { - numArgs: 1 - }, - handler: ({ parser, funcName }, args) => { - const base = args[0]; - return { - type: "accentUnder", - mode: parser.mode, - label: funcName, - base: base - }; - }, - mathmlBuilder: (group, style) => { - const accentNode = stretchy.mathMLnode(group.label); - const node = new mathMLTree.MathNode("munder", [ - buildGroup(group.base, style), - accentNode - ]); - node.setAttribute("accentunder", "true"); - return node; - } -}); - -// Helper functions -const paddedNode = (group, width = "+0.6em") => { - const node = new mathMLTree.MathNode("mpadded", group ? [group] : []); - node.setAttribute("width", width); - node.setAttribute("lspace", "0.3em"); - return node; -}; - -const munderoverNode = (label, body, below, style, macros = {}) => { - const arrowNode = stretchy.mathMLnode(label, macros); - const minWidth = label.charAt(1) === "x" - ? "1.75em" // mathtools extensible arrows - : label.slice(2, 4) === "cd" - ? "3.0em" // cd package arrows - : "2.0em"; // mhchem arrows - arrowNode.setAttribute("minsize", minWidth); - // minsize attribute doesn't work in Firefox. - // https://bugzilla.mozilla.org/show_bug.cgi?id=320303 - const labelStyle = style.incrementLevel(); - - const upperNode = (body && body.body && - // \hphantom visible content - (body.body.body || body.body.length > 0)) - ? paddedNode(buildGroup(body, labelStyle)) - // Since Firefox does not recognize minsize set on the arrow, - // create an upper node w/correct width. - : paddedNode(null, minWidth); - const lowerNode = (below && below.body && - (below.body.body || below.body.length > 0)) - ? paddedNode(buildGroup(below, labelStyle)) - : paddedNode(null, minWidth); - const node = new mathMLTree.MathNode("munderover", [arrowNode, lowerNode, upperNode]); - return node -}; - -// Stretchy arrows with an optional argument -defineFunction({ - type: "xArrow", - names: [ - "\\xleftarrow", - "\\xrightarrow", - "\\xLeftarrow", - "\\xRightarrow", - "\\xleftrightarrow", - "\\xLeftrightarrow", - "\\xhookleftarrow", - "\\xhookrightarrow", - "\\xmapsto", - "\\xrightharpoondown", - "\\xrightharpoonup", - "\\xleftharpoondown", - "\\xleftharpoonup", - "\\xlongequal", - "\\xtwoheadrightarrow", - "\\xtwoheadleftarrow", - // The next 7 functions are here only to support mhchem - "\\yields", - "\\yieldsLeft", - "\\mesomerism", - "\\longrightharpoonup", - "\\longleftharpoondown", - "\\equilibriumRight", - "\\equilibriumLeft", - // The next 3 functions are here only to support the {CD} environment. - "\\\\cdrightarrow", - "\\\\cdleftarrow", - "\\\\cdlongequal" - ], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser, funcName }, args, optArgs) { - return { - type: "xArrow", - mode: parser.mode, - label: funcName, - body: args[0], - below: optArgs[0], - macros: parser.gullet.macros // Contains SVG paths for mhchem equilibrium arrows. - }; - }, - mathmlBuilder(group, style) { - return munderoverNode(group.label, group.body, group.below, style, group.macros) - } -}); - -const arrowComponent = { - "\\xtofrom": ["\\xrightarrow", "\\xleftarrow"], - "\\xleftrightharpoons": ["\\xleftharpoonup", "\\xrightharpoondown"], - "\\xrightleftharpoons": ["\\xrightharpoonup", "\\xleftharpoondown"], - "\\yieldsLeftRight": ["\\yields", "\\yieldsLeft"], - "\\equilibrium": ["\\longrightharpoonup", "\\longleftharpoondown"] -}; - -// Browser are not good at stretching stacked arrows such as ⇄. -// So we stack a pair of single arrows. -defineFunction({ - type: "stackedArrow", - names: [ - "\\xtofrom", // expfeil - "\\xleftrightharpoons", // mathtools - "\\xrightleftharpoons", // mathtools - "\\yieldsLeftRight", // mhchem - "\\equilibrium" // mhchem - ], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser, funcName }, args, optArgs) { - const lowerArrowBody = args[0] - ? { - type: "hphantom", - mode: parser.mode, - body: args[0] - } - : null; - const upperArrowBelow = optArgs[0] - ? { - type: "hphantom", - mode: parser.mode, - body: optArgs[0] - } - : null; - return { - type: "stackedArrow", - mode: parser.mode, - label: funcName, - body: args[0], - upperArrowBelow, - lowerArrowBody, - below: optArgs[0] - }; - }, - mathmlBuilder(group, style) { - const topLabel = arrowComponent[group.label][0]; - const botLabel = arrowComponent[group.label][1]; - const topArrow = munderoverNode(topLabel, group.body, group.upperArrowBelow, style); - const botArrow = munderoverNode(botLabel, group.lowerArrowBody, group.below, style); - - const topSpace = new mathMLTree.MathNode("mspace"); - topSpace.setAttribute("width", "0.2778em"); - const botSpace = new mathMLTree.MathNode("mspace"); - botSpace.setAttribute("width", "-0.2778em"); - - const raiseNode = new mathMLTree.MathNode("mpadded", [topSpace, topArrow]); - raiseNode.setAttribute("voffset", "0.3em"); - raiseNode.setAttribute("height", "+0.3em"); - raiseNode.setAttribute("depth", "-0.3em"); - raiseNode.setAttribute("width", "0em"); - - const botRow = new mathMLTree.MathNode("mrow", [botSpace, botArrow]); - - const wrapper = new mathMLTree.MathNode("mpadded", [raiseNode, botRow]); - wrapper.setAttribute("voffset", "-0.18em"); - wrapper.setAttribute("height", "-0.18em"); - wrapper.setAttribute("depth", "+0.18em"); - wrapper.setAttribute("lspace", "0em"); - wrapper.setAttribute("rspace", "0em"); - return wrapper - } -}); - -defineFunction({ - type: "cancelto", - names: ["\\cancelto"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "cancelto", - mode: parser.mode, - value: args[0], - expression: args[1] - }; - }, - mathmlBuilder(group, style) { - const value = new mathMLTree.MathNode( - "mpadded", - [buildGroup(group.value, style)] - ); - value.setAttribute("depth", `-0.1em`); - value.setAttribute("height", `+0.1em`); - value.setAttribute("voffset", `0.1em`); - - const expression = new mathMLTree.MathNode( - "menclose", - [buildGroup(group.expression, style)] - ); - expression.setAttribute("notation", `updiagonalarrow`); - - return new mathMLTree.MathNode("msup", [expression, value]) - } -}); - -/** - * Asserts that the node is of the given type and returns it with stricter - * typing. Throws if the node's type does not match. - */ -function assertNodeType(node, type) { - if (!node || node.type !== type) { - throw new Error( - `Expected node of type ${type}, but got ` + - (node ? `node of type ${node.type}` : String(node)) - ); - } - return node; -} - -/** - * Returns the node more strictly typed iff it is of the given type. Otherwise, - * returns null. - */ -function assertSymbolNodeType(node) { - const typedNode = checkSymbolNodeType(node); - if (!typedNode) { - throw new Error( - `Expected node of symbol group type, but got ` + - (node ? `node of type ${node.type}` : String(node)) - ); - } - return typedNode; -} - -/** - * Returns the node more strictly typed iff it is of the given type. Otherwise, - * returns null. - */ -function checkSymbolNodeType(node) { - if (node && (node.type === "atom" || - Object.prototype.hasOwnProperty.call(NON_ATOMS, node.type))) { - return node; - } - return null; -} - -const cdArrowFunctionName = { - ">": "\\\\cdrightarrow", - "<": "\\\\cdleftarrow", - "=": "\\\\cdlongequal", - A: "\\uparrow", - V: "\\downarrow", - "|": "\\Vert", - ".": "no arrow" -}; - -const newCell = () => { - // Create an empty cell, to be filled below with parse nodes. - return { type: "styling", body: [], mode: "math", scriptLevel: "display" }; -}; - -const isStartOfArrow = (node) => { - return node.type === "textord" && node.text === "@"; -}; - -const isLabelEnd = (node, endChar) => { - return (node.type === "mathord" || node.type === "atom") && node.text === endChar; -}; - -function cdArrow(arrowChar, labels, parser) { - // Return a parse tree of an arrow and its labels. - // This acts in a way similar to a macro expansion. - const funcName = cdArrowFunctionName[arrowChar]; - switch (funcName) { - case "\\\\cdrightarrow": - case "\\\\cdleftarrow": - return parser.callFunction(funcName, [labels[0]], [labels[1]]); - case "\\uparrow": - case "\\downarrow": { - const leftLabel = parser.callFunction("\\\\cdleft", [labels[0]], []); - const bareArrow = { - type: "atom", - text: funcName, - mode: "math", - family: "rel" - }; - const sizedArrow = parser.callFunction("\\Big", [bareArrow], []); - const rightLabel = parser.callFunction("\\\\cdright", [labels[1]], []); - const arrowGroup = { - type: "ordgroup", - mode: "math", - body: [leftLabel, sizedArrow, rightLabel] - }; - return parser.callFunction("\\\\cdparent", [arrowGroup], []); - } - case "\\\\cdlongequal": - return parser.callFunction("\\\\cdlongequal", [], []); - case "\\Vert": { - const arrow = { type: "textord", text: "\\Vert", mode: "math" }; - return parser.callFunction("\\Big", [arrow], []); - } - default: - return { type: "textord", text: " ", mode: "math" }; - } -} - -function parseCD(parser) { - // Get the array's parse nodes with \\ temporarily mapped to \cr. - const parsedRows = []; - parser.gullet.beginGroup(); - parser.gullet.macros.set("\\cr", "\\\\\\relax"); - parser.gullet.beginGroup(); - while (true) { // eslint-disable-line no-constant-condition - // Get the parse nodes for the next row. - parsedRows.push(parser.parseExpression(false, "\\\\")); - parser.gullet.endGroup(); - parser.gullet.beginGroup(); - const next = parser.fetch().text; - if (next === "&" || next === "\\\\") { - parser.consume(); - } else if (next === "\\end") { - if (parsedRows[parsedRows.length - 1].length === 0) { - parsedRows.pop(); // final row ended in \\ - } - break; - } else { - throw new ParseError("Expected \\\\ or \\cr or \\end", parser.nextToken); - } - } - - let row = []; - const body = [row]; - - // Loop thru the parse nodes. Collect them into cells and arrows. - for (let i = 0; i < parsedRows.length; i++) { - // Start a new row. - const rowNodes = parsedRows[i]; - // Create the first cell. - let cell = newCell(); - - for (let j = 0; j < rowNodes.length; j++) { - if (!isStartOfArrow(rowNodes[j])) { - // If a parseNode is not an arrow, it goes into a cell. - cell.body.push(rowNodes[j]); - } else { - // Parse node j is an "@", the start of an arrow. - // Before starting on the arrow, push the cell into `row`. - row.push(cell); - - // Now collect parseNodes into an arrow. - // The character after "@" defines the arrow type. - j += 1; - const arrowChar = assertSymbolNodeType(rowNodes[j]).text; - - // Create two empty label nodes. We may or may not use them. - const labels = new Array(2); - labels[0] = { type: "ordgroup", mode: "math", body: [] }; - labels[1] = { type: "ordgroup", mode: "math", body: [] }; - - // Process the arrow. - if ("=|.".indexOf(arrowChar) > -1) ; else if ("<>AV".indexOf(arrowChar) > -1) { - // Four arrows, `@>>>`, `@<<<`, `@AAA`, and `@VVV`, each take - // two optional labels. E.g. the right-point arrow syntax is - // really: @>{optional label}>{optional label}> - // Collect parseNodes into labels. - for (let labelNum = 0; labelNum < 2; labelNum++) { - let inLabel = true; - for (let k = j + 1; k < rowNodes.length; k++) { - if (isLabelEnd(rowNodes[k], arrowChar)) { - inLabel = false; - j = k; - break; - } - if (isStartOfArrow(rowNodes[k])) { - throw new ParseError( - "Missing a " + arrowChar + " character to complete a CD arrow.", - rowNodes[k] - ); - } - - labels[labelNum].body.push(rowNodes[k]); - } - if (inLabel) { - // isLabelEnd never returned a true. - throw new ParseError( - "Missing a " + arrowChar + " character to complete a CD arrow.", - rowNodes[j] - ); - } - } - } else { - throw new ParseError(`Expected one of "<>AV=|." after @.`); - } - - // Now join the arrow to its labels. - const arrow = cdArrow(arrowChar, labels, parser); - - // Wrap the arrow in a styling node - row.push(arrow); - // In CD's syntax, cells are implicit. That is, everything that - // is not an arrow gets collected into a cell. So create an empty - // cell now. It will collect upcoming parseNodes. - cell = newCell(); - } - } - if (i % 2 === 0) { - // Even-numbered rows consist of: cell, arrow, cell, arrow, ... cell - // The last cell is not yet pushed into `row`, so: - row.push(cell); - } else { - // Odd-numbered rows consist of: vert arrow, empty cell, ... vert arrow - // Remove the empty cell that was placed at the beginning of `row`. - row.shift(); - } - row = []; - body.push(row); - } - - // End row group - parser.gullet.endGroup(); - // End array group defining \\ - parser.gullet.endGroup(); - - // define column separation. - const cols = new Array(body[0].length).fill({ - type: "align", - align: "c" - }); - - return { - type: "array", - mode: "math", - body, - arraystretch: 1, - addJot: true, - rowGaps: [null], - cols, - colSeparationType: "CD", - hLinesBeforeRow: new Array(body.length + 1).fill([]) - }; -} - -// The functions below are not available for general use. -// They are here only for internal use by the {CD} environment in placing labels -// next to vertical arrows. - -// We don't need any such functions for horizontal arrows because we can reuse -// the functionality that already exists for extensible arrows. - -defineFunction({ - type: "cdlabel", - names: ["\\\\cdleft", "\\\\cdright"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - return { - type: "cdlabel", - mode: parser.mode, - side: funcName.slice(4), - label: args[0] - }; - }, - mathmlBuilder(group, style) { - let label = new mathMLTree.MathNode("mrow", [buildGroup(group.label, style)]); - label = new mathMLTree.MathNode("mpadded", [label]); - label.setAttribute("width", "0"); - if (group.side === "left") { - label.setAttribute("lspace", "-1width"); - } - // We have to guess at vertical alignment. We know the arrow is 1.8em tall, - // But we don't know the height or depth of the label. - label.setAttribute("voffset", "0.7em"); - label = new mathMLTree.MathNode("mstyle", [label]); - label.setAttribute("displaystyle", "false"); - label.setAttribute("scriptlevel", "1"); - return label; - } -}); - -defineFunction({ - type: "cdlabelparent", - names: ["\\\\cdparent"], - props: { - numArgs: 1 - }, - handler({ parser }, args) { - return { - type: "cdlabelparent", - mode: parser.mode, - fragment: args[0] - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow", [buildGroup(group.fragment, style)]); - } -}); - -// \@char is an internal function that takes a grouped decimal argument like -// {123} and converts into symbol with code 123. It is used by the *macro* -// \char defined in macros.js. -defineFunction({ - type: "textord", - names: ["\\@char"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser }, args) { - const arg = assertNodeType(args[0], "ordgroup"); - const group = arg.body; - let number = ""; - for (let i = 0; i < group.length; i++) { - const node = assertNodeType(group[i], "textord"); - number += node.text; - } - const code = parseInt(number); - if (isNaN(code)) { - throw new ParseError(`\\@char has non-numeric argument ${number}`) - } - return { - type: "textord", - mode: parser.mode, - text: String.fromCodePoint(code) - } - } -}); - -/* In LaTeX, \colon is defined as: - * \renewcommand{\colon}{\nobreak\mskip2mu\mathpunct{}\nonscript - * \mkern-\thinmuskip{:}\mskip6muplus1mu\relax} - * - * Doing that with a Temml macro produces semantically poor MathML. Do it more directly. - */ - -defineFunction({ - type: "colonFunction", - names: ["\\colon"], - props: { numArgs: 0 }, - handler({ parser }) { return { type: "colonFunction", mode: parser.mode } }, - mathmlBuilder(group, style) { - const mo = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(":")]); - // lspace depends on the script level. - mo.attributes.lspace = (style.level < 2 ? "0.05556em" : "0.1111em"); - mo.attributes.rspace = "0.3333em"; // 6mu - return mo - } -}); - -defineFunction({ - type: "colonequal", - names: [":"], - props: { numArgs: 0 }, - handler({ parser }, args) { - if (parser.fetch().text === "=") { - // Special case for := - parser.consume(); - return { type: "colonequal", mode: parser.mode } - } - return { type: "atom", family: "rel", text: ":", mode: parser.mode } - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u2254")]) - } -}); - -// Helpers -const htmlRegEx = /^(#[a-f0-9]{3}|#?[a-f0-9]{6})$/i; -const htmlOrNameRegEx = /^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i; -const RGBregEx = /^ *\d{1,3} *(?:, *\d{1,3} *){2}$/; -const rgbRegEx = /^ *[10](?:\.\d*)? *(?:, *[10](?:\.\d*)? *){2}$/; -const xcolorHtmlRegEx = /^[a-f0-9]{6}$/i; -const toHex = num => { - let str = num.toString(16); - if (str.length === 1) { str = "0" + str; } - return str -}; - -// Colors from Tables 4.1 and 4.2 of the xcolor package. -// Table 4.1 (lower case) RGB values are taken from chroma and xcolor.dtx. -// Table 4.2 (Capitalizzed) values were sampled, because Chroma contains a unreliable -// conversion from cmyk to RGB. See https://tex.stackexchange.com/a/537274. -const xcolors = JSON.parse(`{ - "Apricot": "#ffb484", - "Aquamarine": "#08b4bc", - "Bittersweet": "#c84c14", - "blue": "#0000FF", - "Blue": "#303494", - "BlueGreen": "#08b4bc", - "BlueViolet": "#503c94", - "BrickRed": "#b8341c", - "brown": "#BF804", - "Brown": "#802404", - "BurntOrange": "#f8941c", - "CadetBlue": "#78749c", - "CarnationPink": "#f884b4", - "Cerulean": "#08a4e4", - "CornflowerBlue": "#40ace4", - "cyan": "#00FFF", - "Cyan": "#08acec", - "Dandelion": "#ffbc44", - "darkgray": "#404040", - "DarkOrchid": "#a8548c", - "Emerald": "#08ac9c", - "ForestGreen": "#089c54", - "Fuchsia": "#90348c", - "Goldenrod": "#ffdc44", - "gray": "#80808", - "Gray": "#98949c", - "green": "#00FF0", - "Green": "#08a44c", - "GreenYellow": "#e0e474", - "JungleGreen": "#08ac9c", - "Lavender": "#f89cc4", - "lightgray": "#BFBFB", - "lime": "#BFFF00", - "LimeGreen": "#90c43c", - "magenta": "#FF00F", - "Magenta": "#f0048c", - "Mahogany": "#b0341c", - "Maroon": "#b03434", - "Melon": "#f89c7c", - "MidnightBlue": "#086494", - "Mulberry": "#b03c94", - "NavyBlue": "#086cbc", - "olive": "#7F7F00", - "OliveGreen": "#407c34", - "orange": "#FF800", - "Orange": "#f8843c", - "OrangeRed": "#f0145c", - "Orchid": "#b074ac", - "Peach": "#f8945c", - "Periwinkle": "#8074bc", - "PineGreen": "#088c74", - "pink": "#ff7f7f", - "Plum": "#98248c", - "ProcessBlue": "#08b4ec", - "purple": "#BF0040", - "Purple": "#a0449c", - "RawSienna": "#983c04", - "red": "#ff0000", - "Red": "#f01c24", - "RedOrange": "#f86434", - "RedViolet": "#a0246c", - "Rhodamine": "#f0549c", - "Royallue": "#0874bc", - "RoyalPurple": "#683c9c", - "RubineRed": "#f0047c", - "Salmon": "#f8948c", - "SeaGreen": "#30bc9c", - "Sepia": "#701404", - "SkyBlue": "#48c4dc", - "SpringGreen": "#c8dc64", - "Tan": "#e09c74", - "teal": "#007F7F", - "TealBlue": "#08acb4", - "Thistle": "#d884b4", - "Turquoise": "#08b4cc", - "violet": "#800080", - "Violet": "#60449c", - "VioletRed": "#f054a4", - "WildStrawberry": "#f0246c", - "yellow": "#FFFF00", - "Yellow": "#fff404", - "YellowGreen": "#98cc6c", - "YellowOrange": "#ffa41c" -}`); - -const colorFromSpec = (model, spec) => { - let color = ""; - if (model === "HTML") { - if (!htmlRegEx.test(spec)) { - throw new ParseError("Invalid HTML input.") - } - color = spec; - } else if (model === "RGB") { - if (!RGBregEx.test(spec)) { - throw new ParseError("Invalid RGB input.") - } - spec.split(",").map(e => { color += toHex(Number(e.trim())); }); - } else { - if (!rgbRegEx.test(spec)) { - throw new ParseError("Invalid rbg input.") - } - spec.split(",").map(e => { - const num = Number(e.trim()); - if (num > 1) { throw new ParseError("Color rgb input must be < 1.") } - color += toHex((num * 255)); - }); - } - if (color.charAt(0) !== "#") { color = "#" + color; } - return color -}; - -const validateColor = (color, macros) => { - const macroName = `\\\\color@${color}`; // from \defineColor. - const match = htmlOrNameRegEx.exec(color); - if (!match) { throw new ParseError("Invalid color: '" + color + "'") } - // We allow a 6-digit HTML color spec without a leading "#". - // This follows the xcolor package's HTML color model. - // Predefined color names are all missed by this RegEx pattern. - if (xcolorHtmlRegEx.test(color)) { - return "#" + color - } else if (color.charAt(0) === "#") { - return color - } else if (macros.has(macroName)) { - color = macros.get(macroName).tokens[0].text; - } else if (xcolors[color]) { - color = xcolors[color]; - } - return color -}; - -const mathmlBuilder$1 = (group, style) => { - const inner = buildExpression(group.body, style.withColor(group.color)); - // Wrap with an element. - const node = wrapWithMstyle(inner); - node.setAttribute("mathcolor", group.color); - // Wrap w/. We get better operator spacing that way. - return new mathMLTree.MathNode("mrow", [node]) -}; - -defineFunction({ - type: "color", - names: ["\\textcolor"], - props: { - numArgs: 2, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "original"] - }, - handler({ parser }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let color = ""; - if (model) { - const spec = assertNodeType(args[0], "raw").string; - color = colorFromSpec(model, spec); - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros); - } - const body = args[1]; - return { - type: "color", - mode: parser.mode, - color, - body: ordargument(body) - } - }, - mathmlBuilder: mathmlBuilder$1 -}); - -defineFunction({ - type: "color", - names: ["\\color"], - props: { - numArgs: 1, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw"] - }, - handler({ parser, breakOnTokenText }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let color = ""; - if (model) { - const spec = assertNodeType(args[0], "raw").string; - color = colorFromSpec(model, spec); - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros); - } - - // Set macro \current@color in current namespace to store the current - // color, mimicking the behavior of color.sty. - // This is currently used just to correctly color a \right - // that follows a \color command. - parser.gullet.macros.set("\\current@color", color); - - // Parse out the implicit body that should be colored. - // Since \color nodes should not be nested, break on \color. - const body = parser.parseExpression(true, "\\color"); - - return { - type: "color", - mode: parser.mode, - color, - body - } - }, - mathmlBuilder: mathmlBuilder$1 -}); - -defineFunction({ - type: "color", - names: ["\\definecolor"], - props: { - numArgs: 3, - allowedInText: true, - argTypes: ["raw", "raw", "raw"] - }, - handler({ parser }, args) { - const name = assertNodeType(args[0], "raw").string; - if (!/^[A-Za-z]+$/.test(name)) { - throw new ParseError("Color name must be latin letters.") - } - const model = assertNodeType(args[1], "raw").string; - if (!["HTML", "RGB", "rgb"].includes(model)) { - throw new ParseError("Color model must be HTML, RGB, or rgb.") - } - const spec = assertNodeType(args[2], "raw").string; - const color = colorFromSpec(model, spec); - parser.gullet.macros.set(`\\\\color@${name}`, { tokens: [{ text: color }], numArgs: 0 }); - return { type: "internal", mode: parser.mode } - } - // No mathmlBuilder. The point of \definecolor is to set a macro. -}); - -/** - * This file does conversion between units. In particular, it provides - * calculateSize to convert other units into CSS units. - */ - -const ptPerUnit = { - // Convert to CSS (Postscipt) points, not TeX points - // https://en.wikibooks.org/wiki/LaTeX/Lengths and - // https://tex.stackexchange.com/a/8263 - pt: 800 / 803, // convert TeX point to CSS (Postscript) point - pc: (12 * 800) / 803, // pica - dd: ((1238 / 1157) * 800) / 803, // didot - cc: ((14856 / 1157) * 800) / 803, // cicero (12 didot) - nd: ((685 / 642) * 800) / 803, // new didot - nc: ((1370 / 107) * 800) / 803, // new cicero (12 new didot) - sp: ((1 / 65536) * 800) / 803 // scaled point (TeX's internal smallest unit) -}; - -/** - * Determine whether the specified unit (either a string defining the unit - * or a "size" parse node containing a unit field) is valid. - */ -const validUnits = [ - "em", - "ex", - "mu", - "pt", - "mm", - "cm", - "in", - "px", - "bp", - "pc", - "dd", - "cc", - "nd", - "nc", - "sp" -]; - -const validUnit = function(unit) { - if (typeof unit !== "string") { - unit = unit.unit; - } - return validUnits.indexOf(unit) > -1 -}; - -const emScale = styleLevel => { - const scriptLevel = Math.max(styleLevel - 1, 0); - return [1, 0.7, 0.5][scriptLevel] -}; - -/* - * Convert a "size" parse node (with numeric "number" and string "unit" fields, - * as parsed by functions.js argType "size") into a CSS value. - */ -const calculateSize = function(sizeValue, style) { - const number = sizeValue.number; - const unit = sizeValue.unit; - switch (unit) { - case "mm": - case "cm": - case "in": - case "px": - return { number, unit }; // absolute CSS units. - case "em": - case "ex": - // In TeX, em and ex do not change size in \scriptstyle. - return { number: utils.round(number / emScale(style.level)), unit }; - case "bp": - return { number, unit: "pt" }; // TeX bp is a CSS pt. (1/72 inch). - case "pt": - case "pc": - case "dd": - case "cc": - case "nd": - case "nc": - case "sp": - return { number: utils.round(number * ptPerUnit[unit]), unit: "pt" } - case "mu": { - return { number: utils.round(number / 18), unit: "em" } - } - default: - throw new ParseError("Invalid unit: '" + unit + "'") - } -}; - -// Row breaks within tabular environments, and line breaks at top level - -// \DeclareRobustCommand\\{...\@xnewline} -defineFunction({ - type: "cr", - names: ["\\\\"], - props: { - numArgs: 0, - numOptionalArgs: 1, - argTypes: ["size"], - allowedInText: true - }, - - handler({ parser }, args, optArgs) { - const size = optArgs[0]; - if (parser.settings.displayMode && parser.settings.strict === "warn") { - parser.settings.reportNonstrict( - "newLineInDisplayMode", - "In LaTeX, \\\\ or \\newline " + "does nothing in display mode" - ); - } - const newLine = !parser.settings.displayMode || parser.settings.strict !== true; - return { - type: "cr", - mode: parser.mode, - newLine, - size: size && assertNodeType(size, "size").value - } - }, - - // The following builder is called only at the top level, - // not within tabular/array environments. - - mathmlBuilder(group, style) { - // MathML 3.0 calls for newline to occur in an or an . - // Ref: https://www.w3.org/TR/MathML3/chapter3.html#presm.linebreaking - const node = new mathMLTree.MathNode("mo"); - if (group.newLine) { - node.setAttribute("linebreak", "newline"); - if (group.size) { - const size = calculateSize(group.size, style); - node.setAttribute("height", size.number + size.unit); - } - } - return node - } -}); - -const checkControlSequence = (tok) => { - const name = tok.text; - if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { - throw new ParseError("Expected a control sequence", tok); - } - return name; -}; - -const getRHS = (parser) => { - let tok = parser.gullet.popToken(); - if (tok.text === "=") { - // consume optional equals - tok = parser.gullet.popToken(); - if (tok.text === " ") { - // consume one optional space - tok = parser.gullet.popToken(); - } - } - return tok; -}; - -const letCommand = (parser, name, tok) => { - let macro = parser.gullet.macros.get(tok.text); - if (macro == null) { - // don't expand it later even if a macro with the same name is defined - // e.g., \let\foo=\frac \def\frac{\relax} \frac12 - tok.noexpand = true; - macro = { - tokens: [tok], - numArgs: 0, - // reproduce the same behavior in expansion - unexpandable: !parser.gullet.isExpandable(tok.text) - }; - } - parser.gullet.macros.set(name, macro); -}; - -// Basic support for macro definitions: \def -// -> -// -> -defineFunction({ - type: "internal", - names: ["\\def", "\\edef"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - let tok = parser.gullet.popToken(); - const name = tok.text; - if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { - throw new ParseError("Expected a control sequence", tok); - } - - let numArgs = 0; - let insert; - const delimiters = [[]]; - // contains no braces - while (parser.gullet.future().text !== "{") { - tok = parser.gullet.popToken(); - if (tok.text === "#") { - // If the very last character of the is #, so that - // this # is immediately followed by {, TeX will behave as if the { - // had been inserted at the right end of both the parameter text - // and the replacement text. - if (parser.gullet.future().text === "{") { - insert = parser.gullet.future(); - delimiters[numArgs].push("{"); - break; - } - - // A parameter, the first appearance of # must be followed by 1, - // the next by 2, and so on; up to nine #’s are allowed - tok = parser.gullet.popToken(); - if (!/^[1-9]$/.test(tok.text)) { - throw new ParseError(`Invalid argument number "${tok.text}"`); - } - if (parseInt(tok.text) !== numArgs + 1) { - throw new ParseError(`Argument number "${tok.text}" out of order`); - } - numArgs++; - delimiters.push([]); - } else if (tok.text === "EOF") { - throw new ParseError("Expected a macro definition"); - } else { - delimiters[numArgs].push(tok.text); - } - } - // replacement text, enclosed in '{' and '}' and properly nested - let { tokens } = parser.gullet.consumeArg(); - if (insert) { - tokens.unshift(insert); - } - - if (funcName === "\\edef") { - tokens = parser.gullet.expandTokens(tokens); - tokens.reverse(); // to fit in with stack order - } - // Final arg is the expansion of the macro - parser.gullet.macros.set(name, { tokens, numArgs, delimiters } - ); - return { type: "internal", mode: parser.mode }; - } -}); - -// -> -// -> \futurelet -// | \let -// -> |= -defineFunction({ - type: "internal", - names: ["\\let"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - const name = checkControlSequence(parser.gullet.popToken()); - parser.gullet.consumeSpaces(); - const tok = getRHS(parser); - letCommand(parser, name, tok); - return { type: "internal", mode: parser.mode }; - } -}); - -// ref: https://www.tug.org/TUGboat/tb09-3/tb22bechtolsheim.pdf -defineFunction({ - type: "internal", - names: ["\\futurelet"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - const name = checkControlSequence(parser.gullet.popToken()); - const middle = parser.gullet.popToken(); - const tok = parser.gullet.popToken(); - letCommand(parser, name, tok); - parser.gullet.pushToken(tok); - parser.gullet.pushToken(middle); - return { type: "internal", mode: parser.mode }; - } -}); - -defineFunction({ - type: "internal", - names: ["\\newcommand", "\\renewcommand", "\\providecommand"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - let name = ""; - const tok = parser.gullet.popToken(); - if (tok.text === "{") { - name = checkControlSequence(parser.gullet.popToken()); - parser.gullet.popToken(); - } else { - name = checkControlSequence(tok); - } - - const exists = parser.gullet.isDefined(name); - if (exists && funcName === "\\newcommand") { - throw new ParseError( - `\\newcommand{${name}} attempting to redefine ${name}; use \\renewcommand` - ); - } - if (!exists && funcName === "\\renewcommand") { - throw new ParseError( - `\\renewcommand{${name}} when command ${name} does not yet exist; use \\newcommand` - ); - } - - let numArgs = 0; - if (parser.gullet.future().text === "[") { - let tok = parser.gullet.popToken(); - tok = parser.gullet.popToken(); - if (!/^[0-9]$/.test(tok.text)) { - throw new ParseError(`Invalid number of arguments: "${tok.text}"`); - } - numArgs = parseInt(tok.text); - tok = parser.gullet.popToken(); - if (tok.text !== "]") { - throw new ParseError(`Invalid argument "${tok.text}"`); - } - } - - // replacement text, enclosed in '{' and '}' and properly nested - const { tokens } = parser.gullet.consumeArg(); - - parser.gullet.macros.set(name, { tokens, numArgs }); - - return { type: "internal", mode: parser.mode }; - - } -}); - -// Extra data needed for the delimiter handler down below -const delimiterSizes = { - "\\bigl": { mclass: "mopen", size: 1 }, - "\\Bigl": { mclass: "mopen", size: 2 }, - "\\biggl": { mclass: "mopen", size: 3 }, - "\\Biggl": { mclass: "mopen", size: 4 }, - "\\bigr": { mclass: "mclose", size: 1 }, - "\\Bigr": { mclass: "mclose", size: 2 }, - "\\biggr": { mclass: "mclose", size: 3 }, - "\\Biggr": { mclass: "mclose", size: 4 }, - "\\bigm": { mclass: "mrel", size: 1 }, - "\\Bigm": { mclass: "mrel", size: 2 }, - "\\biggm": { mclass: "mrel", size: 3 }, - "\\Biggm": { mclass: "mrel", size: 4 }, - "\\big": { mclass: "mord", size: 1 }, - "\\Big": { mclass: "mord", size: 2 }, - "\\bigg": { mclass: "mord", size: 3 }, - "\\Bigg": { mclass: "mord", size: 4 } -}; - -const delimiters = [ - "(", - "\\lparen", - ")", - "\\rparen", - "[", - "\\lbrack", - "]", - "\\rbrack", - "\\{", - "\\lbrace", - "\\}", - "\\rbrace", - "\\lfloor", - "\\rfloor", - "\u230a", - "\u230b", - "\\lceil", - "\\rceil", - "\u2308", - "\u2309", - "<", - ">", - "\\langle", - "\u27e8", - "\\rangle", - "\u27e9", - "\\lt", - "\\gt", - "\\lvert", - "\\rvert", - "\\lVert", - "\\rVert", - "\\lgroup", - "\\rgroup", - "\u27ee", - "\u27ef", - "\\lmoustache", - "\\rmoustache", - "\u23b0", - "\u23b1", - "\\llbracket", - "\\rrbracket", - "\u27e6", - "\u27e6", - "\\lBrace", - "\\rBrace", - "\u2983", - "\u2984", - "/", - "\\backslash", - "|", - "\\vert", - "\\|", - "\\Vert", - "\\uparrow", - "\\Uparrow", - "\\downarrow", - "\\Downarrow", - "\\updownarrow", - "\\Updownarrow", - "." -]; - -// Metrics of the different sizes. Found by looking at TeX's output of -// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$ -// Used to create stacked delimiters of appropriate sizes in makeSizedDelim. -const sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0]; - -// Delimiter functions -function checkDelimiter(delim, context) { - if (delim.type === "ordgroup" && delim.body.length === 1 && delim.body[0].text === "\u2044") { - // Recover "/" from the zero spacing group. (See macros.js) - delim = { type: "textord", text: "/", mode: "math" }; - } - const symDelim = checkSymbolNodeType(delim); - if (symDelim && utils.contains(delimiters, symDelim.text)) { - // If a character is not in the MathML operator dictionary, it will not stretch. - // Replace such characters w/characters that will stretch. - if (utils.contains(["<", "\\lt"], symDelim.text)) { symDelim.text = "⟨"; } - if (utils.contains([">", "\\gt"], symDelim.text)) { symDelim.text = "⟩"; } - if (symDelim.text === "/") { symDelim.text = "\u2215"; } - if (symDelim.text === "\\backslash") { symDelim.text = "\u2216"; } - return symDelim; - } else if (symDelim) { - throw new ParseError(`Invalid delimiter '${symDelim.text}' after '${context.funcName}'`, delim); - } else { - throw new ParseError(`Invalid delimiter type '${delim.type}'`, delim); - } -} - -defineFunction({ - type: "delimsizing", - names: [ - "\\bigl", - "\\Bigl", - "\\biggl", - "\\Biggl", - "\\bigr", - "\\Bigr", - "\\biggr", - "\\Biggr", - "\\bigm", - "\\Bigm", - "\\biggm", - "\\Biggm", - "\\big", - "\\Big", - "\\bigg", - "\\Bigg" - ], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - - return { - type: "delimsizing", - mode: context.parser.mode, - size: delimiterSizes[context.funcName].size, - mclass: delimiterSizes[context.funcName].mclass, - delim: delim.text - }; - }, - mathmlBuilder: (group) => { - const children = []; - - if (group.delim === ".") { group.delim = ""; } - children.push(makeText(group.delim, group.mode)); - - const node = new mathMLTree.MathNode("mo", children); - - if (group.mclass === "mopen" || group.mclass === "mclose") { - // Only some of the delimsizing functions act as fences, and they - // return "mopen" or "mclose" mclass. - node.setAttribute("fence", "true"); - } else { - // Explicitly disable fencing if it's not a fence, to override the - // defaults. - node.setAttribute("fence", "false"); - } - if (group.delim === "\u2216") { - // \backslash is not in the operator dictionary, - // so we have to explicitly set stretchy to true. - node.setAttribute("stretchy", "true"); - } - - node.setAttribute("symmetric", "true"); // Needed for tall arrows in Firefox. - node.setAttribute("minsize", sizeToMaxHeight[group.size] + "em"); - node.setAttribute("maxsize", sizeToMaxHeight[group.size] + "em"); - - return node; - } -}); - -function assertParsed(group) { - if (!group.body) { - throw new Error("Bug: The leftright ParseNode wasn't fully parsed."); - } -} - -defineFunction({ - type: "leftright-right", - names: ["\\right"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - // \left case below triggers parsing of \right in - // `const right = parser.parseFunction();` - // uses this return value. - const color = context.parser.gullet.macros.get("\\current@color"); - if (color && typeof color !== "string") { - throw new ParseError("\\current@color set to non-string in \\right"); - } - return { - type: "leftright-right", - mode: context.parser.mode, - delim: checkDelimiter(args[0], context).text, - color // undefined if not set via \color - }; - } -}); - -defineFunction({ - type: "leftright", - names: ["\\left"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - - const parser = context.parser; - // Parse out the implicit body - ++parser.leftrightDepth; - // parseExpression stops before '\\right' - const body = parser.parseExpression(false); - --parser.leftrightDepth; - // Check the next token - parser.expect("\\right", false); - const right = assertNodeType(parser.parseFunction(), "leftright-right"); - return { - type: "leftright", - mode: parser.mode, - body, - left: delim.text, - right: right.delim, - rightColor: right.color - }; - }, - mathmlBuilder: (group, style) => { - assertParsed(group); - const inner = buildExpression(group.body, style); - - if (group.left === ".") { group.left = ""; } - const leftNode = new mathMLTree.MathNode("mo", [makeText(group.left, group.mode)]); - leftNode.setAttribute("fence", "true"); - leftNode.setAttribute("form", "prefix"); - if (group.left === "\u2216") { leftNode.setAttribute("stretchy", "true"); } - inner.unshift(leftNode); - - if (group.right === ".") { group.right = ""; } - const rightNode = new mathMLTree.MathNode("mo", [makeText(group.right, group.mode)]); - rightNode.setAttribute("fence", "true"); - rightNode.setAttribute("form", "postfix"); - if (group.right === "\u2216") { rightNode.setAttribute("stretchy", "true"); } - if (group.rightColor) { rightNode.setAttribute("mathcolor", group.rightColor); } - inner.push(rightNode); - - return makeRow(inner); - } -}); - -defineFunction({ - type: "middle", - names: ["\\middle"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - if (!context.parser.leftrightDepth) { - throw new ParseError("\\middle without preceding \\left", delim); - } - - return { - type: "middle", - mode: context.parser.mode, - delim: delim.text - }; - }, - mathmlBuilder: (group, style) => { - const textNode = makeText(group.delim, group.mode); - const middleNode = new mathMLTree.MathNode("mo", [textNode]); - middleNode.setAttribute("fence", "true"); - // MathML gives 5/18em spacing to each element. - // \middle should get delimiter spacing instead. - middleNode.setAttribute("lspace", "0.05em"); - middleNode.setAttribute("rspace", "0.05em"); - return middleNode; - } -}); - -const mathmlBuilder$2 = (group, style) => { - const node = new mathMLTree.MathNode( - group.label.indexOf("colorbox") > -1 ? "mpadded" : "menclose", - [buildGroup(group.body, style)] - ); - switch (group.label) { - case "\\cancel": - node.setAttribute("notation", "updiagonalstrike"); - break; - case "\\bcancel": - node.setAttribute("notation", "downdiagonalstrike"); - break; - case "\\longdiv": - node.setAttribute("notation", "longdiv"); - break; - case "\\phase": - node.setAttribute("notation", "phasorangle"); - break; - case "\\sout": - node.setAttribute("notation", "horizontalstrike"); - break; - case "\\fbox": - node.setAttribute("notation", "box"); - break; - case "\\angl": - node.setAttribute("notation", "actuarial"); - break; - case "\\fcolorbox": - case "\\colorbox": { - // doesn't have a good notation option for \colorbox. - // So use instead. Set some attributes that come - // included with . - const fboxsep = 3; // 3 pt from LaTeX source2e - node.setAttribute("width", `+${2 * fboxsep}pt`); - node.setAttribute("height", `+${2 * fboxsep}pt`); - node.setAttribute("lspace", `${fboxsep}pt`); // - node.setAttribute("voffset", `${fboxsep}pt`); - if (group.label === "\\fcolorbox") { - node.setAttribute("style", "border: 0.06em solid " + String(group.borderColor)); - } - break; - } - case "\\xcancel": - node.setAttribute("notation", "updiagonalstrike downdiagonalstrike"); - break; - } - if (group.backgroundColor) { - node.setAttribute("mathbackground", group.backgroundColor); - } - return node; -}; - -defineFunction({ - type: "enclose", - names: ["\\colorbox"], - props: { - numArgs: 2, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "text"] - }, - handler({ parser, funcName }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let color = ""; - if (model) { - const spec = assertNodeType(args[0], "raw").string; - color = colorFromSpec(model, spec); - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros); - } - const body = args[1]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - backgroundColor: color, - body - }; - }, - mathmlBuilder: mathmlBuilder$2 -}); - -defineFunction({ - type: "enclose", - names: ["\\fcolorbox"], - props: { - numArgs: 3, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "raw", "text"] - }, - handler({ parser, funcName }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let borderColor = ""; - let backgroundColor; - if (model) { - const borderSpec = assertNodeType(args[0], "raw").string; - const backgroundSpec = assertNodeType(args[0], "raw").string; - borderColor = colorFromSpec(model, borderSpec); - backgroundColor = colorFromSpec(model, backgroundSpec); - } else { - borderColor = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros); - backgroundColor = validateColor(assertNodeType(args[1], "raw").string, parser.gullet.macros); - } - const body = args[2]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - backgroundColor, - borderColor, - body - }; - }, - mathmlBuilder: mathmlBuilder$2 -}); - -defineFunction({ - type: "enclose", - names: ["\\fbox"], - props: { - numArgs: 1, - argTypes: ["hbox"], - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "enclose", - mode: parser.mode, - label: "\\fbox", - body: args[0] - }; - } -}); - -defineFunction({ - type: "enclose", - names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\angl", "\\phase", "\\longdiv"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - const body = args[0]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - body - }; - }, - mathmlBuilder: mathmlBuilder$2 -}); - -/** - * All registered environments. - * `environments.js` exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary via `environments.js`. - */ -const _environments = {}; - -function defineEnvironment({ type, names, props, handler, mathmlBuilder }) { - // Set default values of environments. - const data = { - type, - numArgs: props.numArgs || 0, - allowedInText: false, - numOptionalArgs: 0, - handler - }; - for (let i = 0; i < names.length; ++i) { - _environments[names[i]] = data; - } - if (mathmlBuilder) { - _mathmlGroupBuilders[type] = mathmlBuilder; - } -} - -// In TeX, there are actually three sets of dimensions, one for each of - -// Math style is not quite the same thing as script level. -const StyleLevel = { - DISPLAY: 0, - TEXT: 1, - SCRIPT: 2, - SCRIPTSCRIPT: 3 -}; - -// Helper functions -function getHLines(parser) { - // Return an array. The array length = number of hlines. - // Each element in the array tells if the line is dashed. - const hlineInfo = []; - parser.consumeSpaces(); - let nxt = parser.fetch().text; - while (nxt === "\\hline" || nxt === "\\hdashline") { - parser.consume(); - hlineInfo.push(nxt === "\\hdashline"); - parser.consumeSpaces(); - nxt = parser.fetch().text; - } - return hlineInfo; -} - -const validateAmsEnvironmentContext = context => { - const settings = context.parser.settings; - if (!settings.displayMode) { - throw new ParseError(`{${context.envName}} can be used only in` + - ` display mode.`); - } -}; - -const getTag = (group, style, rowNum) => { - let tag; - const tagContents = group.tags.shift(); - if (tagContents) { - // The author has written a \tag or a \notag in this row. - if (tagContents.body) { - tag = buildExpressionRow(tagContents.body, style); - tag.classes = ["tml-tag"]; - } else { - // \notag. Return an empty cell. - tag = new mathMLTree.MathNode("mtd", []); - tag.setAttribute("style", "padding: 0; min-width:0"); - return tag - } - } else if (group.colSeparationType === "multline" && - ((group.leqno && rowNum !== 0) || (!group.leqno && rowNum !== group.body.length - 1))) { - // A multiline that does not receive a tag. Return an empty cell. - tag = new mathMLTree.MathNode("mtd", []); - tag.setAttribute("style", "padding: 0; min-width:0"); - return tag - } else { - // AMS automatcally numbered equaton. - // Insert a class so the element can be populated by a post-processor. - tag = new mathMLTree.MathNode("mtext", [], ["tml-eqn"]); - } - if (!group.preventTagLap) { - tag = new mathMLTree.MathNode("mpadded", [tag]); - tag.setAttribute("style", "width:0;"); - tag.setAttribute("width", "0"); - if (!group.leqno) { tag.setAttribute("lspace", "-1width"); } - } - tag = new mathMLTree.MathNode("mtd", [tag]); - if (!group.preventTagLap) { tag.setAttribute("style", "padding: 0; min-width:0"); } - return tag -}; - -/** - * Parse the body of the environment, with rows delimited by \\ and - * columns delimited by &, and create a nested list in row-major order - * with one group per cell. If given an optional argument scriptLevel - * ("text", "display", etc.), then each cell is cast into that scriptLevel. - */ -function parseArray( - parser, - { - hskipBeforeAndAfter, // boolean - addJot, // boolean - cols, // [{ type: string , align: l|c|r|null }] - arraystretch, // number - colSeparationType, // "align" | "alignat" | "gather" | "small" | "CD" | "multline" - addEqnNum, // boolean - singleRow, // boolean - emptySingleRow, // boolean - maxNumCols, // number - leqno // boolean - }, - scriptLevel -) { - parser.gullet.beginGroup(); - if (!singleRow) { - // \cr is equivalent to \\ without the optional size argument (see below) - // TODO: provide helpful error when \cr is used outside array environment - parser.gullet.macros.set("\\cr", "\\\\\\relax"); - } - if (addEqnNum) { - parser.gullet.macros.set("\\tag", "\\env@tag{\\text{#1}}"); - parser.gullet.macros.set("\\notag", "\\env@notag"); - parser.gullet.macros.set("\\nonumber", "\\env@notag"); - } - - // Get current arraystretch if it's not set by the environment - if (arraystretch === undefined || Number.isNaN(arraystretch)) { - const stretch = parser.gullet.expandMacroAsText("\\arraystretch"); - if (stretch == null) { - // Default \arraystretch from lttab.dtx - arraystretch = 1; - } else { - arraystretch = parseFloat(stretch); - if (!arraystretch || arraystretch < 0) { - throw new ParseError(`Invalid \\arraystretch: ${stretch}`); - } - } - } - - // Start group for first cell - parser.gullet.beginGroup(); - - let row = []; - const body = [row]; - const rowGaps = []; - const tags = []; - let rowTag; - const hLinesBeforeRow = []; - - // Test for \hline at the top of the array. - hLinesBeforeRow.push(getHLines(parser)); - - // eslint-disable-next-line no-constant-condition - while (true) { - // Parse each cell in its own group (namespace) - let cell = parser.parseExpression(false, singleRow ? "\\end" : "\\\\"); - - if (addEqnNum && !rowTag) { - // Check if the author wrote a \tag{} inside this cell. - for (let i = 0; i < cell.length; i++) { - if (cell[i].type === "envTag" || cell[i].type === "noTag") { - // Get the contents of the \text{} nested inside the \env@Tag{} - rowTag = cell[i].type === "envTag" - ? cell.splice(i, 1)[0].body.body[0] - : { body: null }; - break - } - } - } - parser.gullet.endGroup(); - parser.gullet.beginGroup(); - - cell = { - type: "ordgroup", - mode: parser.mode, - body: cell - }; - row.push(cell); - const next = parser.fetch().text; - if (next === "&") { - if (maxNumCols && row.length === maxNumCols) { - if (singleRow || colSeparationType) { - // {equation} or {split} - throw new ParseError("Too many tab characters: &", parser.nextToken); - } else { - // {array} environment - parser.settings.reportNonstrict( - "textEnv", - "Too few columns " + "specified in the {array} column argument." - ); - } - } - parser.consume(); - } else if (next === "\\end") { - // Arrays terminate newlines with `\crcr` which consumes a `\cr` if - // the last line is empty. However, AMS environments keep the - // empty row if it's the only one. - // NOTE: Currently, `cell` is the last item added into `row`. - if (row.length === 1 && cell.body.length === 0 && (body.length > 1 || !emptySingleRow)) { - body.pop(); - } - if (hLinesBeforeRow.length < body.length + 1) { - hLinesBeforeRow.push([]); - } - break; - } else if (next === "\\\\") { - parser.consume(); - let size; - // \def\Let@{\let\\\math@cr} - // \def\math@cr{...\math@cr@} - // \def\math@cr@{\new@ifnextchar[\math@cr@@{\math@cr@@[\z@]}} - // \def\math@cr@@[#1]{...\math@cr@@@...} - // \def\math@cr@@@{\cr} - if (parser.gullet.future().text !== " ") { - size = parser.parseSizeGroup(true); - } - rowGaps.push(size ? size.value : null); - - tags.push(rowTag); - - // check for \hline(s) following the row separator - hLinesBeforeRow.push(getHLines(parser)); - - row = []; - rowTag = null; - body.push(row); - } else { - throw new ParseError("Expected & or \\\\ or \\cr or \\end", parser.nextToken); - } - } - - // End cell group - parser.gullet.endGroup(); - // End array group defining \cr - parser.gullet.endGroup(); - - tags.push(rowTag); - - return { - type: "array", - mode: parser.mode, - addJot, - arraystretch, - body, - cols, - rowGaps, - hskipBeforeAndAfter, - hLinesBeforeRow, - colSeparationType, - addEqnNum, - scriptLevel, - tags, - leqno, - preventTagLap: parser.settings.preventTagLap - }; -} - -// Decides on a scriptLevel for cells in an array according to whether the given -// environment name starts with the letter 'd'. -function dCellStyle(envName) { - return envName.substr(0, 1) === "d" ? "display" : "text" -} - -const alignMap = { - c: "center ", - l: "left ", - r: "right " -}; - -const mathmlBuilder$3 = function(group, style) { - const tbl = []; - const numRows = group.body.length; - let glue; - if (group.addEqnNum) { - glue = new mathMLTree.MathNode("mtd", [], []); - const glueStyle = "padding: 0;width: " + - (group.colSeparationType === "multline" ? "7.5%" : "50%"); - glue.setAttribute("style", glueStyle); - } - - for (let i = 0; i < numRows; i++) { - const rw = group.body[i]; - const row = []; - const cellStyle = group.scriptLevel === "text" - ? StyleLevel.TEXT - : group.scriptLevel === "script" - ? StyleLevel.SCRIPT - : StyleLevel.DISPLAY; - - for (let j = 0; j < rw.length; j++) { - const mtd = new mathMLTree.MathNode( - "mtd", - [buildGroup(rw[j], style.withLevel(cellStyle))] - ); - if (group.colSeparationType === "multline") { - const align = i === 0 ? "left" : i === numRows - 1 ? "right" : "center"; - mtd.setAttribute("columnalign", align); - } - row.push(mtd); - } - if (group.addEqnNum) { - row.unshift(glue); - row.push(glue); - const tag = getTag(group, style.withLevel(cellStyle), i); - if (group.leqno) { - row.unshift(tag); - } else { - row.push(tag); - } - } - // If group.addEqnNum, insert a breadcrumb to be found by temmlPostProcess(). - tbl.push(new mathMLTree.MathNode("mtr", row, group.addEqnNum ? ["tml-tageqn"] : [] )); - } - let table = new mathMLTree.MathNode("mtable", tbl); - if (group.scriptLevel === "display") { table.setAttribute("displaystyle", "true"); } - - // Set column alignment, row spacing, column spacing, and - // array lines by setting attributes on the table element. - - // Set the row spacing. In MathML, we specify a gap distance. - // We do not use rowGap[] because MathML automatically increases - // cell height with the height/depth of the element content. - - // LaTeX \arraystretch multiplies the row baseline-to-baseline distance. - // We simulate this by adding (arraystretch - 1)em to the gap. This - // does a reasonable job of adjusting arrays containing 1 em tall content. - - // The 0.16 and 0.09 values are found emprically. They produce an array - // similar to LaTeX and in which content does not interfere with \hines. - const gap = - group.arraystretch === 0 - ? 0 // {subarray} - : group.arraystretch === 0.5 - ? 0.1 // {smallmatrix} - : 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0); - table.setAttribute("rowspacing", utils.round(gap) + "em"); - - if (group.addEqnNum || group.colSeparationType === "multline") { - table.setAttribute("width", "100%"); - } - - // MathML table lines go only between cells. - // To place a line on an edge we'll use , if necessary. - let menclose = ""; - let align = ""; - - if (group.cols && group.cols.length > 0) { - // Find column alignment, column spacing, and vertical lines. - const cols = group.cols; - let columnLines = ""; - let prevTypeWasAlign = false; - let iStart = 0; - let iEnd = cols.length; - - if (cols[0].type === "separator") { - menclose += "left "; - iStart = 1; - } - if (cols[cols.length - 1].type === "separator") { - menclose += "right "; - iEnd -= 1; - } - - for (let i = iStart; i < iEnd; i++) { - if (cols[i].type === "align") { - align += alignMap[cols[i].align]; - - if (prevTypeWasAlign) { - columnLines += "none "; - } - prevTypeWasAlign = true; - } else if (cols[i].type === "separator") { - // MathML accepts only single lines between cells. - // So we read only the first of consecutive separators. - if (prevTypeWasAlign) { - columnLines += cols[i].separator === "|" ? "solid " : "dashed "; - prevTypeWasAlign = false; - } - } - } - if (group.addEqnNum) { - align = "left " + align + "right "; // allow for glue cells on each side - align = group.leqno ? "left " + align : align += "right"; // eqn num cell - } - - table.setAttribute("columnalign", align.trim()); - - if (/[sd]/.test(columnLines)) { - table.setAttribute("columnlines", columnLines.trim()); - } - } - - // Set column spacing. - switch (group.colSeparationType) { - case "gather": - case "gathered": - case "alignedat": - case "alignat": - case "alignat*": - table.setAttribute("columnspacing", "0em"); - break - case "small": - table.setAttribute("columnspacing", "0.2778em"); - break - case "CD": - table.setAttribute("columnspacing", "0.5em"); - break - case "align": - case "align*": { - const cols = group.cols || []; - let spacing = group.addEqnNum ? "0em " : ""; - for (let i = 1; i < cols.length; i++) { - spacing += i % 2 ? "0em " : "1em "; - } - if (group.addEqnNum) { spacing += "0em"; } - table.setAttribute("columnspacing", spacing.trim()); - break - } - default: - table.setAttribute("columnspacing", "1em"); - } - - // Address \hline and \hdashline - let rowLines = ""; - const hlines = group.hLinesBeforeRow; - - menclose += hlines[0].length > 0 ? "top " : ""; - menclose += hlines[hlines.length - 1].length > 0 ? "bottom " : ""; - - for (let i = 1; i < hlines.length - 1; i++) { - rowLines += - hlines[i].length === 0 - ? "none " - : // MathML accepts only a single line between rows. Read one element. - hlines[i][0] - ? "dashed " - : "solid "; - } - if (/[sd]/.test(rowLines)) { - table.setAttribute("rowlines", rowLines.trim()); - } - - if (menclose !== "") { - table = new mathMLTree.MathNode("menclose", [table]); - table.setAttribute("notation", menclose.trim()); - } - - if (!Number.isNaN(group.arraystretch) && group.arraystretch < 1) { - // A small array. Wrap in scriptstyle so row gap is not too large. - table = new mathMLTree.MathNode("mstyle", [table]); - table.setAttribute("scriptlevel", "1"); - } - - return table; -}; - -// Convenience function for align, align*, aligned, alignat, alignat*, alignedat. -const alignedHandler = function(context, args) { - if (context.envName.indexOf("ed") === -1) { - validateAmsEnvironmentContext(context); - } - const cols = []; - const res = parseArray( - context.parser, - { - cols, - addJot: true, - addEqnNum: context.envName === "align" || context.envName === "alignat", - emptySingleRow: true, - colSeparationType: context.envName, - maxNumCols: context.envName === "split" ? 2 : undefined, - leqno: context.parser.settings.leqno - }, - "display" - ); - - // Determining number of columns. - // 1. If the first argument is given, we use it as a number of columns, - // and makes sure that each row doesn't exceed that number. - // 2. Otherwise, just count number of columns = maximum number - // of cells in each row ("aligned" mode -- isAligned will be true). - // - // At the same time, prepend empty group {} at beginning of every second - // cell in each row (starting with second cell) so that operators become - // binary. This behavior is implemented in amsmath's \start@aligned. - let numMaths; - let numCols = 0; - if (args[0] && args[0].type === "ordgroup") { - let arg0 = ""; - for (let i = 0; i < args[0].body.length; i++) { - const textord = assertNodeType(args[0].body[i], "textord"); - arg0 += textord.text; - } - numMaths = Number(arg0); - numCols = numMaths * 2; - } - const isAligned = !numCols; - res.body.forEach(function(row) { - if (!isAligned) { - // Case 1 - const curMaths = row.length / 2; - if (numMaths < curMaths) { - throw new ParseError( - "Too many math in a row: " + `expected ${numMaths}, but got ${curMaths}`, - row[0] - ); - } - } else if (numCols < row.length) { - // Case 2 - numCols = row.length; - } - }); - - // Adjusting alignment. - // In aligned mode, we add one \qquad between columns; - // otherwise we add nothing. - for (let i = 0; i < numCols; ++i) { - let align = "r"; - if (i % 2 === 1) { - align = "l"; - } - cols[i] = { - type: "align", - align: align - }; - } - res.colSeparationType = isAligned ? "align" : "alignat"; - return res; -}; - -// Arrays are part of LaTeX, defined in lttab.dtx so its documentation -// is part of the source2e.pdf file of LaTeX2e source documentation. -// {darray} is an {array} environment where cells are set in \displaystyle, -// as defined in nccmath.sty. -defineEnvironment({ - type: "array", - names: ["array", "darray"], - props: { - numArgs: 1 - }, - handler(context, args) { - // Since no types are specified above, the two possibilities are - // - The argument is wrapped in {} or [], in which case Parser's - // parseGroup() returns an "ordgroup" wrapping some symbol node. - // - The argument is a bare symbol node. - const symNode = checkSymbolNodeType(args[0]); - const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; - const cols = colalign.map(function(nde) { - const node = assertSymbolNodeType(nde); - const ca = node.text; - if ("lcr".indexOf(ca) !== -1) { - return { - type: "align", - align: ca - }; - } else if (ca === "|") { - return { - type: "separator", - separator: "|" - }; - } else if (ca === ":") { - return { - type: "separator", - separator: ":" - }; - } - throw new ParseError("Unknown column alignment: " + ca, nde); - }); - const res = { - cols, - colSeparationType: "array", - hskipBeforeAndAfter: true, // \@preamble in lttab.dtx - maxNumCols: cols.length - }; - return parseArray(context.parser, res, dCellStyle(context.envName)); - }, - mathmlBuilder: mathmlBuilder$3 -}); - -// The matrix environments of amsmath builds on the array environment -// of LaTeX, which is discussed above. -// The mathtools package adds starred versions of the same environments. -// These have an optional argument to choose left|center|right justification. -defineEnvironment({ - type: "array", - names: [ - "matrix", - "pmatrix", - "bmatrix", - "Bmatrix", - "vmatrix", - "Vmatrix", - "matrix*", - "pmatrix*", - "bmatrix*", - "Bmatrix*", - "vmatrix*", - "Vmatrix*" - ], - props: { - numArgs: 0 - }, - handler(context) { - const delimiters = { - matrix: null, - pmatrix: ["(", ")"], - bmatrix: ["[", "]"], - Bmatrix: ["\\{", "\\}"], - vmatrix: ["|", "|"], - Vmatrix: ["\\Vert", "\\Vert"] - }[context.envName.replace("*", "")]; - // \hskip -\arraycolsep in amsmath - let colAlign = "c"; - const payload = { - hskipBeforeAndAfter: false, - colSeparationType: "matrix", - cols: [{ type: "align", align: colAlign }] - }; - if (context.envName.charAt(context.envName.length - 1) === "*") { - // It's one of the mathtools starred functions. - // Parse the optional alignment argument. - const parser = context.parser; - parser.consumeSpaces(); - if (parser.fetch().text === "[") { - parser.consume(); - parser.consumeSpaces(); - colAlign = parser.fetch().text; - if ("lcr".indexOf(colAlign) === -1) { - throw new ParseError("Expected l or c or r", parser.nextToken); - } - parser.consume(); - parser.consumeSpaces(); - parser.expect("]"); - parser.consume(); - payload.cols = [{ type: "align", align: colAlign }]; - } - } - const res = parseArray(context.parser, payload, "text"); - // Populate cols with the correct number of column alignment specs. - const numCols = Math.max(0, ...res.body.map((row) => row.length)); - res.cols = new Array(numCols).fill({ type: "align", align: colAlign }); - return delimiters - ? { - type: "leftright", - mode: context.mode, - body: [res], - left: delimiters[0], - right: delimiters[1], - rightColor: undefined // \right uninfluenced by \color in array - } - : res; - }, - mathmlBuilder: mathmlBuilder$3 -}); - -defineEnvironment({ - type: "array", - names: ["smallmatrix"], - props: { - numArgs: 0 - }, - handler(context) { - const payload = { arraystretch: 0.5 }; - const res = parseArray(context.parser, payload, "script"); - res.colSeparationType = "small"; - return res; - }, - mathmlBuilder: mathmlBuilder$3 -}); - -defineEnvironment({ - type: "array", - names: ["subarray"], - props: { - numArgs: 1 - }, - handler(context, args) { - // Parsing of {subarray} is similar to {array} - const symNode = checkSymbolNodeType(args[0]); - const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; - const cols = colalign.map(function(nde) { - const node = assertSymbolNodeType(nde); - const ca = node.text; - // {subarray} only recognizes "l" & "c" - if ("lc".indexOf(ca) !== -1) { - return { - type: "align", - align: ca - }; - } - throw new ParseError("Unknown column alignment: " + ca, nde); - }); - if (cols.length > 1) { - throw new ParseError("{subarray} can contain only one column"); - } - let res = { - cols, - hskipBeforeAndAfter: false, - colSeparationType: "array", - arraystretch: 0 - }; - res = parseArray(context.parser, res, "script"); - if (res.body.length > 0 && res.body[0].length > 1) { - throw new ParseError("{subarray} can contain only one column"); - } - return res; - }, - mathmlBuilder: mathmlBuilder$3 -}); - -// A cases environment (in amsmath.sty) is almost equivalent to -// \def -// \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right. -// {dcases} is a {cases} environment where cells are set in \displaystyle, -// as defined in mathtools.sty. -// {rcases} is another mathtools environment. It's brace is on the right side. -defineEnvironment({ - type: "array", - names: ["cases", "dcases", "rcases", "drcases"], - props: { - numArgs: 0 - }, - handler(context) { - const payload = { - cols: [ - { - type: "align", - align: "l" - }, - { - type: "align", - align: "l" - } - ], - colSeparationType: "cases" - }; - const res = parseArray(context.parser, payload, dCellStyle(context.envName)); - return { - type: "leftright", - mode: context.mode, - body: [res], - left: context.envName.indexOf("r") > -1 ? "." : "\\{", - right: context.envName.indexOf("r") > -1 ? "\\}" : ".", - rightColor: undefined - }; - }, - mathmlBuilder: mathmlBuilder$3 -}); - -// In the align environment, one uses ampersands, &, to specify number of -// columns in each row, and to locate spacing between each column. -// align gets automatic numbering. align* and aligned do not. -// The alignedat environment can be used in math mode. -// Note that we assume \nomallineskiplimit to be zero, -// so that \strut@ is the same as \strut. -defineEnvironment({ - type: "array", - names: ["align", "align*", "aligned", "split"], - props: { - numArgs: 0 - }, - handler: alignedHandler, - mathmlBuilder: mathmlBuilder$3 -}); - -// A gathered environment is like an array environment with one centered -// column, but where rows are considered lines so get \jot line spacing -// and contents are set in \displaystyle. -defineEnvironment({ - type: "array", - names: ["gathered", "gather", "gather*"], - props: { - numArgs: 0 - }, - handler(context) { - if (utils.contains(["gather", "gather*"], context.envName)) { - validateAmsEnvironmentContext(context); - } - const res = { - cols: [ - { - type: "align", - align: "c" - } - ], - addJot: true, - colSeparationType: "gather", - addEqnNum: context.envName === "gather", - emptySingleRow: true, - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder: mathmlBuilder$3 -}); - -// alignat environment is like an align environment, but one must explicitly -// specify maximum number of columns in each row, and can adjust spacing between -// each columns. -defineEnvironment({ - type: "array", - names: ["alignat", "alignat*", "alignedat"], - props: { - numArgs: 1 - }, - handler: alignedHandler, - mathmlBuilder: mathmlBuilder$3 -}); - -defineEnvironment({ - type: "array", - names: ["equation", "equation*"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - const res = { - addEqnNum: context.envName === "equation", - emptySingleRow: true, - singleRow: true, - maxNumCols: 1, - colSeparationType: "gather", - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder: mathmlBuilder$3 -}); - -defineEnvironment({ - type: "array", - names: ["multline", "multline*"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - const res = { - addEqnNum: context.envName === "multline", - maxNumCols: 1, - colSeparationType: "multline", - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder: mathmlBuilder$3 -}); - -defineEnvironment({ - type: "array", - names: ["CD"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - return parseCD(context.parser); - }, - mathmlBuilder: mathmlBuilder$3 -}); - -// Catch \hline outside array environment -defineFunction({ - type: "text", // Doesn't matter what this is. - names: ["\\hline", "\\hdashline"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: true - }, - handler(context, args) { - throw new ParseError(`${context.funcName} valid only within array environment`); - } -}); - -const environments = _environments; - -// Environment delimiters. HTML/MathML rendering is defined in the corresponding -// defineEnvironment definitions. -defineFunction({ - type: "environment", - names: ["\\begin", "\\end"], - props: { - numArgs: 1, - argTypes: ["text"] - }, - handler({ parser, funcName }, args) { - const nameGroup = args[0]; - if (nameGroup.type !== "ordgroup") { - throw new ParseError("Invalid environment name", nameGroup); - } - let envName = ""; - for (let i = 0; i < nameGroup.body.length; ++i) { - envName += assertNodeType(nameGroup.body[i], "textord").text; - } - - if (funcName === "\\begin") { - // begin...end is similar to left...right - if (!Object.prototype.hasOwnProperty.call(environments, envName )) { - throw new ParseError("No such environment: " + envName, nameGroup); - } - // Build the environment object. Arguments and other information will - // be made available to the begin and end methods using properties. - const env = environments[envName]; - const { args, optArgs } = parser.parseArguments("\\begin{" + envName + "}", env); - const context = { - mode: parser.mode, - envName, - parser - }; - const result = env.handler(context, args, optArgs); - parser.expect("\\end", false); - const endNameToken = parser.nextToken; - const end = assertNodeType(parser.parseFunction(), "environment"); - if (end.name !== envName) { - throw new ParseError( - `Mismatch: \\begin{${envName}} matched by \\end{${end.name}}`, - endNameToken - ); - } - return result; - } - - return { - type: "environment", - mode: parser.mode, - name: envName, - nameGroup - }; - } -}); - -defineFunction({ - type: "envTag", - names: ["\\env@tag"], - props: { - numArgs: 1, - argTypes: ["math"] - }, - handler({ parser }, args) { - return { - type: "envTag", - mode: parser.mode, - body: args[0] - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow"); - } -}); - -defineFunction({ - type: "noTag", - names: ["\\env@notag"], - props: { - numArgs: 0 - }, - handler({ parser }) { - return { - type: "noTag", - mode: parser.mode - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow"); - } -}); - -const mathmlBuilder$4 = (group, style) => { - const font = group.font; - const newStyle = style.withFont(font); - const mathGroup = buildGroup(group.body, newStyle); - - if (mathGroup.children.length === 0) { return mathGroup } // empty group, e.g., \mathrm{} - if (mathGroup.type === "mo" && font === "boldsymbol") { - mathGroup.style.fontWeight = "bold"; - return mathGroup - } - // Check if it is possible to consolidate elements into a single element. - let canConsolidate = mathGroup.children[0].type === "mo"; - for (let i = 1; i < mathGroup.children.length; i++) { - if (mathGroup.children[i].type === "mo" && font === "boldsymbol") { - mathGroup.children[i].style.fontWeight = "bold"; - } - if (mathGroup.children[i].type !== "mi") { canConsolidate = false; } - const localVariant = mathGroup.children[i].attributes && - mathGroup.children[i].attributes.mathvariant || ""; - if (localVariant !== "normal") { canConsolidate = false; } - } - if (!canConsolidate) { return mathGroup } - // Consolidate the elements. - const mi = mathGroup.children[0]; - for (let i = 1; i < mathGroup.children.length; i++) { - mi.children.push(mathGroup.children[i].children[0]); - } - if (mathGroup.attributes.mathcolor) { mi.attributes.mathcolor = mathGroup.attributes.mathcolor; } - if (mi.attributes.mathvariant && mi.attributes.mathvariant === "normal") { - // Workaround for a Firefox bug that renders spurious space around - // a - // Ref: https://bugs.webkit.org/show_bug.cgi?id=129097 - // We insert a text node that contains a zero-width space and wrap in an mrow. - // TODO: Get rid of this workaround when the Firefox bug is fixed. - const bogus = new mathMLTree.MathNode("mtext", new mathMLTree.TextNode("\u200b")); - return new mathMLTree.MathNode("mrow", [bogus, mi]) - } - return mi -}; - -const fontAliases = { - "\\Bbb": "\\mathbb", - "\\bold": "\\mathbf", - "\\frak": "\\mathfrak", - "\\bm": "\\boldsymbol" -}; - -defineFunction({ - type: "font", - names: [ - // styles - "\\mathrm", - "\\mathit", - "\\mathbf", - "\\mathnormal", - "\\up@greek", - "\\pmb", - "\\boldsymbol", - - // families - "\\mathbb", - "\\mathcal", - "\\mathfrak", - "\\mathscr", - "\\mathsf", - "\\mathtt", - "\\oldstylenums", - - // aliases - "\\Bbb", - "\\bm", - "\\bold", - "\\frak" - ], - props: { - numArgs: 1, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const body = normalizeArgument(args[0]); - let func = funcName; - if (func in fontAliases) { - func = fontAliases[func]; - } - return { - type: "font", - mode: parser.mode, - font: func.slice(1), - body - }; - }, - mathmlBuilder: mathmlBuilder$4 -}); - -// Old font changing functions -defineFunction({ - type: "font", - names: ["\\rm", "\\sf", "\\tt", "\\bf", "\\it", "\\cal"], - props: { - numArgs: 0, - allowedInText: true - }, - handler: ({ parser, funcName, breakOnTokenText }, args) => { - const { mode } = parser; - const body = parser.parseExpression(true, breakOnTokenText); - const fontStyle = `math${funcName.slice(1)}`; - - return { - type: "font", - mode: mode, - font: fontStyle, - body: { - type: "ordgroup", - mode: parser.mode, - body - } - }; - }, - mathmlBuilder: mathmlBuilder$4 -}); - -const stylArray = ["display", "text", "script", "scriptscript"]; -const scriptLevel = { auto: -1, display: 0, text: 0, script: 1, scriptscript: 2 }; - -const mathmlBuilder$5 = (group, style) => { - // Track the scriptLevel of the numerator and denominator. - // We may need that info for \mathchoice or for adjusting em dimensions. - const childOptions = group.scriptLevel === "auto" - ? style.incrementLevel() - : group.scriptLevel === "display" - ? style.withLevel(StyleLevel.TEXT) - : group.scriptLevel === "text" - ? style.withLevel(StyleLevel.SCRIPT) - : style.withLevel(StyleLevel.SCRIPTSCRIPT); - - let node = new mathMLTree.MathNode("mfrac", [ - buildGroup(group.numer, childOptions), - buildGroup(group.denom, childOptions) - ]); - - if (!group.hasBarLine) { - node.setAttribute("linethickness", "0px"); - } else if (group.barSize) { - const ruleWidth = calculateSize(group.barSize, style); - node.setAttribute("linethickness", ruleWidth.number + ruleWidth.unit); - } - - if (group.leftDelim != null || group.rightDelim != null) { - const withDelims = []; - - if (group.leftDelim != null) { - const leftOp = new mathMLTree.MathNode("mo", [ - new mathMLTree.TextNode(group.leftDelim.replace("\\", "")) - ]); - leftOp.setAttribute("fence", "true"); - withDelims.push(leftOp); - } - - withDelims.push(node); - - if (group.rightDelim != null) { - const rightOp = new mathMLTree.MathNode("mo", [ - new mathMLTree.TextNode(group.rightDelim.replace("\\", "")) - ]); - rightOp.setAttribute("fence", "true"); - withDelims.push(rightOp); - } - - node = makeRow(withDelims); - } - - if (group.scriptLevel !== "auto") { - node = new mathMLTree.MathNode("mstyle", [node]); - node.setAttribute("displaystyle", String(group.scriptLevel === "display")); - node.setAttribute("scriptlevel", scriptLevel[group.scriptLevel]); - } - - return node; -}; - -defineFunction({ - type: "genfrac", - names: [ - "\\dfrac", - "\\frac", - "\\tfrac", - "\\dbinom", - "\\binom", - "\\tbinom", - "\\\\atopfrac", // can’t be entered directly - "\\\\bracefrac", - "\\\\brackfrac" // ditto - ], - props: { - numArgs: 2, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const denom = args[1]; - let hasBarLine = false; - let leftDelim = null; - let rightDelim = null; - let scriptLevel = "auto"; - - switch (funcName) { - case "\\dfrac": - case "\\frac": - case "\\tfrac": - hasBarLine = true; - break; - case "\\\\atopfrac": - hasBarLine = false; - break; - case "\\dbinom": - case "\\binom": - case "\\tbinom": - leftDelim = "("; - rightDelim = ")"; - break; - case "\\\\bracefrac": - leftDelim = "\\{"; - rightDelim = "\\}"; - break; - case "\\\\brackfrac": - leftDelim = "["; - rightDelim = "]"; - break; - default: - throw new Error("Unrecognized genfrac command"); - } - - switch (funcName) { - case "\\dfrac": - case "\\dbinom": - scriptLevel = "display"; - break; - case "\\tfrac": - case "\\tbinom": - scriptLevel = "text"; - break; - } - - return { - type: "genfrac", - mode: parser.mode, - continued: false, - numer, - denom, - hasBarLine, - leftDelim, - rightDelim, - scriptLevel, - barSize: null - }; - }, - mathmlBuilder: mathmlBuilder$5 -}); - -defineFunction({ - type: "genfrac", - names: ["\\cfrac"], - props: { - numArgs: 2 - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const denom = args[1]; - - return { - type: "genfrac", - mode: parser.mode, - continued: true, - numer, - denom, - hasBarLine: true, - leftDelim: null, - rightDelim: null, - scriptLevel: "display", - barSize: null - }; - } -}); - -// Infix generalized fractions -- these are not rendered directly, but replaced -// immediately by one of the variants above. -defineFunction({ - type: "infix", - names: ["\\over", "\\choose", "\\atop", "\\brace", "\\brack"], - props: { - numArgs: 0, - infix: true - }, - handler({ parser, funcName, token }) { - let replaceWith; - switch (funcName) { - case "\\over": - replaceWith = "\\frac"; - break; - case "\\choose": - replaceWith = "\\binom"; - break; - case "\\atop": - replaceWith = "\\\\atopfrac"; - break; - case "\\brace": - replaceWith = "\\\\bracefrac"; - break; - case "\\brack": - replaceWith = "\\\\brackfrac"; - break; - default: - throw new Error("Unrecognized infix genfrac command"); - } - return { - type: "infix", - mode: parser.mode, - replaceWith, - token - }; - } -}); - -const delimFromValue = function(delimString) { - let delim = null; - if (delimString.length > 0) { - delim = delimString; - delim = delim === "." ? null : delim; - } - return delim; -}; - -defineFunction({ - type: "genfrac", - names: ["\\genfrac"], - props: { - numArgs: 6, - allowedInArgument: true, - argTypes: ["math", "math", "size", "text", "math", "math"] - }, - handler({ parser }, args) { - const numer = args[4]; - const denom = args[5]; - - // Look into the parse nodes to get the desired delimiters. - const leftNode = normalizeArgument(args[0]); - const leftDelim = leftNode.type === "atom" && leftNode.family === "open" - ? delimFromValue(leftNode.text) - : null; - const rightNode = normalizeArgument(args[1]); - const rightDelim = - rightNode.type === "atom" && rightNode.family === "close" - ? delimFromValue(rightNode.text) - : null; - - const barNode = assertNodeType(args[2], "size"); - let hasBarLine; - let barSize = null; - if (barNode.isBlank) { - // \genfrac acts differently than \above. - // \genfrac treats an empty size group as a signal to use a - // standard bar size. \above would see size = 0 and omit the bar. - hasBarLine = true; - } else { - barSize = barNode.value; - hasBarLine = barSize.number > 0; - } - - // Find out if we want displaystyle, textstyle, etc. - let scriptLevel = "auto"; - let styl = args[3]; - if (styl.type === "ordgroup") { - if (styl.body.length > 0) { - const textOrd = assertNodeType(styl.body[0], "textord"); - scriptLevel = stylArray[Number(textOrd.text)]; - } - } else { - styl = assertNodeType(styl, "textord"); - scriptLevel = stylArray[Number(styl.text)]; - } - - return { - type: "genfrac", - mode: parser.mode, - numer, - denom, - continued: false, - hasBarLine, - barSize, - leftDelim, - rightDelim, - scriptLevel - }; - }, - mathmlBuilder: mathmlBuilder$5 -}); - -// \above is an infix fraction that also defines a fraction bar size. -defineFunction({ - type: "infix", - names: ["\\above"], - props: { - numArgs: 1, - argTypes: ["size"], - infix: true - }, - handler({ parser, funcName, token }, args) { - return { - type: "infix", - mode: parser.mode, - replaceWith: "\\\\abovefrac", - barSize: assertNodeType(args[0], "size").value, - token - }; - } -}); - -defineFunction({ - type: "genfrac", - names: ["\\\\abovefrac"], - props: { - numArgs: 3, - argTypes: ["math", "size", "math"] - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const barSize = assert(assertNodeType(args[1], "infix").barSize); - const denom = args[2]; - - const hasBarLine = barSize.number > 0; - return { - type: "genfrac", - mode: parser.mode, - numer, - denom, - continued: false, - hasBarLine, - barSize, - leftDelim: null, - rightDelim: null, - scriptLevel: "auto" - }; - }, - - mathmlBuilder: mathmlBuilder$5 -}); - -const mathmlBuilder$6 = (group, style) => { - const accentNode = stretchy.mathMLnode(group.label); - return new mathMLTree.MathNode(group.isOver ? "mover" : "munder", [ - buildGroup(group.base, style), - accentNode - ]); -}; - -// Horizontal stretchy braces -defineFunction({ - type: "horizBrace", - names: ["\\overbrace", "\\underbrace"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - return { - type: "horizBrace", - mode: parser.mode, - label: funcName, - isOver: /^\\over/.test(funcName), - base: args[0] - }; - }, - mathmlBuilder: mathmlBuilder$6 -}); - -defineFunction({ - type: "href", - names: ["\\href"], - props: { - numArgs: 2, - argTypes: ["url", "original"], - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[1]; - const href = assertNodeType(args[0], "url").url; - - if ( - !parser.settings.isTrusted({ - command: "\\href", - url: href - }) - ) { - return parser.formatUnsupportedCmd("\\href"); - } - - return { - type: "href", - mode: parser.mode, - href, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - let math = buildExpressionRow(group.body, style); - if (!(math instanceof MathNode)) { - math = new MathNode("mrow", [math]); - } - math.setAttribute("href", group.href); - return math; - } -}); - -defineFunction({ - type: "href", - names: ["\\url"], - props: { - numArgs: 1, - argTypes: ["url"], - allowedInText: true - }, - handler: ({ parser }, args) => { - const href = assertNodeType(args[0], "url").url; - - if ( - !parser.settings.isTrusted({ - command: "\\url", - url: href - }) - ) { - return parser.formatUnsupportedCmd("\\url"); - } - - const chars = []; - for (let i = 0; i < href.length; i++) { - let c = href[i]; - if (c === "~") { - c = "\\textasciitilde"; - } - chars.push({ - type: "textord", - mode: "text", - text: c - }); - } - const body = { - type: "text", - mode: parser.mode, - font: "\\texttt", - body: chars - }; - return { - type: "href", - mode: parser.mode, - href, - body: ordargument(body) - }; - } -}); - -defineFunction({ - type: "html", - names: ["\\class", "\\id", "\\style", "\\data"], - props: { - numArgs: 2, - argTypes: ["raw", "original"], - allowedInText: true - }, - handler: ({ parser, funcName, token }, args) => { - const value = assertNodeType(args[0], "raw").string; - const body = args[1]; - - if (parser.settings.strict) { - parser.settings.reportNonstrict( - "htmlExtension", "HTML extension is disabled on strict mode" - ); - } - - let trustContext; - const attributes = {}; - - switch (funcName) { - case "\\class": - attributes.class = value; - trustContext = { - command: "\\class", - class: value - }; - break; - case "\\id": - attributes.id = value; - trustContext = { - command: "\\id", - id: value - }; - break; - case "\\style": - attributes.style = value; - trustContext = { - command: "\\style", - style: value - }; - break; - case "\\data": { - const data = value.split(","); - for (let i = 0; i < data.length; i++) { - const keyVal = data[i].split("="); - if (keyVal.length !== 2) { - throw new ParseError("Error parsing key-value for \\data"); - } - attributes["data-" + keyVal[0].trim()] = keyVal[1].trim(); - } - - trustContext = { - command: "\\data", - attributes - }; - break; - } - default: - throw new Error("Unrecognized html command"); - } - - if (!parser.settings.isTrusted(trustContext)) { - return parser.formatUnsupportedCmd(funcName); - } - return { - type: "html", - mode: parser.mode, - attributes, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - const element = buildExpressionRow(group.body, style); - - const classes = []; - if (group.attributes.class) { - classes.push(...group.attributes.class.trim().split(/\s+/)); - } - element.classes = classes; - - for (const attr in group.attributes) { - if (attr !== "class" && Object.prototype.hasOwnProperty.call(group.attributes, attr)) { - element.setAttribute(attr, group.attributes[attr]); - } - } - - return element; - } -}); - -const sizeData = function(str) { - if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(str)) { - // str is a number with no unit specified. - // default unit is bp, per graphix package. - return { number: +str, unit: "bp" } - } else { - const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(str); - if (!match) { - throw new ParseError("Invalid size: '" + str + "' in \\includegraphics"); - } - const data = { - number: +(match[1] + match[2]), // sign + magnitude, cast to number - unit: match[3] - }; - if (!validUnit(data)) { - throw new ParseError("Invalid unit: '" + data.unit + "' in \\includegraphics."); - } - return data - } -}; - -defineFunction({ - type: "includegraphics", - names: ["\\includegraphics"], - props: { - numArgs: 1, - numOptionalArgs: 1, - argTypes: ["raw", "url"], - allowedInText: false - }, - handler: ({ parser }, args, optArgs) => { - let width = { number: 0, unit: "em" }; - let height = { number: 0.9, unit: "em" }; // sorta character sized. - let totalheight = { number: 0, unit: "em" }; - let alt = ""; - - if (optArgs[0]) { - const attributeStr = assertNodeType(optArgs[0], "raw").string; - - // Parser.js does not parse key/value pairs. We get a string. - const attributes = attributeStr.split(","); - for (let i = 0; i < attributes.length; i++) { - const keyVal = attributes[i].split("="); - if (keyVal.length === 2) { - const str = keyVal[1].trim(); - switch (keyVal[0].trim()) { - case "alt": - alt = str; - break - case "width": - width = sizeData(str); - break - case "height": - height = sizeData(str); - break - case "totalheight": - totalheight = sizeData(str); - break - default: - throw new ParseError("Invalid key: '" + keyVal[0] + "' in \\includegraphics.") - } - } - } - } - - const src = assertNodeType(args[0], "url").url; - - if (alt === "") { - // No alt given. Use the file name. Strip away the path. - alt = src; - alt = alt.replace(/^.*[\\/]/, ""); - alt = alt.substring(0, alt.lastIndexOf(".")); - } - - if ( - !parser.settings.isTrusted({ - command: "\\includegraphics", - url: src - }) - ) { - return parser.formatUnsupportedCmd("\\includegraphics") - } - - return { - type: "includegraphics", - mode: parser.mode, - alt: alt, - width: width, - height: height, - totalheight: totalheight, - src: src - } - }, - mathmlBuilder: (group, style) => { - const height = calculateSize(group.height, style); - const depth = { number: 0, unit: "em" }; - - if (group.totalheight.number > 0) { - if (group.totalheight.unit === height.unit && - group.totalheight.number > height.number) { - depth.number = group.totalheight.number - height.number; - depth.unit = height.unit; - } - } - - let width = 0; - if (group.width.number > 0) { - width = calculateSize(group.width, style); - } - - const graphicStyle = { height: height.number + depth.number + "em" }; - if (width.number > 0) { - graphicStyle.width = width.number + width.unit; - } - if (depth.number > 0) { - graphicStyle.verticalAlign = -depth.number + depth.unit; - } - - const node = new Img(group.src, group.alt, graphicStyle); - node.height = height; - node.depth = depth; - return new mathMLTree.MathNode("mtext", [node]) - } -}); - -// Horizontal spacing commands - -// TODO: \hskip and \mskip should support plus and minus in lengths - -defineFunction({ - type: "kern", - names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"], - props: { - numArgs: 1, - argTypes: ["size"], - primitive: true, - allowedInText: true - }, - handler({ parser, funcName }, args) { - const size = assertNodeType(args[0], "size"); - if (parser.settings.strict) { - const mathFunction = funcName[1] === "m"; // \mkern, \mskip - const muUnit = size.value.unit === "mu"; - if (mathFunction) { - if (!muUnit) { - parser.settings.reportNonstrict( - "mathVsTextUnits", - `LaTeX's ${funcName} supports only mu units, ` + `not ${size.value.unit} units` - ); - } - if (parser.mode !== "math") { - parser.settings.reportNonstrict( - "mathVsTextUnits", - `LaTeX's ${funcName} works only in math mode` - ); - } - } else { - // !mathFunction - if (muUnit) { - parser.settings.reportNonstrict( - "mathVsTextUnits", - `LaTeX's ${funcName} doesn't support mu units` - ); - } - } - } - return { - type: "kern", - mode: parser.mode, - dimension: size.value - }; - }, - mathmlBuilder(group, style) { - const dimension = calculateSize(group.dimension, style); - const ch = dimension.unit === "em" ? spaceCharacter(dimension.number) : ""; - if (group.mode === "text" && ch.length > 0) { - const character = new mathMLTree.TextNode(ch); - return new mathMLTree.MathNode("mtext", [character]); - } else { - const node = new mathMLTree.MathNode("mspace"); - node.setAttribute("width", dimension.number + dimension.unit); - return node; - } - } -}); - -const spaceCharacter = function(width) { - if (width >= 0.05555 && width <= 0.05556) { - return "\u200a"; //   - } else if (width >= 0.1666 && width <= 0.1667) { - return "\u2009"; //   - } else if (width >= 0.2222 && width <= 0.2223) { - return "\u2005"; //   - } else if (width >= 0.2777 && width <= 0.2778) { - return "\u2005\u200a"; //    - } else { - return ""; - } -}; - -// Limit valid characters to a small set, for safety. -const invalidIdRegEx = /[^A-Za-z_0-9-]/g; - -defineFunction({ - type: "label", - names: ["\\label"], - props: { - numArgs: 1, - argTypes: ["raw"] - }, - handler({ parser }, args) { - return { - type: "label", - mode: parser.mode, - string: args[0].string.replace(invalidIdRegEx, "") - }; - }, - mathmlBuilder(group, style) { - // Return a no-width, no-ink element with an HTML id. - const node = new mathMLTree.MathNode("mrow", [], ["tml-label"]); - if (group.string.length > 0) { - node.setAttribute("id", group.string); - } - return node - } -}); - -// Horizontal overlap functions - -const textModeLap = ["\\clap", "\\llap", "\\rlap"]; - -defineFunction({ - type: "lap", - names: ["\\mathllap", "\\mathrlap", "\\mathclap", "\\clap", "\\llap", "\\rlap"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser, funcName }, args) => { - if (textModeLap.includes(funcName)) { - if (parser.settings.strict && parser.mode !== "text") { - throw new ParseError(`{${funcName}} can be used only in text mode.`) - } - funcName = funcName.slice(1); - } else { - funcName = funcName.slice(5); - } - const body = args[0]; - return { - type: "lap", - mode: parser.mode, - alignment: funcName, - body - } - }, - mathmlBuilder: (group, style) => { - // mathllap, mathrlap, mathclap - const node = new mathMLTree.MathNode("mpadded", [buildGroup(group.body, style)]); - - if (group.alignment === "rlap") { - if (group.body.body.length > 0 && group.body.body[0].type === "genfrac") { - // In Firefox, a squashes the 3/18em padding of a child \frac. Put it back. - node.setAttribute("lspace", "0.16667em"); - } - } else { - const offset = group.alignment === "llap" ? "-1" : "-0.5"; - node.setAttribute("lspace", offset + "width"); - } - node.setAttribute("width", "0px"); - return node - } -}); - -// Switching from text mode back to math mode -defineFunction({ - type: "ordgroup", - names: ["\\(", "$"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: false - }, - handler({ funcName, parser }, args) { - const outerMode = parser.mode; - parser.switchMode("math"); - const close = funcName === "\\(" ? "\\)" : "$"; - const body = parser.parseExpression(false, close); - parser.expect(close); - parser.switchMode(outerMode); - return { - type: "ordgroup", - mode: parser.mode, - body - }; - } -}); - -// Check for extra closing math delimiters -defineFunction({ - type: "text", // Doesn't matter what this is. - names: ["\\)", "\\]"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: false - }, - handler(context, args) { - throw new ParseError(`Mismatched ${context.funcName}`); - } -}); - -const chooseStyle = (group, style) => { - switch (style.level) { - case StyleLevel.DISPLAY: // 0 - return group.display; - case StyleLevel.TEXT: // 1 - return group.text; - case StyleLevel.SCRIPT: // 2 - return group.script; - case StyleLevel.SCRIPTSCRIPT: // 3 - return group.scriptscript; - default: - return group.text; - } -}; - -defineFunction({ - type: "mathchoice", - names: ["\\mathchoice"], - props: { - numArgs: 4, - primitive: true - }, - handler: ({ parser }, args) => { - return { - type: "mathchoice", - mode: parser.mode, - display: ordargument(args[0]), - text: ordargument(args[1]), - script: ordargument(args[2]), - scriptscript: ordargument(args[3]) - }; - }, - mathmlBuilder: (group, style) => { - const body = chooseStyle(group, style); - return buildExpressionRow(body, style); - } -}); - -const textAtomTypes = ["text", "textord", "mathord", "atom"]; - -function mathmlBuilder$7(group, style) { - let node; - const inner = buildExpression(group.body, style); - - if (group.mclass === "minner") { - return mathMLTree.newDocumentFragment(inner); - } else if (group.mclass === "mord") { - if (group.isCharacterBox || inner[0].type === "mathord") { - node = inner[0]; - node.type = "mi"; - } else { - node = new mathMLTree.MathNode("mi", inner); - } - } else { - if (group.mustPromote) { - node = inner[0]; - node.type = "mo"; - if (group.isCharacterBox && group.body[0].text && /[A-Za-z]/.test(group.body[0].text)) { - node.setAttribute("mathvariant", "italic"); - } - } else { - node = new mathMLTree.MathNode("mo", inner); - } - - // Set spacing based on what is the most likely adjacent atom type. - // See TeXbook p170. - const doSpacing = style.level < 2; // Operator spacing is zero inside a (sub|super)script. - if (group.mclass === "mbin") { - // medium space - node.attributes.lspace = (doSpacing ? "0.2222em" : "0"); - node.attributes.rspace = (doSpacing ? "0.2222em" : "0"); - } else if (group.mclass === "mrel") { - // thickspace - node.attributes.lspace = (doSpacing ? "0.2778em" : "0"); - node.attributes.rspace = (doSpacing ? "0.2778em" : "0"); - } else if (group.mclass === "mpunct") { - node.attributes.lspace = "0em"; - node.attributes.rspace = (doSpacing ? "0.1667em" : "0"); - } else if (group.mclass === "mopen" || group.mclass === "mclose") { - node.attributes.lspace = "0em"; - node.attributes.rspace = "0em"; - } - if (!(group.mclass === "mopen" || group.mclass === "mclose")) { - delete node.attributes.stretchy; - delete node.attributes.form; - } - } - return node; -} - -// Math class commands except \mathop -defineFunction({ - type: "mclass", - names: [ - "\\mathord", - "\\mathbin", - "\\mathrel", - "\\mathopen", - "\\mathclose", - "\\mathpunct", - "\\mathinner" - ], - props: { - numArgs: 1, - primitive: true - }, - handler({ parser, funcName }, args) { - const body = args[0]; - const isCharacterBox = utils.isCharacterBox(body); - // We should not wrap a around a or . That would be invalid MathML. - // In that case, we instead promote the text contents of the body to the parent. - let mustPromote = true; - const mord = { type: "mathord", text: "", mode: parser.mode }; - const arr = (body.body) ? body.body : [body]; - for (const arg of arr) { - if (textAtomTypes.includes(arg.type)) { - if (arg.text) { - mord.text += arg.text; - } else if (arg.body) { - arg.body.map(e => { mord.text += e.text; }); - } - } else { - mustPromote = false; - break - } - } - return { - type: "mclass", - mode: parser.mode, - mclass: "m" + funcName.substr(5), - body: ordargument(mustPromote ? mord : body), - isCharacterBox, - mustPromote - }; - }, - mathmlBuilder: mathmlBuilder$7 -}); - -const binrelClass = (arg) => { - // \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument. - // (by rendering separately and with {}s before and after, and measuring - // the change in spacing). We'll do roughly the same by detecting the - // atom type directly. - const atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg; - if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) { - return "m" + atom.family; - } else { - return "mord"; - } -}; - -// \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord. -// This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX. -defineFunction({ - type: "mclass", - names: ["\\@binrel"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "mclass", - mode: parser.mode, - mclass: binrelClass(args[0]), - body: ordargument(args[1]), - isCharacterBox: utils.isCharacterBox(args[1]) - }; - } -}); - -// Build a relation or stacked op by placing one symbol on top of another -defineFunction({ - type: "mclass", - names: ["\\stackrel", "\\overset", "\\underset"], - props: { - numArgs: 2 - }, - handler({ parser, funcName }, args) { - const baseArg = args[1]; - const shiftedArg = args[0]; - - const baseOp = { - type: "op", - mode: baseArg.mode, - limits: true, - alwaysHandleSupSub: true, - parentIsSupSub: false, - symbol: false, - stack: true, - suppressBaseShift: funcName !== "\\stackrel", - body: ordargument(baseArg) - }; - - return { - type: "supsub", - mode: shiftedArg.mode, - base: baseOp, - sup: funcName === "\\underset" ? null : shiftedArg, - sub: funcName === "\\underset" ? shiftedArg : null - }; - }, - mathmlBuilder: mathmlBuilder$7 -}); - -// Helper function -const buildGroup$1 = (el, style, noneNode) => { - if (!el) { return noneNode } - const node = buildGroup(el, style); - if (node.type === "mrow" && node.children.length === 0) { return noneNode } - return node -}; - -defineFunction({ - type: "multiscript", - names: ["\\sideset", "\\pres@cript"], // See macros.js for \prescript - props: { - numArgs: 3 - }, - handler({ parser, funcName }, args) { - if (args[2].body.length === 0) { - throw new ParseError(funcName + `cannot parse an empty base.`) - } - const base = args[2].body[0]; - if (parser.settings.strict && funcName === "\\sideset" && !base.symbol) { - throw new ParseError(`The base of \\sideset must be a big operator.`) - } - - if ((args[0].body.length > 0 && args[0].body[0].type !== "supsub") || - (args[1].body.length > 0 && args[1].body[0].type !== "supsub")) { - throw new ParseError("\\sideset can parse only subscripts and " + - "superscripts in its first two arguments") - } - - // The prescripts and postscripts come wrapped in a supsub. - const prescripts = args[0].body.length > 0 ? args[0].body[0] : null; - const postscripts = args[1].body.length > 0 ? args[1].body[0] : null; - - if (!prescripts && !postscripts) { - return base - } else if (!prescripts) { - // It's not a multi-script. Get a \textstyle supsub. - return { - type: "styling", - mode: parser.mode, - scriptLevel: "text", - body: [{ - type: "supsub", - mode: parser.mode, - base, - sup: postscripts.sup, - sub: postscripts.sub - }] - } - } else { - return { - type: "multiscript", - mode: parser.mode, - isSideset: funcName === "\\sideset", - prescripts, - postscripts, - base - } - } - }, - mathmlBuilder(group, style) { - const base = buildGroup(group.base, style); - - const prescriptsNode = new mathMLTree.MathNode("mprescripts"); - const noneNode = new mathMLTree.MathNode("none"); - let children = []; - - const preSub = buildGroup$1(group.prescripts.sub, style, noneNode); - const preSup = buildGroup$1(group.prescripts.sup, style, noneNode); - if (group.isSideset) { - // This seems silly, but LaTeX does this. Firefox ignores it, which does not make me sad. - preSub.setAttribute("style", "text-align: left;"); - preSup.setAttribute("style", "text-align: left;"); - } - - if (group.postscripts) { - const postSub = buildGroup$1(group.postscripts.sub, style, noneNode); - const postSup = buildGroup$1(group.postscripts.sup, style, noneNode); - children = [base, postSub, postSup, prescriptsNode, preSub, preSup]; - } else { - children = [base, prescriptsNode, preSub, preSup]; - } - - return new mathMLTree.MathNode("mmultiscripts", children); - } -}); - -defineFunction({ - type: "not", - names: ["\\not"], - props: { - numArgs: 1, - primitive: true, - allowedInText: false - }, - handler({ parser }, args) { - const isCharacterBox = utils.isCharacterBox(args[0]); - let body; - if (isCharacterBox) { - body = ordargument(args[0]); - if (body[0].text.charAt(0) === "\\") { - body[0].text = symbols.math[body[0].text].replace; - } - // \u0338 is the Unicode Combining Long Solidus Overlay - body[0].text = body[0].text.slice(0, 1) + "\u0338" + body[0].text.slice(1); - } else { - // When the argument is not a character box, TeX does an awkward, poorly placed overlay. - // We'll do the same. - const notNode = { type: "textord", mode: "math", text: "\u0338" }; - const kernNode = { type: "kern", mode: "math", dimension: { number: -0.6, unit: "em" } }; - body = [notNode, kernNode, args[0]]; - } - return { - type: "not", - mode: parser.mode, - body, - isCharacterBox - }; - }, - mathmlBuilder(group, style) { - if (group.isCharacterBox) { - const inner = buildExpression(group.body, style); - return inner[0] - } else { - return buildExpressionRow(group.body, style, true) - } - } -}); - -// Limits, symbols - -const ordAtomTypes = ["textord", "mathord", "atom"]; - -// Most operators have a large successor symbol, but these don't. -const noSuccessor = ["\\smallint"]; - -// Math operators (e.g. \sin) need a space between these types and themselves: -const ordTypes = ["textord", "mathord", "ordgroup", "close", "leftright"]; - -// NOTE: Unlike most `builders`s, this one handles not only "op", but also -// "supsub" since some of them (like \int) can affect super/subscripting. - -const mathmlBuilder$8 = (group, style) => { - let node; - - if (group.symbol) { - // This is a symbol. Just add the symbol. - node = new MathNode("mo", [makeText(group.name, group.mode)]); - if (utils.contains(noSuccessor, group.name)) { - node.setAttribute("largeop", "false"); - } else { - node.setAttribute("movablelimits", "false"); - } - } else if (group.body) { - // This is an operator with children. Add them. - node = new MathNode("mo", buildExpression(group.body, style)); - } else { - // This is a text operator. Add all of the characters from the operator's name. - node = new MathNode("mi", [new TextNode$1(group.name.slice(1))]); - - if (!group.parentIsSupSub) { - // Append an . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new MathNode("mo", [makeText("\u2061", "text")]); - if (group.needsLeadingSpace) { - const space = new MathNode("mspace"); - space.setAttribute("width", "0.1667em"); // thin space. - node = newDocumentFragment([space, node, operator]); - } else { - node = newDocumentFragment([node, operator]); - } - } - } - - return node; -}; - -const singleCharBigOps = { - "\u220F": "\\prod", - "\u2210": "\\coprod", - "\u2211": "\\sum", - "\u22c0": "\\bigwedge", - "\u22c1": "\\bigvee", - "\u22c2": "\\bigcap", - "\u22c3": "\\bigcup", - "\u2a00": "\\bigodot", - "\u2a01": "\\bigoplus", - "\u2a02": "\\bigotimes", - "\u2a04": "\\biguplus", - "\u2a05": "\\bigsqcap", - "\u2a06": "\\bigsqcup" -}; - -defineFunction({ - type: "op", - names: [ - "\\coprod", - "\\bigvee", - "\\bigwedge", - "\\biguplus", - "\\bigcap", - "\\bigcup", - "\\intop", - "\\prod", - "\\sum", - "\\bigotimes", - "\\bigoplus", - "\\bigodot", - "\\bigsqcap", - "\\bigsqcup", - "\\smallint", - "\u220F", - "\u2210", - "\u2211", - "\u22c0", - "\u22c1", - "\u22c2", - "\u22c3", - "\u2a00", - "\u2a01", - "\u2a02", - "\u2a04", - "\u2a06" - ], - props: { - numArgs: 0 - }, - handler: ({ parser, funcName }, args) => { - let fName = funcName; - if (fName.length === 1) { - fName = singleCharBigOps[fName]; - } - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: true, - stack: false, // This is true for \stackrel{}, not here. - name: fName - }; - }, - mathmlBuilder: mathmlBuilder$8 -}); - -// Note: calling defineFunction with a type that's already been defined only -// works because the same mathmlBuilder is being used. -defineFunction({ - type: "op", - names: ["\\mathop"], - props: { - numArgs: 1, - primitive: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - // It would be convienient to just wrap a around the argument. - // But if the argument is a or , that would be invalid MathML. - // In that case, we instead promote the text contents of the body to the parent. - const arr = (body.body) ? body.body : [body]; - const isSymbol = arr.length === 1 && ordAtomTypes.includes(arr[0].type); - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: isSymbol, - stack: false, - name: isSymbol ? arr[0].text : null, - body: isSymbol ? null : ordargument(body) - }; - }, - mathmlBuilder: mathmlBuilder$8 -}); - -// There are 2 flags for operators; whether they produce limits in -// displaystyle, and whether they are symbols and should grow in -// displaystyle. These four groups cover the four possible choices. - -const singleCharIntegrals = { - "\u222b": "\\int", - "\u222c": "\\iint", - "\u222d": "\\iiint", - "\u222e": "\\oint", - "\u222f": "\\oiint", - "\u2230": "\\oiiint", - "\u2231": "\\intclockwise", - "\u2232": "\\varointclockwise", - "\u2a0c": "\\iiiint", - "\u2a0d": "\\intbar", - "\u2a0e": "\\intBar", - "\u2a0f": "\\fint", - "\u2a12": "\\rppolint", - "\u2a13": "\\scpolint", - "\u2a15": "\\pointint", - "\u2a16": "\\sqint", - "\u2a17": "\\intlarhk", - "\u2a18": "\\intx", - "\u2a19": "\\intcap", - "\u2a1a": "\\intcup" -}; - -// No limits, not symbols -defineFunction({ - type: "op", - names: [ - "\\arcsin", - "\\arccos", - "\\arctan", - "\\arctg", - "\\arcctg", - "\\arg", - "\\ch", - "\\cos", - "\\cosec", - "\\cosh", - "\\cot", - "\\cotg", - "\\coth", - "\\csc", - "\\ctg", - "\\cth", - "\\deg", - "\\dim", - "\\exp", - "\\hom", - "\\ker", - "\\lg", - "\\ln", - "\\log", - "\\sec", - "\\sin", - "\\sinh", - "\\sh", - "\\sgn", - "\\tan", - "\\tanh", - "\\tg", - "\\th" - ], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - const prevAtomType = parser.prevAtomType; - return { - type: "op", - mode: parser.mode, - limits: false, - parentIsSupSub: false, - symbol: false, - stack: false, - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType), - name: funcName - }; - }, - mathmlBuilder: mathmlBuilder$8 -}); - -// Limits, not symbols -defineFunction({ - type: "op", - names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - const prevAtomType = parser.prevAtomType; - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: false, - stack: false, - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType), - name: funcName - }; - }, - mathmlBuilder: mathmlBuilder$8 -}); - -// No limits, symbols -defineFunction({ - type: "op", - names: [ - "\\int", - "\\iint", - "\\iiint", - "\\iiiint", - "\\oint", - "\\oiint", - "\\oiiint", - "\\intclockwise", - "\\varointclockwise", - "\\intbar", - "\\intBar", - "\\fint", - "\\rppolint", - "\\scpolint", - "\\pointint", - "\\sqint", - "\\intlarhk", - "\\intx", - "\\intcap", - "\\intcup", - "\u222b", - "\u222c", - "\u222d", - "\u222e", - "\u222f", - "\u2230", - "\u2231", - "\u2232", - "\u2a0c", - "\u2a0d", - "\u2a0e", - "\u2a0f", - "\u2a12", - "\u2a13", - "\u2a15", - "\u2a16", - "\u2a17", - "\u2a18", - "\u2a19", - "\u2a1a" - ], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - let fName = funcName; - if (fName.length === 1) { - fName = singleCharIntegrals[fName]; - } - return { - type: "op", - mode: parser.mode, - limits: false, - parentIsSupSub: false, - symbol: true, - stack: false, - name: fName - }; - }, - mathmlBuilder: mathmlBuilder$8 -}); - -/** - * All registered global/built-in macros. - * `macros.js` exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary via `macros.js`. - */ -const _macros = {}; - -// This function might one day accept an additional argument and do more things. -function defineMacro(name, body) { - _macros[name] = body; -} - -// NOTE: Unlike most builders, this one handles not only -// "operatorname", but also "supsub" since \operatorname* can -// affect super/subscripting. - -const mathmlBuilder$9 = (group, style) => { - let expression = buildExpression(group.body, style.withFont("mathrm")); - - // Is expression a string or has it something like a fraction? - let isAllString = true; // default - for (let i = 0; i < expression.length; i++) { - const node = expression[i]; - if (node instanceof mathMLTree.MathNode) { - switch (node.type) { - case "mi": - case "mn": - case "ms": - case "mtext": - break; // Do nothing yet. - case "mspace": - { - if (node.attributes.width) { - const width = node.attributes.width.replace("em", ""); - const ch = spaceCharacter(Number(width)); - if (ch === "") { - isAllString = false; - } else { - expression[i] = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode(ch)]); - } - } - } - break - case "mo": { - const child = node.children[0]; - if (node.children.length === 1 && child instanceof mathMLTree.TextNode) { - child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*"); - } else { - isAllString = false; - } - break - } - default: - isAllString = false; - } - } else { - isAllString = false; - } - } - - if (isAllString) { - // Write a single TextNode instead of multiple nested tags. - const word = expression.map((node) => node.toText()).join(""); - expression = [new mathMLTree.TextNode(word)]; - } else if ( - expression.length === 1 - && utils.contains(["mover", "munder"], expression[0].type) && - (expression[0].children[0].type === "mi" || expression[0].children[0].type === "mtext") - ) { - expression[0].children[0].type = "mi"; - if (group.parentIsSupSub) { - return new mathMLTree.MathNode("mrow", expression) - } else { - const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); - return mathMLTree.newDocumentFragment([expression[0], operator]) - } - } - - let wrapper; - if (isAllString) { - wrapper = new mathMLTree.MathNode("mi", expression); - wrapper.setAttribute("mathvariant", "normal"); - } else { - wrapper = new mathMLTree.MathNode("mrow", expression); - } - - if (!group.parentIsSupSub) { - // Append an . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); - if (group.needsLeadingSpace) { - // LaTeX gives operator spacing, but a gets ord spacing. - // So add a leading space. - const space = new mathMLTree.MathNode("mspace"); - space.setAttribute("width", "0.1667em"); // thin space. - return mathMLTree.newDocumentFragment([space, wrapper, operator]) - } else { - return mathMLTree.newDocumentFragment([wrapper, operator]) - } - } - - return wrapper -}; - -// \operatorname -// amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@ -defineFunction({ - type: "operatorname", - names: ["\\operatorname@", "\\operatornamewithlimits"], - props: { - numArgs: 1, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const body = args[0]; - const prevAtomType = parser.prevAtomType; - return { - type: "operatorname", - mode: parser.mode, - body: ordargument(body), - alwaysHandleSupSub: (funcName === "\\operatornamewithlimits"), - limits: false, - parentIsSupSub: false, - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType) - }; - }, - mathmlBuilder: mathmlBuilder$9 -}); - -defineMacro("\\operatorname", - "\\@ifstar\\operatornamewithlimits\\operatorname@"); - -defineFunctionBuilders({ - type: "ordgroup", - mathmlBuilder(group, style) { - return buildExpressionRow(group.body, style, true); - } -}); - -defineFunction({ - type: "overline", - names: ["\\overline"], - props: { - numArgs: 1 - }, - handler({ parser }, args) { - const body = args[0]; - return { - type: "overline", - mode: parser.mode, - body - }; - }, - mathmlBuilder(group, style) { - const operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u005F")]); - operator.setAttribute("stretchy", "true"); - - const node = new mathMLTree.MathNode( - "mover", - [buildGroup(group.body, style), operator] - ); - node.setAttribute("accent", "true"); - - return node; - } -}); - -defineFunction({ - type: "phantom", - names: ["\\phantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "phantom", - mode: parser.mode, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(group.body, style); - return new mathMLTree.MathNode("mphantom", inner); - } -}); - -defineFunction({ - type: "hphantom", - names: ["\\hphantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "hphantom", - mode: parser.mode, - body - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(ordargument(group.body), style); - const phantom = new mathMLTree.MathNode("mphantom", inner); - const node = new mathMLTree.MathNode("mpadded", [phantom]); - node.setAttribute("height", "0px"); - node.setAttribute("depth", "0px"); - return node; - } -}); - -defineFunction({ - type: "vphantom", - names: ["\\vphantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "vphantom", - mode: parser.mode, - body - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(ordargument(group.body), style); - const phantom = new mathMLTree.MathNode("mphantom", inner); - const node = new mathMLTree.MathNode("mpadded", [phantom]); - node.setAttribute("width", "0px"); - return node; - } -}); - -// \pmb is a simulation of bold font. -// The version of \pmb in ambsy.sty works by typesetting three copies of the argument -// with small offsets. We use CSS text-shadow. -// It's a hack. Not as good as a real bold font. Better than nothing. - -defineFunction({ - type: "pmb", - names: ["\\pmb"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "pmb", - mode: parser.mode, - body: ordargument(args[0]) - } - }, - mathmlBuilder(group, style) { - const inner = buildExpression(group.body, style); - // Wrap with an element. - const node = wrapWithMstyle(inner); - node.setAttribute("style", "text-shadow: 0.02em 0.01em 0.04px"); - return node - } -}); - -const sign = num => num >= 0 ? "+" : "-"; - -// \raise, \lower, and \raisebox - -const mathmlBuilder$a = (group, style) => { - const newStyle = style.withLevel(StyleLevel.TEXT); - const node = new mathMLTree.MathNode("mpadded", [buildGroup(group.body, newStyle)]); - const dy = calculateSize(group.dy, style); - node.setAttribute("voffset", dy.number + dy.unit); - const dyAbs = Math.abs(dy.number); - node.setAttribute("height", sign(dy.number) + dyAbs + dy.unit); - node.setAttribute("depth", sign(-dy.number) + dyAbs + dy.unit); - return node -}; - -defineFunction({ - type: "raise", - names: ["\\raise", "\\lower"], - props: { - numArgs: 2, - argTypes: ["size", "primitive"], - primitive: true - }, - handler({ parser, funcName }, args) { - const amount = assertNodeType(args[0], "size").value; - if (funcName === "\\lower") { amount.number *= -1; } - const body = args[1]; - return { - type: "raise", - mode: parser.mode, - dy: amount, - body - }; - }, - mathmlBuilder: mathmlBuilder$a -}); - - -defineFunction({ - type: "raise", - names: ["\\raisebox"], - props: { - numArgs: 2, - argTypes: ["size", "hbox"], - allowedInText: true - }, - handler({ parser, funcName }, args) { - const amount = assertNodeType(args[0], "size").value; - const body = args[1]; - return { - type: "raise", - mode: parser.mode, - dy: amount, - body - }; - }, - mathmlBuilder: mathmlBuilder$a -}); - -defineFunction({ - type: "ref", - names: ["\\ref", "\\eqref"], - props: { - numArgs: 1, - argTypes: ["raw"] - }, - handler({ parser, funcName }, args) { - return { - type: "ref", - mode: parser.mode, - funcName, - string: args[0].string.replace(invalidIdRegEx, "") - }; - }, - mathmlBuilder(group, style) { - // Create an empty text node. Set a class and an href. - // The post-processor will populate with the target's tag or equation number. - const classes = group.funcName === "\\ref" ? ["tml-ref"] : ["tml-ref", "tml-eqref"]; - const node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("")], classes); - node.setAttribute("href", "#" + group.string); - return node - } -}); - -defineFunction({ - type: "internal", - names: ["\\relax"], - props: { - numArgs: 0, - allowedInText: true - }, - handler({ parser }) { - return { - type: "internal", - mode: parser.mode - }; - } -}); - -defineFunction({ - type: "rule", - names: ["\\rule"], - props: { - numArgs: 2, - numOptionalArgs: 1, - argTypes: ["size", "size", "size"] - }, - handler({ parser }, args, optArgs) { - const shift = optArgs[0]; - const width = assertNodeType(args[0], "size"); - const height = assertNodeType(args[1], "size"); - return { - type: "rule", - mode: parser.mode, - shift: shift && assertNodeType(shift, "size").value, - width: width.value, - height: height.value - }; - }, - mathmlBuilder(group, style) { - const width = calculateSize(group.width, style); - const height = calculateSize(group.height, style); - const shift = group.shift - ? calculateSize(group.shift, style) - : { number: 0, unit: "em" }; - const color = (style.color && style.getColor()) || "black"; - - const rule = new mathMLTree.MathNode("mspace"); - rule.setAttribute("mathbackground", color); - rule.setAttribute("width", width.number + width.unit); - rule.setAttribute("height", height.number + height.unit); - - const wrapper = new mathMLTree.MathNode("mpadded", [rule]); - if (shift.number >= 0) { - wrapper.setAttribute("height", "+" + shift.number + shift.unit); - } else { - wrapper.setAttribute("height", shift.number + shift.unit); - wrapper.setAttribute("depth", "+" + -shift.number + shift.unit); - } - wrapper.setAttribute("voffset", shift.number + shift.unit); - return wrapper; - } -}); - -// The size mappings are taken from TeX with \normalsize=10pt. -// We don't have to track script level. MathML does that. -const sizeMap = { - "\\tiny": 0.5, - "\\sixptsize": 0.6, - "\\Tiny": 0.6, - "\\scriptsize": 0.7, - "\\footnotesize": 0.8, - "\\small": 0.9, - "\\normalsize": 1.0, - "\\large": 1.2, - "\\Large": 1.44, - "\\LARGE": 1.728, - "\\huge": 2.074, - "\\Huge": 2.488 -}; - -defineFunction({ - type: "sizing", - names: [ - "\\tiny", - "\\sixptsize", - "\\Tiny", - "\\scriptsize", - "\\footnotesize", - "\\small", - "\\normalsize", - "\\large", - "\\Large", - "\\LARGE", - "\\huge", - "\\Huge" - ], - props: { - numArgs: 0, - allowedInText: true - }, - handler: ({ breakOnTokenText, funcName, parser }, args) => { - const body = parser.parseExpression(false, breakOnTokenText); - return { - type: "sizing", - mode: parser.mode, - funcName, - body - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(group.body, style); - // Wrap with an element. - const node = wrapWithMstyle(inner); - node.setAttribute("mathsize", sizeMap[group.funcName] + "em"); - return node; - } -}); - -// smash, with optional [tb], as in AMS - -defineFunction({ - type: "smash", - names: ["\\smash"], - props: { - numArgs: 1, - numOptionalArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args, optArgs) => { - let smashHeight = false; - let smashDepth = false; - const tbArg = optArgs[0] && assertNodeType(optArgs[0], "ordgroup"); - if (tbArg) { - // Optional [tb] argument is engaged. - // ref: amsmath: \renewcommand{\smash}[1][tb]{% - // def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}% - let letter = ""; - for (let i = 0; i < tbArg.body.length; ++i) { - const node = tbArg.body[i]; - // TODO: Write an AssertSymbolNode - letter = node.text; - if (letter === "t") { - smashHeight = true; - } else if (letter === "b") { - smashDepth = true; - } else { - smashHeight = false; - smashDepth = false; - break; - } - } - } else { - smashHeight = true; - smashDepth = true; - } - - const body = args[0]; - return { - type: "smash", - mode: parser.mode, - body, - smashHeight, - smashDepth - }; - }, - mathmlBuilder: (group, style) => { - const node = new mathMLTree.MathNode("mpadded", [buildGroup(group.body, style)]); - - if (group.smashHeight) { - node.setAttribute("height", "0px"); - } - - if (group.smashDepth) { - node.setAttribute("depth", "0px"); - } - - return node; - } -}); - -defineFunction({ - type: "sqrt", - names: ["\\sqrt"], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser }, args, optArgs) { - const index = optArgs[0]; - const body = args[0]; - return { - type: "sqrt", - mode: parser.mode, - body, - index - }; - }, - mathmlBuilder(group, style) { - const { body, index } = group; - return index - ? new mathMLTree.MathNode("mroot", [ - buildGroup(body, style), - buildGroup(index, style.incrementLevel()) - ]) - : new mathMLTree.MathNode("msqrt", [buildGroup(body, style)]); - } -}); - -const styleMap = { - display: 0, - text: 1, - script: 2, - scriptscript: 3 -}; - -const styleAttributes = { - display: ["0", "true"], - text: ["0", "false"], - script: ["1", "false"], - scriptscript: ["2", "false"] -}; - -defineFunction({ - type: "styling", - names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ breakOnTokenText, funcName, parser }, args) { - // parse out the implicit body - const body = parser.parseExpression(true, breakOnTokenText); - - const scriptLevel = funcName.slice(1, funcName.length - 5); - return { - type: "styling", - mode: parser.mode, - // Figure out what scriptLevel to use by pulling out the scriptLevel from - // the function name - scriptLevel, - body - }; - }, - mathmlBuilder(group, style) { - // Figure out what scriptLevel we're changing to. - const newStyle = style.withLevel(styleMap[group.scriptLevel]); - // The style argument in the next line does NOT directly set a MathML script level. - // It just tracks the style level, in case we need to know it for supsub or mathchoice. - const inner = buildExpression(group.body, newStyle); - // Wrap with an element. - const node = wrapWithMstyle(inner); - - const attr = styleAttributes[group.scriptLevel]; - - // Here is where we set the MathML script level. - node.setAttribute("scriptlevel", attr[0]); - node.setAttribute("displaystyle", attr[1]); - - return node; - } -}); - -/** - * Sometimes, groups perform special rules when they have superscripts or - * subscripts attached to them. This function lets the `supsub` group know that - * Sometimes, groups perform special rules when they have superscripts or - * its inner element should handle the superscripts and subscripts instead of - * handling them itself. - */ - -// Helpers -const symbolRegEx = /^m(over|under|underover)$/; - -// Super scripts and subscripts, whose precise placement can depend on other -// functions that precede them. -defineFunctionBuilders({ - type: "supsub", - mathmlBuilder(group, style) { - // Is the inner group a relevant horizonal brace? - let isBrace = false; - let isOver; - let isSup; - let appendApplyFunction = false; - let needsLeadingSpace = false; - - if (group.base && group.base.type === "horizBrace") { - isSup = !!group.sup; - if (isSup === group.base.isOver) { - isBrace = true; - isOver = group.base.isOver; - } - } - - if (group.base && !group.base.stack && - (group.base.type === "op" || group.base.type === "operatorname")) { - group.base.parentIsSupSub = true; - appendApplyFunction = !group.base.symbol; - needsLeadingSpace = group.base.needsLeadingSpace; - } - - const children = group.base && group.base.stack - ? [buildGroup(group.base.body[0], style)] - : [buildGroup(group.base, style)]; - - const childStyle = style.inSubOrSup(); - if (group.sub) { - children.push(buildGroup(group.sub, childStyle)); - } - - if (group.sup) { - children.push(buildGroup(group.sup, childStyle)); - } - - let nodeType; - if (isBrace) { - nodeType = isOver ? "mover" : "munder"; - } else if (!group.sub) { - const base = group.base; - if ( - base && - base.type === "op" && - base.limits && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "mover"; - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (base.limits || style.level === StyleLevel.DISPLAY) - ) { - nodeType = "mover"; - } else { - nodeType = "msup"; - } - } else if (!group.sup) { - const base = group.base; - if ( - base && - base.type === "op" && - base.limits && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "munder"; - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (base.limits || style.level === StyleLevel.DISPLAY) - ) { - nodeType = "munder"; - } else { - nodeType = "msub"; - } - } else { - const base = group.base; - if (base && ((base.type === "op" && base.limits) || base.type === "multiscript") && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "munderover"; - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (style.level === StyleLevel.DISPLAY || base.limits) - ) { - nodeType = "munderover"; - } else { - nodeType = "msubsup"; - } - } - - let node = new mathMLTree.MathNode(nodeType, children); - if (appendApplyFunction) { - // Append an . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); - if (needsLeadingSpace) { - const space = new mathMLTree.MathNode("mspace"); - space.setAttribute("width", "0.1667em"); // thin space. - node = mathMLTree.newDocumentFragment([space, node, operator]); - } else { - node = mathMLTree.newDocumentFragment([node, operator]); - } - } else if (symbolRegEx.test(nodeType)) { - // Wrap in a . Otherwise Firefox stretchy parens will not stretch to include limits. - node = new mathMLTree.MathNode("mrow", [node]); - } - - return node - } -}); - -// Operator ParseNodes created in Parser.js from symbol Groups in src/symbols.js. - -const short = ["\\shortmid", "\\nshortmid", "\\shortparallel", - "\\nshortparallel", "\\smallsetminus"]; - -defineFunctionBuilders({ - type: "atom", - mathmlBuilder(group, style) { - const node = new mathMLTree.MathNode("mo", [makeText(group.text, group.mode)]); - if (group.family === "punct") { - node.setAttribute("separator", "true"); - } else if (group.family === "open" || group.family === "close") { - // Delims built here should not stretch vertically. - // See delimsizing.js for stretchy delims. - if (group.family === "open") { - node.setAttribute("form", "prefix"); - // Set an explicit attribute for stretch. Otherwise Firefox may do it wrong. - node.setAttribute("stretchy", "false"); - } else if (group.family === "close") { - node.setAttribute("form", "postfix"); - node.setAttribute("stretchy", "false"); - } - } else if (group.text === "\\mid") { - // Firefox messes up this spacing if at the end of an . See it explicitly. - node.setAttribute("lspace", "0.22em"); // medium space - node.setAttribute("rspace", "0.22em"); - node.setAttribute("stretchy", "false"); - } else if (short.includes(group.text)) { - node.setAttribute("mathsize", "70%"); - } else if (group.text === ":") { - // ":" is not in the MathML operator dictionary. Give it BIN spacing. - node.attributes.lspace = "0.2222em"; - node.attributes.rspace = "0.2222em"; - } - return node; - } -}); - -/** - * Maps TeX font commands to "mathvariant" attribute in buildMathML.js - */ -const fontMap = { - // styles - mathbf: "bold", - mathrm: "normal", - textit: "italic", - mathit: "italic", - mathnormal: "italic", - - // families - mathbb: "double-struck", - mathcal: "script", - mathfrak: "fraktur", - mathscr: "script", - mathsf: "sans-serif", - mathtt: "monospace", - oldstylenums: "oldstylenums" -}; - -/** - * Returns the math variant as a string or null if none is required. - */ -const getVariant = function(group, style) { - // Handle font specifiers as best we can. - // Chromium does not support the MathML mathvariant attribute. - // So we'll use Unicode replacement characters instead. - // But first, determine the math variant. - - // Deal with the \textit, \textbf, etc., functions. - if (style.fontFamily === "texttt") { - return "monospace" - } else if (style.fontFamily === "textsc") { - return "normal"; // handled via character substitution in symbolsOrd.js. - } else if (style.fontFamily === "textsf") { - if (style.fontShape === "textit" && style.fontWeight === "textbf") { - return "sans-serif-bold-italic" - } else if (style.fontShape === "textit") { - return "sans-serif-italic" - } else if (style.fontWeight === "textbf") { - return "sans-serif-bold" - } else { - return "sans-serif" - } - } else if (style.fontShape === "textit" && style.fontWeight === "textbf") { - return "bold-italic" - } else if (style.fontShape === "textit") { - return "italic" - } else if (style.fontWeight === "textbf") { - return "bold" - } - - // Deal with the \mathit, mathbf, etc, functions. - const font = style.font; - if (!font || font === "mathnormal") { - return null - } - - const mode = group.mode; - switch (font) { - case "mathit": - return "italic" - case "mathrm": { - const codePoint = group.text.codePointAt(0); - // LaTeX \mathrm returns italic for Greek characters. - return (0x03ab < codePoint && codePoint < 0x03cf) ? "italic" : "normal" - } - case "greekItalic": - return "italic" - case "up@greek": - return "normal" - case "boldsymbol": - case "mathboldsymbol": - return "bold-italic" - case "mathbf": - return "bold" - case "mathbb": - return "double-struck" - case "mathfrak": - return "fraktur" - case "mathscr": - case "mathcal": - return "script" - case "mathsf": - return "sans-serif" - case "mathtt": - return "monospace" - case "oldstylenums": - return "oldstylenums" - } - - let text = group.text; - if (symbols[mode][text] && symbols[mode][text].replace) { - text = symbols[mode][text].replace; - } - - return Object.prototype.hasOwnProperty.call(fontMap, font) ? fontMap[font] : null -}; - -// Chromium does not support the MathML `mathvariant` attribute. -// Instead, we replace ASCII characters with Unicode characters that -// are defined in the font as bold, italic, double-struck, etc. -// This module identifies those Unicode code points. - -// First, a few helpers. -const script = Object.freeze({ - B: 0x20EA, // Offset from ASCII B to Unicode script B - E: 0x20EB, - F: 0x20EB, - H: 0x20C3, - I: 0x20C7, - L: 0x20C6, - M: 0x20E6, - R: 0x20C9, - e: 0x20CA, - g: 0x20A3, - o: 0x20C5 -}); - -const frak = Object.freeze({ - C: 0x20EA, - H: 0x20C4, - I: 0x20C8, - R: 0x20CA, - Z: 0x20CE -}); - -const bbb = Object.freeze({ - C: 0x20BF, // blackboard bold - H: 0x20C5, - N: 0x20C7, - P: 0x20C9, - Q: 0x20C9, - R: 0x20CB, - Z: 0x20CA -}); - -const bold = Object.freeze({ - "\u03f5": 0x1D2E7, // lunate epsilon - "\u03d1": 0x1D30C, // vartheta - "\u03f0": 0x1D2EE, // varkappa - "\u03c6": 0x1D319, // varphi - "\u03f1": 0x1D2EF, // varrho - "\u03d6": 0x1D30B // varpi -}); - -const boldItalic = Object.freeze({ - "\u03f5": 0x1D35B, // lunate epsilon - "\u03d1": 0x1D380, // vartheta - "\u03f0": 0x1D362, // varkappa - "\u03c6": 0x1D38D, // varphi - "\u03f1": 0x1D363, // varrho - "\u03d6": 0x1D37F // varpi -}); - -const boldsf = Object.freeze({ - "\u03f5": 0x1D395, // lunate epsilon - "\u03d1": 0x1D3BA, // vartheta - "\u03f0": 0x1D39C, // varkappa - "\u03c6": 0x1D3C7, // varphi - "\u03f1": 0x1D39D, // varrho - "\u03d6": 0x1D3B9 // varpi -}); - -const bisf = Object.freeze({ - "\u03f5": 0x1D3CF, // lunate epsilon - "\u03d1": 0x1D3F4, // vartheta - "\u03f0": 0x1D3D6, // varkappa - "\u03c6": 0x1D401, // varphi - "\u03f1": 0x1D3D7, // varrho - "\u03d6": 0x1D3F3 // varpi -}); - -// Code point offsets below are derived from https://www.unicode.org/charts/PDF/U1D400.pdf -const offset = Object.freeze({ - upperCaseLatin: { // A-Z - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D3BF }, - "italic": ch => { return 0x1D3F3 }, - "bold-italic": ch => { return 0x1D427 }, - "script": ch => { return script[ch] || 0x1D45B }, - "script-bold": ch => { return 0x1D48F }, - "fraktur": ch => { return frak[ch] || 0x1D4C3 }, - "fraktur-bold": ch => { return 0x1D52B }, - "double-struck": ch => { return bbb[ch] || 0x1D4F7 }, - "sans-serif": ch => { return 0x1D55F }, - "sans-serif-bold": ch => { return 0x1D593 }, - "sans-serif-italic": ch => { return 0x1D5C7 }, - "sans-serif-bold-italic": ch => { return 0x1D63C }, - "monospace": ch => { return 0x1D62F } - }, - lowerCaseLatin: { // a-z - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D3B9 }, - "italic": ch => { return ch === "h" ? 0x20A6 : 0x1D3ED }, - "bold-italic": ch => { return 0x1D421 }, - "script": ch => { return script[ch] || 0x1D455 }, - "script-bold": ch => { return 0x1D489 }, - "fraktur": ch => { return 0x1D4BD }, - "fraktur-bold": ch => { return 0x1D525 }, - "double-struck": ch => { return 0x1D4F1 }, - "sans-serif": ch => { return 0x1D559 }, - "sans-serif-bold": ch => { return 0x1D58D }, - "sans-serif-italic": ch => { return 0x1D5C1 }, - "sans-serif-bold-italic": ch => { return 0x1D5F5 }, - "monospace": ch => { return 0x1D629 } - }, - upperCaseGreek: { // A-Ω ∇ - "normal": ch => { return 0 }, - "bold": ch => { return ch === "∇" ? 0x1B4BA : 0x1D317 }, - "italic": ch => { return ch === "∇" ? 0x1B4F4 : 0x1D351 }, - // \boldsymbol actually returns upright bold for upperCaseGreek - "bold-italic": ch => { return ch === "∇" ? 0x1B4BA : 0x1D317 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - // Unicode has no code points for regular-weight san-serif Greek. Use bold. - "sans-serif": ch => { return ch === "∇" ? 0x1B568 : 0x1D3C5 }, - "sans-serif-bold": ch => { return ch === "∇" ? 0x1B568 : 0x1D3C5 }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return ch === "∇" ? 0x1B5A2 : 0x1D3FF }, - "monospace": ch => { return 0 } - }, - lowerCaseGreek: { // α-ω - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D311 }, - "italic": ch => { return 0x1D34B }, - "bold-italic": ch => { return ch === "\u03d5" ? 0x1D37E : 0x1D385 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - // Unicode has no code points for regular-weight san-serif Greek. Use bold. - "sans-serif": ch => { return 0x1D3BF }, - "sans-serif-bold": ch => { return 0x1D3BF }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return 0x1D3F9 }, - "monospace": ch => { return 0 } - }, - varGreek: { // \varGamma, etc - "normal": ch => { return 0 }, - "bold": ch => { return bold[ch] || -51 }, - "italic": ch => { return 0 }, - "bold-italic": ch => { return boldItalic[ch] || 0x3A }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - "sans-serif": ch => { return boldsf[ch] || 0x74 }, - "sans-serif-bold": ch => { return boldsf[ch] || 0x74 }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return bisf[ch] || 0xAE }, - "monospace": ch => { return 0 } - }, - numeral: { // 0-9 - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D79E }, - "italic": ch => { return 0 }, - "bold-italic": ch => { return 0 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0x1D7A8 }, - "sans-serif": ch => { return 0x1D7B2 }, - "sans-serif-bold": ch => { return 0x1D7BC }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return 0 }, - "monospace": ch => { return 0x1D7C6 } - } -}); - -const variantChar = (ch, variant) => { - const codePoint = ch.codePointAt(0); - const block = 0x40 < codePoint && codePoint < 0x5b - ? "upperCaseLatin" - : 0x60 < codePoint && codePoint < 0x7b - ? "lowerCaseLatin" - : (0x390 < codePoint && codePoint < 0x3AA) || ch === "∇" - ? "upperCaseGreek" - : 0x3B0 < codePoint && codePoint < 0x3CA || ch === "\u03d5" - ? "lowerCaseGreek" - : 0x1D6E1 < codePoint && codePoint < 0x1D6FC || bold[ch] - ? "varGreek" - : (0x2F < codePoint && codePoint < 0x3A) - ? "numeral" - : "other"; - return block === "other" - ? ch - : String.fromCodePoint(codePoint + offset[block][variant](ch)) -}; - -const smallCaps = Object.freeze({ - a: "ᴀ", - b: "ʙ", - c: "ᴄ", - d: "ᴅ", - e: "ᴇ", - f: "ꜰ", - g: "ɢ", - h: "ʜ", - i: "ɪ", - j: "ᴊ", - k: "ᴋ", - l: "ʟ", - m: "ᴍ", - n: "ɴ", - o: "ᴏ", - p: "ᴘ", - q: "ǫ", - r: "ʀ", - s: "s", - t: "ᴛ", - u: "ᴜ", - v: "ᴠ", - w: "ᴡ", - x: "x", - y: "ʏ", - z: "ᴢ" -}); - -// "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in -// src/symbols.js. - -const numberRegEx = /^\d[\d.]*$/; // Keep in sync with numberRegEx in Parser.js - -const italicNumber = (text, variant) => { - const mn = new mathMLTree.MathNode("mn", [text]); - const wrapper = new mathMLTree.MathNode("mstyle", [mn]); - wrapper.style["font-style"] = "italic"; - wrapper.style["font-family"] = "Cambria, 'Times New Roman', serif"; - if (variant === "bold-italic") { wrapper.style["font-weight"] = "bold"; } - return wrapper -}; - -defineFunctionBuilders({ - type: "mathord", - mathmlBuilder(group, style) { - const text = makeText(group.text, group.mode, style); - const codePoint = text.text.codePointAt(0); - // Test for upper-case Greek - const defaultVariant = (0x0390 < codePoint && codePoint < 0x03aa) ? "normal" : "italic"; - const variant = getVariant(group, style) || defaultVariant; - if (variant === "script") { - text.text = variantChar(text.text, variant); - return new mathMLTree.MathNode("mi", [text], [style.font]) - } else if (variant !== "italic") { - text.text = variantChar(text.text, variant); - } - const node = new mathMLTree.MathNode("mi", [text]); - // TODO: Handle U+1D49C - U+1D4CF per https://www.unicode.org/charts/PDF/U1D400.pdf - if (variant === "normal") { - node.setAttribute("mathvariant", "normal"); - } - return node - } -}); - -defineFunctionBuilders({ - type: "textord", - mathmlBuilder(group, style) { - let ch = group.text; - const codePoint = ch.codePointAt(0); - if (style.fontFamily === "textsc") { - // Convert small latin letters to small caps. - if (96 < codePoint && codePoint < 123) { - ch = smallCaps[ch]; - } - } - const text = makeText(ch, group.mode, style); - const variant = getVariant(group, style) || "normal"; - - let node; - if (group.mode === "text") { - if (variant === "italic" || variant === "bold-italic") { - if (numberRegEx.test(group.text)) { - return italicNumber(text, variant) - } - } - if (variant !== "normal") { - text.text = variantChar(text.text, variant); - } - node = new mathMLTree.MathNode("mtext", [text]); - } else if (numberRegEx.test(group.text)) { - if (variant === "oldstylenums") { - const ms = new mathMLTree.MathNode("mstyle", [text], ["oldstylenums"]); - node = new mathMLTree.MathNode("mn", [ms]); - } else if (variant === "italic" || variant === "bold-italic") { - return italicNumber(text, variant) - } else { - if (variant !== "normal") { - text.text = text.text.split("").map(c => variantChar(c, variant)).join(""); - } - node = new mathMLTree.MathNode("mn", [text]); - } - } else if (group.text === "\\prime") { - node = new mathMLTree.MathNode("mo", [text]); - } else { - const origText = text.text; - if (variant !== "italic") { - text.text = variantChar(text.text, variant); - } - node = new mathMLTree.MathNode("mi", [text]); - if (text.text === origText ) { - node.setAttribute("mathvariant", "italic"); - } - } - return node - } -}); - -// A map of CSS-based spacing functions to their CSS class. -const cssSpace = { - "\\nobreak": "nobreak", - "\\allowbreak": "allowbreak" -}; - -// A lookup table to determine whether a spacing function/symbol should be -// treated like a regular space character. If a symbol or command is a key -// in this table, then it should be a regular space character. Furthermore, -// the associated value may have a `className` specifying an extra CSS class -// to add to the created `span`. -const regularSpace = { - " ": {}, - "\\ ": {}, - "~": { - className: "nobreak" - }, - "\\space": {}, - "\\nobreakspace": { - className: "nobreak" - } -}; - -// ParseNode<"spacing"> created in Parser.js from the "spacing" symbol Groups in -// src/symbols.js. -defineFunctionBuilders({ - type: "spacing", - mathmlBuilder(group, style) { - let node; - - if (Object.prototype.hasOwnProperty.call(regularSpace, group.text)) { - // Firefox does not render a space in a . So write a no-break space. - // TODO: If Firefox fixes that bug, uncomment the next line and write ch into the node. - //const ch = (regularSpace[group.text].className === "nobreak") ? "\u00a0" : " " - node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("\u00a0")]); - } else if (Object.prototype.hasOwnProperty.call(cssSpace, group.text)) { - // MathML 3.0 calls for nobreak to occur in an , not an - // Ref: https://www.w3.org/Math/draft-spec/mathml.html#chapter3_presm.lbattrs - node = new mathMLTree.MathNode("mo"); - if (group.text === "\\nobreak") { - node.setAttribute("linebreak", "nobreak"); - } - } else { - throw new ParseError(`Unknown type of space "${group.text}"`) - } - - return node - } -}); - -defineFunctionBuilders({ - type: "tag" -}); - -// For a \tag, the work usually done in a mathmlBuilder is instead done in buildMathML.js. -// That way, a \tag can be pulled out of the parse tree and wrapped around the outer node. - -// Non-mathy text, possibly in a font -const textFontFamilies = { - "\\text": undefined, - "\\textrm": "textrm", - "\\textsf": "textsf", - "\\texttt": "texttt", - "\\textnormal": "textrm", - "\\textsc": "textsc" // small caps -}; - -const textFontWeights = { - "\\textbf": "textbf", - "\\textmd": "textmd" -}; - -const textFontShapes = { - "\\textit": "textit", - "\\textup": "textup" -}; - -const styleWithFont = (group, style) => { - const font = group.font; - // Checks if the argument is a font family or a font style. - if (!font) { - return style; - } else if (textFontFamilies[font]) { - return style.withTextFontFamily(textFontFamilies[font]); - } else if (textFontWeights[font]) { - return style.withTextFontWeight(textFontWeights[font]); - } else { - return style.withTextFontShape(textFontShapes[font]); - } -}; - -defineFunction({ - type: "text", - names: [ - // Font families - "\\text", - "\\textrm", - "\\textsf", - "\\texttt", - "\\textnormal", - "\\textsc", - // Font weights - "\\textbf", - "\\textmd", - // Font Shapes - "\\textit", - "\\textup" - ], - props: { - numArgs: 1, - argTypes: ["text"], - allowedInArgument: true, - allowedInText: true - }, - handler({ parser, funcName }, args) { - const body = args[0]; - return { - type: "text", - mode: parser.mode, - body: ordargument(body), - font: funcName - }; - }, - mathmlBuilder(group, style) { - const newStyle = styleWithFont(group, style); - const mrow = buildExpressionRow(group.body, newStyle); - - // If possible, consolidate adjacent elements into a single element. - // First, check if it is possible. If not, return the . - if (mrow.type !== "mrow") { return mrow } - if (mrow.children.length === 0) { return mrow } // empty group, e.g., \text{} - const mtext = mrow.children[0]; - if (!mtext.attributes || mtext.type !== "mtext") { return mrow } - const variant = mtext.attributes.mathvariant || ""; - for (let i = 1; i < mrow.children.length; i++) { - const localVariant = mrow.children[i].attributes.mathvariant || ""; - if (localVariant !== variant || mrow.children[i].type !== "mtext") { return mrow } - } - - // Consolidate the elements. - for (let i = 1; i < mrow.children.length; i++) { - mtext.children[0].text += mrow.children[i].children[0].text; - } - mtext.children.splice(1, mtext.children.length - 1); - // Firefox does not render a space at either end of the string. - // To get proper rendering, we replace with no-break spaces. - if (mtext.children[0].text.charAt(0) === " ") { - mtext.children[0].text = "\u00a0" + mtext.children[0].text.slice(1); - } - const L = mtext.children[0].text.length; - if (L > 0 && mtext.children[0].text.charAt(L - 1) === " ") { - mtext.children[0].text = mtext.children[0].text.slice(0, -1) + "\u00a0"; - } - return mtext - } -}); - -// Two functions included to enable migration from Mathjax. - -defineFunction({ - type: "tip", - names: ["\\mathtip"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "tip", - mode: parser.mode, - body: args[0], - tip: args[1] - }; - }, - mathmlBuilder: (group, style) => { - const math = buildGroup(group.body, style); - const tip = buildGroup(group.tip, style); - // Browsers don't support the tooltip actiontype. - // TODO: Come back and fix \mathtip when it can be done via CSS w/o a JS event. - const node = new mathMLTree.MathNode("maction", [math, tip], ["tml-tip"]); - node.setAttribute("actiontype", "tooltip"); - return node - } -}); - -defineFunction({ - type: "tip", - names: ["\\texttip"], - props: { - numArgs: 2, - argTypes: ["math", "text"] - }, - handler({ parser }, args) { - return { - type: "tip", - mode: parser.mode, - body: args[0], - tip: args[1] - }; - }, - mathmlBuilder: (group, style) => { - const math = buildGroup(group.body, style); - const tip = buildGroup(group.tip, style); - // args[1] only accepted text, so tip is a element or a of them. - let str = ""; - if (tip.type === "mtext") { - str = tip.children[0].text; - } else { - for (const child of tip.children) { - str += child.children[0].text; - } - } - // Implement \texttip via a title attribute. - math.setAttribute("title", str); - return math - } -}); - -defineFunctionBuilders({ - type: "toggle", - mathmlBuilder(group, style) { - const expression = buildExpression(group.body, style); - const node = new mathMLTree.MathNode("maction", expression, [], { cursor: "default" }); - node.setAttribute("actiontype", "toggle"); - return node - } -}); - -defineFunction({ - type: "underline", - names: ["\\underline"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "underline", - mode: parser.mode, - body: args[0] - }; - }, - mathmlBuilder(group, style) { - const operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u005f")]); - operator.setAttribute("stretchy", "true"); - - const node = new mathMLTree.MathNode("munder", - [buildGroup(group.body, style), operator] - ); - node.setAttribute("accentunder", "true"); - - return node; - } -}); - -defineFunction({ - type: "verb", - names: ["\\verb"], - props: { - numArgs: 0, - allowedInText: true - }, - handler(context, args, optArgs) { - // \verb and \verb* are dealt with directly in Parser.js. - // If we end up here, it's because of a failure to match the two delimiters - // in the regex in Lexer.js. LaTeX raises the following error when \verb is - // terminated by end of line (or file). - throw new ParseError("\\verb ended by end of line instead of matching delimiter"); - }, - mathmlBuilder(group, style) { - const text = new mathMLTree.TextNode(makeVerb(group)); - const node = new mathMLTree.MathNode("mtext", [text]); - node.setAttribute("mathvariant", "monospace"); - return node; - } -}); - -/** - * Converts verb group into body string. - * - * \verb* replaces each space with an open box \u2423 - * \verb replaces each space with a no-break space \xA0 - */ -const makeVerb = (group) => group.body.replace(/ /g, group.star ? "\u2423" : "\xA0"); - -/** Include this to ensure that all functions are defined. */ - -const functions = _functions; - -/** - * Lexing or parsing positional information for error reporting. - * This object is immutable. - */ -class SourceLocation { - constructor(lexer, start, end) { - this.lexer = lexer; // Lexer holding the input string. - this.start = start; // Start offset, zero-based inclusive. - this.end = end; // End offset, zero-based exclusive. - } - - /** - * Merges two `SourceLocation`s from location providers, given they are - * provided in order of appearance. - * - Returns the first one's location if only the first is provided. - * - Returns a merged range of the first and the last if both are provided - * and their lexers match. - * - Otherwise, returns null. - */ - static range(first, second) { - if (!second) { - return first && first.loc; - } else if (!first || !first.loc || !second.loc || first.loc.lexer !== second.loc.lexer) { - return null; - } else { - return new SourceLocation(first.loc.lexer, first.loc.start, second.loc.end); - } - } -} - -/** - * Interface required to break circular dependency between Token, Lexer, and - * ParseError. - */ - -/** - * The resulting token returned from `lex`. - * - * It consists of the token text plus some position information. - * The position information is essentially a range in an input string, - * but instead of referencing the bare input string, we refer to the lexer. - * That way it is possible to attach extra metadata to the input string, - * like for example a file name or similar. - * - * The position information is optional, so it is OK to construct synthetic - * tokens if appropriate. Not providing available position information may - * lead to degraded error reporting, though. - */ -class Token { - constructor( - text, // the text of this token - loc - ) { - this.text = text; - this.loc = loc; - } - - /** - * Given a pair of tokens (this and endToken), compute a `Token` encompassing - * the whole input range enclosed by these two. - */ - range( - endToken, // last token of the range, inclusive - text // the text of the newly constructed token - ) { - return new Token(text, SourceLocation.range(this, endToken)); - } -} - -/** - * The Lexer class handles tokenizing the input in various ways. Since our - * parser expects us to be able to backtrack, the lexer allows lexing from any - * given starting point. - * - * Its main exposed function is the `lex` function, which takes a position to - * lex from and a type of token to lex. It defers to the appropriate `_innerLex` - * function. - * - * The various `_innerLex` functions perform the actual lexing of different - * kinds. - */ - -/* The following tokenRegex - * - matches typical whitespace (but not NBSP etc.) using its first two groups - * - does not match any control character \x00-\x1f except whitespace - * - does not match a bare backslash - * - matches any ASCII character except those just mentioned - * - does not match the BMP private use area \uE000-\uF8FF - * - does not match bare surrogate code units - * - matches any BMP character except for those just described - * - matches any valid Unicode surrogate pair - * - mathches numerals - * - matches a backslash followed by one or more whitespace characters - * - matches a backslash followed by one or more letters then whitespace - * - matches a backslash followed by any BMP character - * Capturing groups: - * [1] regular whitespace - * [2] backslash followed by whitespace - * [3] anything else, which may include: - * [4] left character of \verb* - * [5] left character of \verb - * [6] backslash followed by word, excluding any trailing whitespace - * Just because the Lexer matches something doesn't mean it's valid input: - * If there is no matching function or symbol definition, the Parser will - * still reject the input. - */ -const spaceRegexString = "[ \r\n\t]"; -const controlWordRegexString = "\\\\[a-zA-Z@]+"; -const controlSymbolRegexString = "\\\\[^\uD800-\uDFFF]"; -const controlWordWhitespaceRegexString = `(${controlWordRegexString})${spaceRegexString}*`; -const controlSpaceRegexString = "\\\\(\n|[ \r\t]+\n?)[ \r\t]*"; -const combiningDiacriticalMarkString = "[\u0300-\u036f]"; -const combiningDiacriticalMarksEndRegex = new RegExp(`${combiningDiacriticalMarkString}+$`); -const tokenRegexString = - `(${spaceRegexString}+)|` + // whitespace - `${controlSpaceRegexString}|` + // whitespace - "(\\d[\\d.]*" + // numbers (in non-strict mode) - "|[!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + // single codepoint - `${combiningDiacriticalMarkString}*` + // ...plus accents - "|[\uD800-\uDBFF][\uDC00-\uDFFF]" + // surrogate pair - `${combiningDiacriticalMarkString}*` + // ...plus accents - "|\\\\verb\\*([^]).*?\\4" + // \verb* - "|\\\\verb([^*a-zA-Z]).*?\\5" + // \verb unstarred - `|${controlWordWhitespaceRegexString}` + // \macroName + spaces - `|${controlSymbolRegexString})`; // \\, \', etc. - -/** Main Lexer class */ -class Lexer { - constructor(input, settings) { - // Separate accents from characters - this.input = input; - this.settings = settings; - this.tokenRegex = new RegExp( - // Strict Temml, like TeX, lexes one numeral at a time. - // Default Temml lexes contiguous numerals into a single element. - tokenRegexString.replace("\\d[\\d.]*|", settings.strict ? "" : "\\d[\\d.]*|"), - "g" - ); - // Category codes. The lexer only supports comment characters (14) for now. - // MacroExpander additionally distinguishes active (13). - this.catcodes = { - "%": 14, // comment character - "~": 13 // active character - }; - } - - setCatcode(char, code) { - this.catcodes[char] = code; - } - - /** - * This function lexes a single token. - */ - lex() { - const input = this.input; - const pos = this.tokenRegex.lastIndex; - if (pos === input.length) { - return new Token("EOF", new SourceLocation(this, pos, pos)); - } - const match = this.tokenRegex.exec(input); - if (match === null || match.index !== pos) { - throw new ParseError( - `Unexpected character: '${input[pos]}'`, - new Token(input[pos], new SourceLocation(this, pos, pos + 1)) - ); - } - const text = match[6] || match[3] || (match[2] ? "\\ " : " "); - - if (this.catcodes[text] === 14) { - // comment character - const nlIndex = input.indexOf("\n", this.tokenRegex.lastIndex); - if (nlIndex === -1) { - this.tokenRegex.lastIndex = input.length; // EOF - this.settings.reportNonstrict( - "commentAtEnd", - "% comment has no terminating newline; LaTeX would " + - "fail because of commenting the end of math mode (e.g. $)" - ); - } else { - this.tokenRegex.lastIndex = nlIndex + 1; - } - return this.lex(); - } - - return new Token(text, new SourceLocation(this, pos, this.tokenRegex.lastIndex)); - } -} - -/** - * A `Namespace` refers to a space of nameable things like macros or lengths, - * which can be `set` either globally or local to a nested group, using an - * undo stack similar to how TeX implements this functionality. - * Performance-wise, `get` and `set` take constant time. - */ - -class Namespace { - /** - * Both arguments are optional. The first argument is an object of - * built-in mappings which never change. The second argument is an object - * of initial (global-level) mappings, which will constantly change - * according to any global/top-level `set`s done. - */ - constructor(builtins = {}, globalMacros = {}) { - this.current = globalMacros; - this.builtins = builtins; - this.undefStack = []; - } - - /** - * Start a new nested group, affecting future local `set`s. - */ - beginGroup() { - this.undefStack.push({}); - } - - /** - * End current nested group, restoring values before the group began. - */ - endGroup() { - if (this.undefStack.length === 0) { - throw new ParseError( - "Unbalanced namespace destruction: attempt " + - "to pop global namespace; please report this as a bug" - ); - } - const undefs = this.undefStack.pop(); - for (const undef in undefs) { - if (Object.prototype.hasOwnProperty.call(undefs, undef )) { - if (undefs[undef] === undefined) { - delete this.current[undef]; - } else { - this.current[undef] = undefs[undef]; - } - } - } - } - - /** - * Detect whether `name` has a definition. Equivalent to - * `get(name) != null`. - */ - has(name) { - return Object.prototype.hasOwnProperty.call(this.current, name ) || - Object.prototype.hasOwnProperty.call(this.builtins, name ); - } - - /** - * Get the current value of a name, or `undefined` if there is no value. - * - * Note: Do not use `if (namespace.get(...))` to detect whether a macro - * is defined, as the definition may be the empty string which evaluates - * to `false` in JavaScript. Use `if (namespace.get(...) != null)` or - * `if (namespace.has(...))`. - */ - get(name) { - if (Object.prototype.hasOwnProperty.call(this.current, name )) { - return this.current[name]; - } else { - return this.builtins[name]; - } - } - - /** - * Set the current value of a name, and adds an undo - * operation to the undo stack. - */ - set(name, value) { - // Undo this set at end of this group (possibly to `undefined`), - // unless an undo is already in place, in which case that older - // value is the correct one. - const top = this.undefStack[this.undefStack.length - 1]; - if (top && !Object.prototype.hasOwnProperty.call(top, name )) { - top[name] = this.current[name]; - } - this.current[name] = value; - } -} - -/** - * Predefined macros for Temml. - * This can be used to define some commands in terms of others. - */ -const macros = _macros; - -////////////////////////////////////////////////////////////////////// -// macro tools - -defineMacro("\\noexpand", function(context) { - // The expansion is the token itself; but that token is interpreted - // as if its meaning were ‘\relax’ if it is a control sequence that - // would ordinarily be expanded by TeX’s expansion rules. - const t = context.popToken(); - if (context.isExpandable(t.text)) { - t.noexpand = true; - t.treatAsRelax = true; - } - return { tokens: [t], numArgs: 0 }; -}); - -defineMacro("\\expandafter", function(context) { - // TeX first reads the token that comes immediately after \expandafter, - // without expanding it; let’s call this token t. Then TeX reads the - // token that comes after t (and possibly more tokens, if that token - // has an argument), replacing it by its expansion. Finally TeX puts - // t back in front of that expansion. - const t = context.popToken(); - context.expandOnce(true); // expand only an expandable token - return { tokens: [t], numArgs: 0 }; -}); - -// LaTeX's \@firstoftwo{#1}{#2} expands to #1, skipping #2 -// TeX source: \long\def\@firstoftwo#1#2{#1} -defineMacro("\\@firstoftwo", function(context) { - const args = context.consumeArgs(2); - return { tokens: args[0], numArgs: 0 }; -}); - -// LaTeX's \@secondoftwo{#1}{#2} expands to #2, skipping #1 -// TeX source: \long\def\@secondoftwo#1#2{#2} -defineMacro("\\@secondoftwo", function(context) { - const args = context.consumeArgs(2); - return { tokens: args[1], numArgs: 0 }; -}); - -// LaTeX's \@ifnextchar{#1}{#2}{#3} looks ahead to the next (unexpanded) -// symbol that isn't a space, consuming any spaces but not consuming the -// first nonspace character. If that nonspace character matches #1, then -// the macro expands to #2; otherwise, it expands to #3. -defineMacro("\\@ifnextchar", function(context) { - const args = context.consumeArgs(3); // symbol, if, else - context.consumeSpaces(); - const nextToken = context.future(); - if (args[0].length === 1 && args[0][0].text === nextToken.text) { - return { tokens: args[1], numArgs: 0 }; - } else { - return { tokens: args[2], numArgs: 0 }; - } -}); - -// LaTeX's \@ifstar{#1}{#2} looks ahead to the next (unexpanded) symbol. -// If it is `*`, then it consumes the symbol, and the macro expands to #1; -// otherwise, the macro expands to #2 (without consuming the symbol). -// TeX source: \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}} -defineMacro("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}"); - -// LaTeX's \TextOrMath{#1}{#2} expands to #1 in text mode, #2 in math mode -defineMacro("\\TextOrMath", function(context) { - const args = context.consumeArgs(2); - if (context.mode === "text") { - return { tokens: args[0], numArgs: 0 }; - } else { - return { tokens: args[1], numArgs: 0 }; - } -}); - -const stringFromArg = arg => { - // Reverse the order of the arg and return a string. - let str = ""; - for (let i = arg.length - 1; i > -1; i--) { - str += arg[i].text; - } - return str -}; - -// Lookup table for parsing numbers in base 8 through 16 -const digitToNumber = { - 0: 0, - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9, - a: 10, - A: 10, - b: 11, - B: 11, - c: 12, - C: 12, - d: 13, - D: 13, - e: 14, - E: 14, - f: 15, - F: 15 -}; - -const nextCharNumber = context => { - const numStr = context.future().text; - if (numStr === "EOF") { return [null, ""] } - return [digitToNumber[numStr.charAt(0)], numStr] -}; - -const appendCharNumbers = (number, numStr, base) => { - for (let i = 1; i < numStr.length; i++) { - const digit = digitToNumber[numStr.charAt(i)]; - number *= base; - number += digit; - } - return number -}; - -// TeX \char makes a literal character (catcode 12) using the following forms: -// (see The TeXBook, p. 43) -// \char123 -- decimal -// \char'123 -- octal -// \char"123 -- hex -// \char`x -- character that can be written (i.e. isn't active) -// \char`\x -- character that cannot be written (e.g. %) -// These all refer to characters from the font, so we turn them into special -// calls to a function \@char dealt with in the Parser. -defineMacro("\\char", function(context) { - let token = context.popToken(); - let base; - let number = ""; - if (token.text === "'") { - base = 8; - token = context.popToken(); - } else if (token.text === '"') { - base = 16; - token = context.popToken(); - } else if (token.text === "`") { - token = context.popToken(); - if (token.text[0] === "\\") { - number = token.text.charCodeAt(1); - } else if (token.text === "EOF") { - throw new ParseError("\\char` missing argument"); - } else { - number = token.text.charCodeAt(0); - } - } else { - base = 10; - } - if (base) { - // Parse a number in the given base, starting with first `token`. - let numStr = token.text; - number = digitToNumber[numStr.charAt(0)]; - if (number == null || number >= base) { - throw new ParseError(`Invalid base-${base} digit ${token.text}`); - } - number = appendCharNumbers(number, numStr, base); - let digit; - [digit, numStr] = nextCharNumber(context); - while (digit != null && digit < base) { - number *= base; - number += digit; - number = appendCharNumbers(number, numStr, base); - context.popToken(); - [digit, numStr] = nextCharNumber(context); - } - } - return `\\@char{${number}}`; -}); - -defineMacro("\\hbox", "\\text{#1}"); - -// Per TeXbook p.122, "/" gets zero operator spacing. -// And MDN recommends using U+2044 instead of / for inline -defineMacro("/", "{\u2044}"); - -// Since Temml has no \par, ignore \long. -defineMacro("\\long", ""); - -////////////////////////////////////////////////////////////////////// -// Grouping -// \let\bgroup={ \let\egroup=} -defineMacro("\\bgroup", "{"); -defineMacro("\\egroup", "}"); - -// Symbols from latex.ltx: -// \def~{\nobreakspace{}} -// \def\lq{`} -// \def\rq{'} -// \def \aa {\r a} -defineMacro("~", "\\nobreakspace"); -defineMacro("\\lq", "`"); -defineMacro("\\rq", "'"); -defineMacro("\\aa", "\\r a"); - -defineMacro("\\Bbbk", "\\Bbb{k}"); - -// \mathstrut from the TeXbook, p 360 -defineMacro("\\mathstrut", "\\vphantom{(}"); - -// \underbar from TeXbook p 353 -defineMacro("\\underbar", "\\underline{\\text{#1}}"); - -////////////////////////////////////////////////////////////////////// -// LaTeX_2ε - -// \vdots{\vbox{\baselineskip4\p@ \lineskiplimit\z@ -// \kern6\p@\hbox{.}\hbox{.}\hbox{.}}} -// We'll call \varvdots, which gets a glyph from symbols.js. -// The zero-width rule gets us an equivalent to the vertical 6pt kern. -defineMacro("\\vdots", "\\mathord{\\varvdots\\rule{0pt}{15pt}}"); -defineMacro("\u22ee", "\\vdots"); - -////////////////////////////////////////////////////////////////////// -// amsmath.sty -// http://mirrors.concertpass.com/tex-archive/macros/latex/required/amsmath/amsmath.pdf - -//\newcommand{\substack}[1]{\subarray{c}#1\endsubarray} -defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}"); - -// \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}} -defineMacro("\\boxed", "\\fbox{$\\displaystyle{#1}$}"); - -// \def\iff{\DOTSB\;\Longleftrightarrow\;} -// \def\implies{\DOTSB\;\Longrightarrow\;} -// \def\impliedby{\DOTSB\;\Longleftarrow\;} -defineMacro("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;"); -defineMacro("\\implies", "\\DOTSB\\;\\Longrightarrow\\;"); -defineMacro("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;"); - -// AMSMath's automatic \dots, based on \mdots@@ macro. -const dotsByToken = { - ",": "\\dotsc", - "\\not": "\\dotsb", - // \keybin@ checks for the following: - "+": "\\dotsb", - "=": "\\dotsb", - "<": "\\dotsb", - ">": "\\dotsb", - "-": "\\dotsb", - "*": "\\dotsb", - ":": "\\dotsb", - // Symbols whose definition starts with \DOTSB: - "\\DOTSB": "\\dotsb", - "\\coprod": "\\dotsb", - "\\bigvee": "\\dotsb", - "\\bigwedge": "\\dotsb", - "\\biguplus": "\\dotsb", - "\\bigcap": "\\dotsb", - "\\bigcup": "\\dotsb", - "\\prod": "\\dotsb", - "\\sum": "\\dotsb", - "\\bigotimes": "\\dotsb", - "\\bigoplus": "\\dotsb", - "\\bigodot": "\\dotsb", - "\\bigsqcap": "\\dotsb", - "\\bigsqcup": "\\dotsb", - "\\And": "\\dotsb", - "\\longrightarrow": "\\dotsb", - "\\Longrightarrow": "\\dotsb", - "\\longleftarrow": "\\dotsb", - "\\Longleftarrow": "\\dotsb", - "\\longleftrightarrow": "\\dotsb", - "\\Longleftrightarrow": "\\dotsb", - "\\mapsto": "\\dotsb", - "\\longmapsto": "\\dotsb", - "\\hookrightarrow": "\\dotsb", - "\\doteq": "\\dotsb", - // Symbols whose definition starts with \mathbin: - "\\mathbin": "\\dotsb", - // Symbols whose definition starts with \mathrel: - "\\mathrel": "\\dotsb", - "\\relbar": "\\dotsb", - "\\Relbar": "\\dotsb", - "\\xrightarrow": "\\dotsb", - "\\xleftarrow": "\\dotsb", - // Symbols whose definition starts with \DOTSI: - "\\DOTSI": "\\dotsi", - "\\int": "\\dotsi", - "\\oint": "\\dotsi", - "\\iint": "\\dotsi", - "\\iiint": "\\dotsi", - "\\iiiint": "\\dotsi", - "\\idotsint": "\\dotsi", - // Symbols whose definition starts with \DOTSX: - "\\DOTSX": "\\dotsx" -}; - -defineMacro("\\dots", function(context) { - // TODO: If used in text mode, should expand to \textellipsis. - // However, in Temml, \textellipsis and \ldots behave the same - // (in text mode), and it's unlikely we'd see any of the math commands - // that affect the behavior of \dots when in text mode. So fine for now - // (until we support \ifmmode ... \else ... \fi). - let thedots = "\\dotso"; - const next = context.expandAfterFuture().text; - if (next in dotsByToken) { - thedots = dotsByToken[next]; - } else if (next.substr(0, 4) === "\\not") { - thedots = "\\dotsb"; - } else if (next in symbols.math) { - if (utils.contains(["bin", "rel"], symbols.math[next].group)) { - thedots = "\\dotsb"; - } - } - return thedots; -}); - -const spaceAfterDots = { - // \rightdelim@ checks for the following: - ")": true, - "]": true, - "\\rbrack": true, - "\\}": true, - "\\rbrace": true, - "\\rangle": true, - "\\rceil": true, - "\\rfloor": true, - "\\rgroup": true, - "\\rmoustache": true, - "\\right": true, - "\\bigr": true, - "\\biggr": true, - "\\Bigr": true, - "\\Biggr": true, - // \extra@ also tests for the following: - $: true, - // \extrap@ checks for the following: - ";": true, - ".": true, - ",": true -}; - -defineMacro("\\dotso", function(context) { - const next = context.future().text; - if (next in spaceAfterDots) { - return "\\ldots\\,"; - } else { - return "\\ldots"; - } -}); - -defineMacro("\\dotsc", function(context) { - const next = context.future().text; - // \dotsc uses \extra@ but not \extrap@, instead specially checking for - // ';' and '.', but doesn't check for ','. - if (next in spaceAfterDots && next !== ",") { - return "\\ldots\\,"; - } else { - return "\\ldots"; - } -}); - -defineMacro("\\cdots", function(context) { - const next = context.future().text; - if (next in spaceAfterDots) { - return "\\@cdots\\,"; - } else { - return "\\@cdots"; - } -}); - -defineMacro("\\dotsb", "\\cdots"); -defineMacro("\\dotsm", "\\cdots"); -defineMacro("\\dotsi", "\\!\\cdots"); -defineMacro("\\idotsint", "\\dotsi"); -// amsmath doesn't actually define \dotsx, but \dots followed by a macro -// starting with \DOTSX implies \dotso, and then \extra@ detects this case -// and forces the added `\,`. -defineMacro("\\dotsx", "\\ldots\\,"); - -// \let\DOTSI\relax -// \let\DOTSB\relax -// \let\DOTSX\relax -defineMacro("\\DOTSI", "\\relax"); -defineMacro("\\DOTSB", "\\relax"); -defineMacro("\\DOTSX", "\\relax"); - -// Spacing, based on amsmath.sty's override of LaTeX defaults -// \DeclareRobustCommand{\tmspace}[3]{% -// \ifmmode\mskip#1#2\else\kern#1#3\fi\relax} -defineMacro("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"); -// \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}} -// TODO: math mode should use \thinmuskip -defineMacro("\\,", "\\tmspace+{3mu}{.1667em}"); -// \let\thinspace\, -defineMacro("\\thinspace", "\\,"); -// \def\>{\mskip\medmuskip} -// \renewcommand{\:}{\tmspace+\medmuskip{.2222em}} -// TODO: \> and math mode of \: should use \medmuskip = 4mu plus 2mu minus 4mu -defineMacro("\\>", "\\mskip{4mu}"); -defineMacro("\\:", "\\tmspace+{4mu}{.2222em}"); -// \let\medspace\: -defineMacro("\\medspace", "\\:"); -// \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}} -// TODO: math mode should use \thickmuskip = 5mu plus 5mu -defineMacro("\\;", "\\tmspace+{5mu}{.2777em}"); -// \let\thickspace\; -defineMacro("\\thickspace", "\\;"); -// \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}} -// TODO: math mode should use \thinmuskip -defineMacro("\\!", "\\tmspace-{3mu}{.1667em}"); -// \let\negthinspace\! -defineMacro("\\negthinspace", "\\!"); -// \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}} -// TODO: math mode should use \medmuskip -defineMacro("\\negmedspace", "\\tmspace-{4mu}{.2222em}"); -// \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}} -// TODO: math mode should use \thickmuskip -defineMacro("\\negthickspace", "\\tmspace-{5mu}{.277em}"); -// \def\enspace{\kern.5em } -defineMacro("\\enspace", "\\kern.5em "); -// \def\enskip{\hskip.5em\relax} -defineMacro("\\enskip", "\\hskip.5em\\relax"); -// \def\quad{\hskip1em\relax} -defineMacro("\\quad", "\\hskip1em\\relax"); -// \def\qquad{\hskip2em\relax} -defineMacro("\\qquad", "\\hskip2em\\relax"); - -// \tag@in@display form of \tag -defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren"); -defineMacro("\\tag@paren", "\\tag@literal{({#1})}"); -defineMacro("\\tag@literal", (context) => { - if (context.macros.get("\\df@tag")) { - throw new ParseError("Multiple \\tag"); - } - return "\\def\\df@tag{\\text{#1}}"; -}); - -// \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin -// {\operator@font mod}\penalty900 -// \mkern5mu\nonscript\mskip-\medmuskip} -// \newcommand{\pod}[1]{\allowbreak -// \if@display\mkern18mu\else\mkern8mu\fi(#1)} -// \renewcommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}} -// \newcommand{\mod}[1]{\allowbreak\if@display\mkern18mu -// \else\mkern12mu\fi{\operator@font mod}\,\,#1} -// TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu -defineMacro("\\bmod", "\\mathbin{\\text{mod}}"); -defineMacro( - "\\pod", - "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)" -); -defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}"); -defineMacro( - "\\mod", - "\\allowbreak" + - "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + - "{\\rm mod}\\,\\,#1" -); - -////////////////////////////////////////////////////////////////////// -// LaTeX source2e - -// \expandafter\let\expandafter\@normalcr -// \csname\expandafter\@gobble\string\\ \endcsname -// \DeclareRobustCommand\newline{\@normalcr\relax} -defineMacro("\\newline", "\\\\\\relax"); - -// \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@} -// TODO: Doesn't normally work in math mode because \@ fails. -defineMacro("\\TeX", "\\textrm{T}\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125em\\textrm{X}"); - -defineMacro( - "\\LaTeX", - "\\textrm{L}\\kern-.35em\\raisebox{0.2em}{\\scriptstyle A}\\kern-.15em\\TeX" -); - -defineMacro( - "\\Temml", - // eslint-disable-next-line max-len - "\\textrm{T}\\kern-0.2em\\lower{0.2em}\\textrm{E}\\kern-0.08em{\\textrm{M}\\kern-0.08em\\raise{0.2em}\\textrm{M}\\kern-0.08em\\textrm{L}}" -); - -// \DeclareRobustCommand\hspace{\@ifstar\@hspacer\@hspace} -// \def\@hspace#1{\hskip #1\relax} -// \def\@hspacer#1{\vrule \@width\z@\nobreak -// \hskip #1\hskip \z@skip} -defineMacro("\\hspace", "\\@ifstar\\@hspacer\\@hspace"); -defineMacro("\\@hspace", "\\hskip #1\\relax"); -defineMacro("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax"); - -////////////////////////////////////////////////////////////////////// -// mathtools.sty - -defineMacro("\\prescript", "\\pres@cript{_{#1}^{#2}}{}{#3}"); - -//\providecommand\ordinarycolon{:} -defineMacro("\\ordinarycolon", ":"); -//\def\vcentcolon{\mathrel{\mathop\ordinarycolon}} -//TODO(edemaine): Not yet centered. Fix via \raisebox or #726 -defineMacro("\\vcentcolon", "\\mathrel{\\mathrel\\ordinarycolon}"); -// \providecommand*\coloneq{\vcentcolon\mathrel{\mkern-1.2mu}\mathrel{-}} -defineMacro("\\coloneq", '\\mathrel{\\char"3a\\char"2212}'); -// \providecommand*\Coloneq{\dblcolon\mathrel{\mkern-1.2mu}\mathrel{-}} -defineMacro("\\Coloneq", '\\mathrel{\\char"2237\\char"2212}'); -// \providecommand*\Eqqcolon{=\mathrel{\mkern-1.2mu}\dblcolon} -defineMacro("\\Eqqcolon", '\\mathrel{\\char"3d\\char"2237}'); -// \providecommand*\Eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\dblcolon} -defineMacro("\\Eqcolon", '\\mathrel{\\char"2212\\char"2237}'); -// \providecommand*\colonapprox{\vcentcolon\mathrel{\mkern-1.2mu}\approx} -defineMacro("\\colonapprox", '\\mathrel{\\char"3a\\char"2248}'); -// \providecommand*\Colonapprox{\dblcolon\mathrel{\mkern-1.2mu}\approx} -defineMacro("\\Colonapprox", '\\mathrel{\\char"2237\\char"2248}'); -// \providecommand*\colonsim{\vcentcolon\mathrel{\mkern-1.2mu}\sim} -defineMacro("\\colonsim", '\\mathrel{\\char"3a\\char"223c}'); -// \providecommand*\Colonsim{\dblcolon\mathrel{\mkern-1.2mu}\sim} -defineMacro("\\Colonsim", '\\mathrel{\\char"2237\\char"223c}'); - -////////////////////////////////////////////////////////////////////// -// colonequals.sty - -// Alternate names for mathtools's macros: -defineMacro("\\ratio", "\\vcentcolon"); -defineMacro("\\coloncolon", "\\dblcolon"); -defineMacro("\\colonequals", "\\coloneqq"); -defineMacro("\\coloncolonequals", "\\Coloneqq"); -defineMacro("\\equalscolon", "\\eqqcolon"); -defineMacro("\\equalscoloncolon", "\\Eqqcolon"); -defineMacro("\\colonminus", "\\coloneq"); -defineMacro("\\coloncolonminus", "\\Coloneq"); -defineMacro("\\minuscolon", "\\eqcolon"); -defineMacro("\\minuscoloncolon", "\\Eqcolon"); -// \colonapprox name is same in mathtools and colonequals. -defineMacro("\\coloncolonapprox", "\\Colonapprox"); -// \colonsim name is same in mathtools and colonequals. -defineMacro("\\coloncolonsim", "\\Colonsim"); - -// Present in newtxmath, pxfonts and txfonts -defineMacro("\\notni", "\\mathrel{\\char`\u220C}"); -defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}"); -defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}"); - -////////////////////////////////////////////////////////////////////// -// From amsopn.sty -defineMacro("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}"); -defineMacro("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}"); -defineMacro("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{\\text{lim}}}"); -defineMacro("\\varliminf", "\\DOTSB\\operatorname*{\\underline{\\text{lim}}}"); -defineMacro("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{\\text{lim}}}"); -defineMacro("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{\\text{lim}}}"); - - -////////////////////////////////////////////////////////////////////// -// statmath.sty -// https://ctan.math.illinois.edu/macros/latex/contrib/statmath/statmath.pdf - -defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}"); -defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}"); -defineMacro("\\plim", "\\DOTSB\\operatorname*{plim}"); - -////////////////////////////////////////////////////////////////////// -// braket.sty -// http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf - -defineMacro("\\bra", "\\mathinner{\\langle{#1}|}"); -defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}"); -defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}"); -defineMacro("\\Bra", "\\left\\langle#1\\right|"); -defineMacro("\\Ket", "\\left|#1\\right\\rangle"); -const braketHelper = (one) => (context) => { - const left = context.consumeArg().tokens; - const middle = context.consumeArg().tokens; - const middleDouble = context.consumeArg().tokens; - const right = context.consumeArg().tokens; - const oldMiddle = context.macros.get("|"); - const oldMiddleDouble = context.macros.get("\\|"); - context.macros.beginGroup(); - const midMacro = (double) => (context) => { - if (one) { - // Only modify the first instance of | or \| - context.macros.set("|", oldMiddle); - if (middleDouble.length) { - context.macros.set("\\|", oldMiddleDouble); - } - } - let doubled = double; - if (!double && middleDouble.length) { - // Mimic \@ifnextchar - const nextToken = context.future(); - if (nextToken.text === "|") { - context.popToken(); - doubled = true; - } - } - return { - tokens: doubled ? middleDouble : middle, - numArgs: 0 - }; - }; - context.macros.set("|", midMacro(false)); - if (middleDouble.length) { - context.macros.set("\\|", midMacro(true)); - } - const arg = context.consumeArg().tokens; - const expanded = context.expandTokens([...right, ...arg, ...left]); // reversed - context.macros.endGroup(); - return { - tokens: expanded.reverse(), - numArgs: 0 - }; -}; -defineMacro("\\bra@ket", braketHelper(false)); -defineMacro("\\bra@set", braketHelper(true)); -defineMacro("\\Braket", "\\bra@ket{\\left\\langle}" + - "{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"); -defineMacro("\\Set", "\\bra@set{\\left\\{\\:}" + - "{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"); -defineMacro("\\set", "\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"); - // has no support for special || or \| - -////////////////////////////////////////////////////////////////////// -// actuarialangle.dtx -defineMacro("\\angln", "{\\angl n}"); - -////////////////////////////////////////////////////////////////////// -// derivative.sty -defineMacro("\\odv", "\\@ifstar\\odv@next\\odv@numerator"); -defineMacro("\\odv@numerator", "\\frac{\\mathrm{d}#1}{\\mathrm{d}#2}"); -defineMacro("\\odv@next", "\\frac{\\mathrm{d}}{\\mathrm{d}#2}#1"); -defineMacro("\\pdv", "\\@ifstar\\pdv@next\\pdv@numerator"); - -const pdvHelper = args => { - const numerator = args[0][0].text; - const denoms = stringFromArg(args[1]).split(","); - const power = String(denoms.length); - const numOp = power === "1" ? "\\partial" : `\\partial^${power}`; - let denominator = ""; - denoms.map(e => { denominator += "\\partial " + e.trim() + "\\,";}); - return [numerator, numOp, denominator.replace(/\\,$/, "")] -}; -defineMacro("\\pdv@numerator", function(context) { - const [numerator, numOp, denominator] = pdvHelper(context.consumeArgs(2)); - return `\\frac{${numOp} ${numerator}}{${denominator}}` -}); -defineMacro("\\pdv@next", function(context) { - const [numerator, numOp, denominator] = pdvHelper(context.consumeArgs(2)); - return `\\frac{${numOp}}{${denominator}} ${numerator}` -}); - -////////////////////////////////////////////////////////////////////// -// upgreek.dtx -defineMacro("\\upalpha", "\\up@greek{\\alpha}"); -defineMacro("\\upbeta", "\\up@greek{\\beta}"); -defineMacro("\\upgamma", "\\up@greek{\\gamma}"); -defineMacro("\\updelta", "\\up@greek{\\delta}"); -defineMacro("\\upepsilon", "\\up@greek{\\epsilon}"); -defineMacro("\\upzeta", "\\up@greek{\\zeta}"); -defineMacro("\\upeta", "\\up@greek{\\eta}"); -defineMacro("\\uptheta", "\\up@greek{\\theta}"); -defineMacro("\\upiota", "\\up@greek{\\iota}"); -defineMacro("\\upkappa", "\\up@greek{\\kappa}"); -defineMacro("\\uplambda", "\\up@greek{\\lambda}"); -defineMacro("\\upmu", "\\up@greek{\\mu}"); -defineMacro("\\upnu", "\\up@greek{\\nu}"); -defineMacro("\\upxi", "\\up@greek{\\xi}"); -defineMacro("\\upomicron", "\\up@greek{\\omicron}"); -defineMacro("\\uppi", "\\up@greek{\\pi}"); -defineMacro("\\upalpha", "\\up@greek{\\alpha}"); -defineMacro("\\uprho", "\\up@greek{\\rho}"); -defineMacro("\\upsigma", "\\up@greek{\\sigma}"); -defineMacro("\\uptau", "\\up@greek{\\tau}"); -defineMacro("\\upupsilon", "\\up@greek{\\upsilon}"); -defineMacro("\\upphi", "\\up@greek{\\phi}"); -defineMacro("\\upchi", "\\up@greek{\\chi}"); -defineMacro("\\uppsi", "\\up@greek{\\psi}"); -defineMacro("\\upomega", "\\up@greek{\\omega}"); - -////////////////////////////////////////////////////////////////////// -// chemstyle package -defineMacro("\\standardstate", "{\\tiny\\char`⦵}"); - -/* eslint-disable */ -/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ - -/************************************************************* - * - * Temml mhchem.js - * - * This file implements a Temml version of mhchem version 3.3.0. - * It is adapted from MathJax/extensions/TeX/mhchem.js - * It differs from the MathJax version as follows: - * 1. The interface is changed so that it can be called from Temml, not MathJax. - * 2. \rlap and \llap are replaced with \mathrlap and \mathllap. - * 3. The reaction arrow code is simplified. All reaction arrows are rendered - * using Temml extensible arrows instead of building non-extensible arrows. - * 4. SVG path geometry is supplied for \equilibriumRight & \equilibriumLeft. - * 5. \tripledash uses Unicode character U+2504, ┄. - * 6. Two dashes in _getBond are wrapped in braces to suppress spacing. i.e., {-} - * 7. The electron dot uses \textbullet instead of \bullet. - * - * This code, as other Temml code, is released under the MIT license. - * - * /************************************************************* - * - * MathJax/extensions/TeX/mhchem.js - * - * Implements the \ce command for handling chemical formulas - * from the mhchem LaTeX package. - * - * --------------------------------------------------------------------- - * - * Copyright (c) 2011-2015 The MathJax Consortium - * Copyright (c) 2015-2018 Martin Hensel - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Coding Style -// - use '' for identifiers that can by minified/uglified -// - use "" for strings that need to stay untouched - -// version: "3.3.0" for MathJax and Temml - - -// Add \ce, \pu, and \tripledash to the Temml macros. - -defineMacro("\\ce", function(context) { - return chemParse(context.consumeArgs(1)[0], "ce") -}); - -defineMacro("\\pu", function(context) { - return chemParse(context.consumeArgs(1)[0], "pu"); -}); - -// Needed for \bond for the ~ forms -// Raise by 2.56mu, not 2mu. We're raising a hyphen-minus, U+002D, not -// a mathematical minus, U+2212. So we need that extra 0.56. -defineMacro("\\tripledash", '\\mathord{\\kern2mu\\raise{0.5mu}{\\char"2504}\\kern2mu}'); - -// Use the Temml macro system to send SVG path geometry for equilibrium arrows. -defineMacro("longRightleftharpoonsLeft", `M507,435c-4,4,-6.3,8.7,-7,14 -c0,5.3,0.7,9,2,11c1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17 -c2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21 -c-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40 -c-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z -M0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z`) -defineMacro("longRightleftharpoonsRight", `M0,241 l0,40c399126,0,399993,0,399993,0 -c4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199, --231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6 -c-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z -M0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z`) -defineMacro("longLeftrightharpoonsLeft", `M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11 -c1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9, -1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7, --152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z -M93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z`) -defineMacro("longLeftrightharpoonsRight", `M53,241l0,40c398570,0,399437,0,399437,0 -c4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199, --231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6 -c-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z -M500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z`) - - -const path = { - "\\equilibriumRight" : { - left: `M507,435c-4,4,-6.3,8.7,-7,14 -c0,5.3,0.7,9,2,11c1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17 -c2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21 -c-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40 -c-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z -M0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z`, - right: `M0,241 l0,40c399126,0,399993,0,399993,0 -c4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199, --231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6 -c-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z -M0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z` - }, - "\\equilibriumLeft": { - left: `M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11 -c1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9, -1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7, --152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z -M93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z`, - right: `M53,241l0,40c398570,0,399437,0,399437,0 -c4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199, --231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6 -c-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z -M500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z` - } -} - -const svg = (name, end) => { - const svg = { - type: "svg", - attributes: { - xmlns: "http://www.w3.org/2000/svg", - width: "400em", - height: "0.716em", - viewBox: "0 0 400000 716", - preserveAspectRatio: `x${end === "left" ? "Min" : "Max"}yMin slice`, - fill: "currrentColor", - "fill-rule": "non-zero", - "fill-opacity" : 1 - }, - style: { position: "absolute" }, - children: [{ - type: "path", - attributes: { d: path[name][end], stroke: "none" }, - children: [] - }] - } - if (end === "left") { svg.style.left = 0 } else { svg.style.right = 0 } - return svg -} - -const endSpan = (name, end) => { - const span = { - type: "span", - attributes: {}, - style: { position: "absolute", width: "50.2%", height: "0.716em", overflow: "hidden" }, - children: [svg(name, end)] - } - if (end === "left") { span.style.left = 0 } else { span.style.right = 0 } - return span -} - -const arrowNode = name => { - return JSON.stringify({ - type: "span", - attributes: {}, - style: { display: "block", position: "relative", width: "100%", height: "0.716em", "min-width": "1.75em" }, - children: [endSpan(name, "left"), endSpan(name, "right")] - }) -} - -defineMacro("\\@equilibriumRight", arrowNode("\\equilibriumRight")) -defineMacro("\\@equilibriumLeft", arrowNode("\\equilibriumLeft")) - - // - // This is the main function for handing the \ce and \pu commands. - // It takes the argument to \ce or \pu and returns the corresponding TeX string. - // - - var chemParse = function (tokens, stateMachine) { - // Recreate the argument string from Temml's array of tokens. - var str = ""; - var expectedLoc = tokens[tokens.length - 1].loc.start - for (var i = tokens.length - 1; i >= 0; i--) { - if(tokens[i].loc.start > expectedLoc) { - // context.consumeArgs has eaten a space. - str += " "; - expectedLoc = tokens[i].loc.start; - } - str += tokens[i].text; - expectedLoc += tokens[i].text.length; - } - // Call the mhchem core parser. - var tex = texify.go(mhchemParser.go(str, stateMachine)); - return tex; - }; - - // - // Core parser for mhchem syntax (recursive) - // - /** @type {MhchemParser} */ - var mhchemParser = { - // - // Parses mchem \ce syntax - // - // Call like - // go("H2O"); - // - go: function (input, stateMachine) { - if (!input) { return []; } - if (stateMachine === undefined) { stateMachine = 'ce'; } - var state = '0'; - - // - // String buffers for parsing: - // - // buffer.a == amount - // buffer.o == element - // buffer.b == left-side superscript - // buffer.p == left-side subscript - // buffer.q == right-side subscript - // buffer.d == right-side superscript - // - // buffer.r == arrow - // buffer.rdt == arrow, script above, type - // buffer.rd == arrow, script above, content - // buffer.rqt == arrow, script below, type - // buffer.rq == arrow, script below, content - // - // buffer.text_ - // buffer.rm - // etc. - // - // buffer.parenthesisLevel == int, starting at 0 - // buffer.sb == bool, space before - // buffer.beginsWithBond == bool - // - // These letters are also used as state names. - // - // Other states: - // 0 == begin of main part (arrow/operator unlikely) - // 1 == next entity - // 2 == next entity (arrow/operator unlikely) - // 3 == next atom - // c == macro - // - /** @type {Buffer} */ - var buffer = {}; - buffer['parenthesisLevel'] = 0; - - input = input.replace(/\n/g, " "); - input = input.replace(/[\u2212\u2013\u2014\u2010]/g, "-"); - input = input.replace(/[\u2026]/g, "..."); - - // - // Looks through mhchemParser.transitions, to execute a matching action - // (recursive) - // - var lastInput; - var watchdog = 10; - /** @type {ParserOutput[]} */ - var output = []; - while (true) { - if (lastInput !== input) { - watchdog = 10; - lastInput = input; - } else { - watchdog--; - } - // - // Find actions in transition table - // - var machine = mhchemParser.stateMachines[stateMachine]; - var t = machine.transitions[state] || machine.transitions['*']; - iterateTransitions: - for (var i=0; i 0) { - if (!task.revisit) { - input = matches.remainder; - } - if (!task.toContinue) { - break iterateTransitions; - } - } else { - return output; - } - } - } - // - // Prevent infinite loop - // - if (watchdog <= 0) { - throw ["MhchemBugU", "mhchem bug U. Please report."]; // Unexpected character - } - } - }, - concatArray: function (a, b) { - if (b) { - if (Array.isArray(b)) { - for (var iB=0; iB': /^[=<>]/, - '#': /^[#\u2261]/, - '+': /^\+/, - '-$': /^-(?=[\s_},;\]/]|$|\([a-z]+\))/, // -space -, -; -] -/ -$ -state-of-aggregation - '-9': /^-(?=[0-9])/, - '- orbital overlap': /^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/, - '-': /^-/, - 'pm-operator': /^(?:\\pm|\$\\pm\$|\+-|\+\/-)/, - 'operator': /^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/, - 'arrowUpDown': /^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/, - '\\bond{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\bond{", "", "", "}"); }, - '->': /^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/, - 'CMT': /^[CMT](?=\[)/, - '[(...)]': function (input) { return mhchemParser.patterns.findObserveGroups(input, "[", "", "", "]"); }, - '1st-level escape': /^(&|\\\\|\\hline)\s*/, - '\\,': /^(?:\\[,\ ;:])/, // \\x - but output no space before - '\\x{}{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); }, - '\\x{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", ""); }, - '\\ca': /^\\ca(?:\s+|(?![a-zA-Z]))/, - '\\x': /^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/, - 'orbital': /^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/, // only those with numbers in front, because the others will be formatted correctly anyway - 'others': /^[\/~|]/, - '\\frac{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\frac{", "", "", "}", "{", "", "", "}"); }, - '\\overset{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\overset{", "", "", "}", "{", "", "", "}"); }, - '\\underset{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\underset{", "", "", "}", "{", "", "", "}"); }, - '\\underbrace{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\underbrace{", "", "", "}_", "{", "", "", "}"); }, - '\\color{(...)}0': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}"); }, - '\\color{(...)}{(...)}1': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}", "{", "", "", "}"); }, - '\\color(...){(...)}2': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color", "\\", "", /^(?=\{)/, "{", "", "", "}"); }, - '\\ce{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\ce{", "", "", "}"); }, - 'oxidation$': /^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, - 'd-oxidation$': /^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, // 0 could be oxidation or charge - 'roman numeral': /^[IVX]+/, - '1/2$': /^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/, - 'amount': function (input) { - var match; - // e.g. 2, 0.5, 1/2, -2, n/2, +; $a$ could be added later in parsing - match = input.match(/^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/); - if (match) { - return { match_: match[0], remainder: input.substr(match[0].length) }; - } - var a = mhchemParser.patterns.findObserveGroups(input, "", "$", "$", ""); - if (a) { // e.g. $2n-1$, $-$ - match = a.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/); - if (match) { - return { match_: match[0], remainder: input.substr(match[0].length) }; - } - } - return null; - }, - 'amount2': function (input) { return this['amount'](input); }, - '(KV letters),': /^(?:[A-Z][a-z]{0,2}|i)(?=,)/, - 'formula$': function (input) { - if (input.match(/^\([a-z]+\)$/)) { return null; } // state of aggregation = no formula - var match = input.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/); - if (match) { - return { match_: match[0], remainder: input.substr(match[0].length) }; - } - return null; - }, - 'uprightEntities': /^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/, - '/': /^\s*(\/)\s*/, - '//': /^\s*(\/\/)\s*/, - '*': /^\s*[*.]\s*/ - }, - findObserveGroups: function (input, begExcl, begIncl, endIncl, endExcl, beg2Excl, beg2Incl, end2Incl, end2Excl, combine) { - /** @type {{(input: string, pattern: string | RegExp): string | string[] | null;}} */ - var _match = function (input, pattern) { - if (typeof pattern === "string") { - if (input.indexOf(pattern) !== 0) { return null; } - return pattern; - } else { - var match = input.match(pattern); - if (!match) { return null; } - return match[0]; - } - }; - /** @type {{(input: string, i: number, endChars: string | RegExp): {endMatchBegin: number, endMatchEnd: number} | null;}} */ - var _findObserveGroups = function (input, i, endChars) { - var braces = 0; - while (i < input.length) { - var a = input.charAt(i); - var match = _match(input.substr(i), endChars); - if (match !== null && braces === 0) { - return { endMatchBegin: i, endMatchEnd: i + match.length }; - } else if (a === "{") { - braces++; - } else if (a === "}") { - if (braces === 0) { - throw ["ExtraCloseMissingOpen", "Extra close brace or missing open brace"]; - } else { - braces--; - } - } - i++; - } - if (braces > 0) { - return null; - } - return null; - }; - var match = _match(input, begExcl); - if (match === null) { return null; } - input = input.substr(match.length); - match = _match(input, begIncl); - if (match === null) { return null; } - var e = _findObserveGroups(input, match.length, endIncl || endExcl); - if (e === null) { return null; } - var match1 = input.substring(0, (endIncl ? e.endMatchEnd : e.endMatchBegin)); - if (!(beg2Excl || beg2Incl)) { - return { - match_: match1, - remainder: input.substr(e.endMatchEnd) - }; - } else { - var group2 = this.findObserveGroups(input.substr(e.endMatchEnd), beg2Excl, beg2Incl, end2Incl, end2Excl); - if (group2 === null) { return null; } - /** @type {string[]} */ - var matchRet = [match1, group2.match_]; - return { - match_: (combine ? matchRet.join("") : matchRet), - remainder: group2.remainder - }; - } - }, - - // - // Matching function - // e.g. match("a", input) will look for the regexp called "a" and see if it matches - // returns null or {match_:"a", remainder:"bc"} - // - match_: function (m, input) { - var pattern = mhchemParser.patterns.patterns[m]; - if (pattern === undefined) { - throw ["MhchemBugP", "mhchem bug P. Please report. (" + m + ")"]; // Trying to use non-existing pattern - } else if (typeof pattern === "function") { - return mhchemParser.patterns.patterns[m](input); // cannot use cached var pattern here, because some pattern functions need this===mhchemParser - } else { // RegExp - var match = input.match(pattern); - if (match) { - var mm; - if (match[2]) { - mm = [ match[1], match[2] ]; - } else if (match[1]) { - mm = match[1]; - } else { - mm = match[0]; - } - return { match_: mm, remainder: input.substr(match[0].length) }; - } - return null; - } - } - }, - - // - // Generic state machine actions - // - actions: { - 'a=': function (buffer, m) { buffer.a = (buffer.a || "") + m; }, - 'b=': function (buffer, m) { buffer.b = (buffer.b || "") + m; }, - 'p=': function (buffer, m) { buffer.p = (buffer.p || "") + m; }, - 'o=': function (buffer, m) { buffer.o = (buffer.o || "") + m; }, - 'q=': function (buffer, m) { buffer.q = (buffer.q || "") + m; }, - 'd=': function (buffer, m) { buffer.d = (buffer.d || "") + m; }, - 'rm=': function (buffer, m) { buffer.rm = (buffer.rm || "") + m; }, - 'text=': function (buffer, m) { buffer.text_ = (buffer.text_ || "") + m; }, - 'insert': function (buffer, m, a) { return { type_: a }; }, - 'insert+p1': function (buffer, m, a) { return { type_: a, p1: m }; }, - 'insert+p1+p2': function (buffer, m, a) { return { type_: a, p1: m[0], p2: m[1] }; }, - 'copy': function (buffer, m) { return m; }, - 'rm': function (buffer, m) { return { type_: 'rm', p1: m || ""}; }, - 'text': function (buffer, m) { return mhchemParser.go(m, 'text'); }, - '{text}': function (buffer, m) { - var ret = [ "{" ]; - mhchemParser.concatArray(ret, mhchemParser.go(m, 'text')); - ret.push("}"); - return ret; - }, - 'tex-math': function (buffer, m) { return mhchemParser.go(m, 'tex-math'); }, - 'tex-math tight': function (buffer, m) { return mhchemParser.go(m, 'tex-math tight'); }, - 'bond': function (buffer, m, k) { return { type_: 'bond', kind_: k || m }; }, - 'color0-output': function (buffer, m) { return { type_: 'color0', color: m[0] }; }, - 'ce': function (buffer, m) { return mhchemParser.go(m); }, - '1/2': function (buffer, m) { - /** @type {ParserOutput[]} */ - var ret = []; - if (m.match(/^[+\-]/)) { - ret.push(m.substr(0, 1)); - m = m.substr(1); - } - var n = m.match(/^([0-9]+|\$[a-z]\$|[a-z])\/([0-9]+)(\$[a-z]\$|[a-z])?$/); - n[1] = n[1].replace(/\$/g, ""); - ret.push({ type_: 'frac', p1: n[1], p2: n[2] }); - if (n[3]) { - n[3] = n[3].replace(/\$/g, ""); - ret.push({ type_: 'tex-math', p1: n[3] }); - } - return ret; - }, - '9,9': function (buffer, m) { return mhchemParser.go(m, '9,9'); } - }, - // - // createTransitions - // convert { 'letter': { 'state': { action_: 'output' } } } to { 'state' => [ { pattern: 'letter', task: { action_: [{type_: 'output'}] } } ] } - // with expansion of 'a|b' to 'a' and 'b' (at 2 places) - // - createTransitions: function (o) { - var pattern, state; - /** @type {string[]} */ - var stateArray; - var i; - // - // 1. Collect all states - // - /** @type {Transitions} */ - var transitions = {}; - for (pattern in o) { - for (state in o[pattern]) { - stateArray = state.split("|"); - o[pattern][state].stateArray = stateArray; - for (i=0; i': { - '0|1|2|3': { action_: 'r=', nextState: 'r' }, - 'a|as': { action_: [ 'output', 'r=' ], nextState: 'r' }, - '*': { action_: [ 'output', 'r=' ], nextState: 'r' } }, - '+': { - 'o': { action_: 'd= kv', nextState: 'd' }, - 'd|D': { action_: 'd=', nextState: 'd' }, - 'q': { action_: 'd=', nextState: 'qd' }, - 'qd|qD': { action_: 'd=', nextState: 'qd' }, - 'dq': { action_: [ 'output', 'd=' ], nextState: 'd' }, - '3': { action_: [ 'sb=false', 'output', 'operator' ], nextState: '0' } }, - 'amount': { - '0|2': { action_: 'a=', nextState: 'a' } }, - 'pm-operator': { - '0|1|2|a|as': { action_: [ 'sb=false', 'output', { type_: 'operator', option: '\\pm' } ], nextState: '0' } }, - 'operator': { - '0|1|2|a|as': { action_: [ 'sb=false', 'output', 'operator' ], nextState: '0' } }, - '-$': { - 'o|q': { action_: [ 'charge or bond', 'output' ], nextState: 'qd' }, - 'd': { action_: 'd=', nextState: 'd' }, - 'D': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' }, - 'q': { action_: 'd=', nextState: 'qd' }, - 'qd': { action_: 'd=', nextState: 'qd' }, - 'qD|dq': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' } }, - '-9': { - '3|o': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '3' } }, - '- orbital overlap': { - 'o': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' }, - 'd': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' } }, - '-': { - '0|1|2': { action_: [ { type_: 'output', option: 1 }, 'beginsWithBond=true', { type_: 'bond', option: "-" } ], nextState: '3' }, - '3': { action_: { type_: 'bond', option: "-" } }, - 'a': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' }, - 'as': { action_: [ { type_: 'output', option: 2 }, { type_: 'bond', option: "-" } ], nextState: '3' }, - 'b': { action_: 'b=' }, - 'o': { action_: { type_: '- after o/d', option: false }, nextState: '2' }, - 'q': { action_: { type_: '- after o/d', option: false }, nextState: '2' }, - 'd|qd|dq': { action_: { type_: '- after o/d', option: true }, nextState: '2' }, - 'D|qD|p': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' } }, - 'amount2': { - '1|3': { action_: 'a=', nextState: 'a' } }, - 'letters': { - '0|1|2|3|a|as|b|p|bp|o': { action_: 'o=', nextState: 'o' }, - 'q|dq': { action_: ['output', 'o='], nextState: 'o' }, - 'd|D|qd|qD': { action_: 'o after d', nextState: 'o' } }, - 'digits': { - 'o': { action_: 'q=', nextState: 'q' }, - 'd|D': { action_: 'q=', nextState: 'dq' }, - 'q': { action_: [ 'output', 'o=' ], nextState: 'o' }, - 'a': { action_: 'o=', nextState: 'o' } }, - 'space A': { - 'b|p|bp': {} }, - 'space': { - 'a': { nextState: 'as' }, - '0': { action_: 'sb=false' }, - '1|2': { action_: 'sb=true' }, - 'r|rt|rd|rdt|rdq': { action_: 'output', nextState: '0' }, - '*': { action_: [ 'output', 'sb=true' ], nextState: '1'} }, - '1st-level escape': { - '1|2': { action_: [ 'output', { type_: 'insert+p1', option: '1st-level escape' } ] }, - '*': { action_: [ 'output', { type_: 'insert+p1', option: '1st-level escape' } ], nextState: '0' } }, - '[(...)]': { - 'r|rt': { action_: 'rd=', nextState: 'rd' }, - 'rd|rdt': { action_: 'rq=', nextState: 'rdq' } }, - '...': { - 'o|d|D|dq|qd|qD': { action_: [ 'output', { type_: 'bond', option: "..." } ], nextState: '3' }, - '*': { action_: [ { type_: 'output', option: 1 }, { type_: 'insert', option: 'ellipsis' } ], nextState: '1' } }, - '. |* ': { - '*': { action_: [ 'output', { type_: 'insert', option: 'addition compound' } ], nextState: '1' } }, - 'state of aggregation $': { - '*': { action_: [ 'output', 'state of aggregation' ], nextState: '1' } }, - '{[(': { - 'a|as|o': { action_: [ 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' }, - '0|1|2|3': { action_: [ 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' }, - '*': { action_: [ 'output', 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' } }, - ')]}': { - '0|1|2|3|b|p|bp|o': { action_: [ 'o=', 'parenthesisLevel--' ], nextState: 'o' }, - 'a|as|d|D|q|qd|qD|dq': { action_: [ 'output', 'o=', 'parenthesisLevel--' ], nextState: 'o' } }, - ', ': { - '*': { action_: [ 'output', 'comma' ], nextState: '0' } }, - '^_': { // ^ and _ without a sensible argument - '*': { } }, - '^{(...)}|^($...$)': { - '0|1|2|as': { action_: 'b=', nextState: 'b' }, - 'p': { action_: 'b=', nextState: 'bp' }, - '3|o': { action_: 'd= kv', nextState: 'D' }, - 'q': { action_: 'd=', nextState: 'qD' }, - 'd|D|qd|qD|dq': { action_: [ 'output', 'd=' ], nextState: 'D' } }, - '^a|^\\x{}{}|^\\x{}|^\\x|\'': { - '0|1|2|as': { action_: 'b=', nextState: 'b' }, - 'p': { action_: 'b=', nextState: 'bp' }, - '3|o': { action_: 'd= kv', nextState: 'd' }, - 'q': { action_: 'd=', nextState: 'qd' }, - 'd|qd|D|qD': { action_: 'd=' }, - 'dq': { action_: [ 'output', 'd=' ], nextState: 'd' } }, - '_{(state of aggregation)}$': { - 'd|D|q|qd|qD|dq': { action_: [ 'output', 'q=' ], nextState: 'q' } }, - '_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x': { - '0|1|2|as': { action_: 'p=', nextState: 'p' }, - 'b': { action_: 'p=', nextState: 'bp' }, - '3|o': { action_: 'q=', nextState: 'q' }, - 'd|D': { action_: 'q=', nextState: 'dq' }, - 'q|qd|qD|dq': { action_: [ 'output', 'q=' ], nextState: 'q' } }, - '=<>': { - '0|1|2|3|a|as|o|q|d|D|qd|qD|dq': { action_: [ { type_: 'output', option: 2 }, 'bond' ], nextState: '3' } }, - '#': { - '0|1|2|3|a|as|o': { action_: [ { type_: 'output', option: 2 }, { type_: 'bond', option: "#" } ], nextState: '3' } }, - '{}': { - '*': { action_: { type_: 'output', option: 1 }, nextState: '1' } }, - '{...}': { - '0|1|2|3|a|as|b|p|bp': { action_: 'o=', nextState: 'o' }, - 'o|d|D|q|qd|qD|dq': { action_: [ 'output', 'o=' ], nextState: 'o' } }, - '$...$': { - 'a': { action_: 'a=' }, // 2$n$ - '0|1|2|3|as|b|p|bp|o': { action_: 'o=', nextState: 'o' }, // not 'amount' - 'as|o': { action_: 'o=' }, - 'q|d|D|qd|qD|dq': { action_: [ 'output', 'o=' ], nextState: 'o' } }, - '\\bond{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'bond' ], nextState: "3" } }, - '\\frac{(...)}': { - '*': { action_: [ { type_: 'output', option: 1 }, 'frac-output' ], nextState: '3' } }, - '\\overset{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'overset-output' ], nextState: '3' } }, - '\\underset{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'underset-output' ], nextState: '3' } }, - '\\underbrace{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'underbrace-output' ], nextState: '3' } }, - '\\color{(...)}{(...)}1|\\color(...){(...)}2': { - '*': { action_: [ { type_: 'output', option: 2 }, 'color-output' ], nextState: '3' } }, - '\\color{(...)}0': { - '*': { action_: [ { type_: 'output', option: 2 }, 'color0-output' ] } }, - '\\ce{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'ce' ], nextState: '3' } }, - '\\,': { - '*': { action_: [ { type_: 'output', option: 1 }, 'copy' ], nextState: '1' } }, - '\\x{}{}|\\x{}|\\x': { - '0|1|2|3|a|as|b|p|bp|o|c0': { action_: [ 'o=', 'output' ], nextState: '3' }, - '*': { action_: ['output', 'o=', 'output' ], nextState: '3' } }, - 'others': { - '*': { action_: [ { type_: 'output', option: 1 }, 'copy' ], nextState: '3' } }, - 'else2': { - 'a': { action_: 'a to o', nextState: 'o', revisit: true }, - 'as': { action_: [ 'output', 'sb=true' ], nextState: '1', revisit: true }, - 'r|rt|rd|rdt|rdq': { action_: [ 'output' ], nextState: '0', revisit: true }, - '*': { action_: [ 'output', 'copy' ], nextState: '3' } } - }), - actions: { - 'o after d': function (buffer, m) { - var ret; - if ((buffer.d || "").match(/^[0-9]+$/)) { - var tmp = buffer.d; - buffer.d = undefined; - ret = this['output'](buffer); - buffer.b = tmp; - } else { - ret = this['output'](buffer); - } - mhchemParser.actions['o='](buffer, m); - return ret; - }, - 'd= kv': function (buffer, m) { - buffer.d = m; - buffer.dType = 'kv'; - }, - 'charge or bond': function (buffer, m) { - if (buffer['beginsWithBond']) { - /** @type {ParserOutput[]} */ - var ret = []; - mhchemParser.concatArray(ret, this['output'](buffer)); - mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-")); - return ret; - } else { - buffer.d = m; - } - }, - '- after o/d': function (buffer, m, isAfterD) { - var c1 = mhchemParser.patterns.match_('orbital', buffer.o || ""); - var c2 = mhchemParser.patterns.match_('one lowercase greek letter $', buffer.o || ""); - var c3 = mhchemParser.patterns.match_('one lowercase latin letter $', buffer.o || ""); - var c4 = mhchemParser.patterns.match_('$one lowercase latin letter$ $', buffer.o || ""); - var hyphenFollows = m==="-" && ( c1 && c1.remainder==="" || c2 || c3 || c4 ); - if (hyphenFollows && !buffer.a && !buffer.b && !buffer.p && !buffer.d && !buffer.q && !c1 && c3) { - buffer.o = '$' + buffer.o + '$'; - } - /** @type {ParserOutput[]} */ - var ret = []; - if (hyphenFollows) { - mhchemParser.concatArray(ret, this['output'](buffer)); - ret.push({ type_: 'hyphen' }); - } else { - c1 = mhchemParser.patterns.match_('digits', buffer.d || ""); - if (isAfterD && c1 && c1.remainder==='') { - mhchemParser.concatArray(ret, mhchemParser.actions['d='](buffer, m)); - mhchemParser.concatArray(ret, this['output'](buffer)); - } else { - mhchemParser.concatArray(ret, this['output'](buffer)); - mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-")); - } - } - return ret; - }, - 'a to o': function (buffer) { - buffer.o = buffer.a; - buffer.a = undefined; - }, - 'sb=true': function (buffer) { buffer.sb = true; }, - 'sb=false': function (buffer) { buffer.sb = false; }, - 'beginsWithBond=true': function (buffer) { buffer['beginsWithBond'] = true; }, - 'beginsWithBond=false': function (buffer) { buffer['beginsWithBond'] = false; }, - 'parenthesisLevel++': function (buffer) { buffer['parenthesisLevel']++; }, - 'parenthesisLevel--': function (buffer) { buffer['parenthesisLevel']--; }, - 'state of aggregation': function (buffer, m) { - return { type_: 'state of aggregation', p1: mhchemParser.go(m, 'o') }; - }, - 'comma': function (buffer, m) { - var a = m.replace(/\s*$/, ''); - var withSpace = (a !== m); - if (withSpace && buffer['parenthesisLevel'] === 0) { - return { type_: 'comma enumeration L', p1: a }; - } else { - return { type_: 'comma enumeration M', p1: a }; - } - }, - 'output': function (buffer, m, entityFollows) { - // entityFollows: - // undefined = if we have nothing else to output, also ignore the just read space (buffer.sb) - // 1 = an entity follows, never omit the space if there was one just read before (can only apply to state 1) - // 2 = 1 + the entity can have an amount, so output a\, instead of converting it to o (can only apply to states a|as) - /** @type {ParserOutput | ParserOutput[]} */ - var ret; - if (!buffer.r) { - ret = []; - if (!buffer.a && !buffer.b && !buffer.p && !buffer.o && !buffer.q && !buffer.d && !entityFollows) { - //ret = []; - } else { - if (buffer.sb) { - ret.push({ type_: 'entitySkip' }); - } - if (!buffer.o && !buffer.q && !buffer.d && !buffer.b && !buffer.p && entityFollows!==2) { - buffer.o = buffer.a; - buffer.a = undefined; - } else if (!buffer.o && !buffer.q && !buffer.d && (buffer.b || buffer.p)) { - buffer.o = buffer.a; - buffer.d = buffer.b; - buffer.q = buffer.p; - buffer.a = buffer.b = buffer.p = undefined; - } else { - if (buffer.o && buffer.dType==='kv' && mhchemParser.patterns.match_('d-oxidation$', buffer.d || "")) { - buffer.dType = 'oxidation'; - } else if (buffer.o && buffer.dType==='kv' && !buffer.q) { - buffer.dType = undefined; - } - } - ret.push({ - type_: 'chemfive', - a: mhchemParser.go(buffer.a, 'a'), - b: mhchemParser.go(buffer.b, 'bd'), - p: mhchemParser.go(buffer.p, 'pq'), - o: mhchemParser.go(buffer.o, 'o'), - q: mhchemParser.go(buffer.q, 'pq'), - d: mhchemParser.go(buffer.d, (buffer.dType === 'oxidation' ? 'oxidation' : 'bd')), - dType: buffer.dType - }); - } - } else { // r - /** @type {ParserOutput[]} */ - var rd; - if (buffer.rdt === 'M') { - rd = mhchemParser.go(buffer.rd, 'tex-math'); - } else if (buffer.rdt === 'T') { - rd = [ { type_: 'text', p1: buffer.rd || "" } ]; - } else { - rd = mhchemParser.go(buffer.rd); - } - /** @type {ParserOutput[]} */ - var rq; - if (buffer.rqt === 'M') { - rq = mhchemParser.go(buffer.rq, 'tex-math'); - } else if (buffer.rqt === 'T') { - rq = [ { type_: 'text', p1: buffer.rq || ""} ]; - } else { - rq = mhchemParser.go(buffer.rq); - } - ret = { - type_: 'arrow', - r: buffer.r, - rd: rd, - rq: rq - }; - } - for (var p in buffer) { - if (p !== 'parenthesisLevel' && p !== 'beginsWithBond') { - delete buffer[p]; - } - } - return ret; - }, - 'oxidation-output': function (buffer, m) { - var ret = [ "{" ]; - mhchemParser.concatArray(ret, mhchemParser.go(m, 'oxidation')); - ret.push("}"); - return ret; - }, - 'frac-output': function (buffer, m) { - return { type_: 'frac-ce', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'overset-output': function (buffer, m) { - return { type_: 'overset', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'underset-output': function (buffer, m) { - return { type_: 'underset', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'underbrace-output': function (buffer, m) { - return { type_: 'underbrace', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'color-output': function (buffer, m) { - return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1]) }; - }, - 'r=': function (buffer, m) { buffer.r = m; }, - 'rdt=': function (buffer, m) { buffer.rdt = m; }, - 'rd=': function (buffer, m) { buffer.rd = m; }, - 'rqt=': function (buffer, m) { buffer.rqt = m; }, - 'rq=': function (buffer, m) { buffer.rq = m; }, - 'operator': function (buffer, m, p1) { return { type_: 'operator', kind_: (p1 || m) }; } - } - }, - 'a': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - '1/2$': { - '0': { action_: '1/2' } }, - 'else': { - '0': { nextState: '1', revisit: true } }, - '$(...)$': { - '*': { action_: 'tex-math tight', nextState: '1' } }, - ',': { - '*': { action_: { type_: 'insert', option: 'commaDecimal' } } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: {} - }, - 'o': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - '1/2$': { - '0': { action_: '1/2' } }, - 'else': { - '0': { nextState: '1', revisit: true } }, - 'letters': { - '*': { action_: 'rm' } }, - '\\ca': { - '*': { action_: { type_: 'insert', option: 'circa' } } }, - '\\x{}{}|\\x{}|\\x': { - '*': { action_: 'copy' } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '{(...)}': { - '*': { action_: '{text}' } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: {} - }, - 'text': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '{...}': { - '*': { action_: 'text=' } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '\\greek': { - '*': { action_: [ 'output', 'rm' ] } }, - '\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: [ 'output', 'copy' ] } }, - 'else': { - '*': { action_: 'text=' } } - }), - actions: { - 'output': function (buffer) { - if (buffer.text_) { - /** @type {ParserOutput} */ - var ret = { type_: 'text', p1: buffer.text_ }; - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - } - }, - 'pq': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - 'state of aggregation $': { - '*': { action_: 'state of aggregation' } }, - 'i$': { - '0': { nextState: '!f', revisit: true } }, - '(KV letters),': { - '0': { action_: 'rm', nextState: '0' } }, - 'formula$': { - '0': { nextState: 'f', revisit: true } }, - '1/2$': { - '0': { action_: '1/2' } }, - 'else': { - '0': { nextState: '!f', revisit: true } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '{(...)}': { - '*': { action_: 'text' } }, - 'a-z': { - 'f': { action_: 'tex-math' } }, - 'letters': { - '*': { action_: 'rm' } }, - '-9.,9': { - '*': { action_: '9,9' } }, - ',': { - '*': { action_: { type_: 'insert+p1', option: 'comma enumeration S' } } }, - '\\color{(...)}{(...)}1|\\color(...){(...)}2': { - '*': { action_: 'color-output' } }, - '\\color{(...)}0': { - '*': { action_: 'color0-output' } }, - '\\ce{(...)}': { - '*': { action_: 'ce' } }, - '\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'copy' } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: { - 'state of aggregation': function (buffer, m) { - return { type_: 'state of aggregation subscript', p1: mhchemParser.go(m, 'o') }; - }, - 'color-output': function (buffer, m) { - return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1], 'pq') }; - } - } - }, - 'bd': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - 'x$': { - '0': { nextState: '!f', revisit: true } }, - 'formula$': { - '0': { nextState: 'f', revisit: true } }, - 'else': { - '0': { nextState: '!f', revisit: true } }, - '-9.,9 no missing 0': { - '*': { action_: '9,9' } }, - '.': { - '*': { action_: { type_: 'insert', option: 'electron dot' } } }, - 'a-z': { - 'f': { action_: 'tex-math' } }, - 'x': { - '*': { action_: { type_: 'insert', option: 'KV x' } } }, - 'letters': { - '*': { action_: 'rm' } }, - '\'': { - '*': { action_: { type_: 'insert', option: 'prime' } } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '{(...)}': { - '*': { action_: 'text' } }, - '\\color{(...)}{(...)}1|\\color(...){(...)}2': { - '*': { action_: 'color-output' } }, - '\\color{(...)}0': { - '*': { action_: 'color0-output' } }, - '\\ce{(...)}': { - '*': { action_: 'ce' } }, - '\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'copy' } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: { - 'color-output': function (buffer, m) { - return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1], 'bd') }; - } - } - }, - 'oxidation': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - 'roman numeral': { - '*': { action_: 'roman-numeral' } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - 'else': { - '*': { action_: 'copy' } } - }), - actions: { - 'roman-numeral': function (buffer, m) { return { type_: 'roman numeral', p1: m || "" }; } - } - }, - 'tex-math': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '\\ce{(...)}': { - '*': { action_: [ 'output', 'ce' ] } }, - '{...}|\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'o=' } }, - 'else': { - '*': { action_: 'o=' } } - }), - actions: { - 'output': function (buffer) { - if (buffer.o) { - /** @type {ParserOutput} */ - var ret = { type_: 'tex-math', p1: buffer.o }; - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - } - }, - 'tex-math tight': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '\\ce{(...)}': { - '*': { action_: [ 'output', 'ce' ] } }, - '{...}|\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'o=' } }, - '-|+': { - '*': { action_: 'tight operator' } }, - 'else': { - '*': { action_: 'o=' } } - }), - actions: { - 'tight operator': function (buffer, m) { buffer.o = (buffer.o || "") + "{"+m+"}"; }, - 'output': function (buffer) { - if (buffer.o) { - /** @type {ParserOutput} */ - var ret = { type_: 'tex-math', p1: buffer.o }; - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - } - }, - '9,9': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - ',': { - '*': { action_: 'comma' } }, - 'else': { - '*': { action_: 'copy' } } - }), - actions: { - 'comma': function () { return { type_: 'commaDecimal' }; } - } - }, - //#endregion - // - // \pu state machines - // - //#region pu - 'pu': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - 'space$': { - '*': { action_: [ 'output', 'space' ] } }, - '{[(|)]}': { - '0|a': { action_: 'copy' } }, - '(-)(9)^(-9)': { - '0': { action_: 'number^', nextState: 'a' } }, - '(-)(9.,9)(e)(99)': { - '0': { action_: 'enumber', nextState: 'a' } }, - 'space': { - '0|a': {} }, - 'pm-operator': { - '0|a': { action_: { type_: 'operator', option: '\\pm' }, nextState: '0' } }, - 'operator': { - '0|a': { action_: 'copy', nextState: '0' } }, - '//': { - 'd': { action_: 'o=', nextState: '/' } }, - '/': { - 'd': { action_: 'o=', nextState: '/' } }, - '{...}|else': { - '0|d': { action_: 'd=', nextState: 'd' }, - 'a': { action_: [ 'space', 'd=' ], nextState: 'd' }, - '/|q': { action_: 'q=', nextState: 'q' } } - }), - actions: { - 'enumber': function (buffer, m) { - /** @type {ParserOutput[]} */ - var ret = []; - if (m[0] === "+-" || m[0] === "+/-") { - ret.push("\\pm "); - } else if (m[0]) { - ret.push(m[0]); - } - if (m[1]) { - mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9')); - if (m[2]) { - if (m[2].match(/[,.]/)) { - mhchemParser.concatArray(ret, mhchemParser.go(m[2], 'pu-9,9')); - } else { - ret.push(m[2]); - } - } - m[3] = m[4] || m[3]; - if (m[3]) { - m[3] = m[3].trim(); - if (m[3] === "e" || m[3].substr(0, 1) === "*") { - ret.push({ type_: 'cdot' }); - } else { - ret.push({ type_: 'times' }); - } - } - } - if (m[3]) { - ret.push("10^{"+m[5]+"}"); - } - return ret; - }, - 'number^': function (buffer, m) { - /** @type {ParserOutput[]} */ - var ret = []; - if (m[0] === "+-" || m[0] === "+/-") { - ret.push("\\pm "); - } else if (m[0]) { - ret.push(m[0]); - } - mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9')); - ret.push("^{"+m[2]+"}"); - return ret; - }, - 'operator': function (buffer, m, p1) { return { type_: 'operator', kind_: (p1 || m) }; }, - 'space': function () { return { type_: 'pu-space-1' }; }, - 'output': function (buffer) { - /** @type {ParserOutput | ParserOutput[]} */ - var ret; - var md = mhchemParser.patterns.match_('{(...)}', buffer.d || ""); - if (md && md.remainder === '') { buffer.d = md.match_; } - var mq = mhchemParser.patterns.match_('{(...)}', buffer.q || ""); - if (mq && mq.remainder === '') { buffer.q = mq.match_; } - if (buffer.d) { - buffer.d = buffer.d.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C"); - buffer.d = buffer.d.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F"); - } - if (buffer.q) { // fraction - buffer.q = buffer.q.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C"); - buffer.q = buffer.q.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F"); - var b5 = { - d: mhchemParser.go(buffer.d, 'pu'), - q: mhchemParser.go(buffer.q, 'pu') - }; - if (buffer.o === '//') { - ret = { type_: 'pu-frac', p1: b5.d, p2: b5.q }; - } else { - ret = b5.d; - if (b5.d.length > 1 || b5.q.length > 1) { - ret.push({ type_: ' / ' }); - } else { - ret.push({ type_: '/' }); - } - mhchemParser.concatArray(ret, b5.q); - } - } else { // no fraction - ret = mhchemParser.go(buffer.d, 'pu-2'); - } - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - }, - 'pu-2': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '*': { - '*': { action_: [ 'output', 'cdot' ], nextState: '0' } }, - '\\x': { - '*': { action_: 'rm=' } }, - 'space': { - '*': { action_: [ 'output', 'space' ], nextState: '0' } }, - '^{(...)}|^(-1)': { - '1': { action_: '^(-1)' } }, - '-9.,9': { - '0': { action_: 'rm=', nextState: '0' }, - '1': { action_: '^(-1)', nextState: '0' } }, - '{...}|else': { - '*': { action_: 'rm=', nextState: '1' } } - }), - actions: { - 'cdot': function () { return { type_: 'tight cdot' }; }, - '^(-1)': function (buffer, m) { buffer.rm += "^{"+m+"}"; }, - 'space': function () { return { type_: 'pu-space-2' }; }, - 'output': function (buffer) { - /** @type {ParserOutput | ParserOutput[]} */ - var ret = []; - if (buffer.rm) { - var mrm = mhchemParser.patterns.match_('{(...)}', buffer.rm || ""); - if (mrm && mrm.remainder === '') { - ret = mhchemParser.go(mrm.match_, 'pu'); - } else { - ret = { type_: 'rm', p1: buffer.rm }; - } - } - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - }, - 'pu-9,9': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '0': { action_: 'output-0' }, - 'o': { action_: 'output-o' } }, - ',': { - '0': { action_: [ 'output-0', 'comma' ], nextState: 'o' } }, - '.': { - '0': { action_: [ 'output-0', 'copy' ], nextState: 'o' } }, - 'else': { - '*': { action_: 'text=' } } - }), - actions: { - 'comma': function () { return { type_: 'commaDecimal' }; }, - 'output-0': function (buffer) { - /** @type {ParserOutput[]} */ - var ret = []; - buffer.text_ = buffer.text_ || ""; - if (buffer.text_.length > 4) { - var a = buffer.text_.length % 3; - if (a === 0) { a = 3; } - for (var i=buffer.text_.length-3; i>0; i-=3) { - ret.push(buffer.text_.substr(i, 3)); - ret.push({ type_: '1000 separator' }); - } - ret.push(buffer.text_.substr(0, a)); - ret.reverse(); - } else { - ret.push(buffer.text_); - } - for (var p in buffer) { delete buffer[p]; } - return ret; - }, - 'output-o': function (buffer) { - /** @type {ParserOutput[]} */ - var ret = []; - buffer.text_ = buffer.text_ || ""; - if (buffer.text_.length > 4) { - var a = buffer.text_.length - 3; - for (var i=0; i, so we change \vphantom{X} to {} - // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed. -// res += "{\\vphantom{X}}"; - res += "{{}}"; - res += "_{\\smash[t]{"+b5.q+"}}"; - } - } else { - if (b5.q) { - // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed. -// res += "{\\vphantom{X}}"; - res += "{{}}"; - res += "_{\\smash[t]{"+b5.q+"}}"; - } - if (b5.d) { - // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed. -// res += "{\\vphantom{X}}"; - res += "{{}}"; - res += "^{"+b5.d+"}"; - } - } - break; - case 'rm': - res = "\\mathrm{"+buf.p1+"}"; - break; - case 'text': - if (buf.p1.match(/[\^_]/)) { - buf.p1 = buf.p1.replace(" ", "~").replace("-", "\\text{-}"); - res = "\\mathrm{"+buf.p1+"}"; - } else { - res = "\\text{"+buf.p1+"}"; - } - break; - case 'roman numeral': - res = "\\mathrm{"+buf.p1+"}"; - break; - case 'state of aggregation': - res = "\\mskip2mu "+texify._goInner(buf.p1); - break; - case 'state of aggregation subscript': - res = "\\mskip1mu "+texify._goInner(buf.p1); - break; - case 'bond': - res = texify._getBond(buf.kind_); - if (!res) { - throw ["MhchemErrorBond", "mhchem Error. Unknown bond type (" + buf.kind_ + ")"]; - } - break; - case 'frac': - var c = "\\frac{" + buf.p1 + "}{" + buf.p2 + "}"; - res = "\\mathchoice{\\textstyle"+c+"}{"+c+"}{"+c+"}{"+c+"}"; - break; - case 'pu-frac': - var d = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - res = "\\mathchoice{\\textstyle"+d+"}{"+d+"}{"+d+"}{"+d+"}"; - break; - case 'tex-math': - res = buf.p1 + " "; - break; - case 'frac-ce': - res = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - break; - case 'overset': - res = "\\overset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - break; - case 'underset': - res = "\\underset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - break; - case 'underbrace': - res = "\\underbrace{" + texify._goInner(buf.p1) + "}_{" + texify._goInner(buf.p2) + "}"; - break; - case 'color': - res = "{\\color{" + buf.color1 + "}{" + texify._goInner(buf.color2) + "}}"; - break; - case 'color0': - res = "\\color{" + buf.color + "}"; - break; - case 'arrow': - var b6 = { - rd: texify._goInner(buf.rd), - rq: texify._goInner(buf.rq) - }; - var arrow = texify._getArrow(buf.r); - if (b6.rq) { arrow += "[{\\rm " + b6.rq + "}]"; } - if (b6.rd) { - arrow += "{\\rm " + b6.rd + "}"; - } else { - arrow += "{}"; - } - res = arrow; - break; - case 'operator': - res = texify._getOperator(buf.kind_); - break; - case '1st-level escape': - res = buf.p1+" "; // &, \\\\, \\hlin - break; - case 'space': - res = " "; - break; - case 'entitySkip': - res = "~"; - break; - case 'pu-space-1': - res = "~"; - break; - case 'pu-space-2': - res = "\\mkern3mu "; - break; - case '1000 separator': - res = "\\mkern2mu "; - break; - case 'commaDecimal': - res = "{,}"; - break; - case 'comma enumeration L': - res = "{"+buf.p1+"}\\mkern6mu "; - break; - case 'comma enumeration M': - res = "{"+buf.p1+"}\\mkern3mu "; - break; - case 'comma enumeration S': - res = "{"+buf.p1+"}\\mkern1mu "; - break; - case 'hyphen': - res = "\\text{-}"; - break; - case 'addition compound': - res = "\\,{\\cdot}\\,"; - break; - case 'electron dot': - res = "\\mkern1mu \\text{\\textbullet}\\mkern1mu "; - break; - case 'KV x': - res = "{\\times}"; - break; - case 'prime': - res = "\\prime "; - break; - case 'cdot': - res = "\\cdot "; - break; - case 'tight cdot': - res = "\\mkern1mu{\\cdot}\\mkern1mu "; - break; - case 'times': - res = "\\times "; - break; - case 'circa': - res = "{\\sim}"; - break; - case '^': - res = "uparrow"; - break; - case 'v': - res = "downarrow"; - break; - case 'ellipsis': - res = "\\ldots "; - break; - case '/': - res = "/"; - break; - case ' / ': - res = "\\,/\\,"; - break; - default: - assertNever(buf); - throw ["MhchemBugT", "mhchem bug T. Please report."]; // Missing texify rule or unknown MhchemParser output - } - assertString(res); - return res; - }, - _getArrow: function (a) { - switch (a) { - case "->": return "\\yields"; - case "\u2192": return "\\yields"; - case "\u27F6": return "\\yields"; - case "<-": return "\\yieldsLeft"; - case "<->": return "\\mesomerism"; - case "<-->": return "\\yieldsLeftRight"; - case "<=>": return "\\equilibrium"; - case "\u21CC": return "\\equilibrium"; - case "<=>>": return "\\equilibriumRight"; - case "<<=>": return "\\equilibriumLeft"; - default: - assertNever(a); - throw ["MhchemBugT", "mhchem bug T. Please report."]; - } - }, - _getBond: function (a) { - switch (a) { - case "-": return "{-}"; - case "1": return "{-}"; - case "=": return "{=}"; - case "2": return "{=}"; - case "#": return "{\\equiv}"; - case "3": return "{\\equiv}"; - case "~": return "{\\tripledash}"; - case "~-": return "{\\mathrlap{\\raise{-.1em}{-}}\\raise{.1em}{\\tripledash}}"; - case "~=": return "{\\mathrlap{\\raise{-.2em}{-}}\\mathrlap{\\raise{.2em}{\\tripledash}}{-}}"; - case "~--": return "{\\mathrlap{\\raise{-.2em}{-}}\\mathrlap{\\raise{.2em}{\\tripledash}}{-}}"; - case "-~-": return "{\\mathrlap{\\raise{-.2em}{-}}\\mathrlap{\\raise{.2em}{-}}\\tripledash}"; - case "...": return "{{\\cdot}{\\cdot}{\\cdot}}"; - case "....": return "{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}"; - case "->": return "{\\rightarrow}"; - case "<-": return "{\\leftarrow}"; - case "<": return "{<}"; - case ">": return "{>}"; - default: - assertNever(a); - throw ["MhchemBugT", "mhchem bug T. Please report."]; - } - }, - _getOperator: function (a) { - switch (a) { - case "+": return " {}+{} "; - case "-": return " {}-{} "; - case "=": return " {}={} "; - case "<": return " {}<{} "; - case ">": return " {}>{} "; - case "<<": return " {}\\ll{} "; - case ">>": return " {}\\gg{} "; - case "\\pm": return " {}\\pm{} "; - case "\\approx": return " {}\\approx{} "; - case "$\\approx$": return " {}\\approx{} "; - case "v": return " \\downarrow{} "; - case "(v)": return " \\downarrow{} "; - case "^": return " \\uparrow{} "; - case "(^)": return " \\uparrow{} "; - default: - assertNever(a); - throw ["MhchemBugT", "mhchem bug T. Please report."]; - } - } - }; - - // - // Helpers for code anaylsis - // Will show type error at calling position - // - /** @param {number} a */ - function assertNever(a) {} - /** @param {string} a */ - function assertString(a) {} - -/* eslint-disable no-undef */ - -////////////////////////////////////////////////////////////////////// -// texvc.sty - -// The texvc package contains macros available in mediawiki pages. -// We omit the functions deprecated at -// https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax - -// We also omit texvc's \O, which conflicts with \text{\O} - -defineMacro("\\darr", "\\downarrow"); -defineMacro("\\dArr", "\\Downarrow"); -defineMacro("\\Darr", "\\Downarrow"); -defineMacro("\\lang", "\\langle"); -defineMacro("\\rang", "\\rangle"); -defineMacro("\\uarr", "\\uparrow"); -defineMacro("\\uArr", "\\Uparrow"); -defineMacro("\\Uarr", "\\Uparrow"); -defineMacro("\\N", "\\mathbb{N}"); -defineMacro("\\R", "\\mathbb{R}"); -defineMacro("\\Z", "\\mathbb{Z}"); -defineMacro("\\alef", "\\aleph"); -defineMacro("\\alefsym", "\\aleph"); -defineMacro("\\bull", "\\bullet"); -defineMacro("\\clubs", "\\clubsuit"); -defineMacro("\\cnums", "\\mathbb{C}"); -defineMacro("\\Complex", "\\mathbb{C}"); -defineMacro("\\Dagger", "\\ddagger"); -defineMacro("\\diamonds", "\\diamondsuit"); -defineMacro("\\empty", "\\emptyset"); -defineMacro("\\exist", "\\exists"); -defineMacro("\\harr", "\\leftrightarrow"); -defineMacro("\\hArr", "\\Leftrightarrow"); -defineMacro("\\Harr", "\\Leftrightarrow"); -defineMacro("\\hearts", "\\heartsuit"); -defineMacro("\\image", "\\Im"); -defineMacro("\\infin", "\\infty"); -defineMacro("\\isin", "\\in"); -defineMacro("\\larr", "\\leftarrow"); -defineMacro("\\lArr", "\\Leftarrow"); -defineMacro("\\Larr", "\\Leftarrow"); -defineMacro("\\lrarr", "\\leftrightarrow"); -defineMacro("\\lrArr", "\\Leftrightarrow"); -defineMacro("\\Lrarr", "\\Leftrightarrow"); -defineMacro("\\natnums", "\\mathbb{N}"); -defineMacro("\\plusmn", "\\pm"); -defineMacro("\\rarr", "\\rightarrow"); -defineMacro("\\rArr", "\\Rightarrow"); -defineMacro("\\Rarr", "\\Rightarrow"); -defineMacro("\\real", "\\Re"); -defineMacro("\\reals", "\\mathbb{R}"); -defineMacro("\\Reals", "\\mathbb{R}"); -defineMacro("\\sdot", "\\cdot"); -defineMacro("\\sect", "\\S"); -defineMacro("\\spades", "\\spadesuit"); -defineMacro("\\sub", "\\subset"); -defineMacro("\\sube", "\\subseteq"); -defineMacro("\\supe", "\\supseteq"); -defineMacro("\\thetasym", "\\vartheta"); -defineMacro("\\weierp", "\\wp"); - -/* eslint-disable no-undef */ - -/**************************************************** - * - * physics.js - * - * Implements the Physics Package for LaTeX input. - * - * --------------------------------------------------------------------- - * - * The original version of this file is licensed as follows: - * Copyright (c) 2015-2016 Kolen Cheung . - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * --------------------------------------------------------------------- - * - * This file has been revised from the original in the following ways: - * 1. The interface is changed so that it can be called from Temml, not MathJax. - * 2. \Re and \Im are not used, to avoid conflict with existing LaTeX letters. - * - * This revision of the file is released under the MIT license. - * https://mit-license.org/ - */ -defineMacro("\\quantity", "{\\left\\{ #1 \\right\\}}"); -defineMacro("\\qty", "{\\left\\{ #1 \\right\\}}"); -defineMacro("\\pqty", "{\\left( #1 \\right)}"); -defineMacro("\\bqty", "{\\left[ #1 \\right]}"); -defineMacro("\\vqty", "{\\left\\vert #1 \\right\\vert}"); -defineMacro("\\Bqty", "{\\left\\{ #1 \\right\\}}"); -defineMacro("\\absolutevalue", "{\\left\\vert #1 \\right\\vert}"); -defineMacro("\\abs", "{\\left\\vert #1 \\right\\vert}"); -defineMacro("\\norm", "{\\left\\Vert #1 \\right\\Vert}"); -defineMacro("\\evaluated", "{\\left.#1 \\right\\vert}"); -defineMacro("\\eval", "{\\left.#1 \\right\\vert}"); -defineMacro("\\order", "{\\mathcal{O} \\left( #1 \\right)}"); -defineMacro("\\commutator", "{\\left[ #1 , #2 \\right]}"); -defineMacro("\\comm", "{\\left[ #1 , #2 \\right]}"); -defineMacro("\\anticommutator", "{\\left\\{ #1 , #2 \\right\\}}"); -defineMacro("\\acomm", "{\\left\\{ #1 , #2 \\right\\}}"); -defineMacro("\\poissonbracket", "{\\left\\{ #1 , #2 \\right\\}}"); -defineMacro("\\pb", "{\\left\\{ #1 , #2 \\right\\}}"); -defineMacro("\\vectorbold", "{\\boldsymbol{ #1 }}"); -defineMacro("\\vb", "{\\boldsymbol{ #1 }}"); -defineMacro("\\vectorarrow", "{\\vec{\\boldsymbol{ #1 }}}"); -defineMacro("\\va", "{\\vec{\\boldsymbol{ #1 }}}"); -defineMacro("\\vectorunit", "{{\\boldsymbol{\\hat{ #1 }}}}"); -defineMacro("\\vu", "{{\\boldsymbol{\\hat{ #1 }}}}"); -defineMacro("\\dotproduct", "\\mathbin{\\boldsymbol\\cdot}"); -defineMacro("\\vdot", "{\\boldsymbol\\cdot}"); -defineMacro("\\crossproduct", "\\mathbin{\\boldsymbol\\times}"); -defineMacro("\\cross", "\\mathbin{\\boldsymbol\\times}"); -defineMacro("\\cp", "\\mathbin{\\boldsymbol\\times}"); -defineMacro("\\gradient", "{\\boldsymbol\\nabla}"); -defineMacro("\\grad", "{\\boldsymbol\\nabla}"); -defineMacro("\\divergence", "{\\grad\\vdot}"); -//defineMacro("\\div", "{\\grad\\vdot}"); Not included in Temml. Conflicts w/LaTeX \div -defineMacro("\\curl", "{\\grad\\cross}"); -defineMacro("\\laplacian", "\\nabla^2"); -defineMacro("\\tr", "{\\operatorname{tr}}"); -defineMacro("\\Tr", "{\\operatorname{Tr}}"); -defineMacro("\\rank", "{\\operatorname{rank}}"); -defineMacro("\\erf", "{\\operatorname{erf}}"); -defineMacro("\\Res", "{\\operatorname{Res}}"); -defineMacro("\\principalvalue", "{\\mathcal{P}}"); -defineMacro("\\pv", "{\\mathcal{P}}"); -defineMacro("\\PV", "{\\operatorname{P.V.}}"); -// Temml does not use the next two lines. They conflict with LaTeX letters. -//defineMacro("\\Re", "{\\operatorname{Re} \\left\\{ #1 \\right\\}}"); -//defineMacro("\\Im", "{\\operatorname{Im} \\left\\{ #1 \\right\\}}"); -defineMacro("\\qqtext", "{\\quad\\text{ #1 }\\quad}"); -defineMacro("\\qq", "{\\quad\\text{ #1 }\\quad}"); -defineMacro("\\qcomma", "{\\text{,}\\quad}"); -defineMacro("\\qc", "{\\text{,}\\quad}"); -defineMacro("\\qcc", "{\\quad\\text{c.c.}\\quad}"); -defineMacro("\\qif", "{\\quad\\text{if}\\quad}"); -defineMacro("\\qthen", "{\\quad\\text{then}\\quad}"); -defineMacro("\\qelse", "{\\quad\\text{else}\\quad}"); -defineMacro("\\qotherwise", "{\\quad\\text{otherwise}\\quad}"); -defineMacro("\\qunless", "{\\quad\\text{unless}\\quad}"); -defineMacro("\\qgiven", "{\\quad\\text{given}\\quad}"); -defineMacro("\\qusing", "{\\quad\\text{using}\\quad}"); -defineMacro("\\qassume", "{\\quad\\text{assume}\\quad}"); -defineMacro("\\qsince", "{\\quad\\text{since}\\quad}"); -defineMacro("\\qlet", "{\\quad\\text{let}\\quad}"); -defineMacro("\\qfor", "{\\quad\\text{for}\\quad}"); -defineMacro("\\qall", "{\\quad\\text{all}\\quad}"); -defineMacro("\\qeven", "{\\quad\\text{even}\\quad}"); -defineMacro("\\qodd", "{\\quad\\text{odd}\\quad}"); -defineMacro("\\qinteger", "{\\quad\\text{integer}\\quad}"); -defineMacro("\\qand", "{\\quad\\text{and}\\quad}"); -defineMacro("\\qor", "{\\quad\\text{or}\\quad}"); -defineMacro("\\qas", "{\\quad\\text{as}\\quad}"); -defineMacro("\\qin", "{\\quad\\text{in}\\quad}"); -defineMacro("\\differential", "{\\text{d}}"); -defineMacro("\\dd", "{\\text{d}}"); -defineMacro("\\derivative", "{\\frac{\\text{d}{ #1 }}{\\text{d}{ #2 }}}"); -defineMacro("\\dv", "{\\frac{\\text{d}{ #1 }}{\\text{d}{ #2 }}}"); -defineMacro("\\partialderivative", "{\\frac{\\partial{ #1 }}{\\partial{ #2 }}}"); -defineMacro("\\variation", "{\\delta}"); -defineMacro("\\var", "{\\delta}"); -defineMacro("\\functionalderivative", "{\\frac{\\delta{ #1 }}{\\delta{ #2 }}}"); -defineMacro("\\fdv", "{\\frac{\\delta{ #1 }}{\\delta{ #2 }}}"); -defineMacro("\\innerproduct", "{\\left\\langle {#1} \\mid { #2} \\right\\rangle}"); -defineMacro("\\outerproduct", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -defineMacro("\\dyad", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -defineMacro("\\ketbra", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -defineMacro("\\op", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -defineMacro("\\expectationvalue", "{\\left\\langle {#1 } \\right\\rangle}"); -defineMacro("\\expval", "{\\left\\langle {#1 } \\right\\rangle}"); -defineMacro("\\ev", "{\\left\\langle {#1 } \\right\\rangle}"); -defineMacro("\\matrixelement", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); -defineMacro("\\matrixel", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); -defineMacro("\\mel", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); - -/** - * This file contains the “gullet” where macros are expanded - * until only non-macro tokens remain. - */ - -// List of commands that act like macros but aren't defined as a macro, -// function, or symbol. Used in `isDefined`. -const implicitCommands = { - "^": true, // Parser.js - _: true, // Parser.js - "\\limits": true, // Parser.js - "\\nolimits": true // Parser.js -}; - -class MacroExpander { - constructor(input, settings, mode) { - this.settings = settings; - this.expansionCount = 0; - this.feed(input); - // Make new global namespace - this.macros = new Namespace(macros, settings.macros); - this.mode = mode; - this.stack = []; // contains tokens in REVERSE order - } - - /** - * Feed a new input string to the same MacroExpander - * (with existing macros etc.). - */ - feed(input) { - this.lexer = new Lexer(input, this.settings); - } - - /** - * Switches between "text" and "math" modes. - */ - switchMode(newMode) { - this.mode = newMode; - } - - /** - * Start a new group nesting within all namespaces. - */ - beginGroup() { - this.macros.beginGroup(); - } - - /** - * End current group nesting within all namespaces. - */ - endGroup() { - this.macros.endGroup(); - } - - /** - * Returns the topmost token on the stack, without expanding it. - * Similar in behavior to TeX's `\futurelet`. - */ - future() { - if (this.stack.length === 0) { - this.pushToken(this.lexer.lex()); - } - return this.stack[this.stack.length - 1] - } - - /** - * Remove and return the next unexpanded token. - */ - popToken() { - this.future(); // ensure non-empty stack - return this.stack.pop(); - } - - /** - * Add a given token to the token stack. In particular, this get be used - * to put back a token returned from one of the other methods. - */ - pushToken(token) { - this.stack.push(token); - } - - /** - * Append an array of tokens to the token stack. - */ - pushTokens(tokens) { - this.stack.push(...tokens); - } - - /** - * Find an macro argument without expanding tokens and append the array of - * tokens to the token stack. Uses Token as a container for the result. - */ - scanArgument(isOptional) { - let start; - let end; - let tokens; - if (isOptional) { - this.consumeSpaces(); // \@ifnextchar gobbles any space following it - if (this.future().text !== "[") { - return null; - } - start = this.popToken(); // don't include [ in tokens - ({ tokens, end } = this.consumeArg(["]"])); - } else { - ({ tokens, start, end } = this.consumeArg()); - } - - // indicate the end of an argument - this.pushToken(new Token("EOF", end.loc)); - - this.pushTokens(tokens); - return start.range(end, ""); - } - - /** - * Consume all following space tokens, without expansion. - */ - consumeSpaces() { - for (;;) { - const token = this.future(); - if (token.text === " ") { - this.stack.pop(); - } else { - break; - } - } - } - - /** - * Consume an argument from the token stream, and return the resulting array - * of tokens and start/end token. - */ - consumeArg(delims) { - // The argument for a delimited parameter is the shortest (possibly - // empty) sequence of tokens with properly nested {...} groups that is - // followed ... by this particular list of non-parameter tokens. - // The argument for an undelimited parameter is the next nonblank - // token, unless that token is ‘{’, when the argument will be the - // entire {...} group that follows. - const tokens = []; - const isDelimited = delims && delims.length > 0; - if (!isDelimited) { - // Ignore spaces between arguments. As the TeXbook says: - // "After you have said ‘\def\row#1#2{...}’, you are allowed to - // put spaces between the arguments (e.g., ‘\row x n’), because - // TeX doesn’t use single spaces as undelimited arguments." - this.consumeSpaces(); - } - const start = this.future(); - let tok; - let depth = 0; - let match = 0; - do { - tok = this.popToken(); - tokens.push(tok); - if (tok.text === "{") { - ++depth; - } else if (tok.text === "}") { - --depth; - if (depth === -1) { - throw new ParseError("Extra }", tok); - } - } else if (tok.text === "EOF") { - throw new ParseError( - "Unexpected end of input in a macro argument" + - ", expected '" + - (delims && isDelimited ? delims[match] : "}") + - "'", - tok - ); - } - if (delims && isDelimited) { - if ((depth === 0 || (depth === 1 && delims[match] === "{")) && tok.text === delims[match]) { - ++match; - if (match === delims.length) { - // don't include delims in tokens - tokens.splice(-match, match); - break; - } - } else { - match = 0; - } - } - } while (depth !== 0 || isDelimited); - // If the argument found ... has the form ‘{}’, - // ... the outermost braces enclosing the argument are removed - if (start.text === "{" && tokens[tokens.length - 1].text === "}") { - tokens.pop(); - tokens.shift(); - } - tokens.reverse(); // to fit in with stack order - return { tokens, start, end: tok }; - } - - /** - * Consume the specified number of (delimited) arguments from the token - * stream and return the resulting array of arguments. - */ - consumeArgs(numArgs, delimiters) { - if (delimiters) { - if (delimiters.length !== numArgs + 1) { - throw new ParseError("The length of delimiters doesn't match the number of args!"); - } - const delims = delimiters[0]; - for (let i = 0; i < delims.length; i++) { - const tok = this.popToken(); - if (delims[i] !== tok.text) { - throw new ParseError("Use of the macro doesn't match its definition", tok); - } - } - } - - const args = []; - for (let i = 0; i < numArgs; i++) { - args.push(this.consumeArg(delimiters && delimiters[i + 1]).tokens); - } - return args; - } - - /** - * Expand the next token only once if possible. - * - * If the token is expanded, the resulting tokens will be pushed onto - * the stack in reverse order and will be returned as an array, - * also in reverse order. - * - * If not, the next token will be returned without removing it - * from the stack. This case can be detected by a `Token` return value - * instead of an `Array` return value. - * - * In either case, the next token will be on the top of the stack, - * or the stack will be empty. - * - * Used to implement `expandAfterFuture` and `expandNextToken`. - * - * If expandableOnly, only expandable tokens are expanded and - * an undefined control sequence results in an error. - */ - expandOnce(expandableOnly) { - const topToken = this.popToken(); - const name = topToken.text; - const expansion = !topToken.noexpand ? this._getExpansion(name) : null; - if (expansion == null || (expandableOnly && expansion.unexpandable)) { - if (expandableOnly && expansion == null && name[0] === "\\" && !this.isDefined(name)) { - throw new ParseError("Undefined control sequence: " + name); - } - this.pushToken(topToken); - return topToken; - } - this.expansionCount++; - if (this.expansionCount > this.settings.maxExpand) { - throw new ParseError( - "Too many expansions: infinite loop or " + "need to increase maxExpand setting" - ); - } - let tokens = expansion.tokens; - const args = this.consumeArgs(expansion.numArgs, expansion.delimiters); - if (expansion.numArgs) { - // paste arguments in place of the placeholders - tokens = tokens.slice(); // make a shallow copy - for (let i = tokens.length - 1; i >= 0; --i) { - let tok = tokens[i]; - if (tok.text === "#") { - if (i === 0) { - throw new ParseError("Incomplete placeholder at end of macro body", tok); - } - tok = tokens[--i]; // next token on stack - if (tok.text === "#") { - // ## → # - tokens.splice(i + 1, 1); // drop first # - } else if (/^[1-9]$/.test(tok.text)) { - // replace the placeholder with the indicated argument - tokens.splice(i, 2, ...args[+tok.text - 1]); - } else { - throw new ParseError("Not a valid argument number", tok); - } - } - } - } - // Concatenate expansion onto top of stack. - this.pushTokens(tokens); - return tokens; - } - - /** - * Expand the next token only once (if possible), and return the resulting - * top token on the stack (without removing anything from the stack). - * Similar in behavior to TeX's `\expandafter\futurelet`. - * Equivalent to expandOnce() followed by future(). - */ - expandAfterFuture() { - this.expandOnce(); - return this.future(); - } - - /** - * Recursively expand first token, then return first non-expandable token. - */ - expandNextToken() { - for (;;) { - const expanded = this.expandOnce(); - // expandOnce returns Token if and only if it's fully expanded. - if (expanded instanceof Token) { - // The token after \noexpand is interpreted as if its meaning were ‘\relax’ - if (expanded.treatAsRelax) { - expanded.text = "\\relax"; - } - return this.stack.pop(); // === expanded - } - } - - // This pathway is impossible. - throw new Error(); // eslint-disable-line no-unreachable - } - - /** - * Fully expand the given macro name and return the resulting list of - * tokens, or return `undefined` if no such macro is defined. - */ - expandMacro(name) { - return this.macros.has(name) ? this.expandTokens([new Token(name)]) : undefined; - } - - /** - * Fully expand the given token stream and return the resulting list of - * tokens. Note that the input tokens are in reverse order, but the - * output tokens are in forward order. - */ - expandTokens(tokens) { - const output = []; - const oldStackLength = this.stack.length; - this.pushTokens(tokens); - while (this.stack.length > oldStackLength) { - const expanded = this.expandOnce(true); // expand only expandable tokens - // expandOnce returns Token if and only if it's fully expanded. - if (expanded instanceof Token) { - if (expanded.treatAsRelax) { - // the expansion of \noexpand is the token itself - expanded.noexpand = false; - expanded.treatAsRelax = false; - } - output.push(this.stack.pop()); - } - } - return output; - } - - /** - * Fully expand the given macro name and return the result as a string, - * or return `undefined` if no such macro is defined. - */ - expandMacroAsText(name) { - const tokens = this.expandMacro(name); - if (tokens) { - return tokens.map((token) => token.text).join(""); - } else { - return tokens; - } - } - - /** - * Returns the expanded macro as a reversed array of tokens and a macro - * argument count. Or returns `null` if no such macro. - */ - _getExpansion(name) { - const definition = this.macros.get(name); - if (definition == null) { - // mainly checking for undefined here - return definition; - } - // If a single character has an associated catcode other than 13 - // (active character), then don't expand it. - if (name.length === 1) { - const catcode = this.lexer.catcodes[name]; - if (catcode != null && catcode !== 13) { - return - } - } - const expansion = typeof definition === "function" ? definition(this) : definition; - if (typeof expansion === "string") { - let numArgs = 0; - if (expansion.indexOf("#") !== -1) { - const stripped = expansion.replace(/##/g, ""); - while (stripped.indexOf("#" + (numArgs + 1)) !== -1) { - ++numArgs; - } - } - const bodyLexer = new Lexer(expansion, this.settings); - const tokens = []; - let tok = bodyLexer.lex(); - while (tok.text !== "EOF") { - tokens.push(tok); - tok = bodyLexer.lex(); - } - tokens.reverse(); // to fit in with stack using push and pop - const expanded = { tokens, numArgs }; - return expanded; - } - - return expansion; - } - - /** - * Determine whether a command is currently "defined" (has some - * functionality), meaning that it's a macro (in the current group), - * a function, a symbol, or one of the special commands listed in - * `implicitCommands`. - */ - isDefined(name) { - return ( - this.macros.has(name) || - Object.prototype.hasOwnProperty.call(functions, name ) || - Object.prototype.hasOwnProperty.call(symbols.math, name ) || - Object.prototype.hasOwnProperty.call(symbols.text, name ) || - Object.prototype.hasOwnProperty.call(implicitCommands, name ) - ); - } - - /** - * Determine whether a command is expandable. - */ - isExpandable(name) { - const macro = this.macros.get(name); - return macro != null - ? typeof macro === "string" || typeof macro === "function" || !macro.unexpandable - : Object.prototype.hasOwnProperty.call(functions, name ) && !functions[name].primitive; - } -} - -/* - * This file defines the Unicode scripts and script families that we - * support. To add new scripts or families, just add a new entry to the - * scriptData array below. Adding scripts to the scriptData array allows - * characters from that script to appear in \text{} environments. - */ - -/** - * Each script or script family has a name and an array of blocks. - * Each block is an array of two numbers which specify the start and - * end points (inclusive) of a block of Unicode codepoints. - -/** - * Unicode block data for the families of scripts we support in \text{}. - * Scripts only need to appear here if they do not have font metrics. - */ -const scriptData = [ - { - // Latin characters beyond the Latin-1 characters we have metrics for. - // Needed for Czech, Hungarian and Turkish text, for example. - name: "latin", - blocks: [ - [0x0100, 0x024f], // Latin Extended-A and Latin Extended-B - [0x0300, 0x036f] // Combining Diacritical marks - ] - }, - { - // The Cyrillic script used by Russian and related languages. - // A Cyrillic subset used to be supported as explicitly defined - // symbols in symbols.js - name: "cyrillic", - blocks: [[0x0400, 0x04ff]] - }, - { - // Armenian - name: "armenian", - blocks: [[0x0530, 0x058f]] - }, - { - // The Brahmic scripts of South and Southeast Asia - // Devanagari (0900–097F) - // Bengali (0980–09FF) - // Gurmukhi (0A00–0A7F) - // Gujarati (0A80–0AFF) - // Oriya (0B00–0B7F) - // Tamil (0B80–0BFF) - // Telugu (0C00–0C7F) - // Kannada (0C80–0CFF) - // Malayalam (0D00–0D7F) - // Sinhala (0D80–0DFF) - // Thai (0E00–0E7F) - // Lao (0E80–0EFF) - // Tibetan (0F00–0FFF) - // Myanmar (1000–109F) - name: "brahmic", - blocks: [[0x0900, 0x109f]] - }, - { - name: "georgian", - blocks: [[0x10a0, 0x10ff]] - }, - { - // Chinese and Japanese. - // The "k" in cjk is for Korean, but we've separated Korean out - name: "cjk", - blocks: [ - [0x3000, 0x30ff], // CJK symbols and punctuation, Hiragana, Katakana - [0x4e00, 0x9faf], // CJK ideograms - [0xff00, 0xff60] // Fullwidth punctuation - // TODO: add halfwidth Katakana and Romanji glyphs - ] - }, - { - // Korean - name: "hangul", - blocks: [[0xac00, 0xd7af]] - } -]; - -/** - * A flattened version of all the supported blocks in a single array. - * This is an optimization to make supportedCodepoint() fast. - */ -const allBlocks = []; -scriptData.forEach((s) => s.blocks.forEach((b) => allBlocks.push(...b))); - -/** - * Given a codepoint, return true if it falls within one of the - * scripts or script families defined above and false otherwise. - * - * Micro benchmarks shows that this is faster than - * /[\u3000-\u30FF\u4E00-\u9FAF\uFF00-\uFF60\uAC00-\uD7AF\u0900-\u109F]/.test() - * in Firefox, Chrome and Node. - */ -function supportedCodepoint(codepoint) { - for (let i = 0; i < allBlocks.length; i += 2) { - if (codepoint >= allBlocks[i] && codepoint <= allBlocks[i + 1]) { - return true; - } - } - return false; -} - -// Mapping of Unicode accent characters to their LaTeX equivalent in text and -// math mode (when they exist). -var unicodeAccents = { - "\u0301": { text: "\\'", math: "\\acute" }, - "\u0300": { text: "\\`", math: "\\grave" }, - "\u0308": { text: '\\"', math: "\\ddot" }, - "\u0303": { text: "\\~", math: "\\tilde" }, - "\u0304": { text: "\\=", math: "\\bar" }, - "\u0306": { text: "\\u", math: "\\breve" }, - "\u030c": { text: "\\v", math: "\\check" }, - "\u0302": { text: "\\^", math: "\\hat" }, - "\u0307": { text: "\\.", math: "\\dot" }, - "\u030a": { text: "\\r", math: "\\mathring" }, - "\u030b": { text: "\\H" }, - '\u0327': { text: '\\c' } -}; - -var unicodeSymbols = { - "á": "á", - "à": "à", - "ä": "ä", - "ǟ": "ǟ", - "ã": "ã", - "ā": "ā", - "ă": "ă", - "ắ": "ắ", - "ằ": "ằ", - "ẵ": "ẵ", - "ǎ": "ǎ", - "â": "â", - "ấ": "ấ", - "ầ": "ầ", - "ẫ": "ẫ", - "ȧ": "ȧ", - "ǡ": "ǡ", - "å": "å", - "ǻ": "ǻ", - "ḃ": "ḃ", - "ć": "ć", - "č": "č", - "ĉ": "ĉ", - "ċ": "ċ", - "ď": "ď", - "ḋ": "ḋ", - "é": "é", - "è": "è", - "ë": "ë", - "ẽ": "ẽ", - "ē": "ē", - "ḗ": "ḗ", - "ḕ": "ḕ", - "ĕ": "ĕ", - "ě": "ě", - "ê": "ê", - "ế": "ế", - "ề": "ề", - "ễ": "ễ", - "ė": "ė", - "ḟ": "ḟ", - "ǵ": "ǵ", - "ḡ": "ḡ", - "ğ": "ğ", - "ǧ": "ǧ", - "ĝ": "ĝ", - "ġ": "ġ", - "ḧ": "ḧ", - "ȟ": "ȟ", - "ĥ": "ĥ", - "ḣ": "ḣ", - "í": "í", - "ì": "ì", - "ï": "ï", - "ḯ": "ḯ", - "ĩ": "ĩ", - "ī": "ī", - "ĭ": "ĭ", - "ǐ": "ǐ", - "î": "î", - "ǰ": "ǰ", - "ĵ": "ĵ", - "ḱ": "ḱ", - "ǩ": "ǩ", - "ĺ": "ĺ", - "ľ": "ľ", - "ḿ": "ḿ", - "ṁ": "ṁ", - "ń": "ń", - "ǹ": "ǹ", - "ñ": "ñ", - "ň": "ň", - "ṅ": "ṅ", - "ó": "ó", - "ò": "ò", - "ö": "ö", - "ȫ": "ȫ", - "õ": "õ", - "ṍ": "ṍ", - "ṏ": "ṏ", - "ȭ": "ȭ", - "ō": "ō", - "ṓ": "ṓ", - "ṑ": "ṑ", - "ŏ": "ŏ", - "ǒ": "ǒ", - "ô": "ô", - "ố": "ố", - "ồ": "ồ", - "ỗ": "ỗ", - "ȯ": "ȯ", - "ȱ": "ȱ", - "ő": "ő", - "ṕ": "ṕ", - "ṗ": "ṗ", - "ŕ": "ŕ", - "ř": "ř", - "ṙ": "ṙ", - "ś": "ś", - "ṥ": "ṥ", - "š": "š", - "ṧ": "ṧ", - "ŝ": "ŝ", - "ṡ": "ṡ", - "ẗ": "ẗ", - "ť": "ť", - "ṫ": "ṫ", - "ú": "ú", - "ù": "ù", - "ü": "ü", - "ǘ": "ǘ", - "ǜ": "ǜ", - "ǖ": "ǖ", - "ǚ": "ǚ", - "ũ": "ũ", - "ṹ": "ṹ", - "ū": "ū", - "ṻ": "ṻ", - "ŭ": "ŭ", - "ǔ": "ǔ", - "û": "û", - "ů": "ů", - "ű": "ű", - "ṽ": "ṽ", - "ẃ": "ẃ", - "ẁ": "ẁ", - "ẅ": "ẅ", - "ŵ": "ŵ", - "ẇ": "ẇ", - "ẘ": "ẘ", - "ẍ": "ẍ", - "ẋ": "ẋ", - "ý": "ý", - "ỳ": "ỳ", - "ÿ": "ÿ", - "ỹ": "ỹ", - "ȳ": "ȳ", - "ŷ": "ŷ", - "ẏ": "ẏ", - "ẙ": "ẙ", - "ź": "ź", - "ž": "ž", - "ẑ": "ẑ", - "ż": "ż", - "Á": "Á", - "À": "À", - "Ä": "Ä", - "Ǟ": "Ǟ", - "Ã": "Ã", - "Ā": "Ā", - "Ă": "Ă", - "Ắ": "Ắ", - "Ằ": "Ằ", - "Ẵ": "Ẵ", - "Ǎ": "Ǎ", - "Â": "Â", - "Ấ": "Ấ", - "Ầ": "Ầ", - "Ẫ": "Ẫ", - "Ȧ": "Ȧ", - "Ǡ": "Ǡ", - "Å": "Å", - "Ǻ": "Ǻ", - "Ḃ": "Ḃ", - "Ć": "Ć", - "Č": "Č", - "Ĉ": "Ĉ", - "Ċ": "Ċ", - "Ď": "Ď", - "Ḋ": "Ḋ", - "É": "É", - "È": "È", - "Ë": "Ë", - "Ẽ": "Ẽ", - "Ē": "Ē", - "Ḗ": "Ḗ", - "Ḕ": "Ḕ", - "Ĕ": "Ĕ", - "Ě": "Ě", - "Ê": "Ê", - "Ế": "Ế", - "Ề": "Ề", - "Ễ": "Ễ", - "Ė": "Ė", - "Ḟ": "Ḟ", - "Ǵ": "Ǵ", - "Ḡ": "Ḡ", - "Ğ": "Ğ", - "Ǧ": "Ǧ", - "Ĝ": "Ĝ", - "Ġ": "Ġ", - "Ḧ": "Ḧ", - "Ȟ": "Ȟ", - "Ĥ": "Ĥ", - "Ḣ": "Ḣ", - "Í": "Í", - "Ì": "Ì", - "Ï": "Ï", - "Ḯ": "Ḯ", - "Ĩ": "Ĩ", - "Ī": "Ī", - "Ĭ": "Ĭ", - "Ǐ": "Ǐ", - "Î": "Î", - "İ": "İ", - "Ĵ": "Ĵ", - "Ḱ": "Ḱ", - "Ǩ": "Ǩ", - "Ĺ": "Ĺ", - "Ľ": "Ľ", - "Ḿ": "Ḿ", - "Ṁ": "Ṁ", - "Ń": "Ń", - "Ǹ": "Ǹ", - "Ñ": "Ñ", - "Ň": "Ň", - "Ṅ": "Ṅ", - "Ó": "Ó", - "Ò": "Ò", - "Ö": "Ö", - "Ȫ": "Ȫ", - "Õ": "Õ", - "Ṍ": "Ṍ", - "Ṏ": "Ṏ", - "Ȭ": "Ȭ", - "Ō": "Ō", - "Ṓ": "Ṓ", - "Ṑ": "Ṑ", - "Ŏ": "Ŏ", - "Ǒ": "Ǒ", - "Ô": "Ô", - "Ố": "Ố", - "Ồ": "Ồ", - "Ỗ": "Ỗ", - "Ȯ": "Ȯ", - "Ȱ": "Ȱ", - "Ő": "Ő", - "Ṕ": "Ṕ", - "Ṗ": "Ṗ", - "Ŕ": "Ŕ", - "Ř": "Ř", - "Ṙ": "Ṙ", - "Ś": "Ś", - "Ṥ": "Ṥ", - "Š": "Š", - "Ṧ": "Ṧ", - "Ŝ": "Ŝ", - "Ṡ": "Ṡ", - "Ť": "Ť", - "Ṫ": "Ṫ", - "Ú": "Ú", - "Ù": "Ù", - "Ü": "Ü", - "Ǘ": "Ǘ", - "Ǜ": "Ǜ", - "Ǖ": "Ǖ", - "Ǚ": "Ǚ", - "Ũ": "Ũ", - "Ṹ": "Ṹ", - "Ū": "Ū", - "Ṻ": "Ṻ", - "Ŭ": "Ŭ", - "Ǔ": "Ǔ", - "Û": "Û", - "Ů": "Ů", - "Ű": "Ű", - "Ṽ": "Ṽ", - "Ẃ": "Ẃ", - "Ẁ": "Ẁ", - "Ẅ": "Ẅ", - "Ŵ": "Ŵ", - "Ẇ": "Ẇ", - "Ẍ": "Ẍ", - "Ẋ": "Ẋ", - "Ý": "Ý", - "Ỳ": "Ỳ", - "Ÿ": "Ÿ", - "Ỹ": "Ỹ", - "Ȳ": "Ȳ", - "Ŷ": "Ŷ", - "Ẏ": "Ẏ", - "Ź": "Ź", - "Ž": "Ž", - "Ẑ": "Ẑ", - "Ż": "Ż", - "ά": "ά", - "ὰ": "ὰ", - "ᾱ": "ᾱ", - "ᾰ": "ᾰ", - "έ": "έ", - "ὲ": "ὲ", - "ή": "ή", - "ὴ": "ὴ", - "ί": "ί", - "ὶ": "ὶ", - "ϊ": "ϊ", - "ΐ": "ΐ", - "ῒ": "ῒ", - "ῑ": "ῑ", - "ῐ": "ῐ", - "ό": "ό", - "ὸ": "ὸ", - "ύ": "ύ", - "ὺ": "ὺ", - "ϋ": "ϋ", - "ΰ": "ΰ", - "ῢ": "ῢ", - "ῡ": "ῡ", - "ῠ": "ῠ", - "ώ": "ώ", - "ὼ": "ὼ", - "Ύ": "Ύ", - "Ὺ": "Ὺ", - "Ϋ": "Ϋ", - "Ῡ": "Ῡ", - "Ῠ": "Ῠ", - "Ώ": "Ώ", - "Ὼ": "Ὼ" -}; - -/* eslint no-constant-condition:0 */ - -const numberRegEx$1 = /^\d[\d.]*$/; // Keep in sync with numberRegEx in symbolsOrd.js - -/** - * This file contains the parser used to parse out a TeX expression from the - * input. Since TeX isn't context-free, standard parsers don't work particularly - * well. - * - * The strategy of this parser is as such: - * - * The main functions (the `.parse...` ones) take a position in the current - * parse string to parse tokens from. The lexer (found in Lexer.js, stored at - * this.gullet.lexer) also supports pulling out tokens at arbitrary places. When - * individual tokens are needed at a position, the lexer is called to pull out a - * token, which is then used. - * - * The parser has a property called "mode" indicating the mode that - * the parser is currently in. Currently it has to be one of "math" or - * "text", which denotes whether the current environment is a math-y - * one or a text-y one (e.g. inside \text). Currently, this serves to - * limit the functions which can be used in text mode. - * - * The main functions then return an object which contains the useful data that - * was parsed at its given point, and a new position at the end of the parsed - * data. The main functions can call each other and continue the parsing by - * using the returned position as a new starting point. - * - * There are also extra `.handle...` functions, which pull out some reused - * functionality into self-contained functions. - * - * The functions return ParseNodes. - */ - -class Parser { - constructor(input, settings, isPreamble = false) { - // Start in math mode - this.mode = "math"; - // Create a new macro expander (gullet) and (indirectly via that) also a - // new lexer (mouth) for this parser (stomach, in the language of TeX) - this.gullet = new MacroExpander(input, settings, this.mode); - // Store the settings for use in parsing - this.settings = settings; - // Are we defining a preamble? - this.isPreamble = isPreamble; - // Count leftright depth (for \middle errors) - this.leftrightDepth = 0; - this.prevAtomType = ""; - } - - /** - * Checks a result to make sure it has the right type, and throws an - * appropriate error otherwise. - */ - expect(text, consume = true) { - if (this.fetch().text !== text) { - throw new ParseError(`Expected '${text}', got '${this.fetch().text}'`, this.fetch()); - } - if (consume) { - this.consume(); - } - } - - /** - * Discards the current lookahead token, considering it consumed. - */ - consume() { - this.nextToken = null; - } - - /** - * Return the current lookahead token, or if there isn't one (at the - * beginning, or if the previous lookahead token was consume()d), - * fetch the next token as the new lookahead token and return it. - */ - fetch() { - if (this.nextToken == null) { - this.nextToken = this.gullet.expandNextToken(); - } - return this.nextToken; - } - - /** - * Switches between "text" and "math" modes. - */ - switchMode(newMode) { - this.mode = newMode; - this.gullet.switchMode(newMode); - } - - /** - * Main parsing function, which parses an entire input. - */ - parse() { - // Create a group namespace for every $...$, $$...$$, \[...\].) - // A \def is then valid only within that pair of delimiters. - this.gullet.beginGroup(); - - if (this.settings.colorIsTextColor) { - // Use old \color behavior (same as LaTeX's \textcolor) if requested. - // We do this within the group for the math expression, so it doesn't - // pollute settings.macros. - this.gullet.macros.set("\\color", "\\textcolor"); - } - - // Try to parse the input - const parse = this.parseExpression(false); - - // If we succeeded, make sure there's an EOF at the end - this.expect("EOF"); - - if (this.isPreamble) { - const macros = Object.create(null); - Object.entries(this.gullet.macros.current).forEach(([key, value]) => { - macros[key] = value; - }); - this.gullet.endGroup(); - return macros - } - - // The only local macro that we want to save is from \tag. - const tag = this.gullet.macros.get("\\df@tag"); - - // End the group namespace for the expression - this.gullet.endGroup(); - - if (tag) { this.gullet.macros.current["\\df@tag"] = tag; } - - return parse; - } - - static get endOfExpression() { - return ["}", "\\endgroup", "\\end", "\\right", "\\endtoggle", "&"]; - } - - /** - * Parses an "expression", which is a list of atoms. - * - * `breakOnInfix`: Should the parsing stop when we hit infix nodes? This - * happens when functions have higher precendence han infix - * nodes in implicit parses. - * - * `breakOnTokenText`: The text of the token that the expression should end - * with, or `null` if something else should end the - * expression. - */ - parseExpression(breakOnInfix, breakOnTokenText) { - const body = []; - // Keep adding atoms to the body until we can't parse any more atoms (either - // we reached the end, a }, or a \right) - while (true) { - // Ignore spaces in math mode - if (this.mode === "math") { - this.consumeSpaces(); - } - const lex = this.fetch(); - if (Parser.endOfExpression.indexOf(lex.text) !== -1) { - break; - } - if (breakOnTokenText && lex.text === breakOnTokenText) { - break; - } - if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) { - break; - } - const atom = this.parseAtom(breakOnTokenText); - if (!atom) { - break; - } else if (atom.type === "internal") { - continue; - } - body.push(atom); - // Keep a record of the atom type, so that op.js can set correct spacing. - this.prevAtomType = atom.type === "atom" ? atom.family : atom.type; - } - if (this.mode === "text") { - this.formLigatures(body); - } - return this.handleInfixNodes(body); - } - - /** - * Rewrites infix operators such as \over with corresponding commands such - * as \frac. - * - * There can only be one infix operator per group. If there's more than one - * then the expression is ambiguous. This can be resolved by adding {}. - */ - handleInfixNodes(body) { - let overIndex = -1; - let funcName; - - for (let i = 0; i < body.length; i++) { - if (body[i].type === "infix") { - if (overIndex !== -1) { - throw new ParseError("only one infix operator per group", body[i].token); - } - overIndex = i; - funcName = body[i].replaceWith; - } - } - - if (overIndex !== -1 && funcName) { - let numerNode; - let denomNode; - - const numerBody = body.slice(0, overIndex); - const denomBody = body.slice(overIndex + 1); - - if (numerBody.length === 1 && numerBody[0].type === "ordgroup") { - numerNode = numerBody[0]; - } else { - numerNode = { type: "ordgroup", mode: this.mode, body: numerBody }; - } - - if (denomBody.length === 1 && denomBody[0].type === "ordgroup") { - denomNode = denomBody[0]; - } else { - denomNode = { type: "ordgroup", mode: this.mode, body: denomBody }; - } - - let node; - if (funcName === "\\\\abovefrac") { - node = this.callFunction(funcName, [numerNode, body[overIndex], denomNode], []); - } else { - node = this.callFunction(funcName, [numerNode, denomNode], []); - } - return [node]; - } else { - return body; - } - } - - /** - * Handle a subscript or superscript with nice errors. - */ - handleSupSubscript( - name // For error reporting. - ) { - const symbolToken = this.fetch(); - const symbol = symbolToken.text; - this.consume(); - this.consumeSpaces(); // ignore spaces before sup/subscript argument - const group = this.parseGroup(name); - - if (!group) { - throw new ParseError("Expected group after '" + symbol + "'", symbolToken); - } - - return group; - } - - /** - * Converts the textual input of an unsupported command into a text node - * contained within a color node whose color is determined by errorColor - */ - formatUnsupportedCmd(text) { - const textordArray = []; - - for (let i = 0; i < text.length; i++) { - textordArray.push({ type: "textord", mode: "text", text: text[i] }); - } - - const textNode = { - type: "text", - mode: this.mode, - body: textordArray - }; - - const colorNode = { - type: "color", - mode: this.mode, - color: this.settings.errorColor, - body: [textNode] - }; - - return colorNode; - } - - /** - * Parses a group with optional super/subscripts. - */ - parseAtom(breakOnTokenText) { - // The body of an atom is an implicit group, so that things like - // \left(x\right)^2 work correctly. - const base = this.parseGroup("atom", breakOnTokenText); - - // In text mode, we don't have superscripts or subscripts - if (this.mode === "text") { - return base; - } - - // Note that base may be empty (i.e. null) at this point. - - let superscript; - let subscript; - while (true) { - // Guaranteed in math mode, so eat any spaces first. - this.consumeSpaces(); - - // Lex the first token - const lex = this.fetch(); - - if (lex.text === "\\limits" || lex.text === "\\nolimits") { - // We got a limit control - if (base && base.type === "op") { - const limits = lex.text === "\\limits"; - base.limits = limits; - base.alwaysHandleSupSub = true; - } else if (base && base.type === "operatorname") { - if (base.alwaysHandleSupSub) { - base.limits = lex.text === "\\limits"; - } - } else { - throw new ParseError("Limit controls must follow a math operator", lex); - } - this.consume(); - } else if (lex.text === "^") { - // We got a superscript start - if (superscript) { - throw new ParseError("Double superscript", lex); - } - superscript = this.handleSupSubscript("superscript"); - } else if (lex.text === "_") { - // We got a subscript start - if (subscript) { - throw new ParseError("Double subscript", lex); - } - subscript = this.handleSupSubscript("subscript"); - } else if (lex.text === "'") { - // We got a prime - if (superscript) { - throw new ParseError("Double superscript", lex); - } - const prime = { type: "textord", mode: this.mode, text: "\\prime" }; - - // Many primes can be grouped together, so we handle this here - const primes = [prime]; - this.consume(); - // Keep lexing tokens until we get something that's not a prime - while (this.fetch().text === "'") { - // For each one, add another prime to the list - primes.push(prime); - this.consume(); - } - // If there's a superscript following the primes, combine that - // superscript in with the primes. - if (this.fetch().text === "^") { - primes.push(this.handleSupSubscript("superscript")); - } - // Put everything into an ordgroup as the superscript - superscript = { type: "ordgroup", mode: this.mode, body: primes }; - } else { - // If it wasn't ^, _, or ', stop parsing super/subscripts - break; - } - } - - if (superscript || subscript) { - if (base && base.type === "multiscript" && !base.postscripts) { - // base is the result of a \prescript function. - // Write the sub- & superscripts into the multiscript element. - base.postscripts = { sup: superscript, sub: subscript }; - return base - } else { - // We got either a superscript or subscript, create a supsub - return { - type: "supsub", - mode: this.mode, - base: base, - sup: superscript, - sub: subscript - } - } - } else { - // Otherwise return the original body - return base; - } - } - - /** - * Parses an entire function, including its base and all of its arguments. - */ - parseFunction( - breakOnTokenText, - name // For determining its context - ) { - const token = this.fetch(); - const func = token.text; - const funcData = functions[func]; - if (!funcData) { - return null; - } - this.consume(); // consume command token - - if (name && name !== "atom" && !funcData.allowedInArgument) { - throw new ParseError( - "Got function '" + func + "' with no arguments" + (name ? " as " + name : ""), - token - ); - } else if (this.mode === "text" && !funcData.allowedInText) { - throw new ParseError("Can't use function '" + func + "' in text mode", token); - } else if (this.mode === "math" && funcData.allowedInMath === false) { - throw new ParseError("Can't use function '" + func + "' in math mode", token); - } - - const prevAtomType = this.prevAtomType; - const { args, optArgs } = this.parseArguments(func, funcData); - this.prevAtomType = prevAtomType; - return this.callFunction(func, args, optArgs, token, breakOnTokenText); - } - - /** - * Call a function handler with a suitable context and arguments. - */ - callFunction(name, args, optArgs, token, breakOnTokenText) { - const context = { - funcName: name, - parser: this, - token, - breakOnTokenText - }; - const func = functions[name]; - if (func && func.handler) { - return func.handler(context, args, optArgs); - } else { - throw new ParseError(`No function handler for ${name}`); - } - } - - /** - * Parses the arguments of a function or environment - */ - parseArguments( - func, // Should look like "\name" or "\begin{name}". - funcData - ) { - const totalArgs = funcData.numArgs + funcData.numOptionalArgs; - if (totalArgs === 0) { - return { args: [], optArgs: [] }; - } - - const args = []; - const optArgs = []; - - for (let i = 0; i < totalArgs; i++) { - let argType = funcData.argTypes && funcData.argTypes[i]; - const isOptional = i < funcData.numOptionalArgs; - - if ( - (funcData.primitive && argType == null) || - // \sqrt expands into primitive if optional argument doesn't exist - (funcData.type === "sqrt" && i === 1 && optArgs[0] == null) - ) { - argType = "primitive"; - } - - const arg = this.parseGroupOfType(`argument to '${func}'`, argType, isOptional); - if (isOptional) { - optArgs.push(arg); - } else if (arg != null) { - args.push(arg); - } else { - // should be unreachable - throw new ParseError("Null argument, please report this as a bug"); - } - } - - return { args, optArgs }; - } - - /** - * Parses a group when the mode is changing. - */ - parseGroupOfType(name, type, optional) { - switch (type) { - case "size": - return this.parseSizeGroup(optional); - case "url": - return this.parseUrlGroup(optional); - case "math": - case "text": - return this.parseArgumentGroup(optional, type); - case "hbox": { - // hbox argument type wraps the argument in the equivalent of - // \hbox, which is like \text but switching to \textstyle size. - const group = this.parseArgumentGroup(optional, "text"); - return group != null - ? { - type: "styling", - mode: group.mode, - body: [group], - scriptLevel: "text" // simulate \textstyle - } - : null; - } - case "raw": { - const token = this.parseStringGroup("raw", optional); - return token != null - ? { - type: "raw", - mode: "text", - string: token.text - } - : null; - } - case "primitive": { - if (optional) { - throw new ParseError("A primitive argument cannot be optional"); - } - const group = this.parseGroup(name); - if (group == null) { - throw new ParseError("Expected group as " + name, this.fetch()); - } - return group; - } - case "original": - case null: - case undefined: - return this.parseArgumentGroup(optional); - default: - throw new ParseError("Unknown group type as " + name, this.fetch()); - } - } - - /** - * Discard any space tokens, fetching the next non-space token. - */ - consumeSpaces() { - while (this.fetch().text === " ") { - this.consume(); - } - } - - /** - * Parses a group, essentially returning the string formed by the - * brace-enclosed tokens plus some position information. - */ - parseStringGroup( - modeName, // Used to describe the mode in error messages. - optional - ) { - const argToken = this.gullet.scanArgument(optional); - if (argToken == null) { - return null; - } - let str = ""; - let nextToken; - while ((nextToken = this.fetch()).text !== "EOF") { - str += nextToken.text; - this.consume(); - } - this.consume(); // consume the end of the argument - argToken.text = str; - return argToken; - } - - /** - * Parses a regex-delimited group: the largest sequence of tokens - * whose concatenated strings match `regex`. Returns the string - * formed by the tokens plus some position information. - */ - parseRegexGroup( - regex, - modeName // Used to describe the mode in error messages. - ) { - const firstToken = this.fetch(); - let lastToken = firstToken; - let str = ""; - let nextToken; - while ((nextToken = this.fetch()).text !== "EOF" && regex.test(str + nextToken.text)) { - lastToken = nextToken; - str += lastToken.text; - this.consume(); - } - if (str === "") { - throw new ParseError("Invalid " + modeName + ": '" + firstToken.text + "'", firstToken); - } - return firstToken.range(lastToken, str); - } - - /** - * Parses a size specification, consisting of magnitude and unit. - */ - parseSizeGroup(optional) { - let res; - let isBlank = false; - // don't expand before parseStringGroup - this.gullet.consumeSpaces(); - if (!optional && this.gullet.future().text !== "{") { - res = this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size"); - } else { - res = this.parseStringGroup("size", optional); - } - if (!res) { - return null; - } - if (!optional && res.text.length === 0) { - // Because we've tested for what is !optional, this block won't - // affect \kern, \hspace, etc. It will capture the mandatory arguments - // to \genfrac and \above. - res.text = "0pt"; // Enable \above{} - isBlank = true; // This is here specifically for \genfrac - } - const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(res.text); - if (!match) { - throw new ParseError("Invalid size: '" + res.text + "'", res); - } - const data = { - number: +(match[1] + match[2]), // sign + magnitude, cast to number - unit: match[3] - }; - if (!validUnit(data)) { - throw new ParseError("Invalid unit: '" + data.unit + "'", res); - } - return { - type: "size", - mode: this.mode, - value: data, - isBlank - }; - } - - /** - * Parses an URL, checking escaped letters and allowed protocols, - * and setting the catcode of % as an active character (as in \hyperref). - */ - parseUrlGroup(optional) { - this.gullet.lexer.setCatcode("%", 13); // active character - this.gullet.lexer.setCatcode("~", 12); // other character - const res = this.parseStringGroup("url", optional); - this.gullet.lexer.setCatcode("%", 14); // comment character - this.gullet.lexer.setCatcode("~", 13); // active character - if (res == null) { - return null; - } - // hyperref package allows backslashes alone in href, but doesn't - // generate valid links in such cases; we interpret this as - // "undefined" behaviour, and keep them as-is. Some browser will - // replace backslashes with forward slashes. - let url = res.text.replace(/\\([#$%&~_^{}])/g, "$1"); - url = res.text.replace(/{\u2044}/g, "/"); - return { - type: "url", - mode: this.mode, - url - }; - } - - /** - * Parses an argument with the mode specified. - */ - parseArgumentGroup(optional, mode) { - const argToken = this.gullet.scanArgument(optional); - if (argToken == null) { - return null; - } - const outerMode = this.mode; - if (mode) { - // Switch to specified mode - this.switchMode(mode); - } - - this.gullet.beginGroup(); - const expression = this.parseExpression(false, "EOF"); - // TODO: find an alternative way to denote the end - this.expect("EOF"); // expect the end of the argument - this.gullet.endGroup(); - const result = { - type: "ordgroup", - mode: this.mode, - loc: argToken.loc, - body: expression - }; - - if (mode) { - // Switch mode back - this.switchMode(outerMode); - } - return result; - } - - /** - * Parses an ordinary group, which is either a single nucleus (like "x") - * or an expression in braces (like "{x+y}") or an implicit group, a group - * that starts at the current position, and ends right before a higher explicit - * group ends, or at EOF. - */ - parseGroup( - name, // For error reporting. - breakOnTokenText - ) { - const firstToken = this.fetch(); - const text = firstToken.text; - - let result; - // Try to parse an open brace or \begingroup - if (text === "{" || text === "\\begingroup" || text === "\\toggle") { - this.consume(); - const groupEnd = text === "{" - ? "}" - : text === "\\begingroup" - ? "\\endgroup" - : "\\endtoggle"; - - this.gullet.beginGroup(); - // If we get a brace, parse an expression - const expression = this.parseExpression(false, groupEnd); - const lastToken = this.fetch(); - this.expect(groupEnd); // Check that we got a matching closing brace - this.gullet.endGroup(); - result = { - type: (lastToken.text === "\\endtoggle" ? "toggle" : "ordgroup"), - mode: this.mode, - loc: SourceLocation.range(firstToken, lastToken), - body: expression, - // A group formed by \begingroup...\endgroup is a semi-simple group - // which doesn't affect spacing in math mode, i.e., is transparent. - // https://tex.stackexchange.com/questions/1930/when-should-one- - // use-begingroup-instead-of-bgroup - semisimple: text === "\\begingroup" || undefined - }; - } else { - // If there exists a function with this name, parse the function. - // Otherwise, just return a nucleus - result = this.parseFunction(breakOnTokenText, name) || this.parseSymbol(); - if (result == null && text[0] === "\\" && - !Object.prototype.hasOwnProperty.call(implicitCommands, text )) { - result = this.formatUnsupportedCmd(text); - this.consume(); - } - } - return result; - } - - /** - * Form ligature-like combinations of characters for text mode. - * This includes inputs like "--", "---", "``" and "''". - * The result will simply replace multiple textord nodes with a single - * character in each value by a single textord node having multiple - * characters in its value. The representation is still ASCII source. - * The group will be modified in place. - */ - formLigatures(group) { - let n = group.length - 1; - for (let i = 0; i < n; ++i) { - const a = group[i]; - const v = a.text; - if (v === "-" && group[i + 1].text === "-") { - if (i + 1 < n && group[i + 2].text === "-") { - group.splice(i, 3, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 2]), - text: "---" - }); - n -= 2; - } else { - group.splice(i, 2, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 1]), - text: "--" - }); - n -= 1; - } - } - if ((v === "'" || v === "`") && group[i + 1].text === v) { - group.splice(i, 2, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 1]), - text: v + v - }); - n -= 1; - } - } - } - - /** - * Parse a single symbol out of the string. Here, we handle single character - * symbols and special functions like \verb. - */ - parseSymbol() { - const nucleus = this.fetch(); - let text = nucleus.text; - - if (/^\\verb[^a-zA-Z]/.test(text)) { - this.consume(); - let arg = text.slice(5); - const star = arg.charAt(0) === "*"; - if (star) { - arg = arg.slice(1); - } - // Lexer's tokenRegex is constructed to always have matching - // first/last characters. - if (arg.length < 2 || arg.charAt(0) !== arg.slice(-1)) { - throw new ParseError(`\\verb assertion failed -- - please report what input caused this bug`); - } - arg = arg.slice(1, -1); // remove first and last char - return { - type: "verb", - mode: "text", - body: arg, - star - }; - } - // At this point, we should have a symbol, possibly with accents. - // First expand any accented base symbol according to unicodeSymbols. - if (Object.prototype.hasOwnProperty.call(unicodeSymbols, text[0] ) && - !symbols[this.mode][text[0]]) { - // This behavior is not strict (XeTeX-compatible) in math mode. - if (this.settings.strict && this.mode === "math") { - this.settings.reportNonstrict( - "unicodeTextInMathMode", - `Accented Unicode text character "${text[0]}" used in ` + `math mode`, - nucleus - ); - } - text = unicodeSymbols[text[0]] + text.substr(1); - } - // Strip off any combining characters - const match = combiningDiacriticalMarksEndRegex.exec(text); - if (match) { - text = text.substring(0, match.index); - if (text === "i") { - text = "\u0131"; // dotless i, in math and text mode - } else if (text === "j") { - text = "\u0237"; // dotless j, in math and text mode - } - } - // Recognize base symbol - let symbol; - if (symbols[this.mode][text]) { - const group = symbols[this.mode][text].group; - const loc = SourceLocation.range(nucleus); - let s; - if (Object.prototype.hasOwnProperty.call(ATOMS, group )) { - const family = group; - s = { - type: "atom", - mode: this.mode, - family, - loc, - text - }; - } else { - s = { - type: group, - mode: this.mode, - loc, - text - }; - } - symbol = s; - } else if (!this.strict && numberRegEx$1.test(text)) { - // A number. Wrap in a - this.consume(); - return { - type: "textord", - mode: "math", - loc: SourceLocation.range(nucleus), - text - } - } else if (text.charCodeAt(0) >= 0x80) { - // no symbol for e.g. ^ - if (this.settings.strict) { - if (!supportedCodepoint(text.charCodeAt(0))) { - this.settings.reportNonstrict( - "unknownSymbol", - `Unrecognized Unicode character "${text[0]}"` + ` (${text.charCodeAt(0)})`, - nucleus - ); - } else if (this.mode === "math") { - this.settings.reportNonstrict( - "unicodeTextInMathMode", - `Unicode text character "${text[0]}" used in math mode`, - nucleus - ); - } - } - // All nonmathematical Unicode characters are rendered as if they - // are in text mode (wrapped in \text) because that's what it - // takes to render them in LaTeX. - symbol = { - type: "textord", - mode: "text", - loc: SourceLocation.range(nucleus), - text - }; - } else { - return null; // EOF, ^, _, {, }, etc. - } - this.consume(); - // Transform combining characters into accents - if (match) { - for (let i = 0; i < match[0].length; i++) { - const accent = match[0][i]; - if (!unicodeAccents[accent]) { - throw new ParseError(`Unknown accent ' ${accent}'`, nucleus); - } - const command = unicodeAccents[accent][this.mode] || - unicodeAccents[accent].text; - if (!command) { - throw new ParseError(`Accent ${accent} unsupported in ${this.mode} mode`, nucleus); - } - symbol = { - type: "accent", - mode: this.mode, - loc: SourceLocation.range(nucleus), - label: command, - isStretchy: false, - isShifty: true, - base: symbol - }; - } - } - return symbol; - } -} - -/** - * Parses an expression using a Parser, then returns the parsed result. - */ -const parseTree = function(toParse, settings) { - if (!(typeof toParse === "string" || toParse instanceof String)) { - throw new TypeError("Temml can only parse string typed expression") - } - const parser = new Parser(toParse, settings); - // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors - delete parser.gullet.macros.current["\\df@tag"]; - - let tree = parser.parse(); - - // LaTeX ignores a \tag placed outside an AMS environment. - if (!(tree.length > 0 && tree[0].type && tree[0].type === "array" && tree[0].addEqnNum)) { - // If the input used \tag, it will set the \df@tag macro to the tag. - // In this case, we separately parse the tag and wrap the tree. - if (parser.gullet.macros.get("\\df@tag")) { - if (!settings.displayMode) { - throw new ParseError("\\tag works only in display equations") - } - parser.gullet.feed("\\df@tag"); - tree = [ - { - type: "tag", - mode: "text", - body: tree, - tag: parser.parse() - } - ]; - } - } - - return tree -}; - -/** - * This file contains information about the style that the Parser carries - * around with it while parsing. Data is held in an `Style` object, and when - * recursing, a new `Style` object can be created with the `.with*` functions. - */ - -const subOrSupLevel = [2, 2, 3, 3]; - -/** - * This is the main Style class. It contains the current style.level, color, and font. - * - * Style objects should not be modified. To create a new Style with - * different properties, call a `.with*` method. - */ -class Style { - constructor(data) { - // Style.level can be 0 | 1 | 2 | 3, which correspond to - // displaystyle, textstyle, scriptstyle, and scriptscriptstyle. - // style.level does not directly set MathML's script level. MathML does that itself. - // We use style.level to track, not set, math style so that we can get the - // correct scriptlevel when needed in supsub.js, mathchoice.js, or for dimensions in em. - this.level = data.level; - this.color = data.color; // string | void - // A font family applies to a group of fonts (i.e. SansSerif), while a font - // represents a specific font (i.e. SansSerif Bold). - // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm - this.font = data.font || ""; // string - this.fontFamily = data.fontFamily || ""; // string - this.fontWeight = data.fontWeight || ""; - this.fontShape = data.fontShape || ""; - this.maxSize = data.maxSize; // number - } - - /** - * Returns a new style object with the same properties as "this". Properties - * from "extension" will be copied to the new style object. - */ - extend(extension) { - const data = { - level: this.level, - color: this.color, - font: this.font, - fontFamily: this.fontFamily, - fontWeight: this.fontWeight, - fontShape: this.fontShape, - maxSize: this.maxSize - }; - - for (const key in extension) { - if (Object.prototype.hasOwnProperty.call(extension, key)) { - data[key] = extension[key]; - } - } - - return new Style(data); - } - - withLevel(n) { - return this.extend({ - level: n - }); - } - - incrementLevel() { - return this.extend({ - level: Math.min(this.level + 1, 3) - }); - } - - inSubOrSup() { - return this.extend({ - level: subOrSupLevel[this.level] - }) - } - - /** - * Create a new style object with the given color. - */ - withColor(color) { - return this.extend({ - color: color - }); - } - - /** - * Creates a new style object with the given math font or old text font. - * @type {[type]} - */ - withFont(font) { - return this.extend({ - font - }); - } - - /** - * Create a new style objects with the given fontFamily. - */ - withTextFontFamily(fontFamily) { - return this.extend({ - fontFamily, - font: "" - }); - } - - /** - * Creates a new style object with the given font weight - */ - withTextFontWeight(fontWeight) { - return this.extend({ - fontWeight, - font: "" - }); - } - - /** - * Creates a new style object with the given font weight - */ - withTextFontShape(fontShape) { - return this.extend({ - fontShape, - font: "" - }); - } - - /** - * Gets the CSS color of the current style object - */ - getColor() { - return this.color; - } -} - -/* Temml Post Process - * Perform two tasks not done by Temml when it created each individual Temml element. - * Given a block of block, - * 1. At each AMS auto-numbered environment, assign an id. - * 2. Populate the text contents of each \ref & \eqref - * - * As with other Temml code, this file is released under terms of the MIT license. - * https://mit-license.org/ - */ - -const version = "0.4.2"; - -function postProcess(block) { - const labelMap = {}; - let i = 0; - - // Get a collection of the parents of each \tag & auto-numbered equation - const parents = block.getElementsByClassName("tml-tageqn"); - for (const parent of parents) { - const eqns = parent.getElementsByClassName("tml-eqn"); - if (eqns. length > 0 ) { - // AMS automatically numbered equation. - // Assign an id. - i += 1; - eqns[0].id = "tml-eqn-" + i; - // No need to write a number into the text content of the element. - // A CSS counter does that even if this postProcess() function is not used. - } - // If there is a \label, add it to labelMap - const labels = parent.getElementsByClassName("tml-label"); - if (labels.length === 0) { continue } - if (eqns.length > 0) { - labelMap[labels[0].id] = String(i); - } else { - const tags = parent.getElementsByClassName("tml-tag"); - if (tags.length > 0) { - labelMap[labels[0].id] = tags[0].textContent; - } - } - } - - // Populate \ref & \eqref text content - const refs = block.getElementsByClassName("tml-ref"); - [...refs].forEach(ref => { - let str = labelMap[ref.getAttribute("href").slice(1)]; - if (ref.className.indexOf("tml-eqref") === -1) { - // \ref. Omit parens. - str = str.replace(/^\(/, ""); - str = str.replace(/\($/, ""); - } { - // \eqref. Include parens - if (str.charAt(0) !== "(") { str = "(" + str; } - if (str.slice(-1) !== ")") { str = str + ")"; } - } - ref.textContent = str; - }); -} - -/* eslint no-console:0 */ - -/** - * Parse and build an expression, and place that expression in the DOM node - * given. - */ -let render = function(expression, baseNode, options) { - baseNode.textContent = ""; - const math = renderToMathMLTree(expression, options); - if (options.elementIsMath) { - // The element already exists. Populate it. - baseNode.textContent = ""; - math.children.forEach(e => { baseNode.appendChild(e.toNode()); }); - } else { - baseNode.appendChild(math.toNode()); - } -}; - -// Temml's styles don't work properly in quirks mode. Print out an error, and -// disable rendering. -if (typeof document !== "undefined") { - if (document.compatMode !== "CSS1Compat") { - typeof console !== "undefined" && - console.warn( - "Warning: Temml doesn't work in quirks mode. Make sure your " + - "website has a suitable doctype." - ); - - render = function() { - throw new ParseError("Temml doesn't work in quirks mode."); - }; - } -} - -/** - * Parse and build an expression, and return the markup for that. - */ -const renderToString = function(expression, options) { - const markup = renderToMathMLTree(expression, options).toMarkup(); - return markup; -}; - -/** - * Parse an expression and return the parse tree. - */ -const generateParseTree = function(expression, options) { - const settings = new Settings(options); - return parseTree(expression, settings); -}; - -/** - * Take an expression which contains a preamble. - * Parse it and return the macros. - */ -const definePreamble = function(expression, options) { - const settings = new Settings(options); - settings.macros = {}; - if (!(typeof expression === "string" || expression instanceof String)) { - throw new TypeError("Temml can only parse string typed expression") - } - const parser = new Parser(expression, settings, true); - // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors - delete parser.gullet.macros.current["\\df@tag"]; - const macros = parser.parse(); - return macros -}; - -/** - * If the given error is a Temml ParseError, - * renders the invalid LaTeX as a span with hover title giving the Temml - * error message. Otherwise, simply throws the error. - */ -const renderError = function(error, expression, options) { - if (options.throwOnError || !(error instanceof ParseError)) { - throw error; - } - const node = new Span(["temml-error"], [new TextNode(expression)]); - node.setAttribute("title", error.toString()); - node.setAttribute("style", `color:${options.errorColor}`); - return node; -}; - -/** - * Generates and returns the Temml build tree. This is used for advanced - * use cases (like rendering to custom output). - */ -const renderToMathMLTree = function(expression, options) { - const settings = new Settings(options); - try { - const tree = parseTree(expression, settings); - const style = new Style({ - level: settings.displayMode ? StyleLevel.DISPLAY : StyleLevel.TEXT, - maxSize: settings.maxSize - }); - return buildMathML(tree, expression, style, settings); - } catch (error) { - return renderError(error, expression, settings); - } -}; - -var temml = { - /** - * Current Temml version - */ - version: version, - /** - * Renders the given LaTeX into MathML, and adds - * it as a child to the specified DOM node. - */ - render, - /** - * Renders the given LaTeX into MathML string, - * for sending to the client. - */ - renderToString, - /** - * Post-process an entire HTML block. - * Writes AMS auto-numbers and implements \ref{}. - * Typcally called once, after a loop has rendered many individual spans. - */ - postProcess, - /** - * Temml error, usually during parsing. - */ - ParseError, - /** - * Creates a set of macros with document-wide scope. - */ - definePreamble, - /** - * Parses the given LaTeX into Temml's internal parse tree structure, - * without rendering to HTML or MathML. - * - * NOTE: This method is not currently recommended for public use. - * The internal tree representation is unstable and is very likely - * to change. Use at your own risk. - */ - __parse: generateParseTree, - /** - * Renders the given LaTeX into a MathML internal DOM tree - * representation, without flattening that representation to a string. - * - * NOTE: This method is not currently recommended for public use. - * The internal tree representation is unstable and is very likely - * to change. Use at your own risk. - */ - __renderToMathMLTree: renderToMathMLTree, - /** - * adds a new symbol to builtin symbols table - */ - __defineSymbol: defineSymbol, - /** - * adds a new macro to builtin macro list - */ - __defineMacro: defineMacro -}; - -module.exports = temml; diff --git a/utils/temml.mjs b/utils/temml.mjs deleted file mode 100644 index 66eb508a..00000000 --- a/utils/temml.mjs +++ /dev/null @@ -1,13099 +0,0 @@ -/** - * This is the ParseError class, which is the main error thrown by Temml - * functions when something has gone wrong. This is used to distinguish internal - * errors from errors in the expression that the user provided. - * - * If possible, a caller should provide a Token or ParseNode with information - * about where in the source string the problem occurred. - */ -class ParseError { - constructor( - message, // The error message - token // An object providing position information - ) { - let error = " " + message; - let start; - - const loc = token && token.loc; - if (loc && loc.start <= loc.end) { - // If we have the input and a position, make the error a bit fancier - - // Get the input - const input = loc.lexer.input; - - // Prepend some information - start = loc.start; - const end = loc.end; - if (start === input.length) { - error += " at end of input: "; - } else { - error += " at position " + (start + 1) + ": "; - } - - // Underline token in question using combining underscores - const underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332"); - - // Extract some context from the input and add it to the error - let left; - if (start > 15) { - left = "…" + input.slice(start - 15, start); - } else { - left = input.slice(0, start); - } - let right; - if (end + 15 < input.length) { - right = input.slice(end, end + 15) + "…"; - } else { - right = input.slice(end); - } - error += left + underlined + right; - } - - // Some hackery to make ParseError a prototype of Error - // See http://stackoverflow.com/a/8460753 - const self = new Error(error); - self.name = "ParseError"; - self.__proto__ = ParseError.prototype; - self.position = start; - return self; - } -} - -ParseError.prototype.__proto__ = Error.prototype; - -// -/** - * This file contains a list of utility functions which are useful in other - * files. - */ - -/** - * Return whether an element is contained in a list - */ -const contains = function(list, elem) { - return list.indexOf(elem) !== -1; -}; - -/** - * Provide a default value if a setting is undefined - */ -const deflt = function(setting, defaultIfUndefined) { - return setting === undefined ? defaultIfUndefined : setting; -}; - -// hyphenate and escape adapted from Facebook's React under Apache 2 license - -const uppercase = /([A-Z])/g; -const hyphenate = function(str) { - return str.replace(uppercase, "-$1").toLowerCase(); -}; - -const ESCAPE_LOOKUP = { - "&": "&", - ">": ">", - "<": "<", - '"': """, - "'": "'" -}; - -const ESCAPE_REGEX = /[&><"']/g; - -/** - * Escapes text to prevent scripting attacks. - */ -function escape(text) { - return String(text).replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]); -} - -/** - * Sometimes we want to pull out the innermost element of a group. In most - * cases, this will just be the group itself, but when ordgroups and colors have - * a single element, we want to pull that out. - */ -const getBaseElem = function(group) { - if (group.type === "ordgroup") { - if (group.body.length === 1) { - return getBaseElem(group.body[0]); - } else { - return group; - } - } else if (group.type === "color") { - if (group.body.length === 1) { - return getBaseElem(group.body[0]); - } else { - return group; - } - } else if (group.type === "font") { - return getBaseElem(group.body); - } else { - return group; - } -}; - -/** - * TeXbook algorithms often reference "character boxes", which are simply groups - * with a single character in them. To decide if something is a character box, - * we find its innermost group, and see if it is a single character. - */ -const isCharacterBox = function(group) { - const baseElem = getBaseElem(group); - - // These are all the types of groups which hold single characters - return baseElem.type === "mathord" || baseElem.type === "textord" || baseElem.type === "atom" -}; - -const assert = function(value) { - if (!value) { - throw new Error("Expected non-null, but got " + String(value)); - } - return value; -}; - -/** - * Return the protocol of a URL, or "_relative" if the URL does not specify a - * protocol (and thus is relative). - */ -const protocolFromUrl = function(url) { - const protocol = /^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(url); - return protocol != null ? protocol[1] : "_relative"; -}; - -/** - * Round `n` to 4 decimal places, or to the nearest 1/10,000th em. The TeXbook - * gives an acceptable rounding error of 100sp (which would be the nearest - * 1/6551.6em with our ptPerEm = 10): - * http://www.ctex.org/documents/shredder/src/texbook.pdf#page=69 - */ -const round = function(n) { - return +n.toFixed(4); -}; - -const consolidateText = mrow => { - // If possible, consolidate adjacent elements into a single element. - if (mrow.type !== "mrow") { return mrow } - if (mrow.children.length === 0) { return mrow } // empty group, e.g., \text{} - const mtext = mrow.children[0]; - if (!mtext.attributes || mtext.type !== "mtext") { return mrow } - const variant = mtext.attributes.mathvariant || ""; - for (let i = 1; i < mrow.children.length; i++) { - // Check each child and, if possible, copy the character into child[0]. - const localVariant = mrow.children[i].attributes.mathvariant || ""; - if (mrow.children[i].type === "mrow") { - const childRow = mrow.children[i]; - for (let j = 0; j < childRow.children.length; j++) { - // We'll also check the children of a mrow. One level only. No recursion. - const childVariant = childRow.children[j].attributes.mathvariant || ""; - if (childVariant !== variant || childRow.children[j].type !== "mtext") { - return mrow // At least one element cannot be consolidated. Get out. - } else { - mtext.children[0].text += childRow.children[j].children[0].text; - } - } - } else if (localVariant !== variant || mrow.children[i].type !== "mtext") { - return mrow - } else { - mtext.children[0].text += mrow.children[i].children[0].text; - } - } - // Since we have gotten here, the text has been loaded into a single mtext node. - // Next, consolidate the children into a single element. - mtext.children.splice(1, mtext.children.length - 1); - // Firefox does not render a space at either end of an string. - // To get proper rendering, we replace leading or trailing spaces with no-break spaces. - if (mtext.children[0].text.charAt(0) === " ") { - mtext.children[0].text = "\u00a0" + mtext.children[0].text.slice(1); - } - const L = mtext.children[0].text.length; - if (L > 0 && mtext.children[0].text.charAt(L - 1) === " ") { - mtext.children[0].text = mtext.children[0].text.slice(0, -1) + "\u00a0"; - } - return mtext -}; - -var utils = { - contains, - deflt, - escape, - hyphenate, - getBaseElem, - isCharacterBox, - protocolFromUrl, - round, - consolidateText -}; - -/** - * This is a module for storing settings passed into Temml. It correctly handles - * default settings. - */ - -/** - * The main Settings object - */ -class Settings { - constructor(options) { - // allow null options - options = options || {}; - this.displayMode = utils.deflt(options.displayMode, false); // boolean - this.annotate = utils.deflt(options.annotate, false); // boolean - this.elementIsMath = utils.deflt(options.elementIsMath, false); // boolean - this.leqno = utils.deflt(options.leqno, false); // boolean - this.errorColor = utils.deflt(options.errorColor, "#b22222"); // string - this.preventTagLap = utils.deflt(options.preventTagLap, false); // boolean - this.macros = options.macros || {}; - this.xml = utils.deflt(options.xml, false); // boolean - this.colorIsTextColor = utils.deflt(options.colorIsTextColor, false); // booelean - this.strict = utils.deflt(options.strict, false); // boolean - this.trust = utils.deflt(options.trust, false); // trust context. See html.js. - this.maxSize = (options.maxSize === undefined - ? [Infinity, Infinity] - : Array.isArray(options.maxSize) - ? options.maxSize - : [Infinity, Infinity] - ); - this.maxExpand = Math.max(0, utils.deflt(options.maxExpand, 1000)); // number - } - - /** - * Check whether to test potentially dangerous input, and return - * `true` (trusted) or `false` (untrusted). The sole argument `context` - * should be an object with `command` field specifying the relevant LaTeX - * command (as a string starting with `\`), and any other arguments, etc. - * If `context` has a `url` field, a `protocol` field will automatically - * get added by this function (changing the specified object). - */ - isTrusted(context) { - if (context.url && !context.protocol) { - context.protocol = utils.protocolFromUrl(context.url); - } - const trust = typeof this.trust === "function" ? this.trust(context) : this.trust; - return Boolean(trust); - } -} - -/** - * All registered functions. - * `functions.js` just exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary. - */ -const _functions = {}; - -/** - * All MathML builders. Should be only used in the `define*` and the `build*ML` - * functions. - */ -const _mathmlGroupBuilders = {}; - -function defineFunction({ - type, - names, - props, - handler, - mathmlBuilder -}) { - // Set default values of functions - const data = { - type, - numArgs: props.numArgs, - argTypes: props.argTypes, - allowedInArgument: !!props.allowedInArgument, - allowedInText: !!props.allowedInText, - allowedInMath: props.allowedInMath === undefined ? true : props.allowedInMath, - numOptionalArgs: props.numOptionalArgs || 0, - infix: !!props.infix, - primitive: !!props.primitive, - handler: handler - }; - for (let i = 0; i < names.length; ++i) { - _functions[names[i]] = data; - } - if (type) { - if (mathmlBuilder) { - _mathmlGroupBuilders[type] = mathmlBuilder; - } - } -} - -/** - * Use this to register only the MathML builder for a function(e.g. - * if the function's ParseNode is generated in Parser.js rather than via a - * stand-alone handler provided to `defineFunction`). - */ -function defineFunctionBuilders({ type, mathmlBuilder }) { - defineFunction({ - type, - names: [], - props: { numArgs: 0 }, - handler() { - throw new Error("Should never be called.") - }, - mathmlBuilder - }); -} - -const normalizeArgument = function(arg) { - return arg.type === "ordgroup" && arg.body.length === 1 ? arg.body[0] : arg -}; - -// Since the corresponding buildMathML function expects a -// list of elements, we normalize for different kinds of arguments -const ordargument = function(arg) { - return arg.type === "ordgroup" ? arg.body : [arg] -}; - -/** - * This node represents a document fragment, which contains elements, but when - * placed into the DOM doesn't have any representation itself. It only contains - * children and doesn't have any DOM node properties. - */ -class DocumentFragment { - constructor(children) { - this.children = children; - this.classes = []; - this.style = {}; - } - - hasClass(className) { - return utils.contains(this.classes, className); - } - - /** Convert the fragment into a node. */ - toNode() { - const frag = document.createDocumentFragment(); - - for (let i = 0; i < this.children.length; i++) { - frag.appendChild(this.children[i].toNode()); - } - - return frag; - } - - /** Convert the fragment into HTML markup. */ - toMarkup() { - let markup = ""; - - // Simply concatenate the markup for the children together. - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - return markup; - } - - /** - * Converts the math node into a string, similar to innerText. Applies to - * MathDomNode's only. - */ - toText() { - // To avoid this, we would subclass documentFragment separately for - // MathML, but polyfills for subclassing is expensive per PR 1469. - const toText = (child) => child.toText(); - return this.children.map(toText).join(""); - } -} - -/** - * These objects store the data about the DOM nodes we create, as well as some - * extra data. They can then be transformed into real DOM nodes with the - * `toNode` function or HTML markup using `toMarkup`. They are useful for both - * storing extra properties on the nodes, as well as providing a way to easily - * work with the DOM. - * - * Similar functions for working with MathML nodes exist in mathMLTree.js. - * - */ - -/** - * Create an HTML className based on a list of classes. In addition to joining - * with spaces, we also remove empty classes. - */ -const createClass = function(classes) { - return classes.filter((cls) => cls).join(" "); -}; - -const initNode = function(classes, style) { - this.classes = classes || []; - this.attributes = {}; - this.style = style || {}; -}; - -/** - * Convert into an HTML node - */ -const toNode = function(tagName) { - const node = document.createElement(tagName); - - // Apply the class - node.className = createClass(this.classes); - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - // Apply attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr )) { - node.setAttribute(attr, this.attributes[attr]); - } - } - - // Append the children, also as HTML nodes - for (let i = 0; i < this.children.length; i++) { - node.appendChild(this.children[i].toNode()); - } - - return node; -}; - -/** - * Convert into an HTML markup string - */ -const toMarkup = function(tagName) { - let markup = `<${tagName}`; - - // Add the class - if (this.classes.length) { - markup += ` class="${utils.escape(createClass(this.classes))}"`; - } - - let styles = ""; - - // Add the styles, after hyphenation - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - styles += `${utils.hyphenate(style)}:${this.style[style]};`; - } - } - - if (styles) { - markup += ` style="${styles}"`; - } - - // Add the attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr )) { - markup += ` ${attr}="${utils.escape(this.attributes[attr])}"`; - } - } - - markup += ">"; - - // Add the markup of the children, also as markup - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - markup += ``; - - return markup; -}; - -/** - * This node represents a span node, with a className, a list of children, and - * an inline style. - * - */ -class Span { - constructor(classes, children, style) { - initNode.call(this, classes, style); - this.children = children || []; - } - - setAttribute(attribute, value) { - this.attributes[attribute] = value; - } - - toNode() { - return toNode.call(this, "span"); - } - - toMarkup() { - return toMarkup.call(this, "span"); - } -} - -class TextNode$1 { - constructor(text) { - this.text = text; - } - toNode() { - return document.createTextNode(this.text); - } - toMarkup() { - return utils.escape(this.text); - } -} - -/** - * This node represents an image embed () element. - */ -class Img { - constructor(src, alt, style) { - this.alt = alt; - this.src = src; - this.classes = ["mord"]; - this.style = style; - } - - hasClass(className) { - return utils.contains(this.classes, className); - } - - toNode() { - const node = document.createElement("img"); - node.src = this.src; - node.alt = this.alt; - node.className = "mord"; - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - return node; - } - - toMarkup() { - let markup = `${this.alt}` and - * `` tags). - */ -class MathNode { - constructor(type, children, classes, style) { - this.type = type; - this.attributes = {}; - this.children = children || []; - this.classes = classes || []; - this.style = style || {}; // Used for elements - } - - /** - * Sets an attribute on a MathML node. MathML depends on attributes to convey a - * semantic content, so this is used heavily. - */ - setAttribute(name, value) { - this.attributes[name] = value; - } - - /** - * Gets an attribute on a MathML node. - */ - getAttribute(name) { - return this.attributes[name]; - } - - /** - * Converts the math node into a MathML-namespaced DOM element. - */ - toNode() { - const node = document.createElementNS("http://www.w3.org/1998/Math/MathML", this.type); - - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { - node.setAttribute(attr, this.attributes[attr]); - } - } - - if (this.classes.length > 0) { - node.className = createClass(this.classes); - } - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - for (let i = 0; i < this.children.length; i++) { - node.appendChild(this.children[i].toNode()); - } - - return node; - } - - /** - * Converts the math node into an HTML markup string. - */ - toMarkup() { - let markup = "<" + this.type; - - // Add the attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { - markup += " " + attr + '="'; - markup += utils.escape(this.attributes[attr]); - markup += '"'; - } - } - - if (this.classes.length > 0) { - markup += ` class="${utils.escape(createClass(this.classes))}"`; - } - - let styles = ""; - - // Add the styles, after hyphenation - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - styles += `${utils.hyphenate(style)}:${this.style[style]};`; - } - } - - if (styles) { - markup += ` style="${styles}"`; - } - - markup += ">"; - - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - markup += ""; - - return markup; - } - - /** - * Converts the math node into a string, similar to innerText, but escaped. - */ - toText() { - return this.children.map((child) => child.toText()).join(""); - } -} - -/** - * This node represents a piece of text. - */ -class TextNode { - constructor(text) { - this.text = text; - } - - /** - * Converts the text node into a DOM text node. - */ - toNode() { - return document.createTextNode(this.text); - } - - /** - * Converts the text node into escaped HTML markup - * (representing the text itself). - */ - toMarkup() { - return utils.escape(this.toText()); - } - - /** - * Converts the text node into a string - * (representing the text iteself). - */ - toText() { - return this.text; - } -} - -// Do not make an the only child of a . -// An acts as its own implicit . -const wrapWithMstyle = expression => { - let node; - if (expression.length === 1 && expression[0].type === "mrow") { - node = expression.pop(); - node.type = "mstyle"; - } else { - node = new MathNode("mstyle", expression); - } - return node -}; - -var mathMLTree = { - MathNode, - TextNode, - newDocumentFragment -}; - -/** - * This file provides support for building horizontal stretchy elements. - */ - -const stretchyCodePoint = { - widehat: "^", - widecheck: "ˇ", - widetilde: "~", - wideparen: "⏜", // \u23dc - utilde: "~", - overleftarrow: "\u2190", - underleftarrow: "\u2190", - xleftarrow: "\u2190", - overrightarrow: "\u2192", - underrightarrow: "\u2192", - xrightarrow: "\u2192", - underbrace: "\u23df", - overbrace: "\u23de", - overgroup: "\u23e0", - overparen: "⏜", - undergroup: "\u23e1", - underparen: "\u23dd", - overleftrightarrow: "\u2194", - underleftrightarrow: "\u2194", - xleftrightarrow: "\u2194", - Overrightarrow: "\u21d2", - xRightarrow: "\u21d2", - overleftharpoon: "\u21bc", - xleftharpoonup: "\u21bc", - overrightharpoon: "\u21c0", - xrightharpoonup: "\u21c0", - xLeftarrow: "\u21d0", - xLeftrightarrow: "\u21d4", - xhookleftarrow: "\u21a9", - xhookrightarrow: "\u21aa", - xmapsto: "\u21a6", - xrightharpoondown: "\u21c1", - xleftharpoondown: "\u21bd", - xtwoheadleftarrow: "\u219e", - xtwoheadrightarrow: "\u21a0", - xlongequal: "=", - xrightleftarrows: "\u21c4", - yields: "\u2192", - yieldsLeft: "\u2190", - mesomerism: "\u2194", - longrightharpoonup: "\u21c0", - longleftharpoondown: "\u21bd", - eqrightharpoonup: "\u21c0", - eqleftharpoondown: "\u21bd", - "\\cdrightarrow": "\u2192", - "\\cdleftarrow": "\u2190", - "\\cdlongequal": "=" -}; - -const mathMLnode = function(label) { - const child = new mathMLTree.TextNode(stretchyCodePoint[label.slice(1)]); - const node = new mathMLTree.MathNode("mo", [child]); - node.setAttribute("stretchy", "true"); - return node -}; - -var stretchy = { - mathMLnode -}; - -/** - * This file holds a list of all no-argument functions and single-character - * symbols (like 'a' or ';'). - * - * For each of the symbols, there are two properties they can have: - * - group (required): the ParseNode group type the symbol should have (i.e. - "textord", "mathord", etc). - * - replace: the character that this symbol or function should be - * replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi - * character in the main font). - * - * The outermost map in the table indicates what mode the symbols should be - * accepted in (e.g. "math" or "text"). - */ - -// Some of these have a "-token" suffix since these are also used as `ParseNode` -// types for raw text tokens, and we want to avoid conflicts with higher-level -// `ParseNode` types. These `ParseNode`s are constructed within `Parser` by -// looking up the `symbols` map. -const ATOMS = { - bin: 1, - close: 1, - inner: 1, - open: 1, - punct: 1, - rel: 1 -}; -const NON_ATOMS = { - "accent-token": 1, - mathord: 1, - "op-token": 1, - spacing: 1, - textord: 1 -}; - -const symbols = { - math: {}, - text: {} -}; - -/** `acceptUnicodeChar = true` is only applicable if `replace` is set. */ -function defineSymbol(mode, group, replace, name, acceptUnicodeChar) { - symbols[mode][name] = { group, replace }; - - if (acceptUnicodeChar && replace) { - symbols[mode][replace] = symbols[mode][name]; - } -} - -// Some abbreviations for commonly used strings. -// This helps minify the code, and also spotting typos using jshint. - -// modes: -const math = "math"; -const text = "text"; - -// groups: -const accent = "accent-token"; -const bin = "bin"; -const close = "close"; -const inner = "inner"; -const mathord = "mathord"; -const op = "op-token"; -const open = "open"; -const punct = "punct"; -const rel = "rel"; -const spacing = "spacing"; -const textord = "textord"; - -// Now comes the symbol table - -// Relation Symbols -defineSymbol(math, rel, "\u2261", "\\equiv", true); -defineSymbol(math, rel, "\u227a", "\\prec", true); -defineSymbol(math, rel, "\u227b", "\\succ", true); -defineSymbol(math, rel, "\u223c", "\\sim", true); -defineSymbol(math, rel, "\u27c2", "\\perp", true); -defineSymbol(math, rel, "\u2aaf", "\\preceq", true); -defineSymbol(math, rel, "\u2ab0", "\\succeq", true); -defineSymbol(math, rel, "\u2243", "\\simeq", true); -defineSymbol(math, rel, "\u224c", "\\backcong", true); -defineSymbol(math, rel, "|", "\\mid", true); -defineSymbol(math, rel, "\u226a", "\\ll", true); -defineSymbol(math, rel, "\u226b", "\\gg", true); -defineSymbol(math, rel, "\u224d", "\\asymp", true); -defineSymbol(math, rel, "\u2225", "\\parallel"); -defineSymbol(math, rel, "\u22c8", "\\bowtie", true); -defineSymbol(math, rel, "\u2323", "\\smile", true); -defineSymbol(math, rel, "\u2291", "\\sqsubseteq", true); -defineSymbol(math, rel, "\u2292", "\\sqsupseteq", true); -defineSymbol(math, rel, "\u2250", "\\doteq", true); -defineSymbol(math, rel, "\u2322", "\\frown", true); -defineSymbol(math, rel, "\u220b", "\\ni", true); -defineSymbol(math, rel, "\u220c", "\\notni", true); -defineSymbol(math, rel, "\u221d", "\\propto", true); -defineSymbol(math, rel, "\u22a2", "\\vdash", true); -defineSymbol(math, rel, "\u22a3", "\\dashv", true); -defineSymbol(math, rel, "\u220b", "\\owns"); -defineSymbol(math, rel, "\u2258", "\\arceq", true); -defineSymbol(math, rel, "\u2259", "\\wedgeq", true); -defineSymbol(math, rel, "\u225a", "\\veeeq", true); -defineSymbol(math, rel, "\u225b", "\\stareq", true); -defineSymbol(math, rel, "\u225d", "\\eqdef", true); -defineSymbol(math, rel, "\u225e", "\\measeq", true); -defineSymbol(math, rel, "\u225f", "\\questeq", true); -defineSymbol(math, rel, "\u2260", "\\ne", true); -defineSymbol(math, rel, "\u2260", "\\neq"); -// mathtools.sty -defineSymbol(math, rel, "\u2237", "\\dblcolon", true); -defineSymbol(math, rel, "\u2254", "\\coloneqq", true); -defineSymbol(math, rel, "\u2255", "\\eqqcolon", true); -defineSymbol(math, rel, "\u2239", "\\eqcolon", true); -defineSymbol(math, rel, "\u2A74", "\\Coloneqq", true); - -// Punctuation -defineSymbol(math, punct, "\u002e", "\\ldotp"); -defineSymbol(math, punct, "\u00b7", "\\cdotp"); - -// Misc Symbols -defineSymbol(math, textord, "\u0023", "\\#"); -defineSymbol(text, textord, "\u0023", "\\#"); -defineSymbol(math, textord, "\u0026", "\\&"); -defineSymbol(text, textord, "\u0026", "\\&"); -defineSymbol(math, textord, "\u2135", "\\aleph", true); -defineSymbol(math, textord, "\u2200", "\\forall", true); -defineSymbol(math, textord, "\u210f", "\\hbar", true); -defineSymbol(math, textord, "\u2203", "\\exists", true); -defineSymbol(math, textord, "\u2207", "\\nabla", true); -defineSymbol(math, textord, "\u266d", "\\flat", true); -defineSymbol(math, textord, "\u2113", "\\ell", true); -defineSymbol(math, textord, "\u266e", "\\natural", true); -defineSymbol(math, textord, "Å", "\\AA", true); -defineSymbol(text, textord, "Å", "\\AA", true); -defineSymbol(math, textord, "\u2663", "\\clubsuit", true); -defineSymbol(math, textord, "\u2667", "\\varclubsuit", true); -defineSymbol(math, textord, "\u2118", "\\wp", true); -defineSymbol(math, textord, "\u266f", "\\sharp", true); -defineSymbol(math, textord, "\u2662", "\\diamondsuit", true); -defineSymbol(math, textord, "\u2666", "\\vardiamondsuit", true); -defineSymbol(math, textord, "\u211c", "\\Re", true); -defineSymbol(math, textord, "\u2661", "\\heartsuit", true); -defineSymbol(math, textord, "\u2665", "\\varheartsuit", true); -defineSymbol(math, textord, "\u2111", "\\Im", true); -defineSymbol(math, textord, "\u2660", "\\spadesuit", true); -defineSymbol(math, textord, "\u2664", "\\varspadesuit", true); -defineSymbol(math, textord, "\u2640", "\\female", true); -defineSymbol(math, textord, "\u2642", "\\male", true); -defineSymbol(math, textord, "\u00a7", "\\S", true); -defineSymbol(text, textord, "\u00a7", "\\S"); -defineSymbol(math, textord, "\u00b6", "\\P", true); -defineSymbol(text, textord, "\u00b6", "\\P"); -defineSymbol(text, textord, "\u263a", "\\smiley", true); -defineSymbol(math, textord, "\u263a", "\\smiley", true); - -// Math and Text -defineSymbol(math, textord, "\u2020", "\\dag"); -defineSymbol(text, textord, "\u2020", "\\dag"); -defineSymbol(text, textord, "\u2020", "\\textdagger"); -defineSymbol(math, textord, "\u2021", "\\ddag"); -defineSymbol(text, textord, "\u2021", "\\ddag"); -defineSymbol(text, textord, "\u2021", "\\textdaggerdbl"); - -// Large Delimiters -defineSymbol(math, close, "\u23b1", "\\rmoustache", true); -defineSymbol(math, open, "\u23b0", "\\lmoustache", true); -defineSymbol(math, close, "\u27ef", "\\rgroup", true); -defineSymbol(math, open, "\u27ee", "\\lgroup", true); - -// Binary Operators -defineSymbol(math, bin, "\u2213", "\\mp", true); -defineSymbol(math, bin, "\u2296", "\\ominus", true); -defineSymbol(math, bin, "\u228e", "\\uplus", true); -defineSymbol(math, bin, "\u2293", "\\sqcap", true); -defineSymbol(math, bin, "\u2217", "\\ast"); -defineSymbol(math, bin, "\u2294", "\\sqcup", true); -defineSymbol(math, bin, "\u25ef", "\\bigcirc", true); -defineSymbol(math, bin, "\u2219", "\\bullet", true); -defineSymbol(math, bin, "\u2021", "\\ddagger"); -defineSymbol(math, bin, "\u2240", "\\wr", true); -defineSymbol(math, bin, "\u2a3f", "\\amalg"); -defineSymbol(math, bin, "\u0026", "\\And"); // from amsmath - -// Arrow Symbols -defineSymbol(math, rel, "\u27f5", "\\longleftarrow", true); -defineSymbol(math, rel, "\u21d0", "\\Leftarrow", true); -defineSymbol(math, rel, "\u27f8", "\\Longleftarrow", true); -defineSymbol(math, rel, "\u27f6", "\\longrightarrow", true); -defineSymbol(math, rel, "\u21d2", "\\Rightarrow", true); -defineSymbol(math, rel, "\u27f9", "\\Longrightarrow", true); -defineSymbol(math, rel, "\u2194", "\\leftrightarrow", true); -defineSymbol(math, rel, "\u27f7", "\\longleftrightarrow", true); -defineSymbol(math, rel, "\u21d4", "\\Leftrightarrow", true); -defineSymbol(math, rel, "\u27fa", "\\Longleftrightarrow", true); -defineSymbol(math, rel, "\u21a6", "\\mapsto", true); -defineSymbol(math, rel, "\u27fc", "\\longmapsto", true); -defineSymbol(math, rel, "\u2197", "\\nearrow", true); -defineSymbol(math, rel, "\u21a9", "\\hookleftarrow", true); -defineSymbol(math, rel, "\u21aa", "\\hookrightarrow", true); -defineSymbol(math, rel, "\u2198", "\\searrow", true); -defineSymbol(math, rel, "\u21bc", "\\leftharpoonup", true); -defineSymbol(math, rel, "\u21c0", "\\rightharpoonup", true); -defineSymbol(math, rel, "\u2199", "\\swarrow", true); -defineSymbol(math, rel, "\u21bd", "\\leftharpoondown", true); -defineSymbol(math, rel, "\u21c1", "\\rightharpoondown", true); -defineSymbol(math, rel, "\u2196", "\\nwarrow", true); -defineSymbol(math, rel, "\u21cc", "\\rightleftharpoons", true); -defineSymbol(math, mathord, "\u21af", "\\lightning", true); -defineSymbol(math, mathord, "\u2030", "\\permil", true); -defineSymbol(text, textord, "\u2030", "\\permil"); - -// AMS Negated Binary Relations -defineSymbol(math, rel, "\u226e", "\\nless", true); -// Symbol names preceeded by "@" each have a corresponding macro. -defineSymbol(math, rel, "\u2a87", "\\lneq", true); -defineSymbol(math, rel, "\u2268", "\\lneqq", true); -defineSymbol(math, rel, "\u2268\ufe00", "\\lvertneqq"); -defineSymbol(math, rel, "\u22e6", "\\lnsim", true); -defineSymbol(math, rel, "\u2a89", "\\lnapprox", true); -defineSymbol(math, rel, "\u2280", "\\nprec", true); -// unicode-math maps \u22e0 to \npreccurlyeq. We'll use the AMS synonym. -defineSymbol(math, rel, "\u22e0", "\\npreceq", true); -defineSymbol(math, rel, "\u22e8", "\\precnsim", true); -defineSymbol(math, rel, "\u2ab9", "\\precnapprox", true); -defineSymbol(math, rel, "\u2241", "\\nsim", true); -defineSymbol(math, rel, "\u2224", "\\nmid", true); -defineSymbol(math, rel, "\u2224", "\\nshortmid"); -defineSymbol(math, rel, "\u22ac", "\\nvdash", true); -defineSymbol(math, rel, "\u22ad", "\\nvDash", true); -defineSymbol(math, rel, "\u22ea", "\\ntriangleleft"); -defineSymbol(math, rel, "\u22ec", "\\ntrianglelefteq", true); -defineSymbol(math, rel, "\u2284", "\\nsubset", true); -defineSymbol(math, rel, "\u2285", "\\nsupset", true); -defineSymbol(math, rel, "\u228a", "\\subsetneq", true); -defineSymbol(math, rel, "\u228a\ufe00", "\\varsubsetneq"); -defineSymbol(math, rel, "\u2acb", "\\subsetneqq", true); -defineSymbol(math, rel, "\u2acb\ufe00", "\\varsubsetneqq"); -defineSymbol(math, rel, "\u226f", "\\ngtr", true); -defineSymbol(math, rel, "\u2a88", "\\gneq", true); -defineSymbol(math, rel, "\u2269", "\\gneqq", true); -defineSymbol(math, rel, "\u2269\ufe00", "\\gvertneqq"); -defineSymbol(math, rel, "\u22e7", "\\gnsim", true); -defineSymbol(math, rel, "\u2a8a", "\\gnapprox", true); -defineSymbol(math, rel, "\u2281", "\\nsucc", true); -// unicode-math maps \u22e1 to \nsucccurlyeq. We'll use the AMS synonym. -defineSymbol(math, rel, "\u22e1", "\\nsucceq", true); -defineSymbol(math, rel, "\u22e9", "\\succnsim", true); -defineSymbol(math, rel, "\u2aba", "\\succnapprox", true); -// unicode-math maps \u2246 to \simneqq. We'll use the AMS synonym. -defineSymbol(math, rel, "\u2246", "\\ncong", true); -defineSymbol(math, rel, "\u2226", "\\nparallel", true); -defineSymbol(math, rel, "\u2226", "\\nshortparallel"); -defineSymbol(math, rel, "\u22af", "\\nVDash", true); -defineSymbol(math, rel, "\u22eb", "\\ntriangleright"); -defineSymbol(math, rel, "\u22ed", "\\ntrianglerighteq", true); -defineSymbol(math, rel, "\u228b", "\\supsetneq", true); -defineSymbol(math, rel, "\u228b", "\\varsupsetneq"); -defineSymbol(math, rel, "\u2acc", "\\supsetneqq", true); -defineSymbol(math, rel, "\u2acc\ufe00", "\\varsupsetneqq"); -defineSymbol(math, rel, "\u22ae", "\\nVdash", true); -defineSymbol(math, rel, "\u2ab5", "\\precneqq", true); -defineSymbol(math, rel, "\u2ab6", "\\succneqq", true); -defineSymbol(math, bin, "\u22b4", "\\unlhd"); -defineSymbol(math, bin, "\u22b5", "\\unrhd"); - -// AMS Negated Arrows -defineSymbol(math, rel, "\u219a", "\\nleftarrow", true); -defineSymbol(math, rel, "\u219b", "\\nrightarrow", true); -defineSymbol(math, rel, "\u21cd", "\\nLeftarrow", true); -defineSymbol(math, rel, "\u21cf", "\\nRightarrow", true); -defineSymbol(math, rel, "\u21ae", "\\nleftrightarrow", true); -defineSymbol(math, rel, "\u21ce", "\\nLeftrightarrow", true); - -// AMS Misc -defineSymbol(math, rel, "\u25b3", "\\vartriangle"); -defineSymbol(math, textord, "\u210f", "\\hslash"); -defineSymbol(math, textord, "\u25bd", "\\triangledown"); -defineSymbol(math, textord, "\u25ca", "\\lozenge"); -defineSymbol(math, textord, "\u24c8", "\\circledS"); -defineSymbol(math, textord, "\u00ae", "\\circledR", true); -defineSymbol(text, textord, "\u00ae", "\\circledR"); -defineSymbol(text, textord, "\u00ae", "\\textregistered"); -defineSymbol(math, textord, "\u2221", "\\measuredangle", true); -defineSymbol(math, textord, "\u2204", "\\nexists"); -defineSymbol(math, textord, "\u2127", "\\mho"); -defineSymbol(math, textord, "\u2132", "\\Finv", true); -defineSymbol(math, textord, "\u2141", "\\Game", true); -defineSymbol(math, textord, "\u2035", "\\backprime"); -defineSymbol(math, textord, "\u25b2", "\\blacktriangle"); -defineSymbol(math, textord, "\u25bc", "\\blacktriangledown"); -defineSymbol(math, textord, "\u25a0", "\\blacksquare"); -defineSymbol(math, textord, "\u29eb", "\\blacklozenge"); -defineSymbol(math, textord, "\u2605", "\\bigstar"); -defineSymbol(math, textord, "\u2222", "\\sphericalangle", true); -defineSymbol(math, textord, "\u2201", "\\complement", true); -// unicode-math maps U+F0 to \matheth. We map to AMS function \eth -defineSymbol(math, textord, "\u00f0", "\\eth", true); -defineSymbol(text, textord, "\u00f0", "\u00f0"); -defineSymbol(math, textord, "\u2571", "\\diagup"); -defineSymbol(math, textord, "\u2572", "\\diagdown"); -defineSymbol(math, textord, "\u25a1", "\\square"); -defineSymbol(math, textord, "\u25a1", "\\Box"); -defineSymbol(math, textord, "\u25ca", "\\Diamond"); -// unicode-math maps U+A5 to \mathyen. We map to AMS function \yen -defineSymbol(math, textord, "\u00a5", "\\yen", true); -defineSymbol(text, textord, "\u00a5", "\\yen", true); -defineSymbol(math, textord, "\u2713", "\\checkmark", true); -defineSymbol(text, textord, "\u2713", "\\checkmark"); -defineSymbol(math, textord, "\u2717", "\\ballotx", true); -defineSymbol(text, textord, "\u2717", "\\ballotx"); -defineSymbol(text, textord, "\u2022", "\\textbullet"); - -// AMS Hebrew -defineSymbol(math, textord, "\u2136", "\\beth", true); -defineSymbol(math, textord, "\u2138", "\\daleth", true); -defineSymbol(math, textord, "\u2137", "\\gimel", true); - -// AMS Greek -defineSymbol(math, textord, "\u03dd", "\\digamma", true); -defineSymbol(math, textord, "\u03f0", "\\varkappa"); - -// AMS Delimiters -defineSymbol(math, open, "\u231C", "\\ulcorner", true); -defineSymbol(math, close, "\u231D", "\\urcorner", true); -defineSymbol(math, open, "\u231E", "\\llcorner", true); -defineSymbol(math, close, "\u231F", "\\lrcorner", true); - -// AMS Binary Relations -defineSymbol(math, rel, "\u2266", "\\leqq", true); -defineSymbol(math, rel, "\u2a7d", "\\leqslant", true); -defineSymbol(math, rel, "\u2a95", "\\eqslantless", true); -defineSymbol(math, rel, "\u2272", "\\lesssim", true); -defineSymbol(math, rel, "\u2a85", "\\lessapprox", true); -defineSymbol(math, rel, "\u224a", "\\approxeq", true); -defineSymbol(math, bin, "\u22d6", "\\lessdot"); -defineSymbol(math, rel, "\u22d8", "\\lll", true); -defineSymbol(math, rel, "\u2276", "\\lessgtr", true); -defineSymbol(math, rel, "\u22da", "\\lesseqgtr", true); -defineSymbol(math, rel, "\u2a8b", "\\lesseqqgtr", true); -defineSymbol(math, rel, "\u2251", "\\doteqdot"); -defineSymbol(math, rel, "\u2253", "\\risingdotseq", true); -defineSymbol(math, rel, "\u2252", "\\fallingdotseq", true); -defineSymbol(math, rel, "\u223d", "\\backsim", true); -defineSymbol(math, rel, "\u22cd", "\\backsimeq", true); -defineSymbol(math, rel, "\u2ac5", "\\subseteqq", true); -defineSymbol(math, rel, "\u22d0", "\\Subset", true); -defineSymbol(math, rel, "\u228f", "\\sqsubset", true); -defineSymbol(math, rel, "\u227c", "\\preccurlyeq", true); -defineSymbol(math, rel, "\u22de", "\\curlyeqprec", true); -defineSymbol(math, rel, "\u227e", "\\precsim", true); -defineSymbol(math, rel, "\u2ab7", "\\precapprox", true); -defineSymbol(math, rel, "\u22b2", "\\vartriangleleft"); -defineSymbol(math, rel, "\u22b4", "\\trianglelefteq"); -defineSymbol(math, rel, "\u22a8", "\\vDash", true); -defineSymbol(math, rel, "\u22aa", "\\Vvdash", true); -defineSymbol(math, rel, "\u2323", "\\smallsmile"); -defineSymbol(math, rel, "\u2322", "\\smallfrown"); -defineSymbol(math, rel, "\u224f", "\\bumpeq", true); -defineSymbol(math, rel, "\u224e", "\\Bumpeq", true); -defineSymbol(math, rel, "\u2267", "\\geqq", true); -defineSymbol(math, rel, "\u2a7e", "\\geqslant", true); -defineSymbol(math, rel, "\u2a96", "\\eqslantgtr", true); -defineSymbol(math, rel, "\u2273", "\\gtrsim", true); -defineSymbol(math, rel, "\u2a86", "\\gtrapprox", true); -defineSymbol(math, bin, "\u22d7", "\\gtrdot"); -defineSymbol(math, rel, "\u22d9", "\\ggg", true); -defineSymbol(math, rel, "\u2277", "\\gtrless", true); -defineSymbol(math, rel, "\u22db", "\\gtreqless", true); -defineSymbol(math, rel, "\u2a8c", "\\gtreqqless", true); -defineSymbol(math, rel, "\u2256", "\\eqcirc", true); -defineSymbol(math, rel, "\u2257", "\\circeq", true); -defineSymbol(math, rel, "\u225c", "\\triangleq", true); -defineSymbol(math, rel, "\u223c", "\\thicksim"); -defineSymbol(math, rel, "\u2248", "\\thickapprox"); -defineSymbol(math, rel, "\u2ac6", "\\supseteqq", true); -defineSymbol(math, rel, "\u22d1", "\\Supset", true); -defineSymbol(math, rel, "\u2290", "\\sqsupset", true); -defineSymbol(math, rel, "\u227d", "\\succcurlyeq", true); -defineSymbol(math, rel, "\u22df", "\\curlyeqsucc", true); -defineSymbol(math, rel, "\u227f", "\\succsim", true); -defineSymbol(math, rel, "\u2ab8", "\\succapprox", true); -defineSymbol(math, rel, "\u22b3", "\\vartriangleright"); -defineSymbol(math, rel, "\u22b5", "\\trianglerighteq"); -defineSymbol(math, rel, "\u22a9", "\\Vdash", true); -defineSymbol(math, rel, "\u2223", "\\shortmid"); -defineSymbol(math, rel, "\u2225", "\\shortparallel"); -defineSymbol(math, rel, "\u226c", "\\between", true); -defineSymbol(math, rel, "\u22d4", "\\pitchfork", true); -defineSymbol(math, rel, "\u221d", "\\varpropto"); -defineSymbol(math, rel, "\u25c0", "\\blacktriangleleft"); -// unicode-math says that \therefore is a mathord atom. -// We kept the amssymb atom type, which is rel. -defineSymbol(math, rel, "\u2234", "\\therefore", true); -defineSymbol(math, rel, "\u220d", "\\backepsilon"); -defineSymbol(math, rel, "\u25b6", "\\blacktriangleright"); -// unicode-math says that \because is a mathord atom. -// We kept the amssymb atom type, which is rel. -defineSymbol(math, rel, "\u2235", "\\because", true); -defineSymbol(math, rel, "\u22d8", "\\llless"); -defineSymbol(math, rel, "\u22d9", "\\gggtr"); -defineSymbol(math, bin, "\u22b2", "\\lhd"); -defineSymbol(math, bin, "\u22b3", "\\rhd"); -defineSymbol(math, rel, "\u2242", "\\eqsim", true); -defineSymbol(math, rel, "\u22c8", "\\Join"); -defineSymbol(math, rel, "\u2251", "\\Doteq", true); -defineSymbol(math, rel, "\u297d", "\\strictif", true); -defineSymbol(math, rel, "\u297c", "\\strictfi", true); - -// AMS Binary Operators -defineSymbol(math, bin, "\u2214", "\\dotplus", true); -defineSymbol(math, bin, "\u2216", "\\smallsetminus"); -defineSymbol(math, bin, "\u22d2", "\\Cap", true); -defineSymbol(math, bin, "\u22d3", "\\Cup", true); -defineSymbol(math, bin, "\u2a5e", "\\doublebarwedge", true); -defineSymbol(math, bin, "\u229f", "\\boxminus", true); -defineSymbol(math, bin, "\u229e", "\\boxplus", true); -defineSymbol(math, bin, "\u22c7", "\\divideontimes", true); -defineSymbol(math, bin, "\u22c9", "\\ltimes", true); -defineSymbol(math, bin, "\u22ca", "\\rtimes", true); -defineSymbol(math, bin, "\u22cb", "\\leftthreetimes", true); -defineSymbol(math, bin, "\u22cc", "\\rightthreetimes", true); -defineSymbol(math, bin, "\u22cf", "\\curlywedge", true); -defineSymbol(math, bin, "\u22ce", "\\curlyvee", true); -defineSymbol(math, bin, "\u229d", "\\circleddash", true); -defineSymbol(math, bin, "\u229b", "\\circledast", true); -defineSymbol(math, bin, "\u22ba", "\\intercal", true); -defineSymbol(math, bin, "\u22d2", "\\doublecap"); -defineSymbol(math, bin, "\u22d3", "\\doublecup"); -defineSymbol(math, bin, "\u22a0", "\\boxtimes", true); - -// AMS Arrows -// Note: unicode-math maps \u21e2 to their own function \rightdasharrow. -// We'll map it to AMS function \dashrightarrow. It produces the same atom. -defineSymbol(math, rel, "\u21e2", "\\dashrightarrow", true); -// unicode-math maps \u21e0 to \leftdasharrow. We'll use the AMS synonym. -defineSymbol(math, rel, "\u21e0", "\\dashleftarrow", true); -defineSymbol(math, rel, "\u21c7", "\\leftleftarrows", true); -defineSymbol(math, rel, "\u21c6", "\\leftrightarrows", true); -defineSymbol(math, rel, "\u21da", "\\Lleftarrow", true); -defineSymbol(math, rel, "\u219e", "\\twoheadleftarrow", true); -defineSymbol(math, rel, "\u21a2", "\\leftarrowtail", true); -defineSymbol(math, rel, "\u21ab", "\\looparrowleft", true); -defineSymbol(math, rel, "\u21cb", "\\leftrightharpoons", true); -defineSymbol(math, rel, "\u21b6", "\\curvearrowleft", true); -// unicode-math maps \u21ba to \acwopencirclearrow. We'll use the AMS synonym. -defineSymbol(math, rel, "\u21ba", "\\circlearrowleft", true); -defineSymbol(math, rel, "\u21b0", "\\Lsh", true); -defineSymbol(math, rel, "\u21c8", "\\upuparrows", true); -defineSymbol(math, rel, "\u21bf", "\\upharpoonleft", true); -defineSymbol(math, rel, "\u21c3", "\\downharpoonleft", true); -defineSymbol(math, rel, "\u22b6", "\\origof", true); -defineSymbol(math, rel, "\u22b7", "\\imageof", true); -defineSymbol(math, rel, "\u22b8", "\\multimap", true); -defineSymbol(math, rel, "\u21ad", "\\leftrightsquigarrow", true); -defineSymbol(math, rel, "\u21c9", "\\rightrightarrows", true); -defineSymbol(math, rel, "\u21c4", "\\rightleftarrows", true); -defineSymbol(math, rel, "\u21a0", "\\twoheadrightarrow", true); -defineSymbol(math, rel, "\u21a3", "\\rightarrowtail", true); -defineSymbol(math, rel, "\u21ac", "\\looparrowright", true); -defineSymbol(math, rel, "\u21b7", "\\curvearrowright", true); -// unicode-math maps \u21bb to \cwopencirclearrow. We'll use the AMS synonym. -defineSymbol(math, rel, "\u21bb", "\\circlearrowright", true); -defineSymbol(math, rel, "\u21b1", "\\Rsh", true); -defineSymbol(math, rel, "\u21ca", "\\downdownarrows", true); -defineSymbol(math, rel, "\u21be", "\\upharpoonright", true); -defineSymbol(math, rel, "\u21c2", "\\downharpoonright", true); -defineSymbol(math, rel, "\u21dd", "\\rightsquigarrow", true); -defineSymbol(math, rel, "\u21dd", "\\leadsto"); -defineSymbol(math, rel, "\u21db", "\\Rrightarrow", true); -defineSymbol(math, rel, "\u21be", "\\restriction"); - -defineSymbol(math, textord, "\u2018", "`"); -defineSymbol(math, textord, "$", "\\$"); -defineSymbol(text, textord, "$", "\\$"); -defineSymbol(text, textord, "$", "\\textdollar"); -defineSymbol(math, textord, "%", "\\%"); -defineSymbol(text, textord, "%", "\\%"); -defineSymbol(math, textord, "_", "\\_"); -defineSymbol(text, textord, "_", "\\_"); -defineSymbol(text, textord, "_", "\\textunderscore"); -defineSymbol(text, textord, "\u2423", "\\textvisiblespace", true); -defineSymbol(math, textord, "\u2220", "\\angle", true); -defineSymbol(math, textord, "\u221e", "\\infty", true); -defineSymbol(math, textord, "\u2032", "\\prime"); -defineSymbol(math, textord, "\u25b3", "\\triangle"); -defineSymbol(text, textord, "\u0391", "\\Alpha", true); -defineSymbol(text, textord, "\u0392", "\\Beta", true); -defineSymbol(text, textord, "\u0393", "\\Gamma", true); -defineSymbol(text, textord, "\u0394", "\\Delta", true); -defineSymbol(text, textord, "\u0395", "\\Epsilon", true); -defineSymbol(text, textord, "\u0396", "\\Zeta", true); -defineSymbol(text, textord, "\u0397", "\\Eta", true); -defineSymbol(text, textord, "\u0398", "\\Theta", true); -defineSymbol(text, textord, "\u0399", "\\Iota", true); -defineSymbol(text, textord, "\u039a", "\\Kappa", true); -defineSymbol(text, textord, "\u039b", "\\Lambda", true); -defineSymbol(text, textord, "\u039c", "\\Mu", true); -defineSymbol(text, textord, "\u039d", "\\Nu", true); -defineSymbol(text, textord, "\u039e", "\\Xi", true); -defineSymbol(text, textord, "\u039f", "\\Omicron", true); -defineSymbol(text, textord, "\u03a0", "\\Pi", true); -defineSymbol(text, textord, "\u03a1", "\\Rho", true); -defineSymbol(text, textord, "\u03a3", "\\Sigma", true); -defineSymbol(text, textord, "\u03a4", "\\Tau", true); -defineSymbol(text, textord, "\u03a5", "\\Upsilon", true); -defineSymbol(text, textord, "\u03a6", "\\Phi", true); -defineSymbol(text, textord, "\u03a7", "\\Chi", true); -defineSymbol(text, textord, "\u03a8", "\\Psi", true); -defineSymbol(text, textord, "\u03a9", "\\Omega", true); -defineSymbol(math, mathord, "\u0391", "\\Alpha", true); -defineSymbol(math, mathord, "\u0392", "\\Beta", true); -defineSymbol(math, mathord, "\u0393", "\\Gamma", true); -defineSymbol(math, mathord, "\u0394", "\\Delta", true); -defineSymbol(math, mathord, "\u0395", "\\Epsilon", true); -defineSymbol(math, mathord, "\u0396", "\\Zeta", true); -defineSymbol(math, mathord, "\u0397", "\\Eta", true); -defineSymbol(math, mathord, "\u0398", "\\Theta", true); -defineSymbol(math, mathord, "\u0399", "\\Iota", true); -defineSymbol(math, mathord, "\u039a", "\\Kappa", true); -defineSymbol(math, mathord, "\u039b", "\\Lambda", true); -defineSymbol(math, mathord, "\u039c", "\\Mu", true); -defineSymbol(math, mathord, "\u039d", "\\Nu", true); -defineSymbol(math, mathord, "\u039e", "\\Xi", true); -defineSymbol(math, mathord, "\u039f", "\\Omicron", true); -defineSymbol(math, mathord, "\u03a0", "\\Pi", true); -defineSymbol(math, mathord, "\u03a1", "\\Rho", true); -defineSymbol(math, mathord, "\u03a3", "\\Sigma", true); -defineSymbol(math, mathord, "\u03a4", "\\Tau", true); -defineSymbol(math, mathord, "\u03a5", "\\Upsilon", true); -defineSymbol(math, mathord, "\u03a6", "\\Phi", true); -defineSymbol(math, mathord, "\u03a7", "\\Chi", true); -defineSymbol(math, mathord, "\u03a8", "\\Psi", true); -defineSymbol(math, mathord, "\u03a9", "\\Omega", true); -defineSymbol(math, open, "\u00ac", "\\neg", true); -defineSymbol(math, open, "\u00ac", "\\lnot"); -defineSymbol(math, textord, "\u22a4", "\\top"); -defineSymbol(math, textord, "\u22a5", "\\bot"); -defineSymbol(math, textord, "\u2205", "\\emptyset"); -defineSymbol(math, textord, "\u00f8", "\\varnothing"); -defineSymbol(math, mathord, "\u03b1", "\\alpha", true); -defineSymbol(math, mathord, "\u03b2", "\\beta", true); -defineSymbol(math, mathord, "\u03b3", "\\gamma", true); -defineSymbol(math, mathord, "\u03b4", "\\delta", true); -defineSymbol(math, mathord, "\u03f5", "\\epsilon", true); -defineSymbol(math, mathord, "\u03b6", "\\zeta", true); -defineSymbol(math, mathord, "\u03b7", "\\eta", true); -defineSymbol(math, mathord, "\u03b8", "\\theta", true); -defineSymbol(math, mathord, "\u03b9", "\\iota", true); -defineSymbol(math, mathord, "\u03ba", "\\kappa", true); -defineSymbol(math, mathord, "\u03bb", "\\lambda", true); -defineSymbol(math, mathord, "\u03bc", "\\mu", true); -defineSymbol(math, mathord, "\u03bd", "\\nu", true); -defineSymbol(math, mathord, "\u03be", "\\xi", true); -defineSymbol(math, mathord, "\u03bf", "\\omicron", true); -defineSymbol(math, mathord, "\u03c0", "\\pi", true); -defineSymbol(math, mathord, "\u03c1", "\\rho", true); -defineSymbol(math, mathord, "\u03c3", "\\sigma", true); -defineSymbol(math, mathord, "\u03c4", "\\tau", true); -defineSymbol(math, mathord, "\u03c5", "\\upsilon", true); -defineSymbol(math, mathord, "\u03d5", "\\phi", true); -defineSymbol(math, mathord, "\u03c7", "\\chi", true); -defineSymbol(math, mathord, "\u03c8", "\\psi", true); -defineSymbol(math, mathord, "\u03c9", "\\omega", true); -defineSymbol(math, mathord, "\u03b5", "\\varepsilon", true); -defineSymbol(math, mathord, "\u03d1", "\\vartheta", true); -defineSymbol(math, mathord, "\u03d6", "\\varpi", true); -defineSymbol(math, mathord, "\u03f1", "\\varrho", true); -defineSymbol(math, mathord, "\u03c2", "\\varsigma", true); -defineSymbol(math, mathord, "\u03c6", "\\varphi", true); -defineSymbol(math, mathord, "\u03d8", "\\Coppa", true); -defineSymbol(math, mathord, "\u03d9", "\\coppa", true); -defineSymbol(math, mathord, "\u03d9", "\\varcoppa", true); -defineSymbol(math, mathord, "\u03de", "\\Koppa", true); -defineSymbol(math, mathord, "\u03df", "\\koppa", true); -defineSymbol(math, mathord, "\u03e0", "\\Sampi", true); -defineSymbol(math, mathord, "\u03e1", "\\sampi", true); -defineSymbol(math, mathord, "\u03da", "\\Stigma", true); -defineSymbol(math, mathord, "\u03db", "\\stigma", true); -defineSymbol(math, mathord, "\u2aeb", "\\Bot"); -defineSymbol(math, bin, "\u2217", "\u2217", true); -defineSymbol(math, bin, "+", "+"); -defineSymbol(math, bin, "*", "*"); -defineSymbol(math, bin, "\u2044", "\u2044"); -defineSymbol(math, bin, "\u2212", "-", true); -defineSymbol(math, bin, "\u22c5", "\\cdot", true); -defineSymbol(math, bin, "\u2218", "\\circ", true); -defineSymbol(math, bin, "\u00f7", "\\div", true); -defineSymbol(math, bin, "\u00b1", "\\pm", true); -defineSymbol(math, bin, "\u00d7", "\\times", true); -defineSymbol(math, bin, "\u2229", "\\cap", true); -defineSymbol(math, bin, "\u222a", "\\cup", true); -defineSymbol(math, bin, "\u2216", "\\setminus", true); -defineSymbol(math, bin, "\u2227", "\\land"); -defineSymbol(math, bin, "\u2228", "\\lor"); -defineSymbol(math, bin, "\u2227", "\\wedge", true); -defineSymbol(math, bin, "\u2228", "\\vee", true); -defineSymbol(math, open, "\u27e6", "\\llbracket", true); // stmaryrd/semantic packages -defineSymbol(math, close, "\u27e7", "\\rrbracket", true); -defineSymbol(math, open, "\u27e8", "\\langle", true); -defineSymbol(math, open, "|", "\\lvert"); -defineSymbol(math, open, "\u2016", "\\lVert"); -defineSymbol(math, textord, "!", "\\oc"); // cmll package -defineSymbol(math, textord, "?", "\\wn"); -defineSymbol(math, textord, "\u2193", "\\shpos"); -defineSymbol(math, textord, "\u2195", "\\shift"); -defineSymbol(math, textord, "\u2191", "\\shneg"); -defineSymbol(math, close, "?", "?"); -defineSymbol(math, close, "!", "!"); -defineSymbol(math, close, "‼", "‼"); -defineSymbol(math, close, "\u27e9", "\\rangle", true); -defineSymbol(math, close, "|", "\\rvert"); -defineSymbol(math, close, "\u2016", "\\rVert"); -defineSymbol(math, open, "\u2983", "\\lBrace", true); // stmaryrd/semantic packages -defineSymbol(math, close, "\u2984", "\\rBrace", true); -defineSymbol(math, rel, "=", "\\equal", true); -defineSymbol(math, rel, ":", ":"); -defineSymbol(math, rel, "\u2248", "\\approx", true); -defineSymbol(math, rel, "\u2245", "\\cong", true); -defineSymbol(math, rel, "\u2265", "\\ge"); -defineSymbol(math, rel, "\u2265", "\\geq", true); -defineSymbol(math, rel, "\u2190", "\\gets"); -defineSymbol(math, rel, ">", "\\gt", true); -defineSymbol(math, rel, "\u2208", "\\in", true); -defineSymbol(math, rel, "\u2209", "\\notin", true); -defineSymbol(math, rel, "\ue020", "\\@not"); -defineSymbol(math, rel, "\u2282", "\\subset", true); -defineSymbol(math, rel, "\u2283", "\\supset", true); -defineSymbol(math, rel, "\u2286", "\\subseteq", true); -defineSymbol(math, rel, "\u2287", "\\supseteq", true); -defineSymbol(math, rel, "\u2288", "\\nsubseteq", true); -defineSymbol(math, rel, "\u2288", "\\nsubseteqq"); -defineSymbol(math, rel, "\u2289", "\\nsupseteq", true); -defineSymbol(math, rel, "\u2289", "\\nsupseteqq"); -defineSymbol(math, rel, "\u22a8", "\\models"); -defineSymbol(math, rel, "\u2190", "\\leftarrow", true); -defineSymbol(math, rel, "\u2264", "\\le"); -defineSymbol(math, rel, "\u2264", "\\leq", true); -defineSymbol(math, rel, "<", "\\lt", true); -defineSymbol(math, rel, "\u2192", "\\rightarrow", true); -defineSymbol(math, rel, "\u2192", "\\to"); -defineSymbol(math, rel, "\u2271", "\\ngeq", true); -defineSymbol(math, rel, "\u2271", "\\ngeqq"); -defineSymbol(math, rel, "\u2271", "\\ngeqslant"); -defineSymbol(math, rel, "\u2270", "\\nleq", true); -defineSymbol(math, rel, "\u2270", "\\nleqq"); -defineSymbol(math, rel, "\u2270", "\\nleqslant"); -defineSymbol(math, rel, "\u2aeb", "\\Perp", true); //cmll package -defineSymbol(math, spacing, "\u00a0", "\\ "); -defineSymbol(math, spacing, "\u00a0", "\\space"); -// Ref: LaTeX Source 2e: \DeclareRobustCommand{\nobreakspace}{% -defineSymbol(math, spacing, "\u00a0", "\\nobreakspace"); -defineSymbol(text, spacing, "\u00a0", "\\ "); -defineSymbol(text, spacing, "\u00a0", " "); -defineSymbol(text, spacing, "\u00a0", "\\space"); -defineSymbol(text, spacing, "\u00a0", "\\nobreakspace"); -defineSymbol(math, spacing, null, "\\nobreak"); -defineSymbol(math, spacing, null, "\\allowbreak"); -defineSymbol(math, punct, ",", ","); -defineSymbol(text, punct, ":", ":"); -defineSymbol(math, punct, ";", ";"); -defineSymbol(math, bin, "\u22bc", "\\barwedge", true); -defineSymbol(math, bin, "\u22bb", "\\veebar", true); -defineSymbol(math, bin, "\u2299", "\\odot", true); -defineSymbol(math, bin, "\u2295", "\\oplus", true); -defineSymbol(math, bin, "\u2297", "\\otimes", true); -defineSymbol(math, textord, "\u2202", "\\partial", true); -defineSymbol(math, bin, "\u2298", "\\oslash", true); -defineSymbol(math, bin, "\u229a", "\\circledcirc", true); -defineSymbol(math, bin, "\u22a1", "\\boxdot", true); -defineSymbol(math, bin, "\u25b3", "\\bigtriangleup"); -defineSymbol(math, bin, "\u25bd", "\\bigtriangledown"); -defineSymbol(math, bin, "\u2020", "\\dagger"); -defineSymbol(math, bin, "\u22c4", "\\diamond"); -defineSymbol(math, bin, "\u22c6", "\\star"); -defineSymbol(math, bin, "\u25c3", "\\triangleleft"); -defineSymbol(math, bin, "\u25b9", "\\triangleright"); -defineSymbol(math, open, "{", "\\{"); -defineSymbol(text, textord, "{", "\\{"); -defineSymbol(text, textord, "{", "\\textbraceleft"); -defineSymbol(math, close, "}", "\\}"); -defineSymbol(text, textord, "}", "\\}"); -defineSymbol(text, textord, "}", "\\textbraceright"); -defineSymbol(math, open, "{", "\\lbrace"); -defineSymbol(math, close, "}", "\\rbrace"); -defineSymbol(math, open, "[", "\\lbrack", true); -defineSymbol(text, textord, "[", "\\lbrack", true); -defineSymbol(math, close, "]", "\\rbrack", true); -defineSymbol(text, textord, "]", "\\rbrack", true); -defineSymbol(math, open, "(", "\\lparen", true); -defineSymbol(math, close, ")", "\\rparen", true); -defineSymbol(text, textord, "<", "\\textless", true); // in T1 fontenc -defineSymbol(text, textord, ">", "\\textgreater", true); // in T1 fontenc -defineSymbol(math, open, "\u230a", "\\lfloor", true); -defineSymbol(math, close, "\u230b", "\\rfloor", true); -defineSymbol(math, open, "\u2308", "\\lceil", true); -defineSymbol(math, close, "\u2309", "\\rceil", true); -defineSymbol(math, textord, "\\", "\\backslash"); -defineSymbol(math, textord, "|", "|"); -defineSymbol(math, textord, "|", "\\vert"); -defineSymbol(text, textord, "|", "\\textbar", true); // in T1 fontenc -defineSymbol(math, textord, "\u2016", "\\|"); -defineSymbol(math, textord, "\u2016", "\\Vert"); -defineSymbol(text, textord, "\u2016", "\\textbardbl"); -defineSymbol(text, textord, "~", "\\textasciitilde"); -defineSymbol(text, textord, "\\", "\\textbackslash"); -defineSymbol(text, textord, "^", "\\textasciicircum"); -defineSymbol(math, rel, "\u2191", "\\uparrow", true); -defineSymbol(math, rel, "\u21d1", "\\Uparrow", true); -defineSymbol(math, rel, "\u2193", "\\downarrow", true); -defineSymbol(math, rel, "\u21d3", "\\Downarrow", true); -defineSymbol(math, rel, "\u2195", "\\updownarrow", true); -defineSymbol(math, rel, "\u21d5", "\\Updownarrow", true); -defineSymbol(math, op, "\u2210", "\\coprod"); -defineSymbol(math, op, "\u22c1", "\\bigvee"); -defineSymbol(math, op, "\u22c0", "\\bigwedge"); -defineSymbol(math, op, "\u2a04", "\\biguplus"); -defineSymbol(math, op, "\u22c2", "\\bigcap"); -defineSymbol(math, op, "\u22c3", "\\bigcup"); -defineSymbol(math, op, "\u222b", "\\int"); -defineSymbol(math, op, "\u222b", "\\intop"); -defineSymbol(math, op, "\u222c", "\\iint"); -defineSymbol(math, op, "\u222d", "\\iiint"); -defineSymbol(math, op, "\u220f", "\\prod"); -defineSymbol(math, op, "\u2211", "\\sum"); -defineSymbol(math, op, "\u2a02", "\\bigotimes"); -defineSymbol(math, op, "\u2a01", "\\bigoplus"); -defineSymbol(math, op, "\u2a00", "\\bigodot"); -defineSymbol(math, op, "\u222e", "\\oint"); -defineSymbol(math, op, "\u222f", "\\oiint"); -defineSymbol(math, op, "\u2230", "\\oiiint"); -defineSymbol(math, op, "\u2231", "\\intclockwise"); -defineSymbol(math, op, "\u2232", "\\varointclockwise"); -defineSymbol(math, op, "\u2a0c", "\\iiiint"); -defineSymbol(math, op, "\u2a0d", "\\intbar"); -defineSymbol(math, op, "\u2a0e", "\\intBar"); -defineSymbol(math, op, "\u2a0f", "\\fint"); -defineSymbol(math, op, "\u2a12", "\\rppolint"); -defineSymbol(math, op, "\u2a13", "\\scpolint"); -defineSymbol(math, op, "\u2a15", "\\pointint"); -defineSymbol(math, op, "\u2a16", "\\sqint"); -defineSymbol(math, op, "\u2a17", "\\intlarhk"); -defineSymbol(math, op, "\u2a18", "\\intx"); -defineSymbol(math, op, "\u2a19", "\\intcap"); -defineSymbol(math, op, "\u2a1a", "\\intcup"); -defineSymbol(math, op, "\u2a05", "\\bigsqcap"); -defineSymbol(math, op, "\u2a06", "\\bigsqcup"); -defineSymbol(math, op, "\u222b", "\\smallint"); -defineSymbol(text, inner, "\u2026", "\\textellipsis"); -defineSymbol(math, inner, "\u2026", "\\mathellipsis"); -defineSymbol(text, inner, "\u2026", "\\ldots", true); -defineSymbol(math, inner, "\u2026", "\\ldots", true); -defineSymbol(math, inner, "\u22f0", "\\iddots", true); -defineSymbol(math, inner, "\u22ef", "\\@cdots", true); -defineSymbol(math, inner, "\u22f1", "\\ddots", true); -defineSymbol(math, textord, "\u22ee", "\\varvdots"); // \vdots is a macro -defineSymbol(math, accent, "\u02ca", "\\acute"); -defineSymbol(math, accent, "\u0060", "\\grave"); -defineSymbol(math, accent, "\u00a8", "\\ddot"); -defineSymbol(math, accent, "\u20db", "\\dddot"); -defineSymbol(math, accent, "\u20dc", "\\ddddot"); -defineSymbol(math, accent, "\u007e", "\\tilde"); -defineSymbol(math, accent, "\u203e", "\\bar"); -defineSymbol(math, accent, "\u02d8", "\\breve"); -defineSymbol(math, accent, "\u02c7", "\\check"); -defineSymbol(math, accent, "\u005e", "\\hat"); -defineSymbol(math, accent, "\u20d7", "\\vec"); -defineSymbol(math, accent, "\u02d9", "\\dot"); -defineSymbol(math, accent, "\u02da", "\\mathring"); -defineSymbol(math, mathord, "\u0131", "\\imath", true); -defineSymbol(math, mathord, "\u0237", "\\jmath", true); -defineSymbol(math, textord, "\u0131", "\u0131"); -defineSymbol(math, textord, "\u0237", "\u0237"); -defineSymbol(text, textord, "\u0131", "\\i", true); -defineSymbol(text, textord, "\u0237", "\\j", true); -defineSymbol(text, textord, "\u00df", "\\ss", true); -defineSymbol(text, textord, "\u00e6", "\\ae", true); -defineSymbol(text, textord, "\u0153", "\\oe", true); -defineSymbol(text, textord, "\u00f8", "\\o", true); -defineSymbol(math, mathord, "\u00f8", "\\o", true); -defineSymbol(text, textord, "\u00c6", "\\AE", true); -defineSymbol(text, textord, "\u0152", "\\OE", true); -defineSymbol(text, textord, "\u00d8", "\\O", true); -defineSymbol(math, mathord, "\u00d8", "\\O", true); -defineSymbol(text, accent, "\u02ca", "\\'"); // acute -defineSymbol(text, accent, "\u02cb", "\\`"); // grave -defineSymbol(text, accent, "\u02c6", "\\^"); // circumflex -defineSymbol(text, accent, "\u02dc", "\\~"); // tilde -defineSymbol(text, accent, "\u02c9", "\\="); // macron -defineSymbol(text, accent, "\u02d8", "\\u"); // breve -defineSymbol(text, accent, "\u02d9", "\\."); // dot above -defineSymbol(text, accent, "\u00b8", "\\c"); // cedilla -defineSymbol(text, accent, "\u02da", "\\r"); // ring above -defineSymbol(text, accent, "\u02c7", "\\v"); // caron -defineSymbol(text, accent, "\u00a8", '\\"'); // diaresis -defineSymbol(text, accent, "\u02dd", "\\H"); // double acute -defineSymbol(math, accent, "\u02ca", "\\'"); // acute -defineSymbol(math, accent, "\u02cb", "\\`"); // grave -defineSymbol(math, accent, "\u02c6", "\\^"); // circumflex -defineSymbol(math, accent, "\u02dc", "\\~"); // tilde -defineSymbol(math, accent, "\u02c9", "\\="); // macron -defineSymbol(math, accent, "\u02d8", "\\u"); // breve -defineSymbol(math, accent, "\u02d9", "\\."); // dot above -defineSymbol(math, accent, "\u00b8", "\\c"); // cedilla -defineSymbol(math, accent, "\u02da", "\\r"); // ring above -defineSymbol(math, accent, "\u02c7", "\\v"); // caron -defineSymbol(math, accent, "\u00a8", '\\"'); // diaresis -defineSymbol(math, accent, "\u02dd", "\\H"); // double acute - -// These ligatures are detected and created in Parser.js's `formLigatures`. -const ligatures = { - "--": true, - "---": true, - "``": true, - "''": true -}; - -defineSymbol(text, textord, "\u2013", "--", true); -defineSymbol(text, textord, "\u2013", "\\textendash"); -defineSymbol(text, textord, "\u2014", "---", true); -defineSymbol(text, textord, "\u2014", "\\textemdash"); -defineSymbol(text, textord, "\u2018", "`", true); -defineSymbol(text, textord, "\u2018", "\\textquoteleft"); -defineSymbol(text, textord, "\u2019", "'", true); -defineSymbol(text, textord, "\u2019", "\\textquoteright"); -defineSymbol(text, textord, "\u201c", "``", true); -defineSymbol(text, textord, "\u201c", "\\textquotedblleft"); -defineSymbol(text, textord, "\u201d", "''", true); -defineSymbol(text, textord, "\u201d", "\\textquotedblright"); -// \degree from gensymb package -defineSymbol(math, textord, "\u00b0", "\\degree", true); -defineSymbol(text, textord, "\u00b0", "\\degree"); -// \textdegree from inputenc package -defineSymbol(text, textord, "\u00b0", "\\textdegree", true); -// TODO: In LaTeX, \pounds can generate a different character in text and math -// mode, but among our fonts, only Main-Regular defines this character "163". -defineSymbol(math, textord, "\u00a3", "\\pounds"); -defineSymbol(math, textord, "\u00a3", "\\mathsterling", true); -defineSymbol(text, textord, "\u00a3", "\\pounds"); -defineSymbol(text, textord, "\u00a3", "\\textsterling", true); -defineSymbol(math, textord, "\u2720", "\\maltese"); -defineSymbol(text, textord, "\u2720", "\\maltese"); -defineSymbol(math, textord, "\u20ac", "\\euro", true); -defineSymbol(text, textord, "\u20ac", "\\euro", true); -defineSymbol(text, textord, "\u20ac", "\\texteuro"); -defineSymbol(math, textord, "\u00a9", "\\copyright", true); -defineSymbol(text, textord, "\u00a9", "\\textcopyright"); - -// Italic Greek -defineSymbol(math, textord, "𝛤", "\\varGamma"); -defineSymbol(math, textord, "𝛥", "\\varDelta"); -defineSymbol(math, textord, "𝛩", "\\varTheta"); -defineSymbol(math, textord, "𝛬", "\\varLambda"); -defineSymbol(math, textord, "𝛯", "\\varXi"); -defineSymbol(math, textord, "𝛱", "\\varPi"); -defineSymbol(math, textord, "𝛴", "\\varSigma"); -defineSymbol(math, textord, "𝛶", "\\varUpsilon"); -defineSymbol(math, textord, "𝛷", "\\varPhi"); -defineSymbol(math, textord, "𝛹", "\\varPsi"); -defineSymbol(math, textord, "𝛺", "\\varOmega"); -defineSymbol(text, textord, "𝛤", "\\varGamma"); -defineSymbol(text, textord, "𝛥", "\\varDelta"); -defineSymbol(text, textord, "𝛩", "\\varTheta"); -defineSymbol(text, textord, "𝛬", "\\varLambda"); -defineSymbol(text, textord, "𝛯", "\\varXi"); -defineSymbol(text, textord, "𝛱", "\\varPi"); -defineSymbol(text, textord, "𝛴", "\\varSigma"); -defineSymbol(text, textord, "𝛶", "\\varUpsilon"); -defineSymbol(text, textord, "𝛷", "\\varPhi"); -defineSymbol(text, textord, "𝛹", "\\varPsi"); -defineSymbol(text, textord, "𝛺", "\\varOmega"); - - -// There are lots of symbols which are the same, so we add them in afterwards. -// All of these are textords in math mode -const mathTextSymbols = '0123456789/@."'; -for (let i = 0; i < mathTextSymbols.length; i++) { - const ch = mathTextSymbols.charAt(i); - defineSymbol(math, textord, ch, ch); -} - -// All of these are textords in text mode -const textSymbols = '0123456789!@*()-=+";:?/.,'; -for (let i = 0; i < textSymbols.length; i++) { - const ch = textSymbols.charAt(i); - defineSymbol(text, textord, ch, ch); -} - -// All of these are textords in text mode, and mathords in math mode -const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -for (let i = 0; i < letters.length; i++) { - const ch = letters.charAt(i); - defineSymbol(math, mathord, ch, ch); - defineSymbol(text, textord, ch, ch); -} - -// Some more letters in Unicode Basic Multilingual Plane. -const narrow = "ÇÐÞçþℂℍℕℙℚℝℤℎℏℊℋℌℐℑℒℓ℘ℛℜℬℰℱℳℭℨ"; -for (let i = 0; i < narrow.length; i++) { - const ch = narrow.charAt(i); - defineSymbol(math, mathord, ch, ch); - defineSymbol(text, textord, ch, ch); -} - -// The next loop loads wide (surrogate pair) characters. -// We support some letters in the Unicode range U+1D400 to U+1D7FF, -// Mathematical Alphanumeric Symbols. -let wideChar = ""; -for (let i = 0; i < letters.length; i++) { - // The hex numbers in the next line are a surrogate pair. - // 0xD835 is the high surrogate for all letters in the range we support. - // 0xDC00 is the low surrogate for bold A. - wideChar = String.fromCharCode(0xd835, 0xdc00 + i); // A-Z a-z bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdc34 + i); // A-Z a-z italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdc68 + i); // A-Z a-z bold italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdd04 + i); // A-Z a-z Fractur - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdda0 + i); // A-Z a-z sans-serif - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xddd4 + i); // A-Z a-z sans bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xde08 + i); // A-Z a-z sans italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xde70 + i); // A-Z a-z monospace - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdd38 + i); // A-Z a-z double struck - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - const ch = letters.charAt(i); - wideChar = String.fromCharCode(0xd835, 0xdc9c + i); // A-Z a-z calligraphic - defineSymbol(math, mathord, ch, wideChar); - defineSymbol(text, textord, ch, wideChar); -} - -// Next, some wide character numerals -for (let i = 0; i < 10; i++) { - wideChar = String.fromCharCode(0xd835, 0xdfce + i); // 0-9 bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdfe2 + i); // 0-9 sans serif - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdfec + i); // 0-9 bold sans - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdff6 + i); // 0-9 monospace - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); -} - -/* - * Neither Firefox nor Chrome support hard line breaks or soft line breaks. - * (Despite https://www.w3.org/Math/draft-spec/mathml.html#chapter3_presm.lbattrs) - * So Temml has work-arounds for both hard and soft breaks. - * The work-arounds sadly do not work simultaneously. Any top-level hard - * break makes soft line breaks impossible. - * - * Hard breaks are simulated by creating a and putting each line in its own . - * - * To create soft line breaks, Temml avoids using the and tags. - * Then the top level of a element can be occupied by elements, and the browser - * will break after a if the expression extends beyond the container limit. - * - * We want the expression to render with soft line breaks after each top-level binary or - * relational operator, per TeXbook p. 173. So we gather the expression into s so that - * each ends in a binary or relational operator. - * - * Soft line breaks will not work in Chromium and Safari, only Firefox. - * - * Hopefully browsers will someday do their own linebreaking and we will be able to delete - * much of this module. - */ - -function setLineBreaks(expression, isDisplayMode, isAnnotated, color = undefined) { - if (color === undefined) { - // First, make one pass through the expression and split any color nodes. - const upperLimit = expression.length - 1; - for (let i = upperLimit; i >= 0; i--) { - const node = expression[i]; - if (node.type === "mstyle" && node.attributes.mathcolor) { - const color = node.attributes.mathcolor; - const fragment = setLineBreaks(node.children, isDisplayMode, isAnnotated, color); - if (!(fragment.type && fragment.type !== "mtable")) { - expression.splice(i, 1, ...fragment.children); - - } - } - } - } - - const tagName = color ? "mstyle" : "mrow"; - - const mtrs = []; - let mrows = []; - let block = []; - let canBeBIN = false; // The first node cannot be an infix binary operator. - for (let i = 0; i < expression.length; i++) { - const node = expression[i]; - if (node.type && node.type === "mstyle" && node.attributes.mathcolor) { - // Start a new block. (Insert a soft linebreak.) - mrows.push(new mathMLTree.MathNode(tagName, block)); - // Insert the mstyle - mrows.push(node); - block = []; - continue - } - if (node.attributes && node.attributes.linebreak && - node.attributes.linebreak === "newline") { - // A hard line break. Create a for the current block. - if (block.length > 0) { - const element = new mathMLTree.MathNode(tagName, block); - if (color) { element.setAttribute("mathcolor", color); } - mrows.push(new mathMLTree.MathNode(tagName, block)); - } - mrows.push(node); - block = []; - const mtd = new mathMLTree.MathNode("mtd", mrows); - mtrs.push(new mathMLTree.MathNode("mtr", [mtd])); - mrows = []; - continue - } - block.push(node); - if (node.type && node.type === "mo" && !isDisplayMode && !isAnnotated) { - // This may be a place for a soft line break. - if (canBeBIN && !node.attributes.form) { - // Check if the following node is a \nobreak text node, e.g. "~"" - const next = i < expression.length - 1 ? expression[i + 1] : null; - let glueIsFreeOfNobreak = true; - if ( - !( - next && - next.type === "mtext" && - next.attributes.linebreak && - next.attributes.linebreak === "nobreak" - ) - ) { - // We may need to start a new block. - // First, put any post-operator glue on same line as operator. - for (let j = i + 1; j < expression.length; j++) { - const nd = expression[j]; - if ( - nd.type && - nd.type === "mspace" && - !(nd.attributes.linebreak && nd.attributes.linebreak === "newline") - ) { - block.push(nd); - i += 1; - if ( - nd.attributes && - nd.attributes.linebreak && - nd.attributes.linebreak === "nobreak" - ) { - glueIsFreeOfNobreak = false; - } - } else { - break; - } - } - } - if (glueIsFreeOfNobreak) { - // Start a new block. (Insert a soft linebreak.) - const element = new mathMLTree.MathNode(tagName, block); - if (color) { element.setAttribute("mathcolor", color); } - mrows.push(element); - block = []; - } - canBeBIN = false; - } - const isOpenDelimiter = node.attributes.form && node.attributes.form === "prefix"; - // Any operator that follows an open delimiter is unary. - canBeBIN = !(node.attributes.separator || isOpenDelimiter); - } else { - canBeBIN = true; - } - } - if (block.length > 0) { - const element = new mathMLTree.MathNode(tagName, block); - if (color) { element.setAttribute("mathcolor", color); } - mrows.push(element); - } - if (mtrs.length > 0) { - const mtd = new mathMLTree.MathNode("mtd", mrows); - const mtr = new mathMLTree.MathNode("mtr", [mtd]); - mtrs.push(mtr); - const mtable = new mathMLTree.MathNode("mtable", mtrs); - if (!isDisplayMode) { - mtable.setAttribute("columnalign", "left"); - mtable.setAttribute("rowspacing", "0em"); - } - return mtable - } - return mathMLTree.newDocumentFragment(mrows); -} - -/** - * This file converts a parse tree into a cooresponding MathML tree. The main - * entry point is the `buildMathML` function, which takes a parse tree from the - * parser. - */ - -/** - * Takes a symbol and converts it into a MathML text node after performing - * optional replacement from symbols.js. - */ -const makeText = function(text, mode, style) { - if ( - symbols[mode][text] && - symbols[mode][text].replace && - text.charCodeAt(0) !== 0xd835 && - !( - Object.prototype.hasOwnProperty.call(ligatures, text) && - style && - ((style.fontFamily && style.fontFamily.slice(4, 6) === "tt") || - (style.font && style.font.slice(4, 6) === "tt")) - ) - ) { - text = symbols[mode][text].replace; - } - - return new mathMLTree.TextNode(text); -}; - -/** - * Wrap the given array of nodes in an node if needed, i.e., - * unless the array has length 1. Always returns a single node. - */ -const makeRow = function(body) { - if (body.length === 1) { - return body[0]; - } else { - return new mathMLTree.MathNode("mrow", body); - } -}; - -const isRel = item => { - return (item.type === "atom" && item.family === "rel") || - (item.type === "mclass" && item.mclass === "mrel") -}; - -/** - * Takes a list of nodes, builds them, and returns a list of the generated - * MathML nodes. Also do a couple chores along the way: - * (1) Suppress spacing when an author wraps an operator w/braces, as in {=}. - * (2) Suppress spacing between two adjacent relations. - */ -const buildExpression = function(expression, style, isOrdgroup) { - if (expression.length === 1) { - const group = buildGroup$1(expression[0], style); - if (isOrdgroup && group instanceof MathNode && group.type === "mo") { - // When TeX writers want to suppress spacing on an operator, - // they often put the operator by itself inside braces. - group.setAttribute("lspace", "0em"); - group.setAttribute("rspace", "0em"); - } - return [group]; - } - - const groups = []; - for (let i = 0; i < expression.length; i++) { - const group = buildGroup$1(expression[i], style); - // Suppress spacing between adjacent relations - if (i < expression.length - 1 && isRel(expression[i]) && isRel(expression[i + 1])) { - group.setAttribute("rspace", "0em"); - } - if (i > 0 && isRel(expression[i]) && isRel(expression[i - 1])) { - group.setAttribute("lspace", "0em"); - } - groups.push(group); - } - return groups; -}; - -/** - * Equivalent to buildExpression, but wraps the elements in an - * if there's more than one. Returns a single node instead of an array. - */ -const buildExpressionRow = function(expression, style, isOrdgroup) { - return makeRow(buildExpression(expression, style, isOrdgroup)); -}; - -/** - * Takes a group from the parser and calls the appropriate groupBuilders function - * on it to produce a MathML node. - */ -const buildGroup$1 = function(group, style) { - if (!group) { - return new mathMLTree.MathNode("mrow"); - } - - if (_mathmlGroupBuilders[group.type]) { - // Call the groupBuilders function - const result = _mathmlGroupBuilders[group.type](group, style); - return result; - } else { - throw new ParseError("Got group of unknown type: '" + group.type + "'"); - } -}; - -const glue = _ => { - const glueNode = new mathMLTree.MathNode("mtd", []); - glueNode.setAttribute("style", "padding: 0;width: 50%;"); - return glueNode -}; - -const taggedExpression = (expression, tag, style, leqno, preventTagLap) => { - tag = buildExpressionRow(tag[0].body, style); - tag = utils.consolidateText(tag); - tag.classes = ["tml-tag"]; - if (!preventTagLap) { - tag = new mathMLTree.MathNode("mpadded", [tag]); - tag.setAttribute("style", "width:0;"); - tag.setAttribute("width", "0"); - tag.setAttribute((leqno ? "rspace" : "lspace"), "-1width"); - } - tag = new mathMLTree.MathNode("mtd", [tag]); - if (!preventTagLap) { tag.setAttribute("style", "padding: 0; min-width:0"); } - - expression = new mathMLTree.MathNode("mtd", [expression]); - const rowArray = leqno - ? [tag, glue(), expression, glue()] - : [glue(), expression, glue(), tag]; - const mtr = new mathMLTree.MathNode("mtr", rowArray, ["tml-tageqn"]); - const table = new mathMLTree.MathNode("mtable", [mtr]); - table.setAttribute("width", "100%"); - table.setAttribute("displaystyle", "true"); - return table -}; - -/** - * Takes a full parse tree and settings and builds a MathML representation of - * it. - */ -function buildMathML(tree, texExpression, style, settings) { - // Strip off outer tag wrapper for processing below. - let tag = null; - if (tree.length === 1 && tree[0].type === "tag") { - tag = tree[0].tag; - tree = tree[0].body; - } - - const expression = buildExpression(tree, style); - - const n1 = expression.length === 0 ? null : expression[0]; - let wrapper = expression.length === 1 && tag === null && (n1 instanceof MathNode) - && !(n1.type === "mstyle" && n1.attributes.mathcolor) - ? expression[0] - : setLineBreaks(expression, settings.displayMode, settings.annotate); - - if (tag) { - wrapper = taggedExpression(wrapper, tag, style, settings.leqno, settings.preventTagLap); - } - - let semantics; - if (settings.annotate) { - // Build a TeX annotation of the source - const annotation = new mathMLTree.MathNode( - "annotation", [new mathMLTree.TextNode(texExpression)]); - annotation.setAttribute("encoding", "application/x-tex"); - semantics = new mathMLTree.MathNode("semantics", [wrapper, annotation]); - } - - const math = settings.annotate - ? new mathMLTree.MathNode("math", [semantics]) - : new mathMLTree.MathNode("math", [wrapper]); - - if (settings.xml) { - math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML"); - } - if (settings.displayMode) { - math.setAttribute("display", "block"); - } - return math; -} - -const mathmlBuilder$a = (group, style) => { - const accentNode = group.isStretchy - ? stretchy.mathMLnode(group.label) - : new mathMLTree.MathNode("mo", [makeText(group.label, group.mode)]); - - if (!group.isStretchy) { - accentNode.setAttribute("stretchy", "false"); - } - - const node = new mathMLTree.MathNode((group.label === "\\c" ? "munder" : "mover"), - [buildGroup$1(group.base, style), accentNode] - ); - - node.setAttribute("accent", "true"); - return node; -}; - -const NON_STRETCHY_ACCENT_REGEX = new RegExp( - [ - "\\acute", - "\\grave", - "\\ddot", - "\\dddot", - "\\ddddot", - "\\tilde", - "\\bar", - "\\breve", - "\\check", - "\\hat", - "\\vec", - "\\dot", - "\\mathring" - ] - .map((accent) => `\\${accent}`) - .join("|") -); - -// Accents -defineFunction({ - type: "accent", - names: [ - "\\acute", - "\\grave", - "\\ddot", - "\\dddot", - "\\ddddot", - "\\tilde", - "\\bar", - "\\breve", - "\\check", - "\\hat", - "\\vec", - "\\dot", - "\\mathring", - "\\overparen", - "\\widecheck", - "\\widehat", - "\\wideparen", - "\\widetilde", - "\\overrightarrow", - "\\overleftarrow", - "\\Overrightarrow", - "\\overleftrightarrow", - "\\overgroup", - "\\overleftharpoon", - "\\overrightharpoon" - ], - props: { - numArgs: 1 - }, - handler: (context, args) => { - const base = normalizeArgument(args[0]); - - const isStretchy = !NON_STRETCHY_ACCENT_REGEX.test(context.funcName); - const isShifty = - !isStretchy || - context.funcName === "\\widehat" || - context.funcName === "\\widetilde" || - context.funcName === "\\widecheck"; - - return { - type: "accent", - mode: context.parser.mode, - label: context.funcName, - isStretchy: isStretchy, - isShifty: isShifty, - base: base - }; - }, - mathmlBuilder: mathmlBuilder$a -}); - -// Text-mode accents -defineFunction({ - type: "accent", - names: ["\\'", "\\`", "\\^", "\\~", "\\=", "\\c", "\\u", "\\.", '\\"', "\\r", "\\H", "\\v"], - props: { - numArgs: 1, - allowedInText: true, - allowedInMath: true, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const base = normalizeArgument(args[0]); - const mode = context.parser.mode; - - if (mode === "math" && context.parser.settings.strict) { - // LaTeX only writes a warning. It doesn't stop. We'll issue the same warning. - // eslint-disable-next-line no-console - console.log(`Temml parse error: Command ${context.funcName} is invalid in math mode.`); - } - - return { - type: "accent", - mode: mode, - label: context.funcName, - isStretchy: false, - isShifty: true, - base: base - }; - }, - mathmlBuilder: mathmlBuilder$a -}); - -defineFunction({ - type: "accentUnder", - names: [ - "\\underleftarrow", - "\\underrightarrow", - "\\underleftrightarrow", - "\\undergroup", - "\\underparen", - "\\utilde" - ], - props: { - numArgs: 1 - }, - handler: ({ parser, funcName }, args) => { - const base = args[0]; - return { - type: "accentUnder", - mode: parser.mode, - label: funcName, - base: base - }; - }, - mathmlBuilder: (group, style) => { - const accentNode = stretchy.mathMLnode(group.label); - const node = new mathMLTree.MathNode("munder", [ - buildGroup$1(group.base, style), - accentNode - ]); - node.setAttribute("accentunder", "true"); - return node; - } -}); - -/** - * This file does conversion between units. In particular, it provides - * calculateSize to convert other units into CSS units. - */ - -const ptPerUnit = { - // Convert to CSS (Postscipt) points, not TeX points - // https://en.wikibooks.org/wiki/LaTeX/Lengths and - // https://tex.stackexchange.com/a/8263 - pt: 800 / 803, // convert TeX point to CSS (Postscript) point - pc: (12 * 800) / 803, // pica - dd: ((1238 / 1157) * 800) / 803, // didot - cc: ((14856 / 1157) * 800) / 803, // cicero (12 didot) - nd: ((685 / 642) * 800) / 803, // new didot - nc: ((1370 / 107) * 800) / 803, // new cicero (12 new didot) - sp: ((1 / 65536) * 800) / 803, // scaled point (TeX's internal smallest unit) - mm: (25.4 / 72), - cm: (2.54 / 72), - in: (1 / 72), - px: (96 / 72) -}; - -/** - * Determine whether the specified unit (either a string defining the unit - * or a "size" parse node containing a unit field) is valid. - */ -const validUnits = [ - "em", - "ex", - "mu", - "pt", - "mm", - "cm", - "in", - "px", - "bp", - "pc", - "dd", - "cc", - "nd", - "nc", - "sp" -]; - -const validUnit = function(unit) { - if (typeof unit !== "string") { - unit = unit.unit; - } - return validUnits.indexOf(unit) > -1 -}; - -const emScale = styleLevel => { - const scriptLevel = Math.max(styleLevel - 1, 0); - return [1, 0.7, 0.5][scriptLevel] -}; - -/* - * Convert a "size" parse node (with numeric "number" and string "unit" fields, - * as parsed by functions.js argType "size") into a CSS value. - */ -const calculateSize = function(sizeValue, style) { - let number = sizeValue.number; - if (style.maxSize[0] < 0 && number > 0) { - return { number: 0, unit: "em" } - } - const unit = sizeValue.unit; - switch (unit) { - case "mm": - case "cm": - case "in": - case "px": { - const numInCssPts = number * ptPerUnit[unit]; - if (numInCssPts > style.maxSize[1]) { - return { number: style.maxSize[1], unit: "pt" } - } - return { number, unit }; // absolute CSS units. - } - case "em": - case "ex": { - // In TeX, em and ex do not change size in \scriptstyle. - if (unit === "ex") { number *= 0.431; } - number = Math.min(number / emScale(style.level), style.maxSize[0]); - return { number: utils.round(number), unit: "em" }; - } - case "bp": { - if (number > style.maxSize[1]) { number = style.maxSize[1]; } - return { number, unit: "pt" }; // TeX bp is a CSS pt. (1/72 inch). - } - case "pt": - case "pc": - case "dd": - case "cc": - case "nd": - case "nc": - case "sp": { - number = Math.min(number * ptPerUnit[unit], style.maxSize[1]); - return { number: utils.round(number), unit: "pt" } - } - case "mu": { - number = Math.min(number / 18, style.maxSize[0]); - return { number: utils.round(number), unit: "em" } - } - default: - throw new ParseError("Invalid unit: '" + unit + "'") - } -}; - -// Helper functions -const paddedNode = (group, width, lspace = "0.3em") => { - const node = new mathMLTree.MathNode("mpadded", group ? [group] : []); - node.setAttribute("width", width); - node.setAttribute("lspace", lspace); - return node; -}; - -const labelSize = (size, scriptLevel) => (size / emScale(scriptLevel)).toFixed(4) + "em"; - -const munderoverNode = (name, body, below, style) => { - const arrowNode = stretchy.mathMLnode(name); - // Is this the short part of a mhchem equilibrium arrow? - const isEq = name.slice(1, 3) === "eq"; - const minWidth = name.charAt(1) === "x" - ? "1.75" // mathtools extensible arrows are 1.75em long - : name.slice(2, 4) === "cd" - ? "3.0" // cd package arrows - : isEq - ? "1.0" // The shorter harpoon of a mhchem equilibrium arrow - : "2.0"; // other mhchem arrows - arrowNode.setAttribute("minsize", String(minWidth) + "em"); - arrowNode.setAttribute("lspace", "0"); - arrowNode.setAttribute("rspace", (isEq ? "0.5em" : "0")); - - // upper and lower labels are set to scriptlevel by MathML - // So we have to adjust our dimensions accordingly. - const labelStyle = style.withLevel(style.level < 2 ? 2 : 3); - const emptyLabelWidth = labelSize(minWidth, labelStyle.level); - const lspace = labelSize((isEq ? 0 : 0.3), labelStyle.level); - let widthAdder = labelSize((isEq ? -0.4 : 0.6), labelStyle.level); - if (widthAdder.charAt(0) !== "-") { widthAdder = "+" + widthAdder; } - - const upperNode = (body && body.body && - // \hphantom visible content - (body.body.body || body.body.length > 0)) - ? paddedNode(buildGroup$1(body, labelStyle), widthAdder, lspace) - // Since Firefox does not recognize minsize set on the arrow, - // create an upper node w/correct width. - : paddedNode(null, emptyLabelWidth, "0"); - const lowerNode = (below && below.body && - (below.body.body || below.body.length > 0)) - ? paddedNode(buildGroup$1(below, labelStyle), widthAdder, lspace) - : paddedNode(null, emptyLabelWidth, "0"); - const node = new mathMLTree.MathNode("munderover", [arrowNode, lowerNode, upperNode]); - return node -}; - -// Stretchy arrows with an optional argument -defineFunction({ - type: "xArrow", - names: [ - "\\xleftarrow", - "\\xrightarrow", - "\\xLeftarrow", - "\\xRightarrow", - "\\xleftrightarrow", - "\\xLeftrightarrow", - "\\xhookleftarrow", - "\\xhookrightarrow", - "\\xmapsto", - "\\xrightharpoondown", - "\\xrightharpoonup", - "\\xleftharpoondown", - "\\xleftharpoonup", - "\\xlongequal", - "\\xtwoheadrightarrow", - "\\xtwoheadleftarrow", - // The next 7 functions are here only to support mhchem - "\\yields", - "\\yieldsLeft", - "\\mesomerism", - "\\longrightharpoonup", - "\\longleftharpoondown", - // The next 3 functions are here only to support the {CD} environment. - "\\\\cdrightarrow", - "\\\\cdleftarrow", - "\\\\cdlongequal" - ], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser, funcName }, args, optArgs) { - return { - type: "xArrow", - mode: parser.mode, - name: funcName, - body: args[0], - below: optArgs[0] - }; - }, - mathmlBuilder(group, style) { - // Build the arrow and its labels. - const node = munderoverNode(group.name, group.body, group.below, style); - // Create operator spacing for a relation. - const wrapper = new mathMLTree.MathNode("mpadded", [node]); - wrapper.setAttribute("lspace", "0.2778em"); - wrapper.setAttribute("width", "+0.5556em"); - return wrapper - } -}); - -const arrowComponent = { - "\\xtofrom": ["\\xrightarrow", "\\xleftarrow"], - "\\xleftrightharpoons": ["\\xleftharpoonup", "\\xrightharpoondown"], - "\\xrightleftharpoons": ["\\xrightharpoonup", "\\xleftharpoondown"], - "\\yieldsLeftRight": ["\\yields", "\\yieldsLeft"], - // The next three all get the same harpoon glyphs. Only the lengths and paddings differ. - "\\equilibrium": ["\\longrightharpoonup", "\\longleftharpoondown"], - "\\equilibriumRight": ["\\longrightharpoonup", "\\eqleftharpoondown"], - "\\equilibriumLeft": ["\\eqrightharpoonup", "\\longleftharpoondown"] -}; - -// Browsers are not good at stretching a glyph that contains a pair of stacked arrows such as ⇄. -// So we stack a pair of single arrows. -defineFunction({ - type: "stackedArrow", - names: [ - "\\xtofrom", // expfeil - "\\xleftrightharpoons", // mathtools - "\\xrightleftharpoons", // mathtools - "\\yieldsLeftRight", // mhchem - "\\equilibrium", // mhchem - "\\equilibriumRight", - "\\equilibriumLeft" - ], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser, funcName }, args, optArgs) { - const lowerArrowBody = args[0] - ? { - type: "hphantom", - mode: parser.mode, - body: args[0] - } - : null; - const upperArrowBelow = optArgs[0] - ? { - type: "hphantom", - mode: parser.mode, - body: optArgs[0] - } - : null; - return { - type: "stackedArrow", - mode: parser.mode, - name: funcName, - body: args[0], - upperArrowBelow, - lowerArrowBody, - below: optArgs[0] - }; - }, - mathmlBuilder(group, style) { - const topLabel = arrowComponent[group.name][0]; - const botLabel = arrowComponent[group.name][1]; - const topArrow = munderoverNode(topLabel, group.body, group.upperArrowBelow, style); - const botArrow = munderoverNode(botLabel, group.lowerArrowBody, group.below, style); - let wrapper; - - const raiseNode = new mathMLTree.MathNode("mpadded", [topArrow]); - raiseNode.setAttribute("voffset", "0.3em"); - raiseNode.setAttribute("height", "+0.3em"); - raiseNode.setAttribute("depth", "-0.3em"); - // One of the arrows is given ~zero width. so the other has the same horzontal alignment. - if (group.name === "\\equilibriumLeft") { - const botNode = new mathMLTree.MathNode("mpadded", [botArrow]); - botNode.setAttribute("width", "0.5em"); - wrapper = new mathMLTree.MathNode("mpadded", [botNode, raiseNode]); - } else { - raiseNode.setAttribute("width", (group.name === "\\equilibriumRight" ? "0.5em" : "0")); - wrapper = new mathMLTree.MathNode("mpadded", [raiseNode, botArrow]); - } - - wrapper.setAttribute("voffset", "-0.18em"); - wrapper.setAttribute("width", "+0.5556em"); - wrapper.setAttribute("height", "-0.18em"); - wrapper.setAttribute("depth", "+0.18em"); - wrapper.setAttribute("lspace", "0.2778em"); - return wrapper - } -}); - -defineFunction({ - type: "cancelto", - names: ["\\cancelto"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "cancelto", - mode: parser.mode, - value: args[0], - expression: args[1] - }; - }, - mathmlBuilder(group, style) { - const value = new mathMLTree.MathNode( - "mpadded", - [buildGroup$1(group.value, style)] - ); - value.setAttribute("depth", `-0.1em`); - value.setAttribute("height", `+0.1em`); - value.setAttribute("voffset", `0.1em`); - - const expression = new mathMLTree.MathNode( - "menclose", - [buildGroup$1(group.expression, style)] - ); - expression.setAttribute("notation", `updiagonalarrow`); - - return new mathMLTree.MathNode("msup", [expression, value]) - } -}); - -/** - * Asserts that the node is of the given type and returns it with stricter - * typing. Throws if the node's type does not match. - */ -function assertNodeType(node, type) { - if (!node || node.type !== type) { - throw new Error( - `Expected node of type ${type}, but got ` + - (node ? `node of type ${node.type}` : String(node)) - ); - } - return node; -} - -/** - * Returns the node more strictly typed iff it is of the given type. Otherwise, - * returns null. - */ -function assertSymbolNodeType(node) { - const typedNode = checkSymbolNodeType(node); - if (!typedNode) { - throw new Error( - `Expected node of symbol group type, but got ` + - (node ? `node of type ${node.type}` : String(node)) - ); - } - return typedNode; -} - -/** - * Returns the node more strictly typed iff it is of the given type. Otherwise, - * returns null. - */ -function checkSymbolNodeType(node) { - if (node && (node.type === "atom" || - Object.prototype.hasOwnProperty.call(NON_ATOMS, node.type))) { - return node; - } - return null; -} - -const cdArrowFunctionName = { - ">": "\\\\cdrightarrow", - "<": "\\\\cdleftarrow", - "=": "\\\\cdlongequal", - A: "\\uparrow", - V: "\\downarrow", - "|": "\\Vert", - ".": "no arrow" -}; - -const newCell = () => { - // Create an empty cell, to be filled below with parse nodes. - return { type: "styling", body: [], mode: "math", scriptLevel: "display" }; -}; - -const isStartOfArrow = (node) => { - return node.type === "textord" && node.text === "@"; -}; - -const isLabelEnd = (node, endChar) => { - return (node.type === "mathord" || node.type === "atom") && node.text === endChar; -}; - -function cdArrow(arrowChar, labels, parser) { - // Return a parse tree of an arrow and its labels. - // This acts in a way similar to a macro expansion. - const funcName = cdArrowFunctionName[arrowChar]; - switch (funcName) { - case "\\\\cdrightarrow": - case "\\\\cdleftarrow": - return parser.callFunction(funcName, [labels[0]], [labels[1]]); - case "\\uparrow": - case "\\downarrow": { - const leftLabel = parser.callFunction("\\\\cdleft", [labels[0]], []); - const bareArrow = { - type: "atom", - text: funcName, - mode: "math", - family: "rel" - }; - const sizedArrow = parser.callFunction("\\Big", [bareArrow], []); - const rightLabel = parser.callFunction("\\\\cdright", [labels[1]], []); - const arrowGroup = { - type: "ordgroup", - mode: "math", - body: [leftLabel, sizedArrow, rightLabel] - }; - return parser.callFunction("\\\\cdparent", [arrowGroup], []); - } - case "\\\\cdlongequal": - return parser.callFunction("\\\\cdlongequal", [], []); - case "\\Vert": { - const arrow = { type: "textord", text: "\\Vert", mode: "math" }; - return parser.callFunction("\\Big", [arrow], []); - } - default: - return { type: "textord", text: " ", mode: "math" }; - } -} - -function parseCD(parser) { - // Get the array's parse nodes with \\ temporarily mapped to \cr. - const parsedRows = []; - parser.gullet.beginGroup(); - parser.gullet.macros.set("\\cr", "\\\\\\relax"); - parser.gullet.beginGroup(); - while (true) { // eslint-disable-line no-constant-condition - // Get the parse nodes for the next row. - parsedRows.push(parser.parseExpression(false, "\\\\")); - parser.gullet.endGroup(); - parser.gullet.beginGroup(); - const next = parser.fetch().text; - if (next === "&" || next === "\\\\") { - parser.consume(); - } else if (next === "\\end") { - if (parsedRows[parsedRows.length - 1].length === 0) { - parsedRows.pop(); // final row ended in \\ - } - break; - } else { - throw new ParseError("Expected \\\\ or \\cr or \\end", parser.nextToken); - } - } - - let row = []; - const body = [row]; - - // Loop thru the parse nodes. Collect them into cells and arrows. - for (let i = 0; i < parsedRows.length; i++) { - // Start a new row. - const rowNodes = parsedRows[i]; - // Create the first cell. - let cell = newCell(); - - for (let j = 0; j < rowNodes.length; j++) { - if (!isStartOfArrow(rowNodes[j])) { - // If a parseNode is not an arrow, it goes into a cell. - cell.body.push(rowNodes[j]); - } else { - // Parse node j is an "@", the start of an arrow. - // Before starting on the arrow, push the cell into `row`. - row.push(cell); - - // Now collect parseNodes into an arrow. - // The character after "@" defines the arrow type. - j += 1; - const arrowChar = assertSymbolNodeType(rowNodes[j]).text; - - // Create two empty label nodes. We may or may not use them. - const labels = new Array(2); - labels[0] = { type: "ordgroup", mode: "math", body: [] }; - labels[1] = { type: "ordgroup", mode: "math", body: [] }; - - // Process the arrow. - if ("=|.".indexOf(arrowChar) > -1) ; else if ("<>AV".indexOf(arrowChar) > -1) { - // Four arrows, `@>>>`, `@<<<`, `@AAA`, and `@VVV`, each take - // two optional labels. E.g. the right-point arrow syntax is - // really: @>{optional label}>{optional label}> - // Collect parseNodes into labels. - for (let labelNum = 0; labelNum < 2; labelNum++) { - let inLabel = true; - for (let k = j + 1; k < rowNodes.length; k++) { - if (isLabelEnd(rowNodes[k], arrowChar)) { - inLabel = false; - j = k; - break; - } - if (isStartOfArrow(rowNodes[k])) { - throw new ParseError( - "Missing a " + arrowChar + " character to complete a CD arrow.", - rowNodes[k] - ); - } - - labels[labelNum].body.push(rowNodes[k]); - } - if (inLabel) { - // isLabelEnd never returned a true. - throw new ParseError( - "Missing a " + arrowChar + " character to complete a CD arrow.", - rowNodes[j] - ); - } - } - } else { - throw new ParseError(`Expected one of "<>AV=|." after @.`); - } - - // Now join the arrow to its labels. - const arrow = cdArrow(arrowChar, labels, parser); - - // Wrap the arrow in a styling node - row.push(arrow); - // In CD's syntax, cells are implicit. That is, everything that - // is not an arrow gets collected into a cell. So create an empty - // cell now. It will collect upcoming parseNodes. - cell = newCell(); - } - } - if (i % 2 === 0) { - // Even-numbered rows consist of: cell, arrow, cell, arrow, ... cell - // The last cell is not yet pushed into `row`, so: - row.push(cell); - } else { - // Odd-numbered rows consist of: vert arrow, empty cell, ... vert arrow - // Remove the empty cell that was placed at the beginning of `row`. - row.shift(); - } - row = []; - body.push(row); - } - - // End row group - parser.gullet.endGroup(); - // End array group defining \\ - parser.gullet.endGroup(); - - // define column separation. - const cols = new Array(body[0].length).fill({ - type: "align", - align: "c" - }); - - return { - type: "array", - mode: "math", - body, - arraystretch: 1, - addJot: true, - rowGaps: [null], - cols, - colSeparationType: "CD", - hLinesBeforeRow: new Array(body.length + 1).fill([]) - }; -} - -// The functions below are not available for general use. -// They are here only for internal use by the {CD} environment in placing labels -// next to vertical arrows. - -// We don't need any such functions for horizontal arrows because we can reuse -// the functionality that already exists for extensible arrows. - -defineFunction({ - type: "cdlabel", - names: ["\\\\cdleft", "\\\\cdright"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - return { - type: "cdlabel", - mode: parser.mode, - side: funcName.slice(4), - label: args[0] - }; - }, - mathmlBuilder(group, style) { - let label = new mathMLTree.MathNode("mrow", [buildGroup$1(group.label, style)]); - label = new mathMLTree.MathNode("mpadded", [label]); - label.setAttribute("width", "0"); - if (group.side === "left") { - label.setAttribute("lspace", "-1width"); - } - // We have to guess at vertical alignment. We know the arrow is 1.8em tall, - // But we don't know the height or depth of the label. - label.setAttribute("voffset", "0.7em"); - label = new mathMLTree.MathNode("mstyle", [label]); - label.setAttribute("displaystyle", "false"); - label.setAttribute("scriptlevel", "1"); - return label; - } -}); - -defineFunction({ - type: "cdlabelparent", - names: ["\\\\cdparent"], - props: { - numArgs: 1 - }, - handler({ parser }, args) { - return { - type: "cdlabelparent", - mode: parser.mode, - fragment: args[0] - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow", [buildGroup$1(group.fragment, style)]); - } -}); - -// \@char is an internal function that takes a grouped decimal argument like -// {123} and converts into symbol with code 123. It is used by the *macro* -// \char defined in macros.js. -defineFunction({ - type: "textord", - names: ["\\@char"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser, token }, args) { - const arg = assertNodeType(args[0], "ordgroup"); - const group = arg.body; - let number = ""; - for (let i = 0; i < group.length; i++) { - const node = assertNodeType(group[i], "textord"); - number += node.text; - } - const code = parseInt(number); - if (isNaN(code)) { - throw new ParseError(`\\@char has non-numeric argument ${number}`, token) - } - return { - type: "textord", - mode: parser.mode, - text: String.fromCodePoint(code) - } - } -}); - -// Helpers -const htmlRegEx = /^(#[a-f0-9]{3}|#?[a-f0-9]{6})$/i; -const htmlOrNameRegEx = /^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i; -const RGBregEx = /^ *\d{1,3} *(?:, *\d{1,3} *){2}$/; -const rgbRegEx = /^ *[10](?:\.\d*)? *(?:, *[10](?:\.\d*)? *){2}$/; -const xcolorHtmlRegEx = /^[a-f0-9]{6}$/i; -const toHex = num => { - let str = num.toString(16); - if (str.length === 1) { str = "0" + str; } - return str -}; - -// Colors from Tables 4.1 and 4.2 of the xcolor package. -// Table 4.1 (lower case) RGB values are taken from chroma and xcolor.dtx. -// Table 4.2 (Capitalizzed) values were sampled, because Chroma contains a unreliable -// conversion from cmyk to RGB. See https://tex.stackexchange.com/a/537274. -const xcolors = JSON.parse(`{ - "Apricot": "#ffb484", - "Aquamarine": "#08b4bc", - "Bittersweet": "#c84c14", - "blue": "#0000FF", - "Blue": "#303494", - "BlueGreen": "#08b4bc", - "BlueViolet": "#503c94", - "BrickRed": "#b8341c", - "brown": "#BF8040", - "Brown": "#802404", - "BurntOrange": "#f8941c", - "CadetBlue": "#78749c", - "CarnationPink": "#f884b4", - "Cerulean": "#08a4e4", - "CornflowerBlue": "#40ace4", - "cyan": "#00FFFF", - "Cyan": "#08acec", - "Dandelion": "#ffbc44", - "darkgray": "#404040", - "DarkOrchid": "#a8548c", - "Emerald": "#08ac9c", - "ForestGreen": "#089c54", - "Fuchsia": "#90348c", - "Goldenrod": "#ffdc44", - "gray": "#808080", - "Gray": "#98949c", - "green": "#00FF00", - "Green": "#08a44c", - "GreenYellow": "#e0e474", - "JungleGreen": "#08ac9c", - "Lavender": "#f89cc4", - "lightgray": "#c0c0c0", - "lime": "#BFFF00", - "LimeGreen": "#90c43c", - "magenta": "#FF00FF", - "Magenta": "#f0048c", - "Mahogany": "#b0341c", - "Maroon": "#b03434", - "Melon": "#f89c7c", - "MidnightBlue": "#086494", - "Mulberry": "#b03c94", - "NavyBlue": "#086cbc", - "olive": "#7F7F00", - "OliveGreen": "#407c34", - "orange": "#FF8000", - "Orange": "#f8843c", - "OrangeRed": "#f0145c", - "Orchid": "#b074ac", - "Peach": "#f8945c", - "Periwinkle": "#8074bc", - "PineGreen": "#088c74", - "pink": "#ff7f7f", - "Plum": "#98248c", - "ProcessBlue": "#08b4ec", - "purple": "#BF0040", - "Purple": "#a0449c", - "RawSienna": "#983c04", - "red": "#ff0000", - "Red": "#f01c24", - "RedOrange": "#f86434", - "RedViolet": "#a0246c", - "Rhodamine": "#f0549c", - "Royallue": "#0874bc", - "RoyalPurple": "#683c9c", - "RubineRed": "#f0047c", - "Salmon": "#f8948c", - "SeaGreen": "#30bc9c", - "Sepia": "#701404", - "SkyBlue": "#48c4dc", - "SpringGreen": "#c8dc64", - "Tan": "#e09c74", - "teal": "#007F7F", - "TealBlue": "#08acb4", - "Thistle": "#d884b4", - "Turquoise": "#08b4cc", - "violet": "#800080", - "Violet": "#60449c", - "VioletRed": "#f054a4", - "WildStrawberry": "#f0246c", - "yellow": "#FFFF00", - "Yellow": "#fff404", - "YellowGreen": "#98cc6c", - "YellowOrange": "#ffa41c" -}`); - -const colorFromSpec = (model, spec) => { - let color = ""; - if (model === "HTML") { - if (!htmlRegEx.test(spec)) { - throw new ParseError("Invalid HTML input.") - } - color = spec; - } else if (model === "RGB") { - if (!RGBregEx.test(spec)) { - throw new ParseError("Invalid RGB input.") - } - spec.split(",").map(e => { color += toHex(Number(e.trim())); }); - } else { - if (!rgbRegEx.test(spec)) { - throw new ParseError("Invalid rbg input.") - } - spec.split(",").map(e => { - const num = Number(e.trim()); - if (num > 1) { throw new ParseError("Color rgb input must be < 1.") } - color += toHex((num * 255)); - }); - } - if (color.charAt(0) !== "#") { color = "#" + color; } - return color -}; - -const validateColor = (color, macros, token) => { - const macroName = `\\\\color@${color}`; // from \defineColor. - const match = htmlOrNameRegEx.exec(color); - if (!match) { throw new ParseError("Invalid color: '" + color + "'", token) } - // We allow a 6-digit HTML color spec without a leading "#". - // This follows the xcolor package's HTML color model. - // Predefined color names are all missed by this RegEx pattern. - if (xcolorHtmlRegEx.test(color)) { - return "#" + color - } else if (color.charAt(0) === "#") { - return color - } else if (macros.has(macroName)) { - color = macros.get(macroName).tokens[0].text; - } else if (xcolors[color]) { - color = xcolors[color]; - } - return color -}; - -const mathmlBuilder$9 = (group, style) => { - const inner = buildExpression(group.body, style.withColor(group.color)); - // Wrap with an element. - const node = wrapWithMstyle(inner); - node.setAttribute("mathcolor", group.color); - // Wrap w/. We get better operator spacing that way. - return new mathMLTree.MathNode("mrow", [node]) -}; - -defineFunction({ - type: "color", - names: ["\\textcolor"], - props: { - numArgs: 2, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "original"] - }, - handler({ parser, token }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let color = ""; - if (model) { - const spec = assertNodeType(args[0], "raw").string; - color = colorFromSpec(model, spec); - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros, token); - } - const body = args[1]; - return { - type: "color", - mode: parser.mode, - color, - body: ordargument(body) - } - }, - mathmlBuilder: mathmlBuilder$9 -}); - -defineFunction({ - type: "color", - names: ["\\color"], - props: { - numArgs: 1, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw"] - }, - handler({ parser, token }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let color = ""; - if (model) { - const spec = assertNodeType(args[0], "raw").string; - color = colorFromSpec(model, spec); - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros, token); - } - - // Set macro \current@color in current namespace to store the current - // color, mimicking the behavior of color.sty. - // This is currently used just to correctly color a \right - // that follows a \color command. - parser.gullet.macros.set("\\current@color", color); - - // Parse out the implicit body that should be colored. - // Since \color nodes should not be nested, break on \color. - const body = parser.parseExpression(true, "\\color"); - - return { - type: "color", - mode: parser.mode, - color, - body - } - }, - mathmlBuilder: mathmlBuilder$9 -}); - -defineFunction({ - type: "color", - names: ["\\definecolor"], - props: { - numArgs: 3, - allowedInText: true, - argTypes: ["raw", "raw", "raw"] - }, - handler({ parser, funcName, token }, args) { - const name = assertNodeType(args[0], "raw").string; - if (!/^[A-Za-z]+$/.test(name)) { - throw new ParseError("Color name must be latin letters.", token) - } - const model = assertNodeType(args[1], "raw").string; - if (!["HTML", "RGB", "rgb"].includes(model)) { - throw new ParseError("Color model must be HTML, RGB, or rgb.", token) - } - const spec = assertNodeType(args[2], "raw").string; - const color = colorFromSpec(model, spec); - parser.gullet.macros.set(`\\\\color@${name}`, { tokens: [{ text: color }], numArgs: 0 }); - return { type: "internal", mode: parser.mode } - } - // No mathmlBuilder. The point of \definecolor is to set a macro. -}); - -// Row breaks within tabular environments, and line breaks at top level - -// \DeclareRobustCommand\\{...\@xnewline} -defineFunction({ - type: "cr", - names: ["\\\\"], - props: { - numArgs: 0, - numOptionalArgs: 1, - argTypes: ["size"], - allowedInText: true - }, - - handler({ parser }, args, optArgs) { - const size = optArgs[0]; - const newLine = !parser.settings.displayMode; - return { - type: "cr", - mode: parser.mode, - newLine, - size: size && assertNodeType(size, "size").value - } - }, - - // The following builder is called only at the top level, - // not within tabular/array environments. - - mathmlBuilder(group, style) { - // MathML 3.0 calls for newline to occur in an or an . - // Ref: https://www.w3.org/TR/MathML3/chapter3.html#presm.linebreaking - const node = new mathMLTree.MathNode("mo"); - if (group.newLine) { - node.setAttribute("linebreak", "newline"); - if (group.size) { - const size = calculateSize(group.size, style); - node.setAttribute("height", size.number + size.unit); - } - } - return node - } -}); - -const checkControlSequence = (tok) => { - const name = tok.text; - if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { - throw new ParseError("Expected a control sequence", tok); - } - return name; -}; - -const getRHS = (parser) => { - let tok = parser.gullet.popToken(); - if (tok.text === "=") { - // consume optional equals - tok = parser.gullet.popToken(); - if (tok.text === " ") { - // consume one optional space - tok = parser.gullet.popToken(); - } - } - return tok; -}; - -const letCommand = (parser, name, tok) => { - let macro = parser.gullet.macros.get(tok.text); - if (macro == null) { - // don't expand it later even if a macro with the same name is defined - // e.g., \let\foo=\frac \def\frac{\relax} \frac12 - tok.noexpand = true; - macro = { - tokens: [tok], - numArgs: 0, - // reproduce the same behavior in expansion - unexpandable: !parser.gullet.isExpandable(tok.text) - }; - } - parser.gullet.macros.set(name, macro); -}; - -// Basic support for macro definitions: \def -// -> -// -> -defineFunction({ - type: "internal", - names: ["\\def", "\\edef"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - let tok = parser.gullet.popToken(); - const name = tok.text; - if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { - throw new ParseError("Expected a control sequence", tok); - } - - let numArgs = 0; - let insert; - const delimiters = [[]]; - // contains no braces - while (parser.gullet.future().text !== "{") { - tok = parser.gullet.popToken(); - if (tok.text === "#") { - // If the very last character of the is #, so that - // this # is immediately followed by {, TeX will behave as if the { - // had been inserted at the right end of both the parameter text - // and the replacement text. - if (parser.gullet.future().text === "{") { - insert = parser.gullet.future(); - delimiters[numArgs].push("{"); - break; - } - - // A parameter, the first appearance of # must be followed by 1, - // the next by 2, and so on; up to nine #’s are allowed - tok = parser.gullet.popToken(); - if (!/^[1-9]$/.test(tok.text)) { - throw new ParseError(`Invalid argument number "${tok.text}"`); - } - if (parseInt(tok.text) !== numArgs + 1) { - throw new ParseError(`Argument number "${tok.text}" out of order`); - } - numArgs++; - delimiters.push([]); - } else if (tok.text === "EOF") { - throw new ParseError("Expected a macro definition"); - } else { - delimiters[numArgs].push(tok.text); - } - } - // replacement text, enclosed in '{' and '}' and properly nested - let { tokens } = parser.gullet.consumeArg(); - if (insert) { - tokens.unshift(insert); - } - - if (funcName === "\\edef") { - tokens = parser.gullet.expandTokens(tokens); - tokens.reverse(); // to fit in with stack order - } - // Final arg is the expansion of the macro - parser.gullet.macros.set(name, { tokens, numArgs, delimiters } - ); - return { type: "internal", mode: parser.mode }; - } -}); - -// -> -// -> \futurelet -// | \let -// -> |= -defineFunction({ - type: "internal", - names: ["\\let"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - const name = checkControlSequence(parser.gullet.popToken()); - parser.gullet.consumeSpaces(); - const tok = getRHS(parser); - letCommand(parser, name, tok); - return { type: "internal", mode: parser.mode }; - } -}); - -// ref: https://www.tug.org/TUGboat/tb09-3/tb22bechtolsheim.pdf -defineFunction({ - type: "internal", - names: ["\\futurelet"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - const name = checkControlSequence(parser.gullet.popToken()); - const middle = parser.gullet.popToken(); - const tok = parser.gullet.popToken(); - letCommand(parser, name, tok); - parser.gullet.pushToken(tok); - parser.gullet.pushToken(middle); - return { type: "internal", mode: parser.mode }; - } -}); - -defineFunction({ - type: "internal", - names: ["\\newcommand", "\\renewcommand", "\\providecommand"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - let name = ""; - const tok = parser.gullet.popToken(); - if (tok.text === "{") { - name = checkControlSequence(parser.gullet.popToken()); - parser.gullet.popToken(); - } else { - name = checkControlSequence(tok); - } - - const exists = parser.gullet.isDefined(name); - if (exists && funcName === "\\newcommand") { - throw new ParseError( - `\\newcommand{${name}} attempting to redefine ${name}; use \\renewcommand` - ); - } - if (!exists && funcName === "\\renewcommand") { - throw new ParseError( - `\\renewcommand{${name}} when command ${name} does not yet exist; use \\newcommand` - ); - } - - let numArgs = 0; - if (parser.gullet.future().text === "[") { - let tok = parser.gullet.popToken(); - tok = parser.gullet.popToken(); - if (!/^[0-9]$/.test(tok.text)) { - throw new ParseError(`Invalid number of arguments: "${tok.text}"`); - } - numArgs = parseInt(tok.text); - tok = parser.gullet.popToken(); - if (tok.text !== "]") { - throw new ParseError(`Invalid argument "${tok.text}"`); - } - } - - // replacement text, enclosed in '{' and '}' and properly nested - const { tokens } = parser.gullet.consumeArg(); - - parser.gullet.macros.set(name, { tokens, numArgs }); - - return { type: "internal", mode: parser.mode }; - - } -}); - -// Extra data needed for the delimiter handler down below -const delimiterSizes = { - "\\bigl": { mclass: "mopen", size: 1 }, - "\\Bigl": { mclass: "mopen", size: 2 }, - "\\biggl": { mclass: "mopen", size: 3 }, - "\\Biggl": { mclass: "mopen", size: 4 }, - "\\bigr": { mclass: "mclose", size: 1 }, - "\\Bigr": { mclass: "mclose", size: 2 }, - "\\biggr": { mclass: "mclose", size: 3 }, - "\\Biggr": { mclass: "mclose", size: 4 }, - "\\bigm": { mclass: "mrel", size: 1 }, - "\\Bigm": { mclass: "mrel", size: 2 }, - "\\biggm": { mclass: "mrel", size: 3 }, - "\\Biggm": { mclass: "mrel", size: 4 }, - "\\big": { mclass: "mord", size: 1 }, - "\\Big": { mclass: "mord", size: 2 }, - "\\bigg": { mclass: "mord", size: 3 }, - "\\Bigg": { mclass: "mord", size: 4 } -}; - -const delimiters = [ - "(", - "\\lparen", - ")", - "\\rparen", - "[", - "\\lbrack", - "]", - "\\rbrack", - "\\{", - "\\lbrace", - "\\}", - "\\rbrace", - "\\lfloor", - "\\rfloor", - "\u230a", - "\u230b", - "\\lceil", - "\\rceil", - "\u2308", - "\u2309", - "<", - ">", - "\\langle", - "\u27e8", - "\\rangle", - "\u27e9", - "\\lt", - "\\gt", - "\\lvert", - "\\rvert", - "\\lVert", - "\\rVert", - "\\lgroup", - "\\rgroup", - "\u27ee", - "\u27ef", - "\\lmoustache", - "\\rmoustache", - "\u23b0", - "\u23b1", - "\\llbracket", - "\\rrbracket", - "\u27e6", - "\u27e6", - "\\lBrace", - "\\rBrace", - "\u2983", - "\u2984", - "/", - "\\backslash", - "|", - "\\vert", - "\\|", - "\\Vert", - "\\uparrow", - "\\Uparrow", - "\\downarrow", - "\\Downarrow", - "\\updownarrow", - "\\Updownarrow", - "." -]; - -// Metrics of the different sizes. Found by looking at TeX's output of -// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$ -// Used to create stacked delimiters of appropriate sizes in makeSizedDelim. -const sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0]; - -// Delimiter functions -function checkDelimiter(delim, context) { - if (delim.type === "ordgroup" && delim.body.length === 1 && delim.body[0].text === "\u2044") { - // Recover "/" from the zero spacing group. (See macros.js) - delim = { type: "textord", text: "/", mode: "math" }; - } - const symDelim = checkSymbolNodeType(delim); - if (symDelim && utils.contains(delimiters, symDelim.text)) { - // If a character is not in the MathML operator dictionary, it will not stretch. - // Replace such characters w/characters that will stretch. - if (utils.contains(["<", "\\lt"], symDelim.text)) { symDelim.text = "⟨"; } - if (utils.contains([">", "\\gt"], symDelim.text)) { symDelim.text = "⟩"; } - if (symDelim.text === "/") { symDelim.text = "\u2215"; } - if (symDelim.text === "\\backslash") { symDelim.text = "\u2216"; } - return symDelim; - } else if (symDelim) { - throw new ParseError(`Invalid delimiter '${symDelim.text}' after '${context.funcName}'`, delim); - } else { - throw new ParseError(`Invalid delimiter type '${delim.type}'`, delim); - } -} - -defineFunction({ - type: "delimsizing", - names: [ - "\\bigl", - "\\Bigl", - "\\biggl", - "\\Biggl", - "\\bigr", - "\\Bigr", - "\\biggr", - "\\Biggr", - "\\bigm", - "\\Bigm", - "\\biggm", - "\\Biggm", - "\\big", - "\\Big", - "\\bigg", - "\\Bigg" - ], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - - return { - type: "delimsizing", - mode: context.parser.mode, - size: delimiterSizes[context.funcName].size, - mclass: delimiterSizes[context.funcName].mclass, - delim: delim.text - }; - }, - mathmlBuilder: (group) => { - const children = []; - - if (group.delim === ".") { group.delim = ""; } - children.push(makeText(group.delim, group.mode)); - - const node = new mathMLTree.MathNode("mo", children); - - if (group.mclass === "mopen" || group.mclass === "mclose") { - // Only some of the delimsizing functions act as fences, and they - // return "mopen" or "mclose" mclass. - node.setAttribute("fence", "true"); - } else { - // Explicitly disable fencing if it's not a fence, to override the - // defaults. - node.setAttribute("fence", "false"); - } - if (group.delim === "\u2216") { - // \backslash is not in the operator dictionary, - // so we have to explicitly set stretchy to true. - node.setAttribute("stretchy", "true"); - } - - node.setAttribute("symmetric", "true"); // Needed for tall arrows in Firefox. - node.setAttribute("minsize", sizeToMaxHeight[group.size] + "em"); - node.setAttribute("maxsize", sizeToMaxHeight[group.size] + "em"); - - return node; - } -}); - -function assertParsed(group) { - if (!group.body) { - throw new Error("Bug: The leftright ParseNode wasn't fully parsed."); - } -} - -defineFunction({ - type: "leftright-right", - names: ["\\right"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - // \left case below triggers parsing of \right in - // `const right = parser.parseFunction();` - // uses this return value. - const color = context.parser.gullet.macros.get("\\current@color"); - if (color && typeof color !== "string") { - throw new ParseError("\\current@color set to non-string in \\right"); - } - return { - type: "leftright-right", - mode: context.parser.mode, - delim: checkDelimiter(args[0], context).text, - color // undefined if not set via \color - }; - } -}); - -defineFunction({ - type: "leftright", - names: ["\\left"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - - const parser = context.parser; - // Parse out the implicit body - ++parser.leftrightDepth; - // parseExpression stops before '\\right' - const body = parser.parseExpression(false); - --parser.leftrightDepth; - // Check the next token - parser.expect("\\right", false); - const right = assertNodeType(parser.parseFunction(), "leftright-right"); - return { - type: "leftright", - mode: parser.mode, - body, - left: delim.text, - right: right.delim, - rightColor: right.color - }; - }, - mathmlBuilder: (group, style) => { - assertParsed(group); - const inner = buildExpression(group.body, style); - - if (group.left === ".") { group.left = ""; } - const leftNode = new mathMLTree.MathNode("mo", [makeText(group.left, group.mode)]); - leftNode.setAttribute("fence", "true"); - leftNode.setAttribute("form", "prefix"); - if (group.left === "\u2216") { leftNode.setAttribute("stretchy", "true"); } - inner.unshift(leftNode); - - if (group.right === ".") { group.right = ""; } - const rightNode = new mathMLTree.MathNode("mo", [makeText(group.right, group.mode)]); - rightNode.setAttribute("fence", "true"); - rightNode.setAttribute("form", "postfix"); - if (group.right === "\u2216") { rightNode.setAttribute("stretchy", "true"); } - if (group.rightColor) { rightNode.setAttribute("mathcolor", group.rightColor); } - inner.push(rightNode); - - return makeRow(inner); - } -}); - -defineFunction({ - type: "middle", - names: ["\\middle"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - if (!context.parser.leftrightDepth) { - throw new ParseError("\\middle without preceding \\left", delim); - } - - return { - type: "middle", - mode: context.parser.mode, - delim: delim.text - }; - }, - mathmlBuilder: (group, style) => { - const textNode = makeText(group.delim, group.mode); - const middleNode = new mathMLTree.MathNode("mo", [textNode]); - middleNode.setAttribute("fence", "true"); - // MathML gives 5/18em spacing to each element. - // \middle should get delimiter spacing instead. - middleNode.setAttribute("lspace", "0.05em"); - middleNode.setAttribute("rspace", "0.05em"); - return middleNode; - } -}); - -const mathmlBuilder$8 = (group, style) => { - const node = new mathMLTree.MathNode( - group.label.indexOf("colorbox") > -1 ? "mpadded" : "menclose", - [buildGroup$1(group.body, style)] - ); - switch (group.label) { - case "\\cancel": - node.setAttribute("notation", "updiagonalstrike"); - break; - case "\\bcancel": - node.setAttribute("notation", "downdiagonalstrike"); - break; - case "\\longdiv": - node.setAttribute("notation", "longdiv"); - break; - case "\\phase": - node.setAttribute("notation", "phasorangle"); - break; - case "\\sout": - node.setAttribute("notation", "horizontalstrike"); - break; - case "\\fbox": - node.setAttribute("notation", "box"); - break; - case "\\angl": - node.setAttribute("notation", "actuarial"); - break; - case "\\fcolorbox": - case "\\colorbox": { - // doesn't have a good notation option for \colorbox. - // So use instead. Set some attributes that come - // included with . - const fboxsep = 3; // 3 pt from LaTeX source2e - node.setAttribute("width", `+${2 * fboxsep}pt`); - node.setAttribute("height", `+${2 * fboxsep}pt`); - node.setAttribute("lspace", `${fboxsep}pt`); // - node.setAttribute("voffset", `${fboxsep}pt`); - if (group.label === "\\fcolorbox") { - node.setAttribute("style", "border: 0.06em solid " + String(group.borderColor)); - } - break; - } - case "\\xcancel": - node.setAttribute("notation", "updiagonalstrike downdiagonalstrike"); - break; - } - if (group.backgroundColor) { - node.setAttribute("mathbackground", group.backgroundColor); - } - return node; -}; - -defineFunction({ - type: "enclose", - names: ["\\colorbox"], - props: { - numArgs: 2, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "text"] - }, - handler({ parser, funcName }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let color = ""; - if (model) { - const spec = assertNodeType(args[0], "raw").string; - color = colorFromSpec(model, spec); - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros); - } - const body = args[1]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - backgroundColor: color, - body - }; - }, - mathmlBuilder: mathmlBuilder$8 -}); - -defineFunction({ - type: "enclose", - names: ["\\fcolorbox"], - props: { - numArgs: 3, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "raw", "text"] - }, - handler({ parser, funcName }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let borderColor = ""; - let backgroundColor; - if (model) { - const borderSpec = assertNodeType(args[0], "raw").string; - const backgroundSpec = assertNodeType(args[0], "raw").string; - borderColor = colorFromSpec(model, borderSpec); - backgroundColor = colorFromSpec(model, backgroundSpec); - } else { - borderColor = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros); - backgroundColor = validateColor(assertNodeType(args[1], "raw").string, parser.gullet.macros); - } - const body = args[2]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - backgroundColor, - borderColor, - body - }; - }, - mathmlBuilder: mathmlBuilder$8 -}); - -defineFunction({ - type: "enclose", - names: ["\\fbox"], - props: { - numArgs: 1, - argTypes: ["hbox"], - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "enclose", - mode: parser.mode, - label: "\\fbox", - body: args[0] - }; - } -}); - -defineFunction({ - type: "enclose", - names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\angl", "\\phase", "\\longdiv"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - const body = args[0]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - body - }; - }, - mathmlBuilder: mathmlBuilder$8 -}); - -/** - * All registered environments. - * `environments.js` exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary via `environments.js`. - */ -const _environments = {}; - -function defineEnvironment({ type, names, props, handler, mathmlBuilder }) { - // Set default values of environments. - const data = { - type, - numArgs: props.numArgs || 0, - allowedInText: false, - numOptionalArgs: 0, - handler - }; - for (let i = 0; i < names.length; ++i) { - _environments[names[i]] = data; - } - if (mathmlBuilder) { - _mathmlGroupBuilders[type] = mathmlBuilder; - } -} - -// In TeX, there are actually three sets of dimensions, one for each of - -// Math style is not quite the same thing as script level. -const StyleLevel = { - DISPLAY: 0, - TEXT: 1, - SCRIPT: 2, - SCRIPTSCRIPT: 3 -}; - -// Helper functions -function getHLines(parser) { - // Return an array. The array length = number of hlines. - // Each element in the array tells if the line is dashed. - const hlineInfo = []; - parser.consumeSpaces(); - let nxt = parser.fetch().text; - while (nxt === "\\hline" || nxt === "\\hdashline") { - parser.consume(); - hlineInfo.push(nxt === "\\hdashline"); - parser.consumeSpaces(); - nxt = parser.fetch().text; - } - return hlineInfo; -} - -const validateAmsEnvironmentContext = context => { - const settings = context.parser.settings; - if (!settings.displayMode) { - throw new ParseError(`{${context.envName}} can be used only in display mode.`); - } -}; - -const getTag = (group, style, rowNum) => { - let tag; - const tagContents = group.tags.shift(); - if (tagContents) { - // The author has written a \tag or a \notag in this row. - if (tagContents.body) { - tag = buildExpressionRow(tagContents.body, style); - tag.classes = ["tml-tag"]; - } else { - // \notag. Return an empty cell. - tag = new mathMLTree.MathNode("mtd", []); - tag.setAttribute("style", "padding: 0; min-width:0"); - return tag - } - } else if (group.colSeparationType === "multline" && - ((group.leqno && rowNum !== 0) || (!group.leqno && rowNum !== group.body.length - 1))) { - // A multiline that does not receive a tag. Return an empty cell. - tag = new mathMLTree.MathNode("mtd", []); - tag.setAttribute("style", "padding: 0; min-width:0"); - return tag - } else { - // AMS automatcally numbered equaton. - // Insert a class so the element can be populated by a post-processor. - tag = new mathMLTree.MathNode("mtext", [], ["tml-eqn"]); - } - if (!group.preventTagLap) { - tag = new mathMLTree.MathNode("mpadded", [tag]); - tag.setAttribute("style", "width:0;"); - tag.setAttribute("width", "0"); - if (!group.leqno) { tag.setAttribute("lspace", "-1width"); } - } - tag = new mathMLTree.MathNode("mtd", [tag]); - if (!group.preventTagLap) { tag.setAttribute("style", "padding: 0; min-width:0"); } - return tag -}; - -/** - * Parse the body of the environment, with rows delimited by \\ and - * columns delimited by &, and create a nested list in row-major order - * with one group per cell. If given an optional argument scriptLevel - * ("text", "display", etc.), then each cell is cast into that scriptLevel. - */ -function parseArray( - parser, - { - hskipBeforeAndAfter, // boolean - addJot, // boolean - cols, // [{ type: string , align: l|c|r|null }] - arraystretch, // number - colSeparationType, // "align" | "alignat" | "gather" | "small" | "CD" | "multline" - addEqnNum, // boolean - singleRow, // boolean - emptySingleRow, // boolean - maxNumCols, // number - leqno // boolean - }, - scriptLevel -) { - parser.gullet.beginGroup(); - if (!singleRow) { - // \cr is equivalent to \\ without the optional size argument (see below) - // TODO: provide helpful error when \cr is used outside array environment - parser.gullet.macros.set("\\cr", "\\\\\\relax"); - } - if (addEqnNum) { - parser.gullet.macros.set("\\tag", "\\env@tag{\\text{#1}}"); - parser.gullet.macros.set("\\notag", "\\env@notag"); - parser.gullet.macros.set("\\nonumber", "\\env@notag"); - } - - // Get current arraystretch if it's not set by the environment - if (arraystretch === undefined || Number.isNaN(arraystretch)) { - const stretch = parser.gullet.expandMacroAsText("\\arraystretch"); - if (stretch == null) { - // Default \arraystretch from lttab.dtx - arraystretch = 1; - } else { - arraystretch = parseFloat(stretch); - if (!arraystretch || arraystretch < 0) { - throw new ParseError(`Invalid \\arraystretch: ${stretch}`); - } - } - } - - // Start group for first cell - parser.gullet.beginGroup(); - - let row = []; - const body = [row]; - const rowGaps = []; - const tags = []; - let rowTag; - const hLinesBeforeRow = []; - - // Test for \hline at the top of the array. - hLinesBeforeRow.push(getHLines(parser)); - - // eslint-disable-next-line no-constant-condition - while (true) { - // Parse each cell in its own group (namespace) - let cell = parser.parseExpression(false, singleRow ? "\\end" : "\\\\"); - - if (addEqnNum && !rowTag) { - // Check if the author wrote a \tag{} inside this cell. - for (let i = 0; i < cell.length; i++) { - if (cell[i].type === "envTag" || cell[i].type === "noTag") { - // Get the contents of the \text{} nested inside the \env@Tag{} - rowTag = cell[i].type === "envTag" - ? cell.splice(i, 1)[0].body.body[0] - : { body: null }; - break - } - } - } - parser.gullet.endGroup(); - parser.gullet.beginGroup(); - - cell = { - type: "ordgroup", - mode: parser.mode, - body: cell - }; - row.push(cell); - const next = parser.fetch().text; - if (next === "&") { - if (maxNumCols && row.length === maxNumCols) { - if (colSeparationType === "split") { - throw new ParseError("The split environment accepts no more than two columns", - parser.nextToken); - } else if (colSeparationType === "array") { - if (parser.settings.strict) { - throw new ParseError("Too few columns " + "specified in the {array} column argument.", - parser.nextToken) - } - } else { - throw new ParseError("The equation environment accepts only one column", - parser.nextToken) - } - } - parser.consume(); - } else if (next === "\\end") { - // Arrays terminate newlines with `\crcr` which consumes a `\cr` if - // the last line is empty. However, AMS environments keep the - // empty row if it's the only one. - // NOTE: Currently, `cell` is the last item added into `row`. - if (row.length === 1 && cell.body.length === 0 && (body.length > 1 || !emptySingleRow)) { - body.pop(); - } - if (hLinesBeforeRow.length < body.length + 1) { - hLinesBeforeRow.push([]); - } - break; - } else if (next === "\\\\") { - parser.consume(); - let size; - // \def\Let@{\let\\\math@cr} - // \def\math@cr{...\math@cr@} - // \def\math@cr@{\new@ifnextchar[\math@cr@@{\math@cr@@[\z@]}} - // \def\math@cr@@[#1]{...\math@cr@@@...} - // \def\math@cr@@@{\cr} - if (parser.gullet.future().text !== " ") { - size = parser.parseSizeGroup(true); - } - rowGaps.push(size ? size.value : null); - - tags.push(rowTag); - - // check for \hline(s) following the row separator - hLinesBeforeRow.push(getHLines(parser)); - - row = []; - rowTag = null; - body.push(row); - } else { - throw new ParseError("Expected & or \\\\ or \\cr or \\end", parser.nextToken); - } - } - - // End cell group - parser.gullet.endGroup(); - // End array group defining \cr - parser.gullet.endGroup(); - - tags.push(rowTag); - - return { - type: "array", - mode: parser.mode, - addJot, - arraystretch, - body, - cols, - rowGaps, - hskipBeforeAndAfter, - hLinesBeforeRow, - colSeparationType, - addEqnNum, - scriptLevel, - tags, - leqno, - preventTagLap: parser.settings.preventTagLap - }; -} - -// Decides on a scriptLevel for cells in an array according to whether the given -// environment name starts with the letter 'd'. -function dCellStyle(envName) { - return envName.slice(0, 1) === "d" ? "display" : "text" -} - -const alignMap = { - c: "center ", - l: "left ", - r: "right " -}; - -const mathmlBuilder$7 = function(group, style) { - const tbl = []; - const numRows = group.body.length; - let glue; - if (group.addEqnNum) { - glue = new mathMLTree.MathNode("mtd", [], []); - const glueStyle = "padding: 0;width: " + - (group.colSeparationType === "multline" ? "7.5%" : "50%"); - glue.setAttribute("style", glueStyle); - } - - for (let i = 0; i < numRows; i++) { - const rw = group.body[i]; - const row = []; - const cellStyle = group.scriptLevel === "text" - ? StyleLevel.TEXT - : group.scriptLevel === "script" - ? StyleLevel.SCRIPT - : StyleLevel.DISPLAY; - - for (let j = 0; j < rw.length; j++) { - const mtd = new mathMLTree.MathNode( - "mtd", - [buildGroup$1(rw[j], style.withLevel(cellStyle))] - ); - if (group.colSeparationType === "multline") { - const align = i === 0 ? "left" : i === numRows - 1 ? "right" : "center"; - mtd.setAttribute("columnalign", align); - } - row.push(mtd); - } - if (group.addEqnNum) { - row.unshift(glue); - row.push(glue); - const tag = getTag(group, style.withLevel(cellStyle), i); - if (group.leqno) { - row.unshift(tag); - } else { - row.push(tag); - } - } - // If group.addEqnNum, insert a breadcrumb to be found by temmlPostProcess(). - tbl.push(new mathMLTree.MathNode("mtr", row, group.addEqnNum ? ["tml-tageqn"] : [] )); - } - let table = new mathMLTree.MathNode("mtable", tbl); - if (group.scriptLevel === "display") { table.setAttribute("displaystyle", "true"); } - - // Set column alignment, row spacing, column spacing, and - // array lines by setting attributes on the table element. - - // Set the row spacing. In MathML, we specify a gap distance. - // We do not use rowGap[] because MathML automatically increases - // cell height with the height/depth of the element content. - - // LaTeX \arraystretch multiplies the row baseline-to-baseline distance. - // We simulate this by adding (arraystretch - 1)em to the gap. This - // does a reasonable job of adjusting arrays containing 1 em tall content. - - // The 0.16 and 0.09 values are found emprically. They produce an array - // similar to LaTeX and in which content does not interfere with \hines. - const gap = - group.arraystretch === 0 - ? 0 // {subarray} - : group.arraystretch === 0.5 - ? 0.1 // {smallmatrix} - : 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0); - table.setAttribute("rowspacing", utils.round(gap) + "em"); - - if (group.addEqnNum || group.colSeparationType === "multline") { - table.setAttribute("width", "100%"); - } - - // MathML table lines go only between cells. - // To place a line on an edge we'll use , if necessary. - let menclose = ""; - let align = ""; - - if (group.cols && group.cols.length > 0) { - // Find column alignment, column spacing, and vertical lines. - const cols = group.cols; - let columnLines = ""; - let prevTypeWasAlign = false; - let iStart = 0; - let iEnd = cols.length; - - if (cols[0].type === "separator") { - menclose += "left "; - iStart = 1; - } - if (cols[cols.length - 1].type === "separator") { - menclose += "right "; - iEnd -= 1; - } - - for (let i = iStart; i < iEnd; i++) { - if (cols[i].type === "align") { - align += alignMap[cols[i].align]; - - if (prevTypeWasAlign) { - columnLines += "none "; - } - prevTypeWasAlign = true; - } else if (cols[i].type === "separator") { - // MathML accepts only single lines between cells. - // So we read only the first of consecutive separators. - if (prevTypeWasAlign) { - columnLines += cols[i].separator === "|" ? "solid " : "dashed "; - prevTypeWasAlign = false; - } - } - } - if (group.addEqnNum) { - align = "left " + align + "right "; // allow for glue cells on each side - align = group.leqno ? "left " + align : align += "right"; // eqn num cell - } - - table.setAttribute("columnalign", align.trim()); - - if (/[sd]/.test(columnLines)) { - table.setAttribute("columnlines", columnLines.trim()); - } - } - - // Set column spacing. - switch (group.colSeparationType) { - case "gather": - case "gathered": - case "alignedat": - case "alignat": - case "alignat*": - table.setAttribute("columnspacing", "0em"); - break - case "small": - table.setAttribute("columnspacing", "0.2778em"); - break - case "CD": - table.setAttribute("columnspacing", "0.5em"); - break - case "align": - case "align*": { - const cols = group.cols || []; - let spacing = group.addEqnNum ? "0em " : ""; - for (let i = 1; i < cols.length; i++) { - spacing += i % 2 ? "0em " : "1em "; - } - if (group.addEqnNum) { spacing += "0em"; } - table.setAttribute("columnspacing", spacing.trim()); - break - } - default: - table.setAttribute("columnspacing", "1em"); - } - - // Address \hline and \hdashline - let rowLines = ""; - const hlines = group.hLinesBeforeRow; - - menclose += hlines[0].length > 0 ? "top " : ""; - menclose += hlines[hlines.length - 1].length > 0 ? "bottom " : ""; - - for (let i = 1; i < hlines.length - 1; i++) { - rowLines += - hlines[i].length === 0 - ? "none " - : // MathML accepts only a single line between rows. Read one element. - hlines[i][0] - ? "dashed " - : "solid "; - } - if (/[sd]/.test(rowLines)) { - table.setAttribute("rowlines", rowLines.trim()); - } - - if (menclose !== "") { - table = new mathMLTree.MathNode("menclose", [table]); - table.setAttribute("notation", menclose.trim()); - } - - if (!Number.isNaN(group.arraystretch) && group.arraystretch < 1) { - // A small array. Wrap in scriptstyle so row gap is not too large. - table = new mathMLTree.MathNode("mstyle", [table]); - table.setAttribute("scriptlevel", "1"); - } - - return table; -}; - -// Convenience function for align, align*, aligned, alignat, alignat*, alignedat. -const alignedHandler = function(context, args) { - if (context.envName.indexOf("ed") === -1) { - validateAmsEnvironmentContext(context); - } - const cols = []; - const res = parseArray( - context.parser, - { - cols, - addJot: true, - addEqnNum: context.envName === "align" || context.envName === "alignat", - emptySingleRow: true, - colSeparationType: context.envName, - maxNumCols: context.envName === "split" ? 2 : undefined, - leqno: context.parser.settings.leqno - }, - "display" - ); - - // Determining number of columns. - // 1. If the first argument is given, we use it as a number of columns, - // and makes sure that each row doesn't exceed that number. - // 2. Otherwise, just count number of columns = maximum number - // of cells in each row ("aligned" mode -- isAligned will be true). - // - // At the same time, prepend empty group {} at beginning of every second - // cell in each row (starting with second cell) so that operators become - // binary. This behavior is implemented in amsmath's \start@aligned. - let numMaths; - let numCols = 0; - if (args[0] && args[0].type === "ordgroup") { - let arg0 = ""; - for (let i = 0; i < args[0].body.length; i++) { - const textord = assertNodeType(args[0].body[i], "textord"); - arg0 += textord.text; - } - numMaths = Number(arg0); - numCols = numMaths * 2; - } - const isAligned = !numCols; - res.body.forEach(function(row) { - if (!isAligned) { - // Case 1 - const curMaths = row.length / 2; - if (numMaths < curMaths) { - throw new ParseError( - "Too many math in a row: " + `expected ${numMaths}, but got ${curMaths}`, - row[0] - ); - } - } else if (numCols < row.length) { - // Case 2 - numCols = row.length; - } - }); - - // Adjusting alignment. - // In aligned mode, we add one \qquad between columns; - // otherwise we add nothing. - for (let i = 0; i < numCols; ++i) { - let align = "r"; - if (i % 2 === 1) { - align = "l"; - } - cols[i] = { - type: "align", - align: align - }; - } - res.colSeparationType = isAligned ? "align" : "alignat"; - return res; -}; - -// Arrays are part of LaTeX, defined in lttab.dtx so its documentation -// is part of the source2e.pdf file of LaTeX2e source documentation. -// {darray} is an {array} environment where cells are set in \displaystyle, -// as defined in nccmath.sty. -defineEnvironment({ - type: "array", - names: ["array", "darray"], - props: { - numArgs: 1 - }, - handler(context, args) { - // Since no types are specified above, the two possibilities are - // - The argument is wrapped in {} or [], in which case Parser's - // parseGroup() returns an "ordgroup" wrapping some symbol node. - // - The argument is a bare symbol node. - const symNode = checkSymbolNodeType(args[0]); - const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; - const cols = colalign.map(function(nde) { - const node = assertSymbolNodeType(nde); - const ca = node.text; - if ("lcr".indexOf(ca) !== -1) { - return { - type: "align", - align: ca - }; - } else if (ca === "|") { - return { - type: "separator", - separator: "|" - }; - } else if (ca === ":") { - return { - type: "separator", - separator: ":" - }; - } - throw new ParseError("Unknown column alignment: " + ca, nde); - }); - const res = { - cols, - colSeparationType: "array", - hskipBeforeAndAfter: true, // \@preamble in lttab.dtx - maxNumCols: cols.length - }; - return parseArray(context.parser, res, dCellStyle(context.envName)); - }, - mathmlBuilder: mathmlBuilder$7 -}); - -// The matrix environments of amsmath builds on the array environment -// of LaTeX, which is discussed above. -// The mathtools package adds starred versions of the same environments. -// These have an optional argument to choose left|center|right justification. -defineEnvironment({ - type: "array", - names: [ - "matrix", - "pmatrix", - "bmatrix", - "Bmatrix", - "vmatrix", - "Vmatrix", - "matrix*", - "pmatrix*", - "bmatrix*", - "Bmatrix*", - "vmatrix*", - "Vmatrix*" - ], - props: { - numArgs: 0 - }, - handler(context) { - const delimiters = { - matrix: null, - pmatrix: ["(", ")"], - bmatrix: ["[", "]"], - Bmatrix: ["\\{", "\\}"], - vmatrix: ["|", "|"], - Vmatrix: ["\\Vert", "\\Vert"] - }[context.envName.replace("*", "")]; - // \hskip -\arraycolsep in amsmath - let colAlign = "c"; - const payload = { - hskipBeforeAndAfter: false, - colSeparationType: "matrix", - cols: [{ type: "align", align: colAlign }] - }; - if (context.envName.charAt(context.envName.length - 1) === "*") { - // It's one of the mathtools starred functions. - // Parse the optional alignment argument. - const parser = context.parser; - parser.consumeSpaces(); - if (parser.fetch().text === "[") { - parser.consume(); - parser.consumeSpaces(); - colAlign = parser.fetch().text; - if ("lcr".indexOf(colAlign) === -1) { - throw new ParseError("Expected l or c or r", parser.nextToken); - } - parser.consume(); - parser.consumeSpaces(); - parser.expect("]"); - parser.consume(); - payload.cols = [{ type: "align", align: colAlign }]; - } - } - const res = parseArray(context.parser, payload, "text"); - // Populate cols with the correct number of column alignment specs. - const numCols = Math.max(0, ...res.body.map((row) => row.length)); - res.cols = new Array(numCols).fill({ type: "align", align: colAlign }); - return delimiters - ? { - type: "leftright", - mode: context.mode, - body: [res], - left: delimiters[0], - right: delimiters[1], - rightColor: undefined // \right uninfluenced by \color in array - } - : res; - }, - mathmlBuilder: mathmlBuilder$7 -}); - -defineEnvironment({ - type: "array", - names: ["smallmatrix"], - props: { - numArgs: 0 - }, - handler(context) { - const payload = { arraystretch: 0.5 }; - const res = parseArray(context.parser, payload, "script"); - res.colSeparationType = "small"; - return res; - }, - mathmlBuilder: mathmlBuilder$7 -}); - -defineEnvironment({ - type: "array", - names: ["subarray"], - props: { - numArgs: 1 - }, - handler(context, args) { - // Parsing of {subarray} is similar to {array} - const symNode = checkSymbolNodeType(args[0]); - const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; - const cols = colalign.map(function(nde) { - const node = assertSymbolNodeType(nde); - const ca = node.text; - // {subarray} only recognizes "l" & "c" - if ("lc".indexOf(ca) !== -1) { - return { - type: "align", - align: ca - }; - } - throw new ParseError("Unknown column alignment: " + ca, nde); - }); - if (cols.length > 1) { - throw new ParseError("{subarray} can contain only one column"); - } - let res = { - cols, - hskipBeforeAndAfter: false, - colSeparationType: "array", - arraystretch: 0 - }; - res = parseArray(context.parser, res, "script"); - if (res.body.length > 0 && res.body[0].length > 1) { - throw new ParseError("{subarray} can contain only one column"); - } - return res; - }, - mathmlBuilder: mathmlBuilder$7 -}); - -// A cases environment (in amsmath.sty) is almost equivalent to -// \def -// \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right. -// {dcases} is a {cases} environment where cells are set in \displaystyle, -// as defined in mathtools.sty. -// {rcases} is another mathtools environment. It's brace is on the right side. -defineEnvironment({ - type: "array", - names: ["cases", "dcases", "rcases", "drcases"], - props: { - numArgs: 0 - }, - handler(context) { - const payload = { - cols: [ - { - type: "align", - align: "l" - }, - { - type: "align", - align: "l" - } - ], - colSeparationType: "cases" - }; - const res = parseArray(context.parser, payload, dCellStyle(context.envName)); - return { - type: "leftright", - mode: context.mode, - body: [res], - left: context.envName.indexOf("r") > -1 ? "." : "\\{", - right: context.envName.indexOf("r") > -1 ? "\\}" : ".", - rightColor: undefined - }; - }, - mathmlBuilder: mathmlBuilder$7 -}); - -// In the align environment, one uses ampersands, &, to specify number of -// columns in each row, and to locate spacing between each column. -// align gets automatic numbering. align* and aligned do not. -// The alignedat environment can be used in math mode. -// Note that we assume \nomallineskiplimit to be zero, -// so that \strut@ is the same as \strut. -defineEnvironment({ - type: "array", - names: ["align", "align*", "aligned", "split"], - props: { - numArgs: 0 - }, - handler: alignedHandler, - mathmlBuilder: mathmlBuilder$7 -}); - -// A gathered environment is like an array environment with one centered -// column, but where rows are considered lines so get \jot line spacing -// and contents are set in \displaystyle. -defineEnvironment({ - type: "array", - names: ["gathered", "gather", "gather*"], - props: { - numArgs: 0 - }, - handler(context) { - if (utils.contains(["gather", "gather*"], context.envName)) { - validateAmsEnvironmentContext(context); - } - const res = { - cols: [ - { - type: "align", - align: "c" - } - ], - addJot: true, - colSeparationType: "gather", - addEqnNum: context.envName === "gather", - emptySingleRow: true, - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder: mathmlBuilder$7 -}); - -// alignat environment is like an align environment, but one must explicitly -// specify maximum number of columns in each row, and can adjust spacing between -// each columns. -defineEnvironment({ - type: "array", - names: ["alignat", "alignat*", "alignedat"], - props: { - numArgs: 1 - }, - handler: alignedHandler, - mathmlBuilder: mathmlBuilder$7 -}); - -defineEnvironment({ - type: "array", - names: ["equation", "equation*"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - const res = { - addEqnNum: context.envName === "equation", - emptySingleRow: true, - singleRow: true, - maxNumCols: 1, - colSeparationType: "gather", - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder: mathmlBuilder$7 -}); - -defineEnvironment({ - type: "array", - names: ["multline", "multline*"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - const res = { - addEqnNum: context.envName === "multline", - maxNumCols: 1, - colSeparationType: "multline", - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder: mathmlBuilder$7 -}); - -defineEnvironment({ - type: "array", - names: ["CD"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - return parseCD(context.parser); - }, - mathmlBuilder: mathmlBuilder$7 -}); - -// Catch \hline outside array environment -defineFunction({ - type: "text", // Doesn't matter what this is. - names: ["\\hline", "\\hdashline"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: true - }, - handler(context, args) { - throw new ParseError(`${context.funcName} valid only within array environment`); - } -}); - -const environments = _environments; - -// Environment delimiters. HTML/MathML rendering is defined in the corresponding -// defineEnvironment definitions. -defineFunction({ - type: "environment", - names: ["\\begin", "\\end"], - props: { - numArgs: 1, - argTypes: ["text"] - }, - handler({ parser, funcName }, args) { - const nameGroup = args[0]; - if (nameGroup.type !== "ordgroup") { - throw new ParseError("Invalid environment name", nameGroup); - } - let envName = ""; - for (let i = 0; i < nameGroup.body.length; ++i) { - envName += assertNodeType(nameGroup.body[i], "textord").text; - } - - if (funcName === "\\begin") { - // begin...end is similar to left...right - if (!Object.prototype.hasOwnProperty.call(environments, envName )) { - throw new ParseError("No such environment: " + envName, nameGroup); - } - // Build the environment object. Arguments and other information will - // be made available to the begin and end methods using properties. - const env = environments[envName]; - const { args, optArgs } = parser.parseArguments("\\begin{" + envName + "}", env); - const context = { - mode: parser.mode, - envName, - parser - }; - const result = env.handler(context, args, optArgs); - parser.expect("\\end", false); - const endNameToken = parser.nextToken; - const end = assertNodeType(parser.parseFunction(), "environment"); - if (end.name !== envName) { - throw new ParseError( - `Mismatch: \\begin{${envName}} matched by \\end{${end.name}}`, - endNameToken - ); - } - return result; - } - - return { - type: "environment", - mode: parser.mode, - name: envName, - nameGroup - }; - } -}); - -defineFunction({ - type: "envTag", - names: ["\\env@tag"], - props: { - numArgs: 1, - argTypes: ["math"] - }, - handler({ parser }, args) { - return { - type: "envTag", - mode: parser.mode, - body: args[0] - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow"); - } -}); - -defineFunction({ - type: "noTag", - names: ["\\env@notag"], - props: { - numArgs: 0 - }, - handler({ parser }) { - return { - type: "noTag", - mode: parser.mode - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow"); - } -}); - -const mathmlBuilder$6 = (group, style) => { - const font = group.font; - const newStyle = style.withFont(font); - const mathGroup = buildGroup$1(group.body, newStyle); - - if (mathGroup.children.length === 0) { return mathGroup } // empty group, e.g., \mathrm{} - if (font === "boldsymbol" && ["mo", "mpadded"].includes(mathGroup.type)) { - mathGroup.style.fontWeight = "bold"; - return mathGroup - } - // Check if it is possible to consolidate elements into a single element. - let canConsolidate = mathGroup.children[0].type === "mo"; - for (let i = 1; i < mathGroup.children.length; i++) { - if (mathGroup.children[i].type === "mo" && font === "boldsymbol") { - mathGroup.children[i].style.fontWeight = "bold"; - } - if (mathGroup.children[i].type !== "mi") { canConsolidate = false; } - const localVariant = mathGroup.children[i].attributes && - mathGroup.children[i].attributes.mathvariant || ""; - if (localVariant !== "normal") { canConsolidate = false; } - } - if (!canConsolidate) { return mathGroup } - // Consolidate the elements. - const mi = mathGroup.children[0]; - for (let i = 1; i < mathGroup.children.length; i++) { - mi.children.push(mathGroup.children[i].children[0]); - } - if (mathGroup.attributes.mathcolor) { mi.attributes.mathcolor = mathGroup.attributes.mathcolor; } - if (mi.attributes.mathvariant && mi.attributes.mathvariant === "normal") { - // Workaround for a Firefox bug that renders spurious space around - // a - // Ref: https://bugs.webkit.org/show_bug.cgi?id=129097 - // We insert a text node that contains a zero-width space and wrap in an mrow. - // TODO: Get rid of this workaround when the Firefox bug is fixed. - const bogus = new mathMLTree.MathNode("mtext", new mathMLTree.TextNode("\u200b")); - return new mathMLTree.MathNode("mrow", [bogus, mi]) - } - return mi -}; - -const fontAliases = { - "\\Bbb": "\\mathbb", - "\\bold": "\\mathbf", - "\\frak": "\\mathfrak", - "\\bm": "\\boldsymbol" -}; - -defineFunction({ - type: "font", - names: [ - // styles - "\\mathrm", - "\\mathit", - "\\mathbf", - "\\mathnormal", - "\\up@greek", - "\\boldsymbol", - - // families - "\\mathbb", - "\\mathcal", - "\\mathfrak", - "\\mathscr", - "\\mathsf", - "\\mathtt", - "\\oldstylenums", - - // aliases - "\\Bbb", - "\\bm", - "\\bold", - "\\frak" - ], - props: { - numArgs: 1, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const body = normalizeArgument(args[0]); - let func = funcName; - if (func in fontAliases) { - func = fontAliases[func]; - } - return { - type: "font", - mode: parser.mode, - font: func.slice(1), - body - }; - }, - mathmlBuilder: mathmlBuilder$6 -}); - -// Old font changing functions -defineFunction({ - type: "font", - names: ["\\rm", "\\sf", "\\tt", "\\bf", "\\it", "\\cal"], - props: { - numArgs: 0, - allowedInText: true - }, - handler: ({ parser, funcName, breakOnTokenText }, args) => { - const { mode } = parser; - const body = parser.parseExpression(true, breakOnTokenText); - const fontStyle = `math${funcName.slice(1)}`; - - return { - type: "font", - mode: mode, - font: fontStyle, - body: { - type: "ordgroup", - mode: parser.mode, - body - } - }; - }, - mathmlBuilder: mathmlBuilder$6 -}); - -const stylArray = ["display", "text", "script", "scriptscript"]; -const scriptLevel = { auto: -1, display: 0, text: 0, script: 1, scriptscript: 2 }; - -const mathmlBuilder$5 = (group, style) => { - // Track the scriptLevel of the numerator and denominator. - // We may need that info for \mathchoice or for adjusting em dimensions. - const childOptions = group.scriptLevel === "auto" - ? style.incrementLevel() - : group.scriptLevel === "display" - ? style.withLevel(StyleLevel.TEXT) - : group.scriptLevel === "text" - ? style.withLevel(StyleLevel.SCRIPT) - : style.withLevel(StyleLevel.SCRIPTSCRIPT); - - let node = new mathMLTree.MathNode("mfrac", [ - buildGroup$1(group.numer, childOptions), - buildGroup$1(group.denom, childOptions) - ]); - - if (!group.hasBarLine) { - node.setAttribute("linethickness", "0px"); - } else if (group.barSize) { - const ruleWidth = calculateSize(group.barSize, style); - node.setAttribute("linethickness", ruleWidth.number + ruleWidth.unit); - } - - if (group.leftDelim != null || group.rightDelim != null) { - const withDelims = []; - - if (group.leftDelim != null) { - const leftOp = new mathMLTree.MathNode("mo", [ - new mathMLTree.TextNode(group.leftDelim.replace("\\", "")) - ]); - leftOp.setAttribute("fence", "true"); - withDelims.push(leftOp); - } - - withDelims.push(node); - - if (group.rightDelim != null) { - const rightOp = new mathMLTree.MathNode("mo", [ - new mathMLTree.TextNode(group.rightDelim.replace("\\", "")) - ]); - rightOp.setAttribute("fence", "true"); - withDelims.push(rightOp); - } - - node = makeRow(withDelims); - } - - if (group.scriptLevel !== "auto") { - node = new mathMLTree.MathNode("mstyle", [node]); - node.setAttribute("displaystyle", String(group.scriptLevel === "display")); - node.setAttribute("scriptlevel", scriptLevel[group.scriptLevel]); - } - - return node; -}; - -defineFunction({ - type: "genfrac", - names: [ - "\\dfrac", - "\\frac", - "\\tfrac", - "\\dbinom", - "\\binom", - "\\tbinom", - "\\\\atopfrac", // can’t be entered directly - "\\\\bracefrac", - "\\\\brackfrac" // ditto - ], - props: { - numArgs: 2, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const denom = args[1]; - let hasBarLine = false; - let leftDelim = null; - let rightDelim = null; - let scriptLevel = "auto"; - - switch (funcName) { - case "\\dfrac": - case "\\frac": - case "\\tfrac": - hasBarLine = true; - break; - case "\\\\atopfrac": - hasBarLine = false; - break; - case "\\dbinom": - case "\\binom": - case "\\tbinom": - leftDelim = "("; - rightDelim = ")"; - break; - case "\\\\bracefrac": - leftDelim = "\\{"; - rightDelim = "\\}"; - break; - case "\\\\brackfrac": - leftDelim = "["; - rightDelim = "]"; - break; - default: - throw new Error("Unrecognized genfrac command"); - } - - switch (funcName) { - case "\\dfrac": - case "\\dbinom": - scriptLevel = "display"; - break; - case "\\tfrac": - case "\\tbinom": - scriptLevel = "text"; - break; - } - - return { - type: "genfrac", - mode: parser.mode, - continued: false, - numer, - denom, - hasBarLine, - leftDelim, - rightDelim, - scriptLevel, - barSize: null - }; - }, - mathmlBuilder: mathmlBuilder$5 -}); - -defineFunction({ - type: "genfrac", - names: ["\\cfrac"], - props: { - numArgs: 2 - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const denom = args[1]; - - return { - type: "genfrac", - mode: parser.mode, - continued: true, - numer, - denom, - hasBarLine: true, - leftDelim: null, - rightDelim: null, - scriptLevel: "display", - barSize: null - }; - } -}); - -// Infix generalized fractions -- these are not rendered directly, but replaced -// immediately by one of the variants above. -defineFunction({ - type: "infix", - names: ["\\over", "\\choose", "\\atop", "\\brace", "\\brack"], - props: { - numArgs: 0, - infix: true - }, - handler({ parser, funcName, token }) { - let replaceWith; - switch (funcName) { - case "\\over": - replaceWith = "\\frac"; - break; - case "\\choose": - replaceWith = "\\binom"; - break; - case "\\atop": - replaceWith = "\\\\atopfrac"; - break; - case "\\brace": - replaceWith = "\\\\bracefrac"; - break; - case "\\brack": - replaceWith = "\\\\brackfrac"; - break; - default: - throw new Error("Unrecognized infix genfrac command"); - } - return { - type: "infix", - mode: parser.mode, - replaceWith, - token - }; - } -}); - -const delimFromValue = function(delimString) { - let delim = null; - if (delimString.length > 0) { - delim = delimString; - delim = delim === "." ? null : delim; - } - return delim; -}; - -defineFunction({ - type: "genfrac", - names: ["\\genfrac"], - props: { - numArgs: 6, - allowedInArgument: true, - argTypes: ["math", "math", "size", "text", "math", "math"] - }, - handler({ parser }, args) { - const numer = args[4]; - const denom = args[5]; - - // Look into the parse nodes to get the desired delimiters. - const leftNode = normalizeArgument(args[0]); - const leftDelim = leftNode.type === "atom" && leftNode.family === "open" - ? delimFromValue(leftNode.text) - : null; - const rightNode = normalizeArgument(args[1]); - const rightDelim = - rightNode.type === "atom" && rightNode.family === "close" - ? delimFromValue(rightNode.text) - : null; - - const barNode = assertNodeType(args[2], "size"); - let hasBarLine; - let barSize = null; - if (barNode.isBlank) { - // \genfrac acts differently than \above. - // \genfrac treats an empty size group as a signal to use a - // standard bar size. \above would see size = 0 and omit the bar. - hasBarLine = true; - } else { - barSize = barNode.value; - hasBarLine = barSize.number > 0; - } - - // Find out if we want displaystyle, textstyle, etc. - let scriptLevel = "auto"; - let styl = args[3]; - if (styl.type === "ordgroup") { - if (styl.body.length > 0) { - const textOrd = assertNodeType(styl.body[0], "textord"); - scriptLevel = stylArray[Number(textOrd.text)]; - } - } else { - styl = assertNodeType(styl, "textord"); - scriptLevel = stylArray[Number(styl.text)]; - } - - return { - type: "genfrac", - mode: parser.mode, - numer, - denom, - continued: false, - hasBarLine, - barSize, - leftDelim, - rightDelim, - scriptLevel - }; - }, - mathmlBuilder: mathmlBuilder$5 -}); - -// \above is an infix fraction that also defines a fraction bar size. -defineFunction({ - type: "infix", - names: ["\\above"], - props: { - numArgs: 1, - argTypes: ["size"], - infix: true - }, - handler({ parser, funcName, token }, args) { - return { - type: "infix", - mode: parser.mode, - replaceWith: "\\\\abovefrac", - barSize: assertNodeType(args[0], "size").value, - token - }; - } -}); - -defineFunction({ - type: "genfrac", - names: ["\\\\abovefrac"], - props: { - numArgs: 3, - argTypes: ["math", "size", "math"] - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const barSize = assert(assertNodeType(args[1], "infix").barSize); - const denom = args[2]; - - const hasBarLine = barSize.number > 0; - return { - type: "genfrac", - mode: parser.mode, - numer, - denom, - continued: false, - hasBarLine, - barSize, - leftDelim: null, - rightDelim: null, - scriptLevel: "auto" - }; - }, - - mathmlBuilder: mathmlBuilder$5 -}); - -const mathmlBuilder$4 = (group, style) => { - const accentNode = stretchy.mathMLnode(group.label); - return new mathMLTree.MathNode(group.isOver ? "mover" : "munder", [ - buildGroup$1(group.base, style), - accentNode - ]); -}; - -// Horizontal stretchy braces -defineFunction({ - type: "horizBrace", - names: ["\\overbrace", "\\underbrace"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - return { - type: "horizBrace", - mode: parser.mode, - label: funcName, - isOver: /^\\over/.test(funcName), - base: args[0] - }; - }, - mathmlBuilder: mathmlBuilder$4 -}); - -defineFunction({ - type: "href", - names: ["\\href"], - props: { - numArgs: 2, - argTypes: ["url", "original"], - allowedInText: true - }, - handler: ({ parser, token }, args) => { - const body = args[1]; - const href = assertNodeType(args[0], "url").url; - - if ( - !parser.settings.isTrusted({ - command: "\\href", - url: href - }) - ) { - throw new ParseError(`Function "\\href" is not trusted`, token) - } - - return { - type: "href", - mode: parser.mode, - href, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - let math = buildExpressionRow(group.body, style); - if (!(math instanceof MathNode)) { - math = new MathNode("mrow", [math]); - } - math.setAttribute("href", group.href); - return math; - } -}); - -defineFunction({ - type: "href", - names: ["\\url"], - props: { - numArgs: 1, - argTypes: ["url"], - allowedInText: true - }, - handler: ({ parser, token }, args) => { - const href = assertNodeType(args[0], "url").url; - - if ( - !parser.settings.isTrusted({ - command: "\\url", - url: href - }) - ) { - throw new ParseError(`Function "\\url" is not trusted`, token) - } - - const chars = []; - for (let i = 0; i < href.length; i++) { - let c = href[i]; - if (c === "~") { - c = "\\textasciitilde"; - } - chars.push({ - type: "textord", - mode: "text", - text: c - }); - } - const body = { - type: "text", - mode: parser.mode, - font: "\\texttt", - body: chars - }; - return { - type: "href", - mode: parser.mode, - href, - body: ordargument(body) - }; - } -}); - -defineFunction({ - type: "html", - names: ["\\class", "\\id", "\\style", "\\data"], - props: { - numArgs: 2, - argTypes: ["raw", "original"], - allowedInText: true - }, - handler: ({ parser, funcName, token }, args) => { - const value = assertNodeType(args[0], "raw").string; - const body = args[1]; - - if (parser.settings.strict) { - throw new ParseError(`Function "${funcName}" is disabled in strict mode`, token) - } - - let trustContext; - const attributes = {}; - - switch (funcName) { - case "\\class": - attributes.class = value; - trustContext = { - command: "\\class", - class: value - }; - break; - case "\\id": - attributes.id = value; - trustContext = { - command: "\\id", - id: value - }; - break; - case "\\style": - attributes.style = value; - trustContext = { - command: "\\style", - style: value - }; - break; - case "\\data": { - const data = value.split(","); - for (let i = 0; i < data.length; i++) { - const keyVal = data[i].split("="); - if (keyVal.length !== 2) { - throw new ParseError("Error parsing key-value for \\data"); - } - attributes["data-" + keyVal[0].trim()] = keyVal[1].trim(); - } - - trustContext = { - command: "\\data", - attributes - }; - break; - } - default: - throw new Error("Unrecognized html command"); - } - - if (!parser.settings.isTrusted(trustContext)) { - throw new ParseError(`Function "${funcName}" is not trusted`, token) - } - return { - type: "html", - mode: parser.mode, - attributes, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - const element = buildExpressionRow(group.body, style); - - const classes = []; - if (group.attributes.class) { - classes.push(...group.attributes.class.trim().split(/\s+/)); - } - element.classes = classes; - - for (const attr in group.attributes) { - if (attr !== "class" && Object.prototype.hasOwnProperty.call(group.attributes, attr)) { - element.setAttribute(attr, group.attributes[attr]); - } - } - - return element; - } -}); - -const sizeData = function(str) { - if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(str)) { - // str is a number with no unit specified. - // default unit is bp, per graphix package. - return { number: +str, unit: "bp" } - } else { - const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(str); - if (!match) { - throw new ParseError("Invalid size: '" + str + "' in \\includegraphics"); - } - const data = { - number: +(match[1] + match[2]), // sign + magnitude, cast to number - unit: match[3] - }; - if (!validUnit(data)) { - throw new ParseError("Invalid unit: '" + data.unit + "' in \\includegraphics."); - } - return data - } -}; - -defineFunction({ - type: "includegraphics", - names: ["\\includegraphics"], - props: { - numArgs: 1, - numOptionalArgs: 1, - argTypes: ["raw", "url"], - allowedInText: false - }, - handler: ({ parser, token }, args, optArgs) => { - let width = { number: 0, unit: "em" }; - let height = { number: 0.9, unit: "em" }; // sorta character sized. - let totalheight = { number: 0, unit: "em" }; - let alt = ""; - - if (optArgs[0]) { - const attributeStr = assertNodeType(optArgs[0], "raw").string; - - // Parser.js does not parse key/value pairs. We get a string. - const attributes = attributeStr.split(","); - for (let i = 0; i < attributes.length; i++) { - const keyVal = attributes[i].split("="); - if (keyVal.length === 2) { - const str = keyVal[1].trim(); - switch (keyVal[0].trim()) { - case "alt": - alt = str; - break - case "width": - width = sizeData(str); - break - case "height": - height = sizeData(str); - break - case "totalheight": - totalheight = sizeData(str); - break - default: - throw new ParseError("Invalid key: '" + keyVal[0] + "' in \\includegraphics.") - } - } - } - } - - const src = assertNodeType(args[0], "url").url; - - if (alt === "") { - // No alt given. Use the file name. Strip away the path. - alt = src; - alt = alt.replace(/^.*[\\/]/, ""); - alt = alt.substring(0, alt.lastIndexOf(".")); - } - - if ( - !parser.settings.isTrusted({ - command: "\\includegraphics", - url: src - }) - ) { - throw new ParseError(`Function "\\includegraphics" is not trusted`, token) - } - - return { - type: "includegraphics", - mode: parser.mode, - alt: alt, - width: width, - height: height, - totalheight: totalheight, - src: src - } - }, - mathmlBuilder: (group, style) => { - const height = calculateSize(group.height, style); - const depth = { number: 0, unit: "em" }; - - if (group.totalheight.number > 0) { - if (group.totalheight.unit === height.unit && - group.totalheight.number > height.number) { - depth.number = group.totalheight.number - height.number; - depth.unit = height.unit; - } - } - - let width = 0; - if (group.width.number > 0) { - width = calculateSize(group.width, style); - } - - const graphicStyle = { height: height.number + depth.number + "em" }; - if (width.number > 0) { - graphicStyle.width = width.number + width.unit; - } - if (depth.number > 0) { - graphicStyle.verticalAlign = -depth.number + depth.unit; - } - - const node = new Img(group.src, group.alt, graphicStyle); - node.height = height; - node.depth = depth; - return new mathMLTree.MathNode("mtext", [node]) - } -}); - -// Horizontal spacing commands - -// TODO: \hskip and \mskip should support plus and minus in lengths - -defineFunction({ - type: "kern", - names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"], - props: { - numArgs: 1, - argTypes: ["size"], - primitive: true, - allowedInText: true - }, - handler({ parser, funcName, token }, args) { - const size = assertNodeType(args[0], "size"); - if (parser.settings.strict) { - const mathFunction = funcName[1] === "m"; // \mkern, \mskip - const muUnit = size.value.unit === "mu"; - if (mathFunction) { - if (!muUnit) { - throw new ParseError(`LaTeX's ${funcName} supports only mu units, ` + - `not ${size.value.unit} units`, token) - } - if (parser.mode !== "math") { - throw new ParseError(`LaTeX's ${funcName} works only in math mode`, token) - } - } else { - // !mathFunction - if (muUnit) { - throw new ParseError(`LaTeX's ${funcName} doesn't support mu units`, token) - } - } - } - return { - type: "kern", - mode: parser.mode, - dimension: size.value - }; - }, - mathmlBuilder(group, style) { - const dimension = calculateSize(group.dimension, style); - const ch = dimension.unit === "em" ? spaceCharacter(dimension.number) : ""; - if (group.mode === "text" && ch.length > 0) { - const character = new mathMLTree.TextNode(ch); - return new mathMLTree.MathNode("mtext", [character]); - } else { - const node = new mathMLTree.MathNode("mspace"); - node.setAttribute("width", dimension.number + dimension.unit); - return node; - } - } -}); - -const spaceCharacter = function(width) { - if (width >= 0.05555 && width <= 0.05556) { - return "\u200a"; //   - } else if (width >= 0.1666 && width <= 0.1667) { - return "\u2009"; //   - } else if (width >= 0.2222 && width <= 0.2223) { - return "\u2005"; //   - } else if (width >= 0.2777 && width <= 0.2778) { - return "\u2005\u200a"; //    - } else { - return ""; - } -}; - -// Limit valid characters to a small set, for safety. -const invalidIdRegEx = /[^A-Za-z_0-9-]/g; - -defineFunction({ - type: "label", - names: ["\\label"], - props: { - numArgs: 1, - argTypes: ["raw"] - }, - handler({ parser }, args) { - return { - type: "label", - mode: parser.mode, - string: args[0].string.replace(invalidIdRegEx, "") - }; - }, - mathmlBuilder(group, style) { - // Return a no-width, no-ink element with an HTML id. - const node = new mathMLTree.MathNode("mrow", [], ["tml-label"]); - if (group.string.length > 0) { - node.setAttribute("id", group.string); - } - return node - } -}); - -// Horizontal overlap functions - -const textModeLap = ["\\clap", "\\llap", "\\rlap"]; - -defineFunction({ - type: "lap", - names: ["\\mathllap", "\\mathrlap", "\\mathclap", "\\clap", "\\llap", "\\rlap"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser, funcName, token }, args) => { - if (textModeLap.includes(funcName)) { - if (parser.settings.strict && parser.mode !== "text") { - throw new ParseError(`{${funcName}} can be used only in text mode. - Try \\math${funcName.slice(1)}`, token) - } - funcName = funcName.slice(1); - } else { - funcName = funcName.slice(5); - } - const body = args[0]; - return { - type: "lap", - mode: parser.mode, - alignment: funcName, - body - } - }, - mathmlBuilder: (group, style) => { - // mathllap, mathrlap, mathclap - const node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, style)]); - - if (group.alignment === "rlap") { - if (group.body.body.length > 0 && group.body.body[0].type === "genfrac") { - // In Firefox, a squashes the 3/18em padding of a child \frac. Put it back. - node.setAttribute("lspace", "0.16667em"); - } - } else { - const offset = group.alignment === "llap" ? "-1" : "-0.5"; - node.setAttribute("lspace", offset + "width"); - } - node.setAttribute("width", "0px"); - return node - } -}); - -// Switching from text mode back to math mode -defineFunction({ - type: "ordgroup", - names: ["\\(", "$"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: false - }, - handler({ funcName, parser }, args) { - const outerMode = parser.mode; - parser.switchMode("math"); - const close = funcName === "\\(" ? "\\)" : "$"; - const body = parser.parseExpression(false, close); - parser.expect(close); - parser.switchMode(outerMode); - return { - type: "ordgroup", - mode: parser.mode, - body - }; - } -}); - -// Check for extra closing math delimiters -defineFunction({ - type: "text", // Doesn't matter what this is. - names: ["\\)", "\\]"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: false - }, - handler(context, token) { - throw new ParseError(`Mismatched ${context.funcName}`, token); - } -}); - -const chooseStyle = (group, style) => { - switch (style.level) { - case StyleLevel.DISPLAY: // 0 - return group.display; - case StyleLevel.TEXT: // 1 - return group.text; - case StyleLevel.SCRIPT: // 2 - return group.script; - case StyleLevel.SCRIPTSCRIPT: // 3 - return group.scriptscript; - default: - return group.text; - } -}; - -defineFunction({ - type: "mathchoice", - names: ["\\mathchoice"], - props: { - numArgs: 4, - primitive: true - }, - handler: ({ parser }, args) => { - return { - type: "mathchoice", - mode: parser.mode, - display: ordargument(args[0]), - text: ordargument(args[1]), - script: ordargument(args[2]), - scriptscript: ordargument(args[3]) - }; - }, - mathmlBuilder: (group, style) => { - const body = chooseStyle(group, style); - return buildExpressionRow(body, style); - } -}); - -const textAtomTypes = ["text", "textord", "mathord", "atom"]; - -function mathmlBuilder$3(group, style) { - let node; - const inner = buildExpression(group.body, style); - - if (group.mclass === "minner") { - node = new mathMLTree.MathNode("mpadded", inner); - } else if (group.mclass === "mord") { - if (group.isCharacterBox || inner[0].type === "mathord") { - node = inner[0]; - node.type = "mi"; - } else { - node = new mathMLTree.MathNode("mi", inner); - } - } else { - if (group.mustPromote) { - node = inner[0]; - node.type = "mo"; - if (group.isCharacterBox && group.body[0].text && /[A-Za-z]/.test(group.body[0].text)) { - node.setAttribute("mathvariant", "italic"); - } - } else { - node = new mathMLTree.MathNode("mo", inner); - } - - // Set spacing based on what is the most likely adjacent atom type. - // See TeXbook p170. - const doSpacing = style.level < 2; // Operator spacing is zero inside a (sub|super)script. - if (group.mclass === "mbin") { - // medium space - node.attributes.lspace = (doSpacing ? "0.2222em" : "0"); - node.attributes.rspace = (doSpacing ? "0.2222em" : "0"); - } else if (group.mclass === "mrel") { - // thickspace - node.attributes.lspace = (doSpacing ? "0.2778em" : "0"); - node.attributes.rspace = (doSpacing ? "0.2778em" : "0"); - } else if (group.mclass === "mpunct") { - node.attributes.lspace = "0em"; - node.attributes.rspace = (doSpacing ? "0.1667em" : "0"); - } else if (group.mclass === "mopen" || group.mclass === "mclose") { - node.attributes.lspace = "0em"; - node.attributes.rspace = "0em"; - } else if (group.mclass === "minner" && doSpacing) { - node.attributes.lspace = "0.0556em"; // 1 mu is the most likely option - node.attributes.width = "+0.1111em"; - } - if (!(group.mclass === "mopen" || group.mclass === "mclose")) { - delete node.attributes.stretchy; - delete node.attributes.form; - } - } - return node; -} - -// Math class commands except \mathop -defineFunction({ - type: "mclass", - names: [ - "\\mathord", - "\\mathbin", - "\\mathrel", - "\\mathopen", - "\\mathclose", - "\\mathpunct", - "\\mathinner" - ], - props: { - numArgs: 1, - primitive: true - }, - handler({ parser, funcName }, args) { - const body = args[0]; - const isCharacterBox = utils.isCharacterBox(body); - // We should not wrap a around a or . That would be invalid MathML. - // In that case, we instead promote the text contents of the body to the parent. - let mustPromote = true; - const mord = { type: "mathord", text: "", mode: parser.mode }; - const arr = (body.body) ? body.body : [body]; - for (const arg of arr) { - if (textAtomTypes.includes(arg.type)) { - if (arg.text) { - mord.text += arg.text; - } else if (arg.body) { - arg.body.map(e => { mord.text += e.text; }); - } - } else { - mustPromote = false; - break - } - } - return { - type: "mclass", - mode: parser.mode, - mclass: "m" + funcName.slice(5), - body: ordargument(mustPromote ? mord : body), - isCharacterBox, - mustPromote - }; - }, - mathmlBuilder: mathmlBuilder$3 -}); - -const binrelClass = (arg) => { - // \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument. - // (by rendering separately and with {}s before and after, and measuring - // the change in spacing). We'll do roughly the same by detecting the - // atom type directly. - const atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg; - if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) { - return "m" + atom.family; - } else { - return "mord"; - } -}; - -// \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord. -// This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX. -defineFunction({ - type: "mclass", - names: ["\\@binrel"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "mclass", - mode: parser.mode, - mclass: binrelClass(args[0]), - body: ordargument(args[1]), - isCharacterBox: utils.isCharacterBox(args[1]) - }; - } -}); - -// Build a relation or stacked op by placing one symbol on top of another -defineFunction({ - type: "mclass", - names: ["\\stackrel", "\\overset", "\\underset"], - props: { - numArgs: 2 - }, - handler({ parser, funcName }, args) { - const baseArg = args[1]; - const shiftedArg = args[0]; - - const baseOp = { - type: "op", - mode: baseArg.mode, - limits: true, - alwaysHandleSupSub: true, - parentIsSupSub: false, - symbol: false, - stack: true, - suppressBaseShift: funcName !== "\\stackrel", - body: ordargument(baseArg) - }; - - return { - type: "supsub", - mode: shiftedArg.mode, - base: baseOp, - sup: funcName === "\\underset" ? null : shiftedArg, - sub: funcName === "\\underset" ? shiftedArg : null - }; - }, - mathmlBuilder: mathmlBuilder$3 -}); - -// Helper function -const buildGroup = (el, style, noneNode) => { - if (!el) { return noneNode } - const node = buildGroup$1(el, style); - if (node.type === "mrow" && node.children.length === 0) { return noneNode } - return node -}; - -defineFunction({ - type: "multiscript", - names: ["\\sideset", "\\pres@cript"], // See macros.js for \prescript - props: { - numArgs: 3 - }, - handler({ parser, funcName, token }, args) { - if (args[2].body.length === 0) { - throw new ParseError(funcName + `cannot parse an empty base.`) - } - const base = args[2].body[0]; - if (parser.settings.strict && funcName === "\\sideset" && !base.symbol) { - throw new ParseError(`The base of \\sideset must be a big operator. Try \\prescript.`) - } - - if ((args[0].body.length > 0 && args[0].body[0].type !== "supsub") || - (args[1].body.length > 0 && args[1].body[0].type !== "supsub")) { - throw new ParseError("\\sideset can parse only subscripts and " + - "superscripts in its first two arguments", token) - } - - // The prescripts and postscripts come wrapped in a supsub. - const prescripts = args[0].body.length > 0 ? args[0].body[0] : null; - const postscripts = args[1].body.length > 0 ? args[1].body[0] : null; - - if (!prescripts && !postscripts) { - return base - } else if (!prescripts) { - // It's not a multi-script. Get a \textstyle supsub. - return { - type: "styling", - mode: parser.mode, - scriptLevel: "text", - body: [{ - type: "supsub", - mode: parser.mode, - base, - sup: postscripts.sup, - sub: postscripts.sub - }] - } - } else { - return { - type: "multiscript", - mode: parser.mode, - isSideset: funcName === "\\sideset", - prescripts, - postscripts, - base - } - } - }, - mathmlBuilder(group, style) { - const base = buildGroup$1(group.base, style); - - const prescriptsNode = new mathMLTree.MathNode("mprescripts"); - const noneNode = new mathMLTree.MathNode("none"); - let children = []; - - const preSub = buildGroup(group.prescripts.sub, style, noneNode); - const preSup = buildGroup(group.prescripts.sup, style, noneNode); - if (group.isSideset) { - // This seems silly, but LaTeX does this. Firefox ignores it, which does not make me sad. - preSub.setAttribute("style", "text-align: left;"); - preSup.setAttribute("style", "text-align: left;"); - } - - if (group.postscripts) { - const postSub = buildGroup(group.postscripts.sub, style, noneNode); - const postSup = buildGroup(group.postscripts.sup, style, noneNode); - children = [base, postSub, postSup, prescriptsNode, preSub, preSup]; - } else { - children = [base, prescriptsNode, preSub, preSup]; - } - - return new mathMLTree.MathNode("mmultiscripts", children); - } -}); - -defineFunction({ - type: "not", - names: ["\\not"], - props: { - numArgs: 1, - primitive: true, - allowedInText: false - }, - handler({ parser }, args) { - const isCharacterBox = utils.isCharacterBox(args[0]); - let body; - if (isCharacterBox) { - body = ordargument(args[0]); - if (body[0].text.charAt(0) === "\\") { - body[0].text = symbols.math[body[0].text].replace; - } - // \u0338 is the Unicode Combining Long Solidus Overlay - body[0].text = body[0].text.slice(0, 1) + "\u0338" + body[0].text.slice(1); - } else { - // When the argument is not a character box, TeX does an awkward, poorly placed overlay. - // We'll do the same. - const notNode = { type: "textord", mode: "math", text: "\u0338" }; - const kernNode = { type: "kern", mode: "math", dimension: { number: -0.6, unit: "em" } }; - body = [notNode, kernNode, args[0]]; - } - return { - type: "not", - mode: parser.mode, - body, - isCharacterBox - }; - }, - mathmlBuilder(group, style) { - if (group.isCharacterBox) { - const inner = buildExpression(group.body, style); - return inner[0] - } else { - return buildExpressionRow(group.body, style, true) - } - } -}); - -// Limits, symbols - -// Some helpers - -const ordAtomTypes = ["textord", "mathord", "atom"]; - -// Most operators have a large successor symbol, but these don't. -const noSuccessor = ["\\smallint"]; - -// Math operators (e.g. \sin) need a space between these types and themselves: -const ordTypes = ["textord", "mathord", "ordgroup", "close", "leftright"]; - -const dels = ["}", "\\left", "\\middle", "\\right"]; -const isDelimiter = str => str.length > 0 && - (delimiters.includes(str) || delimiterSizes[str] || dels.includes(str)); - -// NOTE: Unlike most `builders`s, this one handles not only "op", but also -// "supsub" since some of them (like \int) can affect super/subscripting. - -const mathmlBuilder$2 = (group, style) => { - let node; - - if (group.symbol) { - // This is a symbol. Just add the symbol. - node = new MathNode("mo", [makeText(group.name, group.mode)]); - if (utils.contains(noSuccessor, group.name)) { - node.setAttribute("largeop", "false"); - } else { - node.setAttribute("movablelimits", "false"); - } - } else if (group.body) { - // This is an operator with children. Add them. - node = new MathNode("mo", buildExpression(group.body, style)); - } else { - // This is a text operator. Add all of the characters from the operator's name. - node = new MathNode("mi", [new TextNode(group.name.slice(1))]); - - if (!group.parentIsSupSub) { - // Append an invisible . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new MathNode("mo", [makeText("\u2061", "text")]); - node = new MathNode("mpadded", [node, operator]); - const lSpace = group.needsLeadingSpace ? 0.1667 : 0; - const rSpace = group.isFollowedByDelimiter ? 0 : 0.1666; - if (group.needsLeadingSpace) { - node.setAttribute("lspace", "0.1667em"); // thin space. - } - if ((lSpace + rSpace) > 0) { - node.setAttribute("width", `+${lSpace + rSpace}em`); - } - } - } - - return node; -}; - -const singleCharBigOps = { - "\u220F": "\\prod", - "\u2210": "\\coprod", - "\u2211": "\\sum", - "\u22c0": "\\bigwedge", - "\u22c1": "\\bigvee", - "\u22c2": "\\bigcap", - "\u22c3": "\\bigcup", - "\u2a00": "\\bigodot", - "\u2a01": "\\bigoplus", - "\u2a02": "\\bigotimes", - "\u2a04": "\\biguplus", - "\u2a05": "\\bigsqcap", - "\u2a06": "\\bigsqcup" -}; - -defineFunction({ - type: "op", - names: [ - "\\coprod", - "\\bigvee", - "\\bigwedge", - "\\biguplus", - "\\bigcap", - "\\bigcup", - "\\intop", - "\\prod", - "\\sum", - "\\bigotimes", - "\\bigoplus", - "\\bigodot", - "\\bigsqcap", - "\\bigsqcup", - "\\smallint", - "\u220F", - "\u2210", - "\u2211", - "\u22c0", - "\u22c1", - "\u22c2", - "\u22c3", - "\u2a00", - "\u2a01", - "\u2a02", - "\u2a04", - "\u2a06" - ], - props: { - numArgs: 0 - }, - handler: ({ parser, funcName }, args) => { - let fName = funcName; - if (fName.length === 1) { - fName = singleCharBigOps[fName]; - } - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: true, - stack: false, // This is true for \stackrel{}, not here. - name: fName - }; - }, - mathmlBuilder: mathmlBuilder$2 -}); - -// Note: calling defineFunction with a type that's already been defined only -// works because the same mathmlBuilder is being used. -defineFunction({ - type: "op", - names: ["\\mathop"], - props: { - numArgs: 1, - primitive: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - // It would be convienient to just wrap a around the argument. - // But if the argument is a or , that would be invalid MathML. - // In that case, we instead promote the text contents of the body to the parent. - const arr = (body.body) ? body.body : [body]; - const isSymbol = arr.length === 1 && ordAtomTypes.includes(arr[0].type); - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: isSymbol, - stack: false, - name: isSymbol ? arr[0].text : null, - body: isSymbol ? null : ordargument(body) - }; - }, - mathmlBuilder: mathmlBuilder$2 -}); - -// There are 2 flags for operators; whether they produce limits in -// displaystyle, and whether they are symbols and should grow in -// displaystyle. These four groups cover the four possible choices. - -const singleCharIntegrals = { - "\u222b": "\\int", - "\u222c": "\\iint", - "\u222d": "\\iiint", - "\u222e": "\\oint", - "\u222f": "\\oiint", - "\u2230": "\\oiiint", - "\u2231": "\\intclockwise", - "\u2232": "\\varointclockwise", - "\u2a0c": "\\iiiint", - "\u2a0d": "\\intbar", - "\u2a0e": "\\intBar", - "\u2a0f": "\\fint", - "\u2a12": "\\rppolint", - "\u2a13": "\\scpolint", - "\u2a15": "\\pointint", - "\u2a16": "\\sqint", - "\u2a17": "\\intlarhk", - "\u2a18": "\\intx", - "\u2a19": "\\intcap", - "\u2a1a": "\\intcup" -}; - -// No limits, not symbols -defineFunction({ - type: "op", - names: [ - "\\arcsin", - "\\arccos", - "\\arctan", - "\\arctg", - "\\arcctg", - "\\arg", - "\\ch", - "\\cos", - "\\cosec", - "\\cosh", - "\\cot", - "\\cotg", - "\\coth", - "\\csc", - "\\ctg", - "\\cth", - "\\deg", - "\\dim", - "\\exp", - "\\hom", - "\\ker", - "\\lg", - "\\ln", - "\\log", - "\\sec", - "\\sin", - "\\sinh", - "\\sh", - "\\sgn", - "\\tan", - "\\tanh", - "\\tg", - "\\th" - ], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - const prevAtomType = parser.prevAtomType; - const next = parser.gullet.future().text; - return { - type: "op", - mode: parser.mode, - limits: false, - parentIsSupSub: false, - symbol: false, - stack: false, - isFollowedByDelimiter: isDelimiter(next), - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType), - name: funcName - }; - }, - mathmlBuilder: mathmlBuilder$2 -}); - -// Limits, not symbols -defineFunction({ - type: "op", - names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - const prevAtomType = parser.prevAtomType; - const next = parser.gullet.future().text; - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: false, - stack: false, - isFollowedByDelimiter: isDelimiter(next), - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType), - name: funcName - }; - }, - mathmlBuilder: mathmlBuilder$2 -}); - -// No limits, symbols -defineFunction({ - type: "op", - names: [ - "\\int", - "\\iint", - "\\iiint", - "\\iiiint", - "\\oint", - "\\oiint", - "\\oiiint", - "\\intclockwise", - "\\varointclockwise", - "\\intbar", - "\\intBar", - "\\fint", - "\\rppolint", - "\\scpolint", - "\\pointint", - "\\sqint", - "\\intlarhk", - "\\intx", - "\\intcap", - "\\intcup", - "\u222b", - "\u222c", - "\u222d", - "\u222e", - "\u222f", - "\u2230", - "\u2231", - "\u2232", - "\u2a0c", - "\u2a0d", - "\u2a0e", - "\u2a0f", - "\u2a12", - "\u2a13", - "\u2a15", - "\u2a16", - "\u2a17", - "\u2a18", - "\u2a19", - "\u2a1a" - ], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - let fName = funcName; - if (fName.length === 1) { - fName = singleCharIntegrals[fName]; - } - return { - type: "op", - mode: parser.mode, - limits: false, - parentIsSupSub: false, - symbol: true, - stack: false, - name: fName - }; - }, - mathmlBuilder: mathmlBuilder$2 -}); - -/** - * All registered global/built-in macros. - * `macros.js` exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary via `macros.js`. - */ -const _macros = {}; - -// This function might one day accept an additional argument and do more things. -function defineMacro(name, body) { - _macros[name] = body; -} - -// NOTE: Unlike most builders, this one handles not only -// "operatorname", but also "supsub" since \operatorname* can -// affect super/subscripting. - -const mathmlBuilder$1 = (group, style) => { - let expression = buildExpression(group.body, style.withFont("mathrm")); - - // Is expression a string or has it something like a fraction? - let isAllString = true; // default - for (let i = 0; i < expression.length; i++) { - const node = expression[i]; - if (node instanceof mathMLTree.MathNode) { - switch (node.type) { - case "mi": - case "mn": - case "ms": - case "mtext": - break; // Do nothing yet. - case "mspace": - { - if (node.attributes.width) { - const width = node.attributes.width.replace("em", ""); - const ch = spaceCharacter(Number(width)); - if (ch === "") { - isAllString = false; - } else { - expression[i] = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode(ch)]); - } - } - } - break - case "mo": { - const child = node.children[0]; - if (node.children.length === 1 && child instanceof mathMLTree.TextNode) { - child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*"); - } else { - isAllString = false; - } - break - } - default: - isAllString = false; - } - } else { - isAllString = false; - } - } - - if (isAllString) { - // Write a single TextNode instead of multiple nested tags. - const word = expression.map((node) => node.toText()).join(""); - expression = [new mathMLTree.TextNode(word)]; - } else if ( - expression.length === 1 - && utils.contains(["mover", "munder"], expression[0].type) && - (expression[0].children[0].type === "mi" || expression[0].children[0].type === "mtext") - ) { - expression[0].children[0].type = "mi"; - if (group.parentIsSupSub) { - return new mathMLTree.MathNode("mrow", expression) - } else { - const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); - return mathMLTree.newDocumentFragment([expression[0], operator]) - } - } - - let wrapper; - if (isAllString) { - wrapper = new mathMLTree.MathNode("mi", expression); - wrapper.setAttribute("mathvariant", "normal"); - } else { - wrapper = new mathMLTree.MathNode("mrow", expression); - } - - if (!group.parentIsSupSub) { - // Append an . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); - if (group.needsLeadingSpace) { - // LaTeX gives operator spacing, but a gets ord spacing. - // So add a leading space. - const space = new mathMLTree.MathNode("mspace"); - space.setAttribute("width", "0.1667em"); // thin space. - return mathMLTree.newDocumentFragment([space, wrapper, operator]) - } else { - return mathMLTree.newDocumentFragment([wrapper, operator]) - } - } - - return wrapper -}; - -// \operatorname -// amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@ -defineFunction({ - type: "operatorname", - names: ["\\operatorname@", "\\operatornamewithlimits"], - props: { - numArgs: 1, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const body = args[0]; - const prevAtomType = parser.prevAtomType; - return { - type: "operatorname", - mode: parser.mode, - body: ordargument(body), - alwaysHandleSupSub: (funcName === "\\operatornamewithlimits"), - limits: false, - parentIsSupSub: false, - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType) - }; - }, - mathmlBuilder: mathmlBuilder$1 -}); - -defineMacro("\\operatorname", - "\\@ifstar\\operatornamewithlimits\\operatorname@"); - -defineFunctionBuilders({ - type: "ordgroup", - mathmlBuilder(group, style) { - return buildExpressionRow(group.body, style, true); - } -}); - -defineFunction({ - type: "overline", - names: ["\\overline"], - props: { - numArgs: 1 - }, - handler({ parser }, args) { - const body = args[0]; - return { - type: "overline", - mode: parser.mode, - body - }; - }, - mathmlBuilder(group, style) { - const operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u005F")]); - operator.setAttribute("stretchy", "true"); - - const node = new mathMLTree.MathNode( - "mover", - [buildGroup$1(group.body, style), operator] - ); - node.setAttribute("accent", "true"); - - return node; - } -}); - -defineFunction({ - type: "phantom", - names: ["\\phantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "phantom", - mode: parser.mode, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(group.body, style); - return new mathMLTree.MathNode("mphantom", inner); - } -}); - -defineFunction({ - type: "hphantom", - names: ["\\hphantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "hphantom", - mode: parser.mode, - body - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(ordargument(group.body), style); - const phantom = new mathMLTree.MathNode("mphantom", inner); - const node = new mathMLTree.MathNode("mpadded", [phantom]); - node.setAttribute("height", "0px"); - node.setAttribute("depth", "0px"); - return node; - } -}); - -defineFunction({ - type: "vphantom", - names: ["\\vphantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "vphantom", - mode: parser.mode, - body - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(ordargument(group.body), style); - const phantom = new mathMLTree.MathNode("mphantom", inner); - const node = new mathMLTree.MathNode("mpadded", [phantom]); - node.setAttribute("width", "0px"); - return node; - } -}); - -// \pmb is a simulation of bold font. -// The version of \pmb in ambsy.sty works by typesetting three copies of the argument -// with small offsets. We use CSS text-shadow. -// It's a hack. Not as good as a real bold font. Better than nothing. - -defineFunction({ - type: "pmb", - names: ["\\pmb"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "pmb", - mode: parser.mode, - body: ordargument(args[0]) - } - }, - mathmlBuilder(group, style) { - const inner = buildExpression(group.body, style); - // Wrap with an element. - const node = wrapWithMstyle(inner); - node.setAttribute("style", "text-shadow: 0.02em 0.01em 0.04px"); - return node - } -}); - -const sign = num => num >= 0 ? "+" : "-"; - -// \raise, \lower, and \raisebox - -const mathmlBuilder = (group, style) => { - const newStyle = style.withLevel(StyleLevel.TEXT); - const node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, newStyle)]); - const dy = calculateSize(group.dy, style); - node.setAttribute("voffset", dy.number + dy.unit); - const dyAbs = Math.abs(dy.number); - node.setAttribute("height", sign(dy.number) + dyAbs + dy.unit); - node.setAttribute("depth", sign(-dy.number) + dyAbs + dy.unit); - return node -}; - -defineFunction({ - type: "raise", - names: ["\\raise", "\\lower"], - props: { - numArgs: 2, - argTypes: ["size", "primitive"], - primitive: true - }, - handler({ parser, funcName }, args) { - const amount = assertNodeType(args[0], "size").value; - if (funcName === "\\lower") { amount.number *= -1; } - const body = args[1]; - return { - type: "raise", - mode: parser.mode, - dy: amount, - body - }; - }, - mathmlBuilder -}); - - -defineFunction({ - type: "raise", - names: ["\\raisebox"], - props: { - numArgs: 2, - argTypes: ["size", "hbox"], - allowedInText: true - }, - handler({ parser, funcName }, args) { - const amount = assertNodeType(args[0], "size").value; - const body = args[1]; - return { - type: "raise", - mode: parser.mode, - dy: amount, - body - }; - }, - mathmlBuilder -}); - -defineFunction({ - type: "ref", - names: ["\\ref", "\\eqref"], - props: { - numArgs: 1, - argTypes: ["raw"] - }, - handler({ parser, funcName }, args) { - return { - type: "ref", - mode: parser.mode, - funcName, - string: args[0].string.replace(invalidIdRegEx, "") - }; - }, - mathmlBuilder(group, style) { - // Create an empty text node. Set a class and an href. - // The post-processor will populate with the target's tag or equation number. - const classes = group.funcName === "\\ref" ? ["tml-ref"] : ["tml-ref", "tml-eqref"]; - const node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("")], classes); - node.setAttribute("href", "#" + group.string); - return node - } -}); - -defineFunction({ - type: "internal", - names: ["\\relax"], - props: { - numArgs: 0, - allowedInText: true - }, - handler({ parser }) { - return { - type: "internal", - mode: parser.mode - }; - } -}); - -defineFunction({ - type: "rule", - names: ["\\rule"], - props: { - numArgs: 2, - numOptionalArgs: 1, - argTypes: ["size", "size", "size"] - }, - handler({ parser }, args, optArgs) { - const shift = optArgs[0]; - const width = assertNodeType(args[0], "size"); - const height = assertNodeType(args[1], "size"); - return { - type: "rule", - mode: parser.mode, - shift: shift && assertNodeType(shift, "size").value, - width: width.value, - height: height.value - }; - }, - mathmlBuilder(group, style) { - const width = calculateSize(group.width, style); - const height = calculateSize(group.height, style); - const shift = group.shift - ? calculateSize(group.shift, style) - : { number: 0, unit: "em" }; - const color = (style.color && style.getColor()) || "black"; - - const rule = new mathMLTree.MathNode("mspace"); - if (width.number > 0 && height.number > 0) { - rule.setAttribute("mathbackground", color); - } - rule.setAttribute("width", width.number + width.unit); - rule.setAttribute("height", height.number + height.unit); - if (shift.number === 0) { return rule } - - const wrapper = new mathMLTree.MathNode("mpadded", [rule]); - if (shift.number >= 0) { - wrapper.setAttribute("height", "+" + shift.number + shift.unit); - } else { - wrapper.setAttribute("height", shift.number + shift.unit); - wrapper.setAttribute("depth", "+" + -shift.number + shift.unit); - } - wrapper.setAttribute("voffset", shift.number + shift.unit); - return wrapper; - } -}); - -// The size mappings are taken from TeX with \normalsize=10pt. -// We don't have to track script level. MathML does that. -const sizeMap = { - "\\tiny": 0.5, - "\\sixptsize": 0.6, - "\\Tiny": 0.6, - "\\scriptsize": 0.7, - "\\footnotesize": 0.8, - "\\small": 0.9, - "\\normalsize": 1.0, - "\\large": 1.2, - "\\Large": 1.44, - "\\LARGE": 1.728, - "\\huge": 2.074, - "\\Huge": 2.488 -}; - -defineFunction({ - type: "sizing", - names: [ - "\\tiny", - "\\sixptsize", - "\\Tiny", - "\\scriptsize", - "\\footnotesize", - "\\small", - "\\normalsize", - "\\large", - "\\Large", - "\\LARGE", - "\\huge", - "\\Huge" - ], - props: { - numArgs: 0, - allowedInText: true - }, - handler: ({ breakOnTokenText, funcName, parser }, args) => { - if (parser.settings.strict && parser.mode === "math") { - // eslint-disable-next-line no-console - console.log(`Temml strict-mode warning: Command ${funcName} is invalid in math mode.`); - } - const body = parser.parseExpression(false, breakOnTokenText); - return { - type: "sizing", - mode: parser.mode, - funcName, - body - }; - }, - mathmlBuilder: (group, style) => { - const newStyle = style.withFontSize(sizeMap[group.funcName]); - const inner = buildExpression(group.body, newStyle); - // Wrap with an element. - const node = wrapWithMstyle(inner); - const factor = (sizeMap[group.funcName] / style.fontSize).toFixed(4); - node.setAttribute("mathsize", factor + "em"); - return node; - } -}); - -// smash, with optional [tb], as in AMS - -defineFunction({ - type: "smash", - names: ["\\smash"], - props: { - numArgs: 1, - numOptionalArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args, optArgs) => { - let smashHeight = false; - let smashDepth = false; - const tbArg = optArgs[0] && assertNodeType(optArgs[0], "ordgroup"); - if (tbArg) { - // Optional [tb] argument is engaged. - // ref: amsmath: \renewcommand{\smash}[1][tb]{% - // def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}% - let letter = ""; - for (let i = 0; i < tbArg.body.length; ++i) { - const node = tbArg.body[i]; - // TODO: Write an AssertSymbolNode - letter = node.text; - if (letter === "t") { - smashHeight = true; - } else if (letter === "b") { - smashDepth = true; - } else { - smashHeight = false; - smashDepth = false; - break; - } - } - } else { - smashHeight = true; - smashDepth = true; - } - - const body = args[0]; - return { - type: "smash", - mode: parser.mode, - body, - smashHeight, - smashDepth - }; - }, - mathmlBuilder: (group, style) => { - const node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, style)]); - - if (group.smashHeight) { - node.setAttribute("height", "0px"); - } - - if (group.smashDepth) { - node.setAttribute("depth", "0px"); - } - - return node; - } -}); - -defineFunction({ - type: "sqrt", - names: ["\\sqrt"], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser }, args, optArgs) { - const index = optArgs[0]; - const body = args[0]; - return { - type: "sqrt", - mode: parser.mode, - body, - index - }; - }, - mathmlBuilder(group, style) { - const { body, index } = group; - return index - ? new mathMLTree.MathNode("mroot", [ - buildGroup$1(body, style), - buildGroup$1(index, style.incrementLevel()) - ]) - : new mathMLTree.MathNode("msqrt", [buildGroup$1(body, style)]); - } -}); - -const styleMap = { - display: 0, - text: 1, - script: 2, - scriptscript: 3 -}; - -const styleAttributes = { - display: ["0", "true"], - text: ["0", "false"], - script: ["1", "false"], - scriptscript: ["2", "false"] -}; - -defineFunction({ - type: "styling", - names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ breakOnTokenText, funcName, parser }, args) { - // parse out the implicit body - const body = parser.parseExpression(true, breakOnTokenText); - - const scriptLevel = funcName.slice(1, funcName.length - 5); - return { - type: "styling", - mode: parser.mode, - // Figure out what scriptLevel to use by pulling out the scriptLevel from - // the function name - scriptLevel, - body - }; - }, - mathmlBuilder(group, style) { - // Figure out what scriptLevel we're changing to. - const newStyle = style.withLevel(styleMap[group.scriptLevel]); - // The style argument in the next line does NOT directly set a MathML script level. - // It just tracks the style level, in case we need to know it for supsub or mathchoice. - const inner = buildExpression(group.body, newStyle); - // Wrap with an element. - const node = wrapWithMstyle(inner); - - const attr = styleAttributes[group.scriptLevel]; - - // Here is where we set the MathML script level. - node.setAttribute("scriptlevel", attr[0]); - node.setAttribute("displaystyle", attr[1]); - - return node; - } -}); - -/** - * Sometimes, groups perform special rules when they have superscripts or - * subscripts attached to them. This function lets the `supsub` group know that - * Sometimes, groups perform special rules when they have superscripts or - * its inner element should handle the superscripts and subscripts instead of - * handling them itself. - */ - -// Helpers -const symbolRegEx = /^m(over|under|underover)$/; - -// Super scripts and subscripts, whose precise placement can depend on other -// functions that precede them. -defineFunctionBuilders({ - type: "supsub", - mathmlBuilder(group, style) { - // Is the inner group a relevant horizonal brace? - let isBrace = false; - let isOver; - let isSup; - let appendApplyFunction = false; - let needsLeadingSpace = false; - - if (group.base && group.base.type === "horizBrace") { - isSup = !!group.sup; - if (isSup === group.base.isOver) { - isBrace = true; - isOver = group.base.isOver; - } - } - - if (group.base && !group.base.stack && - (group.base.type === "op" || group.base.type === "operatorname")) { - group.base.parentIsSupSub = true; - appendApplyFunction = !group.base.symbol; - needsLeadingSpace = group.base.needsLeadingSpace; - } - - const children = group.base && group.base.stack - ? [buildGroup$1(group.base.body[0], style)] - : [buildGroup$1(group.base, style)]; - - const childStyle = style.inSubOrSup(); - if (group.sub) { - children.push(buildGroup$1(group.sub, childStyle)); - } - - if (group.sup) { - children.push(buildGroup$1(group.sup, childStyle)); - } - - let nodeType; - if (isBrace) { - nodeType = isOver ? "mover" : "munder"; - } else if (!group.sub) { - const base = group.base; - if ( - base && - base.type === "op" && - base.limits && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "mover"; - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (base.limits || style.level === StyleLevel.DISPLAY) - ) { - nodeType = "mover"; - } else { - nodeType = "msup"; - } - } else if (!group.sup) { - const base = group.base; - if ( - base && - base.type === "op" && - base.limits && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "munder"; - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (base.limits || style.level === StyleLevel.DISPLAY) - ) { - nodeType = "munder"; - } else { - nodeType = "msub"; - } - } else { - const base = group.base; - if (base && ((base.type === "op" && base.limits) || base.type === "multiscript") && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "munderover"; - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (style.level === StyleLevel.DISPLAY || base.limits) - ) { - nodeType = "munderover"; - } else { - nodeType = "msubsup"; - } - } - - let node = new mathMLTree.MathNode(nodeType, children); - if (appendApplyFunction) { - // Append an . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); - if (needsLeadingSpace) { - const space = new mathMLTree.MathNode("mspace"); - space.setAttribute("width", "0.1667em"); // thin space. - node = mathMLTree.newDocumentFragment([space, node, operator]); - } else { - node = mathMLTree.newDocumentFragment([node, operator]); - } - } else if (symbolRegEx.test(nodeType)) { - // Wrap in a . Otherwise Firefox stretchy parens will not stretch to include limits. - node = new mathMLTree.MathNode("mrow", [node]); - } - - return node - } -}); - -// Operator ParseNodes created in Parser.js from symbol Groups in src/symbols.js. - -const short = ["\\shortmid", "\\nshortmid", "\\shortparallel", - "\\nshortparallel", "\\smallsetminus"]; - -defineFunctionBuilders({ - type: "atom", - mathmlBuilder(group, style) { - const node = new mathMLTree.MathNode("mo", [makeText(group.text, group.mode)]); - if (group.family === "punct") { - node.setAttribute("separator", "true"); - } else if (group.family === "open" || group.family === "close") { - // Delims built here should not stretch vertically. - // See delimsizing.js for stretchy delims. - if (group.family === "open") { - node.setAttribute("form", "prefix"); - // Set an explicit attribute for stretch. Otherwise Firefox may do it wrong. - node.setAttribute("stretchy", "false"); - } else if (group.family === "close") { - node.setAttribute("form", "postfix"); - node.setAttribute("stretchy", "false"); - } - } else if (group.text === "\\mid") { - // Firefox messes up this spacing if at the end of an . See it explicitly. - node.setAttribute("lspace", "0.22em"); // medium space - node.setAttribute("rspace", "0.22em"); - node.setAttribute("stretchy", "false"); - } else if (short.includes(group.text)) { - node.setAttribute("mathsize", "70%"); - } else if (group.text === ":") { - // ":" is not in the MathML operator dictionary. Give it BIN spacing. - node.attributes.lspace = "0.2222em"; - node.attributes.rspace = "0.2222em"; - } - return node; - } -}); - -/** - * Maps TeX font commands to "mathvariant" attribute in buildMathML.js - */ -const fontMap = { - // styles - mathbf: "bold", - mathrm: "normal", - textit: "italic", - mathit: "italic", - mathnormal: "italic", - - // families - mathbb: "double-struck", - mathcal: "script", - mathfrak: "fraktur", - mathscr: "script", - mathsf: "sans-serif", - mathtt: "monospace", - oldstylenums: "oldstylenums" -}; - -/** - * Returns the math variant as a string or null if none is required. - */ -const getVariant = function(group, style) { - // Handle font specifiers as best we can. - // Chromium does not support the MathML mathvariant attribute. - // So we'll use Unicode replacement characters instead. - // But first, determine the math variant. - - // Deal with the \textit, \textbf, etc., functions. - if (style.fontFamily === "texttt") { - return "monospace" - } else if (style.fontFamily === "textsc") { - return "normal"; // handled via character substitution in symbolsOrd.js. - } else if (style.fontFamily === "textsf") { - if (style.fontShape === "textit" && style.fontWeight === "textbf") { - return "sans-serif-bold-italic" - } else if (style.fontShape === "textit") { - return "sans-serif-italic" - } else if (style.fontWeight === "textbf") { - return "sans-serif-bold" - } else { - return "sans-serif" - } - } else if (style.fontShape === "textit" && style.fontWeight === "textbf") { - return "bold-italic" - } else if (style.fontShape === "textit") { - return "italic" - } else if (style.fontWeight === "textbf") { - return "bold" - } - - // Deal with the \mathit, mathbf, etc, functions. - const font = style.font; - if (!font || font === "mathnormal") { - return null - } - - const mode = group.mode; - switch (font) { - case "mathit": - return "italic" - case "mathrm": { - const codePoint = group.text.codePointAt(0); - // LaTeX \mathrm returns italic for Greek characters. - return (0x03ab < codePoint && codePoint < 0x03cf) ? "italic" : "normal" - } - case "greekItalic": - return "italic" - case "up@greek": - return "normal" - case "boldsymbol": - case "mathboldsymbol": - return "bold-italic" - case "mathbf": - return "bold" - case "mathbb": - return "double-struck" - case "mathfrak": - return "fraktur" - case "mathscr": - case "mathcal": - return "script" - case "mathsf": - return "sans-serif" - case "mathtt": - return "monospace" - case "oldstylenums": - return "oldstylenums" - } - - let text = group.text; - if (symbols[mode][text] && symbols[mode][text].replace) { - text = symbols[mode][text].replace; - } - - return Object.prototype.hasOwnProperty.call(fontMap, font) ? fontMap[font] : null -}; - -// Chromium does not support the MathML `mathvariant` attribute. -// Instead, we replace ASCII characters with Unicode characters that -// are defined in the font as bold, italic, double-struck, etc. -// This module identifies those Unicode code points. - -// First, a few helpers. -const script = Object.freeze({ - B: 0x20EA, // Offset from ASCII B to Unicode script B - E: 0x20EB, - F: 0x20EB, - H: 0x20C3, - I: 0x20C7, - L: 0x20C6, - M: 0x20E6, - R: 0x20C9, - e: 0x20CA, - g: 0x20A3, - o: 0x20C5 -}); - -const frak = Object.freeze({ - C: 0x20EA, - H: 0x20C4, - I: 0x20C8, - R: 0x20CA, - Z: 0x20CE -}); - -const bbb = Object.freeze({ - C: 0x20BF, // blackboard bold - H: 0x20C5, - N: 0x20C7, - P: 0x20C9, - Q: 0x20C9, - R: 0x20CB, - Z: 0x20CA -}); - -const bold = Object.freeze({ - "\u03f5": 0x1D2E7, // lunate epsilon - "\u03d1": 0x1D30C, // vartheta - "\u03f0": 0x1D2EE, // varkappa - "\u03c6": 0x1D319, // varphi - "\u03f1": 0x1D2EF, // varrho - "\u03d6": 0x1D30B // varpi -}); - -const boldItalic = Object.freeze({ - "\u03f5": 0x1D35B, // lunate epsilon - "\u03d1": 0x1D380, // vartheta - "\u03f0": 0x1D362, // varkappa - "\u03c6": 0x1D38D, // varphi - "\u03f1": 0x1D363, // varrho - "\u03d6": 0x1D37F // varpi -}); - -const boldsf = Object.freeze({ - "\u03f5": 0x1D395, // lunate epsilon - "\u03d1": 0x1D3BA, // vartheta - "\u03f0": 0x1D39C, // varkappa - "\u03c6": 0x1D3C7, // varphi - "\u03f1": 0x1D39D, // varrho - "\u03d6": 0x1D3B9 // varpi -}); - -const bisf = Object.freeze({ - "\u03f5": 0x1D3CF, // lunate epsilon - "\u03d1": 0x1D3F4, // vartheta - "\u03f0": 0x1D3D6, // varkappa - "\u03c6": 0x1D401, // varphi - "\u03f1": 0x1D3D7, // varrho - "\u03d6": 0x1D3F3 // varpi -}); - -// Code point offsets below are derived from https://www.unicode.org/charts/PDF/U1D400.pdf -const offset = Object.freeze({ - upperCaseLatin: { // A-Z - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D3BF }, - "italic": ch => { return 0x1D3F3 }, - "bold-italic": ch => { return 0x1D427 }, - "script": ch => { return script[ch] || 0x1D45B }, - "script-bold": ch => { return 0x1D48F }, - "fraktur": ch => { return frak[ch] || 0x1D4C3 }, - "fraktur-bold": ch => { return 0x1D52B }, - "double-struck": ch => { return bbb[ch] || 0x1D4F7 }, - "sans-serif": ch => { return 0x1D55F }, - "sans-serif-bold": ch => { return 0x1D593 }, - "sans-serif-italic": ch => { return 0x1D5C7 }, - "sans-serif-bold-italic": ch => { return 0x1D63C }, - "monospace": ch => { return 0x1D62F } - }, - lowerCaseLatin: { // a-z - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D3B9 }, - "italic": ch => { return ch === "h" ? 0x20A6 : 0x1D3ED }, - "bold-italic": ch => { return 0x1D421 }, - "script": ch => { return script[ch] || 0x1D455 }, - "script-bold": ch => { return 0x1D489 }, - "fraktur": ch => { return 0x1D4BD }, - "fraktur-bold": ch => { return 0x1D525 }, - "double-struck": ch => { return 0x1D4F1 }, - "sans-serif": ch => { return 0x1D559 }, - "sans-serif-bold": ch => { return 0x1D58D }, - "sans-serif-italic": ch => { return 0x1D5C1 }, - "sans-serif-bold-italic": ch => { return 0x1D5F5 }, - "monospace": ch => { return 0x1D629 } - }, - upperCaseGreek: { // A-Ω ∇ - "normal": ch => { return 0 }, - "bold": ch => { return ch === "∇" ? 0x1B4BA : 0x1D317 }, - "italic": ch => { return ch === "∇" ? 0x1B4F4 : 0x1D351 }, - // \boldsymbol actually returns upright bold for upperCaseGreek - "bold-italic": ch => { return ch === "∇" ? 0x1B4BA : 0x1D317 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - // Unicode has no code points for regular-weight san-serif Greek. Use bold. - "sans-serif": ch => { return ch === "∇" ? 0x1B568 : 0x1D3C5 }, - "sans-serif-bold": ch => { return ch === "∇" ? 0x1B568 : 0x1D3C5 }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return ch === "∇" ? 0x1B5A2 : 0x1D3FF }, - "monospace": ch => { return 0 } - }, - lowerCaseGreek: { // α-ω - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D311 }, - "italic": ch => { return 0x1D34B }, - "bold-italic": ch => { return ch === "\u03d5" ? 0x1D37E : 0x1D385 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - // Unicode has no code points for regular-weight san-serif Greek. Use bold. - "sans-serif": ch => { return 0x1D3BF }, - "sans-serif-bold": ch => { return 0x1D3BF }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return 0x1D3F9 }, - "monospace": ch => { return 0 } - }, - varGreek: { // \varGamma, etc - "normal": ch => { return 0 }, - "bold": ch => { return bold[ch] || -51 }, - "italic": ch => { return 0 }, - "bold-italic": ch => { return boldItalic[ch] || 0x3A }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - "sans-serif": ch => { return boldsf[ch] || 0x74 }, - "sans-serif-bold": ch => { return boldsf[ch] || 0x74 }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return bisf[ch] || 0xAE }, - "monospace": ch => { return 0 } - }, - numeral: { // 0-9 - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D79E }, - "italic": ch => { return 0 }, - "bold-italic": ch => { return 0 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0x1D7A8 }, - "sans-serif": ch => { return 0x1D7B2 }, - "sans-serif-bold": ch => { return 0x1D7BC }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return 0 }, - "monospace": ch => { return 0x1D7C6 } - } -}); - -const variantChar = (ch, variant) => { - const codePoint = ch.codePointAt(0); - const block = 0x40 < codePoint && codePoint < 0x5b - ? "upperCaseLatin" - : 0x60 < codePoint && codePoint < 0x7b - ? "lowerCaseLatin" - : (0x390 < codePoint && codePoint < 0x3AA) || ch === "∇" - ? "upperCaseGreek" - : 0x3B0 < codePoint && codePoint < 0x3CA || ch === "\u03d5" - ? "lowerCaseGreek" - : 0x1D6E1 < codePoint && codePoint < 0x1D6FC || bold[ch] - ? "varGreek" - : (0x2F < codePoint && codePoint < 0x3A) - ? "numeral" - : "other"; - return block === "other" - ? ch - : String.fromCodePoint(codePoint + offset[block][variant](ch)) -}; - -const smallCaps = Object.freeze({ - a: "ᴀ", - b: "ʙ", - c: "ᴄ", - d: "ᴅ", - e: "ᴇ", - f: "ꜰ", - g: "ɢ", - h: "ʜ", - i: "ɪ", - j: "ᴊ", - k: "ᴋ", - l: "ʟ", - m: "ᴍ", - n: "ɴ", - o: "ᴏ", - p: "ᴘ", - q: "ǫ", - r: "ʀ", - s: "s", - t: "ᴛ", - u: "ᴜ", - v: "ᴠ", - w: "ᴡ", - x: "x", - y: "ʏ", - z: "ᴢ" -}); - -// "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in -// src/symbols.js. - -const numberRegEx$1 = /^\d(?:[\d,.]*\d)?$/; // Keep in sync with numberRegEx in Parser.js - -const latinRegEx = /[A-Ba-z]/; - -const italicNumber = (text, variant) => { - const mn = new mathMLTree.MathNode("mn", [text]); - const wrapper = new mathMLTree.MathNode("mstyle", [mn]); - wrapper.style["font-style"] = "italic"; - wrapper.style["font-family"] = "Cambria, 'Times New Roman', serif"; - if (variant === "bold-italic") { wrapper.style["font-weight"] = "bold"; } - return wrapper -}; - -defineFunctionBuilders({ - type: "mathord", - mathmlBuilder(group, style) { - const text = makeText(group.text, group.mode, style); - const codePoint = text.text.codePointAt(0); - // Test for upper-case Greek - const defaultVariant = (0x0390 < codePoint && codePoint < 0x03aa) ? "normal" : "italic"; - const variant = getVariant(group, style) || defaultVariant; - if (variant === "script") { - text.text = variantChar(text.text, variant); - return new mathMLTree.MathNode("mi", [text], [style.font]) - } else if (variant !== "italic") { - text.text = variantChar(text.text, variant); - } - let node = new mathMLTree.MathNode("mi", [text]); - // TODO: Handle U+1D49C - U+1D4CF per https://www.unicode.org/charts/PDF/U1D400.pdf - if (variant === "normal") { - node.setAttribute("mathvariant", "normal"); - if (text.text.length === 1) { - // A Firefox bug will apply spacing here, but there should be none. Fix it. - node = new mathMLTree.MathNode("mpadded", [node]); - node.setAttribute("lspace", "0"); - node.setAttribute("width", "+0em"); - } - } - return node - } -}); - -defineFunctionBuilders({ - type: "textord", - mathmlBuilder(group, style) { - let ch = group.text; - const codePoint = ch.codePointAt(0); - if (style.fontFamily === "textsc") { - // Convert small latin letters to small caps. - if (96 < codePoint && codePoint < 123) { - ch = smallCaps[ch]; - } - } - const text = makeText(ch, group.mode, style); - const variant = getVariant(group, style) || "normal"; - - let node; - if (group.mode === "text") { - if (variant === "italic" || variant === "bold-italic") { - if (numberRegEx$1.test(group.text)) { - return italicNumber(text, variant) - } - } - if (variant !== "normal") { - text.text = variantChar(text.text, variant); - } - node = new mathMLTree.MathNode("mtext", [text]); - } else if (numberRegEx$1.test(group.text)) { - if (variant === "oldstylenums") { - const ms = new mathMLTree.MathNode("mstyle", [text], ["oldstylenums"]); - node = new mathMLTree.MathNode("mn", [ms]); - } else if (variant === "italic" || variant === "bold-italic") { - return italicNumber(text, variant) - } else { - if (variant !== "normal") { - text.text = text.text.split("").map(c => variantChar(c, variant)).join(""); - } - node = new mathMLTree.MathNode("mn", [text]); - } - } else if (group.text === "\\prime") { - node = new mathMLTree.MathNode("mo", [text]); - } else { - const origText = text.text; - if (variant !== "italic") { - text.text = variantChar(text.text, variant); - } - node = new mathMLTree.MathNode("mi", [text]); - if (text.text === origText && latinRegEx.test(origText)) { - node.setAttribute("mathvariant", "italic"); - } - } - return node - } -}); - -// A map of CSS-based spacing functions to their CSS class. -const cssSpace = { - "\\nobreak": "nobreak", - "\\allowbreak": "allowbreak" -}; - -// A lookup table to determine whether a spacing function/symbol should be -// treated like a regular space character. If a symbol or command is a key -// in this table, then it should be a regular space character. Furthermore, -// the associated value may have a `className` specifying an extra CSS class -// to add to the created `span`. -const regularSpace = { - " ": {}, - "\\ ": {}, - "~": { - className: "nobreak" - }, - "\\space": {}, - "\\nobreakspace": { - className: "nobreak" - } -}; - -// ParseNode<"spacing"> created in Parser.js from the "spacing" symbol Groups in -// src/symbols.js. -defineFunctionBuilders({ - type: "spacing", - mathmlBuilder(group, style) { - let node; - - if (Object.prototype.hasOwnProperty.call(regularSpace, group.text)) { - // Firefox does not render a space in a . So write a no-break space. - // TODO: If Firefox fixes that bug, uncomment the next line and write ch into the node. - //const ch = (regularSpace[group.text].className === "nobreak") ? "\u00a0" : " " - node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("\u00a0")]); - } else if (Object.prototype.hasOwnProperty.call(cssSpace, group.text)) { - // MathML 3.0 calls for nobreak to occur in an , not an - // Ref: https://www.w3.org/Math/draft-spec/mathml.html#chapter3_presm.lbattrs - node = new mathMLTree.MathNode("mo"); - if (group.text === "\\nobreak") { - node.setAttribute("linebreak", "nobreak"); - } - } else { - throw new ParseError(`Unknown type of space "${group.text}"`) - } - - return node - } -}); - -defineFunctionBuilders({ - type: "tag" -}); - -// For a \tag, the work usually done in a mathmlBuilder is instead done in buildMathML.js. -// That way, a \tag can be pulled out of the parse tree and wrapped around the outer node. - -// Non-mathy text, possibly in a font -const textFontFamilies = { - "\\text": undefined, - "\\textrm": "textrm", - "\\textsf": "textsf", - "\\texttt": "texttt", - "\\textnormal": "textrm", - "\\textsc": "textsc" // small caps -}; - -const textFontWeights = { - "\\textbf": "textbf", - "\\textmd": "textmd" -}; - -const textFontShapes = { - "\\textit": "textit", - "\\textup": "textup" -}; - -const styleWithFont = (group, style) => { - const font = group.font; - // Checks if the argument is a font family or a font style. - if (!font) { - return style; - } else if (textFontFamilies[font]) { - return style.withTextFontFamily(textFontFamilies[font]); - } else if (textFontWeights[font]) { - return style.withTextFontWeight(textFontWeights[font]); - } else { - return style.withTextFontShape(textFontShapes[font]); - } -}; - -defineFunction({ - type: "text", - names: [ - // Font families - "\\text", - "\\textrm", - "\\textsf", - "\\texttt", - "\\textnormal", - "\\textsc", - // Font weights - "\\textbf", - "\\textmd", - // Font Shapes - "\\textit", - "\\textup" - ], - props: { - numArgs: 1, - argTypes: ["text"], - allowedInArgument: true, - allowedInText: true - }, - handler({ parser, funcName }, args) { - const body = args[0]; - return { - type: "text", - mode: parser.mode, - body: ordargument(body), - font: funcName - }; - }, - mathmlBuilder(group, style) { - const newStyle = styleWithFont(group, style); - const mrow = buildExpressionRow(group.body, newStyle); - return utils.consolidateText(mrow) - } -}); - -// Two functions included to enable migration from Mathjax. - -defineFunction({ - type: "tip", - names: ["\\mathtip"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "tip", - mode: parser.mode, - body: args[0], - tip: args[1] - }; - }, - mathmlBuilder: (group, style) => { - const math = buildGroup$1(group.body, style); - const tip = buildGroup$1(group.tip, style); - // Browsers don't support the tooltip actiontype. - // TODO: Come back and fix \mathtip when it can be done via CSS w/o a JS event. - const node = new mathMLTree.MathNode("maction", [math, tip], ["tml-tip"]); - node.setAttribute("actiontype", "tooltip"); - return node - } -}); - -defineFunction({ - type: "tip", - names: ["\\texttip"], - props: { - numArgs: 2, - argTypes: ["math", "text"] - }, - handler({ parser }, args) { - return { - type: "tip", - mode: parser.mode, - body: args[0], - tip: args[1] - }; - }, - mathmlBuilder: (group, style) => { - const math = buildGroup$1(group.body, style); - const tip = buildGroup$1(group.tip, style); - // args[1] only accepted text, so tip is a element or a of them. - let str = ""; - if (tip.type === "mtext") { - str = tip.children[0].text; - } else { - for (const child of tip.children) { - str += child.children[0].text; - } - } - // Implement \texttip via a title attribute. - math.setAttribute("title", str); - return math - } -}); - -defineFunctionBuilders({ - type: "toggle", - mathmlBuilder(group, style) { - const expression = buildExpression(group.body, style); - const node = new mathMLTree.MathNode("maction", expression, [], { cursor: "default" }); - node.setAttribute("actiontype", "toggle"); - return node - } -}); - -defineFunction({ - type: "underline", - names: ["\\underline"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "underline", - mode: parser.mode, - body: args[0] - }; - }, - mathmlBuilder(group, style) { - const operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u005f")]); - operator.setAttribute("stretchy", "true"); - - const node = new mathMLTree.MathNode("munder", - [buildGroup$1(group.body, style), operator] - ); - node.setAttribute("accentunder", "true"); - - return node; - } -}); - -defineFunction({ - type: "verb", - names: ["\\verb"], - props: { - numArgs: 0, - allowedInText: true - }, - handler(context, args, optArgs) { - // \verb and \verb* are dealt with directly in Parser.js. - // If we end up here, it's because of a failure to match the two delimiters - // in the regex in Lexer.js. LaTeX raises the following error when \verb is - // terminated by end of line (or file). - throw new ParseError("\\verb ended by end of line instead of matching delimiter"); - }, - mathmlBuilder(group, style) { - const text = new mathMLTree.TextNode(makeVerb(group)); - const node = new mathMLTree.MathNode("mtext", [text]); - node.setAttribute("mathvariant", "monospace"); - return node; - } -}); - -/** - * Converts verb group into body string. - * - * \verb* replaces each space with an open box \u2423 - * \verb replaces each space with a no-break space \xA0 - */ -const makeVerb = (group) => group.body.replace(/ /g, group.star ? "\u2423" : "\xA0"); - -/** Include this to ensure that all functions are defined. */ - -const functions = _functions; - -/** - * Lexing or parsing positional information for error reporting. - * This object is immutable. - */ -class SourceLocation { - constructor(lexer, start, end) { - this.lexer = lexer; // Lexer holding the input string. - this.start = start; // Start offset, zero-based inclusive. - this.end = end; // End offset, zero-based exclusive. - } - - /** - * Merges two `SourceLocation`s from location providers, given they are - * provided in order of appearance. - * - Returns the first one's location if only the first is provided. - * - Returns a merged range of the first and the last if both are provided - * and their lexers match. - * - Otherwise, returns null. - */ - static range(first, second) { - if (!second) { - return first && first.loc; - } else if (!first || !first.loc || !second.loc || first.loc.lexer !== second.loc.lexer) { - return null; - } else { - return new SourceLocation(first.loc.lexer, first.loc.start, second.loc.end); - } - } -} - -/** - * Interface required to break circular dependency between Token, Lexer, and - * ParseError. - */ - -/** - * The resulting token returned from `lex`. - * - * It consists of the token text plus some position information. - * The position information is essentially a range in an input string, - * but instead of referencing the bare input string, we refer to the lexer. - * That way it is possible to attach extra metadata to the input string, - * like for example a file name or similar. - * - * The position information is optional, so it is OK to construct synthetic - * tokens if appropriate. Not providing available position information may - * lead to degraded error reporting, though. - */ -class Token { - constructor( - text, // the text of this token - loc - ) { - this.text = text; - this.loc = loc; - } - - /** - * Given a pair of tokens (this and endToken), compute a `Token` encompassing - * the whole input range enclosed by these two. - */ - range( - endToken, // last token of the range, inclusive - text // the text of the newly constructed token - ) { - return new Token(text, SourceLocation.range(this, endToken)); - } -} - -/** - * The Lexer class handles tokenizing the input in various ways. Since our - * parser expects us to be able to backtrack, the lexer allows lexing from any - * given starting point. - * - * Its main exposed function is the `lex` function, which takes a position to - * lex from and a type of token to lex. It defers to the appropriate `_innerLex` - * function. - * - * The various `_innerLex` functions perform the actual lexing of different - * kinds. - */ - -/* The following tokenRegex - * - matches typical whitespace (but not NBSP etc.) using its first two groups - * - does not match any control character \x00-\x1f except whitespace - * - does not match a bare backslash - * - matches any ASCII character except those just mentioned - * - does not match the BMP private use area \uE000-\uF8FF - * - does not match bare surrogate code units - * - matches any BMP character except for those just described - * - matches any valid Unicode surrogate pair - * - mathches numerals - * - matches a backslash followed by one or more whitespace characters - * - matches a backslash followed by one or more letters then whitespace - * - matches a backslash followed by any BMP character - * Capturing groups: - * [1] regular whitespace - * [2] backslash followed by whitespace - * [3] anything else, which may include: - * [4] left character of \verb* - * [5] left character of \verb - * [6] backslash followed by word, excluding any trailing whitespace - * Just because the Lexer matches something doesn't mean it's valid input: - * If there is no matching function or symbol definition, the Parser will - * still reject the input. - */ -const spaceRegexString = "[ \r\n\t]"; -const controlWordRegexString = "\\\\[a-zA-Z@]+"; -const controlSymbolRegexString = "\\\\[^\uD800-\uDFFF]"; -const controlWordWhitespaceRegexString = `(${controlWordRegexString})${spaceRegexString}*`; -const controlSpaceRegexString = "\\\\(\n|[ \r\t]+\n?)[ \r\t]*"; -const combiningDiacriticalMarkString = "[\u0300-\u036f]"; -const combiningDiacriticalMarksEndRegex = new RegExp(`${combiningDiacriticalMarkString}+$`); -const tokenRegexString = - `(${spaceRegexString}+)|` + // whitespace - `${controlSpaceRegexString}|` + // whitespace - "(number" + // numbers (in non-strict mode) - "|[!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + // single codepoint - `${combiningDiacriticalMarkString}*` + // ...plus accents - "|[\uD800-\uDBFF][\uDC00-\uDFFF]" + // surrogate pair - `${combiningDiacriticalMarkString}*` + // ...plus accents - "|\\\\verb\\*([^]).*?\\4" + // \verb* - "|\\\\verb([^*a-zA-Z]).*?\\5" + // \verb unstarred - `|${controlWordWhitespaceRegexString}` + // \macroName + spaces - `|${controlSymbolRegexString})`; // \\, \', etc. - -/** Main Lexer class */ -class Lexer { - constructor(input, settings) { - // Separate accents from characters - this.input = input; - this.settings = settings; - this.tokenRegex = new RegExp( - // Strict Temml, like TeX, lexes one numeral at a time. - // Default Temml lexes contiguous numerals into a single element. - tokenRegexString.replace("number|", settings.strict ? "" : "\\d(?:[\\d,.]*\\d)?|"), - "g" - ); - // Category codes. The lexer only supports comment characters (14) for now. - // MacroExpander additionally distinguishes active (13). - this.catcodes = { - "%": 14, // comment character - "~": 13 // active character - }; - } - - setCatcode(char, code) { - this.catcodes[char] = code; - } - - /** - * This function lexes a single token. - */ - lex() { - const input = this.input; - const pos = this.tokenRegex.lastIndex; - if (pos === input.length) { - return new Token("EOF", new SourceLocation(this, pos, pos)); - } - const match = this.tokenRegex.exec(input); - if (match === null || match.index !== pos) { - throw new ParseError( - `Unexpected character: '${input[pos]}'`, - new Token(input[pos], new SourceLocation(this, pos, pos + 1)) - ); - } - const text = match[6] || match[3] || (match[2] ? "\\ " : " "); - - if (this.catcodes[text] === 14) { - // comment character - const nlIndex = input.indexOf("\n", this.tokenRegex.lastIndex); - if (nlIndex === -1) { - this.tokenRegex.lastIndex = input.length; // EOF - if (this.settings.strict) { - throw new ParseError("% comment has no terminating newline; LaTeX would " + - "fail because of commenting the end of math mode") - } - } else { - this.tokenRegex.lastIndex = nlIndex + 1; - } - return this.lex(); - } - - return new Token(text, new SourceLocation(this, pos, this.tokenRegex.lastIndex)); - } -} - -/** - * A `Namespace` refers to a space of nameable things like macros or lengths, - * which can be `set` either globally or local to a nested group, using an - * undo stack similar to how TeX implements this functionality. - * Performance-wise, `get` and `set` take constant time. - */ - -class Namespace { - /** - * Both arguments are optional. The first argument is an object of - * built-in mappings which never change. The second argument is an object - * of initial (global-level) mappings, which will constantly change - * according to any global/top-level `set`s done. - */ - constructor(builtins = {}, globalMacros = {}) { - this.current = globalMacros; - this.builtins = builtins; - this.undefStack = []; - } - - /** - * Start a new nested group, affecting future local `set`s. - */ - beginGroup() { - this.undefStack.push({}); - } - - /** - * End current nested group, restoring values before the group began. - */ - endGroup() { - if (this.undefStack.length === 0) { - throw new ParseError( - "Unbalanced namespace destruction: attempt " + - "to pop global namespace; please report this as a bug" - ); - } - const undefs = this.undefStack.pop(); - for (const undef in undefs) { - if (Object.prototype.hasOwnProperty.call(undefs, undef )) { - if (undefs[undef] === undefined) { - delete this.current[undef]; - } else { - this.current[undef] = undefs[undef]; - } - } - } - } - - /** - * Detect whether `name` has a definition. Equivalent to - * `get(name) != null`. - */ - has(name) { - return Object.prototype.hasOwnProperty.call(this.current, name ) || - Object.prototype.hasOwnProperty.call(this.builtins, name ); - } - - /** - * Get the current value of a name, or `undefined` if there is no value. - * - * Note: Do not use `if (namespace.get(...))` to detect whether a macro - * is defined, as the definition may be the empty string which evaluates - * to `false` in JavaScript. Use `if (namespace.get(...) != null)` or - * `if (namespace.has(...))`. - */ - get(name) { - if (Object.prototype.hasOwnProperty.call(this.current, name )) { - return this.current[name]; - } else { - return this.builtins[name]; - } - } - - /** - * Set the current value of a name, and adds an undo - * operation to the undo stack. - */ - set(name, value) { - // Undo this set at end of this group (possibly to `undefined`), - // unless an undo is already in place, in which case that older - // value is the correct one. - const top = this.undefStack[this.undefStack.length - 1]; - if (top && !Object.prototype.hasOwnProperty.call(top, name )) { - top[name] = this.current[name]; - } - this.current[name] = value; - } -} - -/** - * Predefined macros for Temml. - * This can be used to define some commands in terms of others. - */ -const macros = _macros; - -////////////////////////////////////////////////////////////////////// -// macro tools - -defineMacro("\\noexpand", function(context) { - // The expansion is the token itself; but that token is interpreted - // as if its meaning were ‘\relax’ if it is a control sequence that - // would ordinarily be expanded by TeX’s expansion rules. - const t = context.popToken(); - if (context.isExpandable(t.text)) { - t.noexpand = true; - t.treatAsRelax = true; - } - return { tokens: [t], numArgs: 0 }; -}); - -defineMacro("\\expandafter", function(context) { - // TeX first reads the token that comes immediately after \expandafter, - // without expanding it; let’s call this token t. Then TeX reads the - // token that comes after t (and possibly more tokens, if that token - // has an argument), replacing it by its expansion. Finally TeX puts - // t back in front of that expansion. - const t = context.popToken(); - context.expandOnce(true); // expand only an expandable token - return { tokens: [t], numArgs: 0 }; -}); - -// LaTeX's \@firstoftwo{#1}{#2} expands to #1, skipping #2 -// TeX source: \long\def\@firstoftwo#1#2{#1} -defineMacro("\\@firstoftwo", function(context) { - const args = context.consumeArgs(2); - return { tokens: args[0], numArgs: 0 }; -}); - -// LaTeX's \@secondoftwo{#1}{#2} expands to #2, skipping #1 -// TeX source: \long\def\@secondoftwo#1#2{#2} -defineMacro("\\@secondoftwo", function(context) { - const args = context.consumeArgs(2); - return { tokens: args[1], numArgs: 0 }; -}); - -// LaTeX's \@ifnextchar{#1}{#2}{#3} looks ahead to the next (unexpanded) -// symbol that isn't a space, consuming any spaces but not consuming the -// first nonspace character. If that nonspace character matches #1, then -// the macro expands to #2; otherwise, it expands to #3. -defineMacro("\\@ifnextchar", function(context) { - const args = context.consumeArgs(3); // symbol, if, else - context.consumeSpaces(); - const nextToken = context.future(); - if (args[0].length === 1 && args[0][0].text === nextToken.text) { - return { tokens: args[1], numArgs: 0 }; - } else { - return { tokens: args[2], numArgs: 0 }; - } -}); - -// LaTeX's \@ifstar{#1}{#2} looks ahead to the next (unexpanded) symbol. -// If it is `*`, then it consumes the symbol, and the macro expands to #1; -// otherwise, the macro expands to #2 (without consuming the symbol). -// TeX source: \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}} -defineMacro("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}"); - -// LaTeX's \TextOrMath{#1}{#2} expands to #1 in text mode, #2 in math mode -defineMacro("\\TextOrMath", function(context) { - const args = context.consumeArgs(2); - if (context.mode === "text") { - return { tokens: args[0], numArgs: 0 }; - } else { - return { tokens: args[1], numArgs: 0 }; - } -}); - -const stringFromArg = arg => { - // Reverse the order of the arg and return a string. - let str = ""; - for (let i = arg.length - 1; i > -1; i--) { - str += arg[i].text; - } - return str -}; - -// Lookup table for parsing numbers in base 8 through 16 -const digitToNumber = { - 0: 0, - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9, - a: 10, - A: 10, - b: 11, - B: 11, - c: 12, - C: 12, - d: 13, - D: 13, - e: 14, - E: 14, - f: 15, - F: 15 -}; - -const nextCharNumber = context => { - const numStr = context.future().text; - if (numStr === "EOF") { return [null, ""] } - return [digitToNumber[numStr.charAt(0)], numStr] -}; - -const appendCharNumbers = (number, numStr, base) => { - for (let i = 1; i < numStr.length; i++) { - const digit = digitToNumber[numStr.charAt(i)]; - number *= base; - number += digit; - } - return number -}; - -// TeX \char makes a literal character (catcode 12) using the following forms: -// (see The TeXBook, p. 43) -// \char123 -- decimal -// \char'123 -- octal -// \char"123 -- hex -// \char`x -- character that can be written (i.e. isn't active) -// \char`\x -- character that cannot be written (e.g. %) -// These all refer to characters from the font, so we turn them into special -// calls to a function \@char dealt with in the Parser. -defineMacro("\\char", function(context) { - let token = context.popToken(); - let base; - let number = ""; - if (token.text === "'") { - base = 8; - token = context.popToken(); - } else if (token.text === '"') { - base = 16; - token = context.popToken(); - } else if (token.text === "`") { - token = context.popToken(); - if (token.text[0] === "\\") { - number = token.text.charCodeAt(1); - } else if (token.text === "EOF") { - throw new ParseError("\\char` missing argument"); - } else { - number = token.text.charCodeAt(0); - } - } else { - base = 10; - } - if (base) { - // Parse a number in the given base, starting with first `token`. - let numStr = token.text; - number = digitToNumber[numStr.charAt(0)]; - if (number == null || number >= base) { - throw new ParseError(`Invalid base-${base} digit ${token.text}`); - } - number = appendCharNumbers(number, numStr, base); - let digit; - [digit, numStr] = nextCharNumber(context); - while (digit != null && digit < base) { - number *= base; - number += digit; - number = appendCharNumbers(number, numStr, base); - context.popToken(); - [digit, numStr] = nextCharNumber(context); - } - } - return `\\@char{${number}}`; -}); - -// The Latin Modern font renders at the wrong vertical alignment. -// This macro provides a better rendering. -defineMacro("\\surd", "\\sqrt{}"); - -defineMacro("\\hbox", "\\text{#1}"); - -// Per TeXbook p.122, "/" gets zero operator spacing. -// And MDN recommends using U+2044 instead of / for inline -defineMacro("/", "{\u2044}"); - -// Since Temml has no \par, ignore \long. -defineMacro("\\long", ""); - -////////////////////////////////////////////////////////////////////// -// Grouping -// \let\bgroup={ \let\egroup=} -defineMacro("\\bgroup", "{"); -defineMacro("\\egroup", "}"); - -// Symbols from latex.ltx: -// \def~{\nobreakspace{}} -// \def\lq{`} -// \def\rq{'} -// \def \aa {\r a} -defineMacro("~", "\\nobreakspace"); -defineMacro("\\lq", "`"); -defineMacro("\\rq", "'"); -defineMacro("\\aa", "\\r a"); - -defineMacro("\\Bbbk", "\\Bbb{k}"); - -// \mathstrut from the TeXbook, p 360 -defineMacro("\\mathstrut", "\\vphantom{(}"); - -// \underbar from TeXbook p 353 -defineMacro("\\underbar", "\\underline{\\text{#1}}"); - -////////////////////////////////////////////////////////////////////// -// LaTeX_2ε - -// \vdots{\vbox{\baselineskip4\p@ \lineskiplimit\z@ -// \kern6\p@\hbox{.}\hbox{.}\hbox{.}}} -// We'll call \varvdots, which gets a glyph from symbols.js. -// The zero-width rule gets us an equivalent to the vertical 6pt kern. -defineMacro("\\vdots", "\\mathord{\\varvdots\\rule{0pt}{15pt}}"); -defineMacro("\u22ee", "\\vdots"); - -////////////////////////////////////////////////////////////////////// -// amsmath.sty -// http://mirrors.concertpass.com/tex-archive/macros/latex/required/amsmath/amsmath.pdf - -//\newcommand{\substack}[1]{\subarray{c}#1\endsubarray} -defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}"); - -// \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}} -defineMacro("\\boxed", "\\fbox{$\\displaystyle{#1}$}"); - -// \def\iff{\DOTSB\;\Longleftrightarrow\;} -// \def\implies{\DOTSB\;\Longrightarrow\;} -// \def\impliedby{\DOTSB\;\Longleftarrow\;} -defineMacro("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;"); -defineMacro("\\implies", "\\DOTSB\\;\\Longrightarrow\\;"); -defineMacro("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;"); - -// AMSMath's automatic \dots, based on \mdots@@ macro. -const dotsByToken = { - ",": "\\dotsc", - "\\not": "\\dotsb", - // \keybin@ checks for the following: - "+": "\\dotsb", - "=": "\\dotsb", - "<": "\\dotsb", - ">": "\\dotsb", - "-": "\\dotsb", - "*": "\\dotsb", - ":": "\\dotsb", - // Symbols whose definition starts with \DOTSB: - "\\DOTSB": "\\dotsb", - "\\coprod": "\\dotsb", - "\\bigvee": "\\dotsb", - "\\bigwedge": "\\dotsb", - "\\biguplus": "\\dotsb", - "\\bigcap": "\\dotsb", - "\\bigcup": "\\dotsb", - "\\prod": "\\dotsb", - "\\sum": "\\dotsb", - "\\bigotimes": "\\dotsb", - "\\bigoplus": "\\dotsb", - "\\bigodot": "\\dotsb", - "\\bigsqcap": "\\dotsb", - "\\bigsqcup": "\\dotsb", - "\\And": "\\dotsb", - "\\longrightarrow": "\\dotsb", - "\\Longrightarrow": "\\dotsb", - "\\longleftarrow": "\\dotsb", - "\\Longleftarrow": "\\dotsb", - "\\longleftrightarrow": "\\dotsb", - "\\Longleftrightarrow": "\\dotsb", - "\\mapsto": "\\dotsb", - "\\longmapsto": "\\dotsb", - "\\hookrightarrow": "\\dotsb", - "\\doteq": "\\dotsb", - // Symbols whose definition starts with \mathbin: - "\\mathbin": "\\dotsb", - // Symbols whose definition starts with \mathrel: - "\\mathrel": "\\dotsb", - "\\relbar": "\\dotsb", - "\\Relbar": "\\dotsb", - "\\xrightarrow": "\\dotsb", - "\\xleftarrow": "\\dotsb", - // Symbols whose definition starts with \DOTSI: - "\\DOTSI": "\\dotsi", - "\\int": "\\dotsi", - "\\oint": "\\dotsi", - "\\iint": "\\dotsi", - "\\iiint": "\\dotsi", - "\\iiiint": "\\dotsi", - "\\idotsint": "\\dotsi", - // Symbols whose definition starts with \DOTSX: - "\\DOTSX": "\\dotsx" -}; - -defineMacro("\\dots", function(context) { - // TODO: If used in text mode, should expand to \textellipsis. - // However, in Temml, \textellipsis and \ldots behave the same - // (in text mode), and it's unlikely we'd see any of the math commands - // that affect the behavior of \dots when in text mode. So fine for now - // (until we support \ifmmode ... \else ... \fi). - let thedots = "\\dotso"; - const next = context.expandAfterFuture().text; - if (next in dotsByToken) { - thedots = dotsByToken[next]; - } else if (next.slice(0, 4) === "\\not") { - thedots = "\\dotsb"; - } else if (next in symbols.math) { - if (utils.contains(["bin", "rel"], symbols.math[next].group)) { - thedots = "\\dotsb"; - } - } - return thedots; -}); - -const spaceAfterDots = { - // \rightdelim@ checks for the following: - ")": true, - "]": true, - "\\rbrack": true, - "\\}": true, - "\\rbrace": true, - "\\rangle": true, - "\\rceil": true, - "\\rfloor": true, - "\\rgroup": true, - "\\rmoustache": true, - "\\right": true, - "\\bigr": true, - "\\biggr": true, - "\\Bigr": true, - "\\Biggr": true, - // \extra@ also tests for the following: - $: true, - // \extrap@ checks for the following: - ";": true, - ".": true, - ",": true -}; - -defineMacro("\\dotso", function(context) { - const next = context.future().text; - if (next in spaceAfterDots) { - return "\\ldots\\,"; - } else { - return "\\ldots"; - } -}); - -defineMacro("\\dotsc", function(context) { - const next = context.future().text; - // \dotsc uses \extra@ but not \extrap@, instead specially checking for - // ';' and '.', but doesn't check for ','. - if (next in spaceAfterDots && next !== ",") { - return "\\ldots\\,"; - } else { - return "\\ldots"; - } -}); - -defineMacro("\\cdots", function(context) { - const next = context.future().text; - if (next in spaceAfterDots) { - return "\\@cdots\\,"; - } else { - return "\\@cdots"; - } -}); - -defineMacro("\\dotsb", "\\cdots"); -defineMacro("\\dotsm", "\\cdots"); -defineMacro("\\dotsi", "\\!\\cdots"); -defineMacro("\\idotsint", "\\dotsi"); -// amsmath doesn't actually define \dotsx, but \dots followed by a macro -// starting with \DOTSX implies \dotso, and then \extra@ detects this case -// and forces the added `\,`. -defineMacro("\\dotsx", "\\ldots\\,"); - -// \let\DOTSI\relax -// \let\DOTSB\relax -// \let\DOTSX\relax -defineMacro("\\DOTSI", "\\relax"); -defineMacro("\\DOTSB", "\\relax"); -defineMacro("\\DOTSX", "\\relax"); - -// Spacing, based on amsmath.sty's override of LaTeX defaults -// \DeclareRobustCommand{\tmspace}[3]{% -// \ifmmode\mskip#1#2\else\kern#1#3\fi\relax} -defineMacro("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"); -// \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}} -// TODO: math mode should use \thinmuskip -defineMacro("\\,", "{\\tmspace+{3mu}{.1667em}}"); -// \let\thinspace\, -defineMacro("\\thinspace", "\\,"); -// \def\>{\mskip\medmuskip} -// \renewcommand{\:}{\tmspace+\medmuskip{.2222em}} -// TODO: \> and math mode of \: should use \medmuskip = 4mu plus 2mu minus 4mu -defineMacro("\\>", "\\mskip{4mu}"); -defineMacro("\\:", "{\\tmspace+{4mu}{.2222em}}"); -// \let\medspace\: -defineMacro("\\medspace", "\\:"); -// \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}} -// TODO: math mode should use \thickmuskip = 5mu plus 5mu -defineMacro("\\;", "{\\tmspace+{5mu}{.2777em}}"); -// \let\thickspace\; -defineMacro("\\thickspace", "\\;"); -// \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}} -// TODO: math mode should use \thinmuskip -defineMacro("\\!", "{\\tmspace-{3mu}{.1667em}}"); -// \let\negthinspace\! -defineMacro("\\negthinspace", "\\!"); -// \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}} -// TODO: math mode should use \medmuskip -defineMacro("\\negmedspace", "{\\tmspace-{4mu}{.2222em}}"); -// \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}} -// TODO: math mode should use \thickmuskip -defineMacro("\\negthickspace", "{\\tmspace-{5mu}{.277em}}"); -// \def\enspace{\kern.5em } -defineMacro("\\enspace", "\\kern.5em "); -// \def\enskip{\hskip.5em\relax} -defineMacro("\\enskip", "\\hskip.5em\\relax"); -// \def\quad{\hskip1em\relax} -defineMacro("\\quad", "\\hskip1em\\relax"); -// \def\qquad{\hskip2em\relax} -defineMacro("\\qquad", "\\hskip2em\\relax"); - -// \tag@in@display form of \tag -defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren"); -defineMacro("\\tag@paren", "\\tag@literal{({#1})}"); -defineMacro("\\tag@literal", (context) => { - if (context.macros.get("\\df@tag")) { - throw new ParseError("Multiple \\tag"); - } - return "\\def\\df@tag{\\text{#1}}"; -}); - -// \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin -// {\operator@font mod}\penalty900 -// \mkern5mu\nonscript\mskip-\medmuskip} -// \newcommand{\pod}[1]{\allowbreak -// \if@display\mkern18mu\else\mkern8mu\fi(#1)} -// \renewcommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}} -// \newcommand{\mod}[1]{\allowbreak\if@display\mkern18mu -// \else\mkern12mu\fi{\operator@font mod}\,\,#1} -// TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu -defineMacro("\\bmod", "\\mathbin{\\text{mod}}"); -defineMacro( - "\\pod", - "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)" -); -defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}"); -defineMacro( - "\\mod", - "\\allowbreak" + - "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + - "{\\rm mod}\\,\\,#1" -); - -////////////////////////////////////////////////////////////////////// -// LaTeX source2e - -// \expandafter\let\expandafter\@normalcr -// \csname\expandafter\@gobble\string\\ \endcsname -// \DeclareRobustCommand\newline{\@normalcr\relax} -defineMacro("\\newline", "\\\\\\relax"); - -// \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@} -// TODO: Doesn't normally work in math mode because \@ fails. -defineMacro("\\TeX", "\\textrm{T}\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125em\\textrm{X}"); - -defineMacro( - "\\LaTeX", - "\\textrm{L}\\kern-.35em\\raisebox{0.2em}{\\scriptstyle A}\\kern-.15em\\TeX" -); - -defineMacro( - "\\Temml", - // eslint-disable-next-line max-len - "\\textrm{T}\\kern-0.2em\\lower{0.2em}\\textrm{E}\\kern-0.08em{\\textrm{M}\\kern-0.08em\\raise{0.2em}\\textrm{M}\\kern-0.08em\\textrm{L}}" -); - -// \DeclareRobustCommand\hspace{\@ifstar\@hspacer\@hspace} -// \def\@hspace#1{\hskip #1\relax} -// \def\@hspacer#1{\vrule \@width\z@\nobreak -// \hskip #1\hskip \z@skip} -defineMacro("\\hspace", "\\@ifstar\\@hspacer\\@hspace"); -defineMacro("\\@hspace", "\\hskip #1\\relax"); -defineMacro("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax"); - -defineMacro("\\colon", `\\mathpunct{\\char"3a}`); - -////////////////////////////////////////////////////////////////////// -// mathtools.sty - -defineMacro("\\prescript", "\\pres@cript{_{#1}^{#2}}{}{#3}"); - -//\providecommand\ordinarycolon{:} -defineMacro("\\ordinarycolon", `\\char"3a`); -// Raise to center on the math axis, as closely as possible. -defineMacro("\\vcentcolon", "\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}}"); -// \providecommand*\coloneq{\vcentcolon\mathrel{\mkern-1.2mu}\mathrel{-}} -defineMacro("\\coloneq", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"2212}'); -// \providecommand*\Coloneq{\dblcolon\mathrel{\mkern-1.2mu}\mathrel{-}} -defineMacro("\\Coloneq", '\\mathrel{\\char"2237\\char"2212}'); -// \providecommand*\Eqqcolon{=\mathrel{\mkern-1.2mu}\dblcolon} -defineMacro("\\Eqqcolon", '\\mathrel{\\char"3d\\char"2237}'); -// \providecommand*\Eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\dblcolon} -defineMacro("\\Eqcolon", '\\mathrel{\\char"2212\\char"2237}'); -// \providecommand*\colonapprox{\vcentcolon\mathrel{\mkern-1.2mu}\approx} -defineMacro("\\colonapprox", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"2248}'); -// \providecommand*\Colonapprox{\dblcolon\mathrel{\mkern-1.2mu}\approx} -defineMacro("\\Colonapprox", '\\mathrel{\\char"2237\\char"2248}'); -// \providecommand*\colonsim{\vcentcolon\mathrel{\mkern-1.2mu}\sim} -defineMacro("\\colonsim", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"223c}'); -// \providecommand*\Colonsim{\dblcolon\mathrel{\mkern-1.2mu}\sim} -defineMacro("\\Colonsim", '\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"223c}'); - -////////////////////////////////////////////////////////////////////// -// colonequals.sty - -// Alternate names for mathtools's macros: -defineMacro("\\ratio", "\\vcentcolon"); -defineMacro("\\coloncolon", "\\dblcolon"); -defineMacro("\\colonequals", "\\coloneqq"); -defineMacro("\\coloncolonequals", "\\Coloneqq"); -defineMacro("\\equalscolon", "\\eqqcolon"); -defineMacro("\\equalscoloncolon", "\\Eqqcolon"); -defineMacro("\\colonminus", "\\coloneq"); -defineMacro("\\coloncolonminus", "\\Coloneq"); -defineMacro("\\minuscolon", "\\eqcolon"); -defineMacro("\\minuscoloncolon", "\\Eqcolon"); -// \colonapprox name is same in mathtools and colonequals. -defineMacro("\\coloncolonapprox", "\\Colonapprox"); -// \colonsim name is same in mathtools and colonequals. -defineMacro("\\coloncolonsim", "\\Colonsim"); - -// Present in newtxmath, pxfonts and txfonts -defineMacro("\\notni", "\\mathrel{\\char`\u220C}"); -defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}"); -defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}"); - -////////////////////////////////////////////////////////////////////// -// From amsopn.sty -defineMacro("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}"); -defineMacro("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}"); -defineMacro("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{\\text{lim}}}"); -defineMacro("\\varliminf", "\\DOTSB\\operatorname*{\\underline{\\text{lim}}}"); -defineMacro("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{\\text{lim}}}"); -defineMacro("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{\\text{lim}}}"); - -defineMacro("\\centerdot", "{\\medspace\\rule{0.167em}{0.189em}\\medspace}"); - -////////////////////////////////////////////////////////////////////// -// statmath.sty -// https://ctan.math.illinois.edu/macros/latex/contrib/statmath/statmath.pdf - -defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}"); -defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}"); -defineMacro("\\plim", "\\DOTSB\\operatorname*{plim}"); - -////////////////////////////////////////////////////////////////////// -// braket.sty -// http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf - -defineMacro("\\bra", "\\mathinner{\\langle{#1}|}"); -defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}"); -defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}"); -defineMacro("\\Bra", "\\left\\langle#1\\right|"); -defineMacro("\\Ket", "\\left|#1\\right\\rangle"); -const braketHelper = (one) => (context) => { - const left = context.consumeArg().tokens; - const middle = context.consumeArg().tokens; - const middleDouble = context.consumeArg().tokens; - const right = context.consumeArg().tokens; - const oldMiddle = context.macros.get("|"); - const oldMiddleDouble = context.macros.get("\\|"); - context.macros.beginGroup(); - const midMacro = (double) => (context) => { - if (one) { - // Only modify the first instance of | or \| - context.macros.set("|", oldMiddle); - if (middleDouble.length) { - context.macros.set("\\|", oldMiddleDouble); - } - } - let doubled = double; - if (!double && middleDouble.length) { - // Mimic \@ifnextchar - const nextToken = context.future(); - if (nextToken.text === "|") { - context.popToken(); - doubled = true; - } - } - return { - tokens: doubled ? middleDouble : middle, - numArgs: 0 - }; - }; - context.macros.set("|", midMacro(false)); - if (middleDouble.length) { - context.macros.set("\\|", midMacro(true)); - } - const arg = context.consumeArg().tokens; - const expanded = context.expandTokens([...right, ...arg, ...left]); // reversed - context.macros.endGroup(); - return { - tokens: expanded.reverse(), - numArgs: 0 - }; -}; -defineMacro("\\bra@ket", braketHelper(false)); -defineMacro("\\bra@set", braketHelper(true)); -defineMacro("\\Braket", "\\bra@ket{\\left\\langle}" + - "{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"); -defineMacro("\\Set", "\\bra@set{\\left\\{\\:}" + - "{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"); -defineMacro("\\set", "\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"); - // has no support for special || or \| - -////////////////////////////////////////////////////////////////////// -// actuarialangle.dtx -defineMacro("\\angln", "{\\angl n}"); - -////////////////////////////////////////////////////////////////////// -// derivative.sty -defineMacro("\\odv", "\\@ifstar\\odv@next\\odv@numerator"); -defineMacro("\\odv@numerator", "\\frac{\\mathrm{d}#1}{\\mathrm{d}#2}"); -defineMacro("\\odv@next", "\\frac{\\mathrm{d}}{\\mathrm{d}#2}#1"); -defineMacro("\\pdv", "\\@ifstar\\pdv@next\\pdv@numerator"); - -const pdvHelper = args => { - const numerator = args[0][0].text; - const denoms = stringFromArg(args[1]).split(","); - const power = String(denoms.length); - const numOp = power === "1" ? "\\partial" : `\\partial^${power}`; - let denominator = ""; - denoms.map(e => { denominator += "\\partial " + e.trim() + "\\,";}); - return [numerator, numOp, denominator.replace(/\\,$/, "")] -}; -defineMacro("\\pdv@numerator", function(context) { - const [numerator, numOp, denominator] = pdvHelper(context.consumeArgs(2)); - return `\\frac{${numOp} ${numerator}}{${denominator}}` -}); -defineMacro("\\pdv@next", function(context) { - const [numerator, numOp, denominator] = pdvHelper(context.consumeArgs(2)); - return `\\frac{${numOp}}{${denominator}} ${numerator}` -}); - -////////////////////////////////////////////////////////////////////// -// upgreek.dtx -defineMacro("\\upalpha", "\\up@greek{\\alpha}"); -defineMacro("\\upbeta", "\\up@greek{\\beta}"); -defineMacro("\\upgamma", "\\up@greek{\\gamma}"); -defineMacro("\\updelta", "\\up@greek{\\delta}"); -defineMacro("\\upepsilon", "\\up@greek{\\epsilon}"); -defineMacro("\\upzeta", "\\up@greek{\\zeta}"); -defineMacro("\\upeta", "\\up@greek{\\eta}"); -defineMacro("\\uptheta", "\\up@greek{\\theta}"); -defineMacro("\\upiota", "\\up@greek{\\iota}"); -defineMacro("\\upkappa", "\\up@greek{\\kappa}"); -defineMacro("\\uplambda", "\\up@greek{\\lambda}"); -defineMacro("\\upmu", "\\up@greek{\\mu}"); -defineMacro("\\upnu", "\\up@greek{\\nu}"); -defineMacro("\\upxi", "\\up@greek{\\xi}"); -defineMacro("\\upomicron", "\\up@greek{\\omicron}"); -defineMacro("\\uppi", "\\up@greek{\\pi}"); -defineMacro("\\upalpha", "\\up@greek{\\alpha}"); -defineMacro("\\uprho", "\\up@greek{\\rho}"); -defineMacro("\\upsigma", "\\up@greek{\\sigma}"); -defineMacro("\\uptau", "\\up@greek{\\tau}"); -defineMacro("\\upupsilon", "\\up@greek{\\upsilon}"); -defineMacro("\\upphi", "\\up@greek{\\phi}"); -defineMacro("\\upchi", "\\up@greek{\\chi}"); -defineMacro("\\uppsi", "\\up@greek{\\psi}"); -defineMacro("\\upomega", "\\up@greek{\\omega}"); - -////////////////////////////////////////////////////////////////////// -// cmll package -defineMacro("\\invamp", '\\mathbin{\\char"214b}'); -defineMacro("\\parr", '\\mathbin{\\char"214b}'); -defineMacro("\\with", '\\mathbin{\\char"26}'); -defineMacro("\\multimapinv", '\\mathrel{\\char"27dc}'); -defineMacro("\\multimapboth", '\\mathrel{\\char"29df}'); -defineMacro("\\scoh", '{\\mkern5mu\\char"2322\\mkern5mu}'); -defineMacro("\\sincoh", '{\\mkern5mu\\char"2323\\mkern5mu}'); -defineMacro("\\coh", `{\\mkern5mu\\rule{}{0.7em}\\mathrlap{\\smash{\\raise2mu{\\char"2322}}} -{\\smash{\\lower4mu{\\char"2323}}}\\mkern5mu}`); -defineMacro("\\incoh", `{\\mkern5mu\\rule{}{0.7em}\\mathrlap{\\smash{\\raise2mu{\\char"2323}}} -{\\smash{\\lower4mu{\\char"2322}}}\\mkern5mu}`); - - -////////////////////////////////////////////////////////////////////// -// chemstyle package -defineMacro("\\standardstate", "\\text{\\tiny\\char`⦵}"); - -/* eslint-disable */ -/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ - -/************************************************************* - * - * Temml mhchem.js - * - * This file implements a Temml version of mhchem version 3.3.0. - * It is adapted from MathJax/extensions/TeX/mhchem.js - * It differs from the MathJax version as follows: - * 1. The interface is changed so that it can be called from Temml, not MathJax. - * 2. \rlap and \llap are replaced with \mathrlap and \mathllap. - * 3. The reaction arrow code is simplified. All reaction arrows are rendered - * using Temml extensible arrows instead of building non-extensible arrows. - * 4. The ~bond forms are composed entirely of \rule elements. - * 5. Two dashes in _getBond are wrapped in braces to suppress spacing. i.e., {-} - * 6. The electron dot uses \textbullet instead of \bullet. - * - * This code, as other Temml code, is released under the MIT license. - * - * /************************************************************* - * - * MathJax/extensions/TeX/mhchem.js - * - * Implements the \ce command for handling chemical formulas - * from the mhchem LaTeX package. - * - * --------------------------------------------------------------------- - * - * Copyright (c) 2011-2015 The MathJax Consortium - * Copyright (c) 2015-2018 Martin Hensel - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Coding Style -// - use '' for identifiers that can by minified/uglified -// - use "" for strings that need to stay untouched - -// version: "3.3.0" for MathJax and Temml - - -// Add \ce, \pu, and \tripleDash to the Temml macros. - -defineMacro("\\ce", function(context) { - return chemParse(context.consumeArgs(1)[0], "ce") -}); - -defineMacro("\\pu", function(context) { - return chemParse(context.consumeArgs(1)[0], "pu"); -}); - -// Math fonts do not include glyphs for the ~ form of bonds. So we'll send path geometry -// So we'll compose characters built from \rule elements. -defineMacro("\\uniDash", `{\\rule{0.672em}{0.06em}}`) -defineMacro("\\triDash", `{\\rule{0.15em}{0.06em}\\kern2mu\\rule{0.15em}{0.06em}\\kern2mu\\rule{0.15em}{0.06em}}`) -defineMacro("\\tripleDash", `\\kern0.075em\\raise0.25em{\\triDash}\\kern0.075em`) -defineMacro("\\tripleDashOverLine", `\\kern0.075em\\mathrlap{\\raise0.125em{\\uniDash}}\\raise0.34em{\\triDash}\\kern0.075em`) -defineMacro("\\tripleDashOverDoubleLine", `\\kern0.075em\\mathrlap{\\mathrlap{\\raise0.48em{\\triDash}}\\raise0.27em{\\uniDash}}{\\raise0.05em{\\uniDash}}\\kern0.075em`) -defineMacro("\\tripleDashBetweenDoubleLine", `\\kern0.075em\\mathrlap{\\mathrlap{\\raise0.48em{\\uniDash}}\\raise0.27em{\\triDash}}{\\raise0.05em{\\uniDash}}\\kern0.075em`) - - // - // This is the main function for handing the \ce and \pu commands. - // It takes the argument to \ce or \pu and returns the corresponding TeX string. - // - - var chemParse = function (tokens, stateMachine) { - // Recreate the argument string from Temml's array of tokens. - var str = ""; - var expectedLoc = tokens.length && tokens[tokens.length - 1].loc.start - for (var i = tokens.length - 1; i >= 0; i--) { - if(tokens[i].loc.start > expectedLoc) { - // context.consumeArgs has eaten a space. - str += " "; - expectedLoc = tokens[i].loc.start; - } - str += tokens[i].text; - expectedLoc += tokens[i].text.length; - } - // Call the mhchem core parser. - var tex = texify.go(mhchemParser.go(str, stateMachine)); - return tex; - }; - - // - // Core parser for mhchem syntax (recursive) - // - /** @type {MhchemParser} */ - var mhchemParser = { - // - // Parses mchem \ce syntax - // - // Call like - // go("H2O"); - // - go: function (input, stateMachine) { - if (!input) { return []; } - if (stateMachine === undefined) { stateMachine = 'ce'; } - var state = '0'; - - // - // String buffers for parsing: - // - // buffer.a == amount - // buffer.o == element - // buffer.b == left-side superscript - // buffer.p == left-side subscript - // buffer.q == right-side subscript - // buffer.d == right-side superscript - // - // buffer.r == arrow - // buffer.rdt == arrow, script above, type - // buffer.rd == arrow, script above, content - // buffer.rqt == arrow, script below, type - // buffer.rq == arrow, script below, content - // - // buffer.text_ - // buffer.rm - // etc. - // - // buffer.parenthesisLevel == int, starting at 0 - // buffer.sb == bool, space before - // buffer.beginsWithBond == bool - // - // These letters are also used as state names. - // - // Other states: - // 0 == begin of main part (arrow/operator unlikely) - // 1 == next entity - // 2 == next entity (arrow/operator unlikely) - // 3 == next atom - // c == macro - // - /** @type {Buffer} */ - var buffer = {}; - buffer['parenthesisLevel'] = 0; - - input = input.replace(/\n/g, " "); - input = input.replace(/[\u2212\u2013\u2014\u2010]/g, "-"); - input = input.replace(/[\u2026]/g, "..."); - - // - // Looks through mhchemParser.transitions, to execute a matching action - // (recursive) - // - var lastInput; - var watchdog = 10; - /** @type {ParserOutput[]} */ - var output = []; - while (true) { - if (lastInput !== input) { - watchdog = 10; - lastInput = input; - } else { - watchdog--; - } - // - // Find actions in transition table - // - var machine = mhchemParser.stateMachines[stateMachine]; - var t = machine.transitions[state] || machine.transitions['*']; - iterateTransitions: - for (var i=0; i 0) { - if (!task.revisit) { - input = matches.remainder; - } - if (!task.toContinue) { - break iterateTransitions; - } - } else { - return output; - } - } - } - // - // Prevent infinite loop - // - if (watchdog <= 0) { - throw ["MhchemBugU", "mhchem bug U. Please report."]; // Unexpected character - } - } - }, - concatArray: function (a, b) { - if (b) { - if (Array.isArray(b)) { - for (var iB=0; iB': /^[=<>]/, - '#': /^[#\u2261]/, - '+': /^\+/, - '-$': /^-(?=[\s_},;\]/]|$|\([a-z]+\))/, // -space -, -; -] -/ -$ -state-of-aggregation - '-9': /^-(?=[0-9])/, - '- orbital overlap': /^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/, - '-': /^-/, - 'pm-operator': /^(?:\\pm|\$\\pm\$|\+-|\+\/-)/, - 'operator': /^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/, - 'arrowUpDown': /^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/, - '\\bond{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\bond{", "", "", "}"); }, - '->': /^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/, - 'CMT': /^[CMT](?=\[)/, - '[(...)]': function (input) { return mhchemParser.patterns.findObserveGroups(input, "[", "", "", "]"); }, - '1st-level escape': /^(&|\\\\|\\hline)\s*/, - '\\,': /^(?:\\[,\ ;:])/, // \\x - but output no space before - '\\x{}{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); }, - '\\x{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", ""); }, - '\\ca': /^\\ca(?:\s+|(?![a-zA-Z]))/, - '\\x': /^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/, - 'orbital': /^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/, // only those with numbers in front, because the others will be formatted correctly anyway - 'others': /^[\/~|]/, - '\\frac{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\frac{", "", "", "}", "{", "", "", "}"); }, - '\\overset{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\overset{", "", "", "}", "{", "", "", "}"); }, - '\\underset{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\underset{", "", "", "}", "{", "", "", "}"); }, - '\\underbrace{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\underbrace{", "", "", "}_", "{", "", "", "}"); }, - '\\color{(...)}0': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}"); }, - '\\color{(...)}{(...)}1': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}", "{", "", "", "}"); }, - '\\color(...){(...)}2': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color", "\\", "", /^(?=\{)/, "{", "", "", "}"); }, - '\\ce{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\ce{", "", "", "}"); }, - 'oxidation$': /^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, - 'd-oxidation$': /^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, // 0 could be oxidation or charge - 'roman numeral': /^[IVX]+/, - '1/2$': /^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/, - 'amount': function (input) { - var match; - // e.g. 2, 0.5, 1/2, -2, n/2, +; $a$ could be added later in parsing - match = input.match(/^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/); - if (match) { - return { match_: match[0], remainder: input.substr(match[0].length) }; - } - var a = mhchemParser.patterns.findObserveGroups(input, "", "$", "$", ""); - if (a) { // e.g. $2n-1$, $-$ - match = a.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/); - if (match) { - return { match_: match[0], remainder: input.substr(match[0].length) }; - } - } - return null; - }, - 'amount2': function (input) { return this['amount'](input); }, - '(KV letters),': /^(?:[A-Z][a-z]{0,2}|i)(?=,)/, - 'formula$': function (input) { - if (input.match(/^\([a-z]+\)$/)) { return null; } // state of aggregation = no formula - var match = input.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/); - if (match) { - return { match_: match[0], remainder: input.substr(match[0].length) }; - } - return null; - }, - 'uprightEntities': /^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/, - '/': /^\s*(\/)\s*/, - '//': /^\s*(\/\/)\s*/, - '*': /^\s*[*.]\s*/ - }, - findObserveGroups: function (input, begExcl, begIncl, endIncl, endExcl, beg2Excl, beg2Incl, end2Incl, end2Excl, combine) { - /** @type {{(input: string, pattern: string | RegExp): string | string[] | null;}} */ - var _match = function (input, pattern) { - if (typeof pattern === "string") { - if (input.indexOf(pattern) !== 0) { return null; } - return pattern; - } else { - var match = input.match(pattern); - if (!match) { return null; } - return match[0]; - } - }; - /** @type {{(input: string, i: number, endChars: string | RegExp): {endMatchBegin: number, endMatchEnd: number} | null;}} */ - var _findObserveGroups = function (input, i, endChars) { - var braces = 0; - while (i < input.length) { - var a = input.charAt(i); - var match = _match(input.substr(i), endChars); - if (match !== null && braces === 0) { - return { endMatchBegin: i, endMatchEnd: i + match.length }; - } else if (a === "{") { - braces++; - } else if (a === "}") { - if (braces === 0) { - throw ["ExtraCloseMissingOpen", "Extra close brace or missing open brace"]; - } else { - braces--; - } - } - i++; - } - if (braces > 0) { - return null; - } - return null; - }; - var match = _match(input, begExcl); - if (match === null) { return null; } - input = input.substr(match.length); - match = _match(input, begIncl); - if (match === null) { return null; } - var e = _findObserveGroups(input, match.length, endIncl || endExcl); - if (e === null) { return null; } - var match1 = input.substring(0, (endIncl ? e.endMatchEnd : e.endMatchBegin)); - if (!(beg2Excl || beg2Incl)) { - return { - match_: match1, - remainder: input.substr(e.endMatchEnd) - }; - } else { - var group2 = this.findObserveGroups(input.substr(e.endMatchEnd), beg2Excl, beg2Incl, end2Incl, end2Excl); - if (group2 === null) { return null; } - /** @type {string[]} */ - var matchRet = [match1, group2.match_]; - return { - match_: (combine ? matchRet.join("") : matchRet), - remainder: group2.remainder - }; - } - }, - - // - // Matching function - // e.g. match("a", input) will look for the regexp called "a" and see if it matches - // returns null or {match_:"a", remainder:"bc"} - // - match_: function (m, input) { - var pattern = mhchemParser.patterns.patterns[m]; - if (pattern === undefined) { - throw ["MhchemBugP", "mhchem bug P. Please report. (" + m + ")"]; // Trying to use non-existing pattern - } else if (typeof pattern === "function") { - return mhchemParser.patterns.patterns[m](input); // cannot use cached var pattern here, because some pattern functions need this===mhchemParser - } else { // RegExp - var match = input.match(pattern); - if (match) { - var mm; - if (match[2]) { - mm = [ match[1], match[2] ]; - } else if (match[1]) { - mm = match[1]; - } else { - mm = match[0]; - } - return { match_: mm, remainder: input.substr(match[0].length) }; - } - return null; - } - } - }, - - // - // Generic state machine actions - // - actions: { - 'a=': function (buffer, m) { buffer.a = (buffer.a || "") + m; }, - 'b=': function (buffer, m) { buffer.b = (buffer.b || "") + m; }, - 'p=': function (buffer, m) { buffer.p = (buffer.p || "") + m; }, - 'o=': function (buffer, m) { buffer.o = (buffer.o || "") + m; }, - 'q=': function (buffer, m) { buffer.q = (buffer.q || "") + m; }, - 'd=': function (buffer, m) { buffer.d = (buffer.d || "") + m; }, - 'rm=': function (buffer, m) { buffer.rm = (buffer.rm || "") + m; }, - 'text=': function (buffer, m) { buffer.text_ = (buffer.text_ || "") + m; }, - 'insert': function (buffer, m, a) { return { type_: a }; }, - 'insert+p1': function (buffer, m, a) { return { type_: a, p1: m }; }, - 'insert+p1+p2': function (buffer, m, a) { return { type_: a, p1: m[0], p2: m[1] }; }, - 'copy': function (buffer, m) { return m; }, - 'rm': function (buffer, m) { return { type_: 'rm', p1: m || ""}; }, - 'text': function (buffer, m) { return mhchemParser.go(m, 'text'); }, - '{text}': function (buffer, m) { - var ret = [ "{" ]; - mhchemParser.concatArray(ret, mhchemParser.go(m, 'text')); - ret.push("}"); - return ret; - }, - 'tex-math': function (buffer, m) { return mhchemParser.go(m, 'tex-math'); }, - 'tex-math tight': function (buffer, m) { return mhchemParser.go(m, 'tex-math tight'); }, - 'bond': function (buffer, m, k) { return { type_: 'bond', kind_: k || m }; }, - 'color0-output': function (buffer, m) { return { type_: 'color0', color: m[0] }; }, - 'ce': function (buffer, m) { return mhchemParser.go(m); }, - '1/2': function (buffer, m) { - /** @type {ParserOutput[]} */ - var ret = []; - if (m.match(/^[+\-]/)) { - ret.push(m.substr(0, 1)); - m = m.substr(1); - } - var n = m.match(/^([0-9]+|\$[a-z]\$|[a-z])\/([0-9]+)(\$[a-z]\$|[a-z])?$/); - n[1] = n[1].replace(/\$/g, ""); - ret.push({ type_: 'frac', p1: n[1], p2: n[2] }); - if (n[3]) { - n[3] = n[3].replace(/\$/g, ""); - ret.push({ type_: 'tex-math', p1: n[3] }); - } - return ret; - }, - '9,9': function (buffer, m) { return mhchemParser.go(m, '9,9'); } - }, - // - // createTransitions - // convert { 'letter': { 'state': { action_: 'output' } } } to { 'state' => [ { pattern: 'letter', task: { action_: [{type_: 'output'}] } } ] } - // with expansion of 'a|b' to 'a' and 'b' (at 2 places) - // - createTransitions: function (o) { - var pattern, state; - /** @type {string[]} */ - var stateArray; - var i; - // - // 1. Collect all states - // - /** @type {Transitions} */ - var transitions = {}; - for (pattern in o) { - for (state in o[pattern]) { - stateArray = state.split("|"); - o[pattern][state].stateArray = stateArray; - for (i=0; i': { - '0|1|2|3': { action_: 'r=', nextState: 'r' }, - 'a|as': { action_: [ 'output', 'r=' ], nextState: 'r' }, - '*': { action_: [ 'output', 'r=' ], nextState: 'r' } }, - '+': { - 'o': { action_: 'd= kv', nextState: 'd' }, - 'd|D': { action_: 'd=', nextState: 'd' }, - 'q': { action_: 'd=', nextState: 'qd' }, - 'qd|qD': { action_: 'd=', nextState: 'qd' }, - 'dq': { action_: [ 'output', 'd=' ], nextState: 'd' }, - '3': { action_: [ 'sb=false', 'output', 'operator' ], nextState: '0' } }, - 'amount': { - '0|2': { action_: 'a=', nextState: 'a' } }, - 'pm-operator': { - '0|1|2|a|as': { action_: [ 'sb=false', 'output', { type_: 'operator', option: '\\pm' } ], nextState: '0' } }, - 'operator': { - '0|1|2|a|as': { action_: [ 'sb=false', 'output', 'operator' ], nextState: '0' } }, - '-$': { - 'o|q': { action_: [ 'charge or bond', 'output' ], nextState: 'qd' }, - 'd': { action_: 'd=', nextState: 'd' }, - 'D': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' }, - 'q': { action_: 'd=', nextState: 'qd' }, - 'qd': { action_: 'd=', nextState: 'qd' }, - 'qD|dq': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' } }, - '-9': { - '3|o': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '3' } }, - '- orbital overlap': { - 'o': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' }, - 'd': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' } }, - '-': { - '0|1|2': { action_: [ { type_: 'output', option: 1 }, 'beginsWithBond=true', { type_: 'bond', option: "-" } ], nextState: '3' }, - '3': { action_: { type_: 'bond', option: "-" } }, - 'a': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' }, - 'as': { action_: [ { type_: 'output', option: 2 }, { type_: 'bond', option: "-" } ], nextState: '3' }, - 'b': { action_: 'b=' }, - 'o': { action_: { type_: '- after o/d', option: false }, nextState: '2' }, - 'q': { action_: { type_: '- after o/d', option: false }, nextState: '2' }, - 'd|qd|dq': { action_: { type_: '- after o/d', option: true }, nextState: '2' }, - 'D|qD|p': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' } }, - 'amount2': { - '1|3': { action_: 'a=', nextState: 'a' } }, - 'letters': { - '0|1|2|3|a|as|b|p|bp|o': { action_: 'o=', nextState: 'o' }, - 'q|dq': { action_: ['output', 'o='], nextState: 'o' }, - 'd|D|qd|qD': { action_: 'o after d', nextState: 'o' } }, - 'digits': { - 'o': { action_: 'q=', nextState: 'q' }, - 'd|D': { action_: 'q=', nextState: 'dq' }, - 'q': { action_: [ 'output', 'o=' ], nextState: 'o' }, - 'a': { action_: 'o=', nextState: 'o' } }, - 'space A': { - 'b|p|bp': {} }, - 'space': { - 'a': { nextState: 'as' }, - '0': { action_: 'sb=false' }, - '1|2': { action_: 'sb=true' }, - 'r|rt|rd|rdt|rdq': { action_: 'output', nextState: '0' }, - '*': { action_: [ 'output', 'sb=true' ], nextState: '1'} }, - '1st-level escape': { - '1|2': { action_: [ 'output', { type_: 'insert+p1', option: '1st-level escape' } ] }, - '*': { action_: [ 'output', { type_: 'insert+p1', option: '1st-level escape' } ], nextState: '0' } }, - '[(...)]': { - 'r|rt': { action_: 'rd=', nextState: 'rd' }, - 'rd|rdt': { action_: 'rq=', nextState: 'rdq' } }, - '...': { - 'o|d|D|dq|qd|qD': { action_: [ 'output', { type_: 'bond', option: "..." } ], nextState: '3' }, - '*': { action_: [ { type_: 'output', option: 1 }, { type_: 'insert', option: 'ellipsis' } ], nextState: '1' } }, - '. |* ': { - '*': { action_: [ 'output', { type_: 'insert', option: 'addition compound' } ], nextState: '1' } }, - 'state of aggregation $': { - '*': { action_: [ 'output', 'state of aggregation' ], nextState: '1' } }, - '{[(': { - 'a|as|o': { action_: [ 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' }, - '0|1|2|3': { action_: [ 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' }, - '*': { action_: [ 'output', 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' } }, - ')]}': { - '0|1|2|3|b|p|bp|o': { action_: [ 'o=', 'parenthesisLevel--' ], nextState: 'o' }, - 'a|as|d|D|q|qd|qD|dq': { action_: [ 'output', 'o=', 'parenthesisLevel--' ], nextState: 'o' } }, - ', ': { - '*': { action_: [ 'output', 'comma' ], nextState: '0' } }, - '^_': { // ^ and _ without a sensible argument - '*': { } }, - '^{(...)}|^($...$)': { - '0|1|2|as': { action_: 'b=', nextState: 'b' }, - 'p': { action_: 'b=', nextState: 'bp' }, - '3|o': { action_: 'd= kv', nextState: 'D' }, - 'q': { action_: 'd=', nextState: 'qD' }, - 'd|D|qd|qD|dq': { action_: [ 'output', 'd=' ], nextState: 'D' } }, - '^a|^\\x{}{}|^\\x{}|^\\x|\'': { - '0|1|2|as': { action_: 'b=', nextState: 'b' }, - 'p': { action_: 'b=', nextState: 'bp' }, - '3|o': { action_: 'd= kv', nextState: 'd' }, - 'q': { action_: 'd=', nextState: 'qd' }, - 'd|qd|D|qD': { action_: 'd=' }, - 'dq': { action_: [ 'output', 'd=' ], nextState: 'd' } }, - '_{(state of aggregation)}$': { - 'd|D|q|qd|qD|dq': { action_: [ 'output', 'q=' ], nextState: 'q' } }, - '_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x': { - '0|1|2|as': { action_: 'p=', nextState: 'p' }, - 'b': { action_: 'p=', nextState: 'bp' }, - '3|o': { action_: 'q=', nextState: 'q' }, - 'd|D': { action_: 'q=', nextState: 'dq' }, - 'q|qd|qD|dq': { action_: [ 'output', 'q=' ], nextState: 'q' } }, - '=<>': { - '0|1|2|3|a|as|o|q|d|D|qd|qD|dq': { action_: [ { type_: 'output', option: 2 }, 'bond' ], nextState: '3' } }, - '#': { - '0|1|2|3|a|as|o': { action_: [ { type_: 'output', option: 2 }, { type_: 'bond', option: "#" } ], nextState: '3' } }, - '{}': { - '*': { action_: { type_: 'output', option: 1 }, nextState: '1' } }, - '{...}': { - '0|1|2|3|a|as|b|p|bp': { action_: 'o=', nextState: 'o' }, - 'o|d|D|q|qd|qD|dq': { action_: [ 'output', 'o=' ], nextState: 'o' } }, - '$...$': { - 'a': { action_: 'a=' }, // 2$n$ - '0|1|2|3|as|b|p|bp|o': { action_: 'o=', nextState: 'o' }, // not 'amount' - 'as|o': { action_: 'o=' }, - 'q|d|D|qd|qD|dq': { action_: [ 'output', 'o=' ], nextState: 'o' } }, - '\\bond{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'bond' ], nextState: "3" } }, - '\\frac{(...)}': { - '*': { action_: [ { type_: 'output', option: 1 }, 'frac-output' ], nextState: '3' } }, - '\\overset{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'overset-output' ], nextState: '3' } }, - '\\underset{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'underset-output' ], nextState: '3' } }, - '\\underbrace{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'underbrace-output' ], nextState: '3' } }, - '\\color{(...)}{(...)}1|\\color(...){(...)}2': { - '*': { action_: [ { type_: 'output', option: 2 }, 'color-output' ], nextState: '3' } }, - '\\color{(...)}0': { - '*': { action_: [ { type_: 'output', option: 2 }, 'color0-output' ] } }, - '\\ce{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'ce' ], nextState: '3' } }, - '\\,': { - '*': { action_: [ { type_: 'output', option: 1 }, 'copy' ], nextState: '1' } }, - '\\x{}{}|\\x{}|\\x': { - '0|1|2|3|a|as|b|p|bp|o|c0': { action_: [ 'o=', 'output' ], nextState: '3' }, - '*': { action_: ['output', 'o=', 'output' ], nextState: '3' } }, - 'others': { - '*': { action_: [ { type_: 'output', option: 1 }, 'copy' ], nextState: '3' } }, - 'else2': { - 'a': { action_: 'a to o', nextState: 'o', revisit: true }, - 'as': { action_: [ 'output', 'sb=true' ], nextState: '1', revisit: true }, - 'r|rt|rd|rdt|rdq': { action_: [ 'output' ], nextState: '0', revisit: true }, - '*': { action_: [ 'output', 'copy' ], nextState: '3' } } - }), - actions: { - 'o after d': function (buffer, m) { - var ret; - if ((buffer.d || "").match(/^[0-9]+$/)) { - var tmp = buffer.d; - buffer.d = undefined; - ret = this['output'](buffer); - buffer.b = tmp; - } else { - ret = this['output'](buffer); - } - mhchemParser.actions['o='](buffer, m); - return ret; - }, - 'd= kv': function (buffer, m) { - buffer.d = m; - buffer.dType = 'kv'; - }, - 'charge or bond': function (buffer, m) { - if (buffer['beginsWithBond']) { - /** @type {ParserOutput[]} */ - var ret = []; - mhchemParser.concatArray(ret, this['output'](buffer)); - mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-")); - return ret; - } else { - buffer.d = m; - } - }, - '- after o/d': function (buffer, m, isAfterD) { - var c1 = mhchemParser.patterns.match_('orbital', buffer.o || ""); - var c2 = mhchemParser.patterns.match_('one lowercase greek letter $', buffer.o || ""); - var c3 = mhchemParser.patterns.match_('one lowercase latin letter $', buffer.o || ""); - var c4 = mhchemParser.patterns.match_('$one lowercase latin letter$ $', buffer.o || ""); - var hyphenFollows = m==="-" && ( c1 && c1.remainder==="" || c2 || c3 || c4 ); - if (hyphenFollows && !buffer.a && !buffer.b && !buffer.p && !buffer.d && !buffer.q && !c1 && c3) { - buffer.o = '$' + buffer.o + '$'; - } - /** @type {ParserOutput[]} */ - var ret = []; - if (hyphenFollows) { - mhchemParser.concatArray(ret, this['output'](buffer)); - ret.push({ type_: 'hyphen' }); - } else { - c1 = mhchemParser.patterns.match_('digits', buffer.d || ""); - if (isAfterD && c1 && c1.remainder==='') { - mhchemParser.concatArray(ret, mhchemParser.actions['d='](buffer, m)); - mhchemParser.concatArray(ret, this['output'](buffer)); - } else { - mhchemParser.concatArray(ret, this['output'](buffer)); - mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-")); - } - } - return ret; - }, - 'a to o': function (buffer) { - buffer.o = buffer.a; - buffer.a = undefined; - }, - 'sb=true': function (buffer) { buffer.sb = true; }, - 'sb=false': function (buffer) { buffer.sb = false; }, - 'beginsWithBond=true': function (buffer) { buffer['beginsWithBond'] = true; }, - 'beginsWithBond=false': function (buffer) { buffer['beginsWithBond'] = false; }, - 'parenthesisLevel++': function (buffer) { buffer['parenthesisLevel']++; }, - 'parenthesisLevel--': function (buffer) { buffer['parenthesisLevel']--; }, - 'state of aggregation': function (buffer, m) { - return { type_: 'state of aggregation', p1: mhchemParser.go(m, 'o') }; - }, - 'comma': function (buffer, m) { - var a = m.replace(/\s*$/, ''); - var withSpace = (a !== m); - if (withSpace && buffer['parenthesisLevel'] === 0) { - return { type_: 'comma enumeration L', p1: a }; - } else { - return { type_: 'comma enumeration M', p1: a }; - } - }, - 'output': function (buffer, m, entityFollows) { - // entityFollows: - // undefined = if we have nothing else to output, also ignore the just read space (buffer.sb) - // 1 = an entity follows, never omit the space if there was one just read before (can only apply to state 1) - // 2 = 1 + the entity can have an amount, so output a\, instead of converting it to o (can only apply to states a|as) - /** @type {ParserOutput | ParserOutput[]} */ - var ret; - if (!buffer.r) { - ret = []; - if (!buffer.a && !buffer.b && !buffer.p && !buffer.o && !buffer.q && !buffer.d && !entityFollows) { - //ret = []; - } else { - if (buffer.sb) { - ret.push({ type_: 'entitySkip' }); - } - if (!buffer.o && !buffer.q && !buffer.d && !buffer.b && !buffer.p && entityFollows!==2) { - buffer.o = buffer.a; - buffer.a = undefined; - } else if (!buffer.o && !buffer.q && !buffer.d && (buffer.b || buffer.p)) { - buffer.o = buffer.a; - buffer.d = buffer.b; - buffer.q = buffer.p; - buffer.a = buffer.b = buffer.p = undefined; - } else { - if (buffer.o && buffer.dType==='kv' && mhchemParser.patterns.match_('d-oxidation$', buffer.d || "")) { - buffer.dType = 'oxidation'; - } else if (buffer.o && buffer.dType==='kv' && !buffer.q) { - buffer.dType = undefined; - } - } - ret.push({ - type_: 'chemfive', - a: mhchemParser.go(buffer.a, 'a'), - b: mhchemParser.go(buffer.b, 'bd'), - p: mhchemParser.go(buffer.p, 'pq'), - o: mhchemParser.go(buffer.o, 'o'), - q: mhchemParser.go(buffer.q, 'pq'), - d: mhchemParser.go(buffer.d, (buffer.dType === 'oxidation' ? 'oxidation' : 'bd')), - dType: buffer.dType - }); - } - } else { // r - /** @type {ParserOutput[]} */ - var rd; - if (buffer.rdt === 'M') { - rd = mhchemParser.go(buffer.rd, 'tex-math'); - } else if (buffer.rdt === 'T') { - rd = [ { type_: 'text', p1: buffer.rd || "" } ]; - } else { - rd = mhchemParser.go(buffer.rd); - } - /** @type {ParserOutput[]} */ - var rq; - if (buffer.rqt === 'M') { - rq = mhchemParser.go(buffer.rq, 'tex-math'); - } else if (buffer.rqt === 'T') { - rq = [ { type_: 'text', p1: buffer.rq || ""} ]; - } else { - rq = mhchemParser.go(buffer.rq); - } - ret = { - type_: 'arrow', - r: buffer.r, - rd: rd, - rq: rq - }; - } - for (var p in buffer) { - if (p !== 'parenthesisLevel' && p !== 'beginsWithBond') { - delete buffer[p]; - } - } - return ret; - }, - 'oxidation-output': function (buffer, m) { - var ret = [ "{" ]; - mhchemParser.concatArray(ret, mhchemParser.go(m, 'oxidation')); - ret.push("}"); - return ret; - }, - 'frac-output': function (buffer, m) { - return { type_: 'frac-ce', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'overset-output': function (buffer, m) { - return { type_: 'overset', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'underset-output': function (buffer, m) { - return { type_: 'underset', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'underbrace-output': function (buffer, m) { - return { type_: 'underbrace', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'color-output': function (buffer, m) { - return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1]) }; - }, - 'r=': function (buffer, m) { buffer.r = m; }, - 'rdt=': function (buffer, m) { buffer.rdt = m; }, - 'rd=': function (buffer, m) { buffer.rd = m; }, - 'rqt=': function (buffer, m) { buffer.rqt = m; }, - 'rq=': function (buffer, m) { buffer.rq = m; }, - 'operator': function (buffer, m, p1) { return { type_: 'operator', kind_: (p1 || m) }; } - } - }, - 'a': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - '1/2$': { - '0': { action_: '1/2' } }, - 'else': { - '0': { nextState: '1', revisit: true } }, - '$(...)$': { - '*': { action_: 'tex-math tight', nextState: '1' } }, - ',': { - '*': { action_: { type_: 'insert', option: 'commaDecimal' } } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: {} - }, - 'o': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - '1/2$': { - '0': { action_: '1/2' } }, - 'else': { - '0': { nextState: '1', revisit: true } }, - 'letters': { - '*': { action_: 'rm' } }, - '\\ca': { - '*': { action_: { type_: 'insert', option: 'circa' } } }, - '\\x{}{}|\\x{}|\\x': { - '*': { action_: 'copy' } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '{(...)}': { - '*': { action_: '{text}' } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: {} - }, - 'text': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '{...}': { - '*': { action_: 'text=' } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '\\greek': { - '*': { action_: [ 'output', 'rm' ] } }, - '\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: [ 'output', 'copy' ] } }, - 'else': { - '*': { action_: 'text=' } } - }), - actions: { - 'output': function (buffer) { - if (buffer.text_) { - /** @type {ParserOutput} */ - var ret = { type_: 'text', p1: buffer.text_ }; - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - } - }, - 'pq': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - 'state of aggregation $': { - '*': { action_: 'state of aggregation' } }, - 'i$': { - '0': { nextState: '!f', revisit: true } }, - '(KV letters),': { - '0': { action_: 'rm', nextState: '0' } }, - 'formula$': { - '0': { nextState: 'f', revisit: true } }, - '1/2$': { - '0': { action_: '1/2' } }, - 'else': { - '0': { nextState: '!f', revisit: true } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '{(...)}': { - '*': { action_: 'text' } }, - 'a-z': { - 'f': { action_: 'tex-math' } }, - 'letters': { - '*': { action_: 'rm' } }, - '-9.,9': { - '*': { action_: '9,9' } }, - ',': { - '*': { action_: { type_: 'insert+p1', option: 'comma enumeration S' } } }, - '\\color{(...)}{(...)}1|\\color(...){(...)}2': { - '*': { action_: 'color-output' } }, - '\\color{(...)}0': { - '*': { action_: 'color0-output' } }, - '\\ce{(...)}': { - '*': { action_: 'ce' } }, - '\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'copy' } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: { - 'state of aggregation': function (buffer, m) { - return { type_: 'state of aggregation subscript', p1: mhchemParser.go(m, 'o') }; - }, - 'color-output': function (buffer, m) { - return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1], 'pq') }; - } - } - }, - 'bd': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - 'x$': { - '0': { nextState: '!f', revisit: true } }, - 'formula$': { - '0': { nextState: 'f', revisit: true } }, - 'else': { - '0': { nextState: '!f', revisit: true } }, - '-9.,9 no missing 0': { - '*': { action_: '9,9' } }, - '.': { - '*': { action_: { type_: 'insert', option: 'electron dot' } } }, - 'a-z': { - 'f': { action_: 'tex-math' } }, - 'x': { - '*': { action_: { type_: 'insert', option: 'KV x' } } }, - 'letters': { - '*': { action_: 'rm' } }, - '\'': { - '*': { action_: { type_: 'insert', option: 'prime' } } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '{(...)}': { - '*': { action_: 'text' } }, - '\\color{(...)}{(...)}1|\\color(...){(...)}2': { - '*': { action_: 'color-output' } }, - '\\color{(...)}0': { - '*': { action_: 'color0-output' } }, - '\\ce{(...)}': { - '*': { action_: 'ce' } }, - '\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'copy' } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: { - 'color-output': function (buffer, m) { - return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1], 'bd') }; - } - } - }, - 'oxidation': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - 'roman numeral': { - '*': { action_: 'roman-numeral' } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - 'else': { - '*': { action_: 'copy' } } - }), - actions: { - 'roman-numeral': function (buffer, m) { return { type_: 'roman numeral', p1: m || "" }; } - } - }, - 'tex-math': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '\\ce{(...)}': { - '*': { action_: [ 'output', 'ce' ] } }, - '{...}|\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'o=' } }, - 'else': { - '*': { action_: 'o=' } } - }), - actions: { - 'output': function (buffer) { - if (buffer.o) { - /** @type {ParserOutput} */ - var ret = { type_: 'tex-math', p1: buffer.o }; - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - } - }, - 'tex-math tight': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '\\ce{(...)}': { - '*': { action_: [ 'output', 'ce' ] } }, - '{...}|\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'o=' } }, - '-|+': { - '*': { action_: 'tight operator' } }, - 'else': { - '*': { action_: 'o=' } } - }), - actions: { - 'tight operator': function (buffer, m) { buffer.o = (buffer.o || "") + "{"+m+"}"; }, - 'output': function (buffer) { - if (buffer.o) { - /** @type {ParserOutput} */ - var ret = { type_: 'tex-math', p1: buffer.o }; - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - } - }, - '9,9': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - ',': { - '*': { action_: 'comma' } }, - 'else': { - '*': { action_: 'copy' } } - }), - actions: { - 'comma': function () { return { type_: 'commaDecimal' }; } - } - }, - //#endregion - // - // \pu state machines - // - //#region pu - 'pu': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - 'space$': { - '*': { action_: [ 'output', 'space' ] } }, - '{[(|)]}': { - '0|a': { action_: 'copy' } }, - '(-)(9)^(-9)': { - '0': { action_: 'number^', nextState: 'a' } }, - '(-)(9.,9)(e)(99)': { - '0': { action_: 'enumber', nextState: 'a' } }, - 'space': { - '0|a': {} }, - 'pm-operator': { - '0|a': { action_: { type_: 'operator', option: '\\pm' }, nextState: '0' } }, - 'operator': { - '0|a': { action_: 'copy', nextState: '0' } }, - '//': { - 'd': { action_: 'o=', nextState: '/' } }, - '/': { - 'd': { action_: 'o=', nextState: '/' } }, - '{...}|else': { - '0|d': { action_: 'd=', nextState: 'd' }, - 'a': { action_: [ 'space', 'd=' ], nextState: 'd' }, - '/|q': { action_: 'q=', nextState: 'q' } } - }), - actions: { - 'enumber': function (buffer, m) { - /** @type {ParserOutput[]} */ - var ret = []; - if (m[0] === "+-" || m[0] === "+/-") { - ret.push("\\pm "); - } else if (m[0]) { - ret.push(m[0]); - } - if (m[1]) { - mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9')); - if (m[2]) { - if (m[2].match(/[,.]/)) { - mhchemParser.concatArray(ret, mhchemParser.go(m[2], 'pu-9,9')); - } else { - ret.push(m[2]); - } - } - m[3] = m[4] || m[3]; - if (m[3]) { - m[3] = m[3].trim(); - if (m[3] === "e" || m[3].substr(0, 1) === "*") { - ret.push({ type_: 'cdot' }); - } else { - ret.push({ type_: 'times' }); - } - } - } - if (m[3]) { - ret.push("10^{"+m[5]+"}"); - } - return ret; - }, - 'number^': function (buffer, m) { - /** @type {ParserOutput[]} */ - var ret = []; - if (m[0] === "+-" || m[0] === "+/-") { - ret.push("\\pm "); - } else if (m[0]) { - ret.push(m[0]); - } - mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9')); - ret.push("^{"+m[2]+"}"); - return ret; - }, - 'operator': function (buffer, m, p1) { return { type_: 'operator', kind_: (p1 || m) }; }, - 'space': function () { return { type_: 'pu-space-1' }; }, - 'output': function (buffer) { - /** @type {ParserOutput | ParserOutput[]} */ - var ret; - var md = mhchemParser.patterns.match_('{(...)}', buffer.d || ""); - if (md && md.remainder === '') { buffer.d = md.match_; } - var mq = mhchemParser.patterns.match_('{(...)}', buffer.q || ""); - if (mq && mq.remainder === '') { buffer.q = mq.match_; } - if (buffer.d) { - buffer.d = buffer.d.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C"); - buffer.d = buffer.d.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F"); - } - if (buffer.q) { // fraction - buffer.q = buffer.q.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C"); - buffer.q = buffer.q.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F"); - var b5 = { - d: mhchemParser.go(buffer.d, 'pu'), - q: mhchemParser.go(buffer.q, 'pu') - }; - if (buffer.o === '//') { - ret = { type_: 'pu-frac', p1: b5.d, p2: b5.q }; - } else { - ret = b5.d; - if (b5.d.length > 1 || b5.q.length > 1) { - ret.push({ type_: ' / ' }); - } else { - ret.push({ type_: '/' }); - } - mhchemParser.concatArray(ret, b5.q); - } - } else { // no fraction - ret = mhchemParser.go(buffer.d, 'pu-2'); - } - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - }, - 'pu-2': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '*': { - '*': { action_: [ 'output', 'cdot' ], nextState: '0' } }, - '\\x': { - '*': { action_: 'rm=' } }, - 'space': { - '*': { action_: [ 'output', 'space' ], nextState: '0' } }, - '^{(...)}|^(-1)': { - '1': { action_: '^(-1)' } }, - '-9.,9': { - '0': { action_: 'rm=', nextState: '0' }, - '1': { action_: '^(-1)', nextState: '0' } }, - '{...}|else': { - '*': { action_: 'rm=', nextState: '1' } } - }), - actions: { - 'cdot': function () { return { type_: 'tight cdot' }; }, - '^(-1)': function (buffer, m) { buffer.rm += "^{"+m+"}"; }, - 'space': function () { return { type_: 'pu-space-2' }; }, - 'output': function (buffer) { - /** @type {ParserOutput | ParserOutput[]} */ - var ret = []; - if (buffer.rm) { - var mrm = mhchemParser.patterns.match_('{(...)}', buffer.rm || ""); - if (mrm && mrm.remainder === '') { - ret = mhchemParser.go(mrm.match_, 'pu'); - } else { - ret = { type_: 'rm', p1: buffer.rm }; - } - } - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - }, - 'pu-9,9': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '0': { action_: 'output-0' }, - 'o': { action_: 'output-o' } }, - ',': { - '0': { action_: [ 'output-0', 'comma' ], nextState: 'o' } }, - '.': { - '0': { action_: [ 'output-0', 'copy' ], nextState: 'o' } }, - 'else': { - '*': { action_: 'text=' } } - }), - actions: { - 'comma': function () { return { type_: 'commaDecimal' }; }, - 'output-0': function (buffer) { - /** @type {ParserOutput[]} */ - var ret = []; - buffer.text_ = buffer.text_ || ""; - if (buffer.text_.length > 4) { - var a = buffer.text_.length % 3; - if (a === 0) { a = 3; } - for (var i=buffer.text_.length-3; i>0; i-=3) { - ret.push(buffer.text_.substr(i, 3)); - ret.push({ type_: '1000 separator' }); - } - ret.push(buffer.text_.substr(0, a)); - ret.reverse(); - } else { - ret.push(buffer.text_); - } - for (var p in buffer) { delete buffer[p]; } - return ret; - }, - 'output-o': function (buffer) { - /** @type {ParserOutput[]} */ - var ret = []; - buffer.text_ = buffer.text_ || ""; - if (buffer.text_.length > 4) { - var a = buffer.text_.length - 3; - for (var i=0; i, so we change \vphantom{X} to {} - // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed. -// res += "{\\vphantom{X}}"; - res += "{{}}"; - res += "_{\\smash[t]{"+b5.q+"}}"; - } - } else { - if (b5.q) { - // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed. -// res += "{\\vphantom{X}}"; - res += "{{}}"; - res += "_{\\smash[t]{"+b5.q+"}}"; - } - if (b5.d) { - // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed. -// res += "{\\vphantom{X}}"; - res += "{{}}"; - res += "^{"+b5.d+"}"; - } - } - break; - case 'rm': - res = "\\mathrm{"+buf.p1+"}"; - break; - case 'text': - if (buf.p1.match(/[\^_]/)) { - buf.p1 = buf.p1.replace(" ", "~").replace("-", "\\text{-}"); - res = "\\mathrm{"+buf.p1+"}"; - } else { - res = "\\text{"+buf.p1+"}"; - } - break; - case 'roman numeral': - res = "\\mathrm{"+buf.p1+"}"; - break; - case 'state of aggregation': - res = "\\mskip2mu "+texify._goInner(buf.p1); - break; - case 'state of aggregation subscript': - res = "\\mskip1mu "+texify._goInner(buf.p1); - break; - case 'bond': - res = texify._getBond(buf.kind_); - if (!res) { - throw ["MhchemErrorBond", "mhchem Error. Unknown bond type (" + buf.kind_ + ")"]; - } - break; - case 'frac': - var c = "\\frac{" + buf.p1 + "}{" + buf.p2 + "}"; - res = "\\mathchoice{\\textstyle"+c+"}{"+c+"}{"+c+"}{"+c+"}"; - break; - case 'pu-frac': - var d = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - res = "\\mathchoice{\\textstyle"+d+"}{"+d+"}{"+d+"}{"+d+"}"; - break; - case 'tex-math': - res = buf.p1 + " "; - break; - case 'frac-ce': - res = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - break; - case 'overset': - res = "\\overset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - break; - case 'underset': - res = "\\underset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - break; - case 'underbrace': - res = "\\underbrace{" + texify._goInner(buf.p1) + "}_{" + texify._goInner(buf.p2) + "}"; - break; - case 'color': - res = "{\\color{" + buf.color1 + "}{" + texify._goInner(buf.color2) + "}}"; - break; - case 'color0': - res = "\\color{" + buf.color + "}"; - break; - case 'arrow': - var b6 = { - rd: texify._goInner(buf.rd), - rq: texify._goInner(buf.rq) - }; - var arrow = texify._getArrow(buf.r); - if (b6.rq) { arrow += "[{\\rm " + b6.rq + "}]"; } - if (b6.rd) { - arrow += "{\\rm " + b6.rd + "}"; - } else { - arrow += "{}"; - } - res = arrow; - break; - case 'operator': - res = texify._getOperator(buf.kind_); - break; - case '1st-level escape': - res = buf.p1+" "; // &, \\\\, \\hlin - break; - case 'space': - res = " "; - break; - case 'entitySkip': - res = "~"; - break; - case 'pu-space-1': - res = "~"; - break; - case 'pu-space-2': - res = "\\mkern3mu "; - break; - case '1000 separator': - res = "\\mkern2mu "; - break; - case 'commaDecimal': - res = "{,}"; - break; - case 'comma enumeration L': - res = "{"+buf.p1+"}\\mkern6mu "; - break; - case 'comma enumeration M': - res = "{"+buf.p1+"}\\mkern3mu "; - break; - case 'comma enumeration S': - res = "{"+buf.p1+"}\\mkern1mu "; - break; - case 'hyphen': - res = "\\text{-}"; - break; - case 'addition compound': - res = "\\,{\\cdot}\\,"; - break; - case 'electron dot': - res = "\\mkern1mu \\text{\\textbullet}\\mkern1mu "; - break; - case 'KV x': - res = "{\\times}"; - break; - case 'prime': - res = "\\prime "; - break; - case 'cdot': - res = "\\cdot "; - break; - case 'tight cdot': - res = "\\mkern1mu{\\cdot}\\mkern1mu "; - break; - case 'times': - res = "\\times "; - break; - case 'circa': - res = "{\\sim}"; - break; - case '^': - res = "uparrow"; - break; - case 'v': - res = "downarrow"; - break; - case 'ellipsis': - res = "\\ldots "; - break; - case '/': - res = "/"; - break; - case ' / ': - res = "\\,/\\,"; - break; - default: - assertNever(buf); - throw ["MhchemBugT", "mhchem bug T. Please report."]; // Missing texify rule or unknown MhchemParser output - } - assertString(res); - return res; - }, - _getArrow: function (a) { - switch (a) { - case "->": return "\\yields"; - case "\u2192": return "\\yields"; - case "\u27F6": return "\\yields"; - case "<-": return "\\yieldsLeft"; - case "<->": return "\\mesomerism"; - case "<-->": return "\\yieldsLeftRight"; - case "<=>": return "\\equilibrium"; - case "\u21CC": return "\\equilibrium"; - case "<=>>": return "\\equilibriumRight"; - case "<<=>": return "\\equilibriumLeft"; - default: - assertNever(a); - throw ["MhchemBugT", "mhchem bug T. Please report."]; - } - }, - _getBond: function (a) { - switch (a) { - case "-": return "{-}"; - case "1": return "{-}"; - case "=": return "{=}"; - case "2": return "{=}"; - case "#": return "{\\equiv}"; - case "3": return "{\\equiv}"; - case "~": return "{\\tripleDash}"; - case "~-": return "{\\tripleDashOverLine}"; - case "~=": return "{\\tripleDashOverDoubleLine}"; - case "~--": return "{\\tripleDashOverDoubleLine}"; - case "-~-": return "{\\tripleDashBetweenDoubleLine}"; - case "...": return "{{\\cdot}{\\cdot}{\\cdot}}"; - case "....": return "{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}"; - case "->": return "{\\rightarrow}"; - case "<-": return "{\\leftarrow}"; - case "<": return "{<}"; - case ">": return "{>}"; - default: - assertNever(a); - throw ["MhchemBugT", "mhchem bug T. Please report."]; - } - }, - _getOperator: function (a) { - switch (a) { - case "+": return " {}+{} "; - case "-": return " {}-{} "; - case "=": return " {}={} "; - case "<": return " {}<{} "; - case ">": return " {}>{} "; - case "<<": return " {}\\ll{} "; - case ">>": return " {}\\gg{} "; - case "\\pm": return " {}\\pm{} "; - case "\\approx": return " {}\\approx{} "; - case "$\\approx$": return " {}\\approx{} "; - case "v": return " \\downarrow{} "; - case "(v)": return " \\downarrow{} "; - case "^": return " \\uparrow{} "; - case "(^)": return " \\uparrow{} "; - default: - assertNever(a); - throw ["MhchemBugT", "mhchem bug T. Please report."]; - } - } - }; - - // - // Helpers for code anaylsis - // Will show type error at calling position - // - /** @param {number} a */ - function assertNever(a) {} - /** @param {string} a */ - function assertString(a) {} - -/* eslint-disable no-undef */ - -////////////////////////////////////////////////////////////////////// -// texvc.sty - -// The texvc package contains macros available in mediawiki pages. -// We omit the functions deprecated at -// https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax - -// We also omit texvc's \O, which conflicts with \text{\O} - -defineMacro("\\darr", "\\downarrow"); -defineMacro("\\dArr", "\\Downarrow"); -defineMacro("\\Darr", "\\Downarrow"); -defineMacro("\\lang", "\\langle"); -defineMacro("\\rang", "\\rangle"); -defineMacro("\\uarr", "\\uparrow"); -defineMacro("\\uArr", "\\Uparrow"); -defineMacro("\\Uarr", "\\Uparrow"); -defineMacro("\\N", "\\mathbb{N}"); -defineMacro("\\R", "\\mathbb{R}"); -defineMacro("\\Z", "\\mathbb{Z}"); -defineMacro("\\alef", "\\aleph"); -defineMacro("\\alefsym", "\\aleph"); -defineMacro("\\bull", "\\bullet"); -defineMacro("\\clubs", "\\clubsuit"); -defineMacro("\\cnums", "\\mathbb{C}"); -defineMacro("\\Complex", "\\mathbb{C}"); -defineMacro("\\Dagger", "\\ddagger"); -defineMacro("\\diamonds", "\\diamondsuit"); -defineMacro("\\empty", "\\emptyset"); -defineMacro("\\exist", "\\exists"); -defineMacro("\\harr", "\\leftrightarrow"); -defineMacro("\\hArr", "\\Leftrightarrow"); -defineMacro("\\Harr", "\\Leftrightarrow"); -defineMacro("\\hearts", "\\heartsuit"); -defineMacro("\\image", "\\Im"); -defineMacro("\\infin", "\\infty"); -defineMacro("\\isin", "\\in"); -defineMacro("\\larr", "\\leftarrow"); -defineMacro("\\lArr", "\\Leftarrow"); -defineMacro("\\Larr", "\\Leftarrow"); -defineMacro("\\lrarr", "\\leftrightarrow"); -defineMacro("\\lrArr", "\\Leftrightarrow"); -defineMacro("\\Lrarr", "\\Leftrightarrow"); -defineMacro("\\natnums", "\\mathbb{N}"); -defineMacro("\\plusmn", "\\pm"); -defineMacro("\\rarr", "\\rightarrow"); -defineMacro("\\rArr", "\\Rightarrow"); -defineMacro("\\Rarr", "\\Rightarrow"); -defineMacro("\\real", "\\Re"); -defineMacro("\\reals", "\\mathbb{R}"); -defineMacro("\\Reals", "\\mathbb{R}"); -defineMacro("\\sdot", "\\cdot"); -defineMacro("\\sect", "\\S"); -defineMacro("\\spades", "\\spadesuit"); -defineMacro("\\sub", "\\subset"); -defineMacro("\\sube", "\\subseteq"); -defineMacro("\\supe", "\\supseteq"); -defineMacro("\\thetasym", "\\vartheta"); -defineMacro("\\weierp", "\\wp"); - -/* eslint-disable no-undef */ - -/**************************************************** - * - * physics.js - * - * Implements the Physics Package for LaTeX input. - * - * --------------------------------------------------------------------- - * - * The original version of this file is licensed as follows: - * Copyright (c) 2015-2016 Kolen Cheung . - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * --------------------------------------------------------------------- - * - * This file has been revised from the original in the following ways: - * 1. The interface is changed so that it can be called from Temml, not MathJax. - * 2. \Re and \Im are not used, to avoid conflict with existing LaTeX letters. - * - * This revision of the file is released under the MIT license. - * https://mit-license.org/ - */ -defineMacro("\\quantity", "{\\left\\{ #1 \\right\\}}"); -defineMacro("\\qty", "{\\left\\{ #1 \\right\\}}"); -defineMacro("\\pqty", "{\\left( #1 \\right)}"); -defineMacro("\\bqty", "{\\left[ #1 \\right]}"); -defineMacro("\\vqty", "{\\left\\vert #1 \\right\\vert}"); -defineMacro("\\Bqty", "{\\left\\{ #1 \\right\\}}"); -defineMacro("\\absolutevalue", "{\\left\\vert #1 \\right\\vert}"); -defineMacro("\\abs", "{\\left\\vert #1 \\right\\vert}"); -defineMacro("\\norm", "{\\left\\Vert #1 \\right\\Vert}"); -defineMacro("\\evaluated", "{\\left.#1 \\right\\vert}"); -defineMacro("\\eval", "{\\left.#1 \\right\\vert}"); -defineMacro("\\order", "{\\mathcal{O} \\left( #1 \\right)}"); -defineMacro("\\commutator", "{\\left[ #1 , #2 \\right]}"); -defineMacro("\\comm", "{\\left[ #1 , #2 \\right]}"); -defineMacro("\\anticommutator", "{\\left\\{ #1 , #2 \\right\\}}"); -defineMacro("\\acomm", "{\\left\\{ #1 , #2 \\right\\}}"); -defineMacro("\\poissonbracket", "{\\left\\{ #1 , #2 \\right\\}}"); -defineMacro("\\pb", "{\\left\\{ #1 , #2 \\right\\}}"); -defineMacro("\\vectorbold", "{\\boldsymbol{ #1 }}"); -defineMacro("\\vb", "{\\boldsymbol{ #1 }}"); -defineMacro("\\vectorarrow", "{\\vec{\\boldsymbol{ #1 }}}"); -defineMacro("\\va", "{\\vec{\\boldsymbol{ #1 }}}"); -defineMacro("\\vectorunit", "{{\\boldsymbol{\\hat{ #1 }}}}"); -defineMacro("\\vu", "{{\\boldsymbol{\\hat{ #1 }}}}"); -defineMacro("\\dotproduct", "\\mathbin{\\boldsymbol\\cdot}"); -defineMacro("\\vdot", "{\\boldsymbol\\cdot}"); -defineMacro("\\crossproduct", "\\mathbin{\\boldsymbol\\times}"); -defineMacro("\\cross", "\\mathbin{\\boldsymbol\\times}"); -defineMacro("\\cp", "\\mathbin{\\boldsymbol\\times}"); -defineMacro("\\gradient", "{\\boldsymbol\\nabla}"); -defineMacro("\\grad", "{\\boldsymbol\\nabla}"); -defineMacro("\\divergence", "{\\grad\\vdot}"); -//defineMacro("\\div", "{\\grad\\vdot}"); Not included in Temml. Conflicts w/LaTeX \div -defineMacro("\\curl", "{\\grad\\cross}"); -defineMacro("\\laplacian", "\\nabla^2"); -defineMacro("\\tr", "{\\operatorname{tr}}"); -defineMacro("\\Tr", "{\\operatorname{Tr}}"); -defineMacro("\\rank", "{\\operatorname{rank}}"); -defineMacro("\\erf", "{\\operatorname{erf}}"); -defineMacro("\\Res", "{\\operatorname{Res}}"); -defineMacro("\\principalvalue", "{\\mathcal{P}}"); -defineMacro("\\pv", "{\\mathcal{P}}"); -defineMacro("\\PV", "{\\operatorname{P.V.}}"); -// Temml does not use the next two lines. They conflict with LaTeX letters. -//defineMacro("\\Re", "{\\operatorname{Re} \\left\\{ #1 \\right\\}}"); -//defineMacro("\\Im", "{\\operatorname{Im} \\left\\{ #1 \\right\\}}"); -defineMacro("\\qqtext", "{\\quad\\text{ #1 }\\quad}"); -defineMacro("\\qq", "{\\quad\\text{ #1 }\\quad}"); -defineMacro("\\qcomma", "{\\text{,}\\quad}"); -defineMacro("\\qc", "{\\text{,}\\quad}"); -defineMacro("\\qcc", "{\\quad\\text{c.c.}\\quad}"); -defineMacro("\\qif", "{\\quad\\text{if}\\quad}"); -defineMacro("\\qthen", "{\\quad\\text{then}\\quad}"); -defineMacro("\\qelse", "{\\quad\\text{else}\\quad}"); -defineMacro("\\qotherwise", "{\\quad\\text{otherwise}\\quad}"); -defineMacro("\\qunless", "{\\quad\\text{unless}\\quad}"); -defineMacro("\\qgiven", "{\\quad\\text{given}\\quad}"); -defineMacro("\\qusing", "{\\quad\\text{using}\\quad}"); -defineMacro("\\qassume", "{\\quad\\text{assume}\\quad}"); -defineMacro("\\qsince", "{\\quad\\text{since}\\quad}"); -defineMacro("\\qlet", "{\\quad\\text{let}\\quad}"); -defineMacro("\\qfor", "{\\quad\\text{for}\\quad}"); -defineMacro("\\qall", "{\\quad\\text{all}\\quad}"); -defineMacro("\\qeven", "{\\quad\\text{even}\\quad}"); -defineMacro("\\qodd", "{\\quad\\text{odd}\\quad}"); -defineMacro("\\qinteger", "{\\quad\\text{integer}\\quad}"); -defineMacro("\\qand", "{\\quad\\text{and}\\quad}"); -defineMacro("\\qor", "{\\quad\\text{or}\\quad}"); -defineMacro("\\qas", "{\\quad\\text{as}\\quad}"); -defineMacro("\\qin", "{\\quad\\text{in}\\quad}"); -defineMacro("\\differential", "{\\text{d}}"); -defineMacro("\\dd", "{\\text{d}}"); -defineMacro("\\derivative", "{\\frac{\\text{d}{ #1 }}{\\text{d}{ #2 }}}"); -defineMacro("\\dv", "{\\frac{\\text{d}{ #1 }}{\\text{d}{ #2 }}}"); -defineMacro("\\partialderivative", "{\\frac{\\partial{ #1 }}{\\partial{ #2 }}}"); -defineMacro("\\variation", "{\\delta}"); -defineMacro("\\var", "{\\delta}"); -defineMacro("\\functionalderivative", "{\\frac{\\delta{ #1 }}{\\delta{ #2 }}}"); -defineMacro("\\fdv", "{\\frac{\\delta{ #1 }}{\\delta{ #2 }}}"); -defineMacro("\\innerproduct", "{\\left\\langle {#1} \\mid { #2} \\right\\rangle}"); -defineMacro("\\outerproduct", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -defineMacro("\\dyad", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -defineMacro("\\ketbra", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -defineMacro("\\op", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -defineMacro("\\expectationvalue", "{\\left\\langle {#1 } \\right\\rangle}"); -defineMacro("\\expval", "{\\left\\langle {#1 } \\right\\rangle}"); -defineMacro("\\ev", "{\\left\\langle {#1 } \\right\\rangle}"); -defineMacro("\\matrixelement", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); -defineMacro("\\matrixel", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); -defineMacro("\\mel", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); - -/** - * This file contains the “gullet” where macros are expanded - * until only non-macro tokens remain. - */ - -// List of commands that act like macros but aren't defined as a macro, -// function, or symbol. Used in `isDefined`. -const implicitCommands = { - "^": true, // Parser.js - _: true, // Parser.js - "\\limits": true, // Parser.js - "\\nolimits": true // Parser.js -}; - -class MacroExpander { - constructor(input, settings, mode) { - this.settings = settings; - this.expansionCount = 0; - this.feed(input); - // Make new global namespace - this.macros = new Namespace(macros, settings.macros); - this.mode = mode; - this.stack = []; // contains tokens in REVERSE order - } - - /** - * Feed a new input string to the same MacroExpander - * (with existing macros etc.). - */ - feed(input) { - this.lexer = new Lexer(input, this.settings); - } - - /** - * Switches between "text" and "math" modes. - */ - switchMode(newMode) { - this.mode = newMode; - } - - /** - * Start a new group nesting within all namespaces. - */ - beginGroup() { - this.macros.beginGroup(); - } - - /** - * End current group nesting within all namespaces. - */ - endGroup() { - this.macros.endGroup(); - } - - /** - * Returns the topmost token on the stack, without expanding it. - * Similar in behavior to TeX's `\futurelet`. - */ - future() { - if (this.stack.length === 0) { - this.pushToken(this.lexer.lex()); - } - return this.stack[this.stack.length - 1] - } - - /** - * Remove and return the next unexpanded token. - */ - popToken() { - this.future(); // ensure non-empty stack - return this.stack.pop(); - } - - /** - * Add a given token to the token stack. In particular, this get be used - * to put back a token returned from one of the other methods. - */ - pushToken(token) { - this.stack.push(token); - } - - /** - * Append an array of tokens to the token stack. - */ - pushTokens(tokens) { - this.stack.push(...tokens); - } - - /** - * Find an macro argument without expanding tokens and append the array of - * tokens to the token stack. Uses Token as a container for the result. - */ - scanArgument(isOptional) { - let start; - let end; - let tokens; - if (isOptional) { - this.consumeSpaces(); // \@ifnextchar gobbles any space following it - if (this.future().text !== "[") { - return null; - } - start = this.popToken(); // don't include [ in tokens - ({ tokens, end } = this.consumeArg(["]"])); - } else { - ({ tokens, start, end } = this.consumeArg()); - } - - // indicate the end of an argument - this.pushToken(new Token("EOF", end.loc)); - - this.pushTokens(tokens); - return start.range(end, ""); - } - - /** - * Consume all following space tokens, without expansion. - */ - consumeSpaces() { - for (;;) { - const token = this.future(); - if (token.text === " ") { - this.stack.pop(); - } else { - break; - } - } - } - - /** - * Consume an argument from the token stream, and return the resulting array - * of tokens and start/end token. - */ - consumeArg(delims) { - // The argument for a delimited parameter is the shortest (possibly - // empty) sequence of tokens with properly nested {...} groups that is - // followed ... by this particular list of non-parameter tokens. - // The argument for an undelimited parameter is the next nonblank - // token, unless that token is ‘{’, when the argument will be the - // entire {...} group that follows. - const tokens = []; - const isDelimited = delims && delims.length > 0; - if (!isDelimited) { - // Ignore spaces between arguments. As the TeXbook says: - // "After you have said ‘\def\row#1#2{...}’, you are allowed to - // put spaces between the arguments (e.g., ‘\row x n’), because - // TeX doesn’t use single spaces as undelimited arguments." - this.consumeSpaces(); - } - const start = this.future(); - let tok; - let depth = 0; - let match = 0; - do { - tok = this.popToken(); - tokens.push(tok); - if (tok.text === "{") { - ++depth; - } else if (tok.text === "}") { - --depth; - if (depth === -1) { - throw new ParseError("Extra }", tok); - } - } else if (tok.text === "EOF") { - throw new ParseError( - "Unexpected end of input in a macro argument" + - ", expected '" + - (delims && isDelimited ? delims[match] : "}") + - "'", - tok - ); - } - if (delims && isDelimited) { - if ((depth === 0 || (depth === 1 && delims[match] === "{")) && tok.text === delims[match]) { - ++match; - if (match === delims.length) { - // don't include delims in tokens - tokens.splice(-match, match); - break; - } - } else { - match = 0; - } - } - } while (depth !== 0 || isDelimited); - // If the argument found ... has the form ‘{}’, - // ... the outermost braces enclosing the argument are removed - if (start.text === "{" && tokens[tokens.length - 1].text === "}") { - tokens.pop(); - tokens.shift(); - } - tokens.reverse(); // to fit in with stack order - return { tokens, start, end: tok }; - } - - /** - * Consume the specified number of (delimited) arguments from the token - * stream and return the resulting array of arguments. - */ - consumeArgs(numArgs, delimiters) { - if (delimiters) { - if (delimiters.length !== numArgs + 1) { - throw new ParseError("The length of delimiters doesn't match the number of args!"); - } - const delims = delimiters[0]; - for (let i = 0; i < delims.length; i++) { - const tok = this.popToken(); - if (delims[i] !== tok.text) { - throw new ParseError("Use of the macro doesn't match its definition", tok); - } - } - } - - const args = []; - for (let i = 0; i < numArgs; i++) { - args.push(this.consumeArg(delimiters && delimiters[i + 1]).tokens); - } - return args; - } - - /** - * Expand the next token only once if possible. - * - * If the token is expanded, the resulting tokens will be pushed onto - * the stack in reverse order and will be returned as an array, - * also in reverse order. - * - * If not, the next token will be returned without removing it - * from the stack. This case can be detected by a `Token` return value - * instead of an `Array` return value. - * - * In either case, the next token will be on the top of the stack, - * or the stack will be empty. - * - * Used to implement `expandAfterFuture` and `expandNextToken`. - * - * If expandableOnly, only expandable tokens are expanded and - * an undefined control sequence results in an error. - */ - expandOnce(expandableOnly) { - const topToken = this.popToken(); - const name = topToken.text; - const expansion = !topToken.noexpand ? this._getExpansion(name) : null; - if (expansion == null || (expandableOnly && expansion.unexpandable)) { - if (expandableOnly && expansion == null && name[0] === "\\" && !this.isDefined(name)) { - throw new ParseError("Undefined control sequence: " + name); - } - this.pushToken(topToken); - return topToken; - } - this.expansionCount++; - if (this.expansionCount > this.settings.maxExpand) { - throw new ParseError( - "Too many expansions: infinite loop or " + "need to increase maxExpand setting" - ); - } - let tokens = expansion.tokens; - const args = this.consumeArgs(expansion.numArgs, expansion.delimiters); - if (expansion.numArgs) { - // paste arguments in place of the placeholders - tokens = tokens.slice(); // make a shallow copy - for (let i = tokens.length - 1; i >= 0; --i) { - let tok = tokens[i]; - if (tok.text === "#") { - if (i === 0) { - throw new ParseError("Incomplete placeholder at end of macro body", tok); - } - tok = tokens[--i]; // next token on stack - if (tok.text === "#") { - // ## → # - tokens.splice(i + 1, 1); // drop first # - } else if (/^[1-9]$/.test(tok.text)) { - // replace the placeholder with the indicated argument - tokens.splice(i, 2, ...args[+tok.text - 1]); - } else { - throw new ParseError("Not a valid argument number", tok); - } - } - } - } - // Concatenate expansion onto top of stack. - this.pushTokens(tokens); - return tokens; - } - - /** - * Expand the next token only once (if possible), and return the resulting - * top token on the stack (without removing anything from the stack). - * Similar in behavior to TeX's `\expandafter\futurelet`. - * Equivalent to expandOnce() followed by future(). - */ - expandAfterFuture() { - this.expandOnce(); - return this.future(); - } - - /** - * Recursively expand first token, then return first non-expandable token. - */ - expandNextToken() { - for (;;) { - const expanded = this.expandOnce(); - // expandOnce returns Token if and only if it's fully expanded. - if (expanded instanceof Token) { - // The token after \noexpand is interpreted as if its meaning were ‘\relax’ - if (expanded.treatAsRelax) { - expanded.text = "\\relax"; - } - return this.stack.pop(); // === expanded - } - } - - // This pathway is impossible. - throw new Error(); // eslint-disable-line no-unreachable - } - - /** - * Fully expand the given macro name and return the resulting list of - * tokens, or return `undefined` if no such macro is defined. - */ - expandMacro(name) { - return this.macros.has(name) ? this.expandTokens([new Token(name)]) : undefined; - } - - /** - * Fully expand the given token stream and return the resulting list of - * tokens. Note that the input tokens are in reverse order, but the - * output tokens are in forward order. - */ - expandTokens(tokens) { - const output = []; - const oldStackLength = this.stack.length; - this.pushTokens(tokens); - while (this.stack.length > oldStackLength) { - const expanded = this.expandOnce(true); // expand only expandable tokens - // expandOnce returns Token if and only if it's fully expanded. - if (expanded instanceof Token) { - if (expanded.treatAsRelax) { - // the expansion of \noexpand is the token itself - expanded.noexpand = false; - expanded.treatAsRelax = false; - } - output.push(this.stack.pop()); - } - } - return output; - } - - /** - * Fully expand the given macro name and return the result as a string, - * or return `undefined` if no such macro is defined. - */ - expandMacroAsText(name) { - const tokens = this.expandMacro(name); - if (tokens) { - return tokens.map((token) => token.text).join(""); - } else { - return tokens; - } - } - - /** - * Returns the expanded macro as a reversed array of tokens and a macro - * argument count. Or returns `null` if no such macro. - */ - _getExpansion(name) { - const definition = this.macros.get(name); - if (definition == null) { - // mainly checking for undefined here - return definition; - } - // If a single character has an associated catcode other than 13 - // (active character), then don't expand it. - if (name.length === 1) { - const catcode = this.lexer.catcodes[name]; - if (catcode != null && catcode !== 13) { - return - } - } - const expansion = typeof definition === "function" ? definition(this) : definition; - if (typeof expansion === "string") { - let numArgs = 0; - if (expansion.indexOf("#") !== -1) { - const stripped = expansion.replace(/##/g, ""); - while (stripped.indexOf("#" + (numArgs + 1)) !== -1) { - ++numArgs; - } - } - const bodyLexer = new Lexer(expansion, this.settings); - const tokens = []; - let tok = bodyLexer.lex(); - while (tok.text !== "EOF") { - tokens.push(tok); - tok = bodyLexer.lex(); - } - tokens.reverse(); // to fit in with stack using push and pop - const expanded = { tokens, numArgs }; - return expanded; - } - - return expansion; - } - - /** - * Determine whether a command is currently "defined" (has some - * functionality), meaning that it's a macro (in the current group), - * a function, a symbol, or one of the special commands listed in - * `implicitCommands`. - */ - isDefined(name) { - return ( - this.macros.has(name) || - Object.prototype.hasOwnProperty.call(functions, name ) || - Object.prototype.hasOwnProperty.call(symbols.math, name ) || - Object.prototype.hasOwnProperty.call(symbols.text, name ) || - Object.prototype.hasOwnProperty.call(implicitCommands, name ) - ); - } - - /** - * Determine whether a command is expandable. - */ - isExpandable(name) { - const macro = this.macros.get(name); - return macro != null - ? typeof macro === "string" || typeof macro === "function" || !macro.unexpandable - : Object.prototype.hasOwnProperty.call(functions, name ) && !functions[name].primitive; - } -} - -/* - * This file defines the Unicode scripts and script families that we - * support. To add new scripts or families, just add a new entry to the - * scriptData array below. Adding scripts to the scriptData array allows - * characters from that script to appear in \text{} environments. - */ - -/** - * Each script or script family has a name and an array of blocks. - * Each block is an array of two numbers which specify the start and - * end points (inclusive) of a block of Unicode codepoints. - -/** - * Unicode block data for the families of scripts we support in \text{}. - * Scripts only need to appear here if they do not have font metrics. - */ -const scriptData = [ - { - // Latin characters beyond the Latin-1 characters we have metrics for. - // Needed for Czech, Hungarian and Turkish text, for example. - name: "latin", - blocks: [ - [0x0100, 0x024f], // Latin Extended-A and Latin Extended-B - [0x0300, 0x036f] // Combining Diacritical marks - ] - }, - { - // The Cyrillic script used by Russian and related languages. - // A Cyrillic subset used to be supported as explicitly defined - // symbols in symbols.js - name: "cyrillic", - blocks: [[0x0400, 0x04ff]] - }, - { - // Armenian - name: "armenian", - blocks: [[0x0530, 0x058f]] - }, - { - // The Brahmic scripts of South and Southeast Asia - // Devanagari (0900–097F) - // Bengali (0980–09FF) - // Gurmukhi (0A00–0A7F) - // Gujarati (0A80–0AFF) - // Oriya (0B00–0B7F) - // Tamil (0B80–0BFF) - // Telugu (0C00–0C7F) - // Kannada (0C80–0CFF) - // Malayalam (0D00–0D7F) - // Sinhala (0D80–0DFF) - // Thai (0E00–0E7F) - // Lao (0E80–0EFF) - // Tibetan (0F00–0FFF) - // Myanmar (1000–109F) - name: "brahmic", - blocks: [[0x0900, 0x109f]] - }, - { - name: "georgian", - blocks: [[0x10a0, 0x10ff]] - }, - { - // Chinese and Japanese. - // The "k" in cjk is for Korean, but we've separated Korean out - name: "cjk", - blocks: [ - [0x3000, 0x30ff], // CJK symbols and punctuation, Hiragana, Katakana - [0x4e00, 0x9faf], // CJK ideograms - [0xff00, 0xff60] // Fullwidth punctuation - // TODO: add halfwidth Katakana and Romanji glyphs - ] - }, - { - // Korean - name: "hangul", - blocks: [[0xac00, 0xd7af]] - } -]; - -/** - * A flattened version of all the supported blocks in a single array. - * This is an optimization to make supportedCodepoint() fast. - */ -const allBlocks = []; -scriptData.forEach((s) => s.blocks.forEach((b) => allBlocks.push(...b))); - -/** - * Given a codepoint, return true if it falls within one of the - * scripts or script families defined above and false otherwise. - * - * Micro benchmarks shows that this is faster than - * /[\u3000-\u30FF\u4E00-\u9FAF\uFF00-\uFF60\uAC00-\uD7AF\u0900-\u109F]/.test() - * in Firefox, Chrome and Node. - */ -function supportedCodepoint(codepoint) { - for (let i = 0; i < allBlocks.length; i += 2) { - if (codepoint >= allBlocks[i] && codepoint <= allBlocks[i + 1]) { - return true; - } - } - return false; -} - -// Helpers for Parser.js handling of Unicode (sub|super)script characters. - -const unicodeSubRegEx = /^[₊₋₌₍₎₀₁₂₃₄₅₆₇₈₉ₐₑₕᵢⱼₖₗₘₙₒₚᵣₛₜᵤᵥₓᵦᵧᵨᵩᵪ]/; - -const uSubsAndSups = Object.freeze({ - '₊': '+', - '₋': '-', - '₌': '=', - '₍': '(', - '₎': ')', - '₀': '0', - '₁': '1', - '₂': '2', - '₃': '3', - '₄': '4', - '₅': '5', - '₆': '6', - '₇': '7', - '₈': '8', - '₉': '9', - '\u2090': 'a', - '\u2091': 'e', - '\u2095': 'h', - '\u1D62': 'i', - '\u2C7C': 'j', - '\u2096': 'k', - '\u2097': 'l', - '\u2098': 'm', - '\u2099': 'n', - '\u2092': 'o', - '\u209A': 'p', - '\u1D63': 'r', - '\u209B': 's', - '\u209C': 't', - '\u1D64': 'u', - '\u1D65': 'v', - '\u2093': 'x', - '\u1D66': 'β', - '\u1D67': 'γ', - '\u1D68': 'ρ', - '\u1D69': '\u03d5', - '\u1D6A': 'χ', - '⁺': '+', - '⁻': '-', - '⁼': '=', - '⁽': '(', - '⁾': ')', - '⁰': '0', - '¹': '1', - '²': '2', - '³': '3', - '⁴': '4', - '⁵': '5', - '⁶': '6', - '⁷': '7', - '⁸': '8', - '⁹': '9', - '\u1D2C': 'A', - '\u1D2E': 'B', - '\u1D30': 'D', - '\u1D31': 'E', - '\u1D33': 'G', - '\u1D34': 'H', - '\u1D35': 'I', - '\u1D36': 'J', - '\u1D37': 'K', - '\u1D38': 'L', - '\u1D39': 'M', - '\u1D3A': 'N', - '\u1D3C': 'O', - '\u1D3E': 'P', - '\u1D3F': 'R', - '\u1D40': 'T', - '\u1D41': 'U', - '\u2C7D': 'V', - '\u1D42': 'W', - '\u1D43': 'a', - '\u1D47': 'b', - '\u1D9C': 'c', - '\u1D48': 'd', - '\u1D49': 'e', - '\u1DA0': 'f', - '\u1D4D': 'g', - '\u02B0': 'h', - '\u2071': 'i', - '\u02B2': 'j', - '\u1D4F': 'k', - '\u02E1': 'l', - '\u1D50': 'm', - '\u207F': 'n', - '\u1D52': 'o', - '\u1D56': 'p', - '\u02B3': 'r', - '\u02E2': 's', - '\u1D57': 't', - '\u1D58': 'u', - '\u1D5B': 'v', - '\u02B7': 'w', - '\u02E3': 'x', - '\u02B8': 'y', - '\u1DBB': 'z', - '\u1D5D': 'β', - '\u1D5E': 'γ', - '\u1D5F': 'δ', - '\u1D60': '\u03d5', - '\u1D61': 'χ', - '\u1DBF': 'θ' -}); - -// Mapping of Unicode accent characters to their LaTeX equivalent in text and -// math mode (when they exist). -var unicodeAccents = { - "\u0301": { text: "\\'", math: "\\acute" }, - "\u0300": { text: "\\`", math: "\\grave" }, - "\u0308": { text: '\\"', math: "\\ddot" }, - "\u0303": { text: "\\~", math: "\\tilde" }, - "\u0304": { text: "\\=", math: "\\bar" }, - "\u0306": { text: "\\u", math: "\\breve" }, - "\u030c": { text: "\\v", math: "\\check" }, - "\u0302": { text: "\\^", math: "\\hat" }, - "\u0307": { text: "\\.", math: "\\dot" }, - "\u030a": { text: "\\r", math: "\\mathring" }, - "\u030b": { text: "\\H" }, - '\u0327': { text: '\\c' } -}; - -var unicodeSymbols = { - "á": "á", - "à": "à", - "ä": "ä", - "ǟ": "ǟ", - "ã": "ã", - "ā": "ā", - "ă": "ă", - "ắ": "ắ", - "ằ": "ằ", - "ẵ": "ẵ", - "ǎ": "ǎ", - "â": "â", - "ấ": "ấ", - "ầ": "ầ", - "ẫ": "ẫ", - "ȧ": "ȧ", - "ǡ": "ǡ", - "å": "å", - "ǻ": "ǻ", - "ḃ": "ḃ", - "ć": "ć", - "č": "č", - "ĉ": "ĉ", - "ċ": "ċ", - "ď": "ď", - "ḋ": "ḋ", - "é": "é", - "è": "è", - "ë": "ë", - "ẽ": "ẽ", - "ē": "ē", - "ḗ": "ḗ", - "ḕ": "ḕ", - "ĕ": "ĕ", - "ě": "ě", - "ê": "ê", - "ế": "ế", - "ề": "ề", - "ễ": "ễ", - "ė": "ė", - "ḟ": "ḟ", - "ǵ": "ǵ", - "ḡ": "ḡ", - "ğ": "ğ", - "ǧ": "ǧ", - "ĝ": "ĝ", - "ġ": "ġ", - "ḧ": "ḧ", - "ȟ": "ȟ", - "ĥ": "ĥ", - "ḣ": "ḣ", - "í": "í", - "ì": "ì", - "ï": "ï", - "ḯ": "ḯ", - "ĩ": "ĩ", - "ī": "ī", - "ĭ": "ĭ", - "ǐ": "ǐ", - "î": "î", - "ǰ": "ǰ", - "ĵ": "ĵ", - "ḱ": "ḱ", - "ǩ": "ǩ", - "ĺ": "ĺ", - "ľ": "ľ", - "ḿ": "ḿ", - "ṁ": "ṁ", - "ń": "ń", - "ǹ": "ǹ", - "ñ": "ñ", - "ň": "ň", - "ṅ": "ṅ", - "ó": "ó", - "ò": "ò", - "ö": "ö", - "ȫ": "ȫ", - "õ": "õ", - "ṍ": "ṍ", - "ṏ": "ṏ", - "ȭ": "ȭ", - "ō": "ō", - "ṓ": "ṓ", - "ṑ": "ṑ", - "ŏ": "ŏ", - "ǒ": "ǒ", - "ô": "ô", - "ố": "ố", - "ồ": "ồ", - "ỗ": "ỗ", - "ȯ": "ȯ", - "ȱ": "ȱ", - "ő": "ő", - "ṕ": "ṕ", - "ṗ": "ṗ", - "ŕ": "ŕ", - "ř": "ř", - "ṙ": "ṙ", - "ś": "ś", - "ṥ": "ṥ", - "š": "š", - "ṧ": "ṧ", - "ŝ": "ŝ", - "ṡ": "ṡ", - "ẗ": "ẗ", - "ť": "ť", - "ṫ": "ṫ", - "ú": "ú", - "ù": "ù", - "ü": "ü", - "ǘ": "ǘ", - "ǜ": "ǜ", - "ǖ": "ǖ", - "ǚ": "ǚ", - "ũ": "ũ", - "ṹ": "ṹ", - "ū": "ū", - "ṻ": "ṻ", - "ŭ": "ŭ", - "ǔ": "ǔ", - "û": "û", - "ů": "ů", - "ű": "ű", - "ṽ": "ṽ", - "ẃ": "ẃ", - "ẁ": "ẁ", - "ẅ": "ẅ", - "ŵ": "ŵ", - "ẇ": "ẇ", - "ẘ": "ẘ", - "ẍ": "ẍ", - "ẋ": "ẋ", - "ý": "ý", - "ỳ": "ỳ", - "ÿ": "ÿ", - "ỹ": "ỹ", - "ȳ": "ȳ", - "ŷ": "ŷ", - "ẏ": "ẏ", - "ẙ": "ẙ", - "ź": "ź", - "ž": "ž", - "ẑ": "ẑ", - "ż": "ż", - "Á": "Á", - "À": "À", - "Ä": "Ä", - "Ǟ": "Ǟ", - "Ã": "Ã", - "Ā": "Ā", - "Ă": "Ă", - "Ắ": "Ắ", - "Ằ": "Ằ", - "Ẵ": "Ẵ", - "Ǎ": "Ǎ", - "Â": "Â", - "Ấ": "Ấ", - "Ầ": "Ầ", - "Ẫ": "Ẫ", - "Ȧ": "Ȧ", - "Ǡ": "Ǡ", - "Å": "Å", - "Ǻ": "Ǻ", - "Ḃ": "Ḃ", - "Ć": "Ć", - "Č": "Č", - "Ĉ": "Ĉ", - "Ċ": "Ċ", - "Ď": "Ď", - "Ḋ": "Ḋ", - "É": "É", - "È": "È", - "Ë": "Ë", - "Ẽ": "Ẽ", - "Ē": "Ē", - "Ḗ": "Ḗ", - "Ḕ": "Ḕ", - "Ĕ": "Ĕ", - "Ě": "Ě", - "Ê": "Ê", - "Ế": "Ế", - "Ề": "Ề", - "Ễ": "Ễ", - "Ė": "Ė", - "Ḟ": "Ḟ", - "Ǵ": "Ǵ", - "Ḡ": "Ḡ", - "Ğ": "Ğ", - "Ǧ": "Ǧ", - "Ĝ": "Ĝ", - "Ġ": "Ġ", - "Ḧ": "Ḧ", - "Ȟ": "Ȟ", - "Ĥ": "Ĥ", - "Ḣ": "Ḣ", - "Í": "Í", - "Ì": "Ì", - "Ï": "Ï", - "Ḯ": "Ḯ", - "Ĩ": "Ĩ", - "Ī": "Ī", - "Ĭ": "Ĭ", - "Ǐ": "Ǐ", - "Î": "Î", - "İ": "İ", - "Ĵ": "Ĵ", - "Ḱ": "Ḱ", - "Ǩ": "Ǩ", - "Ĺ": "Ĺ", - "Ľ": "Ľ", - "Ḿ": "Ḿ", - "Ṁ": "Ṁ", - "Ń": "Ń", - "Ǹ": "Ǹ", - "Ñ": "Ñ", - "Ň": "Ň", - "Ṅ": "Ṅ", - "Ó": "Ó", - "Ò": "Ò", - "Ö": "Ö", - "Ȫ": "Ȫ", - "Õ": "Õ", - "Ṍ": "Ṍ", - "Ṏ": "Ṏ", - "Ȭ": "Ȭ", - "Ō": "Ō", - "Ṓ": "Ṓ", - "Ṑ": "Ṑ", - "Ŏ": "Ŏ", - "Ǒ": "Ǒ", - "Ô": "Ô", - "Ố": "Ố", - "Ồ": "Ồ", - "Ỗ": "Ỗ", - "Ȯ": "Ȯ", - "Ȱ": "Ȱ", - "Ő": "Ő", - "Ṕ": "Ṕ", - "Ṗ": "Ṗ", - "Ŕ": "Ŕ", - "Ř": "Ř", - "Ṙ": "Ṙ", - "Ś": "Ś", - "Ṥ": "Ṥ", - "Š": "Š", - "Ṧ": "Ṧ", - "Ŝ": "Ŝ", - "Ṡ": "Ṡ", - "Ť": "Ť", - "Ṫ": "Ṫ", - "Ú": "Ú", - "Ù": "Ù", - "Ü": "Ü", - "Ǘ": "Ǘ", - "Ǜ": "Ǜ", - "Ǖ": "Ǖ", - "Ǚ": "Ǚ", - "Ũ": "Ũ", - "Ṹ": "Ṹ", - "Ū": "Ū", - "Ṻ": "Ṻ", - "Ŭ": "Ŭ", - "Ǔ": "Ǔ", - "Û": "Û", - "Ů": "Ů", - "Ű": "Ű", - "Ṽ": "Ṽ", - "Ẃ": "Ẃ", - "Ẁ": "Ẁ", - "Ẅ": "Ẅ", - "Ŵ": "Ŵ", - "Ẇ": "Ẇ", - "Ẍ": "Ẍ", - "Ẋ": "Ẋ", - "Ý": "Ý", - "Ỳ": "Ỳ", - "Ÿ": "Ÿ", - "Ỹ": "Ỹ", - "Ȳ": "Ȳ", - "Ŷ": "Ŷ", - "Ẏ": "Ẏ", - "Ź": "Ź", - "Ž": "Ž", - "Ẑ": "Ẑ", - "Ż": "Ż", - "ά": "ά", - "ὰ": "ὰ", - "ᾱ": "ᾱ", - "ᾰ": "ᾰ", - "έ": "έ", - "ὲ": "ὲ", - "ή": "ή", - "ὴ": "ὴ", - "ί": "ί", - "ὶ": "ὶ", - "ϊ": "ϊ", - "ΐ": "ΐ", - "ῒ": "ῒ", - "ῑ": "ῑ", - "ῐ": "ῐ", - "ό": "ό", - "ὸ": "ὸ", - "ύ": "ύ", - "ὺ": "ὺ", - "ϋ": "ϋ", - "ΰ": "ΰ", - "ῢ": "ῢ", - "ῡ": "ῡ", - "ῠ": "ῠ", - "ώ": "ώ", - "ὼ": "ὼ", - "Ύ": "Ύ", - "Ὺ": "Ὺ", - "Ϋ": "Ϋ", - "Ῡ": "Ῡ", - "Ῠ": "Ῠ", - "Ώ": "Ώ", - "Ὼ": "Ὼ" -}; - -/* eslint no-constant-condition:0 */ - -const numberRegEx = /^\d(?:[\d,.]*\d)?$/; // Keep in sync with numberRegEx in symbolsOrd.js - -/** - * This file contains the parser used to parse out a TeX expression from the - * input. Since TeX isn't context-free, standard parsers don't work particularly - * well. - * - * The strategy of this parser is as such: - * - * The main functions (the `.parse...` ones) take a position in the current - * parse string to parse tokens from. The lexer (found in Lexer.js, stored at - * this.gullet.lexer) also supports pulling out tokens at arbitrary places. When - * individual tokens are needed at a position, the lexer is called to pull out a - * token, which is then used. - * - * The parser has a property called "mode" indicating the mode that - * the parser is currently in. Currently it has to be one of "math" or - * "text", which denotes whether the current environment is a math-y - * one or a text-y one (e.g. inside \text). Currently, this serves to - * limit the functions which can be used in text mode. - * - * The main functions then return an object which contains the useful data that - * was parsed at its given point, and a new position at the end of the parsed - * data. The main functions can call each other and continue the parsing by - * using the returned position as a new starting point. - * - * There are also extra `.handle...` functions, which pull out some reused - * functionality into self-contained functions. - * - * The functions return ParseNodes. - */ - -class Parser { - constructor(input, settings, isPreamble = false) { - // Start in math mode - this.mode = "math"; - // Create a new macro expander (gullet) and (indirectly via that) also a - // new lexer (mouth) for this parser (stomach, in the language of TeX) - this.gullet = new MacroExpander(input, settings, this.mode); - // Store the settings for use in parsing - this.settings = settings; - // Are we defining a preamble? - this.isPreamble = isPreamble; - // Count leftright depth (for \middle errors) - this.leftrightDepth = 0; - this.prevAtomType = ""; - } - - /** - * Checks a result to make sure it has the right type, and throws an - * appropriate error otherwise. - */ - expect(text, consume = true) { - if (this.fetch().text !== text) { - throw new ParseError(`Expected '${text}', got '${this.fetch().text}'`, this.fetch()); - } - if (consume) { - this.consume(); - } - } - - /** - * Discards the current lookahead token, considering it consumed. - */ - consume() { - this.nextToken = null; - } - - /** - * Return the current lookahead token, or if there isn't one (at the - * beginning, or if the previous lookahead token was consume()d), - * fetch the next token as the new lookahead token and return it. - */ - fetch() { - if (this.nextToken == null) { - this.nextToken = this.gullet.expandNextToken(); - } - return this.nextToken; - } - - /** - * Switches between "text" and "math" modes. - */ - switchMode(newMode) { - this.mode = newMode; - this.gullet.switchMode(newMode); - } - - /** - * Main parsing function, which parses an entire input. - */ - parse() { - // Create a group namespace for every $...$, $$...$$, \[...\].) - // A \def is then valid only within that pair of delimiters. - this.gullet.beginGroup(); - - if (this.settings.colorIsTextColor) { - // Use old \color behavior (same as LaTeX's \textcolor) if requested. - // We do this within the group for the math expression, so it doesn't - // pollute settings.macros. - this.gullet.macros.set("\\color", "\\textcolor"); - } - - // Try to parse the input - const parse = this.parseExpression(false); - - // If we succeeded, make sure there's an EOF at the end - this.expect("EOF"); - - if (this.isPreamble) { - const macros = Object.create(null); - Object.entries(this.gullet.macros.current).forEach(([key, value]) => { - macros[key] = value; - }); - this.gullet.endGroup(); - return macros - } - - // The only local macro that we want to save is from \tag. - const tag = this.gullet.macros.get("\\df@tag"); - - // End the group namespace for the expression - this.gullet.endGroup(); - - if (tag) { this.gullet.macros.current["\\df@tag"] = tag; } - - return parse; - } - - static get endOfExpression() { - return ["}", "\\endgroup", "\\end", "\\right", "\\endtoggle", "&"]; - } - - /** - * Parses an "expression", which is a list of atoms. - * - * `breakOnInfix`: Should the parsing stop when we hit infix nodes? This - * happens when functions have higher precendence han infix - * nodes in implicit parses. - * - * `breakOnTokenText`: The text of the token that the expression should end - * with, or `null` if something else should end the - * expression. - */ - parseExpression(breakOnInfix, breakOnTokenText) { - const body = []; - // Keep adding atoms to the body until we can't parse any more atoms (either - // we reached the end, a }, or a \right) - while (true) { - // Ignore spaces in math mode - if (this.mode === "math") { - this.consumeSpaces(); - } - const lex = this.fetch(); - if (Parser.endOfExpression.indexOf(lex.text) !== -1) { - break; - } - if (breakOnTokenText && lex.text === breakOnTokenText) { - break; - } - if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) { - break; - } - const atom = this.parseAtom(breakOnTokenText); - if (!atom) { - break; - } else if (atom.type === "internal") { - continue; - } - body.push(atom); - // Keep a record of the atom type, so that op.js can set correct spacing. - this.prevAtomType = atom.type === "atom" ? atom.family : atom.type; - } - if (this.mode === "text") { - this.formLigatures(body); - } - return this.handleInfixNodes(body); - } - - /** - * Rewrites infix operators such as \over with corresponding commands such - * as \frac. - * - * There can only be one infix operator per group. If there's more than one - * then the expression is ambiguous. This can be resolved by adding {}. - */ - handleInfixNodes(body) { - let overIndex = -1; - let funcName; - - for (let i = 0; i < body.length; i++) { - if (body[i].type === "infix") { - if (overIndex !== -1) { - throw new ParseError("only one infix operator per group", body[i].token); - } - overIndex = i; - funcName = body[i].replaceWith; - } - } - - if (overIndex !== -1 && funcName) { - let numerNode; - let denomNode; - - const numerBody = body.slice(0, overIndex); - const denomBody = body.slice(overIndex + 1); - - if (numerBody.length === 1 && numerBody[0].type === "ordgroup") { - numerNode = numerBody[0]; - } else { - numerNode = { type: "ordgroup", mode: this.mode, body: numerBody }; - } - - if (denomBody.length === 1 && denomBody[0].type === "ordgroup") { - denomNode = denomBody[0]; - } else { - denomNode = { type: "ordgroup", mode: this.mode, body: denomBody }; - } - - let node; - if (funcName === "\\\\abovefrac") { - node = this.callFunction(funcName, [numerNode, body[overIndex], denomNode], []); - } else { - node = this.callFunction(funcName, [numerNode, denomNode], []); - } - return [node]; - } else { - return body; - } - } - - /** - * Handle a subscript or superscript with nice errors. - */ - handleSupSubscript( - name // For error reporting. - ) { - const symbolToken = this.fetch(); - const symbol = symbolToken.text; - this.consume(); - this.consumeSpaces(); // ignore spaces before sup/subscript argument - const group = this.parseGroup(name); - - if (!group) { - throw new ParseError("Expected group after '" + symbol + "'", symbolToken); - } - - return group; - } - - /** - * Converts the textual input of an unsupported command into a text node - * contained within a color node whose color is determined by errorColor - */ - formatUnsupportedCmd(text) { - const textordArray = []; - - for (let i = 0; i < text.length; i++) { - textordArray.push({ type: "textord", mode: "text", text: text[i] }); - } - - const textNode = { - type: "text", - mode: this.mode, - body: textordArray - }; - - const colorNode = { - type: "color", - mode: this.mode, - color: this.settings.errorColor, - body: [textNode] - }; - - return colorNode; - } - - /** - * Parses a group with optional super/subscripts. - */ - parseAtom(breakOnTokenText) { - // The body of an atom is an implicit group, so that things like - // \left(x\right)^2 work correctly. - const base = this.parseGroup("atom", breakOnTokenText); - - // In text mode, we don't have superscripts or subscripts - if (this.mode === "text") { - return base; - } - - // Note that base may be empty (i.e. null) at this point. - - let superscript; - let subscript; - while (true) { - // Guaranteed in math mode, so eat any spaces first. - this.consumeSpaces(); - - // Lex the first token - const lex = this.fetch(); - - if (lex.text === "\\limits" || lex.text === "\\nolimits") { - // We got a limit control - if (base && base.type === "op") { - const limits = lex.text === "\\limits"; - base.limits = limits; - base.alwaysHandleSupSub = true; - } else if (base && base.type === "operatorname") { - if (base.alwaysHandleSupSub) { - base.limits = lex.text === "\\limits"; - } - } else { - throw new ParseError("Limit controls must follow a math operator", lex); - } - this.consume(); - } else if (lex.text === "^") { - // We got a superscript start - if (superscript) { - throw new ParseError("Double superscript", lex); - } - superscript = this.handleSupSubscript("superscript"); - } else if (lex.text === "_") { - // We got a subscript start - if (subscript) { - throw new ParseError("Double subscript", lex); - } - subscript = this.handleSupSubscript("subscript"); - } else if (lex.text === "'") { - // We got a prime - if (superscript) { - throw new ParseError("Double superscript", lex); - } - const prime = { type: "textord", mode: this.mode, text: "\\prime" }; - - // Many primes can be grouped together, so we handle this here - const primes = [prime]; - this.consume(); - // Keep lexing tokens until we get something that's not a prime - while (this.fetch().text === "'") { - // For each one, add another prime to the list - primes.push(prime); - this.consume(); - } - // If there's a superscript following the primes, combine that - // superscript in with the primes. - if (this.fetch().text === "^") { - primes.push(this.handleSupSubscript("superscript")); - } - // Put everything into an ordgroup as the superscript - superscript = { type: "ordgroup", mode: this.mode, body: primes }; - } else if (uSubsAndSups[lex.text]) { - // A Unicode subscript or superscript character. - // We treat these similarly to the unicode-math package. - // So we render a string of Unicode (sub|super)scripts the - // same as a (sub|super)script of regular characters. - let str = uSubsAndSups[lex.text]; - const isSub = unicodeSubRegEx.test(lex.text); - this.consume(); - // Continue fetching tokens to fill out the string. - while (true) { - const token = this.fetch().text; - if (!(uSubsAndSups[token])) { break } - if (unicodeSubRegEx.test(token) !== isSub) { break } - this.consume(); - str += uSubsAndSups[token]; - } - // Now create a (sub|super)script. - const body = (new Parser(str, this.settings)).parse(); - if (isSub) { - subscript = { type: "ordgroup", mode: "math", body }; - } else { - superscript = { type: "ordgroup", mode: "math", body }; - } - } else { - // If it wasn't ^, _, a Unicode (sub|super)script, or ', stop parsing super/subscripts - break; - } - } - - if (superscript || subscript) { - if (base && base.type === "multiscript" && !base.postscripts) { - // base is the result of a \prescript function. - // Write the sub- & superscripts into the multiscript element. - base.postscripts = { sup: superscript, sub: subscript }; - return base - } else { - // We got either a superscript or subscript, create a supsub - return { - type: "supsub", - mode: this.mode, - base: base, - sup: superscript, - sub: subscript - } - } - } else { - // Otherwise return the original body - return base; - } - } - - /** - * Parses an entire function, including its base and all of its arguments. - */ - parseFunction( - breakOnTokenText, - name // For determining its context - ) { - const token = this.fetch(); - const func = token.text; - const funcData = functions[func]; - if (!funcData) { - return null; - } - this.consume(); // consume command token - - if (name && name !== "atom" && !funcData.allowedInArgument) { - throw new ParseError( - "Got function '" + func + "' with no arguments" + (name ? " as " + name : ""), - token - ); - } else if (this.mode === "text" && !funcData.allowedInText) { - throw new ParseError("Can't use function '" + func + "' in text mode", token); - } else if (this.mode === "math" && funcData.allowedInMath === false) { - throw new ParseError("Can't use function '" + func + "' in math mode", token); - } - - const prevAtomType = this.prevAtomType; - const { args, optArgs } = this.parseArguments(func, funcData); - this.prevAtomType = prevAtomType; - return this.callFunction(func, args, optArgs, token, breakOnTokenText); - } - - /** - * Call a function handler with a suitable context and arguments. - */ - callFunction(name, args, optArgs, token, breakOnTokenText) { - const context = { - funcName: name, - parser: this, - token, - breakOnTokenText - }; - const func = functions[name]; - if (func && func.handler) { - return func.handler(context, args, optArgs); - } else { - throw new ParseError(`No function handler for ${name}`); - } - } - - /** - * Parses the arguments of a function or environment - */ - parseArguments( - func, // Should look like "\name" or "\begin{name}". - funcData - ) { - const totalArgs = funcData.numArgs + funcData.numOptionalArgs; - if (totalArgs === 0) { - return { args: [], optArgs: [] }; - } - - const args = []; - const optArgs = []; - - for (let i = 0; i < totalArgs; i++) { - let argType = funcData.argTypes && funcData.argTypes[i]; - const isOptional = i < funcData.numOptionalArgs; - - if ( - (funcData.primitive && argType == null) || - // \sqrt expands into primitive if optional argument doesn't exist - (funcData.type === "sqrt" && i === 1 && optArgs[0] == null) - ) { - argType = "primitive"; - } - - const arg = this.parseGroupOfType(`argument to '${func}'`, argType, isOptional); - if (isOptional) { - optArgs.push(arg); - } else if (arg != null) { - args.push(arg); - } else { - // should be unreachable - throw new ParseError("Null argument, please report this as a bug"); - } - } - - return { args, optArgs }; - } - - /** - * Parses a group when the mode is changing. - */ - parseGroupOfType(name, type, optional) { - switch (type) { - case "size": - return this.parseSizeGroup(optional); - case "url": - return this.parseUrlGroup(optional); - case "math": - case "text": - return this.parseArgumentGroup(optional, type); - case "hbox": { - // hbox argument type wraps the argument in the equivalent of - // \hbox, which is like \text but switching to \textstyle size. - const group = this.parseArgumentGroup(optional, "text"); - return group != null - ? { - type: "styling", - mode: group.mode, - body: [group], - scriptLevel: "text" // simulate \textstyle - } - : null; - } - case "raw": { - const token = this.parseStringGroup("raw", optional); - return token != null - ? { - type: "raw", - mode: "text", - string: token.text - } - : null; - } - case "primitive": { - if (optional) { - throw new ParseError("A primitive argument cannot be optional"); - } - const group = this.parseGroup(name); - if (group == null) { - throw new ParseError("Expected group as " + name, this.fetch()); - } - return group; - } - case "original": - case null: - case undefined: - return this.parseArgumentGroup(optional); - default: - throw new ParseError("Unknown group type as " + name, this.fetch()); - } - } - - /** - * Discard any space tokens, fetching the next non-space token. - */ - consumeSpaces() { - while (this.fetch().text === " ") { - this.consume(); - } - } - - /** - * Parses a group, essentially returning the string formed by the - * brace-enclosed tokens plus some position information. - */ - parseStringGroup( - modeName, // Used to describe the mode in error messages. - optional - ) { - const argToken = this.gullet.scanArgument(optional); - if (argToken == null) { - return null; - } - let str = ""; - let nextToken; - while ((nextToken = this.fetch()).text !== "EOF") { - str += nextToken.text; - this.consume(); - } - this.consume(); // consume the end of the argument - argToken.text = str; - return argToken; - } - - /** - * Parses a regex-delimited group: the largest sequence of tokens - * whose concatenated strings match `regex`. Returns the string - * formed by the tokens plus some position information. - */ - parseRegexGroup( - regex, - modeName // Used to describe the mode in error messages. - ) { - const firstToken = this.fetch(); - let lastToken = firstToken; - let str = ""; - let nextToken; - while ((nextToken = this.fetch()).text !== "EOF" && regex.test(str + nextToken.text)) { - lastToken = nextToken; - str += lastToken.text; - this.consume(); - } - if (str === "") { - throw new ParseError("Invalid " + modeName + ": '" + firstToken.text + "'", firstToken); - } - return firstToken.range(lastToken, str); - } - - /** - * Parses a size specification, consisting of magnitude and unit. - */ - parseSizeGroup(optional) { - let res; - let isBlank = false; - // don't expand before parseStringGroup - this.gullet.consumeSpaces(); - if (!optional && this.gullet.future().text !== "{") { - res = this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size"); - } else { - res = this.parseStringGroup("size", optional); - } - if (!res) { - return null; - } - if (!optional && res.text.length === 0) { - // Because we've tested for what is !optional, this block won't - // affect \kern, \hspace, etc. It will capture the mandatory arguments - // to \genfrac and \above. - res.text = "0pt"; // Enable \above{} - isBlank = true; // This is here specifically for \genfrac - } - const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(res.text); - if (!match) { - throw new ParseError("Invalid size: '" + res.text + "'", res); - } - const data = { - number: +(match[1] + match[2]), // sign + magnitude, cast to number - unit: match[3] - }; - if (!validUnit(data)) { - throw new ParseError("Invalid unit: '" + data.unit + "'", res); - } - return { - type: "size", - mode: this.mode, - value: data, - isBlank - }; - } - - /** - * Parses an URL, checking escaped letters and allowed protocols, - * and setting the catcode of % as an active character (as in \hyperref). - */ - parseUrlGroup(optional) { - this.gullet.lexer.setCatcode("%", 13); // active character - this.gullet.lexer.setCatcode("~", 12); // other character - const res = this.parseStringGroup("url", optional); - this.gullet.lexer.setCatcode("%", 14); // comment character - this.gullet.lexer.setCatcode("~", 13); // active character - if (res == null) { - return null; - } - // hyperref package allows backslashes alone in href, but doesn't - // generate valid links in such cases; we interpret this as - // "undefined" behaviour, and keep them as-is. Some browser will - // replace backslashes with forward slashes. - let url = res.text.replace(/\\([#$%&~_^{}])/g, "$1"); - url = res.text.replace(/{\u2044}/g, "/"); - return { - type: "url", - mode: this.mode, - url - }; - } - - /** - * Parses an argument with the mode specified. - */ - parseArgumentGroup(optional, mode) { - const argToken = this.gullet.scanArgument(optional); - if (argToken == null) { - return null; - } - const outerMode = this.mode; - if (mode) { - // Switch to specified mode - this.switchMode(mode); - } - - this.gullet.beginGroup(); - const expression = this.parseExpression(false, "EOF"); - // TODO: find an alternative way to denote the end - this.expect("EOF"); // expect the end of the argument - this.gullet.endGroup(); - const result = { - type: "ordgroup", - mode: this.mode, - loc: argToken.loc, - body: expression - }; - - if (mode) { - // Switch mode back - this.switchMode(outerMode); - } - return result; - } - - /** - * Parses an ordinary group, which is either a single nucleus (like "x") - * or an expression in braces (like "{x+y}") or an implicit group, a group - * that starts at the current position, and ends right before a higher explicit - * group ends, or at EOF. - */ - parseGroup( - name, // For error reporting. - breakOnTokenText - ) { - const firstToken = this.fetch(); - const text = firstToken.text; - - let result; - // Try to parse an open brace or \begingroup - if (text === "{" || text === "\\begingroup" || text === "\\toggle") { - this.consume(); - const groupEnd = text === "{" - ? "}" - : text === "\\begingroup" - ? "\\endgroup" - : "\\endtoggle"; - - this.gullet.beginGroup(); - // If we get a brace, parse an expression - const expression = this.parseExpression(false, groupEnd); - const lastToken = this.fetch(); - this.expect(groupEnd); // Check that we got a matching closing brace - this.gullet.endGroup(); - result = { - type: (lastToken.text === "\\endtoggle" ? "toggle" : "ordgroup"), - mode: this.mode, - loc: SourceLocation.range(firstToken, lastToken), - body: expression, - // A group formed by \begingroup...\endgroup is a semi-simple group - // which doesn't affect spacing in math mode, i.e., is transparent. - // https://tex.stackexchange.com/questions/1930/when-should-one- - // use-begingroup-instead-of-bgroup - semisimple: text === "\\begingroup" || undefined - }; - } else { - // If there exists a function with this name, parse the function. - // Otherwise, just return a nucleus - result = this.parseFunction(breakOnTokenText, name) || this.parseSymbol(); - if (result == null && text[0] === "\\" && - !Object.prototype.hasOwnProperty.call(implicitCommands, text )) { - result = this.formatUnsupportedCmd(text); - this.consume(); - } - } - return result; - } - - /** - * Form ligature-like combinations of characters for text mode. - * This includes inputs like "--", "---", "``" and "''". - * The result will simply replace multiple textord nodes with a single - * character in each value by a single textord node having multiple - * characters in its value. The representation is still ASCII source. - * The group will be modified in place. - */ - formLigatures(group) { - let n = group.length - 1; - for (let i = 0; i < n; ++i) { - const a = group[i]; - const v = a.text; - if (v === "-" && group[i + 1].text === "-") { - if (i + 1 < n && group[i + 2].text === "-") { - group.splice(i, 3, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 2]), - text: "---" - }); - n -= 2; - } else { - group.splice(i, 2, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 1]), - text: "--" - }); - n -= 1; - } - } - if ((v === "'" || v === "`") && group[i + 1].text === v) { - group.splice(i, 2, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 1]), - text: v + v - }); - n -= 1; - } - } - } - - /** - * Parse a single symbol out of the string. Here, we handle single character - * symbols and special functions like \verb. - */ - parseSymbol() { - const nucleus = this.fetch(); - let text = nucleus.text; - - if (/^\\verb[^a-zA-Z]/.test(text)) { - this.consume(); - let arg = text.slice(5); - const star = arg.charAt(0) === "*"; - if (star) { - arg = arg.slice(1); - } - // Lexer's tokenRegex is constructed to always have matching - // first/last characters. - if (arg.length < 2 || arg.charAt(0) !== arg.slice(-1)) { - throw new ParseError(`\\verb assertion failed -- - please report what input caused this bug`); - } - arg = arg.slice(1, -1); // remove first and last char - return { - type: "verb", - mode: "text", - body: arg, - star - }; - } - // At this point, we should have a symbol, possibly with accents. - // First expand any accented base symbol according to unicodeSymbols. - if (Object.prototype.hasOwnProperty.call(unicodeSymbols, text[0]) && - !symbols[this.mode][text[0]]) { - // This behavior is not strict (XeTeX-compatible) in math mode. - if (this.settings.strict && this.mode === "math") { - throw new ParseError(`Accented Unicode text character "${text[0]}" used in ` + `math mode`, - nucleus - ); - } - text = unicodeSymbols[text[0]] + text.slice(1); - } - // Strip off any combining characters - const match = combiningDiacriticalMarksEndRegex.exec(text); - if (match) { - text = text.substring(0, match.index); - if (text === "i") { - text = "\u0131"; // dotless i, in math and text mode - } else if (text === "j") { - text = "\u0237"; // dotless j, in math and text mode - } - } - // Recognize base symbol - let symbol; - if (symbols[this.mode][text]) { - const group = symbols[this.mode][text].group; - const loc = SourceLocation.range(nucleus); - let s; - if (Object.prototype.hasOwnProperty.call(ATOMS, group )) { - const family = group; - s = { - type: "atom", - mode: this.mode, - family, - loc, - text - }; - } else { - s = { - type: group, - mode: this.mode, - loc, - text - }; - } - symbol = s; - } else if (!this.strict && numberRegEx.test(text)) { - // A number. Wrap in a if in math mode; otherwise. - this.consume(); - return { - type: "textord", - mode: this.mode, - loc: SourceLocation.range(nucleus), - text - } - } else if (text.charCodeAt(0) >= 0x80) { - // no symbol for e.g. ^ - if (this.settings.strict) { - if (!supportedCodepoint(text.charCodeAt(0))) { - throw new ParseError(`Unrecognized Unicode character "${text[0]}"` + - ` (${text.charCodeAt(0)})`, nucleus); - } else if (this.mode === "math") { - throw new ParseError(`Unicode text character "${text[0]}" used in math mode`, nucleus) - } - } - // All nonmathematical Unicode characters are rendered as if they - // are in text mode (wrapped in \text) because that's what it - // takes to render them in LaTeX. - symbol = { - type: "textord", - mode: "text", - loc: SourceLocation.range(nucleus), - text - }; - } else { - return null; // EOF, ^, _, {, }, etc. - } - this.consume(); - // Transform combining characters into accents - if (match) { - for (let i = 0; i < match[0].length; i++) { - const accent = match[0][i]; - if (!unicodeAccents[accent]) { - throw new ParseError(`Unknown accent ' ${accent}'`, nucleus); - } - const command = unicodeAccents[accent][this.mode] || - unicodeAccents[accent].text; - if (!command) { - throw new ParseError(`Accent ${accent} unsupported in ${this.mode} mode`, nucleus); - } - symbol = { - type: "accent", - mode: this.mode, - loc: SourceLocation.range(nucleus), - label: command, - isStretchy: false, - isShifty: true, - base: symbol - }; - } - } - return symbol; - } -} - -/** - * Parses an expression using a Parser, then returns the parsed result. - */ -const parseTree = function(toParse, settings) { - if (!(typeof toParse === "string" || toParse instanceof String)) { - throw new TypeError("Temml can only parse string typed expression") - } - const parser = new Parser(toParse, settings); - // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors - delete parser.gullet.macros.current["\\df@tag"]; - - let tree = parser.parse(); - - // LaTeX ignores a \tag placed outside an AMS environment. - if (!(tree.length > 0 && tree[0].type && tree[0].type === "array" && tree[0].addEqnNum)) { - // If the input used \tag, it will set the \df@tag macro to the tag. - // In this case, we separately parse the tag and wrap the tree. - if (parser.gullet.macros.get("\\df@tag")) { - if (!settings.displayMode) { - throw new ParseError("\\tag works only in display mode") - } - parser.gullet.feed("\\df@tag"); - tree = [ - { - type: "tag", - mode: "text", - body: tree, - tag: parser.parse() - } - ]; - } - } - - return tree -}; - -/** - * This file contains information about the style that the mathmlBuilder carries - * around with it. Data is held in an `Style` object, and when - * recursing, a new `Style` object can be created with the `.with*` functions. - */ - -const subOrSupLevel = [2, 2, 3, 3]; - -/** - * This is the main Style class. It contains the current style.level, color, and font. - * - * Style objects should not be modified. To create a new Style with - * different properties, call a `.with*` method. - */ -class Style { - constructor(data) { - // Style.level can be 0 | 1 | 2 | 3, which correspond to - // displaystyle, textstyle, scriptstyle, and scriptscriptstyle. - // style.level does not directly set MathML's script level. MathML does that itself. - // We use style.level to track, not set, math style so that we can get the - // correct scriptlevel when needed in supsub.js, mathchoice.js, or for dimensions in em. - this.level = data.level; - this.color = data.color; // string | void - // A font family applies to a group of fonts (i.e. SansSerif), while a font - // represents a specific font (i.e. SansSerif Bold). - // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm - this.font = data.font || ""; // string - this.fontFamily = data.fontFamily || ""; // string - this.fontSize = data.fontSize || 1.0; // number - this.fontWeight = data.fontWeight || ""; - this.fontShape = data.fontShape || ""; - this.maxSize = data.maxSize; // [number, number] - } - - /** - * Returns a new style object with the same properties as "this". Properties - * from "extension" will be copied to the new style object. - */ - extend(extension) { - const data = { - level: this.level, - color: this.color, - font: this.font, - fontFamily: this.fontFamily, - fontSize: this.fontSize, - fontWeight: this.fontWeight, - fontShape: this.fontShape, - maxSize: this.maxSize - }; - - for (const key in extension) { - if (Object.prototype.hasOwnProperty.call(extension, key)) { - data[key] = extension[key]; - } - } - - return new Style(data); - } - - withLevel(n) { - return this.extend({ - level: n - }); - } - - incrementLevel() { - return this.extend({ - level: Math.min(this.level + 1, 3) - }); - } - - inSubOrSup() { - return this.extend({ - level: subOrSupLevel[this.level] - }) - } - - /** - * Create a new style object with the given color. - */ - withColor(color) { - return this.extend({ - color: color - }); - } - - /** - * Creates a new style object with the given math font or old text font. - * @type {[type]} - */ - withFont(font) { - return this.extend({ - font - }); - } - - /** - * Create a new style objects with the given fontFamily. - */ - withTextFontFamily(fontFamily) { - return this.extend({ - fontFamily, - font: "" - }); - } - - /** - * Creates a new style object with the given font size - */ - withFontSize(num) { - return this.extend({ - fontSize: num - }); - } - - /** - * Creates a new style object with the given font weight - */ - withTextFontWeight(fontWeight) { - return this.extend({ - fontWeight, - font: "" - }); - } - - /** - * Creates a new style object with the given font weight - */ - withTextFontShape(fontShape) { - return this.extend({ - fontShape, - font: "" - }); - } - - /** - * Gets the CSS color of the current style object - */ - getColor() { - return this.color; - } -} - -/* Temml Post Process - * Perform two tasks not done by Temml when it created each individual Temml element. - * Given a block of block, - * 1. At each AMS auto-numbered environment, assign an id. - * 2. Populate the text contents of each \ref & \eqref - * - * As with other Temml code, this file is released under terms of the MIT license. - * https://mit-license.org/ - */ - -const version = "0.6.9"; - -function postProcess(block) { - const labelMap = {}; - let i = 0; - - // Get a collection of the parents of each \tag & auto-numbered equation - const parents = block.getElementsByClassName("tml-tageqn"); - for (const parent of parents) { - const eqns = parent.getElementsByClassName("tml-eqn"); - if (eqns. length > 0 ) { - // AMS automatically numbered equation. - // Assign an id. - i += 1; - eqns[0].id = "tml-eqn-" + i; - // No need to write a number into the text content of the element. - // A CSS counter does that even if this postProcess() function is not used. - } - // If there is a \label, add it to labelMap - const labels = parent.getElementsByClassName("tml-label"); - if (labels.length === 0) { continue } - if (eqns.length > 0) { - labelMap[labels[0].id] = String(i); - } else { - const tags = parent.getElementsByClassName("tml-tag"); - if (tags.length > 0) { - labelMap[labels[0].id] = tags[0].textContent; - } - } - } - - // Populate \ref & \eqref text content - const refs = block.getElementsByClassName("tml-ref"); - [...refs].forEach(ref => { - let str = labelMap[ref.getAttribute("href").slice(1)]; - if (ref.className.indexOf("tml-eqref") === -1) { - // \ref. Omit parens. - str = str.replace(/^\(/, ""); - str = str.replace(/\($/, ""); - } { - // \eqref. Include parens - if (str.charAt(0) !== "(") { str = "(" + str; } - if (str.slice(-1) !== ")") { str = str + ")"; } - } - ref.textContent = str; - }); -} - -/* eslint no-console:0 */ - -/** - * Parse and build an expression, and place that expression in the DOM node - * given. - */ -let render = function(expression, baseNode, options) { - baseNode.textContent = ""; - const math = renderToMathMLTree(expression, options); - if (options.elementIsMath) { - // The element already exists. Populate it. - baseNode.textContent = ""; - math.children.forEach(e => { baseNode.appendChild(e.toNode()); }); - } else { - baseNode.appendChild(math.toNode()); - } -}; - -// Temml's styles don't work properly in quirks mode. Print out an error, and -// disable rendering. -if (typeof document !== "undefined") { - if (document.compatMode !== "CSS1Compat") { - typeof console !== "undefined" && - console.warn( - "Warning: Temml doesn't work in quirks mode. Make sure your " + - "website has a suitable doctype." - ); - - render = function() { - throw new ParseError("Temml doesn't work in quirks mode."); - }; - } -} - -/** - * Parse and build an expression, and return the markup for that. - */ -const renderToString = function(expression, options) { - const markup = renderToMathMLTree(expression, options).toMarkup(); - return markup; -}; - -/** - * Parse an expression and return the parse tree. - */ -const generateParseTree = function(expression, options) { - const settings = new Settings(options); - return parseTree(expression, settings); -}; - -/** - * Take an expression which contains a preamble. - * Parse it and return the macros. - */ -const definePreamble = function(expression, options) { - const settings = new Settings(options); - settings.macros = {}; - if (!(typeof expression === "string" || expression instanceof String)) { - throw new TypeError("Temml can only parse string typed expression") - } - const parser = new Parser(expression, settings, true); - // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors - delete parser.gullet.macros.current["\\df@tag"]; - const macros = parser.parse(); - return macros -}; - -/** - * If the given error is a Temml ParseError, - * renders the invalid LaTeX as a span with hover title giving the Temml - * error message. Otherwise, simply throws the error. - */ -const renderError = function(error, expression, options) { - if (options.throwOnError || !(error instanceof ParseError)) { - throw error; - } - const node = new Span(["temml-error"], [new TextNode$1(expression + "\n" + error.toString())]); - node.style.color = options.errorColor; - node.style.whiteSpace = "pre-line"; - return node; -}; - -/** - * Generates and returns the Temml build tree. This is used for advanced - * use cases (like rendering to custom output). - */ -const renderToMathMLTree = function(expression, options) { - const settings = new Settings(options); - try { - const tree = parseTree(expression, settings); - const style = new Style({ - level: settings.displayMode ? StyleLevel.DISPLAY : StyleLevel.TEXT, - maxSize: settings.maxSize - }); - return buildMathML(tree, expression, style, settings); - } catch (error) { - return renderError(error, expression, settings); - } -}; - -var temml = { - /** - * Current Temml version - */ - version: version, - /** - * Renders the given LaTeX into MathML, and adds - * it as a child to the specified DOM node. - */ - render, - /** - * Renders the given LaTeX into MathML string, - * for sending to the client. - */ - renderToString, - /** - * Post-process an entire HTML block. - * Writes AMS auto-numbers and implements \ref{}. - * Typcally called once, after a loop has rendered many individual spans. - */ - postProcess, - /** - * Temml error, usually during parsing. - */ - ParseError, - /** - * Creates a set of macros with document-wide scope. - */ - definePreamble, - /** - * Parses the given LaTeX into Temml's internal parse tree structure, - * without rendering to HTML or MathML. - * - * NOTE: This method is not currently recommended for public use. - * The internal tree representation is unstable and is very likely - * to change. Use at your own risk. - */ - __parse: generateParseTree, - /** - * Renders the given LaTeX into a MathML internal DOM tree - * representation, without flattening that representation to a string. - * - * NOTE: This method is not currently recommended for public use. - * The internal tree representation is unstable and is very likely - * to change. Use at your own risk. - */ - __renderToMathMLTree: renderToMathMLTree, - /** - * adds a new symbol to builtin symbols table - */ - __defineSymbol: defineSymbol, - /** - * adds a new macro to builtin macro list - */ - __defineMacro: defineMacro -}; - -export { temml as default }; diff --git a/utils/temml.mjs.js b/utils/temml.mjs.js deleted file mode 100644 index 504be204..00000000 --- a/utils/temml.mjs.js +++ /dev/null @@ -1,13020 +0,0 @@ -/** - * This is the ParseError class, which is the main error thrown by Temml - * functions when something has gone wrong. This is used to distinguish internal - * errors from errors in the expression that the user provided. - * - * If possible, a caller should provide a Token or ParseNode with information - * about where in the source string the problem occurred. - */ -class ParseError { - constructor( - message, // The error message - token // An object providing position information - ) { - let error = " " + message; - let start; - - const loc = token && token.loc; - if (loc && loc.start <= loc.end) { - // If we have the input and a position, make the error a bit fancier - - // Get the input - const input = loc.lexer.input; - - // Prepend some information - start = loc.start; - const end = loc.end; - if (start === input.length) { - error += " at end of input: "; - } else { - error += " at position " + (start + 1) + ": "; - } - - // Underline token in question using combining underscores - const underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332"); - - // Extract some context from the input and add it to the error - let left; - if (start > 15) { - left = "…" + input.slice(start - 15, start); - } else { - left = input.slice(0, start); - } - let right; - if (end + 15 < input.length) { - right = input.slice(end, end + 15) + "…"; - } else { - right = input.slice(end); - } - error += left + underlined + right; - } - - // Some hackery to make ParseError a prototype of Error - // See http://stackoverflow.com/a/8460753 - const self = new Error(error); - self.name = "TemmlParseError"; - self.__proto__ = ParseError.prototype; - self.position = start; - return self; - } -} - -ParseError.prototype.__proto__ = Error.prototype; - -// -/** - * This file contains a list of utility functions which are useful in other - * files. - */ - -/** - * Return whether an element is contained in a list - */ -const contains = function(list, elem) { - return list.indexOf(elem) !== -1; -}; - -/** - * Provide a default value if a setting is undefined - */ -const deflt = function(setting, defaultIfUndefined) { - return setting === undefined ? defaultIfUndefined : setting; -}; - -// hyphenate and escape adapted from Facebook's React under Apache 2 license - -const uppercase = /([A-Z])/g; -const hyphenate = function(str) { - return str.replace(uppercase, "-$1").toLowerCase(); -}; - -const ESCAPE_LOOKUP = { - "&": "&", - ">": ">", - "<": "<", - '"': """, - "'": "'" -}; - -const ESCAPE_REGEX = /[&><"']/g; - -/** - * Escapes text to prevent scripting attacks. - */ -function escape(text) { - return String(text).replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]); -} - -/** - * Sometimes we want to pull out the innermost element of a group. In most - * cases, this will just be the group itself, but when ordgroups and colors have - * a single element, we want to pull that out. - */ -const getBaseElem = function(group) { - if (group.type === "ordgroup") { - if (group.body.length === 1) { - return getBaseElem(group.body[0]); - } else { - return group; - } - } else if (group.type === "color") { - if (group.body.length === 1) { - return getBaseElem(group.body[0]); - } else { - return group; - } - } else if (group.type === "font") { - return getBaseElem(group.body); - } else { - return group; - } -}; - -/** - * TeXbook algorithms often reference "character boxes", which are simply groups - * with a single character in them. To decide if something is a character box, - * we find its innermost group, and see if it is a single character. - */ -const isCharacterBox = function(group) { - const baseElem = getBaseElem(group); - - // These are all the types of groups which hold single characters - return baseElem.type === "mathord" || baseElem.type === "textord" || baseElem.type === "atom" -}; - -const assert = function(value) { - if (!value) { - throw new Error("Expected non-null, but got " + String(value)); - } - return value; -}; - -/** - * Return the protocol of a URL, or "_relative" if the URL does not specify a - * protocol (and thus is relative). - */ -const protocolFromUrl = function(url) { - const protocol = /^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(url); - return protocol != null ? protocol[1] : "_relative"; -}; - -/** - * Round `n` to 4 decimal places, or to the nearest 1/10,000th em. The TeXbook - * gives an acceptable rounding error of 100sp (which would be the nearest - * 1/6551.6em with our ptPerEm = 10): - * http://www.ctex.org/documents/shredder/src/texbook.pdf#page=69 - */ -const round = function(n) { - return +n.toFixed(4); -}; - -var utils = { - contains, - deflt, - escape, - hyphenate, - getBaseElem, - isCharacterBox, - protocolFromUrl, - round -}; - -/** - * This is a module for storing settings passed into Temml. It correctly handles - * default settings. - */ - -/** - * The main Settings object - */ -class Settings { - constructor(options) { - // allow null options - options = options || {}; - this.displayMode = utils.deflt(options.displayMode, false); // boolean - this.annotate = utils.deflt(options.annotate, false); // boolean - this.elementIsMath = utils.deflt(options.elementIsMath, false); // boolean - this.leqno = utils.deflt(options.leqno, false); // boolean - this.errorColor = utils.deflt(options.errorColor, "#b22222"); // string - this.preventTagLap = utils.deflt(options.preventTagLap, false); // boolean - this.macros = options.macros || {}; - this.xml = utils.deflt(options.xml, false); // boolean - this.colorIsTextColor = utils.deflt(options.colorIsTextColor, false); // booelean - this.strict = utils.deflt(options.strict, false); // boolean - this.trust = utils.deflt(options.trust, false); // trust context. See html.js. - this.maxSize = Math.max(0, utils.deflt(options.maxSize, Infinity)); // number - this.maxExpand = Math.max(0, utils.deflt(options.maxExpand, 1000)); // number - } - - /** - * Report nonstrict (non-LaTeX-compatible) input. - * Can safely not be called if `this.strict` is false in JavaScript. - */ - reportNonstrict(errorCode, errorMsg, token) { - const strict = this.strict; - if (strict === false) { - return; - } else if (strict === true) { - throw new ParseError( - "LaTeX-incompatible input and strict mode is set to 'error': " + - `${errorMsg} [${errorCode}]`, - token - ); - } else { - // won't happen in type-safe code - return; - } - } - - /** - * Check whether to test potentially dangerous input, and return - * `true` (trusted) or `false` (untrusted). The sole argument `context` - * should be an object with `command` field specifying the relevant LaTeX - * command (as a string starting with `\`), and any other arguments, etc. - * If `context` has a `url` field, a `protocol` field will automatically - * get added by this function (changing the specified object). - */ - isTrusted(context) { - if (context.url && !context.protocol) { - context.protocol = utils.protocolFromUrl(context.url); - } - const trust = typeof this.trust === "function" ? this.trust(context) : this.trust; - return Boolean(trust); - } -} - -/** - * All registered functions. - * `functions.js` just exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary. - */ -const _functions = {}; - -/** - * All MathML builders. Should be only used in the `define*` and the `build*ML` - * functions. - */ -const _mathmlGroupBuilders = {}; - -function defineFunction({ - type, - names, - props, - handler, - mathmlBuilder -}) { - // Set default values of functions - const data = { - type, - numArgs: props.numArgs, - argTypes: props.argTypes, - allowedInArgument: !!props.allowedInArgument, - allowedInText: !!props.allowedInText, - allowedInMath: props.allowedInMath === undefined ? true : props.allowedInMath, - numOptionalArgs: props.numOptionalArgs || 0, - infix: !!props.infix, - primitive: !!props.primitive, - handler: handler - }; - for (let i = 0; i < names.length; ++i) { - _functions[names[i]] = data; - } - if (type) { - if (mathmlBuilder) { - _mathmlGroupBuilders[type] = mathmlBuilder; - } - } -} - -/** - * Use this to register only the MathML builder for a function(e.g. - * if the function's ParseNode is generated in Parser.js rather than via a - * stand-alone handler provided to `defineFunction`). - */ -function defineFunctionBuilders({ type, mathmlBuilder }) { - defineFunction({ - type, - names: [], - props: { numArgs: 0 }, - handler() { - throw new Error("Should never be called.") - }, - mathmlBuilder - }); -} - -const normalizeArgument = function(arg) { - return arg.type === "ordgroup" && arg.body.length === 1 ? arg.body[0] : arg -}; - -// Since the corresponding buildMathML function expects a -// list of elements, we normalize for different kinds of arguments -const ordargument = function(arg) { - return arg.type === "ordgroup" ? arg.body : [arg] -}; - -/** - * This node represents a document fragment, which contains elements, but when - * placed into the DOM doesn't have any representation itself. It only contains - * children and doesn't have any DOM node properties. - */ -class DocumentFragment { - constructor(children) { - this.children = children; - this.classes = []; - this.style = {}; - } - - hasClass(className) { - return utils.contains(this.classes, className); - } - - /** Convert the fragment into a node. */ - toNode() { - const frag = document.createDocumentFragment(); - - for (let i = 0; i < this.children.length; i++) { - frag.appendChild(this.children[i].toNode()); - } - - return frag; - } - - /** Convert the fragment into HTML markup. */ - toMarkup() { - let markup = ""; - - // Simply concatenate the markup for the children together. - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - return markup; - } - - /** - * Converts the math node into a string, similar to innerText. Applies to - * MathDomNode's only. - */ - toText() { - // To avoid this, we would subclass documentFragment separately for - // MathML, but polyfills for subclassing is expensive per PR 1469. - const toText = (child) => child.toText(); - return this.children.map(toText).join(""); - } -} - -/** - * These objects store the data about the DOM nodes we create, as well as some - * extra data. They can then be transformed into real DOM nodes with the - * `toNode` function or HTML markup using `toMarkup`. They are useful for both - * storing extra properties on the nodes, as well as providing a way to easily - * work with the DOM. - * - * Similar functions for working with MathML nodes exist in mathMLTree.js. - * - */ - -/** - * Create an HTML className based on a list of classes. In addition to joining - * with spaces, we also remove empty classes. - */ -const createClass = function(classes) { - return classes.filter((cls) => cls).join(" "); -}; - -const initNode = function(classes, style) { - this.classes = classes || []; - this.attributes = {}; - this.style = style || {}; -}; - -/** - * Convert into an HTML node - */ -const toNode = function(tagName) { - const node = document.createElement(tagName); - - // Apply the class - node.className = createClass(this.classes); - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - // Apply attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr )) { - node.setAttribute(attr, this.attributes[attr]); - } - } - - // Append the children, also as HTML nodes - for (let i = 0; i < this.children.length; i++) { - node.appendChild(this.children[i].toNode()); - } - - return node; -}; - -/** - * Convert into an HTML markup string - */ -const toMarkup = function(tagName) { - let markup = `<${tagName}`; - - // Add the class - if (this.classes.length) { - markup += ` class="${utils.escape(createClass(this.classes))}"`; - } - - let styles = ""; - - // Add the styles, after hyphenation - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - styles += `${utils.hyphenate(style)}:${this.style[style]};`; - } - } - - if (styles) { - markup += ` style="${styles}"`; - } - - // Add the attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr )) { - markup += ` ${attr}="${utils.escape(this.attributes[attr])}"`; - } - } - - markup += ">"; - - // Add the markup of the children, also as markup - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - markup += ``; - - return markup; -}; - -/** - * This node represents a span node, with a className, a list of children, and - * an inline style. - * - */ -class Span { - constructor(classes, children, style) { - initNode.call(this, classes, style); - this.children = children || []; - } - - setAttribute(attribute, value) { - this.attributes[attribute] = value; - } - - toNode() { - return toNode.call(this, "span"); - } - - toMarkup() { - return toMarkup.call(this, "span"); - } -} - -class TextNode { - constructor(text) { - this.text = text; - } - toNode() { - return document.createTextNode(this.text); - } - toMarkup() { - return utils.escape(this.text); - } -} - -/** - * This node represents an image embed () element. - */ -class Img { - constructor(src, alt, style) { - this.alt = alt; - this.src = src; - this.classes = ["mord"]; - this.style = style; - } - - hasClass(className) { - return utils.contains(this.classes, className); - } - - toNode() { - const node = document.createElement("img"); - node.src = this.src; - node.alt = this.alt; - node.className = "mord"; - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - return node; - } - - toMarkup() { - let markup = `${this.alt}` and - * `` tags). - */ -class MathNode { - constructor(type, children, classes, style, isSVG) { - this.type = type; - this.attributes = {}; - this.children = children || []; - this.classes = classes || []; - this.style = style || {}; // Used for elements - this.isSVG = isSVG || false; - } - - /** - * Sets an attribute on a MathML node. MathML depends on attributes to convey a - * semantic content, so this is used heavily. - */ - setAttribute(name, value) { - this.attributes[name] = value; - } - - /** - * Gets an attribute on a MathML node. - */ - getAttribute(name) { - return this.attributes[name]; - } - - /** - * Converts the math node into a MathML-namespaced DOM element. - */ - toNode() { - const node = this.isSVG - ? document.createElementNS("http://www.w3.org/2000/svg", this.type) - : document.createElementNS("http://www.w3.org/1998/Math/MathML", this.type); - - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { - node.setAttribute(attr, this.attributes[attr]); - } - } - - if (this.classes.length > 0) { - node.className = createClass(this.classes); - } - - // Apply inline styles - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - node.style[style] = this.style[style]; - } - } - - for (let i = 0; i < this.children.length; i++) { - node.appendChild(this.children[i].toNode()); - } - - return node; - } - - /** - * Converts the math node into an HTML markup string. - */ - toMarkup() { - let markup = "<" + this.type; - - // Add the attributes - for (const attr in this.attributes) { - if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) { - markup += " " + attr + '="'; - markup += utils.escape(this.attributes[attr]); - markup += '"'; - } - } - - if (this.classes.length > 0) { - markup += ` class ="${utils.escape(createClass(this.classes))}"`; - } - - let styles = ""; - - // Add the styles, after hyphenation - for (const style in this.style) { - if (Object.prototype.hasOwnProperty.call(this.style, style )) { - styles += `${utils.hyphenate(style)}:${this.style[style]};`; - } - } - - if (styles) { - markup += ` style="${styles}"`; - } - - markup += ">"; - - for (let i = 0; i < this.children.length; i++) { - markup += this.children[i].toMarkup(); - } - - markup += ""; - - return markup; - } - - /** - * Converts the math node into a string, similar to innerText, but escaped. - */ - toText() { - return this.children.map((child) => child.toText()).join(""); - } -} - -/** - * This node represents a piece of text. - */ -class TextNode$1 { - constructor(text) { - this.text = text; - } - - /** - * Converts the text node into a DOM text node. - */ - toNode() { - return document.createTextNode(this.text); - } - - /** - * Converts the text node into escaped HTML markup - * (representing the text itself). - */ - toMarkup() { - return utils.escape(this.toText()); - } - - /** - * Converts the text node into a string - * (representing the text iteself). - */ - toText() { - return this.text; - } -} - -// Do not make an the only child of a . -// An acts as its own implicit . -const wrapWithMstyle = expression => { - let node; - if (expression.length === 1 && expression[0].type === "mrow") { - node = expression.pop(); - node.type = "mstyle"; - } else { - node = new MathNode("mstyle", expression); - } - return node -}; - -var mathMLTree = { - MathNode, - TextNode: TextNode$1, - newDocumentFragment -}; - -/** - * This file provides support for building horizontal stretchy elements. - */ - -// From mhchem reaction arrows \ce{A <=>> B} and \ce{A <<=> B} -const keysWithoutUnicodePoints = ["equilibriumRight", "equilibriumLeft"]; - -const stretchyCodePoint = { - widehat: "^", - widecheck: "ˇ", - widetilde: "~", - wideparen: "⏜", // \u23dc - utilde: "~", - overleftarrow: "\u2190", - underleftarrow: "\u2190", - xleftarrow: "\u2190", - overrightarrow: "\u2192", - underrightarrow: "\u2192", - xrightarrow: "\u2192", - underbrace: "\u23df", - overbrace: "\u23de", - overgroup: "\u23e0", - overparen: "⏜", - undergroup: "\u23e1", - underparen: "\u23dd", - overleftrightarrow: "\u2194", - underleftrightarrow: "\u2194", - xleftrightarrow: "\u2194", - Overrightarrow: "\u21d2", - xRightarrow: "\u21d2", - overleftharpoon: "\u21bc", - xleftharpoonup: "\u21bc", - overrightharpoon: "\u21c0", - xrightharpoonup: "\u21c0", - xLeftarrow: "\u21d0", - xLeftrightarrow: "\u21d4", - xhookleftarrow: "\u21a9", - xhookrightarrow: "\u21aa", - xmapsto: "\u21a6", - xrightharpoondown: "\u21c1", - xleftharpoondown: "\u21bd", - xtwoheadleftarrow: "\u219e", - xtwoheadrightarrow: "\u21a0", - xlongequal: "=", - xrightleftarrows: "\u21c4", - yields: "\u2192", - yieldsLeft: "\u2190", - mesomerism: "\u2194", - longrightharpoonup: "\u21c0", - longleftharpoondown: "\u21bd", - "\\cdrightarrow": "\u2192", - "\\cdleftarrow": "\u2190", - "\\cdlongequal": "=" -}; - -const nodeFromObject = (obj) => { - // Build a stretchy arrow from two SVGs. - const children = []; - if (obj.children) { - obj.children.map(child => { children.push(nodeFromObject(child)); }); - } - const node = obj.type === "span" - ? new Span(null, children, obj.style) - : new mathMLTree.MathNode(obj.type, children, [], obj.style, true); - Object.entries(obj.attributes).forEach(([key, value]) => { - node.setAttribute(key, value); - }); - return node -}; - -const mathMLnode = function(label, macros = {}) { - const key = label.slice(1); - let child; - if (!keysWithoutUnicodePoints.includes(key)) { - child = new mathMLTree.TextNode(stretchyCodePoint[key]); - } else { - const atKey = "\\@" + key; - if (!macros.has(atKey)) { - throw new ParseError("Arrow not available. The mhchem package is needed.") - } - child = nodeFromObject(JSON.parse(macros.get(atKey))); - } - const node = new mathMLTree.MathNode("mo", [child]); - node.setAttribute("stretchy", "true"); - return node -}; - -var stretchy = { - mathMLnode -}; - -/** - * This file holds a list of all no-argument functions and single-character - * symbols (like 'a' or ';'). - * - * For each of the symbols, there are two properties they can have: - * - group (required): the ParseNode group type the symbol should have (i.e. - "textord", "mathord", etc). - * - replace: the character that this symbol or function should be - * replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi - * character in the main font). - * - * The outermost map in the table indicates what mode the symbols should be - * accepted in (e.g. "math" or "text"). - */ - -// Some of these have a "-token" suffix since these are also used as `ParseNode` -// types for raw text tokens, and we want to avoid conflicts with higher-level -// `ParseNode` types. These `ParseNode`s are constructed within `Parser` by -// looking up the `symbols` map. -const ATOMS = { - bin: 1, - close: 1, - inner: 1, - open: 1, - punct: 1, - rel: 1 -}; -const NON_ATOMS = { - "accent-token": 1, - mathord: 1, - "op-token": 1, - spacing: 1, - textord: 1 -}; - -const symbols = { - math: {}, - text: {} -}; - -/** `acceptUnicodeChar = true` is only applicable if `replace` is set. */ -function defineSymbol(mode, group, replace, name, acceptUnicodeChar) { - symbols[mode][name] = { group, replace }; - - if (acceptUnicodeChar && replace) { - symbols[mode][replace] = symbols[mode][name]; - } -} - -// Some abbreviations for commonly used strings. -// This helps minify the code, and also spotting typos using jshint. - -// modes: -const math = "math"; -const text = "text"; - -// groups: -const accent = "accent-token"; -const bin = "bin"; -const close = "close"; -const inner = "inner"; -const mathord = "mathord"; -const op = "op-token"; -const open = "open"; -const punct = "punct"; -const rel = "rel"; -const spacing = "spacing"; -const textord = "textord"; - -// Now comes the symbol table - -// Relation Symbols -defineSymbol(math, rel, "\u2261", "\\equiv", true); -defineSymbol(math, rel, "\u227a", "\\prec", true); -defineSymbol(math, rel, "\u227b", "\\succ", true); -defineSymbol(math, rel, "\u223c", "\\sim", true); -defineSymbol(math, rel, "\u27c2", "\\perp", true); -defineSymbol(math, rel, "\u2aaf", "\\preceq", true); -defineSymbol(math, rel, "\u2ab0", "\\succeq", true); -defineSymbol(math, rel, "\u2243", "\\simeq", true); -defineSymbol(math, rel, "\u224c", "\\backcong", true); -defineSymbol(math, rel, "|", "\\mid", true); -defineSymbol(math, rel, "\u226a", "\\ll", true); -defineSymbol(math, rel, "\u226b", "\\gg", true); -defineSymbol(math, rel, "\u224d", "\\asymp", true); -defineSymbol(math, rel, "\u2225", "\\parallel"); -defineSymbol(math, rel, "\u22c8", "\\bowtie", true); -defineSymbol(math, rel, "\u2323", "\\smile", true); -defineSymbol(math, rel, "\u2291", "\\sqsubseteq", true); -defineSymbol(math, rel, "\u2292", "\\sqsupseteq", true); -defineSymbol(math, rel, "\u2250", "\\doteq", true); -defineSymbol(math, rel, "\u2322", "\\frown", true); -defineSymbol(math, rel, "\u220b", "\\ni", true); -defineSymbol(math, rel, "\u220c", "\\notni", true); -defineSymbol(math, rel, "\u221d", "\\propto", true); -defineSymbol(math, rel, "\u22a2", "\\vdash", true); -defineSymbol(math, rel, "\u22a3", "\\dashv", true); -defineSymbol(math, rel, "\u220b", "\\owns"); -defineSymbol(math, rel, "\u2258", "\\arceq", true); -defineSymbol(math, rel, "\u2259", "\\wedgeq", true); -defineSymbol(math, rel, "\u225a", "\\veeeq", true); -defineSymbol(math, rel, "\u225b", "\\stareq", true); -defineSymbol(math, rel, "\u225d", "\\eqdef", true); -defineSymbol(math, rel, "\u225e", "\\measeq", true); -defineSymbol(math, rel, "\u225f", "\\questeq", true); -defineSymbol(math, rel, "\u2260", "\\ne", true); -defineSymbol(math, rel, "\u2260", "\\neq"); -// mathtools.sty -defineSymbol(math, rel, "\u2237", "\\dblcolon", true); -defineSymbol(math, rel, "\u2254", "\\coloneqq", true); -defineSymbol(math, rel, "\u2255", "\\eqqcolon", true); -defineSymbol(math, rel, "\u2239", "\\eqcolon", true); -defineSymbol(math, rel, "\u2A74", "\\Coloneqq", true); - -// Punctuation -defineSymbol(math, punct, "\u002e", "\\ldotp"); -defineSymbol(math, punct, "\u00b7", "\\cdotp"); - -// Misc Symbols -defineSymbol(math, textord, "\u0023", "\\#"); -defineSymbol(text, textord, "\u0023", "\\#"); -defineSymbol(math, textord, "\u0026", "\\&"); -defineSymbol(text, textord, "\u0026", "\\&"); -defineSymbol(math, textord, "\u2135", "\\aleph", true); -defineSymbol(math, textord, "\u2200", "\\forall", true); -defineSymbol(math, textord, "\u210f", "\\hbar", true); -defineSymbol(math, textord, "\u2203", "\\exists", true); -defineSymbol(math, textord, "\u2207", "\\nabla", true); -defineSymbol(math, textord, "\u266d", "\\flat", true); -defineSymbol(math, textord, "\u2113", "\\ell", true); -defineSymbol(math, textord, "\u266e", "\\natural", true); -defineSymbol(math, textord, "Å", "\\AA", true); -defineSymbol(text, textord, "Å", "\\AA", true); -defineSymbol(math, textord, "\u2663", "\\clubsuit", true); -defineSymbol(math, textord, "\u2667", "\\varclubsuit", true); -defineSymbol(math, textord, "\u2118", "\\wp", true); -defineSymbol(math, textord, "\u266f", "\\sharp", true); -defineSymbol(math, textord, "\u2662", "\\diamondsuit", true); -defineSymbol(math, textord, "\u2666", "\\vardiamondsuit", true); -defineSymbol(math, textord, "\u211c", "\\Re", true); -defineSymbol(math, textord, "\u2661", "\\heartsuit", true); -defineSymbol(math, textord, "\u2665", "\\varheartsuit", true); -defineSymbol(math, textord, "\u2111", "\\Im", true); -defineSymbol(math, textord, "\u2660", "\\spadesuit", true); -defineSymbol(math, textord, "\u2664", "\\varspadesuit", true); -defineSymbol(math, textord, "\u2640", "\\female", true); -defineSymbol(math, textord, "\u2642", "\\male", true); -defineSymbol(math, textord, "\u00a7", "\\S", true); -defineSymbol(text, textord, "\u00a7", "\\S"); -defineSymbol(math, textord, "\u00b6", "\\P", true); -defineSymbol(text, textord, "\u00b6", "\\P"); -defineSymbol(text, textord, "\u263a", "\\smiley", true); -defineSymbol(math, textord, "\u263a", "\\smiley", true); - -// Math and Text -defineSymbol(math, textord, "\u2020", "\\dag"); -defineSymbol(text, textord, "\u2020", "\\dag"); -defineSymbol(text, textord, "\u2020", "\\textdagger"); -defineSymbol(math, textord, "\u2021", "\\ddag"); -defineSymbol(text, textord, "\u2021", "\\ddag"); -defineSymbol(text, textord, "\u2021", "\\textdaggerdbl"); - -// Large Delimiters -defineSymbol(math, close, "\u23b1", "\\rmoustache", true); -defineSymbol(math, open, "\u23b0", "\\lmoustache", true); -defineSymbol(math, close, "\u27ef", "\\rgroup", true); -defineSymbol(math, open, "\u27ee", "\\lgroup", true); - -// Binary Operators -defineSymbol(math, bin, "\u2213", "\\mp", true); -defineSymbol(math, bin, "\u2296", "\\ominus", true); -defineSymbol(math, bin, "\u228e", "\\uplus", true); -defineSymbol(math, bin, "\u2293", "\\sqcap", true); -defineSymbol(math, bin, "\u2217", "\\ast"); -defineSymbol(math, bin, "\u2294", "\\sqcup", true); -defineSymbol(math, bin, "\u25ef", "\\bigcirc", true); -defineSymbol(math, bin, "\u2219", "\\bullet"); -defineSymbol(math, bin, "\u2021", "\\ddagger"); -defineSymbol(math, bin, "\u2240", "\\wr", true); -defineSymbol(math, bin, "\u2a3f", "\\amalg"); -defineSymbol(math, bin, "\u0026", "\\And"); // from amsmath - -// Arrow Symbols -defineSymbol(math, rel, "\u27f5", "\\longleftarrow", true); -defineSymbol(math, rel, "\u21d0", "\\Leftarrow", true); -defineSymbol(math, rel, "\u27f8", "\\Longleftarrow", true); -defineSymbol(math, rel, "\u27f6", "\\longrightarrow", true); -defineSymbol(math, rel, "\u21d2", "\\Rightarrow", true); -defineSymbol(math, rel, "\u27f9", "\\Longrightarrow", true); -defineSymbol(math, rel, "\u2194", "\\leftrightarrow", true); -defineSymbol(math, rel, "\u27f7", "\\longleftrightarrow", true); -defineSymbol(math, rel, "\u21d4", "\\Leftrightarrow", true); -defineSymbol(math, rel, "\u27fa", "\\Longleftrightarrow", true); -defineSymbol(math, rel, "\u21a6", "\\mapsto", true); -defineSymbol(math, rel, "\u27fc", "\\longmapsto", true); -defineSymbol(math, rel, "\u2197", "\\nearrow", true); -defineSymbol(math, rel, "\u21a9", "\\hookleftarrow", true); -defineSymbol(math, rel, "\u21aa", "\\hookrightarrow", true); -defineSymbol(math, rel, "\u2198", "\\searrow", true); -defineSymbol(math, rel, "\u21bc", "\\leftharpoonup", true); -defineSymbol(math, rel, "\u21c0", "\\rightharpoonup", true); -defineSymbol(math, rel, "\u2199", "\\swarrow", true); -defineSymbol(math, rel, "\u21bd", "\\leftharpoondown", true); -defineSymbol(math, rel, "\u21c1", "\\rightharpoondown", true); -defineSymbol(math, rel, "\u2196", "\\nwarrow", true); -defineSymbol(math, rel, "\u21cc", "\\rightleftharpoons", true); -defineSymbol(math, mathord, "\u21af", "\\lightning", true); -defineSymbol(math, mathord, "\u2030", "\\permil", true); -defineSymbol(text, textord, "\u2030", "\\permil"); - -// AMS Negated Binary Relations -defineSymbol(math, rel, "\u226e", "\\nless", true); -// Symbol names preceeded by "@" each have a corresponding macro. -defineSymbol(math, rel, "\u2a87", "\\lneq", true); -defineSymbol(math, rel, "\u2268", "\\lneqq", true); -defineSymbol(math, rel, "\u2268\ufe00", "\\lvertneqq"); -defineSymbol(math, rel, "\u22e6", "\\lnsim", true); -defineSymbol(math, rel, "\u2a89", "\\lnapprox", true); -defineSymbol(math, rel, "\u2280", "\\nprec", true); -// unicode-math maps \u22e0 to \npreccurlyeq. We'll use the AMS synonym. -defineSymbol(math, rel, "\u22e0", "\\npreceq", true); -defineSymbol(math, rel, "\u22e8", "\\precnsim", true); -defineSymbol(math, rel, "\u2ab9", "\\precnapprox", true); -defineSymbol(math, rel, "\u2241", "\\nsim", true); -defineSymbol(math, rel, "\u2224", "\\nmid", true); -defineSymbol(math, rel, "\u2224", "\\nshortmid"); -defineSymbol(math, rel, "\u22ac", "\\nvdash", true); -defineSymbol(math, rel, "\u22ad", "\\nvDash", true); -defineSymbol(math, rel, "\u22ea", "\\ntriangleleft"); -defineSymbol(math, rel, "\u22ec", "\\ntrianglelefteq", true); -defineSymbol(math, rel, "\u2284", "\\nsubset", true); -defineSymbol(math, rel, "\u2285", "\\nsupset", true); -defineSymbol(math, rel, "\u228a", "\\subsetneq", true); -defineSymbol(math, rel, "\u228a\ufe00", "\\varsubsetneq"); -defineSymbol(math, rel, "\u2acb", "\\subsetneqq", true); -defineSymbol(math, rel, "\u2acb\ufe00", "\\varsubsetneqq"); -defineSymbol(math, rel, "\u226f", "\\ngtr", true); -defineSymbol(math, rel, "\u2a88", "\\gneq", true); -defineSymbol(math, rel, "\u2269", "\\gneqq", true); -defineSymbol(math, rel, "\u2269\ufe00", "\\gvertneqq"); -defineSymbol(math, rel, "\u22e7", "\\gnsim", true); -defineSymbol(math, rel, "\u2a8a", "\\gnapprox", true); -defineSymbol(math, rel, "\u2281", "\\nsucc", true); -// unicode-math maps \u22e1 to \nsucccurlyeq. We'll use the AMS synonym. -defineSymbol(math, rel, "\u22e1", "\\nsucceq", true); -defineSymbol(math, rel, "\u22e9", "\\succnsim", true); -defineSymbol(math, rel, "\u2aba", "\\succnapprox", true); -// unicode-math maps \u2246 to \simneqq. We'll use the AMS synonym. -defineSymbol(math, rel, "\u2246", "\\ncong", true); -defineSymbol(math, rel, "\u2226", "\\nparallel", true); -defineSymbol(math, rel, "\u2226", "\\nshortparallel"); -defineSymbol(math, rel, "\u22af", "\\nVDash", true); -defineSymbol(math, rel, "\u22eb", "\\ntriangleright"); -defineSymbol(math, rel, "\u22ed", "\\ntrianglerighteq", true); -defineSymbol(math, rel, "\u228b", "\\supsetneq", true); -defineSymbol(math, rel, "\u228b", "\\varsupsetneq"); -defineSymbol(math, rel, "\u2acc", "\\supsetneqq", true); -defineSymbol(math, rel, "\u2acc\ufe00", "\\varsupsetneqq"); -defineSymbol(math, rel, "\u22ae", "\\nVdash", true); -defineSymbol(math, rel, "\u2ab5", "\\precneqq", true); -defineSymbol(math, rel, "\u2ab6", "\\succneqq", true); -defineSymbol(math, bin, "\u22b4", "\\unlhd"); -defineSymbol(math, bin, "\u22b5", "\\unrhd"); - -// AMS Negated Arrows -defineSymbol(math, rel, "\u219a", "\\nleftarrow", true); -defineSymbol(math, rel, "\u219b", "\\nrightarrow", true); -defineSymbol(math, rel, "\u21cd", "\\nLeftarrow", true); -defineSymbol(math, rel, "\u21cf", "\\nRightarrow", true); -defineSymbol(math, rel, "\u21ae", "\\nleftrightarrow", true); -defineSymbol(math, rel, "\u21ce", "\\nLeftrightarrow", true); - -// AMS Misc -defineSymbol(math, rel, "\u25b3", "\\vartriangle"); -defineSymbol(math, textord, "\u210f", "\\hslash"); -defineSymbol(math, textord, "\u25bd", "\\triangledown"); -defineSymbol(math, textord, "\u25ca", "\\lozenge"); -defineSymbol(math, textord, "\u24c8", "\\circledS"); -defineSymbol(math, textord, "\u00ae", "\\circledR", true); -defineSymbol(text, textord, "\u00ae", "\\circledR"); -defineSymbol(text, textord, "\u00ae", "\\textregistered"); -defineSymbol(math, textord, "\u2221", "\\measuredangle", true); -defineSymbol(math, textord, "\u2204", "\\nexists"); -defineSymbol(math, textord, "\u2127", "\\mho"); -defineSymbol(math, textord, "\u2132", "\\Finv", true); -defineSymbol(math, textord, "\u2141", "\\Game", true); -defineSymbol(math, textord, "\u2035", "\\backprime"); -defineSymbol(math, textord, "\u25b2", "\\blacktriangle"); -defineSymbol(math, textord, "\u25bc", "\\blacktriangledown"); -defineSymbol(math, textord, "\u25a0", "\\blacksquare"); -defineSymbol(math, textord, "\u29eb", "\\blacklozenge"); -defineSymbol(math, textord, "\u2605", "\\bigstar"); -defineSymbol(math, textord, "\u2222", "\\sphericalangle", true); -defineSymbol(math, textord, "\u2201", "\\complement", true); -// unicode-math maps U+F0 to \matheth. We map to AMS function \eth -defineSymbol(math, textord, "\u00f0", "\\eth", true); -defineSymbol(text, textord, "\u00f0", "\u00f0"); -defineSymbol(math, textord, "\u2571", "\\diagup"); -defineSymbol(math, textord, "\u2572", "\\diagdown"); -defineSymbol(math, textord, "\u25a1", "\\square"); -defineSymbol(math, textord, "\u25a1", "\\Box"); -defineSymbol(math, textord, "\u25ca", "\\Diamond"); -// unicode-math maps U+A5 to \mathyen. We map to AMS function \yen -defineSymbol(math, textord, "\u00a5", "\\yen", true); -defineSymbol(text, textord, "\u00a5", "\\yen", true); -defineSymbol(math, textord, "\u2713", "\\checkmark", true); -defineSymbol(text, textord, "\u2713", "\\checkmark"); -defineSymbol(math, textord, "\u2717", "\\ballotx", true); -defineSymbol(text, textord, "\u2717", "\\ballotx"); -defineSymbol(text, textord, "\u2022", "\\textbullet"); - -// AMS Hebrew -defineSymbol(math, textord, "\u2136", "\\beth", true); -defineSymbol(math, textord, "\u2138", "\\daleth", true); -defineSymbol(math, textord, "\u2137", "\\gimel", true); - -// AMS Greek -defineSymbol(math, textord, "\u03dd", "\\digamma", true); -defineSymbol(math, textord, "\u03f0", "\\varkappa"); - -// AMS Delimiters -defineSymbol(math, open, "\u231C", "\\ulcorner", true); -defineSymbol(math, close, "\u231D", "\\urcorner", true); -defineSymbol(math, open, "\u231E", "\\llcorner", true); -defineSymbol(math, close, "\u231F", "\\lrcorner", true); - -// AMS Binary Relations -defineSymbol(math, rel, "\u2266", "\\leqq", true); -defineSymbol(math, rel, "\u2a7d", "\\leqslant", true); -defineSymbol(math, rel, "\u2a95", "\\eqslantless", true); -defineSymbol(math, rel, "\u2272", "\\lesssim", true); -defineSymbol(math, rel, "\u2a85", "\\lessapprox", true); -defineSymbol(math, rel, "\u224a", "\\approxeq", true); -defineSymbol(math, bin, "\u22d6", "\\lessdot"); -defineSymbol(math, rel, "\u22d8", "\\lll", true); -defineSymbol(math, rel, "\u2276", "\\lessgtr", true); -defineSymbol(math, rel, "\u22da", "\\lesseqgtr", true); -defineSymbol(math, rel, "\u2a8b", "\\lesseqqgtr", true); -defineSymbol(math, rel, "\u2251", "\\doteqdot"); -defineSymbol(math, rel, "\u2253", "\\risingdotseq", true); -defineSymbol(math, rel, "\u2252", "\\fallingdotseq", true); -defineSymbol(math, rel, "\u223d", "\\backsim", true); -defineSymbol(math, rel, "\u22cd", "\\backsimeq", true); -defineSymbol(math, rel, "\u2ac5", "\\subseteqq", true); -defineSymbol(math, rel, "\u22d0", "\\Subset", true); -defineSymbol(math, rel, "\u228f", "\\sqsubset", true); -defineSymbol(math, rel, "\u227c", "\\preccurlyeq", true); -defineSymbol(math, rel, "\u22de", "\\curlyeqprec", true); -defineSymbol(math, rel, "\u227e", "\\precsim", true); -defineSymbol(math, rel, "\u2ab7", "\\precapprox", true); -defineSymbol(math, rel, "\u22b2", "\\vartriangleleft"); -defineSymbol(math, rel, "\u22b4", "\\trianglelefteq"); -defineSymbol(math, rel, "\u22a8", "\\vDash", true); -defineSymbol(math, rel, "\u22aa", "\\Vvdash", true); -defineSymbol(math, rel, "\u2323", "\\smallsmile"); -defineSymbol(math, rel, "\u2322", "\\smallfrown"); -defineSymbol(math, rel, "\u224f", "\\bumpeq", true); -defineSymbol(math, rel, "\u224e", "\\Bumpeq", true); -defineSymbol(math, rel, "\u2267", "\\geqq", true); -defineSymbol(math, rel, "\u2a7e", "\\geqslant", true); -defineSymbol(math, rel, "\u2a96", "\\eqslantgtr", true); -defineSymbol(math, rel, "\u2273", "\\gtrsim", true); -defineSymbol(math, rel, "\u2a86", "\\gtrapprox", true); -defineSymbol(math, bin, "\u22d7", "\\gtrdot"); -defineSymbol(math, rel, "\u22d9", "\\ggg", true); -defineSymbol(math, rel, "\u2277", "\\gtrless", true); -defineSymbol(math, rel, "\u22db", "\\gtreqless", true); -defineSymbol(math, rel, "\u2a8c", "\\gtreqqless", true); -defineSymbol(math, rel, "\u2256", "\\eqcirc", true); -defineSymbol(math, rel, "\u2257", "\\circeq", true); -defineSymbol(math, rel, "\u225c", "\\triangleq", true); -defineSymbol(math, rel, "\u223c", "\\thicksim"); -defineSymbol(math, rel, "\u2248", "\\thickapprox"); -defineSymbol(math, rel, "\u2ac6", "\\supseteqq", true); -defineSymbol(math, rel, "\u22d1", "\\Supset", true); -defineSymbol(math, rel, "\u2290", "\\sqsupset", true); -defineSymbol(math, rel, "\u227d", "\\succcurlyeq", true); -defineSymbol(math, rel, "\u22df", "\\curlyeqsucc", true); -defineSymbol(math, rel, "\u227f", "\\succsim", true); -defineSymbol(math, rel, "\u2ab8", "\\succapprox", true); -defineSymbol(math, rel, "\u22b3", "\\vartriangleright"); -defineSymbol(math, rel, "\u22b5", "\\trianglerighteq"); -defineSymbol(math, rel, "\u22a9", "\\Vdash", true); -defineSymbol(math, rel, "\u2223", "\\shortmid"); -defineSymbol(math, rel, "\u2225", "\\shortparallel"); -defineSymbol(math, rel, "\u226c", "\\between", true); -defineSymbol(math, rel, "\u22d4", "\\pitchfork", true); -defineSymbol(math, rel, "\u221d", "\\varpropto"); -defineSymbol(math, rel, "\u25c0", "\\blacktriangleleft"); -// unicode-math says that \therefore is a mathord atom. -// We kept the amssymb atom type, which is rel. -defineSymbol(math, rel, "\u2234", "\\therefore", true); -defineSymbol(math, rel, "\u220d", "\\backepsilon"); -defineSymbol(math, rel, "\u25b6", "\\blacktriangleright"); -// unicode-math says that \because is a mathord atom. -// We kept the amssymb atom type, which is rel. -defineSymbol(math, rel, "\u2235", "\\because", true); -defineSymbol(math, rel, "\u22d8", "\\llless"); -defineSymbol(math, rel, "\u22d9", "\\gggtr"); -defineSymbol(math, bin, "\u22b2", "\\lhd"); -defineSymbol(math, bin, "\u22b3", "\\rhd"); -defineSymbol(math, rel, "\u2242", "\\eqsim", true); -defineSymbol(math, rel, "\u22c8", "\\Join"); -defineSymbol(math, rel, "\u2251", "\\Doteq", true); - -// AMS Binary Operators -defineSymbol(math, bin, "\u2214", "\\dotplus", true); -defineSymbol(math, bin, "\u2216", "\\smallsetminus"); -defineSymbol(math, bin, "\u22d2", "\\Cap", true); -defineSymbol(math, bin, "\u22d3", "\\Cup", true); -defineSymbol(math, bin, "\u2a5e", "\\doublebarwedge", true); -defineSymbol(math, bin, "\u229f", "\\boxminus", true); -defineSymbol(math, bin, "\u229e", "\\boxplus", true); -defineSymbol(math, bin, "\u22c7", "\\divideontimes", true); -defineSymbol(math, bin, "\u22c9", "\\ltimes", true); -defineSymbol(math, bin, "\u22ca", "\\rtimes", true); -defineSymbol(math, bin, "\u22cb", "\\leftthreetimes", true); -defineSymbol(math, bin, "\u22cc", "\\rightthreetimes", true); -defineSymbol(math, bin, "\u22cf", "\\curlywedge", true); -defineSymbol(math, bin, "\u22ce", "\\curlyvee", true); -defineSymbol(math, bin, "\u229d", "\\circleddash", true); -defineSymbol(math, bin, "\u229b", "\\circledast", true); -defineSymbol(math, bin, "\u22ba", "\\intercal", true); -defineSymbol(math, bin, "\u22d2", "\\doublecap"); -defineSymbol(math, bin, "\u22d3", "\\doublecup"); -defineSymbol(math, bin, "\u22a0", "\\boxtimes", true); - -// AMS Arrows -// Note: unicode-math maps \u21e2 to their own function \rightdasharrow. -// We'll map it to AMS function \dashrightarrow. It produces the same atom. -defineSymbol(math, rel, "\u21e2", "\\dashrightarrow", true); -// unicode-math maps \u21e0 to \leftdasharrow. We'll use the AMS synonym. -defineSymbol(math, rel, "\u21e0", "\\dashleftarrow", true); -defineSymbol(math, rel, "\u21c7", "\\leftleftarrows", true); -defineSymbol(math, rel, "\u21c6", "\\leftrightarrows", true); -defineSymbol(math, rel, "\u21da", "\\Lleftarrow", true); -defineSymbol(math, rel, "\u219e", "\\twoheadleftarrow", true); -defineSymbol(math, rel, "\u21a2", "\\leftarrowtail", true); -defineSymbol(math, rel, "\u21ab", "\\looparrowleft", true); -defineSymbol(math, rel, "\u21cb", "\\leftrightharpoons", true); -defineSymbol(math, rel, "\u21b6", "\\curvearrowleft", true); -// unicode-math maps \u21ba to \acwopencirclearrow. We'll use the AMS synonym. -defineSymbol(math, rel, "\u21ba", "\\circlearrowleft", true); -defineSymbol(math, rel, "\u21b0", "\\Lsh", true); -defineSymbol(math, rel, "\u21c8", "\\upuparrows", true); -defineSymbol(math, rel, "\u21bf", "\\upharpoonleft", true); -defineSymbol(math, rel, "\u21c3", "\\downharpoonleft", true); -defineSymbol(math, rel, "\u22b6", "\\origof", true); -defineSymbol(math, rel, "\u22b7", "\\imageof", true); -defineSymbol(math, rel, "\u22b8", "\\multimap", true); -defineSymbol(math, rel, "\u21ad", "\\leftrightsquigarrow", true); -defineSymbol(math, rel, "\u21c9", "\\rightrightarrows", true); -defineSymbol(math, rel, "\u21c4", "\\rightleftarrows", true); -defineSymbol(math, rel, "\u21a0", "\\twoheadrightarrow", true); -defineSymbol(math, rel, "\u21a3", "\\rightarrowtail", true); -defineSymbol(math, rel, "\u21ac", "\\looparrowright", true); -defineSymbol(math, rel, "\u21b7", "\\curvearrowright", true); -// unicode-math maps \u21bb to \cwopencirclearrow. We'll use the AMS synonym. -defineSymbol(math, rel, "\u21bb", "\\circlearrowright", true); -defineSymbol(math, rel, "\u21b1", "\\Rsh", true); -defineSymbol(math, rel, "\u21ca", "\\downdownarrows", true); -defineSymbol(math, rel, "\u21be", "\\upharpoonright", true); -defineSymbol(math, rel, "\u21c2", "\\downharpoonright", true); -defineSymbol(math, rel, "\u21dd", "\\rightsquigarrow", true); -defineSymbol(math, rel, "\u21dd", "\\leadsto"); -defineSymbol(math, rel, "\u21db", "\\Rrightarrow", true); -defineSymbol(math, rel, "\u21be", "\\restriction"); - -defineSymbol(math, textord, "\u2018", "`"); -defineSymbol(math, textord, "$", "\\$"); -defineSymbol(text, textord, "$", "\\$"); -defineSymbol(text, textord, "$", "\\textdollar"); -defineSymbol(math, textord, "%", "\\%"); -defineSymbol(text, textord, "%", "\\%"); -defineSymbol(math, textord, "_", "\\_"); -defineSymbol(text, textord, "_", "\\_"); -defineSymbol(text, textord, "_", "\\textunderscore"); -defineSymbol(text, textord, "\u2423", "\\textvisiblespace", true); -defineSymbol(math, textord, "\u2220", "\\angle", true); -defineSymbol(math, textord, "\u221e", "\\infty", true); -defineSymbol(math, textord, "\u2032", "\\prime"); -defineSymbol(math, textord, "\u25b3", "\\triangle"); -defineSymbol(text, textord, "\u0391", "\\Alpha", true); -defineSymbol(text, textord, "\u0392", "\\Beta", true); -defineSymbol(text, textord, "\u0393", "\\Gamma", true); -defineSymbol(text, textord, "\u0394", "\\Delta", true); -defineSymbol(text, textord, "\u0395", "\\Epsilon", true); -defineSymbol(text, textord, "\u0396", "\\Zeta", true); -defineSymbol(text, textord, "\u0397", "\\Eta", true); -defineSymbol(text, textord, "\u0398", "\\Theta", true); -defineSymbol(text, textord, "\u0399", "\\Iota", true); -defineSymbol(text, textord, "\u039a", "\\Kappa", true); -defineSymbol(text, textord, "\u039b", "\\Lambda", true); -defineSymbol(text, textord, "\u039c", "\\Mu", true); -defineSymbol(text, textord, "\u039d", "\\Nu", true); -defineSymbol(text, textord, "\u039e", "\\Xi", true); -defineSymbol(text, textord, "\u039f", "\\Omicron", true); -defineSymbol(text, textord, "\u03a0", "\\Pi", true); -defineSymbol(text, textord, "\u03a1", "\\Rho", true); -defineSymbol(text, textord, "\u03a3", "\\Sigma", true); -defineSymbol(text, textord, "\u03a4", "\\Tau", true); -defineSymbol(text, textord, "\u03a5", "\\Upsilon", true); -defineSymbol(text, textord, "\u03a6", "\\Phi", true); -defineSymbol(text, textord, "\u03a7", "\\Chi", true); -defineSymbol(text, textord, "\u03a8", "\\Psi", true); -defineSymbol(text, textord, "\u03a9", "\\Omega", true); -defineSymbol(math, mathord, "\u0391", "\\Alpha", true); -defineSymbol(math, mathord, "\u0392", "\\Beta", true); -defineSymbol(math, mathord, "\u0393", "\\Gamma", true); -defineSymbol(math, mathord, "\u0394", "\\Delta", true); -defineSymbol(math, mathord, "\u0395", "\\Epsilon", true); -defineSymbol(math, mathord, "\u0396", "\\Zeta", true); -defineSymbol(math, mathord, "\u0397", "\\Eta", true); -defineSymbol(math, mathord, "\u0398", "\\Theta", true); -defineSymbol(math, mathord, "\u0399", "\\Iota", true); -defineSymbol(math, mathord, "\u039a", "\\Kappa", true); -defineSymbol(math, mathord, "\u039b", "\\Lambda", true); -defineSymbol(math, mathord, "\u039c", "\\Mu", true); -defineSymbol(math, mathord, "\u039d", "\\Nu", true); -defineSymbol(math, mathord, "\u039e", "\\Xi", true); -defineSymbol(math, mathord, "\u039f", "\\Omicron", true); -defineSymbol(math, mathord, "\u03a0", "\\Pi", true); -defineSymbol(math, mathord, "\u03a1", "\\Rho", true); -defineSymbol(math, mathord, "\u03a3", "\\Sigma", true); -defineSymbol(math, mathord, "\u03a4", "\\Tau", true); -defineSymbol(math, mathord, "\u03a5", "\\Upsilon", true); -defineSymbol(math, mathord, "\u03a6", "\\Phi", true); -defineSymbol(math, mathord, "\u03a7", "\\Chi", true); -defineSymbol(math, mathord, "\u03a8", "\\Psi", true); -defineSymbol(math, mathord, "\u03a9", "\\Omega", true); -defineSymbol(math, textord, "\u00ac", "\\neg", true); -defineSymbol(math, textord, "\u00ac", "\\lnot"); -defineSymbol(math, textord, "\u22a4", "\\top"); -defineSymbol(math, textord, "\u22a5", "\\bot"); -defineSymbol(math, textord, "\u2205", "\\emptyset"); -defineSymbol(math, textord, "\u00f8", "\\varnothing"); -defineSymbol(math, mathord, "\u03b1", "\\alpha", true); -defineSymbol(math, mathord, "\u03b2", "\\beta", true); -defineSymbol(math, mathord, "\u03b3", "\\gamma", true); -defineSymbol(math, mathord, "\u03b4", "\\delta", true); -defineSymbol(math, mathord, "\u03f5", "\\epsilon", true); -defineSymbol(math, mathord, "\u03b6", "\\zeta", true); -defineSymbol(math, mathord, "\u03b7", "\\eta", true); -defineSymbol(math, mathord, "\u03b8", "\\theta", true); -defineSymbol(math, mathord, "\u03b9", "\\iota", true); -defineSymbol(math, mathord, "\u03ba", "\\kappa", true); -defineSymbol(math, mathord, "\u03bb", "\\lambda", true); -defineSymbol(math, mathord, "\u03bc", "\\mu", true); -defineSymbol(math, mathord, "\u03bd", "\\nu", true); -defineSymbol(math, mathord, "\u03be", "\\xi", true); -defineSymbol(math, mathord, "\u03bf", "\\omicron", true); -defineSymbol(math, mathord, "\u03c0", "\\pi", true); -defineSymbol(math, mathord, "\u03c1", "\\rho", true); -defineSymbol(math, mathord, "\u03c3", "\\sigma", true); -defineSymbol(math, mathord, "\u03c4", "\\tau", true); -defineSymbol(math, mathord, "\u03c5", "\\upsilon", true); -defineSymbol(math, mathord, "\u03d5", "\\phi", true); -defineSymbol(math, mathord, "\u03c7", "\\chi", true); -defineSymbol(math, mathord, "\u03c8", "\\psi", true); -defineSymbol(math, mathord, "\u03c9", "\\omega", true); -defineSymbol(math, mathord, "\u03b5", "\\varepsilon", true); -defineSymbol(math, mathord, "\u03d1", "\\vartheta", true); -defineSymbol(math, mathord, "\u03d6", "\\varpi", true); -defineSymbol(math, mathord, "\u03f1", "\\varrho", true); -defineSymbol(math, mathord, "\u03c2", "\\varsigma", true); -defineSymbol(math, mathord, "\u03c6", "\\varphi", true); -defineSymbol(math, mathord, "\u03d8", "\\Coppa", true); -defineSymbol(math, mathord, "\u03d9", "\\coppa", true); -defineSymbol(math, mathord, "\u03d9", "\\varcoppa", true); -defineSymbol(math, mathord, "\u03de", "\\Koppa", true); -defineSymbol(math, mathord, "\u03df", "\\koppa", true); -defineSymbol(math, mathord, "\u03e0", "\\Sampi", true); -defineSymbol(math, mathord, "\u03e1", "\\sampi", true); -defineSymbol(math, mathord, "\u03da", "\\Stigma", true); -defineSymbol(math, mathord, "\u03db", "\\stigma", true); -defineSymbol(math, bin, "\u2217", "\u2217", true); -defineSymbol(math, bin, "+", "+"); -defineSymbol(math, bin, "*", "*"); -defineSymbol(math, bin, "\u2044", "\u2044"); -defineSymbol(math, bin, "\u2212", "-", true); -defineSymbol(math, bin, "\u22c5", "\\cdot", true); -defineSymbol(math, bin, "\u2218", "\\circ"); -defineSymbol(math, bin, "\u00f7", "\\div", true); -defineSymbol(math, bin, "\u00b1", "\\pm", true); -defineSymbol(math, bin, "\u00d7", "\\times", true); -defineSymbol(math, bin, "\u2229", "\\cap", true); -defineSymbol(math, bin, "\u222a", "\\cup", true); -defineSymbol(math, bin, "\u2216", "\\setminus"); -defineSymbol(math, bin, "\u2227", "\\land"); -defineSymbol(math, bin, "\u2228", "\\lor"); -defineSymbol(math, bin, "\u2227", "\\wedge", true); -defineSymbol(math, bin, "\u2228", "\\vee", true); -defineSymbol(math, textord, "\u221a", "\\surd"); -defineSymbol(math, open, "\u27e6", "\\llbracket", true); // stmaryrd/semantic packages -defineSymbol(math, close, "\u27e7", "\\rrbracket", true); -defineSymbol(math, open, "\u27e8", "\\langle", true); -defineSymbol(math, open, "|", "\\lvert"); -defineSymbol(math, open, "\u2016", "\\lVert"); -defineSymbol(math, close, "?", "?"); -defineSymbol(math, close, "!", "!"); -defineSymbol(math, close, "‼", "‼"); -defineSymbol(math, close, "\u27e9", "\\rangle", true); -defineSymbol(math, close, "|", "\\rvert"); -defineSymbol(math, close, "\u2016", "\\rVert"); -defineSymbol(math, open, "\u2983", "\\lBrace", true); // stmaryrd/semantic packages -defineSymbol(math, close, "\u2984", "\\rBrace", true); -defineSymbol(math, rel, "=", "="); -defineSymbol(math, rel, "\u2248", "\\approx", true); -defineSymbol(math, rel, "\u2245", "\\cong", true); -defineSymbol(math, rel, "\u2265", "\\ge"); -defineSymbol(math, rel, "\u2265", "\\geq", true); -defineSymbol(math, rel, "\u2190", "\\gets"); -defineSymbol(math, rel, ">", "\\gt", true); -defineSymbol(math, rel, "\u2208", "\\in", true); -defineSymbol(math, rel, "\u2209", "\\notin", true); -defineSymbol(math, rel, "\ue020", "\\@not"); -defineSymbol(math, rel, "\u2282", "\\subset", true); -defineSymbol(math, rel, "\u2283", "\\supset", true); -defineSymbol(math, rel, "\u2286", "\\subseteq", true); -defineSymbol(math, rel, "\u2287", "\\supseteq", true); -defineSymbol(math, rel, "\u2288", "\\nsubseteq", true); -defineSymbol(math, rel, "\u2288", "\\nsubseteqq"); -defineSymbol(math, rel, "\u2289", "\\nsupseteq", true); -defineSymbol(math, rel, "\u2289", "\\nsupseteqq"); -defineSymbol(math, rel, "\u22a8", "\\models"); -defineSymbol(math, rel, "\u2190", "\\leftarrow", true); -defineSymbol(math, rel, "\u2264", "\\le"); -defineSymbol(math, rel, "\u2264", "\\leq", true); -defineSymbol(math, rel, "<", "\\lt", true); -defineSymbol(math, rel, "\u2192", "\\rightarrow", true); -defineSymbol(math, rel, "\u2192", "\\to"); -defineSymbol(math, rel, "\u2271", "\\ngeq", true); -defineSymbol(math, rel, "\u2271", "\\ngeqq"); -defineSymbol(math, rel, "\u2271", "\\ngeqslant"); -defineSymbol(math, rel, "\u2270", "\\nleq", true); -defineSymbol(math, rel, "\u2270", "\\nleqq"); -defineSymbol(math, rel, "\u2270", "\\nleqslant"); -defineSymbol(math, spacing, "\u00a0", "\\ "); -defineSymbol(math, spacing, "\u00a0", "\\space"); -// Ref: LaTeX Source 2e: \DeclareRobustCommand{\nobreakspace}{% -defineSymbol(math, spacing, "\u00a0", "\\nobreakspace"); -defineSymbol(text, spacing, "\u00a0", "\\ "); -defineSymbol(text, spacing, "\u00a0", " "); -defineSymbol(text, spacing, "\u00a0", "\\space"); -defineSymbol(text, spacing, "\u00a0", "\\nobreakspace"); -defineSymbol(math, spacing, null, "\\nobreak"); -defineSymbol(math, spacing, null, "\\allowbreak"); -defineSymbol(math, punct, ",", ","); -defineSymbol(math, punct, ";", ";"); -defineSymbol(math, bin, "\u22bc", "\\barwedge", true); -defineSymbol(math, bin, "\u22bb", "\\veebar", true); -defineSymbol(math, bin, "\u2299", "\\odot", true); -defineSymbol(math, bin, "\u2295", "\\oplus", true); -defineSymbol(math, bin, "\u2297", "\\otimes", true); -defineSymbol(math, textord, "\u2202", "\\partial", true); -defineSymbol(math, bin, "\u2298", "\\oslash", true); -defineSymbol(math, bin, "\u229a", "\\circledcirc", true); -defineSymbol(math, bin, "\u22a1", "\\boxdot", true); -defineSymbol(math, bin, "\u25b3", "\\bigtriangleup"); -defineSymbol(math, bin, "\u25bd", "\\bigtriangledown"); -defineSymbol(math, bin, "\u2020", "\\dagger"); -defineSymbol(math, bin, "\u22c4", "\\diamond"); -defineSymbol(math, bin, "\u22c6", "\\star"); -defineSymbol(math, bin, "\u25c3", "\\triangleleft"); -defineSymbol(math, bin, "\u25b9", "\\triangleright"); -defineSymbol(math, open, "{", "\\{"); -defineSymbol(text, textord, "{", "\\{"); -defineSymbol(text, textord, "{", "\\textbraceleft"); -defineSymbol(math, close, "}", "\\}"); -defineSymbol(text, textord, "}", "\\}"); -defineSymbol(text, textord, "}", "\\textbraceright"); -defineSymbol(math, open, "{", "\\lbrace"); -defineSymbol(math, close, "}", "\\rbrace"); -defineSymbol(math, open, "[", "\\lbrack", true); -defineSymbol(text, textord, "[", "\\lbrack", true); -defineSymbol(math, close, "]", "\\rbrack", true); -defineSymbol(text, textord, "]", "\\rbrack", true); -defineSymbol(math, open, "(", "\\lparen", true); -defineSymbol(math, close, ")", "\\rparen", true); -defineSymbol(text, textord, "<", "\\textless", true); // in T1 fontenc -defineSymbol(text, textord, ">", "\\textgreater", true); // in T1 fontenc -defineSymbol(math, open, "\u230a", "\\lfloor", true); -defineSymbol(math, close, "\u230b", "\\rfloor", true); -defineSymbol(math, open, "\u2308", "\\lceil", true); -defineSymbol(math, close, "\u2309", "\\rceil", true); -defineSymbol(math, textord, "\\", "\\backslash"); -defineSymbol(math, textord, "|", "|"); -defineSymbol(math, textord, "|", "\\vert"); -defineSymbol(text, textord, "|", "\\textbar", true); // in T1 fontenc -defineSymbol(math, textord, "\u2016", "\\|"); -defineSymbol(math, textord, "\u2016", "\\Vert"); -defineSymbol(text, textord, "\u2016", "\\textbardbl"); -defineSymbol(text, textord, "~", "\\textasciitilde"); -defineSymbol(text, textord, "\\", "\\textbackslash"); -defineSymbol(text, textord, "^", "\\textasciicircum"); -defineSymbol(math, rel, "\u2191", "\\uparrow", true); -defineSymbol(math, rel, "\u21d1", "\\Uparrow", true); -defineSymbol(math, rel, "\u2193", "\\downarrow", true); -defineSymbol(math, rel, "\u21d3", "\\Downarrow", true); -defineSymbol(math, rel, "\u2195", "\\updownarrow", true); -defineSymbol(math, rel, "\u21d5", "\\Updownarrow", true); -defineSymbol(math, op, "\u2210", "\\coprod"); -defineSymbol(math, op, "\u22c1", "\\bigvee"); -defineSymbol(math, op, "\u22c0", "\\bigwedge"); -defineSymbol(math, op, "\u2a04", "\\biguplus"); -defineSymbol(math, op, "\u22c2", "\\bigcap"); -defineSymbol(math, op, "\u22c3", "\\bigcup"); -defineSymbol(math, op, "\u222b", "\\int"); -defineSymbol(math, op, "\u222b", "\\intop"); -defineSymbol(math, op, "\u222c", "\\iint"); -defineSymbol(math, op, "\u222d", "\\iiint"); -defineSymbol(math, op, "\u220f", "\\prod"); -defineSymbol(math, op, "\u2211", "\\sum"); -defineSymbol(math, op, "\u2a02", "\\bigotimes"); -defineSymbol(math, op, "\u2a01", "\\bigoplus"); -defineSymbol(math, op, "\u2a00", "\\bigodot"); -defineSymbol(math, op, "\u222e", "\\oint"); -defineSymbol(math, op, "\u222f", "\\oiint"); -defineSymbol(math, op, "\u2230", "\\oiiint"); -defineSymbol(math, op, "\u2231", "\\intclockwise"); -defineSymbol(math, op, "\u2232", "\\varointclockwise"); -defineSymbol(math, op, "\u2a0c", "\\iiiint"); -defineSymbol(math, op, "\u2a0d", "\\intbar"); -defineSymbol(math, op, "\u2a0e", "\\intBar"); -defineSymbol(math, op, "\u2a0f", "\\fint"); -defineSymbol(math, op, "\u2a12", "\\rppolint"); -defineSymbol(math, op, "\u2a13", "\\scpolint"); -defineSymbol(math, op, "\u2a15", "\\pointint"); -defineSymbol(math, op, "\u2a16", "\\sqint"); -defineSymbol(math, op, "\u2a17", "\\intlarhk"); -defineSymbol(math, op, "\u2a18", "\\intx"); -defineSymbol(math, op, "\u2a19", "\\intcap"); -defineSymbol(math, op, "\u2a1a", "\\intcup"); -defineSymbol(math, op, "\u2a05", "\\bigsqcap"); -defineSymbol(math, op, "\u2a06", "\\bigsqcup"); -defineSymbol(math, op, "\u222b", "\\smallint"); -defineSymbol(text, inner, "\u2026", "\\textellipsis"); -defineSymbol(math, inner, "\u2026", "\\mathellipsis"); -defineSymbol(text, inner, "\u2026", "\\ldots", true); -defineSymbol(math, inner, "\u2026", "\\ldots", true); -defineSymbol(math, inner, "\u22f0", "\\iddots", true); -defineSymbol(math, inner, "\u22ef", "\\@cdots", true); -defineSymbol(math, inner, "\u22f1", "\\ddots", true); -defineSymbol(math, textord, "\u22ee", "\\varvdots"); // \vdots is a macro -defineSymbol(math, accent, "\u02ca", "\\acute"); -defineSymbol(math, accent, "\u0060", "\\grave"); -defineSymbol(math, accent, "\u00a8", "\\ddot"); -defineSymbol(math, accent, "\u20db", "\\dddot"); -defineSymbol(math, accent, "\u20dc", "\\ddddot"); -defineSymbol(math, accent, "\u007e", "\\tilde"); -defineSymbol(math, accent, "\u00af", "\\bar"); -defineSymbol(math, accent, "\u02d8", "\\breve"); -defineSymbol(math, accent, "\u02c7", "\\check"); -defineSymbol(math, accent, "\u005e", "\\hat"); -defineSymbol(math, accent, "\u20d7", "\\vec"); -defineSymbol(math, accent, "\u02d9", "\\dot"); -defineSymbol(math, accent, "\u02da", "\\mathring"); -defineSymbol(math, mathord, "\u0131", "\\imath", true); -defineSymbol(math, mathord, "\u0237", "\\jmath", true); -defineSymbol(math, textord, "\u0131", "\u0131"); -defineSymbol(math, textord, "\u0237", "\u0237"); -defineSymbol(text, textord, "\u0131", "\\i", true); -defineSymbol(text, textord, "\u0237", "\\j", true); -defineSymbol(text, textord, "\u00df", "\\ss", true); -defineSymbol(text, textord, "\u00e6", "\\ae", true); -defineSymbol(text, textord, "\u0153", "\\oe", true); -defineSymbol(text, textord, "\u00f8", "\\o", true); -defineSymbol(math, mathord, "\u00f8", "\\o", true); -defineSymbol(text, textord, "\u00c6", "\\AE", true); -defineSymbol(text, textord, "\u0152", "\\OE", true); -defineSymbol(text, textord, "\u00d8", "\\O", true); -defineSymbol(math, mathord, "\u00d8", "\\O", true); -defineSymbol(text, accent, "\u02ca", "\\'"); // acute -defineSymbol(text, accent, "\u02cb", "\\`"); // grave -defineSymbol(text, accent, "\u02c6", "\\^"); // circumflex -defineSymbol(text, accent, "\u02dc", "\\~"); // tilde -defineSymbol(text, accent, "\u02c9", "\\="); // macron -defineSymbol(text, accent, "\u02d8", "\\u"); // breve -defineSymbol(text, accent, "\u02d9", "\\."); // dot above -defineSymbol(text, accent, "\u00b8", "\\c"); // cedilla -defineSymbol(text, accent, "\u02da", "\\r"); // ring above -defineSymbol(text, accent, "\u02c7", "\\v"); // caron -defineSymbol(text, accent, "\u00a8", '\\"'); // diaresis -defineSymbol(text, accent, "\u02dd", "\\H"); // double acute -defineSymbol(math, accent, "\u02ca", "\\'"); // acute -defineSymbol(math, accent, "\u02cb", "\\`"); // grave -defineSymbol(math, accent, "\u02c6", "\\^"); // circumflex -defineSymbol(math, accent, "\u02dc", "\\~"); // tilde -defineSymbol(math, accent, "\u02c9", "\\="); // macron -defineSymbol(math, accent, "\u02d8", "\\u"); // breve -defineSymbol(math, accent, "\u02d9", "\\."); // dot above -defineSymbol(math, accent, "\u00b8", "\\c"); // cedilla -defineSymbol(math, accent, "\u02da", "\\r"); // ring above -defineSymbol(math, accent, "\u02c7", "\\v"); // caron -defineSymbol(math, accent, "\u00a8", '\\"'); // diaresis -defineSymbol(math, accent, "\u02dd", "\\H"); // double acute - -// These ligatures are detected and created in Parser.js's `formLigatures`. -const ligatures = { - "--": true, - "---": true, - "``": true, - "''": true -}; - -defineSymbol(text, textord, "\u2013", "--", true); -defineSymbol(text, textord, "\u2013", "\\textendash"); -defineSymbol(text, textord, "\u2014", "---", true); -defineSymbol(text, textord, "\u2014", "\\textemdash"); -defineSymbol(text, textord, "\u2018", "`", true); -defineSymbol(text, textord, "\u2018", "\\textquoteleft"); -defineSymbol(text, textord, "\u2019", "'", true); -defineSymbol(text, textord, "\u2019", "\\textquoteright"); -defineSymbol(text, textord, "\u201c", "``", true); -defineSymbol(text, textord, "\u201c", "\\textquotedblleft"); -defineSymbol(text, textord, "\u201d", "''", true); -defineSymbol(text, textord, "\u201d", "\\textquotedblright"); -// \degree from gensymb package -defineSymbol(math, textord, "\u00b0", "\\degree", true); -defineSymbol(text, textord, "\u00b0", "\\degree"); -// \textdegree from inputenc package -defineSymbol(text, textord, "\u00b0", "\\textdegree", true); -// TODO: In LaTeX, \pounds can generate a different character in text and math -// mode, but among our fonts, only Main-Regular defines this character "163". -defineSymbol(math, textord, "\u00a3", "\\pounds"); -defineSymbol(math, textord, "\u00a3", "\\mathsterling", true); -defineSymbol(text, textord, "\u00a3", "\\pounds"); -defineSymbol(text, textord, "\u00a3", "\\textsterling", true); -defineSymbol(math, textord, "\u2720", "\\maltese"); -defineSymbol(text, textord, "\u2720", "\\maltese"); -defineSymbol(math, textord, "\u20ac", "\\euro", true); -defineSymbol(text, textord, "\u20ac", "\\euro", true); -defineSymbol(text, textord, "\u20ac", "\\texteuro"); -defineSymbol(math, textord, "\u00a9", "\\copyright", true); -defineSymbol(text, textord, "\u00a9", "\\textcopyright"); - -// Italic Greek -defineSymbol(math, textord, "𝛤", "\\varGamma"); -defineSymbol(math, textord, "𝛥", "\\varDelta"); -defineSymbol(math, textord, "𝛩", "\\varTheta"); -defineSymbol(math, textord, "𝛬", "\\varLambda"); -defineSymbol(math, textord, "𝛯", "\\varXi"); -defineSymbol(math, textord, "𝛱", "\\varPi"); -defineSymbol(math, textord, "𝛴", "\\varSigma"); -defineSymbol(math, textord, "𝛶", "\\varUpsilon"); -defineSymbol(math, textord, "𝛷", "\\varPhi"); -defineSymbol(math, textord, "𝛹", "\\varPsi"); -defineSymbol(math, textord, "𝛺", "\\varOmega"); -defineSymbol(text, textord, "𝛤", "\\varGamma"); -defineSymbol(text, textord, "𝛥", "\\varDelta"); -defineSymbol(text, textord, "𝛩", "\\varTheta"); -defineSymbol(text, textord, "𝛬", "\\varLambda"); -defineSymbol(text, textord, "𝛯", "\\varXi"); -defineSymbol(text, textord, "𝛱", "\\varPi"); -defineSymbol(text, textord, "𝛴", "\\varSigma"); -defineSymbol(text, textord, "𝛶", "\\varUpsilon"); -defineSymbol(text, textord, "𝛷", "\\varPhi"); -defineSymbol(text, textord, "𝛹", "\\varPsi"); -defineSymbol(text, textord, "𝛺", "\\varOmega"); - - -// There are lots of symbols which are the same, so we add them in afterwards. -// All of these are textords in math mode -const mathTextSymbols = '0123456789/@."'; -for (let i = 0; i < mathTextSymbols.length; i++) { - const ch = mathTextSymbols.charAt(i); - defineSymbol(math, textord, ch, ch); -} - -// All of these are textords in text mode -const textSymbols = '0123456789!@*()-=+";:?/.,'; -for (let i = 0; i < textSymbols.length; i++) { - const ch = textSymbols.charAt(i); - defineSymbol(text, textord, ch, ch); -} - -// All of these are textords in text mode, and mathords in math mode -const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -for (let i = 0; i < letters.length; i++) { - const ch = letters.charAt(i); - defineSymbol(math, mathord, ch, ch); - defineSymbol(text, textord, ch, ch); -} - -// Some more letters in Unicode Basic Multilingual Plane. -const narrow = "ÇÐÞçþℂℍℕℙℚℝℤℎℏℊℋℌℐℑℒℓ℘ℛℜℬℰℱℳℭℨ"; -for (let i = 0; i < narrow.length; i++) { - const ch = narrow.charAt(i); - defineSymbol(math, mathord, ch, ch); - defineSymbol(text, textord, ch, ch); -} - -// The next loop loads wide (surrogate pair) characters. -// We support some letters in the Unicode range U+1D400 to U+1D7FF, -// Mathematical Alphanumeric Symbols. -let wideChar = ""; -for (let i = 0; i < letters.length; i++) { - // The hex numbers in the next line are a surrogate pair. - // 0xD835 is the high surrogate for all letters in the range we support. - // 0xDC00 is the low surrogate for bold A. - wideChar = String.fromCharCode(0xd835, 0xdc00 + i); // A-Z a-z bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdc34 + i); // A-Z a-z italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdc68 + i); // A-Z a-z bold italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdd04 + i); // A-Z a-z Fractur - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdda0 + i); // A-Z a-z sans-serif - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xddd4 + i); // A-Z a-z sans bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xde08 + i); // A-Z a-z sans italic - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xde70 + i); // A-Z a-z monospace - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdd38 + i); // A-Z a-z double struck - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - const ch = letters.charAt(i); - wideChar = String.fromCharCode(0xd835, 0xdc9c + i); // A-Z a-z calligraphic - defineSymbol(math, mathord, ch, wideChar); - defineSymbol(text, textord, ch, wideChar); -} - -// Next, some wide character numerals -for (let i = 0; i < 10; i++) { - wideChar = String.fromCharCode(0xd835, 0xdfce + i); // 0-9 bold - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdfe2 + i); // 0-9 sans serif - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdfec + i); // 0-9 bold sans - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); - - wideChar = String.fromCharCode(0xd835, 0xdff6 + i); // 0-9 monospace - defineSymbol(math, mathord, wideChar, wideChar); - defineSymbol(text, textord, wideChar, wideChar); -} - -/* - * Neither Firefox nor Chrome support hard line breaks or soft line breaks. - * (Despite https://www.w3.org/Math/draft-spec/mathml.html#chapter3_presm.lbattrs) - * So Temml has work-arounds for both hard and soft breaks. - * The work-arounds sadly do not work simultaneously. Any top-level hard - * break makes soft line breaks impossible. - * - * Hard breaks are simulated by creating a and putting each line in its own . - * - * To create soft line breaks, Temml avoids using the and tags. - * Then the top level of a element can be occupied by elements, and the browser - * will break after a if the expression extends beyond the container limit. - * - * We want the expression to render with soft line breaks after each top-level binary or - * relational operator, per TeXbook p. 173. So we gather the expression into s so that - * each ends in a binary or relational operator. - * - * Soft line breaks will not work in Chromium and Safari, only Firefox. - * - * Hopefully browsers will someday do their own linebreaking and we will be able to delete - * much of this module. - */ - -function setLineBreaks(expression, isDisplayMode, isAnnotated, color = undefined) { - if (color === undefined) { - // First, make one pass through the expression and split any color nodes. - const upperLimit = expression.length - 1; - for (let i = upperLimit; i >= 0; i--) { - const node = expression[i]; - if (node.type === "mstyle" && node.attributes.mathcolor) { - const color = node.attributes.mathcolor; - const fragment = setLineBreaks(node.children, isDisplayMode, isAnnotated, color); - if (!(fragment.type && fragment.type !== "mtable")) { - expression.splice(i, 1, ...fragment.children); - - } - } - } - } - - const tagName = color ? "mstyle" : "mrow"; - - const mtrs = []; - let mrows = []; - let block = []; - let canBeBIN = false; // The first node cannot be an infix binary operator. - for (let i = 0; i < expression.length; i++) { - const node = expression[i]; - if (node.type && node.type === "mstyle" && node.attributes.mathcolor) { - // Start a new block. (Insert a soft linebreak.) - mrows.push(new mathMLTree.MathNode(tagName, block)); - // Insert the mstyle - mrows.push(node); - block = []; - continue - } - if (node.attributes && node.attributes.linebreak && - node.attributes.linebreak === "newline") { - // A hard line break. Create a for the current block. - if (block.length > 0) { - const element = new mathMLTree.MathNode(tagName, block); - if (color) { element.setAttribute("mathcolor", color); } - mrows.push(new mathMLTree.MathNode(tagName, block)); - } - mrows.push(node); - block = []; - const mtd = new mathMLTree.MathNode("mtd", mrows); - mtrs.push(new mathMLTree.MathNode("mtr", [mtd])); - mrows = []; - continue - } - block.push(node); - if (node.type && node.type === "mo" && !isDisplayMode && !isAnnotated) { - // This may be a place for a soft line break. - if (canBeBIN && !node.attributes.form) { - // Check if the following node is a \nobreak text node, e.g. "~"" - const next = i < expression.length - 1 ? expression[i + 1] : null; - let glueIsFreeOfNobreak = true; - if ( - !( - next && - next.type === "mtext" && - next.attributes.linebreak && - next.attributes.linebreak === "nobreak" - ) - ) { - // We may need to start a new block. - // First, put any post-operator glue on same line as operator. - for (let j = i + 1; j < expression.length; j++) { - const nd = expression[j]; - if ( - nd.type && - nd.type === "mspace" && - !(nd.attributes.linebreak && nd.attributes.linebreak === "newline") - ) { - block.push(nd); - i += 1; - if ( - nd.attributes && - nd.attributes.linebreak && - nd.attributes.linebreak === "nobreak" - ) { - glueIsFreeOfNobreak = false; - } - } else { - break; - } - } - } - if (glueIsFreeOfNobreak) { - // Start a new block. (Insert a soft linebreak.) - const element = new mathMLTree.MathNode(tagName, block); - if (color) { element.setAttribute("mathcolor", color); } - mrows.push(element); - block = []; - } - canBeBIN = false; - } - const isOpenDelimiter = node.attributes.form && node.attributes.form === "prefix"; - // Any operator that follows an open delimiter is unary. - canBeBIN = !(node.attributes.separator || isOpenDelimiter); - } else { - canBeBIN = true; - } - } - if (block.length > 0) { - const element = new mathMLTree.MathNode(tagName, block); - if (color) { element.setAttribute("mathcolor", color); } - mrows.push(element); - } - if (mtrs.length > 0) { - const mtd = new mathMLTree.MathNode("mtd", mrows); - const mtr = new mathMLTree.MathNode("mtr", [mtd]); - mtrs.push(mtr); - const mtable = new mathMLTree.MathNode("mtable", mtrs); - if (!isDisplayMode) { - mtable.setAttribute("columnalign", "left"); - mtable.setAttribute("rowspacing", "0em"); - } - return mtable - } - return mathMLTree.newDocumentFragment(mrows); -} - -/** - * This file converts a parse tree into a cooresponding MathML tree. The main - * entry point is the `buildMathML` function, which takes a parse tree from the - * parser. - */ - -/** - * Takes a symbol and converts it into a MathML text node after performing - * optional replacement from symbols.js. - */ -const makeText = function(text, mode, style) { - if ( - symbols[mode][text] && - symbols[mode][text].replace && - text.charCodeAt(0) !== 0xd835 && - !( - Object.prototype.hasOwnProperty.call(ligatures, text) && - style && - ((style.fontFamily && style.fontFamily.substr(4, 2) === "tt") || - (style.font && style.font.substr(4, 2) === "tt")) - ) - ) { - text = symbols[mode][text].replace; - } - - return new mathMLTree.TextNode(text); -}; - -/** - * Wrap the given array of nodes in an node if needed, i.e., - * unless the array has length 1. Always returns a single node. - */ -const makeRow = function(body) { - if (body.length === 1) { - return body[0]; - } else { - return new mathMLTree.MathNode("mrow", body); - } -}; - -/** - * Takes a list of nodes, builds them, and returns a list of the generated - * MathML nodes. Also combine consecutive outputs into a single - * tag. - */ -const buildExpression = function(expression, style, isOrdgroup) { - if (expression.length === 1) { - const group = buildGroup(expression[0], style); - if (isOrdgroup && group instanceof MathNode && group.type === "mo") { - // When TeX writers want to suppress spacing on an operator, - // they often put the operator by itself inside braces. - group.setAttribute("lspace", "0em"); - group.setAttribute("rspace", "0em"); - } - return [group]; - } - - const groups = []; - for (let i = 0; i < expression.length; i++) { - const group = buildGroup(expression[i], style); - groups.push(group); - } - return groups; -}; - -/** - * Equivalent to buildExpression, but wraps the elements in an - * if there's more than one. Returns a single node instead of an array. - */ -const buildExpressionRow = function(expression, style, isOrdgroup) { - return makeRow(buildExpression(expression, style, isOrdgroup)); -}; - -/** - * Takes a group from the parser and calls the appropriate groupBuilders function - * on it to produce a MathML node. - */ -const buildGroup = function(group, style) { - if (!group) { - return new mathMLTree.MathNode("mrow"); - } - - if (_mathmlGroupBuilders[group.type]) { - // Call the groupBuilders function - const result = _mathmlGroupBuilders[group.type](group, style); - return result; - } else { - throw new ParseError("Got group of unknown type: '" + group.type + "'"); - } -}; - - -const taggedExpression = (expression, tag, style, leqno, preventTagLap) => { - const glue = new mathMLTree.MathNode("mtd", []); - glue.setAttribute("style", "padding: 0;width: 50%;"); - tag = buildExpressionRow(tag[0].body, style); - tag.classes = ["tml-tag"]; - if (!preventTagLap) { - tag = new mathMLTree.MathNode("mpadded", [tag]); - tag.setAttribute("style", "width:0;"); - tag.setAttribute("width", "0"); - tag.setAttribute((leqno ? "rspace" : "lspace"), "-1width"); - } - tag = new mathMLTree.MathNode("mtd", [tag]); - if (!preventTagLap) { tag.setAttribute("style", "padding: 0; min-width:0"); } - - expression = new mathMLTree.MathNode("mtd", [expression]); - const rowArray = leqno - ? [tag, glue, expression, glue] - : [glue, expression, glue, tag]; - const mtr = new mathMLTree.MathNode("mtr", rowArray, ["tml-tageqn"]); - const table = new mathMLTree.MathNode("mtable", [mtr]); - table.setAttribute("width", "100%"); - return table -}; - -/** - * Takes a full parse tree and settings and builds a MathML representation of - * it. - */ -function buildMathML(tree, texExpression, style, settings) { - // Strip off outer tag wrapper for processing below. - let tag = null; - if (tree.length === 1 && tree[0].type === "tag") { - tag = tree[0].tag; - tree = tree[0].body; - } - - const expression = buildExpression(tree, style); - - const n1 = expression.length === 0 ? null : expression[0]; - let wrapper = expression.length === 1 && tag === null && (n1 instanceof MathNode) - && !(n1.type === "mstyle" && n1.attributes.mathcolor) - ? expression[0] - : setLineBreaks(expression, settings.displayMode, settings.annotate); - - if (tag) { - wrapper = taggedExpression(wrapper, tag, style, settings.leqno, settings.preventTagLap); - } - - let semantics; - if (settings.annotate) { - // Build a TeX annotation of the source - const annotation = new mathMLTree.MathNode( - "annotation", [new mathMLTree.TextNode(texExpression)]); - annotation.setAttribute("encoding", "application/x-tex"); - semantics = new mathMLTree.MathNode("semantics", [wrapper, annotation]); - } - - const math = settings.annotate - ? new mathMLTree.MathNode("math", [semantics]) - : new mathMLTree.MathNode("math", [wrapper]); - - if (settings.xml) { - math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML"); - } - if (settings.displayMode) { - math.setAttribute("display", "block"); - } - return math; -} - -const mathmlBuilder = (group, style) => { - const accentNode = group.isStretchy - ? stretchy.mathMLnode(group.label) - : new mathMLTree.MathNode("mo", [makeText(group.label, group.mode)]); - - if (!group.isStretchy) { - accentNode.setAttribute("stretchy", "false"); - } - - const node = new mathMLTree.MathNode((group.label === "\\c" ? "munder" : "mover"), - [buildGroup(group.base, style), accentNode] - ); - - node.setAttribute("accent", "true"); - return node; -}; - -const NON_STRETCHY_ACCENT_REGEX = new RegExp( - [ - "\\acute", - "\\grave", - "\\ddot", - "\\dddot", - "\\ddddot", - "\\tilde", - "\\bar", - "\\breve", - "\\check", - "\\hat", - "\\vec", - "\\dot", - "\\mathring" - ] - .map((accent) => `\\${accent}`) - .join("|") -); - -// Accents -defineFunction({ - type: "accent", - names: [ - "\\acute", - "\\grave", - "\\ddot", - "\\dddot", - "\\ddddot", - "\\tilde", - "\\bar", - "\\breve", - "\\check", - "\\hat", - "\\vec", - "\\dot", - "\\mathring", - "\\overparen", - "\\widecheck", - "\\widehat", - "\\wideparen", - "\\widetilde", - "\\overrightarrow", - "\\overleftarrow", - "\\Overrightarrow", - "\\overleftrightarrow", - "\\overgroup", - "\\overleftharpoon", - "\\overrightharpoon" - ], - props: { - numArgs: 1 - }, - handler: (context, args) => { - const base = normalizeArgument(args[0]); - - const isStretchy = !NON_STRETCHY_ACCENT_REGEX.test(context.funcName); - const isShifty = - !isStretchy || - context.funcName === "\\widehat" || - context.funcName === "\\widetilde" || - context.funcName === "\\widecheck"; - - return { - type: "accent", - mode: context.parser.mode, - label: context.funcName, - isStretchy: isStretchy, - isShifty: isShifty, - base: base - }; - }, - mathmlBuilder -}); - -// Text-mode accents -defineFunction({ - type: "accent", - names: ["\\'", "\\`", "\\^", "\\~", "\\=", "\\c", "\\u", "\\.", '\\"', "\\r", "\\H", "\\v"], - props: { - numArgs: 1, - allowedInText: true, - allowedInMath: true, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const base = normalizeArgument(args[0]); - const mode = context.parser.mode; - - if (mode === "math" && context.parser.settings.strict) { - // LaTeX only writes a warning. It doesn't stop. We'll issue the same warning. - // eslint-disable-next-line no-console - console.log(`Temml parse error: Command ${context.funcName} is invalid in math mode.`); - } - - return { - type: "accent", - mode: mode, - label: context.funcName, - isStretchy: false, - isShifty: true, - base: base - }; - }, - mathmlBuilder -}); - -defineFunction({ - type: "accentUnder", - names: [ - "\\underleftarrow", - "\\underrightarrow", - "\\underleftrightarrow", - "\\undergroup", - "\\underparen", - "\\utilde" - ], - props: { - numArgs: 1 - }, - handler: ({ parser, funcName }, args) => { - const base = args[0]; - return { - type: "accentUnder", - mode: parser.mode, - label: funcName, - base: base - }; - }, - mathmlBuilder: (group, style) => { - const accentNode = stretchy.mathMLnode(group.label); - const node = new mathMLTree.MathNode("munder", [ - buildGroup(group.base, style), - accentNode - ]); - node.setAttribute("accentunder", "true"); - return node; - } -}); - -// Helper functions -const paddedNode = (group, width = "+0.6em") => { - const node = new mathMLTree.MathNode("mpadded", group ? [group] : []); - node.setAttribute("width", width); - node.setAttribute("lspace", "0.3em"); - return node; -}; - -const munderoverNode = (label, body, below, style, macros = {}) => { - const arrowNode = stretchy.mathMLnode(label, macros); - const minWidth = label.charAt(1) === "x" - ? "1.75em" // mathtools extensible arrows - : label.slice(2, 4) === "cd" - ? "3.0em" // cd package arrows - : "2.0em"; // mhchem arrows - arrowNode.setAttribute("minsize", minWidth); - // minsize attribute doesn't work in Firefox. - // https://bugzilla.mozilla.org/show_bug.cgi?id=320303 - const labelStyle = style.incrementLevel(); - - const upperNode = (body && body.body && - // \hphantom visible content - (body.body.body || body.body.length > 0)) - ? paddedNode(buildGroup(body, labelStyle)) - // Since Firefox does not recognize minsize set on the arrow, - // create an upper node w/correct width. - : paddedNode(null, minWidth); - const lowerNode = (below && below.body && - (below.body.body || below.body.length > 0)) - ? paddedNode(buildGroup(below, labelStyle)) - : paddedNode(null, minWidth); - const node = new mathMLTree.MathNode("munderover", [arrowNode, lowerNode, upperNode]); - return node -}; - -// Stretchy arrows with an optional argument -defineFunction({ - type: "xArrow", - names: [ - "\\xleftarrow", - "\\xrightarrow", - "\\xLeftarrow", - "\\xRightarrow", - "\\xleftrightarrow", - "\\xLeftrightarrow", - "\\xhookleftarrow", - "\\xhookrightarrow", - "\\xmapsto", - "\\xrightharpoondown", - "\\xrightharpoonup", - "\\xleftharpoondown", - "\\xleftharpoonup", - "\\xlongequal", - "\\xtwoheadrightarrow", - "\\xtwoheadleftarrow", - // The next 7 functions are here only to support mhchem - "\\yields", - "\\yieldsLeft", - "\\mesomerism", - "\\longrightharpoonup", - "\\longleftharpoondown", - "\\equilibriumRight", - "\\equilibriumLeft", - // The next 3 functions are here only to support the {CD} environment. - "\\\\cdrightarrow", - "\\\\cdleftarrow", - "\\\\cdlongequal" - ], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser, funcName }, args, optArgs) { - return { - type: "xArrow", - mode: parser.mode, - label: funcName, - body: args[0], - below: optArgs[0], - macros: parser.gullet.macros // Contains SVG paths for mhchem equilibrium arrows. - }; - }, - mathmlBuilder(group, style) { - return munderoverNode(group.label, group.body, group.below, style, group.macros) - } -}); - -const arrowComponent = { - "\\xtofrom": ["\\xrightarrow", "\\xleftarrow"], - "\\xleftrightharpoons": ["\\xleftharpoonup", "\\xrightharpoondown"], - "\\xrightleftharpoons": ["\\xrightharpoonup", "\\xleftharpoondown"], - "\\yieldsLeftRight": ["\\yields", "\\yieldsLeft"], - "\\equilibrium": ["\\longrightharpoonup", "\\longleftharpoondown"] -}; - -// Browser are not good at stretching stacked arrows such as ⇄. -// So we stack a pair of single arrows. -defineFunction({ - type: "stackedArrow", - names: [ - "\\xtofrom", // expfeil - "\\xleftrightharpoons", // mathtools - "\\xrightleftharpoons", // mathtools - "\\yieldsLeftRight", // mhchem - "\\equilibrium" // mhchem - ], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser, funcName }, args, optArgs) { - const lowerArrowBody = args[0] - ? { - type: "hphantom", - mode: parser.mode, - body: args[0] - } - : null; - const upperArrowBelow = optArgs[0] - ? { - type: "hphantom", - mode: parser.mode, - body: optArgs[0] - } - : null; - return { - type: "stackedArrow", - mode: parser.mode, - label: funcName, - body: args[0], - upperArrowBelow, - lowerArrowBody, - below: optArgs[0] - }; - }, - mathmlBuilder(group, style) { - const topLabel = arrowComponent[group.label][0]; - const botLabel = arrowComponent[group.label][1]; - const topArrow = munderoverNode(topLabel, group.body, group.upperArrowBelow, style); - const botArrow = munderoverNode(botLabel, group.lowerArrowBody, group.below, style); - - const topSpace = new mathMLTree.MathNode("mspace"); - topSpace.setAttribute("width", "0.2778em"); - const botSpace = new mathMLTree.MathNode("mspace"); - botSpace.setAttribute("width", "-0.2778em"); - - const raiseNode = new mathMLTree.MathNode("mpadded", [topSpace, topArrow]); - raiseNode.setAttribute("voffset", "0.3em"); - raiseNode.setAttribute("height", "+0.3em"); - raiseNode.setAttribute("depth", "-0.3em"); - raiseNode.setAttribute("width", "0em"); - - const botRow = new mathMLTree.MathNode("mrow", [botSpace, botArrow]); - - const wrapper = new mathMLTree.MathNode("mpadded", [raiseNode, botRow]); - wrapper.setAttribute("voffset", "-0.18em"); - wrapper.setAttribute("height", "-0.18em"); - wrapper.setAttribute("depth", "+0.18em"); - wrapper.setAttribute("lspace", "0em"); - wrapper.setAttribute("rspace", "0em"); - return wrapper - } -}); - -defineFunction({ - type: "cancelto", - names: ["\\cancelto"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "cancelto", - mode: parser.mode, - value: args[0], - expression: args[1] - }; - }, - mathmlBuilder(group, style) { - const value = new mathMLTree.MathNode( - "mpadded", - [buildGroup(group.value, style)] - ); - value.setAttribute("depth", `-0.1em`); - value.setAttribute("height", `+0.1em`); - value.setAttribute("voffset", `0.1em`); - - const expression = new mathMLTree.MathNode( - "menclose", - [buildGroup(group.expression, style)] - ); - expression.setAttribute("notation", `updiagonalarrow`); - - return new mathMLTree.MathNode("msup", [expression, value]) - } -}); - -/** - * Asserts that the node is of the given type and returns it with stricter - * typing. Throws if the node's type does not match. - */ -function assertNodeType(node, type) { - if (!node || node.type !== type) { - throw new Error( - `Expected node of type ${type}, but got ` + - (node ? `node of type ${node.type}` : String(node)) - ); - } - return node; -} - -/** - * Returns the node more strictly typed iff it is of the given type. Otherwise, - * returns null. - */ -function assertSymbolNodeType(node) { - const typedNode = checkSymbolNodeType(node); - if (!typedNode) { - throw new Error( - `Expected node of symbol group type, but got ` + - (node ? `node of type ${node.type}` : String(node)) - ); - } - return typedNode; -} - -/** - * Returns the node more strictly typed iff it is of the given type. Otherwise, - * returns null. - */ -function checkSymbolNodeType(node) { - if (node && (node.type === "atom" || - Object.prototype.hasOwnProperty.call(NON_ATOMS, node.type))) { - return node; - } - return null; -} - -const cdArrowFunctionName = { - ">": "\\\\cdrightarrow", - "<": "\\\\cdleftarrow", - "=": "\\\\cdlongequal", - A: "\\uparrow", - V: "\\downarrow", - "|": "\\Vert", - ".": "no arrow" -}; - -const newCell = () => { - // Create an empty cell, to be filled below with parse nodes. - return { type: "styling", body: [], mode: "math", scriptLevel: "display" }; -}; - -const isStartOfArrow = (node) => { - return node.type === "textord" && node.text === "@"; -}; - -const isLabelEnd = (node, endChar) => { - return (node.type === "mathord" || node.type === "atom") && node.text === endChar; -}; - -function cdArrow(arrowChar, labels, parser) { - // Return a parse tree of an arrow and its labels. - // This acts in a way similar to a macro expansion. - const funcName = cdArrowFunctionName[arrowChar]; - switch (funcName) { - case "\\\\cdrightarrow": - case "\\\\cdleftarrow": - return parser.callFunction(funcName, [labels[0]], [labels[1]]); - case "\\uparrow": - case "\\downarrow": { - const leftLabel = parser.callFunction("\\\\cdleft", [labels[0]], []); - const bareArrow = { - type: "atom", - text: funcName, - mode: "math", - family: "rel" - }; - const sizedArrow = parser.callFunction("\\Big", [bareArrow], []); - const rightLabel = parser.callFunction("\\\\cdright", [labels[1]], []); - const arrowGroup = { - type: "ordgroup", - mode: "math", - body: [leftLabel, sizedArrow, rightLabel] - }; - return parser.callFunction("\\\\cdparent", [arrowGroup], []); - } - case "\\\\cdlongequal": - return parser.callFunction("\\\\cdlongequal", [], []); - case "\\Vert": { - const arrow = { type: "textord", text: "\\Vert", mode: "math" }; - return parser.callFunction("\\Big", [arrow], []); - } - default: - return { type: "textord", text: " ", mode: "math" }; - } -} - -function parseCD(parser) { - // Get the array's parse nodes with \\ temporarily mapped to \cr. - const parsedRows = []; - parser.gullet.beginGroup(); - parser.gullet.macros.set("\\cr", "\\\\\\relax"); - parser.gullet.beginGroup(); - while (true) { // eslint-disable-line no-constant-condition - // Get the parse nodes for the next row. - parsedRows.push(parser.parseExpression(false, "\\\\")); - parser.gullet.endGroup(); - parser.gullet.beginGroup(); - const next = parser.fetch().text; - if (next === "&" || next === "\\\\") { - parser.consume(); - } else if (next === "\\end") { - if (parsedRows[parsedRows.length - 1].length === 0) { - parsedRows.pop(); // final row ended in \\ - } - break; - } else { - throw new ParseError("Expected \\\\ or \\cr or \\end", parser.nextToken); - } - } - - let row = []; - const body = [row]; - - // Loop thru the parse nodes. Collect them into cells and arrows. - for (let i = 0; i < parsedRows.length; i++) { - // Start a new row. - const rowNodes = parsedRows[i]; - // Create the first cell. - let cell = newCell(); - - for (let j = 0; j < rowNodes.length; j++) { - if (!isStartOfArrow(rowNodes[j])) { - // If a parseNode is not an arrow, it goes into a cell. - cell.body.push(rowNodes[j]); - } else { - // Parse node j is an "@", the start of an arrow. - // Before starting on the arrow, push the cell into `row`. - row.push(cell); - - // Now collect parseNodes into an arrow. - // The character after "@" defines the arrow type. - j += 1; - const arrowChar = assertSymbolNodeType(rowNodes[j]).text; - - // Create two empty label nodes. We may or may not use them. - const labels = new Array(2); - labels[0] = { type: "ordgroup", mode: "math", body: [] }; - labels[1] = { type: "ordgroup", mode: "math", body: [] }; - - // Process the arrow. - if ("=|.".indexOf(arrowChar) > -1) ; else if ("<>AV".indexOf(arrowChar) > -1) { - // Four arrows, `@>>>`, `@<<<`, `@AAA`, and `@VVV`, each take - // two optional labels. E.g. the right-point arrow syntax is - // really: @>{optional label}>{optional label}> - // Collect parseNodes into labels. - for (let labelNum = 0; labelNum < 2; labelNum++) { - let inLabel = true; - for (let k = j + 1; k < rowNodes.length; k++) { - if (isLabelEnd(rowNodes[k], arrowChar)) { - inLabel = false; - j = k; - break; - } - if (isStartOfArrow(rowNodes[k])) { - throw new ParseError( - "Missing a " + arrowChar + " character to complete a CD arrow.", - rowNodes[k] - ); - } - - labels[labelNum].body.push(rowNodes[k]); - } - if (inLabel) { - // isLabelEnd never returned a true. - throw new ParseError( - "Missing a " + arrowChar + " character to complete a CD arrow.", - rowNodes[j] - ); - } - } - } else { - throw new ParseError(`Expected one of "<>AV=|." after @.`); - } - - // Now join the arrow to its labels. - const arrow = cdArrow(arrowChar, labels, parser); - - // Wrap the arrow in a styling node - row.push(arrow); - // In CD's syntax, cells are implicit. That is, everything that - // is not an arrow gets collected into a cell. So create an empty - // cell now. It will collect upcoming parseNodes. - cell = newCell(); - } - } - if (i % 2 === 0) { - // Even-numbered rows consist of: cell, arrow, cell, arrow, ... cell - // The last cell is not yet pushed into `row`, so: - row.push(cell); - } else { - // Odd-numbered rows consist of: vert arrow, empty cell, ... vert arrow - // Remove the empty cell that was placed at the beginning of `row`. - row.shift(); - } - row = []; - body.push(row); - } - - // End row group - parser.gullet.endGroup(); - // End array group defining \\ - parser.gullet.endGroup(); - - // define column separation. - const cols = new Array(body[0].length).fill({ - type: "align", - align: "c" - }); - - return { - type: "array", - mode: "math", - body, - arraystretch: 1, - addJot: true, - rowGaps: [null], - cols, - colSeparationType: "CD", - hLinesBeforeRow: new Array(body.length + 1).fill([]) - }; -} - -// The functions below are not available for general use. -// They are here only for internal use by the {CD} environment in placing labels -// next to vertical arrows. - -// We don't need any such functions for horizontal arrows because we can reuse -// the functionality that already exists for extensible arrows. - -defineFunction({ - type: "cdlabel", - names: ["\\\\cdleft", "\\\\cdright"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - return { - type: "cdlabel", - mode: parser.mode, - side: funcName.slice(4), - label: args[0] - }; - }, - mathmlBuilder(group, style) { - let label = new mathMLTree.MathNode("mrow", [buildGroup(group.label, style)]); - label = new mathMLTree.MathNode("mpadded", [label]); - label.setAttribute("width", "0"); - if (group.side === "left") { - label.setAttribute("lspace", "-1width"); - } - // We have to guess at vertical alignment. We know the arrow is 1.8em tall, - // But we don't know the height or depth of the label. - label.setAttribute("voffset", "0.7em"); - label = new mathMLTree.MathNode("mstyle", [label]); - label.setAttribute("displaystyle", "false"); - label.setAttribute("scriptlevel", "1"); - return label; - } -}); - -defineFunction({ - type: "cdlabelparent", - names: ["\\\\cdparent"], - props: { - numArgs: 1 - }, - handler({ parser }, args) { - return { - type: "cdlabelparent", - mode: parser.mode, - fragment: args[0] - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow", [buildGroup(group.fragment, style)]); - } -}); - -// \@char is an internal function that takes a grouped decimal argument like -// {123} and converts into symbol with code 123. It is used by the *macro* -// \char defined in macros.js. -defineFunction({ - type: "textord", - names: ["\\@char"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser }, args) { - const arg = assertNodeType(args[0], "ordgroup"); - const group = arg.body; - let number = ""; - for (let i = 0; i < group.length; i++) { - const node = assertNodeType(group[i], "textord"); - number += node.text; - } - const code = parseInt(number); - if (isNaN(code)) { - throw new ParseError(`\\@char has non-numeric argument ${number}`) - } - return { - type: "textord", - mode: parser.mode, - text: String.fromCodePoint(code) - } - } -}); - -/* In LaTeX, \colon is defined as: - * \renewcommand{\colon}{\nobreak\mskip2mu\mathpunct{}\nonscript - * \mkern-\thinmuskip{:}\mskip6muplus1mu\relax} - * - * Doing that with a Temml macro produces semantically poor MathML. Do it more directly. - */ - -defineFunction({ - type: "colonFunction", - names: ["\\colon"], - props: { numArgs: 0 }, - handler({ parser }) { return { type: "colonFunction", mode: parser.mode } }, - mathmlBuilder(group, style) { - const mo = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(":")]); - // lspace depends on the script level. - mo.attributes.lspace = (style.level < 2 ? "0.05556em" : "0.1111em"); - mo.attributes.rspace = "0.3333em"; // 6mu - return mo - } -}); - -defineFunction({ - type: "colonequal", - names: [":"], - props: { numArgs: 0 }, - handler({ parser }, args) { - if (parser.fetch().text === "=") { - // Special case for := - parser.consume(); - return { type: "colonequal", mode: parser.mode } - } - return { type: "atom", family: "rel", text: ":", mode: parser.mode } - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u2254")]) - } -}); - -// Helpers -const htmlRegEx = /^(#[a-f0-9]{3}|#?[a-f0-9]{6})$/i; -const htmlOrNameRegEx = /^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i; -const RGBregEx = /^ *\d{1,3} *(?:, *\d{1,3} *){2}$/; -const rgbRegEx = /^ *[10](?:\.\d*)? *(?:, *[10](?:\.\d*)? *){2}$/; -const xcolorHtmlRegEx = /^[a-f0-9]{6}$/i; -const toHex = num => { - let str = num.toString(16); - if (str.length === 1) { str = "0" + str; } - return str -}; - -// Colors from Tables 4.1 and 4.2 of the xcolor package. -// Table 4.1 (lower case) RGB values are taken from chroma and xcolor.dtx. -// Table 4.2 (Capitalizzed) values were sampled, because Chroma contains a unreliable -// conversion from cmyk to RGB. See https://tex.stackexchange.com/a/537274. -const xcolors = JSON.parse(`{ - "Apricot": "#ffb484", - "Aquamarine": "#08b4bc", - "Bittersweet": "#c84c14", - "blue": "#0000FF", - "Blue": "#303494", - "BlueGreen": "#08b4bc", - "BlueViolet": "#503c94", - "BrickRed": "#b8341c", - "brown": "#BF804", - "Brown": "#802404", - "BurntOrange": "#f8941c", - "CadetBlue": "#78749c", - "CarnationPink": "#f884b4", - "Cerulean": "#08a4e4", - "CornflowerBlue": "#40ace4", - "cyan": "#00FFF", - "Cyan": "#08acec", - "Dandelion": "#ffbc44", - "darkgray": "#404040", - "DarkOrchid": "#a8548c", - "Emerald": "#08ac9c", - "ForestGreen": "#089c54", - "Fuchsia": "#90348c", - "Goldenrod": "#ffdc44", - "gray": "#80808", - "Gray": "#98949c", - "green": "#00FF0", - "Green": "#08a44c", - "GreenYellow": "#e0e474", - "JungleGreen": "#08ac9c", - "Lavender": "#f89cc4", - "lightgray": "#BFBFB", - "lime": "#BFFF00", - "LimeGreen": "#90c43c", - "magenta": "#FF00F", - "Magenta": "#f0048c", - "Mahogany": "#b0341c", - "Maroon": "#b03434", - "Melon": "#f89c7c", - "MidnightBlue": "#086494", - "Mulberry": "#b03c94", - "NavyBlue": "#086cbc", - "olive": "#7F7F00", - "OliveGreen": "#407c34", - "orange": "#FF800", - "Orange": "#f8843c", - "OrangeRed": "#f0145c", - "Orchid": "#b074ac", - "Peach": "#f8945c", - "Periwinkle": "#8074bc", - "PineGreen": "#088c74", - "pink": "#ff7f7f", - "Plum": "#98248c", - "ProcessBlue": "#08b4ec", - "purple": "#BF0040", - "Purple": "#a0449c", - "RawSienna": "#983c04", - "red": "#ff0000", - "Red": "#f01c24", - "RedOrange": "#f86434", - "RedViolet": "#a0246c", - "Rhodamine": "#f0549c", - "Royallue": "#0874bc", - "RoyalPurple": "#683c9c", - "RubineRed": "#f0047c", - "Salmon": "#f8948c", - "SeaGreen": "#30bc9c", - "Sepia": "#701404", - "SkyBlue": "#48c4dc", - "SpringGreen": "#c8dc64", - "Tan": "#e09c74", - "teal": "#007F7F", - "TealBlue": "#08acb4", - "Thistle": "#d884b4", - "Turquoise": "#08b4cc", - "violet": "#800080", - "Violet": "#60449c", - "VioletRed": "#f054a4", - "WildStrawberry": "#f0246c", - "yellow": "#FFFF00", - "Yellow": "#fff404", - "YellowGreen": "#98cc6c", - "YellowOrange": "#ffa41c" -}`); - -const colorFromSpec = (model, spec) => { - let color = ""; - if (model === "HTML") { - if (!htmlRegEx.test(spec)) { - throw new ParseError("Invalid HTML input.") - } - color = spec; - } else if (model === "RGB") { - if (!RGBregEx.test(spec)) { - throw new ParseError("Invalid RGB input.") - } - spec.split(",").map(e => { color += toHex(Number(e.trim())); }); - } else { - if (!rgbRegEx.test(spec)) { - throw new ParseError("Invalid rbg input.") - } - spec.split(",").map(e => { - const num = Number(e.trim()); - if (num > 1) { throw new ParseError("Color rgb input must be < 1.") } - color += toHex((num * 255)); - }); - } - if (color.charAt(0) !== "#") { color = "#" + color; } - return color -}; - -const validateColor = (color, macros) => { - const macroName = `\\\\color@${color}`; // from \defineColor. - const match = htmlOrNameRegEx.exec(color); - if (!match) { throw new ParseError("Invalid color: '" + color + "'") } - // We allow a 6-digit HTML color spec without a leading "#". - // This follows the xcolor package's HTML color model. - // Predefined color names are all missed by this RegEx pattern. - if (xcolorHtmlRegEx.test(color)) { - return "#" + color - } else if (color.charAt(0) === "#") { - return color - } else if (macros.has(macroName)) { - color = macros.get(macroName).tokens[0].text; - } else if (xcolors[color]) { - color = xcolors[color]; - } - return color -}; - -const mathmlBuilder$1 = (group, style) => { - const inner = buildExpression(group.body, style.withColor(group.color)); - // Wrap with an element. - const node = wrapWithMstyle(inner); - node.setAttribute("mathcolor", group.color); - // Wrap w/. We get better operator spacing that way. - return new mathMLTree.MathNode("mrow", [node]) -}; - -defineFunction({ - type: "color", - names: ["\\textcolor"], - props: { - numArgs: 2, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "original"] - }, - handler({ parser }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let color = ""; - if (model) { - const spec = assertNodeType(args[0], "raw").string; - color = colorFromSpec(model, spec); - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros); - } - const body = args[1]; - return { - type: "color", - mode: parser.mode, - color, - body: ordargument(body) - } - }, - mathmlBuilder: mathmlBuilder$1 -}); - -defineFunction({ - type: "color", - names: ["\\color"], - props: { - numArgs: 1, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw"] - }, - handler({ parser, breakOnTokenText }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let color = ""; - if (model) { - const spec = assertNodeType(args[0], "raw").string; - color = colorFromSpec(model, spec); - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros); - } - - // Set macro \current@color in current namespace to store the current - // color, mimicking the behavior of color.sty. - // This is currently used just to correctly color a \right - // that follows a \color command. - parser.gullet.macros.set("\\current@color", color); - - // Parse out the implicit body that should be colored. - // Since \color nodes should not be nested, break on \color. - const body = parser.parseExpression(true, "\\color"); - - return { - type: "color", - mode: parser.mode, - color, - body - } - }, - mathmlBuilder: mathmlBuilder$1 -}); - -defineFunction({ - type: "color", - names: ["\\definecolor"], - props: { - numArgs: 3, - allowedInText: true, - argTypes: ["raw", "raw", "raw"] - }, - handler({ parser }, args) { - const name = assertNodeType(args[0], "raw").string; - if (!/^[A-Za-z]+$/.test(name)) { - throw new ParseError("Color name must be latin letters.") - } - const model = assertNodeType(args[1], "raw").string; - if (!["HTML", "RGB", "rgb"].includes(model)) { - throw new ParseError("Color model must be HTML, RGB, or rgb.") - } - const spec = assertNodeType(args[2], "raw").string; - const color = colorFromSpec(model, spec); - parser.gullet.macros.set(`\\\\color@${name}`, { tokens: [{ text: color }], numArgs: 0 }); - return { type: "internal", mode: parser.mode } - } - // No mathmlBuilder. The point of \definecolor is to set a macro. -}); - -/** - * This file does conversion between units. In particular, it provides - * calculateSize to convert other units into CSS units. - */ - -const ptPerUnit = { - // Convert to CSS (Postscipt) points, not TeX points - // https://en.wikibooks.org/wiki/LaTeX/Lengths and - // https://tex.stackexchange.com/a/8263 - pt: 800 / 803, // convert TeX point to CSS (Postscript) point - pc: (12 * 800) / 803, // pica - dd: ((1238 / 1157) * 800) / 803, // didot - cc: ((14856 / 1157) * 800) / 803, // cicero (12 didot) - nd: ((685 / 642) * 800) / 803, // new didot - nc: ((1370 / 107) * 800) / 803, // new cicero (12 new didot) - sp: ((1 / 65536) * 800) / 803 // scaled point (TeX's internal smallest unit) -}; - -/** - * Determine whether the specified unit (either a string defining the unit - * or a "size" parse node containing a unit field) is valid. - */ -const validUnits = [ - "em", - "ex", - "mu", - "pt", - "mm", - "cm", - "in", - "px", - "bp", - "pc", - "dd", - "cc", - "nd", - "nc", - "sp" -]; - -const validUnit = function(unit) { - if (typeof unit !== "string") { - unit = unit.unit; - } - return validUnits.indexOf(unit) > -1 -}; - -const emScale = styleLevel => { - const scriptLevel = Math.max(styleLevel - 1, 0); - return [1, 0.7, 0.5][scriptLevel] -}; - -/* - * Convert a "size" parse node (with numeric "number" and string "unit" fields, - * as parsed by functions.js argType "size") into a CSS value. - */ -const calculateSize = function(sizeValue, style) { - const number = sizeValue.number; - const unit = sizeValue.unit; - switch (unit) { - case "mm": - case "cm": - case "in": - case "px": - return { number, unit }; // absolute CSS units. - case "em": - case "ex": - // In TeX, em and ex do not change size in \scriptstyle. - return { number: utils.round(number / emScale(style.level)), unit }; - case "bp": - return { number, unit: "pt" }; // TeX bp is a CSS pt. (1/72 inch). - case "pt": - case "pc": - case "dd": - case "cc": - case "nd": - case "nc": - case "sp": - return { number: utils.round(number * ptPerUnit[unit]), unit: "pt" } - case "mu": { - return { number: utils.round(number / 18), unit: "em" } - } - default: - throw new ParseError("Invalid unit: '" + unit + "'") - } -}; - -// Row breaks within tabular environments, and line breaks at top level - -// \DeclareRobustCommand\\{...\@xnewline} -defineFunction({ - type: "cr", - names: ["\\\\"], - props: { - numArgs: 0, - numOptionalArgs: 1, - argTypes: ["size"], - allowedInText: true - }, - - handler({ parser }, args, optArgs) { - const size = optArgs[0]; - if (parser.settings.displayMode && parser.settings.strict === "warn") { - parser.settings.reportNonstrict( - "newLineInDisplayMode", - "In LaTeX, \\\\ or \\newline " + "does nothing in display mode" - ); - } - const newLine = !parser.settings.displayMode || parser.settings.strict !== true; - return { - type: "cr", - mode: parser.mode, - newLine, - size: size && assertNodeType(size, "size").value - } - }, - - // The following builder is called only at the top level, - // not within tabular/array environments. - - mathmlBuilder(group, style) { - // MathML 3.0 calls for newline to occur in an or an . - // Ref: https://www.w3.org/TR/MathML3/chapter3.html#presm.linebreaking - const node = new mathMLTree.MathNode("mo"); - if (group.newLine) { - node.setAttribute("linebreak", "newline"); - if (group.size) { - const size = calculateSize(group.size, style); - node.setAttribute("height", size.number + size.unit); - } - } - return node - } -}); - -const checkControlSequence = (tok) => { - const name = tok.text; - if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { - throw new ParseError("Expected a control sequence", tok); - } - return name; -}; - -const getRHS = (parser) => { - let tok = parser.gullet.popToken(); - if (tok.text === "=") { - // consume optional equals - tok = parser.gullet.popToken(); - if (tok.text === " ") { - // consume one optional space - tok = parser.gullet.popToken(); - } - } - return tok; -}; - -const letCommand = (parser, name, tok) => { - let macro = parser.gullet.macros.get(tok.text); - if (macro == null) { - // don't expand it later even if a macro with the same name is defined - // e.g., \let\foo=\frac \def\frac{\relax} \frac12 - tok.noexpand = true; - macro = { - tokens: [tok], - numArgs: 0, - // reproduce the same behavior in expansion - unexpandable: !parser.gullet.isExpandable(tok.text) - }; - } - parser.gullet.macros.set(name, macro); -}; - -// Basic support for macro definitions: \def -// -> -// -> -defineFunction({ - type: "internal", - names: ["\\def", "\\edef"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - let tok = parser.gullet.popToken(); - const name = tok.text; - if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) { - throw new ParseError("Expected a control sequence", tok); - } - - let numArgs = 0; - let insert; - const delimiters = [[]]; - // contains no braces - while (parser.gullet.future().text !== "{") { - tok = parser.gullet.popToken(); - if (tok.text === "#") { - // If the very last character of the is #, so that - // this # is immediately followed by {, TeX will behave as if the { - // had been inserted at the right end of both the parameter text - // and the replacement text. - if (parser.gullet.future().text === "{") { - insert = parser.gullet.future(); - delimiters[numArgs].push("{"); - break; - } - - // A parameter, the first appearance of # must be followed by 1, - // the next by 2, and so on; up to nine #’s are allowed - tok = parser.gullet.popToken(); - if (!/^[1-9]$/.test(tok.text)) { - throw new ParseError(`Invalid argument number "${tok.text}"`); - } - if (parseInt(tok.text) !== numArgs + 1) { - throw new ParseError(`Argument number "${tok.text}" out of order`); - } - numArgs++; - delimiters.push([]); - } else if (tok.text === "EOF") { - throw new ParseError("Expected a macro definition"); - } else { - delimiters[numArgs].push(tok.text); - } - } - // replacement text, enclosed in '{' and '}' and properly nested - let { tokens } = parser.gullet.consumeArg(); - if (insert) { - tokens.unshift(insert); - } - - if (funcName === "\\edef") { - tokens = parser.gullet.expandTokens(tokens); - tokens.reverse(); // to fit in with stack order - } - // Final arg is the expansion of the macro - parser.gullet.macros.set(name, { tokens, numArgs, delimiters } - ); - return { type: "internal", mode: parser.mode }; - } -}); - -// -> -// -> \futurelet -// | \let -// -> |= -defineFunction({ - type: "internal", - names: ["\\let"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - const name = checkControlSequence(parser.gullet.popToken()); - parser.gullet.consumeSpaces(); - const tok = getRHS(parser); - letCommand(parser, name, tok); - return { type: "internal", mode: parser.mode }; - } -}); - -// ref: https://www.tug.org/TUGboat/tb09-3/tb22bechtolsheim.pdf -defineFunction({ - type: "internal", - names: ["\\futurelet"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - const name = checkControlSequence(parser.gullet.popToken()); - const middle = parser.gullet.popToken(); - const tok = parser.gullet.popToken(); - letCommand(parser, name, tok); - parser.gullet.pushToken(tok); - parser.gullet.pushToken(middle); - return { type: "internal", mode: parser.mode }; - } -}); - -defineFunction({ - type: "internal", - names: ["\\newcommand", "\\renewcommand", "\\providecommand"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ parser, funcName }) { - let name = ""; - const tok = parser.gullet.popToken(); - if (tok.text === "{") { - name = checkControlSequence(parser.gullet.popToken()); - parser.gullet.popToken(); - } else { - name = checkControlSequence(tok); - } - - const exists = parser.gullet.isDefined(name); - if (exists && funcName === "\\newcommand") { - throw new ParseError( - `\\newcommand{${name}} attempting to redefine ${name}; use \\renewcommand` - ); - } - if (!exists && funcName === "\\renewcommand") { - throw new ParseError( - `\\renewcommand{${name}} when command ${name} does not yet exist; use \\newcommand` - ); - } - - let numArgs = 0; - if (parser.gullet.future().text === "[") { - let tok = parser.gullet.popToken(); - tok = parser.gullet.popToken(); - if (!/^[0-9]$/.test(tok.text)) { - throw new ParseError(`Invalid number of arguments: "${tok.text}"`); - } - numArgs = parseInt(tok.text); - tok = parser.gullet.popToken(); - if (tok.text !== "]") { - throw new ParseError(`Invalid argument "${tok.text}"`); - } - } - - // replacement text, enclosed in '{' and '}' and properly nested - const { tokens } = parser.gullet.consumeArg(); - - parser.gullet.macros.set(name, { tokens, numArgs }); - - return { type: "internal", mode: parser.mode }; - - } -}); - -// Extra data needed for the delimiter handler down below -const delimiterSizes = { - "\\bigl": { mclass: "mopen", size: 1 }, - "\\Bigl": { mclass: "mopen", size: 2 }, - "\\biggl": { mclass: "mopen", size: 3 }, - "\\Biggl": { mclass: "mopen", size: 4 }, - "\\bigr": { mclass: "mclose", size: 1 }, - "\\Bigr": { mclass: "mclose", size: 2 }, - "\\biggr": { mclass: "mclose", size: 3 }, - "\\Biggr": { mclass: "mclose", size: 4 }, - "\\bigm": { mclass: "mrel", size: 1 }, - "\\Bigm": { mclass: "mrel", size: 2 }, - "\\biggm": { mclass: "mrel", size: 3 }, - "\\Biggm": { mclass: "mrel", size: 4 }, - "\\big": { mclass: "mord", size: 1 }, - "\\Big": { mclass: "mord", size: 2 }, - "\\bigg": { mclass: "mord", size: 3 }, - "\\Bigg": { mclass: "mord", size: 4 } -}; - -const delimiters = [ - "(", - "\\lparen", - ")", - "\\rparen", - "[", - "\\lbrack", - "]", - "\\rbrack", - "\\{", - "\\lbrace", - "\\}", - "\\rbrace", - "\\lfloor", - "\\rfloor", - "\u230a", - "\u230b", - "\\lceil", - "\\rceil", - "\u2308", - "\u2309", - "<", - ">", - "\\langle", - "\u27e8", - "\\rangle", - "\u27e9", - "\\lt", - "\\gt", - "\\lvert", - "\\rvert", - "\\lVert", - "\\rVert", - "\\lgroup", - "\\rgroup", - "\u27ee", - "\u27ef", - "\\lmoustache", - "\\rmoustache", - "\u23b0", - "\u23b1", - "\\llbracket", - "\\rrbracket", - "\u27e6", - "\u27e6", - "\\lBrace", - "\\rBrace", - "\u2983", - "\u2984", - "/", - "\\backslash", - "|", - "\\vert", - "\\|", - "\\Vert", - "\\uparrow", - "\\Uparrow", - "\\downarrow", - "\\Downarrow", - "\\updownarrow", - "\\Updownarrow", - "." -]; - -// Metrics of the different sizes. Found by looking at TeX's output of -// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$ -// Used to create stacked delimiters of appropriate sizes in makeSizedDelim. -const sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0]; - -// Delimiter functions -function checkDelimiter(delim, context) { - if (delim.type === "ordgroup" && delim.body.length === 1 && delim.body[0].text === "\u2044") { - // Recover "/" from the zero spacing group. (See macros.js) - delim = { type: "textord", text: "/", mode: "math" }; - } - const symDelim = checkSymbolNodeType(delim); - if (symDelim && utils.contains(delimiters, symDelim.text)) { - // If a character is not in the MathML operator dictionary, it will not stretch. - // Replace such characters w/characters that will stretch. - if (utils.contains(["<", "\\lt"], symDelim.text)) { symDelim.text = "⟨"; } - if (utils.contains([">", "\\gt"], symDelim.text)) { symDelim.text = "⟩"; } - if (symDelim.text === "/") { symDelim.text = "\u2215"; } - if (symDelim.text === "\\backslash") { symDelim.text = "\u2216"; } - return symDelim; - } else if (symDelim) { - throw new ParseError(`Invalid delimiter '${symDelim.text}' after '${context.funcName}'`, delim); - } else { - throw new ParseError(`Invalid delimiter type '${delim.type}'`, delim); - } -} - -defineFunction({ - type: "delimsizing", - names: [ - "\\bigl", - "\\Bigl", - "\\biggl", - "\\Biggl", - "\\bigr", - "\\Bigr", - "\\biggr", - "\\Biggr", - "\\bigm", - "\\Bigm", - "\\biggm", - "\\Biggm", - "\\big", - "\\Big", - "\\bigg", - "\\Bigg" - ], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - - return { - type: "delimsizing", - mode: context.parser.mode, - size: delimiterSizes[context.funcName].size, - mclass: delimiterSizes[context.funcName].mclass, - delim: delim.text - }; - }, - mathmlBuilder: (group) => { - const children = []; - - if (group.delim === ".") { group.delim = ""; } - children.push(makeText(group.delim, group.mode)); - - const node = new mathMLTree.MathNode("mo", children); - - if (group.mclass === "mopen" || group.mclass === "mclose") { - // Only some of the delimsizing functions act as fences, and they - // return "mopen" or "mclose" mclass. - node.setAttribute("fence", "true"); - } else { - // Explicitly disable fencing if it's not a fence, to override the - // defaults. - node.setAttribute("fence", "false"); - } - if (group.delim === "\u2216") { - // \backslash is not in the operator dictionary, - // so we have to explicitly set stretchy to true. - node.setAttribute("stretchy", "true"); - } - - node.setAttribute("symmetric", "true"); // Needed for tall arrows in Firefox. - node.setAttribute("minsize", sizeToMaxHeight[group.size] + "em"); - node.setAttribute("maxsize", sizeToMaxHeight[group.size] + "em"); - - return node; - } -}); - -function assertParsed(group) { - if (!group.body) { - throw new Error("Bug: The leftright ParseNode wasn't fully parsed."); - } -} - -defineFunction({ - type: "leftright-right", - names: ["\\right"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - // \left case below triggers parsing of \right in - // `const right = parser.parseFunction();` - // uses this return value. - const color = context.parser.gullet.macros.get("\\current@color"); - if (color && typeof color !== "string") { - throw new ParseError("\\current@color set to non-string in \\right"); - } - return { - type: "leftright-right", - mode: context.parser.mode, - delim: checkDelimiter(args[0], context).text, - color // undefined if not set via \color - }; - } -}); - -defineFunction({ - type: "leftright", - names: ["\\left"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - - const parser = context.parser; - // Parse out the implicit body - ++parser.leftrightDepth; - // parseExpression stops before '\\right' - const body = parser.parseExpression(false); - --parser.leftrightDepth; - // Check the next token - parser.expect("\\right", false); - const right = assertNodeType(parser.parseFunction(), "leftright-right"); - return { - type: "leftright", - mode: parser.mode, - body, - left: delim.text, - right: right.delim, - rightColor: right.color - }; - }, - mathmlBuilder: (group, style) => { - assertParsed(group); - const inner = buildExpression(group.body, style); - - if (group.left === ".") { group.left = ""; } - const leftNode = new mathMLTree.MathNode("mo", [makeText(group.left, group.mode)]); - leftNode.setAttribute("fence", "true"); - leftNode.setAttribute("form", "prefix"); - if (group.left === "\u2216") { leftNode.setAttribute("stretchy", "true"); } - inner.unshift(leftNode); - - if (group.right === ".") { group.right = ""; } - const rightNode = new mathMLTree.MathNode("mo", [makeText(group.right, group.mode)]); - rightNode.setAttribute("fence", "true"); - rightNode.setAttribute("form", "postfix"); - if (group.right === "\u2216") { rightNode.setAttribute("stretchy", "true"); } - if (group.rightColor) { rightNode.setAttribute("mathcolor", group.rightColor); } - inner.push(rightNode); - - return makeRow(inner); - } -}); - -defineFunction({ - type: "middle", - names: ["\\middle"], - props: { - numArgs: 1, - argTypes: ["primitive"] - }, - handler: (context, args) => { - const delim = checkDelimiter(args[0], context); - if (!context.parser.leftrightDepth) { - throw new ParseError("\\middle without preceding \\left", delim); - } - - return { - type: "middle", - mode: context.parser.mode, - delim: delim.text - }; - }, - mathmlBuilder: (group, style) => { - const textNode = makeText(group.delim, group.mode); - const middleNode = new mathMLTree.MathNode("mo", [textNode]); - middleNode.setAttribute("fence", "true"); - // MathML gives 5/18em spacing to each element. - // \middle should get delimiter spacing instead. - middleNode.setAttribute("lspace", "0.05em"); - middleNode.setAttribute("rspace", "0.05em"); - return middleNode; - } -}); - -const mathmlBuilder$2 = (group, style) => { - const node = new mathMLTree.MathNode( - group.label.indexOf("colorbox") > -1 ? "mpadded" : "menclose", - [buildGroup(group.body, style)] - ); - switch (group.label) { - case "\\cancel": - node.setAttribute("notation", "updiagonalstrike"); - break; - case "\\bcancel": - node.setAttribute("notation", "downdiagonalstrike"); - break; - case "\\longdiv": - node.setAttribute("notation", "longdiv"); - break; - case "\\phase": - node.setAttribute("notation", "phasorangle"); - break; - case "\\sout": - node.setAttribute("notation", "horizontalstrike"); - break; - case "\\fbox": - node.setAttribute("notation", "box"); - break; - case "\\angl": - node.setAttribute("notation", "actuarial"); - break; - case "\\fcolorbox": - case "\\colorbox": { - // doesn't have a good notation option for \colorbox. - // So use instead. Set some attributes that come - // included with . - const fboxsep = 3; // 3 pt from LaTeX source2e - node.setAttribute("width", `+${2 * fboxsep}pt`); - node.setAttribute("height", `+${2 * fboxsep}pt`); - node.setAttribute("lspace", `${fboxsep}pt`); // - node.setAttribute("voffset", `${fboxsep}pt`); - if (group.label === "\\fcolorbox") { - node.setAttribute("style", "border: 0.06em solid " + String(group.borderColor)); - } - break; - } - case "\\xcancel": - node.setAttribute("notation", "updiagonalstrike downdiagonalstrike"); - break; - } - if (group.backgroundColor) { - node.setAttribute("mathbackground", group.backgroundColor); - } - return node; -}; - -defineFunction({ - type: "enclose", - names: ["\\colorbox"], - props: { - numArgs: 2, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "text"] - }, - handler({ parser, funcName }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let color = ""; - if (model) { - const spec = assertNodeType(args[0], "raw").string; - color = colorFromSpec(model, spec); - } else { - color = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros); - } - const body = args[1]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - backgroundColor: color, - body - }; - }, - mathmlBuilder: mathmlBuilder$2 -}); - -defineFunction({ - type: "enclose", - names: ["\\fcolorbox"], - props: { - numArgs: 3, - numOptionalArgs: 1, - allowedInText: true, - argTypes: ["raw", "raw", "raw", "text"] - }, - handler({ parser, funcName }, args, optArgs) { - const model = optArgs[0] && assertNodeType(optArgs[0], "raw").string; - let borderColor = ""; - let backgroundColor; - if (model) { - const borderSpec = assertNodeType(args[0], "raw").string; - const backgroundSpec = assertNodeType(args[0], "raw").string; - borderColor = colorFromSpec(model, borderSpec); - backgroundColor = colorFromSpec(model, backgroundSpec); - } else { - borderColor = validateColor(assertNodeType(args[0], "raw").string, parser.gullet.macros); - backgroundColor = validateColor(assertNodeType(args[1], "raw").string, parser.gullet.macros); - } - const body = args[2]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - backgroundColor, - borderColor, - body - }; - }, - mathmlBuilder: mathmlBuilder$2 -}); - -defineFunction({ - type: "enclose", - names: ["\\fbox"], - props: { - numArgs: 1, - argTypes: ["hbox"], - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "enclose", - mode: parser.mode, - label: "\\fbox", - body: args[0] - }; - } -}); - -defineFunction({ - type: "enclose", - names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\angl", "\\phase", "\\longdiv"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - const body = args[0]; - return { - type: "enclose", - mode: parser.mode, - label: funcName, - body - }; - }, - mathmlBuilder: mathmlBuilder$2 -}); - -/** - * All registered environments. - * `environments.js` exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary via `environments.js`. - */ -const _environments = {}; - -function defineEnvironment({ type, names, props, handler, mathmlBuilder }) { - // Set default values of environments. - const data = { - type, - numArgs: props.numArgs || 0, - allowedInText: false, - numOptionalArgs: 0, - handler - }; - for (let i = 0; i < names.length; ++i) { - _environments[names[i]] = data; - } - if (mathmlBuilder) { - _mathmlGroupBuilders[type] = mathmlBuilder; - } -} - -// In TeX, there are actually three sets of dimensions, one for each of - -// Math style is not quite the same thing as script level. -const StyleLevel = { - DISPLAY: 0, - TEXT: 1, - SCRIPT: 2, - SCRIPTSCRIPT: 3 -}; - -// Helper functions -function getHLines(parser) { - // Return an array. The array length = number of hlines. - // Each element in the array tells if the line is dashed. - const hlineInfo = []; - parser.consumeSpaces(); - let nxt = parser.fetch().text; - while (nxt === "\\hline" || nxt === "\\hdashline") { - parser.consume(); - hlineInfo.push(nxt === "\\hdashline"); - parser.consumeSpaces(); - nxt = parser.fetch().text; - } - return hlineInfo; -} - -const validateAmsEnvironmentContext = context => { - const settings = context.parser.settings; - if (!settings.displayMode) { - throw new ParseError(`{${context.envName}} can be used only in` + - ` display mode.`); - } -}; - -const getTag = (group, style, rowNum) => { - let tag; - const tagContents = group.tags.shift(); - if (tagContents) { - // The author has written a \tag or a \notag in this row. - if (tagContents.body) { - tag = buildExpressionRow(tagContents.body, style); - tag.classes = ["tml-tag"]; - } else { - // \notag. Return an empty cell. - tag = new mathMLTree.MathNode("mtd", []); - tag.setAttribute("style", "padding: 0; min-width:0"); - return tag - } - } else if (group.colSeparationType === "multline" && - ((group.leqno && rowNum !== 0) || (!group.leqno && rowNum !== group.body.length - 1))) { - // A multiline that does not receive a tag. Return an empty cell. - tag = new mathMLTree.MathNode("mtd", []); - tag.setAttribute("style", "padding: 0; min-width:0"); - return tag - } else { - // AMS automatcally numbered equaton. - // Insert a class so the element can be populated by a post-processor. - tag = new mathMLTree.MathNode("mtext", [], ["tml-eqn"]); - } - if (!group.preventTagLap) { - tag = new mathMLTree.MathNode("mpadded", [tag]); - tag.setAttribute("style", "width:0;"); - tag.setAttribute("width", "0"); - if (!group.leqno) { tag.setAttribute("lspace", "-1width"); } - } - tag = new mathMLTree.MathNode("mtd", [tag]); - if (!group.preventTagLap) { tag.setAttribute("style", "padding: 0; min-width:0"); } - return tag -}; - -/** - * Parse the body of the environment, with rows delimited by \\ and - * columns delimited by &, and create a nested list in row-major order - * with one group per cell. If given an optional argument scriptLevel - * ("text", "display", etc.), then each cell is cast into that scriptLevel. - */ -function parseArray( - parser, - { - hskipBeforeAndAfter, // boolean - addJot, // boolean - cols, // [{ type: string , align: l|c|r|null }] - arraystretch, // number - colSeparationType, // "align" | "alignat" | "gather" | "small" | "CD" | "multline" - addEqnNum, // boolean - singleRow, // boolean - emptySingleRow, // boolean - maxNumCols, // number - leqno // boolean - }, - scriptLevel -) { - parser.gullet.beginGroup(); - if (!singleRow) { - // \cr is equivalent to \\ without the optional size argument (see below) - // TODO: provide helpful error when \cr is used outside array environment - parser.gullet.macros.set("\\cr", "\\\\\\relax"); - } - if (addEqnNum) { - parser.gullet.macros.set("\\tag", "\\env@tag{\\text{#1}}"); - parser.gullet.macros.set("\\notag", "\\env@notag"); - parser.gullet.macros.set("\\nonumber", "\\env@notag"); - } - - // Get current arraystretch if it's not set by the environment - if (arraystretch === undefined || Number.isNaN(arraystretch)) { - const stretch = parser.gullet.expandMacroAsText("\\arraystretch"); - if (stretch == null) { - // Default \arraystretch from lttab.dtx - arraystretch = 1; - } else { - arraystretch = parseFloat(stretch); - if (!arraystretch || arraystretch < 0) { - throw new ParseError(`Invalid \\arraystretch: ${stretch}`); - } - } - } - - // Start group for first cell - parser.gullet.beginGroup(); - - let row = []; - const body = [row]; - const rowGaps = []; - const tags = []; - let rowTag; - const hLinesBeforeRow = []; - - // Test for \hline at the top of the array. - hLinesBeforeRow.push(getHLines(parser)); - - // eslint-disable-next-line no-constant-condition - while (true) { - // Parse each cell in its own group (namespace) - let cell = parser.parseExpression(false, singleRow ? "\\end" : "\\\\"); - - if (addEqnNum && !rowTag) { - // Check if the author wrote a \tag{} inside this cell. - for (let i = 0; i < cell.length; i++) { - if (cell[i].type === "envTag" || cell[i].type === "noTag") { - // Get the contents of the \text{} nested inside the \env@Tag{} - rowTag = cell[i].type === "envTag" - ? cell.splice(i, 1)[0].body.body[0] - : { body: null }; - break - } - } - } - parser.gullet.endGroup(); - parser.gullet.beginGroup(); - - cell = { - type: "ordgroup", - mode: parser.mode, - body: cell - }; - row.push(cell); - const next = parser.fetch().text; - if (next === "&") { - if (maxNumCols && row.length === maxNumCols) { - if (singleRow || colSeparationType) { - // {equation} or {split} - throw new ParseError("Too many tab characters: &", parser.nextToken); - } else { - // {array} environment - parser.settings.reportNonstrict( - "textEnv", - "Too few columns " + "specified in the {array} column argument." - ); - } - } - parser.consume(); - } else if (next === "\\end") { - // Arrays terminate newlines with `\crcr` which consumes a `\cr` if - // the last line is empty. However, AMS environments keep the - // empty row if it's the only one. - // NOTE: Currently, `cell` is the last item added into `row`. - if (row.length === 1 && cell.body.length === 0 && (body.length > 1 || !emptySingleRow)) { - body.pop(); - } - if (hLinesBeforeRow.length < body.length + 1) { - hLinesBeforeRow.push([]); - } - break; - } else if (next === "\\\\") { - parser.consume(); - let size; - // \def\Let@{\let\\\math@cr} - // \def\math@cr{...\math@cr@} - // \def\math@cr@{\new@ifnextchar[\math@cr@@{\math@cr@@[\z@]}} - // \def\math@cr@@[#1]{...\math@cr@@@...} - // \def\math@cr@@@{\cr} - if (parser.gullet.future().text !== " ") { - size = parser.parseSizeGroup(true); - } - rowGaps.push(size ? size.value : null); - - tags.push(rowTag); - - // check for \hline(s) following the row separator - hLinesBeforeRow.push(getHLines(parser)); - - row = []; - rowTag = null; - body.push(row); - } else { - throw new ParseError("Expected & or \\\\ or \\cr or \\end", parser.nextToken); - } - } - - // End cell group - parser.gullet.endGroup(); - // End array group defining \cr - parser.gullet.endGroup(); - - tags.push(rowTag); - - return { - type: "array", - mode: parser.mode, - addJot, - arraystretch, - body, - cols, - rowGaps, - hskipBeforeAndAfter, - hLinesBeforeRow, - colSeparationType, - addEqnNum, - scriptLevel, - tags, - leqno, - preventTagLap: parser.settings.preventTagLap - }; -} - -// Decides on a scriptLevel for cells in an array according to whether the given -// environment name starts with the letter 'd'. -function dCellStyle(envName) { - return envName.substr(0, 1) === "d" ? "display" : "text" -} - -const alignMap = { - c: "center ", - l: "left ", - r: "right " -}; - -const mathmlBuilder$3 = function(group, style) { - const tbl = []; - const numRows = group.body.length; - let glue; - if (group.addEqnNum) { - glue = new mathMLTree.MathNode("mtd", [], []); - const glueStyle = "padding: 0;width: " + - (group.colSeparationType === "multline" ? "7.5%" : "50%"); - glue.setAttribute("style", glueStyle); - } - - for (let i = 0; i < numRows; i++) { - const rw = group.body[i]; - const row = []; - const cellStyle = group.scriptLevel === "text" - ? StyleLevel.TEXT - : group.scriptLevel === "script" - ? StyleLevel.SCRIPT - : StyleLevel.DISPLAY; - - for (let j = 0; j < rw.length; j++) { - const mtd = new mathMLTree.MathNode( - "mtd", - [buildGroup(rw[j], style.withLevel(cellStyle))] - ); - if (group.colSeparationType === "multline") { - const align = i === 0 ? "left" : i === numRows - 1 ? "right" : "center"; - mtd.setAttribute("columnalign", align); - } - row.push(mtd); - } - if (group.addEqnNum) { - row.unshift(glue); - row.push(glue); - const tag = getTag(group, style.withLevel(cellStyle), i); - if (group.leqno) { - row.unshift(tag); - } else { - row.push(tag); - } - } - // If group.addEqnNum, insert a breadcrumb to be found by temmlPostProcess(). - tbl.push(new mathMLTree.MathNode("mtr", row, group.addEqnNum ? ["tml-tageqn"] : [] )); - } - let table = new mathMLTree.MathNode("mtable", tbl); - if (group.scriptLevel === "display") { table.setAttribute("displaystyle", "true"); } - - // Set column alignment, row spacing, column spacing, and - // array lines by setting attributes on the table element. - - // Set the row spacing. In MathML, we specify a gap distance. - // We do not use rowGap[] because MathML automatically increases - // cell height with the height/depth of the element content. - - // LaTeX \arraystretch multiplies the row baseline-to-baseline distance. - // We simulate this by adding (arraystretch - 1)em to the gap. This - // does a reasonable job of adjusting arrays containing 1 em tall content. - - // The 0.16 and 0.09 values are found emprically. They produce an array - // similar to LaTeX and in which content does not interfere with \hines. - const gap = - group.arraystretch === 0 - ? 0 // {subarray} - : group.arraystretch === 0.5 - ? 0.1 // {smallmatrix} - : 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0); - table.setAttribute("rowspacing", utils.round(gap) + "em"); - - if (group.addEqnNum || group.colSeparationType === "multline") { - table.setAttribute("width", "100%"); - } - - // MathML table lines go only between cells. - // To place a line on an edge we'll use , if necessary. - let menclose = ""; - let align = ""; - - if (group.cols && group.cols.length > 0) { - // Find column alignment, column spacing, and vertical lines. - const cols = group.cols; - let columnLines = ""; - let prevTypeWasAlign = false; - let iStart = 0; - let iEnd = cols.length; - - if (cols[0].type === "separator") { - menclose += "left "; - iStart = 1; - } - if (cols[cols.length - 1].type === "separator") { - menclose += "right "; - iEnd -= 1; - } - - for (let i = iStart; i < iEnd; i++) { - if (cols[i].type === "align") { - align += alignMap[cols[i].align]; - - if (prevTypeWasAlign) { - columnLines += "none "; - } - prevTypeWasAlign = true; - } else if (cols[i].type === "separator") { - // MathML accepts only single lines between cells. - // So we read only the first of consecutive separators. - if (prevTypeWasAlign) { - columnLines += cols[i].separator === "|" ? "solid " : "dashed "; - prevTypeWasAlign = false; - } - } - } - if (group.addEqnNum) { - align = "left " + align + "right "; // allow for glue cells on each side - align = group.leqno ? "left " + align : align += "right"; // eqn num cell - } - - table.setAttribute("columnalign", align.trim()); - - if (/[sd]/.test(columnLines)) { - table.setAttribute("columnlines", columnLines.trim()); - } - } - - // Set column spacing. - switch (group.colSeparationType) { - case "gather": - case "gathered": - case "alignedat": - case "alignat": - case "alignat*": - table.setAttribute("columnspacing", "0em"); - break - case "small": - table.setAttribute("columnspacing", "0.2778em"); - break - case "CD": - table.setAttribute("columnspacing", "0.5em"); - break - case "align": - case "align*": { - const cols = group.cols || []; - let spacing = group.addEqnNum ? "0em " : ""; - for (let i = 1; i < cols.length; i++) { - spacing += i % 2 ? "0em " : "1em "; - } - if (group.addEqnNum) { spacing += "0em"; } - table.setAttribute("columnspacing", spacing.trim()); - break - } - default: - table.setAttribute("columnspacing", "1em"); - } - - // Address \hline and \hdashline - let rowLines = ""; - const hlines = group.hLinesBeforeRow; - - menclose += hlines[0].length > 0 ? "top " : ""; - menclose += hlines[hlines.length - 1].length > 0 ? "bottom " : ""; - - for (let i = 1; i < hlines.length - 1; i++) { - rowLines += - hlines[i].length === 0 - ? "none " - : // MathML accepts only a single line between rows. Read one element. - hlines[i][0] - ? "dashed " - : "solid "; - } - if (/[sd]/.test(rowLines)) { - table.setAttribute("rowlines", rowLines.trim()); - } - - if (menclose !== "") { - table = new mathMLTree.MathNode("menclose", [table]); - table.setAttribute("notation", menclose.trim()); - } - - if (!Number.isNaN(group.arraystretch) && group.arraystretch < 1) { - // A small array. Wrap in scriptstyle so row gap is not too large. - table = new mathMLTree.MathNode("mstyle", [table]); - table.setAttribute("scriptlevel", "1"); - } - - return table; -}; - -// Convenience function for align, align*, aligned, alignat, alignat*, alignedat. -const alignedHandler = function(context, args) { - if (context.envName.indexOf("ed") === -1) { - validateAmsEnvironmentContext(context); - } - const cols = []; - const res = parseArray( - context.parser, - { - cols, - addJot: true, - addEqnNum: context.envName === "align" || context.envName === "alignat", - emptySingleRow: true, - colSeparationType: context.envName, - maxNumCols: context.envName === "split" ? 2 : undefined, - leqno: context.parser.settings.leqno - }, - "display" - ); - - // Determining number of columns. - // 1. If the first argument is given, we use it as a number of columns, - // and makes sure that each row doesn't exceed that number. - // 2. Otherwise, just count number of columns = maximum number - // of cells in each row ("aligned" mode -- isAligned will be true). - // - // At the same time, prepend empty group {} at beginning of every second - // cell in each row (starting with second cell) so that operators become - // binary. This behavior is implemented in amsmath's \start@aligned. - let numMaths; - let numCols = 0; - if (args[0] && args[0].type === "ordgroup") { - let arg0 = ""; - for (let i = 0; i < args[0].body.length; i++) { - const textord = assertNodeType(args[0].body[i], "textord"); - arg0 += textord.text; - } - numMaths = Number(arg0); - numCols = numMaths * 2; - } - const isAligned = !numCols; - res.body.forEach(function(row) { - if (!isAligned) { - // Case 1 - const curMaths = row.length / 2; - if (numMaths < curMaths) { - throw new ParseError( - "Too many math in a row: " + `expected ${numMaths}, but got ${curMaths}`, - row[0] - ); - } - } else if (numCols < row.length) { - // Case 2 - numCols = row.length; - } - }); - - // Adjusting alignment. - // In aligned mode, we add one \qquad between columns; - // otherwise we add nothing. - for (let i = 0; i < numCols; ++i) { - let align = "r"; - if (i % 2 === 1) { - align = "l"; - } - cols[i] = { - type: "align", - align: align - }; - } - res.colSeparationType = isAligned ? "align" : "alignat"; - return res; -}; - -// Arrays are part of LaTeX, defined in lttab.dtx so its documentation -// is part of the source2e.pdf file of LaTeX2e source documentation. -// {darray} is an {array} environment where cells are set in \displaystyle, -// as defined in nccmath.sty. -defineEnvironment({ - type: "array", - names: ["array", "darray"], - props: { - numArgs: 1 - }, - handler(context, args) { - // Since no types are specified above, the two possibilities are - // - The argument is wrapped in {} or [], in which case Parser's - // parseGroup() returns an "ordgroup" wrapping some symbol node. - // - The argument is a bare symbol node. - const symNode = checkSymbolNodeType(args[0]); - const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; - const cols = colalign.map(function(nde) { - const node = assertSymbolNodeType(nde); - const ca = node.text; - if ("lcr".indexOf(ca) !== -1) { - return { - type: "align", - align: ca - }; - } else if (ca === "|") { - return { - type: "separator", - separator: "|" - }; - } else if (ca === ":") { - return { - type: "separator", - separator: ":" - }; - } - throw new ParseError("Unknown column alignment: " + ca, nde); - }); - const res = { - cols, - colSeparationType: "array", - hskipBeforeAndAfter: true, // \@preamble in lttab.dtx - maxNumCols: cols.length - }; - return parseArray(context.parser, res, dCellStyle(context.envName)); - }, - mathmlBuilder: mathmlBuilder$3 -}); - -// The matrix environments of amsmath builds on the array environment -// of LaTeX, which is discussed above. -// The mathtools package adds starred versions of the same environments. -// These have an optional argument to choose left|center|right justification. -defineEnvironment({ - type: "array", - names: [ - "matrix", - "pmatrix", - "bmatrix", - "Bmatrix", - "vmatrix", - "Vmatrix", - "matrix*", - "pmatrix*", - "bmatrix*", - "Bmatrix*", - "vmatrix*", - "Vmatrix*" - ], - props: { - numArgs: 0 - }, - handler(context) { - const delimiters = { - matrix: null, - pmatrix: ["(", ")"], - bmatrix: ["[", "]"], - Bmatrix: ["\\{", "\\}"], - vmatrix: ["|", "|"], - Vmatrix: ["\\Vert", "\\Vert"] - }[context.envName.replace("*", "")]; - // \hskip -\arraycolsep in amsmath - let colAlign = "c"; - const payload = { - hskipBeforeAndAfter: false, - colSeparationType: "matrix", - cols: [{ type: "align", align: colAlign }] - }; - if (context.envName.charAt(context.envName.length - 1) === "*") { - // It's one of the mathtools starred functions. - // Parse the optional alignment argument. - const parser = context.parser; - parser.consumeSpaces(); - if (parser.fetch().text === "[") { - parser.consume(); - parser.consumeSpaces(); - colAlign = parser.fetch().text; - if ("lcr".indexOf(colAlign) === -1) { - throw new ParseError("Expected l or c or r", parser.nextToken); - } - parser.consume(); - parser.consumeSpaces(); - parser.expect("]"); - parser.consume(); - payload.cols = [{ type: "align", align: colAlign }]; - } - } - const res = parseArray(context.parser, payload, "text"); - // Populate cols with the correct number of column alignment specs. - const numCols = Math.max(0, ...res.body.map((row) => row.length)); - res.cols = new Array(numCols).fill({ type: "align", align: colAlign }); - return delimiters - ? { - type: "leftright", - mode: context.mode, - body: [res], - left: delimiters[0], - right: delimiters[1], - rightColor: undefined // \right uninfluenced by \color in array - } - : res; - }, - mathmlBuilder: mathmlBuilder$3 -}); - -defineEnvironment({ - type: "array", - names: ["smallmatrix"], - props: { - numArgs: 0 - }, - handler(context) { - const payload = { arraystretch: 0.5 }; - const res = parseArray(context.parser, payload, "script"); - res.colSeparationType = "small"; - return res; - }, - mathmlBuilder: mathmlBuilder$3 -}); - -defineEnvironment({ - type: "array", - names: ["subarray"], - props: { - numArgs: 1 - }, - handler(context, args) { - // Parsing of {subarray} is similar to {array} - const symNode = checkSymbolNodeType(args[0]); - const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body; - const cols = colalign.map(function(nde) { - const node = assertSymbolNodeType(nde); - const ca = node.text; - // {subarray} only recognizes "l" & "c" - if ("lc".indexOf(ca) !== -1) { - return { - type: "align", - align: ca - }; - } - throw new ParseError("Unknown column alignment: " + ca, nde); - }); - if (cols.length > 1) { - throw new ParseError("{subarray} can contain only one column"); - } - let res = { - cols, - hskipBeforeAndAfter: false, - colSeparationType: "array", - arraystretch: 0 - }; - res = parseArray(context.parser, res, "script"); - if (res.body.length > 0 && res.body[0].length > 1) { - throw new ParseError("{subarray} can contain only one column"); - } - return res; - }, - mathmlBuilder: mathmlBuilder$3 -}); - -// A cases environment (in amsmath.sty) is almost equivalent to -// \def -// \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right. -// {dcases} is a {cases} environment where cells are set in \displaystyle, -// as defined in mathtools.sty. -// {rcases} is another mathtools environment. It's brace is on the right side. -defineEnvironment({ - type: "array", - names: ["cases", "dcases", "rcases", "drcases"], - props: { - numArgs: 0 - }, - handler(context) { - const payload = { - cols: [ - { - type: "align", - align: "l" - }, - { - type: "align", - align: "l" - } - ], - colSeparationType: "cases" - }; - const res = parseArray(context.parser, payload, dCellStyle(context.envName)); - return { - type: "leftright", - mode: context.mode, - body: [res], - left: context.envName.indexOf("r") > -1 ? "." : "\\{", - right: context.envName.indexOf("r") > -1 ? "\\}" : ".", - rightColor: undefined - }; - }, - mathmlBuilder: mathmlBuilder$3 -}); - -// In the align environment, one uses ampersands, &, to specify number of -// columns in each row, and to locate spacing between each column. -// align gets automatic numbering. align* and aligned do not. -// The alignedat environment can be used in math mode. -// Note that we assume \nomallineskiplimit to be zero, -// so that \strut@ is the same as \strut. -defineEnvironment({ - type: "array", - names: ["align", "align*", "aligned", "split"], - props: { - numArgs: 0 - }, - handler: alignedHandler, - mathmlBuilder: mathmlBuilder$3 -}); - -// A gathered environment is like an array environment with one centered -// column, but where rows are considered lines so get \jot line spacing -// and contents are set in \displaystyle. -defineEnvironment({ - type: "array", - names: ["gathered", "gather", "gather*"], - props: { - numArgs: 0 - }, - handler(context) { - if (utils.contains(["gather", "gather*"], context.envName)) { - validateAmsEnvironmentContext(context); - } - const res = { - cols: [ - { - type: "align", - align: "c" - } - ], - addJot: true, - colSeparationType: "gather", - addEqnNum: context.envName === "gather", - emptySingleRow: true, - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder: mathmlBuilder$3 -}); - -// alignat environment is like an align environment, but one must explicitly -// specify maximum number of columns in each row, and can adjust spacing between -// each columns. -defineEnvironment({ - type: "array", - names: ["alignat", "alignat*", "alignedat"], - props: { - numArgs: 1 - }, - handler: alignedHandler, - mathmlBuilder: mathmlBuilder$3 -}); - -defineEnvironment({ - type: "array", - names: ["equation", "equation*"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - const res = { - addEqnNum: context.envName === "equation", - emptySingleRow: true, - singleRow: true, - maxNumCols: 1, - colSeparationType: "gather", - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder: mathmlBuilder$3 -}); - -defineEnvironment({ - type: "array", - names: ["multline", "multline*"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - const res = { - addEqnNum: context.envName === "multline", - maxNumCols: 1, - colSeparationType: "multline", - leqno: context.parser.settings.leqno - }; - return parseArray(context.parser, res, "display"); - }, - mathmlBuilder: mathmlBuilder$3 -}); - -defineEnvironment({ - type: "array", - names: ["CD"], - props: { - numArgs: 0 - }, - handler(context) { - validateAmsEnvironmentContext(context); - return parseCD(context.parser); - }, - mathmlBuilder: mathmlBuilder$3 -}); - -// Catch \hline outside array environment -defineFunction({ - type: "text", // Doesn't matter what this is. - names: ["\\hline", "\\hdashline"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: true - }, - handler(context, args) { - throw new ParseError(`${context.funcName} valid only within array environment`); - } -}); - -const environments = _environments; - -// Environment delimiters. HTML/MathML rendering is defined in the corresponding -// defineEnvironment definitions. -defineFunction({ - type: "environment", - names: ["\\begin", "\\end"], - props: { - numArgs: 1, - argTypes: ["text"] - }, - handler({ parser, funcName }, args) { - const nameGroup = args[0]; - if (nameGroup.type !== "ordgroup") { - throw new ParseError("Invalid environment name", nameGroup); - } - let envName = ""; - for (let i = 0; i < nameGroup.body.length; ++i) { - envName += assertNodeType(nameGroup.body[i], "textord").text; - } - - if (funcName === "\\begin") { - // begin...end is similar to left...right - if (!Object.prototype.hasOwnProperty.call(environments, envName )) { - throw new ParseError("No such environment: " + envName, nameGroup); - } - // Build the environment object. Arguments and other information will - // be made available to the begin and end methods using properties. - const env = environments[envName]; - const { args, optArgs } = parser.parseArguments("\\begin{" + envName + "}", env); - const context = { - mode: parser.mode, - envName, - parser - }; - const result = env.handler(context, args, optArgs); - parser.expect("\\end", false); - const endNameToken = parser.nextToken; - const end = assertNodeType(parser.parseFunction(), "environment"); - if (end.name !== envName) { - throw new ParseError( - `Mismatch: \\begin{${envName}} matched by \\end{${end.name}}`, - endNameToken - ); - } - return result; - } - - return { - type: "environment", - mode: parser.mode, - name: envName, - nameGroup - }; - } -}); - -defineFunction({ - type: "envTag", - names: ["\\env@tag"], - props: { - numArgs: 1, - argTypes: ["math"] - }, - handler({ parser }, args) { - return { - type: "envTag", - mode: parser.mode, - body: args[0] - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow"); - } -}); - -defineFunction({ - type: "noTag", - names: ["\\env@notag"], - props: { - numArgs: 0 - }, - handler({ parser }) { - return { - type: "noTag", - mode: parser.mode - }; - }, - mathmlBuilder(group, style) { - return new mathMLTree.MathNode("mrow"); - } -}); - -const mathmlBuilder$4 = (group, style) => { - const font = group.font; - const newStyle = style.withFont(font); - const mathGroup = buildGroup(group.body, newStyle); - - if (mathGroup.children.length === 0) { return mathGroup } // empty group, e.g., \mathrm{} - if (mathGroup.type === "mo" && font === "boldsymbol") { - mathGroup.style.fontWeight = "bold"; - return mathGroup - } - // Check if it is possible to consolidate elements into a single element. - let canConsolidate = mathGroup.children[0].type === "mo"; - for (let i = 1; i < mathGroup.children.length; i++) { - if (mathGroup.children[i].type === "mo" && font === "boldsymbol") { - mathGroup.children[i].style.fontWeight = "bold"; - } - if (mathGroup.children[i].type !== "mi") { canConsolidate = false; } - const localVariant = mathGroup.children[i].attributes && - mathGroup.children[i].attributes.mathvariant || ""; - if (localVariant !== "normal") { canConsolidate = false; } - } - if (!canConsolidate) { return mathGroup } - // Consolidate the elements. - const mi = mathGroup.children[0]; - for (let i = 1; i < mathGroup.children.length; i++) { - mi.children.push(mathGroup.children[i].children[0]); - } - if (mathGroup.attributes.mathcolor) { mi.attributes.mathcolor = mathGroup.attributes.mathcolor; } - if (mi.attributes.mathvariant && mi.attributes.mathvariant === "normal") { - // Workaround for a Firefox bug that renders spurious space around - // a - // Ref: https://bugs.webkit.org/show_bug.cgi?id=129097 - // We insert a text node that contains a zero-width space and wrap in an mrow. - // TODO: Get rid of this workaround when the Firefox bug is fixed. - const bogus = new mathMLTree.MathNode("mtext", new mathMLTree.TextNode("\u200b")); - return new mathMLTree.MathNode("mrow", [bogus, mi]) - } - return mi -}; - -const fontAliases = { - "\\Bbb": "\\mathbb", - "\\bold": "\\mathbf", - "\\frak": "\\mathfrak", - "\\bm": "\\boldsymbol" -}; - -defineFunction({ - type: "font", - names: [ - // styles - "\\mathrm", - "\\mathit", - "\\mathbf", - "\\mathnormal", - "\\up@greek", - "\\pmb", - "\\boldsymbol", - - // families - "\\mathbb", - "\\mathcal", - "\\mathfrak", - "\\mathscr", - "\\mathsf", - "\\mathtt", - "\\oldstylenums", - - // aliases - "\\Bbb", - "\\bm", - "\\bold", - "\\frak" - ], - props: { - numArgs: 1, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const body = normalizeArgument(args[0]); - let func = funcName; - if (func in fontAliases) { - func = fontAliases[func]; - } - return { - type: "font", - mode: parser.mode, - font: func.slice(1), - body - }; - }, - mathmlBuilder: mathmlBuilder$4 -}); - -// Old font changing functions -defineFunction({ - type: "font", - names: ["\\rm", "\\sf", "\\tt", "\\bf", "\\it", "\\cal"], - props: { - numArgs: 0, - allowedInText: true - }, - handler: ({ parser, funcName, breakOnTokenText }, args) => { - const { mode } = parser; - const body = parser.parseExpression(true, breakOnTokenText); - const fontStyle = `math${funcName.slice(1)}`; - - return { - type: "font", - mode: mode, - font: fontStyle, - body: { - type: "ordgroup", - mode: parser.mode, - body - } - }; - }, - mathmlBuilder: mathmlBuilder$4 -}); - -const stylArray = ["display", "text", "script", "scriptscript"]; -const scriptLevel = { auto: -1, display: 0, text: 0, script: 1, scriptscript: 2 }; - -const mathmlBuilder$5 = (group, style) => { - // Track the scriptLevel of the numerator and denominator. - // We may need that info for \mathchoice or for adjusting em dimensions. - const childOptions = group.scriptLevel === "auto" - ? style.incrementLevel() - : group.scriptLevel === "display" - ? style.withLevel(StyleLevel.TEXT) - : group.scriptLevel === "text" - ? style.withLevel(StyleLevel.SCRIPT) - : style.withLevel(StyleLevel.SCRIPTSCRIPT); - - let node = new mathMLTree.MathNode("mfrac", [ - buildGroup(group.numer, childOptions), - buildGroup(group.denom, childOptions) - ]); - - if (!group.hasBarLine) { - node.setAttribute("linethickness", "0px"); - } else if (group.barSize) { - const ruleWidth = calculateSize(group.barSize, style); - node.setAttribute("linethickness", ruleWidth.number + ruleWidth.unit); - } - - if (group.leftDelim != null || group.rightDelim != null) { - const withDelims = []; - - if (group.leftDelim != null) { - const leftOp = new mathMLTree.MathNode("mo", [ - new mathMLTree.TextNode(group.leftDelim.replace("\\", "")) - ]); - leftOp.setAttribute("fence", "true"); - withDelims.push(leftOp); - } - - withDelims.push(node); - - if (group.rightDelim != null) { - const rightOp = new mathMLTree.MathNode("mo", [ - new mathMLTree.TextNode(group.rightDelim.replace("\\", "")) - ]); - rightOp.setAttribute("fence", "true"); - withDelims.push(rightOp); - } - - node = makeRow(withDelims); - } - - if (group.scriptLevel !== "auto") { - node = new mathMLTree.MathNode("mstyle", [node]); - node.setAttribute("displaystyle", String(group.scriptLevel === "display")); - node.setAttribute("scriptlevel", scriptLevel[group.scriptLevel]); - } - - return node; -}; - -defineFunction({ - type: "genfrac", - names: [ - "\\dfrac", - "\\frac", - "\\tfrac", - "\\dbinom", - "\\binom", - "\\tbinom", - "\\\\atopfrac", // can’t be entered directly - "\\\\bracefrac", - "\\\\brackfrac" // ditto - ], - props: { - numArgs: 2, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const denom = args[1]; - let hasBarLine = false; - let leftDelim = null; - let rightDelim = null; - let scriptLevel = "auto"; - - switch (funcName) { - case "\\dfrac": - case "\\frac": - case "\\tfrac": - hasBarLine = true; - break; - case "\\\\atopfrac": - hasBarLine = false; - break; - case "\\dbinom": - case "\\binom": - case "\\tbinom": - leftDelim = "("; - rightDelim = ")"; - break; - case "\\\\bracefrac": - leftDelim = "\\{"; - rightDelim = "\\}"; - break; - case "\\\\brackfrac": - leftDelim = "["; - rightDelim = "]"; - break; - default: - throw new Error("Unrecognized genfrac command"); - } - - switch (funcName) { - case "\\dfrac": - case "\\dbinom": - scriptLevel = "display"; - break; - case "\\tfrac": - case "\\tbinom": - scriptLevel = "text"; - break; - } - - return { - type: "genfrac", - mode: parser.mode, - continued: false, - numer, - denom, - hasBarLine, - leftDelim, - rightDelim, - scriptLevel, - barSize: null - }; - }, - mathmlBuilder: mathmlBuilder$5 -}); - -defineFunction({ - type: "genfrac", - names: ["\\cfrac"], - props: { - numArgs: 2 - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const denom = args[1]; - - return { - type: "genfrac", - mode: parser.mode, - continued: true, - numer, - denom, - hasBarLine: true, - leftDelim: null, - rightDelim: null, - scriptLevel: "display", - barSize: null - }; - } -}); - -// Infix generalized fractions -- these are not rendered directly, but replaced -// immediately by one of the variants above. -defineFunction({ - type: "infix", - names: ["\\over", "\\choose", "\\atop", "\\brace", "\\brack"], - props: { - numArgs: 0, - infix: true - }, - handler({ parser, funcName, token }) { - let replaceWith; - switch (funcName) { - case "\\over": - replaceWith = "\\frac"; - break; - case "\\choose": - replaceWith = "\\binom"; - break; - case "\\atop": - replaceWith = "\\\\atopfrac"; - break; - case "\\brace": - replaceWith = "\\\\bracefrac"; - break; - case "\\brack": - replaceWith = "\\\\brackfrac"; - break; - default: - throw new Error("Unrecognized infix genfrac command"); - } - return { - type: "infix", - mode: parser.mode, - replaceWith, - token - }; - } -}); - -const delimFromValue = function(delimString) { - let delim = null; - if (delimString.length > 0) { - delim = delimString; - delim = delim === "." ? null : delim; - } - return delim; -}; - -defineFunction({ - type: "genfrac", - names: ["\\genfrac"], - props: { - numArgs: 6, - allowedInArgument: true, - argTypes: ["math", "math", "size", "text", "math", "math"] - }, - handler({ parser }, args) { - const numer = args[4]; - const denom = args[5]; - - // Look into the parse nodes to get the desired delimiters. - const leftNode = normalizeArgument(args[0]); - const leftDelim = leftNode.type === "atom" && leftNode.family === "open" - ? delimFromValue(leftNode.text) - : null; - const rightNode = normalizeArgument(args[1]); - const rightDelim = - rightNode.type === "atom" && rightNode.family === "close" - ? delimFromValue(rightNode.text) - : null; - - const barNode = assertNodeType(args[2], "size"); - let hasBarLine; - let barSize = null; - if (barNode.isBlank) { - // \genfrac acts differently than \above. - // \genfrac treats an empty size group as a signal to use a - // standard bar size. \above would see size = 0 and omit the bar. - hasBarLine = true; - } else { - barSize = barNode.value; - hasBarLine = barSize.number > 0; - } - - // Find out if we want displaystyle, textstyle, etc. - let scriptLevel = "auto"; - let styl = args[3]; - if (styl.type === "ordgroup") { - if (styl.body.length > 0) { - const textOrd = assertNodeType(styl.body[0], "textord"); - scriptLevel = stylArray[Number(textOrd.text)]; - } - } else { - styl = assertNodeType(styl, "textord"); - scriptLevel = stylArray[Number(styl.text)]; - } - - return { - type: "genfrac", - mode: parser.mode, - numer, - denom, - continued: false, - hasBarLine, - barSize, - leftDelim, - rightDelim, - scriptLevel - }; - }, - mathmlBuilder: mathmlBuilder$5 -}); - -// \above is an infix fraction that also defines a fraction bar size. -defineFunction({ - type: "infix", - names: ["\\above"], - props: { - numArgs: 1, - argTypes: ["size"], - infix: true - }, - handler({ parser, funcName, token }, args) { - return { - type: "infix", - mode: parser.mode, - replaceWith: "\\\\abovefrac", - barSize: assertNodeType(args[0], "size").value, - token - }; - } -}); - -defineFunction({ - type: "genfrac", - names: ["\\\\abovefrac"], - props: { - numArgs: 3, - argTypes: ["math", "size", "math"] - }, - handler: ({ parser, funcName }, args) => { - const numer = args[0]; - const barSize = assert(assertNodeType(args[1], "infix").barSize); - const denom = args[2]; - - const hasBarLine = barSize.number > 0; - return { - type: "genfrac", - mode: parser.mode, - numer, - denom, - continued: false, - hasBarLine, - barSize, - leftDelim: null, - rightDelim: null, - scriptLevel: "auto" - }; - }, - - mathmlBuilder: mathmlBuilder$5 -}); - -const mathmlBuilder$6 = (group, style) => { - const accentNode = stretchy.mathMLnode(group.label); - return new mathMLTree.MathNode(group.isOver ? "mover" : "munder", [ - buildGroup(group.base, style), - accentNode - ]); -}; - -// Horizontal stretchy braces -defineFunction({ - type: "horizBrace", - names: ["\\overbrace", "\\underbrace"], - props: { - numArgs: 1 - }, - handler({ parser, funcName }, args) { - return { - type: "horizBrace", - mode: parser.mode, - label: funcName, - isOver: /^\\over/.test(funcName), - base: args[0] - }; - }, - mathmlBuilder: mathmlBuilder$6 -}); - -defineFunction({ - type: "href", - names: ["\\href"], - props: { - numArgs: 2, - argTypes: ["url", "original"], - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[1]; - const href = assertNodeType(args[0], "url").url; - - if ( - !parser.settings.isTrusted({ - command: "\\href", - url: href - }) - ) { - return parser.formatUnsupportedCmd("\\href"); - } - - return { - type: "href", - mode: parser.mode, - href, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - let math = buildExpressionRow(group.body, style); - if (!(math instanceof MathNode)) { - math = new MathNode("mrow", [math]); - } - math.setAttribute("href", group.href); - return math; - } -}); - -defineFunction({ - type: "href", - names: ["\\url"], - props: { - numArgs: 1, - argTypes: ["url"], - allowedInText: true - }, - handler: ({ parser }, args) => { - const href = assertNodeType(args[0], "url").url; - - if ( - !parser.settings.isTrusted({ - command: "\\url", - url: href - }) - ) { - return parser.formatUnsupportedCmd("\\url"); - } - - const chars = []; - for (let i = 0; i < href.length; i++) { - let c = href[i]; - if (c === "~") { - c = "\\textasciitilde"; - } - chars.push({ - type: "textord", - mode: "text", - text: c - }); - } - const body = { - type: "text", - mode: parser.mode, - font: "\\texttt", - body: chars - }; - return { - type: "href", - mode: parser.mode, - href, - body: ordargument(body) - }; - } -}); - -defineFunction({ - type: "html", - names: ["\\class", "\\id", "\\style", "\\data"], - props: { - numArgs: 2, - argTypes: ["raw", "original"], - allowedInText: true - }, - handler: ({ parser, funcName, token }, args) => { - const value = assertNodeType(args[0], "raw").string; - const body = args[1]; - - if (parser.settings.strict) { - parser.settings.reportNonstrict( - "htmlExtension", "HTML extension is disabled on strict mode" - ); - } - - let trustContext; - const attributes = {}; - - switch (funcName) { - case "\\class": - attributes.class = value; - trustContext = { - command: "\\class", - class: value - }; - break; - case "\\id": - attributes.id = value; - trustContext = { - command: "\\id", - id: value - }; - break; - case "\\style": - attributes.style = value; - trustContext = { - command: "\\style", - style: value - }; - break; - case "\\data": { - const data = value.split(","); - for (let i = 0; i < data.length; i++) { - const keyVal = data[i].split("="); - if (keyVal.length !== 2) { - throw new ParseError("Error parsing key-value for \\data"); - } - attributes["data-" + keyVal[0].trim()] = keyVal[1].trim(); - } - - trustContext = { - command: "\\data", - attributes - }; - break; - } - default: - throw new Error("Unrecognized html command"); - } - - if (!parser.settings.isTrusted(trustContext)) { - return parser.formatUnsupportedCmd(funcName); - } - return { - type: "html", - mode: parser.mode, - attributes, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - const element = buildExpressionRow(group.body, style); - - const classes = []; - if (group.attributes.class) { - classes.push(...group.attributes.class.trim().split(/\s+/)); - } - element.classes = classes; - - for (const attr in group.attributes) { - if (attr !== "class" && Object.prototype.hasOwnProperty.call(group.attributes, attr)) { - element.setAttribute(attr, group.attributes[attr]); - } - } - - return element; - } -}); - -const sizeData = function(str) { - if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(str)) { - // str is a number with no unit specified. - // default unit is bp, per graphix package. - return { number: +str, unit: "bp" } - } else { - const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(str); - if (!match) { - throw new ParseError("Invalid size: '" + str + "' in \\includegraphics"); - } - const data = { - number: +(match[1] + match[2]), // sign + magnitude, cast to number - unit: match[3] - }; - if (!validUnit(data)) { - throw new ParseError("Invalid unit: '" + data.unit + "' in \\includegraphics."); - } - return data - } -}; - -defineFunction({ - type: "includegraphics", - names: ["\\includegraphics"], - props: { - numArgs: 1, - numOptionalArgs: 1, - argTypes: ["raw", "url"], - allowedInText: false - }, - handler: ({ parser }, args, optArgs) => { - let width = { number: 0, unit: "em" }; - let height = { number: 0.9, unit: "em" }; // sorta character sized. - let totalheight = { number: 0, unit: "em" }; - let alt = ""; - - if (optArgs[0]) { - const attributeStr = assertNodeType(optArgs[0], "raw").string; - - // Parser.js does not parse key/value pairs. We get a string. - const attributes = attributeStr.split(","); - for (let i = 0; i < attributes.length; i++) { - const keyVal = attributes[i].split("="); - if (keyVal.length === 2) { - const str = keyVal[1].trim(); - switch (keyVal[0].trim()) { - case "alt": - alt = str; - break - case "width": - width = sizeData(str); - break - case "height": - height = sizeData(str); - break - case "totalheight": - totalheight = sizeData(str); - break - default: - throw new ParseError("Invalid key: '" + keyVal[0] + "' in \\includegraphics.") - } - } - } - } - - const src = assertNodeType(args[0], "url").url; - - if (alt === "") { - // No alt given. Use the file name. Strip away the path. - alt = src; - alt = alt.replace(/^.*[\\/]/, ""); - alt = alt.substring(0, alt.lastIndexOf(".")); - } - - if ( - !parser.settings.isTrusted({ - command: "\\includegraphics", - url: src - }) - ) { - return parser.formatUnsupportedCmd("\\includegraphics") - } - - return { - type: "includegraphics", - mode: parser.mode, - alt: alt, - width: width, - height: height, - totalheight: totalheight, - src: src - } - }, - mathmlBuilder: (group, style) => { - const height = calculateSize(group.height, style); - const depth = { number: 0, unit: "em" }; - - if (group.totalheight.number > 0) { - if (group.totalheight.unit === height.unit && - group.totalheight.number > height.number) { - depth.number = group.totalheight.number - height.number; - depth.unit = height.unit; - } - } - - let width = 0; - if (group.width.number > 0) { - width = calculateSize(group.width, style); - } - - const graphicStyle = { height: height.number + depth.number + "em" }; - if (width.number > 0) { - graphicStyle.width = width.number + width.unit; - } - if (depth.number > 0) { - graphicStyle.verticalAlign = -depth.number + depth.unit; - } - - const node = new Img(group.src, group.alt, graphicStyle); - node.height = height; - node.depth = depth; - return new mathMLTree.MathNode("mtext", [node]) - } -}); - -// Horizontal spacing commands - -// TODO: \hskip and \mskip should support plus and minus in lengths - -defineFunction({ - type: "kern", - names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"], - props: { - numArgs: 1, - argTypes: ["size"], - primitive: true, - allowedInText: true - }, - handler({ parser, funcName }, args) { - const size = assertNodeType(args[0], "size"); - if (parser.settings.strict) { - const mathFunction = funcName[1] === "m"; // \mkern, \mskip - const muUnit = size.value.unit === "mu"; - if (mathFunction) { - if (!muUnit) { - parser.settings.reportNonstrict( - "mathVsTextUnits", - `LaTeX's ${funcName} supports only mu units, ` + `not ${size.value.unit} units` - ); - } - if (parser.mode !== "math") { - parser.settings.reportNonstrict( - "mathVsTextUnits", - `LaTeX's ${funcName} works only in math mode` - ); - } - } else { - // !mathFunction - if (muUnit) { - parser.settings.reportNonstrict( - "mathVsTextUnits", - `LaTeX's ${funcName} doesn't support mu units` - ); - } - } - } - return { - type: "kern", - mode: parser.mode, - dimension: size.value - }; - }, - mathmlBuilder(group, style) { - const dimension = calculateSize(group.dimension, style); - const ch = dimension.unit === "em" ? spaceCharacter(dimension.number) : ""; - if (group.mode === "text" && ch.length > 0) { - const character = new mathMLTree.TextNode(ch); - return new mathMLTree.MathNode("mtext", [character]); - } else { - const node = new mathMLTree.MathNode("mspace"); - node.setAttribute("width", dimension.number + dimension.unit); - return node; - } - } -}); - -const spaceCharacter = function(width) { - if (width >= 0.05555 && width <= 0.05556) { - return "\u200a"; //   - } else if (width >= 0.1666 && width <= 0.1667) { - return "\u2009"; //   - } else if (width >= 0.2222 && width <= 0.2223) { - return "\u2005"; //   - } else if (width >= 0.2777 && width <= 0.2778) { - return "\u2005\u200a"; //    - } else { - return ""; - } -}; - -// Limit valid characters to a small set, for safety. -const invalidIdRegEx = /[^A-Za-z_0-9-]/g; - -defineFunction({ - type: "label", - names: ["\\label"], - props: { - numArgs: 1, - argTypes: ["raw"] - }, - handler({ parser }, args) { - return { - type: "label", - mode: parser.mode, - string: args[0].string.replace(invalidIdRegEx, "") - }; - }, - mathmlBuilder(group, style) { - // Return a no-width, no-ink element with an HTML id. - const node = new mathMLTree.MathNode("mrow", [], ["tml-label"]); - if (group.string.length > 0) { - node.setAttribute("id", group.string); - } - return node - } -}); - -// Horizontal overlap functions - -const textModeLap = ["\\clap", "\\llap", "\\rlap"]; - -defineFunction({ - type: "lap", - names: ["\\mathllap", "\\mathrlap", "\\mathclap", "\\clap", "\\llap", "\\rlap"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser, funcName }, args) => { - if (textModeLap.includes(funcName)) { - if (parser.settings.strict && parser.mode !== "text") { - throw new ParseError(`{${funcName}} can be used only in text mode.`) - } - funcName = funcName.slice(1); - } else { - funcName = funcName.slice(5); - } - const body = args[0]; - return { - type: "lap", - mode: parser.mode, - alignment: funcName, - body - } - }, - mathmlBuilder: (group, style) => { - // mathllap, mathrlap, mathclap - const node = new mathMLTree.MathNode("mpadded", [buildGroup(group.body, style)]); - - if (group.alignment === "rlap") { - if (group.body.body.length > 0 && group.body.body[0].type === "genfrac") { - // In Firefox, a squashes the 3/18em padding of a child \frac. Put it back. - node.setAttribute("lspace", "0.16667em"); - } - } else { - const offset = group.alignment === "llap" ? "-1" : "-0.5"; - node.setAttribute("lspace", offset + "width"); - } - node.setAttribute("width", "0px"); - return node - } -}); - -// Switching from text mode back to math mode -defineFunction({ - type: "ordgroup", - names: ["\\(", "$"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: false - }, - handler({ funcName, parser }, args) { - const outerMode = parser.mode; - parser.switchMode("math"); - const close = funcName === "\\(" ? "\\)" : "$"; - const body = parser.parseExpression(false, close); - parser.expect(close); - parser.switchMode(outerMode); - return { - type: "ordgroup", - mode: parser.mode, - body - }; - } -}); - -// Check for extra closing math delimiters -defineFunction({ - type: "text", // Doesn't matter what this is. - names: ["\\)", "\\]"], - props: { - numArgs: 0, - allowedInText: true, - allowedInMath: false - }, - handler(context, args) { - throw new ParseError(`Mismatched ${context.funcName}`); - } -}); - -const chooseStyle = (group, style) => { - switch (style.level) { - case StyleLevel.DISPLAY: // 0 - return group.display; - case StyleLevel.TEXT: // 1 - return group.text; - case StyleLevel.SCRIPT: // 2 - return group.script; - case StyleLevel.SCRIPTSCRIPT: // 3 - return group.scriptscript; - default: - return group.text; - } -}; - -defineFunction({ - type: "mathchoice", - names: ["\\mathchoice"], - props: { - numArgs: 4, - primitive: true - }, - handler: ({ parser }, args) => { - return { - type: "mathchoice", - mode: parser.mode, - display: ordargument(args[0]), - text: ordargument(args[1]), - script: ordargument(args[2]), - scriptscript: ordargument(args[3]) - }; - }, - mathmlBuilder: (group, style) => { - const body = chooseStyle(group, style); - return buildExpressionRow(body, style); - } -}); - -const textAtomTypes = ["text", "textord", "mathord", "atom"]; - -function mathmlBuilder$7(group, style) { - let node; - const inner = buildExpression(group.body, style); - - if (group.mclass === "minner") { - return mathMLTree.newDocumentFragment(inner); - } else if (group.mclass === "mord") { - if (group.isCharacterBox || inner[0].type === "mathord") { - node = inner[0]; - node.type = "mi"; - } else { - node = new mathMLTree.MathNode("mi", inner); - } - } else { - if (group.mustPromote) { - node = inner[0]; - node.type = "mo"; - if (group.isCharacterBox && group.body[0].text && /[A-Za-z]/.test(group.body[0].text)) { - node.setAttribute("mathvariant", "italic"); - } - } else { - node = new mathMLTree.MathNode("mo", inner); - } - - // Set spacing based on what is the most likely adjacent atom type. - // See TeXbook p170. - const doSpacing = style.level < 2; // Operator spacing is zero inside a (sub|super)script. - if (group.mclass === "mbin") { - // medium space - node.attributes.lspace = (doSpacing ? "0.2222em" : "0"); - node.attributes.rspace = (doSpacing ? "0.2222em" : "0"); - } else if (group.mclass === "mrel") { - // thickspace - node.attributes.lspace = (doSpacing ? "0.2778em" : "0"); - node.attributes.rspace = (doSpacing ? "0.2778em" : "0"); - } else if (group.mclass === "mpunct") { - node.attributes.lspace = "0em"; - node.attributes.rspace = (doSpacing ? "0.1667em" : "0"); - } else if (group.mclass === "mopen" || group.mclass === "mclose") { - node.attributes.lspace = "0em"; - node.attributes.rspace = "0em"; - } - if (!(group.mclass === "mopen" || group.mclass === "mclose")) { - delete node.attributes.stretchy; - delete node.attributes.form; - } - } - return node; -} - -// Math class commands except \mathop -defineFunction({ - type: "mclass", - names: [ - "\\mathord", - "\\mathbin", - "\\mathrel", - "\\mathopen", - "\\mathclose", - "\\mathpunct", - "\\mathinner" - ], - props: { - numArgs: 1, - primitive: true - }, - handler({ parser, funcName }, args) { - const body = args[0]; - const isCharacterBox = utils.isCharacterBox(body); - // We should not wrap a around a or . That would be invalid MathML. - // In that case, we instead promote the text contents of the body to the parent. - let mustPromote = true; - const mord = { type: "mathord", text: "", mode: parser.mode }; - const arr = (body.body) ? body.body : [body]; - for (const arg of arr) { - if (textAtomTypes.includes(arg.type)) { - if (arg.text) { - mord.text += arg.text; - } else if (arg.body) { - arg.body.map(e => { mord.text += e.text; }); - } - } else { - mustPromote = false; - break - } - } - return { - type: "mclass", - mode: parser.mode, - mclass: "m" + funcName.substr(5), - body: ordargument(mustPromote ? mord : body), - isCharacterBox, - mustPromote - }; - }, - mathmlBuilder: mathmlBuilder$7 -}); - -const binrelClass = (arg) => { - // \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument. - // (by rendering separately and with {}s before and after, and measuring - // the change in spacing). We'll do roughly the same by detecting the - // atom type directly. - const atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg; - if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) { - return "m" + atom.family; - } else { - return "mord"; - } -}; - -// \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord. -// This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX. -defineFunction({ - type: "mclass", - names: ["\\@binrel"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "mclass", - mode: parser.mode, - mclass: binrelClass(args[0]), - body: ordargument(args[1]), - isCharacterBox: utils.isCharacterBox(args[1]) - }; - } -}); - -// Build a relation or stacked op by placing one symbol on top of another -defineFunction({ - type: "mclass", - names: ["\\stackrel", "\\overset", "\\underset"], - props: { - numArgs: 2 - }, - handler({ parser, funcName }, args) { - const baseArg = args[1]; - const shiftedArg = args[0]; - - const baseOp = { - type: "op", - mode: baseArg.mode, - limits: true, - alwaysHandleSupSub: true, - parentIsSupSub: false, - symbol: false, - stack: true, - suppressBaseShift: funcName !== "\\stackrel", - body: ordargument(baseArg) - }; - - return { - type: "supsub", - mode: shiftedArg.mode, - base: baseOp, - sup: funcName === "\\underset" ? null : shiftedArg, - sub: funcName === "\\underset" ? shiftedArg : null - }; - }, - mathmlBuilder: mathmlBuilder$7 -}); - -// Helper function -const buildGroup$1 = (el, style, noneNode) => { - if (!el) { return noneNode } - const node = buildGroup(el, style); - if (node.type === "mrow" && node.children.length === 0) { return noneNode } - return node -}; - -defineFunction({ - type: "multiscript", - names: ["\\sideset", "\\pres@cript"], // See macros.js for \prescript - props: { - numArgs: 3 - }, - handler({ parser, funcName }, args) { - if (args[2].body.length === 0) { - throw new ParseError(funcName + `cannot parse an empty base.`) - } - const base = args[2].body[0]; - if (parser.settings.strict && funcName === "\\sideset" && !base.symbol) { - throw new ParseError(`The base of \\sideset must be a big operator.`) - } - - if ((args[0].body.length > 0 && args[0].body[0].type !== "supsub") || - (args[1].body.length > 0 && args[1].body[0].type !== "supsub")) { - throw new ParseError("\\sideset can parse only subscripts and " + - "superscripts in its first two arguments") - } - - // The prescripts and postscripts come wrapped in a supsub. - const prescripts = args[0].body.length > 0 ? args[0].body[0] : null; - const postscripts = args[1].body.length > 0 ? args[1].body[0] : null; - - if (!prescripts && !postscripts) { - return base - } else if (!prescripts) { - // It's not a multi-script. Get a \textstyle supsub. - return { - type: "styling", - mode: parser.mode, - scriptLevel: "text", - body: [{ - type: "supsub", - mode: parser.mode, - base, - sup: postscripts.sup, - sub: postscripts.sub - }] - } - } else { - return { - type: "multiscript", - mode: parser.mode, - isSideset: funcName === "\\sideset", - prescripts, - postscripts, - base - } - } - }, - mathmlBuilder(group, style) { - const base = buildGroup(group.base, style); - - const prescriptsNode = new mathMLTree.MathNode("mprescripts"); - const noneNode = new mathMLTree.MathNode("none"); - let children = []; - - const preSub = buildGroup$1(group.prescripts.sub, style, noneNode); - const preSup = buildGroup$1(group.prescripts.sup, style, noneNode); - if (group.isSideset) { - // This seems silly, but LaTeX does this. Firefox ignores it, which does not make me sad. - preSub.setAttribute("style", "text-align: left;"); - preSup.setAttribute("style", "text-align: left;"); - } - - if (group.postscripts) { - const postSub = buildGroup$1(group.postscripts.sub, style, noneNode); - const postSup = buildGroup$1(group.postscripts.sup, style, noneNode); - children = [base, postSub, postSup, prescriptsNode, preSub, preSup]; - } else { - children = [base, prescriptsNode, preSub, preSup]; - } - - return new mathMLTree.MathNode("mmultiscripts", children); - } -}); - -defineFunction({ - type: "not", - names: ["\\not"], - props: { - numArgs: 1, - primitive: true, - allowedInText: false - }, - handler({ parser }, args) { - const isCharacterBox = utils.isCharacterBox(args[0]); - let body; - if (isCharacterBox) { - body = ordargument(args[0]); - if (body[0].text.charAt(0) === "\\") { - body[0].text = symbols.math[body[0].text].replace; - } - // \u0338 is the Unicode Combining Long Solidus Overlay - body[0].text = body[0].text.slice(0, 1) + "\u0338" + body[0].text.slice(1); - } else { - // When the argument is not a character box, TeX does an awkward, poorly placed overlay. - // We'll do the same. - const notNode = { type: "textord", mode: "math", text: "\u0338" }; - const kernNode = { type: "kern", mode: "math", dimension: { number: -0.6, unit: "em" } }; - body = [notNode, kernNode, args[0]]; - } - return { - type: "not", - mode: parser.mode, - body, - isCharacterBox - }; - }, - mathmlBuilder(group, style) { - if (group.isCharacterBox) { - const inner = buildExpression(group.body, style); - return inner[0] - } else { - return buildExpressionRow(group.body, style, true) - } - } -}); - -// Limits, symbols - -const ordAtomTypes = ["textord", "mathord", "atom"]; - -// Most operators have a large successor symbol, but these don't. -const noSuccessor = ["\\smallint"]; - -// Math operators (e.g. \sin) need a space between these types and themselves: -const ordTypes = ["textord", "mathord", "ordgroup", "close", "leftright"]; - -// NOTE: Unlike most `builders`s, this one handles not only "op", but also -// "supsub" since some of them (like \int) can affect super/subscripting. - -const mathmlBuilder$8 = (group, style) => { - let node; - - if (group.symbol) { - // This is a symbol. Just add the symbol. - node = new MathNode("mo", [makeText(group.name, group.mode)]); - if (utils.contains(noSuccessor, group.name)) { - node.setAttribute("largeop", "false"); - } else { - node.setAttribute("movablelimits", "false"); - } - } else if (group.body) { - // This is an operator with children. Add them. - node = new MathNode("mo", buildExpression(group.body, style)); - } else { - // This is a text operator. Add all of the characters from the operator's name. - node = new MathNode("mi", [new TextNode$1(group.name.slice(1))]); - - if (!group.parentIsSupSub) { - // Append an . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new MathNode("mo", [makeText("\u2061", "text")]); - if (group.needsLeadingSpace) { - const space = new MathNode("mspace"); - space.setAttribute("width", "0.1667em"); // thin space. - node = newDocumentFragment([space, node, operator]); - } else { - node = newDocumentFragment([node, operator]); - } - } - } - - return node; -}; - -const singleCharBigOps = { - "\u220F": "\\prod", - "\u2210": "\\coprod", - "\u2211": "\\sum", - "\u22c0": "\\bigwedge", - "\u22c1": "\\bigvee", - "\u22c2": "\\bigcap", - "\u22c3": "\\bigcup", - "\u2a00": "\\bigodot", - "\u2a01": "\\bigoplus", - "\u2a02": "\\bigotimes", - "\u2a04": "\\biguplus", - "\u2a05": "\\bigsqcap", - "\u2a06": "\\bigsqcup" -}; - -defineFunction({ - type: "op", - names: [ - "\\coprod", - "\\bigvee", - "\\bigwedge", - "\\biguplus", - "\\bigcap", - "\\bigcup", - "\\intop", - "\\prod", - "\\sum", - "\\bigotimes", - "\\bigoplus", - "\\bigodot", - "\\bigsqcap", - "\\bigsqcup", - "\\smallint", - "\u220F", - "\u2210", - "\u2211", - "\u22c0", - "\u22c1", - "\u22c2", - "\u22c3", - "\u2a00", - "\u2a01", - "\u2a02", - "\u2a04", - "\u2a06" - ], - props: { - numArgs: 0 - }, - handler: ({ parser, funcName }, args) => { - let fName = funcName; - if (fName.length === 1) { - fName = singleCharBigOps[fName]; - } - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: true, - stack: false, // This is true for \stackrel{}, not here. - name: fName - }; - }, - mathmlBuilder: mathmlBuilder$8 -}); - -// Note: calling defineFunction with a type that's already been defined only -// works because the same mathmlBuilder is being used. -defineFunction({ - type: "op", - names: ["\\mathop"], - props: { - numArgs: 1, - primitive: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - // It would be convienient to just wrap a around the argument. - // But if the argument is a or , that would be invalid MathML. - // In that case, we instead promote the text contents of the body to the parent. - const arr = (body.body) ? body.body : [body]; - const isSymbol = arr.length === 1 && ordAtomTypes.includes(arr[0].type); - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: isSymbol, - stack: false, - name: isSymbol ? arr[0].text : null, - body: isSymbol ? null : ordargument(body) - }; - }, - mathmlBuilder: mathmlBuilder$8 -}); - -// There are 2 flags for operators; whether they produce limits in -// displaystyle, and whether they are symbols and should grow in -// displaystyle. These four groups cover the four possible choices. - -const singleCharIntegrals = { - "\u222b": "\\int", - "\u222c": "\\iint", - "\u222d": "\\iiint", - "\u222e": "\\oint", - "\u222f": "\\oiint", - "\u2230": "\\oiiint", - "\u2231": "\\intclockwise", - "\u2232": "\\varointclockwise", - "\u2a0c": "\\iiiint", - "\u2a0d": "\\intbar", - "\u2a0e": "\\intBar", - "\u2a0f": "\\fint", - "\u2a12": "\\rppolint", - "\u2a13": "\\scpolint", - "\u2a15": "\\pointint", - "\u2a16": "\\sqint", - "\u2a17": "\\intlarhk", - "\u2a18": "\\intx", - "\u2a19": "\\intcap", - "\u2a1a": "\\intcup" -}; - -// No limits, not symbols -defineFunction({ - type: "op", - names: [ - "\\arcsin", - "\\arccos", - "\\arctan", - "\\arctg", - "\\arcctg", - "\\arg", - "\\ch", - "\\cos", - "\\cosec", - "\\cosh", - "\\cot", - "\\cotg", - "\\coth", - "\\csc", - "\\ctg", - "\\cth", - "\\deg", - "\\dim", - "\\exp", - "\\hom", - "\\ker", - "\\lg", - "\\ln", - "\\log", - "\\sec", - "\\sin", - "\\sinh", - "\\sh", - "\\sgn", - "\\tan", - "\\tanh", - "\\tg", - "\\th" - ], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - const prevAtomType = parser.prevAtomType; - return { - type: "op", - mode: parser.mode, - limits: false, - parentIsSupSub: false, - symbol: false, - stack: false, - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType), - name: funcName - }; - }, - mathmlBuilder: mathmlBuilder$8 -}); - -// Limits, not symbols -defineFunction({ - type: "op", - names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - const prevAtomType = parser.prevAtomType; - return { - type: "op", - mode: parser.mode, - limits: true, - parentIsSupSub: false, - symbol: false, - stack: false, - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType), - name: funcName - }; - }, - mathmlBuilder: mathmlBuilder$8 -}); - -// No limits, symbols -defineFunction({ - type: "op", - names: [ - "\\int", - "\\iint", - "\\iiint", - "\\iiiint", - "\\oint", - "\\oiint", - "\\oiiint", - "\\intclockwise", - "\\varointclockwise", - "\\intbar", - "\\intBar", - "\\fint", - "\\rppolint", - "\\scpolint", - "\\pointint", - "\\sqint", - "\\intlarhk", - "\\intx", - "\\intcap", - "\\intcup", - "\u222b", - "\u222c", - "\u222d", - "\u222e", - "\u222f", - "\u2230", - "\u2231", - "\u2232", - "\u2a0c", - "\u2a0d", - "\u2a0e", - "\u2a0f", - "\u2a12", - "\u2a13", - "\u2a15", - "\u2a16", - "\u2a17", - "\u2a18", - "\u2a19", - "\u2a1a" - ], - props: { - numArgs: 0 - }, - handler({ parser, funcName }) { - let fName = funcName; - if (fName.length === 1) { - fName = singleCharIntegrals[fName]; - } - return { - type: "op", - mode: parser.mode, - limits: false, - parentIsSupSub: false, - symbol: true, - stack: false, - name: fName - }; - }, - mathmlBuilder: mathmlBuilder$8 -}); - -/** - * All registered global/built-in macros. - * `macros.js` exports this same dictionary again and makes it public. - * `Parser.js` requires this dictionary via `macros.js`. - */ -const _macros = {}; - -// This function might one day accept an additional argument and do more things. -function defineMacro(name, body) { - _macros[name] = body; -} - -// NOTE: Unlike most builders, this one handles not only -// "operatorname", but also "supsub" since \operatorname* can -// affect super/subscripting. - -const mathmlBuilder$9 = (group, style) => { - let expression = buildExpression(group.body, style.withFont("mathrm")); - - // Is expression a string or has it something like a fraction? - let isAllString = true; // default - for (let i = 0; i < expression.length; i++) { - const node = expression[i]; - if (node instanceof mathMLTree.MathNode) { - switch (node.type) { - case "mi": - case "mn": - case "ms": - case "mtext": - break; // Do nothing yet. - case "mspace": - { - if (node.attributes.width) { - const width = node.attributes.width.replace("em", ""); - const ch = spaceCharacter(Number(width)); - if (ch === "") { - isAllString = false; - } else { - expression[i] = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode(ch)]); - } - } - } - break - case "mo": { - const child = node.children[0]; - if (node.children.length === 1 && child instanceof mathMLTree.TextNode) { - child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*"); - } else { - isAllString = false; - } - break - } - default: - isAllString = false; - } - } else { - isAllString = false; - } - } - - if (isAllString) { - // Write a single TextNode instead of multiple nested tags. - const word = expression.map((node) => node.toText()).join(""); - expression = [new mathMLTree.TextNode(word)]; - } else if ( - expression.length === 1 - && utils.contains(["mover", "munder"], expression[0].type) && - (expression[0].children[0].type === "mi" || expression[0].children[0].type === "mtext") - ) { - expression[0].children[0].type = "mi"; - if (group.parentIsSupSub) { - return new mathMLTree.MathNode("mrow", expression) - } else { - const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); - return mathMLTree.newDocumentFragment([expression[0], operator]) - } - } - - let wrapper; - if (isAllString) { - wrapper = new mathMLTree.MathNode("mi", expression); - wrapper.setAttribute("mathvariant", "normal"); - } else { - wrapper = new mathMLTree.MathNode("mrow", expression); - } - - if (!group.parentIsSupSub) { - // Append an . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); - if (group.needsLeadingSpace) { - // LaTeX gives operator spacing, but a gets ord spacing. - // So add a leading space. - const space = new mathMLTree.MathNode("mspace"); - space.setAttribute("width", "0.1667em"); // thin space. - return mathMLTree.newDocumentFragment([space, wrapper, operator]) - } else { - return mathMLTree.newDocumentFragment([wrapper, operator]) - } - } - - return wrapper -}; - -// \operatorname -// amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@ -defineFunction({ - type: "operatorname", - names: ["\\operatorname@", "\\operatornamewithlimits"], - props: { - numArgs: 1, - allowedInArgument: true - }, - handler: ({ parser, funcName }, args) => { - const body = args[0]; - const prevAtomType = parser.prevAtomType; - return { - type: "operatorname", - mode: parser.mode, - body: ordargument(body), - alwaysHandleSupSub: (funcName === "\\operatornamewithlimits"), - limits: false, - parentIsSupSub: false, - needsLeadingSpace: prevAtomType.length > 0 && utils.contains(ordTypes, prevAtomType) - }; - }, - mathmlBuilder: mathmlBuilder$9 -}); - -defineMacro("\\operatorname", - "\\@ifstar\\operatornamewithlimits\\operatorname@"); - -defineFunctionBuilders({ - type: "ordgroup", - mathmlBuilder(group, style) { - return buildExpressionRow(group.body, style, true); - } -}); - -defineFunction({ - type: "overline", - names: ["\\overline"], - props: { - numArgs: 1 - }, - handler({ parser }, args) { - const body = args[0]; - return { - type: "overline", - mode: parser.mode, - body - }; - }, - mathmlBuilder(group, style) { - const operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u005F")]); - operator.setAttribute("stretchy", "true"); - - const node = new mathMLTree.MathNode( - "mover", - [buildGroup(group.body, style), operator] - ); - node.setAttribute("accent", "true"); - - return node; - } -}); - -defineFunction({ - type: "phantom", - names: ["\\phantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "phantom", - mode: parser.mode, - body: ordargument(body) - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(group.body, style); - return new mathMLTree.MathNode("mphantom", inner); - } -}); - -defineFunction({ - type: "hphantom", - names: ["\\hphantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "hphantom", - mode: parser.mode, - body - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(ordargument(group.body), style); - const phantom = new mathMLTree.MathNode("mphantom", inner); - const node = new mathMLTree.MathNode("mpadded", [phantom]); - node.setAttribute("height", "0px"); - node.setAttribute("depth", "0px"); - return node; - } -}); - -defineFunction({ - type: "vphantom", - names: ["\\vphantom"], - props: { - numArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args) => { - const body = args[0]; - return { - type: "vphantom", - mode: parser.mode, - body - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(ordargument(group.body), style); - const phantom = new mathMLTree.MathNode("mphantom", inner); - const node = new mathMLTree.MathNode("mpadded", [phantom]); - node.setAttribute("width", "0px"); - return node; - } -}); - -// \pmb is a simulation of bold font. -// The version of \pmb in ambsy.sty works by typesetting three copies of the argument -// with small offsets. We use CSS text-shadow. -// It's a hack. Not as good as a real bold font. Better than nothing. - -defineFunction({ - type: "pmb", - names: ["\\pmb"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "pmb", - mode: parser.mode, - body: ordargument(args[0]) - } - }, - mathmlBuilder(group, style) { - const inner = buildExpression(group.body, style); - // Wrap with an element. - const node = wrapWithMstyle(inner); - node.setAttribute("style", "text-shadow: 0.02em 0.01em 0.04px"); - return node - } -}); - -const sign = num => num >= 0 ? "+" : "-"; - -// \raise, \lower, and \raisebox - -const mathmlBuilder$a = (group, style) => { - const newStyle = style.withLevel(StyleLevel.TEXT); - const node = new mathMLTree.MathNode("mpadded", [buildGroup(group.body, newStyle)]); - const dy = calculateSize(group.dy, style); - node.setAttribute("voffset", dy.number + dy.unit); - const dyAbs = Math.abs(dy.number); - node.setAttribute("height", sign(dy.number) + dyAbs + dy.unit); - node.setAttribute("depth", sign(-dy.number) + dyAbs + dy.unit); - return node -}; - -defineFunction({ - type: "raise", - names: ["\\raise", "\\lower"], - props: { - numArgs: 2, - argTypes: ["size", "primitive"], - primitive: true - }, - handler({ parser, funcName }, args) { - const amount = assertNodeType(args[0], "size").value; - if (funcName === "\\lower") { amount.number *= -1; } - const body = args[1]; - return { - type: "raise", - mode: parser.mode, - dy: amount, - body - }; - }, - mathmlBuilder: mathmlBuilder$a -}); - - -defineFunction({ - type: "raise", - names: ["\\raisebox"], - props: { - numArgs: 2, - argTypes: ["size", "hbox"], - allowedInText: true - }, - handler({ parser, funcName }, args) { - const amount = assertNodeType(args[0], "size").value; - const body = args[1]; - return { - type: "raise", - mode: parser.mode, - dy: amount, - body - }; - }, - mathmlBuilder: mathmlBuilder$a -}); - -defineFunction({ - type: "ref", - names: ["\\ref", "\\eqref"], - props: { - numArgs: 1, - argTypes: ["raw"] - }, - handler({ parser, funcName }, args) { - return { - type: "ref", - mode: parser.mode, - funcName, - string: args[0].string.replace(invalidIdRegEx, "") - }; - }, - mathmlBuilder(group, style) { - // Create an empty text node. Set a class and an href. - // The post-processor will populate with the target's tag or equation number. - const classes = group.funcName === "\\ref" ? ["tml-ref"] : ["tml-ref", "tml-eqref"]; - const node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("")], classes); - node.setAttribute("href", "#" + group.string); - return node - } -}); - -defineFunction({ - type: "internal", - names: ["\\relax"], - props: { - numArgs: 0, - allowedInText: true - }, - handler({ parser }) { - return { - type: "internal", - mode: parser.mode - }; - } -}); - -defineFunction({ - type: "rule", - names: ["\\rule"], - props: { - numArgs: 2, - numOptionalArgs: 1, - argTypes: ["size", "size", "size"] - }, - handler({ parser }, args, optArgs) { - const shift = optArgs[0]; - const width = assertNodeType(args[0], "size"); - const height = assertNodeType(args[1], "size"); - return { - type: "rule", - mode: parser.mode, - shift: shift && assertNodeType(shift, "size").value, - width: width.value, - height: height.value - }; - }, - mathmlBuilder(group, style) { - const width = calculateSize(group.width, style); - const height = calculateSize(group.height, style); - const shift = group.shift - ? calculateSize(group.shift, style) - : { number: 0, unit: "em" }; - const color = (style.color && style.getColor()) || "black"; - - const rule = new mathMLTree.MathNode("mspace"); - rule.setAttribute("mathbackground", color); - rule.setAttribute("width", width.number + width.unit); - rule.setAttribute("height", height.number + height.unit); - - const wrapper = new mathMLTree.MathNode("mpadded", [rule]); - if (shift.number >= 0) { - wrapper.setAttribute("height", "+" + shift.number + shift.unit); - } else { - wrapper.setAttribute("height", shift.number + shift.unit); - wrapper.setAttribute("depth", "+" + -shift.number + shift.unit); - } - wrapper.setAttribute("voffset", shift.number + shift.unit); - return wrapper; - } -}); - -// The size mappings are taken from TeX with \normalsize=10pt. -// We don't have to track script level. MathML does that. -const sizeMap = { - "\\tiny": 0.5, - "\\sixptsize": 0.6, - "\\Tiny": 0.6, - "\\scriptsize": 0.7, - "\\footnotesize": 0.8, - "\\small": 0.9, - "\\normalsize": 1.0, - "\\large": 1.2, - "\\Large": 1.44, - "\\LARGE": 1.728, - "\\huge": 2.074, - "\\Huge": 2.488 -}; - -defineFunction({ - type: "sizing", - names: [ - "\\tiny", - "\\sixptsize", - "\\Tiny", - "\\scriptsize", - "\\footnotesize", - "\\small", - "\\normalsize", - "\\large", - "\\Large", - "\\LARGE", - "\\huge", - "\\Huge" - ], - props: { - numArgs: 0, - allowedInText: true - }, - handler: ({ breakOnTokenText, funcName, parser }, args) => { - const body = parser.parseExpression(false, breakOnTokenText); - return { - type: "sizing", - mode: parser.mode, - funcName, - body - }; - }, - mathmlBuilder: (group, style) => { - const inner = buildExpression(group.body, style); - // Wrap with an element. - const node = wrapWithMstyle(inner); - node.setAttribute("mathsize", sizeMap[group.funcName] + "em"); - return node; - } -}); - -// smash, with optional [tb], as in AMS - -defineFunction({ - type: "smash", - names: ["\\smash"], - props: { - numArgs: 1, - numOptionalArgs: 1, - allowedInText: true - }, - handler: ({ parser }, args, optArgs) => { - let smashHeight = false; - let smashDepth = false; - const tbArg = optArgs[0] && assertNodeType(optArgs[0], "ordgroup"); - if (tbArg) { - // Optional [tb] argument is engaged. - // ref: amsmath: \renewcommand{\smash}[1][tb]{% - // def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}% - let letter = ""; - for (let i = 0; i < tbArg.body.length; ++i) { - const node = tbArg.body[i]; - // TODO: Write an AssertSymbolNode - letter = node.text; - if (letter === "t") { - smashHeight = true; - } else if (letter === "b") { - smashDepth = true; - } else { - smashHeight = false; - smashDepth = false; - break; - } - } - } else { - smashHeight = true; - smashDepth = true; - } - - const body = args[0]; - return { - type: "smash", - mode: parser.mode, - body, - smashHeight, - smashDepth - }; - }, - mathmlBuilder: (group, style) => { - const node = new mathMLTree.MathNode("mpadded", [buildGroup(group.body, style)]); - - if (group.smashHeight) { - node.setAttribute("height", "0px"); - } - - if (group.smashDepth) { - node.setAttribute("depth", "0px"); - } - - return node; - } -}); - -defineFunction({ - type: "sqrt", - names: ["\\sqrt"], - props: { - numArgs: 1, - numOptionalArgs: 1 - }, - handler({ parser }, args, optArgs) { - const index = optArgs[0]; - const body = args[0]; - return { - type: "sqrt", - mode: parser.mode, - body, - index - }; - }, - mathmlBuilder(group, style) { - const { body, index } = group; - return index - ? new mathMLTree.MathNode("mroot", [ - buildGroup(body, style), - buildGroup(index, style.incrementLevel()) - ]) - : new mathMLTree.MathNode("msqrt", [buildGroup(body, style)]); - } -}); - -const styleMap = { - display: 0, - text: 1, - script: 2, - scriptscript: 3 -}; - -const styleAttributes = { - display: ["0", "true"], - text: ["0", "false"], - script: ["1", "false"], - scriptscript: ["2", "false"] -}; - -defineFunction({ - type: "styling", - names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"], - props: { - numArgs: 0, - allowedInText: true, - primitive: true - }, - handler({ breakOnTokenText, funcName, parser }, args) { - // parse out the implicit body - const body = parser.parseExpression(true, breakOnTokenText); - - const scriptLevel = funcName.slice(1, funcName.length - 5); - return { - type: "styling", - mode: parser.mode, - // Figure out what scriptLevel to use by pulling out the scriptLevel from - // the function name - scriptLevel, - body - }; - }, - mathmlBuilder(group, style) { - // Figure out what scriptLevel we're changing to. - const newStyle = style.withLevel(styleMap[group.scriptLevel]); - // The style argument in the next line does NOT directly set a MathML script level. - // It just tracks the style level, in case we need to know it for supsub or mathchoice. - const inner = buildExpression(group.body, newStyle); - // Wrap with an element. - const node = wrapWithMstyle(inner); - - const attr = styleAttributes[group.scriptLevel]; - - // Here is where we set the MathML script level. - node.setAttribute("scriptlevel", attr[0]); - node.setAttribute("displaystyle", attr[1]); - - return node; - } -}); - -/** - * Sometimes, groups perform special rules when they have superscripts or - * subscripts attached to them. This function lets the `supsub` group know that - * Sometimes, groups perform special rules when they have superscripts or - * its inner element should handle the superscripts and subscripts instead of - * handling them itself. - */ - -// Helpers -const symbolRegEx = /^m(over|under|underover)$/; - -// Super scripts and subscripts, whose precise placement can depend on other -// functions that precede them. -defineFunctionBuilders({ - type: "supsub", - mathmlBuilder(group, style) { - // Is the inner group a relevant horizonal brace? - let isBrace = false; - let isOver; - let isSup; - let appendApplyFunction = false; - let needsLeadingSpace = false; - - if (group.base && group.base.type === "horizBrace") { - isSup = !!group.sup; - if (isSup === group.base.isOver) { - isBrace = true; - isOver = group.base.isOver; - } - } - - if (group.base && !group.base.stack && - (group.base.type === "op" || group.base.type === "operatorname")) { - group.base.parentIsSupSub = true; - appendApplyFunction = !group.base.symbol; - needsLeadingSpace = group.base.needsLeadingSpace; - } - - const children = group.base && group.base.stack - ? [buildGroup(group.base.body[0], style)] - : [buildGroup(group.base, style)]; - - const childStyle = style.inSubOrSup(); - if (group.sub) { - children.push(buildGroup(group.sub, childStyle)); - } - - if (group.sup) { - children.push(buildGroup(group.sup, childStyle)); - } - - let nodeType; - if (isBrace) { - nodeType = isOver ? "mover" : "munder"; - } else if (!group.sub) { - const base = group.base; - if ( - base && - base.type === "op" && - base.limits && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "mover"; - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (base.limits || style.level === StyleLevel.DISPLAY) - ) { - nodeType = "mover"; - } else { - nodeType = "msup"; - } - } else if (!group.sup) { - const base = group.base; - if ( - base && - base.type === "op" && - base.limits && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "munder"; - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (base.limits || style.level === StyleLevel.DISPLAY) - ) { - nodeType = "munder"; - } else { - nodeType = "msub"; - } - } else { - const base = group.base; - if (base && ((base.type === "op" && base.limits) || base.type === "multiscript") && - (style.level === StyleLevel.DISPLAY || base.alwaysHandleSupSub) - ) { - nodeType = "munderover"; - } else if ( - base && - base.type === "operatorname" && - base.alwaysHandleSupSub && - (style.level === StyleLevel.DISPLAY || base.limits) - ) { - nodeType = "munderover"; - } else { - nodeType = "msubsup"; - } - } - - let node = new mathMLTree.MathNode(nodeType, children); - if (appendApplyFunction) { - // Append an . - // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4 - const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]); - if (needsLeadingSpace) { - const space = new mathMLTree.MathNode("mspace"); - space.setAttribute("width", "0.1667em"); // thin space. - node = mathMLTree.newDocumentFragment([space, node, operator]); - } else { - node = mathMLTree.newDocumentFragment([node, operator]); - } - } else if (symbolRegEx.test(nodeType)) { - // Wrap in a . Otherwise Firefox stretchy parens will not stretch to include limits. - node = new mathMLTree.MathNode("mrow", [node]); - } - - return node - } -}); - -// Operator ParseNodes created in Parser.js from symbol Groups in src/symbols.js. - -const short = ["\\shortmid", "\\nshortmid", "\\shortparallel", - "\\nshortparallel", "\\smallsetminus"]; - -defineFunctionBuilders({ - type: "atom", - mathmlBuilder(group, style) { - const node = new mathMLTree.MathNode("mo", [makeText(group.text, group.mode)]); - if (group.family === "punct") { - node.setAttribute("separator", "true"); - } else if (group.family === "open" || group.family === "close") { - // Delims built here should not stretch vertically. - // See delimsizing.js for stretchy delims. - if (group.family === "open") { - node.setAttribute("form", "prefix"); - // Set an explicit attribute for stretch. Otherwise Firefox may do it wrong. - node.setAttribute("stretchy", "false"); - } else if (group.family === "close") { - node.setAttribute("form", "postfix"); - node.setAttribute("stretchy", "false"); - } - } else if (group.text === "\\mid") { - // Firefox messes up this spacing if at the end of an . See it explicitly. - node.setAttribute("lspace", "0.22em"); // medium space - node.setAttribute("rspace", "0.22em"); - node.setAttribute("stretchy", "false"); - } else if (short.includes(group.text)) { - node.setAttribute("mathsize", "70%"); - } else if (group.text === ":") { - // ":" is not in the MathML operator dictionary. Give it BIN spacing. - node.attributes.lspace = "0.2222em"; - node.attributes.rspace = "0.2222em"; - } - return node; - } -}); - -/** - * Maps TeX font commands to "mathvariant" attribute in buildMathML.js - */ -const fontMap = { - // styles - mathbf: "bold", - mathrm: "normal", - textit: "italic", - mathit: "italic", - mathnormal: "italic", - - // families - mathbb: "double-struck", - mathcal: "script", - mathfrak: "fraktur", - mathscr: "script", - mathsf: "sans-serif", - mathtt: "monospace", - oldstylenums: "oldstylenums" -}; - -/** - * Returns the math variant as a string or null if none is required. - */ -const getVariant = function(group, style) { - // Handle font specifiers as best we can. - // Chromium does not support the MathML mathvariant attribute. - // So we'll use Unicode replacement characters instead. - // But first, determine the math variant. - - // Deal with the \textit, \textbf, etc., functions. - if (style.fontFamily === "texttt") { - return "monospace" - } else if (style.fontFamily === "textsc") { - return "normal"; // handled via character substitution in symbolsOrd.js. - } else if (style.fontFamily === "textsf") { - if (style.fontShape === "textit" && style.fontWeight === "textbf") { - return "sans-serif-bold-italic" - } else if (style.fontShape === "textit") { - return "sans-serif-italic" - } else if (style.fontWeight === "textbf") { - return "sans-serif-bold" - } else { - return "sans-serif" - } - } else if (style.fontShape === "textit" && style.fontWeight === "textbf") { - return "bold-italic" - } else if (style.fontShape === "textit") { - return "italic" - } else if (style.fontWeight === "textbf") { - return "bold" - } - - // Deal with the \mathit, mathbf, etc, functions. - const font = style.font; - if (!font || font === "mathnormal") { - return null - } - - const mode = group.mode; - switch (font) { - case "mathit": - return "italic" - case "mathrm": { - const codePoint = group.text.codePointAt(0); - // LaTeX \mathrm returns italic for Greek characters. - return (0x03ab < codePoint && codePoint < 0x03cf) ? "italic" : "normal" - } - case "greekItalic": - return "italic" - case "up@greek": - return "normal" - case "boldsymbol": - case "mathboldsymbol": - return "bold-italic" - case "mathbf": - return "bold" - case "mathbb": - return "double-struck" - case "mathfrak": - return "fraktur" - case "mathscr": - case "mathcal": - return "script" - case "mathsf": - return "sans-serif" - case "mathtt": - return "monospace" - case "oldstylenums": - return "oldstylenums" - } - - let text = group.text; - if (symbols[mode][text] && symbols[mode][text].replace) { - text = symbols[mode][text].replace; - } - - return Object.prototype.hasOwnProperty.call(fontMap, font) ? fontMap[font] : null -}; - -// Chromium does not support the MathML `mathvariant` attribute. -// Instead, we replace ASCII characters with Unicode characters that -// are defined in the font as bold, italic, double-struck, etc. -// This module identifies those Unicode code points. - -// First, a few helpers. -const script = Object.freeze({ - B: 0x20EA, // Offset from ASCII B to Unicode script B - E: 0x20EB, - F: 0x20EB, - H: 0x20C3, - I: 0x20C7, - L: 0x20C6, - M: 0x20E6, - R: 0x20C9, - e: 0x20CA, - g: 0x20A3, - o: 0x20C5 -}); - -const frak = Object.freeze({ - C: 0x20EA, - H: 0x20C4, - I: 0x20C8, - R: 0x20CA, - Z: 0x20CE -}); - -const bbb = Object.freeze({ - C: 0x20BF, // blackboard bold - H: 0x20C5, - N: 0x20C7, - P: 0x20C9, - Q: 0x20C9, - R: 0x20CB, - Z: 0x20CA -}); - -const bold = Object.freeze({ - "\u03f5": 0x1D2E7, // lunate epsilon - "\u03d1": 0x1D30C, // vartheta - "\u03f0": 0x1D2EE, // varkappa - "\u03c6": 0x1D319, // varphi - "\u03f1": 0x1D2EF, // varrho - "\u03d6": 0x1D30B // varpi -}); - -const boldItalic = Object.freeze({ - "\u03f5": 0x1D35B, // lunate epsilon - "\u03d1": 0x1D380, // vartheta - "\u03f0": 0x1D362, // varkappa - "\u03c6": 0x1D38D, // varphi - "\u03f1": 0x1D363, // varrho - "\u03d6": 0x1D37F // varpi -}); - -const boldsf = Object.freeze({ - "\u03f5": 0x1D395, // lunate epsilon - "\u03d1": 0x1D3BA, // vartheta - "\u03f0": 0x1D39C, // varkappa - "\u03c6": 0x1D3C7, // varphi - "\u03f1": 0x1D39D, // varrho - "\u03d6": 0x1D3B9 // varpi -}); - -const bisf = Object.freeze({ - "\u03f5": 0x1D3CF, // lunate epsilon - "\u03d1": 0x1D3F4, // vartheta - "\u03f0": 0x1D3D6, // varkappa - "\u03c6": 0x1D401, // varphi - "\u03f1": 0x1D3D7, // varrho - "\u03d6": 0x1D3F3 // varpi -}); - -// Code point offsets below are derived from https://www.unicode.org/charts/PDF/U1D400.pdf -const offset = Object.freeze({ - upperCaseLatin: { // A-Z - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D3BF }, - "italic": ch => { return 0x1D3F3 }, - "bold-italic": ch => { return 0x1D427 }, - "script": ch => { return script[ch] || 0x1D45B }, - "script-bold": ch => { return 0x1D48F }, - "fraktur": ch => { return frak[ch] || 0x1D4C3 }, - "fraktur-bold": ch => { return 0x1D52B }, - "double-struck": ch => { return bbb[ch] || 0x1D4F7 }, - "sans-serif": ch => { return 0x1D55F }, - "sans-serif-bold": ch => { return 0x1D593 }, - "sans-serif-italic": ch => { return 0x1D5C7 }, - "sans-serif-bold-italic": ch => { return 0x1D63C }, - "monospace": ch => { return 0x1D62F } - }, - lowerCaseLatin: { // a-z - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D3B9 }, - "italic": ch => { return ch === "h" ? 0x20A6 : 0x1D3ED }, - "bold-italic": ch => { return 0x1D421 }, - "script": ch => { return script[ch] || 0x1D455 }, - "script-bold": ch => { return 0x1D489 }, - "fraktur": ch => { return 0x1D4BD }, - "fraktur-bold": ch => { return 0x1D525 }, - "double-struck": ch => { return 0x1D4F1 }, - "sans-serif": ch => { return 0x1D559 }, - "sans-serif-bold": ch => { return 0x1D58D }, - "sans-serif-italic": ch => { return 0x1D5C1 }, - "sans-serif-bold-italic": ch => { return 0x1D5F5 }, - "monospace": ch => { return 0x1D629 } - }, - upperCaseGreek: { // A-Ω ∇ - "normal": ch => { return 0 }, - "bold": ch => { return ch === "∇" ? 0x1B4BA : 0x1D317 }, - "italic": ch => { return ch === "∇" ? 0x1B4F4 : 0x1D351 }, - // \boldsymbol actually returns upright bold for upperCaseGreek - "bold-italic": ch => { return ch === "∇" ? 0x1B4BA : 0x1D317 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - // Unicode has no code points for regular-weight san-serif Greek. Use bold. - "sans-serif": ch => { return ch === "∇" ? 0x1B568 : 0x1D3C5 }, - "sans-serif-bold": ch => { return ch === "∇" ? 0x1B568 : 0x1D3C5 }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return ch === "∇" ? 0x1B5A2 : 0x1D3FF }, - "monospace": ch => { return 0 } - }, - lowerCaseGreek: { // α-ω - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D311 }, - "italic": ch => { return 0x1D34B }, - "bold-italic": ch => { return ch === "\u03d5" ? 0x1D37E : 0x1D385 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - // Unicode has no code points for regular-weight san-serif Greek. Use bold. - "sans-serif": ch => { return 0x1D3BF }, - "sans-serif-bold": ch => { return 0x1D3BF }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return 0x1D3F9 }, - "monospace": ch => { return 0 } - }, - varGreek: { // \varGamma, etc - "normal": ch => { return 0 }, - "bold": ch => { return bold[ch] || -51 }, - "italic": ch => { return 0 }, - "bold-italic": ch => { return boldItalic[ch] || 0x3A }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0 }, - "sans-serif": ch => { return boldsf[ch] || 0x74 }, - "sans-serif-bold": ch => { return boldsf[ch] || 0x74 }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return bisf[ch] || 0xAE }, - "monospace": ch => { return 0 } - }, - numeral: { // 0-9 - "normal": ch => { return 0 }, - "bold": ch => { return 0x1D79E }, - "italic": ch => { return 0 }, - "bold-italic": ch => { return 0 }, - "script": ch => { return 0 }, - "script-bold": ch => { return 0 }, - "fraktur": ch => { return 0 }, - "fraktur-bold": ch => { return 0 }, - "double-struck": ch => { return 0x1D7A8 }, - "sans-serif": ch => { return 0x1D7B2 }, - "sans-serif-bold": ch => { return 0x1D7BC }, - "sans-serif-italic": ch => { return 0 }, - "sans-serif-bold-italic": ch => { return 0 }, - "monospace": ch => { return 0x1D7C6 } - } -}); - -const variantChar = (ch, variant) => { - const codePoint = ch.codePointAt(0); - const block = 0x40 < codePoint && codePoint < 0x5b - ? "upperCaseLatin" - : 0x60 < codePoint && codePoint < 0x7b - ? "lowerCaseLatin" - : (0x390 < codePoint && codePoint < 0x3AA) || ch === "∇" - ? "upperCaseGreek" - : 0x3B0 < codePoint && codePoint < 0x3CA || ch === "\u03d5" - ? "lowerCaseGreek" - : 0x1D6E1 < codePoint && codePoint < 0x1D6FC || bold[ch] - ? "varGreek" - : (0x2F < codePoint && codePoint < 0x3A) - ? "numeral" - : "other"; - return block === "other" - ? ch - : String.fromCodePoint(codePoint + offset[block][variant](ch)) -}; - -const smallCaps = Object.freeze({ - a: "ᴀ", - b: "ʙ", - c: "ᴄ", - d: "ᴅ", - e: "ᴇ", - f: "ꜰ", - g: "ɢ", - h: "ʜ", - i: "ɪ", - j: "ᴊ", - k: "ᴋ", - l: "ʟ", - m: "ᴍ", - n: "ɴ", - o: "ᴏ", - p: "ᴘ", - q: "ǫ", - r: "ʀ", - s: "s", - t: "ᴛ", - u: "ᴜ", - v: "ᴠ", - w: "ᴡ", - x: "x", - y: "ʏ", - z: "ᴢ" -}); - -// "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in -// src/symbols.js. - -const numberRegEx = /^\d[\d.]*$/; // Keep in sync with numberRegEx in Parser.js - -const italicNumber = (text, variant) => { - const mn = new mathMLTree.MathNode("mn", [text]); - const wrapper = new mathMLTree.MathNode("mstyle", [mn]); - wrapper.style["font-style"] = "italic"; - wrapper.style["font-family"] = "Cambria, 'Times New Roman', serif"; - if (variant === "bold-italic") { wrapper.style["font-weight"] = "bold"; } - return wrapper -}; - -defineFunctionBuilders({ - type: "mathord", - mathmlBuilder(group, style) { - const text = makeText(group.text, group.mode, style); - const codePoint = text.text.codePointAt(0); - // Test for upper-case Greek - const defaultVariant = (0x0390 < codePoint && codePoint < 0x03aa) ? "normal" : "italic"; - const variant = getVariant(group, style) || defaultVariant; - if (variant === "script") { - text.text = variantChar(text.text, variant); - return new mathMLTree.MathNode("mi", [text], [style.font]) - } else if (variant !== "italic") { - text.text = variantChar(text.text, variant); - } - const node = new mathMLTree.MathNode("mi", [text]); - // TODO: Handle U+1D49C - U+1D4CF per https://www.unicode.org/charts/PDF/U1D400.pdf - if (variant === "normal") { - node.setAttribute("mathvariant", "normal"); - } - return node - } -}); - -defineFunctionBuilders({ - type: "textord", - mathmlBuilder(group, style) { - let ch = group.text; - const codePoint = ch.codePointAt(0); - if (style.fontFamily === "textsc") { - // Convert small latin letters to small caps. - if (96 < codePoint && codePoint < 123) { - ch = smallCaps[ch]; - } - } - const text = makeText(ch, group.mode, style); - const variant = getVariant(group, style) || "normal"; - - let node; - if (group.mode === "text") { - if (variant === "italic" || variant === "bold-italic") { - if (numberRegEx.test(group.text)) { - return italicNumber(text, variant) - } - } - if (variant !== "normal") { - text.text = variantChar(text.text, variant); - } - node = new mathMLTree.MathNode("mtext", [text]); - } else if (numberRegEx.test(group.text)) { - if (variant === "oldstylenums") { - const ms = new mathMLTree.MathNode("mstyle", [text], ["oldstylenums"]); - node = new mathMLTree.MathNode("mn", [ms]); - } else if (variant === "italic" || variant === "bold-italic") { - return italicNumber(text, variant) - } else { - if (variant !== "normal") { - text.text = text.text.split("").map(c => variantChar(c, variant)).join(""); - } - node = new mathMLTree.MathNode("mn", [text]); - } - } else if (group.text === "\\prime") { - node = new mathMLTree.MathNode("mo", [text]); - } else { - const origText = text.text; - if (variant !== "italic") { - text.text = variantChar(text.text, variant); - } - node = new mathMLTree.MathNode("mi", [text]); - if (text.text === origText ) { - node.setAttribute("mathvariant", "italic"); - } - } - return node - } -}); - -// A map of CSS-based spacing functions to their CSS class. -const cssSpace = { - "\\nobreak": "nobreak", - "\\allowbreak": "allowbreak" -}; - -// A lookup table to determine whether a spacing function/symbol should be -// treated like a regular space character. If a symbol or command is a key -// in this table, then it should be a regular space character. Furthermore, -// the associated value may have a `className` specifying an extra CSS class -// to add to the created `span`. -const regularSpace = { - " ": {}, - "\\ ": {}, - "~": { - className: "nobreak" - }, - "\\space": {}, - "\\nobreakspace": { - className: "nobreak" - } -}; - -// ParseNode<"spacing"> created in Parser.js from the "spacing" symbol Groups in -// src/symbols.js. -defineFunctionBuilders({ - type: "spacing", - mathmlBuilder(group, style) { - let node; - - if (Object.prototype.hasOwnProperty.call(regularSpace, group.text)) { - // Firefox does not render a space in a . So write a no-break space. - // TODO: If Firefox fixes that bug, uncomment the next line and write ch into the node. - //const ch = (regularSpace[group.text].className === "nobreak") ? "\u00a0" : " " - node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("\u00a0")]); - } else if (Object.prototype.hasOwnProperty.call(cssSpace, group.text)) { - // MathML 3.0 calls for nobreak to occur in an , not an - // Ref: https://www.w3.org/Math/draft-spec/mathml.html#chapter3_presm.lbattrs - node = new mathMLTree.MathNode("mo"); - if (group.text === "\\nobreak") { - node.setAttribute("linebreak", "nobreak"); - } - } else { - throw new ParseError(`Unknown type of space "${group.text}"`) - } - - return node - } -}); - -defineFunctionBuilders({ - type: "tag" -}); - -// For a \tag, the work usually done in a mathmlBuilder is instead done in buildMathML.js. -// That way, a \tag can be pulled out of the parse tree and wrapped around the outer node. - -// Non-mathy text, possibly in a font -const textFontFamilies = { - "\\text": undefined, - "\\textrm": "textrm", - "\\textsf": "textsf", - "\\texttt": "texttt", - "\\textnormal": "textrm", - "\\textsc": "textsc" // small caps -}; - -const textFontWeights = { - "\\textbf": "textbf", - "\\textmd": "textmd" -}; - -const textFontShapes = { - "\\textit": "textit", - "\\textup": "textup" -}; - -const styleWithFont = (group, style) => { - const font = group.font; - // Checks if the argument is a font family or a font style. - if (!font) { - return style; - } else if (textFontFamilies[font]) { - return style.withTextFontFamily(textFontFamilies[font]); - } else if (textFontWeights[font]) { - return style.withTextFontWeight(textFontWeights[font]); - } else { - return style.withTextFontShape(textFontShapes[font]); - } -}; - -defineFunction({ - type: "text", - names: [ - // Font families - "\\text", - "\\textrm", - "\\textsf", - "\\texttt", - "\\textnormal", - "\\textsc", - // Font weights - "\\textbf", - "\\textmd", - // Font Shapes - "\\textit", - "\\textup" - ], - props: { - numArgs: 1, - argTypes: ["text"], - allowedInArgument: true, - allowedInText: true - }, - handler({ parser, funcName }, args) { - const body = args[0]; - return { - type: "text", - mode: parser.mode, - body: ordargument(body), - font: funcName - }; - }, - mathmlBuilder(group, style) { - const newStyle = styleWithFont(group, style); - const mrow = buildExpressionRow(group.body, newStyle); - - // If possible, consolidate adjacent elements into a single element. - // First, check if it is possible. If not, return the . - if (mrow.type !== "mrow") { return mrow } - if (mrow.children.length === 0) { return mrow } // empty group, e.g., \text{} - const mtext = mrow.children[0]; - if (!mtext.attributes || mtext.type !== "mtext") { return mrow } - const variant = mtext.attributes.mathvariant || ""; - for (let i = 1; i < mrow.children.length; i++) { - const localVariant = mrow.children[i].attributes.mathvariant || ""; - if (localVariant !== variant || mrow.children[i].type !== "mtext") { return mrow } - } - - // Consolidate the elements. - for (let i = 1; i < mrow.children.length; i++) { - mtext.children[0].text += mrow.children[i].children[0].text; - } - mtext.children.splice(1, mtext.children.length - 1); - // Firefox does not render a space at either end of the string. - // To get proper rendering, we replace with no-break spaces. - if (mtext.children[0].text.charAt(0) === " ") { - mtext.children[0].text = "\u00a0" + mtext.children[0].text.slice(1); - } - const L = mtext.children[0].text.length; - if (L > 0 && mtext.children[0].text.charAt(L - 1) === " ") { - mtext.children[0].text = mtext.children[0].text.slice(0, -1) + "\u00a0"; - } - return mtext - } -}); - -// Two functions included to enable migration from Mathjax. - -defineFunction({ - type: "tip", - names: ["\\mathtip"], - props: { - numArgs: 2 - }, - handler({ parser }, args) { - return { - type: "tip", - mode: parser.mode, - body: args[0], - tip: args[1] - }; - }, - mathmlBuilder: (group, style) => { - const math = buildGroup(group.body, style); - const tip = buildGroup(group.tip, style); - // Browsers don't support the tooltip actiontype. - // TODO: Come back and fix \mathtip when it can be done via CSS w/o a JS event. - const node = new mathMLTree.MathNode("maction", [math, tip], ["tml-tip"]); - node.setAttribute("actiontype", "tooltip"); - return node - } -}); - -defineFunction({ - type: "tip", - names: ["\\texttip"], - props: { - numArgs: 2, - argTypes: ["math", "text"] - }, - handler({ parser }, args) { - return { - type: "tip", - mode: parser.mode, - body: args[0], - tip: args[1] - }; - }, - mathmlBuilder: (group, style) => { - const math = buildGroup(group.body, style); - const tip = buildGroup(group.tip, style); - // args[1] only accepted text, so tip is a element or a of them. - let str = ""; - if (tip.type === "mtext") { - str = tip.children[0].text; - } else { - for (const child of tip.children) { - str += child.children[0].text; - } - } - // Implement \texttip via a title attribute. - math.setAttribute("title", str); - return math - } -}); - -defineFunctionBuilders({ - type: "toggle", - mathmlBuilder(group, style) { - const expression = buildExpression(group.body, style); - const node = new mathMLTree.MathNode("maction", expression, [], { cursor: "default" }); - node.setAttribute("actiontype", "toggle"); - return node - } -}); - -defineFunction({ - type: "underline", - names: ["\\underline"], - props: { - numArgs: 1, - allowedInText: true - }, - handler({ parser }, args) { - return { - type: "underline", - mode: parser.mode, - body: args[0] - }; - }, - mathmlBuilder(group, style) { - const operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u005f")]); - operator.setAttribute("stretchy", "true"); - - const node = new mathMLTree.MathNode("munder", - [buildGroup(group.body, style), operator] - ); - node.setAttribute("accentunder", "true"); - - return node; - } -}); - -defineFunction({ - type: "verb", - names: ["\\verb"], - props: { - numArgs: 0, - allowedInText: true - }, - handler(context, args, optArgs) { - // \verb and \verb* are dealt with directly in Parser.js. - // If we end up here, it's because of a failure to match the two delimiters - // in the regex in Lexer.js. LaTeX raises the following error when \verb is - // terminated by end of line (or file). - throw new ParseError("\\verb ended by end of line instead of matching delimiter"); - }, - mathmlBuilder(group, style) { - const text = new mathMLTree.TextNode(makeVerb(group)); - const node = new mathMLTree.MathNode("mtext", [text]); - node.setAttribute("mathvariant", "monospace"); - return node; - } -}); - -/** - * Converts verb group into body string. - * - * \verb* replaces each space with an open box \u2423 - * \verb replaces each space with a no-break space \xA0 - */ -const makeVerb = (group) => group.body.replace(/ /g, group.star ? "\u2423" : "\xA0"); - -/** Include this to ensure that all functions are defined. */ - -const functions = _functions; - -/** - * Lexing or parsing positional information for error reporting. - * This object is immutable. - */ -class SourceLocation { - constructor(lexer, start, end) { - this.lexer = lexer; // Lexer holding the input string. - this.start = start; // Start offset, zero-based inclusive. - this.end = end; // End offset, zero-based exclusive. - } - - /** - * Merges two `SourceLocation`s from location providers, given they are - * provided in order of appearance. - * - Returns the first one's location if only the first is provided. - * - Returns a merged range of the first and the last if both are provided - * and their lexers match. - * - Otherwise, returns null. - */ - static range(first, second) { - if (!second) { - return first && first.loc; - } else if (!first || !first.loc || !second.loc || first.loc.lexer !== second.loc.lexer) { - return null; - } else { - return new SourceLocation(first.loc.lexer, first.loc.start, second.loc.end); - } - } -} - -/** - * Interface required to break circular dependency between Token, Lexer, and - * ParseError. - */ - -/** - * The resulting token returned from `lex`. - * - * It consists of the token text plus some position information. - * The position information is essentially a range in an input string, - * but instead of referencing the bare input string, we refer to the lexer. - * That way it is possible to attach extra metadata to the input string, - * like for example a file name or similar. - * - * The position information is optional, so it is OK to construct synthetic - * tokens if appropriate. Not providing available position information may - * lead to degraded error reporting, though. - */ -class Token { - constructor( - text, // the text of this token - loc - ) { - this.text = text; - this.loc = loc; - } - - /** - * Given a pair of tokens (this and endToken), compute a `Token` encompassing - * the whole input range enclosed by these two. - */ - range( - endToken, // last token of the range, inclusive - text // the text of the newly constructed token - ) { - return new Token(text, SourceLocation.range(this, endToken)); - } -} - -/** - * The Lexer class handles tokenizing the input in various ways. Since our - * parser expects us to be able to backtrack, the lexer allows lexing from any - * given starting point. - * - * Its main exposed function is the `lex` function, which takes a position to - * lex from and a type of token to lex. It defers to the appropriate `_innerLex` - * function. - * - * The various `_innerLex` functions perform the actual lexing of different - * kinds. - */ - -/* The following tokenRegex - * - matches typical whitespace (but not NBSP etc.) using its first two groups - * - does not match any control character \x00-\x1f except whitespace - * - does not match a bare backslash - * - matches any ASCII character except those just mentioned - * - does not match the BMP private use area \uE000-\uF8FF - * - does not match bare surrogate code units - * - matches any BMP character except for those just described - * - matches any valid Unicode surrogate pair - * - mathches numerals - * - matches a backslash followed by one or more whitespace characters - * - matches a backslash followed by one or more letters then whitespace - * - matches a backslash followed by any BMP character - * Capturing groups: - * [1] regular whitespace - * [2] backslash followed by whitespace - * [3] anything else, which may include: - * [4] left character of \verb* - * [5] left character of \verb - * [6] backslash followed by word, excluding any trailing whitespace - * Just because the Lexer matches something doesn't mean it's valid input: - * If there is no matching function or symbol definition, the Parser will - * still reject the input. - */ -const spaceRegexString = "[ \r\n\t]"; -const controlWordRegexString = "\\\\[a-zA-Z@]+"; -const controlSymbolRegexString = "\\\\[^\uD800-\uDFFF]"; -const controlWordWhitespaceRegexString = `(${controlWordRegexString})${spaceRegexString}*`; -const controlSpaceRegexString = "\\\\(\n|[ \r\t]+\n?)[ \r\t]*"; -const combiningDiacriticalMarkString = "[\u0300-\u036f]"; -const combiningDiacriticalMarksEndRegex = new RegExp(`${combiningDiacriticalMarkString}+$`); -const tokenRegexString = - `(${spaceRegexString}+)|` + // whitespace - `${controlSpaceRegexString}|` + // whitespace - "(\\d[\\d.]*" + // numbers (in non-strict mode) - "|[!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + // single codepoint - `${combiningDiacriticalMarkString}*` + // ...plus accents - "|[\uD800-\uDBFF][\uDC00-\uDFFF]" + // surrogate pair - `${combiningDiacriticalMarkString}*` + // ...plus accents - "|\\\\verb\\*([^]).*?\\4" + // \verb* - "|\\\\verb([^*a-zA-Z]).*?\\5" + // \verb unstarred - `|${controlWordWhitespaceRegexString}` + // \macroName + spaces - `|${controlSymbolRegexString})`; // \\, \', etc. - -/** Main Lexer class */ -class Lexer { - constructor(input, settings) { - // Separate accents from characters - this.input = input; - this.settings = settings; - this.tokenRegex = new RegExp( - // Strict Temml, like TeX, lexes one numeral at a time. - // Default Temml lexes contiguous numerals into a single element. - tokenRegexString.replace("\\d[\\d.]*|", settings.strict ? "" : "\\d[\\d.]*|"), - "g" - ); - // Category codes. The lexer only supports comment characters (14) for now. - // MacroExpander additionally distinguishes active (13). - this.catcodes = { - "%": 14, // comment character - "~": 13 // active character - }; - } - - setCatcode(char, code) { - this.catcodes[char] = code; - } - - /** - * This function lexes a single token. - */ - lex() { - const input = this.input; - const pos = this.tokenRegex.lastIndex; - if (pos === input.length) { - return new Token("EOF", new SourceLocation(this, pos, pos)); - } - const match = this.tokenRegex.exec(input); - if (match === null || match.index !== pos) { - throw new ParseError( - `Unexpected character: '${input[pos]}'`, - new Token(input[pos], new SourceLocation(this, pos, pos + 1)) - ); - } - const text = match[6] || match[3] || (match[2] ? "\\ " : " "); - - if (this.catcodes[text] === 14) { - // comment character - const nlIndex = input.indexOf("\n", this.tokenRegex.lastIndex); - if (nlIndex === -1) { - this.tokenRegex.lastIndex = input.length; // EOF - this.settings.reportNonstrict( - "commentAtEnd", - "% comment has no terminating newline; LaTeX would " + - "fail because of commenting the end of math mode (e.g. $)" - ); - } else { - this.tokenRegex.lastIndex = nlIndex + 1; - } - return this.lex(); - } - - return new Token(text, new SourceLocation(this, pos, this.tokenRegex.lastIndex)); - } -} - -/** - * A `Namespace` refers to a space of nameable things like macros or lengths, - * which can be `set` either globally or local to a nested group, using an - * undo stack similar to how TeX implements this functionality. - * Performance-wise, `get` and `set` take constant time. - */ - -class Namespace { - /** - * Both arguments are optional. The first argument is an object of - * built-in mappings which never change. The second argument is an object - * of initial (global-level) mappings, which will constantly change - * according to any global/top-level `set`s done. - */ - constructor(builtins = {}, globalMacros = {}) { - this.current = globalMacros; - this.builtins = builtins; - this.undefStack = []; - } - - /** - * Start a new nested group, affecting future local `set`s. - */ - beginGroup() { - this.undefStack.push({}); - } - - /** - * End current nested group, restoring values before the group began. - */ - endGroup() { - if (this.undefStack.length === 0) { - throw new ParseError( - "Unbalanced namespace destruction: attempt " + - "to pop global namespace; please report this as a bug" - ); - } - const undefs = this.undefStack.pop(); - for (const undef in undefs) { - if (Object.prototype.hasOwnProperty.call(undefs, undef )) { - if (undefs[undef] === undefined) { - delete this.current[undef]; - } else { - this.current[undef] = undefs[undef]; - } - } - } - } - - /** - * Detect whether `name` has a definition. Equivalent to - * `get(name) != null`. - */ - has(name) { - return Object.prototype.hasOwnProperty.call(this.current, name ) || - Object.prototype.hasOwnProperty.call(this.builtins, name ); - } - - /** - * Get the current value of a name, or `undefined` if there is no value. - * - * Note: Do not use `if (namespace.get(...))` to detect whether a macro - * is defined, as the definition may be the empty string which evaluates - * to `false` in JavaScript. Use `if (namespace.get(...) != null)` or - * `if (namespace.has(...))`. - */ - get(name) { - if (Object.prototype.hasOwnProperty.call(this.current, name )) { - return this.current[name]; - } else { - return this.builtins[name]; - } - } - - /** - * Set the current value of a name, and adds an undo - * operation to the undo stack. - */ - set(name, value) { - // Undo this set at end of this group (possibly to `undefined`), - // unless an undo is already in place, in which case that older - // value is the correct one. - const top = this.undefStack[this.undefStack.length - 1]; - if (top && !Object.prototype.hasOwnProperty.call(top, name )) { - top[name] = this.current[name]; - } - this.current[name] = value; - } -} - -/** - * Predefined macros for Temml. - * This can be used to define some commands in terms of others. - */ -const macros = _macros; - -////////////////////////////////////////////////////////////////////// -// macro tools - -defineMacro("\\noexpand", function(context) { - // The expansion is the token itself; but that token is interpreted - // as if its meaning were ‘\relax’ if it is a control sequence that - // would ordinarily be expanded by TeX’s expansion rules. - const t = context.popToken(); - if (context.isExpandable(t.text)) { - t.noexpand = true; - t.treatAsRelax = true; - } - return { tokens: [t], numArgs: 0 }; -}); - -defineMacro("\\expandafter", function(context) { - // TeX first reads the token that comes immediately after \expandafter, - // without expanding it; let’s call this token t. Then TeX reads the - // token that comes after t (and possibly more tokens, if that token - // has an argument), replacing it by its expansion. Finally TeX puts - // t back in front of that expansion. - const t = context.popToken(); - context.expandOnce(true); // expand only an expandable token - return { tokens: [t], numArgs: 0 }; -}); - -// LaTeX's \@firstoftwo{#1}{#2} expands to #1, skipping #2 -// TeX source: \long\def\@firstoftwo#1#2{#1} -defineMacro("\\@firstoftwo", function(context) { - const args = context.consumeArgs(2); - return { tokens: args[0], numArgs: 0 }; -}); - -// LaTeX's \@secondoftwo{#1}{#2} expands to #2, skipping #1 -// TeX source: \long\def\@secondoftwo#1#2{#2} -defineMacro("\\@secondoftwo", function(context) { - const args = context.consumeArgs(2); - return { tokens: args[1], numArgs: 0 }; -}); - -// LaTeX's \@ifnextchar{#1}{#2}{#3} looks ahead to the next (unexpanded) -// symbol that isn't a space, consuming any spaces but not consuming the -// first nonspace character. If that nonspace character matches #1, then -// the macro expands to #2; otherwise, it expands to #3. -defineMacro("\\@ifnextchar", function(context) { - const args = context.consumeArgs(3); // symbol, if, else - context.consumeSpaces(); - const nextToken = context.future(); - if (args[0].length === 1 && args[0][0].text === nextToken.text) { - return { tokens: args[1], numArgs: 0 }; - } else { - return { tokens: args[2], numArgs: 0 }; - } -}); - -// LaTeX's \@ifstar{#1}{#2} looks ahead to the next (unexpanded) symbol. -// If it is `*`, then it consumes the symbol, and the macro expands to #1; -// otherwise, the macro expands to #2 (without consuming the symbol). -// TeX source: \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}} -defineMacro("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}"); - -// LaTeX's \TextOrMath{#1}{#2} expands to #1 in text mode, #2 in math mode -defineMacro("\\TextOrMath", function(context) { - const args = context.consumeArgs(2); - if (context.mode === "text") { - return { tokens: args[0], numArgs: 0 }; - } else { - return { tokens: args[1], numArgs: 0 }; - } -}); - -const stringFromArg = arg => { - // Reverse the order of the arg and return a string. - let str = ""; - for (let i = arg.length - 1; i > -1; i--) { - str += arg[i].text; - } - return str -}; - -// Lookup table for parsing numbers in base 8 through 16 -const digitToNumber = { - 0: 0, - 1: 1, - 2: 2, - 3: 3, - 4: 4, - 5: 5, - 6: 6, - 7: 7, - 8: 8, - 9: 9, - a: 10, - A: 10, - b: 11, - B: 11, - c: 12, - C: 12, - d: 13, - D: 13, - e: 14, - E: 14, - f: 15, - F: 15 -}; - -const nextCharNumber = context => { - const numStr = context.future().text; - if (numStr === "EOF") { return [null, ""] } - return [digitToNumber[numStr.charAt(0)], numStr] -}; - -const appendCharNumbers = (number, numStr, base) => { - for (let i = 1; i < numStr.length; i++) { - const digit = digitToNumber[numStr.charAt(i)]; - number *= base; - number += digit; - } - return number -}; - -// TeX \char makes a literal character (catcode 12) using the following forms: -// (see The TeXBook, p. 43) -// \char123 -- decimal -// \char'123 -- octal -// \char"123 -- hex -// \char`x -- character that can be written (i.e. isn't active) -// \char`\x -- character that cannot be written (e.g. %) -// These all refer to characters from the font, so we turn them into special -// calls to a function \@char dealt with in the Parser. -defineMacro("\\char", function(context) { - let token = context.popToken(); - let base; - let number = ""; - if (token.text === "'") { - base = 8; - token = context.popToken(); - } else if (token.text === '"') { - base = 16; - token = context.popToken(); - } else if (token.text === "`") { - token = context.popToken(); - if (token.text[0] === "\\") { - number = token.text.charCodeAt(1); - } else if (token.text === "EOF") { - throw new ParseError("\\char` missing argument"); - } else { - number = token.text.charCodeAt(0); - } - } else { - base = 10; - } - if (base) { - // Parse a number in the given base, starting with first `token`. - let numStr = token.text; - number = digitToNumber[numStr.charAt(0)]; - if (number == null || number >= base) { - throw new ParseError(`Invalid base-${base} digit ${token.text}`); - } - number = appendCharNumbers(number, numStr, base); - let digit; - [digit, numStr] = nextCharNumber(context); - while (digit != null && digit < base) { - number *= base; - number += digit; - number = appendCharNumbers(number, numStr, base); - context.popToken(); - [digit, numStr] = nextCharNumber(context); - } - } - return `\\@char{${number}}`; -}); - -defineMacro("\\hbox", "\\text{#1}"); - -// Per TeXbook p.122, "/" gets zero operator spacing. -// And MDN recommends using U+2044 instead of / for inline -defineMacro("/", "{\u2044}"); - -// Since Temml has no \par, ignore \long. -defineMacro("\\long", ""); - -////////////////////////////////////////////////////////////////////// -// Grouping -// \let\bgroup={ \let\egroup=} -defineMacro("\\bgroup", "{"); -defineMacro("\\egroup", "}"); - -// Symbols from latex.ltx: -// \def~{\nobreakspace{}} -// \def\lq{`} -// \def\rq{'} -// \def \aa {\r a} -defineMacro("~", "\\nobreakspace"); -defineMacro("\\lq", "`"); -defineMacro("\\rq", "'"); -defineMacro("\\aa", "\\r a"); - -defineMacro("\\Bbbk", "\\Bbb{k}"); - -// \mathstrut from the TeXbook, p 360 -defineMacro("\\mathstrut", "\\vphantom{(}"); - -// \underbar from TeXbook p 353 -defineMacro("\\underbar", "\\underline{\\text{#1}}"); - -////////////////////////////////////////////////////////////////////// -// LaTeX_2ε - -// \vdots{\vbox{\baselineskip4\p@ \lineskiplimit\z@ -// \kern6\p@\hbox{.}\hbox{.}\hbox{.}}} -// We'll call \varvdots, which gets a glyph from symbols.js. -// The zero-width rule gets us an equivalent to the vertical 6pt kern. -defineMacro("\\vdots", "\\mathord{\\varvdots\\rule{0pt}{15pt}}"); -defineMacro("\u22ee", "\\vdots"); - -////////////////////////////////////////////////////////////////////// -// amsmath.sty -// http://mirrors.concertpass.com/tex-archive/macros/latex/required/amsmath/amsmath.pdf - -//\newcommand{\substack}[1]{\subarray{c}#1\endsubarray} -defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}"); - -// \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}} -defineMacro("\\boxed", "\\fbox{$\\displaystyle{#1}$}"); - -// \def\iff{\DOTSB\;\Longleftrightarrow\;} -// \def\implies{\DOTSB\;\Longrightarrow\;} -// \def\impliedby{\DOTSB\;\Longleftarrow\;} -defineMacro("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;"); -defineMacro("\\implies", "\\DOTSB\\;\\Longrightarrow\\;"); -defineMacro("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;"); - -// AMSMath's automatic \dots, based on \mdots@@ macro. -const dotsByToken = { - ",": "\\dotsc", - "\\not": "\\dotsb", - // \keybin@ checks for the following: - "+": "\\dotsb", - "=": "\\dotsb", - "<": "\\dotsb", - ">": "\\dotsb", - "-": "\\dotsb", - "*": "\\dotsb", - ":": "\\dotsb", - // Symbols whose definition starts with \DOTSB: - "\\DOTSB": "\\dotsb", - "\\coprod": "\\dotsb", - "\\bigvee": "\\dotsb", - "\\bigwedge": "\\dotsb", - "\\biguplus": "\\dotsb", - "\\bigcap": "\\dotsb", - "\\bigcup": "\\dotsb", - "\\prod": "\\dotsb", - "\\sum": "\\dotsb", - "\\bigotimes": "\\dotsb", - "\\bigoplus": "\\dotsb", - "\\bigodot": "\\dotsb", - "\\bigsqcap": "\\dotsb", - "\\bigsqcup": "\\dotsb", - "\\And": "\\dotsb", - "\\longrightarrow": "\\dotsb", - "\\Longrightarrow": "\\dotsb", - "\\longleftarrow": "\\dotsb", - "\\Longleftarrow": "\\dotsb", - "\\longleftrightarrow": "\\dotsb", - "\\Longleftrightarrow": "\\dotsb", - "\\mapsto": "\\dotsb", - "\\longmapsto": "\\dotsb", - "\\hookrightarrow": "\\dotsb", - "\\doteq": "\\dotsb", - // Symbols whose definition starts with \mathbin: - "\\mathbin": "\\dotsb", - // Symbols whose definition starts with \mathrel: - "\\mathrel": "\\dotsb", - "\\relbar": "\\dotsb", - "\\Relbar": "\\dotsb", - "\\xrightarrow": "\\dotsb", - "\\xleftarrow": "\\dotsb", - // Symbols whose definition starts with \DOTSI: - "\\DOTSI": "\\dotsi", - "\\int": "\\dotsi", - "\\oint": "\\dotsi", - "\\iint": "\\dotsi", - "\\iiint": "\\dotsi", - "\\iiiint": "\\dotsi", - "\\idotsint": "\\dotsi", - // Symbols whose definition starts with \DOTSX: - "\\DOTSX": "\\dotsx" -}; - -defineMacro("\\dots", function(context) { - // TODO: If used in text mode, should expand to \textellipsis. - // However, in Temml, \textellipsis and \ldots behave the same - // (in text mode), and it's unlikely we'd see any of the math commands - // that affect the behavior of \dots when in text mode. So fine for now - // (until we support \ifmmode ... \else ... \fi). - let thedots = "\\dotso"; - const next = context.expandAfterFuture().text; - if (next in dotsByToken) { - thedots = dotsByToken[next]; - } else if (next.substr(0, 4) === "\\not") { - thedots = "\\dotsb"; - } else if (next in symbols.math) { - if (utils.contains(["bin", "rel"], symbols.math[next].group)) { - thedots = "\\dotsb"; - } - } - return thedots; -}); - -const spaceAfterDots = { - // \rightdelim@ checks for the following: - ")": true, - "]": true, - "\\rbrack": true, - "\\}": true, - "\\rbrace": true, - "\\rangle": true, - "\\rceil": true, - "\\rfloor": true, - "\\rgroup": true, - "\\rmoustache": true, - "\\right": true, - "\\bigr": true, - "\\biggr": true, - "\\Bigr": true, - "\\Biggr": true, - // \extra@ also tests for the following: - $: true, - // \extrap@ checks for the following: - ";": true, - ".": true, - ",": true -}; - -defineMacro("\\dotso", function(context) { - const next = context.future().text; - if (next in spaceAfterDots) { - return "\\ldots\\,"; - } else { - return "\\ldots"; - } -}); - -defineMacro("\\dotsc", function(context) { - const next = context.future().text; - // \dotsc uses \extra@ but not \extrap@, instead specially checking for - // ';' and '.', but doesn't check for ','. - if (next in spaceAfterDots && next !== ",") { - return "\\ldots\\,"; - } else { - return "\\ldots"; - } -}); - -defineMacro("\\cdots", function(context) { - const next = context.future().text; - if (next in spaceAfterDots) { - return "\\@cdots\\,"; - } else { - return "\\@cdots"; - } -}); - -defineMacro("\\dotsb", "\\cdots"); -defineMacro("\\dotsm", "\\cdots"); -defineMacro("\\dotsi", "\\!\\cdots"); -defineMacro("\\idotsint", "\\dotsi"); -// amsmath doesn't actually define \dotsx, but \dots followed by a macro -// starting with \DOTSX implies \dotso, and then \extra@ detects this case -// and forces the added `\,`. -defineMacro("\\dotsx", "\\ldots\\,"); - -// \let\DOTSI\relax -// \let\DOTSB\relax -// \let\DOTSX\relax -defineMacro("\\DOTSI", "\\relax"); -defineMacro("\\DOTSB", "\\relax"); -defineMacro("\\DOTSX", "\\relax"); - -// Spacing, based on amsmath.sty's override of LaTeX defaults -// \DeclareRobustCommand{\tmspace}[3]{% -// \ifmmode\mskip#1#2\else\kern#1#3\fi\relax} -defineMacro("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"); -// \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}} -// TODO: math mode should use \thinmuskip -defineMacro("\\,", "\\tmspace+{3mu}{.1667em}"); -// \let\thinspace\, -defineMacro("\\thinspace", "\\,"); -// \def\>{\mskip\medmuskip} -// \renewcommand{\:}{\tmspace+\medmuskip{.2222em}} -// TODO: \> and math mode of \: should use \medmuskip = 4mu plus 2mu minus 4mu -defineMacro("\\>", "\\mskip{4mu}"); -defineMacro("\\:", "\\tmspace+{4mu}{.2222em}"); -// \let\medspace\: -defineMacro("\\medspace", "\\:"); -// \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}} -// TODO: math mode should use \thickmuskip = 5mu plus 5mu -defineMacro("\\;", "\\tmspace+{5mu}{.2777em}"); -// \let\thickspace\; -defineMacro("\\thickspace", "\\;"); -// \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}} -// TODO: math mode should use \thinmuskip -defineMacro("\\!", "\\tmspace-{3mu}{.1667em}"); -// \let\negthinspace\! -defineMacro("\\negthinspace", "\\!"); -// \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}} -// TODO: math mode should use \medmuskip -defineMacro("\\negmedspace", "\\tmspace-{4mu}{.2222em}"); -// \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}} -// TODO: math mode should use \thickmuskip -defineMacro("\\negthickspace", "\\tmspace-{5mu}{.277em}"); -// \def\enspace{\kern.5em } -defineMacro("\\enspace", "\\kern.5em "); -// \def\enskip{\hskip.5em\relax} -defineMacro("\\enskip", "\\hskip.5em\\relax"); -// \def\quad{\hskip1em\relax} -defineMacro("\\quad", "\\hskip1em\\relax"); -// \def\qquad{\hskip2em\relax} -defineMacro("\\qquad", "\\hskip2em\\relax"); - -// \tag@in@display form of \tag -defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren"); -defineMacro("\\tag@paren", "\\tag@literal{({#1})}"); -defineMacro("\\tag@literal", (context) => { - if (context.macros.get("\\df@tag")) { - throw new ParseError("Multiple \\tag"); - } - return "\\def\\df@tag{\\text{#1}}"; -}); - -// \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin -// {\operator@font mod}\penalty900 -// \mkern5mu\nonscript\mskip-\medmuskip} -// \newcommand{\pod}[1]{\allowbreak -// \if@display\mkern18mu\else\mkern8mu\fi(#1)} -// \renewcommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}} -// \newcommand{\mod}[1]{\allowbreak\if@display\mkern18mu -// \else\mkern12mu\fi{\operator@font mod}\,\,#1} -// TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu -defineMacro("\\bmod", "\\mathbin{\\text{mod}}"); -defineMacro( - "\\pod", - "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)" -); -defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}"); -defineMacro( - "\\mod", - "\\allowbreak" + - "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + - "{\\rm mod}\\,\\,#1" -); - -////////////////////////////////////////////////////////////////////// -// LaTeX source2e - -// \expandafter\let\expandafter\@normalcr -// \csname\expandafter\@gobble\string\\ \endcsname -// \DeclareRobustCommand\newline{\@normalcr\relax} -defineMacro("\\newline", "\\\\\\relax"); - -// \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@} -// TODO: Doesn't normally work in math mode because \@ fails. -defineMacro("\\TeX", "\\textrm{T}\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125em\\textrm{X}"); - -defineMacro( - "\\LaTeX", - "\\textrm{L}\\kern-.35em\\raisebox{0.2em}{\\scriptstyle A}\\kern-.15em\\TeX" -); - -defineMacro( - "\\Temml", - // eslint-disable-next-line max-len - "\\textrm{T}\\kern-0.2em\\lower{0.2em}\\textrm{E}\\kern-0.08em{\\textrm{M}\\kern-0.08em\\raise{0.2em}\\textrm{M}\\kern-0.08em\\textrm{L}}" -); - -// \DeclareRobustCommand\hspace{\@ifstar\@hspacer\@hspace} -// \def\@hspace#1{\hskip #1\relax} -// \def\@hspacer#1{\vrule \@width\z@\nobreak -// \hskip #1\hskip \z@skip} -defineMacro("\\hspace", "\\@ifstar\\@hspacer\\@hspace"); -defineMacro("\\@hspace", "\\hskip #1\\relax"); -defineMacro("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax"); - -////////////////////////////////////////////////////////////////////// -// mathtools.sty - -defineMacro("\\prescript", "\\pres@cript{_{#1}^{#2}}{}{#3}"); - -//\providecommand\ordinarycolon{:} -defineMacro("\\ordinarycolon", ":"); -//\def\vcentcolon{\mathrel{\mathop\ordinarycolon}} -//TODO(edemaine): Not yet centered. Fix via \raisebox or #726 -defineMacro("\\vcentcolon", "\\mathrel{\\mathrel\\ordinarycolon}"); -// \providecommand*\coloneq{\vcentcolon\mathrel{\mkern-1.2mu}\mathrel{-}} -defineMacro("\\coloneq", '\\mathrel{\\char"3a\\char"2212}'); -// \providecommand*\Coloneq{\dblcolon\mathrel{\mkern-1.2mu}\mathrel{-}} -defineMacro("\\Coloneq", '\\mathrel{\\char"2237\\char"2212}'); -// \providecommand*\Eqqcolon{=\mathrel{\mkern-1.2mu}\dblcolon} -defineMacro("\\Eqqcolon", '\\mathrel{\\char"3d\\char"2237}'); -// \providecommand*\Eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\dblcolon} -defineMacro("\\Eqcolon", '\\mathrel{\\char"2212\\char"2237}'); -// \providecommand*\colonapprox{\vcentcolon\mathrel{\mkern-1.2mu}\approx} -defineMacro("\\colonapprox", '\\mathrel{\\char"3a\\char"2248}'); -// \providecommand*\Colonapprox{\dblcolon\mathrel{\mkern-1.2mu}\approx} -defineMacro("\\Colonapprox", '\\mathrel{\\char"2237\\char"2248}'); -// \providecommand*\colonsim{\vcentcolon\mathrel{\mkern-1.2mu}\sim} -defineMacro("\\colonsim", '\\mathrel{\\char"3a\\char"223c}'); -// \providecommand*\Colonsim{\dblcolon\mathrel{\mkern-1.2mu}\sim} -defineMacro("\\Colonsim", '\\mathrel{\\char"2237\\char"223c}'); - -////////////////////////////////////////////////////////////////////// -// colonequals.sty - -// Alternate names for mathtools's macros: -defineMacro("\\ratio", "\\vcentcolon"); -defineMacro("\\coloncolon", "\\dblcolon"); -defineMacro("\\colonequals", "\\coloneqq"); -defineMacro("\\coloncolonequals", "\\Coloneqq"); -defineMacro("\\equalscolon", "\\eqqcolon"); -defineMacro("\\equalscoloncolon", "\\Eqqcolon"); -defineMacro("\\colonminus", "\\coloneq"); -defineMacro("\\coloncolonminus", "\\Coloneq"); -defineMacro("\\minuscolon", "\\eqcolon"); -defineMacro("\\minuscoloncolon", "\\Eqcolon"); -// \colonapprox name is same in mathtools and colonequals. -defineMacro("\\coloncolonapprox", "\\Colonapprox"); -// \colonsim name is same in mathtools and colonequals. -defineMacro("\\coloncolonsim", "\\Colonsim"); - -// Present in newtxmath, pxfonts and txfonts -defineMacro("\\notni", "\\mathrel{\\char`\u220C}"); -defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}"); -defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}"); - -////////////////////////////////////////////////////////////////////// -// From amsopn.sty -defineMacro("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}"); -defineMacro("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}"); -defineMacro("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{\\text{lim}}}"); -defineMacro("\\varliminf", "\\DOTSB\\operatorname*{\\underline{\\text{lim}}}"); -defineMacro("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{\\text{lim}}}"); -defineMacro("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{\\text{lim}}}"); - - -////////////////////////////////////////////////////////////////////// -// statmath.sty -// https://ctan.math.illinois.edu/macros/latex/contrib/statmath/statmath.pdf - -defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}"); -defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}"); -defineMacro("\\plim", "\\DOTSB\\operatorname*{plim}"); - -////////////////////////////////////////////////////////////////////// -// braket.sty -// http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf - -defineMacro("\\bra", "\\mathinner{\\langle{#1}|}"); -defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}"); -defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}"); -defineMacro("\\Bra", "\\left\\langle#1\\right|"); -defineMacro("\\Ket", "\\left|#1\\right\\rangle"); -const braketHelper = (one) => (context) => { - const left = context.consumeArg().tokens; - const middle = context.consumeArg().tokens; - const middleDouble = context.consumeArg().tokens; - const right = context.consumeArg().tokens; - const oldMiddle = context.macros.get("|"); - const oldMiddleDouble = context.macros.get("\\|"); - context.macros.beginGroup(); - const midMacro = (double) => (context) => { - if (one) { - // Only modify the first instance of | or \| - context.macros.set("|", oldMiddle); - if (middleDouble.length) { - context.macros.set("\\|", oldMiddleDouble); - } - } - let doubled = double; - if (!double && middleDouble.length) { - // Mimic \@ifnextchar - const nextToken = context.future(); - if (nextToken.text === "|") { - context.popToken(); - doubled = true; - } - } - return { - tokens: doubled ? middleDouble : middle, - numArgs: 0 - }; - }; - context.macros.set("|", midMacro(false)); - if (middleDouble.length) { - context.macros.set("\\|", midMacro(true)); - } - const arg = context.consumeArg().tokens; - const expanded = context.expandTokens([...right, ...arg, ...left]); // reversed - context.macros.endGroup(); - return { - tokens: expanded.reverse(), - numArgs: 0 - }; -}; -defineMacro("\\bra@ket", braketHelper(false)); -defineMacro("\\bra@set", braketHelper(true)); -defineMacro("\\Braket", "\\bra@ket{\\left\\langle}" + - "{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"); -defineMacro("\\Set", "\\bra@set{\\left\\{\\:}" + - "{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"); -defineMacro("\\set", "\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"); - // has no support for special || or \| - -////////////////////////////////////////////////////////////////////// -// actuarialangle.dtx -defineMacro("\\angln", "{\\angl n}"); - -////////////////////////////////////////////////////////////////////// -// derivative.sty -defineMacro("\\odv", "\\@ifstar\\odv@next\\odv@numerator"); -defineMacro("\\odv@numerator", "\\frac{\\mathrm{d}#1}{\\mathrm{d}#2}"); -defineMacro("\\odv@next", "\\frac{\\mathrm{d}}{\\mathrm{d}#2}#1"); -defineMacro("\\pdv", "\\@ifstar\\pdv@next\\pdv@numerator"); - -const pdvHelper = args => { - const numerator = args[0][0].text; - const denoms = stringFromArg(args[1]).split(","); - const power = String(denoms.length); - const numOp = power === "1" ? "\\partial" : `\\partial^${power}`; - let denominator = ""; - denoms.map(e => { denominator += "\\partial " + e.trim() + "\\,";}); - return [numerator, numOp, denominator.replace(/\\,$/, "")] -}; -defineMacro("\\pdv@numerator", function(context) { - const [numerator, numOp, denominator] = pdvHelper(context.consumeArgs(2)); - return `\\frac{${numOp} ${numerator}}{${denominator}}` -}); -defineMacro("\\pdv@next", function(context) { - const [numerator, numOp, denominator] = pdvHelper(context.consumeArgs(2)); - return `\\frac{${numOp}}{${denominator}} ${numerator}` -}); - -////////////////////////////////////////////////////////////////////// -// upgreek.dtx -defineMacro("\\upalpha", "\\up@greek{\\alpha}"); -defineMacro("\\upbeta", "\\up@greek{\\beta}"); -defineMacro("\\upgamma", "\\up@greek{\\gamma}"); -defineMacro("\\updelta", "\\up@greek{\\delta}"); -defineMacro("\\upepsilon", "\\up@greek{\\epsilon}"); -defineMacro("\\upzeta", "\\up@greek{\\zeta}"); -defineMacro("\\upeta", "\\up@greek{\\eta}"); -defineMacro("\\uptheta", "\\up@greek{\\theta}"); -defineMacro("\\upiota", "\\up@greek{\\iota}"); -defineMacro("\\upkappa", "\\up@greek{\\kappa}"); -defineMacro("\\uplambda", "\\up@greek{\\lambda}"); -defineMacro("\\upmu", "\\up@greek{\\mu}"); -defineMacro("\\upnu", "\\up@greek{\\nu}"); -defineMacro("\\upxi", "\\up@greek{\\xi}"); -defineMacro("\\upomicron", "\\up@greek{\\omicron}"); -defineMacro("\\uppi", "\\up@greek{\\pi}"); -defineMacro("\\upalpha", "\\up@greek{\\alpha}"); -defineMacro("\\uprho", "\\up@greek{\\rho}"); -defineMacro("\\upsigma", "\\up@greek{\\sigma}"); -defineMacro("\\uptau", "\\up@greek{\\tau}"); -defineMacro("\\upupsilon", "\\up@greek{\\upsilon}"); -defineMacro("\\upphi", "\\up@greek{\\phi}"); -defineMacro("\\upchi", "\\up@greek{\\chi}"); -defineMacro("\\uppsi", "\\up@greek{\\psi}"); -defineMacro("\\upomega", "\\up@greek{\\omega}"); - -////////////////////////////////////////////////////////////////////// -// chemstyle package -defineMacro("\\standardstate", "{\\tiny\\char`⦵}"); - -/* eslint-disable */ -/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ -/* vim: set ts=2 et sw=2 tw=80: */ - -/************************************************************* - * - * Temml mhchem.js - * - * This file implements a Temml version of mhchem version 3.3.0. - * It is adapted from MathJax/extensions/TeX/mhchem.js - * It differs from the MathJax version as follows: - * 1. The interface is changed so that it can be called from Temml, not MathJax. - * 2. \rlap and \llap are replaced with \mathrlap and \mathllap. - * 3. The reaction arrow code is simplified. All reaction arrows are rendered - * using Temml extensible arrows instead of building non-extensible arrows. - * 4. SVG path geometry is supplied for \equilibriumRight & \equilibriumLeft. - * 5. \tripledash uses Unicode character U+2504, ┄. - * 6. Two dashes in _getBond are wrapped in braces to suppress spacing. i.e., {-} - * 7. The electron dot uses \textbullet instead of \bullet. - * - * This code, as other Temml code, is released under the MIT license. - * - * /************************************************************* - * - * MathJax/extensions/TeX/mhchem.js - * - * Implements the \ce command for handling chemical formulas - * from the mhchem LaTeX package. - * - * --------------------------------------------------------------------- - * - * Copyright (c) 2011-2015 The MathJax Consortium - * Copyright (c) 2015-2018 Martin Hensel - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Coding Style -// - use '' for identifiers that can by minified/uglified -// - use "" for strings that need to stay untouched - -// version: "3.3.0" for MathJax and Temml - - -// Add \ce, \pu, and \tripledash to the Temml macros. - -defineMacro("\\ce", function(context) { - return chemParse(context.consumeArgs(1)[0], "ce") -}); - -defineMacro("\\pu", function(context) { - return chemParse(context.consumeArgs(1)[0], "pu"); -}); - -// Needed for \bond for the ~ forms -// Raise by 2.56mu, not 2mu. We're raising a hyphen-minus, U+002D, not -// a mathematical minus, U+2212. So we need that extra 0.56. -defineMacro("\\tripledash", '\\mathord{\\kern2mu\\raise{0.5mu}{\\char"2504}\\kern2mu}'); - -// Use the Temml macro system to send SVG path geometry for equilibrium arrows. -defineMacro("longRightleftharpoonsLeft", `M507,435c-4,4,-6.3,8.7,-7,14 -c0,5.3,0.7,9,2,11c1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17 -c2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21 -c-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40 -c-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z -M0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z`) -defineMacro("longRightleftharpoonsRight", `M0,241 l0,40c399126,0,399993,0,399993,0 -c4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199, --231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6 -c-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z -M0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z`) -defineMacro("longLeftrightharpoonsLeft", `M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11 -c1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9, -1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7, --152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z -M93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z`) -defineMacro("longLeftrightharpoonsRight", `M53,241l0,40c398570,0,399437,0,399437,0 -c4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199, --231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6 -c-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z -M500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z`) - - -const path = { - "\\equilibriumRight" : { - left: `M507,435c-4,4,-6.3,8.7,-7,14 -c0,5.3,0.7,9,2,11c1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17 -c2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21 -c-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40 -c-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z -M0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z`, - right: `M0,241 l0,40c399126,0,399993,0,399993,0 -c4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199, --231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6 -c-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z -M0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z` - }, - "\\equilibriumLeft": { - left: `M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11 -c1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9, -1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7, --152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z -M93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z`, - right: `M53,241l0,40c398570,0,399437,0,399437,0 -c4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199, --231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6 -c-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z -M500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z` - } -} - -const svg = (name, end) => { - const svg = { - type: "svg", - attributes: { - xmlns: "http://www.w3.org/2000/svg", - width: "400em", - height: "0.716em", - viewBox: "0 0 400000 716", - preserveAspectRatio: `x${end === "left" ? "Min" : "Max"}yMin slice`, - fill: "currrentColor", - "fill-rule": "non-zero", - "fill-opacity" : 1 - }, - style: { position: "absolute" }, - children: [{ - type: "path", - attributes: { d: path[name][end], stroke: "none" }, - children: [] - }] - } - if (end === "left") { svg.style.left = 0 } else { svg.style.right = 0 } - return svg -} - -const endSpan = (name, end) => { - const span = { - type: "span", - attributes: {}, - style: { position: "absolute", width: "50.2%", height: "0.716em", overflow: "hidden" }, - children: [svg(name, end)] - } - if (end === "left") { span.style.left = 0 } else { span.style.right = 0 } - return span -} - -const arrowNode = name => { - return JSON.stringify({ - type: "span", - attributes: {}, - style: { display: "block", position: "relative", width: "100%", height: "0.716em", "min-width": "1.75em" }, - children: [endSpan(name, "left"), endSpan(name, "right")] - }) -} - -defineMacro("\\@equilibriumRight", arrowNode("\\equilibriumRight")) -defineMacro("\\@equilibriumLeft", arrowNode("\\equilibriumLeft")) - - // - // This is the main function for handing the \ce and \pu commands. - // It takes the argument to \ce or \pu and returns the corresponding TeX string. - // - - var chemParse = function (tokens, stateMachine) { - // Recreate the argument string from Temml's array of tokens. - var str = ""; - var expectedLoc = tokens[tokens.length - 1].loc.start - for (var i = tokens.length - 1; i >= 0; i--) { - if(tokens[i].loc.start > expectedLoc) { - // context.consumeArgs has eaten a space. - str += " "; - expectedLoc = tokens[i].loc.start; - } - str += tokens[i].text; - expectedLoc += tokens[i].text.length; - } - // Call the mhchem core parser. - var tex = texify.go(mhchemParser.go(str, stateMachine)); - return tex; - }; - - // - // Core parser for mhchem syntax (recursive) - // - /** @type {MhchemParser} */ - var mhchemParser = { - // - // Parses mchem \ce syntax - // - // Call like - // go("H2O"); - // - go: function (input, stateMachine) { - if (!input) { return []; } - if (stateMachine === undefined) { stateMachine = 'ce'; } - var state = '0'; - - // - // String buffers for parsing: - // - // buffer.a == amount - // buffer.o == element - // buffer.b == left-side superscript - // buffer.p == left-side subscript - // buffer.q == right-side subscript - // buffer.d == right-side superscript - // - // buffer.r == arrow - // buffer.rdt == arrow, script above, type - // buffer.rd == arrow, script above, content - // buffer.rqt == arrow, script below, type - // buffer.rq == arrow, script below, content - // - // buffer.text_ - // buffer.rm - // etc. - // - // buffer.parenthesisLevel == int, starting at 0 - // buffer.sb == bool, space before - // buffer.beginsWithBond == bool - // - // These letters are also used as state names. - // - // Other states: - // 0 == begin of main part (arrow/operator unlikely) - // 1 == next entity - // 2 == next entity (arrow/operator unlikely) - // 3 == next atom - // c == macro - // - /** @type {Buffer} */ - var buffer = {}; - buffer['parenthesisLevel'] = 0; - - input = input.replace(/\n/g, " "); - input = input.replace(/[\u2212\u2013\u2014\u2010]/g, "-"); - input = input.replace(/[\u2026]/g, "..."); - - // - // Looks through mhchemParser.transitions, to execute a matching action - // (recursive) - // - var lastInput; - var watchdog = 10; - /** @type {ParserOutput[]} */ - var output = []; - while (true) { - if (lastInput !== input) { - watchdog = 10; - lastInput = input; - } else { - watchdog--; - } - // - // Find actions in transition table - // - var machine = mhchemParser.stateMachines[stateMachine]; - var t = machine.transitions[state] || machine.transitions['*']; - iterateTransitions: - for (var i=0; i 0) { - if (!task.revisit) { - input = matches.remainder; - } - if (!task.toContinue) { - break iterateTransitions; - } - } else { - return output; - } - } - } - // - // Prevent infinite loop - // - if (watchdog <= 0) { - throw ["MhchemBugU", "mhchem bug U. Please report."]; // Unexpected character - } - } - }, - concatArray: function (a, b) { - if (b) { - if (Array.isArray(b)) { - for (var iB=0; iB': /^[=<>]/, - '#': /^[#\u2261]/, - '+': /^\+/, - '-$': /^-(?=[\s_},;\]/]|$|\([a-z]+\))/, // -space -, -; -] -/ -$ -state-of-aggregation - '-9': /^-(?=[0-9])/, - '- orbital overlap': /^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/, - '-': /^-/, - 'pm-operator': /^(?:\\pm|\$\\pm\$|\+-|\+\/-)/, - 'operator': /^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/, - 'arrowUpDown': /^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/, - '\\bond{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\bond{", "", "", "}"); }, - '->': /^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/, - 'CMT': /^[CMT](?=\[)/, - '[(...)]': function (input) { return mhchemParser.patterns.findObserveGroups(input, "[", "", "", "]"); }, - '1st-level escape': /^(&|\\\\|\\hline)\s*/, - '\\,': /^(?:\\[,\ ;:])/, // \\x - but output no space before - '\\x{}{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); }, - '\\x{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", ""); }, - '\\ca': /^\\ca(?:\s+|(?![a-zA-Z]))/, - '\\x': /^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/, - 'orbital': /^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/, // only those with numbers in front, because the others will be formatted correctly anyway - 'others': /^[\/~|]/, - '\\frac{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\frac{", "", "", "}", "{", "", "", "}"); }, - '\\overset{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\overset{", "", "", "}", "{", "", "", "}"); }, - '\\underset{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\underset{", "", "", "}", "{", "", "", "}"); }, - '\\underbrace{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\underbrace{", "", "", "}_", "{", "", "", "}"); }, - '\\color{(...)}0': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}"); }, - '\\color{(...)}{(...)}1': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}", "{", "", "", "}"); }, - '\\color(...){(...)}2': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color", "\\", "", /^(?=\{)/, "{", "", "", "}"); }, - '\\ce{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\ce{", "", "", "}"); }, - 'oxidation$': /^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, - 'd-oxidation$': /^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, // 0 could be oxidation or charge - 'roman numeral': /^[IVX]+/, - '1/2$': /^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/, - 'amount': function (input) { - var match; - // e.g. 2, 0.5, 1/2, -2, n/2, +; $a$ could be added later in parsing - match = input.match(/^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/); - if (match) { - return { match_: match[0], remainder: input.substr(match[0].length) }; - } - var a = mhchemParser.patterns.findObserveGroups(input, "", "$", "$", ""); - if (a) { // e.g. $2n-1$, $-$ - match = a.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/); - if (match) { - return { match_: match[0], remainder: input.substr(match[0].length) }; - } - } - return null; - }, - 'amount2': function (input) { return this['amount'](input); }, - '(KV letters),': /^(?:[A-Z][a-z]{0,2}|i)(?=,)/, - 'formula$': function (input) { - if (input.match(/^\([a-z]+\)$/)) { return null; } // state of aggregation = no formula - var match = input.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/); - if (match) { - return { match_: match[0], remainder: input.substr(match[0].length) }; - } - return null; - }, - 'uprightEntities': /^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/, - '/': /^\s*(\/)\s*/, - '//': /^\s*(\/\/)\s*/, - '*': /^\s*[*.]\s*/ - }, - findObserveGroups: function (input, begExcl, begIncl, endIncl, endExcl, beg2Excl, beg2Incl, end2Incl, end2Excl, combine) { - /** @type {{(input: string, pattern: string | RegExp): string | string[] | null;}} */ - var _match = function (input, pattern) { - if (typeof pattern === "string") { - if (input.indexOf(pattern) !== 0) { return null; } - return pattern; - } else { - var match = input.match(pattern); - if (!match) { return null; } - return match[0]; - } - }; - /** @type {{(input: string, i: number, endChars: string | RegExp): {endMatchBegin: number, endMatchEnd: number} | null;}} */ - var _findObserveGroups = function (input, i, endChars) { - var braces = 0; - while (i < input.length) { - var a = input.charAt(i); - var match = _match(input.substr(i), endChars); - if (match !== null && braces === 0) { - return { endMatchBegin: i, endMatchEnd: i + match.length }; - } else if (a === "{") { - braces++; - } else if (a === "}") { - if (braces === 0) { - throw ["ExtraCloseMissingOpen", "Extra close brace or missing open brace"]; - } else { - braces--; - } - } - i++; - } - if (braces > 0) { - return null; - } - return null; - }; - var match = _match(input, begExcl); - if (match === null) { return null; } - input = input.substr(match.length); - match = _match(input, begIncl); - if (match === null) { return null; } - var e = _findObserveGroups(input, match.length, endIncl || endExcl); - if (e === null) { return null; } - var match1 = input.substring(0, (endIncl ? e.endMatchEnd : e.endMatchBegin)); - if (!(beg2Excl || beg2Incl)) { - return { - match_: match1, - remainder: input.substr(e.endMatchEnd) - }; - } else { - var group2 = this.findObserveGroups(input.substr(e.endMatchEnd), beg2Excl, beg2Incl, end2Incl, end2Excl); - if (group2 === null) { return null; } - /** @type {string[]} */ - var matchRet = [match1, group2.match_]; - return { - match_: (combine ? matchRet.join("") : matchRet), - remainder: group2.remainder - }; - } - }, - - // - // Matching function - // e.g. match("a", input) will look for the regexp called "a" and see if it matches - // returns null or {match_:"a", remainder:"bc"} - // - match_: function (m, input) { - var pattern = mhchemParser.patterns.patterns[m]; - if (pattern === undefined) { - throw ["MhchemBugP", "mhchem bug P. Please report. (" + m + ")"]; // Trying to use non-existing pattern - } else if (typeof pattern === "function") { - return mhchemParser.patterns.patterns[m](input); // cannot use cached var pattern here, because some pattern functions need this===mhchemParser - } else { // RegExp - var match = input.match(pattern); - if (match) { - var mm; - if (match[2]) { - mm = [ match[1], match[2] ]; - } else if (match[1]) { - mm = match[1]; - } else { - mm = match[0]; - } - return { match_: mm, remainder: input.substr(match[0].length) }; - } - return null; - } - } - }, - - // - // Generic state machine actions - // - actions: { - 'a=': function (buffer, m) { buffer.a = (buffer.a || "") + m; }, - 'b=': function (buffer, m) { buffer.b = (buffer.b || "") + m; }, - 'p=': function (buffer, m) { buffer.p = (buffer.p || "") + m; }, - 'o=': function (buffer, m) { buffer.o = (buffer.o || "") + m; }, - 'q=': function (buffer, m) { buffer.q = (buffer.q || "") + m; }, - 'd=': function (buffer, m) { buffer.d = (buffer.d || "") + m; }, - 'rm=': function (buffer, m) { buffer.rm = (buffer.rm || "") + m; }, - 'text=': function (buffer, m) { buffer.text_ = (buffer.text_ || "") + m; }, - 'insert': function (buffer, m, a) { return { type_: a }; }, - 'insert+p1': function (buffer, m, a) { return { type_: a, p1: m }; }, - 'insert+p1+p2': function (buffer, m, a) { return { type_: a, p1: m[0], p2: m[1] }; }, - 'copy': function (buffer, m) { return m; }, - 'rm': function (buffer, m) { return { type_: 'rm', p1: m || ""}; }, - 'text': function (buffer, m) { return mhchemParser.go(m, 'text'); }, - '{text}': function (buffer, m) { - var ret = [ "{" ]; - mhchemParser.concatArray(ret, mhchemParser.go(m, 'text')); - ret.push("}"); - return ret; - }, - 'tex-math': function (buffer, m) { return mhchemParser.go(m, 'tex-math'); }, - 'tex-math tight': function (buffer, m) { return mhchemParser.go(m, 'tex-math tight'); }, - 'bond': function (buffer, m, k) { return { type_: 'bond', kind_: k || m }; }, - 'color0-output': function (buffer, m) { return { type_: 'color0', color: m[0] }; }, - 'ce': function (buffer, m) { return mhchemParser.go(m); }, - '1/2': function (buffer, m) { - /** @type {ParserOutput[]} */ - var ret = []; - if (m.match(/^[+\-]/)) { - ret.push(m.substr(0, 1)); - m = m.substr(1); - } - var n = m.match(/^([0-9]+|\$[a-z]\$|[a-z])\/([0-9]+)(\$[a-z]\$|[a-z])?$/); - n[1] = n[1].replace(/\$/g, ""); - ret.push({ type_: 'frac', p1: n[1], p2: n[2] }); - if (n[3]) { - n[3] = n[3].replace(/\$/g, ""); - ret.push({ type_: 'tex-math', p1: n[3] }); - } - return ret; - }, - '9,9': function (buffer, m) { return mhchemParser.go(m, '9,9'); } - }, - // - // createTransitions - // convert { 'letter': { 'state': { action_: 'output' } } } to { 'state' => [ { pattern: 'letter', task: { action_: [{type_: 'output'}] } } ] } - // with expansion of 'a|b' to 'a' and 'b' (at 2 places) - // - createTransitions: function (o) { - var pattern, state; - /** @type {string[]} */ - var stateArray; - var i; - // - // 1. Collect all states - // - /** @type {Transitions} */ - var transitions = {}; - for (pattern in o) { - for (state in o[pattern]) { - stateArray = state.split("|"); - o[pattern][state].stateArray = stateArray; - for (i=0; i': { - '0|1|2|3': { action_: 'r=', nextState: 'r' }, - 'a|as': { action_: [ 'output', 'r=' ], nextState: 'r' }, - '*': { action_: [ 'output', 'r=' ], nextState: 'r' } }, - '+': { - 'o': { action_: 'd= kv', nextState: 'd' }, - 'd|D': { action_: 'd=', nextState: 'd' }, - 'q': { action_: 'd=', nextState: 'qd' }, - 'qd|qD': { action_: 'd=', nextState: 'qd' }, - 'dq': { action_: [ 'output', 'd=' ], nextState: 'd' }, - '3': { action_: [ 'sb=false', 'output', 'operator' ], nextState: '0' } }, - 'amount': { - '0|2': { action_: 'a=', nextState: 'a' } }, - 'pm-operator': { - '0|1|2|a|as': { action_: [ 'sb=false', 'output', { type_: 'operator', option: '\\pm' } ], nextState: '0' } }, - 'operator': { - '0|1|2|a|as': { action_: [ 'sb=false', 'output', 'operator' ], nextState: '0' } }, - '-$': { - 'o|q': { action_: [ 'charge or bond', 'output' ], nextState: 'qd' }, - 'd': { action_: 'd=', nextState: 'd' }, - 'D': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' }, - 'q': { action_: 'd=', nextState: 'qd' }, - 'qd': { action_: 'd=', nextState: 'qd' }, - 'qD|dq': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' } }, - '-9': { - '3|o': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '3' } }, - '- orbital overlap': { - 'o': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' }, - 'd': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' } }, - '-': { - '0|1|2': { action_: [ { type_: 'output', option: 1 }, 'beginsWithBond=true', { type_: 'bond', option: "-" } ], nextState: '3' }, - '3': { action_: { type_: 'bond', option: "-" } }, - 'a': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' }, - 'as': { action_: [ { type_: 'output', option: 2 }, { type_: 'bond', option: "-" } ], nextState: '3' }, - 'b': { action_: 'b=' }, - 'o': { action_: { type_: '- after o/d', option: false }, nextState: '2' }, - 'q': { action_: { type_: '- after o/d', option: false }, nextState: '2' }, - 'd|qd|dq': { action_: { type_: '- after o/d', option: true }, nextState: '2' }, - 'D|qD|p': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' } }, - 'amount2': { - '1|3': { action_: 'a=', nextState: 'a' } }, - 'letters': { - '0|1|2|3|a|as|b|p|bp|o': { action_: 'o=', nextState: 'o' }, - 'q|dq': { action_: ['output', 'o='], nextState: 'o' }, - 'd|D|qd|qD': { action_: 'o after d', nextState: 'o' } }, - 'digits': { - 'o': { action_: 'q=', nextState: 'q' }, - 'd|D': { action_: 'q=', nextState: 'dq' }, - 'q': { action_: [ 'output', 'o=' ], nextState: 'o' }, - 'a': { action_: 'o=', nextState: 'o' } }, - 'space A': { - 'b|p|bp': {} }, - 'space': { - 'a': { nextState: 'as' }, - '0': { action_: 'sb=false' }, - '1|2': { action_: 'sb=true' }, - 'r|rt|rd|rdt|rdq': { action_: 'output', nextState: '0' }, - '*': { action_: [ 'output', 'sb=true' ], nextState: '1'} }, - '1st-level escape': { - '1|2': { action_: [ 'output', { type_: 'insert+p1', option: '1st-level escape' } ] }, - '*': { action_: [ 'output', { type_: 'insert+p1', option: '1st-level escape' } ], nextState: '0' } }, - '[(...)]': { - 'r|rt': { action_: 'rd=', nextState: 'rd' }, - 'rd|rdt': { action_: 'rq=', nextState: 'rdq' } }, - '...': { - 'o|d|D|dq|qd|qD': { action_: [ 'output', { type_: 'bond', option: "..." } ], nextState: '3' }, - '*': { action_: [ { type_: 'output', option: 1 }, { type_: 'insert', option: 'ellipsis' } ], nextState: '1' } }, - '. |* ': { - '*': { action_: [ 'output', { type_: 'insert', option: 'addition compound' } ], nextState: '1' } }, - 'state of aggregation $': { - '*': { action_: [ 'output', 'state of aggregation' ], nextState: '1' } }, - '{[(': { - 'a|as|o': { action_: [ 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' }, - '0|1|2|3': { action_: [ 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' }, - '*': { action_: [ 'output', 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' } }, - ')]}': { - '0|1|2|3|b|p|bp|o': { action_: [ 'o=', 'parenthesisLevel--' ], nextState: 'o' }, - 'a|as|d|D|q|qd|qD|dq': { action_: [ 'output', 'o=', 'parenthesisLevel--' ], nextState: 'o' } }, - ', ': { - '*': { action_: [ 'output', 'comma' ], nextState: '0' } }, - '^_': { // ^ and _ without a sensible argument - '*': { } }, - '^{(...)}|^($...$)': { - '0|1|2|as': { action_: 'b=', nextState: 'b' }, - 'p': { action_: 'b=', nextState: 'bp' }, - '3|o': { action_: 'd= kv', nextState: 'D' }, - 'q': { action_: 'd=', nextState: 'qD' }, - 'd|D|qd|qD|dq': { action_: [ 'output', 'd=' ], nextState: 'D' } }, - '^a|^\\x{}{}|^\\x{}|^\\x|\'': { - '0|1|2|as': { action_: 'b=', nextState: 'b' }, - 'p': { action_: 'b=', nextState: 'bp' }, - '3|o': { action_: 'd= kv', nextState: 'd' }, - 'q': { action_: 'd=', nextState: 'qd' }, - 'd|qd|D|qD': { action_: 'd=' }, - 'dq': { action_: [ 'output', 'd=' ], nextState: 'd' } }, - '_{(state of aggregation)}$': { - 'd|D|q|qd|qD|dq': { action_: [ 'output', 'q=' ], nextState: 'q' } }, - '_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x': { - '0|1|2|as': { action_: 'p=', nextState: 'p' }, - 'b': { action_: 'p=', nextState: 'bp' }, - '3|o': { action_: 'q=', nextState: 'q' }, - 'd|D': { action_: 'q=', nextState: 'dq' }, - 'q|qd|qD|dq': { action_: [ 'output', 'q=' ], nextState: 'q' } }, - '=<>': { - '0|1|2|3|a|as|o|q|d|D|qd|qD|dq': { action_: [ { type_: 'output', option: 2 }, 'bond' ], nextState: '3' } }, - '#': { - '0|1|2|3|a|as|o': { action_: [ { type_: 'output', option: 2 }, { type_: 'bond', option: "#" } ], nextState: '3' } }, - '{}': { - '*': { action_: { type_: 'output', option: 1 }, nextState: '1' } }, - '{...}': { - '0|1|2|3|a|as|b|p|bp': { action_: 'o=', nextState: 'o' }, - 'o|d|D|q|qd|qD|dq': { action_: [ 'output', 'o=' ], nextState: 'o' } }, - '$...$': { - 'a': { action_: 'a=' }, // 2$n$ - '0|1|2|3|as|b|p|bp|o': { action_: 'o=', nextState: 'o' }, // not 'amount' - 'as|o': { action_: 'o=' }, - 'q|d|D|qd|qD|dq': { action_: [ 'output', 'o=' ], nextState: 'o' } }, - '\\bond{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'bond' ], nextState: "3" } }, - '\\frac{(...)}': { - '*': { action_: [ { type_: 'output', option: 1 }, 'frac-output' ], nextState: '3' } }, - '\\overset{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'overset-output' ], nextState: '3' } }, - '\\underset{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'underset-output' ], nextState: '3' } }, - '\\underbrace{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'underbrace-output' ], nextState: '3' } }, - '\\color{(...)}{(...)}1|\\color(...){(...)}2': { - '*': { action_: [ { type_: 'output', option: 2 }, 'color-output' ], nextState: '3' } }, - '\\color{(...)}0': { - '*': { action_: [ { type_: 'output', option: 2 }, 'color0-output' ] } }, - '\\ce{(...)}': { - '*': { action_: [ { type_: 'output', option: 2 }, 'ce' ], nextState: '3' } }, - '\\,': { - '*': { action_: [ { type_: 'output', option: 1 }, 'copy' ], nextState: '1' } }, - '\\x{}{}|\\x{}|\\x': { - '0|1|2|3|a|as|b|p|bp|o|c0': { action_: [ 'o=', 'output' ], nextState: '3' }, - '*': { action_: ['output', 'o=', 'output' ], nextState: '3' } }, - 'others': { - '*': { action_: [ { type_: 'output', option: 1 }, 'copy' ], nextState: '3' } }, - 'else2': { - 'a': { action_: 'a to o', nextState: 'o', revisit: true }, - 'as': { action_: [ 'output', 'sb=true' ], nextState: '1', revisit: true }, - 'r|rt|rd|rdt|rdq': { action_: [ 'output' ], nextState: '0', revisit: true }, - '*': { action_: [ 'output', 'copy' ], nextState: '3' } } - }), - actions: { - 'o after d': function (buffer, m) { - var ret; - if ((buffer.d || "").match(/^[0-9]+$/)) { - var tmp = buffer.d; - buffer.d = undefined; - ret = this['output'](buffer); - buffer.b = tmp; - } else { - ret = this['output'](buffer); - } - mhchemParser.actions['o='](buffer, m); - return ret; - }, - 'd= kv': function (buffer, m) { - buffer.d = m; - buffer.dType = 'kv'; - }, - 'charge or bond': function (buffer, m) { - if (buffer['beginsWithBond']) { - /** @type {ParserOutput[]} */ - var ret = []; - mhchemParser.concatArray(ret, this['output'](buffer)); - mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-")); - return ret; - } else { - buffer.d = m; - } - }, - '- after o/d': function (buffer, m, isAfterD) { - var c1 = mhchemParser.patterns.match_('orbital', buffer.o || ""); - var c2 = mhchemParser.patterns.match_('one lowercase greek letter $', buffer.o || ""); - var c3 = mhchemParser.patterns.match_('one lowercase latin letter $', buffer.o || ""); - var c4 = mhchemParser.patterns.match_('$one lowercase latin letter$ $', buffer.o || ""); - var hyphenFollows = m==="-" && ( c1 && c1.remainder==="" || c2 || c3 || c4 ); - if (hyphenFollows && !buffer.a && !buffer.b && !buffer.p && !buffer.d && !buffer.q && !c1 && c3) { - buffer.o = '$' + buffer.o + '$'; - } - /** @type {ParserOutput[]} */ - var ret = []; - if (hyphenFollows) { - mhchemParser.concatArray(ret, this['output'](buffer)); - ret.push({ type_: 'hyphen' }); - } else { - c1 = mhchemParser.patterns.match_('digits', buffer.d || ""); - if (isAfterD && c1 && c1.remainder==='') { - mhchemParser.concatArray(ret, mhchemParser.actions['d='](buffer, m)); - mhchemParser.concatArray(ret, this['output'](buffer)); - } else { - mhchemParser.concatArray(ret, this['output'](buffer)); - mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-")); - } - } - return ret; - }, - 'a to o': function (buffer) { - buffer.o = buffer.a; - buffer.a = undefined; - }, - 'sb=true': function (buffer) { buffer.sb = true; }, - 'sb=false': function (buffer) { buffer.sb = false; }, - 'beginsWithBond=true': function (buffer) { buffer['beginsWithBond'] = true; }, - 'beginsWithBond=false': function (buffer) { buffer['beginsWithBond'] = false; }, - 'parenthesisLevel++': function (buffer) { buffer['parenthesisLevel']++; }, - 'parenthesisLevel--': function (buffer) { buffer['parenthesisLevel']--; }, - 'state of aggregation': function (buffer, m) { - return { type_: 'state of aggregation', p1: mhchemParser.go(m, 'o') }; - }, - 'comma': function (buffer, m) { - var a = m.replace(/\s*$/, ''); - var withSpace = (a !== m); - if (withSpace && buffer['parenthesisLevel'] === 0) { - return { type_: 'comma enumeration L', p1: a }; - } else { - return { type_: 'comma enumeration M', p1: a }; - } - }, - 'output': function (buffer, m, entityFollows) { - // entityFollows: - // undefined = if we have nothing else to output, also ignore the just read space (buffer.sb) - // 1 = an entity follows, never omit the space if there was one just read before (can only apply to state 1) - // 2 = 1 + the entity can have an amount, so output a\, instead of converting it to o (can only apply to states a|as) - /** @type {ParserOutput | ParserOutput[]} */ - var ret; - if (!buffer.r) { - ret = []; - if (!buffer.a && !buffer.b && !buffer.p && !buffer.o && !buffer.q && !buffer.d && !entityFollows) { - //ret = []; - } else { - if (buffer.sb) { - ret.push({ type_: 'entitySkip' }); - } - if (!buffer.o && !buffer.q && !buffer.d && !buffer.b && !buffer.p && entityFollows!==2) { - buffer.o = buffer.a; - buffer.a = undefined; - } else if (!buffer.o && !buffer.q && !buffer.d && (buffer.b || buffer.p)) { - buffer.o = buffer.a; - buffer.d = buffer.b; - buffer.q = buffer.p; - buffer.a = buffer.b = buffer.p = undefined; - } else { - if (buffer.o && buffer.dType==='kv' && mhchemParser.patterns.match_('d-oxidation$', buffer.d || "")) { - buffer.dType = 'oxidation'; - } else if (buffer.o && buffer.dType==='kv' && !buffer.q) { - buffer.dType = undefined; - } - } - ret.push({ - type_: 'chemfive', - a: mhchemParser.go(buffer.a, 'a'), - b: mhchemParser.go(buffer.b, 'bd'), - p: mhchemParser.go(buffer.p, 'pq'), - o: mhchemParser.go(buffer.o, 'o'), - q: mhchemParser.go(buffer.q, 'pq'), - d: mhchemParser.go(buffer.d, (buffer.dType === 'oxidation' ? 'oxidation' : 'bd')), - dType: buffer.dType - }); - } - } else { // r - /** @type {ParserOutput[]} */ - var rd; - if (buffer.rdt === 'M') { - rd = mhchemParser.go(buffer.rd, 'tex-math'); - } else if (buffer.rdt === 'T') { - rd = [ { type_: 'text', p1: buffer.rd || "" } ]; - } else { - rd = mhchemParser.go(buffer.rd); - } - /** @type {ParserOutput[]} */ - var rq; - if (buffer.rqt === 'M') { - rq = mhchemParser.go(buffer.rq, 'tex-math'); - } else if (buffer.rqt === 'T') { - rq = [ { type_: 'text', p1: buffer.rq || ""} ]; - } else { - rq = mhchemParser.go(buffer.rq); - } - ret = { - type_: 'arrow', - r: buffer.r, - rd: rd, - rq: rq - }; - } - for (var p in buffer) { - if (p !== 'parenthesisLevel' && p !== 'beginsWithBond') { - delete buffer[p]; - } - } - return ret; - }, - 'oxidation-output': function (buffer, m) { - var ret = [ "{" ]; - mhchemParser.concatArray(ret, mhchemParser.go(m, 'oxidation')); - ret.push("}"); - return ret; - }, - 'frac-output': function (buffer, m) { - return { type_: 'frac-ce', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'overset-output': function (buffer, m) { - return { type_: 'overset', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'underset-output': function (buffer, m) { - return { type_: 'underset', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'underbrace-output': function (buffer, m) { - return { type_: 'underbrace', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; - }, - 'color-output': function (buffer, m) { - return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1]) }; - }, - 'r=': function (buffer, m) { buffer.r = m; }, - 'rdt=': function (buffer, m) { buffer.rdt = m; }, - 'rd=': function (buffer, m) { buffer.rd = m; }, - 'rqt=': function (buffer, m) { buffer.rqt = m; }, - 'rq=': function (buffer, m) { buffer.rq = m; }, - 'operator': function (buffer, m, p1) { return { type_: 'operator', kind_: (p1 || m) }; } - } - }, - 'a': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - '1/2$': { - '0': { action_: '1/2' } }, - 'else': { - '0': { nextState: '1', revisit: true } }, - '$(...)$': { - '*': { action_: 'tex-math tight', nextState: '1' } }, - ',': { - '*': { action_: { type_: 'insert', option: 'commaDecimal' } } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: {} - }, - 'o': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - '1/2$': { - '0': { action_: '1/2' } }, - 'else': { - '0': { nextState: '1', revisit: true } }, - 'letters': { - '*': { action_: 'rm' } }, - '\\ca': { - '*': { action_: { type_: 'insert', option: 'circa' } } }, - '\\x{}{}|\\x{}|\\x': { - '*': { action_: 'copy' } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '{(...)}': { - '*': { action_: '{text}' } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: {} - }, - 'text': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '{...}': { - '*': { action_: 'text=' } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '\\greek': { - '*': { action_: [ 'output', 'rm' ] } }, - '\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: [ 'output', 'copy' ] } }, - 'else': { - '*': { action_: 'text=' } } - }), - actions: { - 'output': function (buffer) { - if (buffer.text_) { - /** @type {ParserOutput} */ - var ret = { type_: 'text', p1: buffer.text_ }; - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - } - }, - 'pq': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - 'state of aggregation $': { - '*': { action_: 'state of aggregation' } }, - 'i$': { - '0': { nextState: '!f', revisit: true } }, - '(KV letters),': { - '0': { action_: 'rm', nextState: '0' } }, - 'formula$': { - '0': { nextState: 'f', revisit: true } }, - '1/2$': { - '0': { action_: '1/2' } }, - 'else': { - '0': { nextState: '!f', revisit: true } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '{(...)}': { - '*': { action_: 'text' } }, - 'a-z': { - 'f': { action_: 'tex-math' } }, - 'letters': { - '*': { action_: 'rm' } }, - '-9.,9': { - '*': { action_: '9,9' } }, - ',': { - '*': { action_: { type_: 'insert+p1', option: 'comma enumeration S' } } }, - '\\color{(...)}{(...)}1|\\color(...){(...)}2': { - '*': { action_: 'color-output' } }, - '\\color{(...)}0': { - '*': { action_: 'color0-output' } }, - '\\ce{(...)}': { - '*': { action_: 'ce' } }, - '\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'copy' } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: { - 'state of aggregation': function (buffer, m) { - return { type_: 'state of aggregation subscript', p1: mhchemParser.go(m, 'o') }; - }, - 'color-output': function (buffer, m) { - return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1], 'pq') }; - } - } - }, - 'bd': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - 'x$': { - '0': { nextState: '!f', revisit: true } }, - 'formula$': { - '0': { nextState: 'f', revisit: true } }, - 'else': { - '0': { nextState: '!f', revisit: true } }, - '-9.,9 no missing 0': { - '*': { action_: '9,9' } }, - '.': { - '*': { action_: { type_: 'insert', option: 'electron dot' } } }, - 'a-z': { - 'f': { action_: 'tex-math' } }, - 'x': { - '*': { action_: { type_: 'insert', option: 'KV x' } } }, - 'letters': { - '*': { action_: 'rm' } }, - '\'': { - '*': { action_: { type_: 'insert', option: 'prime' } } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - '{(...)}': { - '*': { action_: 'text' } }, - '\\color{(...)}{(...)}1|\\color(...){(...)}2': { - '*': { action_: 'color-output' } }, - '\\color{(...)}0': { - '*': { action_: 'color0-output' } }, - '\\ce{(...)}': { - '*': { action_: 'ce' } }, - '\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'copy' } }, - 'else2': { - '*': { action_: 'copy' } } - }), - actions: { - 'color-output': function (buffer, m) { - return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1], 'bd') }; - } - } - }, - 'oxidation': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - 'roman numeral': { - '*': { action_: 'roman-numeral' } }, - '${(...)}$|$(...)$': { - '*': { action_: 'tex-math' } }, - 'else': { - '*': { action_: 'copy' } } - }), - actions: { - 'roman-numeral': function (buffer, m) { return { type_: 'roman numeral', p1: m || "" }; } - } - }, - 'tex-math': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '\\ce{(...)}': { - '*': { action_: [ 'output', 'ce' ] } }, - '{...}|\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'o=' } }, - 'else': { - '*': { action_: 'o=' } } - }), - actions: { - 'output': function (buffer) { - if (buffer.o) { - /** @type {ParserOutput} */ - var ret = { type_: 'tex-math', p1: buffer.o }; - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - } - }, - 'tex-math tight': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '\\ce{(...)}': { - '*': { action_: [ 'output', 'ce' ] } }, - '{...}|\\,|\\x{}{}|\\x{}|\\x': { - '*': { action_: 'o=' } }, - '-|+': { - '*': { action_: 'tight operator' } }, - 'else': { - '*': { action_: 'o=' } } - }), - actions: { - 'tight operator': function (buffer, m) { buffer.o = (buffer.o || "") + "{"+m+"}"; }, - 'output': function (buffer) { - if (buffer.o) { - /** @type {ParserOutput} */ - var ret = { type_: 'tex-math', p1: buffer.o }; - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - } - }, - '9,9': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': {} }, - ',': { - '*': { action_: 'comma' } }, - 'else': { - '*': { action_: 'copy' } } - }), - actions: { - 'comma': function () { return { type_: 'commaDecimal' }; } - } - }, - //#endregion - // - // \pu state machines - // - //#region pu - 'pu': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - 'space$': { - '*': { action_: [ 'output', 'space' ] } }, - '{[(|)]}': { - '0|a': { action_: 'copy' } }, - '(-)(9)^(-9)': { - '0': { action_: 'number^', nextState: 'a' } }, - '(-)(9.,9)(e)(99)': { - '0': { action_: 'enumber', nextState: 'a' } }, - 'space': { - '0|a': {} }, - 'pm-operator': { - '0|a': { action_: { type_: 'operator', option: '\\pm' }, nextState: '0' } }, - 'operator': { - '0|a': { action_: 'copy', nextState: '0' } }, - '//': { - 'd': { action_: 'o=', nextState: '/' } }, - '/': { - 'd': { action_: 'o=', nextState: '/' } }, - '{...}|else': { - '0|d': { action_: 'd=', nextState: 'd' }, - 'a': { action_: [ 'space', 'd=' ], nextState: 'd' }, - '/|q': { action_: 'q=', nextState: 'q' } } - }), - actions: { - 'enumber': function (buffer, m) { - /** @type {ParserOutput[]} */ - var ret = []; - if (m[0] === "+-" || m[0] === "+/-") { - ret.push("\\pm "); - } else if (m[0]) { - ret.push(m[0]); - } - if (m[1]) { - mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9')); - if (m[2]) { - if (m[2].match(/[,.]/)) { - mhchemParser.concatArray(ret, mhchemParser.go(m[2], 'pu-9,9')); - } else { - ret.push(m[2]); - } - } - m[3] = m[4] || m[3]; - if (m[3]) { - m[3] = m[3].trim(); - if (m[3] === "e" || m[3].substr(0, 1) === "*") { - ret.push({ type_: 'cdot' }); - } else { - ret.push({ type_: 'times' }); - } - } - } - if (m[3]) { - ret.push("10^{"+m[5]+"}"); - } - return ret; - }, - 'number^': function (buffer, m) { - /** @type {ParserOutput[]} */ - var ret = []; - if (m[0] === "+-" || m[0] === "+/-") { - ret.push("\\pm "); - } else if (m[0]) { - ret.push(m[0]); - } - mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9')); - ret.push("^{"+m[2]+"}"); - return ret; - }, - 'operator': function (buffer, m, p1) { return { type_: 'operator', kind_: (p1 || m) }; }, - 'space': function () { return { type_: 'pu-space-1' }; }, - 'output': function (buffer) { - /** @type {ParserOutput | ParserOutput[]} */ - var ret; - var md = mhchemParser.patterns.match_('{(...)}', buffer.d || ""); - if (md && md.remainder === '') { buffer.d = md.match_; } - var mq = mhchemParser.patterns.match_('{(...)}', buffer.q || ""); - if (mq && mq.remainder === '') { buffer.q = mq.match_; } - if (buffer.d) { - buffer.d = buffer.d.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C"); - buffer.d = buffer.d.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F"); - } - if (buffer.q) { // fraction - buffer.q = buffer.q.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C"); - buffer.q = buffer.q.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F"); - var b5 = { - d: mhchemParser.go(buffer.d, 'pu'), - q: mhchemParser.go(buffer.q, 'pu') - }; - if (buffer.o === '//') { - ret = { type_: 'pu-frac', p1: b5.d, p2: b5.q }; - } else { - ret = b5.d; - if (b5.d.length > 1 || b5.q.length > 1) { - ret.push({ type_: ' / ' }); - } else { - ret.push({ type_: '/' }); - } - mhchemParser.concatArray(ret, b5.q); - } - } else { // no fraction - ret = mhchemParser.go(buffer.d, 'pu-2'); - } - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - }, - 'pu-2': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '*': { action_: 'output' } }, - '*': { - '*': { action_: [ 'output', 'cdot' ], nextState: '0' } }, - '\\x': { - '*': { action_: 'rm=' } }, - 'space': { - '*': { action_: [ 'output', 'space' ], nextState: '0' } }, - '^{(...)}|^(-1)': { - '1': { action_: '^(-1)' } }, - '-9.,9': { - '0': { action_: 'rm=', nextState: '0' }, - '1': { action_: '^(-1)', nextState: '0' } }, - '{...}|else': { - '*': { action_: 'rm=', nextState: '1' } } - }), - actions: { - 'cdot': function () { return { type_: 'tight cdot' }; }, - '^(-1)': function (buffer, m) { buffer.rm += "^{"+m+"}"; }, - 'space': function () { return { type_: 'pu-space-2' }; }, - 'output': function (buffer) { - /** @type {ParserOutput | ParserOutput[]} */ - var ret = []; - if (buffer.rm) { - var mrm = mhchemParser.patterns.match_('{(...)}', buffer.rm || ""); - if (mrm && mrm.remainder === '') { - ret = mhchemParser.go(mrm.match_, 'pu'); - } else { - ret = { type_: 'rm', p1: buffer.rm }; - } - } - for (var p in buffer) { delete buffer[p]; } - return ret; - } - } - }, - 'pu-9,9': { - transitions: mhchemParser.createTransitions({ - 'empty': { - '0': { action_: 'output-0' }, - 'o': { action_: 'output-o' } }, - ',': { - '0': { action_: [ 'output-0', 'comma' ], nextState: 'o' } }, - '.': { - '0': { action_: [ 'output-0', 'copy' ], nextState: 'o' } }, - 'else': { - '*': { action_: 'text=' } } - }), - actions: { - 'comma': function () { return { type_: 'commaDecimal' }; }, - 'output-0': function (buffer) { - /** @type {ParserOutput[]} */ - var ret = []; - buffer.text_ = buffer.text_ || ""; - if (buffer.text_.length > 4) { - var a = buffer.text_.length % 3; - if (a === 0) { a = 3; } - for (var i=buffer.text_.length-3; i>0; i-=3) { - ret.push(buffer.text_.substr(i, 3)); - ret.push({ type_: '1000 separator' }); - } - ret.push(buffer.text_.substr(0, a)); - ret.reverse(); - } else { - ret.push(buffer.text_); - } - for (var p in buffer) { delete buffer[p]; } - return ret; - }, - 'output-o': function (buffer) { - /** @type {ParserOutput[]} */ - var ret = []; - buffer.text_ = buffer.text_ || ""; - if (buffer.text_.length > 4) { - var a = buffer.text_.length - 3; - for (var i=0; i, so we change \vphantom{X} to {} - // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed. -// res += "{\\vphantom{X}}"; - res += "{{}}"; - res += "_{\\smash[t]{"+b5.q+"}}"; - } - } else { - if (b5.q) { - // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed. -// res += "{\\vphantom{X}}"; - res += "{{}}"; - res += "_{\\smash[t]{"+b5.q+"}}"; - } - if (b5.d) { - // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed. -// res += "{\\vphantom{X}}"; - res += "{{}}"; - res += "^{"+b5.d+"}"; - } - } - break; - case 'rm': - res = "\\mathrm{"+buf.p1+"}"; - break; - case 'text': - if (buf.p1.match(/[\^_]/)) { - buf.p1 = buf.p1.replace(" ", "~").replace("-", "\\text{-}"); - res = "\\mathrm{"+buf.p1+"}"; - } else { - res = "\\text{"+buf.p1+"}"; - } - break; - case 'roman numeral': - res = "\\mathrm{"+buf.p1+"}"; - break; - case 'state of aggregation': - res = "\\mskip2mu "+texify._goInner(buf.p1); - break; - case 'state of aggregation subscript': - res = "\\mskip1mu "+texify._goInner(buf.p1); - break; - case 'bond': - res = texify._getBond(buf.kind_); - if (!res) { - throw ["MhchemErrorBond", "mhchem Error. Unknown bond type (" + buf.kind_ + ")"]; - } - break; - case 'frac': - var c = "\\frac{" + buf.p1 + "}{" + buf.p2 + "}"; - res = "\\mathchoice{\\textstyle"+c+"}{"+c+"}{"+c+"}{"+c+"}"; - break; - case 'pu-frac': - var d = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - res = "\\mathchoice{\\textstyle"+d+"}{"+d+"}{"+d+"}{"+d+"}"; - break; - case 'tex-math': - res = buf.p1 + " "; - break; - case 'frac-ce': - res = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - break; - case 'overset': - res = "\\overset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - break; - case 'underset': - res = "\\underset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; - break; - case 'underbrace': - res = "\\underbrace{" + texify._goInner(buf.p1) + "}_{" + texify._goInner(buf.p2) + "}"; - break; - case 'color': - res = "{\\color{" + buf.color1 + "}{" + texify._goInner(buf.color2) + "}}"; - break; - case 'color0': - res = "\\color{" + buf.color + "}"; - break; - case 'arrow': - var b6 = { - rd: texify._goInner(buf.rd), - rq: texify._goInner(buf.rq) - }; - var arrow = texify._getArrow(buf.r); - if (b6.rq) { arrow += "[{\\rm " + b6.rq + "}]"; } - if (b6.rd) { - arrow += "{\\rm " + b6.rd + "}"; - } else { - arrow += "{}"; - } - res = arrow; - break; - case 'operator': - res = texify._getOperator(buf.kind_); - break; - case '1st-level escape': - res = buf.p1+" "; // &, \\\\, \\hlin - break; - case 'space': - res = " "; - break; - case 'entitySkip': - res = "~"; - break; - case 'pu-space-1': - res = "~"; - break; - case 'pu-space-2': - res = "\\mkern3mu "; - break; - case '1000 separator': - res = "\\mkern2mu "; - break; - case 'commaDecimal': - res = "{,}"; - break; - case 'comma enumeration L': - res = "{"+buf.p1+"}\\mkern6mu "; - break; - case 'comma enumeration M': - res = "{"+buf.p1+"}\\mkern3mu "; - break; - case 'comma enumeration S': - res = "{"+buf.p1+"}\\mkern1mu "; - break; - case 'hyphen': - res = "\\text{-}"; - break; - case 'addition compound': - res = "\\,{\\cdot}\\,"; - break; - case 'electron dot': - res = "\\mkern1mu \\text{\\textbullet}\\mkern1mu "; - break; - case 'KV x': - res = "{\\times}"; - break; - case 'prime': - res = "\\prime "; - break; - case 'cdot': - res = "\\cdot "; - break; - case 'tight cdot': - res = "\\mkern1mu{\\cdot}\\mkern1mu "; - break; - case 'times': - res = "\\times "; - break; - case 'circa': - res = "{\\sim}"; - break; - case '^': - res = "uparrow"; - break; - case 'v': - res = "downarrow"; - break; - case 'ellipsis': - res = "\\ldots "; - break; - case '/': - res = "/"; - break; - case ' / ': - res = "\\,/\\,"; - break; - default: - assertNever(buf); - throw ["MhchemBugT", "mhchem bug T. Please report."]; // Missing texify rule or unknown MhchemParser output - } - assertString(res); - return res; - }, - _getArrow: function (a) { - switch (a) { - case "->": return "\\yields"; - case "\u2192": return "\\yields"; - case "\u27F6": return "\\yields"; - case "<-": return "\\yieldsLeft"; - case "<->": return "\\mesomerism"; - case "<-->": return "\\yieldsLeftRight"; - case "<=>": return "\\equilibrium"; - case "\u21CC": return "\\equilibrium"; - case "<=>>": return "\\equilibriumRight"; - case "<<=>": return "\\equilibriumLeft"; - default: - assertNever(a); - throw ["MhchemBugT", "mhchem bug T. Please report."]; - } - }, - _getBond: function (a) { - switch (a) { - case "-": return "{-}"; - case "1": return "{-}"; - case "=": return "{=}"; - case "2": return "{=}"; - case "#": return "{\\equiv}"; - case "3": return "{\\equiv}"; - case "~": return "{\\tripledash}"; - case "~-": return "{\\mathrlap{\\raise{-.1em}{-}}\\raise{.1em}{\\tripledash}}"; - case "~=": return "{\\mathrlap{\\raise{-.2em}{-}}\\mathrlap{\\raise{.2em}{\\tripledash}}{-}}"; - case "~--": return "{\\mathrlap{\\raise{-.2em}{-}}\\mathrlap{\\raise{.2em}{\\tripledash}}{-}}"; - case "-~-": return "{\\mathrlap{\\raise{-.2em}{-}}\\mathrlap{\\raise{.2em}{-}}\\tripledash}"; - case "...": return "{{\\cdot}{\\cdot}{\\cdot}}"; - case "....": return "{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}"; - case "->": return "{\\rightarrow}"; - case "<-": return "{\\leftarrow}"; - case "<": return "{<}"; - case ">": return "{>}"; - default: - assertNever(a); - throw ["MhchemBugT", "mhchem bug T. Please report."]; - } - }, - _getOperator: function (a) { - switch (a) { - case "+": return " {}+{} "; - case "-": return " {}-{} "; - case "=": return " {}={} "; - case "<": return " {}<{} "; - case ">": return " {}>{} "; - case "<<": return " {}\\ll{} "; - case ">>": return " {}\\gg{} "; - case "\\pm": return " {}\\pm{} "; - case "\\approx": return " {}\\approx{} "; - case "$\\approx$": return " {}\\approx{} "; - case "v": return " \\downarrow{} "; - case "(v)": return " \\downarrow{} "; - case "^": return " \\uparrow{} "; - case "(^)": return " \\uparrow{} "; - default: - assertNever(a); - throw ["MhchemBugT", "mhchem bug T. Please report."]; - } - } - }; - - // - // Helpers for code anaylsis - // Will show type error at calling position - // - /** @param {number} a */ - function assertNever(a) {} - /** @param {string} a */ - function assertString(a) {} - -/* eslint-disable no-undef */ - -////////////////////////////////////////////////////////////////////// -// texvc.sty - -// The texvc package contains macros available in mediawiki pages. -// We omit the functions deprecated at -// https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax - -// We also omit texvc's \O, which conflicts with \text{\O} - -defineMacro("\\darr", "\\downarrow"); -defineMacro("\\dArr", "\\Downarrow"); -defineMacro("\\Darr", "\\Downarrow"); -defineMacro("\\lang", "\\langle"); -defineMacro("\\rang", "\\rangle"); -defineMacro("\\uarr", "\\uparrow"); -defineMacro("\\uArr", "\\Uparrow"); -defineMacro("\\Uarr", "\\Uparrow"); -defineMacro("\\N", "\\mathbb{N}"); -defineMacro("\\R", "\\mathbb{R}"); -defineMacro("\\Z", "\\mathbb{Z}"); -defineMacro("\\alef", "\\aleph"); -defineMacro("\\alefsym", "\\aleph"); -defineMacro("\\bull", "\\bullet"); -defineMacro("\\clubs", "\\clubsuit"); -defineMacro("\\cnums", "\\mathbb{C}"); -defineMacro("\\Complex", "\\mathbb{C}"); -defineMacro("\\Dagger", "\\ddagger"); -defineMacro("\\diamonds", "\\diamondsuit"); -defineMacro("\\empty", "\\emptyset"); -defineMacro("\\exist", "\\exists"); -defineMacro("\\harr", "\\leftrightarrow"); -defineMacro("\\hArr", "\\Leftrightarrow"); -defineMacro("\\Harr", "\\Leftrightarrow"); -defineMacro("\\hearts", "\\heartsuit"); -defineMacro("\\image", "\\Im"); -defineMacro("\\infin", "\\infty"); -defineMacro("\\isin", "\\in"); -defineMacro("\\larr", "\\leftarrow"); -defineMacro("\\lArr", "\\Leftarrow"); -defineMacro("\\Larr", "\\Leftarrow"); -defineMacro("\\lrarr", "\\leftrightarrow"); -defineMacro("\\lrArr", "\\Leftrightarrow"); -defineMacro("\\Lrarr", "\\Leftrightarrow"); -defineMacro("\\natnums", "\\mathbb{N}"); -defineMacro("\\plusmn", "\\pm"); -defineMacro("\\rarr", "\\rightarrow"); -defineMacro("\\rArr", "\\Rightarrow"); -defineMacro("\\Rarr", "\\Rightarrow"); -defineMacro("\\real", "\\Re"); -defineMacro("\\reals", "\\mathbb{R}"); -defineMacro("\\Reals", "\\mathbb{R}"); -defineMacro("\\sdot", "\\cdot"); -defineMacro("\\sect", "\\S"); -defineMacro("\\spades", "\\spadesuit"); -defineMacro("\\sub", "\\subset"); -defineMacro("\\sube", "\\subseteq"); -defineMacro("\\supe", "\\supseteq"); -defineMacro("\\thetasym", "\\vartheta"); -defineMacro("\\weierp", "\\wp"); - -/* eslint-disable no-undef */ - -/**************************************************** - * - * physics.js - * - * Implements the Physics Package for LaTeX input. - * - * --------------------------------------------------------------------- - * - * The original version of this file is licensed as follows: - * Copyright (c) 2015-2016 Kolen Cheung . - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * --------------------------------------------------------------------- - * - * This file has been revised from the original in the following ways: - * 1. The interface is changed so that it can be called from Temml, not MathJax. - * 2. \Re and \Im are not used, to avoid conflict with existing LaTeX letters. - * - * This revision of the file is released under the MIT license. - * https://mit-license.org/ - */ -defineMacro("\\quantity", "{\\left\\{ #1 \\right\\}}"); -defineMacro("\\qty", "{\\left\\{ #1 \\right\\}}"); -defineMacro("\\pqty", "{\\left( #1 \\right)}"); -defineMacro("\\bqty", "{\\left[ #1 \\right]}"); -defineMacro("\\vqty", "{\\left\\vert #1 \\right\\vert}"); -defineMacro("\\Bqty", "{\\left\\{ #1 \\right\\}}"); -defineMacro("\\absolutevalue", "{\\left\\vert #1 \\right\\vert}"); -defineMacro("\\abs", "{\\left\\vert #1 \\right\\vert}"); -defineMacro("\\norm", "{\\left\\Vert #1 \\right\\Vert}"); -defineMacro("\\evaluated", "{\\left.#1 \\right\\vert}"); -defineMacro("\\eval", "{\\left.#1 \\right\\vert}"); -defineMacro("\\order", "{\\mathcal{O} \\left( #1 \\right)}"); -defineMacro("\\commutator", "{\\left[ #1 , #2 \\right]}"); -defineMacro("\\comm", "{\\left[ #1 , #2 \\right]}"); -defineMacro("\\anticommutator", "{\\left\\{ #1 , #2 \\right\\}}"); -defineMacro("\\acomm", "{\\left\\{ #1 , #2 \\right\\}}"); -defineMacro("\\poissonbracket", "{\\left\\{ #1 , #2 \\right\\}}"); -defineMacro("\\pb", "{\\left\\{ #1 , #2 \\right\\}}"); -defineMacro("\\vectorbold", "{\\boldsymbol{ #1 }}"); -defineMacro("\\vb", "{\\boldsymbol{ #1 }}"); -defineMacro("\\vectorarrow", "{\\vec{\\boldsymbol{ #1 }}}"); -defineMacro("\\va", "{\\vec{\\boldsymbol{ #1 }}}"); -defineMacro("\\vectorunit", "{{\\boldsymbol{\\hat{ #1 }}}}"); -defineMacro("\\vu", "{{\\boldsymbol{\\hat{ #1 }}}}"); -defineMacro("\\dotproduct", "\\mathbin{\\boldsymbol\\cdot}"); -defineMacro("\\vdot", "{\\boldsymbol\\cdot}"); -defineMacro("\\crossproduct", "\\mathbin{\\boldsymbol\\times}"); -defineMacro("\\cross", "\\mathbin{\\boldsymbol\\times}"); -defineMacro("\\cp", "\\mathbin{\\boldsymbol\\times}"); -defineMacro("\\gradient", "{\\boldsymbol\\nabla}"); -defineMacro("\\grad", "{\\boldsymbol\\nabla}"); -defineMacro("\\divergence", "{\\grad\\vdot}"); -//defineMacro("\\div", "{\\grad\\vdot}"); Not included in Temml. Conflicts w/LaTeX \div -defineMacro("\\curl", "{\\grad\\cross}"); -defineMacro("\\laplacian", "\\nabla^2"); -defineMacro("\\tr", "{\\operatorname{tr}}"); -defineMacro("\\Tr", "{\\operatorname{Tr}}"); -defineMacro("\\rank", "{\\operatorname{rank}}"); -defineMacro("\\erf", "{\\operatorname{erf}}"); -defineMacro("\\Res", "{\\operatorname{Res}}"); -defineMacro("\\principalvalue", "{\\mathcal{P}}"); -defineMacro("\\pv", "{\\mathcal{P}}"); -defineMacro("\\PV", "{\\operatorname{P.V.}}"); -// Temml does not use the next two lines. They conflict with LaTeX letters. -//defineMacro("\\Re", "{\\operatorname{Re} \\left\\{ #1 \\right\\}}"); -//defineMacro("\\Im", "{\\operatorname{Im} \\left\\{ #1 \\right\\}}"); -defineMacro("\\qqtext", "{\\quad\\text{ #1 }\\quad}"); -defineMacro("\\qq", "{\\quad\\text{ #1 }\\quad}"); -defineMacro("\\qcomma", "{\\text{,}\\quad}"); -defineMacro("\\qc", "{\\text{,}\\quad}"); -defineMacro("\\qcc", "{\\quad\\text{c.c.}\\quad}"); -defineMacro("\\qif", "{\\quad\\text{if}\\quad}"); -defineMacro("\\qthen", "{\\quad\\text{then}\\quad}"); -defineMacro("\\qelse", "{\\quad\\text{else}\\quad}"); -defineMacro("\\qotherwise", "{\\quad\\text{otherwise}\\quad}"); -defineMacro("\\qunless", "{\\quad\\text{unless}\\quad}"); -defineMacro("\\qgiven", "{\\quad\\text{given}\\quad}"); -defineMacro("\\qusing", "{\\quad\\text{using}\\quad}"); -defineMacro("\\qassume", "{\\quad\\text{assume}\\quad}"); -defineMacro("\\qsince", "{\\quad\\text{since}\\quad}"); -defineMacro("\\qlet", "{\\quad\\text{let}\\quad}"); -defineMacro("\\qfor", "{\\quad\\text{for}\\quad}"); -defineMacro("\\qall", "{\\quad\\text{all}\\quad}"); -defineMacro("\\qeven", "{\\quad\\text{even}\\quad}"); -defineMacro("\\qodd", "{\\quad\\text{odd}\\quad}"); -defineMacro("\\qinteger", "{\\quad\\text{integer}\\quad}"); -defineMacro("\\qand", "{\\quad\\text{and}\\quad}"); -defineMacro("\\qor", "{\\quad\\text{or}\\quad}"); -defineMacro("\\qas", "{\\quad\\text{as}\\quad}"); -defineMacro("\\qin", "{\\quad\\text{in}\\quad}"); -defineMacro("\\differential", "{\\text{d}}"); -defineMacro("\\dd", "{\\text{d}}"); -defineMacro("\\derivative", "{\\frac{\\text{d}{ #1 }}{\\text{d}{ #2 }}}"); -defineMacro("\\dv", "{\\frac{\\text{d}{ #1 }}{\\text{d}{ #2 }}}"); -defineMacro("\\partialderivative", "{\\frac{\\partial{ #1 }}{\\partial{ #2 }}}"); -defineMacro("\\variation", "{\\delta}"); -defineMacro("\\var", "{\\delta}"); -defineMacro("\\functionalderivative", "{\\frac{\\delta{ #1 }}{\\delta{ #2 }}}"); -defineMacro("\\fdv", "{\\frac{\\delta{ #1 }}{\\delta{ #2 }}}"); -defineMacro("\\innerproduct", "{\\left\\langle {#1} \\mid { #2} \\right\\rangle}"); -defineMacro("\\outerproduct", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -defineMacro("\\dyad", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -defineMacro("\\ketbra", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -defineMacro("\\op", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -defineMacro("\\expectationvalue", "{\\left\\langle {#1 } \\right\\rangle}"); -defineMacro("\\expval", "{\\left\\langle {#1 } \\right\\rangle}"); -defineMacro("\\ev", "{\\left\\langle {#1 } \\right\\rangle}"); -defineMacro("\\matrixelement", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); -defineMacro("\\matrixel", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); -defineMacro("\\mel", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); - -/** - * This file contains the “gullet” where macros are expanded - * until only non-macro tokens remain. - */ - -// List of commands that act like macros but aren't defined as a macro, -// function, or symbol. Used in `isDefined`. -const implicitCommands = { - "^": true, // Parser.js - _: true, // Parser.js - "\\limits": true, // Parser.js - "\\nolimits": true // Parser.js -}; - -class MacroExpander { - constructor(input, settings, mode) { - this.settings = settings; - this.expansionCount = 0; - this.feed(input); - // Make new global namespace - this.macros = new Namespace(macros, settings.macros); - this.mode = mode; - this.stack = []; // contains tokens in REVERSE order - } - - /** - * Feed a new input string to the same MacroExpander - * (with existing macros etc.). - */ - feed(input) { - this.lexer = new Lexer(input, this.settings); - } - - /** - * Switches between "text" and "math" modes. - */ - switchMode(newMode) { - this.mode = newMode; - } - - /** - * Start a new group nesting within all namespaces. - */ - beginGroup() { - this.macros.beginGroup(); - } - - /** - * End current group nesting within all namespaces. - */ - endGroup() { - this.macros.endGroup(); - } - - /** - * Returns the topmost token on the stack, without expanding it. - * Similar in behavior to TeX's `\futurelet`. - */ - future() { - if (this.stack.length === 0) { - this.pushToken(this.lexer.lex()); - } - return this.stack[this.stack.length - 1] - } - - /** - * Remove and return the next unexpanded token. - */ - popToken() { - this.future(); // ensure non-empty stack - return this.stack.pop(); - } - - /** - * Add a given token to the token stack. In particular, this get be used - * to put back a token returned from one of the other methods. - */ - pushToken(token) { - this.stack.push(token); - } - - /** - * Append an array of tokens to the token stack. - */ - pushTokens(tokens) { - this.stack.push(...tokens); - } - - /** - * Find an macro argument without expanding tokens and append the array of - * tokens to the token stack. Uses Token as a container for the result. - */ - scanArgument(isOptional) { - let start; - let end; - let tokens; - if (isOptional) { - this.consumeSpaces(); // \@ifnextchar gobbles any space following it - if (this.future().text !== "[") { - return null; - } - start = this.popToken(); // don't include [ in tokens - ({ tokens, end } = this.consumeArg(["]"])); - } else { - ({ tokens, start, end } = this.consumeArg()); - } - - // indicate the end of an argument - this.pushToken(new Token("EOF", end.loc)); - - this.pushTokens(tokens); - return start.range(end, ""); - } - - /** - * Consume all following space tokens, without expansion. - */ - consumeSpaces() { - for (;;) { - const token = this.future(); - if (token.text === " ") { - this.stack.pop(); - } else { - break; - } - } - } - - /** - * Consume an argument from the token stream, and return the resulting array - * of tokens and start/end token. - */ - consumeArg(delims) { - // The argument for a delimited parameter is the shortest (possibly - // empty) sequence of tokens with properly nested {...} groups that is - // followed ... by this particular list of non-parameter tokens. - // The argument for an undelimited parameter is the next nonblank - // token, unless that token is ‘{’, when the argument will be the - // entire {...} group that follows. - const tokens = []; - const isDelimited = delims && delims.length > 0; - if (!isDelimited) { - // Ignore spaces between arguments. As the TeXbook says: - // "After you have said ‘\def\row#1#2{...}’, you are allowed to - // put spaces between the arguments (e.g., ‘\row x n’), because - // TeX doesn’t use single spaces as undelimited arguments." - this.consumeSpaces(); - } - const start = this.future(); - let tok; - let depth = 0; - let match = 0; - do { - tok = this.popToken(); - tokens.push(tok); - if (tok.text === "{") { - ++depth; - } else if (tok.text === "}") { - --depth; - if (depth === -1) { - throw new ParseError("Extra }", tok); - } - } else if (tok.text === "EOF") { - throw new ParseError( - "Unexpected end of input in a macro argument" + - ", expected '" + - (delims && isDelimited ? delims[match] : "}") + - "'", - tok - ); - } - if (delims && isDelimited) { - if ((depth === 0 || (depth === 1 && delims[match] === "{")) && tok.text === delims[match]) { - ++match; - if (match === delims.length) { - // don't include delims in tokens - tokens.splice(-match, match); - break; - } - } else { - match = 0; - } - } - } while (depth !== 0 || isDelimited); - // If the argument found ... has the form ‘{}’, - // ... the outermost braces enclosing the argument are removed - if (start.text === "{" && tokens[tokens.length - 1].text === "}") { - tokens.pop(); - tokens.shift(); - } - tokens.reverse(); // to fit in with stack order - return { tokens, start, end: tok }; - } - - /** - * Consume the specified number of (delimited) arguments from the token - * stream and return the resulting array of arguments. - */ - consumeArgs(numArgs, delimiters) { - if (delimiters) { - if (delimiters.length !== numArgs + 1) { - throw new ParseError("The length of delimiters doesn't match the number of args!"); - } - const delims = delimiters[0]; - for (let i = 0; i < delims.length; i++) { - const tok = this.popToken(); - if (delims[i] !== tok.text) { - throw new ParseError("Use of the macro doesn't match its definition", tok); - } - } - } - - const args = []; - for (let i = 0; i < numArgs; i++) { - args.push(this.consumeArg(delimiters && delimiters[i + 1]).tokens); - } - return args; - } - - /** - * Expand the next token only once if possible. - * - * If the token is expanded, the resulting tokens will be pushed onto - * the stack in reverse order and will be returned as an array, - * also in reverse order. - * - * If not, the next token will be returned without removing it - * from the stack. This case can be detected by a `Token` return value - * instead of an `Array` return value. - * - * In either case, the next token will be on the top of the stack, - * or the stack will be empty. - * - * Used to implement `expandAfterFuture` and `expandNextToken`. - * - * If expandableOnly, only expandable tokens are expanded and - * an undefined control sequence results in an error. - */ - expandOnce(expandableOnly) { - const topToken = this.popToken(); - const name = topToken.text; - const expansion = !topToken.noexpand ? this._getExpansion(name) : null; - if (expansion == null || (expandableOnly && expansion.unexpandable)) { - if (expandableOnly && expansion == null && name[0] === "\\" && !this.isDefined(name)) { - throw new ParseError("Undefined control sequence: " + name); - } - this.pushToken(topToken); - return topToken; - } - this.expansionCount++; - if (this.expansionCount > this.settings.maxExpand) { - throw new ParseError( - "Too many expansions: infinite loop or " + "need to increase maxExpand setting" - ); - } - let tokens = expansion.tokens; - const args = this.consumeArgs(expansion.numArgs, expansion.delimiters); - if (expansion.numArgs) { - // paste arguments in place of the placeholders - tokens = tokens.slice(); // make a shallow copy - for (let i = tokens.length - 1; i >= 0; --i) { - let tok = tokens[i]; - if (tok.text === "#") { - if (i === 0) { - throw new ParseError("Incomplete placeholder at end of macro body", tok); - } - tok = tokens[--i]; // next token on stack - if (tok.text === "#") { - // ## → # - tokens.splice(i + 1, 1); // drop first # - } else if (/^[1-9]$/.test(tok.text)) { - // replace the placeholder with the indicated argument - tokens.splice(i, 2, ...args[+tok.text - 1]); - } else { - throw new ParseError("Not a valid argument number", tok); - } - } - } - } - // Concatenate expansion onto top of stack. - this.pushTokens(tokens); - return tokens; - } - - /** - * Expand the next token only once (if possible), and return the resulting - * top token on the stack (without removing anything from the stack). - * Similar in behavior to TeX's `\expandafter\futurelet`. - * Equivalent to expandOnce() followed by future(). - */ - expandAfterFuture() { - this.expandOnce(); - return this.future(); - } - - /** - * Recursively expand first token, then return first non-expandable token. - */ - expandNextToken() { - for (;;) { - const expanded = this.expandOnce(); - // expandOnce returns Token if and only if it's fully expanded. - if (expanded instanceof Token) { - // The token after \noexpand is interpreted as if its meaning were ‘\relax’ - if (expanded.treatAsRelax) { - expanded.text = "\\relax"; - } - return this.stack.pop(); // === expanded - } - } - - // This pathway is impossible. - throw new Error(); // eslint-disable-line no-unreachable - } - - /** - * Fully expand the given macro name and return the resulting list of - * tokens, or return `undefined` if no such macro is defined. - */ - expandMacro(name) { - return this.macros.has(name) ? this.expandTokens([new Token(name)]) : undefined; - } - - /** - * Fully expand the given token stream and return the resulting list of - * tokens. Note that the input tokens are in reverse order, but the - * output tokens are in forward order. - */ - expandTokens(tokens) { - const output = []; - const oldStackLength = this.stack.length; - this.pushTokens(tokens); - while (this.stack.length > oldStackLength) { - const expanded = this.expandOnce(true); // expand only expandable tokens - // expandOnce returns Token if and only if it's fully expanded. - if (expanded instanceof Token) { - if (expanded.treatAsRelax) { - // the expansion of \noexpand is the token itself - expanded.noexpand = false; - expanded.treatAsRelax = false; - } - output.push(this.stack.pop()); - } - } - return output; - } - - /** - * Fully expand the given macro name and return the result as a string, - * or return `undefined` if no such macro is defined. - */ - expandMacroAsText(name) { - const tokens = this.expandMacro(name); - if (tokens) { - return tokens.map((token) => token.text).join(""); - } else { - return tokens; - } - } - - /** - * Returns the expanded macro as a reversed array of tokens and a macro - * argument count. Or returns `null` if no such macro. - */ - _getExpansion(name) { - const definition = this.macros.get(name); - if (definition == null) { - // mainly checking for undefined here - return definition; - } - // If a single character has an associated catcode other than 13 - // (active character), then don't expand it. - if (name.length === 1) { - const catcode = this.lexer.catcodes[name]; - if (catcode != null && catcode !== 13) { - return - } - } - const expansion = typeof definition === "function" ? definition(this) : definition; - if (typeof expansion === "string") { - let numArgs = 0; - if (expansion.indexOf("#") !== -1) { - const stripped = expansion.replace(/##/g, ""); - while (stripped.indexOf("#" + (numArgs + 1)) !== -1) { - ++numArgs; - } - } - const bodyLexer = new Lexer(expansion, this.settings); - const tokens = []; - let tok = bodyLexer.lex(); - while (tok.text !== "EOF") { - tokens.push(tok); - tok = bodyLexer.lex(); - } - tokens.reverse(); // to fit in with stack using push and pop - const expanded = { tokens, numArgs }; - return expanded; - } - - return expansion; - } - - /** - * Determine whether a command is currently "defined" (has some - * functionality), meaning that it's a macro (in the current group), - * a function, a symbol, or one of the special commands listed in - * `implicitCommands`. - */ - isDefined(name) { - return ( - this.macros.has(name) || - Object.prototype.hasOwnProperty.call(functions, name ) || - Object.prototype.hasOwnProperty.call(symbols.math, name ) || - Object.prototype.hasOwnProperty.call(symbols.text, name ) || - Object.prototype.hasOwnProperty.call(implicitCommands, name ) - ); - } - - /** - * Determine whether a command is expandable. - */ - isExpandable(name) { - const macro = this.macros.get(name); - return macro != null - ? typeof macro === "string" || typeof macro === "function" || !macro.unexpandable - : Object.prototype.hasOwnProperty.call(functions, name ) && !functions[name].primitive; - } -} - -/* - * This file defines the Unicode scripts and script families that we - * support. To add new scripts or families, just add a new entry to the - * scriptData array below. Adding scripts to the scriptData array allows - * characters from that script to appear in \text{} environments. - */ - -/** - * Each script or script family has a name and an array of blocks. - * Each block is an array of two numbers which specify the start and - * end points (inclusive) of a block of Unicode codepoints. - -/** - * Unicode block data for the families of scripts we support in \text{}. - * Scripts only need to appear here if they do not have font metrics. - */ -const scriptData = [ - { - // Latin characters beyond the Latin-1 characters we have metrics for. - // Needed for Czech, Hungarian and Turkish text, for example. - name: "latin", - blocks: [ - [0x0100, 0x024f], // Latin Extended-A and Latin Extended-B - [0x0300, 0x036f] // Combining Diacritical marks - ] - }, - { - // The Cyrillic script used by Russian and related languages. - // A Cyrillic subset used to be supported as explicitly defined - // symbols in symbols.js - name: "cyrillic", - blocks: [[0x0400, 0x04ff]] - }, - { - // Armenian - name: "armenian", - blocks: [[0x0530, 0x058f]] - }, - { - // The Brahmic scripts of South and Southeast Asia - // Devanagari (0900–097F) - // Bengali (0980–09FF) - // Gurmukhi (0A00–0A7F) - // Gujarati (0A80–0AFF) - // Oriya (0B00–0B7F) - // Tamil (0B80–0BFF) - // Telugu (0C00–0C7F) - // Kannada (0C80–0CFF) - // Malayalam (0D00–0D7F) - // Sinhala (0D80–0DFF) - // Thai (0E00–0E7F) - // Lao (0E80–0EFF) - // Tibetan (0F00–0FFF) - // Myanmar (1000–109F) - name: "brahmic", - blocks: [[0x0900, 0x109f]] - }, - { - name: "georgian", - blocks: [[0x10a0, 0x10ff]] - }, - { - // Chinese and Japanese. - // The "k" in cjk is for Korean, but we've separated Korean out - name: "cjk", - blocks: [ - [0x3000, 0x30ff], // CJK symbols and punctuation, Hiragana, Katakana - [0x4e00, 0x9faf], // CJK ideograms - [0xff00, 0xff60] // Fullwidth punctuation - // TODO: add halfwidth Katakana and Romanji glyphs - ] - }, - { - // Korean - name: "hangul", - blocks: [[0xac00, 0xd7af]] - } -]; - -/** - * A flattened version of all the supported blocks in a single array. - * This is an optimization to make supportedCodepoint() fast. - */ -const allBlocks = []; -scriptData.forEach((s) => s.blocks.forEach((b) => allBlocks.push(...b))); - -/** - * Given a codepoint, return true if it falls within one of the - * scripts or script families defined above and false otherwise. - * - * Micro benchmarks shows that this is faster than - * /[\u3000-\u30FF\u4E00-\u9FAF\uFF00-\uFF60\uAC00-\uD7AF\u0900-\u109F]/.test() - * in Firefox, Chrome and Node. - */ -function supportedCodepoint(codepoint) { - for (let i = 0; i < allBlocks.length; i += 2) { - if (codepoint >= allBlocks[i] && codepoint <= allBlocks[i + 1]) { - return true; - } - } - return false; -} - -// Mapping of Unicode accent characters to their LaTeX equivalent in text and -// math mode (when they exist). -var unicodeAccents = { - "\u0301": { text: "\\'", math: "\\acute" }, - "\u0300": { text: "\\`", math: "\\grave" }, - "\u0308": { text: '\\"', math: "\\ddot" }, - "\u0303": { text: "\\~", math: "\\tilde" }, - "\u0304": { text: "\\=", math: "\\bar" }, - "\u0306": { text: "\\u", math: "\\breve" }, - "\u030c": { text: "\\v", math: "\\check" }, - "\u0302": { text: "\\^", math: "\\hat" }, - "\u0307": { text: "\\.", math: "\\dot" }, - "\u030a": { text: "\\r", math: "\\mathring" }, - "\u030b": { text: "\\H" }, - '\u0327': { text: '\\c' } -}; - -var unicodeSymbols = { - "á": "á", - "à": "à", - "ä": "ä", - "ǟ": "ǟ", - "ã": "ã", - "ā": "ā", - "ă": "ă", - "ắ": "ắ", - "ằ": "ằ", - "ẵ": "ẵ", - "ǎ": "ǎ", - "â": "â", - "ấ": "ấ", - "ầ": "ầ", - "ẫ": "ẫ", - "ȧ": "ȧ", - "ǡ": "ǡ", - "å": "å", - "ǻ": "ǻ", - "ḃ": "ḃ", - "ć": "ć", - "č": "č", - "ĉ": "ĉ", - "ċ": "ċ", - "ď": "ď", - "ḋ": "ḋ", - "é": "é", - "è": "è", - "ë": "ë", - "ẽ": "ẽ", - "ē": "ē", - "ḗ": "ḗ", - "ḕ": "ḕ", - "ĕ": "ĕ", - "ě": "ě", - "ê": "ê", - "ế": "ế", - "ề": "ề", - "ễ": "ễ", - "ė": "ė", - "ḟ": "ḟ", - "ǵ": "ǵ", - "ḡ": "ḡ", - "ğ": "ğ", - "ǧ": "ǧ", - "ĝ": "ĝ", - "ġ": "ġ", - "ḧ": "ḧ", - "ȟ": "ȟ", - "ĥ": "ĥ", - "ḣ": "ḣ", - "í": "í", - "ì": "ì", - "ï": "ï", - "ḯ": "ḯ", - "ĩ": "ĩ", - "ī": "ī", - "ĭ": "ĭ", - "ǐ": "ǐ", - "î": "î", - "ǰ": "ǰ", - "ĵ": "ĵ", - "ḱ": "ḱ", - "ǩ": "ǩ", - "ĺ": "ĺ", - "ľ": "ľ", - "ḿ": "ḿ", - "ṁ": "ṁ", - "ń": "ń", - "ǹ": "ǹ", - "ñ": "ñ", - "ň": "ň", - "ṅ": "ṅ", - "ó": "ó", - "ò": "ò", - "ö": "ö", - "ȫ": "ȫ", - "õ": "õ", - "ṍ": "ṍ", - "ṏ": "ṏ", - "ȭ": "ȭ", - "ō": "ō", - "ṓ": "ṓ", - "ṑ": "ṑ", - "ŏ": "ŏ", - "ǒ": "ǒ", - "ô": "ô", - "ố": "ố", - "ồ": "ồ", - "ỗ": "ỗ", - "ȯ": "ȯ", - "ȱ": "ȱ", - "ő": "ő", - "ṕ": "ṕ", - "ṗ": "ṗ", - "ŕ": "ŕ", - "ř": "ř", - "ṙ": "ṙ", - "ś": "ś", - "ṥ": "ṥ", - "š": "š", - "ṧ": "ṧ", - "ŝ": "ŝ", - "ṡ": "ṡ", - "ẗ": "ẗ", - "ť": "ť", - "ṫ": "ṫ", - "ú": "ú", - "ù": "ù", - "ü": "ü", - "ǘ": "ǘ", - "ǜ": "ǜ", - "ǖ": "ǖ", - "ǚ": "ǚ", - "ũ": "ũ", - "ṹ": "ṹ", - "ū": "ū", - "ṻ": "ṻ", - "ŭ": "ŭ", - "ǔ": "ǔ", - "û": "û", - "ů": "ů", - "ű": "ű", - "ṽ": "ṽ", - "ẃ": "ẃ", - "ẁ": "ẁ", - "ẅ": "ẅ", - "ŵ": "ŵ", - "ẇ": "ẇ", - "ẘ": "ẘ", - "ẍ": "ẍ", - "ẋ": "ẋ", - "ý": "ý", - "ỳ": "ỳ", - "ÿ": "ÿ", - "ỹ": "ỹ", - "ȳ": "ȳ", - "ŷ": "ŷ", - "ẏ": "ẏ", - "ẙ": "ẙ", - "ź": "ź", - "ž": "ž", - "ẑ": "ẑ", - "ż": "ż", - "Á": "Á", - "À": "À", - "Ä": "Ä", - "Ǟ": "Ǟ", - "Ã": "Ã", - "Ā": "Ā", - "Ă": "Ă", - "Ắ": "Ắ", - "Ằ": "Ằ", - "Ẵ": "Ẵ", - "Ǎ": "Ǎ", - "Â": "Â", - "Ấ": "Ấ", - "Ầ": "Ầ", - "Ẫ": "Ẫ", - "Ȧ": "Ȧ", - "Ǡ": "Ǡ", - "Å": "Å", - "Ǻ": "Ǻ", - "Ḃ": "Ḃ", - "Ć": "Ć", - "Č": "Č", - "Ĉ": "Ĉ", - "Ċ": "Ċ", - "Ď": "Ď", - "Ḋ": "Ḋ", - "É": "É", - "È": "È", - "Ë": "Ë", - "Ẽ": "Ẽ", - "Ē": "Ē", - "Ḗ": "Ḗ", - "Ḕ": "Ḕ", - "Ĕ": "Ĕ", - "Ě": "Ě", - "Ê": "Ê", - "Ế": "Ế", - "Ề": "Ề", - "Ễ": "Ễ", - "Ė": "Ė", - "Ḟ": "Ḟ", - "Ǵ": "Ǵ", - "Ḡ": "Ḡ", - "Ğ": "Ğ", - "Ǧ": "Ǧ", - "Ĝ": "Ĝ", - "Ġ": "Ġ", - "Ḧ": "Ḧ", - "Ȟ": "Ȟ", - "Ĥ": "Ĥ", - "Ḣ": "Ḣ", - "Í": "Í", - "Ì": "Ì", - "Ï": "Ï", - "Ḯ": "Ḯ", - "Ĩ": "Ĩ", - "Ī": "Ī", - "Ĭ": "Ĭ", - "Ǐ": "Ǐ", - "Î": "Î", - "İ": "İ", - "Ĵ": "Ĵ", - "Ḱ": "Ḱ", - "Ǩ": "Ǩ", - "Ĺ": "Ĺ", - "Ľ": "Ľ", - "Ḿ": "Ḿ", - "Ṁ": "Ṁ", - "Ń": "Ń", - "Ǹ": "Ǹ", - "Ñ": "Ñ", - "Ň": "Ň", - "Ṅ": "Ṅ", - "Ó": "Ó", - "Ò": "Ò", - "Ö": "Ö", - "Ȫ": "Ȫ", - "Õ": "Õ", - "Ṍ": "Ṍ", - "Ṏ": "Ṏ", - "Ȭ": "Ȭ", - "Ō": "Ō", - "Ṓ": "Ṓ", - "Ṑ": "Ṑ", - "Ŏ": "Ŏ", - "Ǒ": "Ǒ", - "Ô": "Ô", - "Ố": "Ố", - "Ồ": "Ồ", - "Ỗ": "Ỗ", - "Ȯ": "Ȯ", - "Ȱ": "Ȱ", - "Ő": "Ő", - "Ṕ": "Ṕ", - "Ṗ": "Ṗ", - "Ŕ": "Ŕ", - "Ř": "Ř", - "Ṙ": "Ṙ", - "Ś": "Ś", - "Ṥ": "Ṥ", - "Š": "Š", - "Ṧ": "Ṧ", - "Ŝ": "Ŝ", - "Ṡ": "Ṡ", - "Ť": "Ť", - "Ṫ": "Ṫ", - "Ú": "Ú", - "Ù": "Ù", - "Ü": "Ü", - "Ǘ": "Ǘ", - "Ǜ": "Ǜ", - "Ǖ": "Ǖ", - "Ǚ": "Ǚ", - "Ũ": "Ũ", - "Ṹ": "Ṹ", - "Ū": "Ū", - "Ṻ": "Ṻ", - "Ŭ": "Ŭ", - "Ǔ": "Ǔ", - "Û": "Û", - "Ů": "Ů", - "Ű": "Ű", - "Ṽ": "Ṽ", - "Ẃ": "Ẃ", - "Ẁ": "Ẁ", - "Ẅ": "Ẅ", - "Ŵ": "Ŵ", - "Ẇ": "Ẇ", - "Ẍ": "Ẍ", - "Ẋ": "Ẋ", - "Ý": "Ý", - "Ỳ": "Ỳ", - "Ÿ": "Ÿ", - "Ỹ": "Ỹ", - "Ȳ": "Ȳ", - "Ŷ": "Ŷ", - "Ẏ": "Ẏ", - "Ź": "Ź", - "Ž": "Ž", - "Ẑ": "Ẑ", - "Ż": "Ż", - "ά": "ά", - "ὰ": "ὰ", - "ᾱ": "ᾱ", - "ᾰ": "ᾰ", - "έ": "έ", - "ὲ": "ὲ", - "ή": "ή", - "ὴ": "ὴ", - "ί": "ί", - "ὶ": "ὶ", - "ϊ": "ϊ", - "ΐ": "ΐ", - "ῒ": "ῒ", - "ῑ": "ῑ", - "ῐ": "ῐ", - "ό": "ό", - "ὸ": "ὸ", - "ύ": "ύ", - "ὺ": "ὺ", - "ϋ": "ϋ", - "ΰ": "ΰ", - "ῢ": "ῢ", - "ῡ": "ῡ", - "ῠ": "ῠ", - "ώ": "ώ", - "ὼ": "ὼ", - "Ύ": "Ύ", - "Ὺ": "Ὺ", - "Ϋ": "Ϋ", - "Ῡ": "Ῡ", - "Ῠ": "Ῠ", - "Ώ": "Ώ", - "Ὼ": "Ὼ" -}; - -/* eslint no-constant-condition:0 */ - -const numberRegEx$1 = /^\d[\d.]*$/; // Keep in sync with numberRegEx in symbolsOrd.js - -/** - * This file contains the parser used to parse out a TeX expression from the - * input. Since TeX isn't context-free, standard parsers don't work particularly - * well. - * - * The strategy of this parser is as such: - * - * The main functions (the `.parse...` ones) take a position in the current - * parse string to parse tokens from. The lexer (found in Lexer.js, stored at - * this.gullet.lexer) also supports pulling out tokens at arbitrary places. When - * individual tokens are needed at a position, the lexer is called to pull out a - * token, which is then used. - * - * The parser has a property called "mode" indicating the mode that - * the parser is currently in. Currently it has to be one of "math" or - * "text", which denotes whether the current environment is a math-y - * one or a text-y one (e.g. inside \text). Currently, this serves to - * limit the functions which can be used in text mode. - * - * The main functions then return an object which contains the useful data that - * was parsed at its given point, and a new position at the end of the parsed - * data. The main functions can call each other and continue the parsing by - * using the returned position as a new starting point. - * - * There are also extra `.handle...` functions, which pull out some reused - * functionality into self-contained functions. - * - * The functions return ParseNodes. - */ - -class Parser { - constructor(input, settings, isPreamble = false) { - // Start in math mode - this.mode = "math"; - // Create a new macro expander (gullet) and (indirectly via that) also a - // new lexer (mouth) for this parser (stomach, in the language of TeX) - this.gullet = new MacroExpander(input, settings, this.mode); - // Store the settings for use in parsing - this.settings = settings; - // Are we defining a preamble? - this.isPreamble = isPreamble; - // Count leftright depth (for \middle errors) - this.leftrightDepth = 0; - this.prevAtomType = ""; - } - - /** - * Checks a result to make sure it has the right type, and throws an - * appropriate error otherwise. - */ - expect(text, consume = true) { - if (this.fetch().text !== text) { - throw new ParseError(`Expected '${text}', got '${this.fetch().text}'`, this.fetch()); - } - if (consume) { - this.consume(); - } - } - - /** - * Discards the current lookahead token, considering it consumed. - */ - consume() { - this.nextToken = null; - } - - /** - * Return the current lookahead token, or if there isn't one (at the - * beginning, or if the previous lookahead token was consume()d), - * fetch the next token as the new lookahead token and return it. - */ - fetch() { - if (this.nextToken == null) { - this.nextToken = this.gullet.expandNextToken(); - } - return this.nextToken; - } - - /** - * Switches between "text" and "math" modes. - */ - switchMode(newMode) { - this.mode = newMode; - this.gullet.switchMode(newMode); - } - - /** - * Main parsing function, which parses an entire input. - */ - parse() { - // Create a group namespace for every $...$, $$...$$, \[...\].) - // A \def is then valid only within that pair of delimiters. - this.gullet.beginGroup(); - - if (this.settings.colorIsTextColor) { - // Use old \color behavior (same as LaTeX's \textcolor) if requested. - // We do this within the group for the math expression, so it doesn't - // pollute settings.macros. - this.gullet.macros.set("\\color", "\\textcolor"); - } - - // Try to parse the input - const parse = this.parseExpression(false); - - // If we succeeded, make sure there's an EOF at the end - this.expect("EOF"); - - if (this.isPreamble) { - const macros = Object.create(null); - Object.entries(this.gullet.macros.current).forEach(([key, value]) => { - macros[key] = value; - }); - this.gullet.endGroup(); - return macros - } - - // The only local macro that we want to save is from \tag. - const tag = this.gullet.macros.get("\\df@tag"); - - // End the group namespace for the expression - this.gullet.endGroup(); - - if (tag) { this.gullet.macros.current["\\df@tag"] = tag; } - - return parse; - } - - static get endOfExpression() { - return ["}", "\\endgroup", "\\end", "\\right", "\\endtoggle", "&"]; - } - - /** - * Parses an "expression", which is a list of atoms. - * - * `breakOnInfix`: Should the parsing stop when we hit infix nodes? This - * happens when functions have higher precendence han infix - * nodes in implicit parses. - * - * `breakOnTokenText`: The text of the token that the expression should end - * with, or `null` if something else should end the - * expression. - */ - parseExpression(breakOnInfix, breakOnTokenText) { - const body = []; - // Keep adding atoms to the body until we can't parse any more atoms (either - // we reached the end, a }, or a \right) - while (true) { - // Ignore spaces in math mode - if (this.mode === "math") { - this.consumeSpaces(); - } - const lex = this.fetch(); - if (Parser.endOfExpression.indexOf(lex.text) !== -1) { - break; - } - if (breakOnTokenText && lex.text === breakOnTokenText) { - break; - } - if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) { - break; - } - const atom = this.parseAtom(breakOnTokenText); - if (!atom) { - break; - } else if (atom.type === "internal") { - continue; - } - body.push(atom); - // Keep a record of the atom type, so that op.js can set correct spacing. - this.prevAtomType = atom.type === "atom" ? atom.family : atom.type; - } - if (this.mode === "text") { - this.formLigatures(body); - } - return this.handleInfixNodes(body); - } - - /** - * Rewrites infix operators such as \over with corresponding commands such - * as \frac. - * - * There can only be one infix operator per group. If there's more than one - * then the expression is ambiguous. This can be resolved by adding {}. - */ - handleInfixNodes(body) { - let overIndex = -1; - let funcName; - - for (let i = 0; i < body.length; i++) { - if (body[i].type === "infix") { - if (overIndex !== -1) { - throw new ParseError("only one infix operator per group", body[i].token); - } - overIndex = i; - funcName = body[i].replaceWith; - } - } - - if (overIndex !== -1 && funcName) { - let numerNode; - let denomNode; - - const numerBody = body.slice(0, overIndex); - const denomBody = body.slice(overIndex + 1); - - if (numerBody.length === 1 && numerBody[0].type === "ordgroup") { - numerNode = numerBody[0]; - } else { - numerNode = { type: "ordgroup", mode: this.mode, body: numerBody }; - } - - if (denomBody.length === 1 && denomBody[0].type === "ordgroup") { - denomNode = denomBody[0]; - } else { - denomNode = { type: "ordgroup", mode: this.mode, body: denomBody }; - } - - let node; - if (funcName === "\\\\abovefrac") { - node = this.callFunction(funcName, [numerNode, body[overIndex], denomNode], []); - } else { - node = this.callFunction(funcName, [numerNode, denomNode], []); - } - return [node]; - } else { - return body; - } - } - - /** - * Handle a subscript or superscript with nice errors. - */ - handleSupSubscript( - name // For error reporting. - ) { - const symbolToken = this.fetch(); - const symbol = symbolToken.text; - this.consume(); - this.consumeSpaces(); // ignore spaces before sup/subscript argument - const group = this.parseGroup(name); - - if (!group) { - throw new ParseError("Expected group after '" + symbol + "'", symbolToken); - } - - return group; - } - - /** - * Converts the textual input of an unsupported command into a text node - * contained within a color node whose color is determined by errorColor - */ - formatUnsupportedCmd(text) { - const textordArray = []; - - for (let i = 0; i < text.length; i++) { - textordArray.push({ type: "textord", mode: "text", text: text[i] }); - } - - const textNode = { - type: "text", - mode: this.mode, - body: textordArray - }; - - const colorNode = { - type: "color", - mode: this.mode, - color: this.settings.errorColor, - body: [textNode] - }; - - return colorNode; - } - - /** - * Parses a group with optional super/subscripts. - */ - parseAtom(breakOnTokenText) { - // The body of an atom is an implicit group, so that things like - // \left(x\right)^2 work correctly. - const base = this.parseGroup("atom", breakOnTokenText); - - // In text mode, we don't have superscripts or subscripts - if (this.mode === "text") { - return base; - } - - // Note that base may be empty (i.e. null) at this point. - - let superscript; - let subscript; - while (true) { - // Guaranteed in math mode, so eat any spaces first. - this.consumeSpaces(); - - // Lex the first token - const lex = this.fetch(); - - if (lex.text === "\\limits" || lex.text === "\\nolimits") { - // We got a limit control - if (base && base.type === "op") { - const limits = lex.text === "\\limits"; - base.limits = limits; - base.alwaysHandleSupSub = true; - } else if (base && base.type === "operatorname") { - if (base.alwaysHandleSupSub) { - base.limits = lex.text === "\\limits"; - } - } else { - throw new ParseError("Limit controls must follow a math operator", lex); - } - this.consume(); - } else if (lex.text === "^") { - // We got a superscript start - if (superscript) { - throw new ParseError("Double superscript", lex); - } - superscript = this.handleSupSubscript("superscript"); - } else if (lex.text === "_") { - // We got a subscript start - if (subscript) { - throw new ParseError("Double subscript", lex); - } - subscript = this.handleSupSubscript("subscript"); - } else if (lex.text === "'") { - // We got a prime - if (superscript) { - throw new ParseError("Double superscript", lex); - } - const prime = { type: "textord", mode: this.mode, text: "\\prime" }; - - // Many primes can be grouped together, so we handle this here - const primes = [prime]; - this.consume(); - // Keep lexing tokens until we get something that's not a prime - while (this.fetch().text === "'") { - // For each one, add another prime to the list - primes.push(prime); - this.consume(); - } - // If there's a superscript following the primes, combine that - // superscript in with the primes. - if (this.fetch().text === "^") { - primes.push(this.handleSupSubscript("superscript")); - } - // Put everything into an ordgroup as the superscript - superscript = { type: "ordgroup", mode: this.mode, body: primes }; - } else { - // If it wasn't ^, _, or ', stop parsing super/subscripts - break; - } - } - - if (superscript || subscript) { - if (base && base.type === "multiscript" && !base.postscripts) { - // base is the result of a \prescript function. - // Write the sub- & superscripts into the multiscript element. - base.postscripts = { sup: superscript, sub: subscript }; - return base - } else { - // We got either a superscript or subscript, create a supsub - return { - type: "supsub", - mode: this.mode, - base: base, - sup: superscript, - sub: subscript - } - } - } else { - // Otherwise return the original body - return base; - } - } - - /** - * Parses an entire function, including its base and all of its arguments. - */ - parseFunction( - breakOnTokenText, - name // For determining its context - ) { - const token = this.fetch(); - const func = token.text; - const funcData = functions[func]; - if (!funcData) { - return null; - } - this.consume(); // consume command token - - if (name && name !== "atom" && !funcData.allowedInArgument) { - throw new ParseError( - "Got function '" + func + "' with no arguments" + (name ? " as " + name : ""), - token - ); - } else if (this.mode === "text" && !funcData.allowedInText) { - throw new ParseError("Can't use function '" + func + "' in text mode", token); - } else if (this.mode === "math" && funcData.allowedInMath === false) { - throw new ParseError("Can't use function '" + func + "' in math mode", token); - } - - const prevAtomType = this.prevAtomType; - const { args, optArgs } = this.parseArguments(func, funcData); - this.prevAtomType = prevAtomType; - return this.callFunction(func, args, optArgs, token, breakOnTokenText); - } - - /** - * Call a function handler with a suitable context and arguments. - */ - callFunction(name, args, optArgs, token, breakOnTokenText) { - const context = { - funcName: name, - parser: this, - token, - breakOnTokenText - }; - const func = functions[name]; - if (func && func.handler) { - return func.handler(context, args, optArgs); - } else { - throw new ParseError(`No function handler for ${name}`); - } - } - - /** - * Parses the arguments of a function or environment - */ - parseArguments( - func, // Should look like "\name" or "\begin{name}". - funcData - ) { - const totalArgs = funcData.numArgs + funcData.numOptionalArgs; - if (totalArgs === 0) { - return { args: [], optArgs: [] }; - } - - const args = []; - const optArgs = []; - - for (let i = 0; i < totalArgs; i++) { - let argType = funcData.argTypes && funcData.argTypes[i]; - const isOptional = i < funcData.numOptionalArgs; - - if ( - (funcData.primitive && argType == null) || - // \sqrt expands into primitive if optional argument doesn't exist - (funcData.type === "sqrt" && i === 1 && optArgs[0] == null) - ) { - argType = "primitive"; - } - - const arg = this.parseGroupOfType(`argument to '${func}'`, argType, isOptional); - if (isOptional) { - optArgs.push(arg); - } else if (arg != null) { - args.push(arg); - } else { - // should be unreachable - throw new ParseError("Null argument, please report this as a bug"); - } - } - - return { args, optArgs }; - } - - /** - * Parses a group when the mode is changing. - */ - parseGroupOfType(name, type, optional) { - switch (type) { - case "size": - return this.parseSizeGroup(optional); - case "url": - return this.parseUrlGroup(optional); - case "math": - case "text": - return this.parseArgumentGroup(optional, type); - case "hbox": { - // hbox argument type wraps the argument in the equivalent of - // \hbox, which is like \text but switching to \textstyle size. - const group = this.parseArgumentGroup(optional, "text"); - return group != null - ? { - type: "styling", - mode: group.mode, - body: [group], - scriptLevel: "text" // simulate \textstyle - } - : null; - } - case "raw": { - const token = this.parseStringGroup("raw", optional); - return token != null - ? { - type: "raw", - mode: "text", - string: token.text - } - : null; - } - case "primitive": { - if (optional) { - throw new ParseError("A primitive argument cannot be optional"); - } - const group = this.parseGroup(name); - if (group == null) { - throw new ParseError("Expected group as " + name, this.fetch()); - } - return group; - } - case "original": - case null: - case undefined: - return this.parseArgumentGroup(optional); - default: - throw new ParseError("Unknown group type as " + name, this.fetch()); - } - } - - /** - * Discard any space tokens, fetching the next non-space token. - */ - consumeSpaces() { - while (this.fetch().text === " ") { - this.consume(); - } - } - - /** - * Parses a group, essentially returning the string formed by the - * brace-enclosed tokens plus some position information. - */ - parseStringGroup( - modeName, // Used to describe the mode in error messages. - optional - ) { - const argToken = this.gullet.scanArgument(optional); - if (argToken == null) { - return null; - } - let str = ""; - let nextToken; - while ((nextToken = this.fetch()).text !== "EOF") { - str += nextToken.text; - this.consume(); - } - this.consume(); // consume the end of the argument - argToken.text = str; - return argToken; - } - - /** - * Parses a regex-delimited group: the largest sequence of tokens - * whose concatenated strings match `regex`. Returns the string - * formed by the tokens plus some position information. - */ - parseRegexGroup( - regex, - modeName // Used to describe the mode in error messages. - ) { - const firstToken = this.fetch(); - let lastToken = firstToken; - let str = ""; - let nextToken; - while ((nextToken = this.fetch()).text !== "EOF" && regex.test(str + nextToken.text)) { - lastToken = nextToken; - str += lastToken.text; - this.consume(); - } - if (str === "") { - throw new ParseError("Invalid " + modeName + ": '" + firstToken.text + "'", firstToken); - } - return firstToken.range(lastToken, str); - } - - /** - * Parses a size specification, consisting of magnitude and unit. - */ - parseSizeGroup(optional) { - let res; - let isBlank = false; - // don't expand before parseStringGroup - this.gullet.consumeSpaces(); - if (!optional && this.gullet.future().text !== "{") { - res = this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size"); - } else { - res = this.parseStringGroup("size", optional); - } - if (!res) { - return null; - } - if (!optional && res.text.length === 0) { - // Because we've tested for what is !optional, this block won't - // affect \kern, \hspace, etc. It will capture the mandatory arguments - // to \genfrac and \above. - res.text = "0pt"; // Enable \above{} - isBlank = true; // This is here specifically for \genfrac - } - const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(res.text); - if (!match) { - throw new ParseError("Invalid size: '" + res.text + "'", res); - } - const data = { - number: +(match[1] + match[2]), // sign + magnitude, cast to number - unit: match[3] - }; - if (!validUnit(data)) { - throw new ParseError("Invalid unit: '" + data.unit + "'", res); - } - return { - type: "size", - mode: this.mode, - value: data, - isBlank - }; - } - - /** - * Parses an URL, checking escaped letters and allowed protocols, - * and setting the catcode of % as an active character (as in \hyperref). - */ - parseUrlGroup(optional) { - this.gullet.lexer.setCatcode("%", 13); // active character - this.gullet.lexer.setCatcode("~", 12); // other character - const res = this.parseStringGroup("url", optional); - this.gullet.lexer.setCatcode("%", 14); // comment character - this.gullet.lexer.setCatcode("~", 13); // active character - if (res == null) { - return null; - } - // hyperref package allows backslashes alone in href, but doesn't - // generate valid links in such cases; we interpret this as - // "undefined" behaviour, and keep them as-is. Some browser will - // replace backslashes with forward slashes. - let url = res.text.replace(/\\([#$%&~_^{}])/g, "$1"); - url = res.text.replace(/{\u2044}/g, "/"); - return { - type: "url", - mode: this.mode, - url - }; - } - - /** - * Parses an argument with the mode specified. - */ - parseArgumentGroup(optional, mode) { - const argToken = this.gullet.scanArgument(optional); - if (argToken == null) { - return null; - } - const outerMode = this.mode; - if (mode) { - // Switch to specified mode - this.switchMode(mode); - } - - this.gullet.beginGroup(); - const expression = this.parseExpression(false, "EOF"); - // TODO: find an alternative way to denote the end - this.expect("EOF"); // expect the end of the argument - this.gullet.endGroup(); - const result = { - type: "ordgroup", - mode: this.mode, - loc: argToken.loc, - body: expression - }; - - if (mode) { - // Switch mode back - this.switchMode(outerMode); - } - return result; - } - - /** - * Parses an ordinary group, which is either a single nucleus (like "x") - * or an expression in braces (like "{x+y}") or an implicit group, a group - * that starts at the current position, and ends right before a higher explicit - * group ends, or at EOF. - */ - parseGroup( - name, // For error reporting. - breakOnTokenText - ) { - const firstToken = this.fetch(); - const text = firstToken.text; - - let result; - // Try to parse an open brace or \begingroup - if (text === "{" || text === "\\begingroup" || text === "\\toggle") { - this.consume(); - const groupEnd = text === "{" - ? "}" - : text === "\\begingroup" - ? "\\endgroup" - : "\\endtoggle"; - - this.gullet.beginGroup(); - // If we get a brace, parse an expression - const expression = this.parseExpression(false, groupEnd); - const lastToken = this.fetch(); - this.expect(groupEnd); // Check that we got a matching closing brace - this.gullet.endGroup(); - result = { - type: (lastToken.text === "\\endtoggle" ? "toggle" : "ordgroup"), - mode: this.mode, - loc: SourceLocation.range(firstToken, lastToken), - body: expression, - // A group formed by \begingroup...\endgroup is a semi-simple group - // which doesn't affect spacing in math mode, i.e., is transparent. - // https://tex.stackexchange.com/questions/1930/when-should-one- - // use-begingroup-instead-of-bgroup - semisimple: text === "\\begingroup" || undefined - }; - } else { - // If there exists a function with this name, parse the function. - // Otherwise, just return a nucleus - result = this.parseFunction(breakOnTokenText, name) || this.parseSymbol(); - if (result == null && text[0] === "\\" && - !Object.prototype.hasOwnProperty.call(implicitCommands, text )) { - result = this.formatUnsupportedCmd(text); - this.consume(); - } - } - return result; - } - - /** - * Form ligature-like combinations of characters for text mode. - * This includes inputs like "--", "---", "``" and "''". - * The result will simply replace multiple textord nodes with a single - * character in each value by a single textord node having multiple - * characters in its value. The representation is still ASCII source. - * The group will be modified in place. - */ - formLigatures(group) { - let n = group.length - 1; - for (let i = 0; i < n; ++i) { - const a = group[i]; - const v = a.text; - if (v === "-" && group[i + 1].text === "-") { - if (i + 1 < n && group[i + 2].text === "-") { - group.splice(i, 3, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 2]), - text: "---" - }); - n -= 2; - } else { - group.splice(i, 2, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 1]), - text: "--" - }); - n -= 1; - } - } - if ((v === "'" || v === "`") && group[i + 1].text === v) { - group.splice(i, 2, { - type: "textord", - mode: "text", - loc: SourceLocation.range(a, group[i + 1]), - text: v + v - }); - n -= 1; - } - } - } - - /** - * Parse a single symbol out of the string. Here, we handle single character - * symbols and special functions like \verb. - */ - parseSymbol() { - const nucleus = this.fetch(); - let text = nucleus.text; - - if (/^\\verb[^a-zA-Z]/.test(text)) { - this.consume(); - let arg = text.slice(5); - const star = arg.charAt(0) === "*"; - if (star) { - arg = arg.slice(1); - } - // Lexer's tokenRegex is constructed to always have matching - // first/last characters. - if (arg.length < 2 || arg.charAt(0) !== arg.slice(-1)) { - throw new ParseError(`\\verb assertion failed -- - please report what input caused this bug`); - } - arg = arg.slice(1, -1); // remove first and last char - return { - type: "verb", - mode: "text", - body: arg, - star - }; - } - // At this point, we should have a symbol, possibly with accents. - // First expand any accented base symbol according to unicodeSymbols. - if (Object.prototype.hasOwnProperty.call(unicodeSymbols, text[0] ) && - !symbols[this.mode][text[0]]) { - // This behavior is not strict (XeTeX-compatible) in math mode. - if (this.settings.strict && this.mode === "math") { - this.settings.reportNonstrict( - "unicodeTextInMathMode", - `Accented Unicode text character "${text[0]}" used in ` + `math mode`, - nucleus - ); - } - text = unicodeSymbols[text[0]] + text.substr(1); - } - // Strip off any combining characters - const match = combiningDiacriticalMarksEndRegex.exec(text); - if (match) { - text = text.substring(0, match.index); - if (text === "i") { - text = "\u0131"; // dotless i, in math and text mode - } else if (text === "j") { - text = "\u0237"; // dotless j, in math and text mode - } - } - // Recognize base symbol - let symbol; - if (symbols[this.mode][text]) { - const group = symbols[this.mode][text].group; - const loc = SourceLocation.range(nucleus); - let s; - if (Object.prototype.hasOwnProperty.call(ATOMS, group )) { - const family = group; - s = { - type: "atom", - mode: this.mode, - family, - loc, - text - }; - } else { - s = { - type: group, - mode: this.mode, - loc, - text - }; - } - symbol = s; - } else if (!this.strict && numberRegEx$1.test(text)) { - // A number. Wrap in a - this.consume(); - return { - type: "textord", - mode: "math", - loc: SourceLocation.range(nucleus), - text - } - } else if (text.charCodeAt(0) >= 0x80) { - // no symbol for e.g. ^ - if (this.settings.strict) { - if (!supportedCodepoint(text.charCodeAt(0))) { - this.settings.reportNonstrict( - "unknownSymbol", - `Unrecognized Unicode character "${text[0]}"` + ` (${text.charCodeAt(0)})`, - nucleus - ); - } else if (this.mode === "math") { - this.settings.reportNonstrict( - "unicodeTextInMathMode", - `Unicode text character "${text[0]}" used in math mode`, - nucleus - ); - } - } - // All nonmathematical Unicode characters are rendered as if they - // are in text mode (wrapped in \text) because that's what it - // takes to render them in LaTeX. - symbol = { - type: "textord", - mode: "text", - loc: SourceLocation.range(nucleus), - text - }; - } else { - return null; // EOF, ^, _, {, }, etc. - } - this.consume(); - // Transform combining characters into accents - if (match) { - for (let i = 0; i < match[0].length; i++) { - const accent = match[0][i]; - if (!unicodeAccents[accent]) { - throw new ParseError(`Unknown accent ' ${accent}'`, nucleus); - } - const command = unicodeAccents[accent][this.mode] || - unicodeAccents[accent].text; - if (!command) { - throw new ParseError(`Accent ${accent} unsupported in ${this.mode} mode`, nucleus); - } - symbol = { - type: "accent", - mode: this.mode, - loc: SourceLocation.range(nucleus), - label: command, - isStretchy: false, - isShifty: true, - base: symbol - }; - } - } - return symbol; - } -} - -/** - * Parses an expression using a Parser, then returns the parsed result. - */ -const parseTree = function(toParse, settings) { - if (!(typeof toParse === "string" || toParse instanceof String)) { - throw new TypeError("Temml can only parse string typed expression") - } - const parser = new Parser(toParse, settings); - // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors - delete parser.gullet.macros.current["\\df@tag"]; - - let tree = parser.parse(); - - // LaTeX ignores a \tag placed outside an AMS environment. - if (!(tree.length > 0 && tree[0].type && tree[0].type === "array" && tree[0].addEqnNum)) { - // If the input used \tag, it will set the \df@tag macro to the tag. - // In this case, we separately parse the tag and wrap the tree. - if (parser.gullet.macros.get("\\df@tag")) { - if (!settings.displayMode) { - throw new ParseError("\\tag works only in display equations") - } - parser.gullet.feed("\\df@tag"); - tree = [ - { - type: "tag", - mode: "text", - body: tree, - tag: parser.parse() - } - ]; - } - } - - return tree -}; - -/** - * This file contains information about the style that the Parser carries - * around with it while parsing. Data is held in an `Style` object, and when - * recursing, a new `Style` object can be created with the `.with*` functions. - */ - -const subOrSupLevel = [2, 2, 3, 3]; - -/** - * This is the main Style class. It contains the current style.level, color, and font. - * - * Style objects should not be modified. To create a new Style with - * different properties, call a `.with*` method. - */ -class Style { - constructor(data) { - // Style.level can be 0 | 1 | 2 | 3, which correspond to - // displaystyle, textstyle, scriptstyle, and scriptscriptstyle. - // style.level does not directly set MathML's script level. MathML does that itself. - // We use style.level to track, not set, math style so that we can get the - // correct scriptlevel when needed in supsub.js, mathchoice.js, or for dimensions in em. - this.level = data.level; - this.color = data.color; // string | void - // A font family applies to a group of fonts (i.e. SansSerif), while a font - // represents a specific font (i.e. SansSerif Bold). - // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm - this.font = data.font || ""; // string - this.fontFamily = data.fontFamily || ""; // string - this.fontWeight = data.fontWeight || ""; - this.fontShape = data.fontShape || ""; - this.maxSize = data.maxSize; // number - } - - /** - * Returns a new style object with the same properties as "this". Properties - * from "extension" will be copied to the new style object. - */ - extend(extension) { - const data = { - level: this.level, - color: this.color, - font: this.font, - fontFamily: this.fontFamily, - fontWeight: this.fontWeight, - fontShape: this.fontShape, - maxSize: this.maxSize - }; - - for (const key in extension) { - if (Object.prototype.hasOwnProperty.call(extension, key)) { - data[key] = extension[key]; - } - } - - return new Style(data); - } - - withLevel(n) { - return this.extend({ - level: n - }); - } - - incrementLevel() { - return this.extend({ - level: Math.min(this.level + 1, 3) - }); - } - - inSubOrSup() { - return this.extend({ - level: subOrSupLevel[this.level] - }) - } - - /** - * Create a new style object with the given color. - */ - withColor(color) { - return this.extend({ - color: color - }); - } - - /** - * Creates a new style object with the given math font or old text font. - * @type {[type]} - */ - withFont(font) { - return this.extend({ - font - }); - } - - /** - * Create a new style objects with the given fontFamily. - */ - withTextFontFamily(fontFamily) { - return this.extend({ - fontFamily, - font: "" - }); - } - - /** - * Creates a new style object with the given font weight - */ - withTextFontWeight(fontWeight) { - return this.extend({ - fontWeight, - font: "" - }); - } - - /** - * Creates a new style object with the given font weight - */ - withTextFontShape(fontShape) { - return this.extend({ - fontShape, - font: "" - }); - } - - /** - * Gets the CSS color of the current style object - */ - getColor() { - return this.color; - } -} - -/* Temml Post Process - * Perform two tasks not done by Temml when it created each individual Temml element. - * Given a block of block, - * 1. At each AMS auto-numbered environment, assign an id. - * 2. Populate the text contents of each \ref & \eqref - * - * As with other Temml code, this file is released under terms of the MIT license. - * https://mit-license.org/ - */ - -const version = "0.4.2"; - -function postProcess(block) { - const labelMap = {}; - let i = 0; - - // Get a collection of the parents of each \tag & auto-numbered equation - const parents = block.getElementsByClassName("tml-tageqn"); - for (const parent of parents) { - const eqns = parent.getElementsByClassName("tml-eqn"); - if (eqns. length > 0 ) { - // AMS automatically numbered equation. - // Assign an id. - i += 1; - eqns[0].id = "tml-eqn-" + i; - // No need to write a number into the text content of the element. - // A CSS counter does that even if this postProcess() function is not used. - } - // If there is a \label, add it to labelMap - const labels = parent.getElementsByClassName("tml-label"); - if (labels.length === 0) { continue } - if (eqns.length > 0) { - labelMap[labels[0].id] = String(i); - } else { - const tags = parent.getElementsByClassName("tml-tag"); - if (tags.length > 0) { - labelMap[labels[0].id] = tags[0].textContent; - } - } - } - - // Populate \ref & \eqref text content - const refs = block.getElementsByClassName("tml-ref"); - [...refs].forEach(ref => { - let str = labelMap[ref.getAttribute("href").slice(1)]; - if (ref.className.indexOf("tml-eqref") === -1) { - // \ref. Omit parens. - str = str.replace(/^\(/, ""); - str = str.replace(/\($/, ""); - } { - // \eqref. Include parens - if (str.charAt(0) !== "(") { str = "(" + str; } - if (str.slice(-1) !== ")") { str = str + ")"; } - } - ref.textContent = str; - }); -} - -/* eslint no-console:0 */ - -/** - * Parse and build an expression, and place that expression in the DOM node - * given. - */ -let render = function(expression, baseNode, options) { - baseNode.textContent = ""; - const math = renderToMathMLTree(expression, options); - if (options.elementIsMath) { - // The element already exists. Populate it. - baseNode.textContent = ""; - math.children.forEach(e => { baseNode.appendChild(e.toNode()); }); - } else { - baseNode.appendChild(math.toNode()); - } -}; - -// Temml's styles don't work properly in quirks mode. Print out an error, and -// disable rendering. -if (typeof document !== "undefined") { - if (document.compatMode !== "CSS1Compat") { - typeof console !== "undefined" && - console.warn( - "Warning: Temml doesn't work in quirks mode. Make sure your " + - "website has a suitable doctype." - ); - - render = function() { - throw new ParseError("Temml doesn't work in quirks mode."); - }; - } -} - -/** - * Parse and build an expression, and return the markup for that. - */ -const renderToString = function(expression, options) { - const markup = renderToMathMLTree(expression, options).toMarkup(); - return markup; -}; - -/** - * Parse an expression and return the parse tree. - */ -const generateParseTree = function(expression, options) { - const settings = new Settings(options); - return parseTree(expression, settings); -}; - -/** - * Take an expression which contains a preamble. - * Parse it and return the macros. - */ -const definePreamble = function(expression, options) { - const settings = new Settings(options); - settings.macros = {}; - if (!(typeof expression === "string" || expression instanceof String)) { - throw new TypeError("Temml can only parse string typed expression") - } - const parser = new Parser(expression, settings, true); - // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors - delete parser.gullet.macros.current["\\df@tag"]; - const macros = parser.parse(); - return macros -}; - -/** - * If the given error is a Temml ParseError, - * renders the invalid LaTeX as a span with hover title giving the Temml - * error message. Otherwise, simply throws the error. - */ -const renderError = function(error, expression, options) { - if (options.throwOnError || !(error instanceof ParseError)) { - throw error; - } - const node = new Span(["temml-error"], [new TextNode(expression)]); - node.setAttribute("title", error.toString()); - node.setAttribute("style", `color:${options.errorColor}`); - return node; -}; - -/** - * Generates and returns the Temml build tree. This is used for advanced - * use cases (like rendering to custom output). - */ -const renderToMathMLTree = function(expression, options) { - const settings = new Settings(options); - try { - const tree = parseTree(expression, settings); - const style = new Style({ - level: settings.displayMode ? StyleLevel.DISPLAY : StyleLevel.TEXT, - maxSize: settings.maxSize - }); - return buildMathML(tree, expression, style, settings); - } catch (error) { - return renderError(error, expression, settings); - } -}; - -var temml = { - /** - * Current Temml version - */ - version: version, - /** - * Renders the given LaTeX into MathML, and adds - * it as a child to the specified DOM node. - */ - render, - /** - * Renders the given LaTeX into MathML string, - * for sending to the client. - */ - renderToString, - /** - * Post-process an entire HTML block. - * Writes AMS auto-numbers and implements \ref{}. - * Typcally called once, after a loop has rendered many individual spans. - */ - postProcess, - /** - * Temml error, usually during parsing. - */ - ParseError, - /** - * Creates a set of macros with document-wide scope. - */ - definePreamble, - /** - * Parses the given LaTeX into Temml's internal parse tree structure, - * without rendering to HTML or MathML. - * - * NOTE: This method is not currently recommended for public use. - * The internal tree representation is unstable and is very likely - * to change. Use at your own risk. - */ - __parse: generateParseTree, - /** - * Renders the given LaTeX into a MathML internal DOM tree - * representation, without flattening that representation to a string. - * - * NOTE: This method is not currently recommended for public use. - * The internal tree representation is unstable and is very likely - * to change. Use at your own risk. - */ - __renderToMathMLTree: renderToMathMLTree, - /** - * adds a new symbol to builtin symbols table - */ - __defineSymbol: defineSymbol, - /** - * adds a new macro to builtin macro list - */ - __defineMacro: defineMacro -}; - -export default temml; diff --git a/yarn-error.log b/yarn-error.log deleted file mode 100644 index 8c8a0d55..00000000 --- a/yarn-error.log +++ /dev/null @@ -1,5361 +0,0 @@ -Arguments: - C:\Program Files\nodejs\node.exe C:\Program Files (x86)\Yarn\bin\yarn.js build - -PATH: - C:\Python38\Scripts\;C:\Python38\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\Git\cmd;C:\ProgramData\chocolatey\bin;C:\Program Files (x86)\Yarn\bin\;C:\Program Files\nodejs\;C:\Users\Ronal\AppData\Local\Microsoft\WindowsApps;C:\Users\Ronal\AppData\Local\Programs\Microsoft VS Code\bin;C:\Users\Ronal\AppData\Local\GitHubDesktop\bin;C:\Users\Ronal\AppData\Local\Yarn\bin;C:\Users\Ronal\AppData\Roaming\npm;%USERPROFILE%\AppData\Local\Microsoft\WindowsApps; - -Yarn version: - 1.22.4 - -Node version: - 12.18.0 - -Platform: - win32 x64 - -Trace: - SyntaxError: C:\Users\Ronal\OneDrive\Documents\temml\package.json: Unexpected token } in JSON at position 588 - at JSON.parse () - at C:\Program Files (x86)\Yarn\lib\cli.js:1625:59 - at Generator.next () - at step (C:\Program Files (x86)\Yarn\lib\cli.js:310:30) - at C:\Program Files (x86)\Yarn\lib\cli.js:321:13 - -npm manifest: - { - "name": "temml", - "version": "0.1.0", - "description": "LaTeX to MathML conversion in JavaScript.", - "main": "dist/temml.js", - "homepage": "https://temml.org", - "repository": { - "type": "git", - "url": "git://github.com/temml/temml.git" - }, - "files": [ - "temml.js", - "src/", - "contrib/", - "dist/" - ], - "license": "MIT", - "devDependencies": { - "eslint": "^5.14.1", - "file-loader": "^3.0.1", - "json-stable-stringify": "^1.0.1", - "jspngopt": "^0.2.0", - "mkdirp": "^0.5.1", - "pako": "^1.0.8", - "rimraf": "^2.6.3", - "rollup": "^1.13.0", - }, - "scripts": { - "test": "yarn test:lint && yarn test:jest", - "test:lint": "yarn test:lint:js", - "test:lint:js": "eslint *.js src static test contrib website", - "clean": "rm -rf dist/ node_modules/", - "clean-install": "yarn clean && yarn", - "build": "rollup --config ./rollup.config.js", - "docs": "node docs/buildDocs.js", - "dist": "yarn test && yarn build && yarn dist:zip", - "dist:zip": "rimraf temml/ temml.tar.gz temml.zip && cp -R dist temml && tar czf temml.tar.gz temml && zip -rq temml.zip temml && rimraf temml/" - } - } - -yarn manifest: - No manifest - -Lockfile: - # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. - # yarn lockfile v1 - - - "@babel/code-frame@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" - integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== - dependencies: - "@babel/highlight" "^7.0.0" - - "@babel/core@>=7.1.0", "@babel/core@^7.1.0": - version "7.3.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.3.3.tgz#d090d157b7c5060d05a05acaebc048bd2b037947" - integrity sha512-w445QGI2qd0E0GlSnq6huRZWPMmQGCp5gd5ZWS4hagn0EiwzxD5QMFkpchyusAyVC1n27OKXzQ0/88aVU9n4xQ== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.3.3" - "@babel/helpers" "^7.2.0" - "@babel/parser" "^7.3.3" - "@babel/template" "^7.2.2" - "@babel/traverse" "^7.2.2" - "@babel/types" "^7.3.3" - convert-source-map "^1.1.0" - debug "^4.1.0" - json5 "^2.1.0" - lodash "^4.17.11" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - - "@babel/generator@^7.2.2", "@babel/generator@^7.3.3": - version "7.3.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.3.tgz#185962ade59a52e00ca2bdfcfd1d58e528d4e39e" - integrity sha512-aEADYwRRZjJyMnKN7llGIlircxTCofm3dtV5pmY6ob18MSIuipHpA2yZWkPlycwu5HJcx/pADS3zssd8eY7/6A== - dependencies: - "@babel/types" "^7.3.3" - jsesc "^2.5.1" - lodash "^4.17.11" - source-map "^0.5.0" - trim-right "^1.0.1" - - "@babel/generator@^7.4.0", "@babel/generator@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.5.0.tgz#f20e4b7a91750ee8b63656073d843d2a736dca4a" - integrity sha512-1TTVrt7J9rcG5PMjvO7VEG3FrEoEJNHxumRq66GemPmzboLWtIjjcJgk8rokuAS7IiRSpgVSu5Vb9lc99iJkOA== - dependencies: - "@babel/types" "^7.5.0" - jsesc "^2.5.1" - lodash "^4.17.11" - source-map "^0.5.0" - trim-right "^1.0.1" - - "@babel/helper-function-name@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" - integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== - dependencies: - "@babel/helper-get-function-arity" "^7.0.0" - "@babel/template" "^7.1.0" - "@babel/types" "^7.0.0" - - "@babel/helper-get-function-arity@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" - integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== - dependencies: - "@babel/types" "^7.0.0" - - "@babel/helper-plugin-utils@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" - integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== - - "@babel/helper-split-export-declaration@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz#3aae285c0311c2ab095d997b8c9a94cad547d813" - integrity sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag== - dependencies: - "@babel/types" "^7.0.0" - - "@babel/helper-split-export-declaration@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" - integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== - dependencies: - "@babel/types" "^7.4.4" - - "@babel/helpers@^7.2.0": - version "7.3.1" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.3.1.tgz#949eec9ea4b45d3210feb7dc1c22db664c9e44b9" - integrity sha512-Q82R3jKsVpUV99mgX50gOPCWwco9Ec5Iln/8Vyu4osNIOQgSrd9RFrQeUvmvddFNoLwMyOUWU+5ckioEKpDoGA== - dependencies: - "@babel/template" "^7.1.2" - "@babel/traverse" "^7.1.5" - "@babel/types" "^7.3.0" - - "@babel/highlight@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" - integrity sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw== - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^4.0.0" - - "@babel/parser@^7.2.2", "@babel/parser@^7.2.3", "@babel/parser@^7.3.3": - version "7.3.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.3.tgz#092d450db02bdb6ccb1ca8ffd47d8774a91aef87" - integrity sha512-xsH1CJoln2r74hR+y7cg2B5JCPaTh+Hd+EbBRk9nWGSNspuo6krjhX0Om6RnRQuIvFq8wVXCLKH3kwKDYhanSg== - - "@babel/parser@^7.4.3", "@babel/parser@^7.4.4", "@babel/parser@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.0.tgz#3e0713dff89ad6ae37faec3b29dcfc5c979770b7" - integrity sha512-I5nW8AhGpOXGCCNYGc+p7ExQIBxRFnS2fd/d862bNOKvmoEPjYPcfIjsfdy0ujagYOIYPczKgD9l3FsgTkAzKA== - - "@babel/plugin-syntax-object-rest-spread@^7.0.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" - integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - - "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2": - version "7.2.2" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907" - integrity sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.2.2" - "@babel/types" "^7.2.2" - - "@babel/template@^7.4.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237" - integrity sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.4.4" - "@babel/types" "^7.4.4" - - "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.5", "@babel/traverse@^7.2.2": - version "7.2.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.2.3.tgz#7ff50cefa9c7c0bd2d81231fdac122f3957748d8" - integrity sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.2.2" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.0.0" - "@babel/parser" "^7.2.3" - "@babel/types" "^7.2.2" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.10" - - "@babel/traverse@^7.4.3": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.5.0.tgz#4216d6586854ef5c3c4592dab56ec7eb78485485" - integrity sha512-SnA9aLbyOCcnnbQEGwdfBggnc142h/rbqqsXcaATj2hZcegCl903pUD/lfpsNBlBSuWow/YDfRyJuWi2EPR5cg== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.5.0" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.5.0" - "@babel/types" "^7.5.0" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.11" - - "@babel/types@^7.0.0", "@babel/types@^7.2.2", "@babel/types@^7.3.0", "@babel/types@^7.3.3": - version "7.3.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.3.tgz#6c44d1cdac2a7625b624216657d5bc6c107ab436" - integrity sha512-2tACZ80Wg09UnPg5uGAOUvvInaqLk3l/IAhQzlxLQOIXacr6bMsra5SH6AWw/hIDRCSbCdHP2KzSOD+cT7TzMQ== - dependencies: - esutils "^2.0.2" - lodash "^4.17.11" - to-fast-properties "^2.0.0" - - "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.0.tgz#e47d43840c2e7f9105bc4d3a2c371b4d0c7832ab" - integrity sha512-UFpDVqRABKsW01bvw7/wSUe56uy6RXM5+VJibVVAybDGxEW25jdwiFJEf7ASvSaC7sN7rbE/l3cLp2izav+CtQ== - dependencies: - esutils "^2.0.2" - lodash "^4.17.11" - to-fast-properties "^2.0.0" - - "@mrmlnc/readdir-enhanced@^2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" - integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== - dependencies: - call-me-maybe "^1.0.1" - glob-to-regexp "^0.3.0" - - "@nodelib/fs.stat@^1.1.2": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" - integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== - - "@rollup/plugin-node-resolve@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-8.1.0.tgz#1da5f3d0ccabc8f66f5e3c74462aad76cfd96c47" - integrity sha512-ovq7ZM3JJYUUmEjjO+H8tnUdmQmdQudJB7xruX8LFZ1W2q8jXdPUS6SsIYip8ByOApu4RR7729Am9WhCeCMiHA== - dependencies: - "@rollup/pluginutils" "^3.0.8" - "@types/resolve" "0.0.8" - builtin-modules "^3.1.0" - deep-freeze "^0.0.1" - deepmerge "^4.2.2" - is-module "^1.0.0" - resolve "^1.14.2" - - "@rollup/pluginutils@^3.0.8": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" - integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== - dependencies: - "@types/estree" "0.0.39" - estree-walker "^1.0.1" - picomatch "^2.2.2" - - "@tootallnate/once@1": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.0.0.tgz#9c13c2574c92d4503b005feca8f2e16cc1611506" - integrity sha512-KYyTT/T6ALPkIRd2Ge080X/BsXvy9O0hcWTtMWkPvwAwF99+vn6Dv4GzrFT/Nn1LePr+FFDbRXXlqmsy9lw2zA== - - "@types/estree@*": - version "0.0.45" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884" - integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g== - - "@types/estree@0.0.39": - version "0.0.39" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" - integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== - - "@types/node@*": - version "10.5.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.5.5.tgz#8e84d24e896cd77b0d4f73df274027e3149ec2ba" - integrity sha512-6Qnb1gXbp3g1JX9QVJj3A6ORzc9XCyhokxUKaoonHgNXcQhmk8adhotxfkeK8El9TnFeUuH72yI6jQ5nDJKS6w== - - "@types/resolve@0.0.8": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" - integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== - dependencies: - "@types/node" "*" - - "@types/unist@*", "@types/unist@^2.0.0": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" - integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== - - "@types/vfile-message@*": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/vfile-message/-/vfile-message-1.0.1.tgz#e1e9895cc6b36c462d4244e64e6d0b6eaf65355a" - integrity sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA== - dependencies: - "@types/node" "*" - "@types/unist" "*" - - "@types/vfile@^3.0.0": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@types/vfile/-/vfile-3.0.2.tgz#19c18cd232df11ce6fa6ad80259bc86c366b09b9" - integrity sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw== - dependencies: - "@types/node" "*" - "@types/unist" "*" - "@types/vfile-message" "*" - - abab@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" - integrity sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4= - - abab@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.0.tgz#aba0ab4c5eee2d4c79d3487d85450fb2376ebb0f" - integrity sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w== - - abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - - acorn-globals@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.1.0.tgz#ab716025dbe17c54d3ef81d32ece2b2d99fe2538" - integrity sha512-KjZwU26uG3u6eZcfGbTULzFcsoz6pegNKtHPksZPOUsiKo5bUmiBPa38FuHZ/Eun+XYh/JCCkS9AS3Lu4McQOQ== - dependencies: - acorn "^5.0.0" - - acorn-jsx@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" - integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== - - acorn@^5.0.0, acorn@^5.5.3: - version "5.7.4" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" - integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== - - acorn@^6.0.7: - version "6.1.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.0.tgz#b0a3be31752c97a0f7013c5f4903b71a05db6818" - integrity sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw== - - acorn@^7.1.0: - version "7.3.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" - integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== - - agent-base@5: - version "5.1.1" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c" - integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g== - - agent-base@6: - version "6.0.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.0.tgz#5d0101f19bbfaed39980b22ae866de153b93f09a" - integrity sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw== - dependencies: - debug "4" - - ajv-errors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.0.tgz#ecf021fa108fd17dfb5e6b383f2dd233e31ffc59" - integrity sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk= - - ajv-keywords@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" - integrity sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo= - - ajv@^5.1.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - - ajv@^6.1.0, ajv@^6.9.1: - version "6.9.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.9.1.tgz#a4d3683d74abc5670e75f0b16520f70a20ea8dc1" - integrity sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA== - dependencies: - fast-deep-equal "^2.0.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - - ansi-escapes@^3.0.0, ansi-escapes@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" - integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== - - ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - - ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - - ansi-regex@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.0.0.tgz#70de791edf021404c3fd615aa89118ae0432e5a9" - integrity sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w== - - ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - - anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - - append-transform@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab" - integrity sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw== - dependencies: - default-require-extensions "^2.0.0" - - aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - - are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - - argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - - argv@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/argv/-/argv-0.0.2.tgz#ecbd16f8949b157183711b1bda334f37840185ab" - integrity sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas= - - arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - - arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - - arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - - array-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" - integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= - - array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= - - array-iterate@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/array-iterate/-/array-iterate-1.1.2.tgz#f66a57e84426f8097f4197fbb6c051b8e5cdf7d8" - integrity sha512-1hWSHTIlG/8wtYD+PPX5AOBtKWngpDFjrsrHgZpe+JdgNGz0udYu6ZIkAa/xuenIUEqFv7DvE2Yr60jxweJSrQ== - - array-union@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - - array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - - array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - - arrify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - - asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" - integrity sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y= - - assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - - assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - - astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - - async-limiter@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" - integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== - - async@^2.6.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" - integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== - dependencies: - lodash "^4.17.11" - - asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - - atob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" - integrity sha1-ri1acpR38onWDdf5amMUoi3Wwio= - - autoprefixer@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.0.1.tgz#b5b74aba3fa60b4f1403729e46a6a1246f16818f" - integrity sha512-ytUcgSKu1mZh8pCJq54BkaK7ijigK+nhqVmu8PYOR00letCkrU71qTfKnzhQgn7by/QJvlJGUAofMt+jyXJTxA== - dependencies: - browserslist "^4.0.1" - caniuse-lite "^1.0.30000865" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^7.0.1" - postcss-value-parser "^3.2.3" - - aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - - aws4@^1.6.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" - integrity sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w== - - babel-jest@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.1.0.tgz#441e23ef75ded3bd547e300ac3194cef87b55190" - integrity sha512-MLcagnVrO9ybQGLEfZUqnOzv36iQzU7Bj4elm39vCukumLVSfoX+tRy3/jW7lUKc7XdpRmB/jech6L/UCsSZjw== - dependencies: - babel-plugin-istanbul "^5.1.0" - babel-preset-jest "^24.1.0" - chalk "^2.4.2" - slash "^2.0.0" - - babel-plugin-istanbul@^5.1.0: - version "5.1.4" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.4.tgz#841d16b9a58eeb407a0ddce622ba02fe87a752ba" - integrity sha512-dySz4VJMH+dpndj0wjJ8JPs/7i1TdSPb1nRrn56/92pKOF9VKC1FMFJmMXjzlGGusnCAqujP6PBCiKq0sVA+YQ== - dependencies: - find-up "^3.0.0" - istanbul-lib-instrument "^3.3.0" - test-exclude "^5.2.3" - - babel-plugin-jest-hoist@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.1.0.tgz#dfecc491fb15e2668abbd690a697a8fd1411a7f8" - integrity sha512-gljYrZz8w1b6fJzKcsfKsipSru2DU2DmQ39aB6nV3xQ0DDv3zpIzKGortA5gknrhNnPN8DweaEgrnZdmbGmhnw== - - babel-preset-jest@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.1.0.tgz#83bc564fdcd4903641af65ec63f2f5de6b04132e" - integrity sha512-FfNLDxFWsNX9lUmtwY7NheGlANnagvxq8LZdl5PKnVG3umP+S/g0XbVBfwtA4Ai3Ri/IMkWabBz3Tyk9wdspcw== - dependencies: - "@babel/plugin-syntax-object-rest-spread" "^7.0.0" - babel-plugin-jest-hoist "^24.1.0" - - babylon@^6.15.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - - bail@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.3.tgz#63cfb9ddbac829b02a3128cd53224be78e6c21a3" - integrity sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg== - - balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - - base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - - bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - - big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - - brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - - braces@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - - browser-process-hrtime@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz#425d68a58d3447f02a04aa894187fce8af8b7b8e" - integrity sha1-Ql1opY00R/AqBKqJQYf86K+Le44= - - browser-resolve@^1.11.3: - version "1.11.3" - resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" - integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ== - dependencies: - resolve "1.1.7" - - browserslist@^4.0.1: - version "4.7.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.1.tgz#bd400d1aea56538580e8c4d5f1c54ac11b5ab468" - integrity sha512-QtULFqKIAtiyNx7NhZ/p4rB8m3xDozVo/pi5VgTlADLF2tNigz/QH+v0m5qhn7XfHT7u+607NcCNOnC0HZAlMg== - dependencies: - caniuse-lite "^1.0.30000999" - electron-to-chromium "^1.3.284" - node-releases "^1.1.36" - - bser@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" - integrity sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk= - dependencies: - node-int64 "^0.4.0" - - buffer-crc32@^0.2.5: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= - - buffer-from@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.0.tgz#87fcaa3a298358e0ade6e442cfce840740d1ad04" - integrity sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ== - - builtin-modules@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= - - builtin-modules@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.1.0.tgz#aad97c15131eb76b65b50ef208e7584cd76a7484" - integrity sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw== - - cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - - call-me-maybe@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" - integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= - - caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= - dependencies: - callsites "^2.0.0" - - caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= - dependencies: - caller-callsite "^2.0.0" - - callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= - - callsites@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.0.0.tgz#fb7eb569b72ad7a45812f93fd9430a3e410b3dd3" - integrity sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw== - - camelcase-keys@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" - integrity sha1-oqpfsa9oh1glnDLBQUJteJI7m3c= - dependencies: - camelcase "^4.1.0" - map-obj "^2.0.0" - quick-lru "^1.0.0" - - camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= - - camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - - caniuse-lite@^1.0.30000865, caniuse-lite@^1.0.30000999: - version "1.0.30001002" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001002.tgz#ba999a737b1abd5bf0fd47efe43a09b9cadbe9b0" - integrity sha512-pRuxPE8wdrWmVPKcDmJJiGBxr6lFJq4ivdSeo9FTmGj5Rb8NX3Mby2pARG57MXF15hYAhZ0nHV5XxT2ig4bz3g== - - capture-exit@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f" - integrity sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28= - dependencies: - rsvp "^3.3.3" - - caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - - ccount@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.3.tgz#f1cec43f332e2ea5a569fd46f9f5bde4e6102aff" - integrity sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw== - - chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - - character-entities-html4@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.2.tgz#c44fdde3ce66b52e8d321d6c1bf46101f0150610" - integrity sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw== - - character-entities-legacy@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz#7c6defb81648498222c9855309953d05f4d63a9c" - integrity sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA== - - character-entities@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.2.tgz#58c8f371c0774ef0ba9b2aca5f00d8f100e6e363" - integrity sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ== - - character-reference-invalid@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz#21e421ad3d84055952dab4a43a04e73cd425d3ed" - integrity sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ== - - chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - - chownr@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" - integrity sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE= - - ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - - class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - - cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= - dependencies: - restore-cursor "^2.0.0" - - cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= - - cliui@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" - integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== - dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrap-ansi "^2.0.0" - - clone-regexp@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-1.0.1.tgz#051805cd33173375d82118fc0918606da39fd60f" - integrity sha512-Fcij9IwRW27XedRIJnSOEupS7RVcXtObJXbcUOX93UCLqqOdRpkvzKywOOSizmEK/Is3S/RHX9dLdfo6R1Q1mw== - dependencies: - is-regexp "^1.0.0" - is-supported-regexp-flag "^1.0.0" - - co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - - code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - - codecov@^3.2.0: - version "3.6.5" - resolved "https://registry.yarnpkg.com/codecov/-/codecov-3.6.5.tgz#d73ce62e8a021f5249f54b073e6f2d6a513f172a" - integrity sha512-v48WuDMUug6JXwmmfsMzhCHRnhUf8O3duqXvltaYJKrO1OekZWpB/eH6iIoaxMl8Qli0+u3OxptdsBOYiD7VAQ== - dependencies: - argv "0.0.2" - ignore-walk "3.0.3" - js-yaml "3.13.1" - teeny-request "6.0.1" - urlgrey "0.4.4" - - collapse-white-space@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.4.tgz#ce05cf49e54c3277ae573036a26851ba430a0091" - integrity sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw== - - collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - - color-convert@^1.9.0: - version "1.9.2" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" - integrity sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg== - dependencies: - color-name "1.1.1" - - color-name@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" - integrity sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok= - - combined-stream@1.0.6, combined-stream@~1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" - integrity sha1-cj599ugBrFYTETp+RFqbactjKBg= - dependencies: - delayed-stream "~1.0.0" - - commander@~2.20.3: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - - compare-versions@^3.2.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.3.1.tgz#1ede3172b713c15f7c7beb98cb74d2d82576dad3" - integrity sha512-GkIcfJ9sDt4+gS+RWH3X+kR7ezuKdu3fg2oA9nRA8HZoqZwAKv3ml3TyfB9OyV2iFXxCw7q5XfV6SyPbSCT2pw== - - component-emitter@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= - - concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - - console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - - convert-source-map@^1.1.0, convert-source-map@^1.4.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" - integrity sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU= - - copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - - core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - - cosmiconfig@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" - integrity sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ== - dependencies: - is-directory "^0.3.1" - js-yaml "^3.9.0" - parse-json "^4.0.0" - require-from-string "^2.0.1" - - cosmiconfig@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.1.0.tgz#6c5c35e97f37f985061cdf653f114784231185cf" - integrity sha512-kCNPvthka8gvLtzAxQXvWo4FxqRB+ftRZyPZNuab5ngvM9Y7yw7hbEysglptLgpkGX9nAOKTBVkHUAe8xtYR6Q== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.9.0" - lodash.get "^4.4.2" - parse-json "^4.0.0" - - cross-spawn@^6.0.0, cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - - cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": - version "0.3.4" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.4.tgz#8cd52e8a3acfd68d3aed38ee0a640177d2f9d797" - integrity sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog== - - cssstyle@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.0.0.tgz#79b16d51ec5591faec60e688891f15d2a5705129" - integrity sha512-Bpuh47j2mRMY60X90mXaJAEtJwxvA2roZzbgwAXYhMbmwmakdRr4Cq9L5SkleKJNLOKqHIa2YWyOXDX3VgggSQ== - dependencies: - cssom "0.3.x" - - currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= - dependencies: - array-find-index "^1.0.1" - - dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - - data-urls@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.0.0.tgz#24802de4e81c298ea8a9388bb0d8e461c774684f" - integrity sha512-ai40PPQR0Fn1lD2PPie79CibnlMN2AYiDhwFX/rZHVsxbs5kNJSjegqXIprhouGXlRdEnfybva7kqRGnB6mypA== - dependencies: - abab "^1.0.4" - whatwg-mimetype "^2.0.0" - whatwg-url "^6.4.0" - - debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - - debug@^2.1.2, debug@^2.2.0, debug@^2.3.3: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - - decamelize-keys@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" - integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= - dependencies: - decamelize "^1.1.0" - map-obj "^1.0.0" - - decamelize@^1.1.0, decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - - decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - - deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - - deep-freeze@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/deep-freeze/-/deep-freeze-0.0.1.tgz#3a0b0005de18672819dfd38cd31f91179c893e84" - integrity sha1-OgsABd4YZygZ39OM0x+RF5yJPoQ= - - deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - - deepmerge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" - integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== - - default-require-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7" - integrity sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc= - dependencies: - strip-bom "^3.0.0" - - define-properties@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" - integrity sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ= - dependencies: - foreach "^2.0.5" - object-keys "^1.0.8" - - define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - - define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - - define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - - delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - - delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - - detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - - detect-newline@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" - integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I= - - diff-sequences@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.0.0.tgz#cdf8e27ed20d8b8d3caccb4e0c0d8fe31a173013" - integrity sha512-46OkIuVGBBnrC0soO/4LHu5LHGHx0uhP65OVz8XOrAJpqiCB2aVIuESvjI1F9oqebuvY8lekS1pt6TN7vt7qsw== - - diffable-html@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/diffable-html/-/diffable-html-4.0.0.tgz#eb44a189785115bacd04829f31658fcd3c0ce590" - integrity sha512-keJdgy2qBkdrrnwP1YE6e834d4Y+mV0aRFzk8w7WzyAJVbQVfcJltSmUWB3r/NOoO/0jt7RdJlvy5ioyqvmQcw== - dependencies: - htmlparser2 "^3.9.2" - - dir-glob@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" - integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw== - dependencies: - path-type "^3.0.0" - - doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - - dom-serializer@0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" - integrity sha1-BzxpdUbOB4DOI75KKOKT5AvDDII= - dependencies: - domelementtype "~1.1.1" - entities "~1.1.1" - - domelementtype@1, domelementtype@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== - - domelementtype@~1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" - integrity sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs= - - domexception@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" - integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== - dependencies: - webidl-conversions "^4.0.2" - - domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - - domutils@^1.5.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - - dot-prop@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" - integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== - dependencies: - is-obj "^1.0.0" - - ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" - integrity sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU= - dependencies: - jsbn "~0.1.0" - - electron-to-chromium@^1.3.284: - version "1.3.293" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.293.tgz#e52a30026b89276e211be36083a4d7136fd480ea" - integrity sha512-DQSBRuU2Z1vG+CEWUIfCEVMHtuaGlhVojzg39mX5dx7PLSFDJ7DSrGUWzaPFFgWR1jo26hj1nXXRQZvFwk7F8w== - - emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - - emojis-list@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= - - end-of-stream@^1.1.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== - dependencies: - once "^1.4.0" - - entities@^1.1.1, entities@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" - integrity sha1-blwtClYhtdra7O+AuQ7ftc13cvA= - - error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - - es-abstract@^1.5.1: - version "1.13.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" - integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== - dependencies: - es-to-primitive "^1.2.0" - function-bind "^1.1.1" - has "^1.0.3" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-keys "^1.0.12" - - es-to-primitive@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - - escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - - escodegen@^1.9.1: - version "1.11.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.0.tgz#b27a9389481d5bfd5bec76f7bb1eb3f8f4556589" - integrity sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw== - dependencies: - esprima "^3.1.3" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - - eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - - eslint-utils@^1.3.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab" - integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q== - dependencies: - eslint-visitor-keys "^1.0.0" - - eslint-visitor-keys@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" - integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== - - eslint@^5.14.1: - version "5.16.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" - integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.9.1" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" - doctrine "^3.0.0" - eslint-scope "^4.0.3" - eslint-utils "^1.3.1" - eslint-visitor-keys "^1.0.0" - espree "^5.0.1" - esquery "^1.0.1" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.7.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - inquirer "^6.2.2" - js-yaml "^3.13.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.11" - minimatch "^3.0.4" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^5.5.1" - strip-ansi "^4.0.0" - strip-json-comments "^2.0.1" - table "^5.2.3" - text-table "^0.2.0" - - espree@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" - integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== - dependencies: - acorn "^6.0.7" - acorn-jsx "^5.0.0" - eslint-visitor-keys "^1.0.0" - - esprima@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" - integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= - - esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - - esquery@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== - dependencies: - estraverse "^4.0.0" - - esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== - dependencies: - estraverse "^4.1.0" - - estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= - - estree-walker@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" - integrity sha1-va/oCVOD2EFNXcLs9MkXO225QS4= - - estree-walker@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" - integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== - - esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= - - exec-sh@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36" - integrity sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw== - dependencies: - merge "^1.2.0" - - execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - - execall@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execall/-/execall-1.0.0.tgz#73d0904e395b3cab0658b08d09ec25307f29bb73" - integrity sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M= - dependencies: - clone-regexp "^1.0.0" - - exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= - - expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - - expect@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-24.1.0.tgz#88e73301c4c785cde5f16da130ab407bdaf8c0f2" - integrity sha512-lVcAPhaYkQcIyMS+F8RVwzbm1jro20IG8OkvxQ6f1JfqhVZyyudCwYogQ7wnktlf14iF3ii7ArIUO/mqvrW9Gw== - dependencies: - ansi-styles "^3.2.0" - jest-get-type "^24.0.0" - jest-matcher-utils "^24.0.0" - jest-message-util "^24.0.0" - jest-regex-util "^24.0.0" - - extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - - extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - - extend@^3.0.0, extend@~3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - - external-editor@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" - integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - - extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - - extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - - extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= - - fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= - - fast-deep-equal@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= - - fast-glob@^2.2.6: - version "2.2.6" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.6.tgz#a5d5b697ec8deda468d85a74035290a025a95295" - integrity sha512-0BvMaZc1k9F+MeWWMe8pL6YltFzZYcJsYU7D4JyDA6PAczaXvxqQQ/z+mDF7/4Mw01DeUc+i3CTKajnkANkV4w== - dependencies: - "@mrmlnc/readdir-enhanced" "^2.2.1" - "@nodelib/fs.stat" "^1.1.2" - glob-parent "^3.1.0" - is-glob "^4.0.0" - merge2 "^1.2.3" - micromatch "^3.1.10" - - fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= - - fast-levenshtein@~2.0.4: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - - fb-watchman@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" - integrity sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg= - dependencies: - bser "^2.0.0" - - figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= - dependencies: - escape-string-regexp "^1.0.5" - - file-entry-cache@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-4.0.0.tgz#633567d15364aefe0b299e1e217735e8f3a9f6e8" - integrity sha512-AVSwsnbV8vH/UVbvgEhf3saVQXORNv0ZzSkvkhQIaia5Tia+JhGTaa/ePUSVoPHQyGayQNmYfkzFi3WZV5zcpA== - dependencies: - flat-cache "^2.0.1" - - file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" - - file-loader@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-3.0.1.tgz#f8e0ba0b599918b51adfe45d66d1e771ad560faa" - integrity sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw== - dependencies: - loader-utils "^1.0.2" - schema-utils "^1.0.0" - - fileset@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0" - integrity sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA= - dependencies: - glob "^7.0.3" - minimatch "^3.0.3" - - fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - - find-up@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - - find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - - flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== - dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" - - flatted@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" - integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== - - flow-bin@^0.102.0: - version "0.102.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.102.0.tgz#3d5de44bcc26d26585e932b3201988b766f9b380" - integrity sha512-mYon6noeLO0Q5SbiWULLQeM1L96iuXnRtYMd47j3bEWXAwUW9EnwNWcn+cZg/jC/Dg4Wj/jnkdTDEuFtbeu1ww== - - flow-parser@^0.132.0: - version "0.132.0" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.132.0.tgz#68c9aea4cfd84577337559a6f121ef3ab687a251" - integrity sha512-y1P37zDCPSdphlk+w+roCqcOar6iQdNaAJldJ6xx5/2r4ZRv4KHO+qL+AXwPWp+34eN+oPxPjWnU7GybJnyISQ== - - flow-remove-types@^1.1.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/flow-remove-types/-/flow-remove-types-1.2.3.tgz#6131aefc7da43364bb8b479758c9dec7735d1a18" - integrity sha512-ypq/U3V+t9atYiOuSJd40tekCra03EHKoRsiK/wXGrsZimuum0kdwVY7Yv0HTaoXgHW1WiayomYd+Q3kkvPl9Q== - dependencies: - babylon "^6.15.0" - vlq "^0.2.1" - - flow-remove-types@^2.132.0: - version "2.132.0" - resolved "https://registry.yarnpkg.com/flow-remove-types/-/flow-remove-types-2.132.0.tgz#7adc416336f96eb00a8603df4aef919e8b648e28" - integrity sha512-J1EfutfdC68xEZ8i44Hdlaa3MnONuQQB4/+wtnw/ontdcwuz/yGAVQ/O35dFIqNaQoCUWNDN1mHHagbRYLfihQ== - dependencies: - flow-parser "^0.132.0" - pirates "^3.0.2" - vlq "^0.2.1" - - for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - - foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= - - forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - - form-data@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" - integrity sha1-SXBJi+YEwgwAXU9cI67NIda0kJk= - dependencies: - asynckit "^0.4.0" - combined-stream "1.0.6" - mime-types "^2.1.12" - - fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - - fs-extra@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - - fs-minipass@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" - integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== - dependencies: - minipass "^2.2.1" - - fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - - fsevents@^1.2.3: - version "1.2.4" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" - integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg== - dependencies: - nan "^2.9.2" - node-pre-gyp "^0.10.0" - - function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - - functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= - - gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - - get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== - - get-stdin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" - integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== - - get-stream@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - - get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - - getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - - glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - - glob-to-regexp@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" - integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= - - glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - - global-modules@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" - integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== - dependencies: - global-prefix "^3.0.0" - - global-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" - integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== - dependencies: - ini "^1.3.5" - kind-of "^6.0.2" - which "^1.3.1" - - globals@^11.1.0, globals@^11.7.0: - version "11.7.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673" - integrity sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg== - - globby@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-9.0.0.tgz#3800df736dc711266df39b4ce33fe0d481f94c23" - integrity sha512-q0qiO/p1w/yJ0hk8V9x1UXlgsXUxlGd0AHUOXZVXBO6aznDtpx7M8D1kBrCAItoPm+4l8r6ATXV1JpjY2SBQOw== - dependencies: - array-union "^1.0.2" - dir-glob "^2.2.1" - fast-glob "^2.2.6" - glob "^7.1.3" - ignore "^4.0.3" - pify "^4.0.1" - slash "^2.0.0" - - globjoin@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43" - integrity sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM= - - gonzales-pe@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.2.3.tgz#41091703625433285e0aee3aa47829fc1fbeb6f2" - integrity sha512-Kjhohco0esHQnOiqqdJeNz/5fyPkOMD/d6XVjwTAoPGUFh0mCollPUTUTa2OZy4dYNAqlPIQdTiNzJTWdd9Htw== - dependencies: - minimist "1.1.x" - - graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6: - version "4.1.15" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" - integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== - - growly@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" - integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= - - handlebars@^4.1.0: - version "4.5.3" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482" - integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA== - dependencies: - neo-async "^2.6.0" - optimist "^0.6.1" - source-map "^0.6.1" - optionalDependencies: - uglify-js "^3.1.4" - - har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - - har-validator@~5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" - integrity sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0= - dependencies: - ajv "^5.1.0" - har-schema "^2.0.0" - - has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - - has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= - - has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - - has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - - has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - - has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - - has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - - has@^1.0.1, has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - - hosted-git-info@^2.1.4: - version "2.7.1" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== - - html-encoding-sniffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" - integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw== - dependencies: - whatwg-encoding "^1.0.1" - - html-tags@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b" - integrity sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos= - - htmlparser2@^3.10.0, htmlparser2@^3.9.2: - version "3.10.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== - dependencies: - domelementtype "^1.3.1" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.1.1" - - http-proxy-agent@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" - integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== - dependencies: - "@tootallnate/once" "1" - agent-base "6" - debug "4" - - http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - - https-proxy-agent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz#702b71fb5520a132a66de1f67541d9e62154d82b" - integrity sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg== - dependencies: - agent-base "5" - debug "4" - - iconv-lite@0.4.19: - version "0.4.19" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" - integrity sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ== - - iconv-lite@^0.4.24, iconv-lite@^0.4.4: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - - ignore-walk@3.0.3, ignore-walk@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" - integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== - dependencies: - minimatch "^3.0.4" - - ignore@^4.0.3, ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - - ignore@^5.0.4: - version "5.0.5" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.0.5.tgz#c663c548d6ce186fb33616a8ccb5d46e56bdbbf9" - integrity sha512-kOC8IUb8HSDMVcYrDVezCxpJkzSQWTAzf3olpKM6o9rM5zpojx23O0Fl8Wr4+qJ6ZbPEHqf1fdwev/DS7v7pmA== - - import-cwd@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" - integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk= - dependencies: - import-from "^2.1.0" - - import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - - import-fresh@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390" - integrity sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - - import-from@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" - integrity sha1-M1238qev/VOqpHHUuAId7ja387E= - dependencies: - resolve-from "^3.0.0" - - import-lazy@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-3.1.0.tgz#891279202c8a2280fdbd6674dbd8da1a1dfc67cc" - integrity sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ== - - import-local@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" - integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== - dependencies: - pkg-dir "^3.0.0" - resolve-cwd "^2.0.0" - - imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - - indent-string@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" - integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= - - indexes-of@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= - - inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - - inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - - ini@^1.3.5, ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - - inquirer@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.2.tgz#46941176f65c9eb20804627149b743a218f25406" - integrity sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA== - dependencies: - ansi-escapes "^3.2.0" - chalk "^2.4.2" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^2.0.0" - lodash "^4.17.11" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^2.1.0" - strip-ansi "^5.0.0" - through "^2.3.6" - - invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - - invert-kv@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" - integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== - - is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - - is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - - is-alphabetical@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.2.tgz#1fa6e49213cb7885b75d15862fb3f3d96c884f41" - integrity sha512-V0xN4BYezDHcBSKb1QHUFMlR4as/XEuCZBzMJUU4n7+Cbt33SmUnSol+pnXFvLxSHNq2CemUXNdaXV6Flg7+xg== - - is-alphanumeric@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz#4a9cef71daf4c001c1d81d63d140cf53fd6889f4" - integrity sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ= - - is-alphanumerical@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz#1138e9ae5040158dc6ff76b820acd6b7a181fd40" - integrity sha512-pyfU/0kHdISIgslFfZN9nfY1Gk3MquQgUm1mJTjdkEPpkAKNWuBTSqFwewOpR7N351VkErCiyV71zX7mlQQqsg== - dependencies: - is-alphabetical "^1.0.0" - is-decimal "^1.0.0" - - is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - - is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - - is-buffer@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" - integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== - - is-builtin-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74= - dependencies: - builtin-modules "^1.0.0" - - is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== - - is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - - is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - - is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - - is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= - - is-decimal@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.2.tgz#894662d6a8709d307f3a276ca4339c8fa5dff0ff" - integrity sha512-TRzl7mOCchnhchN+f3ICUCzYvL9ul7R+TYOsZ8xia++knyZAJfv/uA1FvQXsAnYIl1T3B2X5E/J7Wb1QXiIBXg== - - is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - - is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - - is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= - - is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - - is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - - is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - - is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - - is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - - is-generator-fn@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.0.0.tgz#038c31b774709641bda678b1f06a4e3227c10b3e" - integrity sha512-elzyIdM7iKoFHzcrndIqjYomImhxrFRnGP3galODoII4TB9gI7mZ+FnlLQmmjf27SxHS2gKEeyhX5/+YRS6H9g== - - is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - - is-glob@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" - integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A= - dependencies: - is-extglob "^2.1.1" - - is-hexadecimal@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz#b6e710d7d07bb66b98cb8cece5c9b4921deeb835" - integrity sha512-but/G3sapV3MNyqiDBLrOi4x8uCIw0RY3o/Vb5GT0sMFHrVV7731wFSVy41T5FO1og7G0gXLJh0MkgPRouko/A== - - is-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" - integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= - - is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - - is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - - is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - - is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - - is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= - - is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= - dependencies: - has "^1.0.1" - - is-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= - - is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - - is-supported-regexp-flag@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.1.tgz#21ee16518d2c1dd3edd3e9a0d57e50207ac364ca" - integrity sha512-3vcJecUUrpgCqc/ca0aWeNu64UGgxcvO60K/Fkr1N6RSvfGCTU60UKN68JDmKokgba0rFFJs12EnzOQa14ubKQ== - - is-symbol@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== - dependencies: - has-symbols "^1.0.0" - - is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - - is-whitespace-character@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz#ede53b4c6f6fb3874533751ec9280d01928d03ed" - integrity sha512-SzM+T5GKUCtLhlHFKt2SDAX2RFzfS6joT91F2/WSi9LxgFdsnhfPK/UIA+JhRR2xuyLdrCys2PiFDrtn1fU5hQ== - - is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - - is-word-character@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.2.tgz#46a5dac3f2a1840898b91e576cd40d493f3ae553" - integrity sha512-T3FlsX8rCHAH8e7RE7PfOPZVFQlcV3XRF9eOOBQ1uf70OxO7CjjSOjeImMPCADBdYWcStAbVbYvJ1m2D3tb+EA== - - isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - - isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - - isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - - isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - - isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - - istanbul-api@^2.0.8: - version "2.1.1" - resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-2.1.1.tgz#194b773f6d9cbc99a9258446848b0f988951c4d0" - integrity sha512-kVmYrehiwyeBAk/wE71tW6emzLiHGjYIiDrc8sfyty4F8M02/lrgXSm+R1kXysmF20zArvmZXjlE/mg24TVPJw== - dependencies: - async "^2.6.1" - compare-versions "^3.2.1" - fileset "^2.0.3" - istanbul-lib-coverage "^2.0.3" - istanbul-lib-hook "^2.0.3" - istanbul-lib-instrument "^3.1.0" - istanbul-lib-report "^2.0.4" - istanbul-lib-source-maps "^3.0.2" - istanbul-reports "^2.1.1" - js-yaml "^3.12.0" - make-dir "^1.3.0" - minimatch "^3.0.4" - once "^1.4.0" - - istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.3, istanbul-lib-coverage@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" - integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== - - istanbul-lib-hook@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.3.tgz#e0e581e461c611be5d0e5ef31c5f0109759916fb" - integrity sha512-CLmEqwEhuCYtGcpNVJjLV1DQyVnIqavMLFHV/DP+np/g3qvdxu3gsPqYoJMXm15sN84xOlckFB3VNvRbf5yEgA== - dependencies: - append-transform "^1.0.0" - - istanbul-lib-instrument@^3.0.1, istanbul-lib-instrument@^3.1.0, istanbul-lib-instrument@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630" - integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA== - dependencies: - "@babel/generator" "^7.4.0" - "@babel/parser" "^7.4.3" - "@babel/template" "^7.4.0" - "@babel/traverse" "^7.4.3" - "@babel/types" "^7.4.0" - istanbul-lib-coverage "^2.0.5" - semver "^6.0.0" - - istanbul-lib-report@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.4.tgz#bfd324ee0c04f59119cb4f07dab157d09f24d7e4" - integrity sha512-sOiLZLAWpA0+3b5w5/dq0cjm2rrNdAfHWaGhmn7XEFW6X++IV9Ohn+pnELAl9K3rfpaeBfbmH9JU5sejacdLeA== - dependencies: - istanbul-lib-coverage "^2.0.3" - make-dir "^1.3.0" - supports-color "^6.0.0" - - istanbul-lib-source-maps@^3.0.1, istanbul-lib-source-maps@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.2.tgz#f1e817229a9146e8424a28e5d69ba220fda34156" - integrity sha512-JX4v0CiKTGp9fZPmoxpu9YEkPbEqCqBbO3403VabKjH+NRXo72HafD5UgnjTEqHL2SAjaZK1XDuDOkn6I5QVfQ== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^2.0.3" - make-dir "^1.3.0" - rimraf "^2.6.2" - source-map "^0.6.1" - - istanbul-reports@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.1.1.tgz#72ef16b4ecb9a4a7bd0e2001e00f95d1eec8afa9" - integrity sha512-FzNahnidyEPBCI0HcufJoSEoKykesRlFcSzQqjH9x0+LC8tnnE/p/90PBLu8iZTxr8yYZNyTtiAujUqyN+CIxw== - dependencies: - handlebars "^4.1.0" - - jest-changed-files@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.0.0.tgz#c02c09a8cc9ca93f513166bc773741bd39898ff7" - integrity sha512-nnuU510R9U+UX0WNb5XFEcsrMqriSiRLeO9KWDFgPrpToaQm60prfQYpxsXigdClpvNot5bekDY440x9dNGnsQ== - dependencies: - execa "^1.0.0" - throat "^4.0.0" - - jest-cli@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.1.0.tgz#f7cc98995f36e7210cce3cbb12974cbf60940843" - integrity sha512-U/iyWPwOI0T1CIxVLtk/2uviOTJ/OiSWJSe8qt6X1VkbbgP+nrtLJlmT9lPBe4lK78VNFJtrJ7pttcNv/s7yCw== - dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.1" - exit "^0.1.2" - glob "^7.1.2" - graceful-fs "^4.1.15" - import-local "^2.0.0" - is-ci "^2.0.0" - istanbul-api "^2.0.8" - istanbul-lib-coverage "^2.0.2" - istanbul-lib-instrument "^3.0.1" - istanbul-lib-source-maps "^3.0.1" - jest-changed-files "^24.0.0" - jest-config "^24.1.0" - jest-environment-jsdom "^24.0.0" - jest-get-type "^24.0.0" - jest-haste-map "^24.0.0" - jest-message-util "^24.0.0" - jest-regex-util "^24.0.0" - jest-resolve-dependencies "^24.1.0" - jest-runner "^24.1.0" - jest-runtime "^24.1.0" - jest-snapshot "^24.1.0" - jest-util "^24.0.0" - jest-validate "^24.0.0" - jest-watcher "^24.0.0" - jest-worker "^24.0.0" - micromatch "^3.1.10" - node-notifier "^5.2.1" - p-each-series "^1.0.0" - pirates "^4.0.0" - prompts "^2.0.1" - realpath-native "^1.0.0" - rimraf "^2.5.4" - slash "^2.0.0" - string-length "^2.0.0" - strip-ansi "^5.0.0" - which "^1.2.12" - yargs "^12.0.2" - - jest-config@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.1.0.tgz#6ea6881cfdd299bc86cc144ee36d937c97c3850c" - integrity sha512-FbbRzRqtFC6eGjG5VwsbW4E5dW3zqJKLWYiZWhB0/4E5fgsMw8GODLbGSrY5t17kKOtCWb/Z7nsIThRoDpuVyg== - dependencies: - "@babel/core" "^7.1.0" - babel-jest "^24.1.0" - chalk "^2.0.1" - glob "^7.1.1" - jest-environment-jsdom "^24.0.0" - jest-environment-node "^24.0.0" - jest-get-type "^24.0.0" - jest-jasmine2 "^24.1.0" - jest-regex-util "^24.0.0" - jest-resolve "^24.1.0" - jest-util "^24.0.0" - jest-validate "^24.0.0" - micromatch "^3.1.10" - pretty-format "^24.0.0" - realpath-native "^1.0.2" - - jest-diff@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.0.0.tgz#a3e5f573dbac482f7d9513ac9cfa21644d3d6b34" - integrity sha512-XY5wMpRaTsuMoU+1/B2zQSKQ9RdE9gsLkGydx3nvApeyPijLA8GtEvIcPwISRCer+VDf9W1mStTYYq6fPt8ryA== - dependencies: - chalk "^2.0.1" - diff-sequences "^24.0.0" - jest-get-type "^24.0.0" - pretty-format "^24.0.0" - - jest-docblock@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.0.0.tgz#54d77a188743e37f62181a91a01eb9222289f94e" - integrity sha512-KfAKZ4SN7CFOZpWg4i7g7MSlY0M+mq7K0aMqENaG2vHuhC9fc3vkpU/iNN9sOus7v3h3Y48uEjqz3+Gdn2iptA== - dependencies: - detect-newline "^2.1.0" - - jest-each@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.0.0.tgz#10987a06b21c7ffbfb7706c89d24c52ed864be55" - integrity sha512-gFcbY4Cu55yxExXMkjrnLXov3bWO3dbPAW7HXb31h/DNWdNc/6X8MtxGff8nh3/MjkF9DpVqnj0KsPKuPK0cpA== - dependencies: - chalk "^2.0.1" - jest-get-type "^24.0.0" - jest-util "^24.0.0" - pretty-format "^24.0.0" - - jest-environment-jsdom@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.0.0.tgz#5affa0654d6e44cd798003daa1a8701dbd6e4d11" - integrity sha512-1YNp7xtxajTRaxbylDc2pWvFnfDTH5BJJGyVzyGAKNt/lEULohwEV9zFqTgG4bXRcq7xzdd+sGFws+LxThXXOw== - dependencies: - jest-mock "^24.0.0" - jest-util "^24.0.0" - jsdom "^11.5.1" - - jest-environment-node@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.0.0.tgz#330948980656ed8773ce2e04eb597ed91e3c7190" - integrity sha512-62fOFcaEdU0VLaq8JL90TqwI7hLn0cOKOl8vY2n477vRkCJRojiRRtJVRzzCcgFvs6gqU97DNqX5R0BrBP6Rxg== - dependencies: - jest-mock "^24.0.0" - jest-util "^24.0.0" - - jest-get-type@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.0.0.tgz#36e72930b78e33da59a4f63d44d332188278940b" - integrity sha512-z6/Eyf6s9ZDGz7eOvl+fzpuJmN9i0KyTt1no37/dHu8galssxz5ZEgnc1KaV8R31q1khxyhB4ui/X5ZjjPk77w== - - jest-haste-map@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.0.0.tgz#e9ef51b2c9257384b4d6beb83bd48c65b37b5e6e" - integrity sha512-CcViJyUo41IQqttLxXVdI41YErkzBKbE6cS6dRAploCeutePYfUimWd3C9rQEWhX0YBOQzvNsC0O9nYxK2nnxQ== - dependencies: - fb-watchman "^2.0.0" - graceful-fs "^4.1.15" - invariant "^2.2.4" - jest-serializer "^24.0.0" - jest-util "^24.0.0" - jest-worker "^24.0.0" - micromatch "^3.1.10" - sane "^3.0.0" - - jest-jasmine2@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.1.0.tgz#8377324b967037c440f0a549ee0bbd9912055db6" - integrity sha512-H+o76SdSNyCh9fM5K8upK45YTo/DiFx5w2YAzblQebSQmukDcoVBVeXynyr7DDnxh+0NTHYRCLwJVf3tC518wg== - dependencies: - "@babel/traverse" "^7.1.0" - chalk "^2.0.1" - co "^4.6.0" - expect "^24.1.0" - is-generator-fn "^2.0.0" - jest-each "^24.0.0" - jest-matcher-utils "^24.0.0" - jest-message-util "^24.0.0" - jest-snapshot "^24.1.0" - jest-util "^24.0.0" - pretty-format "^24.0.0" - throat "^4.0.0" - - jest-leak-detector@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.0.0.tgz#78280119fd05ee98317daee62cddb3aa537a31c6" - integrity sha512-ZYHJYFeibxfsDSKowjDP332pStuiFT2xfc5R67Rjm/l+HFJWJgNIOCOlQGeXLCtyUn3A23+VVDdiCcnB6dTTrg== - dependencies: - pretty-format "^24.0.0" - - jest-matcher-utils@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.0.0.tgz#fc9c41cfc49b2c3ec14e576f53d519c37729d579" - integrity sha512-LQTDmO+aWRz1Tf9HJg+HlPHhDh1E1c65kVwRFo5mwCVp5aQDzlkz4+vCvXhOKFjitV2f0kMdHxnODrXVoi+rlA== - dependencies: - chalk "^2.0.1" - jest-diff "^24.0.0" - jest-get-type "^24.0.0" - pretty-format "^24.0.0" - - jest-message-util@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.0.0.tgz#a07a141433b2c992dbaec68d4cbfe470ba289619" - integrity sha512-J9ROJIwz/IeC+eV1XSwnRK4oAwPuhmxEyYx1+K5UI+pIYwFZDSrfZaiWTdq0d2xYFw4Xiu+0KQWsdsQpgJMf3Q== - dependencies: - "@babel/code-frame" "^7.0.0" - chalk "^2.0.1" - micromatch "^3.1.10" - slash "^2.0.0" - stack-utils "^1.0.1" - - jest-mock@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.0.0.tgz#9a4b53e01d66a0e780f7d857462d063e024c617d" - integrity sha512-sQp0Hu5fcf5NZEh1U9eIW2qD0BwJZjb63Yqd98PQJFvf/zzUTBoUAwv/Dc/HFeNHIw1f3hl/48vNn+j3STaI7A== - - jest-regex-util@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.0.0.tgz#4feee8ec4a358f5bee0a654e94eb26163cb9089a" - integrity sha512-Jv/uOTCuC+PY7WpJl2mpoI+WbY2ut73qwwO9ByJJNwOCwr1qWhEW2Lyi2S9ZewUdJqeVpEBisdEVZSI+Zxo58Q== - - jest-resolve-dependencies@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.1.0.tgz#78f738a2ec59ff4d00751d9da56f176e3f589f6c" - integrity sha512-2VwPsjd3kRPu7qe2cpytAgowCObk5AKeizfXuuiwgm1a9sijJDZe8Kh1sFj6FKvSaNEfCPlBVkZEJa2482m/Uw== - dependencies: - jest-regex-util "^24.0.0" - jest-snapshot "^24.1.0" - - jest-resolve@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.1.0.tgz#42ff0169b0ea47bfdbd0c52a0067ca7d022c7688" - integrity sha512-TPiAIVp3TG6zAxH28u/6eogbwrvZjBMWroSLBDkwkHKrqxB/RIdwkWDye4uqPlZIXWIaHtifY3L0/eO5Z0f2wg== - dependencies: - browser-resolve "^1.11.3" - chalk "^2.0.1" - realpath-native "^1.0.0" - - jest-runner@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.1.0.tgz#3686a2bb89ce62800da23d7fdc3da2c32792943b" - integrity sha512-CDGOkT3AIFl16BLL/OdbtYgYvbAprwJ+ExKuLZmGSCSldwsuU2dEGauqkpvd9nphVdAnJUcP12e/EIlnTX0QXg== - dependencies: - chalk "^2.4.2" - exit "^0.1.2" - graceful-fs "^4.1.15" - jest-config "^24.1.0" - jest-docblock "^24.0.0" - jest-haste-map "^24.0.0" - jest-jasmine2 "^24.1.0" - jest-leak-detector "^24.0.0" - jest-message-util "^24.0.0" - jest-runtime "^24.1.0" - jest-util "^24.0.0" - jest-worker "^24.0.0" - source-map-support "^0.5.6" - throat "^4.0.0" - - jest-runtime@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.1.0.tgz#7c157a2e776609e8cf552f956a5a19ec9c985214" - integrity sha512-59/BY6OCuTXxGeDhEMU7+N33dpMQyXq7MLK07cNSIY/QYt2QZgJ7Tjx+rykBI0skAoigFl0A5tmT8UdwX92YuQ== - dependencies: - "@babel/core" "^7.1.0" - babel-plugin-istanbul "^5.1.0" - chalk "^2.0.1" - convert-source-map "^1.4.0" - exit "^0.1.2" - fast-json-stable-stringify "^2.0.0" - glob "^7.1.3" - graceful-fs "^4.1.15" - jest-config "^24.1.0" - jest-haste-map "^24.0.0" - jest-message-util "^24.0.0" - jest-regex-util "^24.0.0" - jest-resolve "^24.1.0" - jest-snapshot "^24.1.0" - jest-util "^24.0.0" - jest-validate "^24.0.0" - micromatch "^3.1.10" - realpath-native "^1.0.0" - slash "^2.0.0" - strip-bom "^3.0.0" - write-file-atomic "2.4.1" - yargs "^12.0.2" - - jest-serializer-html@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/jest-serializer-html/-/jest-serializer-html-6.0.0.tgz#39ce49a42b3937d1687f93923814d21b47ae9a85" - integrity sha512-S855oT9Yt1T07I45+uRaLsH22TR5lAvgqBxKreqDKs6QmcaxzapGgKamc4J2KxMrPc2uDdWcuOaprcjIuVUxvQ== - dependencies: - diffable-html "^4.0.0" - - jest-serializer@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.0.0.tgz#522c44a332cdd194d8c0531eb06a1ee5afb4256b" - integrity sha512-9FKxQyrFgHtx3ozU+1a8v938ILBE7S8Ko3uiAVjT8Yfi2o91j/fj81jacCQZ/Ihjiff/VsUCXVgQ+iF1XdImOw== - - jest-snapshot@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.1.0.tgz#85e22f810357aa5994ab61f236617dc2205f2f5b" - integrity sha512-th6TDfFqEmXvuViacU1ikD7xFb7lQsPn2rJl7OEmnfIVpnrx3QNY2t3PE88meeg0u/mQ0nkyvmC05PBqO4USFA== - dependencies: - "@babel/types" "^7.0.0" - chalk "^2.0.1" - jest-diff "^24.0.0" - jest-matcher-utils "^24.0.0" - jest-message-util "^24.0.0" - jest-resolve "^24.1.0" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - pretty-format "^24.0.0" - semver "^5.5.0" - - jest-util@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.0.0.tgz#fd38fcafd6dedbd0af2944d7a227c0d91b68f7d6" - integrity sha512-QxsALc4wguYS7cfjdQSOr5HTkmjzkHgmZvIDkcmPfl1ib8PNV8QUWLwbKefCudWS0PRKioV+VbQ0oCUPC691fQ== - dependencies: - callsites "^3.0.0" - chalk "^2.0.1" - graceful-fs "^4.1.15" - is-ci "^2.0.0" - jest-message-util "^24.0.0" - mkdirp "^0.5.1" - slash "^2.0.0" - source-map "^0.6.0" - - jest-validate@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.0.0.tgz#aa8571a46983a6538328fef20406b4a496b6c020" - integrity sha512-vMrKrTOP4BBFIeOWsjpsDgVXATxCspC9S1gqvbJ3Tnn/b9ACsJmteYeVx9830UMV28Cob1RX55x96Qq3Tfad4g== - dependencies: - camelcase "^5.0.0" - chalk "^2.0.1" - jest-get-type "^24.0.0" - leven "^2.1.0" - pretty-format "^24.0.0" - - jest-watcher@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.0.0.tgz#20d44244d10b0b7312410aefd256c1c1eef68890" - integrity sha512-GxkW2QrZ4YxmW1GUWER05McjVDunBlKMFfExu+VsGmXJmpej1saTEKvONdx5RJBlVdpPI5x6E3+EDQSIGgl53g== - dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.1" - jest-util "^24.0.0" - string-length "^2.0.0" - - jest-worker@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.0.0.tgz#3d3483b077bf04f412f47654a27bba7e947f8b6d" - integrity sha512-s64/OThpfQvoCeHG963MiEZOAAxu8kHsaL/rCMF7lpdzo7vgF0CtPml9hfguOMgykgH/eOm4jFP4ibfHLruytg== - dependencies: - merge-stream "^1.0.1" - supports-color "^6.1.0" - - jest@^24.1.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-24.1.0.tgz#b1e1135caefcf2397950ecf7f90e395fde866fd2" - integrity sha512-+q91L65kypqklvlRFfXfdzUKyngQLOcwGhXQaLmVHv+d09LkNXuBuGxlofTFW42XMzu3giIcChchTsCNUjQ78A== - dependencies: - import-local "^2.0.0" - jest-cli "^24.1.0" - - "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - - js-yaml@3.13.1, js-yaml@^3.12.0, js-yaml@^3.12.1, js-yaml@^3.13.0, js-yaml@^3.9.0: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - - jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - - jsdom@^11.5.1: - version "11.12.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8" - integrity sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw== - dependencies: - abab "^2.0.0" - acorn "^5.5.3" - acorn-globals "^4.1.0" - array-equal "^1.0.0" - cssom ">= 0.3.2 < 0.4.0" - cssstyle "^1.0.0" - data-urls "^1.0.0" - domexception "^1.0.1" - escodegen "^1.9.1" - html-encoding-sniffer "^1.0.2" - left-pad "^1.3.0" - nwsapi "^2.0.7" - parse5 "4.0.0" - pn "^1.1.0" - request "^2.87.0" - request-promise-native "^1.0.5" - sax "^1.2.4" - symbol-tree "^3.2.2" - tough-cookie "^2.3.4" - w3c-hr-time "^1.0.1" - webidl-conversions "^4.0.2" - whatwg-encoding "^1.0.3" - whatwg-mimetype "^2.1.0" - whatwg-url "^6.4.1" - ws "^5.2.0" - xml-name-validator "^3.0.0" - - jsesc@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" - integrity sha1-5CGiqOINawgZ3yiQj3glJrlt0f4= - - json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - - json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= - - json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - - json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - - json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - - json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= - dependencies: - jsonify "~0.0.0" - - json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - - json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" - - json5@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" - integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ== - dependencies: - minimist "^1.2.0" - - jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= - optionalDependencies: - graceful-fs "^4.1.6" - - jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= - - jspngopt@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/jspngopt/-/jspngopt-0.2.0.tgz#a05e4625bc64ef06a54f11763bc90b75a2dcf815" - integrity sha1-oF5GJbxk7walTxF2O8kLdaLc+BU= - dependencies: - buffer-crc32 "^0.2.5" - - jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - - kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - - kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - - kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - - kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== - - kleur@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.2.tgz#83c7ec858a41098b613d5998a7b653962b504f68" - integrity sha512-3h7B2WRT5LNXOtQiAaWonilegHcPSf9nLVXlSTci8lu1dZUuui61+EsPEZqSVxY7rXYmB2DVKMQILxaO5WL61Q== - - known-css-properties@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.11.0.tgz#0da784f115ea77c76b81536d7052e90ee6c86a8a" - integrity sha512-bEZlJzXo5V/ApNNa5z375mJC6Nrz4vG43UgcSCrg2OHC+yuB6j0iDSrY7RQ/+PRofFB03wNIIt9iXIVLr4wc7w== - - lcid@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" - integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== - dependencies: - invert-kv "^2.0.0" - - left-pad@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" - integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA== - - leven@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" - integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA= - - levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - - load-json-file@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= - dependencies: - graceful-fs "^4.1.2" - parse-json "^4.0.0" - pify "^3.0.0" - strip-bom "^3.0.0" - - loader-utils@^1.0.2, loader-utils@^1.1.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" - integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== - dependencies: - big.js "^5.2.2" - emojis-list "^2.0.0" - json5 "^1.0.1" - - locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - - locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - - lodash.get@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - - lodash.sortby@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" - integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= - - lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4: - version "4.17.14" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" - integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== - - log-symbols@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== - dependencies: - chalk "^2.0.1" - - longest-streak@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.2.tgz#2421b6ba939a443bb9ffebf596585a50b4c38e2e" - integrity sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA== - - loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - - loud-rejection@^1.0.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" - - make-dir@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== - dependencies: - pify "^3.0.0" - - makeerror@1.0.x: - version "1.0.11" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" - integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= - dependencies: - tmpl "1.0.x" - - map-age-cleaner@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" - integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== - dependencies: - p-defer "^1.0.0" - - map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - - map-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= - - map-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" - integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk= - - map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - - markdown-escapes@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.2.tgz#e639cbde7b99c841c0bacc8a07982873b46d2122" - integrity sha512-lbRZ2mE3Q9RtLjxZBZ9+IMl68DKIXaVAhwvwn9pmjnPLS0h/6kyBMgNhqi1xFJ/2yv6cSyv0jbiZavZv93JkkA== - - markdown-table@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.2.tgz#c78db948fa879903a41bce522e3b96f801c63786" - integrity sha512-NcWuJFHDA8V3wkDgR/j4+gZx+YQwstPgfQDV8ndUeWWzta3dnDTBxpVzqS9lkmJAuV5YX35lmyojl6HO5JXAgw== - - mathml-tag-names@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.0.tgz#490b70e062ee24636536e3d9481e333733d00f2c" - integrity sha512-3Zs9P/0zzwTob2pdgT0CHZuMbnSUSp8MB1bddfm+HDmnFWHGT4jvEZRf+2RuPoa+cjdn/z25SEt5gFTqdhvJAg== - - mdast-util-compact@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz#cdb5f84e2b6a2d3114df33bd05d9cb32e3c4083a" - integrity sha1-zbX4TitqLTEU3zO9BdnLMuPECDo= - dependencies: - unist-util-modify-children "^1.0.0" - unist-util-visit "^1.1.0" - - mem@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-4.1.0.tgz#aeb9be2d21f47e78af29e4ac5978e8afa2ca5b8a" - integrity sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg== - dependencies: - map-age-cleaner "^0.1.1" - mimic-fn "^1.0.0" - p-is-promise "^2.0.0" - - meow@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4" - integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig== - dependencies: - camelcase-keys "^4.0.0" - decamelize-keys "^1.0.0" - loud-rejection "^1.0.0" - minimist-options "^3.0.1" - normalize-package-data "^2.3.4" - read-pkg-up "^3.0.0" - redent "^2.0.0" - trim-newlines "^2.0.0" - yargs-parser "^10.0.0" - - merge-stream@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" - integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE= - dependencies: - readable-stream "^2.0.1" - - merge2@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" - integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA== - - merge@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" - integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ== - - micromatch@^3.1.10, micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - - mime-db@~1.35.0: - version "1.35.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47" - integrity sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg== - - mime-types@^2.1.12, mime-types@~2.1.17: - version "2.1.19" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.19.tgz#71e464537a7ef81c15f2db9d97e913fc0ff606f0" - integrity sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw== - dependencies: - mime-db "~1.35.0" - - mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - - minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - - minimist-options@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" - integrity sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ== - dependencies: - arrify "^1.0.1" - is-plain-obj "^1.1.0" - - minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - - minimist@1.1.x: - version "1.1.3" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8" - integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag= - - minimist@^1.1.1, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - - minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= - - minipass@^2.2.1, minipass@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233" - integrity sha512-/jAn9/tEX4gnpyRATxgHEOV6xbcyxgT7iUnxo9Y3+OB0zX00TgKIv/2FZCf5brBbICcwbLqVv2ImjvWWrQMSYw== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - - minizlib@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" - integrity sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA== - dependencies: - minipass "^2.2.1" - - mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - - mkdirp@^0.5.0, mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - - ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - - ms@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - - mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= - - nan@^2.9.2: - version "2.10.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" - integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA== - - nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - - natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - - needle@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d" - integrity sha512-t/ZswCM9JTWjAdXS9VpvqhI2Ct2sL2MdY4fUXqGJaGBk13ge99ObqRksRTbBE56K+wxUXwwfZYOuZHifFW9q+Q== - dependencies: - debug "^2.1.2" - iconv-lite "^0.4.4" - sax "^1.2.4" - - neo-async@^2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" - integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== - - nice-try@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" - integrity sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA== - - node-fetch@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.3.0.tgz#1a1d940bbfb916a1d3e0219f037e89e71f8c5fa5" - integrity sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA== - - node-int64@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= - - node-modules-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" - integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= - - node-notifier@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.2.1.tgz#fa313dd08f5517db0e2502e5758d664ac69f9dea" - integrity sha512-MIBs+AAd6dJ2SklbbE8RUDRlIVhU8MaNLh1A9SUZDUHPiZkWLFde6UNwG41yQHZEToHgJMXqyVZ9UcS/ReOVTg== - dependencies: - growly "^1.3.0" - semver "^5.4.1" - shellwords "^0.1.1" - which "^1.3.0" - - node-pre-gyp@^0.10.0: - version "0.10.3" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" - integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - - node-releases@^1.1.36: - version "1.1.38" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.38.tgz#d81b365df2936654ba37f509ba2fbe91eff2578b" - integrity sha512-/5NZAaOyTj134Oy5Cp/J8mso8OD/D9CSuL+6TOXXsTKO8yjc5e4up75SRPCganCjwFKMj2jbp5tR0dViVdox7g== - dependencies: - semver "^6.3.0" - - nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - - normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: - version "2.4.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" - integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw== - dependencies: - hosted-git-info "^2.1.4" - is-builtin-module "^1.0.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - - normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - - normalize-range@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= - - normalize-selector@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" - integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM= - - npm-bundled@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308" - integrity sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow== - - npm-packlist@^1.1.6: - version "1.1.11" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.11.tgz#84e8c683cbe7867d34b1d357d893ce29e28a02de" - integrity sha512-CxKlZ24urLkJk+9kCm48RTQ7L4hsmgSVzEk0TLGPzzyuFxD7VNgy5Sl24tOLMzQv773a/NeJ1ce1DKeacqffEA== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - - npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= - dependencies: - path-key "^2.0.0" - - npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - - num2fraction@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" - integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= - - number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - - nwsapi@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.0.7.tgz#6fc54c254621f10cac5225b76e81c74120139b78" - integrity sha512-VZXniaaaORAXGCNsvUNefsKRQYk8zCzQZ57jalgrpHcU70OrAzKAiN/3plYtH/VPRmZeYyUzQiYfKzcMXC1g5Q== - - oauth-sign@~0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM= - - object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - - object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - - object-keys@^1.0.12, object-keys@^1.0.8: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032" - integrity sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg== - - object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - - object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" - - object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - - once@^1.3.0, once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - - onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= - dependencies: - mimic-fn "^1.0.0" - - optimist@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - - optionator@^0.8.1, optionator@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.4" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - wordwrap "~1.0.0" - - os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - - os-locale@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" - integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== - dependencies: - execa "^1.0.0" - lcid "^2.0.0" - mem "^4.0.0" - - os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - - osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - - p-defer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" - integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= - - p-each-series@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-1.0.0.tgz#930f3d12dd1f50e7434457a22cd6f04ac6ad7f71" - integrity sha1-kw89Et0fUOdDRFeiLNbwSsatf3E= - dependencies: - p-reduce "^1.0.0" - - p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - - p-is-promise@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.0.0.tgz#7554e3d572109a87e1f3f53f6a7d85d1b194f4c5" - integrity sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg== - - p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - - p-limit@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec" - integrity sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A== - dependencies: - p-try "^2.0.0" - - p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - - p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - - p-reduce@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" - integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo= - - p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - - p-try@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" - integrity sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ== - - pako@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.8.tgz#6844890aab9c635af868ad5fecc62e8acbba3ea4" - integrity sha512-6i0HVbUfcKaTv+EG8ZTr75az7GFXcLYk9UyLEg7Notv/Ma+z/UG3TCoz6GiNeOrn1E/e63I0X/Hpw18jHOTUnA== - - parent-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.0.tgz#df250bdc5391f4a085fb589dad761f5ad6b865b5" - integrity sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA== - dependencies: - callsites "^3.0.0" - - parse-entities@^1.0.2, parse-entities@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.1.2.tgz#9eaf719b29dc3bd62246b4332009072e01527777" - integrity sha512-5N9lmQ7tmxfXf+hO3X6KRG6w7uYO/HL9fHalSySTdyn63C3WNvTM/1R8tn1u1larNcEbo3Slcy2bsVDQqvEpUg== - dependencies: - character-entities "^1.0.0" - character-entities-legacy "^1.0.0" - character-reference-invalid "^1.0.0" - is-alphanumerical "^1.0.0" - is-decimal "^1.0.0" - is-hexadecimal "^1.0.0" - - parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - - parse5@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" - integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA== - - pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - - path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - - path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - - path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - - path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - - path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - - path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== - - path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== - dependencies: - pify "^3.0.0" - - performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - - picomatch@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" - integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== - - pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= - - pify@^4.0.0, pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - - pirates@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-3.0.2.tgz#7e6f85413fd9161ab4e12b539b06010d85954bb9" - integrity sha512-c5CgUJq6H2k6MJz72Ak1F5sN9n9wlSlJyEnwvpm9/y3WB4E3pHBDT2c6PEiS1vyJvq2bUxUAIu0EGf8Cx4Ic7Q== - dependencies: - node-modules-regexp "^1.0.0" - - pirates@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.0.tgz#850b18781b4ac6ec58a43c9ed9ec5fe6796addbd" - integrity sha512-8t5BsXy1LUIjn3WWOlOuFDuKswhQb/tkak641lvBgmPOBUQHXveORtlMCp6OdPV1dtuTaEahKA8VNz6uLfKBtA== - dependencies: - node-modules-regexp "^1.0.0" - - pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - - pn@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" - integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== - - posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - - postcss-html@^0.36.0: - version "0.36.0" - resolved "https://registry.yarnpkg.com/postcss-html/-/postcss-html-0.36.0.tgz#b40913f94eaacc2453fd30a1327ad6ee1f88b204" - integrity sha512-HeiOxGcuwID0AFsNAL0ox3mW6MHH5cstWN1Z3Y+n6H+g12ih7LHdYxWwEA/QmrebctLjo79xz9ouK3MroHwOJw== - dependencies: - htmlparser2 "^3.10.0" - - postcss-jsx@^0.36.0: - version "0.36.0" - resolved "https://registry.yarnpkg.com/postcss-jsx/-/postcss-jsx-0.36.0.tgz#b7685ed3d070a175ef0aa48f83d9015bd772c82d" - integrity sha512-/lWOSXSX5jlITCKFkuYU2WLFdrncZmjSVyNpHAunEgirZXLwI8RjU556e3Uz4mv0WVHnJA9d3JWb36lK9Yx99g== - dependencies: - "@babel/core" ">=7.1.0" - - postcss-less@^3.1.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-3.1.2.tgz#fb67e7ba351dbdf69de3c52eebd1184c52bfaea6" - integrity sha512-66ZBVo1JGkQ7r13M97xcHcyarWpgg21RaqIZWZXHE3XOtb5+ywK1uZWeY1DYkYRkIX/l8Hvxnx9iSKB68nFr+w== - dependencies: - postcss "^7.0.14" - - postcss-load-config@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.0.0.tgz#f1312ddbf5912cd747177083c5ef7a19d62ee484" - integrity sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ== - dependencies: - cosmiconfig "^4.0.0" - import-cwd "^2.0.0" - - postcss-loader@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d" - integrity sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA== - dependencies: - loader-utils "^1.1.0" - postcss "^7.0.0" - postcss-load-config "^2.0.0" - schema-utils "^1.0.0" - - postcss-markdown@^0.36.0: - version "0.36.0" - resolved "https://registry.yarnpkg.com/postcss-markdown/-/postcss-markdown-0.36.0.tgz#7f22849ae0e3db18820b7b0d5e7833f13a447560" - integrity sha512-rl7fs1r/LNSB2bWRhyZ+lM/0bwKv9fhl38/06gF6mKMo/NPnp55+K1dSTosSVjFZc0e1ppBlu+WT91ba0PMBfQ== - dependencies: - remark "^10.0.1" - unist-util-find-all-after "^1.0.2" - - postcss-media-query-parser@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244" - integrity sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ= - - postcss-reporter@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-6.0.0.tgz#44c873129d8c029a430b6d2186210d79c8de88b8" - integrity sha512-5xQXm1UPWuFObjbtyQzWvQaupru8yFcFi4HUlm6OPo1o2bUszYASuqRJ7bVArb3svGCdbYtqdMBKrqR1Aoy+tw== - dependencies: - chalk "^2.0.1" - lodash "^4.17.4" - log-symbols "^2.0.0" - postcss "^7.0.2" - - postcss-resolve-nested-selector@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz#29ccbc7c37dedfac304e9fff0bf1596b3f6a0e4e" - integrity sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4= - - postcss-safe-parser@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-4.0.1.tgz#8756d9e4c36fdce2c72b091bbc8ca176ab1fcdea" - integrity sha512-xZsFA3uX8MO3yAda03QrG3/Eg1LN3EPfjjf07vke/46HERLZyHrTsQ9E1r1w1W//fWEhtYNndo2hQplN2cVpCQ== - dependencies: - postcss "^7.0.0" - - postcss-sass@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/postcss-sass/-/postcss-sass-0.3.5.tgz#6d3e39f101a53d2efa091f953493116d32beb68c" - integrity sha512-B5z2Kob4xBxFjcufFnhQ2HqJQ2y/Zs/ic5EZbCywCkxKd756Q40cIQ/veRDwSrw1BF6+4wUgmpm0sBASqVi65A== - dependencies: - gonzales-pe "^4.2.3" - postcss "^7.0.1" - - postcss-scss@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-2.0.0.tgz#248b0a28af77ea7b32b1011aba0f738bda27dea1" - integrity sha512-um9zdGKaDZirMm+kZFKKVsnKPF7zF7qBAtIfTSnZXD1jZ0JNZIxdB6TxQOjCnlSzLRInVl2v3YdBh/M881C4ug== - dependencies: - postcss "^7.0.0" - - postcss-selector-parser@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" - integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU= - dependencies: - dot-prop "^4.1.1" - indexes-of "^1.0.1" - uniq "^1.0.1" - - postcss-syntax@^0.36.2: - version "0.36.2" - resolved "https://registry.yarnpkg.com/postcss-syntax/-/postcss-syntax-0.36.2.tgz#f08578c7d95834574e5593a82dfbfa8afae3b51c" - integrity sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w== - - postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" - integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== - - postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.13, postcss@^7.0.14, postcss@^7.0.2: - version "7.0.17" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.17.tgz#4da1bdff5322d4a0acaab4d87f3e782436bad31f" - integrity sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ== - dependencies: - chalk "^2.4.2" - source-map "^0.6.1" - supports-color "^6.1.0" - - prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - - pretty-format@^24.0.0: - version "24.0.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.0.0.tgz#cb6599fd73ac088e37ed682f61291e4678f48591" - integrity sha512-LszZaKG665djUcqg5ZQq+XzezHLKrxsA86ZABTozp+oNhkdqa+tG2dX4qa6ERl5c/sRDrAa3lHmwnvKoP+OG/g== - dependencies: - ansi-regex "^4.0.0" - ansi-styles "^3.2.0" - - process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== - - progress@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" - integrity sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8= - - prompts@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.0.3.tgz#c5ccb324010b2e8f74752aadceeb57134c1d2522" - integrity sha512-H8oWEoRZpybm6NV4to9/1limhttEo13xK62pNvn2JzY0MA03p7s0OjtmhXyon3uJmxiJJVSuUwEJFFssI3eBiQ== - dependencies: - kleur "^3.0.2" - sisteransi "^1.0.0" - - psl@^1.1.24: - version "1.1.28" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.28.tgz#4fb6ceb08a1e2214d4fd4de0ca22dae13740bc7b" - integrity sha512-+AqO1Ae+N/4r7Rvchrdm432afjT9hqJRyBN3DQv9At0tPz4hIFSGKbq64fN9dVoCow4oggIIax5/iONx0r9hZw== - - pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - - punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - - punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - - qs@~6.5.1: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - - query-string@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.2.0.tgz#468edeb542b7e0538f9f9b1aeb26f034f19c86e1" - integrity sha512-5wupExkIt8RYL4h/FE+WTg3JHk62e6fFPWtAZA9J5IWK1PfTfKkMS93HBUHcFpeYi9KsY5pFbh+ldvEyaz5MyA== - dependencies: - decode-uri-component "^0.2.0" - strict-uri-encode "^2.0.0" - - quick-lru@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" - integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g= - - rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - - read-pkg-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" - integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= - dependencies: - find-up "^2.0.0" - read-pkg "^3.0.0" - - read-pkg-up@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" - integrity sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA== - dependencies: - find-up "^3.0.0" - read-pkg "^3.0.0" - - read-pkg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= - dependencies: - load-json-file "^4.0.0" - normalize-package-data "^2.3.2" - path-type "^3.0.0" - - readable-stream@^2.0.1, readable-stream@^2.0.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - - readable-stream@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.1.1.tgz#ed6bbc6c5ba58b090039ff18ce670515795aeb06" - integrity sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - - realpath-native@^1.0.0, realpath-native@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c" - integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA== - dependencies: - util.promisify "^1.0.0" - - redent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" - integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo= - dependencies: - indent-string "^3.0.0" - strip-indent "^2.0.0" - - regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - - regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - - remark-parse@^6.0.0: - version "6.0.3" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-6.0.3.tgz#c99131052809da482108413f87b0ee7f52180a3a" - integrity sha512-QbDXWN4HfKTUC0hHa4teU463KclLAnwpn/FBn87j9cKYJWWawbiLgMfP2Q4XwhxxuuuOxHlw+pSN0OKuJwyVvg== - dependencies: - collapse-white-space "^1.0.2" - is-alphabetical "^1.0.0" - is-decimal "^1.0.0" - is-whitespace-character "^1.0.0" - is-word-character "^1.0.0" - markdown-escapes "^1.0.0" - parse-entities "^1.1.0" - repeat-string "^1.5.4" - state-toggle "^1.0.0" - trim "0.0.1" - trim-trailing-lines "^1.0.0" - unherit "^1.0.4" - unist-util-remove-position "^1.0.0" - vfile-location "^2.0.0" - xtend "^4.0.1" - - remark-stringify@^6.0.0: - version "6.0.4" - resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-6.0.4.tgz#16ac229d4d1593249018663c7bddf28aafc4e088" - integrity sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg== - dependencies: - ccount "^1.0.0" - is-alphanumeric "^1.0.0" - is-decimal "^1.0.0" - is-whitespace-character "^1.0.0" - longest-streak "^2.0.1" - markdown-escapes "^1.0.0" - markdown-table "^1.1.0" - mdast-util-compact "^1.0.0" - parse-entities "^1.0.2" - repeat-string "^1.5.4" - state-toggle "^1.0.0" - stringify-entities "^1.0.1" - unherit "^1.0.4" - xtend "^4.0.1" - - remark@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/remark/-/remark-10.0.1.tgz#3058076dc41781bf505d8978c291485fe47667df" - integrity sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ== - dependencies: - remark-parse "^6.0.0" - remark-stringify "^6.0.0" - unified "^7.0.0" - - remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - - repeat-element@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" - integrity sha1-7wiaF40Ug7quTZPrmLT55OEdmQo= - - repeat-string@^1.5.4, repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - - replace-ext@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= - - request-promise-core@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" - integrity sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY= - dependencies: - lodash "^4.13.1" - - request-promise-native@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.5.tgz#5281770f68e0c9719e5163fd3fab482215f4fda5" - integrity sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU= - dependencies: - request-promise-core "1.1.1" - stealthy-require "^1.1.0" - tough-cookie ">=2.3.3" - - request@^2.87.0: - version "2.87.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" - integrity sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - - require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - - require-from-string@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - - require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= - - require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - - resolve-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" - integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= - dependencies: - resolve-from "^3.0.0" - - resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= - - resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - - resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - - resolve@1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= - - resolve@^1.14.2: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== - dependencies: - path-parse "^1.0.6" - - resolve@^1.3.2: - version "1.10.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba" - integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg== - dependencies: - path-parse "^1.0.6" - - restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - - ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - - rimraf@2.6.3, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - - rollup-plugin-flow@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/rollup-plugin-flow/-/rollup-plugin-flow-1.1.1.tgz#6ce568f1dd559666b77ab76b4bae251407528db6" - integrity sha1-bOVo8d1Vlma3erdrS64lFAdSjbY= - dependencies: - flow-remove-types "^1.1.0" - rollup-pluginutils "^1.5.1" - - rollup-pluginutils@^1.5.1: - version "1.5.2" - resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" - integrity sha1-HhVud4+UtyVb+hs9AXi+j1xVJAg= - dependencies: - estree-walker "^0.2.1" - minimatch "^3.0.2" - - rollup@^1.13.0: - version "1.32.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.32.1.tgz#4480e52d9d9e2ae4b46ba0d9ddeaf3163940f9c4" - integrity sha512-/2HA0Ec70TvQnXdzynFffkjA6XN+1e2pEv/uKS5Ulca40g2L7KuOE3riasHoNVHOsFD5KKZgDsMk1CP3Tw9s+A== - dependencies: - "@types/estree" "*" - "@types/node" "*" - acorn "^7.1.0" - - rsvp@^3.3.3: - version "3.6.2" - resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" - integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw== - - run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= - dependencies: - is-promise "^2.1.0" - - rxjs@^6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.4.0.tgz#f3bb0fe7bda7fb69deac0c16f17b50b0b8790504" - integrity sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw== - dependencies: - tslib "^1.9.0" - - safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - - safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - - "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - - sane@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/sane/-/sane-3.1.0.tgz#995193b7dc1445ef1fe41ddfca2faf9f111854c6" - integrity sha512-G5GClRRxT1cELXfdAq7UKtUsv8q/ZC5k8lQGmjEm4HcAl3HzBy68iglyNCmw4+0tiXPCBZntslHlRhbnsSws+Q== - dependencies: - anymatch "^2.0.0" - capture-exit "^1.2.0" - exec-sh "^0.2.0" - execa "^1.0.0" - fb-watchman "^2.0.0" - micromatch "^3.1.4" - minimist "^1.1.1" - walker "~1.0.5" - watch "~0.18.0" - optionalDependencies: - fsevents "^1.2.3" - - sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - - schema-utils@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" - integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== - dependencies: - ajv "^6.1.0" - ajv-errors "^1.0.0" - ajv-keywords "^3.1.0" - - "semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1: - version "5.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" - integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== - - semver@^6.0.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.2.0.tgz#4d813d9590aaf8a9192693d6c85b9344de5901db" - integrity sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A== - - semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - - set-blocking@^2.0.0, set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - - set-value@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.1" - to-object-path "^0.3.0" - - set-value@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" - integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - - shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - - shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - - shellwords@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" - integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== - - signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= - - sisteransi@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.0.tgz#77d9622ff909080f1c19e5f4a1df0c1b0a27b88c" - integrity sha512-N+z4pHB4AmUv0SjveWRd6q1Nj5w62m5jodv+GD8lvmbY/83T/rpbJGZOnK5T149OldDj4Db07BSv9xY4K6NTPQ== - - slash@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" - integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== - - slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - - snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - - snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - - snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - - source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== - dependencies: - atob "^2.1.1" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - - source-map-support@^0.5.6: - version "0.5.10" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.10.tgz#2214080bc9d51832511ee2bab96e3c2f9353120c" - integrity sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - - source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= - - source-map@^0.5.0, source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - - source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - - spdx-correct@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" - integrity sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - - spdx-exceptions@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" - integrity sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg== - - spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - - spdx-license-ids@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" - integrity sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA== - - specificity@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/specificity/-/specificity-0.4.1.tgz#aab5e645012db08ba182e151165738d00887b019" - integrity sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg== - - split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - - sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - - sshpk@^1.7.0: - version "1.14.2" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" - integrity sha1-xvxhZIo9nE52T9P8306hBeSSupg= - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - safer-buffer "^2.0.2" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jsbn "~0.1.0" - tweetnacl "~0.14.0" - - stack-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620" - integrity sha1-1PM6tU6OOHeLDKXP07OvsS22hiA= - - state-toggle@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.1.tgz#c3cb0974f40a6a0f8e905b96789eb41afa1cde3a" - integrity sha512-Qe8QntFrrpWTnHwvwj2FZTgv+PKIsp0B9VxLzLLbSpPXWOgRgc5LVj/aTiSfK1RqIeF9jeC1UeOH8Q8y60A7og== - - static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - - stealthy-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= - - stream-events@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5" - integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg== - dependencies: - stubs "^3.0.0" - - strict-uri-encode@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" - integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= - - string-length@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" - integrity sha1-1A27aGo6zpYMHP/KVivyxF+DY+0= - dependencies: - astral-regex "^1.0.0" - strip-ansi "^4.0.0" - - string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - - "string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - - string-width@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.0.0.tgz#5a1690a57cc78211fffd9bf24bbe24d090604eb1" - integrity sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.0.0" - - string_decoder@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" - integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== - dependencies: - safe-buffer "~5.1.0" - - string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - - stringify-entities@^1.0.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-1.3.2.tgz#a98417e5471fd227b3e45d3db1861c11caf668f7" - integrity sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A== - dependencies: - character-entities-html4 "^1.0.0" - character-entities-legacy "^1.0.0" - is-alphanumerical "^1.0.0" - is-hexadecimal "^1.0.0" - - strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - - strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - - strip-ansi@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.0.0.tgz#f78f68b5d0866c20b2c9b8c61b5298508dc8756f" - integrity sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow== - dependencies: - ansi-regex "^4.0.0" - - strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= - - strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= - - strip-indent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" - integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= - - strip-json-comments@^2.0.1, strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - - stubs@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b" - integrity sha1-6NK6H6nJBXAwPAMLaQD31fiavls= - - style-loader@^0.23.1: - version "0.23.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.1.tgz#cb9154606f3e771ab6c4ab637026a1049174d925" - integrity sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg== - dependencies: - loader-utils "^1.1.0" - schema-utils "^1.0.0" - - style-search@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902" - integrity sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI= - - stylelint-config-recommended@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-2.1.0.tgz#f526d5c771c6811186d9eaedbed02195fee30858" - integrity sha512-ajMbivOD7JxdsnlS5945KYhvt7L/HwN6YeYF2BH6kE4UCLJR0YvXMf+2j7nQpJyYLZx9uZzU5G1ZOSBiWAc6yA== - - stylelint-config-standard@^18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/stylelint-config-standard/-/stylelint-config-standard-18.2.0.tgz#6283149aba7f64f18731aef8f0abfb35cf619e06" - integrity sha512-07x0TaSIzvXlbOioUU4ORkCIM07kyIuojkbSVCyFWNVgXMXYHfhnQSCkqu+oHWJf3YADAnPGWzdJ53NxkoJ7RA== - dependencies: - stylelint-config-recommended "^2.1.0" - - stylelint@^9.10.1: - version "9.10.1" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-9.10.1.tgz#5f0ee3701461dff1d68284e1386efe8f0677a75d" - integrity sha512-9UiHxZhOAHEgeQ7oLGwrwoDR8vclBKlSX7r4fH0iuu0SfPwFaLkb1c7Q2j1cqg9P7IDXeAV2TvQML/fRQzGBBQ== - dependencies: - autoprefixer "^9.0.0" - balanced-match "^1.0.0" - chalk "^2.4.1" - cosmiconfig "^5.0.0" - debug "^4.0.0" - execall "^1.0.0" - file-entry-cache "^4.0.0" - get-stdin "^6.0.0" - global-modules "^2.0.0" - globby "^9.0.0" - globjoin "^0.1.4" - html-tags "^2.0.0" - ignore "^5.0.4" - import-lazy "^3.1.0" - imurmurhash "^0.1.4" - known-css-properties "^0.11.0" - leven "^2.1.0" - lodash "^4.17.4" - log-symbols "^2.0.0" - mathml-tag-names "^2.0.1" - meow "^5.0.0" - micromatch "^3.1.10" - normalize-selector "^0.2.0" - pify "^4.0.0" - postcss "^7.0.13" - postcss-html "^0.36.0" - postcss-jsx "^0.36.0" - postcss-less "^3.1.0" - postcss-markdown "^0.36.0" - postcss-media-query-parser "^0.2.3" - postcss-reporter "^6.0.0" - postcss-resolve-nested-selector "^0.1.1" - postcss-safe-parser "^4.0.0" - postcss-sass "^0.3.5" - postcss-scss "^2.0.0" - postcss-selector-parser "^3.1.0" - postcss-syntax "^0.36.2" - postcss-value-parser "^3.3.0" - resolve-from "^4.0.0" - signal-exit "^3.0.2" - slash "^2.0.0" - specificity "^0.4.1" - string-width "^3.0.0" - style-search "^0.1.0" - sugarss "^2.0.0" - svg-tags "^1.0.0" - table "^5.0.0" - - sugarss@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d" - integrity sha512-WfxjozUk0UVA4jm+U1d736AUpzSrNsQcIbyOkoE364GrtWmIrFdk5lksEupgWMD4VaT/0kVx1dobpiDumSgmJQ== - dependencies: - postcss "^7.0.2" - - supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - - supports-color@^6.0.0, supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - - svg-tags@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" - integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= - - symbol-tree@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" - integrity sha1-rifbOPZgp64uHDt9G8KQgZuFGeY= - - table@^5.0.0, table@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/table/-/table-5.2.3.tgz#cde0cc6eb06751c009efab27e8c820ca5b67b7f2" - integrity sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ== - dependencies: - ajv "^6.9.1" - lodash "^4.17.11" - slice-ansi "^2.1.0" - string-width "^3.0.0" - - tar@^4: - version "4.4.4" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.4.tgz#ec8409fae9f665a4355cc3b4087d0820232bb8cd" - integrity sha512-mq9ixIYfNF9SK0IS/h2HKMu8Q2iaCuhDDsZhdEag/FHv8fOaYld4vN7ouMgcSSt5WKZzPs8atclTcJm36OTh4w== - dependencies: - chownr "^1.0.1" - fs-minipass "^1.2.5" - minipass "^2.3.3" - minizlib "^1.1.0" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.2" - - teeny-request@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-6.0.1.tgz#9b1f512cef152945827ba7e34f62523a4ce2c5b0" - integrity sha512-TAK0c9a00ELOqLrZ49cFxvPVogMUFaWY8dUsQc/0CuQPGF+BOxOQzXfE413BAk2kLomwNplvdtMpeaeGWmoc2g== - dependencies: - http-proxy-agent "^4.0.0" - https-proxy-agent "^4.0.0" - node-fetch "^2.2.0" - stream-events "^1.0.5" - uuid "^3.3.2" - - test-exclude@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0" - integrity sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g== - dependencies: - glob "^7.1.3" - minimatch "^3.0.4" - read-pkg-up "^4.0.0" - require-main-filename "^2.0.0" - - text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - - throat@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" - integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= - - through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - - tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - - tmpl@1.0.x: - version "1.0.4" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" - integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= - - to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - - to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - - to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - - to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - - tough-cookie@>=2.3.3, tough-cookie@^2.3.4: - version "2.4.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== - dependencies: - psl "^1.1.24" - punycode "^1.4.1" - - tough-cookie@~2.3.3: - version "2.3.4" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" - integrity sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA== - dependencies: - punycode "^1.4.1" - - tr46@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" - integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= - dependencies: - punycode "^2.1.0" - - trim-newlines@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" - integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA= - - trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= - - trim-trailing-lines@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz#e0ec0810fd3c3f1730516b45f49083caaf2774d9" - integrity sha512-bWLv9BbWbbd7mlqqs2oQYnLD/U/ZqeJeJwbO0FG2zA1aTq+HTvxfHNKFa/HGCVyJpDiioUYaBhfiT6rgk+l4mg== - - trim@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= - - trough@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.2.tgz#7f1663ec55c480139e2de5e486c6aef6cc24a535" - integrity sha512-FHkoUZvG6Egrv9XZAyYGKEyb1JMsFphgPjoczkZC2y6W93U1jswcVURB8MUvtsahEPEVACyxD47JAL63vF4JsQ== - - tslib@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" - integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== - - tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - - tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - - type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" - - uglify-js@^3.1.4: - version "3.7.2" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.2.tgz#cb1a601e67536e9ed094a92dd1e333459643d3f9" - integrity sha512-uhRwZcANNWVLrxLfNFEdltoPNhECUR3lc+UdJoG9CBpMcSnKyWA94tc3eAujB1GcMY5Uwq8ZMp4qWpxWYDQmaA== - dependencies: - commander "~2.20.3" - source-map "~0.6.1" - - unherit@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.1.tgz#132748da3e88eab767e08fabfbb89c5e9d28628c" - integrity sha512-+XZuV691Cn4zHsK0vkKYwBEwB74T3IZIcxrgn2E4rKwTfFyI1zCh7X7grwh9Re08fdPlarIdyWgI8aVB3F5A5g== - dependencies: - inherits "^2.0.1" - xtend "^4.0.1" - - unified@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/unified/-/unified-7.1.0.tgz#5032f1c1ee3364bd09da12e27fdd4a7553c7be13" - integrity sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw== - dependencies: - "@types/unist" "^2.0.0" - "@types/vfile" "^3.0.0" - bail "^1.0.0" - extend "^3.0.0" - is-plain-obj "^1.1.0" - trough "^1.0.0" - vfile "^3.0.0" - x-is-string "^0.1.0" - - union-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" - integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^0.4.3" - - uniq@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= - - unist-util-find-all-after@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-1.0.2.tgz#9be49cfbae5ca1566b27536670a92836bf2f8d6d" - integrity sha512-nDl79mKpffXojLpCimVXnxhlH/jjaTnDuScznU9J4jjsaUtBdDbxmlc109XtcqxY4SDO0SwzngsxxW8DIISt1w== - dependencies: - unist-util-is "^2.0.0" - - unist-util-is@^2.0.0, unist-util-is@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-2.1.2.tgz#1193fa8f2bfbbb82150633f3a8d2eb9a1c1d55db" - integrity sha512-YkXBK/H9raAmG7KXck+UUpnKiNmUdB+aBGrknfQ4EreE1banuzrKABx3jP6Z5Z3fMSPMQQmeXBlKpCbMwBkxVw== - - unist-util-modify-children@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/unist-util-modify-children/-/unist-util-modify-children-1.1.2.tgz#c7f1b91712554ee59c47a05b551ed3e052a4e2d1" - integrity sha512-GRi04yhng1WqBf5RBzPkOtWAadcZS2gvuOgNn/cyJBYNxtTuyYqTKN0eg4rC1YJwGnzrqfRB3dSKm8cNCjNirg== - dependencies: - array-iterate "^1.0.0" - - unist-util-remove-position@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz#86b5dad104d0bbfbeb1db5f5c92f3570575c12cb" - integrity sha512-XxoNOBvq1WXRKXxgnSYbtCF76TJrRoe5++pD4cCBsssSiWSnPEktyFrFLE8LTk3JW5mt9hB0Sk5zn4x/JeWY7Q== - dependencies: - unist-util-visit "^1.1.0" - - unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6" - integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ== - - unist-util-visit-parents@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.0.1.tgz#63fffc8929027bee04bfef7d2cce474f71cb6217" - integrity sha512-6B0UTiMfdWql4cQ03gDTCSns+64Zkfo2OCbK31Ov0uMizEz+CJeAp0cgZVb5Fhmcd7Bct2iRNywejT0orpbqUA== - dependencies: - unist-util-is "^2.1.2" - - unist-util-visit@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.0.tgz#1cb763647186dc26f5e1df5db6bd1e48b3cc2fb1" - integrity sha512-FiGu34ziNsZA3ZUteZxSFaczIjGmksfSgdKqBfOejrrfzyUy5b7YrlzT1Bcvi+djkYDituJDy2XB7tGTeBieKw== - dependencies: - unist-util-visit-parents "^2.0.0" - - universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - - unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - - uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== - dependencies: - punycode "^2.1.0" - - urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - - urlgrey@0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/urlgrey/-/urlgrey-0.4.4.tgz#892fe95960805e85519f1cd4389f2cb4cbb7652f" - integrity sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8= - - use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - - util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - - util.promisify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" - integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== - dependencies: - define-properties "^1.1.2" - object.getownpropertydescriptors "^2.0.3" - - uuid@^3.1.0, uuid@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== - - validate-npm-package-license@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" - integrity sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - - verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - - vfile-location@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.3.tgz#083ba80e50968e8d420be49dd1ea9a992131df77" - integrity sha512-zM5/l4lfw1CBoPx3Jimxoc5RNDAHHpk6AM6LM0pTIkm5SUSsx8ZekZ0PVdf0WEZ7kjlhSt7ZlqbRL6Cd6dBs6A== - - vfile-message@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.0.1.tgz#51a2ccd8a6b97a7980bb34efb9ebde9632e93677" - integrity sha512-vSGCkhNvJzO6VcWC6AlJW4NtYOVtS+RgCaqFIYUjoGIlHnFL+i0LbtYvonDWOMcB97uTPT4PRsyYY7REWC9vug== - dependencies: - unist-util-stringify-position "^1.1.1" - - vfile@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-3.0.1.tgz#47331d2abe3282424f4a4bb6acd20a44c4121803" - integrity sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ== - dependencies: - is-buffer "^2.0.0" - replace-ext "1.0.0" - unist-util-stringify-position "^1.0.0" - vfile-message "^1.0.0" - - vlq@^0.2.1: - version "0.2.3" - resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" - integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow== - - w3c-hr-time@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" - integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU= - dependencies: - browser-process-hrtime "^0.1.2" - - walker@~1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" - integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= - dependencies: - makeerror "1.0.x" - - watch@~0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986" - integrity sha1-KAlUdsbffJDJYxOJkMClQj60uYY= - dependencies: - exec-sh "^0.2.0" - minimist "^1.2.0" - - webidl-conversions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" - integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== - - whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz#57c235bc8657e914d24e1a397d3c82daee0a6ba3" - integrity sha512-jLBwwKUhi8WtBfsMQlL4bUUcT8sMkAtQinscJAe/M4KHCkHuUJAF6vuB0tueNIw4c8ziO6AkRmgY+jL3a0iiPw== - dependencies: - iconv-lite "0.4.19" - - whatwg-mimetype@^2.0.0, whatwg-mimetype@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.1.0.tgz#f0f21d76cbba72362eb609dbed2a30cd17fcc7d4" - integrity sha512-FKxhYLytBQiUKjkYteN71fAUA3g6KpNXoho1isLiLSB3N1G4F35Q5vUxWfKFhBwi5IWF27VE6WxhrnnC+m0Mew== - - whatwg-url@^6.4.0, whatwg-url@^6.4.1: - version "6.5.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8" - integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ== - dependencies: - lodash.sortby "^4.7.0" - tr46 "^1.0.1" - webidl-conversions "^4.0.2" - - which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= - - which@^1.2.12, which@^1.2.9, which@^1.3.0, which@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - - wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - - wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= - - wordwrap@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= - - wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - - wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - - write-file-atomic@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.1.tgz#d0b05463c188ae804396fd5ab2a370062af87529" - integrity sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg== - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - signal-exit "^3.0.2" - - write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - - ws@^5.2.0: - version "5.2.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" - integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA== - dependencies: - async-limiter "~1.0.0" - - x-is-string@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" - integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI= - - xml-name-validator@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" - integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== - - xtend@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= - - "y18n@^3.2.1 || ^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== - - yallist@^3.0.0, yallist@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" - integrity sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k= - - yargs-parser@^10.0.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" - integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== - dependencies: - camelcase "^4.1.0" - - yargs-parser@^11.1.1: - version "11.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" - integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - - yargs@^12.0.2: - version "12.0.5" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" - integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== - dependencies: - cliui "^4.0.0" - decamelize "^1.2.0" - find-up "^3.0.0" - get-caller-file "^1.0.1" - os-locale "^3.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1 || ^4.0.0" - yargs-parser "^11.1.1" diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index af5f274b..00000000 --- a/yarn.lock +++ /dev/null @@ -1,648 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@eslint/eslintrc@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.0.5.tgz#33f1b838dbf1f923bfa517e008362b78ddbbf318" - integrity sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.2.0" - globals "^13.9.0" - ignore "^4.0.6" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.0.4" - strip-json-comments "^3.1.1" - -"@humanwhocodes/config-array@^0.9.2": - version "0.9.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.3.tgz#f2564c744b387775b436418491f15fce6601f63e" - integrity sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ== - dependencies: - "@humanwhocodes/object-schema" "^1.2.1" - debug "^4.1.1" - minimatch "^3.0.4" - -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== - -acorn-jsx@^5.3.1: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn@^8.7.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== - -ajv@^6.10.0, ajv@^6.12.4: - version "6.12.5" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.5.tgz#19b0e8bae8f476e5ba666300387775fb1a00a4da" - integrity sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - -callsites@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.0.0.tgz#fb7eb569b72ad7a45812f93fd9430a3e410b3dd3" - integrity sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw== - -chalk@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" - integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -cross-spawn@^7.0.2: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -debug@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - -debug@^4.3.2: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - -deep-is@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-scope@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.0.tgz#c1f6ea30ac583031f203d65c73e723b01298f153" - integrity sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz#6fbb166a6798ee5991358bc2daa1ba76cc1254a1" - integrity sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ== - -eslint@^8.7.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.7.0.tgz#22e036842ee5b7cf87b03fe237731675b4d3633c" - integrity sha512-ifHYzkBGrzS2iDU7KjhCAVMGCvF6M3Xfs8X8b37cgrUlDt6bWRTpRh6T/gtSXv1HJ/BUGgmjvNvOEGu85Iif7w== - dependencies: - "@eslint/eslintrc" "^1.0.5" - "@humanwhocodes/config-array" "^0.9.2" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.1.0" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.2.0" - espree "^9.3.0" - esquery "^1.4.0" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^6.0.1" - globals "^13.6.0" - ignore "^5.2.0" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.0.4" - natural-compare "^1.4.0" - optionator "^0.9.1" - regexpp "^3.2.0" - strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - -esm@^3.2.25: - version "3.2.25" - resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" - integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== - -espree@^9.2.0, espree@^9.3.0: - version "9.3.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.0.tgz#c1240d79183b72aaee6ccfa5a90bc9111df085a8" - integrity sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ== - dependencies: - acorn "^8.7.0" - acorn-jsx "^5.3.1" - eslint-visitor-keys "^3.1.0" - -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" - integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== - -esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - -flatted@^3.1.0: - version "3.2.5" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" - integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= - -glob-parent@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^13.6.0, globals@^13.9.0: - version "13.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.0.tgz#4d733760304230a0082ed96e21e5c565f898089e" - integrity sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg== - dependencies: - type-fest "^0.20.2" - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - -ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== - -import-fresh@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390" - integrity sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-fresh@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" - integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-glob@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" - integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A= - dependencies: - is-extglob "^2.1.1" - -is-glob@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -ms@2.1.2, ms@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.3" - -parent-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.0.tgz#df250bdc5391f4a085fb589dad761f5ad6b865b5" - integrity sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA== - dependencies: - callsites "^3.0.0" - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -rollup@^2.66.1: - version "2.66.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.66.1.tgz#366b0404de353c4331d538c3ad2963934fcb4937" - integrity sha512-crSgLhSkLMnKr4s9iZ/1qJCplgAgrRY+igWv8KhG/AjKOJ0YX/WpmANyn8oxrw+zenF3BXWDLa7Xl/QZISH+7w== - optionalDependencies: - fsevents "~2.3.2" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@~0.7.2: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - -strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -terser@^5.10.0: - version "5.10.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc" - integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA== - dependencies: - commander "^2.20.0" - source-map "~0.7.2" - source-map-support "~0.5.20" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== - dependencies: - punycode "^2.1.0" - -v8-compile-cache@^2.0.3: - version "2.1.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" - integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -word-wrap@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -xml-formatter@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/xml-formatter/-/xml-formatter-2.4.0.tgz#c956ea6c5345240c0829da86a5e81d44ed4cb9c7" - integrity sha512-xTQ2IfbkCQKn0DGN5SD5KUgTgVohWiolyOXTLUHKJczIuSeGonN0BPduB9VQR5HOEuT1KOHQsOHSmTpU76zpUA== - dependencies: - xml-parser-xo "^3.1.1" - -xml-parser-xo@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/xml-parser-xo/-/xml-parser-xo-3.1.1.tgz#a87d92e44fa8ad3ba7242517df96e6b0893f1f47" - integrity sha512-gq1nDlJxjKQpPPZUhLbJ52pghtlB4Rz6LAQULm3SF6xzOYVnUloBglNhJR9vtZB3vIxMN/R3nZTf3qmun+6GCg==

    EXThDZf{ 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ⅇrs4AS2m$F(PX01ZHKFn%D!)n&dz#6R03_upuy3h!YsMe7N zXsFhOhQb^1k=6Pzn-OLpi)u}1)C#KyIbJ7QA?p*oR+E#P9Bdr3#|E;iIz}~E@^?cE ze1Og6k=~+~#u-Ayb$=Bh9|E^~bmJB^UVNkNs@)!C28 z?{+haPkv5Ljh?L=?W`Qd`$TKW3Q)caT*u9og9>?s3WCD*Ik~8=;9K0jl~1yCM5wKn zXvG;<)>g!5MOnqT^9vw7wrEsAM5(A1)&wCQL3M*hSuIWm-9{tG<$2_9x3aUQ4aO2S zmsiE^jBw2gCq7Gba_+l@iJfm8p~`}x6ge5KJd$ns1G4W|dMsat=g$ObFr1K~lelkF z%q5+jc8<`K4oeFtdV6r%EJMwI;SIaZ`4?)OF5XL∋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%0Dx2TsH-K6?_*MnIgOcv*+?)aYUr_fBv1{P_{7 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 diff --git a/site/assets/mhchem.min.js b/site/assets/mhchem.min.js deleted file mode 100644 index 2eafa389..00000000 --- a/site/assets/mhchem.min.js +++ /dev/null @@ -1 +0,0 @@ -temml.__defineMacro("\\ce",(function(t){return chemParse(t.consumeArgs(1)[0],"ce")})),temml.__defineMacro("\\pu",(function(t){return chemParse(t.consumeArgs(1)[0],"pu")})),temml.__defineMacro("\\uniDash","{\\rule{0.672em}{0.06em}}"),temml.__defineMacro("\\triDash","{\\rule{0.15em}{0.06em}\\kern2mu\\rule{0.15em}{0.06em}\\kern2mu\\rule{0.15em}{0.06em}}"),temml.__defineMacro("\\tripleDash","\\kern0.075em\\raise0.25em{\\triDash}\\kern0.075em"),temml.__defineMacro("\\tripleDashOverLine","\\kern0.075em\\mathrlap{\\raise0.125em{\\uniDash}}\\raise0.34em{\\triDash}\\kern0.075em"),temml.__defineMacro("\\tripleDashOverDoubleLine","\\kern0.075em\\mathrlap{\\mathrlap{\\raise0.48em{\\triDash}}\\raise0.27em{\\uniDash}}{\\raise0.05em{\\uniDash}}\\kern0.075em"),temml.__defineMacro("\\tripleDashBetweenDoubleLine","\\kern0.075em\\mathrlap{\\mathrlap{\\raise0.48em{\\uniDash}}\\raise0.27em{\\triDash}}{\\raise0.05em{\\uniDash}}\\kern0.075em");var chemParse=function(t,e){for(var r="",a=t.length&&t[t.length-1].loc.start,n=t.length-1;n>=0;n--)t[n].loc.start>a&&(r+=" ",a=t[n].loc.start),r+=t[n].text,a+=t[n].text.length;return texify.go(mhchemParser.go(r,e))},mhchemParser={go:function(t,e){if(!t)return[];void 0===e&&(e="ce");var r,a="0",n={};n.parenthesisLevel=0,t=(t=(t=t.replace(/\n/g," ")).replace(/[\u2212\u2013\u2014\u2010]/g,"-")).replace(/[\u2026]/g,"...");for(var o=10,i=[];;){r!==t?(o=10,r=t):o--;var c=mhchemParser.stateMachines[e],s=c.transitions[a]||c.transitions["*"];t:for(var u=0;u0))return i;if(m.revisit||(t=p.remainder),!m.toContinue)break t}}if(o<=0)throw["MhchemBugU","mhchem bug U. Please report."]}},concatArray:function(t,e){if(e)if(Array.isArray(e))for(var r=0;r":/^[=<>]/,"#":/^[#\u2261]/,"+":/^\+/,"-$":/^-(?=[\s_},;\]/]|$|\([a-z]+\))/,"-9":/^-(?=[0-9])/,"- orbital overlap":/^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/,"-":/^-/,"pm-operator":/^(?:\\pm|\$\\pm\$|\+-|\+\/-)/,operator:/^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/,arrowUpDown:/^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/,"\\bond{(...)}":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\bond{","","","}")},"->":/^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/,CMT:/^[CMT](?=\[)/,"[(...)]":function(t){return mhchemParser.patterns.findObserveGroups(t,"[","","","]")},"1st-level escape":/^(&|\\\\|\\hline)\s*/,"\\,":/^(?:\\[,\ ;:])/,"\\x{}{}":function(t){return mhchemParser.patterns.findObserveGroups(t,"",/^\\[a-zA-Z]+\{/,"}","","","{","}","",!0)},"\\x{}":function(t){return mhchemParser.patterns.findObserveGroups(t,"",/^\\[a-zA-Z]+\{/,"}","")},"\\ca":/^\\ca(?:\s+|(?![a-zA-Z]))/,"\\x":/^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/,orbital:/^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/,others:/^[\/~|]/,"\\frac{(...)}":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\frac{","","","}","{","","","}")},"\\overset{(...)}":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\overset{","","","}","{","","","}")},"\\underset{(...)}":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\underset{","","","}","{","","","}")},"\\underbrace{(...)}":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\underbrace{","","","}_","{","","","}")},"\\color{(...)}0":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\color{","","","}")},"\\color{(...)}{(...)}1":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\color{","","","}","{","","","}")},"\\color(...){(...)}2":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\color","\\","",/^(?=\{)/,"{","","","}")},"\\ce{(...)}":function(t){return mhchemParser.patterns.findObserveGroups(t,"\\ce{","","","}")},oxidation$:/^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,"d-oxidation$":/^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,"roman numeral":/^[IVX]+/,"1/2$":/^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/,amount:function(t){var e;if(e=t.match(/^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/))return{match_:e[0],remainder:t.substr(e[0].length)};var r=mhchemParser.patterns.findObserveGroups(t,"","$","$","");return r&&(e=r.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/))?{match_:e[0],remainder:t.substr(e[0].length)}:null},amount2:function(t){return this.amount(t)},"(KV letters),":/^(?:[A-Z][a-z]{0,2}|i)(?=,)/,formula$:function(t){if(t.match(/^\([a-z]+\)$/))return null;var e=t.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/);return e?{match_:e[0],remainder:t.substr(e[0].length)}:null},uprightEntities:/^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/,"/":/^\s*(\/)\s*/,"//":/^\s*(\/\/)\s*/,"*":/^\s*[*.]\s*/},findObserveGroups:function(t,e,r,a,n,o,i,c,s,u){var p=function(t,e){if("string"==typeof e)return 0!==t.indexOf(e)?null:e;var r=t.match(e);return r?r[0]:null},m=p(t,e);if(null===m)return null;if(t=t.substr(m.length),null===(m=p(t,r)))return null;var h=function(t,e,r){for(var a=0;e":{"0|1|2|3":{action_:"r=",nextState:"r"},"a|as":{action_:["output","r="],nextState:"r"},"*":{action_:["output","r="],nextState:"r"}},"+":{o:{action_:"d= kv",nextState:"d"},"d|D":{action_:"d=",nextState:"d"},q:{action_:"d=",nextState:"qd"},"qd|qD":{action_:"d=",nextState:"qd"},dq:{action_:["output","d="],nextState:"d"},3:{action_:["sb=false","output","operator"],nextState:"0"}},amount:{"0|2":{action_:"a=",nextState:"a"}},"pm-operator":{"0|1|2|a|as":{action_:["sb=false","output",{type_:"operator",option:"\\pm"}],nextState:"0"}},operator:{"0|1|2|a|as":{action_:["sb=false","output","operator"],nextState:"0"}},"-$":{"o|q":{action_:["charge or bond","output"],nextState:"qd"},d:{action_:"d=",nextState:"d"},D:{action_:["output",{type_:"bond",option:"-"}],nextState:"3"},q:{action_:"d=",nextState:"qd"},qd:{action_:"d=",nextState:"qd"},"qD|dq":{action_:["output",{type_:"bond",option:"-"}],nextState:"3"}},"-9":{"3|o":{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"3"}},"- orbital overlap":{o:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"},d:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"}},"-":{"0|1|2":{action_:[{type_:"output",option:1},"beginsWithBond=true",{type_:"bond",option:"-"}],nextState:"3"},3:{action_:{type_:"bond",option:"-"}},a:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"},as:{action_:[{type_:"output",option:2},{type_:"bond",option:"-"}],nextState:"3"},b:{action_:"b="},o:{action_:{type_:"- after o/d",option:!1},nextState:"2"},q:{action_:{type_:"- after o/d",option:!1},nextState:"2"},"d|qd|dq":{action_:{type_:"- after o/d",option:!0},nextState:"2"},"D|qD|p":{action_:["output",{type_:"bond",option:"-"}],nextState:"3"}},amount2:{"1|3":{action_:"a=",nextState:"a"}},letters:{"0|1|2|3|a|as|b|p|bp|o":{action_:"o=",nextState:"o"},"q|dq":{action_:["output","o="],nextState:"o"},"d|D|qd|qD":{action_:"o after d",nextState:"o"}},digits:{o:{action_:"q=",nextState:"q"},"d|D":{action_:"q=",nextState:"dq"},q:{action_:["output","o="],nextState:"o"},a:{action_:"o=",nextState:"o"}},"space A":{"b|p|bp":{}},space:{a:{nextState:"as"},0:{action_:"sb=false"},"1|2":{action_:"sb=true"},"r|rt|rd|rdt|rdq":{action_:"output",nextState:"0"},"*":{action_:["output","sb=true"],nextState:"1"}},"1st-level escape":{"1|2":{action_:["output",{type_:"insert+p1",option:"1st-level escape"}]},"*":{action_:["output",{type_:"insert+p1",option:"1st-level escape"}],nextState:"0"}},"[(...)]":{"r|rt":{action_:"rd=",nextState:"rd"},"rd|rdt":{action_:"rq=",nextState:"rdq"}},"...":{"o|d|D|dq|qd|qD":{action_:["output",{type_:"bond",option:"..."}],nextState:"3"},"*":{action_:[{type_:"output",option:1},{type_:"insert",option:"ellipsis"}],nextState:"1"}},". |* ":{"*":{action_:["output",{type_:"insert",option:"addition compound"}],nextState:"1"}},"state of aggregation $":{"*":{action_:["output","state of aggregation"],nextState:"1"}},"{[(":{"a|as|o":{action_:["o=","output","parenthesisLevel++"],nextState:"2"},"0|1|2|3":{action_:["o=","output","parenthesisLevel++"],nextState:"2"},"*":{action_:["output","o=","output","parenthesisLevel++"],nextState:"2"}},")]}":{"0|1|2|3|b|p|bp|o":{action_:["o=","parenthesisLevel--"],nextState:"o"},"a|as|d|D|q|qd|qD|dq":{action_:["output","o=","parenthesisLevel--"],nextState:"o"}},", ":{"*":{action_:["output","comma"],nextState:"0"}},"^_":{"*":{}},"^{(...)}|^($...$)":{"0|1|2|as":{action_:"b=",nextState:"b"},p:{action_:"b=",nextState:"bp"},"3|o":{action_:"d= kv",nextState:"D"},q:{action_:"d=",nextState:"qD"},"d|D|qd|qD|dq":{action_:["output","d="],nextState:"D"}},"^a|^\\x{}{}|^\\x{}|^\\x|'":{"0|1|2|as":{action_:"b=",nextState:"b"},p:{action_:"b=",nextState:"bp"},"3|o":{action_:"d= kv",nextState:"d"},q:{action_:"d=",nextState:"qd"},"d|qd|D|qD":{action_:"d="},dq:{action_:["output","d="],nextState:"d"}},"_{(state of aggregation)}$":{"d|D|q|qd|qD|dq":{action_:["output","q="],nextState:"q"}},"_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x":{"0|1|2|as":{action_:"p=",nextState:"p"},b:{action_:"p=",nextState:"bp"},"3|o":{action_:"q=",nextState:"q"},"d|D":{action_:"q=",nextState:"dq"},"q|qd|qD|dq":{action_:["output","q="],nextState:"q"}},"=<>":{"0|1|2|3|a|as|o|q|d|D|qd|qD|dq":{action_:[{type_:"output",option:2},"bond"],nextState:"3"}},"#":{"0|1|2|3|a|as|o":{action_:[{type_:"output",option:2},{type_:"bond",option:"#"}],nextState:"3"}},"{}":{"*":{action_:{type_:"output",option:1},nextState:"1"}},"{...}":{"0|1|2|3|a|as|b|p|bp":{action_:"o=",nextState:"o"},"o|d|D|q|qd|qD|dq":{action_:["output","o="],nextState:"o"}},"$...$":{a:{action_:"a="},"0|1|2|3|as|b|p|bp|o":{action_:"o=",nextState:"o"},"as|o":{action_:"o="},"q|d|D|qd|qD|dq":{action_:["output","o="],nextState:"o"}},"\\bond{(...)}":{"*":{action_:[{type_:"output",option:2},"bond"],nextState:"3"}},"\\frac{(...)}":{"*":{action_:[{type_:"output",option:1},"frac-output"],nextState:"3"}},"\\overset{(...)}":{"*":{action_:[{type_:"output",option:2},"overset-output"],nextState:"3"}},"\\underset{(...)}":{"*":{action_:[{type_:"output",option:2},"underset-output"],nextState:"3"}},"\\underbrace{(...)}":{"*":{action_:[{type_:"output",option:2},"underbrace-output"],nextState:"3"}},"\\color{(...)}{(...)}1|\\color(...){(...)}2":{"*":{action_:[{type_:"output",option:2},"color-output"],nextState:"3"}},"\\color{(...)}0":{"*":{action_:[{type_:"output",option:2},"color0-output"]}},"\\ce{(...)}":{"*":{action_:[{type_:"output",option:2},"ce"],nextState:"3"}},"\\,":{"*":{action_:[{type_:"output",option:1},"copy"],nextState:"1"}},"\\x{}{}|\\x{}|\\x":{"0|1|2|3|a|as|b|p|bp|o|c0":{action_:["o=","output"],nextState:"3"},"*":{action_:["output","o=","output"],nextState:"3"}},others:{"*":{action_:[{type_:"output",option:1},"copy"],nextState:"3"}},else2:{a:{action_:"a to o",nextState:"o",revisit:!0},as:{action_:["output","sb=true"],nextState:"1",revisit:!0},"r|rt|rd|rdt|rdq":{action_:["output"],nextState:"0",revisit:!0},"*":{action_:["output","copy"],nextState:"3"}}}),actions:{"o after d":function(t,e){var r;if((t.d||"").match(/^[0-9]+$/)){var a=t.d;t.d=void 0,r=this.output(t),t.b=a}else r=this.output(t);return mhchemParser.actions["o="](t,e),r},"d= kv":function(t,e){t.d=e,t.dType="kv"},"charge or bond":function(t,e){if(t.beginsWithBond){var r=[];return mhchemParser.concatArray(r,this.output(t)),mhchemParser.concatArray(r,mhchemParser.actions.bond(t,e,"-")),r}t.d=e},"- after o/d":function(t,e,r){var a=mhchemParser.patterns.match_("orbital",t.o||""),n=mhchemParser.patterns.match_("one lowercase greek letter $",t.o||""),o=mhchemParser.patterns.match_("one lowercase latin letter $",t.o||""),i=mhchemParser.patterns.match_("$one lowercase latin letter$ $",t.o||""),c="-"===e&&(a&&""===a.remainder||n||o||i);!c||t.a||t.b||t.p||t.d||t.q||a||!o||(t.o="$"+t.o+"$");var s=[];return c?(mhchemParser.concatArray(s,this.output(t)),s.push({type_:"hyphen"})):(a=mhchemParser.patterns.match_("digits",t.d||""),r&&a&&""===a.remainder?(mhchemParser.concatArray(s,mhchemParser.actions["d="](t,e)),mhchemParser.concatArray(s,this.output(t))):(mhchemParser.concatArray(s,this.output(t)),mhchemParser.concatArray(s,mhchemParser.actions.bond(t,e,"-")))),s},"a to o":function(t){t.o=t.a,t.a=void 0},"sb=true":function(t){t.sb=!0},"sb=false":function(t){t.sb=!1},"beginsWithBond=true":function(t){t.beginsWithBond=!0},"beginsWithBond=false":function(t){t.beginsWithBond=!1},"parenthesisLevel++":function(t){t.parenthesisLevel++},"parenthesisLevel--":function(t){t.parenthesisLevel--},"state of aggregation":function(t,e){return{type_:"state of aggregation",p1:mhchemParser.go(e,"o")}},comma:function(t,e){var r=e.replace(/\s*$/,"");return r!==e&&0===t.parenthesisLevel?{type_:"comma enumeration L",p1:r}:{type_:"comma enumeration M",p1:r}},output:function(t,e,r){var a,n,o;t.r?(n="M"===t.rdt?mhchemParser.go(t.rd,"tex-math"):"T"===t.rdt?[{type_:"text",p1:t.rd||""}]:mhchemParser.go(t.rd),o="M"===t.rqt?mhchemParser.go(t.rq,"tex-math"):"T"===t.rqt?[{type_:"text",p1:t.rq||""}]:mhchemParser.go(t.rq),a={type_:"arrow",r:t.r,rd:n,rq:o}):(a=[],(t.a||t.b||t.p||t.o||t.q||t.d||r)&&(t.sb&&a.push({type_:"entitySkip"}),t.o||t.q||t.d||t.b||t.p||2===r?t.o||t.q||t.d||!t.b&&!t.p?t.o&&"kv"===t.dType&&mhchemParser.patterns.match_("d-oxidation$",t.d||"")?t.dType="oxidation":t.o&&"kv"===t.dType&&!t.q&&(t.dType=void 0):(t.o=t.a,t.d=t.b,t.q=t.p,t.a=t.b=t.p=void 0):(t.o=t.a,t.a=void 0),a.push({type_:"chemfive",a:mhchemParser.go(t.a,"a"),b:mhchemParser.go(t.b,"bd"),p:mhchemParser.go(t.p,"pq"),o:mhchemParser.go(t.o,"o"),q:mhchemParser.go(t.q,"pq"),d:mhchemParser.go(t.d,"oxidation"===t.dType?"oxidation":"bd"),dType:t.dType})));for(var i in t)"parenthesisLevel"!==i&&"beginsWithBond"!==i&&delete t[i];return a},"oxidation-output":function(t,e){var r=["{"];return mhchemParser.concatArray(r,mhchemParser.go(e,"oxidation")),r.push("}"),r},"frac-output":function(t,e){return{type_:"frac-ce",p1:mhchemParser.go(e[0]),p2:mhchemParser.go(e[1])}},"overset-output":function(t,e){return{type_:"overset",p1:mhchemParser.go(e[0]),p2:mhchemParser.go(e[1])}},"underset-output":function(t,e){return{type_:"underset",p1:mhchemParser.go(e[0]),p2:mhchemParser.go(e[1])}},"underbrace-output":function(t,e){return{type_:"underbrace",p1:mhchemParser.go(e[0]),p2:mhchemParser.go(e[1])}},"color-output":function(t,e){return{type_:"color",color1:e[0],color2:mhchemParser.go(e[1])}},"r=":function(t,e){t.r=e},"rdt=":function(t,e){t.rdt=e},"rd=":function(t,e){t.rd=e},"rqt=":function(t,e){t.rqt=e},"rq=":function(t,e){t.rq=e},operator:function(t,e,r){return{type_:"operator",kind_:r||e}}}},a:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"1",revisit:!0}},"$(...)$":{"*":{action_:"tex-math tight",nextState:"1"}},",":{"*":{action_:{type_:"insert",option:"commaDecimal"}}},else2:{"*":{action_:"copy"}}}),actions:{}},o:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"1",revisit:!0}},letters:{"*":{action_:"rm"}},"\\ca":{"*":{action_:{type_:"insert",option:"circa"}}},"\\x{}{}|\\x{}|\\x":{"*":{action_:"copy"}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"{(...)}":{"*":{action_:"{text}"}},else2:{"*":{action_:"copy"}}}),actions:{}},text:{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"{...}":{"*":{action_:"text="}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"\\greek":{"*":{action_:["output","rm"]}},"\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:["output","copy"]}},else:{"*":{action_:"text="}}}),actions:{output:function(t){if(t.text_){var e={type_:"text",p1:t.text_};for(var r in t)delete t[r];return e}}}},pq:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"state of aggregation $":{"*":{action_:"state of aggregation"}},i$:{0:{nextState:"!f",revisit:!0}},"(KV letters),":{0:{action_:"rm",nextState:"0"}},formula$:{0:{nextState:"f",revisit:!0}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"!f",revisit:!0}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"{(...)}":{"*":{action_:"text"}},"a-z":{f:{action_:"tex-math"}},letters:{"*":{action_:"rm"}},"-9.,9":{"*":{action_:"9,9"}},",":{"*":{action_:{type_:"insert+p1",option:"comma enumeration S"}}},"\\color{(...)}{(...)}1|\\color(...){(...)}2":{"*":{action_:"color-output"}},"\\color{(...)}0":{"*":{action_:"color0-output"}},"\\ce{(...)}":{"*":{action_:"ce"}},"\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"copy"}},else2:{"*":{action_:"copy"}}}),actions:{"state of aggregation":function(t,e){return{type_:"state of aggregation subscript",p1:mhchemParser.go(e,"o")}},"color-output":function(t,e){return{type_:"color",color1:e[0],color2:mhchemParser.go(e[1],"pq")}}}},bd:{transitions:mhchemParser.createTransitions({empty:{"*":{}},x$:{0:{nextState:"!f",revisit:!0}},formula$:{0:{nextState:"f",revisit:!0}},else:{0:{nextState:"!f",revisit:!0}},"-9.,9 no missing 0":{"*":{action_:"9,9"}},".":{"*":{action_:{type_:"insert",option:"electron dot"}}},"a-z":{f:{action_:"tex-math"}},x:{"*":{action_:{type_:"insert",option:"KV x"}}},letters:{"*":{action_:"rm"}},"'":{"*":{action_:{type_:"insert",option:"prime"}}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"{(...)}":{"*":{action_:"text"}},"\\color{(...)}{(...)}1|\\color(...){(...)}2":{"*":{action_:"color-output"}},"\\color{(...)}0":{"*":{action_:"color0-output"}},"\\ce{(...)}":{"*":{action_:"ce"}},"\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"copy"}},else2:{"*":{action_:"copy"}}}),actions:{"color-output":function(t,e){return{type_:"color",color1:e[0],color2:mhchemParser.go(e[1],"bd")}}}},oxidation:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"roman numeral":{"*":{action_:"roman-numeral"}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},else:{"*":{action_:"copy"}}}),actions:{"roman-numeral":function(t,e){return{type_:"roman numeral",p1:e||""}}}},"tex-math":{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"\\ce{(...)}":{"*":{action_:["output","ce"]}},"{...}|\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"o="}},else:{"*":{action_:"o="}}}),actions:{output:function(t){if(t.o){var e={type_:"tex-math",p1:t.o};for(var r in t)delete t[r];return e}}}},"tex-math tight":{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"\\ce{(...)}":{"*":{action_:["output","ce"]}},"{...}|\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"o="}},"-|+":{"*":{action_:"tight operator"}},else:{"*":{action_:"o="}}}),actions:{"tight operator":function(t,e){t.o=(t.o||"")+"{"+e+"}"},output:function(t){if(t.o){var e={type_:"tex-math",p1:t.o};for(var r in t)delete t[r];return e}}}},"9,9":{transitions:mhchemParser.createTransitions({empty:{"*":{}},",":{"*":{action_:"comma"}},else:{"*":{action_:"copy"}}}),actions:{comma:function(){return{type_:"commaDecimal"}}}},pu:{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},space$:{"*":{action_:["output","space"]}},"{[(|)]}":{"0|a":{action_:"copy"}},"(-)(9)^(-9)":{0:{action_:"number^",nextState:"a"}},"(-)(9.,9)(e)(99)":{0:{action_:"enumber",nextState:"a"}},space:{"0|a":{}},"pm-operator":{"0|a":{action_:{type_:"operator",option:"\\pm"},nextState:"0"}},operator:{"0|a":{action_:"copy",nextState:"0"}},"//":{d:{action_:"o=",nextState:"/"}},"/":{d:{action_:"o=",nextState:"/"}},"{...}|else":{"0|d":{action_:"d=",nextState:"d"},a:{action_:["space","d="],nextState:"d"},"/|q":{action_:"q=",nextState:"q"}}}),actions:{enumber:function(t,e){var r=[];return"+-"===e[0]||"+/-"===e[0]?r.push("\\pm "):e[0]&&r.push(e[0]),e[1]&&(mhchemParser.concatArray(r,mhchemParser.go(e[1],"pu-9,9")),e[2]&&(e[2].match(/[,.]/)?mhchemParser.concatArray(r,mhchemParser.go(e[2],"pu-9,9")):r.push(e[2])),e[3]=e[4]||e[3],e[3]&&(e[3]=e[3].trim(),"e"===e[3]||"*"===e[3].substr(0,1)?r.push({type_:"cdot"}):r.push({type_:"times"}))),e[3]&&r.push("10^{"+e[5]+"}"),r},"number^":function(t,e){var r=[];return"+-"===e[0]||"+/-"===e[0]?r.push("\\pm "):e[0]&&r.push(e[0]),mhchemParser.concatArray(r,mhchemParser.go(e[1],"pu-9,9")),r.push("^{"+e[2]+"}"),r},operator:function(t,e,r){return{type_:"operator",kind_:r||e}},space:function(){return{type_:"pu-space-1"}},output:function(t){var e,r=mhchemParser.patterns.match_("{(...)}",t.d||"");r&&""===r.remainder&&(t.d=r.match_);var a=mhchemParser.patterns.match_("{(...)}",t.q||"");if(a&&""===a.remainder&&(t.q=a.match_),t.d&&(t.d=t.d.replace(/\u00B0C|\^oC|\^{o}C/g,"{}^{\\circ}C"),t.d=t.d.replace(/\u00B0F|\^oF|\^{o}F/g,"{}^{\\circ}F")),t.q){t.q=t.q.replace(/\u00B0C|\^oC|\^{o}C/g,"{}^{\\circ}C"),t.q=t.q.replace(/\u00B0F|\^oF|\^{o}F/g,"{}^{\\circ}F");var n={d:mhchemParser.go(t.d,"pu"),q:mhchemParser.go(t.q,"pu")};"//"===t.o?e={type_:"pu-frac",p1:n.d,p2:n.q}:(e=n.d,n.d.length>1||n.q.length>1?e.push({type_:" / "}):e.push({type_:"/"}),mhchemParser.concatArray(e,n.q))}else e=mhchemParser.go(t.d,"pu-2");for(var o in t)delete t[o];return e}}},"pu-2":{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"*":{"*":{action_:["output","cdot"],nextState:"0"}},"\\x":{"*":{action_:"rm="}},space:{"*":{action_:["output","space"],nextState:"0"}},"^{(...)}|^(-1)":{1:{action_:"^(-1)"}},"-9.,9":{0:{action_:"rm=",nextState:"0"},1:{action_:"^(-1)",nextState:"0"}},"{...}|else":{"*":{action_:"rm=",nextState:"1"}}}),actions:{cdot:function(){return{type_:"tight cdot"}},"^(-1)":function(t,e){t.rm+="^{"+e+"}"},space:function(){return{type_:"pu-space-2"}},output:function(t){var e=[];if(t.rm){var r=mhchemParser.patterns.match_("{(...)}",t.rm||"");e=r&&""===r.remainder?mhchemParser.go(r.match_,"pu"):{type_:"rm",p1:t.rm}}for(var a in t)delete t[a];return e}}},"pu-9,9":{transitions:mhchemParser.createTransitions({empty:{0:{action_:"output-0"},o:{action_:"output-o"}},",":{0:{action_:["output-0","comma"],nextState:"o"}},".":{0:{action_:["output-0","copy"],nextState:"o"}},else:{"*":{action_:"text="}}}),actions:{comma:function(){return{type_:"commaDecimal"}},"output-0":function(t){var e=[];if(t.text_=t.text_||"",t.text_.length>4){var r=t.text_.length%3;0===r&&(r=3);for(var a=t.text_.length-3;a>0;a-=3)e.push(t.text_.substr(a,3)),e.push({type_:"1000 separator"});e.push(t.text_.substr(0,r)),e.reverse()}else e.push(t.text_);for(var n in t)delete t[n];return e},"output-o":function(t){var e=[];if(t.text_=t.text_||"",t.text_.length>4){for(var r=t.text_.length-3,a=0;a":case"→":case"⟶":return"\\yields";case"<-":return"\\yieldsLeft";case"<->":return"\\mesomerism";case"<--\x3e":return"\\yieldsLeftRight";case"<=>":case"⇌":return"\\equilibrium";case"<=>>":return"\\equilibriumRight";case"<<=>":return"\\equilibriumLeft";default:throw assertNever(t),["MhchemBugT","mhchem bug T. Please report."]}},_getBond:function(t){switch(t){case"-":case"1":return"{-}";case"=":case"2":return"{=}";case"#":case"3":return"{\\equiv}";case"~":return"{\\tripleDash}";case"~-":return"{\\tripleDashOverLine}";case"~=":case"~--":return"{\\tripleDashOverDoubleLine}";case"-~-":return"{\\tripleDashBetweenDoubleLine}";case"...":return"{{\\cdot}{\\cdot}{\\cdot}}";case"....":return"{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}";case"->":return"{\\rightarrow}";case"<-":return"{\\leftarrow}";case"<":return"{<}";case">":return"{>}";default:throw assertNever(t),["MhchemBugT","mhchem bug T. Please report."]}},_getOperator:function(t){switch(t){case"+":return" {}+{} ";case"-":return" {}-{} ";case"=":return" {}={} ";case"<":return" {}<{} ";case">":return" {}>{} ";case"<<":return" {}\\ll{} ";case">>":return" {}\\gg{} ";case"\\pm":return" {}\\pm{} ";case"\\approx":case"$\\approx$":return" {}\\approx{} ";case"v":case"(v)":return" \\downarrow{} ";case"^":case"(^)":return" \\uparrow{} ";default:throw assertNever(t),["MhchemBugT","mhchem bug T. Please report."]}}};function assertNever(t){}function assertString(t){} \ No newline at end of file diff --git a/site/assets/physics.js b/site/assets/physics.js deleted file mode 100644 index 803ccc31..00000000 --- a/site/assets/physics.js +++ /dev/null @@ -1,132 +0,0 @@ -/* eslint-disable no-undef */ - -/**************************************************** - * - * physics.js - * - * Implements the Physics Package for LaTeX input. - * - * --------------------------------------------------------------------- - * - * The original version of this file is licensed as follows: - * Copyright (c) 2015-2016 Kolen Cheung . - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * --------------------------------------------------------------------- - * - * This file has been revised from the original in the following ways: - * 1. The interface is changed so that it can be called from Temml, not MathJax. - * 2. \Re and \Im are not used, to avoid conflict with existing LaTeX letters. - * - * This revision of the file is released under the MIT license. - * https://mit-license.org/ - */ -temml.__defineMacro("\\quantity", "{\\left\\{ #1 \\right\\}}"); -temml.__defineMacro("\\qty", "{\\left\\{ #1 \\right\\}}"); -temml.__defineMacro("\\pqty", "{\\left( #1 \\right)}"); -temml.__defineMacro("\\bqty", "{\\left[ #1 \\right]}"); -temml.__defineMacro("\\vqty", "{\\left\\vert #1 \\right\\vert}"); -temml.__defineMacro("\\Bqty", "{\\left\\{ #1 \\right\\}}"); -temml.__defineMacro("\\absolutevalue", "{\\left\\vert #1 \\right\\vert}"); -temml.__defineMacro("\\abs", "{\\left\\vert #1 \\right\\vert}"); -temml.__defineMacro("\\norm", "{\\left\\Vert #1 \\right\\Vert}"); -temml.__defineMacro("\\evaluated", "{\\left.#1 \\right\\vert}"); -temml.__defineMacro("\\eval", "{\\left.#1 \\right\\vert}"); -temml.__defineMacro("\\order", "{\\mathcal{O} \\left( #1 \\right)}"); -temml.__defineMacro("\\commutator", "{\\left[ #1 , #2 \\right]}"); -temml.__defineMacro("\\comm", "{\\left[ #1 , #2 \\right]}"); -temml.__defineMacro("\\anticommutator", "{\\left\\{ #1 , #2 \\right\\}}"); -temml.__defineMacro("\\acomm", "{\\left\\{ #1 , #2 \\right\\}}"); -temml.__defineMacro("\\poissonbracket", "{\\left\\{ #1 , #2 \\right\\}}"); -temml.__defineMacro("\\pb", "{\\left\\{ #1 , #2 \\right\\}}"); -temml.__defineMacro("\\vectorbold", "{\\boldsymbol{ #1 }}"); -temml.__defineMacro("\\vb", "{\\boldsymbol{ #1 }}"); -temml.__defineMacro("\\vectorarrow", "{\\vec{\\boldsymbol{ #1 }}}"); -temml.__defineMacro("\\va", "{\\vec{\\boldsymbol{ #1 }}}"); -temml.__defineMacro("\\vectorunit", "{{\\boldsymbol{\\hat{ #1 }}}}"); -temml.__defineMacro("\\vu", "{{\\boldsymbol{\\hat{ #1 }}}}"); -temml.__defineMacro("\\dotproduct", "\\mathbin{\\boldsymbol\\cdot}"); -temml.__defineMacro("\\vdot", "{\\boldsymbol\\cdot}"); -temml.__defineMacro("\\crossproduct", "\\mathbin{\\boldsymbol\\times}"); -temml.__defineMacro("\\cross", "\\mathbin{\\boldsymbol\\times}"); -temml.__defineMacro("\\cp", "\\mathbin{\\boldsymbol\\times}"); -temml.__defineMacro("\\gradient", "{\\boldsymbol\\nabla}"); -temml.__defineMacro("\\grad", "{\\boldsymbol\\nabla}"); -temml.__defineMacro("\\divergence", "{\\grad\\vdot}"); -//temml.__defineMacro("\\div", "{\\grad\\vdot}"); Not included in Temml. Conflicts w/LaTeX \div -temml.__defineMacro("\\curl", "{\\grad\\cross}"); -temml.__defineMacro("\\laplacian", "\\nabla^2"); -temml.__defineMacro("\\tr", "{\\operatorname{tr}}"); -temml.__defineMacro("\\Tr", "{\\operatorname{Tr}}"); -temml.__defineMacro("\\rank", "{\\operatorname{rank}}"); -temml.__defineMacro("\\erf", "{\\operatorname{erf}}"); -temml.__defineMacro("\\Res", "{\\operatorname{Res}}"); -temml.__defineMacro("\\principalvalue", "{\\mathcal{P}}"); -temml.__defineMacro("\\pv", "{\\mathcal{P}}"); -temml.__defineMacro("\\PV", "{\\operatorname{P.V.}}"); -// Temml does not use the next two lines. They conflict with LaTeX letters. -//temml.__defineMacro("\\Re", "{\\operatorname{Re} \\left\\{ #1 \\right\\}}"); -//temml.__defineMacro("\\Im", "{\\operatorname{Im} \\left\\{ #1 \\right\\}}"); -temml.__defineMacro("\\qqtext", "{\\quad\\text{ #1 }\\quad}"); -temml.__defineMacro("\\qq", "{\\quad\\text{ #1 }\\quad}"); -temml.__defineMacro("\\qcomma", "{\\text{,}\\quad}"); -temml.__defineMacro("\\qc", "{\\text{,}\\quad}"); -temml.__defineMacro("\\qcc", "{\\quad\\text{c.c.}\\quad}"); -temml.__defineMacro("\\qif", "{\\quad\\text{if}\\quad}"); -temml.__defineMacro("\\qthen", "{\\quad\\text{then}\\quad}"); -temml.__defineMacro("\\qelse", "{\\quad\\text{else}\\quad}"); -temml.__defineMacro("\\qotherwise", "{\\quad\\text{otherwise}\\quad}"); -temml.__defineMacro("\\qunless", "{\\quad\\text{unless}\\quad}"); -temml.__defineMacro("\\qgiven", "{\\quad\\text{given}\\quad}"); -temml.__defineMacro("\\qusing", "{\\quad\\text{using}\\quad}"); -temml.__defineMacro("\\qassume", "{\\quad\\text{assume}\\quad}"); -temml.__defineMacro("\\qsince", "{\\quad\\text{since}\\quad}"); -temml.__defineMacro("\\qlet", "{\\quad\\text{let}\\quad}"); -temml.__defineMacro("\\qfor", "{\\quad\\text{for}\\quad}"); -temml.__defineMacro("\\qall", "{\\quad\\text{all}\\quad}"); -temml.__defineMacro("\\qeven", "{\\quad\\text{even}\\quad}"); -temml.__defineMacro("\\qodd", "{\\quad\\text{odd}\\quad}"); -temml.__defineMacro("\\qinteger", "{\\quad\\text{integer}\\quad}"); -temml.__defineMacro("\\qand", "{\\quad\\text{and}\\quad}"); -temml.__defineMacro("\\qor", "{\\quad\\text{or}\\quad}"); -temml.__defineMacro("\\qas", "{\\quad\\text{as}\\quad}"); -temml.__defineMacro("\\qin", "{\\quad\\text{in}\\quad}"); -temml.__defineMacro("\\differential", "{\\text{d}}"); -temml.__defineMacro("\\dd", "{\\text{d}}"); -temml.__defineMacro("\\derivative", "{\\frac{\\text{d}{ #1 }}{\\text{d}{ #2 }}}"); -temml.__defineMacro("\\dv", "{\\frac{\\text{d}{ #1 }}{\\text{d}{ #2 }}}"); -temml.__defineMacro("\\partialderivative", "{\\frac{\\partial{ #1 }}{\\partial{ #2 }}}"); -temml.__defineMacro("\\pdv", "{\\frac{\\partial{ #1 }}{\\partial{ #2 }}}"); -temml.__defineMacro("\\variation", "{\\delta}"); -temml.__defineMacro("\\var", "{\\delta}"); -temml.__defineMacro("\\functionalderivative", "{\\frac{\\delta{ #1 }}{\\delta{ #2 }}}"); -temml.__defineMacro("\\fdv", "{\\frac{\\delta{ #1 }}{\\delta{ #2 }}}"); -temml.__defineMacro("\\innerproduct", "{\\left\\langle {#1} \\mid { #2} \\right\\rangle}"); -temml.__defineMacro("\\outerproduct", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -temml.__defineMacro("\\dyad", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -temml.__defineMacro("\\ketbra", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -temml.__defineMacro("\\op", - "{\\left\\vert { #1 } \\right\\rangle\\left\\langle { #2} \\right\\vert}"); -temml.__defineMacro("\\expectationvalue", "{\\left\\langle {#1 } \\right\\rangle}"); -temml.__defineMacro("\\expval", "{\\left\\langle {#1 } \\right\\rangle}"); -temml.__defineMacro("\\ev", "{\\left\\langle {#1 } \\right\\rangle}"); -temml.__defineMacro("\\matrixelement", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); -temml.__defineMacro("\\matrixel", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); -temml.__defineMacro("\\mel", - "{\\left\\langle{ #1 }\\right\\vert{ #2 }\\left\\vert{#3}\\right\\rangle}"); diff --git a/site/assets/temml.min.js b/site/assets/temml.min.js deleted file mode 100644 index b71c30cd..00000000 --- a/site/assets/temml.min.js +++ /dev/null @@ -1 +0,0 @@ -var temml=function(){"use strict";class e{constructor(t,r){let n,o=" "+t;const s=r&&r.loc;if(s&&s.start<=s.end){const e=s.lexer.input;n=s.start;const t=s.end;n===e.length?o+=" at end of input: ":o+=" at position "+(n+1)+": ";const r=e.slice(n,t).replace(/[^]/g,"$&̲");let a,i;a=n>15?"…"+e.slice(n-15,n):e.slice(0,n),i=t+15":">","<":"<",'"':""","'":"'"},n=/[&><"']/g;const o=function(e){return"ordgroup"===e.type||"color"===e.type?1===e.body.length?o(e.body[0]):e:"font"===e.type?o(e.body):e};var s={contains:function(e,t){return-1!==e.indexOf(t)},deflt:function(e,t){return void 0===e?t:e},escape:function(e){return String(e).replace(n,(e=>r[e]))},hyphenate:function(e){return e.replace(t,"-$1").toLowerCase()},getBaseElem:o,isCharacterBox:function(e){const t=o(e);return"mathord"===t.type||"textord"===t.type||"atom"===t.type},protocolFromUrl:function(e){const t=/^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(e);return null!=t?t[1]:"_relative"},round:function(e){return+e.toFixed(4)},consolidateText:e=>{if("mrow"!==e.type)return e;if(0===e.children.length)return e;const t=e.children[0];if(!t.attributes||"mtext"!==t.type)return e;const r=t.attributes.mathvariant||"";for(let n=1;n0&&" "===t.children[0].text.charAt(n-1)&&(t.children[0].text=t.children[0].text.slice(0,-1)+" "),t}};class a{constructor(e){e=e||{},this.displayMode=s.deflt(e.displayMode,!1),this.annotate=s.deflt(e.annotate,!1),this.elementIsMath=s.deflt(e.elementIsMath,!1),this.leqno=s.deflt(e.leqno,!1),this.errorColor=s.deflt(e.errorColor,"#b22222"),this.preventTagLap=s.deflt(e.preventTagLap,!1),this.macros=e.macros||{},this.xml=s.deflt(e.xml,!1),this.colorIsTextColor=s.deflt(e.colorIsTextColor,!1),this.strict=s.deflt(e.strict,!1),this.trust=s.deflt(e.trust,!1),this.maxSize=void 0===e.maxSize?[1/0,1/0]:Array.isArray(e.maxSize)?e.maxSize:[1/0,1/0],this.maxExpand=Math.max(0,s.deflt(e.maxExpand,1e3))}isTrusted(e){e.url&&!e.protocol&&(e.protocol=s.protocolFromUrl(e.url));const t="function"==typeof this.trust?this.trust(e):this.trust;return Boolean(t)}}const i={},l={};function c({type:e,names:t,props:r,handler:n,mathmlBuilder:o}){const s={type:e,numArgs:r.numArgs,argTypes:r.argTypes,allowedInArgument:!!r.allowedInArgument,allowedInText:!!r.allowedInText,allowedInMath:void 0===r.allowedInMath||r.allowedInMath,numOptionalArgs:r.numOptionalArgs||0,infix:!!r.infix,primitive:!!r.primitive,handler:n};for(let e=0;ee.toText())).join("")}}const h=function(e){return e.filter((e=>e)).join(" ")},g=function(e,t){this.classes=e||[],this.attributes={},this.style=t||{}},f=function(e){const t=document.createElement(e);t.className=h(this.classes);for(const e in this.style)Object.prototype.hasOwnProperty.call(this.style,e)&&(t.style[e]=this.style[e]);for(const e in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,e)&&t.setAttribute(e,this.attributes[e]);for(let e=0;e`,t};class y{constructor(e,t,r){g.call(this,e,r),this.children=t||[]}setAttribute(e,t){this.attributes[e]=t}toNode(){return f.call(this,"span")}toMarkup(){return b.call(this,"span")}}class w{constructor(e){this.text=e}toNode(){return document.createTextNode(this.text)}toMarkup(){return s.escape(this.text)}}class x{constructor(e,t,r){this.alt=t,this.src=e,this.classes=["mord"],this.style=r}hasClass(e){return s.contains(this.classes,e)}toNode(){const e=document.createElement("img");e.src=this.src,e.alt=this.alt,e.className="mord";for(const t in this.style)Object.prototype.hasOwnProperty.call(this.style,t)&&(e.style[t]=this.style[t]);return e}toMarkup(){let e=`${this.alt}0&&(e.className=h(this.classes));for(const t in this.style)Object.prototype.hasOwnProperty.call(this.style,t)&&(e.style[t]=this.style[t]);for(let t=0;t0&&(e+=` class="${s.escape(h(this.classes))}"`);let t="";for(const e in this.style)Object.prototype.hasOwnProperty.call(this.style,e)&&(t+=`${s.hyphenate(e)}:${this.style[e]};`);t&&(e+=` style="${t}"`),e+=">";for(let t=0;t",e}toText(){return this.children.map((e=>e.toText())).join("")}}class A{constructor(e){this.text=e}toNode(){return document.createTextNode(this.text)}toMarkup(){return s.escape(this.toText())}toText(){return this.text}}const v=e=>{let t;return 1===e.length&&"mrow"===e[0].type?(t=e.pop(),t.type="mstyle"):t=new k("mstyle",e),t};var T={MathNode:k,TextNode:A,newDocumentFragment:function(e){return new d(e)}};const N={widehat:"^",widecheck:"ˇ",widetilde:"~",wideparen:"⏜",utilde:"~",overleftarrow:"←",underleftarrow:"←",xleftarrow:"←",overrightarrow:"→",underrightarrow:"→",xrightarrow:"→",underbrace:"⏟",overbrace:"⏞",overgroup:"⏠",overparen:"⏜",undergroup:"⏡",underparen:"⏝",overleftrightarrow:"↔",underleftrightarrow:"↔",xleftrightarrow:"↔",Overrightarrow:"⇒",xRightarrow:"⇒",overleftharpoon:"↼",xleftharpoonup:"↼",overrightharpoon:"⇀",xrightharpoonup:"⇀",xLeftarrow:"⇐",xLeftrightarrow:"⇔",xhookleftarrow:"↩",xhookrightarrow:"↪",xmapsto:"↦",xrightharpoondown:"⇁",xleftharpoondown:"↽",xtwoheadleftarrow:"↞",xtwoheadrightarrow:"↠",xlongequal:"=",xrightleftarrows:"⇄",yields:"→",yieldsLeft:"←",mesomerism:"↔",longrightharpoonup:"⇀",longleftharpoondown:"↽",eqrightharpoonup:"⇀",eqleftharpoondown:"↽","\\cdrightarrow":"→","\\cdleftarrow":"←","\\cdlongequal":"="};var S=function(e){const t=new T.TextNode(N[e.slice(1)]),r=new T.MathNode("mo",[t]);return r.setAttribute("stretchy","true"),r};const q={bin:1,close:1,inner:1,open:1,punct:1,rel:1},B={"accent-token":1,mathord:1,"op-token":1,spacing:1,textord:1},M={math:{},text:{}};function O(e,t,r,n,o){M[e][n]={group:t,replace:r},o&&r&&(M[e][r]=M[e][n])}const C="math",z="text",E="accent-token",I="bin",L="close",$="inner",F="mathord",G="op-token",D="open",P="punct",R="rel",j="spacing",U="textord";O(C,R,"≡","\\equiv",!0),O(C,R,"≺","\\prec",!0),O(C,R,"≻","\\succ",!0),O(C,R,"∼","\\sim",!0),O(C,R,"⟂","\\perp",!0),O(C,R,"⪯","\\preceq",!0),O(C,R,"⪰","\\succeq",!0),O(C,R,"≃","\\simeq",!0),O(C,R,"≌","\\backcong",!0),O(C,R,"|","\\mid",!0),O(C,R,"≪","\\ll",!0),O(C,R,"≫","\\gg",!0),O(C,R,"≍","\\asymp",!0),O(C,R,"∥","\\parallel"),O(C,R,"⋈","\\bowtie",!0),O(C,R,"⌣","\\smile",!0),O(C,R,"⊑","\\sqsubseteq",!0),O(C,R,"⊒","\\sqsupseteq",!0),O(C,R,"≐","\\doteq",!0),O(C,R,"⌢","\\frown",!0),O(C,R,"∋","\\ni",!0),O(C,R,"∌","\\notni",!0),O(C,R,"∝","\\propto",!0),O(C,R,"⊢","\\vdash",!0),O(C,R,"⊣","\\dashv",!0),O(C,R,"∋","\\owns"),O(C,R,"≘","\\arceq",!0),O(C,R,"≙","\\wedgeq",!0),O(C,R,"≚","\\veeeq",!0),O(C,R,"≛","\\stareq",!0),O(C,R,"≝","\\eqdef",!0),O(C,R,"≞","\\measeq",!0),O(C,R,"≟","\\questeq",!0),O(C,R,"≠","\\ne",!0),O(C,R,"≠","\\neq"),O(C,R,"∷","\\dblcolon",!0),O(C,R,"≔","\\coloneqq",!0),O(C,R,"≕","\\eqqcolon",!0),O(C,R,"∹","\\eqcolon",!0),O(C,R,"⩴","\\Coloneqq",!0),O(C,P,".","\\ldotp"),O(C,P,"·","\\cdotp"),O(C,U,"#","\\#"),O(z,U,"#","\\#"),O(C,U,"&","\\&"),O(z,U,"&","\\&"),O(C,U,"ℵ","\\aleph",!0),O(C,U,"∀","\\forall",!0),O(C,U,"ℏ","\\hbar",!0),O(C,U,"∃","\\exists",!0),O(C,U,"∇","\\nabla",!0),O(C,U,"♭","\\flat",!0),O(C,U,"ℓ","\\ell",!0),O(C,U,"♮","\\natural",!0),O(C,U,"Å","\\AA",!0),O(z,U,"Å","\\AA",!0),O(C,U,"♣","\\clubsuit",!0),O(C,U,"♧","\\varclubsuit",!0),O(C,U,"℘","\\wp",!0),O(C,U,"♯","\\sharp",!0),O(C,U,"♢","\\diamondsuit",!0),O(C,U,"♦","\\vardiamondsuit",!0),O(C,U,"ℜ","\\Re",!0),O(C,U,"♡","\\heartsuit",!0),O(C,U,"♥","\\varheartsuit",!0),O(C,U,"ℑ","\\Im",!0),O(C,U,"♠","\\spadesuit",!0),O(C,U,"♤","\\varspadesuit",!0),O(C,U,"♀","\\female",!0),O(C,U,"♂","\\male",!0),O(C,U,"§","\\S",!0),O(z,U,"§","\\S"),O(C,U,"¶","\\P",!0),O(z,U,"¶","\\P"),O(z,U,"☺","\\smiley",!0),O(C,U,"☺","\\smiley",!0),O(C,U,"†","\\dag"),O(z,U,"†","\\dag"),O(z,U,"†","\\textdagger"),O(C,U,"‡","\\ddag"),O(z,U,"‡","\\ddag"),O(z,U,"‡","\\textdaggerdbl"),O(C,L,"⎱","\\rmoustache",!0),O(C,D,"⎰","\\lmoustache",!0),O(C,L,"⟯","\\rgroup",!0),O(C,D,"⟮","\\lgroup",!0),O(C,I,"∓","\\mp",!0),O(C,I,"⊖","\\ominus",!0),O(C,I,"⊎","\\uplus",!0),O(C,I,"⊓","\\sqcap",!0),O(C,I,"∗","\\ast"),O(C,I,"⊔","\\sqcup",!0),O(C,I,"◯","\\bigcirc",!0),O(C,I,"∙","\\bullet",!0),O(C,I,"‡","\\ddagger"),O(C,I,"≀","\\wr",!0),O(C,I,"⨿","\\amalg"),O(C,I,"&","\\And"),O(C,R,"⟵","\\longleftarrow",!0),O(C,R,"⇐","\\Leftarrow",!0),O(C,R,"⟸","\\Longleftarrow",!0),O(C,R,"⟶","\\longrightarrow",!0),O(C,R,"⇒","\\Rightarrow",!0),O(C,R,"⟹","\\Longrightarrow",!0),O(C,R,"↔","\\leftrightarrow",!0),O(C,R,"⟷","\\longleftrightarrow",!0),O(C,R,"⇔","\\Leftrightarrow",!0),O(C,R,"⟺","\\Longleftrightarrow",!0),O(C,R,"↦","\\mapsto",!0),O(C,R,"⟼","\\longmapsto",!0),O(C,R,"↗","\\nearrow",!0),O(C,R,"↩","\\hookleftarrow",!0),O(C,R,"↪","\\hookrightarrow",!0),O(C,R,"↘","\\searrow",!0),O(C,R,"↼","\\leftharpoonup",!0),O(C,R,"⇀","\\rightharpoonup",!0),O(C,R,"↙","\\swarrow",!0),O(C,R,"↽","\\leftharpoondown",!0),O(C,R,"⇁","\\rightharpoondown",!0),O(C,R,"↖","\\nwarrow",!0),O(C,R,"⇌","\\rightleftharpoons",!0),O(C,F,"↯","\\lightning",!0),O(C,F,"‰","\\permil",!0),O(z,U,"‰","\\permil"),O(C,R,"≮","\\nless",!0),O(C,R,"⪇","\\lneq",!0),O(C,R,"≨","\\lneqq",!0),O(C,R,"≨︀","\\lvertneqq"),O(C,R,"⋦","\\lnsim",!0),O(C,R,"⪉","\\lnapprox",!0),O(C,R,"⊀","\\nprec",!0),O(C,R,"⋠","\\npreceq",!0),O(C,R,"⋨","\\precnsim",!0),O(C,R,"⪹","\\precnapprox",!0),O(C,R,"≁","\\nsim",!0),O(C,R,"∤","\\nmid",!0),O(C,R,"∤","\\nshortmid"),O(C,R,"⊬","\\nvdash",!0),O(C,R,"⊭","\\nvDash",!0),O(C,R,"⋪","\\ntriangleleft"),O(C,R,"⋬","\\ntrianglelefteq",!0),O(C,R,"⊄","\\nsubset",!0),O(C,R,"⊅","\\nsupset",!0),O(C,R,"⊊","\\subsetneq",!0),O(C,R,"⊊︀","\\varsubsetneq"),O(C,R,"⫋","\\subsetneqq",!0),O(C,R,"⫋︀","\\varsubsetneqq"),O(C,R,"≯","\\ngtr",!0),O(C,R,"⪈","\\gneq",!0),O(C,R,"≩","\\gneqq",!0),O(C,R,"≩︀","\\gvertneqq"),O(C,R,"⋧","\\gnsim",!0),O(C,R,"⪊","\\gnapprox",!0),O(C,R,"⊁","\\nsucc",!0),O(C,R,"⋡","\\nsucceq",!0),O(C,R,"⋩","\\succnsim",!0),O(C,R,"⪺","\\succnapprox",!0),O(C,R,"≆","\\ncong",!0),O(C,R,"∦","\\nparallel",!0),O(C,R,"∦","\\nshortparallel"),O(C,R,"⊯","\\nVDash",!0),O(C,R,"⋫","\\ntriangleright"),O(C,R,"⋭","\\ntrianglerighteq",!0),O(C,R,"⊋","\\supsetneq",!0),O(C,R,"⊋","\\varsupsetneq"),O(C,R,"⫌","\\supsetneqq",!0),O(C,R,"⫌︀","\\varsupsetneqq"),O(C,R,"⊮","\\nVdash",!0),O(C,R,"⪵","\\precneqq",!0),O(C,R,"⪶","\\succneqq",!0),O(C,I,"⊴","\\unlhd"),O(C,I,"⊵","\\unrhd"),O(C,R,"↚","\\nleftarrow",!0),O(C,R,"↛","\\nrightarrow",!0),O(C,R,"⇍","\\nLeftarrow",!0),O(C,R,"⇏","\\nRightarrow",!0),O(C,R,"↮","\\nleftrightarrow",!0),O(C,R,"⇎","\\nLeftrightarrow",!0),O(C,R,"△","\\vartriangle"),O(C,U,"ℏ","\\hslash"),O(C,U,"▽","\\triangledown"),O(C,U,"◊","\\lozenge"),O(C,U,"Ⓢ","\\circledS"),O(C,U,"®","\\circledR",!0),O(z,U,"®","\\circledR"),O(z,U,"®","\\textregistered"),O(C,U,"∡","\\measuredangle",!0),O(C,U,"∄","\\nexists"),O(C,U,"℧","\\mho"),O(C,U,"Ⅎ","\\Finv",!0),O(C,U,"⅁","\\Game",!0),O(C,U,"‵","\\backprime"),O(C,U,"▲","\\blacktriangle"),O(C,U,"▼","\\blacktriangledown"),O(C,U,"■","\\blacksquare"),O(C,U,"⧫","\\blacklozenge"),O(C,U,"★","\\bigstar"),O(C,U,"∢","\\sphericalangle",!0),O(C,U,"∁","\\complement",!0),O(C,U,"ð","\\eth",!0),O(z,U,"ð","ð"),O(C,U,"╱","\\diagup"),O(C,U,"╲","\\diagdown"),O(C,U,"□","\\square"),O(C,U,"□","\\Box"),O(C,U,"◊","\\Diamond"),O(C,U,"¥","\\yen",!0),O(z,U,"¥","\\yen",!0),O(C,U,"✓","\\checkmark",!0),O(z,U,"✓","\\checkmark"),O(C,U,"✗","\\ballotx",!0),O(z,U,"✗","\\ballotx"),O(z,U,"•","\\textbullet"),O(C,U,"ℶ","\\beth",!0),O(C,U,"ℸ","\\daleth",!0),O(C,U,"ℷ","\\gimel",!0),O(C,U,"ϝ","\\digamma",!0),O(C,U,"ϰ","\\varkappa"),O(C,D,"⌜","\\ulcorner",!0),O(C,L,"⌝","\\urcorner",!0),O(C,D,"⌞","\\llcorner",!0),O(C,L,"⌟","\\lrcorner",!0),O(C,R,"≦","\\leqq",!0),O(C,R,"⩽","\\leqslant",!0),O(C,R,"⪕","\\eqslantless",!0),O(C,R,"≲","\\lesssim",!0),O(C,R,"⪅","\\lessapprox",!0),O(C,R,"≊","\\approxeq",!0),O(C,I,"⋖","\\lessdot"),O(C,R,"⋘","\\lll",!0),O(C,R,"≶","\\lessgtr",!0),O(C,R,"⋚","\\lesseqgtr",!0),O(C,R,"⪋","\\lesseqqgtr",!0),O(C,R,"≑","\\doteqdot"),O(C,R,"≓","\\risingdotseq",!0),O(C,R,"≒","\\fallingdotseq",!0),O(C,R,"∽","\\backsim",!0),O(C,R,"⋍","\\backsimeq",!0),O(C,R,"⫅","\\subseteqq",!0),O(C,R,"⋐","\\Subset",!0),O(C,R,"⊏","\\sqsubset",!0),O(C,R,"≼","\\preccurlyeq",!0),O(C,R,"⋞","\\curlyeqprec",!0),O(C,R,"≾","\\precsim",!0),O(C,R,"⪷","\\precapprox",!0),O(C,R,"⊲","\\vartriangleleft"),O(C,R,"⊴","\\trianglelefteq"),O(C,R,"⊨","\\vDash",!0),O(C,R,"⊪","\\Vvdash",!0),O(C,R,"⌣","\\smallsmile"),O(C,R,"⌢","\\smallfrown"),O(C,R,"≏","\\bumpeq",!0),O(C,R,"≎","\\Bumpeq",!0),O(C,R,"≧","\\geqq",!0),O(C,R,"⩾","\\geqslant",!0),O(C,R,"⪖","\\eqslantgtr",!0),O(C,R,"≳","\\gtrsim",!0),O(C,R,"⪆","\\gtrapprox",!0),O(C,I,"⋗","\\gtrdot"),O(C,R,"⋙","\\ggg",!0),O(C,R,"≷","\\gtrless",!0),O(C,R,"⋛","\\gtreqless",!0),O(C,R,"⪌","\\gtreqqless",!0),O(C,R,"≖","\\eqcirc",!0),O(C,R,"≗","\\circeq",!0),O(C,R,"≜","\\triangleq",!0),O(C,R,"∼","\\thicksim"),O(C,R,"≈","\\thickapprox"),O(C,R,"⫆","\\supseteqq",!0),O(C,R,"⋑","\\Supset",!0),O(C,R,"⊐","\\sqsupset",!0),O(C,R,"≽","\\succcurlyeq",!0),O(C,R,"⋟","\\curlyeqsucc",!0),O(C,R,"≿","\\succsim",!0),O(C,R,"⪸","\\succapprox",!0),O(C,R,"⊳","\\vartriangleright"),O(C,R,"⊵","\\trianglerighteq"),O(C,R,"⊩","\\Vdash",!0),O(C,R,"∣","\\shortmid"),O(C,R,"∥","\\shortparallel"),O(C,R,"≬","\\between",!0),O(C,R,"⋔","\\pitchfork",!0),O(C,R,"∝","\\varpropto"),O(C,R,"◀","\\blacktriangleleft"),O(C,R,"∴","\\therefore",!0),O(C,R,"∍","\\backepsilon"),O(C,R,"▶","\\blacktriangleright"),O(C,R,"∵","\\because",!0),O(C,R,"⋘","\\llless"),O(C,R,"⋙","\\gggtr"),O(C,I,"⊲","\\lhd"),O(C,I,"⊳","\\rhd"),O(C,R,"≂","\\eqsim",!0),O(C,R,"⋈","\\Join"),O(C,R,"≑","\\Doteq",!0),O(C,R,"⥽","\\strictif",!0),O(C,R,"⥼","\\strictfi",!0),O(C,I,"∔","\\dotplus",!0),O(C,I,"∖","\\smallsetminus"),O(C,I,"⋒","\\Cap",!0),O(C,I,"⋓","\\Cup",!0),O(C,I,"⩞","\\doublebarwedge",!0),O(C,I,"⊟","\\boxminus",!0),O(C,I,"⊞","\\boxplus",!0),O(C,I,"⋇","\\divideontimes",!0),O(C,I,"⋉","\\ltimes",!0),O(C,I,"⋊","\\rtimes",!0),O(C,I,"⋋","\\leftthreetimes",!0),O(C,I,"⋌","\\rightthreetimes",!0),O(C,I,"⋏","\\curlywedge",!0),O(C,I,"⋎","\\curlyvee",!0),O(C,I,"⊝","\\circleddash",!0),O(C,I,"⊛","\\circledast",!0),O(C,I,"⊺","\\intercal",!0),O(C,I,"⋒","\\doublecap"),O(C,I,"⋓","\\doublecup"),O(C,I,"⊠","\\boxtimes",!0),O(C,R,"⇢","\\dashrightarrow",!0),O(C,R,"⇠","\\dashleftarrow",!0),O(C,R,"⇇","\\leftleftarrows",!0),O(C,R,"⇆","\\leftrightarrows",!0),O(C,R,"⇚","\\Lleftarrow",!0),O(C,R,"↞","\\twoheadleftarrow",!0),O(C,R,"↢","\\leftarrowtail",!0),O(C,R,"↫","\\looparrowleft",!0),O(C,R,"⇋","\\leftrightharpoons",!0),O(C,R,"↶","\\curvearrowleft",!0),O(C,R,"↺","\\circlearrowleft",!0),O(C,R,"↰","\\Lsh",!0),O(C,R,"⇈","\\upuparrows",!0),O(C,R,"↿","\\upharpoonleft",!0),O(C,R,"⇃","\\downharpoonleft",!0),O(C,R,"⊶","\\origof",!0),O(C,R,"⊷","\\imageof",!0),O(C,R,"⊸","\\multimap",!0),O(C,R,"↭","\\leftrightsquigarrow",!0),O(C,R,"⇉","\\rightrightarrows",!0),O(C,R,"⇄","\\rightleftarrows",!0),O(C,R,"↠","\\twoheadrightarrow",!0),O(C,R,"↣","\\rightarrowtail",!0),O(C,R,"↬","\\looparrowright",!0),O(C,R,"↷","\\curvearrowright",!0),O(C,R,"↻","\\circlearrowright",!0),O(C,R,"↱","\\Rsh",!0),O(C,R,"⇊","\\downdownarrows",!0),O(C,R,"↾","\\upharpoonright",!0),O(C,R,"⇂","\\downharpoonright",!0),O(C,R,"⇝","\\rightsquigarrow",!0),O(C,R,"⇝","\\leadsto"),O(C,R,"⇛","\\Rrightarrow",!0),O(C,R,"↾","\\restriction"),O(C,U,"‘","`"),O(C,U,"$","\\$"),O(z,U,"$","\\$"),O(z,U,"$","\\textdollar"),O(C,U,"%","\\%"),O(z,U,"%","\\%"),O(C,U,"_","\\_"),O(z,U,"_","\\_"),O(z,U,"_","\\textunderscore"),O(z,U,"␣","\\textvisiblespace",!0),O(C,U,"∠","\\angle",!0),O(C,U,"∞","\\infty",!0),O(C,U,"′","\\prime"),O(C,U,"△","\\triangle"),O(z,U,"Α","\\Alpha",!0),O(z,U,"Β","\\Beta",!0),O(z,U,"Γ","\\Gamma",!0),O(z,U,"Δ","\\Delta",!0),O(z,U,"Ε","\\Epsilon",!0),O(z,U,"Ζ","\\Zeta",!0),O(z,U,"Η","\\Eta",!0),O(z,U,"Θ","\\Theta",!0),O(z,U,"Ι","\\Iota",!0),O(z,U,"Κ","\\Kappa",!0),O(z,U,"Λ","\\Lambda",!0),O(z,U,"Μ","\\Mu",!0),O(z,U,"Ν","\\Nu",!0),O(z,U,"Ξ","\\Xi",!0),O(z,U,"Ο","\\Omicron",!0),O(z,U,"Π","\\Pi",!0),O(z,U,"Ρ","\\Rho",!0),O(z,U,"Σ","\\Sigma",!0),O(z,U,"Τ","\\Tau",!0),O(z,U,"Υ","\\Upsilon",!0),O(z,U,"Φ","\\Phi",!0),O(z,U,"Χ","\\Chi",!0),O(z,U,"Ψ","\\Psi",!0),O(z,U,"Ω","\\Omega",!0),O(C,F,"Α","\\Alpha",!0),O(C,F,"Β","\\Beta",!0),O(C,F,"Γ","\\Gamma",!0),O(C,F,"Δ","\\Delta",!0),O(C,F,"Ε","\\Epsilon",!0),O(C,F,"Ζ","\\Zeta",!0),O(C,F,"Η","\\Eta",!0),O(C,F,"Θ","\\Theta",!0),O(C,F,"Ι","\\Iota",!0),O(C,F,"Κ","\\Kappa",!0),O(C,F,"Λ","\\Lambda",!0),O(C,F,"Μ","\\Mu",!0),O(C,F,"Ν","\\Nu",!0),O(C,F,"Ξ","\\Xi",!0),O(C,F,"Ο","\\Omicron",!0),O(C,F,"Π","\\Pi",!0),O(C,F,"Ρ","\\Rho",!0),O(C,F,"Σ","\\Sigma",!0),O(C,F,"Τ","\\Tau",!0),O(C,F,"Υ","\\Upsilon",!0),O(C,F,"Φ","\\Phi",!0),O(C,F,"Χ","\\Chi",!0),O(C,F,"Ψ","\\Psi",!0),O(C,F,"Ω","\\Omega",!0),O(C,D,"¬","\\neg",!0),O(C,D,"¬","\\lnot"),O(C,U,"⊤","\\top"),O(C,U,"⊥","\\bot"),O(C,U,"∅","\\emptyset"),O(C,U,"ø","\\varnothing"),O(C,F,"α","\\alpha",!0),O(C,F,"β","\\beta",!0),O(C,F,"γ","\\gamma",!0),O(C,F,"δ","\\delta",!0),O(C,F,"ϵ","\\epsilon",!0),O(C,F,"ζ","\\zeta",!0),O(C,F,"η","\\eta",!0),O(C,F,"θ","\\theta",!0),O(C,F,"ι","\\iota",!0),O(C,F,"κ","\\kappa",!0),O(C,F,"λ","\\lambda",!0),O(C,F,"μ","\\mu",!0),O(C,F,"ν","\\nu",!0),O(C,F,"ξ","\\xi",!0),O(C,F,"ο","\\omicron",!0),O(C,F,"π","\\pi",!0),O(C,F,"ρ","\\rho",!0),O(C,F,"σ","\\sigma",!0),O(C,F,"τ","\\tau",!0),O(C,F,"υ","\\upsilon",!0),O(C,F,"ϕ","\\phi",!0),O(C,F,"χ","\\chi",!0),O(C,F,"ψ","\\psi",!0),O(C,F,"ω","\\omega",!0),O(C,F,"ε","\\varepsilon",!0),O(C,F,"ϑ","\\vartheta",!0),O(C,F,"ϖ","\\varpi",!0),O(C,F,"ϱ","\\varrho",!0),O(C,F,"ς","\\varsigma",!0),O(C,F,"φ","\\varphi",!0),O(C,F,"Ϙ","\\Coppa",!0),O(C,F,"ϙ","\\coppa",!0),O(C,F,"ϙ","\\varcoppa",!0),O(C,F,"Ϟ","\\Koppa",!0),O(C,F,"ϟ","\\koppa",!0),O(C,F,"Ϡ","\\Sampi",!0),O(C,F,"ϡ","\\sampi",!0),O(C,F,"Ϛ","\\Stigma",!0),O(C,F,"ϛ","\\stigma",!0),O(C,F,"⫫","\\Bot"),O(C,I,"∗","∗",!0),O(C,I,"+","+"),O(C,I,"*","*"),O(C,I,"⁄","⁄"),O(C,I,"−","-",!0),O(C,I,"⋅","\\cdot",!0),O(C,I,"∘","\\circ",!0),O(C,I,"÷","\\div",!0),O(C,I,"±","\\pm",!0),O(C,I,"×","\\times",!0),O(C,I,"∩","\\cap",!0),O(C,I,"∪","\\cup",!0),O(C,I,"∖","\\setminus",!0),O(C,I,"∧","\\land"),O(C,I,"∨","\\lor"),O(C,I,"∧","\\wedge",!0),O(C,I,"∨","\\vee",!0),O(C,D,"⟦","\\llbracket",!0),O(C,L,"⟧","\\rrbracket",!0),O(C,D,"⟨","\\langle",!0),O(C,D,"|","\\lvert"),O(C,D,"‖","\\lVert"),O(C,U,"!","\\oc"),O(C,U,"?","\\wn"),O(C,U,"↓","\\shpos"),O(C,U,"↕","\\shift"),O(C,U,"↑","\\shneg"),O(C,L,"?","?"),O(C,L,"!","!"),O(C,L,"‼","‼"),O(C,L,"⟩","\\rangle",!0),O(C,L,"|","\\rvert"),O(C,L,"‖","\\rVert"),O(C,D,"⦃","\\lBrace",!0),O(C,L,"⦄","\\rBrace",!0),O(C,R,"=","\\equal",!0),O(C,R,":",":"),O(C,R,"≈","\\approx",!0),O(C,R,"≅","\\cong",!0),O(C,R,"≥","\\ge"),O(C,R,"≥","\\geq",!0),O(C,R,"←","\\gets"),O(C,R,">","\\gt",!0),O(C,R,"∈","\\in",!0),O(C,R,"∉","\\notin",!0),O(C,R,"","\\@not"),O(C,R,"⊂","\\subset",!0),O(C,R,"⊃","\\supset",!0),O(C,R,"⊆","\\subseteq",!0),O(C,R,"⊇","\\supseteq",!0),O(C,R,"⊈","\\nsubseteq",!0),O(C,R,"⊈","\\nsubseteqq"),O(C,R,"⊉","\\nsupseteq",!0),O(C,R,"⊉","\\nsupseteqq"),O(C,R,"⊨","\\models"),O(C,R,"←","\\leftarrow",!0),O(C,R,"≤","\\le"),O(C,R,"≤","\\leq",!0),O(C,R,"<","\\lt",!0),O(C,R,"→","\\rightarrow",!0),O(C,R,"→","\\to"),O(C,R,"≱","\\ngeq",!0),O(C,R,"≱","\\ngeqq"),O(C,R,"≱","\\ngeqslant"),O(C,R,"≰","\\nleq",!0),O(C,R,"≰","\\nleqq"),O(C,R,"≰","\\nleqslant"),O(C,R,"⫫","\\Perp",!0),O(C,j," ","\\ "),O(C,j," ","\\space"),O(C,j," ","\\nobreakspace"),O(z,j," ","\\ "),O(z,j," "," "),O(z,j," ","\\space"),O(z,j," ","\\nobreakspace"),O(C,j,null,"\\nobreak"),O(C,j,null,"\\allowbreak"),O(C,P,",",","),O(z,P,":",":"),O(C,P,";",";"),O(C,I,"⊼","\\barwedge",!0),O(C,I,"⊻","\\veebar",!0),O(C,I,"⊙","\\odot",!0),O(C,I,"⊕","\\oplus",!0),O(C,I,"⊗","\\otimes",!0),O(C,U,"∂","\\partial",!0),O(C,I,"⊘","\\oslash",!0),O(C,I,"⊚","\\circledcirc",!0),O(C,I,"⊡","\\boxdot",!0),O(C,I,"△","\\bigtriangleup"),O(C,I,"▽","\\bigtriangledown"),O(C,I,"†","\\dagger"),O(C,I,"⋄","\\diamond"),O(C,I,"⋆","\\star"),O(C,I,"◃","\\triangleleft"),O(C,I,"▹","\\triangleright"),O(C,D,"{","\\{"),O(z,U,"{","\\{"),O(z,U,"{","\\textbraceleft"),O(C,L,"}","\\}"),O(z,U,"}","\\}"),O(z,U,"}","\\textbraceright"),O(C,D,"{","\\lbrace"),O(C,L,"}","\\rbrace"),O(C,D,"[","\\lbrack",!0),O(z,U,"[","\\lbrack",!0),O(C,L,"]","\\rbrack",!0),O(z,U,"]","\\rbrack",!0),O(C,D,"(","\\lparen",!0),O(C,L,")","\\rparen",!0),O(z,U,"<","\\textless",!0),O(z,U,">","\\textgreater",!0),O(C,D,"⌊","\\lfloor",!0),O(C,L,"⌋","\\rfloor",!0),O(C,D,"⌈","\\lceil",!0),O(C,L,"⌉","\\rceil",!0),O(C,U,"\\","\\backslash"),O(C,U,"|","|"),O(C,U,"|","\\vert"),O(z,U,"|","\\textbar",!0),O(C,U,"‖","\\|"),O(C,U,"‖","\\Vert"),O(z,U,"‖","\\textbardbl"),O(z,U,"~","\\textasciitilde"),O(z,U,"\\","\\textbackslash"),O(z,U,"^","\\textasciicircum"),O(C,R,"↑","\\uparrow",!0),O(C,R,"⇑","\\Uparrow",!0),O(C,R,"↓","\\downarrow",!0),O(C,R,"⇓","\\Downarrow",!0),O(C,R,"↕","\\updownarrow",!0),O(C,R,"⇕","\\Updownarrow",!0),O(C,G,"∐","\\coprod"),O(C,G,"⋁","\\bigvee"),O(C,G,"⋀","\\bigwedge"),O(C,G,"⨄","\\biguplus"),O(C,G,"⋂","\\bigcap"),O(C,G,"⋃","\\bigcup"),O(C,G,"∫","\\int"),O(C,G,"∫","\\intop"),O(C,G,"∬","\\iint"),O(C,G,"∭","\\iiint"),O(C,G,"∏","\\prod"),O(C,G,"∑","\\sum"),O(C,G,"⨂","\\bigotimes"),O(C,G,"⨁","\\bigoplus"),O(C,G,"⨀","\\bigodot"),O(C,G,"∮","\\oint"),O(C,G,"∯","\\oiint"),O(C,G,"∰","\\oiiint"),O(C,G,"∱","\\intclockwise"),O(C,G,"∲","\\varointclockwise"),O(C,G,"⨌","\\iiiint"),O(C,G,"⨍","\\intbar"),O(C,G,"⨎","\\intBar"),O(C,G,"⨏","\\fint"),O(C,G,"⨒","\\rppolint"),O(C,G,"⨓","\\scpolint"),O(C,G,"⨕","\\pointint"),O(C,G,"⨖","\\sqint"),O(C,G,"⨗","\\intlarhk"),O(C,G,"⨘","\\intx"),O(C,G,"⨙","\\intcap"),O(C,G,"⨚","\\intcup"),O(C,G,"⨅","\\bigsqcap"),O(C,G,"⨆","\\bigsqcup"),O(C,G,"∫","\\smallint"),O(z,$,"…","\\textellipsis"),O(C,$,"…","\\mathellipsis"),O(z,$,"…","\\ldots",!0),O(C,$,"…","\\ldots",!0),O(C,$,"⋰","\\iddots",!0),O(C,$,"⋯","\\@cdots",!0),O(C,$,"⋱","\\ddots",!0),O(C,U,"⋮","\\varvdots"),O(C,E,"ˊ","\\acute"),O(C,E,"`","\\grave"),O(C,E,"¨","\\ddot"),O(C,E,"⃛","\\dddot"),O(C,E,"⃜","\\ddddot"),O(C,E,"~","\\tilde"),O(C,E,"‾","\\bar"),O(C,E,"˘","\\breve"),O(C,E,"ˇ","\\check"),O(C,E,"^","\\hat"),O(C,E,"⃗","\\vec"),O(C,E,"˙","\\dot"),O(C,E,"˚","\\mathring"),O(C,F,"ı","\\imath",!0),O(C,F,"ȷ","\\jmath",!0),O(C,U,"ı","ı"),O(C,U,"ȷ","ȷ"),O(z,U,"ı","\\i",!0),O(z,U,"ȷ","\\j",!0),O(z,U,"ß","\\ss",!0),O(z,U,"æ","\\ae",!0),O(z,U,"œ","\\oe",!0),O(z,U,"ø","\\o",!0),O(C,F,"ø","\\o",!0),O(z,U,"Æ","\\AE",!0),O(z,U,"Œ","\\OE",!0),O(z,U,"Ø","\\O",!0),O(C,F,"Ø","\\O",!0),O(z,E,"ˊ","\\'"),O(z,E,"ˋ","\\`"),O(z,E,"ˆ","\\^"),O(z,E,"˜","\\~"),O(z,E,"ˉ","\\="),O(z,E,"˘","\\u"),O(z,E,"˙","\\."),O(z,E,"¸","\\c"),O(z,E,"˚","\\r"),O(z,E,"ˇ","\\v"),O(z,E,"¨",'\\"'),O(z,E,"˝","\\H"),O(C,E,"ˊ","\\'"),O(C,E,"ˋ","\\`"),O(C,E,"ˆ","\\^"),O(C,E,"˜","\\~"),O(C,E,"ˉ","\\="),O(C,E,"˘","\\u"),O(C,E,"˙","\\."),O(C,E,"¸","\\c"),O(C,E,"˚","\\r"),O(C,E,"ˇ","\\v"),O(C,E,"¨",'\\"'),O(C,E,"˝","\\H");const _={"--":!0,"---":!0,"``":!0,"''":!0};O(z,U,"–","--",!0),O(z,U,"–","\\textendash"),O(z,U,"—","---",!0),O(z,U,"—","\\textemdash"),O(z,U,"‘","`",!0),O(z,U,"‘","\\textquoteleft"),O(z,U,"’","'",!0),O(z,U,"’","\\textquoteright"),O(z,U,"“","``",!0),O(z,U,"“","\\textquotedblleft"),O(z,U,"”","''",!0),O(z,U,"”","\\textquotedblright"),O(C,U,"°","\\degree",!0),O(z,U,"°","\\degree"),O(z,U,"°","\\textdegree",!0),O(C,U,"£","\\pounds"),O(C,U,"£","\\mathsterling",!0),O(z,U,"£","\\pounds"),O(z,U,"£","\\textsterling",!0),O(C,U,"✠","\\maltese"),O(z,U,"✠","\\maltese"),O(C,U,"€","\\euro",!0),O(z,U,"€","\\euro",!0),O(z,U,"€","\\texteuro"),O(C,U,"©","\\copyright",!0),O(z,U,"©","\\textcopyright"),O(C,U,"𝛤","\\varGamma"),O(C,U,"𝛥","\\varDelta"),O(C,U,"𝛩","\\varTheta"),O(C,U,"𝛬","\\varLambda"),O(C,U,"𝛯","\\varXi"),O(C,U,"𝛱","\\varPi"),O(C,U,"𝛴","\\varSigma"),O(C,U,"𝛶","\\varUpsilon"),O(C,U,"𝛷","\\varPhi"),O(C,U,"𝛹","\\varPsi"),O(C,U,"𝛺","\\varOmega"),O(z,U,"𝛤","\\varGamma"),O(z,U,"𝛥","\\varDelta"),O(z,U,"𝛩","\\varTheta"),O(z,U,"𝛬","\\varLambda"),O(z,U,"𝛯","\\varXi"),O(z,U,"𝛱","\\varPi"),O(z,U,"𝛴","\\varSigma"),O(z,U,"𝛶","\\varUpsilon"),O(z,U,"𝛷","\\varPhi"),O(z,U,"𝛹","\\varPsi"),O(z,U,"𝛺","\\varOmega");const H='0123456789/@."';for(let e=0;e=0;n--){const o=e[n];if("mstyle"===o.type&&o.attributes.mathcolor){const s=o.attributes.mathcolor,a=J(o.children,t,r,s);a.type&&"mtable"!==a.type||e.splice(n,1,...a.children)}}}const o=n?"mstyle":"mrow",s=[];let a=[],i=[],l=!1;for(let c=0;c0){const e=new T.MathNode(o,i);n&&e.setAttribute("mathcolor",n),a.push(new T.MathNode(o,i))}a.push(m),i=[];const e=new T.MathNode("mtd",a);s.push(new T.MathNode("mtr",[e])),a=[]}else if(i.push(m),!m.type||"mo"!==m.type||t||r)l=!0;else{if(l&&!m.attributes.form){const t=c0){const e=new T.MathNode(o,i);n&&e.setAttribute("mathcolor",n),a.push(e)}if(s.length>0){const e=new T.MathNode("mtd",a),r=new T.MathNode("mtr",[e]);s.push(r);const n=new T.MathNode("mtable",s);return t||(n.setAttribute("columnalign","left"),n.setAttribute("rowspacing","0em")),n}return T.newDocumentFragment(a)}const Y=function(e,t,r){return!M[t][e]||!M[t][e].replace||55349===e.charCodeAt(0)||Object.prototype.hasOwnProperty.call(_,e)&&r&&(r.fontFamily&&"tt"===r.fontFamily.slice(4,6)||r.font&&"tt"===r.font.slice(4,6))||(e=M[t][e].replace),new T.TextNode(e)},K=function(e){return 1===e.length?e[0]:new T.MathNode("mrow",e)},Q=e=>"atom"===e.type&&"rel"===e.family||"mclass"===e.type&&"mrel"===e.mclass,ee=function(e,t,r){if(1===e.length){const n=re(e[0],t);return r&&n instanceof k&&"mo"===n.type&&(n.setAttribute("lspace","0em"),n.setAttribute("rspace","0em")),[n]}const n=[];for(let r=0;r0&&Q(e[r])&&Q(e[r-1])&&o.setAttribute("lspace","0em"),n.push(o)}return n},te=function(e,t,r){return K(ee(e,t,r))},re=function(t,r){if(!t)return new T.MathNode("mrow");if(l[t.type]){return l[t.type](t,r)}throw new e("Got group of unknown type: '"+t.type+"'")},ne=e=>{const t=new T.MathNode("mtd",[]);return t.setAttribute("style","padding: 0;width: 50%;"),t};function oe(e,t,r,n){let o=null;1===e.length&&"tag"===e[0].type&&(o=e[0].tag,e=e[0].body);const a=ee(e,r),i=0===a.length?null:a[0];let l,c=1===a.length&&null===o&&i instanceof k&&("mstyle"!==i.type||!i.attributes.mathcolor)?a[0]:J(a,n.displayMode,n.annotate);if(o&&(c=((e,t,r,n,o)=>{t=te(t[0].body,r),(t=s.consolidateText(t)).classes=["tml-tag"],o||((t=new T.MathNode("mpadded",[t])).setAttribute("style","width:0;"),t.setAttribute("width","0"),t.setAttribute(n?"rspace":"lspace","-1width")),t=new T.MathNode("mtd",[t]),o||t.setAttribute("style","padding: 0; min-width:0"),e=new T.MathNode("mtd",[e]);const a=n?[t,ne(),e,ne()]:[ne(),e,ne(),t],i=new T.MathNode("mtr",a,["tml-tageqn"]),l=new T.MathNode("mtable",[i]);return l.setAttribute("width","100%"),l.setAttribute("displaystyle","true"),l})(c,o,r,n.leqno,n.preventTagLap)),n.annotate){const e=new T.MathNode("annotation",[new T.TextNode(t)]);e.setAttribute("encoding","application/x-tex"),l=new T.MathNode("semantics",[c,e])}const m=n.annotate?new T.MathNode("math",[l]):new T.MathNode("math",[c]);return n.xml&&m.setAttribute("xmlns","http://www.w3.org/1998/Math/MathML"),n.displayMode&&m.setAttribute("display","block"),m}const se=(e,t)=>{const r=e.isStretchy?S(e.label):new T.MathNode("mo",[Y(e.label,e.mode)]);e.isStretchy||r.setAttribute("stretchy","false");const n=new T.MathNode("\\c"===e.label?"munder":"mover",[re(e.base,t),r]);return n.setAttribute("accent","true"),n},ae=new RegExp(["\\acute","\\grave","\\ddot","\\dddot","\\ddddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring"].map((e=>`\\${e}`)).join("|"));c({type:"accent",names:["\\acute","\\grave","\\ddot","\\dddot","\\ddddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring","\\overparen","\\widecheck","\\widehat","\\wideparen","\\widetilde","\\overrightarrow","\\overleftarrow","\\Overrightarrow","\\overleftrightarrow","\\overgroup","\\overleftharpoon","\\overrightharpoon"],props:{numArgs:1},handler:(e,t)=>{const r=u(t[0]),n=!ae.test(e.funcName),o=!n||"\\widehat"===e.funcName||"\\widetilde"===e.funcName||"\\widecheck"===e.funcName;return{type:"accent",mode:e.parser.mode,label:e.funcName,isStretchy:n,isShifty:o,base:r}},mathmlBuilder:se}),c({type:"accent",names:["\\'","\\`","\\^","\\~","\\=","\\c","\\u","\\.",'\\"',"\\r","\\H","\\v"],props:{numArgs:1,allowedInText:!0,allowedInMath:!0,argTypes:["primitive"]},handler:(e,t)=>{const r=u(t[0]),n=e.parser.mode;return"math"===n&&e.parser.settings.strict&&console.log(`Temml parse error: Command ${e.funcName} is invalid in math mode.`),{type:"accent",mode:n,label:e.funcName,isStretchy:!1,isShifty:!0,base:r}},mathmlBuilder:se}),c({type:"accentUnder",names:["\\underleftarrow","\\underrightarrow","\\underleftrightarrow","\\undergroup","\\underparen","\\utilde"],props:{numArgs:1},handler:({parser:e,funcName:t},r)=>{const n=r[0];return{type:"accentUnder",mode:e.mode,label:t,base:n}},mathmlBuilder:(e,t)=>{const r=S(e.label),n=new T.MathNode("munder",[re(e.base,t),r]);return n.setAttribute("accentunder","true"),n}});const ie={pt:800/803,pc:9600/803,dd:1238/1157*800/803,cc:12.792133216944668,nd:685/642*800/803,nc:1370/107*800/803,sp:1/65536*800/803,mm:25.4/72,cm:2.54/72,in:1/72,px:96/72},le=["em","ex","mu","pt","mm","cm","in","px","bp","pc","dd","cc","nd","nc","sp"],ce=function(e){return"string"!=typeof e&&(e=e.unit),le.indexOf(e)>-1},me=e=>[1,.7,.5][Math.max(e-1,0)],ue=function(t,r){let n=t.number;if(r.maxSize[0]<0&&n>0)return{number:0,unit:"em"};const o=t.unit;switch(o){case"mm":case"cm":case"in":case"px":return n*ie[o]>r.maxSize[1]?{number:r.maxSize[1],unit:"pt"}:{number:n,unit:o};case"em":case"ex":return"ex"===o&&(n*=.431),n=Math.min(n/me(r.level),r.maxSize[0]),{number:s.round(n),unit:"em"};case"bp":return n>r.maxSize[1]&&(n=r.maxSize[1]),{number:n,unit:"pt"};case"pt":case"pc":case"dd":case"cc":case"nd":case"nc":case"sp":return n=Math.min(n*ie[o],r.maxSize[1]),{number:s.round(n),unit:"pt"};case"mu":return n=Math.min(n/18,r.maxSize[0]),{number:s.round(n),unit:"em"};default:throw new e("Invalid unit: '"+o+"'")}},pe=(e,t,r="0.3em")=>{const n=new T.MathNode("mpadded",e?[e]:[]);return n.setAttribute("width",t),n.setAttribute("lspace",r),n},de=(e,t)=>(e/me(t)).toFixed(4)+"em",he=(e,t,r,n)=>{const o=S(e),s="eq"===e.slice(1,3),a="x"===e.charAt(1)?"1.75":"cd"===e.slice(2,4)?"3.0":s?"1.0":"2.0";o.setAttribute("minsize",String(a)+"em"),o.setAttribute("lspace","0"),o.setAttribute("rspace",s?"0.5em":"0");const i=n.withLevel(n.level<2?2:3),l=de(a,i.level),c=de(s?0:.3,i.level);let m=de(s?-.4:.6,i.level);"-"!==m.charAt(0)&&(m="+"+m);const u=t&&t.body&&(t.body.body||t.body.length>0)?pe(re(t,i),m,c):pe(null,l,"0"),p=r&&r.body&&(r.body.body||r.body.length>0)?pe(re(r,i),m,c):pe(null,l,"0");return new T.MathNode("munderover",[o,p,u])};c({type:"xArrow",names:["\\xleftarrow","\\xrightarrow","\\xLeftarrow","\\xRightarrow","\\xleftrightarrow","\\xLeftrightarrow","\\xhookleftarrow","\\xhookrightarrow","\\xmapsto","\\xrightharpoondown","\\xrightharpoonup","\\xleftharpoondown","\\xleftharpoonup","\\xlongequal","\\xtwoheadrightarrow","\\xtwoheadleftarrow","\\yields","\\yieldsLeft","\\mesomerism","\\longrightharpoonup","\\longleftharpoondown","\\\\cdrightarrow","\\\\cdleftarrow","\\\\cdlongequal"],props:{numArgs:1,numOptionalArgs:1},handler:({parser:e,funcName:t},r,n)=>({type:"xArrow",mode:e.mode,name:t,body:r[0],below:n[0]}),mathmlBuilder(e,t){const r=he(e.name,e.body,e.below,t),n=new T.MathNode("mpadded",[r]);return n.setAttribute("lspace","0.2778em"),n.setAttribute("width","+0.5556em"),n}});const ge={"\\xtofrom":["\\xrightarrow","\\xleftarrow"],"\\xleftrightharpoons":["\\xleftharpoonup","\\xrightharpoondown"],"\\xrightleftharpoons":["\\xrightharpoonup","\\xleftharpoondown"],"\\yieldsLeftRight":["\\yields","\\yieldsLeft"],"\\equilibrium":["\\longrightharpoonup","\\longleftharpoondown"],"\\equilibriumRight":["\\longrightharpoonup","\\eqleftharpoondown"],"\\equilibriumLeft":["\\eqrightharpoonup","\\longleftharpoondown"]};function fe(e,t){if(!e||e.type!==t)throw new Error(`Expected node of type ${t}, but got `+(e?`node of type ${e.type}`:String(e)));return e}function be(e){const t=ye(e);if(!t)throw new Error("Expected node of symbol group type, but got "+(e?`node of type ${e.type}`:String(e)));return t}function ye(e){return e&&("atom"===e.type||Object.prototype.hasOwnProperty.call(B,e.type))?e:null}c({type:"stackedArrow",names:["\\xtofrom","\\xleftrightharpoons","\\xrightleftharpoons","\\yieldsLeftRight","\\equilibrium","\\equilibriumRight","\\equilibriumLeft"],props:{numArgs:1,numOptionalArgs:1},handler({parser:e,funcName:t},r,n){const o=r[0]?{type:"hphantom",mode:e.mode,body:r[0]}:null,s=n[0]?{type:"hphantom",mode:e.mode,body:n[0]}:null;return{type:"stackedArrow",mode:e.mode,name:t,body:r[0],upperArrowBelow:s,lowerArrowBody:o,below:n[0]}},mathmlBuilder(e,t){const r=ge[e.name][0],n=ge[e.name][1],o=he(r,e.body,e.upperArrowBelow,t),s=he(n,e.lowerArrowBody,e.below,t);let a;const i=new T.MathNode("mpadded",[o]);if(i.setAttribute("voffset","0.3em"),i.setAttribute("height","+0.3em"),i.setAttribute("depth","-0.3em"),"\\equilibriumLeft"===e.name){const e=new T.MathNode("mpadded",[s]);e.setAttribute("width","0.5em"),a=new T.MathNode("mpadded",[e,i])}else i.setAttribute("width","\\equilibriumRight"===e.name?"0.5em":"0"),a=new T.MathNode("mpadded",[i,s]);return a.setAttribute("voffset","-0.18em"),a.setAttribute("width","+0.5556em"),a.setAttribute("height","-0.18em"),a.setAttribute("depth","+0.18em"),a.setAttribute("lspace","0.2778em"),a}}),c({type:"cancelto",names:["\\cancelto"],props:{numArgs:2},handler:({parser:e},t)=>({type:"cancelto",mode:e.mode,value:t[0],expression:t[1]}),mathmlBuilder(e,t){const r=new T.MathNode("mpadded",[re(e.value,t)]);r.setAttribute("depth","-0.1em"),r.setAttribute("height","+0.1em"),r.setAttribute("voffset","0.1em");const n=new T.MathNode("menclose",[re(e.expression,t)]);return n.setAttribute("notation","updiagonalarrow"),new T.MathNode("msup",[n,r])}});const we={">":"\\\\cdrightarrow","<":"\\\\cdleftarrow","=":"\\\\cdlongequal",A:"\\uparrow",V:"\\downarrow","|":"\\Vert",".":"no arrow"},xe=e=>"textord"===e.type&&"@"===e.text;function ke(e,t,r){const n=we[e];switch(n){case"\\\\cdrightarrow":case"\\\\cdleftarrow":return r.callFunction(n,[t[0]],[t[1]]);case"\\uparrow":case"\\downarrow":{const e={type:"atom",text:n,mode:"math",family:"rel"},o={type:"ordgroup",mode:"math",body:[r.callFunction("\\\\cdleft",[t[0]],[]),r.callFunction("\\Big",[e],[]),r.callFunction("\\\\cdright",[t[1]],[])]};return r.callFunction("\\\\cdparent",[o],[])}case"\\\\cdlongequal":return r.callFunction("\\\\cdlongequal",[],[]);case"\\Vert":{const e={type:"textord",text:"\\Vert",mode:"math"};return r.callFunction("\\Big",[e],[])}default:return{type:"textord",text:" ",mode:"math"}}}c({type:"cdlabel",names:["\\\\cdleft","\\\\cdright"],props:{numArgs:1},handler:({parser:e,funcName:t},r)=>({type:"cdlabel",mode:e.mode,side:t.slice(4),label:r[0]}),mathmlBuilder(e,t){let r=new T.MathNode("mrow",[re(e.label,t)]);return r=new T.MathNode("mpadded",[r]),r.setAttribute("width","0"),"left"===e.side&&r.setAttribute("lspace","-1width"),r.setAttribute("voffset","0.7em"),r=new T.MathNode("mstyle",[r]),r.setAttribute("displaystyle","false"),r.setAttribute("scriptlevel","1"),r}}),c({type:"cdlabelparent",names:["\\\\cdparent"],props:{numArgs:1},handler:({parser:e},t)=>({type:"cdlabelparent",mode:e.mode,fragment:t[0]}),mathmlBuilder:(e,t)=>new T.MathNode("mrow",[re(e.fragment,t)])}),c({type:"textord",names:["\\@char"],props:{numArgs:1,allowedInText:!0},handler({parser:t,token:r},n){const o=fe(n[0],"ordgroup").body;let s="";for(let e=0;e{let t=e.toString(16);return 1===t.length&&(t="0"+t),t},Be=JSON.parse('{\n "Apricot": "#ffb484",\n "Aquamarine": "#08b4bc",\n "Bittersweet": "#c84c14",\n "blue": "#0000FF",\n "Blue": "#303494",\n "BlueGreen": "#08b4bc",\n "BlueViolet": "#503c94",\n "BrickRed": "#b8341c",\n "brown": "#BF8040",\n "Brown": "#802404",\n "BurntOrange": "#f8941c",\n "CadetBlue": "#78749c",\n "CarnationPink": "#f884b4",\n "Cerulean": "#08a4e4",\n "CornflowerBlue": "#40ace4",\n "cyan": "#00FFFF",\n "Cyan": "#08acec",\n "Dandelion": "#ffbc44",\n "darkgray": "#404040",\n "DarkOrchid": "#a8548c",\n "Emerald": "#08ac9c",\n "ForestGreen": "#089c54",\n "Fuchsia": "#90348c",\n "Goldenrod": "#ffdc44",\n "gray": "#808080",\n "Gray": "#98949c",\n "green": "#00FF00",\n "Green": "#08a44c",\n "GreenYellow": "#e0e474",\n "JungleGreen": "#08ac9c",\n "Lavender": "#f89cc4",\n "lightgray": "#c0c0c0",\n "lime": "#BFFF00",\n "LimeGreen": "#90c43c",\n "magenta": "#FF00FF",\n "Magenta": "#f0048c",\n "Mahogany": "#b0341c",\n "Maroon": "#b03434",\n "Melon": "#f89c7c",\n "MidnightBlue": "#086494",\n "Mulberry": "#b03c94",\n "NavyBlue": "#086cbc",\n "olive": "#7F7F00",\n "OliveGreen": "#407c34",\n "orange": "#FF8000",\n "Orange": "#f8843c",\n "OrangeRed": "#f0145c",\n "Orchid": "#b074ac",\n "Peach": "#f8945c",\n "Periwinkle": "#8074bc",\n "PineGreen": "#088c74",\n "pink": "#ff7f7f",\n "Plum": "#98248c",\n "ProcessBlue": "#08b4ec",\n "purple": "#BF0040",\n "Purple": "#a0449c",\n "RawSienna": "#983c04",\n "red": "#ff0000",\n "Red": "#f01c24",\n "RedOrange": "#f86434",\n "RedViolet": "#a0246c",\n "Rhodamine": "#f0549c",\n "Royallue": "#0874bc",\n "RoyalPurple": "#683c9c",\n "RubineRed": "#f0047c",\n "Salmon": "#f8948c",\n "SeaGreen": "#30bc9c",\n "Sepia": "#701404",\n "SkyBlue": "#48c4dc",\n "SpringGreen": "#c8dc64",\n "Tan": "#e09c74",\n "teal": "#007F7F",\n "TealBlue": "#08acb4",\n "Thistle": "#d884b4",\n "Turquoise": "#08b4cc",\n "violet": "#800080",\n "Violet": "#60449c",\n "VioletRed": "#f054a4",\n "WildStrawberry": "#f0246c",\n "yellow": "#FFFF00",\n "Yellow": "#fff404",\n "YellowGreen": "#98cc6c",\n "YellowOrange": "#ffa41c"\n}'),Me=(t,r)=>{let n="";if("HTML"===t){if(!Ae.test(r))throw new e("Invalid HTML input.");n=r}else if("RGB"===t){if(!Te.test(r))throw new e("Invalid RGB input.");r.split(",").map((e=>{n+=qe(Number(e.trim()))}))}else{if(!Ne.test(r))throw new e("Invalid rbg input.");r.split(",").map((t=>{const r=Number(t.trim());if(r>1)throw new e("Color rgb input must be < 1.");n+=qe(255*r)}))}return"#"!==n.charAt(0)&&(n="#"+n),n},Oe=(t,r,n)=>{const o=`\\\\color@${t}`;if(!ve.exec(t))throw new e("Invalid color: '"+t+"'",n);return Se.test(t)?"#"+t:("#"===t.charAt(0)||(r.has(o)?t=r.get(o).tokens[0].text:Be[t]&&(t=Be[t])),t)},Ce=(e,t)=>{const r=ee(e.body,t.withColor(e.color)),n=v(r);return n.setAttribute("mathcolor",e.color),new T.MathNode("mrow",[n])};c({type:"color",names:["\\textcolor"],props:{numArgs:2,numOptionalArgs:1,allowedInText:!0,argTypes:["raw","raw","original"]},handler({parser:e,token:t},r,n){const o=n[0]&&fe(n[0],"raw").string;let s="";if(o){const e=fe(r[0],"raw").string;s=Me(o,e)}else s=Oe(fe(r[0],"raw").string,e.gullet.macros,t);const a=r[1];return{type:"color",mode:e.mode,color:s,body:p(a)}},mathmlBuilder:Ce}),c({type:"color",names:["\\color"],props:{numArgs:1,numOptionalArgs:1,allowedInText:!0,argTypes:["raw","raw"]},handler({parser:e,token:t},r,n){const o=n[0]&&fe(n[0],"raw").string;let s="";if(o){const e=fe(r[0],"raw").string;s=Me(o,e)}else s=Oe(fe(r[0],"raw").string,e.gullet.macros,t);e.gullet.macros.set("\\current@color",s);const a=e.parseExpression(!0,"\\color");return{type:"color",mode:e.mode,color:s,body:a}},mathmlBuilder:Ce}),c({type:"color",names:["\\definecolor"],props:{numArgs:3,allowedInText:!0,argTypes:["raw","raw","raw"]},handler({parser:t,funcName:r,token:n},o){const s=fe(o[0],"raw").string;if(!/^[A-Za-z]+$/.test(s))throw new e("Color name must be latin letters.",n);const a=fe(o[1],"raw").string;if(!["HTML","RGB","rgb"].includes(a))throw new e("Color model must be HTML, RGB, or rgb.",n);const i=fe(o[2],"raw").string,l=Me(a,i);return t.gullet.macros.set(`\\\\color@${s}`,{tokens:[{text:l}],numArgs:0}),{type:"internal",mode:t.mode}}}),c({type:"cr",names:["\\\\"],props:{numArgs:0,numOptionalArgs:1,argTypes:["size"],allowedInText:!0},handler({parser:e},t,r){const n=r[0],o=!e.settings.displayMode;return{type:"cr",mode:e.mode,newLine:o,size:n&&fe(n,"size").value}},mathmlBuilder(e,t){const r=new T.MathNode("mo");if(e.newLine&&(r.setAttribute("linebreak","newline"),e.size)){const n=ue(e.size,t);r.setAttribute("height",n.number+n.unit)}return r}});const ze=t=>{const r=t.text;if(/^(?:[\\{}$&#^_]|EOF)$/.test(r))throw new e("Expected a control sequence",t);return r},Ee=(e,t,r)=>{let n=e.gullet.macros.get(r.text);null==n&&(r.noexpand=!0,n={tokens:[r],numArgs:0,unexpandable:!e.gullet.isExpandable(r.text)}),e.gullet.macros.set(t,n)};c({type:"internal",names:["\\def","\\edef"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler({parser:t,funcName:r}){let n=t.gullet.popToken();const o=n.text;if(/^(?:[\\{}$&#^_]|EOF)$/.test(o))throw new e("Expected a control sequence",n);let s,a=0;const i=[[]];for(;"{"!==t.gullet.future().text;)if(n=t.gullet.popToken(),"#"===n.text){if("{"===t.gullet.future().text){s=t.gullet.future(),i[a].push("{");break}if(n=t.gullet.popToken(),!/^[1-9]$/.test(n.text))throw new e(`Invalid argument number "${n.text}"`);if(parseInt(n.text)!==a+1)throw new e(`Argument number "${n.text}" out of order`);a++,i.push([])}else{if("EOF"===n.text)throw new e("Expected a macro definition");i[a].push(n.text)}let{tokens:l}=t.gullet.consumeArg();return s&&l.unshift(s),"\\edef"===r&&(l=t.gullet.expandTokens(l),l.reverse()),t.gullet.macros.set(o,{tokens:l,numArgs:a,delimiters:i}),{type:"internal",mode:t.mode}}}),c({type:"internal",names:["\\let"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler({parser:e,funcName:t}){const r=ze(e.gullet.popToken());e.gullet.consumeSpaces();const n=(e=>{let t=e.gullet.popToken();return"="===t.text&&(t=e.gullet.popToken()," "===t.text&&(t=e.gullet.popToken())),t})(e);return Ee(e,r,n),{type:"internal",mode:e.mode}}}),c({type:"internal",names:["\\futurelet"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler({parser:e,funcName:t}){const r=ze(e.gullet.popToken()),n=e.gullet.popToken(),o=e.gullet.popToken();return Ee(e,r,o),e.gullet.pushToken(o),e.gullet.pushToken(n),{type:"internal",mode:e.mode}}}),c({type:"internal",names:["\\newcommand","\\renewcommand","\\providecommand"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler({parser:t,funcName:r}){let n="";const o=t.gullet.popToken();"{"===o.text?(n=ze(t.gullet.popToken()),t.gullet.popToken()):n=ze(o);const s=t.gullet.isDefined(n);if(s&&"\\newcommand"===r)throw new e(`\\newcommand{${n}} attempting to redefine ${n}; use \\renewcommand`);if(!s&&"\\renewcommand"===r)throw new e(`\\renewcommand{${n}} when command ${n} does not yet exist; use \\newcommand`);let a=0;if("["===t.gullet.future().text){let r=t.gullet.popToken();if(r=t.gullet.popToken(),!/^[0-9]$/.test(r.text))throw new e(`Invalid number of arguments: "${r.text}"`);if(a=parseInt(r.text),r=t.gullet.popToken(),"]"!==r.text)throw new e(`Invalid argument "${r.text}"`)}const{tokens:i}=t.gullet.consumeArg();return t.gullet.macros.set(n,{tokens:i,numArgs:a}),{type:"internal",mode:t.mode}}});const Ie={"\\bigl":{mclass:"mopen",size:1},"\\Bigl":{mclass:"mopen",size:2},"\\biggl":{mclass:"mopen",size:3},"\\Biggl":{mclass:"mopen",size:4},"\\bigr":{mclass:"mclose",size:1},"\\Bigr":{mclass:"mclose",size:2},"\\biggr":{mclass:"mclose",size:3},"\\Biggr":{mclass:"mclose",size:4},"\\bigm":{mclass:"mrel",size:1},"\\Bigm":{mclass:"mrel",size:2},"\\biggm":{mclass:"mrel",size:3},"\\Biggm":{mclass:"mrel",size:4},"\\big":{mclass:"mord",size:1},"\\Big":{mclass:"mord",size:2},"\\bigg":{mclass:"mord",size:3},"\\Bigg":{mclass:"mord",size:4}},Le=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","⌊","⌋","\\lceil","\\rceil","⌈","⌉","<",">","\\langle","⟨","\\rangle","⟩","\\lt","\\gt","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","⟮","⟯","\\lmoustache","\\rmoustache","⎰","⎱","\\llbracket","\\rrbracket","⟦","⟦","\\lBrace","\\rBrace","⦃","⦄","/","\\backslash","|","\\vert","\\|","\\Vert","\\uparrow","\\Uparrow","\\downarrow","\\Downarrow","\\updownarrow","\\Updownarrow","."],$e=[0,1.2,1.8,2.4,3];function Fe(t,r){"ordgroup"===t.type&&1===t.body.length&&"⁄"===t.body[0].text&&(t={type:"textord",text:"/",mode:"math"});const n=ye(t);if(n&&s.contains(Le,n.text))return s.contains(["<","\\lt"],n.text)&&(n.text="⟨"),s.contains([">","\\gt"],n.text)&&(n.text="⟩"),"/"===n.text&&(n.text="∕"),"\\backslash"===n.text&&(n.text="∖"),n;throw new e(n?`Invalid delimiter '${n.text}' after '${r.funcName}'`:`Invalid delimiter type '${t.type}'`,t)}c({type:"delimsizing",names:["\\bigl","\\Bigl","\\biggl","\\Biggl","\\bigr","\\Bigr","\\biggr","\\Biggr","\\bigm","\\Bigm","\\biggm","\\Biggm","\\big","\\Big","\\bigg","\\Bigg"],props:{numArgs:1,argTypes:["primitive"]},handler:(e,t)=>{const r=Fe(t[0],e);return{type:"delimsizing",mode:e.parser.mode,size:Ie[e.funcName].size,mclass:Ie[e.funcName].mclass,delim:r.text}},mathmlBuilder:e=>{const t=[];"."===e.delim&&(e.delim=""),t.push(Y(e.delim,e.mode));const r=new T.MathNode("mo",t);return"mopen"===e.mclass||"mclose"===e.mclass?r.setAttribute("fence","true"):r.setAttribute("fence","false"),"∖"===e.delim&&r.setAttribute("stretchy","true"),r.setAttribute("symmetric","true"),r.setAttribute("minsize",$e[e.size]+"em"),r.setAttribute("maxsize",$e[e.size]+"em"),r}}),c({type:"leftright-right",names:["\\right"],props:{numArgs:1,argTypes:["primitive"]},handler:(t,r)=>{const n=t.parser.gullet.macros.get("\\current@color");if(n&&"string"!=typeof n)throw new e("\\current@color set to non-string in \\right");return{type:"leftright-right",mode:t.parser.mode,delim:Fe(r[0],t).text,color:n}}}),c({type:"leftright",names:["\\left"],props:{numArgs:1,argTypes:["primitive"]},handler:(e,t)=>{const r=Fe(t[0],e),n=e.parser;++n.leftrightDepth;const o=n.parseExpression(!1);--n.leftrightDepth,n.expect("\\right",!1);const s=fe(n.parseFunction(),"leftright-right");return{type:"leftright",mode:n.mode,body:o,left:r.text,right:s.delim,rightColor:s.color}},mathmlBuilder:(e,t)=>{!function(e){if(!e.body)throw new Error("Bug: The leftright ParseNode wasn't fully parsed.")}(e);const r=ee(e.body,t);"."===e.left&&(e.left="");const n=new T.MathNode("mo",[Y(e.left,e.mode)]);n.setAttribute("fence","true"),n.setAttribute("form","prefix"),"∖"===e.left&&n.setAttribute("stretchy","true"),r.unshift(n),"."===e.right&&(e.right="");const o=new T.MathNode("mo",[Y(e.right,e.mode)]);return o.setAttribute("fence","true"),o.setAttribute("form","postfix"),"∖"===e.right&&o.setAttribute("stretchy","true"),e.rightColor&&o.setAttribute("mathcolor",e.rightColor),r.push(o),K(r)}}),c({type:"middle",names:["\\middle"],props:{numArgs:1,argTypes:["primitive"]},handler:(t,r)=>{const n=Fe(r[0],t);if(!t.parser.leftrightDepth)throw new e("\\middle without preceding \\left",n);return{type:"middle",mode:t.parser.mode,delim:n.text}},mathmlBuilder:(e,t)=>{const r=Y(e.delim,e.mode),n=new T.MathNode("mo",[r]);return n.setAttribute("fence","true"),n.setAttribute("lspace","0.05em"),n.setAttribute("rspace","0.05em"),n}});const Ge=(e,t)=>{const r=new T.MathNode(e.label.indexOf("colorbox")>-1?"mpadded":"menclose",[re(e.body,t)]);switch(e.label){case"\\cancel":r.setAttribute("notation","updiagonalstrike");break;case"\\bcancel":r.setAttribute("notation","downdiagonalstrike");break;case"\\longdiv":r.setAttribute("notation","longdiv");break;case"\\phase":r.setAttribute("notation","phasorangle");break;case"\\sout":r.setAttribute("notation","horizontalstrike");break;case"\\fbox":r.setAttribute("notation","box");break;case"\\angl":r.setAttribute("notation","actuarial");break;case"\\fcolorbox":case"\\colorbox":{const t=3;r.setAttribute("width",`+${2*t}pt`),r.setAttribute("height",`+${2*t}pt`),r.setAttribute("lspace",`${t}pt`),r.setAttribute("voffset",`${t}pt`),"\\fcolorbox"===e.label&&r.setAttribute("style","border: 0.06em solid "+String(e.borderColor));break}case"\\xcancel":r.setAttribute("notation","updiagonalstrike downdiagonalstrike")}return e.backgroundColor&&r.setAttribute("mathbackground",e.backgroundColor),r};c({type:"enclose",names:["\\colorbox"],props:{numArgs:2,numOptionalArgs:1,allowedInText:!0,argTypes:["raw","raw","text"]},handler({parser:e,funcName:t},r,n){const o=n[0]&&fe(n[0],"raw").string;let s="";if(o){const e=fe(r[0],"raw").string;s=Me(o,e)}else s=Oe(fe(r[0],"raw").string,e.gullet.macros);const a=r[1];return{type:"enclose",mode:e.mode,label:t,backgroundColor:s,body:a}},mathmlBuilder:Ge}),c({type:"enclose",names:["\\fcolorbox"],props:{numArgs:3,numOptionalArgs:1,allowedInText:!0,argTypes:["raw","raw","raw","text"]},handler({parser:e,funcName:t},r,n){const o=n[0]&&fe(n[0],"raw").string;let s,a="";if(o){const e=fe(r[0],"raw").string,t=fe(r[0],"raw").string;a=Me(o,e),s=Me(o,t)}else a=Oe(fe(r[0],"raw").string,e.gullet.macros),s=Oe(fe(r[1],"raw").string,e.gullet.macros);const i=r[2];return{type:"enclose",mode:e.mode,label:t,backgroundColor:s,borderColor:a,body:i}},mathmlBuilder:Ge}),c({type:"enclose",names:["\\fbox"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!0},handler:({parser:e},t)=>({type:"enclose",mode:e.mode,label:"\\fbox",body:t[0]})}),c({type:"enclose",names:["\\cancel","\\bcancel","\\xcancel","\\sout","\\angl","\\phase","\\longdiv"],props:{numArgs:1},handler({parser:e,funcName:t},r){const n=r[0];return{type:"enclose",mode:e.mode,label:t,body:n}},mathmlBuilder:Ge});const De={};function Pe({type:e,names:t,props:r,handler:n,mathmlBuilder:o}){const s={type:e,numArgs:r.numArgs||0,allowedInText:!1,numOptionalArgs:0,handler:n};for(let e=0;e{if(!t.parser.settings.displayMode)throw new e(`{${t.envName}} can be used only in display mode.`)},We=(e,t,r)=>{let n;const o=e.tags.shift();if(o){if(!o.body)return n=new T.MathNode("mtd",[]),n.setAttribute("style","padding: 0; min-width:0"),n;n=te(o.body,t),n.classes=["tml-tag"]}else{if("multline"===e.colSeparationType&&(e.leqno&&0!==r||!e.leqno&&r!==e.body.length-1))return n=new T.MathNode("mtd",[]),n.setAttribute("style","padding: 0; min-width:0"),n;n=new T.MathNode("mtext",[],["tml-eqn"])}return e.preventTagLap||(n=new T.MathNode("mpadded",[n]),n.setAttribute("style","width:0;"),n.setAttribute("width","0"),e.leqno||n.setAttribute("lspace","-1width")),n=new T.MathNode("mtd",[n]),e.preventTagLap||n.setAttribute("style","padding: 0; min-width:0"),n};function Xe(t,{hskipBeforeAndAfter:r,addJot:n,cols:o,arraystretch:s,colSeparationType:a,addEqnNum:i,singleRow:l,emptySingleRow:c,maxNumCols:m,leqno:u},p){if(t.gullet.beginGroup(),l||t.gullet.macros.set("\\cr","\\\\\\relax"),i&&(t.gullet.macros.set("\\tag","\\env@tag{\\text{#1}}"),t.gullet.macros.set("\\notag","\\env@notag"),t.gullet.macros.set("\\nonumber","\\env@notag")),void 0===s||Number.isNaN(s)){const r=t.gullet.expandMacroAsText("\\arraystretch");if(null==r)s=1;else if(!(s=parseFloat(r))||s<0)throw new e(`Invalid \\arraystretch: ${r}`)}t.gullet.beginGroup();let d=[];const h=[d],g=[],f=[];let b;const y=[];for(y.push(He(t));;){let r=t.parseExpression(!1,l?"\\end":"\\\\");if(i&&!b)for(let e=0;e1||!c)&&h.pop(),y.length0){const t=e.cols;let r="",n=!1,o=0,s=t.length;"separator"===t[0].type&&(l+="left ",o=1),"separator"===t[t.length-1].type&&(l+="right ",s-=1);for(let e=o;e0?"top ":"",l+=u[u.length-1].length>0?"bottom ":"";for(let e=1;ee.length)));return s.cols=new Array(a).fill({type:"align",align:n}),r?{type:"leftright",mode:t.mode,body:[s],left:r[0],right:r[1],rightColor:void 0}:s},mathmlBuilder:Ye}),Pe({type:"array",names:["smallmatrix"],props:{numArgs:0},handler(e){const t=Xe(e.parser,{arraystretch:.5},"script");return t.colSeparationType="small",t},mathmlBuilder:Ye}),Pe({type:"array",names:["subarray"],props:{numArgs:1},handler(t,r){const n=(ye(r[0])?[r[0]]:fe(r[0],"ordgroup").body).map((function(t){const r=be(t).text;if(-1!=="lc".indexOf(r))return{type:"align",align:r};throw new e("Unknown column alignment: "+r,t)}));if(n.length>1)throw new e("{subarray} can contain only one column");let o={cols:n,hskipBeforeAndAfter:!1,colSeparationType:"array",arraystretch:0};if(o=Xe(t.parser,o,"script"),o.body.length>0&&o.body[0].length>1)throw new e("{subarray} can contain only one column");return o},mathmlBuilder:Ye}),Pe({type:"array",names:["cases","dcases","rcases","drcases"],props:{numArgs:0},handler(e){const t=Xe(e.parser,{cols:[{type:"align",align:"l"},{type:"align",align:"l"}],colSeparationType:"cases"},Ze(e.envName));return{type:"leftright",mode:e.mode,body:[t],left:e.envName.indexOf("r")>-1?".":"\\{",right:e.envName.indexOf("r")>-1?"\\}":".",rightColor:void 0}},mathmlBuilder:Ye}),Pe({type:"array",names:["align","align*","aligned","split"],props:{numArgs:0},handler:Ke,mathmlBuilder:Ye}),Pe({type:"array",names:["gathered","gather","gather*"],props:{numArgs:0},handler(e){s.contains(["gather","gather*"],e.envName)&&Ve(e);const t={cols:[{type:"align",align:"c"}],addJot:!0,colSeparationType:"gather",addEqnNum:"gather"===e.envName,emptySingleRow:!0,leqno:e.parser.settings.leqno};return Xe(e.parser,t,"display")},mathmlBuilder:Ye}),Pe({type:"array",names:["alignat","alignat*","alignedat"],props:{numArgs:1},handler:Ke,mathmlBuilder:Ye}),Pe({type:"array",names:["equation","equation*"],props:{numArgs:0},handler(e){Ve(e);const t={addEqnNum:"equation"===e.envName,emptySingleRow:!0,singleRow:!0,maxNumCols:1,colSeparationType:"gather",leqno:e.parser.settings.leqno};return Xe(e.parser,t,"display")},mathmlBuilder:Ye}),Pe({type:"array",names:["multline","multline*"],props:{numArgs:0},handler(e){Ve(e);const t={addEqnNum:"multline"===e.envName,maxNumCols:1,colSeparationType:"multline",leqno:e.parser.settings.leqno};return Xe(e.parser,t,"display")},mathmlBuilder:Ye}),Pe({type:"array",names:["CD"],props:{numArgs:0},handler:t=>(Ve(t),function(t){const r=[];for(t.gullet.beginGroup(),t.gullet.macros.set("\\cr","\\\\\\relax"),t.gullet.beginGroup();;){r.push(t.parseExpression(!1,"\\\\")),t.gullet.endGroup(),t.gullet.beginGroup();const n=t.fetch().text;if("&"!==n&&"\\\\"!==n){if("\\end"===n){0===r[r.length-1].length&&r.pop();break}throw new e("Expected \\\\ or \\cr or \\end",t.nextToken)}t.consume()}let n=[];const o=[n];for(let i=0;i-1);else{if(!("<>AV".indexOf(o)>-1))throw new e('Expected one of "<>AV=|." after @.');for(let t=0;t<2;t++){let n=!0;for(let c=r+1;c({type:"envTag",mode:e.mode,body:t[0]}),mathmlBuilder:(e,t)=>new T.MathNode("mrow")}),c({type:"noTag",names:["\\env@notag"],props:{numArgs:0},handler:({parser:e})=>({type:"noTag",mode:e.mode}),mathmlBuilder:(e,t)=>new T.MathNode("mrow")});const et=(e,t)=>{const r=e.font,n=t.withFont(r),o=re(e.body,n);if(0===o.children.length)return o;if("boldsymbol"===r&&["mo","mpadded"].includes(o.type))return o.style.fontWeight="bold",o;let s="mo"===o.children[0].type;for(let e=1;e{const n=u(r[0]);let o=t;return o in tt&&(o=tt[o]),{type:"font",mode:e.mode,font:o.slice(1),body:n}},mathmlBuilder:et}),c({type:"font",names:["\\rm","\\sf","\\tt","\\bf","\\it","\\cal"],props:{numArgs:0,allowedInText:!0},handler:({parser:e,funcName:t,breakOnTokenText:r},n)=>{const{mode:o}=e,s=e.parseExpression(!0,r);return{type:"font",mode:o,font:`math${t.slice(1)}`,body:{type:"ordgroup",mode:e.mode,body:s}}},mathmlBuilder:et});const rt=["display","text","script","scriptscript"],nt={auto:-1,display:0,text:0,script:1,scriptscript:2},ot=(e,t)=>{const r="auto"===e.scriptLevel?t.incrementLevel():"display"===e.scriptLevel?t.withLevel(je):"text"===e.scriptLevel?t.withLevel(Ue):t.withLevel(_e);let n=new T.MathNode("mfrac",[re(e.numer,r),re(e.denom,r)]);if(e.hasBarLine){if(e.barSize){const r=ue(e.barSize,t);n.setAttribute("linethickness",r.number+r.unit)}}else n.setAttribute("linethickness","0px");if(null!=e.leftDelim||null!=e.rightDelim){const t=[];if(null!=e.leftDelim){const r=new T.MathNode("mo",[new T.TextNode(e.leftDelim.replace("\\",""))]);r.setAttribute("fence","true"),t.push(r)}if(t.push(n),null!=e.rightDelim){const r=new T.MathNode("mo",[new T.TextNode(e.rightDelim.replace("\\",""))]);r.setAttribute("fence","true"),t.push(r)}n=K(t)}return"auto"!==e.scriptLevel&&(n=new T.MathNode("mstyle",[n]),n.setAttribute("displaystyle",String("display"===e.scriptLevel)),n.setAttribute("scriptlevel",nt[e.scriptLevel])),n};c({type:"genfrac",names:["\\dfrac","\\frac","\\tfrac","\\dbinom","\\binom","\\tbinom","\\\\atopfrac","\\\\bracefrac","\\\\brackfrac"],props:{numArgs:2,allowedInArgument:!0},handler:({parser:e,funcName:t},r)=>{const n=r[0],o=r[1];let s=!1,a=null,i=null,l="auto";switch(t){case"\\dfrac":case"\\frac":case"\\tfrac":s=!0;break;case"\\\\atopfrac":s=!1;break;case"\\dbinom":case"\\binom":case"\\tbinom":a="(",i=")";break;case"\\\\bracefrac":a="\\{",i="\\}";break;case"\\\\brackfrac":a="[",i="]";break;default:throw new Error("Unrecognized genfrac command")}switch(t){case"\\dfrac":case"\\dbinom":l="display";break;case"\\tfrac":case"\\tbinom":l="text"}return{type:"genfrac",mode:e.mode,continued:!1,numer:n,denom:o,hasBarLine:s,leftDelim:a,rightDelim:i,scriptLevel:l,barSize:null}},mathmlBuilder:ot}),c({type:"genfrac",names:["\\cfrac"],props:{numArgs:2},handler:({parser:e,funcName:t},r)=>{const n=r[0],o=r[1];return{type:"genfrac",mode:e.mode,continued:!0,numer:n,denom:o,hasBarLine:!0,leftDelim:null,rightDelim:null,scriptLevel:"display",barSize:null}}}),c({type:"infix",names:["\\over","\\choose","\\atop","\\brace","\\brack"],props:{numArgs:0,infix:!0},handler({parser:e,funcName:t,token:r}){let n;switch(t){case"\\over":n="\\frac";break;case"\\choose":n="\\binom";break;case"\\atop":n="\\\\atopfrac";break;case"\\brace":n="\\\\bracefrac";break;case"\\brack":n="\\\\brackfrac";break;default:throw new Error("Unrecognized infix genfrac command")}return{type:"infix",mode:e.mode,replaceWith:n,token:r}}});const st=function(e){let t=null;return e.length>0&&(t=e,t="."===t?null:t),t};c({type:"genfrac",names:["\\genfrac"],props:{numArgs:6,allowedInArgument:!0,argTypes:["math","math","size","text","math","math"]},handler({parser:e},t){const r=t[4],n=t[5],o=u(t[0]),s="atom"===o.type&&"open"===o.family?st(o.text):null,a=u(t[1]),i="atom"===a.type&&"close"===a.family?st(a.text):null,l=fe(t[2],"size");let c,m=null;l.isBlank?c=!0:(m=l.value,c=m.number>0);let p="auto",d=t[3];if("ordgroup"===d.type){if(d.body.length>0){const e=fe(d.body[0],"textord");p=rt[Number(e.text)]}}else d=fe(d,"textord"),p=rt[Number(d.text)];return{type:"genfrac",mode:e.mode,numer:r,denom:n,continued:!1,hasBarLine:c,barSize:m,leftDelim:s,rightDelim:i,scriptLevel:p}},mathmlBuilder:ot}),c({type:"infix",names:["\\above"],props:{numArgs:1,argTypes:["size"],infix:!0},handler:({parser:e,funcName:t,token:r},n)=>({type:"infix",mode:e.mode,replaceWith:"\\\\abovefrac",barSize:fe(n[0],"size").value,token:r})}),c({type:"genfrac",names:["\\\\abovefrac"],props:{numArgs:3,argTypes:["math","size","math"]},handler:({parser:e,funcName:t},r)=>{const n=r[0],o=function(e){if(!e)throw new Error("Expected non-null, but got "+String(e));return e}(fe(r[1],"infix").barSize),s=r[2],a=o.number>0;return{type:"genfrac",mode:e.mode,numer:n,denom:s,continued:!1,hasBarLine:a,barSize:o,leftDelim:null,rightDelim:null,scriptLevel:"auto"}},mathmlBuilder:ot});c({type:"horizBrace",names:["\\overbrace","\\underbrace"],props:{numArgs:1},handler:({parser:e,funcName:t},r)=>({type:"horizBrace",mode:e.mode,label:t,isOver:/^\\over/.test(t),base:r[0]}),mathmlBuilder:(e,t)=>{const r=S(e.label);return new T.MathNode(e.isOver?"mover":"munder",[re(e.base,t),r])}}),c({type:"href",names:["\\href"],props:{numArgs:2,argTypes:["url","original"],allowedInText:!0},handler:({parser:t,token:r},n)=>{const o=n[1],s=fe(n[0],"url").url;if(!t.settings.isTrusted({command:"\\href",url:s}))throw new e('Function "\\href" is not trusted',r);return{type:"href",mode:t.mode,href:s,body:p(o)}},mathmlBuilder:(e,t)=>{let r=te(e.body,t);return r instanceof k||(r=new k("mrow",[r])),r.setAttribute("href",e.href),r}}),c({type:"href",names:["\\url"],props:{numArgs:1,argTypes:["url"],allowedInText:!0},handler:({parser:t,token:r},n)=>{const o=fe(n[0],"url").url;if(!t.settings.isTrusted({command:"\\url",url:o}))throw new e('Function "\\url" is not trusted',r);const s=[];for(let e=0;e{const s=fe(o[0],"raw").string,a=o[1];if(t.settings.strict)throw new e(`Function "${r}" is disabled in strict mode`,n);let i;const l={};switch(r){case"\\class":l.class=s,i={command:"\\class",class:s};break;case"\\id":l.id=s,i={command:"\\id",id:s};break;case"\\style":l.style=s,i={command:"\\style",style:s};break;case"\\data":{const t=s.split(",");for(let r=0;r{const r=te(e.body,t),n=[];e.attributes.class&&n.push(...e.attributes.class.trim().split(/\s+/)),r.classes=n;for(const t in e.attributes)"class"!==t&&Object.prototype.hasOwnProperty.call(e.attributes,t)&&r.setAttribute(t,e.attributes[t]);return r}});const at=function(t){if(/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(t))return{number:+t,unit:"bp"};{const r=/([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(t);if(!r)throw new e("Invalid size: '"+t+"' in \\includegraphics");const n={number:+(r[1]+r[2]),unit:r[3]};if(!ce(n))throw new e("Invalid unit: '"+n.unit+"' in \\includegraphics.");return n}};c({type:"includegraphics",names:["\\includegraphics"],props:{numArgs:1,numOptionalArgs:1,argTypes:["raw","url"],allowedInText:!1},handler:({parser:t,token:r},n,o)=>{let s={number:0,unit:"em"},a={number:.9,unit:"em"},i={number:0,unit:"em"},l="";if(o[0]){const t=fe(o[0],"raw").string.split(",");for(let r=0;r{const r=ue(e.height,t),n={number:0,unit:"em"};e.totalheight.number>0&&e.totalheight.unit===r.unit&&e.totalheight.number>r.number&&(n.number=e.totalheight.number-r.number,n.unit=r.unit);let o=0;e.width.number>0&&(o=ue(e.width,t));const s={height:r.number+n.number+"em"};o.number>0&&(s.width=o.number+o.unit),n.number>0&&(s.verticalAlign=-n.number+n.unit);const a=new x(e.src,e.alt,s);return a.height=r,a.depth=n,new T.MathNode("mtext",[a])}}),c({type:"kern",names:["\\kern","\\mkern","\\hskip","\\mskip"],props:{numArgs:1,argTypes:["size"],primitive:!0,allowedInText:!0},handler({parser:t,funcName:r,token:n},o){const s=fe(o[0],"size");if(t.settings.strict){const o="m"===r[1],a="mu"===s.value.unit;if(o){if(!a)throw new e(`LaTeX's ${r} supports only mu units, not ${s.value.unit} units`,n);if("math"!==t.mode)throw new e(`LaTeX's ${r} works only in math mode`,n)}else if(a)throw new e(`LaTeX's ${r} doesn't support mu units`,n)}return{type:"kern",mode:t.mode,dimension:s.value}},mathmlBuilder(e,t){const r=ue(e.dimension,t),n="em"===r.unit?it(r.number):"";if("text"===e.mode&&n.length>0){const e=new T.TextNode(n);return new T.MathNode("mtext",[e])}{const e=new T.MathNode("mspace");return e.setAttribute("width",r.number+r.unit),e}}});const it=function(e){return e>=.05555&&e<=.05556?" ":e>=.1666&&e<=.1667?" ":e>=.2222&&e<=.2223?" ":e>=.2777&&e<=.2778?"  ":""},lt=/[^A-Za-z_0-9-]/g;c({type:"label",names:["\\label"],props:{numArgs:1,argTypes:["raw"]},handler:({parser:e},t)=>({type:"label",mode:e.mode,string:t[0].string.replace(lt,"")}),mathmlBuilder(e,t){const r=new T.MathNode("mrow",[],["tml-label"]);return e.string.length>0&&r.setAttribute("id",e.string),r}});const ct=["\\clap","\\llap","\\rlap"];c({type:"lap",names:["\\mathllap","\\mathrlap","\\mathclap","\\clap","\\llap","\\rlap"],props:{numArgs:1,allowedInText:!0},handler:({parser:t,funcName:r,token:n},o)=>{if(ct.includes(r)){if(t.settings.strict&&"text"!==t.mode)throw new e(`{${r}} can be used only in text mode.\n Try \\math${r.slice(1)}`,n);r=r.slice(1)}else r=r.slice(5);const s=o[0];return{type:"lap",mode:t.mode,alignment:r,body:s}},mathmlBuilder:(e,t)=>{const r=new T.MathNode("mpadded",[re(e.body,t)]);if("rlap"===e.alignment)e.body.body.length>0&&"genfrac"===e.body.body[0].type&&r.setAttribute("lspace","0.16667em");else{const t="llap"===e.alignment?"-1":"-0.5";r.setAttribute("lspace",t+"width")}return r.setAttribute("width","0px"),r}}),c({type:"ordgroup",names:["\\(","$"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler({funcName:e,parser:t},r){const n=t.mode;t.switchMode("math");const o="\\("===e?"\\)":"$",s=t.parseExpression(!1,o);return t.expect(o),t.switchMode(n),{type:"ordgroup",mode:t.mode,body:s}}}),c({type:"text",names:["\\)","\\]"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler(t,r){throw new e(`Mismatched ${t.funcName}`,r)}});c({type:"mathchoice",names:["\\mathchoice"],props:{numArgs:4,primitive:!0},handler:({parser:e},t)=>({type:"mathchoice",mode:e.mode,display:p(t[0]),text:p(t[1]),script:p(t[2]),scriptscript:p(t[3])}),mathmlBuilder:(e,t)=>{const r=((e,t)=>{switch(t.level){case Re:return e.display;case je:return e.text;case Ue:return e.script;case _e:return e.scriptscript;default:return e.text}})(e,t);return te(r,t)}});const mt=["text","textord","mathord","atom"];function ut(e,t){let r;const n=ee(e.body,t);if("minner"===e.mclass)r=new T.MathNode("mpadded",n);else if("mord"===e.mclass)e.isCharacterBox||"mathord"===n[0].type?(r=n[0],r.type="mi"):r=new T.MathNode("mi",n);else{e.mustPromote?(r=n[0],r.type="mo",e.isCharacterBox&&e.body[0].text&&/[A-Za-z]/.test(e.body[0].text)&&r.setAttribute("mathvariant","italic")):r=new T.MathNode("mo",n);const o=t.level<2;"mbin"===e.mclass?(r.attributes.lspace=o?"0.2222em":"0",r.attributes.rspace=o?"0.2222em":"0"):"mrel"===e.mclass?(r.attributes.lspace=o?"0.2778em":"0",r.attributes.rspace=o?"0.2778em":"0"):"mpunct"===e.mclass?(r.attributes.lspace="0em",r.attributes.rspace=o?"0.1667em":"0"):"mopen"===e.mclass||"mclose"===e.mclass?(r.attributes.lspace="0em",r.attributes.rspace="0em"):"minner"===e.mclass&&o&&(r.attributes.lspace="0.0556em",r.attributes.width="+0.1111em"),"mopen"!==e.mclass&&"mclose"!==e.mclass&&(delete r.attributes.stretchy,delete r.attributes.form)}return r}c({type:"mclass",names:["\\mathord","\\mathbin","\\mathrel","\\mathopen","\\mathclose","\\mathpunct","\\mathinner"],props:{numArgs:1,primitive:!0},handler({parser:e,funcName:t},r){const n=r[0],o=s.isCharacterBox(n);let a=!0;const i={type:"mathord",text:"",mode:e.mode},l=n.body?n.body:[n];for(const e of l){if(!mt.includes(e.type)){a=!1;break}e.text?i.text+=e.text:e.body&&e.body.map((e=>{i.text+=e.text}))}return{type:"mclass",mode:e.mode,mclass:"m"+t.slice(5),body:p(a?i:n),isCharacterBox:o,mustPromote:a}},mathmlBuilder:ut});const pt=e=>{const t="ordgroup"===e.type&&e.body.length?e.body[0]:e;return"atom"!==t.type||"bin"!==t.family&&"rel"!==t.family?"mord":"m"+t.family};c({type:"mclass",names:["\\@binrel"],props:{numArgs:2},handler:({parser:e},t)=>({type:"mclass",mode:e.mode,mclass:pt(t[0]),body:p(t[1]),isCharacterBox:s.isCharacterBox(t[1])})}),c({type:"mclass",names:["\\stackrel","\\overset","\\underset"],props:{numArgs:2},handler({parser:e,funcName:t},r){const n=r[1],o=r[0],s={type:"op",mode:n.mode,limits:!0,alwaysHandleSupSub:!0,parentIsSupSub:!1,symbol:!1,stack:!0,suppressBaseShift:"\\stackrel"!==t,body:p(n)};return{type:"supsub",mode:o.mode,base:s,sup:"\\underset"===t?null:o,sub:"\\underset"===t?o:null}},mathmlBuilder:ut});const dt=(e,t,r)=>{if(!e)return r;const n=re(e,t);return"mrow"===n.type&&0===n.children.length?r:n};c({type:"multiscript",names:["\\sideset","\\pres@cript"],props:{numArgs:3},handler({parser:t,funcName:r,token:n},o){if(0===o[2].body.length)throw new e(r+"cannot parse an empty base.");const s=o[2].body[0];if(t.settings.strict&&"\\sideset"===r&&!s.symbol)throw new e("The base of \\sideset must be a big operator. Try \\prescript.");if(o[0].body.length>0&&"supsub"!==o[0].body[0].type||o[1].body.length>0&&"supsub"!==o[1].body[0].type)throw new e("\\sideset can parse only subscripts and superscripts in its first two arguments",n);const a=o[0].body.length>0?o[0].body[0]:null,i=o[1].body.length>0?o[1].body[0]:null;return a||i?a?{type:"multiscript",mode:t.mode,isSideset:"\\sideset"===r,prescripts:a,postscripts:i,base:s}:{type:"styling",mode:t.mode,scriptLevel:"text",body:[{type:"supsub",mode:t.mode,base:s,sup:i.sup,sub:i.sub}]}:s},mathmlBuilder(e,t){const r=re(e.base,t),n=new T.MathNode("mprescripts"),o=new T.MathNode("none");let s=[];const a=dt(e.prescripts.sub,t,o),i=dt(e.prescripts.sup,t,o);if(e.isSideset&&(a.setAttribute("style","text-align: left;"),i.setAttribute("style","text-align: left;")),e.postscripts){s=[r,dt(e.postscripts.sub,t,o),dt(e.postscripts.sup,t,o),n,a,i]}else s=[r,n,a,i];return new T.MathNode("mmultiscripts",s)}}),c({type:"not",names:["\\not"],props:{numArgs:1,primitive:!0,allowedInText:!1},handler({parser:e},t){const r=s.isCharacterBox(t[0]);let n;if(r)n=p(t[0]),"\\"===n[0].text.charAt(0)&&(n[0].text=M.math[n[0].text].replace),n[0].text=n[0].text.slice(0,1)+"̸"+n[0].text.slice(1);else{n=[{type:"textord",mode:"math",text:"̸"},{type:"kern",mode:"math",dimension:{number:-.6,unit:"em"}},t[0]]}return{type:"not",mode:e.mode,body:n,isCharacterBox:r}},mathmlBuilder(e,t){if(e.isCharacterBox){return ee(e.body,t)[0]}return te(e.body,t,!0)}});const ht=["textord","mathord","atom"],gt=["\\smallint"],ft=["textord","mathord","ordgroup","close","leftright"],bt=["}","\\left","\\middle","\\right"],yt=e=>e.length>0&&(Le.includes(e)||Ie[e]||bt.includes(e)),wt=(e,t)=>{let r;if(e.symbol)r=new k("mo",[Y(e.name,e.mode)]),s.contains(gt,e.name)?r.setAttribute("largeop","false"):r.setAttribute("movablelimits","false");else if(e.body)r=new k("mo",ee(e.body,t));else if(r=new k("mi",[new A(e.name.slice(1))]),!e.parentIsSupSub){const t=new k("mo",[Y("⁡","text")]);r=new k("mpadded",[r,t]);const n=e.needsLeadingSpace?.1667:0,o=e.isFollowedByDelimiter?0:.1666;e.needsLeadingSpace&&r.setAttribute("lspace","0.1667em"),n+o>0&&r.setAttribute("width",`+${n+o}em`)}return r},xt={"∏":"\\prod","∐":"\\coprod","∑":"\\sum","⋀":"\\bigwedge","⋁":"\\bigvee","⋂":"\\bigcap","⋃":"\\bigcup","⨀":"\\bigodot","⨁":"\\bigoplus","⨂":"\\bigotimes","⨄":"\\biguplus","⨅":"\\bigsqcap","⨆":"\\bigsqcup"};c({type:"op",names:["\\coprod","\\bigvee","\\bigwedge","\\biguplus","\\bigcap","\\bigcup","\\intop","\\prod","\\sum","\\bigotimes","\\bigoplus","\\bigodot","\\bigsqcap","\\bigsqcup","\\smallint","∏","∐","∑","⋀","⋁","⋂","⋃","⨀","⨁","⨂","⨄","⨆"],props:{numArgs:0},handler:({parser:e,funcName:t},r)=>{let n=t;return 1===n.length&&(n=xt[n]),{type:"op",mode:e.mode,limits:!0,parentIsSupSub:!1,symbol:!0,stack:!1,name:n}},mathmlBuilder:wt}),c({type:"op",names:["\\mathop"],props:{numArgs:1,primitive:!0},handler:({parser:e},t)=>{const r=t[0],n=r.body?r.body:[r],o=1===n.length&&ht.includes(n[0].type);return{type:"op",mode:e.mode,limits:!0,parentIsSupSub:!1,symbol:o,stack:!1,name:o?n[0].text:null,body:o?null:p(r)}},mathmlBuilder:wt});const kt={"∫":"\\int","∬":"\\iint","∭":"\\iiint","∮":"\\oint","∯":"\\oiint","∰":"\\oiiint","∱":"\\intclockwise","∲":"\\varointclockwise","⨌":"\\iiiint","⨍":"\\intbar","⨎":"\\intBar","⨏":"\\fint","⨒":"\\rppolint","⨓":"\\scpolint","⨕":"\\pointint","⨖":"\\sqint","⨗":"\\intlarhk","⨘":"\\intx","⨙":"\\intcap","⨚":"\\intcup"};c({type:"op",names:["\\arcsin","\\arccos","\\arctan","\\arctg","\\arcctg","\\arg","\\ch","\\cos","\\cosec","\\cosh","\\cot","\\cotg","\\coth","\\csc","\\ctg","\\cth","\\deg","\\dim","\\exp","\\hom","\\ker","\\lg","\\ln","\\log","\\sec","\\sin","\\sinh","\\sh","\\sgn","\\tan","\\tanh","\\tg","\\th"],props:{numArgs:0},handler({parser:e,funcName:t}){const r=e.prevAtomType,n=e.gullet.future().text;return{type:"op",mode:e.mode,limits:!1,parentIsSupSub:!1,symbol:!1,stack:!1,isFollowedByDelimiter:yt(n),needsLeadingSpace:r.length>0&&s.contains(ft,r),name:t}},mathmlBuilder:wt}),c({type:"op",names:["\\det","\\gcd","\\inf","\\lim","\\max","\\min","\\Pr","\\sup"],props:{numArgs:0},handler({parser:e,funcName:t}){const r=e.prevAtomType,n=e.gullet.future().text;return{type:"op",mode:e.mode,limits:!0,parentIsSupSub:!1,symbol:!1,stack:!1,isFollowedByDelimiter:yt(n),needsLeadingSpace:r.length>0&&s.contains(ft,r),name:t}},mathmlBuilder:wt}),c({type:"op",names:["\\int","\\iint","\\iiint","\\iiiint","\\oint","\\oiint","\\oiiint","\\intclockwise","\\varointclockwise","\\intbar","\\intBar","\\fint","\\rppolint","\\scpolint","\\pointint","\\sqint","\\intlarhk","\\intx","\\intcap","\\intcup","∫","∬","∭","∮","∯","∰","∱","∲","⨌","⨍","⨎","⨏","⨒","⨓","⨕","⨖","⨗","⨘","⨙","⨚"],props:{numArgs:0},handler({parser:e,funcName:t}){let r=t;return 1===r.length&&(r=kt[r]),{type:"op",mode:e.mode,limits:!1,parentIsSupSub:!1,symbol:!0,stack:!1,name:r}},mathmlBuilder:wt});const At={};function vt(e,t){At[e]=t}c({type:"operatorname",names:["\\operatorname@","\\operatornamewithlimits"],props:{numArgs:1,allowedInArgument:!0},handler:({parser:e,funcName:t},r)=>{const n=r[0],o=e.prevAtomType;return{type:"operatorname",mode:e.mode,body:p(n),alwaysHandleSupSub:"\\operatornamewithlimits"===t,limits:!1,parentIsSupSub:!1,needsLeadingSpace:o.length>0&&s.contains(ft,o)}},mathmlBuilder:(e,t)=>{let r,n=ee(e.body,t.withFont("mathrm")),o=!0;for(let e=0;ee.toText())).join("");n=[new T.TextNode(e)]}else if(1===n.length&&s.contains(["mover","munder"],n[0].type)&&("mi"===n[0].children[0].type||"mtext"===n[0].children[0].type)){if(n[0].children[0].type="mi",e.parentIsSupSub)return new T.MathNode("mrow",n);{const e=new T.MathNode("mo",[Y("⁡","text")]);return T.newDocumentFragment([n[0],e])}}if(o?(r=new T.MathNode("mi",n),r.setAttribute("mathvariant","normal")):r=new T.MathNode("mrow",n),!e.parentIsSupSub){const t=new T.MathNode("mo",[Y("⁡","text")]);if(e.needsLeadingSpace){const e=new T.MathNode("mspace");return e.setAttribute("width","0.1667em"),T.newDocumentFragment([e,r,t])}return T.newDocumentFragment([r,t])}return r}}),vt("\\operatorname","\\@ifstar\\operatornamewithlimits\\operatorname@"),m({type:"ordgroup",mathmlBuilder:(e,t)=>te(e.body,t,!0)}),c({type:"overline",names:["\\overline"],props:{numArgs:1},handler({parser:e},t){const r=t[0];return{type:"overline",mode:e.mode,body:r}},mathmlBuilder(e,t){const r=new T.MathNode("mo",[new T.TextNode("_")]);r.setAttribute("stretchy","true");const n=new T.MathNode("mover",[re(e.body,t),r]);return n.setAttribute("accent","true"),n}}),c({type:"phantom",names:["\\phantom"],props:{numArgs:1,allowedInText:!0},handler:({parser:e},t)=>{const r=t[0];return{type:"phantom",mode:e.mode,body:p(r)}},mathmlBuilder:(e,t)=>{const r=ee(e.body,t);return new T.MathNode("mphantom",r)}}),c({type:"hphantom",names:["\\hphantom"],props:{numArgs:1,allowedInText:!0},handler:({parser:e},t)=>{const r=t[0];return{type:"hphantom",mode:e.mode,body:r}},mathmlBuilder:(e,t)=>{const r=ee(p(e.body),t),n=new T.MathNode("mphantom",r),o=new T.MathNode("mpadded",[n]);return o.setAttribute("height","0px"),o.setAttribute("depth","0px"),o}}),c({type:"vphantom",names:["\\vphantom"],props:{numArgs:1,allowedInText:!0},handler:({parser:e},t)=>{const r=t[0];return{type:"vphantom",mode:e.mode,body:r}},mathmlBuilder:(e,t)=>{const r=ee(p(e.body),t),n=new T.MathNode("mphantom",r),o=new T.MathNode("mpadded",[n]);return o.setAttribute("width","0px"),o}}),c({type:"pmb",names:["\\pmb"],props:{numArgs:1,allowedInText:!0},handler:({parser:e},t)=>({type:"pmb",mode:e.mode,body:p(t[0])}),mathmlBuilder(e,t){const r=ee(e.body,t),n=v(r);return n.setAttribute("style","text-shadow: 0.02em 0.01em 0.04px"),n}});const Tt=e=>e>=0?"+":"-",Nt=(e,t)=>{const r=t.withLevel(je),n=new T.MathNode("mpadded",[re(e.body,r)]),o=ue(e.dy,t);n.setAttribute("voffset",o.number+o.unit);const s=Math.abs(o.number);return n.setAttribute("height",Tt(o.number)+s+o.unit),n.setAttribute("depth",Tt(-o.number)+s+o.unit),n};c({type:"raise",names:["\\raise","\\lower"],props:{numArgs:2,argTypes:["size","primitive"],primitive:!0},handler({parser:e,funcName:t},r){const n=fe(r[0],"size").value;"\\lower"===t&&(n.number*=-1);const o=r[1];return{type:"raise",mode:e.mode,dy:n,body:o}},mathmlBuilder:Nt}),c({type:"raise",names:["\\raisebox"],props:{numArgs:2,argTypes:["size","hbox"],allowedInText:!0},handler({parser:e,funcName:t},r){const n=fe(r[0],"size").value,o=r[1];return{type:"raise",mode:e.mode,dy:n,body:o}},mathmlBuilder:Nt}),c({type:"ref",names:["\\ref","\\eqref"],props:{numArgs:1,argTypes:["raw"]},handler:({parser:e,funcName:t},r)=>({type:"ref",mode:e.mode,funcName:t,string:r[0].string.replace(lt,"")}),mathmlBuilder(e,t){const r="\\ref"===e.funcName?["tml-ref"]:["tml-ref","tml-eqref"],n=new T.MathNode("mtext",[new T.TextNode("")],r);return n.setAttribute("href","#"+e.string),n}}),c({type:"internal",names:["\\relax"],props:{numArgs:0,allowedInText:!0},handler:({parser:e})=>({type:"internal",mode:e.mode})}),c({type:"rule",names:["\\rule"],props:{numArgs:2,numOptionalArgs:1,argTypes:["size","size","size"]},handler({parser:e},t,r){const n=r[0],o=fe(t[0],"size"),s=fe(t[1],"size");return{type:"rule",mode:e.mode,shift:n&&fe(n,"size").value,width:o.value,height:s.value}},mathmlBuilder(e,t){const r=ue(e.width,t),n=ue(e.height,t),o=e.shift?ue(e.shift,t):{number:0,unit:"em"},s=t.color&&t.getColor()||"black",a=new T.MathNode("mspace");if(r.number>0&&n.number>0&&a.setAttribute("mathbackground",s),a.setAttribute("width",r.number+r.unit),a.setAttribute("height",n.number+n.unit),0===o.number)return a;const i=new T.MathNode("mpadded",[a]);return o.number>=0?i.setAttribute("height","+"+o.number+o.unit):(i.setAttribute("height",o.number+o.unit),i.setAttribute("depth","+"+-o.number+o.unit)),i.setAttribute("voffset",o.number+o.unit),i}});const St={"\\tiny":.5,"\\sixptsize":.6,"\\Tiny":.6,"\\scriptsize":.7,"\\footnotesize":.8,"\\small":.9,"\\normalsize":1,"\\large":1.2,"\\Large":1.44,"\\LARGE":1.728,"\\huge":2.074,"\\Huge":2.488};c({type:"sizing",names:["\\tiny","\\sixptsize","\\Tiny","\\scriptsize","\\footnotesize","\\small","\\normalsize","\\large","\\Large","\\LARGE","\\huge","\\Huge"],props:{numArgs:0,allowedInText:!0},handler:({breakOnTokenText:e,funcName:t,parser:r},n)=>{r.settings.strict&&"math"===r.mode&&console.log(`Temml strict-mode warning: Command ${t} is invalid in math mode.`);const o=r.parseExpression(!1,e);return{type:"sizing",mode:r.mode,funcName:t,body:o}},mathmlBuilder:(e,t)=>{const r=t.withFontSize(St[e.funcName]),n=ee(e.body,r),o=v(n),s=(St[e.funcName]/t.fontSize).toFixed(4);return o.setAttribute("mathsize",s+"em"),o}}),c({type:"smash",names:["\\smash"],props:{numArgs:1,numOptionalArgs:1,allowedInText:!0},handler:({parser:e},t,r)=>{let n=!1,o=!1;const s=r[0]&&fe(r[0],"ordgroup");if(s){let e="";for(let t=0;t{const r=new T.MathNode("mpadded",[re(e.body,t)]);return e.smashHeight&&r.setAttribute("height","0px"),e.smashDepth&&r.setAttribute("depth","0px"),r}}),c({type:"sqrt",names:["\\sqrt"],props:{numArgs:1,numOptionalArgs:1},handler({parser:e},t,r){const n=r[0],o=t[0];return{type:"sqrt",mode:e.mode,body:o,index:n}},mathmlBuilder(e,t){const{body:r,index:n}=e;return n?new T.MathNode("mroot",[re(r,t),re(n,t.incrementLevel())]):new T.MathNode("msqrt",[re(r,t)])}});const qt={display:0,text:1,script:2,scriptscript:3},Bt={display:["0","true"],text:["0","false"],script:["1","false"],scriptscript:["2","false"]};c({type:"styling",names:["\\displaystyle","\\textstyle","\\scriptstyle","\\scriptscriptstyle"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler({breakOnTokenText:e,funcName:t,parser:r},n){const o=r.parseExpression(!0,e),s=t.slice(1,t.length-5);return{type:"styling",mode:r.mode,scriptLevel:s,body:o}},mathmlBuilder(e,t){const r=t.withLevel(qt[e.scriptLevel]),n=ee(e.body,r),o=v(n),s=Bt[e.scriptLevel];return o.setAttribute("scriptlevel",s[0]),o.setAttribute("displaystyle",s[1]),o}});const Mt=/^m(over|under|underover)$/;m({type:"supsub",mathmlBuilder(e,t){let r,n,o=!1,s=!1,a=!1;e.base&&"horizBrace"===e.base.type&&(n=!!e.sup,n===e.base.isOver&&(o=!0,r=e.base.isOver)),!e.base||e.base.stack||"op"!==e.base.type&&"operatorname"!==e.base.type||(e.base.parentIsSupSub=!0,s=!e.base.symbol,a=e.base.needsLeadingSpace);const i=e.base&&e.base.stack?[re(e.base.body[0],t)]:[re(e.base,t)],l=t.inSubOrSup();let c;if(e.sub&&i.push(re(e.sub,l)),e.sup&&i.push(re(e.sup,l)),o)c=r?"mover":"munder";else if(e.sub)if(e.sup){const r=e.base;c=r&&("op"===r.type&&r.limits||"multiscript"===r.type)&&(t.level===Re||r.alwaysHandleSupSub)||r&&"operatorname"===r.type&&r.alwaysHandleSupSub&&(t.level===Re||r.limits)?"munderover":"msubsup"}else{const r=e.base;c=r&&"op"===r.type&&r.limits&&(t.level===Re||r.alwaysHandleSupSub)||r&&"operatorname"===r.type&&r.alwaysHandleSupSub&&(r.limits||t.level===Re)?"munder":"msub"}else{const r=e.base;c=r&&"op"===r.type&&r.limits&&(t.level===Re||r.alwaysHandleSupSub)||r&&"operatorname"===r.type&&r.alwaysHandleSupSub&&(r.limits||t.level===Re)?"mover":"msup"}let m=new T.MathNode(c,i);if(s){const e=new T.MathNode("mo",[Y("⁡","text")]);if(a){const t=new T.MathNode("mspace");t.setAttribute("width","0.1667em"),m=T.newDocumentFragment([t,m,e])}else m=T.newDocumentFragment([m,e])}else Mt.test(c)&&(m=new T.MathNode("mrow",[m]));return m}});const Ot=["\\shortmid","\\nshortmid","\\shortparallel","\\nshortparallel","\\smallsetminus"];m({type:"atom",mathmlBuilder(e,t){const r=new T.MathNode("mo",[Y(e.text,e.mode)]);return"punct"===e.family?r.setAttribute("separator","true"):"open"===e.family||"close"===e.family?"open"===e.family?(r.setAttribute("form","prefix"),r.setAttribute("stretchy","false")):"close"===e.family&&(r.setAttribute("form","postfix"),r.setAttribute("stretchy","false")):"\\mid"===e.text?(r.setAttribute("lspace","0.22em"),r.setAttribute("rspace","0.22em"),r.setAttribute("stretchy","false")):Ot.includes(e.text)?r.setAttribute("mathsize","70%"):":"===e.text&&(r.attributes.lspace="0.2222em",r.attributes.rspace="0.2222em"),r}});const Ct={mathbf:"bold",mathrm:"normal",textit:"italic",mathit:"italic",mathnormal:"italic",mathbb:"double-struck",mathcal:"script",mathfrak:"fraktur",mathscr:"script",mathsf:"sans-serif",mathtt:"monospace",oldstylenums:"oldstylenums"},zt=function(e,t){if("texttt"===t.fontFamily)return"monospace";if("textsc"===t.fontFamily)return"normal";if("textsf"===t.fontFamily)return"textit"===t.fontShape&&"textbf"===t.fontWeight?"sans-serif-bold-italic":"textit"===t.fontShape?"sans-serif-italic":"textbf"===t.fontWeight?"sans-serif-bold":"sans-serif";if("textit"===t.fontShape&&"textbf"===t.fontWeight)return"bold-italic";if("textit"===t.fontShape)return"italic";if("textbf"===t.fontWeight)return"bold";const r=t.font;if(!r||"mathnormal"===r)return null;const n=e.mode;switch(r){case"mathit":case"greekItalic":return"italic";case"mathrm":{const t=e.text.codePointAt(0);return 9390,bold:e=>119743,italic:e=>119795,"bold-italic":e=>119847,script:e=>Et[e]||119899,"script-bold":e=>119951,fraktur:e=>It[e]||120003,"fraktur-bold":e=>120107,"double-struck":e=>Lt[e]||120055,"sans-serif":e=>120159,"sans-serif-bold":e=>120211,"sans-serif-italic":e=>120263,"sans-serif-bold-italic":e=>120380,monospace:e=>120367},lowerCaseLatin:{normal:e=>0,bold:e=>119737,italic:e=>"h"===e?8358:119789,"bold-italic":e=>119841,script:e=>Et[e]||119893,"script-bold":e=>119945,fraktur:e=>119997,"fraktur-bold":e=>120101,"double-struck":e=>120049,"sans-serif":e=>120153,"sans-serif-bold":e=>120205,"sans-serif-italic":e=>120257,"sans-serif-bold-italic":e=>120309,monospace:e=>120361},upperCaseGreek:{normal:e=>0,bold:e=>"∇"===e?111802:119575,italic:e=>"∇"===e?111860:119633,"bold-italic":e=>"∇"===e?111802:119575,script:e=>0,"script-bold":e=>0,fraktur:e=>0,"fraktur-bold":e=>0,"double-struck":e=>0,"sans-serif":e=>"∇"===e?111976:119749,"sans-serif-bold":e=>"∇"===e?111976:119749,"sans-serif-italic":e=>0,"sans-serif-bold-italic":e=>"∇"===e?112034:119807,monospace:e=>0},lowerCaseGreek:{normal:e=>0,bold:e=>119569,italic:e=>119627,"bold-italic":e=>"ϕ"===e?119678:119685,script:e=>0,"script-bold":e=>0,fraktur:e=>0,"fraktur-bold":e=>0,"double-struck":e=>0,"sans-serif":e=>119743,"sans-serif-bold":e=>119743,"sans-serif-italic":e=>0,"sans-serif-bold-italic":e=>119801,monospace:e=>0},varGreek:{normal:e=>0,bold:e=>$t[e]||-51,italic:e=>0,"bold-italic":e=>Ft[e]||58,script:e=>0,"script-bold":e=>0,fraktur:e=>0,"fraktur-bold":e=>0,"double-struck":e=>0,"sans-serif":e=>Gt[e]||116,"sans-serif-bold":e=>Gt[e]||116,"sans-serif-italic":e=>0,"sans-serif-bold-italic":e=>Dt[e]||174,monospace:e=>0},numeral:{normal:e=>0,bold:e=>120734,italic:e=>0,"bold-italic":e=>0,script:e=>0,"script-bold":e=>0,fraktur:e=>0,"fraktur-bold":e=>0,"double-struck":e=>120744,"sans-serif":e=>120754,"sans-serif-bold":e=>120764,"sans-serif-italic":e=>0,"sans-serif-bold-italic":e=>0,monospace:e=>120774}}),Rt=(e,t)=>{const r=e.codePointAt(0),n=64{const r=new T.MathNode("mn",[e]),n=new T.MathNode("mstyle",[r]);return n.style["font-style"]="italic",n.style["font-family"]="Cambria, 'Times New Roman', serif","bold-italic"===t&&(n.style["font-weight"]="bold"),n};m({type:"mathord",mathmlBuilder(e,t){const r=Y(e.text,e.mode,t),n=r.text.codePointAt(0),o=912Rt(e,s))).join("")),a=new T.MathNode("mn",[o])}else if("\\prime"===e.text)a=new T.MathNode("mo",[o]);else{const e=o.text;"italic"!==s&&(o.text=Rt(o.text,s)),a=new T.MathNode("mi",[o]),o.text===e&&_t.test(e)&&a.setAttribute("mathvariant","italic")}return a}});const Vt={"\\nobreak":"nobreak","\\allowbreak":"allowbreak"},Wt={" ":{},"\\ ":{},"~":{className:"nobreak"},"\\space":{},"\\nobreakspace":{className:"nobreak"}};m({type:"spacing",mathmlBuilder(t,r){let n;if(Object.prototype.hasOwnProperty.call(Wt,t.text))n=new T.MathNode("mtext",[new T.TextNode(" ")]);else{if(!Object.prototype.hasOwnProperty.call(Vt,t.text))throw new e(`Unknown type of space "${t.text}"`);n=new T.MathNode("mo"),"\\nobreak"===t.text&&n.setAttribute("linebreak","nobreak")}return n}}),m({type:"tag"});const Xt={"\\text":void 0,"\\textrm":"textrm","\\textsf":"textsf","\\texttt":"texttt","\\textnormal":"textrm","\\textsc":"textsc"},Zt={"\\textbf":"textbf","\\textmd":"textmd"},Jt={"\\textit":"textit","\\textup":"textup"};c({type:"text",names:["\\text","\\textrm","\\textsf","\\texttt","\\textnormal","\\textsc","\\textbf","\\textmd","\\textit","\\textup"],props:{numArgs:1,argTypes:["text"],allowedInArgument:!0,allowedInText:!0},handler({parser:e,funcName:t},r){const n=r[0];return{type:"text",mode:e.mode,body:p(n),font:t}},mathmlBuilder(e,t){const r=((e,t)=>{const r=e.font;return r?Xt[r]?t.withTextFontFamily(Xt[r]):Zt[r]?t.withTextFontWeight(Zt[r]):t.withTextFontShape(Jt[r]):t})(e,t),n=te(e.body,r);return s.consolidateText(n)}}),c({type:"tip",names:["\\mathtip"],props:{numArgs:2},handler:({parser:e},t)=>({type:"tip",mode:e.mode,body:t[0],tip:t[1]}),mathmlBuilder:(e,t)=>{const r=re(e.body,t),n=re(e.tip,t),o=new T.MathNode("maction",[r,n],["tml-tip"]);return o.setAttribute("actiontype","tooltip"),o}}),c({type:"tip",names:["\\texttip"],props:{numArgs:2,argTypes:["math","text"]},handler:({parser:e},t)=>({type:"tip",mode:e.mode,body:t[0],tip:t[1]}),mathmlBuilder:(e,t)=>{const r=re(e.body,t),n=re(e.tip,t);let o="";if("mtext"===n.type)o=n.children[0].text;else for(const e of n.children)o+=e.children[0].text;return r.setAttribute("title",o),r}}),m({type:"toggle",mathmlBuilder(e,t){const r=ee(e.body,t),n=new T.MathNode("maction",r,[],{cursor:"default"});return n.setAttribute("actiontype","toggle"),n}}),c({type:"underline",names:["\\underline"],props:{numArgs:1,allowedInText:!0},handler:({parser:e},t)=>({type:"underline",mode:e.mode,body:t[0]}),mathmlBuilder(e,t){const r=new T.MathNode("mo",[new T.TextNode("_")]);r.setAttribute("stretchy","true");const n=new T.MathNode("munder",[re(e.body,t),r]);return n.setAttribute("accentunder","true"),n}}),c({type:"verb",names:["\\verb"],props:{numArgs:0,allowedInText:!0},handler(t,r,n){throw new e("\\verb ended by end of line instead of matching delimiter")},mathmlBuilder(e,t){const r=new T.TextNode(Yt(e)),n=new T.MathNode("mtext",[r]);return n.setAttribute("mathvariant","monospace"),n}});const Yt=e=>e.body.replace(/ /g,e.star?"␣":" "),Kt=i;class Qt{constructor(e,t,r){this.lexer=e,this.start=t,this.end=r}static range(e,t){return t?e&&e.loc&&t.loc&&e.loc.lexer===t.loc.lexer?new Qt(e.loc.lexer,e.loc.start,t.loc.end):null:e&&e.loc}}class er{constructor(e,t){this.text=e,this.loc=t}range(e,t){return new er(t,Qt.range(this,e))}}const tr=new RegExp("[̀-ͯ]+$"),rr="([ \r\n\t]+)|\\\\(\n|[ \r\t]+\n?)[ \r\t]*|(number|[!-\\[\\]-‧‪-퟿豈-￿][̀-ͯ]*|[\ud800-\udbff][\udc00-\udfff][̀-ͯ]*|\\\\verb\\*([^]).*?\\4|\\\\verb([^*a-zA-Z]).*?\\5|(\\\\[a-zA-Z@]+)[ \r\n\t]*|\\\\[^\ud800-\udfff])";class nr{constructor(e,t){this.input=e,this.settings=t,this.tokenRegex=new RegExp(rr.replace("number|",t.strict?"":"\\d(?:[\\d,.]*\\d)?|"),"g"),this.catcodes={"%":14,"~":13}}setCatcode(e,t){this.catcodes[e]=t}lex(){const t=this.input,r=this.tokenRegex.lastIndex;if(r===t.length)return new er("EOF",new Qt(this,r,r));const n=this.tokenRegex.exec(t);if(null===n||n.index!==r)throw new e(`Unexpected character: '${t[r]}'`,new er(t[r],new Qt(this,r,r+1)));const o=n[6]||n[3]||(n[2]?"\\ ":" ");if(14===this.catcodes[o]){const r=t.indexOf("\n",this.tokenRegex.lastIndex);if(-1===r){if(this.tokenRegex.lastIndex=t.length,this.settings.strict)throw new e("% comment has no terminating newline; LaTeX would fail because of commenting the end of math mode")}else this.tokenRegex.lastIndex=r+1;return this.lex()}return new er(o,new Qt(this,r,this.tokenRegex.lastIndex))}}class or{constructor(e={},t={}){this.current=t,this.builtins=e,this.undefStack=[]}beginGroup(){this.undefStack.push({})}endGroup(){if(0===this.undefStack.length)throw new e("Unbalanced namespace destruction: attempt to pop global namespace; please report this as a bug");const t=this.undefStack.pop();for(const e in t)Object.prototype.hasOwnProperty.call(t,e)&&(void 0===t[e]?delete this.current[e]:this.current[e]=t[e])}has(e){return Object.prototype.hasOwnProperty.call(this.current,e)||Object.prototype.hasOwnProperty.call(this.builtins,e)}get(e){return Object.prototype.hasOwnProperty.call(this.current,e)?this.current[e]:this.builtins[e]}set(e,t){const r=this.undefStack[this.undefStack.length-1];r&&!Object.prototype.hasOwnProperty.call(r,e)&&(r[e]=this.current[e]),this.current[e]=t}}const sr=At;vt("\\noexpand",(function(e){const t=e.popToken();return e.isExpandable(t.text)&&(t.noexpand=!0,t.treatAsRelax=!0),{tokens:[t],numArgs:0}})),vt("\\expandafter",(function(e){const t=e.popToken();return e.expandOnce(!0),{tokens:[t],numArgs:0}})),vt("\\@firstoftwo",(function(e){return{tokens:e.consumeArgs(2)[0],numArgs:0}})),vt("\\@secondoftwo",(function(e){return{tokens:e.consumeArgs(2)[1],numArgs:0}})),vt("\\@ifnextchar",(function(e){const t=e.consumeArgs(3);e.consumeSpaces();const r=e.future();return 1===t[0].length&&t[0][0].text===r.text?{tokens:t[1],numArgs:0}:{tokens:t[2],numArgs:0}})),vt("\\@ifstar","\\@ifnextchar *{\\@firstoftwo{#1}}"),vt("\\TextOrMath",(function(e){const t=e.consumeArgs(2);return"text"===e.mode?{tokens:t[0],numArgs:0}:{tokens:t[1],numArgs:0}}));const ar={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,a:10,A:10,b:11,B:11,c:12,C:12,d:13,D:13,e:14,E:14,f:15,F:15},ir=e=>{const t=e.future().text;return"EOF"===t?[null,""]:[ar[t.charAt(0)],t]},lr=(e,t,r)=>{for(let n=1;n=r)throw new e(`Invalid base-${r} digit ${n.text}`);for(o=lr(o,a,r),[s,a]=ir(t);null!=s&&s":"\\dotsb","-":"\\dotsb","*":"\\dotsb",":":"\\dotsb","\\DOTSB":"\\dotsb","\\coprod":"\\dotsb","\\bigvee":"\\dotsb","\\bigwedge":"\\dotsb","\\biguplus":"\\dotsb","\\bigcap":"\\dotsb","\\bigcup":"\\dotsb","\\prod":"\\dotsb","\\sum":"\\dotsb","\\bigotimes":"\\dotsb","\\bigoplus":"\\dotsb","\\bigodot":"\\dotsb","\\bigsqcap":"\\dotsb","\\bigsqcup":"\\dotsb","\\And":"\\dotsb","\\longrightarrow":"\\dotsb","\\Longrightarrow":"\\dotsb","\\longleftarrow":"\\dotsb","\\Longleftarrow":"\\dotsb","\\longleftrightarrow":"\\dotsb","\\Longleftrightarrow":"\\dotsb","\\mapsto":"\\dotsb","\\longmapsto":"\\dotsb","\\hookrightarrow":"\\dotsb","\\doteq":"\\dotsb","\\mathbin":"\\dotsb","\\mathrel":"\\dotsb","\\relbar":"\\dotsb","\\Relbar":"\\dotsb","\\xrightarrow":"\\dotsb","\\xleftarrow":"\\dotsb","\\DOTSI":"\\dotsi","\\int":"\\dotsi","\\oint":"\\dotsi","\\iint":"\\dotsi","\\iiint":"\\dotsi","\\iiiint":"\\dotsi","\\idotsint":"\\dotsi","\\DOTSX":"\\dotsx"};vt("\\dots",(function(e){let t="\\dotso";const r=e.expandAfterFuture().text;return r in cr?t=cr[r]:("\\not"===r.slice(0,4)||r in M.math&&s.contains(["bin","rel"],M.math[r].group))&&(t="\\dotsb"),t}));const mr={")":!0,"]":!0,"\\rbrack":!0,"\\}":!0,"\\rbrace":!0,"\\rangle":!0,"\\rceil":!0,"\\rfloor":!0,"\\rgroup":!0,"\\rmoustache":!0,"\\right":!0,"\\bigr":!0,"\\biggr":!0,"\\Bigr":!0,"\\Biggr":!0,$:!0,";":!0,".":!0,",":!0};vt("\\dotso",(function(e){return e.future().text in mr?"\\ldots\\,":"\\ldots"})),vt("\\dotsc",(function(e){const t=e.future().text;return t in mr&&","!==t?"\\ldots\\,":"\\ldots"})),vt("\\cdots",(function(e){return e.future().text in mr?"\\@cdots\\,":"\\@cdots"})),vt("\\dotsb","\\cdots"),vt("\\dotsm","\\cdots"),vt("\\dotsi","\\!\\cdots"),vt("\\idotsint","\\dotsi"),vt("\\dotsx","\\ldots\\,"),vt("\\DOTSI","\\relax"),vt("\\DOTSB","\\relax"),vt("\\DOTSX","\\relax"),vt("\\tmspace","\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"),vt("\\,","{\\tmspace+{3mu}{.1667em}}"),vt("\\thinspace","\\,"),vt("\\>","\\mskip{4mu}"),vt("\\:","{\\tmspace+{4mu}{.2222em}}"),vt("\\medspace","\\:"),vt("\\;","{\\tmspace+{5mu}{.2777em}}"),vt("\\thickspace","\\;"),vt("\\!","{\\tmspace-{3mu}{.1667em}}"),vt("\\negthinspace","\\!"),vt("\\negmedspace","{\\tmspace-{4mu}{.2222em}}"),vt("\\negthickspace","{\\tmspace-{5mu}{.277em}}"),vt("\\enspace","\\kern.5em "),vt("\\enskip","\\hskip.5em\\relax"),vt("\\quad","\\hskip1em\\relax"),vt("\\qquad","\\hskip2em\\relax"),vt("\\tag","\\@ifstar\\tag@literal\\tag@paren"),vt("\\tag@paren","\\tag@literal{({#1})}"),vt("\\tag@literal",(t=>{if(t.macros.get("\\df@tag"))throw new e("Multiple \\tag");return"\\def\\df@tag{\\text{#1}}"})),vt("\\bmod","\\mathbin{\\text{mod}}"),vt("\\pod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"),vt("\\pmod","\\pod{{\\rm mod}\\mkern6mu#1}"),vt("\\mod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}{\\rm mod}\\,\\,#1"),vt("\\newline","\\\\\\relax"),vt("\\TeX","\\textrm{T}\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125em\\textrm{X}"),vt("\\LaTeX","\\textrm{L}\\kern-.35em\\raisebox{0.2em}{\\scriptstyle A}\\kern-.15em\\TeX"),vt("\\Temml","\\textrm{T}\\kern-0.2em\\lower{0.2em}\\textrm{E}\\kern-0.08em{\\textrm{M}\\kern-0.08em\\raise{0.2em}\\textrm{M}\\kern-0.08em\\textrm{L}}"),vt("\\hspace","\\@ifstar\\@hspacer\\@hspace"),vt("\\@hspace","\\hskip #1\\relax"),vt("\\@hspacer","\\rule{0pt}{0pt}\\hskip #1\\relax"),vt("\\colon",'\\mathpunct{\\char"3a}'),vt("\\prescript","\\pres@cript{_{#1}^{#2}}{}{#3}"),vt("\\ordinarycolon",'\\char"3a'),vt("\\vcentcolon","\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}}"),vt("\\coloneq",'\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"2212}'),vt("\\Coloneq",'\\mathrel{\\char"2237\\char"2212}'),vt("\\Eqqcolon",'\\mathrel{\\char"3d\\char"2237}'),vt("\\Eqcolon",'\\mathrel{\\char"2212\\char"2237}'),vt("\\colonapprox",'\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"2248}'),vt("\\Colonapprox",'\\mathrel{\\char"2237\\char"2248}'),vt("\\colonsim",'\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"223c}'),vt("\\Colonsim",'\\mathrel{\\raisebox{0.035em}{\\ordinarycolon}\\char"223c}'),vt("\\ratio","\\vcentcolon"),vt("\\coloncolon","\\dblcolon"),vt("\\colonequals","\\coloneqq"),vt("\\coloncolonequals","\\Coloneqq"),vt("\\equalscolon","\\eqqcolon"),vt("\\equalscoloncolon","\\Eqqcolon"),vt("\\colonminus","\\coloneq"),vt("\\coloncolonminus","\\Coloneq"),vt("\\minuscolon","\\eqcolon"),vt("\\minuscoloncolon","\\Eqcolon"),vt("\\coloncolonapprox","\\Colonapprox"),vt("\\coloncolonsim","\\Colonsim"),vt("\\notni","\\mathrel{\\char`∌}"),vt("\\limsup","\\DOTSB\\operatorname*{lim\\,sup}"),vt("\\liminf","\\DOTSB\\operatorname*{lim\\,inf}"),vt("\\injlim","\\DOTSB\\operatorname*{inj\\,lim}"),vt("\\projlim","\\DOTSB\\operatorname*{proj\\,lim}"),vt("\\varlimsup","\\DOTSB\\operatorname*{\\overline{\\text{lim}}}"),vt("\\varliminf","\\DOTSB\\operatorname*{\\underline{\\text{lim}}}"),vt("\\varinjlim","\\DOTSB\\operatorname*{\\underrightarrow{\\text{lim}}}"),vt("\\varprojlim","\\DOTSB\\operatorname*{\\underleftarrow{\\text{lim}}}"),vt("\\centerdot","{\\medspace\\rule{0.167em}{0.189em}\\medspace}"),vt("\\argmin","\\DOTSB\\operatorname*{arg\\,min}"),vt("\\argmax","\\DOTSB\\operatorname*{arg\\,max}"),vt("\\plim","\\DOTSB\\operatorname*{plim}"),vt("\\bra","\\mathinner{\\langle{#1}|}"),vt("\\ket","\\mathinner{|{#1}\\rangle}"),vt("\\braket","\\mathinner{\\langle{#1}\\rangle}"),vt("\\Bra","\\left\\langle#1\\right|"),vt("\\Ket","\\left|#1\\right\\rangle");const ur=e=>t=>{const r=t.consumeArg().tokens,n=t.consumeArg().tokens,o=t.consumeArg().tokens,s=t.consumeArg().tokens,a=t.macros.get("|"),i=t.macros.get("\\|");t.macros.beginGroup();const l=t=>r=>{e&&(r.macros.set("|",a),o.length&&r.macros.set("\\|",i));let s=t;if(!t&&o.length){"|"===r.future().text&&(r.popToken(),s=!0)}return{tokens:s?o:n,numArgs:0}};t.macros.set("|",l(!1)),o.length&&t.macros.set("\\|",l(!0));const c=t.consumeArg().tokens,m=t.expandTokens([...s,...c,...r]);return t.macros.endGroup(),{tokens:m.reverse(),numArgs:0}};vt("\\bra@ket",ur(!1)),vt("\\bra@set",ur(!0)),vt("\\Braket","\\bra@ket{\\left\\langle}{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"),vt("\\Set","\\bra@set{\\left\\{\\:}{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"),vt("\\set","\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"),vt("\\angln","{\\angl n}"),vt("\\odv","\\@ifstar\\odv@next\\odv@numerator"),vt("\\odv@numerator","\\frac{\\mathrm{d}#1}{\\mathrm{d}#2}"),vt("\\odv@next","\\frac{\\mathrm{d}}{\\mathrm{d}#2}#1"),vt("\\pdv","\\@ifstar\\pdv@next\\pdv@numerator");const pr=e=>{const t=e[0][0].text,r=(e=>{let t="";for(let r=e.length-1;r>-1;r--)t+=e[r].text;return t})(e[1]).split(","),n=String(r.length),o="1"===n?"\\partial":`\\partial^${n}`;let s="";return r.map((e=>{s+="\\partial "+e.trim()+"\\,"})),[t,o,s.replace(/\\,$/,"")]};vt("\\pdv@numerator",(function(e){const[t,r,n]=pr(e.consumeArgs(2));return`\\frac{${r} ${t}}{${n}}`})),vt("\\pdv@next",(function(e){const[t,r,n]=pr(e.consumeArgs(2));return`\\frac{${r}}{${n}} ${t}`})),vt("\\upalpha","\\up@greek{\\alpha}"),vt("\\upbeta","\\up@greek{\\beta}"),vt("\\upgamma","\\up@greek{\\gamma}"),vt("\\updelta","\\up@greek{\\delta}"),vt("\\upepsilon","\\up@greek{\\epsilon}"),vt("\\upzeta","\\up@greek{\\zeta}"),vt("\\upeta","\\up@greek{\\eta}"),vt("\\uptheta","\\up@greek{\\theta}"),vt("\\upiota","\\up@greek{\\iota}"),vt("\\upkappa","\\up@greek{\\kappa}"),vt("\\uplambda","\\up@greek{\\lambda}"),vt("\\upmu","\\up@greek{\\mu}"),vt("\\upnu","\\up@greek{\\nu}"),vt("\\upxi","\\up@greek{\\xi}"),vt("\\upomicron","\\up@greek{\\omicron}"),vt("\\uppi","\\up@greek{\\pi}"),vt("\\upalpha","\\up@greek{\\alpha}"),vt("\\uprho","\\up@greek{\\rho}"),vt("\\upsigma","\\up@greek{\\sigma}"),vt("\\uptau","\\up@greek{\\tau}"),vt("\\upupsilon","\\up@greek{\\upsilon}"),vt("\\upphi","\\up@greek{\\phi}"),vt("\\upchi","\\up@greek{\\chi}"),vt("\\uppsi","\\up@greek{\\psi}"),vt("\\upomega","\\up@greek{\\omega}"),vt("\\invamp",'\\mathbin{\\char"214b}'),vt("\\parr",'\\mathbin{\\char"214b}'),vt("\\with",'\\mathbin{\\char"26}'),vt("\\multimapinv",'\\mathrel{\\char"27dc}'),vt("\\multimapboth",'\\mathrel{\\char"29df}'),vt("\\scoh",'{\\mkern5mu\\char"2322\\mkern5mu}'),vt("\\sincoh",'{\\mkern5mu\\char"2323\\mkern5mu}'),vt("\\coh",'{\\mkern5mu\\rule{}{0.7em}\\mathrlap{\\smash{\\raise2mu{\\char"2322}}}\n{\\smash{\\lower4mu{\\char"2323}}}\\mkern5mu}'),vt("\\incoh",'{\\mkern5mu\\rule{}{0.7em}\\mathrlap{\\smash{\\raise2mu{\\char"2323}}}\n{\\smash{\\lower4mu{\\char"2322}}}\\mkern5mu}'),vt("\\standardstate","\\text{\\tiny\\char`⦵}");const dr={"^":!0,_:!0,"\\limits":!0,"\\nolimits":!0};class hr{constructor(e,t,r){this.settings=t,this.expansionCount=0,this.feed(e),this.macros=new or(sr,t.macros),this.mode=r,this.stack=[]}feed(e){this.lexer=new nr(e,this.settings)}switchMode(e){this.mode=e}beginGroup(){this.macros.beginGroup()}endGroup(){this.macros.endGroup()}future(){return 0===this.stack.length&&this.pushToken(this.lexer.lex()),this.stack[this.stack.length-1]}popToken(){return this.future(),this.stack.pop()}pushToken(e){this.stack.push(e)}pushTokens(e){this.stack.push(...e)}scanArgument(e){let t,r,n;if(e){if(this.consumeSpaces(),"["!==this.future().text)return null;t=this.popToken(),({tokens:n,end:r}=this.consumeArg(["]"]))}else({tokens:n,start:t,end:r}=this.consumeArg());return this.pushToken(new er("EOF",r.loc)),this.pushTokens(n),t.range(r,"")}consumeSpaces(){for(;;){if(" "!==this.future().text)break;this.stack.pop()}}consumeArg(t){const r=[],n=t&&t.length>0;n||this.consumeSpaces();const o=this.future();let s,a=0,i=0;do{if(s=this.popToken(),r.push(s),"{"===s.text)++a;else if("}"===s.text){if(--a,-1===a)throw new e("Extra }",s)}else if("EOF"===s.text)throw new e("Unexpected end of input in a macro argument, expected '"+(t&&n?t[i]:"}")+"'",s);if(t&&n)if((0===a||1===a&&"{"===t[i])&&s.text===t[i]){if(++i,i===t.length){r.splice(-i,i);break}}else i=0}while(0!==a||n);return"{"===o.text&&"}"===r[r.length-1].text&&(r.pop(),r.shift()),r.reverse(),{tokens:r,start:o,end:s}}consumeArgs(t,r){if(r){if(r.length!==t+1)throw new e("The length of delimiters doesn't match the number of args!");const n=r[0];for(let t=0;tthis.settings.maxExpand)throw new e("Too many expansions: infinite loop or need to increase maxExpand setting");let s=o.tokens;const a=this.consumeArgs(o.numArgs,o.delimiters);if(o.numArgs){s=s.slice();for(let t=s.length-1;t>=0;--t){let r=s[t];if("#"===r.text){if(0===t)throw new e("Incomplete placeholder at end of macro body",r);if(r=s[--t],"#"===r.text)s.splice(t+1,1);else{if(!/^[1-9]$/.test(r.text))throw new e("Not a valid argument number",r);s.splice(t,2,...a[+r.text-1])}}}}return this.pushTokens(s),s}expandAfterFuture(){return this.expandOnce(),this.future()}expandNextToken(){for(;;){const e=this.expandOnce();if(e instanceof er)return e.treatAsRelax&&(e.text="\\relax"),this.stack.pop()}throw new Error}expandMacro(e){return this.macros.has(e)?this.expandTokens([new er(e)]):void 0}expandTokens(e){const t=[],r=this.stack.length;for(this.pushTokens(e);this.stack.length>r;){const e=this.expandOnce(!0);e instanceof er&&(e.treatAsRelax&&(e.noexpand=!1,e.treatAsRelax=!1),t.push(this.stack.pop()))}return t}expandMacroAsText(e){const t=this.expandMacro(e);return t?t.map((e=>e.text)).join(""):t}_getExpansion(e){const t=this.macros.get(e);if(null==t)return t;if(1===e.length){const t=this.lexer.catcodes[e];if(null!=t&&13!==t)return}const r="function"==typeof t?t(this):t;if("string"==typeof r){let e=0;if(-1!==r.indexOf("#")){const t=r.replace(/##/g,"");for(;-1!==t.indexOf("#"+(e+1));)++e}const t=new nr(r,this.settings),n=[];let o=t.lex();for(;"EOF"!==o.text;)n.push(o),o=t.lex();n.reverse();return{tokens:n,numArgs:e}}return r}isDefined(e){return this.macros.has(e)||Object.prototype.hasOwnProperty.call(Kt,e)||Object.prototype.hasOwnProperty.call(M.math,e)||Object.prototype.hasOwnProperty.call(M.text,e)||Object.prototype.hasOwnProperty.call(dr,e)}isExpandable(e){const t=this.macros.get(e);return null!=t?"string"==typeof t||"function"==typeof t||!t.unexpandable:Object.prototype.hasOwnProperty.call(Kt,e)&&!Kt[e].primitive}}const gr=[];[{name:"latin",blocks:[[256,591],[768,879]]},{name:"cyrillic",blocks:[[1024,1279]]},{name:"armenian",blocks:[[1328,1423]]},{name:"brahmic",blocks:[[2304,4255]]},{name:"georgian",blocks:[[4256,4351]]},{name:"cjk",blocks:[[12288,12543],[19968,40879],[65280,65376]]},{name:"hangul",blocks:[[44032,55215]]}].forEach((e=>e.blocks.forEach((e=>gr.push(...e)))));const fr=/^[₊₋₌₍₎₀₁₂₃₄₅₆₇₈₉ₐₑₕᵢⱼₖₗₘₙₒₚᵣₛₜᵤᵥₓᵦᵧᵨᵩᵪ]/,br=Object.freeze({"₊":"+","₋":"-","₌":"=","₍":"(","₎":")","₀":"0","₁":"1","₂":"2","₃":"3","₄":"4","₅":"5","₆":"6","₇":"7","₈":"8","₉":"9","ₐ":"a","ₑ":"e","ₕ":"h","ᵢ":"i","ⱼ":"j","ₖ":"k","ₗ":"l","ₘ":"m","ₙ":"n","ₒ":"o","ₚ":"p","ᵣ":"r","ₛ":"s","ₜ":"t","ᵤ":"u","ᵥ":"v","ₓ":"x","ᵦ":"β","ᵧ":"γ","ᵨ":"ρ","ᵩ":"ϕ","ᵪ":"χ","⁺":"+","⁻":"-","⁼":"=","⁽":"(","⁾":")","⁰":"0","¹":"1","²":"2","³":"3","⁴":"4","⁵":"5","⁶":"6","⁷":"7","⁸":"8","⁹":"9","ᴬ":"A","ᴮ":"B","ᴰ":"D","ᴱ":"E","ᴳ":"G","ᴴ":"H","ᴵ":"I","ᴶ":"J","ᴷ":"K","ᴸ":"L","ᴹ":"M","ᴺ":"N","ᴼ":"O","ᴾ":"P","ᴿ":"R","ᵀ":"T","ᵁ":"U","ⱽ":"V","ᵂ":"W","ᵃ":"a","ᵇ":"b","ᶜ":"c","ᵈ":"d","ᵉ":"e","ᶠ":"f","ᵍ":"g","ʰ":"h","ⁱ":"i","ʲ":"j","ᵏ":"k","ˡ":"l","ᵐ":"m","ⁿ":"n","ᵒ":"o","ᵖ":"p","ʳ":"r","ˢ":"s","ᵗ":"t","ᵘ":"u","ᵛ":"v","ʷ":"w","ˣ":"x","ʸ":"y","ᶻ":"z","ᵝ":"β","ᵞ":"γ","ᵟ":"δ","ᵠ":"ϕ","ᵡ":"χ","ᶿ":"θ"});var yr={"́":{text:"\\'",math:"\\acute"},"̀":{text:"\\`",math:"\\grave"},"̈":{text:'\\"',math:"\\ddot"},"̃":{text:"\\~",math:"\\tilde"},"̄":{text:"\\=",math:"\\bar"},"̆":{text:"\\u",math:"\\breve"},"̌":{text:"\\v",math:"\\check"},"̂":{text:"\\^",math:"\\hat"},"̇":{text:"\\.",math:"\\dot"},"̊":{text:"\\r",math:"\\mathring"},"̋":{text:"\\H"},"̧":{text:"\\c"}},wr={"á":"á","à":"à","ä":"ä","ǟ":"ǟ","ã":"ã","ā":"ā","ă":"ă","ắ":"ắ","ằ":"ằ","ẵ":"ẵ","ǎ":"ǎ","â":"â","ấ":"ấ","ầ":"ầ","ẫ":"ẫ","ȧ":"ȧ","ǡ":"ǡ","å":"å","ǻ":"ǻ","ḃ":"ḃ","ć":"ć","č":"č","ĉ":"ĉ","ċ":"ċ","ď":"ď","ḋ":"ḋ","é":"é","è":"è","ë":"ë","ẽ":"ẽ","ē":"ē","ḗ":"ḗ","ḕ":"ḕ","ĕ":"ĕ","ě":"ě","ê":"ê","ế":"ế","ề":"ề","ễ":"ễ","ė":"ė","ḟ":"ḟ","ǵ":"ǵ","ḡ":"ḡ","ğ":"ğ","ǧ":"ǧ","ĝ":"ĝ","ġ":"ġ","ḧ":"ḧ","ȟ":"ȟ","ĥ":"ĥ","ḣ":"ḣ","í":"í","ì":"ì","ï":"ï","ḯ":"ḯ","ĩ":"ĩ","ī":"ī","ĭ":"ĭ","ǐ":"ǐ","î":"î","ǰ":"ǰ","ĵ":"ĵ","ḱ":"ḱ","ǩ":"ǩ","ĺ":"ĺ","ľ":"ľ","ḿ":"ḿ","ṁ":"ṁ","ń":"ń","ǹ":"ǹ","ñ":"ñ","ň":"ň","ṅ":"ṅ","ó":"ó","ò":"ò","ö":"ö","ȫ":"ȫ","õ":"õ","ṍ":"ṍ","ṏ":"ṏ","ȭ":"ȭ","ō":"ō","ṓ":"ṓ","ṑ":"ṑ","ŏ":"ŏ","ǒ":"ǒ","ô":"ô","ố":"ố","ồ":"ồ","ỗ":"ỗ","ȯ":"ȯ","ȱ":"ȱ","ő":"ő","ṕ":"ṕ","ṗ":"ṗ","ŕ":"ŕ","ř":"ř","ṙ":"ṙ","ś":"ś","ṥ":"ṥ","š":"š","ṧ":"ṧ","ŝ":"ŝ","ṡ":"ṡ","ẗ":"ẗ","ť":"ť","ṫ":"ṫ","ú":"ú","ù":"ù","ü":"ü","ǘ":"ǘ","ǜ":"ǜ","ǖ":"ǖ","ǚ":"ǚ","ũ":"ũ","ṹ":"ṹ","ū":"ū","ṻ":"ṻ","ŭ":"ŭ","ǔ":"ǔ","û":"û","ů":"ů","ű":"ű","ṽ":"ṽ","ẃ":"ẃ","ẁ":"ẁ","ẅ":"ẅ","ŵ":"ŵ","ẇ":"ẇ","ẘ":"ẘ","ẍ":"ẍ","ẋ":"ẋ","ý":"ý","ỳ":"ỳ","ÿ":"ÿ","ỹ":"ỹ","ȳ":"ȳ","ŷ":"ŷ","ẏ":"ẏ","ẙ":"ẙ","ź":"ź","ž":"ž","ẑ":"ẑ","ż":"ż","Á":"Á","À":"À","Ä":"Ä","Ǟ":"Ǟ","Ã":"Ã","Ā":"Ā","Ă":"Ă","Ắ":"Ắ","Ằ":"Ằ","Ẵ":"Ẵ","Ǎ":"Ǎ","Â":"Â","Ấ":"Ấ","Ầ":"Ầ","Ẫ":"Ẫ","Ȧ":"Ȧ","Ǡ":"Ǡ","Å":"Å","Ǻ":"Ǻ","Ḃ":"Ḃ","Ć":"Ć","Č":"Č","Ĉ":"Ĉ","Ċ":"Ċ","Ď":"Ď","Ḋ":"Ḋ","É":"É","È":"È","Ë":"Ë","Ẽ":"Ẽ","Ē":"Ē","Ḗ":"Ḗ","Ḕ":"Ḕ","Ĕ":"Ĕ","Ě":"Ě","Ê":"Ê","Ế":"Ế","Ề":"Ề","Ễ":"Ễ","Ė":"Ė","Ḟ":"Ḟ","Ǵ":"Ǵ","Ḡ":"Ḡ","Ğ":"Ğ","Ǧ":"Ǧ","Ĝ":"Ĝ","Ġ":"Ġ","Ḧ":"Ḧ","Ȟ":"Ȟ","Ĥ":"Ĥ","Ḣ":"Ḣ","Í":"Í","Ì":"Ì","Ï":"Ï","Ḯ":"Ḯ","Ĩ":"Ĩ","Ī":"Ī","Ĭ":"Ĭ","Ǐ":"Ǐ","Î":"Î","İ":"İ","Ĵ":"Ĵ","Ḱ":"Ḱ","Ǩ":"Ǩ","Ĺ":"Ĺ","Ľ":"Ľ","Ḿ":"Ḿ","Ṁ":"Ṁ","Ń":"Ń","Ǹ":"Ǹ","Ñ":"Ñ","Ň":"Ň","Ṅ":"Ṅ","Ó":"Ó","Ò":"Ò","Ö":"Ö","Ȫ":"Ȫ","Õ":"Õ","Ṍ":"Ṍ","Ṏ":"Ṏ","Ȭ":"Ȭ","Ō":"Ō","Ṓ":"Ṓ","Ṑ":"Ṑ","Ŏ":"Ŏ","Ǒ":"Ǒ","Ô":"Ô","Ố":"Ố","Ồ":"Ồ","Ỗ":"Ỗ","Ȯ":"Ȯ","Ȱ":"Ȱ","Ő":"Ő","Ṕ":"Ṕ","Ṗ":"Ṗ","Ŕ":"Ŕ","Ř":"Ř","Ṙ":"Ṙ","Ś":"Ś","Ṥ":"Ṥ","Š":"Š","Ṧ":"Ṧ","Ŝ":"Ŝ","Ṡ":"Ṡ","Ť":"Ť","Ṫ":"Ṫ","Ú":"Ú","Ù":"Ù","Ü":"Ü","Ǘ":"Ǘ","Ǜ":"Ǜ","Ǖ":"Ǖ","Ǚ":"Ǚ","Ũ":"Ũ","Ṹ":"Ṹ","Ū":"Ū","Ṻ":"Ṻ","Ŭ":"Ŭ","Ǔ":"Ǔ","Û":"Û","Ů":"Ů","Ű":"Ű","Ṽ":"Ṽ","Ẃ":"Ẃ","Ẁ":"Ẁ","Ẅ":"Ẅ","Ŵ":"Ŵ","Ẇ":"Ẇ","Ẍ":"Ẍ","Ẋ":"Ẋ","Ý":"Ý","Ỳ":"Ỳ","Ÿ":"Ÿ","Ỹ":"Ỹ","Ȳ":"Ȳ","Ŷ":"Ŷ","Ẏ":"Ẏ","Ź":"Ź","Ž":"Ž","Ẑ":"Ẑ","Ż":"Ż","ά":"ά","ὰ":"ὰ","ᾱ":"ᾱ","ᾰ":"ᾰ","έ":"έ","ὲ":"ὲ","ή":"ή","ὴ":"ὴ","ί":"ί","ὶ":"ὶ","ϊ":"ϊ","ΐ":"ΐ","ῒ":"ῒ","ῑ":"ῑ","ῐ":"ῐ","ό":"ό","ὸ":"ὸ","ύ":"ύ","ὺ":"ὺ","ϋ":"ϋ","ΰ":"ΰ","ῢ":"ῢ","ῡ":"ῡ","ῠ":"ῠ","ώ":"ώ","ὼ":"ὼ","Ύ":"Ύ","Ὺ":"Ὺ","Ϋ":"Ϋ","Ῡ":"Ῡ","Ῠ":"Ῠ","Ώ":"Ώ","Ὼ":"Ὼ"};const xr=/^\d(?:[\d,.]*\d)?$/;class kr{constructor(e,t,r=!1){this.mode="math",this.gullet=new hr(e,t,this.mode),this.settings=t,this.isPreamble=r,this.leftrightDepth=0,this.prevAtomType=""}expect(t,r=!0){if(this.fetch().text!==t)throw new e(`Expected '${t}', got '${this.fetch().text}'`,this.fetch());r&&this.consume()}consume(){this.nextToken=null}fetch(){return null==this.nextToken&&(this.nextToken=this.gullet.expandNextToken()),this.nextToken}switchMode(e){this.mode=e,this.gullet.switchMode(e)}parse(){this.gullet.beginGroup(),this.settings.colorIsTextColor&&this.gullet.macros.set("\\color","\\textcolor");const e=this.parseExpression(!1);if(this.expect("EOF"),this.isPreamble){const e=Object.create(null);return Object.entries(this.gullet.macros.current).forEach((([t,r])=>{e[t]=r})),this.gullet.endGroup(),e}const t=this.gullet.macros.get("\\df@tag");return this.gullet.endGroup(),t&&(this.gullet.macros.current["\\df@tag"]=t),e}static get endOfExpression(){return["}","\\endgroup","\\end","\\right","\\endtoggle","&"]}parseExpression(e,t){const r=[];for(;;){"math"===this.mode&&this.consumeSpaces();const n=this.fetch();if(-1!==kr.endOfExpression.indexOf(n.text))break;if(t&&n.text===t)break;if(e&&Kt[n.text]&&Kt[n.text].infix)break;const o=this.parseAtom(t);if(!o)break;"internal"!==o.type&&(r.push(o),this.prevAtomType="atom"===o.type?o.family:o.type)}return"text"===this.mode&&this.formLigatures(r),this.handleInfixNodes(r)}handleInfixNodes(t){let r,n=-1;for(let o=0;o=128))return null;if(this.settings.strict){if(!function(e){for(let t=0;t=gr[t]&&e<=gr[t+1])return!0;return!1}(r.charCodeAt(0)))throw new e(`Unrecognized Unicode character "${r[0]}" (${r.charCodeAt(0)})`,t);if("math"===this.mode)throw new e(`Unicode text character "${r[0]}" used in math mode`,t)}o={type:"textord",mode:"text",loc:Qt.range(t),text:r}}if(this.consume(),n)for(let r=0;r0&&o[0].type&&"array"===o[0].type&&o[0].addEqnNum)&&n.gullet.macros.get("\\df@tag")){if(!r.displayMode)throw new e("\\tag works only in display mode");n.gullet.feed("\\df@tag"),o=[{type:"tag",mode:"text",body:o,tag:n.parse()}]}return o},vr=[2,2,3,3];class Tr{constructor(e){this.level=e.level,this.color=e.color,this.font=e.font||"",this.fontFamily=e.fontFamily||"",this.fontSize=e.fontSize||1,this.fontWeight=e.fontWeight||"",this.fontShape=e.fontShape||"",this.maxSize=e.maxSize}extend(e){const t={level:this.level,color:this.color,font:this.font,fontFamily:this.fontFamily,fontSize:this.fontSize,fontWeight:this.fontWeight,fontShape:this.fontShape,maxSize:this.maxSize};for(const r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return new Tr(t)}withLevel(e){return this.extend({level:e})}incrementLevel(){return this.extend({level:Math.min(this.level+1,3)})}inSubOrSup(){return this.extend({level:vr[this.level]})}withColor(e){return this.extend({color:e})}withFont(e){return this.extend({font:e})}withTextFontFamily(e){return this.extend({fontFamily:e,font:""})}withFontSize(e){return this.extend({fontSize:e})}withTextFontWeight(e){return this.extend({fontWeight:e,font:""})}withTextFontShape(e){return this.extend({fontShape:e,font:""})}getColor(){return this.color}}let Nr=function(e,t,r){t.textContent="";const n=Sr(e,r);r.elementIsMath?(t.textContent="",n.children.forEach((e=>{t.appendChild(e.toNode())}))):t.appendChild(n.toNode())};"undefined"!=typeof document&&"CSS1Compat"!==document.compatMode&&("undefined"!=typeof console&&console.warn("Warning: Temml doesn't work in quirks mode. Make sure your website has a suitable doctype."),Nr=function(){throw new e("Temml doesn't work in quirks mode.")});const Sr=function(t,r){const n=new a(r);try{const e=Ar(t,n);return oe(e,t,new Tr({level:n.displayMode?Re:je,maxSize:n.maxSize}),n)}catch(r){return function(t,r,n){if(n.throwOnError||!(t instanceof e))throw t;const o=new y(["temml-error"],[new w(r+"\n"+t.toString())]);return o.style.color=n.errorColor,o.style.whiteSpace="pre-line",o}(r,t,n)}};return{version:"0.6.9",render:Nr,renderToString:function(e,t){return Sr(e,t).toMarkup()},postProcess:function(e){const t={};let r=0;const n=e.getElementsByClassName("tml-tageqn");for(const e of n){const n=e.getElementsByClassName("tml-eqn");n.length>0&&(r+=1,n[0].id="tml-eqn-"+r);const o=e.getElementsByClassName("tml-label");if(0!==o.length)if(n.length>0)t[o[0].id]=String(r);else{const r=e.getElementsByClassName("tml-tag");r.length>0&&(t[o[0].id]=r[0].textContent)}}[...e.getElementsByClassName("tml-ref")].forEach((e=>{let r=t[e.getAttribute("href").slice(1)];-1===e.className.indexOf("tml-eqref")&&(r=r.replace(/^\(/,""),r=r.replace(/\($/,"")),"("!==r.charAt(0)&&(r="("+r),")"!==r.slice(-1)&&(r+=")"),e.textContent=r}))},ParseError:e,definePreamble:function(e,t){const r=new a(t);if(r.macros={},!("string"==typeof e||e instanceof String))throw new TypeError("Temml can only parse string typed expression");const n=new kr(e,r,!0);delete n.gullet.macros.current["\\df@tag"];return n.parse()},__parse:function(e,t){const r=new a(t);return Ar(e,r)},__renderToMathMLTree:Sr,__defineSymbol:O,__defineMacro:vt}}(); \ No newline at end of file diff --git a/site/assets/texvc.js b/site/assets/texvc.js deleted file mode 100644 index ddd5b1aa..00000000 --- a/site/assets/texvc.js +++ /dev/null @@ -1,61 +0,0 @@ -/* eslint-disable no-undef */ - -////////////////////////////////////////////////////////////////////// -// texvc.sty - -// The texvc package contains macros available in mediawiki pages. -// We omit the functions deprecated at -// https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax - -// We also omit texvc's \O, which conflicts with \text{\O} - -temml.__defineMacro("\\darr", "\\downarrow"); -temml.__defineMacro("\\dArr", "\\Downarrow"); -temml.__defineMacro("\\Darr", "\\Downarrow"); -temml.__defineMacro("\\lang", "\\langle"); -temml.__defineMacro("\\rang", "\\rangle"); -temml.__defineMacro("\\uarr", "\\uparrow"); -temml.__defineMacro("\\uArr", "\\Uparrow"); -temml.__defineMacro("\\Uarr", "\\Uparrow"); -temml.__defineMacro("\\N", "\\mathbb{N}"); -temml.__defineMacro("\\R", "\\mathbb{R}"); -temml.__defineMacro("\\Z", "\\mathbb{Z}"); -temml.__defineMacro("\\alef", "\\aleph"); -temml.__defineMacro("\\alefsym", "\\aleph"); -temml.__defineMacro("\\bull", "\\bullet"); -temml.__defineMacro("\\clubs", "\\clubsuit"); -temml.__defineMacro("\\cnums", "\\mathbb{C}"); -temml.__defineMacro("\\Complex", "\\mathbb{C}"); -temml.__defineMacro("\\Dagger", "\\ddagger"); -temml.__defineMacro("\\diamonds", "\\diamondsuit"); -temml.__defineMacro("\\empty", "\\emptyset"); -temml.__defineMacro("\\exist", "\\exists"); -temml.__defineMacro("\\harr", "\\leftrightarrow"); -temml.__defineMacro("\\hArr", "\\Leftrightarrow"); -temml.__defineMacro("\\Harr", "\\Leftrightarrow"); -temml.__defineMacro("\\hearts", "\\heartsuit"); -temml.__defineMacro("\\image", "\\Im"); -temml.__defineMacro("\\infin", "\\infty"); -temml.__defineMacro("\\isin", "\\in"); -temml.__defineMacro("\\larr", "\\leftarrow"); -temml.__defineMacro("\\lArr", "\\Leftarrow"); -temml.__defineMacro("\\Larr", "\\Leftarrow"); -temml.__defineMacro("\\lrarr", "\\leftrightarrow"); -temml.__defineMacro("\\lrArr", "\\Leftrightarrow"); -temml.__defineMacro("\\Lrarr", "\\Leftrightarrow"); -temml.__defineMacro("\\natnums", "\\mathbb{N}"); -temml.__defineMacro("\\plusmn", "\\pm"); -temml.__defineMacro("\\rarr", "\\rightarrow"); -temml.__defineMacro("\\rArr", "\\Rightarrow"); -temml.__defineMacro("\\Rarr", "\\Rightarrow"); -temml.__defineMacro("\\real", "\\Re"); -temml.__defineMacro("\\reals", "\\mathbb{R}"); -temml.__defineMacro("\\Reals", "\\mathbb{R}"); -temml.__defineMacro("\\sdot", "\\cdot"); -temml.__defineMacro("\\sect", "\\S"); -temml.__defineMacro("\\spades", "\\spadesuit"); -temml.__defineMacro("\\sub", "\\subset"); -temml.__defineMacro("\\sube", "\\subseteq"); -temml.__defineMacro("\\supe", "\\supseteq"); -temml.__defineMacro("\\thetasym", "\\vartheta"); -temml.__defineMacro("\\weierp", "\\wp"); diff --git a/site/assets/xits-math.woff2 b/site/assets/xits-math.woff2 deleted file mode 100644 index 595e92633952c20d86c3ba4f794fed1b79549109..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 293336 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