sashimi-webapp/src/logic/documentPackager/plugins/ASCIIMathTeXImg.js
/*
ASCIIMathTeXImg.js
Based on ASCIIMathML, Version 1.4.7 Aug 30, 2005, (c) Peter Jipsen http://www.chapman.edu/~jipsen
Modified with TeX conversion for IMG rendering Sept 6, 2006 (c) David Lippman http://www.pierce.ctc.edu/dlippman
Updated to match ver 2.2 Mar 3, 2014
Latest at https://github.com/mathjax/asciimathml
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/* eslint max-len:0 */
const AMTcgiloc = ''; // set to the URL of your LaTex renderer
// const noMathRender = false;
const config = {
translateOnLoad: false, // true to autotranslate
mathcolor: '', // defaults to back, or specify any other color
displaystyle: true, // puts limits above and below large operators
showasciiformulaonhover: true, // helps students learn ASCIIMath
decimalsign: ',', // change to "," if you like, beware of `(1,2)`!
AMdelimiter1: '`',
AMescape1: '\\\\`', // can use other characters
AMusedelimiter2: false, // whether to use second delimiter below
AMdelimiter2: '$',
AMescape2: '\\\\\\$',
AMdelimiter2regexp: '\\$',
AMdocumentId: 'wikitext', // PmWiki element containing math (default=body)
doubleblankmathdelimiter: false // if true, x+1 is equal to `x+1`
}; // for IE this works only in <!-- -->
// token types
const CONST = 0;
const UNARY = 1;
const BINARY = 2;
const INFIX = 3;
const LEFTBRACKET = 4;
const RIGHTBRACKET = 5;
const SPACE = 6;
const UNDEROVER = 7;
const DEFINITION = 8;
const LEFTRIGHT = 9;
const TEXT = 10;
const AMsqrt = { input: 'sqrt', tag: 'msqrt', output: 'sqrt', tex: null, ttype: UNARY };
const AMroot = { input: 'root', tag: 'mroot', output: 'root', tex: null, ttype: BINARY };
const AMfrac = { input: 'frac', tag: 'mfrac', output: '/', tex: null, ttype: BINARY };
const AMdiv = { input: '/', tag: 'mfrac', output: '/', tex: null, ttype: INFIX };
const AMover = { input: 'stackrel', tag: 'mover', output: 'stackrel', tex: null, ttype: BINARY };
const AMsub = { input: '_', tag: 'msub', output: '_', tex: null, ttype: INFIX };
const AMsup = { input: '^', tag: 'msup', output: '^', tex: null, ttype: INFIX };
const AMtext = { input: 'text', tag: 'mtext', output: 'text', tex: null, ttype: TEXT };
const AMmbox = { input: 'mbox', tag: 'mtext', output: 'mbox', tex: null, ttype: TEXT };
const AMquote = { input: '"', tag: 'mtext', output: 'mbox', tex: null, ttype: TEXT };
const AMsymbols = [
// some greek symbols
{ input: 'alpha', tag: 'mi', output: '\u03B1', tex: null, ttype: CONST },
{ input: 'beta', tag: 'mi', output: '\u03B2', tex: null, ttype: CONST },
{ input: 'chi', tag: 'mi', output: '\u03C7', tex: null, ttype: CONST },
{ input: 'delta', tag: 'mi', output: '\u03B4', tex: null, ttype: CONST },
{ input: 'Delta', tag: 'mo', output: '\u0394', tex: null, ttype: CONST },
{ input: 'epsi', tag: 'mi', output: '\u03B5', tex: 'epsilon', ttype: CONST },
{ input: 'varepsilon', tag: 'mi', output: '\u025B', tex: null, ttype: CONST },
{ input: 'eta', tag: 'mi', output: '\u03B7', tex: null, ttype: CONST },
{ input: 'gamma', tag: 'mi', output: '\u03B3', tex: null, ttype: CONST },
{ input: 'Gamma', tag: 'mo', output: '\u0393', tex: null, ttype: CONST },
{ input: 'iota', tag: 'mi', output: '\u03B9', tex: null, ttype: CONST },
{ input: 'kappa', tag: 'mi', output: '\u03BA', tex: null, ttype: CONST },
{ input: 'lambda', tag: 'mi', output: '\u03BB', tex: null, ttype: CONST },
{ input: 'Lambda', tag: 'mo', output: '\u039B', tex: null, ttype: CONST },
{ input: 'lamda', tag: 'mi', output: 'lambda', tex: null, ttype: DEFINITION },
{ input: 'Lamda', tag: 'mi', output: 'Lambda', tex: null, ttype: DEFINITION },
{ input: 'mu', tag: 'mi', output: '\u03BC', tex: null, ttype: CONST },
{ input: 'nu', tag: 'mi', output: '\u03BD', tex: null, ttype: CONST },
{ input: 'omega', tag: 'mi', output: '\u03C9', tex: null, ttype: CONST },
{ input: 'Omega', tag: 'mo', output: '\u03A9', tex: null, ttype: CONST },
{ input: 'phi', tag: 'mi', output: '\u03C6', tex: null, ttype: CONST },
{ input: 'varphi', tag: 'mi', output: '\u03D5', tex: null, ttype: CONST },
{ input: 'Phi', tag: 'mo', output: '\u03A6', tex: null, ttype: CONST },
{ input: 'pi', tag: 'mi', output: '\u03C0', tex: null, ttype: CONST },
{ input: 'Pi', tag: 'mo', output: '\u03A0', tex: null, ttype: CONST },
{ input: 'psi', tag: 'mi', output: '\u03C8', tex: null, ttype: CONST },
{ input: 'Psi', tag: 'mi', output: '\u03A8', tex: null, ttype: CONST },
{ input: 'rho', tag: 'mi', output: '\u03C1', tex: null, ttype: CONST },
{ input: 'sigma', tag: 'mi', output: '\u03C3', tex: null, ttype: CONST },
{ input: 'Sigma', tag: 'mo', output: '\u03A3', tex: null, ttype: CONST },
{ input: 'tau', tag: 'mi', output: '\u03C4', tex: null, ttype: CONST },
{ input: 'theta', tag: 'mi', output: '\u03B8', tex: null, ttype: CONST },
{ input: 'vartheta', tag: 'mi', output: '\u03D1', tex: null, ttype: CONST },
{ input: 'Theta', tag: 'mo', output: '\u0398', tex: null, ttype: CONST },
{ input: 'upsilon', tag: 'mi', output: '\u03C5', tex: null, ttype: CONST },
{ input: 'xi', tag: 'mi', output: '\u03BE', tex: null, ttype: CONST },
{ input: 'Xi', tag: 'mo', output: '\u039E', tex: null, ttype: CONST },
{ input: 'zeta', tag: 'mi', output: '\u03B6', tex: null, ttype: CONST },
// binary operation symbols
{ input: '*', tag: 'mo', output: '\u22C5', tex: 'cdot', ttype: CONST },
{ input: '**', tag: 'mo', output: '\u2217', tex: 'ast', ttype: CONST },
{ input: '***', tag: 'mo', output: '\u22C6', tex: 'star', ttype: CONST },
{ input: '//', tag: 'mo', output: '/', tex: '/', ttype: CONST, val: true, notexcopy: true },
{ input: '\\\\', tag: 'mo', output: '\\', tex: 'backslash', ttype: CONST },
{ input: 'setminus', tag: 'mo', output: '\\', tex: null, ttype: CONST },
{ input: 'xx', tag: 'mo', output: '\u00D7', tex: 'times', ttype: CONST },
{ input: '|><', tag: 'mo', output: '\u22C9', tex: 'ltimes', ttype: CONST },
{ input: '><|', tag: 'mo', output: '\u22CA', tex: 'rtimes', ttype: CONST },
{ input: '|><|', tag: 'mo', output: '\u22C8', tex: 'bowtie', ttype: CONST },
{ input: '-:', tag: 'mo', output: '\u00F7', tex: 'div', ttype: CONST },
{ input: 'divide', tag: 'mo', output: '-:', tex: null, ttype: DEFINITION },
{ input: '@', tag: 'mo', output: '\u2218', tex: 'circ', ttype: CONST },
{ input: 'o+', tag: 'mo', output: '\u2295', tex: 'oplus', ttype: CONST },
{ input: 'ox', tag: 'mo', output: '\u2297', tex: 'otimes', ttype: CONST },
{ input: 'o.', tag: 'mo', output: '\u2299', tex: 'odot', ttype: CONST },
{ input: 'sum', tag: 'mo', output: '\u2211', tex: null, ttype: UNDEROVER },
{ input: 'prod', tag: 'mo', output: '\u220F', tex: null, ttype: UNDEROVER },
{ input: '^^', tag: 'mo', output: '\u2227', tex: 'wedge', ttype: CONST },
{ input: '^^^', tag: 'mo', output: '\u22C0', tex: 'bigwedge', ttype: UNDEROVER },
{ input: 'vv', tag: 'mo', output: '\u2228', tex: 'vee', ttype: CONST },
{ input: 'vvv', tag: 'mo', output: '\u22C1', tex: 'bigvee', ttype: UNDEROVER },
{ input: 'nn', tag: 'mo', output: '\u2229', tex: 'cap', ttype: CONST },
{ input: 'nnn', tag: 'mo', output: '\u22C2', tex: 'bigcap', ttype: UNDEROVER },
{ input: 'uu', tag: 'mo', output: '\u222A', tex: 'cup', ttype: CONST },
{ input: 'uuu', tag: 'mo', output: '\u22C3', tex: 'bigcup', ttype: UNDEROVER },
{ input: 'overset', tag: 'mover', output: 'stackrel', tex: null, ttype: BINARY },
{ input: 'underset', tag: 'munder', output: 'stackrel', tex: null, ttype: BINARY },
// binary relation symbols
{ input: '!=', tag: 'mo', output: '\u2260', tex: 'ne', ttype: CONST },
{ input: ':=', tag: 'mo', output: ':=', tex: null, ttype: CONST },
{ input: 'lt', tag: 'mo', output: '<', tex: null, ttype: CONST },
{ input: 'gt', tag: 'mo', output: '>', tex: null, ttype: CONST },
{ input: '<=', tag: 'mo', output: '\u2264', tex: 'le', ttype: CONST },
{ input: 'lt=', tag: 'mo', output: '\u2264', tex: 'leq', ttype: CONST },
{ input: 'gt=', tag: 'mo', output: '\u2265', tex: 'geq', ttype: CONST },
{ input: '>=', tag: 'mo', output: '\u2265', tex: 'ge', ttype: CONST },
{ input: '-<', tag: 'mo', output: '\u227A', tex: 'prec', ttype: CONST },
{ input: '-lt', tag: 'mo', output: '\u227A', tex: null, ttype: CONST },
{ input: '>-', tag: 'mo', output: '\u227B', tex: 'succ', ttype: CONST },
{ input: '-<=', tag: 'mo', output: '\u2AAF', tex: 'preceq', ttype: CONST },
{ input: '>-=', tag: 'mo', output: '\u2AB0', tex: 'succeq', ttype: CONST },
{ input: 'in', tag: 'mo', output: '\u2208', tex: null, ttype: CONST },
{ input: '!in', tag: 'mo', output: '\u2209', tex: 'notin', ttype: CONST },
{ input: 'sub', tag: 'mo', output: '\u2282', tex: 'subset', ttype: CONST },
{ input: 'sup', tag: 'mo', output: '\u2283', tex: 'supset', ttype: CONST },
{ input: 'sube', tag: 'mo', output: '\u2286', tex: 'subseteq', ttype: CONST },
{ input: 'supe', tag: 'mo', output: '\u2287', tex: 'supseteq', ttype: CONST },
{ input: '-=', tag: 'mo', output: '\u2261', tex: 'equiv', ttype: CONST },
{ input: '~=', tag: 'mo', output: '\u2245', tex: 'stackrel{\\sim}{=}', ttype: CONST }, // back hack b/c mimetex doesn't support /cong
{ input: 'cong', tag: 'mo', output: '~=', tex: null, ttype: DEFINITION },
{ input: '~~', tag: 'mo', output: '\u2248', tex: 'approx', ttype: CONST },
{ input: 'prop', tag: 'mo', output: '\u221D', tex: 'propto', ttype: CONST },
// logical symbols
{ input: 'and', tag: 'mtext', output: 'and', tex: null, ttype: SPACE },
{ input: 'or', tag: 'mtext', output: 'or', tex: null, ttype: SPACE },
{ input: 'not', tag: 'mo', output: '\u00AC', tex: 'neg', ttype: CONST },
{ input: '=>', tag: 'mo', output: '\u21D2', tex: 'Rightarrow', ttype: CONST },
{ input: 'implies', tag: 'mo', output: '=>', tex: null, ttype: DEFINITION },
{ input: 'if', tag: 'mo', output: 'if', tex: null, ttype: SPACE },
{ input: '<=>', tag: 'mo', output: '\u21D4', tex: 'Leftrightarrow', ttype: CONST },
{ input: 'iff', tag: 'mo', output: '<=>', tex: null, ttype: DEFINITION },
{ input: 'AA', tag: 'mo', output: '\u2200', tex: 'forall', ttype: CONST },
{ input: 'EE', tag: 'mo', output: '\u2203', tex: 'exists', ttype: CONST },
{ input: '_|_', tag: 'mo', output: '\u22A5', tex: 'bot', ttype: CONST },
{ input: 'TT', tag: 'mo', output: '\u22A4', tex: 'top', ttype: CONST },
{ input: '|--', tag: 'mo', output: '\u22A2', tex: 'vdash', ttype: CONST },
{ input: '|==', tag: 'mo', output: '\u22A8', tex: 'models', ttype: CONST }, // mimetex doesn't support
// grouping brackets
{ input: '(', tag: 'mo', output: '(', tex: null, ttype: LEFTBRACKET, val: true },
{ input: ')', tag: 'mo', output: ')', tex: null, ttype: RIGHTBRACKET, val: true },
{ input: '[', tag: 'mo', output: '[', tex: null, ttype: LEFTBRACKET, val: true },
{ input: ']', tag: 'mo', output: ']', tex: null, ttype: RIGHTBRACKET, val: true },
{ input: '{', tag: 'mo', output: '{', tex: 'lbrace', ttype: LEFTBRACKET },
{ input: '}', tag: 'mo', output: '}', tex: 'rbrace', ttype: RIGHTBRACKET },
{ input: '|', tag: 'mo', output: '|', tex: null, ttype: LEFTRIGHT, val: true },
// {input:"||", tag:"mo", output:"||", tex:null, ttype:LEFTRIGHT},
{ input: '(:', tag: 'mo', output: '\u2329', tex: 'langle', ttype: LEFTBRACKET },
{ input: ':)', tag: 'mo', output: '\u232A', tex: 'rangle', ttype: RIGHTBRACKET },
{ input: '<<', tag: 'mo', output: '\u2329', tex: 'langle', ttype: LEFTBRACKET },
{ input: '>>', tag: 'mo', output: '\u232A', tex: 'rangle', ttype: RIGHTBRACKET },
{ input: '{:', tag: 'mo', output: '{:', tex: null, ttype: LEFTBRACKET, invisible: true },
{ input: ':}', tag: 'mo', output: ':}', tex: null, ttype: RIGHTBRACKET, invisible: true },
// miscellaneous symbols
{ input: 'int', tag: 'mo', output: '\u222B', tex: null, ttype: CONST },
{ input: 'dx', tag: 'mi', output: '{:d x:}', tex: null, ttype: DEFINITION },
{ input: 'dy', tag: 'mi', output: '{:d y:}', tex: null, ttype: DEFINITION },
{ input: 'dz', tag: 'mi', output: '{:d z:}', tex: null, ttype: DEFINITION },
{ input: 'dt', tag: 'mi', output: '{:d t:}', tex: null, ttype: DEFINITION },
{ input: 'oint', tag: 'mo', output: '\u222E', tex: null, ttype: CONST },
{ input: 'del', tag: 'mo', output: '\u2202', tex: 'partial', ttype: CONST },
{ input: 'grad', tag: 'mo', output: '\u2207', tex: 'nabla', ttype: CONST },
{ input: '+-', tag: 'mo', output: '\u00B1', tex: 'pm', ttype: CONST },
{ input: 'O/', tag: 'mo', output: '\u2205', tex: 'emptyset', ttype: CONST },
{ input: 'oo', tag: 'mo', output: '\u221E', tex: 'infty', ttype: CONST },
{ input: 'aleph', tag: 'mo', output: '\u2135', tex: null, ttype: CONST },
{ input: '...', tag: 'mo', output: '...', tex: 'ldots', ttype: CONST },
{ input: ':.', tag: 'mo', output: '\u2234', tex: 'therefore', ttype: CONST },
{ input: '/_', tag: 'mo', output: '\u2220', tex: 'angle', ttype: CONST },
{ input: '/_\\', tag: 'mo', output: '\u25B3', tex: 'triangle', ttype: CONST },
{ input: '\\ ', tag: 'mo', output: '\u00A0', tex: null, ttype: CONST, val: true },
{ input: 'frown', tag: 'mo', output: '\u2322', tex: null, ttype: CONST },
{ input: '%', tag: 'mo', output: '%', tex: '%', ttype: CONST, notexcopy: true },
{ input: 'quad', tag: 'mo', output: '\u00A0\u00A0', tex: null, ttype: CONST },
{ input: 'qquad', tag: 'mo', output: '\u00A0\u00A0\u00A0\u00A0', tex: null, ttype: CONST },
{ input: 'cdots', tag: 'mo', output: '\u22EF', tex: null, ttype: CONST },
{ input: 'vdots', tag: 'mo', output: '\u22EE', tex: null, ttype: CONST },
{ input: 'ddots', tag: 'mo', output: '\u22F1', tex: null, ttype: CONST },
{ input: 'diamond', tag: 'mo', output: '\u22C4', tex: null, ttype: CONST },
{ input: 'square', tag: 'mo', output: '\u25A1', tex: 'boxempty', ttype: CONST },
{ input: '|__', tag: 'mo', output: '\u230A', tex: 'lfloor', ttype: CONST },
{ input: '__|', tag: 'mo', output: '\u230B', tex: 'rfloor', ttype: CONST },
{ input: '|~', tag: 'mo', output: '\u2308', tex: 'lceil', ttype: CONST },
{ input: 'lceiling', tag: 'mo', output: '|~', tex: null, ttype: DEFINITION },
{ input: '~|', tag: 'mo', output: '\u2309', tex: 'rceil', ttype: CONST },
{ input: 'rceiling', tag: 'mo', output: '~|', tex: null, ttype: DEFINITION },
{ input: 'CC', tag: 'mo', output: '\u2102', tex: 'mathbb{C}', ttype: CONST, notexcopy: true },
{ input: 'NN', tag: 'mo', output: '\u2115', tex: 'mathbb{N}', ttype: CONST, notexcopy: true },
{ input: 'QQ', tag: 'mo', output: '\u211A', tex: 'mathbb{Q}', ttype: CONST, notexcopy: true },
{ input: 'RR', tag: 'mo', output: '\u211D', tex: 'mathbb{R}', ttype: CONST, notexcopy: true },
{ input: 'ZZ', tag: 'mo', output: '\u2124', tex: 'mathbb{Z}', ttype: CONST, notexcopy: true },
{ input: 'f', tag: 'mi', output: 'f', tex: null, ttype: UNARY, func: true, val: true },
{ input: 'g', tag: 'mi', output: 'g', tex: null, ttype: UNARY, func: true, val: true },
{ input: '\'\'', tag: 'mo', output: '\'\'', tex: null, val: true },
{ input: '\'\'\'', tag: 'mo', output: '\'\'\'', tex: null, val: true },
{ input: '\'\'\'\'', tag: 'mo', output: '\'\'\'\'', tex: null, val: true },
// standard functions
{ input: 'lim', tag: 'mo', output: 'lim', tex: null, ttype: UNDEROVER },
{ input: 'Lim', tag: 'mo', output: 'Lim', tex: null, ttype: UNDEROVER },
{ input: 'sin', tag: 'mo', output: 'sin', tex: null, ttype: UNARY, func: true },
{ input: 'cos', tag: 'mo', output: 'cos', tex: null, ttype: UNARY, func: true },
{ input: 'tan', tag: 'mo', output: 'tan', tex: null, ttype: UNARY, func: true },
{ input: 'arcsin', tag: 'mo', output: 'arcsin', tex: null, ttype: UNARY, func: true },
{ input: 'arccos', tag: 'mo', output: 'arccos', tex: null, ttype: UNARY, func: true },
{ input: 'arctan', tag: 'mo', output: 'arctan', tex: null, ttype: UNARY, func: true },
{ input: 'sinh', tag: 'mo', output: 'sinh', tex: null, ttype: UNARY, func: true },
{ input: 'cosh', tag: 'mo', output: 'cosh', tex: null, ttype: UNARY, func: true },
{ input: 'tanh', tag: 'mo', output: 'tanh', tex: null, ttype: UNARY, func: true },
{ input: 'cot', tag: 'mo', output: 'cot', tex: null, ttype: UNARY, func: true },
{ input: 'coth', tag: 'mo', output: 'coth', tex: null, ttype: UNARY, func: true },
{ input: 'sech', tag: 'mo', output: 'sech', tex: null, ttype: UNARY, func: true },
{ input: 'csch', tag: 'mo', output: 'csch', tex: null, ttype: UNARY, func: true },
{ input: 'sec', tag: 'mo', output: 'sec', tex: null, ttype: UNARY, func: true },
{ input: 'csc', tag: 'mo', output: 'csc', tex: null, ttype: UNARY, func: true },
{ input: 'log', tag: 'mo', output: 'log', tex: null, ttype: UNARY, func: true },
{ input: 'ln', tag: 'mo', output: 'ln', tex: null, ttype: UNARY, func: true },
{ input: 'abs', tag: 'mo', output: 'abs', tex: null, ttype: UNARY, notexcopy: true, rewriteleftright: ['|', '|'] },
{ input: 'norm', tag: 'mo', output: 'norm', tex: null, ttype: UNARY, notexcopy: true, rewriteleftright: ['\\|', '\\|'] },
{ input: 'floor', tag: 'mo', output: 'floor', tex: null, ttype: UNARY, notexcopy: true, rewriteleftright: ['\\lfloor', '\\rfloor'] },
{ input: 'ceil', tag: 'mo', output: 'ceil', tex: null, ttype: UNARY, notexcopy: true, rewriteleftright: ['\\lceil', '\\rceil'] },
{ input: 'Sin', tag: 'mo', output: 'sin', tex: null, ttype: UNARY, func: true },
{ input: 'Cos', tag: 'mo', output: 'cos', tex: null, ttype: UNARY, func: true },
{ input: 'Tan', tag: 'mo', output: 'tan', tex: null, ttype: UNARY, func: true },
{ input: 'Arcsin', tag: 'mo', output: 'arcsin', tex: null, ttype: UNARY, func: true },
{ input: 'Arccos', tag: 'mo', output: 'arccos', tex: null, ttype: UNARY, func: true },
{ input: 'Arctan', tag: 'mo', output: 'arctan', tex: null, ttype: UNARY, func: true },
{ input: 'Sinh', tag: 'mo', output: 'sinh', tex: null, ttype: UNARY, func: true },
{ input: 'Sosh', tag: 'mo', output: 'cosh', tex: null, ttype: UNARY, func: true },
{ input: 'Tanh', tag: 'mo', output: 'tanh', tex: null, ttype: UNARY, func: true },
{ input: 'Cot', tag: 'mo', output: 'cot', tex: null, ttype: UNARY, func: true },
{ input: 'Sec', tag: 'mo', output: 'sec', tex: null, ttype: UNARY, func: true },
{ input: 'Csc', tag: 'mo', output: 'csc', tex: null, ttype: UNARY, func: true },
{ input: 'Log', tag: 'mo', output: 'log', tex: null, ttype: UNARY, func: true },
{ input: 'Ln', tag: 'mo', output: 'ln', tex: null, ttype: UNARY, func: true },
{ input: 'Abs', tag: 'mo', output: 'abs', tex: null, ttype: UNARY, notexcopy: true, rewriteleftright: ['|', '|'] },
{ input: 'det', tag: 'mo', output: 'det', tex: null, ttype: UNARY, func: true },
{ input: 'exp', tag: 'mo', output: 'exp', tex: null, ttype: UNARY, func: true },
{ input: 'dim', tag: 'mo', output: 'dim', tex: null, ttype: CONST },
{ input: 'mod', tag: 'mo', output: 'mod', tex: 'text{mod}', ttype: CONST, notexcopy: true },
{ input: 'gcd', tag: 'mo', output: 'gcd', tex: null, ttype: UNARY, func: true },
{ input: 'lcm', tag: 'mo', output: 'lcm', tex: 'text{lcm}', ttype: UNARY, func: true, notexcopy: true },
{ input: 'lub', tag: 'mo', output: 'lub', tex: null, ttype: CONST },
{ input: 'glb', tag: 'mo', output: 'glb', tex: null, ttype: CONST },
{ input: 'min', tag: 'mo', output: 'min', tex: null, ttype: UNDEROVER },
{ input: 'max', tag: 'mo', output: 'max', tex: null, ttype: UNDEROVER },
// arrows
{ input: 'uarr', tag: 'mo', output: '\u2191', tex: 'uparrow', ttype: CONST },
{ input: 'darr', tag: 'mo', output: '\u2193', tex: 'downarrow', ttype: CONST },
{ input: 'rarr', tag: 'mo', output: '\u2192', tex: 'rightarrow', ttype: CONST },
{ input: '->', tag: 'mo', output: '\u2192', tex: 'to', ttype: CONST },
{ input: '>->', tag: 'mo', output: '\u21A3', tex: 'rightarrowtail', ttype: CONST },
{ input: '->>', tag: 'mo', output: '\u21A0', tex: 'twoheadrightarrow', ttype: CONST },
{ input: '>->>', tag: 'mo', output: '\u2916', tex: 'twoheadrightarrowtail', ttype: CONST },
{ input: '|->', tag: 'mo', output: '\u21A6', tex: 'mapsto', ttype: CONST },
{ input: 'larr', tag: 'mo', output: '\u2190', tex: 'leftarrow', ttype: CONST },
{ input: 'harr', tag: 'mo', output: '\u2194', tex: 'leftrightarrow', ttype: CONST },
{ input: 'rArr', tag: 'mo', output: '\u21D2', tex: 'Rightarrow', ttype: CONST },
{ input: 'lArr', tag: 'mo', output: '\u21D0', tex: 'Leftarrow', ttype: CONST },
{ input: 'hArr', tag: 'mo', output: '\u21D4', tex: 'Leftrightarrow', ttype: CONST },
// commands with argument
AMsqrt, AMroot, AMfrac, AMdiv, AMover, AMsub, AMsup,
{ input: 'cancel', tag: 'menclose', output: 'cancel', tex: null, ttype: UNARY },
{ input: 'Sqrt', tag: 'msqrt', output: 'sqrt', tex: null, ttype: UNARY },
{ input: 'hat', tag: 'mover', output: '\u005E', tex: null, ttype: UNARY, acc: true },
{ input: 'bar', tag: 'mover', output: '\u00AF', tex: 'overline', ttype: UNARY, acc: true },
{ input: 'vec', tag: 'mover', output: '\u2192', tex: null, ttype: UNARY, acc: true },
{ input: 'tilde', tag: 'mover', output: '~', tex: null, ttype: UNARY, acc: true },
{ input: 'dot', tag: 'mover', output: '.', tex: null, ttype: UNARY, acc: true },
{ input: 'ddot', tag: 'mover', output: '..', tex: null, ttype: UNARY, acc: true },
{ input: 'ul', tag: 'munder', output: '\u0332', tex: 'underline', ttype: UNARY, acc: true },
{ input: 'ubrace', tag: 'munder', output: '\u23DF', tex: 'underbrace', ttype: UNARY, acc: true },
{ input: 'obrace', tag: 'mover', output: '\u23DE', tex: 'overbrace', ttype: UNARY, acc: true },
AMtext, AMmbox, AMquote,
// {input:"var", tag:"mstyle", atname:"fontstyle", atval:"italic", output:"var", tex:null, ttype:UNARY},
{ input: 'color', tag: 'mstyle', ttype: BINARY },
{ input: 'bb', tag: 'mstyle', atname: 'mathvariant', atval: 'bold', output: 'bb', tex: 'mathbf', ttype: UNARY, notexcopy: true },
{ input: 'mathbf', tag: 'mstyle', atname: 'mathvariant', atval: 'bold', output: 'mathbf', tex: null, ttype: UNARY },
{ input: 'sf', tag: 'mstyle', atname: 'mathvariant', atval: 'sans-serif', output: 'sf', tex: 'mathsf', ttype: UNARY, notexcopy: true },
{ input: 'mathsf', tag: 'mstyle', atname: 'mathvariant', atval: 'sans-serif', output: 'mathsf', tex: null, ttype: UNARY },
{ input: 'bbb', tag: 'mstyle', atname: 'mathvariant', atval: 'double-struck', output: 'bbb', tex: 'mathbb', ttype: UNARY, notexcopy: true },
{ input: 'mathbb', tag: 'mstyle', atname: 'mathvariant', atval: 'double-struck', output: 'mathbb', tex: null, ttype: UNARY },
{ input: 'cc', tag: 'mstyle', atname: 'mathvariant', atval: 'script', output: 'cc', tex: 'mathcal', ttype: UNARY, notexcopy: true },
{ input: 'mathcal', tag: 'mstyle', atname: 'mathvariant', atval: 'script', output: 'mathcal', tex: null, ttype: UNARY },
{ input: 'tt', tag: 'mstyle', atname: 'mathvariant', atval: 'monospace', output: 'tt', tex: 'mathtt', ttype: UNARY, notexcopy: true },
{ input: 'mathtt', tag: 'mstyle', atname: 'mathvariant', atval: 'monospace', output: 'mathtt', tex: null, ttype: UNARY },
{ input: 'fr', tag: 'mstyle', atname: 'mathvariant', atval: 'fraktur', output: 'fr', tex: 'mathfrak', ttype: UNARY, notexcopy: true },
{ input: 'mathfrak', tag: 'mstyle', atname: 'mathvariant', atval: 'fraktur', output: 'mathfrak', tex: null, ttype: UNARY }
];
function compareNames(s1, s2) {
if (s1.input > s2.input) return 1;
else return -1;
}
const AMnames = []; // list of input symbols
function refreshSymbols() {
let i;
AMsymbols.sort(compareNames);
for (i=0; i<AMsymbols.length; i+=1) AMnames[i] = AMsymbols[i].input;
}
function AMinitSymbols() {
let i;
const symlen = AMsymbols.length;
for (i=0; i<symlen; i+=1) {
if (AMsymbols[i].tex && !(typeof AMsymbols[i].notexcopy == 'boolean' && AMsymbols[i].notexcopy)) {
AMsymbols.push({ input: AMsymbols[i].tex,
tag: AMsymbols[i].tag,
output: AMsymbols[i].output,
ttype: AMsymbols[i].ttype,
acc: (AMsymbols[i].acc||false) });
}
}
refreshSymbols();
}
// function newcommand(oldstr, newstr) {
// AMsymbols.push({ input: oldstr, tag: 'mo', output: newstr, tex: null, ttype: DEFINITION });
// refreshSymbols();
// }
// function newsymbol(symbolobj) {
// AMsymbols.push(symbolobj);
// refreshSymbols();
// }
function AMremoveCharsAndBlanks(str, n) {
// remove n characters and any following blanks
let st;
let i;
if (str.charAt(n)==='\\' && str.charAt(n+1)!=='\\' && str.charAt(n+1)!==' ') { st = str.slice(n+1); } else st = str.slice(n);
for (i=0; i<st.length && st.charCodeAt(i)<=32; i+=1);
return st.slice(i);
}
function AMposition(arr, str, n) {
// return position >=n where str appears or would be inserted
// assumes arr is sorted
let i;
if (n===0) {
let h;
let m;
n = -1;
h = arr.length;
while (n+1<h) {
// Substitute bitwise operator
if ((n+h)%2 !== 0) {
m = ((n+h)-1)/2;
} else {
m = (n+h)/2;
}
if (arr[m]<str) n = m; else h = m;
}
return h;
} else { for (i=n; i<arr.length && arr[i]<str; i+=1); }
return i; // i=arr.length || arr[i]>=str
}
function AMTremoveBrackets(node) {
let st;
if (node.charAt(0)==='{' && node.charAt(node.length-1)==='}') {
let leftchop = 0;
st = node.substr(1, 5);
if (st==='\\left') {
st = node.charAt(6);
if (st==='(' || st==='[' || st==='{') {
leftchop = 7;
} else {
st = node.substr(6, 7);
if (st==='\\lbrace') {
leftchop = 13;
}
}
} else {
st = node.charAt(1);
if (st==='(' || st==='[') {
leftchop = 2;
}
}
if (leftchop>0) {
// st = node.charAt(node.length-7);
st = node.substr(node.length-8);
if (st==='\\right)}' || st==='\\right]}' || st==='\\right.}') {
node = `{${node.substr(leftchop)}`;
node = `${node.substr(0, node.length-8)}}`;
} else if (st==='\\rbrace}') {
node = `{${node.substr(leftchop)}`;
node = `${node.substr(0, node.length-14)}}`;
}
}
}
return node;
}
/* Parsing ASCII math expressions with the following grammar
v ::= [A-Za-z] | greek letters | numbers | other constant symbols
u ::= sqrt | text | bb | other unary symbols for font commands
b ::= frac | root | stackrel binary symbols
l ::= ( | [ | { | (: | {: left brackets
r ::= ) | ] | } | :) | :} right brackets
S ::= v | lEr | uS | bSS Simple expression
I ::= S_S | S^S | S_S^S | S Intermediate expression
E ::= IE | I/I Expression
Each terminal symbol is translated into a corresponding mathml node.*/
let AMnestingDepth;
let AMpreviousSymbol;
let AMcurrentSymbol;
function AMTgetTeXsymbol(symb) {
let pre;
if (typeof symb.val == 'boolean' && symb.val) {
pre = '';
} else {
pre = '\\';
}
if (symb.tex==null) {
// can't remember why this was here. Breaks /delta /Delta to removed
// return (pre+(pre==''?symb.input:symb.input.toLowerCase()));
return (pre+symb.input);
} else {
return (pre+symb.tex);
}
}
function AMgetSymbol(str) {
// return maximal initial substring of str that appears in names
// return null if there is none
let k = 0; // new pos
let j = 0; // old pos
let mk; // match pos
let st;
let tagst;
let match = '';
let more = true;
for (let i=1; i<=str.length && more; i+=1) {
st = str.slice(0, i); // initial substring of length i
j = k;
k = AMposition(AMnames, st, j);
if (k<AMnames.length && str.slice(0, AMnames[k].length)===AMnames[k]) {
match = AMnames[k];
mk = k;
i = match.length;
}
more = k<AMnames.length && str.slice(0, AMnames[k].length)>=AMnames[k];
}
AMpreviousSymbol=AMcurrentSymbol;
if (match!=='') {
AMcurrentSymbol=AMsymbols[mk].ttype;
return AMsymbols[mk];
}
// if str[0] is a digit or - return maxsubstring of digits.digits
AMcurrentSymbol=CONST;
k = 1;
st = str.slice(0, 1);
let integ = true;
while (st>='0' && st<='9' && k<=str.length) {
st = str.slice(k, k+1);
k+=1;
}
if (st === config.decimalsign) {
st = str.slice(k, k+1);
if (st>='0' && st<='9') {
integ = false;
k+=1;
while (st>='0' && st<='9' && k<=str.length) {
st = str.slice(k, k+1);
k+=1;
}
}
}
if ((integ && k>1) || k>2) {
st = str.slice(0, k-1);
tagst = 'mn';
} else {
k = 2;
st = str.slice(0, 1); // take 1 character
tagst = ((st<'A' || st>'Z') && (st<'a' || st>'z')?'mo':'mi');
}
if (st==='-' && AMpreviousSymbol===INFIX) {
AMcurrentSymbol = INFIX;
return { input: st, tag: tagst, output: st, ttype: UNARY, func: true, val: true };
}
return { input: st, tag: tagst, output: st, ttype: CONST, val: true }; // added val bit
}
/* eslint no-use-before-define: ["error", { "functions": false }]*/
function AMTparseIexpr(str) {
let sym2;
let node;
let result;
str = AMremoveCharsAndBlanks(str, 0);
const sym1 = AMgetSymbol(str);
result = AMTparseSexpr(str);
node = result[0];
str = result[1];
const symbol = AMgetSymbol(str);
if (symbol.ttype === INFIX && symbol.input !== '/') {
str = AMremoveCharsAndBlanks(str, symbol.input.length);
// if (symbol.input == "/") result = AMTparseIexpr(str); else
result = AMTparseSexpr(str);
if (result[0] == null) { // show box in place of missing argument
result[0] = '{}';
} else result[0] = AMTremoveBrackets(result[0]);
str = result[1];
// if (symbol.input == "/") AMTremoveBrackets(node);
if (symbol.input === '_') {
sym2 = AMgetSymbol(str);
if (sym2.input === '^') {
str = AMremoveCharsAndBlanks(str, sym2.input.length);
const res2 = AMTparseSexpr(str);
res2[0] = AMTremoveBrackets(res2[0]);
str = res2[1];
node = `{${node}`;
node += `_{${result[0]}}`;
node += `^{${res2[0]}}`;
node += '}';
} else {
node += `_{${result[0]}}`;
}
} else { // must be ^
// node = '{'+node+'}^{'+result[0]+'}';
node = `${node}^{${result[0]}}`;
}
if (typeof sym1.func != 'undefined' && sym1.func) {
sym2 = AMgetSymbol(str);
if (sym2.ttype !== INFIX && sym2.ttype !== RIGHTBRACKET) {
result = AMTparseIexpr(str);
node = `{${node}${result[0]}}`;
str = result[1];
}
}
}
return [node, str];
}
function AMTparseExpr(str, rightbracket) {
let symbol;
let node;
let result;
let i;
// const nodeList = [];
let newFrag = '';
let addedright = false;
do {
str = AMremoveCharsAndBlanks(str, 0);
result = AMTparseIexpr(str);
node = result[0];
str = result[1];
symbol = AMgetSymbol(str);
if (symbol.ttype === INFIX && symbol.input === '/') {
str = AMremoveCharsAndBlanks(str, symbol.input.length);
result = AMTparseIexpr(str);
if (result[0] == null) { // show box in place of missing argument
result[0] = '{}';
} else result[0] = AMTremoveBrackets(result[0]);
str = result[1];
node = AMTremoveBrackets(node);
node = `${'\\frac{'}${node}}`;
node += `{${result[0]}}`;
newFrag += node;
symbol = AMgetSymbol(str);
} else if (node!==undefined) newFrag += node;
} while (((symbol.ttype !== RIGHTBRACKET &&
(symbol.ttype !== LEFTRIGHT || rightbracket))
|| AMnestingDepth === 0) && symbol!=null && symbol.output!=='');
if (symbol.ttype === RIGHTBRACKET || symbol.ttype === LEFTRIGHT) {
// if (AMnestingDepth > 0) AMnestingDepth--;
const len = newFrag.length;
if (len>2 && newFrag.charAt(0)==='{' && newFrag.indexOf(',')>0) { // could be matrix (total rewrite from .js)
const right = newFrag.charAt(len - 2);
if (right===')' || right===']') {
const left = newFrag.charAt(6);
if ((left==='(' && right===')' && symbol.output !== '}') || (left==='[' && right===']')) {
let mxout = '\\matrix{';
const pos = []; // position of commas
pos.push(0);
let matrix = true;
let mxnestingd = 0;
const subpos = [];
subpos[0] = [0];
let lastsubposstart = 0;
let mxanynestingd = 0;
for (i=1; i<len-1; i+=1) {
if (newFrag.charAt(i)===left) mxnestingd+=1;
if (newFrag.charAt(i)===right) {
mxnestingd-=1;
if (mxnestingd===0 && newFrag.charAt(i+2)===',' && newFrag.charAt(i+3)==='{') {
pos.push(i+2);
lastsubposstart = i+2;
subpos[lastsubposstart] = [i+2];
}
}
if (newFrag.charAt(i)==='[' || newFrag.charAt(i)==='(' || newFrag.charAt(i)==='{') { mxanynestingd+=1; }
if (newFrag.charAt(i)===']' || newFrag.charAt(i)===')' || newFrag.charAt(i)==='}') { mxanynestingd-=1; }
if (newFrag.charAt(i)===',' && mxanynestingd===1) {
subpos[lastsubposstart].push(i);
}
if (mxanynestingd<0) { // happens at the end of the row
if (lastsubposstart === i+1) { // if at end of row, skip to next row
i+=1;
} else { // misformed something - abandon treating as a matrix
matrix = false;
}
}
}
pos.push(len);
let lastmxsubcnt = -1;
if (mxnestingd===0 && pos.length>0 && matrix) {
for (i=0; i<pos.length-1; i+=1) {
let subarr;
if (i>0) mxout += '\\\\';
if (i===0) {
// var subarr = newFrag.substr(pos[i]+7,pos[i+1]-pos[i]-15).split(',');
if (subpos[pos[i]].length===1) {
subarr = [newFrag.substr(pos[i]+7, pos[i+1]-pos[i]-15)];
} else {
subarr = [newFrag.substring(pos[i]+7, subpos[pos[i]][1])];
for (let j=2; j<subpos[pos[i]].length; j+=1) {
subarr.push(newFrag.substring(subpos[pos[i]][j-1]+1, subpos[pos[i]][j]));
}
subarr.push(newFrag.substring(subpos[pos[i]][subpos[pos[i]].length-1]+1, pos[i+1]-8));
}
} else if (subpos[pos[i]].length===1) { // var subarr = newFrag.substr(pos[i]+8,pos[i+1]-pos[i]-16).split(',');
subarr = [newFrag.substr(pos[i]+8, pos[i+1]-pos[i]-16)];
} else {
subarr = [newFrag.substring(pos[i]+8, subpos[pos[i]][1])];
for (let j=2; j<subpos[pos[i]].length; j+=1) {
subarr.push(newFrag.substring(subpos[pos[i]][j-1]+1, subpos[pos[i]][j]));
}
subarr.push(newFrag.substring(subpos[pos[i]][subpos[pos[i]].length-1]+1, pos[i+1]-8));
}
if (lastmxsubcnt>0 && subarr.length!==lastmxsubcnt) {
matrix = false;
} else if (lastmxsubcnt===-1) {
lastmxsubcnt=subarr.length;
}
mxout += subarr.join('&');
}
}
mxout += '}';
if (matrix) { newFrag = mxout; }
}
}
}
str = AMremoveCharsAndBlanks(str, symbol.input.length);
if (typeof symbol.invisible != 'boolean' || !symbol.invisible) {
node = `\\right${AMTgetTeXsymbol(symbol)}`; // AMcreateMmlNode("mo",document.createTextNode(symbol.output));
newFrag += node;
addedright = true;
} else {
newFrag += '\\right.';
addedright = true;
}
}
if (AMnestingDepth>0 && !addedright) {
newFrag += '\\right.'; // adjust for non-matching left brackets
// todo: adjust for non-matching right brackets
}
return [newFrag, str];
}
function AMTparseSexpr(str) { // parses str and returns [node,tailstr]
let symbol;
let node;
let result;
let i;
let st; // rightvert = false,
let newFrag = '';
str = AMremoveCharsAndBlanks(str, 0);
symbol = AMgetSymbol(str); // either a token or a bracket or empty
if (symbol == null || (symbol.ttype === RIGHTBRACKET && AMnestingDepth > 0)) {
return [null, str];
}
if (symbol.ttype === DEFINITION) {
str = symbol.output+AMremoveCharsAndBlanks(str, symbol.input.length);
symbol = AMgetSymbol(str);
}
switch (symbol.ttype) {
case UNDEROVER:
case CONST: {
str = AMremoveCharsAndBlanks(str, symbol.input.length);
const texsymbol = AMTgetTeXsymbol(symbol);
if (texsymbol.charAt(0)==='\\' || symbol.tag==='mo') return [texsymbol, str];
else return [`{${texsymbol}}`, str];
}
case LEFTBRACKET: { // read (expr+)
AMnestingDepth+=1;
str = AMremoveCharsAndBlanks(str, symbol.input.length);
result = AMTparseExpr(str, true);
AMnestingDepth-=1;
let leftchop = 0;
if (result[0].substr(0, 6)==='\\right') {
st = result[0].charAt(6);
if (st===')' || st===']' || st==='}') {
leftchop = 6;
} else if (st==='.') {
leftchop = 7;
} else {
st = result[0].substr(6, 7);
if (st==='\\rbrace') {
leftchop = 13;
}
}
}
if (leftchop>0) {
result[0] = result[0].substr(leftchop);
if (typeof symbol.invisible == 'boolean' && symbol.invisible) { node = `{${result[0]}}`; } else {
node = `{${AMTgetTeXsymbol(symbol)}${result[0]}}`;
}
} else if (typeof symbol.invisible == 'boolean' && symbol.invisible) { node = `{\\left.${result[0]}}`; } else {
node = `{\\left${AMTgetTeXsymbol(symbol)}${result[0]}}`;
}
return [node, result[1]];
}
case TEXT:
if (symbol!==AMquote) str = AMremoveCharsAndBlanks(str, symbol.input.length);
if (str.charAt(0)==='{') i=str.indexOf('}');
else if (str.charAt(0)==='(') i=str.indexOf(')');
else if (str.charAt(0)==='[') i=str.indexOf(']');
else if (symbol===AMquote) i=str.slice(1).indexOf('"')+1;
else i = 0;
if (i===-1) i = str.length;
st = str.slice(1, i);
if (st.charAt(0) === ' ') {
newFrag = '\\ ';
}
newFrag += `\\text{${st}}`;
if (st.charAt(st.length-1) === ' ') {
newFrag += '\\ ';
}
str = AMremoveCharsAndBlanks(str, i+1);
return [newFrag, str];
case UNARY:
str = AMremoveCharsAndBlanks(str, symbol.input.length);
result = AMTparseSexpr(str);
if (result[0]==null) return [`{${AMTgetTeXsymbol(symbol)}}`, str];
if (typeof symbol.func == 'boolean' && symbol.func) { // functions hack
st = str.charAt(0);
if (st==='^' || st==='_' || st==='/' || st==='|' || st===','
|| (symbol.input.length===1 && symbol.input.match(/\w/) && st!=='(')) {
return [`{${AMTgetTeXsymbol(symbol)}}`, str];
} else {
node = `{${AMTgetTeXsymbol(symbol)}{${result[0]}}}`;
return [node, result[1]];
}
}
result[0] = AMTremoveBrackets(result[0]);
if (symbol.input === 'sqrt') { // sqrt
return [`\\sqrt{${result[0]}}`, result[1]];
} else if (symbol.input === 'cancel') { // cancel
return [`\\cancel{${result[0]}}`, result[1]];
} else if (typeof symbol.rewriteleftright != 'undefined') { // abs, floor, ceil
return [`{\\left${symbol.rewriteleftright[0]}${result[0]}\\right${symbol.rewriteleftright[1]}}`, result[1]];
} else if (typeof symbol.acc == 'boolean' && symbol.acc) { // accent
// return ['{'+AMTgetTeXsymbol(symbol)+'{'+result[0]+'}}',result[1]];
return [`${AMTgetTeXsymbol(symbol)}{${result[0]}}`, result[1]];
} else { // font change command
return [`{${AMTgetTeXsymbol(symbol)}{${result[0]}}}`, result[1]];
}
case BINARY: {
str = AMremoveCharsAndBlanks(str, symbol.input.length);
result = AMTparseSexpr(str);
if (result[0]==null) return [`{${AMTgetTeXsymbol(symbol)}}`, str];
result[0] = AMTremoveBrackets(result[0]);
const result2 = AMTparseSexpr(result[1]);
if (result2[0]==null) return [`{${AMTgetTeXsymbol(symbol)}}`, str];
result2[0] = AMTremoveBrackets(result2[0]);
if (symbol.input==='color') {
newFrag = `{\\color{${result[0].replace(/[{}]/g, '')}}${result2[0]}}`;
} else if (symbol.input==='root') {
newFrag = `{\\sqrt[${result[0]}]{${result2[0]}}}`;
} else {
newFrag = `{${AMTgetTeXsymbol(symbol)}{${result[0]}}{${result2[0]}}}`;
}
return [newFrag, result2[1]];
}
case INFIX:
str = AMremoveCharsAndBlanks(str, symbol.input.length);
return [symbol.output, str];
case SPACE:
str = AMremoveCharsAndBlanks(str, symbol.input.length);
return [`{\\quad\\text{${symbol.input}}\\quad}`, str];
case LEFTRIGHT:
// if (rightvert) return [null,str]; else rightvert = true;
AMnestingDepth+=1;
str = AMremoveCharsAndBlanks(str, symbol.input.length);
result = AMTparseExpr(str, false);
AMnestingDepth-=1;
st = '';
st = result[0].charAt(result[0].length -1);
// alert(result[0].lastChild+"***"+st);
if (st === '|') { // its an absolute value subterm
node = `{\\left|${result[0]}}`;
return [node, result[1]];
} else { // the "|" is a \mid
node = '{\\mid}';
return [node, str];
}
default:
// alert("default");
str = AMremoveCharsAndBlanks(str, symbol.input.length);
return [`{${AMTgetTeXsymbol(symbol)}}`, str];
}
}
function AMTparseAMtoTeX(str) {
AMnestingDepth = 0;
str = str.replace(/( |\u00a0| )/g, '');
str = str.replace(/>/g, '>');
str = str.replace(/</g, '<');
if (str.match(/\S/)==null) {
return '';
}
return AMTparseExpr(str.replace(/^\s+/g, ''), false)[0];
}
function AMparseMath(str) {
// DLMOD to remove , which editor adds on multiple spaces
str = str.replace(/( |\u00a0| )/g, '');
str = str.replace(/>/g, '>');
str = str.replace(/</g, '<');
if (str.match(/\S/)==null) {
return document.createTextNode(' ');
}
let texstring = AMTparseAMtoTeX(str);
let mathbg;
if (typeof mathbg !== 'undefined' && mathbg==='dark') {
texstring = `\\reverse ${texstring}`;
}
if (config.mathcolor!=='') {
texstring = `\\${config.mathcolor}${texstring}`;
}
if (config.displaystyle) {
texstring = `\\displaystyle${texstring}`;
} else {
texstring = `\\textstyle${texstring}`;
}
texstring = texstring.replace('$', '\\$');
const node = document.createElement('img');
if (typeof encodeURIComponent == 'function') {
texstring = encodeURIComponent(texstring);
} else {
texstring = escape(texstring);
}
node.src = `${AMTcgiloc}?${texstring}`;
node.style.verticalAlign = 'middle';
if (config.showasciiformulaonhover) { // fixed by djhsu so newline
node.setAttribute('title', str.replace(/\s+/g, ' '));
}// does not show in Gecko
const snode = document.createElement('span');
snode.appendChild(node); // chg
return snode;
}
// alias to align with wFallback function
function AMTparseMath(str) {
return AMparseMath(str);
}
function AMstrarr2docFrag(arr, linebreaks) {
const newFrag=document.createDocumentFragment();
let expr = false;
for (let i=0; i<arr.length; i+=1) {
if (expr) newFrag.appendChild(AMparseMath(arr[i]));
else {
const arri = (linebreaks ? arr[i].split('\n\n') : [arr[i]]);
newFrag.appendChild(document.createElement('span')
.appendChild(document.createTextNode(arri[0])));
for (let j=1; j<arri.length; j+=1) {
newFrag.appendChild(document.createElement('p'));
newFrag.appendChild(document.createElement('span')
.appendChild(document.createTextNode(arri[j])));
}
}
expr = !expr;
}
return newFrag;
}
function AMprocessNodeR(n, linebreaks) {
let mtch;
let str;
let arr;
let frg;
let i;
if (n.childNodes.length === 0) {
if ((n.nodeType!==8 || linebreaks) &&
n.parentNode.nodeName!=='form' && n.parentNode.nodeName!=='FORM' &&
n.parentNode.nodeName!=='textarea' && n.parentNode.nodeName!=='TEXTAREA' &&
n.parentNode.nodeName!=='pre' && n.parentNode.nodeName!=='PRE') {
str = n.nodeValue;
if (!(str === null)) {
str = str.replace(/\r\n\r\n/g, '\n\n');
if (config.doubleblankmathdelimiter) {
str = str.replace(/\x20\x20\./g, ` ${config.AMdelimiter1}.`);
str = str.replace(/\x20\x20,/g, ` ${config.AMdelimiter1},`);
str = str.replace(/\x20\x20/g, ` ${config.AMdelimiter1} `);
}
str = str.replace(/\x20+/g, ' ');
str = str.replace(/\s*\r\n/g, ' ');
mtch = false;
if (config.AMusedelimiter2) {
str = str.replace(new RegExp(config.AMescape2, 'g'),
(st) => { mtch=true; return 'AMescape2'; });
}
str = str.replace(new RegExp(config.AMescape1, 'g'),
(st) => { mtch=true; return 'AMescape1'; });
if (config.AMusedelimiter2) str = str.replace(new RegExp(config.AMdelimiter2regexp, 'g'), config.AMdelimiter1);
arr = str.split(config.AMdelimiter1);
for (i=0; i<arr.length; i+=1) {
if (config.AMusedelimiter2) {
arr[i]=arr[i].replace(/AMescape2/g, config.AMdelimiter2).replace(/AMescape1/g, config.AMdelimiter1);
} else {
arr[i]=arr[i].replace(/AMescape1/g, config.AMdelimiter1);
}
}
if (arr.length>1 || mtch) {
frg = AMstrarr2docFrag(arr, n.nodeType===8);
const len = frg.childNodes.length;
n.parentNode.replaceChild(frg, n);
return len-1;
}
}
} else return 0;
} else if (n.nodeName!=='math') { // should this change to img?
for (i=0; i<n.childNodes.length; i+=1) { i += AMprocessNodeR(n.childNodes[i], linebreaks); }
}
return 0;
}
function AMprocessNode(n, linebreaks, spanclassAM) {
let frag;
let st;
if (spanclassAM!=null) {
frag = document.getElementsByTagName('span');
for (let i=0; i<frag.length; i+=1) {
if (frag[i].className === 'AM') { AMprocessNodeR(frag[i], linebreaks); }
}
} else {
try {
st = n.innerHTML;
} catch (err) { /* empty */ }
if (st==null ||
st.indexOf(config.AMdelimiter1)!==-1) { AMprocessNodeR(n, linebreaks); }// || st.indexOf(config.AMdelimiter2)!=-1)
}
}
// let AMbody;
// let AMtranslated = false;
// const AMnoMathML = true;
// function translate(spanclassAM) {
// if (!AMtranslated) { // run this only once
// AMtranslated = true;
// const body = document.getElementsByTagName('body')[0];
// const processN = document.getElementById(config.AMdocumentId);
// AMprocessNode((processN!=null?processN:body), false, spanclassAM);
// }
// }
AMinitSymbols();
// function generic() {
// if (config.translateOnLoad) {
// translate();
// }
// }
// // setup onload function
// if (typeof window.addEventListener != 'undefined') {
// // .. gecko, safari, konqueror and standard
// window.addEventListener('load', generic, false);
// } else if (typeof document.addEventListener != 'undefined') {
// // .. opera 7
// document.addEventListener('load', generic, false);
// } else if (typeof window.attachEvent != 'undefined') {
// // .. win/ie
// window.attachEvent('onload', generic);
// } else if (typeof window.onload == 'function') {
// // .. mac/ie5 and anything else that gets this far
// // if there's an existing onload function
// // store it
// const existing = onload;
// // add new onload handler
// window.onload = function() {
// // call existing onload function
// existing();
// // call generic onload function
// generic();
// };
// } else {
// window.onload = generic;
// }
export default {
// translate,
AMTconfig: config,
AMprocessNode,
AMparseMath,
AMTparseMath,
AMTparseAMtoTeX
};