tex2typst 0.3.10 → 0.3.12
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.js +165 -133
- package/dist/tex2typst.min.js +13 -13
- package/dist/types.d.ts +12 -11
- package/docs/api-reference.md +2 -2
- package/package.json +1 -1
- package/src/convert.ts +56 -32
- package/src/index.ts +1 -0
- package/src/tex-parser.ts +5 -4
- package/src/types.ts +12 -8
- package/src/typst-parser.ts +24 -27
- package/src/typst-writer.ts +21 -14
package/src/convert.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TexNode, TypstNode, TexSupsubData, TypstSupsubData, TexSqrtData, Tex2TypstOptions,
|
|
1
|
+
import { TexNode, TypstNode, TexSupsubData, TypstSupsubData, TexSqrtData, Tex2TypstOptions, TYPST_NONE, TYPST_TRUE, TypstPrimitiveValue, TypstToken, TypstTokenType, TypstLrData, TexArrayData } from "./types";
|
|
2
2
|
import { TypstWriterError } from "./typst-writer";
|
|
3
3
|
import { symbolMap, reverseSymbolMap } from "./map";
|
|
4
4
|
import { array_join } from "./generic";
|
|
@@ -90,7 +90,7 @@ function convert_overset(node: TexNode, options: Tex2TypstOptions): TypstNode {
|
|
|
90
90
|
export function convert_tex_node_to_typst(node: TexNode, options: Tex2TypstOptions = {}): TypstNode {
|
|
91
91
|
switch (node.type) {
|
|
92
92
|
case 'empty':
|
|
93
|
-
return
|
|
93
|
+
return TYPST_NONE;
|
|
94
94
|
case 'whitespace':
|
|
95
95
|
return new TypstNode('whitespace', node.content);
|
|
96
96
|
case 'ordgroup':
|
|
@@ -103,8 +103,16 @@ export function convert_tex_node_to_typst(node: TexNode, options: Tex2TypstOptio
|
|
|
103
103
|
return new TypstNode('atom', tex_token_to_typst(node.content));
|
|
104
104
|
case 'symbol':
|
|
105
105
|
return new TypstNode('symbol', tex_token_to_typst(node.content));
|
|
106
|
-
case 'text':
|
|
106
|
+
case 'text': {
|
|
107
|
+
if ((/[^\x00-\x7F]+/).test(node.content) && options.nonAsciiWrapper !== "") {
|
|
108
|
+
return new TypstNode(
|
|
109
|
+
'funcCall',
|
|
110
|
+
options.nonAsciiWrapper!,
|
|
111
|
+
[new TypstNode('text', node.content)]
|
|
112
|
+
);
|
|
113
|
+
}
|
|
107
114
|
return new TypstNode('text', node.content);
|
|
115
|
+
}
|
|
108
116
|
case 'comment':
|
|
109
117
|
return new TypstNode('comment', node.content);
|
|
110
118
|
case 'supsub': {
|
|
@@ -128,8 +136,8 @@ export function convert_tex_node_to_typst(node: TexNode, options: Tex2TypstOptio
|
|
|
128
136
|
const data: TypstSupsubData = {
|
|
129
137
|
base: convert_tex_node_to_typst(base, options),
|
|
130
138
|
};
|
|
131
|
-
if (data.base.type === '
|
|
132
|
-
data.base = new TypstNode('
|
|
139
|
+
if (data.base.type === 'none') {
|
|
140
|
+
data.base = new TypstNode('none', '');
|
|
133
141
|
}
|
|
134
142
|
|
|
135
143
|
if (sup) {
|
|
@@ -281,10 +289,10 @@ export function convert_tex_node_to_typst(node: TexNode, options: Tex2TypstOptio
|
|
|
281
289
|
return new TypstNode('cases', '', [], data);
|
|
282
290
|
}
|
|
283
291
|
if (node.content!.endsWith('matrix')) {
|
|
284
|
-
let delim: TypstPrimitiveValue
|
|
292
|
+
let delim: TypstPrimitiveValue;
|
|
285
293
|
switch (node.content) {
|
|
286
294
|
case 'matrix':
|
|
287
|
-
delim =
|
|
295
|
+
delim = TYPST_NONE;
|
|
288
296
|
break;
|
|
289
297
|
case 'pmatrix':
|
|
290
298
|
delim = '(';
|
|
@@ -299,7 +307,7 @@ export function convert_tex_node_to_typst(node: TexNode, options: Tex2TypstOptio
|
|
|
299
307
|
delim = '|';
|
|
300
308
|
break;
|
|
301
309
|
case 'Vmatrix': {
|
|
302
|
-
delim = new
|
|
310
|
+
delim = new TypstNode('symbol', 'bar.v.double');
|
|
303
311
|
break;
|
|
304
312
|
}
|
|
305
313
|
default:
|
|
@@ -388,7 +396,8 @@ export function convert_typst_node_to_tex(node: TypstNode): TexNode {
|
|
|
388
396
|
]);
|
|
389
397
|
}
|
|
390
398
|
switch (node.type) {
|
|
391
|
-
case '
|
|
399
|
+
case 'none':
|
|
400
|
+
// e.g. Typst `#none^2` is converted to TeX `^2`
|
|
392
401
|
return new TexNode('empty', '');
|
|
393
402
|
case 'whitespace':
|
|
394
403
|
return new TexNode('whitespace', node.content);
|
|
@@ -513,29 +522,44 @@ export function convert_typst_node_to_tex(node: TypstNode): TexNode {
|
|
|
513
522
|
let env_type = 'pmatrix';
|
|
514
523
|
if (node.options) {
|
|
515
524
|
if ('delim' in node.options) {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
525
|
+
const delim = node.options.delim;
|
|
526
|
+
if (delim instanceof TypstNode) {
|
|
527
|
+
switch (delim.content) {
|
|
528
|
+
case '#none':
|
|
529
|
+
env_type = 'matrix';
|
|
530
|
+
break;
|
|
531
|
+
case 'bar.v.double':
|
|
532
|
+
env_type = 'Vmatrix';
|
|
533
|
+
break;
|
|
534
|
+
case 'bar':
|
|
535
|
+
case 'bar.v':
|
|
536
|
+
env_type = 'vmatrix';
|
|
537
|
+
break;
|
|
538
|
+
default:
|
|
539
|
+
throw new Error(`Unexpected delimiter ${delim.content}`);
|
|
540
|
+
}
|
|
541
|
+
} else {
|
|
542
|
+
switch (delim) {
|
|
543
|
+
case '[':
|
|
544
|
+
env_type = 'bmatrix';
|
|
545
|
+
break;
|
|
546
|
+
case ']':
|
|
547
|
+
env_type = 'bmatrix';
|
|
548
|
+
break;
|
|
549
|
+
case '{':
|
|
550
|
+
env_type = 'Bmatrix';
|
|
551
|
+
break;
|
|
552
|
+
case '}':
|
|
553
|
+
env_type = 'Bmatrix';
|
|
554
|
+
break;
|
|
555
|
+
case '|':
|
|
556
|
+
env_type = 'vmatrix';
|
|
557
|
+
break;
|
|
558
|
+
case ')':
|
|
559
|
+
case '(':
|
|
560
|
+
default:
|
|
561
|
+
env_type = 'pmatrix';
|
|
562
|
+
}
|
|
539
563
|
}
|
|
540
564
|
}
|
|
541
565
|
}
|
package/src/index.ts
CHANGED
package/src/tex-parser.ts
CHANGED
|
@@ -209,9 +209,12 @@ const rules_map = new Map<string, (a: Scanner<TexToken>) => TexToken | TexToken[
|
|
|
209
209
|
const command = s.text()!;
|
|
210
210
|
return [ new TexToken(TexTokenType.COMMAND, command), ];
|
|
211
211
|
}],
|
|
212
|
-
|
|
212
|
+
// Numbers like "123", "3.14"
|
|
213
|
+
[String.raw`[0-9]+(\.[0-9]+)?`, (s) => new TexToken(TexTokenType.ELEMENT, s.text()!)],
|
|
213
214
|
[String.raw`[a-zA-Z]`, (s) => new TexToken(TexTokenType.ELEMENT, s.text()!)],
|
|
214
215
|
[String.raw`[+\-*/='<>!.,;:?()\[\]|]`, (s) => new TexToken(TexTokenType.ELEMENT, s.text()!)],
|
|
216
|
+
// non-ASCII characters
|
|
217
|
+
[String.raw`[^\x00-\x7F]`, (s) => new TexToken(TexTokenType.ELEMENT, s.text()!)],
|
|
215
218
|
[String.raw`.`, (s) => new TexToken(TexTokenType.UNKNOWN, s.text()!)],
|
|
216
219
|
]);
|
|
217
220
|
|
|
@@ -273,9 +276,7 @@ export class LatexParser {
|
|
|
273
276
|
}
|
|
274
277
|
|
|
275
278
|
let node: TexNode;
|
|
276
|
-
if (results.length ===
|
|
277
|
-
node = EMPTY_NODE;
|
|
278
|
-
} else if (results.length === 1) {
|
|
279
|
+
if (results.length === 1) {
|
|
279
280
|
node = results[0];
|
|
280
281
|
} else {
|
|
281
282
|
node = new TexNode('ordgroup', '', results);
|
package/src/types.ts
CHANGED
|
@@ -233,12 +233,12 @@ export class TexNode {
|
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
export enum TypstTokenType {
|
|
236
|
+
NONE,
|
|
236
237
|
SYMBOL,
|
|
237
238
|
ELEMENT,
|
|
238
239
|
TEXT,
|
|
239
240
|
COMMENT,
|
|
240
241
|
SPACE,
|
|
241
|
-
SOFT_SPACE,
|
|
242
242
|
CONTROL,
|
|
243
243
|
NEWLINE,
|
|
244
244
|
}
|
|
@@ -262,6 +262,8 @@ export class TypstToken {
|
|
|
262
262
|
|
|
263
263
|
public toNode(): TypstNode {
|
|
264
264
|
switch(this.type) {
|
|
265
|
+
case TypstTokenType.NONE:
|
|
266
|
+
return new TypstNode('none', '#none');
|
|
265
267
|
case TypstTokenType.TEXT:
|
|
266
268
|
return new TypstNode('text', this.value);
|
|
267
269
|
case TypstTokenType.COMMENT:
|
|
@@ -279,7 +281,7 @@ export class TypstToken {
|
|
|
279
281
|
case '':
|
|
280
282
|
case '_':
|
|
281
283
|
case '^':
|
|
282
|
-
|
|
284
|
+
throw new Error(`Should not convert ${controlChar} to a node`);
|
|
283
285
|
case '&':
|
|
284
286
|
return new TypstNode('control', '&');
|
|
285
287
|
case '\\':
|
|
@@ -318,15 +320,11 @@ export interface TypstLrData {
|
|
|
318
320
|
}
|
|
319
321
|
|
|
320
322
|
type TypstNodeType = 'atom' | 'symbol' | 'text' | 'control' | 'comment' | 'whitespace'
|
|
321
|
-
| '
|
|
323
|
+
| 'none' | 'group' | 'supsub' | 'funcCall' | 'fraction' | 'align' | 'matrix' | 'cases' | 'unknown';
|
|
322
324
|
|
|
323
|
-
export type TypstPrimitiveValue = string | boolean |
|
|
325
|
+
export type TypstPrimitiveValue = string | boolean | TypstNode;
|
|
324
326
|
export type TypstNamedParams = { [key: string]: TypstPrimitiveValue };
|
|
325
327
|
|
|
326
|
-
// #none
|
|
327
|
-
export const TYPST_NULL: TypstPrimitiveValue = null;
|
|
328
|
-
export const TYPST_TRUE: TypstPrimitiveValue = true;
|
|
329
|
-
export const TYPST_FALSE: TypstPrimitiveValue = false;
|
|
330
328
|
|
|
331
329
|
export class TypstNode {
|
|
332
330
|
type: TypstNodeType;
|
|
@@ -379,6 +377,11 @@ export class TypstNode {
|
|
|
379
377
|
}
|
|
380
378
|
}
|
|
381
379
|
|
|
380
|
+
// #none
|
|
381
|
+
export const TYPST_NONE = new TypstNode('none', '#none');
|
|
382
|
+
export const TYPST_TRUE: TypstPrimitiveValue = true;
|
|
383
|
+
export const TYPST_FALSE: TypstPrimitiveValue = false;
|
|
384
|
+
|
|
382
385
|
export interface Tex2TypstOptions {
|
|
383
386
|
nonStrict?: boolean; // default is true
|
|
384
387
|
preferTypstIntrinsic?: boolean; // default is true,
|
|
@@ -386,6 +389,7 @@ export interface Tex2TypstOptions {
|
|
|
386
389
|
keepSpaces?: boolean; // default is false
|
|
387
390
|
fracToSlash?: boolean; // default is true
|
|
388
391
|
inftyToOo?: boolean; // default is false
|
|
392
|
+
nonAsciiWrapper?: string; // default is ""
|
|
389
393
|
customTexMacros?: { [key: string]: string };
|
|
390
394
|
// TODO: custom typst functions
|
|
391
395
|
}
|
package/src/typst-parser.ts
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
|
|
2
2
|
import { array_find } from "./generic";
|
|
3
|
-
import {
|
|
3
|
+
import { TYPST_NONE, TypstLrData, TypstNamedParams, TypstNode, TypstSupsubData, TypstToken, TypstTokenType } from "./types";
|
|
4
4
|
import { assert, isalpha } from "./util";
|
|
5
5
|
import { reverseShorthandMap } from "./typst-shorthands";
|
|
6
6
|
import { JSLex, Scanner } from "./jslex";
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
const TYPST_EMPTY_NODE = new TypstNode('empty', '');
|
|
10
|
-
|
|
11
8
|
const TYPST_SHORTHANDS = Array.from(reverseShorthandMap.keys());
|
|
12
9
|
|
|
13
10
|
// TODO: In Typst, y' ' is not the same as y''.
|
|
@@ -78,6 +75,7 @@ const rules_map = new Map<string, (a: Scanner<TypstToken>) => TypstToken | Typst
|
|
|
78
75
|
[String.raw`[a-zA-Z\.]+`, (s) => {
|
|
79
76
|
return new TypstToken(s.text()!.length === 1? TypstTokenType.ELEMENT: TypstTokenType.SYMBOL, s.text()!);
|
|
80
77
|
}],
|
|
78
|
+
[String.raw`#none`, (s) => new TypstToken(TypstTokenType.NONE, s.text()!)],
|
|
81
79
|
[String.raw`.`, (s) => new TypstToken(TypstTokenType.ELEMENT, s.text()!)],
|
|
82
80
|
]);
|
|
83
81
|
|
|
@@ -168,12 +166,12 @@ const DIV = new TypstNode('atom', '/');
|
|
|
168
166
|
|
|
169
167
|
|
|
170
168
|
|
|
171
|
-
function next_non_whitespace(nodes: TypstNode[], start: number): TypstNode {
|
|
169
|
+
function next_non_whitespace(nodes: TypstNode[], start: number): TypstNode | null {
|
|
172
170
|
let pos = start;
|
|
173
171
|
while (pos < nodes.length && nodes[pos].type === 'whitespace') {
|
|
174
172
|
pos++;
|
|
175
173
|
}
|
|
176
|
-
return pos === nodes.length ?
|
|
174
|
+
return pos === nodes.length ? null : nodes[pos];
|
|
177
175
|
}
|
|
178
176
|
|
|
179
177
|
function trim_whitespace_around_operators(nodes: TypstNode[]): TypstNode[] {
|
|
@@ -185,7 +183,7 @@ function trim_whitespace_around_operators(nodes: TypstNode[]): TypstNode[] {
|
|
|
185
183
|
if(after_operator) {
|
|
186
184
|
continue;
|
|
187
185
|
}
|
|
188
|
-
if(next_non_whitespace(nodes, i + 1)
|
|
186
|
+
if(next_non_whitespace(nodes, i + 1)?.eq(DIV)) {
|
|
189
187
|
continue;
|
|
190
188
|
}
|
|
191
189
|
}
|
|
@@ -253,9 +251,7 @@ function process_operators(nodes: TypstNode[], parenthesis = false): TypstNode {
|
|
|
253
251
|
if(parenthesis) {
|
|
254
252
|
return new TypstNode('group', 'parenthesis', args);
|
|
255
253
|
} else {
|
|
256
|
-
if(args.length ===
|
|
257
|
-
return TYPST_EMPTY_NODE;
|
|
258
|
-
} else if(args.length === 1) {
|
|
254
|
+
if(args.length === 1) {
|
|
259
255
|
return args[0];
|
|
260
256
|
} else {
|
|
261
257
|
return new TypstNode('group', '', args);
|
|
@@ -322,9 +318,7 @@ export class TypstParser {
|
|
|
322
318
|
if(parentheses) {
|
|
323
319
|
node = process_operators(results, true);
|
|
324
320
|
} else {
|
|
325
|
-
if (results.length ===
|
|
326
|
-
node = TYPST_EMPTY_NODE;
|
|
327
|
-
} else if (results.length === 1) {
|
|
321
|
+
if (results.length === 1) {
|
|
328
322
|
node = results[0];
|
|
329
323
|
} else {
|
|
330
324
|
node = process_operators(results);
|
|
@@ -489,19 +483,24 @@ export class TypstParser {
|
|
|
489
483
|
to_delete.push(i);
|
|
490
484
|
const param_name = g.args![pos_colon - 1];
|
|
491
485
|
if(param_name.eq(new TypstNode('symbol', 'delim'))) {
|
|
492
|
-
if(g.args
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
486
|
+
if(g.args!.length !== 3) {
|
|
487
|
+
throw new TypstParserError('Invalid number of arguments for delim');
|
|
488
|
+
}
|
|
489
|
+
switch (g.args![pos_colon + 1].type) {
|
|
490
|
+
case 'text': {
|
|
491
|
+
np['delim'] = g.args![pos_colon + 1].content;
|
|
492
|
+
break;
|
|
493
|
+
}
|
|
494
|
+
case 'none': {
|
|
495
|
+
np['delim'] = TYPST_NONE;
|
|
496
|
+
break;
|
|
496
497
|
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
throw new TypstParserError('Invalid number of arguments for delim');
|
|
498
|
+
case 'symbol': {
|
|
499
|
+
np['delim'] = g.args![pos_colon + 1];
|
|
500
|
+
break;
|
|
501
501
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
throw new TypstParserError('Not implemented for other types of delim');
|
|
502
|
+
default:
|
|
503
|
+
throw new TypstParserError('Not implemented for other types of delim');
|
|
505
504
|
}
|
|
506
505
|
} else {
|
|
507
506
|
throw new TypstParserError('Not implemented for other named parameters');
|
|
@@ -543,9 +542,7 @@ export class TypstParser {
|
|
|
543
542
|
}
|
|
544
543
|
|
|
545
544
|
let arg: TypstNode;
|
|
546
|
-
if (nodes.length ===
|
|
547
|
-
arg = TYPST_EMPTY_NODE;
|
|
548
|
-
} else if (nodes.length === 1) {
|
|
545
|
+
if (nodes.length === 1) {
|
|
549
546
|
arg = nodes[0];
|
|
550
547
|
} else {
|
|
551
548
|
arg = process_operators(nodes);
|
package/src/typst-writer.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TexNode, TypstNode, TypstPrimitiveValue, TypstSupsubData, TypstToken, TypstTokenType } from "./types";
|
|
2
2
|
import { shorthandMap } from "./typst-shorthands";
|
|
3
|
+
import { assert } from "./util";
|
|
3
4
|
|
|
4
5
|
function is_delimiter(c: TypstNode): boolean {
|
|
5
6
|
return c.type === 'atom' && ['(', ')', '[', ']', '{', '}', '|', '⌊', '⌋', '⌈', '⌉'].includes(c.content);
|
|
@@ -19,12 +20,8 @@ function typst_primitive_to_string(value: TypstPrimitiveValue) {
|
|
|
19
20
|
case 'boolean':
|
|
20
21
|
return (value as boolean) ? '#true' : '#false';
|
|
21
22
|
default:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
} else if (value instanceof TypstToken) {
|
|
25
|
-
return value.toString();
|
|
26
|
-
}
|
|
27
|
-
throw new TypstWriterError(`Invalid primitive value: ${value}`, value);
|
|
23
|
+
assert(value instanceof TypstNode, 'Not a valid primitive value');
|
|
24
|
+
return (value as TypstNode).content;
|
|
28
25
|
}
|
|
29
26
|
}
|
|
30
27
|
|
|
@@ -108,7 +105,8 @@ export class TypstWriter {
|
|
|
108
105
|
// Serialize a tree of TypstNode into a list of TypstToken
|
|
109
106
|
public serialize(node: TypstNode) {
|
|
110
107
|
switch (node.type) {
|
|
111
|
-
case '
|
|
108
|
+
case 'none':
|
|
109
|
+
this.queue.push(new TypstToken(TypstTokenType.NONE, '#none'));
|
|
112
110
|
break;
|
|
113
111
|
case 'atom': {
|
|
114
112
|
if (node.content === ',' && this.insideFunctionDepth > 0) {
|
|
@@ -163,7 +161,7 @@ export class TypstWriter {
|
|
|
163
161
|
const has_prime = (sup && sup.type === 'atom' && sup.content === '\'');
|
|
164
162
|
if (has_prime) {
|
|
165
163
|
// Put prime symbol before '_'. Because $y_1'$ is not displayed properly in Typst (so far)
|
|
166
|
-
// e.g.
|
|
164
|
+
// e.g.
|
|
167
165
|
// y_1' -> y'_1
|
|
168
166
|
// y_{a_1}' -> y'_{a_1}
|
|
169
167
|
this.queue.push(new TypstToken(TypstTokenType.ELEMENT, '\''));
|
|
@@ -185,7 +183,9 @@ export class TypstWriter {
|
|
|
185
183
|
case 'funcCall': {
|
|
186
184
|
const func_symbol: TypstToken = new TypstToken(TypstTokenType.SYMBOL, node.content);
|
|
187
185
|
this.queue.push(func_symbol);
|
|
188
|
-
|
|
186
|
+
if (node.content !== 'lr') {
|
|
187
|
+
this.insideFunctionDepth++;
|
|
188
|
+
}
|
|
189
189
|
this.queue.push(TYPST_LEFT_PARENTHESIS);
|
|
190
190
|
for (let i = 0; i < node.args!.length; i++) {
|
|
191
191
|
this.serialize(node.args![i]);
|
|
@@ -200,7 +200,9 @@ export class TypstWriter {
|
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
this.queue.push(TYPST_RIGHT_PARENTHESIS);
|
|
203
|
-
|
|
203
|
+
if (node.content !== 'lr') {
|
|
204
|
+
this.insideFunctionDepth--;
|
|
205
|
+
}
|
|
204
206
|
break;
|
|
205
207
|
}
|
|
206
208
|
case 'fraction': {
|
|
@@ -317,10 +319,15 @@ export class TypstWriter {
|
|
|
317
319
|
let need_to_wrap = ['group', 'supsub', 'empty'].includes(node.type);
|
|
318
320
|
|
|
319
321
|
if (node.type === 'group') {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
322
|
+
if (node.args!.length === 0) {
|
|
323
|
+
// e.g. TeX `P_{}` converts to Typst `P_()`
|
|
324
|
+
need_to_wrap = true;
|
|
325
|
+
} else {
|
|
326
|
+
const first = node.args![0];
|
|
327
|
+
const last = node.args![node.args!.length - 1];
|
|
328
|
+
if (is_delimiter(first) && is_delimiter(last)) {
|
|
329
|
+
need_to_wrap = false;
|
|
330
|
+
}
|
|
324
331
|
}
|
|
325
332
|
}
|
|
326
333
|
|