diff options
author | Yuchen Pei <me@ypei.me> | 2021-06-24 17:50:34 +1000 |
---|---|---|
committer | Yuchen Pei <me@ypei.me> | 2021-06-24 17:50:34 +1000 |
commit | 11011d7c373c655830053b155eeaf632c2658ac7 (patch) | |
tree | 2e7ae85b013041fef7e733ddb4c74dd197c17f56 /js/mathjax/extensions/TeX | |
parent | 4f5ad1a70089365c5b6949d06386930433e09193 (diff) |
Updated.
- added mathjax (freed)
- added rss.py
- updated publish.el
- etc.
Diffstat (limited to 'js/mathjax/extensions/TeX')
24 files changed, 6595 insertions, 0 deletions
diff --git a/js/mathjax/extensions/TeX/AMScd.js b/js/mathjax/extensions/TeX/AMScd.js new file mode 100644 index 0000000..d6bee02 --- /dev/null +++ b/js/mathjax/extensions/TeX/AMScd.js @@ -0,0 +1,160 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/AMScd.js + * + * Implements the CD environment for commutative diagrams. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2013-2020 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. + */ + +MathJax.Extension["TeX/AMScd"] = { + version: "2.7.9", + config: MathJax.Hub.CombineConfig("TeX.CD",{ + colspace: "5pt", + rowspace: "5pt", + harrowsize: "2.75em", + varrowsize: "1.75em", + hideHorizontalLabels: false + }) +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + var MML = MathJax.ElementJax.mml, + TEX = MathJax.InputJax.TeX, + STACKITEM = TEX.Stack.Item, + TEXDEF = TEX.Definitions, + CONFIG = MathJax.Extension["TeX/AMScd"].config; + + TEXDEF.environment.CD = "CD_env"; + TEXDEF.special["@"] = "CD_arrow"; + TEXDEF.macros.minCDarrowwidth = "CD_minwidth"; + TEXDEF.macros.minCDarrowheight = "CD_minheight"; + + TEX.Parse.Augment({ + // + // Implements \begin{CD}...\end{CD} + // + CD_env: function (begin) { + this.Push(begin); + return STACKITEM.array().With({ + arraydef: { + columnalign: "center", + columnspacing: CONFIG.colspace, + rowspacing: CONFIG.rowspace, + displaystyle: true + }, + minw: this.stack.env.CD_minw || CONFIG.harrowsize, + minh: this.stack.env.CD_minh || CONFIG.varrowsize + }); + }, + + CD_arrow: function (name) { + var c = this.string.charAt(this.i); + if (!c.match(/[><VA.|=]/)) {return this.Other(name)} else {this.i++} + + var top = this.stack.Top(); + if (!top.isa(STACKITEM.array) || top.data.length) { + this.CD_cell(name); + top = this.stack.Top(); + } + // + // Add enough cells to place the arrow correctly + // + var arrowRow = ((top.table.length % 2) === 1); + var n = (top.row.length + (arrowRow ? 0 : 1)) % 2; + while (n) {this.CD_cell(name); n--} + + var mml; + var hdef = {minsize: top.minw, stretchy:true}, + vdef = {minsize: top.minh, stretchy:true, symmetric:true, lspace:0, rspace:0}; + + if (c === ".") {} + else if (c === "|") {mml = this.mmlToken(MML.mo("\u2225").With(vdef))} + else if (c === "=") {mml = this.mmlToken(MML.mo("=").With(hdef))} + else { + // + // for @>>> @<<< @VVV and @AAA, get the arrow and labels + // + var arrow = {">":"\u2192", "<":"\u2190", V:"\u2193", A:"\u2191"}[c]; + var a = this.GetUpTo(name+c,c), + b = this.GetUpTo(name+c,c); + + if (c === ">" || c === "<") { + // + // Lay out horizontal arrows with munderover if it has labels + // + mml = MML.mo(arrow).With(hdef); + if (!a) {a = "\\kern "+top.minw} // minsize needs work + if (a || b) { + var pad = {width:"+11mu", lspace:"6mu"}; + mml = MML.munderover(this.mmlToken(mml)); + if (a) { + a = TEX.Parse(a,this.stack.env).mml(); + mml.SetData(mml.over,MML.mpadded(a).With(pad).With({voffset:".1em"})); + } + if (b) { + b = TEX.Parse(b,this.stack.env).mml(); + mml.SetData(mml.under,MML.mpadded(b).With(pad)); + } + if (CONFIG.hideHorizontalLabels) + {mml = MML.mpadded(mml).With({depth:0, height:".67em"})} + } + } else { + // + // Lay out vertical arrows with mrow if there are labels + // + mml = arrow = this.mmlToken(MML.mo(arrow).With(vdef)); + if (a || b) { + mml = MML.mrow(); + if (a) {mml.Append(TEX.Parse("\\scriptstyle\\llap{"+a+"}",this.stack.env).mml())} + mml.Append(arrow.With({texClass: MML.TEXCLASS.ORD})); + if (b) {mml.Append(TEX.Parse("\\scriptstyle\\rlap{"+b+"}",this.stack.env).mml())} + } + } + } + if (mml) {this.Push(mml)}; + this.CD_cell(name); + }, + CD_cell: function (name) { + var top = this.stack.Top(); + if ((top.table||[]).length % 2 === 0 && (top.row||[]).length === 0) { + // + // Add a strut to the first cell in even rows to get + // better spacing of arrow rows. + // + this.Push(MML.mpadded().With({height:"8.5pt",depth:"2pt"})); + } + this.Push(STACKITEM.cell().With({isEntry:true, name:name})); + }, + + CD_minwidth: function (name) { + this.stack.env.CD_minw = this.GetDimen(name); + }, + CD_minheight: function (name) { + this.stack.env.CD_minh = this.GetDimen(name); + } + + }); + +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/AMScd.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/AMSmath.js b/js/mathjax/extensions/TeX/AMSmath.js new file mode 100644 index 0000000..70d5183 --- /dev/null +++ b/js/mathjax/extensions/TeX/AMSmath.js @@ -0,0 +1,665 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/AMSmath.js + * + * Implements AMS math environments and macros. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2009-2020 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. + */ + +MathJax.Extension["TeX/AMSmath"] = { + version: "2.7.9", + + number: 0, // current equation number + startNumber: 0, // current starting equation number (for when equation is restarted) + IDs: {}, // IDs used in previous equations + eqIDs: {}, // IDs used in this equation + labels: {}, // the set of labels + eqlabels: {}, // labels in the current equation + refs: [] // array of jax with unresolved references +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + + var MML = MathJax.ElementJax.mml, + TEX = MathJax.InputJax.TeX, + AMS = MathJax.Extension["TeX/AMSmath"]; + + var TEXDEF = TEX.Definitions, + STACKITEM = TEX.Stack.Item, + CONFIG = TEX.config.equationNumbers; + + var COLS = function (W) { + var WW = []; + for (var i = 0, m = W.length; i < m; i++) + {WW[i] = TEX.Parse.prototype.Em(W[i])} + return WW.join(" "); + }; + + // + // Get the URL of the page (for use with formatURL) when there + // is a <base> element on the page. + // + var baseURL = (document.getElementsByTagName("base").length === 0) ? "" : + String(document.location).replace(/#.*$/,""); + + + /******************************************************************************/ + + TEXDEF.Add({ + mathchar0mo: { + iiiint: ['2A0C',{texClass: MML.TEXCLASS.OP}] + }, + + macros: { + mathring: ['Accent','2DA'], // or 0x30A + + nobreakspace: 'Tilde', + negmedspace: ['Spacer',MML.LENGTH.NEGATIVEMEDIUMMATHSPACE], + negthickspace: ['Spacer',MML.LENGTH.NEGATIVETHICKMATHSPACE], + +// intI: ['Macro','\\mathchoice{\\!}{}{}{}\\!\\!\\int'], +// iint: ['MultiIntegral','\\int\\intI'], // now in core TeX input jax +// iiint: ['MultiIntegral','\\int\\intI\\intI'], // now in core TeX input jax +// iiiint: ['MultiIntegral','\\int\\intI\\intI\\intI'], // now in mathchar0mo above + idotsint: ['MultiIntegral','\\int\\cdots\\int'], + +// dddot: ['Macro','\\mathop{#1}\\limits^{\\textstyle \\mathord{.}\\mathord{.}\\mathord{.}}',1], +// ddddot: ['Macro','\\mathop{#1}\\limits^{\\textstyle \\mathord{.}\\mathord{.}\\mathord{.}\\mathord{.}}',1], + dddot: ['Accent','20DB'], + ddddot: ['Accent','20DC'], + + sideset: ['Macro','\\mathop{\\mathop{\\rlap{\\phantom{#3}}}\\nolimits#1\\!\\mathop{#3}\\nolimits#2}',3], + + boxed: ['Macro','\\fbox{$\\displaystyle{#1}$}',1], + + tag: 'HandleTag', + notag: 'HandleNoTag', + label: 'HandleLabel', + ref: 'HandleRef', + eqref: ['HandleRef',true], + + substack: ['Macro','\\begin{subarray}{c}#1\\end{subarray}',1], + + injlim: ['NamedOp','inj lim'], + projlim: ['NamedOp','proj lim'], + varliminf: ['Macro','\\mathop{\\underline{\\mmlToken{mi}{lim}}}'], + varlimsup: ['Macro','\\mathop{\\overline{\\mmlToken{mi}{lim}}}'], + varinjlim: ['Macro','\\mathop{\\underrightarrow{\\mmlToken{mi}{lim}}}'], + varprojlim: ['Macro','\\mathop{\\underleftarrow{\\mmlToken{mi}{lim}}}'], + + DeclareMathOperator: 'HandleDeclareOp', + operatorname: 'HandleOperatorName', + SkipLimits: 'SkipLimits', + + genfrac: 'Genfrac', + frac: ['Genfrac',"","","",""], + tfrac: ['Genfrac',"","","",1], + dfrac: ['Genfrac',"","","",0], + binom: ['Genfrac',"(",")","0",""], + tbinom: ['Genfrac',"(",")","0",1], + dbinom: ['Genfrac',"(",")","0",0], + + cfrac: 'CFrac', + + shoveleft: ['HandleShove',MML.ALIGN.LEFT], + shoveright: ['HandleShove',MML.ALIGN.RIGHT], + + xrightarrow: ['xArrow',0x2192,5,6], + xleftarrow: ['xArrow',0x2190,7,3] + }, + + environment: { + align: ['AMSarray',null,true,true, 'rlrlrlrlrlrl',COLS([0,2,0,2,0,2,0,2,0,2,0])], + 'align*': ['AMSarray',null,false,true, 'rlrlrlrlrlrl',COLS([0,2,0,2,0,2,0,2,0,2,0])], + multline: ['Multline',null,true], + 'multline*': ['Multline',null,false], + split: ['AMSarray',null,false,false,'rl',COLS([0])], + gather: ['AMSarray',null,true,true, 'c'], + 'gather*': ['AMSarray',null,false,true, 'c'], + + alignat: ['AlignAt',null,true,true], + 'alignat*': ['AlignAt',null,false,true], + alignedat: ['AlignAt',null,false,false], + + aligned: ['AlignedAMSArray',null,null,null,'rlrlrlrlrlrl',COLS([0,2,0,2,0,2,0,2,0,2,0]),".5em",'D'], + gathered: ['AlignedAMSArray',null,null,null,'c',null,".5em",'D'], + + subarray: ['Array',null,null,null,null,COLS([0]),"0.1em",'S',1], + smallmatrix: ['Array',null,null,null,'c',COLS([1/3]),".2em",'S',1], + + 'equation': ['EquationBegin','Equation',true], + 'equation*': ['EquationBegin','EquationStar',false], + + eqnarray: ['AMSarray',null,true,true, 'rcl',"0 "+MML.LENGTH.THICKMATHSPACE,".5em"], + 'eqnarray*': ['AMSarray',null,false,true,'rcl',"0 "+MML.LENGTH.THICKMATHSPACE,".5em"] + }, + + delimiter: { + '\\lvert': ['007C',{texClass:MML.TEXCLASS.OPEN}], + '\\rvert': ['007C',{texClass:MML.TEXCLASS.CLOSE}], + '\\lVert': ['2016',{texClass:MML.TEXCLASS.OPEN}], + '\\rVert': ['2016',{texClass:MML.TEXCLASS.CLOSE}] + } + },null,true); + + + /******************************************************************************/ + + TEX.Parse.Augment({ + + /* + * Add the tag to the environment (to be added to the table row later) + */ + HandleTag: function (name) { + var star = this.GetStar(); + var arg = this.trimSpaces(this.GetArgument(name)), tag = arg; + if (!star) {arg = CONFIG.formatTag(arg)} + var global = this.stack.global; global.tagID = tag; + if (global.notags) { + TEX.Error(["CommandNotAllowedInEnv", + "%1 not allowed in %2 environment", + name,global.notags] + ); + } + if (global.tag) {TEX.Error(["MultipleCommand","Multiple %1",name])} + global.tag = MML.mtd.apply(MML,this.InternalMath(arg)).With({id:CONFIG.formatID(tag)}); + }, + HandleNoTag: function (name) { + if (this.stack.global.tag) {delete this.stack.global.tag} + this.stack.global.notag = true; // prevent auto-tagging + }, + + /* + * Record a label name for a tag + */ + HandleLabel: function (name) { + var global = this.stack.global, label = this.GetArgument(name); + if (label === "") return; + if (!AMS.refUpdate) { + if (global.label) {TEX.Error(["MultipleCommand","Multiple %1",name])} + global.label = label; + if (AMS.labels[label] || AMS.eqlabels[label]) + {TEX.Error(["MultipleLabel","Label '%1' multiply defined",label])} + AMS.eqlabels[label] = {tag:"???", id:""}; // will be replaced by tag value later + } + }, + + /* + * Handle a label reference + */ + HandleRef: function (name,eqref) { + var label = this.GetArgument(name); + var ref = AMS.labels[label] || AMS.eqlabels[label]; + if (!ref) {ref = {tag:"???",id:""}; AMS.badref = !AMS.refUpdate} + var tag = ref.tag; if (eqref) {tag = CONFIG.formatTag(tag)} + this.Push(MML.mrow.apply(MML,this.InternalMath(tag)).With({ + href:CONFIG.formatURL(ref.id,baseURL), "class":"MathJax_ref" + })); + }, + + /* + * Handle \DeclareMathOperator + */ + HandleDeclareOp: function (name) { + var limits = (this.GetStar() ? "" : "\\nolimits\\SkipLimits"); + var cs = this.trimSpaces(this.GetArgument(name)); + if (cs.charAt(0) == "\\") {cs = cs.substr(1)} + var op = this.GetArgument(name); + if (!op.match(/\\text/)) op = op.replace(/\*/g,'\\text{*}').replace(/-/g,'\\text{-}'); + this.setDef(cs, ['Macro', '\\mathop{\\rm '+op+'}'+limits]); + }, + + HandleOperatorName: function (name) { + var limits = (this.GetStar() ? "" : "\\nolimits\\SkipLimits"); + var op = this.trimSpaces(this.GetArgument(name)); + if (!op.match(/\\text/)) op = op.replace(/\*/g,'\\text{*}').replace(/-/g,'\\text{-}'); + this.string = '\\mathop{\\rm '+op+'}'+limits+" "+this.string.slice(this.i); + this.i = 0; + }, + + SkipLimits: function (name) { + var c = this.GetNext(), i = this.i; + if (c === "\\" && ++this.i && this.GetCS() !== "limits") this.i = i; + }, + + /* + * Record presence of \shoveleft and \shoveright + */ + HandleShove: function (name,shove) { + var top = this.stack.Top(); + if (top.type !== "multline") { + TEX.Error(["CommandInMultline", + "%1 can only appear within the multline environment",name]); + } + if (top.data.length) { + TEX.Error(["CommandAtTheBeginingOfLine", + "%1 must come at the beginning of the line",name]); + } + top.data.shove = shove; + }, + + /* + * Handle \cfrac + */ + CFrac: function (name) { + var lr = this.trimSpaces(this.GetBrackets(name,"")), + num = this.GetArgument(name), + den = this.GetArgument(name); + var frac = MML.mfrac(TEX.Parse('\\strut\\textstyle{'+num+'}',this.stack.env).mml(), + TEX.Parse('\\strut\\textstyle{'+den+'}',this.stack.env).mml()); + lr = ({l:MML.ALIGN.LEFT, r:MML.ALIGN.RIGHT,"":""})[lr]; + if (lr == null) + {TEX.Error(["IllegalAlign","Illegal alignment specified in %1",name])} + if (lr) {frac.numalign = frac.denomalign = lr} + this.Push(frac); + }, + + /* + * Implement AMS generalized fraction + */ + Genfrac: function (name,left,right,thick,style) { + if (left == null) {left = this.GetDelimiterArg(name)} + if (right == null) {right = this.GetDelimiterArg(name)} + if (thick == null) {thick = this.GetArgument(name)} + if (style == null) {style = this.trimSpaces(this.GetArgument(name))} + var num = this.ParseArg(name); + var den = this.ParseArg(name); + var frac = MML.mfrac(num,den); + if (thick !== "") {frac.linethickness = thick} + if (left || right) {frac = TEX.fixedFence(left,frac.With({texWithDelims:true}),right)} + if (style !== "") { + var STYLE = (["D","T","S","SS"])[style]; + if (STYLE == null) + {TEX.Error(["BadMathStyleFor","Bad math style for %1",name])} + frac = MML.mstyle(frac); + if (STYLE === "D") {frac.displaystyle = true; frac.scriptlevel = 0} + else {frac.displaystyle = false; frac.scriptlevel = style - 1} + } + this.Push(frac); + }, + + /* + * Implements multline environment (mostly handled through STACKITEM below) + */ + Multline: function (begin,numbered) { + this.Push(begin); this.checkEqnEnv(); + return STACKITEM.multline(numbered,this.stack).With({ + arraydef: { + displaystyle: true, + rowspacing: ".5em", + width: TEX.config.MultLineWidth, columnwidth:"100%", + side: TEX.config.TagSide, + minlabelspacing: TEX.config.TagIndent + } + }); + }, + + /* + * Handle AMS aligned environments + */ + AMSarray: function (begin,numbered,taggable,align,spacing) { + this.Push(begin); if (taggable) {this.checkEqnEnv()} + align = align.replace(/[^clr]/g,'').split('').join(' '); + align = align.replace(/l/g,'left').replace(/r/g,'right').replace(/c/g,'center'); + return STACKITEM.AMSarray(begin.name,numbered,taggable,this.stack).With({ + arraydef: { + displaystyle: true, + rowspacing: ".5em", + columnalign: align, + columnspacing: (spacing||"1em"), + rowspacing: "3pt", + side: TEX.config.TagSide, + minlabelspacing: TEX.config.TagIndent + } + }); + }, + + AlignedAMSArray: function (begin) { + var align = this.GetBrackets("\\begin{"+begin.name+"}"); + return this.setArrayAlign(this.AMSarray.apply(this,arguments),align); + }, + + /* + * Handle alignat environments + */ + AlignAt: function (begin,numbered,taggable) { + var n, valign, align = "", spacing = []; + if (!taggable) {valign = this.GetBrackets("\\begin{"+begin.name+"}")} + n = this.GetArgument("\\begin{"+begin.name+"}"); + if (n.match(/[^0-9]/)) { + TEX.Error(["PositiveIntegerArg","Argument to %1 must me a positive integer", + "\\begin{"+begin.name+"}"]); + } + while (n > 0) {align += "rl"; spacing.push("0em 0em"); n--} + spacing = spacing.join(" "); + if (taggable) {return this.AMSarray(begin,numbered,taggable,align,spacing)} + var array = this.AMSarray(begin,numbered,taggable,align,spacing); + return this.setArrayAlign(array,valign); + }, + + /* + * Handle equation environment + */ + EquationBegin: function (begin,force) { + this.checkEqnEnv(); + this.stack.global.forcetag = (force && CONFIG.autoNumber !== "none"); + return begin; + }, + EquationStar: function (begin,row) { + this.stack.global.tagged = true; // prevent automatic tagging + return row; + }, + + /* + * Check for bad nesting of equation environments + */ + checkEqnEnv: function () { + if (this.stack.global.eqnenv) + {TEX.Error(["ErroneousNestingEq","Erroneous nesting of equation structures"])} + this.stack.global.eqnenv = true; + }, + + /* + * Handle multiple integrals (make a mathop if followed by limits) + */ + MultiIntegral: function (name,integral) { + var next = this.GetNext(); + if (next === "\\") { + var i = this.i; next = this.GetArgument(name); this.i = i; + if (next === "\\limits") { + if (name === "\\idotsint") {integral = "\\!\\!\\mathop{\\,\\,"+integral+"}"} + else {integral = "\\!\\!\\!\\mathop{\\,\\,\\,"+integral+"}"} + } + } + this.string = integral + " " + this.string.slice(this.i); + this.i = 0; + }, + + /* + * Handle stretchable arrows + */ + xArrow: function (name,chr,l,r) { + var def = {width: "+"+(l+r)+"mu", lspace: l+"mu"}; + var bot = this.GetBrackets(name), + top = this.ParseArg(name); + var arrow = MML.mo(MML.chars(String.fromCharCode(chr))).With({ + stretchy: true, texClass: MML.TEXCLASS.REL + }); + var mml = MML.munderover(arrow); + mml.SetData(mml.over,MML.mpadded(top).With(def).With({voffset:".15em"})); + if (bot) { + bot = TEX.Parse(bot,this.stack.env).mml() + mml.SetData(mml.under,MML.mpadded(bot).With(def).With({voffset:"-.24em"})); + } + this.Push(mml.With({subsupOK:true})); + }, + + /* + * Get a delimiter or empty argument + */ + GetDelimiterArg: function (name) { + var c = this.trimSpaces(this.GetArgument(name)); + if (c == "") return null; + if (c in TEXDEF.delimiter) return c; + TEX.Error(["MissingOrUnrecognizedDelim","Missing or unrecognized delimiter for %1",name]); + }, + + /* + * Get a star following a control sequence name, if any + */ + GetStar: function () { + var star = (this.GetNext() === "*"); + if (star) {this.i++} + return star; + } + + }); + + /******************************************************************************/ + + STACKITEM.Augment({ + /* + * Increment equation number and form tag mtd element + */ + autoTag: function () { + var global = this.global; + if (!global.notag) { + AMS.number++; global.tagID = CONFIG.formatNumber(AMS.number.toString()); + var mml = TEX.Parse("\\text{"+CONFIG.formatTag(global.tagID)+"}",{}).mml(); + global.tag = MML.mtd(mml).With({id:CONFIG.formatID(global.tagID)}); + } + }, + + /* + * Get the tag and record the label, if any + */ + getTag: function () { + var global = this.global, tag = global.tag; global.tagged = true; + if (global.label) { + if (CONFIG.useLabelIds) {tag.id = CONFIG.formatID(global.label)} + AMS.eqlabels[global.label] = {tag:global.tagID, id:tag.id}; + } + // + // Check for repeated ID's (either in the document or as + // a previous tag) and find a unique related one. (#240) + // + if (document.getElementById(tag.id) || AMS.IDs[tag.id] || AMS.eqIDs[tag.id]) { + var i = 0, ID; + do {i++; ID = tag.id+"_"+i} + while (document.getElementById(ID) || AMS.IDs[ID] || AMS.eqIDs[ID]); + tag.id = ID; if (global.label) {AMS.eqlabels[global.label].id = ID} + } + AMS.eqIDs[tag.id] = 1; + this.clearTag(); + return tag; + }, + clearTag: function () { + var global = this.global; + delete global.tag; delete global.tagID; delete global.label; + }, + + /* + * If the initial child, skipping any initial space or + * empty braces (TeXAtom with child being an empty inferred row), + * is an <mo>, precede it by an empty <mi> to force the <mo> to + * be infix. + */ + fixInitialMO: function (data) { + for (var i = 0, m = data.length; i < m; i++) { + if (data[i] && (data[i].type !== "mspace" && + (data[i].type !== "texatom" || (data[i].data[0] && data[i].data[0].data.length)))) { + if (data[i].isEmbellished() || + (data[i].type === "texatom" && data[i].texClass === MML.TEXCLASS.REL)) data.unshift(MML.mi()); + break; + } + } + } + }); + + /* + * Implement multline environment via a STACKITEM + */ + STACKITEM.multline = STACKITEM.array.Subclass({ + type: "multline", + Init: function (numbered,stack) { + this.SUPER(arguments).Init.apply(this); + this.numbered = (numbered && CONFIG.autoNumber !== "none"); + this.save = {notag: stack.global.notag}; + stack.global.tagged = !numbered && !stack.global.forcetag; // prevent automatic tagging in starred environments + }, + EndEntry: function () { + if (this.table.length) {this.fixInitialMO(this.data)} + var mtd = MML.mtd.apply(MML,this.data); + if (this.data.shove) {mtd.columnalign = this.data.shove} + this.row.push(mtd); + this.data = []; + }, + EndRow: function () { + if (this.row.length != 1) { + TEX.Error(["MultlineRowsOneCol", + "The rows within the %1 environment must have exactly one column", + "multline"]); + } + this.table.push(this.row); this.row = []; + }, + EndTable: function () { + this.SUPER(arguments).EndTable.call(this); + if (this.table.length) { + var m = this.table.length-1, i, label = -1; + if (!this.table[0][0].columnalign) {this.table[0][0].columnalign = MML.ALIGN.LEFT} + if (!this.table[m][0].columnalign) {this.table[m][0].columnalign = MML.ALIGN.RIGHT} + if (!this.global.tag && this.numbered) {this.autoTag()} + if (this.global.tag && !this.global.notags) { + label = (this.arraydef.side === "left" ? 0 : this.table.length - 1); + this.table[label] = [this.getTag()].concat(this.table[label]); + } + for (i = 0, m = this.table.length; i < m; i++) { + var mtr = (i === label ? MML.mlabeledtr : MML.mtr); + this.table[i] = mtr.apply(MML,this.table[i]); + } + } + this.global.notag = this.save.notag; + } + }); + + /* + * Save data about numbering and taging equations, and add + * tags at the ends of rows. + */ + STACKITEM.AMSarray = STACKITEM.array.Subclass({ + type: "AMSarray", + Init: function (name,numbered,taggable,stack) { + this.SUPER(arguments).Init.apply(this); + this.numbered = (numbered && CONFIG.autoNumber !== "none"); + this.save = {notags: stack.global.notags, notag: stack.global.notag}; + stack.global.notags = (taggable ? null : name); + stack.global.tagged = !numbered && taggable && !stack.global.forcetag; // prevent automatic tagging in starred environments + }, + EndEntry: function () { + if (this.row.length % 2 === 1) {this.fixInitialMO(this.data)} + this.row.push(MML.mtd.apply(MML,this.data)); + this.data = []; + }, + EndRow: function () { + var mtr = MML.mtr; + if (!this.global.tag && this.numbered) {this.autoTag()} + if (!this.global.notags) { + if (this.global.tag) { + this.row = [this.getTag()].concat(this.row); + mtr = MML.mlabeledtr; + } else { + this.clearTag(); + } + } + if (this.numbered) {delete this.global.notag} + this.table.push(mtr.apply(MML,this.row)); this.row = []; + }, + EndTable: function () { + this.SUPER(arguments).EndTable.call(this); + this.global.notags = this.save.notags; + this.global.notag = this.save.notag; + } + }); + + // + // Look for \tag on a formula and make an mtable to include it + // + STACKITEM.start.Augment({ + oldCheckItem: STACKITEM.start.prototype.checkItem, + checkItem: function (item) { + if (item.type === "stop") { + var mml = this.mmlData(), global = this.global; + if (AMS.display && !global.tag && !global.tagged && !global.isInner && + (CONFIG.autoNumber === "all" || global.forcetag)) {this.autoTag()} + if (global.tag) { + var row = [this.getTag(),MML.mtd(mml)]; + var def = { + side: TEX.config.TagSide, + minlabelspacing: TEX.config.TagIndent, + displaystyle: "inherit" // replaced by TeX input jax Translate() function with actual value + }; + mml = MML.mtable(MML.mlabeledtr.apply(MML,row)).With(def); + } + return STACKITEM.mml(mml); + } + return this.oldCheckItem.call(this,item); + } + }); + + /******************************************************************************/ + + /* + * Add pre- and post-filters to handle the equation number maintenance. + */ + TEX.prefilterHooks.Add(function (data) { + AMS.display = data.display; + AMS.number = AMS.startNumber; // reset equation numbers (in case the equation restarted) + AMS.eqlabels = {}; + AMS.eqIDs = {}; + AMS.badref = false; + if (AMS.refUpdate) {AMS.number = data.script.MathJax.startNumber} + }); + TEX.postfilterHooks.Add(function (data) { + data.script.MathJax.startNumber = AMS.startNumber; + AMS.startNumber = AMS.number; // equation numbers for next equation + MathJax.Hub.Insert(AMS.IDs,AMS.eqIDs); // save IDs from this equation + MathJax.Hub.Insert(AMS.labels,AMS.eqlabels); // save labels from this equation + if (AMS.badref && !data.math.texError) {AMS.refs.push(data.script)} // reprocess later + },100); + + MathJax.Hub.Register.MessageHook("Begin Math Input",function () { + AMS.refs = []; // array of jax with bad references + AMS.refUpdate = false; + }); + MathJax.Hub.Register.MessageHook("End Math Input",function (message) { + if (AMS.refs.length) { + AMS.refUpdate = true; + for (var i = 0, m = AMS.refs.length; i < m; i++) + {AMS.refs[i].MathJax.state = MathJax.ElementJax.STATE.UPDATE} + return MathJax.Hub.processInput({ + scripts:AMS.refs, + start: new Date().getTime(), + i:0, j:0, jax:{}, jaxIDs:[] + }); + } + return null; + }); + + // + // Clear the equation numbers and labels + // + TEX.resetEquationNumbers = function (n,keepLabels) { + AMS.startNumber = (n || 0); + if (!keepLabels) { + AMS.labels = {}; + AMS.IDs = {}; + } + } + + /******************************************************************************/ + + MathJax.Hub.Startup.signal.Post("TeX AMSmath Ready"); + +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/AMSmath.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/AMSsymbols.js b/js/mathjax/extensions/TeX/AMSsymbols.js new file mode 100644 index 0000000..ef7ae5f --- /dev/null +++ b/js/mathjax/extensions/TeX/AMSsymbols.js @@ -0,0 +1,351 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/AMSsymbols.js + * + * Implements macros for accessing the AMS symbol fonts. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2009-2020 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. + */ + +MathJax.Extension["TeX/AMSsymbols"] = { + version: "2.7.9" +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + var MML = MathJax.ElementJax.mml, + TEXDEF = MathJax.InputJax.TeX.Definitions; + + TEXDEF.Add({ + + mathchar0mi: { + // Lowercase Greek letters + digamma: '03DD', + varkappa: '03F0', + + // Uppercase Greek letters + varGamma: ['0393',{mathvariant: MML.VARIANT.ITALIC}], + varDelta: ['0394',{mathvariant: MML.VARIANT.ITALIC}], + varTheta: ['0398',{mathvariant: MML.VARIANT.ITALIC}], + varLambda: ['039B',{mathvariant: MML.VARIANT.ITALIC}], + varXi: ['039E',{mathvariant: MML.VARIANT.ITALIC}], + varPi: ['03A0',{mathvariant: MML.VARIANT.ITALIC}], + varSigma: ['03A3',{mathvariant: MML.VARIANT.ITALIC}], + varUpsilon: ['03A5',{mathvariant: MML.VARIANT.ITALIC}], + varPhi: ['03A6',{mathvariant: MML.VARIANT.ITALIC}], + varPsi: ['03A8',{mathvariant: MML.VARIANT.ITALIC}], + varOmega: ['03A9',{mathvariant: MML.VARIANT.ITALIC}], + + // Hebrew letters + beth: '2136', + gimel: '2137', + daleth: '2138', + + // Miscellaneous symbols +// hbar: '0127', // in TeX/jax.js + backprime: ['2035',{variantForm: true}], + hslash: '210F', + varnothing: ['2205',{variantForm: true}], + blacktriangle: '25B4', + triangledown: ['25BD',{variantForm: true}], + blacktriangledown: '25BE', + square: '25FB', + Box: '25FB', + blacksquare: '25FC', + lozenge: '25CA', + Diamond: '25CA', + blacklozenge: '29EB', + circledS: ['24C8',{mathvariant: MML.VARIANT.NORMAL}], + bigstar: '2605', +// angle: '2220', // in TeX/jax.js + sphericalangle: '2222', + measuredangle: '2221', + nexists: '2204', + complement: '2201', + mho: '2127', + eth: ['00F0',{mathvariant: MML.VARIANT.NORMAL}], + Finv: '2132', + diagup: '2571', + Game: '2141', + diagdown: '2572', + Bbbk: ['006B',{mathvariant: MML.VARIANT.DOUBLESTRUCK}], + + yen: '00A5', + circledR: '00AE', + checkmark: '2713', + maltese: '2720' + }, + + mathchar0mo: { + // Binary operators + dotplus: '2214', + ltimes: '22C9', + smallsetminus: '2216', + rtimes: '22CA', + Cap: '22D2', + doublecap: '22D2', + leftthreetimes: '22CB', + Cup: '22D3', + doublecup: '22D3', + rightthreetimes: '22CC', + barwedge: '22BC', + curlywedge: '22CF', + veebar: '22BB', + curlyvee: '22CE', + doublebarwedge: '2A5E', + boxminus: '229F', + circleddash: '229D', + boxtimes: '22A0', + circledast: '229B', + boxdot: '22A1', + circledcirc: '229A', + boxplus: '229E', + centerdot: ['22C5',{variantForm: true}], + divideontimes: '22C7', + intercal: '22BA', + + // Binary relations + leqq: '2266', + geqq: '2267', + leqslant: '2A7D', + geqslant: '2A7E', + eqslantless: '2A95', + eqslantgtr: '2A96', + lesssim: '2272', + gtrsim: '2273', + lessapprox: '2A85', + gtrapprox: '2A86', + approxeq: '224A', + lessdot: '22D6', + gtrdot: '22D7', + lll: '22D8', + llless: '22D8', + ggg: '22D9', + gggtr: '22D9', + lessgtr: '2276', + gtrless: '2277', + lesseqgtr: '22DA', + gtreqless: '22DB', + lesseqqgtr: '2A8B', + gtreqqless: '2A8C', + doteqdot: '2251', + Doteq: '2251', + eqcirc: '2256', + risingdotseq: '2253', + circeq: '2257', + fallingdotseq: '2252', + triangleq: '225C', + backsim: '223D', + thicksim: ['223C',{variantForm: true}], + backsimeq: '22CD', + thickapprox: ['2248',{variantForm: true}], + subseteqq: '2AC5', + supseteqq: '2AC6', + Subset: '22D0', + Supset: '22D1', + sqsubset: '228F', + sqsupset: '2290', + preccurlyeq: '227C', + succcurlyeq: '227D', + curlyeqprec: '22DE', + curlyeqsucc: '22DF', + precsim: '227E', + succsim: '227F', + precapprox: '2AB7', + succapprox: '2AB8', + vartriangleleft: '22B2', + lhd: '22B2', + vartriangleright: '22B3', + rhd: '22B3', + trianglelefteq: '22B4', + unlhd: '22B4', + trianglerighteq: '22B5', + unrhd: '22B5', + vDash: '22A8', + Vdash: '22A9', + Vvdash: '22AA', + smallsmile: ['2323',{variantForm: true}], + shortmid: ['2223',{variantForm: true}], + smallfrown: ['2322',{variantForm: true}], + shortparallel: ['2225',{variantForm: true}], + bumpeq: '224F', + between: '226C', + Bumpeq: '224E', + pitchfork: '22D4', + varpropto: '221D', + backepsilon: '220D', + blacktriangleleft: '25C2', + blacktriangleright: '25B8', + therefore: '2234', + because: '2235', + eqsim: '2242', + vartriangle: ['25B3',{variantForm: true}], + Join: '22C8', + + // Negated relations + nless: '226E', + ngtr: '226F', + nleq: '2270', + ngeq: '2271', + nleqslant: ['2A87',{variantForm: true}], + ngeqslant: ['2A88',{variantForm: true}], + nleqq: ['2270',{variantForm: true}], + ngeqq: ['2271',{variantForm: true}], + lneq: '2A87', + gneq: '2A88', + lneqq: '2268', + gneqq: '2269', + lvertneqq: ['2268',{variantForm: true}], + gvertneqq: ['2269',{variantForm: true}], + lnsim: '22E6', + gnsim: '22E7', + lnapprox: '2A89', + gnapprox: '2A8A', + nprec: '2280', + nsucc: '2281', + npreceq: ['22E0',{variantForm: true}], + nsucceq: ['22E1',{variantForm: true}], + precneqq: '2AB5', + succneqq: '2AB6', + precnsim: '22E8', + succnsim: '22E9', + precnapprox: '2AB9', + succnapprox: '2ABA', + nsim: '2241', + ncong: '2246', + nshortmid: ['2224',{variantForm: true}], + nshortparallel: ['2226',{variantForm: true}], + nmid: '2224', + nparallel: '2226', + nvdash: '22AC', + nvDash: '22AD', + nVdash: '22AE', + nVDash: '22AF', + ntriangleleft: '22EA', + ntriangleright: '22EB', + ntrianglelefteq: '22EC', + ntrianglerighteq: '22ED', + nsubseteq: '2288', + nsupseteq: '2289', + nsubseteqq: ['2288',{variantForm: true}], + nsupseteqq: ['2289',{variantForm: true}], + subsetneq: '228A', + supsetneq: '228B', + varsubsetneq: ['228A',{variantForm: true}], + varsupsetneq: ['228B',{variantForm: true}], + subsetneqq: '2ACB', + supsetneqq: '2ACC', + varsubsetneqq: ['2ACB',{variantForm: true}], + varsupsetneqq: ['2ACC',{variantForm: true}], + + + // Arrows + leftleftarrows: '21C7', + rightrightarrows: '21C9', + leftrightarrows: '21C6', + rightleftarrows: '21C4', + Lleftarrow: '21DA', + Rrightarrow: '21DB', + twoheadleftarrow: '219E', + twoheadrightarrow: '21A0', + leftarrowtail: '21A2', + rightarrowtail: '21A3', + looparrowleft: '21AB', + looparrowright: '21AC', + leftrightharpoons: '21CB', + rightleftharpoons: ['21CC',{variantForm: true}], + curvearrowleft: '21B6', + curvearrowright: '21B7', + circlearrowleft: '21BA', + circlearrowright: '21BB', + Lsh: '21B0', + Rsh: '21B1', + upuparrows: '21C8', + downdownarrows: '21CA', + upharpoonleft: '21BF', + upharpoonright: '21BE', + downharpoonleft: '21C3', + restriction: '21BE', + multimap: '22B8', + downharpoonright: '21C2', + leftrightsquigarrow: '21AD', + rightsquigarrow: '21DD', + leadsto: '21DD', + dashrightarrow: '21E2', + dashleftarrow: '21E0', + + // Negated arrows + nleftarrow: '219A', + nrightarrow: '219B', + nLeftarrow: '21CD', + nRightarrow: '21CF', + nleftrightarrow: '21AE', + nLeftrightarrow: '21CE' + }, + + delimiter: { + // corners + "\\ulcorner": '231C', + "\\urcorner": '231D', + "\\llcorner": '231E', + "\\lrcorner": '231F' + }, + + macros: { + implies: ['Macro','\\;\\Longrightarrow\\;'], + impliedby: ['Macro','\\;\\Longleftarrow\\;'] + } + + },null,true); + + var REL = MML.mo.OPTYPES.REL; + + MathJax.Hub.Insert(MML.mo.prototype,{ + OPTABLE: { + infix: { + '\u2322': REL, // smallfrown + '\u2323': REL, // smallsmile + '\u25B3': REL, // vartriangle + '\uE006': REL, // nshortmid + '\uE007': REL, // nshortparallel + '\uE00C': REL, // lvertneqq + '\uE00D': REL, // gvertneqq + '\uE00E': REL, // ngeqq + '\uE00F': REL, // ngeqslant + '\uE010': REL, // nleqslant + '\uE011': REL, // nleqq + '\uE016': REL, // nsubseteqq + '\uE017': REL, // varsubsetneqq + '\uE018': REL, // nsupseteqq + '\uE019': REL, // varsupsetneqq + '\uE01A': REL, // varsubsetneq + '\uE01B': REL, // varsupsetneq + '\uE04B': REL, // npreceq + '\uE04F': REL // nsucceq + } + } + }); + + MathJax.Hub.Startup.signal.Post("TeX AMSsymbols Ready"); + +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/AMSsymbols.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/HTML.js b/js/mathjax/extensions/TeX/HTML.js new file mode 100644 index 0000000..75e4e45 --- /dev/null +++ b/js/mathjax/extensions/TeX/HTML.js @@ -0,0 +1,108 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/HTML.js + * + * Implements the \href, \class, \style, \cssId macros. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2010-2020 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. + */ + +MathJax.Extension["TeX/HTML"] = { + version: "2.7.9" +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + + var TEX = MathJax.InputJax.TeX; + var TEXDEF = TEX.Definitions; + + TEXDEF.Add({ + macros: { + href: 'HREF_attribute', + "class": 'CLASS_attribute', + style: 'STYLE_attribute', + cssId: 'ID_attribute' + } + },null,true); + + TEX.Parse.Augment({ + + // + // Implements \href{url}{math} + // + HREF_attribute: function (name) { + var url = this.GetArgument(name), + arg = this.GetArgumentMML(name); + this.Push(arg.With({href:url})); + }, + + // + // Implements \class{name}{math} + // + CLASS_attribute: function (name) { + var CLASS = this.GetArgument(name), + arg = this.GetArgumentMML(name); + if (arg["class"] != null) {CLASS = arg["class"] + " " + CLASS} + this.Push(arg.With({"class":CLASS})); + }, + + // + // Implements \style{style-string}{math} + // + STYLE_attribute: function (name) { + var style = this.GetArgument(name), + arg = this.GetArgumentMML(name); + // check that it looks like a style string + if (arg.style != null) { + if (style.charAt(style.length-1) !== ";") {style += ";"} + style = arg.style + " " + style; + } + this.Push(arg.With({style: style})); + }, + + // + // Implements \cssId{id}{math} + // + ID_attribute: function (name) { + var ID = this.GetArgument(name), + arg = this.GetArgumentMML(name); + this.Push(arg.With({id:ID})); + }, + + // + // returns an argument that is a single MathML element + // (in an mrow if necessary) + // + GetArgumentMML: function (name) { + var arg = this.ParseArg(name); + if (arg.inferred && arg.data.length == 1) + {arg = arg.data[0]} else {delete arg.inferred} + return arg; + } + + }); + + MathJax.Hub.Startup.signal.Post("TeX HTML Ready"); + +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/HTML.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/action.js b/js/mathjax/extensions/TeX/action.js new file mode 100644 index 0000000..5ef06fd --- /dev/null +++ b/js/mathjax/extensions/TeX/action.js @@ -0,0 +1,85 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/action.js + * + * Implements the \mathtip, \texttip, and \toggle macros, which give + * access from TeX to the <maction> tag in the MathML that underlies + * MathJax's internal format. + * + * Usage: + * + * \mathtip{math}{tip} % use "tip" (in math mode) as tooltip for "math" + * \texttip{math}{tip} % use "tip" (in text mode) as tooltip for "math" + * \toggle{math1}{math2}...\endtoggle + * % show math1, and when clicked, show math2, and so on. + * % When the last one is clicked, go back to math1. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2011-2020 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. + */ + +MathJax.Extension["TeX/action"] = { + version: "2.7.9" +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + var TEX = MathJax.InputJax.TeX, + MML = MathJax.ElementJax.mml; + + // + // Set up control sequenecs + // + TEX.Definitions.Add({ + macros: { + toggle: 'Toggle', + mathtip: 'Mathtip', + texttip: ['Macro','\\mathtip{#1}{\\text{#2}}',2] + } + },null,true); + + TEX.Parse.Augment({ + + // + // Implement \toggle {math1} {math2} ... \endtoggle + // (as an <maction actiontype="toggle">) + // + Toggle: function (name) { + var data = [], arg; + while ((arg = this.GetArgument(name)) !== "\\endtoggle") + {data.push(TEX.Parse(arg,this.stack.env).mml())} + this.Push(MML.maction.apply(MML,data).With({actiontype: MML.ACTIONTYPE.TOGGLE})); + }, + + // + // Implement \mathtip{math}{tip} + // (an an <maction actiontype="tooltip">) + // + Mathtip: function(name) { + var arg = this.ParseArg(name), tip = this.ParseArg(name); + this.Push(MML.maction(arg,tip).With({actiontype: MML.ACTIONTYPE.TOOLTIP})); + } + }); + + MathJax.Hub.Startup.signal.Post("TeX action Ready"); + +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/action.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/autobold.js b/js/mathjax/extensions/TeX/autobold.js new file mode 100644 index 0000000..1d058ee --- /dev/null +++ b/js/mathjax/extensions/TeX/autobold.js @@ -0,0 +1,52 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/autobold.js + * + * Adds \boldsymbol around mathematics that appears in a section + * of an HTML page that is in bold. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2009-2020 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. + */ + +MathJax.Extension["TeX/autobold"] = { + version: "2.7.9" +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + var TEX = MathJax.InputJax.TeX; + + TEX.prefilterHooks.Add(function (data) { + var span = data.script.parentNode.insertBefore(document.createElement("span"),data.script); + span.visibility = "hidden"; + span.style.fontFamily = "Times, serif"; + span.appendChild(document.createTextNode("ABCXYZabcxyz")); + var W = span.offsetWidth; + span.style.fontWeight = "bold"; + if (W && span.offsetWidth === W) {data.math = "\\boldsymbol{"+data.math+"}"} + span.parentNode.removeChild(span); + }); + + MathJax.Hub.Startup.signal.Post("TeX autobold Ready"); + +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/autobold.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/autoload-all.js b/js/mathjax/extensions/TeX/autoload-all.js new file mode 100644 index 0000000..6032aad --- /dev/null +++ b/js/mathjax/extensions/TeX/autoload-all.js @@ -0,0 +1,85 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/autoload-all.js + * + * Provides pre-defined macros to autoload all the extensions + * so that all macros that MathJax knows about are available. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2013-2020 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. + */ + +MathJax.Extension["TeX/autoload-all"] = { + version: "2.7.9" +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + + var EXTENSIONS = { + action: ["mathtip","texttip","toggle"], + AMSmath: ["mathring","nobreakspace","negmedspace","negthickspace","intI", + "iiiint","idotsint","dddot","ddddot","sideset","boxed", + "substack","injlim","projlim","varliminf","varlimsup", + "varinjlim","varprojlim","DeclareMathOperator","operatorname", + "genfrac","tfrac","dfrac","binom","tbinom","dbinom","cfrac", + "shoveleft","shoveright","xrightarrow","xleftarrow"], + begingroup: ["begingroup","endgroup","gdef","global"], + cancel: ["cancel","bcancel","xcancel","cancelto"], + color: ["color","textcolor","colorbox","fcolorbox","definecolor"], + enclose: ["enclose"], + extpfeil: ["Newextarrow","xlongequal","xmapsto","xtofrom", + "xtwoheadleftarrow","xtwoheadrightarrow"], + mhchem: ["ce","cee","cf"] + }; + + var ENVIRONMENTS = { + AMSmath: ["subarray","smallmatrix","equation","equation*"], + AMScd: ["CD"] + }; + + var name, i, m, defs = {macros:{}, environment:{}}; + + for (name in EXTENSIONS) {if (EXTENSIONS.hasOwnProperty(name)) { + if (!MathJax.Extension["TeX/"+name]) { + var macros = EXTENSIONS[name]; + for (i = 0, m = macros.length; i < m; i++) + {defs.macros[macros[i]] = ["Extension",name]} + } + }} + + for (name in ENVIRONMENTS) {if (ENVIRONMENTS.hasOwnProperty(name)) { + if (!MathJax.Extension["TeX/"+name]) { + var envs = ENVIRONMENTS[name]; + for (i = 0, m = envs.length; i < m; i++) + {defs.environment[envs[i]] = ["ExtensionEnv",null,name]} + } + }} + + MathJax.InputJax.TeX.Definitions.Add(defs); + + MathJax.Hub.Startup.signal.Post("TeX autoload-all Ready"); + +}); + +MathJax.Callback.Queue( + ["Require",MathJax.Ajax,"[MathJax]/extensions/TeX/AMSsymbols.js"], + ["loadComplete",MathJax.Ajax,"[MathJax]/extensions/TeX/autoload-all.js"] +); +// @license-end diff --git a/js/mathjax/extensions/TeX/bbox.js b/js/mathjax/extensions/TeX/bbox.js new file mode 100644 index 0000000..cc5440a --- /dev/null +++ b/js/mathjax/extensions/TeX/bbox.js @@ -0,0 +1,104 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/bbox.js + * + * This file implements the \bbox macro, which creates an box that + * can be styled (for background colors, and so on). You can include + * an optional dimension that tells how much extra padding to include + * around the bounding box for the mathematics, or a color specification + * for the background color to use, or both. E.g., + * + * \bbox[2pt]{x+y} % an invisible box around x+y with 2pt of extra space + * \bbox[green]{x+y} % a green box around x+y + * \bbox[green,2pt]{x+y} % a green box with 2pt of extra space + * + * You can also specify style attributes, for example + * + * \bbox[red,border:3px solid blue,5px]{x+y} + * + * would give a red background with a 3px solid blue border that has 5px + * of padding between the border and the mathematics. Note that not all + * output formats support the style specifications. In particular, the + * NativeMML output depends on the browser to render the attributes, and + * not all MathML renderers will honor them (e.g., MathPlayer2 doesn't + * render border styles). + * + * This file will be loaded automatically when \bbox is first used. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2011-2020 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. + */ + +MathJax.Extension["TeX/bbox"] = { + version: "2.7.9" +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + + var TEX = MathJax.InputJax.TeX, + MML = MathJax.ElementJax.mml; + + TEX.Definitions.Add({macros: {bbox: "BBox"}},null,true); + + TEX.Parse.Augment({ + BBox: function (name) { + var bbox = this.GetBrackets(name,""), + math = this.ParseArg(name); + var parts = bbox.split(/,/), def, background, style; + for (var i = 0, m = parts.length; i < m; i++) { + var part = parts[i].replace(/^\s+/,'').replace(/\s+$/,''); + var match = part.match(/^(\.\d+|\d+(\.\d*)?)(pt|em|ex|mu|px|in|cm|mm)$/); + if (match) { + if (def) + {TEX.Error(["MultipleBBoxProperty","%1 specified twice in %2","Padding",name])} + var pad = this.BBoxPadding(match[1]+match[3]); + if (pad) def = {height:"+"+pad, depth:"+"+pad, lspace:pad, width:"+"+(2*match[1])+match[3]}; + } else if (part.match(/^([a-z0-9]+|\#[0-9a-f]{6}|\#[0-9a-f]{3})$/i)) { + if (background) + {TEX.Error(["MultipleBBoxProperty","%1 specified twice in %2","Background",name])} + background = part; + } else if (part.match(/^[-a-z]+:/i)) { + if (style) + {TEX.Error(["MultipleBBoxProperty","%1 specified twice in %2", "Style",name])} + style = this.BBoxStyle(part); + } else if (part !== "") { + TEX.Error( + ["InvalidBBoxProperty", + "'%1' doesn't look like a color, a padding dimension, or a style", + part] + ); + } + } + if (def) {math = MML.mpadded(math).With(def)} + if (background || style) { + math = MML.mstyle(math).With({mathbackground:background, style:style}); + } + this.Push(math); + }, + BBoxStyle: function (styles) {return styles}, + BBoxPadding: function (pad) {return pad} + }); + + MathJax.Hub.Startup.signal.Post("TeX bbox Ready"); + +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/bbox.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/begingroup.js b/js/mathjax/extensions/TeX/begingroup.js new file mode 100644 index 0000000..f750fc5 --- /dev/null +++ b/js/mathjax/extensions/TeX/begingroup.js @@ -0,0 +1,294 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/begingroup.js + * + * Implements \begingroup and \endgroup commands that make local + * definitions possible and are removed when the \endgroup occurs. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2011-2020 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. + */ + +MathJax.Extension["TeX/begingroup"] = { + version: "2.7.9" +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + + var TEX = MathJax.InputJax.TeX, + TEXDEF = TEX.Definitions; + + /****************************************************/ + + // + // A namespace for localizing macros and environments + // (\begingroup and \endgroup create and destroy these) + // + var NSFRAME = MathJax.Object.Subclass({ + macros: null, // the local macro definitions + environments: null, // the local environments + Init: function (macros,environments) { + this.macros = (macros || {}); + this.environments = (environments || {}); + }, + // + // Find a macro or environment by name + // + Find: function (name,type) {if (this[type].hasOwnProperty(name)) {return this[type][name]}}, + // + // Define or remove a macro or environment + // + Def: function (name,value,type) {this[type][name] = value}, + Undef: function (name,type) {delete this[type][name]}, + // + // Merge two namespaces (used when the equation namespace is combined with the root one) + // + Merge: function (frame) { + MathJax.Hub.Insert(this.macros,frame.macros); + MathJax.Hub.Insert(this.environments,frame.environments); + }, + // + // Move global macros to the stack (globally) and remove from the frame + // + MergeGlobals: function (stack) { + var macros = this.macros; + for (var cs in macros) {if (macros.hasOwnProperty(cs) && macros[cs].global) { + stack.Def(cs,macros[cs],"macros",true); + delete macros[cs].global; delete macros[cs]; + }} + }, + // + // Clear the macro and environment lists + // (but not global macros unless "all" is true) + // + Clear: function (all) { + this.environments = {}; + if (all) {this.macros = {}} else { + var macros = this.macros; + for (var cs in macros) { + if (macros.hasOwnProperty(cs) && !macros[cs].global) {delete macros[cs]} + } + } + return this; + } + }); + + /****************************************************/ + + // + // A Stack of namespace frames + // + var NSSTACK = TEX.nsStack = MathJax.Object.Subclass({ + stack: null, // the namespace frames + top: 0, // the current top one (we don't pop for real until the equation completes) + isEqn: false, // true if this is the equation stack (not the global one) + // + // Set up the initial stack frame + // + Init: function (eqn) { + this.isEqn = eqn; this.stack = []; + if (!eqn) {this.Push(NSFRAME(TEXDEF.macros,TEXDEF.environment))} + else {this.Push(NSFRAME())} + }, + // + // Define a macro or environment in the top frame + // + Def: function (name,value,type,global) { + var n = this.top-1; + if (global) { + // + // Define global macros in the base frame and remove that cs + // from all other frames. Mark the global ones in equations + // so they can be made global when merged with the root stack. + // + while (n > 0) {this.stack[n].Undef(name,type); n--} + if (!MathJax.Object.isArray(value)) {value = [value]} + if (this.isEqn) {value.global = true} + } + this.stack[n].Def(name,value,type); + }, + // + // Push a new namespace frame on the stack + // + Push: function (frame) { + this.stack.push(frame); + this.top = this.stack.length; + }, + // + // Pop the top stack frame + // (if it is the root, just keep track of the pop so we can + // reset it if the equation is reprocessed) + // + Pop: function () { + var top; + if (this.top > 1) { + top = this.stack[--this.top]; + if (this.isEqn) {this.stack.pop()} + } else if (this.isEqn) { + this.Clear(); + } + return top; + }, + // + // Search the stack from top to bottom for the first + // definition of the given control sequence in the given type + // + Find: function (name,type) { + for (var i = this.top-1; i >= 0; i--) { + var def = this.stack[i].Find(name,type); + if (def) {return def} + } + return null; + }, + // + // Combine the equation stack with the global one + // (The bottom frame of the equation goes with the top frame of the global one, + // and the remainder are pushed on the global stack, truncated to the + // position where items were poped from it.) + // + Merge: function (stack) { + stack.stack[0].MergeGlobals(this); + this.stack[this.top-1].Merge(stack.stack[0]); + var data = [this.top,this.stack.length-this.top].concat(stack.stack.slice(1)); + this.stack.splice.apply(this.stack,data); + this.top = this.stack.length; + }, + // + // Put back the temporarily poped items + // + Reset: function () {this.top = this.stack.length}, + // + // Clear the stack and start with a blank frame + // + Clear: function (all) { + this.stack = [this.stack[0].Clear()]; + this.top = this.stack.length; + } + },{ + nsFrame: NSFRAME + }); + + /****************************************************/ + + // + // Define the new macros + // + TEXDEF.Add({ + macros: { + begingroup: "BeginGroup", + endgroup: "EndGroup", + global: "Global", + gdef: ["Macro","\\global\\def"] + } + },null,true); + + TEX.Parse.Augment({ + // + // Implement \begingroup + // + BeginGroup: function (name) { + TEX.eqnStack.Push(NSFRAME()); + }, + // + // Implements \endgroup + // + EndGroup: function (name) { + // + // If the equation has pushed frames, pop one, + // Otherwise clear the equation stack and pop the top global one + // + if (TEX.eqnStack.top > 1) { + TEX.eqnStack.Pop(); + } else if (TEX.rootStack.top === 1) { + TEX.Error(["ExtraEndMissingBegin","Extra %1 or missing \\begingroup",name]); + } else { + TEX.eqnStack.Clear(); + TEX.rootStack.Pop(); + } + }, + + // + // Replace the original routines with ones that looks through the + // equation and root stacks for the given name + // + csFindMacro: function (name) { + return (TEX.eqnStack.Find(name,"macros") || TEX.rootStack.Find(name,"macros")); + }, + envFindName: function (name) { + return (TEX.eqnStack.Find(name,"environments") || TEX.rootStack.Find(name,"environments")); + }, + + // + // Modify the way macros and environments are defined + // to make them go into the equation namespace stack + // + setDef: function (name,value) { + value.isUser = true; + TEX.eqnStack.Def(name,value,"macros",this.stack.env.isGlobal); + delete this.stack.env.isGlobal; + }, + setEnv: function (name,value) { + value.isUser = true; + TEX.eqnStack.Def(name,value,"environments") + }, + + // + // Implement \global (for \global\let, \global\def and \global\newcommand) + // + Global: function (name) { + var i = this.i; var cs = this.GetCSname(name); this.i = i; + if (cs !== "let" && cs !== "def" && cs !== "newcommand" && + cs !== "DeclareMathOperator" && cs !== "Newextarrow") { + TEX.Error(["GlobalNotFollowedBy", + "%1 not followed by \\let, \\def, or \\newcommand",name]); + } + this.stack.env.isGlobal = true; + } + }); + + /****************************************************/ + + TEX.rootStack = NSSTACK(); // the global namespace stack + TEX.eqnStack = NSSTACK(true); // the equation stack + + // + // Reset the global stack and clear the equation stack + // (this gets us back to the initial stack state as it was + // before the equation was first processed, in case the equation + // get restarted due to an autoloaded file) + // + TEX.prefilterHooks.Add(function () {TEX.rootStack.Reset(); TEX.eqnStack.Clear(true)}); + + // + // We only get here if there were no errors and the equation is fully + // processed (all restarts are complete). So we merge the equation + // stack into the global stack, thus making the changes from this + // equation permanent. + // + TEX.postfilterHooks.Add(function () {TEX.rootStack.Merge(TEX.eqnStack)}); + + /*********************************************************/ + + MathJax.Hub.Startup.signal.Post("TeX begingroup Ready"); + +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/begingroup.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/boldsymbol.js b/js/mathjax/extensions/TeX/boldsymbol.js new file mode 100644 index 0000000..e25fff0 --- /dev/null +++ b/js/mathjax/extensions/TeX/boldsymbol.js @@ -0,0 +1,77 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/boldsymbol.js + * + * Implements the \boldsymbol{...} command to make bold + * versions of all math characters (not just variables). + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2009-2020 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. + */ + +MathJax.Extension["TeX/boldsymbol"] = { + version: "2.7.9" +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + + var MML = MathJax.ElementJax.mml; + var TEX = MathJax.InputJax.TeX; + var TEXDEF = TEX.Definitions; + + var BOLDVARIANT = {}; + BOLDVARIANT[MML.VARIANT.NORMAL] = MML.VARIANT.BOLD; + BOLDVARIANT[MML.VARIANT.ITALIC] = MML.VARIANT.BOLDITALIC; + BOLDVARIANT[MML.VARIANT.FRAKTUR] = MML.VARIANT.BOLDFRAKTUR; + BOLDVARIANT[MML.VARIANT.SCRIPT] = MML.VARIANT.BOLDSCRIPT; + BOLDVARIANT[MML.VARIANT.SANSSERIF] = MML.VARIANT.BOLDSANSSERIF; + BOLDVARIANT["-tex-caligraphic"] = "-tex-caligraphic-bold"; + BOLDVARIANT["-tex-oldstyle"] = "-tex-oldstyle-bold"; + + TEXDEF.Add({macros: {boldsymbol: 'Boldsymbol'}},null,true); + + TEX.Parse.Augment({ + mmlToken: function (token) { + if (this.stack.env.boldsymbol) { + var variant = token.Get("mathvariant"); + if (variant == null) {token.mathvariant = MML.VARIANT.BOLD} + else {token.mathvariant = (BOLDVARIANT[variant]||variant)} + } + return token; + }, + + Boldsymbol: function (name) { + var boldsymbol = this.stack.env.boldsymbol, + font = this.stack.env.font; + this.stack.env.boldsymbol = true; + this.stack.env.font = null; + var mml = this.ParseArg(name); + this.stack.env.font = font; + this.stack.env.boldsymbol = boldsymbol; + this.Push(mml); + } + }); + + MathJax.Hub.Startup.signal.Post("TeX boldsymbol Ready"); + +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/boldsymbol.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/cancel.js b/js/mathjax/extensions/TeX/cancel.js new file mode 100644 index 0000000..9f2afe8 --- /dev/null +++ b/js/mathjax/extensions/TeX/cancel.js @@ -0,0 +1,112 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/cancel.js + * + * Implements the \cancel, \bcancel, \xcancel, and \cancelto macros. + * + * Usage: + * + * \cancel{math} % strikeout math from lower left to upper right + * \bcancel{math} % strikeout from upper left to lower right + * \xcancel{math} % strikeout with an X + * \cancelto{value}{math} % strikeout with arrow going to value + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2011-2020 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. + */ + +MathJax.Extension["TeX/cancel"] = { + version: "2.7.9", + + // + // The attributes allowed in \enclose{notation}[attributes]{math} + // + ALLOWED: { + color: 1, mathcolor: 1, + background: 1, mathbackground: 1, + padding: 1, + thickness: 1 + } +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + var TEX = MathJax.InputJax.TeX, + MML = MathJax.ElementJax.mml, + CANCEL = MathJax.Extension["TeX/cancel"]; + + CANCEL.setAttributes = function (def,attr) { + if (attr !== "") { + attr = attr.replace(/ /g,"").split(/,/); + for (var i = 0, m = attr.length; i < m; i++) { + var keyvalue = attr[i].split(/[:=]/); + if (CANCEL.ALLOWED[keyvalue[0]]) { + if (keyvalue[1] === "true") {keyvalue[1] = true} + if (keyvalue[1] === "false") {keyvalue[1] = false} + def[keyvalue[0]] = keyvalue[1]; + } + } + } + return def; + }; + + // + // Set up macros + // + TEX.Definitions.Add({ + macros: { + cancel: ['Cancel',MML.NOTATION.UPDIAGONALSTRIKE], + bcancel: ['Cancel',MML.NOTATION.DOWNDIAGONALSTRIKE], + xcancel: ['Cancel',MML.NOTATION.UPDIAGONALSTRIKE+" "+MML.NOTATION.DOWNDIAGONALSTRIKE], + cancelto: 'CancelTo' + } + },null,true); + + TEX.Parse.Augment({ + // + // Implement \cancel[attributes]{math}, + // \bcancel[attributes]{math}, and + // \xcancel[attributes]{math} + // + Cancel: function(name,notation) { + var attr = this.GetBrackets(name,""), math = this.ParseArg(name); + var def = CANCEL.setAttributes({notation: notation},attr); + this.Push(MML.menclose(math).With(def)); + }, + + // + // Implement \cancelto{value}[attributes]{math} + // + CancelTo: function(name,notation) { + var value = this.ParseArg(name), + attr = this.GetBrackets(name,""), + math = this.ParseArg(name); + var def = CANCEL.setAttributes({notation: MML.NOTATION.UPDIAGONALSTRIKE+" "+MML.NOTATION.UPDIAGONALARROW},attr); + value = MML.mpadded(value).With({depth:"-.1em",height:"+.1em",voffset:".1em"}); + this.Push(MML.msup(MML.menclose(math).With(def),value)); + } + + }); + + MathJax.Hub.Startup.signal.Post("TeX cancel Ready"); + +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/cancel.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/color.js b/js/mathjax/extensions/TeX/color.js new file mode 100644 index 0000000..45c9b9e --- /dev/null +++ b/js/mathjax/extensions/TeX/color.js @@ -0,0 +1,283 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/color.js + * + * Implements LaTeX-compatible \color macro rather than MathJax's original + * (non-standard) version. It includes the rgb, RGB, gray, and named color + * models, and the \textcolor, \definecolor, \colorbox, and \fcolorbox + * macros. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2011-2020 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. + */ + +// +// The configuration defaults, augmented by the user settings +// +MathJax.Extension["TeX/color"] = { + version: "2.7.9", + + config: MathJax.Hub.CombineConfig("TeX.color",{ + padding: "5px", + border: "2px" + }), + + colors: { + Apricot: "#FBB982", + Aquamarine: "#00B5BE", + Bittersweet: "#C04F17", + Black: "#221E1F", + Blue: "#2D2F92", + BlueGreen: "#00B3B8", + BlueViolet: "#473992", + BrickRed: "#B6321C", + Brown: "#792500", + BurntOrange: "#F7921D", + CadetBlue: "#74729A", + CarnationPink: "#F282B4", + Cerulean: "#00A2E3", + CornflowerBlue: "#41B0E4", + Cyan: "#00AEEF", + Dandelion: "#FDBC42", + DarkOrchid: "#A4538A", + Emerald: "#00A99D", + ForestGreen: "#009B55", + Fuchsia: "#8C368C", + Goldenrod: "#FFDF42", + Gray: "#949698", + Green: "#00A64F", + GreenYellow: "#DFE674", + JungleGreen: "#00A99A", + Lavender: "#F49EC4", + LimeGreen: "#8DC73E", + Magenta: "#EC008C", + Mahogany: "#A9341F", + Maroon: "#AF3235", + Melon: "#F89E7B", + MidnightBlue: "#006795", + Mulberry: "#A93C93", + NavyBlue: "#006EB8", + OliveGreen: "#3C8031", + Orange: "#F58137", + OrangeRed: "#ED135A", + Orchid: "#AF72B0", + Peach: "#F7965A", + Periwinkle: "#7977B8", + PineGreen: "#008B72", + Plum: "#92268F", + ProcessBlue: "#00B0F0", + Purple: "#99479B", + RawSienna: "#974006", + Red: "#ED1B23", + RedOrange: "#F26035", + RedViolet: "#A1246B", + Rhodamine: "#EF559F", + RoyalBlue: "#0071BC", + RoyalPurple: "#613F99", + RubineRed: "#ED017D", + Salmon: "#F69289", + SeaGreen: "#3FBC9D", + Sepia: "#671800", + SkyBlue: "#46C5DD", + SpringGreen: "#C6DC67", + Tan: "#DA9D76", + TealBlue: "#00AEB3", + Thistle: "#D883B7", + Turquoise: "#00B4CE", + Violet: "#58429B", + VioletRed: "#EF58A0", + White: "#FFFFFF", + WildStrawberry: "#EE2967", + Yellow: "#FFF200", + YellowGreen: "#98CC70", + YellowOrange: "#FAA21A" + }, + + /* + * Look up a color based on its model and definition + */ + getColor: function (model,def) { + if (!model) {model = "named"} + var fn = this["get_"+model]; + if (!fn) {this.TEX.Error(["UndefinedColorModel","Color model '%1' not defined",model])} + return fn.call(this,def); + }, + + /* + * Get an rgb color + */ + get_rgb: function (rgb) { + rgb = rgb.replace(/^\s+/,"").replace(/\s+$/,"").split(/\s*,\s*/); var RGB = "#"; + if (rgb.length !== 3) + {this.TEX.Error(["ModelArg1","Color values for the %1 model require 3 numbers","rgb"])} + for (var i = 0; i < 3; i++) { + if (!rgb[i].match(/^(\d+(\.\d*)?|\.\d+)$/)) + {this.TEX.Error(["InvalidDecimalNumber","Invalid decimal number"])} + var n = parseFloat(rgb[i]); + if (n < 0 || n > 1) { + this.TEX.Error(["ModelArg2", + "Color values for the %1 model must be between %2 and %3", + "rgb",0,1]); + } + n = Math.floor(n*255).toString(16); if (n.length < 2) {n = "0"+n} + RGB += n; + } + return RGB; + }, + + /* + * Get an RGB color + */ + get_RGB: function (rgb) { + rgb = rgb.replace(/^\s+/,"").replace(/\s+$/,"").split(/\s*,\s*/); var RGB = "#"; + if (rgb.length !== 3) + {this.TEX.Error(["ModelArg1","Color values for the %1 model require 3 numbers","RGB"])} + for (var i = 0; i < 3; i++) { + if (!rgb[i].match(/^\d+$/)) + {this.TEX.Error(["InvalidNumber","Invalid number"])} + var n = parseInt(rgb[i]); + if (n > 255) { + this.TEX.Error(["ModelArg2", + "Color values for the %1 model must be between %2 and %3", + "RGB",0,255]); + } + n = n.toString(16); if (n.length < 2) {n = "0"+n} + RGB += n; + } + return RGB; + }, + + /* + * Get a gray-scale value + */ + get_gray: function (gray) { + if (!gray.match(/^\s*(\d+(\.\d*)?|\.\d+)\s*$/)) + {this.TEX.Error(["InvalidDecimalNumber","Invalid decimal number"])} + var n = parseFloat(gray); + if (n < 0 || n > 1) { + this.TEX.Error(["ModelArg2", + "Color values for the %1 model must be between %2 and %3", + "gray",0,1]); + } + n = Math.floor(n*255).toString(16); if (n.length < 2) {n = "0"+n} + return "#"+n+n+n; + }, + + /* + * Get a named value + */ + get_named: function (name) { + if (this.colors.hasOwnProperty(name)) {return this.colors[name]} + return name; + }, + + padding: function () { + var pad = "+"+this.config.padding; + var unit = this.config.padding.replace(/^.*?([a-z]*)$/,"$1"); + var pad2 = "+"+(2*parseFloat(pad))+unit; + return {width:pad2, height:pad, depth:pad, lspace:this.config.padding}; + } + +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + var TEX = MathJax.InputJax.TeX, + MML = MathJax.ElementJax.mml; + var STACKITEM = TEX.Stack.Item; + var COLOR = MathJax.Extension["TeX/color"]; + + COLOR.TEX = TEX; // for reference in getColor above + + TEX.Definitions.Add({ + macros: { + color: "Color", + textcolor: "TextColor", + definecolor: "DefineColor", + colorbox: "ColorBox", + fcolorbox: "fColorBox" + } + },null,true); + + TEX.Parse.Augment({ + + // + // Override \color macro definition + // + Color: function (name) { + var model = this.GetBrackets(name), + color = this.GetArgument(name); + color = COLOR.getColor(model,color); + var mml = STACKITEM.style().With({styles:{mathcolor:color}}); + this.stack.env.color = color; + this.Push(mml); + }, + + TextColor: function (name) { + var model = this.GetBrackets(name), + color = this.GetArgument(name); + color = COLOR.getColor(model,color); + var old = this.stack.env.color; this.stack.env.color = color; + var math = this.ParseArg(name); + if (old) {this.stack.env.color} else {delete this.stack.env.color} + this.Push(MML.mstyle(math).With({mathcolor: color})); + }, + + // + // Define the \definecolor macro + // + DefineColor: function (name) { + var cname = this.GetArgument(name), + model = this.GetArgument(name), + def = this.GetArgument(name); + COLOR.colors[cname] = COLOR.getColor(model,def); + }, + + // + // Produce a text box with a colored background + // + ColorBox: function (name) { + var cname = this.GetArgument(name), + arg = this.InternalMath(this.GetArgument(name)); + this.Push(MML.mpadded.apply(MML,arg).With({ + mathbackground:COLOR.getColor("named",cname) + }).With(COLOR.padding())); + }, + + // + // Procude a framed text box with a colored background + // + fColorBox: function (name) { + var fname = this.GetArgument(name), + cname = this.GetArgument(name), + arg = this.InternalMath(this.GetArgument(name)); + this.Push(MML.mpadded.apply(MML,arg).With({ + mathbackground: COLOR.getColor("named",cname), + style: "border: "+COLOR.config.border+" solid "+COLOR.getColor("named",fname) + }).With(COLOR.padding())); + } + + }); + + MathJax.Hub.Startup.signal.Post("TeX color Ready"); + +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/color.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/enclose.js b/js/mathjax/extensions/TeX/enclose.js new file mode 100644 index 0000000..0976984 --- /dev/null +++ b/js/mathjax/extensions/TeX/enclose.js @@ -0,0 +1,93 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/enclose.js + * + * Implements the \enclose macros, which give access from TeX to the + * <menclose> tag in the MathML that underlies MathJax's internal format. + * + * Usage: + * + * \enclose{notation}{math} % enclose math using given notation + * \enclose{notation,notation,...}{math} % enclose with several notations + * \enclose{notation}[attributes]{math} % enclose with attributes + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2011-2020 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. + */ + +MathJax.Extension["TeX/enclose"] = { + version: "2.7.9", + + // + // The attributes allowed in \enclose{notation}[attributes]{math} + // + ALLOWED: { + arrow: 1, + color: 1, mathcolor: 1, + background: 1, mathbackground: 1, + padding: 1, + thickness: 1 + } +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + var TEX = MathJax.InputJax.TeX, + MML = MathJax.ElementJax.mml, + ALLOW = MathJax.Extension["TeX/enclose"].ALLOWED; + + // + // Set up macro + // + TEX.Definitions.Add({macros: {enclose: 'Enclose'}},null,true); + + TEX.Parse.Augment({ + // + // Implement \enclose{notation}[attr]{math} + // (create <menclose notation="notation">math</menclose>) + // + Enclose: function(name) { + var notation = this.GetArgument(name), + attr = this.GetBrackets(name), + math = this.ParseArg(name); + var def = {notation: notation.replace(/,/g," ")}; + if (attr) { + attr = attr.replace(/ /g,"").split(/,/); + for (var i = 0, m = attr.length; i < m; i++) { + var keyvalue = attr[i].split(/[:=]/); + if (ALLOW[keyvalue[0]]) { + keyvalue[1] = keyvalue[1].replace(/^"(.*)"$/,"$1"); + if (keyvalue[1] === "true") {keyvalue[1] = true} + if (keyvalue[1] === "false") {keyvalue[1] = false} + if (keyvalue[0] === "arrow" && keyvalue[1]) + {def.notation = def.notation + " updiagonalarrow"} else + {def[keyvalue[0]] = keyvalue[1]} + } + } + } + this.Push(MML.menclose(math).With(def)); + } + }); + + MathJax.Hub.Startup.signal.Post("TeX enclose Ready"); + +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/enclose.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/extpfeil.js b/js/mathjax/extensions/TeX/extpfeil.js new file mode 100644 index 0000000..f07adac --- /dev/null +++ b/js/mathjax/extensions/TeX/extpfeil.js @@ -0,0 +1,104 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/extpfeil.js + * + * Implements additional stretchy arrow macros. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2011-2020 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. + */ + +MathJax.Extension["TeX/extpfeil"] = { + version: "2.7.9" +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + + var TEX = MathJax.InputJax.TeX, + TEXDEF = TEX.Definitions; + + // + // Define the arrows to load the AMSmath extension + // (since they need its xArrow method) + // + TEXDEF.Add({ + macros: { + xtwoheadrightarrow: ['Extension','AMSmath'], + xtwoheadleftarrow: ['Extension','AMSmath'], + xmapsto: ['Extension','AMSmath'], + xlongequal: ['Extension','AMSmath'], + xtofrom: ['Extension','AMSmath'], + Newextarrow: ['Extension','AMSmath'] + } + },null,true); + + // + // Redefine the macros when AMSmath is loaded + // + MathJax.Hub.Register.StartupHook("TeX AMSmath Ready",function () { + MathJax.Hub.Insert(TEXDEF,{ + macros: { + xtwoheadrightarrow: ['xArrow',0x21A0,12,16], + xtwoheadleftarrow: ['xArrow',0x219E,17,13], + xmapsto: ['xArrow',0x21A6,6,7], + xlongequal: ['xArrow',0x003D,7,7], + xtofrom: ['xArrow',0x21C4,12,12], + Newextarrow: 'NewExtArrow' + } + }); + }); + + // + // Implements \Newextarrow to define a new arrow (not compatible with \newextarrow, but + // the equivalent for MathJax) + // + TEX.Parse.Augment({ + NewExtArrow: function (name) { + var cs = this.GetArgument(name), + space = this.GetArgument(name), + chr = this.GetArgument(name); + if (!cs.match(/^\\([a-z]+|.)$/i)) { + TEX.Error(["NewextarrowArg1", + "First argument to %1 must be a control sequence name",name]); + } + if (!space.match(/^(\d+),(\d+)$/)) { + TEX.Error( + ["NewextarrowArg2", + "Second argument to %1 must be two integers separated by a comma", + name] + ); + } + if (!chr.match(/^(\d+|0x[0-9A-F]+)$/i)) { + TEX.Error( + ["NewextarrowArg3", + "Third argument to %1 must be a unicode character number", + name] + ); + } + cs = cs.substr(1); space = space.split(","); chr = parseInt(chr); + this.setDef(cs, ['xArrow', chr, parseInt(space[0]), parseInt(space[1])]); + } + }); + + MathJax.Hub.Startup.signal.Post("TeX extpfeil Ready"); +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/extpfeil.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/mathchoice.js b/js/mathjax/extensions/TeX/mathchoice.js new file mode 100644 index 0000000..7042395 --- /dev/null +++ b/js/mathjax/extensions/TeX/mathchoice.js @@ -0,0 +1,109 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/mathchoice.js + * + * Implements the \mathchoice macro (rarely used) + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2009-2020 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. + */ + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + var VERSION = "2.7.9"; + + var MML = MathJax.ElementJax.mml; + var TEX = MathJax.InputJax.TeX; + var TEXDEF = TEX.Definitions; + + TEXDEF.Add({macros: {mathchoice: 'MathChoice'}},null,true); + + TEX.Parse.Augment({ + MathChoice: function (name) { + var D = this.ParseArg(name), + T = this.ParseArg(name), + S = this.ParseArg(name), + SS = this.ParseArg(name); + this.Push(MML.TeXmathchoice(D,T,S,SS)); + } + }); + + MML.TeXmathchoice = MML.mbase.Subclass({ + type: "TeXmathchoice", notParent: true, + choice: function () { + if (this.selection != null) return this.selection; + if (this.choosing) return 2; // prevent infinite loops: see issue #1151 + this.choosing = true; + var selection = 0, values = this.getValues("displaystyle","scriptlevel"); + if (values.scriptlevel > 0) {selection = Math.min(3,values.scriptlevel+1)} + else {selection = (values.displaystyle ? 0 : 1)} + // only cache the result if we are actually in place in a <math> tag. + var node = this.inherit; while (node && node.type !== "math") node = node.inherit; + if (node) this.selection = selection; + this.choosing = false; + return selection; + }, + selected: function () {return this.data[this.choice()]}, + setTeXclass: function (prev) {return this.selected().setTeXclass(prev)}, + isSpacelike: function () {return this.selected().isSpacelike()}, + isEmbellished: function () {return this.selected().isEmbellished()}, + Core: function () {return this.selected()}, + CoreMO: function () {return this.selected().CoreMO()}, + toHTML: function (span) { + span = this.HTMLcreateSpan(span); + span.bbox = this.Core().toHTML(span).bbox; + // Firefox doesn't correctly handle a span with a negatively sized content, + // so move marginLeft to main span (this is a hack to get \iiiint to work). + // FIXME: This is a symptom of a more general problem with Firefox, and + // there probably needs to be a more general solution (e.g., modifying + // HTMLhandleSpace() to get the width and adjust the right margin to + // compensate for negative-width contents) + if (span.firstChild && span.firstChild.style.marginLeft) { + span.style.marginLeft = span.firstChild.style.marginLeft; + span.firstChild.style.marginLeft = ""; + } + return span; + }, + toSVG: function () { + var svg = this.Core().toSVG(); + this.SVGsaveData(svg); + return svg; + }, + toCommonHTML: function (node) { + node = this.CHTMLcreateNode(node); + this.CHTMLhandleStyle(node); + this.CHTMLhandleColor(node); + this.CHTMLaddChild(node,this.choice(),{}); + return node; + }, + toPreviewHTML: function(span) { + span = this.PHTMLcreateSpan(span); + this.PHTMLhandleStyle(span); + this.PHTMLhandleColor(span); + this.PHTMLaddChild(span,this.choice(),{}); + return span; + } + }); + + MathJax.Hub.Startup.signal.Post("TeX mathchoice Ready"); + +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/mathchoice.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/mediawiki-texvc.js b/js/mathjax/extensions/TeX/mediawiki-texvc.js new file mode 100644 index 0000000..ab1ed42 --- /dev/null +++ b/js/mathjax/extensions/TeX/mediawiki-texvc.js @@ -0,0 +1,138 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/************************************************************* + * + * MathJax/extensions/TeX/mediawiki-texvc.js + * + * Implements macros used by mediawiki with their texvc preprocessor. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2015-2020 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. + */ + +MathJax.Extension["TeX/mediawiki-texvc"] = { + version: "2.7.9" +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready", function () { + MathJax.InputJax.TeX.Definitions.Add({ + macros: { + AA: ["Macro", "\u00c5"], + alef: ["Macro", "\\aleph"], + alefsym: ["Macro", "\\aleph"], + Alpha: ["Macro", "\\mathrm{A}"], + and: ["Macro", "\\land"], + ang: ["Macro", "\\angle"], + Bbb: ["Macro", "\\mathbb"], + Beta: ["Macro", "\\mathrm{B}"], + bold: ["Macro", "\\mathbf"], + bull: ["Macro", "\\bullet"], + C: ["Macro", "\\mathbb{C}"], + Chi: ["Macro", "\\mathrm{X}"], + clubs: ["Macro", "\\clubsuit"], + cnums: ["Macro", "\\mathbb{C}"], + Complex: ["Macro", "\\mathbb{C}"], + coppa: ["Macro", "\u03D9"], + Coppa: ["Macro", "\u03D8"], + Dagger: ["Macro", "\\ddagger"], + Digamma: ["Macro", "\u03DC"], + darr: ["Macro", "\\downarrow"], + dArr: ["Macro", "\\Downarrow"], + Darr: ["Macro", "\\Downarrow"], + dashint: ["Macro", "\\unicodeInt{x2A0D}"], + ddashint: ["Macro", "\\unicodeInt{x2A0E}"], + diamonds: ["Macro", "\\diamondsuit"], + empty: ["Macro", "\\emptyset"], + Epsilon: ["Macro", "\\mathrm{E}"], + Eta: ["Macro", "\\mathrm{H}"], + euro: ["Macro", "\u20AC"], + exist: ["Macro", "\\exists"], + geneuro: ["Macro", "\u20AC"], + geneuronarrow: ["Macro", "\u20AC"], + geneurowide: ["Macro", "\u20AC"], + H: ["Macro", "\\mathbb{H}"], + hAar: ["Macro", "\\Leftrightarrow"], + harr: ["Macro", "\\leftrightarrow"], + Harr: ["Macro", "\\Leftrightarrow"], + hearts: ["Macro", "\\heartsuit"], + image: ["Macro", "\\Im"], + infin: ["Macro", "\\infty"], + Iota: ["Macro", "\\mathrm{I}"], + isin: ["Macro", "\\in"], + Kappa: ["Macro", "\\mathrm{K}"], + koppa: ["Macro", "\u03DF"], + Koppa: ["Macro", "\u03DE"], + lang: ["Macro", "\\langle"], + larr: ["Macro", "\\leftarrow"], + Larr: ["Macro", "\\Leftarrow"], + lArr: ["Macro", "\\Leftarrow"], + lrarr: ["Macro", "\\leftrightarrow"], + Lrarr: ["Macro", "\\Leftrightarrow"], + lrArr: ["Macro", "\\Leftrightarrow"], + Mu: ["Macro", "\\mathrm{M}"], + N: ["Macro", "\\mathbb{N}"], + natnums: ["Macro", "\\mathbb{N}"], + Nu: ["Macro", "\\mathrm{N}"], + O: ["Macro", "\\emptyset"], + oiint: ["Macro", "\\unicodeInt{x222F}"], + oiiint: ["Macro", "\\unicodeInt{x2230}"], + ointctrclockwise: ["Macro", "\\unicodeInt{x2233}"], + officialeuro: ["Macro", "\u20AC"], + Omicron: ["Macro", "\\mathrm{O}"], + or: ["Macro", "\\lor"], + P: ["Macro", "\u00B6"], + pagecolor: ['Macro','',1], // ignore \pagecolor{} + part: ["Macro", "\\partial"], + plusmn: ["Macro", "\\pm"], + Q: ["Macro", "\\mathbb{Q}"], + R: ["Macro", "\\mathbb{R}"], + rang: ["Macro", "\\rangle"], + rarr: ["Macro", "\\rightarrow"], + Rarr: ["Macro", "\\Rightarrow"], + rArr: ["Macro", "\\Rightarrow"], + real: ["Macro", "\\Re"], + reals: ["Macro", "\\mathbb{R}"], + Reals: ["Macro", "\\mathbb{R}"], + Rho: ["Macro", "\\mathrm{P}"], + sdot: ["Macro", "\\cdot"], + sampi: ["Macro", "\u03E1"], + Sampi: ["Macro", "\u03E0"], + sect: ["Macro", "\\S"], + spades: ["Macro", "\\spadesuit"], + stigma: ["Macro", "\u03DB"], + Stigma: ["Macro", "\u03DA"], + sub: ["Macro", "\\subset"], + sube: ["Macro", "\\subseteq"], + supe: ["Macro", "\\supseteq"], + Tau: ["Macro", "\\mathrm{T}"], + textvisiblespace: ["Macro", "\u2423"], + thetasym: ["Macro", "\\vartheta"], + uarr: ["Macro", "\\uparrow"], + uArr: ["Macro", "\\Uparrow"], + Uarr: ["Macro", "\\Uparrow"], + unicodeInt: ["Macro", "\\mathop{\\vcenter{\\mathchoice{\\huge\\unicode{#1}\\,}{\\unicode{#1}}{\\unicode{#1}}{\\unicode{#1}}}\\,}\\nolimits", 1], + varcoppa: ["Macro", "\u03D9"], + varstigma: ["Macro", "\u03DB"], + varointclockwise: ["Macro", "\\unicodeInt{x2232}"], + vline: ['Macro','\\smash{\\large\\lvert}',0], + weierp: ["Macro", "\\wp"], + Z: ["Macro", "\\mathbb{Z}"], + Zeta: ["Macro", "\\mathrm{Z}"] + } + }); +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/mediawiki-texvc.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/mhchem.js b/js/mathjax/extensions/TeX/mhchem.js new file mode 100644 index 0000000..9d15876 --- /dev/null +++ b/js/mathjax/extensions/TeX/mhchem.js @@ -0,0 +1,522 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/mhchem.js + * + * Implements the \ce command for handling chemical formulas + * from the mhchem LaTeX package. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2011-2020 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. + */ + + +// +// Don't replace [Contrib]/mhchem if it is already loaded +// +if (MathJax.Extension["TeX/mhchem"]) { + MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/mhchem.js"); +} else { + +MathJax.Extension["TeX/mhchem"] = { + version: "2.7.9", + config: MathJax.Hub.CombineConfig("TeX.mhchem",{ + legacy: true + }) +}; + +// +// Load [mhchem]/mhchem.js if not configured for legacy vesion +// +if (!MathJax.Extension["TeX/mhchem"].config.legacy) { + if (!MathJax.Ajax.config.path.mhchem) { + MathJax.Ajax.config.path.mhchem = MathJax.Hub.config.root + "/extensions/TeX/mhchem3"; + } + MathJax.Callback.Queue( + ["Require",MathJax.Ajax,"[mhchem]/mhchem.js"], + ["loadComplete",MathJax.Ajax,"[MathJax]/extensions/TeX/mhchem.js"] + ); +} else { + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + + var TEX = MathJax.InputJax.TeX; + + /* + * This is the main class for handing the \ce and related commands. + * Its main method is Parse() which takes the argument to \ce and + * returns the corresponding TeX string. + */ + + var CE = MathJax.Object.Subclass({ + string: "", // the \ce string being parsed + i: 0, // the current position in the string + tex: "", // the partially processed TeX result + TEX: "", // the full TeX result + atom: false, // last processed token is an atom + sup: "", // pending superscript + sub: "", // pending subscript + presup: "", // pending pre-superscript + presub: "", // pending pre-subscript + + // + // Store the string when a CE object is created + // + Init: function (string) {this.string = string}, + + // + // These are the special characters and the methods that + // handle them. All others are passed through verbatim. + // + ParseTable: { + '-': "Minus", + '+': "Plus", + '(': "Open", + ')': "Close", + '[': "Open", + ']': "Close", + '<': "Less", + '^': "Superscript", + '_': "Subscript", + '*': "Dot", + '.': "Dot", + '=': "Equal", + '#': "Pound", + '$': "Math", + '\\': "Macro", + ' ': "Space" + }, + // + // Basic arrow names for reactions + // + Arrows: { + '->': "rightarrow", + '<-': "leftarrow", + '<->': "leftrightarrow", + '<=>': "rightleftharpoons", + '<=>>': "Rightleftharpoons", + '<<=>': "Leftrightharpoons", + '^': "uparrow", + 'v': "downarrow" + }, + + // + // Implementations for the various bonds + // (the ~ ones are hacks that don't work well in NativeMML) + // + Bonds: { + '-': "-", + '=': "=", + '#': "\\equiv", + '~': "\\tripledash", + '~-': "\\begin{CEstack}{}\\tripledash\\\\-\\end{CEstack}", + '~=': "\\raise2mu{\\begin{CEstack}{}\\tripledash\\\\-\\\\-\\end{CEstack}}", + '~--': "\\raise2mu{\\begin{CEstack}{}\\tripledash\\\\-\\\\-\\end{CEstack}}", + '-~-': "\\raise2mu{\\begin{CEstack}{}-\\\\\\tripledash\\\\-\\end{CEstack}}", + '...': "{\\cdot}{\\cdot}{\\cdot}", + '....': "{\\cdot}{\\cdot}{\\cdot}{\\cdot}", + '->': "\\rightarrow", + '<-': "\\leftarrow", + '??': "\\text{??}" // unknown bond + }, + + // + // This converts the CE string to a TeX string. + // It loops through the string and calls the proper + // method depending on the ccurrent character. + // + Parse: function () { + this.tex = ""; this.atom = false; + while (this.i < this.string.length) { + var c = this.string.charAt(this.i); + if (c.match(/[a-z]/i)) {this.ParseLetter()} + else if (c.match(/[0-9]/)) {this.ParseNumber()} + else {this["Parse"+(this.ParseTable[c]||"Other")](c)} + } + this.FinishAtom(true); + return this.TEX; + }, + + // + // Make an atom name or a down arrow + // + ParseLetter: function () { + this.FinishAtom(); + if (this.Match(/^v( |$)/)) { + this.tex += "{\\"+this.Arrows["v"]+"}"; + } else { + this.tex += "\\text{"+this.Match(/^[a-z]+/i)+"}"; + this.atom = true; + } + }, + + // + // Make a number or fraction preceding an atom, + // or a subscript for an atom. + // + ParseNumber: function () { + var n = this.Match(/^\d+/); + if (this.atom && !this.sub) { + this.sub = n; + } else { + this.FinishAtom(); + var match = this.Match(/^\/\d+/); + if (match) { + var frac = "\\frac{"+n+"}{"+match.substr(1)+"}"; + this.tex += "\\mathchoice{\\textstyle"+frac+"}{"+frac+"}{"+frac+"}{"+frac+"}"; + } else { + this.tex += n; + if (this.i < this.string.length) {this.tex += "\\,"} + } + } + }, + + // + // Make a superscript minus, or an arrow, or a single bond. + // + ParseMinus: function (c) { + if (this.atom && (this.i === this.string.length-1 || this.string.charAt(this.i+1) === " ")) { + this.sup += c; + } else { + this.FinishAtom(); + if (this.string.substr(this.i,2) === "->") {this.i += 2; this.AddArrow("->"); return} + else {this.tex += "{-}"} + } + this.i++; + }, + + // + // Make a superscript plus, or pass it through + // + ParsePlus: function (c) { + if (this.atom) {this.sup += c} else {this.FinishAtom(); this.tex += c} + this.i++; + }, + + // + // Handle dots and double or triple bonds + // + ParseDot: function (c) {this.FinishAtom(); this.tex += "\\cdot "; this.i++}, + ParseEqual: function (c) {this.FinishAtom(); this.tex += "{=}"; this.i++}, + ParsePound: function (c) {this.FinishAtom(); this.tex += "{\\equiv}"; this.i++}, + + // + // Look for (v) or (^), or pass it through + // + ParseOpen: function (c) { + this.FinishAtom(); + var match = this.Match(/^\([v^]\)/); + if (match) {this.tex += "{\\"+this.Arrows[match.charAt(1)]+"}"} + else {this.tex += "{"+c; this.i++} + }, + // + // Allow ) and ] to get super- and subscripts + // + ParseClose: function (c) {this.FinishAtom(); this.atom = true; this.tex += c+"}"; this.i++}, + + // + // Make the proper arrow + // + ParseLess: function (c) { + this.FinishAtom(); + var arrow = this.Match(/^(<->?|<=>>?|<<=>)/); + if (!arrow) {this.tex += c; this.i++} else {this.AddArrow(arrow)} + }, + + // + // Look for a superscript, or an up arrow + // + ParseSuperscript: function (c) { + c = this.string.charAt(++this.i); + if (c === "{") { + this.i++; var m = this.Find("}"); + if (m === "-.") {this.sup += "{-}{\\cdot}"} + else if (m) {this.sup += CE(m).Parse().replace(/^\{-\}/,"-")} + } else if (c === " " || c === "") { + this.tex += "{\\"+this.Arrows["^"]+"}"; this.i++; + } else { + var n = this.Match(/^(\d+|-\.)/); + if (n) {this.sup += n} + } + }, + // + // Look for subscripts + // + ParseSubscript: function (c) { + if (this.string.charAt(++this.i) == "{") { + this.i++; this.sub += CE(this.Find("}")).Parse().replace(/^\{-\}/,"-"); + } else { + var n = this.Match(/^\d+/); + if (n) {this.sub += n} + } + }, + + // + // Look for raw TeX code to include + // + ParseMath: function (c) { + this.FinishAtom(); + this.i++; this.tex += this.Find(c); + }, + + // + // Look for specific macros for bonds + // and allow \} to have subscripts + // + ParseMacro: function (c) { + this.FinishAtom(); + this.i++; var match = this.Match(/^([a-z]+|.)/i)||" "; + if (match === "sbond") {this.tex += "{-}"} + else if (match === "dbond") {this.tex += "{=}"} + else if (match === "tbond") {this.tex += "{\\equiv}"} + else if (match === "bond") { + var bond = (this.Match(/^\{.*?\}/)||""); + bond = bond.substr(1,bond.length-2); + this.tex += "{"+(this.Bonds[bond]||"\\text{??}")+"}"; + } + else if (match === "{") {this.tex += "{\\{"} + else if (match === "}") {this.tex += "\\}}"; this.atom = true} + else {this.tex += c+match} + }, + + // + // Ignore spaces + // + ParseSpace: function (c) {this.FinishAtom(); this.i++}, + + // + // Pass anything else on verbatim + // + ParseOther: function (c) {this.FinishAtom(); this.tex += c; this.i++}, + + // + // Process an arrow (looking for brackets for above and below) + // + AddArrow: function (arrow) { + var c = this.Match(/^[CT]\[/); + if (c) {this.i--; c = c.charAt(0)} + var above = this.GetBracket(c), below = this.GetBracket(c); + arrow = this.Arrows[arrow]; + if (above || below) { + if (below) {arrow += "["+below+"]"} + arrow += "{"+above+"}"; + arrow = "\\mathrel{\\x"+arrow+"}"; + } else { + arrow = "\\long"+arrow+" "; + } + this.tex += arrow; + }, + + // + // Handle the super and subscripts for an atom + // + FinishAtom: function (force) { + if (this.sup || this.sub || this.presup || this.presub) { + if (!force && !this.atom) { + if (this.tex === "" && !this.sup && !this.sub) return; + if (!this.presup && !this.presub && + (this.tex === "" || this.tex === "{" || + (this.tex === "}" && this.TEX.substr(-1) === "{"))) { + this.presup = this.sup, this.presub = this.sub; // save for later + this.sub = this.sup = ""; + this.TEX += this.tex; this.tex = ""; + return; + } + } + if (this.sub && !this.sup) {this.sup = "\\Space{0pt}{0pt}{.2em}"} // forces subscripts to align properly + if ((this.presup || this.presub) && this.tex !== "{") { + if (!this.presup && !this.sup) {this.presup = "\\Space{0pt}{0pt}{.2em}"} + this.tex = "\\CEprescripts{"+(this.presub||"\\CEnone")+"}{"+(this.presup||"\\CEnone")+"}" + + "{"+(this.tex !== "}" ? this.tex : "")+"}" + + "{"+(this.sub||"\\CEnone")+"}{"+(this.sup||"\\CEnone")+"}" + + (this.tex === "}" ? "}" : ""); + this.presub = this.presup = ""; + } else { + if (this.sup) this.tex += "^{"+this.sup+"}"; + if (this.sub) this.tex += "_{"+this.sub+"}"; + } + this.sup = this.sub = ""; + } + this.TEX += this.tex; this.tex = ""; + this.atom = false; + }, + + // + // Find a bracket group and handle C and T prefixes + // + GetBracket: function (c) { + if (this.string.charAt(this.i) !== "[") {return ""} + this.i++; var bracket = this.Find("]"); + if (c === "C") {bracket = "\\ce{"+bracket+"}"} else + if (c === "T") { + if (!bracket.match(/^\{.*\}$/)) {bracket = "{"+bracket+"}"} + bracket = "\\text"+bracket; + }; + return bracket; + }, + + // + // Check if the string matches a regular expression + // and move past it if so, returning the match + // + Match: function (regex) { + var match = regex.exec(this.string.substr(this.i)); + if (match) {match = match[0]; this.i += match.length} + return match; + }, + + // + // Find a particular character, skipping over braced groups + // + Find: function (c) { + var m = this.string.length, i = this.i, braces = 0; + while (this.i < m) { + var C = this.string.charAt(this.i++); + if (C === c && braces === 0) {return this.string.substr(i,this.i-i-1)} + if (C === "{") {braces++} else + if (C === "}") { + if (braces) {braces--} + else { + TEX.Error(["ExtraCloseMissingOpen","Extra close brace or missing open brace"]) + } + } + } + if (braces) {TEX.Error(["MissingCloseBrace","Missing close brace"])} + TEX.Error(["NoClosingChar","Can't find closing %1",c]); + } + + }); + + MathJax.Extension["TeX/mhchem"].CE = CE; + + /***************************************************************************/ + + TEX.Definitions.Add({ + macros: { + // + // Set up the macros for chemistry + // + ce: 'CE', + cf: 'CE', + cee: 'CE', + + // + // Make these load AMSmath package (redefined below when loaded) + // + xleftrightarrow: ['Extension','AMSmath'], + xrightleftharpoons: ['Extension','AMSmath'], + xRightleftharpoons: ['Extension','AMSmath'], + xLeftrightharpoons: ['Extension','AMSmath'], + + // FIXME: These don't work well in FF NativeMML mode + longrightleftharpoons: ["Macro","\\stackrel{\\textstyle{{-}\\!\\!{\\rightharpoonup}}}{\\smash{{\\leftharpoondown}\\!\\!{-}}}"], + longRightleftharpoons: ["Macro","\\stackrel{\\textstyle{-}\\!\\!{\\rightharpoonup}}{\\small\\smash\\leftharpoondown}"], + longLeftrightharpoons: ["Macro","\\stackrel{\\rightharpoonup}{{{\\leftharpoondown}\\!\\!\\textstyle{-}}}"], + + // + // Add \hyphen used in some mhchem examples + // + hyphen: ["Macro","\\text{-}"], + + // + // Handle prescripts and none + // + CEprescripts: "CEprescripts", + CEnone: "CEnone", + + // + // Needed for \bond for the ~ forms + // + tripledash: ["Macro","\\raise3mu{\\tiny\\text{-}\\kern2mu\\text{-}\\kern2mu\\text{-}}"] + }, + + // + // Needed for \bond for the ~ forms + // + environment: { + CEstack: ['Array',null,null,null,'r',null,"0.001em",'T',1] + } + },null,true); + + if (!MathJax.Extension["TeX/AMSmath"]) { + TEX.Definitions.Add({ + macros: { + xrightarrow: ['Extension','AMSmath'], + xleftarrow: ['Extension','AMSmath'] + } + },null,true); + } + + // + // These arrows need to wait until AMSmath is loaded + // + MathJax.Hub.Register.StartupHook("TeX AMSmath Ready",function () { + TEX.Definitions.Add({ + macros: { + // + // Some of these are hacks for now + // + xleftrightarrow: ['xArrow',0x2194,6,6], + xrightleftharpoons: ['xArrow',0x21CC,5,7], // FIXME: doesn't stretch in HTML-CSS output + xRightleftharpoons: ['xArrow',0x21CC,5,7], // FIXME: how should this be handled? + xLeftrightharpoons: ['xArrow',0x21CC,5,7] + } + },null,true); + }); + + TEX.Parse.Augment({ + + // + // Implements \ce and friends + // + CE: function (name) { + var arg = this.GetArgument(name); + var tex = CE(arg).Parse(); + this.string = tex + this.string.substr(this.i); this.i = 0; + }, + + // + // Implements \CEprescripts{presub}{presup}{base}{sub}{sup} + // + CEprescripts: function (name) { + var presub = this.ParseArg(name), + presup = this.ParseArg(name), + base = this.ParseArg(name), + sub = this.ParseArg(name), + sup = this.ParseArg(name); + var MML = MathJax.ElementJax.mml; + this.Push(MML.mmultiscripts(base,sub,sup,MML.mprescripts(),presub,presup)); + }, + CEnone: function (name) { + this.Push(MathJax.ElementJax.mml.none()); + } + + }); + + // + // Indicate that the extension is ready + // + MathJax.Hub.Startup.signal.Post("TeX mhchem Ready"); + +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/mhchem.js"); + +}} +// @license-end diff --git a/js/mathjax/extensions/TeX/mhchem3/mhchem.js b/js/mathjax/extensions/TeX/mhchem3/mhchem.js new file mode 100644 index 0000000..2caa810 --- /dev/null +++ b/js/mathjax/extensions/TeX/mhchem3/mhchem.js @@ -0,0 +1,1776 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/mhchem.js + * + * Implements the \ce command for handling chemical formulas + * from the mhchem LaTeX package. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2011-2015 The MathJax Consortium + * Copyright (c) 2015-2019 Martin Hensel + * + * 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. + */ + +// +// Coding Style +// - use '' for identifiers that can by minified/uglified +// - use "" for strings that need to stay untouched + + +MathJax.Extension["TeX/mhchem"] = { + version: "3.3.2" +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready", function () { + + var TEX = MathJax.InputJax.TeX; + + // + // This is the main class for handing the \ce and related commands. + // Its main method is Parse() which takes the argument to \ce and + // returns the corresponding TeX string. + // + + var CE = MathJax.Object.Subclass({ + string: "", // the \ce string being parsed + + // + // Store the string when a CE object is created + // + Init: function (string) { this.string = string; }, + + // + // This converts the CE string to a TeX string. + // + Parse: function (stateMachine) { + try { + return texify.go(mhchemParser.go(this.string, stateMachine)); + } catch (ex) { + TEX.Error(ex); + } + } + }); + + // + // Core parser for mhchem syntax (recursive) + // + /** @type {MhchemParser} */ + var mhchemParser = { + // + // Parses mchem \ce syntax + // + // Call like + // go("H2O"); + // + go: function (input, stateMachine) { + if (!input) { return []; } + if (stateMachine === undefined) { stateMachine = 'ce'; } + var state = '0'; + + // + // String buffers for parsing: + // + // buffer.a == amount + // buffer.o == element + // buffer.b == left-side superscript + // buffer.p == left-side subscript + // buffer.q == right-side subscript + // buffer.d == right-side superscript + // + // buffer.r == arrow + // buffer.rdt == arrow, script above, type + // buffer.rd == arrow, script above, content + // buffer.rqt == arrow, script below, type + // buffer.rq == arrow, script below, content + // + // buffer.text_ + // buffer.rm + // etc. + // + // buffer.parenthesisLevel == int, starting at 0 + // buffer.sb == bool, space before + // buffer.beginsWithBond == bool + // + // These letters are also used as state names. + // + // Other states: + // 0 == begin of main part (arrow/operator unlikely) + // 1 == next entity + // 2 == next entity (arrow/operator unlikely) + // 3 == next atom + // c == macro + // + /** @type {Buffer} */ + var buffer = {}; + buffer['parenthesisLevel'] = 0; + + input = input.replace(/\n/g, " "); + input = input.replace(/[\u2212\u2013\u2014\u2010]/g, "-"); + input = input.replace(/[\u2026]/g, "..."); + + // + // Looks through mhchemParser.transitions, to execute a matching action + // (recursive) + // + var lastInput; + var watchdog = 10; + /** @type {ParserOutput[]} */ + var output = []; + while (true) { + if (lastInput !== input) { + watchdog = 10; + lastInput = input; + } else { + watchdog--; + } + // + // Find actions in transition table + // + var machine = mhchemParser.stateMachines[stateMachine]; + var t = machine.transitions[state] || machine.transitions['*']; + iterateTransitions: + for (var i=0; i<t.length; i++) { + var matches = mhchemParser.patterns.match_(t[i].pattern, input); + if (matches) { + // + // Execute actions + // + var task = t[i].task; + for (var iA=0; iA<task.action_.length; iA++) { + var o; + // + // Find and execute action + // + if (machine.actions[task.action_[iA].type_]) { + o = machine.actions[task.action_[iA].type_](buffer, matches.match_, task.action_[iA].option); + } else if (mhchemParser.actions[task.action_[iA].type_]) { + o = mhchemParser.actions[task.action_[iA].type_](buffer, matches.match_, task.action_[iA].option); + } else { + throw ["MhchemBugA", "mhchem bug A. Please report. (" + task.action_[iA].type_ + ")"]; // Trying to use non-existing action + } + // + // Add output + // + mhchemParser.concatArray(output, o); + } + // + // Set next state, + // Shorten input, + // Continue with next character + // (= apply only one transition per position) + // + state = task.nextState || state; + if (input.length > 0) { + if (!task.revisit) { + input = matches.remainder; + } + if (!task.toContinue) { + break iterateTransitions; + } + } else { + return output; + } + } + } + // + // Prevent infinite loop + // + if (watchdog <= 0) { + throw ["MhchemBugU", "mhchem bug U. Please report."]; // Unexpected character + } + } + }, + concatArray: function (a, b) { + if (b) { + if (Object.prototype.toString.call(b) === "[object Array]") { // Array.isArray(b) + for (var iB=0; iB<b.length; iB++) { + a.push(b[iB]); + } + } else { + a.push(b); + } + } + }, + + patterns: { + // + // Matching patterns + // either regexps or function that return null or {match_:"a", remainder:"bc"} + // + patterns: { + // property names must not look like integers ("2") for correct property traversal order, later on + 'empty': /^$/, + 'else': /^./, + 'else2': /^./, + 'space': /^\s/, + 'space A': /^\s(?=[A-Z\\$])/, + 'space$': /^\s$/, + 'a-z': /^[a-z]/, + 'x': /^x/, + 'x$': /^x$/, + 'i$': /^i$/, + 'letters': /^(?:[a-zA-Z\u03B1-\u03C9\u0391-\u03A9?@]|(?:\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))))+/, + '\\greek': /^\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))/, + 'one lowercase latin letter $': /^(?:([a-z])(?:$|[^a-zA-Z]))$/, + '$one lowercase latin letter$ $': /^\$(?:([a-z])(?:$|[^a-zA-Z]))\$$/, + 'one lowercase greek letter $': /^(?:\$?[\u03B1-\u03C9]\$?|\$?\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega)\s*\$?)(?:\s+|\{\}|(?![a-zA-Z]))$/, + 'digits': /^[0-9]+/, + '-9.,9': /^[+\-]?(?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))/, + '-9.,9 no missing 0': /^[+\-]?[0-9]+(?:[.,][0-9]+)?/, + '(-)(9.,9)(e)(99)': function (input) { + var m = input.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))?(\((?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))\))?(?:(?:([eE])|\s*(\*|x|\\times|\u00D7)\s*10\^)([+\-]?[0-9]+|\{[+\-]?[0-9]+\}))?/); + if (m && m[0]) { + return { match_: m.slice(1), remainder: input.substr(m[0].length) }; + } + return null; + }, + '(-)(9)^(-9)': function (input) { + var m = input.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+)?)\^([+\-]?[0-9]+|\{[+\-]?[0-9]+\})/); + if (m && m[0]) { + return { match_: m.slice(1), remainder: input.substr(m[0].length) }; + } + return null; + }, + 'state of aggregation $': function (input) { // ... or crystal system + var a = mhchemParser.patterns.findObserveGroups(input, "", /^\([a-z]{1,3}(?=[\),])/, ")", ""); // (aq), (aq,$\infty$), (aq, sat) + if (a && a.remainder.match(/^($|[\s,;\)\]\}])/)) { return a; } // AND end of 'phrase' + var m = input.match(/^(?:\((?:\\ca\s?)?\$[amothc]\$\))/); // OR crystal system ($o$) (\ca$c$) + if (m) { + return { match_: m[0], remainder: input.substr(m[0].length) }; + } + return null; + }, + '_{(state of aggregation)}$': /^_\{(\([a-z]{1,3}\))\}/, + '{[(': /^(?:\\\{|\[|\()/, + ')]}': /^(?:\)|\]|\\\})/, + ', ': /^[,;]\s*/, + ',': /^[,;]/, + '.': /^[.]/, + '. ': /^([.\u22C5\u00B7\u2022])\s*/, + '...': /^\.\.\.(?=$|[^.])/, + '* ': /^([*])\s*/, + '^{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "^{", "", "", "}"); }, + '^($...$)': function (input) { return mhchemParser.patterns.findObserveGroups(input, "^", "$", "$", ""); }, + '^a': /^\^([0-9]+|[^\\_])/, + '^\\x{}{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "^", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); }, + '^\\x{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "^", /^\\[a-zA-Z]+\{/, "}", ""); }, + '^\\x': /^\^(\\[a-zA-Z]+)\s*/, + '^(-1)': /^\^(-?\d+)/, + '\'': /^'/, + '_{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "_{", "", "", "}"); }, + '_($...$)': function (input) { return mhchemParser.patterns.findObserveGroups(input, "_", "$", "$", ""); }, + '_9': /^_([+\-]?[0-9]+|[^\\])/, + '_\\x{}{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "_", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); }, + '_\\x{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "_", /^\\[a-zA-Z]+\{/, "}", ""); }, + '_\\x': /^_(\\[a-zA-Z]+)\s*/, + '^_': /^(?:\^(?=_)|\_(?=\^)|[\^_]$)/, + '{}': /^\{\}/, + '{...}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", "{", "}", ""); }, + '{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "{", "", "", "}"); }, + '$...$': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", "$", "$", ""); }, + '${(...)}$': function (input) { return mhchemParser.patterns.findObserveGroups(input, "${", "", "", "}$"); }, + '$(...)$': function (input) { return mhchemParser.patterns.findObserveGroups(input, "$", "", "", "$"); }, + '=<>': /^[=<>]/, + '#': /^[#\u2261]/, + '+': /^\+/, + '-$': /^-(?=[\s_},;\]/]|$|\([a-z]+\))/, // -space -, -; -] -/ -$ -state-of-aggregation + '-9': /^-(?=[0-9])/, + '- orbital overlap': /^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/, + '-': /^-/, + 'pm-operator': /^(?:\\pm|\$\\pm\$|\+-|\+\/-)/, + 'operator': /^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/, + 'arrowUpDown': /^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/, + '\\bond{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\bond{", "", "", "}"); }, + '->': /^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/, + 'CMT': /^[CMT](?=\[)/, + '[(...)]': function (input) { return mhchemParser.patterns.findObserveGroups(input, "[", "", "", "]"); }, + '1st-level escape': /^(&|\\\\|\\hline)\s*/, + '\\,': /^(?:\\[,\ ;:])/, // \\x - but output no space before + '\\x{}{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", "", "", "{", "}", "", true); }, + '\\x{}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "", /^\\[a-zA-Z]+\{/, "}", ""); }, + '\\ca': /^\\ca(?:\s+|(?![a-zA-Z]))/, + '\\x': /^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/, + 'orbital': /^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/, // only those with numbers in front, because the others will be formatted correctly anyway + 'others': /^[\/~|]/, + '\\frac{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\frac{", "", "", "}", "{", "", "", "}"); }, + '\\overset{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\overset{", "", "", "}", "{", "", "", "}"); }, + '\\underset{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\underset{", "", "", "}", "{", "", "", "}"); }, + '\\underbrace{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\underbrace{", "", "", "}_", "{", "", "", "}"); }, + '\\color{(...)}0': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}"); }, + '\\color{(...)}{(...)}1': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color{", "", "", "}", "{", "", "", "}"); }, + '\\color(...){(...)}2': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\color", "\\", "", /^(?=\{)/, "{", "", "", "}"); }, + '\\ce{(...)}': function (input) { return mhchemParser.patterns.findObserveGroups(input, "\\ce{", "", "", "}"); }, + 'oxidation$': /^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, + 'd-oxidation$': /^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/, // 0 could be oxidation or charge + 'roman numeral': /^[IVX]+/, + '1/2$': /^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/, + 'amount': function (input) { + var match; + // e.g. 2, 0.5, 1/2, -2, n/2, +; $a$ could be added later in parsing + match = input.match(/^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/); + if (match) { + return { match_: match[0], remainder: input.substr(match[0].length) }; + } + var a = mhchemParser.patterns.findObserveGroups(input, "", "$", "$", ""); + if (a) { // e.g. $2n-1$, $-$ + match = a.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/); + if (match) { + return { match_: match[0], remainder: input.substr(match[0].length) }; + } + } + return null; + }, + 'amount2': function (input) { return this['amount'](input); }, + '(KV letters),': /^(?:[A-Z][a-z]{0,2}|i)(?=,)/, + 'formula$': function (input) { + if (input.match(/^\([a-z]+\)$/)) { return null; } // state of aggregation = no formula + var match = input.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/); + if (match) { + return { match_: match[0], remainder: input.substr(match[0].length) }; + } + return null; + }, + 'uprightEntities': /^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/, + '/': /^\s*(\/)\s*/, + '//': /^\s*(\/\/)\s*/, + '*': /^\s*[*.]\s*/ + }, + findObserveGroups: function (input, begExcl, begIncl, endIncl, endExcl, beg2Excl, beg2Incl, end2Incl, end2Excl, combine) { + /** @type {{(input: string, pattern: string | RegExp): string | string[] | null;}} */ + var _match = function (input, pattern) { + if (typeof pattern === "string") { + if (input.indexOf(pattern) !== 0) { return null; } + return pattern; + } else { + var match = input.match(pattern); + if (!match) { return null; } + return match[0]; + } + }; + /** @type {{(input: string, i: number, endChars: string | RegExp): {endMatchBegin: number, endMatchEnd: number} | null;}} */ + var _findObserveGroups = function (input, i, endChars) { + var braces = 0; + while (i < input.length) { + var a = input.charAt(i); + var match = _match(input.substr(i), endChars); + if (match !== null && braces === 0) { + return { endMatchBegin: i, endMatchEnd: i + match.length }; + } else if (a === "{") { + braces++; + } else if (a === "}") { + if (braces === 0) { + throw ["ExtraCloseMissingOpen", "Extra close brace or missing open brace"]; + } else { + braces--; + } + } + i++; + } + if (braces > 0) { + return null; + } + return null; + }; + var match = _match(input, begExcl); + if (match === null) { return null; } + input = input.substr(match.length); + match = _match(input, begIncl); + if (match === null) { return null; } + var e = _findObserveGroups(input, match.length, endIncl || endExcl); + if (e === null) { return null; } + var match1 = input.substring(0, (endIncl ? e.endMatchEnd : e.endMatchBegin)); + if (!(beg2Excl || beg2Incl)) { + return { + match_: match1, + remainder: input.substr(e.endMatchEnd) + }; + } else { + var group2 = this.findObserveGroups(input.substr(e.endMatchEnd), beg2Excl, beg2Incl, end2Incl, end2Excl); + if (group2 === null) { return null; } + /** @type {string[]} */ + var matchRet = [match1, group2.match_]; + return { + match_: (combine ? matchRet.join("") : matchRet), + remainder: group2.remainder + }; + } + }, + + // + // Matching function + // e.g. match("a", input) will look for the regexp called "a" and see if it matches + // returns null or {match_:"a", remainder:"bc"} + // + match_: function (m, input) { + var pattern = mhchemParser.patterns.patterns[m]; + if (pattern === undefined) { + throw ["MhchemBugP", "mhchem bug P. Please report. (" + m + ")"]; // Trying to use non-existing pattern + } else if (typeof pattern === "function") { + return mhchemParser.patterns.patterns[m](input); // cannot use cached var pattern here, because some pattern functions need this===mhchemParser + } else { // RegExp + var match = input.match(pattern); + if (match) { + var mm; + if (match[2]) { + mm = [ match[1], match[2] ]; + } else if (match[1]) { + mm = match[1]; + } else { + mm = match[0]; + } + return { match_: mm, remainder: input.substr(match[0].length) }; + } + return null; + } + } + }, + + // + // Generic state machine actions + // + actions: { + 'a=': function (buffer, m) { buffer.a = (buffer.a || "") + m; }, + 'b=': function (buffer, m) { buffer.b = (buffer.b || "") + m; }, + 'p=': function (buffer, m) { buffer.p = (buffer.p || "") + m; }, + 'o=': function (buffer, m) { buffer.o = (buffer.o || "") + m; }, + 'q=': function (buffer, m) { buffer.q = (buffer.q || "") + m; }, + 'd=': function (buffer, m) { buffer.d = (buffer.d || "") + m; }, + 'rm=': function (buffer, m) { buffer.rm = (buffer.rm || "") + m; }, + 'text=': function (buffer, m) { buffer.text_ = (buffer.text_ || "") + m; }, + 'insert': function (buffer, m, a) { return { type_: a }; }, + 'insert+p1': function (buffer, m, a) { return { type_: a, p1: m }; }, + 'insert+p1+p2': function (buffer, m, a) { return { type_: a, p1: m[0], p2: m[1] }; }, + 'copy': function (buffer, m) { return m; }, + 'rm': function (buffer, m) { return { type_: 'rm', p1: m || ""}; }, + 'text': function (buffer, m) { return mhchemParser.go(m, 'text'); }, + '{text}': function (buffer, m) { + var ret = [ "{" ]; + mhchemParser.concatArray(ret, mhchemParser.go(m, 'text')); + ret.push("}"); + return ret; + }, + 'tex-math': function (buffer, m) { return mhchemParser.go(m, 'tex-math'); }, + 'tex-math tight': function (buffer, m) { return mhchemParser.go(m, 'tex-math tight'); }, + 'bond': function (buffer, m, k) { return { type_: 'bond', kind_: k || m }; }, + 'color0-output': function (buffer, m) { return { type_: 'color0', color: m[0] }; }, + 'ce': function (buffer, m) { return mhchemParser.go(m); }, + '1/2': function (buffer, m) { + /** @type {ParserOutput[]} */ + var ret = []; + if (m.match(/^[+\-]/)) { + ret.push(m.substr(0, 1)); + m = m.substr(1); + } + var n = m.match(/^([0-9]+|\$[a-z]\$|[a-z])\/([0-9]+)(\$[a-z]\$|[a-z])?$/); + n[1] = n[1].replace(/\$/g, ""); + ret.push({ type_: 'frac', p1: n[1], p2: n[2] }); + if (n[3]) { + n[3] = n[3].replace(/\$/g, ""); + ret.push({ type_: 'tex-math', p1: n[3] }); + } + return ret; + }, + '9,9': function (buffer, m) { return mhchemParser.go(m, '9,9'); } + }, + // + // createTransitions + // convert { 'letter': { 'state': { action_: 'output' } } } to { 'state' => [ { pattern: 'letter', task: { action_: [{type_: 'output'}] } } ] } + // with expansion of 'a|b' to 'a' and 'b' (at 2 places) + // + createTransitions: function (o) { + var pattern, state; + /** @type {string[]} */ + var stateArray; + var i; + // + // 1. Collect all states + // + /** @type {Transitions} */ + var transitions = {}; + for (pattern in o) { + for (state in o[pattern]) { + stateArray = state.split("|"); + o[pattern][state].stateArray = stateArray; + for (i=0; i<stateArray.length; i++) { + transitions[stateArray[i]] = []; + } + } + } + // + // 2. Fill states + // + for (pattern in o) { + for (state in o[pattern]) { + stateArray = o[pattern][state].stateArray || []; + for (i=0; i<stateArray.length; i++) { + // + // 2a. Normalize actions into array: 'text=' ==> [{type_:'text='}] + // (Note to myself: Resolving the function here would be problematic. It would need .bind (for *this*) and currying (for *option*).) + // + /** @type {any} */ + var p = o[pattern][state]; + if (p.action_) { + p.action_ = [].concat(p.action_); + for (var k=0; k<p.action_.length; k++) { + if (typeof p.action_[k] === "string") { + p.action_[k] = { type_: p.action_[k] }; + } + } + } else { + p.action_ = []; + } + // + // 2.b Multi-insert + // + var patternArray = pattern.split("|"); + for (var j=0; j<patternArray.length; j++) { + if (stateArray[i] === '*') { // insert into all + for (var t in transitions) { + transitions[t].push({ pattern: patternArray[j], task: p }); + } + } else { + transitions[stateArray[i]].push({ pattern: patternArray[j], task: p }); + } + } + } + } + } + return transitions; + }, + stateMachines: {} + }; + + // + // Definition of state machines + // + mhchemParser.stateMachines = { + // + // \ce state machines + // + //#region ce + 'ce': { // main parser + transitions: mhchemParser.createTransitions({ + 'empty': { + '*': { action_: 'output' } }, + 'else': { + '0|1|2': { action_: 'beginsWithBond=false', revisit: true, toContinue: true } }, + 'oxidation$': { + '0': { action_: 'oxidation-output' } }, + 'CMT': { + 'r': { action_: 'rdt=', nextState: 'rt' }, + 'rd': { action_: 'rqt=', nextState: 'rdt' } }, + 'arrowUpDown': { + '0|1|2|as': { action_: [ 'sb=false', 'output', 'operator' ], nextState: '1' } }, + 'uprightEntities': { + '0|1|2': { action_: [ 'o=', 'output' ], nextState: '1' } }, + 'orbital': { + '0|1|2|3': { action_: 'o=', nextState: 'o' } }, + '->': { + '0|1|2|3': { action_: 'r=', nextState: 'r' }, + 'a|as': { action_: [ 'output', 'r=' ], nextState: 'r' }, + '*': { action_: [ 'output', 'r=' ], nextState: 'r' } }, + '+': { + 'o': { action_: 'd= kv', nextState: 'd' }, + 'd|D': { action_: 'd=', nextState: 'd' }, + 'q': { action_: 'd=', nextState: 'qd' }, + 'qd|qD': { action_: 'd=', nextState: 'qd' }, + 'dq': { action_: [ 'output', 'd=' ], nextState: 'd' }, + '3': { action_: [ 'sb=false', 'output', 'operator' ], nextState: '0' } }, + 'amount': { + '0|2': { action_: 'a=', nextState: 'a' } }, + 'pm-operator': { + '0|1|2|a|as': { action_: [ 'sb=false', 'output', { type_: 'operator', option: '\\pm' } ], nextState: '0' } }, + 'operator': { + '0|1|2|a|as': { action_: [ 'sb=false', 'output', 'operator' ], nextState: '0' } }, + '-$': { + 'o|q': { action_: [ 'charge or bond', 'output' ], nextState: 'qd' }, + 'd': { action_: 'd=', nextState: 'd' }, + 'D': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' }, + 'q': { action_: 'd=', nextState: 'qd' }, + 'qd': { action_: 'd=', nextState: 'qd' }, + 'qD|dq': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' } }, + '-9': { + '3|o': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '3' } }, + '- orbital overlap': { + 'o': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' }, + 'd': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' } }, + '-': { + '0|1|2': { action_: [ { type_: 'output', option: 1 }, 'beginsWithBond=true', { type_: 'bond', option: "-" } ], nextState: '3' }, + '3': { action_: { type_: 'bond', option: "-" } }, + 'a': { action_: [ 'output', { type_: 'insert', option: 'hyphen' } ], nextState: '2' }, + 'as': { action_: [ { type_: 'output', option: 2 }, { type_: 'bond', option: "-" } ], nextState: '3' }, + 'b': { action_: 'b=' }, + 'o': { action_: { type_: '- after o/d', option: false }, nextState: '2' }, + 'q': { action_: { type_: '- after o/d', option: false }, nextState: '2' }, + 'd|qd|dq': { action_: { type_: '- after o/d', option: true }, nextState: '2' }, + 'D|qD|p': { action_: [ 'output', { type_: 'bond', option: "-" } ], nextState: '3' } }, + 'amount2': { + '1|3': { action_: 'a=', nextState: 'a' } }, + 'letters': { + '0|1|2|3|a|as|b|p|bp|o': { action_: 'o=', nextState: 'o' }, + 'q|dq': { action_: ['output', 'o='], nextState: 'o' }, + 'd|D|qd|qD': { action_: 'o after d', nextState: 'o' } }, + 'digits': { + 'o': { action_: 'q=', nextState: 'q' }, + 'd|D': { action_: 'q=', nextState: 'dq' }, + 'q': { action_: [ 'output', 'o=' ], nextState: 'o' }, + 'a': { action_: 'o=', nextState: 'o' } }, + 'space A': { + 'b|p|bp': {} }, + 'space': { + 'a': { nextState: 'as' }, + '0': { action_: 'sb=false' }, + '1|2': { action_: 'sb=true' }, + 'r|rt|rd|rdt|rdq': { action_: 'output', nextState: '0' }, + '*': { action_: [ 'output', 'sb=true' ], nextState: '1'} }, + '1st-level escape': { + '1|2': { action_: [ 'output', { type_: 'insert+p1', option: '1st-level escape' } ] }, + '*': { action_: [ 'output', { type_: 'insert+p1', option: '1st-level escape' } ], nextState: '0' } }, + '[(...)]': { + 'r|rt': { action_: 'rd=', nextState: 'rd' }, + 'rd|rdt': { action_: 'rq=', nextState: 'rdq' } }, + '...': { + 'o|d|D|dq|qd|qD': { action_: [ 'output', { type_: 'bond', option: "..." } ], nextState: '3' }, + '*': { action_: [ { type_: 'output', option: 1 }, { type_: 'insert', option: 'ellipsis' } ], nextState: '1' } }, + '. |* ': { + '*': { action_: [ 'output', { type_: 'insert', option: 'addition compound' } ], nextState: '1' } }, + 'state of aggregation $': { + '*': { action_: [ 'output', 'state of aggregation' ], nextState: '1' } }, + '{[(': { + 'a|as|o': { action_: [ 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' }, + '0|1|2|3': { action_: [ 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' }, + '*': { action_: [ 'output', 'o=', 'output', 'parenthesisLevel++' ], nextState: '2' } }, + ')]}': { + '0|1|2|3|b|p|bp|o': { action_: [ 'o=', 'parenthesisLevel--' ], nextState: 'o' }, + 'a|as|d|D|q|qd|qD|dq': { action_: [ 'output', 'o=', 'parenthesisLevel--' ], nextState: 'o' } }, + ', ': { + '*': { action_: [ 'output', 'comma' ], nextState: '0' } }, + '^_': { // ^ and _ without a sensible argument + '*': { } }, + '^{(...)}|^($...$)': { + '0|1|2|as': { action_: 'b=', nextState: 'b' }, + 'p': { action_: 'b=', nextState: 'bp' }, + '3|o': { action_: 'd= kv', nextState: 'D' }, + 'q': { action_: 'd=', nextState: 'qD' }, + 'd|D|qd|qD|dq': { action_: [ 'output', 'd=' ], nextState: 'D' } }, + '^a|^\\x{}{}|^\\x{}|^\\x|\'': { + '0|1|2|as': { action_: 'b=', nextState: 'b' }, + 'p': { action_: 'b=', nextState: 'bp' }, + '3|o': { action_: 'd= kv', nextState: 'd' }, + 'q': { action_: 'd=', nextState: 'qd' }, + 'd|qd|D|qD': { action_: 'd=' }, + 'dq': { action_: [ 'output', 'd=' ], nextState: 'd' } }, + '_{(state of aggregation)}$': { + 'd|D|q|qd|qD|dq': { action_: [ 'output', 'q=' ], nextState: 'q' } }, + '_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x': { + '0|1|2|as': { action_: 'p=', nextState: 'p' }, + 'b': { action_: 'p=', nextState: 'bp' }, + '3|o': { action_: 'q=', nextState: 'q' }, + 'd|D': { action_: 'q=', nextState: 'dq' }, + 'q|qd|qD|dq': { action_: [ 'output', 'q=' ], nextState: 'q' } }, + '=<>': { + '0|1|2|3|a|as|o|q|d|D|qd|qD|dq': { action_: [ { type_: 'output', option: 2 }, 'bond' ], nextState: '3' } }, + '#': { + '0|1|2|3|a|as|o': { action_: [ { type_: 'output', option: 2 }, { type_: 'bond', option: "#" } ], nextState: '3' } }, + '{}': { + '*': { action_: { type_: 'output', option: 1 }, nextState: '1' } }, + '{...}': { + '0|1|2|3|a|as|b|p|bp': { action_: 'o=', nextState: 'o' }, + 'o|d|D|q|qd|qD|dq': { action_: [ 'output', 'o=' ], nextState: 'o' } }, + '$...$': { + 'a': { action_: 'a=' }, // 2$n$ + '0|1|2|3|as|b|p|bp|o': { action_: 'o=', nextState: 'o' }, // not 'amount' + 'as|o': { action_: 'o=' }, + 'q|d|D|qd|qD|dq': { action_: [ 'output', 'o=' ], nextState: 'o' } }, + '\\bond{(...)}': { + '*': { action_: [ { type_: 'output', option: 2 }, 'bond' ], nextState: "3" } }, + '\\frac{(...)}': { + '*': { action_: [ { type_: 'output', option: 1 }, 'frac-output' ], nextState: '3' } }, + '\\overset{(...)}': { + '*': { action_: [ { type_: 'output', option: 2 }, 'overset-output' ], nextState: '3' } }, + '\\underset{(...)}': { + '*': { action_: [ { type_: 'output', option: 2 }, 'underset-output' ], nextState: '3' } }, + '\\underbrace{(...)}': { + '*': { action_: [ { type_: 'output', option: 2 }, 'underbrace-output' ], nextState: '3' } }, + '\\color{(...)}{(...)}1|\\color(...){(...)}2': { + '*': { action_: [ { type_: 'output', option: 2 }, 'color-output' ], nextState: '3' } }, + '\\color{(...)}0': { + '*': { action_: [ { type_: 'output', option: 2 }, 'color0-output' ] } }, + '\\ce{(...)}': { + '*': { action_: [ { type_: 'output', option: 2 }, 'ce' ], nextState: '3' } }, + '\\,': { + '*': { action_: [ { type_: 'output', option: 1 }, 'copy' ], nextState: '1' } }, + '\\x{}{}|\\x{}|\\x': { + '0|1|2|3|a|as|b|p|bp|o|c0': { action_: [ 'o=', 'output' ], nextState: '3' }, + '*': { action_: ['output', 'o=', 'output' ], nextState: '3' } }, + 'others': { + '*': { action_: [ { type_: 'output', option: 1 }, 'copy' ], nextState: '3' } }, + 'else2': { + 'a': { action_: 'a to o', nextState: 'o', revisit: true }, + 'as': { action_: [ 'output', 'sb=true' ], nextState: '1', revisit: true }, + 'r|rt|rd|rdt|rdq': { action_: [ 'output' ], nextState: '0', revisit: true }, + '*': { action_: [ 'output', 'copy' ], nextState: '3' } } + }), + actions: { + 'o after d': function (buffer, m) { + var ret; + if ((buffer.d || "").match(/^[0-9]+$/)) { + var tmp = buffer.d; + buffer.d = undefined; + ret = this['output'](buffer); + buffer.b = tmp; + } else { + ret = this['output'](buffer); + } + mhchemParser.actions['o='](buffer, m); + return ret; + }, + 'd= kv': function (buffer, m) { + buffer.d = m; + buffer.dType = 'kv'; + }, + 'charge or bond': function (buffer, m) { + if (buffer['beginsWithBond']) { + /** @type {ParserOutput[]} */ + var ret = []; + mhchemParser.concatArray(ret, this['output'](buffer)); + mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-")); + return ret; + } else { + buffer.d = m; + } + }, + '- after o/d': function (buffer, m, isAfterD) { + var c1 = mhchemParser.patterns.match_('orbital', buffer.o || ""); + var c2 = mhchemParser.patterns.match_('one lowercase greek letter $', buffer.o || ""); + var c3 = mhchemParser.patterns.match_('one lowercase latin letter $', buffer.o || ""); + var c4 = mhchemParser.patterns.match_('$one lowercase latin letter$ $', buffer.o || ""); + var hyphenFollows = m==="-" && ( c1 && c1.remainder==="" || c2 || c3 || c4 ); + if (hyphenFollows && !buffer.a && !buffer.b && !buffer.p && !buffer.d && !buffer.q && !c1 && c3) { + buffer.o = '$' + buffer.o + '$'; + } + /** @type {ParserOutput[]} */ + var ret = []; + if (hyphenFollows) { + mhchemParser.concatArray(ret, this['output'](buffer)); + ret.push({ type_: 'hyphen' }); + } else { + c1 = mhchemParser.patterns.match_('digits', buffer.d || ""); + if (isAfterD && c1 && c1.remainder==='') { + mhchemParser.concatArray(ret, mhchemParser.actions['d='](buffer, m)); + mhchemParser.concatArray(ret, this['output'](buffer)); + } else { + mhchemParser.concatArray(ret, this['output'](buffer)); + mhchemParser.concatArray(ret, mhchemParser.actions['bond'](buffer, m, "-")); + } + } + return ret; + }, + 'a to o': function (buffer) { + buffer.o = buffer.a; + buffer.a = undefined; + }, + 'sb=true': function (buffer) { buffer.sb = true; }, + 'sb=false': function (buffer) { buffer.sb = false; }, + 'beginsWithBond=true': function (buffer) { buffer['beginsWithBond'] = true; }, + 'beginsWithBond=false': function (buffer) { buffer['beginsWithBond'] = false; }, + 'parenthesisLevel++': function (buffer) { buffer['parenthesisLevel']++; }, + 'parenthesisLevel--': function (buffer) { buffer['parenthesisLevel']--; }, + 'state of aggregation': function (buffer, m) { + return { type_: 'state of aggregation', p1: mhchemParser.go(m, 'o') }; + }, + 'comma': function (buffer, m) { + var a = m.replace(/\s*$/, ''); + var withSpace = (a !== m); + if (withSpace && buffer['parenthesisLevel'] === 0) { + return { type_: 'comma enumeration L', p1: a }; + } else { + return { type_: 'comma enumeration M', p1: a }; + } + }, + 'output': function (buffer, m, entityFollows) { + // entityFollows: + // undefined = if we have nothing else to output, also ignore the just read space (buffer.sb) + // 1 = an entity follows, never omit the space if there was one just read before (can only apply to state 1) + // 2 = 1 + the entity can have an amount, so output a\, instead of converting it to o (can only apply to states a|as) + /** @type {ParserOutput | ParserOutput[]} */ + var ret; + if (!buffer.r) { + ret = []; + if (!buffer.a && !buffer.b && !buffer.p && !buffer.o && !buffer.q && !buffer.d && !entityFollows) { + //ret = []; + } else { + if (buffer.sb) { + ret.push({ type_: 'entitySkip' }); + } + if (!buffer.o && !buffer.q && !buffer.d && !buffer.b && !buffer.p && entityFollows!==2) { + buffer.o = buffer.a; + buffer.a = undefined; + } else if (!buffer.o && !buffer.q && !buffer.d && (buffer.b || buffer.p)) { + buffer.o = buffer.a; + buffer.d = buffer.b; + buffer.q = buffer.p; + buffer.a = buffer.b = buffer.p = undefined; + } else { + if (buffer.o && buffer.dType==='kv' && mhchemParser.patterns.match_('d-oxidation$', buffer.d || "")) { + buffer.dType = 'oxidation'; + } else if (buffer.o && buffer.dType==='kv' && !buffer.q) { + buffer.dType = undefined; + } + } + ret.push({ + type_: 'chemfive', + a: mhchemParser.go(buffer.a, 'a'), + b: mhchemParser.go(buffer.b, 'bd'), + p: mhchemParser.go(buffer.p, 'pq'), + o: mhchemParser.go(buffer.o, 'o'), + q: mhchemParser.go(buffer.q, 'pq'), + d: mhchemParser.go(buffer.d, (buffer.dType === 'oxidation' ? 'oxidation' : 'bd')), + dType: buffer.dType + }); + } + } else { // r + /** @type {ParserOutput[]} */ + var rd; + if (buffer.rdt === 'M') { + rd = mhchemParser.go(buffer.rd, 'tex-math'); + } else if (buffer.rdt === 'T') { + rd = [ { type_: 'text', p1: buffer.rd || "" } ]; + } else { + rd = mhchemParser.go(buffer.rd); + } + /** @type {ParserOutput[]} */ + var rq; + if (buffer.rqt === 'M') { + rq = mhchemParser.go(buffer.rq, 'tex-math'); + } else if (buffer.rqt === 'T') { + rq = [ { type_: 'text', p1: buffer.rq || ""} ]; + } else { + rq = mhchemParser.go(buffer.rq); + } + ret = { + type_: 'arrow', + r: buffer.r, + rd: rd, + rq: rq + }; + } + for (var p in buffer) { + if (p !== 'parenthesisLevel' && p !== 'beginsWithBond') { + delete buffer[p]; + } + } + return ret; + }, + 'oxidation-output': function (buffer, m) { + var ret = [ "{" ]; + mhchemParser.concatArray(ret, mhchemParser.go(m, 'oxidation')); + ret.push("}"); + return ret; + }, + 'frac-output': function (buffer, m) { + return { type_: 'frac-ce', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; + }, + 'overset-output': function (buffer, m) { + return { type_: 'overset', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; + }, + 'underset-output': function (buffer, m) { + return { type_: 'underset', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; + }, + 'underbrace-output': function (buffer, m) { + return { type_: 'underbrace', p1: mhchemParser.go(m[0]), p2: mhchemParser.go(m[1]) }; + }, + 'color-output': function (buffer, m) { + return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1]) }; + }, + 'r=': function (buffer, m) { buffer.r = m; }, + 'rdt=': function (buffer, m) { buffer.rdt = m; }, + 'rd=': function (buffer, m) { buffer.rd = m; }, + 'rqt=': function (buffer, m) { buffer.rqt = m; }, + 'rq=': function (buffer, m) { buffer.rq = m; }, + 'operator': function (buffer, m, p1) { return { type_: 'operator', kind_: (p1 || m) }; } + } + }, + 'a': { + transitions: mhchemParser.createTransitions({ + 'empty': { + '*': {} }, + '1/2$': { + '0': { action_: '1/2' } }, + 'else': { + '0': { nextState: '1', revisit: true } }, + '$(...)$': { + '*': { action_: 'tex-math tight', nextState: '1' } }, + ',': { + '*': { action_: { type_: 'insert', option: 'commaDecimal' } } }, + 'else2': { + '*': { action_: 'copy' } } + }), + actions: {} + }, + 'o': { + transitions: mhchemParser.createTransitions({ + 'empty': { + '*': {} }, + '1/2$': { + '0': { action_: '1/2' } }, + 'else': { + '0': { nextState: '1', revisit: true } }, + 'letters': { + '*': { action_: 'rm' } }, + '\\ca': { + '*': { action_: { type_: 'insert', option: 'circa' } } }, + '\\x{}{}|\\x{}|\\x': { + '*': { action_: 'copy' } }, + '${(...)}$|$(...)$': { + '*': { action_: 'tex-math' } }, + '{(...)}': { + '*': { action_: '{text}' } }, + 'else2': { + '*': { action_: 'copy' } } + }), + actions: {} + }, + 'text': { + transitions: mhchemParser.createTransitions({ + 'empty': { + '*': { action_: 'output' } }, + '{...}': { + '*': { action_: 'text=' } }, + '${(...)}$|$(...)$': { + '*': { action_: 'tex-math' } }, + '\\greek': { + '*': { action_: [ 'output', 'rm' ] } }, + '\\,|\\x{}{}|\\x{}|\\x': { + '*': { action_: [ 'output', 'copy' ] } }, + 'else': { + '*': { action_: 'text=' } } + }), + actions: { + 'output': function (buffer) { + if (buffer.text_) { + /** @type {ParserOutput} */ + var ret = { type_: 'text', p1: buffer.text_ }; + for (var p in buffer) { delete buffer[p]; } + return ret; + } + } + } + }, + 'pq': { + transitions: mhchemParser.createTransitions({ + 'empty': { + '*': {} }, + 'state of aggregation $': { + '*': { action_: 'state of aggregation' } }, + 'i$': { + '0': { nextState: '!f', revisit: true } }, + '(KV letters),': { + '0': { action_: 'rm', nextState: '0' } }, + 'formula$': { + '0': { nextState: 'f', revisit: true } }, + '1/2$': { + '0': { action_: '1/2' } }, + 'else': { + '0': { nextState: '!f', revisit: true } }, + '${(...)}$|$(...)$': { + '*': { action_: 'tex-math' } }, + '{(...)}': { + '*': { action_: 'text' } }, + 'a-z': { + 'f': { action_: 'tex-math' } }, + 'letters': { + '*': { action_: 'rm' } }, + '-9.,9': { + '*': { action_: '9,9' } }, + ',': { + '*': { action_: { type_: 'insert+p1', option: 'comma enumeration S' } } }, + '\\color{(...)}{(...)}1|\\color(...){(...)}2': { + '*': { action_: 'color-output' } }, + '\\color{(...)}0': { + '*': { action_: 'color0-output' } }, + '\\ce{(...)}': { + '*': { action_: 'ce' } }, + '\\,|\\x{}{}|\\x{}|\\x': { + '*': { action_: 'copy' } }, + 'else2': { + '*': { action_: 'copy' } } + }), + actions: { + 'state of aggregation': function (buffer, m) { + return { type_: 'state of aggregation subscript', p1: mhchemParser.go(m, 'o') }; + }, + 'color-output': function (buffer, m) { + return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1], 'pq') }; + } + } + }, + 'bd': { + transitions: mhchemParser.createTransitions({ + 'empty': { + '*': {} }, + 'x$': { + '0': { nextState: '!f', revisit: true } }, + 'formula$': { + '0': { nextState: 'f', revisit: true } }, + 'else': { + '0': { nextState: '!f', revisit: true } }, + '-9.,9 no missing 0': { + '*': { action_: '9,9' } }, + '.': { + '*': { action_: { type_: 'insert', option: 'electron dot' } } }, + 'a-z': { + 'f': { action_: 'tex-math' } }, + 'x': { + '*': { action_: { type_: 'insert', option: 'KV x' } } }, + 'letters': { + '*': { action_: 'rm' } }, + '\'': { + '*': { action_: { type_: 'insert', option: 'prime' } } }, + '${(...)}$|$(...)$': { + '*': { action_: 'tex-math' } }, + '{(...)}': { + '*': { action_: 'text' } }, + '\\color{(...)}{(...)}1|\\color(...){(...)}2': { + '*': { action_: 'color-output' } }, + '\\color{(...)}0': { + '*': { action_: 'color0-output' } }, + '\\ce{(...)}': { + '*': { action_: 'ce' } }, + '\\,|\\x{}{}|\\x{}|\\x': { + '*': { action_: 'copy' } }, + 'else2': { + '*': { action_: 'copy' } } + }), + actions: { + 'color-output': function (buffer, m) { + return { type_: 'color', color1: m[0], color2: mhchemParser.go(m[1], 'bd') }; + } + } + }, + 'oxidation': { + transitions: mhchemParser.createTransitions({ + 'empty': { + '*': {} }, + 'roman numeral': { + '*': { action_: 'roman-numeral' } }, + '${(...)}$|$(...)$': { + '*': { action_: 'tex-math' } }, + 'else': { + '*': { action_: 'copy' } } + }), + actions: { + 'roman-numeral': function (buffer, m) { return { type_: 'roman numeral', p1: m || "" }; } + } + }, + 'tex-math': { + transitions: mhchemParser.createTransitions({ + 'empty': { + '*': { action_: 'output' } }, + '\\ce{(...)}': { + '*': { action_: [ 'output', 'ce' ] } }, + '{...}|\\,|\\x{}{}|\\x{}|\\x': { + '*': { action_: 'o=' } }, + 'else': { + '*': { action_: 'o=' } } + }), + actions: { + 'output': function (buffer) { + if (buffer.o) { + /** @type {ParserOutput} */ + var ret = { type_: 'tex-math', p1: buffer.o }; + for (var p in buffer) { delete buffer[p]; } + return ret; + } + } + } + }, + 'tex-math tight': { + transitions: mhchemParser.createTransitions({ + 'empty': { + '*': { action_: 'output' } }, + '\\ce{(...)}': { + '*': { action_: [ 'output', 'ce' ] } }, + '{...}|\\,|\\x{}{}|\\x{}|\\x': { + '*': { action_: 'o=' } }, + '-|+': { + '*': { action_: 'tight operator' } }, + 'else': { + '*': { action_: 'o=' } } + }), + actions: { + 'tight operator': function (buffer, m) { buffer.o = (buffer.o || "") + "{"+m+"}"; }, + 'output': function (buffer) { + if (buffer.o) { + /** @type {ParserOutput} */ + var ret = { type_: 'tex-math', p1: buffer.o }; + for (var p in buffer) { delete buffer[p]; } + return ret; + } + } + } + }, + '9,9': { + transitions: mhchemParser.createTransitions({ + 'empty': { + '*': {} }, + ',': { + '*': { action_: 'comma' } }, + 'else': { + '*': { action_: 'copy' } } + }), + actions: { + 'comma': function () { return { type_: 'commaDecimal' }; } + } + }, + //#endregion + // + // \pu state machines + // + //#region pu + 'pu': { + transitions: mhchemParser.createTransitions({ + 'empty': { + '*': { action_: 'output' } }, + 'space$': { + '*': { action_: [ 'output', 'space' ] } }, + '{[(|)]}': { + '0|a': { action_: 'copy' } }, + '(-)(9)^(-9)': { + '0': { action_: 'number^', nextState: 'a' } }, + '(-)(9.,9)(e)(99)': { + '0': { action_: 'enumber', nextState: 'a' } }, + 'space': { + '0|a': {} }, + 'pm-operator': { + '0|a': { action_: { type_: 'operator', option: '\\pm' }, nextState: '0' } }, + 'operator': { + '0|a': { action_: 'copy', nextState: '0' } }, + '//': { + 'd': { action_: 'o=', nextState: '/' } }, + '/': { + 'd': { action_: 'o=', nextState: '/' } }, + '{...}|else': { + '0|d': { action_: 'd=', nextState: 'd' }, + 'a': { action_: [ 'space', 'd=' ], nextState: 'd' }, + '/|q': { action_: 'q=', nextState: 'q' } } + }), + actions: { + 'enumber': function (buffer, m) { + /** @type {ParserOutput[]} */ + var ret = []; + if (m[0] === "+-" || m[0] === "+/-") { + ret.push("\\pm "); + } else if (m[0]) { + ret.push(m[0]); + } + if (m[1]) { // 1.2 + mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9')); + if (m[2]) { + if (m[2].match(/[,.]/)) { // 1.23456(0.01111) + mhchemParser.concatArray(ret, mhchemParser.go(m[2], 'pu-9,9')); + } else { // 1.23456(1111) - without spacings + ret.push(m[2]); + } + } + if (m[3] || m[4]) { // 1.2e7 1.2x10^7 + if (m[3] === "e" || m[4] === "*") { + ret.push({ type_: 'cdot' }); + } else { + ret.push({ type_: 'times' }); + } + } + } + if (m[5]) { // 10^7 + ret.push("10^{"+m[5]+"}"); + } + return ret; + }, + 'number^': function (buffer, m) { + /** @type {ParserOutput[]} */ + var ret = []; + if (m[0] === "+-" || m[0] === "+/-") { + ret.push("\\pm "); + } else if (m[0]) { + ret.push(m[0]); + } + mhchemParser.concatArray(ret, mhchemParser.go(m[1], 'pu-9,9')); + ret.push("^{"+m[2]+"}"); + return ret; + }, + 'operator': function (buffer, m, p1) { return { type_: 'operator', kind_: (p1 || m) }; }, + 'space': function () { return { type_: 'pu-space-1' }; }, + 'output': function (buffer) { + /** @type {ParserOutput | ParserOutput[]} */ + var ret; + var md = mhchemParser.patterns.match_('{(...)}', buffer.d || ""); + if (md && md.remainder === '') { buffer.d = md.match_; } + var mq = mhchemParser.patterns.match_('{(...)}', buffer.q || ""); + if (mq && mq.remainder === '') { buffer.q = mq.match_; } + if (buffer.d) { + buffer.d = buffer.d.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C"); + buffer.d = buffer.d.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F"); + } + if (buffer.q) { // fraction + buffer.q = buffer.q.replace(/\u00B0C|\^oC|\^{o}C/g, "{}^{\\circ}C"); + buffer.q = buffer.q.replace(/\u00B0F|\^oF|\^{o}F/g, "{}^{\\circ}F"); + var b5 = { + d: mhchemParser.go(buffer.d, 'pu'), + q: mhchemParser.go(buffer.q, 'pu') + }; + if (buffer.o === '//') { + ret = { type_: 'pu-frac', p1: b5.d, p2: b5.q }; + } else { + ret = b5.d; + if (b5.d.length > 1 || b5.q.length > 1) { + ret.push({ type_: ' / ' }); + } else { + ret.push({ type_: '/' }); + } + mhchemParser.concatArray(ret, b5.q); + } + } else { // no fraction + ret = mhchemParser.go(buffer.d, 'pu-2'); + } + for (var p in buffer) { delete buffer[p]; } + return ret; + } + } + }, + 'pu-2': { + transitions: mhchemParser.createTransitions({ + 'empty': { + '*': { action_: 'output' } }, + '*': { + '*': { action_: [ 'output', 'cdot' ], nextState: '0' } }, + '\\x': { + '*': { action_: 'rm=' } }, + 'space': { + '*': { action_: [ 'output', 'space' ], nextState: '0' } }, + '^{(...)}|^(-1)': { + '1': { action_: '^(-1)' } }, + '-9.,9': { + '0': { action_: 'rm=', nextState: '0' }, + '1': { action_: '^(-1)', nextState: '0' } }, + '{...}|else': { + '*': { action_: 'rm=', nextState: '1' } } + }), + actions: { + 'cdot': function () { return { type_: 'tight cdot' }; }, + '^(-1)': function (buffer, m) { buffer.rm += "^{"+m+"}"; }, + 'space': function () { return { type_: 'pu-space-2' }; }, + 'output': function (buffer) { + /** @type {ParserOutput | ParserOutput[]} */ + var ret = []; + if (buffer.rm) { + var mrm = mhchemParser.patterns.match_('{(...)}', buffer.rm || ""); + if (mrm && mrm.remainder === '') { + ret = mhchemParser.go(mrm.match_, 'pu'); + } else { + ret = { type_: 'rm', p1: buffer.rm }; + } + } + for (var p in buffer) { delete buffer[p]; } + return ret; + } + } + }, + 'pu-9,9': { + transitions: mhchemParser.createTransitions({ + 'empty': { + '0': { action_: 'output-0' }, + 'o': { action_: 'output-o' } }, + ',': { + '0': { action_: [ 'output-0', 'comma' ], nextState: 'o' } }, + '.': { + '0': { action_: [ 'output-0', 'copy' ], nextState: 'o' } }, + 'else': { + '*': { action_: 'text=' } } + }), + actions: { + 'comma': function () { return { type_: 'commaDecimal' }; }, + 'output-0': function (buffer) { + /** @type {ParserOutput[]} */ + var ret = []; + buffer.text_ = buffer.text_ || ""; + if (buffer.text_.length > 4) { + var a = buffer.text_.length % 3; + if (a === 0) { a = 3; } + for (var i=buffer.text_.length-3; i>0; i-=3) { + ret.push(buffer.text_.substr(i, 3)); + ret.push({ type_: '1000 separator' }); + } + ret.push(buffer.text_.substr(0, a)); + ret.reverse(); + } else { + ret.push(buffer.text_); + } + for (var p in buffer) { delete buffer[p]; } + return ret; + }, + 'output-o': function (buffer) { + /** @type {ParserOutput[]} */ + var ret = []; + buffer.text_ = buffer.text_ || ""; + if (buffer.text_.length > 4) { + var a = buffer.text_.length - 3; + for (var i=0; i<a; i+=3) { + ret.push(buffer.text_.substr(i, 3)); + ret.push({ type_: '1000 separator' }); + } + ret.push(buffer.text_.substr(i)); + } else { + ret.push(buffer.text_); + } + for (var p in buffer) { delete buffer[p]; } + return ret; + } + } + } + //#endregion + }; + + // + // texify: Take MhchemParser output and convert it to TeX + // + /** @type {Texify} */ + var texify = { + go: function (input, isInner) { // (recursive, max 4 levels) + if (!input) { return ""; } + var res = ""; + var cee = false; + for (var i=0; i < input.length; i++) { + var inputi = input[i]; + if (typeof inputi === "string") { + res += inputi; + } else { + res += texify._go2(inputi); + if (inputi.type_ === '1st-level escape') { cee = true; } + } + } + if (!isInner && !cee && res) { + res = "{" + res + "}"; + } + return res; + }, + _goInner: function (input) { + if (!input) { return input; } + return texify.go(input, true); + }, + _go2: function (buf) { + /** @type {undefined | string} */ + var res; + switch (buf.type_) { + case 'chemfive': + res = ""; + var b5 = { + a: texify._goInner(buf.a), + b: texify._goInner(buf.b), + p: texify._goInner(buf.p), + o: texify._goInner(buf.o), + q: texify._goInner(buf.q), + d: texify._goInner(buf.d) + }; + // + // a + // + if (b5.a) { + if (b5.a.match(/^[+\-]/)) { b5.a = "{"+b5.a+"}"; } + res += b5.a + "\\,"; + } + // + // b and p + // + if (b5.b || b5.p) { + res += "{\\vphantom{X}}"; + res += "^{\\hphantom{"+(b5.b||"")+"}}_{\\hphantom{"+(b5.p||"")+"}}"; + res += "{\\vphantom{X}}"; + res += "^{\\smash[t]{\\vphantom{2}}\\llap{"+(b5.b||"")+"}}"; + res += "_{\\vphantom{2}\\llap{\\smash[t]{"+(b5.p||"")+"}}}"; + } + // + // o + // + if (b5.o) { + if (b5.o.match(/^[+\-]/)) { b5.o = "{"+b5.o+"}"; } + res += b5.o; + } + // + // q and d + // + if (buf.dType === 'kv') { + if (b5.d || b5.q) { + res += "{\\vphantom{X}}"; + } + if (b5.d) { + res += "^{"+b5.d+"}"; + } + if (b5.q) { + res += "_{\\smash[t]{"+b5.q+"}}"; + } + } else if (buf.dType === 'oxidation') { + if (b5.d) { + res += "{\\vphantom{X}}"; + res += "^{"+b5.d+"}"; + } + if (b5.q) { + res += "{\\vphantom{X}}"; + res += "_{\\smash[t]{"+b5.q+"}}"; + } + } else { + if (b5.q) { + res += "{\\vphantom{X}}"; + res += "_{\\smash[t]{"+b5.q+"}}"; + } + if (b5.d) { + res += "{\\vphantom{X}}"; + res += "^{"+b5.d+"}"; + } + } + break; + case 'rm': + res = "\\mathrm{"+buf.p1+"}"; + break; + case 'text': + if (buf.p1.match(/[\^_]/)) { + buf.p1 = buf.p1.replace(" ", "~").replace("-", "\\text{-}"); + res = "\\mathrm{"+buf.p1+"}"; + } else { + res = "\\text{"+buf.p1+"}"; + } + break; + case 'roman numeral': + res = "\\mathrm{"+buf.p1+"}"; + break; + case 'state of aggregation': + res = "\\mskip2mu "+texify._goInner(buf.p1); + break; + case 'state of aggregation subscript': + res = "\\mskip1mu "+texify._goInner(buf.p1); + break; + case 'bond': + res = texify._getBond(buf.kind_); + if (!res) { + throw ["MhchemErrorBond", "mhchem Error. Unknown bond type (" + buf.kind_ + ")"]; + } + break; + case 'frac': + var c = "\\frac{" + buf.p1 + "}{" + buf.p2 + "}"; + res = "\\mathchoice{\\textstyle"+c+"}{"+c+"}{"+c+"}{"+c+"}"; + break; + case 'pu-frac': + var d = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; + res = "\\mathchoice{\\textstyle"+d+"}{"+d+"}{"+d+"}{"+d+"}"; + break; + case 'tex-math': + res = buf.p1 + " "; + break; + case 'frac-ce': + res = "\\frac{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; + break; + case 'overset': + res = "\\overset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; + break; + case 'underset': + res = "\\underset{" + texify._goInner(buf.p1) + "}{" + texify._goInner(buf.p2) + "}"; + break; + case 'underbrace': + res = "\\underbrace{" + texify._goInner(buf.p1) + "}_{" + texify._goInner(buf.p2) + "}"; + break; + case 'color': + res = "{\\color{" + buf.color1 + "}{" + texify._goInner(buf.color2) + "}}"; + break; + case 'color0': + res = "\\color{" + buf.color + "}"; + break; + case 'arrow': + var b6 = { + rd: texify._goInner(buf.rd), + rq: texify._goInner(buf.rq) + }; + var arrow = texify._getArrow(buf.r); + if (b6.rd || b6.rq) { + if (buf.r === "<=>" || buf.r === "<=>>" || buf.r === "<<=>" || buf.r === "<-->") { + // arrows that cannot stretch correctly yet, https://github.com/mathjax/MathJax/issues/1491 + arrow = "\\long"+arrow; + if (b6.rd) { arrow = "\\overset{"+b6.rd+"}{"+arrow+"}"; } + if (b6.rq) { + if (buf.r === "<-->") { + arrow = "\\underset{\\lower2mu{"+b6.rq+"}}{"+arrow+"}"; + } else { + arrow = "\\underset{\\lower6mu{"+b6.rq+"}}{"+arrow+"}"; // align with ->[][under] + } + } + arrow = " {}\\mathrel{"+arrow+"}{} "; + } else { + if (b6.rq) { arrow += "[{"+b6.rq+"}]"; } + arrow += "{"+b6.rd+"}"; + arrow = " {}\\mathrel{\\x"+arrow+"}{} "; + } + } else { + arrow = " {}\\mathrel{\\long"+arrow+"}{} "; + } + res = arrow; + break; + case 'operator': + res = texify._getOperator(buf.kind_); + break; + case '1st-level escape': + res = buf.p1+" "; // &, \\\\, \\hlin + break; + case 'space': + res = " "; + break; + case 'entitySkip': + res = "~"; + break; + case 'pu-space-1': + res = "~"; + break; + case 'pu-space-2': + res = "\\mkern3mu "; + break; + case '1000 separator': + res = "\\mkern2mu "; + break; + case 'commaDecimal': + res = "{,}"; + break; + case 'comma enumeration L': + res = "{"+buf.p1+"}\\mkern6mu "; + break; + case 'comma enumeration M': + res = "{"+buf.p1+"}\\mkern3mu "; + break; + case 'comma enumeration S': + res = "{"+buf.p1+"}\\mkern1mu "; + break; + case 'hyphen': + res = "\\text{-}"; + break; + case 'addition compound': + res = "\\,{\\cdot}\\,"; + break; + case 'electron dot': + res = "\\mkern1mu \\bullet\\mkern1mu "; + break; + case 'KV x': + res = "{\\times}"; + break; + case 'prime': + res = "\\prime "; + break; + case 'cdot': + res = "\\cdot "; + break; + case 'tight cdot': + res = "\\mkern1mu{\\cdot}\\mkern1mu "; + break; + case 'times': + res = "\\times "; + break; + case 'circa': + res = "{\\sim}"; + break; + case '^': + res = "uparrow"; + break; + case 'v': + res = "downarrow"; + break; + case 'ellipsis': + res = "\\ldots "; + break; + case '/': + res = "/"; + break; + case ' / ': + res = "\\,/\\,"; + break; + default: + assertNever(buf); + throw ["MhchemBugT", "mhchem bug T. Please report."]; // Missing texify rule or unknown MhchemParser output + } + assertString(res); + return res; + }, + _getArrow: function (a) { + switch (a) { + case "->": return "rightarrow"; + case "\u2192": return "rightarrow"; + case "\u27F6": return "rightarrow"; + case "<-": return "leftarrow"; + case "<->": return "leftrightarrow"; + case "<-->": return "leftrightarrows"; + case "<=>": return "rightleftharpoons"; + case "\u21CC": return "rightleftharpoons"; + case "<=>>": return "Rightleftharpoons"; + case "<<=>": return "Leftrightharpoons"; + default: + assertNever(a); + throw ["MhchemBugT", "mhchem bug T. Please report."]; + } + }, + _getBond: function (a) { + switch (a) { + case "-": return "{-}"; + case "1": return "{-}"; + case "=": return "{=}"; + case "2": return "{=}"; + case "#": return "{\\equiv}"; + case "3": return "{\\equiv}"; + case "~": return "{\\tripledash}"; + case "~-": return "{\\rlap{\\lower.1em{-}}\\raise.1em{\\tripledash}}"; + case "~=": return "{\\rlap{\\lower.2em{-}}\\rlap{\\raise.2em{\\tripledash}}-}"; + case "~--": return "{\\rlap{\\lower.2em{-}}\\rlap{\\raise.2em{\\tripledash}}-}"; + case "-~-": return "{\\rlap{\\lower.2em{-}}\\rlap{\\raise.2em{-}}\\tripledash}"; + case "...": return "{{\\cdot}{\\cdot}{\\cdot}}"; + case "....": return "{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}"; + case "->": return "{\\rightarrow}"; + case "<-": return "{\\leftarrow}"; + case "<": return "{<}"; + case ">": return "{>}"; + default: + assertNever(a); + throw ["MhchemBugT", "mhchem bug T. Please report."]; + } + }, + _getOperator: function (a) { + switch (a) { + case "+": return " {}+{} "; + case "-": return " {}-{} "; + case "=": return " {}={} "; + case "<": return " {}<{} "; + case ">": return " {}>{} "; + case "<<": return " {}\\ll{} "; + case ">>": return " {}\\gg{} "; + case "\\pm": return " {}\\pm{} "; + case "\\approx": return " {}\\approx{} "; + case "$\\approx$": return " {}\\approx{} "; + case "v": return " \\downarrow{} "; + case "(v)": return " \\downarrow{} "; + case "^": return " \\uparrow{} "; + case "(^)": return " \\uparrow{} "; + default: + assertNever(a); + throw ["MhchemBugT", "mhchem bug T. Please report."]; + } + } + }; + + // + // Helpers for code anaylsis + // Will show type error at calling position + // + /** @param {number} a */ + function assertNever(a) {} + /** @param {string} a */ + function assertString(a) {} + + // + // MathJax definitions + // + MathJax.Extension["TeX/mhchem"].CE = CE; + + /***************************************************************************/ + + TEX.Definitions.Add({ + macros: { + // + // Set up the macros for chemistry + // + ce: "CE", + pu: "PU", + + // + // Make these load AMSmath package (redefined below when loaded) + // + xleftrightarrow: ["Extension", "AMSmath"], + xrightleftharpoons: ["Extension", "AMSmath"], + xRightleftharpoons: ["Extension", "AMSmath"], + xLeftrightharpoons: ["Extension", "AMSmath"], + + // FIXME: These don't work well in FF NativeMML mode + longrightleftharpoons: ["Macro", "\\stackrel{\\textstyle{-}\\!\\!{\\rightharpoonup}}{\\smash{{\\leftharpoondown}\\!\\!{-}}}"], + longRightleftharpoons: ["Macro", "\\stackrel{\\textstyle{-}\\!\\!{\\rightharpoonup}}{\\smash{\\leftharpoondown}}"], + longLeftrightharpoons: ["Macro", "\\stackrel{\\textstyle\\vphantom{{-}}{\\rightharpoonup}}{\\smash{{\\leftharpoondown}\\!\\!{-}}}"], + longleftrightarrows: ["Macro", "\\raise-3mu{\\stackrel{\\longrightarrow}{\\raise2mu{\\smash{\\longleftarrow}}}}"], + + // + // Needed for \bond for the ~ forms + // Not perfectly aligned when zoomed in, but on 100% + // + tripledash: ["Macro", "\\vphantom{-}\\raise2mu{\\kern2mu\\tiny\\text{-}\\kern1mu\\text{-}\\kern1mu\\text{-}\\kern2mu}"] + } + }, null, true); + + if (!MathJax.Extension["TeX/AMSmath"]) { + TEX.Definitions.Add({ + macros: { + xrightarrow: ["Extension", "AMSmath"], + xleftarrow: ["Extension", "AMSmath"] + } + }, null, true); + } + + // + // These arrows need to wait until AMSmath is loaded + // + MathJax.Hub.Register.StartupHook("TeX AMSmath Ready", function () { + TEX.Definitions.Add({ + macros: { + // + // Some of these are hacks for now + // + xleftrightarrow: ["xArrow", 0x2194, 6, 6], + xrightleftharpoons: ["xArrow", 0x21CC, 5, 7], // FIXME: doesn't stretch in HTML-CSS output + xRightleftharpoons: ["xArrow", 0x21CC, 5, 7], // FIXME: how should this be handled? + xLeftrightharpoons: ["xArrow", 0x21CC, 5, 7] + } + }, null, true); + }); + + TEX.Parse.Augment({ + + // + // Implements \ce and friends + // + CE: function (name) { + var arg = this.GetArgument(name); + var tex = CE(arg).Parse(); + this.string = tex + this.string.substr(this.i); this.i = 0; + }, + + PU: function (name) { + var arg = this.GetArgument(name); + var tex = CE(arg).Parse('pu'); + this.string = tex + this.string.substr(this.i); this.i = 0; + } + + }); + + // + // Indicate that the extension is ready + // + MathJax.Hub.Startup.signal.Post("TeX mhchem Ready"); + +}); + +MathJax.Ajax.loadComplete("[mhchem]/mhchem.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/newcommand.js b/js/mathjax/extensions/TeX/newcommand.js new file mode 100644 index 0000000..d106811 --- /dev/null +++ b/js/mathjax/extensions/TeX/newcommand.js @@ -0,0 +1,272 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/newcommand.js + * + * Implements the \newcommand, \newenvironment and \def + * macros, and is loaded automatically when needed. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2009-2020 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. + */ + +MathJax.Extension["TeX/newcommand"] = { + version: "2.7.9" +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + + var TEX = MathJax.InputJax.TeX; + var TEXDEF = TEX.Definitions; + + TEXDEF.Add({ + macros: { + newcommand: 'NewCommand', + renewcommand: 'NewCommand', + newenvironment: 'NewEnvironment', + renewenvironment: 'NewEnvironment', + def: 'MacroDef', + 'let': 'Let' + } + },null,true); + + TEX.Parse.Augment({ + + /* + * Implement \newcommand{\name}[n][default]{...} + */ + NewCommand: function (name) { + var cs = this.trimSpaces(this.GetArgument(name)), + n = this.GetBrackets(name), + opt = this.GetBrackets(name), + def = this.GetArgument(name); + if (cs.charAt(0) === "\\") {cs = cs.substr(1)} + if (!cs.match(/^(.|[a-z]+)$/i)) { + TEX.Error(["IllegalControlSequenceName", + "Illegal control sequence name for %1",name]); + } + if (n) { + n = this.trimSpaces(n); + if (!n.match(/^[0-9]+$/)) { + TEX.Error(["IllegalParamNumber", + "Illegal number of parameters specified in %1",name]); + } + } + this.setDef(cs,['Macro',def,n,opt]); + }, + + /* + * Implement \newenvironment{name}[n][default]{begincmd}{endcmd} + */ + NewEnvironment: function (name) { + var env = this.trimSpaces(this.GetArgument(name)), + n = this.GetBrackets(name), + opt = this.GetBrackets(name), + bdef = this.GetArgument(name), + edef = this.GetArgument(name); + if (n) { + n = this.trimSpaces(n); + if (!n.match(/^[0-9]+$/)) { + TEX.Error(["IllegalParamNumber", + "Illegal number of parameters specified in %1",name]); + } + } + this.setEnv(env,['BeginEnv',[null,'EndEnv'],bdef,edef,n,opt]); + }, + + /* + * Implement \def command + */ + MacroDef: function (name) { + var cs = this.GetCSname(name), + params = this.GetTemplate(name,"\\"+cs), + def = this.GetArgument(name); + if (!(params instanceof Array)) {this.setDef(cs,['Macro',def,params])} + else {this.setDef(cs,['MacroWithTemplate',def].concat(params))} + }, + + /* + * Implements the \let command + */ + Let: function (name) { + var cs = this.GetCSname(name), macro; + var c = this.GetNext(); if (c === "=") {this.i++; c = this.GetNext()} + // + // All \let commands create entries in the macros array, but we + // have to look in the various mathchar and delimiter arrays if + // the source isn't a macro already, and attach the data to a + // macro with the proper routine to process it. + // + // A command of the form \let\cs=char produces a macro equivalent + // to \def\cs{char}, which is as close as MathJax can get for this. + // So \let\bgroup={ is possible, but doesn't work as it does in TeX. + // + if (c === "\\") { + name = this.GetCSname(name); + macro = this.csFindMacro(name); + if (!macro) { + if (TEXDEF.mathchar0mi.hasOwnProperty(name)) {macro = ["csMathchar0mi",TEXDEF.mathchar0mi[name]]} else + if (TEXDEF.mathchar0mo.hasOwnProperty(name)) {macro = ["csMathchar0mo",TEXDEF.mathchar0mo[name]]} else + if (TEXDEF.mathchar7.hasOwnProperty(name)) {macro = ["csMathchar7",TEXDEF.mathchar7[name]]} else + if (TEXDEF.delimiter.hasOwnProperty("\\"+name)) {macro = ["csDelimiter",TEXDEF.delimiter["\\"+name]]} else + return; + } + } else {macro = ["Macro",c]; this.i++} + this.setDef(cs,macro); + }, + + /* + * Get a CS name or give an error + */ + GetCSname: function (cmd) { + var c = this.GetNext(); + if (c !== "\\") { + TEX.Error(["MissingCS", + "%1 must be followed by a control sequence", cmd]) + } + var cs = this.trimSpaces(this.GetArgument(cmd)); + return cs.substr(1); + }, + + /* + * Get a \def parameter template + */ + GetTemplate: function (cmd,cs) { + var c, params = [], n = 0; + c = this.GetNext(); var i = this.i; + while (this.i < this.string.length) { + c = this.GetNext(); + if (c === '#') { + if (i !== this.i) {params[n] = this.string.substr(i,this.i-i)} + c = this.string.charAt(++this.i); + if (!c.match(/^[1-9]$/)) { + TEX.Error(["CantUseHash2", + "Illegal use of # in template for %1",cs]); + } + if (parseInt(c) != ++n) { + TEX.Error(["SequentialParam", + "Parameters for %1 must be numbered sequentially",cs]); + } + i = this.i+1; + } else if (c === '{') { + if (i !== this.i) {params[n] = this.string.substr(i,this.i-i)} + if (params.length > 0) {return [n,params]} else {return n} + } + this.i++; + } + TEX.Error(["MissingReplacementString", + "Missing replacement string for definition of %1",cmd]); + }, + + /* + * Process a macro with a parameter template + */ + MacroWithTemplate: function (name,text,n,params) { + if (n) { + var args = []; this.GetNext(); + if (params[0] && !this.MatchParam(params[0])) { + TEX.Error(["MismatchUseDef", + "Use of %1 doesn't match its definition",name]); + } + for (var i = 0; i < n; i++) {args.push(this.GetParameter(name,params[i+1]))} + text = this.SubstituteArgs(args,text); + } + this.string = this.AddArgs(text,this.string.slice(this.i)); + this.i = 0; + if (++this.macroCount > TEX.config.MAXMACROS) { + TEX.Error(["MaxMacroSub1", + "MathJax maximum macro substitution count exceeded; " + + "is there a recursive macro call?"]); + } + }, + + /* + * Process a user-defined environment + */ + BeginEnv: function (begin,bdef,edef,n,def) { + if (n) { + var args = []; + if (def != null) { + var optional = this.GetBrackets("\\begin{"+name+"}"); + args.push(optional == null ? def : optional); + } + for (var i = args.length; i < n; i++) {args.push(this.GetArgument("\\begin{"+name+"}"))} + bdef = this.SubstituteArgs(args,bdef); + edef = this.SubstituteArgs([],edef); // no args, but get errors for #n in edef + } + this.string = this.AddArgs(bdef,this.string.slice(this.i)); this.i = 0; + return begin; + }, + EndEnv: function (begin,bdef,edef,n) { + var end = "\\end{\\end\\"+begin.name+"}"; // special version of \end for after edef + this.string = this.AddArgs(edef,end+this.string.slice(this.i)); this.i = 0; + return null; + }, + + /* + * Find a single parameter delimited by a trailing template + */ + GetParameter: function (name,param) { + if (param == null) {return this.GetArgument(name)} + var i = this.i, j = 0, hasBraces = 0; + while (this.i < this.string.length) { + var c = this.string.charAt(this.i); + if (c === '{') { + if (this.i === i) {hasBraces = 1} + this.GetArgument(name); j = this.i - i; + } else if (this.MatchParam(param)) { + if (hasBraces) {i++; j -= 2} + return this.string.substr(i,j); + } else if (c === "\\") { + this.i++; j++; hasBraces = 0; + var match = this.string.substr(this.i).match(/[a-z]+|./i); + if (match) {this.i += match[0].length; j = this.i - i} + } else { + this.i++; j++; hasBraces = 0; + } + } + TEX.Error(["RunawayArgument","Runaway argument for %1?",name]); + }, + + /* + * Check if a template is at the current location. + * (The match must be exact, with no spacing differences. TeX is + * a little more forgiving than this about spaces after macro names) + */ + MatchParam: function (param) { + if (this.string.substr(this.i,param.length) !== param) {return 0} + if (param.match(/\\[a-z]+$/i) && + this.string.charAt(this.i+param.length).match(/[a-z]/i)) {return 0} + this.i += param.length; + return 1; + } + + }); + + TEX.Environment = function (name) { + TEXDEF.environment[name] = ['BeginEnv',[null,'EndEnv']].concat([].slice.call(arguments,1)); + TEXDEF.environment[name].isUser = true; + } + + MathJax.Hub.Startup.signal.Post("TeX newcommand Ready"); + +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/newcommand.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/noErrors.js b/js/mathjax/extensions/TeX/noErrors.js new file mode 100644 index 0000000..ae3f7f0 --- /dev/null +++ b/js/mathjax/extensions/TeX/noErrors.js @@ -0,0 +1,407 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/noErrors.js + * + * Prevents the TeX error messages from being displayed and shows the + * original TeX code instead. You can configure whether the dollar signs + * are shown or not for in-line math, and whether to put all the TeX on + * one line or use multiple-lines. + * + * To configure this extension, use + * + * MathJax.Hub.Config({ + * TeX: { + * noErrors: { + * inlineDelimiters: ["",""], // or ["$","$"] or ["\\(","\\)"] + * multiLine: true, // false for TeX on all one line + * style: { + * "font-size": "90%", + * "text-align": "left", + * "color": "black", + * "padding": "1px 3px", + * "border": "1px solid" + * // add any additional CSS styles that you want + * // (be sure there is no extra comma at the end of the last item) + * } + * } + * } + * }); + * + * Display-style math is always shown in multi-line format, and without + * delimiters, as it will already be set off in its own centered + * paragraph, like standard display mathematics. + * + * The default settings place the invalid TeX in a multi-line box with a + * black border. If you want it to look as though the TeX is just part of + * the paragraph, use + * + * MathJax.Hub.Config({ + * TeX: { + * noErrors: { + * inlineDelimiters: ["$","$"], // or ["",""] or ["\\(","\\)"] + * multiLine: false, + * style: { + * "font-size": "normal", + * "border": "" + * } + * } + * } + * }); + * + * You may also wish to set the font family, as the default is "serif" + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2009-2020 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 (HUB,HTML) { + var VERSION = "2.7.9"; + + var CONFIG = HUB.CombineConfig("TeX.noErrors",{ + disabled: false, // set to true to return to original error messages + multiLine: true, + inlineDelimiters: ["",""], // or use ["$","$"] or ["\\(","\\)"] + style: { + "font-size": "90%", + "text-align": "left", + "color": "black", + "padding": "1px 3px", + "border": "1px solid" + } + }); + + var NBSP = "\u00A0"; + + // + // The configuration defaults, augmented by the user settings + // + MathJax.Extension["TeX/noErrors"] = { + version: VERSION, + config: CONFIG + }; + + HUB.Register.StartupHook("TeX Jax Ready",function () { + var FORMAT = MathJax.InputJax.TeX.formatError; + + MathJax.InputJax.TeX.Augment({ + // + // Make error messages be the original TeX code + // Mark them as errors and multi-line or not, and for + // multi-line TeX, make spaces non-breakable (to get formatting right) + // + formatError: function (err,math,displaystyle,script) { + if (CONFIG.disabled) {return FORMAT.apply(this,arguments)} + var message = err.message.replace(/\n.*/,""); + HUB.signal.Post(["TeX Jax - parse error",message,math,displaystyle,script]); + var delim = CONFIG.inlineDelimiters; + var multiLine = (displaystyle || CONFIG.multiLine); + if (!displaystyle) {math = delim[0] + math + delim[1]} + if (multiLine) {math = math.replace(/ /g,NBSP)} else {math = math.replace(/\n/g," ")} + return MathJax.ElementJax.mml.merror(math).With({isError:true, multiLine: multiLine}); + } + }); + }); + + /******************************************************************* + * + * Fix HTML-CSS output + */ + + HUB.Register.StartupHook("HTML-CSS Jax Config",function () { + HUB.Config({ + "HTML-CSS": { + styles: { + ".MathJax .noError": HUB.Insert({ + "vertical-align": (HUB.Browser.isMSIE && CONFIG.multiLine ? "-2px" : "") + },CONFIG.style) + } + } + }); + }); + + HUB.Register.StartupHook("HTML-CSS Jax Ready",function () { + var MML = MathJax.ElementJax.mml; + var HTMLCSS = MathJax.OutputJax["HTML-CSS"]; + + var MATH = MML.math.prototype.toHTML, + MERROR = MML.merror.prototype.toHTML; + + // + // Override math toHTML routine so that error messages + // don't have the clipping and other unneeded overhead + // + MML.math.Augment({ + toHTML: function (span,node) { + var data = this.data[0]; + if (data && data.data[0] && data.data[0].isError) { + span.style.fontSize = ""; + span = this.HTMLcreateSpan(span); + span.bbox = data.data[0].toHTML(span).bbox; + } else { + span = MATH.apply(this,arguments); + } + return span; + } + }); + + // + // Override merror toHTML routine so that it puts out the + // TeX code in an inline-block with line breaks as in the original + // + MML.merror.Augment({ + toHTML: function (span) { + if (!this.isError) {return MERROR.apply(this,arguments)} + span = this.HTMLcreateSpan(span); span.className = "noError" + if (this.multiLine) {span.style.display = "inline-block"} + var text = this.data[0].data[0].data.join("").split(/\n/); + for (var i = 0, m = text.length; i < m; i++) { + HTMLCSS.addText(span,text[i]); + if (i !== m-1) {HTMLCSS.addElement(span,"br",{isMathJax:true})} + } + var HD = HTMLCSS.getHD(span.parentNode), W = HTMLCSS.getW(span.parentNode); + if (m > 1) { + var H = (HD.h + HD.d)/2, x = HTMLCSS.TeX.x_height/2; + span.parentNode.style.verticalAlign = HTMLCSS.Em(HD.d+(x-H)); + HD.h = x + H; HD.d = H - x; + } + span.bbox = {h: HD.h, d: HD.d, w: W, lw: 0, rw: W}; + return span; + } + }); + + }); + + /******************************************************************* + * + * Fix SVG output + */ + + HUB.Register.StartupHook("SVG Jax Config",function () { + HUB.Config({ + "SVG": { + styles: { + ".MathJax_SVG .noError": HUB.Insert({ + "vertical-align": (HUB.Browser.isMSIE && CONFIG.multiLine ? "-2px" : "") + },CONFIG.style) + } + } + }); + }); + + HUB.Register.StartupHook("SVG Jax Ready",function () { + var MML = MathJax.ElementJax.mml; + + var MATH = MML.math.prototype.toSVG, + MERROR = MML.merror.prototype.toSVG; + + // + // Override math toSVG routine so that error messages + // don't have the clipping and other unneeded overhead + // + MML.math.Augment({ + toSVG: function (span,node) { + var data = this.data[0]; + if (data && data.data[0] && data.data[0].isError) + {span = data.data[0].toSVG(span)} else {span = MATH.apply(this,arguments)} + return span; + } + }); + + // + // Override merror toSVG routine so that it puts out the + // TeX code in an inline-block with line breaks as in the original + // + MML.merror.Augment({ + toSVG: function (span) { + if (!this.isError || this.Parent().type !== "math") {return MERROR.apply(this,arguments)} + span = HTML.addElement(span,"span",{className: "noError", isMathJax:true}); + if (this.multiLine) {span.style.display = "inline-block"} + var text = this.data[0].data[0].data.join("").split(/\n/); + for (var i = 0, m = text.length; i < m; i++) { + HTML.addText(span,text[i]); + if (i !== m-1) {HTML.addElement(span,"br",{isMathJax:true})} + } + if (m > 1) { + var H = span.offsetHeight/2; + span.style.verticalAlign = (-H+(H/m))+"px"; + } + return span; + } + }); + + }); + + /******************************************************************* + * + * Fix NativeMML output + */ + + HUB.Register.StartupHook("NativeMML Jax Ready",function () { + var MML = MathJax.ElementJax.mml; + var CONFIG = MathJax.Extension["TeX/noErrors"].config; + + var MATH = MML.math.prototype.toNativeMML, + MERROR = MML.merror.prototype.toNativeMML; + + // + // Override math toNativeMML routine so that error messages + // don't get placed inside math tags. + // + MML.math.Augment({ + toNativeMML: function (span) { + var data = this.data[0]; + if (data && data.data[0] && data.data[0].isError) + {span = data.data[0].toNativeMML(span)} else {span = MATH.apply(this,arguments)} + return span; + } + }); + + // + // Override merror toNativeMML routine so that it puts out the + // TeX code in an inline-block with line breaks as in the original + // + MML.merror.Augment({ + toNativeMML: function (span) { + if (!this.isError) {return MERROR.apply(this,arguments)} + span = span.appendChild(document.createElement("span")); + var text = this.data[0].data[0].data.join("").split(/\n/); + for (var i = 0, m = text.length; i < m; i++) { + span.appendChild(document.createTextNode(text[i])); + if (i !== m-1) {span.appendChild(document.createElement("br"))} + } + if (this.multiLine) { + span.style.display = "inline-block"; + if (m > 1) {span.style.verticalAlign = "middle"} + } + for (var id in CONFIG.style) {if (CONFIG.style.hasOwnProperty(id)) { + var ID = id.replace(/-./g,function (c) {return c.charAt(1).toUpperCase()}); + span.style[ID] = CONFIG.style[id]; + }} + return span; + } + }); + + }); + + /******************************************************************* + * + * Fix PreviewHTML output + */ + + HUB.Register.StartupHook("PreviewHTML Jax Config",function () { + HUB.Config({ + PreviewHTML: { + styles: { + ".MathJax_PHTML .noError": HUB.Insert({ + "vertical-align": (HUB.Browser.isMSIE && CONFIG.multiLine ? "-2px" : "") + },CONFIG.style) + } + } + }); + }); + + HUB.Register.StartupHook("PreviewHTML Jax Ready",function () { + var MML = MathJax.ElementJax.mml; + var HTML = MathJax.HTML; + + var MERROR = MML.merror.prototype.toPreviewHTML; + + // + // Override merror toPreviewHTML routine so that it puts out the + // TeX code in an inline-block with line breaks as in the original + // + MML.merror.Augment({ + toPreviewHTML: function (span) { + if (!this.isError) return MERROR.apply(this,arguments); + span = this.PHTMLcreateSpan(span); span.className = "noError" + if (this.multiLine) span.style.display = "inline-block"; + var text = this.data[0].data[0].data.join("").split(/\n/); + for (var i = 0, m = text.length; i < m; i++) { + HTML.addText(span,text[i]); + if (i !== m-1) {HTML.addElement(span,"br",{isMathJax:true})} + } + return span; + } + }); + + }); + + /******************************************************************* + * + * Fix CommonHTML output + */ + + HUB.Register.StartupHook("CommonHTML Jax Config",function () { + HUB.Config({ + CommonHTML: { + styles: { + ".mjx-chtml .mjx-noError": HUB.Insert({ + "line-height": 1.2, + "vertical-align": (HUB.Browser.isMSIE && CONFIG.multiLine ? "-2px" : "") + },CONFIG.style) + } + } + }); + }); + + HUB.Register.StartupHook("CommonHTML Jax Ready",function () { + var MML = MathJax.ElementJax.mml; + var CHTML = MathJax.OutputJax.CommonHTML; + var HTML = MathJax.HTML; + + var MERROR = MML.merror.prototype.toCommonHTML; + + // + // Override merror toCommonHTML routine so that it puts out the + // TeX code in an inline-block with line breaks as in the original + // + MML.merror.Augment({ + toCommonHTML: function (node) { + if (!this.isError) return MERROR.apply(this,arguments); + node = CHTML.addElement(node,"mjx-noError"); + var text = this.data[0].data[0].data.join("").split(/\n/); + for (var i = 0, m = text.length; i < m; i++) { + HTML.addText(node,text[i]); + if (i !== m-1) {CHTML.addElement(node,"br",{isMathJax:true})} + } + var bbox = this.CHTML = CHTML.BBOX.zero(); + bbox.w = (node.offsetWidth)/CHTML.em; + if (m > 1) { + var H2 = 1.2*m/2; + bbox.h = H2+.25; bbox.d = H2-.25; + node.style.verticalAlign = CHTML.Em(.45-H2); + } else { + bbox.h = 1; bbox.d = .2 + 2/CHTML.em; + } + return node; + } + }); + + }); + + /*******************************************************************/ + + HUB.Startup.signal.Post("TeX noErrors Ready"); + +})(MathJax.Hub,MathJax.HTML); + + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/noErrors.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/noUndefined.js b/js/mathjax/extensions/TeX/noUndefined.js new file mode 100644 index 0000000..463a446 --- /dev/null +++ b/js/mathjax/extensions/TeX/noUndefined.js @@ -0,0 +1,74 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/noUndefined.js + * + * This causes undefined control sequences to be shown as their macro + * names rather than producing an error message. So $X_{\xxx}$ would + * display as an X with a subscript consiting of the text "\xxx". + * + * To configure this extension, use for example + * + * MathJax.Hub.Config({ + * TeX: { + * noUndefined: { + * attributes: { + * mathcolor: "red", + * mathbackground: "#FFEEEE", + * mathsize: "90%" + * } + * } + * } + * }); + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2010-2020 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. + */ + +// +// The configuration defaults, augmented by the user settings +// +MathJax.Extension["TeX/noUndefined"] = { + version: "2.7.9", + config: MathJax.Hub.CombineConfig("TeX.noUndefined",{ + disabled: false, // set to true to return to original error messages + attributes: { + mathcolor: "red" + } + }) +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + var CONFIG = MathJax.Extension["TeX/noUndefined"].config; + var MML = MathJax.ElementJax.mml; + var UNDEFINED = MathJax.InputJax.TeX.Parse.prototype.csUndefined; + + MathJax.InputJax.TeX.Parse.Augment({ + csUndefined: function (name) { + if (CONFIG.disabled) {return UNDEFINED.apply(this,arguments)} + MathJax.Hub.signal.Post(["TeX Jax - undefined control sequence",name]); + this.Push(MML.mtext(name).With(CONFIG.attributes)); + } + }); + + MathJax.Hub.Startup.signal.Post("TeX noUndefined Ready"); +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/noUndefined.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/text-macros.js b/js/mathjax/extensions/TeX/text-macros.js new file mode 100644 index 0000000..447a853 --- /dev/null +++ b/js/mathjax/extensions/TeX/text-macros.js @@ -0,0 +1,489 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/************************************************************* + * + * MathJax/extensions/TeX/text-macros.js + * + * Implements the processing of some text-mode macros inside + * \text{} and other text boxes. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2018-2020 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. + */ + +MathJax.Extension["TeX/text-macros"] = { + version: "2.7.9" +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready", function () { + var MML = MathJax.ElementJax.mml; + var TEX = MathJax.InputJax.TeX; + var TEXDEF = TEX.Definitions; + + TEX.Parse.Augment({ + // + // Replace InternalMath with parser that handles some text macros + // + InternalMath: function(text,level) { + var mml = TextParser(text, {}).Parse(); + if (level != null) { + mml = [MML.mstyle.apply(MML,mml).With({displaystyle:false, scriptlevel:level})]; + } else if (mml.length > 1) { + mml = [MML.mrow.apply(MML,mml)]; + } + return mml; + }, + + // + // Correctly skip newline as well as comment + // + Comment: function (c) { + while (this.i < this.string.length && this.string.charAt(this.i) != "\n") {this.i++} + this.i++; + }, + + // + // Correctly skip trailing space as well + // + GetCS: function () { + var CS = this.string.slice(this.i).match(/^([a-z]+|.) ?/i); + if (CS) {this.i += CS[0].length; return CS[1]} else {this.i++; return " "} + } + + }); + + // + // The text parser is a subclass of the math parser, so we can use + // some of the existing methods (like GetArgument()), and some of the + // control sequence implementations (like Macro, Spacer, etc.) + // + var TextParser = TEX.TextParser = TEX.Parse.Subclass({ + + Init: function (text, env) { + this.env = MathJax.Hub.Insert({},env); + this.stack = {env: this.env}; + this.string = text; + this.i = 0; + this.mml = []; // the accumulated MathML elements + this.text = ''; // the accumulated text so far + }, + + // + // These are the special characters in text mode + // + textSpecial: { + '\\': 'ControlSequence', + '$': 'Math', + '%': 'Comment', + '^': 'MathModeOnly', + '_': 'MathModeOnly', + '&': 'Misplaced', + '#': 'Misplaced', + '~': 'Tilde', + ' ': 'Space', + '\t': 'Space', + '\r': 'Space', + '\n': 'Space', + '\u00A0': 'Tilde', + '{': 'OpenBrace', + '}': 'CloseBrace', + '`': 'OpenQuote', + "'": 'CloseQuote' + }, + + // + // These are text-mode macros we support + // + textMacros: { + '(': 'Math', + + '$': 'SelfQuote', + '_': 'SelfQuote', + '%': 'SelfQuote', + '{': 'SelfQuote', + '}': 'SelfQuote', + ' ': 'SelfQuote', + '&': 'SelfQuote', + '#': 'SelfQuote', + '\\': 'SelfQuote', + + "'": ['Accent', '\u00B4'], + '`': ['Accent', '\u0060'], + '^': ['Accent', '^'], + '"': ['Accent', '\u00A8'], + '~': ['Accent', '~'], + '=': ['Accent', '\u00AF'], + '.': ['Accent', '\u02D9'], + 'u': ['Accent', '\u02D8'], + 'v': ['Accent', '\u02C7'], + + emph: 'Emph', + 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], + + 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], + + mathcal: 'MathModeOnly', + mathscr: 'MathModeOnly', + mathrm: 'MathModeOnly', + mathbf: 'MathModeOnly', + mathbb: 'MathModeOnly', + mathit: 'MathModeOnly', + mathfrak: 'MathModeOnly', + mathsf: 'MathModeOnly', + mathtt: 'MathModeOnly', + Bbb: ['Macro','{\\bbFont #1}',1], + textrm: ['Macro','{\\rm #1}',1], + textit: ['Macro','{\\it #1}',1], + textbf: ['Macro','{\\bf #1}',1], + textsf: ['Macro','{\\sf #1}',1], + texttt: ['Macro','{\\tt #1}',1], + + dagger: ['Insert', '\u2020'], + ddagger: ['Insert', '\u2021'], + S: ['Insert', '\u00A7'] + }, + + // + // These are the original macros that are allowed in text mode + // + useMathMacros: { + ',': true, + ':': true, + '>': true, + ';': true, + '!': true, + enspace: true, + quad: true, + qquad: true, + thinspace: true, + negthinspace: true, + + hskip: true, + hspace: true, + kern: true, + mskip: true, + mspace: true, + mkern: true, + rule: true, + Rule: true, + Space: true, + + color: true, + href: true, + unicode: true, + + ref: true, + eqref: true + }, + + // + // Look through the text for special characters and process them. + // Save any accumulated text aat the end and return the MathML + // elements produced. + // + Parse: function () { + var c; + while ((c = this.string.charAt(this.i++))) { + if (this.textSpecial.hasOwnProperty(c)) { + this[this.textSpecial[c]](c); + } else { + this.text += c; + } + } + this.SaveText(); + return this.mml; + }, + + // + // Handle a control sequence name + // If it is a text-mode macro, use it. + // Otherwise look for it in the math-mode lists + // Report an error if it is not there + // Otherwise check if it is a macro or one of the allowed control sequences + // Run the macro (with arguments if given) + // + ControlSequence: function (c) { + var cs = this.GetCS(), name = c + cs, cmd; + if (this.textMacros.hasOwnProperty(cs)) { + cmd = this.textMacros[cs]; + } else { + cmd = this.LookupCS(cs); + if (!cmd) { + this.Error(["UndefinedControlSequence","Undefined control sequence %1",name]); + } + if ((!(cmd instanceof Array) || cmd[0] !== 'Macro') && + !this.useMathMacros.hasOwnProperty(cs)) { + this.Error(["MathMacro","'%1' is only supported in math mode",name]); + } + } + if (cmd instanceof Array) { + if (!this.hasOwnProperty[cmd[0]]) this.SaveText(); + this[cmd[0]].apply(this,[name].concat(cmd.slice(1))); + } else { + if (!this.hasOwnProperty[cmd]) this.SaveText(); + this[cmd].call(this,name); + } + }, + + // + // Lookup the CS as a math-mode macro + // + LookupCS: function(cs) { + if (TEXDEF.macros.hasOwnProperty(cs)) return TEXDEF.macros[cs]; + if (TEXDEF.mathchar0mi.hasOwnProperty(cs)) return TEXDEF.mathchar0mi[cs]; + if (TEXDEF.mathchar0mo.hasOwnProperty(cs)) return TEXDEF.mathchar0mo[cs]; + if (TEXDEF.mathchar7.hasOwnProperty(cs)) return TEXDEF.mathchar7[cs]; + if (TEXDEF.delimiter.hasOwnProperty('\\'+cs)) return TEXDEF.delimiter['\\'+cs]; + return null; + }, + + // + // Handle internal math mode + // Look for the close delimiter and process the contents + // + Math: function (open) { + this.SaveText(); + var i = this.i, j; + var braces = 0, c; + while ((c = this.GetNext())) { + j = this.i++; + switch(c) { + case '\\': + var cs = this.GetCS(); + if (cs === ')') c = '\\('; + case '$': + if (braces === 0 && open === c) { + this.Push(TEX.Parse(this.string.substr(i, j-i),this.env).mml()); + return; + } + break; + + case '{': + braces++; + break; + + case '}': + if (braces == 0) { + this.Error(["ExtraCloseMissingOpen","Extra close brace or missing open brace"]); + } + braces--; + break; + } + } + this.Error(["MathNotTerminated","Math not terminated in text box"]); + }, + + // + // Character can only be used in math mode + // + MathModeOnly: function (c) { + this.Error(["MathModeOnly","'%1' allowed only in math mode",c]); + }, + + // + // Character is being used out of place + // + Misplaced: function (c) { + this.Error(["Misplaced","'%1' can not be used here",c]); + }, + + // + // Braces start new environments + // + OpenBrace: function (c) { + var env = this.env; + this.env = MathJax.Hub.Insert({}, env); + this.env.oldEnv = env; + }, + CloseBrace: function (c) { + if (this.env.oldEnv) { + this.SaveText(); + this.env = this.env.oldEnv; + } else { + this.Error(["ExtraCloseMissingOpen","Extra close brace or missing open brace"]); + } + }, + + // + // Handle open and close quotes + // + OpenQuote: function (c) { + if (this.string.charAt(this.i) === c) { + this.text += "\u201C"; + this.i++; + } else { + this.text += "\u2018" + } + }, + CloseQuote: function (c) { + if (this.string.charAt(this.i) === c) { + this.text += "\u201D"; + this.i++; + } else { + this.text += "\u2019" + } + }, + + // + // Handle non-breaking and regular spaces + // + Tilde: function (c) { + this.text += '\u00A0'; + }, + Space: function (c) { + this.text += ' '; + while (this.GetNext().match(/\s/)) this.i++; + }, + + // + // Insert the escaped characer + // + SelfQuote: function (name) { + this.text += name.substr(1); + }, + + // + // Insert a given character + // + Insert: function (name, c) { + this.text += c; + }, + + // + // Create an accented character using mover + // + Accent: function (name, c) { + this.SaveText(); + var base = this.ParseArg(name); + var accent = MML.mo(MML.chars(c)); + if (this.env.mathvariant) accent.mathvariant = this.env.mathvariant; + this.Push(MML.mover(base,accent)); + }, + + // + // Switch to/from italics + // + Emph: function (name) { + this.UseFont(name, this.env.mathvariant === '-tex-mathit' ? 'normal' : '-tex-mathit'); + }, + + // + // Use a given font on its argument + // + UseFont: function (name, variant) { + this.SaveText(); + this.Push(this.ParseTextArg(name,{mathvariant: variant})); + }, + + // + // Set a font for the rest of the text + // + SetFont: function (name, variant) { + this.SaveText(); + this.env.mathvariant = variant; + }, + + // + // Set the size to use + // + SetSize: function (name, size) { + this.SaveText(); + this.env.mathsize = size; + }, + + // + // Process the argument as text with the given environment settings + // + ParseTextArg: function (name, env) { + var text = this.GetArgument(name); + env = MathJax.Hub.Insert(MathJax.Hub.Insert({}, this.env), env); + delete env.oldEnv; + return TextParser(text, env).Parse(); + }, + + // + // Process an argument as text (overrides the math-mode version) + // + ParseArg: function (name) { + var mml = TextParser(this.GetArgument(name), this.env).Parse(); + if (mml.length === 0) return mml[0]; + return MML.mrow.apply(MML.mrow, mml); + }, + + // + // Create an mtext element with the accumulated text, if any + // and set it variant + // + SaveText: function () { + if (this.text) { + var text = MML.mtext(MML.chars(this.text)); + if (this.env.mathvariant) text.mathvariant = this.env.mathvariant; + this.Push(text); + } + this.text = ""; + }, + + // + // Save a MathML element or array, setting its size and color, if any + // + Push: function (mml) { + if (mml instanceof Array) { + if (this.env.mathsize || this.env.mathcolor) { + mml = MML.mstyle.apply(MML,mml); + if (this.env.mathsize) mml.mathsize = this.env.mathsize; + if (this.env.mathcolor) mml.mathcolor = this.env.mathcolor; + } + this.mml.push.apply(this.mml,mml); + } else { + if (this.env.mathsize && !mml.mathsize) mml.mathsize = this.env.mathsize; + if (this.env.mathcolor && !mml.mathcolor) mml.mathcolor = this.env.mathcolor; + this.mml.push(mml); + } + }, + + // + // Throw an error + // + Error: function (message) { + TEX.Error(message); + } + + }); + + MathJax.Hub.Startup.signal.Post('TeX text-macros Ready'); + +}); + +MathJax.Ajax.loadComplete('[MathJax]/extensions/TeX/text-macros.js'); +// @license-end diff --git a/js/mathjax/extensions/TeX/unicode.js b/js/mathjax/extensions/TeX/unicode.js new file mode 100644 index 0000000..0c3e50a --- /dev/null +++ b/js/mathjax/extensions/TeX/unicode.js @@ -0,0 +1,172 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/unicode.js + * + * Implements the \unicode extension to TeX to allow arbitrary unicode + * code points to be entered into the TeX file. You can specify + * the height and depth of the character (the width is determined by + * the browser), and the default font from which to take the character. + * + * Examples: + * \unicode{65} % the character 'A' + * \unicode{x41} % the character 'A' + * \unicode[.55,0.05]{x22D6} % less-than with dot, with height .55 and depth 0.05 + * \unicode[.55,0.05][Geramond]{x22D6} % same taken from Geramond font + * \unicode[Garamond]{x22D6} % same, but with default height, depth of .8,.2 + * + * Once a size and font are provided for a given code point, they need + * not be specified again in subsequent \unicode calls for that character. + * Note that a font list can be given, but Internet Explorer has a buggy + * implementation of font-family where it only looks in the first + * available font and if the glyph is not in that, it does not look at + * later fonts, but goes directly to the default font as set in the + * Internet-Options/Font panel. For this reason, the default font list is + * "STIXGeneral,'Arial Unicode MS'", so if the user has STIX fonts, the + * symbol will be taken from that (almost all the symbols are in + * STIXGeneral), otherwise Arial Unicode MS is tried. + * + * To configure the default font list, use + * + * MathJax.Hub.Config({ + * TeX: { + * unicode: { + * fonts: "STIXGeneral,'Arial Unicode MS'" + * } + * } + * }); + * + * The result of \unicode will have TeX class ORD (i.e., it will act like a + * variable). Use \mathbin, \mathrel, etc, to specify a different class. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2009-2020 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. + */ + +// +// The configuration defaults, augmented by the user settings +// +MathJax.Extension["TeX/unicode"] = { + version: "2.7.9", + unicode: {}, + config: MathJax.Hub.CombineConfig("TeX.unicode",{ + fonts: "STIXGeneral,'Arial Unicode MS'" + }) +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + var TEX = MathJax.InputJax.TeX; + var MML = MathJax.ElementJax.mml; + var UNICODE = MathJax.Extension["TeX/unicode"].unicode; + + // + // Add \unicode macro + // + TEX.Definitions.Add({macros: {unicode: 'Unicode'}},null,true); + // + // Implementation of \unicode in parser + // + TEX.Parse.Augment({ + Unicode: function(name) { + var HD = this.GetBrackets(name), font; + if (HD) { + if (HD.replace(/ /g,"").match(/^(\d+(\.\d*)?|\.\d+),(\d+(\.\d*)?|\.\d+)$/)) + {HD = HD.replace(/ /g,"").split(/,/); font = this.GetBrackets(name)} + else {font = HD; HD = null} + } + var n = this.trimSpaces(this.GetArgument(name)).replace(/^0x/,"x"); + if (!n.match(/^(x[0-9A-Fa-f]+|[0-9]+)$/)) { + TEX.Error(["BadUnicode","Argument to \\unicode must be a number"]); + } + var N = parseInt(n.match(/^x/) ? "0"+n : n); + if (!UNICODE[N]) {UNICODE[N] = [800,200,font,N]} + else if (!font) {font = UNICODE[N][2]} + if (HD) { + UNICODE[N][0] = Math.floor(HD[0]*1000); + UNICODE[N][1] = Math.floor(HD[1]*1000); + } + var variant = this.stack.env.font, def = {}; + if (font) { + UNICODE[N][2] = def.fontfamily = font.replace(/"/g,"'"); + if (variant) { + if (variant.match(/bold/)) {def.fontweight = "bold"} + if (variant.match(/italic|-mathit/)) {def.fontstyle = "italic"} + } + } else if (variant) {def.mathvariant = variant} + def.unicode = [].concat(UNICODE[N]); // make a copy + this.Push(MML.mtext(MML.entity("#"+n)).With(def)); + } + }); + + MathJax.Hub.Startup.signal.Post("TeX unicode Ready"); + +}); + +MathJax.Hub.Register.StartupHook("HTML-CSS Jax Ready",function () { + var MML = MathJax.ElementJax.mml; + var FONTS = MathJax.Extension["TeX/unicode"].config.fonts; + + // + // Override getVariant to make one that includes the font and size + // + var GETVARIANT = MML.mbase.prototype.HTMLgetVariant; + MML.mbase.Augment({ + HTMLgetVariant: function () { + var variant = GETVARIANT.apply(this,arguments); + if (variant.unicode) {delete variant.unicode; delete variant.FONTS} // clear font cache in case of restart + if (!this.unicode) {return variant} + variant.unicode = true; + if (!variant.defaultFont) { + variant = MathJax.Hub.Insert({},variant); // make a copy + variant.defaultFont = {family:FONTS}; + } + var family = this.unicode[2]; if (family) {family += ","+FONTS} else {family = FONTS} + variant.defaultFont[this.unicode[3]] = [ + this.unicode[0],this.unicode[1],500,0,500, + {isUnknown:true, isUnicode:true, font:family} + ]; + return variant; + } + }); +}); + +MathJax.Hub.Register.StartupHook("SVG Jax Ready",function () { + var MML = MathJax.ElementJax.mml; + var FONTS = MathJax.Extension["TeX/unicode"].config.fonts; + + // + // Override getVariant to make one that includes the font and size + // + var GETVARIANT = MML.mbase.prototype.SVGgetVariant; + MML.mbase.Augment({ + SVGgetVariant: function () { + var variant = GETVARIANT.call(this); + if (variant.unicode) {delete variant.unicode; delete variant.FONTS} // clear font cache in case of restart + if (!this.unicode) {return variant} + variant.unicode = true; + if (!variant.forceFamily) {variant = MathJax.Hub.Insert({},variant)} // make a copy + variant.defaultFamily = FONTS; variant.noRemap = true; + variant.h = this.unicode[0]; variant.d = this.unicode[1]; + return variant; + } + }); +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/unicode.js"); +// @license-end diff --git a/js/mathjax/extensions/TeX/verb.js b/js/mathjax/extensions/TeX/verb.js new file mode 100644 index 0000000..0f6f845 --- /dev/null +++ b/js/mathjax/extensions/TeX/verb.js @@ -0,0 +1,63 @@ +// @license magnet:?xt=urn:btih:8e4f440f4c65981c5bf93c76d35135ba5064d8b7dn=apache-2.0.txt Apache-2.0 +/* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ + +/************************************************************* + * + * MathJax/extensions/TeX/verb.js + * + * Implements the \verb|...| command for including text verbatim + * (with no processing of macros or special characters). + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2009-2020 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. + */ + +MathJax.Extension["TeX/verb"] = { + version: "2.7.9" +}; + +MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { + + var MML = MathJax.ElementJax.mml; + var TEX = MathJax.InputJax.TeX; + var TEXDEF = TEX.Definitions; + + TEXDEF.Add({macros: {verb: 'Verb'}},null,true); + + TEX.Parse.Augment({ + + /* + * Implement \verb|...| + */ + Verb: function (name) { + var c = this.GetNext(); var start = ++this.i; + if (c == "" ) {TEX.Error(["MissingArgFor","Missing argument for %1",name])} + while (this.i < this.string.length && this.string.charAt(this.i) != c) {this.i++} + if (this.i == this.string.length) + {TEX.Error(["NoClosingDelim","Can't find closing delimiter for %1", name])} + var text = this.string.slice(start,this.i).replace(/ /g,"\u00A0"); this.i++; + this.Push(MML.mtext(text).With({mathvariant:MML.VARIANT.MONOSPACE})); + } + + }); + + MathJax.Hub.Startup.signal.Post("TeX verb Ready"); + +}); + +MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/verb.js"); +// @license-end |