katex 0.16.46 → 0.17.0

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 (81) hide show
  1. package/README.md +5 -10
  2. package/contrib/copy-tex/README.md +2 -2
  3. package/contrib/mathtex-script-type/README.md +5 -5
  4. package/contrib/mhchem/README.md +1 -1
  5. package/contrib/render-a11y-string/render-a11y-string.ts +1 -1
  6. package/dist/README.md +5 -10
  7. package/dist/katex-swap.css +1 -1
  8. package/dist/katex-swap.min.css +1 -1
  9. package/dist/katex.css +1 -1
  10. package/dist/katex.js +255 -434
  11. package/dist/katex.min.css +1 -1
  12. package/dist/katex.min.js +1 -1
  13. package/dist/katex.mjs +243 -415
  14. package/katex.ts +1 -1
  15. package/package.json +1 -2
  16. package/src/MacroExpander.ts +1 -1
  17. package/src/Namespace.ts +1 -1
  18. package/src/ParseError.ts +1 -1
  19. package/src/Parser.ts +42 -48
  20. package/src/Settings.ts +1 -1
  21. package/src/SourceLocation.ts +2 -2
  22. package/src/buildCommon.ts +6 -6
  23. package/src/buildHTML.ts +4 -5
  24. package/src/buildMathML.ts +1 -1
  25. package/src/buildTree.ts +1 -1
  26. package/src/defineEnvironment.ts +1 -2
  27. package/src/defineFunction.ts +104 -112
  28. package/src/environments/array.ts +8 -12
  29. package/src/environments/cd.ts +8 -8
  30. package/src/functions/accent.ts +10 -13
  31. package/src/functions/accentunder.ts +4 -4
  32. package/src/functions/arrow.ts +5 -5
  33. package/src/functions/char.ts +3 -4
  34. package/src/functions/color.ts +10 -13
  35. package/src/functions/cr.ts +3 -5
  36. package/src/functions/def.ts +15 -19
  37. package/src/functions/delimsizing.ts +23 -23
  38. package/src/functions/enclose.ts +22 -33
  39. package/src/functions/environment.ts +4 -5
  40. package/src/functions/font.ts +15 -27
  41. package/src/functions/genfrac.ts +19 -23
  42. package/src/functions/hbox.ts +6 -6
  43. package/src/functions/horizBrace.ts +4 -4
  44. package/src/functions/href.ts +10 -11
  45. package/src/functions/html.ts +5 -5
  46. package/src/functions/htmlmathml.ts +5 -5
  47. package/src/functions/includegraphics.ts +7 -7
  48. package/src/functions/kern.ts +6 -6
  49. package/src/functions/lap.ts +4 -4
  50. package/src/functions/math.ts +8 -10
  51. package/src/functions/mathchoice.ts +5 -5
  52. package/src/functions/mclass.ts +16 -28
  53. package/src/functions/op.ts +16 -30
  54. package/src/functions/operatorname.ts +4 -4
  55. package/src/functions/overline.ts +3 -3
  56. package/src/functions/phantom.ts +8 -8
  57. package/src/functions/pmb.ts +5 -5
  58. package/src/functions/raisebox.ts +5 -5
  59. package/src/functions/relax.ts +4 -5
  60. package/src/functions/rule.ts +7 -7
  61. package/src/functions/sizing.ts +6 -6
  62. package/src/functions/smash.ts +5 -5
  63. package/src/functions/sqrt.ts +4 -4
  64. package/src/functions/styling.ts +5 -5
  65. package/src/functions/supsub.ts +1 -1
  66. package/src/functions/symbolsOrd.ts +3 -3
  67. package/src/functions/symbolsSpacing.ts +1 -1
  68. package/src/functions/text.ts +7 -7
  69. package/src/functions/underline.ts +4 -4
  70. package/src/functions/utils/assembleSupSub.ts +1 -1
  71. package/src/functions/vcenter.ts +5 -5
  72. package/src/functions/verb.ts +5 -5
  73. package/src/parseNode.ts +2 -476
  74. package/src/parseTree.ts +1 -6
  75. package/src/spacingData.ts +2 -1
  76. package/src/stretchy.ts +1 -1
  77. package/src/svgGeometry.ts +2 -2
  78. package/src/types/index.ts +12 -0
  79. package/src/types/nodes.ts +456 -0
  80. package/src/units.ts +1 -2
  81. package/src/utils.ts +1 -1
@@ -1,24 +1,26 @@
1
1
  import type Parser from "./Parser";
2
- import type {ParseNode, AnyParseNode, NodeType, UnsupportedCmdParseNode}
3
- from "./parseNode";
4
2
  import type Options from "./Options";
5
3
  import type {ArgType, BreakToken} from "./types";
4
+ import type {AnyParseNode, NodeType, ParseNode, UnsupportedCmdParseNode} from "./types/nodes";
6
5
  import type {HtmlDomNode} from "./domTree";
7
6
  import type {Token} from "./Token";
8
7
  import type {MathDomNode} from "./mathMLTree";
9
8
 
10
9
  /** Context provided to function handlers for error messages. */
11
- export type FunctionContext = {
12
- funcName: string;
10
+ export type FunctionContext<FUNCNAME extends string = string> = {
11
+ funcName: FUNCNAME;
13
12
  parser: Parser;
14
13
  token?: Token;
15
14
  breakOnTokenText?: BreakToken;
16
15
  };
17
16
 
18
- export type FunctionHandler<NODETYPE extends NodeType> = (
19
- context: FunctionContext,
17
+ export type FunctionHandler<
18
+ NODETYPE extends NodeType,
19
+ FUNCNAME extends string = string,
20
+ > = (
21
+ context: FunctionContext<FUNCNAME>,
20
22
  args: AnyParseNode[],
21
- optArgs: (AnyParseNode | null | undefined)[],
23
+ optArgs: (AnyParseNode | null)[],
22
24
  ) => UnsupportedCmdParseNode | ParseNode<NODETYPE>;
23
25
  // Note: reverse the order of the return type union will cause a flow error.
24
26
  // See https://github.com/facebook/flow/issues/3663.
@@ -34,104 +36,109 @@ export type MathMLBuilder<NODETYPE extends NodeType> =
34
36
  export type HtmlBuilderSupSub<NODETYPE extends NodeType> =
35
37
  (group: ParseNode<"supsub"> | ParseNode<NODETYPE>, options: Options) => HtmlDomNode;
36
38
 
37
- export type FunctionPropSpec = {
38
- // The number of arguments the function takes.
39
+ /**
40
+ * Parser-facing function spec. Optional properties should use the defaults
41
+ * documented below.
42
+ */
43
+ export type FunctionSpec<
44
+ NODETYPE extends NodeType,
45
+ FUNCNAME extends string = string,
46
+ > = {
47
+ /**
48
+ * Unique string to differentiate parse nodes.
49
+ * Also determines the type of the value returned by `handler`.
50
+ */
51
+ type: NODETYPE;
52
+
53
+ /** The number of arguments the function takes. */
39
54
  numArgs: number;
40
55
 
41
- // An array corresponding to each argument of the function, giving the
42
- // type of argument that should be parsed. Its length should be equal
43
- // to `numOptionalArgs + numArgs`, and types for optional arguments
44
- // should appear before types for mandatory arguments.
56
+ /**
57
+ * An array corresponding to each argument of the function, giving the
58
+ * type of argument that should be parsed. Its length should be equal
59
+ * to `numOptionalArgs + numArgs`, and types for optional arguments
60
+ * should appear before types for mandatory arguments.
61
+ */
45
62
  argTypes?: ArgType[];
46
63
 
47
- // Whether it expands to a single token or a braced group of tokens.
48
- // If it's grouped, it can be used as an argument to primitive commands,
49
- // such as \sqrt (without the optional argument) and super/subscript.
64
+ /**
65
+ * Whether it expands to a single token or a braced group of tokens.
66
+ * If it's grouped, it can be used as an argument to primitive commands,
67
+ * such as \sqrt (without the optional argument) and super/subscript.
68
+ * (default false)
69
+ */
50
70
  allowedInArgument?: boolean;
51
71
 
52
- // Whether or not the function is allowed inside text mode
53
- // (default false)
72
+ /**
73
+ * Whether or not the function is allowed inside text mode
74
+ * (default false)
75
+ */
54
76
  allowedInText?: boolean;
55
77
 
56
- // Whether or not the function is allowed inside text mode
57
- // (default true)
78
+ /**
79
+ * Whether or not the function is allowed inside math mode
80
+ * (default true)
81
+ */
58
82
  allowedInMath?: boolean;
59
83
 
60
- // (optional) The number of optional arguments the function
61
- // should parse. If the optional arguments aren't found,
62
- // `null` will be passed to the handler in their place.
63
- // (default 0)
84
+ /**
85
+ * The number of optional arguments the function should parse. If the
86
+ * optional arguments aren't found, `null` will be passed to the handler in
87
+ * their place.
88
+ * (default 0)
89
+ */
64
90
  numOptionalArgs?: number;
65
91
 
66
- // Must be true if the function is an infix operator.
92
+ /** Must be true if the function is an infix operator. */
67
93
  infix?: boolean;
68
94
 
69
- // Whether or not the function is a TeX primitive.
95
+ /** Whether or not the function is a TeX primitive. */
70
96
  primitive?: boolean;
71
- };
72
97
 
73
- type FunctionDefSpec<NODETYPE extends NodeType> = {
74
- // Unique string to differentiate parse nodes.
75
- // Also determines the type of the value returned by `handler`.
76
- type: NODETYPE;
77
-
78
- // The first argument to defineFunction is a single name or a list of names.
79
- // All functions named in such a list will share a single implementation.
80
- names: Array<string>;
81
-
82
- // Properties that control how the functions are parsed.
83
- props: FunctionPropSpec;
84
-
85
- // The handler is called to handle these functions and their arguments and
86
- // returns a `ParseNode`.
87
- handler: FunctionHandler<NODETYPE> | null | undefined;
98
+ /**
99
+ * The handler is called to handle these functions and their arguments and
100
+ * returns a `ParseNode`. It must be specified unless it's handled directly
101
+ * in the parser.
102
+ */
103
+ handler: FunctionHandler<NODETYPE, FUNCNAME> | null | undefined;
104
+ };
88
105
 
89
- // This function returns an object representing the DOM structure to be
90
- // created when rendering the defined LaTeX function.
91
- // This should not modify the `ParseNode`.
106
+ /**
107
+ * Builder fields consumed during registration. These are stored separately in
108
+ * `_htmlGroupBuilders` and `_mathmlGroupBuilders`, and are not used by Parser.
109
+ */
110
+ export type FunctionBuilders<NODETYPE extends NodeType> = {
111
+ /**
112
+ * This function returns an object representing the DOM structure to be
113
+ * created when rendering the defined LaTeX function.
114
+ * This should not modify the `ParseNode`.
115
+ */
92
116
  htmlBuilder?: HtmlBuilder<NODETYPE>;
93
117
 
94
- // This function returns an object representing the MathML structure to be
95
- // created when rendering the defined LaTeX function.
96
- // This should not modify the `ParseNode`.
118
+ /**
119
+ * This function returns an object representing the MathML structure to be
120
+ * created when rendering the defined LaTeX function.
121
+ * This should not modify the `ParseNode`.
122
+ */
97
123
  mathmlBuilder?: MathMLBuilder<NODETYPE>;
98
124
  };
99
125
 
100
126
  /**
101
- * Final function spec for use at parse time.
102
- * This is almost identical to `FunctionPropSpec`, except it
103
- * 1. includes the function handler, and
104
- * 2. requires all arguments except argTypes.
105
- * It is generated by `defineFunction()` below.
127
+ * Full registration spec passed to `defineFunction`. It combines the
128
+ * parser-facing fields with optional builder fields and the names being
129
+ * registered.
106
130
  */
107
- export type FunctionSpec<NODETYPE extends NodeType> = {
108
- type: NODETYPE; // Need to use the type to avoid error. See NOTES below.
109
- numArgs: number;
110
- argTypes?: ArgType[];
111
- allowedInArgument: boolean;
112
- allowedInText: boolean;
113
- allowedInMath: boolean;
114
- numOptionalArgs: number;
115
- infix: boolean;
116
- primitive: boolean;
117
-
118
- // FLOW TYPE NOTES: Doing either one of the following two
119
- //
120
- // - removing the NODETYPE type parameter in FunctionSpec above;
121
- // - using ?FunctionHandler<NODETYPE> below;
122
- //
123
- // results in a confusing flow typing error:
124
- // "string literal `styling`. This type is incompatible with..."
125
- // pointing to the definition of `defineFunction` and finishing with
126
- // "some incompatible instantiation of `NODETYPE`"
127
- //
128
- // Having FunctionSpec<NODETYPE> above and FunctionHandler<*> below seems to
129
- // circumvent this error. This is not harmful for catching errors since
130
- // _functions is typed FunctionSpec<*> (it stores all TeX function specs).
131
-
132
- // Must be specified unless it's handled directly in the parser.
133
- handler: FunctionHandler<NodeType> | null | undefined;
134
- };
131
+ type FunctionDefSpec<
132
+ NODETYPE extends NodeType,
133
+ NAMES extends readonly string[],
134
+ > =
135
+ FunctionSpec<NODETYPE, NAMES[number]> & FunctionBuilders<NODETYPE> & {
136
+ /**
137
+ * The first argument to defineFunction is a single name or a list of names.
138
+ * All functions named in such a list will share a single implementation.
139
+ */
140
+ names: NAMES;
141
+ };
135
142
 
136
143
  /**
137
144
  * All registered functions.
@@ -159,30 +166,17 @@ export const _htmlGroupBuilders: Record<string, HtmlBuilder<any>> = {};
159
166
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
160
167
  export const _mathmlGroupBuilders: Record<string, MathMLBuilder<any>> = {};
161
168
 
162
- export default function defineFunction<NODETYPE extends NodeType>({
163
- type,
164
- names,
165
- props,
166
- handler,
167
- htmlBuilder,
168
- mathmlBuilder,
169
- }: FunctionDefSpec<NODETYPE>) {
170
- // Set default values of functions
171
- const data = {
172
- type,
173
- numArgs: props.numArgs,
174
- argTypes: props.argTypes,
175
- allowedInArgument: !!props.allowedInArgument,
176
- allowedInText: !!props.allowedInText,
177
- allowedInMath: (props.allowedInMath === undefined)
178
- ? true
179
- : props.allowedInMath,
180
- numOptionalArgs: props.numOptionalArgs || 0,
181
- infix: !!props.infix,
182
- primitive: !!props.primitive,
183
- handler,
184
- };
169
+ export default function defineFunction<
170
+ NODETYPE extends NodeType,
171
+ const NAMES extends readonly string[],
172
+ >(
173
+ data: FunctionDefSpec<NODETYPE, NAMES>,
174
+ ) {
175
+ const {type, names, htmlBuilder, mathmlBuilder} = data;
185
176
  for (let i = 0; i < names.length; ++i) {
177
+ // To avoid destructuring and rebuilding an object,
178
+ // we store the entire FunctionDefSpec object,
179
+ // even though Parser only needs the FunctionSpec fields.
186
180
  _functions[names[i]] = data;
187
181
  }
188
182
  if (type) {
@@ -207,14 +201,12 @@ export function defineFunctionBuilders<NODETYPE extends NodeType>({
207
201
  htmlBuilder?: HtmlBuilder<NODETYPE>;
208
202
  mathmlBuilder: MathMLBuilder<NODETYPE>;
209
203
  }) {
210
- defineFunction({
211
- type,
212
- names: [],
213
- props: {numArgs: 0},
214
- handler() { throw new Error('Should never be called.'); },
215
- htmlBuilder,
216
- mathmlBuilder,
217
- });
204
+ if (htmlBuilder) {
205
+ _htmlGroupBuilders[type] = htmlBuilder;
206
+ }
207
+ if (mathmlBuilder) {
208
+ _mathmlGroupBuilders[type] = mathmlBuilder;
209
+ }
218
210
  }
219
211
 
220
212
  export const normalizeArgument = function(arg: AnyParseNode): AnyParseNode {
@@ -15,8 +15,8 @@ import * as html from "../buildHTML";
15
15
  import * as mml from "../buildMathML";
16
16
 
17
17
  import type Parser from "../Parser";
18
- import type {ParseNode, AnyParseNode} from "../parseNode";
19
18
  import type {StyleStr, Mode} from "../types";
19
+ import type {AnyParseNode, ParseNode} from "../types/nodes";
20
20
  import type {HtmlBuilder, MathMLBuilder} from "../defineFunction";
21
21
  import type {HtmlDomNode} from "../domTree";
22
22
 
@@ -703,7 +703,6 @@ const alignedHandler = function(context: EnvContextLike, args: AnyParseNode[]) {
703
703
  validateAmsEnvironmentContext(context);
704
704
  }
705
705
  const cols: AlignSpec[] = [];
706
- const separationType: ColSeparationType = context.envName.includes("at") ? "alignat" : "align";
707
706
  const isSplit = context.envName === "split";
708
707
  const res = parseArray(context.parser,
709
708
  {
@@ -711,7 +710,7 @@ const alignedHandler = function(context: EnvContextLike, args: AnyParseNode[]) {
711
710
  addJot: true,
712
711
  autoTag: isSplit ? undefined : getAutoTag(context.envName),
713
712
  emptySingleRow: true,
714
- colSeparationType: separationType,
713
+ colSeparationType: context.envName.includes("at") ? "alignat" : "align",
715
714
  maxNumCols: isSplit ? 2 : undefined,
716
715
  leqno: context.parser.settings.leqno,
717
716
  },
@@ -893,8 +892,7 @@ defineEnvironment({
893
892
  payload.cols = [{type: "align", align: colAlign}];
894
893
  }
895
894
  }
896
- const res: ParseNode<"array"> =
897
- parseArray(context.parser, payload, dCellStyle(context.envName));
895
+ const res = parseArray(context.parser, payload, dCellStyle(context.envName));
898
896
  // Populate cols with the correct number of column alignment specs.
899
897
  const numCols = Math.max(0, ...res.body.map(row => row.length));
900
898
  res.cols = new Array(numCols).fill(
@@ -1006,8 +1004,7 @@ defineEnvironment({
1006
1004
  postgap: 0,
1007
1005
  }],
1008
1006
  };
1009
- const res: ParseNode<"array"> =
1010
- parseArray(context.parser, payload, dCellStyle(context.envName));
1007
+ const res = parseArray(context.parser, payload, dCellStyle(context.envName));
1011
1008
  return {
1012
1009
  type: "leftright",
1013
1010
  mode: context.mode,
@@ -1124,11 +1121,10 @@ defineMacro("\\notag", "\\nonumber");
1124
1121
  defineFunction({
1125
1122
  type: "text", // Doesn't matter what this is.
1126
1123
  names: ["\\hline", "\\hdashline"],
1127
- props: {
1128
- numArgs: 0,
1129
- allowedInText: true,
1130
- allowedInMath: true,
1131
- },
1124
+ numArgs: 0,
1125
+ allowedInText: true,
1126
+ allowedInMath: true,
1127
+
1132
1128
  handler(context, args) {
1133
1129
  throw new ParseError(
1134
1130
  `${context.funcName} valid only within array environment`);
@@ -8,7 +8,8 @@ import ParseError from "../ParseError";
8
8
  import {makeEm} from "../units";
9
9
 
10
10
  import type Parser from "../Parser";
11
- import type {ParseNode, AnyParseNode} from "../parseNode";
11
+ import type {AnyParseNode, ParseNode} from "../types/nodes";
12
+ import type {Slice4} from "../types";
12
13
 
13
14
  const cdArrowFunctionName: Record<string, string> = {
14
15
  ">": "\\\\cdrightarrow",
@@ -247,17 +248,16 @@ export function parseCD(parser: Parser): ParseNode<"array"> {
247
248
  defineFunction({
248
249
  type: "cdlabel",
249
250
  names: ["\\\\cdleft", "\\\\cdright"],
250
- props: {
251
- numArgs: 1,
252
- },
251
+ numArgs: 1,
253
252
  handler({parser, funcName}, args) {
254
253
  return {
255
254
  type: "cdlabel",
256
255
  mode: parser.mode,
257
- side: funcName.slice(4),
256
+ side: funcName.slice(4) as Slice4<typeof funcName>,
258
257
  label: args[0],
259
258
  };
260
259
  },
260
+
261
261
  htmlBuilder(group, options) {
262
262
  const newOptions = options.havingStyle(options.style.sup());
263
263
  const label = wrapFragment(
@@ -291,9 +291,8 @@ defineFunction({
291
291
  defineFunction({
292
292
  type: "cdlabelparent",
293
293
  names: ["\\\\cdparent"],
294
- props: {
295
- numArgs: 1,
296
- },
294
+ numArgs: 1,
295
+
297
296
  handler({parser}, args) {
298
297
  return {
299
298
  type: "cdlabelparent",
@@ -301,6 +300,7 @@ defineFunction({
301
300
  fragment: args[0],
302
301
  };
303
302
  },
303
+
304
304
  htmlBuilder(group, options) {
305
305
  // Wrap the vertical arrow and its labels.
306
306
  // The parent gets position: relative. The child gets position: absolute.
@@ -10,9 +10,9 @@ import {makeEm} from "../units";
10
10
  import * as html from "../buildHTML";
11
11
  import * as mml from "../buildMathML";
12
12
 
13
- import type {ParseNode, AnyParseNode} from "../parseNode";
14
13
  import type {HtmlBuilderSupSub, MathMLBuilder} from "../defineFunction";
15
14
  import type {HtmlDomNode} from "../domTree";
15
+ import type {AnyParseNode, ParseNode} from "../types/nodes";
16
16
 
17
17
  const getBaseSymbol = (group: HtmlDomNode): SymbolNode | undefined => {
18
18
  if (group instanceof SymbolNode) {
@@ -100,7 +100,7 @@ export const htmlBuilder: HtmlBuilderSupSub<"accent"> = (grp, options) => {
100
100
  width = svgData.vec[1];
101
101
  } else {
102
102
  accent = makeOrd({type: "textord", mode: group.mode, text: group.label},
103
- options, "textord");
103
+ options);
104
104
  accent = assertSymbolDomNode(accent);
105
105
  // Remove the italic correction of the accent, because it only serves to
106
106
  // shift the accent over to a place we don't want.
@@ -223,9 +223,8 @@ defineFunction({
223
223
  "\\Overrightarrow", "\\overleftrightarrow", "\\overgroup",
224
224
  "\\overlinesegment", "\\overleftharpoon", "\\overrightharpoon",
225
225
  ],
226
- props: {
227
- numArgs: 1,
228
- },
226
+ numArgs: 1,
227
+
229
228
  handler: (context, args) => {
230
229
  const base = normalizeArgument(args[0]);
231
230
 
@@ -244,6 +243,7 @@ defineFunction({
244
243
  base: base,
245
244
  };
246
245
  },
246
+
247
247
  htmlBuilder,
248
248
  mathmlBuilder,
249
249
  });
@@ -255,12 +255,11 @@ defineFunction({
255
255
  "\\'", "\\`", "\\^", "\\~", "\\=", "\\u", "\\.", '\\"',
256
256
  "\\c", "\\r", "\\H", "\\v", "\\textcircled",
257
257
  ],
258
- props: {
259
- numArgs: 1,
260
- allowedInText: true,
261
- allowedInMath: true, // unless in strict mode
262
- argTypes: ["primitive"],
263
- },
258
+ numArgs: 1,
259
+ allowedInText: true,
260
+ allowedInMath: true, // unless in strict mode
261
+ argTypes: ["primitive"],
262
+
264
263
  handler: (context, args) => {
265
264
  const base = args[0];
266
265
  let mode = context.parser.mode;
@@ -280,6 +279,4 @@ defineFunction({
280
279
  base: base,
281
280
  };
282
281
  },
283
- htmlBuilder,
284
- mathmlBuilder,
285
282
  });
@@ -7,7 +7,7 @@ import {stretchyMathML, stretchySvg} from "../stretchy";
7
7
  import * as html from "../buildHTML";
8
8
  import * as mml from "../buildMathML";
9
9
 
10
- import type {ParseNode} from "../parseNode";
10
+ import type {ParseNode} from "../types/nodes";
11
11
 
12
12
  defineFunction({
13
13
  type: "accentUnder",
@@ -15,9 +15,8 @@ defineFunction({
15
15
  "\\underleftarrow", "\\underrightarrow", "\\underleftrightarrow",
16
16
  "\\undergroup", "\\underlinesegment", "\\utilde",
17
17
  ],
18
- props: {
19
- numArgs: 1,
20
- },
18
+ numArgs: 1,
19
+
21
20
  handler: ({parser, funcName}, args) => {
22
21
  const base = args[0];
23
22
  return {
@@ -27,6 +26,7 @@ defineFunction({
27
26
  base: base,
28
27
  };
29
28
  },
29
+
30
30
  htmlBuilder: (group: ParseNode<"accentUnder">, options) => {
31
31
  // Treat under accents much like underlines.
32
32
  const innerGroup = html.buildGroup(group.base, options);
@@ -6,7 +6,7 @@ import {stretchyMathML, stretchySvg} from "../stretchy";
6
6
  import * as html from "../buildHTML";
7
7
  import * as mml from "../buildMathML";
8
8
 
9
- import type {ParseNode} from "../parseNode";
9
+ import type {ParseNode} from "../types/nodes";
10
10
  import type {MathDomNode} from "../mathMLTree";
11
11
 
12
12
  // Helper function
@@ -33,10 +33,9 @@ defineFunction({
33
33
  // The next 3 functions are here only to support the {CD} environment.
34
34
  "\\\\cdrightarrow", "\\\\cdleftarrow", "\\\\cdlongequal",
35
35
  ],
36
- props: {
37
- numArgs: 1,
38
- numOptionalArgs: 1,
39
- },
36
+ numArgs: 1,
37
+ numOptionalArgs: 1,
38
+
40
39
  handler({parser, funcName}, args, optArgs) {
41
40
  return {
42
41
  type: "xArrow",
@@ -46,6 +45,7 @@ defineFunction({
46
45
  below: optArgs[0],
47
46
  };
48
47
  },
48
+
49
49
  htmlBuilder(group: ParseNode<"xArrow">, options) {
50
50
  const style = options.style;
51
51
 
@@ -8,10 +8,9 @@ import {assertNodeType} from "../parseNode";
8
8
  defineFunction({
9
9
  type: "textord",
10
10
  names: ["\\@char"],
11
- props: {
12
- numArgs: 1,
13
- allowedInText: true,
14
- },
11
+ numArgs: 1,
12
+ allowedInText: true,
13
+
15
14
  handler({parser}, args) {
16
15
  const arg = assertNodeType(args[0], "ordgroup");
17
16
  const group = arg.body;
@@ -2,7 +2,7 @@ import defineFunction, {ordargument} from "../defineFunction";
2
2
  import {makeFragment} from "../buildCommon";
3
3
  import {MathNode} from "../mathMLTree";
4
4
  import {assertNodeType} from "../parseNode";
5
- import type {AnyParseNode} from "../parseNode";
5
+ import type {AnyParseNode} from "../types/nodes";
6
6
  import type {HtmlBuilder, MathMLBuilder} from "../defineFunction";
7
7
 
8
8
  import * as html from "../buildHTML";
@@ -36,11 +36,10 @@ const mathmlBuilder: MathMLBuilder<"color"> = (group, options) => {
36
36
  defineFunction({
37
37
  type: "color",
38
38
  names: ["\\textcolor"],
39
- props: {
40
- numArgs: 2,
41
- allowedInText: true,
42
- argTypes: ["color", "original"],
43
- },
39
+ numArgs: 2,
40
+ allowedInText: true,
41
+ argTypes: ["color", "original"],
42
+
44
43
  handler({parser}, args) {
45
44
  const color = assertNodeType(args[0], "color-token").color;
46
45
  const body = args[1];
@@ -51,6 +50,7 @@ defineFunction({
51
50
  body: (ordargument(body) as AnyParseNode[]),
52
51
  };
53
52
  },
53
+
54
54
  htmlBuilder,
55
55
  mathmlBuilder,
56
56
  });
@@ -58,11 +58,10 @@ defineFunction({
58
58
  defineFunction({
59
59
  type: "color",
60
60
  names: ["\\color"],
61
- props: {
62
- numArgs: 1,
63
- allowedInText: true,
64
- argTypes: ["color"],
65
- },
61
+ numArgs: 1,
62
+ allowedInText: true,
63
+ argTypes: ["color"],
64
+
66
65
  handler({parser, breakOnTokenText}, args) {
67
66
  const color = assertNodeType(args[0], "color-token").color;
68
67
 
@@ -82,6 +81,4 @@ defineFunction({
82
81
  body,
83
82
  };
84
83
  },
85
- htmlBuilder,
86
- mathmlBuilder,
87
84
  });
@@ -10,11 +10,9 @@ import {assertNodeType} from "../parseNode";
10
10
  defineFunction({
11
11
  type: "cr",
12
12
  names: ["\\\\"],
13
- props: {
14
- numArgs: 0,
15
- numOptionalArgs: 0,
16
- allowedInText: true,
17
- },
13
+ numArgs: 0,
14
+ numOptionalArgs: 0,
15
+ allowedInText: true,
18
16
 
19
17
  handler({parser}, args, optArgs) {
20
18
  const size = parser.gullet.future().text === "[" ?
@@ -62,10 +62,9 @@ defineFunction({
62
62
  "\\global", "\\long",
63
63
  "\\\\globallong", // can’t be entered directly
64
64
  ],
65
- props: {
66
- numArgs: 0,
67
- allowedInText: true,
68
- },
65
+ numArgs: 0,
66
+ allowedInText: true,
67
+
69
68
  handler({parser, funcName}) {
70
69
  parser.consumeSpaces();
71
70
  const token = parser.fetch();
@@ -87,11 +86,10 @@ defineFunction({
87
86
  defineFunction({
88
87
  type: "internal",
89
88
  names: ["\\def", "\\gdef", "\\edef", "\\xdef"],
90
- props: {
91
- numArgs: 0,
92
- allowedInText: true,
93
- primitive: true,
94
- },
89
+ numArgs: 0,
90
+ allowedInText: true,
91
+ primitive: true,
92
+
95
93
  handler({parser, funcName}) {
96
94
  let tok = parser.gullet.popToken();
97
95
  const name = tok.text;
@@ -168,11 +166,10 @@ defineFunction({
168
166
  "\\let",
169
167
  "\\\\globallet", // can’t be entered directly
170
168
  ],
171
- props: {
172
- numArgs: 0,
173
- allowedInText: true,
174
- primitive: true,
175
- },
169
+ numArgs: 0,
170
+ allowedInText: true,
171
+ primitive: true,
172
+
176
173
  handler({parser, funcName}) {
177
174
  const name = checkControlSequence(parser.gullet.popToken());
178
175
  parser.gullet.consumeSpaces();
@@ -192,11 +189,10 @@ defineFunction({
192
189
  "\\futurelet",
193
190
  "\\\\globalfuture", // can’t be entered directly
194
191
  ],
195
- props: {
196
- numArgs: 0,
197
- allowedInText: true,
198
- primitive: true,
199
- },
192
+ numArgs: 0,
193
+ allowedInText: true,
194
+ primitive: true,
195
+
200
196
  handler({parser, funcName}) {
201
197
  const name = checkControlSequence(parser.gullet.popToken());
202
198
  const middle = parser.gullet.popToken();