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/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
- irregularData?: TexSqrtData | TexSupsubData | TexArrayData;
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 === 'atom') {
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: 'atom', content: content });
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.irregularData as TexSupsubData;
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.irregularData) {
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.irregularData as TexSqrtData); // the number of times to take the root
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 === 'symbol' && /^[A-Z]$/.test(body.content)) {
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 === 'align') {
232
- const matrix = node.irregularData as TexNode[][];
233
- matrix.forEach((row, i) => {
234
- row.forEach((cell, j) => {
235
- if (j > 0) {
236
- this.queue.push({ type: 'atom', content: '&' });
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
- if (i < matrix.length - 1) {
241
- this.queue.push({ type: 'symbol', content: '\\\\' });
242
- }
243
- });
244
- } else if (node.type === 'matrix') {
245
- const matrix = node.irregularData as TexNode[][];
246
- this.queue.push({ type: 'symbol', content: 'mat' });
247
- this.insideFunctionDepth ++;
248
- this.queue.push({ type: 'atom', content: '('});
249
- this.queue.push({type: 'symbol', content: 'delim: #none, '});
250
- matrix.forEach((row, i) => {
251
- row.forEach((cell, j) => {
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
- this.queue.push({ type: 'atom', content: ')'});
272
- this.insideFunctionDepth --;
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 is_single_atom = (node.type === 'atom');
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 {