katex 0.16.45 → 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 (59) 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 +519 -315
  19. package/dist/katex.min.css +1 -1
  20. package/dist/katex.min.js +1 -1
  21. package/dist/katex.mjs +491 -320
  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/parseNode.ts +7 -5
  52. package/src/stretchy.ts +14 -14
  53. package/src/styles/katex.scss +3 -1
  54. package/src/symbols.ts +11 -26
  55. package/src/tree.ts +11 -5
  56. package/src/types/fonts.ts +73 -0
  57. package/src/{types.ts → types/index.ts} +4 -10
  58. package/src/utils.ts +0 -1
  59. package/src/wide-character.ts +101 -55
package/dist/katex.js CHANGED
@@ -49,10 +49,6 @@ __webpack_require__.d(__webpack_exports__, {
49
49
  * about where in the source string the problem occurred.
50
50
  */
51
51
  class ParseError extends Error {
52
- // Error start position based on passed-in Token or ParseNode.
53
-
54
- // Length of affected text based on passed-in Token or ParseNode.
55
-
56
52
  // The underlying error message without any context added.
57
53
 
58
54
  constructor(message,
@@ -97,6 +93,11 @@ class ParseError extends Error {
97
93
  }
98
94
  super(error);
99
95
  this.name = "ParseError";
96
+ this.position = void 0;
97
+ // Error start position based on passed-in Token or ParseNode.
98
+ this.length = void 0;
99
+ // Length of affected text based on passed-in Token or ParseNode.
100
+ this.rawMessage = void 0;
100
101
  Object.setPrototypeOf(this, ParseError.prototype);
101
102
  this.position = start;
102
103
  if (start != null && end != null) {
@@ -171,7 +172,6 @@ const protocolFromUrl = url => {
171
172
  // Check for possible leading protocol.
172
173
  // https://url.spec.whatwg.org/#url-parsing strips leading whitespace
173
174
  // (U+20) or C0 control (U+00-U+1F) characters.
174
- // eslint-disable-next-line no-control-regex
175
175
  const protocol = /^[\x00-\x20]*([^\\/#?]*?)(:|&#0*58|&#x0*3a|&colon)/i.exec(url);
176
176
  if (!protocol) {
177
177
  return "_relative";
@@ -197,6 +197,13 @@ const protocolFromUrl = url => {
197
197
 
198
198
 
199
199
 
200
+
201
+ /**
202
+ * Union of all values that appear as schema defaults, cliDefaults, or
203
+ * cliProcessor return values. StrictFunction / TrustFunction are
204
+ * option-value types, not default/schema values, so they are excluded.
205
+ */
206
+
200
207
  // TODO: automatically generate documentation
201
208
  // TODO: check all properties on Settings exist
202
209
  // TODO: check the type of a property on Settings matches
@@ -290,16 +297,11 @@ const SETTINGS_SCHEMA = {
290
297
  cli: false
291
298
  }
292
299
  };
293
- function getDefaultValue(schema) {
294
- if ("default" in schema) {
295
- return schema.default;
296
- }
297
- const type = schema.type;
298
- const defaultType = Array.isArray(type) ? type[0] : type;
299
- if (typeof defaultType !== 'string') {
300
- return defaultType.enum[0];
300
+ function getImplicitDefault(type) {
301
+ if (typeof type !== 'string') {
302
+ return type.enum[0];
301
303
  }
302
- switch (defaultType) {
304
+ switch (type) {
303
305
  case 'boolean':
304
306
  return false;
305
307
  case 'string':
@@ -308,7 +310,20 @@ function getDefaultValue(schema) {
308
310
  return 0;
309
311
  case 'object':
310
312
  return {};
313
+ default:
314
+ throw new Error("Unexpected schema type; settings must declare an explicit default.");
315
+ }
316
+ }
317
+ function getDefaultValue(schema) {
318
+ if (schema.default !== undefined) {
319
+ return schema.default;
311
320
  }
321
+ const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
322
+ return getImplicitDefault(type);
323
+ }
324
+ function applySetting(target, prop, options, schema) {
325
+ const optionValue = options[prop];
326
+ target[prop] = optionValue !== undefined ? schema.processor ? schema.processor(optionValue) : optionValue : getDefaultValue(schema);
312
327
  }
313
328
 
314
329
  /**
@@ -326,13 +341,28 @@ class Settings {
326
341
  if (options === void 0) {
327
342
  options = {};
328
343
  }
344
+ this.displayMode = void 0;
345
+ this.output = void 0;
346
+ this.leqno = void 0;
347
+ this.fleqn = void 0;
348
+ this.throwOnError = void 0;
349
+ this.errorColor = void 0;
350
+ this.macros = void 0;
351
+ this.minRuleThickness = void 0;
352
+ this.colorIsTextColor = void 0;
353
+ this.strict = void 0;
354
+ this.trust = void 0;
355
+ this.maxSize = void 0;
356
+ this.maxExpand = void 0;
357
+ this.globalGroup = void 0;
329
358
  // allow null options
330
359
  options = options || {};
331
360
  for (const prop of Object.keys(SETTINGS_SCHEMA)) {
332
361
  const schema = SETTINGS_SCHEMA[prop];
333
- const optionValue = options[prop];
334
- // TODO: validate options
335
- this[prop] = optionValue !== undefined ? schema.processor ? schema.processor(optionValue) : optionValue : getDefaultValue(schema);
362
+ if (schema) {
363
+ // TODO: validate options
364
+ applySetting(this, prop, options, schema);
365
+ }
336
366
  }
337
367
  }
338
368
 
@@ -429,6 +459,9 @@ class Settings {
429
459
  */
430
460
  class Style {
431
461
  constructor(id, size, cramped) {
462
+ this.id = void 0;
463
+ this.size = void 0;
464
+ this.cramped = void 0;
432
465
  this.id = id;
433
466
  this.size = size;
434
467
  this.cramped = cramped;
@@ -866,6 +899,10 @@ const tallDelim = function (label, midHeight) {
866
899
  ;// ./src/tree.ts
867
900
  // To ensure that all nodes have compatible signatures for these methods.
868
901
 
902
+ function isMathDomNode(node) {
903
+ return 'toText' in node;
904
+ }
905
+
869
906
  /**
870
907
  * This node represents a document fragment, which contains elements, but when
871
908
  * placed into the DOM doesn't have any representation itself. It only contains
@@ -875,6 +912,12 @@ class DocumentFragment {
875
912
  // Never used; needed for satisfying interface.
876
913
 
877
914
  constructor(children) {
915
+ this.children = void 0;
916
+ this.classes = void 0;
917
+ this.height = void 0;
918
+ this.depth = void 0;
919
+ this.maxFontSize = void 0;
920
+ this.style = void 0;
878
921
  this.children = children;
879
922
  this.classes = [];
880
923
  this.height = 0;
@@ -911,11 +954,12 @@ class DocumentFragment {
911
954
  * MathDomNode's only.
912
955
  */
913
956
  toText() {
914
- // To avoid this, we would subclass documentFragment separately for
915
- // MathML, but polyfills for subclassing is expensive per PR 1469.
916
- // TODO(ts): Only works for ChildType = MathDomNode.
917
- const toText = child => child.toText();
918
- return this.children.map(toText).join("");
957
+ return this.children.map(child => {
958
+ if (isMathDomNode(child)) {
959
+ return child.toText();
960
+ }
961
+ throw new Error("Expected MathDomNode with toText, got " + child.constructor.name);
962
+ }).join("");
919
963
  }
920
964
  }
921
965
  ;// ./src/units.ts
@@ -1054,6 +1098,21 @@ const makeEm = function (n) {
1054
1098
  const createClass = function (classes) {
1055
1099
  return classes.filter(cls => cls).join(" ");
1056
1100
  };
1101
+
1102
+ /**
1103
+ * Serialize a CssStyle object into a semicolon-delimited inline-style string
1104
+ * (hyphenating camelCase property names). Returns "" when no property is set.
1105
+ */
1106
+ const cssStyleToString = function (style) {
1107
+ let styles = "";
1108
+ for (const key of Object.keys(style)) {
1109
+ const value = style[key];
1110
+ if (value !== undefined) {
1111
+ styles += hyphenate(key) + ":" + value + ";";
1112
+ }
1113
+ }
1114
+ return styles;
1115
+ };
1057
1116
  const initNode = function (classes, options, style) {
1058
1117
  this.classes = classes || [];
1059
1118
  this.attributes = {};
@@ -1082,9 +1141,7 @@ const toNode = function (tagName) {
1082
1141
  node.className = createClass(this.classes);
1083
1142
 
1084
1143
  // Apply inline styles
1085
- for (const key of Object.keys(this.style)) {
1086
- node.style[key] = this.style[key];
1087
- }
1144
+ Object.assign(node.style, this.style);
1088
1145
 
1089
1146
  // Apply attributes
1090
1147
  for (const attr of Object.keys(this.attributes)) {
@@ -1118,12 +1175,7 @@ const toMarkup = function (tagName) {
1118
1175
  if (this.classes.length) {
1119
1176
  markup += " class=\"" + utils_escape(createClass(this.classes)) + "\"";
1120
1177
  }
1121
- let styles = "";
1122
-
1123
- // Add the styles, after hyphenation
1124
- for (const key of Object.keys(this.style)) {
1125
- styles += hyphenate(key) + ":" + this.style[key] + ";";
1126
- }
1178
+ const styles = cssStyleToString(this.style);
1127
1179
  if (styles) {
1128
1180
  markup += " style=\"" + utils_escape(styles) + "\"";
1129
1181
  }
@@ -1168,6 +1220,20 @@ const toMarkup = function (tagName) {
1168
1220
  */
1169
1221
  class Span {
1170
1222
  constructor(classes, children, options, style) {
1223
+ this.children = void 0;
1224
+ this.attributes = void 0;
1225
+ this.classes = void 0;
1226
+ this.height = void 0;
1227
+ this.depth = void 0;
1228
+ this.width = void 0;
1229
+ this.maxFontSize = void 0;
1230
+ this.style = void 0;
1231
+ /**
1232
+ * Italic correction carried over from a SymbolNode when the symbol is
1233
+ * wrapped in a vlist (e.g. \oiint / \oiiint). Read by supsub to adjust
1234
+ * subscript positioning. Only set when nonzero; use `?? 0` at read sites.
1235
+ */
1236
+ this.italic = void 0;
1171
1237
  initNode.call(this, classes, options, style);
1172
1238
  this.children = children || [];
1173
1239
  }
@@ -1197,6 +1263,13 @@ class Span {
1197
1263
  */
1198
1264
  class Anchor {
1199
1265
  constructor(href, classes, children, options) {
1266
+ this.children = void 0;
1267
+ this.attributes = void 0;
1268
+ this.classes = void 0;
1269
+ this.height = void 0;
1270
+ this.depth = void 0;
1271
+ this.maxFontSize = void 0;
1272
+ this.style = void 0;
1200
1273
  initNode.call(this, classes, options);
1201
1274
  this.children = children || [];
1202
1275
  this.setAttribute('href', href);
@@ -1220,6 +1293,13 @@ class Anchor {
1220
1293
  */
1221
1294
  class Img {
1222
1295
  constructor(src, alt, style) {
1296
+ this.src = void 0;
1297
+ this.alt = void 0;
1298
+ this.classes = void 0;
1299
+ this.height = void 0;
1300
+ this.depth = void 0;
1301
+ this.maxFontSize = void 0;
1302
+ this.style = void 0;
1223
1303
  this.alt = alt;
1224
1304
  this.src = src;
1225
1305
  this.classes = ["mord"];
@@ -1238,19 +1318,12 @@ class Img {
1238
1318
  node.className = "mord";
1239
1319
 
1240
1320
  // Apply inline styles
1241
- for (const key of Object.keys(this.style)) {
1242
- node.style[key] = this.style[key];
1243
- }
1321
+ Object.assign(node.style, this.style);
1244
1322
  return node;
1245
1323
  }
1246
1324
  toMarkup() {
1247
1325
  let markup = "<img src=\"" + utils_escape(this.src) + "\"" + (" alt=\"" + utils_escape(this.alt) + "\"");
1248
-
1249
- // Add the styles, after hyphenation
1250
- let styles = "";
1251
- for (const key of Object.keys(this.style)) {
1252
- styles += hyphenate(key) + ":" + this.style[key] + ";";
1253
- }
1326
+ const styles = cssStyleToString(this.style);
1254
1327
  if (styles) {
1255
1328
  markup += " style=\"" + utils_escape(styles) + "\"";
1256
1329
  }
@@ -1273,6 +1346,15 @@ const iCombinations = {
1273
1346
  */
1274
1347
  class SymbolNode {
1275
1348
  constructor(text, height, depth, italic, skew, width, classes, style) {
1349
+ this.text = void 0;
1350
+ this.height = void 0;
1351
+ this.depth = void 0;
1352
+ this.italic = void 0;
1353
+ this.skew = void 0;
1354
+ this.width = void 0;
1355
+ this.maxFontSize = void 0;
1356
+ this.classes = void 0;
1357
+ this.style = void 0;
1276
1358
  this.text = text;
1277
1359
  this.height = height || 0;
1278
1360
  this.depth = depth || 0;
@@ -1318,9 +1400,9 @@ class SymbolNode {
1318
1400
  span = span || document.createElement("span");
1319
1401
  span.className = createClass(this.classes);
1320
1402
  }
1321
- for (const key of Object.keys(this.style)) {
1403
+ if (Object.keys(this.style).length > 0) {
1322
1404
  span = span || document.createElement("span");
1323
- span.style[key] = this.style[key];
1405
+ Object.assign(span.style, this.style);
1324
1406
  }
1325
1407
  if (span) {
1326
1408
  span.appendChild(node);
@@ -1348,9 +1430,7 @@ class SymbolNode {
1348
1430
  if (this.italic > 0) {
1349
1431
  styles += "margin-right:" + makeEm(this.italic) + ";";
1350
1432
  }
1351
- for (const key of Object.keys(this.style)) {
1352
- styles += hyphenate(key) + ":" + this.style[key] + ";";
1353
- }
1433
+ styles += cssStyleToString(this.style);
1354
1434
  if (styles) {
1355
1435
  needsSpan = true;
1356
1436
  markup += " style=\"" + utils_escape(styles) + "\"";
@@ -1372,6 +1452,8 @@ class SymbolNode {
1372
1452
  */
1373
1453
  class SvgNode {
1374
1454
  constructor(children, attributes) {
1455
+ this.children = void 0;
1456
+ this.attributes = void 0;
1375
1457
  this.children = children || [];
1376
1458
  this.attributes = attributes || {};
1377
1459
  }
@@ -1405,6 +1487,8 @@ class SvgNode {
1405
1487
  }
1406
1488
  class PathNode {
1407
1489
  constructor(pathName, alternate) {
1490
+ this.pathName = void 0;
1491
+ this.alternate = void 0;
1408
1492
  this.pathName = pathName;
1409
1493
  this.alternate = alternate; // Used only for \sqrt, \phase, & tall delims
1410
1494
  }
@@ -1428,6 +1512,7 @@ class PathNode {
1428
1512
  }
1429
1513
  class LineNode {
1430
1514
  constructor(attributes) {
1515
+ this.attributes = void 0;
1431
1516
  this.attributes = attributes || {};
1432
1517
  }
1433
1518
  toNode() {
@@ -3551,6 +3636,12 @@ const hasHtmlDomChildren = node => node instanceof Span || node instanceof Ancho
3551
3636
  });
3552
3637
  ;// ./src/fontMetrics.ts
3553
3638
 
3639
+ // This map contains a mapping from font name and character code to character
3640
+ // metrics, including height, depth, italic correction, and skew (kern from the
3641
+ // character to the corresponding \skewchar)
3642
+ // This map is generated via `make metrics`. It should not be changed manually.
3643
+
3644
+
3554
3645
  /**
3555
3646
  * This file contains metrics regarding fonts and individual symbols. The sigma
3556
3647
  * and xi variables, as well as the metricMap map contain data extracted from
@@ -3665,12 +3756,6 @@ const sigmasAndXis = {
3665
3756
  fboxrule: [0.04, 0.04, 0.04] // 0.4 pt / ptPerEm
3666
3757
  };
3667
3758
 
3668
- // This map contains a mapping from font name and character code to character
3669
- // metrics, including height, depth, italic correction, and skew (kern from the
3670
- // character to the corresponding \skewchar)
3671
- // This map is generated via `make metrics`. It should not be changed manually.
3672
-
3673
-
3674
3759
  // These are very rough approximations. We default to Times New Roman which
3675
3760
  // should have Latin-1 and Cyrillic characters, but may not depending on the
3676
3761
  // operating system. The metrics do not account for extra height from the
@@ -3752,6 +3837,7 @@ const extraCharacterMap = {
3752
3837
  'ю': 'm',
3753
3838
  'я': 'r'
3754
3839
  };
3840
+
3755
3841
  /**
3756
3842
  * This function adds new font metrics to default metricMap
3757
3843
  * It can also override existing metrics
@@ -3849,21 +3935,7 @@ function getGlobalMetrics(size) {
3849
3935
  // types for raw text tokens, and we want to avoid conflicts with higher-level
3850
3936
  // `ParseNode` types. These `ParseNode`s are constructed within `Parser` by
3851
3937
  // looking up the `symbols` map.
3852
- const ATOMS = {
3853
- "bin": 1,
3854
- "close": 1,
3855
- "inner": 1,
3856
- "open": 1,
3857
- "punct": 1,
3858
- "rel": 1
3859
- };
3860
- const NON_ATOMS = {
3861
- "accent-token": 1,
3862
- "mathord": 1,
3863
- "op-token": 1,
3864
- "spacing": 1,
3865
- "textord": 1
3866
- };
3938
+
3867
3939
  const symbols = {
3868
3940
  "math": {},
3869
3941
  "text": {}
@@ -4409,8 +4481,8 @@ defineSymbol(symbols_text, main, spacing, "\u00a0", "\\ ");
4409
4481
  defineSymbol(symbols_text, main, spacing, "\u00a0", " ");
4410
4482
  defineSymbol(symbols_text, main, spacing, "\u00a0", "\\space");
4411
4483
  defineSymbol(symbols_text, main, spacing, "\u00a0", "\\nobreakspace");
4412
- defineSymbol(math, main, spacing, null, "\\nobreak");
4413
- defineSymbol(math, main, spacing, null, "\\allowbreak");
4484
+ defineSymbol(math, main, spacing, "", "\\nobreak");
4485
+ defineSymbol(math, main, spacing, "", "\\allowbreak");
4414
4486
  defineSymbol(math, main, punct, ",", ",");
4415
4487
  defineSymbol(math, main, punct, ";", ";");
4416
4488
  defineSymbol(math, ams, bin, "\u22bc", "\\barwedge", true);
@@ -4612,7 +4684,7 @@ defineSymbol(symbols_text, main, mathord, "h", "\u210E");
4612
4684
  // Mathematical Alphanumeric Symbols.
4613
4685
  // Some editors do not deal well with wide characters. So don't write the
4614
4686
  // string into this file. Instead, create the string from the surrogate pair.
4615
- let wideChar = "";
4687
+ let wideChar;
4616
4688
  for (let i = 0; i < letters.length; i++) {
4617
4689
  const ch = letters.charAt(i);
4618
4690
 
@@ -4701,116 +4773,136 @@ for (let i = 0; i < extraLatin.length; i++) {
4701
4773
  */
4702
4774
 
4703
4775
 
4776
+ const boldUpright = {
4777
+ mathClass: "mathbf",
4778
+ textClass: "textbf",
4779
+ font: "Main-Bold"
4780
+ };
4781
+ const italic = {
4782
+ mathClass: "mathnormal",
4783
+ textClass: "textit",
4784
+ font: "Math-Italic"
4785
+ };
4786
+ const boldItalic = {
4787
+ mathClass: "boldsymbol",
4788
+ textClass: "boldsymbol",
4789
+ font: "Main-BoldItalic"
4790
+ };
4791
+ const script = {
4792
+ mathClass: "mathscr",
4793
+ textClass: "textscr",
4794
+ font: "Script-Regular"
4795
+ };
4796
+ const noFont = {
4797
+ mathClass: "",
4798
+ textClass: "",
4799
+ font: ""
4800
+ };
4801
+ const fraktur = {
4802
+ mathClass: "mathfrak",
4803
+ textClass: "textfrak",
4804
+ font: "Fraktur-Regular"
4805
+ };
4806
+ const doubleStruck = {
4807
+ mathClass: "mathbb",
4808
+ textClass: "textbb",
4809
+ font: "AMS-Regular"
4810
+ };
4811
+ const boldFraktur = {
4812
+ mathClass: "mathboldfrak",
4813
+ textClass: "textboldfrak",
4814
+ font: "Fraktur-Regular"
4815
+ };
4816
+ const sansSerif = {
4817
+ mathClass: "mathsf",
4818
+ textClass: "textsf",
4819
+ font: "SansSerif-Regular"
4820
+ };
4821
+ const boldSansSerif = {
4822
+ mathClass: "mathboldsf",
4823
+ textClass: "textboldsf",
4824
+ font: "SansSerif-Bold"
4825
+ };
4826
+ const italicSansSerif = {
4827
+ mathClass: "mathitsf",
4828
+ textClass: "textitsf",
4829
+ font: "SansSerif-Italic"
4830
+ };
4831
+ const monospace = {
4832
+ mathClass: "mathtt",
4833
+ textClass: "texttt",
4834
+ font: "Typewriter-Regular"
4835
+ };
4704
4836
 
4705
4837
  /**
4706
4838
  * Data below is from https://www.unicode.org/charts/PDF/U1D400.pdf
4707
4839
  * That document sorts characters into groups by font type, say bold or italic.
4708
4840
  *
4709
- * In the arrays below, each subarray consists three elements:
4841
+ * In the arrays below, each object consists of three properties:
4710
4842
  * * The CSS class of that group when in math mode.
4711
4843
  * * The CSS class of that group when in text mode.
4712
4844
  * * The font name, so that KaTeX can get font metrics.
4713
4845
  */
4714
4846
 
4715
- const wideLatinLetterData = [["mathbf", "textbf", "Main-Bold"],
4716
- // A-Z bold upright
4717
- ["mathbf", "textbf", "Main-Bold"],
4718
- // a-z bold upright
4719
-
4720
- ["mathnormal", "textit", "Math-Italic"],
4721
- // A-Z italic
4722
- ["mathnormal", "textit", "Math-Italic"],
4723
- // a-z italic
4724
-
4725
- ["boldsymbol", "boldsymbol", "Main-BoldItalic"],
4726
- // A-Z bold italic
4727
- ["boldsymbol", "boldsymbol", "Main-BoldItalic"],
4728
- // a-z bold italic
4729
-
4847
+ const wideLatinLetterData = [boldUpright, boldUpright,
4848
+ // A-Z, a-z
4849
+ italic, italic,
4850
+ // A-Z, a-z
4851
+ boldItalic, boldItalic,
4852
+ // A-Z, a-z
4730
4853
  // Map fancy A-Z letters to script, not calligraphic.
4731
4854
  // This aligns with unicode-math and math fonts (except Cambria Math).
4732
- ["mathscr", "textscr", "Script-Regular"],
4733
- // A-Z script
4734
- ["", "", ""],
4735
- // a-z script. No font
4736
-
4737
- ["", "", ""],
4738
- // A-Z bold script. No font
4739
- ["", "", ""],
4740
- // a-z bold script. No font
4741
-
4742
- ["mathfrak", "textfrak", "Fraktur-Regular"],
4743
- // A-Z Fraktur
4744
- ["mathfrak", "textfrak", "Fraktur-Regular"],
4745
- // a-z Fraktur
4746
-
4747
- ["mathbb", "textbb", "AMS-Regular"],
4748
- // A-Z double-struck
4749
- ["mathbb", "textbb", "AMS-Regular"],
4750
- // k double-struck
4751
-
4855
+ script, noFont,
4856
+ // A-Z script, a-z — no font
4857
+ noFont, noFont,
4858
+ // A-Z bold script, a-z bold script — no font
4859
+ fraktur, fraktur,
4860
+ // A-Z, a-z
4861
+ doubleStruck, doubleStruck,
4862
+ // A-Z double-struck, k double-struck
4752
4863
  // Note that we are using a bold font, but font metrics for regular Fraktur.
4753
- ["mathboldfrak", "textboldfrak", "Fraktur-Regular"],
4754
- // A-Z bold Fraktur
4755
- ["mathboldfrak", "textboldfrak", "Fraktur-Regular"],
4756
- // a-z bold Fraktur
4757
-
4758
- ["mathsf", "textsf", "SansSerif-Regular"],
4759
- // A-Z sans-serif
4760
- ["mathsf", "textsf", "SansSerif-Regular"],
4761
- // a-z sans-serif
4762
-
4763
- ["mathboldsf", "textboldsf", "SansSerif-Bold"],
4764
- // A-Z bold sans-serif
4765
- ["mathboldsf", "textboldsf", "SansSerif-Bold"],
4766
- // a-z bold sans-serif
4767
-
4768
- ["mathitsf", "textitsf", "SansSerif-Italic"],
4769
- // A-Z italic sans-serif
4770
- ["mathitsf", "textitsf", "SansSerif-Italic"],
4771
- // a-z italic sans-serif
4772
-
4773
- ["", "", ""],
4774
- // A-Z bold italic sans. No font
4775
- ["", "", ""],
4776
- // a-z bold italic sans. No font
4777
-
4778
- ["mathtt", "texttt", "Typewriter-Regular"],
4779
- // A-Z monospace
4780
- ["mathtt", "texttt", "Typewriter-Regular"] // a-z monospace
4864
+ boldFraktur, boldFraktur,
4865
+ // A-Z, a-z
4866
+ sansSerif, sansSerif,
4867
+ // A-Z, a-z
4868
+ boldSansSerif, boldSansSerif,
4869
+ // A-Z, a-z
4870
+ italicSansSerif, italicSansSerif,
4871
+ // A-Z, a-z
4872
+ noFont, noFont,
4873
+ // A-Z bold italic sans, a-z bold italic sans - no font
4874
+ monospace, monospace // A-Z, a-z
4781
4875
  ];
4782
- const wideNumeralData = [["mathbf", "textbf", "Main-Bold"],
4783
- // 0-9 bold
4784
- ["", "", ""],
4876
+ const wideNumeralData = [boldUpright,
4877
+ // 0-9
4878
+ noFont,
4785
4879
  // 0-9 double-struck. No KaTeX font.
4786
- ["mathsf", "textsf", "SansSerif-Regular"],
4787
- // 0-9 sans-serif
4788
- ["mathboldsf", "textboldsf", "SansSerif-Bold"],
4789
- // 0-9 bold sans-serif
4790
- ["mathtt", "texttt", "Typewriter-Regular"] // 0-9 monospace
4880
+ sansSerif,
4881
+ // 0-9
4882
+ boldSansSerif,
4883
+ // 0-9
4884
+ monospace // 0-9
4791
4885
  ];
4792
- const wideCharacterFont = (wideChar, mode) => {
4886
+ const wideCharacterFont = wideChar => {
4793
4887
  // IE doesn't support codePointAt(). So work with the surrogate pair.
4794
4888
  const H = wideChar.charCodeAt(0); // high surrogate
4795
4889
  const L = wideChar.charCodeAt(1); // low surrogate
4796
4890
  const codePoint = (H - 0xD800) * 0x400 + (L - 0xDC00) + 0x10000;
4797
- const j = mode === "math" ? 0 : 1; // column index for CSS class.
4798
-
4799
4891
  if (0x1D400 <= codePoint && codePoint < 0x1D6A4) {
4800
4892
  // wideLatinLetterData contains exactly 26 chars on each row.
4801
4893
  // So we can calculate the relevant row. No traverse necessary.
4802
4894
  const i = Math.floor((codePoint - 0x1D400) / 26);
4803
- return [wideLatinLetterData[i][2], wideLatinLetterData[i][j]];
4895
+ return wideLatinLetterData[i];
4804
4896
  } else if (0x1D7CE <= codePoint && codePoint <= 0x1D7FF) {
4805
4897
  // Numerals, ten per row.
4806
4898
  const i = Math.floor((codePoint - 0x1D7CE) / 10);
4807
- return [wideNumeralData[i][2], wideNumeralData[i][j]];
4899
+ return wideNumeralData[i];
4808
4900
  } else if (codePoint === 0x1D6A5 || codePoint === 0x1D6A6) {
4809
4901
  // dotless i or j
4810
- return [wideLatinLetterData[0][2], wideLatinLetterData[0][j]];
4902
+ return wideLatinLetterData[0];
4811
4903
  } else if (0x1D6A6 < codePoint && codePoint < 0x1D7CE) {
4812
4904
  // Greek letters. Not supported, yet.
4813
- return ["", ""];
4905
+ return noFont;
4814
4906
  } else {
4815
4907
  // We don't support any wide characters outside 1D400–1D7FF.
4816
4908
  throw new src_ParseError("Unsupported character: " + wideChar);
@@ -4833,9 +4925,7 @@ const wideCharacterFont = (wideChar, mode) => {
4833
4925
  * Looks up the given symbol in fontMetrics, after applying any symbol
4834
4926
  * replacements defined in symbol.js
4835
4927
  */
4836
- const lookupSymbol = function (value,
4837
- // TODO(#963): Use a union type for this.
4838
- fontName, mode) {
4928
+ const lookupSymbol = function (value, fontName, mode) {
4839
4929
  // Replace the value with its replaced value from symbol.js
4840
4930
  if (src_symbols[mode][value]) {
4841
4931
  const replacement = src_symbols[mode][value].replace;
@@ -4918,7 +5008,7 @@ const mathsym = function (value, mode, options, classes) {
4918
5008
  * depending on the symbol. Use this function instead of fontMap for font
4919
5009
  * "boldsymbol".
4920
5010
  */
4921
- const boldsymbol = function (value, mode, options, classes, type) {
5011
+ const boldSymbol = function (value, mode, type) {
4922
5012
  if (type !== "textord" && lookupSymbol(value, "Math-BoldItalic", mode).metrics) {
4923
5013
  return {
4924
5014
  fontName: "Math-BoldItalic",
@@ -4941,31 +5031,39 @@ const makeOrd = function (group, options, type) {
4941
5031
  const mode = group.mode;
4942
5032
  const text = group.text;
4943
5033
  const classes = ["mord"];
5034
+ const {
5035
+ font,
5036
+ fontFamily,
5037
+ fontWeight,
5038
+ fontShape
5039
+ } = options;
4944
5040
 
4945
5041
  // Math mode or Old font (i.e. \rm)
4946
- const isFont = mode === "math" || mode === "text" && options.font;
4947
- const fontOrFamily = isFont ? options.font : options.fontFamily;
5042
+ const useFont = mode === "math" || mode === "text" && !!font;
5043
+ const fontOrFamily = useFont ? font : fontFamily;
4948
5044
  let wideFontName = "";
4949
5045
  let wideFontClass = "";
4950
5046
  if (text.charCodeAt(0) === 0xD835) {
4951
- [wideFontName, wideFontClass] = wideCharacterFont(text, mode);
5047
+ const wideCharData = wideCharacterFont(text);
5048
+ wideFontName = wideCharData.font;
5049
+ wideFontClass = wideCharData[mode + "Class"];
4952
5050
  }
4953
- if (wideFontName.length > 0) {
5051
+ if (wideFontName) {
4954
5052
  // surrogate pairs get special treatment
4955
5053
  return makeSymbol(text, wideFontName, mode, options, classes.concat(wideFontClass));
4956
5054
  } else if (fontOrFamily) {
4957
5055
  let fontName;
4958
5056
  let fontClasses;
4959
5057
  if (fontOrFamily === "boldsymbol") {
4960
- const fontData = boldsymbol(text, mode, options, classes, type);
5058
+ const fontData = boldSymbol(text, mode, type);
4961
5059
  fontName = fontData.fontName;
4962
5060
  fontClasses = [fontData.fontClass];
4963
- } else if (isFont) {
4964
- fontName = fontMap[fontOrFamily].fontName;
4965
- fontClasses = [fontOrFamily];
5061
+ } else if (useFont) {
5062
+ fontName = fontMap[font].fontName;
5063
+ fontClasses = [font];
4966
5064
  } else {
4967
- fontName = retrieveTextFontName(fontOrFamily, options.fontWeight, options.fontShape);
4968
- fontClasses = [fontOrFamily, options.fontWeight, options.fontShape];
5065
+ fontName = retrieveTextFontName(fontFamily, fontWeight, fontShape);
5066
+ fontClasses = [fontFamily, fontWeight, fontShape];
4969
5067
  }
4970
5068
  if (lookupSymbol(text, fontName, mode).metrics) {
4971
5069
  return makeSymbol(text, fontName, mode, options, classes.concat(fontClasses));
@@ -4985,16 +5083,16 @@ const makeOrd = function (group, options, type) {
4985
5083
  } else if (type === "textord") {
4986
5084
  const font = src_symbols[mode][text] && src_symbols[mode][text].font;
4987
5085
  if (font === "ams") {
4988
- const fontName = retrieveTextFontName("amsrm", options.fontWeight, options.fontShape);
4989
- return makeSymbol(text, fontName, mode, options, classes.concat("amsrm", options.fontWeight, options.fontShape));
5086
+ const fontName = retrieveTextFontName("amsrm", fontWeight, fontShape);
5087
+ return makeSymbol(text, fontName, mode, options, classes.concat("amsrm", fontWeight, fontShape));
4990
5088
  } else if (font === "main" || !font) {
4991
- const fontName = retrieveTextFontName("textrm", options.fontWeight, options.fontShape);
4992
- return makeSymbol(text, fontName, mode, options, classes.concat(options.fontWeight, options.fontShape));
5089
+ const fontName = retrieveTextFontName("textrm", fontWeight, fontShape);
5090
+ return makeSymbol(text, fontName, mode, options, classes.concat(fontWeight, fontShape));
4993
5091
  } else {
4994
5092
  // fonts added by plugins
4995
- const fontName = retrieveTextFontName(font, options.fontWeight, options.fontShape);
5093
+ const fontName = retrieveTextFontName(font, fontWeight, fontShape);
4996
5094
  // We add font name as a css class
4997
- return makeSymbol(text, fontName, mode, options, classes.concat(fontName, options.fontWeight, options.fontShape));
5095
+ return makeSymbol(text, fontName, mode, options, classes.concat(fontName, fontWeight, fontShape));
4998
5096
  }
4999
5097
  } else {
5000
5098
  throw new Error("unexpected type: " + type + " in makeOrd");
@@ -5302,8 +5400,9 @@ const makeGlue = (measurement, options) => {
5302
5400
  };
5303
5401
 
5304
5402
  // Takes font options, and returns the appropriate fontLookup name
5305
- const retrieveTextFontName = function (fontFamily, fontWeight, fontShape) {
5306
- let baseFontName = "";
5403
+ const retrieveTextFontName = (fontFamily, fontWeight, fontShape) => {
5404
+ let baseFontName;
5405
+ let fontStylesName;
5307
5406
  switch (fontFamily) {
5308
5407
  case "amsrm":
5309
5408
  baseFontName = "AMS";
@@ -5321,12 +5420,11 @@ const retrieveTextFontName = function (fontFamily, fontWeight, fontShape) {
5321
5420
  baseFontName = fontFamily;
5322
5421
  // use fonts added by a plugin
5323
5422
  }
5324
- let fontStylesName;
5325
5423
  if (fontWeight === "textbf" && fontShape === "textit") {
5326
5424
  fontStylesName = "BoldItalic";
5327
5425
  } else if (fontWeight === "textbf") {
5328
5426
  fontStylesName = "Bold";
5329
- } else if (fontWeight === "textit") {
5427
+ } else if (fontShape === "textit") {
5330
5428
  fontStylesName = "Italic";
5331
5429
  } else {
5332
5430
  fontStylesName = "Regular";
@@ -5549,13 +5647,20 @@ const _functions = {};
5549
5647
  /**
5550
5648
  * All HTML builders. Should be only used in the `define*` and the `build*ML`
5551
5649
  * functions.
5650
+ *
5651
+ * Builders for different node types are stored side by side, but
5652
+ * `HtmlBuilder<T>` is contravariant in `T`, so there is no single type
5653
+ * argument that makes storing/retrieving them typecheck. `any` is used
5654
+ * as an existential-quantifier escape hatch.
5552
5655
  */
5656
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5553
5657
  const _htmlGroupBuilders = {};
5554
5658
 
5555
5659
  /**
5556
5660
  * All MathML builders. Should be only used in the `define*` and the `build*ML`
5557
- * functions.
5661
+ * functions. See `_htmlGroupBuilders` above for the rationale behind `any`.
5558
5662
  */
5663
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5559
5664
  const _mathmlGroupBuilders = {};
5560
5665
  function defineFunction(_ref) {
5561
5666
  let {
@@ -5761,7 +5866,8 @@ const traverseNonSpaceNodes = function (nodes, callback, prev, next, isRoot) {
5761
5866
  const partialGroup = checkPartialGroup(node);
5762
5867
  if (partialGroup) {
5763
5868
  // Recursive DFS
5764
- // TODO(ts): make nodes a $ReadOnlyArray by returning a new array
5869
+ // TODO(ts): partialGroup.children is ReadonlyArray but this
5870
+ // function mutates the array (insertAfter splices into it).
5765
5871
  traverseNonSpaceNodes(partialGroup.children, callback, prev, null, isRoot);
5766
5872
  continue;
5767
5873
  }
@@ -5849,8 +5955,8 @@ const buildGroup = function (group, options, baseOptions) {
5849
5955
  return makeSpan();
5850
5956
  }
5851
5957
  if (_htmlGroupBuilders[group.type]) {
5852
- // Call the groupBuilders function
5853
- // TODO(ts)
5958
+ // TODO(ts): groupBuilders is Record<string, HtmlBuilder<any>>;
5959
+ // a type-safe registry would need a mapped type keyed by NodeType.
5854
5960
  let groupNode = _htmlGroupBuilders[group.type](group, options);
5855
5961
 
5856
5962
  // If the size changed between the parent and the current group, account
@@ -6006,6 +6112,10 @@ function newDocumentFragment(children) {
6006
6112
  */
6007
6113
  class MathNode {
6008
6114
  constructor(type, children, classes) {
6115
+ this.type = void 0;
6116
+ this.attributes = void 0;
6117
+ this.children = void 0;
6118
+ this.classes = void 0;
6009
6119
  this.type = type;
6010
6120
  this.attributes = {};
6011
6121
  this.children = children || [];
@@ -6094,6 +6204,7 @@ class MathNode {
6094
6204
  */
6095
6205
  class TextNode {
6096
6206
  constructor(text) {
6207
+ this.text = void 0;
6097
6208
  this.text = text;
6098
6209
  }
6099
6210
 
@@ -6130,6 +6241,8 @@ class SpaceNode {
6130
6241
  * Create a Space node with width given in CSS ems.
6131
6242
  */
6132
6243
  constructor(width) {
6244
+ this.width = void 0;
6245
+ this.character = void 0;
6133
6246
  this.width = width;
6134
6247
  // See https://www.w3.org/TR/2000/WD-MathML2-20000328/chapter6.html
6135
6248
  // for a table of space-like characters. We use Unicode
@@ -6229,57 +6342,55 @@ const makeRow = function (body) {
6229
6342
  return new MathNode("mrow", body);
6230
6343
  }
6231
6344
  };
6345
+ const mathFontVariants = {
6346
+ mathit: "italic",
6347
+ boldsymbol: group => group.type === "textord" ? "bold" : "bold-italic",
6348
+ mathbf: "bold",
6349
+ mathbb: "double-struck",
6350
+ mathsfit: "sans-serif-italic",
6351
+ mathfrak: "fraktur",
6352
+ mathscr: "script",
6353
+ mathcal: "script",
6354
+ mathsf: "sans-serif",
6355
+ mathtt: "monospace"
6356
+ };
6232
6357
 
6233
6358
  /**
6234
6359
  * Returns the math variant as a string or null if none is required.
6235
6360
  */
6236
- const getVariant = function (group, options) {
6361
+ const getVariant = (group, options) => {
6237
6362
  // Handle \text... font specifiers as best we can.
6238
6363
  // MathML has a limited list of allowable mathvariant specifiers; see
6239
6364
  // https://www.w3.org/TR/MathML3/chapter3.html#presm.commatt
6240
- if (options.fontFamily === "texttt") {
6241
- return "monospace";
6242
- } else if (options.fontFamily === "textsf") {
6243
- if (options.fontShape === "textit" && options.fontWeight === "textbf") {
6244
- return "sans-serif-bold-italic";
6365
+ if (group.mode === "text") {
6366
+ if (options.fontFamily === "texttt") {
6367
+ return "monospace";
6368
+ } else if (options.fontFamily === "textsf") {
6369
+ if (options.fontShape === "textit" && options.fontWeight === "textbf") {
6370
+ return "sans-serif-bold-italic";
6371
+ } else if (options.fontShape === "textit") {
6372
+ return "sans-serif-italic";
6373
+ } else if (options.fontWeight === "textbf") {
6374
+ return "bold-sans-serif";
6375
+ } else {
6376
+ return "sans-serif";
6377
+ }
6378
+ } else if (options.fontShape === "textit" && options.fontWeight === "textbf") {
6379
+ return "bold-italic";
6245
6380
  } else if (options.fontShape === "textit") {
6246
- return "sans-serif-italic";
6381
+ return "italic";
6247
6382
  } else if (options.fontWeight === "textbf") {
6248
- return "bold-sans-serif";
6249
- } else {
6250
- return "sans-serif";
6383
+ return "bold";
6251
6384
  }
6252
- } else if (options.fontShape === "textit" && options.fontWeight === "textbf") {
6253
- return "bold-italic";
6254
- } else if (options.fontShape === "textit") {
6255
- return "italic";
6256
- } else if (options.fontWeight === "textbf") {
6257
- return "bold";
6258
6385
  }
6259
6386
  const font = options.font;
6260
6387
  if (!font || font === "mathnormal") {
6261
6388
  return null;
6262
6389
  }
6263
6390
  const mode = group.mode;
6264
- if (font === "mathit") {
6265
- return "italic";
6266
- } else if (font === "boldsymbol") {
6267
- return group.type === "textord" ? "bold" : "bold-italic";
6268
- } else if (font === "mathbf") {
6269
- return "bold";
6270
- } else if (font === "mathbb") {
6271
- return "double-struck";
6272
- } else if (font === "mathsfit") {
6273
- return "sans-serif-italic";
6274
- } else if (font === "mathfrak") {
6275
- return "fraktur";
6276
- } else if (font === "mathscr" || font === "mathcal") {
6277
- // MathML makes no distinction between script and calligraphic
6278
- return "script";
6279
- } else if (font === "mathsf") {
6280
- return "sans-serif";
6281
- } else if (font === "mathtt") {
6282
- return "monospace";
6391
+ const mathVariant = mathFontVariants[font];
6392
+ if (mathVariant) {
6393
+ return typeof mathVariant === "function" ? mathVariant(group) : mathVariant;
6283
6394
  }
6284
6395
  let text = group.text;
6285
6396
  if (noVariantSymbols.has(text)) {
@@ -6399,11 +6510,10 @@ const buildMathML_buildGroup = function (group, options) {
6399
6510
  return new MathNode("mrow");
6400
6511
  }
6401
6512
  if (_mathmlGroupBuilders[group.type]) {
6402
- // Call the groupBuilders function
6403
- // TODO(ts)
6404
- const result = _mathmlGroupBuilders[group.type](group, options);
6405
- // TODO(ts)
6406
- return result;
6513
+ // TODO(ts): MathMLBuilder returns MathDomNode but all concrete
6514
+ // builders return MathNode. Widening the return type here would
6515
+ // require updating all callers that assume MathNode.
6516
+ return _mathmlGroupBuilders[group.type](group, options);
6407
6517
  } else {
6408
6518
  throw new src_ParseError("Got group of unknown type: '" + group.type + "'");
6409
6519
  }
@@ -6448,8 +6558,11 @@ function buildMathML(tree, texExpression, options, isDisplayMode, forMathmlOnly)
6448
6558
  // NOTE: The span class is not typed to have <math> nodes as children, and
6449
6559
  // we don't want to make the children type more generic since the children
6450
6560
  // of span are expected to have more fields in `buildHtml` contexts.
6561
+ // The MathNode implements VirtualNode (toNode/toMarkup) which is all that
6562
+ // Span needs from its children for rendering.
6563
+ // TODO(ts): Span's child type is HtmlDomNode, but MathNode only implements
6564
+ // VirtualNode. The double-cast acknowledges this architectural limitation.
6451
6565
  const wrapperClass = forMathmlOnly ? "katex" : "katex-mathml";
6452
- // TODO(ts)
6453
6566
  return makeSpan([wrapperClass], [math]);
6454
6567
  }
6455
6568
  ;// ./src/Options.ts
@@ -6493,9 +6606,6 @@ const sizeMultipliers = [
6493
6606
  const sizeAtStyle = function (size, style) {
6494
6607
  return style.size < 2 ? size : sizeStyleMap[size - 1][style.size - 1];
6495
6608
  };
6496
-
6497
- // In these types, "" (empty string) means "no change".
6498
-
6499
6609
  /**
6500
6610
  * This is the main options class. It contains the current style, size, color,
6501
6611
  * and font.
@@ -6505,6 +6615,22 @@ const sizeAtStyle = function (size, style) {
6505
6615
  */
6506
6616
  class Options {
6507
6617
  constructor(data) {
6618
+ this.style = void 0;
6619
+ this.color = void 0;
6620
+ this.size = void 0;
6621
+ this.textSize = void 0;
6622
+ this.phantom = void 0;
6623
+ // A font family applies to a group of fonts (i.e. SansSerif), while a font
6624
+ // represents a specific font (i.e. SansSerif Bold).
6625
+ // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm
6626
+ this.font = void 0;
6627
+ this.fontFamily = void 0;
6628
+ this.fontWeight = void 0;
6629
+ this.fontShape = void 0;
6630
+ this.sizeMultiplier = void 0;
6631
+ this.maxSize = void 0;
6632
+ this.minRuleThickness = void 0;
6633
+ this._fontMetrics = void 0;
6508
6634
  this.style = data.style;
6509
6635
  this.color = data.color;
6510
6636
  this.size = data.size || Options.BASESIZE;
@@ -6512,8 +6638,8 @@ class Options {
6512
6638
  this.phantom = !!data.phantom;
6513
6639
  this.font = data.font || "";
6514
6640
  this.fontFamily = data.fontFamily || "";
6515
- this.fontWeight = data.fontWeight || '';
6516
- this.fontShape = data.fontShape || '';
6641
+ this.fontWeight = data.fontWeight || "";
6642
+ this.fontShape = data.fontShape || "";
6517
6643
  this.sizeMultiplier = sizeMultipliers[this.size - 1];
6518
6644
  this.maxSize = data.maxSize;
6519
6645
  this.minRuleThickness = data.minRuleThickness;
@@ -6727,9 +6853,6 @@ class Options {
6727
6853
  }
6728
6854
  }
6729
6855
  }
6730
- // A font family applies to a group of fonts (i.e. SansSerif), while a font
6731
- // represents a specific font (i.e. SansSerif Bold).
6732
- // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm
6733
6856
  /**
6734
6857
  * The base size index.
6735
6858
  */
@@ -6938,14 +7061,10 @@ const stretchySvg = function (group, options) {
6938
7061
  function buildSvgSpan_() {
6939
7062
  let viewBoxWidth = 400000; // default
6940
7063
  const label = group.label.slice(1);
6941
- if (wideAccentLabels.has(label)) {
6942
- // Each type in the `if` statement corresponds to one of the ParseNode
6943
- // types below. This narrowing is required to access `grp.base`.
6944
- // TODO(ts)
6945
- const grp = group;
7064
+ if (wideAccentLabels.has(label) && 'base' in group) {
6946
7065
  // There are four SVG images available for each function.
6947
7066
  // Choose a taller image when there are more characters.
6948
- const numChars = grp.base.type === "ordgroup" ? grp.base.body.length : 1;
7067
+ const numChars = group.base.type === "ordgroup" ? group.base.body.length : 1;
6949
7068
  let viewBoxHeight;
6950
7069
  let pathName;
6951
7070
  let height;
@@ -6990,16 +7109,20 @@ const stretchySvg = function (group, options) {
6990
7109
  } else {
6991
7110
  const spans = [];
6992
7111
  const data = katexImagesData[label];
7112
+ if (!data) {
7113
+ throw new Error("No SVG data for \"" + label + "\".");
7114
+ }
6993
7115
  const [paths, minWidth, viewBoxHeight] = data;
6994
7116
  const height = viewBoxHeight / 1000;
6995
7117
  const numSvgChildren = paths.length;
6996
7118
  let widthClasses;
6997
7119
  let aligns;
6998
7120
  if (numSvgChildren === 1) {
6999
- // TODO(ts): All these cases must be of the 4-tuple type.
7000
- const align1 = data[3];
7121
+ if (data.length !== 4) {
7122
+ throw new Error("Expected 4-tuple for single-path SVG data \"" + label + "\".");
7123
+ }
7001
7124
  widthClasses = ["hide-tail"];
7002
- aligns = [align1];
7125
+ aligns = [data[3]];
7003
7126
  } else if (numSvgChildren === 2) {
7004
7127
  widthClasses = ["halfarrow-left", "halfarrow-right"];
7005
7128
  aligns = ["xMinYMin", "xMaxYMin"];
@@ -7097,6 +7220,35 @@ const stretchyEnclose = function (inner, label, topPad, bottomPad, options) {
7097
7220
  img.style.height = makeEm(totalHeight);
7098
7221
  return img;
7099
7222
  };
7223
+ ;// ./src/atoms.ts
7224
+ /**
7225
+ * Small module for atom-group constants and type guard. Kept separate from
7226
+ * `symbols.ts` so that consumers (notably `contrib/render-a11y-string`) can
7227
+ * pull in `isAtom` without dragging in the ~870-line symbol tables.
7228
+ */
7229
+
7230
+ // Some of these have a "-token" suffix since these are also used as `ParseNode`
7231
+ // types for raw text tokens, and we want to avoid conflicts with higher-level
7232
+ // `ParseNode` types. These `ParseNode`s are constructed within `Parser` by
7233
+ // looking up the `symbols` map.
7234
+ const ATOMS = {
7235
+ "bin": 1,
7236
+ "close": 1,
7237
+ "inner": 1,
7238
+ "open": 1,
7239
+ "punct": 1,
7240
+ "rel": 1
7241
+ };
7242
+ const NON_ATOMS = {
7243
+ "accent-token": 1,
7244
+ "mathord": 1,
7245
+ "op-token": 1,
7246
+ "spacing": 1,
7247
+ "textord": 1
7248
+ };
7249
+ function isAtom(value) {
7250
+ return value in ATOMS;
7251
+ }
7100
7252
  ;// ./src/parseNode.ts
7101
7253
 
7102
7254
 
@@ -7526,7 +7678,8 @@ defineFunction({
7526
7678
  }, {
7527
7679
  type: "elem",
7528
7680
  elem: arrowBody,
7529
- shift: arrowShift
7681
+ shift: arrowShift,
7682
+ wrapperClasses: ["svg-align"]
7530
7683
  }, {
7531
7684
  type: "elem",
7532
7685
  elem: lowerGroup,
@@ -7543,13 +7696,11 @@ defineFunction({
7543
7696
  }, {
7544
7697
  type: "elem",
7545
7698
  elem: arrowBody,
7546
- shift: arrowShift
7699
+ shift: arrowShift,
7700
+ wrapperClasses: ["svg-align"]
7547
7701
  }]
7548
7702
  }, options);
7549
7703
  }
7550
-
7551
- // TODO(ts): Replace this with passing "svg-align" into makeVList.
7552
- vlist.children[0].children[0].children[1].classes.push("svg-align");
7553
7704
  return makeSpan(["mrel", "x-arrow"], [vlist], options);
7554
7705
  },
7555
7706
  mathmlBuilder(group, options) {
@@ -7809,7 +7960,8 @@ const newCell = () => {
7809
7960
  type: "styling",
7810
7961
  body: [],
7811
7962
  mode: "math",
7812
- style: "display"
7963
+ style: "display",
7964
+ resetFont: true
7813
7965
  };
7814
7966
  };
7815
7967
  const isStartOfArrow = node => {
@@ -7871,7 +8023,6 @@ function parseCD(parser) {
7871
8023
  parser.gullet.macros.set("\\cr", "\\\\\\relax");
7872
8024
  parser.gullet.beginGroup();
7873
8025
  while (true) {
7874
- // eslint-disable-line no-constant-condition
7875
8026
  // Get the parse nodes for the next row.
7876
8027
  parsedRows.push(parser.parseExpression(false, "\\\\"));
7877
8028
  parser.gullet.endGroup();
@@ -7964,7 +8115,9 @@ function parseCD(parser) {
7964
8115
  type: "styling",
7965
8116
  body: [arrow],
7966
8117
  mode: "math",
7967
- style: "display" // CD is always displaystyle.
8118
+ style: "display",
8119
+ // CD is always displaystyle.
8120
+ resetFont: true
7968
8121
  };
7969
8122
  row.push(wrappedArrow);
7970
8123
  // In CD's syntax, cells are implicit. That is, everything that
@@ -8909,9 +9062,9 @@ const makeSqrtImage = function (height, options) {
8909
9062
 
8910
9063
  // Create a span containing an SVG image of a sqrt symbol.
8911
9064
  let span;
8912
- let spanHeight = 0;
8913
- let texHeight = 0;
8914
- let viewBoxHeight = 0;
9065
+ let spanHeight;
9066
+ let texHeight;
9067
+ let viewBoxHeight;
8915
9068
  let advanceWidth;
8916
9069
 
8917
9070
  // We create viewBoxes with 80 units of "padding" above each surd.
@@ -9273,6 +9426,16 @@ const delimiterSizes = {
9273
9426
  }
9274
9427
  };
9275
9428
  const 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", "."]);
9429
+
9430
+ /**
9431
+ * An HtmlDomNode that carries an `isMiddle` property, used by the
9432
+ * \middle command to communicate delimiter info to the \left/\right builder.
9433
+ */
9434
+
9435
+ function isMiddleDelimNode(node) {
9436
+ return 'isMiddle' in node;
9437
+ }
9438
+
9276
9439
  // Delimiter functions
9277
9440
  function checkDelimiter(delim, context) {
9278
9441
  const symDelim = checkSymbolNodeType(delim);
@@ -9396,10 +9559,8 @@ defineFunction({
9396
9559
 
9397
9560
  // Calculate its height and depth
9398
9561
  for (let i = 0; i < inner.length; i++) {
9399
- // Property `isMiddle` not defined on `span`. See comment in
9400
- // "middle"'s htmlBuilder.
9401
- // TODO(ts)
9402
- if (inner[i].isMiddle) {
9562
+ const node = inner[i];
9563
+ if (isMiddleDelimNode(node)) {
9403
9564
  hadMiddle = true;
9404
9565
  } else {
9405
9566
  innerHeight = Math.max(inner[i].height, innerHeight);
@@ -9428,11 +9589,8 @@ defineFunction({
9428
9589
  if (hadMiddle) {
9429
9590
  for (let i = 1; i < inner.length; i++) {
9430
9591
  const middleDelim = inner[i];
9431
- // Property `isMiddle` not defined on `span`. See comment in
9432
- // "middle"'s htmlBuilder.
9433
- // TODO(ts)
9434
- const isMiddle = middleDelim.isMiddle;
9435
- if (isMiddle) {
9592
+ if (isMiddleDelimNode(middleDelim)) {
9593
+ const isMiddle = middleDelim.isMiddle;
9436
9594
  // Apply the options that were active when \middle was called
9437
9595
  inner[i] = makeLeftRightDelim(isMiddle.delim, innerHeight, innerDepth, isMiddle.options, group.mode, []);
9438
9596
  }
@@ -9493,16 +9651,15 @@ defineFunction({
9493
9651
  middleDelim = makeNullDelimiter(options, []);
9494
9652
  } else {
9495
9653
  middleDelim = makeSizedDelim(group.delim, 1, options, group.mode, []);
9496
- const isMiddle = {
9654
+
9655
+ // Patch an ad-hoc property onto the node so the \left/\right
9656
+ // builder can reconstruct appropriately sized middle delimiters.
9657
+ // isMiddle is not part of HtmlDomNode; the read side uses
9658
+ // isMiddleDelimNode() to check before accessing.
9659
+ middleDelim.isMiddle = {
9497
9660
  delim: group.delim,
9498
9661
  options
9499
9662
  };
9500
- // Property `isMiddle` not defined on `span`. It is only used in
9501
- // this file above.
9502
- // TODO: Fix this violation of the `span` type and possibly rename
9503
- // things since `isMiddle` sounds like a boolean, but is a struct.
9504
- // TODO(ts)
9505
- middleDelim.isMiddle = isMiddle;
9506
9663
  }
9507
9664
  return middleDelim;
9508
9665
  },
@@ -9541,7 +9698,7 @@ const enclose_htmlBuilder = (group, options) => {
9541
9698
  const label = group.label.slice(1);
9542
9699
  let scale = options.sizeMultiplier;
9543
9700
  let img;
9544
- let imgShift = 0;
9701
+ let imgShift;
9545
9702
 
9546
9703
  // In the LaTeX cancel package, line geometry is slightly different
9547
9704
  // depending on whether the subject is wider than it is tall, or vice versa.
@@ -9597,8 +9754,8 @@ const enclose_htmlBuilder = (group, options) => {
9597
9754
  }
9598
9755
 
9599
9756
  // Add vertical padding
9600
- let topPad = 0;
9601
- let bottomPad = 0;
9757
+ let topPad;
9758
+ let bottomPad;
9602
9759
  let ruleThickness = 0;
9603
9760
  // ref: cancel package: \advance\totalheight2\p@ % "+2"
9604
9761
  if (/box/.test(label)) {
@@ -9680,7 +9837,7 @@ const enclose_htmlBuilder = (group, options) => {
9680
9837
  }
9681
9838
  };
9682
9839
  const enclose_mathmlBuilder = (group, options) => {
9683
- let fboxsep = 0;
9840
+ let fboxsep;
9684
9841
  const node = new MathNode(group.label.includes("colorbox") ? "mpadded" : "menclose", [buildMathML_buildGroup(group.body, options)]);
9685
9842
  switch (group.label) {
9686
9843
  case "\\cancel":
@@ -9733,7 +9890,7 @@ defineFunction({
9733
9890
  props: {
9734
9891
  numArgs: 2,
9735
9892
  allowedInText: true,
9736
- argTypes: ["color", "text"]
9893
+ argTypes: ["color", "hbox"]
9737
9894
  },
9738
9895
  handler(_ref, args, optArgs) {
9739
9896
  let {
@@ -9759,7 +9916,7 @@ defineFunction({
9759
9916
  props: {
9760
9917
  numArgs: 3,
9761
9918
  allowedInText: true,
9762
- argTypes: ["color", "color", "text"]
9919
+ argTypes: ["color", "color", "hbox"]
9763
9920
  },
9764
9921
  handler(_ref2, args, optArgs) {
9765
9922
  let {
@@ -9962,12 +10119,15 @@ function defineMacro(name, body) {
9962
10119
  * This object is immutable.
9963
10120
  */
9964
10121
  class SourceLocation {
9965
- // The + prefix indicates that these fields aren't writeable
9966
- // Lexer holding the input string.
9967
- // Start offset, zero-based inclusive.
9968
10122
  // End offset, zero-based exclusive.
9969
10123
 
9970
10124
  constructor(lexer, start, end) {
10125
+ // The + prefix indicates that these fields aren't writeable
10126
+ this.lexer = void 0;
10127
+ // Lexer holding the input string.
10128
+ this.start = void 0;
10129
+ // Start offset, zero-based inclusive.
10130
+ this.end = void 0;
9971
10131
  this.lexer = lexer;
9972
10132
  this.start = start;
9973
10133
  this.end = end;
@@ -10013,12 +10173,16 @@ class SourceLocation {
10013
10173
  * lead to degraded error reporting, though.
10014
10174
  */
10015
10175
  class Token {
10016
- // don't expand the token
10017
10176
  // used in \noexpand
10018
10177
 
10019
10178
  constructor(text,
10020
10179
  // the text of this token
10021
10180
  loc) {
10181
+ this.text = void 0;
10182
+ this.loc = void 0;
10183
+ this.noexpand = void 0;
10184
+ // don't expand the token
10185
+ this.treatAsRelax = void 0;
10022
10186
  this.text = text;
10023
10187
  this.loc = loc;
10024
10188
  }
@@ -10166,7 +10330,6 @@ function parseArray(parser, _ref, style) {
10166
10330
  // Test for \hline at the top of the array.
10167
10331
  hLinesBeforeRow.push(getHLines(parser));
10168
10332
  while (true) {
10169
- // eslint-disable-line no-constant-condition
10170
10333
  // Parse each cell in its own group (namespace)
10171
10334
  const cellBody = parser.parseExpression(false, singleRow ? "\\end" : "\\\\");
10172
10335
  parser.gullet.endGroup();
@@ -10181,6 +10344,7 @@ function parseArray(parser, _ref, style) {
10181
10344
  type: "styling",
10182
10345
  mode: parser.mode,
10183
10346
  style,
10347
+ resetFont: true,
10184
10348
  body: [cell]
10185
10349
  };
10186
10350
  }
@@ -10324,7 +10488,12 @@ const array_htmlBuilder = function (group, options) {
10324
10488
  if (nc < inrow.length) {
10325
10489
  nc = inrow.length;
10326
10490
  }
10327
- const outrow = new Array(inrow.length);
10491
+ const outrow = {
10492
+ cells: new Array(inrow.length),
10493
+ height: 0,
10494
+ depth: 0,
10495
+ pos: 0
10496
+ };
10328
10497
  for (c = 0; c < inrow.length; ++c) {
10329
10498
  const elt = buildGroup(inrow[c], options);
10330
10499
  if (depth < elt.depth) {
@@ -10333,7 +10502,7 @@ const array_htmlBuilder = function (group, options) {
10333
10502
  if (height < elt.height) {
10334
10503
  height = elt.height;
10335
10504
  }
10336
- outrow[c] = elt;
10505
+ outrow.cells[c] = elt;
10337
10506
  }
10338
10507
  const rowGap = group.rowGaps[r];
10339
10508
  let gap = 0;
@@ -10449,7 +10618,7 @@ const array_htmlBuilder = function (group, options) {
10449
10618
  const colElems = [];
10450
10619
  for (r = 0; r < nr; ++r) {
10451
10620
  const row = body[r];
10452
- const elem = row[c];
10621
+ const elem = row.cells[c];
10453
10622
  if (!elem) {
10454
10623
  continue;
10455
10624
  }
@@ -11081,7 +11250,6 @@ const environments = _environments;
11081
11250
 
11082
11251
 
11083
11252
 
11084
-
11085
11253
  // Environment delimiters. HTML/MathML rendering is defined in the corresponding
11086
11254
  // defineEnvironment definitions.
11087
11255
  defineFunction({
@@ -11128,7 +11296,10 @@ defineFunction({
11128
11296
  if (end.name !== envName) {
11129
11297
  throw new src_ParseError("Mismatch: \\begin{" + envName + "} matched by \\end{" + end.name + "}", endNameToken);
11130
11298
  }
11131
- // TODO(ts), "environment" handler returns an environment ParseNode
11299
+ // env.handler returns the specific node type (e.g. "array"),
11300
+ // not "environment". This cast is unavoidable: defineFunction
11301
+ // requires the handler to return ParseNode<"environment"> but
11302
+ // \begin delegates to environment handlers with different types.
11132
11303
  return result;
11133
11304
  }
11134
11305
  return {
@@ -11160,8 +11331,7 @@ const font_mathmlBuilder = (group, options) => {
11160
11331
  const fontAliases = {
11161
11332
  "\\Bbb": "\\mathbb",
11162
11333
  "\\bold": "\\mathbf",
11163
- "\\frak": "\\mathfrak",
11164
- "\\bm": "\\boldsymbol"
11334
+ "\\frak": "\\mathfrak"
11165
11335
  };
11166
11336
  defineFunction({
11167
11337
  type: "font",
@@ -11242,11 +11412,10 @@ defineFunction({
11242
11412
  mode
11243
11413
  } = parser;
11244
11414
  const body = parser.parseExpression(true, breakOnTokenText);
11245
- const style = "math" + funcName.slice(1);
11246
11415
  return {
11247
11416
  type: "font",
11248
11417
  mode: mode,
11249
- font: style,
11418
+ font: "math" + funcName.slice(1),
11250
11419
  body: {
11251
11420
  type: "ordgroup",
11252
11421
  mode: parser.mode,
@@ -11730,18 +11899,18 @@ const horizBrace_htmlBuilder = (grp, options) => {
11730
11899
  size: 0.1
11731
11900
  }, {
11732
11901
  type: "elem",
11733
- elem: braceBody
11902
+ elem: braceBody,
11903
+ wrapperClasses: ["svg-align"]
11734
11904
  }]
11735
11905
  }, options);
11736
- // TODO(ts): Replace this with passing "svg-align" into makeVList.
11737
- vlist.children[0].children[0].children[1].classes.push("svg-align");
11738
11906
  } else {
11739
11907
  vlist = makeVList({
11740
11908
  positionType: "bottom",
11741
11909
  positionData: body.depth + 0.1 + braceBody.height,
11742
11910
  children: [{
11743
11911
  type: "elem",
11744
- elem: braceBody
11912
+ elem: braceBody,
11913
+ wrapperClasses: ["svg-align"]
11745
11914
  }, {
11746
11915
  type: "kern",
11747
11916
  size: 0.1
@@ -11750,8 +11919,6 @@ const horizBrace_htmlBuilder = (grp, options) => {
11750
11919
  elem: body
11751
11920
  }]
11752
11921
  }, options);
11753
- // TODO(ts): Replace this with passing "svg-align" into makeVList.
11754
- vlist.children[0].children[0].children[0].classes.push("svg-align");
11755
11922
  }
11756
11923
  if (supSubGroup) {
11757
11924
  // To write the supsub, wrap the first vlist in another vlist:
@@ -11949,11 +12116,11 @@ defineFunction({
11949
12116
  };
11950
12117
  },
11951
12118
  htmlBuilder(group, options) {
11952
- const elements = buildExpression(group.body, options, false);
12119
+ const elements = buildExpression(group.body, options.withFont(''), false);
11953
12120
  return makeFragment(elements);
11954
12121
  },
11955
12122
  mathmlBuilder(group, options) {
11956
- return new MathNode("mrow", buildMathML_buildExpression(group.body, options));
12123
+ return new MathNode("mrow", buildMathML_buildExpression(group.body, options.withFont('')));
11957
12124
  }
11958
12125
  });
11959
12126
  ;// ./src/functions/html.ts
@@ -12393,6 +12560,7 @@ defineFunction({
12393
12560
  type: "styling",
12394
12561
  mode: parser.mode,
12395
12562
  style: "text",
12563
+ resetFont: true,
12396
12564
  body
12397
12565
  };
12398
12566
  }
@@ -12627,6 +12795,9 @@ const op_htmlBuilder = (grp, options) => {
12627
12795
  large = true;
12628
12796
  }
12629
12797
  let base;
12798
+ // Italic correction from the symbol glyph, captured before the symbol
12799
+ // may be wrapped in a vlist (for \oiint/\oiiint). Stays 0 for non-symbol ops.
12800
+ let symbolItalic;
12630
12801
  if (group.symbol) {
12631
12802
  // If this is a symbol, create the symbol.
12632
12803
  const fontName = large ? "Size2-Regular" : "Size1-Regular";
@@ -12638,10 +12809,10 @@ const op_htmlBuilder = (grp, options) => {
12638
12809
  group.name = stash === "oiint" ? "\\iint" : "\\iiint";
12639
12810
  }
12640
12811
  base = makeSymbol(group.name, fontName, "math", options, ["mop", "op-symbol", large ? "large-op" : "small-op"]);
12812
+ symbolItalic = base.italic;
12641
12813
  if (stash.length > 0) {
12642
12814
  // We're in \oiint or \oiiint. Overlay the oval.
12643
12815
  // TODO: When font glyphs are available, delete this code.
12644
- const italic = base.italic;
12645
12816
  const oval = staticSvg(stash + "Size" + (large ? "2" : "1"), options);
12646
12817
  base = makeVList({
12647
12818
  positionType: "individualShift",
@@ -12657,8 +12828,9 @@ const op_htmlBuilder = (grp, options) => {
12657
12828
  }, options);
12658
12829
  group.name = "\\" + stash;
12659
12830
  base.classes.unshift("mop");
12660
- // TODO(ts)
12661
- base.italic = italic;
12831
+ // Carry the italic correction from the original symbol to the
12832
+ // vlist wrapper so supsub can use it for subscript positioning.
12833
+ base.italic = symbolItalic;
12662
12834
  }
12663
12835
  } else if (group.body) {
12664
12836
  // If this is a list, compose that list.
@@ -12683,6 +12855,7 @@ const op_htmlBuilder = (grp, options) => {
12683
12855
  let baseShift = 0;
12684
12856
  let slant = 0;
12685
12857
  if ((base instanceof SymbolNode || group.name === "\\oiint" || group.name === "\\oiiint") && !group.suppressBaseShift) {
12858
+ var _base$italic;
12686
12859
  // We suppress the shift of the base of \overset and \underset. Otherwise,
12687
12860
  // shift the symbol so its center lies on the axis (rule 13). It
12688
12861
  // appears that our fonts have the centers of the symbols already
@@ -12692,8 +12865,9 @@ const op_htmlBuilder = (grp, options) => {
12692
12865
  baseShift = (base.height - base.depth) / 2 - options.fontMetrics().axisHeight;
12693
12866
 
12694
12867
  // The slant of the symbol is just its italic correction.
12695
- // TODO(ts)
12696
- slant = base.italic || 0;
12868
+ // SymbolNode carries .italic natively; Span (for \oiint/\oiiint)
12869
+ // only has it set when nonzero, so default to 0.
12870
+ slant = (_base$italic = base.italic) != null ? _base$italic : 0;
12697
12871
  }
12698
12872
  if (hasLimits) {
12699
12873
  return assembleSupSub(base, supGroup, subGroup, options, style, slant, baseShift);
@@ -13427,7 +13601,7 @@ defineFunction({
13427
13601
  // Optional [tb] argument is engaged.
13428
13602
  // ref: amsmath: \renewcommand{\smash}[1][tb]{%
13429
13603
  // def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}%
13430
- let letter = "";
13604
+ let letter;
13431
13605
  for (let i = 0; i < tbArg.body.length; ++i) {
13432
13606
  const node = tbArg.body[i];
13433
13607
  letter = assertSymbolNodeType(node).text;
@@ -13649,6 +13823,9 @@ const styling_styleMap = {
13649
13823
  "script": src_Style.SCRIPT,
13650
13824
  "scriptscript": src_Style.SCRIPTSCRIPT
13651
13825
  };
13826
+ function isStyleStr(s) {
13827
+ return s in styling_styleMap;
13828
+ }
13652
13829
  defineFunction({
13653
13830
  type: "styling",
13654
13831
  names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"],
@@ -13668,8 +13845,10 @@ defineFunction({
13668
13845
 
13669
13846
  // TODO: Refactor to avoid duplicating styleMap in multiple places (e.g.
13670
13847
  // here and in buildHTML and de-dupe the enumeration of all the styles).
13671
- // TODO(ts): The names above exactly match the styles.
13672
13848
  const style = funcName.slice(1, funcName.length - 5);
13849
+ if (!isStyleStr(style)) {
13850
+ throw new Error("Unknown style: " + style);
13851
+ }
13673
13852
  return {
13674
13853
  type: "styling",
13675
13854
  mode: parser.mode,
@@ -13682,13 +13861,19 @@ defineFunction({
13682
13861
  htmlBuilder(group, options) {
13683
13862
  // Style changes are handled in the TeXbook on pg. 442, Rule 3.
13684
13863
  const newStyle = styling_styleMap[group.style];
13685
- const newOptions = options.havingStyle(newStyle).withFont('');
13864
+ let newOptions = options.havingStyle(newStyle);
13865
+ if (group.resetFont) {
13866
+ newOptions = newOptions.withFont('');
13867
+ }
13686
13868
  return sizingGroup(group.body, newOptions, options);
13687
13869
  },
13688
13870
  mathmlBuilder(group, options) {
13689
13871
  // Figure out what style we're changing to.
13690
13872
  const newStyle = styling_styleMap[group.style];
13691
- const newOptions = options.havingStyle(newStyle);
13873
+ let newOptions = options.havingStyle(newStyle);
13874
+ if (group.resetFont) {
13875
+ newOptions = newOptions.withFont('');
13876
+ }
13692
13877
  const inner = buildMathML_buildExpression(group.body, newOptions);
13693
13878
  const node = new MathNode("mstyle", inner);
13694
13879
  const styleAttributes = {
@@ -13724,7 +13909,9 @@ defineFunction({
13724
13909
  * its inner element should handle the superscripts and subscripts instead of
13725
13910
  * handling them itself.
13726
13911
  */
13727
- const htmlBuilderDelegate = function (group, options) {
13912
+ const htmlBuilderDelegate = function (group, options
13913
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13914
+ ) {
13728
13915
  const base = group.base;
13729
13916
  if (!base) {
13730
13917
  return null;
@@ -13810,8 +13997,10 @@ defineFunctionBuilders({
13810
13997
  // amount. Note we only do this when the base is a single symbol.
13811
13998
  const isOiint = group.base && group.base.type === "op" && group.base.name && (group.base.name === "\\oiint" || group.base.name === "\\oiiint");
13812
13999
  if (base instanceof SymbolNode || isOiint) {
13813
- // @ts-ignore
13814
- marginLeft = makeEm(-base.italic);
14000
+ var _italic;
14001
+ // SymbolNode has .italic natively; for \oiint/\oiiint the
14002
+ // op builder stores .italic on the wrapping Span.
14003
+ marginLeft = makeEm(-((_italic = base.italic) != null ? _italic : 0));
13815
14004
  }
13816
14005
  }
13817
14006
  let supsub;
@@ -14457,10 +14646,13 @@ combiningDiacriticalMarkString + "*") +
14457
14646
 
14458
14647
  /** Main Lexer class */
14459
14648
  class Lexer {
14460
- // Category codes. The lexer only supports comment characters (14) for now.
14461
- // MacroExpander additionally distinguishes active (13).
14462
-
14463
14649
  constructor(input, settings) {
14650
+ this.input = void 0;
14651
+ this.settings = void 0;
14652
+ this.tokenRegex = void 0;
14653
+ // Category codes. The lexer only supports comment characters (14) for now.
14654
+ // MacroExpander additionally distinguishes active (13).
14655
+ this.catcodes = void 0;
14464
14656
  // Separate accents from characters
14465
14657
  this.input = input;
14466
14658
  this.settings = settings;
@@ -14527,6 +14719,9 @@ class Namespace {
14527
14719
  if (globalMacros === void 0) {
14528
14720
  globalMacros = {};
14529
14721
  }
14722
+ this.current = void 0;
14723
+ this.builtins = void 0;
14724
+ this.undefStack = void 0;
14530
14725
  this.current = globalMacros;
14531
14726
  this.builtins = builtins;
14532
14727
  this.undefStack = [];
@@ -15630,6 +15825,12 @@ const implicitCommands = {
15630
15825
  };
15631
15826
  class MacroExpander {
15632
15827
  constructor(input, settings, mode) {
15828
+ this.settings = void 0;
15829
+ this.expansionCount = void 0;
15830
+ this.lexer = void 0;
15831
+ this.macros = void 0;
15832
+ this.stack = void 0;
15833
+ this.mode = void 0;
15633
15834
  this.settings = settings;
15634
15835
  this.expansionCount = 0;
15635
15836
  this.feed(input);
@@ -16176,6 +16377,7 @@ const uSubsAndSups = Object.freeze({
16176
16377
 
16177
16378
 
16178
16379
 
16380
+
16179
16381
  // Pre-evaluate both modules as unicodeSymbols require String.normalize()
16180
16382
  const unicodeAccents = {
16181
16383
  "́": {
@@ -16603,6 +16805,11 @@ const unicodeSymbols = {
16603
16805
 
16604
16806
  class Parser {
16605
16807
  constructor(input, settings) {
16808
+ this.mode = void 0;
16809
+ this.gullet = void 0;
16810
+ this.settings = void 0;
16811
+ this.leftrightDepth = void 0;
16812
+ this.nextToken = void 0;
16606
16813
  // Start in math mode
16607
16814
  this.mode = "math";
16608
16815
  // Create a new macro expander (gullet) and (indirectly via that) also a
@@ -17107,13 +17314,16 @@ class Parser {
17107
17314
  case "hbox":
17108
17315
  {
17109
17316
  // hbox argument type wraps the argument in the equivalent of
17110
- // \hbox, which is like \text but switching to \textstyle size.
17317
+ // \hbox, which is like \text but switching to \textstyle size
17318
+ // and resetting math font.
17111
17319
  const group = this.parseArgumentGroup(optional, "text");
17112
17320
  return group != null ? {
17113
17321
  type: "styling",
17114
17322
  mode: group.mode,
17115
17323
  body: [group],
17116
- style: "text" // simulate \textstyle
17324
+ style: "text",
17325
+ // simulate \textstyle
17326
+ resetFont: true
17117
17327
  } : null;
17118
17328
  }
17119
17329
  case "raw":
@@ -17479,18 +17689,15 @@ class Parser {
17479
17689
  const group = src_symbols[this.mode][text].group;
17480
17690
  const loc = SourceLocation.range(nucleus);
17481
17691
  let s;
17482
- if (ATOMS.hasOwnProperty(group)) {
17483
- // TODO(ts)
17484
- const family = group;
17692
+ if (isAtom(group)) {
17485
17693
  s = {
17486
17694
  type: "atom",
17487
17695
  mode: this.mode,
17488
- family,
17696
+ family: group,
17489
17697
  loc,
17490
17698
  text
17491
17699
  };
17492
17700
  } else {
17493
- // TODO(ts)
17494
17701
  s = {
17495
17702
  type: group,
17496
17703
  mode: this.mode,
@@ -17498,7 +17705,6 @@ class Parser {
17498
17705
  text
17499
17706
  };
17500
17707
  }
17501
- // TODO(ts)
17502
17708
  symbol = s;
17503
17709
  } else if (text.charCodeAt(0) >= 0x80) {
17504
17710
  // no symbol for e.g. ^
@@ -17544,12 +17750,10 @@ class Parser {
17544
17750
  label: command,
17545
17751
  isStretchy: false,
17546
17752
  isShifty: true,
17547
- // TODO(ts)
17548
17753
  base: symbol
17549
17754
  };
17550
17755
  }
17551
17756
  }
17552
- // TODO(ts)
17553
17757
  return symbol;
17554
17758
  }
17555
17759
  }
@@ -17695,7 +17899,7 @@ const renderToHTMLTree = function (expression, options) {
17695
17899
  return renderError(error, expression, settings);
17696
17900
  }
17697
17901
  };
17698
- const version = "0.16.45";
17902
+ const version = "0.16.46";
17699
17903
  const __domTree = {
17700
17904
  Span: Span,
17701
17905
  Anchor: Anchor,