tex2typst 0.3.23 → 0.3.25

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/types.d.ts DELETED
@@ -1,109 +0,0 @@
1
- export declare enum TexTokenType {
2
- ELEMENT = 0,
3
- COMMAND = 1,
4
- LITERAL = 2,
5
- COMMENT = 3,
6
- SPACE = 4,
7
- NEWLINE = 5,
8
- CONTROL = 6,
9
- UNKNOWN = 7
10
- }
11
- export declare class TexToken {
12
- type: TexTokenType;
13
- value: string;
14
- constructor(type: TexTokenType, value: string);
15
- eq(token: TexToken): boolean;
16
- toString(): string;
17
- }
18
- export interface TexSupsubData {
19
- base: TexNode;
20
- sup?: TexNode;
21
- sub?: TexNode;
22
- }
23
- export type TexSqrtData = TexNode;
24
- export type TexArrayData = TexNode[][];
25
- /**
26
- * element: 0-9, a-z, A-Z, punctuations such as +-/*,:; etc.
27
- * symbol: LaTeX macro with no parameter. e.g. \sin \cos \int \sum
28
- * unaryFunc: LaTeX macro with 1 parameter. e.g. \sqrt{3} \log{x} \exp{x}
29
- * binaryFunc: LaTeX macro with 2 parameters. e.g. \frac{1}{2}
30
- * text: text enclosed by braces. e.g. \text{hello world}
31
- * empty: special type when something is empty. e.g. the base of _{a} or ^{a}
32
- * whitespace: space, tab, newline
33
- */
34
- type TexNodeType = 'element' | 'text' | 'literal' | 'comment' | 'whitespace' | 'control' | 'ordgroup' | 'supsub' | 'unaryFunc' | 'binaryFunc' | 'leftright' | 'beginend' | 'symbol' | 'empty' | 'unknownMacro';
35
- export declare class TexNode {
36
- type: TexNodeType;
37
- content: string;
38
- args?: TexNode[];
39
- data?: TexSqrtData | TexSupsubData | TexArrayData;
40
- constructor(type: TexNodeType, content: string, args?: TexNode[], data?: TexSqrtData | TexSupsubData | TexArrayData);
41
- eq(other: TexNode): boolean;
42
- serialize(): TexToken[];
43
- }
44
- export declare enum TypstTokenType {
45
- NONE = 0,
46
- SYMBOL = 1,
47
- ELEMENT = 2,
48
- LITERAL = 3,
49
- TEXT = 4,
50
- COMMENT = 5,
51
- SPACE = 6,
52
- CONTROL = 7,
53
- NEWLINE = 8
54
- }
55
- export declare class TypstToken {
56
- type: TypstTokenType;
57
- value: string;
58
- constructor(type: TypstTokenType, content: string);
59
- eq(other: TypstToken): boolean;
60
- isOneOf(tokens: TypstToken[]): boolean;
61
- toNode(): TypstNode;
62
- toString(): string;
63
- }
64
- export interface TypstSupsubData {
65
- base: TypstNode;
66
- sup?: TypstNode;
67
- sub?: TypstNode;
68
- }
69
- export type TypstArrayData = TypstNode[][];
70
- export interface TypstLrData {
71
- leftDelim: string | null;
72
- rightDelim: string | null;
73
- }
74
- type TypstNodeType = 'atom' | 'symbol' | 'text' | 'literal' | 'control' | 'comment' | 'whitespace' | 'none' | 'group' | 'supsub' | 'funcCall' | 'fraction' | 'align' | 'matrix' | 'cases' | 'unknown';
75
- export type TypstNamedParams = {
76
- [key: string]: TypstNode;
77
- };
78
- export declare class TypstNode {
79
- type: TypstNodeType;
80
- content: string;
81
- args?: TypstNode[];
82
- data?: TypstSupsubData | TypstArrayData | TypstLrData;
83
- options?: TypstNamedParams;
84
- constructor(type: TypstNodeType, content: string, args?: TypstNode[], data?: TypstSupsubData | TypstArrayData | TypstLrData);
85
- setOptions(options: TypstNamedParams): void;
86
- eq(other: TypstNode): boolean;
87
- isOverHigh(): boolean;
88
- toString(): string;
89
- }
90
- export declare const TYPST_NONE: TypstNode;
91
- /**
92
- * ATTENTION:
93
- * Don't use any options except those explicitly documented in
94
- * https://github.com/qwinsi/tex2typst/blob/main/docs/api-reference.md
95
- * Any undocumented options may be not working at present or break in the future!
96
- */
97
- export interface Tex2TypstOptions {
98
- nonStrict?: boolean; /** default is true */
99
- preferShorthands?: boolean; /** default is true */
100
- keepSpaces?: boolean; /** default is false */
101
- fracToSlash?: boolean; /** default is true */
102
- inftyToOo?: boolean; /** default is false */
103
- optimize?: boolean; /** default is true */
104
- nonAsciiWrapper?: string; /** default is "" */
105
- customTexMacros?: {
106
- [key: string]: string;
107
- };
108
- }
109
- export {};
package/src/types.ts DELETED
@@ -1,414 +0,0 @@
1
- import { array_includes } from "./generic";
2
-
3
- export enum TexTokenType {
4
- ELEMENT,
5
- COMMAND,
6
- LITERAL,
7
- COMMENT,
8
- SPACE,
9
- NEWLINE,
10
- CONTROL,
11
- UNKNOWN,
12
- }
13
-
14
- export class TexToken {
15
- type: TexTokenType;
16
- value: string;
17
-
18
- constructor(type: TexTokenType, value: string) {
19
- this.type = type;
20
- this.value = value;
21
- }
22
-
23
- public eq(token: TexToken): boolean {
24
- return this.type === token.type && this.value === token.value;
25
- }
26
-
27
- public toString(): string {
28
- switch (this.type) {
29
- case TexTokenType.COMMENT:
30
- return "%" + this.value;
31
- default:
32
- return this.value;
33
- }
34
- }
35
- }
36
-
37
-
38
- export interface TexSupsubData {
39
- base: TexNode;
40
- sup?: TexNode;
41
- sub?: TexNode;
42
- }
43
-
44
- export type TexSqrtData = TexNode;
45
-
46
- export type TexArrayData = TexNode[][];
47
-
48
- /**
49
- * element: 0-9, a-z, A-Z, punctuations such as +-/*,:; etc.
50
- * symbol: LaTeX macro with no parameter. e.g. \sin \cos \int \sum
51
- * unaryFunc: LaTeX macro with 1 parameter. e.g. \sqrt{3} \log{x} \exp{x}
52
- * binaryFunc: LaTeX macro with 2 parameters. e.g. \frac{1}{2}
53
- * text: text enclosed by braces. e.g. \text{hello world}
54
- * empty: special type when something is empty. e.g. the base of _{a} or ^{a}
55
- * whitespace: space, tab, newline
56
- */
57
- type TexNodeType = 'element' | 'text' | 'literal' | 'comment' | 'whitespace' | 'control' | 'ordgroup' | 'supsub'
58
- | 'unaryFunc' | 'binaryFunc' | 'leftright' | 'beginend' | 'symbol' | 'empty' | 'unknownMacro';
59
-
60
-
61
- function apply_escape_if_needed(c: string) {
62
- if (['{', '}', '%'].includes(c)) {
63
- return '\\' + c;
64
- }
65
- return c;
66
- }
67
-
68
- export class TexNode {
69
- type: TexNodeType;
70
- content: string;
71
- args?: TexNode[];
72
- // For type="sqrt", it's additional argument wrapped square bracket. e.g. 3 in \sqrt[3]{x}
73
- // For type="supsub", it's base, sup, and sub.
74
- // For type="beginend", it's the 2-dimensional matrix.
75
- data?: TexSqrtData | TexSupsubData | TexArrayData;
76
-
77
- constructor(type: TexNodeType, content: string, args?: TexNode[],
78
- data?: TexSqrtData | TexSupsubData | TexArrayData) {
79
- this.type = type;
80
- this.content = content;
81
- this.args = args;
82
- this.data = data;
83
- }
84
-
85
- // Note that this is only shallow equality.
86
- public eq(other: TexNode): boolean {
87
- return this.type === other.type && this.content === other.content;
88
- }
89
-
90
- public serialize(): TexToken[] {
91
- switch (this.type) {
92
- case 'empty':
93
- return [];
94
- case 'element': {
95
- let c = this.content;
96
- c = apply_escape_if_needed(c);
97
- return [new TexToken(TexTokenType.ELEMENT, c)];
98
- }
99
- case 'symbol':
100
- return [new TexToken(TexTokenType.COMMAND, this.content)];
101
- case 'literal':
102
- return [new TexToken(TexTokenType.LITERAL, this.content)];
103
- case 'text':
104
- return [
105
- new TexToken(TexTokenType.COMMAND, '\\text'),
106
- new TexToken(TexTokenType.ELEMENT, '{'),
107
- new TexToken(TexTokenType.LITERAL, this.content),
108
- new TexToken(TexTokenType.ELEMENT, '}'),
109
- ];
110
- case 'comment':
111
- return [new TexToken(TexTokenType.COMMENT, this.content)];
112
- case 'whitespace': {
113
- const tokens: TexToken[] = [];
114
- for (const c of this.content) {
115
- const token_type = c === ' ' ? TexTokenType.SPACE : TexTokenType.NEWLINE;
116
- tokens.push(new TexToken(token_type, c));
117
- }
118
- return tokens;
119
- }
120
- case 'ordgroup': {
121
- return this.args!.map((n) => n.serialize()).flat();
122
- }
123
- case 'leftright': {
124
- let tokens = this.args!.map((n) => n.serialize()).flat();
125
- tokens.splice(0, 0, new TexToken(TexTokenType.COMMAND, '\\left'));
126
- tokens.splice(tokens.length - 1, 0, new TexToken(TexTokenType.COMMAND, '\\right'));
127
-
128
- return tokens;
129
- }
130
- case 'unaryFunc': {
131
- let tokens: TexToken[] = [];
132
- tokens.push(new TexToken(TexTokenType.COMMAND, this.content));
133
-
134
- // special hook for \sqrt
135
- if (this.content === '\\sqrt' && this.data) {
136
- tokens.push(new TexToken(TexTokenType.ELEMENT, '['));
137
- tokens = tokens.concat((this.data! as TexSqrtData).serialize());
138
- tokens.push(new TexToken(TexTokenType.ELEMENT, ']'));
139
- }
140
- // special hook for \operatorname
141
- if (this.content === '\\operatorname' && this.args!.length === 1 && this.args![0].type === 'text') {
142
- const text = this.args![0].content;
143
- tokens.push(new TexToken(TexTokenType.ELEMENT, '{'));
144
- // this.serialize(new TexNode('symbol', text));
145
- tokens.push(new TexToken(TexTokenType.COMMAND, text));
146
- tokens.push(new TexToken(TexTokenType.ELEMENT, '}'));
147
- return tokens;
148
- }
149
-
150
- tokens.push(new TexToken(TexTokenType.ELEMENT, '{'));
151
- tokens = tokens.concat(this.args![0].serialize());
152
- tokens.push(new TexToken(TexTokenType.ELEMENT, '}'));
153
-
154
- return tokens;
155
- }
156
- case 'binaryFunc': {
157
- let tokens: TexToken[] = [];
158
- tokens.push(new TexToken(TexTokenType.COMMAND, this.content));
159
- tokens.push(new TexToken(TexTokenType.ELEMENT, '{'));
160
- tokens = tokens.concat(this.args![0].serialize());
161
- tokens.push(new TexToken(TexTokenType.ELEMENT, '}'));
162
- tokens.push(new TexToken(TexTokenType.ELEMENT, '{'));
163
- tokens = tokens.concat(this.args![1].serialize());
164
- tokens.push(new TexToken(TexTokenType.ELEMENT, '}'));
165
- return tokens;
166
- }
167
- case 'supsub': {
168
- let tokens: TexToken[] = [];
169
- const { base, sup, sub } = this.data! as TexSupsubData;
170
- tokens = tokens.concat(base.serialize());
171
-
172
- // TODO: should return true for more cases e.g. a_{\theta} instead of a_\theta
173
- function should_wrap_in_braces(node: TexNode): boolean {
174
- if(node.type === 'ordgroup' || node.type === 'supsub' || node.type === 'empty') {
175
- return true;
176
- } else if(node.type === 'element' && /\d+(\.\d+)?/.test(node.content) && node.content.length > 1) {
177
- // a number with more than 1 digit as a subscript/superscript should be wrapped in braces
178
- return true;
179
- } else {
180
- return false;
181
- }
182
- }
183
-
184
- if (sub) {
185
- tokens.push(new TexToken(TexTokenType.CONTROL, '_'));
186
- if (should_wrap_in_braces(sub)) {
187
- tokens.push(new TexToken(TexTokenType.ELEMENT, '{'));
188
- tokens = tokens.concat(sub.serialize());
189
- tokens.push(new TexToken(TexTokenType.ELEMENT, '}'));
190
- } else {
191
- tokens = tokens.concat(sub.serialize());
192
- }
193
- }
194
- if (sup) {
195
- tokens.push(new TexToken(TexTokenType.CONTROL, '^'));
196
- if (should_wrap_in_braces(sup)) {
197
- tokens.push(new TexToken(TexTokenType.ELEMENT, '{'));
198
- tokens = tokens.concat(sup.serialize());
199
- tokens.push(new TexToken(TexTokenType.ELEMENT, '}'));
200
- } else {
201
- tokens = tokens.concat(sup.serialize());
202
- }
203
- }
204
- return tokens;
205
- }
206
- case 'control': {
207
- return [new TexToken(TexTokenType.CONTROL, this.content)];
208
- }
209
- case 'beginend': {
210
- let tokens: TexToken[] = [];
211
- const matrix = this.data as TexArrayData;
212
- tokens.push(new TexToken(TexTokenType.COMMAND, `\\begin{${this.content}}`));
213
- tokens.push(new TexToken(TexTokenType.NEWLINE, '\n'));
214
- for (let i = 0; i < matrix.length; i++) {
215
- const row = matrix[i];
216
- for (let j = 0; j < row.length; j++) {
217
- const cell = row[j];
218
- tokens = tokens.concat(cell.serialize());
219
- if (j !== row.length - 1) {
220
- tokens.push(new TexToken(TexTokenType.CONTROL, '&'));
221
- }
222
- }
223
- if (i !== matrix.length - 1) {
224
- tokens.push(new TexToken(TexTokenType.CONTROL, '\\\\'));
225
- }
226
- }
227
- tokens.push(new TexToken(TexTokenType.NEWLINE, '\n'));
228
- tokens.push(new TexToken(TexTokenType.COMMAND, `\\end{${this.content}}`));
229
- return tokens;
230
- }
231
- default:
232
- throw new Error('[TexNode.serialize] Unimplemented type: ' + this.type);
233
- }
234
- }
235
- }
236
-
237
- export enum TypstTokenType {
238
- NONE,
239
- SYMBOL,
240
- ELEMENT,
241
- LITERAL,
242
- TEXT,
243
- COMMENT,
244
- SPACE,
245
- CONTROL,
246
- NEWLINE,
247
- }
248
-
249
- export class TypstToken {
250
- type: TypstTokenType;
251
- value: string;
252
-
253
- constructor(type: TypstTokenType, content: string) {
254
- this.type = type;
255
- this.value = content;
256
- }
257
-
258
- eq(other: TypstToken): boolean {
259
- return this.type === other.type && this.value === other.value;
260
- }
261
-
262
- isOneOf(tokens: TypstToken[]): boolean {
263
- return array_includes(tokens, this);
264
- }
265
-
266
- public toNode(): TypstNode {
267
- switch(this.type) {
268
- case TypstTokenType.NONE:
269
- return new TypstNode('none', '#none');
270
- case TypstTokenType.LITERAL:
271
- return new TypstNode('literal', this.value);
272
- case TypstTokenType.TEXT:
273
- return new TypstNode('text', this.value);
274
- case TypstTokenType.COMMENT:
275
- return new TypstNode('comment', this.value);
276
- case TypstTokenType.SPACE:
277
- case TypstTokenType.NEWLINE:
278
- return new TypstNode('whitespace', this.value);
279
- case TypstTokenType.ELEMENT:
280
- return new TypstNode('atom', this.value);
281
- case TypstTokenType.SYMBOL:
282
- return new TypstNode('symbol', this.value);
283
- case TypstTokenType.CONTROL: {
284
- const controlChar = this.value;
285
- switch (controlChar) {
286
- case '':
287
- case '_':
288
- case '^':
289
- throw new Error(`Should not convert ${controlChar} to a node`);
290
- case '&':
291
- return new TypstNode('control', '&');
292
- case '\\':
293
- return new TypstNode('control', '\\');
294
- default:
295
- throw new Error(`Unexpected control character ${controlChar}`);
296
- }
297
- }
298
- default:
299
- throw new Error(`Unexpected token type ${this.type}`);
300
- }
301
- }
302
-
303
- public toString(): string {
304
- switch (this.type) {
305
- case TypstTokenType.TEXT:
306
- return `"${this.value}"`;
307
- case TypstTokenType.COMMENT:
308
- return `//${this.value}`;
309
- default:
310
- return this.value;
311
- }
312
- }
313
- }
314
-
315
- export interface TypstSupsubData {
316
- base: TypstNode;
317
- sup?: TypstNode;
318
- sub?: TypstNode;
319
- }
320
-
321
- export type TypstArrayData = TypstNode[][];
322
- export interface TypstLrData {
323
- leftDelim: string | null;
324
- rightDelim: string | null;
325
- }
326
-
327
- type TypstNodeType = 'atom' | 'symbol' | 'text' | 'literal' | 'control' | 'comment' | 'whitespace'
328
- | 'none' | 'group' | 'supsub' | 'funcCall' | 'fraction' | 'align' | 'matrix' | 'cases' | 'unknown';
329
-
330
- export type TypstNamedParams = { [key: string]: TypstNode };
331
-
332
-
333
- export class TypstNode {
334
- type: TypstNodeType;
335
- content: string;
336
- args?: TypstNode[];
337
- data?: TypstSupsubData | TypstArrayData | TypstLrData;
338
- // Some Typst functions accept additional options. e.g. mat() has option "delim", op() has option "limits"
339
- options?: TypstNamedParams;
340
-
341
- constructor(type: TypstNodeType, content: string, args?: TypstNode[],
342
- data?: TypstSupsubData | TypstArrayData| TypstLrData) {
343
- this.type = type;
344
- this.content = content;
345
- this.args = args;
346
- this.data = data;
347
- }
348
-
349
- public setOptions(options: TypstNamedParams) {
350
- this.options = options;
351
- }
352
-
353
- // Note that this is only shallow equality.
354
- public eq(other: TypstNode): boolean {
355
- return this.type === other.type && this.content === other.content;
356
- }
357
-
358
- // whether the node is over high so that if it's wrapped in braces, \left and \right should be used in its TeX form
359
- // e.g. 1/2 is over high, "2" is not.
360
- public isOverHigh(): boolean {
361
- switch (this.type) {
362
- case 'fraction':
363
- return true;
364
- case 'funcCall': {
365
- if (this.content === 'frac') {
366
- return true;
367
- }
368
- return this.args!.some((n) => n.isOverHigh());
369
- }
370
- case 'group':
371
- return this.args!.some((n) => n.isOverHigh());
372
- case 'supsub':
373
- return (this.data as TypstSupsubData).base.isOverHigh();
374
- case 'align':
375
- case 'cases':
376
- case 'matrix':
377
- return true;
378
- default:
379
- return false;
380
- }
381
- }
382
-
383
- public toString(): string {
384
- switch (this.type) {
385
- case 'text':
386
- return `"${this.content}"`;
387
- case 'comment':
388
- return `//${this.content}`;
389
- default:
390
- return this.content;
391
- }
392
- }
393
- }
394
-
395
- // #none
396
- export const TYPST_NONE = new TypstNode('none', '#none');
397
-
398
- /**
399
- * ATTENTION:
400
- * Don't use any options except those explicitly documented in
401
- * https://github.com/qwinsi/tex2typst/blob/main/docs/api-reference.md
402
- * Any undocumented options may be not working at present or break in the future!
403
- */
404
- export interface Tex2TypstOptions {
405
- nonStrict?: boolean; /** default is true */
406
- preferShorthands?: boolean; /** default is true */
407
- keepSpaces?: boolean; /** default is false */
408
- fracToSlash?: boolean; /** default is true */
409
- inftyToOo?: boolean; /** default is false */
410
- optimize?: boolean; /** default is true */
411
- nonAsciiWrapper?: string; /** default is "" */
412
- customTexMacros?: { [key: string]: string };
413
- // TODO: custom typst functions
414
- }