tex2typst 0.5.7 → 0.6.1
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/bun.lock +282 -0
- package/dist/index.js +163 -31
- package/dist/tex2typst.min.js +11 -11
- package/package.json +1 -1
- package/src/convert.ts +0 -19
- package/src/index.ts +6 -2
- package/src/{jslex.ts → lex.ts} +7 -2
- package/src/map.ts +0 -2
- package/src/tex-semantic-analysis.ts +39 -0
- package/src/tex-tokenizer.ts +2 -2
- package/src/tex-types.ts +44 -0
- package/src/typst-semantic-analyais.ts +38 -0
- package/src/typst-tokenizer.ts +2 -2
- package/src/typst-types.ts +55 -0
- package/dist/parser.js +0 -23
package/dist/index.js
CHANGED
|
@@ -78,6 +78,9 @@ var TexTerminal = class extends TexNode {
|
|
|
78
78
|
throw new Error(`Unknown terminal token type: ${this.head.type}`);
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
+
bottomTopTraversalTransform(operationFn) {
|
|
82
|
+
return operationFn(this);
|
|
83
|
+
}
|
|
81
84
|
};
|
|
82
85
|
var TexText = class extends TexNode {
|
|
83
86
|
constructor(head) {
|
|
@@ -92,8 +95,11 @@ var TexText = class extends TexNode {
|
|
|
92
95
|
new TexToken(1 /* ELEMENT */, "}")
|
|
93
96
|
];
|
|
94
97
|
}
|
|
98
|
+
bottomTopTraversalTransform(operationFn) {
|
|
99
|
+
return operationFn(this);
|
|
100
|
+
}
|
|
95
101
|
};
|
|
96
|
-
var TexGroup = class extends TexNode {
|
|
102
|
+
var TexGroup = class _TexGroup extends TexNode {
|
|
97
103
|
items;
|
|
98
104
|
constructor(items) {
|
|
99
105
|
super("ordgroup", TexToken.EMPTY);
|
|
@@ -102,8 +108,12 @@ var TexGroup = class extends TexNode {
|
|
|
102
108
|
serialize() {
|
|
103
109
|
return this.items.map((n) => n.serialize()).flat();
|
|
104
110
|
}
|
|
111
|
+
bottomTopTraversalTransform(operationFn) {
|
|
112
|
+
const g = new _TexGroup(this.items.map((n) => n.bottomTopTraversalTransform(operationFn)));
|
|
113
|
+
return operationFn(g);
|
|
114
|
+
}
|
|
105
115
|
};
|
|
106
|
-
var TexSupSub = class extends TexNode {
|
|
116
|
+
var TexSupSub = class _TexSupSub extends TexNode {
|
|
107
117
|
base;
|
|
108
118
|
sup;
|
|
109
119
|
sub;
|
|
@@ -148,8 +158,16 @@ var TexSupSub = class extends TexNode {
|
|
|
148
158
|
}
|
|
149
159
|
return tokens;
|
|
150
160
|
}
|
|
161
|
+
bottomTopTraversalTransform(operationFn) {
|
|
162
|
+
const s = new _TexSupSub({
|
|
163
|
+
base: this.base.bottomTopTraversalTransform(operationFn),
|
|
164
|
+
sup: this.sup ? this.sup.bottomTopTraversalTransform(operationFn) : null,
|
|
165
|
+
sub: this.sub ? this.sub.bottomTopTraversalTransform(operationFn) : null
|
|
166
|
+
});
|
|
167
|
+
return operationFn(s);
|
|
168
|
+
}
|
|
151
169
|
};
|
|
152
|
-
var TexFuncCall = class extends TexNode {
|
|
170
|
+
var TexFuncCall = class _TexFuncCall extends TexNode {
|
|
153
171
|
args;
|
|
154
172
|
// For type="sqrt", it's additional argument wrapped square bracket. e.g. 3 in \sqrt[3]{x}
|
|
155
173
|
data;
|
|
@@ -173,8 +191,12 @@ var TexFuncCall = class extends TexNode {
|
|
|
173
191
|
}
|
|
174
192
|
return tokens;
|
|
175
193
|
}
|
|
194
|
+
bottomTopTraversalTransform(operationFn) {
|
|
195
|
+
const f = new _TexFuncCall(this.head, this.args.map((n) => n.bottomTopTraversalTransform(operationFn)), this.data);
|
|
196
|
+
return operationFn(f);
|
|
197
|
+
}
|
|
176
198
|
};
|
|
177
|
-
var TexLeftRight = class extends TexNode {
|
|
199
|
+
var TexLeftRight = class _TexLeftRight extends TexNode {
|
|
178
200
|
body;
|
|
179
201
|
left;
|
|
180
202
|
right;
|
|
@@ -193,8 +215,16 @@ var TexLeftRight = class extends TexNode {
|
|
|
193
215
|
tokens.push(new TexToken(1 /* ELEMENT */, this.right ? this.right.value : "."));
|
|
194
216
|
return tokens;
|
|
195
217
|
}
|
|
218
|
+
bottomTopTraversalTransform(operationFn) {
|
|
219
|
+
const l = new _TexLeftRight({
|
|
220
|
+
body: this.body.bottomTopTraversalTransform(operationFn),
|
|
221
|
+
left: this.left,
|
|
222
|
+
right: this.right
|
|
223
|
+
});
|
|
224
|
+
return operationFn(l);
|
|
225
|
+
}
|
|
196
226
|
};
|
|
197
|
-
var TexBeginEnd = class extends TexNode {
|
|
227
|
+
var TexBeginEnd = class _TexBeginEnd extends TexNode {
|
|
198
228
|
matrix;
|
|
199
229
|
// for environment="array" or "subarray", there's additional data like {c|c} right after \begin{env}
|
|
200
230
|
data;
|
|
@@ -232,6 +262,12 @@ var TexBeginEnd = class extends TexNode {
|
|
|
232
262
|
tokens.push(new TexToken(1 /* ELEMENT */, "}"));
|
|
233
263
|
return tokens;
|
|
234
264
|
}
|
|
265
|
+
bottomTopTraversalTransform(operationFn) {
|
|
266
|
+
const m = this.matrix.map((row) => row.map((cell) => cell.bottomTopTraversalTransform(operationFn)));
|
|
267
|
+
const d = this.data ? this.data.bottomTopTraversalTransform(operationFn) : null;
|
|
268
|
+
const be = new _TexBeginEnd(this.head, m, d);
|
|
269
|
+
return operationFn(be);
|
|
270
|
+
}
|
|
235
271
|
};
|
|
236
272
|
function writeTexTokenBuffer(buffer, token) {
|
|
237
273
|
const str = token.toString();
|
|
@@ -287,7 +323,7 @@ function array_intersperse(array, sep) {
|
|
|
287
323
|
return array.flatMap((x, i) => i !== array.length - 1 ? [x, sep] : [x]);
|
|
288
324
|
}
|
|
289
325
|
|
|
290
|
-
// src/
|
|
326
|
+
// src/lex.ts
|
|
291
327
|
var EOF = {};
|
|
292
328
|
function matchcompare(m1, m2) {
|
|
293
329
|
const m1_len = m1.reMatchArray[0].length;
|
|
@@ -1362,6 +1398,9 @@ var TypstTerminal = class extends TypstNode {
|
|
|
1362
1398
|
}
|
|
1363
1399
|
return [this.head];
|
|
1364
1400
|
}
|
|
1401
|
+
bottomTopTraversalTransform(transform) {
|
|
1402
|
+
return transform(this);
|
|
1403
|
+
}
|
|
1365
1404
|
};
|
|
1366
1405
|
var TypstTokenQueue = class {
|
|
1367
1406
|
queue = [];
|
|
@@ -1397,7 +1436,7 @@ var TypstTokenQueue = class {
|
|
|
1397
1436
|
return res;
|
|
1398
1437
|
}
|
|
1399
1438
|
};
|
|
1400
|
-
var TypstGroup = class extends TypstNode {
|
|
1439
|
+
var TypstGroup = class _TypstGroup extends TypstNode {
|
|
1401
1440
|
items;
|
|
1402
1441
|
constructor(items) {
|
|
1403
1442
|
super("group", TypstToken.NONE);
|
|
@@ -1442,8 +1481,12 @@ var TypstGroup = class extends TypstNode {
|
|
|
1442
1481
|
}
|
|
1443
1482
|
return queue;
|
|
1444
1483
|
}
|
|
1484
|
+
bottomTopTraversalTransform(transform) {
|
|
1485
|
+
const g = new _TypstGroup(this.items.map((n) => n.bottomTopTraversalTransform(transform)));
|
|
1486
|
+
return transform(g);
|
|
1487
|
+
}
|
|
1445
1488
|
};
|
|
1446
|
-
var TypstSupsub = class extends TypstNode {
|
|
1489
|
+
var TypstSupsub = class _TypstSupsub extends TypstNode {
|
|
1447
1490
|
base;
|
|
1448
1491
|
sup;
|
|
1449
1492
|
sub;
|
|
@@ -1480,8 +1523,16 @@ var TypstSupsub = class extends TypstNode {
|
|
|
1480
1523
|
}
|
|
1481
1524
|
return queue;
|
|
1482
1525
|
}
|
|
1526
|
+
bottomTopTraversalTransform(transform) {
|
|
1527
|
+
const s = new _TypstSupsub({
|
|
1528
|
+
base: this.base.bottomTopTraversalTransform(transform),
|
|
1529
|
+
sup: this.sup?.bottomTopTraversalTransform(transform) || null,
|
|
1530
|
+
sub: this.sub?.bottomTopTraversalTransform(transform) || null
|
|
1531
|
+
});
|
|
1532
|
+
return transform(s);
|
|
1533
|
+
}
|
|
1483
1534
|
};
|
|
1484
|
-
var TypstFuncCall = class extends TypstNode {
|
|
1535
|
+
var TypstFuncCall = class _TypstFuncCall extends TypstNode {
|
|
1485
1536
|
args;
|
|
1486
1537
|
constructor(head, args) {
|
|
1487
1538
|
super("funcCall", head);
|
|
@@ -1521,8 +1572,13 @@ var TypstFuncCall = class extends TypstNode {
|
|
|
1521
1572
|
env.insideFunctionDepth--;
|
|
1522
1573
|
return queue;
|
|
1523
1574
|
}
|
|
1575
|
+
bottomTopTraversalTransform(transform) {
|
|
1576
|
+
const f = new _TypstFuncCall(this.head, this.args.map((n) => n.bottomTopTraversalTransform(transform)));
|
|
1577
|
+
f.options = this.options;
|
|
1578
|
+
return transform(f);
|
|
1579
|
+
}
|
|
1524
1580
|
};
|
|
1525
|
-
var TypstFraction = class extends TypstNode {
|
|
1581
|
+
var TypstFraction = class _TypstFraction extends TypstNode {
|
|
1526
1582
|
args;
|
|
1527
1583
|
constructor(args) {
|
|
1528
1584
|
super("fraction", TypstToken.NONE);
|
|
@@ -1545,10 +1601,14 @@ var TypstFraction = class extends TypstNode {
|
|
|
1545
1601
|
queue.push(...denominator.serialize(env, options));
|
|
1546
1602
|
return queue;
|
|
1547
1603
|
}
|
|
1604
|
+
bottomTopTraversalTransform(transform) {
|
|
1605
|
+
const f = new _TypstFraction(this.args.map((n) => n.bottomTopTraversalTransform(transform)));
|
|
1606
|
+
return transform(f);
|
|
1607
|
+
}
|
|
1548
1608
|
};
|
|
1549
1609
|
var TYPST_LEFT_PARENTHESIS = new TypstToken(2 /* ELEMENT */, "(");
|
|
1550
1610
|
var TYPST_RIGHT_PARENTHESIS = new TypstToken(2 /* ELEMENT */, ")");
|
|
1551
|
-
var TypstLeftright = class extends TypstNode {
|
|
1611
|
+
var TypstLeftright = class _TypstLeftright extends TypstNode {
|
|
1552
1612
|
body;
|
|
1553
1613
|
left;
|
|
1554
1614
|
right;
|
|
@@ -1594,6 +1654,14 @@ var TypstLeftright = class extends TypstNode {
|
|
|
1594
1654
|
}
|
|
1595
1655
|
return queue;
|
|
1596
1656
|
}
|
|
1657
|
+
bottomTopTraversalTransform(transform) {
|
|
1658
|
+
const l = new _TypstLeftright(this.head, {
|
|
1659
|
+
body: this.body.bottomTopTraversalTransform(transform),
|
|
1660
|
+
left: this.left,
|
|
1661
|
+
right: this.right
|
|
1662
|
+
});
|
|
1663
|
+
return transform(l);
|
|
1664
|
+
}
|
|
1597
1665
|
};
|
|
1598
1666
|
var TypstMatrixLike = class _TypstMatrixLike extends TypstNode {
|
|
1599
1667
|
matrix;
|
|
@@ -1661,10 +1729,16 @@ var TypstMatrixLike = class _TypstMatrixLike extends TypstNode {
|
|
|
1661
1729
|
}
|
|
1662
1730
|
return queue;
|
|
1663
1731
|
}
|
|
1732
|
+
bottomTopTraversalTransform(transform) {
|
|
1733
|
+
const m = this.matrix.map((row) => row.map((cell) => cell.bottomTopTraversalTransform(transform)));
|
|
1734
|
+
const ml = new _TypstMatrixLike(this.head, m);
|
|
1735
|
+
ml.options = this.options;
|
|
1736
|
+
return transform(ml);
|
|
1737
|
+
}
|
|
1664
1738
|
static MAT = new TypstToken(1 /* SYMBOL */, "mat");
|
|
1665
1739
|
static CASES = new TypstToken(1 /* SYMBOL */, "cases");
|
|
1666
1740
|
};
|
|
1667
|
-
var TypstMarkupFunc = class extends TypstNode {
|
|
1741
|
+
var TypstMarkupFunc = class _TypstMarkupFunc extends TypstNode {
|
|
1668
1742
|
/*
|
|
1669
1743
|
In idealized situations, for `#heading([some text and math $x + y$ example])`,
|
|
1670
1744
|
fragments would be [TypstMarkup{"some text and math "}, TypstNode{"x + y"}, TypstMarkup{" example"}]
|
|
@@ -1711,6 +1785,11 @@ var TypstMarkupFunc = class extends TypstNode {
|
|
|
1711
1785
|
queue.push(new TypstToken(3 /* LITERAL */, "]"));
|
|
1712
1786
|
return queue;
|
|
1713
1787
|
}
|
|
1788
|
+
bottomTopTraversalTransform(transform) {
|
|
1789
|
+
const mf = new _TypstMarkupFunc(this.head, this.fragments.map((n) => n.bottomTopTraversalTransform(transform)));
|
|
1790
|
+
mf.options = this.options;
|
|
1791
|
+
return transform(mf);
|
|
1792
|
+
}
|
|
1714
1793
|
};
|
|
1715
1794
|
|
|
1716
1795
|
// src/typst-writer.ts
|
|
@@ -1830,7 +1909,6 @@ var symbolMap = /* @__PURE__ */ new Map([
|
|
|
1830
1909
|
["neq", "eq.not"],
|
|
1831
1910
|
["dot", "dot"],
|
|
1832
1911
|
["ddot", "dot.double"],
|
|
1833
|
-
["doteq", "dot(eq)"],
|
|
1834
1912
|
["dots", "dots.h"],
|
|
1835
1913
|
["vdots", "dots.v"],
|
|
1836
1914
|
["ddots", "dots.down"],
|
|
@@ -2903,7 +2981,6 @@ var reverseSymbolMap = /* @__PURE__ */ new Map();
|
|
|
2903
2981
|
for (const [key, value] of Array.from(symbolMap.entries()).reverse()) {
|
|
2904
2982
|
reverseSymbolMap.set(value, key);
|
|
2905
2983
|
}
|
|
2906
|
-
reverseSymbolMap.set("oo", "infty");
|
|
2907
2984
|
var typst_to_tex_map = /* @__PURE__ */ new Map([
|
|
2908
2985
|
["top", "top"],
|
|
2909
2986
|
["frac", "frac"],
|
|
@@ -3514,21 +3591,6 @@ function convert_typst_node_to_tex(abstractNode, options) {
|
|
|
3514
3591
|
case "terminal": {
|
|
3515
3592
|
const node = abstractNode;
|
|
3516
3593
|
if (node.head.type === 1 /* SYMBOL */) {
|
|
3517
|
-
if (node.head.value === "eq.def") {
|
|
3518
|
-
return new TexFuncCall(new TexToken(2 /* COMMAND */, "\\overset"), [
|
|
3519
|
-
new TexText(new TexToken(3 /* LITERAL */, "def")),
|
|
3520
|
-
new TexToken(1 /* ELEMENT */, "=").toNode()
|
|
3521
|
-
]);
|
|
3522
|
-
}
|
|
3523
|
-
if (node.head.value === "comma") {
|
|
3524
|
-
return new TexToken(1 /* ELEMENT */, ",").toNode();
|
|
3525
|
-
}
|
|
3526
|
-
if (node.head.value === "dif") {
|
|
3527
|
-
return new TexFuncCall(new TexToken(2 /* COMMAND */, "\\mathrm"), [new TexToken(1 /* ELEMENT */, "d").toNode()]);
|
|
3528
|
-
}
|
|
3529
|
-
if (node.head.value === "hyph" || node.head.value === "hyph.minus") {
|
|
3530
|
-
return new TexText(new TexToken(3 /* LITERAL */, "-"));
|
|
3531
|
-
}
|
|
3532
3594
|
if (/^([A-Z])\1$/.test(node.head.value)) {
|
|
3533
3595
|
return new TexFuncCall(new TexToken(2 /* COMMAND */, "\\mathbb"), [
|
|
3534
3596
|
new TexToken(1 /* ELEMENT */, node.head.value[0]).toNode()
|
|
@@ -4275,6 +4337,74 @@ var TexWriter = class {
|
|
|
4275
4337
|
}
|
|
4276
4338
|
};
|
|
4277
4339
|
|
|
4340
|
+
// src/tex-semantic-analysis.ts
|
|
4341
|
+
var TEX_PREDEFINED_MACROS = /* @__PURE__ */ new Map([
|
|
4342
|
+
// https://github.com/KaTeX/KaTeX/blob/434d4b8aef4c3311ebfd3405a9f0cce18ead953b/src/macros.ts#L351-L367
|
|
4343
|
+
["\\varGamma", "\\mathit{\\Gamma}"],
|
|
4344
|
+
["\\varDelta", "\\mathit{\\Delta}"],
|
|
4345
|
+
["\\varTheta", "\\mathit{\\Theta}"],
|
|
4346
|
+
["\\varLambda", "\\mathit{\\Lambda}"],
|
|
4347
|
+
["\\varXi", "\\mathit{\\Xi}"],
|
|
4348
|
+
["\\varPi", "\\mathit{\\Pi}"],
|
|
4349
|
+
["\\varSigma", "\\mathit{\\Sigma}"],
|
|
4350
|
+
["\\varUpsilon", "\\mathit{\\Upsilon}"],
|
|
4351
|
+
["\\varPhi", "\\mathit{\\Phi}"],
|
|
4352
|
+
["\\varPsi", "\\mathit{\\Psi}"],
|
|
4353
|
+
["\\varOmega", "\\mathit{\\Omega}"],
|
|
4354
|
+
["\\doteq", "\\dot{=}"]
|
|
4355
|
+
]);
|
|
4356
|
+
function _expand_tex_predefined_macros(node) {
|
|
4357
|
+
switch (node.type) {
|
|
4358
|
+
case "terminal": {
|
|
4359
|
+
if (node.head.type === 2 /* COMMAND */) {
|
|
4360
|
+
if (TEX_PREDEFINED_MACROS.has(node.head.value)) {
|
|
4361
|
+
const target_str = TEX_PREDEFINED_MACROS.get(node.head.value);
|
|
4362
|
+
return parseTex(target_str);
|
|
4363
|
+
}
|
|
4364
|
+
}
|
|
4365
|
+
}
|
|
4366
|
+
case "funcCall":
|
|
4367
|
+
default:
|
|
4368
|
+
return node;
|
|
4369
|
+
}
|
|
4370
|
+
}
|
|
4371
|
+
function expand_tex_predefined_macros(node) {
|
|
4372
|
+
return node.bottomTopTraversalTransform(_expand_tex_predefined_macros);
|
|
4373
|
+
}
|
|
4374
|
+
|
|
4375
|
+
// src/typst-semantic-analyais.ts
|
|
4376
|
+
var TEX_PREDEFINED_VARIABLES = /* @__PURE__ */ new Map([
|
|
4377
|
+
["dif", "upright(d)"],
|
|
4378
|
+
["eq.def", 'limits(=)^"def"'],
|
|
4379
|
+
["oo", "infinity"],
|
|
4380
|
+
["comma", ","],
|
|
4381
|
+
["hyph", '"-"'],
|
|
4382
|
+
["hyph.minus", '"-"']
|
|
4383
|
+
/*
|
|
4384
|
+
["AA", "bb(A)"],
|
|
4385
|
+
["BB", "bb(B)"],
|
|
4386
|
+
["CC", "bb(C)"],
|
|
4387
|
+
*/
|
|
4388
|
+
]);
|
|
4389
|
+
function _expand_typst_predefined_variables(node) {
|
|
4390
|
+
switch (node.type) {
|
|
4391
|
+
case "terminal": {
|
|
4392
|
+
if (node.head.type === 1 /* SYMBOL */) {
|
|
4393
|
+
if (TEX_PREDEFINED_VARIABLES.has(node.head.value)) {
|
|
4394
|
+
const target_str = TEX_PREDEFINED_VARIABLES.get(node.head.value);
|
|
4395
|
+
return parseTypst(target_str);
|
|
4396
|
+
}
|
|
4397
|
+
}
|
|
4398
|
+
}
|
|
4399
|
+
case "funcCall":
|
|
4400
|
+
default:
|
|
4401
|
+
return node;
|
|
4402
|
+
}
|
|
4403
|
+
}
|
|
4404
|
+
function expand_typst_predefined_variables(node) {
|
|
4405
|
+
return node.bottomTopTraversalTransform(_expand_typst_predefined_variables);
|
|
4406
|
+
}
|
|
4407
|
+
|
|
4278
4408
|
// src/index.ts
|
|
4279
4409
|
function tex2typst(tex, options = {}) {
|
|
4280
4410
|
const opt = {
|
|
@@ -4295,7 +4425,8 @@ function tex2typst(tex, options = {}) {
|
|
|
4295
4425
|
}
|
|
4296
4426
|
}
|
|
4297
4427
|
const texTree = parseTex(tex, opt.customTexMacros);
|
|
4298
|
-
const
|
|
4428
|
+
const preprocessedTexTree = expand_tex_predefined_macros(texTree);
|
|
4429
|
+
const typstTree = convert_tex_node_to_typst(preprocessedTexTree, opt);
|
|
4299
4430
|
const writer = new TypstWriter(opt);
|
|
4300
4431
|
writer.serialize(typstTree);
|
|
4301
4432
|
return writer.finalize();
|
|
@@ -4313,7 +4444,8 @@ function typst2tex(typst, options = {}) {
|
|
|
4313
4444
|
}
|
|
4314
4445
|
}
|
|
4315
4446
|
const typstTree = parseTypst(typst);
|
|
4316
|
-
const
|
|
4447
|
+
const preprocessedTypstTree = expand_typst_predefined_variables(typstTree);
|
|
4448
|
+
const texTree = convert_typst_node_to_tex(preprocessedTypstTree, opt);
|
|
4317
4449
|
const writer = new TexWriter();
|
|
4318
4450
|
writer.append(texTree);
|
|
4319
4451
|
return writer.finalize();
|