tex2typst 0.3.27-beta.1 → 0.3.28

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.
@@ -0,0 +1,412 @@
1
+ # Most test cases are from https://github.com/curvenote/tex-to-typst/blob/1d0b121d162911f1c99b47171939e30656f49270/tests/math.yml (MIT License)
2
+ title: integration-cases
3
+ cases:
4
+ - title: Integrals and vec
5
+ tex: '\nabla \cdot \vec{j}(p) = \lim_{v \rightarrow \{p\}} = \int \int_{S(v)} \frac{\vec{j} \cdot \vec{n}}{v} d S'
6
+ typst: nabla dot.op arrow(j)(p) = lim_(v arrow.r {p}) = integral integral_(S(v)) frac(arrow(j) dot.op arrow(n), v) d S
7
+ - title: Fractions and vectors
8
+ tex: '\frac{1}{4} \sum_{i = 1}^4 \boldsymbol{P}_i^\top \sqrt{v} \boldsymbol{\Sigma}^{-1} \sqrt{v} \boldsymbol{P}_i \boldsymbol{j} = \boldsymbol{D}^\top v \phi'
9
+ typst: frac(1, 4) sum_(i = 1)^4 bold(P)_i^top sqrt(v) bold(Sigma)^(-1) sqrt(v) bold(P)_i bold(j) = bold(D)^top v phi.alt
10
+
11
+
12
+ - title: Plus minus
13
+ tex: 'q = \pm I'
14
+ typst: q = plus.minus I
15
+ - title: Comma inside function
16
+ tex: '\boldsymbol{j_x, j_y}'
17
+ typst: 'bold(j_x comma j_y)'
18
+
19
+ - title: Nested functions
20
+ tex: '\boldsymbol{m}_\text{ref}'
21
+ typst: 'bold(m)_"ref"'
22
+ - title: left and right brackets
23
+ tex: '\left[\frac{1}{3} \right) \left\{b + \frac{1}{3} \right)'
24
+ typst: 'lr([1/3)) lr({b + 1/3))'
25
+ - title: left and right brackets, not overHigh
26
+ tex: '[\boldsymbol{A}) \{b)'
27
+ typst: 'lr([bold(A))) lr({b))'
28
+ - title: lr
29
+ tex: \left|a + \frac{1}{3} \right|^2
30
+ typst: lr(|a + frac(1, 3)|)^2
31
+ - title: should keep commas in lr, case 1
32
+ tex: \left[a, b, \frac{1}{2} \right\}
33
+ typst: lr([a, b, 1/2 })
34
+ - title: should keep commas in lr, case 2
35
+ tex: \left. a, b, \frac{1}{2} \right.
36
+ typst: lr(a, b, 1/2 )
37
+ - title: symmetry left right
38
+ tex: \{a\}(b) [c]
39
+ typst: '{a}(b) [c]'
40
+ - title: operatorname
41
+ tex: '\operatorname{diag} \text{diag}'
42
+ typst: 'op("diag") "diag"'
43
+ - title: scripts
44
+ tex: '\boldsymbol{k}_{A v} \boldsymbol{k}^{A v}'
45
+ typst: 'bold(k)_(A v) bold(k)^(A v)'
46
+ - title: scripts
47
+ tex: |-
48
+ \boldsymbol{D}
49
+ \\
50
+ \boldsymbol{G}_z
51
+ typst: |-
52
+ bold(D)
53
+ \
54
+ bold(G)_z
55
+ - title: Complex equations with nested over/under braces
56
+ tex: |-
57
+ \begin{aligned}
58
+ \overbrace{
59
+ [
60
+ \frac{1}{\Delta t}
61
+ \frac{\partial \boldsymbol{\theta}^{n + 1}}{\partial \boldsymbol{\psi}^{n + 1}}
62
+ - \boldsymbol{D}
63
+ \text{diag}(\boldsymbol{G} \boldsymbol{\psi}^{n + 1})
64
+ \frac{\partial \boldsymbol{k}_{A v}}{\partial \boldsymbol{\psi}^{n + 1}}
65
+ - \boldsymbol{D}
66
+ \text{diag}(\boldsymbol{k}_{A v}(\boldsymbol{\psi}^{n + 1}, \boldsymbol{m}))
67
+ \boldsymbol{G}
68
+ - \boldsymbol{G}_z
69
+ \frac{\partial \boldsymbol{k}_{A v}}{\partial \boldsymbol{\psi}^{n + 1}}
70
+ ]
71
+ }^{\boldsymbol{A}_0(\boldsymbol{\psi}^{n + 1})}
72
+ \frac{\partial \boldsymbol{\psi}^{n + 1}}{\partial \boldsymbol{m}}
73
+ \\
74
+ +
75
+ \underbrace{
76
+ [
77
+ -\frac{1}{\Delta t}
78
+ \frac{\partial \boldsymbol{\theta}^n}{\partial \boldsymbol{\psi}^n}
79
+ ]
80
+ }_{\boldsymbol{A}_{-1}(\boldsymbol{\psi}^n)}
81
+ \frac{\partial \boldsymbol{\psi}^n}{\partial \boldsymbol{m}}
82
+ =
83
+ \underbrace{
84
+ [
85
+ -\boldsymbol{D}
86
+ \text{diag}(\boldsymbol{G} \boldsymbol{\psi}^{n + 1})
87
+ \frac{\partial \boldsymbol{k}_{A v}}{\partial \boldsymbol{m}}
88
+ - \boldsymbol{G}_z
89
+ \frac{\partial \boldsymbol{k}_{A v}}{\partial \boldsymbol{m}}
90
+ ]
91
+ }_{\boldsymbol{B}(\psi^{n + 1})} &
92
+ \end{aligned}
93
+ typst: |-
94
+ overbrace(
95
+ [
96
+ frac(1, Delta t)
97
+ frac(diff bold(theta)^(n + 1), diff bold(psi)^(n + 1))
98
+ - bold(D)
99
+ "diag"(bold(G) bold(psi)^(n + 1))
100
+ frac(diff bold(k)_(A v), diff bold(psi)^(n + 1))
101
+ - bold(D)
102
+ "diag"(bold(k)_(A v)(bold(psi)^(n + 1), bold(m)))
103
+ bold(G)
104
+ - bold(G)_z
105
+ frac(diff bold(k)_(A v), diff bold(psi)^(n + 1))
106
+ ]
107
+ , bold(A)_0 (bold(psi)^(n + 1)))
108
+ frac(diff bold(psi)^(n + 1), diff bold(m))
109
+ \
110
+ +
111
+ underbrace(
112
+ [
113
+ -frac(1, Delta t)
114
+ frac(diff bold(theta)^n, diff bold(psi)^n)
115
+ ]
116
+ , bold(A)_(-1)(bold(psi)^n))
117
+ frac(diff bold(psi)^n, diff bold(m))
118
+ =
119
+ underbrace(
120
+ [
121
+ -bold(D)
122
+ "diag"(bold(G) bold(psi)^(n + 1))
123
+ frac(diff bold(k)_(A v), diff bold(m))
124
+ - bold(G)_z
125
+ frac(diff bold(k)_(A v), diff bold(m))
126
+ ]
127
+ , bold(B)(psi^(n + 1))) &
128
+ # - title: leading underscore
129
+ # tex: _2
130
+ # typst: '""_2'
131
+ # - title: leading power
132
+ # tex: '^{\text{st}}'
133
+ # typst: '""^"st"'
134
+ - title: greater than
135
+ tex: 'a \ge b'
136
+ typst: a gt.eq b
137
+ - title: ddot
138
+ tex: 'q, \dot{q}, \ddot{q}'
139
+ typst: q, dot(q), dot.double(q)
140
+ - title: brackets
141
+ tex: '\frac{1}{\tau(X_2)}'
142
+ typst: 'frac(1, tau(X_2))'
143
+ - title: bar and nested bb
144
+ tex: '\mathbb{\bar{R}}'
145
+ typst: 'bb(macron(R))'
146
+ - title: Underscore with no content
147
+ tex: 'P_{}^1'
148
+ typst: 'P_()^1'
149
+ - title: Simple overbrace
150
+ tex: '\overbrace{a}^b'
151
+ typst: 'overbrace(a, b)'
152
+ - title: underbrace
153
+ tex: '\underbrace{a}_b'
154
+ typst: underbrace(a, b)
155
+ - title: Test
156
+ tex: a^{b^{n + 1}}
157
+ typst: a^(b^(n + 1))
158
+ - title: Test2
159
+ tex: a + b^1 + \frac{2}{3} + \overbrace{123}^b
160
+ typst: a + b^1 + frac(2, 3) + overbrace(123, b)
161
+ - title: Symbols
162
+ tex: '\alpha \nabla \partial'
163
+ typst: alpha nabla diff
164
+ - title: Test3
165
+ tex: \boldsymbol{x}
166
+ typst: bold(x)
167
+ - title: Test4
168
+ tex: a^2 + b^2 = c^2
169
+ typst: a^2 + b^2 = c^2
170
+ - title: Euler Complex Exponential
171
+ tex: e^{i \theta} = \cos \theta + i \sin \theta
172
+ typst: e^(i theta) = cos theta + i sin theta
173
+ - title: Euler Product
174
+ tex: \prod_p \frac{1}{1 - p^{-s}} = \sum_{n = 1}^\infty \frac{1}{n^s}
175
+ typst: product_p frac(1, 1 - p^(-s)) = sum_(n = 1)^infinity 1/n^s
176
+ - title: Test7
177
+ tex: (a + b)^2
178
+ typst: (a + b)^2
179
+ - title: leading minus sign
180
+ tex: a^{-s}
181
+ typst: a^(-s)
182
+ - title: Test8
183
+ tex: \sqrt{\frac{1}{x^2 + y^2}}
184
+ typst: sqrt(frac(1, x^2 + y^2))
185
+ - title: basic prime case
186
+ tex: y'
187
+ typst: y'
188
+ - title: has both prime and subscript
189
+ tex: y'_2 + y'_{a_1} + \theta'_1
190
+ typst: y'_2 + y'_(a_1) + theta'_1
191
+
192
+
193
+ - title: Horizontal space symbols
194
+ tex: "\\, \\: \\; \\quad"
195
+ typst: thin med thick quad
196
+ - title: spaces around text
197
+ tex: i_D = \mu_n C_\text{ox} \frac{W}{L} [ (v_\text{GS} - V_t) v_\text{DS} - \frac{1}{2} v_\text{DS}^2 ]
198
+ typst: i_D = mu_n C_"ox" frac(W, L) [ (v_"GS" - V_t) v_"DS" - frac(1, 2) v_"DS"^2 ]
199
+ - title: base is group wrapped in brackets
200
+ tex: e = \lim_{n \rightarrow \infty} \left(1 + \frac{1}{n} \right)^n
201
+ typst: e = lim_(n arrow.r infinity) (1 + frac(1, n))^n
202
+
203
+ - title: fraction1
204
+ tex: \frac{1}{2}
205
+ typst: 1/2
206
+ - title: fraction2
207
+ tex: \frac{1}{2} + 3
208
+ typst: 1 / 2 + 3
209
+ - title: fraction3
210
+ tex: 1 + \frac{1}{2} + 3
211
+ typst: 1 + 1 / 2 + 3
212
+ - title: fraction4
213
+ tex: \frac{5 + 6}{4} + 8
214
+ typst: (5 + 6) / 4 + 8
215
+ - title: fraction5
216
+ tex: \frac{1 + 4}{5 + 6 + 7}
217
+ typst: (1 + 4)/(5 + 6 + 7)
218
+ - title: fraction6
219
+ tex: \sin x = \frac{e^{i x} - e^{-i x}}{2 i}
220
+ typst: sin x = (e^(i x) - e^(-i x))/(2 i)
221
+ - title: fraction7
222
+ tex: \frac{1}{\frac{1}{2}}
223
+ typst: 1/(1/2)
224
+ - title: parenthesis1
225
+ tex: \text{diag}(\boldsymbol{k}_{A v}(\boldsymbol{\psi}^{n + 1}, \boldsymbol{m}))
226
+ typst: '"diag"(bold(k)_(A v)(bold(psi)^(n + 1), bold(m)))'
227
+ - title: base of natural logarithm
228
+ tex: e \overset{\text{def}}{=} \lim_{n \rightarrow \infty} \left(1 + \frac{1}{n} \right)^n
229
+ typst: e eq.def lim_(n arrow.r infinity) (1 + frac(1, n))^n
230
+ - title: base of natural logarithm (shorthands)
231
+ tex: e \overset{\text{def}}{=} \lim_{n \rightarrow \infty} \left(1 + \frac{1}{n} \right)^n
232
+ typst: e eq.def lim_(n -> infinity) (1 + 1/n)^n
233
+ - title: Euler's product formula
234
+ tex: \prod_p \frac{1}{1 - p^{-s}} = \sum_{n = 1}^\infty \frac{1}{n^s}
235
+ typst: product_p frac(1, 1 - p^(-s)) = sum_(n = 1)^(infinity) frac(1, n^s)
236
+ - title: Fermat's little theorem
237
+ tex: a^{p - 1} \equiv 1 \mod p
238
+ typst: a^(p - 1) equiv 1 mod p
239
+ - title: Maxwell's equations
240
+ tex: |-
241
+ \begin{aligned}
242
+ \nabla \times \boldsymbol{H} &= \boldsymbol{J} + \frac{\partial \boldsymbol{D}}{\partial t} \\
243
+ \nabla \times \boldsymbol{E} &= - \frac{\partial \boldsymbol{B}}{\partial t} \\
244
+ \nabla \cdot \boldsymbol{B} &= 0 \\
245
+ \nabla \cdot \boldsymbol{D} &= \rho
246
+ \end{aligned}
247
+ typst: |-
248
+ nabla times bold(H) &= bold(J) + frac(diff bold(D), diff t) \
249
+ nabla times bold(E) &= - frac(diff bold(B), diff t) \
250
+ nabla dot.op bold(B) &= 0 \
251
+ nabla dot.op bold(D) &= rho
252
+ - title: Chen's inequality
253
+ tex: \yen 2000 > \$ 3000
254
+ typst: yen 2000 > \$ 3000
255
+ - title: harmonic series
256
+ tex: \sum_{k = 1}^n \frac{1}{k} = \ln n + \gamma + O(\frac{1}{n})
257
+ typst: sum_(k = 1)^n frac(1, k) = ln n + gamma + O(frac(1, n))
258
+ - title: Euler's complex exponential formula
259
+ tex: e^{i x} = \cos x + i \sin x
260
+ typst: e^(i x) = cos x + i sin x
261
+ - title: Gauss's divergence theorem
262
+ tex: \iiint_\Omega \operatorname{div}(\vec{F}) \mathrm{d} V = \oiint_{\partial \Omega} \vec{F} \cdot \mathrm{d} \vec{S}
263
+ typst: integral.triple_Omega op("div")(arrow(F)) dif V = integral.surf_(diff Omega) arrow(F) dot.op dif arrow(S)
264
+ - title: Stokes' theorem
265
+ tex: \iint_\Sigma \operatorname{curl}(\vec{F}) \cdot \mathrm{d} \vec{S} = \oint_{\partial \Sigma} \vec{F} \times \mathrm{d} \vec{l}
266
+ typst: integral.double_Sigma op("curl")(arrow(F)) dot.op dif arrow(S) = integral.cont_(diff Sigma) arrow(F) times dif arrow(l)
267
+ # - title: Black-Scholes formula for option pricing
268
+ # tex: |-
269
+ # \begin{aligned}
270
+ # C &= N(d_1) S_t - N(d_2) K e^{-r t} \\
271
+ # d_1 &= \frac{\ln \frac{S_t}{K} + (r + \frac{\sigma^2}{2}) t}{\sigma \sqrt{t}} \\
272
+ # d_2 &= d_1 - \sigma \sqrt{t}
273
+ # \end{aligned}
274
+ # typst: |-
275
+ # C &= N(d_1) S_t - N(d_2) K e^(-r t) \
276
+ # d_1 &= frac(ln frac(S_t, K) + (r + frac(sigma^2, 2)) t, sigma sqrt(t)) \
277
+ # d_2 &= d_1 - sigma sqrt(t)
278
+ - title: Cauchy's integral formula
279
+ tex: f(z_0) = \frac{1}{2 \pi \mathrm{i}} \oint_C \frac{f(z)}{z - z_0} \mathrm{d} z
280
+ typst: f(z_0) = frac(1, 2 pi upright(i)) integral.cont_C frac(f(z), z - z_0) dif z
281
+ - title: determinant of a Vandermonde matrix
282
+ tex: |-
283
+ \begin{vmatrix}
284
+ 1 & 1 & \dots & 1 \\
285
+ x_1 & x_2 & \dots & x_n \\
286
+ x_1^2 & x_2^2 & \dots & x_n^2 \\
287
+ \vdots & \vdots & \ddots & \vdots \\
288
+ x_1^{n - 1} & x_2^{n - 1} & \dots & x_n^{n - 1}
289
+ \end{vmatrix}
290
+ = \prod_{1 \le i < j \le n} (x_j - x_i)
291
+ typst: |-
292
+ mat(delim: "|", 1, 1, dots.h, 1;
293
+ x_1, x_2, dots.h, x_n;
294
+ x_1^2, x_2^2, dots.h, x_n^2;
295
+ dots.v, dots.v, dots.down, dots.v;
296
+ x_1^(n - 1), x_2^(n - 1), dots.h, x_n^(n - 1))
297
+ = product_(1 lt.eq i < j lt.eq n) (x_j - x_i)
298
+ - title: hyph
299
+ tex: a \text{-} b
300
+ typst: a hyph b
301
+ - title: hyph.minus
302
+ tex: a \text{-} b
303
+ typst: a hyph.minus b
304
+ - title: backslash not in the end
305
+ tex: a \\ b
306
+ typst: a \ b
307
+ - title: number
308
+ tex: 134 + 3.14
309
+ typst: 134 + 3.14
310
+ - title: number in subscript
311
+ tex: a_{23}
312
+ typst: a_(23)
313
+ - title: number in superscript
314
+ tex: a^{23}
315
+ typst: a^(23)
316
+ - title: matrixes
317
+ tex: |-
318
+ \begin{bmatrix}
319
+ a_x & a_1 \\ a_1 & a_x
320
+ \end{bmatrix} + \begin{bmatrix}
321
+ a_y & a_2 \\ a_2 & a_y
322
+ \end{bmatrix}
323
+ typst: |-
324
+ mat(delim: "[", a_x , a_1 ; a_1 , a_x) + mat(delim: "[", a_y, a_2; a_2, a_y)
325
+ # shorthands
326
+ - title: oo
327
+ tex: \infty
328
+ typst: oo
329
+ - title: ll and gg
330
+ tex: a \ll b \gg c
331
+ typst: a << b >> c
332
+ - title: "<==>"
333
+ tex: a \Longleftrightarrow b
334
+ typst: a <==> b
335
+ - title: "<-->"
336
+ tex: a \longleftrightarrow b
337
+ typst: a <--> b
338
+ - title: cases1
339
+ tex: |-
340
+ \begin{cases}
341
+ x^2, & \text{if } x \ge 0 \\
342
+ - x, & \text{if } x < 0
343
+ \end{cases}
344
+ typst: |-
345
+ cases(x^2 comma & "if " x >= 0,
346
+ - x comma & "if " x < 0)
347
+ - title: cases2
348
+ tex: |-
349
+ A_{i j} =
350
+ \begin{cases}
351
+ 1, & \text{if } i = j \\
352
+ 0, & \text{otherwise}
353
+ \end{cases}
354
+ typst: |-
355
+ A_(i j) =
356
+ cases(1 comma & "if " i = j,
357
+ 0 comma & "otherwise")
358
+ - title: cases3
359
+ tex: |-
360
+ P(X = x) =
361
+ \begin{cases}
362
+ n, & x \in\{1, 2, \dots, n\} \\
363
+ 0, & \text{otherwise}
364
+ \end{cases}
365
+ typst: |-
366
+ P(X = x) =
367
+ cases(n comma & x in {1 comma 2 comma ... comma n},
368
+ 0 comma & "otherwise")
369
+ - title: cases4
370
+ tex: |-
371
+ f(x) =
372
+ \begin{cases}
373
+ x^2 + 1, & \text{if } x < - 1 \\
374
+ \sin x + x^2, & \text{if } - 1 \le x \le 1 \\
375
+ \sqrt{x}, & \text{if } x > 1
376
+ \end{cases}
377
+ typst: |-
378
+ f(x) =
379
+ cases(x^2 + 1 comma & "if " x < - 1,
380
+ sin x + x^2 comma & "if " - 1 <= x <= 1,
381
+ sqrt(x) comma & "if " x > 1)
382
+ - title: cases5
383
+ tex: |-
384
+ \begin{aligned}
385
+ f(x) &=
386
+ \begin{cases}
387
+ x^2, & x \ge 0 \\
388
+ - x, & x < 0
389
+ \end{cases} \\
390
+ g(x) &=
391
+ \begin{cases}
392
+ \sin x, & x < \pi \\
393
+ 0, & x \ge \pi
394
+ \end{cases}
395
+ \end{aligned}
396
+ typst: |-
397
+ f(x) &=
398
+ cases(x^2 comma & x >= 0,
399
+ - x comma & x < 0) \
400
+ g(x) &=
401
+ cases(sin x comma & x < pi,
402
+ 0 comma & x >= pi)
403
+
404
+ - title: Typst vec to Tex pmatrix
405
+ tex: |-
406
+ \begin{pmatrix}
407
+ a \\ b \\ c
408
+ \end{pmatrix}
409
+ typst: vec(a,b,c)
410
+ - title: overset & underset
411
+ tex: \overset{b}{\underset{a}{+}}
412
+ typst: limits(+)_a^b
@@ -0,0 +1,126 @@
1
+ title: Symbol Map
2
+ cases:
3
+ - title: backslash
4
+ tex: \backslash
5
+ typst: backslash
6
+ - title: lowercase Greek alphabet
7
+ tex: \alpha \beta \gamma \delta \epsilon \zeta \eta \theta \iota \kappa \lambda \mu \nu \xi \omicron \pi \rho \sigma \tau \upsilon \phi \chi \psi \omega
8
+ typst: alpha beta gamma delta epsilon.alt zeta eta theta iota kappa lambda mu nu xi omicron pi rho sigma tau upsilon phi.alt chi psi omega
9
+ - title: lowercase Greek letter variants
10
+ tex: \varepsilon \vartheta \varpi \varrho \varsigma \varphi
11
+ typst: epsilon theta.alt pi.alt rho.alt sigma.alt phi
12
+ - title: Greek letters and their variants that should be handled specially
13
+ tex: \epsilon \phi
14
+ typst: epsilon.alt phi.alt
15
+ - title: uppercase Greek alphabet
16
+ tex: \Gamma \Delta \Theta \Lambda \Xi \Pi \Sigma \Upsilon \Phi \Psi \Omega
17
+ typst: Gamma Delta Theta Lambda Xi Pi Sigma Upsilon Phi Psi Omega
18
+ - title: mathbb for others
19
+ tex: \mathbb{1 \alpha}
20
+ typst: bb(1 alpha)
21
+ - title: mathcal
22
+ tex: \mathcal{A} \mathcal{B} \mathcal{C} \mathcal{D} \mathcal{E} \mathcal{F} \mathcal{G} \mathcal{H} \mathcal{I} \mathcal{J} \mathcal{K} \mathcal{L} \mathcal{M} \mathcal{N} \mathcal{O} \mathcal{P} \mathcal{Q} \mathcal{R} \mathcal{S} \mathcal{T} \mathcal{U} \mathcal{V} \mathcal{W} \mathcal{X} \mathcal{Y} \mathcal{Z}
23
+ typst: cal(A) cal(B) cal(C) cal(D) cal(E) cal(F) cal(G) cal(H) cal(I) cal(J) cal(K) cal(L) cal(M) cal(N) cal(O) cal(P) cal(Q) cal(R) cal(S) cal(T) cal(U) cal(V) cal(W) cal(X) cal(Y) cal(Z)
24
+ - title: mathscr
25
+ tex: \mathscr{A}
26
+ typst: scr(A)
27
+ - title: mathrm
28
+ tex: \mathrm{a} \rm{a}
29
+ typst: upright(a) upright(a)
30
+ - title: pmb
31
+ tex: \pmb{a}
32
+ typst: bold(a)
33
+ - title: variants of plus,minus,times,divide
34
+ tex: \pm \mp \oplus \boxplus \otimes \boxtimes
35
+ typst: plus.minus minus.plus plus.circle plus.square times.circle times.square
36
+ - title: symbols about mathematical logic
37
+ tex: \neg \land \lor
38
+ typst: not and or
39
+ - title: symbols about sets
40
+ tex: \in \subset \subseteq
41
+ typst: in subset subset.eq
42
+ - title: empty set
43
+ tex: \varnothing
44
+ typst: diameter
45
+ - title: symbols about comparing numbers and order relations
46
+ # prec.eq and succ.eq don't looks like \preceq and \succeq
47
+ tex: \neq \leq \geq \ll \gg \prec \succ \preceq \succeq
48
+ typst: eq.not lt.eq gt.eq lt.double gt.double prec succ prec.eq succ.eq
49
+ preferShorthands: false
50
+ - title: symbols about differential
51
+ # TODO: \mathrm{d} or \operatorname{d} -> dif
52
+ tex: \Delta \nabla \partial
53
+ typst: Delta nabla diff
54
+ - title: symbols about integral
55
+ tex: \int \oint \iint \oiint \iiint \oiiint
56
+ typst: integral integral.cont integral.double integral.surf integral.triple integral.vol
57
+ - title: big symbols used to denote accumulated operations
58
+ tex: \sum \prod \bigcup \bigcap \bigvee \bigwedge \bigoplus \bigotimes \bigodot \biguplus \bigsqcup
59
+ typst: sum product union.big inter.big or.big and.big plus.circle.big times.circle.big dot.circle.big union.plus.big union.sq.big
60
+ - title: wave
61
+ tex: \sim \approx \cong \simeq \asymp \equiv \propto
62
+ typst: tilde.op approx tilde.equiv tilde.eq asymp equiv prop
63
+ preferShorthands: false
64
+ - title: arrows used in proofs
65
+ tex: \implies \iff \leftrightarrow \longleftrightarrow \rightrightarrows
66
+ typst: arrow.r.double.long arrow.l.r.double.long arrow.l.r arrow.l.r.long arrows.rr
67
+ preferShorthands: false
68
+ # - title: def eq
69
+ # tex: \overset{\text{def}}{=}
70
+ # typst: eq.def
71
+ - title: monetary symbols
72
+ tex: \$ \pounds \yen
73
+ typst: \$ pound yen
74
+ - title: escape characters
75
+ tex: \{ \} \_ \& \# \% \$
76
+ typst: "{} \\_\\& \\# % \\$" # Ideally there should be a space between \ and {, but not implemented yet
77
+ - title: combinatorial number
78
+ tex: \binom{n}{k}
79
+ typst: binom(n, k)
80
+ - title: unpaired left and right floor,ceil
81
+ tex: \rfloor \lceil \left\lceil \frac{1}{2} \right \rfloor
82
+ typst: floor.r ceil.l lr(ceil.l 1/2 floor.r)
83
+ - title: paired left and right floor,ceil
84
+ tex: \lfloor x \rfloor \lceil x \rceil \left\lceil \frac{1}{2} \right \rceil
85
+ typst: floor(x) ceil(x) ceil(1/2)
86
+ - title: paired lfloor and rceil
87
+ tex: \lfloor \rceil \lfloor x \rceil \left \lfloor \frac{1}{2} \right \rceil
88
+ typst: round("") round(x) round(1/2)
89
+ - title: trigonometric functions
90
+ tex: \sin \cos \tan \cot \sec \csc
91
+ typst: sin cos tan cot sec csc
92
+ # - title: hyperbolic functions
93
+ # tex: \sinh \cosh \tanh \coth \sech \csch
94
+ # typst: sinh cosh tanh coth sech csch
95
+ - title: prefer Typst Intrinsic
96
+ tex: \operatorname{sech}
97
+ typst: sech
98
+ - title: custom macros
99
+ tex: \myop y=\sgn(x)
100
+ typst: op("myop") y = op("sgn")(x)
101
+ customTexMacros:
102
+ \myop: \operatorname{myop}
103
+ \sgn: \operatorname{sgn}
104
+ - title: non-strict mode
105
+ tex: \myop
106
+ typst: myop
107
+ nonStrict: true
108
+ - title: extended
109
+ tex: \LaTeX \TeX
110
+ typst: "#LaTeX #TeX"
111
+ - title: mathbf
112
+ tex: \mathbf{A}
113
+ typst: upright(bold(A))
114
+ - title: slash
115
+ tex: 1/2
116
+ typst: 1 \/2
117
+ - title: double bar
118
+ tex: \|
119
+ typst: bar.v.double
120
+ - title: double bar as left-right delimiter
121
+ tex: \left\| a + \frac{1}{2} \right.
122
+ typst: lr(bar.v.double a + 1/2)
123
+ - title: preferShorthands
124
+ tex: \leadsto
125
+ typst: ~>
126
+ preferShorthands: true
@@ -0,0 +1,26 @@
1
+ import path from 'node:path';
2
+ import fs from 'node:fs';
3
+ // @ts-ignore
4
+ import yaml from 'js-yaml';
5
+
6
+ export interface TestCase {
7
+ title: string;
8
+ tex: string;
9
+ typst: string;
10
+ nonStrict?: boolean;
11
+ preferShorthands?: boolean;
12
+ inftyToOo?: boolean;
13
+ customTexMacros: { [key: string]: string };
14
+ };
15
+
16
+
17
+ export interface TestCaseFile {
18
+ title: string;
19
+ cases: TestCase[];
20
+ };
21
+
22
+
23
+ export function loadTestCases(filename: string): TestCaseFile {
24
+ const content = fs.readFileSync(path.join(__dirname, filename), { encoding: 'utf-8' });
25
+ return yaml.load(content) as TestCaseFile;
26
+ }
@@ -0,0 +1,97 @@
1
+ import { describe, test, expect } from 'vitest';
2
+ import { tokenize_tex } from '../src/tex-tokenizer';
3
+ import { LatexParserError, parseTex } from '../src/tex-parser';
4
+ import { TexToken, TexTokenType } from '../src/tex-types';
5
+
6
+
7
+ describe('typst-tokenizer', () => {
8
+ test('a + b', function () {
9
+ const res = tokenize_tex('a + b');
10
+ expect(res).toEqual([
11
+ new TexToken(TexTokenType.ELEMENT, 'a'),
12
+ new TexToken(TexTokenType.SPACE, ' '),
13
+ new TexToken(TexTokenType.ELEMENT, '+'),
14
+ new TexToken(TexTokenType.SPACE, ' '),
15
+ new TexToken(TexTokenType.ELEMENT, 'b'),
16
+ ]);
17
+ });
18
+
19
+ test('a (x)', function () {
20
+ const res = tokenize_tex('a (x)');
21
+ expect(res).toEqual([
22
+ new TexToken(TexTokenType.ELEMENT, 'a'),
23
+ new TexToken(TexTokenType.SPACE, ' '),
24
+ new TexToken(TexTokenType.ELEMENT, '('),
25
+ new TexToken(TexTokenType.ELEMENT, 'x'),
26
+ new TexToken(TexTokenType.ELEMENT, ')'),
27
+ ]);
28
+ });
29
+
30
+ test('f(x)', function () {
31
+ const res = tokenize_tex('f(x)');
32
+ expect(res).toEqual([
33
+ new TexToken(TexTokenType.ELEMENT, 'f'),
34
+ new TexToken(TexTokenType.ELEMENT, '('),
35
+ new TexToken(TexTokenType.ELEMENT, 'x'),
36
+ new TexToken(TexTokenType.ELEMENT, ')'),
37
+ ]);
38
+ });
39
+
40
+ test('comment', function() {
41
+ const res = tokenize_tex('a % comment');
42
+ expect(res).toEqual([
43
+ new TexToken(TexTokenType.ELEMENT, 'a'),
44
+ new TexToken(TexTokenType.SPACE, ' '),
45
+ new TexToken(TexTokenType.COMMENT, ' comment'),
46
+ ]);
47
+ });
48
+
49
+ test('macro', function() {
50
+ const res = tokenize_tex('\\sqrt{a}');
51
+ expect(res).toEqual([
52
+ new TexToken(TexTokenType.COMMAND, '\\sqrt'),
53
+ new TexToken(TexTokenType.CONTROL, '{'),
54
+ new TexToken(TexTokenType.ELEMENT, 'a'),
55
+ new TexToken(TexTokenType.CONTROL, '}'),
56
+ ]);
57
+ });
58
+
59
+ test('throw error on & outside of an alignment', function() {
60
+ expect(() => parseTex('a & b')).toThrow();
61
+ });
62
+
63
+ test('throw on missing ] for sqrt', function() {
64
+ const input = '\\sqrt[3{x}';
65
+ expect(() => parseTex(input)).toThrowError(LatexParserError.UNMATCHED_LEFT_BRACKET);
66
+ });
67
+
68
+ test('throw on extra {', function() {
69
+ const input = 'a { {b}';
70
+ expect(() => parseTex(input)).toThrowError(LatexParserError.UNMATCHED_LEFT_BRACE);
71
+ });
72
+
73
+ test('throw on extra }', function() {
74
+ const input = 'a { b } }';
75
+ expect(() => parseTex(input)).toThrowError(LatexParserError.UNMATCHED_RIGHT_BRACE);
76
+ });
77
+
78
+ test('throw on extra \\left', function() {
79
+ const input = 'a \\left( \\left( b \\right)';
80
+ expect(() => parseTex(input)).toThrowError(LatexParserError.UNMATCHED_COMMAND_LEFT);
81
+ });
82
+
83
+ test('throw on extra \\right', function() {
84
+ const input = 'a \\left( b \\right) \\right)';
85
+ expect(() => parseTex(input)).toThrowError(LatexParserError.UNMATCHED_COMMAND_RIGHT);
86
+ });
87
+
88
+ test('throw on extra \\begin', function() {
89
+ const input = 'a \\begin{aligned} \\begin{aligned} b \\end{aligned}';
90
+ expect(() => parseTex(input)).toThrowError(LatexParserError.UNMATCHED_COMMAND_BEGIN);
91
+ });
92
+
93
+ test('throw on extra \\end', function() {
94
+ const input = 'a \\begin{aligned} b \\end{aligned} \\end{aligned}';
95
+ expect(() => parseTex(input)).toThrowError(LatexParserError.UNMATCHED_COMMAND_END);
96
+ });
97
+ });