PageSourceSearch

https://momath.org/wp-content/themes/momath-prod/js/ASCIIMathML.js?ver=7.1.1

js momath.org collected 2026-09-24 08:48:58 UTC 57,289 bytes, 1,187 lines download raw bytes

1/*
2ASCIIMathML.js
3==============
4This file contains JavaScript functions to convert ASCII math notation
5and (some) LaTeX to Presentation MathML. The conversion is done while the
6HTML page loads, and should work with Firefox and other browsers that can
7render MathML.
8
9Just add the next line to your HTML page with this file in the same folder:
10
11<script type="text/javascript" src="ASCIIMathML.js"></script>
12
13Version 2.2 Mar 3, 2014.
14Latest version at https://github.com/mathjax/asciimathml
15If you use it on a webpage, please send the URL to [email protected]
16
17Copyright (c) 2014 Peter Jipsen and other ASCIIMathML.js contributors
18
19Permission is hereby granted, free of charge, to any person obtaining a copy
20of this software and associated documentation files (the "Software"), to deal
21in the Software without restriction, including without limitation the rights
22to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23copies of the Software, and to permit persons to whom the Software is
24furnished to do so, subject to the following conditions:
25
26The above copyright notice and this permission notice shall be included in
27all copies or substantial portions of the Software.
28
29THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35THE SOFTWARE.
36*/
37var asciimath = {};
38
39(function(){
40var mathcolor = "black";        // change it to "" (to inherit) or another color
41var mathfontsize = "1em";      // change to e.g. 1.2em for larger math
42var mathfontfamily = "serif";  // change to "" to inherit (works in IE)
43                               // or another family (e.g. "arial")
44var automathrecognize = false; // writing "amath" on page makes this true
45var checkForMathML = true;     // check if browser can display MathML
46var notifyIfNoMathML = true;   // display note at top if no MathML capability
47var alertIfNoMathML = false;   // show alert box if no MathML capability
48var translateOnLoad = true;    // set to false to do call translators from js
49var translateASCIIMath = true; // false to preserve `..`
50var displaystyle = true;      // puts limits above and below large operators
51var showasciiformulaonhover = true; // helps students learn ASCIIMath
52var decimalsign = ".";        // if "," then when writing lists or matrices put
53			      //a space after the "," like `(1, 2)` not `(1,2)`
54var AMdelimiter1 = "`", AMescape1 = "\\\\`"; // can use other characters
55var AMdocumentId = "wikitext" // PmWiki element containing math (default=body)
56var fixphi = true;  		//false to return to legacy phi/varphi mapping
57
58/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
59
60var isIE = (navigator.appName.slice(0,9)=="Microsoft");
61var noMathML = false, translated = false;
62
63if (isIE) { // add MathPlayer info to IE webpages
64  document.write("<object id=\"mathplayer\"\
65  classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>");
66  document.write("<?import namespace=\"m\" implementation=\"#mathplayer\"?>");
67}
68
69// Add a stylesheet, replacing any previous custom stylesheet (adapted from TW)
70function setStylesheet(s) {
71	var id = "AMMLcustomStyleSheet";
72	var n = document.getElementById(id);
73	if(document.createStyleSheet) {
74		// Test for IE's non-standard createStyleSheet method
75		if(n)
76			n.parentNode.removeChild(n);
77		// This failed without the &nbsp;
78		document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd","&nbsp;<style id='" + id + "'>" + s + "</style>");
79	} else {
80		if(n) {
81			n.replaceChild(document.createTextNode(s),n.firstChild);
82		} else {
83			n = document.createElement("style");
84			n.type = "text/css";
85			n.id = id;
86			n.appendChild(document.createTextNode(s));
87			document.getElementsByTagName("head")[0].appendChild(n);
88		}
89	}
90}
91
92setStylesheet("#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\}");
93
94function init(){
95	var msg, warnings = new Array();
96	if (document.getElementById==null){
97		alert("This webpage requires a recent browser such as Mozilla Firefox");
98		return null;
99	}
100	if (checkForMathML && (msg = checkMathML())) warnings.push(msg);
101	if (warnings.length>0) displayWarnings(warnings);
102	if (!noMathML) initSymbols();
103	return true;
104}
105
106function checkMathML(){
107  if (navigator.appName.slice(0,8)=="Netscape")
108    if (navigator.appVersion.slice(0,1)>="5") noMathML = null;
109    else noMathML = true;
110  else if (navigator.appName.slice(0,9)=="Microsoft")
111    try {
112        var ActiveX = new ActiveXObject("MathPlayer.Factory.1");
113        noMathML = null;
114    } catch (e) {
115        noMathML = true;
116    }
117  else if (navigator.appName.slice(0,5)=="Opera")
118    if (navigator.appVersion.slice(0,3)>="9.5") noMathML = null;
119  else noMathML = true;
120
121  //noMathML = true; //uncomment to check
122  if (noMathML && notifyIfNoMathML) {
123    var msg = "To view the ASCIIMathML notation use Internet Explorer + MathPlayer or Mozilla Firefox 2.0 or later.";
124    if (alertIfNoMathML)
125       alert(msg);
126    else return msg;
127  }
128}
129
130function hideWarning(){
131	var body = document.getElementsByTagName("body")[0];
132	body.removeChild(document.getElementById('AMMLwarningBox'));
133	body.onclick = null;
134}
135
136function displayWarnings(warnings) {
137  var i, frag, nd = createElementXHTML("div");
138  var body = document.getElementsByTagName("body")[0];
139  body.onclick=hideWarning;
140  nd.id = 'AMMLwarningBox';
141  for (i=0; i<warnings.length; i++) {
142	frag = createElementXHTML("div");
143	frag.appendChild(document.createTextNode(warnings[i]));
144	frag.style.paddingBottom = "1.0em";
145	nd.appendChild(frag);
146  }
147  nd.appendChild(createElementXHTML("p"));
148  nd.appendChild(document.createTextNode("For instructions see the "));
149  var an = createElementXHTML("a");
150  an.appendChild(document.createTextNode("ASCIIMathML"));
151  an.setAttribute("href","http://www.chapman.edu/~jipsen/asciimath.html");
152  nd.appendChild(an);
153  nd.appendChild(document.createTextNode(" homepage"));
154  an = createElementXHTML("div");
155  an.id = 'AMMLcloseDiv';
156  an.appendChild(document.createTextNode('(click anywhere to close this warning)'));
157  nd.appendChild(an);
158  var body = document.getElementsByTagName("body")[0];
159  body.insertBefore(nd,body.childNodes[0]);
160}
161
162function translate(spanclassAM) {
163  if (!translated) { // run this only once
164    translated = true;
165    var body = document.getElementsByTagName("body")[0];
166    var processN = document.getElementById(AMdocumentId);
167    if (translateASCIIMath) AMprocessNode((processN!=null?processN:body), false, spanclassAM);
168  }
169}
170
171function createElementXHTML(t) {
172  if (isIE) return document.createElement(t);
173  else return document.createElementNS("http://www.w3.org/1999/xhtml",t);
174}
175
176var AMmathml = "http://www.w3.org/1998/Math/MathML";
177
178function AMcreateElementMathML(t) {
179  if (isIE) return document.createElement("m:"+t);
180  else return document.createElementNS(AMmathml,t);
181}
182
183function createMmlNode(t,frag) {
184  var node;
185  if (isIE) node = document.createElement("m:"+t);
186  else node = document.createElementNS(AMmathml,t);
187  if (frag) node.appendChild(frag);
188  return node;
189}
190
191function newcommand(oldstr,newstr) {
192  AMsymbols.push({input:oldstr, tag:"mo", output:newstr, tex:null, ttype:DEFINITION});
193  refreshSymbols();
194}
195
196function newsymbol(symbolobj) {
197  AMsymbols.push(symbolobj);
198  refreshSymbols();
199}
200
201// character lists for Mozilla/Netscape fonts
202var 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"];
203
204var 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"];
205
206var 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"];
207/*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];
208var 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];
209var 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];*/
210
211var CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4,
212    RIGHTBRACKET = 5, SPACE = 6, UNDEROVER = 7, DEFINITION = 8,
213    LEFTRIGHT = 9, TEXT = 10, BIG = 11, LONG = 12, STRETCHY = 13,
214    MATRIX = 14, UNARYUNDEROVER = 15; // token types
215
216var AMquote = {input:"\"",   tag:"mtext", output:"mbox", tex:null, ttype:TEXT};
217
218var AMsymbols = [
219//some greek symbols
220{input:"alpha",  tag:"mi", output:"\u03B1", tex:null, ttype:CONST},
221{input:"beta",   tag:"mi", output:"\u03B2", tex:null, ttype:CONST},
222{input:"chi",    tag:"mi", output:"\u03C7", tex:null, ttype:CONST},
223{input:"delta",  tag:"mi", output:"\u03B4", tex:null, ttype:CONST},
224{input:"Delta",  tag:"mo", output:"\u0394", tex:null, ttype:CONST},
225{input:"epsi",   tag:"mi", output:"\u03B5", tex:"epsilon", ttype:CONST},
226{input:"varepsilon", tag:"mi", output:"\u025B", tex:null, ttype:CONST},
227{input:"eta",    tag:"mi", output:"\u03B7", tex:null, ttype:CONST},
228{input:"gamma",  tag:"mi", output:"\u03B3", tex:null, ttype:CONST},
229{input:"Gamma",  tag:"mo", output:"\u0393", tex:null, ttype:CONST},
230{input:"iota",   tag:"mi", output:"\u03B9", tex:null, ttype:CONST},
231{input:"kappa",  tag:"mi", output:"\u03BA", tex:null, ttype:CONST},
232{input:"lambda", tag:"mi", output:"\u03BB", tex:null, ttype:CONST},
233{input:"Lambda", tag:"mo", output:"\u039B", tex:null, ttype:CONST},
234{input:"lamda", tag:"mi", output:"\u03BB", tex:null, ttype:CONST},
235{input:"Lamda", tag:"mo", output:"\u039B", tex:null, ttype:CONST},
236{input:"mu",     tag:"mi", output:"\u03BC", tex:null, ttype:CONST},
237{input:"nu",     tag:"mi", output:"\u03BD", tex:null, ttype:CONST},
238{input:"omega",  tag:"mi", output:"\u03C9", tex:null, ttype:CONST},
239{input:"Omega",  tag:"mo", output:"\u03A9", tex:null, ttype:CONST},
240{input:"phi",    tag:"mi", output:fixphi?"\u03D5":"\u03C6", tex:null, ttype:CONST},
241{input:"varphi", tag:"mi", output:fixphi?"\u03C6":"\u03D5", tex:null, ttype:CONST},
242{input:"Phi",    tag:"mo", output:"\u03A6", tex:null, ttype:CONST},
243{input:"pi",     tag:"mi", output:"\u03C0", tex:null, ttype:CONST},
244{input:"Pi",     tag:"mo", output:"\u03A0", tex:null, ttype:CONST},
245{input:"psi",    tag:"mi", output:"\u03C8", tex:null, ttype:CONST},
246{input:"Psi",    tag:"mi", output:"\u03A8", tex:null, ttype:CONST},
247{input:"rho",    tag:"mi", output:"\u03C1", tex:null, ttype:CONST},
248{input:"sigma",  tag:"mi", output:"\u03C3", tex:null, ttype:CONST},
249{input:"Sigma",  tag:"mo", output:"\u03A3", tex:null, ttype:CONST},
250{input:"tau",    tag:"mi", output:"\u03C4", tex:null, ttype:CONST},
251{input:"theta",  tag:"mi", output:"\u03B8", tex:null, ttype:CONST},
252{input:"vartheta", tag:"mi", output:"\u03D1", tex:null, ttype:CONST},
253{input:"Theta",  tag:"mo", output:"\u0398", tex:null, ttype:CONST},
254{input:"upsilon", tag:"mi", output:"\u03C5", tex:null, ttype:CONST},
255{input:"xi",     tag:"mi", output:"\u03BE", tex:null, ttype:CONST},
256{input:"Xi",     tag:"mo", output:"\u039E", tex:null, ttype:CONST},
257{input:"zeta",   tag:"mi", output:"\u03B6", tex:null, ttype:CONST},
258
259//binary operation symbols
260//{input:"-",  tag:"mo", output:"\u0096", tex:null, ttype:CONST},
261{input:"*",  tag:"mo", output:"\u22C5", tex:"cdot", ttype:CONST},
262{input:"**", tag:"mo", output:"\u2217", tex:"ast", ttype:CONST},
263{input:"***", tag:"mo", output:"\u22C6", tex:"star", ttype:CONST},
264{input:"//", tag:"mo", output:"/",      tex:null, ttype:CONST},
265{input:"\\\\", tag:"mo", output:"\\",   tex:"backslash", ttype:CONST},
266{input:"setminus", tag:"mo", output:"\\", tex:null, ttype:CONST},
267{input:"xx", tag:"mo", output:"\u00D7", tex:"times", ttype:CONST},
268{input:"|><", tag:"mo", output:"\u22C9", tex:"ltimes", ttype:CONST},
269{input:"><|", tag:"mo", output:"\u22CA", tex:"rtimes", ttype:CONST},
270{input:"|><|", tag:"mo", output:"\u22C8", tex:"bowtie", ttype:CONST},
271{input:"-:", tag:"mo", output:"\u00F7", tex:"div", ttype:CONST},
272{input:"divide",   tag:"mo", output:"-:", tex:null, ttype:DEFINITION},
273{input:"@",  tag:"mo", output:"\u2218", tex:"circ", ttype:CONST},
274{input:"o+", tag:"mo", output:"\u2295", tex:"oplus", ttype:CONST},
275{input:"ox", tag:"mo", output:"\u2297", tex:"otimes", ttype:CONST},
276{input:"o.", tag:"mo", output:"\u2299", tex:"odot", ttype:CONST},
277{input:"sum", tag:"mo", output:"\u2211", tex:null, ttype:UNDEROVER},
278{input:"prod", tag:"mo", output:"\u220F", tex:null, ttype:UNDEROVER},
279{input:"^^",  tag:"mo", output:"\u2227", tex:"wedge", ttype:CONST},
280{input:"^^^", tag:"mo", output:"\u22C0", tex:"bigwedge", ttype:UNDEROVER},
281{input:"vv",  tag:"mo", output:"\u2228", tex:"vee", ttype:CONST},
282{input:"vvv", tag:"mo", output:"\u22C1", tex:"bigvee", ttype:UNDEROVER},
283{input:"nn",  tag:"mo", output:"\u2229", tex:"cap", ttype:CONST},
284{input:"nnn", tag:"mo", output:"\u22C2", tex:"bigcap", ttype:UNDEROVER},
285{input:"uu",  tag:"mo", output:"\u222A", tex:"cup", ttype:CONST},
286{input:"uuu", tag:"mo", output:"\u22C3", tex:"bigcup", ttype:UNDEROVER},
287
288//binary relation symbols
289{input:"!=",  tag:"mo", output:"\u2260", tex:"ne", ttype:CONST},
290{input:":=",  tag:"mo", output:":=",     tex:null, ttype:CONST},
291{input:"lt",  tag:"mo", output:"<",      tex:null, ttype:CONST},
292{input:"<=",  tag:"mo", output:"\u2264", tex:"le", ttype:CONST},
293{input:"lt=", tag:"mo", output:"\u2264", tex:"leq", ttype:CONST},
294{input:"gt",  tag:"mo", output:">",      tex:null, ttype:CONST},
295{input:">=",  tag:"mo", output:"\u2265", tex:"ge", ttype:CONST},
296{input:"gt=", tag:"mo", output:"\u2265", tex:"geq", ttype:CONST},
297{input:"-<",  tag:"mo", output:"\u227A", tex:"prec", ttype:CONST},
298{input:"-lt", tag:"mo", output:"\u227A", tex:null, ttype:CONST},
299{input:">-",  tag:"mo", output:"\u227B", tex:"succ", ttype:CONST},
300{input:"-<=", tag:"mo", output:"\u2AAF", tex:"preceq", ttype:CONST},
301{input:">-=", tag:"mo", output:"\u2AB0", tex:"succeq", ttype:CONST},
302{input:"in",  tag:"mo", output:"\u2208", tex:null, ttype:CONST},
303{input:"!in", tag:"mo", output:"\u2209", tex:"notin", ttype:CONST},
304{input:"sub", tag:"mo", output:"\u2282", tex:"subset", ttype:CONST},
305{input:"sup", tag:"mo", output:"\u2283", tex:"supset", ttype:CONST},
306{input:"sube", tag:"mo", output:"\u2286", tex:"subseteq", ttype:CONST},
307{input:"supe", tag:"mo", output:"\u2287", tex:"supseteq", ttype:CONST},
308{input:"-=",  tag:"mo", output:"\u2261", tex:"equiv", ttype:CONST},
309{input:"~=",  tag:"mo", output:"\u2245", tex:"cong", ttype:CONST},
310{input:"~~",  tag:"mo", output:"\u2248", tex:"approx", ttype:CONST},
311{input:"prop", tag:"mo", output:"\u221D", tex:"propto", ttype:CONST},
312
313//logical symbols
314{input:"and", tag:"mtext", output:"and", tex:null, ttype:SPACE},
315{input:"or",  tag:"mtext", output:"or",  tex:null, ttype:SPACE},
316{input:"not", tag:"mo", output:"\u00AC", tex:"neg", ttype:CONST},
317{input:"=>",  tag:"mo", output:"\u21D2", tex:"implies", ttype:CONST},
318{input:"if",  tag:"mo", output:"if",     tex:null, ttype:SPACE},
319{input:"<=>", tag:"mo", output:"\u21D4", tex:"iff", ttype:CONST},
320{input:"AA",  tag:"mo", output:"\u2200", tex:"forall", ttype:CONST},
321{input:"EE",  tag:"mo", output:"\u2203", tex:"exists", ttype:CONST},
322{input:"_|_", tag:"mo", output:"\u22A5", tex:"bot", ttype:CONST},
323{input:"TT",  tag:"mo", output:"\u22A4", tex:"top", ttype:CONST},
324{input:"|--",  tag:"mo", output:"\u22A2", tex:"vdash", ttype:CONST},
325{input:"|==",  tag:"mo", output:"\u22A8", tex:"models", ttype:CONST},
326
327//grouping brackets
328{input:"(", tag:"mo", output:"(", tex:"left(", ttype:LEFTBRACKET},
329{input:")", tag:"mo", output:")", tex:"right)", ttype:RIGHTBRACKET},
330{input:"[", tag:"mo", output:"[", tex:"left[", ttype:LEFTBRACKET},
331{input:"]", tag:"mo", output:"]", tex:"right]", ttype:RIGHTBRACKET},
332{input:"{", tag:"mo", output:"{", tex:null, ttype:LEFTBRACKET},
333{input:"}", tag:"mo", output:"}", tex:null, ttype:RIGHTBRACKET},
334{input:"|", tag:"mo", output:"|", tex:null, ttype:LEFTRIGHT},
335{input:":|:", tag:"mo", output:"|", tex:null, ttype:CONST},
336{input:"|:", tag:"mo", output:"|", tex:null, ttype:LEFTBRACKET},
337{input:":|", tag:"mo", output:"|", tex:null, ttype:RIGHTBRACKET},
338//{input:"||", tag:"mo", output:"||", tex:null, ttype:LEFTRIGHT},
339{input:"(:", tag:"mo", output:"\u2329", tex:"langle", ttype:LEFTBRACKET},
340{input:":)", tag:"mo", output:"\u232A", tex:"rangle", ttype:RIGHTBRACKET},
341{input:"<<", tag:"mo", output:"\u2329", tex:null, ttype:LEFTBRACKET},
342{input:">>", tag:"mo", output:"\u232A", tex:null, ttype:RIGHTBRACKET},
343{input:"{:", tag:"mo", output:"{:", tex:null, ttype:LEFTBRACKET, invisible:true},
344{input:":}", tag:"mo", output:":}", tex:null, ttype:RIGHTBRACKET, invisible:true},
345
346//miscellaneous symbols
347{input:"int",  tag:"mo", output:"\u222B", tex:null, ttype:CONST},
348{input:"dx",   tag:"mi", output:"{:d x:}", tex:null, ttype:DEFINITION},
349{input:"dy",   tag:"mi", output:"{:d y:}", tex:null, ttype:DEFINITION},
350{input:"dz",   tag:"mi", output:"{:d z:}", tex:null, ttype:DEFINITION},
351{input:"dt",   tag:"mi", output:"{:d t:}", tex:null, ttype:DEFINITION},
352{input:"oint", tag:"mo", output:"\u222E", tex:null, ttype:CONST},
353{input:"del",  tag:"mo", output:"\u2202", tex:"partial", ttype:CONST},
354{input:"grad", tag:"mo", output:"\u2207", tex:"nabla", ttype:CONST},
355{input:"+-",   tag:"mo", output:"\u00B1", tex:"pm", ttype:CONST},
356{input:"O/",   tag:"mo", output:"\u2205", tex:"emptyset", ttype:CONST},
357{input:"oo",   tag:"mo", output:"\u221E", tex:"infty", ttype:CONST},
358{input:"aleph", tag:"mo", output:"\u2135", tex:null, ttype:CONST},
359{input:"...",  tag:"mo", output:"...",    tex:"ldots", ttype:CONST},
360{input:":.",  tag:"mo", output:"\u2234",  tex:"therefore", ttype:CONST},
361{input:":'",  tag:"mo", output:"\u2235",  tex:"because", ttype:CONST},
362{input:"/_",  tag:"mo", output:"\u2220",  tex:"angle", ttype:CONST},
363{input:"/_\\",  tag:"mo", output:"\u25B3",  tex:"triangle", ttype:CONST},
364{input:"'",   tag:"mo", output:"\u2032",  tex:"prime", ttype:CONST},
365{input:"tilde", tag:"mover", output:"~", tex:null, ttype:UNARY, acc:true},
366{input:"\\ ",  tag:"mo", output:"\u00A0", tex:null, ttype:CONST},
367{input:"frown",  tag:"mo", output:"\u2322", tex:null, ttype:CONST},
368{input:"quad", tag:"mo", output:"\u00A0\u00A0", tex:null, ttype:CONST},
369{input:"qquad", tag:"mo", output:"\u00A0\u00A0\u00A0\u00A0", tex:null, ttype:CONST},
370{input:"cdots", tag:"mo", output:"\u22EF", tex:null, ttype:CONST},
371{input:"vdots", tag:"mo", output:"\u22EE", tex:null, ttype:CONST},
372{input:"ddots", tag:"mo", output:"\u22F1", tex:null, ttype:CONST},
373{input:"diamond", tag:"mo", output:"\u22C4", tex:null, ttype:CONST},
374{input:"square", tag:"mo", output:"\u25A1", tex:null, ttype:CONST},
375{input:"|__", tag:"mo", output:"\u230A",  tex:"lfloor", ttype:CONST},
376{input:"__|", tag:"mo", output:"\u230B",  tex:"rfloor", ttype:CONST},
377{input:"|~", tag:"mo", output:"\u2308",  tex:"lceiling", ttype:CONST},
378{input:"~|", tag:"mo", output:"\u2309",  tex:"rceiling", ttype:CONST},
379{input:"CC",  tag:"mo", output:"\u2102", tex:null, ttype:CONST},
380{input:"NN",  tag:"mo", output:"\u2115", tex:null, ttype:CONST},
381{input:"QQ",  tag:"mo", output:"\u211A", tex:null, ttype:CONST},
382{input:"RR",  tag:"mo", output:"\u211D", tex:null, ttype:CONST},
383{input:"ZZ",  tag:"mo", output:"\u2124", tex:null, ttype:CONST},
384{input:"f",   tag:"mi", output:"f",      tex:null, ttype:UNARY, func:true},
385{input:"g",   tag:"mi", output:"g",      tex:null, ttype:UNARY, func:true},
386
387//standard functions
388{input:"lim",  tag:"mo", output:"lim", tex:null, ttype:UNDEROVER},
389{input:"Lim",  tag:"mo", output:"Lim", tex:null, ttype:UNDEROVER},
390{input:"sin",  tag:"mo", output:"sin", tex:null, ttype:UNARY, func:true},
391{input:"cos",  tag:"mo", output:"cos", tex:null, ttype:UNARY, func:true},
392{input:"tan",  tag:"mo", output:"tan", tex:null, ttype:UNARY, func:true},
393{input:"sinh", tag:"mo", output:"sinh", tex:null, ttype:UNARY, func:true},
394{input:"cosh", tag:"mo", output:"cosh", tex:null, ttype:UNARY, func:true},
395{input:"tanh", tag:"mo", output:"tanh", tex:null, ttype:UNARY, func:true},
396{input:"cot",  tag:"mo", output:"cot", tex:null, ttype:UNARY, func:true},
397{input:"sec",  tag:"mo", output:"sec", tex:null, ttype:UNARY, func:true},
398{input:"csc",  tag:"mo", output:"csc", tex:null, ttype:UNARY, func:true},
399{input:"arcsin",  tag:"mo", output:"arcsin", tex:null, ttype:UNARY, func:true},
400{input:"arccos",  tag:"mo", output:"arccos", tex:null, ttype:UNARY, func:true},
401{input:"arctan",  tag:"mo", output:"arctan", tex:null, ttype:UNARY, func:true},
402{input:"coth",  tag:"mo", output:"coth", tex:null, ttype:UNARY, func:true},
403{input:"sech",  tag:"mo", output:"sech", tex:null, ttype:UNARY, func:true},
404{input:"csch",  tag:"mo", output:"csch", tex:null, ttype:UNARY, func:true},
405{input:"exp",  tag:"mo", output:"exp", tex:null, ttype:UNARY, func:true},
406{input:"abs",   tag:"mo", output:"abs",  tex:null, ttype:UNARY, rewriteleftright:["|","|"]},
407{input:"norm",   tag:"mo", output:"norm",  tex:null, ttype:UNARY, rewriteleftright:["\u2225","\u2225"]},
408{input:"floor",   tag:"mo", output:"floor",  tex:null, ttype:UNARY, rewriteleftright:["\u230A","\u230B"]},
409{input:"ceil",   tag:"mo", output:"ceil",  tex:null, ttype:UNARY, rewriteleftright:["\u2308","\u2309"]},
410{input:"log",  tag:"mo", output:"log", tex:null, ttype:UNARY, func:true},
411{input:"ln",   tag:"mo", output:"ln",  tex:null, ttype:UNARY, func:true},
412{input:"det",  tag:"mo", output:"det", tex:null, ttype:UNARY, func:true},
413{input:"dim",  tag:"mo", output:"dim", tex:null, ttype:CONST},
414{input:"mod",  tag:"mo", output:"mod", tex:null, ttype:CONST},
415{input:"gcd",  tag:"mo", output:"gcd", tex:null, ttype:UNARY, func:true},
416{input:"lcm",  tag:"mo", output:"lcm", tex:null, ttype:UNARY, func:true},
417{input:"lub",  tag:"mo", output:"lub", tex:null, ttype:CONST},
418{input:"glb",  tag:"mo", output:"glb", tex:null, ttype:CONST},
419{input:"min",  tag:"mo", output:"min", tex:null, ttype:UNDEROVER},
420{input:"max",  tag:"mo", output:"max", tex:null, ttype:UNDEROVER},
421{input:"Sin",  tag:"mo", output:"Sin", tex:null, ttype:UNARY, func:true},
422{input:"Cos",  tag:"mo", output:"Cos", tex:null, ttype:UNARY, func:true},
423{input:"Tan",  tag:"mo", output:"Tan", tex:null, ttype:UNARY, func:true},
424{input:"Arcsin",  tag:"mo", output:"Arcsin", tex:null, ttype:UNARY, func:true},
425{input:"Arccos",  tag:"mo", output:"Arccos", tex:null, ttype:UNARY, func:true},
426{input:"Arctan",  tag:"mo", output:"Arctan", tex:null, ttype:UNARY, func:true},
427{input:"Sinh", tag:"mo", output:"Sinh", tex:null, ttype:UNARY, func:true},
428{input:"Cosh", tag:"mo", output:"Cosh", tex:null, ttype:UNARY, func:true},
429{input:"Tanh", tag:"mo", output:"Tanh", tex:null, ttype:UNARY, func:true},
430{input:"Cot",  tag:"mo", output:"Cot", tex:null, ttype:UNARY, func:true},
431{input:"Sec",  tag:"mo", output:"Sec", tex:null, ttype:UNARY, func:true},
432{input:"Csc",  tag:"mo", output:"Csc", tex:null, ttype:UNARY, func:true},
433{input:"Log",  tag:"mo", output:"Log", tex:null, ttype:UNARY, func:true},
434{input:"Ln",   tag:"mo", output:"Ln",  tex:null, ttype:UNARY, func:true},
435{input:"Abs",   tag:"mo", output:"abs",  tex:null, ttype:UNARY, notexcopy:true, rewriteleftright:["|","|"]},
436
437//arrows
438{input:"uarr", tag:"mo", output:"\u2191", tex:"uparrow", ttype:CONST},
439{input:"darr", tag:"mo", output:"\u2193", tex:"downarrow", ttype:CONST},
440{input:"rarr", tag:"mo", output:"\u2192", tex:"rightarrow", ttype:CONST},
441{input:"->",   tag:"mo", output:"\u2192", tex:"to", ttype:CONST},
442{input:">->",   tag:"mo", output:"\u21A3", tex:"rightarrowtail", ttype:CONST},
443{input:"->>",   tag:"mo", output:"\u21A0", tex:"twoheadrightarrow", ttype:CONST},
444{input:">->>",   tag:"mo", output:"\u2916", tex:"twoheadrightarrowtail", ttype:CONST},
445{input:"|->",  tag:"mo", output:"\u21A6", tex:"mapsto", ttype:CONST},
446{input:"larr", tag:"mo", output:"\u2190", tex:"leftarrow", ttype:CONST},
447{input:"harr", tag:"mo", output:"\u2194", tex:"leftrightarrow", ttype:CONST},
448{input:"rArr", tag:"mo", output:"\u21D2", tex:"Rightarrow", ttype:CONST},
449{input:"lArr", tag:"mo", output:"\u21D0", tex:"Leftarrow", ttype:CONST},
450{input:"hArr", tag:"mo", output:"\u21D4", tex:"Leftrightarrow", ttype:CONST},
451//commands with argument
452{input:"sqrt", tag:"msqrt", output:"sqrt", tex:null, ttype:UNARY},
453{input:"root", tag:"mroot", output:"root", tex:null, ttype:BINARY},
454{input:"frac", tag:"mfrac", output:"/",    tex:null, ttype:BINARY},
455{input:"/",    tag:"mfrac", output:"/",    tex:null, ttype:I
455NFIX},
456{input:"stackrel", tag:"mover", output:"stackrel", tex:null, ttype:BINARY},
457{input:"overset", tag:"mover", output:"stackrel", tex:null, ttype:BINARY},
458{input:"underset", tag:"munder", output:"stackrel", tex:null, ttype:BINARY},
459{input:"_",    tag:"msub",  output:"_",    tex:null, ttype:INFIX},
460{input:"^",    tag:"msup",  output:"^",    tex:null, ttype:INFIX},
461{input:"hat", tag:"mover", output:"\u005E", tex:null, ttype:UNARY, acc:true},
462{input:"bar", tag:"mover", output:"\u00AF", tex:"overline", ttype:UNARY, acc:true},
463{input:"vec", tag:"mover", output:"\u2192", tex:null, ttype:UNARY, acc:true},
464{input:"dot", tag:"mover", output:".",      tex:null, ttype:UNARY, acc:true},
465{input:"ddot", tag:"mover", output:"..",    tex:null, ttype:UNARY, acc:true},
466{input:"overarc", tag:"mover", output:"\u23DC", tex:"overparen", ttype:UNARY, acc:true},
467{input:"ul", tag:"munder", output:"\u0332", tex:"underline", ttype:UNARY, acc:true},
468{input:"ubrace", tag:"munder", output:"\u23DF", tex:"underbrace", ttype:UNARYUNDEROVER, acc:true},
469{input:"obrace", tag:"mover", output:"\u23DE", tex:"overbrace", ttype:UNARYUNDEROVER, acc:true},
470{input:"text", tag:"mtext", output:"text", tex:null, ttype:TEXT},
471{input:"mbox", tag:"mtext", output:"mbox", tex:null, ttype:TEXT},
472{input:"color", tag:"mstyle", ttype:BINARY},
473{input:"id", tag:"mrow", ttype:BINARY},
474{input:"class", tag:"mrow", ttype:BINARY},
475{input:"cancel", tag:"menclose", output:"cancel", tex:null, ttype:UNARY},
476AMquote,
477{input:"bb", tag:"mstyle", atname:"mathvariant", atval:"bold", output:"bb", tex:null, ttype:UNARY},
478{input:"mathbf", tag:"mstyle", atname:"mathvariant", atval:"bold", output:"mathbf", tex:null, ttype:UNARY},
479{input:"sf", tag:"mstyle", atname:"mathvariant", atval:"sans-serif", output:"sf", tex:null, ttype:UNARY},
480{input:"mathsf", tag:"mstyle", atname:"mathvariant", atval:"sans-serif", output:"mathsf", tex:null, ttype:UNARY},
481{input:"bbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"bbb", tex:null, ttype:UNARY, codes:AMbbb},
482{input:"mathbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"mathbb", tex:null, ttype:UNARY, codes:AMbbb},
483{input:"cc",  tag:"mstyle", atname:"mathvariant", atval:"script", output:"cc", tex:null, ttype:UNARY, codes:AMcal},
484{input:"mathcal", tag:"mstyle", atname:"mathvariant", atval:"script", output:"mathcal", tex:null, ttype:UNARY, codes:AMcal},
485{input:"tt",  tag:"mstyle", atname:"mathvariant", atval:"monospace", output:"tt", tex:null, ttype:UNARY},
486{input:"mathtt", tag:"mstyle", atname:"mathvariant", atval:"monospace", output:"mathtt", tex:null, ttype:UNARY},
487{input:"fr",  tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"fr", tex:null, ttype:UNARY, codes:AMfrk},
488{input:"mathfrak",  tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"mathfrak", tex:null, ttype:UNARY, codes:AMfrk}
489];
490
491function compareNames(s1,s2) {
492  if (s1.input > s2.input) return 1
493  else return -1;
494}
495
496var AMnames = []; //list of input symbols
497
498function initSymbols() {
499  var i;
500  var symlen = AMsymbols.length;
501  for (i=0; i<symlen; i++) {
502    if (AMsymbols[i].tex) {
503      AMsymbols.push({input:AMsymbols[i].tex,
504        tag:AMsymbols[i].tag, output:AMsymbols[i].output, ttype:AMsymbols[i].ttype,
505        acc:(AMsymbols[i].acc||false)});
506    }
507  }
508  refreshSymbols();
509}
510
511function refreshSymbols(){
512  var i;
513  AMsymbols.sort(compareNames);
514  for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input;
515}
516
517function define(oldstr,newstr) {
518  AMsymbols.push({input:oldstr, tag:"mo", output:newstr, tex:null, ttype:DEFINITION});
519  refreshSymbols(); // this may be a problem if many symbols are defined!
520}
521
522function AMremoveCharsAndBlanks(str,n) {
523//remove n characters and any following blanks
524  var st;
525  if (str.charAt(n)=="\\" && str.charAt(n+1)!="\\" && str.charAt(n+1)!=" ")
526    st = str.slice(n+1);
527  else st = str.slice(n);
528  for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);
529  return st.slice(i);
530}
531
532function position(arr, str, n) {
533// return position >=n where str appears or would be inserted
534// assumes arr is sorted
535  if (n==0) {
536    var h,m;
537    n = -1;
538    h = arr.length;
539    while (n+1<h) {
540      m = (n+h) >> 1;
541      if (arr[m]<str) n = m; else h = m;
542    }
543    return h;
544  } else
545    for (var i=n; i<arr.length && arr[i]<str; i++);
546  return i; // i=arr.length || arr[i]>=str
547}
548
549function AMgetSymbol(str) {
550//return maximal initial substring of str that appears in names
551//return null if there is none
552  var k = 0; //new pos
553  var j = 0; //old pos
554  var mk; //match pos
555  var st;
556  var tagst;
557  var match = "";
558  var more = true;
559  for (var i=1; i<=str.length && more; i++) {
560    st = str.slice(0,i); //initial substring of length i
561    j = k;
562    k = position(AMnames, st, j);
563    if (k<AMnames.length && str.slice(0,AMnames[k].length)==AMnames[k]){
564      match = AMnames[k];
565      mk = k;
566      i = match.length;
567    }
568    more = k<AMnames.length && str.slice(0,AMnames[k].length)>=AMnames[k];
569  }
570  AMpreviousSymbol=AMcurrentSymbol;
571  if (match!=""){
572    AMcurrentSymbol=AMsymbols[mk].ttype;
573    return AMsymbols[mk];
574  }
575// if str[0] is a digit or - return maxsubstring of digits.digits
576  AMcurrentSymbol=CONST;
577  k = 1;
578  st = str.slice(0,1);
579  var integ = true;
580  while ("0"<=st && st<="9" && k<=str.length) {
581    st = str.slice(k,k+1);
582    k++;
583  }
584  if (st == decimalsign) {
585    st = str.slice(k,k+1);
586    if ("0"<=st && st<="9") {
587      integ = false;
588      k++;
589      while ("0"<=st && st<="9" && k<=str.length) {
590        st = str.slice(k,k+1);
591        k++;
592      }
593    }
594  }
595  if ((integ && k>1) || k>2) {
596    st = str.slice(0,k-1);
597    tagst = "mn";
598  } else {
599    k = 2;
600    st = str.slice(0,1); //take 1 character
601    tagst = (("A">st || st>"Z") && ("a">st || st>"z")?"mo":"mi");
602  }
603  if (st=="-" && AMpreviousSymbol==INFIX) {
604    AMcurrentSymbol = INFIX;  //trick "/" into recognizing "-" on second parse
605    return {input:st, tag:tagst, output:st, ttype:UNARY, func:true};
606  }
607  return {input:st, tag:tagst, output:st, ttype:CONST};
608}
609
610function AMremoveBrackets(node) {
611  var st;
612  if (!node.hasChildNodes()) { return; }
613  if (node.firstChild.hasChildNodes() && (node.nodeName=="mrow" || node.nodeName=="M:MROW")) {
614    st = node.firstChild.firstChild.nodeValue;
615    if (st=="(" || st=="[" || st=="{") node.removeChild(node.firstChild);
616  }
617  if (node.lastChild.hasChildNodes() && (node.nodeName=="mrow" || node.nodeName=="M:MROW")) {
618    st = node.lastChild.firstChild.nodeValue;
619    if (st==")" || st=="]" || st=="}") node.removeChild(node.lastChild);
620  }
621}
622
623/*Parsing ASCII math expressions with the following grammar
624v ::= [A-Za-z] | greek letters | numbers | other constant symbols
625u ::= sqrt | text | bb | other unary symbols for font commands
626b ::= frac | root | stackrel         binary symbols
627l ::= ( | [ | { | (: | {:            left brackets
628r ::= ) | ] | } | :) | :}            right brackets
629S ::= v | lEr | uS | bSS             Simple expression
630I ::= S_S | S^S | S_S^S | S          Intermediate expression
631E ::= IE | I/I                       Expression
632Each terminal symbol is translated into a corresponding mathml node.*/
633
634var AMnestingDepth,AMpreviousSymbol,AMcurrentSymbol;
635
636function AMparseSexpr(str) { //parses str and returns [node,tailstr]
637  var symbol, node, result, i, st,// rightvert = false,
638    newFrag = document.createDocumentFragment();
639  str = AMremoveCharsAndBlanks(str,0);
640  symbol = AMgetSymbol(str);             //either a token or a bracket or empty
641  if (symbol == null || symbol.ttype == RIGHTBRACKET && AMnestingDepth > 0) {
642    return [null,str];
643  }
644  if (symbol.ttype == DEFINITION) {
645    str = symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length);
646    symbol = AMgetSymbol(str);
647  }
648  switch (symbol.ttype) {  case UNDEROVER:
649  case CONST:
650    str = AMremoveCharsAndBlanks(str,symbol.input.length);
651    return [createMmlNode(symbol.tag,        //its a constant
652                             document.createTextNode(symbol.output)),str];
653  case LEFTBRACKET:   //read (expr+)
654    AMnestingDepth++;
655    str = AMremoveCharsAndBlanks(str,symbol.input.length);
656    result = AMparseExpr(str,true);
657    AMnestingDepth--;
658    if (typeof symbol.invisible == "boolean" && symbol.invisible)
659      node = createMmlNode("mrow",result[0]);
660    else {
661      node = createMmlNode("mo",document.createTextNode(symbol.output));
662      node = createMmlNode("mrow",node);
663      node.appendChild(result[0]);
664    }
665    return [node,result[1]];
666  case TEXT:
667      if (symbol!=AMquote) str = AMremoveCharsAndBlanks(str,symbol.input.length);
668      if (str.charAt(0)=="{") i=str.indexOf("}");
669      else if (str.charAt(0)=="(") i=str.indexOf(")");
670      else if (str.charAt(0)=="[") i=str.indexOf("]");
671      else if (symbol==AMquote) i=str.slice(1).indexOf("\"")+1;
672      else i = 0;
673      if (i==-1) i = str.length;
674      st = str.slice(1,i);
675      if (st.charAt(0) == " ") {
676        node = createMmlNode("mspace");
677        node.setAttribute("width","1ex");
678        newFrag.appendChild(node);
679      }
680      newFrag.appendChild(
681        createMmlNode(symbol.tag,document.createTextNode(st)));
682      if (st.charAt(st.length-1) == " ") {
683        node = createMmlNode("mspace");
684        node.setAttribute("width","1ex");
685        newFrag.appendChild(node);
686      }
687      str = AMremoveCharsAndBlanks(str,i+1);
688      return [createMmlNode("mrow",newFrag),str];
689  case UNARYUNDEROVER:
690  case UNARY:
691      str = AMremoveCharsAndBlanks(str,symbol.input.length);
692      result = AMparseSexpr(str);
693      if (result[0]==null) return [createMmlNode(symbol.tag,
694                             document.createTextNode(symbol.output)),str];
695      if (typeof symbol.func == "boolean" && symbol.func) { // functions hack
696        st = str.charAt(0);
697          if (st=="^" || st=="_" || st=="/" || st=="|" || st=="," ||
698             (symbol.input.length==1 && symbol.input.match(/\w/) && st!="(")) {
699          return [createMmlNode(symbol.tag,
700                    document.createTextNode(symbol.output)),str];
701        } else {
702          node = createMmlNode("mrow",
703           createMmlNode(symbol.tag,document.createTextNode(symbol.output)));
704          node.appendChild(result[0]);
705          return [node,result[1]];
706        }
707      }
708      AMremoveBrackets(result[0]);
709      if (symbol.input == "sqrt") {           // sqrt
710        return [createMmlNode(symbol.tag,result[0]),result[1]];
711      } else if (typeof symbol.rewriteleftright != "undefined") {    // abs, floor, ceil
712          node = createMmlNode("mrow", createMmlNode("mo",document.createTextNode(symbol.rewriteleftright[0])));
713          node.appendChild(result[0]);
714          node.appendChild(createMmlNode("mo",document.createTextNode(symbol.rewriteleftright[1])));
715          return [node,result[1]];
716      } else if (symbol.input == "cancel") {   // cancel
717        node = createMmlNode(symbol.tag,result[0]);
718	node.setAttribute("notation","updiagonalstrike");
719	return [node,result[1]];
720      } else if (typeof symbol.acc == "boolean" && symbol.acc) {   // accent
721        node = createMmlNode(symbol.tag,result[0]);
722        var accnode = createMmlNode("mo",document.createTextNode(symbol.output));
723        if (symbol.input=="vec" && (
724		(result[0].nodeName=="mrow" && result[0].childNodes.length==1
725			&& result[0].firstChild.firstChild.nodeValue !== null
726			&& result[0].firstChild.firstChild.nodeValue.length==1) ||
727		(result[0].firstChild.nodeValue !== null
728			&& result[0].firstChild.nodeValue.length==1) )) {
729			accnode.setAttribute("stretchy",false);
730        }
731        node.appendChild(accnode);
732        return [node,result[1]];
733      } else {                        // font change command
734        if (!isIE && typeof symbol.codes != "undefined") {
735          for (i=0; i<result[0].childNodes.length; i++)
736            if (result[0].childNodes[i].nodeName=="mi" || result[0].nodeName=="mi") {
737              st = (result[0].nodeName=="mi"?result[0].firstChild.nodeValue:
738                              result[0].childNodes[i].firstChild.nodeValue);
739              var newst = [];
740              for (var j=0; j<st.length; j++)
741		  if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91)
742		  	newst = newst + symbol.codes[st.charCodeAt(j)-65];
743                else if (st.charCodeAt(j)>96 && st.charCodeAt(j)<123)
744                	newst = newst + symbol.codes[st.charCodeAt(j)-71];
745                else newst = newst + st.charAt(j);
746              if (result[0].nodeName=="mi")
747                result[0]=createMmlNode("mo").
748                          appendChild(document.createTextNode(newst));
749              else result[0].replaceChild(createMmlNode("mo").
750                               appendChild(document.createTextNode(newst)),
751                                           result[0].childNodes[i]);
752            }
753        }
754        node = createMmlNode(symbol.tag,result[0]);
755        node.setAttribute(symbol.atname,symbol.atval);
756        return [node,result[1]];
757      }
758  case BINARY:
759    str = AMremoveCharsAndBlanks(str,symbol.input.length);
760    result = AMparseSexpr(str);
761    if (result[0]==null) return [createMmlNode("mo",
762                           document.createTextNode(symbol.input)),str];
763    AMremoveBrackets(result[0]);
764    var result2 = AMparseSexpr(result[1]);
765    if (result2[0]==null) return [createMmlNode("mo",
766                           document.createTextNode(symbol.input)),str];
767    AMremoveBrackets(result2[0]);
768    if (['color', 'class', 'id'].indexOf(symbol.input) >= 0) {
769
770      // Get the second argument
771    	if (str.charAt(0)=="{") i=str.indexOf("}");
772      else if (str.charAt(0)=="(") i=str.indexOf(")");
773      else if (str.charAt(0)=="[") i=str.indexOf("]");
774    	st = str.slice(1,i);
775
776      // Make a mathml node
777    	node = createMmlNode(symbol.tag,result2[0]);
778
779      // Set the correct attribute
780      if (symbol.input === "color") node.setAttribute("mathcolor", st)
781      else if (symbol.input === "class") node.setAttribute("class", st)
782      else if (symbol.input === "id") node.setAttribute("id", st)
783    	return [node,result2[1]];
784    }
785    if (symbol.input=="root" || symbol.output=="stackrel")
786      newFrag.appendChild(result2[0]);
787    newFrag.appendChild(result[0]);
788    if (symbol.input=="frac") newFrag.appendChild(result2[0]);
789    return [createMmlNode(symbol.tag,newFrag),result2[1]];
790  case INFIX:
791    str = AMremoveCharsAndBlanks(str,symbol.input.length);
792    return [createMmlNode("mo",document.createTextNode(symbol.output)),str];
793  case SPACE:
794    str = AMremoveCharsAndBlanks(str,symbol.input.length);
795    node = createMmlNode("mspace");
796    node.setAttribute("width","1ex");
797    newFrag.appendChild(node);
798    newFrag.appendChild(
799      createMmlNode(symbol.tag,document.createTextNode(symbol.output)));
800    node = createMmlNode("mspace");
801    node.setAttribute("width","1ex");
802    newFrag.appendChild(node);
803    return [createMmlNode("mrow",newFrag),str];
804  case LEFTRIGHT:
805//    if (rightvert) return [null,str]; else rightvert = true;
806    AMnestingDepth++;
807    str = AMremoveCharsAndBlanks(str,symbol.input.length);
808    result = AMparseExpr(str,false);
809    AMnestingDepth--;
810    st = "";
811    if (result[0].lastChild!=null)
812      st = result[0].lastChild.firstChild.nodeValue;
813    if (st == "|" && str.charAt(0)!==",") { // its an absolute value subterm
814      node = createMmlNode("mo",document.createTextNode(symbol.output));
815      node = createMmlNode("mrow",node);
816      node.appendChild(result[0]);
817      return [node,result[1]];
818    } else { // the "|" is a \mid so use unicode 2223 (divides) for spacing
819      node = createMmlNode("mo",document.createTextNode("\u2223"));
820      node = createMmlNode("mrow",node);
821      return [node,str];
822    }
823  default:
824//alert("default");
825    str = AMremoveCharsAndBlanks(str,symbol.input.length);
826    return [createMmlNode(symbol.tag,        //its a constant
827                             document.createTextNode(symbol.output)),str];
828  }
829}
830
831function AMparseIexpr(str) {
832  var symbol, sym1, sym2, node, result, underover;
833  str = AMremoveCharsAndBlanks(str,0);
834  sym1 = AMgetSymbol(str);
835  result = AMparseSexpr(str);
836  node = result[0];
837  str = result[1];
838  symbol = AMgetSymbol(str);
839  if (symbol.ttype == INFIX && symbol.input != "/") {
840    str = AMremoveCharsAndBlanks(str,symbol.input.length);
841//    if (symbol.input == "/") result = AMparseIexpr(str); else ...
842    result = AMparseSexpr(str);
843    if (result[0] == null) // show box in place of missing argument
844      result[0] = createMmlNode("mo",document.createTextNode("\u25A1"));
845    else AMremoveBrackets(result[0]);
846    str = result[1];
847//    if (symbol.input == "/") AMremoveBrackets(node);
848    underover = (sym1.ttype == UNDEROVER || sym1.ttype == UNARYUNDEROVER);
849    if (symbol.input == "_") {
850      sym2 = AMgetSymbol(str);
851      if (sym2.input == "^") {
852        str = AMremoveCharsAndBlanks(str,sym2.input.length);
853        var res2 = AMparseSexpr(str);
854        AMremoveBrackets(res2[0]);
855        str = res2[1];
856        node = createMmlNode((underover?"munderover":"msubsup"),node);
857        node.appendChild(result[0]);
858        node.appendChild(res2[0]);
859        node = createMmlNode("mrow",node); // so sum does not stretch
860      } else {
861        node = createMmlNode((underover?"munder":"msub"),node);
862        node.appendChild(result[0]);
863      }
864    } else if (symbol.input == "^" && underover) {
865    	node = createMmlNode("mover",node);
866        node.appendChild(result[0]);
867    } else {
868      node = createMmlNode(symbol.tag,node);
869      node.appendChild(result[0]);
870    }
871    if (typeof sym1.func != 'undefined' && sym1.func) {
872    	sym2 = AMgetSymbol(str);
873    	if (sym2.ttype != INFIX && sym2.ttype != RIGHTBRACKET &&
874    	    (sym1.input.length>1 || sym2.ttype == LEFTBRACKET)) {
875    		result = AMparseIexpr(str);
876    		node = createMmlNode("mrow",node);
877    		node.appendChild(result[0]);
878    		str = result[1];
879    	}
880    }
881  }
882  return [node,str];
883}
884
885function AMparseExpr(str,rightbracket) {
886  var symbol, node, result, i,
887  newFrag = document.createDocumentFragment();
888  do {
889    str = AMremoveCharsAndBlanks(str,0);
890    result = AMparseIexpr(str);
891    node = result[0];
892    str = result[1];
893    symbol = AMgetSymbol(str);
894    if (symbol.ttype == INFIX && symbol.input == "/") {
895      str = AMremoveCharsAndBlanks(str,symbol.input.length);
896      result = AMparseIexpr(str);
897      if (result[0] == null) // show box in place of missing argument
898        result[0] = createMmlNode("mo",document.createTextNode("\u25A1"));
899      else AMremoveBrackets(result[0]);
900      str = result[1];
901      AMremoveBrackets(node);
902      node = createMmlNode(symbol.tag,node);
903      node.appendChild(result[0]);
904      newFrag.appendChild(node);
905      symbol = AMgetSymbol(str);
906    }
907    else if (node!=undefined) newFrag.appendChild(node);
908  } while ((symbol.ttype != RIGHTBRACKET &&
909           (symbol.ttype != LEFTRIGHT || rightbracket)
910           || AMnestingDepth == 0) && symbol!=null && symbol.output!="");
911  if (symbol.ttype == RIGHTBRACKET || symbol.ttype == LEFTRIGHT) {
912//    if (AMnestingDepth > 0) AMnestingDepth--;
913    var len = newFrag.childNodes.length;
914    if (len>0 && newFrag.childNodes[len-1].nodeName == "mrow"
915    	    && newFrag.childNodes[len-1].lastChild
916    	    && newFrag.childNodes[len-1].lastChild.firstChild ) { //matrix
917    	    //removed to allow row vectors: //&& len>1 &&
918    	    //newFrag.childNodes[len-2].nodeName == "mo" &&
919    	    //newFrag.childNodes[len-2].firstChild.nodeValue == ","
920      var right = newFrag.childNodes[len-1].lastChild.firstChild.nodeValue;
921      if (right==")" || right=="]") {
922        var left = newFrag.childNodes[len-1].firstChild.firstChild.nodeValue;
923        if (left=="(" && right==")" && symbol.output != "}" ||
924            left=="[" && right=="]") {
925        var pos = []; // positions of commas
926        var matrix = true;
927        var m = newFrag.childNodes.length;
928        for (i=0; matrix && i<m; i=i+2) {
929          pos[i] = [];
930          node = newFrag.childNodes[i];
931          if (matrix) matrix = node.nodeName=="mrow" &&
932            (i==m-1 || node.nextSibling.nodeName=="mo" &&
933            node.nextSibling.firstChild.nodeValue==",")&&
934            node.firstChild.firstChild.nodeValue==left &&
935            node.lastChild.firstChild.nodeValue==right;
936          if (matrix)
937            for (var j=0; j<node.childNodes.length; j++)
938              if (node.childNodes[j].firstChild.nodeValue==",")
939                pos[i][pos[i].length]=j;
940          if (matrix && i>1) matrix = pos[i].length == pos[i-2].length;
941        }
942        matrix = matrix && (pos.length>1 || pos[0].length>0);
943        var columnlines = [];
944        if (matrix) {
945          var row, frag, n, k, table = document.createDocumentFragment();
946          for (i=0; i<m; i=i+2) {
947            row = document.createDocumentFragment();
948            frag = document.createDocumentFragment();
949            node = newFrag.firstChild; // <mrow>(-,-,...,-,-)</mrow>
950            n = node.childNodes.length;
951            k = 0;
952            node.removeChild(node.firstChild); //remove (
953            for (j=1; j<n-1; j++) {
954              if (typeof pos[i][k] != "undefined" && j==pos[i][k]){
955                node.removeChild(node.firstChild); //remove ,
956                if (node.firstChild.nodeName=="mrow" && node.firstChild.childNodes.length==1 &&
957         	  node.firstChild.firstChild.firstChild.nodeValue=="\u2223") {
958         	    //is columnline marker - skip it
959         	    if (i==0) { columnlines.push("solid"); }
960         	    node.removeChild(node.firstChild); //remove mrow
961         	    node.removeChild(node.firstChild); //remove ,
962         	    j+=2;
963         	    k++;
964            	} else if (i==0) { columnlines.push("none"); }
965                row.appendChild(createMmlNode("mtd",frag));
966                k++;
967              } else frag.appendChild(node.firstChild);
968            }
969            row.appendChild(createMmlNode("mtd",frag));
970            if (i==0) { columnlines.push("none"); }
971            if (newFrag.childNodes.length>2) {
972              newFrag.removeChild(newFrag.firstChild); //remove <mrow>)</mrow>
973              newFrag.removeChild(newFrag.firstChild); //remove <mo>,</mo>
974            }
975            table.appendChild(createMmlNode("mtr",row));
976          }
977          node = createMmlNode("mtable",table);
978          node.setAttribute("columnlines", columnlines.join(" "));
979          if (typeof symbol.invisible == "boolean" && symbol.invisible) node.setAttribute("columnalign","left");
980          newFrag.replaceChild(node,newFrag.firstChild);
981        }
982       }
983      }
984    }
985    str = AMremoveCharsAndBlanks(str,symbol.input.length);
986    if (typeof symbol.invisible != "boolean" || !symbol.invisible) {
987      node = createMmlNode("mo",document.createTextNode(symbol.output));
988      newFrag.appendChild(node);
989    }
990  }
991  return [newFrag,str];
992}
993
994function parseMath(str,latex) {
995  var frag, node;
996  AMnestingDepth = 0;
997  //some basic cleanup for dealing with stuff editors like TinyMCE adds
998  str = str.replace(/&nbsp;/g,"");
999  str = str.replace(/&gt;/g,">");
1000  str = str.replace(/&lt;/g,"<");
1001  frag = AMparseExpr(str.replace(/^\s+/g,""),false)[0];
1002  node = createMmlNode("mstyle",frag);
1003  if (mathcolor != "") node.setAttribute("mathcolor",mathcolor);
1004  if (mathfontsize != "") {
1005	  node.setAttribute("fontsize", mathfontsize);
1006	  node.setAttribute("mathsize", mathfontsize);
1007  }
1008  if (mathfontfamily != "") {
1009	  node.setAttribute("fontfamily", mathfontfamily);
1010	  node.setAttribute("mathvariant", mathfontfamily);
1011  }
1012
1013  if (displaystyle) node.setAttribute("displaystyle","true");
1014  node = createMmlNode("math",node);
1015  if (showasciiformulaonhover)                      //fixed by djhsu so newline
1016    node.setAttribute("title",str.replace(/\s+/g," "));//does not show in Gecko
1017  return node;
1018}
1019
1020function strarr2docFrag(arr, linebreaks, latex) {
1021  var newFrag=document.createDocumentFragment();
1022  var expr = false;
1023  for (var i=0; i<arr.length; i++) {
1024    if (expr) newFrag.appendChild(parseMath(arr[i],latex));
1025    else {
1026      var arri = (linebreaks ? arr[i].split("\n\n") : [arr[i]]);
1027      newFrag.appendChild(createElementXHTML("span").
1028      appendChild(document.createTextNode(arri[0])));
1029      for (var j=1; j<arri.length; j++) {
1030        newFrag.appendChild(createElementXHTML("p"));
1031        newFrag.appendChild(createElementXHTML("span").
1032        appendChild(document.createTextNode(arri[j])));
1033      }
1034    }
1035    expr = !expr;
1036  }
1037  return newFrag;
1038}
1039
1040function AMautomathrec(str) {
1041//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.
1042//tokens are single letters (except a, A, I) and ASCIIMathML tokens
1043  var texcommand = "\\\\[a-zA-Z]+|\\\\\\s|";
1044  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])|";
1045  var englishAMtoken = "\\b(?:sum|ox|log|sin|tan|dim|hat|bar|dot)(?![a-z])|";
1046  var secondenglishAMtoken = "|\\bI\\b|\\bin\\b|\\btext\\b"; // took if and or not out
1047  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?
1048  var letter = "[a-zA-HJ-Z](?=(?:[^a-zA-Z]|$|"+ambigAMtoken+englishAMtoken+simpleAMtoken+"))|";
1049  var token = letter+texcommand+"\\d+|[-()[\\]{}+=*&^_%\\\@/<>,\\|!:;'~]|\\.(?!(?:\x20|$))|"+ambigAMtoken+englishAMtoken+simpleAMtoken;
1050  var re = new RegExp("(^|\\s)((("+token+")\\s?)(("+token+secondenglishAMtoken+")\\s?)+)([,.?]?(?=\\s|$))","g");
1051  str = str.replace(re," `$2`$7");
1052  var arr = str.split(AMdelimiter1);
1053  var re1 = new RegExp("(^|\\s)([b-zB-HJ-Z+*<>]|"+texcommand+ambigAMtoken+simpleAMtoken+")(\\s|\\n|$)","g");
1054  var re2 = new RegExp("(^|\\s)([a-z]|"+texcommand+ambigAMtoken+simpleAMtoken+")([,.])","g"); // removed |\d+ for now
1055  for (i=0; i<arr.length; i++)   //single nonenglish tokens
1056    if (i%2==0) {
1057      arr[i] = arr[i].replace(re1," `$2`$3");
1058      arr[i] = arr[i].replace(re2," `$2`$3");
1059      arr[i] = arr[i].replace(/([{}[\]])/,"`$1`");
1060    }
1061  str = arr.join(AMdelimiter1);
1062  str = str.replace(/((^|\s)\([a-zA-Z]{2,}.*?)\)`/g,"$1`)");  //fix parentheses
1063  str = str.replace(/`(\((a\s|in\s))(.*?[a-zA-Z]{2,}\))/g,"$1`$3");  //fix parentheses
1064  str = str.replace(/\sin`/g,"` in");
1065  str = str.replace(/`(\(\w\)[,.]?(\s|\n|$))/g,"$1`");
1066  str = str.replace(/`([0-9.]+|e.g|i.e)`(\.?)/gi,"$1$2");
1067  str = str.replace(/`([0-9.]+:)`/g,"$1");
1068  return str;
1069}
1070
1071function processNodeR(n, linebreaks,latex) {
1072  var mtch, str, arr, frg, i;
1073  if (n.childNodes.length == 0) {
1074   if ((n.nodeType!=8 || linebreaks) &&
1075    n.parentNode.nodeName!="form" && n.parentNode.nodeName!="FORM" &&
1076    n.parentNode.nodeName!="textarea" && n.parentNode.nodeName!="TEXTAREA" /*&&
1077    n.parentNode.nodeName!="pre" && n.parentNode.nodeName!="PRE"*/) {
1078    str = n.nodeValue;
1079    if (!(str == null)) {
1080      str = str.replace(/\r\n\r\n/g,"\n\n");
1081      str = str.replace(/\x20+/g," ");
1082      str = str.replace(/\s*\r\n/g," ");
1083      if(latex) {
1084// DELIMITERS:
1085        mtch = (str.indexOf("\$")==-1 ? false : true);
1086        str = str.replace(/([^\\])\$/g,"$1 \$");
1087        str = str.replace(/^\$/," \$");	// in case \$ at start of string
1088        arr = str.split(" \$");
1089        for (i=0; i<arr.length; i++)
1090	  arr[i]=arr[i].replace(/\\\$/g,"\$");
1091      } else {
1092      mtch = false;
1093      str = str.replace(new RegExp(AMescape1, "g"),
1094              function(){mtch = true; return "AMescape1"});
1095      str = str.replace(/\\?end{?a?math}?/i,
1096              function(){automathrecognize = false; mtch = true; return ""});
1097      str = str.replace(/amath\b|\\begin{a?math}/i,
1098              function(){automathrecognize = true; mtch = true; return ""});
1099      arr = str.split(AMdelimiter1);
1100      if (automathrecognize)
1101        for (i=0; i<arr.length; i++)
1102          if (i%2==0) arr[i] = AMautomathrec(arr[i]);
1103      str = arr.join(AMdelimiter1);
1104      arr = str.split(AMdelimiter1);
1105      for (i=0; i<arr.length; i++) // this is a problem ************
1106        arr[i]=arr[i].replace(/AMescape1/g,AMdelimiter1);
1107      }
1108      if (arr.length>1 || mtch) {
1109        if (!noMathML) {
1110          frg = strarr2docFrag(arr,n.nodeType==8,latex);
1111          var len = frg.childNodes.length;
1112          n.parentNode.replaceChild(frg,n);
1113          return len-1;
1114        } else return 0;
1115      }
1116    }
1117   } else return 0;
1118  } else if (n.nodeName!="math") {
1119    for (i=0; i<n.childNodes.length; i++)
1120      i += processNodeR(n.childNodes[i], linebreaks,latex);
1121  }
1122  return 0;
1123}
1124
1125function AMprocessNode(n, linebreaks, spanclassAM) {
1126  var frag,st;
1127  if (spanclassAM!=null) {
1128    frag = document.getElementsByTagName("span")
1129    for (var i=0;i<frag.length;i++)
1130      if (frag[i].className == "AM")
1131        processNodeR(frag[i],linebreaks,false);
1132  } else {
1133    try {
1134      st = n.innerHTML; // look for AMdelimiter on page
1135    } catch(err) {}
1136//alert(st)
1137    if (st==null || /amath\b|\\begin{a?math}/i.test(st) ||
1138      st.indexOf(AMdelimiter1+" ")!=-1 || st.slice(-1)==AMdelimiter1 ||
1139      st.indexOf(AMdelimiter1+"<")!=-1 || st.indexOf(AMdelimiter1+"\n")!=-1) {
1140      processNodeR(n,linebreaks,false);
1141    }
1142  }
1143}
1144
1145function generic(){
1146  if(!init()) return;
1147  if (translateOnLoad) {
1148      translate();
1149  }
1150};
1151//setup onload function
1152if(typeof window.addEventListener != 'undefined'){
1153  //.. gecko, safari, konqueror and standard
1154  window.addEventListener('load', generic, false);
1155}
1156else if(typeof document.addEventListener != 'undefined'){
1157  //.. opera 7
1158  document.addEventListener('load', generic, false);
1159}
1160else if(typeof window.attachEvent != 'undefined'){
1161  //.. win/ie
1162  window.attachEvent('onload', generic);
1163}else{
1164  //.. mac/ie5 and anything else that gets this far
1165  //if there's an existing onload function
1166  if(typeof window.onload == 'function'){
1167    //store it
1168    var existing = onload;
1169    //add new onload handler
1170    window.onload = function(){
1171      //call existing onload function
1172      existing();
1173      //call generic onload function
1174      generic();
1175    };
1176  }else{
1177    window.onload = generic;
1178  }
1179}
1180
1181//expose some functions to outside
1182asciimath.newcommand = newcommand;
1183asciimath.newsymbol = newsymbol;
1184asciimath.AMprocesssNode = AMprocessNode;
1185asciimath.parseMath = parseMath;
1186asciimath.translate = translate;
1187})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.