www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

jax.js (66432B)


      1 /* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 
      4 /*************************************************************
      5  *
      6  *  MathJax/jax/input/AsciiMath/jax.js
      7  *  
      8  *  An Input Jax for AsciiMath notation 
      9  *  (see http://www1.chapman.edu/~jipsen/mathml/asciimath.html).
     10  *  
     11  *  Originally adapted for MathJax by David Lippman.
     12  *  Additional work done by Davide P. Cervone.
     13  *  
     14  *  The current development repository for AsciiMathML is
     15  *      https://github.com/mathjax/asciimathml
     16  *  
     17  *  A portion of this file is taken from
     18  *  ASCIIMathML.js Version 2.2 Mar 3, 2014, (c) Peter Jipsen http://www.chapman.edu/~jipsen
     19  *  and is used by permission of Peter Jipsen, who has agreed to allow us to
     20  *  release it under the Apache2 license (see below).  That portion is indicated
     21  *  via comments.
     22  *  
     23  *  The remainder falls under the copyright that follows.
     24  *  
     25  *  ---------------------------------------------------------------------
     26  *  
     27  *  Copyright (c) 2012-2015 The MathJax Consortium
     28  * 
     29  *  Licensed under the Apache License, Version 2.0 (the "License");
     30  *  you may not use this file except in compliance with the License.
     31  *  You may obtain a copy of the License at
     32  * 
     33  *      http://www.apache.org/licenses/LICENSE-2.0
     34  * 
     35  *  Unless required by applicable law or agreed to in writing, software
     36  *  distributed under the License is distributed on an "AS IS" BASIS,
     37  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     38  *  See the License for the specific language governing permissions and
     39  *  limitations under the License.
     40  */
     41 
     42 (function (ASCIIMATH) {
     43 
     44   var MML;  // Filled in later
     45 
     46   //
     47   //  Make a documentFragment work-alike that uses MML objects
     48   //  rather than DOM objects.
     49   //
     50   var DOCFRAG = MathJax.Object.Subclass({
     51     firstChild: null,
     52     lastChild: null,
     53     Init: function () {
     54       this.childNodes = [];
     55     },
     56     appendChild: function (node) {
     57       if (node.parent) {node.parent.removeChild(node)}
     58       if (this.lastChild) {this.lastChild.nextSibling = node}
     59       if (!this.firstChild) {this.firstChild = node}
     60       this.childNodes.push(node); node.parent = this;
     61       this.lastChild = node;
     62       return node;
     63     },
     64     removeChild: function (node) {
     65       for (var i = 0, m = this.childNodes.length; i < m; i++)
     66         {if (this.childNodes[i] === node) break}
     67       if (i === m) return;
     68       this.childNodes.splice(i,1);
     69       if (node === this.firstChild) {this.firstChild = node.nextSibling}
     70       if (node === this.lastChild) {
     71         if (!this.childNodes.length) {this.lastChild = null}
     72           else {this.lastChild = this.childNodes[this.childNodes.length-1]}
     73       }
     74       if (i) {this.childNodes[i-1].nextSibling = node.nextSibling}
     75       node.nextSibling = node.parent = null;
     76       return node;
     77     },
     78     replaceChild: function (node,old) {
     79       for (var i = 0, m = this.childNodes.length; i < m; i++)
     80         {if (this.childNodes[i] === old) break}
     81       if (i) {this.childNodes[i-1].nextSibling = node} else {this.firstChild = node}
     82       if (i >= m-1) {this.lastChild = node}
     83       this.childNodes[i] = node; node.nextSibling = old.nextSibling;
     84       old.nextSibling = old.parent = null;
     85       return old;
     86     },
     87     hasChildNodes: function (node) {
     88       return (this.childNodes.length>0);	    
     89     },
     90     toString: function () {return "{"+this.childNodes.join("")+"}"}
     91   });
     92   
     93   var INITASCIIMATH = function () {
     94     MML = MathJax.ElementJax.mml;
     95     var MBASEINIT = MML.mbase.prototype.Init;
     96     
     97     //
     98     //  Make MML elements looks like DOM elements (add the
     99     //  methods that AsciiMath needs)
    100     //
    101     MML.mbase.Augment({
    102       firstChild: null,
    103       lastChild: null,
    104       nodeValue: null,
    105       nextSibling: null,
    106       Init: function () {
    107         var obj = MBASEINIT.apply(this,arguments) || this;
    108         obj.childNodes = obj.data;
    109         obj.nodeName = obj.type;
    110         return obj;
    111       },
    112       appendChild: function (node) {
    113         if (node.parent) {node.parent.removeChild(node)}
    114         var nodes = arguments;
    115         if (node.isa(DOCFRAG)) {
    116           nodes = node.childNodes;
    117           node.data = node.childNodes = [];
    118           node.firstChild = node.lastChild = null;
    119         }
    120         for (var i = 0, m = nodes.length; i < m; i++) {
    121           node = nodes[i];
    122           if (this.lastChild) {this.lastChild.nextSibling = node}
    123           if (!this.firstChild) {this.firstChild = node}
    124           this.Append(node);
    125           this.lastChild = node;
    126         }
    127         return node;
    128       },
    129       removeChild: function (node) {
    130         for (var i = 0, m = this.childNodes.length; i < m; i++)
    131           {if (this.childNodes[i] === node) break}
    132         if (i === m) return;
    133         this.childNodes.splice(i,1);
    134         if (node === this.firstChild) {this.firstChild = node.nextSibling}
    135         if (node === this.lastChild) {
    136           if (!this.childNodes.length) {this.lastChild = null}
    137             else {this.lastChild = this.childNodes[this.childNodes.length-1]}
    138         }
    139         if (i) {this.childNodes[i-1].nextSibling = node.nextSibling}
    140         node.nextSibling = node.parent = null;
    141         return node;
    142       },
    143       replaceChild: function (node,old) {
    144         for (var i = 0, m = this.childNodes.length; i < m; i++)
    145           {if (this.childNodes[i] === old) break}
    146         // FIXME:  make this work with DOCFRAG's?
    147         if (i) {this.childNodes[i-1].nextSibling = node} else {this.firstChild = node}
    148         if (i >= m-1) {this.lastChild = node}
    149         this.SetData(i,node); node.nextSibling = old.nextSibling;
    150         old.nextSibling = old.parent = null;
    151         return old;
    152       },
    153       hasChildNodes: function (node) {
    154         return (this.childNodes.length>0);	    
    155       },
    156       setAttribute: function (name,value) {this[name] = value}
    157     });
    158   };
    159   
    160   //
    161   //  Set up to isolate ASCIIMathML.js
    162   //
    163   
    164   var window = {};  // hide the true window
    165   
    166   //
    167   //  Hide the true document, and add functions that
    168   //  use and produce MML objects instead of DOM objects
    169   //
    170   var document = {
    171     getElementById: true,
    172     createElementNS: function (ns,type) {
    173       var node = MML[type]();
    174       if (type === "mo" && ASCIIMATH.config.useMathMLspacing) {node.useMMLspacing = 0x80}
    175       return node;
    176     },
    177     createTextNode: function (text) {return MML.chars(text).With({nodeValue:text})},
    178     createDocumentFragment: function () {return DOCFRAG()}
    179   };
    180   
    181   var navigator = {appName: "MathJax"};  // hide the true navigator object
    182   
    183   var i; // avoid global variable used in code below
    184   
    185 /******************************************************************
    186  *
    187  *   The following section is ASCIIMathML.js Version 2.2
    188  *   (c) Peter Jipsen, used with permission.
    189  *   
    190  *   Some sections are commented out to save space in the
    191  *   minified version (but that is not strictly necessary).
    192  *   
    193  ******************************************************************/
    194 
    195 /*
    196 ASCIIMathML.js
    197 ==============
    198 This file contains JavaScript functions to convert ASCII math notation
    199 and (some) LaTeX to Presentation MathML. The conversion is done while the 
    200 HTML page loads, and should work with Firefox and other browsers that can
    201 render MathML.
    202 
    203 Just add the next line to your HTML page with this file in the same folder:
    204 
    205 <script type="text/javascript" src="ASCIIMathML.js"></script>
    206 
    207 Version 2.2 Mar 3, 2014.
    208 Latest version at https://github.com/mathjax/asciimathml
    209 If you use it on a webpage, please send the URL to jipsen@chapman.edu
    210 
    211 Copyright (c) 2014 Peter Jipsen and other ASCIIMathML.js contributors
    212 
    213 Permission is hereby granted, free of charge, to any person obtaining a copy
    214 of this software and associated documentation files (the "Software"), to deal
    215 in the Software without restriction, including without limitation the rights
    216 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    217 copies of the Software, and to permit persons to whom the Software is
    218 furnished to do so, subject to the following conditions:
    219 
    220 The above copyright notice and this permission notice shall be included in
    221 all copies or substantial portions of the Software.
    222 
    223 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    224 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    225 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    226 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    227 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    228 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    229 THE SOFTWARE.
    230 */
    231 //var asciimath = {};
    232 
    233 //(function(){
    234 var mathcolor = "blue";        // change it to "" (to inherit) or another color
    235 //var mathfontsize = "1em";      // change to e.g. 1.2em for larger math
    236 var mathfontfamily = "serif";  // change to "" to inherit (works in IE) 
    237                                // or another family (e.g. "arial")
    238 //var automathrecognize = false; // writing "amath" on page makes this true
    239 //var checkForMathML = true;     // check if browser can display MathML
    240 //var notifyIfNoMathML = true;   // display note at top if no MathML capability
    241 //var alertIfNoMathML = false;   // show alert box if no MathML capability
    242 //var translateOnLoad = true;    // set to false to do call translators from js 
    243 //var translateASCIIMath = true; // false to preserve `..`
    244 var displaystyle = true;      // puts limits above and below large operators
    245 var showasciiformulaonhover = true; // helps students learn ASCIIMath
    246 var decimalsign = ".";        // change to "," if you like, beware of `(1,2)`!
    247 //var AMdelimiter1 = "`", AMescape1 = "\\\\`"; // can use other characters
    248 //var AMdocumentId = "wikitext" // PmWiki element containing math (default=body)
    249 var fixphi = true;  		//false to return to legacy phi/varphi mapping
    250 
    251 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    252 
    253 var isIE = (navigator.appName.slice(0,9)=="Microsoft");
    254 /*
    255 var noMathML = false, translated = false;
    256 
    257 if (isIE) { // add MathPlayer info to IE webpages
    258   document.write("<object id=\"mathplayer\"\
    259   classid=\"clsid:32F66A20-7614-11D4-BD11-00104BD3F987\"></object>");
    260   document.write("<?import namespace=\"m\" implementation=\"#mathplayer\"?>");
    261 }
    262 
    263 // Add a stylesheet, replacing any previous custom stylesheet (adapted from TW)
    264 function setStylesheet(s) {
    265 	var id = "AMMLcustomStyleSheet";
    266 	var n = document.getElementById(id);
    267 	if(document.createStyleSheet) {
    268 		// Test for IE's non-standard createStyleSheet method
    269 		if(n)
    270 			n.parentNode.removeChild(n);
    271 		// This failed without the &nbsp;
    272 		document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeEnd","&nbsp;<style id='" + id + "'>" + s + "</style>");
    273 	} else {
    274 		if(n) {
    275 			n.replaceChild(document.createTextNode(s),n.firstChild);
    276 		} else {
    277 			n = document.createElement("style");
    278 			n.type = "text/css";
    279 			n.id = id;
    280 			n.appendChild(document.createTextNode(s));
    281 			document.getElementsByTagName("head")[0].appendChild(n);
    282 		}
    283 	}
    284 }
    285 
    286 setStylesheet("#AMMLcloseDiv \{font-size:0.8em; padding-top:1em; color:#014\}\n#AMMLwarningBox \{position:absolute; width:100%; top:0; left:0; z-index:200; text-align:center; font-size:1em; font-weight:bold; padding:0.5em 0 0.5em 0; color:#ffc; background:#c30\}");
    287 
    288 function init(){
    289 	var msg, warnings = new Array();
    290 	if (document.getElementById==null){
    291 		alert("This webpage requires a recent browser such as Mozilla Firefox");
    292 		return null;
    293 	}
    294 	if (checkForMathML && (msg = checkMathML())) warnings.push(msg);
    295 	if (warnings.length>0) displayWarnings(warnings);
    296 	if (!noMathML) initSymbols();
    297 	return true;
    298 }
    299 
    300 function checkMathML(){
    301   if (navigator.appName.slice(0,8)=="Netscape") 
    302     if (navigator.appVersion.slice(0,1)>="5") noMathML = null;
    303     else noMathML = true;
    304   else if (navigator.appName.slice(0,9)=="Microsoft")
    305     try {
    306         var ActiveX = new ActiveXObject("MathPlayer.Factory.1");
    307         noMathML = null;
    308     } catch (e) {
    309         noMathML = true;
    310     }
    311   else if (navigator.appName.slice(0,5)=="Opera") 
    312     if (navigator.appVersion.slice(0,3)>="9.5") noMathML = null;
    313   else noMathML = true;
    314 //noMathML = true; //uncomment to check
    315   if (noMathML && notifyIfNoMathML) {
    316     var msg = "To view the ASCIIMathML notation use Internet Explorer + MathPlayer or Mozilla Firefox 2.0 or later.";
    317     if (alertIfNoMathML)
    318        alert(msg);
    319     else return msg;
    320   }
    321 }
    322 
    323 function hideWarning(){
    324 	var body = document.getElementsByTagName("body")[0];
    325 	body.removeChild(document.getElementById('AMMLwarningBox'));
    326 	body.onclick = null;
    327 }
    328 
    329 function displayWarnings(warnings) {
    330   var i, frag, nd = createElementXHTML("div");
    331   var body = document.getElementsByTagName("body")[0];
    332   body.onclick=hideWarning;
    333   nd.id = 'AMMLwarningBox';
    334   for (i=0; i<warnings.length; i++) {
    335 	frag = createElementXHTML("div");
    336 	frag.appendChild(document.createTextNode(warnings[i]));
    337 	frag.style.paddingBottom = "1.0em";
    338 	nd.appendChild(frag);
    339   }
    340   nd.appendChild(createElementXHTML("p"));
    341   nd.appendChild(document.createTextNode("For instructions see the "));
    342   var an = createElementXHTML("a");
    343   an.appendChild(document.createTextNode("ASCIIMathML"));
    344   an.setAttribute("href","http://www.chapman.edu/~jipsen/asciimath.html");
    345   nd.appendChild(an);
    346   nd.appendChild(document.createTextNode(" homepage"));
    347   an = createElementXHTML("div");
    348   an.id = 'AMMLcloseDiv';
    349   an.appendChild(document.createTextNode('(click anywhere to close this warning)'));
    350   nd.appendChild(an);
    351   var body = document.getElementsByTagName("body")[0];
    352   body.insertBefore(nd,body.childNodes[0]);
    353 }
    354 
    355 function translate(spanclassAM) {
    356   if (!translated) { // run this only once
    357     translated = true;
    358     var body = document.getElementsByTagName("body")[0];
    359     var processN = document.getElementById(AMdocumentId);
    360     if (translateASCIIMath) AMprocessNode((processN!=null?processN:body), false, spanclassAM);
    361   }
    362 }
    363 */
    364 function createElementXHTML(t) {
    365   if (isIE) return document.createElement(t);
    366   else return document.createElementNS("http://www.w3.org/1999/xhtml",t);
    367 }
    368 
    369 var AMmathml = "http://www.w3.org/1998/Math/MathML";
    370 
    371 function AMcreateElementMathML(t) {
    372   if (isIE) return document.createElement("m:"+t);
    373   else return document.createElementNS(AMmathml,t);
    374 }
    375 
    376 function createMmlNode(t,frag) {
    377   var node;
    378   if (isIE) node = document.createElement("m:"+t);
    379   else node = document.createElementNS(AMmathml,t);
    380   if (frag) node.appendChild(frag);
    381   return node;
    382 }
    383 
    384 function newcommand(oldstr,newstr) {
    385   AMsymbols = AMsymbols.concat([{input:oldstr, tag:"mo", output:newstr, 
    386                                  tex:null, ttype:DEFINITION}]);
    387   // ####  Added from Version 2.0.1 #### //
    388   AMsymbols.sort(compareNames);
    389   for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input;
    390   // ####  End of Addition #### //
    391 }
    392 
    393 // character lists for Mozilla/Netscape fonts
    394 var AMcal = ["\uD835\uDC9C","\u212C","\uD835\uDC9E","\uD835\uDC9F","\u2130","\u2131","\uD835\uDCA2","\u210B","\u2110","\uD835\uDCA5","\uD835\uDCA6","\u2112","\u2133","\uD835\uDCA9","\uD835\uDCAA","\uD835\uDCAB","\uD835\uDCAC","\u211B","\uD835\uDCAE","\uD835\uDCAF","\uD835\uDCB0","\uD835\uDCB1","\uD835\uDCB2","\uD835\uDCB3","\uD835\uDCB4","\uD835\uDCB5","\uD835\uDCB6","\uD835\uDCB7","\uD835\uDCB8","\uD835\uDCB9","\u212F","\uD835\uDCBB","\u210A","\uD835\uDCBD","\uD835\uDCBE","\uD835\uDCBF","\uD835\uDCC0","\uD835\uDCC1","\uD835\uDCC2","\uD835\uDCC3","\u2134","\uD835\uDCC5","\uD835\uDCC6","\uD835\uDCC7","\uD835\uDCC8","\uD835\uDCC9","\uD835\uDCCA","\uD835\uDCCB","\uD835\uDCCC","\uD835\uDCCD","\uD835\uDCCE","\uD835\uDCCF"]; 
    395 
    396 var AMfrk = ["\uD835\uDD04","\uD835\uDD05","\u212D","\uD835\uDD07","\uD835\uDD08","\uD835\uDD09","\uD835\uDD0A","\u210C","\u2111","\uD835\uDD0D","\uD835\uDD0E","\uD835\uDD0F","\uD835\uDD10","\uD835\uDD11","\uD835\uDD12","\uD835\uDD13","\uD835\uDD14","\u211C","\uD835\uDD16","\uD835\uDD17","\uD835\uDD18","\uD835\uDD19","\uD835\uDD1A","\uD835\uDD1B","\uD835\uDD1C","\u2128","\uD835\uDD1E","\uD835\uDD1F","\uD835\uDD20","\uD835\uDD21","\uD835\uDD22","\uD835\uDD23","\uD835\uDD24","\uD835\uDD25","\uD835\uDD26","\uD835\uDD27","\uD835\uDD28","\uD835\uDD29","\uD835\uDD2A","\uD835\uDD2B","\uD835\uDD2C","\uD835\uDD2D","\uD835\uDD2E","\uD835\uDD2F","\uD835\uDD30","\uD835\uDD31","\uD835\uDD32","\uD835\uDD33","\uD835\uDD34","\uD835\uDD35","\uD835\uDD36","\uD835\uDD37"];
    397 
    398 var AMbbb = ["\uD835\uDD38","\uD835\uDD39","\u2102","\uD835\uDD3B","\uD835\uDD3C","\uD835\uDD3D","\uD835\uDD3E","\u210D","\uD835\uDD40","\uD835\uDD41","\uD835\uDD42","\uD835\uDD43","\uD835\uDD44","\u2115","\uD835\uDD46","\u2119","\u211A","\u211D","\uD835\uDD4A","\uD835\uDD4B","\uD835\uDD4C","\uD835\uDD4D","\uD835\uDD4E","\uD835\uDD4F","\uD835\uDD50","\u2124","\uD835\uDD52","\uD835\uDD53","\uD835\uDD54","\uD835\uDD55","\uD835\uDD56","\uD835\uDD57","\uD835\uDD58","\uD835\uDD59","\uD835\uDD5A","\uD835\uDD5B","\uD835\uDD5C","\uD835\uDD5D","\uD835\uDD5E","\uD835\uDD5F","\uD835\uDD60","\uD835\uDD61","\uD835\uDD62","\uD835\uDD63","\uD835\uDD64","\uD835\uDD65","\uD835\uDD66","\uD835\uDD67","\uD835\uDD68","\uD835\uDD69","\uD835\uDD6A","\uD835\uDD6B"];
    399 /*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];
    400 var AMfrk = [0xEF5D,0xEF5E,0x212D,0xEF5F,0xEF60,0xEF61,0xEF62,0x210C,0x2111,0xEF63,0xEF64,0xEF65,0xEF66,0xEF67,0xEF68,0xEF69,0xEF6A,0x211C,0xEF6B,0xEF6C,0xEF6D,0xEF6E,0xEF6F,0xEF70,0xEF71,0x2128];
    401 var AMbbb = [0xEF8C,0xEF8D,0x2102,0xEF8E,0xEF8F,0xEF90,0xEF91,0x210D,0xEF92,0xEF93,0xEF94,0xEF95,0xEF96,0x2115,0xEF97,0x2119,0x211A,0x211D,0xEF98,0xEF99,0xEF9A,0xEF9B,0xEF9C,0xEF9D,0xEF9E,0x2124];*/
    402 
    403 var CONST = 0, UNARY = 1, BINARY = 2, INFIX = 3, LEFTBRACKET = 4,
    404     RIGHTBRACKET = 5, SPACE = 6, UNDEROVER = 7, DEFINITION = 8,
    405     LEFTRIGHT = 9, TEXT = 10, /*BIG = 11, LONG = 12, STRETCHY = 13,
    406     MATRIX = 14,*/ UNARYUNDEROVER = 15; // token types
    407 
    408 var AMquote = {input:"\"",   tag:"mtext", output:"mbox", tex:null, ttype:TEXT};
    409 
    410 var AMsymbols = [
    411 //some greek symbols
    412 {input:"alpha",  tag:"mi", output:"\u03B1", tex:null, ttype:CONST},
    413 {input:"beta",   tag:"mi", output:"\u03B2", tex:null, ttype:CONST},
    414 {input:"chi",    tag:"mi", output:"\u03C7", tex:null, ttype:CONST},
    415 {input:"delta",  tag:"mi", output:"\u03B4", tex:null, ttype:CONST},
    416 {input:"Delta",  tag:"mo", output:"\u0394", tex:null, ttype:CONST},
    417 {input:"epsi",   tag:"mi", output:"\u03B5", tex:"epsilon", ttype:CONST},
    418 {input:"varepsilon", tag:"mi", output:"\u025B", tex:null, ttype:CONST},
    419 {input:"eta",    tag:"mi", output:"\u03B7", tex:null, ttype:CONST},
    420 {input:"gamma",  tag:"mi", output:"\u03B3", tex:null, ttype:CONST},
    421 {input:"Gamma",  tag:"mo", output:"\u0393", tex:null, ttype:CONST},
    422 {input:"iota",   tag:"mi", output:"\u03B9", tex:null, ttype:CONST},
    423 {input:"kappa",  tag:"mi", output:"\u03BA", tex:null, ttype:CONST},
    424 {input:"lambda", tag:"mi", output:"\u03BB", tex:null, ttype:CONST},
    425 {input:"Lambda", tag:"mo", output:"\u039B", tex:null, ttype:CONST},
    426 {input:"lamda", tag:"mi", output:"\u03BB", tex:null, ttype:CONST},
    427 {input:"Lamda", tag:"mo", output:"\u039B", tex:null, ttype:CONST},
    428 {input:"mu",     tag:"mi", output:"\u03BC", tex:null, ttype:CONST},
    429 {input:"nu",     tag:"mi", output:"\u03BD", tex:null, ttype:CONST},
    430 {input:"omega",  tag:"mi", output:"\u03C9", tex:null, ttype:CONST},
    431 {input:"Omega",  tag:"mo", output:"\u03A9", tex:null, ttype:CONST},
    432 {input:"phi",    tag:"mi", output:fixphi?"\u03D5":"\u03C6", tex:null, ttype:CONST},
    433 {input:"varphi", tag:"mi", output:fixphi?"\u03C6":"\u03D5", tex:null, ttype:CONST},
    434 {input:"Phi",    tag:"mo", output:"\u03A6", tex:null, ttype:CONST},
    435 {input:"pi",     tag:"mi", output:"\u03C0", tex:null, ttype:CONST},
    436 {input:"Pi",     tag:"mo", output:"\u03A0", tex:null, ttype:CONST},
    437 {input:"psi",    tag:"mi", output:"\u03C8", tex:null, ttype:CONST},
    438 {input:"Psi",    tag:"mi", output:"\u03A8", tex:null, ttype:CONST},
    439 {input:"rho",    tag:"mi", output:"\u03C1", tex:null, ttype:CONST},
    440 {input:"sigma",  tag:"mi", output:"\u03C3", tex:null, ttype:CONST},
    441 {input:"Sigma",  tag:"mo", output:"\u03A3", tex:null, ttype:CONST},
    442 {input:"tau",    tag:"mi", output:"\u03C4", tex:null, ttype:CONST},
    443 {input:"theta",  tag:"mi", output:"\u03B8", tex:null, ttype:CONST},
    444 {input:"vartheta", tag:"mi", output:"\u03D1", tex:null, ttype:CONST},
    445 {input:"Theta",  tag:"mo", output:"\u0398", tex:null, ttype:CONST},
    446 {input:"upsilon", tag:"mi", output:"\u03C5", tex:null, ttype:CONST},
    447 {input:"xi",     tag:"mi", output:"\u03BE", tex:null, ttype:CONST},
    448 {input:"Xi",     tag:"mo", output:"\u039E", tex:null, ttype:CONST},
    449 {input:"zeta",   tag:"mi", output:"\u03B6", tex:null, ttype:CONST},
    450 
    451 //binary operation symbols
    452 //{input:"-",  tag:"mo", output:"\u0096", tex:null, ttype:CONST},
    453 {input:"*",  tag:"mo", output:"\u22C5", tex:"cdot", ttype:CONST},
    454 {input:"**", tag:"mo", output:"\u2217", tex:"ast", ttype:CONST},
    455 {input:"***", tag:"mo", output:"\u22C6", tex:"star", ttype:CONST},
    456 {input:"//", tag:"mo", output:"/",      tex:null, ttype:CONST},
    457 {input:"\\\\", tag:"mo", output:"\\",   tex:"backslash", ttype:CONST},
    458 {input:"setminus", tag:"mo", output:"\\", tex:null, ttype:CONST},
    459 {input:"xx", tag:"mo", output:"\u00D7", tex:"times", ttype:CONST},
    460 {input:"|><", tag:"mo", output:"\u22C9", tex:"ltimes", ttype:CONST},
    461 {input:"><|", tag:"mo", output:"\u22CA", tex:"rtimes", ttype:CONST},
    462 {input:"|><|", tag:"mo", output:"\u22C8", tex:"bowtie", ttype:CONST},
    463 {input:"-:", tag:"mo", output:"\u00F7", tex:"div", ttype:CONST},
    464 {input:"divide",   tag:"mo", output:"-:", tex:null, ttype:DEFINITION},
    465 {input:"@",  tag:"mo", output:"\u2218", tex:"circ", ttype:CONST},
    466 {input:"o+", tag:"mo", output:"\u2295", tex:"oplus", ttype:CONST},
    467 {input:"ox", tag:"mo", output:"\u2297", tex:"otimes", ttype:CONST},
    468 {input:"o.", tag:"mo", output:"\u2299", tex:"odot", ttype:CONST},
    469 {input:"sum", tag:"mo", output:"\u2211", tex:null, ttype:UNDEROVER},
    470 {input:"prod", tag:"mo", output:"\u220F", tex:null, ttype:UNDEROVER},
    471 {input:"^^",  tag:"mo", output:"\u2227", tex:"wedge", ttype:CONST},
    472 {input:"^^^", tag:"mo", output:"\u22C0", tex:"bigwedge", ttype:UNDEROVER},
    473 {input:"vv",  tag:"mo", output:"\u2228", tex:"vee", ttype:CONST},
    474 {input:"vvv", tag:"mo", output:"\u22C1", tex:"bigvee", ttype:UNDEROVER},
    475 {input:"nn",  tag:"mo", output:"\u2229", tex:"cap", ttype:CONST},
    476 {input:"nnn", tag:"mo", output:"\u22C2", tex:"bigcap", ttype:UNDEROVER},
    477 {input:"uu",  tag:"mo", output:"\u222A", tex:"cup", ttype:CONST},
    478 {input:"uuu", tag:"mo", output:"\u22C3", tex:"bigcup", ttype:UNDEROVER},
    479 
    480 //binary relation symbols
    481 {input:"!=",  tag:"mo", output:"\u2260", tex:"ne", ttype:CONST},
    482 {input:":=",  tag:"mo", output:":=",     tex:null, ttype:CONST},
    483 {input:"lt",  tag:"mo", output:"<",      tex:null, ttype:CONST},
    484 {input:"<=",  tag:"mo", output:"\u2264", tex:"le", ttype:CONST},
    485 {input:"lt=", tag:"mo", output:"\u2264", tex:"leq", ttype:CONST},
    486 {input:"gt",  tag:"mo", output:">",      tex:null, ttype:CONST},
    487 {input:">=",  tag:"mo", output:"\u2265", tex:"ge", ttype:CONST},
    488 {input:"gt=", tag:"mo", output:"\u2265", tex:"geq", ttype:CONST},
    489 {input:"-<",  tag:"mo", output:"\u227A", tex:"prec", ttype:CONST},
    490 {input:"-lt", tag:"mo", output:"\u227A", tex:null, ttype:CONST},
    491 {input:">-",  tag:"mo", output:"\u227B", tex:"succ", ttype:CONST},
    492 {input:"-<=", tag:"mo", output:"\u2AAF", tex:"preceq", ttype:CONST},
    493 {input:">-=", tag:"mo", output:"\u2AB0", tex:"succeq", ttype:CONST},
    494 {input:"in",  tag:"mo", output:"\u2208", tex:null, ttype:CONST},
    495 {input:"!in", tag:"mo", output:"\u2209", tex:"notin", ttype:CONST},
    496 {input:"sub", tag:"mo", output:"\u2282", tex:"subset", ttype:CONST},
    497 {input:"sup", tag:"mo", output:"\u2283", tex:"supset", ttype:CONST},
    498 {input:"sube", tag:"mo", output:"\u2286", tex:"subseteq", ttype:CONST},
    499 {input:"supe", tag:"mo", output:"\u2287", tex:"supseteq", ttype:CONST},
    500 {input:"-=",  tag:"mo", output:"\u2261", tex:"equiv", ttype:CONST},
    501 {input:"~=",  tag:"mo", output:"\u2245", tex:"cong", ttype:CONST},
    502 {input:"~~",  tag:"mo", output:"\u2248", tex:"approx", ttype:CONST},
    503 {input:"prop", tag:"mo", output:"\u221D", tex:"propto", ttype:CONST},
    504 
    505 //logical symbols
    506 {input:"and", tag:"mtext", output:"and", tex:null, ttype:SPACE},
    507 {input:"or",  tag:"mtext", output:"or",  tex:null, ttype:SPACE},
    508 {input:"not", tag:"mo", output:"\u00AC", tex:"neg", ttype:CONST},
    509 {input:"=>",  tag:"mo", output:"\u21D2", tex:"implies", ttype:CONST},
    510 {input:"if",  tag:"mo", output:"if",     tex:null, ttype:SPACE},
    511 {input:"<=>", tag:"mo", output:"\u21D4", tex:"iff", ttype:CONST},
    512 {input:"AA",  tag:"mo", output:"\u2200", tex:"forall", ttype:CONST},
    513 {input:"EE",  tag:"mo", output:"\u2203", tex:"exists", ttype:CONST},
    514 {input:"_|_", tag:"mo", output:"\u22A5", tex:"bot", ttype:CONST},
    515 {input:"TT",  tag:"mo", output:"\u22A4", tex:"top", ttype:CONST},
    516 {input:"|--",  tag:"mo", output:"\u22A2", tex:"vdash", ttype:CONST},
    517 {input:"|==",  tag:"mo", output:"\u22A8", tex:"models", ttype:CONST},
    518 
    519 //grouping brackets
    520 {input:"(", tag:"mo", output:"(", tex:null, ttype:LEFTBRACKET},
    521 {input:")", tag:"mo", output:")", tex:null, ttype:RIGHTBRACKET},
    522 {input:"[", tag:"mo", output:"[", tex:null, ttype:LEFTBRACKET},
    523 {input:"]", tag:"mo", output:"]", tex:null, ttype:RIGHTBRACKET},
    524 {input:"{", tag:"mo", output:"{", tex:null, ttype:LEFTBRACKET},
    525 {input:"}", tag:"mo", output:"}", tex:null, ttype:RIGHTBRACKET},
    526 {input:"|", tag:"mo", output:"|", tex:null, ttype:LEFTRIGHT},
    527 //{input:"||", tag:"mo", output:"||", tex:null, ttype:LEFTRIGHT},
    528 {input:"(:", tag:"mo", output:"\u2329", tex:"langle", ttype:LEFTBRACKET},
    529 {input:":)", tag:"mo", output:"\u232A", tex:"rangle", ttype:RIGHTBRACKET},
    530 {input:"<<", tag:"mo", output:"\u2329", tex:null, ttype:LEFTBRACKET},
    531 {input:">>", tag:"mo", output:"\u232A", tex:null, ttype:RIGHTBRACKET},
    532 {input:"{:", tag:"mo", output:"{:", tex:null, ttype:LEFTBRACKET, invisible:true},
    533 {input:":}", tag:"mo", output:":}", tex:null, ttype:RIGHTBRACKET, invisible:true},
    534 
    535 //miscellaneous symbols
    536 {input:"int",  tag:"mo", output:"\u222B", tex:null, ttype:CONST},
    537 {input:"dx",   tag:"mi", output:"{:d x:}", tex:null, ttype:DEFINITION},
    538 {input:"dy",   tag:"mi", output:"{:d y:}", tex:null, ttype:DEFINITION},
    539 {input:"dz",   tag:"mi", output:"{:d z:}", tex:null, ttype:DEFINITION},
    540 {input:"dt",   tag:"mi", output:"{:d t:}", tex:null, ttype:DEFINITION},
    541 {input:"oint", tag:"mo", output:"\u222E", tex:null, ttype:CONST},
    542 {input:"del",  tag:"mo", output:"\u2202", tex:"partial", ttype:CONST},
    543 {input:"grad", tag:"mo", output:"\u2207", tex:"nabla", ttype:CONST},
    544 {input:"+-",   tag:"mo", output:"\u00B1", tex:"pm", ttype:CONST},
    545 {input:"O/",   tag:"mo", output:"\u2205", tex:"emptyset", ttype:CONST},
    546 {input:"oo",   tag:"mo", output:"\u221E", tex:"infty", ttype:CONST},
    547 {input:"aleph", tag:"mo", output:"\u2135", tex:null, ttype:CONST},
    548 {input:"...",  tag:"mo", output:"...",    tex:"ldots", ttype:CONST},
    549 {input:":.",  tag:"mo", output:"\u2234",  tex:"therefore", ttype:CONST},
    550 {input:"/_",  tag:"mo", output:"\u2220",  tex:"angle", ttype:CONST},
    551 {input:"/_\\",  tag:"mo", output:"\u25B3",  tex:"triangle", ttype:CONST},
    552 {input:"'",   tag:"mo", output:"\u2032",  tex:"prime", ttype:CONST},
    553 {input:"tilde", tag:"mover", output:"~", tex:null, ttype:UNARY, acc:true},
    554 {input:"\\ ",  tag:"mo", output:"\u00A0", tex:null, ttype:CONST},
    555 {input:"frown",  tag:"mo", output:"\u2322", tex:null, ttype:CONST},
    556 {input:"quad", tag:"mo", output:"\u00A0\u00A0", tex:null, ttype:CONST},
    557 {input:"qquad", tag:"mo", output:"\u00A0\u00A0\u00A0\u00A0", tex:null, ttype:CONST},
    558 {input:"cdots", tag:"mo", output:"\u22EF", tex:null, ttype:CONST},
    559 {input:"vdots", tag:"mo", output:"\u22EE", tex:null, ttype:CONST},
    560 {input:"ddots", tag:"mo", output:"\u22F1", tex:null, ttype:CONST},
    561 {input:"diamond", tag:"mo", output:"\u22C4", tex:null, ttype:CONST},
    562 {input:"square", tag:"mo", output:"\u25A1", tex:null, ttype:CONST},
    563 {input:"|__", tag:"mo", output:"\u230A",  tex:"lfloor", ttype:CONST},
    564 {input:"__|", tag:"mo", output:"\u230B",  tex:"rfloor", ttype:CONST},
    565 {input:"|~", tag:"mo", output:"\u2308",  tex:"lceiling", ttype:CONST},
    566 {input:"~|", tag:"mo", output:"\u2309",  tex:"rceiling", ttype:CONST},
    567 {input:"CC",  tag:"mo", output:"\u2102", tex:null, ttype:CONST},
    568 {input:"NN",  tag:"mo", output:"\u2115", tex:null, ttype:CONST},
    569 {input:"QQ",  tag:"mo", output:"\u211A", tex:null, ttype:CONST},
    570 {input:"RR",  tag:"mo", output:"\u211D", tex:null, ttype:CONST},
    571 {input:"ZZ",  tag:"mo", output:"\u2124", tex:null, ttype:CONST},
    572 {input:"f",   tag:"mi", output:"f",      tex:null, ttype:UNARY, func:true},
    573 {input:"g",   tag:"mi", output:"g",      tex:null, ttype:UNARY, func:true},
    574 
    575 //standard functions
    576 {input:"lim",  tag:"mo", output:"lim", tex:null, ttype:UNDEROVER},
    577 {input:"Lim",  tag:"mo", output:"Lim", tex:null, ttype:UNDEROVER},
    578 {input:"sin",  tag:"mo", output:"sin", tex:null, ttype:UNARY, func:true},
    579 {input:"cos",  tag:"mo", output:"cos", tex:null, ttype:UNARY, func:true},
    580 {input:"tan",  tag:"mo", output:"tan", tex:null, ttype:UNARY, func:true},
    581 {input:"sinh", tag:"mo", output:"sinh", tex:null, ttype:UNARY, func:true},
    582 {input:"cosh", tag:"mo", output:"cosh", tex:null, ttype:UNARY, func:true},
    583 {input:"tanh", tag:"mo", output:"tanh", tex:null, ttype:UNARY, func:true},
    584 {input:"cot",  tag:"mo", output:"cot", tex:null, ttype:UNARY, func:true},
    585 {input:"sec",  tag:"mo", output:"sec", tex:null, ttype:UNARY, func:true},
    586 {input:"csc",  tag:"mo", output:"csc", tex:null, ttype:UNARY, func:true},
    587 {input:"arcsin",  tag:"mo", output:"arcsin", tex:null, ttype:UNARY, func:true},
    588 {input:"arccos",  tag:"mo", output:"arccos", tex:null, ttype:UNARY, func:true},
    589 {input:"arctan",  tag:"mo", output:"arctan", tex:null, ttype:UNARY, func:true},
    590 {input:"coth",  tag:"mo", output:"coth", tex:null, ttype:UNARY, func:true},
    591 {input:"sech",  tag:"mo", output:"sech", tex:null, ttype:UNARY, func:true},
    592 {input:"csch",  tag:"mo", output:"csch", tex:null, ttype:UNARY, func:true},
    593 {input:"exp",  tag:"mo", output:"exp", tex:null, ttype:UNARY, func:true},
    594 {input:"abs",   tag:"mo", output:"abs",  tex:null, ttype:UNARY, rewriteleftright:["|","|"]},
    595 {input:"norm",   tag:"mo", output:"norm",  tex:null, ttype:UNARY, rewriteleftright:["\u2225","\u2225"]},
    596 {input:"floor",   tag:"mo", output:"floor",  tex:null, ttype:UNARY, rewriteleftright:["\u230A","\u230B"]},
    597 {input:"ceil",   tag:"mo", output:"ceil",  tex:null, ttype:UNARY, rewriteleftright:["\u2308","\u2309"]},
    598 {input:"log",  tag:"mo", output:"log", tex:null, ttype:UNARY, func:true},
    599 {input:"ln",   tag:"mo", output:"ln",  tex:null, ttype:UNARY, func:true},
    600 {input:"det",  tag:"mo", output:"det", tex:null, ttype:UNARY, func:true},
    601 {input:"dim",  tag:"mo", output:"dim", tex:null, ttype:CONST},
    602 {input:"mod",  tag:"mo", output:"mod", tex:null, ttype:CONST},
    603 {input:"gcd",  tag:"mo", output:"gcd", tex:null, ttype:UNARY, func:true},
    604 {input:"lcm",  tag:"mo", output:"lcm", tex:null, ttype:UNARY, func:true},
    605 {input:"lub",  tag:"mo", output:"lub", tex:null, ttype:CONST},
    606 {input:"glb",  tag:"mo", output:"glb", tex:null, ttype:CONST},
    607 {input:"min",  tag:"mo", output:"min", tex:null, ttype:UNDEROVER},
    608 {input:"max",  tag:"mo", output:"max", tex:null, ttype:UNDEROVER},
    609 
    610 //arrows
    611 {input:"uarr", tag:"mo", output:"\u2191", tex:"uparrow", ttype:CONST},
    612 {input:"darr", tag:"mo", output:"\u2193", tex:"downarrow", ttype:CONST},
    613 {input:"rarr", tag:"mo", output:"\u2192", tex:"rightarrow", ttype:CONST},
    614 {input:"->",   tag:"mo", output:"\u2192", tex:"to", ttype:CONST},
    615 {input:">->",   tag:"mo", output:"\u21A3", tex:"rightarrowtail", ttype:CONST},
    616 {input:"->>",   tag:"mo", output:"\u21A0", tex:"twoheadrightarrow", ttype:CONST},
    617 {input:">->>",   tag:"mo", output:"\u2916", tex:"twoheadrightarrowtail", ttype:CONST},
    618 {input:"|->",  tag:"mo", output:"\u21A6", tex:"mapsto", ttype:CONST},
    619 {input:"larr", tag:"mo", output:"\u2190", tex:"leftarrow", ttype:CONST},
    620 {input:"harr", tag:"mo", output:"\u2194", tex:"leftrightarrow", ttype:CONST},
    621 {input:"rArr", tag:"mo", output:"\u21D2", tex:"Rightarrow", ttype:CONST},
    622 {input:"lArr", tag:"mo", output:"\u21D0", tex:"Leftarrow", ttype:CONST},
    623 {input:"hArr", tag:"mo", output:"\u21D4", tex:"Leftrightarrow", ttype:CONST},
    624 //commands with argument
    625 {input:"sqrt", tag:"msqrt", output:"sqrt", tex:null, ttype:UNARY},
    626 {input:"root", tag:"mroot", output:"root", tex:null, ttype:BINARY},
    627 {input:"frac", tag:"mfrac", output:"/",    tex:null, ttype:BINARY},
    628 {input:"/",    tag:"mfrac", output:"/",    tex:null, ttype:INFIX},
    629 {input:"stackrel", tag:"mover", output:"stackrel", tex:null, ttype:BINARY},
    630 {input:"overset", tag:"mover", output:"stackrel", tex:null, ttype:BINARY},
    631 {input:"underset", tag:"munder", output:"stackrel", tex:null, ttype:BINARY},
    632 {input:"_",    tag:"msub",  output:"_",    tex:null, ttype:INFIX},
    633 {input:"^",    tag:"msup",  output:"^",    tex:null, ttype:INFIX},
    634 {input:"hat", tag:"mover", output:"\u005E", tex:null, ttype:UNARY, acc:true},
    635 {input:"bar", tag:"mover", output:"\u00AF", tex:"overline", ttype:UNARY, acc:true},
    636 {input:"vec", tag:"mover", output:"\u2192", tex:null, ttype:UNARY, acc:true},
    637 {input:"dot", tag:"mover", output:".",      tex:null, ttype:UNARY, acc:true},
    638 {input:"ddot", tag:"mover", output:"..",    tex:null, ttype:UNARY, acc:true},
    639 {input:"ul", tag:"munder", output:"\u0332", tex:"underline", ttype:UNARY, acc:true},
    640 {input:"ubrace", tag:"munder", output:"\u23DF", tex:"underbrace", ttype:UNARYUNDEROVER, acc:true},
    641 {input:"obrace", tag:"mover", output:"\u23DE", tex:"overbrace", ttype:UNARYUNDEROVER, acc:true},
    642 {input:"text", tag:"mtext", output:"text", tex:null, ttype:TEXT},
    643 {input:"mbox", tag:"mtext", output:"mbox", tex:null, ttype:TEXT},
    644 {input:"color", tag:"mstyle", ttype:BINARY},
    645 {input:"cancel", tag:"menclose", output:"cancel", tex:null, ttype:UNARY},
    646 AMquote,
    647 {input:"bb", tag:"mstyle", atname:"mathvariant", atval:"bold", output:"bb", tex:null, ttype:UNARY},
    648 {input:"mathbf", tag:"mstyle", atname:"mathvariant", atval:"bold", output:"mathbf", tex:null, ttype:UNARY},
    649 {input:"sf", tag:"mstyle", atname:"mathvariant", atval:"sans-serif", output:"sf", tex:null, ttype:UNARY},
    650 {input:"mathsf", tag:"mstyle", atname:"mathvariant", atval:"sans-serif", output:"mathsf", tex:null, ttype:UNARY},
    651 {input:"bbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"bbb", tex:null, ttype:UNARY, codes:AMbbb},
    652 {input:"mathbb", tag:"mstyle", atname:"mathvariant", atval:"double-struck", output:"mathbb", tex:null, ttype:UNARY, codes:AMbbb},
    653 {input:"cc",  tag:"mstyle", atname:"mathvariant", atval:"script", output:"cc", tex:null, ttype:UNARY, codes:AMcal},
    654 {input:"mathcal", tag:"mstyle", atname:"mathvariant", atval:"script", output:"mathcal", tex:null, ttype:UNARY, codes:AMcal},
    655 {input:"tt",  tag:"mstyle", atname:"mathvariant", atval:"monospace", output:"tt", tex:null, ttype:UNARY},
    656 {input:"mathtt", tag:"mstyle", atname:"mathvariant", atval:"monospace", output:"mathtt", tex:null, ttype:UNARY},
    657 {input:"fr",  tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"fr", tex:null, ttype:UNARY, codes:AMfrk},
    658 {input:"mathfrak",  tag:"mstyle", atname:"mathvariant", atval:"fraktur", output:"mathfrak", tex:null, ttype:UNARY, codes:AMfrk}
    659 ];
    660 
    661 function compareNames(s1,s2) {
    662   if (s1.input > s2.input) return 1
    663   else return -1;
    664 }
    665 
    666 var AMnames = []; //list of input symbols
    667 
    668 function initSymbols() {
    669   var texsymbols = [], i;
    670   for (i=0; i<AMsymbols.length; i++)
    671     if (AMsymbols[i].tex) {
    672       texsymbols[texsymbols.length] = {input:AMsymbols[i].tex, 
    673         tag:AMsymbols[i].tag, output:AMsymbols[i].output, ttype:AMsymbols[i].ttype,
    674         acc:(AMsymbols[i].acc||false)};
    675     }
    676   AMsymbols = AMsymbols.concat(texsymbols);
    677   refreshSymbols();
    678 }
    679 
    680 function refreshSymbols(){
    681   var i;
    682   AMsymbols.sort(compareNames);
    683   for (i=0; i<AMsymbols.length; i++) AMnames[i] = AMsymbols[i].input;
    684 }
    685 
    686 function define(oldstr,newstr) {
    687   AMsymbols = AMsymbols.concat([{input:oldstr, tag:"mo", output:newstr, 
    688                                  tex:null, ttype:DEFINITION}]);
    689   refreshSymbols(); // this may be a problem if many symbols are defined!
    690 }
    691 
    692 function AMremoveCharsAndBlanks(str,n) {
    693 //remove n characters and any following blanks
    694   var st;
    695   if (str.charAt(n)=="\\" && str.charAt(n+1)!="\\" && str.charAt(n+1)!=" ") 
    696     st = str.slice(n+1);
    697   else st = str.slice(n);
    698   for (var i=0; i<st.length && st.charCodeAt(i)<=32; i=i+1);
    699   return st.slice(i);
    700 }
    701 
    702 function position(arr, str, n) { 
    703 // return position >=n where str appears or would be inserted
    704 // assumes arr is sorted
    705   if (n==0) {
    706     var h,m;
    707     n = -1;
    708     h = arr.length;
    709     while (n+1<h) {
    710       m = (n+h) >> 1;
    711       if (arr[m]<str) n = m; else h = m;
    712     }
    713     return h;
    714   } else
    715     for (var i=n; i<arr.length && arr[i]<str; i++);
    716   return i; // i=arr.length || arr[i]>=str
    717 }
    718 
    719 function AMgetSymbol(str) {
    720 //return maximal initial substring of str that appears in names
    721 //return null if there is none
    722   var k = 0; //new pos
    723   var j = 0; //old pos
    724   var mk; //match pos
    725   var st;
    726   var tagst;
    727   var match = "";
    728   var more = true;
    729   for (var i=1; i<=str.length && more; i++) {
    730     st = str.slice(0,i); //initial substring of length i
    731     j = k;
    732     k = position(AMnames, st, j);
    733     if (k<AMnames.length && str.slice(0,AMnames[k].length)==AMnames[k]){
    734       match = AMnames[k];
    735       mk = k;
    736       i = match.length;
    737     }
    738     more = k<AMnames.length && str.slice(0,AMnames[k].length)>=AMnames[k];
    739   }
    740   AMpreviousSymbol=AMcurrentSymbol;
    741   if (match!=""){
    742     AMcurrentSymbol=AMsymbols[mk].ttype;
    743     return AMsymbols[mk]; 
    744   }
    745 // if str[0] is a digit or - return maxsubstring of digits.digits
    746   AMcurrentSymbol=CONST;
    747   k = 1;
    748   st = str.slice(0,1);
    749   var integ = true;
    750   while ("0"<=st && st<="9" && k<=str.length) {
    751     st = str.slice(k,k+1);
    752     k++;
    753   }
    754   if (st == decimalsign) {
    755     st = str.slice(k,k+1);
    756     if ("0"<=st && st<="9") {
    757       integ = false;
    758       k++;
    759       while ("0"<=st && st<="9" && k<=str.length) {
    760         st = str.slice(k,k+1);
    761         k++;
    762       }
    763     }
    764   }
    765   if ((integ && k>1) || k>2) {
    766     st = str.slice(0,k-1);
    767     tagst = "mn";
    768   } else {
    769     k = 2;
    770     st = str.slice(0,1); //take 1 character
    771     tagst = (("A">st || st>"Z") && ("a">st || st>"z")?"mo":"mi");
    772   }
    773   if (st=="-" && AMpreviousSymbol==INFIX) {
    774     AMcurrentSymbol = INFIX;  //trick "/" into recognizing "-" on second parse
    775     return {input:st, tag:tagst, output:st, ttype:UNARY, func:true};
    776   }
    777   return {input:st, tag:tagst, output:st, ttype:CONST};
    778 }
    779 
    780 function AMremoveBrackets(node) {
    781   var st;
    782   if (!node.hasChildNodes()) { return; }
    783   if (node.firstChild.hasChildNodes() && (node.nodeName=="mrow" || node.nodeName=="M:MROW")) {
    784     st = node.firstChild.firstChild.nodeValue;
    785     if (st=="(" || st=="[" || st=="{") node.removeChild(node.firstChild);
    786   }
    787   if (node.lastChild.hasChildNodes() && (node.nodeName=="mrow" || node.nodeName=="M:MROW")) {
    788     st = node.lastChild.firstChild.nodeValue;
    789     if (st==")" || st=="]" || st=="}") node.removeChild(node.lastChild);
    790   }
    791 }
    792 
    793 /*Parsing ASCII math expressions with the following grammar
    794 v ::= [A-Za-z] | greek letters | numbers | other constant symbols
    795 u ::= sqrt | text | bb | other unary symbols for font commands
    796 b ::= frac | root | stackrel         binary symbols
    797 l ::= ( | [ | { | (: | {:            left brackets
    798 r ::= ) | ] | } | :) | :}            right brackets
    799 S ::= v | lEr | uS | bSS             Simple expression
    800 I ::= S_S | S^S | S_S^S | S          Intermediate expression
    801 E ::= IE | I/I                       Expression
    802 Each terminal symbol is translated into a corresponding mathml node.*/
    803 
    804 var AMnestingDepth,AMpreviousSymbol,AMcurrentSymbol;
    805 
    806 function AMparseSexpr(str) { //parses str and returns [node,tailstr]
    807   var symbol, node, result, i, st,// rightvert = false,
    808     newFrag = document.createDocumentFragment();
    809   str = AMremoveCharsAndBlanks(str,0);
    810   symbol = AMgetSymbol(str);             //either a token or a bracket or empty
    811   if (symbol == null || symbol.ttype == RIGHTBRACKET && AMnestingDepth > 0) {
    812     return [null,str];
    813   }
    814   if (symbol.ttype == DEFINITION) {
    815     str = symbol.output+AMremoveCharsAndBlanks(str,symbol.input.length); 
    816     symbol = AMgetSymbol(str);
    817   }
    818   switch (symbol.ttype) {  case UNDEROVER:
    819   case CONST:
    820     str = AMremoveCharsAndBlanks(str,symbol.input.length); 
    821     return [createMmlNode(symbol.tag,        //its a constant
    822                              document.createTextNode(symbol.output)),str];
    823   case LEFTBRACKET:   //read (expr+)
    824     AMnestingDepth++;
    825     str = AMremoveCharsAndBlanks(str,symbol.input.length); 
    826     result = AMparseExpr(str,true);
    827     AMnestingDepth--;
    828     if (typeof symbol.invisible == "boolean" && symbol.invisible) 
    829       node = createMmlNode("mrow",result[0]);
    830     else {
    831       node = createMmlNode("mo",document.createTextNode(symbol.output));
    832       node = createMmlNode("mrow",node);
    833       node.appendChild(result[0]);
    834     }
    835     return [node,result[1]];
    836   case TEXT:
    837       if (symbol!=AMquote) str = AMremoveCharsAndBlanks(str,symbol.input.length);
    838       if (str.charAt(0)=="{") i=str.indexOf("}");
    839       else if (str.charAt(0)=="(") i=str.indexOf(")");
    840       else if (str.charAt(0)=="[") i=str.indexOf("]");
    841       else if (symbol==AMquote) i=str.slice(1).indexOf("\"")+1;
    842       else i = 0;
    843       if (i==-1) i = str.length;
    844       st = str.slice(1,i);
    845       if (st.charAt(0) == " ") {
    846         node = createMmlNode("mspace");
    847         node.setAttribute("width","1ex");
    848         newFrag.appendChild(node);
    849       }
    850       newFrag.appendChild(
    851         createMmlNode(symbol.tag,document.createTextNode(st)));
    852       if (st.charAt(st.length-1) == " ") {
    853         node = createMmlNode("mspace");
    854         node.setAttribute("width","1ex");
    855         newFrag.appendChild(node);
    856       }
    857       str = AMremoveCharsAndBlanks(str,i+1);
    858       return [createMmlNode("mrow",newFrag),str];
    859   case UNARYUNDEROVER:
    860   case UNARY:
    861       str = AMremoveCharsAndBlanks(str,symbol.input.length); 
    862       result = AMparseSexpr(str);
    863       if (result[0]==null) return [createMmlNode(symbol.tag,
    864                              document.createTextNode(symbol.output)),str];
    865       if (typeof symbol.func == "boolean" && symbol.func) { // functions hack
    866         st = str.charAt(0);
    867           if (st=="^" || st=="_" || st=="/" || st=="|" || st=="," ||
    868              (symbol.input.length==1 && symbol.input.match(/\w/) && st!="(")) {
    869           return [createMmlNode(symbol.tag,
    870                     document.createTextNode(symbol.output)),str];
    871         } else {
    872           node = createMmlNode("mrow",
    873            createMmlNode(symbol.tag,document.createTextNode(symbol.output)));
    874           node.appendChild(result[0]);
    875           return [node,result[1]];
    876         }
    877       }
    878       AMremoveBrackets(result[0]);
    879       if (symbol.input == "sqrt") {           // sqrt
    880         return [createMmlNode(symbol.tag,result[0]),result[1]];
    881       } else if (typeof symbol.rewriteleftright != "undefined") {    // abs, floor, ceil
    882           node = createMmlNode("mrow", createMmlNode("mo",document.createTextNode(symbol.rewriteleftright[0])));
    883           node.appendChild(result[0]);
    884           node.appendChild(createMmlNode("mo",document.createTextNode(symbol.rewriteleftright[1])));
    885           return [node,result[1]];
    886       } else if (symbol.input == "cancel") {   // cancel
    887         node = createMmlNode(symbol.tag,result[0]);
    888 	node.setAttribute("notation","updiagonalstrike");
    889 	return [node,result[1]];
    890       } else if (typeof symbol.acc == "boolean" && symbol.acc) {   // accent
    891         node = createMmlNode(symbol.tag,result[0]);
    892         node.appendChild(createMmlNode("mo",document.createTextNode(symbol.output)));
    893         return [node,result[1]];
    894       } else {                        // font change command
    895         if (!isIE && typeof symbol.codes != "undefined") {
    896           for (i=0; i<result[0].childNodes.length; i++)
    897             if (result[0].childNodes[i].nodeName=="mi" || result[0].nodeName=="mi") {
    898               st = (result[0].nodeName=="mi"?result[0].firstChild.nodeValue:
    899                               result[0].childNodes[i].firstChild.nodeValue);
    900               var newst = [];
    901               for (var j=0; j<st.length; j++)
    902 		  if (st.charCodeAt(j)>64 && st.charCodeAt(j)<91) 
    903 		  	newst = newst + symbol.codes[st.charCodeAt(j)-65];
    904                 else if (st.charCodeAt(j)>96 && st.charCodeAt(j)<123) 
    905                 	newst = newst + symbol.codes[st.charCodeAt(j)-71];
    906                 else newst = newst + st.charAt(j);
    907               if (result[0].nodeName=="mi")
    908                 result[0]=createMmlNode("mo").
    909                           appendChild(document.createTextNode(newst));
    910               else result[0].replaceChild(createMmlNode("mo").
    911                                appendChild(document.createTextNode(newst)),
    912                                            result[0].childNodes[i]);
    913             }
    914         }
    915         node = createMmlNode(symbol.tag,result[0]);
    916         node.setAttribute(symbol.atname,symbol.atval);
    917         return [node,result[1]];
    918       }
    919   case BINARY:
    920     str = AMremoveCharsAndBlanks(str,symbol.input.length); 
    921     result = AMparseSexpr(str);
    922     if (result[0]==null) return [createMmlNode("mo",
    923                            document.createTextNode(symbol.input)),str];
    924     AMremoveBrackets(result[0]);
    925     var result2 = AMparseSexpr(result[1]);
    926     if (result2[0]==null) return [createMmlNode("mo",
    927                            document.createTextNode(symbol.input)),str];
    928     AMremoveBrackets(result2[0]);
    929     if (symbol.input=="color") {
    930 	if (str.charAt(0)=="{") i=str.indexOf("}");
    931         else if (str.charAt(0)=="(") i=str.indexOf(")");
    932         else if (str.charAt(0)=="[") i=str.indexOf("]");
    933 	st = str.slice(1,i);
    934 	node = createMmlNode(symbol.tag,result2[0]);
    935 	node.setAttribute("mathcolor",st);
    936 	return [node,result2[1]];
    937     }
    938     if (symbol.input=="root" || symbol.output=="stackrel") 
    939       newFrag.appendChild(result2[0]);
    940     newFrag.appendChild(result[0]);
    941     if (symbol.input=="frac") newFrag.appendChild(result2[0]);
    942     return [createMmlNode(symbol.tag,newFrag),result2[1]];
    943   case INFIX:
    944     str = AMremoveCharsAndBlanks(str,symbol.input.length); 
    945     return [createMmlNode("mo",document.createTextNode(symbol.output)),str];
    946   case SPACE:
    947     str = AMremoveCharsAndBlanks(str,symbol.input.length); 
    948     node = createMmlNode("mspace");
    949     node.setAttribute("width","1ex");
    950     newFrag.appendChild(node);
    951     newFrag.appendChild(
    952       createMmlNode(symbol.tag,document.createTextNode(symbol.output)));
    953     node = createMmlNode("mspace");
    954     node.setAttribute("width","1ex");
    955     newFrag.appendChild(node);
    956     return [createMmlNode("mrow",newFrag),str];
    957   case LEFTRIGHT:
    958 //    if (rightvert) return [null,str]; else rightvert = true;
    959     AMnestingDepth++;
    960     str = AMremoveCharsAndBlanks(str,symbol.input.length); 
    961     result = AMparseExpr(str,false);
    962     AMnestingDepth--;
    963     st = "";
    964     if (result[0].lastChild!=null)
    965       st = result[0].lastChild.firstChild.nodeValue;
    966     if (st == "|") { // its an absolute value subterm
    967       node = createMmlNode("mo",document.createTextNode(symbol.output));
    968       node = createMmlNode("mrow",node);
    969       node.appendChild(result[0]);
    970       return [node,result[1]];
    971     } else { // the "|" is a \mid so use unicode 2223 (divides) for spacing
    972       node = createMmlNode("mo",document.createTextNode("\u2223"));
    973       node = createMmlNode("mrow",node);
    974       return [node,str];
    975     }
    976   default:
    977 //alert("default");
    978     str = AMremoveCharsAndBlanks(str,symbol.input.length); 
    979     return [createMmlNode(symbol.tag,        //its a constant
    980                              document.createTextNode(symbol.output)),str];
    981   }
    982 }
    983 
    984 function AMparseIexpr(str) {
    985   var symbol, sym1, sym2, node, result, underover;
    986   str = AMremoveCharsAndBlanks(str,0);
    987   sym1 = AMgetSymbol(str);
    988   result = AMparseSexpr(str);
    989   node = result[0];
    990   str = result[1];
    991   symbol = AMgetSymbol(str);
    992   if (symbol.ttype == INFIX && symbol.input != "/") {
    993     str = AMremoveCharsAndBlanks(str,symbol.input.length);
    994 //    if (symbol.input == "/") result = AMparseIexpr(str); else ...
    995     result = AMparseSexpr(str);
    996     if (result[0] == null) // show box in place of missing argument
    997       result[0] = createMmlNode("mo",document.createTextNode("\u25A1"));
    998     else AMremoveBrackets(result[0]);
    999     str = result[1];
   1000 //    if (symbol.input == "/") AMremoveBrackets(node);
   1001     underover = (sym1.ttype == UNDEROVER || sym1.ttype == UNARYUNDEROVER);
   1002     if (symbol.input == "_") {
   1003       sym2 = AMgetSymbol(str);
   1004       if (sym2.input == "^") {
   1005         str = AMremoveCharsAndBlanks(str,sym2.input.length);
   1006         var res2 = AMparseSexpr(str);
   1007         AMremoveBrackets(res2[0]);
   1008         str = res2[1];
   1009         node = createMmlNode((underover?"munderover":"msubsup"),node);
   1010         node.appendChild(result[0]);
   1011         node.appendChild(res2[0]);
   1012         node = createMmlNode("mrow",node); // so sum does not stretch
   1013       } else {
   1014         node = createMmlNode((underover?"munder":"msub"),node);
   1015         node.appendChild(result[0]);
   1016       }
   1017     } else if (symbol.input == "^" && underover) {
   1018     	node = createMmlNode("mover",node);
   1019         node.appendChild(result[0]);   
   1020     } else {
   1021       node = createMmlNode(symbol.tag,node);
   1022       node.appendChild(result[0]);
   1023     }
   1024     if (typeof sym1.func != 'undefined' && sym1.func) {
   1025     	sym2 = AMgetSymbol(str);
   1026     	if (sym2.ttype != INFIX && sym2.ttype != RIGHTBRACKET) {
   1027     		result = AMparseIexpr(str);
   1028     		node = createMmlNode("mrow",node);
   1029     		node.appendChild(result[0]);
   1030     		str = result[1];
   1031     	}
   1032     }
   1033   }
   1034   return [node,str];
   1035 }
   1036 
   1037 function AMparseExpr(str,rightbracket) {
   1038   var symbol, node, result, i,
   1039   newFrag = document.createDocumentFragment();
   1040   do {
   1041     str = AMremoveCharsAndBlanks(str,0);
   1042     result = AMparseIexpr(str);
   1043     node = result[0];
   1044     str = result[1];
   1045     symbol = AMgetSymbol(str);
   1046     if (symbol.ttype == INFIX && symbol.input == "/") {
   1047       str = AMremoveCharsAndBlanks(str,symbol.input.length);
   1048       result = AMparseIexpr(str);
   1049       if (result[0] == null) // show box in place of missing argument
   1050         result[0] = createMmlNode("mo",document.createTextNode("\u25A1"));
   1051       else AMremoveBrackets(result[0]);
   1052       str = result[1];
   1053       AMremoveBrackets(node);
   1054       node = createMmlNode(symbol.tag,node);
   1055       node.appendChild(result[0]);
   1056       newFrag.appendChild(node);
   1057       symbol = AMgetSymbol(str);
   1058     } 
   1059     else if (node!=undefined) newFrag.appendChild(node);
   1060   } while ((symbol.ttype != RIGHTBRACKET && 
   1061            (symbol.ttype != LEFTRIGHT || rightbracket)
   1062            || AMnestingDepth == 0) && symbol!=null && symbol.output!="");
   1063   if (symbol.ttype == RIGHTBRACKET || symbol.ttype == LEFTRIGHT) {
   1064 //    if (AMnestingDepth > 0) AMnestingDepth--;
   1065     var len = newFrag.childNodes.length;
   1066     if (len>0 && newFrag.childNodes[len-1].nodeName == "mrow" 
   1067             && newFrag.childNodes[len-1].lastChild
   1068             && newFrag.childNodes[len-1].lastChild.firstChild ) { //matrix
   1069       	    //removed to allow row vectors: //&& len>1 && 
   1070     	    //newFrag.childNodes[len-2].nodeName == "mo" &&
   1071     	    //newFrag.childNodes[len-2].firstChild.nodeValue == ","
   1072       var right = newFrag.childNodes[len-1].lastChild.firstChild.nodeValue;
   1073       if (right==")" || right=="]") {
   1074         var left = newFrag.childNodes[len-1].firstChild.firstChild.nodeValue;
   1075         if (left=="(" && right==")" && symbol.output != "}" || 
   1076             left=="[" && right=="]") {
   1077         var pos = []; // positions of commas
   1078         var matrix = true;
   1079         var m = newFrag.childNodes.length;
   1080         for (i=0; matrix && i<m; i=i+2) {
   1081           pos[i] = [];
   1082           node = newFrag.childNodes[i];
   1083           if (matrix) matrix = node.nodeName=="mrow" && 
   1084             (i==m-1 || node.nextSibling.nodeName=="mo" && 
   1085             node.nextSibling.firstChild.nodeValue==",")&&
   1086             node.firstChild.firstChild.nodeValue==left &&
   1087             node.lastChild.firstChild.nodeValue==right;
   1088           if (matrix) 
   1089             for (var j=0; j<node.childNodes.length; j++)
   1090               if (node.childNodes[j].firstChild.nodeValue==",")
   1091                 pos[i][pos[i].length]=j;
   1092           if (matrix && i>1) matrix = pos[i].length == pos[i-2].length;
   1093         }
   1094         matrix = matrix && (pos.length>1 || pos[0].length>0);
   1095         if (matrix) {
   1096           var row, frag, n, k, table = document.createDocumentFragment();
   1097           for (i=0; i<m; i=i+2) {
   1098             row = document.createDocumentFragment();
   1099             frag = document.createDocumentFragment();
   1100             node = newFrag.firstChild; // <mrow>(-,-,...,-,-)</mrow>
   1101             n = node.childNodes.length;
   1102             k = 0;
   1103             node.removeChild(node.firstChild); //remove (
   1104             for (j=1; j<n-1; j++) {
   1105               if (typeof pos[i][k] != "undefined" && j==pos[i][k]){
   1106                 node.removeChild(node.firstChild); //remove ,
   1107                 row.appendChild(createMmlNode("mtd",frag));
   1108                 k++;
   1109               } else frag.appendChild(node.firstChild);
   1110             }
   1111             row.appendChild(createMmlNode("mtd",frag));
   1112             if (newFrag.childNodes.length>2) {
   1113               newFrag.removeChild(newFrag.firstChild); //remove <mrow>)</mrow>
   1114               newFrag.removeChild(newFrag.firstChild); //remove <mo>,</mo>
   1115             }
   1116             table.appendChild(createMmlNode("mtr",row));
   1117           }
   1118           node = createMmlNode("mtable",table);
   1119           if (typeof symbol.invisible == "boolean" && symbol.invisible) node.setAttribute("columnalign","left");
   1120           newFrag.replaceChild(node,newFrag.firstChild);
   1121         }
   1122        }
   1123       }
   1124     }
   1125     str = AMremoveCharsAndBlanks(str,symbol.input.length);
   1126     if (typeof symbol.invisible != "boolean" || !symbol.invisible) {
   1127       node = createMmlNode("mo",document.createTextNode(symbol.output));
   1128       newFrag.appendChild(node);
   1129     }
   1130   }
   1131   return [newFrag,str];
   1132 }
   1133 
   1134 function parseMath(str,latex) {
   1135   var frag, node;
   1136   AMnestingDepth = 0;
   1137   //some basic cleanup for dealing with stuff editors like TinyMCE adds
   1138   str = str.replace(/&nbsp;/g,"");
   1139   str = str.replace(/&gt;/g,">");
   1140   str = str.replace(/&lt;/g,"<");
   1141   str = str.replace(/(Sin|Cos|Tan|Arcsin|Arccos|Arctan|Sinh|Cosh|Tanh|Cot|Sec|Csc|Log|Ln|Abs)/g, function(v) { return v.toLowerCase(); });
   1142   frag = AMparseExpr(str.replace(/^\s+/g,""),false)[0];
   1143   node = createMmlNode("mstyle",frag);
   1144   if (mathcolor != "") node.setAttribute("mathcolor",mathcolor);
   1145   if (mathfontfamily != "") node.setAttribute("fontfamily",mathfontfamily);
   1146   if (displaystyle) node.setAttribute("displaystyle","true");
   1147   node = createMmlNode("math",node);
   1148   if (showasciiformulaonhover)                      //fixed by djhsu so newline
   1149     node.setAttribute("title",str.replace(/\s+/g," "));//does not show in Gecko
   1150   return node;
   1151 }
   1152 
   1153 /*
   1154 function strarr2docFrag(arr, linebreaks, latex) {
   1155   var newFrag=document.createDocumentFragment();
   1156   var expr = false;
   1157   for (var i=0; i<arr.length; i++) {
   1158     if (expr) newFrag.appendChild(parseMath(arr[i],latex));
   1159     else {
   1160       var arri = (linebreaks ? arr[i].split("\n\n") : [arr[i]]);
   1161       newFrag.appendChild(createElementXHTML("span").
   1162       appendChild(document.createTextNode(arri[0])));
   1163       for (var j=1; j<arri.length; j++) {
   1164         newFrag.appendChild(createElementXHTML("p"));
   1165         newFrag.appendChild(createElementXHTML("span").
   1166         appendChild(document.createTextNode(arri[j])));
   1167       }
   1168     }
   1169     expr = !expr;
   1170   }
   1171   return newFrag;
   1172 }
   1173 
   1174 function AMautomathrec(str) {
   1175 //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.
   1176 //tokens are single letters (except a, A, I) and ASCIIMathML tokens
   1177   var texcommand = "\\\\[a-zA-Z]+|\\\\\\s|";
   1178   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])|";
   1179   var englishAMtoken = "\\b(?:sum|ox|log|sin|tan|dim|hat|bar|dot)(?![a-z])|";
   1180   var secondenglishAMtoken = "|\\bI\\b|\\bin\\b|\\btext\\b"; // took if and or not out
   1181   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?
   1182   var letter = "[a-zA-HJ-Z](?=(?:[^a-zA-Z]|$|"+ambigAMtoken+englishAMtoken+simpleAMtoken+"))|";
   1183   var token = letter+texcommand+"\\d+|[-()[\\]{}+=*&^_%\\\@/<>,\\|!:;'~]|\\.(?!(?:\x20|$))|"+ambigAMtoken+englishAMtoken+simpleAMtoken;
   1184   var re = new RegExp("(^|\\s)((("+token+")\\s?)(("+token+secondenglishAMtoken+")\\s?)+)([,.?]?(?=\\s|$))","g");
   1185   str = str.replace(re," `$2`$7");
   1186   var arr = str.split(AMdelimiter1);
   1187   var re1 = new RegExp("(^|\\s)([b-zB-HJ-Z+*<>]|"+texcommand+ambigAMtoken+simpleAMtoken+")(\\s|\\n|$)","g");
   1188   var re2 = new RegExp("(^|\\s)([a-z]|"+texcommand+ambigAMtoken+simpleAMtoken+")([,.])","g"); // removed |\d+ for now
   1189   for (i=0; i<arr.length; i++)   //single nonenglish tokens
   1190     if (i%2==0) {
   1191       arr[i] = arr[i].replace(re1," `$2`$3");
   1192       arr[i] = arr[i].replace(re2," `$2`$3");
   1193       arr[i] = arr[i].replace(/([{}[\]])/,"`$1`");
   1194     }
   1195   str = arr.join(AMdelimiter1);
   1196   str = str.replace(/((^|\s)\([a-zA-Z]{2,}.*?)\)`/g,"$1`)");  //fix parentheses
   1197   str = str.replace(/`(\((a\s|in\s))(.*?[a-zA-Z]{2,}\))/g,"$1`$3");  //fix parentheses
   1198   str = str.replace(/\sin`/g,"` in");
   1199   str = str.replace(/`(\(\w\)[,.]?(\s|\n|$))/g,"$1`");
   1200   str = str.replace(/`([0-9.]+|e.g|i.e)`(\.?)/gi,"$1$2");
   1201   str = str.replace(/`([0-9.]+:)`/g,"$1");
   1202   return str;
   1203 }
   1204 
   1205 function processNodeR(n, linebreaks,latex) {
   1206   var mtch, str, arr, frg, i;
   1207   if (n.childNodes.length == 0) {
   1208    if ((n.nodeType!=8 || linebreaks) &&
   1209     n.parentNode.nodeName!="form" && n.parentNode.nodeName!="FORM" &&
   1210     n.parentNode.nodeName!="textarea" && n.parentNode.nodeName!="TEXTAREA"
   1211       //&&
   1212       //n.parentNode.nodeName!="pre" && n.parentNode.nodeName!="PRE"
   1213     ) {
   1214     str = n.nodeValue;
   1215     if (!(str == null)) {
   1216       str = str.replace(/\r\n\r\n/g,"\n\n");
   1217       str = str.replace(/\x20+/g," ");
   1218       str = str.replace(/\s*\r\n/g," ");
   1219       if(latex) {
   1220 // DELIMITERS:
   1221         mtch = (str.indexOf("\$")==-1 ? false : true);
   1222         str = str.replace(/([^\\])\$/g,"$1 \$");
   1223         str = str.replace(/^\$/," \$");	// in case \$ at start of string
   1224         arr = str.split(" \$");
   1225         for (i=0; i<arr.length; i++)
   1226 	  arr[i]=arr[i].replace(/\\\$/g,"\$");
   1227       } else {
   1228       mtch = false;
   1229       str = str.replace(new RegExp(AMescape1, "g"),
   1230               function(){mtch = true; return "AMescape1"});
   1231       str = str.replace(/\\?end{?a?math}?/i,
   1232               function(){automathrecognize = false; mtch = true; return ""});
   1233       str = str.replace(/amath\b|\\begin{a?math}/i,
   1234               function(){automathrecognize = true; mtch = true; return ""});
   1235       arr = str.split(AMdelimiter1);
   1236       if (automathrecognize)
   1237         for (i=0; i<arr.length; i++)
   1238           if (i%2==0) arr[i] = AMautomathrec(arr[i]);
   1239       str = arr.join(AMdelimiter1);
   1240       arr = str.split(AMdelimiter1);
   1241       for (i=0; i<arr.length; i++) // this is a problem ************
   1242         arr[i]=arr[i].replace(/AMescape1/g,AMdelimiter1);
   1243       }
   1244       if (arr.length>1 || mtch) {
   1245         if (!noMathML) {
   1246           frg = strarr2docFrag(arr,n.nodeType==8,latex);
   1247           var len = frg.childNodes.length;
   1248           n.parentNode.replaceChild(frg,n);
   1249           return len-1;
   1250         } else return 0;
   1251       }
   1252     }
   1253    } else return 0;
   1254   } else if (n.nodeName!="math") {
   1255     for (i=0; i<n.childNodes.length; i++)
   1256       i += processNodeR(n.childNodes[i], linebreaks,latex);
   1257   }
   1258   return 0;
   1259 }
   1260 
   1261 function AMprocessNode(n, linebreaks, spanclassAM) {
   1262   var frag,st;
   1263   if (spanclassAM!=null) {
   1264     frag = document.getElementsByTagName("span")
   1265     for (var i=0;i<frag.length;i++)
   1266       if (frag[i].className == "AM") 
   1267         processNodeR(frag[i],linebreaks,false);
   1268   } else {
   1269     try {
   1270       st = n.innerHTML; // look for AMdelimiter on page
   1271     } catch(err) {}
   1272 //alert(st)
   1273     if (st==null || /amath\b|\\begin{a?math}/i.test(st) ||
   1274       st.indexOf(AMdelimiter1+" ")!=-1 || st.slice(-1)==AMdelimiter1 ||
   1275       st.indexOf(AMdelimiter1+"<")!=-1 || st.indexOf(AMdelimiter1+"\n")!=-1) {
   1276       processNodeR(n,linebreaks,false);
   1277     }
   1278   }
   1279 }
   1280 
   1281 function generic(){
   1282   if(!init()) return;
   1283   if (translateOnLoad) {
   1284       translate();
   1285   }
   1286 };
   1287 //setup onload function
   1288 if(typeof window.addEventListener != 'undefined'){
   1289   //.. gecko, safari, konqueror and standard
   1290   window.addEventListener('load', generic, false);
   1291 }
   1292 else if(typeof document.addEventListener != 'undefined'){
   1293   //.. opera 7
   1294   document.addEventListener('load', generic, false);
   1295 }
   1296 else if(typeof window.attachEvent != 'undefined'){
   1297   //.. win/ie
   1298   window.attachEvent('onload', generic);
   1299 }else{
   1300   //.. mac/ie5 and anything else that gets this far
   1301   //if there's an existing onload function
   1302   if(typeof window.onload == 'function'){
   1303     //store it
   1304     var existing = onload;
   1305     //add new onload handler
   1306     window.onload = function(){
   1307       //call existing onload function
   1308       existing();
   1309       //call generic onload function
   1310       generic();
   1311     };
   1312   }else{
   1313     window.onload = generic;
   1314   }
   1315 }
   1316 
   1317 //expose some functions to outside
   1318 asciimath.newcommand = newcommand;
   1319 asciimath.AMprocesssNode = AMprocessNode;
   1320 asciimath.parseMath = parseMath;
   1321 asciimath.translate = translate;
   1322 })();
   1323 
   1324 */
   1325 
   1326 /******************************************************************
   1327  *
   1328  *   The previous section is ASCIIMathML.js Version 2.2
   1329  *   (c) Peter Jipsen, used with permission.
   1330  *
   1331  ******************************************************************/
   1332 
   1333 showasciiformulaonhover = false;
   1334 mathfontfamily = "";
   1335 mathcolor = "";
   1336 
   1337 //
   1338 //  Remove remapping of mathvariants to plane1 (MathJax handles that)
   1339 //  Change functions to mi rather than mo (to get spacing right)
   1340 //
   1341 (function () {
   1342   for (var i = 0, m = AMsymbols.length; i < m; i++) {
   1343     if (AMsymbols[i].codes) {delete AMsymbols[i].codes}
   1344     if (AMsymbols[i].func) {AMsymbols[i].tag = "mi"}
   1345   }
   1346 })();
   1347 
   1348 //
   1349 //  Access to AsciiMath functions and values
   1350 //
   1351 ASCIIMATH.Augment({
   1352   AM: {
   1353     Init: function () {
   1354       displaystyle = ASCIIMATH.config.displaystyle;
   1355       // Old versions use the "decimal" option, so take it into account if it
   1356       // is defined by the user. See issue 384.
   1357       decimalsign  = (ASCIIMATH.config.decimal || ASCIIMATH.config.decimalsign);
   1358       // unfix phi and varphi, if requested
   1359       if (!ASCIIMATH.config.fixphi) {
   1360         for (var i = 0, m = AMsymbols.length; i < m; i++) {
   1361           if (AMsymbols[i].input === "phi")    {AMsymbols[i].output = "\u03C6"}
   1362           if (AMsymbols[i].input === "varphi") {AMsymbols[i].output = "\u03D5"; i = m}
   1363         }
   1364       }
   1365    
   1366       INITASCIIMATH();
   1367       initSymbols();
   1368     },
   1369     Augment: function (def) {
   1370       for (var id in def) {if (def.hasOwnProperty(id)) {
   1371 	switch (id) {
   1372 	 case "displaystyle": displaystyle = def[id]; break;
   1373 	 case "decimal": decimal = def[id]; break;
   1374 	 case "parseMath": parseMath = def[id]; break;
   1375 	 case "parseExpr": AMparseExpr = def[id]; break;
   1376 	 case "parseIexpr": AMparseIexpr = def[id]; break;
   1377 	 case "parseSexpr": AMparseSexpr = def[id]; break;
   1378 	 case "removeBrackets": AMremoveBrackets = def[id]; break;
   1379 	 case "getSymbol": AMgetSymbol = def[id]; break;
   1380 	 case "position": position = def[id]; break;
   1381 	 case "removeCharsAndBlanks": AMremoveCharsAndBlanks = def[id]; break;
   1382 	 case "createMmlNode": createMmlNode = def[id]; break;
   1383 	 case "createElementMathML": AMcreateElementMathML = def[id]; break;
   1384 	 case "createElementXHTML": createElementXHTML = def[id]; break;
   1385 	 case "initSymbols": initSymbols = def[id]; break;
   1386 	 case "refreshSymbols": refreshSymbols = def[id]; break;
   1387 	 case "compareNames": compareNames = def[id]; break;
   1388 	};
   1389         this[id] = def[id];
   1390       }};
   1391     },
   1392     parseMath:  parseMath,
   1393     parseExpr:  AMparseExpr,
   1394     parseIexpr: AMparseIexpr,
   1395     parseSexr:  AMparseSexpr,
   1396     removeBrackets: AMremoveBrackets,
   1397     getSymbol:  AMgetSymbol,
   1398     position:   position,
   1399     removeCharsAndBlanks: AMremoveCharsAndBlanks,
   1400     createMmlNode: createMmlNode,
   1401     createElementMathML: AMcreateElementMathML,
   1402     createElementXHTML:  createElementXHTML,
   1403     initSymbols: initSymbols,
   1404     refreshSymbols: refreshSymbols,
   1405     compareNames: compareNames,
   1406     
   1407     createDocumentFragment: DOCFRAG,
   1408     document: document,
   1409     
   1410     define: define,
   1411     newcommand: newcommand,
   1412     symbols: AMsymbols,
   1413     names: AMnames,
   1414         
   1415     TOKEN: {
   1416       CONST:CONST, UNARY:UNARY, BINARY:BINARY, INFIX:INFIX,
   1417       LEFTBRACKET:LEFTBRACKET, RIGHTBRACKET:RIGHTBRACKET, SPACE:SPACE,
   1418       UNDEROVER:UNDEROVER, DEFINITION:DEFINITION, LEFTRIGHT:LEFTRIGHT, TEXT:TEXT,
   1419       UNARYUNDEROVER:UNARYUNDEROVER
   1420     }
   1421   }
   1422 });
   1423 
   1424 //
   1425 //  Make minimizer think these have been used
   1426 //
   1427 var junk = [window, navigator]; junk = null;
   1428   
   1429 })(MathJax.InputJax.AsciiMath);
   1430 
   1431 
   1432 /************************************************************************/
   1433 
   1434 (function (ASCIIMATH) {
   1435   var MML;
   1436   
   1437   ASCIIMATH.Augment({
   1438     sourceMenuTitle: /*_(MathMenu)*/ ["AsciiMathInput","AsciiMath Input"],
   1439     annotationEncoding: "text/x-asciimath",
   1440 
   1441     prefilterHooks:    MathJax.Callback.Hooks(true),   // hooks to run before processing AsciiMath
   1442     postfilterHooks:   MathJax.Callback.Hooks(true),   // hooks to run after processing AsciiMath
   1443 
   1444     Translate: function (script) {
   1445       var mml, math = MathJax.HTML.getScript(script);
   1446       var data = {math:math, script:script};
   1447       var callback = this.prefilterHooks.Execute(data); if (callback) return callback;
   1448       math = data.math;
   1449       try {
   1450         mml = this.AM.parseMath(math);
   1451       } catch(err) {
   1452         if (!err.asciimathError) {throw err}
   1453         mml = this.formatError(err,math);
   1454       }
   1455       data.math = MML(mml); this.postfilterHooks.Execute(data);
   1456       return this.postfilterHooks.Execute(data) || data.math;
   1457     },
   1458     formatError: function (err,math,script) {
   1459       var message = err.message.replace(/\n.*/,"");
   1460       MathJax.Hub.signal.Post(["AsciiMath Jax - parse error",message,math,script]);
   1461       return MML.Error(message);
   1462     },
   1463     Error: function (message) {
   1464       throw MathJax.Hub.Insert(Error(message),{asciimathError: true});
   1465     },
   1466     //
   1467     //  Initialize the MML variable and AsciiMath itself
   1468     //
   1469     Startup: function () {
   1470       MML = MathJax.ElementJax.mml;
   1471       this.AM.Init();
   1472     }
   1473   });
   1474 
   1475   ASCIIMATH.loadComplete("jax.js");
   1476   
   1477 })(MathJax.InputJax.AsciiMath);
   1478 
   1479 
   1480