1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693 |
- /* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
- /* vim: set ts=2 et sw=2 tw=80: */
- /*************************************************************
- *
- * 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-2017 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
- MathJax.Extension["TeX/mhchem"] = {
- version: "3.2.0"
- };
- MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
- var TEX = MathJax.InputJax.TeX;
- //
- // This is the main class for handing the \ce and related commands.
- // Its main method is Parse() which takes the argument to \ce and
- // returns the corresponding TeX string.
- //
- var CE = MathJax.Object.Subclass({
- string: "", // the \ce string being parsed
- //
- // Store the string when a CE object is created
- //
- Init: function (string) { this.string = string; },
- //
- // This converts the CE string to a TeX string.
- //
- Parse: function (stateMachine) {
- try {
- return texify.go(mhchemParser.go(this.string, stateMachine));
- } catch (ex) {
- TEX.Error(ex);
- }
- }
- });
- //
- // Core parser for mhchem syntax (recursive)
- //
- var mhchemParser = {};
- //
- // Parses mchem \ce syntax
- //
- // Call like
- // go("H2O");
- //
- // Looks through mhchemParser.transitions, to execute a matching action
- // (recursive)
- //
- mhchemParser.go = function(input, stateMachine) {
- if (!input) { return input; }
- 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
- //
- var buffer = {};
- buffer['parenthesisLevel'] = 0;
- input = input.replace(/[\u2212\u2013\u2014\u2010]/g, "-");
- input = input.replace(/[\u2026]/g, "...");
- var lastInput, watchdog;
- var output = [];
- while (true) {
- if (lastInput !== input) {
- watchdog = 10;
- lastInput = input;
- } else {
- watchdog--;
- }
- //
- // Look for matching string in transition table
- //
- var machine = mhchemParser.stateMachines[stateMachine];
- var iTmax = machine.transitions.length;
- iterateTransitions:
- for (var iT=0; iT<iTmax; iT++) { // Surprisingly, looping is not slower than another data structure with direct lookups. 635d910e-0a6d-45b4-8d38-2f98ac9d9a94
- var t = machine.transitions[iT];
- var tasks = t.actions[state] || t.actions['*'] || null;
- if (tasks) { // testing tasks (actions) before matches is slightly faster
- var matches = mhchemParser.matchh(t.matchh, input);
- if (matches) {
- //
- // Execute action
- //
- var actions = mhchemParser.concatNotUndefined([], tasks.action);
- var iAmax = actions.length;
- for (var iA=0; iA<iAmax; iA++) {
- var a = actions[iA];
- var o;
- var option = undefined;
- if (a.type) {
- option = a.option;
- a = a.type;
- }
- if (typeof a === "string") {
- if (machine.actions[a]) {
- o = machine.actions[a](buffer, matches.matchh, option);
- } else if (mhchemParser.actions[a]) {
- o = mhchemParser.actions[a](buffer, matches.matchh, option);
- } else {
- throw ["MhchemBugA", "mhchem bug A. Please report. (" + a + ")"]; // Trying to use non-existing action
- }
- } else if (typeof a === "function") {
- o = a(buffer, matches.matchh);
- }
- output = mhchemParser.concatNotUndefined(output, o);
- }
- //
- // Set next state,
- // Shorten input,
- // Continue with next character
- // (= apply only one transition per position)
- //
- state = tasks.nextState || state;
- if (input.length > 0) {
- if (!tasks.revisit) {
- input = matches.remainder;
- }
- if (!tasks.toContinue) {
- break iterateTransitions;
- }
- } else {
- return output;
- }
- }
- }
- }
- //
- // Prevent infinite loop
- //
- if (watchdog <= 0) {
- throw ["MhchemBugU", "mhchem bug U. Please report."]; // Unexpected character
- }
- }
- };
- mhchemParser.concatNotUndefined = function(a, b) {
- if (!b) { return a; }
- if (!a) { return [].concat(b); }
- return a.concat(b);
- };
- //
- // Matching patterns
- // either regexps or function that return null or {match:"a", remainder:"bc"}
- //
- mhchemParser.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\\$])/,
- '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 (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 { matchh: 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 { matchh: m.splice(1), remainder: input.substr(m[0].length) };
- }
- return null;
- },
- 'state of aggregation $': function (input) { // or crystal system
- var a = this['_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 { matchh: 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 this['_findObserveGroups'](input, "^{", "", "", "}"); },
- '^($...$)': function (input) { return this['_findObserveGroups'](input, "^", "$", "$", ""); },
- '^a': /^\^([0-9]+|[^\\_])/,
- '^\\x{}{}': function (input) { return this['_findObserveGroups'](input, "^", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); },
- '^\\x{}': function (input) { return this['_findObserveGroups'](input, "^", /^\\[a-zA-Z]+\{/, "}", ""); },
- '^\\x': /^\^(\\[a-zA-Z]+)\s*/,
- '^(-1)': /^\^(-?\d+)/,
- '\'': /^'/,
- '_{(...)}': function (input) { return this['_findObserveGroups'](input, "_{", "", "", "}"); },
- '_($...$)': function (input) { return this['_findObserveGroups'](input, "_", "$", "$", ""); },
- '_9': /^_([+\-]?[0-9]+|[^\\])/,
- '_\\x{}{}': function (input) { return this['_findObserveGroups'](input, "_", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); },
- '_\\x{}': function (input) { return this['_findObserveGroups'](input, "_", /^\\[a-zA-Z]+\{/, "}", ""); },
- '_\\x': /^_(\\[a-zA-Z]+)\s*/,
- '^_': /^(?:\^(?=_)|\_(?=\^)|[\^_]$)/,
- '{}': /^\{\}/,
- '{...}': function (input) { return this['_findObserveGroups'](input, "", "{", "}", ""); },
- '{(...)}': function (input) { return this['_findObserveGroups'](input, "{", "", "", "}"); },
- '$...$': function (input) { return this['_findObserveGroups'](input, "", "$", "$", ""); },
- '${(...)}$': function (input) { return this['_findObserveGroups'](input, "${", "", "", "}$"); },
- '$(...)$': function (input) { return this['_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 (input) { return this['_findObserveGroups'](input, "\\bond{", "", "", "}"); },
- '->': /^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/,
- 'CMT': /^[CMT](?=\[)/,
- '[(...)]': function (input) { return this['_findObserveGroups'](input, "[", "", "", "]"); },
- '1st-level escape': /^(&|\\\\|\\hline)\s*/,
- '\\,': /^(?:\\[,\ ;:])/, // \\x - but output no space before
- '\\x{}{}': function (input) { return this['_findObserveGroups'](input, "", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); },
- '\\x{}': function (input) { return this['_findObserveGroups'](input, "", /^\\[a-zA-Z]+\{/, "}", ""); },
- '\\ca': /^\\ca(?:\s+|(?![a-zA-Z]))/,
- '\\x': /^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/,
- 'orbital': /^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/, // only those with numbers in front, because the others will be formatted correctly anyway
- 'others': /^[\/~|]/,
- '\\frac{(...)}': function (input) { return this['_findObserveGroups'](input, "\\frac{", "", "", "}", "{", "", "", "}"); },
- '\\overset{(...)}': function (input) { return this['_findObserveGroups'](input, "\\overset{", "", "", "}", "{", "", "", "}"); },
- '\\underset{(...)}': function (input) { return this['_findObserveGroups'](input, "\\underset{", "", "", "}", "{", "", "", "}"); },
- '\\underbrace{(...)}': function (input) { return this['_findObserveGroups'](input, "\\underbrace{", "", "", "}_", "{", "", "", "}"); },
- '\\color{(...)}0': function (input) { return this['_findObserveGroups'](input, "\\color{", "", "", "}"); },
- '\\color{(...)}{(...)}1': function (input) { return this['_findObserveGroups'](input, "\\color{", "", "", "}", "{", "", "", "}"); },
- '\\color(...){(...)}2': function (input) { return this['_findObserveGroups'](input, "\\color", "\\", "", /^(?=\{)/, "{", "", "", "}"); },
- '\\ce{(...)}': function (input) { return this['_findObserveGroups'](input, "\\ce{", "", "", "}"); },
- 'oxidation$': /^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,
- 'd-oxidation$': /^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, // 0 could be oxidation or charge
- 'roman numeral': /^[IVX]+/,
- '1/2$': /^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/,
- 'amount': function (input) {
- var matchh;
- // e.g. 2, 0.5, 1/2, -2, n/2, +; $a$ could be added later in parsing
- matchh = 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 (matchh) {
- return { matchh: matchh[0], remainder: input.substr(matchh[0].length) };
- }
- var a = this['_findObserveGroups'](input, "", "$", "$", "");
- if (a) { // e.g. $2n-1$, $-$
- matchh = a.matchh.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/);
- if (matchh) {
- return { matchh: matchh[0], remainder: input.substr(matchh[0].length) };
- }
- }
- return null;
- },
- 'amount2': function (input) { return this['amount'](input); },
- '(KV letters),': /^(?:[A-Z][a-z]{0,2}|i)(?=,)/,
- 'formula$': function (input) {
- if (input.match(/^\([a-z]+\)$/)) { return null; } // state of aggregation = no formula
- var matchh = input.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/);
- if (matchh) {
- return { matchh: matchh[0], remainder: input.substr(matchh[0].length) };
- }
- return null;
- },
- 'uprightEntities': /^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/,
- '/': /^\s*(\/)\s*/,
- '//': /^\s*(\/\/)\s*/,
- '*': /^\s*\*\s*/,
- '_findObserveGroups': function (input, begExcl, begIncl, endIncl, endExcl, beg2Excl, beg2Incl, end2Incl, end2Excl, combine) {
- var matchh = this['__match'](input, begExcl);
- if (matchh === null) { return null; }
- input = input.substr(matchh.length);
- matchh = this['__match'](input, begIncl);
- if (matchh === null) { return null; }
- var e = this['__findObserveGroups'](input, matchh.length, endIncl || endExcl);
- if (e === null) { return null; }
- var match1 = input.substring(0, (endIncl ? e.endMatchEnd : e.endMatchBegin));
- if (!(beg2Excl || beg2Incl)) {
- return {
- matchh: match1,
- remainder: input.substr(e.endMatchEnd)
- };
- } else {
- var group2 = this['_findObserveGroups'](input.substr(e.endMatchEnd), beg2Excl, beg2Incl, end2Incl, end2Excl);
- if (group2 === null) { return null; }
- var matchRet = [match1, group2.matchh];
- if (combine) { matchRet = matchRet.join(""); }
- return {
- matchh: matchRet,
- remainder: group2.remainder
- };
- }
- },
- '__match': function (input, pattern) {
- if (typeof pattern === "string") {
- if (input.indexOf(pattern) !== 0) { return null; }
- return pattern;
- } else {
- var matchh = input.match(pattern);
- if (!matchh) { return null; }
- return matchh[0];
- }
- },
- '__findObserveGroups': function (input, i, endChars) {
- var braces = 0;
- while (i < input.length) {
- var a = input.charAt(i);
- var matchh = this['__match'](input.substr(i), endChars);
- if (matchh !== null && braces === 0) {
- return { endMatchBegin: i, endMatchEnd: i + matchh.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;
- }
- };
- //
- // Matching function
- // e.g. matchh("a", input) will look for the regexp called "a" and see if it matches
- // returns null or {matchh:"a", remainder:"bc"}
- //
- mhchemParser.matchh = function (m, input) {
- var pattern = mhchemParser.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[m](input); // cannot use cached var pattern here, because some pattern functions need this===mhchemParser
- } else { // RegExp
- var matchh = input.match(pattern);
- if (matchh) {
- var mm;
- if (matchh[2]) {
- mm = [ matchh[1], matchh[2] ];
- } else if (matchh[1]) {
- mm = matchh[1];
- } else {
- mm = matchh[0];
- }
- return { matchh: mm, remainder: input.substr(matchh[0].length) };
- }
- return null;
- }
- };
- //
- // Generic state machine actions
- //
- mhchemParser.actions = {
- 'a=': function (buffer, m) { buffer.a = (buffer.a || "") + m; },
- 'b=': function (buffer, m) { buffer.b = (buffer.b || "") + m; },
- 'p=': function (buffer, m) { buffer.p = (buffer.p || "") + m; },
- 'o=': function (buffer, m) { buffer.o = (buffer.o || "") + m; },
- 'q=': function (buffer, m) { buffer.q = (buffer.q || "") + m; },
- 'd=': function (buffer, m) { buffer.d = (buffer.d || "") + m; },
- 'rm=': function (buffer, m) { buffer.rm = (buffer.rm || "") + m; },
- 'text=': function (buffer, m) { buffer.text = (buffer.text || "") + m; },
- 'insert': function (buffer, m, a) { return { type: a }; },
- 'insert+p1': function (buffer, m, a) { return { type: a, p1: m }; },
- 'insert+p1+p2': function (buffer, m, a) { return { type: a, p1: m[0], p2: m[1] }; },
- 'copy': function (buffer, m) { return m; },
- 'rm': function (buffer, m) { return { type: 'rm', p1: m }; },
- 'text': function (buffer, m) { return mhchemParser.go(m, 'text'); },
- '{text}': function (buffer, m) {
- var ret = [ "{" ];
- ret = mhchemParser.concatNotUndefined(ret, mhchemParser.go(m, 'text'));
- ret = mhchemParser.concatNotUndefined(ret, "}");
- return ret;
- },
- 'tex-math': function (buffer, m) { return mhchemParser.go(m, 'tex-math'); },
- 'tex-math tight': function (buffer, m) { return mhchemParser.go(m, 'tex-math tight'); },
- 'bond': function (buffer, m, k) { return { type: 'bond', kind: k || m }; },
- 'color0-output': function (buffer, m) { return { type: 'color0', color: m[0] }; },
- 'ce': function (buffer, m) { return mhchemParser.go(m); },
- '1/2': function (buffer, m) {
- var ret;
- if (m.match(/^[+\-]/)) {
- ret = [ 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 = mhchemParser.concatNotUndefined(ret, { type: 'frac', p1: n[1], p2: n[2] } );
- if (n[3]) {
- n[3] = n[3].replace(/\$/g, "");
- ret = mhchemParser.concatNotUndefined(ret, { type: 'tex-math', p1: n[3] } );
- }
- return ret;
- },
- '9,9': function (buffer, m) { return mhchemParser.go(m, '9,9'); }
- };
- //
- // State machine definitions
- //
- mhchemParser.stateMachines = {};
- //
- // convert { 'a': { '*': { action: 'output' } } } to [ { matchh: 'a', actions: { '*': { action: 'output' } } } ]
- // with expansion of 'a|b' to 'a' and 'b' (at 2 places)
- //
- mhchemParser.createTransitions = function (o) {
- var a, b, s, i;
- //
- // 1. o ==> oo, expanding 'a|b'
- //
- var oo = {};
- for (a in o) {
- if (a.indexOf("|") !== -1) {
- s = a.split("|");
- for (i=0; i<s.length; i++) {
- oo[s[i]] = o[a];
- }
- } else {
- oo[a] = o[a];
- }
- }
- //
- // 2. oo ==> transition array
- //
- var transitions = [];
- for (a in oo) {
- var actions = {};
- var ooa = oo[a];
- for (b in ooa) {
- //
- // expanding action-state:'a|b' if needed
- //
- if (b.indexOf("|") !== -1) {
- s = b.split("|");
- for (i=0; i<s.length; i++) {
- actions[s[i]] = ooa[b];
- }
- } else {
- actions[b] = ooa[b];
- }
- }
- transitions.push( { matchh: a, actions: actions } );
- }
- return transitions;
- };
- //
- //
- // \ce state machines
- //
- //
- // Transitions and actions of main parser
- //
- mhchemParser.stateMachines['ce'] = {
- 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: { type: '- after o', option: true }, nextState: '2' },
- 'd': { action: { type: '- after d', option: true }, 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: '- after o', nextState: '2' },
- 'q': { action: '- after o', nextState: '2' },
- 'd|qd|dq': { action: '- after d', 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: [ { type: 'output' }, 'sb=true' ], nextState: '1', revisit: true },
- 'r|rt|rd|rdt|rdq': { action: [ 'output' ], nextState: '0', revisit: true },
- '*': { action: [ 'output', 'copy' ], nextState: '3' } }
- }),
- actions: {
- 'o after d': function (buffer, m) {
- var ret;
- if (buffer.d.match(/^[0-9]+$/)) {
- var tmp = buffer.d;
- buffer.d = undefined;
- ret = this['output'](buffer);
- buffer.b = tmp;
- } else {
- ret = this['output'](buffer);
- }
- mhchemParser.actions['o='](buffer, m);
- return ret;
- },
- 'd= kv': function (buffer, m) {
- buffer.d = m;
- buffer['d-type'] = 'kv';
- },
- 'charge or bond': function (buffer, m) {
- if (buffer['beginsWithBond']) {
- var ret = mhchemParser.concatNotUndefined(ret, this['output'](buffer));
- ret = mhchemParser.concatNotUndefined(ret, mhchemParser.actions['bond'](buffer, m, "-"));
- return ret;
- } else {
- buffer.d = m;
- }
- },
- '- after o': function (buffer, m, isOrbitalOverlap) {
- var hyphenFollows = isOrbitalOverlap || this['_hyphenFollows'](buffer, m);
- var ret = mhchemParser.concatNotUndefined(null, this['output'](buffer, m));
- if (hyphenFollows) {
- ret = mhchemParser.concatNotUndefined(ret, { type: 'hyphen' });
- } else {
- ret = mhchemParser.concatNotUndefined(ret, mhchemParser.actions['bond'](buffer, m, "-"));
- }
- return ret;
- },
- '- after d': function (buffer, m, isOrbitalOverlap) {
- var hyphenFollows = isOrbitalOverlap || this['_hyphenFollows'](buffer, m);
- var ret;
- if (hyphenFollows) {
- ret = mhchemParser.concatNotUndefined(ret, this['output'](buffer, m));
- ret = mhchemParser.concatNotUndefined(ret, { type: 'hyphen' });
- } else {
- var c1 = mhchemParser.matchh('digits', buffer.d || "");
- if (c1 && c1.remainder==='') {
- ret = mhchemParser.concatNotUndefined(null, mhchemParser.actions['d='](buffer, m));
- ret = mhchemParser.concatNotUndefined(ret, this['output'](buffer));
- } else {
- ret = mhchemParser.concatNotUndefined(ret, this['output'](buffer, m));
- ret = mhchemParser.concatNotUndefined(ret, mhchemParser.actions['bond'](buffer, m, "-"));
- }
- }
- return ret;
- },
- '_hyphenFollows': function (buffer, m) {
- var c1 = mhchemParser.matchh('orbital', buffer.o || "");
- var c2 = mhchemParser.matchh('one lowercase greek letter $', buffer.o || "");
- var c3 = mhchemParser.matchh('one lowercase latin letter $', buffer.o || "");
- var c4 = mhchemParser.matchh('$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 + '$';
- }
- return hyphenFollows;
- },
- 'a to o': function (buffer, m) {
- buffer.o = buffer.a;
- buffer.a = undefined;
- },
- 'sb=true': function (buffer, m) { buffer.sb = true; },
- 'sb=false': function (buffer, m) { buffer.sb = false; },
- 'beginsWithBond=true': function (buffer, m) { buffer.beginsWithBond = true; },
- 'beginsWithBond=false': function (buffer, m) { buffer.beginsWithBond = false; },
- 'parenthesisLevel++': function (buffer, m) { buffer.parenthesisLevel++; },
- 'parenthesisLevel--': function (buffer, m) { buffer.parenthesisLevel--; },
- 'state of aggregation': function (buffer, m) {
- m = mhchemParser.go(m, 'o');
- return { type: 'state of aggregation', p1: m };
- },
- 'comma': function (buffer, m) {
- var a = m.replace(/\s*$/, '');
- var withSpace = (a !== m);
- if (withSpace && buffer['parenthesisLevel'] === 0) {
- return { type: 'comma enumeration L', p1: a };
- } else {
- return { type: 'comma enumeration M', p1: a };
- }
- },
- 'output': function (buffer, m, entityFollows) {
- // entityFollows:
- // undefined = if we have nothing else to output, also ignore the just read space (buffer.sb)
- // 1 = an entity follows, never omit the space if there was one just read before (can only apply to state 1)
- // 2 = 1 + the entity can have an amount, so output a\, instead of converting it to o (can only apply to states a|as)
- var ret;
- if (!buffer.r) {
- ret = [];
- if (!buffer.a && !buffer.b && !buffer.p && !buffer.o && !buffer.q && !buffer.d && !entityFollows) {
- ret = null;
- } 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['d-type']==='kv' && mhchemParser.matchh('d-oxidation$', buffer.d || "")) {
- buffer['d-type'] = 'oxidation';
- } else if (buffer.o && buffer['d-type']==='kv' && !buffer.q) {
- buffer['d-type'] = undefined;
- }
- }
- buffer.a = mhchemParser.go(buffer.a, 'a');
- buffer.b = mhchemParser.go(buffer.b, 'bd');
- buffer.p = mhchemParser.go(buffer.p, 'pq');
- buffer.o = mhchemParser.go(buffer.o, 'o');
- if (buffer['d-type'] === 'oxidation') {
- buffer.d = mhchemParser.go(buffer.d, 'oxidation');
- } else {
- buffer.d = mhchemParser.go(buffer.d, 'bd');
- }
- buffer.q = mhchemParser.go(buffer.q, 'pq');
- ret.push({
- type: 'chemfive',
- a: buffer.a,
- b: buffer.b,
- p: buffer.p,
- o: buffer.o,
- q: buffer.q,
- d: buffer.d,
- 'd-type': buffer['d-type']
- });
- }
- } else { // r
- if (buffer.rdt === 'M') {
- buffer.rd = mhchemParser.go(buffer.rd, 'tex-math');
- } else if (buffer.rdt === 'T') {
- buffer.rd = [ { type: 'text', p1: buffer.rd } ];
- } else {
- buffer.rd = mhchemParser.go(buffer.rd);
- }
- if (buffer.rqt === 'M') {
- buffer.rq = mhchemParser.go(buffer.rq, 'tex-math');
- } else if (buffer.rqt === 'T') {
- buffer.rq = [ { type: 'text', p1: buffer.rq } ];
- } else {
- buffer.rq = mhchemParser.go(buffer.rq);
- }
- ret = {
- type: 'arrow',
- r: buffer.r,
- rd: buffer.rd,
- rq: buffer.rq
- };
- }
- for (var p in buffer) {
- if (p !== 'parenthesisLevel' && p !== 'beginsWithBond') {
- delete buffer[p];
- }
- }
- return ret;
- },
- 'oxidation-output': function (buffer, m) {
- var ret = [ "{" ];
- ret = mhchemParser.concatNotUndefined(ret, mhchemParser.go(m, 'oxidation'));
- ret = ret.concat([ "}" ]);
- return ret;
- },
- 'frac-output': function (buffer, m) {
- return { type: 'frac-ce', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) };
- },
- 'overset-output': function (buffer, m) {
- return { type: 'overset', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) };
- },
- 'underset-output': function (buffer, m) {
- return { type: 'underset', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) };
- },
- 'underbrace-output': function (buffer, m) {
- return { type: 'underbrace', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) };
- },
- 'color-output': function (buffer, m) {
- return { type: 'color', color1: m[0], color2: mhchemParser.go(m[1]) };
- },
- 'r=': function (buffer, m) { buffer.r = (buffer.r || "") + m; },
- 'rdt=': function (buffer, m) { buffer.rdt = (buffer.rdt || "") + m; },
- 'rd=': function (buffer, m) { buffer.rd = (buffer.rd || "") + m; },
- 'rqt=': function (buffer, m) { buffer.rqt = (buffer.rqt || "") + m; },
- 'rq=': function (buffer, m) { buffer.rq = (buffer.rq || "") + m; },
- 'operator': function (buffer, m, p1) { return { type: 'operator', kind: (p1 || m) }; }
- }
- };
- //
- // Transitions and actions of a parser
- //
- mhchemParser.stateMachines['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: {}
- };
- //
- // Transitions and actions of o parser
- //
- mhchemParser.stateMachines['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: {}
- };
- //
- // Transitions and actions of text parser
- //
- mhchemParser.stateMachines['text'] = {
- transitions: mhchemParser.createTransitions({
- 'empty': {
- '*': { action: 'output' } },
- '{...}': {
- '*': { action: 'text=' } },
- '${(...)}$|$(...)$': {
- '*': { action: 'tex-math' } },
- '\\greek': {
- '*': { action: [ 'output', 'rm' ] } },
- '\\,|\\x{}{}|\\x{}|\\x': {
- '*': { action: [ 'output', 'copy' ] } },
- 'else': {
- '*': { action: 'text=' } }
- }),
- actions: {
- 'output': function (buffer, m) {
- if (buffer.text) {
- var ret = { type: 'text', p1: buffer.text };
- for (var p in buffer) { delete buffer[p]; }
- return ret;
- }
- return null;
- }
- }
- };
- //
- // Transitions and actions of pq parser
- //
- mhchemParser.stateMachines['pq'] = {
- transitions: mhchemParser.createTransitions({
- 'empty': {
- '*': {} },
- 'state of aggregation $': {
- '*': { action: 'state of aggregation' } },
- 'i$': {
- '0': { nextState: '!f', revisit: true } },
- '(KV letters),': {
- '0': { action: 'rm', nextState: '0' } },
- 'formula$': {
- '0': { nextState: 'f', revisit: true } },
- '1/2$': {
- '0': { action: '1/2' } },
- 'else': {
- '0': { nextState: '!f', revisit: true } },
- '${(...)}$|$(...)$': {
- '*': { action: 'tex-math' } },
- '{(...)}': {
- '*': { action: 'text' } },
- 'a-z': {
- 'f': { action: 'tex-math' } },
- 'letters': {
- '*': { action: 'rm' } },
- '-9.,9': {
- '*': { action: '9,9' } },
- ',': {
- '*': { action: { type: 'insert+p1', option: 'comma enumeration S' } } },
- '\\color{(...)}{(...)}1|\\color(...){(...)}2': {
- '*': { action: 'color-output' } },
- '\\color{(...)}0': {
- '*': { action: 'color0-output' } },
- '\\ce{(...)}': {
- '*': { action: 'ce' } },
- '\\,|\\x{}{}|\\x{}|\\x': {
- '*': { action: 'copy' } },
- 'else2': {
- '*': { action: 'copy' } }
- }),
- actions: {
- 'state of aggregation': function (buffer, m) {
- m = mhchemParser.go(m, 'o');
- return { type: 'state of aggregation subscript', p1: m };
- },
- 'color-output': function (buffer, m) {
- return { type: 'color', color1: m[0], color2: mhchemParser.go(m[1], 'pq') };
- }
- }
- };
- //
- // Transitions and actions of bd parser
- //
- mhchemParser.stateMachines['bd'] = {
- transitions: mhchemParser.createTransitions({
- 'empty': {
- '*': {} },
- 'x$': {
- '0': { nextState: '!f', revisit: true } },
- 'formula$': {
- '0': { nextState: 'f', revisit: true } },
- 'else': {
- '0': { nextState: '!f', revisit: true } },
- '-9.,9 no missing 0': {
- '*': { action: '9,9' } },
- '.': {
- '*': { action: { type: 'insert', option: 'electron dot' } } },
- 'a-z': {
- 'f': { action: 'tex-math' } },
- 'x': {
- '*': { action: { type: 'insert', option: 'KV x' } } },
- 'letters': {
- '*': { action: 'rm' } },
- '\'': {
- '*': { action: { type: 'insert', option: 'prime' } } },
- '${(...)}$|$(...)$': {
- '*': { action: 'tex-math' } },
- '{(...)}': {
- '*': { action: 'text' } },
- '\\color{(...)}{(...)}1|\\color(...){(...)}2': {
- '*': { action: 'color-output' } },
- '\\color{(...)}0': {
- '*': { action: 'color0-output' } },
- '\\ce{(...)}': {
- '*': { action: 'ce' } },
- '\\,|\\x{}{}|\\x{}|\\x': {
- '*': { action: 'copy' } },
- 'else2': {
- '*': { action: 'copy' } }
- }),
- actions: {
- 'color-output': function (buffer, m) {
- return { type: 'color', color1: m[0], color2: mhchemParser.go(m[1], 'bd') };
- }
- }
- };
- //
- // Transitions and actions of oxidation parser
- //
- mhchemParser.stateMachines['oxidation'] = {
- transitions: mhchemParser.createTransitions({
- 'empty': {
- '*': {} },
- 'roman numeral': {
- '*': { action: 'roman-numeral' } },
- '${(...)}$|$(...)$': {
- '*': { action: 'tex-math' } },
- 'else': {
- '*': { action: 'copy' } }
- }),
- actions: {
- 'roman-numeral': function (buffer, m) { return { type: 'roman numeral', p1: m }; }
- }
- };
- //
- // Transitions and actions of tex-math parser
- //
- mhchemParser.stateMachines['tex-math'] = {
- transitions: mhchemParser.createTransitions({
- 'empty': {
- '*': { action: 'output' } },
- '\\ce{(...)}': {
- '*': { action: [ 'output', 'ce' ] } },
- '{...}|\\,|\\x{}{}|\\x{}|\\x': {
- '*': { action: 'o=' } },
- 'else': {
- '*': { action: 'o=' } }
- }),
- actions: {
- 'output': function (buffer, m) {
- if (buffer.o) {
- var ret = { type: 'tex-math', p1: buffer.o };
- for (var p in buffer) { delete buffer[p]; }
- return ret;
- }
- return null;
- }
- }
- };
- //
- // Transitions and actions of tex-math-tight parser
- //
- mhchemParser.stateMachines['tex-math tight'] = {
- transitions: mhchemParser.createTransitions({
- 'empty': {
- '*': { action: 'output' } },
- '\\ce{(...)}': {
- '*': { action: [ 'output', 'ce' ] } },
- '{...}|\\,|\\x{}{}|\\x{}|\\x': {
- '*': { action: 'o=' } },
- '-|+': {
- '*': { action: 'tight operator' } },
- 'else': {
- '*': { action: 'o=' } }
- }),
- actions: {
- 'tight operator': function (buffer, m) { buffer.o = (buffer.o || "") + "{"+m+"}"; },
- 'output': function (buffer, m) {
- if (buffer.o) {
- var ret = { type: 'tex-math', p1: buffer.o };
- for (var p in buffer) { delete buffer[p]; }
- return ret;
- }
- return null;
- }
- }
- };
- //
- // Transitions and actions of 9,9 parser
- //
- mhchemParser.stateMachines['9,9'] = {
- transitions: mhchemParser.createTransitions({
- 'empty': {
- '*': {} },
- ',': {
- '*': { action: 'comma' } },
- 'else': {
- '*': { action: 'copy' } }
- }),
- actions: {
- 'comma': function (buffer, m) { return { type: 'commaDecimal' }; }
- }
- };
- //
- //
- // \pu state machines
- //
- //
- // Transitions and actions of pu main parser
- //
- mhchemParser.stateMachines['pu'] = {
- transitions: mhchemParser.createTransitions({
- 'empty': {
- '*': { action: 'output' } },
- '\{[(|)]\}': {
- '0|a': { action: 'copy' } },
- '(-)(9)^(-9)': {
- '0': { action: 'number^', nextState: 'a' } },
- '(-)(9.,9)(e)(99)': {
- '0': { action: 'enumber', nextState: 'a' } },
- 'space': {
- '0|a': {} },
- 'pm-operator': {
- '0|a': { action: { type: 'operator', option: '\\pm' }, nextState: '0' } },
- 'operator': {
- '0|a': { action: 'copy', nextState: '0' } },
- '//': {
- 'd': { action: 'o=', nextState: '/' } },
- '/': {
- 'd': { action: 'o=', nextState: '/' } },
- '{...}|else': {
- '0|d': { action: 'd=', nextState: 'd' },
- 'a': { action: [ 'space', 'd=' ], nextState: 'd' },
- '/|q': { action: 'q=', nextState: 'q' } }
- }),
- actions: {
- 'enumber': function (buffer, m) {
- var ret = [];
- if (m[0] === "+-" || m[0] === "+/-") {
- ret.push("\\pm ");
- } else if (m[0]) {
- ret.push(m[0]);
- }
- if (m[1]) {
- ret = mhchemParser.concatNotUndefined(ret, mhchemParser.go(m[1], 'pu-9,9'));
- if (m[2]) {
- if (m[2].match(/[,.]/)) {
- ret = mhchemParser.concatNotUndefined(ret, mhchemParser.go(m[2], 'pu-9,9'));
- } else {
- ret.push(m[2]);
- }
- }
- m[3] = m[4] || m[3];
- if (m[3]) {
- m[3] = m[3].trim();
- if (m[3] === "e" || m[3].substr(0, 1) === "*") {
- ret.push({ type: 'cdot' });
- } else {
- ret.push({ type: 'times' });
- }
- }
- }
- if (m[3]) {
- ret.push("10^{"+m[5]+"}");
- }
- return ret;
- },
- 'number^': function (buffer, m) {
- var ret = [];
- if (m[0] === "+-" || m[0] === "+/-") {
- ret.push("\\pm ");
- } else if (m[0]) {
- ret.push(m[0]);
- }
- ret = mhchemParser.concatNotUndefined(ret, mhchemParser.go(m[1], 'pu-9,9'));
- ret.push("^{"+m[2]+"}");
- return ret;
- },
- 'operator': function (buffer, m, p1) { return { type: 'operator', kind: (p1 || m) }; },
- 'space': function (buffer, m) { return { type: 'pu-space-1' }; },
- 'output': function (buffer, m) {
- var ret;
- var md = mhchemParser.matchh('{(...)}', buffer.d || "");
- if (md && md.remainder === '') { buffer.d = md.matchh; }
- var mq = mhchemParser.matchh('{(...)}', buffer.q || "");
- if (mq && mq.remainder === '') { buffer.q = mq.matchh; }
- 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.d = mhchemParser.go(buffer.d, 'pu');
- buffer.q = buffer.q.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C");
- buffer.q = buffer.q.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F");
- buffer.q = mhchemParser.go(buffer.q, 'pu');
- if (buffer.o === '//') {
- ret = { type: 'pu-frac', p1: buffer.d, p2: buffer.q };
- } else {
- ret = buffer.d;
- if (buffer.d.length > 1 || buffer.q.length > 1) {
- ret = mhchemParser.concatNotUndefined(ret, { type: ' / ' });
- } else {
- ret = mhchemParser.concatNotUndefined(ret, { type: '/' });
- }
- ret = mhchemParser.concatNotUndefined(ret, buffer.q);
- }
- } else { // no fraction
- ret = mhchemParser.go(buffer.d, 'pu-2');
- }
- for (var p in buffer) { delete buffer[p]; }
- return ret;
- }
- }
- };
- //
- // Transitions and actions of pu-2 parser
- //
- mhchemParser.stateMachines['pu-2'] = {
- transitions: mhchemParser.createTransitions({
- 'empty': {
- '*': { action: 'output' } },
- '*': {
- '*': { action: [ 'output', 'cdot' ], nextState: '0' } },
- '\\x': {
- '*': { action: 'rm=' }, nextState: '1' },
- '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 (buffer, m) { return { type: 'tight cdot' }; },
- '^(-1)': function (buffer, m) { buffer.rm += "^{"+m+"}"; },
- 'space': function (buffer, m) { return { type: 'pu-space-2' }; },
- 'output': function (buffer, m) {
- var ret;
- if (buffer.rm) {
- var mrm = mhchemParser.matchh('{(...)}', buffer.rm || "");
- if (mrm && mrm.remainder === '') {
- ret = mhchemParser.go(mrm.matchh, 'pu');
- } else {
- ret = { type: 'rm', p1: buffer.rm };
- }
- }
- for (var p in buffer) { delete buffer[p]; }
- return ret;
- }
- }
- };
- //
- // Transitions and actions of 9,9 parser
- //
- mhchemParser.stateMachines['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 (buffer, m) { return { type: 'commaDecimal' }; },
- 'output-0': function (buffer, m) {
- var ret = [];
- if (buffer.text.length > 4) {
- var a = buffer.text.length % 3;
- if (a === 0) { a = 3; }
- for (var i=buffer.text.length-3; i>0; i-=3) {
- ret.push(buffer.text.substr(i, 3));
- ret.push({ type: '1000 separator' });
- }
- ret.push(buffer.text.substr(0, a));
- ret.reverse();
- } else {
- ret.push(buffer.text);
- }
- for (var p in buffer) { delete buffer[p]; }
- return ret;
- },
- 'output-o': function (buffer, m) {
- var ret = [];
- 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;
- }
- }
- };
- //
- //
- // Take MhchemParser output and convert it to TeX
- // (recursive)
- //
- //
- var texify = {
- types: {
- 'chemfive': function (buf) {
- var res = "";
- buf.a = texify.go2(buf.a);
- buf.b = texify.go2(buf.b);
- buf.p = texify.go2(buf.p);
- buf.o = texify.go2(buf.o);
- buf.q = texify.go2(buf.q);
- buf.d = texify.go2(buf.d);
- //
- // a
- //
- if (buf.a) {
- if (buf.a.match(/^[+\-]/)) { buf.a = "{"+buf.a+"}"; }
- res += buf.a + "\\,";
- }
- //
- // b and p
- //
- if (buf.b || buf.p) {
- res += "{\\vphantom{X}}";
- res += "^{\\hphantom{"+(buf.b||"")+"}}_{\\hphantom{"+(buf.p||"")+"}}";
- res += "{\\vphantom{X}}";
- res += "^{\\smash[t]{\\vphantom{2}}\\llap{"+(buf.b||"")+"}}";
- res += "_{\\vphantom{2}\\llap{\\smash[t]{"+(buf.p||"")+"}}}";
- }
- //
- // o
- //
- if (buf.o) {
- if (buf.o.match(/^[+\-]/)) { buf.o = "{"+buf.o+"}"; }
- res += buf.o;
- }
- //
- // q and d
- //
- if (buf['d-type'] === 'kv') {
- if (buf.d || buf.q) {
- res += "{\\vphantom{X}}";
- }
- if (buf.d) {
- res += "^{"+buf.d+"}";
- }
- if (buf.q) {
- res += "_{\\smash[t]{"+buf.q+"}}";
- }
- } else if (buf['d-type'] === 'oxidation') {
- if (buf.d) {
- res += "{\\vphantom{X}}";
- res += "^{"+buf.d+"}";
- }
- if (buf.q) {
- res += "{\\vphantom{X}}";
- res += "_{\\smash[t]{"+buf.q+"}}";
- }
- } else {
- if (buf.q) {
- res += "{\\vphantom{X}}";
- res += "_{\\smash[t]{"+buf.q+"}}";
- }
- if (buf.d) {
- res += "{\\vphantom{X}}";
- res += "^{"+buf.d+"}";
- }
- }
- return res;
- },
- 'rm': function (buf) { return "\\mathrm{"+buf.p1+"}"; },
- 'text': function (buf) {
- if (buf.p1.match(/[\^_]/)) {
- buf.p1 = buf.p1.replace(" ", "~").replace("-", "\\text{-}");
- return "\\mathrm{"+buf.p1+"}";
- } else {
- return "\\text{"+buf.p1+"}";
- }
- },
- 'roman numeral': function (buf) { return "\\mathrm{"+buf.p1+"}"; },
- 'state of aggregation': function (buf) { return "\\mskip2mu "+texify.go2(buf.p1); },
- 'state of aggregation subscript': function (buf) { return "\\mskip1mu "+texify.go2(buf.p1); },
- 'bond': function (buf) {
- var ret = texify.bonds[buf.kind];
- if (!ret) {
- throw ["MhchemErrorBond", "mhchem Error. Unknown bond type (" + buf.kind + ")"];
- }
- return ret;
- },
- 'frac': function (buf) {
- var c = "\\frac{" + buf.p1 + "}{" + buf.p2 + "}";
- return "\\mathchoice{\\textstyle"+c+"}{"+c+"}{"+c+"}{"+c+"}";
- },
- 'pu-frac': function (buf) {
- var c = "\\frac{" + texify.go2(buf.p1) + "}{" + texify.go2(buf.p2) + "}";
- return "\\mathchoice{\\textstyle"+c+"}{"+c+"}{"+c+"}{"+c+"}";
- },
- 'tex-math': function (buf) { return buf.p1 + " "; },
- 'frac-ce': function (buf) {
- return "\\frac{" + texify.go2(buf.p1) + "}{" + texify.go2(buf.p2) + "}";
- },
- 'overset': function (buf) {
- return "\\overset{" + texify.go2(buf.p1) + "}{" + texify.go2(buf.p2) + "}";
- },
- 'underset': function (buf) {
- return "\\underset{" + texify.go2(buf.p1) + "}{" + texify.go2(buf.p2) + "}";
- },
- 'underbrace': function (buf) {
- return "\\underbrace{" + texify.go2(buf.p1) + "}_{" + texify.go2(buf.p2) + "}";
- },
- 'color': function (buf) {
- return "{\\color{" + buf.color1 + "}{" + texify.go2(buf.color2) + "}}";
- },
- 'color0': function (buf) {
- return "\\color{" + buf.color + "}";
- },
- 'arrow': function (buf) {
- buf.rd = texify.go2(buf.rd);
- buf.rq = texify.go2(buf.rq);
- var arrow = texify.arrows[buf.r];
- if (buf.rd || buf.rq) {
- if (buf.r === "<=>" || buf.r === "<=>>" || buf.r === "<<=>" || buf.r === "<-->") {
- // arrows that cannot stretch correctly yet, https://github.com/mathjax/MathJax/issues/1491
- arrow = "\\long"+arrow;
- if (buf.rd) { arrow = "\\overset{"+buf.rd+"}{"+arrow+"}"; }
- if (buf.rq) { arrow = "\\underset{\\lower7mu{"+buf.rq+"}}{"+arrow+"}"; }
- arrow = " {}\\mathrel{"+arrow+"}{} ";
- } else {
- if (buf.rq) { arrow += "[{"+buf.rq+"}]"; }
- arrow += "{"+buf.rd+"}";
- arrow = " {}\\mathrel{\\x"+arrow+"}{} ";
- }
- } else {
- arrow = " {}\\mathrel{\\long"+arrow+"}{} ";
- }
- return arrow;
- },
- 'operator': function (buf) { return texify.operators[buf.kind]; }
- },
- arrows: {
- "->": "rightarrow",
- "\u2192": "rightarrow",
- "\u27F6": "rightarrow",
- "<-": "leftarrow",
- "<->": "leftrightarrow",
- "<-->": "leftrightarrows",
- "<=>": "rightleftharpoons",
- "\u21CC": "rightleftharpoons",
- "<=>>": "Rightleftharpoons",
- "<<=>": "Leftrightharpoons"
- },
- bonds: {
- "-": "{-}",
- "1": "{-}",
- "=": "{=}",
- "2": "{=}",
- "#": "{\\equiv}",
- "3": "{\\equiv}",
- "~": "{\\tripledash}",
- "~-": "{\\rlap{\\lower.1em{-}}\\raise.1em{\\tripledash}}",
- "~=": "{\\rlap{\\lower.2em{-}}\\rlap{\\raise.2em{\\tripledash}}-}",
- "~--": "{\\rlap{\\lower.2em{-}}\\rlap{\\raise.2em{\\tripledash}}-}",
- "-~-": "{\\rlap{\\lower.2em{-}}\\rlap{\\raise.2em{-}}\\tripledash}",
- "...": "{{\\cdot}{\\cdot}{\\cdot}}",
- "....": "{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}",
- "->": "{\\rightarrow}",
- "<-": "{\\leftarrow}",
- "<": "{<}",
- ">": "{>}"
- },
- entities: {
- 'space': " ",
- 'entitySkip': "~",
- 'pu-space-1': "~",
- 'pu-space-2': "\\mkern3mu ",
- '1000 separator': "\\mkern2mu ",
- 'commaDecimal': "{,}",
- 'comma enumeration L': "{{0}}\\mkern6mu ",
- 'comma enumeration M': "{{0}}\\mkern3mu ",
- 'comma enumeration S': "{{0}}\\mkern1mu ",
- 'hyphen': "\\text{-}",
- 'addition compound': "\\,{\\cdot}\\,",
- 'electron dot': "\\mkern1mu \\bullet\\mkern1mu ",
- 'KV x': "{\\times}",
- 'prime': "\\prime ",
- 'cdot': "\\cdot ",
- 'tight cdot': "\\mkern1mu{\\cdot}\\mkern1mu ",
- 'times': "\\times ",
- 'circa': "{\\sim}",
- '^': "uparrow",
- 'v': "downarrow",
- 'ellipsis': "\\ldots ",
- '/': "/",
- ' / ': "\\,/\\,",
- '1st-level escape': "{0} " // &, \\\\, \\hline
- },
- operators: {
- "+": " {}+{} ",
- "-": " {}-{} ",
- "=": " {}={} ",
- "<": " {}<{} ",
- ">": " {}>{} ",
- "<<": " {}\\ll{} ",
- ">>": " {}\\gg{} ",
- "\\pm": " {}\\pm{} ",
- "\\approx": " {}\\approx{} ",
- "$\\approx$": " {}\\approx{} ",
- "v": " \\downarrow{} ",
- "(v)": " \\downarrow{} ",
- "^": " \\uparrow{} ",
- "(^)": " \\uparrow{} "
- },
- go: function (input, isInner) {
- if (!input) { return input; }
- var res = "";
- var cee = false;
- for (var i=0; i<input.length; i++) {
- var inputi = input[i];
- if (typeof inputi === "string") {
- res += inputi;
- } else if (this.types[inputi.type]) {
- res += this.types[inputi.type](inputi);
- } else if (this.entities[inputi.type]) {
- var a = this.entities[inputi.type];
- a = a.replace("{0}", inputi.p1 || "");
- a = a.replace("{1}", inputi.p2 || "");
- res += a;
- if (inputi.type === '1st-level escape') { cee = true; }
- } else {
- throw ["MhchemBugT", "mhchem bug T. Please report."]; // Missing texify rule or unknown MhchemParser output
- }
- }
- if (!isInner && !cee) {
- res = "{" + res + "}";
- }
- return res;
- },
- go2: function(input) {
- return this.go(input, true);
- }
- };
- MathJax.Extension["TeX/mhchem"].CE = CE;
- /***************************************************************************/
- TEX.Definitions.Add({
- macros: {
- //
- // Set up the macros for chemistry
- //
- ce: "CE",
- pu: "PU",
- //
- // Make these load AMSmath package (redefined below when loaded)
- //
- xleftrightarrow: ["Extension","AMSmath"],
- xrightleftharpoons: ["Extension","AMSmath"],
- xRightleftharpoons: ["Extension","AMSmath"],
- xLeftrightharpoons: ["Extension","AMSmath"],
- // FIXME: These don't work well in FF NativeMML mode
- longrightleftharpoons: ["Macro","\\stackrel{\\textstyle{-}\\!\\!{\\rightharpoonup}}{\\smash{{\\leftharpoondown}\\!\\!{-}}}"],
- longRightleftharpoons: ["Macro","\\stackrel{\\textstyle{-}\\!\\!{\\rightharpoonup}}{\\smash{\\leftharpoondown}}"],
- longLeftrightharpoons: ["Macro","\\stackrel{\\textstyle\\vphantom{{-}}{\\rightharpoonup}}{\\smash{{\\leftharpoondown}\\!\\!{-}}}"],
- longleftrightarrows: ["Macro","\\stackrel{\\longrightarrow}{\\smash{\\longleftarrow}\\Rule{0px}{.25em}{0px}}"],
- //
- // Needed for \bond for the ~ forms
- // Not perfectly aligned when zoomed in, but on 100%
- //
- tripledash: ["Macro","\\vphantom{-}\\raise2mu{\\kern2mu\\tiny\\text{-}\\kern1mu\\text{-}\\kern1mu\\text{-}\\kern2mu}"]
- },
- },null,true);
- if (!MathJax.Extension["TeX/AMSmath"]) {
- TEX.Definitions.Add({
- macros: {
- xrightarrow: ["Extension","AMSmath"],
- xleftarrow: ["Extension","AMSmath"]
- }
- },null,true);
- }
- //
- // These arrows need to wait until AMSmath is loaded
- //
- MathJax.Hub.Register.StartupHook("TeX AMSmath Ready",function () {
- TEX.Definitions.Add({
- macros: {
- //
- // Some of these are hacks for now
- //
- xleftrightarrow: ["xArrow",0x2194,6,6],
- xrightleftharpoons: ["xArrow",0x21CC,5,7], // FIXME: doesn't stretch in HTML-CSS output
- xRightleftharpoons: ["xArrow",0x21CC,5,7], // FIXME: how should this be handled?
- xLeftrightharpoons: ["xArrow",0x21CC,5,7]
- }
- },null,true);
- });
- TEX.Parse.Augment({
- //
- // Implements \ce and friends
- //
- CE: function (name) {
- var arg = this.GetArgument(name);
- var tex = CE(arg).Parse();
- this.string = tex + this.string.substr(this.i); this.i = 0;
- },
- PU: function (name) {
- var arg = this.GetArgument(name);
- var tex = CE(arg).Parse('pu');
- this.string = tex + this.string.substr(this.i); this.i = 0;
- }
- });
- //
- // Indicate that the extension is ready
- //
- MathJax.Hub.Startup.signal.Post("TeX mhchem Ready");
- });
- MathJax.Ajax.loadComplete("[mhchem]/mhchem.js");
|