www

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

jax.js (65445B)


      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/element/mml/jax.js
      7  *  
      8  *  Implements the MML ElementJax that holds the internal represetation
      9  *  of the mathematics on the page.  Various InputJax will produce this
     10  *  format, and the OutputJax will display it in various formats.
     11  *
     12  *  ---------------------------------------------------------------------
     13  *  
     14  *  Copyright (c) 2009-2015 The MathJax Consortium
     15  * 
     16  *  Licensed under the Apache License, Version 2.0 (the "License");
     17  *  you may not use this file except in compliance with the License.
     18  *  You may obtain a copy of the License at
     19  * 
     20  *      http://www.apache.org/licenses/LICENSE-2.0
     21  * 
     22  *  Unless required by applicable law or agreed to in writing, software
     23  *  distributed under the License is distributed on an "AS IS" BASIS,
     24  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     25  *  See the License for the specific language governing permissions and
     26  *  limitations under the License.
     27  */
     28 
     29 MathJax.ElementJax.mml = MathJax.ElementJax({
     30   mimeType: "jax/mml"
     31 },{
     32   id: "mml",
     33   version: "2.6.0",
     34   directory: MathJax.ElementJax.directory + "/mml",
     35   extensionDir: MathJax.ElementJax.extensionDir + "/mml",
     36   optableDir: MathJax.ElementJax.directory + "/mml/optable"
     37 });
     38 
     39 MathJax.ElementJax.mml.Augment({
     40   Init: function () {
     41     if (arguments.length === 1 && arguments[0].type === "math") {this.root = arguments[0]}
     42       else {this.root = MathJax.ElementJax.mml.math.apply(this,arguments)}
     43     if (this.root.attr && this.root.attr.mode) {
     44       if (!this.root.display && this.root.attr.mode === "display") {
     45         this.root.display = "block";
     46         this.root.attrNames.push("display");
     47       }
     48       delete this.root.attr.mode;
     49       for (var i = 0, m = this.root.attrNames.length; i < m; i++) {
     50         if (this.root.attrNames[i] === "mode") {this.root.attrNames.splice(i,1); break}
     51       }
     52     }
     53   }
     54 },{
     55   INHERIT: "_inherit_",
     56   AUTO: "_auto_",
     57   SIZE: {
     58     INFINITY: "infinity",
     59     SMALL: "small",
     60     NORMAL: "normal",
     61     BIG: "big"
     62   },
     63   COLOR: {
     64     TRANSPARENT: "transparent"
     65   },
     66   VARIANT: {
     67     NORMAL: "normal",
     68     BOLD: "bold",
     69     ITALIC: "italic",
     70     BOLDITALIC: "bold-italic",
     71     DOUBLESTRUCK: "double-struck",
     72     FRAKTUR: "fraktur",
     73     BOLDFRAKTUR: "bold-fraktur",
     74     SCRIPT: "script",
     75     BOLDSCRIPT: "bold-script",
     76     SANSSERIF: "sans-serif",
     77     BOLDSANSSERIF: "bold-sans-serif",
     78     SANSSERIFITALIC: "sans-serif-italic",
     79     SANSSERIFBOLDITALIC: "sans-serif-bold-italic",
     80     MONOSPACE: "monospace",
     81     INITIAL: "inital",
     82     TAILED: "tailed",
     83     LOOPED: "looped",
     84     STRETCHED: "stretched",
     85     CALIGRAPHIC: "-tex-caligraphic",
     86     OLDSTYLE: "-tex-oldstyle"
     87   },
     88   FORM: {
     89     PREFIX: "prefix",
     90     INFIX: "infix",
     91     POSTFIX: "postfix"
     92   },
     93   LINEBREAK: {
     94     AUTO: "auto",
     95     NEWLINE: "newline",
     96     NOBREAK: "nobreak",
     97     GOODBREAK: "goodbreak",
     98     BADBREAK: "badbreak"
     99   },
    100   LINEBREAKSTYLE: {
    101     BEFORE: "before",
    102     AFTER: "after",
    103     DUPLICATE: "duplicate",
    104     INFIXLINBREAKSTYLE: "infixlinebreakstyle"
    105   },
    106   INDENTALIGN: {
    107     LEFT: "left",
    108     CENTER: "center",
    109     RIGHT: "right",
    110     AUTO: "auto",
    111     ID: "id",
    112     INDENTALIGN: "indentalign"
    113   },
    114   INDENTSHIFT: {
    115     INDENTSHIFT: "indentshift"
    116   },
    117   LINETHICKNESS: {
    118     THIN: "thin",
    119     MEDIUM: "medium",
    120     THICK: "thick"
    121   },
    122   NOTATION: {
    123     LONGDIV: "longdiv",
    124     ACTUARIAL: "actuarial",
    125     RADICAL: "radical",
    126     BOX: "box",
    127     ROUNDEDBOX: "roundedbox",
    128     CIRCLE: "circle",
    129     LEFT: "left",
    130     RIGHT: "right",
    131     TOP: "top",
    132     BOTTOM: "bottom",
    133     UPDIAGONALSTRIKE: "updiagonalstrike",
    134     DOWNDIAGONALSTRIKE: "downdiagonalstrike",
    135     UPDIAGONALARROW: "updiagonalarrow",
    136     VERTICALSTRIKE: "verticalstrike",
    137     HORIZONTALSTRIKE: "horizontalstrike",
    138     PHASORANGLE: "phasorangle",
    139     MADRUWB: "madruwb"
    140   },
    141   ALIGN: {
    142     TOP: "top",
    143     BOTTOM: "bottom",
    144     CENTER: "center",
    145     BASELINE: "baseline",
    146     AXIS: "axis",
    147     LEFT: "left",
    148     RIGHT: "right"
    149   },
    150   LINES: {
    151     NONE: "none",
    152     SOLID: "solid",
    153     DASHED: "dashed"
    154   },
    155   SIDE: {
    156     LEFT: "left",
    157     RIGHT: "right",
    158     LEFTOVERLAP: "leftoverlap",
    159     RIGHTOVERLAP: "rightoverlap"
    160   },
    161   WIDTH: {
    162     AUTO: "auto",
    163     FIT: "fit"
    164   },
    165   ACTIONTYPE: {
    166     TOGGLE: "toggle",
    167     STATUSLINE: "statusline",
    168     TOOLTIP: "tooltip",
    169     INPUT: "input"
    170   },
    171   LENGTH: {
    172     VERYVERYTHINMATHSPACE: "veryverythinmathspace",
    173     VERYTHINMATHSPACE: "verythinmathspace",
    174     THINMATHSPACE: "thinmathspace",
    175     MEDIUMMATHSPACE: "mediummathspace",
    176     THICKMATHSPACE: "thickmathspace",
    177     VERYTHICKMATHSPACE: "verythickmathspace",
    178     VERYVERYTHICKMATHSPACE: "veryverythickmathspace",
    179     NEGATIVEVERYVERYTHINMATHSPACE: "negativeveryverythinmathspace",
    180     NEGATIVEVERYTHINMATHSPACE: "negativeverythinmathspace",
    181     NEGATIVETHINMATHSPACE: "negativethinmathspace",
    182     NEGATIVEMEDIUMMATHSPACE: "negativemediummathspace",
    183     NEGATIVETHICKMATHSPACE: "negativethickmathspace",
    184     NEGATIVEVERYTHICKMATHSPACE: "negativeverythickmathspace",
    185     NEGATIVEVERYVERYTHICKMATHSPACE: "negativeveryverythickmathspace"
    186   },
    187   OVERFLOW: {
    188     LINBREAK: "linebreak",
    189     SCROLL: "scroll",
    190     ELIDE: "elide",
    191     TRUNCATE: "truncate",
    192     SCALE: "scale"
    193   },
    194   UNIT: {
    195     EM: "em",
    196     EX: "ex",
    197     PX: "px",
    198     IN: "in",
    199     CM: "cm",
    200     MM: "mm",
    201     PT: "pt",
    202     PC: "pc"
    203   },
    204   TEXCLASS: {
    205     ORD:   0,
    206     OP:    1,
    207     BIN:   2,
    208     REL:   3,
    209     OPEN:  4,
    210     CLOSE: 5,
    211     PUNCT: 6,
    212     INNER: 7,
    213     VCENTER: 8,
    214     NONE:   -1
    215   },
    216   TEXCLASSNAMES: ["ORD", "OP", "BIN", "REL", "OPEN", "CLOSE", "PUNCT", "INNER", "VCENTER"],
    217   skipAttributes: {
    218     texClass:true, useHeight:true, texprimestyle:true
    219   },
    220   copyAttributes: {
    221     displaystyle:1, scriptlevel:1, open:1, close:1, form:1,
    222     actiontype: 1,
    223     fontfamily:true, fontsize:true, fontweight:true, fontstyle:true,
    224     color:true, background:true,
    225     id:true, "class":1, href:true, style:true
    226   },
    227   copyAttributeNames: [
    228     "displaystyle", "scriptlevel", "open", "close", "form",  // force these to be copied
    229     "actiontype",
    230     "fontfamily", "fontsize", "fontweight", "fontstyle",
    231     "color", "background",
    232     "id", "class", "href", "style"
    233   ],
    234   nocopyAttributes: {
    235     fontfamily: true, fontsize: true, fontweight: true, fontstyle: true,
    236     color: true, background: true,
    237     id: true, 'class': true, href: true, style: true,
    238     xmlns: true
    239   },
    240   Error: function (message,def) {
    241     var mml = this.merror(message),
    242         dir = MathJax.Localization.fontDirection(),
    243         font = MathJax.Localization.fontFamily();
    244     if (def) {mml = mml.With(def)}
    245     if (dir || font) {
    246       mml = this.mstyle(mml);
    247       if (dir) {mml.dir = dir}
    248       if (font) {mml.style.fontFamily = "font-family: "+font}
    249     }
    250     return mml;
    251   }
    252 });
    253 
    254 (function (MML) {
    255 
    256   MML.mbase = MathJax.Object.Subclass({
    257     type: "base", isToken: false,
    258     defaults: {
    259       mathbackground: MML.INHERIT,
    260       mathcolor: MML.INHERIT,
    261       dir: MML.INHERIT
    262     },
    263     noInherit: {},
    264     noInheritAttribute: {
    265       texClass: true
    266     },
    267     getRemoved: {},
    268     linebreakContainer: false,
    269     
    270     Init: function () {
    271       this.data = [];
    272       if (this.inferRow && !(arguments.length === 1 && arguments[0].inferred))
    273         {this.Append(MML.mrow().With({inferred: true, notParent: true}))}
    274       this.Append.apply(this,arguments);
    275     },
    276     With: function (def) {
    277       for (var id in def) {if (def.hasOwnProperty(id)) {this[id] = def[id]}}
    278       return this;
    279     },
    280     Append: function () {
    281       if (this.inferRow && this.data.length) {
    282         this.data[0].Append.apply(this.data[0],arguments);
    283       } else {
    284         for (var i = 0, m = arguments.length; i < m; i++)
    285           {this.SetData(this.data.length,arguments[i])}
    286       }
    287     },
    288     SetData: function (i,item) {
    289       if (item != null) {
    290         if (!(item instanceof MML.mbase))
    291           {item = (this.isToken || this.isChars ? MML.chars(item) : MML.mtext(item))}
    292         item.parent = this;
    293         item.setInherit(this.inheritFromMe ? this : this.inherit);
    294       }
    295       this.data[i] = item;
    296     },
    297     Parent: function () {
    298       var parent = this.parent;
    299       while (parent && parent.notParent) {parent = parent.parent}
    300       return parent;
    301     },
    302     Get: function (name,nodefault,noself) {
    303       if (!noself) {
    304         if (this[name] != null) {return this[name]}
    305         if (this.attr && this.attr[name] != null) {return this.attr[name]}
    306       }
    307       // FIXME: should cache these values and get from cache
    308       // (clear cache when appended to a new object?)
    309       var parent = this.Parent();
    310       if (parent && parent["adjustChild_"+name] != null) {
    311         return (parent["adjustChild_"+name])(this.childPosition(),nodefault);
    312       }
    313       var obj = this.inherit; var root = obj;
    314       while (obj) {
    315         var value = obj[name]; if (value == null && obj.attr) {value = obj.attr[name]}
    316         if (obj.removedStyles && obj.getRemoved[name] && value == null) value = obj.removedStyles[obj.getRemoved[name]];
    317         if (value != null && obj.noInheritAttribute && !obj.noInheritAttribute[name]) {
    318           var noInherit = obj.noInherit[this.type];
    319           if (!(noInherit && noInherit[name])) {return value}
    320         }
    321         root = obj; obj = obj.inherit;
    322       }
    323       if (!nodefault) {
    324         if (this.defaults[name] === MML.AUTO) {return this.autoDefault(name)}
    325         if (this.defaults[name] !== MML.INHERIT && this.defaults[name] != null)
    326           {return this.defaults[name]}
    327         if (root) {return root.defaults[name]}
    328       }
    329       return null;
    330     },
    331     hasValue: function (name) {return (this.Get(name,true) != null)},
    332     getValues: function () {
    333       var values = {};
    334       for (var i = 0, m = arguments.length; i < m; i++)
    335         {values[arguments[i]] = this.Get(arguments[i])}
    336       return values;
    337     },
    338     adjustChild_scriptlevel:   function (i,nodef) {return this.Get("scriptlevel",nodef)},   // always inherit from parent
    339     adjustChild_displaystyle:  function (i,nodef) {return this.Get("displaystyle",nodef)},  // always inherit from parent
    340     adjustChild_texprimestyle: function (i,nodef) {return this.Get("texprimestyle",nodef)}, // always inherit from parent
    341     childPosition: function () {
    342       var child = this, parent = child.parent;
    343       while (parent.notParent) {child = parent; parent = child.parent}
    344       for (var i = 0, m = parent.data.length; i < m; i++) {if (parent.data[i] === child) {return i}}
    345       return null;
    346     },
    347     setInherit: function (obj) {
    348       if (obj !== this.inherit && this.inherit == null) {
    349         this.inherit = obj;
    350         for (var i = 0, m = this.data.length; i < m; i++) {
    351           if (this.data[i] && this.data[i].setInherit) {this.data[i].setInherit(obj)}
    352         }
    353       }
    354     },
    355     setTeXclass: function (prev) {
    356       this.getPrevClass(prev);
    357       return (typeof(this.texClass) !== "undefined" ? this : prev);
    358     },
    359     getPrevClass: function (prev) {
    360       if (prev) {
    361         this.prevClass = prev.Get("texClass");
    362         this.prevLevel = prev.Get("scriptlevel");
    363       }
    364     },
    365     updateTeXclass: function (core) {
    366       if (core) {
    367         this.prevClass = core.prevClass; delete core.prevClass;
    368         this.prevLevel = core.prevLevel; delete core.prevLevel;
    369         this.texClass = core.Get("texClass");
    370       }
    371     },
    372     texSpacing: function () {
    373       var prev = (this.prevClass != null ? this.prevClass : MML.TEXCLASS.NONE);
    374       var tex = (this.Get("texClass") || MML.TEXCLASS.ORD);
    375       if (prev === MML.TEXCLASS.NONE || tex === MML.TEXCLASS.NONE) {return ""}
    376       if (prev === MML.TEXCLASS.VCENTER) {prev = MML.TEXCLASS.ORD}
    377       if (tex  === MML.TEXCLASS.VCENTER) {tex  = MML.TEXCLASS.ORD}
    378       var space = this.TEXSPACE[prev][tex];
    379       if (this.prevLevel > 0 && this.Get("scriptlevel") > 0 && space >= 0) {return ""}
    380       return this.TEXSPACELENGTH[Math.abs(space)];
    381     },
    382     TEXSPACELENGTH:[
    383       "",
    384       MML.LENGTH.THINMATHSPACE,
    385       MML.LENGTH.MEDIUMMATHSPACE,
    386       MML.LENGTH.THICKMATHSPACE
    387     ],
    388     // See TeXBook Chapter 18 (p. 170)
    389     TEXSPACE: [
    390       [ 0,-1, 2, 3, 0, 0, 0, 1], // ORD
    391       [-1,-1, 0, 3, 0, 0, 0, 1], // OP
    392       [ 2, 2, 0, 0, 2, 0, 0, 2], // BIN
    393       [ 3, 3, 0, 0, 3, 0, 0, 3], // REL
    394       [ 0, 0, 0, 0, 0, 0, 0, 0], // OPEN
    395       [ 0,-1, 2, 3, 0, 0, 0, 1], // CLOSE
    396       [ 1, 1, 0, 1, 1, 1, 1, 1], // PUNCT
    397       [ 1,-1, 2, 3, 1, 0, 1, 1]  // INNER
    398     ],
    399     autoDefault: function (name) {return ""},
    400     isSpacelike: function () {return false},
    401     isEmbellished: function () {return false},
    402     Core: function () {return this},
    403     CoreMO: function () {return this},
    404     childIndex: function(child) {
    405       if (child == null) return;
    406       for (var i = 0, m = this.data.length; i < m; i++) if (child === this.data[i]) return i;
    407     },
    408     CoreIndex: function () {
    409       return (this.inferRow ? this.data[0]||this : this).childIndex(this.Core());
    410     },
    411     hasNewline: function () {
    412       if (this.isEmbellished()) {return this.CoreMO().hasNewline()}
    413       if (this.isToken || this.linebreakContainer) {return false}
    414       for (var i = 0, m = this.data.length; i < m; i++) {
    415         if (this.data[i] && this.data[i].hasNewline()) {return true}
    416       }
    417       return false;
    418     },
    419     array: function () {if (this.inferred) {return this.data} else {return [this]}},
    420     toString: function () {return this.type+"("+this.data.join(",")+")"},
    421     getAnnotation: function () {return null}
    422   },{
    423     childrenSpacelike: function () {
    424       for (var i = 0, m = this.data.length; i < m; i++)
    425         {if (!this.data[i].isSpacelike()) {return false}}
    426       return true;
    427     },
    428     childEmbellished: function () {
    429       return (this.data[0] && this.data[0].isEmbellished());
    430     },
    431     childCore: function () {return (this.inferRow && this.data[0] ? this.data[0].Core() : this.data[0])},
    432     childCoreMO: function () {return (this.data[0] ? this.data[0].CoreMO() : null)},
    433     setChildTeXclass: function (prev) {
    434       if (this.data[0]) {
    435         prev = this.data[0].setTeXclass(prev);
    436         this.updateTeXclass(this.data[0]);
    437       }
    438       return prev;
    439     },
    440     setBaseTeXclasses: function (prev) {
    441       this.getPrevClass(prev); this.texClass = null;
    442       if (this.data[0]) {
    443         if (this.isEmbellished() || this.data[0].isa(MML.mi)) {
    444           prev = this.data[0].setTeXclass(prev);
    445           this.updateTeXclass(this.Core());
    446         } else {this.data[0].setTeXclass(); prev = this}
    447       } else {prev = this}
    448       for (var i = 1, m = this.data.length; i < m; i++)
    449         {if (this.data[i]) {this.data[i].setTeXclass()}}
    450       return prev;
    451     },
    452     setSeparateTeXclasses: function (prev) {
    453       this.getPrevClass(prev);
    454       for (var i = 0, m = this.data.length; i < m; i++)
    455         {if (this.data[i]) {this.data[i].setTeXclass()}}
    456       if (this.isEmbellished()) {this.updateTeXclass(this.Core())}
    457       return this;
    458     }
    459   });
    460   
    461   MML.mi = MML.mbase.Subclass({
    462     type: "mi", isToken: true,
    463     texClass: MML.TEXCLASS.ORD,
    464     defaults: {
    465       mathvariant: MML.AUTO,
    466       mathsize: MML.INHERIT,
    467       mathbackground: MML.INHERIT,
    468       mathcolor: MML.INHERIT,
    469       dir: MML.INHERIT
    470     },
    471     autoDefault: function (name) {
    472       if (name === "mathvariant") {
    473         var mi = (this.data[0]||"").toString();
    474         return (mi.length === 1 ||
    475                (mi.length === 2 && mi.charCodeAt(0) >= 0xD800 && mi.charCodeAt(0) < 0xDC00) ?
    476                   MML.VARIANT.ITALIC : MML.VARIANT.NORMAL);
    477       }
    478       return "";
    479     },
    480     setTeXclass: function (prev) {
    481       this.getPrevClass(prev);
    482       var name = this.data.join("");
    483       if (name.length > 1 && name.match(/^[a-z][a-z0-9]*$/i) &&
    484           this.texClass === MML.TEXCLASS.ORD) {
    485         this.texClass = MML.TEXCLASS.OP;
    486         this.autoOP = true;
    487       }
    488       return this;
    489     }
    490   });
    491   
    492   MML.mn = MML.mbase.Subclass({
    493     type: "mn", isToken: true,
    494     texClass: MML.TEXCLASS.ORD,
    495     defaults: {
    496       mathvariant: MML.INHERIT,
    497       mathsize: MML.INHERIT,
    498       mathbackground: MML.INHERIT,
    499       mathcolor: MML.INHERIT,
    500       dir: MML.INHERIT
    501     }
    502   });
    503   
    504   MML.mo = MML.mbase.Subclass({
    505     type: "mo", isToken: true,
    506     defaults: {
    507       mathvariant: MML.INHERIT,
    508       mathsize: MML.INHERIT,
    509       mathbackground: MML.INHERIT,
    510       mathcolor: MML.INHERIT,
    511       dir: MML.INHERIT,
    512       form: MML.AUTO,
    513       fence: MML.AUTO,
    514       separator: MML.AUTO,
    515       lspace: MML.AUTO,
    516       rspace: MML.AUTO,
    517       stretchy: MML.AUTO,
    518       symmetric: MML.AUTO,
    519       maxsize: MML.AUTO,
    520       minsize: MML.AUTO,
    521       largeop: MML.AUTO,
    522       movablelimits: MML.AUTO,
    523       accent: MML.AUTO,
    524       linebreak: MML.LINEBREAK.AUTO,
    525       lineleading: MML.INHERIT,
    526       linebreakstyle: MML.AUTO,
    527       linebreakmultchar: MML.INHERIT,
    528       indentalign: MML.INHERIT,
    529       indentshift: MML.INHERIT,
    530       indenttarget: MML.INHERIT,
    531       indentalignfirst: MML.INHERIT,
    532       indentshiftfirst: MML.INHERIT,
    533       indentalignlast: MML.INHERIT,
    534       indentshiftlast: MML.INHERIT,
    535       texClass: MML.AUTO
    536     },
    537     defaultDef: {
    538       form: MML.FORM.INFIX,
    539       fence: false,
    540       separator: false,
    541       lspace: MML.LENGTH.THICKMATHSPACE,
    542       rspace: MML.LENGTH.THICKMATHSPACE,
    543       stretchy: false,
    544       symmetric: false,
    545       maxsize: MML.SIZE.INFINITY,
    546       minsize: '0em', //'1em',
    547       largeop: false,
    548       movablelimits: false,
    549       accent: false,
    550       linebreak: MML.LINEBREAK.AUTO,
    551       lineleading: "1ex",
    552       linebreakstyle: "before",
    553       indentalign: MML.INDENTALIGN.AUTO,
    554       indentshift: "0",
    555       indenttarget: "",
    556       indentalignfirst: MML.INDENTALIGN.INDENTALIGN,
    557       indentshiftfirst: MML.INDENTSHIFT.INDENTSHIFT,
    558       indentalignlast: MML.INDENTALIGN.INDENTALIGN,
    559       indentshiftlast: MML.INDENTSHIFT.INDENTSHIFT,
    560       texClass: MML.TEXCLASS.REL // for MML, but TeX sets ORD explicitly
    561     },
    562     SPACE_ATTR: {lspace: 0x01, rspace: 0x02, form: 0x04},
    563     useMMLspacing: 0x07,
    564     autoDefault: function (name,nodefault) {
    565       var def = this.def;
    566       if (!def) {
    567         if (name === "form") {this.useMMLspacing &= ~this.SPACE_ATTR.form; return this.getForm()}
    568         var mo = this.data.join("");
    569         var forms = [this.Get("form"),MML.FORM.INFIX,MML.FORM.POSTFIX,MML.FORM.PREFIX];
    570         for (var i = 0, m = forms.length; i < m; i++) {
    571           var data = this.OPTABLE[forms[i]][mo];
    572           if (data) {def = this.makeDef(data); break}
    573         }
    574         if (!def) {def = this.CheckRange(mo)}
    575         if (!def && nodefault) {def = {}} else {
    576           if (!def) {def = MathJax.Hub.Insert({},this.defaultDef)}
    577           if (this.parent) {this.def = def} else {def = MathJax.Hub.Insert({},def)}
    578           def.form = forms[0];
    579         }
    580       }
    581       this.useMMLspacing &= ~(this.SPACE_ATTR[name] || 0);
    582       if (def[name] != null) {return def[name]}
    583       else if (!nodefault) {return this.defaultDef[name]}
    584       return "";
    585     },
    586     CheckRange: function (mo) {
    587       var n = mo.charCodeAt(0);
    588       if (n >= 0xD800 && n < 0xDC00) {n = (((n-0xD800)<<10)+(mo.charCodeAt(1)-0xDC00))+0x10000}
    589       for (var i = 0, m = this.RANGES.length; i < m && this.RANGES[i][0] <= n; i++) {
    590         if (n <= this.RANGES[i][1]) {
    591           if (this.RANGES[i][3]) {
    592             var file = MML.optableDir+"/"+this.RANGES[i][3]+".js";
    593             this.RANGES[i][3] = null;
    594             MathJax.Hub.RestartAfter(MathJax.Ajax.Require(file));
    595           }
    596           var data = MML.TEXCLASSNAMES[this.RANGES[i][2]];
    597           data = this.OPTABLE.infix[mo] = MML.mo.OPTYPES[data === "BIN" ? "BIN3" : data];
    598           return this.makeDef(data);
    599         }
    600       }
    601       return null;
    602     },
    603     makeDef: function (data) {
    604       if (data[2] == null) {data[2] = this.defaultDef.texClass}
    605       if (!data[3]) {data[3] = {}}
    606       var def = MathJax.Hub.Insert({},data[3]);
    607       def.lspace = this.SPACE[data[0]]; def.rspace = this.SPACE[data[1]];
    608       def.texClass = data[2];
    609       if (def.texClass === MML.TEXCLASS.REL &&
    610          (this.movablelimits || this.data.join("").match(/^[a-z]+$/i)))
    611              {def.texClass = MML.TEXCLASS.OP} // mark named operators as OP
    612       return def;
    613     },
    614     getForm: function () {
    615       var core = this, parent = this.parent, Parent = this.Parent();
    616       while (Parent && Parent.isEmbellished())
    617         {core = parent; parent = Parent.parent; Parent = Parent.Parent()}
    618       if (parent && parent.type === "mrow" && parent.NonSpaceLength() !== 1) {
    619         if (parent.FirstNonSpace() === core) {return MML.FORM.PREFIX}
    620         if (parent.LastNonSpace() === core) {return MML.FORM.POSTFIX}
    621       }
    622       return MML.FORM.INFIX;
    623     },
    624     isEmbellished: function () {return true},
    625     hasNewline: function () {return (this.Get("linebreak") === MML.LINEBREAK.NEWLINE)},
    626     CoreParent: function () {
    627       var parent = this;
    628       while (parent && parent.isEmbellished() &&
    629              parent.CoreMO() === this && !parent.isa(MML.math)) {parent = parent.Parent()}
    630       return parent;
    631     },
    632     CoreText: function (parent) {
    633       if (!parent) {return ""}
    634       if (parent.isEmbellished()) {return parent.CoreMO().data.join("")}
    635       while ((((parent.isa(MML.mrow) || parent.isa(MML.TeXAtom) ||
    636                 parent.isa(MML.mstyle) || parent.isa(MML.mphantom)) &&
    637                 parent.data.length === 1) || parent.isa(MML.munderover)) &&
    638                 parent.data[0]) {parent = parent.data[0]}
    639       if (!parent.isToken) {return ""} else {return parent.data.join("")}
    640     },
    641     remapChars: {
    642       '*':"\u2217",
    643       '"':"\u2033",
    644       "\u00B0":"\u2218",
    645       "\u00B2":"2",
    646       "\u00B3":"3",
    647       "\u00B4":"\u2032",
    648       "\u00B9":"1"
    649     },
    650     remap: function (text,map) {
    651       text = text.replace(/-/g,"\u2212");
    652       if (map) {
    653         text = text.replace(/'/g,"\u2032").replace(/`/g,"\u2035");
    654         if (text.length === 1) {text = map[text]||text}
    655       }
    656       return text;
    657     },
    658     setTeXclass: function (prev) {
    659       var values = this.getValues("form","lspace","rspace","fence"); // sets useMMLspacing
    660       if (this.useMMLspacing) {this.texClass = MML.TEXCLASS.NONE; return this}
    661       if (values.fence && !this.texClass) {
    662         if (values.form === MML.FORM.PREFIX) {this.texClass = MML.TEXCLASS.OPEN}
    663         if (values.form === MML.FORM.POSTFIX) {this.texClass = MML.TEXCLASS.CLOSE}
    664       }
    665       this.texClass = this.Get("texClass");
    666       if (this.data.join("") === "\u2061") {
    667         // force previous node to be texClass OP, and skip this node
    668         if (prev) {prev.texClass = MML.TEXCLASS.OP; prev.fnOP = true}
    669         this.texClass = this.prevClass = MML.TEXCLASS.NONE;
    670         return prev;
    671       }
    672       return this.adjustTeXclass(prev);
    673     },
    674     adjustTeXclass: function (prev) {
    675       if (this.texClass === MML.TEXCLASS.NONE) {return prev}
    676       if (prev) {
    677         if (prev.autoOP && (this.texClass === MML.TEXCLASS.BIN ||
    678                             this.texClass === MML.TEXCLASS.REL))
    679           {prev.texClass = MML.TEXCLASS.ORD}
    680         this.prevClass = prev.texClass || MML.TEXCLASS.ORD;
    681         this.prevLevel = prev.Get("scriptlevel")
    682       } else {this.prevClass = MML.TEXCLASS.NONE}
    683       if (this.texClass === MML.TEXCLASS.BIN &&
    684             (this.prevClass === MML.TEXCLASS.NONE ||
    685              this.prevClass === MML.TEXCLASS.BIN ||
    686              this.prevClass === MML.TEXCLASS.OP ||
    687              this.prevClass === MML.TEXCLASS.REL ||
    688              this.prevClass === MML.TEXCLASS.OPEN ||
    689              this.prevClass === MML.TEXCLASS.PUNCT)) {
    690         this.texClass = MML.TEXCLASS.ORD;
    691       } else if (this.prevClass === MML.TEXCLASS.BIN &&
    692                    (this.texClass === MML.TEXCLASS.REL ||
    693                     this.texClass === MML.TEXCLASS.CLOSE ||
    694                     this.texClass === MML.TEXCLASS.PUNCT)) {
    695         prev.texClass = this.prevClass = MML.TEXCLASS.ORD;
    696       } else if (this.texClass === MML.TEXCLASS.BIN) {
    697         //
    698         // Check if node is the last one in its container since the rule
    699         // above only takes effect if there is a node that follows.
    700         //
    701         var child = this, parent = this.parent;
    702         while (parent && parent.parent && parent.isEmbellished() &&
    703               (parent.data.length === 1 ||
    704               (parent.type !== "mrow" && parent.Core() === child))) // handles msubsup and munderover
    705                  {child = parent; parent = parent.parent}
    706         if (parent.data[parent.data.length-1] === child) this.texClass = MML.TEXCLASS.ORD;
    707       }
    708       return this;
    709     }
    710   });
    711   
    712   MML.mtext = MML.mbase.Subclass({
    713     type: "mtext", isToken: true,
    714     isSpacelike: function () {return true},
    715     texClass: MML.TEXCLASS.ORD,
    716     defaults: {
    717       mathvariant: MML.INHERIT,
    718       mathsize: MML.INHERIT,
    719       mathbackground: MML.INHERIT,
    720       mathcolor: MML.INHERIT,
    721       dir: MML.INHERIT
    722     }
    723   });
    724 
    725   MML.mspace = MML.mbase.Subclass({
    726     type: "mspace", isToken: true,
    727     isSpacelike: function () {return true},
    728     defaults: {
    729       mathbackground: MML.INHERIT,
    730       mathcolor: MML.INHERIT,
    731       width: "0em",
    732       height: "0ex",
    733       depth: "0ex",
    734       linebreak: MML.LINEBREAK.AUTO
    735     },
    736     hasDimAttr: function () {
    737       return (this.hasValue("width") || this.hasValue("height") ||
    738               this.hasValue("depth"));
    739     },
    740     hasNewline: function () {
    741       // The MathML spec says that the linebreak attribute should be ignored
    742       // if any dimensional attribute is set.
    743       return (!this.hasDimAttr() &&
    744               this.Get("linebreak") === MML.LINEBREAK.NEWLINE);
    745     }
    746   });
    747 
    748   MML.ms = MML.mbase.Subclass({
    749     type: "ms", isToken: true,
    750     texClass: MML.TEXCLASS.ORD,
    751     defaults: {
    752       mathvariant: MML.INHERIT,
    753       mathsize: MML.INHERIT,
    754       mathbackground: MML.INHERIT,
    755       mathcolor: MML.INHERIT,
    756       dir: MML.INHERIT,
    757       lquote: '"',
    758       rquote: '"'
    759     }
    760   });
    761 
    762   MML.mglyph = MML.mbase.Subclass({
    763     type: "mglyph", isToken: true,
    764     texClass: MML.TEXCLASS.ORD,
    765     defaults: {
    766       mathbackground: MML.INHERIT,
    767       mathcolor: MML.INHERIT,
    768       alt: "",
    769       src: "",
    770       width: MML.AUTO,
    771       height: MML.AUTO,
    772       valign: "0em"
    773     }
    774   });
    775 
    776   MML.mrow = MML.mbase.Subclass({
    777     type: "mrow",
    778     isSpacelike: MML.mbase.childrenSpacelike,
    779     inferred: false, notParent: false,
    780     isEmbellished: function () {
    781       var isEmbellished = false;
    782       for (var i = 0, m = this.data.length; i < m; i++) {
    783         if (this.data[i] == null) continue;
    784         if (this.data[i].isEmbellished()) {
    785           if (isEmbellished) {return false}
    786           isEmbellished = true; this.core = i;
    787         } else if (!this.data[i].isSpacelike()) {return false}
    788       }
    789       return isEmbellished;
    790     },
    791     NonSpaceLength: function () {
    792       var n = 0;
    793       for (var i = 0, m = this.data.length; i < m; i++)
    794         {if (this.data[i] && !this.data[i].isSpacelike()) {n++}}
    795       return n;
    796     },
    797     FirstNonSpace: function () {
    798       for (var i = 0, m = this.data.length; i < m; i++)
    799         {if (this.data[i] && !this.data[i].isSpacelike()) {return this.data[i]}}
    800       return null;
    801     },
    802     LastNonSpace: function () {
    803       for (var i = this.data.length-1; i >= 0; i--)
    804         {if (this.data[0] && !this.data[i].isSpacelike()) {return this.data[i]}}
    805       return null;
    806     },
    807     Core: function () {
    808       if (!(this.isEmbellished()) || typeof(this.core) === "undefined") {return this}
    809       return this.data[this.core];
    810     },
    811     CoreMO: function () {
    812       if (!(this.isEmbellished()) || typeof(this.core) === "undefined") {return this}
    813       return this.data[this.core].CoreMO();
    814     },
    815     toString: function () {
    816       if (this.inferred) {return '[' + this.data.join(',') + ']'}
    817       return this.SUPER(arguments).toString.call(this);
    818     },
    819     setTeXclass: function (prev) {
    820       var i, m = this.data.length;
    821       if ((this.open || this.close) && (!prev || !prev.fnOP)) {
    822         //
    823         // <mrow> came from \left...\right
    824         // so treat as subexpression (tex class INNER)
    825         //
    826         this.getPrevClass(prev); prev = null;
    827         for (i = 0; i < m; i++)
    828           {if (this.data[i]) {prev = this.data[i].setTeXclass(prev)}}
    829         if (!this.hasOwnProperty("texClass")) this.texClass = MML.TEXCLASS.INNER;
    830         return this;
    831       } else {
    832         //
    833         //  Normal <mrow>, so treat as
    834         //  thorugh mrow is not there
    835         //
    836         for (i = 0; i < m; i++)
    837           {if (this.data[i]) {prev = this.data[i].setTeXclass(prev)}}
    838         if (this.data[0]) {this.updateTeXclass(this.data[0])}
    839         return prev;
    840       }
    841     },
    842     getAnnotation: function (name) {
    843       if (this.data.length != 1) return null;
    844       return this.data[0].getAnnotation(name);
    845     }
    846   });
    847 
    848   MML.mfrac = MML.mbase.Subclass({
    849     type: "mfrac", num: 0, den: 1,
    850     linebreakContainer: true,
    851     isEmbellished: MML.mbase.childEmbellished,
    852     Core: MML.mbase.childCore,
    853     CoreMO: MML.mbase.childCoreMO,
    854     defaults: {
    855       mathbackground: MML.INHERIT,
    856       mathcolor: MML.INHERIT,
    857       linethickness: MML.LINETHICKNESS.MEDIUM,
    858       numalign: MML.ALIGN.CENTER,
    859       denomalign: MML.ALIGN.CENTER,
    860       bevelled: false
    861     },
    862     adjustChild_displaystyle: function (n) {return false},
    863     adjustChild_scriptlevel: function (n) {
    864       var level = this.Get("scriptlevel");
    865       if (!this.Get("displaystyle") || level > 0) {level++}
    866       return level;
    867     },
    868     adjustChild_texprimestyle: function (n) {
    869       if (n == this.den) {return true}
    870       return this.Get("texprimestyle");
    871     },
    872     setTeXclass: MML.mbase.setSeparateTeXclasses
    873   });
    874 
    875   MML.msqrt = MML.mbase.Subclass({
    876     type: "msqrt",
    877     inferRow: true,
    878     linebreakContainer: true,
    879     texClass: MML.TEXCLASS.ORD,
    880     setTeXclass: MML.mbase.setSeparateTeXclasses,
    881     adjustChild_texprimestyle: function (n) {return true}
    882   });
    883 
    884   MML.mroot = MML.mbase.Subclass({
    885     type: "mroot",
    886     linebreakContainer: true,
    887     texClass: MML.TEXCLASS.ORD,
    888     adjustChild_displaystyle: function (n) {
    889       if (n === 1) {return false}
    890       return this.Get("displaystyle");
    891     },
    892     adjustChild_scriptlevel: function (n) {
    893       var level = this.Get("scriptlevel");
    894       if (n === 1) {level += 2}
    895       return level;
    896     },
    897     adjustChild_texprimestyle: function (n) {
    898       if (n === 0) {return true};
    899       return this.Get("texprimestyle");
    900     },
    901     setTeXclass: MML.mbase.setSeparateTeXclasses
    902   });
    903 
    904   MML.mstyle = MML.mbase.Subclass({
    905     type: "mstyle",
    906     isSpacelike: MML.mbase.childrenSpacelike,
    907     isEmbellished: MML.mbase.childEmbellished,
    908     Core: MML.mbase.childCore,
    909     CoreMO: MML.mbase.childCoreMO,
    910     inferRow: true,
    911     defaults: {
    912       scriptlevel: MML.INHERIT,
    913       displaystyle: MML.INHERIT,
    914       scriptsizemultiplier: Math.sqrt(1/2),
    915       scriptminsize: "8pt",
    916       mathbackground: MML.INHERIT,
    917       mathcolor: MML.INHERIT,
    918       dir: MML.INHERIT,
    919       infixlinebreakstyle: MML.LINEBREAKSTYLE.BEFORE,
    920       decimalseparator: "."
    921     },
    922     adjustChild_scriptlevel: function (n) {
    923       var level = this.scriptlevel;
    924       if (level == null) {
    925         level = this.Get("scriptlevel");
    926       } else if (String(level).match(/^ *[-+]/)) {
    927         var LEVEL = this.Get("scriptlevel",null,true);
    928         level = LEVEL + parseInt(level);
    929       }
    930       return level;
    931     },
    932     inheritFromMe: true,
    933     noInherit: {
    934       mpadded: {width: true, height: true, depth: true, lspace: true, voffset: true},
    935       mtable:  {width: true, height: true, depth: true, align: true}
    936     },
    937     getRemoved: {fontfamily:"fontFamily", fontweight:"fontWeight", fontstyle:"fontStyle", fontsize:"fontSize"},
    938     setTeXclass: MML.mbase.setChildTeXclass
    939   });
    940 
    941   MML.merror = MML.mbase.Subclass({
    942     type: "merror",
    943     inferRow: true,
    944     linebreakContainer: true,
    945     texClass: MML.TEXCLASS.ORD
    946   });
    947 
    948   MML.mpadded = MML.mbase.Subclass({
    949     type: "mpadded",
    950     inferRow: true,
    951     isSpacelike: MML.mbase.childrenSpacelike,
    952     isEmbellished: MML.mbase.childEmbellished,
    953     Core: MML.mbase.childCore,
    954     CoreMO: MML.mbase.childCoreMO,
    955     defaults: {
    956       mathbackground: MML.INHERIT,
    957       mathcolor: MML.INHERIT,
    958       width: "",
    959       height: "",
    960       depth: "",
    961       lspace: 0,
    962       voffset: 0
    963     },
    964     setTeXclass: MML.mbase.setChildTeXclass
    965   });
    966 
    967   MML.mphantom = MML.mbase.Subclass({
    968     type: "mphantom",
    969     texClass: MML.TEXCLASS.ORD,
    970     inferRow: true,
    971     isSpacelike: MML.mbase.childrenSpacelike,
    972     isEmbellished: MML.mbase.childEmbellished,
    973     Core: MML.mbase.childCore,
    974     CoreMO: MML.mbase.childCoreMO,
    975     setTeXclass: MML.mbase.setChildTeXclass
    976   });
    977 
    978   MML.mfenced = MML.mbase.Subclass({
    979     type: "mfenced",
    980     defaults: {
    981       mathbackground: MML.INHERIT,
    982       mathcolor: MML.INHERIT,
    983       open: '(',
    984       close: ')',
    985       separators: ','
    986     },
    987     addFakeNodes: function () {
    988       var values = this.getValues("open","close","separators");
    989       values.open = values.open.replace(/[ \t\n\r]/g,"");
    990       values.close = values.close.replace(/[ \t\n\r]/g,"");
    991       values.separators = values.separators.replace(/[ \t\n\r]/g,"");
    992       //
    993       //  Create a fake node for the open item
    994       //
    995       if (values.open !== "") {
    996         this.SetData("open",MML.mo(values.open).With({
    997           fence:true, form:MML.FORM.PREFIX, texClass:MML.TEXCLASS.OPEN
    998         }));
    999         //
   1000         //  Clear flag for using MML spacing even though form is specified
   1001         //
   1002         this.data.open.useMMLspacing = 0;
   1003       }
   1004       //
   1005       //  Create fake nodes for the separators
   1006       //
   1007       if (values.separators !== "") {
   1008         while (values.separators.length < this.data.length)
   1009           {values.separators += values.separators.charAt(values.separators.length-1)}
   1010         for (var i = 1, m = this.data.length; i < m; i++) {
   1011           if (this.data[i]) {
   1012             this.SetData("sep"+i,MML.mo(values.separators.charAt(i-1)).With({separator:true}))
   1013             this.data["sep"+i].useMMLspacing = 0;
   1014           }
   1015         }
   1016       }
   1017       //
   1018       //  Create fake node for the close item
   1019       //
   1020       if (values.close !== "") {
   1021         this.SetData("close",MML.mo(values.close).With({
   1022           fence:true, form:MML.FORM.POSTFIX, texClass:MML.TEXCLASS.CLOSE
   1023         }));
   1024         //
   1025         //  Clear flag for using MML spacing even though form is specified
   1026         //
   1027         this.data.close.useMMLspacing = 0;
   1028       }
   1029     },
   1030     texClass: MML.TEXCLASS.OPEN,
   1031     setTeXclass: function (prev) {
   1032       this.addFakeNodes();
   1033       this.getPrevClass(prev);
   1034       if (this.data.open) {prev = this.data.open.setTeXclass(prev)}
   1035       if (this.data[0]) {prev = this.data[0].setTeXclass(prev)}
   1036       for (var i = 1, m = this.data.length; i < m; i++) {
   1037         if (this.data["sep"+i]) {prev = this.data["sep"+i].setTeXclass(prev)}
   1038         if (this.data[i]) {prev = this.data[i].setTeXclass(prev)}
   1039       }
   1040       if (this.data.close) {prev = this.data.close.setTeXclass(prev)}
   1041       this.updateTeXclass(this.data.open);
   1042       this.texClass = MML.TEXCLASS.INNER;
   1043       return prev;
   1044     }
   1045   });
   1046 
   1047   MML.menclose = MML.mbase.Subclass({
   1048     type: "menclose",
   1049     inferRow: true,
   1050     linebreakContainer: true,
   1051     defaults: {
   1052       mathbackground: MML.INHERIT,
   1053       mathcolor: MML.INHERIT,
   1054       notation: MML.NOTATION.LONGDIV,
   1055       texClass: MML.TEXCLASS.ORD
   1056     },
   1057     setTeXclass: MML.mbase.setSeparateTeXclasses
   1058   });
   1059 
   1060   MML.msubsup = MML.mbase.Subclass({
   1061     type: "msubsup", base: 0, sub: 1, sup: 2,
   1062     isEmbellished: MML.mbase.childEmbellished,
   1063     Core: MML.mbase.childCore,
   1064     CoreMO: MML.mbase.childCoreMO,
   1065     defaults: {
   1066       mathbackground: MML.INHERIT,
   1067       mathcolor: MML.INHERIT,
   1068       subscriptshift: "",
   1069       superscriptshift: "",
   1070       texClass: MML.AUTO
   1071     },
   1072     autoDefault: function (name) {
   1073       if (name === "texClass")
   1074         {return (this.isEmbellished() ? this.CoreMO().Get(name) : MML.TEXCLASS.ORD)}
   1075       return 0;
   1076     },
   1077     adjustChild_displaystyle: function (n) {
   1078       if (n > 0) {return false}
   1079       return this.Get("displaystyle");
   1080     },
   1081     adjustChild_scriptlevel: function (n) {
   1082       var level = this.Get("scriptlevel");
   1083       if (n > 0) {level++}
   1084       return level;
   1085     },
   1086     adjustChild_texprimestyle: function (n) {
   1087       if (n === this.sub) {return true}
   1088       return this.Get("texprimestyle");
   1089     },
   1090     setTeXclass: MML.mbase.setBaseTeXclasses
   1091   });
   1092   
   1093   MML.msub = MML.msubsup.Subclass({type: "msub"});
   1094   MML.msup = MML.msubsup.Subclass({type: "msup", sub:2, sup:1});
   1095   MML.mmultiscripts = MML.msubsup.Subclass({
   1096     type: "mmultiscripts",
   1097     adjustChild_texprimestyle: function (n) {
   1098       if (n % 2 === 1) {return true}
   1099       return this.Get("texprimestyle");
   1100     }
   1101   });
   1102   MML.mprescripts = MML.mbase.Subclass({type: "mprescripts"});
   1103   MML.none = MML.mbase.Subclass({type: "none"});
   1104   
   1105   MML.munderover = MML.mbase.Subclass({
   1106     type: "munderover",
   1107     base: 0, under: 1, over: 2, sub: 1, sup: 2,
   1108     ACCENTS: ["", "accentunder", "accent"],
   1109     linebreakContainer: true,
   1110     isEmbellished: MML.mbase.childEmbellished,
   1111     Core: MML.mbase.childCore,
   1112     CoreMO: MML.mbase.childCoreMO,
   1113     defaults: {
   1114       mathbackground: MML.INHERIT,
   1115       mathcolor: MML.INHERIT,
   1116       accent: MML.AUTO,
   1117       accentunder: MML.AUTO,
   1118       align: MML.ALIGN.CENTER,
   1119       texClass: MML.AUTO,
   1120       subscriptshift: "",  // when converted to msubsup by moveablelimits
   1121       superscriptshift: "" // when converted to msubsup by moveablelimits
   1122     },
   1123     autoDefault: function (name) {
   1124       if (name === "texClass")
   1125         {return (this.isEmbellished() ? this.CoreMO().Get(name) : MML.TEXCLASS.ORD)}
   1126       if (name === "accent" && this.data[this.over]) {return this.data[this.over].CoreMO().Get("accent")}
   1127       if (name === "accentunder" && this.data[this.under]) {return this.data[this.under].CoreMO().Get("accent")}
   1128       return false;
   1129     },
   1130     adjustChild_displaystyle: function (n) {
   1131       if (n > 0) {return false}
   1132       return this.Get("displaystyle");
   1133     },
   1134     adjustChild_scriptlevel: function (n) {
   1135       var level = this.Get("scriptlevel");
   1136       var force = (this.data[this.base] && !this.Get("displaystyle") &&
   1137                    this.data[this.base].CoreMO().Get("movablelimits"));
   1138       if (n == this.under && (force || !this.Get("accentunder"))) {level++}
   1139       if (n == this.over  && (force || !this.Get("accent"))) {level++}
   1140       return level;
   1141     },
   1142     adjustChild_texprimestyle: function (n) {
   1143       if (n === this.base && this.data[this.over]) {return true}
   1144       return this.Get("texprimestyle");
   1145     },
   1146     setTeXclass: MML.mbase.setBaseTeXclasses
   1147   });
   1148   
   1149   MML.munder = MML.munderover.Subclass({type: "munder"});
   1150   MML.mover = MML.munderover.Subclass({
   1151     type: "mover", over: 1, under: 2, sup: 1, sub: 2,
   1152     ACCENTS: ["", "accent", "accentunder"]
   1153   });
   1154 
   1155   MML.mtable = MML.mbase.Subclass({
   1156     type: "mtable",
   1157     defaults: {
   1158       mathbackground: MML.INHERIT,
   1159       mathcolor: MML.INHERIT,
   1160       align: MML.ALIGN.AXIS,
   1161       rowalign: MML.ALIGN.BASELINE,
   1162       columnalign: MML.ALIGN.CENTER,
   1163       groupalign: "{left}",
   1164       alignmentscope: true,
   1165       columnwidth: MML.WIDTH.AUTO,
   1166       width: MML.WIDTH.AUTO,
   1167       rowspacing: "1ex",
   1168       columnspacing: ".8em",
   1169       rowlines: MML.LINES.NONE,
   1170       columnlines: MML.LINES.NONE,
   1171       frame: MML.LINES.NONE,
   1172       framespacing: "0.4em 0.5ex",
   1173       equalrows: false,
   1174       equalcolumns: false,
   1175       displaystyle: false,
   1176       side: MML.SIDE.RIGHT,
   1177       minlabelspacing: "0.8em",
   1178       texClass: MML.TEXCLASS.ORD,
   1179       useHeight: 1
   1180     },
   1181     adjustChild_displaystyle: function () {
   1182       return (this.displaystyle != null ? this.displaystyle : this.defaults.displaystyle);
   1183     },
   1184     inheritFromMe: true,
   1185     noInherit: {
   1186       mover: {align: true},
   1187       munder: {align: true},
   1188       munderover: {align: true},
   1189       mtable: {
   1190         align: true, rowalign: true, columnalign: true, groupalign: true,
   1191         alignmentscope: true, columnwidth: true, width: true, rowspacing: true,
   1192         columnspacing: true, rowlines: true, columnlines: true, frame: true,
   1193         framespacing: true, equalrows: true, equalcolumns: true, displaystyle: true,
   1194         side: true, minlabelspacing: true, texClass: true, useHeight: 1
   1195       }
   1196     },
   1197     linebreakContainer: true,
   1198     Append: function () {
   1199       for (var i = 0, m = arguments.length; i < m; i++) {
   1200         if (!((arguments[i] instanceof MML.mtr) ||
   1201               (arguments[i] instanceof MML.mlabeledtr))) {arguments[i] = MML.mtr(arguments[i])}
   1202       }
   1203       this.SUPER(arguments).Append.apply(this,arguments);
   1204     },
   1205     setTeXclass: MML.mbase.setSeparateTeXclasses
   1206   });
   1207 
   1208   MML.mtr = MML.mbase.Subclass({
   1209     type: "mtr",
   1210     defaults: {
   1211       mathbackground: MML.INHERIT,
   1212       mathcolor: MML.INHERIT,
   1213       rowalign: MML.INHERIT,
   1214       columnalign: MML.INHERIT,
   1215       groupalign: MML.INHERIT
   1216     },
   1217     inheritFromMe: true,
   1218     noInherit: {
   1219       mrow: {rowalign: true, columnalign: true, groupalign: true},
   1220       mtable: {rowalign: true, columnalign: true, groupalign: true}
   1221     },
   1222     linebreakContainer: true,
   1223     Append: function () {
   1224       for (var i = 0, m = arguments.length; i < m; i++) {
   1225         if (!(arguments[i] instanceof MML.mtd)) {arguments[i] = MML.mtd(arguments[i])}
   1226       }
   1227       this.SUPER(arguments).Append.apply(this,arguments);
   1228     },
   1229     setTeXclass: MML.mbase.setSeparateTeXclasses
   1230   });
   1231 
   1232   MML.mtd = MML.mbase.Subclass({
   1233     type: "mtd",
   1234     inferRow: true,
   1235     linebreakContainer: true,
   1236     isEmbellished: MML.mbase.childEmbellished,
   1237     Core: MML.mbase.childCore,
   1238     CoreMO: MML.mbase.childCoreMO,
   1239     defaults: {
   1240       mathbackground: MML.INHERIT,
   1241       mathcolor: MML.INHERIT,
   1242       rowspan: 1,
   1243       columnspan: 1,
   1244       rowalign: MML.INHERIT,
   1245       columnalign: MML.INHERIT,
   1246       groupalign: MML.INHERIT
   1247     },
   1248     setTeXclass: MML.mbase.setSeparateTeXclasses
   1249   });
   1250 
   1251   MML.maligngroup = MML.mbase.Subclass({
   1252     type: "maligngroup",
   1253     isSpacelike: function () {return true},
   1254     defaults: {
   1255       mathbackground: MML.INHERIT,
   1256       mathcolor: MML.INHERIT,
   1257       groupalign: MML.INHERIT
   1258     },
   1259     inheritFromMe: true,
   1260     noInherit: {
   1261       mrow: {groupalign: true},
   1262       mtable: {groupalign: true}
   1263     }
   1264   });
   1265 
   1266   MML.malignmark = MML.mbase.Subclass({
   1267     type: "malignmark",
   1268     defaults: {
   1269       mathbackground: MML.INHERIT,
   1270       mathcolor: MML.INHERIT,
   1271       edge: MML.SIDE.LEFT
   1272     },
   1273     isSpacelike: function () {return true}
   1274   });
   1275 
   1276   MML.mlabeledtr = MML.mtr.Subclass({
   1277     type: "mlabeledtr"
   1278   });
   1279   
   1280   MML.maction = MML.mbase.Subclass({
   1281     type: "maction",
   1282     defaults: {
   1283       mathbackground: MML.INHERIT,
   1284       mathcolor: MML.INHERIT,
   1285       actiontype: MML.ACTIONTYPE.TOGGLE,
   1286       selection: 1
   1287     },
   1288     selected: function () {return this.data[this.Get("selection")-1] || MML.NULL},
   1289     isEmbellished: function () {return this.selected().isEmbellished()},
   1290     isSpacelike: function () {return this.selected().isSpacelike()},
   1291     Core: function () {return this.selected().Core()},
   1292     CoreMO: function () {return this.selected().CoreMO()},
   1293     setTeXclass: function (prev) {
   1294       if (this.Get("actiontype") === MML.ACTIONTYPE.TOOLTIP && this.data[1]) {
   1295         // Make sure tooltip has proper spacing when typeset (see issue #412)
   1296         this.data[1].setTeXclass();
   1297       }
   1298       var selected = this.selected();
   1299       prev = selected.setTeXclass(prev);
   1300       this.updateTeXclass(selected);
   1301       return prev;
   1302     }
   1303   });
   1304   
   1305   MML.semantics = MML.mbase.Subclass({
   1306     type: "semantics", notParent: true,
   1307     isEmbellished: MML.mbase.childEmbellished,
   1308     Core: MML.mbase.childCore,
   1309     CoreMO: MML.mbase.childCoreMO,
   1310     defaults: {
   1311       definitionURL: null,
   1312       encoding: null
   1313     },
   1314     setTeXclass: MML.mbase.setChildTeXclass,
   1315     getAnnotation: function (name) {
   1316       var encodingList = MathJax.Hub.config.MathMenu.semanticsAnnotations[name];
   1317       if (encodingList) {
   1318         for (var i = 0, m = this.data.length; i < m; i++) {
   1319           var encoding = this.data[i].Get("encoding");
   1320           if (encoding) {
   1321             for (var j = 0, n = encodingList.length; j < n; j++) {
   1322               if (encodingList[j] === encoding) return this.data[i];
   1323             }
   1324           }
   1325         }
   1326       }
   1327       return null;
   1328     }
   1329   });
   1330   MML.annotation = MML.mbase.Subclass({
   1331     type: "annotation", isChars: true,
   1332     linebreakContainer: true,
   1333     defaults: {
   1334       definitionURL: null,
   1335       encoding: null,
   1336       cd: "mathmlkeys",
   1337       name: "",
   1338       src: null
   1339     }
   1340   });
   1341   MML["annotation-xml"] = MML.mbase.Subclass({
   1342     type: "annotation-xml",
   1343     linebreakContainer: true,
   1344     defaults: {
   1345       definitionURL: null,
   1346       encoding: null,
   1347       cd: "mathmlkeys",
   1348       name: "",
   1349       src: null
   1350     }
   1351   });
   1352 
   1353   MML.math = MML.mstyle.Subclass({
   1354     type: "math",
   1355     defaults: {
   1356       mathvariant: MML.VARIANT.NORMAL,
   1357       mathsize: MML.SIZE.NORMAL,
   1358       mathcolor: "", // should be "black", but allow it to inherit from surrounding text
   1359       mathbackground: MML.COLOR.TRANSPARENT,
   1360       dir: "ltr",
   1361       scriptlevel: 0,
   1362       displaystyle: MML.AUTO,
   1363       display: "inline",
   1364       maxwidth: "",
   1365       overflow: MML.OVERFLOW.LINEBREAK,
   1366       altimg: "",
   1367       'altimg-width': "",
   1368       'altimg-height': "",
   1369       'altimg-valign': "",
   1370       alttext: "",
   1371       cdgroup: "",
   1372       scriptsizemultiplier: Math.sqrt(1/2),
   1373       scriptminsize: "8px",    // should be 8pt, but that's too big
   1374       infixlinebreakstyle: MML.LINEBREAKSTYLE.BEFORE,
   1375       lineleading: "1ex",
   1376       indentshift: "auto",     // use user configuration
   1377       indentalign: MML.INDENTALIGN.AUTO,
   1378       indentalignfirst: MML.INDENTALIGN.INDENTALIGN,
   1379       indentshiftfirst: MML.INDENTSHIFT.INDENTSHIFT,
   1380       indentalignlast:  MML.INDENTALIGN.INDENTALIGN,
   1381       indentshiftlast:  MML.INDENTSHIFT.INDENTSHIFT,
   1382       decimalseparator: ".",
   1383       texprimestyle: false     // is it in TeX's C' style?
   1384     },
   1385     autoDefault: function (name) {
   1386       if (name === "displaystyle") {return this.Get("display") === "block"}
   1387       return "";
   1388     },
   1389     linebreakContainer: true,
   1390     setTeXclass: MML.mbase.setChildTeXclass,
   1391     getAnnotation: function (name) {
   1392       if (this.data.length != 1) return null;
   1393       return this.data[0].getAnnotation(name);
   1394     }
   1395   });
   1396   
   1397   MML.chars = MML.mbase.Subclass({
   1398     type: "chars",
   1399     Append: function () {this.data.push.apply(this.data,arguments)},
   1400     value: function () {return this.data.join("")},
   1401     toString: function () {return this.data.join("")}
   1402   });
   1403   
   1404   MML.entity = MML.mbase.Subclass({
   1405     type: "entity",
   1406     Append: function () {this.data.push.apply(this.data,arguments)},
   1407     value: function () {
   1408       if (this.data[0].substr(0,2) === "#x") {return parseInt(this.data[0].substr(2),16)}
   1409       else if (this.data[0].substr(0,1) === "#") {return parseInt(this.data[0].substr(1))}
   1410       else {return 0}  // FIXME: look up named entities from table
   1411     },
   1412     toString: function () {
   1413       var n = this.value();
   1414       if (n <= 0xFFFF) {return String.fromCharCode(n)}
   1415       n -= 0x10000;
   1416       return String.fromCharCode((n>>10)+0xD800)
   1417            + String.fromCharCode((n&0x3FF)+0xDC00);
   1418     }
   1419   });
   1420   
   1421   MML.xml = MML.mbase.Subclass({
   1422     type: "xml",
   1423     Init: function () {
   1424       this.div = document.createElement("div");
   1425       return this.SUPER(arguments).Init.apply(this,arguments);
   1426     },
   1427     Append: function () {
   1428       for (var i = 0, m = arguments.length; i < m; i++) {
   1429         var node = this.Import(arguments[i]);
   1430         this.data.push(node);
   1431         this.div.appendChild(node);
   1432       }
   1433     },
   1434     Import: function (node) {
   1435       if (document.importNode) {return document.importNode(node,true)}
   1436       //
   1437       //  IE < 9 doesn't have importNode, so fake it.
   1438       //
   1439       var nNode, i, m;
   1440       if (node.nodeType === 1) { // ELEMENT_NODE
   1441         nNode = document.createElement(node.nodeName);
   1442         for (i = 0, m = node.attributes.length; i < m; i++) {
   1443           var attribute = node.attributes[i];
   1444           if (attribute.specified && attribute.nodeValue != null && attribute.nodeValue != '')
   1445             {nNode.setAttribute(attribute.nodeName,attribute.nodeValue)}
   1446           if (attribute.nodeName === "style") {nNode.style.cssText = attribute.nodeValue}
   1447         }
   1448         if (node.className) {nNode.className = node.className}
   1449       } else if (node.nodeType === 3 || node.nodeType === 4) { // TEXT_NODE or CDATA_SECTION_NODE
   1450         nNode = document.createTextNode(node.nodeValue);
   1451       } else if (node.nodeType === 8) { // COMMENT_NODE
   1452         nNode = document.createComment(node.nodeValue);
   1453       } else {
   1454         return document.createTextNode('');
   1455       }
   1456       for (i = 0, m = node.childNodes.length; i < m; i++)
   1457         {nNode.appendChild(this.Import(node.childNodes[i]))}
   1458       return nNode;
   1459     },
   1460     value: function () {return this.div},
   1461     toString: function () {return this.div.innerHTML}
   1462   });
   1463   
   1464   MML.TeXAtom = MML.mbase.Subclass({
   1465     type: "texatom",
   1466     inferRow: true, notParent: true,
   1467     texClass: MML.TEXCLASS.ORD,
   1468     Core: MML.mbase.childCore,
   1469     CoreMO: MML.mbase.childCoreMO,
   1470     isEmbellished: MML.mbase.childEmbellished,
   1471     setTeXclass: function (prev) {
   1472       this.data[0].setTeXclass();
   1473       return this.adjustTeXclass(prev);
   1474     },
   1475     adjustTeXclass: MML.mo.prototype.adjustTeXclass
   1476   });
   1477   
   1478   MML.NULL = MML.mbase().With({type:"null"});
   1479 
   1480   var TEXCLASS = MML.TEXCLASS;
   1481   
   1482   var MO = {
   1483     ORD:        [0,0,TEXCLASS.ORD],
   1484     ORD11:      [1,1,TEXCLASS.ORD],
   1485     ORD21:      [2,1,TEXCLASS.ORD],
   1486     ORD02:      [0,2,TEXCLASS.ORD],
   1487     ORD55:      [5,5,TEXCLASS.ORD],
   1488     OP:         [1,2,TEXCLASS.OP,{largeop: true, movablelimits: true, symmetric: true}],
   1489     OPFIXED:    [1,2,TEXCLASS.OP,{largeop: true, movablelimits: true}],
   1490     INTEGRAL:   [0,1,TEXCLASS.OP,{largeop: true, symmetric: true}],
   1491     INTEGRAL2:  [1,2,TEXCLASS.OP,{largeop: true, symmetric: true}],
   1492     BIN3:       [3,3,TEXCLASS.BIN],
   1493     BIN4:       [4,4,TEXCLASS.BIN],
   1494     BIN01:      [0,1,TEXCLASS.BIN],
   1495     BIN5:       [5,5,TEXCLASS.BIN],
   1496     TALLBIN:    [4,4,TEXCLASS.BIN,{stretchy: true}],
   1497     BINOP:      [4,4,TEXCLASS.BIN,{largeop: true, movablelimits: true}],
   1498     REL:        [5,5,TEXCLASS.REL],
   1499     REL1:       [1,1,TEXCLASS.REL,{stretchy: true}],
   1500     REL4:       [4,4,TEXCLASS.REL],
   1501     RELSTRETCH: [5,5,TEXCLASS.REL,{stretchy: true}],
   1502     RELACCENT:  [5,5,TEXCLASS.REL,{accent: true}],
   1503     WIDEREL:    [5,5,TEXCLASS.REL,{accent: true, stretchy: true}],
   1504     OPEN:       [0,0,TEXCLASS.OPEN,{fence: true, stretchy: true, symmetric: true}],
   1505     CLOSE:      [0,0,TEXCLASS.CLOSE,{fence: true, stretchy: true, symmetric: true}],
   1506     INNER:      [0,0,TEXCLASS.INNER],
   1507     PUNCT:      [0,3,TEXCLASS.PUNCT],
   1508     ACCENT:     [0,0,TEXCLASS.ORD,{accent: true}],
   1509     WIDEACCENT: [0,0,TEXCLASS.ORD,{accent: true, stretchy: true}]
   1510   };
   1511 
   1512   MML.mo.Augment({
   1513     SPACE: [
   1514       '0em',
   1515       '0.1111em',
   1516       '0.1667em',
   1517       '0.2222em',
   1518       '0.2667em',
   1519       '0.3333em'
   1520     ],
   1521     RANGES: [
   1522       [0x20,0x7F,TEXCLASS.REL,"BasicLatin"],
   1523       [0xA0,0xFF,TEXCLASS.ORD,"Latin1Supplement"],
   1524       [0x100,0x17F,TEXCLASS.ORD],
   1525       [0x180,0x24F,TEXCLASS.ORD],
   1526       [0x2B0,0x2FF,TEXCLASS.ORD,"SpacingModLetters"],
   1527       [0x300,0x36F,TEXCLASS.ORD,"CombDiacritMarks"],
   1528       [0x370,0x3FF,TEXCLASS.ORD,"GreekAndCoptic"],
   1529       [0x1E00,0x1EFF,TEXCLASS.ORD],
   1530       [0x2000,0x206F,TEXCLASS.PUNCT,"GeneralPunctuation"],
   1531       [0x2070,0x209F,TEXCLASS.ORD],
   1532       [0x20A0,0x20CF,TEXCLASS.ORD],
   1533       [0x20D0,0x20FF,TEXCLASS.ORD,"CombDiactForSymbols"],
   1534       [0x2100,0x214F,TEXCLASS.ORD,"LetterlikeSymbols"],
   1535       [0x2150,0x218F,TEXCLASS.ORD],
   1536       [0x2190,0x21FF,TEXCLASS.REL,"Arrows"],
   1537       [0x2200,0x22FF,TEXCLASS.BIN,"MathOperators"],
   1538       [0x2300,0x23FF,TEXCLASS.ORD,"MiscTechnical"],
   1539       [0x2460,0x24FF,TEXCLASS.ORD],
   1540       [0x2500,0x259F,TEXCLASS.ORD],
   1541       [0x25A0,0x25FF,TEXCLASS.ORD,"GeometricShapes"],
   1542       [0x2700,0x27BF,TEXCLASS.ORD,"Dingbats"],
   1543       [0x27C0,0x27EF,TEXCLASS.ORD,"MiscMathSymbolsA"],
   1544       [0x27F0,0x27FF,TEXCLASS.REL,"SupplementalArrowsA"],
   1545       [0x2900,0x297F,TEXCLASS.REL,"SupplementalArrowsB"],
   1546       [0x2980,0x29FF,TEXCLASS.ORD,"MiscMathSymbolsB"],
   1547       [0x2A00,0x2AFF,TEXCLASS.BIN,"SuppMathOperators"],
   1548       [0x2B00,0x2BFF,TEXCLASS.ORD,"MiscSymbolsAndArrows"],
   1549       [0x1D400,0x1D7FF,TEXCLASS.ORD]
   1550     ],
   1551     OPTABLE: {
   1552       prefix: {
   1553         '\u2200': MO.ORD21,    // for all
   1554         '\u2202': MO.ORD21,    // partial differential
   1555         '\u2203': MO.ORD21,    // there exists
   1556         '\u2207': MO.ORD21,    // nabla
   1557         '\u220F': MO.OP,       // n-ary product
   1558         '\u2210': MO.OP,       // n-ary coproduct
   1559         '\u2211': MO.OP,       // n-ary summation
   1560         '\u2212': MO.BIN01,    // minus sign
   1561         '\u2213': MO.BIN01,    // minus-or-plus sign
   1562         '\u221A': [1,1,TEXCLASS.ORD,{stretchy: true}], // square root
   1563         '\u2220': MO.ORD,      // angle
   1564         '\u222B': MO.INTEGRAL, // integral
   1565         '\u222E': MO.INTEGRAL, // contour integral
   1566         '\u22C0': MO.OP,       // n-ary logical and
   1567         '\u22C1': MO.OP,       // n-ary logical or
   1568         '\u22C2': MO.OP,       // n-ary intersection
   1569         '\u22C3': MO.OP,       // n-ary union
   1570         '\u2308': MO.OPEN,     // left ceiling
   1571         '\u230A': MO.OPEN,     // left floor
   1572         '\u27E8': MO.OPEN,     // mathematical left angle bracket
   1573         '\u27EE': MO.OPEN,     // mathematical left flattened parenthesis
   1574         '\u2A00': MO.OP,       // n-ary circled dot operator
   1575         '\u2A01': MO.OP,       // n-ary circled plus operator
   1576         '\u2A02': MO.OP,       // n-ary circled times operator
   1577         '\u2A04': MO.OP,       // n-ary union operator with plus
   1578         '\u2A06': MO.OP,       // n-ary square union operator
   1579         '\u00AC': MO.ORD21,    // not sign
   1580         '\u00B1': MO.BIN01,    // plus-minus sign
   1581         '(': MO.OPEN,          // left parenthesis
   1582         '+': MO.BIN01,         // plus sign
   1583         '-': MO.BIN01,         // hyphen-minus
   1584         '[': MO.OPEN,          // left square bracket
   1585         '{': MO.OPEN,          // left curly bracket
   1586         '|': MO.OPEN           // vertical line
   1587       },
   1588       postfix: {
   1589         '!': [1,0,TEXCLASS.CLOSE], // exclamation mark
   1590         '&': MO.ORD,           // ampersand
   1591         '\u2032': MO.ORD02,    // prime
   1592         '\u203E': MO.WIDEACCENT, // overline
   1593         '\u2309': MO.CLOSE,    // right ceiling
   1594         '\u230B': MO.CLOSE,    // right floor
   1595         '\u23DE': MO.WIDEACCENT, // top curly bracket
   1596         '\u23DF': MO.WIDEACCENT, // bottom curly bracket
   1597         '\u266D': MO.ORD02,    // music flat sign
   1598         '\u266E': MO.ORD02,    // music natural sign
   1599         '\u266F': MO.ORD02,    // music sharp sign
   1600         '\u27E9': MO.CLOSE,    // mathematical right angle bracket
   1601         '\u27EF': MO.CLOSE,    // mathematical right flattened parenthesis
   1602         '\u02C6': MO.WIDEACCENT, // modifier letter circumflex accent
   1603         '\u02C7': MO.WIDEACCENT, // caron
   1604         '\u02C9': MO.WIDEACCENT, // modifier letter macron
   1605         '\u02CA': MO.ACCENT,   // modifier letter acute accent
   1606         '\u02CB': MO.ACCENT,   // modifier letter grave accent
   1607         '\u02D8': MO.ACCENT,   // breve
   1608         '\u02D9': MO.ACCENT,   // dot above
   1609         '\u02DC': MO.WIDEACCENT, // small tilde
   1610         '\u0302': MO.WIDEACCENT, // combining circumflex accent
   1611         '\u00A8': MO.ACCENT,   // diaeresis
   1612         '\u00AF': MO.WIDEACCENT, // macron
   1613         ')': MO.CLOSE,         // right parenthesis
   1614         ']': MO.CLOSE,         // right square bracket
   1615         '^': MO.WIDEACCENT,    // circumflex accent
   1616         '_': MO.WIDEACCENT,    // low line
   1617         '`': MO.ACCENT,        // grave accent
   1618         '|': MO.CLOSE,         // vertical line
   1619         '}': MO.CLOSE,         // right curly bracket
   1620         '~': MO.WIDEACCENT     // tilde
   1621       },
   1622       infix: {
   1623         '': MO.ORD,            // empty <mo>
   1624         '%': [3,3,TEXCLASS.ORD], // percent sign
   1625         '\u2022': MO.BIN4,     // bullet
   1626         '\u2026': MO.INNER,    // horizontal ellipsis
   1627         '\u2044': MO.TALLBIN,  // fraction slash
   1628         '\u2061': MO.ORD,      // function application
   1629         '\u2062': MO.ORD,      // invisible times
   1630         '\u2063': [0,0,TEXCLASS.ORD,{linebreakstyle:"after", separator: true}], // invisible separator
   1631         '\u2064': MO.ORD,      // invisible plus
   1632         '\u2190': MO.WIDEREL,  // leftwards arrow
   1633         '\u2191': MO.RELSTRETCH, // upwards arrow
   1634         '\u2192': MO.WIDEREL,  // rightwards arrow
   1635         '\u2193': MO.RELSTRETCH, // downwards arrow
   1636         '\u2194': MO.WIDEREL,  // left right arrow
   1637         '\u2195': MO.RELSTRETCH, // up down arrow
   1638         '\u2196': MO.RELSTRETCH, // north west arrow
   1639         '\u2197': MO.RELSTRETCH, // north east arrow
   1640         '\u2198': MO.RELSTRETCH, // south east arrow
   1641         '\u2199': MO.RELSTRETCH, // south west arrow
   1642         '\u21A6': MO.WIDEREL,  // rightwards arrow from bar
   1643         '\u21A9': MO.WIDEREL,  // leftwards arrow with hook
   1644         '\u21AA': MO.WIDEREL,  // rightwards arrow with hook
   1645         '\u21BC': MO.WIDEREL,  // leftwards harpoon with barb upwards
   1646         '\u21BD': MO.WIDEREL,  // leftwards harpoon with barb downwards
   1647         '\u21C0': MO.WIDEREL,  // rightwards harpoon with barb upwards
   1648         '\u21C1': MO.WIDEREL,  // rightwards harpoon with barb downwards
   1649         '\u21CC': MO.WIDEREL,  // rightwards harpoon over leftwards harpoon
   1650         '\u21D0': MO.WIDEREL,  // leftwards double arrow
   1651         '\u21D1': MO.RELSTRETCH, // upwards double arrow
   1652         '\u21D2': MO.WIDEREL,  // rightwards double arrow
   1653         '\u21D3': MO.RELSTRETCH, // downwards double arrow
   1654         '\u21D4': MO.WIDEREL,  // left right double arrow
   1655         '\u21D5': MO.RELSTRETCH, // up down double arrow
   1656         '\u2208': MO.REL,      // element of
   1657         '\u2209': MO.REL,      // not an element of
   1658         '\u220B': MO.REL,      // contains as member
   1659         '\u2212': MO.BIN4,     // minus sign
   1660         '\u2213': MO.BIN4,     // minus-or-plus sign
   1661         '\u2215': MO.TALLBIN,  // division slash
   1662         '\u2216': MO.BIN4,     // set minus
   1663         '\u2217': MO.BIN4,     // asterisk operator
   1664         '\u2218': MO.BIN4,     // ring operator
   1665         '\u2219': MO.BIN4,     // bullet operator
   1666         '\u221D': MO.REL,      // proportional to
   1667         '\u2223': MO.REL,      // divides
   1668         '\u2225': MO.REL,      // parallel to
   1669         '\u2227': MO.BIN4,     // logical and
   1670         '\u2228': MO.BIN4,     // logical or
   1671         '\u2229': MO.BIN4,     // intersection
   1672         '\u222A': MO.BIN4,     // union
   1673         '\u223C': MO.REL,      // tilde operator
   1674         '\u2240': MO.BIN4,     // wreath product
   1675         '\u2243': MO.REL,      // asymptotically equal to
   1676         '\u2245': MO.REL,      // approximately equal to
   1677         '\u2248': MO.REL,      // almost equal to
   1678         '\u224D': MO.REL,      // equivalent to
   1679         '\u2250': MO.REL,      // approaches the limit
   1680         '\u2260': MO.REL,      // not equal to
   1681         '\u2261': MO.REL,      // identical to
   1682         '\u2264': MO.REL,      // less-than or equal to
   1683         '\u2265': MO.REL,      // greater-than or equal to
   1684         '\u226A': MO.REL,      // much less-than
   1685         '\u226B': MO.REL,      // much greater-than
   1686         '\u227A': MO.REL,      // precedes
   1687         '\u227B': MO.REL,      // succeeds
   1688         '\u2282': MO.REL,      // subset of
   1689         '\u2283': MO.REL,      // superset of
   1690         '\u2286': MO.REL,      // subset of or equal to
   1691         '\u2287': MO.REL,      // superset of or equal to
   1692         '\u228E': MO.BIN4,     // multiset union
   1693         '\u2291': MO.REL,      // square image of or equal to
   1694         '\u2292': MO.REL,      // square original of or equal to
   1695         '\u2293': MO.BIN4,     // square cap
   1696         '\u2294': MO.BIN4,     // square cup
   1697         '\u2295': MO.BIN4,     // circled plus
   1698         '\u2296': MO.BIN4,     // circled minus
   1699         '\u2297': MO.BIN4,     // circled times
   1700         '\u2298': MO.BIN4,     // circled division slash
   1701         '\u2299': MO.BIN4,     // circled dot operator
   1702         '\u22A2': MO.REL,      // right tack
   1703         '\u22A3': MO.REL,      // left tack
   1704         '\u22A4': MO.ORD55,    // down tack
   1705         '\u22A5': MO.REL,      // up tack
   1706         '\u22A8': MO.REL,      // true
   1707         '\u22C4': MO.BIN4,     // diamond operator
   1708         '\u22C5': MO.BIN4,     // dot operator
   1709         '\u22C6': MO.BIN4,     // star operator
   1710         '\u22C8': MO.REL,      // bowtie
   1711         '\u22EE': MO.ORD55,    // vertical ellipsis
   1712         '\u22EF': MO.INNER,    // midline horizontal ellipsis
   1713         '\u22F1': [5,5,TEXCLASS.INNER], // down right diagonal ellipsis
   1714         '\u25B3': MO.BIN4,     // white up-pointing triangle
   1715         '\u25B5': MO.BIN4,     // white up-pointing small triangle
   1716         '\u25B9': MO.BIN4,     // white right-pointing small triangle
   1717         '\u25BD': MO.BIN4,     // white down-pointing triangle
   1718         '\u25BF': MO.BIN4,     // white down-pointing small triangle
   1719         '\u25C3': MO.BIN4,     // white left-pointing small triangle
   1720         '\u2758': MO.REL,      // light vertical bar
   1721         '\u27F5': MO.WIDEREL,  // long leftwards arrow
   1722         '\u27F6': MO.WIDEREL,  // long rightwards arrow
   1723         '\u27F7': MO.WIDEREL,  // long left right arrow
   1724         '\u27F8': MO.WIDEREL,  // long leftwards double arrow
   1725         '\u27F9': MO.WIDEREL,  // long rightwards double arrow
   1726         '\u27FA': MO.WIDEREL,  // long left right double arrow
   1727         '\u27FC': MO.WIDEREL,  // long rightwards arrow from bar
   1728         '\u2A2F': MO.BIN4,     // vector or cross product
   1729         '\u2A3F': MO.BIN4,     // amalgamation or coproduct
   1730         '\u2AAF': MO.REL,      // precedes above single-line equals sign
   1731         '\u2AB0': MO.REL,      // succeeds above single-line equals sign
   1732         '\u00B1': MO.BIN4,     // plus-minus sign
   1733         '\u00B7': MO.BIN4,     // middle dot
   1734         '\u00D7': MO.BIN4,     // multiplication sign
   1735         '\u00F7': MO.BIN4,     // division sign
   1736         '*': MO.BIN3,          // asterisk
   1737         '+': MO.BIN4,          // plus sign
   1738         ',': [0,3,TEXCLASS.PUNCT,{linebreakstyle:"after", separator: true}], // comma
   1739         '-': MO.BIN4,          // hyphen-minus
   1740         '.': [3,3,TEXCLASS.ORD], // full stop
   1741         '/': MO.ORD11,         // solidus
   1742         ':': [1,2,TEXCLASS.REL], // colon
   1743         ';': [0,3,TEXCLASS.PUNCT,{linebreakstyle:"after", separator: true}], // semicolon
   1744         '<': MO.REL,           // less-than sign
   1745         '=': MO.REL,           // equals sign
   1746         '>': MO.REL,           // greater-than sign
   1747         '?': [1,1,TEXCLASS.CLOSE], // question mark
   1748         '\\': MO.ORD,          // reverse solidus
   1749         '^': MO.ORD11,         // circumflex accent
   1750         '_': MO.ORD11,         // low line
   1751         '|': [2,2,TEXCLASS.ORD,{fence: true, stretchy: true, symmetric: true}], // vertical line
   1752         '#': MO.ORD,           // #
   1753         '$': MO.ORD,           // $
   1754         '\u002E': [0,3,TEXCLASS.PUNCT,{separator: true}], // \ldotp
   1755         '\u02B9': MO.ORD,      // prime
   1756         '\u0300': MO.ACCENT,   // \grave
   1757         '\u0301': MO.ACCENT,   // \acute
   1758         '\u0303': MO.WIDEACCENT, // \tilde
   1759         '\u0304': MO.ACCENT,   // \bar
   1760         '\u0306': MO.ACCENT,   // \breve
   1761         '\u0307': MO.ACCENT,   // \dot
   1762         '\u0308': MO.ACCENT,   // \ddot
   1763         '\u030C': MO.ACCENT,   // \check
   1764         '\u0332': MO.WIDEACCENT, // horizontal line
   1765         '\u0338': MO.REL4,     // \not
   1766         '\u2015': [0,0,TEXCLASS.ORD,{stretchy: true}], // horizontal line
   1767         '\u2017': [0,0,TEXCLASS.ORD,{stretchy: true}], // horizontal line
   1768         '\u2020': MO.BIN3,     // \dagger
   1769         '\u2021': MO.BIN3,     // \ddagger
   1770         '\u20D7': MO.ACCENT,   // \vec
   1771         '\u2111': MO.ORD,      // \Im
   1772         '\u2113': MO.ORD,      // \ell
   1773         '\u2118': MO.ORD,      // \wp
   1774         '\u211C': MO.ORD,      // \Re
   1775         '\u2205': MO.ORD,      // \emptyset
   1776         '\u221E': MO.ORD,      // \infty
   1777         '\u2305': MO.BIN3,     // barwedge
   1778         '\u2306': MO.BIN3,     // doublebarwedge
   1779         '\u2322': MO.REL4,     // \frown
   1780         '\u2323': MO.REL4,     // \smile
   1781         '\u2329': MO.OPEN,     // langle
   1782         '\u232A': MO.CLOSE,    // rangle
   1783         '\u23AA': MO.ORD,      // \bracevert
   1784         '\u23AF': [0,0,TEXCLASS.ORD,{stretchy: true}], // \underline
   1785         '\u23B0': MO.OPEN,     // \lmoustache
   1786         '\u23B1': MO.CLOSE,    // \rmoustache
   1787         '\u2500': MO.ORD,      // horizontal line
   1788         '\u25EF': MO.BIN3,     // \bigcirc
   1789         '\u2660': MO.ORD,      // \spadesuit
   1790         '\u2661': MO.ORD,      // \heartsuit
   1791         '\u2662': MO.ORD,      // \diamondsuit
   1792         '\u2663': MO.ORD,      // \clubsuit
   1793         '\u3008': MO.OPEN,     // langle
   1794         '\u3009': MO.CLOSE,    // rangle
   1795         '\uFE37': MO.WIDEACCENT, // horizontal brace down
   1796         '\uFE38': MO.WIDEACCENT  // horizontal brace up
   1797       }
   1798     }
   1799   },{
   1800     OPTYPES: MO
   1801   });
   1802   
   1803   //
   1804   //  These are not in the W3C table, but FF works this way,
   1805   //  and it makes sense, so add it here
   1806   //
   1807   var OPTABLE = MML.mo.prototype.OPTABLE;
   1808   OPTABLE.infix["^"] = MO.WIDEREL;
   1809   OPTABLE.infix["_"] = MO.WIDEREL;
   1810   OPTABLE.prefix["\u2223"] = MO.OPEN;
   1811   OPTABLE.prefix["\u2225"] = MO.OPEN;
   1812   OPTABLE.postfix["\u2223"] = MO.CLOSE;
   1813   OPTABLE.postfix["\u2225"] = MO.CLOSE;
   1814   
   1815 })(MathJax.ElementJax.mml);
   1816 
   1817 MathJax.ElementJax.mml.loadComplete("jax.js");