temml 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
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) {}