tex2typst 0.4.0 → 0.5.0

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/convert.ts CHANGED
@@ -8,7 +8,7 @@ import { TypstToken } from "./typst-types";
8
8
  import { TypstTokenType } from "./typst-types";
9
9
  import { symbolMap, reverseSymbolMap } from "./map";
10
10
  import { array_includes, array_intersperse, array_split } from "./generic";
11
- import { assert } from "./util";
11
+ import { assert } from "./utils";
12
12
  import { TEX_BINARY_COMMANDS, TEX_UNARY_COMMANDS } from "./tex-tokenizer";
13
13
 
14
14
 
@@ -191,27 +191,10 @@ function convert_tex_array_align_literal(alignLiteral: string): TypstNamedParams
191
191
  const TYPST_LEFT_PARENTHESIS: TypstToken = new TypstToken(TypstTokenType.ELEMENT, '(');
192
192
  const TYPST_RIGHT_PARENTHESIS: TypstToken = new TypstToken(TypstTokenType.ELEMENT, ')');
193
193
 
194
- function is_delimiter(c: TypstNode): boolean {
195
- return c.head.type === TypstTokenType.ELEMENT && ['(', ')', '[', ']', '{', '}', '|', '⌊', '⌋', '⌈', '⌉'].includes(c.head.value);
196
- }
197
194
 
198
195
  function appendWithBracketsIfNeeded(node: TypstNode): TypstNode {
199
196
  let need_to_wrap = ['group', 'supsub', 'matrixLike', 'fraction','empty'].includes(node.type);
200
197
 
201
- if (node.type === 'group') {
202
- const group = node as TypstGroup;
203
- if (group.items.length === 0) {
204
- // e.g. TeX `P_{}` converts to Typst `P_()`
205
- need_to_wrap = true;
206
- } else {
207
- const first = group.items[0];
208
- const last = group.items[group.items.length - 1];
209
- if (is_delimiter(first) && is_delimiter(last)) {
210
- need_to_wrap = false;
211
- }
212
- }
213
- }
214
-
215
198
  if (need_to_wrap) {
216
199
  return new TypstLeftright(null, {
217
200
  left: TYPST_LEFT_PARENTHESIS,
@@ -263,7 +246,6 @@ export function convert_tex_node_to_typst(abstractNode: TexNode, options: Tex2Ty
263
246
  sub: sub? convert_tex_node_to_typst(sub, options) : null,
264
247
  };
265
248
 
266
- data.base = appendWithBracketsIfNeeded(data.base);
267
249
  if (data.sup) {
268
250
  data.sup = appendWithBracketsIfNeeded(data.sup);
269
251
  }
@@ -433,6 +415,22 @@ export function convert_tex_node_to_typst(abstractNode: TexNode, options: Tex2Ty
433
415
  );
434
416
  }
435
417
 
418
+ // \not X -> X.not
419
+ if (node.head.value === '\\not') {
420
+ const sym = convert_tex_node_to_typst(node.args[0], options);
421
+ assert(sym.type === "terminal");
422
+ if(sym.head.type === TypstTokenType.SYMBOL) {
423
+ return new TypstToken(TypstTokenType.SYMBOL, sym.head.value + '.not').toNode();
424
+ } else {
425
+ switch(sym.head.value) {
426
+ case '=':
427
+ return new TypstToken(TypstTokenType.SYMBOL, 'eq.not').toNode();
428
+ default:
429
+ throw new Error(`Not supported: \\not ${sym.head.value}`);
430
+ }
431
+ }
432
+ }
433
+
436
434
  if (node.head.value === '\\overset') {
437
435
  return convert_overset(node, options);
438
436
  }
@@ -573,14 +571,6 @@ const TYPST_BINARY_FUNCTIONS: string[] = [
573
571
  ];
574
572
  */
575
573
 
576
- function apply_escape_if_needed(c: TexToken): TexToken {
577
- if (['{', '}', '%'].includes(c.value)) {
578
- return new TexToken(TexTokenType.ELEMENT, '\\' + c.value);
579
- }
580
- return c;
581
- }
582
-
583
-
584
574
  function typst_token_to_tex(token: TypstToken): TexToken {
585
575
  switch (token.type) {
586
576
  case TypstTokenType.NONE:
@@ -588,12 +578,28 @@ function typst_token_to_tex(token: TypstToken): TexToken {
588
578
  return TexToken.EMPTY;
589
579
  case TypstTokenType.SYMBOL: {
590
580
  const _typst_symbol_to_tex = function(symbol: string): string {
591
- if (reverseSymbolMap.has(symbol)) {
592
- return '\\' + reverseSymbolMap.get(symbol)!;
593
- } else {
594
- return '\\' + symbol;
581
+ switch(symbol) {
582
+ case 'eq':
583
+ return '=';
584
+ case 'plus':
585
+ return '+';
586
+ case 'minus':
587
+ return '-';
588
+ case 'percent':
589
+ return '%';
590
+ default: {
591
+ if (reverseSymbolMap.has(symbol)) {
592
+ return '\\' + reverseSymbolMap.get(symbol);
593
+ } else {
594
+ return '\\' + symbol;
595
+ }
596
+ }
595
597
  }
596
598
  }
599
+ if (token.value.endsWith('.not')) {
600
+ const sym = _typst_symbol_to_tex(token.value.slice(0, -4));
601
+ return new TexToken(TexTokenType.COMMAND, sym.startsWith('\\') ? `\\not${sym}` : `\\not ${sym}`);
602
+ }
597
603
  return new TexToken(TexTokenType.COMMAND, _typst_symbol_to_tex(token.value));
598
604
  }
599
605
  case TypstTokenType.ELEMENT: {
@@ -954,4 +960,3 @@ export function convert_typst_node_to_tex(abstractNode: TypstNode, options: Typs
954
960
  throw new Error('[convert_typst_node_to_tex] Unimplemented type: ' + abstractNode.type);
955
961
  }
956
962
  }
957
-
package/src/generic.ts CHANGED
@@ -1,8 +1,8 @@
1
- interface IEquatable {
2
- eq(other: IEquatable): boolean;
1
+ interface IEquatable<T> {
2
+ eq(other: T): boolean;
3
3
  }
4
4
 
5
- export function array_equal<T extends IEquatable>(a: T[], b: T[]): boolean {
5
+ export function array_equal<T extends IEquatable<T>>(a: T[], b: T[]): boolean {
6
6
  /*
7
7
  if (a.length !== b.length) {
8
8
  return false;
@@ -17,7 +17,7 @@ export function array_equal<T extends IEquatable>(a: T[], b: T[]): boolean {
17
17
  return a.length === b.length && a.every((x, i) => x.eq(b[i]));
18
18
  }
19
19
 
20
- export function array_find<T extends IEquatable>(array: T[], item: T, start: number = 0): number {
20
+ export function array_find<T extends IEquatable<T>>(array: T[], item: T, start: number = 0): number {
21
21
  /*
22
22
  for (let i = start; i < array.length; i++) {
23
23
  if (array[i].eq(item)) {
@@ -30,7 +30,7 @@ export function array_find<T extends IEquatable>(array: T[], item: T, start: num
30
30
  return index === -1 ? -1 : index + start;
31
31
  }
32
32
 
33
- export function array_includes<T extends IEquatable>(array: T[], item: T): boolean {
33
+ export function array_includes<T extends IEquatable<T>>(array: T[], item: T): boolean {
34
34
  /*
35
35
  for (const x of array) {
36
36
  if (x.eq(item)) {
@@ -44,7 +44,7 @@ export function array_includes<T extends IEquatable>(array: T[], item: T): boole
44
44
 
45
45
  // e.g. input array=['a', 'b', '+', 'c', '+', 'd', 'e'], sep = '+'
46
46
  // return [['a', 'b'], ['c'], ['d', 'e']]
47
- export function array_split<T extends IEquatable>(array: T[], sep: T): T[][] {
47
+ export function array_split<T extends IEquatable<T>>(array: T[], sep: T): T[][] {
48
48
  const res: T[][] = [];
49
49
  let current_slice: T[] = [];
50
50
  for (const i of array) {