temml 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +44 -0
  3. package/contrib/auto-render/README.md +89 -0
  4. package/contrib/auto-render/auto-render.js +128 -0
  5. package/contrib/auto-render/dist/auto-render.js +217 -0
  6. package/contrib/auto-render/dist/auto-render.min.js +1 -0
  7. package/contrib/auto-render/splitAtDelimiters.js +84 -0
  8. package/contrib/auto-render/test/auto-render-spec.js +234 -0
  9. package/contrib/auto-render/test/auto-render.js +217 -0
  10. package/contrib/auto-render/test/test_page.html +59 -0
  11. package/contrib/mhchem/README.md +26 -0
  12. package/contrib/mhchem/mhchem.js +1705 -0
  13. package/contrib/mhchem/mhchem.min.js +1 -0
  14. package/contrib/physics/README.md +20 -0
  15. package/contrib/physics/physics.js +131 -0
  16. package/contrib/texvc/README.md +23 -0
  17. package/contrib/texvc/texvc.js +61 -0
  18. package/dist/Temml-Asana.css +201 -0
  19. package/dist/Temml-Latin-Modern.css +216 -0
  20. package/dist/Temml-Libertinus.css +214 -0
  21. package/dist/Temml-Local.css +194 -0
  22. package/dist/Temml-STIX2.css +203 -0
  23. package/dist/Temml.woff2 +0 -0
  24. package/dist/temml.cjs +13122 -0
  25. package/dist/temml.js +11225 -0
  26. package/dist/temml.min.js +1 -0
  27. package/dist/temml.mjs +13120 -0
  28. package/dist/temmlPostProcess.js +70 -0
  29. package/package.json +34 -0
  30. package/src/Lexer.js +121 -0
  31. package/src/MacroExpander.js +437 -0
  32. package/src/Namespace.js +107 -0
  33. package/src/ParseError.js +64 -0
  34. package/src/Parser.js +977 -0
  35. package/src/Settings.js +49 -0
  36. package/src/SourceLocation.js +29 -0
  37. package/src/Style.js +144 -0
  38. package/src/Token.js +40 -0
  39. package/src/buildMathML.js +235 -0
  40. package/src/constants.js +25 -0
  41. package/src/defineEnvironment.js +25 -0
  42. package/src/defineFunction.js +69 -0
  43. package/src/defineMacro.js +11 -0
  44. package/src/domTree.js +185 -0
  45. package/src/environments/array.js +791 -0
  46. package/src/environments/cd.js +252 -0
  47. package/src/environments.js +8 -0
  48. package/src/functions/accent.js +127 -0
  49. package/src/functions/accentunder.js +38 -0
  50. package/src/functions/arrow.js +204 -0
  51. package/src/functions/cancelto.js +36 -0
  52. package/src/functions/char.js +33 -0
  53. package/src/functions/color.js +253 -0
  54. package/src/functions/cr.js +46 -0
  55. package/src/functions/def.js +259 -0
  56. package/src/functions/delimsizing.js +304 -0
  57. package/src/functions/enclose.js +193 -0
  58. package/src/functions/envTag.js +38 -0
  59. package/src/functions/environment.js +59 -0
  60. package/src/functions/font.js +123 -0
  61. package/src/functions/genfrac.js +333 -0
  62. package/src/functions/hbox.js +29 -0
  63. package/src/functions/horizBrace.js +32 -0
  64. package/src/functions/href.js +90 -0
  65. package/src/functions/html.js +95 -0
  66. package/src/functions/includegraphics.js +131 -0
  67. package/src/functions/kern.js +75 -0
  68. package/src/functions/label.js +29 -0
  69. package/src/functions/lap.js +75 -0
  70. package/src/functions/math.js +40 -0
  71. package/src/functions/mathchoice.js +41 -0
  72. package/src/functions/mclass.js +201 -0
  73. package/src/functions/multiscript.js +91 -0
  74. package/src/functions/not.js +46 -0
  75. package/src/functions/op.js +338 -0
  76. package/src/functions/operatorname.js +139 -0
  77. package/src/functions/ordgroup.js +9 -0
  78. package/src/functions/phantom.js +73 -0
  79. package/src/functions/pmb.js +31 -0
  80. package/src/functions/raise.js +68 -0
  81. package/src/functions/ref.js +28 -0
  82. package/src/functions/relax.js +16 -0
  83. package/src/functions/rule.js +52 -0
  84. package/src/functions/sizing.js +64 -0
  85. package/src/functions/smash.js +66 -0
  86. package/src/functions/sqrt.js +31 -0
  87. package/src/functions/styling.js +58 -0
  88. package/src/functions/supsub.js +135 -0
  89. package/src/functions/symbolsOp.js +53 -0
  90. package/src/functions/symbolsOrd.js +102 -0
  91. package/src/functions/symbolsSpacing.js +53 -0
  92. package/src/functions/tag.js +8 -0
  93. package/src/functions/text.js +75 -0
  94. package/src/functions/tip.js +63 -0
  95. package/src/functions/toggle.js +13 -0
  96. package/src/functions/verb.js +33 -0
  97. package/src/functions.js +57 -0
  98. package/src/linebreaking.js +159 -0
  99. package/src/macros.js +708 -0
  100. package/src/mathMLTree.js +175 -0
  101. package/src/parseNode.js +42 -0
  102. package/src/parseTree.js +40 -0
  103. package/src/postProcess.js +57 -0
  104. package/src/replace.js +225 -0
  105. package/src/stretchy.js +66 -0
  106. package/src/svg.js +110 -0
  107. package/src/symbols.js +972 -0
  108. package/src/tree.js +50 -0
  109. package/src/unicodeAccents.js +16 -0
  110. package/src/unicodeScripts.js +119 -0
  111. package/src/unicodeSupOrSub.js +108 -0
  112. package/src/unicodeSymbolBuilder.js +31 -0
  113. package/src/unicodeSymbols.js +320 -0
  114. package/src/units.js +109 -0
  115. package/src/utils.js +109 -0
  116. package/src/variant.js +103 -0
  117. package/temml.js +181 -0
@@ -0,0 +1,1705 @@
1
+ /* eslint-disable */
2
+ /* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
3
+ /* vim: set ts=2 et sw=2 tw=80: */
4
+
5
+ /*************************************************************
6
+ *
7
+ * Temml mhchem.js
8
+ *
9
+ * This file implements a Temml version of mhchem version 3.3.0.
10
+ * It is adapted from MathJax/extensions/TeX/mhchem.js
11
+ * It differs from the MathJax version as follows:
12
+ * 1. The interface is changed so that it can be called from Temml, not MathJax.
13
+ * 2. \rlap and \llap are replaced with \mathrlap and \mathllap.
14
+ * 3. The reaction arrow code is simplified. All reaction arrows are rendered
15
+ * using Temml extensible arrows instead of building non-extensible arrows.
16
+ * 4. The ~bond forms are composed entirely of \rule elements.
17
+ * 5. Two dashes in _getBond are wrapped in braces to suppress spacing. i.e., {-}
18
+ * 6. The electron dot uses \textbullet instead of \bullet.
19
+ *
20
+ * This code, as other Temml code, is released under the MIT license.
21
+ *
22
+ * /*************************************************************
23
+ *
24
+ * MathJax/extensions/TeX/mhchem.js
25
+ *
26
+ * Implements the \ce command for handling chemical formulas
27
+ * from the mhchem LaTeX package.
28
+ *
29
+ * ---------------------------------------------------------------------
30
+ *
31
+ * Copyright (c) 2011-2015 The MathJax Consortium
32
+ * Copyright (c) 2015-2018 Martin Hensel
33
+ *
34
+ * Licensed under the Apache License, Version 2.0 (the "License");
35
+ * you may not use this file except in compliance with the License.
36
+ * You may obtain a copy of the License at
37
+ *
38
+ * http://www.apache.org/licenses/LICENSE-2.0
39
+ *
40
+ * Unless required by applicable law or agreed to in writing, software
41
+ * distributed under the License is distributed on an "AS IS" BASIS,
42
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
43
+ * See the License for the specific language governing permissions and
44
+ * limitations under the License.
45
+ */
46
+
47
+ //
48
+ // Coding Style
49
+ // - use '' for identifiers that can by minified/uglified
50
+ // - use "" for strings that need to stay untouched
51
+
52
+ // version: "3.3.0" for MathJax and Temml
53
+
54
+
55
+ // Add \ce, \pu, and \tripleDash to the Temml macros.
56
+
57
+ temml.__defineMacro("\\ce", function(context) {
58
+ return chemParse(context.consumeArgs(1)[0], "ce")
59
+ });
60
+
61
+ temml.__defineMacro("\\pu", function(context) {
62
+ return chemParse(context.consumeArgs(1)[0], "pu");
63
+ });
64
+
65
+ // Math fonts do not include glyphs for the ~ form of bonds. So we'll send path geometry
66
+ // So we'll compose characters built from \rule elements.
67
+ temml.__defineMacro("\\uniDash", `{\\rule{0.672em}{0.06em}}`)
68
+ temml.__defineMacro("\\triDash", `{\\rule{0.15em}{0.06em}\\kern2mu\\rule{0.15em}{0.06em}\\kern2mu\\rule{0.15em}{0.06em}}`)
69
+ temml.__defineMacro("\\tripleDash", `\\kern0.075em\\raise0.25em{\\triDash}\\kern0.075em`)
70
+ temml.__defineMacro("\\tripleDashOverLine", `\\kern0.075em\\mathrlap{\\raise0.125em{\\uniDash}}\\raise0.34em{\\triDash}\\kern0.075em`)
71
+ temml.__defineMacro("\\tripleDashOverDoubleLine", `\\kern0.075em\\mathrlap{\\mathrlap{\\raise0.48em{\\triDash}}\\raise0.27em{\\uniDash}}{\\raise0.05em{\\uniDash}}\\kern0.075em`)
72
+ temml.__defineMacro("\\tripleDashBetweenDoubleLine", `\\kern0.075em\\mathrlap{\\mathrlap{\\raise0.48em{\\uniDash}}\\raise0.27em{\\triDash}}{\\raise0.05em{\\uniDash}}\\kern0.075em`)
73
+
74
+ //
75
+ // This is the main function for handing the \ce and \pu commands.
76
+ // It takes the argument to \ce or \pu and returns the corresponding TeX string.
77
+ //
78
+
79
+ var chemParse = function (tokens, stateMachine) {
80
+ // Recreate the argument string from Temml's array of tokens.
81
+ var str = "";
82
+ var expectedLoc = tokens.length && tokens[tokens.length - 1].loc.start
83
+ for (var i = tokens.length - 1; i >= 0; i--) {
84
+ if(tokens[i].loc.start > expectedLoc) {
85
+ // context.consumeArgs has eaten a space.
86
+ str += " ";
87
+ expectedLoc = tokens[i].loc.start;
88
+ }
89
+ str += tokens[i].text;
90
+ expectedLoc += tokens[i].text.length;
91
+ }
92
+ // Call the mhchem core parser.
93
+ var tex = texify.go(mhchemParser.go(str, stateMachine));
94
+ return tex;
95
+ };
96
+
97
+ //
98
+ // Core parser for mhchem syntax (recursive)
99
+ //
100
+ /** @type {MhchemParser} */
101
+ var mhchemParser = {
102
+ //
103
+ // Parses mchem \ce syntax
104
+ //
105
+ // Call like
106
+ // go("H2O");
107
+ //
108
+ go: function (input, stateMachine) {
109
+ if (!input) { return []; }
110
+ if (stateMachine === undefined) { stateMachine = 'ce'; }
111
+ var state = '0';
112
+
113
+ //
114
+ // String buffers for parsing:
115
+ //
116
+ // buffer.a == amount
117
+ // buffer.o == element
118
+ // buffer.b == left-side superscript
119
+ // buffer.p == left-side subscript
120
+ // buffer.q == right-side subscript
121
+ // buffer.d == right-side superscript
122
+ //
123
+ // buffer.r == arrow
124
+ // buffer.rdt == arrow, script above, type
125
+ // buffer.rd == arrow, script above, content
126
+ // buffer.rqt == arrow, script below, type
127
+ // buffer.rq == arrow, script below, content
128
+ //
129
+ // buffer.text_
130
+ // buffer.rm
131
+ // etc.
132
+ //
133
+ // buffer.parenthesisLevel == int, starting at 0
134
+ // buffer.sb == bool, space before
135
+ // buffer.beginsWithBond == bool
136
+ //
137
+ // These letters are also used as state names.
138
+ //
139
+ // Other states:
140
+ // 0 == begin of main part (arrow/operator unlikely)
141
+ // 1 == next entity
142
+ // 2 == next entity (arrow/operator unlikely)
143
+ // 3 == next atom
144
+ // c == macro
145
+ //
146
+ /** @type {Buffer} */
147
+ var buffer = {};
148
+ buffer['parenthesisLevel'] = 0;
149
+
150
+ input = input.replace(/\n/g, " ");
151
+ input = input.replace(/[\u2212\u2013\u2014\u2010]/g, "-");
152
+ input = input.replace(/[\u2026]/g, "...");
153
+
154
+ //
155
+ // Looks through mhchemParser.transitions, to execute a matching action
156
+ // (recursive)
157
+ //
158
+ var lastInput;
159
+ var watchdog = 10;
160
+ /** @type {ParserOutput[]} */
161
+ var output = [];
162
+ while (true) {
163
+ if (lastInput !== input) {
164
+ watchdog = 10;
165
+ lastInput = input;
166
+ } else {
167
+ watchdog--;
168
+ }
169
+ //
170
+ // Find actions in transition table
171
+ //
172
+ var machine = mhchemParser.stateMachines[stateMachine];
173
+ var t = machine.transitions[state] || machine.transitions['*'];
174
+ iterateTransitions:
175
+ for (var i=0; i<t.length; i++) {
176
+ var matches = mhchemParser.patterns.match_(t[i].pattern, input);
177
+ if (matches) {
178
+ //
179
+ // Execute actions
180
+ //
181
+ var task = t[i].task;
182
+ for (var iA=0; iA<task.action_.length; iA++) {
183
+ var o;
184
+ //
185
+ // Find and execute action
186
+ //
187
+ if (machine.actions[task.action_[iA].type_]) {
188
+ o = machine.actions[task.action_[iA].type_](buffer, matches.match_, task.action_[iA].option);
189
+ } else if (mhchemParser.actions[task.action_[iA].type_]) {
190
+ o = mhchemParser.actions[task.action_[iA].type_](buffer, matches.match_, task.action_[iA].option);
191
+ } else {
192
+ throw ["MhchemBugA", "mhchem bug A. Please report. (" + task.action_[iA].type_ + ")"]; // Trying to use non-existing action
193
+ }
194
+ //
195
+ // Add output
196
+ //
197
+ mhchemParser.concatArray(output, o);
198
+ }
199
+ //
200
+ // Set next state,
201
+ // Shorten input,
202
+ // Continue with next character
203
+ // (= apply only one transition per position)
204
+ //
205
+ state = task.nextState || state;
206
+ if (input.length > 0) {
207
+ if (!task.revisit) {
208
+ input = matches.remainder;
209
+ }
210
+ if (!task.toContinue) {
211
+ break iterateTransitions;
212
+ }
213
+ } else {
214
+ return output;
215
+ }
216
+ }
217
+ }
218
+ //
219
+ // Prevent infinite loop
220
+ //
221
+ if (watchdog <= 0) {
222
+ throw ["MhchemBugU", "mhchem bug U. Please report."]; // Unexpected character
223
+ }
224
+ }
225
+ },
226
+ concatArray: function (a, b) {
227
+ if (b) {
228
+ if (Array.isArray(b)) {
229
+ for (var iB=0; iB<b.length; iB++) {
230
+ a.push(b[iB]);
231
+ }
232
+ } else {
233
+ a.push(b);
234
+ }
235
+ }
236
+ },
237
+
238
+ patterns: {
239
+ //
240
+ // Matching patterns
241
+ // either regexps or function that return null or {match_:"a", remainder:"bc"}
242
+ //
243
+ patterns: {
244
+ // property names must not look like integers ("2") for correct property traversal order, later on
245
+ 'empty': /^$/,
246
+ 'else': /^./,
247
+ 'else2': /^./,
248
+ 'space': /^\s/,
249
+ 'space A': /^\s(?=[A-Z\\$])/,
250
+ 'space$': /^\s$/,
251
+ 'a-z': /^[a-z]/,
252
+ 'x': /^x/,
253
+ 'x$': /^x$/,
254
+ 'i$': /^i$/,
255
+ 'letters': /^(?:[a-zA-Z\u03B1-\u03C9\u0391-\u03A9?@]|(?:\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))))+/,
256
+ '\\greek': /^\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))/,
257
+ 'one lowercase latin letter $': /^(?:([a-z])(?:$|[^a-zA-Z]))$/,
258
+ '$one lowercase latin letter$ $': /^\$(?:([a-z])(?:$|[^a-zA-Z]))\$$/,
259
+ 'one lowercase greek letter $': /^(?:\$?[\u03B1-\u03C9]\$?|\$?\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega)\s*\$?)(?:\s+|\{\}|(?![a-zA-Z]))$/,
260
+ 'digits': /^[0-9]+/,
261
+ '-9.,9': /^[+\-]?(?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))/,
262
+ '-9.,9 no missing 0': /^[+\-]?[0-9]+(?:[.,][0-9]+)?/,
263
+ '(-)(9.,9)(e)(99)': function (input) {
264
+ var m = input.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))?(\((?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))\))?(?:([eE]|\s*(\*|x|\\times|\u00D7)\s*10\^)([+\-]?[0-9]+|\{[+\-]?[0-9]+\}))?/);
265
+ if (m && m[0]) {
266
+ return { match_: m.splice(1), remainder: input.substr(m[0].length) };
267
+ }
268
+ return null;
269
+ },
270
+ '(-)(9)^(-9)': function (input) {
271
+ var m = input.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+)?)\^([+\-]?[0-9]+|\{[+\-]?[0-9]+\})/);
272
+ if (m && m[0]) {
273
+ return { match_: m.splice(1), remainder: input.substr(m[0].length) };
274
+ }
275
+ return null;
276
+ },
277
+ 'state of aggregation $': function (input) { // ... or crystal system
278
+ var a = mhchemParser.patterns.findObserveGroups(input, "", /^\([a-z]{1,3}(?=[\),])/, ")", ""); // (aq), (aq,$\infty$), (aq, sat)
279
+ if (a && a.remainder.match(/^($|[\s,;\)\]\}])/)) { return a; } // AND end of 'phrase'
280
+ var m = input.match(/^(?:\((?:\\ca\s?)?\$[amothc]\$\))/); // OR crystal system ($o$) (\ca$c$)
281
+ if (m) {
282
+ return { match_: m[0], remainder: input.substr(m[0].length) };
283
+ }
284
+ return null;
285
+ },
286
+ '_{(state of aggregation)}$': /^_\{(\([a-z]{1,3}\))\}/,
287
+ '{[(': /^(?:\\\{|\[|\()/,
288
+ ')]}': /^(?:\)|\]|\\\})/,
289
+ ', ': /^[,;]\s*/,
290
+ ',': /^[,;]/,
291
+ '.': /^[.]/,
292
+ '. ': /^([.\u22C5\u00B7\u2022])\s*/,
293
+ '...': /^\.\.\.(?=$|[^.])/,
294
+ '* ': /^([*])\s*/,
295
+ '^{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "^{", "", "", "}"); },
296
+ '^($...$)': function (input) { return mhchemParser.patterns.findObserveGroups(input, "^", "$", "$", ""); },
297
+ '^a': /^\^([0-9]+|[^\\_])/,
298
+ '^\\x{}{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "^", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); },
299
+ '^\\x{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "^", /^\\[a-zA-Z]+\{/, "}", ""); },
300
+ '^\\x': /^\^(\\[a-zA-Z]+)\s*/,
301
+ '^(-1)': /^\^(-?\d+)/,
302
+ '\'': /^'/,
303
+ '_{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "_{", "", "", "}"); },
304
+ '_($...$)': function (input) { return mhchemParser.patterns.findObserveGroups(input, "_", "$", "$", ""); },
305
+ '_9': /^_([+\-]?[0-9]+|[^\\])/,
306
+ '_\\x{}{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "_", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); },
307
+ '_\\x{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "_", /^\\[a-zA-Z]+\{/, "}", ""); },
308
+ '_\\x': /^_(\\[a-zA-Z]+)\s*/,
309
+ '^_': /^(?:\^(?=_)|\_(?=\^)|[\^_]$)/,
310
+ '{}': /^\{\}/,
311
+ '{...}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", "{", "}", ""); },
312
+ '{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "{", "", "", "}"); },
313
+ '$...$': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", "$", "$", ""); },
314
+ '${(...)}$': function (input) { return mhchemParser.patterns.findObserveGroups(input, "${", "", "", "}$"); },
315
+ '$(...)$': function (input) { return mhchemParser.patterns.findObserveGroups(input, "$", "", "", "$"); },
316
+ '=<>': /^[=<>]/,
317
+ '#': /^[#\u2261]/,
318
+ '+': /^\+/,
319
+ '-$': /^-(?=[\s_},;\]/]|$|\([a-z]+\))/, // -space -, -; -] -/ -$ -state-of-aggregation
320
+ '-9': /^-(?=[0-9])/,
321
+ '- orbital overlap': /^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/,
322
+ '-': /^-/,
323
+ 'pm-operator': /^(?:\\pm|\$\\pm\$|\+-|\+\/-)/,
324
+ 'operator': /^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/,
325
+ 'arrowUpDown': /^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/,
326
+ '\\bond{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\bond{", "", "", "}"); },
327
+ '->': /^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/,
328
+ 'CMT': /^[CMT](?=\[)/,
329
+ '[(...)]': function (input) { return mhchemParser.patterns.findObserveGroups(input, "[", "", "", "]"); },
330
+ '1st-level escape': /^(&|\\\\|\\hline)\s*/,
331
+ '\\,': /^(?:\\[,\ ;:])/, // \\x - but output no space before
332
+ '\\x{}{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); },
333
+ '\\x{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", ""); },
334
+ '\\ca': /^\\ca(?:\s+|(?![a-zA-Z]))/,
335
+ '\\x': /^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/,
336
+ 'orbital': /^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/, // only those with numbers in front, because the others will be formatted correctly anyway
337
+ 'others': /^[\/~|]/,
338
+ '\\frac{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\frac{", "", "", "}", "{", "", "", "}"); },
339
+ '\\overset{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\overset{", "", "", "}", "{", "", "", "}"); },
340
+ '\\underset{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\underset{", "", "", "}", "{", "", "", "}"); },
341
+ '\\underbrace{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\underbrace{", "", "", "}_", "{", "", "", "}"); },
342
+ '\\color{(...)}0': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}"); },
343
+ '\\color{(...)}{(...)}1': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}", "{", "", "", "}"); },
344
+ '\\color(...){(...)}2': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color", "\\", "", /^(?=\{)/, "{", "", "", "}"); },
345
+ '\\ce{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\ce{", "", "", "}"); },
346
+ 'oxidation$': /^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,
347
+ 'd-oxidation$': /^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, // 0 could be oxidation or charge
348
+ 'roman numeral': /^[IVX]+/,
349
+ '1/2$': /^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/,
350
+ 'amount': function (input) {
351
+ var match;
352
+ // e.g. 2, 0.5, 1/2, -2, n/2, +; $a$ could be added later in parsing
353
+ match = input.match(/^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/);
354
+ if (match) {
355
+ return { match_: match[0], remainder: input.substr(match[0].length) };
356
+ }
357
+ var a = mhchemParser.patterns.findObserveGroups(input, "", "$", "$", "");
358
+ if (a) { // e.g. $2n-1$, $-$
359
+ match = a.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/);
360
+ if (match) {
361
+ return { match_: match[0], remainder: input.substr(match[0].length) };
362
+ }
363
+ }
364
+ return null;
365
+ },
366
+ 'amount2': function (input) { return this['amount'](input); },
367
+ '(KV letters),': /^(?:[A-Z][a-z]{0,2}|i)(?=,)/,
368
+ 'formula$': function (input) {
369
+ if (input.match(/^\([a-z]+\)$/)) { return null; } // state of aggregation = no formula
370
+ var match = input.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/);
371
+ if (match) {
372
+ return { match_: match[0], remainder: input.substr(match[0].length) };
373
+ }
374
+ return null;
375
+ },
376
+ 'uprightEntities': /^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/,
377
+ '/': /^\s*(\/)\s*/,
378
+ '//': /^\s*(\/\/)\s*/,
379
+ '*': /^\s*[*.]\s*/
380
+ },
381
+ findObserveGroups: function (input, begExcl, begIncl, endIncl, endExcl, beg2Excl, beg2Incl, end2Incl, end2Excl, combine) {
382
+ /** @type {{(input: string, pattern: string | RegExp): string | string[] | null;}} */
383
+ var _match = function (input, pattern) {
384
+ if (typeof pattern === "string") {
385
+ if (input.indexOf(pattern) !== 0) { return null; }
386
+ return pattern;
387
+ } else {
388
+ var match = input.match(pattern);
389
+ if (!match) { return null; }
390
+ return match[0];
391
+ }
392
+ };
393
+ /** @type {{(input: string, i: number, endChars: string | RegExp): {endMatchBegin: number, endMatchEnd: number} | null;}} */
394
+ var _findObserveGroups = function (input, i, endChars) {
395
+ var braces = 0;
396
+ while (i < input.length) {
397
+ var a = input.charAt(i);
398
+ var match = _match(input.substr(i), endChars);
399
+ if (match !== null && braces === 0) {
400
+ return { endMatchBegin: i, endMatchEnd: i + match.length };
401
+ } else if (a === "{") {
402
+ braces++;
403
+ } else if (a === "}") {
404
+ if (braces === 0) {
405
+ throw ["ExtraCloseMissingOpen", "Extra close brace or missing open brace"];
406
+ } else {
407
+ braces--;
408
+ }
409
+ }
410
+ i++;
411
+ }
412
+ if (braces > 0) {
413
+ return null;
414
+ }
415
+ return null;
416
+ };
417
+ var match = _match(input, begExcl);
418
+ if (match === null) { return null; }
419
+ input = input.substr(match.length);
420
+ match = _match(input, begIncl);
421
+ if (match === null) { return null; }
422
+ var e = _findObserveGroups(input, match.length, endIncl || endExcl);
423
+ if (e === null) { return null; }
424
+ var match1 = input.substring(0, (endIncl ? e.endMatchEnd : e.endMatchBegin));
425
+ if (!(beg2Excl || beg2Incl)) {
426
+ return {
427
+ match_: match1,
428
+ remainder: input.substr(e.endMatchEnd)
429
+ };
430
+ } else {
431
+ var group2 = this.findObserveGroups(input.substr(e.endMatchEnd), beg2Excl, beg2Incl, end2Incl, end2Excl);
432
+ if (group2 === null) { return null; }
433
+ /** @type {string[]} */
434
+ var matchRet = [match1, group2.match_];
435
+ return {
436
+ match_: (combine ? matchRet.join("") : matchRet),
437
+ remainder: group2.remainder
438
+ };
439
+ }
440
+ },
441
+
442
+ //
443
+ // Matching function
444
+ // e.g. match("a", input) will look for the regexp called "a" and see if it matches
445
+ // returns null or {match_:"a", remainder:"bc"}
446
+ //
447
+ match_: function (m, input) {
448
+ var pattern = mhchemParser.patterns.patterns[m];
449
+ if (pattern === undefined) {
450
+ throw ["MhchemBugP", "mhchem bug P. Please report. (" + m + ")"]; // Trying to use non-existing pattern
451
+ } else if (typeof pattern === "function") {
452
+ return mhchemParser.patterns.patterns[m](input); // cannot use cached var pattern here, because some pattern functions need this===mhchemParser
453
+ } else { // RegExp
454
+ var match = input.match(pattern);
455
+ if (match) {
456
+ var mm;
457
+ if (match[2]) {
458
+ mm = [ match[1], match[2] ];
459
+ } else if (match[1]) {
460
+ mm = match[1];
461
+ } else {
462
+ mm = match[0];
463
+ }
464
+ return { match_: mm, remainder: input.substr(match[0].length) };
465
+ }
466
+ return null;
467
+ }
468
+ }
469
+ },
470
+
471
+ //
472
+ // Generic state machine actions
473
+ //
474
+ actions: {
475
+ 'a=': function (buffer, m) { buffer.a = (buffer.a || "") + m; },
476
+ 'b=': function (buffer, m) { buffer.b = (buffer.b || "") + m; },
477
+ 'p=': function (buffer, m) { buffer.p = (buffer.p || "") + m; },
478
+ 'o=': function (buffer, m) { buffer.o = (buffer.o || "") + m; },
479
+ 'q=': function (buffer, m) { buffer.q = (buffer.q || "") + m; },
480
+ 'd=': function (buffer, m) { buffer.d = (buffer.d || "") + m; },
481
+ 'rm=': function (buffer, m) { buffer.rm = (buffer.rm || "") + m; },
482
+ 'text=': function (buffer, m) { buffer.text_ = (buffer.text_ || "") + m; },
483
+ 'insert': function (buffer, m, a) { return { type_: a }; },
484
+ 'insert+p1': function (buffer, m, a) { return { type_: a, p1: m }; },
485
+ 'insert+p1+p2': function (buffer, m, a) { return { type_: a, p1: m[0], p2: m[1] }; },
486
+ 'copy': function (buffer, m) { return m; },
487
+ 'rm': function (buffer, m) { return { type_: 'rm', p1: m || ""}; },
488
+ 'text': function (buffer, m) { return mhchemParser.go(m, 'text'); },
489
+ '{text}': function (buffer, m) {
490
+ var ret = [ "{" ];
491
+ mhchemParser.concatArray(ret, mhchemParser.go(m, 'text'));
492
+ ret.push("}");
493
+ return ret;
494
+ },
495
+ 'tex-math': function (buffer, m) { return mhchemParser.go(m, 'tex-math'); },
496
+ 'tex-math tight': function (buffer, m) { return mhchemParser.go(m, 'tex-math tight'); },
497
+ 'bond': function (buffer, m, k) { return { type_: 'bond', kind_: k || m }; },
498
+ 'color0-output': function (buffer, m) { return { type_: 'color0', color: m[0] }; },
499
+ 'ce': function (buffer, m) { return mhchemParser.go(m); },
500
+ '1/2': function (buffer, m) {
501
+ /** @type {ParserOutput[]} */
502
+ var ret = [];
503
+ if (m.match(/^[+\-]/)) {
504
+ ret.push(m.substr(0, 1));
505
+ m = m.substr(1);
506
+ }
507
+ var n = m.match(/^([0-9]+|\$[a-z]\$|[a-z])\/([0-9]+)(\$[a-z]\$|[a-z])?$/);
508
+ n[1] = n[1].replace(/\$/g, "");
509
+ ret.push({ type_: 'frac', p1: n[1], p2: n[2] });
510
+ if (n[3]) {
511
+ n[3] = n[3].replace(/\$/g, "");
512
+ ret.push({ type_: 'tex-math', p1: n[3] });
513
+ }
514
+ return ret;
515
+ },
516
+ '9,9': function (buffer, m) { return mhchemParser.go(m, '9,9'); }
517
+ },
518
+ //
519
+ // createTransitions
520
+ // convert { 'letter': { 'state': { action_: 'output' } } } to { 'state' => [ { pattern: 'letter', task: { action_: [{type_: 'output'}] } } ] }
521
+ // with expansion of 'a|b' to 'a' and 'b' (at 2 places)
522
+ //
523
+ createTransitions: function (o) {
524
+ var pattern, state;
525
+ /** @type {string[]} */
526
+ var stateArray;
527
+ var i;
528
+ //
529
+ // 1. Collect all states
530
+ //
531
+ /** @type {Transitions} */
532
+ var transitions = {};
533
+ for (pattern in o) {
534
+ for (state in o[pattern]) {
535
+ stateArray = state.split("|");
536
+ o[pattern][state].stateArray = stateArray;
537
+ for (i=0; i<stateArray.length; i++) {
538
+ transitions[stateArray[i]] = [];
539
+ }
540
+ }
541
+ }
542
+ //
543
+ // 2. Fill states
544
+ //
545
+ for (pattern in o) {
546
+ for (state in o[pattern]) {
547
+ stateArray = o[pattern][state].stateArray || [];
548
+ for (i=0; i<stateArray.length; i++) {
549
+ //
550
+ // 2a. Normalize actions into array: 'text=' ==> [{type_:'text='}]
551
+ // (Note to myself: Resolving the function here would be problematic. It would need .bind (for *this*) and currying (for *option*).)
552
+ //
553
+ /** @type {any} */
554
+ var p = o[pattern][state];
555
+ if (p.action_) {
556
+ p.action_ = [].concat(p.action_);
557
+ for (var k=0; k<p.action_.length; k++) {
558
+ if (typeof p.action_[k] === "string") {
559
+ p.action_[k] = { type_: p.action_[k] };
560
+ }
561
+ }
562
+ } else {
563
+ p.action_ = [];
564
+ }
565
+ //
566
+ // 2.b Multi-insert
567
+ //
568
+ var patternArray = pattern.split("|");
569
+ for (var j=0; j<patternArray.length; j++) {
570
+ if (stateArray[i] === '*') { // insert into all
571
+ for (var t in transitions) {
572
+ transitions[t].push({ pattern: patternArray[j], task: p });
573
+ }
574
+ } else {
575
+ transitions[stateArray[i]].push({ pattern: patternArray[j], task: p });
576
+ }
577
+ }
578
+ }
579
+ }
580
+ }
581
+ return transitions;
582
+ },
583
+ stateMachines: {}
584
+ };
585
+
586
+ //
587
+ // Definition of state machines
588
+ //
589
+ mhchemParser.stateMachines = {
590
+ //
591
+ // \ce state machines
592
+ //
593
+ //#region ce
594
+ 'ce': { // main parser
595
+ transitions: mhchemParser.createTransitions({
596
+ 'empty': {
597
+ '*': { action_: 'output' } },
598
+ 'else': {
599
+ '0|1|2': { action_: 'beginsWithBond=false', revisit: true, toContinue: true } },
600
+ 'oxidation$': {
601
+ '0': { action_: 'oxidation-output' } },
602
+ 'CMT': {
603
+ 'r': { action_: 'rdt=', nextState: 'rt' },
604
+ 'rd': { action_: 'rqt=', nextState: 'rdt' } },
605
+ 'arrowUpDown': {
606
+ '0|1|2|as': { action_: [ 'sb=false', 'output', 'operator' ], nextState: '1' } },
607
+ 'uprightEntities': {
608
+ '0|1|2': { action_: [ 'o=', 'output' ], nextState: '1' } },
609
+ 'orbital': {
610
+ '0|1|2|3': { action_: 'o=', nextState: 'o' } },
611
+ '->': {
612
+ '0|1|2|3': { action_: 'r=', nextState: 'r' },
613
+ 'a|as': { action_: [ 'output', 'r=' ], nextState: 'r' },
614
+ '*': { action_: [ 'output', 'r=' ], nextState: 'r' } },
615
+ '+': {
616
+ 'o': { action_: 'd= kv', nextState: 'd' },
617
+ 'd|D': { action_: 'd=', nextState: 'd' },
618
+ 'q': { action_: 'd=', nextState: 'qd' },
619
+ 'qd|qD': { action_: 'd=', nextState: 'qd' },
620
+ 'dq': { action_: [ 'output', 'd=' ], nextState: 'd' },
621
+ '3': { action_: [ 'sb=false', 'output', 'operator' ], nextState: '0' } },
622
+ 'amount': {
623
+ '0|2': { action_: 'a=', nextState: 'a' } },
624
+ 'pm-operator': {
625
+ '0|1|2|a|as': { action_: [ 'sb=false', 'output', { type_: 'operator', option: '\\pm' } ], nextState: '0' } },
626
+ 'operator': {
627
+ '0|1|2|a|as': { action_: [ 'sb=false', 'output', 'operator' ], nextState: '0' } },
628
+ '-$': {
629
+ 'o|q': { action_: [ 'charge or bond', 'output' ], nextState: 'qd' },
630
+ 'd': { action_: 'd=', nextState: 'd' },
631
+ 'D': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' },
632
+ 'q': { action_: 'd=', nextState: 'qd' },
633
+ 'qd': { action_: 'd=', nextState: 'qd' },
634
+ 'qD|dq': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' } },
635
+ '-9': {
636
+ '3|o': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '3' } },
637
+ '- orbital overlap': {
638
+ 'o': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' },
639
+ 'd': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' } },
640
+ '-': {
641
+ '0|1|2': { action_: [ { type_: 'output', option: 1 }, 'beginsWithBond=true', { type_: 'bond', option: "-" } ], nextState: '3' },
642
+ '3': { action_: { type_: 'bond', option: "-" } },
643
+ 'a': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' },
644
+ 'as': { action_: [ { type_: 'output', option: 2 }, { type_: 'bond', option: "-" } ], nextState: '3' },
645
+ 'b': { action_: 'b=' },
646
+ 'o': { action_: { type_: '- after o/d', option: false }, nextState: '2' },
647
+ 'q': { action_: { type_: '- after o/d', option: false }, nextState: '2' },
648
+ 'd|qd|dq': { action_: { type_: '- after o/d', option: true }, nextState: '2' },
649
+ 'D|qD|p': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' } },
650
+ 'amount2': {
651
+ '1|3': { action_: 'a=', nextState: 'a' } },
652
+ 'letters': {
653
+ '0|1|2|3|a|as|b|p|bp|o': { action_: 'o=', nextState: 'o' },
654
+ 'q|dq': { action_: ['output', 'o='], nextState: 'o' },
655
+ 'd|D|qd|qD': { action_: 'o after d', nextState: 'o' } },
656
+ 'digits': {
657
+ 'o': { action_: 'q=', nextState: 'q' },
658
+ 'd|D': { action_: 'q=', nextState: 'dq' },
659
+ 'q': { action_: [ 'output', 'o=' ], nextState: 'o' },
660
+ 'a': { action_: 'o=', nextState: 'o' } },
661
+ 'space A': {
662
+ 'b|p|bp': {} },
663
+ 'space': {
664
+ 'a': { nextState: 'as' },
665
+ '0': { action_: 'sb=false' },
666
+ '1|2': { action_: 'sb=true' },
667
+ 'r|rt|rd|rdt|rdq': { action_: 'output', nextState: '0' },
668
+ '*': { action_: [ 'output', 'sb=true' ], nextState: '1'} },
669
+ '1st-level escape': {
670
+ '1|2': { action_: [ 'output', { type_: 'insert+p1', option: '1st-level escape' } ] },
671
+ '*': { action_: [ 'output', { type_: 'insert+p1', option: '1st-level escape' } ], nextState: '0' } },
672
+ '[(...)]': {
673
+ 'r|rt': { action_: 'rd=', nextState: 'rd' },
674
+ 'rd|rdt': { action_: 'rq=', nextState: 'rdq' } },
675
+ '...': {
676
+ 'o|d|D|dq|qd|qD': { action_: [ 'output', { type_: 'bond', option: "..." } ], nextState: '3' },
677
+ '*': { action_: [ { type_: 'output', option: 1 }, { type_: 'insert', option: 'ellipsis' } ], nextState: '1' } },
678
+ '. |* ': {
679
+ '*': { action_: [ 'output', { type_: 'insert', option: 'addition compound' } ], nextState: '1' } },
680
+ 'state of aggregation $': {
681
+ '*': { action_: [ 'output', 'state of aggregation' ], nextState: '1' } },
682
+ '{[(': {
683
+ 'a|as|o': { action_: [ 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' },
684
+ '0|1|2|3': { action_: [ 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' },
685
+ '*': { action_: [ 'output', 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' } },
686
+ ')]}': {
687
+ '0|1|2|3|b|p|bp|o': { action_: [ 'o=', 'parenthesisLevel--' ], nextState: 'o' },
688
+ 'a|as|d|D|q|qd|qD|dq': { action_: [ 'output', 'o=', 'parenthesisLevel--' ], nextState: 'o' } },
689
+ ', ': {
690
+ '*': { action_: [ 'output', 'comma' ], nextState: '0' } },
691
+ '^_': { // ^ and _ without a sensible argument
692
+ '*': { } },
693
+ '^{(...)}|^($...$)': {
694
+ '0|1|2|as': { action_: 'b=', nextState: 'b' },
695
+ 'p': { action_: 'b=', nextState: 'bp' },
696
+ '3|o': { action_: 'd= kv', nextState: 'D' },
697
+ 'q': { action_: 'd=', nextState: 'qD' },
698
+ 'd|D|qd|qD|dq': { action_: [ 'output', 'd=' ], nextState: 'D' } },
699
+ '^a|^\\x{}{}|^\\x{}|^\\x|\'': {
700
+ '0|1|2|as': { action_: 'b=', nextState: 'b' },
701
+ 'p': { action_: 'b=', nextState: 'bp' },
702
+ '3|o': { action_: 'd= kv', nextState: 'd' },
703
+ 'q': { action_: 'd=', nextState: 'qd' },
704
+ 'd|qd|D|qD': { action_: 'd=' },
705
+ 'dq': { action_: [ 'output', 'd=' ], nextState: 'd' } },
706
+ '_{(state of aggregation)}$': {
707
+ 'd|D|q|qd|qD|dq': { action_: [ 'output', 'q=' ], nextState: 'q' } },
708
+ '_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x': {
709
+ '0|1|2|as': { action_: 'p=', nextState: 'p' },
710
+ 'b': { action_: 'p=', nextState: 'bp' },
711
+ '3|o': { action_: 'q=', nextState: 'q' },
712
+ 'd|D': { action_: 'q=', nextState: 'dq' },
713
+ 'q|qd|qD|dq': { action_: [ 'output', 'q=' ], nextState: 'q' } },
714
+ '=<>': {
715
+ '0|1|2|3|a|as|o|q|d|D|qd|qD|dq': { action_: [ { type_: 'output', option: 2 }, 'bond' ], nextState: '3' } },
716
+ '#': {
717
+ '0|1|2|3|a|as|o': { action_: [ { type_: 'output', option: 2 }, { type_: 'bond', option: "#" } ], nextState: '3' } },
718
+ '{}': {
719
+ '*': { action_: { type_: 'output', option: 1 }, nextState: '1' } },
720
+ '{...}': {
721
+ '0|1|2|3|a|as|b|p|bp': { action_: 'o=', nextState: 'o' },
722
+ 'o|d|D|q|qd|qD|dq': { action_: [ 'output', 'o=' ], nextState: 'o' } },
723
+ '$...$': {
724
+ 'a': { action_: 'a=' }, // 2$n$
725
+ '0|1|2|3|as|b|p|bp|o': { action_: 'o=', nextState: 'o' }, // not 'amount'
726
+ 'as|o': { action_: 'o=' },
727
+ 'q|d|D|qd|qD|dq': { action_: [ 'output', 'o=' ], nextState: 'o' } },
728
+ '\\bond{(...)}': {
729
+ '*': { action_: [ { type_: 'output', option: 2 }, 'bond' ], nextState: "3" } },
730
+ '\\frac{(...)}': {
731
+ '*': { action_: [ { type_: 'output', option: 1 }, 'frac-output' ], nextState: '3' } },
732
+ '\\overset{(...)}': {
733
+ '*': { action_: [ { type_: 'output', option: 2 }, 'overset-output' ], nextState: '3' } },
734
+ '\\underset{(...)}': {
735
+ '*': { action_: [ { type_: 'output', option: 2 }, 'underset-output' ], nextState: '3' } },
736
+ '\\underbrace{(...)}': {
737
+ '*': { action_: [ { type_: 'output', option: 2 }, 'underbrace-output' ], nextState: '3' } },
738
+ '\\color{(...)}{(...)}1|\\color(...){(...)}2': {
739
+ '*': { action_: [ { type_: 'output', option: 2 }, 'color-output' ], nextState: '3' } },
740
+ '\\color{(...)}0': {
741
+ '*': { action_: [ { type_: 'output', option: 2 }, 'color0-output' ] } },
742
+ '\\ce{(...)}': {
743
+ '*': { action_: [ { type_: 'output', option: 2 }, 'ce' ], nextState: '3' } },
744
+ '\\,': {
745
+ '*': { action_: [ { type_: 'output', option: 1 }, 'copy' ], nextState: '1' } },
746
+ '\\x{}{}|\\x{}|\\x': {
747
+ '0|1|2|3|a|as|b|p|bp|o|c0': { action_: [ 'o=', 'output' ], nextState: '3' },
748
+ '*': { action_: ['output', 'o=', 'output' ], nextState: '3' } },
749
+ 'others': {
750
+ '*': { action_: [ { type_: 'output', option: 1 }, 'copy' ], nextState: '3' } },
751
+ 'else2': {
752
+ 'a': { action_: 'a to o', nextState: 'o', revisit: true },
753
+ 'as': { action_: [ 'output', 'sb=true' ], nextState: '1', revisit: true },
754
+ 'r|rt|rd|rdt|rdq': { action_: [ 'output' ], nextState: '0', revisit: true },
755
+ '*': { action_: [ 'output', 'copy' ], nextState: '3' } }
756
+ }),
757
+ actions: {
758
+ 'o after d': function (buffer, m) {
759
+ var ret;
760
+ if ((buffer.d || "").match(/^[0-9]+$/)) {
761
+ var tmp = buffer.d;
762
+ buffer.d = undefined;
763
+ ret = this['output'](buffer);
764
+ buffer.b = tmp;
765
+ } else {
766
+ ret = this['output'](buffer);
767
+ }
768
+ mhchemParser.actions['o='](buffer, m);
769
+ return ret;
770
+ },
771
+ 'd= kv': function (buffer, m) {
772
+ buffer.d = m;
773
+ buffer.dType = 'kv';
774
+ },
775
+ 'charge or bond': function (buffer, m) {
776
+ if (buffer['beginsWithBond']) {
777
+ /** @type {ParserOutput[]} */
778
+ var ret = [];
779
+ mhchemParser.concatArray(ret, this['output'](buffer));
780
+ mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-"));
781
+ return ret;
782
+ } else {
783
+ buffer.d = m;
784
+ }
785
+ },
786
+ '- after o/d': function (buffer, m, isAfterD) {
787
+ var c1 = mhchemParser.patterns.match_('orbital', buffer.o || "");
788
+ var c2 = mhchemParser.patterns.match_('one lowercase greek letter $', buffer.o || "");
789
+ var c3 = mhchemParser.patterns.match_('one lowercase latin letter $', buffer.o || "");
790
+ var c4 = mhchemParser.patterns.match_('$one lowercase latin letter$ $', buffer.o || "");
791
+ var hyphenFollows = m==="-" && ( c1 && c1.remainder==="" || c2 || c3 || c4 );
792
+ if (hyphenFollows && !buffer.a && !buffer.b && !buffer.p && !buffer.d && !buffer.q && !c1 && c3) {
793
+ buffer.o = '$' + buffer.o + '$';
794
+ }
795
+ /** @type {ParserOutput[]} */
796
+ var ret = [];
797
+ if (hyphenFollows) {
798
+ mhchemParser.concatArray(ret, this['output'](buffer));
799
+ ret.push({ type_: 'hyphen' });
800
+ } else {
801
+ c1 = mhchemParser.patterns.match_('digits', buffer.d || "");
802
+ if (isAfterD && c1 && c1.remainder==='') {
803
+ mhchemParser.concatArray(ret, mhchemParser.actions['d='](buffer, m));
804
+ mhchemParser.concatArray(ret, this['output'](buffer));
805
+ } else {
806
+ mhchemParser.concatArray(ret, this['output'](buffer));
807
+ mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-"));
808
+ }
809
+ }
810
+ return ret;
811
+ },
812
+ 'a to o': function (buffer) {
813
+ buffer.o = buffer.a;
814
+ buffer.a = undefined;
815
+ },
816
+ 'sb=true': function (buffer) { buffer.sb = true; },
817
+ 'sb=false': function (buffer) { buffer.sb = false; },
818
+ 'beginsWithBond=true': function (buffer) { buffer['beginsWithBond'] = true; },
819
+ 'beginsWithBond=false': function (buffer) { buffer['beginsWithBond'] = false; },
820
+ 'parenthesisLevel++': function (buffer) { buffer['parenthesisLevel']++; },
821
+ 'parenthesisLevel--': function (buffer) { buffer['parenthesisLevel']--; },
822
+ 'state of aggregation': function (buffer, m) {
823
+ return { type_: 'state of aggregation', p1: mhchemParser.go(m, 'o') };
824
+ },
825
+ 'comma': function (buffer, m) {
826
+ var a = m.replace(/\s*$/, '');
827
+ var withSpace = (a !== m);
828
+ if (withSpace && buffer['parenthesisLevel'] === 0) {
829
+ return { type_: 'comma enumeration L', p1: a };
830
+ } else {
831
+ return { type_: 'comma enumeration M', p1: a };
832
+ }
833
+ },
834
+ 'output': function (buffer, m, entityFollows) {
835
+ // entityFollows:
836
+ // undefined = if we have nothing else to output, also ignore the just read space (buffer.sb)
837
+ // 1 = an entity follows, never omit the space if there was one just read before (can only apply to state 1)
838
+ // 2 = 1 + the entity can have an amount, so output a\, instead of converting it to o (can only apply to states a|as)
839
+ /** @type {ParserOutput | ParserOutput[]} */
840
+ var ret;
841
+ if (!buffer.r) {
842
+ ret = [];
843
+ if (!buffer.a && !buffer.b && !buffer.p && !buffer.o && !buffer.q && !buffer.d && !entityFollows) {
844
+ //ret = [];
845
+ } else {
846
+ if (buffer.sb) {
847
+ ret.push({ type_: 'entitySkip' });
848
+ }
849
+ if (!buffer.o && !buffer.q && !buffer.d && !buffer.b && !buffer.p && entityFollows!==2) {
850
+ buffer.o = buffer.a;
851
+ buffer.a = undefined;
852
+ } else if (!buffer.o && !buffer.q && !buffer.d && (buffer.b || buffer.p)) {
853
+ buffer.o = buffer.a;
854
+ buffer.d = buffer.b;
855
+ buffer.q = buffer.p;
856
+ buffer.a = buffer.b = buffer.p = undefined;
857
+ } else {
858
+ if (buffer.o && buffer.dType==='kv' && mhchemParser.patterns.match_('d-oxidation$', buffer.d || "")) {
859
+ buffer.dType = 'oxidation';
860
+ } else if (buffer.o && buffer.dType==='kv' && !buffer.q) {
861
+ buffer.dType = undefined;
862
+ }
863
+ }
864
+ ret.push({
865
+ type_: 'chemfive',
866
+ a: mhchemParser.go(buffer.a, 'a'),
867
+ b: mhchemParser.go(buffer.b, 'bd'),
868
+ p: mhchemParser.go(buffer.p, 'pq'),
869
+ o: mhchemParser.go(buffer.o, 'o'),
870
+ q: mhchemParser.go(buffer.q, 'pq'),
871
+ d: mhchemParser.go(buffer.d, (buffer.dType === 'oxidation' ? 'oxidation' : 'bd')),
872
+ dType: buffer.dType
873
+ });
874
+ }
875
+ } else { // r
876
+ /** @type {ParserOutput[]} */
877
+ var rd;
878
+ if (buffer.rdt === 'M') {
879
+ rd = mhchemParser.go(buffer.rd, 'tex-math');
880
+ } else if (buffer.rdt === 'T') {
881
+ rd = [ { type_: 'text', p1: buffer.rd || "" } ];
882
+ } else {
883
+ rd = mhchemParser.go(buffer.rd);
884
+ }
885
+ /** @type {ParserOutput[]} */
886
+ var rq;
887
+ if (buffer.rqt === 'M') {
888
+ rq = mhchemParser.go(buffer.rq, 'tex-math');
889
+ } else if (buffer.rqt === 'T') {
890
+ rq = [ { type_: 'text', p1: buffer.rq || ""} ];
891
+ } else {
892
+ rq = mhchemParser.go(buffer.rq);
893
+ }
894
+ ret = {
895
+ type_: 'arrow',
896
+ r: buffer.r,
897
+ rd: rd,
898
+ rq: rq
899
+ };
900
+ }
901
+ for (var p in buffer) {
902
+ if (p !== 'parenthesisLevel' && p !== 'beginsWithBond') {
903
+ delete buffer[p];
904
+ }
905
+ }
906
+ return ret;
907
+ },
908
+ 'oxidation-output': function (buffer, m) {
909
+ var ret = [ "{" ];
910
+ mhchemParser.concatArray(ret, mhchemParser.go(m, 'oxidation'));
911
+ ret.push("}");
912
+ return ret;
913
+ },
914
+ 'frac-output': function (buffer, m) {
915
+ return { type_: 'frac-ce', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) };
916
+ },
917
+ 'overset-output': function (buffer, m) {
918
+ return { type_: 'overset', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) };
919
+ },
920
+ 'underset-output': function (buffer, m) {
921
+ return { type_: 'underset', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) };
922
+ },
923
+ 'underbrace-output': function (buffer, m) {
924
+ return { type_: 'underbrace', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) };
925
+ },
926
+ 'color-output': function (buffer, m) {
927
+ return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1]) };
928
+ },
929
+ 'r=': function (buffer, m) { buffer.r = m; },
930
+ 'rdt=': function (buffer, m) { buffer.rdt = m; },
931
+ 'rd=': function (buffer, m) { buffer.rd = m; },
932
+ 'rqt=': function (buffer, m) { buffer.rqt = m; },
933
+ 'rq=': function (buffer, m) { buffer.rq = m; },
934
+ 'operator': function (buffer, m, p1) { return { type_: 'operator', kind_: (p1 || m) }; }
935
+ }
936
+ },
937
+ 'a': {
938
+ transitions: mhchemParser.createTransitions({
939
+ 'empty': {
940
+ '*': {} },
941
+ '1/2$': {
942
+ '0': { action_: '1/2' } },
943
+ 'else': {
944
+ '0': { nextState: '1', revisit: true } },
945
+ '$(...)$': {
946
+ '*': { action_: 'tex-math tight', nextState: '1' } },
947
+ ',': {
948
+ '*': { action_: { type_: 'insert', option: 'commaDecimal' } } },
949
+ 'else2': {
950
+ '*': { action_: 'copy' } }
951
+ }),
952
+ actions: {}
953
+ },
954
+ 'o': {
955
+ transitions: mhchemParser.createTransitions({
956
+ 'empty': {
957
+ '*': {} },
958
+ '1/2$': {
959
+ '0': { action_: '1/2' } },
960
+ 'else': {
961
+ '0': { nextState: '1', revisit: true } },
962
+ 'letters': {
963
+ '*': { action_: 'rm' } },
964
+ '\\ca': {
965
+ '*': { action_: { type_: 'insert', option: 'circa' } } },
966
+ '\\x{}{}|\\x{}|\\x': {
967
+ '*': { action_: 'copy' } },
968
+ '${(...)}$|$(...)$': {
969
+ '*': { action_: 'tex-math' } },
970
+ '{(...)}': {
971
+ '*': { action_: '{text}' } },
972
+ 'else2': {
973
+ '*': { action_: 'copy' } }
974
+ }),
975
+ actions: {}
976
+ },
977
+ 'text': {
978
+ transitions: mhchemParser.createTransitions({
979
+ 'empty': {
980
+ '*': { action_: 'output' } },
981
+ '{...}': {
982
+ '*': { action_: 'text=' } },
983
+ '${(...)}$|$(...)$': {
984
+ '*': { action_: 'tex-math' } },
985
+ '\\greek': {
986
+ '*': { action_: [ 'output', 'rm' ] } },
987
+ '\\,|\\x{}{}|\\x{}|\\x': {
988
+ '*': { action_: [ 'output', 'copy' ] } },
989
+ 'else': {
990
+ '*': { action_: 'text=' } }
991
+ }),
992
+ actions: {
993
+ 'output': function (buffer) {
994
+ if (buffer.text_) {
995
+ /** @type {ParserOutput} */
996
+ var ret = { type_: 'text', p1: buffer.text_ };
997
+ for (var p in buffer) { delete buffer[p]; }
998
+ return ret;
999
+ }
1000
+ }
1001
+ }
1002
+ },
1003
+ 'pq': {
1004
+ transitions: mhchemParser.createTransitions({
1005
+ 'empty': {
1006
+ '*': {} },
1007
+ 'state of aggregation $': {
1008
+ '*': { action_: 'state of aggregation' } },
1009
+ 'i$': {
1010
+ '0': { nextState: '!f', revisit: true } },
1011
+ '(KV letters),': {
1012
+ '0': { action_: 'rm', nextState: '0' } },
1013
+ 'formula$': {
1014
+ '0': { nextState: 'f', revisit: true } },
1015
+ '1/2$': {
1016
+ '0': { action_: '1/2' } },
1017
+ 'else': {
1018
+ '0': { nextState: '!f', revisit: true } },
1019
+ '${(...)}$|$(...)$': {
1020
+ '*': { action_: 'tex-math' } },
1021
+ '{(...)}': {
1022
+ '*': { action_: 'text' } },
1023
+ 'a-z': {
1024
+ 'f': { action_: 'tex-math' } },
1025
+ 'letters': {
1026
+ '*': { action_: 'rm' } },
1027
+ '-9.,9': {
1028
+ '*': { action_: '9,9' } },
1029
+ ',': {
1030
+ '*': { action_: { type_: 'insert+p1', option: 'comma enumeration S' } } },
1031
+ '\\color{(...)}{(...)}1|\\color(...){(...)}2': {
1032
+ '*': { action_: 'color-output' } },
1033
+ '\\color{(...)}0': {
1034
+ '*': { action_: 'color0-output' } },
1035
+ '\\ce{(...)}': {
1036
+ '*': { action_: 'ce' } },
1037
+ '\\,|\\x{}{}|\\x{}|\\x': {
1038
+ '*': { action_: 'copy' } },
1039
+ 'else2': {
1040
+ '*': { action_: 'copy' } }
1041
+ }),
1042
+ actions: {
1043
+ 'state of aggregation': function (buffer, m) {
1044
+ return { type_: 'state of aggregation subscript', p1: mhchemParser.go(m, 'o') };
1045
+ },
1046
+ 'color-output': function (buffer, m) {
1047
+ return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1], 'pq') };
1048
+ }
1049
+ }
1050
+ },
1051
+ 'bd': {
1052
+ transitions: mhchemParser.createTransitions({
1053
+ 'empty': {
1054
+ '*': {} },
1055
+ 'x$': {
1056
+ '0': { nextState: '!f', revisit: true } },
1057
+ 'formula$': {
1058
+ '0': { nextState: 'f', revisit: true } },
1059
+ 'else': {
1060
+ '0': { nextState: '!f', revisit: true } },
1061
+ '-9.,9 no missing 0': {
1062
+ '*': { action_: '9,9' } },
1063
+ '.': {
1064
+ '*': { action_: { type_: 'insert', option: 'electron dot' } } },
1065
+ 'a-z': {
1066
+ 'f': { action_: 'tex-math' } },
1067
+ 'x': {
1068
+ '*': { action_: { type_: 'insert', option: 'KV x' } } },
1069
+ 'letters': {
1070
+ '*': { action_: 'rm' } },
1071
+ '\'': {
1072
+ '*': { action_: { type_: 'insert', option: 'prime' } } },
1073
+ '${(...)}$|$(...)$': {
1074
+ '*': { action_: 'tex-math' } },
1075
+ '{(...)}': {
1076
+ '*': { action_: 'text' } },
1077
+ '\\color{(...)}{(...)}1|\\color(...){(...)}2': {
1078
+ '*': { action_: 'color-output' } },
1079
+ '\\color{(...)}0': {
1080
+ '*': { action_: 'color0-output' } },
1081
+ '\\ce{(...)}': {
1082
+ '*': { action_: 'ce' } },
1083
+ '\\,|\\x{}{}|\\x{}|\\x': {
1084
+ '*': { action_: 'copy' } },
1085
+ 'else2': {
1086
+ '*': { action_: 'copy' } }
1087
+ }),
1088
+ actions: {
1089
+ 'color-output': function (buffer, m) {
1090
+ return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1], 'bd') };
1091
+ }
1092
+ }
1093
+ },
1094
+ 'oxidation': {
1095
+ transitions: mhchemParser.createTransitions({
1096
+ 'empty': {
1097
+ '*': {} },
1098
+ 'roman numeral': {
1099
+ '*': { action_: 'roman-numeral' } },
1100
+ '${(...)}$|$(...)$': {
1101
+ '*': { action_: 'tex-math' } },
1102
+ 'else': {
1103
+ '*': { action_: 'copy' } }
1104
+ }),
1105
+ actions: {
1106
+ 'roman-numeral': function (buffer, m) { return { type_: 'roman numeral', p1: m || "" }; }
1107
+ }
1108
+ },
1109
+ 'tex-math': {
1110
+ transitions: mhchemParser.createTransitions({
1111
+ 'empty': {
1112
+ '*': { action_: 'output' } },
1113
+ '\\ce{(...)}': {
1114
+ '*': { action_: [ 'output', 'ce' ] } },
1115
+ '{...}|\\,|\\x{}{}|\\x{}|\\x': {
1116
+ '*': { action_: 'o=' } },
1117
+ 'else': {
1118
+ '*': { action_: 'o=' } }
1119
+ }),
1120
+ actions: {
1121
+ 'output': function (buffer) {
1122
+ if (buffer.o) {
1123
+ /** @type {ParserOutput} */
1124
+ var ret = { type_: 'tex-math', p1: buffer.o };
1125
+ for (var p in buffer) { delete buffer[p]; }
1126
+ return ret;
1127
+ }
1128
+ }
1129
+ }
1130
+ },
1131
+ 'tex-math tight': {
1132
+ transitions: mhchemParser.createTransitions({
1133
+ 'empty': {
1134
+ '*': { action_: 'output' } },
1135
+ '\\ce{(...)}': {
1136
+ '*': { action_: [ 'output', 'ce' ] } },
1137
+ '{...}|\\,|\\x{}{}|\\x{}|\\x': {
1138
+ '*': { action_: 'o=' } },
1139
+ '-|+': {
1140
+ '*': { action_: 'tight operator' } },
1141
+ 'else': {
1142
+ '*': { action_: 'o=' } }
1143
+ }),
1144
+ actions: {
1145
+ 'tight operator': function (buffer, m) { buffer.o = (buffer.o || "") + "{"+m+"}"; },
1146
+ 'output': function (buffer) {
1147
+ if (buffer.o) {
1148
+ /** @type {ParserOutput} */
1149
+ var ret = { type_: 'tex-math', p1: buffer.o };
1150
+ for (var p in buffer) { delete buffer[p]; }
1151
+ return ret;
1152
+ }
1153
+ }
1154
+ }
1155
+ },
1156
+ '9,9': {
1157
+ transitions: mhchemParser.createTransitions({
1158
+ 'empty': {
1159
+ '*': {} },
1160
+ ',': {
1161
+ '*': { action_: 'comma' } },
1162
+ 'else': {
1163
+ '*': { action_: 'copy' } }
1164
+ }),
1165
+ actions: {
1166
+ 'comma': function () { return { type_: 'commaDecimal' }; }
1167
+ }
1168
+ },
1169
+ //#endregion
1170
+ //
1171
+ // \pu state machines
1172
+ //
1173
+ //#region pu
1174
+ 'pu': {
1175
+ transitions: mhchemParser.createTransitions({
1176
+ 'empty': {
1177
+ '*': { action_: 'output' } },
1178
+ 'space$': {
1179
+ '*': { action_: [ 'output', 'space' ] } },
1180
+ '{[(|)]}': {
1181
+ '0|a': { action_: 'copy' } },
1182
+ '(-)(9)^(-9)': {
1183
+ '0': { action_: 'number^', nextState: 'a' } },
1184
+ '(-)(9.,9)(e)(99)': {
1185
+ '0': { action_: 'enumber', nextState: 'a' } },
1186
+ 'space': {
1187
+ '0|a': {} },
1188
+ 'pm-operator': {
1189
+ '0|a': { action_: { type_: 'operator', option: '\\pm' }, nextState: '0' } },
1190
+ 'operator': {
1191
+ '0|a': { action_: 'copy', nextState: '0' } },
1192
+ '//': {
1193
+ 'd': { action_: 'o=', nextState: '/' } },
1194
+ '/': {
1195
+ 'd': { action_: 'o=', nextState: '/' } },
1196
+ '{...}|else': {
1197
+ '0|d': { action_: 'd=', nextState: 'd' },
1198
+ 'a': { action_: [ 'space', 'd=' ], nextState: 'd' },
1199
+ '/|q': { action_: 'q=', nextState: 'q' } }
1200
+ }),
1201
+ actions: {
1202
+ 'enumber': function (buffer, m) {
1203
+ /** @type {ParserOutput[]} */
1204
+ var ret = [];
1205
+ if (m[0] === "+-" || m[0] === "+/-") {
1206
+ ret.push("\\pm ");
1207
+ } else if (m[0]) {
1208
+ ret.push(m[0]);
1209
+ }
1210
+ if (m[1]) {
1211
+ mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9'));
1212
+ if (m[2]) {
1213
+ if (m[2].match(/[,.]/)) {
1214
+ mhchemParser.concatArray(ret, mhchemParser.go(m[2], 'pu-9,9'));
1215
+ } else {
1216
+ ret.push(m[2]);
1217
+ }
1218
+ }
1219
+ m[3] = m[4] || m[3];
1220
+ if (m[3]) {
1221
+ m[3] = m[3].trim();
1222
+ if (m[3] === "e" || m[3].substr(0, 1) === "*") {
1223
+ ret.push({ type_: 'cdot' });
1224
+ } else {
1225
+ ret.push({ type_: 'times' });
1226
+ }
1227
+ }
1228
+ }
1229
+ if (m[3]) {
1230
+ ret.push("10^{"+m[5]+"}");
1231
+ }
1232
+ return ret;
1233
+ },
1234
+ 'number^': function (buffer, m) {
1235
+ /** @type {ParserOutput[]} */
1236
+ var ret = [];
1237
+ if (m[0] === "+-" || m[0] === "+/-") {
1238
+ ret.push("\\pm ");
1239
+ } else if (m[0]) {
1240
+ ret.push(m[0]);
1241
+ }
1242
+ mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9'));
1243
+ ret.push("^{"+m[2]+"}");
1244
+ return ret;
1245
+ },
1246
+ 'operator': function (buffer, m, p1) { return { type_: 'operator', kind_: (p1 || m) }; },
1247
+ 'space': function () { return { type_: 'pu-space-1' }; },
1248
+ 'output': function (buffer) {
1249
+ /** @type {ParserOutput | ParserOutput[]} */
1250
+ var ret;
1251
+ var md = mhchemParser.patterns.match_('{(...)}', buffer.d || "");
1252
+ if (md && md.remainder === '') { buffer.d = md.match_; }
1253
+ var mq = mhchemParser.patterns.match_('{(...)}', buffer.q || "");
1254
+ if (mq && mq.remainder === '') { buffer.q = mq.match_; }
1255
+ if (buffer.d) {
1256
+ buffer.d = buffer.d.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C");
1257
+ buffer.d = buffer.d.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F");
1258
+ }
1259
+ if (buffer.q) { // fraction
1260
+ buffer.q = buffer.q.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C");
1261
+ buffer.q = buffer.q.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F");
1262
+ var b5 = {
1263
+ d: mhchemParser.go(buffer.d, 'pu'),
1264
+ q: mhchemParser.go(buffer.q, 'pu')
1265
+ };
1266
+ if (buffer.o === '//') {
1267
+ ret = { type_: 'pu-frac', p1: b5.d, p2: b5.q };
1268
+ } else {
1269
+ ret = b5.d;
1270
+ if (b5.d.length > 1 || b5.q.length > 1) {
1271
+ ret.push({ type_: ' / ' });
1272
+ } else {
1273
+ ret.push({ type_: '/' });
1274
+ }
1275
+ mhchemParser.concatArray(ret, b5.q);
1276
+ }
1277
+ } else { // no fraction
1278
+ ret = mhchemParser.go(buffer.d, 'pu-2');
1279
+ }
1280
+ for (var p in buffer) { delete buffer[p]; }
1281
+ return ret;
1282
+ }
1283
+ }
1284
+ },
1285
+ 'pu-2': {
1286
+ transitions: mhchemParser.createTransitions({
1287
+ 'empty': {
1288
+ '*': { action_: 'output' } },
1289
+ '*': {
1290
+ '*': { action_: [ 'output', 'cdot' ], nextState: '0' } },
1291
+ '\\x': {
1292
+ '*': { action_: 'rm=' } },
1293
+ 'space': {
1294
+ '*': { action_: [ 'output', 'space' ], nextState: '0' } },
1295
+ '^{(...)}|^(-1)': {
1296
+ '1': { action_: '^(-1)' } },
1297
+ '-9.,9': {
1298
+ '0': { action_: 'rm=', nextState: '0' },
1299
+ '1': { action_: '^(-1)', nextState: '0' } },
1300
+ '{...}|else': {
1301
+ '*': { action_: 'rm=', nextState: '1' } }
1302
+ }),
1303
+ actions: {
1304
+ 'cdot': function () { return { type_: 'tight cdot' }; },
1305
+ '^(-1)': function (buffer, m) { buffer.rm += "^{"+m+"}"; },
1306
+ 'space': function () { return { type_: 'pu-space-2' }; },
1307
+ 'output': function (buffer) {
1308
+ /** @type {ParserOutput | ParserOutput[]} */
1309
+ var ret = [];
1310
+ if (buffer.rm) {
1311
+ var mrm = mhchemParser.patterns.match_('{(...)}', buffer.rm || "");
1312
+ if (mrm && mrm.remainder === '') {
1313
+ ret = mhchemParser.go(mrm.match_, 'pu');
1314
+ } else {
1315
+ ret = { type_: 'rm', p1: buffer.rm };
1316
+ }
1317
+ }
1318
+ for (var p in buffer) { delete buffer[p]; }
1319
+ return ret;
1320
+ }
1321
+ }
1322
+ },
1323
+ 'pu-9,9': {
1324
+ transitions: mhchemParser.createTransitions({
1325
+ 'empty': {
1326
+ '0': { action_: 'output-0' },
1327
+ 'o': { action_: 'output-o' } },
1328
+ ',': {
1329
+ '0': { action_: [ 'output-0', 'comma' ], nextState: 'o' } },
1330
+ '.': {
1331
+ '0': { action_: [ 'output-0', 'copy' ], nextState: 'o' } },
1332
+ 'else': {
1333
+ '*': { action_: 'text=' } }
1334
+ }),
1335
+ actions: {
1336
+ 'comma': function () { return { type_: 'commaDecimal' }; },
1337
+ 'output-0': function (buffer) {
1338
+ /** @type {ParserOutput[]} */
1339
+ var ret = [];
1340
+ buffer.text_ = buffer.text_ || "";
1341
+ if (buffer.text_.length > 4) {
1342
+ var a = buffer.text_.length % 3;
1343
+ if (a === 0) { a = 3; }
1344
+ for (var i=buffer.text_.length-3; i>0; i-=3) {
1345
+ ret.push(buffer.text_.substr(i, 3));
1346
+ ret.push({ type_: '1000 separator' });
1347
+ }
1348
+ ret.push(buffer.text_.substr(0, a));
1349
+ ret.reverse();
1350
+ } else {
1351
+ ret.push(buffer.text_);
1352
+ }
1353
+ for (var p in buffer) { delete buffer[p]; }
1354
+ return ret;
1355
+ },
1356
+ 'output-o': function (buffer) {
1357
+ /** @type {ParserOutput[]} */
1358
+ var ret = [];
1359
+ buffer.text_ = buffer.text_ || "";
1360
+ if (buffer.text_.length > 4) {
1361
+ var a = buffer.text_.length - 3;
1362
+ for (var i=0; i<a; i+=3) {
1363
+ ret.push(buffer.text_.substr(i, 3));
1364
+ ret.push({ type_: '1000 separator' });
1365
+ }
1366
+ ret.push(buffer.text_.substr(i));
1367
+ } else {
1368
+ ret.push(buffer.text_);
1369
+ }
1370
+ for (var p in buffer) { delete buffer[p]; }
1371
+ return ret;
1372
+ }
1373
+ }
1374
+ }
1375
+ //#endregion
1376
+ };
1377
+
1378
+ //
1379
+ // texify: Take MhchemParser output and convert it to TeX
1380
+ //
1381
+ /** @type {Texify} */
1382
+ var texify = {
1383
+ go: function (input, isInner) { // (recursive, max 4 levels)
1384
+ if (!input) { return ""; }
1385
+ var res = "";
1386
+ var cee = false;
1387
+ for (var i=0; i < input.length; i++) {
1388
+ var inputi = input[i];
1389
+ if (typeof inputi === "string") {
1390
+ res += inputi;
1391
+ } else {
1392
+ res += texify._go2(inputi);
1393
+ if (inputi.type_ === '1st-level escape') { cee = true; }
1394
+ }
1395
+ }
1396
+ if (!isInner && !cee && res) {
1397
+ res = "{" + res + "}";
1398
+ }
1399
+ return res;
1400
+ },
1401
+ _goInner: function (input) {
1402
+ if (!input) { return input; }
1403
+ return texify.go(input, true);
1404
+ },
1405
+ _go2: function (buf) {
1406
+ /** @type {undefined | string} */
1407
+ var res;
1408
+ switch (buf.type_) {
1409
+ case 'chemfive':
1410
+ res = "";
1411
+ var b5 = {
1412
+ a: texify._goInner(buf.a),
1413
+ b: texify._goInner(buf.b),
1414
+ p: texify._goInner(buf.p),
1415
+ o: texify._goInner(buf.o),
1416
+ q: texify._goInner(buf.q),
1417
+ d: texify._goInner(buf.d)
1418
+ };
1419
+ //
1420
+ // a
1421
+ //
1422
+ if (b5.a) {
1423
+ if (b5.a.match(/^[+\-]/)) { b5.a = "{"+b5.a+"}"; }
1424
+ res += b5.a + "\\,";
1425
+ }
1426
+ //
1427
+ // b and p
1428
+ //
1429
+ if (b5.b || b5.p) {
1430
+ res += "{\\vphantom{X}}";
1431
+ res += "^{\\hphantom{"+(b5.b||"")+"}}_{\\hphantom{"+(b5.p||"")+"}}";
1432
+ res += "{\\vphantom{X}}";
1433
+ res += "^{\\smash[t]{\\vphantom{2}}\\mathllap{"+(b5.b||"")+"}}";
1434
+ res += "_{\\vphantom{2}\\mathllap{\\smash[t]{"+(b5.p||"")+"}}}";
1435
+ }
1436
+ //
1437
+ // o
1438
+ //
1439
+ if (b5.o) {
1440
+ if (b5.o.match(/^[+\-]/)) { b5.o = "{"+b5.o+"}"; }
1441
+ res += b5.o;
1442
+ }
1443
+ //
1444
+ // q and d
1445
+ //
1446
+ if (buf.dType === 'kv') {
1447
+ if (b5.d || b5.q) {
1448
+ res += "{\\vphantom{X}}";
1449
+ }
1450
+ if (b5.d) {
1451
+ res += "^{"+b5.d+"}";
1452
+ }
1453
+ if (b5.q) {
1454
+ res += "_{\\smash[t]{"+b5.q+"}}";
1455
+ }
1456
+ } else if (buf.dType === 'oxidation') {
1457
+ if (b5.d) {
1458
+ res += "{\\vphantom{X}}";
1459
+ res += "^{"+b5.d+"}";
1460
+ }
1461
+ if (b5.q) {
1462
+ // A Firefox bug adds a bogus depth to <mphantom>, so we change \vphantom{X} to {}
1463
+ // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed.
1464
+ // res += "{\\vphantom{X}}";
1465
+ res += "{{}}";
1466
+ res += "_{\\smash[t]{"+b5.q+"}}";
1467
+ }
1468
+ } else {
1469
+ if (b5.q) {
1470
+ // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed.
1471
+ // res += "{\\vphantom{X}}";
1472
+ res += "{{}}";
1473
+ res += "_{\\smash[t]{"+b5.q+"}}";
1474
+ }
1475
+ if (b5.d) {
1476
+ // TODO: Reinstate \vphantom{X} when the Firefox bug is fixed.
1477
+ // res += "{\\vphantom{X}}";
1478
+ res += "{{}}";
1479
+ res += "^{"+b5.d+"}";
1480
+ }
1481
+ }
1482
+ break;
1483
+ case 'rm':
1484
+ res = "\\mathrm{"+buf.p1+"}";
1485
+ break;
1486
+ case 'text':
1487
+ if (buf.p1.match(/[\^_]/)) {
1488
+ buf.p1 = buf.p1.replace(" ", "~").replace("-", "\\text{-}");
1489
+ res = "\\mathrm{"+buf.p1+"}";
1490
+ } else {
1491
+ res = "\\text{"+buf.p1+"}";
1492
+ }
1493
+ break;
1494
+ case 'roman numeral':
1495
+ res = "\\mathrm{"+buf.p1+"}";
1496
+ break;
1497
+ case 'state of aggregation':
1498
+ res = "\\mskip2mu "+texify._goInner(buf.p1);
1499
+ break;
1500
+ case 'state of aggregation subscript':
1501
+ res = "\\mskip1mu "+texify._goInner(buf.p1);
1502
+ break;
1503
+ case 'bond':
1504
+ res = texify._getBond(buf.kind_);
1505
+ if (!res) {
1506
+ throw ["MhchemErrorBond", "mhchem Error. Unknown bond type (" + buf.kind_ + ")"];
1507
+ }
1508
+ break;
1509
+ case 'frac':
1510
+ var c = "\\frac{" + buf.p1 + "}{" + buf.p2 + "}";
1511
+ res = "\\mathchoice{\\textstyle"+c+"}{"+c+"}{"+c+"}{"+c+"}";
1512
+ break;
1513
+ case 'pu-frac':
1514
+ var d = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}";
1515
+ res = "\\mathchoice{\\textstyle"+d+"}{"+d+"}{"+d+"}{"+d+"}";
1516
+ break;
1517
+ case 'tex-math':
1518
+ res = buf.p1 + " ";
1519
+ break;
1520
+ case 'frac-ce':
1521
+ res = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}";
1522
+ break;
1523
+ case 'overset':
1524
+ res = "\\overset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}";
1525
+ break;
1526
+ case 'underset':
1527
+ res = "\\underset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}";
1528
+ break;
1529
+ case 'underbrace':
1530
+ res = "\\underbrace{" + texify._goInner(buf.p1) + "}_{" + texify._goInner(buf.p2) + "}";
1531
+ break;
1532
+ case 'color':
1533
+ res = "{\\color{" + buf.color1 + "}{" + texify._goInner(buf.color2) + "}}";
1534
+ break;
1535
+ case 'color0':
1536
+ res = "\\color{" + buf.color + "}";
1537
+ break;
1538
+ case 'arrow':
1539
+ var b6 = {
1540
+ rd: texify._goInner(buf.rd),
1541
+ rq: texify._goInner(buf.rq)
1542
+ };
1543
+ var arrow = texify._getArrow(buf.r);
1544
+ if (b6.rq) { arrow += "[{\\rm " + b6.rq + "}]"; }
1545
+ if (b6.rd) {
1546
+ arrow += "{\\rm " + b6.rd + "}";
1547
+ } else {
1548
+ arrow += "{}";
1549
+ }
1550
+ res = arrow;
1551
+ break;
1552
+ case 'operator':
1553
+ res = texify._getOperator(buf.kind_);
1554
+ break;
1555
+ case '1st-level escape':
1556
+ res = buf.p1+" "; // &, \\\\, \\hlin
1557
+ break;
1558
+ case 'space':
1559
+ res = " ";
1560
+ break;
1561
+ case 'entitySkip':
1562
+ res = "~";
1563
+ break;
1564
+ case 'pu-space-1':
1565
+ res = "~";
1566
+ break;
1567
+ case 'pu-space-2':
1568
+ res = "\\mkern3mu ";
1569
+ break;
1570
+ case '1000 separator':
1571
+ res = "\\mkern2mu ";
1572
+ break;
1573
+ case 'commaDecimal':
1574
+ res = "{,}";
1575
+ break;
1576
+ case 'comma enumeration L':
1577
+ res = "{"+buf.p1+"}\\mkern6mu ";
1578
+ break;
1579
+ case 'comma enumeration M':
1580
+ res = "{"+buf.p1+"}\\mkern3mu ";
1581
+ break;
1582
+ case 'comma enumeration S':
1583
+ res = "{"+buf.p1+"}\\mkern1mu ";
1584
+ break;
1585
+ case 'hyphen':
1586
+ res = "\\text{-}";
1587
+ break;
1588
+ case 'addition compound':
1589
+ res = "\\,{\\cdot}\\,";
1590
+ break;
1591
+ case 'electron dot':
1592
+ res = "\\mkern1mu \\text{\\textbullet}\\mkern1mu ";
1593
+ break;
1594
+ case 'KV x':
1595
+ res = "{\\times}";
1596
+ break;
1597
+ case 'prime':
1598
+ res = "\\prime ";
1599
+ break;
1600
+ case 'cdot':
1601
+ res = "\\cdot ";
1602
+ break;
1603
+ case 'tight cdot':
1604
+ res = "\\mkern1mu{\\cdot}\\mkern1mu ";
1605
+ break;
1606
+ case 'times':
1607
+ res = "\\times ";
1608
+ break;
1609
+ case 'circa':
1610
+ res = "{\\sim}";
1611
+ break;
1612
+ case '^':
1613
+ res = "uparrow";
1614
+ break;
1615
+ case 'v':
1616
+ res = "downarrow";
1617
+ break;
1618
+ case 'ellipsis':
1619
+ res = "\\ldots ";
1620
+ break;
1621
+ case '/':
1622
+ res = "/";
1623
+ break;
1624
+ case ' / ':
1625
+ res = "\\,/\\,";
1626
+ break;
1627
+ default:
1628
+ assertNever(buf);
1629
+ throw ["MhchemBugT", "mhchem bug T. Please report."]; // Missing texify rule or unknown MhchemParser output
1630
+ }
1631
+ assertString(res);
1632
+ return res;
1633
+ },
1634
+ _getArrow: function (a) {
1635
+ switch (a) {
1636
+ case "->": return "\\yields";
1637
+ case "\u2192": return "\\yields";
1638
+ case "\u27F6": return "\\yields";
1639
+ case "<-": return "\\yieldsLeft";
1640
+ case "<->": return "\\mesomerism";
1641
+ case "<-->": return "\\yieldsLeftRight";
1642
+ case "<=>": return "\\equilibrium";
1643
+ case "\u21CC": return "\\equilibrium";
1644
+ case "<=>>": return "\\equilibriumRight";
1645
+ case "<<=>": return "\\equilibriumLeft";
1646
+ default:
1647
+ assertNever(a);
1648
+ throw ["MhchemBugT", "mhchem bug T. Please report."];
1649
+ }
1650
+ },
1651
+ _getBond: function (a) {
1652
+ switch (a) {
1653
+ case "-": return "{-}";
1654
+ case "1": return "{-}";
1655
+ case "=": return "{=}";
1656
+ case "2": return "{=}";
1657
+ case "#": return "{\\equiv}";
1658
+ case "3": return "{\\equiv}";
1659
+ case "~": return "{\\tripleDash}";
1660
+ case "~-": return "{\\tripleDashOverLine}";
1661
+ case "~=": return "{\\tripleDashOverDoubleLine}";
1662
+ case "~--": return "{\\tripleDashOverDoubleLine}";
1663
+ case "-~-": return "{\\tripleDashBetweenDoubleLine}";
1664
+ case "...": return "{{\\cdot}{\\cdot}{\\cdot}}";
1665
+ case "....": return "{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}";
1666
+ case "->": return "{\\rightarrow}";
1667
+ case "<-": return "{\\leftarrow}";
1668
+ case "<": return "{<}";
1669
+ case ">": return "{>}";
1670
+ default:
1671
+ assertNever(a);
1672
+ throw ["MhchemBugT", "mhchem bug T. Please report."];
1673
+ }
1674
+ },
1675
+ _getOperator: function (a) {
1676
+ switch (a) {
1677
+ case "+": return " {}+{} ";
1678
+ case "-": return " {}-{} ";
1679
+ case "=": return " {}={} ";
1680
+ case "<": return " {}<{} ";
1681
+ case ">": return " {}>{} ";
1682
+ case "<<": return " {}\\ll{} ";
1683
+ case ">>": return " {}\\gg{} ";
1684
+ case "\\pm": return " {}\\pm{} ";
1685
+ case "\\approx": return " {}\\approx{} ";
1686
+ case "$\\approx$": return " {}\\approx{} ";
1687
+ case "v": return " \\downarrow{} ";
1688
+ case "(v)": return " \\downarrow{} ";
1689
+ case "^": return " \\uparrow{} ";
1690
+ case "(^)": return " \\uparrow{} ";
1691
+ default:
1692
+ assertNever(a);
1693
+ throw ["MhchemBugT", "mhchem bug T. Please report."];
1694
+ }
1695
+ }
1696
+ };
1697
+
1698
+ //
1699
+ // Helpers for code anaylsis
1700
+ // Will show type error at calling position
1701
+ //
1702
+ /** @param {number} a */
1703
+ function assertNever(a) {}
1704
+ /** @param {string} a */
1705
+ function assertString(a) {}