mirror of
https://git.mirrors.martin98.com/https://github.com/google/draco
synced 2025-04-19 12:19:53 +08:00
1629 lines
58 KiB
JavaScript
1629 lines
58 KiB
JavaScript
/*
|
|
ASCIIMathML.js
|
|
==============
|
|
This file contains JavaScript functions to convert ASCII math notation
|
|
and (some) LaTeX to Presentation MathML. The conversion is done while the
|
|
HTML page loads, and should work with Firefox and other browsers that can
|
|
render MathML.
|
|
|
|
Just add the next line to your HTML page with this file in the same folder:
|
|
|
|
<script type="text/javascript" src="ASCIIMathML.js"></script>
|
|
|
|
Version 2.2 Mar 3, 2014.
|
|
Latest version at https://github.com/mathjax/asciimathml
|
|
If you use it on a webpage, please send the URL to jipsen@chapman.edu
|
|
|
|
Copyright (c) 2014 Peter Jipsen and other ASCIIMathML.js contributors
|
|
|
|
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.
|
|
*/
|
|
var asciimath = {};
|
|
|
|
(function() {
|
|
var mathcolor = 'blue'; // change it to "" (to inherit) or another color
|
|
var mathfontsize = '1em'; // change to e.g. 1.2em for larger math
|
|
var mathfontfamily = 'serif'; // change to "" to inherit (works in IE)
|
|
// or another family (e.g. "arial")
|
|
var automathrecognize = false; // writing "amath" on page makes this true
|
|
var checkForMathML = true; // check if browser can display MathML
|
|
var notifyIfNoMathML = true; // display note at top if no MathML capability
|
|
var alertIfNoMathML = false; // show alert box if no MathML capability
|
|
var translateOnLoad = true; // set to false to do call translators from js
|
|
var translateASCIIMath = true; // false to preserve `..`
|
|
var displaystyle = true; // puts limits above and below large operators
|
|
var showasciiformulaonhover = true; // helps students learn ASCIIMath
|
|
var decimalsign = '.'; // change to "," if you like, beware of `(1,2)`!
|
|
var AMdelimiter1 = '`', AMescape1 = '\\\\`'; // can use other characters
|
|
var AMdocumentId = 'wikitext' // PmWiki element containing math (default=body)
|
|
var fixphi = true; // false to return to legacy phi/varphi mapping
|
|
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
|
|
var isIE = (navigator.appName.slice(0, 9) == 'Microsoft');
|
|
var noMathML = false, translated = false;
|
|
|
|
if (isIE) { // add MathPlayer info to IE webpages
|
|
document.write('<object id="mathplayer"\
|
|
classid="clsid:32F66A20-7614-11D4-BD11-00104BD3F987"></object>');
|
|
document.write('<?import namespace="m" implementation="#mathplayer"?>');
|
|
}
|
|
|
|
// Add a stylesheet, replacing any previous custom stylesheet (adapted from TW)
|
|
function setStylesheet(s) {
|
|
var id = 'AMMLcustomStyleSheet';
|
|
var n = document.getElementById(id);
|
|
if (document.createStyleSheet) {
|
|
// Test for IE's non-standard createStyleSheet method
|
|
if (n) n.parentNode.removeChild(n);
|
|
// This failed without the
|
|
document.getElementsByTagName('head')[0].insertAdjacentHTML(
|
|
'beforeEnd', ' <style id=\'' + id + '\'>' + s + '</style>');
|
|
} else {
|
|
if (n) {
|
|
n.replaceChild(document.createTextNode(s), n.firstChild);
|
|
} else {
|
|
n = document.createElement('style');
|
|
n.type = 'text/css';
|
|
n.id = id;
|
|
n.appendChild(document.createTextNode(s));
|
|
document.getElementsByTagName('head')[0].appendChild(n);
|
|
}
|
|
}
|
|
}
|
|
|
|
setStylesheet(
|
|
'#AMMLcloseDiv \{font-size:0.8em; padding-top:1em; color:#014\}\n#AMMLwarningBox \{position:absolute; width:100%; top:0; left:0; z-index:200; text-align:center; font-size:1em; font-weight:bold; padding:0.5em 0 0.5em 0; color:#ffc; background:#c30\}');
|
|
|
|
function init() {
|
|
var msg, warnings = new Array();
|
|
if (document.getElementById == null) {
|
|
alert('This webpage requires a recent browser such as Mozilla Firefox');
|
|
return null;
|
|
}
|
|
if (checkForMathML && (msg = checkMathML())) warnings.push(msg);
|
|
if (warnings.length > 0) displayWarnings(warnings);
|
|
if (!noMathML) initSymbols();
|
|
return true;
|
|
}
|
|
|
|
function checkMathML() {
|
|
if (navigator.appName.slice(0, 8) == 'Netscape')
|
|
if (navigator.appVersion.slice(0, 1) >= '5')
|
|
noMathML = null;
|
|
else
|
|
noMathML = true;
|
|
else if (navigator.appName.slice(0, 9) == 'Microsoft')
|
|
try {
|
|
var ActiveX = new ActiveXObject('MathPlayer.Factory.1');
|
|
noMathML = null;
|
|
} catch (e) {
|
|
noMathML = true;
|
|
}
|
|
else if (navigator.appName.slice(0, 5) == 'Opera')
|
|
if (navigator.appVersion.slice(0, 3) >= '9.5')
|
|
noMathML = null;
|
|
else
|
|
noMathML = true;
|
|
// noMathML = true; //uncomment to check
|
|
if (noMathML && notifyIfNoMathML) {
|
|
var msg =
|
|
'To view the ASCIIMathML notation use Internet Explorer + MathPlayer or Mozilla Firefox 2.0 or later.';
|
|
if (alertIfNoMathML)
|
|
alert(msg);
|
|
else
|
|
return msg;
|
|
}
|
|
}
|
|
|
|
function hideWarning() {
|
|
var body = document.getElementsByTagName('body')[0];
|
|
body.removeChild(document.getElementById('AMMLwarningBox'));
|
|
body.onclick = null;
|
|
}
|
|
|
|
function displayWarnings(warnings) {
|
|
var i, frag, nd = createElementXHTML('div');
|
|
var body = document.getElementsByTagName('body')[0];
|
|
body.onclick = hideWarning;
|
|
nd.id = 'AMMLwarningBox';
|
|
for (i = 0; i < warnings.length; i++) {
|
|
frag = createElementXHTML('div');
|
|
frag.appendChild(document.createTextNode(warnings[i]));
|
|
frag.style.paddingBottom = '1.0em';
|
|
nd.appendChild(frag);
|
|
}
|
|
nd.appendChild(createElementXHTML('p'));
|
|
nd.appendChild(document.createTextNode('For instructions see the '));
|
|
var an = createElementXHTML('a');
|
|
an.appendChild(document.createTextNode('ASCIIMathML'));
|
|
an.setAttribute('href', 'http://www.chapman.edu/~jipsen/asciimath.html');
|
|
nd.appendChild(an);
|
|
nd.appendChild(document.createTextNode(' homepage'));
|
|
an = createElementXHTML('div');
|
|
an.id = 'AMMLcloseDiv';
|
|
an.appendChild(
|
|
document.createTextNode('(click anywhere to close this warning)'));
|
|
nd.appendChild(an);
|
|
var body = document.getElementsByTagName('body')[0];
|
|
body.insertBefore(nd, body.childNodes[0]);
|
|
}
|
|
|
|
function translate(spanclassAM) {
|
|
if (!translated) { // run this only once
|
|
translated = true;
|
|
var body = document.getElementsByTagName('body')[0];
|
|
var processN = document.getElementById(AMdocumentId);
|
|
if (translateASCIIMath)
|
|
AMprocessNode((processN != null ? processN : body), false, spanclassAM);
|
|
}
|
|
}
|
|
|
|
function createElementXHTML(t) {
|
|
if (isIE)
|
|
return document.createElement(t);
|
|
else
|
|
return document.createElementNS('http://www.w3.org/1999/xhtml', t);
|
|
}
|
|
|
|
var AMmathml = 'http://www.w3.org/1998/Math/MathML';
|
|
|
|
function AMcreateElementMathML(t) {
|
|
if (isIE)
|
|
return document.createElement('m:' + t);
|
|
else
|
|
return document.createElementNS(AMmathml, t);
|
|
}
|
|
|
|
function createMmlNode(t, frag) {
|
|
var node;
|
|
if (isIE)
|
|
node = document.createElement('m:' + t);
|
|
else
|
|
node = document.createElementNS(AMmathml, t);
|
|
if (frag) node.appendChild(frag);
|
|
return node;
|
|
}
|
|
|
|
function newcommand(oldstr, newstr) {
|
|
AMsymbols.push(
|
|
{input: oldstr, tag: 'mo', output: newstr, tex: null, ttype: DEFINITION});
|
|
refreshSymbols();
|
|
}
|
|
|
|
function newsymbol(symbolobj) {
|
|
AMsymbols.push(symbolobj);
|
|
refreshSymbols();
|
|
}
|
|
|
|
// character lists for Mozilla/Netscape fonts
|
|
var AMcal = [
|
|
'\uD835\uDC9C', '\u212C', '\uD835\uDC9E', '\uD835\uDC9F',
|
|
'\u2130', '\u2131', '\uD835\uDCA2', '\u210B',
|
|
'\u2110', '\uD835\uDCA5', '\uD835\uDCA6', '\u2112',
|
|
'\u2133', '\uD835\uDCA9', '\uD835\uDCAA', '\uD835\uDCAB',
|
|
'\uD835\uDCAC', '\u211B', '\uD835\uDCAE', '\uD835\uDCAF',
|
|
'\uD835\uDCB0', '\uD835\uDCB1', '\uD835\uDCB2', '\uD835\uDCB3',
|
|
'\uD835\uDCB4', '\uD835\uDCB5', '\uD835\uDCB6', '\uD835\uDCB7',
|
|
'\uD835\uDCB8', '\uD835\uDCB9', '\u212F', '\uD835\uDCBB',
|
|
'\u210A', '\uD835\uDCBD', '\uD835\uDCBE', '\uD835\uDCBF',
|
|
'\uD835\uDCC0', '\uD835\uDCC1', '\uD835\uDCC2', '\uD835\uDCC3',
|
|
'\u2134', '\uD835\uDCC5', '\uD835\uDCC6', '\uD835\uDCC7',
|
|
'\uD835\uDCC8', '\uD835\uDCC9', '\uD835\uDCCA', '\uD835\uDCCB',
|
|
'\uD835\uDCCC', '\uD835\uDCCD', '\uD835\uDCCE', '\uD835\uDCCF'
|
|
];
|
|
|
|
var AMfrk = [
|
|
'\uD835\uDD04', '\uD835\uDD05', '\u212D', '\uD835\uDD07',
|
|
'\uD835\uDD08', '\uD835\uDD09', '\uD835\uDD0A', '\u210C',
|
|
'\u2111', '\uD835\uDD0D', '\uD835\uDD0E', '\uD835\uDD0F',
|
|
'\uD835\uDD10', '\uD835\uDD11', '\uD835\uDD12', '\uD835\uDD13',
|
|
'\uD835\uDD14', '\u211C', '\uD835\uDD16', '\uD835\uDD17',
|
|
'\uD835\uDD18', '\uD835\uDD19', '\uD835\uDD1A', '\uD835\uDD1B',
|
|
'\uD835\uDD1C', '\u2128', '\uD835\uDD1E', '\uD835\uDD1F',
|
|
'\uD835\uDD20', '\uD835\uDD21', '\uD835\uDD22', '\uD835\uDD23',
|
|
'\uD835\uDD24', '\uD835\uDD25', '\uD835\uDD26', '\uD835\uDD27',
|
|
'\uD835\uDD28', '\uD835\uDD29', '\uD835\uDD2A', '\uD835\uDD2B',
|
|
'\uD835\uDD2C', '\uD835\uDD2D', '\uD835\uDD2E', '\uD835\uDD2F',
|
|
'\uD835\uDD30', '\uD835\uDD31', '\uD835\uDD32', '\uD835\uDD33',
|
|
'\uD835\uDD34', '\uD835\uDD35', '\uD835\uDD36', '\uD835\uDD37'
|
|
];
|
|
|
|
var AMbbb = [
|
|
'\uD835\uDD38', '\uD835\uDD39', '\u2102', '\uD835\uDD3B',
|
|
'\uD835\uDD3C', '\uD835\uDD3D', '\uD835\uDD3E', '\u210D',
|
|
'\uD835\uDD40', '\uD835\uDD41', '\uD835\uDD42', '\uD835\uDD43',
|
|
'\uD835\uDD44', '\u2115', '\uD835\uDD46', '\u2119',
|
|
'\u211A', '\u211D', '\uD835\uDD4A', '\uD835\uDD4B',
|
|
'\uD835\uDD4C', '\uD835\uDD4D', '\uD835\uDD4E', '\uD835\uDD4F',
|
|
'\uD835\uDD50', '\u2124', '\uD835\uDD52', '\uD835\uDD53',
|
|
'\uD835\uDD54', '\uD835\uDD55', '\uD835\uDD56', '\uD835\uDD57',
|
|
'\uD835\uDD58', '\uD835\uDD59', '\uD835\uDD5A', '\uD835\uDD5B',
|
|
'\uD835\uDD5C', '\uD835\uDD5D', '\uD835\uDD5E', '\uD835\uDD5F',
|
|
'\uD835\uDD60', '\uD835\uDD61', '\uD835\uDD62', '\uD835\uDD63',
|
|
'\uD835\uDD64', '\uD835\uDD65', '\uD835\uDD66', '\uD835\uDD67',
|
|
'\uD835\uDD68', '\uD835\uDD69', '\uD835\uDD6A', '\uD835\uDD6B'
|
|
];
|
|
/*var AMcal =
|
|
[0xEF35,0x212C,0xEF36,0xEF37,0x2130,0x2131,0xEF38,0x210B,0x2110,0xEF39,0xEF3A,0x2112,0x2133,0xEF3B,0xEF3C,0xEF3D,0xEF3E,0x211B,0xEF3F,0xEF40,0xEF41,0xEF42,0xEF43,0xEF44,0xEF45,0xEF46];
|
|
var AMfrk =
|
|
[0xEF5D,0xEF5E,0x212D,0xEF5F,0xEF60,0xEF61,0xEF62,0x210C,0x2111,0xEF63,0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0x211C,0xEF6B,0xEF6C,0xEF6D,0xEF6E,0xEF6F,0xEF70,0xEF71,0x2128];
|
|
var AMbbb =
|
|
[0xEF8C,0xEF8D,0x2102,0xEF8E,0xEF8F,0xEF90,0xEF91,0x210D,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0x2115,0xEF97,0x2119,0x211A,0x211D,0xEF98,0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0x2124];*/
|
|
|
|
var CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4,
|
|
RIGHTBRACKET = 5, SPACE = 6, UNDEROVER = 7, DEFINITION = 8, LEFTRIGHT = 9,
|
|
TEXT = 10, BIG = 11, LONG = 12, STRETCHY = 13, MATRIX = 14,
|
|
UNARYUNDEROVER = 15; // token types
|
|
|
|
var AMquote =
|
|
{input: '"', tag: 'mtext', output: 'mbox', tex: null, ttype: TEXT};
|
|
|
|
var 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: '\u03BB', tex: null, ttype: CONST},
|
|
{input: 'Lamda', tag: 'mo', output: '\u039B', tex: null, ttype: CONST},
|
|
{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: fixphi ? '\u03D5' : '\u03C6',
|
|
tex: null,
|
|
ttype: CONST
|
|
},
|
|
{
|
|
input: 'varphi',
|
|
tag: 'mi',
|
|
output: fixphi ? '\u03C6' : '\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:"\u0096", tex:null, ttype:CONST},
|
|
{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: null, ttype: CONST},
|
|
{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},
|
|
|
|
// 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: '<=', tag: 'mo', output: '\u2264', tex: 'le', ttype: CONST},
|
|
{input: 'lt=', tag: 'mo', output: '\u2264', tex: 'leq', ttype: CONST},
|
|
{input: 'gt', tag: 'mo', output: '>', tex: null, ttype: CONST},
|
|
{input: '>=', tag: 'mo', output: '\u2265', tex: 'ge', ttype: CONST},
|
|
{input: 'gt=', tag: 'mo', output: '\u2265', tex: 'geq', 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: 'cong', ttype: CONST},
|
|
{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: 'implies', ttype: CONST},
|
|
{input: 'if', tag: 'mo', output: 'if', tex: null, ttype: SPACE},
|
|
{input: '<=>', tag: 'mo', output: '\u21D4', tex: 'iff', ttype: CONST},
|
|
{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},
|
|
|
|
// grouping brackets
|
|
{input: '(', tag: 'mo', output: '(', tex: null, ttype: LEFTBRACKET},
|
|
{input: ')', tag: 'mo', output: ')', tex: null, ttype: RIGHTBRACKET},
|
|
{input: '[', tag: 'mo', output: '[', tex: null, ttype: LEFTBRACKET},
|
|
{input: ']', tag: 'mo', output: ']', tex: null, ttype: RIGHTBRACKET},
|
|
{input: '{', tag: 'mo', output: '{', tex: null, ttype: LEFTBRACKET},
|
|
{input: '}', tag: 'mo', output: '}', tex: null, ttype: RIGHTBRACKET},
|
|
{input: '|', tag: 'mo', output: '|', tex: null, ttype: LEFTRIGHT},
|
|
//{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: null, ttype: LEFTBRACKET},
|
|
{input: '>>', tag: 'mo', output: '\u232A', tex: null, 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: '\u2235', tex: 'because', ttype: CONST},
|
|
{input: '/_', tag: 'mo', output: '\u2220', tex: 'angle', ttype: CONST},
|
|
{input: '/_\\', tag: 'mo', output: '\u25B3', tex: 'triangle', ttype: CONST},
|
|
{input: '\'', tag: 'mo', output: '\u2032', tex: 'prime', ttype: CONST},
|
|
{
|
|
input: 'tilde',
|
|
tag: 'mover',
|
|
output: '~',
|
|
tex: null,
|
|
ttype: UNARY,
|
|
acc: true
|
|
},
|
|
{input: '\\ ', tag: 'mo', output: '\u00A0', tex: null, ttype: CONST},
|
|
{input: 'frown', tag: 'mo', output: '\u2322', tex: null, ttype: CONST},
|
|
{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: null, 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: 'lceiling', ttype: CONST},
|
|
{input: '~|', tag: 'mo', output: '\u2309', tex: 'rceiling', ttype: CONST},
|
|
{input: 'CC', tag: 'mo', output: '\u2102', tex: null, ttype: CONST},
|
|
{input: 'NN', tag: 'mo', output: '\u2115', tex: null, ttype: CONST},
|
|
{input: 'QQ', tag: 'mo', output: '\u211A', tex: null, ttype: CONST},
|
|
{input: 'RR', tag: 'mo', output: '\u211D', tex: null, ttype: CONST},
|
|
{input: 'ZZ', tag: 'mo', output: '\u2124', tex: null, ttype: CONST},
|
|
{input: 'f', tag: 'mi', output: 'f', tex: null, ttype: UNARY, func: true},
|
|
{input: 'g', tag: 'mi', output: 'g', tex: null, ttype: UNARY, func: 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: '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: 'sec', tag: 'mo', output: 'sec', tex: null, ttype: UNARY, func: true},
|
|
{input: 'csc', tag: 'mo', output: 'csc', 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: '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: 'exp', tag: 'mo', output: 'exp', tex: null, ttype: UNARY, func: true},
|
|
{
|
|
input: 'abs',
|
|
tag: 'mo',
|
|
output: 'abs',
|
|
tex: null,
|
|
ttype: UNARY,
|
|
rewriteleftright: ['|', '|']
|
|
},
|
|
{
|
|
input: 'norm',
|
|
tag: 'mo',
|
|
output: 'norm',
|
|
tex: null,
|
|
ttype: UNARY,
|
|
rewriteleftright: ['\u2225', '\u2225']
|
|
},
|
|
{
|
|
input: 'floor',
|
|
tag: 'mo',
|
|
output: 'floor',
|
|
tex: null,
|
|
ttype: UNARY,
|
|
rewriteleftright: ['\u230A', '\u230B']
|
|
},
|
|
{
|
|
input: 'ceil',
|
|
tag: 'mo',
|
|
output: 'ceil',
|
|
tex: null,
|
|
ttype: UNARY,
|
|
rewriteleftright: ['\u2308', '\u2309']
|
|
},
|
|
{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: 'det', tag: 'mo', output: 'det', tex: null, ttype: UNARY, func: true},
|
|
{input: 'dim', tag: 'mo', output: 'dim', tex: null, ttype: CONST},
|
|
{input: 'mod', tag: 'mo', output: 'mod', tex: null, ttype: CONST},
|
|
{input: 'gcd', tag: 'mo', output: 'gcd', tex: null, ttype: UNARY, func: true},
|
|
{input: 'lcm', tag: 'mo', output: 'lcm', tex: null, ttype: UNARY, func: 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
|
|
{input: 'sqrt', tag: 'msqrt', output: 'sqrt', tex: null, ttype: UNARY},
|
|
{input: 'root', tag: 'mroot', output: 'root', tex: null, ttype: BINARY},
|
|
{input: 'frac', tag: 'mfrac', output: '/', tex: null, ttype: BINARY},
|
|
{input: '/', tag: 'mfrac', output: '/', tex: null, ttype: INFIX},
|
|
{
|
|
input: 'stackrel',
|
|
tag: 'mover',
|
|
output: 'stackrel',
|
|
tex: null,
|
|
ttype: BINARY
|
|
},
|
|
{
|
|
input: 'overset',
|
|
tag: 'mover',
|
|
output: 'stackrel',
|
|
tex: null,
|
|
ttype: BINARY
|
|
},
|
|
{
|
|
input: 'underset',
|
|
tag: 'munder',
|
|
output: 'stackrel',
|
|
tex: null,
|
|
ttype: BINARY
|
|
},
|
|
{input: '_', tag: 'msub', output: '_', tex: null, ttype: INFIX},
|
|
{input: '^', tag: 'msup', output: '^', tex: null, ttype: INFIX},
|
|
{
|
|
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: '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: UNARYUNDEROVER,
|
|
acc: true
|
|
},
|
|
{
|
|
input: 'obrace',
|
|
tag: 'mover',
|
|
output: '\u23DE',
|
|
tex: 'overbrace',
|
|
ttype: UNARYUNDEROVER,
|
|
acc: true
|
|
},
|
|
{input: 'text', tag: 'mtext', output: 'text', tex: null, ttype: TEXT},
|
|
{input: 'mbox', tag: 'mtext', output: 'mbox', tex: null, ttype: TEXT},
|
|
{input: 'color', tag: 'mstyle', ttype: BINARY},
|
|
{input: 'cancel', tag: 'menclose', output: 'cancel', tex: null, ttype: UNARY},
|
|
AMquote,
|
|
{
|
|
input: 'bb',
|
|
tag: 'mstyle',
|
|
atname: 'mathvariant',
|
|
atval: 'bold',
|
|
output: 'bb',
|
|
tex: null,
|
|
ttype: UNARY
|
|
},
|
|
{
|
|
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: null,
|
|
ttype: UNARY
|
|
},
|
|
{
|
|
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: null,
|
|
ttype: UNARY,
|
|
codes: AMbbb
|
|
},
|
|
{
|
|
input: 'mathbb',
|
|
tag: 'mstyle',
|
|
atname: 'mathvariant',
|
|
atval: 'double-struck',
|
|
output: 'mathbb',
|
|
tex: null,
|
|
ttype: UNARY,
|
|
codes: AMbbb
|
|
},
|
|
{
|
|
input: 'cc',
|
|
tag: 'mstyle',
|
|
atname: 'mathvariant',
|
|
atval: 'script',
|
|
output: 'cc',
|
|
tex: null,
|
|
ttype: UNARY,
|
|
codes: AMcal
|
|
},
|
|
{
|
|
input: 'mathcal',
|
|
tag: 'mstyle',
|
|
atname: 'mathvariant',
|
|
atval: 'script',
|
|
output: 'mathcal',
|
|
tex: null,
|
|
ttype: UNARY,
|
|
codes: AMcal
|
|
},
|
|
{
|
|
input: 'tt',
|
|
tag: 'mstyle',
|
|
atname: 'mathvariant',
|
|
atval: 'monospace',
|
|
output: 'tt',
|
|
tex: null,
|
|
ttype: UNARY
|
|
},
|
|
{
|
|
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: null,
|
|
ttype: UNARY,
|
|
codes: AMfrk
|
|
},
|
|
{
|
|
input: 'mathfrak',
|
|
tag: 'mstyle',
|
|
atname: 'mathvariant',
|
|
atval: 'fraktur',
|
|
output: 'mathfrak',
|
|
tex: null,
|
|
ttype: UNARY,
|
|
codes: AMfrk
|
|
}
|
|
];
|
|
|
|
function compareNames(s1, s2) {
|
|
if (s1.input > s2.input)
|
|
return 1
|
|
else return -1;
|
|
}
|
|
|
|
var AMnames = []; // list of input symbols
|
|
|
|
function initSymbols() {
|
|
var i;
|
|
var symlen = AMsymbols.length;
|
|
for (i = 0; i < symlen; i++) {
|
|
if (AMsymbols[i].tex) {
|
|
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 refreshSymbols() {
|
|
var i;
|
|
AMsymbols.sort(compareNames);
|
|
for (i = 0; i < AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input;
|
|
}
|
|
|
|
function define(oldstr, newstr) {
|
|
AMsymbols.push(
|
|
{input: oldstr, tag: 'mo', output: newstr, tex: null, ttype: DEFINITION});
|
|
refreshSymbols(); // this may be a problem if many symbols are defined!
|
|
}
|
|
|
|
function AMremoveCharsAndBlanks(str, n) {
|
|
// remove n characters and any following blanks
|
|
var st;
|
|
if (str.charAt(n) == '\\' && str.charAt(n + 1) != '\\' &&
|
|
str.charAt(n + 1) != ' ')
|
|
st = str.slice(n + 1);
|
|
else
|
|
st = str.slice(n);
|
|
for (var i = 0; i < st.length && st.charCodeAt(i) <= 32; i = i + 1)
|
|
;
|
|
return st.slice(i);
|
|
}
|
|
|
|
function position(arr, str, n) {
|
|
// return position >=n where str appears or would be inserted
|
|
// assumes arr is sorted
|
|
if (n == 0) {
|
|
var h, m;
|
|
n = -1;
|
|
h = arr.length;
|
|
while (n + 1 < h) {
|
|
m = (n + h) >> 1;
|
|
if (arr[m] < str)
|
|
n = m;
|
|
else
|
|
h = m;
|
|
}
|
|
return h;
|
|
} else
|
|
for (var i = n; i < arr.length && arr[i] < str; i++)
|
|
;
|
|
return i; // i=arr.length || arr[i]>=str
|
|
}
|
|
|
|
function AMgetSymbol(str) {
|
|
// return maximal initial substring of str that appears in names
|
|
// return null if there is none
|
|
var k = 0; // new pos
|
|
var j = 0; // old pos
|
|
var mk; // match pos
|
|
var st;
|
|
var tagst;
|
|
var match = '';
|
|
var more = true;
|
|
for (var i = 1; i <= str.length && more; i++) {
|
|
st = str.slice(0, i); // initial substring of length i
|
|
j = k;
|
|
k = position(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);
|
|
var integ = true;
|
|
while ('0' <= st && st <= '9' && k <= str.length) {
|
|
st = str.slice(k, k + 1);
|
|
k++;
|
|
}
|
|
if (st == decimalsign) {
|
|
st = str.slice(k, k + 1);
|
|
if ('0' <= st && st <= '9') {
|
|
integ = false;
|
|
k++;
|
|
while ('0' <= st && st <= '9' && k <= str.length) {
|
|
st = str.slice(k, k + 1);
|
|
k++;
|
|
}
|
|
}
|
|
}
|
|
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 = (('A' > st || st > 'Z') && ('a' > st || st > 'z') ? 'mo' : 'mi');
|
|
}
|
|
if (st == '-' && AMpreviousSymbol == INFIX) {
|
|
AMcurrentSymbol = INFIX; // trick "/" into recognizing "-" on second parse
|
|
return {input: st, tag: tagst, output: st, ttype: UNARY, func: true};
|
|
}
|
|
return {input: st, tag: tagst, output: st, ttype: CONST};
|
|
}
|
|
|
|
function AMremoveBrackets(node) {
|
|
var st;
|
|
if (!node.hasChildNodes()) {
|
|
return;
|
|
}
|
|
if (node.firstChild.hasChildNodes() &&
|
|
(node.nodeName == 'mrow' || node.nodeName == 'M:MROW')) {
|
|
st = node.firstChild.firstChild.nodeValue;
|
|
if (st == '(' || st == '[' || st == '{') node.removeChild(node.firstChild);
|
|
}
|
|
if (node.lastChild.hasChildNodes() &&
|
|
(node.nodeName == 'mrow' || node.nodeName == 'M:MROW')) {
|
|
st = node.lastChild.firstChild.nodeValue;
|
|
if (st == ')' || st == ']' || st == '}') node.removeChild(node.lastChild);
|
|
}
|
|
}
|
|
|
|
/*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.*/
|
|
|
|
var AMnestingDepth, AMpreviousSymbol, AMcurrentSymbol;
|
|
|
|
function AMparseSexpr(str) { // parses str and returns [node,tailstr]
|
|
var symbol, node, result, i, st, // rightvert = false,
|
|
newFrag = document.createDocumentFragment();
|
|
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);
|
|
return [
|
|
createMmlNode(
|
|
symbol.tag, // its a constant
|
|
document.createTextNode(symbol.output)),
|
|
str
|
|
];
|
|
case LEFTBRACKET: // read (expr+)
|
|
AMnestingDepth++;
|
|
str = AMremoveCharsAndBlanks(str, symbol.input.length);
|
|
result = AMparseExpr(str, true);
|
|
AMnestingDepth--;
|
|
if (typeof symbol.invisible == 'boolean' && symbol.invisible)
|
|
node = createMmlNode('mrow', result[0]);
|
|
else {
|
|
node = createMmlNode('mo', document.createTextNode(symbol.output));
|
|
node = createMmlNode('mrow', node);
|
|
node.appendChild(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) == ' ') {
|
|
node = createMmlNode('mspace');
|
|
node.setAttribute('width', '1ex');
|
|
newFrag.appendChild(node);
|
|
}
|
|
newFrag.appendChild(
|
|
createMmlNode(symbol.tag, document.createTextNode(st)));
|
|
if (st.charAt(st.length - 1) == ' ') {
|
|
node = createMmlNode('mspace');
|
|
node.setAttribute('width', '1ex');
|
|
newFrag.appendChild(node);
|
|
}
|
|
str = AMremoveCharsAndBlanks(str, i + 1);
|
|
return [createMmlNode('mrow', newFrag), str];
|
|
case UNARYUNDEROVER:
|
|
case UNARY:
|
|
str = AMremoveCharsAndBlanks(str, symbol.input.length);
|
|
result = AMparseSexpr(str);
|
|
if (result[0] == null)
|
|
return [
|
|
createMmlNode(symbol.tag, document.createTextNode(symbol.output)), 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 [
|
|
createMmlNode(symbol.tag, document.createTextNode(symbol.output)),
|
|
str
|
|
];
|
|
} else {
|
|
node = createMmlNode(
|
|
'mrow',
|
|
createMmlNode(
|
|
symbol.tag, document.createTextNode(symbol.output)));
|
|
node.appendChild(result[0]);
|
|
return [node, result[1]];
|
|
}
|
|
}
|
|
AMremoveBrackets(result[0]);
|
|
if (symbol.input == 'sqrt') { // sqrt
|
|
return [createMmlNode(symbol.tag, result[0]), result[1]];
|
|
} else if (typeof symbol.rewriteleftright != 'undefined') { // abs,
|
|
// floor,
|
|
// ceil
|
|
node = createMmlNode(
|
|
'mrow',
|
|
createMmlNode(
|
|
'mo', document.createTextNode(symbol.rewriteleftright[0])));
|
|
node.appendChild(result[0]);
|
|
node.appendChild(createMmlNode(
|
|
'mo', document.createTextNode(symbol.rewriteleftright[1])));
|
|
return [node, result[1]];
|
|
} else if (symbol.input == 'cancel') { // cancel
|
|
node = createMmlNode(symbol.tag, result[0]);
|
|
node.setAttribute('notation', 'updiagonalstrike');
|
|
return [node, result[1]];
|
|
} else if (typeof symbol.acc == 'boolean' && symbol.acc) { // accent
|
|
node = createMmlNode(symbol.tag, result[0]);
|
|
node.appendChild(
|
|
createMmlNode('mo', document.createTextNode(symbol.output)));
|
|
return [node, result[1]];
|
|
} else { // font change command
|
|
if (!isIE && typeof symbol.codes != 'undefined') {
|
|
for (i = 0; i < result[0].childNodes.length; i++)
|
|
if (result[0].childNodes[i].nodeName == 'mi' ||
|
|
result[0].nodeName == 'mi') {
|
|
st =
|
|
(result[0].nodeName == 'mi' ?
|
|
result[0].firstChild.nodeValue :
|
|
result[0].childNodes[i].firstChild.nodeValue);
|
|
var newst = [];
|
|
for (var j = 0; j < st.length; j++)
|
|
if (st.charCodeAt(j) > 64 && st.charCodeAt(j) < 91)
|
|
newst = newst + symbol.codes[st.charCodeAt(j) - 65];
|
|
else if (st.charCodeAt(j) > 96 && st.charCodeAt(j) < 123)
|
|
newst = newst + symbol.codes[st.charCodeAt(j) - 71];
|
|
else
|
|
newst = newst + st.charAt(j);
|
|
if (result[0].nodeName == 'mi')
|
|
result[0] = createMmlNode('mo').appendChild(
|
|
document.createTextNode(newst));
|
|
else
|
|
result[0].replaceChild(
|
|
createMmlNode('mo').appendChild(
|
|
document.createTextNode(newst)),
|
|
result[0].childNodes[i]);
|
|
}
|
|
}
|
|
node = createMmlNode(symbol.tag, result[0]);
|
|
node.setAttribute(symbol.atname, symbol.atval);
|
|
return [node, result[1]];
|
|
}
|
|
case BINARY:
|
|
str = AMremoveCharsAndBlanks(str, symbol.input.length);
|
|
result = AMparseSexpr(str);
|
|
if (result[0] == null)
|
|
return [
|
|
createMmlNode('mo', document.createTextNode(symbol.input)), str
|
|
];
|
|
AMremoveBrackets(result[0]);
|
|
var result2 = AMparseSexpr(result[1]);
|
|
if (result2[0] == null)
|
|
return [
|
|
createMmlNode('mo', document.createTextNode(symbol.input)), str
|
|
];
|
|
AMremoveBrackets(result2[0]);
|
|
if (symbol.input == 'color') {
|
|
if (str.charAt(0) == '{')
|
|
i = str.indexOf('}');
|
|
else if (str.charAt(0) == '(')
|
|
i = str.indexOf(')');
|
|
else if (str.charAt(0) == '[')
|
|
i = str.indexOf(']');
|
|
st = str.slice(1, i);
|
|
node = createMmlNode(symbol.tag, result2[0]);
|
|
node.setAttribute('mathcolor', st);
|
|
return [node, result2[1]];
|
|
}
|
|
if (symbol.input == 'root' || symbol.output == 'stackrel')
|
|
newFrag.appendChild(result2[0]);
|
|
newFrag.appendChild(result[0]);
|
|
if (symbol.input == 'frac') newFrag.appendChild(result2[0]);
|
|
return [createMmlNode(symbol.tag, newFrag), result2[1]];
|
|
case INFIX:
|
|
str = AMremoveCharsAndBlanks(str, symbol.input.length);
|
|
return [createMmlNode('mo', document.createTextNode(symbol.output)), str];
|
|
case SPACE:
|
|
str = AMremoveCharsAndBlanks(str, symbol.input.length);
|
|
node = createMmlNode('mspace');
|
|
node.setAttribute('width', '1ex');
|
|
newFrag.appendChild(node);
|
|
newFrag.appendChild(
|
|
createMmlNode(symbol.tag, document.createTextNode(symbol.output)));
|
|
node = createMmlNode('mspace');
|
|
node.setAttribute('width', '1ex');
|
|
newFrag.appendChild(node);
|
|
return [createMmlNode('mrow', newFrag), str];
|
|
case LEFTRIGHT:
|
|
// if (rightvert) return [null,str]; else rightvert = true;
|
|
AMnestingDepth++;
|
|
str = AMremoveCharsAndBlanks(str, symbol.input.length);
|
|
result = AMparseExpr(str, false);
|
|
AMnestingDepth--;
|
|
st = '';
|
|
if (result[0].lastChild != null)
|
|
st = result[0].lastChild.firstChild.nodeValue;
|
|
if (st == '|') { // its an absolute value subterm
|
|
node = createMmlNode('mo', document.createTextNode(symbol.output));
|
|
node = createMmlNode('mrow', node);
|
|
node.appendChild(result[0]);
|
|
return [node, result[1]];
|
|
} else { // the "|" is a \mid so use unicode 2223 (divides) for spacing
|
|
node = createMmlNode('mo', document.createTextNode('\u2223'));
|
|
node = createMmlNode('mrow', node);
|
|
return [node, str];
|
|
}
|
|
default:
|
|
// alert("default");
|
|
str = AMremoveCharsAndBlanks(str, symbol.input.length);
|
|
return [
|
|
createMmlNode(
|
|
symbol.tag, // its a constant
|
|
document.createTextNode(symbol.output)),
|
|
str
|
|
];
|
|
}
|
|
}
|
|
|
|
function AMparseIexpr(str) {
|
|
var symbol, sym1, sym2, node, result, underover;
|
|
str = AMremoveCharsAndBlanks(str, 0);
|
|
sym1 = AMgetSymbol(str);
|
|
result = AMparseSexpr(str);
|
|
node = result[0];
|
|
str = result[1];
|
|
symbol = AMgetSymbol(str);
|
|
if (symbol.ttype == INFIX && symbol.input != '/') {
|
|
str = AMremoveCharsAndBlanks(str, symbol.input.length);
|
|
// if (symbol.input == "/") result = AMparseIexpr(str); else ...
|
|
result = AMparseSexpr(str);
|
|
if (result[0] == null) // show box in place of missing argument
|
|
result[0] = createMmlNode('mo', document.createTextNode('\u25A1'));
|
|
else
|
|
AMremoveBrackets(result[0]);
|
|
str = result[1];
|
|
// if (symbol.input == "/") AMremoveBrackets(node);
|
|
underover = (sym1.ttype == UNDEROVER || sym1.ttype == UNARYUNDEROVER);
|
|
if (symbol.input == '_') {
|
|
sym2 = AMgetSymbol(str);
|
|
if (sym2.input == '^') {
|
|
str = AMremoveCharsAndBlanks(str, sym2.input.length);
|
|
var res2 = AMparseSexpr(str);
|
|
AMremoveBrackets(res2[0]);
|
|
str = res2[1];
|
|
node = createMmlNode((underover ? 'munderover' : 'msubsup'), node);
|
|
node.appendChild(result[0]);
|
|
node.appendChild(res2[0]);
|
|
node = createMmlNode('mrow', node); // so sum does not stretch
|
|
} else {
|
|
node = createMmlNode((underover ? 'munder' : 'msub'), node);
|
|
node.appendChild(result[0]);
|
|
}
|
|
} else if (symbol.input == '^' && underover) {
|
|
node = createMmlNode('mover', node);
|
|
node.appendChild(result[0]);
|
|
} else {
|
|
node = createMmlNode(symbol.tag, node);
|
|
node.appendChild(result[0]);
|
|
}
|
|
if (typeof sym1.func != 'undefined' && sym1.func) {
|
|
sym2 = AMgetSymbol(str);
|
|
if (sym2.ttype != INFIX && sym2.ttype != RIGHTBRACKET) {
|
|
result = AMparseIexpr(str);
|
|
node = createMmlNode('mrow', node);
|
|
node.appendChild(result[0]);
|
|
str = result[1];
|
|
}
|
|
}
|
|
}
|
|
return [node, str];
|
|
}
|
|
|
|
function AMparseExpr(str, rightbracket) {
|
|
var symbol, node, result, i, newFrag = document.createDocumentFragment();
|
|
do {
|
|
str = AMremoveCharsAndBlanks(str, 0);
|
|
result = AMparseIexpr(str);
|
|
node = result[0];
|
|
str = result[1];
|
|
symbol = AMgetSymbol(str);
|
|
if (symbol.ttype == INFIX && symbol.input == '/') {
|
|
str = AMremoveCharsAndBlanks(str, symbol.input.length);
|
|
result = AMparseIexpr(str);
|
|
if (result[0] == null) // show box in place of missing argument
|
|
result[0] = createMmlNode('mo', document.createTextNode('\u25A1'));
|
|
else
|
|
AMremoveBrackets(result[0]);
|
|
str = result[1];
|
|
AMremoveBrackets(node);
|
|
node = createMmlNode(symbol.tag, node);
|
|
node.appendChild(result[0]);
|
|
newFrag.appendChild(node);
|
|
symbol = AMgetSymbol(str);
|
|
} else if (node != undefined)
|
|
newFrag.appendChild(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--;
|
|
var len = newFrag.childNodes.length;
|
|
if (len > 0 && newFrag.childNodes[len - 1].nodeName == 'mrow' &&
|
|
newFrag.childNodes[len - 1].lastChild &&
|
|
newFrag.childNodes[len - 1].lastChild.firstChild) { // matrix
|
|
// removed to allow row vectors: //&& len>1 &&
|
|
// newFrag.childNodes[len-2].nodeName == "mo" &&
|
|
// newFrag.childNodes[len-2].firstChild.nodeValue == ","
|
|
var right = newFrag.childNodes[len - 1].lastChild.firstChild.nodeValue;
|
|
if (right == ')' || right == ']') {
|
|
var left = newFrag.childNodes[len - 1].firstChild.firstChild.nodeValue;
|
|
if (left == '(' && right == ')' && symbol.output != '}' ||
|
|
left == '[' && right == ']') {
|
|
var pos = []; // positions of commas
|
|
var matrix = true;
|
|
var m = newFrag.childNodes.length;
|
|
for (i = 0; matrix && i < m; i = i + 2) {
|
|
pos[i] = [];
|
|
node = newFrag.childNodes[i];
|
|
if (matrix)
|
|
matrix = node.nodeName == 'mrow' &&
|
|
(i == m - 1 ||
|
|
node.nextSibling.nodeName == 'mo' &&
|
|
node.nextSibling.firstChild.nodeValue == ',') &&
|
|
node.firstChild.firstChild.nodeValue == left &&
|
|
node.lastChild.firstChild.nodeValue == right;
|
|
if (matrix)
|
|
for (var j = 0; j < node.childNodes.length; j++)
|
|
if (node.childNodes[j].firstChild.nodeValue == ',')
|
|
pos[i][pos[i].length] = j;
|
|
if (matrix && i > 1) matrix = pos[i].length == pos[i - 2].length;
|
|
}
|
|
matrix = matrix && (pos.length > 1 || pos[0].length > 0);
|
|
if (matrix) {
|
|
var row, frag, n, k, table = document.createDocumentFragment();
|
|
for (i = 0; i < m; i = i + 2) {
|
|
row = document.createDocumentFragment();
|
|
frag = document.createDocumentFragment();
|
|
node = newFrag.firstChild; // <mrow>(-,-,...,-,-)</mrow>
|
|
n = node.childNodes.length;
|
|
k = 0;
|
|
node.removeChild(node.firstChild); // remove (
|
|
for (j = 1; j < n - 1; j++) {
|
|
if (typeof pos[i][k] != 'undefined' && j == pos[i][k]) {
|
|
node.removeChild(node.firstChild); // remove ,
|
|
row.appendChild(createMmlNode('mtd', frag));
|
|
k++;
|
|
} else
|
|
frag.appendChild(node.firstChild);
|
|
}
|
|
row.appendChild(createMmlNode('mtd', frag));
|
|
if (newFrag.childNodes.length > 2) {
|
|
newFrag.removeChild(
|
|
newFrag.firstChild); // remove <mrow>)</mrow>
|
|
newFrag.removeChild(newFrag.firstChild); // remove <mo>,</mo>
|
|
}
|
|
table.appendChild(createMmlNode('mtr', row));
|
|
}
|
|
node = createMmlNode('mtable', table);
|
|
if (typeof symbol.invisible == 'boolean' && symbol.invisible)
|
|
node.setAttribute('columnalign', 'left');
|
|
newFrag.replaceChild(node, newFrag.firstChild);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
str = AMremoveCharsAndBlanks(str, symbol.input.length);
|
|
if (typeof symbol.invisible != 'boolean' || !symbol.invisible) {
|
|
node = createMmlNode('mo', document.createTextNode(symbol.output));
|
|
newFrag.appendChild(node);
|
|
}
|
|
}
|
|
return [newFrag, str];
|
|
}
|
|
|
|
function parseMath(str, latex) {
|
|
var frag, node;
|
|
AMnestingDepth = 0;
|
|
// some basic cleanup for dealing with stuff editors like TinyMCE adds
|
|
str = str.replace(/ /g, '');
|
|
str = str.replace(/>/g, '>');
|
|
str = str.replace(/</g, '<');
|
|
str = str.replace(
|
|
/(Sin|Cos|Tan|Arcsin|Arccos|Arctan|Sinh|Cosh|Tanh|Cot|Sec|Csc|Log|Ln|Abs)/g,
|
|
function(v) {
|
|
return v.toLowerCase();
|
|
});
|
|
frag = AMparseExpr(str.replace(/^\s+/g, ''), false)[0];
|
|
node = createMmlNode('mstyle', frag);
|
|
if (mathcolor != '') node.setAttribute('mathcolor', mathcolor);
|
|
if (mathfontfamily != '') node.setAttribute('fontfamily', mathfontfamily);
|
|
if (displaystyle) node.setAttribute('displaystyle', 'true');
|
|
node = createMmlNode('math', node);
|
|
if (showasciiformulaonhover) // fixed by djhsu so newline
|
|
node.setAttribute(
|
|
'title', str.replace(/\s+/g, ' ')); // does not show in Gecko
|
|
return node;
|
|
}
|
|
|
|
function strarr2docFrag(arr, linebreaks, latex) {
|
|
var newFrag = document.createDocumentFragment();
|
|
var expr = false;
|
|
for (var i = 0; i < arr.length; i++) {
|
|
if (expr)
|
|
newFrag.appendChild(parseMath(arr[i], latex));
|
|
else {
|
|
var arri = (linebreaks ? arr[i].split('\n\n') : [arr[i]]);
|
|
newFrag.appendChild(createElementXHTML('span').appendChild(
|
|
document.createTextNode(arri[0])));
|
|
for (var j = 1; j < arri.length; j++) {
|
|
newFrag.appendChild(createElementXHTML('p'));
|
|
newFrag.appendChild(createElementXHTML('span').appendChild(
|
|
document.createTextNode(arri[j])));
|
|
}
|
|
}
|
|
expr = !expr;
|
|
}
|
|
return newFrag;
|
|
}
|
|
|
|
function AMautomathrec(str) {
|
|
// formula is a space (or start of str) followed by a maximal sequence of
|
|
// *two* or more tokens, possibly separated by runs of digits and/or space.
|
|
// tokens are single letters (except a, A, I) and ASCIIMathML tokens
|
|
var texcommand = '\\\\[a-zA-Z]+|\\\\\\s|';
|
|
var ambigAMtoken =
|
|
'\\b(?:oo|lim|ln|int|oint|del|grad|aleph|prod|prop|sinh|cosh|tanh|cos|sec|pi|tt|fr|sf|sube|supe|sub|sup|det|mod|gcd|lcm|min|max|vec|ddot|ul|chi|eta|nu|mu)(?![a-z])|';
|
|
var englishAMtoken = '\\b(?:sum|ox|log|sin|tan|dim|hat|bar|dot)(?![a-z])|';
|
|
var secondenglishAMtoken =
|
|
'|\\bI\\b|\\bin\\b|\\btext\\b'; // took if and or not out
|
|
var simpleAMtoken =
|
|
'NN|ZZ|QQ|RR|CC|TT|AA|EE|sqrt|dx|dy|dz|dt|xx|vv|uu|nn|bb|cc|csc|cot|alpha|beta|delta|Delta|epsilon|gamma|Gamma|kappa|lambda|Lambda|omega|phi|Phi|Pi|psi|Psi|rho|sigma|Sigma|tau|theta|Theta|xi|Xi|zeta'; // uuu nnn?
|
|
var letter = '[a-zA-HJ-Z](?=(?:[^a-zA-Z]|$|' + ambigAMtoken + englishAMtoken +
|
|
simpleAMtoken + '))|';
|
|
var token = letter + texcommand +
|
|
'\\d+|[-()[\\]{}+=*&^_%\\\@/<>,\\|!:;\'~]|\\.(?!(?:\x20|$))|' +
|
|
ambigAMtoken + englishAMtoken + simpleAMtoken;
|
|
var re = new RegExp(
|
|
'(^|\\s)(((' + token + ')\\s?)((' + token + secondenglishAMtoken +
|
|
')\\s?)+)([,.?]?(?=\\s|$))',
|
|
'g');
|
|
str = str.replace(re, ' `$2`$7');
|
|
var arr = str.split(AMdelimiter1);
|
|
var re1 = new RegExp(
|
|
'(^|\\s)([b-zB-HJ-Z+*<>]|' + texcommand + ambigAMtoken + simpleAMtoken +
|
|
')(\\s|\\n|$)',
|
|
'g');
|
|
var re2 = new RegExp(
|
|
'(^|\\s)([a-z]|' + texcommand + ambigAMtoken + simpleAMtoken + ')([,.])',
|
|
'g'); // removed |\d+ for now
|
|
for (i = 0; i < arr.length; i++) // single nonenglish tokens
|
|
if (i % 2 == 0) {
|
|
arr[i] = arr[i].replace(re1, ' `$2`$3');
|
|
arr[i] = arr[i].replace(re2, ' `$2`$3');
|
|
arr[i] = arr[i].replace(/([{}[\]])/, '`$1`');
|
|
}
|
|
str = arr.join(AMdelimiter1);
|
|
str = str.replace(/((^|\s)\([a-zA-Z]{2,}.*?)\)`/g, '$1`)'); // fix
|
|
// parentheses
|
|
str = str.replace(
|
|
/`(\((a\s|in\s))(.*?[a-zA-Z]{2,}\))/g, '$1`$3'); // fix parentheses
|
|
str = str.replace(/\sin`/g, '` in');
|
|
str = str.replace(/`(\(\w\)[,.]?(\s|\n|$))/g, '$1`');
|
|
str = str.replace(/`([0-9.]+|e.g|i.e)`(\.?)/gi, '$1$2');
|
|
str = str.replace(/`([0-9.]+:)`/g, '$1');
|
|
return str;
|
|
}
|
|
|
|
function processNodeR(n, linebreaks, latex) {
|
|
var mtch, str, arr, frg, 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');
|
|
str = str.replace(/\x20+/g, ' ');
|
|
str = str.replace(/\s*\r\n/g, ' ');
|
|
if (latex) {
|
|
// DELIMITERS:
|
|
mtch = (str.indexOf('\$') == -1 ? false : true);
|
|
str = str.replace(/([^\\])\$/g, '$1 \$');
|
|
str = str.replace(/^\$/, ' \$'); // in case \$ at start of string
|
|
arr = str.split(' \$');
|
|
for (i = 0; i < arr.length; i++)
|
|
arr[i] = arr[i].replace(/\\\$/g, '\$');
|
|
} else {
|
|
mtch = false;
|
|
str = str.replace(new RegExp(AMescape1, 'g'), function() {
|
|
mtch = true;
|
|
return 'AMescape1'
|
|
});
|
|
str = str.replace(/\\?end{?a?math}?/i, function() {
|
|
automathrecognize = false;
|
|
mtch = true;
|
|
return ''
|
|
});
|
|
str = str.replace(/amath\b|\\begin{a?math}/i, function() {
|
|
automathrecognize = true;
|
|
mtch = true;
|
|
return ''
|
|
});
|
|
arr = str.split(AMdelimiter1);
|
|
if (automathrecognize)
|
|
for (i = 0; i < arr.length; i++)
|
|
if (i % 2 == 0) arr[i] = AMautomathrec(arr[i]);
|
|
str = arr.join(AMdelimiter1);
|
|
arr = str.split(AMdelimiter1);
|
|
for (i = 0; i < arr.length; i++) // this is a problem ************
|
|
arr[i] = arr[i].replace(/AMescape1/g, AMdelimiter1);
|
|
}
|
|
if (arr.length > 1 || mtch) {
|
|
if (!noMathML) {
|
|
frg = strarr2docFrag(arr, n.nodeType == 8, latex);
|
|
var len = frg.childNodes.length;
|
|
n.parentNode.replaceChild(frg, n);
|
|
return len - 1;
|
|
} else
|
|
return 0;
|
|
}
|
|
}
|
|
} else
|
|
return 0;
|
|
} else if (n.nodeName != 'math') {
|
|
for (i = 0; i < n.childNodes.length; i++)
|
|
i += processNodeR(n.childNodes[i], linebreaks, latex);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
function AMprocessNode(n, linebreaks, spanclassAM) {
|
|
var frag, st;
|
|
if (spanclassAM != null) {
|
|
frag = document.getElementsByTagName('span')
|
|
for (var i = 0; i < frag.length; i++)
|
|
if (frag[i].className == 'AM') processNodeR(frag[i], linebreaks, false);
|
|
} else {
|
|
try {
|
|
st = n.innerHTML; // look for AMdelimiter on page
|
|
} catch (err) {
|
|
}
|
|
// alert(st)
|
|
if (st == null || /amath\b|\\begin{a?math}/i.test(st) ||
|
|
st.indexOf(AMdelimiter1 + ' ') != -1 || st.slice(-1) == AMdelimiter1 ||
|
|
st.indexOf(AMdelimiter1 + '<') != -1 ||
|
|
st.indexOf(AMdelimiter1 + '\n') != -1) {
|
|
processNodeR(n, linebreaks, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
function generic() {
|
|
if (!init()) return;
|
|
if (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 {
|
|
//.. mac/ie5 and anything else that gets this far
|
|
// if there's an existing onload function
|
|
if (typeof window.onload == 'function') {
|
|
// store it
|
|
var existing = onload;
|
|
// add new onload handler
|
|
window.onload = function() {
|
|
// call existing onload function
|
|
existing();
|
|
// call generic onload function
|
|
generic();
|
|
};
|
|
} else {
|
|
window.onload = generic;
|
|
}
|
|
}
|
|
|
|
// expose some functions to outside
|
|
asciimath.newcommand = newcommand;
|
|
asciimath.newsymbol = newsymbol;
|
|
asciimath.AMprocesssNode = AMprocessNode;
|
|
asciimath.parseMath = parseMath;
|
|
asciimath.translate = translate;
|
|
})();
|