AMSmath.js (23992B)
1 /* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 4 /************************************************************* 5 * 6 * MathJax/extensions/TeX/AMSmath.js 7 * 8 * Implements AMS math environments and macros. 9 * 10 * --------------------------------------------------------------------- 11 * 12 * Copyright (c) 2009-2015 The MathJax Consortium 13 * 14 * Licensed under the Apache License, Version 2.0 (the "License"); 15 * you may not use this file except in compliance with the License. 16 * You may obtain a copy of the License at 17 * 18 * http://www.apache.org/licenses/LICENSE-2.0 19 * 20 * Unless required by applicable law or agreed to in writing, software 21 * distributed under the License is distributed on an "AS IS" BASIS, 22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 * See the License for the specific language governing permissions and 24 * limitations under the License. 25 */ 26 27 MathJax.Extension["TeX/AMSmath"] = { 28 version: "2.6.1", 29 30 number: 0, // current equation number 31 startNumber: 0, // current starting equation number (for when equation is restarted) 32 IDs: {}, // IDs used in previous equations 33 eqIDs: {}, // IDs used in this equation 34 labels: {}, // the set of labels 35 eqlabels: {}, // labels in the current equation 36 refs: [] // array of jax with unresolved references 37 }; 38 39 MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () { 40 41 var MML = MathJax.ElementJax.mml, 42 TEX = MathJax.InputJax.TeX, 43 AMS = MathJax.Extension["TeX/AMSmath"]; 44 45 var TEXDEF = TEX.Definitions, 46 STACKITEM = TEX.Stack.Item, 47 CONFIG = TEX.config.equationNumbers; 48 49 var COLS = function (W) { 50 var WW = []; 51 for (var i = 0, m = W.length; i < m; i++) 52 {WW[i] = TEX.Parse.prototype.Em(W[i])} 53 return WW.join(" "); 54 }; 55 56 /******************************************************************************/ 57 58 TEXDEF.Add({ 59 mathchar0mo: { 60 iiiint: ['2A0C',{texClass: MML.TEXCLASS.OP}] 61 }, 62 63 macros: { 64 mathring: ['Accent','2DA'], // or 0x30A 65 66 nobreakspace: 'Tilde', 67 negmedspace: ['Spacer',MML.LENGTH.NEGATIVEMEDIUMMATHSPACE], 68 negthickspace: ['Spacer',MML.LENGTH.NEGATIVETHICKMATHSPACE], 69 70 // intI: ['Macro','\\mathchoice{\\!}{}{}{}\\!\\!\\int'], 71 // iint: ['MultiIntegral','\\int\\intI'], // now in core TeX input jax 72 // iiint: ['MultiIntegral','\\int\\intI\\intI'], // now in core TeX input jax 73 // iiiint: ['MultiIntegral','\\int\\intI\\intI\\intI'], // now in mathchar0mo above 74 idotsint: ['MultiIntegral','\\int\\cdots\\int'], 75 76 // dddot: ['Macro','\\mathop{#1}\\limits^{\\textstyle \\mathord{.}\\mathord{.}\\mathord{.}}',1], 77 // ddddot: ['Macro','\\mathop{#1}\\limits^{\\textstyle \\mathord{.}\\mathord{.}\\mathord{.}\\mathord{.}}',1], 78 dddot: ['Accent','20DB'], 79 ddddot: ['Accent','20DC'], 80 81 sideset: ['Macro','\\mathop{\\mathop{\\rlap{\\phantom{#3}}}\\nolimits#1\\!\\mathop{#3}\\nolimits#2}',3], 82 83 boxed: ['Macro','\\fbox{$\\displaystyle{#1}$}',1], 84 85 tag: 'HandleTag', 86 notag: 'HandleNoTag', 87 label: 'HandleLabel', 88 ref: 'HandleRef', 89 eqref: ['HandleRef',true], 90 91 substack: ['Macro','\\begin{subarray}{c}#1\\end{subarray}',1], 92 93 injlim: ['NamedOp','inj lim'], 94 projlim: ['NamedOp','proj lim'], 95 varliminf: ['Macro','\\mathop{\\underline{\\mmlToken{mi}{lim}}}'], 96 varlimsup: ['Macro','\\mathop{\\overline{\\mmlToken{mi}{lim}}}'], 97 varinjlim: ['Macro','\\mathop{\\underrightarrow{\\mmlToken{mi}{lim}}}'], 98 varprojlim: ['Macro','\\mathop{\\underleftarrow{\\mmlToken{mi}{lim}}}'], 99 100 DeclareMathOperator: 'HandleDeclareOp', 101 operatorname: 'HandleOperatorName', 102 SkipLimits: 'SkipLimits', 103 104 genfrac: 'Genfrac', 105 frac: ['Genfrac',"","","",""], 106 tfrac: ['Genfrac',"","","",1], 107 dfrac: ['Genfrac',"","","",0], 108 binom: ['Genfrac',"(",")","0",""], 109 tbinom: ['Genfrac',"(",")","0",1], 110 dbinom: ['Genfrac',"(",")","0",0], 111 112 cfrac: 'CFrac', 113 114 shoveleft: ['HandleShove',MML.ALIGN.LEFT], 115 shoveright: ['HandleShove',MML.ALIGN.RIGHT], 116 117 xrightarrow: ['xArrow',0x2192,5,6], 118 xleftarrow: ['xArrow',0x2190,7,3] 119 }, 120 121 environment: { 122 align: ['AMSarray',null,true,true, 'rlrlrlrlrlrl',COLS([0,2,0,2,0,2,0,2,0,2,0])], 123 'align*': ['AMSarray',null,false,true, 'rlrlrlrlrlrl',COLS([0,2,0,2,0,2,0,2,0,2,0])], 124 multline: ['Multline',null,true], 125 'multline*': ['Multline',null,false], 126 split: ['AMSarray',null,false,false,'rl',COLS([0])], 127 gather: ['AMSarray',null,true,true, 'c'], 128 'gather*': ['AMSarray',null,false,true, 'c'], 129 130 alignat: ['AlignAt',null,true,true], 131 'alignat*': ['AlignAt',null,false,true], 132 alignedat: ['AlignAt',null,false,false], 133 134 aligned: ['AlignedAMSArray',null,null,null,'rlrlrlrlrlrl',COLS([0,2,0,2,0,2,0,2,0,2,0]),".5em",'D'], 135 gathered: ['AlignedAMSArray',null,null,null,'c',null,".5em",'D'], 136 137 subarray: ['Array',null,null,null,null,COLS([0]),"0.1em",'S',1], 138 smallmatrix: ['Array',null,null,null,'c',COLS([1/3]),".2em",'S',1], 139 140 'equation': ['EquationBegin','Equation',true], 141 'equation*': ['EquationBegin','EquationStar',false], 142 143 eqnarray: ['AMSarray',null,true,true, 'rcl',"0 "+MML.LENGTH.THICKMATHSPACE,".5em"], 144 'eqnarray*': ['AMSarray',null,false,true,'rcl',"0 "+MML.LENGTH.THICKMATHSPACE,".5em"] 145 }, 146 147 delimiter: { 148 '\\lvert': ['2223',{texClass:MML.TEXCLASS.OPEN}], 149 '\\rvert': ['2223',{texClass:MML.TEXCLASS.CLOSE}], 150 '\\lVert': ['2225',{texClass:MML.TEXCLASS.OPEN}], 151 '\\rVert': ['2225',{texClass:MML.TEXCLASS.CLOSE}] 152 } 153 },null,true); 154 155 156 /******************************************************************************/ 157 158 TEX.Parse.Augment({ 159 160 /* 161 * Add the tag to the environment (to be added to the table row later) 162 */ 163 HandleTag: function (name) { 164 var star = this.GetStar(); 165 var arg = this.trimSpaces(this.GetArgument(name)), tag = arg; 166 if (!star) {arg = CONFIG.formatTag(arg)} 167 var global = this.stack.global; global.tagID = tag; 168 if (global.notags) { 169 TEX.Error(["CommandNotAllowedInEnv", 170 "%1 not allowed in %2 environment", 171 name,global.notags] 172 ); 173 } 174 if (global.tag) {TEX.Error(["MultipleCommand","Multiple %1",name])} 175 global.tag = MML.mtd.apply(MML,this.InternalMath(arg)).With({id:CONFIG.formatID(tag)}); 176 }, 177 HandleNoTag: function (name) { 178 if (this.stack.global.tag) {delete this.stack.global.tag} 179 this.stack.global.notag = true; // prevent auto-tagging 180 }, 181 182 /* 183 * Record a label name for a tag 184 */ 185 HandleLabel: function (name) { 186 var global = this.stack.global, label = this.GetArgument(name); 187 if (label === "") return; 188 if (!AMS.refUpdate) { 189 if (global.label) {TEX.Error(["MultipleCommand","Multiple %1",name])} 190 global.label = label; 191 if (AMS.labels[label] || AMS.eqlabels[label]) 192 {TEX.Error(["MultipleLabel","Label '%1' multiply defined",label])} 193 AMS.eqlabels[label] = {tag:"???", id:""}; // will be replaced by tag value later 194 } 195 }, 196 197 /* 198 * Handle a label reference 199 */ 200 HandleRef: function (name,eqref) { 201 var label = this.GetArgument(name); 202 var ref = AMS.labels[label] || AMS.eqlabels[label]; 203 if (!ref) {ref = {tag:"???",id:""}; AMS.badref = !AMS.refUpdate} 204 var tag = ref.tag; if (eqref) {tag = CONFIG.formatTag(tag)} 205 this.Push(MML.mrow.apply(MML,this.InternalMath(tag)).With({ 206 href:CONFIG.formatURL(ref.id), "class":"MathJax_ref" 207 })); 208 }, 209 210 /* 211 * Handle \DeclareMathOperator 212 */ 213 HandleDeclareOp: function (name) { 214 var limits = (this.GetStar() ? "" : "\\nolimits\\SkipLimits"); 215 var cs = this.trimSpaces(this.GetArgument(name)); 216 if (cs.charAt(0) == "\\") {cs = cs.substr(1)} 217 var op = this.GetArgument(name); 218 op = op.replace(/\*/g,'\\text{*}').replace(/-/g,'\\text{-}'); 219 TEX.Definitions.macros[cs] = ['Macro','\\mathop{\\rm '+op+'}'+limits]; 220 }, 221 222 HandleOperatorName: function (name) { 223 var limits = (this.GetStar() ? "" : "\\nolimits\\SkipLimits"); 224 var op = this.trimSpaces(this.GetArgument(name)); 225 op = op.replace(/\*/g,'\\text{*}').replace(/-/g,'\\text{-}'); 226 this.string = '\\mathop{\\rm '+op+'}'+limits+" "+this.string.slice(this.i); 227 this.i = 0; 228 }, 229 230 SkipLimits: function (name) { 231 var c = this.GetNext(), i = this.i; 232 if (c === "\\" && ++this.i && this.GetCS() !== "limits") this.i = i; 233 }, 234 235 /* 236 * Record presence of \shoveleft and \shoveright 237 */ 238 HandleShove: function (name,shove) { 239 var top = this.stack.Top(); 240 if (top.type !== "multline" || top.data.length) { 241 TEX.Error(["CommandAtTheBeginingOfLine", 242 "%1 must come at the beginning of the line",name]); 243 } 244 top.data.shove = shove; 245 }, 246 247 /* 248 * Handle \cfrac 249 */ 250 CFrac: function (name) { 251 var lr = this.trimSpaces(this.GetBrackets(name,"")), 252 num = this.GetArgument(name), 253 den = this.GetArgument(name); 254 var frac = MML.mfrac(TEX.Parse('\\strut\\textstyle{'+num+'}',this.stack.env).mml(), 255 TEX.Parse('\\strut\\textstyle{'+den+'}',this.stack.env).mml()); 256 lr = ({l:MML.ALIGN.LEFT, r:MML.ALIGN.RIGHT,"":""})[lr]; 257 if (lr == null) 258 {TEX.Error(["IllegalAlign","Illegal alignment specified in %1",name])} 259 if (lr) {frac.numalign = frac.denomalign = lr} 260 this.Push(frac); 261 }, 262 263 /* 264 * Implement AMS generalized fraction 265 */ 266 Genfrac: function (name,left,right,thick,style) { 267 if (left == null) {left = this.GetDelimiterArg(name)} 268 if (right == null) {right = this.GetDelimiterArg(name)} 269 if (thick == null) {thick = this.GetArgument(name)} 270 if (style == null) {style = this.trimSpaces(this.GetArgument(name))} 271 var num = this.ParseArg(name); 272 var den = this.ParseArg(name); 273 var frac = MML.mfrac(num,den); 274 if (thick !== "") {frac.linethickness = thick} 275 if (left || right) {frac = TEX.fixedFence(left,frac.With({texWithDelims:true}),right)} 276 if (style !== "") { 277 var STYLE = (["D","T","S","SS"])[style]; 278 if (STYLE == null) 279 {TEX.Error(["BadMathStyleFor","Bad math style for %1",name])} 280 frac = MML.mstyle(frac); 281 if (STYLE === "D") {frac.displaystyle = true; frac.scriptlevel = 0} 282 else {frac.displaystyle = false; frac.scriptlevel = style - 1} 283 } 284 this.Push(frac); 285 }, 286 287 /* 288 * Implements multline environment (mostly handled through STACKITEM below) 289 */ 290 Multline: function (begin,numbered) { 291 this.Push(begin); this.checkEqnEnv(); 292 return STACKITEM.multline(numbered,this.stack).With({ 293 arraydef: { 294 displaystyle: true, 295 rowspacing: ".5em", 296 width: TEX.config.MultLineWidth, columnwidth:"100%", 297 side: TEX.config.TagSide, 298 minlabelspacing: TEX.config.TagIndent 299 } 300 }); 301 }, 302 303 /* 304 * Handle AMS aligned environments 305 */ 306 AMSarray: function (begin,numbered,taggable,align,spacing) { 307 this.Push(begin); if (taggable) {this.checkEqnEnv()} 308 align = align.replace(/[^clr]/g,'').split('').join(' '); 309 align = align.replace(/l/g,'left').replace(/r/g,'right').replace(/c/g,'center'); 310 return STACKITEM.AMSarray(begin.name,numbered,taggable,this.stack).With({ 311 arraydef: { 312 displaystyle: true, 313 rowspacing: ".5em", 314 columnalign: align, 315 columnspacing: (spacing||"1em"), 316 rowspacing: "3pt", 317 side: TEX.config.TagSide, 318 minlabelspacing: TEX.config.TagIndent 319 } 320 }); 321 }, 322 323 AlignedAMSArray: function (begin) { 324 var align = this.GetBrackets("\\begin{"+begin.name+"}"); 325 return this.setArrayAlign(this.AMSarray.apply(this,arguments),align); 326 }, 327 328 /* 329 * Handle alignat environments 330 */ 331 AlignAt: function (begin,numbered,taggable) { 332 var n, valign, align = "", spacing = []; 333 if (!taggable) {valign = this.GetBrackets("\\begin{"+begin.name+"}")} 334 n = this.GetArgument("\\begin{"+begin.name+"}"); 335 if (n.match(/[^0-9]/)) { 336 TEX.Error(["PositiveIntegerArg","Argument to %1 must me a positive integer", 337 "\\begin{"+begin.name+"}"]); 338 } 339 while (n > 0) {align += "rl"; spacing.push("0em 0em"); n--} 340 spacing = spacing.join(" "); 341 if (taggable) {return this.AMSarray(begin,numbered,taggable,align,spacing)} 342 var array = this.AMSarray(begin,numbered,taggable,align,spacing); 343 return this.setArrayAlign(array,valign); 344 }, 345 346 /* 347 * Handle equation environment 348 */ 349 EquationBegin: function (begin,force) { 350 this.checkEqnEnv(); 351 this.stack.global.forcetag = (force && CONFIG.autoNumber !== "none"); 352 return begin; 353 }, 354 EquationStar: function (begin,row) { 355 this.stack.global.tagged = true; // prevent automatic tagging 356 return row; 357 }, 358 359 /* 360 * Check for bad nesting of equation environments 361 */ 362 checkEqnEnv: function () { 363 if (this.stack.global.eqnenv) 364 {TEX.Error(["ErroneousNestingEq","Erroneous nesting of equation structures"])} 365 this.stack.global.eqnenv = true; 366 }, 367 368 /* 369 * Handle multiple integrals (make a mathop if followed by limits) 370 */ 371 MultiIntegral: function (name,integral) { 372 var next = this.GetNext(); 373 if (next === "\\") { 374 var i = this.i; next = this.GetArgument(name); this.i = i; 375 if (next === "\\limits") { 376 if (name === "\\idotsint") {integral = "\\!\\!\\mathop{\\,\\,"+integral+"}"} 377 else {integral = "\\!\\!\\!\\mathop{\\,\\,\\,"+integral+"}"} 378 } 379 } 380 this.string = integral + " " + this.string.slice(this.i); 381 this.i = 0; 382 }, 383 384 /* 385 * Handle stretchable arrows 386 */ 387 xArrow: function (name,chr,l,r) { 388 var def = {width: "+"+(l+r)+"mu", lspace: l+"mu"}; 389 var bot = this.GetBrackets(name), 390 top = this.ParseArg(name); 391 var arrow = MML.mo(MML.chars(String.fromCharCode(chr))).With({ 392 stretchy: true, texClass: MML.TEXCLASS.REL 393 }); 394 var mml = MML.munderover(arrow); 395 mml.SetData(mml.over,MML.mpadded(top).With(def).With({voffset:".15em"})); 396 if (bot) { 397 bot = TEX.Parse(bot,this.stack.env).mml() 398 mml.SetData(mml.under,MML.mpadded(bot).With(def).With({voffset:"-.24em"})); 399 } 400 this.Push(mml.With({subsupOK:true})); 401 }, 402 403 /* 404 * Get a delimiter or empty argument 405 */ 406 GetDelimiterArg: function (name) { 407 var c = this.trimSpaces(this.GetArgument(name)); 408 if (c == "") return null; 409 if (c in TEXDEF.delimiter) return c; 410 TEX.Error(["MissingOrUnrecognizedDelim","Missing or unrecognized delimiter for %1",name]); 411 }, 412 413 /* 414 * Get a star following a control sequence name, if any 415 */ 416 GetStar: function () { 417 var star = (this.GetNext() === "*"); 418 if (star) {this.i++} 419 return star; 420 } 421 422 }); 423 424 /******************************************************************************/ 425 426 STACKITEM.Augment({ 427 /* 428 * Increment equation number and form tag mtd element 429 */ 430 autoTag: function () { 431 var global = this.global; 432 if (!global.notag) { 433 AMS.number++; global.tagID = CONFIG.formatNumber(AMS.number.toString()); 434 var mml = TEX.Parse("\\text{"+CONFIG.formatTag(global.tagID)+"}",{}).mml(); 435 global.tag = MML.mtd(mml).With({id:CONFIG.formatID(global.tagID)}); 436 } 437 }, 438 439 /* 440 * Get the tag and record the label, if any 441 */ 442 getTag: function () { 443 var global = this.global, tag = global.tag; global.tagged = true; 444 if (global.label) { 445 if (CONFIG.useLabelIds) {tag.id = CONFIG.formatID(global.label)} 446 AMS.eqlabels[global.label] = {tag:global.tagID, id:tag.id}; 447 } 448 // 449 // Check for repeated ID's (either in the document or as 450 // a previous tag) and find a unique related one. (#240) 451 // 452 if (document.getElementById(tag.id) || AMS.IDs[tag.id] || AMS.eqIDs[tag.id]) { 453 var i = 0, ID; 454 do {i++; ID = tag.id+"_"+i} 455 while (document.getElementById(ID) || AMS.IDs[ID] || AMS.eqIDs[ID]); 456 tag.id = ID; if (global.label) {AMS.eqlabels[global.label].id = ID} 457 } 458 AMS.eqIDs[tag.id] = 1; 459 this.clearTag(); 460 return tag; 461 }, 462 clearTag: function () { 463 var global = this.global; 464 delete global.tag; delete global.tagID; delete global.label; 465 }, 466 467 /* 468 * If the initial child, skipping any initial space or 469 * empty braces (TeXAtom with child being an empty inferred row), 470 * is an <mo>, preceed it by an empty <mi> to force the <mo> to 471 * be infix. 472 */ 473 fixInitialMO: function (data) { 474 for (var i = 0, m = data.length; i < m; i++) { 475 if (data[i] && (data[i].type !== "mspace" && 476 (data[i].type !== "texatom" || (data[i].data[0] && data[i].data[0].data.length)))) { 477 if (data[i].isEmbellished()) data.unshift(MML.mi()); 478 break; 479 } 480 } 481 } 482 }); 483 484 /* 485 * Implement multline environment via a STACKITEM 486 */ 487 STACKITEM.multline = STACKITEM.array.Subclass({ 488 type: "multline", 489 Init: function (numbered,stack) { 490 this.SUPER(arguments).Init.apply(this); 491 this.numbered = (numbered && CONFIG.autoNumber !== "none"); 492 this.save = {notag: stack.global.notag}; 493 stack.global.tagged = !numbered && !stack.global.forcetag; // prevent automatic tagging in starred environments 494 }, 495 EndEntry: function () { 496 if (this.table.length) {this.fixInitialMO(this.data)} 497 var mtd = MML.mtd.apply(MML,this.data); 498 if (this.data.shove) {mtd.columnalign = this.data.shove} 499 this.row.push(mtd); 500 this.data = []; 501 }, 502 EndRow: function () { 503 if (this.row.length != 1) { 504 TEX.Error(["MultlineRowsOneCol", 505 "The rows within the %1 environment must have exactly one column", 506 "multline"]); 507 } 508 this.table.push(this.row); this.row = []; 509 }, 510 EndTable: function () { 511 this.SUPER(arguments).EndTable.call(this); 512 if (this.table.length) { 513 var m = this.table.length-1, i, label = -1; 514 if (!this.table[0][0].columnalign) {this.table[0][0].columnalign = MML.ALIGN.LEFT} 515 if (!this.table[m][0].columnalign) {this.table[m][0].columnalign = MML.ALIGN.RIGHT} 516 if (!this.global.tag && this.numbered) {this.autoTag()} 517 if (this.global.tag && !this.global.notags) { 518 label = (this.arraydef.side === "left" ? 0 : this.table.length - 1); 519 this.table[label] = [this.getTag()].concat(this.table[label]); 520 } 521 for (i = 0, m = this.table.length; i < m; i++) { 522 var mtr = (i === label ? MML.mlabeledtr : MML.mtr); 523 this.table[i] = mtr.apply(MML,this.table[i]); 524 } 525 } 526 this.global.notag = this.save.notag; 527 } 528 }); 529 530 /* 531 * Save data about numbering and taging equations, and add 532 * tags at the ends of rows. 533 */ 534 STACKITEM.AMSarray = STACKITEM.array.Subclass({ 535 type: "AMSarray", 536 Init: function (name,numbered,taggable,stack) { 537 this.SUPER(arguments).Init.apply(this); 538 this.numbered = (numbered && CONFIG.autoNumber !== "none"); 539 this.save = {notags: stack.global.notags, notag: stack.global.notag}; 540 stack.global.notags = (taggable ? null : name); 541 stack.global.tagged = !numbered && !stack.global.forcetag; // prevent automatic tagging in starred environments 542 }, 543 EndEntry: function () { 544 if (this.row.length) {this.fixInitialMO(this.data)} 545 this.row.push(MML.mtd.apply(MML,this.data)); 546 this.data = []; 547 }, 548 EndRow: function () { 549 var mtr = MML.mtr; 550 if (!this.global.tag && this.numbered) {this.autoTag()} 551 if (this.global.tag && !this.global.notags) { 552 this.row = [this.getTag()].concat(this.row); 553 mtr = MML.mlabeledtr; 554 } else {this.clearTag()} 555 if (this.numbered) {delete this.global.notag} 556 this.table.push(mtr.apply(MML,this.row)); this.row = []; 557 }, 558 EndTable: function () { 559 this.SUPER(arguments).EndTable.call(this); 560 this.global.notags = this.save.notags; 561 this.global.notag = this.save.notag; 562 } 563 }); 564 565 // 566 // Look for \tag on a formula and make an mtable to include it 567 // 568 STACKITEM.start.Augment({ 569 oldCheckItem: STACKITEM.start.prototype.checkItem, 570 checkItem: function (item) { 571 if (item.type === "stop") { 572 var mml = this.mmlData(), global = this.global; 573 if (AMS.display && !global.tag && !global.tagged && !global.isInner && 574 (CONFIG.autoNumber === "all" || global.forcetag)) {this.autoTag()} 575 if (global.tag) { 576 var row = [this.getTag(),MML.mtd(mml)]; 577 var def = { 578 side: TEX.config.TagSide, 579 minlabelspacing: TEX.config.TagIndent, 580 displaystyle: "inherit" // replaced by TeX input jax Translate() function with actual value 581 }; 582 mml = MML.mtable(MML.mlabeledtr.apply(MML,row)).With(def); 583 } 584 return STACKITEM.mml(mml); 585 } 586 return this.oldCheckItem.call(this,item); 587 } 588 }); 589 590 /******************************************************************************/ 591 592 /* 593 * Add pre- and post-filters to handle the equation number maintainance. 594 */ 595 TEX.prefilterHooks.Add(function (data) { 596 AMS.display = data.display; 597 AMS.number = AMS.startNumber; // reset equation numbers (in case the equation restarted) 598 AMS.eqlabels = AMS.eqIDs = {}; AMS.badref = false; 599 if (AMS.refUpdate) {AMS.number = data.script.MathJax.startNumber} 600 }); 601 TEX.postfilterHooks.Add(function (data) { 602 data.script.MathJax.startNumber = AMS.startNumber; 603 AMS.startNumber = AMS.number; // equation numbers for next equation 604 MathJax.Hub.Insert(AMS.IDs,AMS.eqIDs); // save IDs from this equation 605 MathJax.Hub.Insert(AMS.labels,AMS.eqlabels); // save labels from this equation 606 if (AMS.badref && !data.math.texError) {AMS.refs.push(data.script)} // reprocess later 607 },100); 608 609 MathJax.Hub.Register.MessageHook("Begin Math Input",function () { 610 AMS.refs = []; // array of jax with bad references 611 AMS.refUpdate = false; 612 }); 613 MathJax.Hub.Register.MessageHook("End Math Input",function (message) { 614 if (AMS.refs.length) { 615 AMS.refUpdate = true; 616 for (var i = 0, m = AMS.refs.length; i < m; i++) 617 {AMS.refs[i].MathJax.state = MathJax.ElementJax.STATE.UPDATE} 618 return MathJax.Hub.processInput({ 619 scripts:AMS.refs, 620 start: new Date().getTime(), 621 i:0, j:0, jax:{}, jaxIDs:[] 622 }); 623 } 624 return null; 625 }); 626 627 // 628 // Clear the equation numbers and labels 629 // 630 TEX.resetEquationNumbers = function (n,keepLabels) { 631 AMS.startNumber = (n || 0); 632 if (!keepLabels) {AMS.labels = AMS.IDs = {}} 633 } 634 635 /******************************************************************************/ 636 637 MathJax.Hub.Startup.signal.Post("TeX AMSmath Ready"); 638 639 }); 640 641 MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/AMSmath.js");