PHPIndex

This page lists files in the current directory. You can view content, get download/execute commands for Wget, Curl, or PowerShell, or filter the list using wildcards (e.g., `*.sh`).

auto-render.js
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/auto-render.js'
View Content
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory(require("katex"));
	else if(typeof define === 'function' && define.amd)
		define(["katex"], factory);
	else if(typeof exports === 'object')
		exports["renderMathInElement"] = factory(require("katex"));
	else
		root["renderMathInElement"] = factory(root["katex"]);
})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__771__) {
return /******/ (function() { // webpackBootstrap
/******/ 	"use strict";
/******/ 	var __webpack_modules__ = ({

/***/ 771:
/***/ (function(module) {

module.exports = __WEBPACK_EXTERNAL_MODULE__771__;

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	!function() {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = function(module) {
/******/ 			var getter = module && module.__esModule ?
/******/ 				function() { return module['default']; } :
/******/ 				function() { return module; };
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
/******/ 		};
/******/ 	}();
/******/ 	
/******/ 	/* webpack/runtime/define property getters */
/******/ 	!function() {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = function(exports, definition) {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	}();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	!function() {
/******/ 		__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ 	}();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
!function() {

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "default": function() { return /* binding */ auto_render; }
});

// EXTERNAL MODULE: external "katex"
var external_katex_ = __webpack_require__(771);
var external_katex_default = /*#__PURE__*/__webpack_require__.n(external_katex_);
;// CONCATENATED MODULE: ./contrib/auto-render/splitAtDelimiters.js
/* eslint no-constant-condition:0 */
var findEndOfMath = function findEndOfMath(delimiter, text, startIndex) {
  // Adapted from
  // https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
  var index = startIndex;
  var braceLevel = 0;
  var delimLength = delimiter.length;

  while (index < text.length) {
    var character = text[index];

    if (braceLevel <= 0 && text.slice(index, index + delimLength) === delimiter) {
      return index;
    } else if (character === "\\") {
      index++;
    } else if (character === "{") {
      braceLevel++;
    } else if (character === "}") {
      braceLevel--;
    }

    index++;
  }

  return -1;
};

var escapeRegex = function escapeRegex(string) {
  return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
};

var amsRegex = /^\\begin{/;

var splitAtDelimiters = function splitAtDelimiters(text, delimiters) {
  var index;
  var data = [];
  var regexLeft = new RegExp("(" + delimiters.map(function (x) {
    return escapeRegex(x.left);
  }).join("|") + ")");

  while (true) {
    index = text.search(regexLeft);

    if (index === -1) {
      break;
    }

    if (index > 0) {
      data.push({
        type: "text",
        data: text.slice(0, index)
      });
      text = text.slice(index); // now text starts with delimiter
    } // ... so this always succeeds:


    var i = delimiters.findIndex(function (delim) {
      return text.startsWith(delim.left);
    });
    index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length);

    if (index === -1) {
      break;
    }

    var rawData = text.slice(0, index + delimiters[i].right.length);
    var math = amsRegex.test(rawData) ? rawData : text.slice(delimiters[i].left.length, index);
    data.push({
      type: "math",
      data: math,
      rawData: rawData,
      display: delimiters[i].display
    });
    text = text.slice(index + delimiters[i].right.length);
  }

  if (text !== "") {
    data.push({
      type: "text",
      data: text
    });
  }

  return data;
};

/* harmony default export */ var auto_render_splitAtDelimiters = (splitAtDelimiters);
;// CONCATENATED MODULE: ./contrib/auto-render/auto-render.js
/* eslint no-console:0 */


/* Note: optionsCopy is mutated by this method. If it is ever exposed in the
 * API, we should copy it before mutating.
 */

var renderMathInText = function renderMathInText(text, optionsCopy) {
  var data = auto_render_splitAtDelimiters(text, optionsCopy.delimiters);

  if (data.length === 1 && data[0].type === 'text') {
    // There is no formula in the text.
    // Let's return null which means there is no need to replace
    // the current text node with a new one.
    return null;
  }

  var fragment = document.createDocumentFragment();

  for (var i = 0; i < data.length; i++) {
    if (data[i].type === "text") {
      fragment.appendChild(document.createTextNode(data[i].data));
    } else {
      var span = document.createElement("span");
      var math = data[i].data; // Override any display mode defined in the settings with that
      // defined by the text itself

      optionsCopy.displayMode = data[i].display;

      try {
        if (optionsCopy.preProcess) {
          math = optionsCopy.preProcess(math);
        }

        external_katex_default().render(math, span, optionsCopy);
      } catch (e) {
        if (!(e instanceof (external_katex_default()).ParseError)) {
          throw e;
        }

        optionsCopy.errorCallback("KaTeX auto-render: Failed to parse `" + data[i].data + "` with ", e);
        fragment.appendChild(document.createTextNode(data[i].rawData));
        continue;
      }

      fragment.appendChild(span);
    }
  }

  return fragment;
};

var renderElem = function renderElem(elem, optionsCopy) {
  for (var i = 0; i < elem.childNodes.length; i++) {
    var childNode = elem.childNodes[i];

    if (childNode.nodeType === 3) {
      // Text node
      // Concatenate all sibling text nodes.
      // Webkit browsers split very large text nodes into smaller ones,
      // so the delimiters may be split across different nodes.
      var textContentConcat = childNode.textContent;
      var sibling = childNode.nextSibling;
      var nSiblings = 0;

      while (sibling && sibling.nodeType === Node.TEXT_NODE) {
        textContentConcat += sibling.textContent;
        sibling = sibling.nextSibling;
        nSiblings++;
      }

      var frag = renderMathInText(textContentConcat, optionsCopy);

      if (frag) {
        // Remove extra text nodes
        for (var j = 0; j < nSiblings; j++) {
          childNode.nextSibling.remove();
        }

        i += frag.childNodes.length - 1;
        elem.replaceChild(frag, childNode);
      } else {
        // If the concatenated text does not contain math
        // the siblings will not either
        i += nSiblings;
      }
    } else if (childNode.nodeType === 1) {
      (function () {
        // Element node
        var className = ' ' + childNode.className + ' ';
        var shouldRender = optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) === -1 && optionsCopy.ignoredClasses.every(function (x) {
          return className.indexOf(' ' + x + ' ') === -1;
        });

        if (shouldRender) {
          renderElem(childNode, optionsCopy);
        }
      })();
    } // Otherwise, it's something else, and ignore it.

  }
};

var renderMathInElement = function renderMathInElement(elem, options) {
  if (!elem) {
    throw new Error("No element provided to render");
  }

  var optionsCopy = {}; // Object.assign(optionsCopy, option)

  for (var option in options) {
    if (options.hasOwnProperty(option)) {
      optionsCopy[option] = options[option];
    }
  } // default options


  optionsCopy.delimiters = optionsCopy.delimiters || [{
    left: "$$",
    right: "$$",
    display: true
  }, {
    left: "\\(",
    right: "\\)",
    display: false
  }, // LaTeX uses $…$, but it ruins the display of normal `$` in text:
  // {left: "$", right: "$", display: false},
  // $ must come after $$
  // Render AMS environments even if outside $$…$$ delimiters.
  {
    left: "\\begin{equation}",
    right: "\\end{equation}",
    display: true
  }, {
    left: "\\begin{align}",
    right: "\\end{align}",
    display: true
  }, {
    left: "\\begin{alignat}",
    right: "\\end{alignat}",
    display: true
  }, {
    left: "\\begin{gather}",
    right: "\\end{gather}",
    display: true
  }, {
    left: "\\begin{CD}",
    right: "\\end{CD}",
    display: true
  }, {
    left: "\\[",
    right: "\\]",
    display: true
  }];
  optionsCopy.ignoredTags = optionsCopy.ignoredTags || ["script", "noscript", "style", "textarea", "pre", "code", "option"];
  optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || [];
  optionsCopy.errorCallback = optionsCopy.errorCallback || console.error; // Enable sharing of global macros defined via `\gdef` between different
  // math elements within a single call to `renderMathInElement`.

  optionsCopy.macros = optionsCopy.macros || {};
  renderElem(elem, optionsCopy);
};

/* harmony default export */ var auto_render = (renderMathInElement);
}();
__webpack_exports__ = __webpack_exports__["default"];
/******/ 	return __webpack_exports__;
/******/ })()
;
});
auto-render.min.js
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/auto-render.min.js'
View Content
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={771:function(t){t.exports=e}},r={};function n(e){var i=r[e];if(void 0!==i)return i.exports;var a=r[e]={exports:{}};return t[e](a,a.exports,n),a.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var i={};return function(){n.d(i,{default:function(){return s}});var e=n(771),t=n.n(e),r=function(e,t,r){for(var n=r,i=0,a=e.length;n<t.length;){var o=t[n];if(i<=0&&t.slice(n,n+a)===e)return n;"\\"===o?n++:"{"===o?i++:"}"===o&&i--,n++}return-1},a=/^\\begin{/,o=function(e,t){for(var n,i=[],o=new RegExp("("+t.map((function(e){return e.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&")})).join("|")+")");-1!==(n=e.search(o));){n>0&&(i.push({type:"text",data:e.slice(0,n)}),e=e.slice(n));var l=t.findIndex((function(t){return e.startsWith(t.left)}));if(-1===(n=r(t[l].right,e,t[l].left.length)))break;var d=e.slice(0,n+t[l].right.length),s=a.test(d)?d:e.slice(t[l].left.length,n);i.push({type:"math",data:s,rawData:d,display:t[l].display}),e=e.slice(n+t[l].right.length)}return""!==e&&i.push({type:"text",data:e}),i},l=function(e,r){var n=o(e,r.delimiters);if(1===n.length&&"text"===n[0].type)return null;for(var i=document.createDocumentFragment(),a=0;a<n.length;a++)if("text"===n[a].type)i.appendChild(document.createTextNode(n[a].data));else{var l=document.createElement("span"),d=n[a].data;r.displayMode=n[a].display;try{r.preProcess&&(d=r.preProcess(d)),t().render(d,l,r)}catch(e){if(!(e instanceof t().ParseError))throw e;r.errorCallback("KaTeX auto-render: Failed to parse `"+n[a].data+"` with ",e),i.appendChild(document.createTextNode(n[a].rawData));continue}i.appendChild(l)}return i},d=function e(t,r){for(var n=0;n<t.childNodes.length;n++){var i=t.childNodes[n];if(3===i.nodeType){for(var a=i.textContent,o=i.nextSibling,d=0;o&&o.nodeType===Node.TEXT_NODE;)a+=o.textContent,o=o.nextSibling,d++;var s=l(a,r);if(s){for(var f=0;f<d;f++)i.nextSibling.remove();n+=s.childNodes.length-1,t.replaceChild(s,i)}else n+=d}else 1===i.nodeType&&function(){var t=" "+i.className+" ";-1===r.ignoredTags.indexOf(i.nodeName.toLowerCase())&&r.ignoredClasses.every((function(e){return-1===t.indexOf(" "+e+" ")}))&&e(i,r)}()}},s=function(e,t){if(!e)throw new Error("No element provided to render");var r={};for(var n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);r.delimiters=r.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\begin{equation}",right:"\\end{equation}",display:!0},{left:"\\begin{align}",right:"\\end{align}",display:!0},{left:"\\begin{alignat}",right:"\\end{alignat}",display:!0},{left:"\\begin{gather}",right:"\\end{gather}",display:!0},{left:"\\begin{CD}",right:"\\end{CD}",display:!0},{left:"\\[",right:"\\]",display:!0}],r.ignoredTags=r.ignoredTags||["script","noscript","style","textarea","pre","code","option"],r.ignoredClasses=r.ignoredClasses||[],r.errorCallback=r.errorCallback||console.error,r.macros=r.macros||{},d(e,r)}}(),i=i.default}()}));
auto-render.mjs
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/auto-render.mjs'
View Content
import katex from '../katex.mjs';

/* eslint no-constant-condition:0 */
var findEndOfMath = function findEndOfMath(delimiter, text, startIndex) {
  // Adapted from
  // https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
  var index = startIndex;
  var braceLevel = 0;
  var delimLength = delimiter.length;

  while (index < text.length) {
    var character = text[index];

    if (braceLevel <= 0 && text.slice(index, index + delimLength) === delimiter) {
      return index;
    } else if (character === "\\") {
      index++;
    } else if (character === "{") {
      braceLevel++;
    } else if (character === "}") {
      braceLevel--;
    }

    index++;
  }

  return -1;
};

var escapeRegex = function escapeRegex(string) {
  return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
};

var amsRegex = /^\\begin{/;

var splitAtDelimiters = function splitAtDelimiters(text, delimiters) {
  var index;
  var data = [];
  var regexLeft = new RegExp("(" + delimiters.map(x => escapeRegex(x.left)).join("|") + ")");

  while (true) {
    index = text.search(regexLeft);

    if (index === -1) {
      break;
    }

    if (index > 0) {
      data.push({
        type: "text",
        data: text.slice(0, index)
      });
      text = text.slice(index); // now text starts with delimiter
    } // ... so this always succeeds:


    var i = delimiters.findIndex(delim => text.startsWith(delim.left));
    index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length);

    if (index === -1) {
      break;
    }

    var rawData = text.slice(0, index + delimiters[i].right.length);
    var math = amsRegex.test(rawData) ? rawData : text.slice(delimiters[i].left.length, index);
    data.push({
      type: "math",
      data: math,
      rawData,
      display: delimiters[i].display
    });
    text = text.slice(index + delimiters[i].right.length);
  }

  if (text !== "") {
    data.push({
      type: "text",
      data: text
    });
  }

  return data;
};

/* eslint no-console:0 */
/* Note: optionsCopy is mutated by this method. If it is ever exposed in the
 * API, we should copy it before mutating.
 */

var renderMathInText = function renderMathInText(text, optionsCopy) {
  var data = splitAtDelimiters(text, optionsCopy.delimiters);

  if (data.length === 1 && data[0].type === 'text') {
    // There is no formula in the text.
    // Let's return null which means there is no need to replace
    // the current text node with a new one.
    return null;
  }

  var fragment = document.createDocumentFragment();

  for (var i = 0; i < data.length; i++) {
    if (data[i].type === "text") {
      fragment.appendChild(document.createTextNode(data[i].data));
    } else {
      var span = document.createElement("span");
      var math = data[i].data; // Override any display mode defined in the settings with that
      // defined by the text itself

      optionsCopy.displayMode = data[i].display;

      try {
        if (optionsCopy.preProcess) {
          math = optionsCopy.preProcess(math);
        }

        katex.render(math, span, optionsCopy);
      } catch (e) {
        if (!(e instanceof katex.ParseError)) {
          throw e;
        }

        optionsCopy.errorCallback("KaTeX auto-render: Failed to parse `" + data[i].data + "` with ", e);
        fragment.appendChild(document.createTextNode(data[i].rawData));
        continue;
      }

      fragment.appendChild(span);
    }
  }

  return fragment;
};

var renderElem = function renderElem(elem, optionsCopy) {
  for (var i = 0; i < elem.childNodes.length; i++) {
    var childNode = elem.childNodes[i];

    if (childNode.nodeType === 3) {
      // Text node
      // Concatenate all sibling text nodes.
      // Webkit browsers split very large text nodes into smaller ones,
      // so the delimiters may be split across different nodes.
      var textContentConcat = childNode.textContent;
      var sibling = childNode.nextSibling;
      var nSiblings = 0;

      while (sibling && sibling.nodeType === Node.TEXT_NODE) {
        textContentConcat += sibling.textContent;
        sibling = sibling.nextSibling;
        nSiblings++;
      }

      var frag = renderMathInText(textContentConcat, optionsCopy);

      if (frag) {
        // Remove extra text nodes
        for (var j = 0; j < nSiblings; j++) {
          childNode.nextSibling.remove();
        }

        i += frag.childNodes.length - 1;
        elem.replaceChild(frag, childNode);
      } else {
        // If the concatenated text does not contain math
        // the siblings will not either
        i += nSiblings;
      }
    } else if (childNode.nodeType === 1) {
      (function () {
        // Element node
        var className = ' ' + childNode.className + ' ';
        var shouldRender = optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) === -1 && optionsCopy.ignoredClasses.every(x => className.indexOf(' ' + x + ' ') === -1);

        if (shouldRender) {
          renderElem(childNode, optionsCopy);
        }
      })();
    } // Otherwise, it's something else, and ignore it.

  }
};

var renderMathInElement = function renderMathInElement(elem, options) {
  if (!elem) {
    throw new Error("No element provided to render");
  }

  var optionsCopy = {}; // Object.assign(optionsCopy, option)

  for (var option in options) {
    if (options.hasOwnProperty(option)) {
      optionsCopy[option] = options[option];
    }
  } // default options


  optionsCopy.delimiters = optionsCopy.delimiters || [{
    left: "$$",
    right: "$$",
    display: true
  }, {
    left: "\\(",
    right: "\\)",
    display: false
  }, // LaTeX uses $…$, but it ruins the display of normal `$` in text:
  // {left: "$", right: "$", display: false},
  // $ must come after $$
  // Render AMS environments even if outside $$…$$ delimiters.
  {
    left: "\\begin{equation}",
    right: "\\end{equation}",
    display: true
  }, {
    left: "\\begin{align}",
    right: "\\end{align}",
    display: true
  }, {
    left: "\\begin{alignat}",
    right: "\\end{alignat}",
    display: true
  }, {
    left: "\\begin{gather}",
    right: "\\end{gather}",
    display: true
  }, {
    left: "\\begin{CD}",
    right: "\\end{CD}",
    display: true
  }, {
    left: "\\[",
    right: "\\]",
    display: true
  }];
  optionsCopy.ignoredTags = optionsCopy.ignoredTags || ["script", "noscript", "style", "textarea", "pre", "code", "option"];
  optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || [];
  optionsCopy.errorCallback = optionsCopy.errorCallback || console.error; // Enable sharing of global macros defined via `\gdef` between different
  // math elements within a single call to `renderMathInElement`.

  optionsCopy.macros = optionsCopy.macros || {};
  renderElem(elem, optionsCopy);
};

export { renderMathInElement as default };
copy-tex.css
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/copy-tex.css'
View Content
/* Force selection of entire .katex/.katex-display blocks, so that we can
 * copy/paste the entire source code.  If you omit this CSS, partial
 * selections of a formula will work, but will copy the ugly HTML
 * representation instead of the LaTeX source code.  (Full selections will
 * still produce the LaTeX source code.)
 */
.katex,
.katex-display {
    user-select: all;
    -moz-user-select: all;
    -webkit-user-select: all;
    -ms-user-select: all;
}

copy-tex.js
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/copy-tex.js'
View Content
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define([], factory);
	else {
		var a = factory();
		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
	}
})((typeof self !== 'undefined' ? self : this), function() {
return /******/ (function() { // webpackBootstrap
/******/ 	"use strict";
var __webpack_exports__ = {};

;// CONCATENATED MODULE: ./contrib/copy-tex/katex2tex.js
// Set these to how you want inline and display math to be delimited.
var defaultCopyDelimiters = {
  inline: ['$', '$'],
  // alternative: ['\(', '\)']
  display: ['$$', '$$'] // alternative: ['\[', '\]']

}; // Replace .katex elements with their TeX source (<annotation> element).
// Modifies fragment in-place.  Useful for writing your own 'copy' handler,
// as in copy-tex.js.

function katexReplaceWithTex(fragment, copyDelimiters) {
  if (copyDelimiters === void 0) {
    copyDelimiters = defaultCopyDelimiters;
  }

  // Remove .katex-html blocks that are preceded by .katex-mathml blocks
  // (which will get replaced below).
  var katexHtml = fragment.querySelectorAll('.katex-mathml + .katex-html');

  for (var i = 0; i < katexHtml.length; i++) {
    var element = katexHtml[i];

    if (element.remove) {
      element.remove();
    } else if (element.parentNode) {
      element.parentNode.removeChild(element);
    }
  } // Replace .katex-mathml elements with their annotation (TeX source)
  // descendant, with inline delimiters.


  var katexMathml = fragment.querySelectorAll('.katex-mathml');

  for (var _i = 0; _i < katexMathml.length; _i++) {
    var _element = katexMathml[_i];

    var texSource = _element.querySelector('annotation');

    if (texSource) {
      if (_element.replaceWith) {
        _element.replaceWith(texSource);
      } else if (_element.parentNode) {
        _element.parentNode.replaceChild(texSource, _element);
      }

      texSource.innerHTML = copyDelimiters.inline[0] + texSource.innerHTML + copyDelimiters.inline[1];
    }
  } // Switch display math to display delimiters.


  var displays = fragment.querySelectorAll('.katex-display annotation');

  for (var _i2 = 0; _i2 < displays.length; _i2++) {
    var _element2 = displays[_i2];
    _element2.innerHTML = copyDelimiters.display[0] + _element2.innerHTML.substr(copyDelimiters.inline[0].length, _element2.innerHTML.length - copyDelimiters.inline[0].length - copyDelimiters.inline[1].length) + copyDelimiters.display[1];
  }

  return fragment;
}
/* harmony default export */ var katex2tex = (katexReplaceWithTex);
;// CONCATENATED MODULE: ./contrib/copy-tex/copy-tex.js
 // Return <div class="katex"> element containing node, or null if not found.

function closestKatex(node) {
  // If node is a Text Node, for example, go up to containing Element,
  // where we can apply the `closest` method.
  var element = node instanceof Element ? node : node.parentElement;
  return element && element.closest('.katex');
} // Global copy handler to modify behavior on/within .katex elements.


document.addEventListener('copy', function (event) {
  var selection = window.getSelection();

  if (selection.isCollapsed || !event.clipboardData) {
    return; // default action OK if selection is empty or unchangeable
  }

  var clipboardData = event.clipboardData;
  var range = selection.getRangeAt(0); // When start point is within a formula, expand to entire formula.

  var startKatex = closestKatex(range.startContainer);

  if (startKatex) {
    range.setStartBefore(startKatex);
  } // Similarly, when end point is within a formula, expand to entire formula.


  var endKatex = closestKatex(range.endContainer);

  if (endKatex) {
    range.setEndAfter(endKatex);
  }

  var fragment = range.cloneContents();

  if (!fragment.querySelector('.katex-mathml')) {
    return; // default action OK if no .katex-mathml elements
  }

  var htmlContents = Array.prototype.map.call(fragment.childNodes, function (el) {
    return el instanceof Text ? el.textContent : el.outerHTML;
  }).join(''); // Preserve usual HTML copy/paste behavior.

  clipboardData.setData('text/html', htmlContents); // Rewrite plain-text version.

  clipboardData.setData('text/plain', katex2tex(fragment).textContent); // Prevent normal copy handling.

  event.preventDefault();
});
__webpack_exports__ = __webpack_exports__["default"];
/******/ 	return __webpack_exports__;
/******/ })()
;
});
copy-tex.min.css
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/copy-tex.min.css'
View Content
.katex,.katex-display{-webkit-user-select:all;-moz-user-select:all;-ms-user-select:all;user-select:all}
copy-tex.min.js
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/copy-tex.min.js'
View Content
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var n=t();for(var r in n)("object"==typeof exports?exports:e)[r]=n[r]}}("undefined"!=typeof self?self:this,(function(){return function(){"use strict";var e={},t={inline:["$","$"],display:["$$","$$"]};var n=function(e,n){void 0===n&&(n=t);for(var r=e.querySelectorAll(".katex-mathml + .katex-html"),a=0;a<r.length;a++){var o=r[a];o.remove?o.remove():o.parentNode&&o.parentNode.removeChild(o)}for(var i=e.querySelectorAll(".katex-mathml"),l=0;l<i.length;l++){var f=i[l],c=f.querySelector("annotation");c&&(f.replaceWith?f.replaceWith(c):f.parentNode&&f.parentNode.replaceChild(c,f),c.innerHTML=n.inline[0]+c.innerHTML+n.inline[1])}for(var d=e.querySelectorAll(".katex-display annotation"),s=0;s<d.length;s++){var p=d[s];p.innerHTML=n.display[0]+p.innerHTML.substr(n.inline[0].length,p.innerHTML.length-n.inline[0].length-n.inline[1].length)+n.display[1]}return e};function r(e){var t=e instanceof Element?e:e.parentElement;return t&&t.closest(".katex")}return document.addEventListener("copy",(function(e){var t=window.getSelection();if(!t.isCollapsed&&e.clipboardData){var a=e.clipboardData,o=t.getRangeAt(0),i=r(o.startContainer);i&&o.setStartBefore(i);var l=r(o.endContainer);l&&o.setEndAfter(l);var f=o.cloneContents();if(f.querySelector(".katex-mathml")){var c=Array.prototype.map.call(f.childNodes,(function(e){return e instanceof Text?e.textContent:e.outerHTML})).join("");a.setData("text/html",c),a.setData("text/plain",n(f).textContent),e.preventDefault()}}})),e=e.default}()}));
copy-tex.mjs
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/copy-tex.mjs'
View Content
// Set these to how you want inline and display math to be delimited.
var defaultCopyDelimiters = {
  inline: ['$', '$'],
  // alternative: ['\(', '\)']
  display: ['$$', '$$'] // alternative: ['\[', '\]']

}; // Replace .katex elements with their TeX source (<annotation> element).
// Modifies fragment in-place.  Useful for writing your own 'copy' handler,
// as in copy-tex.js.

function katexReplaceWithTex(fragment, copyDelimiters) {
  if (copyDelimiters === void 0) {
    copyDelimiters = defaultCopyDelimiters;
  }

  // Remove .katex-html blocks that are preceded by .katex-mathml blocks
  // (which will get replaced below).
  var katexHtml = fragment.querySelectorAll('.katex-mathml + .katex-html');

  for (var i = 0; i < katexHtml.length; i++) {
    var element = katexHtml[i];

    if (element.remove) {
      element.remove();
    } else if (element.parentNode) {
      element.parentNode.removeChild(element);
    }
  } // Replace .katex-mathml elements with their annotation (TeX source)
  // descendant, with inline delimiters.


  var katexMathml = fragment.querySelectorAll('.katex-mathml');

  for (var _i = 0; _i < katexMathml.length; _i++) {
    var _element = katexMathml[_i];

    var texSource = _element.querySelector('annotation');

    if (texSource) {
      if (_element.replaceWith) {
        _element.replaceWith(texSource);
      } else if (_element.parentNode) {
        _element.parentNode.replaceChild(texSource, _element);
      }

      texSource.innerHTML = copyDelimiters.inline[0] + texSource.innerHTML + copyDelimiters.inline[1];
    }
  } // Switch display math to display delimiters.


  var displays = fragment.querySelectorAll('.katex-display annotation');

  for (var _i2 = 0; _i2 < displays.length; _i2++) {
    var _element2 = displays[_i2];
    _element2.innerHTML = copyDelimiters.display[0] + _element2.innerHTML.substr(copyDelimiters.inline[0].length, _element2.innerHTML.length - copyDelimiters.inline[0].length - copyDelimiters.inline[1].length) + copyDelimiters.display[1];
  }

  return fragment;
}

function closestKatex(node) {
  // If node is a Text Node, for example, go up to containing Element,
  // where we can apply the `closest` method.
  var element = node instanceof Element ? node : node.parentElement;
  return element && element.closest('.katex');
} // Global copy handler to modify behavior on/within .katex elements.


document.addEventListener('copy', function (event) {
  var selection = window.getSelection();

  if (selection.isCollapsed || !event.clipboardData) {
    return; // default action OK if selection is empty or unchangeable
  }

  var clipboardData = event.clipboardData;
  var range = selection.getRangeAt(0); // When start point is within a formula, expand to entire formula.

  var startKatex = closestKatex(range.startContainer);

  if (startKatex) {
    range.setStartBefore(startKatex);
  } // Similarly, when end point is within a formula, expand to entire formula.


  var endKatex = closestKatex(range.endContainer);

  if (endKatex) {
    range.setEndAfter(endKatex);
  }

  var fragment = range.cloneContents();

  if (!fragment.querySelector('.katex-mathml')) {
    return; // default action OK if no .katex-mathml elements
  }

  var htmlContents = Array.prototype.map.call(fragment.childNodes, el => el instanceof Text ? el.textContent : el.outerHTML).join(''); // Preserve usual HTML copy/paste behavior.

  clipboardData.setData('text/html', htmlContents); // Rewrite plain-text version.

  clipboardData.setData('text/plain', katexReplaceWithTex(fragment).textContent); // Prevent normal copy handling.

  event.preventDefault();
});
mathtex-script-type.js
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/mathtex-script-type.js'
View Content
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory(require("katex"));
	else if(typeof define === 'function' && define.amd)
		define(["katex"], factory);
	else {
		var a = typeof exports === 'object' ? factory(require("katex")) : factory(root["katex"]);
		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
	}
})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__771__) {
return /******/ (function() { // webpackBootstrap
/******/ 	"use strict";
/******/ 	var __webpack_modules__ = ({

/***/ 771:
/***/ (function(module) {

module.exports = __WEBPACK_EXTERNAL_MODULE__771__;

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	!function() {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = function(module) {
/******/ 			var getter = module && module.__esModule ?
/******/ 				function() { return module['default']; } :
/******/ 				function() { return module; };
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
/******/ 		};
/******/ 	}();
/******/ 	
/******/ 	/* webpack/runtime/define property getters */
/******/ 	!function() {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = function(exports, definition) {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	}();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	!function() {
/******/ 		__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ 	}();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
!function() {
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(771);
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(katex__WEBPACK_IMPORTED_MODULE_0__);

var scripts = document.body.getElementsByTagName("script");
scripts = Array.prototype.slice.call(scripts);
scripts.forEach(function (script) {
  if (!script.type || !script.type.match(/math\/tex/i)) {
    return -1;
  }

  var display = script.type.match(/mode\s*=\s*display(;|\s|\n|$)/) != null;
  var katexElement = document.createElement(display ? "div" : "span");
  katexElement.setAttribute("class", display ? "equation" : "inline-equation");

  try {
    katex__WEBPACK_IMPORTED_MODULE_0___default().render(script.text, katexElement, {
      displayMode: display
    });
  } catch (err) {
    //console.error(err); linter doesn't like this
    katexElement.textContent = script.text;
  }

  script.parentNode.replaceChild(katexElement, script);
});
}();
__webpack_exports__ = __webpack_exports__["default"];
/******/ 	return __webpack_exports__;
/******/ })()
;
});
mathtex-script-type.min.js
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/mathtex-script-type.min.js'
View Content
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("katex"));else if("function"==typeof define&&define.amd)define(["katex"],t);else{var r="object"==typeof exports?t(require("katex")):t(e.katex);for(var n in r)("object"==typeof exports?exports:e)[n]=r[n]}}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={771:function(t){t.exports=e}},r={};function n(e){var o=r[e];if(void 0!==o)return o.exports;var i=r[e]={exports:{}};return t[e](i,i.exports,n),i.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var o,i,a,u={};return o=n(771),i=n.n(o),a=document.body.getElementsByTagName("script"),(a=Array.prototype.slice.call(a)).forEach((function(e){if(!e.type||!e.type.match(/math\/tex/i))return-1;var t=null!=e.type.match(/mode\s*=\s*display(;|\s|\n|$)/),r=document.createElement(t?"div":"span");r.setAttribute("class",t?"equation":"inline-equation");try{i().render(e.text,r,{displayMode:t})}catch(t){r.textContent=e.text}e.parentNode.replaceChild(r,e)})),u=u.default}()}));
mathtex-script-type.mjs
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/mathtex-script-type.mjs'
View Content
import katex from '../katex.mjs';

var scripts = document.body.getElementsByTagName("script");
scripts = Array.prototype.slice.call(scripts);
scripts.forEach(function (script) {
  if (!script.type || !script.type.match(/math\/tex/i)) {
    return -1;
  }

  var display = script.type.match(/mode\s*=\s*display(;|\s|\n|$)/) != null;
  var katexElement = document.createElement(display ? "div" : "span");
  katexElement.setAttribute("class", display ? "equation" : "inline-equation");

  try {
    katex.render(script.text, katexElement, {
      displayMode: display
    });
  } catch (err) {
    //console.error(err); linter doesn't like this
    katexElement.textContent = script.text;
  }

  script.parentNode.replaceChild(katexElement, script);
});
mhchem.js
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/mhchem.js'
View Content
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory(require("katex"));
	else if(typeof define === 'function' && define.amd)
		define(["katex"], factory);
	else {
		var a = typeof exports === 'object' ? factory(require("katex")) : factory(root["katex"]);
		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
	}
})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__771__) {
return /******/ (function() { // webpackBootstrap
/******/ 	"use strict";
/******/ 	var __webpack_modules__ = ({

/***/ 771:
/***/ (function(module) {

module.exports = __WEBPACK_EXTERNAL_MODULE__771__;

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	!function() {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = function(module) {
/******/ 			var getter = module && module.__esModule ?
/******/ 				function() { return module['default']; } :
/******/ 				function() { return module; };
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
/******/ 		};
/******/ 	}();
/******/ 	
/******/ 	/* webpack/runtime/define property getters */
/******/ 	!function() {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = function(exports, definition) {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	}();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	!function() {
/******/ 		__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ 	}();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
!function() {
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(771);
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(katex__WEBPACK_IMPORTED_MODULE_0__);
/* eslint-disable */

/* -*- Mode: JavaScript; indent-tabs-mode:nil; js-indent-level: 2 -*- */

/* vim: set ts=2 et sw=2 tw=80: */

/*************************************************************
 *
 *  KaTeX mhchem.js
 *
 *  This file implements a KaTeX version of mhchem version 3.3.0.
 *  It is adapted from MathJax/extensions/TeX/mhchem.js
 *  It differs from the MathJax version as follows:
 *    1. The interface is changed so that it can be called from KaTeX, not MathJax.
 *    2. \rlap and \llap are replaced with \mathrlap and \mathllap.
 *    3. Four lines of code are edited in order to use \raisebox instead of \raise.
 *    4. The reaction arrow code is simplified. All reaction arrows are rendered
 *       using KaTeX extensible arrows instead of building non-extensible arrows.
 *    5. \tripledash vertical alignment is slightly adjusted.
 *
 *    This code, as other KaTeX code, is released under the MIT license.
 * 
 * /*************************************************************
 *
 *  MathJax/extensions/TeX/mhchem.js
 *
 *  Implements the \ce command for handling chemical formulas
 *  from the mhchem LaTeX package.
 *
 *  ---------------------------------------------------------------------
 *
 *  Copyright (c) 2011-2015 The MathJax Consortium
 *  Copyright (c) 2015-2018 Martin Hensel
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
//
// Coding Style
//   - use '' for identifiers that can by minified/uglified
//   - use "" for strings that need to stay untouched
// version: "3.3.0" for MathJax and KaTeX
// Add \ce, \pu, and \tripledash to the KaTeX macros.
katex__WEBPACK_IMPORTED_MODULE_0___default().__defineMacro("\\ce", function (context) {
  return chemParse(context.consumeArgs(1)[0], "ce");
});

katex__WEBPACK_IMPORTED_MODULE_0___default().__defineMacro("\\pu", function (context) {
  return chemParse(context.consumeArgs(1)[0], "pu");
}); //  Needed for \bond for the ~ forms
//  Raise by 2.56mu, not 2mu. We're raising a hyphen-minus, U+002D, not 
//  a mathematical minus, U+2212. So we need that extra 0.56.


katex__WEBPACK_IMPORTED_MODULE_0___default().__defineMacro("\\tripledash", "{\\vphantom{-}\\raisebox{2.56mu}{$\\mkern2mu" + "\\tiny\\text{-}\\mkern1mu\\text{-}\\mkern1mu\\text{-}\\mkern2mu$}}");

 //
//  This is the main function for handing the \ce and \pu commands.
//  It takes the argument to \ce or \pu and returns the corresponding TeX string.
//

var chemParse = function chemParse(tokens, stateMachine) {
  // Recreate the argument string from KaTeX's array of tokens.
  var str = "";
  var expectedLoc = tokens.length && tokens[tokens.length - 1].loc.start;

  for (var i = tokens.length - 1; i >= 0; i--) {
    if (tokens[i].loc.start > expectedLoc) {
      // context.consumeArgs has eaten a space.
      str += " ";
      expectedLoc = tokens[i].loc.start;
    }

    str += tokens[i].text;
    expectedLoc += tokens[i].text.length;
  }

  var tex = texify.go(mhchemParser.go(str, stateMachine));
  return tex;
}; //
// Core parser for mhchem syntax  (recursive)
//

/** @type {MhchemParser} */


var mhchemParser = {
  //
  // Parses mchem \ce syntax
  //
  // Call like
  //   go("H2O");
  //
  go: function go(input, stateMachine) {
    if (!input) {
      return [];
    }

    if (stateMachine === undefined) {
      stateMachine = 'ce';
    }

    var state = '0'; //
    // String buffers for parsing:
    //
    // buffer.a == amount
    // buffer.o == element
    // buffer.b == left-side superscript
    // buffer.p == left-side subscript
    // buffer.q == right-side subscript
    // buffer.d == right-side superscript
    //
    // buffer.r == arrow
    // buffer.rdt == arrow, script above, type
    // buffer.rd == arrow, script above, content
    // buffer.rqt == arrow, script below, type
    // buffer.rq == arrow, script below, content
    //
    // buffer.text_
    // buffer.rm
    // etc.
    //
    // buffer.parenthesisLevel == int, starting at 0
    // buffer.sb == bool, space before
    // buffer.beginsWithBond == bool
    //
    // These letters are also used as state names.
    //
    // Other states:
    // 0 == begin of main part (arrow/operator unlikely)
    // 1 == next entity
    // 2 == next entity (arrow/operator unlikely)
    // 3 == next atom
    // c == macro
    //

    /** @type {Buffer} */

    var buffer = {};
    buffer['parenthesisLevel'] = 0;
    input = input.replace(/\n/g, " ");
    input = input.replace(/[\u2212\u2013\u2014\u2010]/g, "-");
    input = input.replace(/[\u2026]/g, "..."); //
    // Looks through mhchemParser.transitions, to execute a matching action
    // (recursive)
    //

    var lastInput;
    var watchdog = 10;
    /** @type {ParserOutput[]} */

    var output = [];

    while (true) {
      if (lastInput !== input) {
        watchdog = 10;
        lastInput = input;
      } else {
        watchdog--;
      } //
      // Find actions in transition table
      //


      var machine = mhchemParser.stateMachines[stateMachine];
      var t = machine.transitions[state] || machine.transitions['*'];

      iterateTransitions: for (var i = 0; i < t.length; i++) {
        var matches = mhchemParser.patterns.match_(t[i].pattern, input);

        if (matches) {
          //
          // Execute actions
          //
          var task = t[i].task;

          for (var iA = 0; iA < task.action_.length; iA++) {
            var o; //
            // Find and execute action
            //

            if (machine.actions[task.action_[iA].type_]) {
              o = machine.actions[task.action_[iA].type_](buffer, matches.match_, task.action_[iA].option);
            } else if (mhchemParser.actions[task.action_[iA].type_]) {
              o = mhchemParser.actions[task.action_[iA].type_](buffer, matches.match_, task.action_[iA].option);
            } else {
              throw ["MhchemBugA", "mhchem bug A. Please report. (" + task.action_[iA].type_ + ")"]; // Trying to use non-existing action
            } //
            // Add output
            //


            mhchemParser.concatArray(output, o);
          } //
          // Set next state,
          // Shorten input,
          // Continue with next character
          //   (= apply only one transition per position)
          //


          state = task.nextState || state;

          if (input.length > 0) {
            if (!task.revisit) {
              input = matches.remainder;
            }

            if (!task.toContinue) {
              break iterateTransitions;
            }
          } else {
            return output;
          }
        }
      } //
      // Prevent infinite loop
      //


      if (watchdog <= 0) {
        throw ["MhchemBugU", "mhchem bug U. Please report."]; // Unexpected character
      }
    }
  },
  concatArray: function concatArray(a, b) {
    if (b) {
      if (Array.isArray(b)) {
        for (var iB = 0; iB < b.length; iB++) {
          a.push(b[iB]);
        }
      } else {
        a.push(b);
      }
    }
  },
  patterns: {
    //
    // Matching patterns
    // either regexps or function that return null or {match_:"a", remainder:"bc"}
    //
    patterns: {
      // property names must not look like integers ("2") for correct property traversal order, later on
      'empty': /^$/,
      'else': /^./,
      'else2': /^./,
      'space': /^\s/,
      'space A': /^\s(?=[A-Z\\$])/,
      'space$': /^\s$/,
      'a-z': /^[a-z]/,
      'x': /^x/,
      'x$': /^x$/,
      'i$': /^i$/,
      'letters': /^(?:[a-zA-Z\u03B1-\u03C9\u0391-\u03A9?@]|(?:\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))))+/,
      '\\greek': /^\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))/,
      'one lowercase latin letter $': /^(?:([a-z])(?:$|[^a-zA-Z]))$/,
      '$one lowercase latin letter$ $': /^\$(?:([a-z])(?:$|[^a-zA-Z]))\$$/,
      'one lowercase greek letter $': /^(?:\$?[\u03B1-\u03C9]\$?|\$?\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega)\s*\$?)(?:\s+|\{\}|(?![a-zA-Z]))$/,
      'digits': /^[0-9]+/,
      '-9.,9': /^[+\-]?(?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))/,
      '-9.,9 no missing 0': /^[+\-]?[0-9]+(?:[.,][0-9]+)?/,
      '(-)(9.,9)(e)(99)': function e99(input) {
        var m = input.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))?(\((?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))\))?(?:([eE]|\s*(\*|x|\\times|\u00D7)\s*10\^)([+\-]?[0-9]+|\{[+\-]?[0-9]+\}))?/);

        if (m && m[0]) {
          return {
            match_: m.splice(1),
            remainder: input.substr(m[0].length)
          };
        }

        return null;
      },
      '(-)(9)^(-9)': function _(input) {
        var m = input.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+)?)\^([+\-]?[0-9]+|\{[+\-]?[0-9]+\})/);

        if (m && m[0]) {
          return {
            match_: m.splice(1),
            remainder: input.substr(m[0].length)
          };
        }

        return null;
      },
      'state of aggregation $': function stateOfAggregation$(input) {
        // ... or crystal system
        var a = mhchemParser.patterns.findObserveGroups(input, "", /^\([a-z]{1,3}(?=[\),])/, ")", ""); // (aq), (aq,$\infty$), (aq, sat)

        if (a && a.remainder.match(/^($|[\s,;\)\]\}])/)) {
          return a;
        } //  AND end of 'phrase'


        var m = input.match(/^(?:\((?:\\ca\s?)?\$[amothc]\$\))/); // OR crystal system ($o$) (\ca$c$)

        if (m) {
          return {
            match_: m[0],
            remainder: input.substr(m[0].length)
          };
        }

        return null;
      },
      '_{(state of aggregation)}$': /^_\{(\([a-z]{1,3}\))\}/,
      '{[(': /^(?:\\\{|\[|\()/,
      ')]}': /^(?:\)|\]|\\\})/,
      ', ': /^[,;]\s*/,
      ',': /^[,;]/,
      '.': /^[.]/,
      '. ': /^([.\u22C5\u00B7\u2022])\s*/,
      '...': /^\.\.\.(?=$|[^.])/,
      '* ': /^([*])\s*/,
      '^{(...)}': function _(input) {
        return mhchemParser.patterns.findObserveGroups(input, "^{", "", "", "}");
      },
      '^($...$)': function $$(input) {
        return mhchemParser.patterns.findObserveGroups(input, "^", "$", "$", "");
      },
      '^a': /^\^([0-9]+|[^\\_])/,
      '^\\x{}{}': function x(input) {
        return mhchemParser.patterns.findObserveGroups(input, "^", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true);
      },
      '^\\x{}': function x(input) {
        return mhchemParser.patterns.findObserveGroups(input, "^", /^\\[a-zA-Z]+\{/, "}", "");
      },
      '^\\x': /^\^(\\[a-zA-Z]+)\s*/,
      '^(-1)': /^\^(-?\d+)/,
      '\'': /^'/,
      '_{(...)}': function _(input) {
        return mhchemParser.patterns.findObserveGroups(input, "_{", "", "", "}");
      },
      '_($...$)': function _$$(input) {
        return mhchemParser.patterns.findObserveGroups(input, "_", "$", "$", "");
      },
      '_9': /^_([+\-]?[0-9]+|[^\\])/,
      '_\\x{}{}': function _X(input) {
        return mhchemParser.patterns.findObserveGroups(input, "_", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true);
      },
      '_\\x{}': function _X(input) {
        return mhchemParser.patterns.findObserveGroups(input, "_", /^\\[a-zA-Z]+\{/, "}", "");
      },
      '_\\x': /^_(\\[a-zA-Z]+)\s*/,
      '^_': /^(?:\^(?=_)|\_(?=\^)|[\^_]$)/,
      '{}': /^\{\}/,
      '{...}': function _(input) {
        return mhchemParser.patterns.findObserveGroups(input, "", "{", "}", "");
      },
      '{(...)}': function _(input) {
        return mhchemParser.patterns.findObserveGroups(input, "{", "", "", "}");
      },
      '$...$': function $$(input) {
        return mhchemParser.patterns.findObserveGroups(input, "", "$", "$", "");
      },
      '${(...)}$': function $$(input) {
        return mhchemParser.patterns.findObserveGroups(input, "${", "", "", "}$");
      },
      '$(...)$': function $$(input) {
        return mhchemParser.patterns.findObserveGroups(input, "$", "", "", "$");
      },
      '=<>': /^[=<>]/,
      '#': /^[#\u2261]/,
      '+': /^\+/,
      '-$': /^-(?=[\s_},;\]/]|$|\([a-z]+\))/,
      // -space -, -; -] -/ -$ -state-of-aggregation
      '-9': /^-(?=[0-9])/,
      '- orbital overlap': /^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/,
      '-': /^-/,
      'pm-operator': /^(?:\\pm|\$\\pm\$|\+-|\+\/-)/,
      'operator': /^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/,
      'arrowUpDown': /^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/,
      '\\bond{(...)}': function bond(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\bond{", "", "", "}");
      },
      '->': /^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/,
      'CMT': /^[CMT](?=\[)/,
      '[(...)]': function _(input) {
        return mhchemParser.patterns.findObserveGroups(input, "[", "", "", "]");
      },
      '1st-level escape': /^(&|\\\\|\\hline)\s*/,
      '\\,': /^(?:\\[,\ ;:])/,
      // \\x - but output no space before
      '\\x{}{}': function x(input) {
        return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true);
      },
      '\\x{}': function x(input) {
        return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", "");
      },
      '\\ca': /^\\ca(?:\s+|(?![a-zA-Z]))/,
      '\\x': /^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/,
      'orbital': /^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/,
      // only those with numbers in front, because the others will be formatted correctly anyway
      'others': /^[\/~|]/,
      '\\frac{(...)}': function frac(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\frac{", "", "", "}", "{", "", "", "}");
      },
      '\\overset{(...)}': function overset(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\overset{", "", "", "}", "{", "", "", "}");
      },
      "\\underset{(...)}": function underset(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\underset{", "", "", "}", "{", "", "", "}");
      },
      "\\underbrace{(...)}": function underbrace(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\underbrace{", "", "", "}_", "{", "", "", "}");
      },
      '\\color{(...)}0': function color0(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}");
      },
      '\\color{(...)}{(...)}1': function color1(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}", "{", "", "", "}");
      },
      '\\color(...){(...)}2': function color2(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\color", "\\", "", /^(?=\{)/, "{", "", "", "}");
      },
      '\\ce{(...)}': function ce(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\ce{", "", "", "}");
      },
      'oxidation$': /^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,
      'd-oxidation$': /^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,
      // 0 could be oxidation or charge
      'roman numeral': /^[IVX]+/,
      '1/2$': /^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/,
      'amount': function amount(input) {
        var match; // e.g. 2, 0.5, 1/2, -2, n/2, +;  $a$ could be added later in parsing

        match = input.match(/^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/);

        if (match) {
          return {
            match_: match[0],
            remainder: input.substr(match[0].length)
          };
        }

        var a = mhchemParser.patterns.findObserveGroups(input, "", "$", "$", "");

        if (a) {
          // e.g. $2n-1$, $-$
          match = a.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/);

          if (match) {
            return {
              match_: match[0],
              remainder: input.substr(match[0].length)
            };
          }
        }

        return null;
      },
      'amount2': function amount2(input) {
        return this['amount'](input);
      },
      '(KV letters),': /^(?:[A-Z][a-z]{0,2}|i)(?=,)/,
      'formula$': function formula$(input) {
        if (input.match(/^\([a-z]+\)$/)) {
          return null;
        } // state of aggregation = no formula


        var match = input.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/);

        if (match) {
          return {
            match_: match[0],
            remainder: input.substr(match[0].length)
          };
        }

        return null;
      },
      'uprightEntities': /^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/,
      '/': /^\s*(\/)\s*/,
      '//': /^\s*(\/\/)\s*/,
      '*': /^\s*[*.]\s*/
    },
    findObserveGroups: function findObserveGroups(input, begExcl, begIncl, endIncl, endExcl, beg2Excl, beg2Incl, end2Incl, end2Excl, combine) {
      /** @type {{(input: string, pattern: string | RegExp): string | string[] | null;}} */
      var _match = function _match(input, pattern) {
        if (typeof pattern === "string") {
          if (input.indexOf(pattern) !== 0) {
            return null;
          }

          return pattern;
        } else {
          var match = input.match(pattern);

          if (!match) {
            return null;
          }

          return match[0];
        }
      };
      /** @type {{(input: string, i: number, endChars: string | RegExp): {endMatchBegin: number, endMatchEnd: number} | null;}} */


      var _findObserveGroups = function _findObserveGroups(input, i, endChars) {
        var braces = 0;

        while (i < input.length) {
          var a = input.charAt(i);

          var match = _match(input.substr(i), endChars);

          if (match !== null && braces === 0) {
            return {
              endMatchBegin: i,
              endMatchEnd: i + match.length
            };
          } else if (a === "{") {
            braces++;
          } else if (a === "}") {
            if (braces === 0) {
              throw ["ExtraCloseMissingOpen", "Extra close brace or missing open brace"];
            } else {
              braces--;
            }
          }

          i++;
        }

        if (braces > 0) {
          return null;
        }

        return null;
      };

      var match = _match(input, begExcl);

      if (match === null) {
        return null;
      }

      input = input.substr(match.length);
      match = _match(input, begIncl);

      if (match === null) {
        return null;
      }

      var e = _findObserveGroups(input, match.length, endIncl || endExcl);

      if (e === null) {
        return null;
      }

      var match1 = input.substring(0, endIncl ? e.endMatchEnd : e.endMatchBegin);

      if (!(beg2Excl || beg2Incl)) {
        return {
          match_: match1,
          remainder: input.substr(e.endMatchEnd)
        };
      } else {
        var group2 = this.findObserveGroups(input.substr(e.endMatchEnd), beg2Excl, beg2Incl, end2Incl, end2Excl);

        if (group2 === null) {
          return null;
        }
        /** @type {string[]} */


        var matchRet = [match1, group2.match_];
        return {
          match_: combine ? matchRet.join("") : matchRet,
          remainder: group2.remainder
        };
      }
    },
    //
    // Matching function
    // e.g. match("a", input) will look for the regexp called "a" and see if it matches
    // returns null or {match_:"a", remainder:"bc"}
    //
    match_: function match_(m, input) {
      var pattern = mhchemParser.patterns.patterns[m];

      if (pattern === undefined) {
        throw ["MhchemBugP", "mhchem bug P. Please report. (" + m + ")"]; // Trying to use non-existing pattern
      } else if (typeof pattern === "function") {
        return mhchemParser.patterns.patterns[m](input); // cannot use cached var pattern here, because some pattern functions need this===mhchemParser
      } else {
        // RegExp
        var match = input.match(pattern);

        if (match) {
          var mm;

          if (match[2]) {
            mm = [match[1], match[2]];
          } else if (match[1]) {
            mm = match[1];
          } else {
            mm = match[0];
          }

          return {
            match_: mm,
            remainder: input.substr(match[0].length)
          };
        }

        return null;
      }
    }
  },
  //
  // Generic state machine actions
  //
  actions: {
    'a=': function a(buffer, m) {
      buffer.a = (buffer.a || "") + m;
    },
    'b=': function b(buffer, m) {
      buffer.b = (buffer.b || "") + m;
    },
    'p=': function p(buffer, m) {
      buffer.p = (buffer.p || "") + m;
    },
    'o=': function o(buffer, m) {
      buffer.o = (buffer.o || "") + m;
    },
    'q=': function q(buffer, m) {
      buffer.q = (buffer.q || "") + m;
    },
    'd=': function d(buffer, m) {
      buffer.d = (buffer.d || "") + m;
    },
    'rm=': function rm(buffer, m) {
      buffer.rm = (buffer.rm || "") + m;
    },
    'text=': function text(buffer, m) {
      buffer.text_ = (buffer.text_ || "") + m;
    },
    'insert': function insert(buffer, m, a) {
      return {
        type_: a
      };
    },
    'insert+p1': function insertP1(buffer, m, a) {
      return {
        type_: a,
        p1: m
      };
    },
    'insert+p1+p2': function insertP1P2(buffer, m, a) {
      return {
        type_: a,
        p1: m[0],
        p2: m[1]
      };
    },
    'copy': function copy(buffer, m) {
      return m;
    },
    'rm': function rm(buffer, m) {
      return {
        type_: 'rm',
        p1: m || ""
      };
    },
    'text': function text(buffer, m) {
      return mhchemParser.go(m, 'text');
    },
    '{text}': function text(buffer, m) {
      var ret = ["{"];
      mhchemParser.concatArray(ret, mhchemParser.go(m, 'text'));
      ret.push("}");
      return ret;
    },
    'tex-math': function texMath(buffer, m) {
      return mhchemParser.go(m, 'tex-math');
    },
    'tex-math tight': function texMathTight(buffer, m) {
      return mhchemParser.go(m, 'tex-math tight');
    },
    'bond': function bond(buffer, m, k) {
      return {
        type_: 'bond',
        kind_: k || m
      };
    },
    'color0-output': function color0Output(buffer, m) {
      return {
        type_: 'color0',
        color: m[0]
      };
    },
    'ce': function ce(buffer, m) {
      return mhchemParser.go(m);
    },
    '1/2': function _(buffer, m) {
      /** @type {ParserOutput[]} */
      var ret = [];

      if (m.match(/^[+\-]/)) {
        ret.push(m.substr(0, 1));
        m = m.substr(1);
      }

      var n = m.match(/^([0-9]+|\$[a-z]\$|[a-z])\/([0-9]+)(\$[a-z]\$|[a-z])?$/);
      n[1] = n[1].replace(/\$/g, "");
      ret.push({
        type_: 'frac',
        p1: n[1],
        p2: n[2]
      });

      if (n[3]) {
        n[3] = n[3].replace(/\$/g, "");
        ret.push({
          type_: 'tex-math',
          p1: n[3]
        });
      }

      return ret;
    },
    '9,9': function _(buffer, m) {
      return mhchemParser.go(m, '9,9');
    }
  },
  //
  // createTransitions
  // convert  { 'letter': { 'state': { action_: 'output' } } }  to  { 'state' => [ { pattern: 'letter', task: { action_: [{type_: 'output'}] } } ] }
  // with expansion of 'a|b' to 'a' and 'b' (at 2 places)
  //
  createTransitions: function createTransitions(o) {
    var pattern, state;
    /** @type {string[]} */

    var stateArray;
    var i; //
    // 1. Collect all states
    //

    /** @type {Transitions} */

    var transitions = {};

    for (pattern in o) {
      for (state in o[pattern]) {
        stateArray = state.split("|");
        o[pattern][state].stateArray = stateArray;

        for (i = 0; i < stateArray.length; i++) {
          transitions[stateArray[i]] = [];
        }
      }
    } //
    // 2. Fill states
    //


    for (pattern in o) {
      for (state in o[pattern]) {
        stateArray = o[pattern][state].stateArray || [];

        for (i = 0; i < stateArray.length; i++) {
          //
          // 2a. Normalize actions into array:  'text=' ==> [{type_:'text='}]
          // (Note to myself: Resolving the function here would be problematic. It would need .bind (for *this*) and currying (for *option*).)
          //

          /** @type {any} */
          var p = o[pattern][state];

          if (p.action_) {
            p.action_ = [].concat(p.action_);

            for (var k = 0; k < p.action_.length; k++) {
              if (typeof p.action_[k] === "string") {
                p.action_[k] = {
                  type_: p.action_[k]
                };
              }
            }
          } else {
            p.action_ = [];
          } //
          // 2.b Multi-insert
          //


          var patternArray = pattern.split("|");

          for (var j = 0; j < patternArray.length; j++) {
            if (stateArray[i] === '*') {
              // insert into all
              for (var t in transitions) {
                transitions[t].push({
                  pattern: patternArray[j],
                  task: p
                });
              }
            } else {
              transitions[stateArray[i]].push({
                pattern: patternArray[j],
                task: p
              });
            }
          }
        }
      }
    }

    return transitions;
  },
  stateMachines: {}
}; //
// Definition of state machines
//

mhchemParser.stateMachines = {
  //
  // \ce state machines
  //
  //#region ce
  'ce': {
    // main parser
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {
          action_: 'output'
        }
      },
      'else': {
        '0|1|2': {
          action_: 'beginsWithBond=false',
          revisit: true,
          toContinue: true
        }
      },
      'oxidation$': {
        '0': {
          action_: 'oxidation-output'
        }
      },
      'CMT': {
        'r': {
          action_: 'rdt=',
          nextState: 'rt'
        },
        'rd': {
          action_: 'rqt=',
          nextState: 'rdt'
        }
      },
      'arrowUpDown': {
        '0|1|2|as': {
          action_: ['sb=false', 'output', 'operator'],
          nextState: '1'
        }
      },
      'uprightEntities': {
        '0|1|2': {
          action_: ['o=', 'output'],
          nextState: '1'
        }
      },
      'orbital': {
        '0|1|2|3': {
          action_: 'o=',
          nextState: 'o'
        }
      },
      '->': {
        '0|1|2|3': {
          action_: 'r=',
          nextState: 'r'
        },
        'a|as': {
          action_: ['output', 'r='],
          nextState: 'r'
        },
        '*': {
          action_: ['output', 'r='],
          nextState: 'r'
        }
      },
      '+': {
        'o': {
          action_: 'd= kv',
          nextState: 'd'
        },
        'd|D': {
          action_: 'd=',
          nextState: 'd'
        },
        'q': {
          action_: 'd=',
          nextState: 'qd'
        },
        'qd|qD': {
          action_: 'd=',
          nextState: 'qd'
        },
        'dq': {
          action_: ['output', 'd='],
          nextState: 'd'
        },
        '3': {
          action_: ['sb=false', 'output', 'operator'],
          nextState: '0'
        }
      },
      'amount': {
        '0|2': {
          action_: 'a=',
          nextState: 'a'
        }
      },
      'pm-operator': {
        '0|1|2|a|as': {
          action_: ['sb=false', 'output', {
            type_: 'operator',
            option: '\\pm'
          }],
          nextState: '0'
        }
      },
      'operator': {
        '0|1|2|a|as': {
          action_: ['sb=false', 'output', 'operator'],
          nextState: '0'
        }
      },
      '-$': {
        'o|q': {
          action_: ['charge or bond', 'output'],
          nextState: 'qd'
        },
        'd': {
          action_: 'd=',
          nextState: 'd'
        },
        'D': {
          action_: ['output', {
            type_: 'bond',
            option: "-"
          }],
          nextState: '3'
        },
        'q': {
          action_: 'd=',
          nextState: 'qd'
        },
        'qd': {
          action_: 'd=',
          nextState: 'qd'
        },
        'qD|dq': {
          action_: ['output', {
            type_: 'bond',
            option: "-"
          }],
          nextState: '3'
        }
      },
      '-9': {
        '3|o': {
          action_: ['output', {
            type_: 'insert',
            option: 'hyphen'
          }],
          nextState: '3'
        }
      },
      '- orbital overlap': {
        'o': {
          action_: ['output', {
            type_: 'insert',
            option: 'hyphen'
          }],
          nextState: '2'
        },
        'd': {
          action_: ['output', {
            type_: 'insert',
            option: 'hyphen'
          }],
          nextState: '2'
        }
      },
      '-': {
        '0|1|2': {
          action_: [{
            type_: 'output',
            option: 1
          }, 'beginsWithBond=true', {
            type_: 'bond',
            option: "-"
          }],
          nextState: '3'
        },
        '3': {
          action_: {
            type_: 'bond',
            option: "-"
          }
        },
        'a': {
          action_: ['output', {
            type_: 'insert',
            option: 'hyphen'
          }],
          nextState: '2'
        },
        'as': {
          action_: [{
            type_: 'output',
            option: 2
          }, {
            type_: 'bond',
            option: "-"
          }],
          nextState: '3'
        },
        'b': {
          action_: 'b='
        },
        'o': {
          action_: {
            type_: '- after o/d',
            option: false
          },
          nextState: '2'
        },
        'q': {
          action_: {
            type_: '- after o/d',
            option: false
          },
          nextState: '2'
        },
        'd|qd|dq': {
          action_: {
            type_: '- after o/d',
            option: true
          },
          nextState: '2'
        },
        'D|qD|p': {
          action_: ['output', {
            type_: 'bond',
            option: "-"
          }],
          nextState: '3'
        }
      },
      'amount2': {
        '1|3': {
          action_: 'a=',
          nextState: 'a'
        }
      },
      'letters': {
        '0|1|2|3|a|as|b|p|bp|o': {
          action_: 'o=',
          nextState: 'o'
        },
        'q|dq': {
          action_: ['output', 'o='],
          nextState: 'o'
        },
        'd|D|qd|qD': {
          action_: 'o after d',
          nextState: 'o'
        }
      },
      'digits': {
        'o': {
          action_: 'q=',
          nextState: 'q'
        },
        'd|D': {
          action_: 'q=',
          nextState: 'dq'
        },
        'q': {
          action_: ['output', 'o='],
          nextState: 'o'
        },
        'a': {
          action_: 'o=',
          nextState: 'o'
        }
      },
      'space A': {
        'b|p|bp': {}
      },
      'space': {
        'a': {
          nextState: 'as'
        },
        '0': {
          action_: 'sb=false'
        },
        '1|2': {
          action_: 'sb=true'
        },
        'r|rt|rd|rdt|rdq': {
          action_: 'output',
          nextState: '0'
        },
        '*': {
          action_: ['output', 'sb=true'],
          nextState: '1'
        }
      },
      '1st-level escape': {
        '1|2': {
          action_: ['output', {
            type_: 'insert+p1',
            option: '1st-level escape'
          }]
        },
        '*': {
          action_: ['output', {
            type_: 'insert+p1',
            option: '1st-level escape'
          }],
          nextState: '0'
        }
      },
      '[(...)]': {
        'r|rt': {
          action_: 'rd=',
          nextState: 'rd'
        },
        'rd|rdt': {
          action_: 'rq=',
          nextState: 'rdq'
        }
      },
      '...': {
        'o|d|D|dq|qd|qD': {
          action_: ['output', {
            type_: 'bond',
            option: "..."
          }],
          nextState: '3'
        },
        '*': {
          action_: [{
            type_: 'output',
            option: 1
          }, {
            type_: 'insert',
            option: 'ellipsis'
          }],
          nextState: '1'
        }
      },
      '. |* ': {
        '*': {
          action_: ['output', {
            type_: 'insert',
            option: 'addition compound'
          }],
          nextState: '1'
        }
      },
      'state of aggregation $': {
        '*': {
          action_: ['output', 'state of aggregation'],
          nextState: '1'
        }
      },
      '{[(': {
        'a|as|o': {
          action_: ['o=', 'output', 'parenthesisLevel++'],
          nextState: '2'
        },
        '0|1|2|3': {
          action_: ['o=', 'output', 'parenthesisLevel++'],
          nextState: '2'
        },
        '*': {
          action_: ['output', 'o=', 'output', 'parenthesisLevel++'],
          nextState: '2'
        }
      },
      ')]}': {
        '0|1|2|3|b|p|bp|o': {
          action_: ['o=', 'parenthesisLevel--'],
          nextState: 'o'
        },
        'a|as|d|D|q|qd|qD|dq': {
          action_: ['output', 'o=', 'parenthesisLevel--'],
          nextState: 'o'
        }
      },
      ', ': {
        '*': {
          action_: ['output', 'comma'],
          nextState: '0'
        }
      },
      '^_': {
        // ^ and _ without a sensible argument
        '*': {}
      },
      '^{(...)}|^($...$)': {
        '0|1|2|as': {
          action_: 'b=',
          nextState: 'b'
        },
        'p': {
          action_: 'b=',
          nextState: 'bp'
        },
        '3|o': {
          action_: 'd= kv',
          nextState: 'D'
        },
        'q': {
          action_: 'd=',
          nextState: 'qD'
        },
        'd|D|qd|qD|dq': {
          action_: ['output', 'd='],
          nextState: 'D'
        }
      },
      '^a|^\\x{}{}|^\\x{}|^\\x|\'': {
        '0|1|2|as': {
          action_: 'b=',
          nextState: 'b'
        },
        'p': {
          action_: 'b=',
          nextState: 'bp'
        },
        '3|o': {
          action_: 'd= kv',
          nextState: 'd'
        },
        'q': {
          action_: 'd=',
          nextState: 'qd'
        },
        'd|qd|D|qD': {
          action_: 'd='
        },
        'dq': {
          action_: ['output', 'd='],
          nextState: 'd'
        }
      },
      '_{(state of aggregation)}$': {
        'd|D|q|qd|qD|dq': {
          action_: ['output', 'q='],
          nextState: 'q'
        }
      },
      '_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x': {
        '0|1|2|as': {
          action_: 'p=',
          nextState: 'p'
        },
        'b': {
          action_: 'p=',
          nextState: 'bp'
        },
        '3|o': {
          action_: 'q=',
          nextState: 'q'
        },
        'd|D': {
          action_: 'q=',
          nextState: 'dq'
        },
        'q|qd|qD|dq': {
          action_: ['output', 'q='],
          nextState: 'q'
        }
      },
      '=<>': {
        '0|1|2|3|a|as|o|q|d|D|qd|qD|dq': {
          action_: [{
            type_: 'output',
            option: 2
          }, 'bond'],
          nextState: '3'
        }
      },
      '#': {
        '0|1|2|3|a|as|o': {
          action_: [{
            type_: 'output',
            option: 2
          }, {
            type_: 'bond',
            option: "#"
          }],
          nextState: '3'
        }
      },
      '{}': {
        '*': {
          action_: {
            type_: 'output',
            option: 1
          },
          nextState: '1'
        }
      },
      '{...}': {
        '0|1|2|3|a|as|b|p|bp': {
          action_: 'o=',
          nextState: 'o'
        },
        'o|d|D|q|qd|qD|dq': {
          action_: ['output', 'o='],
          nextState: 'o'
        }
      },
      '$...$': {
        'a': {
          action_: 'a='
        },
        // 2$n$
        '0|1|2|3|as|b|p|bp|o': {
          action_: 'o=',
          nextState: 'o'
        },
        // not 'amount'
        'as|o': {
          action_: 'o='
        },
        'q|d|D|qd|qD|dq': {
          action_: ['output', 'o='],
          nextState: 'o'
        }
      },
      '\\bond{(...)}': {
        '*': {
          action_: [{
            type_: 'output',
            option: 2
          }, 'bond'],
          nextState: "3"
        }
      },
      '\\frac{(...)}': {
        '*': {
          action_: [{
            type_: 'output',
            option: 1
          }, 'frac-output'],
          nextState: '3'
        }
      },
      '\\overset{(...)}': {
        '*': {
          action_: [{
            type_: 'output',
            option: 2
          }, 'overset-output'],
          nextState: '3'
        }
      },
      "\\underset{(...)}": {
        '*': {
          action_: [{
            type_: 'output',
            option: 2
          }, 'underset-output'],
          nextState: '3'
        }
      },
      "\\underbrace{(...)}": {
        '*': {
          action_: [{
            type_: 'output',
            option: 2
          }, 'underbrace-output'],
          nextState: '3'
        }
      },
      '\\color{(...)}{(...)}1|\\color(...){(...)}2': {
        '*': {
          action_: [{
            type_: 'output',
            option: 2
          }, 'color-output'],
          nextState: '3'
        }
      },
      '\\color{(...)}0': {
        '*': {
          action_: [{
            type_: 'output',
            option: 2
          }, 'color0-output']
        }
      },
      '\\ce{(...)}': {
        '*': {
          action_: [{
            type_: 'output',
            option: 2
          }, 'ce'],
          nextState: '3'
        }
      },
      '\\,': {
        '*': {
          action_: [{
            type_: 'output',
            option: 1
          }, 'copy'],
          nextState: '1'
        }
      },
      '\\x{}{}|\\x{}|\\x': {
        '0|1|2|3|a|as|b|p|bp|o|c0': {
          action_: ['o=', 'output'],
          nextState: '3'
        },
        '*': {
          action_: ['output', 'o=', 'output'],
          nextState: '3'
        }
      },
      'others': {
        '*': {
          action_: [{
            type_: 'output',
            option: 1
          }, 'copy'],
          nextState: '3'
        }
      },
      'else2': {
        'a': {
          action_: 'a to o',
          nextState: 'o',
          revisit: true
        },
        'as': {
          action_: ['output', 'sb=true'],
          nextState: '1',
          revisit: true
        },
        'r|rt|rd|rdt|rdq': {
          action_: ['output'],
          nextState: '0',
          revisit: true
        },
        '*': {
          action_: ['output', 'copy'],
          nextState: '3'
        }
      }
    }),
    actions: {
      'o after d': function oAfterD(buffer, m) {
        var ret;

        if ((buffer.d || "").match(/^[0-9]+$/)) {
          var tmp = buffer.d;
          buffer.d = undefined;
          ret = this['output'](buffer);
          buffer.b = tmp;
        } else {
          ret = this['output'](buffer);
        }

        mhchemParser.actions['o='](buffer, m);
        return ret;
      },
      'd= kv': function dKv(buffer, m) {
        buffer.d = m;
        buffer.dType = 'kv';
      },
      'charge or bond': function chargeOrBond(buffer, m) {
        if (buffer['beginsWithBond']) {
          /** @type {ParserOutput[]} */
          var ret = [];
          mhchemParser.concatArray(ret, this['output'](buffer));
          mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-"));
          return ret;
        } else {
          buffer.d = m;
        }
      },
      '- after o/d': function afterOD(buffer, m, isAfterD) {
        var c1 = mhchemParser.patterns.match_('orbital', buffer.o || "");
        var c2 = mhchemParser.patterns.match_('one lowercase greek letter $', buffer.o || "");
        var c3 = mhchemParser.patterns.match_('one lowercase latin letter $', buffer.o || "");
        var c4 = mhchemParser.patterns.match_('$one lowercase latin letter$ $', buffer.o || "");
        var hyphenFollows = m === "-" && (c1 && c1.remainder === "" || c2 || c3 || c4);

        if (hyphenFollows && !buffer.a && !buffer.b && !buffer.p && !buffer.d && !buffer.q && !c1 && c3) {
          buffer.o = '$' + buffer.o + '$';
        }
        /** @type {ParserOutput[]} */


        var ret = [];

        if (hyphenFollows) {
          mhchemParser.concatArray(ret, this['output'](buffer));
          ret.push({
            type_: 'hyphen'
          });
        } else {
          c1 = mhchemParser.patterns.match_('digits', buffer.d || "");

          if (isAfterD && c1 && c1.remainder === '') {
            mhchemParser.concatArray(ret, mhchemParser.actions['d='](buffer, m));
            mhchemParser.concatArray(ret, this['output'](buffer));
          } else {
            mhchemParser.concatArray(ret, this['output'](buffer));
            mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-"));
          }
        }

        return ret;
      },
      'a to o': function aToO(buffer) {
        buffer.o = buffer.a;
        buffer.a = undefined;
      },
      'sb=true': function sbTrue(buffer) {
        buffer.sb = true;
      },
      'sb=false': function sbFalse(buffer) {
        buffer.sb = false;
      },
      'beginsWithBond=true': function beginsWithBondTrue(buffer) {
        buffer['beginsWithBond'] = true;
      },
      'beginsWithBond=false': function beginsWithBondFalse(buffer) {
        buffer['beginsWithBond'] = false;
      },
      'parenthesisLevel++': function parenthesisLevel(buffer) {
        buffer['parenthesisLevel']++;
      },
      'parenthesisLevel--': function parenthesisLevel(buffer) {
        buffer['parenthesisLevel']--;
      },
      'state of aggregation': function stateOfAggregation(buffer, m) {
        return {
          type_: 'state of aggregation',
          p1: mhchemParser.go(m, 'o')
        };
      },
      'comma': function comma(buffer, m) {
        var a = m.replace(/\s*$/, '');
        var withSpace = a !== m;

        if (withSpace && buffer['parenthesisLevel'] === 0) {
          return {
            type_: 'comma enumeration L',
            p1: a
          };
        } else {
          return {
            type_: 'comma enumeration M',
            p1: a
          };
        }
      },
      'output': function output(buffer, m, entityFollows) {
        // entityFollows:
        //   undefined = if we have nothing else to output, also ignore the just read space (buffer.sb)
        //   1 = an entity follows, never omit the space if there was one just read before (can only apply to state 1)
        //   2 = 1 + the entity can have an amount, so output a\, instead of converting it to o (can only apply to states a|as)

        /** @type {ParserOutput | ParserOutput[]} */
        var ret;

        if (!buffer.r) {
          ret = [];

          if (!buffer.a && !buffer.b && !buffer.p && !buffer.o && !buffer.q && !buffer.d && !entityFollows) {//ret = [];
          } else {
            if (buffer.sb) {
              ret.push({
                type_: 'entitySkip'
              });
            }

            if (!buffer.o && !buffer.q && !buffer.d && !buffer.b && !buffer.p && entityFollows !== 2) {
              buffer.o = buffer.a;
              buffer.a = undefined;
            } else if (!buffer.o && !buffer.q && !buffer.d && (buffer.b || buffer.p)) {
              buffer.o = buffer.a;
              buffer.d = buffer.b;
              buffer.q = buffer.p;
              buffer.a = buffer.b = buffer.p = undefined;
            } else {
              if (buffer.o && buffer.dType === 'kv' && mhchemParser.patterns.match_('d-oxidation$', buffer.d || "")) {
                buffer.dType = 'oxidation';
              } else if (buffer.o && buffer.dType === 'kv' && !buffer.q) {
                buffer.dType = undefined;
              }
            }

            ret.push({
              type_: 'chemfive',
              a: mhchemParser.go(buffer.a, 'a'),
              b: mhchemParser.go(buffer.b, 'bd'),
              p: mhchemParser.go(buffer.p, 'pq'),
              o: mhchemParser.go(buffer.o, 'o'),
              q: mhchemParser.go(buffer.q, 'pq'),
              d: mhchemParser.go(buffer.d, buffer.dType === 'oxidation' ? 'oxidation' : 'bd'),
              dType: buffer.dType
            });
          }
        } else {
          // r

          /** @type {ParserOutput[]} */
          var rd;

          if (buffer.rdt === 'M') {
            rd = mhchemParser.go(buffer.rd, 'tex-math');
          } else if (buffer.rdt === 'T') {
            rd = [{
              type_: 'text',
              p1: buffer.rd || ""
            }];
          } else {
            rd = mhchemParser.go(buffer.rd);
          }
          /** @type {ParserOutput[]} */


          var rq;

          if (buffer.rqt === 'M') {
            rq = mhchemParser.go(buffer.rq, 'tex-math');
          } else if (buffer.rqt === 'T') {
            rq = [{
              type_: 'text',
              p1: buffer.rq || ""
            }];
          } else {
            rq = mhchemParser.go(buffer.rq);
          }

          ret = {
            type_: 'arrow',
            r: buffer.r,
            rd: rd,
            rq: rq
          };
        }

        for (var p in buffer) {
          if (p !== 'parenthesisLevel' && p !== 'beginsWithBond') {
            delete buffer[p];
          }
        }

        return ret;
      },
      'oxidation-output': function oxidationOutput(buffer, m) {
        var ret = ["{"];
        mhchemParser.concatArray(ret, mhchemParser.go(m, 'oxidation'));
        ret.push("}");
        return ret;
      },
      'frac-output': function fracOutput(buffer, m) {
        return {
          type_: 'frac-ce',
          p1: mhchemParser.go(m[0]),
          p2: mhchemParser.go(m[1])
        };
      },
      'overset-output': function oversetOutput(buffer, m) {
        return {
          type_: 'overset',
          p1: mhchemParser.go(m[0]),
          p2: mhchemParser.go(m[1])
        };
      },
      'underset-output': function undersetOutput(buffer, m) {
        return {
          type_: 'underset',
          p1: mhchemParser.go(m[0]),
          p2: mhchemParser.go(m[1])
        };
      },
      'underbrace-output': function underbraceOutput(buffer, m) {
        return {
          type_: 'underbrace',
          p1: mhchemParser.go(m[0]),
          p2: mhchemParser.go(m[1])
        };
      },
      'color-output': function colorOutput(buffer, m) {
        return {
          type_: 'color',
          color1: m[0],
          color2: mhchemParser.go(m[1])
        };
      },
      'r=': function r(buffer, m) {
        buffer.r = m;
      },
      'rdt=': function rdt(buffer, m) {
        buffer.rdt = m;
      },
      'rd=': function rd(buffer, m) {
        buffer.rd = m;
      },
      'rqt=': function rqt(buffer, m) {
        buffer.rqt = m;
      },
      'rq=': function rq(buffer, m) {
        buffer.rq = m;
      },
      'operator': function operator(buffer, m, p1) {
        return {
          type_: 'operator',
          kind_: p1 || m
        };
      }
    }
  },
  'a': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {}
      },
      '1/2$': {
        '0': {
          action_: '1/2'
        }
      },
      'else': {
        '0': {
          nextState: '1',
          revisit: true
        }
      },
      '$(...)$': {
        '*': {
          action_: 'tex-math tight',
          nextState: '1'
        }
      },
      ',': {
        '*': {
          action_: {
            type_: 'insert',
            option: 'commaDecimal'
          }
        }
      },
      'else2': {
        '*': {
          action_: 'copy'
        }
      }
    }),
    actions: {}
  },
  'o': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {}
      },
      '1/2$': {
        '0': {
          action_: '1/2'
        }
      },
      'else': {
        '0': {
          nextState: '1',
          revisit: true
        }
      },
      'letters': {
        '*': {
          action_: 'rm'
        }
      },
      '\\ca': {
        '*': {
          action_: {
            type_: 'insert',
            option: 'circa'
          }
        }
      },
      '\\x{}{}|\\x{}|\\x': {
        '*': {
          action_: 'copy'
        }
      },
      '${(...)}$|$(...)$': {
        '*': {
          action_: 'tex-math'
        }
      },
      '{(...)}': {
        '*': {
          action_: '{text}'
        }
      },
      'else2': {
        '*': {
          action_: 'copy'
        }
      }
    }),
    actions: {}
  },
  'text': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {
          action_: 'output'
        }
      },
      '{...}': {
        '*': {
          action_: 'text='
        }
      },
      '${(...)}$|$(...)$': {
        '*': {
          action_: 'tex-math'
        }
      },
      '\\greek': {
        '*': {
          action_: ['output', 'rm']
        }
      },
      '\\,|\\x{}{}|\\x{}|\\x': {
        '*': {
          action_: ['output', 'copy']
        }
      },
      'else': {
        '*': {
          action_: 'text='
        }
      }
    }),
    actions: {
      'output': function output(buffer) {
        if (buffer.text_) {
          /** @type {ParserOutput} */
          var ret = {
            type_: 'text',
            p1: buffer.text_
          };

          for (var p in buffer) {
            delete buffer[p];
          }

          return ret;
        }
      }
    }
  },
  'pq': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {}
      },
      'state of aggregation $': {
        '*': {
          action_: 'state of aggregation'
        }
      },
      'i$': {
        '0': {
          nextState: '!f',
          revisit: true
        }
      },
      '(KV letters),': {
        '0': {
          action_: 'rm',
          nextState: '0'
        }
      },
      'formula$': {
        '0': {
          nextState: 'f',
          revisit: true
        }
      },
      '1/2$': {
        '0': {
          action_: '1/2'
        }
      },
      'else': {
        '0': {
          nextState: '!f',
          revisit: true
        }
      },
      '${(...)}$|$(...)$': {
        '*': {
          action_: 'tex-math'
        }
      },
      '{(...)}': {
        '*': {
          action_: 'text'
        }
      },
      'a-z': {
        'f': {
          action_: 'tex-math'
        }
      },
      'letters': {
        '*': {
          action_: 'rm'
        }
      },
      '-9.,9': {
        '*': {
          action_: '9,9'
        }
      },
      ',': {
        '*': {
          action_: {
            type_: 'insert+p1',
            option: 'comma enumeration S'
          }
        }
      },
      '\\color{(...)}{(...)}1|\\color(...){(...)}2': {
        '*': {
          action_: 'color-output'
        }
      },
      '\\color{(...)}0': {
        '*': {
          action_: 'color0-output'
        }
      },
      '\\ce{(...)}': {
        '*': {
          action_: 'ce'
        }
      },
      '\\,|\\x{}{}|\\x{}|\\x': {
        '*': {
          action_: 'copy'
        }
      },
      'else2': {
        '*': {
          action_: 'copy'
        }
      }
    }),
    actions: {
      'state of aggregation': function stateOfAggregation(buffer, m) {
        return {
          type_: 'state of aggregation subscript',
          p1: mhchemParser.go(m, 'o')
        };
      },
      'color-output': function colorOutput(buffer, m) {
        return {
          type_: 'color',
          color1: m[0],
          color2: mhchemParser.go(m[1], 'pq')
        };
      }
    }
  },
  'bd': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {}
      },
      'x$': {
        '0': {
          nextState: '!f',
          revisit: true
        }
      },
      'formula$': {
        '0': {
          nextState: 'f',
          revisit: true
        }
      },
      'else': {
        '0': {
          nextState: '!f',
          revisit: true
        }
      },
      '-9.,9 no missing 0': {
        '*': {
          action_: '9,9'
        }
      },
      '.': {
        '*': {
          action_: {
            type_: 'insert',
            option: 'electron dot'
          }
        }
      },
      'a-z': {
        'f': {
          action_: 'tex-math'
        }
      },
      'x': {
        '*': {
          action_: {
            type_: 'insert',
            option: 'KV x'
          }
        }
      },
      'letters': {
        '*': {
          action_: 'rm'
        }
      },
      '\'': {
        '*': {
          action_: {
            type_: 'insert',
            option: 'prime'
          }
        }
      },
      '${(...)}$|$(...)$': {
        '*': {
          action_: 'tex-math'
        }
      },
      '{(...)}': {
        '*': {
          action_: 'text'
        }
      },
      '\\color{(...)}{(...)}1|\\color(...){(...)}2': {
        '*': {
          action_: 'color-output'
        }
      },
      '\\color{(...)}0': {
        '*': {
          action_: 'color0-output'
        }
      },
      '\\ce{(...)}': {
        '*': {
          action_: 'ce'
        }
      },
      '\\,|\\x{}{}|\\x{}|\\x': {
        '*': {
          action_: 'copy'
        }
      },
      'else2': {
        '*': {
          action_: 'copy'
        }
      }
    }),
    actions: {
      'color-output': function colorOutput(buffer, m) {
        return {
          type_: 'color',
          color1: m[0],
          color2: mhchemParser.go(m[1], 'bd')
        };
      }
    }
  },
  'oxidation': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {}
      },
      'roman numeral': {
        '*': {
          action_: 'roman-numeral'
        }
      },
      '${(...)}$|$(...)$': {
        '*': {
          action_: 'tex-math'
        }
      },
      'else': {
        '*': {
          action_: 'copy'
        }
      }
    }),
    actions: {
      'roman-numeral': function romanNumeral(buffer, m) {
        return {
          type_: 'roman numeral',
          p1: m || ""
        };
      }
    }
  },
  'tex-math': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {
          action_: 'output'
        }
      },
      '\\ce{(...)}': {
        '*': {
          action_: ['output', 'ce']
        }
      },
      '{...}|\\,|\\x{}{}|\\x{}|\\x': {
        '*': {
          action_: 'o='
        }
      },
      'else': {
        '*': {
          action_: 'o='
        }
      }
    }),
    actions: {
      'output': function output(buffer) {
        if (buffer.o) {
          /** @type {ParserOutput} */
          var ret = {
            type_: 'tex-math',
            p1: buffer.o
          };

          for (var p in buffer) {
            delete buffer[p];
          }

          return ret;
        }
      }
    }
  },
  'tex-math tight': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {
          action_: 'output'
        }
      },
      '\\ce{(...)}': {
        '*': {
          action_: ['output', 'ce']
        }
      },
      '{...}|\\,|\\x{}{}|\\x{}|\\x': {
        '*': {
          action_: 'o='
        }
      },
      '-|+': {
        '*': {
          action_: 'tight operator'
        }
      },
      'else': {
        '*': {
          action_: 'o='
        }
      }
    }),
    actions: {
      'tight operator': function tightOperator(buffer, m) {
        buffer.o = (buffer.o || "") + "{" + m + "}";
      },
      'output': function output(buffer) {
        if (buffer.o) {
          /** @type {ParserOutput} */
          var ret = {
            type_: 'tex-math',
            p1: buffer.o
          };

          for (var p in buffer) {
            delete buffer[p];
          }

          return ret;
        }
      }
    }
  },
  '9,9': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {}
      },
      ',': {
        '*': {
          action_: 'comma'
        }
      },
      'else': {
        '*': {
          action_: 'copy'
        }
      }
    }),
    actions: {
      'comma': function comma() {
        return {
          type_: 'commaDecimal'
        };
      }
    }
  },
  //#endregion
  //
  // \pu state machines
  //
  //#region pu
  'pu': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {
          action_: 'output'
        }
      },
      'space$': {
        '*': {
          action_: ['output', 'space']
        }
      },
      '{[(|)]}': {
        '0|a': {
          action_: 'copy'
        }
      },
      '(-)(9)^(-9)': {
        '0': {
          action_: 'number^',
          nextState: 'a'
        }
      },
      '(-)(9.,9)(e)(99)': {
        '0': {
          action_: 'enumber',
          nextState: 'a'
        }
      },
      'space': {
        '0|a': {}
      },
      'pm-operator': {
        '0|a': {
          action_: {
            type_: 'operator',
            option: '\\pm'
          },
          nextState: '0'
        }
      },
      'operator': {
        '0|a': {
          action_: 'copy',
          nextState: '0'
        }
      },
      '//': {
        'd': {
          action_: 'o=',
          nextState: '/'
        }
      },
      '/': {
        'd': {
          action_: 'o=',
          nextState: '/'
        }
      },
      '{...}|else': {
        '0|d': {
          action_: 'd=',
          nextState: 'd'
        },
        'a': {
          action_: ['space', 'd='],
          nextState: 'd'
        },
        '/|q': {
          action_: 'q=',
          nextState: 'q'
        }
      }
    }),
    actions: {
      'enumber': function enumber(buffer, m) {
        /** @type {ParserOutput[]} */
        var ret = [];

        if (m[0] === "+-" || m[0] === "+/-") {
          ret.push("\\pm ");
        } else if (m[0]) {
          ret.push(m[0]);
        }

        if (m[1]) {
          mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9'));

          if (m[2]) {
            if (m[2].match(/[,.]/)) {
              mhchemParser.concatArray(ret, mhchemParser.go(m[2], 'pu-9,9'));
            } else {
              ret.push(m[2]);
            }
          }

          m[3] = m[4] || m[3];

          if (m[3]) {
            m[3] = m[3].trim();

            if (m[3] === "e" || m[3].substr(0, 1) === "*") {
              ret.push({
                type_: 'cdot'
              });
            } else {
              ret.push({
                type_: 'times'
              });
            }
          }
        }

        if (m[3]) {
          ret.push("10^{" + m[5] + "}");
        }

        return ret;
      },
      'number^': function number(buffer, m) {
        /** @type {ParserOutput[]} */
        var ret = [];

        if (m[0] === "+-" || m[0] === "+/-") {
          ret.push("\\pm ");
        } else if (m[0]) {
          ret.push(m[0]);
        }

        mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9'));
        ret.push("^{" + m[2] + "}");
        return ret;
      },
      'operator': function operator(buffer, m, p1) {
        return {
          type_: 'operator',
          kind_: p1 || m
        };
      },
      'space': function space() {
        return {
          type_: 'pu-space-1'
        };
      },
      'output': function output(buffer) {
        /** @type {ParserOutput | ParserOutput[]} */
        var ret;
        var md = mhchemParser.patterns.match_('{(...)}', buffer.d || "");

        if (md && md.remainder === '') {
          buffer.d = md.match_;
        }

        var mq = mhchemParser.patterns.match_('{(...)}', buffer.q || "");

        if (mq && mq.remainder === '') {
          buffer.q = mq.match_;
        }

        if (buffer.d) {
          buffer.d = buffer.d.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C");
          buffer.d = buffer.d.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F");
        }

        if (buffer.q) {
          // fraction
          buffer.q = buffer.q.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C");
          buffer.q = buffer.q.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F");
          var b5 = {
            d: mhchemParser.go(buffer.d, 'pu'),
            q: mhchemParser.go(buffer.q, 'pu')
          };

          if (buffer.o === '//') {
            ret = {
              type_: 'pu-frac',
              p1: b5.d,
              p2: b5.q
            };
          } else {
            ret = b5.d;

            if (b5.d.length > 1 || b5.q.length > 1) {
              ret.push({
                type_: ' / '
              });
            } else {
              ret.push({
                type_: '/'
              });
            }

            mhchemParser.concatArray(ret, b5.q);
          }
        } else {
          // no fraction
          ret = mhchemParser.go(buffer.d, 'pu-2');
        }

        for (var p in buffer) {
          delete buffer[p];
        }

        return ret;
      }
    }
  },
  'pu-2': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {
          action_: 'output'
        }
      },
      '*': {
        '*': {
          action_: ['output', 'cdot'],
          nextState: '0'
        }
      },
      '\\x': {
        '*': {
          action_: 'rm='
        }
      },
      'space': {
        '*': {
          action_: ['output', 'space'],
          nextState: '0'
        }
      },
      '^{(...)}|^(-1)': {
        '1': {
          action_: '^(-1)'
        }
      },
      '-9.,9': {
        '0': {
          action_: 'rm=',
          nextState: '0'
        },
        '1': {
          action_: '^(-1)',
          nextState: '0'
        }
      },
      '{...}|else': {
        '*': {
          action_: 'rm=',
          nextState: '1'
        }
      }
    }),
    actions: {
      'cdot': function cdot() {
        return {
          type_: 'tight cdot'
        };
      },
      '^(-1)': function _(buffer, m) {
        buffer.rm += "^{" + m + "}";
      },
      'space': function space() {
        return {
          type_: 'pu-space-2'
        };
      },
      'output': function output(buffer) {
        /** @type {ParserOutput | ParserOutput[]} */
        var ret = [];

        if (buffer.rm) {
          var mrm = mhchemParser.patterns.match_('{(...)}', buffer.rm || "");

          if (mrm && mrm.remainder === '') {
            ret = mhchemParser.go(mrm.match_, 'pu');
          } else {
            ret = {
              type_: 'rm',
              p1: buffer.rm
            };
          }
        }

        for (var p in buffer) {
          delete buffer[p];
        }

        return ret;
      }
    }
  },
  'pu-9,9': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '0': {
          action_: 'output-0'
        },
        'o': {
          action_: 'output-o'
        }
      },
      ',': {
        '0': {
          action_: ['output-0', 'comma'],
          nextState: 'o'
        }
      },
      '.': {
        '0': {
          action_: ['output-0', 'copy'],
          nextState: 'o'
        }
      },
      'else': {
        '*': {
          action_: 'text='
        }
      }
    }),
    actions: {
      'comma': function comma() {
        return {
          type_: 'commaDecimal'
        };
      },
      'output-0': function output0(buffer) {
        /** @type {ParserOutput[]} */
        var ret = [];
        buffer.text_ = buffer.text_ || "";

        if (buffer.text_.length > 4) {
          var a = buffer.text_.length % 3;

          if (a === 0) {
            a = 3;
          }

          for (var i = buffer.text_.length - 3; i > 0; i -= 3) {
            ret.push(buffer.text_.substr(i, 3));
            ret.push({
              type_: '1000 separator'
            });
          }

          ret.push(buffer.text_.substr(0, a));
          ret.reverse();
        } else {
          ret.push(buffer.text_);
        }

        for (var p in buffer) {
          delete buffer[p];
        }

        return ret;
      },
      'output-o': function outputO(buffer) {
        /** @type {ParserOutput[]} */
        var ret = [];
        buffer.text_ = buffer.text_ || "";

        if (buffer.text_.length > 4) {
          var a = buffer.text_.length - 3;

          for (var i = 0; i < a; i += 3) {
            ret.push(buffer.text_.substr(i, 3));
            ret.push({
              type_: '1000 separator'
            });
          }

          ret.push(buffer.text_.substr(i));
        } else {
          ret.push(buffer.text_);
        }

        for (var p in buffer) {
          delete buffer[p];
        }

        return ret;
      }
    }
  } //#endregion

}; //
// texify: Take MhchemParser output and convert it to TeX
//

/** @type {Texify} */

var texify = {
  go: function go(input, isInner) {
    // (recursive, max 4 levels)
    if (!input) {
      return "";
    }

    var res = "";
    var cee = false;

    for (var i = 0; i < input.length; i++) {
      var inputi = input[i];

      if (typeof inputi === "string") {
        res += inputi;
      } else {
        res += texify._go2(inputi);

        if (inputi.type_ === '1st-level escape') {
          cee = true;
        }
      }
    }

    if (!isInner && !cee && res) {
      res = "{" + res + "}";
    }

    return res;
  },
  _goInner: function _goInner(input) {
    if (!input) {
      return input;
    }

    return texify.go(input, true);
  },
  _go2: function _go2(buf) {
    /** @type {undefined | string} */
    var res;

    switch (buf.type_) {
      case 'chemfive':
        res = "";
        var b5 = {
          a: texify._goInner(buf.a),
          b: texify._goInner(buf.b),
          p: texify._goInner(buf.p),
          o: texify._goInner(buf.o),
          q: texify._goInner(buf.q),
          d: texify._goInner(buf.d)
        }; //
        // a
        //

        if (b5.a) {
          if (b5.a.match(/^[+\-]/)) {
            b5.a = "{" + b5.a + "}";
          }

          res += b5.a + "\\,";
        } //
        // b and p
        //


        if (b5.b || b5.p) {
          res += "{\\vphantom{X}}";
          res += "^{\\hphantom{" + (b5.b || "") + "}}_{\\hphantom{" + (b5.p || "") + "}}";
          res += "{\\vphantom{X}}";
          res += "^{\\smash[t]{\\vphantom{2}}\\mathllap{" + (b5.b || "") + "}}";
          res += "_{\\vphantom{2}\\mathllap{\\smash[t]{" + (b5.p || "") + "}}}";
        } //
        // o
        //


        if (b5.o) {
          if (b5.o.match(/^[+\-]/)) {
            b5.o = "{" + b5.o + "}";
          }

          res += b5.o;
        } //
        // q and d
        //


        if (buf.dType === 'kv') {
          if (b5.d || b5.q) {
            res += "{\\vphantom{X}}";
          }

          if (b5.d) {
            res += "^{" + b5.d + "}";
          }

          if (b5.q) {
            res += "_{\\smash[t]{" + b5.q + "}}";
          }
        } else if (buf.dType === 'oxidation') {
          if (b5.d) {
            res += "{\\vphantom{X}}";
            res += "^{" + b5.d + "}";
          }

          if (b5.q) {
            res += "{\\vphantom{X}}";
            res += "_{\\smash[t]{" + b5.q + "}}";
          }
        } else {
          if (b5.q) {
            res += "{\\vphantom{X}}";
            res += "_{\\smash[t]{" + b5.q + "}}";
          }

          if (b5.d) {
            res += "{\\vphantom{X}}";
            res += "^{" + b5.d + "}";
          }
        }

        break;

      case 'rm':
        res = "\\mathrm{" + buf.p1 + "}";
        break;

      case 'text':
        if (buf.p1.match(/[\^_]/)) {
          buf.p1 = buf.p1.replace(" ", "~").replace("-", "\\text{-}");
          res = "\\mathrm{" + buf.p1 + "}";
        } else {
          res = "\\text{" + buf.p1 + "}";
        }

        break;

      case 'roman numeral':
        res = "\\mathrm{" + buf.p1 + "}";
        break;

      case 'state of aggregation':
        res = "\\mskip2mu " + texify._goInner(buf.p1);
        break;

      case 'state of aggregation subscript':
        res = "\\mskip1mu " + texify._goInner(buf.p1);
        break;

      case 'bond':
        res = texify._getBond(buf.kind_);

        if (!res) {
          throw ["MhchemErrorBond", "mhchem Error. Unknown bond type (" + buf.kind_ + ")"];
        }

        break;

      case 'frac':
        var c = "\\frac{" + buf.p1 + "}{" + buf.p2 + "}";
        res = "\\mathchoice{\\textstyle" + c + "}{" + c + "}{" + c + "}{" + c + "}";
        break;

      case 'pu-frac':
        var d = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}";
        res = "\\mathchoice{\\textstyle" + d + "}{" + d + "}{" + d + "}{" + d + "}";
        break;

      case 'tex-math':
        res = buf.p1 + " ";
        break;

      case 'frac-ce':
        res = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}";
        break;

      case 'overset':
        res = "\\overset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}";
        break;

      case 'underset':
        res = "\\underset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}";
        break;

      case 'underbrace':
        res = "\\underbrace{" + texify._goInner(buf.p1) + "}_{" + texify._goInner(buf.p2) + "}";
        break;

      case 'color':
        res = "{\\color{" + buf.color1 + "}{" + texify._goInner(buf.color2) + "}}";
        break;

      case 'color0':
        res = "\\color{" + buf.color + "}";
        break;

      case 'arrow':
        var b6 = {
          rd: texify._goInner(buf.rd),
          rq: texify._goInner(buf.rq)
        };

        var arrow = "\\x" + texify._getArrow(buf.r);

        if (b6.rq) {
          arrow += "[{" + b6.rq + "}]";
        }

        if (b6.rd) {
          arrow += "{" + b6.rd + "}";
        } else {
          arrow += "{}";
        }

        res = arrow;
        break;

      case 'operator':
        res = texify._getOperator(buf.kind_);
        break;

      case '1st-level escape':
        res = buf.p1 + " "; // &, \\\\, \\hlin

        break;

      case 'space':
        res = " ";
        break;

      case 'entitySkip':
        res = "~";
        break;

      case 'pu-space-1':
        res = "~";
        break;

      case 'pu-space-2':
        res = "\\mkern3mu ";
        break;

      case '1000 separator':
        res = "\\mkern2mu ";
        break;

      case 'commaDecimal':
        res = "{,}";
        break;

      case 'comma enumeration L':
        res = "{" + buf.p1 + "}\\mkern6mu ";
        break;

      case 'comma enumeration M':
        res = "{" + buf.p1 + "}\\mkern3mu ";
        break;

      case 'comma enumeration S':
        res = "{" + buf.p1 + "}\\mkern1mu ";
        break;

      case 'hyphen':
        res = "\\text{-}";
        break;

      case 'addition compound':
        res = "\\,{\\cdot}\\,";
        break;

      case 'electron dot':
        res = "\\mkern1mu \\bullet\\mkern1mu ";
        break;

      case 'KV x':
        res = "{\\times}";
        break;

      case 'prime':
        res = "\\prime ";
        break;

      case 'cdot':
        res = "\\cdot ";
        break;

      case 'tight cdot':
        res = "\\mkern1mu{\\cdot}\\mkern1mu ";
        break;

      case 'times':
        res = "\\times ";
        break;

      case 'circa':
        res = "{\\sim}";
        break;

      case '^':
        res = "uparrow";
        break;

      case 'v':
        res = "downarrow";
        break;

      case 'ellipsis':
        res = "\\ldots ";
        break;

      case '/':
        res = "/";
        break;

      case ' / ':
        res = "\\,/\\,";
        break;

      default:
        assertNever(buf);
        throw ["MhchemBugT", "mhchem bug T. Please report."];
      // Missing texify rule or unknown MhchemParser output
    }

    assertString(res);
    return res;
  },
  _getArrow: function _getArrow(a) {
    switch (a) {
      case "->":
        return "rightarrow";

      case "\u2192":
        return "rightarrow";

      case "\u27F6":
        return "rightarrow";

      case "<-":
        return "leftarrow";

      case "<->":
        return "leftrightarrow";

      case "<-->":
        return "rightleftarrows";

      case "<=>":
        return "rightleftharpoons";

      case "\u21CC":
        return "rightleftharpoons";

      case "<=>>":
        return "rightequilibrium";

      case "<<=>":
        return "leftequilibrium";

      default:
        assertNever(a);
        throw ["MhchemBugT", "mhchem bug T. Please report."];
    }
  },
  _getBond: function _getBond(a) {
    switch (a) {
      case "-":
        return "{-}";

      case "1":
        return "{-}";

      case "=":
        return "{=}";

      case "2":
        return "{=}";

      case "#":
        return "{\\equiv}";

      case "3":
        return "{\\equiv}";

      case "~":
        return "{\\tripledash}";

      case "~-":
        return "{\\mathrlap{\\raisebox{-.1em}{$-$}}\\raisebox{.1em}{$\\tripledash$}}";

      case "~=":
        return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}";

      case "~--":
        return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}";

      case "-~-":
        return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$-$}}\\tripledash}";

      case "...":
        return "{{\\cdot}{\\cdot}{\\cdot}}";

      case "....":
        return "{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}";

      case "->":
        return "{\\rightarrow}";

      case "<-":
        return "{\\leftarrow}";

      case "<":
        return "{<}";

      case ">":
        return "{>}";

      default:
        assertNever(a);
        throw ["MhchemBugT", "mhchem bug T. Please report."];
    }
  },
  _getOperator: function _getOperator(a) {
    switch (a) {
      case "+":
        return " {}+{} ";

      case "-":
        return " {}-{} ";

      case "=":
        return " {}={} ";

      case "<":
        return " {}<{} ";

      case ">":
        return " {}>{} ";

      case "<<":
        return " {}\\ll{} ";

      case ">>":
        return " {}\\gg{} ";

      case "\\pm":
        return " {}\\pm{} ";

      case "\\approx":
        return " {}\\approx{} ";

      case "$\\approx$":
        return " {}\\approx{} ";

      case "v":
        return " \\downarrow{} ";

      case "(v)":
        return " \\downarrow{} ";

      case "^":
        return " \\uparrow{} ";

      case "(^)":
        return " \\uparrow{} ";

      default:
        assertNever(a);
        throw ["MhchemBugT", "mhchem bug T. Please report."];
    }
  }
}; //
// Helpers for code analysis
// Will show type error at calling position
//

/** @param {number} a */

function assertNever(a) {}
/** @param {string} a */


function assertString(a) {}
}();
__webpack_exports__ = __webpack_exports__["default"];
/******/ 	return __webpack_exports__;
/******/ })()
;
});
mhchem.min.js
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/mhchem.min.js'
View Content
!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("katex"));else if("function"==typeof define&&define.amd)define(["katex"],e);else{var n="object"==typeof exports?e(require("katex")):e(t.katex);for(var o in n)("object"==typeof exports?exports:t)[o]=n[o]}}("undefined"!=typeof self?self:this,(function(t){return function(){"use strict";var e={771:function(e){e.exports=t}},n={};function o(t){var a=n[t];if(void 0!==a)return a.exports;var r=n[t]={exports:{}};return e[t](r,r.exports,o),r.exports}o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,{a:e}),e},o.d=function(t,e){for(var n in e)o.o(e,n)&&!o.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)};var a={};return function(){var t=o(771),e=o.n(t);e().__defineMacro("\\ce",(function(t){return n(t.consumeArgs(1)[0],"ce")})),e().__defineMacro("\\pu",(function(t){return n(t.consumeArgs(1)[0],"pu")})),e().__defineMacro("\\tripledash","{\\vphantom{-}\\raisebox{2.56mu}{$\\mkern2mu\\tiny\\text{-}\\mkern1mu\\text{-}\\mkern1mu\\text{-}\\mkern2mu$}}");var n=function(t,e){for(var n="",o=t.length&&t[t.length-1].loc.start,i=t.length-1;i>=0;i--)t[i].loc.start>o&&(n+=" ",o=t[i].loc.start),n+=t[i].text,o+=t[i].text.length;return r.go(a.go(n,e))},a={go:function(t,e){if(!t)return[];void 0===e&&(e="ce");var n,o="0",r={};r.parenthesisLevel=0,t=(t=(t=t.replace(/\n/g," ")).replace(/[\u2212\u2013\u2014\u2010]/g,"-")).replace(/[\u2026]/g,"...");for(var i=10,c=[];;){n!==t?(i=10,n=t):i--;var u=a.stateMachines[e],p=u.transitions[o]||u.transitions["*"];t:for(var s=0;s<p.length;s++){var _=a.patterns.match_(p[s].pattern,t);if(_){for(var d=p[s].task,m=0;m<d.action_.length;m++){var l;if(u.actions[d.action_[m].type_])l=u.actions[d.action_[m].type_](r,_.match_,d.action_[m].option);else{if(!a.actions[d.action_[m].type_])throw["MhchemBugA","mhchem bug A. Please report. ("+d.action_[m].type_+")"];l=a.actions[d.action_[m].type_](r,_.match_,d.action_[m].option)}a.concatArray(c,l)}if(o=d.nextState||o,!(t.length>0))return c;if(d.revisit||(t=_.remainder),!d.toContinue)break t}}if(i<=0)throw["MhchemBugU","mhchem bug U. Please report."]}},concatArray:function(t,e){if(e)if(Array.isArray(e))for(var n=0;n<e.length;n++)t.push(e[n]);else t.push(e)},patterns:{patterns:{empty:/^$/,else:/^./,else2:/^./,space:/^\s/,"space A":/^\s(?=[A-Z\\$])/,space$:/^\s$/,"a-z":/^[a-z]/,x:/^x/,x$:/^x$/,i$:/^i$/,letters:/^(?:[a-zA-Z\u03B1-\u03C9\u0391-\u03A9?@]|(?:\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))))+/,"\\greek":/^\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))/,"one lowercase latin letter $":/^(?:([a-z])(?:$|[^a-zA-Z]))$/,"$one lowercase latin letter$ $":/^\$(?:([a-z])(?:$|[^a-zA-Z]))\$$/,"one lowercase greek letter $":/^(?:\$?[\u03B1-\u03C9]\$?|\$?\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega)\s*\$?)(?:\s+|\{\}|(?![a-zA-Z]))$/,digits:/^[0-9]+/,"-9.,9":/^[+\-]?(?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))/,"-9.,9 no missing 0":/^[+\-]?[0-9]+(?:[.,][0-9]+)?/,"(-)(9.,9)(e)(99)":function(t){var e=t.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]+\}))?/);return e&&e[0]?{match_:e.splice(1),remainder:t.substr(e[0].length)}:null},"(-)(9)^(-9)":function(t){var e=t.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+)?)\^([+\-]?[0-9]+|\{[+\-]?[0-9]+\})/);return e&&e[0]?{match_:e.splice(1),remainder:t.substr(e[0].length)}:null},"state of aggregation $":function(t){var e=a.patterns.findObserveGroups(t,"",/^\([a-z]{1,3}(?=[\),])/,")","");if(e&&e.remainder.match(/^($|[\s,;\)\]\}])/))return e;var n=t.match(/^(?:\((?:\\ca\s?)?\$[amothc]\$\))/);return n?{match_:n[0],remainder:t.substr(n[0].length)}:null},"_{(state of aggregation)}$":/^_\{(\([a-z]{1,3}\))\}/,"{[(":/^(?:\\\{|\[|\()/,")]}":/^(?:\)|\]|\\\})/,", ":/^[,;]\s*/,",":/^[,;]/,".":/^[.]/,". ":/^([.\u22C5\u00B7\u2022])\s*/,"...":/^\.\.\.(?=$|[^.])/,"* ":/^([*])\s*/,"^{(...)}":function(t){return a.patterns.findObserveGroups(t,"^{","","","}")},"^($...$)":function(t){return a.patterns.findObserveGroups(t,"^","$","$","")},"^a":/^\^([0-9]+|[^\\_])/,"^\\x{}{}":function(t){return a.patterns.findObserveGroups(t,"^",/^\\[a-zA-Z]+\{/,"}","","","{","}","",!0)},"^\\x{}":function(t){return a.patterns.findObserveGroups(t,"^",/^\\[a-zA-Z]+\{/,"}","")},"^\\x":/^\^(\\[a-zA-Z]+)\s*/,"^(-1)":/^\^(-?\d+)/,"'":/^'/,"_{(...)}":function(t){return a.patterns.findObserveGroups(t,"_{","","","}")},"_($...$)":function(t){return a.patterns.findObserveGroups(t,"_","$","$","")},_9:/^_([+\-]?[0-9]+|[^\\])/,"_\\x{}{}":function(t){return a.patterns.findObserveGroups(t,"_",/^\\[a-zA-Z]+\{/,"}","","","{","}","",!0)},"_\\x{}":function(t){return a.patterns.findObserveGroups(t,"_",/^\\[a-zA-Z]+\{/,"}","")},"_\\x":/^_(\\[a-zA-Z]+)\s*/,"^_":/^(?:\^(?=_)|\_(?=\^)|[\^_]$)/,"{}":/^\{\}/,"{...}":function(t){return a.patterns.findObserveGroups(t,"","{","}","")},"{(...)}":function(t){return a.patterns.findObserveGroups(t,"{","","","}")},"$...$":function(t){return a.patterns.findObserveGroups(t,"","$","$","")},"${(...)}$":function(t){return a.patterns.findObserveGroups(t,"${","","","}$")},"$(...)$":function(t){return a.patterns.findObserveGroups(t,"$","","","$")},"=<>":/^[=<>]/,"#":/^[#\u2261]/,"+":/^\+/,"-$":/^-(?=[\s_},;\]/]|$|\([a-z]+\))/,"-9":/^-(?=[0-9])/,"- orbital overlap":/^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/,"-":/^-/,"pm-operator":/^(?:\\pm|\$\\pm\$|\+-|\+\/-)/,operator:/^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/,arrowUpDown:/^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/,"\\bond{(...)}":function(t){return a.patterns.findObserveGroups(t,"\\bond{","","","}")},"->":/^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/,CMT:/^[CMT](?=\[)/,"[(...)]":function(t){return a.patterns.findObserveGroups(t,"[","","","]")},"1st-level escape":/^(&|\\\\|\\hline)\s*/,"\\,":/^(?:\\[,\ ;:])/,"\\x{}{}":function(t){return a.patterns.findObserveGroups(t,"",/^\\[a-zA-Z]+\{/,"}","","","{","}","",!0)},"\\x{}":function(t){return a.patterns.findObserveGroups(t,"",/^\\[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])/,others:/^[\/~|]/,"\\frac{(...)}":function(t){return a.patterns.findObserveGroups(t,"\\frac{","","","}","{","","","}")},"\\overset{(...)}":function(t){return a.patterns.findObserveGroups(t,"\\overset{","","","}","{","","","}")},"\\underset{(...)}":function(t){return a.patterns.findObserveGroups(t,"\\underset{","","","}","{","","","}")},"\\underbrace{(...)}":function(t){return a.patterns.findObserveGroups(t,"\\underbrace{","","","}_","{","","","}")},"\\color{(...)}0":function(t){return a.patterns.findObserveGroups(t,"\\color{","","","}")},"\\color{(...)}{(...)}1":function(t){return a.patterns.findObserveGroups(t,"\\color{","","","}","{","","","}")},"\\color(...){(...)}2":function(t){return a.patterns.findObserveGroups(t,"\\color","\\","",/^(?=\{)/,"{","","","}")},"\\ce{(...)}":function(t){return a.patterns.findObserveGroups(t,"\\ce{","","","}")},oxidation$:/^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,"d-oxidation$":/^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,"roman numeral":/^[IVX]+/,"1/2$":/^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/,amount:function(t){var e;if(e=t.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))/))return{match_:e[0],remainder:t.substr(e[0].length)};var n=a.patterns.findObserveGroups(t,"","$","$","");return n&&(e=n.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/))?{match_:e[0],remainder:t.substr(e[0].length)}:null},amount2:function(t){return this.amount(t)},"(KV letters),":/^(?:[A-Z][a-z]{0,2}|i)(?=,)/,formula$:function(t){if(t.match(/^\([a-z]+\)$/))return null;var e=t.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/);return e?{match_:e[0],remainder:t.substr(e[0].length)}:null},uprightEntities:/^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/,"/":/^\s*(\/)\s*/,"//":/^\s*(\/\/)\s*/,"*":/^\s*[*.]\s*/},findObserveGroups:function(t,e,n,o,a,r,i,c,u,p){var s=function(t,e){if("string"==typeof e)return 0!==t.indexOf(e)?null:e;var n=t.match(e);return n?n[0]:null},_=s(t,e);if(null===_)return null;if(t=t.substr(_.length),null===(_=s(t,n)))return null;var d=function(t,e,n){for(var o=0;e<t.length;){var a=t.charAt(e),r=s(t.substr(e),n);if(null!==r&&0===o)return{endMatchBegin:e,endMatchEnd:e+r.length};if("{"===a)o++;else if("}"===a){if(0===o)throw["ExtraCloseMissingOpen","Extra close brace or missing open brace"];o--}e++}return null}(t,_.length,o||a);if(null===d)return null;var m=t.substring(0,o?d.endMatchEnd:d.endMatchBegin);if(r||i){var l=this.findObserveGroups(t.substr(d.endMatchEnd),r,i,c,u);if(null===l)return null;var f=[m,l.match_];return{match_:p?f.join(""):f,remainder:l.remainder}}return{match_:m,remainder:t.substr(d.endMatchEnd)}},match_:function(t,e){var n=a.patterns.patterns[t];if(void 0===n)throw["MhchemBugP","mhchem bug P. Please report. ("+t+")"];if("function"==typeof n)return a.patterns.patterns[t](e);var o=e.match(n);return o?{match_:o[2]?[o[1],o[2]]:o[1]?o[1]:o[0],remainder:e.substr(o[0].length)}:null}},actions:{"a=":function(t,e){t.a=(t.a||"")+e},"b=":function(t,e){t.b=(t.b||"")+e},"p=":function(t,e){t.p=(t.p||"")+e},"o=":function(t,e){t.o=(t.o||"")+e},"q=":function(t,e){t.q=(t.q||"")+e},"d=":function(t,e){t.d=(t.d||"")+e},"rm=":function(t,e){t.rm=(t.rm||"")+e},"text=":function(t,e){t.text_=(t.text_||"")+e},insert:function(t,e,n){return{type_:n}},"insert+p1":function(t,e,n){return{type_:n,p1:e}},"insert+p1+p2":function(t,e,n){return{type_:n,p1:e[0],p2:e[1]}},copy:function(t,e){return e},rm:function(t,e){return{type_:"rm",p1:e||""}},text:function(t,e){return a.go(e,"text")},"{text}":function(t,e){var n=["{"];return a.concatArray(n,a.go(e,"text")),n.push("}"),n},"tex-math":function(t,e){return a.go(e,"tex-math")},"tex-math tight":function(t,e){return a.go(e,"tex-math tight")},bond:function(t,e,n){return{type_:"bond",kind_:n||e}},"color0-output":function(t,e){return{type_:"color0",color:e[0]}},ce:function(t,e){return a.go(e)},"1/2":function(t,e){var n=[];e.match(/^[+\-]/)&&(n.push(e.substr(0,1)),e=e.substr(1));var o=e.match(/^([0-9]+|\$[a-z]\$|[a-z])\/([0-9]+)(\$[a-z]\$|[a-z])?$/);return o[1]=o[1].replace(/\$/g,""),n.push({type_:"frac",p1:o[1],p2:o[2]}),o[3]&&(o[3]=o[3].replace(/\$/g,""),n.push({type_:"tex-math",p1:o[3]})),n},"9,9":function(t,e){return a.go(e,"9,9")}},createTransitions:function(t){var e,n,o,a,r={};for(e in t)for(n in t[e])for(o=n.split("|"),t[e][n].stateArray=o,a=0;a<o.length;a++)r[o[a]]=[];for(e in t)for(n in t[e])for(o=t[e][n].stateArray||[],a=0;a<o.length;a++){var i=t[e][n];if(i.action_){i.action_=[].concat(i.action_);for(var c=0;c<i.action_.length;c++)"string"==typeof i.action_[c]&&(i.action_[c]={type_:i.action_[c]})}else i.action_=[];for(var u=e.split("|"),p=0;p<u.length;p++)if("*"===o[a])for(var s in r)r[s].push({pattern:u[p],task:i});else r[o[a]].push({pattern:u[p],task:i})}return r},stateMachines:{}};a.stateMachines={ce:{transitions:a.createTransitions({empty:{"*":{action_:"output"}},else:{"0|1|2":{action_:"beginsWithBond=false",revisit:!0,toContinue:!0}},oxidation$:{0:{action_:"oxidation-output"}},CMT:{r:{action_:"rdt=",nextState:"rt"},rd:{action_:"rqt=",nextState:"rdt"}},arrowUpDown:{"0|1|2|as":{action_:["sb=false","output","operator"],nextState:"1"}},uprightEntities:{"0|1|2":{action_:["o=","output"],nextState:"1"}},orbital:{"0|1|2|3":{action_:"o=",nextState:"o"}},"->":{"0|1|2|3":{action_:"r=",nextState:"r"},"a|as":{action_:["output","r="],nextState:"r"},"*":{action_:["output","r="],nextState:"r"}},"+":{o:{action_:"d= kv",nextState:"d"},"d|D":{action_:"d=",nextState:"d"},q:{action_:"d=",nextState:"qd"},"qd|qD":{action_:"d=",nextState:"qd"},dq:{action_:["output","d="],nextState:"d"},3:{action_:["sb=false","output","operator"],nextState:"0"}},amount:{"0|2":{action_:"a=",nextState:"a"}},"pm-operator":{"0|1|2|a|as":{action_:["sb=false","output",{type_:"operator",option:"\\pm"}],nextState:"0"}},operator:{"0|1|2|a|as":{action_:["sb=false","output","operator"],nextState:"0"}},"-$":{"o|q":{action_:["charge or bond","output"],nextState:"qd"},d:{action_:"d=",nextState:"d"},D:{action_:["output",{type_:"bond",option:"-"}],nextState:"3"},q:{action_:"d=",nextState:"qd"},qd:{action_:"d=",nextState:"qd"},"qD|dq":{action_:["output",{type_:"bond",option:"-"}],nextState:"3"}},"-9":{"3|o":{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"3"}},"- orbital overlap":{o:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"},d:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"}},"-":{"0|1|2":{action_:[{type_:"output",option:1},"beginsWithBond=true",{type_:"bond",option:"-"}],nextState:"3"},3:{action_:{type_:"bond",option:"-"}},a:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"},as:{action_:[{type_:"output",option:2},{type_:"bond",option:"-"}],nextState:"3"},b:{action_:"b="},o:{action_:{type_:"- after o/d",option:!1},nextState:"2"},q:{action_:{type_:"- after o/d",option:!1},nextState:"2"},"d|qd|dq":{action_:{type_:"- after o/d",option:!0},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"}},"^_":{"*":{}},"^{(...)}|^($...$)":{"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="},"0|1|2|3|as|b|p|bp|o":{action_:"o=",nextState:"o"},"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:!0},as:{action_:["output","sb=true"],nextState:"1",revisit:!0},"r|rt|rd|rdt|rdq":{action_:["output"],nextState:"0",revisit:!0},"*":{action_:["output","copy"],nextState:"3"}}}),actions:{"o after d":function(t,e){var n;if((t.d||"").match(/^[0-9]+$/)){var o=t.d;t.d=void 0,n=this.output(t),t.b=o}else n=this.output(t);return a.actions["o="](t,e),n},"d= kv":function(t,e){t.d=e,t.dType="kv"},"charge or bond":function(t,e){if(t.beginsWithBond){var n=[];return a.concatArray(n,this.output(t)),a.concatArray(n,a.actions.bond(t,e,"-")),n}t.d=e},"- after o/d":function(t,e,n){var o=a.patterns.match_("orbital",t.o||""),r=a.patterns.match_("one lowercase greek letter $",t.o||""),i=a.patterns.match_("one lowercase latin letter $",t.o||""),c=a.patterns.match_("$one lowercase latin letter$ $",t.o||""),u="-"===e&&(o&&""===o.remainder||r||i||c);!u||t.a||t.b||t.p||t.d||t.q||o||!i||(t.o="$"+t.o+"$");var p=[];return u?(a.concatArray(p,this.output(t)),p.push({type_:"hyphen"})):(o=a.patterns.match_("digits",t.d||""),n&&o&&""===o.remainder?(a.concatArray(p,a.actions["d="](t,e)),a.concatArray(p,this.output(t))):(a.concatArray(p,this.output(t)),a.concatArray(p,a.actions.bond(t,e,"-")))),p},"a to o":function(t){t.o=t.a,t.a=void 0},"sb=true":function(t){t.sb=!0},"sb=false":function(t){t.sb=!1},"beginsWithBond=true":function(t){t.beginsWithBond=!0},"beginsWithBond=false":function(t){t.beginsWithBond=!1},"parenthesisLevel++":function(t){t.parenthesisLevel++},"parenthesisLevel--":function(t){t.parenthesisLevel--},"state of aggregation":function(t,e){return{type_:"state of aggregation",p1:a.go(e,"o")}},comma:function(t,e){var n=e.replace(/\s*$/,"");return n!==e&&0===t.parenthesisLevel?{type_:"comma enumeration L",p1:n}:{type_:"comma enumeration M",p1:n}},output:function(t,e,n){var o,r,i;t.r?(r="M"===t.rdt?a.go(t.rd,"tex-math"):"T"===t.rdt?[{type_:"text",p1:t.rd||""}]:a.go(t.rd),i="M"===t.rqt?a.go(t.rq,"tex-math"):"T"===t.rqt?[{type_:"text",p1:t.rq||""}]:a.go(t.rq),o={type_:"arrow",r:t.r,rd:r,rq:i}):(o=[],(t.a||t.b||t.p||t.o||t.q||t.d||n)&&(t.sb&&o.push({type_:"entitySkip"}),t.o||t.q||t.d||t.b||t.p||2===n?t.o||t.q||t.d||!t.b&&!t.p?t.o&&"kv"===t.dType&&a.patterns.match_("d-oxidation$",t.d||"")?t.dType="oxidation":t.o&&"kv"===t.dType&&!t.q&&(t.dType=void 0):(t.o=t.a,t.d=t.b,t.q=t.p,t.a=t.b=t.p=void 0):(t.o=t.a,t.a=void 0),o.push({type_:"chemfive",a:a.go(t.a,"a"),b:a.go(t.b,"bd"),p:a.go(t.p,"pq"),o:a.go(t.o,"o"),q:a.go(t.q,"pq"),d:a.go(t.d,"oxidation"===t.dType?"oxidation":"bd"),dType:t.dType})));for(var c in t)"parenthesisLevel"!==c&&"beginsWithBond"!==c&&delete t[c];return o},"oxidation-output":function(t,e){var n=["{"];return a.concatArray(n,a.go(e,"oxidation")),n.push("}"),n},"frac-output":function(t,e){return{type_:"frac-ce",p1:a.go(e[0]),p2:a.go(e[1])}},"overset-output":function(t,e){return{type_:"overset",p1:a.go(e[0]),p2:a.go(e[1])}},"underset-output":function(t,e){return{type_:"underset",p1:a.go(e[0]),p2:a.go(e[1])}},"underbrace-output":function(t,e){return{type_:"underbrace",p1:a.go(e[0]),p2:a.go(e[1])}},"color-output":function(t,e){return{type_:"color",color1:e[0],color2:a.go(e[1])}},"r=":function(t,e){t.r=e},"rdt=":function(t,e){t.rdt=e},"rd=":function(t,e){t.rd=e},"rqt=":function(t,e){t.rqt=e},"rq=":function(t,e){t.rq=e},operator:function(t,e,n){return{type_:"operator",kind_:n||e}}}},a:{transitions:a.createTransitions({empty:{"*":{}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"1",revisit:!0}},"$(...)$":{"*":{action_:"tex-math tight",nextState:"1"}},",":{"*":{action_:{type_:"insert",option:"commaDecimal"}}},else2:{"*":{action_:"copy"}}}),actions:{}},o:{transitions:a.createTransitions({empty:{"*":{}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"1",revisit:!0}},letters:{"*":{action_:"rm"}},"\\ca":{"*":{action_:{type_:"insert",option:"circa"}}},"\\x{}{}|\\x{}|\\x":{"*":{action_:"copy"}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"{(...)}":{"*":{action_:"{text}"}},else2:{"*":{action_:"copy"}}}),actions:{}},text:{transitions:a.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(t){if(t.text_){var e={type_:"text",p1:t.text_};for(var n in t)delete t[n];return e}}}},pq:{transitions:a.createTransitions({empty:{"*":{}},"state of aggregation $":{"*":{action_:"state of aggregation"}},i$:{0:{nextState:"!f",revisit:!0}},"(KV letters),":{0:{action_:"rm",nextState:"0"}},formula$:{0:{nextState:"f",revisit:!0}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"!f",revisit:!0}},"${(...)}$|$(...)$":{"*":{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(t,e){return{type_:"state of aggregation subscript",p1:a.go(e,"o")}},"color-output":function(t,e){return{type_:"color",color1:e[0],color2:a.go(e[1],"pq")}}}},bd:{transitions:a.createTransitions({empty:{"*":{}},x$:{0:{nextState:"!f",revisit:!0}},formula$:{0:{nextState:"f",revisit:!0}},else:{0:{nextState:"!f",revisit:!0}},"-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(t,e){return{type_:"color",color1:e[0],color2:a.go(e[1],"bd")}}}},oxidation:{transitions:a.createTransitions({empty:{"*":{}},"roman numeral":{"*":{action_:"roman-numeral"}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},else:{"*":{action_:"copy"}}}),actions:{"roman-numeral":function(t,e){return{type_:"roman numeral",p1:e||""}}}},"tex-math":{transitions:a.createTransitions({empty:{"*":{action_:"output"}},"\\ce{(...)}":{"*":{action_:["output","ce"]}},"{...}|\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"o="}},else:{"*":{action_:"o="}}}),actions:{output:function(t){if(t.o){var e={type_:"tex-math",p1:t.o};for(var n in t)delete t[n];return e}}}},"tex-math tight":{transitions:a.createTransitions({empty:{"*":{action_:"output"}},"\\ce{(...)}":{"*":{action_:["output","ce"]}},"{...}|\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"o="}},"-|+":{"*":{action_:"tight operator"}},else:{"*":{action_:"o="}}}),actions:{"tight operator":function(t,e){t.o=(t.o||"")+"{"+e+"}"},output:function(t){if(t.o){var e={type_:"tex-math",p1:t.o};for(var n in t)delete t[n];return e}}}},"9,9":{transitions:a.createTransitions({empty:{"*":{}},",":{"*":{action_:"comma"}},else:{"*":{action_:"copy"}}}),actions:{comma:function(){return{type_:"commaDecimal"}}}},pu:{transitions:a.createTransitions({empty:{"*":{action_:"output"}},space$:{"*":{action_:["output","space"]}},"{[(|)]}":{"0|a":{action_:"copy"}},"(-)(9)^(-9)":{0:{action_:"number^",nextState:"a"}},"(-)(9.,9)(e)(99)":{0:{action_:"enumber",nextState:"a"}},space:{"0|a":{}},"pm-operator":{"0|a":{action_:{type_:"operator",option:"\\pm"},nextState:"0"}},operator:{"0|a":{action_:"copy",nextState:"0"}},"//":{d:{action_:"o=",nextState:"/"}},"/":{d:{action_:"o=",nextState:"/"}},"{...}|else":{"0|d":{action_:"d=",nextState:"d"},a:{action_:["space","d="],nextState:"d"},"/|q":{action_:"q=",nextState:"q"}}}),actions:{enumber:function(t,e){var n=[];return"+-"===e[0]||"+/-"===e[0]?n.push("\\pm "):e[0]&&n.push(e[0]),e[1]&&(a.concatArray(n,a.go(e[1],"pu-9,9")),e[2]&&(e[2].match(/[,.]/)?a.concatArray(n,a.go(e[2],"pu-9,9")):n.push(e[2])),e[3]=e[4]||e[3],e[3]&&(e[3]=e[3].trim(),"e"===e[3]||"*"===e[3].substr(0,1)?n.push({type_:"cdot"}):n.push({type_:"times"}))),e[3]&&n.push("10^{"+e[5]+"}"),n},"number^":function(t,e){var n=[];return"+-"===e[0]||"+/-"===e[0]?n.push("\\pm "):e[0]&&n.push(e[0]),a.concatArray(n,a.go(e[1],"pu-9,9")),n.push("^{"+e[2]+"}"),n},operator:function(t,e,n){return{type_:"operator",kind_:n||e}},space:function(){return{type_:"pu-space-1"}},output:function(t){var e,n=a.patterns.match_("{(...)}",t.d||"");n&&""===n.remainder&&(t.d=n.match_);var o=a.patterns.match_("{(...)}",t.q||"");if(o&&""===o.remainder&&(t.q=o.match_),t.d&&(t.d=t.d.replace(/\u00B0C|\^oC|\^{o}C/g,"{}^{\\circ}C"),t.d=t.d.replace(/\u00B0F|\^oF|\^{o}F/g,"{}^{\\circ}F")),t.q){t.q=t.q.replace(/\u00B0C|\^oC|\^{o}C/g,"{}^{\\circ}C"),t.q=t.q.replace(/\u00B0F|\^oF|\^{o}F/g,"{}^{\\circ}F");var r={d:a.go(t.d,"pu"),q:a.go(t.q,"pu")};"//"===t.o?e={type_:"pu-frac",p1:r.d,p2:r.q}:(e=r.d,r.d.length>1||r.q.length>1?e.push({type_:" / "}):e.push({type_:"/"}),a.concatArray(e,r.q))}else e=a.go(t.d,"pu-2");for(var i in t)delete t[i];return e}}},"pu-2":{transitions:a.createTransitions({empty:{"*":{action_:"output"}},"*":{"*":{action_:["output","cdot"],nextState:"0"}},"\\x":{"*":{action_:"rm="}},space:{"*":{action_:["output","space"],nextState:"0"}},"^{(...)}|^(-1)":{1:{action_:"^(-1)"}},"-9.,9":{0:{action_:"rm=",nextState:"0"},1:{action_:"^(-1)",nextState:"0"}},"{...}|else":{"*":{action_:"rm=",nextState:"1"}}}),actions:{cdot:function(){return{type_:"tight cdot"}},"^(-1)":function(t,e){t.rm+="^{"+e+"}"},space:function(){return{type_:"pu-space-2"}},output:function(t){var e=[];if(t.rm){var n=a.patterns.match_("{(...)}",t.rm||"");e=n&&""===n.remainder?a.go(n.match_,"pu"):{type_:"rm",p1:t.rm}}for(var o in t)delete t[o];return e}}},"pu-9,9":{transitions:a.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(){return{type_:"commaDecimal"}},"output-0":function(t){var e=[];if(t.text_=t.text_||"",t.text_.length>4){var n=t.text_.length%3;0===n&&(n=3);for(var o=t.text_.length-3;o>0;o-=3)e.push(t.text_.substr(o,3)),e.push({type_:"1000 separator"});e.push(t.text_.substr(0,n)),e.reverse()}else e.push(t.text_);for(var a in t)delete t[a];return e},"output-o":function(t){var e=[];if(t.text_=t.text_||"",t.text_.length>4){for(var n=t.text_.length-3,o=0;o<n;o+=3)e.push(t.text_.substr(o,3)),e.push({type_:"1000 separator"});e.push(t.text_.substr(o))}else e.push(t.text_);for(var a in t)delete t[a];return e}}}};var r={go:function(t,e){if(!t)return"";for(var n="",o=!1,a=0;a<t.length;a++){var i=t[a];"string"==typeof i?n+=i:(n+=r._go2(i),"1st-level escape"===i.type_&&(o=!0))}return e||o||!n||(n="{"+n+"}"),n},_goInner:function(t){return t?r.go(t,!0):t},_go2:function(t){var e;switch(t.type_){case"chemfive":e="";var n={a:r._goInner(t.a),b:r._goInner(t.b),p:r._goInner(t.p),o:r._goInner(t.o),q:r._goInner(t.q),d:r._goInner(t.d)};n.a&&(n.a.match(/^[+\-]/)&&(n.a="{"+n.a+"}"),e+=n.a+"\\,"),(n.b||n.p)&&(e+="{\\vphantom{X}}",e+="^{\\hphantom{"+(n.b||"")+"}}_{\\hphantom{"+(n.p||"")+"}}",e+="{\\vphantom{X}}",e+="^{\\smash[t]{\\vphantom{2}}\\mathllap{"+(n.b||"")+"}}",e+="_{\\vphantom{2}\\mathllap{\\smash[t]{"+(n.p||"")+"}}}"),n.o&&(n.o.match(/^[+\-]/)&&(n.o="{"+n.o+"}"),e+=n.o),"kv"===t.dType?((n.d||n.q)&&(e+="{\\vphantom{X}}"),n.d&&(e+="^{"+n.d+"}"),n.q&&(e+="_{\\smash[t]{"+n.q+"}}")):"oxidation"===t.dType?(n.d&&(e+="{\\vphantom{X}}",e+="^{"+n.d+"}"),n.q&&(e+="{\\vphantom{X}}",e+="_{\\smash[t]{"+n.q+"}}")):(n.q&&(e+="{\\vphantom{X}}",e+="_{\\smash[t]{"+n.q+"}}"),n.d&&(e+="{\\vphantom{X}}",e+="^{"+n.d+"}"));break;case"rm":case"roman numeral":e="\\mathrm{"+t.p1+"}";break;case"text":t.p1.match(/[\^_]/)?(t.p1=t.p1.replace(" ","~").replace("-","\\text{-}"),e="\\mathrm{"+t.p1+"}"):e="\\text{"+t.p1+"}";break;case"state of aggregation":e="\\mskip2mu "+r._goInner(t.p1);break;case"state of aggregation subscript":e="\\mskip1mu "+r._goInner(t.p1);break;case"bond":if(!(e=r._getBond(t.kind_)))throw["MhchemErrorBond","mhchem Error. Unknown bond type ("+t.kind_+")"];break;case"frac":var o="\\frac{"+t.p1+"}{"+t.p2+"}";e="\\mathchoice{\\textstyle"+o+"}{"+o+"}{"+o+"}{"+o+"}";break;case"pu-frac":var a="\\frac{"+r._goInner(t.p1)+"}{"+r._goInner(t.p2)+"}";e="\\mathchoice{\\textstyle"+a+"}{"+a+"}{"+a+"}{"+a+"}";break;case"tex-math":case"1st-level escape":e=t.p1+" ";break;case"frac-ce":e="\\frac{"+r._goInner(t.p1)+"}{"+r._goInner(t.p2)+"}";break;case"overset":e="\\overset{"+r._goInner(t.p1)+"}{"+r._goInner(t.p2)+"}";break;case"underset":e="\\underset{"+r._goInner(t.p1)+"}{"+r._goInner(t.p2)+"}";break;case"underbrace":e="\\underbrace{"+r._goInner(t.p1)+"}_{"+r._goInner(t.p2)+"}";break;case"color":e="{\\color{"+t.color1+"}{"+r._goInner(t.color2)+"}}";break;case"color0":e="\\color{"+t.color+"}";break;case"arrow":var i={rd:r._goInner(t.rd),rq:r._goInner(t.rq)},c="\\x"+r._getArrow(t.r);i.rq&&(c+="[{"+i.rq+"}]"),e=c+=i.rd?"{"+i.rd+"}":"{}";break;case"operator":e=r._getOperator(t.kind_);break;case"space":e=" ";break;case"entitySkip":case"pu-space-1":e="~";break;case"pu-space-2":e="\\mkern3mu ";break;case"1000 separator":e="\\mkern2mu ";break;case"commaDecimal":e="{,}";break;case"comma enumeration L":e="{"+t.p1+"}\\mkern6mu ";break;case"comma enumeration M":e="{"+t.p1+"}\\mkern3mu ";break;case"comma enumeration S":e="{"+t.p1+"}\\mkern1mu ";break;case"hyphen":e="\\text{-}";break;case"addition compound":e="\\,{\\cdot}\\,";break;case"electron dot":e="\\mkern1mu \\bullet\\mkern1mu ";break;case"KV x":e="{\\times}";break;case"prime":e="\\prime ";break;case"cdot":e="\\cdot ";break;case"tight cdot":e="\\mkern1mu{\\cdot}\\mkern1mu ";break;case"times":e="\\times ";break;case"circa":e="{\\sim}";break;case"^":e="uparrow";break;case"v":e="downarrow";break;case"ellipsis":e="\\ldots ";break;case"/":e="/";break;case" / ":e="\\,/\\,";break;default:throw["MhchemBugT","mhchem bug T. Please report."]}return e},_getArrow:function(t){switch(t){case"->":case"\u2192":case"\u27f6":return"rightarrow";case"<-":return"leftarrow";case"<->":return"leftrightarrow";case"<--\x3e":return"rightleftarrows";case"<=>":case"\u21cc":return"rightleftharpoons";case"<=>>":return"rightequilibrium";case"<<=>":return"leftequilibrium";default:throw["MhchemBugT","mhchem bug T. Please report."]}},_getBond:function(t){switch(t){case"-":case"1":return"{-}";case"=":case"2":return"{=}";case"#":case"3":return"{\\equiv}";case"~":return"{\\tripledash}";case"~-":return"{\\mathrlap{\\raisebox{-.1em}{$-$}}\\raisebox{.1em}{$\\tripledash$}}";case"~=":case"~--":return"{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}";case"-~-":return"{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$-$}}\\tripledash}";case"...":return"{{\\cdot}{\\cdot}{\\cdot}}";case"....":return"{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}";case"->":return"{\\rightarrow}";case"<-":return"{\\leftarrow}";case"<":return"{<}";case">":return"{>}";default:throw["MhchemBugT","mhchem bug T. Please report."]}},_getOperator:function(t){switch(t){case"+":return" {}+{} ";case"-":return" {}-{} ";case"=":return" {}={} ";case"<":return" {}<{} ";case">":return" {}>{} ";case"<<":return" {}\\ll{} ";case">>":return" {}\\gg{} ";case"\\pm":return" {}\\pm{} ";case"\\approx":case"$\\approx$":return" {}\\approx{} ";case"v":case"(v)":return" \\downarrow{} ";case"^":case"(^)":return" \\uparrow{} ";default:throw["MhchemBugT","mhchem bug T. Please report."]}}}}(),a=a.default}()}));
mhchem.mjs
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/mhchem.mjs'
View Content
import katex from '../katex.mjs';

/* eslint-disable */

/* -*- Mode: JavaScript; indent-tabs-mode:nil; js-indent-level: 2 -*- */

/* vim: set ts=2 et sw=2 tw=80: */

/*************************************************************
 *
 *  KaTeX mhchem.js
 *
 *  This file implements a KaTeX version of mhchem version 3.3.0.
 *  It is adapted from MathJax/extensions/TeX/mhchem.js
 *  It differs from the MathJax version as follows:
 *    1. The interface is changed so that it can be called from KaTeX, not MathJax.
 *    2. \rlap and \llap are replaced with \mathrlap and \mathllap.
 *    3. Four lines of code are edited in order to use \raisebox instead of \raise.
 *    4. The reaction arrow code is simplified. All reaction arrows are rendered
 *       using KaTeX extensible arrows instead of building non-extensible arrows.
 *    5. \tripledash vertical alignment is slightly adjusted.
 *
 *    This code, as other KaTeX code, is released under the MIT license.
 * 
 * /*************************************************************
 *
 *  MathJax/extensions/TeX/mhchem.js
 *
 *  Implements the \ce command for handling chemical formulas
 *  from the mhchem LaTeX package.
 *
 *  ---------------------------------------------------------------------
 *
 *  Copyright (c) 2011-2015 The MathJax Consortium
 *  Copyright (c) 2015-2018 Martin Hensel
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
//
// Coding Style
//   - use '' for identifiers that can by minified/uglified
//   - use "" for strings that need to stay untouched
// version: "3.3.0" for MathJax and KaTeX
// Add \ce, \pu, and \tripledash to the KaTeX macros.
katex.__defineMacro("\\ce", function (context) {
  return chemParse(context.consumeArgs(1)[0], "ce");
});

katex.__defineMacro("\\pu", function (context) {
  return chemParse(context.consumeArgs(1)[0], "pu");
}); //  Needed for \bond for the ~ forms
//  Raise by 2.56mu, not 2mu. We're raising a hyphen-minus, U+002D, not 
//  a mathematical minus, U+2212. So we need that extra 0.56.


katex.__defineMacro("\\tripledash", "{\\vphantom{-}\\raisebox{2.56mu}{$\\mkern2mu" + "\\tiny\\text{-}\\mkern1mu\\text{-}\\mkern1mu\\text{-}\\mkern2mu$}}");
//  This is the main function for handing the \ce and \pu commands.
//  It takes the argument to \ce or \pu and returns the corresponding TeX string.
//

var chemParse = function chemParse(tokens, stateMachine) {
  // Recreate the argument string from KaTeX's array of tokens.
  var str = "";
  var expectedLoc = tokens.length && tokens[tokens.length - 1].loc.start;

  for (var i = tokens.length - 1; i >= 0; i--) {
    if (tokens[i].loc.start > expectedLoc) {
      // context.consumeArgs has eaten a space.
      str += " ";
      expectedLoc = tokens[i].loc.start;
    }

    str += tokens[i].text;
    expectedLoc += tokens[i].text.length;
  }

  var tex = texify.go(mhchemParser.go(str, stateMachine));
  return tex;
}; //
// Core parser for mhchem syntax  (recursive)
//

/** @type {MhchemParser} */


var mhchemParser = {
  //
  // Parses mchem \ce syntax
  //
  // Call like
  //   go("H2O");
  //
  go: function go(input, stateMachine) {
    if (!input) {
      return [];
    }

    if (stateMachine === undefined) {
      stateMachine = 'ce';
    }

    var state = '0'; //
    // String buffers for parsing:
    //
    // buffer.a == amount
    // buffer.o == element
    // buffer.b == left-side superscript
    // buffer.p == left-side subscript
    // buffer.q == right-side subscript
    // buffer.d == right-side superscript
    //
    // buffer.r == arrow
    // buffer.rdt == arrow, script above, type
    // buffer.rd == arrow, script above, content
    // buffer.rqt == arrow, script below, type
    // buffer.rq == arrow, script below, content
    //
    // buffer.text_
    // buffer.rm
    // etc.
    //
    // buffer.parenthesisLevel == int, starting at 0
    // buffer.sb == bool, space before
    // buffer.beginsWithBond == bool
    //
    // These letters are also used as state names.
    //
    // Other states:
    // 0 == begin of main part (arrow/operator unlikely)
    // 1 == next entity
    // 2 == next entity (arrow/operator unlikely)
    // 3 == next atom
    // c == macro
    //

    /** @type {Buffer} */

    var buffer = {};
    buffer['parenthesisLevel'] = 0;
    input = input.replace(/\n/g, " ");
    input = input.replace(/[\u2212\u2013\u2014\u2010]/g, "-");
    input = input.replace(/[\u2026]/g, "..."); //
    // Looks through mhchemParser.transitions, to execute a matching action
    // (recursive)
    //

    var lastInput;
    var watchdog = 10;
    /** @type {ParserOutput[]} */

    var output = [];

    while (true) {
      if (lastInput !== input) {
        watchdog = 10;
        lastInput = input;
      } else {
        watchdog--;
      } //
      // Find actions in transition table
      //


      var machine = mhchemParser.stateMachines[stateMachine];
      var t = machine.transitions[state] || machine.transitions['*'];

      iterateTransitions: for (var i = 0; i < t.length; i++) {
        var matches = mhchemParser.patterns.match_(t[i].pattern, input);

        if (matches) {
          //
          // Execute actions
          //
          var task = t[i].task;

          for (var iA = 0; iA < task.action_.length; iA++) {
            var o; //
            // Find and execute action
            //

            if (machine.actions[task.action_[iA].type_]) {
              o = machine.actions[task.action_[iA].type_](buffer, matches.match_, task.action_[iA].option);
            } else if (mhchemParser.actions[task.action_[iA].type_]) {
              o = mhchemParser.actions[task.action_[iA].type_](buffer, matches.match_, task.action_[iA].option);
            } else {
              throw ["MhchemBugA", "mhchem bug A. Please report. (" + task.action_[iA].type_ + ")"]; // Trying to use non-existing action
            } //
            // Add output
            //


            mhchemParser.concatArray(output, o);
          } //
          // Set next state,
          // Shorten input,
          // Continue with next character
          //   (= apply only one transition per position)
          //


          state = task.nextState || state;

          if (input.length > 0) {
            if (!task.revisit) {
              input = matches.remainder;
            }

            if (!task.toContinue) {
              break iterateTransitions;
            }
          } else {
            return output;
          }
        }
      } //
      // Prevent infinite loop
      //


      if (watchdog <= 0) {
        throw ["MhchemBugU", "mhchem bug U. Please report."]; // Unexpected character
      }
    }
  },
  concatArray: function concatArray(a, b) {
    if (b) {
      if (Array.isArray(b)) {
        for (var iB = 0; iB < b.length; iB++) {
          a.push(b[iB]);
        }
      } else {
        a.push(b);
      }
    }
  },
  patterns: {
    //
    // Matching patterns
    // either regexps or function that return null or {match_:"a", remainder:"bc"}
    //
    patterns: {
      // property names must not look like integers ("2") for correct property traversal order, later on
      'empty': /^$/,
      'else': /^./,
      'else2': /^./,
      'space': /^\s/,
      'space A': /^\s(?=[A-Z\\$])/,
      'space$': /^\s$/,
      'a-z': /^[a-z]/,
      'x': /^x/,
      'x$': /^x$/,
      'i$': /^i$/,
      'letters': /^(?:[a-zA-Z\u03B1-\u03C9\u0391-\u03A9?@]|(?:\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))))+/,
      '\\greek': /^\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))/,
      'one lowercase latin letter $': /^(?:([a-z])(?:$|[^a-zA-Z]))$/,
      '$one lowercase latin letter$ $': /^\$(?:([a-z])(?:$|[^a-zA-Z]))\$$/,
      'one lowercase greek letter $': /^(?:\$?[\u03B1-\u03C9]\$?|\$?\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega)\s*\$?)(?:\s+|\{\}|(?![a-zA-Z]))$/,
      'digits': /^[0-9]+/,
      '-9.,9': /^[+\-]?(?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))/,
      '-9.,9 no missing 0': /^[+\-]?[0-9]+(?:[.,][0-9]+)?/,
      '(-)(9.,9)(e)(99)': function e99(input) {
        var m = input.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))?(\((?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))\))?(?:([eE]|\s*(\*|x|\\times|\u00D7)\s*10\^)([+\-]?[0-9]+|\{[+\-]?[0-9]+\}))?/);

        if (m && m[0]) {
          return {
            match_: m.splice(1),
            remainder: input.substr(m[0].length)
          };
        }

        return null;
      },
      '(-)(9)^(-9)': function _(input) {
        var m = input.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+)?)\^([+\-]?[0-9]+|\{[+\-]?[0-9]+\})/);

        if (m && m[0]) {
          return {
            match_: m.splice(1),
            remainder: input.substr(m[0].length)
          };
        }

        return null;
      },
      'state of aggregation $': function stateOfAggregation$(input) {
        // ... or crystal system
        var a = mhchemParser.patterns.findObserveGroups(input, "", /^\([a-z]{1,3}(?=[\),])/, ")", ""); // (aq), (aq,$\infty$), (aq, sat)

        if (a && a.remainder.match(/^($|[\s,;\)\]\}])/)) {
          return a;
        } //  AND end of 'phrase'


        var m = input.match(/^(?:\((?:\\ca\s?)?\$[amothc]\$\))/); // OR crystal system ($o$) (\ca$c$)

        if (m) {
          return {
            match_: m[0],
            remainder: input.substr(m[0].length)
          };
        }

        return null;
      },
      '_{(state of aggregation)}$': /^_\{(\([a-z]{1,3}\))\}/,
      '{[(': /^(?:\\\{|\[|\()/,
      ')]}': /^(?:\)|\]|\\\})/,
      ', ': /^[,;]\s*/,
      ',': /^[,;]/,
      '.': /^[.]/,
      '. ': /^([.\u22C5\u00B7\u2022])\s*/,
      '...': /^\.\.\.(?=$|[^.])/,
      '* ': /^([*])\s*/,
      '^{(...)}': function _(input) {
        return mhchemParser.patterns.findObserveGroups(input, "^{", "", "", "}");
      },
      '^($...$)': function $$(input) {
        return mhchemParser.patterns.findObserveGroups(input, "^", "$", "$", "");
      },
      '^a': /^\^([0-9]+|[^\\_])/,
      '^\\x{}{}': function x(input) {
        return mhchemParser.patterns.findObserveGroups(input, "^", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true);
      },
      '^\\x{}': function x(input) {
        return mhchemParser.patterns.findObserveGroups(input, "^", /^\\[a-zA-Z]+\{/, "}", "");
      },
      '^\\x': /^\^(\\[a-zA-Z]+)\s*/,
      '^(-1)': /^\^(-?\d+)/,
      '\'': /^'/,
      '_{(...)}': function _(input) {
        return mhchemParser.patterns.findObserveGroups(input, "_{", "", "", "}");
      },
      '_($...$)': function _$$(input) {
        return mhchemParser.patterns.findObserveGroups(input, "_", "$", "$", "");
      },
      '_9': /^_([+\-]?[0-9]+|[^\\])/,
      '_\\x{}{}': function _X(input) {
        return mhchemParser.patterns.findObserveGroups(input, "_", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true);
      },
      '_\\x{}': function _X(input) {
        return mhchemParser.patterns.findObserveGroups(input, "_", /^\\[a-zA-Z]+\{/, "}", "");
      },
      '_\\x': /^_(\\[a-zA-Z]+)\s*/,
      '^_': /^(?:\^(?=_)|\_(?=\^)|[\^_]$)/,
      '{}': /^\{\}/,
      '{...}': function _(input) {
        return mhchemParser.patterns.findObserveGroups(input, "", "{", "}", "");
      },
      '{(...)}': function _(input) {
        return mhchemParser.patterns.findObserveGroups(input, "{", "", "", "}");
      },
      '$...$': function $$(input) {
        return mhchemParser.patterns.findObserveGroups(input, "", "$", "$", "");
      },
      '${(...)}$': function $$(input) {
        return mhchemParser.patterns.findObserveGroups(input, "${", "", "", "}$");
      },
      '$(...)$': function $$(input) {
        return mhchemParser.patterns.findObserveGroups(input, "$", "", "", "$");
      },
      '=<>': /^[=<>]/,
      '#': /^[#\u2261]/,
      '+': /^\+/,
      '-$': /^-(?=[\s_},;\]/]|$|\([a-z]+\))/,
      // -space -, -; -] -/ -$ -state-of-aggregation
      '-9': /^-(?=[0-9])/,
      '- orbital overlap': /^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/,
      '-': /^-/,
      'pm-operator': /^(?:\\pm|\$\\pm\$|\+-|\+\/-)/,
      'operator': /^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/,
      'arrowUpDown': /^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/,
      '\\bond{(...)}': function bond(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\bond{", "", "", "}");
      },
      '->': /^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/,
      'CMT': /^[CMT](?=\[)/,
      '[(...)]': function _(input) {
        return mhchemParser.patterns.findObserveGroups(input, "[", "", "", "]");
      },
      '1st-level escape': /^(&|\\\\|\\hline)\s*/,
      '\\,': /^(?:\\[,\ ;:])/,
      // \\x - but output no space before
      '\\x{}{}': function x(input) {
        return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true);
      },
      '\\x{}': function x(input) {
        return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", "");
      },
      '\\ca': /^\\ca(?:\s+|(?![a-zA-Z]))/,
      '\\x': /^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/,
      'orbital': /^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/,
      // only those with numbers in front, because the others will be formatted correctly anyway
      'others': /^[\/~|]/,
      '\\frac{(...)}': function frac(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\frac{", "", "", "}", "{", "", "", "}");
      },
      '\\overset{(...)}': function overset(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\overset{", "", "", "}", "{", "", "", "}");
      },
      '\\underset{(...)}': function underset(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\underset{", "", "", "}", "{", "", "", "}");
      },
      '\\underbrace{(...)}': function underbrace(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\underbrace{", "", "", "}_", "{", "", "", "}");
      },
      '\\color{(...)}0': function color0(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}");
      },
      '\\color{(...)}{(...)}1': function color1(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}", "{", "", "", "}");
      },
      '\\color(...){(...)}2': function color2(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\color", "\\", "", /^(?=\{)/, "{", "", "", "}");
      },
      '\\ce{(...)}': function ce(input) {
        return mhchemParser.patterns.findObserveGroups(input, "\\ce{", "", "", "}");
      },
      'oxidation$': /^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,
      'd-oxidation$': /^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,
      // 0 could be oxidation or charge
      'roman numeral': /^[IVX]+/,
      '1/2$': /^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/,
      'amount': function amount(input) {
        var match; // e.g. 2, 0.5, 1/2, -2, n/2, +;  $a$ could be added later in parsing

        match = input.match(/^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/);

        if (match) {
          return {
            match_: match[0],
            remainder: input.substr(match[0].length)
          };
        }

        var a = mhchemParser.patterns.findObserveGroups(input, "", "$", "$", "");

        if (a) {
          // e.g. $2n-1$, $-$
          match = a.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/);

          if (match) {
            return {
              match_: match[0],
              remainder: input.substr(match[0].length)
            };
          }
        }

        return null;
      },
      'amount2': function amount2(input) {
        return this['amount'](input);
      },
      '(KV letters),': /^(?:[A-Z][a-z]{0,2}|i)(?=,)/,
      'formula$': function formula$(input) {
        if (input.match(/^\([a-z]+\)$/)) {
          return null;
        } // state of aggregation = no formula


        var match = input.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/);

        if (match) {
          return {
            match_: match[0],
            remainder: input.substr(match[0].length)
          };
        }

        return null;
      },
      'uprightEntities': /^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/,
      '/': /^\s*(\/)\s*/,
      '//': /^\s*(\/\/)\s*/,
      '*': /^\s*[*.]\s*/
    },
    findObserveGroups: function findObserveGroups(input, begExcl, begIncl, endIncl, endExcl, beg2Excl, beg2Incl, end2Incl, end2Excl, combine) {
      /** @type {{(input: string, pattern: string | RegExp): string | string[] | null;}} */
      var _match = function _match(input, pattern) {
        if (typeof pattern === "string") {
          if (input.indexOf(pattern) !== 0) {
            return null;
          }

          return pattern;
        } else {
          var match = input.match(pattern);

          if (!match) {
            return null;
          }

          return match[0];
        }
      };
      /** @type {{(input: string, i: number, endChars: string | RegExp): {endMatchBegin: number, endMatchEnd: number} | null;}} */


      var _findObserveGroups = function _findObserveGroups(input, i, endChars) {
        var braces = 0;

        while (i < input.length) {
          var a = input.charAt(i);

          var match = _match(input.substr(i), endChars);

          if (match !== null && braces === 0) {
            return {
              endMatchBegin: i,
              endMatchEnd: i + match.length
            };
          } else if (a === "{") {
            braces++;
          } else if (a === "}") {
            if (braces === 0) {
              throw ["ExtraCloseMissingOpen", "Extra close brace or missing open brace"];
            } else {
              braces--;
            }
          }

          i++;
        }

        if (braces > 0) {
          return null;
        }

        return null;
      };

      var match = _match(input, begExcl);

      if (match === null) {
        return null;
      }

      input = input.substr(match.length);
      match = _match(input, begIncl);

      if (match === null) {
        return null;
      }

      var e = _findObserveGroups(input, match.length, endIncl || endExcl);

      if (e === null) {
        return null;
      }

      var match1 = input.substring(0, endIncl ? e.endMatchEnd : e.endMatchBegin);

      if (!(beg2Excl || beg2Incl)) {
        return {
          match_: match1,
          remainder: input.substr(e.endMatchEnd)
        };
      } else {
        var group2 = this.findObserveGroups(input.substr(e.endMatchEnd), beg2Excl, beg2Incl, end2Incl, end2Excl);

        if (group2 === null) {
          return null;
        }
        /** @type {string[]} */


        var matchRet = [match1, group2.match_];
        return {
          match_: combine ? matchRet.join("") : matchRet,
          remainder: group2.remainder
        };
      }
    },
    //
    // Matching function
    // e.g. match("a", input) will look for the regexp called "a" and see if it matches
    // returns null or {match_:"a", remainder:"bc"}
    //
    match_: function match_(m, input) {
      var pattern = mhchemParser.patterns.patterns[m];

      if (pattern === undefined) {
        throw ["MhchemBugP", "mhchem bug P. Please report. (" + m + ")"]; // Trying to use non-existing pattern
      } else if (typeof pattern === "function") {
        return mhchemParser.patterns.patterns[m](input); // cannot use cached var pattern here, because some pattern functions need this===mhchemParser
      } else {
        // RegExp
        var match = input.match(pattern);

        if (match) {
          var mm;

          if (match[2]) {
            mm = [match[1], match[2]];
          } else if (match[1]) {
            mm = match[1];
          } else {
            mm = match[0];
          }

          return {
            match_: mm,
            remainder: input.substr(match[0].length)
          };
        }

        return null;
      }
    }
  },
  //
  // Generic state machine actions
  //
  actions: {
    'a=': function a(buffer, m) {
      buffer.a = (buffer.a || "") + m;
    },
    'b=': function b(buffer, m) {
      buffer.b = (buffer.b || "") + m;
    },
    'p=': function p(buffer, m) {
      buffer.p = (buffer.p || "") + m;
    },
    'o=': function o(buffer, m) {
      buffer.o = (buffer.o || "") + m;
    },
    'q=': function q(buffer, m) {
      buffer.q = (buffer.q || "") + m;
    },
    'd=': function d(buffer, m) {
      buffer.d = (buffer.d || "") + m;
    },
    'rm=': function rm(buffer, m) {
      buffer.rm = (buffer.rm || "") + m;
    },
    'text=': function text(buffer, m) {
      buffer.text_ = (buffer.text_ || "") + m;
    },
    'insert': function insert(buffer, m, a) {
      return {
        type_: a
      };
    },
    'insert+p1': function insertP1(buffer, m, a) {
      return {
        type_: a,
        p1: m
      };
    },
    'insert+p1+p2': function insertP1P2(buffer, m, a) {
      return {
        type_: a,
        p1: m[0],
        p2: m[1]
      };
    },
    'copy': function copy(buffer, m) {
      return m;
    },
    'rm': function rm(buffer, m) {
      return {
        type_: 'rm',
        p1: m || ""
      };
    },
    'text': function text(buffer, m) {
      return mhchemParser.go(m, 'text');
    },
    '{text}': function text(buffer, m) {
      var ret = ["{"];
      mhchemParser.concatArray(ret, mhchemParser.go(m, 'text'));
      ret.push("}");
      return ret;
    },
    'tex-math': function texMath(buffer, m) {
      return mhchemParser.go(m, 'tex-math');
    },
    'tex-math tight': function texMathTight(buffer, m) {
      return mhchemParser.go(m, 'tex-math tight');
    },
    'bond': function bond(buffer, m, k) {
      return {
        type_: 'bond',
        kind_: k || m
      };
    },
    'color0-output': function color0Output(buffer, m) {
      return {
        type_: 'color0',
        color: m[0]
      };
    },
    'ce': function ce(buffer, m) {
      return mhchemParser.go(m);
    },
    '1/2': function _(buffer, m) {
      /** @type {ParserOutput[]} */
      var ret = [];

      if (m.match(/^[+\-]/)) {
        ret.push(m.substr(0, 1));
        m = m.substr(1);
      }

      var n = m.match(/^([0-9]+|\$[a-z]\$|[a-z])\/([0-9]+)(\$[a-z]\$|[a-z])?$/);
      n[1] = n[1].replace(/\$/g, "");
      ret.push({
        type_: 'frac',
        p1: n[1],
        p2: n[2]
      });

      if (n[3]) {
        n[3] = n[3].replace(/\$/g, "");
        ret.push({
          type_: 'tex-math',
          p1: n[3]
        });
      }

      return ret;
    },
    '9,9': function _(buffer, m) {
      return mhchemParser.go(m, '9,9');
    }
  },
  //
  // createTransitions
  // convert  { 'letter': { 'state': { action_: 'output' } } }  to  { 'state' => [ { pattern: 'letter', task: { action_: [{type_: 'output'}] } } ] }
  // with expansion of 'a|b' to 'a' and 'b' (at 2 places)
  //
  createTransitions: function createTransitions(o) {
    var pattern, state;
    /** @type {string[]} */

    var stateArray;
    var i; //
    // 1. Collect all states
    //

    /** @type {Transitions} */

    var transitions = {};

    for (pattern in o) {
      for (state in o[pattern]) {
        stateArray = state.split("|");
        o[pattern][state].stateArray = stateArray;

        for (i = 0; i < stateArray.length; i++) {
          transitions[stateArray[i]] = [];
        }
      }
    } //
    // 2. Fill states
    //


    for (pattern in o) {
      for (state in o[pattern]) {
        stateArray = o[pattern][state].stateArray || [];

        for (i = 0; i < stateArray.length; i++) {
          //
          // 2a. Normalize actions into array:  'text=' ==> [{type_:'text='}]
          // (Note to myself: Resolving the function here would be problematic. It would need .bind (for *this*) and currying (for *option*).)
          //

          /** @type {any} */
          var p = o[pattern][state];

          if (p.action_) {
            p.action_ = [].concat(p.action_);

            for (var k = 0; k < p.action_.length; k++) {
              if (typeof p.action_[k] === "string") {
                p.action_[k] = {
                  type_: p.action_[k]
                };
              }
            }
          } else {
            p.action_ = [];
          } //
          // 2.b Multi-insert
          //


          var patternArray = pattern.split("|");

          for (var j = 0; j < patternArray.length; j++) {
            if (stateArray[i] === '*') {
              // insert into all
              for (var t in transitions) {
                transitions[t].push({
                  pattern: patternArray[j],
                  task: p
                });
              }
            } else {
              transitions[stateArray[i]].push({
                pattern: patternArray[j],
                task: p
              });
            }
          }
        }
      }
    }

    return transitions;
  },
  stateMachines: {}
}; //
// Definition of state machines
//

mhchemParser.stateMachines = {
  //
  // \ce state machines
  //
  //#region ce
  'ce': {
    // main parser
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {
          action_: 'output'
        }
      },
      'else': {
        '0|1|2': {
          action_: 'beginsWithBond=false',
          revisit: true,
          toContinue: true
        }
      },
      'oxidation$': {
        '0': {
          action_: 'oxidation-output'
        }
      },
      'CMT': {
        'r': {
          action_: 'rdt=',
          nextState: 'rt'
        },
        'rd': {
          action_: 'rqt=',
          nextState: 'rdt'
        }
      },
      'arrowUpDown': {
        '0|1|2|as': {
          action_: ['sb=false', 'output', 'operator'],
          nextState: '1'
        }
      },
      'uprightEntities': {
        '0|1|2': {
          action_: ['o=', 'output'],
          nextState: '1'
        }
      },
      'orbital': {
        '0|1|2|3': {
          action_: 'o=',
          nextState: 'o'
        }
      },
      '->': {
        '0|1|2|3': {
          action_: 'r=',
          nextState: 'r'
        },
        'a|as': {
          action_: ['output', 'r='],
          nextState: 'r'
        },
        '*': {
          action_: ['output', 'r='],
          nextState: 'r'
        }
      },
      '+': {
        'o': {
          action_: 'd= kv',
          nextState: 'd'
        },
        'd|D': {
          action_: 'd=',
          nextState: 'd'
        },
        'q': {
          action_: 'd=',
          nextState: 'qd'
        },
        'qd|qD': {
          action_: 'd=',
          nextState: 'qd'
        },
        'dq': {
          action_: ['output', 'd='],
          nextState: 'd'
        },
        '3': {
          action_: ['sb=false', 'output', 'operator'],
          nextState: '0'
        }
      },
      'amount': {
        '0|2': {
          action_: 'a=',
          nextState: 'a'
        }
      },
      'pm-operator': {
        '0|1|2|a|as': {
          action_: ['sb=false', 'output', {
            type_: 'operator',
            option: '\\pm'
          }],
          nextState: '0'
        }
      },
      'operator': {
        '0|1|2|a|as': {
          action_: ['sb=false', 'output', 'operator'],
          nextState: '0'
        }
      },
      '-$': {
        'o|q': {
          action_: ['charge or bond', 'output'],
          nextState: 'qd'
        },
        'd': {
          action_: 'd=',
          nextState: 'd'
        },
        'D': {
          action_: ['output', {
            type_: 'bond',
            option: "-"
          }],
          nextState: '3'
        },
        'q': {
          action_: 'd=',
          nextState: 'qd'
        },
        'qd': {
          action_: 'd=',
          nextState: 'qd'
        },
        'qD|dq': {
          action_: ['output', {
            type_: 'bond',
            option: "-"
          }],
          nextState: '3'
        }
      },
      '-9': {
        '3|o': {
          action_: ['output', {
            type_: 'insert',
            option: 'hyphen'
          }],
          nextState: '3'
        }
      },
      '- orbital overlap': {
        'o': {
          action_: ['output', {
            type_: 'insert',
            option: 'hyphen'
          }],
          nextState: '2'
        },
        'd': {
          action_: ['output', {
            type_: 'insert',
            option: 'hyphen'
          }],
          nextState: '2'
        }
      },
      '-': {
        '0|1|2': {
          action_: [{
            type_: 'output',
            option: 1
          }, 'beginsWithBond=true', {
            type_: 'bond',
            option: "-"
          }],
          nextState: '3'
        },
        '3': {
          action_: {
            type_: 'bond',
            option: "-"
          }
        },
        'a': {
          action_: ['output', {
            type_: 'insert',
            option: 'hyphen'
          }],
          nextState: '2'
        },
        'as': {
          action_: [{
            type_: 'output',
            option: 2
          }, {
            type_: 'bond',
            option: "-"
          }],
          nextState: '3'
        },
        'b': {
          action_: 'b='
        },
        'o': {
          action_: {
            type_: '- after o/d',
            option: false
          },
          nextState: '2'
        },
        'q': {
          action_: {
            type_: '- after o/d',
            option: false
          },
          nextState: '2'
        },
        'd|qd|dq': {
          action_: {
            type_: '- after o/d',
            option: true
          },
          nextState: '2'
        },
        'D|qD|p': {
          action_: ['output', {
            type_: 'bond',
            option: "-"
          }],
          nextState: '3'
        }
      },
      'amount2': {
        '1|3': {
          action_: 'a=',
          nextState: 'a'
        }
      },
      'letters': {
        '0|1|2|3|a|as|b|p|bp|o': {
          action_: 'o=',
          nextState: 'o'
        },
        'q|dq': {
          action_: ['output', 'o='],
          nextState: 'o'
        },
        'd|D|qd|qD': {
          action_: 'o after d',
          nextState: 'o'
        }
      },
      'digits': {
        'o': {
          action_: 'q=',
          nextState: 'q'
        },
        'd|D': {
          action_: 'q=',
          nextState: 'dq'
        },
        'q': {
          action_: ['output', 'o='],
          nextState: 'o'
        },
        'a': {
          action_: 'o=',
          nextState: 'o'
        }
      },
      'space A': {
        'b|p|bp': {}
      },
      'space': {
        'a': {
          nextState: 'as'
        },
        '0': {
          action_: 'sb=false'
        },
        '1|2': {
          action_: 'sb=true'
        },
        'r|rt|rd|rdt|rdq': {
          action_: 'output',
          nextState: '0'
        },
        '*': {
          action_: ['output', 'sb=true'],
          nextState: '1'
        }
      },
      '1st-level escape': {
        '1|2': {
          action_: ['output', {
            type_: 'insert+p1',
            option: '1st-level escape'
          }]
        },
        '*': {
          action_: ['output', {
            type_: 'insert+p1',
            option: '1st-level escape'
          }],
          nextState: '0'
        }
      },
      '[(...)]': {
        'r|rt': {
          action_: 'rd=',
          nextState: 'rd'
        },
        'rd|rdt': {
          action_: 'rq=',
          nextState: 'rdq'
        }
      },
      '...': {
        'o|d|D|dq|qd|qD': {
          action_: ['output', {
            type_: 'bond',
            option: "..."
          }],
          nextState: '3'
        },
        '*': {
          action_: [{
            type_: 'output',
            option: 1
          }, {
            type_: 'insert',
            option: 'ellipsis'
          }],
          nextState: '1'
        }
      },
      '. |* ': {
        '*': {
          action_: ['output', {
            type_: 'insert',
            option: 'addition compound'
          }],
          nextState: '1'
        }
      },
      'state of aggregation $': {
        '*': {
          action_: ['output', 'state of aggregation'],
          nextState: '1'
        }
      },
      '{[(': {
        'a|as|o': {
          action_: ['o=', 'output', 'parenthesisLevel++'],
          nextState: '2'
        },
        '0|1|2|3': {
          action_: ['o=', 'output', 'parenthesisLevel++'],
          nextState: '2'
        },
        '*': {
          action_: ['output', 'o=', 'output', 'parenthesisLevel++'],
          nextState: '2'
        }
      },
      ')]}': {
        '0|1|2|3|b|p|bp|o': {
          action_: ['o=', 'parenthesisLevel--'],
          nextState: 'o'
        },
        'a|as|d|D|q|qd|qD|dq': {
          action_: ['output', 'o=', 'parenthesisLevel--'],
          nextState: 'o'
        }
      },
      ', ': {
        '*': {
          action_: ['output', 'comma'],
          nextState: '0'
        }
      },
      '^_': {
        // ^ and _ without a sensible argument
        '*': {}
      },
      '^{(...)}|^($...$)': {
        '0|1|2|as': {
          action_: 'b=',
          nextState: 'b'
        },
        'p': {
          action_: 'b=',
          nextState: 'bp'
        },
        '3|o': {
          action_: 'd= kv',
          nextState: 'D'
        },
        'q': {
          action_: 'd=',
          nextState: 'qD'
        },
        'd|D|qd|qD|dq': {
          action_: ['output', 'd='],
          nextState: 'D'
        }
      },
      '^a|^\\x{}{}|^\\x{}|^\\x|\'': {
        '0|1|2|as': {
          action_: 'b=',
          nextState: 'b'
        },
        'p': {
          action_: 'b=',
          nextState: 'bp'
        },
        '3|o': {
          action_: 'd= kv',
          nextState: 'd'
        },
        'q': {
          action_: 'd=',
          nextState: 'qd'
        },
        'd|qd|D|qD': {
          action_: 'd='
        },
        'dq': {
          action_: ['output', 'd='],
          nextState: 'd'
        }
      },
      '_{(state of aggregation)}$': {
        'd|D|q|qd|qD|dq': {
          action_: ['output', 'q='],
          nextState: 'q'
        }
      },
      '_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x': {
        '0|1|2|as': {
          action_: 'p=',
          nextState: 'p'
        },
        'b': {
          action_: 'p=',
          nextState: 'bp'
        },
        '3|o': {
          action_: 'q=',
          nextState: 'q'
        },
        'd|D': {
          action_: 'q=',
          nextState: 'dq'
        },
        'q|qd|qD|dq': {
          action_: ['output', 'q='],
          nextState: 'q'
        }
      },
      '=<>': {
        '0|1|2|3|a|as|o|q|d|D|qd|qD|dq': {
          action_: [{
            type_: 'output',
            option: 2
          }, 'bond'],
          nextState: '3'
        }
      },
      '#': {
        '0|1|2|3|a|as|o': {
          action_: [{
            type_: 'output',
            option: 2
          }, {
            type_: 'bond',
            option: "#"
          }],
          nextState: '3'
        }
      },
      '{}': {
        '*': {
          action_: {
            type_: 'output',
            option: 1
          },
          nextState: '1'
        }
      },
      '{...}': {
        '0|1|2|3|a|as|b|p|bp': {
          action_: 'o=',
          nextState: 'o'
        },
        'o|d|D|q|qd|qD|dq': {
          action_: ['output', 'o='],
          nextState: 'o'
        }
      },
      '$...$': {
        'a': {
          action_: 'a='
        },
        // 2$n$
        '0|1|2|3|as|b|p|bp|o': {
          action_: 'o=',
          nextState: 'o'
        },
        // not 'amount'
        'as|o': {
          action_: 'o='
        },
        'q|d|D|qd|qD|dq': {
          action_: ['output', 'o='],
          nextState: 'o'
        }
      },
      '\\bond{(...)}': {
        '*': {
          action_: [{
            type_: 'output',
            option: 2
          }, 'bond'],
          nextState: "3"
        }
      },
      '\\frac{(...)}': {
        '*': {
          action_: [{
            type_: 'output',
            option: 1
          }, 'frac-output'],
          nextState: '3'
        }
      },
      '\\overset{(...)}': {
        '*': {
          action_: [{
            type_: 'output',
            option: 2
          }, 'overset-output'],
          nextState: '3'
        }
      },
      '\\underset{(...)}': {
        '*': {
          action_: [{
            type_: 'output',
            option: 2
          }, 'underset-output'],
          nextState: '3'
        }
      },
      '\\underbrace{(...)}': {
        '*': {
          action_: [{
            type_: 'output',
            option: 2
          }, 'underbrace-output'],
          nextState: '3'
        }
      },
      '\\color{(...)}{(...)}1|\\color(...){(...)}2': {
        '*': {
          action_: [{
            type_: 'output',
            option: 2
          }, 'color-output'],
          nextState: '3'
        }
      },
      '\\color{(...)}0': {
        '*': {
          action_: [{
            type_: 'output',
            option: 2
          }, 'color0-output']
        }
      },
      '\\ce{(...)}': {
        '*': {
          action_: [{
            type_: 'output',
            option: 2
          }, 'ce'],
          nextState: '3'
        }
      },
      '\\,': {
        '*': {
          action_: [{
            type_: 'output',
            option: 1
          }, 'copy'],
          nextState: '1'
        }
      },
      '\\x{}{}|\\x{}|\\x': {
        '0|1|2|3|a|as|b|p|bp|o|c0': {
          action_: ['o=', 'output'],
          nextState: '3'
        },
        '*': {
          action_: ['output', 'o=', 'output'],
          nextState: '3'
        }
      },
      'others': {
        '*': {
          action_: [{
            type_: 'output',
            option: 1
          }, 'copy'],
          nextState: '3'
        }
      },
      'else2': {
        'a': {
          action_: 'a to o',
          nextState: 'o',
          revisit: true
        },
        'as': {
          action_: ['output', 'sb=true'],
          nextState: '1',
          revisit: true
        },
        'r|rt|rd|rdt|rdq': {
          action_: ['output'],
          nextState: '0',
          revisit: true
        },
        '*': {
          action_: ['output', 'copy'],
          nextState: '3'
        }
      }
    }),
    actions: {
      'o after d': function oAfterD(buffer, m) {
        var ret;

        if ((buffer.d || "").match(/^[0-9]+$/)) {
          var tmp = buffer.d;
          buffer.d = undefined;
          ret = this['output'](buffer);
          buffer.b = tmp;
        } else {
          ret = this['output'](buffer);
        }

        mhchemParser.actions['o='](buffer, m);
        return ret;
      },
      'd= kv': function dKv(buffer, m) {
        buffer.d = m;
        buffer.dType = 'kv';
      },
      'charge or bond': function chargeOrBond(buffer, m) {
        if (buffer['beginsWithBond']) {
          /** @type {ParserOutput[]} */
          var ret = [];
          mhchemParser.concatArray(ret, this['output'](buffer));
          mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-"));
          return ret;
        } else {
          buffer.d = m;
        }
      },
      '- after o/d': function afterOD(buffer, m, isAfterD) {
        var c1 = mhchemParser.patterns.match_('orbital', buffer.o || "");
        var c2 = mhchemParser.patterns.match_('one lowercase greek letter $', buffer.o || "");
        var c3 = mhchemParser.patterns.match_('one lowercase latin letter $', buffer.o || "");
        var c4 = mhchemParser.patterns.match_('$one lowercase latin letter$ $', buffer.o || "");
        var hyphenFollows = m === "-" && (c1 && c1.remainder === "" || c2 || c3 || c4);

        if (hyphenFollows && !buffer.a && !buffer.b && !buffer.p && !buffer.d && !buffer.q && !c1 && c3) {
          buffer.o = '$' + buffer.o + '$';
        }
        /** @type {ParserOutput[]} */


        var ret = [];

        if (hyphenFollows) {
          mhchemParser.concatArray(ret, this['output'](buffer));
          ret.push({
            type_: 'hyphen'
          });
        } else {
          c1 = mhchemParser.patterns.match_('digits', buffer.d || "");

          if (isAfterD && c1 && c1.remainder === '') {
            mhchemParser.concatArray(ret, mhchemParser.actions['d='](buffer, m));
            mhchemParser.concatArray(ret, this['output'](buffer));
          } else {
            mhchemParser.concatArray(ret, this['output'](buffer));
            mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-"));
          }
        }

        return ret;
      },
      'a to o': function aToO(buffer) {
        buffer.o = buffer.a;
        buffer.a = undefined;
      },
      'sb=true': function sbTrue(buffer) {
        buffer.sb = true;
      },
      'sb=false': function sbFalse(buffer) {
        buffer.sb = false;
      },
      'beginsWithBond=true': function beginsWithBondTrue(buffer) {
        buffer['beginsWithBond'] = true;
      },
      'beginsWithBond=false': function beginsWithBondFalse(buffer) {
        buffer['beginsWithBond'] = false;
      },
      'parenthesisLevel++': function parenthesisLevel(buffer) {
        buffer['parenthesisLevel']++;
      },
      'parenthesisLevel--': function parenthesisLevel(buffer) {
        buffer['parenthesisLevel']--;
      },
      'state of aggregation': function stateOfAggregation(buffer, m) {
        return {
          type_: 'state of aggregation',
          p1: mhchemParser.go(m, 'o')
        };
      },
      'comma': function comma(buffer, m) {
        var a = m.replace(/\s*$/, '');
        var withSpace = a !== m;

        if (withSpace && buffer['parenthesisLevel'] === 0) {
          return {
            type_: 'comma enumeration L',
            p1: a
          };
        } else {
          return {
            type_: 'comma enumeration M',
            p1: a
          };
        }
      },
      'output': function output(buffer, m, entityFollows) {
        // entityFollows:
        //   undefined = if we have nothing else to output, also ignore the just read space (buffer.sb)
        //   1 = an entity follows, never omit the space if there was one just read before (can only apply to state 1)
        //   2 = 1 + the entity can have an amount, so output a\, instead of converting it to o (can only apply to states a|as)

        /** @type {ParserOutput | ParserOutput[]} */
        var ret;

        if (!buffer.r) {
          ret = [];

          if (!buffer.a && !buffer.b && !buffer.p && !buffer.o && !buffer.q && !buffer.d && !entityFollows) ; else {
            if (buffer.sb) {
              ret.push({
                type_: 'entitySkip'
              });
            }

            if (!buffer.o && !buffer.q && !buffer.d && !buffer.b && !buffer.p && entityFollows !== 2) {
              buffer.o = buffer.a;
              buffer.a = undefined;
            } else if (!buffer.o && !buffer.q && !buffer.d && (buffer.b || buffer.p)) {
              buffer.o = buffer.a;
              buffer.d = buffer.b;
              buffer.q = buffer.p;
              buffer.a = buffer.b = buffer.p = undefined;
            } else {
              if (buffer.o && buffer.dType === 'kv' && mhchemParser.patterns.match_('d-oxidation$', buffer.d || "")) {
                buffer.dType = 'oxidation';
              } else if (buffer.o && buffer.dType === 'kv' && !buffer.q) {
                buffer.dType = undefined;
              }
            }

            ret.push({
              type_: 'chemfive',
              a: mhchemParser.go(buffer.a, 'a'),
              b: mhchemParser.go(buffer.b, 'bd'),
              p: mhchemParser.go(buffer.p, 'pq'),
              o: mhchemParser.go(buffer.o, 'o'),
              q: mhchemParser.go(buffer.q, 'pq'),
              d: mhchemParser.go(buffer.d, buffer.dType === 'oxidation' ? 'oxidation' : 'bd'),
              dType: buffer.dType
            });
          }
        } else {
          // r

          /** @type {ParserOutput[]} */
          var rd;

          if (buffer.rdt === 'M') {
            rd = mhchemParser.go(buffer.rd, 'tex-math');
          } else if (buffer.rdt === 'T') {
            rd = [{
              type_: 'text',
              p1: buffer.rd || ""
            }];
          } else {
            rd = mhchemParser.go(buffer.rd);
          }
          /** @type {ParserOutput[]} */


          var rq;

          if (buffer.rqt === 'M') {
            rq = mhchemParser.go(buffer.rq, 'tex-math');
          } else if (buffer.rqt === 'T') {
            rq = [{
              type_: 'text',
              p1: buffer.rq || ""
            }];
          } else {
            rq = mhchemParser.go(buffer.rq);
          }

          ret = {
            type_: 'arrow',
            r: buffer.r,
            rd: rd,
            rq: rq
          };
        }

        for (var p in buffer) {
          if (p !== 'parenthesisLevel' && p !== 'beginsWithBond') {
            delete buffer[p];
          }
        }

        return ret;
      },
      'oxidation-output': function oxidationOutput(buffer, m) {
        var ret = ["{"];
        mhchemParser.concatArray(ret, mhchemParser.go(m, 'oxidation'));
        ret.push("}");
        return ret;
      },
      'frac-output': function fracOutput(buffer, m) {
        return {
          type_: 'frac-ce',
          p1: mhchemParser.go(m[0]),
          p2: mhchemParser.go(m[1])
        };
      },
      'overset-output': function oversetOutput(buffer, m) {
        return {
          type_: 'overset',
          p1: mhchemParser.go(m[0]),
          p2: mhchemParser.go(m[1])
        };
      },
      'underset-output': function undersetOutput(buffer, m) {
        return {
          type_: 'underset',
          p1: mhchemParser.go(m[0]),
          p2: mhchemParser.go(m[1])
        };
      },
      'underbrace-output': function underbraceOutput(buffer, m) {
        return {
          type_: 'underbrace',
          p1: mhchemParser.go(m[0]),
          p2: mhchemParser.go(m[1])
        };
      },
      'color-output': function colorOutput(buffer, m) {
        return {
          type_: 'color',
          color1: m[0],
          color2: mhchemParser.go(m[1])
        };
      },
      'r=': function r(buffer, m) {
        buffer.r = m;
      },
      'rdt=': function rdt(buffer, m) {
        buffer.rdt = m;
      },
      'rd=': function rd(buffer, m) {
        buffer.rd = m;
      },
      'rqt=': function rqt(buffer, m) {
        buffer.rqt = m;
      },
      'rq=': function rq(buffer, m) {
        buffer.rq = m;
      },
      'operator': function operator(buffer, m, p1) {
        return {
          type_: 'operator',
          kind_: p1 || m
        };
      }
    }
  },
  'a': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {}
      },
      '1/2$': {
        '0': {
          action_: '1/2'
        }
      },
      'else': {
        '0': {
          nextState: '1',
          revisit: true
        }
      },
      '$(...)$': {
        '*': {
          action_: 'tex-math tight',
          nextState: '1'
        }
      },
      ',': {
        '*': {
          action_: {
            type_: 'insert',
            option: 'commaDecimal'
          }
        }
      },
      'else2': {
        '*': {
          action_: 'copy'
        }
      }
    }),
    actions: {}
  },
  'o': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {}
      },
      '1/2$': {
        '0': {
          action_: '1/2'
        }
      },
      'else': {
        '0': {
          nextState: '1',
          revisit: true
        }
      },
      'letters': {
        '*': {
          action_: 'rm'
        }
      },
      '\\ca': {
        '*': {
          action_: {
            type_: 'insert',
            option: 'circa'
          }
        }
      },
      '\\x{}{}|\\x{}|\\x': {
        '*': {
          action_: 'copy'
        }
      },
      '${(...)}$|$(...)$': {
        '*': {
          action_: 'tex-math'
        }
      },
      '{(...)}': {
        '*': {
          action_: '{text}'
        }
      },
      'else2': {
        '*': {
          action_: 'copy'
        }
      }
    }),
    actions: {}
  },
  'text': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {
          action_: 'output'
        }
      },
      '{...}': {
        '*': {
          action_: 'text='
        }
      },
      '${(...)}$|$(...)$': {
        '*': {
          action_: 'tex-math'
        }
      },
      '\\greek': {
        '*': {
          action_: ['output', 'rm']
        }
      },
      '\\,|\\x{}{}|\\x{}|\\x': {
        '*': {
          action_: ['output', 'copy']
        }
      },
      'else': {
        '*': {
          action_: 'text='
        }
      }
    }),
    actions: {
      'output': function output(buffer) {
        if (buffer.text_) {
          /** @type {ParserOutput} */
          var ret = {
            type_: 'text',
            p1: buffer.text_
          };

          for (var p in buffer) {
            delete buffer[p];
          }

          return ret;
        }
      }
    }
  },
  'pq': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {}
      },
      'state of aggregation $': {
        '*': {
          action_: 'state of aggregation'
        }
      },
      'i$': {
        '0': {
          nextState: '!f',
          revisit: true
        }
      },
      '(KV letters),': {
        '0': {
          action_: 'rm',
          nextState: '0'
        }
      },
      'formula$': {
        '0': {
          nextState: 'f',
          revisit: true
        }
      },
      '1/2$': {
        '0': {
          action_: '1/2'
        }
      },
      'else': {
        '0': {
          nextState: '!f',
          revisit: true
        }
      },
      '${(...)}$|$(...)$': {
        '*': {
          action_: 'tex-math'
        }
      },
      '{(...)}': {
        '*': {
          action_: 'text'
        }
      },
      'a-z': {
        'f': {
          action_: 'tex-math'
        }
      },
      'letters': {
        '*': {
          action_: 'rm'
        }
      },
      '-9.,9': {
        '*': {
          action_: '9,9'
        }
      },
      ',': {
        '*': {
          action_: {
            type_: 'insert+p1',
            option: 'comma enumeration S'
          }
        }
      },
      '\\color{(...)}{(...)}1|\\color(...){(...)}2': {
        '*': {
          action_: 'color-output'
        }
      },
      '\\color{(...)}0': {
        '*': {
          action_: 'color0-output'
        }
      },
      '\\ce{(...)}': {
        '*': {
          action_: 'ce'
        }
      },
      '\\,|\\x{}{}|\\x{}|\\x': {
        '*': {
          action_: 'copy'
        }
      },
      'else2': {
        '*': {
          action_: 'copy'
        }
      }
    }),
    actions: {
      'state of aggregation': function stateOfAggregation(buffer, m) {
        return {
          type_: 'state of aggregation subscript',
          p1: mhchemParser.go(m, 'o')
        };
      },
      'color-output': function colorOutput(buffer, m) {
        return {
          type_: 'color',
          color1: m[0],
          color2: mhchemParser.go(m[1], 'pq')
        };
      }
    }
  },
  'bd': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {}
      },
      'x$': {
        '0': {
          nextState: '!f',
          revisit: true
        }
      },
      'formula$': {
        '0': {
          nextState: 'f',
          revisit: true
        }
      },
      'else': {
        '0': {
          nextState: '!f',
          revisit: true
        }
      },
      '-9.,9 no missing 0': {
        '*': {
          action_: '9,9'
        }
      },
      '.': {
        '*': {
          action_: {
            type_: 'insert',
            option: 'electron dot'
          }
        }
      },
      'a-z': {
        'f': {
          action_: 'tex-math'
        }
      },
      'x': {
        '*': {
          action_: {
            type_: 'insert',
            option: 'KV x'
          }
        }
      },
      'letters': {
        '*': {
          action_: 'rm'
        }
      },
      '\'': {
        '*': {
          action_: {
            type_: 'insert',
            option: 'prime'
          }
        }
      },
      '${(...)}$|$(...)$': {
        '*': {
          action_: 'tex-math'
        }
      },
      '{(...)}': {
        '*': {
          action_: 'text'
        }
      },
      '\\color{(...)}{(...)}1|\\color(...){(...)}2': {
        '*': {
          action_: 'color-output'
        }
      },
      '\\color{(...)}0': {
        '*': {
          action_: 'color0-output'
        }
      },
      '\\ce{(...)}': {
        '*': {
          action_: 'ce'
        }
      },
      '\\,|\\x{}{}|\\x{}|\\x': {
        '*': {
          action_: 'copy'
        }
      },
      'else2': {
        '*': {
          action_: 'copy'
        }
      }
    }),
    actions: {
      'color-output': function colorOutput(buffer, m) {
        return {
          type_: 'color',
          color1: m[0],
          color2: mhchemParser.go(m[1], 'bd')
        };
      }
    }
  },
  'oxidation': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {}
      },
      'roman numeral': {
        '*': {
          action_: 'roman-numeral'
        }
      },
      '${(...)}$|$(...)$': {
        '*': {
          action_: 'tex-math'
        }
      },
      'else': {
        '*': {
          action_: 'copy'
        }
      }
    }),
    actions: {
      'roman-numeral': function romanNumeral(buffer, m) {
        return {
          type_: 'roman numeral',
          p1: m || ""
        };
      }
    }
  },
  'tex-math': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {
          action_: 'output'
        }
      },
      '\\ce{(...)}': {
        '*': {
          action_: ['output', 'ce']
        }
      },
      '{...}|\\,|\\x{}{}|\\x{}|\\x': {
        '*': {
          action_: 'o='
        }
      },
      'else': {
        '*': {
          action_: 'o='
        }
      }
    }),
    actions: {
      'output': function output(buffer) {
        if (buffer.o) {
          /** @type {ParserOutput} */
          var ret = {
            type_: 'tex-math',
            p1: buffer.o
          };

          for (var p in buffer) {
            delete buffer[p];
          }

          return ret;
        }
      }
    }
  },
  'tex-math tight': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {
          action_: 'output'
        }
      },
      '\\ce{(...)}': {
        '*': {
          action_: ['output', 'ce']
        }
      },
      '{...}|\\,|\\x{}{}|\\x{}|\\x': {
        '*': {
          action_: 'o='
        }
      },
      '-|+': {
        '*': {
          action_: 'tight operator'
        }
      },
      'else': {
        '*': {
          action_: 'o='
        }
      }
    }),
    actions: {
      'tight operator': function tightOperator(buffer, m) {
        buffer.o = (buffer.o || "") + "{" + m + "}";
      },
      'output': function output(buffer) {
        if (buffer.o) {
          /** @type {ParserOutput} */
          var ret = {
            type_: 'tex-math',
            p1: buffer.o
          };

          for (var p in buffer) {
            delete buffer[p];
          }

          return ret;
        }
      }
    }
  },
  '9,9': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {}
      },
      ',': {
        '*': {
          action_: 'comma'
        }
      },
      'else': {
        '*': {
          action_: 'copy'
        }
      }
    }),
    actions: {
      'comma': function comma() {
        return {
          type_: 'commaDecimal'
        };
      }
    }
  },
  //#endregion
  //
  // \pu state machines
  //
  //#region pu
  'pu': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {
          action_: 'output'
        }
      },
      'space$': {
        '*': {
          action_: ['output', 'space']
        }
      },
      '{[(|)]}': {
        '0|a': {
          action_: 'copy'
        }
      },
      '(-)(9)^(-9)': {
        '0': {
          action_: 'number^',
          nextState: 'a'
        }
      },
      '(-)(9.,9)(e)(99)': {
        '0': {
          action_: 'enumber',
          nextState: 'a'
        }
      },
      'space': {
        '0|a': {}
      },
      'pm-operator': {
        '0|a': {
          action_: {
            type_: 'operator',
            option: '\\pm'
          },
          nextState: '0'
        }
      },
      'operator': {
        '0|a': {
          action_: 'copy',
          nextState: '0'
        }
      },
      '//': {
        'd': {
          action_: 'o=',
          nextState: '/'
        }
      },
      '/': {
        'd': {
          action_: 'o=',
          nextState: '/'
        }
      },
      '{...}|else': {
        '0|d': {
          action_: 'd=',
          nextState: 'd'
        },
        'a': {
          action_: ['space', 'd='],
          nextState: 'd'
        },
        '/|q': {
          action_: 'q=',
          nextState: 'q'
        }
      }
    }),
    actions: {
      'enumber': function enumber(buffer, m) {
        /** @type {ParserOutput[]} */
        var ret = [];

        if (m[0] === "+-" || m[0] === "+/-") {
          ret.push("\\pm ");
        } else if (m[0]) {
          ret.push(m[0]);
        }

        if (m[1]) {
          mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9'));

          if (m[2]) {
            if (m[2].match(/[,.]/)) {
              mhchemParser.concatArray(ret, mhchemParser.go(m[2], 'pu-9,9'));
            } else {
              ret.push(m[2]);
            }
          }

          m[3] = m[4] || m[3];

          if (m[3]) {
            m[3] = m[3].trim();

            if (m[3] === "e" || m[3].substr(0, 1) === "*") {
              ret.push({
                type_: 'cdot'
              });
            } else {
              ret.push({
                type_: 'times'
              });
            }
          }
        }

        if (m[3]) {
          ret.push("10^{" + m[5] + "}");
        }

        return ret;
      },
      'number^': function number(buffer, m) {
        /** @type {ParserOutput[]} */
        var ret = [];

        if (m[0] === "+-" || m[0] === "+/-") {
          ret.push("\\pm ");
        } else if (m[0]) {
          ret.push(m[0]);
        }

        mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9'));
        ret.push("^{" + m[2] + "}");
        return ret;
      },
      'operator': function operator(buffer, m, p1) {
        return {
          type_: 'operator',
          kind_: p1 || m
        };
      },
      'space': function space() {
        return {
          type_: 'pu-space-1'
        };
      },
      'output': function output(buffer) {
        /** @type {ParserOutput | ParserOutput[]} */
        var ret;
        var md = mhchemParser.patterns.match_('{(...)}', buffer.d || "");

        if (md && md.remainder === '') {
          buffer.d = md.match_;
        }

        var mq = mhchemParser.patterns.match_('{(...)}', buffer.q || "");

        if (mq && mq.remainder === '') {
          buffer.q = mq.match_;
        }

        if (buffer.d) {
          buffer.d = buffer.d.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C");
          buffer.d = buffer.d.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F");
        }

        if (buffer.q) {
          // fraction
          buffer.q = buffer.q.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C");
          buffer.q = buffer.q.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F");
          var b5 = {
            d: mhchemParser.go(buffer.d, 'pu'),
            q: mhchemParser.go(buffer.q, 'pu')
          };

          if (buffer.o === '//') {
            ret = {
              type_: 'pu-frac',
              p1: b5.d,
              p2: b5.q
            };
          } else {
            ret = b5.d;

            if (b5.d.length > 1 || b5.q.length > 1) {
              ret.push({
                type_: ' / '
              });
            } else {
              ret.push({
                type_: '/'
              });
            }

            mhchemParser.concatArray(ret, b5.q);
          }
        } else {
          // no fraction
          ret = mhchemParser.go(buffer.d, 'pu-2');
        }

        for (var p in buffer) {
          delete buffer[p];
        }

        return ret;
      }
    }
  },
  'pu-2': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '*': {
          action_: 'output'
        }
      },
      '*': {
        '*': {
          action_: ['output', 'cdot'],
          nextState: '0'
        }
      },
      '\\x': {
        '*': {
          action_: 'rm='
        }
      },
      'space': {
        '*': {
          action_: ['output', 'space'],
          nextState: '0'
        }
      },
      '^{(...)}|^(-1)': {
        '1': {
          action_: '^(-1)'
        }
      },
      '-9.,9': {
        '0': {
          action_: 'rm=',
          nextState: '0'
        },
        '1': {
          action_: '^(-1)',
          nextState: '0'
        }
      },
      '{...}|else': {
        '*': {
          action_: 'rm=',
          nextState: '1'
        }
      }
    }),
    actions: {
      'cdot': function cdot() {
        return {
          type_: 'tight cdot'
        };
      },
      '^(-1)': function _(buffer, m) {
        buffer.rm += "^{" + m + "}";
      },
      'space': function space() {
        return {
          type_: 'pu-space-2'
        };
      },
      'output': function output(buffer) {
        /** @type {ParserOutput | ParserOutput[]} */
        var ret = [];

        if (buffer.rm) {
          var mrm = mhchemParser.patterns.match_('{(...)}', buffer.rm || "");

          if (mrm && mrm.remainder === '') {
            ret = mhchemParser.go(mrm.match_, 'pu');
          } else {
            ret = {
              type_: 'rm',
              p1: buffer.rm
            };
          }
        }

        for (var p in buffer) {
          delete buffer[p];
        }

        return ret;
      }
    }
  },
  'pu-9,9': {
    transitions: mhchemParser.createTransitions({
      'empty': {
        '0': {
          action_: 'output-0'
        },
        'o': {
          action_: 'output-o'
        }
      },
      ',': {
        '0': {
          action_: ['output-0', 'comma'],
          nextState: 'o'
        }
      },
      '.': {
        '0': {
          action_: ['output-0', 'copy'],
          nextState: 'o'
        }
      },
      'else': {
        '*': {
          action_: 'text='
        }
      }
    }),
    actions: {
      'comma': function comma() {
        return {
          type_: 'commaDecimal'
        };
      },
      'output-0': function output0(buffer) {
        /** @type {ParserOutput[]} */
        var ret = [];
        buffer.text_ = buffer.text_ || "";

        if (buffer.text_.length > 4) {
          var a = buffer.text_.length % 3;

          if (a === 0) {
            a = 3;
          }

          for (var i = buffer.text_.length - 3; i > 0; i -= 3) {
            ret.push(buffer.text_.substr(i, 3));
            ret.push({
              type_: '1000 separator'
            });
          }

          ret.push(buffer.text_.substr(0, a));
          ret.reverse();
        } else {
          ret.push(buffer.text_);
        }

        for (var p in buffer) {
          delete buffer[p];
        }

        return ret;
      },
      'output-o': function outputO(buffer) {
        /** @type {ParserOutput[]} */
        var ret = [];
        buffer.text_ = buffer.text_ || "";

        if (buffer.text_.length > 4) {
          var a = buffer.text_.length - 3;

          for (var i = 0; i < a; i += 3) {
            ret.push(buffer.text_.substr(i, 3));
            ret.push({
              type_: '1000 separator'
            });
          }

          ret.push(buffer.text_.substr(i));
        } else {
          ret.push(buffer.text_);
        }

        for (var p in buffer) {
          delete buffer[p];
        }

        return ret;
      }
    }
  } //#endregion

}; //
// texify: Take MhchemParser output and convert it to TeX
//

/** @type {Texify} */

var texify = {
  go: function go(input, isInner) {
    // (recursive, max 4 levels)
    if (!input) {
      return "";
    }

    var res = "";
    var cee = false;

    for (var i = 0; i < input.length; i++) {
      var inputi = input[i];

      if (typeof inputi === "string") {
        res += inputi;
      } else {
        res += texify._go2(inputi);

        if (inputi.type_ === '1st-level escape') {
          cee = true;
        }
      }
    }

    if (!isInner && !cee && res) {
      res = "{" + res + "}";
    }

    return res;
  },
  _goInner: function _goInner(input) {
    if (!input) {
      return input;
    }

    return texify.go(input, true);
  },
  _go2: function _go2(buf) {
    /** @type {undefined | string} */
    var res;

    switch (buf.type_) {
      case 'chemfive':
        res = "";
        var b5 = {
          a: texify._goInner(buf.a),
          b: texify._goInner(buf.b),
          p: texify._goInner(buf.p),
          o: texify._goInner(buf.o),
          q: texify._goInner(buf.q),
          d: texify._goInner(buf.d)
        }; //
        // a
        //

        if (b5.a) {
          if (b5.a.match(/^[+\-]/)) {
            b5.a = "{" + b5.a + "}";
          }

          res += b5.a + "\\,";
        } //
        // b and p
        //


        if (b5.b || b5.p) {
          res += "{\\vphantom{X}}";
          res += "^{\\hphantom{" + (b5.b || "") + "}}_{\\hphantom{" + (b5.p || "") + "}}";
          res += "{\\vphantom{X}}";
          res += "^{\\smash[t]{\\vphantom{2}}\\mathllap{" + (b5.b || "") + "}}";
          res += "_{\\vphantom{2}\\mathllap{\\smash[t]{" + (b5.p || "") + "}}}";
        } //
        // o
        //


        if (b5.o) {
          if (b5.o.match(/^[+\-]/)) {
            b5.o = "{" + b5.o + "}";
          }

          res += b5.o;
        } //
        // q and d
        //


        if (buf.dType === 'kv') {
          if (b5.d || b5.q) {
            res += "{\\vphantom{X}}";
          }

          if (b5.d) {
            res += "^{" + b5.d + "}";
          }

          if (b5.q) {
            res += "_{\\smash[t]{" + b5.q + "}}";
          }
        } else if (buf.dType === 'oxidation') {
          if (b5.d) {
            res += "{\\vphantom{X}}";
            res += "^{" + b5.d + "}";
          }

          if (b5.q) {
            res += "{\\vphantom{X}}";
            res += "_{\\smash[t]{" + b5.q + "}}";
          }
        } else {
          if (b5.q) {
            res += "{\\vphantom{X}}";
            res += "_{\\smash[t]{" + b5.q + "}}";
          }

          if (b5.d) {
            res += "{\\vphantom{X}}";
            res += "^{" + b5.d + "}";
          }
        }

        break;

      case 'rm':
        res = "\\mathrm{" + buf.p1 + "}";
        break;

      case 'text':
        if (buf.p1.match(/[\^_]/)) {
          buf.p1 = buf.p1.replace(" ", "~").replace("-", "\\text{-}");
          res = "\\mathrm{" + buf.p1 + "}";
        } else {
          res = "\\text{" + buf.p1 + "}";
        }

        break;

      case 'roman numeral':
        res = "\\mathrm{" + buf.p1 + "}";
        break;

      case 'state of aggregation':
        res = "\\mskip2mu " + texify._goInner(buf.p1);
        break;

      case 'state of aggregation subscript':
        res = "\\mskip1mu " + texify._goInner(buf.p1);
        break;

      case 'bond':
        res = texify._getBond(buf.kind_);

        if (!res) {
          throw ["MhchemErrorBond", "mhchem Error. Unknown bond type (" + buf.kind_ + ")"];
        }

        break;

      case 'frac':
        var c = "\\frac{" + buf.p1 + "}{" + buf.p2 + "}";
        res = "\\mathchoice{\\textstyle" + c + "}{" + c + "}{" + c + "}{" + c + "}";
        break;

      case 'pu-frac':
        var d = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}";
        res = "\\mathchoice{\\textstyle" + d + "}{" + d + "}{" + d + "}{" + d + "}";
        break;

      case 'tex-math':
        res = buf.p1 + " ";
        break;

      case 'frac-ce':
        res = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}";
        break;

      case 'overset':
        res = "\\overset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}";
        break;

      case 'underset':
        res = "\\underset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}";
        break;

      case 'underbrace':
        res = "\\underbrace{" + texify._goInner(buf.p1) + "}_{" + texify._goInner(buf.p2) + "}";
        break;

      case 'color':
        res = "{\\color{" + buf.color1 + "}{" + texify._goInner(buf.color2) + "}}";
        break;

      case 'color0':
        res = "\\color{" + buf.color + "}";
        break;

      case 'arrow':
        var b6 = {
          rd: texify._goInner(buf.rd),
          rq: texify._goInner(buf.rq)
        };

        var arrow = "\\x" + texify._getArrow(buf.r);

        if (b6.rq) {
          arrow += "[{" + b6.rq + "}]";
        }

        if (b6.rd) {
          arrow += "{" + b6.rd + "}";
        } else {
          arrow += "{}";
        }

        res = arrow;
        break;

      case 'operator':
        res = texify._getOperator(buf.kind_);
        break;

      case '1st-level escape':
        res = buf.p1 + " "; // &, \\\\, \\hlin

        break;

      case 'space':
        res = " ";
        break;

      case 'entitySkip':
        res = "~";
        break;

      case 'pu-space-1':
        res = "~";
        break;

      case 'pu-space-2':
        res = "\\mkern3mu ";
        break;

      case '1000 separator':
        res = "\\mkern2mu ";
        break;

      case 'commaDecimal':
        res = "{,}";
        break;

      case 'comma enumeration L':
        res = "{" + buf.p1 + "}\\mkern6mu ";
        break;

      case 'comma enumeration M':
        res = "{" + buf.p1 + "}\\mkern3mu ";
        break;

      case 'comma enumeration S':
        res = "{" + buf.p1 + "}\\mkern1mu ";
        break;

      case 'hyphen':
        res = "\\text{-}";
        break;

      case 'addition compound':
        res = "\\,{\\cdot}\\,";
        break;

      case 'electron dot':
        res = "\\mkern1mu \\bullet\\mkern1mu ";
        break;

      case 'KV x':
        res = "{\\times}";
        break;

      case 'prime':
        res = "\\prime ";
        break;

      case 'cdot':
        res = "\\cdot ";
        break;

      case 'tight cdot':
        res = "\\mkern1mu{\\cdot}\\mkern1mu ";
        break;

      case 'times':
        res = "\\times ";
        break;

      case 'circa':
        res = "{\\sim}";
        break;

      case '^':
        res = "uparrow";
        break;

      case 'v':
        res = "downarrow";
        break;

      case 'ellipsis':
        res = "\\ldots ";
        break;

      case '/':
        res = "/";
        break;

      case ' / ':
        res = "\\,/\\,";
        break;

      default:
        throw ["MhchemBugT", "mhchem bug T. Please report."];
      // Missing texify rule or unknown MhchemParser output
    }
    return res;
  },
  _getArrow: function _getArrow(a) {
    switch (a) {
      case "->":
        return "rightarrow";

      case "\u2192":
        return "rightarrow";

      case "\u27F6":
        return "rightarrow";

      case "<-":
        return "leftarrow";

      case "<->":
        return "leftrightarrow";

      case "<-->":
        return "rightleftarrows";

      case "<=>":
        return "rightleftharpoons";

      case "\u21CC":
        return "rightleftharpoons";

      case "<=>>":
        return "rightequilibrium";

      case "<<=>":
        return "leftequilibrium";

      default:
        throw ["MhchemBugT", "mhchem bug T. Please report."];
    }
  },
  _getBond: function _getBond(a) {
    switch (a) {
      case "-":
        return "{-}";

      case "1":
        return "{-}";

      case "=":
        return "{=}";

      case "2":
        return "{=}";

      case "#":
        return "{\\equiv}";

      case "3":
        return "{\\equiv}";

      case "~":
        return "{\\tripledash}";

      case "~-":
        return "{\\mathrlap{\\raisebox{-.1em}{$-$}}\\raisebox{.1em}{$\\tripledash$}}";

      case "~=":
        return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}";

      case "~--":
        return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}";

      case "-~-":
        return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$-$}}\\tripledash}";

      case "...":
        return "{{\\cdot}{\\cdot}{\\cdot}}";

      case "....":
        return "{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}";

      case "->":
        return "{\\rightarrow}";

      case "<-":
        return "{\\leftarrow}";

      case "<":
        return "{<}";

      case ">":
        return "{>}";

      default:
        throw ["MhchemBugT", "mhchem bug T. Please report."];
    }
  },
  _getOperator: function _getOperator(a) {
    switch (a) {
      case "+":
        return " {}+{} ";

      case "-":
        return " {}-{} ";

      case "=":
        return " {}={} ";

      case "<":
        return " {}<{} ";

      case ">":
        return " {}>{} ";

      case "<<":
        return " {}\\ll{} ";

      case ">>":
        return " {}\\gg{} ";

      case "\\pm":
        return " {}\\pm{} ";

      case "\\approx":
        return " {}\\approx{} ";

      case "$\\approx$":
        return " {}\\approx{} ";

      case "v":
        return " \\downarrow{} ";

      case "(v)":
        return " \\downarrow{} ";

      case "^":
        return " \\uparrow{} ";

      case "(^)":
        return " \\uparrow{} ";

      default:
        throw ["MhchemBugT", "mhchem bug T. Please report."];
    }
  }
}; //
render-a11y-string.js
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/render-a11y-string.js'
View Content
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory(require("katex"));
	else if(typeof define === 'function' && define.amd)
		define(["katex"], factory);
	else {
		var a = typeof exports === 'object' ? factory(require("katex")) : factory(root["katex"]);
		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
	}
})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__771__) {
return /******/ (function() { // webpackBootstrap
/******/ 	"use strict";
/******/ 	var __webpack_modules__ = ({

/***/ 771:
/***/ (function(module) {

module.exports = __WEBPACK_EXTERNAL_MODULE__771__;

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	!function() {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = function(module) {
/******/ 			var getter = module && module.__esModule ?
/******/ 				function() { return module['default']; } :
/******/ 				function() { return module; };
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
/******/ 		};
/******/ 	}();
/******/ 	
/******/ 	/* webpack/runtime/define property getters */
/******/ 	!function() {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = function(exports, definition) {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	}();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	!function() {
/******/ 		__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ 	}();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
!function() {
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(771);
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(katex__WEBPACK_IMPORTED_MODULE_0__);
/**
 * renderA11yString returns a readable string.
 *
 * In some cases the string will have the proper semantic math
 * meaning,:
 *   renderA11yString("\\frac{1}{2}"")
 *   -> "start fraction, 1, divided by, 2, end fraction"
 *
 * However, other cases do not:
 *   renderA11yString("f(x) = x^2")
 *   -> "f, left parenthesis, x, right parenthesis, equals, x, squared"
 *
 * The commas in the string aim to increase ease of understanding
 * when read by a screenreader.
 */
// NOTE: since we're importing types here these files won't actually be
// included in the build.
// $FlowIgnore: we import the types directly anyways

var stringMap = {
  "(": "left parenthesis",
  ")": "right parenthesis",
  "[": "open bracket",
  "]": "close bracket",
  "\\{": "left brace",
  "\\}": "right brace",
  "\\lvert": "open vertical bar",
  "\\rvert": "close vertical bar",
  "|": "vertical bar",
  "\\uparrow": "up arrow",
  "\\Uparrow": "up arrow",
  "\\downarrow": "down arrow",
  "\\Downarrow": "down arrow",
  "\\updownarrow": "up down arrow",
  "\\leftarrow": "left arrow",
  "\\Leftarrow": "left arrow",
  "\\rightarrow": "right arrow",
  "\\Rightarrow": "right arrow",
  "\\langle": "open angle",
  "\\rangle": "close angle",
  "\\lfloor": "open floor",
  "\\rfloor": "close floor",
  "\\int": "integral",
  "\\intop": "integral",
  "\\lim": "limit",
  "\\ln": "natural log",
  "\\log": "log",
  "\\sin": "sine",
  "\\cos": "cosine",
  "\\tan": "tangent",
  "\\cot": "cotangent",
  "\\sum": "sum",
  "/": "slash",
  ",": "comma",
  ".": "point",
  "-": "negative",
  "+": "plus",
  "~": "tilde",
  ":": "colon",
  "?": "question mark",
  "'": "apostrophe",
  "\\%": "percent",
  " ": "space",
  "\\ ": "space",
  "\\$": "dollar sign",
  "\\angle": "angle",
  "\\degree": "degree",
  "\\circ": "circle",
  "\\vec": "vector",
  "\\triangle": "triangle",
  "\\pi": "pi",
  "\\prime": "prime",
  "\\infty": "infinity",
  "\\alpha": "alpha",
  "\\beta": "beta",
  "\\gamma": "gamma",
  "\\omega": "omega",
  "\\theta": "theta",
  "\\sigma": "sigma",
  "\\lambda": "lambda",
  "\\tau": "tau",
  "\\Delta": "delta",
  "\\delta": "delta",
  "\\mu": "mu",
  "\\rho": "rho",
  "\\nabla": "del",
  "\\ell": "ell",
  "\\ldots": "dots",
  // TODO: add entries for all accents
  "\\hat": "hat",
  "\\acute": "acute"
};
var powerMap = {
  "prime": "prime",
  "degree": "degrees",
  "circle": "degrees",
  "2": "squared",
  "3": "cubed"
};
var openMap = {
  "|": "open vertical bar",
  ".": ""
};
var closeMap = {
  "|": "close vertical bar",
  ".": ""
};
var binMap = {
  "+": "plus",
  "-": "minus",
  "\\pm": "plus minus",
  "\\cdot": "dot",
  "*": "times",
  "/": "divided by",
  "\\times": "times",
  "\\div": "divided by",
  "\\circ": "circle",
  "\\bullet": "bullet"
};
var relMap = {
  "=": "equals",
  "\\approx": "approximately equals",
  "≠": "does not equal",
  "\\geq": "is greater than or equal to",
  "\\ge": "is greater than or equal to",
  "\\leq": "is less than or equal to",
  "\\le": "is less than or equal to",
  ">": "is greater than",
  "<": "is less than",
  "\\leftarrow": "left arrow",
  "\\Leftarrow": "left arrow",
  "\\rightarrow": "right arrow",
  "\\Rightarrow": "right arrow",
  ":": "colon"
};
var accentUnderMap = {
  "\\underleftarrow": "left arrow",
  "\\underrightarrow": "right arrow",
  "\\underleftrightarrow": "left-right arrow",
  "\\undergroup": "group",
  "\\underlinesegment": "line segment",
  "\\utilde": "tilde"
};

var buildString = function buildString(str, type, a11yStrings) {
  if (!str) {
    return;
  }

  var ret;

  if (type === "open") {
    ret = str in openMap ? openMap[str] : stringMap[str] || str;
  } else if (type === "close") {
    ret = str in closeMap ? closeMap[str] : stringMap[str] || str;
  } else if (type === "bin") {
    ret = binMap[str] || str;
  } else if (type === "rel") {
    ret = relMap[str] || str;
  } else {
    ret = stringMap[str] || str;
  } // If the text to add is a number and there is already a string
  // in the list and the last string is a number then we should
  // combine them into a single number


  if (/^\d+$/.test(ret) && a11yStrings.length > 0 && // TODO(kevinb): check that the last item in a11yStrings is a string
  // I think we might be able to drop the nested arrays, which would make
  // this easier to type
  // $FlowFixMe
  /^\d+$/.test(a11yStrings[a11yStrings.length - 1])) {
    a11yStrings[a11yStrings.length - 1] += ret;
  } else if (ret) {
    a11yStrings.push(ret);
  }
};

var buildRegion = function buildRegion(a11yStrings, callback) {
  var regionStrings = [];
  a11yStrings.push(regionStrings);
  callback(regionStrings);
};

var handleObject = function handleObject(tree, a11yStrings, atomType) {
  // Everything else is assumed to be an object...
  switch (tree.type) {
    case "accent":
      {
        buildRegion(a11yStrings, function (a11yStrings) {
          buildA11yStrings(tree.base, a11yStrings, atomType);
          a11yStrings.push("with");
          buildString(tree.label, "normal", a11yStrings);
          a11yStrings.push("on top");
        });
        break;
      }

    case "accentUnder":
      {
        buildRegion(a11yStrings, function (a11yStrings) {
          buildA11yStrings(tree.base, a11yStrings, atomType);
          a11yStrings.push("with");
          buildString(accentUnderMap[tree.label], "normal", a11yStrings);
          a11yStrings.push("underneath");
        });
        break;
      }

    case "accent-token":
      {
        // Used internally by accent symbols.
        break;
      }

    case "atom":
      {
        var text = tree.text;

        switch (tree.family) {
          case "bin":
            {
              buildString(text, "bin", a11yStrings);
              break;
            }

          case "close":
            {
              buildString(text, "close", a11yStrings);
              break;
            }
          // TODO(kevinb): figure out what should be done for inner

          case "inner":
            {
              buildString(tree.text, "inner", a11yStrings);
              break;
            }

          case "open":
            {
              buildString(text, "open", a11yStrings);
              break;
            }

          case "punct":
            {
              buildString(text, "punct", a11yStrings);
              break;
            }

          case "rel":
            {
              buildString(text, "rel", a11yStrings);
              break;
            }

          default:
            {
              tree.family;
              throw new Error("\"" + tree.family + "\" is not a valid atom type");
            }
        }

        break;
      }

    case "color":
      {
        var color = tree.color.replace(/katex-/, "");
        buildRegion(a11yStrings, function (regionStrings) {
          regionStrings.push("start color " + color);
          buildA11yStrings(tree.body, regionStrings, atomType);
          regionStrings.push("end color " + color);
        });
        break;
      }

    case "color-token":
      {
        // Used by \color, \colorbox, and \fcolorbox but not directly rendered.
        // It's a leaf node and has no children so just break.
        break;
      }

    case "delimsizing":
      {
        if (tree.delim && tree.delim !== ".") {
          buildString(tree.delim, "normal", a11yStrings);
        }

        break;
      }

    case "genfrac":
      {
        buildRegion(a11yStrings, function (regionStrings) {
          // genfrac can have unbalanced delimiters
          var leftDelim = tree.leftDelim,
              rightDelim = tree.rightDelim; // NOTE: Not sure if this is a safe assumption
          // hasBarLine true -> fraction, false -> binomial

          if (tree.hasBarLine) {
            regionStrings.push("start fraction");
            leftDelim && buildString(leftDelim, "open", regionStrings);
            buildA11yStrings(tree.numer, regionStrings, atomType);
            regionStrings.push("divided by");
            buildA11yStrings(tree.denom, regionStrings, atomType);
            rightDelim && buildString(rightDelim, "close", regionStrings);
            regionStrings.push("end fraction");
          } else {
            regionStrings.push("start binomial");
            leftDelim && buildString(leftDelim, "open", regionStrings);
            buildA11yStrings(tree.numer, regionStrings, atomType);
            regionStrings.push("over");
            buildA11yStrings(tree.denom, regionStrings, atomType);
            rightDelim && buildString(rightDelim, "close", regionStrings);
            regionStrings.push("end binomial");
          }
        });
        break;
      }

    case "hbox":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "kern":
      {
        // No op: we don't attempt to present kerning information
        // to the screen reader.
        break;
      }

    case "leftright":
      {
        buildRegion(a11yStrings, function (regionStrings) {
          buildString(tree.left, "open", regionStrings);
          buildA11yStrings(tree.body, regionStrings, atomType);
          buildString(tree.right, "close", regionStrings);
        });
        break;
      }

    case "leftright-right":
      {
        // TODO: double check that this is a no-op
        break;
      }

    case "lap":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "mathord":
      {
        buildString(tree.text, "normal", a11yStrings);
        break;
      }

    case "op":
      {
        var body = tree.body,
            name = tree.name;

        if (body) {
          buildA11yStrings(body, a11yStrings, atomType);
        } else if (name) {
          buildString(name, "normal", a11yStrings);
        }

        break;
      }

    case "op-token":
      {
        // Used internally by operator symbols.
        buildString(tree.text, atomType, a11yStrings);
        break;
      }

    case "ordgroup":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "overline":
      {
        buildRegion(a11yStrings, function (a11yStrings) {
          a11yStrings.push("start overline");
          buildA11yStrings(tree.body, a11yStrings, atomType);
          a11yStrings.push("end overline");
        });
        break;
      }

    case "pmb":
      {
        a11yStrings.push("bold");
        break;
      }

    case "phantom":
      {
        a11yStrings.push("empty space");
        break;
      }

    case "raisebox":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "rule":
      {
        a11yStrings.push("rectangle");
        break;
      }

    case "sizing":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "spacing":
      {
        a11yStrings.push("space");
        break;
      }

    case "styling":
      {
        // We ignore the styling and just pass through the contents
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "sqrt":
      {
        buildRegion(a11yStrings, function (regionStrings) {
          var body = tree.body,
              index = tree.index;

          if (index) {
            var indexString = flatten(buildA11yStrings(index, [], atomType)).join(",");

            if (indexString === "3") {
              regionStrings.push("cube root of");
              buildA11yStrings(body, regionStrings, atomType);
              regionStrings.push("end cube root");
              return;
            }

            regionStrings.push("root");
            regionStrings.push("start index");
            buildA11yStrings(index, regionStrings, atomType);
            regionStrings.push("end index");
            return;
          }

          regionStrings.push("square root of");
          buildA11yStrings(body, regionStrings, atomType);
          regionStrings.push("end square root");
        });
        break;
      }

    case "supsub":
      {
        var base = tree.base,
            sub = tree.sub,
            sup = tree.sup;
        var isLog = false;

        if (base) {
          buildA11yStrings(base, a11yStrings, atomType);
          isLog = base.type === "op" && base.name === "\\log";
        }

        if (sub) {
          var regionName = isLog ? "base" : "subscript";
          buildRegion(a11yStrings, function (regionStrings) {
            regionStrings.push("start " + regionName);
            buildA11yStrings(sub, regionStrings, atomType);
            regionStrings.push("end " + regionName);
          });
        }

        if (sup) {
          buildRegion(a11yStrings, function (regionStrings) {
            var supString = flatten(buildA11yStrings(sup, [], atomType)).join(",");

            if (supString in powerMap) {
              regionStrings.push(powerMap[supString]);
              return;
            }

            regionStrings.push("start superscript");
            buildA11yStrings(sup, regionStrings, atomType);
            regionStrings.push("end superscript");
          });
        }

        break;
      }

    case "text":
      {
        // TODO: handle other fonts
        if (tree.font === "\\textbf") {
          buildRegion(a11yStrings, function (regionStrings) {
            regionStrings.push("start bold text");
            buildA11yStrings(tree.body, regionStrings, atomType);
            regionStrings.push("end bold text");
          });
          break;
        }

        buildRegion(a11yStrings, function (regionStrings) {
          regionStrings.push("start text");
          buildA11yStrings(tree.body, regionStrings, atomType);
          regionStrings.push("end text");
        });
        break;
      }

    case "textord":
      {
        buildString(tree.text, atomType, a11yStrings);
        break;
      }

    case "smash":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "enclose":
      {
        // TODO: create a map for these.
        // TODO: differentiate between a body with a single atom, e.g.
        // "cancel a" instead of "start cancel, a, end cancel"
        if (/cancel/.test(tree.label)) {
          buildRegion(a11yStrings, function (regionStrings) {
            regionStrings.push("start cancel");
            buildA11yStrings(tree.body, regionStrings, atomType);
            regionStrings.push("end cancel");
          });
          break;
        } else if (/box/.test(tree.label)) {
          buildRegion(a11yStrings, function (regionStrings) {
            regionStrings.push("start box");
            buildA11yStrings(tree.body, regionStrings, atomType);
            regionStrings.push("end box");
          });
          break;
        } else if (/sout/.test(tree.label)) {
          buildRegion(a11yStrings, function (regionStrings) {
            regionStrings.push("start strikeout");
            buildA11yStrings(tree.body, regionStrings, atomType);
            regionStrings.push("end strikeout");
          });
          break;
        } else if (/phase/.test(tree.label)) {
          buildRegion(a11yStrings, function (regionStrings) {
            regionStrings.push("start phase angle");
            buildA11yStrings(tree.body, regionStrings, atomType);
            regionStrings.push("end phase angle");
          });
          break;
        }

        throw new Error("KaTeX-a11y: enclose node with " + tree.label + " not supported yet");
      }

    case "vcenter":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "vphantom":
      {
        throw new Error("KaTeX-a11y: vphantom not implemented yet");
      }

    case "hphantom":
      {
        throw new Error("KaTeX-a11y: hphantom not implemented yet");
      }

    case "operatorname":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "array":
      {
        throw new Error("KaTeX-a11y: array not implemented yet");
      }

    case "raw":
      {
        throw new Error("KaTeX-a11y: raw not implemented yet");
      }

    case "size":
      {
        // Although there are nodes of type "size" in the parse tree, they have
        // no semantic meaning and should be ignored.
        break;
      }

    case "url":
      {
        throw new Error("KaTeX-a11y: url not implemented yet");
      }

    case "tag":
      {
        throw new Error("KaTeX-a11y: tag not implemented yet");
      }

    case "verb":
      {
        buildString("start verbatim", "normal", a11yStrings);
        buildString(tree.body, "normal", a11yStrings);
        buildString("end verbatim", "normal", a11yStrings);
        break;
      }

    case "environment":
      {
        throw new Error("KaTeX-a11y: environment not implemented yet");
      }

    case "horizBrace":
      {
        buildString("start " + tree.label.slice(1), "normal", a11yStrings);
        buildA11yStrings(tree.base, a11yStrings, atomType);
        buildString("end " + tree.label.slice(1), "normal", a11yStrings);
        break;
      }

    case "infix":
      {
        // All infix nodes are replace with other nodes.
        break;
      }

    case "includegraphics":
      {
        throw new Error("KaTeX-a11y: includegraphics not implemented yet");
      }

    case "font":
      {
        // TODO: callout the start/end of specific fonts
        // TODO: map \BBb{N} to "the naturals" or something like that
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "href":
      {
        throw new Error("KaTeX-a11y: href not implemented yet");
      }

    case "cr":
      {
        // This is used by environments.
        throw new Error("KaTeX-a11y: cr not implemented yet");
      }

    case "underline":
      {
        buildRegion(a11yStrings, function (a11yStrings) {
          a11yStrings.push("start underline");
          buildA11yStrings(tree.body, a11yStrings, atomType);
          a11yStrings.push("end underline");
        });
        break;
      }

    case "xArrow":
      {
        throw new Error("KaTeX-a11y: xArrow not implemented yet");
      }

    case "cdlabel":
      {
        throw new Error("KaTeX-a11y: cdlabel not implemented yet");
      }

    case "cdlabelparent":
      {
        throw new Error("KaTeX-a11y: cdlabelparent not implemented yet");
      }

    case "mclass":
      {
        // \neq and \ne are macros so we let "htmlmathml" render the mathmal
        // side of things and extract the text from that.
        var _atomType = tree.mclass.slice(1); // $FlowFixMe: drop the leading "m" from the values in mclass


        buildA11yStrings(tree.body, a11yStrings, _atomType);
        break;
      }

    case "mathchoice":
      {
        // TODO: track which style we're using, e.g. display, text, etc.
        // default to text style if even that may not be the correct style
        buildA11yStrings(tree.text, a11yStrings, atomType);
        break;
      }

    case "htmlmathml":
      {
        buildA11yStrings(tree.mathml, a11yStrings, atomType);
        break;
      }

    case "middle":
      {
        buildString(tree.delim, atomType, a11yStrings);
        break;
      }

    case "internal":
      {
        // internal nodes are never included in the parse tree
        break;
      }

    case "html":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    default:
      tree.type;
      throw new Error("KaTeX a11y un-recognized type: " + tree.type);
  }
};

var buildA11yStrings = function buildA11yStrings(tree, a11yStrings, atomType) {
  if (a11yStrings === void 0) {
    a11yStrings = [];
  }

  if (tree instanceof Array) {
    for (var i = 0; i < tree.length; i++) {
      buildA11yStrings(tree[i], a11yStrings, atomType);
    }
  } else {
    handleObject(tree, a11yStrings, atomType);
  }

  return a11yStrings;
};

var flatten = function flatten(array) {
  var result = [];
  array.forEach(function (item) {
    if (item instanceof Array) {
      result = result.concat(flatten(item));
    } else {
      result.push(item);
    }
  });
  return result;
};

var renderA11yString = function renderA11yString(text, settings) {
  var tree = katex__WEBPACK_IMPORTED_MODULE_0___default().__parse(text, settings);

  var a11yStrings = buildA11yStrings(tree, [], "normal");
  return flatten(a11yStrings).join(", ");
};

/* harmony default export */ __webpack_exports__["default"] = (renderA11yString);
}();
__webpack_exports__ = __webpack_exports__["default"];
/******/ 	return __webpack_exports__;
/******/ })()
;
});
render-a11y-string.min.js
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/render-a11y-string.min.js'
View Content
!function(e,r){if("object"==typeof exports&&"object"==typeof module)module.exports=r(require("katex"));else if("function"==typeof define&&define.amd)define(["katex"],r);else{var a="object"==typeof exports?r(require("katex")):r(e.katex);for(var t in a)("object"==typeof exports?exports:e)[t]=a[t]}}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var r={771:function(r){r.exports=e}},a={};function t(e){var o=a[e];if(void 0!==o)return o.exports;var n=a[e]={exports:{}};return r[e](n,n.exports,t),n.exports}t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,{a:r}),r},t.d=function(e,r){for(var a in r)t.o(r,a)&&!t.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:r[a]})},t.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)};var o,n,s,i,l,c,u,p,d,h,b,m,f,w,g={};return o=t(771),n=t.n(o),s={"(":"left parenthesis",")":"right parenthesis","[":"open bracket","]":"close bracket","\\{":"left brace","\\}":"right brace","\\lvert":"open vertical bar","\\rvert":"close vertical bar","|":"vertical bar","\\uparrow":"up arrow","\\Uparrow":"up arrow","\\downarrow":"down arrow","\\Downarrow":"down arrow","\\updownarrow":"up down arrow","\\leftarrow":"left arrow","\\Leftarrow":"left arrow","\\rightarrow":"right arrow","\\Rightarrow":"right arrow","\\langle":"open angle","\\rangle":"close angle","\\lfloor":"open floor","\\rfloor":"close floor","\\int":"integral","\\intop":"integral","\\lim":"limit","\\ln":"natural log","\\log":"log","\\sin":"sine","\\cos":"cosine","\\tan":"tangent","\\cot":"cotangent","\\sum":"sum","/":"slash",",":"comma",".":"point","-":"negative","+":"plus","~":"tilde",":":"colon","?":"question mark","'":"apostrophe","\\%":"percent"," ":"space","\\ ":"space","\\$":"dollar sign","\\angle":"angle","\\degree":"degree","\\circ":"circle","\\vec":"vector","\\triangle":"triangle","\\pi":"pi","\\prime":"prime","\\infty":"infinity","\\alpha":"alpha","\\beta":"beta","\\gamma":"gamma","\\omega":"omega","\\theta":"theta","\\sigma":"sigma","\\lambda":"lambda","\\tau":"tau","\\Delta":"delta","\\delta":"delta","\\mu":"mu","\\rho":"rho","\\nabla":"del","\\ell":"ell","\\ldots":"dots","\\hat":"hat","\\acute":"acute"},i={prime:"prime",degree:"degrees",circle:"degrees",2:"squared",3:"cubed"},l={"|":"open vertical bar",".":""},c={"|":"close vertical bar",".":""},u={"+":"plus","-":"minus","\\pm":"plus minus","\\cdot":"dot","*":"times","/":"divided by","\\times":"times","\\div":"divided by","\\circ":"circle","\\bullet":"bullet"},p={"=":"equals","\\approx":"approximately equals","\u2260":"does not equal","\\geq":"is greater than or equal to","\\ge":"is greater than or equal to","\\leq":"is less than or equal to","\\le":"is less than or equal to",">":"is greater than","<":"is less than","\\leftarrow":"left arrow","\\Leftarrow":"left arrow","\\rightarrow":"right arrow","\\Rightarrow":"right arrow",":":"colon"},d={"\\underleftarrow":"left arrow","\\underrightarrow":"right arrow","\\underleftrightarrow":"left-right arrow","\\undergroup":"group","\\underlinesegment":"line segment","\\utilde":"tilde"},h=function(e,r,a){var t;e&&(/^\d+$/.test(t="open"===r?e in l?l[e]:s[e]||e:"close"===r?e in c?c[e]:s[e]||e:"bin"===r?u[e]||e:"rel"===r?p[e]||e:s[e]||e)&&a.length>0&&/^\d+$/.test(a[a.length-1])?a[a.length-1]+=t:t&&a.push(t))},b=function(e,r){var a=[];e.push(a),r(a)},m=function(e,r,a){switch(e.type){case"accent":b(r,(function(r){f(e.base,r,a),r.push("with"),h(e.label,"normal",r),r.push("on top")}));break;case"accentUnder":b(r,(function(r){f(e.base,r,a),r.push("with"),h(d[e.label],"normal",r),r.push("underneath")}));break;case"accent-token":case"color-token":case"kern":case"leftright-right":case"size":case"infix":case"internal":break;case"atom":var t=e.text;switch(e.family){case"bin":h(t,"bin",r);break;case"close":h(t,"close",r);break;case"inner":h(e.text,"inner",r);break;case"open":h(t,"open",r);break;case"punct":h(t,"punct",r);break;case"rel":h(t,"rel",r);break;default:throw e.family,new Error('"'+e.family+'" is not a valid atom type')}break;case"color":var o=e.color.replace(/katex-/,"");b(r,(function(r){r.push("start color "+o),f(e.body,r,a),r.push("end color "+o)}));break;case"delimsizing":e.delim&&"."!==e.delim&&h(e.delim,"normal",r);break;case"genfrac":b(r,(function(r){var t=e.leftDelim,o=e.rightDelim;e.hasBarLine?(r.push("start fraction"),t&&h(t,"open",r),f(e.numer,r,a),r.push("divided by"),f(e.denom,r,a),o&&h(o,"close",r),r.push("end fraction")):(r.push("start binomial"),t&&h(t,"open",r),f(e.numer,r,a),r.push("over"),f(e.denom,r,a),o&&h(o,"close",r),r.push("end binomial"))}));break;case"hbox":case"lap":case"ordgroup":case"raisebox":case"sizing":case"styling":case"smash":case"vcenter":case"operatorname":case"font":case"html":f(e.body,r,a);break;case"leftright":b(r,(function(r){h(e.left,"open",r),f(e.body,r,a),h(e.right,"close",r)}));break;case"mathord":h(e.text,"normal",r);break;case"op":var n=e.body,s=e.name;n?f(n,r,a):s&&h(s,"normal",r);break;case"op-token":case"textord":h(e.text,a,r);break;case"overline":b(r,(function(r){r.push("start overline"),f(e.body,r,a),r.push("end overline")}));break;case"pmb":r.push("bold");break;case"phantom":r.push("empty space");break;case"rule":r.push("rectangle");break;case"spacing":r.push("space");break;case"sqrt":b(r,(function(r){var t=e.body,o=e.index;if(o)return"3"===w(f(o,[],a)).join(",")?(r.push("cube root of"),f(t,r,a),void r.push("end cube root")):(r.push("root"),r.push("start index"),f(o,r,a),void r.push("end index"));r.push("square root of"),f(t,r,a),r.push("end square root")}));break;case"supsub":var l=e.base,c=e.sub,u=e.sup,p=!1;if(l&&(f(l,r,a),p="op"===l.type&&"\\log"===l.name),c){var m=p?"base":"subscript";b(r,(function(e){e.push("start "+m),f(c,e,a),e.push("end "+m)}))}u&&b(r,(function(e){var r=w(f(u,[],a)).join(",");r in i?e.push(i[r]):(e.push("start superscript"),f(u,e,a),e.push("end superscript"))}));break;case"text":if("\\textbf"===e.font){b(r,(function(r){r.push("start bold text"),f(e.body,r,a),r.push("end bold text")}));break}b(r,(function(r){r.push("start text"),f(e.body,r,a),r.push("end text")}));break;case"enclose":if(/cancel/.test(e.label)){b(r,(function(r){r.push("start cancel"),f(e.body,r,a),r.push("end cancel")}));break}if(/box/.test(e.label)){b(r,(function(r){r.push("start box"),f(e.body,r,a),r.push("end box")}));break}if(/sout/.test(e.label)){b(r,(function(r){r.push("start strikeout"),f(e.body,r,a),r.push("end strikeout")}));break}if(/phase/.test(e.label)){b(r,(function(r){r.push("start phase angle"),f(e.body,r,a),r.push("end phase angle")}));break}throw new Error("KaTeX-a11y: enclose node with "+e.label+" not supported yet");case"vphantom":throw new Error("KaTeX-a11y: vphantom not implemented yet");case"hphantom":throw new Error("KaTeX-a11y: hphantom not implemented yet");case"array":throw new Error("KaTeX-a11y: array not implemented yet");case"raw":throw new Error("KaTeX-a11y: raw not implemented yet");case"url":throw new Error("KaTeX-a11y: url not implemented yet");case"tag":throw new Error("KaTeX-a11y: tag not implemented yet");case"verb":h("start verbatim","normal",r),h(e.body,"normal",r),h("end verbatim","normal",r);break;case"environment":throw new Error("KaTeX-a11y: environment not implemented yet");case"horizBrace":h("start "+e.label.slice(1),"normal",r),f(e.base,r,a),h("end "+e.label.slice(1),"normal",r);break;case"includegraphics":throw new Error("KaTeX-a11y: includegraphics not implemented yet");case"href":throw new Error("KaTeX-a11y: href not implemented yet");case"cr":throw new Error("KaTeX-a11y: cr not implemented yet");case"underline":b(r,(function(r){r.push("start underline"),f(e.body,r,a),r.push("end underline")}));break;case"xArrow":throw new Error("KaTeX-a11y: xArrow not implemented yet");case"cdlabel":throw new Error("KaTeX-a11y: cdlabel not implemented yet");case"cdlabelparent":throw new Error("KaTeX-a11y: cdlabelparent not implemented yet");case"mclass":var g=e.mclass.slice(1);f(e.body,r,g);break;case"mathchoice":f(e.text,r,a);break;case"htmlmathml":f(e.mathml,r,a);break;case"middle":h(e.delim,a,r);break;default:throw e.type,new Error("KaTeX a11y un-recognized type: "+e.type)}},f=function e(r,a,t){if(void 0===a&&(a=[]),r instanceof Array)for(var o=0;o<r.length;o++)e(r[o],a,t);else m(r,a,t);return a},w=function e(r){var a=[];return r.forEach((function(r){r instanceof Array?a=a.concat(e(r)):a.push(r)})),a},g.default=function(e,r){var a=n().__parse(e,r),t=f(a,[],"normal");return w(t).join(", ")},g=g.default}()}));
render-a11y-string.mjs
wget 'https://sme10.lists2.roe3.org/kodbox/static/app/vender/markdown/katex/contrib/render-a11y-string.mjs'
View Content
import katex from '../katex.mjs';

/**
 * renderA11yString returns a readable string.
 *
 * In some cases the string will have the proper semantic math
 * meaning,:
 *   renderA11yString("\\frac{1}{2}"")
 *   -> "start fraction, 1, divided by, 2, end fraction"
 *
 * However, other cases do not:
 *   renderA11yString("f(x) = x^2")
 *   -> "f, left parenthesis, x, right parenthesis, equals, x, squared"
 *
 * The commas in the string aim to increase ease of understanding
 * when read by a screenreader.
 */
var stringMap = {
  "(": "left parenthesis",
  ")": "right parenthesis",
  "[": "open bracket",
  "]": "close bracket",
  "\\{": "left brace",
  "\\}": "right brace",
  "\\lvert": "open vertical bar",
  "\\rvert": "close vertical bar",
  "|": "vertical bar",
  "\\uparrow": "up arrow",
  "\\Uparrow": "up arrow",
  "\\downarrow": "down arrow",
  "\\Downarrow": "down arrow",
  "\\updownarrow": "up down arrow",
  "\\leftarrow": "left arrow",
  "\\Leftarrow": "left arrow",
  "\\rightarrow": "right arrow",
  "\\Rightarrow": "right arrow",
  "\\langle": "open angle",
  "\\rangle": "close angle",
  "\\lfloor": "open floor",
  "\\rfloor": "close floor",
  "\\int": "integral",
  "\\intop": "integral",
  "\\lim": "limit",
  "\\ln": "natural log",
  "\\log": "log",
  "\\sin": "sine",
  "\\cos": "cosine",
  "\\tan": "tangent",
  "\\cot": "cotangent",
  "\\sum": "sum",
  "/": "slash",
  ",": "comma",
  ".": "point",
  "-": "negative",
  "+": "plus",
  "~": "tilde",
  ":": "colon",
  "?": "question mark",
  "'": "apostrophe",
  "\\%": "percent",
  " ": "space",
  "\\ ": "space",
  "\\$": "dollar sign",
  "\\angle": "angle",
  "\\degree": "degree",
  "\\circ": "circle",
  "\\vec": "vector",
  "\\triangle": "triangle",
  "\\pi": "pi",
  "\\prime": "prime",
  "\\infty": "infinity",
  "\\alpha": "alpha",
  "\\beta": "beta",
  "\\gamma": "gamma",
  "\\omega": "omega",
  "\\theta": "theta",
  "\\sigma": "sigma",
  "\\lambda": "lambda",
  "\\tau": "tau",
  "\\Delta": "delta",
  "\\delta": "delta",
  "\\mu": "mu",
  "\\rho": "rho",
  "\\nabla": "del",
  "\\ell": "ell",
  "\\ldots": "dots",
  // TODO: add entries for all accents
  "\\hat": "hat",
  "\\acute": "acute"
};
var powerMap = {
  "prime": "prime",
  "degree": "degrees",
  "circle": "degrees",
  "2": "squared",
  "3": "cubed"
};
var openMap = {
  "|": "open vertical bar",
  ".": ""
};
var closeMap = {
  "|": "close vertical bar",
  ".": ""
};
var binMap = {
  "+": "plus",
  "-": "minus",
  "\\pm": "plus minus",
  "\\cdot": "dot",
  "*": "times",
  "/": "divided by",
  "\\times": "times",
  "\\div": "divided by",
  "\\circ": "circle",
  "\\bullet": "bullet"
};
var relMap = {
  "=": "equals",
  "\\approx": "approximately equals",
  "≠": "does not equal",
  "\\geq": "is greater than or equal to",
  "\\ge": "is greater than or equal to",
  "\\leq": "is less than or equal to",
  "\\le": "is less than or equal to",
  ">": "is greater than",
  "<": "is less than",
  "\\leftarrow": "left arrow",
  "\\Leftarrow": "left arrow",
  "\\rightarrow": "right arrow",
  "\\Rightarrow": "right arrow",
  ":": "colon"
};
var accentUnderMap = {
  "\\underleftarrow": "left arrow",
  "\\underrightarrow": "right arrow",
  "\\underleftrightarrow": "left-right arrow",
  "\\undergroup": "group",
  "\\underlinesegment": "line segment",
  "\\utilde": "tilde"
};

var buildString = (str, type, a11yStrings) => {
  if (!str) {
    return;
  }

  var ret;

  if (type === "open") {
    ret = str in openMap ? openMap[str] : stringMap[str] || str;
  } else if (type === "close") {
    ret = str in closeMap ? closeMap[str] : stringMap[str] || str;
  } else if (type === "bin") {
    ret = binMap[str] || str;
  } else if (type === "rel") {
    ret = relMap[str] || str;
  } else {
    ret = stringMap[str] || str;
  } // If the text to add is a number and there is already a string
  // in the list and the last string is a number then we should
  // combine them into a single number


  if (/^\d+$/.test(ret) && a11yStrings.length > 0 && // TODO(kevinb): check that the last item in a11yStrings is a string
  // I think we might be able to drop the nested arrays, which would make
  // this easier to type
  // $FlowFixMe
  /^\d+$/.test(a11yStrings[a11yStrings.length - 1])) {
    a11yStrings[a11yStrings.length - 1] += ret;
  } else if (ret) {
    a11yStrings.push(ret);
  }
};

var buildRegion = (a11yStrings, callback) => {
  var regionStrings = [];
  a11yStrings.push(regionStrings);
  callback(regionStrings);
};

var handleObject = (tree, a11yStrings, atomType) => {
  // Everything else is assumed to be an object...
  switch (tree.type) {
    case "accent":
      {
        buildRegion(a11yStrings, a11yStrings => {
          buildA11yStrings(tree.base, a11yStrings, atomType);
          a11yStrings.push("with");
          buildString(tree.label, "normal", a11yStrings);
          a11yStrings.push("on top");
        });
        break;
      }

    case "accentUnder":
      {
        buildRegion(a11yStrings, a11yStrings => {
          buildA11yStrings(tree.base, a11yStrings, atomType);
          a11yStrings.push("with");
          buildString(accentUnderMap[tree.label], "normal", a11yStrings);
          a11yStrings.push("underneath");
        });
        break;
      }

    case "accent-token":
      {
        // Used internally by accent symbols.
        break;
      }

    case "atom":
      {
        var {
          text
        } = tree;

        switch (tree.family) {
          case "bin":
            {
              buildString(text, "bin", a11yStrings);
              break;
            }

          case "close":
            {
              buildString(text, "close", a11yStrings);
              break;
            }
          // TODO(kevinb): figure out what should be done for inner

          case "inner":
            {
              buildString(tree.text, "inner", a11yStrings);
              break;
            }

          case "open":
            {
              buildString(text, "open", a11yStrings);
              break;
            }

          case "punct":
            {
              buildString(text, "punct", a11yStrings);
              break;
            }

          case "rel":
            {
              buildString(text, "rel", a11yStrings);
              break;
            }

          default:
            {
              tree.family;
              throw new Error("\"" + tree.family + "\" is not a valid atom type");
            }
        }

        break;
      }

    case "color":
      {
        var color = tree.color.replace(/katex-/, "");
        buildRegion(a11yStrings, regionStrings => {
          regionStrings.push("start color " + color);
          buildA11yStrings(tree.body, regionStrings, atomType);
          regionStrings.push("end color " + color);
        });
        break;
      }

    case "color-token":
      {
        // Used by \color, \colorbox, and \fcolorbox but not directly rendered.
        // It's a leaf node and has no children so just break.
        break;
      }

    case "delimsizing":
      {
        if (tree.delim && tree.delim !== ".") {
          buildString(tree.delim, "normal", a11yStrings);
        }

        break;
      }

    case "genfrac":
      {
        buildRegion(a11yStrings, regionStrings => {
          // genfrac can have unbalanced delimiters
          var {
            leftDelim,
            rightDelim
          } = tree; // NOTE: Not sure if this is a safe assumption
          // hasBarLine true -> fraction, false -> binomial

          if (tree.hasBarLine) {
            regionStrings.push("start fraction");
            leftDelim && buildString(leftDelim, "open", regionStrings);
            buildA11yStrings(tree.numer, regionStrings, atomType);
            regionStrings.push("divided by");
            buildA11yStrings(tree.denom, regionStrings, atomType);
            rightDelim && buildString(rightDelim, "close", regionStrings);
            regionStrings.push("end fraction");
          } else {
            regionStrings.push("start binomial");
            leftDelim && buildString(leftDelim, "open", regionStrings);
            buildA11yStrings(tree.numer, regionStrings, atomType);
            regionStrings.push("over");
            buildA11yStrings(tree.denom, regionStrings, atomType);
            rightDelim && buildString(rightDelim, "close", regionStrings);
            regionStrings.push("end binomial");
          }
        });
        break;
      }

    case "hbox":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "kern":
      {
        // No op: we don't attempt to present kerning information
        // to the screen reader.
        break;
      }

    case "leftright":
      {
        buildRegion(a11yStrings, regionStrings => {
          buildString(tree.left, "open", regionStrings);
          buildA11yStrings(tree.body, regionStrings, atomType);
          buildString(tree.right, "close", regionStrings);
        });
        break;
      }

    case "leftright-right":
      {
        // TODO: double check that this is a no-op
        break;
      }

    case "lap":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "mathord":
      {
        buildString(tree.text, "normal", a11yStrings);
        break;
      }

    case "op":
      {
        var {
          body,
          name
        } = tree;

        if (body) {
          buildA11yStrings(body, a11yStrings, atomType);
        } else if (name) {
          buildString(name, "normal", a11yStrings);
        }

        break;
      }

    case "op-token":
      {
        // Used internally by operator symbols.
        buildString(tree.text, atomType, a11yStrings);
        break;
      }

    case "ordgroup":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "overline":
      {
        buildRegion(a11yStrings, function (a11yStrings) {
          a11yStrings.push("start overline");
          buildA11yStrings(tree.body, a11yStrings, atomType);
          a11yStrings.push("end overline");
        });
        break;
      }

    case "pmb":
      {
        a11yStrings.push("bold");
        break;
      }

    case "phantom":
      {
        a11yStrings.push("empty space");
        break;
      }

    case "raisebox":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "rule":
      {
        a11yStrings.push("rectangle");
        break;
      }

    case "sizing":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "spacing":
      {
        a11yStrings.push("space");
        break;
      }

    case "styling":
      {
        // We ignore the styling and just pass through the contents
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "sqrt":
      {
        buildRegion(a11yStrings, regionStrings => {
          var {
            body,
            index
          } = tree;

          if (index) {
            var indexString = flatten(buildA11yStrings(index, [], atomType)).join(",");

            if (indexString === "3") {
              regionStrings.push("cube root of");
              buildA11yStrings(body, regionStrings, atomType);
              regionStrings.push("end cube root");
              return;
            }

            regionStrings.push("root");
            regionStrings.push("start index");
            buildA11yStrings(index, regionStrings, atomType);
            regionStrings.push("end index");
            return;
          }

          regionStrings.push("square root of");
          buildA11yStrings(body, regionStrings, atomType);
          regionStrings.push("end square root");
        });
        break;
      }

    case "supsub":
      {
        var {
          base,
          sub,
          sup
        } = tree;
        var isLog = false;

        if (base) {
          buildA11yStrings(base, a11yStrings, atomType);
          isLog = base.type === "op" && base.name === "\\log";
        }

        if (sub) {
          var regionName = isLog ? "base" : "subscript";
          buildRegion(a11yStrings, function (regionStrings) {
            regionStrings.push("start " + regionName);
            buildA11yStrings(sub, regionStrings, atomType);
            regionStrings.push("end " + regionName);
          });
        }

        if (sup) {
          buildRegion(a11yStrings, function (regionStrings) {
            var supString = flatten(buildA11yStrings(sup, [], atomType)).join(",");

            if (supString in powerMap) {
              regionStrings.push(powerMap[supString]);
              return;
            }

            regionStrings.push("start superscript");
            buildA11yStrings(sup, regionStrings, atomType);
            regionStrings.push("end superscript");
          });
        }

        break;
      }

    case "text":
      {
        // TODO: handle other fonts
        if (tree.font === "\\textbf") {
          buildRegion(a11yStrings, function (regionStrings) {
            regionStrings.push("start bold text");
            buildA11yStrings(tree.body, regionStrings, atomType);
            regionStrings.push("end bold text");
          });
          break;
        }

        buildRegion(a11yStrings, function (regionStrings) {
          regionStrings.push("start text");
          buildA11yStrings(tree.body, regionStrings, atomType);
          regionStrings.push("end text");
        });
        break;
      }

    case "textord":
      {
        buildString(tree.text, atomType, a11yStrings);
        break;
      }

    case "smash":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "enclose":
      {
        // TODO: create a map for these.
        // TODO: differentiate between a body with a single atom, e.g.
        // "cancel a" instead of "start cancel, a, end cancel"
        if (/cancel/.test(tree.label)) {
          buildRegion(a11yStrings, function (regionStrings) {
            regionStrings.push("start cancel");
            buildA11yStrings(tree.body, regionStrings, atomType);
            regionStrings.push("end cancel");
          });
          break;
        } else if (/box/.test(tree.label)) {
          buildRegion(a11yStrings, function (regionStrings) {
            regionStrings.push("start box");
            buildA11yStrings(tree.body, regionStrings, atomType);
            regionStrings.push("end box");
          });
          break;
        } else if (/sout/.test(tree.label)) {
          buildRegion(a11yStrings, function (regionStrings) {
            regionStrings.push("start strikeout");
            buildA11yStrings(tree.body, regionStrings, atomType);
            regionStrings.push("end strikeout");
          });
          break;
        } else if (/phase/.test(tree.label)) {
          buildRegion(a11yStrings, function (regionStrings) {
            regionStrings.push("start phase angle");
            buildA11yStrings(tree.body, regionStrings, atomType);
            regionStrings.push("end phase angle");
          });
          break;
        }

        throw new Error("KaTeX-a11y: enclose node with " + tree.label + " not supported yet");
      }

    case "vcenter":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "vphantom":
      {
        throw new Error("KaTeX-a11y: vphantom not implemented yet");
      }

    case "hphantom":
      {
        throw new Error("KaTeX-a11y: hphantom not implemented yet");
      }

    case "operatorname":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "array":
      {
        throw new Error("KaTeX-a11y: array not implemented yet");
      }

    case "raw":
      {
        throw new Error("KaTeX-a11y: raw not implemented yet");
      }

    case "size":
      {
        // Although there are nodes of type "size" in the parse tree, they have
        // no semantic meaning and should be ignored.
        break;
      }

    case "url":
      {
        throw new Error("KaTeX-a11y: url not implemented yet");
      }

    case "tag":
      {
        throw new Error("KaTeX-a11y: tag not implemented yet");
      }

    case "verb":
      {
        buildString("start verbatim", "normal", a11yStrings);
        buildString(tree.body, "normal", a11yStrings);
        buildString("end verbatim", "normal", a11yStrings);
        break;
      }

    case "environment":
      {
        throw new Error("KaTeX-a11y: environment not implemented yet");
      }

    case "horizBrace":
      {
        buildString("start " + tree.label.slice(1), "normal", a11yStrings);
        buildA11yStrings(tree.base, a11yStrings, atomType);
        buildString("end " + tree.label.slice(1), "normal", a11yStrings);
        break;
      }

    case "infix":
      {
        // All infix nodes are replace with other nodes.
        break;
      }

    case "includegraphics":
      {
        throw new Error("KaTeX-a11y: includegraphics not implemented yet");
      }

    case "font":
      {
        // TODO: callout the start/end of specific fonts
        // TODO: map \BBb{N} to "the naturals" or something like that
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    case "href":
      {
        throw new Error("KaTeX-a11y: href not implemented yet");
      }

    case "cr":
      {
        // This is used by environments.
        throw new Error("KaTeX-a11y: cr not implemented yet");
      }

    case "underline":
      {
        buildRegion(a11yStrings, function (a11yStrings) {
          a11yStrings.push("start underline");
          buildA11yStrings(tree.body, a11yStrings, atomType);
          a11yStrings.push("end underline");
        });
        break;
      }

    case "xArrow":
      {
        throw new Error("KaTeX-a11y: xArrow not implemented yet");
      }

    case "cdlabel":
      {
        throw new Error("KaTeX-a11y: cdlabel not implemented yet");
      }

    case "cdlabelparent":
      {
        throw new Error("KaTeX-a11y: cdlabelparent not implemented yet");
      }

    case "mclass":
      {
        // \neq and \ne are macros so we let "htmlmathml" render the mathmal
        // side of things and extract the text from that.
        var _atomType = tree.mclass.slice(1); // $FlowFixMe: drop the leading "m" from the values in mclass


        buildA11yStrings(tree.body, a11yStrings, _atomType);
        break;
      }

    case "mathchoice":
      {
        // TODO: track which style we're using, e.g. display, text, etc.
        // default to text style if even that may not be the correct style
        buildA11yStrings(tree.text, a11yStrings, atomType);
        break;
      }

    case "htmlmathml":
      {
        buildA11yStrings(tree.mathml, a11yStrings, atomType);
        break;
      }

    case "middle":
      {
        buildString(tree.delim, atomType, a11yStrings);
        break;
      }

    case "internal":
      {
        // internal nodes are never included in the parse tree
        break;
      }

    case "html":
      {
        buildA11yStrings(tree.body, a11yStrings, atomType);
        break;
      }

    default:
      tree.type;
      throw new Error("KaTeX a11y un-recognized type: " + tree.type);
  }
};

var buildA11yStrings = function buildA11yStrings(tree, a11yStrings, atomType) {
  if (a11yStrings === void 0) {
    a11yStrings = [];
  }

  if (tree instanceof Array) {
    for (var i = 0; i < tree.length; i++) {
      buildA11yStrings(tree[i], a11yStrings, atomType);
    }
  } else {
    handleObject(tree, a11yStrings, atomType);
  }

  return a11yStrings;
};

var flatten = function flatten(array) {
  var result = [];
  array.forEach(function (item) {
    if (item instanceof Array) {
      result = result.concat(flatten(item));
    } else {
      result.push(item);
    }
  });
  return result;
};

var renderA11yString = function renderA11yString(text, settings) {
  var tree = katex.__parse(text, settings);

  var a11yStrings = buildA11yStrings(tree, [], "normal");
  return flatten(a11yStrings).join(", ");
};

export { renderA11yString as default };