UNPKG

mathjax

Version:

Beautiful math in all browsers. MathJax is an open-source JavaScript display engine for LaTeX, MathML, and AsciiMath notation that works in all browsers.

1,257 lines (1,161 loc) 92.1 kB
/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ /* vim: set ts=2 et sw=2 tw=80: */ /************************************************************* * * MathJax/jax/input/TeX/jax.js * * Implements the TeX InputJax that reads mathematics in * TeX and LaTeX format and converts it to the MML ElementJax * internal format. * * --------------------------------------------------------------------- * * Copyright (c) 2009-2019 The MathJax Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ (function (TEX,HUB,AJAX) { var MML, NBSP = "\u00A0"; var _ = function (id) { return MathJax.Localization._.apply(MathJax.Localization, [["TeX", id]].concat([].slice.call(arguments,1))); }; var isArray = MathJax.Object.isArray; var STACK = MathJax.Object.Subclass({ Init: function (env,inner) { this.global = {isInner: inner}; this.data = [STACKITEM.start(this.global)]; if (env) {this.data[0].env = env} this.env = this.data[0].env; }, Push: function () { var i, m, item, top; for (i = 0, m = arguments.length; i < m; i++) { item = arguments[i]; if (!item) continue; if (item instanceof MML.mbase) {item = STACKITEM.mml(item)} item.global = this.global; top = (this.data.length ? this.Top().checkItem(item) : true); if (top instanceof Array) {this.Pop(); this.Push.apply(this,top)} else if (top instanceof STACKITEM) {this.Pop(); this.Push(top)} else if (top) { this.data.push(item); if (item.env) { if (item.copyEnv !== false) { for (var id in this.env) {if (this.env.hasOwnProperty(id)) {item.env[id] = this.env[id]}} } this.env = item.env; } else {item.env = this.env} } } }, Pop: function () { var item = this.data.pop(); if (!item.isOpen) {delete item.env} this.env = (this.data.length ? this.Top().env : {}); return item; }, Top: function (n) { if (n == null) {n = 1} if (this.data.length < n) {return null} return this.data[this.data.length-n]; }, Prev: function (noPop) { var top = this.Top(); if (noPop) {return top.data[top.data.length-1]} else {return top.Pop()} }, toString: function () {return "stack[\n "+this.data.join("\n ")+"\n]"} }); var STACKITEM = STACK.Item = MathJax.Object.Subclass({ type: "base", endError: /*_()*/ ["ExtraOpenMissingClose","Extra open brace or missing close brace"], closeError: /*_()*/ ["ExtraCloseMissingOpen","Extra close brace or missing open brace"], rightError: /*_()*/ ["MissingLeftExtraRight","Missing \\left or extra \\right"], Init: function () { if (this.isOpen) {this.env = {}} this.data = []; this.Push.apply(this,arguments); }, Push: function () {this.data.push.apply(this.data,arguments)}, Pop: function () {return this.data.pop()}, mmlData: function (inferred,forceRow) { if (inferred == null) {inferred = true} if (this.data.length === 1 && !forceRow) {return this.data[0]} return MML.mrow.apply(MML,this.data).With((inferred ? {inferred: true}: {})); }, checkItem: function (item) { if (item.type === "over" && this.isOpen) {item.num = this.mmlData(false); this.data = []} if (item.type === "cell" && this.isOpen) { if (item.linebreak) {return false} TEX.Error(["Misplaced","Misplaced %1",item.name]); } if (item.isClose && this[item.type+"Error"]) {TEX.Error(this[item.type+"Error"])} if (!item.isNotStack) {return true} this.Push(item.data[0]); return false; }, With: function (def) { for (var id in def) {if (def.hasOwnProperty(id)) {this[id] = def[id]}} return this; }, toString: function () {return this.type+"["+this.data.join("; ")+"]"} }); STACKITEM.start = STACKITEM.Subclass({ type: "start", isOpen: true, Init: function (global) { this.SUPER(arguments).Init.call(this); this.global = global; }, checkItem: function (item) { if (item.type === "stop") {return STACKITEM.mml(this.mmlData())} return this.SUPER(arguments).checkItem.call(this,item); } }); STACKITEM.stop = STACKITEM.Subclass({ type: "stop", isClose: true }); STACKITEM.open = STACKITEM.Subclass({ type: "open", isOpen: true, stopError: /*_()*/ ["ExtraOpenMissingClose","Extra open brace or missing close brace"], checkItem: function (item) { if (item.type === "close") { var mml = this.mmlData(); return STACKITEM.mml(MML.TeXAtom(mml)); // TeXAtom make it an ORD to prevent spacing (FIXME: should be another way) } return this.SUPER(arguments).checkItem.call(this,item); } }); STACKITEM.close = STACKITEM.Subclass({ type: "close", isClose: true }); STACKITEM.prime = STACKITEM.Subclass({ type: "prime", checkItem: function (item) { if (this.data[0].type !== "msubsup") {return [MML.msup(this.data[0],this.data[1]),item]} this.data[0].SetData(this.data[0].sup,this.data[1]); return [this.data[0],item]; } }); STACKITEM.subsup = STACKITEM.Subclass({ type: "subsup", stopError: /*_()*/ ["MissingScript","Missing superscript or subscript argument"], supError: /*_()*/ ["MissingOpenForSup","Missing open brace for superscript"], subError: /*_()*/ ["MissingOpenForSub","Missing open brace for subscript"], checkItem: function (item) { if (item.type === "open" || item.type === "left") {return true} if (item.type === "mml") { if (this.primes) { if (this.position !== 2) {this.data[0].SetData(2,this.primes)} else {item.data[0] = MML.mrow(this.primes.With({variantForm:true}),item.data[0])} } this.data[0].SetData(this.position,item.data[0]); if (this.movesupsub != null) {this.data[0].movesupsub = this.movesupsub} return STACKITEM.mml(this.data[0]); } if (this.SUPER(arguments).checkItem.call(this,item)) {TEX.Error(this[["","subError","supError"][this.position]])} }, Pop: function () {} }); STACKITEM.over = STACKITEM.Subclass({ type: "over", isClose: true, name: "\\over", checkItem: function (item,stack) { if (item.type === "over") {TEX.Error(["AmbiguousUseOf","Ambiguous use of %1",item.name])} if (item.isClose) { var mml = MML.mfrac(this.num,this.mmlData(false)); if (this.thickness != null) {mml.linethickness = this.thickness} if (this.open || this.close) { mml.texWithDelims = true; mml = TEX.fixedFence(this.open,mml,this.close); } return [STACKITEM.mml(mml), item]; } return this.SUPER(arguments).checkItem.call(this,item); }, toString: function () {return "over["+this.num+" / "+this.data.join("; ")+"]"} }); STACKITEM.left = STACKITEM.Subclass({ type: "left", isOpen: true, delim: '(', stopError: /*_()*/ ["ExtraLeftMissingRight", "Extra \\left or missing \\right"], checkItem: function (item) { if (item.type === "right") {return STACKITEM.mml(TEX.fenced(this.delim,this.mmlData(),item.delim))} return this.SUPER(arguments).checkItem.call(this,item); } }); STACKITEM.right = STACKITEM.Subclass({ type: "right", isClose: true, delim: ')' }); STACKITEM.begin = STACKITEM.Subclass({ type: "begin", isOpen: true, checkItem: function (item) { if (item.type === "end") { if (item.name !== this.name) {TEX.Error(["EnvBadEnd","\\begin{%1} ended with \\end{%2}",this.name,item.name])} if (!this.end) {return STACKITEM.mml(this.mmlData())} return this.parse[this.end].call(this.parse,this,this.data); } if (item.type === "stop") {TEX.Error(["EnvMissingEnd","Missing \\end{%1}",this.name])} return this.SUPER(arguments).checkItem.call(this,item); } }); STACKITEM.end = STACKITEM.Subclass({ type: "end", isClose: true }); STACKITEM.style = STACKITEM.Subclass({ type: "style", checkItem: function (item) { if (!item.isClose) {return this.SUPER(arguments).checkItem.call(this,item)} var mml = MML.mstyle.apply(MML,this.data).With(this.styles); return [STACKITEM.mml(mml),item]; } }); STACKITEM.position = STACKITEM.Subclass({ type: "position", checkItem: function (item) { if (item.isClose) {TEX.Error(["MissingBoxFor","Missing box for %1",this.name])} if (item.isNotStack) { var mml = item.mmlData(); switch (this.move) { case 'vertical': mml = MML.mpadded(mml).With({height: this.dh, depth: this.dd, voffset: this.dh}); return [STACKITEM.mml(mml)]; case 'horizontal': return [STACKITEM.mml(this.left),item,STACKITEM.mml(this.right)]; } } return this.SUPER(arguments).checkItem.call(this,item); } }); STACKITEM.array = STACKITEM.Subclass({ type: "array", isOpen: true, copyEnv: false, arraydef: {}, Init: function () { this.table = []; this.row = []; this.frame = []; this.hfill = []; this.SUPER(arguments).Init.apply(this,arguments); }, checkItem: function (item) { if (item.isClose && item.type !== "over") { if (item.isEntry) {this.EndEntry(); this.clearEnv(); return false} if (item.isCR) {this.EndEntry(); this.EndRow(); this.clearEnv(); return false} this.EndTable(); this.clearEnv(); var scriptlevel = this.arraydef.scriptlevel; delete this.arraydef.scriptlevel; var mml = MML.mtable.apply(MML,this.table).With(this.arraydef); if (this.frame.length === 4) { mml.frame = (this.frame.dashed ? "dashed" : "solid"); } else if (this.frame.length) { mml.hasFrame = true; if (this.arraydef.rowlines) {this.arraydef.rowlines = this.arraydef.rowlines.replace(/none( none)+$/,"none")} mml = MML.menclose(mml).With({notation: this.frame.join(" "), isFrame: true}); if ((this.arraydef.columnlines||"none") != "none" || (this.arraydef.rowlines||"none") != "none") {mml.padding = 0} // HTML-CSS jax implements this } if (scriptlevel) {mml = MML.mstyle(mml).With({scriptlevel: scriptlevel})} if (this.open || this.close) {mml = TEX.fenced(this.open,mml,this.close)} mml = STACKITEM.mml(mml); if (this.requireClose) { if (item.type === 'close') {return mml} TEX.Error(["MissingCloseBrace","Missing close brace"]); } return [mml,item]; } return this.SUPER(arguments).checkItem.call(this,item); }, EndEntry: function () { var mtd = MML.mtd.apply(MML,this.data); if (this.hfill.length) { if (this.hfill[0] === 0) mtd.columnalign = "right"; if (this.hfill[this.hfill.length-1] === this.data.length) mtd.columnalign = (mtd.columnalign ? "center" : "left"); } this.row.push(mtd); this.data = []; this.hfill = []; }, EndRow: function () { var mtr = MML.mtr; if (this.isNumbered && this.row.length === 3) { this.row.unshift(this.row.pop()); // move equation number to first position mtr = MML.mlabeledtr; } this.table.push(mtr.apply(MML,this.row)); this.row = []; }, EndTable: function () { if (this.data.length || this.row.length) {this.EndEntry(); this.EndRow()} this.checkLines(); }, checkLines: function () { if (this.arraydef.rowlines) { var lines = this.arraydef.rowlines.split(/ /); if (lines.length === this.table.length) { this.frame.push("bottom"); lines.pop(); this.arraydef.rowlines = lines.join(' '); } else if (lines.length < this.table.length-1) { this.arraydef.rowlines += " none"; } } if (this.rowspacing) { var rows = this.arraydef.rowspacing.split(/ /); while (rows.length < this.table.length) {rows.push(this.rowspacing+"em")} this.arraydef.rowspacing = rows.join(' '); } }, clearEnv: function () { for (var id in this.env) {if (this.env.hasOwnProperty(id)) {delete this.env[id]}} } }); STACKITEM.cell = STACKITEM.Subclass({ type: "cell", isClose: true }); STACKITEM.mml = STACKITEM.Subclass({ type: "mml", isNotStack: true, Add: function () {this.data.push.apply(this.data,arguments); return this} }); STACKITEM.fn = STACKITEM.Subclass({ type: "fn", checkItem: function (item) { if (this.data[0]) { if (item.isOpen) {return true} if (item.type !== "fn") { if (item.type !== "mml" || !item.data[0]) {return [this.data[0],item]} if (item.data[0].isa(MML.mspace)) {return [this.data[0],item]} var mml = item.data[0]; if (mml.isEmbellished()) {mml = mml.CoreMO()} if ([0,0,1,1,0,1,1,0,0,0][mml.Get("texClass")]) {return [this.data[0],item]} } return [this.data[0],MML.mo(MML.entity("#x2061")).With({texClass:MML.TEXCLASS.NONE}),item]; } return this.SUPER(arguments).checkItem.apply(this,arguments); } }); STACKITEM.not = STACKITEM.Subclass({ type: "not", checkItem: function (item) { var mml, c; if (item.type === "open" || item.type === "left") {return true} if (item.type === "mml" && item.data[0].type.match(/^(mo|mi|mtext)$/)) { mml = item.data[0], c = mml.data.join(""); if (c.length === 1 && !mml.movesupsub && mml.data.length === 1) { c = STACKITEM.not.remap[c.charCodeAt(0)]; if (c) {mml.SetData(0,MML.chars(String.fromCharCode(c)))} else {mml.Append(MML.chars("\u0338"))} return item; } } // \mathrel{\rlap{\notChar}} mml = MML.mpadded(MML.mtext("\u29F8")).With({width:0}); mml = MML.TeXAtom(mml).With({texClass:MML.TEXCLASS.REL}); return [mml,item]; } }); STACKITEM.not.remap = { 0x2190:0x219A, 0x2192:0x219B, 0x2194:0x21AE, 0x21D0:0x21CD, 0x21D2:0x21CF, 0x21D4:0x21CE, 0x2208:0x2209, 0x220B:0x220C, 0x2223:0x2224, 0x2225:0x2226, 0x223C:0x2241, 0x007E:0x2241, 0x2243:0x2244, 0x2245:0x2247, 0x2248:0x2249, 0x224D:0x226D, 0x003D:0x2260, 0x2261:0x2262, 0x003C:0x226E, 0x003E:0x226F, 0x2264:0x2270, 0x2265:0x2271, 0x2272:0x2274, 0x2273:0x2275, 0x2276:0x2278, 0x2277:0x2279, 0x227A:0x2280, 0x227B:0x2281, 0x2282:0x2284, 0x2283:0x2285, 0x2286:0x2288, 0x2287:0x2289, 0x22A2:0x22AC, 0x22A8:0x22AD, 0x22A9:0x22AE, 0x22AB:0x22AF, 0x227C:0x22E0, 0x227D:0x22E1, 0x2291:0x22E2, 0x2292:0x22E3, 0x22B2:0x22EA, 0x22B3:0x22EB, 0x22B4:0x22EC, 0x22B5:0x22ED, 0x2203:0x2204 }; STACKITEM.dots = STACKITEM.Subclass({ type: "dots", checkItem: function (item) { if (item.type === "open" || item.type === "left") {return true} var dots = this.ldots; if (item.type === "mml" && item.data[0].isEmbellished()) { var tclass = item.data[0].CoreMO().Get("texClass"); if (tclass === MML.TEXCLASS.BIN || tclass === MML.TEXCLASS.REL) {dots = this.cdots} } return [dots,item]; } }); var TEXDEF = { // // Add new definitions without overriding user-defined ones // Add: function (src,dst,nouser) { if (!dst) {dst = this} for (var id in src) {if (src.hasOwnProperty(id)) { if (typeof src[id] === 'object' && !isArray(src[id]) && (typeof dst[id] === 'object' || typeof dst[id] === 'function')) {this.Add(src[id],dst[id],src[id],nouser)} else if (!dst[id] || !dst[id].isUser || !nouser) {dst[id] = src[id]} }} return dst; } }; var STARTUP = function () { MML = MathJax.ElementJax.mml; HUB.Insert(TEXDEF,{ // patterns for letters and numbers letter: /[a-z]/i, digit: /[0-9.]/, number: /^(?:[0-9]+(?:\{,\}[0-9]{3})*(?:\.[0-9]*)*|\.[0-9]+)/, special: { '\\': 'ControlSequence', '{': 'Open', '}': 'Close', '~': 'Tilde', '^': 'Superscript', '_': 'Subscript', ' ': 'Space', "\t": 'Space', "\r": 'Space', "\n": 'Space', "'": 'Prime', '%': 'Comment', '&': 'Entry', '#': 'Hash', '\u00A0': 'Space', '\u2019': 'Prime' }, remap: { '-': '2212', '*': '2217', '`': '2018' // map ` to back quote }, mathchar0mi: { // Lower-case greek alpha: '03B1', beta: '03B2', gamma: '03B3', delta: '03B4', epsilon: '03F5', zeta: '03B6', eta: '03B7', theta: '03B8', iota: '03B9', kappa: '03BA', lambda: '03BB', mu: '03BC', nu: '03BD', xi: '03BE', omicron: '03BF', // added for completeness pi: '03C0', rho: '03C1', sigma: '03C3', tau: '03C4', upsilon: '03C5', phi: '03D5', chi: '03C7', psi: '03C8', omega: '03C9', varepsilon: '03B5', vartheta: '03D1', varpi: '03D6', varrho: '03F1', varsigma: '03C2', varphi: '03C6', // Ord symbols S: ['00A7',{mathvariant: MML.VARIANT.NORMAL}], aleph: ['2135',{mathvariant: MML.VARIANT.NORMAL}], hbar: ['210F',{variantForm:true}], imath: '0131', jmath: '0237', ell: '2113', wp: ['2118',{mathvariant: MML.VARIANT.NORMAL}], Re: ['211C',{mathvariant: MML.VARIANT.NORMAL}], Im: ['2111',{mathvariant: MML.VARIANT.NORMAL}], partial: ['2202',{mathvariant: MML.VARIANT.NORMAL}], infty: ['221E',{mathvariant: MML.VARIANT.NORMAL}], prime: ['2032',{mathvariant: MML.VARIANT.NORMAL, variantForm:true}], emptyset: ['2205',{mathvariant: MML.VARIANT.NORMAL}], nabla: ['2207',{mathvariant: MML.VARIANT.NORMAL}], top: ['22A4',{mathvariant: MML.VARIANT.NORMAL}], bot: ['22A5',{mathvariant: MML.VARIANT.NORMAL}], angle: ['2220',{mathvariant: MML.VARIANT.NORMAL}], triangle: ['25B3',{mathvariant: MML.VARIANT.NORMAL}], backslash: ['2216',{mathvariant: MML.VARIANT.NORMAL, variantForm:true}], forall: ['2200',{mathvariant: MML.VARIANT.NORMAL}], exists: ['2203',{mathvariant: MML.VARIANT.NORMAL}], neg: ['00AC',{mathvariant: MML.VARIANT.NORMAL}], lnot: ['00AC',{mathvariant: MML.VARIANT.NORMAL}], flat: ['266D',{mathvariant: MML.VARIANT.NORMAL}], natural: ['266E',{mathvariant: MML.VARIANT.NORMAL}], sharp: ['266F',{mathvariant: MML.VARIANT.NORMAL}], clubsuit: ['2663',{mathvariant: MML.VARIANT.NORMAL}], diamondsuit: ['2662',{mathvariant: MML.VARIANT.NORMAL}], heartsuit: ['2661',{mathvariant: MML.VARIANT.NORMAL}], spadesuit: ['2660',{mathvariant: MML.VARIANT.NORMAL}] }, mathchar0mo: { surd: '221A', // big ops coprod: ['2210',{texClass: MML.TEXCLASS.OP, movesupsub:true}], bigvee: ['22C1',{texClass: MML.TEXCLASS.OP, movesupsub:true}], bigwedge: ['22C0',{texClass: MML.TEXCLASS.OP, movesupsub:true}], biguplus: ['2A04',{texClass: MML.TEXCLASS.OP, movesupsub:true}], bigcap: ['22C2',{texClass: MML.TEXCLASS.OP, movesupsub:true}], bigcup: ['22C3',{texClass: MML.TEXCLASS.OP, movesupsub:true}], 'int': ['222B',{texClass: MML.TEXCLASS.OP}], intop: ['222B',{texClass: MML.TEXCLASS.OP, movesupsub:true, movablelimits:true}], iint: ['222C',{texClass: MML.TEXCLASS.OP}], iiint: ['222D',{texClass: MML.TEXCLASS.OP}], prod: ['220F',{texClass: MML.TEXCLASS.OP, movesupsub:true}], sum: ['2211',{texClass: MML.TEXCLASS.OP, movesupsub:true}], bigotimes: ['2A02',{texClass: MML.TEXCLASS.OP, movesupsub:true}], bigoplus: ['2A01',{texClass: MML.TEXCLASS.OP, movesupsub:true}], bigodot: ['2A00',{texClass: MML.TEXCLASS.OP, movesupsub:true}], oint: ['222E',{texClass: MML.TEXCLASS.OP}], bigsqcup: ['2A06',{texClass: MML.TEXCLASS.OP, movesupsub:true}], smallint: ['222B',{largeop:false}], // binary operations triangleleft: '25C3', triangleright: '25B9', bigtriangleup: '25B3', bigtriangledown: '25BD', wedge: '2227', land: '2227', vee: '2228', lor: '2228', cap: '2229', cup: '222A', ddagger: '2021', dagger: '2020', sqcap: '2293', sqcup: '2294', uplus: '228E', amalg: '2A3F', diamond: '22C4', bullet: '2219', wr: '2240', div: '00F7', odot: ['2299',{largeop: false}], oslash: ['2298',{largeop: false}], otimes: ['2297',{largeop: false}], ominus: ['2296',{largeop: false}], oplus: ['2295',{largeop: false}], mp: '2213', pm: '00B1', circ: '2218', bigcirc: '25EF', setminus: ['2216',{variantForm:true}], cdot: '22C5', ast: '2217', times: '00D7', star: '22C6', // Relations propto: '221D', sqsubseteq: '2291', sqsupseteq: '2292', parallel: '2225', mid: '2223', dashv: '22A3', vdash: '22A2', leq: '2264', le: '2264', geq: '2265', ge: '2265', lt: '003C', gt: '003E', succ: '227B', prec: '227A', approx: '2248', succeq: '2AB0', // or '227C', preceq: '2AAF', // or '227D', supset: '2283', subset: '2282', supseteq: '2287', subseteq: '2286', 'in': '2208', ni: '220B', notin: '2209', owns: '220B', gg: '226B', ll: '226A', sim: '223C', simeq: '2243', perp: '22A5', equiv: '2261', asymp: '224D', smile: '2323', frown: '2322', ne: '2260', neq: '2260', cong: '2245', doteq: '2250', bowtie: '22C8', models: '22A8', notChar: '29F8', // Arrows Leftrightarrow: '21D4', Leftarrow: '21D0', Rightarrow: '21D2', leftrightarrow: '2194', leftarrow: '2190', gets: '2190', rightarrow: '2192', to: '2192', mapsto: '21A6', leftharpoonup: '21BC', leftharpoondown: '21BD', rightharpoonup: '21C0', rightharpoondown: '21C1', nearrow: '2197', searrow: '2198', nwarrow: '2196', swarrow: '2199', rightleftharpoons: '21CC', hookrightarrow: '21AA', hookleftarrow: '21A9', longleftarrow: '27F5', Longleftarrow: '27F8', longrightarrow: '27F6', Longrightarrow: '27F9', Longleftrightarrow: '27FA', longleftrightarrow: '27F7', longmapsto: '27FC', // Misc. ldots: '2026', cdots: '22EF', vdots: '22EE', ddots: '22F1', dotsc: '2026', // dots with commas dotsb: '22EF', // dots with binary ops and relations dotsm: '22EF', // dots with multiplication dotsi: '22EF', // dots with integrals dotso: '2026', // other dots ldotp: ['002E', {texClass: MML.TEXCLASS.PUNCT}], cdotp: ['22C5', {texClass: MML.TEXCLASS.PUNCT}], colon: ['003A', {texClass: MML.TEXCLASS.PUNCT}] }, mathchar7: { Gamma: '0393', Delta: '0394', Theta: '0398', Lambda: '039B', Xi: '039E', Pi: '03A0', Sigma: '03A3', Upsilon: '03A5', Phi: '03A6', Psi: '03A8', Omega: '03A9', '_': '005F', '#': '0023', '$': '0024', '%': '0025', '&': '0026', And: '0026' }, delimiter: { '(': '(', ')': ')', '[': '[', ']': ']', '<': '27E8', '>': '27E9', '\\lt': '27E8', '\\gt': '27E9', '/': '/', '|': ['|',{texClass:MML.TEXCLASS.ORD}], '.': '', '\\\\': '\\', '\\lmoustache': '23B0', // non-standard '\\rmoustache': '23B1', // non-standard '\\lgroup': '27EE', // non-standard '\\rgroup': '27EF', // non-standard '\\arrowvert': '23D0', '\\Arrowvert': '2016', '\\bracevert': '23AA', // non-standard '\\Vert': ['2016',{texClass:MML.TEXCLASS.ORD}], '\\|': ['2016',{texClass:MML.TEXCLASS.ORD}], '\\vert': ['|',{texClass:MML.TEXCLASS.ORD}], '\\uparrow': '2191', '\\downarrow': '2193', '\\updownarrow': '2195', '\\Uparrow': '21D1', '\\Downarrow': '21D3', '\\Updownarrow': '21D5', '\\backslash': '\\', '\\rangle': '27E9', '\\langle': '27E8', '\\rbrace': '}', '\\lbrace': '{', '\\}': '}', '\\{': '{', '\\rceil': '2309', '\\lceil': '2308', '\\rfloor': '230B', '\\lfloor': '230A', '\\lbrack': '[', '\\rbrack': ']' }, macros: { displaystyle: ['SetStyle','D',true,0], textstyle: ['SetStyle','T',false,0], scriptstyle: ['SetStyle','S',false,1], scriptscriptstyle: ['SetStyle','SS',false,2], rm: ['SetFont',MML.VARIANT.NORMAL], mit: ['SetFont',MML.VARIANT.ITALIC], oldstyle: ['SetFont',MML.VARIANT.OLDSTYLE], cal: ['SetFont',MML.VARIANT.CALIGRAPHIC], it: ['SetFont',"-tex-mathit"], // needs special handling bf: ['SetFont',MML.VARIANT.BOLD], bbFont: ['SetFont',MML.VARIANT.DOUBLESTRUCK], scr: ['SetFont',MML.VARIANT.SCRIPT], frak: ['SetFont',MML.VARIANT.FRAKTUR], sf: ['SetFont',MML.VARIANT.SANSSERIF], tt: ['SetFont',MML.VARIANT.MONOSPACE], // font: tiny: ['SetSize',0.5], Tiny: ['SetSize',0.6], // non-standard scriptsize: ['SetSize',0.7], small: ['SetSize',0.85], normalsize: ['SetSize',1.0], large: ['SetSize',1.2], Large: ['SetSize',1.44], LARGE: ['SetSize',1.73], huge: ['SetSize',2.07], Huge: ['SetSize',2.49], arcsin: ['NamedFn'], arccos: ['NamedFn'], arctan: ['NamedFn'], arg: ['NamedFn'], cos: ['NamedFn'], cosh: ['NamedFn'], cot: ['NamedFn'], coth: ['NamedFn'], csc: ['NamedFn'], deg: ['NamedFn'], det: 'NamedOp', dim: ['NamedFn'], exp: ['NamedFn'], gcd: 'NamedOp', hom: ['NamedFn'], inf: 'NamedOp', ker: ['NamedFn'], lg: ['NamedFn'], lim: 'NamedOp', liminf: ['NamedOp','lim&thinsp;inf'], limsup: ['NamedOp','lim&thinsp;sup'], ln: ['NamedFn'], log: ['NamedFn'], max: 'NamedOp', min: 'NamedOp', Pr: 'NamedOp', sec: ['NamedFn'], sin: ['NamedFn'], sinh: ['NamedFn'], sup: 'NamedOp', tan: ['NamedFn'], tanh: ['NamedFn'], limits: ['Limits',1], nolimits: ['Limits',0], overline: ['UnderOver','00AF',null,1], underline: ['UnderOver','005F'], overbrace: ['UnderOver','23DE',1], underbrace: ['UnderOver','23DF',1], overparen: ['UnderOver','23DC'], underparen: ['UnderOver','23DD'], overrightarrow: ['UnderOver','2192'], underrightarrow: ['UnderOver','2192'], overleftarrow: ['UnderOver','2190'], underleftarrow: ['UnderOver','2190'], overleftrightarrow: ['UnderOver','2194'], underleftrightarrow: ['UnderOver','2194'], overset: 'Overset', underset: 'Underset', stackrel: ['Macro','\\mathrel{\\mathop{#2}\\limits^{#1}}',2], over: 'Over', overwithdelims: 'Over', atop: 'Over', atopwithdelims: 'Over', above: 'Over', abovewithdelims: 'Over', brace: ['Over','{','}'], brack: ['Over','[',']'], choose: ['Over','(',')'], frac: 'Frac', sqrt: 'Sqrt', root: 'Root', uproot: ['MoveRoot','upRoot'], leftroot: ['MoveRoot','leftRoot'], left: 'LeftRight', right: 'LeftRight', middle: 'Middle', llap: 'Lap', rlap: 'Lap', raise: 'RaiseLower', lower: 'RaiseLower', moveleft: 'MoveLeftRight', moveright: 'MoveLeftRight', ',': ['Spacer',MML.LENGTH.THINMATHSPACE], ':': ['Spacer',MML.LENGTH.MEDIUMMATHSPACE], // for LaTeX '>': ['Spacer',MML.LENGTH.MEDIUMMATHSPACE], ';': ['Spacer',MML.LENGTH.THICKMATHSPACE], '!': ['Spacer',MML.LENGTH.NEGATIVETHINMATHSPACE], enspace: ['Spacer',".5em"], quad: ['Spacer',"1em"], qquad: ['Spacer',"2em"], thinspace: ['Spacer',MML.LENGTH.THINMATHSPACE], negthinspace: ['Spacer',MML.LENGTH.NEGATIVETHINMATHSPACE], hskip: 'Hskip', hspace: 'Hskip', kern: 'Hskip', mskip: 'Hskip', mspace: 'Hskip', mkern: 'Hskip', rule: 'rule', Rule: ['Rule'], Space: ['Rule','blank'], big: ['MakeBig',MML.TEXCLASS.ORD,0.85], Big: ['MakeBig',MML.TEXCLASS.ORD,1.15], bigg: ['MakeBig',MML.TEXCLASS.ORD,1.45], Bigg: ['MakeBig',MML.TEXCLASS.ORD,1.75], bigl: ['MakeBig',MML.TEXCLASS.OPEN,0.85], Bigl: ['MakeBig',MML.TEXCLASS.OPEN,1.15], biggl: ['MakeBig',MML.TEXCLASS.OPEN,1.45], Biggl: ['MakeBig',MML.TEXCLASS.OPEN,1.75], bigr: ['MakeBig',MML.TEXCLASS.CLOSE,0.85], Bigr: ['MakeBig',MML.TEXCLASS.CLOSE,1.15], biggr: ['MakeBig',MML.TEXCLASS.CLOSE,1.45], Biggr: ['MakeBig',MML.TEXCLASS.CLOSE,1.75], bigm: ['MakeBig',MML.TEXCLASS.REL,0.85], Bigm: ['MakeBig',MML.TEXCLASS.REL,1.15], biggm: ['MakeBig',MML.TEXCLASS.REL,1.45], Biggm: ['MakeBig',MML.TEXCLASS.REL,1.75], mathord: ['TeXAtom',MML.TEXCLASS.ORD], mathop: ['TeXAtom',MML.TEXCLASS.OP], mathopen: ['TeXAtom',MML.TEXCLASS.OPEN], mathclose: ['TeXAtom',MML.TEXCLASS.CLOSE], mathbin: ['TeXAtom',MML.TEXCLASS.BIN], mathrel: ['TeXAtom',MML.TEXCLASS.REL], mathpunct: ['TeXAtom',MML.TEXCLASS.PUNCT], mathinner: ['TeXAtom',MML.TEXCLASS.INNER], vcenter: ['TeXAtom',MML.TEXCLASS.VCENTER], mathchoice: ['Extension','mathchoice'], buildrel: 'BuildRel', hbox: ['HBox',0], text: 'HBox', mbox: ['HBox',0], fbox: 'FBox', strut: 'Strut', mathstrut: ['Macro','\\vphantom{(}'], phantom: 'Phantom', vphantom: ['Phantom',1,0], hphantom: ['Phantom',0,1], smash: 'Smash', acute: ['Accent', "00B4"], // or 0301 or 02CA grave: ['Accent', "0060"], // or 0300 or 02CB ddot: ['Accent', "00A8"], // or 0308 tilde: ['Accent', "007E"], // or 0303 or 02DC bar: ['Accent', "00AF"], // or 0304 or 02C9 breve: ['Accent', "02D8"], // or 0306 check: ['Accent', "02C7"], // or 030C hat: ['Accent', "005E"], // or 0302 or 02C6 vec: ['Accent', "2192"], // or 20D7 dot: ['Accent', "02D9"], // or 0307 widetilde: ['Accent', "007E",1], // or 0303 or 02DC widehat: ['Accent', "005E",1], // or 0302 or 02C6 matrix: 'Matrix', array: 'Matrix', pmatrix: ['Matrix','(',')'], cases: ['Matrix','{','',"left left",null,".1em",null,true], eqalign: ['Matrix',null,null,"right left",MML.LENGTH.THICKMATHSPACE,".5em",'D'], displaylines: ['Matrix',null,null,"center",null,".5em",'D'], cr: 'Cr', '\\': 'CrLaTeX', newline: 'Cr', hline: ['HLine','solid'], hdashline: ['HLine','dashed'], // noalign: 'HandleNoAlign', eqalignno: ['Matrix',null,null,"right left",MML.LENGTH.THICKMATHSPACE,".5em",'D',null,"right"], leqalignno: ['Matrix',null,null,"right left",MML.LENGTH.THICKMATHSPACE,".5em",'D',null,"left"], hfill: 'HFill', hfil: 'HFill', // \hfil treated as \hfill for now hfilll: 'HFill', // \hfilll treated as \hfill for now // TeX substitution macros bmod: ['Macro','\\mmlToken{mo}[lspace="thickmathspace" rspace="thickmathspace"]{mod}'], pmod: ['Macro','\\pod{\\mmlToken{mi}{mod}\\kern 6mu #1}',1], mod: ['Macro','\\mathchoice{\\kern18mu}{\\kern12mu}{\\kern12mu}{\\kern12mu}\\mmlToken{mi}{mod}\\,\\,#1',1], pod: ['Macro','\\mathchoice{\\kern18mu}{\\kern8mu}{\\kern8mu}{\\kern8mu}(#1)',1], iff: ['Macro','\\;\\Longleftrightarrow\\;'], skew: ['Macro','{{#2{#3\\mkern#1mu}\\mkern-#1mu}{}}',3], mathcal: ['Macro','{\\cal #1}',1], mathscr: ['Macro','{\\scr #1}',1], mathrm: ['Macro','{\\rm #1}',1], mathbf: ['Macro','{\\bf #1}',1], mathbb: ['Macro','{\\bbFont #1}',1], Bbb: ['Macro','{\\bbFont #1}',1], mathit: ['Macro','{\\it #1}',1], mathfrak: ['Macro','{\\frak #1}',1], mathsf: ['Macro','{\\sf #1}',1], mathtt: ['Macro','{\\tt #1}',1], textrm: ['Macro','\\mathord{\\rm\\text{#1}}',1], textit: ['Macro','\\mathord{\\it\\text{#1}}',1], textbf: ['Macro','\\mathord{\\bf\\text{#1}}',1], textsf: ['Macro','\\mathord{\\sf\\text{#1}}',1], texttt: ['Macro','\\mathord{\\tt\\text{#1}}',1], pmb: ['Macro','\\rlap{#1}\\kern1px{#1}',1], TeX: ['Macro','T\\kern-.14em\\lower.5ex{E}\\kern-.115em X'], LaTeX: ['Macro','L\\kern-.325em\\raise.21em{\\scriptstyle{A}}\\kern-.17em\\TeX'], ' ': ['Macro','\\text{ }'], // Specially handled not: 'Not', dots: 'Dots', space: 'Tilde', '\u00A0': 'Tilde', // LaTeX begin: 'BeginEnd', end: 'BeginEnd', newcommand: ['Extension','newcommand'], renewcommand: ['Extension','newcommand'], newenvironment: ['Extension','newcommand'], renewenvironment: ['Extension','newcommand'], def: ['Extension','newcommand'], 'let': ['Extension','newcommand'], verb: ['Extension','verb'], boldsymbol: ['Extension','boldsymbol'], tag: ['Extension','AMSmath'], notag: ['Extension','AMSmath'], label: ['Extension','AMSmath'], ref: ['Extension','AMSmath'], eqref: ['Extension','AMSmath'], nonumber: ['Macro','\\notag'], // Extensions to TeX unicode: ['Extension','unicode'], color: 'Color', href: ['Extension','HTML'], 'class': ['Extension','HTML'], style: ['Extension','HTML'], cssId: ['Extension','HTML'], bbox: ['Extension','bbox'], mmlToken: 'MmlToken', require: 'Require' }, environment: { array: ['AlignedArray'], matrix: ['Array',null,null,null,'c'], pmatrix: ['Array',null,'(',')','c'], bmatrix: ['Array',null,'[',']','c'], Bmatrix: ['Array',null,'\\{','\\}','c'], vmatrix: ['Array',null,'\\vert','\\vert','c'], Vmatrix: ['Array',null,'\\Vert','\\Vert','c'], cases: ['Array',null,'\\{','.','ll',null,".2em",'T'], equation: [null,'Equation'], 'equation*': [null,'Equation'], eqnarray: ['ExtensionEnv',null,'AMSmath'], 'eqnarray*': ['ExtensionEnv',null,'AMSmath'], align: ['ExtensionEnv',null,'AMSmath'], 'align*': ['ExtensionEnv',null,'AMSmath'], aligned: ['ExtensionEnv',null,'AMSmath'], multline: ['ExtensionEnv',null,'AMSmath'], 'multline*': ['ExtensionEnv',null,'AMSmath'], split: ['ExtensionEnv',null,'AMSmath'], gather: ['ExtensionEnv',null,'AMSmath'], 'gather*': ['ExtensionEnv',null,'AMSmath'], gathered: ['ExtensionEnv',null,'AMSmath'], alignat: ['ExtensionEnv',null,'AMSmath'], 'alignat*': ['ExtensionEnv',null,'AMSmath'], alignedat: ['ExtensionEnv',null,'AMSmath'] }, p_height: 1.2 / .85 // cmex10 height plus depth over .85 }); // // Add macros defined in the configuration // if (this.config.Macros) { var MACROS = this.config.Macros; for (var id in MACROS) {if (MACROS.hasOwnProperty(id)) { if (typeof(MACROS[id]) === "string") {TEXDEF.macros[id] = ['Macro',MACROS[id]]} else {TEXDEF.macros[id] = ["Macro"].concat(MACROS[id])} TEXDEF.macros[id].isUser = true; }} } }; /************************************************************************/ /* * The TeX Parser */ var PARSE = MathJax.Object.Subclass({ Init: function (string,env) { this.string = string; this.i = 0; this.macroCount = 0; var ENV; if (env) {ENV = {}; for (var id in env) {if (env.hasOwnProperty(id)) {ENV[id] = env[id]}}} this.stack = TEX.Stack(ENV,!!env); this.Parse(); this.Push(STACKITEM.stop()); }, Parse: function () { var c, n; while (this.i < this.string.length) { c = this.string.charAt(this.i++); n = c.charCodeAt(0); if (n >= 0xD800 && n < 0xDC00) {c += this.string.charAt(this.i++)} if (TEXDEF.special.hasOwnProperty(c)) {this[TEXDEF.special[c]](c)} else if (TEXDEF.letter.test(c)) {this.Variable(c)} else if (TEXDEF.digit.test(c)) {this.Number(c)} else {this.Other(c)} } }, Push: function () {this.stack.Push.apply(this.stack,arguments)}, mml: function () { if (this.stack.Top().type !== "mml") {return null} return this.stack.Top().data[0]; }, mmlToken: function (token) {return token}, // used by boldsymbol extension /************************************************************************/ /* * Handle various token classes */ /* * Lookup a control-sequence and process it */ ControlSequence: function (c) { var name = this.GetCS(), macro = this.csFindMacro(name); if (macro) { if (!isArray(macro)) {macro = [macro]} var fn = macro[0]; if (!(fn instanceof Function)) {fn = this[fn]} fn.apply(this,[c+name].concat(macro.slice(1))); } else if (TEXDEF.mathchar0mi.hasOwnProperty(name)) {this.csMathchar0mi(name,TEXDEF.mathchar0mi[name])} else if (TEXDEF.mathchar0mo.hasOwnProperty(name)) {this.csMathchar0mo(name,TEXDEF.mathchar0mo[name])} else if (TEXDEF.mathchar7.hasOwnProperty(name)) {this.csMathchar7(name,TEXDEF.mathchar7[name])} else if (TEXDEF.delimiter.hasOwnProperty("\\"+name)) {this.csDelimiter(name,TEXDEF.delimiter["\\"+name])} else {this.csUndefined(c+name)} }, // // Look up a macro in the macros list // (overridden in begingroup extension) // csFindMacro: function (name) { return (TEXDEF.macros.hasOwnProperty(name) ? TEXDEF.macros[name] : null); }, // // Handle normal mathchar (as an mi) // csMathchar0mi: function (name,mchar) { var def = {mathvariant: MML.VARIANT.ITALIC}; if (isArray(mchar)) {def = mchar[1]; mchar = mchar[0]} this.Push(this.mmlToken(MML.mi(MML.entity("#x"+mchar)).With(def))); }, // // Handle normal mathchar (as an mo) // csMathchar0mo: function (name,mchar) { var def = {stretchy: false}; if (isArray(mchar)) {def = mchar[1]; def.stretchy = false; mchar = mchar[0]} this.Push(this.mmlToken(MML.mo(MML.entity("#x"+mchar)).With(def))); }, // // Handle mathchar in current family // csMathchar7: function (name,mchar) { var def = {mathvariant: MML.VARIANT.NORMAL}; if (isArray(mchar)) {def = mchar[1]; mchar = mchar[0]} if (this.stack.env.font) {def.mathvariant = this.stack.env.font} this.Push(this.mmlToken(MML.mi(MML.entity("#x"+mchar)).With(def))); }, // // Handle delimiter // csDelimiter: function (name,delim) { var def = {}; if (isArray(delim)) {def = delim[1]; delim = delim[0]} if (delim.length === 4) {delim = MML.entity('#x'+delim)} else {delim = MML.chars(delim)} this.Push(this.mmlToken(MML.mo(delim).With({fence: false, stretchy: false}).With(def))); }, // // Handle undefined control sequence // (overridden in noUndefined extension) // csUndefined: function (name) { TEX.Error(["UndefinedControlSequence","Undefined control sequence %1",name]); }, /* * Handle a variable (a single letter) */ Variable: function (c) { var def = {}; if (this.stack.env.font) {def.mathvariant = this.stack.env.font} this.Push(this.mmlToken(MML.mi(MML.chars(c)).With(def))); }, /* * Determine the extent of a number (pattern may need work) */ Number: function (c) { var mml, n = this.string.slice(this.i-1).match(TEXDEF.number); if (n) {mml = MML.mn(n[0].replace(/[{}]/g,"")); this.i += n[0].length - 1} else {mml = MML.mo(MML.chars(c))} if (this.stack.env.font) {mml.mathvariant = this.stack.env.font} this.Push(this.mmlToken(mml)); }, /* * Handle { and } */ Open: function (c) {this.Push(STACKITEM.open())}, Close: function (c) {this.Push(STACKITEM.close())}, /* * Handle tilde and spaces */ Tilde: function (c) {this.Push(MML.mtext(MML.chars(NBSP)))}, Space: function (c) {}, /* * Handle ^, _, and ' */ Superscript: function (c) { if (this.GetNext().match(/\d/)) // don't treat numbers as a unit {this.string = this.string.substr(0,this.i+1)+" "+this.string.substr(this.i+1)} var primes, base, top = this.stack.Top(); if (top.type === "prime") {base = top.data[0]; primes = top.data[1]; this.stack.Pop()} else {base = this.stack.Prev(); if (!base) {base = MML.mi("")}} if (base.isEmbellishedWrapper) {base = base.data[0].data[0]} var movesupsub = base.movesupsub, position = base.sup; if ((base.type === "msubsup" && base.data[base.sup]) || (base.type === "munderover" && base.data[base.over] && !base.subsupOK)) {TEX.Error(["DoubleExponent","Double exponent: use braces to clarify"])} if (base.type !== "msubsup") { if (movesupsub) { if (base.type !== "munderover" || base.data[base.over]) { if (base.movablelimits && base.isa(MML.mi)) {base = this.mi2mo(base)} base = MML.munderover(base,null,null).With({movesupsub:true}) } position = base.over; } else { base = MML.msubsup(base,null,null); position = base.sup; } } this.Push(STACKITEM.subsup(base).With({ position: position, primes: primes, movesupsub: movesupsub })); }, Subscript: function (c) { if (this.GetNext().match(/\d/)) // don't treat numbers as a unit {this.string = this.string.substr(0,this.i+1)+" "+this.string.substr(this.i+1)} var primes, base, top = this.stack.Top(); if (top.type === "prime") {base = top.data[0]; primes = top.data[1]; this.stack.Pop()} else {base = this.stack.Prev(); if (!base) {base = MML.mi("")}} if (base.isEmbellishedWrapper) {base = base.data[0].data[0]} var movesupsub = base.movesupsub, position = base.sub; if ((base.type === "msubsup" && base.data[base.sub]) || (base.type === "munderover" && base.data[base.under] && !base.subsupOK)) {TEX.Error(["DoubleSubscripts","Double subscripts: use braces to clarify"])} if (base.type !== "msubsup") { if (movesupsub) { if (base.type !== "munderover" || base.data[base.under]) { if (base.movablelimits && base.isa(MML.mi)) {base = this.mi2mo(base)} base = MML.munderover(base,null,null).With({movesupsub:true}) } position = base.under; } else { base = MML.msubsup(base,null,null); position = base.sub; } } this.Push(STACKITEM.subsup(base).With({ position: position, primes: primes, movesupsub: movesupsub })); }, PRIME: "\u2032", SMARTQUOTE: "\u2019", Prime: function (c) { var base = this.stack.Prev()