AMScd.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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/AMScd.js
  6. *
  7. * Implements the CD environment for commutative diagrams.
  8. *
  9. * ---------------------------------------------------------------------
  10. *
  11. * Copyright (c) 2013-2015 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/AMScd"] = {
  26. version: "2.5.0",
  27. config: MathJax.Hub.CombineConfig("TeX.CD",{
  28. colspace: "5pt",
  29. rowspace: "5pt",
  30. harrowsize: "2.75em",
  31. varrowsize: "1.75em",
  32. hideHorizontalLabels: false
  33. })
  34. };
  35. MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
  36. var MML = MathJax.ElementJax.mml,
  37. TEX = MathJax.InputJax.TeX,
  38. STACKITEM = TEX.Stack.Item,
  39. TEXDEF = TEX.Definitions,
  40. CONFIG = MathJax.Extension["TeX/AMScd"].config;
  41. TEXDEF.environment.CD = "CD_env";
  42. TEXDEF.special["@"] = "CD_arrow";
  43. TEXDEF.macros.minCDarrowwidth = "CD_minwidth";
  44. TEXDEF.macros.minCDarrowheight = "CD_minheight";
  45. TEX.Parse.Augment({
  46. //
  47. // Implements \begin{CD}...\end{CD}
  48. //
  49. CD_env: function (begin) {
  50. this.Push(begin);
  51. return STACKITEM.array().With({
  52. arraydef: {
  53. columnalign: "center",
  54. columnspacing: CONFIG.colspace,
  55. rowspacing: CONFIG.rowspace,
  56. displaystyle: true
  57. },
  58. minw: this.stack.env.CD_minw || CONFIG.harrowsize,
  59. minh: this.stack.env.CD_minh || CONFIG.varrowsize
  60. });
  61. },
  62. CD_arrow: function (name) {
  63. var c = this.string.charAt(this.i);
  64. if (!c.match(/[><VA.|=]/)) {return this.Other(name)} else {this.i++}
  65. var top = this.stack.Top();
  66. if (!top.isa(STACKITEM.array) || top.data.length) {
  67. this.CD_cell(name);
  68. top = this.stack.Top();
  69. }
  70. //
  71. // Add enough cells to place the arrow correctly
  72. //
  73. var arrowRow = ((top.table.length % 2) === 1);
  74. var n = (top.row.length + (arrowRow ? 0 : 1)) % 2;
  75. while (n) {this.CD_cell(name); n--}
  76. var mml;
  77. var hdef = {minsize: top.minw, stretchy:true},
  78. vdef = {minsize: top.minh, stretchy:true, symmetric:true, lspace:0, rspace:0};
  79. if (c === ".") {}
  80. else if (c === "|") {mml = this.mmlToken(MML.mo("\u2225").With(vdef))}
  81. else if (c === "=") {mml = this.mmlToken(MML.mo("=").With(hdef))}
  82. else {
  83. //
  84. // for @>>> @<<< @VVV and @AAA, get the arrow and labels
  85. //
  86. var arrow = {">":"\u2192", "<":"\u2190", V:"\u2193", A:"\u2191"}[c];
  87. var a = this.GetUpTo(name+c,c),
  88. b = this.GetUpTo(name+c,c);
  89. if (c === ">" || c === "<") {
  90. //
  91. // Lay out horizontal arrows with munderover if it has labels
  92. //
  93. mml = MML.mo(arrow).With(hdef);
  94. if (!a) {a = "\\kern "+top.minw} // minsize needs work
  95. if (a || b) {
  96. var pad = {width:"+11mu", lspace:"6mu"};
  97. mml = MML.munderover(this.mmlToken(mml));
  98. if (a) {
  99. a = TEX.Parse(a,this.stack.env).mml();
  100. mml.SetData(mml.over,MML.mpadded(a).With(pad).With({voffset:".1em"}));
  101. }
  102. if (b) {
  103. b = TEX.Parse(b,this.stack.env).mml();
  104. mml.SetData(mml.under,MML.mpadded(b).With(pad));
  105. }
  106. if (CONFIG.hideHorizontalLabels)
  107. {mml = MML.mpadded(mml).With({depth:0, height:".67em"})}
  108. }
  109. } else {
  110. //
  111. // Lay out vertical arrows with mrow if there are labels
  112. //
  113. mml = arrow = this.mmlToken(MML.mo(arrow).With(vdef));
  114. if (a || b) {
  115. mml = MML.mrow();
  116. if (a) {mml.Append(TEX.Parse("\\scriptstyle\\llap{"+a+"}",this.stack.env).mml())}
  117. mml.Append(arrow.With({texClass: MML.TEXCLASS.ORD}));
  118. if (b) {mml.Append(TEX.Parse("\\scriptstyle\\rlap{"+b+"}",this.stack.env).mml())}
  119. }
  120. }
  121. }
  122. if (mml) {this.Push(mml)};
  123. this.CD_cell(name);
  124. },
  125. CD_cell: function (name) {
  126. var top = this.stack.Top();
  127. if ((top.table||[]).length % 2 === 0 && (top.row||[]).length === 0) {
  128. //
  129. // Add a strut to the first cell in even rows to get
  130. // better spacing of arrow rows.
  131. //
  132. this.Push(MML.mpadded().With({height:"8.5pt",depth:"2pt"}));
  133. }
  134. this.Push(STACKITEM.cell().With({isEntry:true, name:name}));
  135. },
  136. CD_minwidth: function (name) {
  137. this.stack.env.CD_minw = this.GetDimen(name);
  138. },
  139. CD_minheight: function (name) {
  140. this.stack.env.CD_minh = this.GetDimen(name);
  141. }
  142. });
  143. });
  144. MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/AMScd.js");