katex 0.12.0 → 0.13.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/LICENSE +1 -1
  3. package/README.md +8 -7
  4. package/contrib/auto-render/auto-render.js +12 -19
  5. package/contrib/auto-render/index.html +9 -3
  6. package/contrib/auto-render/splitAtDelimiters.js +44 -61
  7. package/contrib/auto-render/test/auto-render-spec.js +88 -52
  8. package/contrib/copy-tex/README.md +5 -9
  9. package/contrib/copy-tex/copy-tex.css +0 -3
  10. package/contrib/mathtex-script-type/README.md +5 -5
  11. package/contrib/mhchem/README.md +4 -2
  12. package/contrib/render-a11y-string/render-a11y-string.js +31 -2
  13. package/contrib/render-a11y-string/test/render-a11y-string-spec.js +23 -0
  14. package/dist/README.md +8 -7
  15. package/dist/contrib/auto-render.js +148 -171
  16. package/dist/contrib/auto-render.min.js +1 -1
  17. package/dist/contrib/auto-render.mjs +91 -95
  18. package/dist/contrib/copy-tex.css +3 -3
  19. package/dist/contrib/copy-tex.js +11 -108
  20. package/dist/contrib/copy-tex.min.css +1 -1
  21. package/dist/contrib/copy-tex.min.js +1 -1
  22. package/dist/contrib/copy-tex.mjs +21 -20
  23. package/dist/contrib/mathtex-script-type.js +66 -91
  24. package/dist/contrib/mathtex-script-type.min.js +1 -1
  25. package/dist/contrib/mathtex-script-type.mjs +3 -3
  26. package/dist/contrib/mhchem.js +70 -95
  27. package/dist/contrib/mhchem.min.js +1 -1
  28. package/dist/contrib/mhchem.mjs +2 -2
  29. package/dist/contrib/render-a11y-string.js +97 -92
  30. package/dist/contrib/render-a11y-string.min.js +1 -1
  31. package/dist/contrib/render-a11y-string.mjs +86 -45
  32. package/dist/fonts/KaTeX_AMS-Regular.ttf +0 -0
  33. package/dist/fonts/KaTeX_AMS-Regular.woff +0 -0
  34. package/dist/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  35. package/dist/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  36. package/dist/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  37. package/dist/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  38. package/dist/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  39. package/dist/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  40. package/dist/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  41. package/dist/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  42. package/dist/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  43. package/dist/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  44. package/dist/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  45. package/dist/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  46. package/dist/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  47. package/dist/fonts/KaTeX_Main-Bold.ttf +0 -0
  48. package/dist/fonts/KaTeX_Main-Bold.woff +0 -0
  49. package/dist/fonts/KaTeX_Main-Bold.woff2 +0 -0
  50. package/dist/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  51. package/dist/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  52. package/dist/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  53. package/dist/fonts/KaTeX_Main-Italic.ttf +0 -0
  54. package/dist/fonts/KaTeX_Main-Italic.woff +0 -0
  55. package/dist/fonts/KaTeX_Main-Italic.woff2 +0 -0
  56. package/dist/fonts/KaTeX_Main-Regular.ttf +0 -0
  57. package/dist/fonts/KaTeX_Main-Regular.woff +0 -0
  58. package/dist/fonts/KaTeX_Main-Regular.woff2 +0 -0
  59. package/dist/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  60. package/dist/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  61. package/dist/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  62. package/dist/fonts/KaTeX_Math-Italic.ttf +0 -0
  63. package/dist/fonts/KaTeX_Math-Italic.woff +0 -0
  64. package/dist/fonts/KaTeX_Math-Italic.woff2 +0 -0
  65. package/dist/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  66. package/dist/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  67. package/dist/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  68. package/dist/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  69. package/dist/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  70. package/dist/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  71. package/dist/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  72. package/dist/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  73. package/dist/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  74. package/dist/fonts/KaTeX_Script-Regular.ttf +0 -0
  75. package/dist/fonts/KaTeX_Script-Regular.woff +0 -0
  76. package/dist/fonts/KaTeX_Script-Regular.woff2 +0 -0
  77. package/dist/fonts/KaTeX_Size1-Regular.ttf +0 -0
  78. package/dist/fonts/KaTeX_Size1-Regular.woff +0 -0
  79. package/dist/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  80. package/dist/fonts/KaTeX_Size2-Regular.ttf +0 -0
  81. package/dist/fonts/KaTeX_Size2-Regular.woff +0 -0
  82. package/dist/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  83. package/dist/fonts/KaTeX_Size3-Regular.ttf +0 -0
  84. package/dist/fonts/KaTeX_Size3-Regular.woff +0 -0
  85. package/dist/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  86. package/dist/fonts/KaTeX_Size4-Regular.ttf +0 -0
  87. package/dist/fonts/KaTeX_Size4-Regular.woff +0 -0
  88. package/dist/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  89. package/dist/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  90. package/dist/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  91. package/dist/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  92. package/dist/katex.css +66 -10
  93. package/dist/katex.js +2714 -1950
  94. package/dist/katex.min.css +1 -1
  95. package/dist/katex.min.js +1 -1
  96. package/dist/katex.mjs +3162 -2372
  97. package/katex.js +4 -3
  98. package/package.json +69 -59
  99. package/src/Lexer.js +4 -2
  100. package/src/MacroExpander.js +117 -37
  101. package/src/Options.js +2 -2
  102. package/src/ParseError.js +1 -1
  103. package/src/Parser.js +100 -159
  104. package/src/Settings.js +2 -2
  105. package/src/Style.js +4 -4
  106. package/src/Token.js +1 -1
  107. package/src/buildCommon.js +12 -5
  108. package/src/buildHTML.js +11 -0
  109. package/src/buildMathML.js +6 -0
  110. package/src/defineEnvironment.js +0 -3
  111. package/src/defineFunction.js +15 -22
  112. package/src/delimiter.js +61 -57
  113. package/src/domTree.js +1 -1
  114. package/src/environments/array.js +223 -35
  115. package/src/environments/cd.js +312 -0
  116. package/src/fontMetrics.js +1 -1
  117. package/src/fontMetricsData.js +2076 -0
  118. package/src/fonts/.gitignore +9 -0
  119. package/src/fonts/Makefile +139 -0
  120. package/src/fonts/default.cfg +20 -0
  121. package/src/fonts/generate_fonts.py +61 -0
  122. package/src/fonts/lib/Extra.otf +0 -0
  123. package/src/fonts/lib/Space.ttx +234 -0
  124. package/src/fonts/makeBlacker +49 -0
  125. package/src/fonts/makeFF +2003 -0
  126. package/src/fonts/xbbold.mf +182 -0
  127. package/src/fonts.less +64 -0
  128. package/src/functions/accent.js +3 -2
  129. package/src/functions/arrow.js +8 -2
  130. package/src/functions/color.js +4 -4
  131. package/src/functions/cr.js +7 -25
  132. package/src/functions/def.js +50 -24
  133. package/src/functions/delimsizing.js +8 -0
  134. package/src/functions/enclose.js +80 -12
  135. package/src/functions/environment.js +1 -1
  136. package/src/functions/font.js +3 -4
  137. package/src/functions/genfrac.js +36 -11
  138. package/src/functions/hbox.js +39 -0
  139. package/src/functions/kern.js +1 -0
  140. package/src/functions/mathchoice.js +1 -0
  141. package/src/functions/mclass.js +2 -1
  142. package/src/functions/op.js +3 -7
  143. package/src/functions/operatorname.js +1 -1
  144. package/src/functions/raisebox.js +0 -1
  145. package/src/functions/styling.js +1 -0
  146. package/src/functions/supsub.js +1 -3
  147. package/src/functions/symbolsOrd.js +0 -2
  148. package/src/functions/text.js +2 -3
  149. package/src/functions/vcenter.js +44 -0
  150. package/src/functions.js +3 -0
  151. package/src/katex.less +69 -16
  152. package/src/macros.js +42 -6
  153. package/src/mathMLTree.js +16 -1
  154. package/src/metrics/.gitignore +1 -0
  155. package/src/metrics/README.md +23 -0
  156. package/src/metrics/extract_tfms.py +114 -0
  157. package/src/metrics/extract_ttfs.py +119 -0
  158. package/src/metrics/format_json.py +28 -0
  159. package/src/metrics/mapping.pl +1224 -0
  160. package/src/metrics/parse_tfm.py +211 -0
  161. package/src/parseNode.js +29 -1
  162. package/src/parseTree.js +6 -0
  163. package/src/stretchy.js +12 -5
  164. package/src/svgGeometry.js +33 -4
  165. package/src/symbols.js +5 -3
  166. package/src/types.js +3 -2
  167. package/src/unicodeScripts.js +5 -0
@@ -2,6 +2,7 @@
2
2
  import buildCommon from "../buildCommon";
3
3
  import Style from "../Style";
4
4
  import defineEnvironment from "../defineEnvironment";
5
+ import {parseCD} from "./cd";
5
6
  import defineFunction from "../defineFunction";
6
7
  import mathMLTree from "../mathMLTree";
7
8
  import ParseError from "../ParseError";
@@ -27,8 +28,9 @@ export type AlignSpec = { type: "separator", separator: string } | {
27
28
  };
28
29
 
29
30
  // Type to indicate column separation in MathML
30
- export type ColSeparationType = "align" | "alignat" | "small";
31
+ export type ColSeparationType = "align" | "alignat" | "gather" | "small" | "CD";
31
32
 
33
+ // Helper functions
32
34
  function getHLines(parser: Parser): boolean[] {
33
35
  // Return an array. The array length = number of hlines.
34
36
  // Each element in the array tells if the line is dashed.
@@ -44,6 +46,14 @@ function getHLines(parser: Parser): boolean[] {
44
46
  return hlineInfo;
45
47
  }
46
48
 
49
+ const validateAmsEnvironmentContext = context => {
50
+ const settings = context.parser.settings;
51
+ if (!settings.displayMode) {
52
+ throw new ParseError(`{${context.envName}} can be used only in` +
53
+ ` display mode.`);
54
+ }
55
+ };
56
+
47
57
  /**
48
58
  * Parse the body of the environment, with rows delimited by \\ and
49
59
  * columns delimited by &, and create a nested list in row-major order
@@ -52,18 +62,37 @@ function getHLines(parser: Parser): boolean[] {
52
62
  */
53
63
  function parseArray(
54
64
  parser: Parser,
55
- {hskipBeforeAndAfter, addJot, cols, arraystretch, colSeparationType}: {|
65
+ {
66
+ hskipBeforeAndAfter,
67
+ addJot,
68
+ cols,
69
+ arraystretch,
70
+ colSeparationType,
71
+ addEqnNum,
72
+ singleRow,
73
+ emptySingleRow,
74
+ maxNumCols,
75
+ leqno,
76
+ }: {|
56
77
  hskipBeforeAndAfter?: boolean,
57
78
  addJot?: boolean,
58
79
  cols?: AlignSpec[],
59
80
  arraystretch?: number,
60
81
  colSeparationType?: ColSeparationType,
82
+ addEqnNum?: boolean,
83
+ singleRow?: boolean,
84
+ emptySingleRow?: boolean,
85
+ maxNumCols?: number,
86
+ leqno?: boolean,
61
87
  |},
62
88
  style: StyleStr,
63
89
  ): ParseNode<"array"> {
64
- // Parse body of array with \\ temporarily mapped to \cr
65
90
  parser.gullet.beginGroup();
66
- parser.gullet.macros.set("\\\\", "\\cr");
91
+ if (!singleRow) {
92
+ // \cr is equivalent to \\ without the optional size argument (see below)
93
+ // TODO: provide helpful error when \cr is used outside array environment
94
+ parser.gullet.macros.set("\\cr", "\\\\\\relax");
95
+ }
67
96
 
68
97
  // Get current arraystretch if it's not set by the environment
69
98
  if (!arraystretch) {
@@ -92,7 +121,7 @@ function parseArray(
92
121
 
93
122
  while (true) { // eslint-disable-line no-constant-condition
94
123
  // Parse each cell in its own group (namespace)
95
- let cell = parser.parseExpression(false, "\\cr");
124
+ let cell = parser.parseExpression(false, singleRow ? "\\end" : "\\\\");
96
125
  parser.gullet.endGroup();
97
126
  parser.gullet.beginGroup();
98
127
 
@@ -112,22 +141,44 @@ function parseArray(
112
141
  row.push(cell);
113
142
  const next = parser.fetch().text;
114
143
  if (next === "&") {
144
+ if (maxNumCols && row.length === maxNumCols) {
145
+ if (singleRow || colSeparationType) {
146
+ // {equation} or {split}
147
+ throw new ParseError("Too many tab characters: &",
148
+ parser.nextToken);
149
+ } else {
150
+ // {array} environment
151
+ parser.settings.reportNonstrict("textEnv", "Too few columns " +
152
+ "specified in the {array} column argument.");
153
+ }
154
+ }
115
155
  parser.consume();
116
156
  } else if (next === "\\end") {
117
157
  // Arrays terminate newlines with `\crcr` which consumes a `\cr` if
118
- // the last line is empty.
158
+ // the last line is empty. However, AMS environments keep the
159
+ // empty row if it's the only one.
119
160
  // NOTE: Currently, `cell` is the last item added into `row`.
120
161
  if (row.length === 1 && cell.type === "styling" &&
121
- cell.body[0].body.length === 0) {
162
+ cell.body[0].body.length === 0 &&
163
+ (body.length > 1 || !emptySingleRow)) {
122
164
  body.pop();
123
165
  }
124
166
  if (hLinesBeforeRow.length < body.length + 1) {
125
167
  hLinesBeforeRow.push([]);
126
168
  }
127
169
  break;
128
- } else if (next === "\\cr") {
129
- const cr = assertNodeType(parser.parseFunction(), "cr");
130
- rowGaps.push(cr.size);
170
+ } else if (next === "\\\\") {
171
+ parser.consume();
172
+ let size;
173
+ // \def\Let@{\let\\\math@cr}
174
+ // \def\math@cr{...\math@cr@}
175
+ // \def\math@cr@{\new@ifnextchar[\math@cr@@{\math@cr@@[\z@]}}
176
+ // \def\math@cr@@[#1]{...\math@cr@@@...}
177
+ // \def\math@cr@@@{\cr}
178
+ if (parser.gullet.future().text !== " ") {
179
+ size = parser.parseSizeGroup(true);
180
+ }
181
+ rowGaps.push(size ? size.value : null);
131
182
 
132
183
  // check for \hline(s) following the row separator
133
184
  hLinesBeforeRow.push(getHLines(parser));
@@ -142,7 +193,7 @@ function parseArray(
142
193
 
143
194
  // End cell group
144
195
  parser.gullet.endGroup();
145
- // End array group defining \\
196
+ // End array group defining \cr
146
197
  parser.gullet.endGroup();
147
198
 
148
199
  return {
@@ -156,6 +207,8 @@ function parseArray(
156
207
  hskipBeforeAndAfter,
157
208
  hLinesBeforeRow,
158
209
  colSeparationType,
210
+ addEqnNum,
211
+ leqno,
159
212
  };
160
213
  }
161
214
 
@@ -206,7 +259,9 @@ const htmlBuilder: HtmlBuilder<"array"> = function(group, options) {
206
259
  }
207
260
 
208
261
  // Vertical spacing
209
- const baselineskip = 12 * pt; // see size10.clo
262
+ const baselineskip = group.colSeparationType === "CD"
263
+ ? calculateSize({number: 3, unit: "ex"}, options)
264
+ : 12 * pt; // see size10.clo
210
265
  // Default \jot from ltmath.dtx
211
266
  // TODO(edemaine): allow overriding \jot via \setlength (#687)
212
267
  const jot = 3 * pt;
@@ -283,6 +338,21 @@ const htmlBuilder: HtmlBuilder<"array"> = function(group, options) {
283
338
  const cols = [];
284
339
  let colSep;
285
340
  let colDescrNum;
341
+
342
+ const eqnNumSpans = [];
343
+ if (group.addEqnNum) {
344
+ // An environment with automatic equation numbers.
345
+ // Create node(s) that will trigger CSS counter increment.
346
+ for (r = 0; r < nr; ++r) {
347
+ const rw = body[r];
348
+ const shift = rw.pos - offset;
349
+ const eqnTag = buildCommon.makeSpan(["eqn-num"], [], options);
350
+ eqnTag.depth = rw.depth;
351
+ eqnTag.height = rw.height;
352
+ eqnNumSpans.push({type: "elem", elem: eqnTag, shift});
353
+ }
354
+ }
355
+
286
356
  for (c = 0, colDescrNum = 0;
287
357
  // Continue while either there are more columns or more column
288
358
  // descriptions, so trailing separators don't get lost.
@@ -393,7 +463,16 @@ const htmlBuilder: HtmlBuilder<"array"> = function(group, options) {
393
463
  }, options);
394
464
  }
395
465
 
396
- return buildCommon.makeSpan(["mord"], [body], options);
466
+ if (!group.addEqnNum) {
467
+ return buildCommon.makeSpan(["mord"], [body], options);
468
+ } else {
469
+ let eqnNumCol = buildCommon.makeVList({
470
+ positionType: "individualShift",
471
+ children: eqnNumSpans,
472
+ }, options);
473
+ eqnNumCol = buildCommon.makeSpan(["tag"], [eqnNumCol], options);
474
+ return buildCommon.makeFragment([body, eqnNumCol]);
475
+ }
397
476
  };
398
477
 
399
478
  const alignMap = {
@@ -403,14 +482,28 @@ const alignMap = {
403
482
  };
404
483
 
405
484
  const mathmlBuilder: MathMLBuilder<"array"> = function(group, options) {
406
- let table = new mathMLTree.MathNode(
407
- "mtable", group.body.map(function(row) {
408
- return new mathMLTree.MathNode(
409
- "mtr", row.map(function(cell) {
410
- return new mathMLTree.MathNode(
411
- "mtd", [mml.buildGroup(cell, options)]);
412
- }));
413
- }));
485
+ const tbl = [];
486
+ const glue = new mathMLTree.MathNode("mtd", [], ["mtr-glue"]);
487
+ const tag = new mathMLTree.MathNode("mtd", [], ["mml-eqn-num"]);
488
+ for (let i = 0; i < group.body.length; i++) {
489
+ const rw = group.body[i];
490
+ const row = [];
491
+ for (let j = 0; j < rw.length; j++) {
492
+ row.push(new mathMLTree.MathNode("mtd",
493
+ [mml.buildGroup(rw[j], options)]));
494
+ }
495
+ if (group.addEqnNum) {
496
+ row.unshift(glue);
497
+ row.push(glue);
498
+ if (group.leqno) {
499
+ row.unshift(tag);
500
+ } else {
501
+ row.push(tag);
502
+ }
503
+ }
504
+ tbl.push(new mathMLTree.MathNode("mtr", row));
505
+ }
506
+ let table = new mathMLTree.MathNode("mtable", tbl);
414
507
 
415
508
  // Set column alignment, row spacing, column spacing, and
416
509
  // array lines by setting attributes on the table element.
@@ -428,7 +521,7 @@ const mathmlBuilder: MathMLBuilder<"array"> = function(group, options) {
428
521
  const gap = (group.arraystretch === 0.5)
429
522
  ? 0.1 // {smallmatrix}, {subarray}
430
523
  : 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0);
431
- table.setAttribute("rowspacing", gap + "em");
524
+ table.setAttribute("rowspacing", gap.toFixed(4) + "em");
432
525
 
433
526
  // MathML table lines go only between cells.
434
527
  // To place a line on an edge we'll use <menclose>, if necessary.
@@ -487,10 +580,13 @@ const mathmlBuilder: MathMLBuilder<"array"> = function(group, options) {
487
580
  spacing += i % 2 ? "0em " : "1em ";
488
581
  }
489
582
  table.setAttribute("columnspacing", spacing.trim());
490
- } else if (group.colSeparationType === "alignat") {
583
+ } else if (group.colSeparationType === "alignat" ||
584
+ group.colSeparationType === "gather") {
491
585
  table.setAttribute("columnspacing", "0em");
492
586
  } else if (group.colSeparationType === "small") {
493
587
  table.setAttribute("columnspacing", "0.2778em");
588
+ } else if (group.colSeparationType === "CD") {
589
+ table.setAttribute("columnspacing", "0.5em");
494
590
  } else {
495
591
  table.setAttribute("columnspacing", "1em");
496
592
  }
@@ -526,10 +622,25 @@ const mathmlBuilder: MathMLBuilder<"array"> = function(group, options) {
526
622
  return table;
527
623
  };
528
624
 
529
- // Convenience function for aligned and alignedat environments.
625
+ // Convenience function for align, align*, aligned, alignat, alignat*, alignedat.
530
626
  const alignedHandler = function(context, args) {
627
+ if (context.envName.indexOf("ed") === -1) {
628
+ validateAmsEnvironmentContext(context);
629
+ }
531
630
  const cols = [];
532
- const res = parseArray(context.parser, {cols, addJot: true}, "display");
631
+ const separationType = context.envName.indexOf("at") > -1 ? "alignat" : "align";
632
+ const res = parseArray(context.parser,
633
+ {
634
+ cols,
635
+ addJot: true,
636
+ addEqnNum: context.envName === "align" || context.envName === "alignat",
637
+ emptySingleRow: true,
638
+ colSeparationType: separationType,
639
+ maxNumCols: context.envName === "split" ? 2 : undefined,
640
+ leqno: context.parser.settings.leqno,
641
+ },
642
+ "display"
643
+ );
533
644
 
534
645
  // Determining number of columns.
535
646
  // 1. If the first argument is given, we use it as a number of columns,
@@ -641,6 +752,7 @@ defineEnvironment({
641
752
  const res = {
642
753
  cols,
643
754
  hskipBeforeAndAfter: true, // \@preamble in lttab.dtx
755
+ maxNumCols: cols.length,
644
756
  };
645
757
  return parseArray(context.parser, res, dCellStyle(context.envName));
646
758
  },
@@ -650,6 +762,8 @@ defineEnvironment({
650
762
 
651
763
  // The matrix environments of amsmath builds on the array environment
652
764
  // of LaTeX, which is discussed above.
765
+ // The mathtools package adds starred versions of the same environments.
766
+ // These have an optional argument to choose left|center|right justification.
653
767
  defineEnvironment({
654
768
  type: "array",
655
769
  names: [
@@ -659,6 +773,12 @@ defineEnvironment({
659
773
  "Bmatrix",
660
774
  "vmatrix",
661
775
  "Vmatrix",
776
+ "matrix*",
777
+ "pmatrix*",
778
+ "bmatrix*",
779
+ "Bmatrix*",
780
+ "vmatrix*",
781
+ "Vmatrix*",
662
782
  ],
663
783
  props: {
664
784
  numArgs: 0,
@@ -671,11 +791,38 @@ defineEnvironment({
671
791
  "Bmatrix": ["\\{", "\\}"],
672
792
  "vmatrix": ["|", "|"],
673
793
  "Vmatrix": ["\\Vert", "\\Vert"],
674
- }[context.envName];
794
+ }[context.envName.replace("*", "")];
675
795
  // \hskip -\arraycolsep in amsmath
676
- const payload = {hskipBeforeAndAfter: false};
796
+ let colAlign = "c";
797
+ const payload = {
798
+ hskipBeforeAndAfter: false,
799
+ cols: [{type: "align", align: colAlign}],
800
+ };
801
+ if (context.envName.charAt(context.envName.length - 1) === "*") {
802
+ // It's one of the mathtools starred functions.
803
+ // Parse the optional alignment argument.
804
+ const parser = context.parser;
805
+ parser.consumeSpaces();
806
+ if (parser.fetch().text === "[") {
807
+ parser.consume();
808
+ parser.consumeSpaces();
809
+ colAlign = parser.fetch().text;
810
+ if ("lcr".indexOf(colAlign) === -1) {
811
+ throw new ParseError("Expected l or c or r", parser.nextToken);
812
+ }
813
+ parser.consume();
814
+ parser.consumeSpaces();
815
+ parser.expect("]");
816
+ parser.consume();
817
+ payload.cols = [{type: "align", align: colAlign}];
818
+ }
819
+ }
677
820
  const res: ParseNode<"array"> =
678
821
  parseArray(context.parser, payload, dCellStyle(context.envName));
822
+ // Populate cols with the correct number of column alignment specs.
823
+ res.cols = new Array(res.body[0].length).fill(
824
+ {type: "align", align: colAlign}
825
+ );
679
826
  return delimiters ? {
680
827
  type: "leftright",
681
828
  mode: context.mode,
@@ -797,13 +944,15 @@ defineEnvironment({
797
944
  mathmlBuilder,
798
945
  });
799
946
 
800
- // An aligned environment is like the align* environment
801
- // except it operates within math mode.
947
+ // In the align environment, one uses ampersands, &, to specify number of
948
+ // columns in each row, and to locate spacing between each column.
949
+ // align gets automatic numbering. align* and aligned do not.
950
+ // The alignedat environment can be used in math mode.
802
951
  // Note that we assume \nomallineskiplimit to be zero,
803
952
  // so that \strut@ is the same as \strut.
804
953
  defineEnvironment({
805
954
  type: "array",
806
- names: ["aligned"],
955
+ names: ["align", "align*", "aligned", "split"],
807
956
  props: {
808
957
  numArgs: 0,
809
958
  },
@@ -817,17 +966,24 @@ defineEnvironment({
817
966
  // and contents are set in \displaystyle.
818
967
  defineEnvironment({
819
968
  type: "array",
820
- names: ["gathered"],
969
+ names: ["gathered", "gather", "gather*"],
821
970
  props: {
822
971
  numArgs: 0,
823
972
  },
824
973
  handler(context) {
974
+ if (utils.contains(["gather", "gather*"], context.envName)) {
975
+ validateAmsEnvironmentContext(context);
976
+ }
825
977
  const res = {
826
978
  cols: [{
827
979
  type: "align",
828
980
  align: "c",
829
981
  }],
830
982
  addJot: true,
983
+ colSeparationType: "gather",
984
+ addEqnNum: context.envName === "gather",
985
+ emptySingleRow: true,
986
+ leqno: context.parser.settings.leqno,
831
987
  };
832
988
  return parseArray(context.parser, res, "display");
833
989
  },
@@ -840,10 +996,7 @@ defineEnvironment({
840
996
  // each columns.
841
997
  defineEnvironment({
842
998
  type: "array",
843
- names: ["alignedat"],
844
- // One for numbered and for unnumbered;
845
- // but, KaTeX doesn't supports math numbering yet,
846
- // they make no difference for now.
999
+ names: ["alignat", "alignat*", "alignedat"],
847
1000
  props: {
848
1001
  numArgs: 1,
849
1002
  },
@@ -852,6 +1005,41 @@ defineEnvironment({
852
1005
  mathmlBuilder,
853
1006
  });
854
1007
 
1008
+ defineEnvironment({
1009
+ type: "array",
1010
+ names: ["equation", "equation*"],
1011
+ props: {
1012
+ numArgs: 0,
1013
+ },
1014
+ handler(context) {
1015
+ validateAmsEnvironmentContext(context);
1016
+ const res = {
1017
+ addEqnNum: context.envName === "equation",
1018
+ emptySingleRow: true,
1019
+ singleRow: true,
1020
+ maxNumCols: 1,
1021
+ leqno: context.parser.settings.leqno,
1022
+ };
1023
+ return parseArray(context.parser, res, "display");
1024
+ },
1025
+ htmlBuilder,
1026
+ mathmlBuilder,
1027
+ });
1028
+
1029
+ defineEnvironment({
1030
+ type: "array",
1031
+ names: ["CD"],
1032
+ props: {
1033
+ numArgs: 0,
1034
+ },
1035
+ handler(context) {
1036
+ validateAmsEnvironmentContext(context);
1037
+ return parseCD(context.parser);
1038
+ },
1039
+ htmlBuilder,
1040
+ mathmlBuilder,
1041
+ });
1042
+
855
1043
  // Catch \hline outside array environment
856
1044
  defineFunction({
857
1045
  type: "text", // Doesn't matter what this is.