mhchem.mjs 74 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864
  1. import katex from '../katex.mjs';
  2. /* eslint-disable */
  3. /* -*- Mode: JavaScript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
  4. /* vim: set ts=2 et sw=2 tw=80: */
  5. /*************************************************************
  6. *
  7. * KaTeX mhchem.js
  8. *
  9. * This file implements a KaTeX version of mhchem version 3.3.0.
  10. * It is adapted from MathJax/extensions/TeX/mhchem.js
  11. * It differs from the MathJax version as follows:
  12. * 1. The interface is changed so that it can be called from KaTeX, not MathJax.
  13. * 2. \rlap and \llap are replaced with \mathrlap and \mathllap.
  14. * 3. Four lines of code are edited in order to use \raisebox instead of \raise.
  15. * 4. The reaction arrow code is simplified. All reaction arrows are rendered
  16. * using KaTeX extensible arrows instead of building non-extensible arrows.
  17. * 5. \tripledash vertical alignment is slightly adjusted.
  18. *
  19. * This code, as other KaTeX code, is released under the MIT license.
  20. *
  21. * /*************************************************************
  22. *
  23. * MathJax/extensions/TeX/mhchem.js
  24. *
  25. * Implements the \ce command for handling chemical formulas
  26. * from the mhchem LaTeX package.
  27. *
  28. * ---------------------------------------------------------------------
  29. *
  30. * Copyright (c) 2011-2015 The MathJax Consortium
  31. * Copyright (c) 2015-2018 Martin Hensel
  32. *
  33. * Licensed under the Apache License, Version 2.0 (the "License");
  34. * you may not use this file except in compliance with the License.
  35. * You may obtain a copy of the License at
  36. *
  37. * http://www.apache.org/licenses/LICENSE-2.0
  38. *
  39. * Unless required by applicable law or agreed to in writing, software
  40. * distributed under the License is distributed on an "AS IS" BASIS,
  41. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  42. * See the License for the specific language governing permissions and
  43. * limitations under the License.
  44. */
  45. //
  46. // Coding Style
  47. // - use '' for identifiers that can by minified/uglified
  48. // - use "" for strings that need to stay untouched
  49. // version: "3.3.0" for MathJax and KaTeX
  50. // Add \ce, \pu, and \tripledash to the KaTeX macros.
  51. katex.__defineMacro("\\ce", function (context) {
  52. return chemParse(context.consumeArgs(1)[0], "ce");
  53. });
  54. katex.__defineMacro("\\pu", function (context) {
  55. return chemParse(context.consumeArgs(1)[0], "pu");
  56. });
  57. // Needed for \bond for the ~ forms
  58. // Raise by 2.56mu, not 2mu. We're raising a hyphen-minus, U+002D, not
  59. // a mathematical minus, U+2212. So we need that extra 0.56.
  60. katex.__defineMacro("\\tripledash", "{\\vphantom{-}\\raisebox{2.56mu}{$\\mkern2mu" + "\\tiny\\text{-}\\mkern1mu\\text{-}\\mkern1mu\\text{-}\\mkern2mu$}}");
  61. //
  62. // This is the main function for handing the \ce and \pu commands.
  63. // It takes the argument to \ce or \pu and returns the corresponding TeX string.
  64. //
  65. var chemParse = function chemParse(tokens, stateMachine) {
  66. // Recreate the argument string from KaTeX's array of tokens.
  67. var str = "";
  68. var expectedLoc = tokens.length && tokens[tokens.length - 1].loc.start;
  69. for (var i = tokens.length - 1; i >= 0; i--) {
  70. if (tokens[i].loc.start > expectedLoc) {
  71. // context.consumeArgs has eaten a space.
  72. str += " ";
  73. expectedLoc = tokens[i].loc.start;
  74. }
  75. str += tokens[i].text;
  76. expectedLoc += tokens[i].text.length;
  77. }
  78. var tex = texify.go(mhchemParser.go(str, stateMachine));
  79. return tex;
  80. };
  81. //
  82. // Core parser for mhchem syntax (recursive)
  83. //
  84. /** @type {MhchemParser} */
  85. var mhchemParser = {
  86. //
  87. // Parses mchem \ce syntax
  88. //
  89. // Call like
  90. // go("H2O");
  91. //
  92. go: function go(input, stateMachine) {
  93. if (!input) {
  94. return [];
  95. }
  96. if (stateMachine === undefined) {
  97. stateMachine = 'ce';
  98. }
  99. var state = '0';
  100. //
  101. // String buffers for parsing:
  102. //
  103. // buffer.a == amount
  104. // buffer.o == element
  105. // buffer.b == left-side superscript
  106. // buffer.p == left-side subscript
  107. // buffer.q == right-side subscript
  108. // buffer.d == right-side superscript
  109. //
  110. // buffer.r == arrow
  111. // buffer.rdt == arrow, script above, type
  112. // buffer.rd == arrow, script above, content
  113. // buffer.rqt == arrow, script below, type
  114. // buffer.rq == arrow, script below, content
  115. //
  116. // buffer.text_
  117. // buffer.rm
  118. // etc.
  119. //
  120. // buffer.parenthesisLevel == int, starting at 0
  121. // buffer.sb == bool, space before
  122. // buffer.beginsWithBond == bool
  123. //
  124. // These letters are also used as state names.
  125. //
  126. // Other states:
  127. // 0 == begin of main part (arrow/operator unlikely)
  128. // 1 == next entity
  129. // 2 == next entity (arrow/operator unlikely)
  130. // 3 == next atom
  131. // c == macro
  132. //
  133. /** @type {Buffer} */
  134. var buffer = {};
  135. buffer['parenthesisLevel'] = 0;
  136. input = input.replace(/\n/g, " ");
  137. input = input.replace(/[\u2212\u2013\u2014\u2010]/g, "-");
  138. input = input.replace(/[\u2026]/g, "...");
  139. //
  140. // Looks through mhchemParser.transitions, to execute a matching action
  141. // (recursive)
  142. //
  143. var lastInput;
  144. var watchdog = 10;
  145. /** @type {ParserOutput[]} */
  146. var output = [];
  147. while (true) {
  148. if (lastInput !== input) {
  149. watchdog = 10;
  150. lastInput = input;
  151. } else {
  152. watchdog--;
  153. }
  154. //
  155. // Find actions in transition table
  156. //
  157. var machine = mhchemParser.stateMachines[stateMachine];
  158. var t = machine.transitions[state] || machine.transitions['*'];
  159. iterateTransitions: for (var i = 0; i < t.length; i++) {
  160. var matches = mhchemParser.patterns.match_(t[i].pattern, input);
  161. if (matches) {
  162. //
  163. // Execute actions
  164. //
  165. var task = t[i].task;
  166. for (var iA = 0; iA < task.action_.length; iA++) {
  167. var o;
  168. //
  169. // Find and execute action
  170. //
  171. if (machine.actions[task.action_[iA].type_]) {
  172. o = machine.actions[task.action_[iA].type_](buffer, matches.match_, task.action_[iA].option);
  173. } else if (mhchemParser.actions[task.action_[iA].type_]) {
  174. o = mhchemParser.actions[task.action_[iA].type_](buffer, matches.match_, task.action_[iA].option);
  175. } else {
  176. throw ["MhchemBugA", "mhchem bug A. Please report. (" + task.action_[iA].type_ + ")"]; // Trying to use non-existing action
  177. }
  178. //
  179. // Add output
  180. //
  181. mhchemParser.concatArray(output, o);
  182. }
  183. //
  184. // Set next state,
  185. // Shorten input,
  186. // Continue with next character
  187. // (= apply only one transition per position)
  188. //
  189. state = task.nextState || state;
  190. if (input.length > 0) {
  191. if (!task.revisit) {
  192. input = matches.remainder;
  193. }
  194. if (!task.toContinue) {
  195. break iterateTransitions;
  196. }
  197. } else {
  198. return output;
  199. }
  200. }
  201. }
  202. //
  203. // Prevent infinite loop
  204. //
  205. if (watchdog <= 0) {
  206. throw ["MhchemBugU", "mhchem bug U. Please report."]; // Unexpected character
  207. }
  208. }
  209. },
  210. concatArray: function concatArray(a, b) {
  211. if (b) {
  212. if (Array.isArray(b)) {
  213. for (var iB = 0; iB < b.length; iB++) {
  214. a.push(b[iB]);
  215. }
  216. } else {
  217. a.push(b);
  218. }
  219. }
  220. },
  221. patterns: {
  222. //
  223. // Matching patterns
  224. // either regexps or function that return null or {match_:"a", remainder:"bc"}
  225. //
  226. patterns: {
  227. // property names must not look like integers ("2") for correct property traversal order, later on
  228. 'empty': /^$/,
  229. 'else': /^./,
  230. 'else2': /^./,
  231. 'space': /^\s/,
  232. 'space A': /^\s(?=[A-Z\\$])/,
  233. 'space$': /^\s$/,
  234. 'a-z': /^[a-z]/,
  235. 'x': /^x/,
  236. 'x$': /^x$/,
  237. 'i$': /^i$/,
  238. '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]))))+/,
  239. '\\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]))/,
  240. 'one lowercase latin letter $': /^(?:([a-z])(?:$|[^a-zA-Z]))$/,
  241. '$one lowercase latin letter$ $': /^\$(?:([a-z])(?:$|[^a-zA-Z]))\$$/,
  242. '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]))$/,
  243. 'digits': /^[0-9]+/,
  244. '-9.,9': /^[+\-]?(?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))/,
  245. '-9.,9 no missing 0': /^[+\-]?[0-9]+(?:[.,][0-9]+)?/,
  246. '(-)(9.,9)(e)(99)': function e99(input) {
  247. 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]+\}))?/);
  248. if (m && m[0]) {
  249. return {
  250. match_: m.splice(1),
  251. remainder: input.substr(m[0].length)
  252. };
  253. }
  254. return null;
  255. },
  256. '(-)(9)^(-9)': function _(input) {
  257. var m = input.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+)?)\^([+\-]?[0-9]+|\{[+\-]?[0-9]+\})/);
  258. if (m && m[0]) {
  259. return {
  260. match_: m.splice(1),
  261. remainder: input.substr(m[0].length)
  262. };
  263. }
  264. return null;
  265. },
  266. 'state of aggregation $': function state_of_aggregation_$(input) {
  267. // ... or crystal system
  268. var a = mhchemParser.patterns.findObserveGroups(input, "", /^\([a-z]{1,3}(?=[\),])/, ")", ""); // (aq), (aq,$\infty$), (aq, sat)
  269. if (a && a.remainder.match(/^($|[\s,;\)\]\}])/)) {
  270. return a;
  271. } // AND end of 'phrase'
  272. var m = input.match(/^(?:\((?:\\ca\s?)?\$[amothc]\$\))/); // OR crystal system ($o$) (\ca$c$)
  273. if (m) {
  274. return {
  275. match_: m[0],
  276. remainder: input.substr(m[0].length)
  277. };
  278. }
  279. return null;
  280. },
  281. '_{(state of aggregation)}$': /^_\{(\([a-z]{1,3}\))\}/,
  282. '{[(': /^(?:\\\{|\[|\()/,
  283. ')]}': /^(?:\)|\]|\\\})/,
  284. ', ': /^[,;]\s*/,
  285. ',': /^[,;]/,
  286. '.': /^[.]/,
  287. '. ': /^([.\u22C5\u00B7\u2022])\s*/,
  288. '...': /^\.\.\.(?=$|[^.])/,
  289. '* ': /^([*])\s*/,
  290. '^{(...)}': function _(input) {
  291. return mhchemParser.patterns.findObserveGroups(input, "^{", "", "", "}");
  292. },
  293. '^($...$)': function $$(input) {
  294. return mhchemParser.patterns.findObserveGroups(input, "^", "$", "$", "");
  295. },
  296. '^a': /^\^([0-9]+|[^\\_])/,
  297. '^\\x{}{}': function x(input) {
  298. return mhchemParser.patterns.findObserveGroups(input, "^", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true);
  299. },
  300. '^\\x{}': function x(input) {
  301. return mhchemParser.patterns.findObserveGroups(input, "^", /^\\[a-zA-Z]+\{/, "}", "");
  302. },
  303. '^\\x': /^\^(\\[a-zA-Z]+)\s*/,
  304. '^(-1)': /^\^(-?\d+)/,
  305. '\'': /^'/,
  306. '_{(...)}': function _(input) {
  307. return mhchemParser.patterns.findObserveGroups(input, "_{", "", "", "}");
  308. },
  309. '_($...$)': function _$$(input) {
  310. return mhchemParser.patterns.findObserveGroups(input, "_", "$", "$", "");
  311. },
  312. '_9': /^_([+\-]?[0-9]+|[^\\])/,
  313. '_\\x{}{}': function _X(input) {
  314. return mhchemParser.patterns.findObserveGroups(input, "_", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true);
  315. },
  316. '_\\x{}': function _X(input) {
  317. return mhchemParser.patterns.findObserveGroups(input, "_", /^\\[a-zA-Z]+\{/, "}", "");
  318. },
  319. '_\\x': /^_(\\[a-zA-Z]+)\s*/,
  320. '^_': /^(?:\^(?=_)|\_(?=\^)|[\^_]$)/,
  321. '{}': /^\{\}/,
  322. '{...}': function _(input) {
  323. return mhchemParser.patterns.findObserveGroups(input, "", "{", "}", "");
  324. },
  325. '{(...)}': function _(input) {
  326. return mhchemParser.patterns.findObserveGroups(input, "{", "", "", "}");
  327. },
  328. '$...$': function $$(input) {
  329. return mhchemParser.patterns.findObserveGroups(input, "", "$", "$", "");
  330. },
  331. '${(...)}$': function $$(input) {
  332. return mhchemParser.patterns.findObserveGroups(input, "${", "", "", "}$");
  333. },
  334. '$(...)$': function $$(input) {
  335. return mhchemParser.patterns.findObserveGroups(input, "$", "", "", "$");
  336. },
  337. '=<>': /^[=<>]/,
  338. '#': /^[#\u2261]/,
  339. '+': /^\+/,
  340. '-$': /^-(?=[\s_},;\]/]|$|\([a-z]+\))/,
  341. // -space -, -; -] -/ -$ -state-of-aggregation
  342. '-9': /^-(?=[0-9])/,
  343. '- orbital overlap': /^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/,
  344. '-': /^-/,
  345. 'pm-operator': /^(?:\\pm|\$\\pm\$|\+-|\+\/-)/,
  346. 'operator': /^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/,
  347. 'arrowUpDown': /^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/,
  348. '\\bond{(...)}': function bond(input) {
  349. return mhchemParser.patterns.findObserveGroups(input, "\\bond{", "", "", "}");
  350. },
  351. '->': /^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/,
  352. 'CMT': /^[CMT](?=\[)/,
  353. '[(...)]': function _(input) {
  354. return mhchemParser.patterns.findObserveGroups(input, "[", "", "", "]");
  355. },
  356. '1st-level escape': /^(&|\\\\|\\hline)\s*/,
  357. '\\,': /^(?:\\[,\ ;:])/,
  358. // \\x - but output no space before
  359. '\\x{}{}': function x(input) {
  360. return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true);
  361. },
  362. '\\x{}': function x(input) {
  363. return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", "");
  364. },
  365. '\\ca': /^\\ca(?:\s+|(?![a-zA-Z]))/,
  366. '\\x': /^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/,
  367. 'orbital': /^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/,
  368. // only those with numbers in front, because the others will be formatted correctly anyway
  369. 'others': /^[\/~|]/,
  370. '\\frac{(...)}': function frac(input) {
  371. return mhchemParser.patterns.findObserveGroups(input, "\\frac{", "", "", "}", "{", "", "", "}");
  372. },
  373. '\\overset{(...)}': function overset(input) {
  374. return mhchemParser.patterns.findObserveGroups(input, "\\overset{", "", "", "}", "{", "", "", "}");
  375. },
  376. '\\underset{(...)}': function underset(input) {
  377. return mhchemParser.patterns.findObserveGroups(input, "\\underset{", "", "", "}", "{", "", "", "}");
  378. },
  379. '\\underbrace{(...)}': function underbrace(input) {
  380. return mhchemParser.patterns.findObserveGroups(input, "\\underbrace{", "", "", "}_", "{", "", "", "}");
  381. },
  382. '\\color{(...)}0': function color0(input) {
  383. return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}");
  384. },
  385. '\\color{(...)}{(...)}1': function color1(input) {
  386. return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}", "{", "", "", "}");
  387. },
  388. '\\color(...){(...)}2': function color2(input) {
  389. return mhchemParser.patterns.findObserveGroups(input, "\\color", "\\", "", /^(?=\{)/, "{", "", "", "}");
  390. },
  391. '\\ce{(...)}': function ce(input) {
  392. return mhchemParser.patterns.findObserveGroups(input, "\\ce{", "", "", "}");
  393. },
  394. 'oxidation$': /^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,
  395. 'd-oxidation$': /^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,
  396. // 0 could be oxidation or charge
  397. 'roman numeral': /^[IVX]+/,
  398. '1/2$': /^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/,
  399. 'amount': function amount(input) {
  400. var match;
  401. // e.g. 2, 0.5, 1/2, -2, n/2, +; $a$ could be added later in parsing
  402. 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))/);
  403. if (match) {
  404. return {
  405. match_: match[0],
  406. remainder: input.substr(match[0].length)
  407. };
  408. }
  409. var a = mhchemParser.patterns.findObserveGroups(input, "", "$", "$", "");
  410. if (a) {
  411. // e.g. $2n-1$, $-$
  412. match = a.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/);
  413. if (match) {
  414. return {
  415. match_: match[0],
  416. remainder: input.substr(match[0].length)
  417. };
  418. }
  419. }
  420. return null;
  421. },
  422. 'amount2': function amount2(input) {
  423. return this['amount'](input);
  424. },
  425. '(KV letters),': /^(?:[A-Z][a-z]{0,2}|i)(?=,)/,
  426. 'formula$': function formula$(input) {
  427. if (input.match(/^\([a-z]+\)$/)) {
  428. return null;
  429. } // state of aggregation = no formula
  430. var match = input.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/);
  431. if (match) {
  432. return {
  433. match_: match[0],
  434. remainder: input.substr(match[0].length)
  435. };
  436. }
  437. return null;
  438. },
  439. 'uprightEntities': /^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/,
  440. '/': /^\s*(\/)\s*/,
  441. '//': /^\s*(\/\/)\s*/,
  442. '*': /^\s*[*.]\s*/
  443. },
  444. findObserveGroups: function findObserveGroups(input, begExcl, begIncl, endIncl, endExcl, beg2Excl, beg2Incl, end2Incl, end2Excl, combine) {
  445. /** @type {{(input: string, pattern: string | RegExp): string | string[] | null;}} */
  446. var _match = function _match(input, pattern) {
  447. if (typeof pattern === "string") {
  448. if (input.indexOf(pattern) !== 0) {
  449. return null;
  450. }
  451. return pattern;
  452. } else {
  453. var match = input.match(pattern);
  454. if (!match) {
  455. return null;
  456. }
  457. return match[0];
  458. }
  459. };
  460. /** @type {{(input: string, i: number, endChars: string | RegExp): {endMatchBegin: number, endMatchEnd: number} | null;}} */
  461. var _findObserveGroups = function _findObserveGroups(input, i, endChars) {
  462. var braces = 0;
  463. while (i < input.length) {
  464. var a = input.charAt(i);
  465. var match = _match(input.substr(i), endChars);
  466. if (match !== null && braces === 0) {
  467. return {
  468. endMatchBegin: i,
  469. endMatchEnd: i + match.length
  470. };
  471. } else if (a === "{") {
  472. braces++;
  473. } else if (a === "}") {
  474. if (braces === 0) {
  475. throw ["ExtraCloseMissingOpen", "Extra close brace or missing open brace"];
  476. } else {
  477. braces--;
  478. }
  479. }
  480. i++;
  481. }
  482. if (braces > 0) {
  483. return null;
  484. }
  485. return null;
  486. };
  487. var match = _match(input, begExcl);
  488. if (match === null) {
  489. return null;
  490. }
  491. input = input.substr(match.length);
  492. match = _match(input, begIncl);
  493. if (match === null) {
  494. return null;
  495. }
  496. var e = _findObserveGroups(input, match.length, endIncl || endExcl);
  497. if (e === null) {
  498. return null;
  499. }
  500. var match1 = input.substring(0, endIncl ? e.endMatchEnd : e.endMatchBegin);
  501. if (!(beg2Excl || beg2Incl)) {
  502. return {
  503. match_: match1,
  504. remainder: input.substr(e.endMatchEnd)
  505. };
  506. } else {
  507. var group2 = this.findObserveGroups(input.substr(e.endMatchEnd), beg2Excl, beg2Incl, end2Incl, end2Excl);
  508. if (group2 === null) {
  509. return null;
  510. }
  511. /** @type {string[]} */
  512. var matchRet = [match1, group2.match_];
  513. return {
  514. match_: combine ? matchRet.join("") : matchRet,
  515. remainder: group2.remainder
  516. };
  517. }
  518. },
  519. //
  520. // Matching function
  521. // e.g. match("a", input) will look for the regexp called "a" and see if it matches
  522. // returns null or {match_:"a", remainder:"bc"}
  523. //
  524. match_: function match_(m, input) {
  525. var pattern = mhchemParser.patterns.patterns[m];
  526. if (pattern === undefined) {
  527. throw ["MhchemBugP", "mhchem bug P. Please report. (" + m + ")"]; // Trying to use non-existing pattern
  528. } else if (typeof pattern === "function") {
  529. return mhchemParser.patterns.patterns[m](input); // cannot use cached var pattern here, because some pattern functions need this===mhchemParser
  530. } else {
  531. // RegExp
  532. var match = input.match(pattern);
  533. if (match) {
  534. var mm;
  535. if (match[2]) {
  536. mm = [match[1], match[2]];
  537. } else if (match[1]) {
  538. mm = match[1];
  539. } else {
  540. mm = match[0];
  541. }
  542. return {
  543. match_: mm,
  544. remainder: input.substr(match[0].length)
  545. };
  546. }
  547. return null;
  548. }
  549. }
  550. },
  551. //
  552. // Generic state machine actions
  553. //
  554. actions: {
  555. 'a=': function a(buffer, m) {
  556. buffer.a = (buffer.a || "") + m;
  557. },
  558. 'b=': function b(buffer, m) {
  559. buffer.b = (buffer.b || "") + m;
  560. },
  561. 'p=': function p(buffer, m) {
  562. buffer.p = (buffer.p || "") + m;
  563. },
  564. 'o=': function o(buffer, m) {
  565. buffer.o = (buffer.o || "") + m;
  566. },
  567. 'q=': function q(buffer, m) {
  568. buffer.q = (buffer.q || "") + m;
  569. },
  570. 'd=': function d(buffer, m) {
  571. buffer.d = (buffer.d || "") + m;
  572. },
  573. 'rm=': function rm(buffer, m) {
  574. buffer.rm = (buffer.rm || "") + m;
  575. },
  576. 'text=': function text(buffer, m) {
  577. buffer.text_ = (buffer.text_ || "") + m;
  578. },
  579. 'insert': function insert(buffer, m, a) {
  580. return {
  581. type_: a
  582. };
  583. },
  584. 'insert+p1': function insertP1(buffer, m, a) {
  585. return {
  586. type_: a,
  587. p1: m
  588. };
  589. },
  590. 'insert+p1+p2': function insertP1P2(buffer, m, a) {
  591. return {
  592. type_: a,
  593. p1: m[0],
  594. p2: m[1]
  595. };
  596. },
  597. 'copy': function copy(buffer, m) {
  598. return m;
  599. },
  600. 'rm': function rm(buffer, m) {
  601. return {
  602. type_: 'rm',
  603. p1: m || ""
  604. };
  605. },
  606. 'text': function text(buffer, m) {
  607. return mhchemParser.go(m, 'text');
  608. },
  609. '{text}': function text(buffer, m) {
  610. var ret = ["{"];
  611. mhchemParser.concatArray(ret, mhchemParser.go(m, 'text'));
  612. ret.push("}");
  613. return ret;
  614. },
  615. 'tex-math': function texMath(buffer, m) {
  616. return mhchemParser.go(m, 'tex-math');
  617. },
  618. 'tex-math tight': function texMath_tight(buffer, m) {
  619. return mhchemParser.go(m, 'tex-math tight');
  620. },
  621. 'bond': function bond(buffer, m, k) {
  622. return {
  623. type_: 'bond',
  624. kind_: k || m
  625. };
  626. },
  627. 'color0-output': function color0Output(buffer, m) {
  628. return {
  629. type_: 'color0',
  630. color: m[0]
  631. };
  632. },
  633. 'ce': function ce(buffer, m) {
  634. return mhchemParser.go(m);
  635. },
  636. '1/2': function _2(buffer, m) {
  637. /** @type {ParserOutput[]} */
  638. var ret = [];
  639. if (m.match(/^[+\-]/)) {
  640. ret.push(m.substr(0, 1));
  641. m = m.substr(1);
  642. }
  643. var n = m.match(/^([0-9]+|\$[a-z]\$|[a-z])\/([0-9]+)(\$[a-z]\$|[a-z])?$/);
  644. n[1] = n[1].replace(/\$/g, "");
  645. ret.push({
  646. type_: 'frac',
  647. p1: n[1],
  648. p2: n[2]
  649. });
  650. if (n[3]) {
  651. n[3] = n[3].replace(/\$/g, "");
  652. ret.push({
  653. type_: 'tex-math',
  654. p1: n[3]
  655. });
  656. }
  657. return ret;
  658. },
  659. '9,9': function _(buffer, m) {
  660. return mhchemParser.go(m, '9,9');
  661. }
  662. },
  663. //
  664. // createTransitions
  665. // convert { 'letter': { 'state': { action_: 'output' } } } to { 'state' => [ { pattern: 'letter', task: { action_: [{type_: 'output'}] } } ] }
  666. // with expansion of 'a|b' to 'a' and 'b' (at 2 places)
  667. //
  668. createTransitions: function createTransitions(o) {
  669. var pattern, state;
  670. /** @type {string[]} */
  671. var stateArray;
  672. var i;
  673. //
  674. // 1. Collect all states
  675. //
  676. /** @type {Transitions} */
  677. var transitions = {};
  678. for (pattern in o) {
  679. for (state in o[pattern]) {
  680. stateArray = state.split("|");
  681. o[pattern][state].stateArray = stateArray;
  682. for (i = 0; i < stateArray.length; i++) {
  683. transitions[stateArray[i]] = [];
  684. }
  685. }
  686. }
  687. //
  688. // 2. Fill states
  689. //
  690. for (pattern in o) {
  691. for (state in o[pattern]) {
  692. stateArray = o[pattern][state].stateArray || [];
  693. for (i = 0; i < stateArray.length; i++) {
  694. //
  695. // 2a. Normalize actions into array: 'text=' ==> [{type_:'text='}]
  696. // (Note to myself: Resolving the function here would be problematic. It would need .bind (for *this*) and currying (for *option*).)
  697. //
  698. /** @type {any} */
  699. var p = o[pattern][state];
  700. if (p.action_) {
  701. p.action_ = [].concat(p.action_);
  702. for (var k = 0; k < p.action_.length; k++) {
  703. if (typeof p.action_[k] === "string") {
  704. p.action_[k] = {
  705. type_: p.action_[k]
  706. };
  707. }
  708. }
  709. } else {
  710. p.action_ = [];
  711. }
  712. //
  713. // 2.b Multi-insert
  714. //
  715. var patternArray = pattern.split("|");
  716. for (var j = 0; j < patternArray.length; j++) {
  717. if (stateArray[i] === '*') {
  718. // insert into all
  719. for (var t in transitions) {
  720. transitions[t].push({
  721. pattern: patternArray[j],
  722. task: p
  723. });
  724. }
  725. } else {
  726. transitions[stateArray[i]].push({
  727. pattern: patternArray[j],
  728. task: p
  729. });
  730. }
  731. }
  732. }
  733. }
  734. }
  735. return transitions;
  736. },
  737. stateMachines: {}
  738. };
  739. //
  740. // Definition of state machines
  741. //
  742. mhchemParser.stateMachines = {
  743. //
  744. // \ce state machines
  745. //
  746. //#region ce
  747. 'ce': {
  748. // main parser
  749. transitions: mhchemParser.createTransitions({
  750. 'empty': {
  751. '*': {
  752. action_: 'output'
  753. }
  754. },
  755. 'else': {
  756. '0|1|2': {
  757. action_: 'beginsWithBond=false',
  758. revisit: true,
  759. toContinue: true
  760. }
  761. },
  762. 'oxidation$': {
  763. '0': {
  764. action_: 'oxidation-output'
  765. }
  766. },
  767. 'CMT': {
  768. 'r': {
  769. action_: 'rdt=',
  770. nextState: 'rt'
  771. },
  772. 'rd': {
  773. action_: 'rqt=',
  774. nextState: 'rdt'
  775. }
  776. },
  777. 'arrowUpDown': {
  778. '0|1|2|as': {
  779. action_: ['sb=false', 'output', 'operator'],
  780. nextState: '1'
  781. }
  782. },
  783. 'uprightEntities': {
  784. '0|1|2': {
  785. action_: ['o=', 'output'],
  786. nextState: '1'
  787. }
  788. },
  789. 'orbital': {
  790. '0|1|2|3': {
  791. action_: 'o=',
  792. nextState: 'o'
  793. }
  794. },
  795. '->': {
  796. '0|1|2|3': {
  797. action_: 'r=',
  798. nextState: 'r'
  799. },
  800. 'a|as': {
  801. action_: ['output', 'r='],
  802. nextState: 'r'
  803. },
  804. '*': {
  805. action_: ['output', 'r='],
  806. nextState: 'r'
  807. }
  808. },
  809. '+': {
  810. 'o': {
  811. action_: 'd= kv',
  812. nextState: 'd'
  813. },
  814. 'd|D': {
  815. action_: 'd=',
  816. nextState: 'd'
  817. },
  818. 'q': {
  819. action_: 'd=',
  820. nextState: 'qd'
  821. },
  822. 'qd|qD': {
  823. action_: 'd=',
  824. nextState: 'qd'
  825. },
  826. 'dq': {
  827. action_: ['output', 'd='],
  828. nextState: 'd'
  829. },
  830. '3': {
  831. action_: ['sb=false', 'output', 'operator'],
  832. nextState: '0'
  833. }
  834. },
  835. 'amount': {
  836. '0|2': {
  837. action_: 'a=',
  838. nextState: 'a'
  839. }
  840. },
  841. 'pm-operator': {
  842. '0|1|2|a|as': {
  843. action_: ['sb=false', 'output', {
  844. type_: 'operator',
  845. option: '\\pm'
  846. }],
  847. nextState: '0'
  848. }
  849. },
  850. 'operator': {
  851. '0|1|2|a|as': {
  852. action_: ['sb=false', 'output', 'operator'],
  853. nextState: '0'
  854. }
  855. },
  856. '-$': {
  857. 'o|q': {
  858. action_: ['charge or bond', 'output'],
  859. nextState: 'qd'
  860. },
  861. 'd': {
  862. action_: 'd=',
  863. nextState: 'd'
  864. },
  865. 'D': {
  866. action_: ['output', {
  867. type_: 'bond',
  868. option: "-"
  869. }],
  870. nextState: '3'
  871. },
  872. 'q': {
  873. action_: 'd=',
  874. nextState: 'qd'
  875. },
  876. 'qd': {
  877. action_: 'd=',
  878. nextState: 'qd'
  879. },
  880. 'qD|dq': {
  881. action_: ['output', {
  882. type_: 'bond',
  883. option: "-"
  884. }],
  885. nextState: '3'
  886. }
  887. },
  888. '-9': {
  889. '3|o': {
  890. action_: ['output', {
  891. type_: 'insert',
  892. option: 'hyphen'
  893. }],
  894. nextState: '3'
  895. }
  896. },
  897. '- orbital overlap': {
  898. 'o': {
  899. action_: ['output', {
  900. type_: 'insert',
  901. option: 'hyphen'
  902. }],
  903. nextState: '2'
  904. },
  905. 'd': {
  906. action_: ['output', {
  907. type_: 'insert',
  908. option: 'hyphen'
  909. }],
  910. nextState: '2'
  911. }
  912. },
  913. '-': {
  914. '0|1|2': {
  915. action_: [{
  916. type_: 'output',
  917. option: 1
  918. }, 'beginsWithBond=true', {
  919. type_: 'bond',
  920. option: "-"
  921. }],
  922. nextState: '3'
  923. },
  924. '3': {
  925. action_: {
  926. type_: 'bond',
  927. option: "-"
  928. }
  929. },
  930. 'a': {
  931. action_: ['output', {
  932. type_: 'insert',
  933. option: 'hyphen'
  934. }],
  935. nextState: '2'
  936. },
  937. 'as': {
  938. action_: [{
  939. type_: 'output',
  940. option: 2
  941. }, {
  942. type_: 'bond',
  943. option: "-"
  944. }],
  945. nextState: '3'
  946. },
  947. 'b': {
  948. action_: 'b='
  949. },
  950. 'o': {
  951. action_: {
  952. type_: '- after o/d',
  953. option: false
  954. },
  955. nextState: '2'
  956. },
  957. 'q': {
  958. action_: {
  959. type_: '- after o/d',
  960. option: false
  961. },
  962. nextState: '2'
  963. },
  964. 'd|qd|dq': {
  965. action_: {
  966. type_: '- after o/d',
  967. option: true
  968. },
  969. nextState: '2'
  970. },
  971. 'D|qD|p': {
  972. action_: ['output', {
  973. type_: 'bond',
  974. option: "-"
  975. }],
  976. nextState: '3'
  977. }
  978. },
  979. 'amount2': {
  980. '1|3': {
  981. action_: 'a=',
  982. nextState: 'a'
  983. }
  984. },
  985. 'letters': {
  986. '0|1|2|3|a|as|b|p|bp|o': {
  987. action_: 'o=',
  988. nextState: 'o'
  989. },
  990. 'q|dq': {
  991. action_: ['output', 'o='],
  992. nextState: 'o'
  993. },
  994. 'd|D|qd|qD': {
  995. action_: 'o after d',
  996. nextState: 'o'
  997. }
  998. },
  999. 'digits': {
  1000. 'o': {
  1001. action_: 'q=',
  1002. nextState: 'q'
  1003. },
  1004. 'd|D': {
  1005. action_: 'q=',
  1006. nextState: 'dq'
  1007. },
  1008. 'q': {
  1009. action_: ['output', 'o='],
  1010. nextState: 'o'
  1011. },
  1012. 'a': {
  1013. action_: 'o=',
  1014. nextState: 'o'
  1015. }
  1016. },
  1017. 'space A': {
  1018. 'b|p|bp': {}
  1019. },
  1020. 'space': {
  1021. 'a': {
  1022. nextState: 'as'
  1023. },
  1024. '0': {
  1025. action_: 'sb=false'
  1026. },
  1027. '1|2': {
  1028. action_: 'sb=true'
  1029. },
  1030. 'r|rt|rd|rdt|rdq': {
  1031. action_: 'output',
  1032. nextState: '0'
  1033. },
  1034. '*': {
  1035. action_: ['output', 'sb=true'],
  1036. nextState: '1'
  1037. }
  1038. },
  1039. '1st-level escape': {
  1040. '1|2': {
  1041. action_: ['output', {
  1042. type_: 'insert+p1',
  1043. option: '1st-level escape'
  1044. }]
  1045. },
  1046. '*': {
  1047. action_: ['output', {
  1048. type_: 'insert+p1',
  1049. option: '1st-level escape'
  1050. }],
  1051. nextState: '0'
  1052. }
  1053. },
  1054. '[(...)]': {
  1055. 'r|rt': {
  1056. action_: 'rd=',
  1057. nextState: 'rd'
  1058. },
  1059. 'rd|rdt': {
  1060. action_: 'rq=',
  1061. nextState: 'rdq'
  1062. }
  1063. },
  1064. '...': {
  1065. 'o|d|D|dq|qd|qD': {
  1066. action_: ['output', {
  1067. type_: 'bond',
  1068. option: "..."
  1069. }],
  1070. nextState: '3'
  1071. },
  1072. '*': {
  1073. action_: [{
  1074. type_: 'output',
  1075. option: 1
  1076. }, {
  1077. type_: 'insert',
  1078. option: 'ellipsis'
  1079. }],
  1080. nextState: '1'
  1081. }
  1082. },
  1083. '. |* ': {
  1084. '*': {
  1085. action_: ['output', {
  1086. type_: 'insert',
  1087. option: 'addition compound'
  1088. }],
  1089. nextState: '1'
  1090. }
  1091. },
  1092. 'state of aggregation $': {
  1093. '*': {
  1094. action_: ['output', 'state of aggregation'],
  1095. nextState: '1'
  1096. }
  1097. },
  1098. '{[(': {
  1099. 'a|as|o': {
  1100. action_: ['o=', 'output', 'parenthesisLevel++'],
  1101. nextState: '2'
  1102. },
  1103. '0|1|2|3': {
  1104. action_: ['o=', 'output', 'parenthesisLevel++'],
  1105. nextState: '2'
  1106. },
  1107. '*': {
  1108. action_: ['output', 'o=', 'output', 'parenthesisLevel++'],
  1109. nextState: '2'
  1110. }
  1111. },
  1112. ')]}': {
  1113. '0|1|2|3|b|p|bp|o': {
  1114. action_: ['o=', 'parenthesisLevel--'],
  1115. nextState: 'o'
  1116. },
  1117. 'a|as|d|D|q|qd|qD|dq': {
  1118. action_: ['output', 'o=', 'parenthesisLevel--'],
  1119. nextState: 'o'
  1120. }
  1121. },
  1122. ', ': {
  1123. '*': {
  1124. action_: ['output', 'comma'],
  1125. nextState: '0'
  1126. }
  1127. },
  1128. '^_': {
  1129. // ^ and _ without a sensible argument
  1130. '*': {}
  1131. },
  1132. '^{(...)}|^($...$)': {
  1133. '0|1|2|as': {
  1134. action_: 'b=',
  1135. nextState: 'b'
  1136. },
  1137. 'p': {
  1138. action_: 'b=',
  1139. nextState: 'bp'
  1140. },
  1141. '3|o': {
  1142. action_: 'd= kv',
  1143. nextState: 'D'
  1144. },
  1145. 'q': {
  1146. action_: 'd=',
  1147. nextState: 'qD'
  1148. },
  1149. 'd|D|qd|qD|dq': {
  1150. action_: ['output', 'd='],
  1151. nextState: 'D'
  1152. }
  1153. },
  1154. '^a|^\\x{}{}|^\\x{}|^\\x|\'': {
  1155. '0|1|2|as': {
  1156. action_: 'b=',
  1157. nextState: 'b'
  1158. },
  1159. 'p': {
  1160. action_: 'b=',
  1161. nextState: 'bp'
  1162. },
  1163. '3|o': {
  1164. action_: 'd= kv',
  1165. nextState: 'd'
  1166. },
  1167. 'q': {
  1168. action_: 'd=',
  1169. nextState: 'qd'
  1170. },
  1171. 'd|qd|D|qD': {
  1172. action_: 'd='
  1173. },
  1174. 'dq': {
  1175. action_: ['output', 'd='],
  1176. nextState: 'd'
  1177. }
  1178. },
  1179. '_{(state of aggregation)}$': {
  1180. 'd|D|q|qd|qD|dq': {
  1181. action_: ['output', 'q='],
  1182. nextState: 'q'
  1183. }
  1184. },
  1185. '_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x': {
  1186. '0|1|2|as': {
  1187. action_: 'p=',
  1188. nextState: 'p'
  1189. },
  1190. 'b': {
  1191. action_: 'p=',
  1192. nextState: 'bp'
  1193. },
  1194. '3|o': {
  1195. action_: 'q=',
  1196. nextState: 'q'
  1197. },
  1198. 'd|D': {
  1199. action_: 'q=',
  1200. nextState: 'dq'
  1201. },
  1202. 'q|qd|qD|dq': {
  1203. action_: ['output', 'q='],
  1204. nextState: 'q'
  1205. }
  1206. },
  1207. '=<>': {
  1208. '0|1|2|3|a|as|o|q|d|D|qd|qD|dq': {
  1209. action_: [{
  1210. type_: 'output',
  1211. option: 2
  1212. }, 'bond'],
  1213. nextState: '3'
  1214. }
  1215. },
  1216. '#': {
  1217. '0|1|2|3|a|as|o': {
  1218. action_: [{
  1219. type_: 'output',
  1220. option: 2
  1221. }, {
  1222. type_: 'bond',
  1223. option: "#"
  1224. }],
  1225. nextState: '3'
  1226. }
  1227. },
  1228. '{}': {
  1229. '*': {
  1230. action_: {
  1231. type_: 'output',
  1232. option: 1
  1233. },
  1234. nextState: '1'
  1235. }
  1236. },
  1237. '{...}': {
  1238. '0|1|2|3|a|as|b|p|bp': {
  1239. action_: 'o=',
  1240. nextState: 'o'
  1241. },
  1242. 'o|d|D|q|qd|qD|dq': {
  1243. action_: ['output', 'o='],
  1244. nextState: 'o'
  1245. }
  1246. },
  1247. '$...$': {
  1248. 'a': {
  1249. action_: 'a='
  1250. },
  1251. // 2$n$
  1252. '0|1|2|3|as|b|p|bp|o': {
  1253. action_: 'o=',
  1254. nextState: 'o'
  1255. },
  1256. // not 'amount'
  1257. 'as|o': {
  1258. action_: 'o='
  1259. },
  1260. 'q|d|D|qd|qD|dq': {
  1261. action_: ['output', 'o='],
  1262. nextState: 'o'
  1263. }
  1264. },
  1265. '\\bond{(...)}': {
  1266. '*': {
  1267. action_: [{
  1268. type_: 'output',
  1269. option: 2
  1270. }, 'bond'],
  1271. nextState: "3"
  1272. }
  1273. },
  1274. '\\frac{(...)}': {
  1275. '*': {
  1276. action_: [{
  1277. type_: 'output',
  1278. option: 1
  1279. }, 'frac-output'],
  1280. nextState: '3'
  1281. }
  1282. },
  1283. '\\overset{(...)}': {
  1284. '*': {
  1285. action_: [{
  1286. type_: 'output',
  1287. option: 2
  1288. }, 'overset-output'],
  1289. nextState: '3'
  1290. }
  1291. },
  1292. '\\underset{(...)}': {
  1293. '*': {
  1294. action_: [{
  1295. type_: 'output',
  1296. option: 2
  1297. }, 'underset-output'],
  1298. nextState: '3'
  1299. }
  1300. },
  1301. '\\underbrace{(...)}': {
  1302. '*': {
  1303. action_: [{
  1304. type_: 'output',
  1305. option: 2
  1306. }, 'underbrace-output'],
  1307. nextState: '3'
  1308. }
  1309. },
  1310. '\\color{(...)}{(...)}1|\\color(...){(...)}2': {
  1311. '*': {
  1312. action_: [{
  1313. type_: 'output',
  1314. option: 2
  1315. }, 'color-output'],
  1316. nextState: '3'
  1317. }
  1318. },
  1319. '\\color{(...)}0': {
  1320. '*': {
  1321. action_: [{
  1322. type_: 'output',
  1323. option: 2
  1324. }, 'color0-output']
  1325. }
  1326. },
  1327. '\\ce{(...)}': {
  1328. '*': {
  1329. action_: [{
  1330. type_: 'output',
  1331. option: 2
  1332. }, 'ce'],
  1333. nextState: '3'
  1334. }
  1335. },
  1336. '\\,': {
  1337. '*': {
  1338. action_: [{
  1339. type_: 'output',
  1340. option: 1
  1341. }, 'copy'],
  1342. nextState: '1'
  1343. }
  1344. },
  1345. '\\x{}{}|\\x{}|\\x': {
  1346. '0|1|2|3|a|as|b|p|bp|o|c0': {
  1347. action_: ['o=', 'output'],
  1348. nextState: '3'
  1349. },
  1350. '*': {
  1351. action_: ['output', 'o=', 'output'],
  1352. nextState: '3'
  1353. }
  1354. },
  1355. 'others': {
  1356. '*': {
  1357. action_: [{
  1358. type_: 'output',
  1359. option: 1
  1360. }, 'copy'],
  1361. nextState: '3'
  1362. }
  1363. },
  1364. 'else2': {
  1365. 'a': {
  1366. action_: 'a to o',
  1367. nextState: 'o',
  1368. revisit: true
  1369. },
  1370. 'as': {
  1371. action_: ['output', 'sb=true'],
  1372. nextState: '1',
  1373. revisit: true
  1374. },
  1375. 'r|rt|rd|rdt|rdq': {
  1376. action_: ['output'],
  1377. nextState: '0',
  1378. revisit: true
  1379. },
  1380. '*': {
  1381. action_: ['output', 'copy'],
  1382. nextState: '3'
  1383. }
  1384. }
  1385. }),
  1386. actions: {
  1387. 'o after d': function o_after_d(buffer, m) {
  1388. var ret;
  1389. if ((buffer.d || "").match(/^[0-9]+$/)) {
  1390. var tmp = buffer.d;
  1391. buffer.d = undefined;
  1392. ret = this['output'](buffer);
  1393. buffer.b = tmp;
  1394. } else {
  1395. ret = this['output'](buffer);
  1396. }
  1397. mhchemParser.actions['o='](buffer, m);
  1398. return ret;
  1399. },
  1400. 'd= kv': function d_kv(buffer, m) {
  1401. buffer.d = m;
  1402. buffer.dType = 'kv';
  1403. },
  1404. 'charge or bond': function charge_or_bond(buffer, m) {
  1405. if (buffer['beginsWithBond']) {
  1406. /** @type {ParserOutput[]} */
  1407. var ret = [];
  1408. mhchemParser.concatArray(ret, this['output'](buffer));
  1409. mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-"));
  1410. return ret;
  1411. } else {
  1412. buffer.d = m;
  1413. }
  1414. },
  1415. '- after o/d': function _after_o_d(buffer, m, isAfterD) {
  1416. var c1 = mhchemParser.patterns.match_('orbital', buffer.o || "");
  1417. var c2 = mhchemParser.patterns.match_('one lowercase greek letter $', buffer.o || "");
  1418. var c3 = mhchemParser.patterns.match_('one lowercase latin letter $', buffer.o || "");
  1419. var c4 = mhchemParser.patterns.match_('$one lowercase latin letter$ $', buffer.o || "");
  1420. var hyphenFollows = m === "-" && (c1 && c1.remainder === "" || c2 || c3 || c4);
  1421. if (hyphenFollows && !buffer.a && !buffer.b && !buffer.p && !buffer.d && !buffer.q && !c1 && c3) {
  1422. buffer.o = '$' + buffer.o + '$';
  1423. }
  1424. /** @type {ParserOutput[]} */
  1425. var ret = [];
  1426. if (hyphenFollows) {
  1427. mhchemParser.concatArray(ret, this['output'](buffer));
  1428. ret.push({
  1429. type_: 'hyphen'
  1430. });
  1431. } else {
  1432. c1 = mhchemParser.patterns.match_('digits', buffer.d || "");
  1433. if (isAfterD && c1 && c1.remainder === '') {
  1434. mhchemParser.concatArray(ret, mhchemParser.actions['d='](buffer, m));
  1435. mhchemParser.concatArray(ret, this['output'](buffer));
  1436. } else {
  1437. mhchemParser.concatArray(ret, this['output'](buffer));
  1438. mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-"));
  1439. }
  1440. }
  1441. return ret;
  1442. },
  1443. 'a to o': function a_to_o(buffer) {
  1444. buffer.o = buffer.a;
  1445. buffer.a = undefined;
  1446. },
  1447. 'sb=true': function sbTrue(buffer) {
  1448. buffer.sb = true;
  1449. },
  1450. 'sb=false': function sbFalse(buffer) {
  1451. buffer.sb = false;
  1452. },
  1453. 'beginsWithBond=true': function beginsWithBondTrue(buffer) {
  1454. buffer['beginsWithBond'] = true;
  1455. },
  1456. 'beginsWithBond=false': function beginsWithBondFalse(buffer) {
  1457. buffer['beginsWithBond'] = false;
  1458. },
  1459. 'parenthesisLevel++': function parenthesisLevel(buffer) {
  1460. buffer['parenthesisLevel']++;
  1461. },
  1462. 'parenthesisLevel--': function parenthesisLevel(buffer) {
  1463. buffer['parenthesisLevel']--;
  1464. },
  1465. 'state of aggregation': function state_of_aggregation(buffer, m) {
  1466. return {
  1467. type_: 'state of aggregation',
  1468. p1: mhchemParser.go(m, 'o')
  1469. };
  1470. },
  1471. 'comma': function comma(buffer, m) {
  1472. var a = m.replace(/\s*$/, '');
  1473. var withSpace = a !== m;
  1474. if (withSpace && buffer['parenthesisLevel'] === 0) {
  1475. return {
  1476. type_: 'comma enumeration L',
  1477. p1: a
  1478. };
  1479. } else {
  1480. return {
  1481. type_: 'comma enumeration M',
  1482. p1: a
  1483. };
  1484. }
  1485. },
  1486. 'output': function output(buffer, m, entityFollows) {
  1487. // entityFollows:
  1488. // undefined = if we have nothing else to output, also ignore the just read space (buffer.sb)
  1489. // 1 = an entity follows, never omit the space if there was one just read before (can only apply to state 1)
  1490. // 2 = 1 + the entity can have an amount, so output a\, instead of converting it to o (can only apply to states a|as)
  1491. /** @type {ParserOutput | ParserOutput[]} */
  1492. var ret;
  1493. if (!buffer.r) {
  1494. ret = [];
  1495. if (!buffer.a && !buffer.b && !buffer.p && !buffer.o && !buffer.q && !buffer.d && !entityFollows) ; else {
  1496. if (buffer.sb) {
  1497. ret.push({
  1498. type_: 'entitySkip'
  1499. });
  1500. }
  1501. if (!buffer.o && !buffer.q && !buffer.d && !buffer.b && !buffer.p && entityFollows !== 2) {
  1502. buffer.o = buffer.a;
  1503. buffer.a = undefined;
  1504. } else if (!buffer.o && !buffer.q && !buffer.d && (buffer.b || buffer.p)) {
  1505. buffer.o = buffer.a;
  1506. buffer.d = buffer.b;
  1507. buffer.q = buffer.p;
  1508. buffer.a = buffer.b = buffer.p = undefined;
  1509. } else {
  1510. if (buffer.o && buffer.dType === 'kv' && mhchemParser.patterns.match_('d-oxidation$', buffer.d || "")) {
  1511. buffer.dType = 'oxidation';
  1512. } else if (buffer.o && buffer.dType === 'kv' && !buffer.q) {
  1513. buffer.dType = undefined;
  1514. }
  1515. }
  1516. ret.push({
  1517. type_: 'chemfive',
  1518. a: mhchemParser.go(buffer.a, 'a'),
  1519. b: mhchemParser.go(buffer.b, 'bd'),
  1520. p: mhchemParser.go(buffer.p, 'pq'),
  1521. o: mhchemParser.go(buffer.o, 'o'),
  1522. q: mhchemParser.go(buffer.q, 'pq'),
  1523. d: mhchemParser.go(buffer.d, buffer.dType === 'oxidation' ? 'oxidation' : 'bd'),
  1524. dType: buffer.dType
  1525. });
  1526. }
  1527. } else {
  1528. // r
  1529. /** @type {ParserOutput[]} */
  1530. var rd;
  1531. if (buffer.rdt === 'M') {
  1532. rd = mhchemParser.go(buffer.rd, 'tex-math');
  1533. } else if (buffer.rdt === 'T') {
  1534. rd = [{
  1535. type_: 'text',
  1536. p1: buffer.rd || ""
  1537. }];
  1538. } else {
  1539. rd = mhchemParser.go(buffer.rd);
  1540. }
  1541. /** @type {ParserOutput[]} */
  1542. var rq;
  1543. if (buffer.rqt === 'M') {
  1544. rq = mhchemParser.go(buffer.rq, 'tex-math');
  1545. } else if (buffer.rqt === 'T') {
  1546. rq = [{
  1547. type_: 'text',
  1548. p1: buffer.rq || ""
  1549. }];
  1550. } else {
  1551. rq = mhchemParser.go(buffer.rq);
  1552. }
  1553. ret = {
  1554. type_: 'arrow',
  1555. r: buffer.r,
  1556. rd: rd,
  1557. rq: rq
  1558. };
  1559. }
  1560. for (var p in buffer) {
  1561. if (p !== 'parenthesisLevel' && p !== 'beginsWithBond') {
  1562. delete buffer[p];
  1563. }
  1564. }
  1565. return ret;
  1566. },
  1567. 'oxidation-output': function oxidationOutput(buffer, m) {
  1568. var ret = ["{"];
  1569. mhchemParser.concatArray(ret, mhchemParser.go(m, 'oxidation'));
  1570. ret.push("}");
  1571. return ret;
  1572. },
  1573. 'frac-output': function fracOutput(buffer, m) {
  1574. return {
  1575. type_: 'frac-ce',
  1576. p1: mhchemParser.go(m[0]),
  1577. p2: mhchemParser.go(m[1])
  1578. };
  1579. },
  1580. 'overset-output': function oversetOutput(buffer, m) {
  1581. return {
  1582. type_: 'overset',
  1583. p1: mhchemParser.go(m[0]),
  1584. p2: mhchemParser.go(m[1])
  1585. };
  1586. },
  1587. 'underset-output': function undersetOutput(buffer, m) {
  1588. return {
  1589. type_: 'underset',
  1590. p1: mhchemParser.go(m[0]),
  1591. p2: mhchemParser.go(m[1])
  1592. };
  1593. },
  1594. 'underbrace-output': function underbraceOutput(buffer, m) {
  1595. return {
  1596. type_: 'underbrace',
  1597. p1: mhchemParser.go(m[0]),
  1598. p2: mhchemParser.go(m[1])
  1599. };
  1600. },
  1601. 'color-output': function colorOutput(buffer, m) {
  1602. return {
  1603. type_: 'color',
  1604. color1: m[0],
  1605. color2: mhchemParser.go(m[1])
  1606. };
  1607. },
  1608. 'r=': function r(buffer, m) {
  1609. buffer.r = m;
  1610. },
  1611. 'rdt=': function rdt(buffer, m) {
  1612. buffer.rdt = m;
  1613. },
  1614. 'rd=': function rd(buffer, m) {
  1615. buffer.rd = m;
  1616. },
  1617. 'rqt=': function rqt(buffer, m) {
  1618. buffer.rqt = m;
  1619. },
  1620. 'rq=': function rq(buffer, m) {
  1621. buffer.rq = m;
  1622. },
  1623. 'operator': function operator(buffer, m, p1) {
  1624. return {
  1625. type_: 'operator',
  1626. kind_: p1 || m
  1627. };
  1628. }
  1629. }
  1630. },
  1631. 'a': {
  1632. transitions: mhchemParser.createTransitions({
  1633. 'empty': {
  1634. '*': {}
  1635. },
  1636. '1/2$': {
  1637. '0': {
  1638. action_: '1/2'
  1639. }
  1640. },
  1641. 'else': {
  1642. '0': {
  1643. nextState: '1',
  1644. revisit: true
  1645. }
  1646. },
  1647. '$(...)$': {
  1648. '*': {
  1649. action_: 'tex-math tight',
  1650. nextState: '1'
  1651. }
  1652. },
  1653. ',': {
  1654. '*': {
  1655. action_: {
  1656. type_: 'insert',
  1657. option: 'commaDecimal'
  1658. }
  1659. }
  1660. },
  1661. 'else2': {
  1662. '*': {
  1663. action_: 'copy'
  1664. }
  1665. }
  1666. }),
  1667. actions: {}
  1668. },
  1669. 'o': {
  1670. transitions: mhchemParser.createTransitions({
  1671. 'empty': {
  1672. '*': {}
  1673. },
  1674. '1/2$': {
  1675. '0': {
  1676. action_: '1/2'
  1677. }
  1678. },
  1679. 'else': {
  1680. '0': {
  1681. nextState: '1',
  1682. revisit: true
  1683. }
  1684. },
  1685. 'letters': {
  1686. '*': {
  1687. action_: 'rm'
  1688. }
  1689. },
  1690. '\\ca': {
  1691. '*': {
  1692. action_: {
  1693. type_: 'insert',
  1694. option: 'circa'
  1695. }
  1696. }
  1697. },
  1698. '\\x{}{}|\\x{}|\\x': {
  1699. '*': {
  1700. action_: 'copy'
  1701. }
  1702. },
  1703. '${(...)}$|$(...)$': {
  1704. '*': {
  1705. action_: 'tex-math'
  1706. }
  1707. },
  1708. '{(...)}': {
  1709. '*': {
  1710. action_: '{text}'
  1711. }
  1712. },
  1713. 'else2': {
  1714. '*': {
  1715. action_: 'copy'
  1716. }
  1717. }
  1718. }),
  1719. actions: {}
  1720. },
  1721. 'text': {
  1722. transitions: mhchemParser.createTransitions({
  1723. 'empty': {
  1724. '*': {
  1725. action_: 'output'
  1726. }
  1727. },
  1728. '{...}': {
  1729. '*': {
  1730. action_: 'text='
  1731. }
  1732. },
  1733. '${(...)}$|$(...)$': {
  1734. '*': {
  1735. action_: 'tex-math'
  1736. }
  1737. },
  1738. '\\greek': {
  1739. '*': {
  1740. action_: ['output', 'rm']
  1741. }
  1742. },
  1743. '\\,|\\x{}{}|\\x{}|\\x': {
  1744. '*': {
  1745. action_: ['output', 'copy']
  1746. }
  1747. },
  1748. 'else': {
  1749. '*': {
  1750. action_: 'text='
  1751. }
  1752. }
  1753. }),
  1754. actions: {
  1755. 'output': function output(buffer) {
  1756. if (buffer.text_) {
  1757. /** @type {ParserOutput} */
  1758. var ret = {
  1759. type_: 'text',
  1760. p1: buffer.text_
  1761. };
  1762. for (var p in buffer) {
  1763. delete buffer[p];
  1764. }
  1765. return ret;
  1766. }
  1767. }
  1768. }
  1769. },
  1770. 'pq': {
  1771. transitions: mhchemParser.createTransitions({
  1772. 'empty': {
  1773. '*': {}
  1774. },
  1775. 'state of aggregation $': {
  1776. '*': {
  1777. action_: 'state of aggregation'
  1778. }
  1779. },
  1780. 'i$': {
  1781. '0': {
  1782. nextState: '!f',
  1783. revisit: true
  1784. }
  1785. },
  1786. '(KV letters),': {
  1787. '0': {
  1788. action_: 'rm',
  1789. nextState: '0'
  1790. }
  1791. },
  1792. 'formula$': {
  1793. '0': {
  1794. nextState: 'f',
  1795. revisit: true
  1796. }
  1797. },
  1798. '1/2$': {
  1799. '0': {
  1800. action_: '1/2'
  1801. }
  1802. },
  1803. 'else': {
  1804. '0': {
  1805. nextState: '!f',
  1806. revisit: true
  1807. }
  1808. },
  1809. '${(...)}$|$(...)$': {
  1810. '*': {
  1811. action_: 'tex-math'
  1812. }
  1813. },
  1814. '{(...)}': {
  1815. '*': {
  1816. action_: 'text'
  1817. }
  1818. },
  1819. 'a-z': {
  1820. 'f': {
  1821. action_: 'tex-math'
  1822. }
  1823. },
  1824. 'letters': {
  1825. '*': {
  1826. action_: 'rm'
  1827. }
  1828. },
  1829. '-9.,9': {
  1830. '*': {
  1831. action_: '9,9'
  1832. }
  1833. },
  1834. ',': {
  1835. '*': {
  1836. action_: {
  1837. type_: 'insert+p1',
  1838. option: 'comma enumeration S'
  1839. }
  1840. }
  1841. },
  1842. '\\color{(...)}{(...)}1|\\color(...){(...)}2': {
  1843. '*': {
  1844. action_: 'color-output'
  1845. }
  1846. },
  1847. '\\color{(...)}0': {
  1848. '*': {
  1849. action_: 'color0-output'
  1850. }
  1851. },
  1852. '\\ce{(...)}': {
  1853. '*': {
  1854. action_: 'ce'
  1855. }
  1856. },
  1857. '\\,|\\x{}{}|\\x{}|\\x': {
  1858. '*': {
  1859. action_: 'copy'
  1860. }
  1861. },
  1862. 'else2': {
  1863. '*': {
  1864. action_: 'copy'
  1865. }
  1866. }
  1867. }),
  1868. actions: {
  1869. 'state of aggregation': function state_of_aggregation(buffer, m) {
  1870. return {
  1871. type_: 'state of aggregation subscript',
  1872. p1: mhchemParser.go(m, 'o')
  1873. };
  1874. },
  1875. 'color-output': function colorOutput(buffer, m) {
  1876. return {
  1877. type_: 'color',
  1878. color1: m[0],
  1879. color2: mhchemParser.go(m[1], 'pq')
  1880. };
  1881. }
  1882. }
  1883. },
  1884. 'bd': {
  1885. transitions: mhchemParser.createTransitions({
  1886. 'empty': {
  1887. '*': {}
  1888. },
  1889. 'x$': {
  1890. '0': {
  1891. nextState: '!f',
  1892. revisit: true
  1893. }
  1894. },
  1895. 'formula$': {
  1896. '0': {
  1897. nextState: 'f',
  1898. revisit: true
  1899. }
  1900. },
  1901. 'else': {
  1902. '0': {
  1903. nextState: '!f',
  1904. revisit: true
  1905. }
  1906. },
  1907. '-9.,9 no missing 0': {
  1908. '*': {
  1909. action_: '9,9'
  1910. }
  1911. },
  1912. '.': {
  1913. '*': {
  1914. action_: {
  1915. type_: 'insert',
  1916. option: 'electron dot'
  1917. }
  1918. }
  1919. },
  1920. 'a-z': {
  1921. 'f': {
  1922. action_: 'tex-math'
  1923. }
  1924. },
  1925. 'x': {
  1926. '*': {
  1927. action_: {
  1928. type_: 'insert',
  1929. option: 'KV x'
  1930. }
  1931. }
  1932. },
  1933. 'letters': {
  1934. '*': {
  1935. action_: 'rm'
  1936. }
  1937. },
  1938. '\'': {
  1939. '*': {
  1940. action_: {
  1941. type_: 'insert',
  1942. option: 'prime'
  1943. }
  1944. }
  1945. },
  1946. '${(...)}$|$(...)$': {
  1947. '*': {
  1948. action_: 'tex-math'
  1949. }
  1950. },
  1951. '{(...)}': {
  1952. '*': {
  1953. action_: 'text'
  1954. }
  1955. },
  1956. '\\color{(...)}{(...)}1|\\color(...){(...)}2': {
  1957. '*': {
  1958. action_: 'color-output'
  1959. }
  1960. },
  1961. '\\color{(...)}0': {
  1962. '*': {
  1963. action_: 'color0-output'
  1964. }
  1965. },
  1966. '\\ce{(...)}': {
  1967. '*': {
  1968. action_: 'ce'
  1969. }
  1970. },
  1971. '\\,|\\x{}{}|\\x{}|\\x': {
  1972. '*': {
  1973. action_: 'copy'
  1974. }
  1975. },
  1976. 'else2': {
  1977. '*': {
  1978. action_: 'copy'
  1979. }
  1980. }
  1981. }),
  1982. actions: {
  1983. 'color-output': function colorOutput(buffer, m) {
  1984. return {
  1985. type_: 'color',
  1986. color1: m[0],
  1987. color2: mhchemParser.go(m[1], 'bd')
  1988. };
  1989. }
  1990. }
  1991. },
  1992. 'oxidation': {
  1993. transitions: mhchemParser.createTransitions({
  1994. 'empty': {
  1995. '*': {}
  1996. },
  1997. 'roman numeral': {
  1998. '*': {
  1999. action_: 'roman-numeral'
  2000. }
  2001. },
  2002. '${(...)}$|$(...)$': {
  2003. '*': {
  2004. action_: 'tex-math'
  2005. }
  2006. },
  2007. 'else': {
  2008. '*': {
  2009. action_: 'copy'
  2010. }
  2011. }
  2012. }),
  2013. actions: {
  2014. 'roman-numeral': function romanNumeral(buffer, m) {
  2015. return {
  2016. type_: 'roman numeral',
  2017. p1: m || ""
  2018. };
  2019. }
  2020. }
  2021. },
  2022. 'tex-math': {
  2023. transitions: mhchemParser.createTransitions({
  2024. 'empty': {
  2025. '*': {
  2026. action_: 'output'
  2027. }
  2028. },
  2029. '\\ce{(...)}': {
  2030. '*': {
  2031. action_: ['output', 'ce']
  2032. }
  2033. },
  2034. '{...}|\\,|\\x{}{}|\\x{}|\\x': {
  2035. '*': {
  2036. action_: 'o='
  2037. }
  2038. },
  2039. 'else': {
  2040. '*': {
  2041. action_: 'o='
  2042. }
  2043. }
  2044. }),
  2045. actions: {
  2046. 'output': function output(buffer) {
  2047. if (buffer.o) {
  2048. /** @type {ParserOutput} */
  2049. var ret = {
  2050. type_: 'tex-math',
  2051. p1: buffer.o
  2052. };
  2053. for (var p in buffer) {
  2054. delete buffer[p];
  2055. }
  2056. return ret;
  2057. }
  2058. }
  2059. }
  2060. },
  2061. 'tex-math tight': {
  2062. transitions: mhchemParser.createTransitions({
  2063. 'empty': {
  2064. '*': {
  2065. action_: 'output'
  2066. }
  2067. },
  2068. '\\ce{(...)}': {
  2069. '*': {
  2070. action_: ['output', 'ce']
  2071. }
  2072. },
  2073. '{...}|\\,|\\x{}{}|\\x{}|\\x': {
  2074. '*': {
  2075. action_: 'o='
  2076. }
  2077. },
  2078. '-|+': {
  2079. '*': {
  2080. action_: 'tight operator'
  2081. }
  2082. },
  2083. 'else': {
  2084. '*': {
  2085. action_: 'o='
  2086. }
  2087. }
  2088. }),
  2089. actions: {
  2090. 'tight operator': function tight_operator(buffer, m) {
  2091. buffer.o = (buffer.o || "") + "{" + m + "}";
  2092. },
  2093. 'output': function output(buffer) {
  2094. if (buffer.o) {
  2095. /** @type {ParserOutput} */
  2096. var ret = {
  2097. type_: 'tex-math',
  2098. p1: buffer.o
  2099. };
  2100. for (var p in buffer) {
  2101. delete buffer[p];
  2102. }
  2103. return ret;
  2104. }
  2105. }
  2106. }
  2107. },
  2108. '9,9': {
  2109. transitions: mhchemParser.createTransitions({
  2110. 'empty': {
  2111. '*': {}
  2112. },
  2113. ',': {
  2114. '*': {
  2115. action_: 'comma'
  2116. }
  2117. },
  2118. 'else': {
  2119. '*': {
  2120. action_: 'copy'
  2121. }
  2122. }
  2123. }),
  2124. actions: {
  2125. 'comma': function comma() {
  2126. return {
  2127. type_: 'commaDecimal'
  2128. };
  2129. }
  2130. }
  2131. },
  2132. //#endregion
  2133. //
  2134. // \pu state machines
  2135. //
  2136. //#region pu
  2137. 'pu': {
  2138. transitions: mhchemParser.createTransitions({
  2139. 'empty': {
  2140. '*': {
  2141. action_: 'output'
  2142. }
  2143. },
  2144. 'space$': {
  2145. '*': {
  2146. action_: ['output', 'space']
  2147. }
  2148. },
  2149. '{[(|)]}': {
  2150. '0|a': {
  2151. action_: 'copy'
  2152. }
  2153. },
  2154. '(-)(9)^(-9)': {
  2155. '0': {
  2156. action_: 'number^',
  2157. nextState: 'a'
  2158. }
  2159. },
  2160. '(-)(9.,9)(e)(99)': {
  2161. '0': {
  2162. action_: 'enumber',
  2163. nextState: 'a'
  2164. }
  2165. },
  2166. 'space': {
  2167. '0|a': {}
  2168. },
  2169. 'pm-operator': {
  2170. '0|a': {
  2171. action_: {
  2172. type_: 'operator',
  2173. option: '\\pm'
  2174. },
  2175. nextState: '0'
  2176. }
  2177. },
  2178. 'operator': {
  2179. '0|a': {
  2180. action_: 'copy',
  2181. nextState: '0'
  2182. }
  2183. },
  2184. '//': {
  2185. 'd': {
  2186. action_: 'o=',
  2187. nextState: '/'
  2188. }
  2189. },
  2190. '/': {
  2191. 'd': {
  2192. action_: 'o=',
  2193. nextState: '/'
  2194. }
  2195. },
  2196. '{...}|else': {
  2197. '0|d': {
  2198. action_: 'd=',
  2199. nextState: 'd'
  2200. },
  2201. 'a': {
  2202. action_: ['space', 'd='],
  2203. nextState: 'd'
  2204. },
  2205. '/|q': {
  2206. action_: 'q=',
  2207. nextState: 'q'
  2208. }
  2209. }
  2210. }),
  2211. actions: {
  2212. 'enumber': function enumber(buffer, m) {
  2213. /** @type {ParserOutput[]} */
  2214. var ret = [];
  2215. if (m[0] === "+-" || m[0] === "+/-") {
  2216. ret.push("\\pm ");
  2217. } else if (m[0]) {
  2218. ret.push(m[0]);
  2219. }
  2220. if (m[1]) {
  2221. mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9'));
  2222. if (m[2]) {
  2223. if (m[2].match(/[,.]/)) {
  2224. mhchemParser.concatArray(ret, mhchemParser.go(m[2], 'pu-9,9'));
  2225. } else {
  2226. ret.push(m[2]);
  2227. }
  2228. }
  2229. m[3] = m[4] || m[3];
  2230. if (m[3]) {
  2231. m[3] = m[3].trim();
  2232. if (m[3] === "e" || m[3].substr(0, 1) === "*") {
  2233. ret.push({
  2234. type_: 'cdot'
  2235. });
  2236. } else {
  2237. ret.push({
  2238. type_: 'times'
  2239. });
  2240. }
  2241. }
  2242. }
  2243. if (m[3]) {
  2244. ret.push("10^{" + m[5] + "}");
  2245. }
  2246. return ret;
  2247. },
  2248. 'number^': function number(buffer, m) {
  2249. /** @type {ParserOutput[]} */
  2250. var ret = [];
  2251. if (m[0] === "+-" || m[0] === "+/-") {
  2252. ret.push("\\pm ");
  2253. } else if (m[0]) {
  2254. ret.push(m[0]);
  2255. }
  2256. mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9'));
  2257. ret.push("^{" + m[2] + "}");
  2258. return ret;
  2259. },
  2260. 'operator': function operator(buffer, m, p1) {
  2261. return {
  2262. type_: 'operator',
  2263. kind_: p1 || m
  2264. };
  2265. },
  2266. 'space': function space() {
  2267. return {
  2268. type_: 'pu-space-1'
  2269. };
  2270. },
  2271. 'output': function output(buffer) {
  2272. /** @type {ParserOutput | ParserOutput[]} */
  2273. var ret;
  2274. var md = mhchemParser.patterns.match_('{(...)}', buffer.d || "");
  2275. if (md && md.remainder === '') {
  2276. buffer.d = md.match_;
  2277. }
  2278. var mq = mhchemParser.patterns.match_('{(...)}', buffer.q || "");
  2279. if (mq && mq.remainder === '') {
  2280. buffer.q = mq.match_;
  2281. }
  2282. if (buffer.d) {
  2283. buffer.d = buffer.d.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C");
  2284. buffer.d = buffer.d.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F");
  2285. }
  2286. if (buffer.q) {
  2287. // fraction
  2288. buffer.q = buffer.q.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C");
  2289. buffer.q = buffer.q.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F");
  2290. var b5 = {
  2291. d: mhchemParser.go(buffer.d, 'pu'),
  2292. q: mhchemParser.go(buffer.q, 'pu')
  2293. };
  2294. if (buffer.o === '//') {
  2295. ret = {
  2296. type_: 'pu-frac',
  2297. p1: b5.d,
  2298. p2: b5.q
  2299. };
  2300. } else {
  2301. ret = b5.d;
  2302. if (b5.d.length > 1 || b5.q.length > 1) {
  2303. ret.push({
  2304. type_: ' / '
  2305. });
  2306. } else {
  2307. ret.push({
  2308. type_: '/'
  2309. });
  2310. }
  2311. mhchemParser.concatArray(ret, b5.q);
  2312. }
  2313. } else {
  2314. // no fraction
  2315. ret = mhchemParser.go(buffer.d, 'pu-2');
  2316. }
  2317. for (var p in buffer) {
  2318. delete buffer[p];
  2319. }
  2320. return ret;
  2321. }
  2322. }
  2323. },
  2324. 'pu-2': {
  2325. transitions: mhchemParser.createTransitions({
  2326. 'empty': {
  2327. '*': {
  2328. action_: 'output'
  2329. }
  2330. },
  2331. '*': {
  2332. '*': {
  2333. action_: ['output', 'cdot'],
  2334. nextState: '0'
  2335. }
  2336. },
  2337. '\\x': {
  2338. '*': {
  2339. action_: 'rm='
  2340. }
  2341. },
  2342. 'space': {
  2343. '*': {
  2344. action_: ['output', 'space'],
  2345. nextState: '0'
  2346. }
  2347. },
  2348. '^{(...)}|^(-1)': {
  2349. '1': {
  2350. action_: '^(-1)'
  2351. }
  2352. },
  2353. '-9.,9': {
  2354. '0': {
  2355. action_: 'rm=',
  2356. nextState: '0'
  2357. },
  2358. '1': {
  2359. action_: '^(-1)',
  2360. nextState: '0'
  2361. }
  2362. },
  2363. '{...}|else': {
  2364. '*': {
  2365. action_: 'rm=',
  2366. nextState: '1'
  2367. }
  2368. }
  2369. }),
  2370. actions: {
  2371. 'cdot': function cdot() {
  2372. return {
  2373. type_: 'tight cdot'
  2374. };
  2375. },
  2376. '^(-1)': function _(buffer, m) {
  2377. buffer.rm += "^{" + m + "}";
  2378. },
  2379. 'space': function space() {
  2380. return {
  2381. type_: 'pu-space-2'
  2382. };
  2383. },
  2384. 'output': function output(buffer) {
  2385. /** @type {ParserOutput | ParserOutput[]} */
  2386. var ret = [];
  2387. if (buffer.rm) {
  2388. var mrm = mhchemParser.patterns.match_('{(...)}', buffer.rm || "");
  2389. if (mrm && mrm.remainder === '') {
  2390. ret = mhchemParser.go(mrm.match_, 'pu');
  2391. } else {
  2392. ret = {
  2393. type_: 'rm',
  2394. p1: buffer.rm
  2395. };
  2396. }
  2397. }
  2398. for (var p in buffer) {
  2399. delete buffer[p];
  2400. }
  2401. return ret;
  2402. }
  2403. }
  2404. },
  2405. 'pu-9,9': {
  2406. transitions: mhchemParser.createTransitions({
  2407. 'empty': {
  2408. '0': {
  2409. action_: 'output-0'
  2410. },
  2411. 'o': {
  2412. action_: 'output-o'
  2413. }
  2414. },
  2415. ',': {
  2416. '0': {
  2417. action_: ['output-0', 'comma'],
  2418. nextState: 'o'
  2419. }
  2420. },
  2421. '.': {
  2422. '0': {
  2423. action_: ['output-0', 'copy'],
  2424. nextState: 'o'
  2425. }
  2426. },
  2427. 'else': {
  2428. '*': {
  2429. action_: 'text='
  2430. }
  2431. }
  2432. }),
  2433. actions: {
  2434. 'comma': function comma() {
  2435. return {
  2436. type_: 'commaDecimal'
  2437. };
  2438. },
  2439. 'output-0': function output0(buffer) {
  2440. /** @type {ParserOutput[]} */
  2441. var ret = [];
  2442. buffer.text_ = buffer.text_ || "";
  2443. if (buffer.text_.length > 4) {
  2444. var a = buffer.text_.length % 3;
  2445. if (a === 0) {
  2446. a = 3;
  2447. }
  2448. for (var i = buffer.text_.length - 3; i > 0; i -= 3) {
  2449. ret.push(buffer.text_.substr(i, 3));
  2450. ret.push({
  2451. type_: '1000 separator'
  2452. });
  2453. }
  2454. ret.push(buffer.text_.substr(0, a));
  2455. ret.reverse();
  2456. } else {
  2457. ret.push(buffer.text_);
  2458. }
  2459. for (var p in buffer) {
  2460. delete buffer[p];
  2461. }
  2462. return ret;
  2463. },
  2464. 'output-o': function outputO(buffer) {
  2465. /** @type {ParserOutput[]} */
  2466. var ret = [];
  2467. buffer.text_ = buffer.text_ || "";
  2468. if (buffer.text_.length > 4) {
  2469. var a = buffer.text_.length - 3;
  2470. for (var i = 0; i < a; i += 3) {
  2471. ret.push(buffer.text_.substr(i, 3));
  2472. ret.push({
  2473. type_: '1000 separator'
  2474. });
  2475. }
  2476. ret.push(buffer.text_.substr(i));
  2477. } else {
  2478. ret.push(buffer.text_);
  2479. }
  2480. for (var p in buffer) {
  2481. delete buffer[p];
  2482. }
  2483. return ret;
  2484. }
  2485. }
  2486. }
  2487. //#endregion
  2488. };
  2489. //
  2490. // texify: Take MhchemParser output and convert it to TeX
  2491. //
  2492. /** @type {Texify} */
  2493. var texify = {
  2494. go: function go(input, isInner) {
  2495. // (recursive, max 4 levels)
  2496. if (!input) {
  2497. return "";
  2498. }
  2499. var res = "";
  2500. var cee = false;
  2501. for (var i = 0; i < input.length; i++) {
  2502. var inputi = input[i];
  2503. if (typeof inputi === "string") {
  2504. res += inputi;
  2505. } else {
  2506. res += texify._go2(inputi);
  2507. if (inputi.type_ === '1st-level escape') {
  2508. cee = true;
  2509. }
  2510. }
  2511. }
  2512. if (!isInner && !cee && res) {
  2513. res = "{" + res + "}";
  2514. }
  2515. return res;
  2516. },
  2517. _goInner: function _goInner(input) {
  2518. if (!input) {
  2519. return input;
  2520. }
  2521. return texify.go(input, true);
  2522. },
  2523. _go2: function _go2(buf) {
  2524. /** @type {undefined | string} */
  2525. var res;
  2526. switch (buf.type_) {
  2527. case 'chemfive':
  2528. res = "";
  2529. var b5 = {
  2530. a: texify._goInner(buf.a),
  2531. b: texify._goInner(buf.b),
  2532. p: texify._goInner(buf.p),
  2533. o: texify._goInner(buf.o),
  2534. q: texify._goInner(buf.q),
  2535. d: texify._goInner(buf.d)
  2536. };
  2537. //
  2538. // a
  2539. //
  2540. if (b5.a) {
  2541. if (b5.a.match(/^[+\-]/)) {
  2542. b5.a = "{" + b5.a + "}";
  2543. }
  2544. res += b5.a + "\\,";
  2545. }
  2546. //
  2547. // b and p
  2548. //
  2549. if (b5.b || b5.p) {
  2550. res += "{\\vphantom{X}}";
  2551. res += "^{\\hphantom{" + (b5.b || "") + "}}_{\\hphantom{" + (b5.p || "") + "}}";
  2552. res += "{\\vphantom{X}}";
  2553. res += "^{\\smash[t]{\\vphantom{2}}\\mathllap{" + (b5.b || "") + "}}";
  2554. res += "_{\\vphantom{2}\\mathllap{\\smash[t]{" + (b5.p || "") + "}}}";
  2555. }
  2556. //
  2557. // o
  2558. //
  2559. if (b5.o) {
  2560. if (b5.o.match(/^[+\-]/)) {
  2561. b5.o = "{" + b5.o + "}";
  2562. }
  2563. res += b5.o;
  2564. }
  2565. //
  2566. // q and d
  2567. //
  2568. if (buf.dType === 'kv') {
  2569. if (b5.d || b5.q) {
  2570. res += "{\\vphantom{X}}";
  2571. }
  2572. if (b5.d) {
  2573. res += "^{" + b5.d + "}";
  2574. }
  2575. if (b5.q) {
  2576. res += "_{\\smash[t]{" + b5.q + "}}";
  2577. }
  2578. } else if (buf.dType === 'oxidation') {
  2579. if (b5.d) {
  2580. res += "{\\vphantom{X}}";
  2581. res += "^{" + b5.d + "}";
  2582. }
  2583. if (b5.q) {
  2584. res += "{\\vphantom{X}}";
  2585. res += "_{\\smash[t]{" + b5.q + "}}";
  2586. }
  2587. } else {
  2588. if (b5.q) {
  2589. res += "{\\vphantom{X}}";
  2590. res += "_{\\smash[t]{" + b5.q + "}}";
  2591. }
  2592. if (b5.d) {
  2593. res += "{\\vphantom{X}}";
  2594. res += "^{" + b5.d + "}";
  2595. }
  2596. }
  2597. break;
  2598. case 'rm':
  2599. res = "\\mathrm{" + buf.p1 + "}";
  2600. break;
  2601. case 'text':
  2602. if (buf.p1.match(/[\^_]/)) {
  2603. buf.p1 = buf.p1.replace(" ", "~").replace("-", "\\text{-}");
  2604. res = "\\mathrm{" + buf.p1 + "}";
  2605. } else {
  2606. res = "\\text{" + buf.p1 + "}";
  2607. }
  2608. break;
  2609. case 'roman numeral':
  2610. res = "\\mathrm{" + buf.p1 + "}";
  2611. break;
  2612. case 'state of aggregation':
  2613. res = "\\mskip2mu " + texify._goInner(buf.p1);
  2614. break;
  2615. case 'state of aggregation subscript':
  2616. res = "\\mskip1mu " + texify._goInner(buf.p1);
  2617. break;
  2618. case 'bond':
  2619. res = texify._getBond(buf.kind_);
  2620. if (!res) {
  2621. throw ["MhchemErrorBond", "mhchem Error. Unknown bond type (" + buf.kind_ + ")"];
  2622. }
  2623. break;
  2624. case 'frac':
  2625. var c = "\\frac{" + buf.p1 + "}{" + buf.p2 + "}";
  2626. res = "\\mathchoice{\\textstyle" + c + "}{" + c + "}{" + c + "}{" + c + "}";
  2627. break;
  2628. case 'pu-frac':
  2629. var d = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}";
  2630. res = "\\mathchoice{\\textstyle" + d + "}{" + d + "}{" + d + "}{" + d + "}";
  2631. break;
  2632. case 'tex-math':
  2633. res = buf.p1 + " ";
  2634. break;
  2635. case 'frac-ce':
  2636. res = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}";
  2637. break;
  2638. case 'overset':
  2639. res = "\\overset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}";
  2640. break;
  2641. case 'underset':
  2642. res = "\\underset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}";
  2643. break;
  2644. case 'underbrace':
  2645. res = "\\underbrace{" + texify._goInner(buf.p1) + "}_{" + texify._goInner(buf.p2) + "}";
  2646. break;
  2647. case 'color':
  2648. res = "{\\color{" + buf.color1 + "}{" + texify._goInner(buf.color2) + "}}";
  2649. break;
  2650. case 'color0':
  2651. res = "\\color{" + buf.color + "}";
  2652. break;
  2653. case 'arrow':
  2654. var b6 = {
  2655. rd: texify._goInner(buf.rd),
  2656. rq: texify._goInner(buf.rq)
  2657. };
  2658. var arrow = "\\x" + texify._getArrow(buf.r);
  2659. if (b6.rq) {
  2660. arrow += "[{" + b6.rq + "}]";
  2661. }
  2662. if (b6.rd) {
  2663. arrow += "{" + b6.rd + "}";
  2664. } else {
  2665. arrow += "{}";
  2666. }
  2667. res = arrow;
  2668. break;
  2669. case 'operator':
  2670. res = texify._getOperator(buf.kind_);
  2671. break;
  2672. case '1st-level escape':
  2673. res = buf.p1 + " "; // &, \\\\, \\hlin
  2674. break;
  2675. case 'space':
  2676. res = " ";
  2677. break;
  2678. case 'entitySkip':
  2679. res = "~";
  2680. break;
  2681. case 'pu-space-1':
  2682. res = "~";
  2683. break;
  2684. case 'pu-space-2':
  2685. res = "\\mkern3mu ";
  2686. break;
  2687. case '1000 separator':
  2688. res = "\\mkern2mu ";
  2689. break;
  2690. case 'commaDecimal':
  2691. res = "{,}";
  2692. break;
  2693. case 'comma enumeration L':
  2694. res = "{" + buf.p1 + "}\\mkern6mu ";
  2695. break;
  2696. case 'comma enumeration M':
  2697. res = "{" + buf.p1 + "}\\mkern3mu ";
  2698. break;
  2699. case 'comma enumeration S':
  2700. res = "{" + buf.p1 + "}\\mkern1mu ";
  2701. break;
  2702. case 'hyphen':
  2703. res = "\\text{-}";
  2704. break;
  2705. case 'addition compound':
  2706. res = "\\,{\\cdot}\\,";
  2707. break;
  2708. case 'electron dot':
  2709. res = "\\mkern1mu \\bullet\\mkern1mu ";
  2710. break;
  2711. case 'KV x':
  2712. res = "{\\times}";
  2713. break;
  2714. case 'prime':
  2715. res = "\\prime ";
  2716. break;
  2717. case 'cdot':
  2718. res = "\\cdot ";
  2719. break;
  2720. case 'tight cdot':
  2721. res = "\\mkern1mu{\\cdot}\\mkern1mu ";
  2722. break;
  2723. case 'times':
  2724. res = "\\times ";
  2725. break;
  2726. case 'circa':
  2727. res = "{\\sim}";
  2728. break;
  2729. case '^':
  2730. res = "uparrow";
  2731. break;
  2732. case 'v':
  2733. res = "downarrow";
  2734. break;
  2735. case 'ellipsis':
  2736. res = "\\ldots ";
  2737. break;
  2738. case '/':
  2739. res = "/";
  2740. break;
  2741. case ' / ':
  2742. res = "\\,/\\,";
  2743. break;
  2744. default:
  2745. throw ["MhchemBugT", "mhchem bug T. Please report."];
  2746. // Missing texify rule or unknown MhchemParser output
  2747. }
  2748. return res;
  2749. },
  2750. _getArrow: function _getArrow(a) {
  2751. switch (a) {
  2752. case "->":
  2753. return "rightarrow";
  2754. case "\u2192":
  2755. return "rightarrow";
  2756. case "\u27F6":
  2757. return "rightarrow";
  2758. case "<-":
  2759. return "leftarrow";
  2760. case "<->":
  2761. return "leftrightarrow";
  2762. case "<-->":
  2763. return "rightleftarrows";
  2764. case "<=>":
  2765. return "rightleftharpoons";
  2766. case "\u21CC":
  2767. return "rightleftharpoons";
  2768. case "<=>>":
  2769. return "rightequilibrium";
  2770. case "<<=>":
  2771. return "leftequilibrium";
  2772. default:
  2773. throw ["MhchemBugT", "mhchem bug T. Please report."];
  2774. }
  2775. },
  2776. _getBond: function _getBond(a) {
  2777. switch (a) {
  2778. case "-":
  2779. return "{-}";
  2780. case "1":
  2781. return "{-}";
  2782. case "=":
  2783. return "{=}";
  2784. case "2":
  2785. return "{=}";
  2786. case "#":
  2787. return "{\\equiv}";
  2788. case "3":
  2789. return "{\\equiv}";
  2790. case "~":
  2791. return "{\\tripledash}";
  2792. case "~-":
  2793. return "{\\mathrlap{\\raisebox{-.1em}{$-$}}\\raisebox{.1em}{$\\tripledash$}}";
  2794. case "~=":
  2795. return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}";
  2796. case "~--":
  2797. return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}";
  2798. case "-~-":
  2799. return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$-$}}\\tripledash}";
  2800. case "...":
  2801. return "{{\\cdot}{\\cdot}{\\cdot}}";
  2802. case "....":
  2803. return "{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}";
  2804. case "->":
  2805. return "{\\rightarrow}";
  2806. case "<-":
  2807. return "{\\leftarrow}";
  2808. case "<":
  2809. return "{<}";
  2810. case ">":
  2811. return "{>}";
  2812. default:
  2813. throw ["MhchemBugT", "mhchem bug T. Please report."];
  2814. }
  2815. },
  2816. _getOperator: function _getOperator(a) {
  2817. switch (a) {
  2818. case "+":
  2819. return " {}+{} ";
  2820. case "-":
  2821. return " {}-{} ";
  2822. case "=":
  2823. return " {}={} ";
  2824. case "<":
  2825. return " {}<{} ";
  2826. case ">":
  2827. return " {}>{} ";
  2828. case "<<":
  2829. return " {}\\ll{} ";
  2830. case ">>":
  2831. return " {}\\gg{} ";
  2832. case "\\pm":
  2833. return " {}\\pm{} ";
  2834. case "\\approx":
  2835. return " {}\\approx{} ";
  2836. case "$\\approx$":
  2837. return " {}\\approx{} ";
  2838. case "v":
  2839. return " \\downarrow{} ";
  2840. case "(v)":
  2841. return " \\downarrow{} ";
  2842. case "^":
  2843. return " \\uparrow{} ";
  2844. case "(^)":
  2845. return " \\uparrow{} ";
  2846. default:
  2847. throw ["MhchemBugT", "mhchem bug T. Please report."];
  2848. }
  2849. }
  2850. };