tex2typst 0.2.15 → 0.3.0-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generic.d.ts +7 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +964 -196
- package/dist/map.d.ts +2 -1
- package/dist/tex-parser.d.ts +1 -7
- package/dist/tex-writer.d.ts +11 -0
- package/dist/tex2typst.min.js +1 -1
- package/dist/types.d.ts +15 -5
- package/dist/typst-parser.d.ts +21 -0
- package/dist/util.d.ts +3 -0
- package/package.json +1 -1
- package/src/generic.ts +37 -0
- package/src/index.ts +10 -0
- package/src/map.ts +29 -3
- package/src/tex-parser.ts +23 -100
- package/src/tex-writer.ts +249 -0
- package/src/tex2typst.ts +2 -1
- package/src/types.ts +206 -14
- package/src/typst-parser.ts +507 -0
- package/src/util.ts +14 -0
- package/src/writer.ts +42 -47
package/src/writer.ts
CHANGED
|
@@ -26,7 +26,7 @@ function convert_overset(node: TexNode): TypstNode {
|
|
|
26
26
|
const [sup, base] = node.args!;
|
|
27
27
|
|
|
28
28
|
const is_def = (n: TexNode): boolean => {
|
|
29
|
-
if (n.
|
|
29
|
+
if (n.eq(new TexNode('text', 'def'))) {
|
|
30
30
|
return true;
|
|
31
31
|
}
|
|
32
32
|
// \overset{def}{=} is also considered as eq.def
|
|
@@ -35,18 +35,18 @@ function convert_overset(node: TexNode): TypstNode {
|
|
|
35
35
|
const d = new TexNode('element', 'd');
|
|
36
36
|
const e = new TexNode('element', 'e');
|
|
37
37
|
const f = new TexNode('element', 'f');
|
|
38
|
-
if (a1.
|
|
38
|
+
if (a1.eq(d) && a2.eq(e) && a3.eq(f)) {
|
|
39
39
|
return true;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
return false;
|
|
43
43
|
};
|
|
44
|
-
const is_eq = (n: TexNode): boolean => n.
|
|
44
|
+
const is_eq = (n: TexNode): boolean => n.eq(new TexNode('element', '='));
|
|
45
45
|
if (is_def(sup) && is_eq(base)) {
|
|
46
46
|
return new TypstNode('symbol', 'eq.def');
|
|
47
47
|
}
|
|
48
48
|
const op_call = new TypstNode(
|
|
49
|
-
'
|
|
49
|
+
'funcCall',
|
|
50
50
|
'op',
|
|
51
51
|
[convertTree(base)]
|
|
52
52
|
);
|
|
@@ -62,9 +62,9 @@ function convert_overset(node: TexNode): TypstNode {
|
|
|
62
62
|
);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
const TYPST_LEFT_PARENTHESIS: TypstToken = new TypstToken(TypstTokenType.
|
|
66
|
-
const TYPST_RIGHT_PARENTHESIS: TypstToken = new TypstToken(TypstTokenType.
|
|
67
|
-
const TYPST_COMMA: TypstToken = new TypstToken(TypstTokenType.
|
|
65
|
+
const TYPST_LEFT_PARENTHESIS: TypstToken = new TypstToken(TypstTokenType.ELEMENT, '(');
|
|
66
|
+
const TYPST_RIGHT_PARENTHESIS: TypstToken = new TypstToken(TypstTokenType.ELEMENT, ')');
|
|
67
|
+
const TYPST_COMMA: TypstToken = new TypstToken(TypstTokenType.ELEMENT, ',');
|
|
68
68
|
const TYPST_NEWLINE: TypstToken = new TypstToken(TypstTokenType.SYMBOL, '\n');
|
|
69
69
|
|
|
70
70
|
export class TypstWriterError extends Error {
|
|
@@ -95,17 +95,19 @@ export class TypstWriter {
|
|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
private writeBuffer(token: TypstToken) {
|
|
98
|
-
const str = token.
|
|
98
|
+
const str = token.toString();
|
|
99
99
|
|
|
100
100
|
if (str === '') {
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
let no_need_space = false;
|
|
105
|
-
//
|
|
106
|
-
no_need_space ||= /[\(\|]$/.test(this.buffer) && /^\w/.test(str);
|
|
105
|
+
// putting the first token in clause
|
|
106
|
+
no_need_space ||= /[\(\[\|]$/.test(this.buffer) && /^\w/.test(str);
|
|
107
|
+
// closing a clause
|
|
108
|
+
no_need_space ||= /^[})\]\|]$/.test(str);
|
|
107
109
|
// putting punctuation
|
|
108
|
-
no_need_space ||= /^[
|
|
110
|
+
no_need_space ||= /^[(_^,;!]$/.test(str);
|
|
109
111
|
// putting a prime
|
|
110
112
|
no_need_space ||= str === "'";
|
|
111
113
|
// continue a number
|
|
@@ -118,6 +120,8 @@ export class TypstWriter {
|
|
|
118
120
|
no_need_space ||= this.buffer === "";
|
|
119
121
|
// str is starting with a space itself
|
|
120
122
|
no_need_space ||= /^\s/.test(str);
|
|
123
|
+
// "&=" instead of "& ="
|
|
124
|
+
no_need_space ||= this.buffer.endsWith('&') && str === '=';
|
|
121
125
|
// other cases
|
|
122
126
|
no_need_space ||= /[\s_^{\(]$/.test(this.buffer);
|
|
123
127
|
if (!no_need_space) {
|
|
@@ -136,7 +140,7 @@ export class TypstWriter {
|
|
|
136
140
|
if (node.content === ',' && this.insideFunctionDepth > 0) {
|
|
137
141
|
this.queue.push(new TypstToken(TypstTokenType.SYMBOL, 'comma'));
|
|
138
142
|
} else {
|
|
139
|
-
this.queue.push(new TypstToken(TypstTokenType.
|
|
143
|
+
this.queue.push(new TypstToken(TypstTokenType.ELEMENT, node.content));
|
|
140
144
|
}
|
|
141
145
|
break;
|
|
142
146
|
}
|
|
@@ -144,10 +148,10 @@ export class TypstWriter {
|
|
|
144
148
|
this.queue.push(new TypstToken(TypstTokenType.SYMBOL, node.content));
|
|
145
149
|
break;
|
|
146
150
|
case 'text':
|
|
147
|
-
this.queue.push(new TypstToken(TypstTokenType.TEXT,
|
|
151
|
+
this.queue.push(new TypstToken(TypstTokenType.TEXT, node.content));
|
|
148
152
|
break;
|
|
149
153
|
case 'comment':
|
|
150
|
-
this.queue.push(new TypstToken(TypstTokenType.COMMENT,
|
|
154
|
+
this.queue.push(new TypstToken(TypstTokenType.COMMENT, node.content));
|
|
151
155
|
break;
|
|
152
156
|
case 'whitespace':
|
|
153
157
|
for (const c of node.content) {
|
|
@@ -178,15 +182,15 @@ export class TypstWriter {
|
|
|
178
182
|
// e.g.
|
|
179
183
|
// y_1' -> y'_1
|
|
180
184
|
// y_{a_1}' -> y'_{a_1}
|
|
181
|
-
this.queue.push(new TypstToken(TypstTokenType.
|
|
185
|
+
this.queue.push(new TypstToken(TypstTokenType.ELEMENT, '\''));
|
|
182
186
|
trailing_space_needed = false;
|
|
183
187
|
}
|
|
184
188
|
if (sub) {
|
|
185
|
-
this.queue.push(new TypstToken(TypstTokenType.
|
|
189
|
+
this.queue.push(new TypstToken(TypstTokenType.ELEMENT, '_'));
|
|
186
190
|
trailing_space_needed = this.appendWithBracketsIfNeeded(sub);
|
|
187
191
|
}
|
|
188
192
|
if (sup && !has_prime) {
|
|
189
|
-
this.queue.push(new TypstToken(TypstTokenType.
|
|
193
|
+
this.queue.push(new TypstToken(TypstTokenType.ELEMENT, '^'));
|
|
190
194
|
trailing_space_needed = this.appendWithBracketsIfNeeded(sup);
|
|
191
195
|
}
|
|
192
196
|
if (trailing_space_needed) {
|
|
@@ -194,26 +198,17 @@ export class TypstWriter {
|
|
|
194
198
|
}
|
|
195
199
|
break;
|
|
196
200
|
}
|
|
197
|
-
case '
|
|
201
|
+
case 'funcCall': {
|
|
198
202
|
const func_symbol: TypstToken = new TypstToken(TypstTokenType.SYMBOL, node.content);
|
|
199
|
-
const [arg0, arg1] = node.args!;
|
|
200
203
|
this.queue.push(func_symbol);
|
|
201
204
|
this.insideFunctionDepth++;
|
|
202
205
|
this.queue.push(TYPST_LEFT_PARENTHESIS);
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}
|
|
210
|
-
case 'unaryFunc': {
|
|
211
|
-
const func_symbol: TypstToken = new TypstToken(TypstTokenType.SYMBOL, node.content);
|
|
212
|
-
const arg0 = node.args![0];
|
|
213
|
-
this.queue.push(func_symbol);
|
|
214
|
-
this.insideFunctionDepth++;
|
|
215
|
-
this.queue.push(TYPST_LEFT_PARENTHESIS);
|
|
216
|
-
this.serialize(arg0);
|
|
206
|
+
for (let i = 0; i < node.args!.length; i++) {
|
|
207
|
+
this.serialize(node.args![i]);
|
|
208
|
+
if (i < node.args!.length - 1) {
|
|
209
|
+
this.queue.push(new TypstToken(TypstTokenType.ELEMENT, ','));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
217
212
|
if (node.options) {
|
|
218
213
|
for (const [key, value] of Object.entries(node.options)) {
|
|
219
214
|
this.queue.push(new TypstToken(TypstTokenType.SYMBOL, `, ${key}: ${value}`));
|
|
@@ -228,7 +223,7 @@ export class TypstWriter {
|
|
|
228
223
|
matrix.forEach((row, i) => {
|
|
229
224
|
row.forEach((cell, j) => {
|
|
230
225
|
if (j > 0) {
|
|
231
|
-
this.queue.push(new TypstToken(TypstTokenType.
|
|
226
|
+
this.queue.push(new TypstToken(TypstTokenType.ELEMENT, '&'));
|
|
232
227
|
}
|
|
233
228
|
this.serialize(cell);
|
|
234
229
|
});
|
|
@@ -261,10 +256,10 @@ export class TypstWriter {
|
|
|
261
256
|
this.serialize(cell);
|
|
262
257
|
// cell.args!.forEach((n) => this.append(n));
|
|
263
258
|
if (j < row.length - 1) {
|
|
264
|
-
this.queue.push(new TypstToken(TypstTokenType.
|
|
259
|
+
this.queue.push(new TypstToken(TypstTokenType.ELEMENT, ','));
|
|
265
260
|
} else {
|
|
266
261
|
if (i < matrix.length - 1) {
|
|
267
|
-
this.queue.push(new TypstToken(TypstTokenType.
|
|
262
|
+
this.queue.push(new TypstToken(TypstTokenType.ELEMENT, ';'));
|
|
268
263
|
}
|
|
269
264
|
}
|
|
270
265
|
});
|
|
@@ -316,9 +311,9 @@ export class TypstWriter {
|
|
|
316
311
|
let token = this.queue[i];
|
|
317
312
|
if (token.eq(SOFT_SPACE)) {
|
|
318
313
|
if (i === this.queue.length - 1) {
|
|
319
|
-
this.queue[i].
|
|
314
|
+
this.queue[i].value = '';
|
|
320
315
|
} else if (this.queue[i + 1].isOneOf([TYPST_RIGHT_PARENTHESIS, TYPST_COMMA, TYPST_NEWLINE])) {
|
|
321
|
-
this.queue[i].
|
|
316
|
+
this.queue[i].value = '';
|
|
322
317
|
}
|
|
323
318
|
}
|
|
324
319
|
}
|
|
@@ -388,13 +383,13 @@ export function convertTree(node: TexNode): TypstNode {
|
|
|
388
383
|
// Special logic for overbrace
|
|
389
384
|
if (base && base.type === 'unaryFunc' && base.content === '\\overbrace' && sup) {
|
|
390
385
|
return new TypstNode(
|
|
391
|
-
'
|
|
386
|
+
'funcCall',
|
|
392
387
|
'overbrace',
|
|
393
388
|
[convertTree(base.args![0]), convertTree(sup)],
|
|
394
389
|
);
|
|
395
390
|
} else if (base && base.type === 'unaryFunc' && base.content === '\\underbrace' && sub) {
|
|
396
391
|
return new TypstNode(
|
|
397
|
-
'
|
|
392
|
+
'funcCall',
|
|
398
393
|
'underbrace',
|
|
399
394
|
[convertTree(base.args![0]), convertTree(sub)],
|
|
400
395
|
);
|
|
@@ -434,7 +429,7 @@ export function convertTree(node: TexNode): TypstNode {
|
|
|
434
429
|
return group;
|
|
435
430
|
}
|
|
436
431
|
return new TypstNode(
|
|
437
|
-
'
|
|
432
|
+
'funcCall',
|
|
438
433
|
'lr',
|
|
439
434
|
[group],
|
|
440
435
|
);
|
|
@@ -444,7 +439,7 @@ export function convertTree(node: TexNode): TypstNode {
|
|
|
444
439
|
return convert_overset(node);
|
|
445
440
|
}
|
|
446
441
|
return new TypstNode(
|
|
447
|
-
'
|
|
442
|
+
'funcCall',
|
|
448
443
|
convertToken(node.content),
|
|
449
444
|
node.args!.map(convertTree),
|
|
450
445
|
);
|
|
@@ -455,7 +450,7 @@ export function convertTree(node: TexNode): TypstNode {
|
|
|
455
450
|
if (node.content === '\\sqrt' && node.data) {
|
|
456
451
|
const data = convertTree(node.data as TexSqrtData); // the number of times to take the root
|
|
457
452
|
return new TypstNode(
|
|
458
|
-
'
|
|
453
|
+
'funcCall',
|
|
459
454
|
'root',
|
|
460
455
|
[data, arg0],
|
|
461
456
|
);
|
|
@@ -463,12 +458,12 @@ export function convertTree(node: TexNode): TypstNode {
|
|
|
463
458
|
// \mathbf{a} -> upright(mathbf(a))
|
|
464
459
|
if (node.content === '\\mathbf') {
|
|
465
460
|
const inner: TypstNode = new TypstNode(
|
|
466
|
-
'
|
|
461
|
+
'funcCall',
|
|
467
462
|
'bold',
|
|
468
463
|
[arg0],
|
|
469
464
|
);
|
|
470
465
|
return new TypstNode(
|
|
471
|
-
'
|
|
466
|
+
'funcCall',
|
|
472
467
|
'upright',
|
|
473
468
|
[inner],
|
|
474
469
|
);
|
|
@@ -489,7 +484,7 @@ export function convertTree(node: TexNode): TypstNode {
|
|
|
489
484
|
return new TypstNode('symbol', text);
|
|
490
485
|
} else {
|
|
491
486
|
return new TypstNode(
|
|
492
|
-
'
|
|
487
|
+
'funcCall',
|
|
493
488
|
'op',
|
|
494
489
|
[new TypstNode('text', text)],
|
|
495
490
|
);
|
|
@@ -498,7 +493,7 @@ export function convertTree(node: TexNode): TypstNode {
|
|
|
498
493
|
|
|
499
494
|
// generic case
|
|
500
495
|
return new TypstNode(
|
|
501
|
-
'
|
|
496
|
+
'funcCall',
|
|
502
497
|
convertToken(node.content),
|
|
503
498
|
node.args!.map(convertTree),
|
|
504
499
|
);
|