katex 0.16.32 → 0.16.34
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.
- package/README.md +3 -3
- package/contrib/auto-render/{auto-render.js → auto-render.ts} +41 -19
- package/contrib/auto-render/{splitAtDelimiters.js → splitAtDelimiters.ts} +18 -4
- package/contrib/auto-render/test/{auto-render-spec.js → auto-render-spec.ts} +10 -2
- package/contrib/copy-tex/README.md +2 -2
- package/contrib/copy-tex/{copy-tex.js → copy-tex.ts} +4 -6
- package/contrib/copy-tex/{katex2tex.js → katex2tex.ts} +2 -3
- package/contrib/mathtex-script-type/README.md +5 -5
- package/contrib/mhchem/README.md +1 -1
- package/contrib/render-a11y-string/{render-a11y-string.js → render-a11y-string.ts} +18 -33
- package/contrib/render-a11y-string/test/{render-a11y-string-spec.js → render-a11y-string-spec.ts} +0 -1
- package/dist/README.md +3 -3
- package/dist/contrib/auto-render.js +24 -57
- package/dist/contrib/auto-render.min.js +1 -1
- package/dist/contrib/auto-render.mjs +16586 -210
- package/dist/contrib/copy-tex.js +23 -37
- package/dist/contrib/copy-tex.min.js +1 -1
- package/dist/contrib/copy-tex.mjs +77 -95
- package/dist/contrib/mathtex-script-type.js +0 -3
- package/dist/contrib/mathtex-script-type.mjs +16427 -4
- package/dist/contrib/mhchem.js +55 -303
- package/dist/contrib/mhchem.mjs +12884 -723
- package/dist/contrib/render-a11y-string.js +13 -108
- package/dist/contrib/render-a11y-string.min.js +1 -1
- package/dist/contrib/render-a11y-string.mjs +17020 -760
- package/dist/katex-swap.css +2 -1
- package/dist/katex-swap.min.css +1 -1
- package/dist/katex.css +2 -1
- package/dist/katex.js +4547 -5680
- package/dist/katex.min.css +1 -1
- package/dist/katex.min.js +1 -1
- package/dist/katex.mjs +11854 -13828
- package/{katex.js → katex.ts} +8 -5
- package/package.json +34 -31
- package/src/{Lexer.js → Lexer.ts} +1 -2
- package/src/{MacroExpander.js → MacroExpander.ts} +11 -15
- package/src/{Namespace.js → Namespace.ts} +4 -6
- package/src/{Options.js → Options.ts} +7 -12
- package/src/{ParseError.js → ParseError.ts} +16 -26
- package/src/{Parser.js → Parser.ts} +68 -56
- package/src/{Settings.js → Settings.ts} +70 -70
- package/src/{SourceLocation.js → SourceLocation.ts} +6 -7
- package/src/{Style.js → Style.ts} +4 -5
- package/src/{Token.js → Token.ts} +8 -6
- package/src/{buildCommon.js → buildCommon.ts} +62 -55
- package/src/{buildHTML.js → buildHTML.ts} +29 -25
- package/src/{buildMathML.js → buildMathML.ts} +15 -13
- package/src/{buildTree.js → buildTree.ts} +1 -2
- package/src/{defineEnvironment.js → defineEnvironment.ts} +26 -27
- package/src/{defineFunction.js → defineFunction.ts} +54 -56
- package/src/{defineMacro.js → defineMacro.ts} +12 -13
- package/src/{delimiter.js → delimiter.ts} +19 -17
- package/src/{domTree.js → domTree.ts} +94 -103
- package/src/environments/{array.js → array.ts} +109 -99
- package/src/environments/{cd.js → cd.ts} +9 -11
- package/src/{environments.js → environments.ts} +0 -1
- package/src/{fontMetrics.js → fontMetrics.ts} +10 -12
- package/src/fontMetricsData.d.ts +3 -0
- package/src/functions/{accent.js → accent.ts} +1 -2
- package/src/functions/{accentunder.js → accentunder.ts} +0 -1
- package/src/functions/{arrow.js → arrow.ts} +4 -6
- package/src/functions/{char.js → char.ts} +0 -1
- package/src/functions/{color.js → color.ts} +5 -6
- package/src/functions/{cr.js → cr.ts} +0 -1
- package/src/functions/{def.js → def.ts} +9 -7
- package/src/functions/{delimsizing.js → delimsizing.ts} +11 -9
- package/src/functions/{enclose.js → enclose.ts} +3 -4
- package/src/functions/{environment.js → environment.ts} +2 -3
- package/src/functions/{font.js → font.ts} +4 -4
- package/src/functions/{genfrac.js → genfrac.ts} +14 -15
- package/src/functions/{hbox.js → hbox.ts} +0 -1
- package/src/functions/{horizBrace.js → horizBrace.ts} +4 -5
- package/src/functions/{href.js → href.ts} +4 -4
- package/src/functions/{html.js → html.ts} +3 -3
- package/src/functions/{htmlmathml.js → htmlmathml.ts} +0 -1
- package/src/functions/{includegraphics.js → includegraphics.ts} +0 -1
- package/src/functions/{kern.js → kern.ts} +0 -1
- package/src/functions/{lap.js → lap.ts} +0 -1
- package/src/functions/{math.js → math.ts} +0 -1
- package/src/functions/{mathchoice.js → mathchoice.ts} +2 -2
- package/src/functions/{mclass.js → mclass.ts} +5 -6
- package/src/functions/{op.js → op.ts} +9 -11
- package/src/functions/{operatorname.js → operatorname.ts} +4 -7
- package/src/functions/{ordgroup.js → ordgroup.ts} +0 -2
- package/src/functions/{overline.js → overline.ts} +0 -1
- package/src/functions/{phantom.js → phantom.ts} +0 -1
- package/src/functions/{pmb.js → pmb.ts} +0 -1
- package/src/functions/{raisebox.js → raisebox.ts} +0 -1
- package/src/functions/{relax.js → relax.ts} +0 -1
- package/src/functions/{rule.js → rule.ts} +0 -1
- package/src/functions/{sizing.js → sizing.ts} +0 -1
- package/src/functions/{smash.js → smash.ts} +2 -4
- package/src/functions/{sqrt.js → sqrt.ts} +0 -1
- package/src/functions/{styling.js → styling.ts} +3 -3
- package/src/functions/{supsub.js → supsub.ts} +6 -8
- package/src/functions/{symbolsOp.js → symbolsOp.ts} +0 -2
- package/src/functions/{symbolsOrd.js → symbolsOrd.ts} +1 -2
- package/src/functions/{symbolsSpacing.js → symbolsSpacing.ts} +2 -3
- package/src/functions/{tag.js → tag.ts} +0 -2
- package/src/functions/{text.js → text.ts} +7 -6
- package/src/functions/{underline.js → underline.ts} +0 -1
- package/src/functions/utils/{assembleSupSub.js → assembleSupSub.ts} +2 -3
- package/src/functions/{vcenter.js → vcenter.ts} +0 -2
- package/src/functions/{verb.js → verb.ts} +0 -1
- package/src/{functions.js → functions.ts} +0 -1
- package/src/{macros.js → macros.ts} +10 -8
- package/src/{mathMLTree.js → mathMLTree.ts} +5 -6
- package/src/parseNode.ts +522 -0
- package/src/{parseTree.js → parseTree.ts} +5 -3
- package/src/{spacingData.js → spacingData.ts} +11 -12
- package/src/{stretchy.js → stretchy.ts} +7 -7
- package/src/styles/katex-swap.scss +1 -4
- package/src/styles/katex.scss +9 -0
- package/src/{svgGeometry.js → svgGeometry.ts} +1 -2
- package/src/{symbols.js → symbols.ts} +6 -6
- package/src/{tree.js → tree.ts} +5 -7
- package/src/{types.js → types.ts} +1 -2
- package/src/unicodeAccents.js +4 -1
- package/src/{unicodeScripts.js → unicodeScripts.ts} +1 -3
- package/src/{unicodeSupOrSub.js → unicodeSupOrSub.ts} +1 -1
- package/src/unicodeSymbols.js +4 -3
- package/src/{units.js → units.ts} +2 -4
- package/src/{utils.js → utils.ts} +2 -3
- package/src/{wide-character.js → wide-character.ts} +8 -10
- package/types/katex.d.ts +13 -12
- package/src/parseNode.js +0 -523
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
/* eslint no-constant-condition:0 */
|
|
3
2
|
import functions from "./functions";
|
|
4
3
|
import MacroExpander, {implicitCommands} from "./MacroExpander";
|
|
@@ -58,7 +57,7 @@ export default class Parser {
|
|
|
58
57
|
gullet: MacroExpander;
|
|
59
58
|
settings: Settings;
|
|
60
59
|
leftrightDepth: number;
|
|
61
|
-
nextToken:
|
|
60
|
+
nextToken: Token | null;
|
|
62
61
|
|
|
63
62
|
constructor(input: string, settings: Settings) {
|
|
64
63
|
// Start in math mode
|
|
@@ -70,13 +69,14 @@ export default class Parser {
|
|
|
70
69
|
this.settings = settings;
|
|
71
70
|
// Count leftright depth (for \middle errors)
|
|
72
71
|
this.leftrightDepth = 0;
|
|
72
|
+
this.nextToken = null;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
/**
|
|
76
76
|
* Checks a result to make sure it has the right type, and throws an
|
|
77
77
|
* appropriate error otherwise.
|
|
78
78
|
*/
|
|
79
|
-
expect(text: string, consume
|
|
79
|
+
expect(text: string, consume = true) {
|
|
80
80
|
if (this.fetch().text !== text) {
|
|
81
81
|
throw new ParseError(
|
|
82
82
|
`Expected '${text}', got '${this.fetch().text}'`, this.fetch()
|
|
@@ -235,20 +235,21 @@ export default class Parser {
|
|
|
235
235
|
let funcName;
|
|
236
236
|
|
|
237
237
|
for (let i = 0; i < body.length; i++) {
|
|
238
|
-
|
|
238
|
+
const node = body[i];
|
|
239
|
+
if (node.type === "infix") {
|
|
239
240
|
if (overIndex !== -1) {
|
|
240
241
|
throw new ParseError(
|
|
241
242
|
"only one infix operator per group",
|
|
242
|
-
|
|
243
|
+
node.token);
|
|
243
244
|
}
|
|
244
245
|
overIndex = i;
|
|
245
|
-
funcName =
|
|
246
|
+
funcName = node.replaceWith;
|
|
246
247
|
}
|
|
247
248
|
}
|
|
248
249
|
|
|
249
250
|
if (overIndex !== -1 && funcName) {
|
|
250
|
-
let numerNode;
|
|
251
|
-
let denomNode;
|
|
251
|
+
let numerNode: AnyParseNode;
|
|
252
|
+
let denomNode: AnyParseNode;
|
|
252
253
|
|
|
253
254
|
const numerBody = body.slice(0, overIndex);
|
|
254
255
|
const denomBody = body.slice(overIndex + 1);
|
|
@@ -290,7 +291,7 @@ export default class Parser {
|
|
|
290
291
|
this.consumeSpaces(); // ignore spaces before sup/subscript argument
|
|
291
292
|
|
|
292
293
|
// Skip over allowed internal nodes such as \relax
|
|
293
|
-
let group:
|
|
294
|
+
let group: AnyParseNode | null | undefined;
|
|
294
295
|
do {
|
|
295
296
|
group = this.parseGroup(name);
|
|
296
297
|
} while (group?.type === "internal");
|
|
@@ -310,19 +311,18 @@ export default class Parser {
|
|
|
310
311
|
* contained within a color node whose color is determined by errorColor
|
|
311
312
|
*/
|
|
312
313
|
formatUnsupportedCmd(text: string): UnsupportedCmdParseNode {
|
|
313
|
-
const textordArray = [];
|
|
314
|
+
const textordArray: ParseNode<"textord">[] = [];
|
|
314
315
|
|
|
315
316
|
for (let i = 0; i < text.length; i++) {
|
|
316
317
|
textordArray.push({type: "textord", mode: "text", text: text[i]});
|
|
317
318
|
}
|
|
318
319
|
|
|
319
|
-
const textNode = {
|
|
320
|
+
const textNode: ParseNode<"text"> = {
|
|
320
321
|
type: "text",
|
|
321
322
|
mode: this.mode,
|
|
322
323
|
body: textordArray,
|
|
323
324
|
};
|
|
324
|
-
|
|
325
|
-
const colorNode = {
|
|
325
|
+
const colorNode: ParseNode<"color"> = {
|
|
326
326
|
type: "color",
|
|
327
327
|
mode: this.mode,
|
|
328
328
|
color: this.settings.errorColor,
|
|
@@ -335,7 +335,7 @@ export default class Parser {
|
|
|
335
335
|
/**
|
|
336
336
|
* Parses a group with optional super/subscripts.
|
|
337
337
|
*/
|
|
338
|
-
parseAtom(breakOnTokenText?: BreakToken):
|
|
338
|
+
parseAtom(breakOnTokenText?: BreakToken): AnyParseNode | null | undefined {
|
|
339
339
|
// The body of an atom is an implicit group, so that things like
|
|
340
340
|
// \left(x\right)^2 work correctly.
|
|
341
341
|
const base = this.parseGroup("atom", breakOnTokenText);
|
|
@@ -353,8 +353,8 @@ export default class Parser {
|
|
|
353
353
|
|
|
354
354
|
// Note that base may be empty (i.e. null) at this point.
|
|
355
355
|
|
|
356
|
-
let superscript;
|
|
357
|
-
let subscript;
|
|
356
|
+
let superscript: AnyParseNode | null | undefined;
|
|
357
|
+
let subscript: AnyParseNode | null | undefined;
|
|
358
358
|
while (true) {
|
|
359
359
|
// Guaranteed in math mode, so eat any spaces first.
|
|
360
360
|
this.consumeSpaces();
|
|
@@ -395,10 +395,11 @@ export default class Parser {
|
|
|
395
395
|
if (superscript) {
|
|
396
396
|
throw new ParseError("Double superscript", lex);
|
|
397
397
|
}
|
|
398
|
-
|
|
398
|
+
|
|
399
|
+
const prime: ParseNode<"textord"> = {type: "textord", mode: this.mode, text: "\\prime"};
|
|
399
400
|
|
|
400
401
|
// Many primes can be grouped together, so we handle this here
|
|
401
|
-
const primes = [prime];
|
|
402
|
+
const primes: AnyParseNode[] = [prime];
|
|
402
403
|
this.consume();
|
|
403
404
|
// Keep lexing tokens until we get something that's not a prime
|
|
404
405
|
while (this.fetch().text === "'") {
|
|
@@ -466,7 +467,7 @@ export default class Parser {
|
|
|
466
467
|
parseFunction(
|
|
467
468
|
breakOnTokenText?: BreakToken,
|
|
468
469
|
name?: string, // For determining its context
|
|
469
|
-
):
|
|
470
|
+
): AnyParseNode | null | undefined {
|
|
470
471
|
const token = this.fetch();
|
|
471
472
|
const func = token.text;
|
|
472
473
|
const funcData = functions[func];
|
|
@@ -497,7 +498,7 @@ export default class Parser {
|
|
|
497
498
|
callFunction(
|
|
498
499
|
name: string,
|
|
499
500
|
args: AnyParseNode[],
|
|
500
|
-
optArgs: (
|
|
501
|
+
optArgs: (AnyParseNode | null | undefined)[],
|
|
501
502
|
token?: Token,
|
|
502
503
|
breakOnTokenText?: BreakToken,
|
|
503
504
|
): AnyParseNode {
|
|
@@ -520,31 +521,32 @@ export default class Parser {
|
|
|
520
521
|
*/
|
|
521
522
|
parseArguments(
|
|
522
523
|
func: string, // Should look like "\name" or "\begin{name}".
|
|
523
|
-
funcData: FunctionSpec
|
|
524
|
+
funcData: FunctionSpec<any> | EnvSpec<any>,
|
|
524
525
|
): {
|
|
525
|
-
args: AnyParseNode[]
|
|
526
|
-
optArgs: (
|
|
526
|
+
args: AnyParseNode[];
|
|
527
|
+
optArgs: (AnyParseNode | null | undefined)[];
|
|
527
528
|
} {
|
|
528
529
|
const totalArgs = funcData.numArgs + funcData.numOptionalArgs;
|
|
529
530
|
if (totalArgs === 0) {
|
|
530
531
|
return {args: [], optArgs: []};
|
|
531
532
|
}
|
|
532
533
|
|
|
533
|
-
const args = [];
|
|
534
|
-
const optArgs = [];
|
|
534
|
+
const args: AnyParseNode[] = [];
|
|
535
|
+
const optArgs: (AnyParseNode | null | undefined)[] = [];
|
|
535
536
|
|
|
536
537
|
for (let i = 0; i < totalArgs; i++) {
|
|
537
538
|
let argType = funcData.argTypes && funcData.argTypes[i];
|
|
538
539
|
const isOptional = i < funcData.numOptionalArgs;
|
|
539
540
|
|
|
540
|
-
if ((funcData.primitive && argType == null) ||
|
|
541
|
+
if (("primitive" in funcData && funcData.primitive && argType == null) ||
|
|
541
542
|
// \sqrt expands into primitive if optional argument doesn't exist
|
|
542
|
-
(funcData.type === "sqrt" && i === 1 && optArgs[0] == null)
|
|
543
|
+
(funcData.type === "sqrt" && i === 1 && optArgs[0] == null)
|
|
544
|
+
) {
|
|
543
545
|
argType = "primitive";
|
|
544
546
|
}
|
|
545
547
|
|
|
546
548
|
const arg = this.parseGroupOfType(`argument to '${func}'`,
|
|
547
|
-
argType, isOptional);
|
|
549
|
+
argType as ArgType | null | undefined, isOptional);
|
|
548
550
|
if (isOptional) {
|
|
549
551
|
optArgs.push(arg);
|
|
550
552
|
} else if (arg != null) {
|
|
@@ -562,9 +564,9 @@ export default class Parser {
|
|
|
562
564
|
*/
|
|
563
565
|
parseGroupOfType(
|
|
564
566
|
name: string,
|
|
565
|
-
type:
|
|
567
|
+
type: ArgType | null | undefined,
|
|
566
568
|
optional: boolean,
|
|
567
|
-
):
|
|
569
|
+
): AnyParseNode | null | undefined {
|
|
568
570
|
switch (type) {
|
|
569
571
|
case "color":
|
|
570
572
|
return this.parseColorGroup(optional);
|
|
@@ -630,13 +632,13 @@ export default class Parser {
|
|
|
630
632
|
parseStringGroup(
|
|
631
633
|
modeName: ArgType, // Used to describe the mode in error messages.
|
|
632
634
|
optional: boolean,
|
|
633
|
-
):
|
|
635
|
+
): Token | null | undefined {
|
|
634
636
|
const argToken = this.gullet.scanArgument(optional);
|
|
635
637
|
if (argToken == null) {
|
|
636
638
|
return null;
|
|
637
639
|
}
|
|
638
640
|
let str = "";
|
|
639
|
-
let nextToken;
|
|
641
|
+
let nextToken: Token;
|
|
640
642
|
while ((nextToken = this.fetch()).text !== "EOF") {
|
|
641
643
|
str += nextToken.text;
|
|
642
644
|
this.consume();
|
|
@@ -658,7 +660,7 @@ export default class Parser {
|
|
|
658
660
|
const firstToken = this.fetch();
|
|
659
661
|
let lastToken = firstToken;
|
|
660
662
|
let str = "";
|
|
661
|
-
let nextToken;
|
|
663
|
+
let nextToken: Token;
|
|
662
664
|
while ((nextToken = this.fetch()).text !== "EOF" &&
|
|
663
665
|
regex.test(str + nextToken.text)) {
|
|
664
666
|
lastToken = nextToken;
|
|
@@ -676,7 +678,7 @@ export default class Parser {
|
|
|
676
678
|
/**
|
|
677
679
|
* Parses a color description.
|
|
678
680
|
*/
|
|
679
|
-
parseColorGroup(optional: boolean):
|
|
681
|
+
parseColorGroup(optional: boolean): ParseNode<"color-token"> | null | undefined {
|
|
680
682
|
const res = this.parseStringGroup("color", optional);
|
|
681
683
|
if (res == null) {
|
|
682
684
|
return null;
|
|
@@ -694,6 +696,7 @@ export default class Parser {
|
|
|
694
696
|
// Predefined color names are all missed by this RegEx pattern.
|
|
695
697
|
color = "#" + color;
|
|
696
698
|
}
|
|
699
|
+
|
|
697
700
|
return {
|
|
698
701
|
type: "color-token",
|
|
699
702
|
mode: this.mode,
|
|
@@ -704,8 +707,8 @@ export default class Parser {
|
|
|
704
707
|
/**
|
|
705
708
|
* Parses a size specification, consisting of magnitude and unit.
|
|
706
709
|
*/
|
|
707
|
-
parseSizeGroup(optional: boolean):
|
|
708
|
-
let res;
|
|
710
|
+
parseSizeGroup(optional: boolean): ParseNode<"size"> | null | undefined {
|
|
711
|
+
let res: Token | null | undefined;
|
|
709
712
|
let isBlank = false;
|
|
710
713
|
// don't expand before parseStringGroup
|
|
711
714
|
this.gullet.consumeSpaces();
|
|
@@ -736,6 +739,7 @@ export default class Parser {
|
|
|
736
739
|
if (!validUnit(data)) {
|
|
737
740
|
throw new ParseError("Invalid unit: '" + data.unit + "'", res);
|
|
738
741
|
}
|
|
742
|
+
|
|
739
743
|
return {
|
|
740
744
|
type: "size",
|
|
741
745
|
mode: this.mode,
|
|
@@ -748,7 +752,7 @@ export default class Parser {
|
|
|
748
752
|
* Parses an URL, checking escaped letters and allowed protocols,
|
|
749
753
|
* and setting the catcode of % as an active character (as in \hyperref).
|
|
750
754
|
*/
|
|
751
|
-
parseUrlGroup(optional: boolean):
|
|
755
|
+
parseUrlGroup(optional: boolean): ParseNode<"url"> | null | undefined {
|
|
752
756
|
this.gullet.lexer.setCatcode("%", 13); // active character
|
|
753
757
|
this.gullet.lexer.setCatcode("~", 12); // other character
|
|
754
758
|
const res = this.parseStringGroup("url", optional);
|
|
@@ -772,7 +776,7 @@ export default class Parser {
|
|
|
772
776
|
/**
|
|
773
777
|
* Parses an argument with the mode specified.
|
|
774
778
|
*/
|
|
775
|
-
parseArgumentGroup(optional: boolean, mode?: Mode):
|
|
779
|
+
parseArgumentGroup(optional: boolean, mode?: Mode): ParseNode<"ordgroup"> | null | undefined {
|
|
776
780
|
const argToken = this.gullet.scanArgument(optional);
|
|
777
781
|
if (argToken == null) {
|
|
778
782
|
return null;
|
|
@@ -787,7 +791,7 @@ export default class Parser {
|
|
|
787
791
|
// TODO: find an alternative way to denote the end
|
|
788
792
|
this.expect("EOF"); // expect the end of the argument
|
|
789
793
|
this.gullet.endGroup();
|
|
790
|
-
const result = {
|
|
794
|
+
const result: ParseNode<"ordgroup"> = {
|
|
791
795
|
type: "ordgroup",
|
|
792
796
|
mode: this.mode,
|
|
793
797
|
loc: argToken.loc,
|
|
@@ -809,11 +813,11 @@ export default class Parser {
|
|
|
809
813
|
parseGroup(
|
|
810
814
|
name: string, // For error reporting.
|
|
811
815
|
breakOnTokenText?: BreakToken,
|
|
812
|
-
):
|
|
816
|
+
): AnyParseNode | null | undefined {
|
|
813
817
|
const firstToken = this.fetch();
|
|
814
818
|
const text = firstToken.text;
|
|
815
819
|
|
|
816
|
-
let result;
|
|
820
|
+
let result: AnyParseNode | null | undefined;
|
|
817
821
|
// Try to parse an open brace or \begingroup
|
|
818
822
|
if (text === "{" || text === "\\begingroup") {
|
|
819
823
|
this.consume();
|
|
@@ -866,14 +870,21 @@ export default class Parser {
|
|
|
866
870
|
let n = group.length - 1;
|
|
867
871
|
for (let i = 0; i < n; ++i) {
|
|
868
872
|
const a = group[i];
|
|
869
|
-
|
|
873
|
+
if (a.type !== "textord") {
|
|
874
|
+
continue;
|
|
875
|
+
}
|
|
870
876
|
const v = a.text;
|
|
871
|
-
|
|
872
|
-
|
|
877
|
+
const next = group[i + 1];
|
|
878
|
+
if (!next || next.type !== "textord") {
|
|
879
|
+
continue;
|
|
880
|
+
}
|
|
881
|
+
if (v === "-" && next.text === "-") {
|
|
882
|
+
const afterNext = group[i + 2];
|
|
883
|
+
if (i + 1 < n && afterNext && afterNext.type === "textord" && afterNext.text === "-") {
|
|
873
884
|
group.splice(i, 3, {
|
|
874
885
|
type: "textord",
|
|
875
886
|
mode: "text",
|
|
876
|
-
loc: SourceLocation.range(a,
|
|
887
|
+
loc: SourceLocation.range(a, afterNext),
|
|
877
888
|
text: "---",
|
|
878
889
|
});
|
|
879
890
|
n -= 2;
|
|
@@ -881,17 +892,17 @@ export default class Parser {
|
|
|
881
892
|
group.splice(i, 2, {
|
|
882
893
|
type: "textord",
|
|
883
894
|
mode: "text",
|
|
884
|
-
loc: SourceLocation.range(a,
|
|
895
|
+
loc: SourceLocation.range(a, next),
|
|
885
896
|
text: "--",
|
|
886
897
|
});
|
|
887
898
|
n -= 1;
|
|
888
899
|
}
|
|
889
900
|
}
|
|
890
|
-
if ((v === "'" || v === "`") &&
|
|
901
|
+
if ((v === "'" || v === "`") && next.text === v) {
|
|
891
902
|
group.splice(i, 2, {
|
|
892
903
|
type: "textord",
|
|
893
904
|
mode: "text",
|
|
894
|
-
loc: SourceLocation.range(a,
|
|
905
|
+
loc: SourceLocation.range(a, next),
|
|
895
906
|
text: v + v,
|
|
896
907
|
});
|
|
897
908
|
n -= 1;
|
|
@@ -903,7 +914,7 @@ export default class Parser {
|
|
|
903
914
|
* Parse a single symbol out of the string. Here, we handle single character
|
|
904
915
|
* symbols and special functions like \verb.
|
|
905
916
|
*/
|
|
906
|
-
parseSymbol():
|
|
917
|
+
parseSymbol(): AnyParseNode | null | undefined {
|
|
907
918
|
const nucleus = this.fetch();
|
|
908
919
|
let text = nucleus.text;
|
|
909
920
|
|
|
@@ -921,6 +932,7 @@ export default class Parser {
|
|
|
921
932
|
please report what input caused this bug`);
|
|
922
933
|
}
|
|
923
934
|
arg = arg.slice(1, -1); // remove first and last char
|
|
935
|
+
|
|
924
936
|
return {
|
|
925
937
|
type: "verb",
|
|
926
938
|
mode: "text",
|
|
@@ -963,8 +975,8 @@ export default class Parser {
|
|
|
963
975
|
const loc = SourceLocation.range(nucleus);
|
|
964
976
|
let s: SymbolParseNode;
|
|
965
977
|
if (ATOMS.hasOwnProperty(group)) {
|
|
966
|
-
//
|
|
967
|
-
const family
|
|
978
|
+
// TODO(ts)
|
|
979
|
+
const family = group as Atom;
|
|
968
980
|
s = {
|
|
969
981
|
type: "atom",
|
|
970
982
|
mode: this.mode,
|
|
@@ -973,15 +985,15 @@ export default class Parser {
|
|
|
973
985
|
text,
|
|
974
986
|
};
|
|
975
987
|
} else {
|
|
976
|
-
//
|
|
988
|
+
// TODO(ts)
|
|
977
989
|
s = {
|
|
978
|
-
type: group,
|
|
990
|
+
type: group as Exclude<SymbolParseNode["type"], "atom">,
|
|
979
991
|
mode: this.mode,
|
|
980
992
|
loc,
|
|
981
993
|
text,
|
|
982
994
|
};
|
|
983
995
|
}
|
|
984
|
-
//
|
|
996
|
+
// TODO(ts)
|
|
985
997
|
symbol = s;
|
|
986
998
|
} else if (text.charCodeAt(0) >= 0x80) { // no symbol for e.g. ^
|
|
987
999
|
if (this.settings.strict) {
|
|
@@ -1033,12 +1045,12 @@ export default class Parser {
|
|
|
1033
1045
|
label: command,
|
|
1034
1046
|
isStretchy: false,
|
|
1035
1047
|
isShifty: true,
|
|
1036
|
-
//
|
|
1048
|
+
// TODO(ts)
|
|
1037
1049
|
base: symbol,
|
|
1038
1050
|
};
|
|
1039
1051
|
}
|
|
1040
1052
|
}
|
|
1041
|
-
//
|
|
1053
|
+
// TODO(ts)
|
|
1042
1054
|
return symbol;
|
|
1043
1055
|
}
|
|
1044
1056
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
/* eslint no-console:0 */
|
|
3
2
|
/**
|
|
4
3
|
* This is a module for storing settings passed into KaTeX. It correctly handles
|
|
@@ -14,50 +13,52 @@ import type {MacroMap} from "./defineMacro";
|
|
|
14
13
|
|
|
15
14
|
export type StrictFunction =
|
|
16
15
|
(errorCode: string, errorMsg: string, token?: Token | AnyParseNode) =>
|
|
17
|
-
|
|
16
|
+
(boolean | string) | null | undefined;
|
|
18
17
|
|
|
19
18
|
export type TrustContextTypes = {
|
|
20
|
-
"\\href": {
|
|
21
|
-
command: "\\href"
|
|
22
|
-
url: string
|
|
23
|
-
protocol?: string
|
|
24
|
-
|
|
25
|
-
"\\includegraphics": {
|
|
26
|
-
command: "\\includegraphics"
|
|
27
|
-
url: string
|
|
28
|
-
protocol?: string
|
|
29
|
-
|
|
30
|
-
"\\url": {
|
|
31
|
-
command: "\\url"
|
|
32
|
-
url: string
|
|
33
|
-
protocol?: string
|
|
34
|
-
|
|
35
|
-
"\\htmlClass": {
|
|
36
|
-
command: "\\htmlClass"
|
|
37
|
-
class: string
|
|
38
|
-
|
|
39
|
-
"\\htmlId": {
|
|
40
|
-
command: "\\htmlId"
|
|
41
|
-
id: string
|
|
42
|
-
|
|
43
|
-
"\\htmlStyle": {
|
|
44
|
-
command: "\\htmlStyle"
|
|
45
|
-
style: string
|
|
46
|
-
|
|
47
|
-
"\\htmlData": {
|
|
48
|
-
command: "\\htmlData"
|
|
49
|
-
attributes:
|
|
50
|
-
|
|
19
|
+
"\\href": {
|
|
20
|
+
command: "\\href";
|
|
21
|
+
url: string;
|
|
22
|
+
protocol?: string;
|
|
23
|
+
};
|
|
24
|
+
"\\includegraphics": {
|
|
25
|
+
command: "\\includegraphics";
|
|
26
|
+
url: string;
|
|
27
|
+
protocol?: string;
|
|
28
|
+
};
|
|
29
|
+
"\\url": {
|
|
30
|
+
command: "\\url";
|
|
31
|
+
url: string;
|
|
32
|
+
protocol?: string;
|
|
33
|
+
};
|
|
34
|
+
"\\htmlClass": {
|
|
35
|
+
command: "\\htmlClass";
|
|
36
|
+
class: string;
|
|
37
|
+
};
|
|
38
|
+
"\\htmlId": {
|
|
39
|
+
command: "\\htmlId";
|
|
40
|
+
id: string;
|
|
41
|
+
};
|
|
42
|
+
"\\htmlStyle": {
|
|
43
|
+
command: "\\htmlStyle";
|
|
44
|
+
style: string;
|
|
45
|
+
};
|
|
46
|
+
"\\htmlData": {
|
|
47
|
+
command: "\\htmlData";
|
|
48
|
+
attributes: Record<string, string>;
|
|
49
|
+
};
|
|
51
50
|
};
|
|
52
|
-
export type AnyTrustContext =
|
|
53
|
-
export type TrustFunction = (context: AnyTrustContext) =>
|
|
51
|
+
export type AnyTrustContext = TrustContextTypes[keyof TrustContextTypes];
|
|
52
|
+
export type TrustFunction = (context: AnyTrustContext) => boolean | null | undefined;
|
|
53
|
+
export type SettingsOptions = Partial<Settings>;
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
type EnumType = {
|
|
56
|
+
enum: string[];
|
|
57
|
+
};
|
|
56
58
|
|
|
57
|
-
type EnumType = {| enum: string[] |};
|
|
58
59
|
type Type = "boolean" | "string" | "number" | "object" | "function" | EnumType;
|
|
59
60
|
type Schema = {
|
|
60
|
-
[
|
|
61
|
+
[key in keyof SettingsOptions]?: {
|
|
61
62
|
/**
|
|
62
63
|
* Allowed type(s) of the value.
|
|
63
64
|
*/
|
|
@@ -76,7 +77,7 @@ type Schema = {
|
|
|
76
77
|
/**
|
|
77
78
|
* The function to process the option.
|
|
78
79
|
*/
|
|
79
|
-
processor?: (any) => any
|
|
80
|
+
processor?: (arg0: any) => any;
|
|
80
81
|
/**
|
|
81
82
|
* The command line argument. See Commander.js docs for more information.
|
|
82
83
|
* If not specified, the name prefixed with -- will be used. Set false not
|
|
@@ -96,10 +97,12 @@ type Schema = {
|
|
|
96
97
|
* The custom argument processor for the CLI. See Commander.js docs for
|
|
97
98
|
* more information.
|
|
98
99
|
*/
|
|
99
|
-
cliProcessor?: (any, any) => any;
|
|
100
|
+
cliProcessor?: (arg0: any, arg1: any) => any;
|
|
100
101
|
};
|
|
101
102
|
};
|
|
102
103
|
|
|
104
|
+
type SchemaEntry = NonNullable<Schema[keyof SettingsOptions]>;
|
|
105
|
+
|
|
103
106
|
// TODO: automatically generate documentation
|
|
104
107
|
// TODO: check all properties on Settings exist
|
|
105
108
|
// TODO: check the type of a property on Settings matches
|
|
@@ -205,8 +208,8 @@ export const SETTINGS_SCHEMA: Schema = {
|
|
|
205
208
|
},
|
|
206
209
|
};
|
|
207
210
|
|
|
208
|
-
function getDefaultValue(schema): any {
|
|
209
|
-
if (schema
|
|
211
|
+
function getDefaultValue(schema: SchemaEntry): any {
|
|
212
|
+
if ("default" in schema) {
|
|
210
213
|
return schema.default;
|
|
211
214
|
}
|
|
212
215
|
const type = schema.type;
|
|
@@ -237,34 +240,31 @@ function getDefaultValue(schema): any {
|
|
|
237
240
|
* and is placed in a block with vertical margin.
|
|
238
241
|
*/
|
|
239
242
|
export default class Settings {
|
|
240
|
-
displayMode
|
|
241
|
-
output
|
|
242
|
-
leqno
|
|
243
|
-
fleqn
|
|
244
|
-
throwOnError
|
|
245
|
-
errorColor
|
|
246
|
-
macros
|
|
247
|
-
minRuleThickness
|
|
248
|
-
colorIsTextColor
|
|
249
|
-
strict
|
|
250
|
-
trust
|
|
251
|
-
maxSize
|
|
252
|
-
maxExpand
|
|
253
|
-
globalGroup
|
|
243
|
+
displayMode!: boolean;
|
|
244
|
+
output!: "html" | "mathml" | "htmlAndMathml";
|
|
245
|
+
leqno!: boolean;
|
|
246
|
+
fleqn!: boolean;
|
|
247
|
+
throwOnError!: boolean;
|
|
248
|
+
errorColor!: string;
|
|
249
|
+
macros!: MacroMap;
|
|
250
|
+
minRuleThickness!: number;
|
|
251
|
+
colorIsTextColor!: boolean;
|
|
252
|
+
strict!: boolean | "ignore" | "warn" | "error" | StrictFunction;
|
|
253
|
+
trust!: boolean | TrustFunction;
|
|
254
|
+
maxSize!: number;
|
|
255
|
+
maxExpand!: number;
|
|
256
|
+
globalGroup!: boolean;
|
|
254
257
|
|
|
255
|
-
constructor(options: SettingsOptions) {
|
|
258
|
+
constructor(options: SettingsOptions = {}) {
|
|
256
259
|
// allow null options
|
|
257
260
|
options = options || {};
|
|
258
|
-
for (const prop
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
? schema.processor(options[prop]) : options[prop])
|
|
266
|
-
: getDefaultValue(schema);
|
|
267
|
-
}
|
|
261
|
+
for (const prop of Object.keys(SETTINGS_SCHEMA) as Array<keyof SettingsOptions>) {
|
|
262
|
+
const schema = SETTINGS_SCHEMA[prop] as SchemaEntry;
|
|
263
|
+
const optionValue = options[prop];
|
|
264
|
+
// TODO: validate options
|
|
265
|
+
(this as Record<string, unknown>)[prop] = optionValue !== undefined ?
|
|
266
|
+
(schema.processor ? schema.processor(optionValue) : optionValue)
|
|
267
|
+
: getDefaultValue(schema);
|
|
268
268
|
}
|
|
269
269
|
}
|
|
270
270
|
|
|
@@ -274,7 +274,7 @@ export default class Settings {
|
|
|
274
274
|
*/
|
|
275
275
|
reportNonstrict(errorCode: string, errorMsg: string,
|
|
276
276
|
token?: Token | AnyParseNode) {
|
|
277
|
-
let strict = this.strict;
|
|
277
|
+
let strict: Settings["strict"] | ReturnType<StrictFunction> = this.strict;
|
|
278
278
|
if (typeof strict === "function") {
|
|
279
279
|
// Allow return value of strict function to be boolean or string
|
|
280
280
|
// (or null/undefined, meaning no further processing).
|
|
@@ -307,7 +307,7 @@ export default class Settings {
|
|
|
307
307
|
*/
|
|
308
308
|
useStrictBehavior(errorCode: string, errorMsg: string,
|
|
309
309
|
token?: Token | AnyParseNode): boolean {
|
|
310
|
-
let strict = this.strict;
|
|
310
|
+
let strict: Settings["strict"] | ReturnType<StrictFunction> = this.strict;
|
|
311
311
|
if (typeof strict === "function") {
|
|
312
312
|
// Allow return value of strict function to be boolean or string
|
|
313
313
|
// (or null/undefined, meaning no further processing).
|
|
@@ -345,7 +345,7 @@ export default class Settings {
|
|
|
345
345
|
* get added by this function (changing the specified object).
|
|
346
346
|
*/
|
|
347
347
|
isTrusted(context: AnyTrustContext): boolean {
|
|
348
|
-
if (context.url && !context.protocol) {
|
|
348
|
+
if ("url" in context && context.url && !context.protocol) {
|
|
349
349
|
const protocol = protocolFromUrl(context.url);
|
|
350
350
|
if (protocol == null) {
|
|
351
351
|
return false;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import type {LexerInterface} from "./Token";
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -7,9 +6,9 @@ import type {LexerInterface} from "./Token";
|
|
|
7
6
|
*/
|
|
8
7
|
export default class SourceLocation {
|
|
9
8
|
// The + prefix indicates that these fields aren't writeable
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
readonly lexer: LexerInterface; // Lexer holding the input string.
|
|
10
|
+
readonly start: number; // Start offset, zero-based inclusive.
|
|
11
|
+
readonly end: number; // End offset, zero-based exclusive.
|
|
13
12
|
|
|
14
13
|
constructor(lexer: LexerInterface, start: number, end: number) {
|
|
15
14
|
this.lexer = lexer;
|
|
@@ -26,9 +25,9 @@ export default class SourceLocation {
|
|
|
26
25
|
* - Otherwise, returns null.
|
|
27
26
|
*/
|
|
28
27
|
static range(
|
|
29
|
-
first?: {loc
|
|
30
|
-
second?: {loc
|
|
31
|
-
):
|
|
28
|
+
first?: {loc?: SourceLocation | null | undefined},
|
|
29
|
+
second?: {loc?: SourceLocation | null | undefined},
|
|
30
|
+
): SourceLocation | null | undefined {
|
|
32
31
|
if (!second) {
|
|
33
32
|
return first && first.loc;
|
|
34
33
|
} else if (!first || !first.loc || !second.loc ||
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
/**
|
|
3
2
|
* This file contains information and classes for the various kinds of styles
|
|
4
3
|
* used in TeX. It provides a generic `Style` class, which holds information
|
|
@@ -123,8 +122,8 @@ const text = [D, Dc, T, Tc, T, Tc, T, Tc];
|
|
|
123
122
|
|
|
124
123
|
// We only export some of the styles.
|
|
125
124
|
export default {
|
|
126
|
-
DISPLAY: (styles[D]
|
|
127
|
-
TEXT: (styles[T]
|
|
128
|
-
SCRIPT: (styles[S]
|
|
129
|
-
SCRIPTSCRIPT: (styles[SS]
|
|
125
|
+
DISPLAY: (styles[D] as Style),
|
|
126
|
+
TEXT: (styles[T] as Style),
|
|
127
|
+
SCRIPT: (styles[S] as Style),
|
|
128
|
+
SCRIPTSCRIPT: (styles[SS] as Style),
|
|
130
129
|
};
|