mirror of
				https://github.com/bspeice/speice.io
				synced 2025-11-04 02:20:36 -05:00 
			
		
		
		
	Deploy website - based on e49ba23e3f
				
					
				
			This commit is contained in:
		
							
								
								
									
										338
									
								
								katex/contrib/auto-render.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										338
									
								
								katex/contrib/auto-render.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,338 @@
 | 
			
		||||
(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__757__) {
 | 
			
		||||
return /******/ (function() { // webpackBootstrap
 | 
			
		||||
/******/ 	"use strict";
 | 
			
		||||
/******/ 	var __webpack_modules__ = ({
 | 
			
		||||
 | 
			
		||||
/***/ 757:
 | 
			
		||||
/***/ (function(module) {
 | 
			
		||||
 | 
			
		||||
module.exports = __WEBPACK_EXTERNAL_MODULE__757__;
 | 
			
		||||
 | 
			
		||||
/***/ })
 | 
			
		||||
 | 
			
		||||
/******/ 	});
 | 
			
		||||
/************************************************************************/
 | 
			
		||||
/******/ 	// 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__ = {};
 | 
			
		||||
 | 
			
		||||
// EXPORTS
 | 
			
		||||
__webpack_require__.d(__webpack_exports__, {
 | 
			
		||||
  "default": function() { return /* binding */ auto_render; }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// EXTERNAL MODULE: external "katex"
 | 
			
		||||
var external_katex_ = __webpack_require__(757);
 | 
			
		||||
var external_katex_default = /*#__PURE__*/__webpack_require__.n(external_katex_);
 | 
			
		||||
;// CONCATENATED MODULE: ./contrib/auto-render/splitAtDelimiters.js
 | 
			
		||||
/* eslint no-constant-condition:0 */
 | 
			
		||||
const findEndOfMath = function (delimiter, text, startIndex) {
 | 
			
		||||
  // Adapted from
 | 
			
		||||
  // https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
 | 
			
		||||
  let index = startIndex;
 | 
			
		||||
  let braceLevel = 0;
 | 
			
		||||
  const delimLength = delimiter.length;
 | 
			
		||||
 | 
			
		||||
  while (index < text.length) {
 | 
			
		||||
    const 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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const escapeRegex = function (string) {
 | 
			
		||||
  return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const amsRegex = /^\\begin{/;
 | 
			
		||||
 | 
			
		||||
const splitAtDelimiters = function (text, delimiters) {
 | 
			
		||||
  let index;
 | 
			
		||||
  const data = [];
 | 
			
		||||
  const 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:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    const i = delimiters.findIndex(delim => text.startsWith(delim.left));
 | 
			
		||||
    index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length);
 | 
			
		||||
 | 
			
		||||
    if (index === -1) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const rawData = text.slice(0, index + delimiters[i].right.length);
 | 
			
		||||
    const 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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
const renderMathInText = function (text, optionsCopy) {
 | 
			
		||||
  const 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;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const fragment = document.createDocumentFragment();
 | 
			
		||||
 | 
			
		||||
  for (let i = 0; i < data.length; i++) {
 | 
			
		||||
    if (data[i].type === "text") {
 | 
			
		||||
      fragment.appendChild(document.createTextNode(data[i].data));
 | 
			
		||||
    } else {
 | 
			
		||||
      const span = document.createElement("span");
 | 
			
		||||
      let 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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const renderElem = function (elem, optionsCopy) {
 | 
			
		||||
  for (let i = 0; i < elem.childNodes.length; i++) {
 | 
			
		||||
    const 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.
 | 
			
		||||
      let textContentConcat = childNode.textContent;
 | 
			
		||||
      let sibling = childNode.nextSibling;
 | 
			
		||||
      let nSiblings = 0;
 | 
			
		||||
 | 
			
		||||
      while (sibling && sibling.nodeType === Node.TEXT_NODE) {
 | 
			
		||||
        textContentConcat += sibling.textContent;
 | 
			
		||||
        sibling = sibling.nextSibling;
 | 
			
		||||
        nSiblings++;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const frag = renderMathInText(textContentConcat, optionsCopy);
 | 
			
		||||
 | 
			
		||||
      if (frag) {
 | 
			
		||||
        // Remove extra text nodes
 | 
			
		||||
        for (let 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) {
 | 
			
		||||
      // Element node
 | 
			
		||||
      const className = ' ' + childNode.className + ' ';
 | 
			
		||||
      const 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.
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const renderMathInElement = function (elem, options) {
 | 
			
		||||
  if (!elem) {
 | 
			
		||||
    throw new Error("No element provided to render");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const optionsCopy = {}; // Object.assign(optionsCopy, option)
 | 
			
		||||
 | 
			
		||||
  for (const 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__;
 | 
			
		||||
/******/ })()
 | 
			
		||||
;
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										1
									
								
								katex/contrib/auto-render.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								katex/contrib/auto-render.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
!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={757:function(t){t.exports=e}},n={};function r(e){var o=n[e];if(void 0!==o)return o.exports;var i=n[e]={exports:{}};return t[e](i,i.exports,r),i.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var o={};r.d(o,{default:function(){return p}});var i=r(757),a=r.n(i);const l=function(e,t,n){let r=n,o=0;const i=e.length;for(;r<t.length;){const n=t[r];if(o<=0&&t.slice(r,r+i)===e)return r;"\\"===n?r++:"{"===n?o++:"}"===n&&o--,r++}return-1},s=/^\\begin{/;var d=function(e,t){let n;const r=[],o=new RegExp("("+t.map((e=>e.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"))).join("|")+")");for(;n=e.search(o),-1!==n;){n>0&&(r.push({type:"text",data:e.slice(0,n)}),e=e.slice(n));const o=t.findIndex((t=>e.startsWith(t.left)));if(n=l(t[o].right,e,t[o].left.length),-1===n)break;const i=e.slice(0,n+t[o].right.length),a=s.test(i)?i:e.slice(t[o].left.length,n);r.push({type:"math",data:a,rawData:i,display:t[o].display}),e=e.slice(n+t[o].right.length)}return""!==e&&r.push({type:"text",data:e}),r};const c=function(e,t){const n=d(e,t.delimiters);if(1===n.length&&"text"===n[0].type)return null;const r=document.createDocumentFragment();for(let e=0;e<n.length;e++)if("text"===n[e].type)r.appendChild(document.createTextNode(n[e].data));else{const o=document.createElement("span");let i=n[e].data;t.displayMode=n[e].display;try{t.preProcess&&(i=t.preProcess(i)),a().render(i,o,t)}catch(o){if(!(o instanceof a().ParseError))throw o;t.errorCallback("KaTeX auto-render: Failed to parse `"+n[e].data+"` with ",o),r.appendChild(document.createTextNode(n[e].rawData));continue}r.appendChild(o)}return r},f=function(e,t){for(let n=0;n<e.childNodes.length;n++){const r=e.childNodes[n];if(3===r.nodeType){let o=r.textContent,i=r.nextSibling,a=0;for(;i&&i.nodeType===Node.TEXT_NODE;)o+=i.textContent,i=i.nextSibling,a++;const l=c(o,t);if(l){for(let e=0;e<a;e++)r.nextSibling.remove();n+=l.childNodes.length-1,e.replaceChild(l,r)}else n+=a}else if(1===r.nodeType){const e=" "+r.className+" ";-1===t.ignoredTags.indexOf(r.nodeName.toLowerCase())&&t.ignoredClasses.every((t=>-1===e.indexOf(" "+t+" ")))&&f(r,t)}}};var p=function(e,t){if(!e)throw new Error("No element provided to render");const n={};for(const e in t)t.hasOwnProperty(e)&&(n[e]=t[e]);n.delimiters=n.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}],n.ignoredTags=n.ignoredTags||["script","noscript","style","textarea","pre","code","option"],n.ignoredClasses=n.ignoredClasses||[],n.errorCallback=n.errorCallback||console.error,n.macros=n.macros||{},f(e,n)};return o=o.default}()}));
 | 
			
		||||
							
								
								
									
										244
									
								
								katex/contrib/auto-render.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										244
									
								
								katex/contrib/auto-render.mjs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,244 @@
 | 
			
		||||
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 };
 | 
			
		||||
							
								
								
									
										127
									
								
								katex/contrib/copy-tex.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								katex/contrib/copy-tex.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,127 @@
 | 
			
		||||
(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.
 | 
			
		||||
const 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).
 | 
			
		||||
  const katexHtml = fragment.querySelectorAll('.katex-mathml + .katex-html');
 | 
			
		||||
 | 
			
		||||
  for (let i = 0; i < katexHtml.length; i++) {
 | 
			
		||||
    const 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.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  const katexMathml = fragment.querySelectorAll('.katex-mathml');
 | 
			
		||||
 | 
			
		||||
  for (let i = 0; i < katexMathml.length; i++) {
 | 
			
		||||
    const element = katexMathml[i];
 | 
			
		||||
    const 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.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  const displays = fragment.querySelectorAll('.katex-display annotation');
 | 
			
		||||
 | 
			
		||||
  for (let i = 0; i < displays.length; i++) {
 | 
			
		||||
    const element = displays[i];
 | 
			
		||||
    element.innerHTML = copyDelimiters.display[0] + element.innerHTML.substr(copyDelimiters.inline[0].length, element.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.
 | 
			
		||||
  const 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) {
 | 
			
		||||
  const selection = window.getSelection();
 | 
			
		||||
 | 
			
		||||
  if (selection.isCollapsed || !event.clipboardData) {
 | 
			
		||||
    return; // default action OK if selection is empty or unchangeable
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const clipboardData = event.clipboardData;
 | 
			
		||||
  const range = selection.getRangeAt(0); // When start point is within a formula, expand to entire formula.
 | 
			
		||||
 | 
			
		||||
  const startKatex = closestKatex(range.startContainer);
 | 
			
		||||
 | 
			
		||||
  if (startKatex) {
 | 
			
		||||
    range.setStartBefore(startKatex);
 | 
			
		||||
  } // Similarly, when end point is within a formula, expand to entire formula.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  const endKatex = closestKatex(range.endContainer);
 | 
			
		||||
 | 
			
		||||
  if (endKatex) {
 | 
			
		||||
    range.setEndAfter(endKatex);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const fragment = range.cloneContents();
 | 
			
		||||
 | 
			
		||||
  if (!fragment.querySelector('.katex-mathml')) {
 | 
			
		||||
    return; // default action OK if no .katex-mathml elements
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const 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', katex2tex(fragment).textContent); // Prevent normal copy handling.
 | 
			
		||||
 | 
			
		||||
  event.preventDefault();
 | 
			
		||||
});
 | 
			
		||||
__webpack_exports__ = __webpack_exports__["default"];
 | 
			
		||||
/******/ 	return __webpack_exports__;
 | 
			
		||||
/******/ })()
 | 
			
		||||
;
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										1
									
								
								katex/contrib/copy-tex.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								katex/contrib/copy-tex.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
!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 o in n)("object"==typeof exports?exports:e)[o]=n[o]}}("undefined"!=typeof self?self:this,(function(){return function(){"use strict";var e={};const t={inline:["$","$"],display:["$$","$$"]};var n=function(e,n){void 0===n&&(n=t);const o=e.querySelectorAll(".katex-mathml + .katex-html");for(let e=0;e<o.length;e++){const t=o[e];t.remove?t.remove():t.parentNode&&t.parentNode.removeChild(t)}const r=e.querySelectorAll(".katex-mathml");for(let e=0;e<r.length;e++){const t=r[e],o=t.querySelector("annotation");o&&(t.replaceWith?t.replaceWith(o):t.parentNode&&t.parentNode.replaceChild(o,t),o.innerHTML=n.inline[0]+o.innerHTML+n.inline[1])}const l=e.querySelectorAll(".katex-display annotation");for(let e=0;e<l.length;e++){const t=l[e];t.innerHTML=n.display[0]+t.innerHTML.substr(n.inline[0].length,t.innerHTML.length-n.inline[0].length-n.inline[1].length)+n.display[1]}return e};function o(e){const t=e instanceof Element?e:e.parentElement;return t&&t.closest(".katex")}return document.addEventListener("copy",(function(e){const t=window.getSelection();if(t.isCollapsed||!e.clipboardData)return;const r=e.clipboardData,l=t.getRangeAt(0),i=o(l.startContainer);i&&l.setStartBefore(i);const a=o(l.endContainer);a&&l.setEndAfter(a);const s=l.cloneContents();if(!s.querySelector(".katex-mathml"))return;const c=Array.prototype.map.call(s.childNodes,(e=>e instanceof Text?e.textContent:e.outerHTML)).join("");r.setData("text/html",c),r.setData("text/plain",n(s).textContent),e.preventDefault()})),e=e.default}()}));
 | 
			
		||||
							
								
								
									
										105
									
								
								katex/contrib/copy-tex.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								katex/contrib/copy-tex.mjs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,105 @@
 | 
			
		||||
// 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();
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										109
									
								
								katex/contrib/mathtex-script-type.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								katex/contrib/mathtex-script-type.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,109 @@
 | 
			
		||||
(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__757__) {
 | 
			
		||||
return /******/ (function() { // webpackBootstrap
 | 
			
		||||
/******/ 	"use strict";
 | 
			
		||||
/******/ 	var __webpack_modules__ = ({
 | 
			
		||||
 | 
			
		||||
/***/ 757:
 | 
			
		||||
/***/ (function(module) {
 | 
			
		||||
 | 
			
		||||
module.exports = __WEBPACK_EXTERNAL_MODULE__757__;
 | 
			
		||||
 | 
			
		||||
/***/ })
 | 
			
		||||
 | 
			
		||||
/******/ 	});
 | 
			
		||||
/************************************************************************/
 | 
			
		||||
/******/ 	// 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__ = {};
 | 
			
		||||
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(757);
 | 
			
		||||
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(katex__WEBPACK_IMPORTED_MODULE_0__);
 | 
			
		||||
 | 
			
		||||
let 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;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const display = script.type.match(/mode\s*=\s*display(;|\s|\n|$)/) != null;
 | 
			
		||||
  const 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__;
 | 
			
		||||
/******/ })()
 | 
			
		||||
;
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										1
									
								
								katex/contrib/mathtex-script-type.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								katex/contrib/mathtex-script-type.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
!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 n="object"==typeof exports?t(require("katex")):t(e.katex);for(var r in n)("object"==typeof exports?exports:e)[r]=n[r]}}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={757:function(t){t.exports=e}},n={};function r(e){var o=n[e];if(void 0!==o)return o.exports;var i=n[e]={exports:{}};return t[e](i,i.exports,r),i.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var o={},i=r(757),a=r.n(i);let u=document.body.getElementsByTagName("script");return u=Array.prototype.slice.call(u),u.forEach((function(e){if(!e.type||!e.type.match(/math\/tex/i))return-1;const t=null!=e.type.match(/mode\s*=\s*display(;|\s|\n|$)/),n=document.createElement(t?"div":"span");n.setAttribute("class",t?"equation":"inline-equation");try{a().render(e.text,n,{displayMode:t})}catch(t){n.textContent=e.text}e.parentNode.replaceChild(n,e)})),o=o.default}()}));
 | 
			
		||||
							
								
								
									
										24
									
								
								katex/contrib/mathtex-script-type.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								katex/contrib/mathtex-script-type.mjs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
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);
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										3213
									
								
								katex/contrib/mhchem.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3213
									
								
								katex/contrib/mhchem.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1
									
								
								katex/contrib/mhchem.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								katex/contrib/mhchem.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										3109
									
								
								katex/contrib/mhchem.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3109
									
								
								katex/contrib/mhchem.mjs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										887
									
								
								katex/contrib/render-a11y-string.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										887
									
								
								katex/contrib/render-a11y-string.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,887 @@
 | 
			
		||||
(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__757__) {
 | 
			
		||||
return /******/ (function() { // webpackBootstrap
 | 
			
		||||
/******/ 	"use strict";
 | 
			
		||||
/******/ 	var __webpack_modules__ = ({
 | 
			
		||||
 | 
			
		||||
/***/ 757:
 | 
			
		||||
/***/ (function(module) {
 | 
			
		||||
 | 
			
		||||
module.exports = __WEBPACK_EXTERNAL_MODULE__757__;
 | 
			
		||||
 | 
			
		||||
/***/ })
 | 
			
		||||
 | 
			
		||||
/******/ 	});
 | 
			
		||||
/************************************************************************/
 | 
			
		||||
/******/ 	// 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__ = {};
 | 
			
		||||
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(757);
 | 
			
		||||
/* 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
 | 
			
		||||
 | 
			
		||||
const 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"
 | 
			
		||||
};
 | 
			
		||||
const powerMap = {
 | 
			
		||||
  "prime": "prime",
 | 
			
		||||
  "degree": "degrees",
 | 
			
		||||
  "circle": "degrees",
 | 
			
		||||
  "2": "squared",
 | 
			
		||||
  "3": "cubed"
 | 
			
		||||
};
 | 
			
		||||
const openMap = {
 | 
			
		||||
  "|": "open vertical bar",
 | 
			
		||||
  ".": ""
 | 
			
		||||
};
 | 
			
		||||
const closeMap = {
 | 
			
		||||
  "|": "close vertical bar",
 | 
			
		||||
  ".": ""
 | 
			
		||||
};
 | 
			
		||||
const binMap = {
 | 
			
		||||
  "+": "plus",
 | 
			
		||||
  "-": "minus",
 | 
			
		||||
  "\\pm": "plus minus",
 | 
			
		||||
  "\\cdot": "dot",
 | 
			
		||||
  "*": "times",
 | 
			
		||||
  "/": "divided by",
 | 
			
		||||
  "\\times": "times",
 | 
			
		||||
  "\\div": "divided by",
 | 
			
		||||
  "\\circ": "circle",
 | 
			
		||||
  "\\bullet": "bullet"
 | 
			
		||||
};
 | 
			
		||||
const 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"
 | 
			
		||||
};
 | 
			
		||||
const accentUnderMap = {
 | 
			
		||||
  "\\underleftarrow": "left arrow",
 | 
			
		||||
  "\\underrightarrow": "right arrow",
 | 
			
		||||
  "\\underleftrightarrow": "left-right arrow",
 | 
			
		||||
  "\\undergroup": "group",
 | 
			
		||||
  "\\underlinesegment": "line segment",
 | 
			
		||||
  "\\utilde": "tilde"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const buildString = (str, type, a11yStrings) => {
 | 
			
		||||
  if (!str) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let 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);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const buildRegion = (a11yStrings, callback) => {
 | 
			
		||||
  const regionStrings = [];
 | 
			
		||||
  a11yStrings.push(regionStrings);
 | 
			
		||||
  callback(regionStrings);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const 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":
 | 
			
		||||
      {
 | 
			
		||||
        const {
 | 
			
		||||
          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":
 | 
			
		||||
      {
 | 
			
		||||
        const 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
 | 
			
		||||
          const {
 | 
			
		||||
            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":
 | 
			
		||||
      {
 | 
			
		||||
        const {
 | 
			
		||||
          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 => {
 | 
			
		||||
          const {
 | 
			
		||||
            body,
 | 
			
		||||
            index
 | 
			
		||||
          } = tree;
 | 
			
		||||
 | 
			
		||||
          if (index) {
 | 
			
		||||
            const 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":
 | 
			
		||||
      {
 | 
			
		||||
        const {
 | 
			
		||||
          base,
 | 
			
		||||
          sub,
 | 
			
		||||
          sup
 | 
			
		||||
        } = tree;
 | 
			
		||||
        let isLog = false;
 | 
			
		||||
 | 
			
		||||
        if (base) {
 | 
			
		||||
          buildA11yStrings(base, a11yStrings, atomType);
 | 
			
		||||
          isLog = base.type === "op" && base.name === "\\log";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (sub) {
 | 
			
		||||
          const 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) {
 | 
			
		||||
            const 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.
 | 
			
		||||
        const 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);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const buildA11yStrings = function (tree, a11yStrings, atomType) {
 | 
			
		||||
  if (a11yStrings === void 0) {
 | 
			
		||||
    a11yStrings = [];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (tree instanceof Array) {
 | 
			
		||||
    for (let i = 0; i < tree.length; i++) {
 | 
			
		||||
      buildA11yStrings(tree[i], a11yStrings, atomType);
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    handleObject(tree, a11yStrings, atomType);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return a11yStrings;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const flatten = function (array) {
 | 
			
		||||
  let result = [];
 | 
			
		||||
  array.forEach(function (item) {
 | 
			
		||||
    if (item instanceof Array) {
 | 
			
		||||
      result = result.concat(flatten(item));
 | 
			
		||||
    } else {
 | 
			
		||||
      result.push(item);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  return result;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const renderA11yString = function (text, settings) {
 | 
			
		||||
  const tree = katex__WEBPACK_IMPORTED_MODULE_0___default().__parse(text, settings);
 | 
			
		||||
 | 
			
		||||
  const a11yStrings = buildA11yStrings(tree, [], "normal");
 | 
			
		||||
  return flatten(a11yStrings).join(", ");
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* harmony default export */ __webpack_exports__["default"] = (renderA11yString);
 | 
			
		||||
__webpack_exports__ = __webpack_exports__["default"];
 | 
			
		||||
/******/ 	return __webpack_exports__;
 | 
			
		||||
/******/ })()
 | 
			
		||||
;
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										1
									
								
								katex/contrib/render-a11y-string.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								katex/contrib/render-a11y-string.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										800
									
								
								katex/contrib/render-a11y-string.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										800
									
								
								katex/contrib/render-a11y-string.mjs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,800 @@
 | 
			
		||||
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 };
 | 
			
		||||
		Reference in New Issue
	
	Block a user