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
@@ -4,6 +4,9 @@ import buildCommon from "../buildCommon";
4
4
  import mathMLTree from "../mathMLTree";
5
5
  import utils from "../utils";
6
6
  import stretchy from "../stretchy";
7
+ import {phasePath} from "../svgGeometry";
8
+ import {PathNode, SvgNode} from "../domTree";
9
+ import {calculateSize} from "../units";
7
10
  import {assertNodeType} from "../parseNode";
8
11
 
9
12
  import * as html from "../buildHTML";
@@ -11,14 +14,14 @@ import * as mml from "../buildMathML";
11
14
 
12
15
 
13
16
  const htmlBuilder = (group, options) => {
14
- // \cancel, \bcancel, \xcancel, \sout, \fbox, \colorbox, \fcolorbox
17
+ // \cancel, \bcancel, \xcancel, \sout, \fbox, \colorbox, \fcolorbox, \phase
15
18
  // Some groups can return document fragments. Handle those by wrapping
16
19
  // them in a span.
17
20
  const inner = buildCommon.wrapFragment(
18
21
  html.buildGroup(group.body, options), options);
19
22
 
20
23
  const label = group.label.substr(1);
21
- const scale = options.sizeMultiplier;
24
+ let scale = options.sizeMultiplier;
22
25
  let img;
23
26
  let imgShift = 0;
24
27
 
@@ -34,18 +37,48 @@ const htmlBuilder = (group, options) => {
34
37
  img.height = options.fontMetrics().defaultRuleThickness / scale;
35
38
  imgShift = -0.5 * options.fontMetrics().xHeight;
36
39
 
40
+ } else if (label === "phase") {
41
+ // Set a couple of dimensions from the steinmetz package.
42
+ const lineWeight = calculateSize({number: 0.6, unit: "pt"}, options);
43
+ const clearance = calculateSize({number: 0.35, unit: "ex"}, options);
44
+
45
+ // Prevent size changes like \Huge from affecting line thickness
46
+ const newOptions = options.havingBaseSizing();
47
+ scale = scale / newOptions.sizeMultiplier;
48
+
49
+ const angleHeight = inner.height + inner.depth + lineWeight + clearance;
50
+ // Reserve a left pad for the angle.
51
+ inner.style.paddingLeft = (angleHeight / 2 + lineWeight) + "em";
52
+
53
+ // Create an SVG
54
+ const viewBoxHeight = Math.floor(1000 * angleHeight * scale);
55
+ const path = phasePath(viewBoxHeight);
56
+ const svgNode = new SvgNode([new PathNode("phase", path)], {
57
+ "width": "400em",
58
+ "height": `${viewBoxHeight / 1000}em`,
59
+ "viewBox": `0 0 400000 ${viewBoxHeight}`,
60
+ "preserveAspectRatio": "xMinYMin slice",
61
+ });
62
+ // Wrap it in a span with overflow: hidden.
63
+ img = buildCommon.makeSvgSpan(["hide-tail"], [svgNode], options);
64
+ img.style.height = angleHeight + "em";
65
+ imgShift = inner.depth + lineWeight + clearance;
66
+
37
67
  } else {
38
68
  // Add horizontal padding
39
69
  if (/cancel/.test(label)) {
40
70
  if (!isSingleChar) {
41
71
  inner.classes.push("cancel-pad");
42
72
  }
73
+ } else if (label === "angl") {
74
+ inner.classes.push("anglpad");
43
75
  } else {
44
76
  inner.classes.push("boxpad");
45
77
  }
46
78
 
47
79
  // Add vertical padding
48
- let vertPad = 0;
80
+ let topPad = 0;
81
+ let bottomPad = 0;
49
82
  let ruleThickness = 0;
50
83
  // ref: cancel package: \advance\totalheight2\p@ % "+2"
51
84
  if (/box/.test(label)) {
@@ -53,18 +86,30 @@ const htmlBuilder = (group, options) => {
53
86
  options.fontMetrics().fboxrule, // default
54
87
  options.minRuleThickness, // User override.
55
88
  );
56
- vertPad = options.fontMetrics().fboxsep +
89
+ topPad = options.fontMetrics().fboxsep +
57
90
  (label === "colorbox" ? 0 : ruleThickness);
91
+ bottomPad = topPad;
92
+ } else if (label === "angl") {
93
+ ruleThickness = Math.max(
94
+ options.fontMetrics().defaultRuleThickness,
95
+ options.minRuleThickness
96
+ );
97
+ topPad = 4 * ruleThickness; // gap = 3 × line, plus the line itself.
98
+ bottomPad = Math.max(0, 0.25 - inner.depth);
58
99
  } else {
59
- vertPad = isSingleChar ? 0.2 : 0;
100
+ topPad = isSingleChar ? 0.2 : 0;
101
+ bottomPad = topPad;
60
102
  }
61
103
 
62
- img = stretchy.encloseSpan(inner, label, vertPad, options);
104
+ img = stretchy.encloseSpan(inner, label, topPad, bottomPad, options);
63
105
  if (/fbox|boxed|fcolorbox/.test(label)) {
64
106
  img.style.borderStyle = "solid";
65
107
  img.style.borderWidth = `${ruleThickness}em`;
108
+ } else if (label === "angl" && ruleThickness !== 0.049) {
109
+ img.style.borderTopWidth = `${ruleThickness}em`;
110
+ img.style.borderRightWidth = `${ruleThickness}em`;
66
111
  }
67
- imgShift = inner.depth + vertPad;
112
+ imgShift = inner.depth + bottomPad;
68
113
 
69
114
  if (group.backgroundColor) {
70
115
  img.style.backgroundColor = group.backgroundColor;
@@ -85,6 +130,7 @@ const htmlBuilder = (group, options) => {
85
130
  ],
86
131
  }, options);
87
132
  } else {
133
+ const classes = /cancel|phase/.test(label) ? ["svg-align"] : [];
88
134
  vlist = buildCommon.makeVList({
89
135
  positionType: "individualShift",
90
136
  children: [
@@ -98,7 +144,7 @@ const htmlBuilder = (group, options) => {
98
144
  type: "elem",
99
145
  elem: img,
100
146
  shift: imgShift,
101
- wrapperClasses: /cancel/.test(label) ? ["svg-align"] : [],
147
+ wrapperClasses: classes,
102
148
  },
103
149
  ],
104
150
  }, options);
@@ -132,12 +178,18 @@ const mathmlBuilder = (group, options) => {
132
178
  case "\\bcancel":
133
179
  node.setAttribute("notation", "downdiagonalstrike");
134
180
  break;
181
+ case "\\phase":
182
+ node.setAttribute("notation", "phasorangle");
183
+ break;
135
184
  case "\\sout":
136
185
  node.setAttribute("notation", "horizontalstrike");
137
186
  break;
138
187
  case "\\fbox":
139
188
  node.setAttribute("notation", "box");
140
189
  break;
190
+ case "\\angl":
191
+ node.setAttribute("notation", "actuarial");
192
+ break;
141
193
  case "\\fcolorbox":
142
194
  case "\\colorbox":
143
195
  // <menclose> doesn't have a good notation option. So use <mpadded>
@@ -173,7 +225,6 @@ defineFunction({
173
225
  props: {
174
226
  numArgs: 2,
175
227
  allowedInText: true,
176
- greediness: 3,
177
228
  argTypes: ["color", "text"],
178
229
  },
179
230
  handler({parser, funcName}, args, optArgs) {
@@ -197,7 +248,6 @@ defineFunction({
197
248
  props: {
198
249
  numArgs: 3,
199
250
  allowedInText: true,
200
- greediness: 3,
201
251
  argTypes: ["color", "color", "text"],
202
252
  },
203
253
  handler({parser, funcName}, args, optArgs) {
@@ -237,11 +287,11 @@ defineFunction({
237
287
 
238
288
  defineFunction({
239
289
  type: "enclose",
240
- names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout"],
290
+ names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\phase"],
241
291
  props: {
242
292
  numArgs: 1,
243
293
  },
244
- handler({parser, funcName}, args, optArgs) {
294
+ handler({parser, funcName}, args) {
245
295
  const body = args[0];
246
296
  return {
247
297
  type: "enclose",
@@ -253,3 +303,21 @@ defineFunction({
253
303
  htmlBuilder,
254
304
  mathmlBuilder,
255
305
  });
306
+
307
+ defineFunction({
308
+ type: "enclose",
309
+ names: ["\\angl"],
310
+ props: {
311
+ numArgs: 1,
312
+ argTypes: ["hbox"],
313
+ allowedInText: false,
314
+ },
315
+ handler({parser}, args) {
316
+ return {
317
+ type: "enclose",
318
+ mode: parser.mode,
319
+ label: "\\angl",
320
+ body: args[0],
321
+ };
322
+ },
323
+ });
@@ -6,7 +6,6 @@ import environments from "../environments";
6
6
 
7
7
  // Environment delimiters. HTML/MathML rendering is defined in the corresponding
8
8
  // defineEnvironment definitions.
9
- // $FlowFixMe, "environment" handler returns an environment ParseNode
10
9
  defineFunction({
11
10
  type: "environment",
12
11
  names: ["\\begin", "\\end"],
@@ -49,6 +48,7 @@ defineFunction({
49
48
  `Mismatch: \\begin{${envName}} matched by \\end{${end.name}}`,
50
49
  endNameToken);
51
50
  }
51
+ // $FlowFixMe, "environment" handler returns an environment ParseNode
52
52
  return result;
53
53
  }
54
54
 
@@ -2,7 +2,7 @@
2
2
  // TODO(kevinb): implement \\sl and \\sc
3
3
 
4
4
  import {binrelClass} from "./mclass";
5
- import defineFunction from "../defineFunction";
5
+ import defineFunction, {normalizeArgument} from "../defineFunction";
6
6
  import utils from "../utils";
7
7
 
8
8
  import * as html from "../buildHTML";
@@ -44,10 +44,10 @@ defineFunction({
44
44
  ],
45
45
  props: {
46
46
  numArgs: 1,
47
- greediness: 2,
47
+ allowedInArgument: true,
48
48
  },
49
49
  handler: ({parser, funcName}, args) => {
50
- const body = args[0];
50
+ const body = normalizeArgument(args[0]);
51
51
  let func = funcName;
52
52
  if (func in fontAliases) {
53
53
  func = fontAliases[func];
@@ -68,7 +68,6 @@ defineFunction({
68
68
  names: ["\\boldsymbol", "\\bm"],
69
69
  props: {
70
70
  numArgs: 1,
71
- greediness: 2,
72
71
  },
73
72
  handler: ({parser}, args) => {
74
73
  const body = args[0];
@@ -1,5 +1,5 @@
1
1
  // @flow
2
- import defineFunction from "../defineFunction";
2
+ import defineFunction, {normalizeArgument} from "../defineFunction";
3
3
  import buildCommon from "../buildCommon";
4
4
  import delimiter from "../delimiter";
5
5
  import mathMLTree from "../mathMLTree";
@@ -241,14 +241,14 @@ const mathmlBuilder = (group, options) => {
241
241
  defineFunction({
242
242
  type: "genfrac",
243
243
  names: [
244
- "\\cfrac", "\\dfrac", "\\frac", "\\tfrac",
244
+ "\\dfrac", "\\frac", "\\tfrac",
245
245
  "\\dbinom", "\\binom", "\\tbinom",
246
246
  "\\\\atopfrac", // can’t be entered directly
247
247
  "\\\\bracefrac", "\\\\brackfrac", // ditto
248
248
  ],
249
249
  props: {
250
250
  numArgs: 2,
251
- greediness: 2,
251
+ allowedInArgument: true,
252
252
  },
253
253
  handler: ({parser, funcName}, args) => {
254
254
  const numer = args[0];
@@ -259,7 +259,6 @@ defineFunction({
259
259
  let size = "auto";
260
260
 
261
261
  switch (funcName) {
262
- case "\\cfrac":
263
262
  case "\\dfrac":
264
263
  case "\\frac":
265
264
  case "\\tfrac":
@@ -290,7 +289,6 @@ defineFunction({
290
289
  }
291
290
 
292
291
  switch (funcName) {
293
- case "\\cfrac":
294
292
  case "\\dfrac":
295
293
  case "\\dbinom":
296
294
  size = "display";
@@ -304,7 +302,7 @@ defineFunction({
304
302
  return {
305
303
  type: "genfrac",
306
304
  mode: parser.mode,
307
- continued: funcName === "\\cfrac",
305
+ continued: false,
308
306
  numer,
309
307
  denom,
310
308
  hasBarLine,
@@ -319,6 +317,31 @@ defineFunction({
319
317
  mathmlBuilder,
320
318
  });
321
319
 
320
+ defineFunction({
321
+ type: "genfrac",
322
+ names: ["\\cfrac"],
323
+ props: {
324
+ numArgs: 2,
325
+ },
326
+ handler: ({parser, funcName}, args) => {
327
+ const numer = args[0];
328
+ const denom = args[1];
329
+
330
+ return {
331
+ type: "genfrac",
332
+ mode: parser.mode,
333
+ continued: true,
334
+ numer,
335
+ denom,
336
+ hasBarLine: true,
337
+ leftDelim: null,
338
+ rightDelim: null,
339
+ size: "display",
340
+ barSize: null,
341
+ };
342
+ },
343
+ });
344
+
322
345
  // Infix generalized fractions -- these are not rendered directly, but replaced
323
346
  // immediately by one of the variants above.
324
347
  defineFunction({
@@ -374,7 +397,7 @@ defineFunction({
374
397
  names: ["\\genfrac"],
375
398
  props: {
376
399
  numArgs: 6,
377
- greediness: 6,
400
+ allowedInArgument: true,
378
401
  argTypes: ["math", "math", "size", "text", "math", "math"],
379
402
  },
380
403
  handler({parser}, args) {
@@ -382,10 +405,12 @@ defineFunction({
382
405
  const denom = args[5];
383
406
 
384
407
  // Look into the parse nodes to get the desired delimiters.
385
- const leftDelim = args[0].type === "atom" && args[0].family === "open"
386
- ? delimFromValue(args[0].text) : null;
387
- const rightDelim = args[1].type === "atom" && args[1].family === "close"
388
- ? delimFromValue(args[1].text) : null;
408
+ const leftNode = normalizeArgument(args[0]);
409
+ const leftDelim = leftNode.type === "atom" && leftNode.family === "open"
410
+ ? delimFromValue(leftNode.text) : null;
411
+ const rightNode = normalizeArgument(args[1]);
412
+ const rightDelim = rightNode.type === "atom" && rightNode.family === "close"
413
+ ? delimFromValue(rightNode.text) : null;
389
414
 
390
415
  const barNode = assertNodeType(args[2], "size");
391
416
  let hasBarLine;
@@ -0,0 +1,39 @@
1
+ // @flow
2
+ import defineFunction, {ordargument} from "../defineFunction";
3
+ import buildCommon from "../buildCommon";
4
+ import mathMLTree from "../mathMLTree";
5
+
6
+ import * as html from "../buildHTML";
7
+ import * as mml from "../buildMathML";
8
+
9
+ // \hbox is provided for compatibility with LaTeX \vcenter.
10
+ // In LaTeX, \vcenter can act only on a box, as in
11
+ // \vcenter{\hbox{$\frac{a+b}{\dfrac{c}{d}}$}}
12
+ // This function by itself doesn't do anything but prevent a soft line break.
13
+
14
+ defineFunction({
15
+ type: "hbox",
16
+ names: ["\\hbox"],
17
+ props: {
18
+ numArgs: 1,
19
+ argTypes: ["text"],
20
+ allowedInText: true,
21
+ primitive: true,
22
+ },
23
+ handler({parser}, args) {
24
+ return {
25
+ type: "hbox",
26
+ mode: parser.mode,
27
+ body: ordargument(args[0]),
28
+ };
29
+ },
30
+ htmlBuilder(group, options) {
31
+ const elements = html.buildExpression(group.body, options, false);
32
+ return buildCommon.makeFragment(elements);
33
+ },
34
+ mathmlBuilder(group, options) {
35
+ return new mathMLTree.MathNode(
36
+ "mrow", mml.buildExpression(group.body, options)
37
+ );
38
+ },
39
+ });
@@ -15,6 +15,7 @@ defineFunction({
15
15
  props: {
16
16
  numArgs: 1,
17
17
  argTypes: ["size"],
18
+ primitive: true,
18
19
  allowedInText: true,
19
20
  },
20
21
  handler({parser, funcName}, args) {
@@ -23,6 +23,7 @@ defineFunction({
23
23
  names: ["\\mathchoice"],
24
24
  props: {
25
25
  numArgs: 4,
26
+ primitive: true,
26
27
  },
27
28
  handler: ({parser}, args) => {
28
29
  return {
@@ -65,6 +65,7 @@ defineFunction({
65
65
  ],
66
66
  props: {
67
67
  numArgs: 1,
68
+ primitive: true,
68
69
  },
69
70
  handler({parser, funcName}, args) {
70
71
  const body = args[0];
@@ -106,7 +107,7 @@ defineFunction({
106
107
  type: "mclass",
107
108
  mode: parser.mode,
108
109
  mclass: binrelClass(args[0]),
109
- body: [args[1]],
110
+ body: ordargument(args[1]),
110
111
  isCharacterBox: utils.isCharacterBox(args[1]),
111
112
  };
112
113
  },
@@ -61,7 +61,6 @@ export const htmlBuilder: HtmlBuilderSupSub<"op"> = (grp, options) => {
61
61
  // No font glyphs yet, so use a glyph w/o the oval.
62
62
  // TODO: When font glyphs are available, delete this code.
63
63
  stash = group.name.substr(1);
64
- // $FlowFixMe
65
64
  group.name = stash === "oiint" ? "\\iint" : "\\iiint";
66
65
  }
67
66
 
@@ -82,7 +81,6 @@ export const htmlBuilder: HtmlBuilderSupSub<"op"> = (grp, options) => {
82
81
  {type: "elem", elem: oval, shift: large ? 0.08 : 0},
83
82
  ],
84
83
  }, options);
85
- // $FlowFixMe
86
84
  group.name = "\\" + stash;
87
85
  base.classes.unshift("mop");
88
86
  // $FlowFixMe
@@ -95,14 +93,11 @@ export const htmlBuilder: HtmlBuilderSupSub<"op"> = (grp, options) => {
95
93
  base = inner[0];
96
94
  base.classes[0] = "mop"; // replace old mclass
97
95
  } else {
98
- base = buildCommon.makeSpan(
99
- ["mop"], buildCommon.tryCombineChars(inner), options);
96
+ base = buildCommon.makeSpan(["mop"], inner, options);
100
97
  }
101
98
  } else {
102
99
  // Otherwise, this is a text operator. Build the text from the
103
100
  // operator's name.
104
- // TODO(emily): Add a space in the middle of some of these
105
- // operators, like \limsup
106
101
  const output = [];
107
102
  for (let i = 1; i < group.name.length; i++) {
108
103
  output.push(buildCommon.mathsym(group.name[i], group.mode, options));
@@ -168,7 +163,7 @@ const mathmlBuilder: MathMLBuilder<"op"> = (group, options) => {
168
163
  const operator = new mathMLTree.MathNode("mo",
169
164
  [mml.makeText("\u2061", "text")]);
170
165
  if (group.parentIsSupSub) {
171
- node = new mathMLTree.MathNode("mo", [node, operator]);
166
+ node = new mathMLTree.MathNode("mrow", [node, operator]);
172
167
  } else {
173
168
  node = mathMLTree.newDocumentFragment([node, operator]);
174
169
  }
@@ -229,6 +224,7 @@ defineFunction({
229
224
  names: ["\\mathop"],
230
225
  props: {
231
226
  numArgs: 1,
227
+ primitive: true,
232
228
  },
233
229
  handler: ({parser}, args) => {
234
230
  const body = args[0];
@@ -130,7 +130,7 @@ const mathmlBuilder: MathMLBuilder<"operatorname"> = (group, options) => {
130
130
  [mml.makeText("\u2061", "text")]);
131
131
 
132
132
  if (group.parentIsSupSub) {
133
- return new mathMLTree.MathNode("mo", [identifier, operator]);
133
+ return new mathMLTree.MathNode("mrow", [identifier, operator]);
134
134
  } else {
135
135
  return mathMLTree.newDocumentFragment([identifier, operator]);
136
136
  }
@@ -44,4 +44,3 @@ defineFunction({
44
44
  return node;
45
45
  },
46
46
  });
47
-
@@ -22,6 +22,7 @@ defineFunction({
22
22
  props: {
23
23
  numArgs: 0,
24
24
  allowedInText: true,
25
+ primitive: true,
25
26
  },
26
27
  handler({breakOnTokenText, funcName, parser}, args) {
27
28
  // parse out the implicit body
@@ -260,9 +260,7 @@ defineFunctionBuilders({
260
260
  }
261
261
  }
262
262
 
263
- const node = new mathMLTree.MathNode(nodeType, children);
264
-
265
- return node;
263
+ return new mathMLTree.MathNode(nodeType, children);
266
264
  },
267
265
  });
268
266
 
@@ -47,8 +47,6 @@ defineFunctionBuilders({
47
47
  if (group.mode === 'text') {
48
48
  node = new mathMLTree.MathNode("mtext", [text]);
49
49
  } else if (/[0-9]/.test(group.text)) {
50
- // TODO(kevinb) merge adjacent <mn> nodes
51
- // do it as a post processing step
52
50
  node = new mathMLTree.MathNode("mn", [text]);
53
51
  } else if (group.text === "\\prime") {
54
52
  node = new mathMLTree.MathNode("mo", [text]);
@@ -48,7 +48,7 @@ defineFunction({
48
48
  props: {
49
49
  numArgs: 1,
50
50
  argTypes: ["text"],
51
- greediness: 2,
51
+ allowedInArgument: true,
52
52
  allowedInText: true,
53
53
  },
54
54
  handler({parser, funcName}, args) {
@@ -63,8 +63,7 @@ defineFunction({
63
63
  htmlBuilder(group, options) {
64
64
  const newOptions = optionsWithFont(group, options);
65
65
  const inner = html.buildExpression(group.body, newOptions, true);
66
- return buildCommon.makeSpan(
67
- ["mord", "text"], buildCommon.tryCombineChars(inner), newOptions);
66
+ return buildCommon.makeSpan(["mord", "text"], inner, newOptions);
68
67
  },
69
68
  mathmlBuilder(group, options) {
70
69
  const newOptions = optionsWithFont(group, options);
@@ -0,0 +1,44 @@
1
+ // @flow
2
+ import defineFunction from "../defineFunction";
3
+ import buildCommon from "../buildCommon";
4
+ import mathMLTree from "../mathMLTree";
5
+
6
+ import * as html from "../buildHTML";
7
+ import * as mml from "../buildMathML";
8
+
9
+ // \vcenter: Vertically center the argument group on the math axis.
10
+
11
+ defineFunction({
12
+ type: "vcenter",
13
+ names: ["\\vcenter"],
14
+ props: {
15
+ numArgs: 1,
16
+ argTypes: ["original"], // In LaTeX, \vcenter can act only on a box.
17
+ allowedInText: false,
18
+ },
19
+ handler({parser}, args) {
20
+ return {
21
+ type: "vcenter",
22
+ mode: parser.mode,
23
+ body: args[0],
24
+ };
25
+ },
26
+ htmlBuilder(group, options) {
27
+ const body = html.buildGroup(group.body, options);
28
+ const axisHeight = options.fontMetrics().axisHeight;
29
+ const dy = 0.5 * ((body.height - axisHeight) - (body.depth + axisHeight));
30
+ return buildCommon.makeVList({
31
+ positionType: "shift",
32
+ positionData: dy,
33
+ children: [{type: "elem", elem: body}],
34
+ }, options);
35
+ },
36
+ mathmlBuilder(group, options) {
37
+ // There is no way to do this in MathML.
38
+ // Write a class as a breadcrumb in case some post-processor wants
39
+ // to perform a vcenter adjustment.
40
+ return new mathMLTree.MathNode(
41
+ "mpadded", [mml.buildGroup(group.body, options)], ["vcenter"]);
42
+ },
43
+ });
44
+
package/src/functions.js CHANGED
@@ -10,6 +10,7 @@ export default functions;
10
10
  import "./functions/accent";
11
11
  import "./functions/accentunder";
12
12
  import "./functions/arrow";
13
+ import "./environments/cd";
13
14
  import "./functions/char";
14
15
  import "./functions/color";
15
16
  import "./functions/cr";
@@ -21,6 +22,7 @@ import "./functions/font";
21
22
  import "./functions/genfrac";
22
23
  import "./functions/horizBrace";
23
24
  import "./functions/href";
25
+ import "./functions/hbox";
24
26
  import "./functions/html";
25
27
  import "./functions/htmlmathml";
26
28
  import "./functions/includegraphics";
@@ -47,4 +49,5 @@ import "./functions/symbolsSpacing";
47
49
  import "./functions/tag";
48
50
  import "./functions/text";
49
51
  import "./functions/underline";
52
+ import "./functions/vcenter";
50
53
  import "./functions/verb";