tex2typst 0.3.27-beta.1 → 0.3.27
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/README.md +1 -1
- package/dist/index.d.ts +23 -24
- package/dist/index.js +338 -314
- package/dist/parser.js +23 -0
- package/dist/tex2typst.min.js +12 -12
- package/package.json +1 -1
- package/src/convert.ts +53 -2
- package/src/exposed-types.ts +23 -24
- package/src/index.ts +7 -3
- package/src/jslex.ts +1 -1
- package/src/tex-tokenizer.ts +1 -0
- package/src/tex2typst.ts +2 -4
- package/src/typst-parser.ts +9 -10
- package/src/typst-types.ts +484 -230
- package/src/typst-writer.ts +28 -274
- package/tests/cheat-sheet.test.ts +42 -0
- package/tests/cheat-sheet.toml +304 -0
- package/tests/example.ts +15 -0
- package/tests/general-symbols.test.ts +22 -0
- package/tests/general-symbols.toml +755 -0
- package/tests/integration-tex2typst.yaml +89 -0
- package/tests/struct-bidirection.yaml +179 -0
- package/tests/struct-tex2typst.yaml +443 -0
- package/tests/struct-typst2tex.yaml +412 -0
- package/tests/symbol.yml +123 -0
- package/tests/test-common.ts +26 -0
- package/tests/tex-parser.test.ts +57 -0
- package/tests/tex-to-typst.test.ts +143 -0
- package/tests/typst-parser.test.ts +134 -0
- package/tests/typst-to-tex.test.ts +76 -0
- package/tsconfig.json +4 -4
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { describe, it, test, expect } from 'vitest';
|
|
2
|
+
import { tokenize_tex } from '../src/tex-tokenizer';
|
|
3
|
+
import { parseTex } from '../src/tex-parser';
|
|
4
|
+
import { tex2typst } from '../src/index';
|
|
5
|
+
import { TypstWriterError } from '../src/typst-writer';
|
|
6
|
+
import { TexNode, TexToken } from '../src/tex-types';
|
|
7
|
+
import type { Tex2TypstOptions } from '../src/exposed-types';
|
|
8
|
+
import { loadTestCases, TestCase } from './test-common';
|
|
9
|
+
import { ConverterError } from '../src/convert';
|
|
10
|
+
|
|
11
|
+
describe('options', () => {
|
|
12
|
+
it('nonStrict = false', function () {
|
|
13
|
+
const input = '\\nonExistentCommand';
|
|
14
|
+
// must throw error
|
|
15
|
+
expect(() => tex2typst(input, { nonStrict: false })).toThrowError(ConverterError);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
it('fracToSlash = true', function () {
|
|
20
|
+
const input = '\\frac{a}{b}';
|
|
21
|
+
const expected = 'a/b';
|
|
22
|
+
const res = tex2typst(input, { fracToSlash: true });
|
|
23
|
+
expect(res).toEqual(expected);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('fracToSlash = false', function () {
|
|
27
|
+
const input = '\\frac{a}{b}';
|
|
28
|
+
const expected = 'frac(a, b)';
|
|
29
|
+
const res = tex2typst(input, { fracToSlash: false });
|
|
30
|
+
expect(res).toEqual(expected);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
it('nonAsciiWrapper = ""', function () {
|
|
35
|
+
const input = 'a + b = \\text{こにちは、世界}';
|
|
36
|
+
const expected = 'a + b = "こにちは、世界"';
|
|
37
|
+
const res = tex2typst(input);
|
|
38
|
+
expect(res).toEqual(expected);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('nonAsciiWrapper = "ut"', function () {
|
|
42
|
+
const input = 'a + b = \\text{こにちは、世界}';
|
|
43
|
+
const expected = 'a + b = ut("こにちは、世界")';
|
|
44
|
+
const res = tex2typst(input, { nonAsciiWrapper: 'ut' });
|
|
45
|
+
expect(res).toEqual(expected);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('preferShorthands = true', function () {
|
|
49
|
+
const map = new Map<string, string>([
|
|
50
|
+
['a \\rightarrow b', 'a -> b'],
|
|
51
|
+
['a \\to b', 'a -> b'],
|
|
52
|
+
['a \\implies b', 'a ==> b'],
|
|
53
|
+
['a \\iff b', 'a <==> b'],
|
|
54
|
+
['a \\ll b', 'a << b'],
|
|
55
|
+
['a \\gg b', 'a >> b'],
|
|
56
|
+
|
|
57
|
+
]);
|
|
58
|
+
for(const [input, expected] of map.entries()) {
|
|
59
|
+
const res = tex2typst(input, { preferShorthands: true });
|
|
60
|
+
expect(res).toEqual(expected);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('preferShorthands = false', function () {
|
|
65
|
+
const map = new Map<string, string>([
|
|
66
|
+
['a \\rightarrow b', 'a arrow.r b'],
|
|
67
|
+
['a \\to b', 'a arrow.r b'],
|
|
68
|
+
['a \\implies b', 'a arrow.r.double.long b'],
|
|
69
|
+
['a \\iff b', 'a arrow.l.r.double.long b'],
|
|
70
|
+
['a \\ll b', 'a lt.double b'],
|
|
71
|
+
['a \\gg b', 'a gt.double b'],
|
|
72
|
+
|
|
73
|
+
]);
|
|
74
|
+
for(const [input, expected] of map.entries()) {
|
|
75
|
+
const res = tex2typst(input, { preferShorthands: false });
|
|
76
|
+
expect(res).toEqual(expected);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it ('customTexMacros', function () {
|
|
81
|
+
const input = '\\myop y=\\sgn(x)';
|
|
82
|
+
const expected = 'op("myop") y = op("sgn")(x)';
|
|
83
|
+
const res = tex2typst(input, { customTexMacros: {
|
|
84
|
+
'\\myop': '\\operatorname{myop}',
|
|
85
|
+
'\\sgn': '\\operatorname{sgn}',
|
|
86
|
+
} });
|
|
87
|
+
expect(res).toEqual(expected);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it ('customTexMacros 2', function () {
|
|
91
|
+
const input = '123 \\foo 456';
|
|
92
|
+
const expected = '123 root(3, x) 456';
|
|
93
|
+
const res = tex2typst(input, { customTexMacros: {
|
|
94
|
+
'\\foo': '\\sqrt[3]{x}',
|
|
95
|
+
} });
|
|
96
|
+
expect(res).toEqual(expected);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
const caseFiles = ["struct-tex2typst.yaml", "symbol.yml", "struct-bidirection.yaml", "integration-tex2typst.yaml"];
|
|
102
|
+
|
|
103
|
+
caseFiles.forEach((ymlFilename) => {
|
|
104
|
+
const suite = loadTestCases(ymlFilename);
|
|
105
|
+
describe(ymlFilename, () => {
|
|
106
|
+
suite.cases.forEach((c: TestCase) => {
|
|
107
|
+
test(c.title, function() {
|
|
108
|
+
const {tex, typst} = c;
|
|
109
|
+
let tokens: null | TexToken[] = null;
|
|
110
|
+
let tex_node: null | TexNode = null;
|
|
111
|
+
let result: null | string = null;
|
|
112
|
+
try {
|
|
113
|
+
const settings: Tex2TypstOptions = {
|
|
114
|
+
nonStrict: c.nonStrict? c.nonStrict: false,
|
|
115
|
+
preferShorthands: c.preferShorthands !== undefined? c.preferShorthands: true,
|
|
116
|
+
inftyToOo: c.inftyToOo !== undefined? c.inftyToOo: false,
|
|
117
|
+
customTexMacros: c.customTexMacros? c.customTexMacros: {},
|
|
118
|
+
};
|
|
119
|
+
tokens = tokenize_tex(tex);
|
|
120
|
+
tex_node = parseTex(tex, settings.customTexMacros!);
|
|
121
|
+
result = tex2typst(tex, settings);
|
|
122
|
+
if (result !== typst) {
|
|
123
|
+
console.log(`====== 😭 Wrong ======`);
|
|
124
|
+
console.log(tex);
|
|
125
|
+
console.log(tokens);
|
|
126
|
+
console.dir(tex_node, {depth: null});
|
|
127
|
+
}
|
|
128
|
+
expect(result).toBe(typst);
|
|
129
|
+
} catch (e) {
|
|
130
|
+
console.log(`====== 😭 Error ======`);
|
|
131
|
+
if (e instanceof TypstWriterError) {
|
|
132
|
+
console.log(e.node);
|
|
133
|
+
}
|
|
134
|
+
if (tex_node !== null) {
|
|
135
|
+
console.dir(tex_node, {depth: null});
|
|
136
|
+
}
|
|
137
|
+
console.log(tex);
|
|
138
|
+
throw e;
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
});
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { tokenize_typst } from '../src/typst-tokenizer';
|
|
3
|
+
import { TypstParser } from '../src/typst-parser';
|
|
4
|
+
import { TypstFraction, TypstFuncCall, TypstGroup, TypstLeftright, TypstSupsub, TypstTerminal, TypstToken, TypstTokenType } from '../src/typst-types';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
describe('typst-tokenizer', () => {
|
|
8
|
+
it('a + b', function () {
|
|
9
|
+
const res = tokenize_typst('a + b');
|
|
10
|
+
expect(res).toEqual([
|
|
11
|
+
new TypstToken(TypstTokenType.ELEMENT, 'a'),
|
|
12
|
+
new TypstToken(TypstTokenType.SPACE, ' '),
|
|
13
|
+
new TypstToken(TypstTokenType.ELEMENT, '+'),
|
|
14
|
+
new TypstToken(TypstTokenType.SPACE, ' '),
|
|
15
|
+
new TypstToken(TypstTokenType.ELEMENT, 'b'),
|
|
16
|
+
]);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('a (x)', function () {
|
|
20
|
+
const res = tokenize_typst('a (x)');
|
|
21
|
+
expect(res).toEqual([
|
|
22
|
+
new TypstToken(TypstTokenType.ELEMENT, 'a'),
|
|
23
|
+
new TypstToken(TypstTokenType.SPACE, ' '),
|
|
24
|
+
new TypstToken(TypstTokenType.ELEMENT, '('),
|
|
25
|
+
new TypstToken(TypstTokenType.ELEMENT, 'x'),
|
|
26
|
+
new TypstToken(TypstTokenType.ELEMENT, ')'),
|
|
27
|
+
]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('f(x)', function () {
|
|
31
|
+
const res = tokenize_typst('f(x)');
|
|
32
|
+
expect(res).toEqual([
|
|
33
|
+
new TypstToken(TypstTokenType.ELEMENT, 'f'),
|
|
34
|
+
new TypstToken(TypstTokenType.ELEMENT, '('),
|
|
35
|
+
new TypstToken(TypstTokenType.ELEMENT, 'x'),
|
|
36
|
+
new TypstToken(TypstTokenType.ELEMENT, ')'),
|
|
37
|
+
]);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('comment', function() {
|
|
41
|
+
const res = tokenize_typst('a // comment');
|
|
42
|
+
expect(res).toEqual([
|
|
43
|
+
new TypstToken(TypstTokenType.ELEMENT, 'a'),
|
|
44
|
+
new TypstToken(TypstTokenType.SPACE, ' '),
|
|
45
|
+
new TypstToken(TypstTokenType.COMMENT, ' comment'),
|
|
46
|
+
]);
|
|
47
|
+
})
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('typst-parser', () => {
|
|
51
|
+
const parser = new TypstParser();
|
|
52
|
+
it('a + b', function () {
|
|
53
|
+
const tokens = tokenize_typst('a + b');
|
|
54
|
+
const res = parser.parse(tokens);
|
|
55
|
+
expect(res).toEqual(new TypstGroup([
|
|
56
|
+
new TypstTerminal(new TypstToken(TypstTokenType.ELEMENT, 'a')),
|
|
57
|
+
new TypstTerminal(new TypstToken(TypstTokenType.SPACE, ' ')),
|
|
58
|
+
new TypstTerminal(new TypstToken(TypstTokenType.ELEMENT, '+')),
|
|
59
|
+
new TypstTerminal(new TypstToken(TypstTokenType.SPACE, ' ')),
|
|
60
|
+
new TypstTerminal(new TypstToken(TypstTokenType.ELEMENT, 'b')),
|
|
61
|
+
]));
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('a (x)', function () {
|
|
65
|
+
const tokens = tokenize_typst('a (x)');
|
|
66
|
+
const res = parser.parse(tokens);
|
|
67
|
+
expect(res).toEqual(new TypstGroup([
|
|
68
|
+
new TypstTerminal(new TypstToken(TypstTokenType.ELEMENT, 'a')),
|
|
69
|
+
new TypstTerminal(new TypstToken(TypstTokenType.SPACE, ' ')),
|
|
70
|
+
new TypstLeftright(null, {
|
|
71
|
+
body: new TypstTerminal(new TypstToken(TypstTokenType.ELEMENT, 'x')),
|
|
72
|
+
left: new TypstToken(TypstTokenType.ELEMENT, '('),
|
|
73
|
+
right: new TypstToken(TypstTokenType.ELEMENT, ')')
|
|
74
|
+
})
|
|
75
|
+
]));
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('f(x)', function () {
|
|
79
|
+
const tokens = tokenize_typst('f(x)');
|
|
80
|
+
const res = parser.parse(tokens);
|
|
81
|
+
expect(res).toEqual(new TypstFuncCall(new TypstToken(TypstTokenType.ELEMENT, 'f'), [
|
|
82
|
+
new TypstTerminal(new TypstToken(TypstTokenType.ELEMENT, 'x')),
|
|
83
|
+
]));
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('root(x, 3)', function () {
|
|
87
|
+
const tokens = tokenize_typst('root(x, 3)');
|
|
88
|
+
const res = parser.parse(tokens);
|
|
89
|
+
expect(res).toEqual(new TypstFuncCall(new TypstToken(TypstTokenType.SYMBOL, 'root'), [
|
|
90
|
+
new TypstTerminal(new TypstToken(TypstTokenType.ELEMENT, 'x')),
|
|
91
|
+
new TypstTerminal(new TypstToken(TypstTokenType.ELEMENT, '3')),
|
|
92
|
+
]));
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('lim_(x arrow.r 0)', function () {
|
|
96
|
+
const tokens = tokenize_typst('lim_(x arrow.r 0)');
|
|
97
|
+
const res = parser.parse(tokens);
|
|
98
|
+
expect(res).toEqual(new TypstSupsub({
|
|
99
|
+
base: new TypstTerminal(new TypstToken(TypstTokenType.SYMBOL, 'lim')),
|
|
100
|
+
sub: new TypstGroup([
|
|
101
|
+
new TypstTerminal(new TypstToken(TypstTokenType.ELEMENT, 'x')),
|
|
102
|
+
new TypstTerminal(new TypstToken(TypstTokenType.SPACE, ' ')),
|
|
103
|
+
new TypstTerminal(new TypstToken(TypstTokenType.SYMBOL, 'arrow.r')),
|
|
104
|
+
new TypstTerminal(new TypstToken(TypstTokenType.SPACE, ' ')),
|
|
105
|
+
new TypstTerminal(new TypstToken(TypstTokenType.ELEMENT, '0')),
|
|
106
|
+
]),
|
|
107
|
+
sup: null,
|
|
108
|
+
}));
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('a -> b', function () {
|
|
112
|
+
const tokens = tokenize_typst('a -> b');
|
|
113
|
+
const res = parser.parse(tokens);
|
|
114
|
+
expect(res).toEqual(new TypstGroup([
|
|
115
|
+
new TypstTerminal(new TypstToken(TypstTokenType.ELEMENT, 'a')),
|
|
116
|
+
new TypstTerminal(new TypstToken(TypstTokenType.SPACE, ' ')),
|
|
117
|
+
new TypstTerminal(new TypstToken(TypstTokenType.SYMBOL, 'arrow.r')),
|
|
118
|
+
new TypstTerminal(new TypstToken(TypstTokenType.SPACE, ' ')),
|
|
119
|
+
new TypstTerminal(new TypstToken(TypstTokenType.ELEMENT, 'b')),
|
|
120
|
+
]));
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('1/(2/3)', function () {
|
|
124
|
+
const tokens = tokenize_typst('1/(2/3)');
|
|
125
|
+
const res = parser.parse(tokens);
|
|
126
|
+
expect(res).toEqual(new TypstFraction([
|
|
127
|
+
new TypstTerminal(new TypstToken(TypstTokenType.ELEMENT, '1')),
|
|
128
|
+
new TypstFraction([
|
|
129
|
+
new TypstTerminal(new TypstToken(TypstTokenType.ELEMENT, '2')),
|
|
130
|
+
new TypstTerminal(new TypstToken(TypstTokenType.ELEMENT, '3')),
|
|
131
|
+
]),
|
|
132
|
+
]));
|
|
133
|
+
});
|
|
134
|
+
});
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
|
|
2
|
+
import { describe, it, test, expect } from 'vitest';
|
|
3
|
+
import { parseTypst } from '../src/typst-parser';
|
|
4
|
+
import { TexWriter } from '../src/tex-writer';
|
|
5
|
+
import { convert_typst_node_to_tex } from '../src/convert';
|
|
6
|
+
import { loadTestCases, TestCase } from './test-common';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
describe('examples', () => {
|
|
11
|
+
it('a + b', function () {
|
|
12
|
+
const typst_node = parseTypst('a + b');
|
|
13
|
+
const tex_node = convert_typst_node_to_tex(typst_node);
|
|
14
|
+
const writer = new TexWriter();
|
|
15
|
+
writer.append(tex_node);
|
|
16
|
+
const res = writer.finalize();
|
|
17
|
+
expect(res).toEqual('a + b');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('sqrt(x)', function () {
|
|
21
|
+
const typst_node = parseTypst('sqrt(x)');
|
|
22
|
+
const tex_node = convert_typst_node_to_tex(typst_node);
|
|
23
|
+
const writer = new TexWriter();
|
|
24
|
+
writer.append(tex_node);
|
|
25
|
+
const res = writer.finalize();
|
|
26
|
+
expect(res).toEqual('\\sqrt{x}');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('integral_a^b f(x) dif x', function () {
|
|
30
|
+
const typst_node = parseTypst('integral_a^b f(x) dif x');
|
|
31
|
+
const tex_node = convert_typst_node_to_tex(typst_node);
|
|
32
|
+
const writer = new TexWriter();
|
|
33
|
+
writer.append(tex_node);
|
|
34
|
+
const res = writer.finalize();
|
|
35
|
+
expect(res).toEqual('\\int_a^b f(x) \\mathrm{d} x');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('lr({a + 1/3))', function () {
|
|
39
|
+
const typst_node = parseTypst('lr({a + 1/3))');
|
|
40
|
+
const tex_node = convert_typst_node_to_tex(typst_node);
|
|
41
|
+
const writer = new TexWriter();
|
|
42
|
+
writer.append(tex_node);
|
|
43
|
+
const res = writer.finalize();
|
|
44
|
+
expect(res).toEqual('\\left\\{a + \\frac{1}{3} \\right)');
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
describe('struct-typst2tex.yaml', function () {
|
|
51
|
+
const suite = loadTestCases('struct-typst2tex.yaml');
|
|
52
|
+
suite.cases.forEach((c: TestCase) => {
|
|
53
|
+
test(c.title, function () {
|
|
54
|
+
const typst_node = parseTypst(c.typst);
|
|
55
|
+
const tex_node = convert_typst_node_to_tex(typst_node);
|
|
56
|
+
const writer = new TexWriter();
|
|
57
|
+
writer.append(tex_node);
|
|
58
|
+
const res = writer.finalize();
|
|
59
|
+
expect(res).toEqual(c.tex);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe('struct-bidirection.yaml', function () {
|
|
65
|
+
const suite = loadTestCases('struct-bidirection.yaml');
|
|
66
|
+
suite.cases.forEach((c: TestCase) => {
|
|
67
|
+
test(c.title, function () {
|
|
68
|
+
const typst_node = parseTypst(c.typst);
|
|
69
|
+
const tex_node = convert_typst_node_to_tex(typst_node);
|
|
70
|
+
const writer = new TexWriter();
|
|
71
|
+
writer.append(tex_node);
|
|
72
|
+
const res = writer.finalize();
|
|
73
|
+
expect(res).toEqual(c.tex);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
});
|
package/tsconfig.json
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
/* Modules */
|
|
26
26
|
// "module": "es6", /* Specify what module code is generated. */
|
|
27
27
|
// "rootDir": "./", /* Specify the root folder within your source files. */
|
|
28
|
-
|
|
28
|
+
"moduleResolution": "bundler", /* Specify how TypeScript looks up a file from a given module specifier. */
|
|
29
29
|
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
|
30
30
|
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
|
31
31
|
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
|
|
78
78
|
/* Type Checking */
|
|
79
79
|
"strict": true, /* Enable all strict type-checking options. */
|
|
80
|
-
"noImplicitAny": false, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
|
80
|
+
// "noImplicitAny": false, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
|
81
81
|
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
|
82
82
|
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
|
83
83
|
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
|
@@ -101,10 +101,10 @@
|
|
|
101
101
|
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
|
102
102
|
},
|
|
103
103
|
"include": [
|
|
104
|
-
"src/**/*.ts"
|
|
104
|
+
"src/**/*.ts",
|
|
105
|
+
"tests/**/*.ts",
|
|
105
106
|
],
|
|
106
107
|
"exclude": [
|
|
107
108
|
"src/tex2typst.ts",
|
|
108
|
-
"tests/**/*"
|
|
109
109
|
]
|
|
110
110
|
}
|