tex2typst 0.2.8 → 0.2.11
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/LICENSE +674 -21
- package/README.md +4 -3
- package/dist/index.js +106 -77
- package/dist/parser.d.ts +7 -1
- package/dist/tex2typst.min.js +1 -1
- package/dist/types.d.ts +0 -4
- package/package.json +2 -2
- package/src/parser.ts +69 -60
- package/src/types.ts +0 -4
- package/src/writer.ts +46 -21
- package/tool/dist/dist/ka.js +0 -13654
- package/tool/dist/ka.js +0 -13634
package/README.md
CHANGED
|
@@ -59,11 +59,12 @@ console.log(output);
|
|
|
59
59
|
|
|
60
60
|
```mermaid
|
|
61
61
|
graph LR
|
|
62
|
-
tex[TeX code] --parser-->
|
|
62
|
+
tex[TeX code] --parser--> tex_ast[TeX AST] --converter--> typst_ast[Typst AST] --writer--> typst[Typst code]
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
- parser: Implemented in class `LatexParser
|
|
66
|
-
-
|
|
65
|
+
- parser: Implemented in class `LatexParser`.
|
|
66
|
+
- converter: Implemented in function `convertTree`.
|
|
67
|
+
- writer: Implemented in class `TypstWriter`.
|
|
67
68
|
|
|
68
69
|
## Contributing
|
|
69
70
|
|
package/dist/index.js
CHANGED
|
@@ -314,16 +314,16 @@ function get_command_param_num(command) {
|
|
|
314
314
|
}
|
|
315
315
|
}
|
|
316
316
|
function find_closing_curly_bracket(tokens, start) {
|
|
317
|
-
assert(
|
|
317
|
+
assert(tokens[start].eq(LEFT_CURLY_BRACKET));
|
|
318
318
|
let count = 1;
|
|
319
319
|
let pos = start + 1;
|
|
320
320
|
while (count > 0) {
|
|
321
321
|
if (pos >= tokens.length) {
|
|
322
322
|
throw new LatexParserError("Unmatched curly brackets");
|
|
323
323
|
}
|
|
324
|
-
if (
|
|
324
|
+
if (tokens[pos].eq(LEFT_CURLY_BRACKET)) {
|
|
325
325
|
count += 1;
|
|
326
|
-
} else if (
|
|
326
|
+
} else if (tokens[pos].eq(RIGHT_CURLY_BRACKET)) {
|
|
327
327
|
count -= 1;
|
|
328
328
|
}
|
|
329
329
|
pos += 1;
|
|
@@ -331,16 +331,16 @@ function find_closing_curly_bracket(tokens, start) {
|
|
|
331
331
|
return pos - 1;
|
|
332
332
|
}
|
|
333
333
|
function find_closing_square_bracket(tokens, start) {
|
|
334
|
-
assert(
|
|
334
|
+
assert(tokens[start].eq(LEFT_SQUARE_BRACKET));
|
|
335
335
|
let count = 1;
|
|
336
336
|
let pos = start + 1;
|
|
337
337
|
while (count > 0) {
|
|
338
338
|
if (pos >= tokens.length) {
|
|
339
339
|
throw new LatexParserError("Unmatched square brackets");
|
|
340
340
|
}
|
|
341
|
-
if (
|
|
341
|
+
if (tokens[pos].eq(LEFT_SQUARE_BRACKET)) {
|
|
342
342
|
count += 1;
|
|
343
|
-
} else if (
|
|
343
|
+
} else if (tokens[pos].eq(RIGHT_SQUARE_BRACKET)) {
|
|
344
344
|
count -= 1;
|
|
345
345
|
}
|
|
346
346
|
pos += 1;
|
|
@@ -372,7 +372,7 @@ function eat_parenthesis(tokens, start) {
|
|
|
372
372
|
}
|
|
373
373
|
function eat_primes(tokens, start) {
|
|
374
374
|
let pos = start;
|
|
375
|
-
while (pos < tokens.length &&
|
|
375
|
+
while (pos < tokens.length && tokens[pos].eq(new Token(0 /* ELEMENT */, "'"))) {
|
|
376
376
|
pos += 1;
|
|
377
377
|
}
|
|
378
378
|
return pos - start;
|
|
@@ -391,9 +391,9 @@ function find_closing_right_command(tokens, start) {
|
|
|
391
391
|
if (pos >= tokens.length) {
|
|
392
392
|
return -1;
|
|
393
393
|
}
|
|
394
|
-
if (
|
|
394
|
+
if (tokens[pos].eq(LEFT_COMMAND)) {
|
|
395
395
|
count += 1;
|
|
396
|
-
} else if (
|
|
396
|
+
} else if (tokens[pos].eq(RIGHT_COMMAND)) {
|
|
397
397
|
count -= 1;
|
|
398
398
|
}
|
|
399
399
|
pos += 1;
|
|
@@ -407,9 +407,9 @@ function find_closing_end_command(tokens, start) {
|
|
|
407
407
|
if (pos >= tokens.length) {
|
|
408
408
|
return -1;
|
|
409
409
|
}
|
|
410
|
-
if (
|
|
410
|
+
if (tokens[pos].eq(BEGIN_COMMAND)) {
|
|
411
411
|
count += 1;
|
|
412
|
-
} else if (
|
|
412
|
+
} else if (tokens[pos].eq(END_COMMAND)) {
|
|
413
413
|
count -= 1;
|
|
414
414
|
}
|
|
415
415
|
pos += 1;
|
|
@@ -449,7 +449,7 @@ function tokenize(latex) {
|
|
|
449
449
|
while (newPos < latex.length && latex[newPos] !== "\n") {
|
|
450
450
|
newPos += 1;
|
|
451
451
|
}
|
|
452
|
-
token =
|
|
452
|
+
token = new Token(3 /* COMMENT */, latex.slice(pos + 1, newPos));
|
|
453
453
|
pos = newPos;
|
|
454
454
|
break;
|
|
455
455
|
}
|
|
@@ -458,19 +458,19 @@ function tokenize(latex) {
|
|
|
458
458
|
case "_":
|
|
459
459
|
case "^":
|
|
460
460
|
case "&":
|
|
461
|
-
token =
|
|
461
|
+
token = new Token(6 /* CONTROL */, firstChar);
|
|
462
462
|
pos++;
|
|
463
463
|
break;
|
|
464
464
|
case "\n":
|
|
465
|
-
token =
|
|
465
|
+
token = new Token(5 /* NEWLINE */, firstChar);
|
|
466
466
|
pos++;
|
|
467
467
|
break;
|
|
468
468
|
case "\r": {
|
|
469
469
|
if (pos + 1 < latex.length && latex[pos + 1] === "\n") {
|
|
470
|
-
token =
|
|
470
|
+
token = new Token(5 /* NEWLINE */, "\n");
|
|
471
471
|
pos += 2;
|
|
472
472
|
} else {
|
|
473
|
-
token =
|
|
473
|
+
token = new Token(5 /* NEWLINE */, "\n");
|
|
474
474
|
pos++;
|
|
475
475
|
}
|
|
476
476
|
break;
|
|
@@ -480,7 +480,7 @@ function tokenize(latex) {
|
|
|
480
480
|
while (newPos < latex.length && latex[newPos] === " ") {
|
|
481
481
|
newPos += 1;
|
|
482
482
|
}
|
|
483
|
-
token =
|
|
483
|
+
token = new Token(4 /* WHITESPACE */, latex.slice(pos, newPos));
|
|
484
484
|
pos = newPos;
|
|
485
485
|
break;
|
|
486
486
|
}
|
|
@@ -490,12 +490,12 @@ function tokenize(latex) {
|
|
|
490
490
|
}
|
|
491
491
|
const firstTwoChars = latex.slice(pos, pos + 2);
|
|
492
492
|
if (["\\\\", "\\,"].includes(firstTwoChars)) {
|
|
493
|
-
token =
|
|
493
|
+
token = new Token(6 /* CONTROL */, firstTwoChars);
|
|
494
494
|
} else if (["\\{", "\\}", "\\%", "\\$", "\\&", "\\#", "\\_"].includes(firstTwoChars)) {
|
|
495
|
-
token =
|
|
495
|
+
token = new Token(0 /* ELEMENT */, firstTwoChars);
|
|
496
496
|
} else {
|
|
497
497
|
const command = eat_command_name(latex, pos + 1);
|
|
498
|
-
token =
|
|
498
|
+
token = new Token(1 /* COMMAND */, "\\" + command);
|
|
499
499
|
}
|
|
500
500
|
pos += token.value.length;
|
|
501
501
|
break;
|
|
@@ -506,13 +506,13 @@ function tokenize(latex) {
|
|
|
506
506
|
while (newPos < latex.length && isdigit(latex[newPos])) {
|
|
507
507
|
newPos += 1;
|
|
508
508
|
}
|
|
509
|
-
token =
|
|
509
|
+
token = new Token(0 /* ELEMENT */, latex.slice(pos, newPos));
|
|
510
510
|
} else if (isalpha(firstChar)) {
|
|
511
|
-
token =
|
|
511
|
+
token = new Token(0 /* ELEMENT */, firstChar);
|
|
512
512
|
} else if ("+-*/=\'<>!.,;?()[]|".includes(firstChar)) {
|
|
513
|
-
token =
|
|
513
|
+
token = new Token(0 /* ELEMENT */, firstChar);
|
|
514
514
|
} else {
|
|
515
|
-
token =
|
|
515
|
+
token = new Token(7 /* UNKNOWN */, firstChar);
|
|
516
516
|
}
|
|
517
517
|
pos += token.value.length;
|
|
518
518
|
}
|
|
@@ -522,7 +522,7 @@ function tokenize(latex) {
|
|
|
522
522
|
if (pos >= latex.length || latex[pos] !== "{") {
|
|
523
523
|
throw new LatexParserError(`No content for ${token.value} command`);
|
|
524
524
|
}
|
|
525
|
-
tokens.push(
|
|
525
|
+
tokens.push(new Token(6 /* CONTROL */, "{"));
|
|
526
526
|
const posClosingBracket = find_closing_curly_bracket_char(latex, pos);
|
|
527
527
|
pos++;
|
|
528
528
|
let textInside = latex.slice(pos, posClosingBracket);
|
|
@@ -530,18 +530,15 @@ function tokenize(latex) {
|
|
|
530
530
|
for (const char of chars) {
|
|
531
531
|
textInside = textInside.replaceAll("\\" + char, char);
|
|
532
532
|
}
|
|
533
|
-
tokens.push(
|
|
534
|
-
tokens.push(
|
|
533
|
+
tokens.push(new Token(2 /* TEXT */, textInside));
|
|
534
|
+
tokens.push(new Token(6 /* CONTROL */, "}"));
|
|
535
535
|
pos = posClosingBracket + 1;
|
|
536
536
|
}
|
|
537
537
|
}
|
|
538
538
|
return tokens;
|
|
539
539
|
}
|
|
540
|
-
function token_eq(token1, token2) {
|
|
541
|
-
return token1.type == token2.type && token1.value == token2.value;
|
|
542
|
-
}
|
|
543
540
|
function passIgnoreWhitespaceBeforeScriptMark(tokens) {
|
|
544
|
-
const is_script_mark = (token) =>
|
|
541
|
+
const is_script_mark = (token) => token.eq(SUB_SYMBOL) || token.eq(SUP_SYMBOL);
|
|
545
542
|
let out_tokens = [];
|
|
546
543
|
for (let i = 0;i < tokens.length; i++) {
|
|
547
544
|
if (tokens[i].type === 4 /* WHITESPACE */ && i + 1 < tokens.length && is_script_mark(tokens[i + 1])) {
|
|
@@ -611,15 +608,27 @@ var BINARY_COMMANDS = [
|
|
|
611
608
|
"dfrac",
|
|
612
609
|
"tbinom"
|
|
613
610
|
];
|
|
611
|
+
|
|
612
|
+
class Token {
|
|
613
|
+
type;
|
|
614
|
+
value;
|
|
615
|
+
constructor(type, value) {
|
|
616
|
+
this.type = type;
|
|
617
|
+
this.value = value;
|
|
618
|
+
}
|
|
619
|
+
eq(token) {
|
|
620
|
+
return this.type === token.type && this.value === token.value;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
614
623
|
var EMPTY_NODE = { type: "empty", content: "" };
|
|
615
|
-
var LEFT_CURLY_BRACKET =
|
|
616
|
-
var RIGHT_CURLY_BRACKET =
|
|
617
|
-
var LEFT_SQUARE_BRACKET =
|
|
618
|
-
var RIGHT_SQUARE_BRACKET =
|
|
619
|
-
var LEFT_COMMAND =
|
|
620
|
-
var RIGHT_COMMAND =
|
|
621
|
-
var BEGIN_COMMAND =
|
|
622
|
-
var END_COMMAND =
|
|
624
|
+
var LEFT_CURLY_BRACKET = new Token(6 /* CONTROL */, "{");
|
|
625
|
+
var RIGHT_CURLY_BRACKET = new Token(6 /* CONTROL */, "}");
|
|
626
|
+
var LEFT_SQUARE_BRACKET = new Token(0 /* ELEMENT */, "[");
|
|
627
|
+
var RIGHT_SQUARE_BRACKET = new Token(0 /* ELEMENT */, "]");
|
|
628
|
+
var LEFT_COMMAND = new Token(1 /* COMMAND */, "\\left");
|
|
629
|
+
var RIGHT_COMMAND = new Token(1 /* COMMAND */, "\\right");
|
|
630
|
+
var BEGIN_COMMAND = new Token(1 /* COMMAND */, "\\begin");
|
|
631
|
+
var END_COMMAND = new Token(1 /* COMMAND */, "\\end");
|
|
623
632
|
|
|
624
633
|
class LatexParserError extends Error {
|
|
625
634
|
constructor(message) {
|
|
@@ -627,8 +636,8 @@ class LatexParserError extends Error {
|
|
|
627
636
|
this.name = "LatexParserError";
|
|
628
637
|
}
|
|
629
638
|
}
|
|
630
|
-
var SUB_SYMBOL =
|
|
631
|
-
var SUP_SYMBOL =
|
|
639
|
+
var SUB_SYMBOL = new Token(6 /* CONTROL */, "_");
|
|
640
|
+
var SUP_SYMBOL = new Token(6 /* CONTROL */, "^");
|
|
632
641
|
|
|
633
642
|
class LatexParser {
|
|
634
643
|
space_sensitive;
|
|
@@ -680,22 +689,22 @@ class LatexParser {
|
|
|
680
689
|
let num_prime = 0;
|
|
681
690
|
num_prime += eat_primes(tokens, pos);
|
|
682
691
|
pos += num_prime;
|
|
683
|
-
if (pos < tokens.length &&
|
|
692
|
+
if (pos < tokens.length && tokens[pos].eq(SUB_SYMBOL)) {
|
|
684
693
|
[sub, pos] = this.parseNextExprWithoutSupSub(tokens, pos + 1);
|
|
685
694
|
num_prime += eat_primes(tokens, pos);
|
|
686
695
|
pos += num_prime;
|
|
687
|
-
if (pos < tokens.length &&
|
|
696
|
+
if (pos < tokens.length && tokens[pos].eq(SUP_SYMBOL)) {
|
|
688
697
|
[sup, pos] = this.parseNextExprWithoutSupSub(tokens, pos + 1);
|
|
689
698
|
if (eat_primes(tokens, pos) > 0) {
|
|
690
699
|
throw new LatexParserError("Double superscript");
|
|
691
700
|
}
|
|
692
701
|
}
|
|
693
|
-
} else if (pos < tokens.length &&
|
|
702
|
+
} else if (pos < tokens.length && tokens[pos].eq(SUP_SYMBOL)) {
|
|
694
703
|
[sup, pos] = this.parseNextExprWithoutSupSub(tokens, pos + 1);
|
|
695
704
|
if (eat_primes(tokens, pos) > 0) {
|
|
696
705
|
throw new LatexParserError("Double superscript");
|
|
697
706
|
}
|
|
698
|
-
if (pos < tokens.length &&
|
|
707
|
+
if (pos < tokens.length && tokens[pos].eq(SUB_SYMBOL)) {
|
|
699
708
|
[sub, pos] = this.parseNextExprWithoutSupSub(tokens, pos + 1);
|
|
700
709
|
if (eat_primes(tokens, pos) > 0) {
|
|
701
710
|
throw new LatexParserError("Double superscript");
|
|
@@ -741,9 +750,9 @@ class LatexParser {
|
|
|
741
750
|
case 5 /* NEWLINE */:
|
|
742
751
|
return [{ type: "newline", content: firstToken.value }, start + 1];
|
|
743
752
|
case 1 /* COMMAND */:
|
|
744
|
-
if (
|
|
753
|
+
if (firstToken.eq(BEGIN_COMMAND)) {
|
|
745
754
|
return this.parseBeginEndExpr(tokens, start);
|
|
746
|
-
} else if (
|
|
755
|
+
} else if (firstToken.eq(LEFT_COMMAND)) {
|
|
747
756
|
return this.parseLeftRightExpr(tokens, start);
|
|
748
757
|
} else {
|
|
749
758
|
return this.parseCommandExpr(tokens, start);
|
|
@@ -791,7 +800,7 @@ class LatexParser {
|
|
|
791
800
|
}
|
|
792
801
|
return [{ type: "symbol", content: command }, pos];
|
|
793
802
|
case 1: {
|
|
794
|
-
if (command === "\\sqrt" && pos < tokens.length &&
|
|
803
|
+
if (command === "\\sqrt" && pos < tokens.length && tokens[pos].eq(LEFT_SQUARE_BRACKET)) {
|
|
795
804
|
const posLeftSquareBracket = pos;
|
|
796
805
|
const posRightSquareBracket = find_closing_square_bracket(tokens, pos);
|
|
797
806
|
const exprInside = tokens.slice(posLeftSquareBracket + 1, posRightSquareBracket);
|
|
@@ -802,9 +811,9 @@ class LatexParser {
|
|
|
802
811
|
if (pos + 2 >= tokens.length) {
|
|
803
812
|
throw new LatexParserError("Expecting content for \\text command");
|
|
804
813
|
}
|
|
805
|
-
assert(
|
|
814
|
+
assert(tokens[pos].eq(LEFT_CURLY_BRACKET));
|
|
806
815
|
assert(tokens[pos + 1].type === 2 /* TEXT */);
|
|
807
|
-
assert(
|
|
816
|
+
assert(tokens[pos + 2].eq(RIGHT_CURLY_BRACKET));
|
|
808
817
|
const text = tokens[pos + 1].value;
|
|
809
818
|
return [{ type: "text", content: text }, pos + 3];
|
|
810
819
|
}
|
|
@@ -821,7 +830,7 @@ class LatexParser {
|
|
|
821
830
|
}
|
|
822
831
|
}
|
|
823
832
|
parseLeftRightExpr(tokens, start) {
|
|
824
|
-
assert(
|
|
833
|
+
assert(tokens[start].eq(LEFT_COMMAND));
|
|
825
834
|
let pos = start + 1;
|
|
826
835
|
pos += eat_whitespaces(tokens, pos).length;
|
|
827
836
|
if (pos >= tokens.length) {
|
|
@@ -859,11 +868,11 @@ class LatexParser {
|
|
|
859
868
|
return [res, pos];
|
|
860
869
|
}
|
|
861
870
|
parseBeginEndExpr(tokens, start) {
|
|
862
|
-
assert(
|
|
871
|
+
assert(tokens[start].eq(BEGIN_COMMAND));
|
|
863
872
|
let pos = start + 1;
|
|
864
|
-
assert(
|
|
873
|
+
assert(tokens[pos].eq(LEFT_CURLY_BRACKET));
|
|
865
874
|
assert(tokens[pos + 1].type === 2 /* TEXT */);
|
|
866
|
-
assert(
|
|
875
|
+
assert(tokens[pos + 2].eq(RIGHT_CURLY_BRACKET));
|
|
867
876
|
const envName = tokens[pos + 1].value;
|
|
868
877
|
pos += 3;
|
|
869
878
|
pos += eat_whitespaces(tokens, pos).length;
|
|
@@ -874,9 +883,9 @@ class LatexParser {
|
|
|
874
883
|
}
|
|
875
884
|
const exprInsideEnd = endIdx;
|
|
876
885
|
pos = endIdx + 1;
|
|
877
|
-
assert(
|
|
886
|
+
assert(tokens[pos].eq(LEFT_CURLY_BRACKET));
|
|
878
887
|
assert(tokens[pos + 1].type === 2 /* TEXT */);
|
|
879
|
-
assert(
|
|
888
|
+
assert(tokens[pos + 2].eq(RIGHT_CURLY_BRACKET));
|
|
880
889
|
if (tokens[pos + 1].value !== envName) {
|
|
881
890
|
throw new LatexParserError("Mismatched \\begin and \\end environments");
|
|
882
891
|
}
|
|
@@ -920,6 +929,9 @@ class LatexParser {
|
|
|
920
929
|
}
|
|
921
930
|
|
|
922
931
|
// src/writer.ts
|
|
932
|
+
function is_delimiter(c) {
|
|
933
|
+
return c.type === "atom" && ["(", ")", "[", "]", "{", "}", "|", "\u230A", "\u230B", "\u2308", "\u2309"].includes(c.content);
|
|
934
|
+
}
|
|
923
935
|
function convertTree(node) {
|
|
924
936
|
switch (node.type) {
|
|
925
937
|
case "empty":
|
|
@@ -932,6 +944,7 @@ function convertTree(node) {
|
|
|
932
944
|
args: node.args.map(convertTree)
|
|
933
945
|
};
|
|
934
946
|
case "element":
|
|
947
|
+
return { type: "atom", content: convertToken(node.content) };
|
|
935
948
|
case "symbol":
|
|
936
949
|
return { type: "symbol", content: convertToken(node.content) };
|
|
937
950
|
case "text":
|
|
@@ -978,7 +991,14 @@ function convertTree(node) {
|
|
|
978
991
|
content: "",
|
|
979
992
|
args: node.args.map(convertTree)
|
|
980
993
|
};
|
|
981
|
-
if ([
|
|
994
|
+
if ([
|
|
995
|
+
"[]",
|
|
996
|
+
"()",
|
|
997
|
+
"\\{\\}",
|
|
998
|
+
"\\lfloor\\rfloor",
|
|
999
|
+
"\\lceil\\rceil",
|
|
1000
|
+
"\\lfloor\\rceil"
|
|
1001
|
+
].includes(left.content + right.content)) {
|
|
982
1002
|
return group;
|
|
983
1003
|
}
|
|
984
1004
|
return {
|
|
@@ -1016,7 +1036,7 @@ function convertTree(node) {
|
|
|
1016
1036
|
args: [inner]
|
|
1017
1037
|
};
|
|
1018
1038
|
}
|
|
1019
|
-
if (node.content === "\\mathbb" && arg0.type === "
|
|
1039
|
+
if (node.content === "\\mathbb" && arg0.type === "atom" && /^[A-Z]$/.test(arg0.content)) {
|
|
1020
1040
|
return {
|
|
1021
1041
|
type: "symbol",
|
|
1022
1042
|
content: arg0.content + arg0.content
|
|
@@ -1141,7 +1161,7 @@ class TypstWriter {
|
|
|
1141
1161
|
no_need_space ||= /[\(\[{]\s*(-|\+)$/.test(this.buffer) || this.buffer === "-" || this.buffer === "+";
|
|
1142
1162
|
no_need_space ||= str.startsWith("\n");
|
|
1143
1163
|
no_need_space ||= this.buffer === "";
|
|
1144
|
-
no_need_space ||= /[\
|
|
1164
|
+
no_need_space ||= /[\s_^{\(]$/.test(this.buffer);
|
|
1145
1165
|
if (!no_need_space) {
|
|
1146
1166
|
this.buffer += " ";
|
|
1147
1167
|
}
|
|
@@ -1155,14 +1175,15 @@ class TypstWriter {
|
|
|
1155
1175
|
switch (node.type) {
|
|
1156
1176
|
case "empty":
|
|
1157
1177
|
break;
|
|
1158
|
-
case "
|
|
1159
|
-
let content = node.content;
|
|
1178
|
+
case "atom": {
|
|
1160
1179
|
if (node.content === "," && this.insideFunctionDepth > 0) {
|
|
1161
|
-
|
|
1180
|
+
this.queue.push({ type: "symbol", content: "comma" });
|
|
1181
|
+
} else {
|
|
1182
|
+
this.queue.push({ type: "atom", content: node.content });
|
|
1162
1183
|
}
|
|
1163
|
-
this.queue.push({ type: "symbol", content });
|
|
1164
1184
|
break;
|
|
1165
1185
|
}
|
|
1186
|
+
case "symbol":
|
|
1166
1187
|
case "text":
|
|
1167
1188
|
case "comment":
|
|
1168
1189
|
case "newline":
|
|
@@ -1177,7 +1198,7 @@ class TypstWriter {
|
|
|
1177
1198
|
let { base, sup, sub } = node.data;
|
|
1178
1199
|
this.appendWithBracketsIfNeeded(base);
|
|
1179
1200
|
let trailing_space_needed = false;
|
|
1180
|
-
const has_prime = sup && sup.type === "
|
|
1201
|
+
const has_prime = sup && sup.type === "atom" && sup.content === "\'";
|
|
1181
1202
|
if (has_prime) {
|
|
1182
1203
|
this.queue.push({ type: "atom", content: "\'" });
|
|
1183
1204
|
trailing_space_needed = false;
|
|
@@ -1269,21 +1290,22 @@ class TypstWriter {
|
|
|
1269
1290
|
}
|
|
1270
1291
|
}
|
|
1271
1292
|
appendWithBracketsIfNeeded(node) {
|
|
1272
|
-
|
|
1273
|
-
if (
|
|
1293
|
+
let need_to_wrap = ["group", "supsub", "empty"].includes(node.type);
|
|
1294
|
+
if (node.type === "group") {
|
|
1295
|
+
const first = node.args[0];
|
|
1296
|
+
const last = node.args[node.args.length - 1];
|
|
1297
|
+
if (is_delimiter(first) && is_delimiter(last)) {
|
|
1298
|
+
need_to_wrap = false;
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
if (need_to_wrap) {
|
|
1302
|
+
this.queue.push({ type: "atom", content: "(" });
|
|
1274
1303
|
this.append(node);
|
|
1304
|
+
this.queue.push({ type: "atom", content: ")" });
|
|
1275
1305
|
} else {
|
|
1276
|
-
this.queue.push({
|
|
1277
|
-
type: "atom",
|
|
1278
|
-
content: "("
|
|
1279
|
-
});
|
|
1280
1306
|
this.append(node);
|
|
1281
|
-
this.queue.push({
|
|
1282
|
-
type: "atom",
|
|
1283
|
-
content: ")"
|
|
1284
|
-
});
|
|
1285
1307
|
}
|
|
1286
|
-
return
|
|
1308
|
+
return !need_to_wrap;
|
|
1287
1309
|
}
|
|
1288
1310
|
flushQueue() {
|
|
1289
1311
|
this.queue.forEach((node) => {
|
|
@@ -1327,8 +1349,15 @@ class TypstWriter {
|
|
|
1327
1349
|
res = res.replace(/ceil\(\)/g, 'ceil("")');
|
|
1328
1350
|
return res;
|
|
1329
1351
|
};
|
|
1330
|
-
|
|
1331
|
-
|
|
1352
|
+
const smartRoundPass = function(input) {
|
|
1353
|
+
let res = input.replace(/⌊\s*(.*?)\s*⌉/g, "round($1)");
|
|
1354
|
+
res = res.replace(/round\(\)/g, 'round("")');
|
|
1355
|
+
return res;
|
|
1356
|
+
};
|
|
1357
|
+
const all_passes = [smartFloorPass, smartCeilPass, smartRoundPass];
|
|
1358
|
+
for (const pass of all_passes) {
|
|
1359
|
+
this.buffer = pass(this.buffer);
|
|
1360
|
+
}
|
|
1332
1361
|
return this.buffer;
|
|
1333
1362
|
}
|
|
1334
1363
|
}
|
package/dist/parser.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import { TexNode,
|
|
1
|
+
import { TexNode, TokenType } from "./types";
|
|
2
|
+
export declare class Token {
|
|
3
|
+
type: TokenType;
|
|
4
|
+
value: string;
|
|
5
|
+
constructor(type: TokenType, value: string);
|
|
6
|
+
eq(token: Token): boolean;
|
|
7
|
+
}
|
|
2
8
|
export declare function tokenize(latex: string): Token[];
|
|
3
9
|
export declare class LatexParserError extends Error {
|
|
4
10
|
constructor(message: string);
|
package/dist/tex2typst.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var O=new Map([["nonumber",""],["vec","arrow"],["neq","eq.not"],["dot","dot"],["ddot","dot.double"],["doteq","dot(eq)"],["dots","dots.h"],["ldots","dots.h"],["vdots","dots.v"],["ddots","dots.down"],["widehat","hat"],["widetilde","tilde"],["quad","quad"],["qquad","wide"],["overbrace","overbrace"],["underbrace","underbrace"],["overline","overline"],["underline","underline"],["bar","macron"],["dbinom","binom"],["tbinom","binom"],["dfrac","frac"],["tfrac","frac"],["boldsymbol","bold"],["mathbb","bb"],["mathbf","bold"],["mathcal","cal"],["mathit","italic"],["mathfrak","frak"],["mathrm","upright"],["mathsf","sans"],["mathtt","mono"],["rm","upright"],["pmb","bold"],["pm","plus.minus"],["mp","minus.plus"],["oplus","xor"],["boxplus","plus.square"],["otimes","times.circle"],["boxtimes","times.square"],["sim","tilde"],["approx","approx"],["cong","tilde.equiv"],["simeq","tilde.eq"],["asymp","\u224D"],["equiv","equiv"],["propto","prop"],["lfloor","\u230A"],["rfloor","\u230B"],["lceil","\u2308"],["rceil","\u2309"],["gets","arrow.l"],["hookleftarrow","arrow.l.hook"],["leftharpoonup","harpoon.lt"],["leftharpoondown","harpoon.lb"],["rightleftharpoons","harpoons.rtlb"],["longleftarrow","arrow.l.long"],["longrightarrow","arrow.r.long"],["longleftrightarrow","arrow.l.r.long"],["Longleftarrow","arrow.l.double.long"],["Longrightarrow","arrow.r.double.long"],["Longleftrightarrow","arrow.l.r.double.long"],["longmapsto","arrow.r.bar"],["hookrightarrow","arrow.r.hook"],["rightharpoonup","harpoon.rt"],["rightharpoondown","harpoon.rb"],["iff","arrow.l.r.double.long"],["implies","arrow.r.double.long"],["uparrow","arrow.t"],["downarrow","arrow.b"],["updownarrow","arrow.t.b"],["Uparrow","arrow.t.double"],["Downarrow","arrow.b.double"],["Updownarrow","arrow.t.b.double"],["nearrow","arrow.tr"],["searrow","arrow.br"],["swarrow","arrow.bl"],["nwarrow","arrow.tl"],["leadsto","arrow.squiggly"],["leftleftarrows","arrows.ll"],["rightrightarrows","arrows.rr"],["Cap","sect.double"],["Cup","union.double"],["Delta","Delta"],["Gamma","Gamma"],["Join","join"],["Lambda","Lambda"],["Leftarrow","arrow.l.double"],["Leftrightarrow","arrow.l.r.double"],["Longrightarrow","arrow.r.double.long"],["Omega","Omega"],["P","pilcrow"],["Phi","Phi"],["Pi","Pi"],["Psi","Psi"],["Rightarrow","arrow.r.double"],["S","section"],["Sigma","Sigma"],["Theta","Theta"],["aleph","alef"],["alpha","alpha"],["angle","angle"],["approx","approx"],["approxeq","approx.eq"],["ast","ast"],["beta","beta"],["bigcap","sect.big"],["bigcirc","circle.big"],["bigcup","union.big"],["bigodot","dot.circle.big"],["bigoplus","xor.big"],["bigotimes","times.circle.big"],["bigsqcup","union.sq.big"],["bigtriangledown","triangle.b"],["bigtriangleup","triangle.t"],["biguplus","union.plus.big"],["bigvee","or.big"],["bigwedge","and.big"],["bullet","bullet"],["cap","sect"],["cdot","dot.op"],["cdots","dots.c"],["checkmark","checkmark"],["chi","chi"],["circ","circle.small"],["colon","colon"],["cong","tilde.equiv"],["coprod","product.co"],["copyright","copyright"],["cup","union"],["curlyvee","or.curly"],["curlywedge","and.curly"],["dagger","dagger"],["dashv","tack.l"],["ddagger","dagger.double"],["delta","delta"],["ddots","dots.down"],["diamond","diamond"],["div","div"],["divideontimes","times.div"],["dotplus","plus.dot"],["downarrow","arrow.b"],["ell","ell"],["emptyset","nothing"],["epsilon","epsilon.alt"],["equiv","equiv"],["eta","eta"],["exists","exists"],["forall","forall"],["gamma","gamma"],["ge","gt.eq"],["geq","gt.eq"],["geqslant","gt.eq.slant"],["gg","gt.double"],["hbar","planck.reduce"],["imath","dotless.i"],["iiiint","intgral.quad"],["iiint","integral.triple"],["iint","integral.double"],["in","in"],["infty","infinity"],["int","integral"],["intercal","top"],["iota","iota"],["jmath","dotless.j"],["kappa","kappa"],["lambda","lambda"],["land","and"],["langle","angle.l"],["lbrace","brace.l"],["lbrack","bracket.l"],["ldots","dots.l"],["le","lt.eq"],["leadsto","arrow.squiggly"],["leftarrow","arrow.l"],["leftthreetimes","times.three.l"],["leftrightarrow","arrow.l.r"],["leq","lt.eq"],["leqslant","lt.eq.slant"],["lhd","triangle.l"],["ll","lt.double"],["longmapsto","arrow.bar.long"],["longrightarrow","arrow.long"],["lor","or"],["ltimes","times.l"],["mapsto","arrow.bar"],["measuredangle","angle.arc"],["mid","divides"],["models","models"],["mp","minus.plus"],["mu","mu"],["nRightarrow","arrow.double.not"],["nabla","nabla"],["ncong","tilde.nequiv"],["ne","eq.not"],["neg","not"],["neq","eq.not"],["nexists","exists.not"],["ni","in.rev"],["nleftarrow","arrow.l.not"],["nleq","lt.eq.not"],["nparallel","parallel.not"],["ngeq","gt.eq.not"],["nmid","divides.not"],["notin","in.not"],["nrightarrow","arrow.not"],["nsim","tilde.not"],["nsubseteq","subset.eq.not"],["nu","nu"],["ntriangleleft","lt.tri.not"],["ntriangleright","gt.tri.not"],["nwarrow","arrow.tl"],["odot","dot.circle"],["oint","integral.cont"],["oiint","integral.surf"],["oiiint","integral.vol"],["omega","omega"],["ominus","minus.circle"],["oplus","xor"],["otimes","times.circle"],["parallel","parallel"],["partial","diff"],["perp","perp"],["phi","phi.alt"],["pi","pi"],["pm","plus.minus"],["pounds","pound"],["prec","prec"],["preceq","prec.eq"],["prime","prime"],["prod","product"],["propto","prop"],["psi","psi"],["rangle","angle.r"],["rbrace","brace.r"],["rbrack","bracket.r"],["rhd","triangle"],["rho","rho"],["rightarrow","arrow.r"],["rightthreetimes","times.three.r"],["rtimes","times.r"],["setminus","without"],["sigma","sigma"],["sim","tilde"],["simeq","tilde.eq"],["slash","slash"],["smallsetminus","without"],["spadesuit","suit.spade"],["sqcap","sect.sq"],["sqcup","union.sq"],["sqsubseteq","subset.eq.sq"],["sqsupseteq","supset.eq.sq"],["star","star"],["subset","subset"],["subseteq","subset.eq"],["subsetneq","subset.neq"],["succ","succ"],["succeq","succ.eq"],["sum","sum"],["supset","supset"],["supseteq","supset.eq"],["supsetneq","supset.neq"],["swarrow","arrow.bl"],["tau","tau"],["theta","theta"],["times","times"],["to","arrow.r"],["top","top"],["triangle","triangle.t"],["triangledown","triangle.b.small"],["triangleleft","triangle.l.small"],["triangleright","triangle.r.small"],["twoheadrightarrow","arrow.r.twohead"],["uparrow","arrow.t"],["updownarrow","arrow.t.b"],["upharpoonright","harpoon.tr"],["uplus","union.plus"],["upsilon","upsilon"],["varepsilon","epsilon"],["varnothing","diameter"],["varphi","phi"],["varpi","pi.alt"],["varrho","rho.alt"],["varsigma","sigma.alt"],["vartheta","theta.alt"],["vdash","tack.r"],["vdots","dots.v"],["vee","or"],["wedge","and"],["wr","wreath"],["xi","xi"],["yen","yen"],["zeta","zeta"],["mathscr","scr"],["LaTeX","#LaTeX"],["TeX","#TeX"]]);function W(z,Z=""){if(!z)throw new H(Z)}function x(z){if(c.includes(z))return 1;else if(_.includes(z))return 2;else return 0}function l(z,Z){W(j(z[Z],D));let J=1,V=Z+1;while(J>0){if(V>=z.length)throw new H("Unmatched curly brackets");if(j(z[V],D))J+=1;else if(j(z[V],v))J-=1;V+=1}return V-1}function d(z,Z){W(j(z[Z],I));let J=1,V=Z+1;while(J>0){if(V>=z.length)throw new H("Unmatched square brackets");if(j(z[V],I))J+=1;else if(j(z[V],i))J-=1;V+=1}return V-1}function L(z){return"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".includes(z)}function g(z){return"0123456789".includes(z)}function A(z,Z){let J=Z;while(J<z.length&&[4,5].includes(z[J].type))J++;return z.slice(Z,J)}function C(z,Z){const J=z[Z];if(J.type===0&&["(",")","[","]","|","\\{","\\}"].includes(J.value))return J;else if(J.type===1&&["lfloor","rfloor","lceil","rceil","langle","rangle"].includes(J.value.slice(1)))return J;else return null}function U(z,Z){let J=Z;while(J<z.length&&j(z[J],{type:0,value:"'"}))J+=1;return J-Z}function T(z,Z){let J=Z;while(J<z.length&&L(z[J]))J+=1;return z.substring(Z,J)}function k(z,Z){let J=1,V=Z;while(J>0){if(V>=z.length)return-1;if(j(z[V],f))J+=1;else if(j(z[V],p))J-=1;V+=1}return V-1}function n(z,Z){let J=1,V=Z;while(J>0){if(V>=z.length)return-1;if(j(z[V],B))J+=1;else if(j(z[V],a))J-=1;V+=1}return V-1}function r(z,Z){W(z[Z]==="{");let J=1,V=Z+1;while(J>0){if(V>=z.length)throw new H("Unmatched curly brackets");if(V+1<z.length&&["\\{","\\}"].includes(z.substring(V,V+2))){V+=2;continue}if(z[V]==="{")J+=1;else if(z[V]==="}")J-=1;V+=1}return V-1}function P(z){const Z=[];let J=0;while(J<z.length){const V=z[J];let X;switch(V){case"%":{let $=J+1;while($<z.length&&z[$]!=="\n")$+=1;X={type:3,value:z.slice(J+1,$)},J=$;break}case"{":case"}":case"_":case"^":case"&":X={type:6,value:V},J++;break;case"\n":X={type:5,value:V},J++;break;case"\r":{if(J+1<z.length&&z[J+1]==="\n")X={type:5,value:"\n"},J+=2;else X={type:5,value:"\n"},J++;break}case" ":{let $=J;while($<z.length&&z[$]===" ")$+=1;X={type:4,value:z.slice(J,$)},J=$;break}case"\\":{if(J+1>=z.length)throw new H("Expecting command name after \\");const $=z.slice(J,J+2);if(["\\\\","\\,"].includes($))X={type:6,value:$};else if(["\\{","\\}","\\%","\\$","\\&","\\#","\\_"].includes($))X={type:0,value:$};else{const q=T(z,J+1);X={type:1,value:"\\"+q}}J+=X.value.length;break}default:{if(g(V)){let $=J;while($<z.length&&g(z[$]))$+=1;X={type:0,value:z.slice(J,$)}}else if(L(V))X={type:0,value:V};else if("+-*/=\'<>!.,;?()[]|".includes(V))X={type:0,value:V};else X={type:7,value:V};J+=X.value.length}}if(Z.push(X),X.type===1&&["\\text","\\operatorname","\\begin","\\end"].includes(X.value)){if(J>=z.length||z[J]!=="{")throw new H(`No content for ${X.value} command`);Z.push({type:6,value:"{"});const $=r(z,J);J++;let q=z.slice(J,$);const Q=["{","}","\\","$","&","#","_","%"];for(let F of Q)q=q.replaceAll("\\"+F,F);Z.push({type:2,value:q}),Z.push({type:6,value:"}"}),J=$+1}}return Z}function j(z,Z){return z.type==Z.type&&z.value==Z.value}function t(z){const Z=(V)=>j(V,M)||j(V,h);let J=[];for(let V=0;V<z.length;V++){if(z[V].type===4&&V+1<z.length&&Z(z[V+1]))continue;if(z[V].type===4&&V-1>=0&&Z(z[V-1]))continue;J.push(z[V])}return J}function s(z,Z){let J=[];for(let V of z)if(V.type===1&&Z[V.value]){const X=P(Z[V.value]);J=J.concat(X)}else J.push(V);return J}function u(z,Z){const J=new y;let V=P(z);return V=t(V),V=s(V,Z),J.parse(V)}var c=["sqrt","text","bar","bold","boldsymbol","ddot","dot","hat","mathbb","mathbf","mathcal","mathfrak","mathit","mathrm","mathscr","mathsf","mathtt","operatorname","overbrace","overline","pmb","rm","tilde","underbrace","underline","vec","widehat","widetilde"],_=["frac","tfrac","binom","dbinom","dfrac","tbinom"],S={type:"empty",content:""},D={type:6,value:"{"},v={type:6,value:"}"},I={type:0,value:"["},i={type:0,value:"]"},f={type:1,value:"\\left"},p={type:1,value:"\\right"},B={type:1,value:"\\begin"},a={type:1,value:"\\end"};class H extends Error{constructor(z){super(z);this.name="LatexParserError"}}var M={type:6,value:"_"},h={type:6,value:"^"};class y{space_sensitive;newline_sensitive;constructor(z=!1,Z=!0){this.space_sensitive=z,this.newline_sensitive=Z}parse(z){const Z=[];let J=0;while(J<z.length){const V=[];let X=0;while(X<z.length){const[$,q]=this.parseNextExpr(z,X);if(X=q,!this.space_sensitive&&$.type==="whitespace")continue;if(!this.newline_sensitive&&$.type==="newline")continue;if($.type==="control"&&$.content==="&")throw new H("Unexpected & outside of an alignment");V.push($)}if(V.length===0)return S;else if(V.length===1)return V[0];else return{type:"ordgroup",content:"",args:V}}if(Z.length===0)return S;else if(Z.length===1)return Z[0];else return{type:"ordgroup",content:"",args:Z}}parseNextExpr(z,Z){let[J,V]=this.parseNextExprWithoutSupSub(z,Z),X=null,$=null,q=0;if(q+=U(z,V),V+=q,V<z.length&&j(z[V],M)){if([X,V]=this.parseNextExprWithoutSupSub(z,V+1),q+=U(z,V),V+=q,V<z.length&&j(z[V],h)){if([$,V]=this.parseNextExprWithoutSupSub(z,V+1),U(z,V)>0)throw new H("Double superscript")}}else if(V<z.length&&j(z[V],h)){if([$,V]=this.parseNextExprWithoutSupSub(z,V+1),U(z,V)>0)throw new H("Double superscript");if(V<z.length&&j(z[V],M)){if([X,V]=this.parseNextExprWithoutSupSub(z,V+1),U(z,V)>0)throw new H("Double superscript")}}if(X!==null||$!==null||q>0){const Q={base:J};if(X)Q.sub=X;if(q>0){Q.sup={type:"ordgroup",content:"",args:[]};for(let F=0;F<q;F++)Q.sup.args.push({type:"element",content:"'"});if($)Q.sup.args.push($);if(Q.sup.args.length===1)Q.sup=Q.sup.args[0]}else if($)Q.sup=$;return[{type:"supsub",content:"",data:Q},V]}else return[J,V]}parseNextExprWithoutSupSub(z,Z){const J=z[Z];switch(J.type){case 0:return[{type:"element",content:J.value},Z+1];case 2:return[{type:"text",content:J.value},Z+1];case 3:return[{type:"comment",content:J.value},Z+1];case 4:return[{type:"whitespace",content:J.value},Z+1];case 5:return[{type:"newline",content:J.value},Z+1];case 1:if(j(J,B))return this.parseBeginEndExpr(z,Z);else if(j(J,f))return this.parseLeftRightExpr(z,Z);else return this.parseCommandExpr(z,Z);case 6:switch(J.value){case"{":const $=l(z,Z),q=z.slice(Z+1,$);return[this.parse(q),$+1];case"}":throw new H("Unmatched '}'");case"\\\\":return[{type:"control",content:"\\\\"},Z+1];case"\\,":return[{type:"control",content:"\\,"},Z+1];case"_":return[S,Z];case"^":return[S,Z];case"&":return[{type:"control",content:"&"},Z+1];default:throw new H("Unknown control sequence")}default:throw new H("Unknown token type")}}parseCommandExpr(z,Z){W(z[Z].type===1);const J=z[Z].value;let V=Z+1;if(["left","right","begin","end"].includes(J.slice(1)))throw new H("Unexpected command: "+J);switch(x(J.slice(1))){case 0:if(!O.has(J.slice(1)))return[{type:"unknownMacro",content:J},V];return[{type:"symbol",content:J},V];case 1:{if(J==="\\sqrt"&&V<z.length&&j(z[V],I)){const Q=V,F=d(z,V),Y=z.slice(Q+1,F),R=this.parse(Y),[w,E]=this.parseNextExprWithoutSupSub(z,F+1);return[{type:"unaryFunc",content:J,args:[w],data:R},E]}else if(J==="\\text"){if(V+2>=z.length)throw new H("Expecting content for \\text command");return W(j(z[V],D)),W(z[V+1].type===2),W(j(z[V+2],v)),[{type:"text",content:z[V+1].value},V+3]}let[$,q]=this.parseNextExprWithoutSupSub(z,V);return[{type:"unaryFunc",content:J,args:[$]},q]}case 2:{const[$,q]=this.parseNextExprWithoutSupSub(z,V),[Q,F]=this.parseNextExprWithoutSupSub(z,q);return[{type:"binaryFunc",content:J,args:[$,Q]},F]}default:throw new Error("Invalid number of parameters")}}parseLeftRightExpr(z,Z){W(j(z[Z],f));let J=Z+1;if(J+=A(z,J).length,J>=z.length)throw new H("Expecting delimiter after \\left");const V=C(z,J);if(V===null)throw new H("Invalid delimiter after \\left");J++;const X=J,$=k(z,J);if($===-1)throw new H("No matching \\right");const q=$;if(J=$+1,J+=A(z,J).length,J>=z.length)throw new H("Expecting \\right after \\left");const Q=C(z,J);if(Q===null)throw new H("Invalid delimiter after \\right");J++;const F=z.slice(X,q),Y=this.parse(F);return[{type:"leftright",content:"",args:[{type:"element",content:V.value},Y,{type:"element",content:Q.value}]},J]}parseBeginEndExpr(z,Z){W(j(z[Z],B));let J=Z+1;W(j(z[J],D)),W(z[J+1].type===2),W(j(z[J+2],v));const V=z[J+1].value;J+=3,J+=A(z,J).length;const X=J,$=n(z,J);if($===-1)throw new H("No matching \\end");const q=$;if(J=$+1,W(j(z[J],D)),W(z[J+1].type===2),W(j(z[J+2],v)),z[J+1].value!==V)throw new H("Mismatched \\begin and \\end environments");J+=3;const Q=z.slice(X,q);while(Q.length>0&&[4,5].includes(Q[Q.length-1].type))Q.pop();const F=this.parseAligned(Q);return[{type:"beginend",content:V,data:F},J]}parseAligned(z){let Z=0;const J=[];let V=[];J.push(V);let X={type:"ordgroup",content:"",args:[]};V.push(X);while(Z<z.length){const[$,q]=this.parseNextExpr(z,Z);if(Z=q,$.type==="whitespace")continue;else if($.type==="newline"&&!this.newline_sensitive)continue;else if($.type==="control"&&$.content==="\\\\")V=[],X={type:"ordgroup",content:"",args:[]},V.push(X),J.push(V);else if($.type==="control"&&$.content==="&")X={type:"ordgroup",content:"",args:[]},V.push(X);else X.args.push($)}return J}}function G(z){switch(z.type){case"empty":case"whitespace":return{type:"empty",content:""};case"ordgroup":return{type:"group",content:"",args:z.args.map(G)};case"element":case"symbol":return{type:"symbol",content:N(z.content)};case"text":return{type:"text",content:z.content};case"comment":return{type:"comment",content:z.content};case"supsub":{let{base:Z,sup:J,sub:V}=z.data;if(Z&&Z.type==="unaryFunc"&&Z.content==="\\overbrace"&&J)return{type:"binaryFunc",content:"overbrace",args:[G(Z.args[0]),G(J)]};else if(Z&&Z.type==="unaryFunc"&&Z.content==="\\underbrace"&&V)return{type:"binaryFunc",content:"underbrace",args:[G(Z.args[0]),G(V)]};const X={base:G(Z)};if(X.base.type==="empty")X.base={type:"text",content:""};if(J)X.sup=G(J);if(V)X.sub=G(V);return{type:"supsub",content:"",data:X}}case"leftright":{const[Z,J,V]=z.args,X={type:"group",content:"",args:z.args.map(G)};if(["[]","()","\\{\\}","\\lfloor\\rfloor","\\lceil\\rceil"].includes(Z.content+V.content))return X;return{type:"unaryFunc",content:"lr",args:[X]}}case"binaryFunc":return{type:"binaryFunc",content:N(z.content),args:z.args.map(G)};case"unaryFunc":{const Z=G(z.args[0]);if(z.content==="\\sqrt"&&z.data)return{type:"binaryFunc",content:"root",args:[G(z.data),Z]};if(z.content==="\\mathbf")return{type:"unaryFunc",content:"upright",args:[{type:"unaryFunc",content:"bold",args:[Z]}]};if(z.content==="\\mathbb"&&Z.type==="symbol"&&/^[A-Z]$/.test(Z.content))return{type:"symbol",content:Z.content+Z.content};if(z.content==="\\operatorname"){const J=z.args;if(J.length!==1||J[0].type!=="text")throw new K("Expecting body of \\operatorname to be text but got",z);const V=J[0].content;if(o.includes(V))return{type:"symbol",content:V};else return{type:"unaryFunc",content:"op",args:[{type:"text",content:V}]}}return{type:"unaryFunc",content:N(z.content),args:z.args.map(G)}}case"newline":return{type:"newline",content:"\n"};case"beginend":{const J=z.data.map((V)=>V.map(G));if(z.content.startsWith("align"))return{type:"align",content:"",data:J};else return{type:"matrix",content:"mat",data:J}}case"unknownMacro":return{type:"unknown",content:N(z.content)};case"control":if(z.content==="\\\\")return{type:"symbol",content:"\\"};else if(z.content==="\\,")return{type:"symbol",content:"thin"};else throw new K(`Unknown control sequence: ${z.content}`,z);default:throw new K(`Unimplemented node type: ${z.type}`,z)}}function N(z){if(/^[a-zA-Z0-9]$/.test(z))return z;else if(z==="\\\\")return"\\";else if(z=="/")return"\\/";else if(["\\$","\\#","\\&","\\_"].includes(z))return z;else if(z.startsWith("\\")){const Z=z.slice(1);if(O.has(Z))return O.get(Z);else return Z}return z}var o=["dim","id","im","mod","Pr","sech","csch"];class K extends Error{node;constructor(z,Z){super(z);this.name="TypstWriterError",this.node=Z}}class b{nonStrict;preferTypstIntrinsic;buffer="";queue=[];needSpaceAfterSingleItemScript=!1;insideFunctionDepth=0;constructor(z,Z){this.nonStrict=z,this.preferTypstIntrinsic=Z}writeBuffer(z){if(this.needSpaceAfterSingleItemScript&&/^[0-9a-zA-Z\(]/.test(z))this.buffer+=" ";else{let Z=!1;if(Z||=/[\(\|]$/.test(this.buffer)&&/^\w/.test(z),Z||=/^[}()_^,;!\|]$/.test(z),Z||=z==="'",Z||=/[0-9]$/.test(this.buffer)&&/^[0-9]/.test(z),Z||=/[\(\[{]\s*(-|\+)$/.test(this.buffer)||this.buffer==="-"||this.buffer==="+",Z||=z.startsWith("\n"),Z||=this.buffer==="",Z||=/[\s"_^{\(]$/.test(this.buffer),!Z)this.buffer+=" "}if(this.needSpaceAfterSingleItemScript)this.needSpaceAfterSingleItemScript=!1;this.buffer+=z}append(z){switch(z.type){case"empty":break;case"symbol":{let Z=z.content;if(z.content===","&&this.insideFunctionDepth>0)Z="comma";this.queue.push({type:"symbol",content:Z});break}case"text":case"comment":case"newline":this.queue.push(z);break;case"group":for(let Z of z.args)this.append(Z);break;case"supsub":{let{base:Z,sup:J,sub:V}=z.data;this.appendWithBracketsIfNeeded(Z);let X=!1;const $=J&&J.type==="symbol"&&J.content==="\'";if($)this.queue.push({type:"atom",content:"\'"}),X=!1;if(V)this.queue.push({type:"atom",content:"_"}),X=this.appendWithBracketsIfNeeded(V);if(J&&!$)this.queue.push({type:"atom",content:"^"}),X=this.appendWithBracketsIfNeeded(J);if(X)this.queue.push({type:"softSpace",content:""});break}case"binaryFunc":{const Z={type:"symbol",content:z.content},[J,V]=z.args;this.queue.push(Z),this.insideFunctionDepth++,this.queue.push({type:"atom",content:"("}),this.append(J),this.queue.push({type:"atom",content:","}),this.append(V),this.queue.push({type:"atom",content:")"}),this.insideFunctionDepth--;break}case"unaryFunc":{const Z={type:"symbol",content:z.content},J=z.args[0];this.queue.push(Z),this.insideFunctionDepth++,this.queue.push({type:"atom",content:"("}),this.append(J),this.queue.push({type:"atom",content:")"}),this.insideFunctionDepth--;break}case"align":{const Z=z.data;Z.forEach((J,V)=>{if(J.forEach((X,$)=>{if($>0)this.queue.push({type:"atom",content:"&"});this.append(X)}),V<Z.length-1)this.queue.push({type:"symbol",content:"\\"})});break}case"matrix":{const Z=z.data;this.queue.push({type:"symbol",content:"mat"}),this.insideFunctionDepth++,this.queue.push({type:"atom",content:"("}),this.queue.push({type:"symbol",content:"delim: #none, "}),Z.forEach((J,V)=>{J.forEach((X,$)=>{if(this.append(X),$<J.length-1)this.queue.push({type:"atom",content:","});else if(V<Z.length-1)this.queue.push({type:"atom",content:";"})})}),this.queue.push({type:"atom",content:")"}),this.insideFunctionDepth--;break}case"unknown":{if(this.nonStrict)this.queue.push({type:"symbol",content:z.content});else throw new K(`Unknown macro: ${z.content}`,z);break}default:throw new K(`Unimplemented node type to append: ${z.type}`,z)}}appendWithBracketsIfNeeded(z){const Z=!["group","supsub","empty"].includes(z.type);if(Z)this.append(z);else this.queue.push({type:"atom",content:"("}),this.append(z),this.queue.push({type:"atom",content:")"});return Z}flushQueue(){this.queue.forEach((z)=>{let Z="";switch(z.type){case"atom":case"symbol":Z=z.content;break;case"text":Z=`"${z.content}"`;break;case"softSpace":this.needSpaceAfterSingleItemScript=!0,Z="";break;case"comment":Z=`//${z.content}`;break;case"newline":Z="\n";break;default:throw new K(`Unexpected node type to stringify: ${z.type}`,z)}if(Z!=="")this.writeBuffer(Z)}),this.queue=[]}finalize(){this.flushQueue();const z=function(J){let V=J.replace(/⌊\s*(.*?)\s*⌋/g,"floor($1)");return V=V.replace(/floor\(\)/g,'floor("")'),V},Z=function(J){let V=J.replace(/⌈\s*(.*?)\s*⌉/g,"ceil($1)");return V=V.replace(/ceil\(\)/g,'ceil("")'),V};return this.buffer=z(this.buffer),this.buffer=Z(this.buffer),this.buffer}}function m(z,Z){const J={nonStrict:!0,preferTypstIntrinsic:!0,customTexMacros:{}};if(Z){if(Z.nonStrict)J.nonStrict=Z.nonStrict;if(Z.preferTypstIntrinsic)J.preferTypstIntrinsic=Z.preferTypstIntrinsic;if(Z.customTexMacros)J.customTexMacros=Z.customTexMacros}const V=u(z,J.customTexMacros),X=G(V),$=new b(J.nonStrict,J.preferTypstIntrinsic);return $.append(X),$.finalize()}if(typeof window!=="undefined")window.tex2typst=m;
|
|
1
|
+
var O=new Map([["nonumber",""],["vec","arrow"],["neq","eq.not"],["dot","dot"],["ddot","dot.double"],["doteq","dot(eq)"],["dots","dots.h"],["ldots","dots.h"],["vdots","dots.v"],["ddots","dots.down"],["widehat","hat"],["widetilde","tilde"],["quad","quad"],["qquad","wide"],["overbrace","overbrace"],["underbrace","underbrace"],["overline","overline"],["underline","underline"],["bar","macron"],["dbinom","binom"],["tbinom","binom"],["dfrac","frac"],["tfrac","frac"],["boldsymbol","bold"],["mathbb","bb"],["mathbf","bold"],["mathcal","cal"],["mathit","italic"],["mathfrak","frak"],["mathrm","upright"],["mathsf","sans"],["mathtt","mono"],["rm","upright"],["pmb","bold"],["pm","plus.minus"],["mp","minus.plus"],["oplus","xor"],["boxplus","plus.square"],["otimes","times.circle"],["boxtimes","times.square"],["sim","tilde"],["approx","approx"],["cong","tilde.equiv"],["simeq","tilde.eq"],["asymp","\u224D"],["equiv","equiv"],["propto","prop"],["lfloor","\u230A"],["rfloor","\u230B"],["lceil","\u2308"],["rceil","\u2309"],["gets","arrow.l"],["hookleftarrow","arrow.l.hook"],["leftharpoonup","harpoon.lt"],["leftharpoondown","harpoon.lb"],["rightleftharpoons","harpoons.rtlb"],["longleftarrow","arrow.l.long"],["longrightarrow","arrow.r.long"],["longleftrightarrow","arrow.l.r.long"],["Longleftarrow","arrow.l.double.long"],["Longrightarrow","arrow.r.double.long"],["Longleftrightarrow","arrow.l.r.double.long"],["longmapsto","arrow.r.bar"],["hookrightarrow","arrow.r.hook"],["rightharpoonup","harpoon.rt"],["rightharpoondown","harpoon.rb"],["iff","arrow.l.r.double.long"],["implies","arrow.r.double.long"],["uparrow","arrow.t"],["downarrow","arrow.b"],["updownarrow","arrow.t.b"],["Uparrow","arrow.t.double"],["Downarrow","arrow.b.double"],["Updownarrow","arrow.t.b.double"],["nearrow","arrow.tr"],["searrow","arrow.br"],["swarrow","arrow.bl"],["nwarrow","arrow.tl"],["leadsto","arrow.squiggly"],["leftleftarrows","arrows.ll"],["rightrightarrows","arrows.rr"],["Cap","sect.double"],["Cup","union.double"],["Delta","Delta"],["Gamma","Gamma"],["Join","join"],["Lambda","Lambda"],["Leftarrow","arrow.l.double"],["Leftrightarrow","arrow.l.r.double"],["Longrightarrow","arrow.r.double.long"],["Omega","Omega"],["P","pilcrow"],["Phi","Phi"],["Pi","Pi"],["Psi","Psi"],["Rightarrow","arrow.r.double"],["S","section"],["Sigma","Sigma"],["Theta","Theta"],["aleph","alef"],["alpha","alpha"],["angle","angle"],["approx","approx"],["approxeq","approx.eq"],["ast","ast"],["beta","beta"],["bigcap","sect.big"],["bigcirc","circle.big"],["bigcup","union.big"],["bigodot","dot.circle.big"],["bigoplus","xor.big"],["bigotimes","times.circle.big"],["bigsqcup","union.sq.big"],["bigtriangledown","triangle.b"],["bigtriangleup","triangle.t"],["biguplus","union.plus.big"],["bigvee","or.big"],["bigwedge","and.big"],["bullet","bullet"],["cap","sect"],["cdot","dot.op"],["cdots","dots.c"],["checkmark","checkmark"],["chi","chi"],["circ","circle.small"],["colon","colon"],["cong","tilde.equiv"],["coprod","product.co"],["copyright","copyright"],["cup","union"],["curlyvee","or.curly"],["curlywedge","and.curly"],["dagger","dagger"],["dashv","tack.l"],["ddagger","dagger.double"],["delta","delta"],["ddots","dots.down"],["diamond","diamond"],["div","div"],["divideontimes","times.div"],["dotplus","plus.dot"],["downarrow","arrow.b"],["ell","ell"],["emptyset","nothing"],["epsilon","epsilon.alt"],["equiv","equiv"],["eta","eta"],["exists","exists"],["forall","forall"],["gamma","gamma"],["ge","gt.eq"],["geq","gt.eq"],["geqslant","gt.eq.slant"],["gg","gt.double"],["hbar","planck.reduce"],["imath","dotless.i"],["iiiint","intgral.quad"],["iiint","integral.triple"],["iint","integral.double"],["in","in"],["infty","infinity"],["int","integral"],["intercal","top"],["iota","iota"],["jmath","dotless.j"],["kappa","kappa"],["lambda","lambda"],["land","and"],["langle","angle.l"],["lbrace","brace.l"],["lbrack","bracket.l"],["ldots","dots.l"],["le","lt.eq"],["leadsto","arrow.squiggly"],["leftarrow","arrow.l"],["leftthreetimes","times.three.l"],["leftrightarrow","arrow.l.r"],["leq","lt.eq"],["leqslant","lt.eq.slant"],["lhd","triangle.l"],["ll","lt.double"],["longmapsto","arrow.bar.long"],["longrightarrow","arrow.long"],["lor","or"],["ltimes","times.l"],["mapsto","arrow.bar"],["measuredangle","angle.arc"],["mid","divides"],["models","models"],["mp","minus.plus"],["mu","mu"],["nRightarrow","arrow.double.not"],["nabla","nabla"],["ncong","tilde.nequiv"],["ne","eq.not"],["neg","not"],["neq","eq.not"],["nexists","exists.not"],["ni","in.rev"],["nleftarrow","arrow.l.not"],["nleq","lt.eq.not"],["nparallel","parallel.not"],["ngeq","gt.eq.not"],["nmid","divides.not"],["notin","in.not"],["nrightarrow","arrow.not"],["nsim","tilde.not"],["nsubseteq","subset.eq.not"],["nu","nu"],["ntriangleleft","lt.tri.not"],["ntriangleright","gt.tri.not"],["nwarrow","arrow.tl"],["odot","dot.circle"],["oint","integral.cont"],["oiint","integral.surf"],["oiiint","integral.vol"],["omega","omega"],["ominus","minus.circle"],["oplus","xor"],["otimes","times.circle"],["parallel","parallel"],["partial","diff"],["perp","perp"],["phi","phi.alt"],["pi","pi"],["pm","plus.minus"],["pounds","pound"],["prec","prec"],["preceq","prec.eq"],["prime","prime"],["prod","product"],["propto","prop"],["psi","psi"],["rangle","angle.r"],["rbrace","brace.r"],["rbrack","bracket.r"],["rhd","triangle"],["rho","rho"],["rightarrow","arrow.r"],["rightthreetimes","times.three.r"],["rtimes","times.r"],["setminus","without"],["sigma","sigma"],["sim","tilde"],["simeq","tilde.eq"],["slash","slash"],["smallsetminus","without"],["spadesuit","suit.spade"],["sqcap","sect.sq"],["sqcup","union.sq"],["sqsubseteq","subset.eq.sq"],["sqsupseteq","supset.eq.sq"],["star","star"],["subset","subset"],["subseteq","subset.eq"],["subsetneq","subset.neq"],["succ","succ"],["succeq","succ.eq"],["sum","sum"],["supset","supset"],["supseteq","supset.eq"],["supsetneq","supset.neq"],["swarrow","arrow.bl"],["tau","tau"],["theta","theta"],["times","times"],["to","arrow.r"],["top","top"],["triangle","triangle.t"],["triangledown","triangle.b.small"],["triangleleft","triangle.l.small"],["triangleright","triangle.r.small"],["twoheadrightarrow","arrow.r.twohead"],["uparrow","arrow.t"],["updownarrow","arrow.t.b"],["upharpoonright","harpoon.tr"],["uplus","union.plus"],["upsilon","upsilon"],["varepsilon","epsilon"],["varnothing","diameter"],["varphi","phi"],["varpi","pi.alt"],["varrho","rho.alt"],["varsigma","sigma.alt"],["vartheta","theta.alt"],["vdash","tack.r"],["vdots","dots.v"],["vee","or"],["wedge","and"],["wr","wreath"],["xi","xi"],["yen","yen"],["zeta","zeta"],["mathscr","scr"],["LaTeX","#LaTeX"],["TeX","#TeX"]]);function F(z,Z=""){if(!z)throw new H(Z)}function l(z){if(x.includes(z))return 1;else if(_.includes(z))return 2;else return 0}function i(z,Z){F(z[Z].eq(D));let J=1,V=Z+1;while(J>0){if(V>=z.length)throw new H("Unmatched curly brackets");if(z[V].eq(D))J+=1;else if(z[V].eq(v))J-=1;V+=1}return V-1}function T(z,Z){F(z[Z].eq(I));let J=1,V=Z+1;while(J>0){if(V>=z.length)throw new H("Unmatched square brackets");if(z[V].eq(I))J+=1;else if(z[V].eq(d))J-=1;V+=1}return V-1}function P(z){return"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".includes(z)}function g(z){return"0123456789".includes(z)}function A(z,Z){let J=Z;while(J<z.length&&[4,5].includes(z[J].type))J++;return z.slice(Z,J)}function C(z,Z){const J=z[Z];if(J.type===0&&["(",")","[","]","|","\\{","\\}"].includes(J.value))return J;else if(J.type===1&&["lfloor","rfloor","lceil","rceil","langle","rangle"].includes(J.value.slice(1)))return J;else return null}function U(z,Z){let J=Z;while(J<z.length&&z[J].eq(new j(0,"'")))J+=1;return J-Z}function p(z,Z){let J=Z;while(J<z.length&&P(z[J]))J+=1;return z.substring(Z,J)}function a(z,Z){let J=1,V=Z;while(J>0){if(V>=z.length)return-1;if(z[V].eq(f))J+=1;else if(z[V].eq(k))J-=1;V+=1}return V-1}function n(z,Z){let J=1,V=Z;while(J>0){if(V>=z.length)return-1;if(z[V].eq(B))J+=1;else if(z[V].eq(r))J-=1;V+=1}return V-1}function t(z,Z){F(z[Z]==="{");let J=1,V=Z+1;while(J>0){if(V>=z.length)throw new H("Unmatched curly brackets");if(V+1<z.length&&["\\{","\\}"].includes(z.substring(V,V+2))){V+=2;continue}if(z[V]==="{")J+=1;else if(z[V]==="}")J-=1;V+=1}return V-1}function L(z){const Z=[];let J=0;while(J<z.length){const V=z[J];let X;switch(V){case"%":{let $=J+1;while($<z.length&&z[$]!=="\n")$+=1;X=new j(3,z.slice(J+1,$)),J=$;break}case"{":case"}":case"_":case"^":case"&":X=new j(6,V),J++;break;case"\n":X=new j(5,V),J++;break;case"\r":{if(J+1<z.length&&z[J+1]==="\n")X=new j(5,"\n"),J+=2;else X=new j(5,"\n"),J++;break}case" ":{let $=J;while($<z.length&&z[$]===" ")$+=1;X=new j(4,z.slice(J,$)),J=$;break}case"\\":{if(J+1>=z.length)throw new H("Expecting command name after \\");const $=z.slice(J,J+2);if(["\\\\","\\,"].includes($))X=new j(6,$);else if(["\\{","\\}","\\%","\\$","\\&","\\#","\\_"].includes($))X=new j(0,$);else{const q=p(z,J+1);X=new j(1,"\\"+q)}J+=X.value.length;break}default:{if(g(V)){let $=J;while($<z.length&&g(z[$]))$+=1;X=new j(0,z.slice(J,$))}else if(P(V))X=new j(0,V);else if("+-*/=\'<>!.,;?()[]|".includes(V))X=new j(0,V);else X=new j(7,V);J+=X.value.length}}if(Z.push(X),X.type===1&&["\\text","\\operatorname","\\begin","\\end"].includes(X.value)){if(J>=z.length||z[J]!=="{")throw new H(`No content for ${X.value} command`);Z.push(new j(6,"{"));const $=t(z,J);J++;let q=z.slice(J,$);const Q=["{","}","\\","$","&","#","_","%"];for(let W of Q)q=q.replaceAll("\\"+W,W);Z.push(new j(2,q)),Z.push(new j(6,"}")),J=$+1}}return Z}function s(z){const Z=(V)=>V.eq(M)||V.eq(h);let J=[];for(let V=0;V<z.length;V++){if(z[V].type===4&&V+1<z.length&&Z(z[V+1]))continue;if(z[V].type===4&&V-1>=0&&Z(z[V-1]))continue;J.push(z[V])}return J}function o(z,Z){let J=[];for(let V of z)if(V.type===1&&Z[V.value]){const X=L(Z[V.value]);J=J.concat(X)}else J.push(V);return J}function u(z,Z){const J=new y;let V=L(z);return V=s(V),V=o(V,Z),J.parse(V)}var x=["sqrt","text","bar","bold","boldsymbol","ddot","dot","hat","mathbb","mathbf","mathcal","mathfrak","mathit","mathrm","mathscr","mathsf","mathtt","operatorname","overbrace","overline","pmb","rm","tilde","underbrace","underline","vec","widehat","widetilde"],_=["frac","tfrac","binom","dbinom","dfrac","tbinom"];class j{type;value;constructor(z,Z){this.type=z,this.value=Z}eq(z){return this.type===z.type&&this.value===z.value}}var N={type:"empty",content:""},D=new j(6,"{"),v=new j(6,"}"),I=new j(0,"["),d=new j(0,"]"),f=new j(1,"\\left"),k=new j(1,"\\right"),B=new j(1,"\\begin"),r=new j(1,"\\end");class H extends Error{constructor(z){super(z);this.name="LatexParserError"}}var M=new j(6,"_"),h=new j(6,"^");class y{space_sensitive;newline_sensitive;constructor(z=!1,Z=!0){this.space_sensitive=z,this.newline_sensitive=Z}parse(z){const Z=[];let J=0;while(J<z.length){const V=[];let X=0;while(X<z.length){const[$,q]=this.parseNextExpr(z,X);if(X=q,!this.space_sensitive&&$.type==="whitespace")continue;if(!this.newline_sensitive&&$.type==="newline")continue;if($.type==="control"&&$.content==="&")throw new H("Unexpected & outside of an alignment");V.push($)}if(V.length===0)return N;else if(V.length===1)return V[0];else return{type:"ordgroup",content:"",args:V}}if(Z.length===0)return N;else if(Z.length===1)return Z[0];else return{type:"ordgroup",content:"",args:Z}}parseNextExpr(z,Z){let[J,V]=this.parseNextExprWithoutSupSub(z,Z),X=null,$=null,q=0;if(q+=U(z,V),V+=q,V<z.length&&z[V].eq(M)){if([X,V]=this.parseNextExprWithoutSupSub(z,V+1),q+=U(z,V),V+=q,V<z.length&&z[V].eq(h)){if([$,V]=this.parseNextExprWithoutSupSub(z,V+1),U(z,V)>0)throw new H("Double superscript")}}else if(V<z.length&&z[V].eq(h)){if([$,V]=this.parseNextExprWithoutSupSub(z,V+1),U(z,V)>0)throw new H("Double superscript");if(V<z.length&&z[V].eq(M)){if([X,V]=this.parseNextExprWithoutSupSub(z,V+1),U(z,V)>0)throw new H("Double superscript")}}if(X!==null||$!==null||q>0){const Q={base:J};if(X)Q.sub=X;if(q>0){Q.sup={type:"ordgroup",content:"",args:[]};for(let W=0;W<q;W++)Q.sup.args.push({type:"element",content:"'"});if($)Q.sup.args.push($);if(Q.sup.args.length===1)Q.sup=Q.sup.args[0]}else if($)Q.sup=$;return[{type:"supsub",content:"",data:Q},V]}else return[J,V]}parseNextExprWithoutSupSub(z,Z){const J=z[Z];switch(J.type){case 0:return[{type:"element",content:J.value},Z+1];case 2:return[{type:"text",content:J.value},Z+1];case 3:return[{type:"comment",content:J.value},Z+1];case 4:return[{type:"whitespace",content:J.value},Z+1];case 5:return[{type:"newline",content:J.value},Z+1];case 1:if(J.eq(B))return this.parseBeginEndExpr(z,Z);else if(J.eq(f))return this.parseLeftRightExpr(z,Z);else return this.parseCommandExpr(z,Z);case 6:switch(J.value){case"{":const $=i(z,Z),q=z.slice(Z+1,$);return[this.parse(q),$+1];case"}":throw new H("Unmatched '}'");case"\\\\":return[{type:"control",content:"\\\\"},Z+1];case"\\,":return[{type:"control",content:"\\,"},Z+1];case"_":return[N,Z];case"^":return[N,Z];case"&":return[{type:"control",content:"&"},Z+1];default:throw new H("Unknown control sequence")}default:throw new H("Unknown token type")}}parseCommandExpr(z,Z){F(z[Z].type===1);const J=z[Z].value;let V=Z+1;if(["left","right","begin","end"].includes(J.slice(1)))throw new H("Unexpected command: "+J);switch(l(J.slice(1))){case 0:if(!O.has(J.slice(1)))return[{type:"unknownMacro",content:J},V];return[{type:"symbol",content:J},V];case 1:{if(J==="\\sqrt"&&V<z.length&&z[V].eq(I)){const Q=V,W=T(z,V),S=z.slice(Q+1,W),R=this.parse(S),[w,c]=this.parseNextExprWithoutSupSub(z,W+1);return[{type:"unaryFunc",content:J,args:[w],data:R},c]}else if(J==="\\text"){if(V+2>=z.length)throw new H("Expecting content for \\text command");return F(z[V].eq(D)),F(z[V+1].type===2),F(z[V+2].eq(v)),[{type:"text",content:z[V+1].value},V+3]}let[$,q]=this.parseNextExprWithoutSupSub(z,V);return[{type:"unaryFunc",content:J,args:[$]},q]}case 2:{const[$,q]=this.parseNextExprWithoutSupSub(z,V),[Q,W]=this.parseNextExprWithoutSupSub(z,q);return[{type:"binaryFunc",content:J,args:[$,Q]},W]}default:throw new Error("Invalid number of parameters")}}parseLeftRightExpr(z,Z){F(z[Z].eq(f));let J=Z+1;if(J+=A(z,J).length,J>=z.length)throw new H("Expecting delimiter after \\left");const V=C(z,J);if(V===null)throw new H("Invalid delimiter after \\left");J++;const X=J,$=a(z,J);if($===-1)throw new H("No matching \\right");const q=$;if(J=$+1,J+=A(z,J).length,J>=z.length)throw new H("Expecting \\right after \\left");const Q=C(z,J);if(Q===null)throw new H("Invalid delimiter after \\right");J++;const W=z.slice(X,q),S=this.parse(W);return[{type:"leftright",content:"",args:[{type:"element",content:V.value},S,{type:"element",content:Q.value}]},J]}parseBeginEndExpr(z,Z){F(z[Z].eq(B));let J=Z+1;F(z[J].eq(D)),F(z[J+1].type===2),F(z[J+2].eq(v));const V=z[J+1].value;J+=3,J+=A(z,J).length;const X=J,$=n(z,J);if($===-1)throw new H("No matching \\end");const q=$;if(J=$+1,F(z[J].eq(D)),F(z[J+1].type===2),F(z[J+2].eq(v)),z[J+1].value!==V)throw new H("Mismatched \\begin and \\end environments");J+=3;const Q=z.slice(X,q);while(Q.length>0&&[4,5].includes(Q[Q.length-1].type))Q.pop();const W=this.parseAligned(Q);return[{type:"beginend",content:V,data:W},J]}parseAligned(z){let Z=0;const J=[];let V=[];J.push(V);let X={type:"ordgroup",content:"",args:[]};V.push(X);while(Z<z.length){const[$,q]=this.parseNextExpr(z,Z);if(Z=q,$.type==="whitespace")continue;else if($.type==="newline"&&!this.newline_sensitive)continue;else if($.type==="control"&&$.content==="\\\\")V=[],X={type:"ordgroup",content:"",args:[]},V.push(X),J.push(V);else if($.type==="control"&&$.content==="&")X={type:"ordgroup",content:"",args:[]},V.push(X);else X.args.push($)}return J}}function m(z){return z.type==="atom"&&["(",")","[","]","{","}","|","\u230A","\u230B","\u2308","\u2309"].includes(z.content)}function G(z){switch(z.type){case"empty":case"whitespace":return{type:"empty",content:""};case"ordgroup":return{type:"group",content:"",args:z.args.map(G)};case"element":return{type:"atom",content:Y(z.content)};case"symbol":return{type:"symbol",content:Y(z.content)};case"text":return{type:"text",content:z.content};case"comment":return{type:"comment",content:z.content};case"supsub":{let{base:Z,sup:J,sub:V}=z.data;if(Z&&Z.type==="unaryFunc"&&Z.content==="\\overbrace"&&J)return{type:"binaryFunc",content:"overbrace",args:[G(Z.args[0]),G(J)]};else if(Z&&Z.type==="unaryFunc"&&Z.content==="\\underbrace"&&V)return{type:"binaryFunc",content:"underbrace",args:[G(Z.args[0]),G(V)]};const X={base:G(Z)};if(X.base.type==="empty")X.base={type:"text",content:""};if(J)X.sup=G(J);if(V)X.sub=G(V);return{type:"supsub",content:"",data:X}}case"leftright":{const[Z,J,V]=z.args,X={type:"group",content:"",args:z.args.map(G)};if(["[]","()","\\{\\}","\\lfloor\\rfloor","\\lceil\\rceil","\\lfloor\\rceil"].includes(Z.content+V.content))return X;return{type:"unaryFunc",content:"lr",args:[X]}}case"binaryFunc":return{type:"binaryFunc",content:Y(z.content),args:z.args.map(G)};case"unaryFunc":{const Z=G(z.args[0]);if(z.content==="\\sqrt"&&z.data)return{type:"binaryFunc",content:"root",args:[G(z.data),Z]};if(z.content==="\\mathbf")return{type:"unaryFunc",content:"upright",args:[{type:"unaryFunc",content:"bold",args:[Z]}]};if(z.content==="\\mathbb"&&Z.type==="atom"&&/^[A-Z]$/.test(Z.content))return{type:"symbol",content:Z.content+Z.content};if(z.content==="\\operatorname"){const J=z.args;if(J.length!==1||J[0].type!=="text")throw new K("Expecting body of \\operatorname to be text but got",z);const V=J[0].content;if(e.includes(V))return{type:"symbol",content:V};else return{type:"unaryFunc",content:"op",args:[{type:"text",content:V}]}}return{type:"unaryFunc",content:Y(z.content),args:z.args.map(G)}}case"newline":return{type:"newline",content:"\n"};case"beginend":{const J=z.data.map((V)=>V.map(G));if(z.content.startsWith("align"))return{type:"align",content:"",data:J};else return{type:"matrix",content:"mat",data:J}}case"unknownMacro":return{type:"unknown",content:Y(z.content)};case"control":if(z.content==="\\\\")return{type:"symbol",content:"\\"};else if(z.content==="\\,")return{type:"symbol",content:"thin"};else throw new K(`Unknown control sequence: ${z.content}`,z);default:throw new K(`Unimplemented node type: ${z.type}`,z)}}function Y(z){if(/^[a-zA-Z0-9]$/.test(z))return z;else if(z==="\\\\")return"\\";else if(z=="/")return"\\/";else if(["\\$","\\#","\\&","\\_"].includes(z))return z;else if(z.startsWith("\\")){const Z=z.slice(1);if(O.has(Z))return O.get(Z);else return Z}return z}var e=["dim","id","im","mod","Pr","sech","csch"];class K extends Error{node;constructor(z,Z){super(z);this.name="TypstWriterError",this.node=Z}}class b{nonStrict;preferTypstIntrinsic;buffer="";queue=[];needSpaceAfterSingleItemScript=!1;insideFunctionDepth=0;constructor(z,Z){this.nonStrict=z,this.preferTypstIntrinsic=Z}writeBuffer(z){if(this.needSpaceAfterSingleItemScript&&/^[0-9a-zA-Z\(]/.test(z))this.buffer+=" ";else{let Z=!1;if(Z||=/[\(\|]$/.test(this.buffer)&&/^\w/.test(z),Z||=/^[}()_^,;!\|]$/.test(z),Z||=z==="'",Z||=/[0-9]$/.test(this.buffer)&&/^[0-9]/.test(z),Z||=/[\(\[{]\s*(-|\+)$/.test(this.buffer)||this.buffer==="-"||this.buffer==="+",Z||=z.startsWith("\n"),Z||=this.buffer==="",Z||=/[\s_^{\(]$/.test(this.buffer),!Z)this.buffer+=" "}if(this.needSpaceAfterSingleItemScript)this.needSpaceAfterSingleItemScript=!1;this.buffer+=z}append(z){switch(z.type){case"empty":break;case"atom":{if(z.content===","&&this.insideFunctionDepth>0)this.queue.push({type:"symbol",content:"comma"});else this.queue.push({type:"atom",content:z.content});break}case"symbol":case"text":case"comment":case"newline":this.queue.push(z);break;case"group":for(let Z of z.args)this.append(Z);break;case"supsub":{let{base:Z,sup:J,sub:V}=z.data;this.appendWithBracketsIfNeeded(Z);let X=!1;const $=J&&J.type==="atom"&&J.content==="\'";if($)this.queue.push({type:"atom",content:"\'"}),X=!1;if(V)this.queue.push({type:"atom",content:"_"}),X=this.appendWithBracketsIfNeeded(V);if(J&&!$)this.queue.push({type:"atom",content:"^"}),X=this.appendWithBracketsIfNeeded(J);if(X)this.queue.push({type:"softSpace",content:""});break}case"binaryFunc":{const Z={type:"symbol",content:z.content},[J,V]=z.args;this.queue.push(Z),this.insideFunctionDepth++,this.queue.push({type:"atom",content:"("}),this.append(J),this.queue.push({type:"atom",content:","}),this.append(V),this.queue.push({type:"atom",content:")"}),this.insideFunctionDepth--;break}case"unaryFunc":{const Z={type:"symbol",content:z.content},J=z.args[0];this.queue.push(Z),this.insideFunctionDepth++,this.queue.push({type:"atom",content:"("}),this.append(J),this.queue.push({type:"atom",content:")"}),this.insideFunctionDepth--;break}case"align":{const Z=z.data;Z.forEach((J,V)=>{if(J.forEach((X,$)=>{if($>0)this.queue.push({type:"atom",content:"&"});this.append(X)}),V<Z.length-1)this.queue.push({type:"symbol",content:"\\"})});break}case"matrix":{const Z=z.data;this.queue.push({type:"symbol",content:"mat"}),this.insideFunctionDepth++,this.queue.push({type:"atom",content:"("}),this.queue.push({type:"symbol",content:"delim: #none, "}),Z.forEach((J,V)=>{J.forEach((X,$)=>{if(this.append(X),$<J.length-1)this.queue.push({type:"atom",content:","});else if(V<Z.length-1)this.queue.push({type:"atom",content:";"})})}),this.queue.push({type:"atom",content:")"}),this.insideFunctionDepth--;break}case"unknown":{if(this.nonStrict)this.queue.push({type:"symbol",content:z.content});else throw new K(`Unknown macro: ${z.content}`,z);break}default:throw new K(`Unimplemented node type to append: ${z.type}`,z)}}appendWithBracketsIfNeeded(z){let Z=["group","supsub","empty"].includes(z.type);if(z.type==="group"){const J=z.args[0],V=z.args[z.args.length-1];if(m(J)&&m(V))Z=!1}if(Z)this.queue.push({type:"atom",content:"("}),this.append(z),this.queue.push({type:"atom",content:")"});else this.append(z);return!Z}flushQueue(){this.queue.forEach((z)=>{let Z="";switch(z.type){case"atom":case"symbol":Z=z.content;break;case"text":Z=`"${z.content}"`;break;case"softSpace":this.needSpaceAfterSingleItemScript=!0,Z="";break;case"comment":Z=`//${z.content}`;break;case"newline":Z="\n";break;default:throw new K(`Unexpected node type to stringify: ${z.type}`,z)}if(Z!=="")this.writeBuffer(Z)}),this.queue=[]}finalize(){this.flushQueue();const V=[function(X){let $=X.replace(/⌊\s*(.*?)\s*⌋/g,"floor($1)");return $=$.replace(/floor\(\)/g,'floor("")'),$},function(X){let $=X.replace(/⌈\s*(.*?)\s*⌉/g,"ceil($1)");return $=$.replace(/ceil\(\)/g,'ceil("")'),$},function(X){let $=X.replace(/⌊\s*(.*?)\s*⌉/g,"round($1)");return $=$.replace(/round\(\)/g,'round("")'),$}];for(let X of V)this.buffer=X(this.buffer);return this.buffer}}function E(z,Z){const J={nonStrict:!0,preferTypstIntrinsic:!0,customTexMacros:{}};if(Z){if(Z.nonStrict)J.nonStrict=Z.nonStrict;if(Z.preferTypstIntrinsic)J.preferTypstIntrinsic=Z.preferTypstIntrinsic;if(Z.customTexMacros)J.customTexMacros=Z.customTexMacros}const V=u(z,J.customTexMacros),X=G(V),$=new b(J.nonStrict,J.preferTypstIntrinsic);return $.append(X),$.finalize()}if(typeof window!=="undefined")window.tex2typst=E;
|