tex2typst 0.3.24 → 0.3.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +261 -211
- package/dist/tex-types.d.ts +11 -7
- package/dist/tex2typst.min.js +13 -13
- package/dist/typst-types.d.ts +18 -16
- package/package.json +1 -1
- package/src/convert.ts +131 -101
- package/src/tex-parser.ts +9 -14
- package/src/tex-tokenizer.ts +3 -2
- package/src/tex-types.ts +28 -17
- package/src/typst-parser.ts +39 -19
- package/src/typst-tokenizer.ts +2 -2
- package/src/typst-types.ts +45 -37
- package/src/typst-writer.ts +73 -73
package/src/typst-writer.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TexNode } from "./tex-types";
|
|
2
|
-
import {
|
|
2
|
+
import { TypstFraction, TypstFuncCall, TypstGroup, TypstLeftright, TypstMarkupFunc, TypstMatrixLike, TypstNode, TypstSupsub, TypstTerminal } from "./typst-types";
|
|
3
3
|
import { TypstToken } from "./typst-types";
|
|
4
4
|
import { TypstTokenType } from "./typst-types";
|
|
5
5
|
import { shorthandMap } from "./typst-shorthands";
|
|
@@ -54,7 +54,7 @@ export class TypstWriter {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
private writeBuffer(token: TypstToken) {
|
|
57
|
+
private writeBuffer(previousToken: TypstToken | null, token: TypstToken) {
|
|
58
58
|
const str = token.toString();
|
|
59
59
|
|
|
60
60
|
if (str === '') {
|
|
@@ -84,8 +84,13 @@ export class TypstWriter {
|
|
|
84
84
|
no_need_space ||= this.buffer.endsWith('&') && str === '=';
|
|
85
85
|
// before or after a slash e.g. "a/b" instead of "a / b"
|
|
86
86
|
no_need_space ||= this.buffer.endsWith('/') || str === '/';
|
|
87
|
+
// "[$x + y$]" instead of "[ $ x + y $ ]"
|
|
88
|
+
no_need_space ||= token.type === TypstTokenType.LITERAL;
|
|
87
89
|
// other cases
|
|
88
90
|
no_need_space ||= /[\s_^{\(]$/.test(this.buffer);
|
|
91
|
+
if (previousToken !== null) {
|
|
92
|
+
no_need_space ||= previousToken.type === TypstTokenType.LITERAL;
|
|
93
|
+
}
|
|
89
94
|
if (!no_need_space) {
|
|
90
95
|
this.buffer += ' ';
|
|
91
96
|
}
|
|
@@ -137,7 +142,7 @@ export class TypstWriter {
|
|
|
137
142
|
}
|
|
138
143
|
case 'group': {
|
|
139
144
|
const node = abstractNode as TypstGroup;
|
|
140
|
-
for (const item of node.
|
|
145
|
+
for (const item of node.items) {
|
|
141
146
|
this.serialize(item);
|
|
142
147
|
}
|
|
143
148
|
break;
|
|
@@ -153,9 +158,7 @@ export class TypstWriter {
|
|
|
153
158
|
if (left) {
|
|
154
159
|
this.queue.push(left);
|
|
155
160
|
}
|
|
156
|
-
|
|
157
|
-
this.serialize(item);
|
|
158
|
-
}
|
|
161
|
+
this.serialize(node.body);
|
|
159
162
|
if (right) {
|
|
160
163
|
this.queue.push(right);
|
|
161
164
|
}
|
|
@@ -198,9 +201,9 @@ export class TypstWriter {
|
|
|
198
201
|
this.queue.push(func_symbol);
|
|
199
202
|
this.insideFunctionDepth++;
|
|
200
203
|
this.queue.push(TYPST_LEFT_PARENTHESIS);
|
|
201
|
-
for (let i = 0; i < node.args
|
|
202
|
-
this.serialize(node.args
|
|
203
|
-
if (i < node.args
|
|
204
|
+
for (let i = 0; i < node.args.length; i++) {
|
|
205
|
+
this.serialize(node.args[i]);
|
|
206
|
+
if (i < node.args.length - 1) {
|
|
204
207
|
this.queue.push(new TypstToken(TypstTokenType.ELEMENT, ','));
|
|
205
208
|
}
|
|
206
209
|
}
|
|
@@ -215,7 +218,7 @@ export class TypstWriter {
|
|
|
215
218
|
}
|
|
216
219
|
case 'fraction': {
|
|
217
220
|
const node = abstractNode as TypstFraction;
|
|
218
|
-
const [numerator, denominator] = node.args
|
|
221
|
+
const [numerator, denominator] = node.args;
|
|
219
222
|
const pos = this.queue.length;
|
|
220
223
|
const no_wrap = this.appendWithBracketsIfNeeded(numerator);
|
|
221
224
|
|
|
@@ -230,83 +233,77 @@ export class TypstWriter {
|
|
|
230
233
|
this.appendWithBracketsIfNeeded(denominator);
|
|
231
234
|
break;
|
|
232
235
|
}
|
|
233
|
-
case '
|
|
234
|
-
const node = abstractNode as
|
|
236
|
+
case 'matrixLike': {
|
|
237
|
+
const node = abstractNode as TypstMatrixLike;
|
|
235
238
|
const matrix = node.matrix;
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
239
|
+
|
|
240
|
+
let cell_sep: TypstToken;
|
|
241
|
+
let row_sep: TypstToken;
|
|
242
|
+
if (node.head.eq(TypstMatrixLike.MAT)) {
|
|
243
|
+
cell_sep = new TypstToken(TypstTokenType.ELEMENT, ',');
|
|
244
|
+
row_sep = new TypstToken(TypstTokenType.ELEMENT, ';');
|
|
245
|
+
} else if (node.head.eq(TypstMatrixLike.CASES)) {
|
|
246
|
+
cell_sep = new TypstToken(TypstTokenType.ELEMENT, '&');
|
|
247
|
+
row_sep = new TypstToken(TypstTokenType.ELEMENT, ',');
|
|
248
|
+
} else if (node.head.eq(TypstToken.NONE)){ // head is null
|
|
249
|
+
cell_sep = new TypstToken(TypstTokenType.ELEMENT, '&');
|
|
250
|
+
row_sep = new TypstToken(TypstTokenType.SYMBOL, '\\');
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (!node.head.eq(TypstToken.NONE)) {
|
|
254
|
+
this.queue.push(node.head);
|
|
255
|
+
this.insideFunctionDepth++;
|
|
256
|
+
this.queue.push(TYPST_LEFT_PARENTHESIS);
|
|
257
|
+
if (node.options) {
|
|
258
|
+
for (const [key, value] of Object.entries(node.options)) {
|
|
259
|
+
this.queue.push(new TypstToken(TypstTokenType.LITERAL, `${key}: ${value.toString()}, `));
|
|
240
260
|
}
|
|
241
|
-
this.serialize(cell);
|
|
242
|
-
});
|
|
243
|
-
if (i < matrix.length - 1) {
|
|
244
|
-
this.queue.push(new TypstToken(TypstTokenType.SYMBOL, '\\'));
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
break;
|
|
248
|
-
}
|
|
249
|
-
case 'matrix': {
|
|
250
|
-
const node = abstractNode as TypstMatrix;
|
|
251
|
-
const matrix = node.matrix;
|
|
252
|
-
this.queue.push(new TypstToken(TypstTokenType.SYMBOL, 'mat'));
|
|
253
|
-
this.insideFunctionDepth++;
|
|
254
|
-
this.queue.push(TYPST_LEFT_PARENTHESIS);
|
|
255
|
-
if (node.options) {
|
|
256
|
-
for (const [key, value] of Object.entries(node.options)) {
|
|
257
|
-
this.queue.push(new TypstToken(TypstTokenType.LITERAL, `${key}: ${value.toString()}, `));
|
|
258
261
|
}
|
|
259
262
|
}
|
|
263
|
+
|
|
260
264
|
matrix.forEach((row, i) => {
|
|
261
265
|
row.forEach((cell, j) => {
|
|
262
|
-
// There is a leading & in row
|
|
263
|
-
// if (cell.type === 'ordgroup' && cell.args!.length === 0) {
|
|
264
|
-
// this.queue.push(new TypstNode('atom', ','));
|
|
265
|
-
// return;
|
|
266
|
-
// }
|
|
267
|
-
// if (j == 0 && cell.type === 'newline' && cell.content === '\n') {
|
|
268
|
-
// return;
|
|
269
|
-
// }
|
|
270
266
|
this.serialize(cell);
|
|
271
|
-
// cell.args!.forEach((n) => this.append(n));
|
|
272
267
|
if (j < row.length - 1) {
|
|
273
|
-
this.queue.push(
|
|
268
|
+
this.queue.push(cell_sep);
|
|
274
269
|
} else {
|
|
275
270
|
if (i < matrix.length - 1) {
|
|
276
|
-
this.queue.push(
|
|
271
|
+
this.queue.push(row_sep);
|
|
277
272
|
}
|
|
278
273
|
}
|
|
279
274
|
});
|
|
280
275
|
});
|
|
281
|
-
|
|
282
|
-
|
|
276
|
+
|
|
277
|
+
if (!node.head.eq(TypstToken.NONE)) {
|
|
278
|
+
this.queue.push(TYPST_RIGHT_PARENTHESIS);
|
|
279
|
+
this.insideFunctionDepth--;
|
|
280
|
+
}
|
|
283
281
|
break;
|
|
284
282
|
}
|
|
285
|
-
case '
|
|
286
|
-
const node = abstractNode as
|
|
287
|
-
|
|
288
|
-
this.queue.push(new TypstToken(TypstTokenType.SYMBOL, 'cases'));
|
|
289
|
-
this.insideFunctionDepth++;
|
|
283
|
+
case 'markupFunc': {
|
|
284
|
+
const node = abstractNode as TypstMarkupFunc;
|
|
285
|
+
this.queue.push(node.head);
|
|
290
286
|
this.queue.push(TYPST_LEFT_PARENTHESIS);
|
|
291
287
|
if (node.options) {
|
|
292
|
-
|
|
293
|
-
|
|
288
|
+
const entries = Object.entries(node.options);
|
|
289
|
+
for (let i = 0; i < entries.length; i++) {
|
|
290
|
+
const [key, value] = entries[i];
|
|
291
|
+
this.queue.push(new TypstToken(TypstTokenType.LITERAL, `${key}: ${value.toString()}`));
|
|
292
|
+
if (i < entries.length - 1) {
|
|
293
|
+
this.queue.push(new TypstToken(TypstTokenType.ELEMENT, ','));
|
|
294
|
+
}
|
|
294
295
|
}
|
|
295
296
|
}
|
|
296
|
-
cases.forEach((row, i) => {
|
|
297
|
-
row.forEach((cell, j) => {
|
|
298
|
-
this.serialize(cell);
|
|
299
|
-
if (j < row.length - 1) {
|
|
300
|
-
this.queue.push(new TypstToken(TypstTokenType.ELEMENT, '&'));
|
|
301
|
-
} else {
|
|
302
|
-
if (i < cases.length - 1) {
|
|
303
|
-
this.queue.push(new TypstToken(TypstTokenType.ELEMENT, ','));
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
});
|
|
307
|
-
});
|
|
308
297
|
this.queue.push(TYPST_RIGHT_PARENTHESIS);
|
|
309
|
-
|
|
298
|
+
|
|
299
|
+
this.queue.push(new TypstToken(TypstTokenType.LITERAL, '['));
|
|
300
|
+
for (const frag of node.fragments) {
|
|
301
|
+
this.queue.push(new TypstToken(TypstTokenType.LITERAL, '$'));
|
|
302
|
+
this.serialize(frag);
|
|
303
|
+
this.queue.push(new TypstToken(TypstTokenType.LITERAL, '$'));
|
|
304
|
+
}
|
|
305
|
+
this.queue.push(new TypstToken(TypstTokenType.LITERAL, ']'));
|
|
306
|
+
|
|
310
307
|
break;
|
|
311
308
|
}
|
|
312
309
|
default:
|
|
@@ -315,15 +312,16 @@ export class TypstWriter {
|
|
|
315
312
|
}
|
|
316
313
|
|
|
317
314
|
private appendWithBracketsIfNeeded(node: TypstNode): boolean {
|
|
318
|
-
let need_to_wrap = ['group', 'supsub', '
|
|
315
|
+
let need_to_wrap = ['group', 'supsub', 'matrixLike', 'fraction','empty'].includes(node.type);
|
|
319
316
|
|
|
320
317
|
if (node.type === 'group') {
|
|
321
|
-
|
|
318
|
+
const group = node as TypstGroup;
|
|
319
|
+
if (group.items.length === 0) {
|
|
322
320
|
// e.g. TeX `P_{}` converts to Typst `P_()`
|
|
323
321
|
need_to_wrap = true;
|
|
324
322
|
} else {
|
|
325
|
-
const first =
|
|
326
|
-
const last =
|
|
323
|
+
const first = group.items[0];
|
|
324
|
+
const last = group.items[group.items.length - 1];
|
|
327
325
|
if (is_delimiter(first) && is_delimiter(last)) {
|
|
328
326
|
need_to_wrap = false;
|
|
329
327
|
}
|
|
@@ -361,9 +359,11 @@ export class TypstWriter {
|
|
|
361
359
|
|
|
362
360
|
this.queue = this.queue.filter((token) => !token.eq(dummy_token));
|
|
363
361
|
|
|
364
|
-
this.queue.
|
|
365
|
-
this.
|
|
366
|
-
|
|
362
|
+
for(let i = 0; i < this.queue.length; i++) {
|
|
363
|
+
let token = this.queue[i];
|
|
364
|
+
let previous_token = i === 0 ? null : this.queue[i - 1];
|
|
365
|
+
this.writeBuffer(previous_token, token);
|
|
366
|
+
}
|
|
367
367
|
|
|
368
368
|
this.queue = [];
|
|
369
369
|
}
|