tex2typst 0.2.0 → 0.2.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/dist/index.js +401 -424
- package/dist/parser.d.ts +16 -13
- package/dist/tex2typst.min.js +1 -1
- package/dist/types.d.ts +1 -13
- package/package.json +2 -4
- package/src/parser.ts +413 -480
- package/src/types.ts +1 -15
- package/src/writer.ts +57 -50
package/src/types.ts
CHANGED
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
export interface LatexParseNode {
|
|
2
|
-
type: string;
|
|
3
|
-
content?: string;
|
|
4
|
-
arg1?: LatexParseNode;
|
|
5
|
-
arg2?: LatexParseNode;
|
|
6
|
-
args?: LatexParseNode[];
|
|
7
|
-
base?: LatexParseNode;
|
|
8
|
-
sub?: LatexParseNode;
|
|
9
|
-
sup?: LatexParseNode;
|
|
10
|
-
exponent?: LatexParseNode;
|
|
11
|
-
body?: LatexParseNode | LatexParseNode[] | LatexParseNode[][];
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
1
|
export interface TexSupsubData {
|
|
16
2
|
base: TexNode;
|
|
17
3
|
sup?: TexNode;
|
|
@@ -30,7 +16,7 @@ export interface TexNode {
|
|
|
30
16
|
// For type="sqrt", it's additional argument wrapped square bracket. e.g. 3 in \sqrt[3]{x}
|
|
31
17
|
// For type="supsub", it's base, sup, and sub.
|
|
32
18
|
// For type="array", it's the 2-dimensional matrix.
|
|
33
|
-
|
|
19
|
+
data?: TexSqrtData | TexSupsubData | TexArrayData;
|
|
34
20
|
}
|
|
35
21
|
|
|
36
22
|
export interface TypstNode {
|
package/src/writer.ts
CHANGED
|
@@ -74,24 +74,24 @@ export class TypstWriter {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
public append(node: TexNode) {
|
|
77
|
-
if (node.type === 'empty') {
|
|
77
|
+
if (node.type === 'empty' || node.type === 'whitespace') {
|
|
78
78
|
return;
|
|
79
79
|
} else if (node.type === 'ordgroup') {
|
|
80
80
|
// const index = this.startBlock();
|
|
81
81
|
node.args!.forEach((arg) => this.append(arg));
|
|
82
82
|
// this.endBlock(index);
|
|
83
|
-
} else if (node.type === '
|
|
83
|
+
} else if (node.type === 'element') {
|
|
84
84
|
let content = node.content!;
|
|
85
85
|
if (node.content === ',' && this.insideFunctionDepth > 0) {
|
|
86
86
|
content = 'comma';
|
|
87
87
|
}
|
|
88
|
-
this.queue.push({ type: '
|
|
88
|
+
this.queue.push({ type: 'symbol', content: content });
|
|
89
89
|
} else if (node.type === 'symbol') {
|
|
90
90
|
this.queue.push({ type: 'symbol', content: node.content });
|
|
91
91
|
} else if (node.type === 'text') {
|
|
92
92
|
this.queue.push(node as TypstNode)
|
|
93
93
|
} else if (node.type === 'supsub') {
|
|
94
|
-
let { base, sup, sub } = node.
|
|
94
|
+
let { base, sup, sub } = node.data as TexSupsubData;
|
|
95
95
|
|
|
96
96
|
// Special logic for overbrace
|
|
97
97
|
if (base && base.type === 'unaryFunc' && base.content === '\\overbrace' && sup) {
|
|
@@ -134,7 +134,7 @@ export class TypstWriter {
|
|
|
134
134
|
} else if (node.type === 'leftright') {
|
|
135
135
|
const [left, body, right] = node.args!;
|
|
136
136
|
// These pairs will be handled by Typst compiler by default. No need to add lr()
|
|
137
|
-
if (["[]", "()", "{}", "\\lfloor\\rfloor", "\\lceil\\rceil"].includes(left.content + right.content)) {
|
|
137
|
+
if (["[]", "()", "\\{\\}", "\\lfloor\\rfloor", "\\lceil\\rceil"].includes(left.content + right.content)) {
|
|
138
138
|
this.append(left);
|
|
139
139
|
this.append(body);
|
|
140
140
|
this.append(right);
|
|
@@ -163,12 +163,12 @@ export class TypstWriter {
|
|
|
163
163
|
} else if (node.type === 'unaryFunc') {
|
|
164
164
|
const func_symbol: TypstNode = { type: 'symbol', content: node.content };
|
|
165
165
|
const arg0 = node.args![0];
|
|
166
|
-
if (node.content === '\\sqrt' && node.
|
|
166
|
+
if (node.content === '\\sqrt' && node.data) {
|
|
167
167
|
func_symbol.content = 'root';
|
|
168
168
|
this.queue.push(func_symbol);
|
|
169
169
|
this.insideFunctionDepth ++;
|
|
170
170
|
this.queue.push({ type: 'atom', content: '('});
|
|
171
|
-
this.append(node.
|
|
171
|
+
this.append(node.data as TexSqrtData); // the number of times to take the root
|
|
172
172
|
this.queue.push({ type: 'atom', content: ','});
|
|
173
173
|
this.append(arg0);
|
|
174
174
|
this.queue.push({ type: 'atom', content: ')'});
|
|
@@ -189,7 +189,7 @@ export class TypstWriter {
|
|
|
189
189
|
return;
|
|
190
190
|
} else if (node.content === '\\mathbb') {
|
|
191
191
|
const body = node.args![0];
|
|
192
|
-
if (body.type === '
|
|
192
|
+
if (body.type === 'element' && /^[A-Z]$/.test(body.content)) {
|
|
193
193
|
// \mathbb{R} -> RR
|
|
194
194
|
this.queue.push({ type: 'symbol', content: body.content + body.content});
|
|
195
195
|
return;
|
|
@@ -228,54 +228,64 @@ export class TypstWriter {
|
|
|
228
228
|
} else if (node.type === 'newline') {
|
|
229
229
|
this.queue.push({ type: 'newline', content: '\n'});
|
|
230
230
|
return;
|
|
231
|
-
} else if (node.type === '
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
231
|
+
} else if (node.type === 'beginend') {
|
|
232
|
+
if (node.content!.startsWith('align')) {
|
|
233
|
+
// align, align*, alignat, alignat*, aligned, etc.
|
|
234
|
+
const matrix = node.data as TexNode[][];
|
|
235
|
+
matrix.forEach((row, i) => {
|
|
236
|
+
row.forEach((cell, j) => {
|
|
237
|
+
if (j > 0) {
|
|
238
|
+
this.queue.push({ type: 'atom', content: '&' });
|
|
239
|
+
}
|
|
240
|
+
this.append(cell);
|
|
241
|
+
});
|
|
242
|
+
if (i < matrix.length - 1) {
|
|
243
|
+
this.queue.push({ type: 'symbol', content: '\\\\' });
|
|
237
244
|
}
|
|
238
|
-
this.append(cell);
|
|
239
245
|
});
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
// There is a leading & in row
|
|
253
|
-
if (cell.type === 'ordgroup' && cell.args!.length === 0) {
|
|
254
|
-
this.queue.push({ type: 'atom', content: ',' });
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
// if (j == 0 && cell.type === 'newline' && cell.content === '\n') {
|
|
258
|
-
// return;
|
|
259
|
-
// }
|
|
260
|
-
this.append(cell);
|
|
261
|
-
// cell.args!.forEach((n) => this.append(n));
|
|
262
|
-
if (j < row.length - 1) {
|
|
263
|
-
this.queue.push({ type: 'atom', content: ',' });
|
|
264
|
-
} else {
|
|
265
|
-
if (i < matrix.length - 1) {
|
|
266
|
-
this.queue.push({ type: 'atom', content: ';' });
|
|
246
|
+
} else {
|
|
247
|
+
const matrix = node.data as TexNode[][];
|
|
248
|
+
this.queue.push({ type: 'symbol', content: 'mat' });
|
|
249
|
+
this.insideFunctionDepth ++;
|
|
250
|
+
this.queue.push({ type: 'atom', content: '('});
|
|
251
|
+
this.queue.push({type: 'symbol', content: 'delim: #none, '});
|
|
252
|
+
matrix.forEach((row, i) => {
|
|
253
|
+
row.forEach((cell, j) => {
|
|
254
|
+
// There is a leading & in row
|
|
255
|
+
if (cell.type === 'ordgroup' && cell.args!.length === 0) {
|
|
256
|
+
this.queue.push({ type: 'atom', content: ',' });
|
|
257
|
+
return;
|
|
267
258
|
}
|
|
268
|
-
|
|
259
|
+
// if (j == 0 && cell.type === 'newline' && cell.content === '\n') {
|
|
260
|
+
// return;
|
|
261
|
+
// }
|
|
262
|
+
this.append(cell);
|
|
263
|
+
// cell.args!.forEach((n) => this.append(n));
|
|
264
|
+
if (j < row.length - 1) {
|
|
265
|
+
this.queue.push({ type: 'atom', content: ',' });
|
|
266
|
+
} else {
|
|
267
|
+
if (i < matrix.length - 1) {
|
|
268
|
+
this.queue.push({ type: 'atom', content: ';' });
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
});
|
|
269
272
|
});
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
+
this.queue.push({ type: 'atom', content: ')'});
|
|
274
|
+
this.insideFunctionDepth --;
|
|
275
|
+
}
|
|
276
|
+
} else if (node.type === 'matrix') {
|
|
273
277
|
} else if (node.type === 'unknownMacro') {
|
|
274
278
|
if (this.nonStrict) {
|
|
275
279
|
this.queue.push({ type: 'symbol', content: node.content });
|
|
276
280
|
} else {
|
|
277
281
|
throw new TypstWriterError(`Unknown macro: ${node.content}`, node);
|
|
278
282
|
}
|
|
283
|
+
} else if (node.type === 'control') {
|
|
284
|
+
if (node.content === '\\\\') {
|
|
285
|
+
this.queue.push({ type: 'symbol', content: node.content });
|
|
286
|
+
} else {
|
|
287
|
+
throw new TypstWriterError(`Unknown control sequence: ${node.content}`, node);
|
|
288
|
+
}
|
|
279
289
|
} else if (node.type === 'comment') {
|
|
280
290
|
this.queue.push({ type: 'comment', content: node.content });
|
|
281
291
|
} else {
|
|
@@ -317,10 +327,7 @@ export class TypstWriter {
|
|
|
317
327
|
}
|
|
318
328
|
|
|
319
329
|
private appendWithBracketsIfNeeded(node: TexNode): boolean {
|
|
320
|
-
const
|
|
321
|
-
const is_single_function = (node.type === 'unaryFunc' || node.type === 'binaryFunc' || node.type === 'leftright');
|
|
322
|
-
|
|
323
|
-
const is_single = ['atom', 'symbol', 'unaryFunc', 'binaryFunc', 'leftright'].includes(node.type);
|
|
330
|
+
const is_single = ['symbol', 'element', 'unaryFunc', 'binaryFunc', 'leftright'].includes(node.type);
|
|
324
331
|
if (is_single) {
|
|
325
332
|
this.append(node);
|
|
326
333
|
} else {
|