AMSmath.js 22 KB

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