| import katex from '../katex.mjs'; |
| |
| /* eslint-disable */ |
| |
| /* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ |
| |
| /* vim: set ts=2 et sw=2 tw=80: */ |
| |
| /************************************************************* |
| * |
| * KaTeX mhchem.js |
| * |
| * This file implements a KaTeX version of mhchem version 3.3.0. |
| * It is adapted from MathJax/extensions/TeX/mhchem.js |
| * It differs from the MathJax version as follows: |
| * 1. The interface is changed so that it can be called from KaTeX, not MathJax. |
| * 2. \rlap and \llap are replaced with \mathrlap and \mathllap. |
| * 3. Four lines of code are edited in order to use \raisebox instead of \raise. |
| * 4. The reaction arrow code is simplified. All reaction arrows are rendered |
| * using KaTeX extensible arrows instead of building non-extensible arrows. |
| * 5. \tripledash vertical alignment is slightly adjusted. |
| * |
| * This code, as other KaTeX code, is released under the MIT license. |
| * |
| * /************************************************************* |
| * |
| * MathJax/extensions/TeX/mhchem.js |
| * |
| * Implements the \ce command for handling chemical formulas |
| * from the mhchem LaTeX package. |
| * |
| * --------------------------------------------------------------------- |
| * |
| * Copyright (c) 2011-2015 The MathJax Consortium |
| * Copyright (c) 2015-2018 Martin Hensel |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| // |
| // Coding Style |
| // - use '' for identifiers that can by minified/uglified |
| // - use "" for strings that need to stay untouched |
| // version: "3.3.0" for MathJax and KaTeX |
| // Add \ce, \pu, and \tripledash to the KaTeX macros. |
| katex.__defineMacro("\\ce", function (context) { |
| return chemParse(context.consumeArgs(1)[0], "ce"); |
| }); |
| |
| katex.__defineMacro("\\pu", function (context) { |
| return chemParse(context.consumeArgs(1)[0], "pu"); |
| }); // Needed for \bond for the ~ forms |
| // Raise by 2.56mu, not 2mu. We're raising a hyphen-minus, U+002D, not |
| // a mathematical minus, U+2212. So we need that extra 0.56. |
| |
| |
| katex.__defineMacro("\\tripledash", "{\\vphantom{-}\\raisebox{2.56mu}{$\\mkern2mu" + "\\tiny\\text{-}\\mkern1mu\\text{-}\\mkern1mu\\text{-}\\mkern2mu$}}"); |
| // This is the main function for handing the \ce and \pu commands. |
| // It takes the argument to \ce or \pu and returns the corresponding TeX string. |
| // |
| |
| var chemParse = function chemParse(tokens, stateMachine) { |
| // Recreate the argument string from KaTeX's array of tokens. |
| var str = ""; |
| var expectedLoc = tokens[tokens.length - 1].loc.start; |
| |
| for (var i = tokens.length - 1; i >= 0; i--) { |
| if (tokens[i].loc.start > expectedLoc) { |
| // context.consumeArgs has eaten a space. |
| str += " "; |
| expectedLoc = tokens[i].loc.start; |
| } |
| |
| str += tokens[i].text; |
| expectedLoc += tokens[i].text.length; |
| } |
| |
| var tex = texify.go(mhchemParser.go(str, stateMachine)); |
| return tex; |
| }; // |
| // Core parser for mhchem syntax (recursive) |
| // |
| |
| /** @type {MhchemParser} */ |
| |
| |
| var mhchemParser = { |
| // |
| // Parses mchem \ce syntax |
| // |
| // Call like |
| // go("H2O"); |
| // |
| go: function go(input, stateMachine) { |
| if (!input) { |
| return []; |
| } |
| |
| if (stateMachine === undefined) { |
| stateMachine = 'ce'; |
| } |
| |
| var state = '0'; // |
| // String buffers for parsing: |
| // |
| // buffer.a == amount |
| // buffer.o == element |
| // buffer.b == left-side superscript |
| // buffer.p == left-side subscript |
| // buffer.q == right-side subscript |
| // buffer.d == right-side superscript |
| // |
| // buffer.r == arrow |
| // buffer.rdt == arrow, script above, type |
| // buffer.rd == arrow, script above, content |
| // buffer.rqt == arrow, script below, type |
| // buffer.rq == arrow, script below, content |
| // |
| // buffer.text_ |
| // buffer.rm |
| // etc. |
| // |
| // buffer.parenthesisLevel == int, starting at 0 |
| // buffer.sb == bool, space before |
| // buffer.beginsWithBond == bool |
| // |
| // These letters are also used as state names. |
| // |
| // Other states: |
| // 0 == begin of main part (arrow/operator unlikely) |
| // 1 == next entity |
| // 2 == next entity (arrow/operator unlikely) |
| // 3 == next atom |
| // c == macro |
| // |
| |
| /** @type {Buffer} */ |
| |
| var buffer = {}; |
| buffer['parenthesisLevel'] = 0; |
| input = input.replace(/\n/g, " "); |
| input = input.replace(/[\u2212\u2013\u2014\u2010]/g, "-"); |
| input = input.replace(/[\u2026]/g, "..."); // |
| // Looks through mhchemParser.transitions, to execute a matching action |
| // (recursive) |
| // |
| |
| var lastInput; |
| var watchdog = 10; |
| /** @type {ParserOutput[]} */ |
| |
| var output = []; |
| |
| while (true) { |
| if (lastInput !== input) { |
| watchdog = 10; |
| lastInput = input; |
| } else { |
| watchdog--; |
| } // |
| // Find actions in transition table |
| // |
| |
| |
| var machine = mhchemParser.stateMachines[stateMachine]; |
| var t = machine.transitions[state] || machine.transitions['*']; |
| |
| iterateTransitions: for (var i = 0; i < t.length; i++) { |
| var matches = mhchemParser.patterns.match_(t[i].pattern, input); |
| |
| if (matches) { |
| // |
| // Execute actions |
| // |
| var task = t[i].task; |
| |
| for (var iA = 0; iA < task.action_.length; iA++) { |
| var o; // |
| // Find and execute action |
| // |
| |
| if (machine.actions[task.action_[iA].type_]) { |
| o = machine.actions[task.action_[iA].type_](buffer, matches.match_, task.action_[iA].option); |
| } else if (mhchemParser.actions[task.action_[iA].type_]) { |
| o = mhchemParser.actions[task.action_[iA].type_](buffer, matches.match_, task.action_[iA].option); |
| } else { |
| throw ["MhchemBugA", "mhchem bug A. Please report. (" + task.action_[iA].type_ + ")"]; // Trying to use non-existing action |
| } // |
| // Add output |
| // |
| |
| |
| mhchemParser.concatArray(output, o); |
| } // |
| // Set next state, |
| // Shorten input, |
| // Continue with next character |
| // (= apply only one transition per position) |
| // |
| |
| |
| state = task.nextState || state; |
| |
| if (input.length > 0) { |
| if (!task.revisit) { |
| input = matches.remainder; |
| } |
| |
| if (!task.toContinue) { |
| break iterateTransitions; |
| } |
| } else { |
| return output; |
| } |
| } |
| } // |
| // Prevent infinite loop |
| // |
| |
| |
| if (watchdog <= 0) { |
| throw ["MhchemBugU", "mhchem bug U. Please report."]; // Unexpected character |
| } |
| } |
| }, |
| concatArray: function concatArray(a, b) { |
| if (b) { |
| if (Array.isArray(b)) { |
| for (var iB = 0; iB < b.length; iB++) { |
| a.push(b[iB]); |
| } |
| } else { |
| a.push(b); |
| } |
| } |
| }, |
| patterns: { |
| // |
| // Matching patterns |
| // either regexps or function that return null or {match_:"a", remainder:"bc"} |
| // |
| patterns: { |
| // property names must not look like integers ("2") for correct property traversal order, later on |
| 'empty': /^$/, |
| 'else': /^./, |
| 'else2': /^./, |
| 'space': /^\s/, |
| 'space A': /^\s(?=[A-Z\\$])/, |
| 'space$': /^\s$/, |
| 'a-z': /^[a-z]/, |
| 'x': /^x/, |
| 'x$': /^x$/, |
| 'i$': /^i$/, |
| '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]))))+/, |
| '\\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]))/, |
| 'one lowercase latin letter $': /^(?:([a-z])(?:$|[^a-zA-Z]))$/, |
| '$one lowercase latin letter$ $': /^\$(?:([a-z])(?:$|[^a-zA-Z]))\$$/, |
| '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]))$/, |
| 'digits': /^[0-9]+/, |
| '-9.,9': /^[+\-]?(?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))/, |
| '-9.,9 no missing 0': /^[+\-]?[0-9]+(?:[.,][0-9]+)?/, |
| '(-)(9.,9)(e)(99)': function e99(input) { |
| 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]+\}))?/); |
| |
| if (m && m[0]) { |
| return { |
| match_: m.splice(1), |
| remainder: input.substr(m[0].length) |
| }; |
| } |
| |
| return null; |
| }, |
| '(-)(9)^(-9)': function _(input) { |
| var m = input.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+)?)\^([+\-]?[0-9]+|\{[+\-]?[0-9]+\})/); |
| |
| if (m && m[0]) { |
| return { |
| match_: m.splice(1), |
| remainder: input.substr(m[0].length) |
| }; |
| } |
| |
| return null; |
| }, |
| 'state of aggregation $': function stateOfAggregation$(input) { |
| // ... or crystal system |
| var a = mhchemParser.patterns.findObserveGroups(input, "", /^\([a-z]{1,3}(?=[\),])/, ")", ""); // (aq), (aq,$\infty$), (aq, sat) |
| |
| if (a && a.remainder.match(/^($|[\s,;\)\]\}])/)) { |
| return a; |
| } // AND end of 'phrase' |
| |
| |
| var m = input.match(/^(?:\((?:\\ca\s?)?\$[amothc]\$\))/); // OR crystal system ($o$) (\ca$c$) |
| |
| if (m) { |
| return { |
| match_: m[0], |
| remainder: input.substr(m[0].length) |
| }; |
| } |
| |
| return null; |
| }, |
| '_{(state of aggregation)}$': /^_\{(\([a-z]{1,3}\))\}/, |
| '{[(': /^(?:\\\{|\[|\()/, |
| ')]}': /^(?:\)|\]|\\\})/, |
| ', ': /^[,;]\s*/, |
| ',': /^[,;]/, |
| '.': /^[.]/, |
| '. ': /^([.\u22C5\u00B7\u2022])\s*/, |
| '...': /^\.\.\.(?=$|[^.])/, |
| '* ': /^([*])\s*/, |
| '^{(...)}': function _(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "^{", "", "", "}"); |
| }, |
| '^($...$)': function $$(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "^", "$", "$", ""); |
| }, |
| '^a': /^\^([0-9]+|[^\\_])/, |
| '^\\x{}{}': function x(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "^", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); |
| }, |
| '^\\x{}': function x(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "^", /^\\[a-zA-Z]+\{/, "}", ""); |
| }, |
| '^\\x': /^\^(\\[a-zA-Z]+)\s*/, |
| '^(-1)': /^\^(-?\d+)/, |
| '\'': /^'/, |
| '_{(...)}': function _(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "_{", "", "", "}"); |
| }, |
| '_($...$)': function _$$(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "_", "$", "$", ""); |
| }, |
| '_9': /^_([+\-]?[0-9]+|[^\\])/, |
| '_\\x{}{}': function _X(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "_", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); |
| }, |
| '_\\x{}': function _X(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "_", /^\\[a-zA-Z]+\{/, "}", ""); |
| }, |
| '_\\x': /^_(\\[a-zA-Z]+)\s*/, |
| '^_': /^(?:\^(?=_)|\_(?=\^)|[\^_]$)/, |
| '{}': /^\{\}/, |
| '{...}': function _(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "", "{", "}", ""); |
| }, |
| '{(...)}': function _(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "{", "", "", "}"); |
| }, |
| '$...$': function $$(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "", "$", "$", ""); |
| }, |
| '${(...)}$': function $$(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "${", "", "", "}$"); |
| }, |
| '$(...)$': function $$(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "$", "", "", "$"); |
| }, |
| '=<>': /^[=<>]/, |
| '#': /^[#\u2261]/, |
| '+': /^\+/, |
| '-$': /^-(?=[\s_},;\]/]|$|\([a-z]+\))/, |
| // -space -, -; -] -/ -$ -state-of-aggregation |
| '-9': /^-(?=[0-9])/, |
| '- orbital overlap': /^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/, |
| '-': /^-/, |
| 'pm-operator': /^(?:\\pm|\$\\pm\$|\+-|\+\/-)/, |
| 'operator': /^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/, |
| 'arrowUpDown': /^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/, |
| '\\bond{(...)}': function bond(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "\\bond{", "", "", "}"); |
| }, |
| '->': /^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/, |
| 'CMT': /^[CMT](?=\[)/, |
| '[(...)]': function _(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "[", "", "", "]"); |
| }, |
| '1st-level escape': /^(&|\\\\|\\hline)\s*/, |
| '\\,': /^(?:\\[,\ ;:])/, |
| // \\x - but output no space before |
| '\\x{}{}': function x(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); |
| }, |
| '\\x{}': function x(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", ""); |
| }, |
| '\\ca': /^\\ca(?:\s+|(?![a-zA-Z]))/, |
| '\\x': /^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/, |
| 'orbital': /^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/, |
| // only those with numbers in front, because the others will be formatted correctly anyway |
| 'others': /^[\/~|]/, |
| '\\frac{(...)}': function frac(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "\\frac{", "", "", "}", "{", "", "", "}"); |
| }, |
| '\\overset{(...)}': function overset(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "\\overset{", "", "", "}", "{", "", "", "}"); |
| }, |
| '\\underset{(...)}': function underset(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "\\underset{", "", "", "}", "{", "", "", "}"); |
| }, |
| '\\underbrace{(...)}': function underbrace(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "\\underbrace{", "", "", "}_", "{", "", "", "}"); |
| }, |
| '\\color{(...)}0': function color0(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}"); |
| }, |
| '\\color{(...)}{(...)}1': function color1(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}", "{", "", "", "}"); |
| }, |
| '\\color(...){(...)}2': function color2(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "\\color", "\\", "", /^(?=\{)/, "{", "", "", "}"); |
| }, |
| '\\ce{(...)}': function ce(input) { |
| return mhchemParser.patterns.findObserveGroups(input, "\\ce{", "", "", "}"); |
| }, |
| 'oxidation$': /^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, |
| 'd-oxidation$': /^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, |
| // 0 could be oxidation or charge |
| 'roman numeral': /^[IVX]+/, |
| '1/2$': /^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/, |
| 'amount': function amount(input) { |
| var match; // e.g. 2, 0.5, 1/2, -2, n/2, +; $a$ could be added later in parsing |
| |
| match = input.match(/^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/); |
| |
| if (match) { |
| return { |
| match_: match[0], |
| remainder: input.substr(match[0].length) |
| }; |
| } |
| |
| var a = mhchemParser.patterns.findObserveGroups(input, "", "$", "$", ""); |
| |
| if (a) { |
| // e.g. $2n-1$, $-$ |
| match = a.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/); |
| |
| if (match) { |
| return { |
| match_: match[0], |
| remainder: input.substr(match[0].length) |
| }; |
| } |
| } |
| |
| return null; |
| }, |
| 'amount2': function amount2(input) { |
| return this['amount'](input); |
| }, |
| '(KV letters),': /^(?:[A-Z][a-z]{0,2}|i)(?=,)/, |
| 'formula$': function formula$(input) { |
| if (input.match(/^\([a-z]+\)$/)) { |
| return null; |
| } // state of aggregation = no formula |
| |
| |
| var match = input.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/); |
| |
| if (match) { |
| return { |
| match_: match[0], |
| remainder: input.substr(match[0].length) |
| }; |
| } |
| |
| return null; |
| }, |
| 'uprightEntities': /^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/, |
| '/': /^\s*(\/)\s*/, |
| '//': /^\s*(\/\/)\s*/, |
| '*': /^\s*[*.]\s*/ |
| }, |
| findObserveGroups: function findObserveGroups(input, begExcl, begIncl, endIncl, endExcl, beg2Excl, beg2Incl, end2Incl, end2Excl, combine) { |
| /** @type {{(input: string, pattern: string | RegExp): string | string[] | null;}} */ |
| var _match = function _match(input, pattern) { |
| if (typeof pattern === "string") { |
| if (input.indexOf(pattern) !== 0) { |
| return null; |
| } |
| |
| return pattern; |
| } else { |
| var match = input.match(pattern); |
| |
| if (!match) { |
| return null; |
| } |
| |
| return match[0]; |
| } |
| }; |
| /** @type {{(input: string, i: number, endChars: string | RegExp): {endMatchBegin: number, endMatchEnd: number} | null;}} */ |
| |
| |
| var _findObserveGroups = function _findObserveGroups(input, i, endChars) { |
| var braces = 0; |
| |
| while (i < input.length) { |
| var a = input.charAt(i); |
| |
| var match = _match(input.substr(i), endChars); |
| |
| if (match !== null && braces === 0) { |
| return { |
| endMatchBegin: i, |
| endMatchEnd: i + match.length |
| }; |
| } else if (a === "{") { |
| braces++; |
| } else if (a === "}") { |
| if (braces === 0) { |
| throw ["ExtraCloseMissingOpen", "Extra close brace or missing open brace"]; |
| } else { |
| braces--; |
| } |
| } |
| |
| i++; |
| } |
| |
| if (braces > 0) { |
| return null; |
| } |
| |
| return null; |
| }; |
| |
| var match = _match(input, begExcl); |
| |
| if (match === null) { |
| return null; |
| } |
| |
| input = input.substr(match.length); |
| match = _match(input, begIncl); |
| |
| if (match === null) { |
| return null; |
| } |
| |
| var e = _findObserveGroups(input, match.length, endIncl || endExcl); |
| |
| if (e === null) { |
| return null; |
| } |
| |
| var match1 = input.substring(0, endIncl ? e.endMatchEnd : e.endMatchBegin); |
| |
| if (!(beg2Excl || beg2Incl)) { |
| return { |
| match_: match1, |
| remainder: input.substr(e.endMatchEnd) |
| }; |
| } else { |
| var group2 = this.findObserveGroups(input.substr(e.endMatchEnd), beg2Excl, beg2Incl, end2Incl, end2Excl); |
| |
| if (group2 === null) { |
| return null; |
| } |
| /** @type {string[]} */ |
| |
| |
| var matchRet = [match1, group2.match_]; |
| return { |
| match_: combine ? matchRet.join("") : matchRet, |
| remainder: group2.remainder |
| }; |
| } |
| }, |
| // |
| // Matching function |
| // e.g. match("a", input) will look for the regexp called "a" and see if it matches |
| // returns null or {match_:"a", remainder:"bc"} |
| // |
| match_: function match_(m, input) { |
| var pattern = mhchemParser.patterns.patterns[m]; |
| |
| if (pattern === undefined) { |
| throw ["MhchemBugP", "mhchem bug P. Please report. (" + m + ")"]; // Trying to use non-existing pattern |
| } else if (typeof pattern === "function") { |
| return mhchemParser.patterns.patterns[m](input); // cannot use cached var pattern here, because some pattern functions need this===mhchemParser |
| } else { |
| // RegExp |
| var match = input.match(pattern); |
| |
| if (match) { |
| var mm; |
| |
| if (match[2]) { |
| mm = [match[1], match[2]]; |
| } else if (match[1]) { |
| mm = match[1]; |
| } else { |
| mm = match[0]; |
| } |
| |
| return { |
| match_: mm, |
| remainder: input.substr(match[0].length) |
| }; |
| } |
| |
| return null; |
| } |
| } |
| }, |
| // |
| // Generic state machine actions |
| // |
| actions: { |
| 'a=': function a(buffer, m) { |
| buffer.a = (buffer.a || "") + m; |
| }, |
| 'b=': function b(buffer, m) { |
| buffer.b = (buffer.b || "") + m; |
| }, |
| 'p=': function p(buffer, m) { |
| buffer.p = (buffer.p || "") + m; |
| }, |
| 'o=': function o(buffer, m) { |
| buffer.o = (buffer.o || "") + m; |
| }, |
| 'q=': function q(buffer, m) { |
| buffer.q = (buffer.q || "") + m; |
| }, |
| 'd=': function d(buffer, m) { |
| buffer.d = (buffer.d || "") + m; |
| }, |
| 'rm=': function rm(buffer, m) { |
| buffer.rm = (buffer.rm || "") + m; |
| }, |
| 'text=': function text(buffer, m) { |
| buffer.text_ = (buffer.text_ || "") + m; |
| }, |
| 'insert': function insert(buffer, m, a) { |
| return { |
| type_: a |
| }; |
| }, |
| 'insert+p1': function insertP1(buffer, m, a) { |
| return { |
| type_: a, |
| p1: m |
| }; |
| }, |
| 'insert+p1+p2': function insertP1P2(buffer, m, a) { |
| return { |
| type_: a, |
| p1: m[0], |
| p2: m[1] |
| }; |
| }, |
| 'copy': function copy(buffer, m) { |
| return m; |
| }, |
| 'rm': function rm(buffer, m) { |
| return { |
| type_: 'rm', |
| p1: m || "" |
| }; |
| }, |
| 'text': function text(buffer, m) { |
| return mhchemParser.go(m, 'text'); |
| }, |
| '{text}': function text(buffer, m) { |
| var ret = ["{"]; |
| mhchemParser.concatArray(ret, mhchemParser.go(m, 'text')); |
| ret.push("}"); |
| return ret; |
| }, |
| 'tex-math': function texMath(buffer, m) { |
| return mhchemParser.go(m, 'tex-math'); |
| }, |
| 'tex-math tight': function texMathTight(buffer, m) { |
| return mhchemParser.go(m, 'tex-math tight'); |
| }, |
| 'bond': function bond(buffer, m, k) { |
| return { |
| type_: 'bond', |
| kind_: k || m |
| }; |
| }, |
| 'color0-output': function color0Output(buffer, m) { |
| return { |
| type_: 'color0', |
| color: m[0] |
| }; |
| }, |
| 'ce': function ce(buffer, m) { |
| return mhchemParser.go(m); |
| }, |
| '1/2': function _(buffer, m) { |
| /** @type {ParserOutput[]} */ |
| var ret = []; |
| |
| if (m.match(/^[+\-]/)) { |
| ret.push(m.substr(0, 1)); |
| m = m.substr(1); |
| } |
| |
| var n = m.match(/^([0-9]+|\$[a-z]\$|[a-z])\/([0-9]+)(\$[a-z]\$|[a-z])?$/); |
| n[1] = n[1].replace(/\$/g, ""); |
| ret.push({ |
| type_: 'frac', |
| p1: n[1], |
| p2: n[2] |
| }); |
| |
| if (n[3]) { |
| n[3] = n[3].replace(/\$/g, ""); |
| ret.push({ |
| type_: 'tex-math', |
| p1: n[3] |
| }); |
| } |
| |
| return ret; |
| }, |
| '9,9': function _(buffer, m) { |
| return mhchemParser.go(m, '9,9'); |
| } |
| }, |
| // |
| // createTransitions |
| // convert { 'letter': { 'state': { action_: 'output' } } } to { 'state' => [ { pattern: 'letter', task: { action_: [{type_: 'output'}] } } ] } |
| // with expansion of 'a|b' to 'a' and 'b' (at 2 places) |
| // |
| createTransitions: function createTransitions(o) { |
| var pattern, state; |
| /** @type {string[]} */ |
| |
| var stateArray; |
| var i; // |
| // 1. Collect all states |
| // |
| |
| /** @type {Transitions} */ |
| |
| var transitions = {}; |
| |
| for (pattern in o) { |
| for (state in o[pattern]) { |
| stateArray = state.split("|"); |
| o[pattern][state].stateArray = stateArray; |
| |
| for (i = 0; i < stateArray.length; i++) { |
| transitions[stateArray[i]] = []; |
| } |
| } |
| } // |
| // 2. Fill states |
| // |
| |
| |
| for (pattern in o) { |
| for (state in o[pattern]) { |
| stateArray = o[pattern][state].stateArray || []; |
| |
| for (i = 0; i < stateArray.length; i++) { |
| // |
| // 2a. Normalize actions into array: 'text=' ==> [{type_:'text='}] |
| // (Note to myself: Resolving the function here would be problematic. It would need .bind (for *this*) and currying (for *option*).) |
| // |
| |
| /** @type {any} */ |
| var p = o[pattern][state]; |
| |
| if (p.action_) { |
| p.action_ = [].concat(p.action_); |
| |
| for (var k = 0; k < p.action_.length; k++) { |
| if (typeof p.action_[k] === "string") { |
| p.action_[k] = { |
| type_: p.action_[k] |
| }; |
| } |
| } |
| } else { |
| p.action_ = []; |
| } // |
| // 2.b Multi-insert |
| // |
| |
| |
| var patternArray = pattern.split("|"); |
| |
| for (var j = 0; j < patternArray.length; j++) { |
| if (stateArray[i] === '*') { |
| // insert into all |
| for (var t in transitions) { |
| transitions[t].push({ |
| pattern: patternArray[j], |
| task: p |
| }); |
| } |
| } else { |
| transitions[stateArray[i]].push({ |
| pattern: patternArray[j], |
| task: p |
| }); |
| } |
| } |
| } |
| } |
| } |
| |
| return transitions; |
| }, |
| stateMachines: {} |
| }; // |
| // Definition of state machines |
| // |
| |
| mhchemParser.stateMachines = { |
| // |
| // \ce state machines |
| // |
| //#region ce |
| 'ce': { |
| // main parser |
| transitions: mhchemParser.createTransitions({ |
| 'empty': { |
| '*': { |
| action_: 'output' |
| } |
| }, |
| 'else': { |
| '0|1|2': { |
| action_: 'beginsWithBond=false', |
| revisit: true, |
| toContinue: true |
| } |
| }, |
| 'oxidation$': { |
| '0': { |
| action_: 'oxidation-output' |
| } |
| }, |
| 'CMT': { |
| 'r': { |
| action_: 'rdt=', |
| nextState: 'rt' |
| }, |
| 'rd': { |
| action_: 'rqt=', |
| nextState: 'rdt' |
| } |
| }, |
| 'arrowUpDown': { |
| '0|1|2|as': { |
| action_: ['sb=false', 'output', 'operator'], |
| nextState: '1' |
| } |
| }, |
| 'uprightEntities': { |
| '0|1|2': { |
| action_: ['o=', 'output'], |
| nextState: '1' |
| } |
| }, |
| 'orbital': { |
| '0|1|2|3': { |
| action_: 'o=', |
| nextState: 'o' |
| } |
| }, |
| '->': { |
| '0|1|2|3': { |
| action_: 'r=', |
| nextState: 'r' |
| }, |
| 'a|as': { |
| action_: ['output', 'r='], |
| nextState: 'r' |
| }, |
| '*': { |
| action_: ['output', 'r='], |
| nextState: 'r' |
| } |
| }, |
| '+': { |
| 'o': { |
| action_: 'd= kv', |
| nextState: 'd' |
| }, |
| 'd|D': { |
| action_: 'd=', |
| nextState: 'd' |
| }, |
| 'q': { |
| action_: 'd=', |
| nextState: 'qd' |
| }, |
| 'qd|qD': { |
| action_: 'd=', |
| nextState: 'qd' |
| }, |
| 'dq': { |
| action_: ['output', 'd='], |
| nextState: 'd' |
| }, |
| '3': { |
| action_: ['sb=false', 'output', 'operator'], |
| nextState: '0' |
| } |
| }, |
| 'amount': { |
| '0|2': { |
| action_: 'a=', |
| nextState: 'a' |
| } |
| }, |
| 'pm-operator': { |
| '0|1|2|a|as': { |
| action_: ['sb=false', 'output', { |
| type_: 'operator', |
| option: '\\pm' |
| }], |
| nextState: '0' |
| } |
| }, |
| 'operator': { |
| '0|1|2|a|as': { |
| action_: ['sb=false', 'output', 'operator'], |
| nextState: '0' |
| } |
| }, |
| '-$': { |
| 'o|q': { |
| action_: ['charge or bond', 'output'], |
| nextState: 'qd' |
| }, |
| 'd': { |
| action_: 'd=', |
| nextState: 'd' |
| }, |
| 'D': { |
| action_: ['output', { |
| type_: 'bond', |
| option: "-" |
| }], |
| nextState: '3' |
| }, |
| 'q': { |
| action_: 'd=', |
| nextState: 'qd' |
| }, |
| 'qd': { |
| action_: 'd=', |
| nextState: 'qd' |
| }, |
| 'qD|dq': { |
| action_: ['output', { |
| type_: 'bond', |
| option: "-" |
| }], |
| nextState: '3' |
| } |
| }, |
| '-9': { |
| '3|o': { |
| action_: ['output', { |
| type_: 'insert', |
| option: 'hyphen' |
| }], |
| nextState: '3' |
| } |
| }, |
| '- orbital overlap': { |
| 'o': { |
| action_: ['output', { |
| type_: 'insert', |
| option: 'hyphen' |
| }], |
| nextState: '2' |
| }, |
| 'd': { |
| action_: ['output', { |
| type_: 'insert', |
| option: 'hyphen' |
| }], |
| nextState: '2' |
| } |
| }, |
| '-': { |
| '0|1|2': { |
| action_: [{ |
| type_: 'output', |
| option: 1 |
| }, 'beginsWithBond=true', { |
| type_: 'bond', |
| option: "-" |
| }], |
| nextState: '3' |
| }, |
| '3': { |
| action_: { |
| type_: 'bond', |
| option: "-" |
| } |
| }, |
| 'a': { |
| action_: ['output', { |
| type_: 'insert', |
| option: 'hyphen' |
| }], |
| nextState: '2' |
| }, |
| 'as': { |
| action_: [{ |
| type_: 'output', |
| option: 2 |
| }, { |
| type_: 'bond', |
| option: "-" |
| }], |
| nextState: '3' |
| }, |
| 'b': { |
| action_: 'b=' |
| }, |
| 'o': { |
| action_: { |
| type_: '- after o/d', |
| option: false |
| }, |
| nextState: '2' |
| }, |
| 'q': { |
| action_: { |
| type_: '- after o/d', |
| option: false |
| }, |
| nextState: '2' |
| }, |
| 'd|qd|dq': { |
| action_: { |
| type_: '- after o/d', |
| option: true |
| }, |
| nextState: '2' |
| }, |
| 'D|qD|p': { |
| action_: ['output', { |
| type_: 'bond', |
| option: "-" |
| }], |
| nextState: '3' |
| } |
| }, |
| 'amount2': { |
| '1|3': { |
| action_: 'a=', |
| nextState: 'a' |
| } |
| }, |
| 'letters': { |
| '0|1|2|3|a|as|b|p|bp|o': { |
| action_: 'o=', |
| nextState: 'o' |
| }, |
| 'q|dq': { |
| action_: ['output', 'o='], |
| nextState: 'o' |
| }, |
| 'd|D|qd|qD': { |
| action_: 'o after d', |
| nextState: 'o' |
| } |
| }, |
| 'digits': { |
| 'o': { |
| action_: 'q=', |
| nextState: 'q' |
| }, |
| 'd|D': { |
| action_: 'q=', |
| nextState: 'dq' |
| }, |
| 'q': { |
| action_: ['output', 'o='], |
| nextState: 'o' |
| }, |
| 'a': { |
| action_: 'o=', |
| nextState: 'o' |
| } |
| }, |
| 'space A': { |
| 'b|p|bp': {} |
| }, |
| 'space': { |
| 'a': { |
| nextState: 'as' |
| }, |
| '0': { |
| action_: 'sb=false' |
| }, |
| '1|2': { |
| action_: 'sb=true' |
| }, |
| 'r|rt|rd|rdt|rdq': { |
| action_: 'output', |
| nextState: '0' |
| }, |
| '*': { |
| action_: ['output', 'sb=true'], |
| nextState: '1' |
| } |
| }, |
| '1st-level escape': { |
| '1|2': { |
| action_: ['output', { |
| type_: 'insert+p1', |
| option: '1st-level escape' |
| }] |
| }, |
| '*': { |
| action_: ['output', { |
| type_: 'insert+p1', |
| option: '1st-level escape' |
| }], |
| nextState: '0' |
| } |
| }, |
| '[(...)]': { |
| 'r|rt': { |
| action_: 'rd=', |
| nextState: 'rd' |
| }, |
| 'rd|rdt': { |
| action_: 'rq=', |
| nextState: 'rdq' |
| } |
| }, |
| '...': { |
| 'o|d|D|dq|qd|qD': { |
| action_: ['output', { |
| type_: 'bond', |
| option: "..." |
| }], |
| nextState: '3' |
| }, |
| '*': { |
| action_: [{ |
| type_: 'output', |
| option: 1 |
| }, { |
| type_: 'insert', |
| option: 'ellipsis' |
| }], |
| nextState: '1' |
| } |
| }, |
| '. |* ': { |
| '*': { |
| action_: ['output', { |
| type_: 'insert', |
| option: 'addition compound' |
| }], |
| nextState: '1' |
| } |
| }, |
| 'state of aggregation $': { |
| '*': { |
| action_: ['output', 'state of aggregation'], |
| nextState: '1' |
| } |
| }, |
| '{[(': { |
| 'a|as|o': { |
| action_: ['o=', 'output', 'parenthesisLevel++'], |
| nextState: '2' |
| }, |
| '0|1|2|3': { |
| action_: ['o=', 'output', 'parenthesisLevel++'], |
| nextState: '2' |
| }, |
| '*': { |
| action_: ['output', 'o=', 'output', 'parenthesisLevel++'], |
| nextState: '2' |
| } |
| }, |
| ')]}': { |
| '0|1|2|3|b|p|bp|o': { |
| action_: ['o=', 'parenthesisLevel--'], |
| nextState: 'o' |
| }, |
| 'a|as|d|D|q|qd|qD|dq': { |
| action_: ['output', 'o=', 'parenthesisLevel--'], |
| nextState: 'o' |
| } |
| }, |
| ', ': { |
| '*': { |
| action_: ['output', 'comma'], |
| nextState: '0' |
| } |
| }, |
| '^_': { |
| // ^ and _ without a sensible argument |
| '*': {} |
| }, |
| '^{(...)}|^($...$)': { |
| '0|1|2|as': { |
| action_: 'b=', |
| nextState: 'b' |
| }, |
| 'p': { |
| action_: 'b=', |
| nextState: 'bp' |
| }, |
| '3|o': { |
| action_: 'd= kv', |
| nextState: 'D' |
| }, |
| 'q': { |
| action_: 'd=', |
| nextState: 'qD' |
| }, |
| 'd|D|qd|qD|dq': { |
| action_: ['output', 'd='], |
| nextState: 'D' |
| } |
| }, |
| '^a|^\\x{}{}|^\\x{}|^\\x|\'': { |
| '0|1|2|as': { |
| action_: 'b=', |
| nextState: 'b' |
| }, |
| 'p': { |
| action_: 'b=', |
| nextState: 'bp' |
| }, |
| '3|o': { |
| action_: 'd= kv', |
| nextState: 'd' |
| }, |
| 'q': { |
| action_: 'd=', |
| nextState: 'qd' |
| }, |
| 'd|qd|D|qD': { |
| action_: 'd=' |
| }, |
| 'dq': { |
| action_: ['output', 'd='], |
| nextState: 'd' |
| } |
| }, |
| '_{(state of aggregation)}$': { |
| 'd|D|q|qd|qD|dq': { |
| action_: ['output', 'q='], |
| nextState: 'q' |
| } |
| }, |
| '_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x': { |
| '0|1|2|as': { |
| action_: 'p=', |
| nextState: 'p' |
| }, |
| 'b': { |
| action_: 'p=', |
| nextState: 'bp' |
| }, |
| '3|o': { |
| action_: 'q=', |
| nextState: 'q' |
| }, |
| 'd|D': { |
| action_: 'q=', |
| nextState: 'dq' |
| }, |
| 'q|qd|qD|dq': { |
| action_: ['output', 'q='], |
| nextState: 'q' |
| } |
| }, |
| '=<>': { |
| '0|1|2|3|a|as|o|q|d|D|qd|qD|dq': { |
| action_: [{ |
| type_: 'output', |
| option: 2 |
| }, 'bond'], |
| nextState: '3' |
| } |
| }, |
| '#': { |
| '0|1|2|3|a|as|o': { |
| action_: [{ |
| type_: 'output', |
| option: 2 |
| }, { |
| type_: 'bond', |
| option: "#" |
| }], |
| nextState: '3' |
| } |
| }, |
| '{}': { |
| '*': { |
| action_: { |
| type_: 'output', |
| option: 1 |
| }, |
| nextState: '1' |
| } |
| }, |
| '{...}': { |
| '0|1|2|3|a|as|b|p|bp': { |
| action_: 'o=', |
| nextState: 'o' |
| }, |
| 'o|d|D|q|qd|qD|dq': { |
| action_: ['output', 'o='], |
| nextState: 'o' |
| } |
| }, |
| '$...$': { |
| 'a': { |
| action_: 'a=' |
| }, |
| // 2$n$ |
| '0|1|2|3|as|b|p|bp|o': { |
| action_: 'o=', |
| nextState: 'o' |
| }, |
| // not 'amount' |
| 'as|o': { |
| action_: 'o=' |
| }, |
| 'q|d|D|qd|qD|dq': { |
| action_: ['output', 'o='], |
| nextState: 'o' |
| } |
| }, |
| '\\bond{(...)}': { |
| '*': { |
| action_: [{ |
| type_: 'output', |
| option: 2 |
| }, 'bond'], |
| nextState: "3" |
| } |
| }, |
| '\\frac{(...)}': { |
| '*': { |
| action_: [{ |
| type_: 'output', |
| option: 1 |
| }, 'frac-output'], |
| nextState: '3' |
| } |
| }, |
| '\\overset{(...)}': { |
| '*': { |
| action_: [{ |
| type_: 'output', |
| option: 2 |
| }, 'overset-output'], |
| nextState: '3' |
| } |
| }, |
| '\\underset{(...)}': { |
| '*': { |
| action_: [{ |
| type_: 'output', |
| option: 2 |
| }, 'underset-output'], |
| nextState: '3' |
| } |
| }, |
| '\\underbrace{(...)}': { |
| '*': { |
| action_: [{ |
| type_: 'output', |
| option: 2 |
| }, 'underbrace-output'], |
| nextState: '3' |
| } |
| }, |
| '\\color{(...)}{(...)}1|\\color(...){(...)}2': { |
| '*': { |
| action_: [{ |
| type_: 'output', |
| option: 2 |
| }, 'color-output'], |
| nextState: '3' |
| } |
| }, |
| '\\color{(...)}0': { |
| '*': { |
| action_: [{ |
| type_: 'output', |
| option: 2 |
| }, 'color0-output'] |
| } |
| }, |
| '\\ce{(...)}': { |
| '*': { |
| action_: [{ |
| type_: 'output', |
| option: 2 |
| }, 'ce'], |
| nextState: '3' |
| } |
| }, |
| '\\,': { |
| '*': { |
| action_: [{ |
| type_: 'output', |
| option: 1 |
| }, 'copy'], |
| nextState: '1' |
| } |
| }, |
| '\\x{}{}|\\x{}|\\x': { |
| '0|1|2|3|a|as|b|p|bp|o|c0': { |
| action_: ['o=', 'output'], |
| nextState: '3' |
| }, |
| '*': { |
| action_: ['output', 'o=', 'output'], |
| nextState: '3' |
| } |
| }, |
| 'others': { |
| '*': { |
| action_: [{ |
| type_: 'output', |
| option: 1 |
| }, 'copy'], |
| nextState: '3' |
| } |
| }, |
| 'else2': { |
| 'a': { |
| action_: 'a to o', |
| nextState: 'o', |
| revisit: true |
| }, |
| 'as': { |
| action_: ['output', 'sb=true'], |
| nextState: '1', |
| revisit: true |
| }, |
| 'r|rt|rd|rdt|rdq': { |
| action_: ['output'], |
| nextState: '0', |
| revisit: true |
| }, |
| '*': { |
| action_: ['output', 'copy'], |
| nextState: '3' |
| } |
| } |
| }), |
| actions: { |
| 'o after d': function oAfterD(buffer, m) { |
| var ret; |
| |
| if ((buffer.d || "").match(/^[0-9]+$/)) { |
| var tmp = buffer.d; |
| buffer.d = undefined; |
| ret = this['output'](buffer); |
| buffer.b = tmp; |
| } else { |
| ret = this['output'](buffer); |
| } |
| |
| mhchemParser.actions['o='](buffer, m); |
| return ret; |
| }, |
| 'd= kv': function dKv(buffer, m) { |
| buffer.d = m; |
| buffer.dType = 'kv'; |
| }, |
| 'charge or bond': function chargeOrBond(buffer, m) { |
| if (buffer['beginsWithBond']) { |
| /** @type {ParserOutput[]} */ |
| var ret = []; |
| mhchemParser.concatArray(ret, this['output'](buffer)); |
| mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-")); |
| return ret; |
| } else { |
| buffer.d = m; |
| } |
| }, |
| '- after o/d': function afterOD(buffer, m, isAfterD) { |
| var c1 = mhchemParser.patterns.match_('orbital', buffer.o || ""); |
| var c2 = mhchemParser.patterns.match_('one lowercase greek letter $', buffer.o || ""); |
| var c3 = mhchemParser.patterns.match_('one lowercase latin letter $', buffer.o || ""); |
| var c4 = mhchemParser.patterns.match_('$one lowercase latin letter$ $', buffer.o || ""); |
| var hyphenFollows = m === "-" && (c1 && c1.remainder === "" || c2 || c3 || c4); |
| |
| if (hyphenFollows && !buffer.a && !buffer.b && !buffer.p && !buffer.d && !buffer.q && !c1 && c3) { |
| buffer.o = '$' + buffer.o + '$'; |
| } |
| /** @type {ParserOutput[]} */ |
| |
| |
| var ret = []; |
| |
| if (hyphenFollows) { |
| mhchemParser.concatArray(ret, this['output'](buffer)); |
| ret.push({ |
| type_: 'hyphen' |
| }); |
| } else { |
| c1 = mhchemParser.patterns.match_('digits', buffer.d || ""); |
| |
| if (isAfterD && c1 && c1.remainder === '') { |
| mhchemParser.concatArray(ret, mhchemParser.actions['d='](buffer, m)); |
| mhchemParser.concatArray(ret, this['output'](buffer)); |
| } else { |
| mhchemParser.concatArray(ret, this['output'](buffer)); |
| mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-")); |
| } |
| } |
| |
| return ret; |
| }, |
| 'a to o': function aToO(buffer) { |
| buffer.o = buffer.a; |
| buffer.a = undefined; |
| }, |
| 'sb=true': function sbTrue(buffer) { |
| buffer.sb = true; |
| }, |
| 'sb=false': function sbFalse(buffer) { |
| buffer.sb = false; |
| }, |
| 'beginsWithBond=true': function beginsWithBondTrue(buffer) { |
| buffer['beginsWithBond'] = true; |
| }, |
| 'beginsWithBond=false': function beginsWithBondFalse(buffer) { |
| buffer['beginsWithBond'] = false; |
| }, |
| 'parenthesisLevel++': function parenthesisLevel(buffer) { |
| buffer['parenthesisLevel']++; |
| }, |
| 'parenthesisLevel--': function parenthesisLevel(buffer) { |
| buffer['parenthesisLevel']--; |
| }, |
| 'state of aggregation': function stateOfAggregation(buffer, m) { |
| return { |
| type_: 'state of aggregation', |
| p1: mhchemParser.go(m, 'o') |
| }; |
| }, |
| 'comma': function comma(buffer, m) { |
| var a = m.replace(/\s*$/, ''); |
| var withSpace = a !== m; |
| |
| if (withSpace && buffer['parenthesisLevel'] === 0) { |
| return { |
| type_: 'comma enumeration L', |
| p1: a |
| }; |
| } else { |
| return { |
| type_: 'comma enumeration M', |
| p1: a |
| }; |
| } |
| }, |
| 'output': function output(buffer, m, entityFollows) { |
| // entityFollows: |
| // undefined = if we have nothing else to output, also ignore the just read space (buffer.sb) |
| // 1 = an entity follows, never omit the space if there was one just read before (can only apply to state 1) |
| // 2 = 1 + the entity can have an amount, so output a\, instead of converting it to o (can only apply to states a|as) |
| |
| /** @type {ParserOutput | ParserOutput[]} */ |
| var ret; |
| |
| if (!buffer.r) { |
| ret = []; |
| |
| if (!buffer.a && !buffer.b && !buffer.p && !buffer.o && !buffer.q && !buffer.d && !entityFollows) ; else { |
| if (buffer.sb) { |
| ret.push({ |
| type_: 'entitySkip' |
| }); |
| } |
| |
| if (!buffer.o && !buffer.q && !buffer.d && !buffer.b && !buffer.p && entityFollows !== 2) { |
| buffer.o = buffer.a; |
| buffer.a = undefined; |
| } else if (!buffer.o && !buffer.q && !buffer.d && (buffer.b || buffer.p)) { |
| buffer.o = buffer.a; |
| buffer.d = buffer.b; |
| buffer.q = buffer.p; |
| buffer.a = buffer.b = buffer.p = undefined; |
| } else { |
| if (buffer.o && buffer.dType === 'kv' && mhchemParser.patterns.match_('d-oxidation$', buffer.d || "")) { |
| buffer.dType = 'oxidation'; |
| } else if (buffer.o && buffer.dType === 'kv' && !buffer.q) { |
| buffer.dType = undefined; |
| } |
| } |
| |
| ret.push({ |
| type_: 'chemfive', |
| a: mhchemParser.go(buffer.a, 'a'), |
| b: mhchemParser.go(buffer.b, 'bd'), |
| p: mhchemParser.go(buffer.p, 'pq'), |
| o: mhchemParser.go(buffer.o, 'o'), |
| q: mhchemParser.go(buffer.q, 'pq'), |
| d: mhchemParser.go(buffer.d, buffer.dType === 'oxidation' ? 'oxidation' : 'bd'), |
| dType: buffer.dType |
| }); |
| } |
| } else { |
| // r |
| |
| /** @type {ParserOutput[]} */ |
| var rd; |
| |
| if (buffer.rdt === 'M') { |
| rd = mhchemParser.go(buffer.rd, 'tex-math'); |
| } else if (buffer.rdt === 'T') { |
| rd = [{ |
| type_: 'text', |
| p1: buffer.rd || "" |
| }]; |
| } else { |
| rd = mhchemParser.go(buffer.rd); |
| } |
| /** @type {ParserOutput[]} */ |
| |
| |
| var rq; |
| |
| if (buffer.rqt === 'M') { |
| rq = mhchemParser.go(buffer.rq, 'tex-math'); |
| } else if (buffer.rqt === 'T') { |
| rq = [{ |
| type_: 'text', |
| p1: buffer.rq || "" |
| }]; |
| } else { |
| rq = mhchemParser.go(buffer.rq); |
| } |
| |
| ret = { |
| type_: 'arrow', |
| r: buffer.r, |
| rd: rd, |
| rq: rq |
| }; |
| } |
| |
| for (var p in buffer) { |
| if (p !== 'parenthesisLevel' && p !== 'beginsWithBond') { |
| delete buffer[p]; |
| } |
| } |
| |
| return ret; |
| }, |
| 'oxidation-output': function oxidationOutput(buffer, m) { |
| var ret = ["{"]; |
| mhchemParser.concatArray(ret, mhchemParser.go(m, 'oxidation')); |
| ret.push("}"); |
| return ret; |
| }, |
| 'frac-output': function fracOutput(buffer, m) { |
| return { |
| type_: 'frac-ce', |
| p1: mhchemParser.go(m[0]), |
| p2: mhchemParser.go(m[1]) |
| }; |
| }, |
| 'overset-output': function oversetOutput(buffer, m) { |
| return { |
| type_: 'overset', |
| p1: mhchemParser.go(m[0]), |
| p2: mhchemParser.go(m[1]) |
| }; |
| }, |
| 'underset-output': function undersetOutput(buffer, m) { |
| return { |
| type_: 'underset', |
| p1: mhchemParser.go(m[0]), |
| p2: mhchemParser.go(m[1]) |
| }; |
| }, |
| 'underbrace-output': function underbraceOutput(buffer, m) { |
| return { |
| type_: 'underbrace', |
| p1: mhchemParser.go(m[0]), |
| p2: mhchemParser.go(m[1]) |
| }; |
| }, |
| 'color-output': function colorOutput(buffer, m) { |
| return { |
| type_: 'color', |
| color1: m[0], |
| color2: mhchemParser.go(m[1]) |
| }; |
| }, |
| 'r=': function r(buffer, m) { |
| buffer.r = m; |
| }, |
| 'rdt=': function rdt(buffer, m) { |
| buffer.rdt = m; |
| }, |
| 'rd=': function rd(buffer, m) { |
| buffer.rd = m; |
| }, |
| 'rqt=': function rqt(buffer, m) { |
| buffer.rqt = m; |
| }, |
| 'rq=': function rq(buffer, m) { |
| buffer.rq = m; |
| }, |
| 'operator': function operator(buffer, m, p1) { |
| return { |
| type_: 'operator', |
| kind_: p1 || m |
| }; |
| } |
| } |
| }, |
| 'a': { |
| transitions: mhchemParser.createTransitions({ |
| 'empty': { |
| '*': {} |
| }, |
| '1/2$': { |
| '0': { |
| action_: '1/2' |
| } |
| }, |
| 'else': { |
| '0': { |
| nextState: '1', |
| revisit: true |
| } |
| }, |
| '$(...)$': { |
| '*': { |
| action_: 'tex-math tight', |
| nextState: '1' |
| } |
| }, |
| ',': { |
| '*': { |
| action_: { |
| type_: 'insert', |
| option: 'commaDecimal' |
| } |
| } |
| }, |
| 'else2': { |
| '*': { |
| action_: 'copy' |
| } |
| } |
| }), |
| actions: {} |
| }, |
| 'o': { |
| transitions: mhchemParser.createTransitions({ |
| 'empty': { |
| '*': {} |
| }, |
| '1/2$': { |
| '0': { |
| action_: '1/2' |
| } |
| }, |
| 'else': { |
| '0': { |
| nextState: '1', |
| revisit: true |
| } |
| }, |
| 'letters': { |
| '*': { |
| action_: 'rm' |
| } |
| }, |
| '\\ca': { |
| '*': { |
| action_: { |
| type_: 'insert', |
| option: 'circa' |
| } |
| } |
| }, |
| '\\x{}{}|\\x{}|\\x': { |
| '*': { |
| action_: 'copy' |
| } |
| }, |
| '${(...)}$|$(...)$': { |
| '*': { |
| action_: 'tex-math' |
| } |
| }, |
| '{(...)}': { |
| '*': { |
| action_: '{text}' |
| } |
| }, |
| 'else2': { |
| '*': { |
| action_: 'copy' |
| } |
| } |
| }), |
| actions: {} |
| }, |
| 'text': { |
| transitions: mhchemParser.createTransitions({ |
| 'empty': { |
| '*': { |
| action_: 'output' |
| } |
| }, |
| '{...}': { |
| '*': { |
| action_: 'text=' |
| } |
| }, |
| '${(...)}$|$(...)$': { |
| '*': { |
| action_: 'tex-math' |
| } |
| }, |
| '\\greek': { |
| '*': { |
| action_: ['output', 'rm'] |
| } |
| }, |
| '\\,|\\x{}{}|\\x{}|\\x': { |
| '*': { |
| action_: ['output', 'copy'] |
| } |
| }, |
| 'else': { |
| '*': { |
| action_: 'text=' |
| } |
| } |
| }), |
| actions: { |
| 'output': function output(buffer) { |
| if (buffer.text_) { |
| /** @type {ParserOutput} */ |
| var ret = { |
| type_: 'text', |
| p1: buffer.text_ |
| }; |
| |
| for (var p in buffer) { |
| delete buffer[p]; |
| } |
| |
| return ret; |
| } |
| } |
| } |
| }, |
| 'pq': { |
| transitions: mhchemParser.createTransitions({ |
| 'empty': { |
| '*': {} |
| }, |
| 'state of aggregation $': { |
| '*': { |
| action_: 'state of aggregation' |
| } |
| }, |
| 'i$': { |
| '0': { |
| nextState: '!f', |
| revisit: true |
| } |
| }, |
| '(KV letters),': { |
| '0': { |
| action_: 'rm', |
| nextState: '0' |
| } |
| }, |
| 'formula$': { |
| '0': { |
| nextState: 'f', |
| revisit: true |
| } |
| }, |
| '1/2$': { |
| '0': { |
| action_: '1/2' |
| } |
| }, |
| 'else': { |
| '0': { |
| nextState: '!f', |
| revisit: true |
| } |
| }, |
| '${(...)}$|$(...)$': { |
| '*': { |
| action_: 'tex-math' |
| } |
| }, |
| '{(...)}': { |
| '*': { |
| action_: 'text' |
| } |
| }, |
| 'a-z': { |
| 'f': { |
| action_: 'tex-math' |
| } |
| }, |
| 'letters': { |
| '*': { |
| action_: 'rm' |
| } |
| }, |
| '-9.,9': { |
| '*': { |
| action_: '9,9' |
| } |
| }, |
| ',': { |
| '*': { |
| action_: { |
| type_: 'insert+p1', |
| option: 'comma enumeration S' |
| } |
| } |
| }, |
| '\\color{(...)}{(...)}1|\\color(...){(...)}2': { |
| '*': { |
| action_: 'color-output' |
| } |
| }, |
| '\\color{(...)}0': { |
| '*': { |
| action_: 'color0-output' |
| } |
| }, |
| '\\ce{(...)}': { |
| '*': { |
| action_: 'ce' |
| } |
| }, |
| '\\,|\\x{}{}|\\x{}|\\x': { |
| '*': { |
| action_: 'copy' |
| } |
| }, |
| 'else2': { |
| '*': { |
| action_: 'copy' |
| } |
| } |
| }), |
| actions: { |
| 'state of aggregation': function stateOfAggregation(buffer, m) { |
| return { |
| type_: 'state of aggregation subscript', |
| p1: mhchemParser.go(m, 'o') |
| }; |
| }, |
| 'color-output': function colorOutput(buffer, m) { |
| return { |
| type_: 'color', |
| color1: m[0], |
| color2: mhchemParser.go(m[1], 'pq') |
| }; |
| } |
| } |
| }, |
| 'bd': { |
| transitions: mhchemParser.createTransitions({ |
| 'empty': { |
| '*': {} |
| }, |
| 'x$': { |
| '0': { |
| nextState: '!f', |
| revisit: true |
| } |
| }, |
| 'formula$': { |
| '0': { |
| nextState: 'f', |
| revisit: true |
| } |
| }, |
| 'else': { |
| '0': { |
| nextState: '!f', |
| revisit: true |
| } |
| }, |
| '-9.,9 no missing 0': { |
| '*': { |
| action_: '9,9' |
| } |
| }, |
| '.': { |
| '*': { |
| action_: { |
| type_: 'insert', |
| option: 'electron dot' |
| } |
| } |
| }, |
| 'a-z': { |
| 'f': { |
| action_: 'tex-math' |
| } |
| }, |
| 'x': { |
| '*': { |
| action_: { |
| type_: 'insert', |
| option: 'KV x' |
| } |
| } |
| }, |
| 'letters': { |
| '*': { |
| action_: 'rm' |
| } |
| }, |
| '\'': { |
| '*': { |
| action_: { |
| type_: 'insert', |
| option: 'prime' |
| } |
| } |
| }, |
| '${(...)}$|$(...)$': { |
| '*': { |
| action_: 'tex-math' |
| } |
| }, |
| '{(...)}': { |
| '*': { |
| action_: 'text' |
| } |
| }, |
| '\\color{(...)}{(...)}1|\\color(...){(...)}2': { |
| '*': { |
| action_: 'color-output' |
| } |
| }, |
| '\\color{(...)}0': { |
| '*': { |
| action_: 'color0-output' |
| } |
| }, |
| '\\ce{(...)}': { |
| '*': { |
| action_: 'ce' |
| } |
| }, |
| '\\,|\\x{}{}|\\x{}|\\x': { |
| '*': { |
| action_: 'copy' |
| } |
| }, |
| 'else2': { |
| '*': { |
| action_: 'copy' |
| } |
| } |
| }), |
| actions: { |
| 'color-output': function colorOutput(buffer, m) { |
| return { |
| type_: 'color', |
| color1: m[0], |
| color2: mhchemParser.go(m[1], 'bd') |
| }; |
| } |
| } |
| }, |
| 'oxidation': { |
| transitions: mhchemParser.createTransitions({ |
| 'empty': { |
| '*': {} |
| }, |
| 'roman numeral': { |
| '*': { |
| action_: 'roman-numeral' |
| } |
| }, |
| '${(...)}$|$(...)$': { |
| '*': { |
| action_: 'tex-math' |
| } |
| }, |
| 'else': { |
| '*': { |
| action_: 'copy' |
| } |
| } |
| }), |
| actions: { |
| 'roman-numeral': function romanNumeral(buffer, m) { |
| return { |
| type_: 'roman numeral', |
| p1: m || "" |
| }; |
| } |
| } |
| }, |
| 'tex-math': { |
| transitions: mhchemParser.createTransitions({ |
| 'empty': { |
| '*': { |
| action_: 'output' |
| } |
| }, |
| '\\ce{(...)}': { |
| '*': { |
| action_: ['output', 'ce'] |
| } |
| }, |
| '{...}|\\,|\\x{}{}|\\x{}|\\x': { |
| '*': { |
| action_: 'o=' |
| } |
| }, |
| 'else': { |
| '*': { |
| action_: 'o=' |
| } |
| } |
| }), |
| actions: { |
| 'output': function output(buffer) { |
| if (buffer.o) { |
| /** @type {ParserOutput} */ |
| var ret = { |
| type_: 'tex-math', |
| p1: buffer.o |
| }; |
| |
| for (var p in buffer) { |
| delete buffer[p]; |
| } |
| |
| return ret; |
| } |
| } |
| } |
| }, |
| 'tex-math tight': { |
| transitions: mhchemParser.createTransitions({ |
| 'empty': { |
| '*': { |
| action_: 'output' |
| } |
| }, |
| '\\ce{(...)}': { |
| '*': { |
| action_: ['output', 'ce'] |
| } |
| }, |
| '{...}|\\,|\\x{}{}|\\x{}|\\x': { |
| '*': { |
| action_: 'o=' |
| } |
| }, |
| '-|+': { |
| '*': { |
| action_: 'tight operator' |
| } |
| }, |
| 'else': { |
| '*': { |
| action_: 'o=' |
| } |
| } |
| }), |
| actions: { |
| 'tight operator': function tightOperator(buffer, m) { |
| buffer.o = (buffer.o || "") + "{" + m + "}"; |
| }, |
| 'output': function output(buffer) { |
| if (buffer.o) { |
| /** @type {ParserOutput} */ |
| var ret = { |
| type_: 'tex-math', |
| p1: buffer.o |
| }; |
| |
| for (var p in buffer) { |
| delete buffer[p]; |
| } |
| |
| return ret; |
| } |
| } |
| } |
| }, |
| '9,9': { |
| transitions: mhchemParser.createTransitions({ |
| 'empty': { |
| '*': {} |
| }, |
| ',': { |
| '*': { |
| action_: 'comma' |
| } |
| }, |
| 'else': { |
| '*': { |
| action_: 'copy' |
| } |
| } |
| }), |
| actions: { |
| 'comma': function comma() { |
| return { |
| type_: 'commaDecimal' |
| }; |
| } |
| } |
| }, |
| //#endregion |
| // |
| // \pu state machines |
| // |
| //#region pu |
| 'pu': { |
| transitions: mhchemParser.createTransitions({ |
| 'empty': { |
| '*': { |
| action_: 'output' |
| } |
| }, |
| 'space$': { |
| '*': { |
| action_: ['output', 'space'] |
| } |
| }, |
| '{[(|)]}': { |
| '0|a': { |
| action_: 'copy' |
| } |
| }, |
| '(-)(9)^(-9)': { |
| '0': { |
| action_: 'number^', |
| nextState: 'a' |
| } |
| }, |
| '(-)(9.,9)(e)(99)': { |
| '0': { |
| action_: 'enumber', |
| nextState: 'a' |
| } |
| }, |
| 'space': { |
| '0|a': {} |
| }, |
| 'pm-operator': { |
| '0|a': { |
| action_: { |
| type_: 'operator', |
| option: '\\pm' |
| }, |
| nextState: '0' |
| } |
| }, |
| 'operator': { |
| '0|a': { |
| action_: 'copy', |
| nextState: '0' |
| } |
| }, |
| '//': { |
| 'd': { |
| action_: 'o=', |
| nextState: '/' |
| } |
| }, |
| '/': { |
| 'd': { |
| action_: 'o=', |
| nextState: '/' |
| } |
| }, |
| '{...}|else': { |
| '0|d': { |
| action_: 'd=', |
| nextState: 'd' |
| }, |
| 'a': { |
| action_: ['space', 'd='], |
| nextState: 'd' |
| }, |
| '/|q': { |
| action_: 'q=', |
| nextState: 'q' |
| } |
| } |
| }), |
| actions: { |
| 'enumber': function enumber(buffer, m) { |
| /** @type {ParserOutput[]} */ |
| var ret = []; |
| |
| if (m[0] === "+-" || m[0] === "+/-") { |
| ret.push("\\pm "); |
| } else if (m[0]) { |
| ret.push(m[0]); |
| } |
| |
| if (m[1]) { |
| mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9')); |
| |
| if (m[2]) { |
| if (m[2].match(/[,.]/)) { |
| mhchemParser.concatArray(ret, mhchemParser.go(m[2], 'pu-9,9')); |
| } else { |
| ret.push(m[2]); |
| } |
| } |
| |
| m[3] = m[4] || m[3]; |
| |
| if (m[3]) { |
| m[3] = m[3].trim(); |
| |
| if (m[3] === "e" || m[3].substr(0, 1) === "*") { |
| ret.push({ |
| type_: 'cdot' |
| }); |
| } else { |
| ret.push({ |
| type_: 'times' |
| }); |
| } |
| } |
| } |
| |
| if (m[3]) { |
| ret.push("10^{" + m[5] + "}"); |
| } |
| |
| return ret; |
| }, |
| 'number^': function number(buffer, m) { |
| /** @type {ParserOutput[]} */ |
| var ret = []; |
| |
| if (m[0] === "+-" || m[0] === "+/-") { |
| ret.push("\\pm "); |
| } else if (m[0]) { |
| ret.push(m[0]); |
| } |
| |
| mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9')); |
| ret.push("^{" + m[2] + "}"); |
| return ret; |
| }, |
| 'operator': function operator(buffer, m, p1) { |
| return { |
| type_: 'operator', |
| kind_: p1 || m |
| }; |
| }, |
| 'space': function space() { |
| return { |
| type_: 'pu-space-1' |
| }; |
| }, |
| 'output': function output(buffer) { |
| /** @type {ParserOutput | ParserOutput[]} */ |
| var ret; |
| var md = mhchemParser.patterns.match_('{(...)}', buffer.d || ""); |
| |
| if (md && md.remainder === '') { |
| buffer.d = md.match_; |
| } |
| |
| var mq = mhchemParser.patterns.match_('{(...)}', buffer.q || ""); |
| |
| if (mq && mq.remainder === '') { |
| buffer.q = mq.match_; |
| } |
| |
| if (buffer.d) { |
| buffer.d = buffer.d.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C"); |
| buffer.d = buffer.d.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F"); |
| } |
| |
| if (buffer.q) { |
| // fraction |
| buffer.q = buffer.q.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C"); |
| buffer.q = buffer.q.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F"); |
| var b5 = { |
| d: mhchemParser.go(buffer.d, 'pu'), |
| q: mhchemParser.go(buffer.q, 'pu') |
| }; |
| |
| if (buffer.o === '//') { |
| ret = { |
| type_: 'pu-frac', |
| p1: b5.d, |
| p2: b5.q |
| }; |
| } else { |
| ret = b5.d; |
| |
| if (b5.d.length > 1 || b5.q.length > 1) { |
| ret.push({ |
| type_: ' / ' |
| }); |
| } else { |
| ret.push({ |
| type_: '/' |
| }); |
| } |
| |
| mhchemParser.concatArray(ret, b5.q); |
| } |
| } else { |
| // no fraction |
| ret = mhchemParser.go(buffer.d, 'pu-2'); |
| } |
| |
| for (var p in buffer) { |
| delete buffer[p]; |
| } |
| |
| return ret; |
| } |
| } |
| }, |
| 'pu-2': { |
| transitions: mhchemParser.createTransitions({ |
| 'empty': { |
| '*': { |
| action_: 'output' |
| } |
| }, |
| '*': { |
| '*': { |
| action_: ['output', 'cdot'], |
| nextState: '0' |
| } |
| }, |
| '\\x': { |
| '*': { |
| action_: 'rm=' |
| } |
| }, |
| 'space': { |
| '*': { |
| action_: ['output', 'space'], |
| nextState: '0' |
| } |
| }, |
| '^{(...)}|^(-1)': { |
| '1': { |
| action_: '^(-1)' |
| } |
| }, |
| '-9.,9': { |
| '0': { |
| action_: 'rm=', |
| nextState: '0' |
| }, |
| '1': { |
| action_: '^(-1)', |
| nextState: '0' |
| } |
| }, |
| '{...}|else': { |
| '*': { |
| action_: 'rm=', |
| nextState: '1' |
| } |
| } |
| }), |
| actions: { |
| 'cdot': function cdot() { |
| return { |
| type_: 'tight cdot' |
| }; |
| }, |
| '^(-1)': function _(buffer, m) { |
| buffer.rm += "^{" + m + "}"; |
| }, |
| 'space': function space() { |
| return { |
| type_: 'pu-space-2' |
| }; |
| }, |
| 'output': function output(buffer) { |
| /** @type {ParserOutput | ParserOutput[]} */ |
| var ret = []; |
| |
| if (buffer.rm) { |
| var mrm = mhchemParser.patterns.match_('{(...)}', buffer.rm || ""); |
| |
| if (mrm && mrm.remainder === '') { |
| ret = mhchemParser.go(mrm.match_, 'pu'); |
| } else { |
| ret = { |
| type_: 'rm', |
| p1: buffer.rm |
| }; |
| } |
| } |
| |
| for (var p in buffer) { |
| delete buffer[p]; |
| } |
| |
| return ret; |
| } |
| } |
| }, |
| 'pu-9,9': { |
| transitions: mhchemParser.createTransitions({ |
| 'empty': { |
| '0': { |
| action_: 'output-0' |
| }, |
| 'o': { |
| action_: 'output-o' |
| } |
| }, |
| ',': { |
| '0': { |
| action_: ['output-0', 'comma'], |
| nextState: 'o' |
| } |
| }, |
| '.': { |
| '0': { |
| action_: ['output-0', 'copy'], |
| nextState: 'o' |
| } |
| }, |
| 'else': { |
| '*': { |
| action_: 'text=' |
| } |
| } |
| }), |
| actions: { |
| 'comma': function comma() { |
| return { |
| type_: 'commaDecimal' |
| }; |
| }, |
| 'output-0': function output0(buffer) { |
| /** @type {ParserOutput[]} */ |
| var ret = []; |
| buffer.text_ = buffer.text_ || ""; |
| |
| if (buffer.text_.length > 4) { |
| var a = buffer.text_.length % 3; |
| |
| if (a === 0) { |
| a = 3; |
| } |
| |
| for (var i = buffer.text_.length - 3; i > 0; i -= 3) { |
| ret.push(buffer.text_.substr(i, 3)); |
| ret.push({ |
| type_: '1000 separator' |
| }); |
| } |
| |
| ret.push(buffer.text_.substr(0, a)); |
| ret.reverse(); |
| } else { |
| ret.push(buffer.text_); |
| } |
| |
| for (var p in buffer) { |
| delete buffer[p]; |
| } |
| |
| return ret; |
| }, |
| 'output-o': function outputO(buffer) { |
| /** @type {ParserOutput[]} */ |
| var ret = []; |
| buffer.text_ = buffer.text_ || ""; |
| |
| if (buffer.text_.length > 4) { |
| var a = buffer.text_.length - 3; |
| |
| for (var i = 0; i < a; i += 3) { |
| ret.push(buffer.text_.substr(i, 3)); |
| ret.push({ |
| type_: '1000 separator' |
| }); |
| } |
| |
| ret.push(buffer.text_.substr(i)); |
| } else { |
| ret.push(buffer.text_); |
| } |
| |
| for (var p in buffer) { |
| delete buffer[p]; |
| } |
| |
| return ret; |
| } |
| } //#endregion |
| |
| } |
| }; // |
| // texify: Take MhchemParser output and convert it to TeX |
| // |
| |
| /** @type {Texify} */ |
| |
| var texify = { |
| go: function go(input, isInner) { |
| // (recursive, max 4 levels) |
| if (!input) { |
| return ""; |
| } |
| |
| var res = ""; |
| var cee = false; |
| |
| for (var i = 0; i < input.length; i++) { |
| var inputi = input[i]; |
| |
| if (typeof inputi === "string") { |
| res += inputi; |
| } else { |
| res += texify._go2(inputi); |
| |
| if (inputi.type_ === '1st-level escape') { |
| cee = true; |
| } |
| } |
| } |
| |
| if (!isInner && !cee && res) { |
| res = "{" + res + "}"; |
| } |
| |
| return res; |
| }, |
| _goInner: function _goInner(input) { |
| if (!input) { |
| return input; |
| } |
| |
| return texify.go(input, true); |
| }, |
| _go2: function _go2(buf) { |
| /** @type {undefined | string} */ |
| var res; |
| |
| switch (buf.type_) { |
| case 'chemfive': |
| res = ""; |
| var b5 = { |
| a: texify._goInner(buf.a), |
| b: texify._goInner(buf.b), |
| p: texify._goInner(buf.p), |
| o: texify._goInner(buf.o), |
| q: texify._goInner(buf.q), |
| d: texify._goInner(buf.d) |
| }; // |
| // a |
| // |
| |
| if (b5.a) { |
| if (b5.a.match(/^[+\-]/)) { |
| b5.a = "{" + b5.a + "}"; |
| } |
| |
| res += b5.a + "\\,"; |
| } // |
| // b and p |
| // |
| |
| |
| if (b5.b || b5.p) { |
| res += "{\\vphantom{X}}"; |
| res += "^{\\hphantom{" + (b5.b || "") + "}}_{\\hphantom{" + (b5.p || "") + "}}"; |
| res += "{\\vphantom{X}}"; |
| res += "^{\\smash[t]{\\vphantom{2}}\\mathllap{" + (b5.b || "") + "}}"; |
| res += "_{\\vphantom{2}\\mathllap{\\smash[t]{" + (b5.p || "") + "}}}"; |
| } // |
| // o |
| // |
| |
| |
| if (b5.o) { |
| if (b5.o.match(/^[+\-]/)) { |
| b5.o = "{" + b5.o + "}"; |
| } |
| |
| res += b5.o; |
| } // |
| // q and d |
| // |
| |
| |
| if (buf.dType === 'kv') { |
| if (b5.d || b5.q) { |
| res += "{\\vphantom{X}}"; |
| } |
| |
| if (b5.d) { |
| res += "^{" + b5.d + "}"; |
| } |
| |
| if (b5.q) { |
| res += "_{\\smash[t]{" + b5.q + "}}"; |
| } |
| } else if (buf.dType === 'oxidation') { |
| if (b5.d) { |
| res += "{\\vphantom{X}}"; |
| res += "^{" + b5.d + "}"; |
| } |
| |
| if (b5.q) { |
| res += "{\\vphantom{X}}"; |
| res += "_{\\smash[t]{" + b5.q + "}}"; |
| } |
| } else { |
| if (b5.q) { |
| res += "{\\vphantom{X}}"; |
| res += "_{\\smash[t]{" + b5.q + "}}"; |
| } |
| |
| if (b5.d) { |
| res += "{\\vphantom{X}}"; |
| res += "^{" + b5.d + "}"; |
| } |
| } |
| |
| break; |
| |
| case 'rm': |
| res = "\\mathrm{" + buf.p1 + "}"; |
| break; |
| |
| case 'text': |
| if (buf.p1.match(/[\^_]/)) { |
| buf.p1 = buf.p1.replace(" ", "~").replace("-", "\\text{-}"); |
| res = "\\mathrm{" + buf.p1 + "}"; |
| } else { |
| res = "\\text{" + buf.p1 + "}"; |
| } |
| |
| break; |
| |
| case 'roman numeral': |
| res = "\\mathrm{" + buf.p1 + "}"; |
| break; |
| |
| case 'state of aggregation': |
| res = "\\mskip2mu " + texify._goInner(buf.p1); |
| break; |
| |
| case 'state of aggregation subscript': |
| res = "\\mskip1mu " + texify._goInner(buf.p1); |
| break; |
| |
| case 'bond': |
| res = texify._getBond(buf.kind_); |
| |
| if (!res) { |
| throw ["MhchemErrorBond", "mhchem Error. Unknown bond type (" + buf.kind_ + ")"]; |
| } |
| |
| break; |
| |
| case 'frac': |
| var c = "\\frac{" + buf.p1 + "}{" + buf.p2 + "}"; |
| res = "\\mathchoice{\\textstyle" + c + "}{" + c + "}{" + c + "}{" + c + "}"; |
| break; |
| |
| case 'pu-frac': |
| var d = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; |
| res = "\\mathchoice{\\textstyle" + d + "}{" + d + "}{" + d + "}{" + d + "}"; |
| break; |
| |
| case 'tex-math': |
| res = buf.p1 + " "; |
| break; |
| |
| case 'frac-ce': |
| res = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; |
| break; |
| |
| case 'overset': |
| res = "\\overset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; |
| break; |
| |
| case 'underset': |
| res = "\\underset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; |
| break; |
| |
| case 'underbrace': |
| res = "\\underbrace{" + texify._goInner(buf.p1) + "}_{" + texify._goInner(buf.p2) + "}"; |
| break; |
| |
| case 'color': |
| res = "{\\color{" + buf.color1 + "}{" + texify._goInner(buf.color2) + "}}"; |
| break; |
| |
| case 'color0': |
| res = "\\color{" + buf.color + "}"; |
| break; |
| |
| case 'arrow': |
| var b6 = { |
| rd: texify._goInner(buf.rd), |
| rq: texify._goInner(buf.rq) |
| }; |
| |
| var arrow = "\\x" + texify._getArrow(buf.r); |
| |
| if (b6.rq) { |
| arrow += "[{" + b6.rq + "}]"; |
| } |
| |
| if (b6.rd) { |
| arrow += "{" + b6.rd + "}"; |
| } else { |
| arrow += "{}"; |
| } |
| |
| res = arrow; |
| break; |
| |
| case 'operator': |
| res = texify._getOperator(buf.kind_); |
| break; |
| |
| case '1st-level escape': |
| res = buf.p1 + " "; // &, \\\\, \\hlin |
| |
| break; |
| |
| case 'space': |
| res = " "; |
| break; |
| |
| case 'entitySkip': |
| res = "~"; |
| break; |
| |
| case 'pu-space-1': |
| res = "~"; |
| break; |
| |
| case 'pu-space-2': |
| res = "\\mkern3mu "; |
| break; |
| |
| case '1000 separator': |
| res = "\\mkern2mu "; |
| break; |
| |
| case 'commaDecimal': |
| res = "{,}"; |
| break; |
| |
| case 'comma enumeration L': |
| res = "{" + buf.p1 + "}\\mkern6mu "; |
| break; |
| |
| case 'comma enumeration M': |
| res = "{" + buf.p1 + "}\\mkern3mu "; |
| break; |
| |
| case 'comma enumeration S': |
| res = "{" + buf.p1 + "}\\mkern1mu "; |
| break; |
| |
| case 'hyphen': |
| res = "\\text{-}"; |
| break; |
| |
| case 'addition compound': |
| res = "\\,{\\cdot}\\,"; |
| break; |
| |
| case 'electron dot': |
| res = "\\mkern1mu \\bullet\\mkern1mu "; |
| break; |
| |
| case 'KV x': |
| res = "{\\times}"; |
| break; |
| |
| case 'prime': |
| res = "\\prime "; |
| break; |
| |
| case 'cdot': |
| res = "\\cdot "; |
| break; |
| |
| case 'tight cdot': |
| res = "\\mkern1mu{\\cdot}\\mkern1mu "; |
| break; |
| |
| case 'times': |
| res = "\\times "; |
| break; |
| |
| case 'circa': |
| res = "{\\sim}"; |
| break; |
| |
| case '^': |
| res = "uparrow"; |
| break; |
| |
| case 'v': |
| res = "downarrow"; |
| break; |
| |
| case 'ellipsis': |
| res = "\\ldots "; |
| break; |
| |
| case '/': |
| res = "/"; |
| break; |
| |
| case ' / ': |
| res = "\\,/\\,"; |
| break; |
| |
| default: |
| throw ["MhchemBugT", "mhchem bug T. Please report."]; |
| // Missing texify rule or unknown MhchemParser output |
| } |
| return res; |
| }, |
| _getArrow: function _getArrow(a) { |
| switch (a) { |
| case "->": |
| return "rightarrow"; |
| |
| case "\u2192": |
| return "rightarrow"; |
| |
| case "\u27F6": |
| return "rightarrow"; |
| |
| case "<-": |
| return "leftarrow"; |
| |
| case "<->": |
| return "leftrightarrow"; |
| |
| case "<-->": |
| return "rightleftarrows"; |
| |
| case "<=>": |
| return "rightleftharpoons"; |
| |
| case "\u21CC": |
| return "rightleftharpoons"; |
| |
| case "<=>>": |
| return "rightequilibrium"; |
| |
| case "<<=>": |
| return "leftequilibrium"; |
| |
| default: |
| throw ["MhchemBugT", "mhchem bug T. Please report."]; |
| } |
| }, |
| _getBond: function _getBond(a) { |
| switch (a) { |
| case "-": |
| return "{-}"; |
| |
| case "1": |
| return "{-}"; |
| |
| case "=": |
| return "{=}"; |
| |
| case "2": |
| return "{=}"; |
| |
| case "#": |
| return "{\\equiv}"; |
| |
| case "3": |
| return "{\\equiv}"; |
| |
| case "~": |
| return "{\\tripledash}"; |
| |
| case "~-": |
| return "{\\mathrlap{\\raisebox{-.1em}{$-$}}\\raisebox{.1em}{$\\tripledash$}}"; |
| |
| case "~=": |
| return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}"; |
| |
| case "~--": |
| return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}"; |
| |
| case "-~-": |
| return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$-$}}\\tripledash}"; |
| |
| case "...": |
| return "{{\\cdot}{\\cdot}{\\cdot}}"; |
| |
| case "....": |
| return "{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}"; |
| |
| case "->": |
| return "{\\rightarrow}"; |
| |
| case "<-": |
| return "{\\leftarrow}"; |
| |
| case "<": |
| return "{<}"; |
| |
| case ">": |
| return "{>}"; |
| |
| default: |
| throw ["MhchemBugT", "mhchem bug T. Please report."]; |
| } |
| }, |
| _getOperator: function _getOperator(a) { |
| switch (a) { |
| case "+": |
| return " {}+{} "; |
| |
| case "-": |
| return " {}-{} "; |
| |
| case "=": |
| return " {}={} "; |
| |
| case "<": |
| return " {}<{} "; |
| |
| case ">": |
| return " {}>{} "; |
| |
| case "<<": |
| return " {}\\ll{} "; |
| |
| case ">>": |
| return " {}\\gg{} "; |
| |
| case "\\pm": |
| return " {}\\pm{} "; |
| |
| case "\\approx": |
| return " {}\\approx{} "; |
| |
| case "$\\approx$": |
| return " {}\\approx{} "; |
| |
| case "v": |
| return " \\downarrow{} "; |
| |
| case "(v)": |
| return " \\downarrow{} "; |
| |
| case "^": |
| return " \\uparrow{} "; |
| |
| case "(^)": |
| return " \\uparrow{} "; |
| |
| default: |
| throw ["MhchemBugT", "mhchem bug T. Please report."]; |
| } |
| } |
| }; // |