tex2typst 0.0.11 → 0.0.16
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/.github/workflows/github-ci.yml +35 -0
- package/dist/map.js +32 -34
- package/dist/parser.js +1 -1
- package/dist/writer.js +19 -0
- package/package.json +1 -1
- package/src/map.ts +33 -38
- package/src/parser.ts +3 -0
- package/src/writer.ts +18 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: tex2typst Tests
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches:
|
|
5
|
+
- main
|
|
6
|
+
- dev
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
unit-tests:
|
|
13
|
+
name: Unit tests
|
|
14
|
+
runs-on: ${{ matrix.os }}
|
|
15
|
+
|
|
16
|
+
strategy:
|
|
17
|
+
matrix:
|
|
18
|
+
os: [ubuntu-latest]
|
|
19
|
+
node: [18]
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout
|
|
23
|
+
uses: actions/checkout@v3
|
|
24
|
+
|
|
25
|
+
- name: Setup node env
|
|
26
|
+
uses: actions/setup-node@v4
|
|
27
|
+
with:
|
|
28
|
+
node-version: ${{ matrix.node }}
|
|
29
|
+
cache: 'yarn'
|
|
30
|
+
|
|
31
|
+
- name: Install dependencies
|
|
32
|
+
run: yarn install
|
|
33
|
+
|
|
34
|
+
- name: Run Vitest Test
|
|
35
|
+
run: npx vitest run
|
package/dist/map.js
CHANGED
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.symbolMap = void 0;
|
|
4
4
|
exports.symbolMap = new Map([
|
|
5
5
|
['gets', 'arrow.l'],
|
|
6
|
-
['infty', 'infinity'], // infinity
|
|
7
6
|
['nonumber', ''],
|
|
8
7
|
['vec', 'arrow'],
|
|
9
8
|
['mathbf', 'bold'],
|
|
@@ -44,36 +43,6 @@ exports.symbolMap = new Map([
|
|
|
44
43
|
['boxplus', 'plus.square'],
|
|
45
44
|
['otimes', 'times.circle'],
|
|
46
45
|
['boxtimes', 'times.square'],
|
|
47
|
-
/* symbols in mathematical logic */
|
|
48
|
-
['neg', 'not'],
|
|
49
|
-
['land', 'and'],
|
|
50
|
-
['lor', 'or'],
|
|
51
|
-
['varnothing', 'diameter'], // empty set
|
|
52
|
-
/* symbols about comparing numbers */
|
|
53
|
-
// tex: \neq \leq \geq \ll \gg \prec \succ \preceq \succeq
|
|
54
|
-
// typst: eq.not lt.eq gt.eq lt.double gt.double prec succ prec.eq succ.eq
|
|
55
|
-
['neq', 'eq.not'],
|
|
56
|
-
['leq', 'lt.eq'],
|
|
57
|
-
['geq', 'gt.eq'],
|
|
58
|
-
['ll', 'lt.double'],
|
|
59
|
-
['gg', 'gt.double'],
|
|
60
|
-
['prec', 'prec'],
|
|
61
|
-
['succ', 'succ'],
|
|
62
|
-
['preceq', 'prec.eq'],
|
|
63
|
-
['succeq', 'succ.eq'],
|
|
64
|
-
/* symbols about differential */
|
|
65
|
-
['Delta', 'Delta'],
|
|
66
|
-
['nabla', 'nabla'],
|
|
67
|
-
['partial', 'diff'],
|
|
68
|
-
/* symbols about integral */
|
|
69
|
-
// tex: \int \oint \iint \oiint \iiint \oiiint
|
|
70
|
-
// typst: integral integral.cont integral.double integral.surf integral.triple integral.vol
|
|
71
|
-
['int', 'integral'],
|
|
72
|
-
['oint', 'integral.cont'],
|
|
73
|
-
['iint', 'integral.double'],
|
|
74
|
-
['oiint', 'integral.surf'],
|
|
75
|
-
['iiint', 'integral.triple'],
|
|
76
|
-
['oiiint', 'integral.vol'],
|
|
77
46
|
/* wave */
|
|
78
47
|
// tex: \sim \approx \cong \simeq \asymp \equiv \propto
|
|
79
48
|
// typst: tilde approx tilde.equiv tilde.eq ≍ equiv prop
|
|
@@ -94,7 +63,6 @@ exports.symbolMap = new Map([
|
|
|
94
63
|
['leftrightarrow', 'arrow.l.r'],
|
|
95
64
|
['longleftrightarrow', 'arrow.l.r.long'],
|
|
96
65
|
['rightrightarrows', 'arrows.rr'],
|
|
97
|
-
['binom', 'binom'],
|
|
98
66
|
/* left and right floor,ceil */
|
|
99
67
|
// tex: \lfloor \rfloor \lceil \rceil
|
|
100
68
|
// typst: ⌊ ⌋ ⌈ ⌉
|
|
@@ -181,12 +149,14 @@ exports.symbolMap = new Map([
|
|
|
181
149
|
['iiint', 'integral.triple'],
|
|
182
150
|
['iint', 'integral.double'],
|
|
183
151
|
['in', 'in'],
|
|
152
|
+
['infty', 'infinity'],
|
|
184
153
|
['int', 'integral'],
|
|
185
154
|
['intercal', 'top'], // 'top' or 'tack.b'
|
|
186
155
|
['iota', 'iota'],
|
|
187
156
|
['jmath', 'dotless.j'],
|
|
188
157
|
['kappa', 'kappa'],
|
|
189
158
|
['lambda', 'lambda'],
|
|
159
|
+
['land', 'and'],
|
|
190
160
|
['langle', 'angle.l'],
|
|
191
161
|
['lbrace', 'brace.l'],
|
|
192
162
|
['lbrack', 'bracket.l'],
|
|
@@ -202,6 +172,7 @@ exports.symbolMap = new Map([
|
|
|
202
172
|
['ll', 'lt.double'],
|
|
203
173
|
['longmapsto', 'arrow.long.bar'],
|
|
204
174
|
['longrightarrow', 'arrow.long'],
|
|
175
|
+
['lor', 'or'],
|
|
205
176
|
['ltimes', 'times.l'],
|
|
206
177
|
['mapsto', 'arrow.bar'],
|
|
207
178
|
['measuredangle', 'angle.arc'],
|
|
@@ -215,14 +186,25 @@ exports.symbolMap = new Map([
|
|
|
215
186
|
['ne', 'eq.not'],
|
|
216
187
|
['neg', 'not'],
|
|
217
188
|
['neq', 'eq.not'],
|
|
189
|
+
['nexists', 'exists.not'],
|
|
190
|
+
['ni', "in.rev"],
|
|
191
|
+
['nleftarrow', "arrow.l.not"],
|
|
192
|
+
['nleq', "lt.eq.not"],
|
|
193
|
+
['nparallel', "parallel.not"],
|
|
194
|
+
['ngeq', 'gt.eq.not'],
|
|
218
195
|
['nmid', 'divides.not'],
|
|
219
196
|
['notin', 'in.not'],
|
|
220
|
-
['nleftarrow', 'arrow.l.not'],
|
|
221
197
|
['nrightarrow', 'arrow.not'],
|
|
222
198
|
['nsim', 'tilde.not'],
|
|
199
|
+
['nsubseteq', 'subset.eq.not'],
|
|
223
200
|
['nu', 'nu'],
|
|
201
|
+
['ntriangleleft', 'lt.tri.not'],
|
|
202
|
+
['ntriangleright', 'gt.tri.not'],
|
|
203
|
+
['nwarrow', 'arrow.tl'],
|
|
224
204
|
['odot', 'dot.circle'],
|
|
225
205
|
['oint', 'integral.cont'],
|
|
206
|
+
['oiint', 'integral.surf'],
|
|
207
|
+
['oiiint', 'integral.vol'],
|
|
226
208
|
['omega', 'omega'],
|
|
227
209
|
// ['omicron', 'omicron'],
|
|
228
210
|
['ominus', 'minus.circle'],
|
|
@@ -234,6 +216,7 @@ exports.symbolMap = new Map([
|
|
|
234
216
|
['phi', 'phi.alt'],
|
|
235
217
|
['pi', 'pi'],
|
|
236
218
|
['pm', 'plus.minus'],
|
|
219
|
+
['pounds', 'pound'],
|
|
237
220
|
['prec', 'prec'],
|
|
238
221
|
['preceq', 'prec.eq'],
|
|
239
222
|
['prime', 'prime'],
|
|
@@ -252,9 +235,14 @@ exports.symbolMap = new Map([
|
|
|
252
235
|
['sigma', 'sigma'],
|
|
253
236
|
['sim', 'tilde'],
|
|
254
237
|
['simeq', 'tilde.eq'],
|
|
238
|
+
['slash', 'slash'],
|
|
239
|
+
['smallsetminus', 'without'],
|
|
255
240
|
// ['smile', 'paren.b'],
|
|
241
|
+
['spadesuit', 'suit.spade'],
|
|
256
242
|
['sqcap', 'sect.sq'],
|
|
257
243
|
['sqcup', 'union.sq'],
|
|
244
|
+
['sqsubseteq', 'subset.eq.sq'],
|
|
245
|
+
['sqsupseteq', 'supset.eq.sq'],
|
|
258
246
|
['star', 'star'],
|
|
259
247
|
['subset', 'subset'],
|
|
260
248
|
['subseteq', 'subset.eq'],
|
|
@@ -265,19 +253,24 @@ exports.symbolMap = new Map([
|
|
|
265
253
|
['supset', 'supset'],
|
|
266
254
|
['supseteq', 'supset.eq'],
|
|
267
255
|
['supsetneq', 'supset.neq'],
|
|
256
|
+
['swarrow', 'arrow.bl'],
|
|
268
257
|
['tau', 'tau'],
|
|
269
258
|
['theta', 'theta'],
|
|
270
259
|
['times', 'times'],
|
|
271
260
|
['to', 'arrow.r'],
|
|
261
|
+
['top', 'top'],
|
|
272
262
|
['triangle', 'triangle.t'],
|
|
263
|
+
['triangledown', 'triangle.b.small'],
|
|
273
264
|
['triangleleft', 'triangle.l.small'],
|
|
274
|
-
['triangleright', 'triangle.small'],
|
|
265
|
+
['triangleright', 'triangle.r.small'],
|
|
266
|
+
['twoheadrightarrow', 'arrow.r.twohead'],
|
|
275
267
|
['uparrow', 'arrow.t'],
|
|
276
268
|
['updownarrow', 'arrow.t.b'],
|
|
277
269
|
['upharpoonright', 'harpoon.tr'],
|
|
278
270
|
['uplus', 'union.plus'],
|
|
279
271
|
['upsilon', 'upsilon'],
|
|
280
272
|
['varepsilon', 'epsilon'],
|
|
273
|
+
['varnothing', 'diameter'], // empty set
|
|
281
274
|
['varphi', 'phi'],
|
|
282
275
|
['varpi', 'pi.alt'],
|
|
283
276
|
['varrho', 'rho.alt'],
|
|
@@ -289,5 +282,10 @@ exports.symbolMap = new Map([
|
|
|
289
282
|
['wedge', 'and'],
|
|
290
283
|
['wr', 'wreath'],
|
|
291
284
|
['xi', 'xi'],
|
|
285
|
+
['yen', 'yen'],
|
|
292
286
|
['zeta', 'zeta'],
|
|
287
|
+
// extended
|
|
288
|
+
['mathscr', 'scr'],
|
|
289
|
+
['LaTeX', '#LaTeX'],
|
|
290
|
+
['TeX', '#TeX'],
|
|
293
291
|
]);
|
package/dist/parser.js
CHANGED
|
@@ -246,7 +246,7 @@ function parseTex(tex, customTexMacros) {
|
|
|
246
246
|
// displayMode=true. Otherwise, "KaTeX parse error: {align*} can be used only in display mode."
|
|
247
247
|
const macros = Object.assign({
|
|
248
248
|
// KaTeX parse these commands so complicatedly that we need some hacks to keep things simple.
|
|
249
|
-
'\\mod': '\\operatorname{SyMb01-mod}', '\\liminf': '\\operatorname{SyMb01-liminf}', '\\limsup': '\\operatorname{SyMb01-limsup}', '\\qquad': '\\operatorname{SyMb01-qquad}', '\\quad': '\\operatorname{SyMb01-quad}', '\\cdots': '\\operatorname{SyMb01-cdots}', '\\colon': '\\operatorname{SyMb01-colon}', '\\imath': '\\operatorname{SyMb01-imath}', '\\\iiiint': '\\operatorname{SyMb01-iiiint}', '\\jmath': '\\operatorname{SyMb01-jmath}', '\\vdots': '\\operatorname{SyMb01-vdots}', '\\notin': '\\operatorname{SyMb01-notin}' }, customTexMacros);
|
|
249
|
+
'\\mod': '\\operatorname{SyMb01-mod}', '\\liminf': '\\operatorname{SyMb01-liminf}', '\\limsup': '\\operatorname{SyMb01-limsup}', '\\qquad': '\\operatorname{SyMb01-qquad}', '\\quad': '\\operatorname{SyMb01-quad}', '\\cdots': '\\operatorname{SyMb01-cdots}', '\\colon': '\\operatorname{SyMb01-colon}', '\\imath': '\\operatorname{SyMb01-imath}', '\\\iiiint': '\\operatorname{SyMb01-iiiint}', '\\jmath': '\\operatorname{SyMb01-jmath}', '\\vdots': '\\operatorname{SyMb01-vdots}', '\\notin': '\\operatorname{SyMb01-notin}', '\\slash': '\\operatorname{SyMb01-slash}', '\\LaTeX': '\\operatorname{SyMb01-LaTeX}', '\\TeX': '\\operatorname{SyMb01-TeX}' }, customTexMacros);
|
|
250
250
|
const options = {
|
|
251
251
|
macros: macros,
|
|
252
252
|
displayMode: true,
|
package/dist/writer.js
CHANGED
|
@@ -310,6 +310,22 @@ class TypstWriter {
|
|
|
310
310
|
}
|
|
311
311
|
finalize() {
|
|
312
312
|
this.flushQueue();
|
|
313
|
+
const smartFloorPass = function (input) {
|
|
314
|
+
// Use regex to replace all "⌊ xxx ⌋" with "floor(xxx)"
|
|
315
|
+
let res = input.replace(/⌊\s*(.*?)\s*⌋/g, "floor($1)");
|
|
316
|
+
// Typst disallow "floor()" with empty argument, so add am empty string inside if it's empty.
|
|
317
|
+
res = res.replace(/floor\(\)/g, 'floor("")');
|
|
318
|
+
return res;
|
|
319
|
+
};
|
|
320
|
+
const smartCeilPass = function (input) {
|
|
321
|
+
// Use regex to replace all "⌈ xxx ⌉" with "ceil(xxx)"
|
|
322
|
+
let res = input.replace(/⌈\s*(.*?)\s*⌉/g, "ceil($1)");
|
|
323
|
+
// Typst disallow "ceil()" with empty argument, so add an empty string inside if it's empty.
|
|
324
|
+
res = res.replace(/ceil\(\)/g, 'ceil("")');
|
|
325
|
+
return res;
|
|
326
|
+
};
|
|
327
|
+
this.buffer = smartFloorPass(this.buffer);
|
|
328
|
+
this.buffer = smartCeilPass(this.buffer);
|
|
313
329
|
return this.buffer;
|
|
314
330
|
}
|
|
315
331
|
}
|
|
@@ -321,6 +337,9 @@ function convertToken(token) {
|
|
|
321
337
|
else if (token === '\\\\') {
|
|
322
338
|
return '\\\n';
|
|
323
339
|
}
|
|
340
|
+
else if (['\\$', '\\#', '\\&', '\\_'].includes(token)) {
|
|
341
|
+
return token;
|
|
342
|
+
}
|
|
324
343
|
else if (token.startsWith('\\')) {
|
|
325
344
|
const symbol = token.slice(1);
|
|
326
345
|
if (map_1.symbolMap.has(symbol)) {
|
package/package.json
CHANGED
package/src/map.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export const symbolMap = new Map<string, string>([
|
|
2
2
|
['gets', 'arrow.l'],
|
|
3
|
-
['infty', 'infinity'], // infinity
|
|
4
3
|
['nonumber', ''],
|
|
5
4
|
['vec', 'arrow'],
|
|
6
5
|
['mathbf', 'bold'],
|
|
@@ -46,40 +45,6 @@ export const symbolMap = new Map<string, string>([
|
|
|
46
45
|
['otimes', 'times.circle'],
|
|
47
46
|
['boxtimes', 'times.square'],
|
|
48
47
|
|
|
49
|
-
/* symbols in mathematical logic */
|
|
50
|
-
['neg', 'not'],
|
|
51
|
-
['land', 'and'],
|
|
52
|
-
['lor', 'or'],
|
|
53
|
-
|
|
54
|
-
['varnothing', 'diameter'], // empty set
|
|
55
|
-
|
|
56
|
-
/* symbols about comparing numbers */
|
|
57
|
-
// tex: \neq \leq \geq \ll \gg \prec \succ \preceq \succeq
|
|
58
|
-
// typst: eq.not lt.eq gt.eq lt.double gt.double prec succ prec.eq succ.eq
|
|
59
|
-
['neq', 'eq.not'],
|
|
60
|
-
['leq', 'lt.eq'],
|
|
61
|
-
['geq', 'gt.eq'],
|
|
62
|
-
['ll', 'lt.double'],
|
|
63
|
-
['gg', 'gt.double'],
|
|
64
|
-
['prec', 'prec'],
|
|
65
|
-
['succ', 'succ'],
|
|
66
|
-
['preceq', 'prec.eq'],
|
|
67
|
-
['succeq', 'succ.eq'],
|
|
68
|
-
|
|
69
|
-
/* symbols about differential */
|
|
70
|
-
['Delta', 'Delta'],
|
|
71
|
-
['nabla', 'nabla'],
|
|
72
|
-
['partial', 'diff'],
|
|
73
|
-
|
|
74
|
-
/* symbols about integral */
|
|
75
|
-
// tex: \int \oint \iint \oiint \iiint \oiiint
|
|
76
|
-
// typst: integral integral.cont integral.double integral.surf integral.triple integral.vol
|
|
77
|
-
['int', 'integral'],
|
|
78
|
-
['oint', 'integral.cont'],
|
|
79
|
-
['iint', 'integral.double'],
|
|
80
|
-
['oiint', 'integral.surf'],
|
|
81
|
-
['iiint', 'integral.triple'],
|
|
82
|
-
['oiiint', 'integral.vol'],
|
|
83
48
|
|
|
84
49
|
/* wave */
|
|
85
50
|
// tex: \sim \approx \cong \simeq \asymp \equiv \propto
|
|
@@ -103,7 +68,6 @@ export const symbolMap = new Map<string, string>([
|
|
|
103
68
|
['longleftrightarrow', 'arrow.l.r.long'],
|
|
104
69
|
['rightrightarrows', 'arrows.rr'],
|
|
105
70
|
|
|
106
|
-
['binom', 'binom'],
|
|
107
71
|
|
|
108
72
|
/* left and right floor,ceil */
|
|
109
73
|
// tex: \lfloor \rfloor \lceil \rceil
|
|
@@ -193,12 +157,14 @@ export const symbolMap = new Map<string, string>([
|
|
|
193
157
|
['iiint', 'integral.triple'],
|
|
194
158
|
['iint', 'integral.double'],
|
|
195
159
|
['in', 'in'],
|
|
160
|
+
['infty', 'infinity'],
|
|
196
161
|
['int', 'integral'],
|
|
197
162
|
['intercal', 'top'], // 'top' or 'tack.b'
|
|
198
163
|
['iota', 'iota'],
|
|
199
164
|
['jmath', 'dotless.j'],
|
|
200
165
|
['kappa', 'kappa'],
|
|
201
166
|
['lambda', 'lambda'],
|
|
167
|
+
['land', 'and'],
|
|
202
168
|
['langle', 'angle.l'],
|
|
203
169
|
['lbrace', 'brace.l'],
|
|
204
170
|
['lbrack', 'bracket.l'],
|
|
@@ -214,6 +180,7 @@ export const symbolMap = new Map<string, string>([
|
|
|
214
180
|
['ll', 'lt.double'],
|
|
215
181
|
['longmapsto', 'arrow.long.bar'],
|
|
216
182
|
['longrightarrow', 'arrow.long'],
|
|
183
|
+
['lor', 'or'],
|
|
217
184
|
['ltimes', 'times.l'],
|
|
218
185
|
['mapsto', 'arrow.bar'],
|
|
219
186
|
['measuredangle', 'angle.arc'],
|
|
@@ -227,14 +194,25 @@ export const symbolMap = new Map<string, string>([
|
|
|
227
194
|
['ne', 'eq.not'],
|
|
228
195
|
['neg', 'not'],
|
|
229
196
|
['neq', 'eq.not'],
|
|
197
|
+
['nexists', 'exists.not'],
|
|
198
|
+
['ni', "in.rev"],
|
|
199
|
+
['nleftarrow', "arrow.l.not"],
|
|
200
|
+
['nleq', "lt.eq.not"],
|
|
201
|
+
['nparallel', "parallel.not"],
|
|
202
|
+
['ngeq', 'gt.eq.not'],
|
|
230
203
|
['nmid', 'divides.not'],
|
|
231
204
|
['notin', 'in.not'],
|
|
232
|
-
['nleftarrow', 'arrow.l.not'],
|
|
233
205
|
['nrightarrow', 'arrow.not'],
|
|
234
206
|
['nsim', 'tilde.not'],
|
|
207
|
+
['nsubseteq', 'subset.eq.not'],
|
|
235
208
|
['nu', 'nu'],
|
|
209
|
+
['ntriangleleft', 'lt.tri.not'],
|
|
210
|
+
['ntriangleright', 'gt.tri.not'],
|
|
211
|
+
['nwarrow', 'arrow.tl'],
|
|
236
212
|
['odot', 'dot.circle'],
|
|
237
213
|
['oint', 'integral.cont'],
|
|
214
|
+
['oiint', 'integral.surf'],
|
|
215
|
+
['oiiint', 'integral.vol'],
|
|
238
216
|
['omega', 'omega'],
|
|
239
217
|
// ['omicron', 'omicron'],
|
|
240
218
|
['ominus', 'minus.circle'],
|
|
@@ -246,6 +224,7 @@ export const symbolMap = new Map<string, string>([
|
|
|
246
224
|
['phi', 'phi.alt'],
|
|
247
225
|
['pi', 'pi'],
|
|
248
226
|
['pm', 'plus.minus'],
|
|
227
|
+
['pounds', 'pound'],
|
|
249
228
|
['prec', 'prec'],
|
|
250
229
|
['preceq', 'prec.eq'],
|
|
251
230
|
['prime', 'prime'],
|
|
@@ -264,9 +243,14 @@ export const symbolMap = new Map<string, string>([
|
|
|
264
243
|
['sigma', 'sigma'],
|
|
265
244
|
['sim', 'tilde'],
|
|
266
245
|
['simeq', 'tilde.eq'],
|
|
246
|
+
['slash', 'slash'],
|
|
247
|
+
['smallsetminus', 'without'],
|
|
267
248
|
// ['smile', 'paren.b'],
|
|
249
|
+
['spadesuit', 'suit.spade'],
|
|
268
250
|
['sqcap', 'sect.sq'],
|
|
269
251
|
['sqcup', 'union.sq'],
|
|
252
|
+
['sqsubseteq', 'subset.eq.sq'],
|
|
253
|
+
['sqsupseteq', 'supset.eq.sq'],
|
|
270
254
|
['star', 'star'],
|
|
271
255
|
['subset', 'subset'],
|
|
272
256
|
['subseteq', 'subset.eq'],
|
|
@@ -277,19 +261,24 @@ export const symbolMap = new Map<string, string>([
|
|
|
277
261
|
['supset', 'supset'],
|
|
278
262
|
['supseteq', 'supset.eq'],
|
|
279
263
|
['supsetneq', 'supset.neq'],
|
|
264
|
+
['swarrow', 'arrow.bl'],
|
|
280
265
|
['tau', 'tau'],
|
|
281
266
|
['theta', 'theta'],
|
|
282
267
|
['times', 'times'],
|
|
283
268
|
['to', 'arrow.r'],
|
|
269
|
+
['top', 'top'],
|
|
284
270
|
['triangle', 'triangle.t'],
|
|
271
|
+
['triangledown', 'triangle.b.small'],
|
|
285
272
|
['triangleleft', 'triangle.l.small'],
|
|
286
|
-
['triangleright', 'triangle.small'],
|
|
273
|
+
['triangleright', 'triangle.r.small'],
|
|
274
|
+
['twoheadrightarrow', 'arrow.r.twohead'],
|
|
287
275
|
['uparrow', 'arrow.t'],
|
|
288
276
|
['updownarrow', 'arrow.t.b'],
|
|
289
277
|
['upharpoonright', 'harpoon.tr'],
|
|
290
278
|
['uplus', 'union.plus'],
|
|
291
279
|
['upsilon', 'upsilon'],
|
|
292
280
|
['varepsilon', 'epsilon'],
|
|
281
|
+
['varnothing', 'diameter'], // empty set
|
|
293
282
|
['varphi', 'phi'],
|
|
294
283
|
['varpi', 'pi.alt'],
|
|
295
284
|
['varrho', 'rho.alt'],
|
|
@@ -301,5 +290,11 @@ export const symbolMap = new Map<string, string>([
|
|
|
301
290
|
['wedge', 'and'],
|
|
302
291
|
['wr', 'wreath'],
|
|
303
292
|
['xi', 'xi'],
|
|
293
|
+
['yen', 'yen'],
|
|
304
294
|
['zeta', 'zeta'],
|
|
295
|
+
|
|
296
|
+
// extended
|
|
297
|
+
['mathscr', 'scr'],
|
|
298
|
+
['LaTeX', '#LaTeX'],
|
|
299
|
+
['TeX', '#TeX'],
|
|
305
300
|
]);
|
package/src/parser.ts
CHANGED
|
@@ -253,6 +253,9 @@ export function parseTex(tex: string, customTexMacros: {[key: string]: string}):
|
|
|
253
253
|
'\\jmath': '\\operatorname{SyMb01-jmath}',
|
|
254
254
|
'\\vdots': '\\operatorname{SyMb01-vdots}',
|
|
255
255
|
'\\notin': '\\operatorname{SyMb01-notin}',
|
|
256
|
+
'\\slash': '\\operatorname{SyMb01-slash}',
|
|
257
|
+
'\\LaTeX': '\\operatorname{SyMb01-LaTeX}',
|
|
258
|
+
'\\TeX': '\\operatorname{SyMb01-TeX}',
|
|
256
259
|
...customTexMacros
|
|
257
260
|
};
|
|
258
261
|
const options = {
|
package/src/writer.ts
CHANGED
|
@@ -312,6 +312,22 @@ export class TypstWriter {
|
|
|
312
312
|
|
|
313
313
|
public finalize(): string {
|
|
314
314
|
this.flushQueue();
|
|
315
|
+
const smartFloorPass = function (input: string): string {
|
|
316
|
+
// Use regex to replace all "⌊ xxx ⌋" with "floor(xxx)"
|
|
317
|
+
let res = input.replace(/⌊\s*(.*?)\s*⌋/g, "floor($1)");
|
|
318
|
+
// Typst disallow "floor()" with empty argument, so add am empty string inside if it's empty.
|
|
319
|
+
res = res.replace(/floor\(\)/g, 'floor("")');
|
|
320
|
+
return res;
|
|
321
|
+
};
|
|
322
|
+
const smartCeilPass = function (input: string): string {
|
|
323
|
+
// Use regex to replace all "⌈ xxx ⌉" with "ceil(xxx)"
|
|
324
|
+
let res = input.replace(/⌈\s*(.*?)\s*⌉/g, "ceil($1)");
|
|
325
|
+
// Typst disallow "ceil()" with empty argument, so add an empty string inside if it's empty.
|
|
326
|
+
res = res.replace(/ceil\(\)/g, 'ceil("")');
|
|
327
|
+
return res;
|
|
328
|
+
}
|
|
329
|
+
this.buffer = smartFloorPass(this.buffer);
|
|
330
|
+
this.buffer = smartCeilPass(this.buffer);
|
|
315
331
|
return this.buffer;
|
|
316
332
|
}
|
|
317
333
|
}
|
|
@@ -322,6 +338,8 @@ function convertToken(token: string): string {
|
|
|
322
338
|
return token;
|
|
323
339
|
} else if (token === '\\\\') {
|
|
324
340
|
return '\\\n';
|
|
341
|
+
} else if (['\\$', '\\#', '\\&', '\\_'].includes(token)) {
|
|
342
|
+
return token;
|
|
325
343
|
} else if (token.startsWith('\\')) {
|
|
326
344
|
const symbol = token.slice(1);
|
|
327
345
|
if (symbolMap.has(symbol)) {
|