AMScd.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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 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.2",
  27. config: MathJax.Hub.CombineConfig("TeX.CD",{
  28. colspace: "5pt",
  29. rowspace: "5pt",
  30. harrowsize: "2.25em",
  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[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) {this.CD_cell(name)}
  67. //
  68. // Add enough cells to place the arrow correctly
  69. //
  70. var arrowRow = ((top.table.length % 2) === 1);
  71. var n = (top.row.length + (arrowRow ? 0 : 1)) % 2;
  72. while (n) {this.CD_cell(name); n--}
  73. var mml;
  74. var hdef = {minsize: top.minw, stretchy:true},
  75. vdef = {minsize: top.minh, stretchy:true, symmetric:true};
  76. if (c === ".") {}
  77. else if (c === "|") {mml = this.mmlToken(MML.mo("\u2225").With(vdef))}
  78. else if (c === "=") {mml = this.mmlToken(MML.mo("=").With(hdef))}
  79. else {
  80. //
  81. // for @>>> @<<< @VVV and @AAA, get the arrow and labels
  82. //
  83. var arrow = {">":"\u2192", "<":"\u2190", V:"\u2193", A:"\u2191"}[c];
  84. var a = this.GetUpTo(name+c,c),
  85. b = this.GetUpTo(name+c,c);
  86. if (c === ">" || c === "<") {
  87. //
  88. // Lay out horizontal arrows with munderover if it has labels
  89. //
  90. mml = MML.mo(arrow).With(hdef);
  91. if (!a) {a = "\\kern "+top.minw} // minsize needs work
  92. if (a || b) {
  93. var pad = {width:"+11mu", lspace:"6mu"};
  94. mml = MML.munderover(this.mmlToken(mml));
  95. if (a) {
  96. a = TEX.Parse(a,this.stack.env).mml();
  97. mml.SetData(mml.over,MML.mpadded(a).With(pad).With({voffset:".1em"}));
  98. }
  99. if (b) {
  100. b = TEX.Parse(b,this.stack.env).mml();
  101. mml.SetData(mml.under,MML.mpadded(b).With(pad));
  102. }
  103. if (CONFIG.hideHorizontalLabels)
  104. {mml = MML.mpadded(mml).With({depth:0, height:".67em"})}
  105. }
  106. } else {
  107. //
  108. // Lay out vertical arrows with mrow if there are labels
  109. //
  110. mml = arrow = this.mmlToken(MML.mo(arrow).With(vdef));
  111. if (a || b) {
  112. mml = MML.mrow();
  113. if (a) {mml.Append(TEX.Parse("\\scriptstyle\\llap{"+a+"}",this.stack.env).mml())}
  114. mml.Append(arrow.With({texClass: MML.TEXCLASS.ORD}));
  115. if (b) {mml.Append(TEX.Parse("\\scriptstyle\\rlap{"+b+"}",this.stack.env).mml())}
  116. }
  117. }
  118. }
  119. if (mml) {this.Push(mml)};
  120. this.CD_cell(name);
  121. },
  122. CD_cell: function (name) {
  123. this.Push(STACKITEM.cell().With({isEntry:true, name:name}));
  124. },
  125. CD_minwidth: function (name) {
  126. this.stack.env.CD_minw = this.GetDimen(name);
  127. },
  128. CD_minheight: function (name) {
  129. this.stack.env.CD_minh = this.GetDimen(name);
  130. }
  131. });
  132. });
  133. MathJax.Ajax.loadComplete("[MathJax]/extensions/TeX/AMScd.js");