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/dist/index.js +324 -306
- package/dist/tex2typst.min.js +10 -11
- package/package.json +2 -2
- package/src/convert.ts +37 -32
- package/src/generic.ts +6 -6
- package/src/map.ts +136 -79
- package/src/tex-parser.ts +53 -64
- package/src/tex-tokenizer.ts +1 -0
- package/src/tex-types.ts +1 -1
- package/src/typst-parser.ts +114 -160
- package/src/typst-shorthands.ts +6 -3
- package/src/typst-types.ts +2 -2
- package/tests/cheat-sheet.test.ts +0 -42
- package/tests/cheat-sheet.toml +0 -304
- package/tests/example.ts +0 -15
- package/tests/general-symbols.test.ts +0 -22
- package/tests/general-symbols.toml +0 -755
- package/tests/integration-tex2typst.yaml +0 -89
- package/tests/struct-bidirection.yaml +0 -203
- package/tests/struct-tex2typst.yaml +0 -451
- package/tests/struct-typst2tex.yaml +0 -412
- package/tests/symbol.yml +0 -126
- package/tests/test-common.ts +0 -26
- package/tests/tex-parser.test.ts +0 -97
- package/tests/tex-to-typst.test.ts +0 -136
- package/tests/typst-parser.test.ts +0 -134
- package/tests/typst-to-tex.test.ts +0 -100
- /package/src/{util.ts → utils.ts} +0 -0
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 "./
|
|
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
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
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:
|
|
1
|
+
interface IEquatable<T> {
|
|
2
|
+
eq(other: T): boolean;
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
-
export function array_equal<T extends IEquatable
|
|
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
|
|
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
|
|
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
|
|
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) {
|