katex 0.16.44 → 0.16.46

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 (61) hide show
  1. package/README.md +3 -3
  2. package/contrib/copy-tex/README.md +2 -2
  3. package/contrib/mathtex-script-type/README.md +5 -5
  4. package/contrib/mathtex-script-type/mathtex-script-type.js +2 -1
  5. package/contrib/mhchem/README.md +1 -1
  6. package/contrib/render-a11y-string/render-a11y-string.ts +7 -5
  7. package/contrib/render-a11y-string/test/render-a11y-string-spec.ts +0 -1
  8. package/dist/README.md +3 -3
  9. package/dist/contrib/mathtex-script-type.js +2 -1
  10. package/dist/contrib/mathtex-script-type.min.js +1 -1
  11. package/dist/contrib/mathtex-script-type.mjs +2 -1
  12. package/dist/contrib/render-a11y-string.js +47 -8
  13. package/dist/contrib/render-a11y-string.min.js +1 -1
  14. package/dist/contrib/render-a11y-string.mjs +27 -2
  15. package/dist/katex-swap.css +5 -2
  16. package/dist/katex-swap.min.css +1 -1
  17. package/dist/katex.css +5 -2
  18. package/dist/katex.js +551 -345
  19. package/dist/katex.min.css +1 -1
  20. package/dist/katex.min.js +1 -1
  21. package/dist/katex.mjs +522 -348
  22. package/package.json +15 -15
  23. package/src/Options.ts +29 -28
  24. package/src/Parser.ts +12 -15
  25. package/src/Settings.ts +177 -60
  26. package/src/atoms.ts +33 -0
  27. package/src/buildCommon.ts +54 -46
  28. package/src/buildHTML.ts +4 -3
  29. package/src/buildMathML.ts +54 -47
  30. package/src/defineEnvironment.ts +1 -1
  31. package/src/defineFunction.ts +10 -3
  32. package/src/delimiter.ts +17 -13
  33. package/src/domTree.ts +28 -23
  34. package/src/environments/array.ts +12 -6
  35. package/src/environments/cd.ts +9 -2
  36. package/src/fontMetrics.ts +10 -23
  37. package/src/fontMetricsData.d.ts +6 -1
  38. package/src/functions/arrow.ts +4 -5
  39. package/src/functions/delimsizing.ts +22 -16
  40. package/src/functions/enclose.ts +6 -6
  41. package/src/functions/environment.ts +7 -2
  42. package/src/functions/font.ts +13 -8
  43. package/src/functions/hbox.ts +2 -2
  44. package/src/functions/horizBrace.ts +4 -6
  45. package/src/functions/math.ts +1 -0
  46. package/src/functions/op.ts +10 -5
  47. package/src/functions/smash.ts +1 -1
  48. package/src/functions/styling.ts +17 -5
  49. package/src/functions/supsub.ts +6 -3
  50. package/src/functions/text.ts +7 -3
  51. package/src/functions/vcenter.ts +3 -1
  52. package/src/parseNode.ts +7 -5
  53. package/src/stretchy.ts +14 -26
  54. package/src/styles/katex.scss +3 -1
  55. package/src/svgGeometry.ts +32 -27
  56. package/src/symbols.ts +11 -26
  57. package/src/tree.ts +11 -5
  58. package/src/types/fonts.ts +73 -0
  59. package/src/{types.ts → types/index.ts} +4 -10
  60. package/src/utils.ts +0 -1
  61. package/src/wide-character.ts +101 -55
package/dist/katex.mjs CHANGED
@@ -7,10 +7,6 @@
7
7
  * about where in the source string the problem occurred.
8
8
  */
9
9
  class ParseError extends Error {
10
- // Error start position based on passed-in Token or ParseNode.
11
-
12
- // Length of affected text based on passed-in Token or ParseNode.
13
-
14
10
  // The underlying error message without any context added.
15
11
  constructor(message,
16
12
  // The error message
@@ -50,6 +46,11 @@ class ParseError extends Error {
50
46
  }
51
47
  super(error);
52
48
  this.name = "ParseError";
49
+ this.position = void 0;
50
+ // Error start position based on passed-in Token or ParseNode.
51
+ this.length = void 0;
52
+ // Length of affected text based on passed-in Token or ParseNode.
53
+ this.rawMessage = void 0;
53
54
  Object.setPrototypeOf(this, ParseError.prototype);
54
55
  this.position = start;
55
56
  if (start != null && end != null) {
@@ -118,7 +119,6 @@ var protocolFromUrl = url => {
118
119
  // Check for possible leading protocol.
119
120
  // https://url.spec.whatwg.org/#url-parsing strips leading whitespace
120
121
  // (U+20) or C0 control (U+00-U+1F) characters.
121
- // eslint-disable-next-line no-control-regex
122
122
  var protocol = /^[\x00-\x20]*([^\\/#?]*?)(:|&#0*58|&#x0*3a|&colon)/i.exec(url);
123
123
  if (!protocol) {
124
124
  return "_relative";
@@ -230,16 +230,11 @@ var SETTINGS_SCHEMA = {
230
230
  cli: false
231
231
  }
232
232
  };
233
- function getDefaultValue(schema) {
234
- if ("default" in schema) {
235
- return schema.default;
233
+ function getImplicitDefault(type) {
234
+ if (typeof type !== 'string') {
235
+ return type.enum[0];
236
236
  }
237
- var type = schema.type;
238
- var defaultType = Array.isArray(type) ? type[0] : type;
239
- if (typeof defaultType !== 'string') {
240
- return defaultType.enum[0];
241
- }
242
- switch (defaultType) {
237
+ switch (type) {
243
238
  case 'boolean':
244
239
  return false;
245
240
  case 'string':
@@ -248,7 +243,20 @@ function getDefaultValue(schema) {
248
243
  return 0;
249
244
  case 'object':
250
245
  return {};
246
+ default:
247
+ throw new Error("Unexpected schema type; settings must declare an explicit default.");
248
+ }
249
+ }
250
+ function getDefaultValue(schema) {
251
+ if (schema.default !== undefined) {
252
+ return schema.default;
251
253
  }
254
+ var type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
255
+ return getImplicitDefault(type);
256
+ }
257
+ function applySetting(target, prop, options, schema) {
258
+ var optionValue = options[prop];
259
+ target[prop] = optionValue !== undefined ? schema.processor ? schema.processor(optionValue) : optionValue : getDefaultValue(schema);
252
260
  }
253
261
  /**
254
262
  * The main Settings object
@@ -265,13 +273,28 @@ class Settings {
265
273
  if (options === void 0) {
266
274
  options = {};
267
275
  }
276
+ this.displayMode = void 0;
277
+ this.output = void 0;
278
+ this.leqno = void 0;
279
+ this.fleqn = void 0;
280
+ this.throwOnError = void 0;
281
+ this.errorColor = void 0;
282
+ this.macros = void 0;
283
+ this.minRuleThickness = void 0;
284
+ this.colorIsTextColor = void 0;
285
+ this.strict = void 0;
286
+ this.trust = void 0;
287
+ this.maxSize = void 0;
288
+ this.maxExpand = void 0;
289
+ this.globalGroup = void 0;
268
290
  // allow null options
269
291
  options = options || {};
270
292
  for (var prop of Object.keys(SETTINGS_SCHEMA)) {
271
293
  var schema = SETTINGS_SCHEMA[prop];
272
- var optionValue = options[prop];
273
- // TODO: validate options
274
- this[prop] = optionValue !== undefined ? schema.processor ? schema.processor(optionValue) : optionValue : getDefaultValue(schema);
294
+ if (schema) {
295
+ // TODO: validate options
296
+ applySetting(this, prop, options, schema);
297
+ }
275
298
  }
276
299
  }
277
300
  /**
@@ -364,6 +387,9 @@ class Settings {
364
387
  */
365
388
  class Style {
366
389
  constructor(id, size, cramped) {
390
+ this.id = void 0;
391
+ this.size = void 0;
392
+ this.cramped = void 0;
367
393
  this.id = id;
368
394
  this.size = size;
369
395
  this.cramped = cramped;
@@ -549,6 +575,17 @@ function supportedCodepoint(codepoint) {
549
575
  * It's a storehouse of path geometry for SVG images.
550
576
  */
551
577
  // In all paths below, the viewBox-to-em scale is 1000:1.
578
+ // Second Brush Stroke
579
+ // Low resolution monitors struggle to display images in fine detail.
580
+ // So browsers apply anti-aliasing. A long straight arrow shaft therefore
581
+ // will sometimes appear as if it has a blurred edge.
582
+ // To mitigate this, these SVG files contain a second "brush-stroke" on the
583
+ // arrow shafts. That is, a second long thin rectangular SVG path has been
584
+ // written directly on top of each arrow shaft. This reinforcement causes
585
+ // some of the screen pixels to display as black instead of the anti-aliased
586
+ // gray pixel that a single path would generate. So we get arrow shafts
587
+ // whose edges appear to be sharper.
588
+ var doubleBrushStroke = svgPath => svgPath + " " + svgPath;
552
589
  var hLinePad = 80; // padding above a sqrt vinculum. Prevents image cropping.
553
590
  // The vinculum of a \sqrt can be made thicker by a KaTeX rendering option.
554
591
  // Think of variable extraVinculum as two detours in the SVG path.
@@ -627,23 +664,23 @@ var innerPath = function innerPath(name, height) {
627
664
  // The inner part of stretchy tall delimiters
628
665
  switch (name) {
629
666
  case "\u239c":
630
- return "M291 0 H417 V" + height + " H291z M291 0 H417 V" + height + " H291z";
667
+ return doubleBrushStroke("M291 0 H417 V" + height + " H291z");
631
668
  case "\u2223":
632
- return "M145 0 H188 V" + height + " H145z M145 0 H188 V" + height + " H145z";
669
+ return doubleBrushStroke("M145 0 H188 V" + height + " H145z");
633
670
  case "\u2225":
634
- return "M145 0 H188 V" + height + " H145z M145 0 H188 V" + height + " H145z" + ("M367 0 H410 V" + height + " H367z M367 0 H410 V" + height + " H367z");
671
+ return doubleBrushStroke("M145 0 H188 V" + height + " H145z") + doubleBrushStroke("M367 0 H410 V" + height + " H367z");
635
672
  case "\u239f":
636
- return "M457 0 H583 V" + height + " H457z M457 0 H583 V" + height + " H457z";
673
+ return doubleBrushStroke("M457 0 H583 V" + height + " H457z");
637
674
  case "\u23a2":
638
- return "M319 0 H403 V" + height + " H319z M319 0 H403 V" + height + " H319z";
675
+ return doubleBrushStroke("M319 0 H403 V" + height + " H319z");
639
676
  case "\u23a5":
640
- return "M263 0 H347 V" + height + " H263z M263 0 H347 V" + height + " H263z";
677
+ return doubleBrushStroke("M263 0 H347 V" + height + " H263z");
641
678
  case "\u23aa":
642
- return "M384 0 H504 V" + height + " H384z M384 0 H504 V" + height + " H384z";
679
+ return doubleBrushStroke("M384 0 H504 V" + height + " H384z");
643
680
  case "\u23d0":
644
- return "M312 0 H355 V" + height + " H312z M312 0 H355 V" + height + " H312z";
681
+ return doubleBrushStroke("M312 0 H355 V" + height + " H312z");
645
682
  case "\u2016":
646
- return "M257 0 H300 V" + height + " H257z M257 0 H300 V" + height + " H257z" + ("M478 0 H521 V" + height + " H478z M478 0 H521 V" + height + " H478z");
683
+ return doubleBrushStroke("M257 0 H300 V" + height + " H257z") + doubleBrushStroke("M478 0 H521 V" + height + " H478z");
647
684
  default:
648
685
  return "";
649
686
  }
@@ -668,13 +705,13 @@ var path = {
668
705
  leftharpoondownplus: "M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z",
669
706
  // hook is from glyph U+21A9 in font KaTeX Main
670
707
  lefthook: "M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z",
671
- leftlinesegment: "M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z",
672
- leftbracketunder: "M0 0 h120 V290 H399995 v120 H0z\nM0 0 h120 V290 H399995 v120 H0z",
673
- leftbracketover: "M0 440 h120 V150 H399995 v-120 H0z\nM0 440 h120 V150 H399995 v-120 H0z",
674
- leftmapsto: "M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z",
708
+ leftlinesegment: doubleBrushStroke("M40 281 V428 H0 V94 H40 V241 H400000 v40z"),
709
+ leftbracketunder: doubleBrushStroke("M0 0 h120 V290 H399995 v120 H0z"),
710
+ leftbracketover: doubleBrushStroke("M0 440 h120 V150 H399995 v-120 H0z"),
711
+ leftmapsto: doubleBrushStroke("M40 281 V448H0V74H40V241H400000v40z"),
675
712
  // tofrom is from glyph U+21C4 in font KaTeX AMS Regular
676
713
  leftToFrom: "M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z",
677
- longequal: "M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z",
714
+ longequal: doubleBrushStroke("M0 50 h400000 v40H0z m0 194h40000v40H0z"),
678
715
  midbrace: "M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z",
679
716
  midbraceunder: "M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z",
680
717
  oiintSize1: "M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z",
@@ -691,9 +728,9 @@ var path = {
691
728
  rightharpoondown: "M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z",
692
729
  rightharpoondownplus: "M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z",
693
730
  righthook: "M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z",
694
- rightlinesegment: "M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z",
695
- rightbracketunder: "M399995 0 h-120 V290 H0 v120 H400000z\nM399995 0 h-120 V290 H0 v120 H400000z",
696
- rightbracketover: "M399995 440 h-120 V150 H0 v-120 H399995z\nM399995 440 h-120 V150 H0 v-120 H399995z",
731
+ rightlinesegment: doubleBrushStroke("M399960 241 V94 h40 V428 h-40 V281 H0 v-40z"),
732
+ rightbracketunder: doubleBrushStroke("M399995 0 h-120 V290 H0 v120 H400000z"),
733
+ rightbracketover: doubleBrushStroke("M399995 440 h-120 V150 H0 v-120 H399995z"),
697
734
  rightToFrom: "M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z",
698
735
  // twoheadleftarrow is from glyph U+219E in font KaTeX AMS Regular
699
736
  twoheadleftarrow: "M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z",
@@ -758,6 +795,9 @@ var tallDelim = function tallDelim(label, midHeight) {
758
795
  }
759
796
  };
760
797
 
798
+ function isMathDomNode(node) {
799
+ return 'toText' in node;
800
+ }
761
801
  /**
762
802
  * This node represents a document fragment, which contains elements, but when
763
803
  * placed into the DOM doesn't have any representation itself. It only contains
@@ -766,6 +806,12 @@ var tallDelim = function tallDelim(label, midHeight) {
766
806
  class DocumentFragment {
767
807
  // Never used; needed for satisfying interface.
768
808
  constructor(children) {
809
+ this.children = void 0;
810
+ this.classes = void 0;
811
+ this.height = void 0;
812
+ this.depth = void 0;
813
+ this.maxFontSize = void 0;
814
+ this.style = void 0;
769
815
  this.children = children;
770
816
  this.classes = [];
771
817
  this.height = 0;
@@ -798,11 +844,12 @@ class DocumentFragment {
798
844
  * MathDomNode's only.
799
845
  */
800
846
  toText() {
801
- // To avoid this, we would subclass documentFragment separately for
802
- // MathML, but polyfills for subclassing is expensive per PR 1469.
803
- // TODO(ts): Only works for ChildType = MathDomNode.
804
- var toText = child => child.toText();
805
- return this.children.map(toText).join("");
847
+ return this.children.map(child => {
848
+ if (isMathDomNode(child)) {
849
+ return child.toText();
850
+ }
851
+ throw new Error("Expected MathDomNode with toText, got " + child.constructor.name);
852
+ }).join("");
806
853
  }
807
854
  }
808
855
 
@@ -930,6 +977,20 @@ var makeEm = function makeEm(n) {
930
977
  var createClass = function createClass(classes) {
931
978
  return classes.filter(cls => cls).join(" ");
932
979
  };
980
+ /**
981
+ * Serialize a CssStyle object into a semicolon-delimited inline-style string
982
+ * (hyphenating camelCase property names). Returns "" when no property is set.
983
+ */
984
+ var cssStyleToString = function cssStyleToString(style) {
985
+ var styles = "";
986
+ for (var key of Object.keys(style)) {
987
+ var value = style[key];
988
+ if (value !== undefined) {
989
+ styles += hyphenate(key) + ":" + value + ";";
990
+ }
991
+ }
992
+ return styles;
993
+ };
933
994
  var initNode = function initNode(classes, options, style) {
934
995
  this.classes = classes || [];
935
996
  this.attributes = {};
@@ -955,9 +1016,7 @@ var toNode = function toNode(tagName) {
955
1016
  // Apply the class
956
1017
  node.className = createClass(this.classes);
957
1018
  // Apply inline styles
958
- for (var key of Object.keys(this.style)) {
959
- node.style[key] = this.style[key];
960
- }
1019
+ Object.assign(node.style, this.style);
961
1020
  // Apply attributes
962
1021
  for (var attr of Object.keys(this.attributes)) {
963
1022
  node.setAttribute(attr, this.attributes[attr]);
@@ -986,11 +1045,7 @@ var toMarkup = function toMarkup(tagName) {
986
1045
  if (this.classes.length) {
987
1046
  markup += " class=\"" + escape(createClass(this.classes)) + "\"";
988
1047
  }
989
- var styles = "";
990
- // Add the styles, after hyphenation
991
- for (var key of Object.keys(this.style)) {
992
- styles += hyphenate(key) + ":" + this.style[key] + ";";
993
- }
1048
+ var styles = cssStyleToString(this.style);
994
1049
  if (styles) {
995
1050
  markup += " style=\"" + escape(styles) + "\"";
996
1051
  }
@@ -1020,6 +1075,20 @@ var toMarkup = function toMarkup(tagName) {
1020
1075
  */
1021
1076
  class Span {
1022
1077
  constructor(classes, children, options, style) {
1078
+ this.children = void 0;
1079
+ this.attributes = void 0;
1080
+ this.classes = void 0;
1081
+ this.height = void 0;
1082
+ this.depth = void 0;
1083
+ this.width = void 0;
1084
+ this.maxFontSize = void 0;
1085
+ this.style = void 0;
1086
+ /**
1087
+ * Italic correction carried over from a SymbolNode when the symbol is
1088
+ * wrapped in a vlist (e.g. \oiint / \oiiint). Read by supsub to adjust
1089
+ * subscript positioning. Only set when nonzero; use `?? 0` at read sites.
1090
+ */
1091
+ this.italic = void 0;
1023
1092
  initNode.call(this, classes, options, style);
1024
1093
  this.children = children || [];
1025
1094
  }
@@ -1047,6 +1116,13 @@ class Span {
1047
1116
  */
1048
1117
  class Anchor {
1049
1118
  constructor(href, classes, children, options) {
1119
+ this.children = void 0;
1120
+ this.attributes = void 0;
1121
+ this.classes = void 0;
1122
+ this.height = void 0;
1123
+ this.depth = void 0;
1124
+ this.maxFontSize = void 0;
1125
+ this.style = void 0;
1050
1126
  initNode.call(this, classes, options);
1051
1127
  this.children = children || [];
1052
1128
  this.setAttribute('href', href);
@@ -1069,6 +1145,13 @@ class Anchor {
1069
1145
  */
1070
1146
  class Img {
1071
1147
  constructor(src, alt, style) {
1148
+ this.src = void 0;
1149
+ this.alt = void 0;
1150
+ this.classes = void 0;
1151
+ this.height = void 0;
1152
+ this.depth = void 0;
1153
+ this.maxFontSize = void 0;
1154
+ this.style = void 0;
1072
1155
  this.alt = alt;
1073
1156
  this.src = src;
1074
1157
  this.classes = ["mord"];
@@ -1086,18 +1169,12 @@ class Img {
1086
1169
  node.alt = this.alt;
1087
1170
  node.className = "mord";
1088
1171
  // Apply inline styles
1089
- for (var key of Object.keys(this.style)) {
1090
- node.style[key] = this.style[key];
1091
- }
1172
+ Object.assign(node.style, this.style);
1092
1173
  return node;
1093
1174
  }
1094
1175
  toMarkup() {
1095
1176
  var markup = "<img src=\"" + escape(this.src) + "\"" + (" alt=\"" + escape(this.alt) + "\"");
1096
- // Add the styles, after hyphenation
1097
- var styles = "";
1098
- for (var key of Object.keys(this.style)) {
1099
- styles += hyphenate(key) + ":" + this.style[key] + ";";
1100
- }
1177
+ var styles = cssStyleToString(this.style);
1101
1178
  if (styles) {
1102
1179
  markup += " style=\"" + escape(styles) + "\"";
1103
1180
  }
@@ -1119,6 +1196,15 @@ var iCombinations = {
1119
1196
  */
1120
1197
  class SymbolNode {
1121
1198
  constructor(text, height, depth, italic, skew, width, classes, style) {
1199
+ this.text = void 0;
1200
+ this.height = void 0;
1201
+ this.depth = void 0;
1202
+ this.italic = void 0;
1203
+ this.skew = void 0;
1204
+ this.width = void 0;
1205
+ this.maxFontSize = void 0;
1206
+ this.classes = void 0;
1207
+ this.style = void 0;
1122
1208
  this.text = text;
1123
1209
  this.height = height || 0;
1124
1210
  this.depth = depth || 0;
@@ -1162,9 +1248,9 @@ class SymbolNode {
1162
1248
  span = span || document.createElement("span");
1163
1249
  span.className = createClass(this.classes);
1164
1250
  }
1165
- for (var key of Object.keys(this.style)) {
1251
+ if (Object.keys(this.style).length > 0) {
1166
1252
  span = span || document.createElement("span");
1167
- span.style[key] = this.style[key];
1253
+ Object.assign(span.style, this.style);
1168
1254
  }
1169
1255
  if (span) {
1170
1256
  span.appendChild(node);
@@ -1191,9 +1277,7 @@ class SymbolNode {
1191
1277
  if (this.italic > 0) {
1192
1278
  styles += "margin-right:" + makeEm(this.italic) + ";";
1193
1279
  }
1194
- for (var key of Object.keys(this.style)) {
1195
- styles += hyphenate(key) + ":" + this.style[key] + ";";
1196
- }
1280
+ styles += cssStyleToString(this.style);
1197
1281
  if (styles) {
1198
1282
  needsSpan = true;
1199
1283
  markup += " style=\"" + escape(styles) + "\"";
@@ -1214,6 +1298,8 @@ class SymbolNode {
1214
1298
  */
1215
1299
  class SvgNode {
1216
1300
  constructor(children, attributes) {
1301
+ this.children = void 0;
1302
+ this.attributes = void 0;
1217
1303
  this.children = children || [];
1218
1304
  this.attributes = attributes || {};
1219
1305
  }
@@ -1245,6 +1331,8 @@ class SvgNode {
1245
1331
  }
1246
1332
  class PathNode {
1247
1333
  constructor(pathName, alternate) {
1334
+ this.pathName = void 0;
1335
+ this.alternate = void 0;
1248
1336
  this.pathName = pathName;
1249
1337
  this.alternate = alternate; // Used only for \sqrt, \phase, & tall delims
1250
1338
  }
@@ -1268,6 +1356,7 @@ class PathNode {
1268
1356
  }
1269
1357
  class LineNode {
1270
1358
  constructor(attributes) {
1359
+ this.attributes = void 0;
1271
1360
  this.attributes = attributes || {};
1272
1361
  }
1273
1362
  toNode() {
@@ -3669,25 +3758,6 @@ function getGlobalMetrics(size) {
3669
3758
  * The outermost map in the table indicates what mode the symbols should be
3670
3759
  * accepted in (e.g. "math" or "text").
3671
3760
  */
3672
- // Some of these have a "-token" suffix since these are also used as `ParseNode`
3673
- // types for raw text tokens, and we want to avoid conflicts with higher-level
3674
- // `ParseNode` types. These `ParseNode`s are constructed within `Parser` by
3675
- // looking up the `symbols` map.
3676
- var ATOMS = {
3677
- "bin": 1,
3678
- "close": 1,
3679
- "inner": 1,
3680
- "open": 1,
3681
- "punct": 1,
3682
- "rel": 1
3683
- };
3684
- var NON_ATOMS = {
3685
- "accent-token": 1,
3686
- "mathord": 1,
3687
- "op-token": 1,
3688
- "spacing": 1,
3689
- "textord": 1
3690
- };
3691
3761
  var symbols = {
3692
3762
  "math": {},
3693
3763
  "text": {}
@@ -4210,8 +4280,8 @@ defineSymbol(text, main, spacing, "\u00a0", "\\ ");
4210
4280
  defineSymbol(text, main, spacing, "\u00a0", " ");
4211
4281
  defineSymbol(text, main, spacing, "\u00a0", "\\space");
4212
4282
  defineSymbol(text, main, spacing, "\u00a0", "\\nobreakspace");
4213
- defineSymbol(math, main, spacing, null, "\\nobreak");
4214
- defineSymbol(math, main, spacing, null, "\\allowbreak");
4283
+ defineSymbol(math, main, spacing, "", "\\nobreak");
4284
+ defineSymbol(math, main, spacing, "", "\\allowbreak");
4215
4285
  defineSymbol(math, main, punct, ",", ",");
4216
4286
  defineSymbol(math, main, punct, ";", ";");
4217
4287
  defineSymbol(math, ams, bin, "\u22bc", "\\barwedge", true);
@@ -4407,7 +4477,7 @@ defineSymbol(text, main, mathord, "h", "\u210E");
4407
4477
  // Mathematical Alphanumeric Symbols.
4408
4478
  // Some editors do not deal well with wide characters. So don't write the
4409
4479
  // string into this file. Instead, create the string from the surrogate pair.
4410
- var wideChar = "";
4480
+ var wideChar;
4411
4481
  for (var _i3 = 0; _i3 < letters.length; _i3++) {
4412
4482
  var _ch3 = letters.charAt(_i3);
4413
4483
  // The hex numbers in the next line are a surrogate pair.
@@ -4490,101 +4560,134 @@ for (var _i5 = 0; _i5 < extraLatin.length; _i5++) {
4490
4560
  * Function wideCharacterFont takes a wide character as input and returns
4491
4561
  * the font information necessary to render it properly.
4492
4562
  */
4563
+ var boldUpright = {
4564
+ mathClass: "mathbf",
4565
+ textClass: "textbf",
4566
+ font: "Main-Bold"
4567
+ };
4568
+ var italic = {
4569
+ mathClass: "mathnormal",
4570
+ textClass: "textit",
4571
+ font: "Math-Italic"
4572
+ };
4573
+ var boldItalic = {
4574
+ mathClass: "boldsymbol",
4575
+ textClass: "boldsymbol",
4576
+ font: "Main-BoldItalic"
4577
+ };
4578
+ var script = {
4579
+ mathClass: "mathscr",
4580
+ textClass: "textscr",
4581
+ font: "Script-Regular"
4582
+ };
4583
+ var noFont = {
4584
+ mathClass: "",
4585
+ textClass: "",
4586
+ font: ""
4587
+ };
4588
+ var fraktur = {
4589
+ mathClass: "mathfrak",
4590
+ textClass: "textfrak",
4591
+ font: "Fraktur-Regular"
4592
+ };
4593
+ var doubleStruck = {
4594
+ mathClass: "mathbb",
4595
+ textClass: "textbb",
4596
+ font: "AMS-Regular"
4597
+ };
4598
+ var boldFraktur = {
4599
+ mathClass: "mathboldfrak",
4600
+ textClass: "textboldfrak",
4601
+ font: "Fraktur-Regular"
4602
+ };
4603
+ var sansSerif = {
4604
+ mathClass: "mathsf",
4605
+ textClass: "textsf",
4606
+ font: "SansSerif-Regular"
4607
+ };
4608
+ var boldSansSerif = {
4609
+ mathClass: "mathboldsf",
4610
+ textClass: "textboldsf",
4611
+ font: "SansSerif-Bold"
4612
+ };
4613
+ var italicSansSerif = {
4614
+ mathClass: "mathitsf",
4615
+ textClass: "textitsf",
4616
+ font: "SansSerif-Italic"
4617
+ };
4618
+ var monospace = {
4619
+ mathClass: "mathtt",
4620
+ textClass: "texttt",
4621
+ font: "Typewriter-Regular"
4622
+ };
4493
4623
  /**
4494
4624
  * Data below is from https://www.unicode.org/charts/PDF/U1D400.pdf
4495
4625
  * That document sorts characters into groups by font type, say bold or italic.
4496
4626
  *
4497
- * In the arrays below, each subarray consists three elements:
4627
+ * In the arrays below, each object consists of three properties:
4498
4628
  * * The CSS class of that group when in math mode.
4499
4629
  * * The CSS class of that group when in text mode.
4500
4630
  * * The font name, so that KaTeX can get font metrics.
4501
4631
  */
4502
- var wideLatinLetterData = [["mathbf", "textbf", "Main-Bold"],
4503
- // A-Z bold upright
4504
- ["mathbf", "textbf", "Main-Bold"],
4505
- // a-z bold upright
4506
- ["mathnormal", "textit", "Math-Italic"],
4507
- // A-Z italic
4508
- ["mathnormal", "textit", "Math-Italic"],
4509
- // a-z italic
4510
- ["boldsymbol", "boldsymbol", "Main-BoldItalic"],
4511
- // A-Z bold italic
4512
- ["boldsymbol", "boldsymbol", "Main-BoldItalic"],
4513
- // a-z bold italic
4632
+ var wideLatinLetterData = [boldUpright, boldUpright,
4633
+ // A-Z, a-z
4634
+ italic, italic,
4635
+ // A-Z, a-z
4636
+ boldItalic, boldItalic,
4637
+ // A-Z, a-z
4514
4638
  // Map fancy A-Z letters to script, not calligraphic.
4515
4639
  // This aligns with unicode-math and math fonts (except Cambria Math).
4516
- ["mathscr", "textscr", "Script-Regular"],
4517
- // A-Z script
4518
- ["", "", ""],
4519
- // a-z script. No font
4520
- ["", "", ""],
4521
- // A-Z bold script. No font
4522
- ["", "", ""],
4523
- // a-z bold script. No font
4524
- ["mathfrak", "textfrak", "Fraktur-Regular"],
4525
- // A-Z Fraktur
4526
- ["mathfrak", "textfrak", "Fraktur-Regular"],
4527
- // a-z Fraktur
4528
- ["mathbb", "textbb", "AMS-Regular"],
4529
- // A-Z double-struck
4530
- ["mathbb", "textbb", "AMS-Regular"],
4531
- // k double-struck
4640
+ script, noFont,
4641
+ // A-Z script, a-z — no font
4642
+ noFont, noFont,
4643
+ // A-Z bold script, a-z bold script — no font
4644
+ fraktur, fraktur,
4645
+ // A-Z, a-z
4646
+ doubleStruck, doubleStruck,
4647
+ // A-Z double-struck, k double-struck
4532
4648
  // Note that we are using a bold font, but font metrics for regular Fraktur.
4533
- ["mathboldfrak", "textboldfrak", "Fraktur-Regular"],
4534
- // A-Z bold Fraktur
4535
- ["mathboldfrak", "textboldfrak", "Fraktur-Regular"],
4536
- // a-z bold Fraktur
4537
- ["mathsf", "textsf", "SansSerif-Regular"],
4538
- // A-Z sans-serif
4539
- ["mathsf", "textsf", "SansSerif-Regular"],
4540
- // a-z sans-serif
4541
- ["mathboldsf", "textboldsf", "SansSerif-Bold"],
4542
- // A-Z bold sans-serif
4543
- ["mathboldsf", "textboldsf", "SansSerif-Bold"],
4544
- // a-z bold sans-serif
4545
- ["mathitsf", "textitsf", "SansSerif-Italic"],
4546
- // A-Z italic sans-serif
4547
- ["mathitsf", "textitsf", "SansSerif-Italic"],
4548
- // a-z italic sans-serif
4549
- ["", "", ""],
4550
- // A-Z bold italic sans. No font
4551
- ["", "", ""],
4552
- // a-z bold italic sans. No font
4553
- ["mathtt", "texttt", "Typewriter-Regular"],
4554
- // A-Z monospace
4555
- ["mathtt", "texttt", "Typewriter-Regular"] // a-z monospace
4649
+ boldFraktur, boldFraktur,
4650
+ // A-Z, a-z
4651
+ sansSerif, sansSerif,
4652
+ // A-Z, a-z
4653
+ boldSansSerif, boldSansSerif,
4654
+ // A-Z, a-z
4655
+ italicSansSerif, italicSansSerif,
4656
+ // A-Z, a-z
4657
+ noFont, noFont,
4658
+ // A-Z bold italic sans, a-z bold italic sans - no font
4659
+ monospace, monospace // A-Z, a-z
4556
4660
  ];
4557
- var wideNumeralData = [["mathbf", "textbf", "Main-Bold"],
4558
- // 0-9 bold
4559
- ["", "", ""],
4661
+ var wideNumeralData = [boldUpright,
4662
+ // 0-9
4663
+ noFont,
4560
4664
  // 0-9 double-struck. No KaTeX font.
4561
- ["mathsf", "textsf", "SansSerif-Regular"],
4562
- // 0-9 sans-serif
4563
- ["mathboldsf", "textboldsf", "SansSerif-Bold"],
4564
- // 0-9 bold sans-serif
4565
- ["mathtt", "texttt", "Typewriter-Regular"] // 0-9 monospace
4665
+ sansSerif,
4666
+ // 0-9
4667
+ boldSansSerif,
4668
+ // 0-9
4669
+ monospace // 0-9
4566
4670
  ];
4567
- var wideCharacterFont = (wideChar, mode) => {
4671
+ var wideCharacterFont = wideChar => {
4568
4672
  // IE doesn't support codePointAt(). So work with the surrogate pair.
4569
4673
  var H = wideChar.charCodeAt(0); // high surrogate
4570
4674
  var L = wideChar.charCodeAt(1); // low surrogate
4571
4675
  var codePoint = (H - 0xD800) * 0x400 + (L - 0xDC00) + 0x10000;
4572
- var j = mode === "math" ? 0 : 1; // column index for CSS class.
4573
4676
  if (0x1D400 <= codePoint && codePoint < 0x1D6A4) {
4574
4677
  // wideLatinLetterData contains exactly 26 chars on each row.
4575
4678
  // So we can calculate the relevant row. No traverse necessary.
4576
4679
  var i = Math.floor((codePoint - 0x1D400) / 26);
4577
- return [wideLatinLetterData[i][2], wideLatinLetterData[i][j]];
4680
+ return wideLatinLetterData[i];
4578
4681
  } else if (0x1D7CE <= codePoint && codePoint <= 0x1D7FF) {
4579
4682
  // Numerals, ten per row.
4580
4683
  var _i = Math.floor((codePoint - 0x1D7CE) / 10);
4581
- return [wideNumeralData[_i][2], wideNumeralData[_i][j]];
4684
+ return wideNumeralData[_i];
4582
4685
  } else if (codePoint === 0x1D6A5 || codePoint === 0x1D6A6) {
4583
4686
  // dotless i or j
4584
- return [wideLatinLetterData[0][2], wideLatinLetterData[0][j]];
4687
+ return wideLatinLetterData[0];
4585
4688
  } else if (0x1D6A6 < codePoint && codePoint < 0x1D7CE) {
4586
4689
  // Greek letters. Not supported, yet.
4587
- return ["", ""];
4690
+ return noFont;
4588
4691
  } else {
4589
4692
  // We don't support any wide characters outside 1D400–1D7FF.
4590
4693
  throw new ParseError("Unsupported character: " + wideChar);
@@ -4596,9 +4699,7 @@ var wideCharacterFont = (wideChar, mode) => {
4596
4699
  * Looks up the given symbol in fontMetrics, after applying any symbol
4597
4700
  * replacements defined in symbol.js
4598
4701
  */
4599
- var lookupSymbol = function lookupSymbol(value,
4600
- // TODO(#963): Use a union type for this.
4601
- fontName, mode) {
4702
+ var lookupSymbol = function lookupSymbol(value, fontName, mode) {
4602
4703
  // Replace the value with its replaced value from symbol.js
4603
4704
  if (symbols[mode][value]) {
4604
4705
  var replacement = symbols[mode][value].replace;
@@ -4678,7 +4779,7 @@ var mathsym = function mathsym(value, mode, options, classes) {
4678
4779
  * depending on the symbol. Use this function instead of fontMap for font
4679
4780
  * "boldsymbol".
4680
4781
  */
4681
- var boldsymbol = function boldsymbol(value, mode, options, classes, type) {
4782
+ var boldSymbol = function boldSymbol(value, mode, type) {
4682
4783
  if (type !== "textord" && lookupSymbol(value, "Math-BoldItalic", mode).metrics) {
4683
4784
  return {
4684
4785
  fontName: "Math-BoldItalic",
@@ -4700,30 +4801,38 @@ var makeOrd = function makeOrd(group, options, type) {
4700
4801
  var mode = group.mode;
4701
4802
  var text = group.text;
4702
4803
  var classes = ["mord"];
4804
+ var {
4805
+ font,
4806
+ fontFamily,
4807
+ fontWeight,
4808
+ fontShape
4809
+ } = options;
4703
4810
  // Math mode or Old font (i.e. \rm)
4704
- var isFont = mode === "math" || mode === "text" && options.font;
4705
- var fontOrFamily = isFont ? options.font : options.fontFamily;
4811
+ var useFont = mode === "math" || mode === "text" && !!font;
4812
+ var fontOrFamily = useFont ? font : fontFamily;
4706
4813
  var wideFontName = "";
4707
4814
  var wideFontClass = "";
4708
4815
  if (text.charCodeAt(0) === 0xD835) {
4709
- [wideFontName, wideFontClass] = wideCharacterFont(text, mode);
4816
+ var wideCharData = wideCharacterFont(text);
4817
+ wideFontName = wideCharData.font;
4818
+ wideFontClass = wideCharData[mode + "Class"];
4710
4819
  }
4711
- if (wideFontName.length > 0) {
4820
+ if (wideFontName) {
4712
4821
  // surrogate pairs get special treatment
4713
4822
  return makeSymbol(text, wideFontName, mode, options, classes.concat(wideFontClass));
4714
4823
  } else if (fontOrFamily) {
4715
4824
  var fontName;
4716
4825
  var fontClasses;
4717
4826
  if (fontOrFamily === "boldsymbol") {
4718
- var fontData = boldsymbol(text, mode, options, classes, type);
4827
+ var fontData = boldSymbol(text, mode, type);
4719
4828
  fontName = fontData.fontName;
4720
4829
  fontClasses = [fontData.fontClass];
4721
- } else if (isFont) {
4722
- fontName = fontMap[fontOrFamily].fontName;
4723
- fontClasses = [fontOrFamily];
4830
+ } else if (useFont) {
4831
+ fontName = fontMap[font].fontName;
4832
+ fontClasses = [font];
4724
4833
  } else {
4725
- fontName = retrieveTextFontName(fontOrFamily, options.fontWeight, options.fontShape);
4726
- fontClasses = [fontOrFamily, options.fontWeight, options.fontShape];
4834
+ fontName = retrieveTextFontName(fontFamily, fontWeight, fontShape);
4835
+ fontClasses = [fontFamily, fontWeight, fontShape];
4727
4836
  }
4728
4837
  if (lookupSymbol(text, fontName, mode).metrics) {
4729
4838
  return makeSymbol(text, fontName, mode, options, classes.concat(fontClasses));
@@ -4740,18 +4849,18 @@ var makeOrd = function makeOrd(group, options, type) {
4740
4849
  if (type === "mathord") {
4741
4850
  return makeSymbol(text, "Math-Italic", mode, options, classes.concat(["mathnormal"]));
4742
4851
  } else if (type === "textord") {
4743
- var font = symbols[mode][text] && symbols[mode][text].font;
4744
- if (font === "ams") {
4745
- var _fontName = retrieveTextFontName("amsrm", options.fontWeight, options.fontShape);
4746
- return makeSymbol(text, _fontName, mode, options, classes.concat("amsrm", options.fontWeight, options.fontShape));
4747
- } else if (font === "main" || !font) {
4748
- var _fontName2 = retrieveTextFontName("textrm", options.fontWeight, options.fontShape);
4749
- return makeSymbol(text, _fontName2, mode, options, classes.concat(options.fontWeight, options.fontShape));
4852
+ var _font = symbols[mode][text] && symbols[mode][text].font;
4853
+ if (_font === "ams") {
4854
+ var _fontName = retrieveTextFontName("amsrm", fontWeight, fontShape);
4855
+ return makeSymbol(text, _fontName, mode, options, classes.concat("amsrm", fontWeight, fontShape));
4856
+ } else if (_font === "main" || !_font) {
4857
+ var _fontName2 = retrieveTextFontName("textrm", fontWeight, fontShape);
4858
+ return makeSymbol(text, _fontName2, mode, options, classes.concat(fontWeight, fontShape));
4750
4859
  } else {
4751
4860
  // fonts added by plugins
4752
- var _fontName3 = retrieveTextFontName(font, options.fontWeight, options.fontShape);
4861
+ var _fontName3 = retrieveTextFontName(_font, fontWeight, fontShape);
4753
4862
  // We add font name as a css class
4754
- return makeSymbol(text, _fontName3, mode, options, classes.concat(_fontName3, options.fontWeight, options.fontShape));
4863
+ return makeSymbol(text, _fontName3, mode, options, classes.concat(_fontName3, fontWeight, fontShape));
4755
4864
  }
4756
4865
  } else {
4757
4866
  throw new Error("unexpected type: " + type + " in makeOrd");
@@ -5037,8 +5146,9 @@ var makeGlue = (measurement, options) => {
5037
5146
  return rule;
5038
5147
  };
5039
5148
  // Takes font options, and returns the appropriate fontLookup name
5040
- var retrieveTextFontName = function retrieveTextFontName(fontFamily, fontWeight, fontShape) {
5041
- var baseFontName = "";
5149
+ var retrieveTextFontName = (fontFamily, fontWeight, fontShape) => {
5150
+ var baseFontName;
5151
+ var fontStylesName;
5042
5152
  switch (fontFamily) {
5043
5153
  case "amsrm":
5044
5154
  baseFontName = "AMS";
@@ -5056,12 +5166,11 @@ var retrieveTextFontName = function retrieveTextFontName(fontFamily, fontWeight,
5056
5166
  baseFontName = fontFamily;
5057
5167
  // use fonts added by a plugin
5058
5168
  }
5059
- var fontStylesName;
5060
5169
  if (fontWeight === "textbf" && fontShape === "textit") {
5061
5170
  fontStylesName = "BoldItalic";
5062
5171
  } else if (fontWeight === "textbf") {
5063
5172
  fontStylesName = "Bold";
5064
- } else if (fontWeight === "textit") {
5173
+ } else if (fontShape === "textit") {
5065
5174
  fontStylesName = "Italic";
5066
5175
  } else {
5067
5176
  fontStylesName = "Regular";
@@ -5252,12 +5361,19 @@ var _functions = {};
5252
5361
  /**
5253
5362
  * All HTML builders. Should be only used in the `define*` and the `build*ML`
5254
5363
  * functions.
5364
+ *
5365
+ * Builders for different node types are stored side by side, but
5366
+ * `HtmlBuilder<T>` is contravariant in `T`, so there is no single type
5367
+ * argument that makes storing/retrieving them typecheck. `any` is used
5368
+ * as an existential-quantifier escape hatch.
5255
5369
  */
5370
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5256
5371
  var _htmlGroupBuilders = {};
5257
5372
  /**
5258
5373
  * All MathML builders. Should be only used in the `define*` and the `build*ML`
5259
- * functions.
5374
+ * functions. See `_htmlGroupBuilders` above for the rationale behind `any`.
5260
5375
  */
5376
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5261
5377
  var _mathmlGroupBuilders = {};
5262
5378
  function defineFunction(_ref) {
5263
5379
  var {
@@ -5445,7 +5561,8 @@ var _traverseNonSpaceNodes = function traverseNonSpaceNodes(nodes, callback, pre
5445
5561
  var partialGroup = checkPartialGroup(node);
5446
5562
  if (partialGroup) {
5447
5563
  // Recursive DFS
5448
- // TODO(ts): make nodes a $ReadOnlyArray by returning a new array
5564
+ // TODO(ts): partialGroup.children is ReadonlyArray but this
5565
+ // function mutates the array (insertAfter splices into it).
5449
5566
  _traverseNonSpaceNodes(partialGroup.children, callback, prev, null, isRoot);
5450
5567
  continue;
5451
5568
  }
@@ -5528,8 +5645,8 @@ var buildGroup$1 = function buildGroup(group, options, baseOptions) {
5528
5645
  return makeSpan();
5529
5646
  }
5530
5647
  if (_htmlGroupBuilders[group.type]) {
5531
- // Call the groupBuilders function
5532
- // TODO(ts)
5648
+ // TODO(ts): groupBuilders is Record<string, HtmlBuilder<any>>;
5649
+ // a type-safe registry would need a mapped type keyed by NodeType.
5533
5650
  var groupNode = _htmlGroupBuilders[group.type](group, options);
5534
5651
  // If the size changed between the parent and the current group, account
5535
5652
  // for that size difference.
@@ -5664,6 +5781,10 @@ function newDocumentFragment(children) {
5664
5781
  */
5665
5782
  class MathNode {
5666
5783
  constructor(type, children, classes) {
5784
+ this.type = void 0;
5785
+ this.attributes = void 0;
5786
+ this.children = void 0;
5787
+ this.classes = void 0;
5667
5788
  this.type = type;
5668
5789
  this.attributes = {};
5669
5790
  this.children = children || [];
@@ -5745,6 +5866,7 @@ class MathNode {
5745
5866
  */
5746
5867
  class TextNode {
5747
5868
  constructor(text) {
5869
+ this.text = void 0;
5748
5870
  this.text = text;
5749
5871
  }
5750
5872
  /**
@@ -5777,6 +5899,8 @@ class SpaceNode {
5777
5899
  * Create a Space node with width given in CSS ems.
5778
5900
  */
5779
5901
  constructor(width) {
5902
+ this.width = void 0;
5903
+ this.character = void 0;
5780
5904
  this.width = width;
5781
5905
  // See https://www.w3.org/TR/2000/WD-MathML2-20000328/chapter6.html
5782
5906
  // for a table of space-like characters. We use Unicode
@@ -5864,56 +5988,54 @@ var makeRow = function makeRow(body) {
5864
5988
  return new MathNode("mrow", body);
5865
5989
  }
5866
5990
  };
5991
+ var mathFontVariants = {
5992
+ mathit: "italic",
5993
+ boldsymbol: group => group.type === "textord" ? "bold" : "bold-italic",
5994
+ mathbf: "bold",
5995
+ mathbb: "double-struck",
5996
+ mathsfit: "sans-serif-italic",
5997
+ mathfrak: "fraktur",
5998
+ mathscr: "script",
5999
+ mathcal: "script",
6000
+ mathsf: "sans-serif",
6001
+ mathtt: "monospace"
6002
+ };
5867
6003
  /**
5868
6004
  * Returns the math variant as a string or null if none is required.
5869
6005
  */
5870
- var getVariant = function getVariant(group, options) {
6006
+ var getVariant = (group, options) => {
5871
6007
  // Handle \text... font specifiers as best we can.
5872
6008
  // MathML has a limited list of allowable mathvariant specifiers; see
5873
6009
  // https://www.w3.org/TR/MathML3/chapter3.html#presm.commatt
5874
- if (options.fontFamily === "texttt") {
5875
- return "monospace";
5876
- } else if (options.fontFamily === "textsf") {
5877
- if (options.fontShape === "textit" && options.fontWeight === "textbf") {
5878
- return "sans-serif-bold-italic";
6010
+ if (group.mode === "text") {
6011
+ if (options.fontFamily === "texttt") {
6012
+ return "monospace";
6013
+ } else if (options.fontFamily === "textsf") {
6014
+ if (options.fontShape === "textit" && options.fontWeight === "textbf") {
6015
+ return "sans-serif-bold-italic";
6016
+ } else if (options.fontShape === "textit") {
6017
+ return "sans-serif-italic";
6018
+ } else if (options.fontWeight === "textbf") {
6019
+ return "bold-sans-serif";
6020
+ } else {
6021
+ return "sans-serif";
6022
+ }
6023
+ } else if (options.fontShape === "textit" && options.fontWeight === "textbf") {
6024
+ return "bold-italic";
5879
6025
  } else if (options.fontShape === "textit") {
5880
- return "sans-serif-italic";
6026
+ return "italic";
5881
6027
  } else if (options.fontWeight === "textbf") {
5882
- return "bold-sans-serif";
5883
- } else {
5884
- return "sans-serif";
6028
+ return "bold";
5885
6029
  }
5886
- } else if (options.fontShape === "textit" && options.fontWeight === "textbf") {
5887
- return "bold-italic";
5888
- } else if (options.fontShape === "textit") {
5889
- return "italic";
5890
- } else if (options.fontWeight === "textbf") {
5891
- return "bold";
5892
6030
  }
5893
6031
  var font = options.font;
5894
6032
  if (!font || font === "mathnormal") {
5895
6033
  return null;
5896
6034
  }
5897
6035
  var mode = group.mode;
5898
- if (font === "mathit") {
5899
- return "italic";
5900
- } else if (font === "boldsymbol") {
5901
- return group.type === "textord" ? "bold" : "bold-italic";
5902
- } else if (font === "mathbf") {
5903
- return "bold";
5904
- } else if (font === "mathbb") {
5905
- return "double-struck";
5906
- } else if (font === "mathsfit") {
5907
- return "sans-serif-italic";
5908
- } else if (font === "mathfrak") {
5909
- return "fraktur";
5910
- } else if (font === "mathscr" || font === "mathcal") {
5911
- // MathML makes no distinction between script and calligraphic
5912
- return "script";
5913
- } else if (font === "mathsf") {
5914
- return "sans-serif";
5915
- } else if (font === "mathtt") {
5916
- return "monospace";
6036
+ var mathVariant = mathFontVariants[font];
6037
+ if (mathVariant) {
6038
+ return typeof mathVariant === "function" ? mathVariant(group) : mathVariant;
5917
6039
  }
5918
6040
  var text = group.text;
5919
6041
  if (noVariantSymbols.has(text)) {
@@ -6029,11 +6151,10 @@ var buildGroup = function buildGroup(group, options) {
6029
6151
  return new MathNode("mrow");
6030
6152
  }
6031
6153
  if (_mathmlGroupBuilders[group.type]) {
6032
- // Call the groupBuilders function
6033
- // TODO(ts)
6034
- var result = _mathmlGroupBuilders[group.type](group, options);
6035
- // TODO(ts)
6036
- return result;
6154
+ // TODO(ts): MathMLBuilder returns MathDomNode but all concrete
6155
+ // builders return MathNode. Widening the return type here would
6156
+ // require updating all callers that assume MathNode.
6157
+ return _mathmlGroupBuilders[group.type](group, options);
6037
6158
  } else {
6038
6159
  throw new ParseError("Got group of unknown type: '" + group.type + "'");
6039
6160
  }
@@ -6073,8 +6194,11 @@ function buildMathML(tree, texExpression, options, isDisplayMode, forMathmlOnly)
6073
6194
  // NOTE: The span class is not typed to have <math> nodes as children, and
6074
6195
  // we don't want to make the children type more generic since the children
6075
6196
  // of span are expected to have more fields in `buildHtml` contexts.
6197
+ // The MathNode implements VirtualNode (toNode/toMarkup) which is all that
6198
+ // Span needs from its children for rendering.
6199
+ // TODO(ts): Span's child type is HtmlDomNode, but MathNode only implements
6200
+ // VirtualNode. The double-cast acknowledges this architectural limitation.
6076
6201
  var wrapperClass = forMathmlOnly ? "katex" : "katex-mathml";
6077
- // TODO(ts)
6078
6202
  return makeSpan([wrapperClass], [math]);
6079
6203
  }
6080
6204
 
@@ -6125,6 +6249,22 @@ var sizeAtStyle = function sizeAtStyle(size, style) {
6125
6249
  */
6126
6250
  class Options {
6127
6251
  constructor(data) {
6252
+ this.style = void 0;
6253
+ this.color = void 0;
6254
+ this.size = void 0;
6255
+ this.textSize = void 0;
6256
+ this.phantom = void 0;
6257
+ // A font family applies to a group of fonts (i.e. SansSerif), while a font
6258
+ // represents a specific font (i.e. SansSerif Bold).
6259
+ // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm
6260
+ this.font = void 0;
6261
+ this.fontFamily = void 0;
6262
+ this.fontWeight = void 0;
6263
+ this.fontShape = void 0;
6264
+ this.sizeMultiplier = void 0;
6265
+ this.maxSize = void 0;
6266
+ this.minRuleThickness = void 0;
6267
+ this._fontMetrics = void 0;
6128
6268
  this.style = data.style;
6129
6269
  this.color = data.color;
6130
6270
  this.size = data.size || Options.BASESIZE;
@@ -6132,8 +6272,8 @@ class Options {
6132
6272
  this.phantom = !!data.phantom;
6133
6273
  this.font = data.font || "";
6134
6274
  this.fontFamily = data.fontFamily || "";
6135
- this.fontWeight = data.fontWeight || '';
6136
- this.fontShape = data.fontShape || '';
6275
+ this.fontWeight = data.fontWeight || "";
6276
+ this.fontShape = data.fontShape || "";
6137
6277
  this.sizeMultiplier = sizeMultipliers[this.size - 1];
6138
6278
  this.maxSize = data.maxSize;
6139
6279
  this.minRuleThickness = data.minRuleThickness;
@@ -6331,9 +6471,6 @@ class Options {
6331
6471
  }
6332
6472
  }
6333
6473
  }
6334
- // A font family applies to a group of fonts (i.e. SansSerif), while a font
6335
- // represents a specific font (i.e. SansSerif Bold).
6336
- // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm
6337
6474
  /**
6338
6475
  * The base size index.
6339
6476
  */
@@ -6439,42 +6576,6 @@ var stretchyMathML = function stretchyMathML(label) {
6439
6576
  node.setAttribute("stretchy", "true");
6440
6577
  return node;
6441
6578
  };
6442
- // Many of the KaTeX SVG images have been adapted from glyphs in KaTeX fonts.
6443
- // Copyright (c) 2009-2010, Design Science, Inc. (<www.mathjax.org>)
6444
- // Copyright (c) 2014-2017 Khan Academy (<www.khanacademy.org>)
6445
- // Licensed under the SIL Open Font License, Version 1.1.
6446
- // See \nhttp://scripts.sil.org/OFL
6447
- // Very Long SVGs
6448
- // Many of the KaTeX stretchy wide elements use a long SVG image and an
6449
- // overflow: hidden tactic to achieve a stretchy image while avoiding
6450
- // distortion of arrowheads or brace corners.
6451
- // The SVG typically contains a very long (400 em) arrow.
6452
- // The SVG is in a container span that has overflow: hidden, so the span
6453
- // acts like a window that exposes only part of the SVG.
6454
- // The SVG always has a longer, thinner aspect ratio than the container span.
6455
- // After the SVG fills 100% of the height of the container span,
6456
- // there is a long arrow shaft left over. That left-over shaft is not shown.
6457
- // Instead, it is sliced off because the span's CSS has overflow: hidden.
6458
- // Thus, the reader sees an arrow that matches the subject matter width
6459
- // without distortion.
6460
- // Some functions, such as \cancel, need to vary their aspect ratio. These
6461
- // functions do not get the overflow SVG treatment.
6462
- // Second Brush Stroke
6463
- // Low resolution monitors struggle to display images in fine detail.
6464
- // So browsers apply anti-aliasing. A long straight arrow shaft therefore
6465
- // will sometimes appear as if it has a blurred edge.
6466
- // To mitigate this, these SVG files contain a second "brush-stroke" on the
6467
- // arrow shafts. That is, a second long thin rectangular SVG path has been
6468
- // written directly on top of each arrow shaft. This reinforcement causes
6469
- // some of the screen pixels to display as black instead of the anti-aliased
6470
- // gray pixel that a single path would generate. So we get arrow shafts
6471
- // whose edges appear to be sharper.
6472
- // In the katexImagesData object just below, the dimensions all
6473
- // correspond to path geometry inside the relevant SVG.
6474
- // For example, \overrightarrow uses the same arrowhead as glyph U+2192
6475
- // from the KaTeX Main font. The scaling factor is 1000.
6476
- // That is, inside the font, that arrowhead is 522 units tall, which
6477
- // corresponds to 0.522 em inside the document.
6478
6579
  var katexImagesData = {
6479
6580
  // path(s), minWidth, height, align
6480
6581
  overrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"],
@@ -6531,14 +6632,10 @@ var stretchySvg = function stretchySvg(group, options) {
6531
6632
  function buildSvgSpan_() {
6532
6633
  var viewBoxWidth = 400000; // default
6533
6634
  var label = group.label.slice(1);
6534
- if (wideAccentLabels.has(label)) {
6535
- // Each type in the `if` statement corresponds to one of the ParseNode
6536
- // types below. This narrowing is required to access `grp.base`.
6537
- // TODO(ts)
6538
- var grp = group;
6635
+ if (wideAccentLabels.has(label) && 'base' in group) {
6539
6636
  // There are four SVG images available for each function.
6540
6637
  // Choose a taller image when there are more characters.
6541
- var numChars = grp.base.type === "ordgroup" ? grp.base.body.length : 1;
6638
+ var numChars = group.base.type === "ordgroup" ? group.base.body.length : 1;
6542
6639
  var viewBoxHeight;
6543
6640
  var pathName;
6544
6641
  var _height;
@@ -6583,16 +6680,20 @@ var stretchySvg = function stretchySvg(group, options) {
6583
6680
  } else {
6584
6681
  var spans = [];
6585
6682
  var data = katexImagesData[label];
6683
+ if (!data) {
6684
+ throw new Error("No SVG data for \"" + label + "\".");
6685
+ }
6586
6686
  var [paths, _minWidth, _viewBoxHeight] = data;
6587
6687
  var _height2 = _viewBoxHeight / 1000;
6588
6688
  var numSvgChildren = paths.length;
6589
6689
  var widthClasses;
6590
6690
  var aligns;
6591
6691
  if (numSvgChildren === 1) {
6592
- // TODO(ts): All these cases must be of the 4-tuple type.
6593
- var align1 = data[3];
6692
+ if (data.length !== 4) {
6693
+ throw new Error("Expected 4-tuple for single-path SVG data \"" + label + "\".");
6694
+ }
6594
6695
  widthClasses = ["hide-tail"];
6595
- aligns = [align1];
6696
+ aligns = [data[3]];
6596
6697
  } else if (numSvgChildren === 2) {
6597
6698
  widthClasses = ["halfarrow-left", "halfarrow-right"];
6598
6699
  aligns = ["xMinYMin", "xMaxYMin"];
@@ -6689,6 +6790,34 @@ var stretchyEnclose = function stretchyEnclose(inner, label, topPad, bottomPad,
6689
6790
  return img;
6690
6791
  };
6691
6792
 
6793
+ /**
6794
+ * Small module for atom-group constants and type guard. Kept separate from
6795
+ * `symbols.ts` so that consumers (notably `contrib/render-a11y-string`) can
6796
+ * pull in `isAtom` without dragging in the ~870-line symbol tables.
6797
+ */
6798
+ // Some of these have a "-token" suffix since these are also used as `ParseNode`
6799
+ // types for raw text tokens, and we want to avoid conflicts with higher-level
6800
+ // `ParseNode` types. These `ParseNode`s are constructed within `Parser` by
6801
+ // looking up the `symbols` map.
6802
+ var ATOMS = {
6803
+ "bin": 1,
6804
+ "close": 1,
6805
+ "inner": 1,
6806
+ "open": 1,
6807
+ "punct": 1,
6808
+ "rel": 1
6809
+ };
6810
+ var NON_ATOMS = {
6811
+ "accent-token": 1,
6812
+ "mathord": 1,
6813
+ "op-token": 1,
6814
+ "spacing": 1,
6815
+ "textord": 1
6816
+ };
6817
+ function isAtom(value) {
6818
+ return value in ATOMS;
6819
+ }
6820
+
6692
6821
  /**
6693
6822
  * Asserts that the node is of the given type and returns it with stricter
6694
6823
  * typing. Throws if the node's type does not match.
@@ -7060,7 +7189,8 @@ defineFunction({
7060
7189
  }, {
7061
7190
  type: "elem",
7062
7191
  elem: arrowBody,
7063
- shift: arrowShift
7192
+ shift: arrowShift,
7193
+ wrapperClasses: ["svg-align"]
7064
7194
  }, {
7065
7195
  type: "elem",
7066
7196
  elem: lowerGroup,
@@ -7077,12 +7207,11 @@ defineFunction({
7077
7207
  }, {
7078
7208
  type: "elem",
7079
7209
  elem: arrowBody,
7080
- shift: arrowShift
7210
+ shift: arrowShift,
7211
+ wrapperClasses: ["svg-align"]
7081
7212
  }]
7082
7213
  });
7083
7214
  }
7084
- // TODO(ts): Replace this with passing "svg-align" into makeVList.
7085
- vlist.children[0].children[0].children[1].classes.push("svg-align");
7086
7215
  return makeSpan(["mrel", "x-arrow"], [vlist], options);
7087
7216
  },
7088
7217
  mathmlBuilder(group, options) {
@@ -7317,7 +7446,8 @@ var newCell = () => {
7317
7446
  type: "styling",
7318
7447
  body: [],
7319
7448
  mode: "math",
7320
- style: "display"
7449
+ style: "display",
7450
+ resetFont: true
7321
7451
  };
7322
7452
  };
7323
7453
  var isStartOfArrow = node => {
@@ -7379,7 +7509,6 @@ function parseCD(parser) {
7379
7509
  parser.gullet.macros.set("\\cr", "\\\\\\relax");
7380
7510
  parser.gullet.beginGroup();
7381
7511
  while (true) {
7382
- // eslint-disable-line no-constant-condition
7383
7512
  // Get the parse nodes for the next row.
7384
7513
  parsedRows.push(parser.parseExpression(false, "\\\\"));
7385
7514
  parser.gullet.endGroup();
@@ -7463,7 +7592,9 @@ function parseCD(parser) {
7463
7592
  type: "styling",
7464
7593
  body: [arrow],
7465
7594
  mode: "math",
7466
- style: "display" // CD is always displaystyle.
7595
+ style: "display",
7596
+ // CD is always displaystyle.
7597
+ resetFont: true
7467
7598
  };
7468
7599
  row.push(wrappedArrow);
7469
7600
  // In CD's syntax, cells are implicit. That is, everything that
@@ -8340,9 +8471,9 @@ var makeSqrtImage = function makeSqrtImage(height, options) {
8340
8471
  var extraVinculum = Math.max(0, options.minRuleThickness - options.fontMetrics().sqrtRuleThickness);
8341
8472
  // Create a span containing an SVG image of a sqrt symbol.
8342
8473
  var span;
8343
- var spanHeight = 0;
8344
- var texHeight = 0;
8345
- var viewBoxHeight = 0;
8474
+ var spanHeight;
8475
+ var texHeight;
8476
+ var viewBoxHeight;
8346
8477
  var advanceWidth;
8347
8478
  // We create viewBoxes with 80 units of "padding" above each surd.
8348
8479
  // Then browser rounding error on the parent span height will not
@@ -8660,6 +8791,9 @@ var delimiterSizes = {
8660
8791
  }
8661
8792
  };
8662
8793
  var delimiters = new Set(["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "<", ">", "\\langle", "\u27e8", "\\rangle", "\u27e9", "\\lt", "\\gt", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1", "/", "\\backslash", "|", "\\vert", "\\|", "\\Vert", "\\uparrow", "\\Uparrow", "\\downarrow", "\\Downarrow", "\\updownarrow", "\\Updownarrow", "."]);
8794
+ function isMiddleDelimNode(node) {
8795
+ return 'isMiddle' in node;
8796
+ }
8663
8797
  // Delimiter functions
8664
8798
  function checkDelimiter(delim, context) {
8665
8799
  var symDelim = checkSymbolNodeType(delim);
@@ -8782,10 +8916,8 @@ defineFunction({
8782
8916
  var hadMiddle = false;
8783
8917
  // Calculate its height and depth
8784
8918
  for (var i = 0; i < inner.length; i++) {
8785
- // Property `isMiddle` not defined on `span`. See comment in
8786
- // "middle"'s htmlBuilder.
8787
- // TODO(ts)
8788
- if (inner[i].isMiddle) {
8919
+ var node = inner[i];
8920
+ if (isMiddleDelimNode(node)) {
8789
8921
  hadMiddle = true;
8790
8922
  } else {
8791
8923
  innerHeight = Math.max(inner[i].height, innerHeight);
@@ -8812,11 +8944,8 @@ defineFunction({
8812
8944
  if (hadMiddle) {
8813
8945
  for (var _i = 1; _i < inner.length; _i++) {
8814
8946
  var middleDelim = inner[_i];
8815
- // Property `isMiddle` not defined on `span`. See comment in
8816
- // "middle"'s htmlBuilder.
8817
- // TODO(ts)
8818
- var isMiddle = middleDelim.isMiddle;
8819
- if (isMiddle) {
8947
+ if (isMiddleDelimNode(middleDelim)) {
8948
+ var isMiddle = middleDelim.isMiddle;
8820
8949
  // Apply the options that were active when \middle was called
8821
8950
  inner[_i] = makeLeftRightDelim(isMiddle.delim, innerHeight, innerDepth, isMiddle.options, group.mode, []);
8822
8951
  }
@@ -8877,16 +9006,14 @@ defineFunction({
8877
9006
  middleDelim = makeNullDelimiter(options, []);
8878
9007
  } else {
8879
9008
  middleDelim = makeSizedDelim(group.delim, 1, options, group.mode, []);
8880
- var isMiddle = {
9009
+ // Patch an ad-hoc property onto the node so the \left/\right
9010
+ // builder can reconstruct appropriately sized middle delimiters.
9011
+ // isMiddle is not part of HtmlDomNode; the read side uses
9012
+ // isMiddleDelimNode() to check before accessing.
9013
+ middleDelim.isMiddle = {
8881
9014
  delim: group.delim,
8882
9015
  options
8883
9016
  };
8884
- // Property `isMiddle` not defined on `span`. It is only used in
8885
- // this file above.
8886
- // TODO: Fix this violation of the `span` type and possibly rename
8887
- // things since `isMiddle` sounds like a boolean, but is a struct.
8888
- // TODO(ts)
8889
- middleDelim.isMiddle = isMiddle;
8890
9017
  }
8891
9018
  return middleDelim;
8892
9019
  },
@@ -8914,7 +9041,7 @@ var htmlBuilder$7 = (group, options) => {
8914
9041
  var label = group.label.slice(1);
8915
9042
  var scale = options.sizeMultiplier;
8916
9043
  var img;
8917
- var imgShift = 0;
9044
+ var imgShift;
8918
9045
  // In the LaTeX cancel package, line geometry is slightly different
8919
9046
  // depending on whether the subject is wider than it is tall, or vice versa.
8920
9047
  // We don't know the width of a group, so as a proxy, we test if
@@ -8966,8 +9093,8 @@ var htmlBuilder$7 = (group, options) => {
8966
9093
  inner.classes.push("boxpad");
8967
9094
  }
8968
9095
  // Add vertical padding
8969
- var topPad = 0;
8970
- var bottomPad = 0;
9096
+ var topPad;
9097
+ var bottomPad;
8971
9098
  var ruleThickness = 0;
8972
9099
  // ref: cancel package: \advance\totalheight2\p@ % "+2"
8973
9100
  if (/box/.test(label)) {
@@ -9048,7 +9175,7 @@ var htmlBuilder$7 = (group, options) => {
9048
9175
  }
9049
9176
  };
9050
9177
  var mathmlBuilder$6 = (group, options) => {
9051
- var fboxsep = 0;
9178
+ var fboxsep;
9052
9179
  var node = new MathNode(group.label.includes("colorbox") ? "mpadded" : "menclose", [buildGroup(group.body, options)]);
9053
9180
  switch (group.label) {
9054
9181
  case "\\cancel":
@@ -9100,7 +9227,7 @@ defineFunction({
9100
9227
  props: {
9101
9228
  numArgs: 2,
9102
9229
  allowedInText: true,
9103
- argTypes: ["color", "text"]
9230
+ argTypes: ["color", "hbox"]
9104
9231
  },
9105
9232
  handler(_ref, args, optArgs) {
9106
9233
  var {
@@ -9126,7 +9253,7 @@ defineFunction({
9126
9253
  props: {
9127
9254
  numArgs: 3,
9128
9255
  allowedInText: true,
9129
- argTypes: ["color", "color", "text"]
9256
+ argTypes: ["color", "color", "hbox"]
9130
9257
  },
9131
9258
  handler(_ref2, args, optArgs) {
9132
9259
  var {
@@ -9290,11 +9417,14 @@ function defineMacro(name, body) {
9290
9417
  * This object is immutable.
9291
9418
  */
9292
9419
  class SourceLocation {
9293
- // The + prefix indicates that these fields aren't writeable
9294
- // Lexer holding the input string.
9295
- // Start offset, zero-based inclusive.
9296
9420
  // End offset, zero-based exclusive.
9297
9421
  constructor(lexer, start, end) {
9422
+ // The + prefix indicates that these fields aren't writeable
9423
+ this.lexer = void 0;
9424
+ // Lexer holding the input string.
9425
+ this.start = void 0;
9426
+ // Start offset, zero-based inclusive.
9427
+ this.end = void 0;
9298
9428
  this.lexer = lexer;
9299
9429
  this.start = start;
9300
9430
  this.end = end;
@@ -9332,11 +9462,15 @@ class SourceLocation {
9332
9462
  * lead to degraded error reporting, though.
9333
9463
  */
9334
9464
  class Token {
9335
- // don't expand the token
9336
9465
  // used in \noexpand
9337
9466
  constructor(text,
9338
9467
  // the text of this token
9339
9468
  loc) {
9469
+ this.text = void 0;
9470
+ this.loc = void 0;
9471
+ this.noexpand = void 0;
9472
+ // don't expand the token
9473
+ this.treatAsRelax = void 0;
9340
9474
  this.text = text;
9341
9475
  this.loc = loc;
9342
9476
  }
@@ -9457,7 +9591,6 @@ function parseArray(parser, _ref, style) {
9457
9591
  // Test for \hline at the top of the array.
9458
9592
  hLinesBeforeRow.push(getHLines(parser));
9459
9593
  while (true) {
9460
- // eslint-disable-line no-constant-condition
9461
9594
  // Parse each cell in its own group (namespace)
9462
9595
  var cellBody = parser.parseExpression(false, singleRow ? "\\end" : "\\\\");
9463
9596
  parser.gullet.endGroup();
@@ -9472,6 +9605,7 @@ function parseArray(parser, _ref, style) {
9472
9605
  type: "styling",
9473
9606
  mode: parser.mode,
9474
9607
  style,
9608
+ resetFont: true,
9475
9609
  body: [cell]
9476
9610
  };
9477
9611
  }
@@ -9606,7 +9740,12 @@ var htmlBuilder$6 = function htmlBuilder(group, options) {
9606
9740
  if (nc < inrow.length) {
9607
9741
  nc = inrow.length;
9608
9742
  }
9609
- var outrow = new Array(inrow.length);
9743
+ var outrow = {
9744
+ cells: new Array(inrow.length),
9745
+ height: 0,
9746
+ depth: 0,
9747
+ pos: 0
9748
+ };
9610
9749
  for (c = 0; c < inrow.length; ++c) {
9611
9750
  var elt = buildGroup$1(inrow[c], options);
9612
9751
  if (depth < elt.depth) {
@@ -9615,7 +9754,7 @@ var htmlBuilder$6 = function htmlBuilder(group, options) {
9615
9754
  if (height < elt.height) {
9616
9755
  height = elt.height;
9617
9756
  }
9618
- outrow[c] = elt;
9757
+ outrow.cells[c] = elt;
9619
9758
  }
9620
9759
  var rowGap = group.rowGaps[r];
9621
9760
  var gap = 0;
@@ -9730,7 +9869,7 @@ var htmlBuilder$6 = function htmlBuilder(group, options) {
9730
9869
  var colElems = [];
9731
9870
  for (r = 0; r < nr; ++r) {
9732
9871
  var row = body[r];
9733
- var elem = row[c];
9872
+ var elem = row.cells[c];
9734
9873
  if (!elem) {
9735
9874
  continue;
9736
9875
  }
@@ -10381,7 +10520,10 @@ defineFunction({
10381
10520
  if (end.name !== envName) {
10382
10521
  throw new ParseError("Mismatch: \\begin{" + envName + "} matched by \\end{" + end.name + "}", endNameToken);
10383
10522
  }
10384
- // TODO(ts), "environment" handler returns an environment ParseNode
10523
+ // env.handler returns the specific node type (e.g. "array"),
10524
+ // not "environment". This cast is unavoidable: defineFunction
10525
+ // requires the handler to return ParseNode<"environment"> but
10526
+ // \begin delegates to environment handlers with different types.
10385
10527
  return result;
10386
10528
  }
10387
10529
  return {
@@ -10407,8 +10549,7 @@ var mathmlBuilder$4 = (group, options) => {
10407
10549
  var fontAliases = {
10408
10550
  "\\Bbb": "\\mathbb",
10409
10551
  "\\bold": "\\mathbf",
10410
- "\\frak": "\\mathfrak",
10411
- "\\bm": "\\boldsymbol"
10552
+ "\\frak": "\\mathfrak"
10412
10553
  };
10413
10554
  defineFunction({
10414
10555
  type: "font",
@@ -10488,11 +10629,10 @@ defineFunction({
10488
10629
  mode
10489
10630
  } = parser;
10490
10631
  var body = parser.parseExpression(true, breakOnTokenText);
10491
- var style = "math" + funcName.slice(1);
10492
10632
  return {
10493
10633
  type: "font",
10494
10634
  mode: mode,
10495
- font: style,
10635
+ font: "math" + funcName.slice(1),
10496
10636
  body: {
10497
10637
  type: "ordgroup",
10498
10638
  mode: parser.mode,
@@ -10947,18 +11087,18 @@ var htmlBuilder$3 = (grp, options) => {
10947
11087
  size: 0.1
10948
11088
  }, {
10949
11089
  type: "elem",
10950
- elem: braceBody
11090
+ elem: braceBody,
11091
+ wrapperClasses: ["svg-align"]
10951
11092
  }]
10952
11093
  });
10953
- // TODO(ts): Replace this with passing "svg-align" into makeVList.
10954
- vlist.children[0].children[0].children[1].classes.push("svg-align");
10955
11094
  } else {
10956
11095
  vlist = makeVList({
10957
11096
  positionType: "bottom",
10958
11097
  positionData: body.depth + 0.1 + braceBody.height,
10959
11098
  children: [{
10960
11099
  type: "elem",
10961
- elem: braceBody
11100
+ elem: braceBody,
11101
+ wrapperClasses: ["svg-align"]
10962
11102
  }, {
10963
11103
  type: "kern",
10964
11104
  size: 0.1
@@ -10967,8 +11107,6 @@ var htmlBuilder$3 = (grp, options) => {
10967
11107
  elem: body
10968
11108
  }]
10969
11109
  });
10970
- // TODO(ts): Replace this with passing "svg-align" into makeVList.
10971
- vlist.children[0].children[0].children[0].classes.push("svg-align");
10972
11110
  }
10973
11111
  if (supSubGroup) {
10974
11112
  // To write the supsub, wrap the first vlist in another vlist:
@@ -11150,11 +11288,11 @@ defineFunction({
11150
11288
  };
11151
11289
  },
11152
11290
  htmlBuilder(group, options) {
11153
- var elements = buildExpression$1(group.body, options, false);
11291
+ var elements = buildExpression$1(group.body, options.withFont(''), false);
11154
11292
  return makeFragment(elements);
11155
11293
  },
11156
11294
  mathmlBuilder(group, options) {
11157
- return new MathNode("mrow", buildExpression(group.body, options));
11295
+ return new MathNode("mrow", buildExpression(group.body, options.withFont('')));
11158
11296
  }
11159
11297
  });
11160
11298
 
@@ -11558,6 +11696,7 @@ defineFunction({
11558
11696
  type: "styling",
11559
11697
  mode: parser.mode,
11560
11698
  style: "text",
11699
+ resetFont: true,
11561
11700
  body
11562
11701
  };
11563
11702
  }
@@ -11767,6 +11906,9 @@ var htmlBuilder$2 = (grp, options) => {
11767
11906
  large = true;
11768
11907
  }
11769
11908
  var base;
11909
+ // Italic correction from the symbol glyph, captured before the symbol
11910
+ // may be wrapped in a vlist (for \oiint/\oiiint). Stays 0 for non-symbol ops.
11911
+ var symbolItalic;
11770
11912
  if (group.symbol) {
11771
11913
  // If this is a symbol, create the symbol.
11772
11914
  var fontName = large ? "Size2-Regular" : "Size1-Regular";
@@ -11778,10 +11920,10 @@ var htmlBuilder$2 = (grp, options) => {
11778
11920
  group.name = stash === "oiint" ? "\\iint" : "\\iiint";
11779
11921
  }
11780
11922
  base = makeSymbol(group.name, fontName, "math", options, ["mop", "op-symbol", large ? "large-op" : "small-op"]);
11923
+ symbolItalic = base.italic;
11781
11924
  if (stash.length > 0) {
11782
11925
  // We're in \oiint or \oiiint. Overlay the oval.
11783
11926
  // TODO: When font glyphs are available, delete this code.
11784
- var italic = base.italic;
11785
11927
  var oval = staticSvg(stash + "Size" + (large ? "2" : "1"), options);
11786
11928
  base = makeVList({
11787
11929
  positionType: "individualShift",
@@ -11797,8 +11939,9 @@ var htmlBuilder$2 = (grp, options) => {
11797
11939
  });
11798
11940
  group.name = "\\" + stash;
11799
11941
  base.classes.unshift("mop");
11800
- // TODO(ts)
11801
- base.italic = italic;
11942
+ // Carry the italic correction from the original symbol to the
11943
+ // vlist wrapper so supsub can use it for subscript positioning.
11944
+ base.italic = symbolItalic;
11802
11945
  }
11803
11946
  } else if (group.body) {
11804
11947
  // If this is a list, compose that list.
@@ -11822,6 +11965,7 @@ var htmlBuilder$2 = (grp, options) => {
11822
11965
  var baseShift = 0;
11823
11966
  var slant = 0;
11824
11967
  if ((base instanceof SymbolNode || group.name === "\\oiint" || group.name === "\\oiiint") && !group.suppressBaseShift) {
11968
+ var _base$italic;
11825
11969
  // We suppress the shift of the base of \overset and \underset. Otherwise,
11826
11970
  // shift the symbol so its center lies on the axis (rule 13). It
11827
11971
  // appears that our fonts have the centers of the symbols already
@@ -11830,8 +11974,9 @@ var htmlBuilder$2 = (grp, options) => {
11830
11974
  // the vlist creation or separately when there are no limits.
11831
11975
  baseShift = (base.height - base.depth) / 2 - options.fontMetrics().axisHeight;
11832
11976
  // The slant of the symbol is just its italic correction.
11833
- // TODO(ts)
11834
- slant = base.italic || 0;
11977
+ // SymbolNode carries .italic natively; Span (for \oiint/\oiiint)
11978
+ // only has it set when nonzero, so default to 0.
11979
+ slant = (_base$italic = base.italic) != null ? _base$italic : 0;
11835
11980
  }
11836
11981
  if (hasLimits) {
11837
11982
  return assembleSupSub(base, supGroup, subGroup, options, style, slant, baseShift);
@@ -12495,7 +12640,7 @@ defineFunction({
12495
12640
  // Optional [tb] argument is engaged.
12496
12641
  // ref: amsmath: \renewcommand{\smash}[1][tb]{%
12497
12642
  // def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}%
12498
- var letter = "";
12643
+ var letter;
12499
12644
  for (var i = 0; i < tbArg.body.length; ++i) {
12500
12645
  var node = tbArg.body[i];
12501
12646
  letter = assertSymbolNodeType(node).text;
@@ -12689,6 +12834,9 @@ var styleMap = {
12689
12834
  "script": Style$1.SCRIPT,
12690
12835
  "scriptscript": Style$1.SCRIPTSCRIPT
12691
12836
  };
12837
+ function isStyleStr(s) {
12838
+ return s in styleMap;
12839
+ }
12692
12840
  defineFunction({
12693
12841
  type: "styling",
12694
12842
  names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"],
@@ -12707,8 +12855,10 @@ defineFunction({
12707
12855
  var body = parser.parseExpression(true, breakOnTokenText);
12708
12856
  // TODO: Refactor to avoid duplicating styleMap in multiple places (e.g.
12709
12857
  // here and in buildHTML and de-dupe the enumeration of all the styles).
12710
- // TODO(ts): The names above exactly match the styles.
12711
12858
  var style = funcName.slice(1, funcName.length - 5);
12859
+ if (!isStyleStr(style)) {
12860
+ throw new Error("Unknown style: " + style);
12861
+ }
12712
12862
  return {
12713
12863
  type: "styling",
12714
12864
  mode: parser.mode,
@@ -12721,13 +12871,19 @@ defineFunction({
12721
12871
  htmlBuilder(group, options) {
12722
12872
  // Style changes are handled in the TeXbook on pg. 442, Rule 3.
12723
12873
  var newStyle = styleMap[group.style];
12724
- var newOptions = options.havingStyle(newStyle).withFont('');
12874
+ var newOptions = options.havingStyle(newStyle);
12875
+ if (group.resetFont) {
12876
+ newOptions = newOptions.withFont('');
12877
+ }
12725
12878
  return sizingGroup(group.body, newOptions, options);
12726
12879
  },
12727
12880
  mathmlBuilder(group, options) {
12728
12881
  // Figure out what style we're changing to.
12729
12882
  var newStyle = styleMap[group.style];
12730
12883
  var newOptions = options.havingStyle(newStyle);
12884
+ if (group.resetFont) {
12885
+ newOptions = newOptions.withFont('');
12886
+ }
12731
12887
  var inner = buildExpression(group.body, newOptions);
12732
12888
  var node = new MathNode("mstyle", inner);
12733
12889
  var styleAttributes = {
@@ -12831,8 +12987,10 @@ defineFunctionBuilders({
12831
12987
  // amount. Note we only do this when the base is a single symbol.
12832
12988
  var isOiint = group.base && group.base.type === "op" && group.base.name && (group.base.name === "\\oiint" || group.base.name === "\\oiiint");
12833
12989
  if (base instanceof SymbolNode || isOiint) {
12834
- // @ts-ignore
12835
- marginLeft = makeEm(-base.italic);
12990
+ var _base$italic;
12991
+ // SymbolNode has .italic natively; for \oiint/\oiiint the
12992
+ // op builder stores .italic on the wrapping Span.
12993
+ marginLeft = makeEm(-((_base$italic = base.italic) != null ? _base$italic : 0));
12836
12994
  }
12837
12995
  }
12838
12996
  var supsub;
@@ -13265,7 +13423,9 @@ defineFunction({
13265
13423
  // There is no way to do this in MathML.
13266
13424
  // Write a class as a breadcrumb in case some post-processor wants
13267
13425
  // to perform a vcenter adjustment.
13268
- return new MathNode("mpadded", [buildGroup(group.body, options)], ["vcenter"]);
13426
+ // Wrap in mrow to ensure valid MathML when placed inside mo (e.g., \mathrel)
13427
+ var mpadded = new MathNode("mpadded", [buildGroup(group.body, options)], ["vcenter"]);
13428
+ return new MathNode("mrow", [mpadded]);
13269
13429
  }
13270
13430
  });
13271
13431
 
@@ -13373,10 +13533,13 @@ combiningDiacriticalMarkString + "*") +
13373
13533
  "|" + controlSymbolRegexString + ")"); // \\, \', etc.
13374
13534
  /** Main Lexer class */
13375
13535
  class Lexer {
13376
- // Category codes. The lexer only supports comment characters (14) for now.
13377
- // MacroExpander additionally distinguishes active (13).
13378
-
13379
13536
  constructor(input, settings) {
13537
+ this.input = void 0;
13538
+ this.settings = void 0;
13539
+ this.tokenRegex = void 0;
13540
+ // Category codes. The lexer only supports comment characters (14) for now.
13541
+ // MacroExpander additionally distinguishes active (13).
13542
+ this.catcodes = void 0;
13380
13543
  // Separate accents from characters
13381
13544
  this.input = input;
13382
13545
  this.settings = settings;
@@ -13440,6 +13603,9 @@ class Namespace {
13440
13603
  if (globalMacros === void 0) {
13441
13604
  globalMacros = {};
13442
13605
  }
13606
+ this.current = void 0;
13607
+ this.builtins = void 0;
13608
+ this.undefStack = void 0;
13443
13609
  this.current = globalMacros;
13444
13610
  this.builtins = builtins;
13445
13611
  this.undefStack = [];
@@ -14451,6 +14617,12 @@ var implicitCommands = {
14451
14617
  };
14452
14618
  class MacroExpander {
14453
14619
  constructor(input, settings, mode) {
14620
+ this.settings = void 0;
14621
+ this.expansionCount = void 0;
14622
+ this.lexer = void 0;
14623
+ this.macros = void 0;
14624
+ this.stack = void 0;
14625
+ this.mode = void 0;
14454
14626
  this.settings = settings;
14455
14627
  this.expansionCount = 0;
14456
14628
  this.feed(input);
@@ -15387,6 +15559,11 @@ var unicodeSymbols = {
15387
15559
  */
15388
15560
  class Parser {
15389
15561
  constructor(input, settings) {
15562
+ this.mode = void 0;
15563
+ this.gullet = void 0;
15564
+ this.settings = void 0;
15565
+ this.leftrightDepth = void 0;
15566
+ this.nextToken = void 0;
15390
15567
  // Start in math mode
15391
15568
  this.mode = "math";
15392
15569
  // Create a new macro expander (gullet) and (indirectly via that) also a
@@ -15860,13 +16037,16 @@ class Parser {
15860
16037
  case "hbox":
15861
16038
  {
15862
16039
  // hbox argument type wraps the argument in the equivalent of
15863
- // \hbox, which is like \text but switching to \textstyle size.
16040
+ // \hbox, which is like \text but switching to \textstyle size
16041
+ // and resetting math font.
15864
16042
  var group = this.parseArgumentGroup(optional, "text");
15865
16043
  return group != null ? {
15866
16044
  type: "styling",
15867
16045
  mode: group.mode,
15868
16046
  body: [group],
15869
- style: "text" // simulate \textstyle
16047
+ style: "text",
16048
+ // simulate \textstyle
16049
+ resetFont: true
15870
16050
  } : null;
15871
16051
  }
15872
16052
  case "raw":
@@ -16220,18 +16400,15 @@ class Parser {
16220
16400
  var group = symbols[this.mode][text].group;
16221
16401
  var loc = SourceLocation.range(nucleus);
16222
16402
  var s;
16223
- if (ATOMS.hasOwnProperty(group)) {
16224
- // TODO(ts)
16225
- var family = group;
16403
+ if (isAtom(group)) {
16226
16404
  s = {
16227
16405
  type: "atom",
16228
16406
  mode: this.mode,
16229
- family,
16407
+ family: group,
16230
16408
  loc,
16231
16409
  text
16232
16410
  };
16233
16411
  } else {
16234
- // TODO(ts)
16235
16412
  s = {
16236
16413
  type: group,
16237
16414
  mode: this.mode,
@@ -16239,7 +16416,6 @@ class Parser {
16239
16416
  text
16240
16417
  };
16241
16418
  }
16242
- // TODO(ts)
16243
16419
  symbol = s;
16244
16420
  } else if (text.charCodeAt(0) >= 0x80) {
16245
16421
  // no symbol for e.g. ^
@@ -16285,12 +16461,10 @@ class Parser {
16285
16461
  label: command,
16286
16462
  isStretchy: false,
16287
16463
  isShifty: true,
16288
- // TODO(ts)
16289
16464
  base: symbol
16290
16465
  };
16291
16466
  }
16292
16467
  }
16293
- // TODO(ts)
16294
16468
  return symbol;
16295
16469
  }
16296
16470
  }
@@ -16404,7 +16578,7 @@ var renderToHTMLTree = function renderToHTMLTree(expression, options) {
16404
16578
  return renderError(error, expression, settings);
16405
16579
  }
16406
16580
  };
16407
- var version = "0.16.44";
16581
+ var version = "0.16.46";
16408
16582
  var __domTree = {
16409
16583
  Span,
16410
16584
  Anchor,