katex 0.12.0 → 0.13.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +112 -0
- package/LICENSE +1 -1
- package/README.md +8 -7
- package/contrib/auto-render/auto-render.js +12 -19
- package/contrib/auto-render/index.html +9 -3
- package/contrib/auto-render/splitAtDelimiters.js +44 -61
- package/contrib/auto-render/test/auto-render-spec.js +88 -52
- package/contrib/copy-tex/README.md +5 -9
- package/contrib/copy-tex/copy-tex.css +0 -3
- package/contrib/mathtex-script-type/README.md +5 -5
- package/contrib/mhchem/README.md +4 -2
- package/contrib/render-a11y-string/render-a11y-string.js +31 -2
- package/contrib/render-a11y-string/test/render-a11y-string-spec.js +23 -0
- package/dist/README.md +8 -7
- package/dist/contrib/auto-render.js +148 -171
- package/dist/contrib/auto-render.min.js +1 -1
- package/dist/contrib/auto-render.mjs +91 -95
- package/dist/contrib/copy-tex.css +3 -3
- package/dist/contrib/copy-tex.js +11 -108
- package/dist/contrib/copy-tex.min.css +1 -1
- package/dist/contrib/copy-tex.min.js +1 -1
- package/dist/contrib/copy-tex.mjs +21 -20
- package/dist/contrib/mathtex-script-type.js +66 -91
- package/dist/contrib/mathtex-script-type.min.js +1 -1
- package/dist/contrib/mathtex-script-type.mjs +3 -3
- package/dist/contrib/mhchem.js +70 -95
- package/dist/contrib/mhchem.min.js +1 -1
- package/dist/contrib/mhchem.mjs +2 -2
- package/dist/contrib/render-a11y-string.js +97 -92
- package/dist/contrib/render-a11y-string.min.js +1 -1
- package/dist/contrib/render-a11y-string.mjs +86 -45
- package/dist/fonts/KaTeX_AMS-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_AMS-Regular.woff +0 -0
- package/dist/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
- package/dist/fonts/KaTeX_Fraktur-Bold.woff +0 -0
- package/dist/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/dist/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Fraktur-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Main-Bold.ttf +0 -0
- package/dist/fonts/KaTeX_Main-Bold.woff +0 -0
- package/dist/fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/dist/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
- package/dist/fonts/KaTeX_Main-BoldItalic.woff +0 -0
- package/dist/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/dist/fonts/KaTeX_Main-Italic.ttf +0 -0
- package/dist/fonts/KaTeX_Main-Italic.woff +0 -0
- package/dist/fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/dist/fonts/KaTeX_Main-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Main-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
- package/dist/fonts/KaTeX_Math-BoldItalic.woff +0 -0
- package/dist/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/dist/fonts/KaTeX_Math-Italic.ttf +0 -0
- package/dist/fonts/KaTeX_Math-Italic.woff +0 -0
- package/dist/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/dist/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
- package/dist/fonts/KaTeX_SansSerif-Bold.woff +0 -0
- package/dist/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/dist/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
- package/dist/fonts/KaTeX_SansSerif-Italic.woff +0 -0
- package/dist/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/dist/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_SansSerif-Regular.woff +0 -0
- package/dist/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Script-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Script-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Size1-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Size1-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Size2-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Size2-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Size3-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Size3-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Size4-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Size4-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/dist/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
- package/dist/fonts/KaTeX_Typewriter-Regular.woff +0 -0
- package/dist/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/dist/katex.css +66 -10
- package/dist/katex.js +2714 -1950
- package/dist/katex.min.css +1 -1
- package/dist/katex.min.js +1 -1
- package/dist/katex.mjs +3162 -2372
- package/katex.js +4 -3
- package/package.json +69 -59
- package/src/Lexer.js +4 -2
- package/src/MacroExpander.js +117 -37
- package/src/Options.js +2 -2
- package/src/ParseError.js +1 -1
- package/src/Parser.js +100 -159
- package/src/Settings.js +2 -2
- package/src/Style.js +4 -4
- package/src/Token.js +1 -1
- package/src/buildCommon.js +12 -5
- package/src/buildHTML.js +11 -0
- package/src/buildMathML.js +6 -0
- package/src/defineEnvironment.js +0 -3
- package/src/defineFunction.js +15 -22
- package/src/delimiter.js +61 -57
- package/src/domTree.js +1 -1
- package/src/environments/array.js +223 -35
- package/src/environments/cd.js +312 -0
- package/src/fontMetrics.js +1 -1
- package/src/fontMetricsData.js +2076 -0
- package/src/fonts/.gitignore +9 -0
- package/src/fonts/Makefile +139 -0
- package/src/fonts/default.cfg +20 -0
- package/src/fonts/generate_fonts.py +61 -0
- package/src/fonts/lib/Extra.otf +0 -0
- package/src/fonts/lib/Space.ttx +234 -0
- package/src/fonts/makeBlacker +49 -0
- package/src/fonts/makeFF +2003 -0
- package/src/fonts/xbbold.mf +182 -0
- package/src/fonts.less +64 -0
- package/src/functions/accent.js +3 -2
- package/src/functions/arrow.js +8 -2
- package/src/functions/color.js +4 -4
- package/src/functions/cr.js +7 -25
- package/src/functions/def.js +50 -24
- package/src/functions/delimsizing.js +8 -0
- package/src/functions/enclose.js +80 -12
- package/src/functions/environment.js +1 -1
- package/src/functions/font.js +3 -4
- package/src/functions/genfrac.js +36 -11
- package/src/functions/hbox.js +39 -0
- package/src/functions/kern.js +1 -0
- package/src/functions/mathchoice.js +1 -0
- package/src/functions/mclass.js +2 -1
- package/src/functions/op.js +3 -7
- package/src/functions/operatorname.js +1 -1
- package/src/functions/raisebox.js +0 -1
- package/src/functions/styling.js +1 -0
- package/src/functions/supsub.js +1 -3
- package/src/functions/symbolsOrd.js +0 -2
- package/src/functions/text.js +2 -3
- package/src/functions/vcenter.js +44 -0
- package/src/functions.js +3 -0
- package/src/katex.less +69 -16
- package/src/macros.js +42 -6
- package/src/mathMLTree.js +16 -1
- package/src/metrics/.gitignore +1 -0
- package/src/metrics/README.md +23 -0
- package/src/metrics/extract_tfms.py +114 -0
- package/src/metrics/extract_ttfs.py +119 -0
- package/src/metrics/format_json.py +28 -0
- package/src/metrics/mapping.pl +1224 -0
- package/src/metrics/parse_tfm.py +211 -0
- package/src/parseNode.js +29 -1
- package/src/parseTree.js +6 -0
- package/src/stretchy.js +12 -5
- package/src/svgGeometry.js +33 -4
- package/src/symbols.js +5 -3
- package/src/types.js +3 -2
- package/src/unicodeScripts.js +5 -0
package/src/Parser.js
CHANGED
|
@@ -143,13 +143,7 @@ export default class Parser {
|
|
|
143
143
|
return parse;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
static endOfExpression = ["}", "\\endgroup", "\\end", "\\right", "&"];
|
|
147
|
-
|
|
148
|
-
static endOfGroup = {
|
|
149
|
-
"[": "]",
|
|
150
|
-
"{": "}",
|
|
151
|
-
"\\begingroup": "\\endgroup",
|
|
152
|
-
}
|
|
146
|
+
static endOfExpression: string[] = ["}", "\\endgroup", "\\end", "\\right", "&"];
|
|
153
147
|
|
|
154
148
|
/**
|
|
155
149
|
* Parses an "expression", which is a list of atoms.
|
|
@@ -253,9 +247,6 @@ export default class Parser {
|
|
|
253
247
|
}
|
|
254
248
|
}
|
|
255
249
|
|
|
256
|
-
// The greediness of a superscript or subscript
|
|
257
|
-
static SUPSUB_GREEDINESS = 1;
|
|
258
|
-
|
|
259
250
|
/**
|
|
260
251
|
* Handle a subscript or superscript with nice errors.
|
|
261
252
|
*/
|
|
@@ -265,9 +256,8 @@ export default class Parser {
|
|
|
265
256
|
const symbolToken = this.fetch();
|
|
266
257
|
const symbol = symbolToken.text;
|
|
267
258
|
this.consume();
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
// ignore spaces before sup/subscript argument
|
|
259
|
+
this.consumeSpaces(); // ignore spaces before sup/subscript argument
|
|
260
|
+
const group = this.parseGroup(name);
|
|
271
261
|
|
|
272
262
|
if (!group) {
|
|
273
263
|
throw new ParseError(
|
|
@@ -312,7 +302,7 @@ export default class Parser {
|
|
|
312
302
|
parseAtom(breakOnTokenText?: BreakToken): ?AnyParseNode {
|
|
313
303
|
// The body of an atom is an implicit group, so that things like
|
|
314
304
|
// \left(x\right)^2 work correctly.
|
|
315
|
-
const base = this.parseGroup("atom",
|
|
305
|
+
const base = this.parseGroup("atom", breakOnTokenText);
|
|
316
306
|
|
|
317
307
|
// In text mode, we don't have superscripts or subscripts
|
|
318
308
|
if (this.mode === "text") {
|
|
@@ -409,8 +399,7 @@ export default class Parser {
|
|
|
409
399
|
*/
|
|
410
400
|
parseFunction(
|
|
411
401
|
breakOnTokenText?: BreakToken,
|
|
412
|
-
name?: string, // For
|
|
413
|
-
greediness?: ?number,
|
|
402
|
+
name?: string, // For determining its context
|
|
414
403
|
): ?AnyParseNode {
|
|
415
404
|
const token = this.fetch();
|
|
416
405
|
const func = token.text;
|
|
@@ -420,7 +409,7 @@ export default class Parser {
|
|
|
420
409
|
}
|
|
421
410
|
this.consume(); // consume command token
|
|
422
411
|
|
|
423
|
-
if (
|
|
412
|
+
if (name && name !== "atom" && !funcData.allowedInArgument) {
|
|
424
413
|
throw new ParseError(
|
|
425
414
|
"Got function '" + func + "' with no arguments" +
|
|
426
415
|
(name ? " as " + name : ""), token);
|
|
@@ -475,36 +464,28 @@ export default class Parser {
|
|
|
475
464
|
return {args: [], optArgs: []};
|
|
476
465
|
}
|
|
477
466
|
|
|
478
|
-
const baseGreediness = funcData.greediness;
|
|
479
467
|
const args = [];
|
|
480
468
|
const optArgs = [];
|
|
481
469
|
|
|
482
470
|
for (let i = 0; i < totalArgs; i++) {
|
|
483
|
-
|
|
471
|
+
let argType = funcData.argTypes && funcData.argTypes[i];
|
|
484
472
|
const isOptional = i < funcData.numOptionalArgs;
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
// macros, e.g. \frac\foo\foo where \foo expands to a space symbol.
|
|
493
|
-
// In LaTeX, the \foo's get treated as (blank) arguments.
|
|
494
|
-
// In KaTeX, for now, both spaces will get consumed.
|
|
495
|
-
// TODO(edemaine)
|
|
496
|
-
(i === 0 && !isOptional && this.mode === "math");
|
|
473
|
+
|
|
474
|
+
if ((funcData.primitive && argType == null) ||
|
|
475
|
+
// \sqrt expands into primitive if optional argument doesn't exist
|
|
476
|
+
(funcData.type === "sqrt" && i === 1 && optArgs[0] == null)) {
|
|
477
|
+
argType = "primitive";
|
|
478
|
+
}
|
|
479
|
+
|
|
497
480
|
const arg = this.parseGroupOfType(`argument to '${func}'`,
|
|
498
|
-
argType, isOptional
|
|
499
|
-
if (
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
throw new ParseError(
|
|
505
|
-
`Expected group after '${func}'`, this.fetch());
|
|
481
|
+
argType, isOptional);
|
|
482
|
+
if (isOptional) {
|
|
483
|
+
optArgs.push(arg);
|
|
484
|
+
} else if (arg != null) {
|
|
485
|
+
args.push(arg);
|
|
486
|
+
} else { // should be unreachable
|
|
487
|
+
throw new ParseError("Null argument, please report this as a bug");
|
|
506
488
|
}
|
|
507
|
-
(isOptional ? optArgs : args).push(arg);
|
|
508
489
|
}
|
|
509
490
|
|
|
510
491
|
return {args, optArgs};
|
|
@@ -517,65 +498,50 @@ export default class Parser {
|
|
|
517
498
|
name: string,
|
|
518
499
|
type: ?ArgType,
|
|
519
500
|
optional: boolean,
|
|
520
|
-
greediness: ?number,
|
|
521
|
-
consumeSpaces: boolean,
|
|
522
501
|
): ?AnyParseNode {
|
|
523
502
|
switch (type) {
|
|
524
503
|
case "color":
|
|
525
|
-
if (consumeSpaces) {
|
|
526
|
-
this.consumeSpaces();
|
|
527
|
-
}
|
|
528
504
|
return this.parseColorGroup(optional);
|
|
529
505
|
case "size":
|
|
530
|
-
if (consumeSpaces) {
|
|
531
|
-
this.consumeSpaces();
|
|
532
|
-
}
|
|
533
506
|
return this.parseSizeGroup(optional);
|
|
534
507
|
case "url":
|
|
535
|
-
return this.parseUrlGroup(optional
|
|
508
|
+
return this.parseUrlGroup(optional);
|
|
536
509
|
case "math":
|
|
537
510
|
case "text":
|
|
538
|
-
return this.
|
|
539
|
-
name, optional, greediness, undefined, type, consumeSpaces);
|
|
511
|
+
return this.parseArgumentGroup(optional, type);
|
|
540
512
|
case "hbox": {
|
|
541
513
|
// hbox argument type wraps the argument in the equivalent of
|
|
542
514
|
// \hbox, which is like \text but switching to \textstyle size.
|
|
543
|
-
const group = this.
|
|
544
|
-
|
|
545
|
-
if (!group) {
|
|
546
|
-
return group;
|
|
547
|
-
}
|
|
548
|
-
const styledGroup = {
|
|
515
|
+
const group = this.parseArgumentGroup(optional, "text");
|
|
516
|
+
return group != null ? {
|
|
549
517
|
type: "styling",
|
|
550
518
|
mode: group.mode,
|
|
551
519
|
body: [group],
|
|
552
520
|
style: "text", // simulate \textstyle
|
|
553
|
-
};
|
|
554
|
-
return styledGroup;
|
|
521
|
+
} : null;
|
|
555
522
|
}
|
|
556
523
|
case "raw": {
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
524
|
+
const token = this.parseStringGroup("raw", optional);
|
|
525
|
+
return token != null ? {
|
|
526
|
+
type: "raw",
|
|
527
|
+
mode: "text",
|
|
528
|
+
string: token.text,
|
|
529
|
+
} : null;
|
|
530
|
+
}
|
|
531
|
+
case "primitive": {
|
|
532
|
+
if (optional) {
|
|
533
|
+
throw new ParseError("A primitive argument cannot be optional");
|
|
562
534
|
}
|
|
563
|
-
const
|
|
564
|
-
if (
|
|
565
|
-
|
|
566
|
-
type: "raw",
|
|
567
|
-
mode: "text",
|
|
568
|
-
string: token.text,
|
|
569
|
-
};
|
|
570
|
-
} else {
|
|
571
|
-
throw new ParseError("Expected raw group", this.fetch());
|
|
535
|
+
const group = this.parseGroup(name);
|
|
536
|
+
if (group == null) {
|
|
537
|
+
throw new ParseError("Expected group as " + name, this.fetch());
|
|
572
538
|
}
|
|
539
|
+
return group;
|
|
573
540
|
}
|
|
574
541
|
case "original":
|
|
575
542
|
case null:
|
|
576
543
|
case undefined:
|
|
577
|
-
return this.
|
|
578
|
-
undefined, undefined, consumeSpaces);
|
|
544
|
+
return this.parseArgumentGroup(optional);
|
|
579
545
|
default:
|
|
580
546
|
throw new ParseError(
|
|
581
547
|
"Unknown group type as " + name, this.fetch());
|
|
@@ -598,49 +564,20 @@ export default class Parser {
|
|
|
598
564
|
parseStringGroup(
|
|
599
565
|
modeName: ArgType, // Used to describe the mode in error messages.
|
|
600
566
|
optional: boolean,
|
|
601
|
-
raw?: boolean,
|
|
602
567
|
): ?Token {
|
|
603
|
-
const
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
if (beginToken.text !== groupBegin) {
|
|
607
|
-
if (optional) {
|
|
608
|
-
return null;
|
|
609
|
-
} else if (raw && beginToken.text !== "EOF" &&
|
|
610
|
-
/[^{}[\]]/.test(beginToken.text)) {
|
|
611
|
-
this.consume();
|
|
612
|
-
return beginToken;
|
|
613
|
-
}
|
|
568
|
+
const argToken = this.gullet.scanArgument(optional);
|
|
569
|
+
if (argToken == null) {
|
|
570
|
+
return null;
|
|
614
571
|
}
|
|
615
|
-
const outerMode = this.mode;
|
|
616
|
-
this.mode = "text";
|
|
617
|
-
this.expect(groupBegin);
|
|
618
572
|
let str = "";
|
|
619
|
-
const firstToken = this.fetch();
|
|
620
|
-
let nested = 0; // allow nested braces in raw string group
|
|
621
|
-
let lastToken = firstToken;
|
|
622
573
|
let nextToken;
|
|
623
|
-
while ((nextToken = this.fetch()).text !==
|
|
624
|
-
|
|
625
|
-
switch (nextToken.text) {
|
|
626
|
-
case "EOF":
|
|
627
|
-
throw new ParseError(
|
|
628
|
-
"Unexpected end of input in " + modeName,
|
|
629
|
-
firstToken.range(lastToken, str));
|
|
630
|
-
case groupBegin:
|
|
631
|
-
nested++;
|
|
632
|
-
break;
|
|
633
|
-
case groupEnd:
|
|
634
|
-
nested--;
|
|
635
|
-
break;
|
|
636
|
-
}
|
|
637
|
-
lastToken = nextToken;
|
|
638
|
-
str += lastToken.text;
|
|
574
|
+
while ((nextToken = this.fetch()).text !== "EOF") {
|
|
575
|
+
str += nextToken.text;
|
|
639
576
|
this.consume();
|
|
640
577
|
}
|
|
641
|
-
this.
|
|
642
|
-
|
|
643
|
-
return
|
|
578
|
+
this.consume(); // consume the end of the argument
|
|
579
|
+
argToken.text = str;
|
|
580
|
+
return argToken;
|
|
644
581
|
}
|
|
645
582
|
|
|
646
583
|
/**
|
|
@@ -652,8 +589,6 @@ export default class Parser {
|
|
|
652
589
|
regex: RegExp,
|
|
653
590
|
modeName: string, // Used to describe the mode in error messages.
|
|
654
591
|
): Token {
|
|
655
|
-
const outerMode = this.mode;
|
|
656
|
-
this.mode = "text";
|
|
657
592
|
const firstToken = this.fetch();
|
|
658
593
|
let lastToken = firstToken;
|
|
659
594
|
let str = "";
|
|
@@ -669,7 +604,6 @@ export default class Parser {
|
|
|
669
604
|
"Invalid " + modeName + ": '" + firstToken.text + "'",
|
|
670
605
|
firstToken);
|
|
671
606
|
}
|
|
672
|
-
this.mode = outerMode;
|
|
673
607
|
return firstToken.range(lastToken, str);
|
|
674
608
|
}
|
|
675
609
|
|
|
@@ -678,7 +612,7 @@ export default class Parser {
|
|
|
678
612
|
*/
|
|
679
613
|
parseColorGroup(optional: boolean): ?ParseNode<"color-token"> {
|
|
680
614
|
const res = this.parseStringGroup("color", optional);
|
|
681
|
-
if (
|
|
615
|
+
if (res == null) {
|
|
682
616
|
return null;
|
|
683
617
|
}
|
|
684
618
|
const match = (/^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i).exec(res.text);
|
|
@@ -705,7 +639,9 @@ export default class Parser {
|
|
|
705
639
|
parseSizeGroup(optional: boolean): ?ParseNode<"size"> {
|
|
706
640
|
let res;
|
|
707
641
|
let isBlank = false;
|
|
708
|
-
|
|
642
|
+
// don't expand before parseStringGroup
|
|
643
|
+
this.gullet.consumeSpaces();
|
|
644
|
+
if (!optional && this.gullet.future().text !== "{") {
|
|
709
645
|
res = this.parseRegexGroup(
|
|
710
646
|
/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size");
|
|
711
647
|
} else {
|
|
@@ -744,11 +680,13 @@ export default class Parser {
|
|
|
744
680
|
* Parses an URL, checking escaped letters and allowed protocols,
|
|
745
681
|
* and setting the catcode of % as an active character (as in \hyperref).
|
|
746
682
|
*/
|
|
747
|
-
parseUrlGroup(optional: boolean
|
|
683
|
+
parseUrlGroup(optional: boolean): ?ParseNode<"url"> {
|
|
748
684
|
this.gullet.lexer.setCatcode("%", 13); // active character
|
|
749
|
-
|
|
685
|
+
this.gullet.lexer.setCatcode("~", 12); // other character
|
|
686
|
+
const res = this.parseStringGroup("url", optional);
|
|
750
687
|
this.gullet.lexer.setCatcode("%", 14); // comment character
|
|
751
|
-
|
|
688
|
+
this.gullet.lexer.setCatcode("~", 13); // active character
|
|
689
|
+
if (res == null) {
|
|
752
690
|
return null;
|
|
753
691
|
}
|
|
754
692
|
// hyperref package allows backslashes alone in href, but doesn't
|
|
@@ -764,52 +702,60 @@ export default class Parser {
|
|
|
764
702
|
}
|
|
765
703
|
|
|
766
704
|
/**
|
|
767
|
-
*
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
705
|
+
* Parses an argument with the mode specified.
|
|
706
|
+
*/
|
|
707
|
+
parseArgumentGroup(optional: boolean, mode?: Mode): ?ParseNode<"ordgroup"> {
|
|
708
|
+
const argToken = this.gullet.scanArgument(optional);
|
|
709
|
+
if (argToken == null) {
|
|
710
|
+
return null;
|
|
711
|
+
}
|
|
712
|
+
const outerMode = this.mode;
|
|
713
|
+
if (mode) { // Switch to specified mode
|
|
714
|
+
this.switchMode(mode);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
this.gullet.beginGroup();
|
|
718
|
+
const expression = this.parseExpression(false, "EOF");
|
|
719
|
+
// TODO: find an alternative way to denote the end
|
|
720
|
+
this.expect("EOF"); // expect the end of the argument
|
|
721
|
+
this.gullet.endGroup();
|
|
722
|
+
const result = {
|
|
723
|
+
type: "ordgroup",
|
|
724
|
+
mode: this.mode,
|
|
725
|
+
loc: argToken.loc,
|
|
726
|
+
body: expression,
|
|
727
|
+
};
|
|
728
|
+
|
|
729
|
+
if (mode) { // Switch mode back
|
|
730
|
+
this.switchMode(outerMode);
|
|
731
|
+
}
|
|
732
|
+
return result;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* Parses an ordinary group, which is either a single nucleus (like "x")
|
|
737
|
+
* or an expression in braces (like "{x+y}") or an implicit group, a group
|
|
738
|
+
* that starts at the current position, and ends right before a higher explicit
|
|
771
739
|
* group ends, or at EOF.
|
|
772
|
-
* If `optional` is true, it parses either a bracket-delimited expression
|
|
773
|
-
* (like "[x+y]") or returns null to indicate the absence of a
|
|
774
|
-
* bracket-enclosed group.
|
|
775
|
-
* If `mode` is present, switches to that mode while parsing the group,
|
|
776
|
-
* and switches back after.
|
|
777
740
|
*/
|
|
778
741
|
parseGroup(
|
|
779
742
|
name: string, // For error reporting.
|
|
780
|
-
optional?: boolean,
|
|
781
|
-
greediness?: ?number,
|
|
782
743
|
breakOnTokenText?: BreakToken,
|
|
783
|
-
mode?: Mode,
|
|
784
|
-
consumeSpaces?: boolean,
|
|
785
744
|
): ?AnyParseNode {
|
|
786
|
-
// Switch to specified mode
|
|
787
|
-
const outerMode = this.mode;
|
|
788
|
-
if (mode) {
|
|
789
|
-
this.switchMode(mode);
|
|
790
|
-
}
|
|
791
|
-
// Consume spaces if requested, crucially *after* we switch modes,
|
|
792
|
-
// so that the next non-space token is parsed in the correct mode.
|
|
793
|
-
if (consumeSpaces) {
|
|
794
|
-
this.consumeSpaces();
|
|
795
|
-
}
|
|
796
|
-
// Get first token
|
|
797
745
|
const firstToken = this.fetch();
|
|
798
746
|
const text = firstToken.text;
|
|
799
747
|
|
|
800
748
|
let result;
|
|
801
749
|
// Try to parse an open brace or \begingroup
|
|
802
|
-
if (
|
|
750
|
+
if (text === "{" || text === "\\begingroup") {
|
|
803
751
|
this.consume();
|
|
804
|
-
const groupEnd =
|
|
805
|
-
|
|
752
|
+
const groupEnd = text === "{" ? "}" : "\\endgroup";
|
|
753
|
+
|
|
806
754
|
this.gullet.beginGroup();
|
|
807
755
|
// If we get a brace, parse an expression
|
|
808
756
|
const expression = this.parseExpression(false, groupEnd);
|
|
809
757
|
const lastToken = this.fetch();
|
|
810
|
-
// Check that we got a matching closing brace
|
|
811
|
-
this.expect(groupEnd);
|
|
812
|
-
// End group namespace
|
|
758
|
+
this.expect(groupEnd); // Check that we got a matching closing brace
|
|
813
759
|
this.gullet.endGroup();
|
|
814
760
|
result = {
|
|
815
761
|
type: "ordgroup",
|
|
@@ -822,13 +768,10 @@ export default class Parser {
|
|
|
822
768
|
// use-begingroup-instead-of-bgroup
|
|
823
769
|
semisimple: text === "\\begingroup" || undefined,
|
|
824
770
|
};
|
|
825
|
-
} else if (optional) {
|
|
826
|
-
// Return nothing for an optional group
|
|
827
|
-
result = null;
|
|
828
771
|
} else {
|
|
829
772
|
// If there exists a function with this name, parse the function.
|
|
830
773
|
// Otherwise, just return a nucleus
|
|
831
|
-
result = this.parseFunction(breakOnTokenText, name
|
|
774
|
+
result = this.parseFunction(breakOnTokenText, name) ||
|
|
832
775
|
this.parseSymbol();
|
|
833
776
|
if (result == null && text[0] === "\\" &&
|
|
834
777
|
!implicitCommands.hasOwnProperty(text)) {
|
|
@@ -840,11 +783,6 @@ export default class Parser {
|
|
|
840
783
|
this.consume();
|
|
841
784
|
}
|
|
842
785
|
}
|
|
843
|
-
|
|
844
|
-
// Switch mode back
|
|
845
|
-
if (mode) {
|
|
846
|
-
this.switchMode(outerMode);
|
|
847
|
-
}
|
|
848
786
|
return result;
|
|
849
787
|
}
|
|
850
788
|
|
|
@@ -975,6 +913,7 @@ export default class Parser {
|
|
|
975
913
|
text,
|
|
976
914
|
};
|
|
977
915
|
}
|
|
916
|
+
// $FlowFixMe
|
|
978
917
|
symbol = s;
|
|
979
918
|
} else if (text.charCodeAt(0) >= 0x80) { // no symbol for e.g. ^
|
|
980
919
|
if (this.settings.strict) {
|
|
@@ -1025,10 +964,12 @@ export default class Parser {
|
|
|
1025
964
|
label: command,
|
|
1026
965
|
isStretchy: false,
|
|
1027
966
|
isShifty: true,
|
|
967
|
+
// $FlowFixMe
|
|
1028
968
|
base: symbol,
|
|
1029
969
|
};
|
|
1030
970
|
}
|
|
1031
971
|
}
|
|
972
|
+
// $FlowFixMe
|
|
1032
973
|
return symbol;
|
|
1033
974
|
}
|
|
1034
975
|
}
|
package/src/Settings.js
CHANGED
|
@@ -155,7 +155,7 @@ export default class Settings {
|
|
|
155
155
|
* This is for the second category of `errorCode`s listed in the README.
|
|
156
156
|
*/
|
|
157
157
|
useStrictBehavior(errorCode: string, errorMsg: string,
|
|
158
|
-
token?: Token | AnyParseNode) {
|
|
158
|
+
token?: Token | AnyParseNode): boolean {
|
|
159
159
|
let strict = this.strict;
|
|
160
160
|
if (typeof strict === "function") {
|
|
161
161
|
// Allow return value of strict function to be boolean or string
|
|
@@ -193,7 +193,7 @@ export default class Settings {
|
|
|
193
193
|
* If `context` has a `url` field, a `protocol` field will automatically
|
|
194
194
|
* get added by this function (changing the specified object).
|
|
195
195
|
*/
|
|
196
|
-
isTrusted(context: AnyTrustContext) {
|
|
196
|
+
isTrusted(context: AnyTrustContext): boolean {
|
|
197
197
|
if (context.url && !context.protocol) {
|
|
198
198
|
context.protocol = utils.protocolFromUrl(context.url);
|
|
199
199
|
}
|
package/src/Style.js
CHANGED
|
@@ -123,8 +123,8 @@ const text = [D, Dc, T, Tc, T, Tc, T, Tc];
|
|
|
123
123
|
|
|
124
124
|
// We only export some of the styles.
|
|
125
125
|
export default {
|
|
126
|
-
DISPLAY: styles[D],
|
|
127
|
-
TEXT: styles[T],
|
|
128
|
-
SCRIPT: styles[S],
|
|
129
|
-
SCRIPTSCRIPT: styles[SS],
|
|
126
|
+
DISPLAY: (styles[D]: Style),
|
|
127
|
+
TEXT: (styles[T]: Style),
|
|
128
|
+
SCRIPT: (styles[S]: Style),
|
|
129
|
+
SCRIPTSCRIPT: (styles[SS]: Style),
|
|
130
130
|
};
|
package/src/Token.js
CHANGED
package/src/buildCommon.js
CHANGED
|
@@ -243,6 +243,15 @@ const canCombine = (prev: SymbolNode, next: SymbolNode) => {
|
|
|
243
243
|
return false;
|
|
244
244
|
}
|
|
245
245
|
|
|
246
|
+
// If prev and next both are just "mbin"s or "mord"s we don't combine them
|
|
247
|
+
// so that the proper spacing can be preserved.
|
|
248
|
+
if (prev.classes.length === 1) {
|
|
249
|
+
const cls = prev.classes[0];
|
|
250
|
+
if (cls === "mbin" || cls === "mord") {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
246
255
|
for (const style in prev.style) {
|
|
247
256
|
if (prev.style.hasOwnProperty(style)
|
|
248
257
|
&& prev.style[style] !== next.style[style]) {
|
|
@@ -261,7 +270,7 @@ const canCombine = (prev: SymbolNode, next: SymbolNode) => {
|
|
|
261
270
|
};
|
|
262
271
|
|
|
263
272
|
/**
|
|
264
|
-
* Combine
|
|
273
|
+
* Combine consecutive domTree.symbolNodes into a single symbolNode.
|
|
265
274
|
* Note: this function mutates the argument.
|
|
266
275
|
*/
|
|
267
276
|
const tryCombineChars = (chars: HtmlDomNode[]): HtmlDomNode[] => {
|
|
@@ -349,7 +358,7 @@ const makeLineSpan = function(
|
|
|
349
358
|
className: string,
|
|
350
359
|
options: Options,
|
|
351
360
|
thickness?: number,
|
|
352
|
-
) {
|
|
361
|
+
): DomSpan {
|
|
353
362
|
const line = makeSpan([className], [], options);
|
|
354
363
|
line.height = Math.max(
|
|
355
364
|
thickness || options.fontMetrics().defaultRuleThickness,
|
|
@@ -369,7 +378,7 @@ const makeAnchor = function(
|
|
|
369
378
|
classes: string[],
|
|
370
379
|
children: HtmlDomNode[],
|
|
371
380
|
options: Options,
|
|
372
|
-
) {
|
|
381
|
+
): Anchor {
|
|
373
382
|
const anchor = new Anchor(href, classes, children, options);
|
|
374
383
|
|
|
375
384
|
sizeElementFromChildren(anchor);
|
|
@@ -728,8 +737,6 @@ const svgData: {
|
|
|
728
737
|
oiintSize2: ["oiintSize2", 1.472, 0.659],
|
|
729
738
|
oiiintSize1: ["oiiintSize1", 1.304, 0.499],
|
|
730
739
|
oiiintSize2: ["oiiintSize2", 1.98, 0.659],
|
|
731
|
-
leftParenInner: ["leftParenInner", 0.875, 0.3],
|
|
732
|
-
rightParenInner: ["rightParenInner", 0.875, 0.3],
|
|
733
740
|
};
|
|
734
741
|
|
|
735
742
|
const staticSvg = function(value: string, options: Options): SvgSpan {
|
package/src/buildHTML.js
CHANGED
|
@@ -74,6 +74,9 @@ export const buildExpression = function(
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
// Combine consecutive domTree.symbolNodes into a single symbolNode.
|
|
78
|
+
buildCommon.tryCombineChars(groups);
|
|
79
|
+
|
|
77
80
|
// If `expression` is a partial group, let the parent handle spacings
|
|
78
81
|
// to avoid processing groups multiple times.
|
|
79
82
|
if (!isRealGroup) {
|
|
@@ -318,6 +321,12 @@ export default function buildHTML(tree: AnyParseNode[], options: Options): DomSp
|
|
|
318
321
|
// Build the expression contained in the tree
|
|
319
322
|
const expression = buildExpression(tree, options, "root");
|
|
320
323
|
|
|
324
|
+
let eqnNum;
|
|
325
|
+
if (expression.length === 2 && expression[1].hasClass("tag")) {
|
|
326
|
+
// An environment with automatic equation numbers, e.g. {gather}.
|
|
327
|
+
eqnNum = expression.pop();
|
|
328
|
+
}
|
|
329
|
+
|
|
321
330
|
const children = [];
|
|
322
331
|
|
|
323
332
|
// Create one base node for each chunk between potential line breaks.
|
|
@@ -373,6 +382,8 @@ export default function buildHTML(tree: AnyParseNode[], options: Options): DomSp
|
|
|
373
382
|
);
|
|
374
383
|
tagChild.classes = ["tag"];
|
|
375
384
|
children.push(tagChild);
|
|
385
|
+
} else if (eqnNum) {
|
|
386
|
+
children.push(eqnNum);
|
|
376
387
|
}
|
|
377
388
|
|
|
378
389
|
const htmlNode = makeSpan(["katex-html"], children);
|
package/src/buildMathML.js
CHANGED
|
@@ -219,6 +219,7 @@ export const buildGroup = function(
|
|
|
219
219
|
// Call the groupBuilders function
|
|
220
220
|
// $FlowFixMe
|
|
221
221
|
const result: MathDomNode = groupBuilders[group.type](group, options);
|
|
222
|
+
// $FlowFixMe
|
|
222
223
|
return result;
|
|
223
224
|
} else {
|
|
224
225
|
throw new ParseError(
|
|
@@ -243,6 +244,11 @@ export default function buildMathML(
|
|
|
243
244
|
): DomSpan {
|
|
244
245
|
const expression = buildExpression(tree, options);
|
|
245
246
|
|
|
247
|
+
// TODO: Make a pass thru the MathML similar to buildHTML.traverseNonSpaceNodes
|
|
248
|
+
// and add spacing nodes. This is necessary only adjacent to math operators
|
|
249
|
+
// like \sin or \lim or to subsup elements that contain math operators.
|
|
250
|
+
// MathML takes care of the other spacing issues.
|
|
251
|
+
|
|
246
252
|
// Wrap up the expression in an mrow so it is presented in the semantics
|
|
247
253
|
// tag correctly, unless it's a single <mrow> or <mtable>.
|
|
248
254
|
let wrapper;
|
package/src/defineEnvironment.js
CHANGED
|
@@ -52,7 +52,6 @@ export type EnvSpec<NODETYPE: NodeType> = {|
|
|
|
52
52
|
type: NODETYPE, // Need to use the type to avoid error. See NOTES below.
|
|
53
53
|
numArgs: number,
|
|
54
54
|
argTypes?: ArgType[],
|
|
55
|
-
greediness: number,
|
|
56
55
|
allowedInText: boolean,
|
|
57
56
|
numOptionalArgs: number,
|
|
58
57
|
handler: EnvHandler,
|
|
@@ -99,7 +98,6 @@ export default function defineEnvironment<NODETYPE: NodeType>({
|
|
|
99
98
|
const data = {
|
|
100
99
|
type,
|
|
101
100
|
numArgs: props.numArgs || 0,
|
|
102
|
-
greediness: 1,
|
|
103
101
|
allowedInText: false,
|
|
104
102
|
numOptionalArgs: 0,
|
|
105
103
|
handler,
|
|
@@ -108,7 +106,6 @@ export default function defineEnvironment<NODETYPE: NodeType>({
|
|
|
108
106
|
// TODO: The value type of _environments should be a type union of all
|
|
109
107
|
// possible `EnvSpec<>` possibilities instead of `EnvSpec<*>`, which is
|
|
110
108
|
// an existential type.
|
|
111
|
-
// $FlowFixMe
|
|
112
109
|
_environments[names[i]] = data;
|
|
113
110
|
}
|
|
114
111
|
if (htmlBuilder) {
|