├── LICENSE ├── README.md ├── dist ├── example.html ├── example.md.html ├── markdeep-1.11.js ├── unicodemathml-integration.js ├── unicodemathml-parser.js └── unicodemathml.js ├── docs ├── MathML Intent Attribute.docx ├── MathML Intent Attribute.pdf ├── Unicode Plain Text Encoding of Mathematics Version 3.2.docx ├── doersing-unicodemath-to-mathml.pdf ├── readme-images │ ├── 1-hero.png │ ├── 2-example.png │ ├── 3-examples.png │ ├── 4-stars.png │ ├── 5-additions.png │ ├── 6-playground.jpg │ └── 7-tooltips.gif └── sargent-unicodemathml-tech-note.pdf ├── lib ├── markdeep-1.11-orig.js ├── markdeep-1.11.js └── peg-0.10.0.min.js ├── playground ├── CopyHtmlToPlainText.html ├── README.md ├── assets │ ├── TeX.js │ ├── braille.js │ ├── charinfo.js │ ├── dictation.js │ ├── lib │ │ ├── jquery.min.js │ │ ├── latinmodern │ │ │ └── 1.959 │ │ │ │ ├── GUST-FONT-LICENSE.txt │ │ │ │ ├── otf │ │ │ │ └── latinmodern-math.otf │ │ │ │ └── webfont.css │ │ └── mathjax │ │ │ └── 3 │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ └── mml-svg.js │ ├── playground.css │ ├── playground.js │ └── speech.js ├── favicon.ico ├── help-images │ ├── Autobuildup5.mp4 │ ├── CodePointHover.png │ ├── OperatorHover.png │ ├── autocl.png │ ├── autocllong.png │ └── intentbox.png ├── help.html ├── help.md ├── index.html └── jquery.toc.js ├── src ├── integration │ ├── example.html │ ├── example.md.html │ └── unicodemathml-integration.js ├── unicodemathml-parser.pegjs └── unicodemathml.js ├── test ├── Dictation.html ├── MmlToUM.html ├── test.js └── testmml.js └── utils ├── benchmark.txt ├── bundle.sh ├── characters-to-codepoints-example.txt ├── characters-to-codepoints.py ├── charinfo.py ├── codepoints-to-characters-example.txt ├── codepoints-to-characters.py ├── emoji.py ├── generate-parser.html └── readme-tables.html /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Noah Doersing 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /dist/example.md.html: -------------------------------------------------------------------------------- 1 | 2 | **UnicodeMathML + Markdeep** 3 | 4 | If the following line looks like a proper formula that's centered, things are working the way they're supposed to:

5 | 6 | ⁅ⅆy/ⅆx=[y-G(x)]/a(x,y)⁆ 7 | 8 | *See `README.md` of the [UnicodeMathML repository](https://github.com/doersino/UnicodeMathML) for more information.* 9 | 10 | --- 11 | 12 | Here's a test of delimiter escapes: ⁅a+b⁆ testing \⁅a+b⁆ testing ⁅a+b\⁆ testing \⁅a+b\⁆ testing. 13 | 14 | And now a test of textstyle versus displaystyle math: ⁅lim▒_(n→∞) a_n⁆ and: 15 | 16 | ⁅lim▒_(n→∞) a_n⁆ 17 | 18 | ## Benchmark 19 | 20 | Translating the following list (see `utils/benchmark.txt`) of UnicodeMath expressions – note that some of them are indeed supposed to yield errors – shouldn't take very long at all. Blink and you'll (ideally) miss it (modulo MathJax rendering, which can be slow): 21 | 22 | ⁅"A COLLECTION OF 628 UNICODEMATH EXPRESSIONS FROM VARIOUS SOURCES"⁆ 23 | ⁅x + 2y + 3z⁆ 24 | ⁅1+▭(⟡(1&1/2/3/4/5))⁆ 25 | ⁅= α_x^2 1 + α_y^2 1 + α_z^2 1 + (α_y α_z y z - α_y α_z y z) + (α_x α_z z x - α_x α_z z x) + (α_x α_y x y - α_x α_y x y)⁆ 26 | ⁅A^* = \sum_{r}{ (-1)^r ⟨ A ⟩_r } = ⟨ A ⟩_+ - ⟨ A ⟩_-⁆ 27 | ⁅𝑊_𝛿₁ⁿ𝜌ⁿⁿa_2⁆ 28 | ⁅- 6y z + 4z x + 2x y = (2x + 3y) ∧ (y - 2z)⁆ 29 | ⁅├1]a┤[⁆ 30 | ⁅3/5 x + √z⁆ 31 | ⁅α_(z x) z x β_(y z) y z + α_(z x) z x β_(z x) z x + α_(z x) z x β_(x y) x y + α_(z x) z x β_(x y z) x y z⁆ 32 | ⁅|(|x| - |y|)|⁆ 33 | ⁅lim▒_(n→∞) a_n⁆ 34 | ⁅{v_i: i \in {1,2,3,4,5}}⁆ 35 | ⁅- α_x β_(y z) z^2y + α_x β_(z x) 1 x + α_x β_(x y) x y z + α_x β_(x y z) x y z z⁆ 36 | ⁅/+'⁆ 37 | ⁅a_b^c⁆ 38 | ⁅▭(128&✎(#e01f32&α))⁆ 39 | ⁅y z, x z, x y⁆ 40 | ⁅(a+b) ̂⁆ 41 | ⁅ⅇ⁆ 42 | ⁅A (B C) = (A B) C = A B C⁆ 43 | ⁅(ℕ_+)⃗⁆ 44 | ⁅a/b⁆ 45 | ⁅▢(a+b*⟌(a+b))⁆ 46 | ⁅mⁿ₋₃₌₍₂₋₅₎⁆ 47 | ⁅+ α_y β_(y z) 1 z + α_y β_(z x) x y z - α_y β_(x y) x y^2 - α_y β_(x y z) x y^2z⁆ 48 | ⁅a b⁆ 49 | ⁅x⁆ 50 | ⁅⫷scripts overhaul start⫸⁆ 51 | ⁅α⁆ 52 | ⁅x^2 = y^2 = z^2 = 1⁆ 53 | ⁅✎(#e01f32&α)⊘✎(#18a199&β)⁆ 54 | ⁅a_2⁆ 55 | ⁅a₉^+-b₁⁆ 56 | ⁅█(10&x+&3&y=2@3&x+&13&y=4)⁆ 57 | ⁅z w⁆ 58 | ⁅+ (α_1 β_(x y z) + α_(x y z) β_1 + α_x β_(y z) + α_(y z) β_x + α_y β_(z x) + α_(z x) β_y + α_x β_(x y) + α_(x y) β_z) x y z⁆ 59 | ⁅(a│b)/⁆ 60 | ⁅β_(y z) yz + β_(z x) z x + β_(x y) x y + β_(x y z) x y z\)⁆ 61 | ⁅∀ A, B, C ∈ 𝒢 ⟹ A \⌊ (B + C) = A \⌊ B + A \⌊ C⁆ 62 | ⁅sin⁡x⁆ 63 | ⁅f'(t) = 8 ((1-cos〖\theta/2〗)/(1+cos〖\theta/2〗) sin〖\theta/2〗)^2 (t-1) t (2t - 1) (6t² - 6t + 1)⁆ 64 | ⁅\root n+1\of(b+c)⁆ 65 | ⁅= α_x^2 + α_y^2 + α_z^2⁆ 66 | ⁅E = m⁢c²⁆ 67 | ⁅= (α_x x + α_y y + α_x z)⁆ 68 | ⁅|_〖|_a〗^b⁆ 69 | ⁅∧⁆ 70 | ⁅∫1_a^b▒x⁆ 71 | ⁅𝒢⁆ 72 | ⁅🔭+🌌⁆ 73 | ⁅1⊘2⁆ 74 | ⁅√a+b+d+1/b\of (c/d)⁆ 75 | ⁅([^⁆ 76 | ⁅ᅲ(α)⁆ 77 | ⁅+ β_1 + α_(x y) x y β_x x + α_(x y) x y β_y y + α_(x y) x y β_z z +⁆ 78 | ⁅= \(α_1 + α_x x + α_y y + α_x z +⁆ 79 | ⁅▭(2&✎(#e01f32&α))⁆ 80 | ⁅c'^2⁆ 81 | ⁅a + b_ℲDℲD2⁆ 82 | ⁅∫3┬(n→∞)┴b▒x⁆ 83 | ⁅123a_11+1234ab/2/W_v_v_v_v_v_v/4/a⁆ 84 | ⁅test+(_☁(blue&n)^☁(red&n))(1,2)_☁(green&n)^☁(yellow&✎(black&n))⁆ 85 | ⁅+ (α_1 β_(y z) + α_(y z) β_1 + α_x β_(x y z) + α_(x y z) β_x + α_y β_z - α_x β_y + α_(x y) β_(z x) - α_(z x) β_(x y)) y z⁆ 86 | ⁅a̼⁆ 87 | ⁅123┴↔ + ↔┴123.⁆ 88 | ⁅a⁗⁆ 89 | ⁅test+(_n^m)(1,2)_n^m⁆ 90 | ⁅a₂^α⁆ 91 | ⁅⟨⟩_r : 𝒢 → 𝒢_r⁆ 92 | ⁅+ α_(z x) β_1 z x + α_(z x) β_x z + α_(z x) β_y x y z - α_(z x) β_z x⁆ 93 | ⁅∀ a ∈ 𝒢_1, ∀ B ∈ 𝒢_m ⟹ B \⌊ a = 1/2 (B a - a B^*)⁆ 94 | ⁅a+⫷stuf\⫸fandthings+1⫸b⁆ 95 | ⁅- α_(y z) β_(y z) z z + α_(y z) β_(z x) y x + α_(y z) β_(x y) z x + α_(y z) β_(x y z) y x y⁆ 96 | ⁅α_x z β_(y z) y z + α_x z β_(z x) z x + α_x z β_(x y) x y + α_x z β_(x y z) x y z⁆ 97 | ⁅lim⁡_(a→∞) a + lim⁡²_(a→∞) a + sin²(a) = 42⁆ 98 | ⁅_β^γ α⁆ 99 | ⁅a‼⁆ 100 | ⁅a‴⁆ 101 | ⁅+ α_(x y) β_(y z) x z + α_(x y) β_(z x) y z - α_(x y) β_(x y) y y - α_(x y) β_(x y z) y y z⁆ 102 | ⁅a  b⁆ 103 | ⁅+ α_(x y) β_(y z) x 1 z + α_(x y) β_(z x) y x x z - α_(x y) β_(x y) y x^2y - α_(x y) β_(x y z) y x^2y z⁆ 104 | ⁅a⃑⁆ 105 | ⁅▭(255&"💩")⁆ 106 | ⁅+ α_(y z) β_1 y z - α_(y z) β_x y x z - α_(y z) β_y zy y + α_(y z) β_z y z^2⁆ 107 | ⁅30-50🐗⁆ 108 | ⁅a b⁆ 109 | ⁅3 D⁆ 110 | ⁅α_1⁆ 111 | ⁅█(10&x+  & 3&y=2@3&x+&13&y=4)⁆ 112 | ⁅∫0_a^b▒x⁆ 113 | ⁅∫₀²⁰ √x ⅆx⁆ 114 | ⁅+ α_(z x) β_1 z x + α_(z x) β_x z 1 + α_(z x) β_y x y z - α_(z x) β_z x z^2⁆ 115 | ⁅⬍(a/b/c/d/e/f)+c⁆ 116 | ⁅(a) + (a] + (a} + (a⟩ + (a〗 + (a⌉ + (a⌋⁆ 117 | ⁅⏠(⏟(x+⋯+x)_(k " times and stuff"))^(test_2_2_2_2_2_2_2_2_2_2_2_2_2_2_2_2)⁆ 118 | ⁅π_(ᅲ(from), ᅲ(to)←ᅲ(to2)) (σ_(ᅲ(to)=ᅲ(from2)) (G×π_(ᅲ(from2)←ᅲ(from), ᅲ(to2)←ᅲ(to)) (G)))⁆ 119 | ⁅= α_x^2 x^2 + α_y^2 y^2 + α_z^2 z^2 + α_y α_z y z - α_y α_z y z + α_x α_z z x - α_x α_z z x + α_x α_y x y - α_x α_y x y⁆ 120 | ⁅∀ a ∈ 𝒢_1, ∀ B ∈ 𝒢_m ⟹ a \⌋ B = 1/2 (a B - B^* a)⁆ 121 | ⁅→┴(𝑎 + 𝑏)⁆ 122 | ⁅v \⌋ B⁆ 123 | ⁅-1⁆ 124 | ⁅𝜌 = ∑_𝜓▒P_𝜓 |𝜓⟩⟨𝜓| ,⁆ 125 | ⁅a_b_b^c⁆ 126 | ⁅_4 F_1 + _42 F⁆ 127 | ⁅+ α_y β_1 y + α_y β_x y x + α_y β_y y y + α_y β_z y z +⁆ 128 | ⁅⟨ α_1 + α_x x + α_y y + α_z z + α_(y z) yz + α_(z x) z x + α_(x y) x y + α_(x y z) x y z ⟩_0 = α_1⁆ 129 | ⁅1.25⁆ 130 | ⁅(α)⁆ 131 | ⁅(α_x x + α_y y + α_z z)^2⁆ 132 | ⁅a/⁆ 133 | ⁅▭(4&✎(#e01f32&α))⁆ 134 | ⁅W_δ_1 ρ₁ σ₂^3β.⁆ 135 | ⁅α_(x y z) x y z β_(y z) y z + α_(x y z) x y z β_(z x) z x + α_(x y z) x y z β_(x y) x y + α_(x y z) x y z β_(x y z) x y z⁆ 136 | ⁅α⊘β⁆ 137 | ⁅ⅆy/ⅆx=[y-G(x)]/a(x,y). + \int_1\of a⁆ 138 | ⁅{x ∣ f(x) = 0}⁆ 139 | ⁅█(1&x+1&3&y=200@10000&x&3&y=2)⁆ 140 | ⁅∀ α ∈ 𝒢_0, ∀ B ∈ 𝒢 ⟹ α ∧ B = B ∧ α = α B = B α⁆ 141 | ⁅∑_1\of (\forall y\exists 1) ⫷if resolveCW == true⫸⁆ 142 | ⁅x_i\times y^n⁆ 143 | ⁅+ α_y β_1 y - α_y β_x x y + α_y β_y 1 + α_y β_z y z⁆ 144 | ⁅v_1 ∧ v_2⁆ 145 | ⁅+ α_1 β_(y z) y z + α_1 β_(z x) z x + α_1 β_(x y) x y + α_1 β_(x y z) x y z⁆ 146 | ⁅⬭(▭(⬭(42)))⁆ 147 | ⁅▭(32&✎(#e01f32&α))⁆ 148 | ⁅+ α_(z x) β_(y z) x z z y - α_(z x) β_(z x) x z^2x + α_(z x) β_(x y) z 1 y + α_(z x) β_(x y z) z 1 y z⁆ 149 | ⁅a _5^1 F_1⁆ 150 | ⁅α_(y z) yz + α_(z x) z x + α_(x y) x y + α_(x y z) x y z\)⁆ 151 | ⁅a⃗ⁿ⁆ 152 | ⁅∫_0^a▒〖xⅆx/(x^2+a^2)〗⁆ 153 | ⁅α̂̌̃́⁆ 154 | ⁅= α_1 β_1 + α_1 β_x x + α_1 β_y y + α_1 β_z z⁆ 155 | ⁅α/β∕γ⁆ 156 | ⁅α #β⁆ 157 | ⁅abc+a⁆ 158 | ⁅a⃢⁆ 159 | ⁅a^1_2_3_4⁆ 160 | ⁅├]1/2┤4[⁆ 161 | ⁅a'⁗‴⁆ 162 | ⁅a ∧ b = -b ∧ a⁆ 163 | ⁅|(a|b−c|d)|⁆ 164 | ⁅(a^n/b_c)/c⁆ 165 | ⁅( _a )a⁆ 166 | ⁅300-3.14^10000^2⁆ 167 | ⁅α'₂^β⁆ 168 | ⁅+ α_x β_(y z) x y z - α_x β_(z x) x x z + α_x β_(x y) x^2 y + α_x β_(x y z) x^2 y z⁆ 169 | ⁅∏_(k=0)^n▒n⒞k = H²(n) / (n!)^(n+1) = (∏_(h=0)^n▒h^h) / (n!)^(n+1)⁆ 170 | ⁅₁a₁⁆ 171 | ⁅a⃒⁆ 172 | ⁅a_b_c⁆ 173 | ⁅\int_0^a xⅆx/(x²+a²)⁆ 174 | ⁅+ α_(z x) β_(y z) x y - α_(z x) β_(z x) - α_(z x) β_(x y) y z - α_(z x) β_(x y z) y⁆ 175 | ⁅+ α_(z x) β_(y z) x y - α_(z x) β_(z x) - α_(z x) β_(x y) y z - α_(z x) β_(x y z) z z y⁆ 176 | ⁅|x| = {█(&x" if "x ≥ 0@−&x" if "x < 0)┤⁆ 177 | ⁅+ α_x β_1 x + α_x β_x 1 + α_x β_y x y - α_x β_z z x⁆ 178 | ⁅(∛a)/3.14159265+{a^b^c^d/2}⁆ 179 | ⁅x y⁆ 180 | ⁅= (α_x x + α_y y + α_x z) \⌋ (β_(y z) yz + β_(z x) zx + β_(x y) x y)⁆ 181 | ⁅▭(16&✎(#e01f32&α))⁆ 182 | ⁅✎(rgba(255,255,100,0.5)&1/☁(red&2/3/✎(black&345)))⁆ 183 | ⁅✎(rgba(255,255,100,0.5)&42)⁆ 184 | ⁅G(x)⁆ 185 | ⁅|x|={█(&x&"if "x≥0@-&x&"if "x<0)〗⁆ 186 | ⁅abcde┬→⁆ 187 | ⁅𝑊^𝛿₁𝜌ⁿ⁆ 188 | ⁅-x y z, 17/41 x y z, ...⁆ 189 | ⁅α_x β_(y z) x y z + α_x β_(z x) x z x + α_x β_(x y) x x y + α_x β_(x y z) x x y z⁆ 190 | ⁅2π⁆ 191 | ⁅α₄₂^+-β₁⁆ 192 | ⁅- α_(y z) β_(y z) - α_(y z) β_(z x) x y + α_(y z) β_(x y) z x - α_(y z) β_(x y z) x⁆ 193 | ⁅\rect(y=x+4)⁆ 194 | ⁅E = mc²⁆ 195 | ⁅_n C_k = n⒞k = n!/(k! ⋅ (n-k)!)⁆ 196 | ⁅α+β⁆ 197 | ⁅(A + B) C = A C + B C⁆ 198 | ⁅a^′′′⁆ 199 | ⁅e'⁆ 200 | ⁅+ α_y β_(y z) y^2z - α_y β_(z x) y x z - α_y β_(x y) x y y - α_y β_(x y z) x y y z⁆ 201 | ⁅⏞(x_1+⋯+x_k)^(k " times")⁆ 202 | ⁅x = 0, y = 2⁆ 203 | ⁅= α_1 β_1 + α_x β_x + α_y β_y + α_x β_z - α_(y z) β_(y z) - α_(z x) β_(z x) - α_(x y) β_(x y) - α_(x y z) β_(x y z)⁆ 204 | ⁅\⌋ : 𝒢_n × 𝒢_m \to 𝒢_{m - n}⁆ 205 | ⁅¹₂3⁆ 206 | ⁅\playground 123⁆ 207 | ⁅☁(red&1/2/3/☁(green&tes☁(blue&t)))⁆ 208 | ⁅|a(x,y)/Δx|a≪1⁆ 209 | ⁅lim⁡_(a→∞) a + lim⁡²_(a→∞) a + sin²(a) = 42/⁆ 210 | ⁅ⅆy/ⅆx=[y-G(x)]/a(x,y)⁆ 211 | ⁅^+ A⁆ 212 | ⁅- α_(x y z) β_(y z) x y y z z + α_(x y z) β_(z x) x y z^2x - α_(x y z) β_(x y) x y x z y - α_(x y z) β_(x y z) y x z x y z⁆ 213 | ⁅⟨ α_1 + α_x x + α_y y + α_z z + α_(y z) yz + α_(z x) z x + α_(x y) x y + α_(x y z) x y z ⟩_-5 = 0⁆ 214 | ⁅sin α⁆ 215 | ⁅α_(y z) y z + α_(z x) z x + α_(x y) x y⁆ 216 | ⁅𝙲𝙰𝚁𝙳𝚂\_𝙱𝙰𝙳/⁆ 217 | ⁅▭(192&α)⁆ 218 | ⁅▭(64&✎(#e01f32&α))⁆ 219 | ⁅a⁗'‴⁆ 220 | ⁅〖▭(255&▭(255&▭(255&▭(255&▭(255&▭(255&▭(255&ℲB"🕷")))))))〗  〖ℲB🦟¦ ¦ 〗⁆ 221 | ⁅ⅆy/ⅆx=[y-G(x)]/a(x,y).⁆ 222 | ⁅+⁆ 223 | ⁅A ⟕_(A.a = B.b) B⁆ 224 | ⁅⟨ |⁆ 225 | ⁅⟨⟩_+ : 𝒢 → 𝒢_+⁆ 226 | ⁅{x_1, ..., x_n}⁆ 227 | ⁅N₀₊₍₂₋₅₎₌₋₃⁆ 228 | ⁅v_1 v_2⁆ 229 | ⁅m+a⁄t_h⁆ 230 | ⁅- α_(x y z) β_(y z) x + α_(x y z) β_(z x) x y x - α_(x y z) β_(x y) zy y - α_(x y z) β_(x y z) y z z y⁆ 231 | ⁅exp(x/a(x,G(x)))⁆ 232 | ⁅x y + z w⁆ 233 | ⁅▭(1&✎(#e01f32&α))⁆ 234 | ⁅∫4_a^b▒x⁆ 235 | ⁅- α_(y z) β_(y z) zy y z + α_(y z) β_(z x) y z^2x - α_(y z) β_(x y) zy x y - α_(y z) β_(x y z) y x z y z⁆ 236 | ⁅\(β_1 + β_x x + β_y y + β_z z +⁆ 237 | ⁅ℲBα⁆ 238 | ⁅1.25^n⁆ 239 | ⁅+ α_(y z) β_1 y z + α_(y z) β_x y z x + α_(y z) β_y y z y + α_(y z) β_z y z z +⁆ 240 | ⁅+ α_x β_1 z + α_x β_x z x - α_x β_y y z + α_x β_z z^2⁆ 241 | ⁅a₀₋₉⁴⁼ⁱ⁆ 242 | ⁅+ : 𝒢 × 𝒢 → 𝒢⁆ 243 | ⁅α⬌(β)γ⁆ 244 | ⁅⨌1_a\of ⨌62^a\of b\cdot c⁆ 245 | ⁅a + b⁆ 246 | ⁅cos▒² α⁆ 247 | ⁅a b = (2 x) (4 x + 3 y) = 8 + 6 x y⁆ 248 | ⁅⏟def┬2⁆ 249 | ⁅(x + y + z) ∧ (x + 3y - 3z) = - 6y z + 4z x + 2x y⁆ 250 | ⁅α_x β_(y z) z y z + α_x β_(z x) z z x + α_x β_(x y) z x y + α_x β_(x y z) z x y z⁆ 251 | ⁅√a + √b⁆ 252 | ⁅a⊘b⊘c⊘d⊘e⊘f⊘g⊘h⊘i⊘j⊘k⊘l⊘m⊘n⊘o⊘p⊘q⊘r⊘s⊘t⊘u⊘v⊘w⊘x⊘y⊘z⁆ 253 | ⁅⬌(_✎(#e01f32&α)^✎(#18a199&β) ✎(#467bc4&γ))(_α^β)γ⁆ 254 | ⁅O(n⁴)⁆ 255 | ⁅α₂³/(β₂³+γ₂³)⁆ 256 | ⁅∫^α₂⁆ 257 | ⁅a′′′'''⁆ 258 | ⁅f'(t) = 8 ((1-cos〖\theta/2〗)/(1+cos〖\theta/2〗) sin〖\theta/2〗)^2 (t-1) t (2t - 1) (6t^2 - 6t + 1)⁆ 259 | ⁅+ (α_1 β_x + α_x β_1 + α_(x y) β_y - α_y β_(x y) + α_x β_(z x) - α_(z x) β_z - α_(y z) β_(x y z) - α_(x y z) β_(y z)) x⁆ 260 | ⁅α_(x y) β_(y z) x y y z + α_(x y) β_(z x) x y z x + α_(x y) β_(x y) x y x y + α_(x y) β_(x y z) x y x y z⁆ 261 | ⁅\sum┬k▒(-1)^k z_k f(t-k) ℲB\/ \sum┬k▒(-1)^k f(t-k)⁆ 262 | ⁅⏜α⁆ 263 | ⁅1/2π ∫_0^2π▒ⅆθ/(a+b sinθ) = 1/√(a^2-b^2),⁆ 264 | ⁅(a + b)^n = ∑_(k=0)^n▒(n¦k) a^k b^(n-k)⁆ 265 | ⁅aⁱ_b⁆ 266 | ⁅a′′′⁆ 267 | ⁅y"'s fifth derivative" = ẏ┴5 = y⃛̈ = ÿ̈̇ = ÿ̇̈⁆ 268 | ⁅▁(a)⁆ 269 | ⁅✎(#e01f32&α)/✎(#18a199&β)⁆ 270 | ⁅a²⋅b²=c²⁆ 271 | ⁅ab/cd/ef/√(10&gh)⁆ 272 | ⁅1∕2⁆ 273 | ⁅(/+)/2⁆ 274 | ⁅+ α_(x y) β_(y z) x y^2z - α_(x y) β_(z x) y x z x - α_(x y) β_(x y) y x x y - α_(x y) β_(x y z) y x x y z⁆ 275 | ⁅√✎(#e01f32&α)⁆ 276 | ⁅1⁴²√√√∛∜back_to_the_roots⁆ 277 | ⁅a_(a┬b)⁆ 278 | ⁅a_ℲDa + a_ℲCa + a_a + a_ℲAa + a_ℲBa⁆ 279 | ⁅+ α_(x y z) β_1 x y z + α_(x y z) β_x y z - α_(x y z) β_y x z + α_(x y z) β_z x y⁆ 280 | ⁅a⃝⁆ 281 | ⁅A⨝_(A.x=B.y) B⁆ 282 | ⁅M = α_1 + α_x x + α_y y + α_x z +⁆ 283 | ⁅(a∣b)⁆ 284 | ⁅⏝(a_1 + b_1) + ⏝(a_2 + b_2) + ⏝(a_3 + b_3)⁆ 285 | ⁅α'′⁆ 286 | ⁅▭(a⃗̂)⁆ 287 | ⁅├)a┤⁆ 288 | ⁅α_(x y) x y β_(y z) y z + α_(x y) x y β_(z x) z x + α_(x y) x y β_(x y) x y + α_(x y) x y β_(x y z) x y z⁆ 289 | ⁅a /~ b⁆ 290 | ⁅↔┬abcdefg⁆ 291 | ⁅a_(a) + a_├1(a) + a_├2(a) + a_├3(a) + a_├4(a)⁆ 292 | ⁅a+{(1]/4⟩⁆ 293 | ⁅α_1 β_(y z) y z + α_1 β_(z x) z x + α_1 β_(x y) x y + α_1 β_(x y z) x y z⁆ 294 | ⁅x = 0, y = 2⁆ 295 | ⁅a''⁆ 296 | ⁅4x y, -3y z + 2z x, π z x - √2 x y, ...⁆ 297 | ⁅ⅆ(tan x)/ⅆx = 1/cos▒^2 x⁆ 298 | ⁅+ (α_1 β_y + α_y β_1 + α_x β_(x y) - α_(x y) β_x + α_(y z) β_z - α_x β_(y z) - α_(z x) β_(x y z) - α_(x y z) β_(z x)) y⁆ 299 | ⁅a +_+_+_+_+_+_+_+_+_+_+_+_+_+_+ b⁆ 300 | ⁅+ α_(x y) β_1 x y - α_(x y) β_x x^2y + α_(x y) β_y x 1 + α_(x y) β_z x y z⁆ 301 | ⁅a⁆ 302 | ⁅α_(z x) β_(y z) z x y z + α_(z x) β_(z x) z x z x + α_(z x) β_(x y) z x x y + α_(z x) β_(x y z) z x x y z⁆ 303 | ⁅○α⁆ 304 | ⁅𝑎⁆ 305 | ⁅∀ a ∈ 𝒢_1, ∀ B ∈ 𝒢 ⟹ a ∧ B = 1/2 (a B + B^* a)⁆ 306 | ⁅= (α_y β_z - α_x β_y) yz⁆ 307 | ⁅a^b₁⁆ 308 | ⁅+ α_x β_1 x + α_x β_x + α_x β_y x y - α_x β_z z x⁆ 309 | ⁅a_1 + a_2 + ⋯ + a_(i-1) + a_i + ⏞(a_(i+1) + ⋯ + a_(n-1) + a_n)^(n-i " times")⁆ 310 | ⁅w^h_c⁆ 311 | ⁅√(n&a + b)⁆ 312 | ⁅[■(α&β@γ&δ)]⁆ 313 | ⁅\playground⁆ 314 | ⁅a^b_c⁆ 315 | ⁅a -̸ b⁆ 316 | ⁅- α_(x y z) β_(y z) x y^2z^2 + α_(x y z) β_(z x) x y 1 x + α_(x y z) β_(x y) x x y zy + α_(x y z) β_(x y z) y z x x y z⁆ 317 | ⁅𝟙+𝟚⁆ 318 | ⁅+ α_y β_(y z) z + α_y β_(z x) x y z - α_y β_(x y) x + α_y β_(x y z) z x⁆ 319 | ⁅\⌊ : 𝒢_n × 𝒢_m \to 𝒢_{n - m}⁆ 320 | ⁅∫64_a▒(1/2/3/4)⁆ 321 | ⁅(a) + ├1(a) + ├2(a) + ├3(a) + ├4(a)⁆ 322 | ⁅⟨ α_1 + α_x x + α_y y + α_z z + α_(y z) yz + α_(z x) z x + α_(x y) x y + α_(x y z) x y z ⟩_2 = α_(y z) yz + α_(z x) z x + α_(x y) x y⁆ 323 | ⁅+ α_(x y) β_1 x y - α_(x y) β_x x x y + α_(x y) β_y x y^2 + α_(x y) β_z x y z⁆ 324 | ⁅⏟abc_1⁆ 325 | ⁅f̂(ξ)=∫_-∞^∞▒f(x)ⅇ^-2πⅈxξ ⅆx⁆ 326 | ⁅"hex"={■(0@1@2@3@4@5@6@7@8@9@A@B@C@D@E@F)┤ " with " |hex|=16⁆ 327 | ⁅𝒢_r⁆ 328 | ⁅(a + b)┴→⁆ 329 | ⁅α_(x y z) x y z⁆ 330 | ⁅α̈̇⁆ 331 | ⁅a⃫⁆ 332 | ⁅- 6y z + 4z x + 2x y⁆ 333 | ⁅(potter)͛⁆ 334 | ⁅a b⁆ 335 | ⁅f⁆ 336 | ⁅∫_0^a▒(xⅆx/(x^2+a^2))⁆ 337 | ⁅c'_2⁆ 338 | ⁅(a)⁆ 339 | ⁅+ α_x β_1 z + α_x β_x z x + α_x β_y z y + α_x β_z z z +⁆ 340 | ⁅b_1 +_1^2 c⁆ 341 | ⁅x, 3x, 17/41 x, 2x + y, 15y, -x + 2y + 5z, z, ...⁆ 342 | ⁅α_(x y z) β_(y z) x y z y z + α_(x y z) β_(z x) x y z z x + α_(x y z) β_(x y) x y z x y + α_(x y z) β_(x y z) x y z x y z⁆ 343 | ⁅a≠b⁆ 344 | ⁅y - 2z⁆ 345 | ⁅+ α_(x y z) β_1 x y z - α_(x y z) β_x x y x z - α_(x y z) β_y x y y z + α_(x y z) β_z x y z^2⁆ 346 | ⁅- α_(x y z) β_(y z) x - α_(x y z) β_(z x) y - α_(x y z) β_(x y) z - α_(x y z) β_(x y z)⁆ 347 | ⁅⁅"BS" = 1/N ∑_(t=1)^N▒(f_t-o_t )^2 ⫷from https://github.com/adiabatic/predictions/ommit/5c08e653ac9035c8a0c127d673a82ef662cc2321⫸⁆ 348 | ⁅(1+2)̂̈⃛⁆ 349 | ⁅1 ¦ 2 ¦ 3 ¦ 4 ¦ 5⁆ 350 | ⁅+ α_x β_1 z + α_x β_x z x - α_x β_y y z + α_x β_z 1⁆ 351 | ⁅lim┬(n→b)⁆ 352 | ⁅⨌_a\of b\cdot c⁆ 353 | ⁅(_β^γ)α_δ^ε⁆ 354 | ⁅𝚊𝚛𝚛[i], i \in ℤ₀⁺/⁆ 355 | ⁅= α_x^2 x^2 + α_x α_y x y - α_x α_z z x - α_x α_y x y + α_y^2 y^2 + α_y α_z y z + α_x α_z z x - α_y α_z y z + α_z^2 z^2⁆ 356 | ⁅a+⫷stuff⫸b⁆ 357 | ⁅y z, z x, x y⁆ 358 | ⁅√56⁆ 359 | ⁅1+\playground+2⁆ 360 | ⁅𝚊𝚛𝚛[i], i \in ℤ₀⁺⁆ 361 | ⁅𝑊_𝛿₁𝜌ⁿ𝜎^2⁆ 362 | ⁅= α_1 - α_x x - α_y y - α_z z + α_(y z) yz + α_(z x) z x + α_(x y) x y - α_(x y z) x y z⁆ 363 | ⁅a  b⁆ 364 | ⁅a₁^b⁆ 365 | ⁅a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z⁆ 366 | ⁅a^*⁆ 367 | ⁅lim⁡⁆ 368 | ⁅∑┬α▒β⁆ 369 | ⁅∑┬Ω▒Δα²⁆ 370 | ⁅\sum_1\of\alpha⁆ 371 | ⁅∧ : 𝒢_n × 𝒢_m → 𝒢_{n+m}⁆ 372 | ⁅- α_x β_(y z) z z y + α_x β_(z x) z^2x - α_x β_(x y) x z y - α_x β_(x y z) x z y z⁆ 373 | ⁅αⅆβ⁆ 374 | ⁅a+b⁆ 375 | ⁅▢(a+b).⁆ 376 | ⁅+ β_1 + α_(z x) z x β_x x + α_(z x) z x β_y y + α_(z x) z x β_z z +⁆ 377 | ⁅✎(#e01f32&α)∕✎(#18a199&β)⁆ 378 | ⁅A_n \⌋ B_m = ⟨ A_n B_m ⟩_{m-n}⁆ 379 | ⁅δ₁⋅ρ₁⁆ 380 | ⁅========== #[1]⁆ 381 | ⁅sin⁡θ = 1⁄2 𝑒^(ⅈ⁢θ) + "c.c."⁆ 382 | ⁅α_x x β_(y z) y z + α_x x β_(z x) z x + α_x x β_(x y) x y + α_x x β_(x y z) x y z⁆ 383 | ⁅a b⁆ 384 | ⁅∫2_a^b▒x⁆ 385 | ⁅↉½⅓⅔¼¾⅕⅖⅗⅘⅙⅚⅐⅛⅜⅝⅞⅑⁆ 386 | ⁅+ α_(y z) β_1 y z + α_(y z) β_x x y z - α_(y z) β_y zy^2 + α_(y z) β_z y 1⁆ 387 | ⁅a^+a_b⁆ 388 | ⁅▭(19&✎(#e01f32&α))⁆ 389 | ⁅b⁆ 390 | ⁅+ α_(x y) β_1 x y + α_(x y) β_x x y x + α_(x y) β_y x y y + α_(x y) β_z x y z +⁆ 391 | ⁅+ β_1 + α_y y β_x x + α_y y β_y y + α_y y β_z z +⁆ 392 | ⁅α_y β_(y z) y y z + α_y β_(z x) y z x + α_y β_(x y) y x y + α_y β_(x y z) y x y z⁆ 393 | ⁅(α_1 + α_x x + α_y y + α_z z + α_(y z) y z + α_(z x) z x + α_(x y) x y + α_(x y z) x y z)^*⁆ 394 | ⁅+ (α_1 β_(z x) + α_(z x) β_1 + α_x β_x - α_x β_z + α_y β_(x y z) + α_(x y z) β_y + α_(y z) β_(x y) - α_(x y) β_(y z)) z x⁆ 395 | ⁅a^b^c^d⁆ 396 | ⁅(a∣b∣c/d)⁆ 397 | ⁅⨄▒α⁆ 398 | ⁅W/e/i/h/n/a/c/h/t/s/b/a/u/m⁆ 399 | ⁅a_ℲA2⁆ 400 | ⁅sin 𝜃 = 1⁄2 𝑒^𝑖𝜃 + "c.c."⁆ 401 | ⁅3D⁆ 402 | ⁅A_n ∧ B_m = ⟨ A_n B_m ⟩_{n+m}⁆ 403 | ⁅₁ a⁆ 404 | ⁅a​b⁆ 405 | ⁅𝛼₂³/(𝛽₂³ + 𝛾₂³)⁆ 406 | ⁅{a⌋^⟨1/[2)/3].⁆ 407 | ⁅a⁗'⁆ 408 | ⁅a∶b:c ⇒ "RATIO U+2236 vs colon"⁆ 409 | ⁅(.*?)⁆ 410 | ⁅a⃚⁆ 411 | ⁅x_j_i_k_1 ...x_i_j_k_r⁆ 412 | ⁅✎(rebeccapurple&6)⁆ 413 | ⁅a" "b⁆ 414 | ⁅⨌1_a\of b\cdot c⁆ 415 | ⁅w^h^y+∑_aα^1Ω+sin(a)+"sin(a)"+c⁆ 416 | ⁅(a) + (a] + (a} + (a⟩ + (a〗 + (a⌉ + (a⌋/⁆ 417 | ⁅(1, 2.3)⁆ 418 | ⁅+ α_x β_(y z) x y z - α_x β_(z x) x^2z + α_x β_(x y) 1 y + α_x β_(x y z) 1 y z⁆ 419 | ⁅a^b^b^b^b_c_c_c_c⁆ 420 | ⁅a′⁆ 421 | ⁅< b + \int_a\of a/⁆ 422 | ⁅√2⁆ 423 | ⁅+ (α_x β_x - α_x β_z) z x⁆ 424 | ⁅+ α_(z x) β_(y z) x y - α_(z x) β_(z x) x x + α_(z x) β_(x y) zy + α_(z x) β_(x y z) zy z⁆ 425 | ⁅n⒞k = (n!)/(k!(n - k)!)⁆ 426 | ⁅ⅉ⁆ 427 | ⁅𝑊^𝜌ⁿ𝛿₁⁆ 428 | ⁅☁(red&1/2/3/345)⁆ 429 | ⁅a /¬ b⁆ 430 | ⁅z⁆ 431 | ⁅w^h^e^e^e^e+1a+"Testing this!"-(1/2/333/4+1+1)+abc₂⁹/W_c+ab+√(42&1g)+▭(255&▭(255&b))+∑_A▒a+1+∑┴a┬b▒b⁆ 432 | ⁅∀ A, B, C ∈ 𝒢 ⟹ A \⌋ (B + C) = A \⌋ B + A \⌋ C⁆ 433 | ⁅├1]α, β┤1)⁆ 434 | ⁅⟨ α_1 + α_x x + α_y y + α_z z + α_(y z) yz + α_(z x) z x + α_(x y) x y + α_(x y z) x y z ⟩_+⁆ 435 | ⁅○(sin(α))⁆ 436 | ⁅A (B + C) = A B + A C⁆ 437 | ⁅a͖⁆ 438 | ⁅⟨ α_1 + α_x x + α_y y + α_z z + α_(y z) yz + α_(z x) z x + α_(x y) x y + α_(x y z) x y z ⟩_-⁆ 439 | ⁅\playground/⁆ 440 | ⁅= (α_x x + α_y y + α_z z)(α_x x + α_y y + α_z z)⁆ 441 | ⁅x y = -y x, x z = -z x, y z = -z y⁆ 442 | ⁅≝   \approx   =┴"def"⁆ 443 | ⁅√(a+(b))⁆ 444 | ⁅π_(ᅲ(X)←ᅲ(A)+ᅲ(C), ᅲ(Y)←¬ᅲ(B), ᅲ(Z)←ᅲ("LEGO")) (R)⁆ 445 | ⁅` ([___U+2045___]) starts a math zone and `⁆ 446 | ⁅+ α_(z x) β_1 z x + α_(z x) β_x z x x + α_(z x) β_y z x y + α_(z x) β_z z x z +⁆ 447 | ⁅+ β_1 + α_x x β_x x + α_x x β_y y + α_x x β_z z +⁆ 448 | ⁅α_y y β_(y z) y z + α_y y β_(z x) z x + α_y y β_(x y) x y + α_y y β_(x y z) x y z⁆ 449 | ⁅a b⁆ 450 | ⁅+┬✎(red&c)⁆ 451 | ⁅a^(1_2)_3_4⁆ 452 | ⁅⏟α_β⁆ 453 | ⁅⇳(a/b/b/b/b/b)+1⁆ 454 | ⁅1⁄2⁆ 455 | ⁅a"0"b⁆ 456 | ⁅(_3)F⁆ 457 | ⁅(β_x x + β_y y + β_z z)⁆ 458 | ⁅α_x x + α_y y + α_x z⁆ 459 | ⁅∰_1^n▒f(x)⁆ 460 | ⁅ℕ_+⁆ 461 | ⁅∮16_α▒β⁆ 462 | ⁅f̂(ξ)=∫_-∞^∞▒f(x)ⅇ^(-2πⅈxξ)ⅆx⁆ 463 | ⁅a^+̸/2⁆ 464 | ⁅f(ξ)=∫_a▒f(x)ⅇ^(2πⅈxξ) ⅆx#[1]⁆ 465 | ⁅+ α_x β_1 x + α_x β_x x x + α_x β_y x y + α_x β_z x z +⁆ 466 | ⁅∀ A, B, C ∈ 𝒢 ⟹ (A + B) \⌋ C = A \⌋ C + B \⌋ C⁆ 467 | ⁅∀ A, B, C ∈ 𝒢 ⟹ (A + B) ∧ C = A ∧ C + B ∧ C⁆ 468 | ⁅\notacontrolword⁆ 469 | ⁅f̂(ξ)=∫_-∞^∞▒f(x)ⅇ^-2πⅈxξ ⅆx#[42]⁆ 470 | ⁅α! + β‼⁆ 471 | ⁅+ α_y β_(y z) z + α_y β_(z x) x y z - α_y β_(x y) x - α_y β_(x y z) x z⁆ 472 | ⁅©(a@b)⁆ 473 | ⁅a⁗⁗'⁗‴⁆ 474 | ⁅Δx⁆ 475 | ⁅lim⁡²_(a→∞) sin²(a) = 42⁆ 476 | ⁅1+"tes\"t"#(this is an equation number)⁆ 477 | ⁅1/2𝜋 ∫_0^2𝜋▒ⅆ𝜃/(𝑎+𝑏 sin⁡𝜃)=1/√(𝑎^2−𝑏^2)⁆ 478 | ⁅+ α_y β_1 y - α_y β_x x y + α_y β_y y^2 + α_y β_z y z⁆ 479 | ⁅b_1+_1^2 c⁆ 480 | ⁅+ α_(x y z) β_1 x y z + α_(x y z) β_x x x y z - α_(x y z) β_y x y^2z + α_(x y z) β_z x y 1⁆ 481 | ⁅= α_1 β_1 + α_1 β_x x + α_1 β_y y + α_1 β_z z +⁆ 482 | ⁅α_(y z) yz + α_(z x) z x + α_(x y) x y + α_(x y z) x y z⁆ 483 | ⁅θ²⁆ 484 | ⁅a″⁆ 485 | ⁅1, 15, 17/41, 2√3, -π, ...⁆ 486 | ⁅= (α_x x + α_y y + α_x z) ∧ (β_x x + β_y y + β_z z)⁆ 487 | ⁅+ (α_x β_x - α_x β_z) zx⁆ 488 | ⁅= α_1 + α_(y z) yz + α_(z x) z x + α_(x y) x y + α_(x y z) x y z⁆ 489 | ⁅a b⁆ 490 | ⁅W_δ₁ρ₁σ₂^3β=U_δ₁ρ₁^3β+1/8π^2⁢∫_α₁^α₂▒dα'₂[(U_δ₁ρ₁^2β-α'₂U_ρ₁σ₂^1β)/U_ρ₁σ₂^0β]⁆ 491 | ⁅"α"⁆ 492 | ⁅y⁆ 493 | ⁅├a)⁆ 494 | ⁅y z = -z y, z x = -x z, x y = -y x⁆ 495 | ⁅w⁆ 496 | ⁅- α_x β_(y z) y + α_x β_(z x) x + α_x β_(x y) x y z + α_x β_(x y z) x y⁆ 497 | ⁅π⁆ 498 | ⁅+ α_y β_1 y - α_y β_x x y + α_y β_y + α_y β_z y z⁆ 499 | ⁅I(x,x') = g(x,x') [ε(x,x') + ∫_S▒ρ(x,x',x'')I(x',x'')ⅆx'']⁆ 500 | ⁅✎(yellow&42)⁆ 501 | ⁅^1_2 F_3^4⁆ 502 | ⁅a b⁆ 503 | ⁅⒨(a & b& c&d @ c& d )⁆ 504 | ⁅a b⁆ 505 | ⁅1a+"Testing this!"-(1/2/3/4+1+1)+abc₂⁹/W_c+ab+√(e&1g)+▭(255&b)+∑_A▒a+1+∑┬a▒b⁆ 506 | ⁅a_-a⁆ 507 | ⁅(■(a+1&y+2@c&d))⁆ 508 | ⁅lim⁡_(a→∞)⁆ 509 | ⁅⬌(⬆(a/b/c/d/e))+b⁆ 510 | ⁅W_δ₁ρ₁σ₂^3β=U_δ₁ρ₁^3β+1/8π^2⁢∫_α₁^α₂▒dα'₂[(U_δ₁ρ₁^2β-α'₂U_δ₁ρ₁^1β)/U_δ₁ρ₁^0β]⁆ 511 | ⁅"rate" = "distance" / "time".⁆ 512 | ⁅1/2⁆ 513 | ⁅∫_α₂⁆ 514 | ⁅A_2⁆ 515 | ⁅abc⃟⁆ 516 | ⁅1/2π ∫_0^(2⬌(π))▒ⅆθ/(a+b sinθ) = 1/√(a^2-b^2).⁆ 517 | ⁅(■(a&b@c&d))⁆ 518 | ⁅∫_-∞^▢(+∞)⁆ 519 | ⁅α_(y z) β_(y z) y z y z + α_(y z) β_(z x) y z z x + α_(y z) β_(x y) y z x y + α_(y z) β_(x y z) y z x y z⁆ 520 | ⁅​^* : 𝒢 → 𝒢⁆ 521 | ⁅ρ⁆ 522 | ⁅- α_(z x) β_(y z) x z y z - α_(z x) β_(z x) x z z x + α_(z x) β_(x y) z x^2y + α_(z x) β_(x y z) z x^2y z⁆ 523 | ⁅= α_x^2 x^2 + α_x α_y x y + α_x α_z x z + α_x α_y y x + α_y^2 y^2 + α_y α_z y z + α_x α_z z x + α_y α_z z y + α_z^2 z^2⁆ 524 | ⁅├1]1/2┤4[⁆ 525 | ⁅+ α_(x y z) β_1 x y z + α_(x y z) β_x y z + α_(x y z) β_y z x + α_(x y z) β_z x y⁆ 526 | ⁅√(δ&α)⁆ 527 | ⁅n⁆ 528 | ⁅ᅲ(let ) x=1 ᅲ( in )f(y) = y + x ⇒ f(y) = y + 1⁆ 529 | ⁅- α_(x y z) β_(y z) x - α_(x y z) β_(z x) x x y - α_(x y z) β_(x y) z - α_(x y z) β_(x y z) y y⁆ 530 | ⁅sin x⁆ 531 | ⁅∀ A, B, C ∈ 𝒢 ⟹ A ∧ (B + C) = A ∧ B + A ∧ C⁆ 532 | ⁅f'(x) = a⁆ 533 | ⁅^1_2 〖n^3_4〗 " or " 〖^1_2 n〗^3_4 " instead of " ^1_2 n^3_4.⁆ 534 | ⁅√(n&✎(#e01f32&α))⁆ 535 | ⁅+ β_1 + α_(y z) y z β_x x + α_(y z) y z β_y y + α_(y z) y z β_z z +⁆ 536 | ⁅= α_x x + α_y y + α_z z + α_(x y z) x y z⁆ 537 | ⁅a'^c⁆ 538 | ⁅sin⁡^2 x⁆ 539 | ⁅"𝓋𝓪𝔯𝖎𝚊𝕟t𝑠"⁆ 540 | ⁅a b⁆ 541 | ⁅α⟡(β)γ⁆ 542 | ⁅∫3_a^b▒x⁆ 543 | ⁅⎴(sin(a))^("test")⁆ 544 | ⁅+ α_(x y z) β_1 x y z + α_(x y z) β_x x y z x + α_(x y z) β_y x y z y + α_(x y z) β_z x y z z +⁆ 545 | ⁅∀ a ∈ 𝒢_1, ∀ B ∈ 𝒢 ⟹ B ∧ a = 1/2 (B a + a B^*)⁆ 546 | ⁅(a) + [a) + {a) + ⟨a) + 〖a) + ⌈a) + ⌊a)/⁆ 547 | ⁅\int\of a⁆ 548 | ⁅= α_x β_x + α_y β_y + α_x β_z⁆ 549 | ⁅+_+_+_+_+_+_+_+_+_+_+_+^+^+^+^+^+^+^+^+^+^+⁆ 550 | ⁅(a│b)⁆ 551 | ⁅1 + 4x + 4z x + √3 x y z, 0, 6y + 3z - 2y z, ...⁆ 552 | ⁅⟨⟩_- : 𝒢 → 𝒢_-⁆ 553 | ⁅- α_(x y) β_(y z) z x + α_(x y) β_(z x) y z - α_(x y) β_(x y) - α_(x y) β_(x y z) z⁆ 554 | ⁅+ α_x β_1 z + α_x β_x z x - α_x β_y y z + α_x β_z⁆ 555 | ⁅+ α_(z x) β_1 z x + α_(z x) β_x z x^2 - α_(z x) β_y x z y - α_(z x) β_z x z z⁆ 556 | ⁅(𝑎 + 𝑏)┴→┬→⁆ 557 | ⁅√α⁆ 558 | ⁅✎(#269&a+b)⁆ 559 | ⁅├)a)⁆ 560 | ⁅▭(255&▭(255&▭(255&▭(255&▭(255&▭(255&▭(255&▭(255&spider))))))))⁆ 561 | ⁅ⅈ⁆ 562 | ⁅_a a_a_a_a_a_a_a_u_g_h⁆ 563 | ⁅M_1 M_2⁆ 564 | ⁅〖a)⁆ 565 | ⁅⫷primes overhaul start⫸⁆ 566 | ⁅α⇳(β)γ⁆ 567 | ⁅⬌(a/b)+c⁆ 568 | ⁅a /= b⁆ 569 | ⁅α┬β┴γ⁆ 570 | ⁅(pizza^🍕)^🍕⁆ 571 | ⁅+ (α_x β_y - α_y β_x) xy⁆ 572 | ⁅⬇(a/((a/b)/(a/b)))+b⁆ 573 | ⁅sin θ=(e^iθ-e^-iθ)/2i⁆ 574 | ⁅𝙲𝙰𝚁𝙳𝚂\_𝙱𝙰𝙳⁆ 575 | ⁅+ (α_x β_y - α_y β_x) x y⁆ 576 | ⁅w^h^e^e^e^e⁆ 577 | ⁅d⁆ 578 | ⁅= (α_x β_(z x) - α_y β_(x y)) x + (α_x β_(x y) - α_x β_(y z)) y + (- α_x β_(z x) + α_y β_(y z)) z⁆ 579 | ⁅𝐏𝓁𝔞𝚢𝗴𝑟𝖔𝓊𝙣𝕕⁆ 580 | ⁅2¹⁶⁆ 581 | ⁅1+⟡(31&1/2/3/4/5)+1⁆ 582 | ⁅ā+ ̄(a)⁆ 583 | ⁅⌊a/b/c⌋⁆ 584 | ⁅∫_1^t▒〖ⅆx/x〗#(42)⁆ 585 | ⁅𝜌 = ∑_𝜓▒P_𝜓 |𝜓⟩⟨𝜓| + 1⁆ 586 | ⁅- α_(y z) β_(y z) - α_(y z) β_(z x) x y + α_(y z) β_(x y) z x - α_(y z) β_(x y z) x y y⁆ 587 | ⁅ℲDa + ℲCa + a + ℲAa + ℲBa⁆ 588 | ⁅α_β^γ⁆ 589 | ⁅{x_i_1, ..., x_i_m}⁆ 590 | ⁅y=G(x)⁆ 591 | ⁅0⁆ 592 | ⁅▭(8&✎(#e01f32&α))⁆ 593 | ⁅a^+_2⁆ 594 | ⁅(a|b|c)⁆ 595 | ⁅|a(x,y)/Δx|a≪1\⁆ 596 | ⁅(a + b)^n = ∑1_(k=0)^n▒(n¦k) a^k b^(n-k)⁆ 597 | ⁅a ≠ b⁆ 598 | ⁅a+b\+c⁆ 599 | ⁅_✎(#e01f32&α)^✎(#18a199&β) ✎(#467bc4&γ)⁆ 600 | ⁅+ α_(y z) β_1 y z + α_(y z) β_x x y z - α_(y z) β_y z + α_(y z) β_z y⁆ 601 | ⁅+ β_1 + α_(x y z) x y z β_x x + α_(x y z) x y z β_y y + α_(x y z) x y z β_z z +⁆ 602 | ⁅_1^b ​^a_2⁆ 603 | ⁅`delimited`⁆ 604 | ⁅a ⟕_(a.a=b.b) b⁆ 605 | ⁅∀ A, B, C ∈ 𝒢 ⟹ (A + B) \⌊ C = A \⌊ C + B \⌊ C⁆ 606 | ⁅+ α_(x y) β_1 x y - α_(x y) β_x y + α_(x y) β_y x + α_(x y) β_z x y z⁆ 607 | ⁅1, x, y, z, y z, z x, x y, x y z⁆ 608 | ⁅ⅆx⁆ 609 | ⁅├3(├1((a)┤1)┤3) /= (((a))).⁆ 610 | ⁅ℲBα ℲAβ γ ℲCδ ℲDε⁆ 611 | ⁅+ (α_y β_z - α_x β_y) y z⁆ 612 | ⁅ⅈ²=-1⁆ 613 | ⁅W_δ₁ρ₁σ₂^3β⁆ 614 | ⁅α_(y z) y z β_(y z) y z + α_(y z) y z β_(z x) z x + α_(y z) y z β_(x y) x y + α_(y z) y z β_(x y z) x y z⁆ 615 | ⁅{■(a@b)〗§⁆ 616 | ⁅w_(a^b)⁆ 617 | ⁅a b⁆ 618 | ⁅+ β_1 + α_x z β_x x + α_x z β_y y + α_x z β_z z +⁆ 619 | ⁅A_n \⌊ B_m = ⟨ A_n B_m ⟩_{n-m}⁆ 620 | ⁅(■(1&2&3@4&5&6@7&8&9@10)).⁆ 621 | ⁅(a) + [a) + {a) + ⟨a) + 〖a) + ⌈a) + ⌊a)⁆ 622 | ⁅"𝐯𝑎𝒓𝗂𝗼𝘶𝙨"⁆ 623 | ⁅𝑊^3𝛽_𝛿₁𝜌₂𝜎₃⁆ 624 | ⁅- α_(y z) β_(y z) zy^2z + α_(y z) β_(z x) y 1 x + α_(y z) β_(x y) zy y x + α_(y z) β_(x y z) y x z z y⁆ 625 | ⁅a+{(1]/4⟩ 📌+1 Jⁱ⁼⁵ |_a⁆ 626 | ⁅⫷scripts overhaul end⫸⁆ 627 | ⁅+ (α_1 β_(x y) + α_(x y) β_1 + α_x β_y - α_y β_x + α_x β_(x y z) + α_(x y z) β_z + α_(z x) β_(y z) - α_(y z) β_(z x)) x y⁆ 628 | ⁅[(𝑥₁, 𝑦₁), (𝑥₂, 𝑦₂), ⋯]⁆ 629 | ⁅✎(#e01f32&α)⁄✎(#18a199&β)⁆ 630 | ⁅(_3)F_3⁆ 631 | ⁅a!/b!⁆ 632 | ⁅+ α_x β_1 x + α_x β_x x^2 + α_x β_y x y - α_x β_z z x⁆ 633 | ⁅⏞(x+⋯+x)^(k " times")⁆ 634 | ⁅sinx⁆ 635 | ⁅8 + 6 x y⁆ 636 | ⁅α/β⁆ 637 | ⁅⟡(a)+1⁆ 638 | ⁅("a") ̂ ⫷correct way of entering a non-italicized but diacriticized character⫸⁆ 639 | ⁅+ α_x β_(y z) x y z - α_x β_(z x) z + α_x β_(x y) y + α_x β_(x y z) y z⁆ 640 | ⁅⒨(a&b&c&d@c&d)⁆ 641 | ⁅+ (α_1 β_z + α_x β_1 + α_(z x) β_x - α_x β_(z x) + α_y β_(y z) - α_(y z) β_y - α_(x y) β_(x y z) - α_(x y z) β_(x y)) z⁆ 642 | ⁅= α_x x α_x x + α_x x α_y y + α_x x α_z z + α_y y α_x x + α_y y α_y y + α_y y α_z z + α_z z α_x x + α_z z α_y y + α_z z α_z z⁆ 643 | ⁅▭(E=mc^2)⁆ 644 | ⁅⫷primes overhaul end⫸⁆ 645 | ⁅x y z⁆ 646 | ⁅"So long" ∧ "thanks"   ∀  "🐟🐠🐡".⁆ 647 | ⁅a'⁆ 648 | ⁅K_c (r) = 𝟏_[¼,¾] (r) + ½ × 𝟏_[0,¼] (r)⁆ 649 | ⁅⏟(a^c_b)_(⏟(a^c_b)_(⏟(a^c_b)_(⏟(a^c_b)_(⏟(a^c_b)_(d)))))⁆ 650 | 651 | 656 | 657 | 658 | 659 | 660 | -------------------------------------------------------------------------------- /docs/MathML Intent Attribute.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/docs/MathML Intent Attribute.docx -------------------------------------------------------------------------------- /docs/MathML Intent Attribute.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/docs/MathML Intent Attribute.pdf -------------------------------------------------------------------------------- /docs/Unicode Plain Text Encoding of Mathematics Version 3.2.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/docs/Unicode Plain Text Encoding of Mathematics Version 3.2.docx -------------------------------------------------------------------------------- /docs/doersing-unicodemath-to-mathml.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/docs/doersing-unicodemath-to-mathml.pdf -------------------------------------------------------------------------------- /docs/readme-images/1-hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/docs/readme-images/1-hero.png -------------------------------------------------------------------------------- /docs/readme-images/2-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/docs/readme-images/2-example.png -------------------------------------------------------------------------------- /docs/readme-images/3-examples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/docs/readme-images/3-examples.png -------------------------------------------------------------------------------- /docs/readme-images/4-stars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/docs/readme-images/4-stars.png -------------------------------------------------------------------------------- /docs/readme-images/5-additions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/docs/readme-images/5-additions.png -------------------------------------------------------------------------------- /docs/readme-images/6-playground.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/docs/readme-images/6-playground.jpg -------------------------------------------------------------------------------- /docs/readme-images/7-tooltips.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/docs/readme-images/7-tooltips.gif -------------------------------------------------------------------------------- /docs/sargent-unicodemathml-tech-note.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/docs/sargent-unicodemathml-tech-note.pdf -------------------------------------------------------------------------------- /playground/CopyHtmlToPlainText.html: -------------------------------------------------------------------------------- 1 |  2 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
32 | 33 | 34 | 53 | 54 | -------------------------------------------------------------------------------- /playground/assets/TeX.js: -------------------------------------------------------------------------------- 1 |  2 | /////////////////////////// 3 | // MathML to [La]TeX // 4 | /////////////////////////// 5 | 6 | const accentsAbove = { 7 | '¯': 'overbar', 8 | '\u0300': 'grave', 9 | '\u0301': 'acute', 10 | '\u0302': 'hat', 11 | '\u0303': 'tilde', 12 | '\u0305': 'bar', 13 | '\u0306': 'breve', 14 | '\u0307': 'dot', 15 | '\u0308': 'ddot', 16 | '\u030C': 'check', 17 | '\u20D7': 'vec', 18 | '\u20DB': 'dddot', 19 | '\u20DC': 'ddddot', 20 | '\u23B4': 'overbracket', 21 | '\u23DC': 'overparen', 22 | '\u23DE': 'overbrace', 23 | '\u23E0': 'overshell', 24 | } 25 | 26 | const accentsBelow = { 27 | '\u23B5': 'underbracket', 28 | '\u23DD': 'underparen', 29 | '\u23DF': 'underbrace', 30 | '\u23E1': 'undershell', 31 | '\u2581': 'underbar', 32 | } 33 | 34 | const enclosures = { 35 | 'box': 'boxed', 36 | 'top': '', 37 | 'bottom': '', 38 | 'roundedbox': '', 39 | 'circle': 'circle', 40 | 'longdiv': '', 41 | 'actuarial': '', 42 | 'cancel': 'cancel', 43 | 'bcancel': 'bcancel', 44 | 'xcancel': 'xcancel', 45 | } 46 | 47 | function MathMLtoTeX(mathML) { 48 | const doc = getMathMLDOM(mathML); 49 | return TeX(doc.firstElementChild) 50 | } 51 | 52 | 53 | function checkBracing(str) { 54 | let code = str.codePointAt(0) 55 | if (str.length > 2 && !isOpenDelimiter(str[0]) && str[0] != '\\' || str.length == 2 && code < 0xD800) 56 | str = '{' + str + '}' 57 | return str 58 | } 59 | 60 | function isDigitArg(node) { 61 | if (!node || !node.lastElementChild) 62 | return false 63 | 64 | return node.lastElementChild.nodeName == 'mn' && node.children[1] && 65 | isAsciiDigit(node.children[1].textContent) 66 | } 67 | 68 | function TeX(value, noAddParens) { 69 | // Function called recursively to convert MathML to [La]TeX 70 | if (!value) 71 | return '' 72 | 73 | function unary(node, op) { 74 | // Unary elements have the implied-mrow property 75 | let cNode = node.childElementCount 76 | let ret = nary(node, '', cNode) 77 | 78 | if (!op) 79 | ret = removeOuterParens(ret) 80 | 81 | return op + '{' + ret + '}' 82 | } 83 | 84 | function binary(node, op) { 85 | let reta = checkBracing(TeX(node.firstElementChild)) 86 | let retb = checkBracing(TeX(node.lastElementChild)) 87 | 88 | return reta + op + retb; 89 | } 90 | 91 | function ternary(node, op1, op2) { 92 | let reta = checkBracing(TeX(node.firstElementChild)) 93 | let retb = checkBracing(TeX(node.children[1])) 94 | let retc = checkBracing(TeX(node.lastElementChild)) 95 | 96 | return reta + op1 + retb + op2 + retc 97 | } 98 | 99 | function nary(node, op, cNode) { 100 | let ret = ''; 101 | 102 | for (let i = 0; i < cNode; i++) { 103 | ret += TeX(node.children[i]) 104 | if (i < cNode - 1) 105 | ret += op; 106 | } 107 | return ret; 108 | } 109 | const matrixIntents = { 110 | 'pmatrix': ':parenthesized-matrix', 111 | 'vmatrix': ':determinant', 112 | 'Vmatrix': ':normed-matrix', 113 | 'bmatrix': ':bracketed-matrix', 114 | 'Bmatrix': ':curly-braced-matrix', 115 | } 116 | 117 | let cNode = value.nodeName == '#text' ? 1 : value.childElementCount 118 | let intent 119 | let ret = '' 120 | let val 121 | 122 | switch (value.localName) { 123 | case 'mtable': 124 | let symbol = 'matrix' 125 | intent = value.getAttribute('intent') 126 | if (intent == ':equations') 127 | symbol = 'aligned' 128 | if (value.parentElement.firstElementChild.textContent == '{' && 129 | (value.parentElement.childElementCount == 2 || 130 | !value.parentElement.lastElementChild.textContent) && 131 | value.parentElement.children[1] == value) { 132 | ret = '\\begin{cases}' + nary(value, '\\\\', cNode) + '\\end{cases}' 133 | break 134 | } else if (value.parentElement.hasAttribute('intent')) { 135 | intent = value.parentElement.getAttribute('intent') 136 | 137 | for (const [key, val] of Object.entries(matrixIntents)) { 138 | if (val == intent) { 139 | symbol = key; 140 | break; 141 | } 142 | } 143 | } else if (intent == ':math-paragraph') { 144 | for (let i = 0; i < cNode; i++) { 145 | let node = value.children[i] // or 146 | if (node.nodeName == 'mlabeledtr' || 147 | node.firstElementChild.getAttribute('intent') 148 | == ':equation-label') { 149 | let eq = node.firstElementChild.textContent 150 | if (eq && eq[0] == '(') 151 | eq = eq.substring(1, eq.length - 1) 152 | ret += '\\begin{equation}\\label{eq' + eq + '}' 153 | if (node.childElementCount > 2) 154 | ret += TeX(node.children[1]) + '&' 155 | ret += TeX(value.firstElementChild.lastElementChild) + 156 | '\\end{equation}' 157 | } else { 158 | ret += dump(node) 159 | } 160 | if (i < cNode - 1) 161 | ret += '\\\\' // Separate eqs by \\ 162 | } 163 | break 164 | } else if (cNode == 1 && hasEqLabel(value)) { 165 | // Numbered equation 166 | let eq = value.firstElementChild.firstElementChild.firstElementChild.textContent 167 | if (eq && eq[0] == '(') 168 | eq = eq.substring(1, eq.length - 1) 169 | ret = '\\begin{equation}\\label{eq' + eq + '}' + 170 | TeX(value.firstElementChild.lastElementChild) + '\\end{equation}' 171 | break; 172 | } 173 | ret = '\\begin{' + symbol + '}' + nary(value, '\\\\', cNode) + '\\end{' + symbol + '}' 174 | break; 175 | 176 | case 'mtr': 177 | ret = nary(value, '&', cNode); 178 | break; 179 | 180 | case 'mtd': 181 | ret = nary(value, '', cNode); 182 | if (ret[0] == '&') 183 | ret = ret.substring(1) 184 | break; 185 | 186 | case 'maligngroup': 187 | case 'malignmark': 188 | ret = '&'; 189 | break; 190 | 191 | case 'menclose': 192 | let notation = value.getAttribute('notation') 193 | if (notation && enclosures[notation]) { 194 | ret = unary(value, '\\' + enclosures[notation]); 195 | break; 196 | } 197 | ret = unary(value, '\\boxed'); 198 | break; 199 | 200 | case 'mphantom': 201 | ret = unary(value,'\\phantom'); // Full size, no display 202 | break; 203 | 204 | case 'mpadded': 205 | var op = ''; 206 | var mask = 0; // Compute phantom mask 207 | 208 | if (value.getAttribute('width') === '0') 209 | mask = 2; // fPhantomZeroWidth 210 | if (value.getAttribute('height') === '0') 211 | mask |= 4; // fPhantomZeroAscent 212 | if (value.getAttribute('depth') === '0') 213 | mask |= 8; // fPhantomZeroDescent 214 | 215 | if (value.firstElementChild.nodeName == 'mphantom') { // No display 216 | if (mask == 2) 217 | op = '\\vphantom'; // fPhantomZeroWidth 218 | else if (mask == 12) 219 | op = '\\hphantom'; // fPhantomZeroAscent | fPhantomZeroDescent 220 | ret = op ? op + TeX(value.firstElementChild).substring(8) 221 | : '⟡(' + mask + '&' + TeX(value.firstElementChild.firstElementChild, true) + ')'; 222 | break; 223 | } 224 | const opsShow = {2: '\\hsmash', 4: '\\asmash', 8: '\\dsmash', 12: '\\smash'}; 225 | op = opsShow[mask]; 226 | mask |= 1; // fPhantomShow 227 | 228 | ret = op ? unary(value, op) 229 | : '⟡(' + mask + '&' + TeX(value.firstElementChild, true) + ')'; 230 | break; 231 | 232 | case 'mstyle': 233 | ret = TeX(value.firstElementChild); 234 | val = value.getAttribute('mathcolor') 235 | if (val) 236 | ret = '✎(' + val + '&' + ret + ')'; 237 | val = value.getAttribute('mathbackground') 238 | if (val) 239 | ret = '☁(' + val + '&' + ret + ')'; 240 | break; 241 | 242 | case 'msqrt': 243 | ret = unary(value, '\\sqrt'); 244 | break; 245 | 246 | case 'mroot': 247 | ret = '\\sqrt[' + TeX(value.lastElementChild) + ']{' + 248 | TeX(value.firstElementChild, true) + '}'; 249 | break; 250 | 251 | case 'mfrac': 252 | var op = '\\frac'; 253 | val = value.getAttribute('displaystyle') 254 | if (!val) { 255 | } 256 | val = value.getAttribute('linethickness') 257 | if (val == '0' || val == '0.0pt') { 258 | op = '¦'; 259 | if (value.parentElement.hasAttribute('intent') && 260 | value.parentElement.getAttribute('intent').startsWith('binomial-coefficient') || 261 | value.parentElement.firstElementChild.hasAttribute('title') && 262 | value.parentElement.firstElementChild.getAttribute('title') == 'binomial coefficient') { 263 | op = '\\binom' 264 | } 265 | } 266 | ret = op + '{' + TeX(value.firstElementChild) + '}{' + TeX(value.lastElementChild) + '}' 267 | break; 268 | 269 | case 'msup': 270 | var op = '^'; 271 | if (isPrime(value.lastElementChild.textContent)) 272 | op = ''; 273 | ret = binary(value, op); 274 | 275 | // Check for intent='transpose' 276 | if (value.lastElementChild.getAttribute('intent') == 'transpose') { 277 | let cRet = ret.length; 278 | let code = codeAt(ret, cRet - 2); 279 | if (code != 0x22BA) { // '⊺' 280 | if (code > 0xDC00) 281 | cRet--; // To remove whole surrogate pair 282 | ret = ret.substring(0, cRet - 2) + '^⊺'; 283 | } 284 | } 285 | break; 286 | 287 | case 'mover': 288 | if (value.lastElementChild.nodeName == 'mo') { 289 | let cwAccent = accentsAbove[value.lastElementChild.textContent] 290 | if (cwAccent) { 291 | ret = '\\' + cwAccent + '{' + TeX(value.firstElementChild) + '}' 292 | break 293 | } 294 | } 295 | op = value.hasAttribute('accent') ? '' : '^'; 296 | ret = binary(value, op); 297 | break; 298 | 299 | case 'munder': 300 | if (value.lastElementChild.nodeName == 'mo') { 301 | let cwAccent = accentsBelow[value.lastElementChild.textContent] 302 | if (cwAccent) { 303 | ret = '\\' + cwAccent + '{' + TeX(value.firstElementChild) + '}' 304 | break 305 | } 306 | } 307 | op = value.hasAttribute('accentunder') ? '' : '_'; 308 | if (value.firstElementChild.innerHTML == 'lim') 309 | op = '_'; 310 | ret = binary(value, op); 311 | break; 312 | 313 | case 'msub': 314 | ret = binary(value, '_'); 315 | break; 316 | 317 | case 'munderover': 318 | intent = value.parentElement.getAttribute('intent') 319 | if (!intent || !intent.startsWith(':nary')) { 320 | ret = ternary(value, '┬', '┴'); 321 | break; 322 | } 323 | // Fall through to msubsup 324 | case 'msubsup': 325 | ret = ternary(value, '_', '^'); 326 | break; 327 | 328 | case 'mmultiscripts': 329 | ret = ''; 330 | if (value.children[3].nodeName == 'mprescripts') { 331 | if (value.children[4].nodeName != 'none') 332 | ret = '_' + TeX(value.children[4]); 333 | if (value.children[5].nodeName != 'none') 334 | ret += '^' + TeX(value.children[5]); 335 | if (ret) 336 | ret += ' '; 337 | } 338 | ret += TeX(value.children[0]); 339 | if (value.children[1].nodeName != 'none') 340 | ret += '_' + TeX(value.children[1]); 341 | if (value.children[2].nodeName != 'none') 342 | ret += '^' + TeX(value.children[2]); 343 | break; 344 | 345 | case 'mfenced': 346 | let [opClose, opOpen, opSeparators] = getFencedOps(value) 347 | let cSep = opSeparators.length; 348 | 349 | ret = opOpen; 350 | for (let i = 0; i < cNode; i++) { 351 | ret += TeX(value.children[i]); 352 | if (i < cNode - 1) 353 | ret += i < cSep - 1 ? opSeparators[i] : opSeparators[cSep - 1]; 354 | } 355 | ret += opClose; 356 | break; 357 | 358 | case 'mo': 359 | const opmap = { 360 | '&': '&', 361 | '&fa;': '', 362 | '>': '>', 363 | '<': '<', 364 | ' ': ' ', 365 | '\u2061': '', 366 | '⋯': '⋅⋅⋅', 367 | } 368 | val = value.innerHTML 369 | if (val in opmap) { 370 | ret = opmap[val] 371 | break 372 | } 373 | if (!intent) 374 | intent = value.getAttribute('intent') 375 | if (intent == ':text') { 376 | ret = '\\' + val 377 | break 378 | } 379 | if (val.startsWith('&#') && val.endsWith(';')) { 380 | ret = value.innerHTML.substring(2, val.length - 1); 381 | if (ret[0] == 'x') 382 | ret = '0' + ret; 383 | ret = String.fromCodePoint(ret); 384 | break; 385 | } 386 | if (!ret && value.hasAttribute('title')) { 387 | // The DLMF title attribute implies the following intents 388 | // (see also for 'mi') 389 | switch (value.getAttribute('title')) { 390 | case 'differential': 391 | case 'derivative': 392 | ret = '𝑑'; 393 | break; 394 | case 'binomial coefficient': 395 | val = ''; 396 | } 397 | } 398 | if (!ret) 399 | ret = val 400 | break; 401 | 402 | case 'mi': 403 | if (value.innerHTML.length == 1) { 404 | let c = value.innerHTML 405 | if (!value.hasAttribute('mathvariant')) { 406 | ret = italicizeCharacter(c); 407 | break; 408 | } 409 | var mathstyle = mathvariants[value.getAttribute('mathvariant')]; 410 | if (c in mathFonts && mathstyle in mathFonts[c] && (c < 'Α' || c > 'Ω' && c != '∇')) { 411 | ret = mathFonts[c][mathstyle]; 412 | break; 413 | } 414 | 415 | if (mathstyle == 'mup') { 416 | if (value.hasAttribute('title')) { 417 | // Differential d (ⅆ) appears in 'mo' 418 | switch (value.getAttribute('title')) { 419 | case 'base of natural logarithm': 420 | ret = 'ⅇ'; 421 | break; 422 | case 'imaginary unit': 423 | ret = 'ⅈ'; 424 | break; 425 | } 426 | if (ret) 427 | break; 428 | } 429 | if (c != '∞' && c != '⋯' && !inRange('\u0391', c, '\u03A9')) { 430 | ret = '"' + c + '"'; 431 | break; 432 | } 433 | } 434 | } else if (isFunctionName(value.textContent)) { 435 | ret = '\\' + value.textContent + ' ' 436 | break 437 | } // else fall through 438 | 439 | case 'mn': 440 | ret = value.textContent; 441 | break; 442 | 443 | case 'mtext': 444 | ret = value.textContent.replace(/\"/g, '\\\"') 445 | ret = '\\textrm{' + ret + '}'; 446 | break; 447 | 448 | case 'mspace': 449 | let width = value.getAttribute('width') 450 | if (width) { 451 | for (let i = 0; i < spaceWidths.length; i++) { 452 | if (width == spaceWidths[i]) { 453 | ret = uniSpaces[i]; 454 | break; 455 | } 456 | } 457 | } 458 | break; 459 | } 460 | 461 | if (ret) 462 | return ret 463 | 464 | // TeX children 465 | for (var i = 0; i < cNode; i++) { 466 | let node = value.children[i]; 467 | if (i == 1 && ret == '{' && node.nodeName == 'mtable' && 468 | (value.childElementCount == 2 || !value.lastElementChild.textContent)) { 469 | // \begin{cases}...\end{cases} includes opening brace 470 | ret = '' 471 | } 472 | ret += TeX(node, false, i); 473 | } 474 | 475 | let mrowIntent = value.nodeName == 'mrow' && value.hasAttribute('intent') 476 | ? value.getAttribute('intent') : ''; 477 | 478 | if (mrowIntent) { 479 | if (mrowIntent == ':fenced' && value.childElementCount && 480 | !value.lastElementChild.textContent) { 481 | return !value.firstElementChild.textContent ? '{' + ret + '}' : ret 482 | } 483 | if (mrowIntent.startsWith('absolute-value') || 484 | mrowIntent.startsWith('cardinality')) { 485 | let abs = mrowIntent[0] == 'a' ? '\\abs' : '\\card' 486 | ret = ret.substring(1, ret.length - 1) // Remove '|'s 487 | return abs + '{' + ret + '}' 488 | } 489 | if (mrowIntent.startsWith('binomial-coefficient') || 490 | mrowIntent.endsWith('matrix') || mrowIntent.endsWith('determinant')) { 491 | // Remove enclosing parens for 𝑛⒞𝑘 and bracketed matrices 492 | let i = ret.length - 1 493 | if (ret[0] == '|') // Determinant 494 | return ret.substring(1, i) 495 | if (ret[0] != '(') 496 | return ret 497 | if (ret[i] == ')') 498 | return ret.substring(1, i) 499 | 500 | // Doesn't end with ')'. Scan ret matching parens. If the last 501 | // ')' follows the '⒞' and matches the opening '(', remove them. 502 | let binomial 503 | let cParen = 1 504 | let k = 0 505 | 506 | for (i = 1; i < ret.length - 1; i++) { 507 | switch (ret[i]) { 508 | case '(': 509 | cParen++ 510 | break; 511 | case ')': 512 | cParen-- 513 | if (!cParen) { 514 | if (!binomial) 515 | return ret // E.g., (𝑘−𝑧)⒞𝑧 516 | k = i 517 | } 518 | break; 519 | case '⒞': 520 | binomial = true 521 | break; 522 | } 523 | } 524 | return k ? ret.substring(1, k) + ret.substring(k + 1) : ret 525 | } 526 | if (mrowIntent == ':function' && value.previousElementSibling && 527 | value.firstElementChild && // (in case empty) 528 | value.firstElementChild.nodeName == 'mi' && 529 | value.firstElementChild.textContent < '\u2100' && 530 | value.previousElementSibling.nodeName == 'mi') { 531 | return ' ' + ret; // Separate variable & function name 532 | } 533 | } 534 | return ret; 535 | } 536 | -------------------------------------------------------------------------------- /playground/assets/dictation.js: -------------------------------------------------------------------------------- 1 | (function (root) { 2 | 'use strict'; 3 | // The function dictationToUnicodeMath(dictation) translates English math speech 4 | // (dictation) to UnicodeMath. The function is called by recognition.onresult in 5 | // playgroud.js. The UnicodeMath produced can be converted to MathML by calling 6 | // unicodemathml(). 7 | 8 | const dictationWords = { 9 | // English math dictation dictionary 10 | 'absolute value': '⒜', // \abs 11 | 'alpha': 'α', // α 12 | 'ampersand': '&', // & (for matrix cell separator or eqarray alignments) 13 | 'and': '&', // & (for matrix cell separator) 14 | 'angle bracket': '⟨', // ⟨ (for "bra") 15 | 'approximately equal': '≅', // ≅ 16 | 'arccosine': 'acos⁡', // arc cosine (ends with \u2061--FUNCTAPPLY) 17 | 'arcsine': 'asin⁡', // arc sine 18 | 'arctangent': 'atan⁡', // arc tangent 19 | 'aren\'t': '/', // Treat as "not" 20 | 'array': '■(', // ■ (bare matrix) 21 | 'arrow': '←', // ← 22 | 'as': '_(', // _( (for limit) 23 | 'atop': '¦', // ¦ (for binomial coefficient) 24 | 'back slash': '\\', // Backslash 25 | 'backslash': '\\', // Backslash 26 | 'bar': '\u0305', // Bar combining mark 27 | 'be': 'b', // b (autocorrect misspelled b) 28 | 'begin': '\u3016', // Begin 29 | 'beginning': '\u3016', // Begin (autocorrect misspelled) 30 | 'beta': 'β', // β 31 | 'bold': 'style', // Math bold style 32 | 'bra': '⟨', // ⟨ (for Dirac notation) 33 | 'brace': '{', // { 34 | 'bracket': '[', // [ 35 | 'by': '×', // Times (U+00D7--looks like cross U+2A2F but isn't) 36 | 'cap': 'style', // Capital letter shift 37 | 'capped': 'style', // cap (autocorrect misspelled) 38 | 'cases': 'Ⓒ\u3016', // TeX cases 39 | 'chi': 'χ', // χ 40 | 'choose': '⒞', // TeX binomial coefficient 41 | 'close': '\u3017', // Close TeX cases or other construct 42 | 'closed interval': '[]', // Closed-interval template 43 | 'closed open interval': '[)', // Closed-open-interval template 44 | 'comma': ',', // , 45 | 'complex conjugate': '\"c.c.\"', // c.c. 46 | 'conjugate': '^* ', // complex conjugate asterisk 47 | 'contour integral': '∮', // ∮ 48 | 'cosine': 'cos⁡', // cosine 49 | 'cotangent': 'cot⁡', // cotangent 50 | 'cross': '⨯', // Vector cross product (U+2A2F) 51 | 'cube root': '∛', // Cube root 52 | 'cubed': '³', // Cubed 53 | 'dagger': '^† ', // † accent (adjoint) 54 | 'del': '∇', // ∇ 55 | 'dell': '∇', // ∇ 56 | 'delta': 'δ', // δ 57 | 'derivative of': 'ⅆ', // ⅆ 58 | 'determinant': '⒱(', // \vmatrix (|array|) 59 | 'diffraction': '\u3017', // Appears sometimes instead of 'end fraction' 60 | 'divided by': '/', // Fraction 61 | 'does': '\uFFFF', // (ignore) 62 | 'doesn\'t': '/', // Treat as "not" 63 | 'dot': '\u0307 ', // Dot combining mark 64 | 'dots': '…', // Ellipsis 65 | 'double dot': '\u0308 ', // Double dot combining mark 66 | 'double integral': '∬', // ∬ 67 | 'double struck': 'style', // Math double-struck or open-face style 68 | 'down arrow': '↓', // ↓ 69 | 'eight': '8', // 8 70 | 'eighth': '/8 ', // 1/8 71 | 'eighths': '/8 ', // n/8 72 | 'ellipse': '⬭', // ⬭ enclosure 73 | 'ellipsis': '…', // Ellipsis 74 | 'end': '\u3017', // End 75 | 'enter': '\uFFFF', // (ignore) 76 | 'epsilon': 'ϵ', // ϵ 77 | 'equal': '=', // = 78 | 'equals': '=', // = 79 | 'equation': '\uFFFF', // (ignore) 80 | 'equivalent': '≍', // ≍ 81 | 'eta': 'η', // η 82 | 'factorial': '!', // ! 83 | 'fifth': '/5 ', // 1/5 84 | 'fifths': '/5 ', // n/5 85 | 'five': '5', // 5 86 | 'for all': '∀', // ∀ 87 | 'four': '4', // 4 88 | 'fourth': '/4 ', // 1/4 89 | 'fourth root': '∜', // Fourth root 90 | 'fourths': '/4 ', // n/4 91 | 'fraction': '⍁', // Start fraction 92 | 'fractor': 'style', // Math fraktur style 93 | 'fraktur': 'style', // Math fraktur style 94 | 'from': '_(', // Lower limit 95 | 'gamma': 'γ', // γ 96 | 'goes to': '→', // → 97 | 'greater than': '>', // > 98 | 'grow': '∫', // ∫ (autocorrection) 99 | 'half': '/2 ', // 1/2 100 | 'halves': '/2 ', // n/2 101 | 'hat': '\u0302 ', // Caret combining mark 102 | 'hbar': 'ℏ', // Plank's constant / 2π 103 | 'hyperbolic cosine': 'cosh⁡', // Hyperbolic cosine 104 | 'hyperbolic secant': 'sech⁡', // Hyperbolic secant 105 | 'hyperbolic sine': 'sinh⁡', // Hyperbolic sine 106 | 'identical': '≡', // ≡ 107 | 'identity': '≡', // ≡ (for identity matrix/determinant) 108 | 'if': '\"if \"', // Ordinary-text "if " 109 | 'imaginary part': 'Im⁡', // Imaginary part of complex number 110 | 'in': '∈', // Element of 111 | 'infinity': '∞', // ∞ 112 | 'integral': '∫', // ∫ 113 | 'interval': '][', // Alias for open interval 114 | 'iota': 'ι', // ι 115 | 'is': '\uFFFF', // (ignore) 116 | 'isn\'t': '/', // Treat as "not" 117 | 'italic': 'style', // Math italic style 118 | 'jay': 'j', // (autocorrect misspelled j) 119 | 'kappa': 'κ', // κ 120 | 'kay': 'k', // (autocorrect misspelled k) 121 | 'kent': '⟩', // ⟩ (autocorrect misspelled) 122 | 'ket': '⟩', // ⟩ (for Dirac notation) 123 | 'lambda': 'λ', // λ 124 | 'left angle bracket': '⟨', // ⟨ (for "bra") 125 | 'left arrow': '←', // ← 126 | 'left brace': '{', // {} 127 | 'left bracket': '[', // [] 128 | 'left double arrow': '⇐', // ⇐ 129 | 'left open interval': '(]', // Open-closed-interval template 130 | 'left paren': '(', // () 131 | 'left right arrow': '↔', // ↔ 132 | 'left right double arrow': '⇔', // ⇔ 133 | 'less than': '<', // < 134 | 'letter': '\uFFFF', // (ignore) 135 | 'limit': 'lim⁡', // Limit 136 | 'matrix': '⒨(', // ■ (parenthesized matrix) 137 | 'minus': '−', // - 138 | 'more than': '>', // > 139 | 'mu': 'μ', // μ 140 | 'nabla': '∇', // ∇ 141 | 'next': '@', // @ (for matrix row separator) 142 | 'nine': '9', // 9 143 | 'nineth': '/9 ', // 1/9 144 | 'nineths': '/9 ', // n/9 145 | 'no serif': 'style', // Math sans-serif style (alternate speech) 146 | 'north': 'n', // n (speech translates n to north 😒) 147 | 'not': '/', // / (for negation) 148 | 'nth': '/n ', // nth (for nth derivative) 149 | 'nu': 'ν', // ν 150 | 'of': '▒', // Get naryand 151 | 'okay': 'k', // (autocorrect misspelled k) 152 | 'omega': 'ω', // ω 153 | 'omicron': 'ο', // ο 154 | 'one': '1', // 1 155 | 'open closed interval': '(]', // Open-closed-interval template 156 | 'open face': 'style', // Math double-struck or open-face style 157 | 'open interval': '][', // Open-interval template 158 | 'or': '\uFFFF', // (ignore) 159 | 'over': '/', // Fraction 160 | 'oversea': '/c', // (autocorrect misspelled 'over c') 161 | 'oversee': '/c', // (autocorrect misspelled 'over c') 162 | 'paren': '(', // ( 163 | 'partial': '∂', // ∂ 164 | 'phi': 'ϕ', // ϕ 165 | 'pi': 'π', // π 166 | 'pie': 'π', // π 167 | 'plus': '+', // + 168 | 'power': '\uFFFF', // (ignore) 169 | 'prime': '′', // ′ 170 | 'product': '∏', // ∏ 171 | 'psi': 'ψ', // ψ 172 | 'quote': '\"', // " (for ordinary text) 173 | 'raised': '\uFFFF', // (ignore) 174 | 'real part': 'Re⁡', // Real part of complex number 175 | 'rectangle': '▭', // ▭ enclosure 176 | 'rho': 'ρ', // ρ 177 | 'right angle bracket': '⟩', // ⟩ (for "ket") 178 | 'right arrow': '→', // → 179 | 'right brace': '}', // } 180 | 'right bracket': ']', // ] 181 | 'right double arrow': '⇒', // ⇒ 182 | 'right open interval': '[)', // Closed-open-interval template 183 | 'right paren': ')', // ) 184 | 'root': '⒭', // Root as in "root n of x" 185 | 'sans serif': 'style', // Math sans-serif style 186 | 'script': 'style', // Math script style 187 | 'sea': 'c', // c (autocorrect misspelled) 188 | 'secant': 'sec⁡', // secant 189 | 'second': '/2 ', // For setting up second derivative 190 | 'see': 'c', // c (autocorrect misspelled) 191 | 'seven': '7', // 7 192 | 'seventh': '/7 ', // 1/7 193 | 'sevenths': '/7 ', // n/7 194 | 'si': 'ψ', // ψ (autocorrect misspelled psi) 195 | 'sigh': 'ψ', // ψ (autocorrect misspelled psi) 196 | 'sigma': 'σ', // σ 197 | 'sign': 'sin⁡', // sine 198 | 'sine': 'sin⁡', // sine 199 | 'six': '6', // 6 200 | 'sixth': '/6 ', // 1/6 201 | 'sixths': '/6 ', // n/6 202 | 'size': '\uFFFF', // (ignore) (for "of size n") 203 | 'some': '∑', // Summation (autocorrect misspelled) 204 | 'space': ' ', // Space (to build something up) 205 | 'sqrt': '√', // Square root 206 | 'square root': '√', // Square root 207 | 'squared': '²', // Squared 208 | 'sub': '_', // Subscript 209 | 'sum': '∑', // Summation 210 | 'summation': '∑', // Summation 211 | 'surface integral': '∯', // ∯ 212 | 'tangent': 'tan⁡', // tangent 213 | 'tau': 'τ', // τ 214 | 'ten': '10', // 10 215 | 'the': '\uFFFF', // (ignore) 216 | 'there exists': '∃', // ∃ 217 | 'therefore': '∴', // ∴ 218 | 'theta': 'θ', // θ 219 | 'third': '/3 ', // 1/3 220 | 'thirds': '/3 ', // n/3 221 | 'three': '3', // 3 222 | 'tilde': '\u0303 ', // Tilde combining mark 223 | 'times': '×', // Times (U+00D7--looks like cross U+2A2F but isn't) 224 | 'to': '^', // Upper limit or power 225 | 'too': '2', // 2 (autocorrect misspelling) 226 | 'top': '¦', // → "atop" if preceded by 'a' (for binomial coefficient) 227 | 'two': '2', // 2 228 | 'up arrow': '↑', // ↑ 229 | 'upsilon': 'υ', // υ 230 | 'var epsilon': '𝜀', // 𝜀 231 | 'var phi': 'φ', // φ 232 | 'var theta': 'ϑ', // ϑ 233 | 'vertical bar': '|', // For absolute value (see also "abs" '⒜') 234 | 'with respect to': '/ⅆ', // As in "derivative of f with respect to x" 235 | 'wp': '℘', // ℘ 236 | 'wrt': '/ⅆ', // (speed up debugging involving "with respect to") 237 | 'xi': 'ξ', // ξ 238 | 'zero': '0', // 0 239 | 'zeta': 'ζ', // ζ 240 | }; 241 | 242 | const keys = Object.keys(dictationWords); 243 | 244 | function resolveDW(dictation) { 245 | // Get longest dictationWords match 246 | let cchWord = 0 247 | let cKeys = keys.length; 248 | let iMax = cKeys - 1; 249 | let iMid; 250 | let iMin = 0; 251 | let key 252 | let matchKey = ''; 253 | 254 | // Find length of first word 255 | for (; cchWord < dictation.length && (isLcAscii(dictation[cchWord]) || dictation[cchWord] == '\''); cchWord++) 256 | ; 257 | 258 | let firstWord = dictation.substring(0, cchWord); 259 | 260 | do { // Binary search for a match 261 | iMid = Math.floor((iMin + iMax) / 2); 262 | key = keys[iMid]; 263 | if (key.startsWith(firstWord) && 264 | (key.length <= cchWord || key[cchWord] == ' ')) { 265 | matchKey = key; 266 | break; 267 | } 268 | if (dictation < key) 269 | iMax = iMid - 1; 270 | else 271 | iMin = iMid + 1; 272 | } while (iMin <= iMax); 273 | 274 | if (matchKey == '') 275 | return ''; // Not in dictionary 276 | 277 | 278 | // matchKey matches first word. Check for matches preceding iMid 279 | for (let j = iMid - 1; j >= 0; j--) { 280 | key = keys[j]; 281 | if (!key.startsWith(firstWord)) 282 | break; 283 | if (dictation.startsWith(key)) { 284 | //console.log("Dictation match: " + key); 285 | return key; 286 | } 287 | } 288 | // Check for matches following iMid 289 | for (let j = iMid + 1; j < cKeys; j++) { 290 | key = keys[j]; 291 | if (!key.startsWith(firstWord)) 292 | break; 293 | if (dictation.startsWith(key)) { 294 | //console.log("Dictation match: " + key); 295 | return key; 296 | } 297 | } 298 | //console.log("Longest match key = " + matchKey); 299 | return matchKey; 300 | } 301 | 302 | function isAsciiDigit(ch) { return /[0-9]/.test(ch); } 303 | function isIntegral(ch) { return '∫∬∭⨌∮∯∰∱⨑∲∳⨍⨎⨏⨕⨖⨗⨘⨙⨚⨛⨜⨒⨓⨔'.includes(ch); } 304 | function isLcAscii(ch) { return /[a-z]/.test(ch); } 305 | function isLcGreek(ch) { return /[α-ϵ]/.test(ch); } 306 | function isMatrix(ch) { return '⒨⒱'.includes(ch); } 307 | function isNary(ch) { return '∑⅀⨊∏∐⨋∫∬∭⨌∮∯∰∱⨑∲∳⨍⨎⨏⨕⨖⨗⨘⨙⨚⨛⨜⨒⨓⨔⋀⋁⋂⋃⨃⨄⨅⨆⨀⨁⨂⨉⫿'.includes(ch); } 308 | 309 | // The following includes most relational (R) operators in 310 | // https://www.unicode.org/Public/math/revision-15/MathClassEx-15.txt 311 | const relationalRanges = [ 312 | [0x003C, 0x003E], [0x2190, 0x21FF], [0x2208, 0x220D], [0x221D, 0x221D], 313 | [0x2223, 0x2226], [0x2223, 0x2226], [0x2234, 0x2237], [0x2239, 0x223D], 314 | [0x2241, 0x228B], [0x228F, 0x2292], [0x22A2, 0x22B8], [0x22D4, 0x22FF], 315 | [0x27F0, 0x297F], [0x2B00, 0x2B11], [0x2B30, 0x2B4C], [0x2B95, 0x2B95] 316 | ]; 317 | 318 | function isRelational(ch) { 319 | let n = ch.codePointAt(0); 320 | 321 | for (let i = 0; i < relationalRanges.length; i++) { 322 | let pair = relationalRanges[i]; 323 | if (n < pair[0]) 324 | return false; 325 | if (n <= pair[1]) 326 | return true; 327 | } 328 | return false; 329 | } 330 | 331 | function getMathAlphanumeric(ch, mathStyle) { 332 | // Return ch in the math style described by mathStyle 333 | let style = ''; 334 | 335 | if (mathStyle.includes('cap')) { 336 | ch = ch.toUpperCase(); 337 | } 338 | if (mathStyle.includes('script')) { 339 | style = mathStyle.includes('bold') ? 'mbfscr' : 'mscr'; 340 | } else if (mathStyle.includes('fraktur') || mathStyle.includes('fractor')) { 341 | style = mathStyle.includes('bold') ? 'mbffrak' : 'mfrak'; 342 | } else if (mathStyle.includes('sans') || mathStyle.includes('no serif')) { 343 | style = 'sans'; // Finish below 344 | } 345 | else if (mathStyle.includes('monospace')) { 346 | style = 'mtt'; 347 | } 348 | else if (mathStyle.includes('double struck') || mathStyle.includes('open face')) { 349 | style = 'Bbb'; 350 | } 351 | if (!style || style == 'sans') { // Finish 'sans' and serif 352 | if (mathStyle.includes('bold')) { 353 | style = (mathStyle.includes('italic') ? 'mbfit' : 'mbf') + style; 354 | } 355 | if (mathStyle.includes('italic')) { 356 | style = 'mit' + style; 357 | } 358 | } 359 | return (ch in mathFonts && style in mathFonts[ch]) 360 | ? mathFonts[ch][style] : ch; 361 | } 362 | 363 | function dictationToUnicodeMath(dictation) { 364 | // Translate dictated text to UnicodeMath 365 | let i 366 | let d = '' 367 | 368 | // First convert dictation to lower case without '.,?' unless a digit 369 | // precedes '.' or ',' 370 | for (i = 0; i < dictation.length; i++) { 371 | let ch = dictation[i] 372 | if (isUcAscii(ch)) { 373 | d += ch.toLowerCase() 374 | } else if (ch == '.' || ch == ',') { 375 | if (i && isAsciiDigit(dictation[i - 1])) 376 | d += ch 377 | } else if (ch != '?') 378 | d += ch 379 | } 380 | dictation = d 381 | 382 | let cDerivOrder = 0; 383 | let ch = ''; 384 | let ch2 = ''; 385 | let chPrev = ''; 386 | let derivClose = false; 387 | let derivOrder = 0; 388 | let derivPartial = false; 389 | let fraction = 0 390 | let integral = false; 391 | let interval = 0; 392 | let iSubSup = 0; 393 | let limit = false; 394 | let mathStyle = []; 395 | let nary = ''; 396 | 397 | for (i = 0; i < dictation.length; chPrev = ch) { 398 | ch = dictation[i] 399 | if (i >= 2) 400 | ch2 = dictation[i - 2]; 401 | 402 | if (ch == ' ' && (!isAsciiDigit(chPrev) || ch2 != '^' || nary == 'naryLim')) { 403 | // Delete space except following "^" which may need 404 | // a space to build up the superscript. Restore the space below 405 | // if it's needed to separate a letter from a function name. 406 | dictation = dictation.substring(0, i) + dictation.substring(i + 1); 407 | continue; 408 | } 409 | if (!chPrev && mathStyle.length && (isLcAscii(ch) || isAsciiDigit(ch)) && 410 | (i == dictation.length - 1 || !isLcAscii(dictation[i + 1]))) { 411 | ch = getMathAlphanumeric(ch, mathStyle); 412 | dictation = dictation.substring(0, i) + ch + dictation.substring(i + 1); 413 | i += ch.length; 414 | mathStyle = []; 415 | continue; 416 | } 417 | if (isLcAscii(ch) && isLcAscii(chPrev)) { 418 | let key = resolveDW(dictation.substring(i - 1)); 419 | if (key != '') { 420 | var unicodeMath = dictationWords[key]; 421 | let b = ''; 422 | let iRem = i - 1 + key.length; 423 | 424 | if (unicodeMath == '\uFFFF' || 425 | unicodeMath == '▒' && '√∛∜⒜⒨⒭⒱('.includes(ch2) || 426 | key == 'from' && (ch2 == ']' || ch2 == '[' || ch2 == '(') || 427 | key == 'to' && isRelational(ch2)) { 428 | unicodeMath = ''; // Ignore word 429 | } else if ((ch2 == '\u3017' || ch2 == '&') && 430 | unicodeMath[unicodeMath.length - 1] == '(') { 431 | i--; 432 | unicodeMath = ')'; 433 | } else if (interval) { // Mathematical interval fix-ups 434 | if (unicodeMath == '][') { 435 | // Finalize the interval-text order 436 | let chClose = dictation[interval]; // Save closing char & delete it 437 | dictation = dictation.substring(0, interval) + dictation.substring(interval + 1); 438 | i--; 439 | if (ch2 == '\u3017' || ch2 == '&') 440 | i--; // Will delete '\u3017' ('end') or 'and' 441 | unicodeMath = chClose; // Insert closing char at end 442 | interval = 0; // Terminate interval mode 443 | } else if (unicodeMath == '^') { 444 | unicodeMath = ','; // 'to' → ',' 445 | } 446 | } else if (key.endsWith('interval')) { // Start interval 447 | interval = i; // Remember start-interval location for final fix-up 448 | } else if (unicodeMath == 'style') { 449 | mathStyle.push(key); // Collect math style words 450 | unicodeMath = ''; // Will delete control word 451 | } else if (unicodeMath == '⍁') { 452 | if (ch2 == '\u3017' || ch2 == '&') { 453 | fraction--; 454 | unicodeMath = ''; 455 | if (ch2 == '&') { // 'and' should be 'end' 456 | unicodeMath = '\u3017' 457 | i-- 458 | } 459 | } else { 460 | fraction++; 461 | } 462 | } 463 | 464 | let cchUni = unicodeMath.length; 465 | 466 | if (dictation[iRem] == ' ') 467 | iRem++; // Remove space following key 468 | 469 | if (cchUni) { 470 | if (unicodeMath[cchUni - 1] == '\u2061') { 471 | if (isLcAscii(ch2)) { 472 | // Insert a space before math function 473 | b = ' '; // E.g., bsin → b sin 474 | } 475 | if (unicodeMath == 'lim\u2061') { 476 | unicodeMath = 'lim '; // Replace 2061 by ' ' 477 | limit = true; 478 | } 479 | } else if (cchUni == 3 && unicodeMath[0] == '/' && unicodeMath[2] == ' ') { 480 | if (ch2 == '^') { 481 | unicodeMath = unicodeMath.substring(1); // E.g., "^/n " → "^n " 482 | } else if (isAsciiDigit(ch2) && isAsciiDigit(unicodeMath[1])) { 483 | unicodeMath = getUnicodeFraction(ch2, unicodeMath[1]); 484 | i--; 485 | } 486 | } else if (key == 'to' && nary == 'naryLim') { 487 | unicodeMath = ')^' // End lower limit; start upper 488 | let k = dictation.lastIndexOf('_(', i) 489 | if (k != -1 && 490 | !needParens(dictation.substring(k + 2, i - 1))) { 491 | unicodeMath = '^' // Don't need parens 492 | i-- // Remove opening paren 493 | iRem-- 494 | dictation = dictation.substring(0, k + 1) + 495 | dictation.substring(k + 2) 496 | } 497 | } else if (unicodeMath == '▒') { 498 | if (limit) { 499 | unicodeMath = ") "; // End limit subscript 500 | limit = false; 501 | } else if (nary == 'naryLim') { 502 | unicodeMath = ' ' 503 | nary = 'naryand' // End nary limits 504 | let k = dictation.lastIndexOf('^', i) 505 | if (k != -1 && 506 | needParens(dictation.substring(k + 1, i - 1))) { 507 | // Parenthesize compound upper limit 508 | iRem++ 509 | i++ 510 | dictation = dictation.substring(0, k +1) + '(' + 511 | dictation.substring(k + 1) 512 | unicodeMath = ') ' 513 | } 514 | } else if (derivOrder) { 515 | unicodeMath = '('; // E.g., df( 516 | derivClose = true; // Queue up corresponding ')' 517 | } else if (ch2 == '\u2061') { 518 | unicodeMath = '⒡'; 519 | } 520 | } else if (mathStyle.length && (isAsciiDigit(unicodeMath) || 521 | isLcGreek(unicodeMath))) { 522 | unicodeMath = getMathAlphanumeric(unicodeMath, mathStyle); 523 | mathStyle = []; 524 | } else if (ch2 == 'h' && key == 'bar') { 525 | unicodeMath = 'ℏ'; // 'h bar' → ℏ 526 | i--; 527 | } else if (key == 'end' && ch2 == '^') { 528 | unicodeMath = 'n'; // Autocorrect 'end' to 'n' 529 | } else if (key == 'derivative of') { 530 | derivClose = derivPartial = false; 531 | derivOrder = 1; 532 | let j = i; 533 | if (ch2 == '∂') { 534 | unicodeMath = ''; 535 | derivPartial = true; 536 | j--; 537 | } 538 | if (j > 3 && dictation[j - 2] == ' ' && dictation[j - 4] == '/') { 539 | // E.g., "/2 ⅆ" → "ⅆ^2 " 540 | derivOrder = dictation[j - 3]; 541 | unicodeMath = (derivPartial ? '∂^' : 'ⅆ^') + derivOrder + ' '; 542 | j -= 3; 543 | i = j; 544 | } 545 | } else if (derivOrder && unicodeMath == '/ⅆ') { 546 | unicodeMath = derivClose ? ')/' : '/'; 547 | unicodeMath += derivPartial ? '∂' : 'ⅆ'; 548 | derivClose = derivPartial = false; 549 | if (derivOrder >= '2') 550 | cDerivOrder = 2; // Countdown for denominator derivative order 551 | } 552 | else if (unicodeMath == '\\') { // Include TeX control word 553 | for (; iRem < dictation.length && isLcAscii(dictation[iRem]); iRem++) { 554 | unicodeMath += dictation[iRem]; 555 | } 556 | if (dictation[iRem] == ' ') { 557 | unicodeMath += ' '; 558 | iRem++; 559 | } 560 | } else if (isMatrix(unicodeMath[0]) && 561 | (ch2 == '≡' || i >= 3 && isAsciiDigit(ch2) && dictation[i - 3] == '×')) { 562 | unicodeMath = unicodeMath[0]; 563 | if (ch2 == '≡') i--; // Identity matrix: delete '≡' 564 | } else if (unicodeMath == '/' && fraction) { 565 | unicodeMath = '&'; // For ⍁...&...〗 fraction construct 566 | } else if (unicodeMath == '^') { 567 | iSubSup++; 568 | } else if (unicodeMath == '_') { 569 | iSubSup--; 570 | } 571 | } 572 | if (cDerivOrder > 0) { 573 | cDerivOrder--; 574 | if (!cDerivOrder) { // E.g., to get "∂^2 f(θ)/∂θ^2 " 575 | unicodeMath += '^' + derivOrder + ' '; 576 | } 577 | } 578 | dictation = dictation.substring(0, i - 1) + b + unicodeMath + dictation.substring(iRem); 579 | cchUni = unicodeMath.length; 580 | i += cchUni - 1; 581 | ch = 0; // To set chPrev = 0 582 | if (cchUni != 1) continue; 583 | 584 | if (isNary(unicodeMath)) { 585 | nary = 'naryLim'; 586 | integral = isIntegral(unicodeMath); 587 | continue; 588 | } 589 | continue; 590 | } 591 | if (isAsciiDigit(ch2) && chPrev == 't' && ch == 'h') { 592 | continue; // E.g., delete "th" in "4th" 593 | } 594 | } // (isLcAscii(ch) && isLcAscii(chPrev)) 595 | 596 | if (interval && ch2 == '(' && i > 2) { 597 | dictation = dictation.substring(0, i - 3) + dictation.substring(i - 1); 598 | i -= 2; 599 | } 600 | 601 | if (cDerivOrder > 0 && !isLcAscii(dictation[i])) { 602 | cDerivOrder = 0; // E.g., to get "ⅆ^2 f(x)/ⅆx^2 " 603 | unicodeMath = '^' + derivOrder; 604 | dictation = dictation.substring(0, i) + unicodeMath + dictation.substring(i); 605 | i += unicodeMath.length; 606 | } 607 | if (ch == 'd' && integral) { 608 | ch = 'ⅆ'; 609 | if (iSubSup > 0) { 610 | iSubSup--; 611 | ch = ' ⅆ'; 612 | } 613 | integral = false; 614 | dictation = dictation.substring(0, i) + ch + dictation.substring(i + 1); 615 | } else if (ch == '/' && fraction) { 616 | // Use ⍁...&...〗 fraction construct to satisfy peg processing 617 | dictation = dictation.substring(0, i) + '&' + dictation.substring(i + 1); 618 | } 619 | if (nary == 'naryAnd') nary = ''; 620 | i++; 621 | } // for loop over dictation 622 | 623 | // Polish the UnicodeMath extracted from dictation. Specifically, convert 624 | // ASCII and lower-case Greek letters to math italic unless they comprise 625 | // function names, and perform negation, mapped-pair, Unicode-fraction, and 626 | // Unicode digit sub/superscript conversions. These conversions aren't 627 | // needed for UnicodeMath converters, but they make the UnicodeMath look 628 | // more like a mathematical notation, which is nice for use in email, 629 | // programs, and plain-text applications in general. 630 | let result = dictation 631 | let quote = false // No conversions inside double quotes 632 | let result1 = '' // Collects polished UnicodeMath 633 | ch = '' // No previous char 634 | 635 | for (let i = 0; i < result.length; i++) { 636 | chPrev = ch 637 | ch = result[i] 638 | if (ch == '"') { 639 | quote = !quote 640 | result1 += ch 641 | } else if (quote) { 642 | result1 += ch 643 | } else if (isLcAscii(ch) || isUcAscii(ch)) { 644 | let fn = ch 645 | let j = i + 1 646 | for (; j < result.length; j++) { 647 | if (!isLcAscii(result[j]) && !isUcAscii(result[j])) 648 | break; 649 | fn += result[j] 650 | } 651 | if (result[j] == '\u2061' || isFunctionName(fn) || chPrev == '\\') 652 | result1 += fn 653 | else 654 | result1 += italicizeCharacters(fn) 655 | i = j - 1 656 | } else { 657 | ch = italicizeCharacter(ch); // Might be lc Greek 658 | if (ch == result[i]) { // Isn't 659 | if (result.length > i + 1) { 660 | // Convert eg '^2 ' to '²' 661 | let delim = result.length > i + 2 ? result[i + 2] : ' '; 662 | let chScriptDigit = getSubSupDigits(result, i + 1, delim) 663 | if (chScriptDigit) { 664 | result1 += chScriptDigit; 665 | i += (delim == ' ' && result.length > i + 2) ? 2 : 1 666 | continue 667 | } 668 | } 669 | if (ch in mappedSingle) 670 | ch = mappedSingle[ch] 671 | if (result.length > i + 2 && isAsciiDigit(ch) && 672 | result[i + 1] == '/' && isAsciiDigit(result[i + 2]) && 673 | !isAsciiDigit(chPrev) && (result.length == i + 3 || 674 | !isAlphanumeric(result[i + 3]))) { 675 | // Convert, e.g., 1/3 to ⅓ 676 | ch = getUnicodeFraction(ch, result[i + 2]) 677 | i += 2 678 | } else if (result.length > i + 1) { 679 | if (ch == '/' && result[i + 1] in negs) { 680 | // Negation conversion 681 | ch = negs[result[i + 1]] 682 | i++ 683 | } else if (chPrev + ch in mappedPair) { 684 | // Mapped-pair conversion 685 | ch = mappedPair[chPrev + ch] 686 | result1 = result1.substring(0, result1.length - 1) 687 | } 688 | } 689 | } 690 | result1 += ch 691 | } 692 | } 693 | return result1 694 | } 695 | 696 | root.dictationToUnicodeMath = dictationToUnicodeMath; 697 | 698 | })(this) 699 | -------------------------------------------------------------------------------- /playground/assets/lib/latinmodern/1.959/GUST-FONT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | % This is a preliminary version (2006-09-30), barring acceptance from 2 | % the LaTeX Project Team and other feedback, of the GUST Font License. 3 | % (GUST is the Polish TeX Users Group, http://www.gust.org.pl) 4 | % 5 | % For the most recent version of this license see 6 | % http://www.gust.org.pl/fonts/licenses/GUST-FONT-LICENSE.txt 7 | % or 8 | % http://tug.org/fonts/licenses/GUST-FONT-LICENSE.txt 9 | % 10 | % This work may be distributed and/or modified under the conditions 11 | % of the LaTeX Project Public License, either version 1.3c of this 12 | % license or (at your option) any later version. 13 | % 14 | % Please also observe the following clause: 15 | % 1) it is requested, but not legally required, that derived works be 16 | % distributed only after changing the names of the fonts comprising this 17 | % work and given in an accompanying "manifest", and that the 18 | % files comprising the Work, as listed in the manifest, also be given 19 | % new names. Any exceptions to this request are also given in the 20 | % manifest. 21 | % 22 | % We recommend the manifest be given in a separate file named 23 | % MANIFEST-.txt, where is some unique identification 24 | % of the font family. If a separate "readme" file accompanies the Work, 25 | % we recommend a name of the form README-.txt. 26 | % 27 | % The latest version of the LaTeX Project Public License is in 28 | % http://www.latex-project.org/lppl.txt and version 1.3c or later 29 | % is part of all distributions of LaTeX version 2006/05/20 or later. 30 | 31 | -------------------------------------------------------------------------------- /playground/assets/lib/latinmodern/1.959/otf/latinmodern-math.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/playground/assets/lib/latinmodern/1.959/otf/latinmodern-math.otf -------------------------------------------------------------------------------- /playground/assets/lib/latinmodern/1.959/webfont.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'LM Math'; 3 | font-weight: 400; 4 | font-style: normal; 5 | src: url('otf/latinmodern-math.otf') format('opentype'); 6 | } 7 | -------------------------------------------------------------------------------- /playground/assets/lib/mathjax/3/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /playground/assets/lib/mathjax/3/README.md: -------------------------------------------------------------------------------- 1 | # MathJax 2 | ## Beautiful math in all browsers 3 | 4 | ![GitHub release version](https://img.shields.io/github/v/release/mathjax/MathJax-src.svg?sort=semver) 5 | ![GitHub release version (v2)](https://img.shields.io/github/package-json/v/mathjax/MathJax/legacy-v2.svg?label=release-v2) 6 | ![NPM version](https://img.shields.io/npm/v/mathjax.svg?style=flat) 7 | ![powered by NumFOCUS](https://img.shields.io/badge/powered%20by-NumFOCUS-orange.svg?style=flat) 8 | ![jsdelivr rank](https://flat.badgen.net/jsdelivr/rank/npm/mathjax?color=green) 9 | ![jsDelivr hits (npm)](https://img.shields.io/jsdelivr/npm/hm/mathjax) 10 | ![npm monthly downloads (full)](https://img.shields.io/npm/dm/mathjax?label=npm) 11 | ![npm total downloads](https://img.shields.io/npm/dt/mathjax.svg?style=flat&label=npm%20total) 12 | 13 | MathJax is an open-source JavaScript display engine for LaTeX, MathML, 14 | and AsciiMath notation that works in all modern browsers. It was 15 | designed with the goal of consolidating the recent advances in web 16 | technologies into a single, definitive, math-on-the-web platform 17 | supporting the major browsers and operating systems. It requires no 18 | setup on the part of the user (no plugins to download or software to 19 | install), so the page author can write web documents that include 20 | mathematics and be confident that users will be able to view it 21 | naturally and easily. Simply include MathJax and some mathematics in 22 | a web page, and MathJax does the rest. 23 | 24 | Some of the main features of MathJax include: 25 | 26 | - High-quality display of LaTeX, MathML, and AsciiMath notation in HTML pages 27 | 28 | - Supported in most browsers with no plug-ins, extra fonts, or special 29 | setup for the reader 30 | 31 | - Easy for authors, flexible for publishers, extensible for developers 32 | 33 | - Supports math accessibility, cut-and-paste interoperability, and other 34 | advanced functionality 35 | 36 | - Powerful API for integration with other web applications 37 | 38 | See for additional details about MathJax, 39 | and for the MathJax documentation. 40 | 41 | ## MathJax Components 42 | 43 | MathJax version 3 uses files called *components* that contain the 44 | various MathJax modules that you can include in your web pages or 45 | access on a server through NodeJS. Some components combine all the 46 | pieces you need to run MathJax with one or more input formats and a 47 | particular output format, while other components are pieces that can 48 | be loaded on demand when needed, or by a configuration that specifies 49 | the pieces you want to combine in a custom way. For usage 50 | instructions, see the [MathJax documentation](https://docs.mathjax.org). 51 | 52 | Components provide a convenient packaging of MathJax's modules, but it 53 | is possible for you to form your own custom components, or to use 54 | MathJax's modules directly in a node application on a server. There 55 | are [web examples](https://github.com/mathjax/MathJax-demos-web) 56 | showing how to use MathJax in web pages and how to build your own 57 | components, and [node 58 | examples](https://github.com/mathjax/MathJax-demos-node) illustrating 59 | how to use components in node applications or call MathJax modules 60 | directly. 61 | 62 | ## What's in this Repository 63 | 64 | This repository contains only the component files for MathJax, not the 65 | source code for MathJax (which are available in a separate [MathJax 66 | source repository](https://github.com/mathjax/MathJax-src/)). These 67 | component files are the ones served by the CDNs that offer MathJax to 68 | the web. In version 2, the files used on the web were also the source 69 | files for MathJax, but in version 3, the source files are no longer on 70 | the CDN, as they are not what are run in the browser. 71 | 72 | The components are stored in the `es5` directory, and are in ES5 format 73 | for the widest possible compatibility. In the future, we may make an 74 | `es6` directory containing ES6 versions of the components. 75 | 76 | ## Installation and Use 77 | 78 | ### Using MathJax components from a CDN on the web 79 | 80 | If you are loading MathJax from a CDN into a web page, there is no 81 | need to install anything. Simply use a `script` tag that loads 82 | MathJax from the CDN. E.g., 83 | 84 | ``` html 85 | 86 | ``` 87 | 88 | See the [MathJax 89 | documentation](https://docs.mathjax.org/en/latest/index.html#browser-components), 90 | the [MathJax Web Demos](https://github.com/mathjax/MathJax-demos-web), 91 | and the [MathJax Component 92 | Repository](https://github.com/mathjax/MathJax-demos-web) for more information. 93 | 94 | ### Hosting your own copy of the MathJax Components 95 | 96 | If you want to host MathJax from your own server, you can do so by 97 | installing the `mathjax` package using `npm` and moving the `es5` 98 | directory to an appropriate location on your server: 99 | 100 | ``` bash 101 | npm install mathjax@3 102 | mv node_modules/mathjax/es5 /mathjax 103 | ``` 104 | 105 | Note that we are still making updates to version 2, so include `@3` 106 | when you install, since the latest chronological version may not be 107 | version 3. 108 | 109 | Alternatively, you can get the files via GitHub: 110 | 111 | ``` bash 112 | git clone https://github.com/mathjax/MathJax.git mj-tmp 113 | mv mj-tmp/es5 /mathjax 114 | rm -rf mj-tmp 115 | ``` 116 | 117 | Then (in either case) you can use a script tag like the following: 118 | 119 | ``` html 120 | 121 | ``` 122 | 123 | where `` is replaced by the URL to the location 124 | where you moved the MathJax files above. 125 | 126 | See the 127 | [documentation](https://docs.mathjax.org/en/latest/web/hosting.html) 128 | for details. 129 | 130 | ### Using MathJax components in a node application 131 | 132 | To use MathJax components in a node application, install the `mathjax` package: 133 | 134 | ``` bash 135 | npm install mathjax@3 136 | ``` 137 | 138 | (we are still making updates to version 2, so you should include `@3` 139 | since the latest chronological version may not be version 3). 140 | 141 | Then require `mathjax` within your application: 142 | 143 | ```js 144 | require('mathjax').init({ ... }).then((MathJax) => { ... }); 145 | ``` 146 | 147 | where the first `{ ... }` is a MathJax configuration, and the second 148 | `{ ... }` is the code to run after MathJax has been loaded. E.g. 149 | 150 | ```js 151 | require('mathjax').init({ 152 | loader: {load: ['input/tex', 'output/svg']} 153 | }).then((MathJax) => { 154 | const svg = MathJax.tex2svg('\\frac{1}{x^2-1}', {display: true}); 155 | console.log(MathJax.startup.adaptor.outerHTML(svg)); 156 | }).catch((err) => console.log(err.message)); 157 | ``` 158 | 159 | **Note:** this technique is for node-based application only, not for 160 | browser applications. This method sets up an alternative DOM 161 | implementation, which you don't need in the browser, and tells MathJax 162 | to use node's `require()` command to load external modules. This 163 | setup will not work properly in the browser, even if you webpack it or 164 | bundle it in other ways. 165 | 166 | See the 167 | [documentation](https://docs.mathjax.org/en/latest/index.html#server-nodejs) 168 | and the [MathJax Node 169 | Repository](https://github.com/mathjax/MathJax-demos-node) for more details. 170 | 171 | ## Reducing the Size of the Components Directory 172 | 173 | Since the `es5` directory contains *all* the component files, so if 174 | you are only planning one use one configuration, you can reduce the 175 | size of the MathJax directory by removing unused components. For 176 | example, if you are using the `tex-chtml.js` component, then you can 177 | remove the `tex-mml-chtml.js`, `tex-svg.js`, `tex-mml-svg.js`, 178 | `tex-chtml-full.js`, and `tex-svg-full.js` configurations, which will 179 | save considerable space. Indeed, you should be able to remove 180 | everything other than `tex-chtml.js`, and the `input/tex/extensions`, 181 | `output/chtml/fonts/woff-v2`, `adaptors`, `a11y`, and `sre` 182 | directories. If you are using the results only on the web, you can 183 | remove `adaptors` as well. 184 | 185 | If you are not using A11Y support (e.g., speech generation, or 186 | semantic enrichment), then you can remove `a11y` and `sre` as well 187 | (though in this case you may need to disable the assistive tools in 188 | the MathJax contextual menu in order to avoid MathJax trying to load 189 | them when they aren't there). 190 | 191 | If you are using SVG rather than CommonHTML output (e.g., `tex-svg.js` 192 | rather than `tex-chtml.js`), you can remove the 193 | `output/chtml/fonts/woff-v2` directory. If you are using MathML input 194 | rather than TeX (e.g., `mml-chtml.js` rather than `tex-chtml.js`), 195 | then you can remove `input/tex/extensions` as well. 196 | 197 | 198 | ## The Component Files and Pull Requests 199 | 200 | The `es5` directory is generated automatically from the contents of the 201 | MathJax source repository. You can rebuild the components using the 202 | command 203 | 204 | ``` bash 205 | npm run make-es5 --silent 206 | ``` 207 | 208 | Note that since the contents of this repository are generated 209 | automatically, you should not submit pull requests that modify the 210 | contents of the `es5` directory. If you wish to submit a modification 211 | to MathJax, you should make a pull request in the [MathJax source 212 | repository](https://github.com/mathjax/MathJax-src). 213 | 214 | ## MathJax Community 215 | 216 | The main MathJax website is , and it includes 217 | announcements and other important information. A [MathJax user 218 | forum](http://groups.google.com/group/mathjax-users) for asking 219 | questions and getting assistance is hosted at Google, and the [MathJax 220 | bug tracker](https://github.com/mathjax/MathJax/issues) is hosted 221 | at GitHub. 222 | 223 | Before reporting a bug, please check that it has not already been 224 | reported. Also, please use the bug tracker (rather than the help 225 | forum) for reporting bugs, and use the user's forum (rather than the 226 | bug tracker) for questions about how to use MathJax. 227 | 228 | ## MathJax Resources 229 | 230 | * [MathJax Documentation](https://docs.mathjax.org) 231 | * [MathJax Components](https://github.com/mathjax/MathJax) 232 | * [MathJax Source Code](https://github.com/mathjax/MathJax-src) 233 | * [MathJax Web Examples](https://github.com/mathjax/MathJax-demos-web) 234 | * [MathJax Node Examples](https://github.com/mathjax/MathJax-demos-node) 235 | * [MathJax Bug Tracker](https://github.com/mathjax/MathJax/issues) 236 | * [MathJax Users' Group](http://groups.google.com/group/mathjax-users) 237 | 238 | -------------------------------------------------------------------------------- /playground/assets/playground.css: -------------------------------------------------------------------------------- 1 | /***********************\ 2 | * GENERAL * 3 | \***********************/ 4 | 5 | :root { 6 | --main-font: "Helvetica Neue", Helvetica, Arial, sans-serif; 7 | --code-font: "Iosevka Web", PragmataPro, monospace; 8 | --math-font: "LM Math", serif; 9 | --blackish-color: #111; 10 | --verydarkgrayish-color: #222; 11 | --darkgrayish-color: #222; 12 | --grayish-color: #222222; 13 | --lightgrayish-color: #aaa; 14 | --faintwhitish-color: #ccc; 15 | --whitish-color: #eee; 16 | --button-radius: 2px; 17 | } 18 | 19 | ::-webkit-scrollbar { 20 | width: 0px; 21 | } 22 | 23 | * { 24 | margin: 0; 25 | padding: 0; 26 | /* line-height: 1em; */ 27 | box-sizing: border-box; 28 | } 29 | html { 30 | font-size: 16px; 31 | } 32 | body { 33 | font-family: var(--main-font); 34 | background-color: var(--blackish-color); 35 | color: var(--whitish-color); 36 | } 37 | h1 { 38 | padding: 0.9rem 1rem 1rem; 39 | font-size: 2.2rem; 40 | background-color: var(--darkgrayish-color); 41 | /* border: 1px solid #ccc; */ 42 | } 43 | h1 em { 44 | font-style: normal; 45 | font-size: 1.1em; 46 | letter-spacing: -0.08em; 47 | } 48 | code { 49 | font-family: var(--code-font); 50 | } 51 | abbr { 52 | text-decoration: underline; 53 | text-decoration-style: dotted; 54 | } 55 | table { 56 | width: 100%; 57 | table-layout: fixed; 58 | border-spacing: 0.6rem; 59 | } 60 | .playground td { 61 | vertical-align: top; 62 | } 63 | a { 64 | color: cyan; 65 | } 66 | 67 | /***********************\ 68 | * INPUT * 69 | \***********************/ 70 | 71 | textarea { 72 | font-family: var(--main-font); 73 | font-size: 1.5rem; 74 | width: 100%; 75 | height: 200px; 76 | padding-left: 0.3rem; 77 | padding-top: 0.3rem; 78 | outline: none; 79 | background: var(--verydarkgrayish-color); 80 | border: none; 81 | color: #FFFFFF; 82 | } 83 | p { 84 | line-height: 1.7rem; 85 | vertical-align: top; 86 | } 87 | p .category { 88 | color: var(--grayish-color); 89 | background-color: var(--whitish-color); 90 | padding-left: 0.4rem; 91 | padding-right: 0.4rem; 92 | border-radius: var(--button-radius); 93 | font-size: 1rem; 94 | display: inline-block; 95 | vertical-align: top; 96 | } 97 | button { 98 | font-size: inherit; 99 | font-family: inherit; 100 | border: 0; 101 | background-color: var(--grayish-color); 102 | color: var(--whitish-color); 103 | padding: 0.3rem 0.5rem; 104 | cursor: pointer; 105 | outline: none; 106 | border-radius: var(--button-radius); 107 | margin: 0 2px 0 0; 108 | } 109 | button.unicode, 110 | button.example, 111 | button.mathfont { 112 | font-family: var(--code-font); 113 | margin-left: 0.6em; 114 | } 115 | button.disabled { 116 | opacity: 0.5; 117 | pointer-events: none; 118 | } 119 | button:hover { 120 | color: var(--grayish-color); 121 | background-color: var(--faintwhitish-color); 122 | } 123 | button.demos:hover { 124 | color: black; 125 | background-color: var(--faintwhitish-color); 126 | } 127 | input { 128 | font-size: inherit; 129 | font-family: var(--code-font); 130 | border: 0; 131 | padding: calc(0.17rem) 0.5rem; 132 | outline: none; 133 | border-radius: var(--button-radius) 0 0 var(--button-radius); 134 | width: 70px; 135 | position: relative; 136 | top: -1px; 137 | background-color: var(--whitish-color); 138 | } 139 | input#dictation { 140 | font-family: var(--code-font); 141 | outline: none; 142 | background: var(--verydarkgrayish-color); 143 | border: none; 144 | color: #FFFFFF; 145 | width: 1440px; 146 | } 147 | input#mathchar { 148 | width: 40px; 149 | background: var(--verydarkgrayish-color); 150 | border: none; 151 | color: #FFFFFF; 152 | } 153 | button.submit { 154 | border-radius: 0 var(--button-radius) var(--button-radius) 0; 155 | vertical-align: top; 156 | } 157 | .history { 158 | overflow-x: scroll; 159 | white-space: nowrap; 160 | margin-right: -1rem; 161 | } 162 | p.codepoint, p.examples { 163 | margin-top: 0.75rem; 164 | } 165 | 166 | .tooltip { 167 | position: absolute; 168 | pointer-events: none; 169 | background: #FFF; 170 | color: #000; 171 | font-size: 1rem; 172 | border-radius: var(--button-radius); 173 | padding-top: 0.6rem; 174 | border: 1px solid var(--darkgrayish-color); 175 | max-width: 30em; 176 | line-height: 1.4em; 177 | } 178 | .tooltip b { 179 | padding: 0.1rem; 180 | display: inline-block; 181 | text-transform: uppercase; 182 | background-color: var(--lightgrayish-color); 183 | color: var(--darkgrayish-color); 184 | margin-bottom: 1px; 185 | font-size: 0.8em; 186 | } 187 | .tooltip hr { 188 | border: 0; 189 | border-bottom: 1px solid var(--grayish-color); 190 | margin: 0.4em 0; 191 | } 192 | 193 | /***********************\ 194 | * AUTOCOMPLETE * 195 | \***********************/ 196 | 197 | /* The container must be positioned relative */ 198 | .autocomplete { 199 | position: relative; 200 | display: inline-block; 201 | } 202 | 203 | input[type=submit] { 204 | background-color: DodgerBlue; 205 | color: #fff; 206 | cursor: pointer; 207 | } 208 | 209 | .autocomplete-items { 210 | position: absolute; 211 | border: 1px solid #d4d4d4; 212 | border-bottom: none; 213 | z-index: 99; 214 | top: 4em; 215 | left: 4em; 216 | right: 30%; 217 | } 218 | 219 | .autocomplete-items div { 220 | padding: 10px; 221 | cursor: pointer; 222 | background-color: #000; 223 | border-bottom: 1px solid #d4d4d4; 224 | } 225 | 226 | /* When hovering over an item: */ 227 | .autocomplete-items div:hover { 228 | background-color: #222; 229 | } 230 | 231 | /* When navigating through items using arrow keys: */ 232 | .autocomplete-active { 233 | background-color: DodgerBlue !important; 234 | color: #000; 235 | } 236 | 237 | .formatmode-items { 238 | border-top: 1px solid #d4d4d4; 239 | } 240 | 241 | .formatmode-active { 242 | background-color: DodgerBlue !important; 243 | color: #000; 244 | } 245 | 246 | .formatmode-items div { 247 | padding: 10px; 248 | cursor: pointer; 249 | background-color: #000; 250 | } 251 | 252 | .formatmode-items div:hover { 253 | background-color: #222; 254 | } 255 | 256 | /***********************\ 257 | * OUTPUT * 258 | \***********************/ 259 | 260 | #codepoints { 261 | font-family: var(--code-font); 262 | margin-top: 0.5rem; 263 | padding: 0.8rem 0.5rem 0.5rem !important; 264 | background-color: var(--verydarkgrayish-color); 265 | line-height: 1.2em; 266 | overflow: hidden; 267 | } 268 | #codepoints:empty { 269 | display: none; 270 | } 271 | #codepoints:hover { 272 | max-height: initial !important; 273 | } 274 | #codepoints .cp { 275 | display: inline-block; 276 | text-align: center; 277 | vertical-align: top; 278 | min-height: 2.2em; 279 | } 280 | #codepoints .cp.invisible-char { 281 | background-color: var(--verydarkgrayish-color); 282 | } 283 | #codepoints .cp .p { 284 | font-size: 0.8em; 285 | padding: 0 0.5em 0.25em; 286 | color: var(--lightgrayish-color); 287 | } 288 | #output { 289 | font-family: var(--math-font); 290 | font-size: 1.3em; 291 | overflow-x: scroll; 292 | width: 100%; 293 | /*overflow: scroll; 294 | max-height: 30em;*/ 295 | min-height: 5rem; 296 | background: var(--verydarkgrayish-color); 297 | padding-top: 0.8rem !important; 298 | } 299 | #output:empty:after { 300 | content: "...and MathML will render here!"; 301 | } 302 | .MathJax_SVG, 303 | .MathJax_SVG_Display { 304 | font-family: var(--math-font); 305 | padding: 0.5rem !important; 306 | background-color: var(--verydarkgrayish-color); 307 | display: block !important; 308 | text-align: center !important; 309 | border-bottom: 1px solid var(--darkgrayish-color) !important; 310 | } 311 | .MathJax_SVG_Display { 312 | padding: 0 !important; 313 | margin: 0 !important; 314 | } 315 | math:last-child, 316 | .MathJax_SVG:last-of-type, 317 | .MathJax_SVG_Display:last-of-type { 318 | border-bottom: none !important; 319 | } 320 | .unicodemathml-error, 321 | .notice { 322 | line-height: 1rem; 323 | background-color: #f53; 324 | display: block; 325 | color: black; 326 | padding: 0.5rem; 327 | font-size: 0.8rem; 328 | border-bottom: 1px solid #d42; 329 | } 330 | .notice { 331 | background-color: #79f; 332 | border-bottom: 1px solid #68d; 333 | font-style: italic; 334 | } 335 | .unicodemathml-error .unicodemathml-error-unicodemath { 336 | font-family: var(--code-font); 337 | font-size: 1.33em; 338 | background-color: #d42; 339 | display: inline-block; 340 | margin-left: -0.5rem; 341 | margin-top: -0.5rem; 342 | padding: 0.5rem; 343 | float: left; 344 | margin-right: 0.5rem; 345 | } 346 | .unicodemathml-error .unicodemathml-error-unicodemath:before { 347 | content: "⚠️"; 348 | padding-right: 0.5rem; 349 | } 350 | .tabs { 351 | font-size: 0; 352 | } 353 | .tab { 354 | background: var(--darkgrayish-color); 355 | color: var(--whitish-color); 356 | font-size: 0.8rem; 357 | font-style: italic; 358 | border-radius: var(--button-radius) var(--button-radius) 0 0; 359 | padding: 0.5rem; 360 | display: inline-block; 361 | margin: 0 1px 0 0; 362 | } 363 | .tab.active { 364 | background: dodgerblue; 365 | } 366 | .tab.active:hover { 367 | color: inherit; 368 | } 369 | .tab span { 370 | background-color: rgba(140,140,140,0.5); 371 | font-size: 0.7em; 372 | padding: 0.3em 0.7em 0.4em; 373 | margin-left: 0.4em; 374 | border-radius: 1em; 375 | vertical-align: middle; 376 | font-style: normal; 377 | } 378 | .tab span:empty { 379 | display: none; 380 | } 381 | .tabcontent { 382 | background: var(--grayish-color); 383 | height: 252px; 384 | overflow: scroll; 385 | padding: 0.5rem; 386 | } 387 | .tabcontent pre { 388 | font-size: 0.8rem; 389 | line-height: 0.9rem; 390 | display: none; 391 | } 392 | 393 | .tabcontent pre:empty:after { 394 | font-family: var(--main-font); 395 | font-size: 1rem; 396 | content: "Intermediate representations display here. They're useful when debugging!"; 397 | } 398 | 399 | @keyframes blink { 400 | 0% {color: #6161f4;} 401 | 100% {color: black;} 402 | } 403 | 404 | @-webkit-keyframes blink { 405 | 0% {color: #6161f4;} 406 | 100% {color: black;} 407 | } 408 | 409 | .blink { 410 | -webkit-animation: blink 2s linear infinite; 411 | -moz-animation: blink 2s linear infinite; 412 | animation: blink 2s linear infinite; 413 | } 414 | 415 | /* json */ 416 | pre .key { 417 | color: salmon; 418 | font-style: italic; 419 | } 420 | pre .string { 421 | color: cornsilk; 422 | } 423 | pre .number { 424 | color: orange; 425 | } 426 | pre .boolean { 427 | color: lightsteelblue; 428 | } 429 | pre .null { 430 | background-color: gold; 431 | color: black; 432 | } 433 | 434 | /* trace */ 435 | pre .match { 436 | color: lawngreen; 437 | } 438 | pre .fail { 439 | color: lightpink; 440 | } 441 | 442 | /* mathml */ 443 | pre .text { 444 | color: gold; 445 | } 446 | pre .bracket { 447 | color: mintcream; 448 | } 449 | pre .tag { 450 | color: lightsteelblue; 451 | } 452 | pre .attribute { 453 | color: salmon; 454 | } 455 | pre .value { 456 | color: cornsilk; 457 | } 458 | pre .comment { 459 | background-color: gold; 460 | color: black; 461 | font-style: italic; 462 | } 463 | 464 | /***********************\ 465 | * CONFIG * 466 | \***********************/ 467 | 468 | #config { 469 | background-color: transparent; 470 | width: 2.5rem; 471 | font-size: 0.8rem; 472 | padding: 0.5rem 0; 473 | position: absolute; 474 | right: 0; 475 | top: 0; 476 | z-index: 1337; 477 | } 478 | #config h2 { 479 | text-align: right; 480 | padding-right: 0.8rem; 481 | padding-bottom: 0.5rem; 482 | font-size: 1.5rem; 483 | } 484 | #config:hover { 485 | background-color: var(--grayish-color); 486 | width: 15rem; 487 | box-shadow: 0 0 1rem var(--verydarkgrayish-color); 488 | border: 1px solid #d4d4d4; 489 | } 490 | #config div { 491 | padding: 0.5em 1em; 492 | display: none; 493 | } 494 | #config:hover div { 495 | display: block; 496 | } 497 | #config div:hover { 498 | background-color: var(--darkgrayish-color); 499 | } 500 | #config input { 501 | display: inline-block; 502 | width: 1.7em; 503 | } 504 | #config label { 505 | display: inline-block; 506 | width: calc(100% - 2em); 507 | vertical-align: top; 508 | } 509 | #config div.buttons:hover { 510 | background-color: transparent; 511 | } 512 | #config button { 513 | background-color: var(--whitish-color); 514 | color: var(--grayish-color); 515 | } 516 | #config button:hover { 517 | background-color: var(--lightgrayish-color); 518 | color: var(--whitish-color); 519 | } 520 | #config a { 521 | color: var(--lightgrayish-color); 522 | margin-left: 0.5em; 523 | cursor: pointer; 524 | } 525 | #config a:hover { 526 | color: orangered; 527 | } 528 | 529 | /***********************\ 530 | * Symbol Gallery Tabs * 531 | \***********************/ 532 | .categorytab { 533 | overflow: hidden; 534 | border: 1px solid #ccc; 535 | background-color: var(--darkgrayish-color); 536 | padding: 0; 537 | } 538 | 539 | /* Style the buttons inside the categorytab */ 540 | .categorytab button { 541 | background-color: inherit; 542 | float: left; 543 | border: none; 544 | outline: none; 545 | cursor: pointer; 546 | padding: 10px 10px; 547 | transition: 0.3s; 548 | font-size: 17px; 549 | } 550 | 551 | /* Change background color of buttons on hover */ 552 | .categorytab button:hover { 553 | background-color: #ddd; 554 | } 555 | 556 | /* Create an active/current categorytablink class */ 557 | .categorytab button.active { 558 | background-color: dodgerblue; 559 | } 560 | 561 | /* Style the categorytab content */ 562 | .categorytabcontent { 563 | display: none; 564 | padding: 6px 12px; 565 | border: 1px solid #ccc; 566 | border-top: none; 567 | } 568 | -------------------------------------------------------------------------------- /playground/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/playground/favicon.ico -------------------------------------------------------------------------------- /playground/help-images/Autobuildup5.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/playground/help-images/Autobuildup5.mp4 -------------------------------------------------------------------------------- /playground/help-images/CodePointHover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/playground/help-images/CodePointHover.png -------------------------------------------------------------------------------- /playground/help-images/OperatorHover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/playground/help-images/OperatorHover.png -------------------------------------------------------------------------------- /playground/help-images/autocl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/playground/help-images/autocl.png -------------------------------------------------------------------------------- /playground/help-images/autocllong.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/playground/help-images/autocllong.png -------------------------------------------------------------------------------- /playground/help-images/intentbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MurrayIII/UnicodeMathML/9555d9a45d94f1653a78f5a602f2c6309ec6dd82/playground/help-images/intentbox.png -------------------------------------------------------------------------------- /playground/help.md: -------------------------------------------------------------------------------- 1 | [UnicodeMath](https://www.unicode.org/notes/tn28/UTN28-PlainTextMath-v3.2.pdf) is a linear representation of math that often resembles math notation and is easy to enter. 2 | For example, a/b is UnicodeMath for ab. 3 | It works well in Microsoft desktop apps such as Word, PowerPoint, Outlook, and OneNote but it hasn't been generally available elsewhere. 4 | This open-source applet implements UnicodeMath on the web. 5 | 6 | ## Entering equations 7 | You can enter equations in four ways: 8 | 1. Enter UnicodeMath in the input (upper-left) window. The corresponding 2D built-up math displays in the output (upper-right) window and the [MathML](https://w3c.github.io/mathml/) for it displays below the output window. This option is quite reliable. 9 | 2. Enter UnicodeMath directly into the output window. This option builds up what you enter automatically, similarly to entry in the Microsoft Office apps. This option is a work in progress. 10 | 3. Click on the Dictate button or type Alt+d, wait for the bell, and dictate the equation in English. You need to have Internet access, and you need to enunciate clearly. This option is also a work in progress but if you get it to work it’s the fastest entry method except for: 11 | 4. Paste MathML into the input or output window. 12 | 13 | ## See and/or hear it in action 14 | Click on the Demo button or type Alt+p in the input window to see it in action! 15 | Hit the space bar to pause the demo and hit it again to continue the demo. 16 | The arrow keys → and ← move to the next/previous equation, respectively. 17 | Escape and Alt+p stop the demo. One of the equations has the UnicodeMath 1/2𝜋 ∫_0^2𝜋 ⅆ𝜃/(𝑎+𝑏 sin⁡𝜃)=1/√(𝑎²−𝑏²), which builds up to 18 | 19 | 12𝜋02𝜋𝑑𝜃𝑎+𝑏sin𝜃=1𝑎2𝑏2 20 | 21 | To speak the equations, type the space bar to pause the demo, type Alt+s to speak the current equation, and then type the right arrow key to advance to the next equation. Alternatively, type Alt+Enter to enter the current Examples equation (and advance the Examples equation ID), and type Alt+s to speak the equation. In these ways, you can cycle through the equations speaking each one. 22 | ## Entering symbols 23 | You can enter a symbol by clicking on the symbol in one of the symbol galleries below the input window. 24 | But it’s faster to type the symbol’s LaTeX control word such as \alpha for α. 25 | After typing two letters, you get a math autocomplete dropdown with possible matches. 26 | This lets you enter the selected symbol (the one highlighted in blue) quickly by typing Enter or Tab. 27 | 28 | For example, if you type \al, you see 29 | 30 | 33 | 34 | Typing the Enter or Tab key inserts 𝛼. 35 | If you want a different symbol in the dropdown, you can click on it, or you can use the up/down (↑↓) arrow keys to select the symbol you want and type the Enter or Tab key to enter it. 36 | 37 | The math autocomplete menu helps you discover a LaTeX control word, and it speeds entry especially for long control words such as those in the dropdown 38 | 39 | 42 | 43 | The symbol dictionary includes some control-word aliases, such as \union for \cup (∪), since you might not guess \cup is the LaTeX control word for the union operator ∪. 44 | 45 | ## Character code points 46 | Below the input window, there’s a Unicode codepoint window that displays the codepoints of the input symbols above the symbols. 47 | This is particularly useful for comparing two strings that appear to be identical but differ in one or more characters. 48 | Both the input and output windows support the Alt+x symbol entry method popular in Microsoft Word, OneNote, and NotePad. 49 | (It should be supported in all editors 😊). 50 | For example, type 222b Alt+x to insert ∫. 51 | 52 | ## Speech, braille, LaTeX, dictation 53 | In addition to generating MathML, you can click on buttons or enter a hot key to 54 | * Speak the math in English (Alt+s) 55 | * Braille the math in Nemeth braille (Alt+b) 56 | * Convert the math to Unicode LaTeX (Alt+t) 57 | * Dictate an equation (Alt+d) 58 | * Display the Help page (Alt+h) 59 | * Display the About page (Alt+a) 60 | * Enter the current Example equation and advance the Example equation ID (Alt+Enter) 61 | 62 | The results for speech, braille and LaTeX are displayed below the input window. 63 | Dictation results are shown in the input, output, and MathML windows. 64 | Dictation hint: wait for the start beep (else the first word(s) might be missing) and enunciate clearly. 65 | ## Math display 66 | The math is rendered in the output window either natively or by MathJax according to a setting (click on the ⚙︎ to change it). 67 | MathJax’s typography resembles LaTeX’s. 68 | The native rendering is good although not yet as good as LaTeX. 69 | But an advantage of the native renderer is that you can edit built-up equations directly in the output window and copy all or part of an equation. 70 | If the selection is an insertion point, the whole equation is copied. 71 | The only editing feature in the MathJax mode is Ctrl+c, which copies the MathML for the whole equation to the clipboard. 72 | ## Navigating the app 73 | A mouse or touchpad provides one way to move between and inside the various facilities. Another way is to use the Tab key. Since the app has myriad default Tab stops, users need a Tab hierarchy. The top of the hierarchy has the menu stops Help, Demo, Speak, Braille, TeX, Dictate, and About, followed by the Input and Output windows, Settings, History, math styles, and symbol galleries. The Tab key navigates these stops in the forward direction, while Shift+Tab navigates in the backward direction. The Enter key activates the current stop's facility. In an activated facility, the left and right arrow keys move between the facility's options. The Enter key then runs the option. For an active symbol gallery, the Enter key inserts the current symbol. For most settings, the Enter key toggles the current option. For menu stops, the Enter key sends the associated hot key. Each change is accompanied by explanatory speech. 74 | ## Intents 75 | UnicodeMathML generates [Presentation MathML 4](https://w3c.github.io/mathml/). 76 | A key addition in MathML 4 is the intent attribute, which allows authors to disambiguate math notation and control math speech. 77 | 78 | For example, does |𝑥| mean the absolute value of 𝑥 or the cardinality of 𝑥? 79 | Absolute value is assumed by default since absolute value is more common than cardinality. 80 | The default MathML for |x| is 81 | ```html 82 | 83 | |𝑥|. 84 | ``` 85 | To specify cardinality, enter \card(x) (or ⓒ(x)). 86 | These inputs produce the MathML 87 | ```html 88 | 89 | |𝑥|. 90 | ``` 91 | If you enter an absolute value or cardinality containing more than one symbol as in |a+b|, the MathML intent contains an argument reference $a. 92 | For |a+b|, the MathML is 93 | ```html 94 | 95 | | 96 | 97 | 𝑎+𝑏 98 | | 99 | ``` 100 | A matrix enclosed in vertical bars is treated as a determinant. 101 | For example, the UnicodeMath |■(a&b@c&d)| builds up to 102 | 103 | |𝑎𝑏𝑐𝑑| 104 | 105 | which has the MathML 106 | ```html 107 | 108 | | 109 | 110 | 111 | 𝑎𝑏 112 | 𝑐𝑑 113 | |. 114 | ``` 115 | The program infers intent attributes for absolute value and determinant, so only cardinality needs to be input without vertical bars. 116 | Note that the ambiguous expression |𝑎|𝑏+𝑐|𝑑| is assumed to be (|𝑎|)𝑏+𝑐(|𝑑|). 117 | If you want |𝑎(|𝑏+𝑐|)𝑑|, enter |(𝑎|𝑏+𝑐|𝑑)| and the parentheses will be removed. 118 | 119 | As we see here, some intent attribute values are implied by the input notations of LaTeX and UnicodeMath. 120 | Others are implied by context. 121 | Still others must be declared explicitly by the content author, by a math-knowledgeable copy editor, or maybe eventually by AI. 122 | ## Author intents 123 | Since most content authors don’t know MathML, we need a way to allow them to enter intents easily. 124 | To this end, UnicodeMathML has an output-window context-menu option that lets you tag entities with intents. 125 | For example, clicking on the 𝐸 in 𝐸 = 𝑚𝑐², you get the input box 126 | 127 | 130 | 131 | and you can type in “energy” or whatever you want followed by the Enter key. 132 | If you type in “energy”, the resulting MathML is 133 | 134 | ```html 135 | 136 | 𝐸 137 | = 138 | 139 | 𝑚 140 | 𝑐 141 | 2 142 | ``` 143 | 144 | Typing Atl+d speaks this as "energy equals m c squared". 145 | 146 | ## UnicodeMath editing 147 | As you type into the input window, various conversions occur in the input window: 148 | * Letters are converted to math italic unless they 1) are part of a function name or of a control word (backslash followed by letters), or 2) follow a quote. For example, a → 𝑎 149 | * Numeric subscripts/superscripts are converted to Unicode subscript/superscript characters, respectively. For example, a_2 → 𝑎₂ and a^2 → 𝑎². 150 | * Numeric fractions are converted to Unicode numeric fractions. For example, 1/2 → ½ 151 | * Control words are converted to their symbols, e.g., \alpha → 𝛼 152 | 153 | These conversions aren't needed in the input window, but they make the input more readable. 154 | ## Editing hot keys: 155 | | Hot key | Function | 156 | | ------- | ----------- | 157 | | Ctrl+b | Toggle the bold attribute. For example, select 𝑎 (U+1D44E), type Ctrl+b and get 𝒂 (U+1D482) as you can verify in the codepoint window. | 158 | | Ctrl+c | Copy the selected text to the clipboard. | 159 | | Alt+h | Display the help page. | 160 | | Ctrl+i | Toggle the italic attribute. If applied to a math italic character, this changes the character to the UnicodeMath way of representing ordinary text, i.e., put it inside quotes as in select 𝑎, Ctrl+i → “a”. | 161 | | Alt+m | Toggle between displaying 1) UnicodeMath in the input window and MathML below the output window, and 2) MathML in the input window and UnicodeMath below the output window. | 162 | | Ctrl+v | Paste plain text from the clipboard. If the text starts with 180 | 181 | Hovering over the ∪ in the Operators gallery displays 182 | 183 | 186 | 187 | Here \cup is the standard [La]TeX control word for entering ∪ but since \union is easier to guess, it’s included too. 188 | 189 | ## Output window editing 190 | You can enter equations and edit the built-up display in the output window as shown in this video 191 | 192 |