tex2typst 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.js +451 -241
- package/dist/tex-parser.d.ts +1 -0
- package/dist/tex2typst.min.js +20 -19
- package/dist/types.d.ts +8 -4
- package/dist/typst-shorthands.d.ts +3 -0
- package/dist/typst-writer.d.ts +9 -3
- package/docs/api-reference.md +64 -0
- package/package.json +5 -5
- package/src/convert.ts +43 -6
- package/src/index.ts +12 -15
- package/src/map.ts +13 -36
- package/src/tex-parser.ts +33 -44
- package/src/tex-writer.ts +0 -1
- package/src/types.ts +10 -2
- package/src/typst-parser.ts +24 -5
- package/src/typst-shorthands.ts +51 -0
- package/src/typst-writer.ts +52 -25
- package/tools/make-shorthand-map.py +33 -0
- package/tools/make-symbol-map.py +4 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
// src/map.ts
|
|
2
|
-
var symbolMap = new Map([
|
|
2
|
+
var symbolMap = /* @__PURE__ */ new Map([
|
|
3
|
+
["cos", "cos"],
|
|
4
|
+
["sin", "sin"],
|
|
5
|
+
["tan", "tan"],
|
|
6
|
+
["cot", "cot"],
|
|
7
|
+
["sec", "sec"],
|
|
8
|
+
["csc", "csc"],
|
|
9
|
+
["mod", "mod"],
|
|
10
|
+
["omicron", "omicron"],
|
|
11
|
+
["Xi", "Xi"],
|
|
12
|
+
["Upsilon", "Upsilon"],
|
|
13
|
+
["lim", "lim"],
|
|
3
14
|
["nonumber", ""],
|
|
4
15
|
["vec", "arrow"],
|
|
5
16
|
["neq", "eq.not"],
|
|
@@ -10,13 +21,19 @@ var symbolMap = new Map([
|
|
|
10
21
|
["vdots", "dots.v"],
|
|
11
22
|
["ddots", "dots.down"],
|
|
12
23
|
["widehat", "hat"],
|
|
24
|
+
// Ideally, the result of \widehat should be longer than \hat. But it is not implemented now.
|
|
13
25
|
["widetilde", "tilde"],
|
|
26
|
+
// Ideally, the result of \widetilde should be longer than \tilde. But it is not implemented now.
|
|
14
27
|
["quad", "quad"],
|
|
15
28
|
["qquad", "wide"],
|
|
16
29
|
["overbrace", "overbrace"],
|
|
30
|
+
// same
|
|
17
31
|
["underbrace", "underbrace"],
|
|
32
|
+
// same
|
|
18
33
|
["overline", "overline"],
|
|
34
|
+
// same
|
|
19
35
|
["underline", "underline"],
|
|
36
|
+
// same
|
|
20
37
|
["bar", "macron"],
|
|
21
38
|
["dbinom", "binom"],
|
|
22
39
|
["tbinom", "binom"],
|
|
@@ -33,56 +50,36 @@ var symbolMap = new Map([
|
|
|
33
50
|
["mathsf", "sans"],
|
|
34
51
|
["mathtt", "mono"],
|
|
35
52
|
["rm", "upright"],
|
|
53
|
+
// TODO: \pmb need special logic to handle but it is not implemented now. See the commented test case.
|
|
36
54
|
["pmb", "bold"],
|
|
55
|
+
/* variants of plus,minus,times,divide */
|
|
37
56
|
["pm", "plus.minus"],
|
|
38
57
|
["mp", "minus.plus"],
|
|
39
58
|
["boxplus", "plus.square"],
|
|
40
59
|
["otimes", "times.circle"],
|
|
41
60
|
["boxtimes", "times.square"],
|
|
61
|
+
/* wave */
|
|
62
|
+
// tex: \sim \approx \cong \simeq \asymp \equiv \propto
|
|
63
|
+
// typst: tilde.op approx tilde.equiv tilde.eq ≍ equiv prop
|
|
42
64
|
["approx", "approx"],
|
|
43
65
|
["cong", "tilde.equiv"],
|
|
44
66
|
["simeq", "tilde.eq"],
|
|
45
|
-
["asymp", "
|
|
67
|
+
["asymp", "\u224D"],
|
|
68
|
+
// just use the unicode character :-)
|
|
46
69
|
["equiv", "equiv"],
|
|
47
70
|
["propto", "prop"],
|
|
71
|
+
/* arrows */
|
|
48
72
|
["gets", "arrow.l"],
|
|
49
|
-
[
|
|
50
|
-
["leftharpoonup", "harpoon.lt"],
|
|
51
|
-
["leftharpoondown", "harpoon.lb"],
|
|
52
|
-
["rightleftharpoons", "harpoons.rtlb"],
|
|
53
|
-
["longleftarrow", "arrow.l.long"],
|
|
54
|
-
["longrightarrow", "arrow.r.long"],
|
|
55
|
-
["longleftrightarrow", "arrow.l.r.long"],
|
|
56
|
-
["Longleftarrow", "arrow.l.double.long"],
|
|
57
|
-
["Longrightarrow", "arrow.r.double.long"],
|
|
58
|
-
["Longleftrightarrow", "arrow.l.r.double.long"],
|
|
59
|
-
["hookrightarrow", "arrow.r.hook"],
|
|
60
|
-
["rightharpoonup", "harpoon.rt"],
|
|
61
|
-
["rightharpoondown", "harpoon.rb"],
|
|
73
|
+
// ['longmapsto', 'arrow.r.bar'],
|
|
62
74
|
["iff", "arrow.l.r.double.long"],
|
|
63
75
|
["implies", "arrow.r.double.long"],
|
|
64
|
-
["uparrow", "arrow.t"],
|
|
65
|
-
["downarrow", "arrow.b"],
|
|
66
|
-
["updownarrow", "arrow.t.b"],
|
|
67
|
-
["Uparrow", "arrow.t.double"],
|
|
68
|
-
["Downarrow", "arrow.b.double"],
|
|
69
|
-
["Updownarrow", "arrow.t.b.double"],
|
|
70
|
-
["nearrow", "arrow.tr"],
|
|
71
|
-
["searrow", "arrow.br"],
|
|
72
|
-
["swarrow", "arrow.bl"],
|
|
73
|
-
["nwarrow", "arrow.tl"],
|
|
74
76
|
["leadsto", "arrow.squiggly"],
|
|
75
|
-
["leftleftarrows", "arrows.ll"],
|
|
76
|
-
["rightrightarrows", "arrows.rr"],
|
|
77
77
|
["Cap", "sect.double"],
|
|
78
78
|
["Cup", "union.double"],
|
|
79
79
|
["Delta", "Delta"],
|
|
80
80
|
["Gamma", "Gamma"],
|
|
81
81
|
["Join", "join"],
|
|
82
82
|
["Lambda", "Lambda"],
|
|
83
|
-
["Leftarrow", "arrow.l.double"],
|
|
84
|
-
["Leftrightarrow", "arrow.l.r.double"],
|
|
85
|
-
["Longrightarrow", "arrow.r.double.long"],
|
|
86
83
|
["Omega", "Omega"],
|
|
87
84
|
["P", "pilcrow"],
|
|
88
85
|
["Phi", "Phi"],
|
|
@@ -94,26 +91,34 @@ var symbolMap = new Map([
|
|
|
94
91
|
["Theta", "Theta"],
|
|
95
92
|
["aleph", "alef"],
|
|
96
93
|
["alpha", "alpha"],
|
|
94
|
+
// ['amalg', 'product.co'],
|
|
97
95
|
["angle", "angle"],
|
|
98
96
|
["approx", "approx"],
|
|
99
97
|
["approxeq", "approx.eq"],
|
|
98
|
+
// ['ast', 'ast'],
|
|
100
99
|
["beta", "beta"],
|
|
101
100
|
["bigcap", "sect.big"],
|
|
102
101
|
["bigcirc", "circle.big"],
|
|
103
102
|
["bigcup", "union.big"],
|
|
104
103
|
["bigodot", "dot.circle.big"],
|
|
104
|
+
// ['bigoplus', 'xor.big'], // or "plus.circle.big"
|
|
105
105
|
["bigotimes", "times.circle.big"],
|
|
106
106
|
["bigsqcup", "union.sq.big"],
|
|
107
|
+
// ['bigtriangledown', 'triangle.b'],
|
|
108
|
+
// ['bigtriangleup', 'triangle.t'],
|
|
107
109
|
["biguplus", "union.plus.big"],
|
|
108
110
|
["bigvee", "or.big"],
|
|
109
111
|
["bigwedge", "and.big"],
|
|
112
|
+
// ['bowtie', 'join'],
|
|
110
113
|
["bullet", "bullet"],
|
|
111
114
|
["cap", "sect"],
|
|
112
115
|
["cdot", "dot.op"],
|
|
116
|
+
// 'dot.op' or 'dot.c'
|
|
113
117
|
["cdots", "dots.c"],
|
|
114
118
|
["checkmark", "checkmark"],
|
|
115
119
|
["chi", "chi"],
|
|
116
120
|
["circ", "circle.small"],
|
|
121
|
+
// 'circle.small' or 'compose'
|
|
117
122
|
["colon", "colon"],
|
|
118
123
|
["cong", "tilde.equiv"],
|
|
119
124
|
["coprod", "product.co"],
|
|
@@ -130,7 +135,6 @@ var symbolMap = new Map([
|
|
|
130
135
|
["div", "div"],
|
|
131
136
|
["divideontimes", "times.div"],
|
|
132
137
|
["dotplus", "plus.dot"],
|
|
133
|
-
["downarrow", "arrow.b"],
|
|
134
138
|
["ell", "ell"],
|
|
135
139
|
["emptyset", "nothing"],
|
|
136
140
|
["epsilon", "epsilon.alt"],
|
|
@@ -138,6 +142,7 @@ var symbolMap = new Map([
|
|
|
138
142
|
["eta", "eta"],
|
|
139
143
|
["exists", "exists"],
|
|
140
144
|
["forall", "forall"],
|
|
145
|
+
// ['frown', 'paren.t'],
|
|
141
146
|
["gamma", "gamma"],
|
|
142
147
|
["ge", "gt.eq"],
|
|
143
148
|
["geq", "gt.eq"],
|
|
@@ -152,6 +157,7 @@ var symbolMap = new Map([
|
|
|
152
157
|
["infty", "infinity"],
|
|
153
158
|
["int", "integral"],
|
|
154
159
|
["intercal", "top"],
|
|
160
|
+
// 'top' or 'tack.b'
|
|
155
161
|
["iota", "iota"],
|
|
156
162
|
["jmath", "dotless.j"],
|
|
157
163
|
["kappa", "kappa"],
|
|
@@ -162,21 +168,23 @@ var symbolMap = new Map([
|
|
|
162
168
|
["lbrack", "bracket.l"],
|
|
163
169
|
["ldots", "dots.h"],
|
|
164
170
|
["le", "lt.eq"],
|
|
165
|
-
["leadsto", "arrow.squiggly"],
|
|
166
|
-
["leftarrow", "arrow.l"],
|
|
167
171
|
["leftthreetimes", "times.three.l"],
|
|
168
172
|
["leftrightarrow", "arrow.l.r"],
|
|
169
173
|
["leq", "lt.eq"],
|
|
170
174
|
["leqslant", "lt.eq.slant"],
|
|
171
175
|
["lhd", "triangle.l"],
|
|
172
176
|
["ll", "lt.double"],
|
|
177
|
+
// ['longmapsto', 'arrow.bar.long'],
|
|
178
|
+
// ['longrightarrow', 'arrow.long'],
|
|
173
179
|
["lor", "or"],
|
|
174
180
|
["ltimes", "times.l"],
|
|
181
|
+
// ['mapsto', 'arrow.bar'],
|
|
175
182
|
["measuredangle", "angle.arc"],
|
|
176
183
|
["mid", "divides"],
|
|
177
184
|
["models", "models"],
|
|
178
185
|
["mp", "minus.plus"],
|
|
179
186
|
["mu", "mu"],
|
|
187
|
+
// ['nRightarrow', 'arrow.double.not'],
|
|
180
188
|
["nabla", "nabla"],
|
|
181
189
|
["ncong", "tilde.equiv.not"],
|
|
182
190
|
["ne", "eq.not"],
|
|
@@ -190,18 +198,20 @@ var symbolMap = new Map([
|
|
|
190
198
|
["ngeq", "gt.eq.not"],
|
|
191
199
|
["nmid", "divides.not"],
|
|
192
200
|
["notin", "in.not"],
|
|
201
|
+
// ['nrightarrow', 'arrow.not'],
|
|
193
202
|
["nsim", "tilde.not"],
|
|
194
203
|
["nsubseteq", "subset.eq.not"],
|
|
195
204
|
["nu", "nu"],
|
|
196
205
|
["ntriangleleft", "lt.tri.not"],
|
|
197
206
|
["ntriangleright", "gt.tri.not"],
|
|
198
|
-
["nwarrow", "arrow.tl"],
|
|
199
207
|
["odot", "dot.circle"],
|
|
200
208
|
["oint", "integral.cont"],
|
|
201
209
|
["oiint", "integral.surf"],
|
|
202
210
|
["oiiint", "integral.vol"],
|
|
203
211
|
["omega", "omega"],
|
|
212
|
+
// ['omicron', 'omicron'],
|
|
204
213
|
["ominus", "minus.circle"],
|
|
214
|
+
// ['oplus', 'xor'], // or 'plus.circle'
|
|
205
215
|
["otimes", "times.circle"],
|
|
206
216
|
["parallel", "parallel"],
|
|
207
217
|
["partial", "diff"],
|
|
@@ -230,11 +240,13 @@ var symbolMap = new Map([
|
|
|
230
240
|
["simeq", "tilde.eq"],
|
|
231
241
|
["slash", "slash"],
|
|
232
242
|
["smallsetminus", "without"],
|
|
243
|
+
// ['smile', 'paren.b'],
|
|
233
244
|
["spadesuit", "suit.spade"],
|
|
234
245
|
["sqcap", "sect.sq"],
|
|
235
246
|
["sqcup", "union.sq"],
|
|
236
247
|
["sqsubseteq", "subset.eq.sq"],
|
|
237
248
|
["sqsupseteq", "supset.eq.sq"],
|
|
249
|
+
// ['star', 'star'],
|
|
238
250
|
["subset", "subset"],
|
|
239
251
|
["subseteq", "subset.eq"],
|
|
240
252
|
["subsetneq", "subset.neq"],
|
|
@@ -244,21 +256,22 @@ var symbolMap = new Map([
|
|
|
244
256
|
["supset", "supset"],
|
|
245
257
|
["supseteq", "supset.eq"],
|
|
246
258
|
["supsetneq", "supset.neq"],
|
|
247
|
-
["swarrow", "arrow.bl"],
|
|
248
259
|
["tau", "tau"],
|
|
249
260
|
["theta", "theta"],
|
|
250
261
|
["times", "times"],
|
|
251
262
|
["to", "arrow.r"],
|
|
252
263
|
["top", "top"],
|
|
253
264
|
["triangle", "triangle.t"],
|
|
265
|
+
// ['triangledown', 'triangle.b.small'],
|
|
266
|
+
// ['triangleleft', 'triangle.l.small'],
|
|
267
|
+
// ['triangleright', 'triangle.r.small'],
|
|
254
268
|
["twoheadrightarrow", "arrow.r.twohead"],
|
|
255
|
-
["uparrow", "arrow.t"],
|
|
256
|
-
["updownarrow", "arrow.t.b"],
|
|
257
269
|
["upharpoonright", "harpoon.tr"],
|
|
258
270
|
["uplus", "union.plus"],
|
|
259
271
|
["upsilon", "upsilon"],
|
|
260
272
|
["varepsilon", "epsilon"],
|
|
261
273
|
["varnothing", "diameter"],
|
|
274
|
+
// empty set
|
|
262
275
|
["varphi", "phi"],
|
|
263
276
|
["varpi", "pi.alt"],
|
|
264
277
|
["varrho", "rho.alt"],
|
|
@@ -272,11 +285,12 @@ var symbolMap = new Map([
|
|
|
272
285
|
["xi", "xi"],
|
|
273
286
|
["yen", "yen"],
|
|
274
287
|
["zeta", "zeta"],
|
|
288
|
+
// extended
|
|
275
289
|
["mathscr", "scr"],
|
|
276
290
|
["LaTeX", "#LaTeX"],
|
|
277
291
|
["TeX", "#TeX"]
|
|
278
292
|
]);
|
|
279
|
-
var map_from_official_docs = new Map([
|
|
293
|
+
var map_from_official_docs = /* @__PURE__ */ new Map([
|
|
280
294
|
["lparen", "paren.l"],
|
|
281
295
|
["lParen", "paren.l.double"],
|
|
282
296
|
["rparen", "paren.r"],
|
|
@@ -287,6 +301,7 @@ var map_from_official_docs = new Map([
|
|
|
287
301
|
["lBrace", "brace.l.double"],
|
|
288
302
|
["rbrace", "brace.r"],
|
|
289
303
|
["rBrace", "brace.r.double"],
|
|
304
|
+
// ['overbrace', 'brace.t'],
|
|
290
305
|
["underbrace", "brace.b"],
|
|
291
306
|
["lbrack", "bracket.l"],
|
|
292
307
|
["lBrack", "bracket.l.double"],
|
|
@@ -367,6 +382,7 @@ var map_from_official_docs = new Map([
|
|
|
367
382
|
["mathquestion", "quest"],
|
|
368
383
|
["Question", "quest.double"],
|
|
369
384
|
["mathoctothorpe", "hash"],
|
|
385
|
+
// ['mathhyphen', 'hyph'],
|
|
370
386
|
["mathpercent", "percent"],
|
|
371
387
|
["mathparagraph", "pilcrow"],
|
|
372
388
|
["mathsection", "section"],
|
|
@@ -435,6 +451,8 @@ var map_from_official_docs = new Map([
|
|
|
435
451
|
["stareq", "eq.star"],
|
|
436
452
|
["circledequal", "eq.circle"],
|
|
437
453
|
["eqcolon", "eq.colon"],
|
|
454
|
+
// \usepackage{mathtools} defines \eqdef
|
|
455
|
+
// https://tex.stackexchange.com/questions/28836/typesetting-the-define-equals-symbol
|
|
438
456
|
["eqdef", "eq.def"],
|
|
439
457
|
["triangleq", "eq.delta"],
|
|
440
458
|
["veeeq", "eq.equi"],
|
|
@@ -936,6 +954,64 @@ var map_from_official_docs = new Map([
|
|
|
936
954
|
["barV", "tack.b.double"],
|
|
937
955
|
["shortdowntack", "tack.b.short"],
|
|
938
956
|
["dashVdash", "tack.l.r"],
|
|
957
|
+
/*
|
|
958
|
+
['mupalpha', 'alpha'],
|
|
959
|
+
['mupbeta', 'beta'],
|
|
960
|
+
['mupchi', 'chi'],
|
|
961
|
+
['mupdelta', 'delta'],
|
|
962
|
+
['mupvarepsilon', 'epsilon'],
|
|
963
|
+
['mupepsilon', 'epsilon.alt'],
|
|
964
|
+
['mupeta', 'eta'],
|
|
965
|
+
['mupgamma', 'gamma'],
|
|
966
|
+
['mupiota', 'iota'],
|
|
967
|
+
['mupkappa', 'kappa'],
|
|
968
|
+
['mupvarkappa', 'kappa.alt'],
|
|
969
|
+
['muplambda', 'lambda'],
|
|
970
|
+
['mupmu', 'mu'],
|
|
971
|
+
['mupnu', 'nu'],
|
|
972
|
+
['mho', 'ohm.inv'],
|
|
973
|
+
['mupomega', 'omega'],
|
|
974
|
+
['mupomicron', 'omicron'],
|
|
975
|
+
['mupvarphi', 'phi'],
|
|
976
|
+
['mupphi', 'phi.alt'],
|
|
977
|
+
['muppi', 'pi'],
|
|
978
|
+
['mupvarpi', 'pi.alt'],
|
|
979
|
+
['muppsi', 'psi'],
|
|
980
|
+
['muprho', 'rho'],
|
|
981
|
+
['mupvarrho', 'rho.alt'],
|
|
982
|
+
['mupsigma', 'sigma'],
|
|
983
|
+
['mupvarsigma', 'sigma.alt'],
|
|
984
|
+
['muptau', 'tau'],
|
|
985
|
+
['muptheta', 'theta'],
|
|
986
|
+
['mupvartheta', 'theta.alt'],
|
|
987
|
+
['mupupsilon', 'upsilon'],
|
|
988
|
+
['mupxi', 'xi'],
|
|
989
|
+
['mupzeta', 'zeta'],
|
|
990
|
+
['mupAlpha', 'Alpha'],
|
|
991
|
+
['mupBeta', 'Beta'],
|
|
992
|
+
['mupChi', 'Chi'],
|
|
993
|
+
['mupDelta', 'Delta'],
|
|
994
|
+
['mupEpsilon', 'Epsilon'],
|
|
995
|
+
['mupEta', 'Eta'],
|
|
996
|
+
['mupGamma', 'Gamma'],
|
|
997
|
+
['mupIota', 'Iota'],
|
|
998
|
+
['mupKappa', 'Kappa'],
|
|
999
|
+
['mupLambda', 'Lambda'],
|
|
1000
|
+
['mupMu', 'Mu'],
|
|
1001
|
+
['mupNu', 'Nu'],
|
|
1002
|
+
['mupOmega', 'Omega'],
|
|
1003
|
+
['mupOmicron', 'Omicron'],
|
|
1004
|
+
['mupPhi', 'Phi'],
|
|
1005
|
+
['mupPi', 'Pi'],
|
|
1006
|
+
['mupPsi', 'Psi'],
|
|
1007
|
+
['mupRho', 'Rho'],
|
|
1008
|
+
['mupSigma', 'Sigma'],
|
|
1009
|
+
['mupTau', 'Tau'],
|
|
1010
|
+
['mupTheta', 'Theta'],
|
|
1011
|
+
['mupUpsilon', 'Upsilon'],
|
|
1012
|
+
['mupXi', 'Xi'],
|
|
1013
|
+
['mupZeta', 'Zeta'],
|
|
1014
|
+
*/
|
|
939
1015
|
["BbbA", "AA"],
|
|
940
1016
|
["BbbB", "BB"],
|
|
941
1017
|
["BbbC", "CC"],
|
|
@@ -976,12 +1052,13 @@ for (const [key, value] of map_from_official_docs) {
|
|
|
976
1052
|
symbolMap.set(key, value);
|
|
977
1053
|
}
|
|
978
1054
|
}
|
|
979
|
-
var reverseSymbolMap = new Map;
|
|
1055
|
+
var reverseSymbolMap = /* @__PURE__ */ new Map();
|
|
980
1056
|
for (const [key, value] of Array.from(symbolMap.entries()).reverse()) {
|
|
981
1057
|
reverseSymbolMap.set(value, key);
|
|
982
1058
|
}
|
|
983
1059
|
reverseSymbolMap.set("dif", "mathrm{d}");
|
|
984
|
-
|
|
1060
|
+
reverseSymbolMap.set("oo", "infty");
|
|
1061
|
+
var typst_to_tex_map = /* @__PURE__ */ new Map([
|
|
985
1062
|
["top", "top"],
|
|
986
1063
|
["frac", "frac"],
|
|
987
1064
|
["tilde", "tilde"],
|
|
@@ -996,7 +1073,7 @@ for (const [key, value] of typst_to_tex_map) {
|
|
|
996
1073
|
|
|
997
1074
|
// src/generic.ts
|
|
998
1075
|
function array_find(array, item, start = 0) {
|
|
999
|
-
for (let i = start;i < array.length; i++) {
|
|
1076
|
+
for (let i = start; i < array.length; i++) {
|
|
1000
1077
|
if (array[i].eq(item)) {
|
|
1001
1078
|
return i;
|
|
1002
1079
|
}
|
|
@@ -1027,9 +1104,7 @@ function array_split(array, sep) {
|
|
|
1027
1104
|
}
|
|
1028
1105
|
|
|
1029
1106
|
// src/types.ts
|
|
1030
|
-
|
|
1031
|
-
type;
|
|
1032
|
-
value;
|
|
1107
|
+
var TexToken = class {
|
|
1033
1108
|
constructor(type, value) {
|
|
1034
1109
|
this.type = type;
|
|
1035
1110
|
this.value = value;
|
|
@@ -1047,25 +1122,21 @@ class TexToken {
|
|
|
1047
1122
|
return this.value;
|
|
1048
1123
|
}
|
|
1049
1124
|
}
|
|
1050
|
-
}
|
|
1125
|
+
};
|
|
1051
1126
|
function apply_escape_if_needed(c) {
|
|
1052
1127
|
if (["{", "}", "%"].includes(c)) {
|
|
1053
1128
|
return "\\" + c;
|
|
1054
1129
|
}
|
|
1055
1130
|
return c;
|
|
1056
1131
|
}
|
|
1057
|
-
|
|
1058
|
-
class TexNode {
|
|
1059
|
-
type;
|
|
1060
|
-
content;
|
|
1061
|
-
args;
|
|
1062
|
-
data;
|
|
1132
|
+
var TexNode = class {
|
|
1063
1133
|
constructor(type, content, args, data) {
|
|
1064
1134
|
this.type = type;
|
|
1065
1135
|
this.content = content;
|
|
1066
1136
|
this.args = args;
|
|
1067
1137
|
this.data = data;
|
|
1068
1138
|
}
|
|
1139
|
+
// Note that this is only shallow equality.
|
|
1069
1140
|
eq(other) {
|
|
1070
1141
|
return this.type === other.type && this.content === other.content;
|
|
1071
1142
|
}
|
|
@@ -1143,7 +1214,7 @@ class TexNode {
|
|
|
1143
1214
|
return tokens;
|
|
1144
1215
|
}
|
|
1145
1216
|
case "supsub": {
|
|
1146
|
-
let
|
|
1217
|
+
let should_wrap_in_braces2 = function(node) {
|
|
1147
1218
|
if (node.type === "ordgroup" || node.type === "supsub" || node.type === "empty") {
|
|
1148
1219
|
return true;
|
|
1149
1220
|
} else if (node.type === "element" && /\d+(\.\d+)?/.test(node.content) && node.content.length > 1) {
|
|
@@ -1152,12 +1223,13 @@ class TexNode {
|
|
|
1152
1223
|
return false;
|
|
1153
1224
|
}
|
|
1154
1225
|
};
|
|
1226
|
+
var should_wrap_in_braces = should_wrap_in_braces2;
|
|
1155
1227
|
let tokens = [];
|
|
1156
1228
|
const { base, sup, sub } = this.data;
|
|
1157
1229
|
tokens = tokens.concat(base.serialize());
|
|
1158
1230
|
if (sub) {
|
|
1159
1231
|
tokens.push(new TexToken(6 /* CONTROL */, "_"));
|
|
1160
|
-
if (
|
|
1232
|
+
if (should_wrap_in_braces2(sub)) {
|
|
1161
1233
|
tokens.push(new TexToken(0 /* ELEMENT */, "{"));
|
|
1162
1234
|
tokens = tokens.concat(sub.serialize());
|
|
1163
1235
|
tokens.push(new TexToken(0 /* ELEMENT */, "}"));
|
|
@@ -1167,7 +1239,7 @@ class TexNode {
|
|
|
1167
1239
|
}
|
|
1168
1240
|
if (sup) {
|
|
1169
1241
|
tokens.push(new TexToken(6 /* CONTROL */, "^"));
|
|
1170
|
-
if (
|
|
1242
|
+
if (should_wrap_in_braces2(sup)) {
|
|
1171
1243
|
tokens.push(new TexToken(0 /* ELEMENT */, "{"));
|
|
1172
1244
|
tokens = tokens.concat(sup.serialize());
|
|
1173
1245
|
tokens.push(new TexToken(0 /* ELEMENT */, "}"));
|
|
@@ -1184,11 +1256,10 @@ class TexNode {
|
|
|
1184
1256
|
let tokens = [];
|
|
1185
1257
|
const matrix = this.data;
|
|
1186
1258
|
tokens.push(new TexToken(1 /* COMMAND */, `\\begin{${this.content}}`));
|
|
1187
|
-
tokens.push(new TexToken(5 /* NEWLINE */,
|
|
1188
|
-
|
|
1189
|
-
for (let i = 0;i < matrix.length; i++) {
|
|
1259
|
+
tokens.push(new TexToken(5 /* NEWLINE */, "\n"));
|
|
1260
|
+
for (let i = 0; i < matrix.length; i++) {
|
|
1190
1261
|
const row = matrix[i];
|
|
1191
|
-
for (let j = 0;j < row.length; j++) {
|
|
1262
|
+
for (let j = 0; j < row.length; j++) {
|
|
1192
1263
|
const cell = row[j];
|
|
1193
1264
|
tokens = tokens.concat(cell.serialize());
|
|
1194
1265
|
if (j !== row.length - 1) {
|
|
@@ -1199,8 +1270,7 @@ class TexNode {
|
|
|
1199
1270
|
tokens.push(new TexToken(6 /* CONTROL */, "\\\\"));
|
|
1200
1271
|
}
|
|
1201
1272
|
}
|
|
1202
|
-
tokens.push(new TexToken(5 /* NEWLINE */,
|
|
1203
|
-
`));
|
|
1273
|
+
tokens.push(new TexToken(5 /* NEWLINE */, "\n"));
|
|
1204
1274
|
tokens.push(new TexToken(1 /* COMMAND */, `\\end{${this.content}}`));
|
|
1205
1275
|
return tokens;
|
|
1206
1276
|
}
|
|
@@ -1208,6 +1278,8 @@ class TexNode {
|
|
|
1208
1278
|
throw new Error("[TexNode.serialize] Unimplemented type: " + this.type);
|
|
1209
1279
|
}
|
|
1210
1280
|
}
|
|
1281
|
+
// whether the node is over high so that if it's wrapped in braces, \left and \right should be used.
|
|
1282
|
+
// e.g. \frac{1}{2} is over high, "2" is not.
|
|
1211
1283
|
isOverHigh() {
|
|
1212
1284
|
switch (this.type) {
|
|
1213
1285
|
case "element":
|
|
@@ -1220,6 +1292,7 @@ class TexNode {
|
|
|
1220
1292
|
if (this.content === "\\frac") {
|
|
1221
1293
|
return true;
|
|
1222
1294
|
}
|
|
1295
|
+
// fall through
|
|
1223
1296
|
case "unaryFunc":
|
|
1224
1297
|
case "ordgroup":
|
|
1225
1298
|
return this.args.some((n) => n.isOverHigh());
|
|
@@ -1232,10 +1305,8 @@ class TexNode {
|
|
|
1232
1305
|
return false;
|
|
1233
1306
|
}
|
|
1234
1307
|
}
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
type;
|
|
1238
|
-
value;
|
|
1308
|
+
};
|
|
1309
|
+
var TypstToken = class {
|
|
1239
1310
|
constructor(type, content) {
|
|
1240
1311
|
this.type = type;
|
|
1241
1312
|
this.value = content;
|
|
@@ -1288,14 +1359,10 @@ class TypstToken {
|
|
|
1288
1359
|
return this.value;
|
|
1289
1360
|
}
|
|
1290
1361
|
}
|
|
1291
|
-
}
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
content;
|
|
1296
|
-
args;
|
|
1297
|
-
data;
|
|
1298
|
-
options;
|
|
1362
|
+
};
|
|
1363
|
+
var TYPST_NONE = null;
|
|
1364
|
+
var TYPST_TRUE = true;
|
|
1365
|
+
var TypstNode = class {
|
|
1299
1366
|
constructor(type, content, args, data) {
|
|
1300
1367
|
this.type = type;
|
|
1301
1368
|
this.content = content;
|
|
@@ -1305,10 +1372,11 @@ class TypstNode {
|
|
|
1305
1372
|
setOptions(options) {
|
|
1306
1373
|
this.options = options;
|
|
1307
1374
|
}
|
|
1375
|
+
// Note that this is only shallow equality.
|
|
1308
1376
|
eq(other) {
|
|
1309
1377
|
return this.type === other.type && this.content === other.content;
|
|
1310
1378
|
}
|
|
1311
|
-
}
|
|
1379
|
+
};
|
|
1312
1380
|
|
|
1313
1381
|
// src/util.ts
|
|
1314
1382
|
function isalpha(char) {
|
|
@@ -1465,8 +1533,7 @@ function tokenize(latex) {
|
|
|
1465
1533
|
switch (firstChar) {
|
|
1466
1534
|
case "%": {
|
|
1467
1535
|
let newPos = pos + 1;
|
|
1468
|
-
while (newPos < latex.length && latex[newPos] !==
|
|
1469
|
-
`) {
|
|
1536
|
+
while (newPos < latex.length && latex[newPos] !== "\n") {
|
|
1470
1537
|
newPos += 1;
|
|
1471
1538
|
}
|
|
1472
1539
|
token = new TexToken(3 /* COMMENT */, latex.slice(pos + 1, newPos));
|
|
@@ -1481,20 +1548,16 @@ function tokenize(latex) {
|
|
|
1481
1548
|
token = new TexToken(6 /* CONTROL */, firstChar);
|
|
1482
1549
|
pos++;
|
|
1483
1550
|
break;
|
|
1484
|
-
case
|
|
1485
|
-
`:
|
|
1551
|
+
case "\n":
|
|
1486
1552
|
token = new TexToken(5 /* NEWLINE */, firstChar);
|
|
1487
1553
|
pos++;
|
|
1488
1554
|
break;
|
|
1489
1555
|
case "\r": {
|
|
1490
|
-
if (pos + 1 < latex.length && latex[pos + 1] ===
|
|
1491
|
-
|
|
1492
|
-
token = new TexToken(5 /* NEWLINE */, `
|
|
1493
|
-
`);
|
|
1556
|
+
if (pos + 1 < latex.length && latex[pos + 1] === "\n") {
|
|
1557
|
+
token = new TexToken(5 /* NEWLINE */, "\n");
|
|
1494
1558
|
pos += 2;
|
|
1495
1559
|
} else {
|
|
1496
|
-
token = new TexToken(5 /* NEWLINE */,
|
|
1497
|
-
`);
|
|
1560
|
+
token = new TexToken(5 /* NEWLINE */, "\n");
|
|
1498
1561
|
pos++;
|
|
1499
1562
|
}
|
|
1500
1563
|
break;
|
|
@@ -1561,61 +1624,51 @@ function tokenize(latex) {
|
|
|
1561
1624
|
}
|
|
1562
1625
|
return tokens;
|
|
1563
1626
|
}
|
|
1564
|
-
|
|
1565
|
-
class LatexParserError extends Error {
|
|
1627
|
+
var LatexParserError = class extends Error {
|
|
1566
1628
|
constructor(message) {
|
|
1567
1629
|
super(message);
|
|
1568
1630
|
this.name = "LatexParserError";
|
|
1569
1631
|
}
|
|
1570
|
-
}
|
|
1632
|
+
};
|
|
1571
1633
|
var SUB_SYMBOL = new TexToken(6 /* CONTROL */, "_");
|
|
1572
1634
|
var SUP_SYMBOL = new TexToken(6 /* CONTROL */, "^");
|
|
1573
|
-
|
|
1574
|
-
class LatexParser {
|
|
1575
|
-
space_sensitive;
|
|
1576
|
-
newline_sensitive;
|
|
1635
|
+
var LatexParser = class {
|
|
1577
1636
|
constructor(space_sensitive = false, newline_sensitive = true) {
|
|
1578
1637
|
this.space_sensitive = space_sensitive;
|
|
1579
1638
|
this.newline_sensitive = newline_sensitive;
|
|
1580
1639
|
}
|
|
1581
1640
|
parse(tokens) {
|
|
1641
|
+
const [tree, _] = this.parseGroup(tokens, 0, tokens.length);
|
|
1642
|
+
return tree;
|
|
1643
|
+
}
|
|
1644
|
+
parseGroup(tokens, start, end) {
|
|
1582
1645
|
const results = [];
|
|
1583
|
-
let pos =
|
|
1584
|
-
while (pos <
|
|
1585
|
-
const
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
if (res.type === "whitespace") {
|
|
1591
|
-
if (!this.space_sensitive && res.content.replace(/ /g, "").length === 0) {
|
|
1592
|
-
continue;
|
|
1593
|
-
}
|
|
1594
|
-
if (!this.newline_sensitive && res.content === `
|
|
1595
|
-
`) {
|
|
1596
|
-
continue;
|
|
1597
|
-
}
|
|
1646
|
+
let pos = start;
|
|
1647
|
+
while (pos < end) {
|
|
1648
|
+
const [res, newPos] = this.parseNextExpr(tokens, pos);
|
|
1649
|
+
pos = newPos;
|
|
1650
|
+
if (res.type === "whitespace") {
|
|
1651
|
+
if (!this.space_sensitive && res.content.replace(/ /g, "").length === 0) {
|
|
1652
|
+
continue;
|
|
1598
1653
|
}
|
|
1599
|
-
if (
|
|
1600
|
-
|
|
1654
|
+
if (!this.newline_sensitive && res.content === "\n") {
|
|
1655
|
+
continue;
|
|
1601
1656
|
}
|
|
1602
|
-
results2.push(res);
|
|
1603
1657
|
}
|
|
1604
|
-
if (
|
|
1605
|
-
|
|
1606
|
-
} else if (results2.length === 1) {
|
|
1607
|
-
return results2[0];
|
|
1608
|
-
} else {
|
|
1609
|
-
return new TexNode("ordgroup", "", results2);
|
|
1658
|
+
if (res.type === "control" && res.content === "&") {
|
|
1659
|
+
throw new LatexParserError("Unexpected & outside of an alignment");
|
|
1610
1660
|
}
|
|
1661
|
+
results.push(res);
|
|
1611
1662
|
}
|
|
1663
|
+
let node;
|
|
1612
1664
|
if (results.length === 0) {
|
|
1613
|
-
|
|
1665
|
+
node = EMPTY_NODE;
|
|
1614
1666
|
} else if (results.length === 1) {
|
|
1615
|
-
|
|
1667
|
+
node = results[0];
|
|
1616
1668
|
} else {
|
|
1617
|
-
|
|
1669
|
+
node = new TexNode("ordgroup", "", results);
|
|
1618
1670
|
}
|
|
1671
|
+
return [node, end + 1];
|
|
1619
1672
|
}
|
|
1620
1673
|
parseNextExpr(tokens, start) {
|
|
1621
1674
|
let [base, pos] = this.parseNextExprWithoutSupSub(tokens, start);
|
|
@@ -1653,7 +1706,7 @@ class LatexParser {
|
|
|
1653
1706
|
}
|
|
1654
1707
|
if (num_prime > 0) {
|
|
1655
1708
|
res.sup = new TexNode("ordgroup", "", []);
|
|
1656
|
-
for (let i = 0;i < num_prime; i++) {
|
|
1709
|
+
for (let i = 0; i < num_prime; i++) {
|
|
1657
1710
|
res.sup.args.push(new TexNode("element", "'"));
|
|
1658
1711
|
}
|
|
1659
1712
|
if (sup) {
|
|
@@ -1672,8 +1725,7 @@ class LatexParser {
|
|
|
1672
1725
|
}
|
|
1673
1726
|
parseNextExprWithoutSupSub(tokens, start) {
|
|
1674
1727
|
const firstToken = tokens[start];
|
|
1675
|
-
|
|
1676
|
-
switch (tokenType) {
|
|
1728
|
+
switch (firstToken.type) {
|
|
1677
1729
|
case 0 /* ELEMENT */:
|
|
1678
1730
|
return [new TexNode("element", firstToken.value), start + 1];
|
|
1679
1731
|
case 2 /* TEXT */:
|
|
@@ -1699,8 +1751,7 @@ class LatexParser {
|
|
|
1699
1751
|
if (posClosingBracket === -1) {
|
|
1700
1752
|
throw new LatexParserError("Unmatched '{'");
|
|
1701
1753
|
}
|
|
1702
|
-
|
|
1703
|
-
return [this.parse(exprInside), posClosingBracket + 1];
|
|
1754
|
+
return this.parseGroup(tokens, start + 1, posClosingBracket);
|
|
1704
1755
|
case "}":
|
|
1705
1756
|
throw new LatexParserError("Unmatched '}'");
|
|
1706
1757
|
case "\\\\":
|
|
@@ -1743,8 +1794,7 @@ class LatexParser {
|
|
|
1743
1794
|
if (posRightSquareBracket === -1) {
|
|
1744
1795
|
throw new LatexParserError("No matching right square bracket for [");
|
|
1745
1796
|
}
|
|
1746
|
-
const
|
|
1747
|
-
const exponent = this.parse(exprInside);
|
|
1797
|
+
const [exponent, _] = this.parseGroup(tokens, posLeftSquareBracket + 1, posRightSquareBracket);
|
|
1748
1798
|
const [arg12, newPos2] = this.parseNextExprWithoutSupSub(tokens, posRightSquareBracket + 1);
|
|
1749
1799
|
return [new TexNode("unaryFunc", command, [arg12], exponent), newPos2];
|
|
1750
1800
|
} else if (command === "\\text") {
|
|
@@ -1797,8 +1847,7 @@ class LatexParser {
|
|
|
1797
1847
|
throw new LatexParserError("Invalid delimiter after \\right");
|
|
1798
1848
|
}
|
|
1799
1849
|
pos++;
|
|
1800
|
-
const
|
|
1801
|
-
const body = this.parse(exprInside);
|
|
1850
|
+
const [body, _] = this.parseGroup(tokens, exprInsideStart, exprInsideEnd);
|
|
1802
1851
|
const args = [
|
|
1803
1852
|
new TexNode("element", leftDelimiter.value),
|
|
1804
1853
|
body,
|
|
@@ -1852,8 +1901,7 @@ class LatexParser {
|
|
|
1852
1901
|
if (!this.space_sensitive && res.content.replace(/ /g, "").length === 0) {
|
|
1853
1902
|
continue;
|
|
1854
1903
|
}
|
|
1855
|
-
if (!this.newline_sensitive && res.content ===
|
|
1856
|
-
`) {
|
|
1904
|
+
if (!this.newline_sensitive && res.content === "\n") {
|
|
1857
1905
|
continue;
|
|
1858
1906
|
}
|
|
1859
1907
|
}
|
|
@@ -1871,11 +1919,11 @@ class LatexParser {
|
|
|
1871
1919
|
}
|
|
1872
1920
|
return allRows;
|
|
1873
1921
|
}
|
|
1874
|
-
}
|
|
1922
|
+
};
|
|
1875
1923
|
function passIgnoreWhitespaceBeforeScriptMark(tokens) {
|
|
1876
1924
|
const is_script_mark = (token) => token.eq(SUB_SYMBOL) || token.eq(SUP_SYMBOL);
|
|
1877
1925
|
let out_tokens = [];
|
|
1878
|
-
for (let i = 0;i < tokens.length; i++) {
|
|
1926
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
1879
1927
|
if (tokens[i].type === 4 /* SPACE */ && i + 1 < tokens.length && is_script_mark(tokens[i + 1])) {
|
|
1880
1928
|
continue;
|
|
1881
1929
|
}
|
|
@@ -1899,52 +1947,102 @@ function passExpandCustomTexMacros(tokens, customTexMacros) {
|
|
|
1899
1947
|
return out_tokens;
|
|
1900
1948
|
}
|
|
1901
1949
|
function parseTex(tex, customTexMacros) {
|
|
1902
|
-
const parser = new LatexParser;
|
|
1950
|
+
const parser = new LatexParser();
|
|
1903
1951
|
let tokens = tokenize(tex);
|
|
1904
1952
|
tokens = passIgnoreWhitespaceBeforeScriptMark(tokens);
|
|
1905
1953
|
tokens = passExpandCustomTexMacros(tokens, customTexMacros);
|
|
1906
1954
|
return parser.parse(tokens);
|
|
1907
1955
|
}
|
|
1908
1956
|
|
|
1957
|
+
// src/typst-shorthands.ts
|
|
1958
|
+
var shorthandMap = /* @__PURE__ */ new Map([
|
|
1959
|
+
["arrow.l.r.double.long", "<==>"],
|
|
1960
|
+
["arrow.l.r.long", "<-->"],
|
|
1961
|
+
["arrow.r.bar", "|->"],
|
|
1962
|
+
["arrow.r.double.bar", "|=>"],
|
|
1963
|
+
["arrow.r.double.long", "==>"],
|
|
1964
|
+
["arrow.r.long", "-->"],
|
|
1965
|
+
["arrow.r.long.squiggly", "~~>"],
|
|
1966
|
+
["arrow.r.tail", ">->"],
|
|
1967
|
+
["arrow.r.twohead", "->>"],
|
|
1968
|
+
["arrow.l.double.long", "<=="],
|
|
1969
|
+
["arrow.l.long", "<--"],
|
|
1970
|
+
["arrow.l.long.squiggly", "<~~"],
|
|
1971
|
+
["arrow.l.tail", "<-<"],
|
|
1972
|
+
["arrow.l.twohead", "<<-"],
|
|
1973
|
+
["arrow.l.r", "<->"],
|
|
1974
|
+
["arrow.l.r.double", "<=>"],
|
|
1975
|
+
["colon.double.eq", "::="],
|
|
1976
|
+
["dots.h", "..."],
|
|
1977
|
+
["gt.triple", ">>>"],
|
|
1978
|
+
["lt.triple", "<<<"],
|
|
1979
|
+
["arrow.r", "->"],
|
|
1980
|
+
["arrow.r.double", "=>"],
|
|
1981
|
+
["arrow.r.squiggly", "~>"],
|
|
1982
|
+
["arrow.l", "<-"],
|
|
1983
|
+
["arrow.l.squiggly", "<~"],
|
|
1984
|
+
["bar.v.double", "||"],
|
|
1985
|
+
["bracket.l.double", "[|"],
|
|
1986
|
+
["bracket.r.double", "|]"],
|
|
1987
|
+
["colon.eq", ":="],
|
|
1988
|
+
["eq.colon", "=:"],
|
|
1989
|
+
["eq.not", "!="],
|
|
1990
|
+
["gt.double", ">>"],
|
|
1991
|
+
["gt.eq", ">="],
|
|
1992
|
+
["lt.double", "<<"],
|
|
1993
|
+
["lt.eq", "<="],
|
|
1994
|
+
["ast.op", "*"],
|
|
1995
|
+
["minus", "-"],
|
|
1996
|
+
["tilde.op", "~"]
|
|
1997
|
+
]);
|
|
1998
|
+
var reverseShorthandMap = /* @__PURE__ */ new Map();
|
|
1999
|
+
for (const [key, value] of shorthandMap.entries()) {
|
|
2000
|
+
if (value.length > 1) {
|
|
2001
|
+
reverseShorthandMap.set(value, key);
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
|
|
1909
2005
|
// src/typst-writer.ts
|
|
1910
|
-
var TYPST_INTRINSIC_SYMBOLS = [
|
|
1911
|
-
"dim",
|
|
1912
|
-
"id",
|
|
1913
|
-
"im",
|
|
1914
|
-
"mod",
|
|
1915
|
-
"Pr",
|
|
1916
|
-
"sech",
|
|
1917
|
-
"csch"
|
|
1918
|
-
];
|
|
1919
2006
|
function is_delimiter(c) {
|
|
1920
|
-
return c.type === "atom" && ["(", ")", "[", "]", "{", "}", "|", "
|
|
2007
|
+
return c.type === "atom" && ["(", ")", "[", "]", "{", "}", "|", "\u230A", "\u230B", "\u2308", "\u2309"].includes(c.content);
|
|
1921
2008
|
}
|
|
1922
2009
|
var TYPST_LEFT_PARENTHESIS = new TypstToken(1 /* ELEMENT */, "(");
|
|
1923
2010
|
var TYPST_RIGHT_PARENTHESIS = new TypstToken(1 /* ELEMENT */, ")");
|
|
1924
2011
|
var TYPST_COMMA = new TypstToken(1 /* ELEMENT */, ",");
|
|
1925
|
-
var TYPST_NEWLINE = new TypstToken(0 /* SYMBOL */,
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
2012
|
+
var TYPST_NEWLINE = new TypstToken(0 /* SYMBOL */, "\n");
|
|
2013
|
+
function typst_primitive_to_string(value) {
|
|
2014
|
+
switch (typeof value) {
|
|
2015
|
+
case "string":
|
|
2016
|
+
return `"${value}"`;
|
|
2017
|
+
case "number":
|
|
2018
|
+
return value.toString();
|
|
2019
|
+
case "boolean":
|
|
2020
|
+
return value ? "#true" : "#false";
|
|
2021
|
+
default:
|
|
2022
|
+
if (value === null) {
|
|
2023
|
+
return "#none";
|
|
2024
|
+
} else if (value instanceof TypstToken) {
|
|
2025
|
+
return value.toString();
|
|
2026
|
+
}
|
|
2027
|
+
throw new TypstWriterError(`Invalid primitive value: ${value}`, value);
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
var TypstWriterError = class extends Error {
|
|
1930
2031
|
constructor(message, node) {
|
|
1931
2032
|
super(message);
|
|
1932
2033
|
this.name = "TypstWriterError";
|
|
1933
2034
|
this.node = node;
|
|
1934
2035
|
}
|
|
1935
|
-
}
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
this.nonStrict = nonStrict;
|
|
1946
|
-
this.preferTypstIntrinsic = preferTypstIntrinsic;
|
|
1947
|
-
this.keepSpaces = keepSpaces;
|
|
2036
|
+
};
|
|
2037
|
+
var TypstWriter = class {
|
|
2038
|
+
constructor(opt) {
|
|
2039
|
+
this.buffer = "";
|
|
2040
|
+
this.queue = [];
|
|
2041
|
+
this.insideFunctionDepth = 0;
|
|
2042
|
+
this.nonStrict = opt.nonStrict;
|
|
2043
|
+
this.preferShorthands = opt.preferShorthands;
|
|
2044
|
+
this.keepSpaces = opt.keepSpaces;
|
|
2045
|
+
this.inftyToOo = opt.inftyToOo;
|
|
1948
2046
|
}
|
|
1949
2047
|
writeBuffer(token) {
|
|
1950
2048
|
const str = token.toString();
|
|
@@ -1959,8 +2057,7 @@ class TypstWriter {
|
|
|
1959
2057
|
no_need_space ||= str === "'";
|
|
1960
2058
|
no_need_space ||= /[0-9]$/.test(this.buffer) && /^[0-9]/.test(str);
|
|
1961
2059
|
no_need_space ||= /[\(\[{]\s*(-|\+)$/.test(this.buffer) || this.buffer === "-" || this.buffer === "+";
|
|
1962
|
-
no_need_space ||= str.startsWith(
|
|
1963
|
-
`);
|
|
2060
|
+
no_need_space ||= str.startsWith("\n");
|
|
1964
2061
|
no_need_space ||= this.buffer === "";
|
|
1965
2062
|
no_need_space ||= /^\s/.test(str);
|
|
1966
2063
|
no_need_space ||= this.buffer.endsWith("&") && str === "=";
|
|
@@ -1971,6 +2068,7 @@ class TypstWriter {
|
|
|
1971
2068
|
}
|
|
1972
2069
|
this.buffer += str;
|
|
1973
2070
|
}
|
|
2071
|
+
// Serialize a tree of TypstNode into a list of TypstToken
|
|
1974
2072
|
serialize(node) {
|
|
1975
2073
|
switch (node.type) {
|
|
1976
2074
|
case "empty":
|
|
@@ -1983,9 +2081,19 @@ class TypstWriter {
|
|
|
1983
2081
|
}
|
|
1984
2082
|
break;
|
|
1985
2083
|
}
|
|
1986
|
-
case "symbol":
|
|
1987
|
-
|
|
2084
|
+
case "symbol": {
|
|
2085
|
+
let content = node.content;
|
|
2086
|
+
if (this.preferShorthands) {
|
|
2087
|
+
if (shorthandMap.has(content)) {
|
|
2088
|
+
content = shorthandMap.get(content);
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
if (this.inftyToOo && content === "infinity") {
|
|
2092
|
+
content = "oo";
|
|
2093
|
+
}
|
|
2094
|
+
this.queue.push(new TypstToken(0 /* SYMBOL */, content));
|
|
1988
2095
|
break;
|
|
2096
|
+
}
|
|
1989
2097
|
case "text":
|
|
1990
2098
|
this.queue.push(new TypstToken(2 /* TEXT */, node.content));
|
|
1991
2099
|
break;
|
|
@@ -1998,8 +2106,7 @@ class TypstWriter {
|
|
|
1998
2106
|
if (this.keepSpaces) {
|
|
1999
2107
|
this.queue.push(new TypstToken(4 /* SPACE */, c));
|
|
2000
2108
|
}
|
|
2001
|
-
} else if (c ===
|
|
2002
|
-
`) {
|
|
2109
|
+
} else if (c === "\n") {
|
|
2003
2110
|
this.queue.push(new TypstToken(0 /* SYMBOL */, c));
|
|
2004
2111
|
} else {
|
|
2005
2112
|
throw new TypstWriterError(`Unexpected whitespace character: ${c}`, node);
|
|
@@ -2038,7 +2145,7 @@ class TypstWriter {
|
|
|
2038
2145
|
this.queue.push(func_symbol);
|
|
2039
2146
|
this.insideFunctionDepth++;
|
|
2040
2147
|
this.queue.push(TYPST_LEFT_PARENTHESIS);
|
|
2041
|
-
for (let i = 0;i < node.args.length; i++) {
|
|
2148
|
+
for (let i = 0; i < node.args.length; i++) {
|
|
2042
2149
|
this.serialize(node.args[i]);
|
|
2043
2150
|
if (i < node.args.length - 1) {
|
|
2044
2151
|
this.queue.push(new TypstToken(1 /* ELEMENT */, ","));
|
|
@@ -2046,7 +2153,8 @@ class TypstWriter {
|
|
|
2046
2153
|
}
|
|
2047
2154
|
if (node.options) {
|
|
2048
2155
|
for (const [key, value] of Object.entries(node.options)) {
|
|
2049
|
-
|
|
2156
|
+
const value_str = typst_primitive_to_string(value);
|
|
2157
|
+
this.queue.push(new TypstToken(0 /* SYMBOL */, `, ${key}: ${value_str}`));
|
|
2050
2158
|
}
|
|
2051
2159
|
}
|
|
2052
2160
|
this.queue.push(TYPST_RIGHT_PARENTHESIS);
|
|
@@ -2094,7 +2202,8 @@ class TypstWriter {
|
|
|
2094
2202
|
this.queue.push(TYPST_LEFT_PARENTHESIS);
|
|
2095
2203
|
if (node.options) {
|
|
2096
2204
|
for (const [key, value] of Object.entries(node.options)) {
|
|
2097
|
-
|
|
2205
|
+
const value_str = typst_primitive_to_string(value);
|
|
2206
|
+
this.queue.push(new TypstToken(0 /* SYMBOL */, `${key}: ${value_str}, `));
|
|
2098
2207
|
}
|
|
2099
2208
|
}
|
|
2100
2209
|
matrix.forEach((row, i) => {
|
|
@@ -2145,7 +2254,7 @@ class TypstWriter {
|
|
|
2145
2254
|
}
|
|
2146
2255
|
flushQueue() {
|
|
2147
2256
|
const SOFT_SPACE = new TypstToken(6 /* CONTROL */, " ");
|
|
2148
|
-
for (let i = 0;i < this.queue.length; i++) {
|
|
2257
|
+
for (let i = 0; i < this.queue.length; i++) {
|
|
2149
2258
|
let token = this.queue[i];
|
|
2150
2259
|
if (token.eq(SOFT_SPACE)) {
|
|
2151
2260
|
if (i === this.queue.length - 1) {
|
|
@@ -2183,9 +2292,19 @@ class TypstWriter {
|
|
|
2183
2292
|
}
|
|
2184
2293
|
return this.buffer;
|
|
2185
2294
|
}
|
|
2186
|
-
}
|
|
2295
|
+
};
|
|
2187
2296
|
|
|
2188
2297
|
// src/convert.ts
|
|
2298
|
+
var TYPST_INTRINSIC_SYMBOLS = [
|
|
2299
|
+
"dim",
|
|
2300
|
+
"id",
|
|
2301
|
+
"im",
|
|
2302
|
+
"mod",
|
|
2303
|
+
"Pr",
|
|
2304
|
+
"sech",
|
|
2305
|
+
"csch"
|
|
2306
|
+
// 'sgn
|
|
2307
|
+
];
|
|
2189
2308
|
function tex_token_to_typst(token) {
|
|
2190
2309
|
if (/^[a-zA-Z0-9]$/.test(token)) {
|
|
2191
2310
|
return token;
|
|
@@ -2228,12 +2347,21 @@ function convert_overset(node, options) {
|
|
|
2228
2347
|
if (is_def(sup) && is_eq(base)) {
|
|
2229
2348
|
return new TypstNode("symbol", "eq.def");
|
|
2230
2349
|
}
|
|
2231
|
-
const op_call = new TypstNode(
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
base
|
|
2235
|
-
|
|
2236
|
-
});
|
|
2350
|
+
const op_call = new TypstNode(
|
|
2351
|
+
"funcCall",
|
|
2352
|
+
"op",
|
|
2353
|
+
[convert_tex_node_to_typst(base, options)]
|
|
2354
|
+
);
|
|
2355
|
+
op_call.setOptions({ limits: TYPST_TRUE });
|
|
2356
|
+
return new TypstNode(
|
|
2357
|
+
"supsub",
|
|
2358
|
+
"",
|
|
2359
|
+
[],
|
|
2360
|
+
{
|
|
2361
|
+
base: op_call,
|
|
2362
|
+
sup: convert_tex_node_to_typst(sup, options)
|
|
2363
|
+
}
|
|
2364
|
+
);
|
|
2237
2365
|
}
|
|
2238
2366
|
function convert_tex_node_to_typst(node, options = {}) {
|
|
2239
2367
|
switch (node.type) {
|
|
@@ -2242,7 +2370,11 @@ function convert_tex_node_to_typst(node, options = {}) {
|
|
|
2242
2370
|
case "whitespace":
|
|
2243
2371
|
return new TypstNode("whitespace", node.content);
|
|
2244
2372
|
case "ordgroup":
|
|
2245
|
-
return new TypstNode(
|
|
2373
|
+
return new TypstNode(
|
|
2374
|
+
"group",
|
|
2375
|
+
"",
|
|
2376
|
+
node.args.map((n) => convert_tex_node_to_typst(n, options))
|
|
2377
|
+
);
|
|
2246
2378
|
case "element":
|
|
2247
2379
|
return new TypstNode("atom", tex_token_to_typst(node.content));
|
|
2248
2380
|
case "symbol":
|
|
@@ -2254,9 +2386,17 @@ function convert_tex_node_to_typst(node, options = {}) {
|
|
|
2254
2386
|
case "supsub": {
|
|
2255
2387
|
let { base, sup, sub } = node.data;
|
|
2256
2388
|
if (base && base.type === "unaryFunc" && base.content === "\\overbrace" && sup) {
|
|
2257
|
-
return new TypstNode(
|
|
2389
|
+
return new TypstNode(
|
|
2390
|
+
"funcCall",
|
|
2391
|
+
"overbrace",
|
|
2392
|
+
[convert_tex_node_to_typst(base.args[0], options), convert_tex_node_to_typst(sup, options)]
|
|
2393
|
+
);
|
|
2258
2394
|
} else if (base && base.type === "unaryFunc" && base.content === "\\underbrace" && sub) {
|
|
2259
|
-
return new TypstNode(
|
|
2395
|
+
return new TypstNode(
|
|
2396
|
+
"funcCall",
|
|
2397
|
+
"underbrace",
|
|
2398
|
+
[convert_tex_node_to_typst(base.args[0], options), convert_tex_node_to_typst(sub, options)]
|
|
2399
|
+
);
|
|
2260
2400
|
}
|
|
2261
2401
|
const data = {
|
|
2262
2402
|
base: convert_tex_node_to_typst(base, options)
|
|
@@ -2274,7 +2414,11 @@ function convert_tex_node_to_typst(node, options = {}) {
|
|
|
2274
2414
|
}
|
|
2275
2415
|
case "leftright": {
|
|
2276
2416
|
const [left, body, right] = node.args;
|
|
2277
|
-
const group = new TypstNode(
|
|
2417
|
+
const group = new TypstNode(
|
|
2418
|
+
"group",
|
|
2419
|
+
"",
|
|
2420
|
+
node.args.map((n) => convert_tex_node_to_typst(n, options))
|
|
2421
|
+
);
|
|
2278
2422
|
if ([
|
|
2279
2423
|
"[]",
|
|
2280
2424
|
"()",
|
|
@@ -2292,7 +2436,11 @@ function convert_tex_node_to_typst(node, options = {}) {
|
|
|
2292
2436
|
group.args.shift();
|
|
2293
2437
|
return new TypstNode("funcCall", "lr", [group]);
|
|
2294
2438
|
}
|
|
2295
|
-
return new TypstNode(
|
|
2439
|
+
return new TypstNode(
|
|
2440
|
+
"funcCall",
|
|
2441
|
+
"lr",
|
|
2442
|
+
[group]
|
|
2443
|
+
);
|
|
2296
2444
|
}
|
|
2297
2445
|
case "binaryFunc": {
|
|
2298
2446
|
if (node.content === "\\overset") {
|
|
@@ -2300,20 +2448,40 @@ function convert_tex_node_to_typst(node, options = {}) {
|
|
|
2300
2448
|
}
|
|
2301
2449
|
if (node.content === "\\frac") {
|
|
2302
2450
|
if (options.fracToSlash) {
|
|
2303
|
-
return new TypstNode(
|
|
2451
|
+
return new TypstNode(
|
|
2452
|
+
"fraction",
|
|
2453
|
+
"",
|
|
2454
|
+
node.args.map((n) => convert_tex_node_to_typst(n, options))
|
|
2455
|
+
);
|
|
2304
2456
|
}
|
|
2305
2457
|
}
|
|
2306
|
-
return new TypstNode(
|
|
2458
|
+
return new TypstNode(
|
|
2459
|
+
"funcCall",
|
|
2460
|
+
tex_token_to_typst(node.content),
|
|
2461
|
+
node.args.map((n) => convert_tex_node_to_typst(n, options))
|
|
2462
|
+
);
|
|
2307
2463
|
}
|
|
2308
2464
|
case "unaryFunc": {
|
|
2309
2465
|
const arg0 = convert_tex_node_to_typst(node.args[0], options);
|
|
2310
2466
|
if (node.content === "\\sqrt" && node.data) {
|
|
2311
2467
|
const data = convert_tex_node_to_typst(node.data, options);
|
|
2312
|
-
return new TypstNode(
|
|
2468
|
+
return new TypstNode(
|
|
2469
|
+
"funcCall",
|
|
2470
|
+
"root",
|
|
2471
|
+
[data, arg0]
|
|
2472
|
+
);
|
|
2313
2473
|
}
|
|
2314
2474
|
if (node.content === "\\mathbf") {
|
|
2315
|
-
const inner = new TypstNode(
|
|
2316
|
-
|
|
2475
|
+
const inner = new TypstNode(
|
|
2476
|
+
"funcCall",
|
|
2477
|
+
"bold",
|
|
2478
|
+
[arg0]
|
|
2479
|
+
);
|
|
2480
|
+
return new TypstNode(
|
|
2481
|
+
"funcCall",
|
|
2482
|
+
"upright",
|
|
2483
|
+
[inner]
|
|
2484
|
+
);
|
|
2317
2485
|
}
|
|
2318
2486
|
if (node.content === "\\mathbb" && arg0.type === "atom" && /^[A-Z]$/.test(arg0.content)) {
|
|
2319
2487
|
return new TypstNode("symbol", arg0.content + arg0.content);
|
|
@@ -2327,21 +2495,55 @@ function convert_tex_node_to_typst(node, options = {}) {
|
|
|
2327
2495
|
if (TYPST_INTRINSIC_SYMBOLS.includes(text)) {
|
|
2328
2496
|
return new TypstNode("symbol", text);
|
|
2329
2497
|
} else {
|
|
2330
|
-
return new TypstNode(
|
|
2498
|
+
return new TypstNode(
|
|
2499
|
+
"funcCall",
|
|
2500
|
+
"op",
|
|
2501
|
+
[new TypstNode("text", text)]
|
|
2502
|
+
);
|
|
2331
2503
|
}
|
|
2332
2504
|
}
|
|
2333
|
-
return new TypstNode(
|
|
2505
|
+
return new TypstNode(
|
|
2506
|
+
"funcCall",
|
|
2507
|
+
tex_token_to_typst(node.content),
|
|
2508
|
+
node.args.map((n) => convert_tex_node_to_typst(n, options))
|
|
2509
|
+
);
|
|
2334
2510
|
}
|
|
2335
2511
|
case "beginend": {
|
|
2336
2512
|
const matrix = node.data;
|
|
2337
2513
|
const data = matrix.map((row) => row.map((n) => convert_tex_node_to_typst(n, options)));
|
|
2338
2514
|
if (node.content.startsWith("align")) {
|
|
2339
2515
|
return new TypstNode("align", "", [], data);
|
|
2340
|
-
}
|
|
2516
|
+
}
|
|
2517
|
+
if (node.content.endsWith("matrix")) {
|
|
2518
|
+
let delim = null;
|
|
2519
|
+
switch (node.content) {
|
|
2520
|
+
case "matrix":
|
|
2521
|
+
delim = TYPST_NONE;
|
|
2522
|
+
break;
|
|
2523
|
+
case "pmatrix":
|
|
2524
|
+
delim = "(";
|
|
2525
|
+
break;
|
|
2526
|
+
case "bmatrix":
|
|
2527
|
+
delim = "[";
|
|
2528
|
+
break;
|
|
2529
|
+
case "Bmatrix":
|
|
2530
|
+
delim = "{";
|
|
2531
|
+
break;
|
|
2532
|
+
case "vmatrix":
|
|
2533
|
+
delim = "|";
|
|
2534
|
+
break;
|
|
2535
|
+
case "Vmatrix": {
|
|
2536
|
+
delim = new TypstToken(0 /* SYMBOL */, "bar.v.double");
|
|
2537
|
+
break;
|
|
2538
|
+
}
|
|
2539
|
+
default:
|
|
2540
|
+
throw new TypstWriterError(`Unimplemented beginend: ${node.content}`, node);
|
|
2541
|
+
}
|
|
2341
2542
|
const res = new TypstNode("matrix", "", [], data);
|
|
2342
|
-
res.setOptions({ delim:
|
|
2543
|
+
res.setOptions({ "delim": delim });
|
|
2343
2544
|
return res;
|
|
2344
2545
|
}
|
|
2546
|
+
throw new TypstWriterError(`Unimplemented beginend: ${node.content}`, node);
|
|
2345
2547
|
}
|
|
2346
2548
|
case "unknownMacro":
|
|
2347
2549
|
return new TypstNode("unknown", tex_token_to_typst(node.content));
|
|
@@ -2413,8 +2615,10 @@ function convert_typst_node_to_tex(node) {
|
|
|
2413
2615
|
return new TexNode("element", node.content);
|
|
2414
2616
|
case "symbol":
|
|
2415
2617
|
switch (node.content) {
|
|
2618
|
+
// special hook for comma
|
|
2416
2619
|
case "comma":
|
|
2417
2620
|
return new TexNode("element", ",");
|
|
2621
|
+
// special hook for hyph and hyph.minus
|
|
2418
2622
|
case "hyph":
|
|
2419
2623
|
case "hyph.minus":
|
|
2420
2624
|
return new TexNode("text", "-");
|
|
@@ -2498,7 +2702,7 @@ function convert_typst_node_to_tex(node) {
|
|
|
2498
2702
|
if (node.options) {
|
|
2499
2703
|
if ("delim" in node.options) {
|
|
2500
2704
|
switch (node.options.delim) {
|
|
2501
|
-
case
|
|
2705
|
+
case TYPST_NONE:
|
|
2502
2706
|
return matrix;
|
|
2503
2707
|
case "[":
|
|
2504
2708
|
left_delim = "\\left[";
|
|
@@ -2559,6 +2763,8 @@ function convert_typst_node_to_tex(node) {
|
|
|
2559
2763
|
}
|
|
2560
2764
|
|
|
2561
2765
|
// src/typst-parser.ts
|
|
2766
|
+
var TYPST_EMPTY_NODE = new TypstNode("empty", "");
|
|
2767
|
+
var TYPST_SHORTHANDS = Array.from(reverseShorthandMap.keys());
|
|
2562
2768
|
function eat_primes2(tokens, start) {
|
|
2563
2769
|
let pos = start;
|
|
2564
2770
|
while (pos < tokens.length && tokens[pos].eq(new TypstToken(1 /* ELEMENT */, "'"))) {
|
|
@@ -2573,7 +2779,14 @@ function eat_identifier_name(typst, start) {
|
|
|
2573
2779
|
}
|
|
2574
2780
|
return typst.substring(start, pos);
|
|
2575
2781
|
}
|
|
2576
|
-
|
|
2782
|
+
function try_eat_shorthand(typst, start) {
|
|
2783
|
+
for (const shorthand of TYPST_SHORTHANDS) {
|
|
2784
|
+
if (typst.startsWith(shorthand, start)) {
|
|
2785
|
+
return shorthand;
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
return null;
|
|
2789
|
+
}
|
|
2577
2790
|
function tokenize_typst(typst) {
|
|
2578
2791
|
const tokens = [];
|
|
2579
2792
|
let pos = 0;
|
|
@@ -2587,20 +2800,16 @@ function tokenize_typst(typst) {
|
|
|
2587
2800
|
token = new TypstToken(6 /* CONTROL */, firstChar);
|
|
2588
2801
|
pos++;
|
|
2589
2802
|
break;
|
|
2590
|
-
case
|
|
2591
|
-
`:
|
|
2803
|
+
case "\n":
|
|
2592
2804
|
token = new TypstToken(7 /* NEWLINE */, firstChar);
|
|
2593
2805
|
pos++;
|
|
2594
2806
|
break;
|
|
2595
2807
|
case "\r": {
|
|
2596
|
-
if (pos + 1 < typst.length && typst[pos + 1] ===
|
|
2597
|
-
|
|
2598
|
-
token = new TypstToken(7 /* NEWLINE */, `
|
|
2599
|
-
`);
|
|
2808
|
+
if (pos + 1 < typst.length && typst[pos + 1] === "\n") {
|
|
2809
|
+
token = new TypstToken(7 /* NEWLINE */, "\n");
|
|
2600
2810
|
pos += 2;
|
|
2601
2811
|
} else {
|
|
2602
|
-
token = new TypstToken(7 /* NEWLINE */,
|
|
2603
|
-
`);
|
|
2812
|
+
token = new TypstToken(7 /* NEWLINE */, "\n");
|
|
2604
2813
|
pos++;
|
|
2605
2814
|
}
|
|
2606
2815
|
break;
|
|
@@ -2617,8 +2826,7 @@ function tokenize_typst(typst) {
|
|
|
2617
2826
|
case "/": {
|
|
2618
2827
|
if (pos < typst.length && typst[pos + 1] === "/") {
|
|
2619
2828
|
let newPos = pos + 2;
|
|
2620
|
-
while (newPos < typst.length && typst[newPos] !==
|
|
2621
|
-
`) {
|
|
2829
|
+
while (newPos < typst.length && typst[newPos] !== "\n") {
|
|
2622
2830
|
newPos++;
|
|
2623
2831
|
}
|
|
2624
2832
|
token = new TypstToken(3 /* COMMENT */, typst.slice(pos + 2, newPos));
|
|
@@ -2664,6 +2872,12 @@ function tokenize_typst(typst) {
|
|
|
2664
2872
|
break;
|
|
2665
2873
|
}
|
|
2666
2874
|
default: {
|
|
2875
|
+
const shorthand = try_eat_shorthand(typst, pos);
|
|
2876
|
+
if (shorthand !== null) {
|
|
2877
|
+
token = new TypstToken(0 /* SYMBOL */, reverseShorthandMap.get(shorthand));
|
|
2878
|
+
pos += shorthand.length;
|
|
2879
|
+
break;
|
|
2880
|
+
}
|
|
2667
2881
|
if (isdigit(firstChar)) {
|
|
2668
2882
|
let newPos = pos;
|
|
2669
2883
|
while (newPos < typst.length && isdigit(typst[newPos])) {
|
|
@@ -2730,7 +2944,7 @@ function find_closing_parenthesis(nodes, start) {
|
|
|
2730
2944
|
}
|
|
2731
2945
|
function primes(num) {
|
|
2732
2946
|
const res = [];
|
|
2733
|
-
for (let i = 0;i < num; i++) {
|
|
2947
|
+
for (let i = 0; i < num; i++) {
|
|
2734
2948
|
res.push(new TypstNode("atom", "'"));
|
|
2735
2949
|
}
|
|
2736
2950
|
return res;
|
|
@@ -2746,7 +2960,7 @@ function next_non_whitespace(nodes, start) {
|
|
|
2746
2960
|
function trim_whitespace_around_operators(nodes) {
|
|
2747
2961
|
let after_operator = false;
|
|
2748
2962
|
const res = [];
|
|
2749
|
-
for (let i = 0;i < nodes.length; i++) {
|
|
2963
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
2750
2964
|
const current = nodes[i];
|
|
2751
2965
|
if (current.type === "whitespace") {
|
|
2752
2966
|
if (after_operator) {
|
|
@@ -2820,13 +3034,12 @@ function process_operators(nodes, parenthesis = false) {
|
|
|
2820
3034
|
}
|
|
2821
3035
|
}
|
|
2822
3036
|
}
|
|
2823
|
-
|
|
2824
|
-
class TypstParserError extends Error {
|
|
3037
|
+
var TypstParserError = class extends Error {
|
|
2825
3038
|
constructor(message) {
|
|
2826
3039
|
super(message);
|
|
2827
3040
|
this.name = "TypstParserError";
|
|
2828
3041
|
}
|
|
2829
|
-
}
|
|
3042
|
+
};
|
|
2830
3043
|
var SUB_SYMBOL2 = new TypstToken(6 /* CONTROL */, "_");
|
|
2831
3044
|
var SUP_SYMBOL2 = new TypstToken(6 /* CONTROL */, "^");
|
|
2832
3045
|
var LEFT_PARENTHESES = new TypstToken(1 /* ELEMENT */, "(");
|
|
@@ -2838,10 +3051,7 @@ var RIGHT_CURLY_BRACKET2 = new TypstToken(1 /* ELEMENT */, "}");
|
|
|
2838
3051
|
var COMMA = new TypstToken(1 /* ELEMENT */, ",");
|
|
2839
3052
|
var SEMICOLON = new TypstToken(1 /* ELEMENT */, ";");
|
|
2840
3053
|
var SINGLE_SPACE = new TypstToken(4 /* SPACE */, " ");
|
|
2841
|
-
|
|
2842
|
-
class TypstParser {
|
|
2843
|
-
space_sensitive;
|
|
2844
|
-
newline_sensitive;
|
|
3054
|
+
var TypstParser = class {
|
|
2845
3055
|
constructor(space_sensitive = true, newline_sensitive = true) {
|
|
2846
3056
|
this.space_sensitive = space_sensitive;
|
|
2847
3057
|
this.newline_sensitive = newline_sensitive;
|
|
@@ -2860,8 +3070,7 @@ class TypstParser {
|
|
|
2860
3070
|
if (!this.space_sensitive && res.content.replace(/ /g, "").length === 0) {
|
|
2861
3071
|
continue;
|
|
2862
3072
|
}
|
|
2863
|
-
if (!this.newline_sensitive && res.content ===
|
|
2864
|
-
`) {
|
|
3073
|
+
if (!this.newline_sensitive && res.content === "\n") {
|
|
2865
3074
|
continue;
|
|
2866
3075
|
}
|
|
2867
3076
|
}
|
|
@@ -2956,10 +3165,12 @@ class TypstParser {
|
|
|
2956
3165
|
}
|
|
2957
3166
|
return [node, start + 1];
|
|
2958
3167
|
}
|
|
3168
|
+
// start: the position of the left parentheses
|
|
2959
3169
|
parseArguments(tokens, start) {
|
|
2960
3170
|
const end = find_closing_match2(tokens, start);
|
|
2961
3171
|
return [this.parseCommaSeparatedArguments(tokens, start + 1, end), end + 1];
|
|
2962
3172
|
}
|
|
3173
|
+
// start: the position of the left parentheses
|
|
2963
3174
|
parseGroupsOfArguments(tokens, start) {
|
|
2964
3175
|
const end = find_closing_match2(tokens, start);
|
|
2965
3176
|
tokens = tokens.slice(0, end);
|
|
@@ -2968,11 +3179,11 @@ class TypstParser {
|
|
|
2968
3179
|
let pos = start + 1;
|
|
2969
3180
|
while (pos < end) {
|
|
2970
3181
|
while (pos < end) {
|
|
2971
|
-
let
|
|
3182
|
+
let extract_named_params2 = function(arr) {
|
|
2972
3183
|
const COLON = new TypstNode("atom", ":");
|
|
2973
3184
|
const np2 = {};
|
|
2974
3185
|
const to_delete = [];
|
|
2975
|
-
for (let i = 0;i < arr.length; i++) {
|
|
3186
|
+
for (let i = 0; i < arr.length; i++) {
|
|
2976
3187
|
if (arr[i].type !== "group") {
|
|
2977
3188
|
continue;
|
|
2978
3189
|
}
|
|
@@ -2993,7 +3204,7 @@ class TypstParser {
|
|
|
2993
3204
|
if (g.args.length !== 4 || !g.args[pos_colon + 2].eq(new TypstNode("symbol", "none"))) {
|
|
2994
3205
|
throw new TypstParserError("Invalid number of arguments for delim");
|
|
2995
3206
|
}
|
|
2996
|
-
np2["delim"] =
|
|
3207
|
+
np2["delim"] = TYPST_NONE;
|
|
2997
3208
|
} else {
|
|
2998
3209
|
throw new TypstParserError("Not implemented for other types of delim");
|
|
2999
3210
|
}
|
|
@@ -3001,18 +3212,19 @@ class TypstParser {
|
|
|
3001
3212
|
throw new TypstParserError("Not implemented for other named parameters");
|
|
3002
3213
|
}
|
|
3003
3214
|
}
|
|
3004
|
-
for (let i = to_delete.length - 1;i >= 0; i--) {
|
|
3215
|
+
for (let i = to_delete.length - 1; i >= 0; i--) {
|
|
3005
3216
|
arr.splice(to_delete[i], 1);
|
|
3006
3217
|
}
|
|
3007
3218
|
return [arr, np2];
|
|
3008
3219
|
};
|
|
3220
|
+
var extract_named_params = extract_named_params2;
|
|
3009
3221
|
let next_stop = array_find(tokens, SEMICOLON, pos);
|
|
3010
3222
|
if (next_stop === -1) {
|
|
3011
3223
|
next_stop = end;
|
|
3012
3224
|
}
|
|
3013
3225
|
let row = this.parseCommaSeparatedArguments(tokens, pos, next_stop);
|
|
3014
3226
|
let np = {};
|
|
3015
|
-
[row, np] =
|
|
3227
|
+
[row, np] = extract_named_params2(row);
|
|
3016
3228
|
matrix.push(row);
|
|
3017
3229
|
Object.assign(named_params, np);
|
|
3018
3230
|
pos = next_stop + 1;
|
|
@@ -3020,6 +3232,7 @@ class TypstParser {
|
|
|
3020
3232
|
}
|
|
3021
3233
|
return [matrix, named_params, end + 1];
|
|
3022
3234
|
}
|
|
3235
|
+
// start: the position of the first token of arguments
|
|
3023
3236
|
parseCommaSeparatedArguments(tokens, start, end) {
|
|
3024
3237
|
const args = [];
|
|
3025
3238
|
let pos = start;
|
|
@@ -3046,17 +3259,19 @@ class TypstParser {
|
|
|
3046
3259
|
}
|
|
3047
3260
|
return args;
|
|
3048
3261
|
}
|
|
3049
|
-
}
|
|
3262
|
+
};
|
|
3050
3263
|
function parseTypst(typst) {
|
|
3051
|
-
const parser = new TypstParser;
|
|
3264
|
+
const parser = new TypstParser();
|
|
3052
3265
|
let tokens = tokenize_typst(typst);
|
|
3053
3266
|
return parser.parse(tokens);
|
|
3054
3267
|
}
|
|
3055
3268
|
|
|
3056
3269
|
// src/tex-writer.ts
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3270
|
+
var TexWriter = class {
|
|
3271
|
+
constructor() {
|
|
3272
|
+
this.buffer = "";
|
|
3273
|
+
this.queue = [];
|
|
3274
|
+
}
|
|
3060
3275
|
writeBuffer(token) {
|
|
3061
3276
|
const str = token.toString();
|
|
3062
3277
|
let no_need_space = false;
|
|
@@ -3095,7 +3310,7 @@ class TexWriter {
|
|
|
3095
3310
|
this.queue = this.queue.concat(node.serialize());
|
|
3096
3311
|
}
|
|
3097
3312
|
flushQueue() {
|
|
3098
|
-
for (let i = 0;i < this.queue.length; i++) {
|
|
3313
|
+
for (let i = 0; i < this.queue.length; i++) {
|
|
3099
3314
|
this.writeBuffer(this.queue[i]);
|
|
3100
3315
|
}
|
|
3101
3316
|
this.queue = [];
|
|
@@ -3104,46 +3319,41 @@ class TexWriter {
|
|
|
3104
3319
|
this.flushQueue();
|
|
3105
3320
|
return this.buffer;
|
|
3106
3321
|
}
|
|
3107
|
-
}
|
|
3322
|
+
};
|
|
3108
3323
|
|
|
3109
3324
|
// src/index.ts
|
|
3110
3325
|
function tex2typst(tex, options) {
|
|
3111
3326
|
const opt = {
|
|
3112
3327
|
nonStrict: true,
|
|
3113
3328
|
preferTypstIntrinsic: true,
|
|
3329
|
+
preferShorthands: true,
|
|
3114
3330
|
keepSpaces: false,
|
|
3115
3331
|
fracToSlash: true,
|
|
3332
|
+
inftyToOo: false,
|
|
3116
3333
|
customTexMacros: {}
|
|
3117
3334
|
};
|
|
3118
|
-
if (options) {
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
opt.preferTypstIntrinsic = options.preferTypstIntrinsic;
|
|
3124
|
-
}
|
|
3125
|
-
if (options.customTexMacros) {
|
|
3126
|
-
opt.customTexMacros = options.customTexMacros;
|
|
3127
|
-
}
|
|
3128
|
-
if (options.fracToSlash !== undefined) {
|
|
3129
|
-
opt.fracToSlash = options.fracToSlash;
|
|
3335
|
+
if (options !== void 0) {
|
|
3336
|
+
for (const key in opt) {
|
|
3337
|
+
if (options[key] !== void 0) {
|
|
3338
|
+
opt[key] = options[key];
|
|
3339
|
+
}
|
|
3130
3340
|
}
|
|
3131
3341
|
}
|
|
3132
3342
|
const texTree = parseTex(tex, opt.customTexMacros);
|
|
3133
3343
|
const typstTree = convert_tex_node_to_typst(texTree, opt);
|
|
3134
|
-
const writer = new TypstWriter(opt
|
|
3344
|
+
const writer = new TypstWriter(opt);
|
|
3135
3345
|
writer.serialize(typstTree);
|
|
3136
3346
|
return writer.finalize();
|
|
3137
3347
|
}
|
|
3138
3348
|
function typst2tex(typst) {
|
|
3139
3349
|
const typstTree = parseTypst(typst);
|
|
3140
3350
|
const texTree = convert_typst_node_to_tex(typstTree);
|
|
3141
|
-
const writer = new TexWriter;
|
|
3351
|
+
const writer = new TexWriter();
|
|
3142
3352
|
writer.append(texTree);
|
|
3143
3353
|
return writer.finalize();
|
|
3144
3354
|
}
|
|
3145
3355
|
export {
|
|
3146
|
-
|
|
3356
|
+
symbolMap,
|
|
3147
3357
|
tex2typst,
|
|
3148
|
-
|
|
3358
|
+
typst2tex
|
|
3149
3359
|
};
|