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 78 document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd"," <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(/ /g,""); 999 str = str.replace(/>/g,">"); 1000 str = str.replace(/</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.