tex2typst 0.3.23 → 0.3.24
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/convert.d.ts +9 -3
- package/dist/generic.d.ts +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2092 -2009
- package/dist/tex-parser.d.ts +1 -1
- package/dist/tex-tokenizer.d.ts +1 -1
- package/dist/tex-types.d.ts +103 -0
- package/dist/tex-writer.d.ts +1 -2
- package/dist/tex2typst.min.js +13 -13
- package/dist/typst-parser.d.ts +6 -4
- package/dist/typst-tokenizer.d.ts +1 -1
- package/dist/typst-types.d.ts +95 -0
- package/dist/typst-writer.d.ts +4 -2
- package/package.json +1 -1
- package/src/convert.ts +455 -393
- package/src/generic.ts +28 -2
- package/src/index.ts +1 -1
- package/src/map.ts +5 -0
- package/src/tex-parser.ts +45 -54
- package/src/tex-tokenizer.ts +1 -1
- package/src/tex-types.ts +358 -0
- package/src/tex-writer.ts +3 -51
- package/src/typst-parser.ts +53 -55
- package/src/typst-tokenizer.ts +86 -85
- package/src/typst-types.ts +221 -0
- package/src/typst-writer.ts +79 -65
- package/src/util.ts +1 -1
- package/dist/types.d.ts +0 -109
- package/src/types.ts +0 -414
package/src/tex-types.ts
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import { assert } from "./util";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ELEMENT: 0-9, a-z, A-Z, punctuations such as +-/*,:; etc.
|
|
5
|
+
* COMMAND: LaTeX macro with no parameter. e.g. \sin \cos \int \sum
|
|
6
|
+
* EMPTY: special type when something is empty. e.g. the base of _{a} or ^{a}
|
|
7
|
+
*/
|
|
8
|
+
export enum TexTokenType {
|
|
9
|
+
EMPTY,
|
|
10
|
+
ELEMENT,
|
|
11
|
+
COMMAND,
|
|
12
|
+
LITERAL,
|
|
13
|
+
COMMENT,
|
|
14
|
+
SPACE,
|
|
15
|
+
NEWLINE,
|
|
16
|
+
CONTROL,
|
|
17
|
+
UNKNOWN,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class TexToken {
|
|
21
|
+
type: TexTokenType;
|
|
22
|
+
value: string;
|
|
23
|
+
|
|
24
|
+
constructor(type: TexTokenType, value: string) {
|
|
25
|
+
this.type = type;
|
|
26
|
+
this.value = value;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public eq(token: TexToken): boolean {
|
|
30
|
+
return this.type === token.type && this.value === token.value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public toString(): string {
|
|
34
|
+
switch (this.type) {
|
|
35
|
+
case TexTokenType.COMMENT:
|
|
36
|
+
return "%" + this.value;
|
|
37
|
+
default:
|
|
38
|
+
return this.value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public toNode(): TexNode {
|
|
43
|
+
return new TexTerminal(this);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public static readonly EMPTY = new TexToken(TexTokenType.EMPTY, '');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
export interface TexSupsubData {
|
|
51
|
+
base: TexNode;
|
|
52
|
+
sup: TexNode | null;
|
|
53
|
+
sub: TexNode | null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// \left. or \right. will be represented as null.
|
|
57
|
+
export interface TexLeftRightData {
|
|
58
|
+
left: TexToken | null;
|
|
59
|
+
right: TexToken | null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* funcCall: LaTeX macro with 1 or more parameters. e.g. \sqrt{3} \log{x} \exp{x} \frac{1}{2}
|
|
64
|
+
* text: text enclosed by braces. e.g. \text{hello world}
|
|
65
|
+
*/
|
|
66
|
+
type TexNodeType = 'terminal' | 'text' | 'ordgroup' | 'supsub'
|
|
67
|
+
| 'funcCall' | 'leftright' | 'beginend';
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
export abstract class TexNode {
|
|
71
|
+
type: TexNodeType;
|
|
72
|
+
head: TexToken;
|
|
73
|
+
args?: TexNode[];
|
|
74
|
+
|
|
75
|
+
constructor(type: TexNodeType, head: TexToken | null, args?: TexNode[]) {
|
|
76
|
+
this.type = type;
|
|
77
|
+
this.head = head ? head : TexToken.EMPTY;
|
|
78
|
+
this.args = args;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Note that this is only shallow equality.
|
|
82
|
+
public eq(other: TexNode): boolean {
|
|
83
|
+
return this.type === other.type && this.head.eq(other.head);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
abstract serialize(): TexToken[];
|
|
87
|
+
|
|
88
|
+
// Note: toString() is expensive. Do not use it on performance-critical code path.
|
|
89
|
+
public toString(): string {
|
|
90
|
+
/*
|
|
91
|
+
let buffer = '';
|
|
92
|
+
const tokens = this.serialize();
|
|
93
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
94
|
+
buffer = writeTexTokenBuffer(buffer, tokens[i]);
|
|
95
|
+
}
|
|
96
|
+
return buffer;
|
|
97
|
+
*/
|
|
98
|
+
return this.serialize().reduce(writeTexTokenBuffer, '');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export class TexTerminal extends TexNode {
|
|
103
|
+
constructor(head: TexToken) {
|
|
104
|
+
super('terminal', head);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public serialize(): TexToken[] {
|
|
108
|
+
switch(this.head.type) {
|
|
109
|
+
case TexTokenType.EMPTY:
|
|
110
|
+
return [];
|
|
111
|
+
case TexTokenType.ELEMENT:
|
|
112
|
+
case TexTokenType.COMMAND:
|
|
113
|
+
case TexTokenType.LITERAL:
|
|
114
|
+
case TexTokenType.COMMENT:
|
|
115
|
+
case TexTokenType.CONTROL: {
|
|
116
|
+
return [this.head];
|
|
117
|
+
}
|
|
118
|
+
case TexTokenType.SPACE:
|
|
119
|
+
case TexTokenType.NEWLINE: {
|
|
120
|
+
const tokens: TexToken[] = [];
|
|
121
|
+
for (const c of this.head.value) {
|
|
122
|
+
const token_type = c === ' ' ? TexTokenType.SPACE : TexTokenType.NEWLINE;
|
|
123
|
+
tokens.push(new TexToken(token_type, c));
|
|
124
|
+
}
|
|
125
|
+
return tokens;
|
|
126
|
+
}
|
|
127
|
+
default:
|
|
128
|
+
throw new Error(`Unknown terminal token type: ${this.head.type}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export class TexText extends TexNode {
|
|
134
|
+
constructor(head: TexToken) {
|
|
135
|
+
assert(head.type === TexTokenType.LITERAL);
|
|
136
|
+
|
|
137
|
+
super('text', head);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public serialize(): TexToken[] {
|
|
141
|
+
return [
|
|
142
|
+
new TexToken(TexTokenType.COMMAND, '\\text'),
|
|
143
|
+
new TexToken(TexTokenType.ELEMENT, '{'),
|
|
144
|
+
this.head,
|
|
145
|
+
new TexToken(TexTokenType.ELEMENT, '}'),
|
|
146
|
+
];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export class TexGroup extends TexNode {
|
|
151
|
+
constructor(args: TexNode[]) {
|
|
152
|
+
super('ordgroup', TexToken.EMPTY, args);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public serialize(): TexToken[] {
|
|
156
|
+
return this.args!.map((n) => n.serialize()).flat();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export class TexSupSub extends TexNode {
|
|
161
|
+
public base: TexNode;
|
|
162
|
+
public sup: TexNode | null;
|
|
163
|
+
public sub: TexNode | null;
|
|
164
|
+
|
|
165
|
+
constructor(data: TexSupsubData) {
|
|
166
|
+
super('supsub', TexToken.EMPTY, []);
|
|
167
|
+
this.base = data.base;
|
|
168
|
+
this.sup = data.sup;
|
|
169
|
+
this.sub = data.sub;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
public serialize(): TexToken[] {
|
|
173
|
+
let tokens: TexToken[] = [];
|
|
174
|
+
const { base, sup, sub } = this;
|
|
175
|
+
tokens = tokens.concat(base.serialize());
|
|
176
|
+
|
|
177
|
+
// TODO: should return true for more cases e.g. a_{\theta} instead of a_\theta
|
|
178
|
+
function should_wrap_in_braces(node: TexNode): boolean {
|
|
179
|
+
if(node.type === 'ordgroup' || node.type === 'supsub' || node.head.type === TexTokenType.EMPTY) {
|
|
180
|
+
return true;
|
|
181
|
+
} else if(node.head.type === TexTokenType.ELEMENT && /\d+(\.\d+)?/.test(node.head.value) && node.head.value.length > 1) {
|
|
182
|
+
// a number with more than 1 digit as a subscript/superscript should be wrapped in braces
|
|
183
|
+
return true;
|
|
184
|
+
} else {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (sub) {
|
|
190
|
+
tokens.push(new TexToken(TexTokenType.CONTROL, '_'));
|
|
191
|
+
if (should_wrap_in_braces(sub)) {
|
|
192
|
+
tokens.push(new TexToken(TexTokenType.ELEMENT, '{'));
|
|
193
|
+
tokens = tokens.concat(sub.serialize());
|
|
194
|
+
tokens.push(new TexToken(TexTokenType.ELEMENT, '}'));
|
|
195
|
+
} else {
|
|
196
|
+
tokens = tokens.concat(sub.serialize());
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (sup) {
|
|
200
|
+
tokens.push(new TexToken(TexTokenType.CONTROL, '^'));
|
|
201
|
+
if (should_wrap_in_braces(sup)) {
|
|
202
|
+
tokens.push(new TexToken(TexTokenType.ELEMENT, '{'));
|
|
203
|
+
tokens = tokens.concat(sup.serialize());
|
|
204
|
+
tokens.push(new TexToken(TexTokenType.ELEMENT, '}'));
|
|
205
|
+
} else {
|
|
206
|
+
tokens = tokens.concat(sup.serialize());
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return tokens;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export class TexFuncCall extends TexNode {
|
|
214
|
+
// For type="sqrt", it's additional argument wrapped square bracket. e.g. 3 in \sqrt[3]{x}
|
|
215
|
+
public data: TexNode | null;
|
|
216
|
+
|
|
217
|
+
constructor(head: TexToken, args: TexNode[], data: TexNode | null = null) {
|
|
218
|
+
super('funcCall', head, args);
|
|
219
|
+
this.data = data;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
public serialize(): TexToken[] {
|
|
223
|
+
let tokens: TexToken[] = [];
|
|
224
|
+
tokens.push(this.head);
|
|
225
|
+
|
|
226
|
+
// special hook for \sqrt
|
|
227
|
+
if (this.head.value === '\\sqrt' && this.data) {
|
|
228
|
+
tokens.push(new TexToken(TexTokenType.ELEMENT, '['));
|
|
229
|
+
tokens = tokens.concat(this.data.serialize());
|
|
230
|
+
tokens.push(new TexToken(TexTokenType.ELEMENT, ']'));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
for (const arg of this.args!) {
|
|
234
|
+
tokens.push(new TexToken(TexTokenType.ELEMENT, '{'));
|
|
235
|
+
tokens = tokens.concat(arg.serialize());
|
|
236
|
+
tokens.push(new TexToken(TexTokenType.ELEMENT, '}'));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return tokens;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export class TexLeftRight extends TexNode {
|
|
244
|
+
public left: TexToken | null;
|
|
245
|
+
public right: TexToken | null;
|
|
246
|
+
|
|
247
|
+
constructor(args: TexNode[], data: TexLeftRightData) {
|
|
248
|
+
super('leftright', TexToken.EMPTY, args);
|
|
249
|
+
this.left = data.left;
|
|
250
|
+
this.right = data.right;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
public serialize(): TexToken[] {
|
|
254
|
+
let tokens: TexToken[] = [];
|
|
255
|
+
tokens.push(new TexToken(TexTokenType.COMMAND, '\\left'));
|
|
256
|
+
tokens.push(new TexToken(TexTokenType.ELEMENT, this.left? this.left.value: '.'));
|
|
257
|
+
tokens = tokens.concat(this.args!.map((n) => n.serialize()).flat());
|
|
258
|
+
tokens.push(new TexToken(TexTokenType.COMMAND, '\\right'));
|
|
259
|
+
tokens.push(new TexToken(TexTokenType.ELEMENT, this.right? this.right.value: '.'));
|
|
260
|
+
return tokens;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export class TexBeginEnd extends TexNode {
|
|
265
|
+
public matrix: TexNode[][];
|
|
266
|
+
|
|
267
|
+
constructor(head: TexToken, args: TexNode[], data: TexNode[][]) {
|
|
268
|
+
assert(head.type === TexTokenType.LITERAL);
|
|
269
|
+
super('beginend', head, args);
|
|
270
|
+
this.matrix = data;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
public serialize(): TexToken[] {
|
|
274
|
+
let tokens: TexToken[] = [];
|
|
275
|
+
const matrix = this.matrix;
|
|
276
|
+
// tokens.push(new TexToken(TexTokenType.COMMAND, `\\begin{${this.content}}`));
|
|
277
|
+
tokens.push(new TexToken(TexTokenType.COMMAND, '\\begin'));
|
|
278
|
+
tokens.push(new TexToken(TexTokenType.ELEMENT, '{'));
|
|
279
|
+
tokens = tokens.concat(this.head);
|
|
280
|
+
tokens.push(new TexToken(TexTokenType.ELEMENT, '}'));
|
|
281
|
+
tokens.push(new TexToken(TexTokenType.NEWLINE, '\n'));
|
|
282
|
+
for (let i = 0; i < matrix.length; i++) {
|
|
283
|
+
const row = matrix[i];
|
|
284
|
+
for (let j = 0; j < row.length; j++) {
|
|
285
|
+
const cell = row[j];
|
|
286
|
+
tokens = tokens.concat(cell.serialize());
|
|
287
|
+
if (j !== row.length - 1) {
|
|
288
|
+
tokens.push(new TexToken(TexTokenType.CONTROL, '&'));
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (i !== matrix.length - 1) {
|
|
292
|
+
tokens.push(new TexToken(TexTokenType.CONTROL, '\\\\'));
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
tokens.push(new TexToken(TexTokenType.NEWLINE, '\n'));
|
|
296
|
+
// tokens.push(new TexToken(TexTokenType.COMMAND, `\\end{${this.content}}`));
|
|
297
|
+
tokens.push(new TexToken(TexTokenType.COMMAND, '\\end'));
|
|
298
|
+
tokens.push(new TexToken(TexTokenType.ELEMENT, '{'));
|
|
299
|
+
tokens = tokens.concat(this.head);
|
|
300
|
+
tokens.push(new TexToken(TexTokenType.ELEMENT, '}'));
|
|
301
|
+
return tokens;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export function writeTexTokenBuffer(buffer: string, token: TexToken): string {
|
|
306
|
+
const str = token.toString();
|
|
307
|
+
|
|
308
|
+
let no_need_space = false;
|
|
309
|
+
if (token.type === TexTokenType.SPACE) {
|
|
310
|
+
no_need_space = true;
|
|
311
|
+
} else {
|
|
312
|
+
// putting the first token in clause
|
|
313
|
+
no_need_space ||= /[{\(\[\|]$/.test(buffer);
|
|
314
|
+
// opening a optional [] parameter for a command
|
|
315
|
+
no_need_space ||= /\\\w+$/.test(buffer) && str === '[';
|
|
316
|
+
// putting a punctuation
|
|
317
|
+
no_need_space ||= /^[\.,;:!\?\(\)\]{}_^]$/.test(str);
|
|
318
|
+
no_need_space ||= ['\\{', '\\}'].includes(str);
|
|
319
|
+
// putting a prime
|
|
320
|
+
no_need_space ||= str === "'";
|
|
321
|
+
// putting a subscript or superscript
|
|
322
|
+
no_need_space ||= buffer.endsWith('_') || buffer.endsWith('^');
|
|
323
|
+
// buffer ends with a whitespace
|
|
324
|
+
no_need_space ||= /\s$/.test(buffer);
|
|
325
|
+
// token starts with a space
|
|
326
|
+
no_need_space ||= /^\s/.test(str);
|
|
327
|
+
// buffer is empty
|
|
328
|
+
no_need_space ||= buffer === '';
|
|
329
|
+
// leading sign. e.g. produce "+1" instead of " +1"
|
|
330
|
+
no_need_space ||= /[\(\[{]\s*(-|\+)$/.test(buffer) || buffer === '-' || buffer === '+';
|
|
331
|
+
// "&=" instead of "& ="
|
|
332
|
+
no_need_space ||= buffer.endsWith('&') && str === '=';
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (!no_need_space) {
|
|
336
|
+
buffer += ' ';
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return buffer + str;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* ATTENTION:
|
|
344
|
+
* Don't use any options except those explicitly documented in
|
|
345
|
+
* https://github.com/qwinsi/tex2typst/blob/main/docs/api-reference.md
|
|
346
|
+
* Any undocumented options may be not working at present or break in the future!
|
|
347
|
+
*/
|
|
348
|
+
export interface Tex2TypstOptions {
|
|
349
|
+
nonStrict?: boolean; /** default is true */
|
|
350
|
+
preferShorthands?: boolean; /** default is true */
|
|
351
|
+
keepSpaces?: boolean; /** default is false */
|
|
352
|
+
fracToSlash?: boolean; /** default is true */
|
|
353
|
+
inftyToOo?: boolean; /** default is false */
|
|
354
|
+
optimize?: boolean; /** default is true */
|
|
355
|
+
nonAsciiWrapper?: string; /** default is "" */
|
|
356
|
+
customTexMacros?: { [key: string]: string };
|
|
357
|
+
// TODO: custom typst functions
|
|
358
|
+
}
|
package/src/tex-writer.ts
CHANGED
|
@@ -1,67 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { TexNode, TexToken, writeTexTokenBuffer } from "./tex-types";
|
|
2
|
+
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
export class TexWriter {
|
|
6
6
|
protected buffer: string = "";
|
|
7
7
|
queue: TexToken[] = [];
|
|
8
8
|
|
|
9
|
-
private writeBuffer(token: TexToken) {
|
|
10
|
-
const str = token.toString();
|
|
11
|
-
|
|
12
|
-
let no_need_space = false;
|
|
13
|
-
if (token.type === TexTokenType.SPACE) {
|
|
14
|
-
no_need_space = true;
|
|
15
|
-
} else {
|
|
16
|
-
// putting the first token in clause
|
|
17
|
-
no_need_space ||= /[{\(\[\|]$/.test(this.buffer);
|
|
18
|
-
// opening a optional [] parameter for a command
|
|
19
|
-
no_need_space ||= /\\\w+$/.test(this.buffer) && str === '[';
|
|
20
|
-
// putting a punctuation
|
|
21
|
-
no_need_space ||= /^[\.,;:!\?\(\)\]{}_^]$/.test(str);
|
|
22
|
-
no_need_space ||= ['\\{', '\\}'].includes(str);
|
|
23
|
-
// putting a prime
|
|
24
|
-
no_need_space ||= str === "'";
|
|
25
|
-
// putting a subscript or superscript
|
|
26
|
-
no_need_space ||= this.buffer.endsWith('_') || this.buffer.endsWith('^');
|
|
27
|
-
// buffer ends with a whitespace
|
|
28
|
-
no_need_space ||= /\s$/.test(this.buffer);
|
|
29
|
-
// token starts with a space
|
|
30
|
-
no_need_space ||= /^\s/.test(str);
|
|
31
|
-
// buffer is empty
|
|
32
|
-
no_need_space ||= this.buffer === '';
|
|
33
|
-
// leading sign. e.g. produce "+1" instead of " +1"
|
|
34
|
-
no_need_space ||= /[\(\[{]\s*(-|\+)$/.test(this.buffer) || this.buffer === '-' || this.buffer === '+';
|
|
35
|
-
// "&=" instead of "& ="
|
|
36
|
-
no_need_space ||= this.buffer.endsWith('&') && str === '=';
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (!no_need_space) {
|
|
40
|
-
this.buffer += ' ';
|
|
41
|
-
}
|
|
42
|
-
this.buffer += str;
|
|
43
|
-
}
|
|
44
9
|
|
|
45
10
|
public append(node: TexNode) {
|
|
46
|
-
const alignment_char = new TexNode('control', '&');
|
|
47
|
-
const newline_char = new TexNode('control', '\\\\');
|
|
48
|
-
|
|
49
|
-
if (node.type === 'ordgroup' && array_includes(node.args!, alignment_char)) {
|
|
50
|
-
// wrap the whole math formula with \begin{aligned} and \end{aligned}
|
|
51
|
-
const rows = array_split(node.args!, newline_char);
|
|
52
|
-
const data: TexNode[][] = [];
|
|
53
|
-
for(const row of rows) {
|
|
54
|
-
const cells = array_split(row, alignment_char);
|
|
55
|
-
data.push(cells.map(cell => new TexNode('ordgroup', '', cell)));
|
|
56
|
-
}
|
|
57
|
-
node = new TexNode('beginend', 'aligned', [], data);
|
|
58
|
-
}
|
|
59
11
|
this.queue = this.queue.concat(node.serialize());
|
|
60
12
|
}
|
|
61
13
|
|
|
62
14
|
protected flushQueue() {
|
|
63
15
|
for (let i = 0; i < this.queue.length; i++) {
|
|
64
|
-
this.
|
|
16
|
+
this.buffer = writeTexTokenBuffer(this.buffer, this.queue[i]);
|
|
65
17
|
}
|
|
66
18
|
this.queue = [];
|
|
67
19
|
}
|