tex2typst 0.0.16 → 0.0.18

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/dist/index.js CHANGED
@@ -1,27 +1,837 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.tex2typst = tex2typst;
4
- const parser_1 = require("./parser");
5
- const writer_1 = require("./writer");
6
- function tex2typst(tex, options) {
7
- const opt = {
8
- nonStrict: false,
9
- preferTypstIntrinsic: true,
10
- customTexMacros: {}
11
- };
12
- if (options) {
13
- if (options.nonStrict) {
14
- opt.nonStrict = options.nonStrict;
1
+ // src/parser.ts
2
+ import katex from "katex";
3
+ function katexNodeToTexNode(node) {
4
+ try {
5
+ if (node.loc) {
6
+ delete node.loc;
7
+ }
8
+ let res = {};
9
+ switch (node.type) {
10
+ case "atom":
11
+ res.type = "atom";
12
+ res.content = node.text;
13
+ if (node.text === "\\{" || node.text === "\\}") {
14
+ res.content = node.text.substring(1);
15
+ } else if (node.text.startsWith("\\")) {
16
+ res.type = "symbol";
17
+ }
18
+ break;
19
+ case "mathord":
20
+ case "textord":
21
+ case "op":
22
+ case "cr":
23
+ res.type = "symbol";
24
+ res.content = node.text;
25
+ if (node.type === "op") {
26
+ res.content = node["name"];
27
+ } else if (node.type === "cr") {
28
+ res.content = "\\\\";
29
+ }
30
+ break;
31
+ case "genfrac":
32
+ res.type = "binaryFunc";
33
+ if (node["leftDelim"] === "(" && node["rightDelim"] === ")") {
34
+ res.content = "\\binom";
35
+ } else {
36
+ res.content = "\\frac";
37
+ }
38
+ res.args = [
39
+ katexNodeToTexNode(node["numer"]),
40
+ katexNodeToTexNode(node["denom"])
41
+ ];
42
+ break;
43
+ case "supsub":
44
+ res.type = "supsub";
45
+ res.irregularData = {};
46
+ if (node["base"]) {
47
+ res.irregularData.base = katexNodeToTexNode(node["base"]);
48
+ }
49
+ if (node["sup"]) {
50
+ res.irregularData.sup = katexNodeToTexNode(node["sup"]);
51
+ }
52
+ if (node["sub"]) {
53
+ res.irregularData.sub = katexNodeToTexNode(node["sub"]);
54
+ }
55
+ break;
56
+ case "mclass":
57
+ case "ordgroup":
58
+ res.type = "ordgroup";
59
+ res.args = node.body.map((n) => katexNodeToTexNode(n));
60
+ if (res.args.length === 1) {
61
+ res = res.args[0];
62
+ }
63
+ break;
64
+ case "leftright": {
65
+ const body = katexNodeToTexNode({
66
+ type: "ordgroup",
67
+ mode: "math",
68
+ body: node.body
69
+ });
70
+ res.type = "leftright";
71
+ let left = node["left"];
72
+ if (left === "\\{") {
73
+ left = "{";
15
74
  }
16
- if (options.preferTypstIntrinsic) {
17
- opt.preferTypstIntrinsic = options.preferTypstIntrinsic;
75
+ let right = node["right"];
76
+ if (right === "\\}") {
77
+ right = "}";
18
78
  }
19
- if (options.customTexMacros) {
20
- opt.customTexMacros = options.customTexMacros;
79
+ const is_atom = (str) => ["(", ")", "[", "]", "{", "}"].includes(str);
80
+ res.args = [
81
+ { type: is_atom(left) ? "atom" : "symbol", content: left },
82
+ body,
83
+ { type: is_atom(right) ? "atom" : "symbol", content: right }
84
+ ];
85
+ break;
86
+ }
87
+ case "underline":
88
+ case "overline":
89
+ res.type = "unaryFunc";
90
+ res.content = "\\" + node.type;
91
+ res.args = [
92
+ katexNodeToTexNode(node["body"])
93
+ ];
94
+ break;
95
+ case "accent": {
96
+ res.type = "unaryFunc";
97
+ res.content = node["label"];
98
+ res.args = [
99
+ katexNodeToTexNode(node["base"])
100
+ ];
101
+ break;
102
+ }
103
+ case "sqrt":
104
+ if (node["index"]) {
105
+ res.irregularData = katexNodeToTexNode(node["index"]);
21
106
  }
107
+ case "font":
108
+ case "operatorname":
109
+ res.type = "unaryFunc";
110
+ res.content = "\\" + node.type;
111
+ if (node.type === "font") {
112
+ res.content = "\\" + node["font"];
113
+ }
114
+ if (Array.isArray(node.body)) {
115
+ const obj = {
116
+ type: "ordgroup",
117
+ mode: "math",
118
+ body: node.body
119
+ };
120
+ res.args = [
121
+ katexNodeToTexNode(obj)
122
+ ];
123
+ } else {
124
+ res.args = [
125
+ katexNodeToTexNode(node.body)
126
+ ];
127
+ }
128
+ break;
129
+ case "horizBrace":
130
+ res.type = "unaryFunc";
131
+ res.content = node["label"];
132
+ res.args = [
133
+ katexNodeToTexNode(node["base"])
134
+ ];
135
+ break;
136
+ case "array":
137
+ if (node["colSeparationType"] === "align") {
138
+ res.type = "align";
139
+ } else {
140
+ res.type = "matrix";
141
+ }
142
+ res.irregularData = node.body.map((row) => {
143
+ return row.map((cell) => {
144
+ if (cell.type !== "styling" || cell.body.length !== 1) {
145
+ throw new KatexNodeToTexNodeError("Expecting cell.type==='\\styling' and cell.body.length===1", cell);
146
+ }
147
+ return katexNodeToTexNode(cell.body[0]);
148
+ });
149
+ });
150
+ break;
151
+ case "text": {
152
+ res.type = "text";
153
+ let str = "";
154
+ node.body.forEach((n) => {
155
+ if (n.mode !== "text") {
156
+ throw new KatexNodeToTexNodeError("Expecting node.mode==='text'", node);
157
+ }
158
+ str += n.text;
159
+ });
160
+ res.content = str;
161
+ break;
162
+ }
163
+ case "spacing":
164
+ case "kern":
165
+ res.type = "empty";
166
+ res.content = " ";
167
+ break;
168
+ case "htmlmathml": {
169
+ const element = node["mathml"][0]["body"][0];
170
+ if (element && element.type === "textord" && element.text === "\u2260") {
171
+ res.type = "symbol";
172
+ res.content = "\\neq";
173
+ break;
174
+ } else {
175
+ }
176
+ }
177
+ case "color":
178
+ if (Array.isArray(node.body) && node.body.length === 1) {
179
+ const sub_body = node.body[0];
180
+ if (sub_body.type === "text") {
181
+ res.type = "unknownMacro";
182
+ const joined = sub_body.body.map((n) => n.text).join("");
183
+ if (/^\\[a-zA-Z]+$/.test(joined)) {
184
+ res.content = joined.substring(1);
185
+ break;
186
+ }
187
+ }
188
+ }
189
+ throw new KatexNodeToTexNodeError(`Unknown error type in parsed result:`, node);
190
+ default:
191
+ throw new KatexNodeToTexNodeError(`Unknown node type: ${node.type}`, node);
192
+ break;
193
+ }
194
+ return res;
195
+ } catch (e) {
196
+ throw e;
197
+ }
198
+ }
199
+ function parseTex(tex, customTexMacros) {
200
+ const macros = {
201
+ "\\mod": "\\operatorname{SyMb01-mod}",
202
+ "\\liminf": "\\operatorname{SyMb01-liminf}",
203
+ "\\limsup": "\\operatorname{SyMb01-limsup}",
204
+ "\\qquad": "\\operatorname{SyMb01-qquad}",
205
+ "\\quad": "\\operatorname{SyMb01-quad}",
206
+ "\\cdots": "\\operatorname{SyMb01-cdots}",
207
+ "\\colon": "\\operatorname{SyMb01-colon}",
208
+ "\\imath": "\\operatorname{SyMb01-imath}",
209
+ "\\iiiint": "\\operatorname{SyMb01-iiiint}",
210
+ "\\jmath": "\\operatorname{SyMb01-jmath}",
211
+ "\\vdots": "\\operatorname{SyMb01-vdots}",
212
+ "\\notin": "\\operatorname{SyMb01-notin}",
213
+ "\\slash": "\\operatorname{SyMb01-slash}",
214
+ "\\LaTeX": "\\operatorname{SyMb01-LaTeX}",
215
+ "\\TeX": "\\operatorname{SyMb01-TeX}",
216
+ ...customTexMacros
217
+ };
218
+ const options = {
219
+ macros,
220
+ displayMode: true,
221
+ strict: "ignore",
222
+ throwOnError: false
223
+ };
224
+ let treeArray = generateParseTree(tex, options);
225
+ let t = {
226
+ type: "ordgroup",
227
+ mode: "math",
228
+ body: treeArray,
229
+ loc: {}
230
+ };
231
+ return katexNodeToTexNode(t);
232
+ }
233
+ var generateParseTree = katex.__parse;
234
+
235
+ class KatexNodeToTexNodeError extends Error {
236
+ node;
237
+ constructor(message, node) {
238
+ super(message);
239
+ this.name = "KatexNodeToTexNodeError";
240
+ this.node = node;
241
+ }
242
+ }
243
+
244
+ // src/map.ts
245
+ var symbolMap = new Map([
246
+ ["gets", "arrow.l"],
247
+ ["nonumber", ""],
248
+ ["vec", "arrow"],
249
+ ["mathbf", "bold"],
250
+ ["boldsymbol", "bold"],
251
+ ["mathfrak", "frak"],
252
+ ["neq", "eq.not"],
253
+ ["dot", "dot"],
254
+ ["ddot", "dot.double"],
255
+ ["doteq", "dot(eq)"],
256
+ ["dots", "dots.h"],
257
+ ["ldots", "dots.h"],
258
+ ["vdots", "dots.v"],
259
+ ["ddots", "dots.down"],
260
+ ["widehat", "hat"],
261
+ ["widetilde", "tilde"],
262
+ ["quad", "quad"],
263
+ ["qquad", "wide"],
264
+ ["overbrace", "overbrace"],
265
+ ["underbrace", "underbrace"],
266
+ ["overline", "overline"],
267
+ ["underline", "underline"],
268
+ ["bar", "macron"],
269
+ ["mathbb", "bb"],
270
+ ["mathcal", "cal"],
271
+ ["mathrm", "upright"],
272
+ ["rm", "upright"],
273
+ ["pmb", "bold"],
274
+ ["pm", "plus.minus"],
275
+ ["mp", "minus.plus"],
276
+ ["oplus", "xor"],
277
+ ["boxplus", "plus.square"],
278
+ ["otimes", "times.circle"],
279
+ ["boxtimes", "times.square"],
280
+ ["sim", "tilde"],
281
+ ["approx", "approx"],
282
+ ["cong", "tilde.equiv"],
283
+ ["simeq", "tilde.eq"],
284
+ ["asymp", "\u224D"],
285
+ ["equiv", "equiv"],
286
+ ["propto", "prop"],
287
+ ["implies", "arrow.r.double.long"],
288
+ ["Longrightarrow", "arrow.r.double.long"],
289
+ ["iff", "arrow.l.r.double.long"],
290
+ ["Longleftrightarrow", "arrow.l.r.double.long"],
291
+ ["leftrightarrow", "arrow.l.r"],
292
+ ["longleftrightarrow", "arrow.l.r.long"],
293
+ ["rightrightarrows", "arrows.rr"],
294
+ ["lfloor", "\u230A"],
295
+ ["rfloor", "\u230B"],
296
+ ["lceil", "\u2308"],
297
+ ["rceil", "\u2309"],
298
+ ["Cap", "sect.double"],
299
+ ["Cup", "union.double"],
300
+ ["Delta", "Delta"],
301
+ ["Gamma", "Gamma"],
302
+ ["Join", "join"],
303
+ ["Lambda", "Lambda"],
304
+ ["Longrightarrow", "arrow.r.double.long"],
305
+ ["Omega", "Omega"],
306
+ ["Phi", "Phi"],
307
+ ["Pi", "Pi"],
308
+ ["Psi", "Psi"],
309
+ ["Rightarrow", "arrow.double"],
310
+ ["Sigma", "Sigma"],
311
+ ["Theta", "Theta"],
312
+ ["aleph", "alef"],
313
+ ["alpha", "alpha"],
314
+ ["angle", "angle"],
315
+ ["approx", "approx"],
316
+ ["approxeq", "approx.eq"],
317
+ ["ast", "ast"],
318
+ ["beta", "beta"],
319
+ ["bigcap", "sect.big"],
320
+ ["bigcirc", "circle.big"],
321
+ ["bigcup", "union.big"],
322
+ ["bigodot", "dot.circle.big"],
323
+ ["bigoplus", "xor.big"],
324
+ ["bigotimes", "times.circle.big"],
325
+ ["bigsqcup", "union.sq.big"],
326
+ ["bigtriangledown", "triangle.b"],
327
+ ["bigtriangleup", "triangle.t"],
328
+ ["biguplus", "union.plus.big"],
329
+ ["bigvee", "or.big"],
330
+ ["bigwedge", "and.big"],
331
+ ["bullet", "bullet"],
332
+ ["cap", "sect"],
333
+ ["cdot", "dot.op"],
334
+ ["cdots", "dots.c"],
335
+ ["checkmark", "checkmark"],
336
+ ["chi", "chi"],
337
+ ["circ", "circle.small"],
338
+ ["colon", "colon"],
339
+ ["cong", "tilde.equiv"],
340
+ ["coprod", "product.co"],
341
+ ["cup", "union"],
342
+ ["curlyvee", "or.curly"],
343
+ ["curlywedge", "and.curly"],
344
+ ["dagger", "dagger"],
345
+ ["dashv", "tack.l"],
346
+ ["ddagger", "dagger.double"],
347
+ ["delta", "delta"],
348
+ ["ddots", "dots.down"],
349
+ ["diamond", "diamond"],
350
+ ["div", "div"],
351
+ ["divideontimes", "times.div"],
352
+ ["dotplus", "plus.dot"],
353
+ ["downarrow", "arrow.b"],
354
+ ["ell", "ell"],
355
+ ["emptyset", "nothing"],
356
+ ["epsilon", "epsilon.alt"],
357
+ ["equiv", "equiv"],
358
+ ["eta", "eta"],
359
+ ["exists", "exists"],
360
+ ["forall", "forall"],
361
+ ["gamma", "gamma"],
362
+ ["ge", "gt.eq"],
363
+ ["geq", "gt.eq"],
364
+ ["geqslant", "gt.eq.slant"],
365
+ ["gg", "gt.double"],
366
+ ["hbar", "planck.reduce"],
367
+ ["imath", "dotless.i"],
368
+ ["iiiint", "intgral.quad"],
369
+ ["iiint", "integral.triple"],
370
+ ["iint", "integral.double"],
371
+ ["in", "in"],
372
+ ["infty", "infinity"],
373
+ ["int", "integral"],
374
+ ["intercal", "top"],
375
+ ["iota", "iota"],
376
+ ["jmath", "dotless.j"],
377
+ ["kappa", "kappa"],
378
+ ["lambda", "lambda"],
379
+ ["land", "and"],
380
+ ["langle", "angle.l"],
381
+ ["lbrace", "brace.l"],
382
+ ["lbrack", "bracket.l"],
383
+ ["ldots", "dots.l"],
384
+ ["le", "lt.eq"],
385
+ ["leadsto", "arrow.squiggly"],
386
+ ["leftarrow", "arrow.l"],
387
+ ["leftthreetimes", "times.three.l"],
388
+ ["leftrightarrow", "arrow.l.r"],
389
+ ["leq", "lt.eq"],
390
+ ["leqslant", "lt.eq.slant"],
391
+ ["lhd", "triangle.l"],
392
+ ["ll", "lt.double"],
393
+ ["longmapsto", "arrow.long.bar"],
394
+ ["longrightarrow", "arrow.long"],
395
+ ["lor", "or"],
396
+ ["ltimes", "times.l"],
397
+ ["mapsto", "arrow.bar"],
398
+ ["measuredangle", "angle.arc"],
399
+ ["mid", "divides"],
400
+ ["models", "models"],
401
+ ["mp", "minus.plus"],
402
+ ["mu", "mu"],
403
+ ["nRightarrow", "arrow.double.not"],
404
+ ["nabla", "nabla"],
405
+ ["ncong", "tilde.nequiv"],
406
+ ["ne", "eq.not"],
407
+ ["neg", "not"],
408
+ ["neq", "eq.not"],
409
+ ["nexists", "exists.not"],
410
+ ["ni", "in.rev"],
411
+ ["nleftarrow", "arrow.l.not"],
412
+ ["nleq", "lt.eq.not"],
413
+ ["nparallel", "parallel.not"],
414
+ ["ngeq", "gt.eq.not"],
415
+ ["nmid", "divides.not"],
416
+ ["notin", "in.not"],
417
+ ["nrightarrow", "arrow.not"],
418
+ ["nsim", "tilde.not"],
419
+ ["nsubseteq", "subset.eq.not"],
420
+ ["nu", "nu"],
421
+ ["ntriangleleft", "lt.tri.not"],
422
+ ["ntriangleright", "gt.tri.not"],
423
+ ["nwarrow", "arrow.tl"],
424
+ ["odot", "dot.circle"],
425
+ ["oint", "integral.cont"],
426
+ ["oiint", "integral.surf"],
427
+ ["oiiint", "integral.vol"],
428
+ ["omega", "omega"],
429
+ ["ominus", "minus.circle"],
430
+ ["oplus", "xor"],
431
+ ["otimes", "times.circle"],
432
+ ["parallel", "parallel"],
433
+ ["partial", "diff"],
434
+ ["perp", "perp"],
435
+ ["phi", "phi.alt"],
436
+ ["pi", "pi"],
437
+ ["pm", "plus.minus"],
438
+ ["pounds", "pound"],
439
+ ["prec", "prec"],
440
+ ["preceq", "prec.eq"],
441
+ ["prime", "prime"],
442
+ ["prod", "product"],
443
+ ["propto", "prop"],
444
+ ["psi", "psi"],
445
+ ["rangle", "angle.r"],
446
+ ["rbrace", "brace.r"],
447
+ ["rbrack", "bracket.r"],
448
+ ["rhd", "triangle"],
449
+ ["rho", "rho"],
450
+ ["rightarrow", "arrow.r"],
451
+ ["rightthreetimes", "times.three.r"],
452
+ ["rtimes", "times.r"],
453
+ ["setminus", "without"],
454
+ ["sigma", "sigma"],
455
+ ["sim", "tilde"],
456
+ ["simeq", "tilde.eq"],
457
+ ["slash", "slash"],
458
+ ["smallsetminus", "without"],
459
+ ["spadesuit", "suit.spade"],
460
+ ["sqcap", "sect.sq"],
461
+ ["sqcup", "union.sq"],
462
+ ["sqsubseteq", "subset.eq.sq"],
463
+ ["sqsupseteq", "supset.eq.sq"],
464
+ ["star", "star"],
465
+ ["subset", "subset"],
466
+ ["subseteq", "subset.eq"],
467
+ ["subsetneq", "subset.neq"],
468
+ ["succ", "succ"],
469
+ ["succeq", "succ.eq"],
470
+ ["sum", "sum"],
471
+ ["supset", "supset"],
472
+ ["supseteq", "supset.eq"],
473
+ ["supsetneq", "supset.neq"],
474
+ ["swarrow", "arrow.bl"],
475
+ ["tau", "tau"],
476
+ ["theta", "theta"],
477
+ ["times", "times"],
478
+ ["to", "arrow.r"],
479
+ ["top", "top"],
480
+ ["triangle", "triangle.t"],
481
+ ["triangledown", "triangle.b.small"],
482
+ ["triangleleft", "triangle.l.small"],
483
+ ["triangleright", "triangle.r.small"],
484
+ ["twoheadrightarrow", "arrow.r.twohead"],
485
+ ["uparrow", "arrow.t"],
486
+ ["updownarrow", "arrow.t.b"],
487
+ ["upharpoonright", "harpoon.tr"],
488
+ ["uplus", "union.plus"],
489
+ ["upsilon", "upsilon"],
490
+ ["varepsilon", "epsilon"],
491
+ ["varnothing", "diameter"],
492
+ ["varphi", "phi"],
493
+ ["varpi", "pi.alt"],
494
+ ["varrho", "rho.alt"],
495
+ ["varsigma", "sigma.alt"],
496
+ ["vartheta", "theta.alt"],
497
+ ["vdash", "tack.r"],
498
+ ["vdots", "dots.v"],
499
+ ["vee", "or"],
500
+ ["wedge", "and"],
501
+ ["wr", "wreath"],
502
+ ["xi", "xi"],
503
+ ["yen", "yen"],
504
+ ["zeta", "zeta"],
505
+ ["mathscr", "scr"],
506
+ ["LaTeX", "#LaTeX"],
507
+ ["TeX", "#TeX"]
508
+ ]);
509
+
510
+ // src/writer.ts
511
+ function convertToken(token) {
512
+ if (/^[a-zA-Z0-9]$/.test(token)) {
513
+ return token;
514
+ } else if (token === "\\\\") {
515
+ return "\\\n";
516
+ } else if (["\\$", "\\#", "\\&", "\\_"].includes(token)) {
517
+ return token;
518
+ } else if (token.startsWith("\\")) {
519
+ const symbol = token.slice(1);
520
+ if (symbolMap.has(symbol)) {
521
+ return symbolMap.get(symbol);
522
+ } else {
523
+ return symbol;
22
524
  }
23
- const t = (0, parser_1.parseTex)(tex, opt.customTexMacros);
24
- const writer = new writer_1.TypstWriter(opt.nonStrict, opt.preferTypstIntrinsic);
25
- writer.append(t);
26
- return writer.finalize();
525
+ }
526
+ return token;
527
+ }
528
+ var TYPST_INTRINSIC_SYMBOLS = [
529
+ "dim",
530
+ "id",
531
+ "im",
532
+ "mod",
533
+ "Pr",
534
+ "sech",
535
+ "csch"
536
+ ];
537
+
538
+ class TypstWriterError extends Error {
539
+ node;
540
+ constructor(message, node) {
541
+ super(message);
542
+ this.name = "TypstWriterError";
543
+ this.node = node;
544
+ }
545
+ }
546
+
547
+ class TypstWriter {
548
+ nonStrict;
549
+ preferTypstIntrinsic;
550
+ buffer = "";
551
+ queue = [];
552
+ needSpaceAfterSingleItemScript = false;
553
+ insideFunctionDepth = 0;
554
+ constructor(nonStrict, preferTypstIntrinsic) {
555
+ this.nonStrict = nonStrict;
556
+ this.preferTypstIntrinsic = preferTypstIntrinsic;
557
+ }
558
+ writeBuffer(str) {
559
+ if (this.needSpaceAfterSingleItemScript && /^[0-9a-zA-Z\(]/.test(str)) {
560
+ this.buffer += " ";
561
+ } else {
562
+ let no_need_space = false;
563
+ no_need_space ||= /[\(\|]$/.test(this.buffer) && /^\w/.test(str);
564
+ no_need_space ||= /^[}()_^,;!\|]$/.test(str);
565
+ no_need_space ||= str === "'";
566
+ no_need_space ||= /[0-9]$/.test(this.buffer) && /^[0-9]/.test(str);
567
+ no_need_space ||= /[\(\[{]\s*(-|\+)$/.test(this.buffer) || this.buffer === "-" || this.buffer === "+";
568
+ no_need_space ||= this.buffer === "";
569
+ no_need_space ||= /[\s"_^{\(]$/.test(this.buffer);
570
+ if (!no_need_space) {
571
+ this.buffer += " ";
572
+ }
573
+ }
574
+ if (this.needSpaceAfterSingleItemScript) {
575
+ this.needSpaceAfterSingleItemScript = false;
576
+ }
577
+ this.buffer += str;
578
+ }
579
+ append(node) {
580
+ if (node.type === "empty") {
581
+ return;
582
+ } else if (node.type === "ordgroup") {
583
+ node.args.forEach((arg) => this.append(arg));
584
+ } else if (node.type === "atom") {
585
+ let content = node.content;
586
+ if (node.content === "," && this.insideFunctionDepth > 0) {
587
+ content = "comma";
588
+ }
589
+ this.queue.push({ type: "atom", content });
590
+ } else if (node.type === "symbol") {
591
+ this.queue.push({ type: "symbol", content: node.content });
592
+ } else if (node.type === "text") {
593
+ this.queue.push(node);
594
+ } else if (node.type === "supsub") {
595
+ let { base, sup, sub } = node.irregularData;
596
+ if (base && base.type === "unaryFunc" && base.content === "\\overbrace" && sup) {
597
+ this.append({ type: "binaryFunc", content: "\\overbrace", args: [base.args[0], sup] });
598
+ return;
599
+ } else if (base && base.type === "unaryFunc" && base.content === "\\underbrace" && sub) {
600
+ this.append({ type: "binaryFunc", content: "\\underbrace", args: [base.args[0], sub] });
601
+ return;
602
+ }
603
+ if (!base) {
604
+ this.queue.push({ type: "text", content: "" });
605
+ } else {
606
+ this.appendWithBracketsIfNeeded(base);
607
+ }
608
+ let trailing_space_needed = false;
609
+ const has_prime = sup && sup.type === "symbol" && sup.content === "\\prime";
610
+ if (has_prime) {
611
+ this.queue.push({ type: "atom", content: "\'" });
612
+ trailing_space_needed = false;
613
+ }
614
+ if (sub) {
615
+ this.queue.push({ type: "atom", content: "_" });
616
+ trailing_space_needed = this.appendWithBracketsIfNeeded(sub);
617
+ }
618
+ if (sup && !has_prime) {
619
+ this.queue.push({ type: "atom", content: "^" });
620
+ trailing_space_needed = this.appendWithBracketsIfNeeded(sup);
621
+ }
622
+ if (trailing_space_needed) {
623
+ this.queue.push({ type: "softSpace", content: "" });
624
+ }
625
+ } else if (node.type === "leftright") {
626
+ const [left, body, right] = node.args;
627
+ if (["[]", "()", "{}", "\\lfloor\\rfloor", "\\lceil\\rceil"].includes(left.content + right.content)) {
628
+ this.append(left);
629
+ this.append(body);
630
+ this.append(right);
631
+ return;
632
+ }
633
+ const func_symbol = { type: "symbol", content: "lr" };
634
+ this.queue.push(func_symbol);
635
+ this.insideFunctionDepth++;
636
+ this.queue.push({ type: "atom", content: "(" });
637
+ this.append(left);
638
+ this.append(body);
639
+ this.append(right);
640
+ this.queue.push({ type: "atom", content: ")" });
641
+ this.insideFunctionDepth--;
642
+ } else if (node.type === "binaryFunc") {
643
+ const func_symbol = { type: "symbol", content: node.content };
644
+ const [arg0, arg1] = node.args;
645
+ this.queue.push(func_symbol);
646
+ this.insideFunctionDepth++;
647
+ this.queue.push({ type: "atom", content: "(" });
648
+ this.append(arg0);
649
+ this.queue.push({ type: "atom", content: "," });
650
+ this.append(arg1);
651
+ this.queue.push({ type: "atom", content: ")" });
652
+ this.insideFunctionDepth--;
653
+ } else if (node.type === "unaryFunc") {
654
+ const func_symbol = { type: "symbol", content: node.content };
655
+ const arg0 = node.args[0];
656
+ if (node.content === "\\sqrt" && node.irregularData) {
657
+ func_symbol.content = "root";
658
+ this.queue.push(func_symbol);
659
+ this.insideFunctionDepth++;
660
+ this.queue.push({ type: "atom", content: "(" });
661
+ this.append(node.irregularData);
662
+ this.queue.push({ type: "atom", content: "," });
663
+ this.append(arg0);
664
+ this.queue.push({ type: "atom", content: ")" });
665
+ this.insideFunctionDepth--;
666
+ return;
667
+ } else if (node.content === "\\mathbb") {
668
+ const body = node.args[0];
669
+ if (body.type === "symbol" && /^[A-Z]$/.test(body.content)) {
670
+ this.queue.push({ type: "symbol", content: body.content + body.content });
671
+ return;
672
+ }
673
+ } else if (node.content === "\\operatorname") {
674
+ let body = node.args;
675
+ if (body.length === 1 && body[0].type == "ordgroup") {
676
+ body = body[0].args;
677
+ }
678
+ const text = body.reduce((buff, n) => {
679
+ buff += convertToken(n.content);
680
+ return buff;
681
+ }, "");
682
+ if (this.preferTypstIntrinsic && TYPST_INTRINSIC_SYMBOLS.includes(text)) {
683
+ this.queue.push({ type: "symbol", content: text });
684
+ } else if (text.startsWith("SyMb01-")) {
685
+ this.queue.push({ type: "symbol", content: "\\" + text.substring(7) });
686
+ } else {
687
+ this.queue.push({ type: "symbol", content: "op" });
688
+ this.queue.push({ type: "atom", content: "(" });
689
+ this.queue.push({ type: "text", content: text });
690
+ this.queue.push({ type: "atom", content: ")" });
691
+ }
692
+ return;
693
+ }
694
+ this.queue.push(func_symbol);
695
+ this.insideFunctionDepth++;
696
+ this.queue.push({ type: "atom", content: "(" });
697
+ this.append(arg0);
698
+ this.queue.push({ type: "atom", content: ")" });
699
+ this.insideFunctionDepth--;
700
+ } else if (node.type === "align") {
701
+ const matrix = node.irregularData;
702
+ matrix.forEach((row, i) => {
703
+ row.forEach((cell, j) => {
704
+ if (j > 0) {
705
+ this.queue.push({ type: "atom", content: "&" });
706
+ }
707
+ this.append(cell);
708
+ });
709
+ if (i < matrix.length - 1) {
710
+ this.queue.push({ type: "symbol", content: "\\\\" });
711
+ }
712
+ });
713
+ } else if (node.type === "matrix") {
714
+ const matrix = node.irregularData;
715
+ this.queue.push({ type: "symbol", content: "mat" });
716
+ this.insideFunctionDepth++;
717
+ this.queue.push({ type: "atom", content: "(" });
718
+ this.queue.push({ type: "symbol", content: "delim: #none, " });
719
+ matrix.forEach((row, i) => {
720
+ row.forEach((cell, j) => {
721
+ if (cell.type === "ordgroup" && cell.args.length === 0) {
722
+ return;
723
+ }
724
+ this.append(cell);
725
+ if (j < row.length - 1) {
726
+ this.queue.push({ type: "atom", content: "," });
727
+ } else {
728
+ if (i < matrix.length - 1) {
729
+ this.queue.push({ type: "atom", content: ";" });
730
+ }
731
+ }
732
+ });
733
+ });
734
+ this.queue.push({ type: "atom", content: ")" });
735
+ this.insideFunctionDepth--;
736
+ } else if (node.type === "unknownMacro") {
737
+ if (this.nonStrict) {
738
+ this.queue.push({ type: "symbol", content: node.content });
739
+ } else {
740
+ throw new TypstWriterError(`Unknown macro: ${node.content}`, node);
741
+ }
742
+ } else {
743
+ throw new TypstWriterError(`Unimplemented node type to append: ${node.type}`, node);
744
+ }
745
+ }
746
+ flushQueue() {
747
+ this.queue.forEach((node) => {
748
+ let str = "";
749
+ switch (node.type) {
750
+ case "atom":
751
+ str = node.content;
752
+ break;
753
+ case "symbol":
754
+ str = convertToken(node.content);
755
+ break;
756
+ case "text":
757
+ str = `"${node.content}"`;
758
+ break;
759
+ case "softSpace":
760
+ this.needSpaceAfterSingleItemScript = true;
761
+ str = "";
762
+ break;
763
+ default:
764
+ throw new TypstWriterError(`Unexpected node type to stringify: ${node.type}`, node);
765
+ }
766
+ if (str !== "") {
767
+ this.writeBuffer(str);
768
+ }
769
+ });
770
+ this.queue = [];
771
+ }
772
+ appendWithBracketsIfNeeded(node) {
773
+ const is_single_atom = node.type === "atom";
774
+ const is_single_function = node.type === "unaryFunc" || node.type === "binaryFunc" || node.type === "leftright";
775
+ const is_single = ["atom", "symbol", "unaryFunc", "binaryFunc", "leftright"].includes(node.type);
776
+ if (is_single) {
777
+ this.append(node);
778
+ } else {
779
+ this.queue.push({
780
+ type: "atom",
781
+ content: "("
782
+ });
783
+ this.append(node);
784
+ this.queue.push({
785
+ type: "atom",
786
+ content: ")"
787
+ });
788
+ }
789
+ return is_single;
790
+ }
791
+ finalize() {
792
+ this.flushQueue();
793
+ const smartFloorPass = function(input) {
794
+ let res = input.replace(/⌊\s*(.*?)\s*⌋/g, "floor($1)");
795
+ res = res.replace(/floor\(\)/g, 'floor("")');
796
+ return res;
797
+ };
798
+ const smartCeilPass = function(input) {
799
+ let res = input.replace(/⌈\s*(.*?)\s*⌉/g, "ceil($1)");
800
+ res = res.replace(/ceil\(\)/g, 'ceil("")');
801
+ return res;
802
+ };
803
+ this.buffer = smartFloorPass(this.buffer);
804
+ this.buffer = smartCeilPass(this.buffer);
805
+ return this.buffer;
806
+ }
807
+ }
808
+
809
+ // src/index.ts
810
+ function tex2typst(tex, options) {
811
+ const opt = {
812
+ nonStrict: false,
813
+ preferTypstIntrinsic: true,
814
+ customTexMacros: {}
815
+ };
816
+ if (options) {
817
+ if (options.nonStrict) {
818
+ opt.nonStrict = options.nonStrict;
819
+ }
820
+ if (options.preferTypstIntrinsic) {
821
+ opt.preferTypstIntrinsic = options.preferTypstIntrinsic;
822
+ }
823
+ if (options.customTexMacros) {
824
+ opt.customTexMacros = options.customTexMacros;
825
+ }
826
+ }
827
+ const t = parseTex(tex, opt.customTexMacros);
828
+ const writer2 = new TypstWriter(opt.nonStrict, opt.preferTypstIntrinsic);
829
+ writer2.append(t);
830
+ return writer2.finalize();
831
+ }
832
+ if (typeof window !== "undefined") {
833
+ window.tex2typst = tex2typst;
27
834
  }
835
+ export {
836
+ tex2typst
837
+ };