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
package/dist/index.js
CHANGED
|
@@ -563,7 +563,8 @@ var TEX_UNARY_COMMANDS = [
|
|
|
563
563
|
"overleftarrow",
|
|
564
564
|
"overrightarrow",
|
|
565
565
|
"hspace",
|
|
566
|
-
"substack"
|
|
566
|
+
"substack",
|
|
567
|
+
"set"
|
|
567
568
|
];
|
|
568
569
|
var TEX_BINARY_COMMANDS = [
|
|
569
570
|
"frac",
|
|
@@ -1118,6 +1119,54 @@ function parseTex(tex, customTexMacros) {
|
|
|
1118
1119
|
return parser.parse(tokens);
|
|
1119
1120
|
}
|
|
1120
1121
|
|
|
1122
|
+
// src/typst-shorthands.ts
|
|
1123
|
+
var shorthandMap = /* @__PURE__ */ new Map([
|
|
1124
|
+
["arrow.l.r.double.long", "<==>"],
|
|
1125
|
+
["arrow.l.r.long", "<-->"],
|
|
1126
|
+
["arrow.r.bar", "|->"],
|
|
1127
|
+
["arrow.r.double.bar", "|=>"],
|
|
1128
|
+
["arrow.r.double.long", "==>"],
|
|
1129
|
+
["arrow.r.long", "-->"],
|
|
1130
|
+
["arrow.r.long.squiggly", "~~>"],
|
|
1131
|
+
["arrow.r.tail", ">->"],
|
|
1132
|
+
["arrow.r.twohead", "->>"],
|
|
1133
|
+
["arrow.l.double.long", "<=="],
|
|
1134
|
+
["arrow.l.long", "<--"],
|
|
1135
|
+
["arrow.l.long.squiggly", "<~~"],
|
|
1136
|
+
["arrow.l.tail", "<-<"],
|
|
1137
|
+
["arrow.l.twohead", "<<-"],
|
|
1138
|
+
["arrow.l.r", "<->"],
|
|
1139
|
+
["arrow.l.r.double", "<=>"],
|
|
1140
|
+
["colon.double.eq", "::="],
|
|
1141
|
+
["dots.h", "..."],
|
|
1142
|
+
["gt.triple", ">>>"],
|
|
1143
|
+
["lt.triple", "<<<"],
|
|
1144
|
+
["arrow.r", "->"],
|
|
1145
|
+
["arrow.r.double", "=>"],
|
|
1146
|
+
["arrow.r.squiggly", "~>"],
|
|
1147
|
+
["arrow.l", "<-"],
|
|
1148
|
+
["arrow.l.squiggly", "<~"],
|
|
1149
|
+
["bar.v.double", "||"],
|
|
1150
|
+
["bracket.l.double", "[|"],
|
|
1151
|
+
["bracket.r.double", "|]"],
|
|
1152
|
+
["colon.eq", ":="],
|
|
1153
|
+
["eq.colon", "=:"],
|
|
1154
|
+
["eq.not", "!="],
|
|
1155
|
+
["gt.double", ">>"],
|
|
1156
|
+
["gt.eq", ">="],
|
|
1157
|
+
["lt.double", "<<"],
|
|
1158
|
+
["lt.eq", "<="],
|
|
1159
|
+
["ast.op", "*"],
|
|
1160
|
+
["minus", "-"],
|
|
1161
|
+
["tilde.op", "~"]
|
|
1162
|
+
]);
|
|
1163
|
+
var reverseShorthandMap = /* @__PURE__ */ new Map();
|
|
1164
|
+
for (const [key, value] of shorthandMap.entries()) {
|
|
1165
|
+
if (value.length > 1) {
|
|
1166
|
+
reverseShorthandMap.set(value, key);
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1121
1170
|
// src/typst-types.ts
|
|
1122
1171
|
var TypstToken = class _TypstToken {
|
|
1123
1172
|
type;
|
|
@@ -1147,7 +1196,32 @@ var TypstToken = class _TypstToken {
|
|
|
1147
1196
|
}
|
|
1148
1197
|
static NONE = new _TypstToken(0 /* NONE */, "#none");
|
|
1149
1198
|
static EMPTY = new _TypstToken(2 /* ELEMENT */, "");
|
|
1199
|
+
static LEFT_BRACE = new _TypstToken(2 /* ELEMENT */, "{");
|
|
1200
|
+
static RIGHT_BRACE = new _TypstToken(2 /* ELEMENT */, "}");
|
|
1201
|
+
static LEFT_DELIMITERS = [
|
|
1202
|
+
new _TypstToken(2 /* ELEMENT */, "("),
|
|
1203
|
+
new _TypstToken(2 /* ELEMENT */, "["),
|
|
1204
|
+
new _TypstToken(2 /* ELEMENT */, "{"),
|
|
1205
|
+
new _TypstToken(2 /* ELEMENT */, "|"),
|
|
1206
|
+
new _TypstToken(1 /* SYMBOL */, "angle.l")
|
|
1207
|
+
];
|
|
1208
|
+
static RIGHT_DELIMITERS = [
|
|
1209
|
+
new _TypstToken(2 /* ELEMENT */, ")"),
|
|
1210
|
+
new _TypstToken(2 /* ELEMENT */, "]"),
|
|
1211
|
+
new _TypstToken(2 /* ELEMENT */, "}"),
|
|
1212
|
+
new _TypstToken(2 /* ELEMENT */, "|"),
|
|
1213
|
+
new _TypstToken(1 /* SYMBOL */, "angle.r")
|
|
1214
|
+
];
|
|
1150
1215
|
};
|
|
1216
|
+
var TypstWriterError = class extends Error {
|
|
1217
|
+
node;
|
|
1218
|
+
constructor(message, node) {
|
|
1219
|
+
super(message);
|
|
1220
|
+
this.name = "TypstWriterError";
|
|
1221
|
+
this.node = node;
|
|
1222
|
+
}
|
|
1223
|
+
};
|
|
1224
|
+
var SOFT_SPACE = new TypstToken(7 /* CONTROL */, " ");
|
|
1151
1225
|
var TypstNode = class {
|
|
1152
1226
|
type;
|
|
1153
1227
|
head;
|
|
@@ -1178,6 +1252,39 @@ var TypstTerminal = class extends TypstNode {
|
|
|
1178
1252
|
toString() {
|
|
1179
1253
|
return this.head.toString();
|
|
1180
1254
|
}
|
|
1255
|
+
serialize(env, options) {
|
|
1256
|
+
if (this.head.type === 2 /* ELEMENT */) {
|
|
1257
|
+
if (this.head.value === "," && env.insideFunctionDepth > 0) {
|
|
1258
|
+
return [new TypstToken(1 /* SYMBOL */, "comma")];
|
|
1259
|
+
}
|
|
1260
|
+
} else if (this.head.type === 1 /* SYMBOL */) {
|
|
1261
|
+
let symbol_name = this.head.value;
|
|
1262
|
+
if (options.preferShorthands) {
|
|
1263
|
+
if (shorthandMap.has(symbol_name)) {
|
|
1264
|
+
symbol_name = shorthandMap.get(symbol_name);
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
if (options.inftyToOo && symbol_name === "infinity") {
|
|
1268
|
+
symbol_name = "oo";
|
|
1269
|
+
}
|
|
1270
|
+
return [new TypstToken(1 /* SYMBOL */, symbol_name)];
|
|
1271
|
+
} else if (this.head.type === 6 /* SPACE */ || this.head.type === 8 /* NEWLINE */) {
|
|
1272
|
+
const queue = [];
|
|
1273
|
+
for (const c of this.head.value) {
|
|
1274
|
+
if (c === " ") {
|
|
1275
|
+
if (options.keepSpaces) {
|
|
1276
|
+
queue.push(new TypstToken(6 /* SPACE */, c));
|
|
1277
|
+
}
|
|
1278
|
+
} else if (c === "\n") {
|
|
1279
|
+
queue.push(new TypstToken(1 /* SYMBOL */, c));
|
|
1280
|
+
} else {
|
|
1281
|
+
throw new TypstWriterError(`Unexpected whitespace character: ${c}`, this);
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
return queue;
|
|
1285
|
+
}
|
|
1286
|
+
return [this.head];
|
|
1287
|
+
}
|
|
1181
1288
|
};
|
|
1182
1289
|
var TypstGroup = class extends TypstNode {
|
|
1183
1290
|
items;
|
|
@@ -1188,6 +1295,16 @@ var TypstGroup = class extends TypstNode {
|
|
|
1188
1295
|
isOverHigh() {
|
|
1189
1296
|
return this.items.some((n) => n.isOverHigh());
|
|
1190
1297
|
}
|
|
1298
|
+
serialize(env, options) {
|
|
1299
|
+
const queue = this.items.flatMap((n) => n.serialize(env, options));
|
|
1300
|
+
if (queue.length > 0 && queue[0].eq(SOFT_SPACE)) {
|
|
1301
|
+
queue.shift();
|
|
1302
|
+
}
|
|
1303
|
+
if (queue.length > 0 && queue[queue.length - 1].eq(SOFT_SPACE)) {
|
|
1304
|
+
queue.pop();
|
|
1305
|
+
}
|
|
1306
|
+
return queue;
|
|
1307
|
+
}
|
|
1191
1308
|
};
|
|
1192
1309
|
var TypstSupsub = class extends TypstNode {
|
|
1193
1310
|
base;
|
|
@@ -1202,6 +1319,25 @@ var TypstSupsub = class extends TypstNode {
|
|
|
1202
1319
|
isOverHigh() {
|
|
1203
1320
|
return this.base.isOverHigh();
|
|
1204
1321
|
}
|
|
1322
|
+
serialize(env, options) {
|
|
1323
|
+
const queue = [];
|
|
1324
|
+
let { base, sup, sub } = this;
|
|
1325
|
+
queue.push(...base.serialize(env, options));
|
|
1326
|
+
const has_prime = sup && sup.head.eq(new TypstToken(2 /* ELEMENT */, "'"));
|
|
1327
|
+
if (has_prime) {
|
|
1328
|
+
queue.push(new TypstToken(2 /* ELEMENT */, "'"));
|
|
1329
|
+
}
|
|
1330
|
+
if (sub) {
|
|
1331
|
+
queue.push(new TypstToken(2 /* ELEMENT */, "_"));
|
|
1332
|
+
queue.push(...sub.serialize(env, options));
|
|
1333
|
+
}
|
|
1334
|
+
if (sup && !has_prime) {
|
|
1335
|
+
queue.push(new TypstToken(2 /* ELEMENT */, "^"));
|
|
1336
|
+
queue.push(...sup.serialize(env, options));
|
|
1337
|
+
}
|
|
1338
|
+
queue.push(SOFT_SPACE);
|
|
1339
|
+
return queue;
|
|
1340
|
+
}
|
|
1205
1341
|
};
|
|
1206
1342
|
var TypstFuncCall = class extends TypstNode {
|
|
1207
1343
|
args;
|
|
@@ -1215,6 +1351,27 @@ var TypstFuncCall = class extends TypstNode {
|
|
|
1215
1351
|
}
|
|
1216
1352
|
return this.args.some((n) => n.isOverHigh());
|
|
1217
1353
|
}
|
|
1354
|
+
serialize(env, options) {
|
|
1355
|
+
const queue = [];
|
|
1356
|
+
const func_symbol = this.head;
|
|
1357
|
+
queue.push(func_symbol);
|
|
1358
|
+
env.insideFunctionDepth++;
|
|
1359
|
+
queue.push(TYPST_LEFT_PARENTHESIS);
|
|
1360
|
+
for (let i = 0; i < this.args.length; i++) {
|
|
1361
|
+
queue.push(...this.args[i].serialize(env, options));
|
|
1362
|
+
if (i < this.args.length - 1) {
|
|
1363
|
+
queue.push(new TypstToken(2 /* ELEMENT */, ","));
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
if (this.options) {
|
|
1367
|
+
for (const [key, value] of Object.entries(this.options)) {
|
|
1368
|
+
queue.push(new TypstToken(3 /* LITERAL */, `, ${key}: ${value.toString()}`));
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
queue.push(TYPST_RIGHT_PARENTHESIS);
|
|
1372
|
+
env.insideFunctionDepth--;
|
|
1373
|
+
return queue;
|
|
1374
|
+
}
|
|
1218
1375
|
};
|
|
1219
1376
|
var TypstFraction = class extends TypstNode {
|
|
1220
1377
|
args;
|
|
@@ -1225,7 +1382,19 @@ var TypstFraction = class extends TypstNode {
|
|
|
1225
1382
|
isOverHigh() {
|
|
1226
1383
|
return true;
|
|
1227
1384
|
}
|
|
1385
|
+
serialize(env, options) {
|
|
1386
|
+
const queue = [];
|
|
1387
|
+
const [numerator, denominator] = this.args;
|
|
1388
|
+
queue.push(SOFT_SPACE);
|
|
1389
|
+
queue.push(...numerator.serialize(env, options));
|
|
1390
|
+
queue.push(new TypstToken(2 /* ELEMENT */, "/"));
|
|
1391
|
+
queue.push(...denominator.serialize(env, options));
|
|
1392
|
+
queue.push(SOFT_SPACE);
|
|
1393
|
+
return queue;
|
|
1394
|
+
}
|
|
1228
1395
|
};
|
|
1396
|
+
var TYPST_LEFT_PARENTHESIS = new TypstToken(2 /* ELEMENT */, "(");
|
|
1397
|
+
var TYPST_RIGHT_PARENTHESIS = new TypstToken(2 /* ELEMENT */, ")");
|
|
1229
1398
|
var TypstLeftright = class extends TypstNode {
|
|
1230
1399
|
body;
|
|
1231
1400
|
left;
|
|
@@ -1240,8 +1409,28 @@ var TypstLeftright = class extends TypstNode {
|
|
|
1240
1409
|
isOverHigh() {
|
|
1241
1410
|
return this.body.isOverHigh();
|
|
1242
1411
|
}
|
|
1412
|
+
serialize(env, options) {
|
|
1413
|
+
const queue = [];
|
|
1414
|
+
const LR = new TypstToken(1 /* SYMBOL */, "lr");
|
|
1415
|
+
const { left, right } = this;
|
|
1416
|
+
if (this.head.eq(LR)) {
|
|
1417
|
+
queue.push(LR);
|
|
1418
|
+
queue.push(TYPST_LEFT_PARENTHESIS);
|
|
1419
|
+
}
|
|
1420
|
+
if (left) {
|
|
1421
|
+
queue.push(left);
|
|
1422
|
+
}
|
|
1423
|
+
queue.push(...this.body.serialize(env, options));
|
|
1424
|
+
if (right) {
|
|
1425
|
+
queue.push(right);
|
|
1426
|
+
}
|
|
1427
|
+
if (this.head.eq(LR)) {
|
|
1428
|
+
queue.push(TYPST_RIGHT_PARENTHESIS);
|
|
1429
|
+
}
|
|
1430
|
+
return queue;
|
|
1431
|
+
}
|
|
1243
1432
|
};
|
|
1244
|
-
var TypstMatrixLike = class extends TypstNode {
|
|
1433
|
+
var TypstMatrixLike = class _TypstMatrixLike extends TypstNode {
|
|
1245
1434
|
matrix;
|
|
1246
1435
|
// head is 'mat', 'cases' or null
|
|
1247
1436
|
constructor(head, data) {
|
|
@@ -1251,6 +1440,48 @@ var TypstMatrixLike = class extends TypstNode {
|
|
|
1251
1440
|
isOverHigh() {
|
|
1252
1441
|
return true;
|
|
1253
1442
|
}
|
|
1443
|
+
serialize(env, options) {
|
|
1444
|
+
const queue = [];
|
|
1445
|
+
let cell_sep;
|
|
1446
|
+
let row_sep;
|
|
1447
|
+
if (this.head.eq(_TypstMatrixLike.MAT)) {
|
|
1448
|
+
cell_sep = new TypstToken(2 /* ELEMENT */, ",");
|
|
1449
|
+
row_sep = new TypstToken(2 /* ELEMENT */, ";");
|
|
1450
|
+
} else if (this.head.eq(_TypstMatrixLike.CASES)) {
|
|
1451
|
+
cell_sep = new TypstToken(2 /* ELEMENT */, "&");
|
|
1452
|
+
row_sep = new TypstToken(2 /* ELEMENT */, ",");
|
|
1453
|
+
} else if (this.head.eq(TypstToken.NONE)) {
|
|
1454
|
+
cell_sep = new TypstToken(2 /* ELEMENT */, "&");
|
|
1455
|
+
row_sep = new TypstToken(1 /* SYMBOL */, "\\");
|
|
1456
|
+
}
|
|
1457
|
+
if (!this.head.eq(TypstToken.NONE)) {
|
|
1458
|
+
queue.push(this.head);
|
|
1459
|
+
env.insideFunctionDepth++;
|
|
1460
|
+
queue.push(TYPST_LEFT_PARENTHESIS);
|
|
1461
|
+
if (this.options) {
|
|
1462
|
+
for (const [key, value] of Object.entries(this.options)) {
|
|
1463
|
+
queue.push(new TypstToken(3 /* LITERAL */, `${key}: ${value.toString()}, `));
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
this.matrix.forEach((row, i) => {
|
|
1468
|
+
row.forEach((cell, j) => {
|
|
1469
|
+
queue.push(...cell.serialize(env, options));
|
|
1470
|
+
if (j < row.length - 1) {
|
|
1471
|
+
queue.push(cell_sep);
|
|
1472
|
+
} else {
|
|
1473
|
+
if (i < this.matrix.length - 1) {
|
|
1474
|
+
queue.push(row_sep);
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
});
|
|
1478
|
+
});
|
|
1479
|
+
if (!this.head.eq(TypstToken.NONE)) {
|
|
1480
|
+
queue.push(TYPST_RIGHT_PARENTHESIS);
|
|
1481
|
+
env.insideFunctionDepth--;
|
|
1482
|
+
}
|
|
1483
|
+
return queue;
|
|
1484
|
+
}
|
|
1254
1485
|
static MAT = new TypstToken(1 /* SYMBOL */, "mat");
|
|
1255
1486
|
static CASES = new TypstToken(1 /* SYMBOL */, "cases");
|
|
1256
1487
|
};
|
|
@@ -1270,88 +1501,45 @@ var TypstMarkupFunc = class extends TypstNode {
|
|
|
1270
1501
|
isOverHigh() {
|
|
1271
1502
|
return this.fragments.some((n) => n.isOverHigh());
|
|
1272
1503
|
}
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
["arrow.r", "->"],
|
|
1298
|
-
["arrow.r.double", "=>"],
|
|
1299
|
-
["arrow.r.squiggly", "~>"],
|
|
1300
|
-
["arrow.l", "<-"],
|
|
1301
|
-
["arrow.l.squiggly", "<~"],
|
|
1302
|
-
["bar.v.double", "||"],
|
|
1303
|
-
["bracket.l.double", "[|"],
|
|
1304
|
-
["bracket.r.double", "|]"],
|
|
1305
|
-
["colon.eq", ":="],
|
|
1306
|
-
["eq.colon", "=:"],
|
|
1307
|
-
["eq.not", "!="],
|
|
1308
|
-
["gt.double", ">>"],
|
|
1309
|
-
["gt.eq", ">="],
|
|
1310
|
-
["lt.double", "<<"],
|
|
1311
|
-
["lt.eq", "<="],
|
|
1312
|
-
["ast.op", "*"],
|
|
1313
|
-
["minus", "-"],
|
|
1314
|
-
["tilde.op", "~"]
|
|
1315
|
-
]);
|
|
1316
|
-
var reverseShorthandMap = /* @__PURE__ */ new Map();
|
|
1317
|
-
for (const [key, value] of shorthandMap.entries()) {
|
|
1318
|
-
if (value.length > 1) {
|
|
1319
|
-
reverseShorthandMap.set(value, key);
|
|
1504
|
+
serialize(env, options) {
|
|
1505
|
+
const queue = [];
|
|
1506
|
+
queue.push(this.head);
|
|
1507
|
+
env.insideFunctionDepth++;
|
|
1508
|
+
queue.push(TYPST_LEFT_PARENTHESIS);
|
|
1509
|
+
if (this.options) {
|
|
1510
|
+
const entries = Object.entries(this.options);
|
|
1511
|
+
for (let i = 0; i < entries.length; i++) {
|
|
1512
|
+
const [key, value] = entries[i];
|
|
1513
|
+
queue.push(new TypstToken(3 /* LITERAL */, `${key}: ${value.toString()}`));
|
|
1514
|
+
if (i < entries.length - 1) {
|
|
1515
|
+
queue.push(new TypstToken(2 /* ELEMENT */, ","));
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
queue.push(TYPST_RIGHT_PARENTHESIS);
|
|
1520
|
+
queue.push(new TypstToken(3 /* LITERAL */, "["));
|
|
1521
|
+
for (const frag of this.fragments) {
|
|
1522
|
+
queue.push(new TypstToken(3 /* LITERAL */, "$"));
|
|
1523
|
+
queue.push(...frag.serialize(env, options));
|
|
1524
|
+
queue.push(new TypstToken(3 /* LITERAL */, "$"));
|
|
1525
|
+
}
|
|
1526
|
+
queue.push(new TypstToken(3 /* LITERAL */, "]"));
|
|
1527
|
+
return queue;
|
|
1320
1528
|
}
|
|
1321
|
-
}
|
|
1529
|
+
};
|
|
1322
1530
|
|
|
1323
1531
|
// src/typst-writer.ts
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
}
|
|
1327
|
-
var TYPST_LEFT_PARENTHESIS = new TypstToken(2 /* ELEMENT */, "(");
|
|
1328
|
-
var TYPST_RIGHT_PARENTHESIS = new TypstToken(2 /* ELEMENT */, ")");
|
|
1532
|
+
var TYPST_LEFT_PARENTHESIS2 = new TypstToken(2 /* ELEMENT */, "(");
|
|
1533
|
+
var TYPST_RIGHT_PARENTHESIS2 = new TypstToken(2 /* ELEMENT */, ")");
|
|
1329
1534
|
var TYPST_COMMA = new TypstToken(2 /* ELEMENT */, ",");
|
|
1330
1535
|
var TYPST_NEWLINE = new TypstToken(1 /* SYMBOL */, "\n");
|
|
1331
|
-
var
|
|
1332
|
-
var TypstWriterError = class extends Error {
|
|
1333
|
-
node;
|
|
1334
|
-
constructor(message, node) {
|
|
1335
|
-
super(message);
|
|
1336
|
-
this.name = "TypstWriterError";
|
|
1337
|
-
this.node = node;
|
|
1338
|
-
}
|
|
1339
|
-
};
|
|
1536
|
+
var SOFT_SPACE2 = new TypstToken(7 /* CONTROL */, " ");
|
|
1340
1537
|
var TypstWriter = class {
|
|
1341
|
-
nonStrict;
|
|
1342
|
-
preferShorthands;
|
|
1343
|
-
keepSpaces;
|
|
1344
|
-
inftyToOo;
|
|
1345
|
-
optimize;
|
|
1346
1538
|
buffer = "";
|
|
1347
1539
|
queue = [];
|
|
1348
|
-
|
|
1540
|
+
options;
|
|
1349
1541
|
constructor(options) {
|
|
1350
|
-
this.
|
|
1351
|
-
this.preferShorthands = options.preferShorthands;
|
|
1352
|
-
this.keepSpaces = options.keepSpaces;
|
|
1353
|
-
this.inftyToOo = options.inftyToOo;
|
|
1354
|
-
this.optimize = options.optimize;
|
|
1542
|
+
this.options = options;
|
|
1355
1543
|
}
|
|
1356
1544
|
writeBuffer(previousToken, token) {
|
|
1357
1545
|
const str = token.toString();
|
|
@@ -1367,7 +1555,7 @@ var TypstWriter = class {
|
|
|
1367
1555
|
no_need_space ||= /[\(\[{]\s*(-|\+)$/.test(this.buffer) || this.buffer === "-" || this.buffer === "+";
|
|
1368
1556
|
no_need_space ||= str.startsWith("\n");
|
|
1369
1557
|
no_need_space ||= this.buffer === "";
|
|
1370
|
-
no_need_space ||= /^\s/.test(str);
|
|
1558
|
+
no_need_space ||= /\s$/.test(this.buffer) || /^\s/.test(str);
|
|
1371
1559
|
no_need_space ||= this.buffer.endsWith("&") && str === "=";
|
|
1372
1560
|
no_need_space ||= this.buffer.endsWith("/") || str === "/";
|
|
1373
1561
|
no_need_space ||= token.type === 3 /* LITERAL */;
|
|
@@ -1382,239 +1570,31 @@ var TypstWriter = class {
|
|
|
1382
1570
|
}
|
|
1383
1571
|
// Serialize a tree of TypstNode into a list of TypstToken
|
|
1384
1572
|
serialize(abstractNode) {
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
const node = abstractNode;
|
|
1388
|
-
if (node.head.type === 2 /* ELEMENT */) {
|
|
1389
|
-
if (node.head.value === "," && this.insideFunctionDepth > 0) {
|
|
1390
|
-
this.queue.push(new TypstToken(1 /* SYMBOL */, "comma"));
|
|
1391
|
-
} else {
|
|
1392
|
-
this.queue.push(node.head);
|
|
1393
|
-
}
|
|
1394
|
-
break;
|
|
1395
|
-
} else if (node.head.type === 1 /* SYMBOL */) {
|
|
1396
|
-
let symbol_name = node.head.value;
|
|
1397
|
-
if (this.preferShorthands) {
|
|
1398
|
-
if (shorthandMap.has(symbol_name)) {
|
|
1399
|
-
symbol_name = shorthandMap.get(symbol_name);
|
|
1400
|
-
}
|
|
1401
|
-
}
|
|
1402
|
-
if (this.inftyToOo && symbol_name === "infinity") {
|
|
1403
|
-
symbol_name = "oo";
|
|
1404
|
-
}
|
|
1405
|
-
this.queue.push(new TypstToken(1 /* SYMBOL */, symbol_name));
|
|
1406
|
-
break;
|
|
1407
|
-
} else if (node.head.type === 6 /* SPACE */ || node.head.type === 8 /* NEWLINE */) {
|
|
1408
|
-
for (const c of node.head.value) {
|
|
1409
|
-
if (c === " ") {
|
|
1410
|
-
if (this.keepSpaces) {
|
|
1411
|
-
this.queue.push(new TypstToken(6 /* SPACE */, c));
|
|
1412
|
-
}
|
|
1413
|
-
} else if (c === "\n") {
|
|
1414
|
-
this.queue.push(new TypstToken(1 /* SYMBOL */, c));
|
|
1415
|
-
} else {
|
|
1416
|
-
throw new TypstWriterError(`Unexpected whitespace character: ${c}`, node);
|
|
1417
|
-
}
|
|
1418
|
-
}
|
|
1419
|
-
break;
|
|
1420
|
-
} else {
|
|
1421
|
-
this.queue.push(node.head);
|
|
1422
|
-
break;
|
|
1423
|
-
}
|
|
1424
|
-
}
|
|
1425
|
-
case "group": {
|
|
1426
|
-
const node = abstractNode;
|
|
1427
|
-
for (const item of node.items) {
|
|
1428
|
-
this.serialize(item);
|
|
1429
|
-
}
|
|
1430
|
-
break;
|
|
1431
|
-
}
|
|
1432
|
-
case "leftright": {
|
|
1433
|
-
const node = abstractNode;
|
|
1434
|
-
const LR = new TypstToken(1 /* SYMBOL */, "lr");
|
|
1435
|
-
const { left, right } = node;
|
|
1436
|
-
if (node.head.eq(LR)) {
|
|
1437
|
-
this.queue.push(LR);
|
|
1438
|
-
this.queue.push(TYPST_LEFT_PARENTHESIS);
|
|
1439
|
-
}
|
|
1440
|
-
if (left) {
|
|
1441
|
-
this.queue.push(left);
|
|
1442
|
-
}
|
|
1443
|
-
this.serialize(node.body);
|
|
1444
|
-
if (right) {
|
|
1445
|
-
this.queue.push(right);
|
|
1446
|
-
}
|
|
1447
|
-
if (node.head.eq(LR)) {
|
|
1448
|
-
this.queue.push(TYPST_RIGHT_PARENTHESIS);
|
|
1449
|
-
}
|
|
1450
|
-
break;
|
|
1451
|
-
}
|
|
1452
|
-
case "supsub": {
|
|
1453
|
-
const node = abstractNode;
|
|
1454
|
-
let { base, sup, sub } = node;
|
|
1455
|
-
this.appendWithBracketsIfNeeded(base);
|
|
1456
|
-
let trailing_space_needed = false;
|
|
1457
|
-
const has_prime = sup && sup.head.eq(new TypstToken(2 /* ELEMENT */, "'"));
|
|
1458
|
-
if (has_prime) {
|
|
1459
|
-
this.queue.push(new TypstToken(2 /* ELEMENT */, "'"));
|
|
1460
|
-
trailing_space_needed = false;
|
|
1461
|
-
}
|
|
1462
|
-
if (sub) {
|
|
1463
|
-
this.queue.push(new TypstToken(2 /* ELEMENT */, "_"));
|
|
1464
|
-
trailing_space_needed = this.appendWithBracketsIfNeeded(sub);
|
|
1465
|
-
}
|
|
1466
|
-
if (sup && !has_prime) {
|
|
1467
|
-
this.queue.push(new TypstToken(2 /* ELEMENT */, "^"));
|
|
1468
|
-
trailing_space_needed = this.appendWithBracketsIfNeeded(sup);
|
|
1469
|
-
}
|
|
1470
|
-
if (trailing_space_needed) {
|
|
1471
|
-
this.queue.push(SOFT_SPACE);
|
|
1472
|
-
}
|
|
1473
|
-
break;
|
|
1474
|
-
}
|
|
1475
|
-
case "funcCall": {
|
|
1476
|
-
const node = abstractNode;
|
|
1477
|
-
const func_symbol = node.head;
|
|
1478
|
-
this.queue.push(func_symbol);
|
|
1479
|
-
this.insideFunctionDepth++;
|
|
1480
|
-
this.queue.push(TYPST_LEFT_PARENTHESIS);
|
|
1481
|
-
for (let i = 0; i < node.args.length; i++) {
|
|
1482
|
-
this.serialize(node.args[i]);
|
|
1483
|
-
if (i < node.args.length - 1) {
|
|
1484
|
-
this.queue.push(new TypstToken(2 /* ELEMENT */, ","));
|
|
1485
|
-
}
|
|
1486
|
-
}
|
|
1487
|
-
if (node.options) {
|
|
1488
|
-
for (const [key, value] of Object.entries(node.options)) {
|
|
1489
|
-
this.queue.push(new TypstToken(3 /* LITERAL */, `, ${key}: ${value.toString()}`));
|
|
1490
|
-
}
|
|
1491
|
-
}
|
|
1492
|
-
this.queue.push(TYPST_RIGHT_PARENTHESIS);
|
|
1493
|
-
this.insideFunctionDepth--;
|
|
1494
|
-
break;
|
|
1495
|
-
}
|
|
1496
|
-
case "fraction": {
|
|
1497
|
-
const node = abstractNode;
|
|
1498
|
-
const [numerator, denominator] = node.args;
|
|
1499
|
-
const pos = this.queue.length;
|
|
1500
|
-
const no_wrap = this.appendWithBracketsIfNeeded(numerator);
|
|
1501
|
-
const wrapped = !no_wrap;
|
|
1502
|
-
if (wrapped) {
|
|
1503
|
-
this.queue.splice(pos, 0, SOFT_SPACE);
|
|
1504
|
-
}
|
|
1505
|
-
this.queue.push(new TypstToken(2 /* ELEMENT */, "/"));
|
|
1506
|
-
this.appendWithBracketsIfNeeded(denominator);
|
|
1507
|
-
break;
|
|
1508
|
-
}
|
|
1509
|
-
case "matrixLike": {
|
|
1510
|
-
const node = abstractNode;
|
|
1511
|
-
const matrix = node.matrix;
|
|
1512
|
-
let cell_sep;
|
|
1513
|
-
let row_sep;
|
|
1514
|
-
if (node.head.eq(TypstMatrixLike.MAT)) {
|
|
1515
|
-
cell_sep = new TypstToken(2 /* ELEMENT */, ",");
|
|
1516
|
-
row_sep = new TypstToken(2 /* ELEMENT */, ";");
|
|
1517
|
-
} else if (node.head.eq(TypstMatrixLike.CASES)) {
|
|
1518
|
-
cell_sep = new TypstToken(2 /* ELEMENT */, "&");
|
|
1519
|
-
row_sep = new TypstToken(2 /* ELEMENT */, ",");
|
|
1520
|
-
} else if (node.head.eq(TypstToken.NONE)) {
|
|
1521
|
-
cell_sep = new TypstToken(2 /* ELEMENT */, "&");
|
|
1522
|
-
row_sep = new TypstToken(1 /* SYMBOL */, "\\");
|
|
1523
|
-
}
|
|
1524
|
-
if (!node.head.eq(TypstToken.NONE)) {
|
|
1525
|
-
this.queue.push(node.head);
|
|
1526
|
-
this.insideFunctionDepth++;
|
|
1527
|
-
this.queue.push(TYPST_LEFT_PARENTHESIS);
|
|
1528
|
-
if (node.options) {
|
|
1529
|
-
for (const [key, value] of Object.entries(node.options)) {
|
|
1530
|
-
this.queue.push(new TypstToken(3 /* LITERAL */, `${key}: ${value.toString()}, `));
|
|
1531
|
-
}
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
|
-
matrix.forEach((row, i) => {
|
|
1535
|
-
row.forEach((cell, j) => {
|
|
1536
|
-
this.serialize(cell);
|
|
1537
|
-
if (j < row.length - 1) {
|
|
1538
|
-
this.queue.push(cell_sep);
|
|
1539
|
-
} else {
|
|
1540
|
-
if (i < matrix.length - 1) {
|
|
1541
|
-
this.queue.push(row_sep);
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
|
-
});
|
|
1545
|
-
});
|
|
1546
|
-
if (!node.head.eq(TypstToken.NONE)) {
|
|
1547
|
-
this.queue.push(TYPST_RIGHT_PARENTHESIS);
|
|
1548
|
-
this.insideFunctionDepth--;
|
|
1549
|
-
}
|
|
1550
|
-
break;
|
|
1551
|
-
}
|
|
1552
|
-
case "markupFunc": {
|
|
1553
|
-
const node = abstractNode;
|
|
1554
|
-
this.queue.push(node.head);
|
|
1555
|
-
this.queue.push(TYPST_LEFT_PARENTHESIS);
|
|
1556
|
-
if (node.options) {
|
|
1557
|
-
const entries = Object.entries(node.options);
|
|
1558
|
-
for (let i = 0; i < entries.length; i++) {
|
|
1559
|
-
const [key, value] = entries[i];
|
|
1560
|
-
this.queue.push(new TypstToken(3 /* LITERAL */, `${key}: ${value.toString()}`));
|
|
1561
|
-
if (i < entries.length - 1) {
|
|
1562
|
-
this.queue.push(new TypstToken(2 /* ELEMENT */, ","));
|
|
1563
|
-
}
|
|
1564
|
-
}
|
|
1565
|
-
}
|
|
1566
|
-
this.queue.push(TYPST_RIGHT_PARENTHESIS);
|
|
1567
|
-
this.queue.push(new TypstToken(3 /* LITERAL */, "["));
|
|
1568
|
-
for (const frag of node.fragments) {
|
|
1569
|
-
this.queue.push(new TypstToken(3 /* LITERAL */, "$"));
|
|
1570
|
-
this.serialize(frag);
|
|
1571
|
-
this.queue.push(new TypstToken(3 /* LITERAL */, "$"));
|
|
1572
|
-
}
|
|
1573
|
-
this.queue.push(new TypstToken(3 /* LITERAL */, "]"));
|
|
1574
|
-
break;
|
|
1575
|
-
}
|
|
1576
|
-
default:
|
|
1577
|
-
throw new TypstWriterError(`Unimplemented node type to append: ${abstractNode.type}`, abstractNode);
|
|
1578
|
-
}
|
|
1573
|
+
const env = { insideFunctionDepth: 0 };
|
|
1574
|
+
this.queue.push(...abstractNode.serialize(env, this.options));
|
|
1579
1575
|
}
|
|
1580
|
-
|
|
1581
|
-
let
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
need_to_wrap = true;
|
|
1586
|
-
} else {
|
|
1587
|
-
const first = group.items[0];
|
|
1588
|
-
const last = group.items[group.items.length - 1];
|
|
1589
|
-
if (is_delimiter(first) && is_delimiter(last)) {
|
|
1590
|
-
need_to_wrap = false;
|
|
1591
|
-
}
|
|
1576
|
+
flushQueue() {
|
|
1577
|
+
let qu = [];
|
|
1578
|
+
for (const token of this.queue) {
|
|
1579
|
+
if (token.eq(SOFT_SPACE2) && qu.length > 0 && qu[qu.length - 1].eq(SOFT_SPACE2)) {
|
|
1580
|
+
continue;
|
|
1592
1581
|
}
|
|
1582
|
+
qu.push(token);
|
|
1593
1583
|
}
|
|
1594
|
-
if (need_to_wrap) {
|
|
1595
|
-
this.queue.push(TYPST_LEFT_PARENTHESIS);
|
|
1596
|
-
this.serialize(node);
|
|
1597
|
-
this.queue.push(TYPST_RIGHT_PARENTHESIS);
|
|
1598
|
-
} else {
|
|
1599
|
-
this.serialize(node);
|
|
1600
|
-
}
|
|
1601
|
-
return !need_to_wrap;
|
|
1602
|
-
}
|
|
1603
|
-
flushQueue() {
|
|
1604
1584
|
const dummy_token = new TypstToken(1 /* SYMBOL */, "");
|
|
1605
|
-
for (let i = 0; i <
|
|
1606
|
-
let token =
|
|
1607
|
-
if (token.eq(
|
|
1608
|
-
const to_delete = i === 0 || i ===
|
|
1585
|
+
for (let i = 0; i < qu.length; i++) {
|
|
1586
|
+
let token = qu[i];
|
|
1587
|
+
if (token.eq(SOFT_SPACE2)) {
|
|
1588
|
+
const to_delete = i === 0 || i === qu.length - 1 || qu[i - 1].type === 6 /* SPACE */ || qu[i - 1].isOneOf([TYPST_LEFT_PARENTHESIS2, TYPST_NEWLINE]) || qu[i + 1].isOneOf([TYPST_RIGHT_PARENTHESIS2, TYPST_COMMA, TYPST_NEWLINE]);
|
|
1609
1589
|
if (to_delete) {
|
|
1610
|
-
|
|
1590
|
+
qu[i] = dummy_token;
|
|
1611
1591
|
}
|
|
1612
1592
|
}
|
|
1613
1593
|
}
|
|
1614
|
-
|
|
1615
|
-
for (let i = 0; i <
|
|
1616
|
-
let token =
|
|
1617
|
-
let previous_token = i === 0 ? null :
|
|
1594
|
+
qu = qu.filter((token) => !token.eq(dummy_token));
|
|
1595
|
+
for (let i = 0; i < qu.length; i++) {
|
|
1596
|
+
let token = qu[i];
|
|
1597
|
+
let previous_token = i === 0 ? null : qu[i - 1];
|
|
1618
1598
|
this.writeBuffer(previous_token, token);
|
|
1619
1599
|
}
|
|
1620
1600
|
this.queue = [];
|
|
@@ -1636,7 +1616,7 @@ var TypstWriter = class {
|
|
|
1636
1616
|
res = res.replace(/round\(\)/g, 'round("")');
|
|
1637
1617
|
return res;
|
|
1638
1618
|
};
|
|
1639
|
-
if (this.optimize) {
|
|
1619
|
+
if (this.options.optimize) {
|
|
1640
1620
|
const all_passes = [smartFloorPass, smartCeilPass, smartRoundPass];
|
|
1641
1621
|
for (const pass of all_passes) {
|
|
1642
1622
|
this.buffer = pass(this.buffer);
|
|
@@ -2874,6 +2854,35 @@ function convert_tex_array_align_literal(alignLiteral) {
|
|
|
2874
2854
|
}
|
|
2875
2855
|
return np;
|
|
2876
2856
|
}
|
|
2857
|
+
var TYPST_LEFT_PARENTHESIS3 = new TypstToken(2 /* ELEMENT */, "(");
|
|
2858
|
+
var TYPST_RIGHT_PARENTHESIS3 = new TypstToken(2 /* ELEMENT */, ")");
|
|
2859
|
+
function is_delimiter(c) {
|
|
2860
|
+
return c.head.type === 2 /* ELEMENT */ && ["(", ")", "[", "]", "{", "}", "|", "\u230A", "\u230B", "\u2308", "\u2309"].includes(c.head.value);
|
|
2861
|
+
}
|
|
2862
|
+
function appendWithBracketsIfNeeded(node) {
|
|
2863
|
+
let need_to_wrap = ["group", "supsub", "matrixLike", "fraction", "empty"].includes(node.type);
|
|
2864
|
+
if (node.type === "group") {
|
|
2865
|
+
const group = node;
|
|
2866
|
+
if (group.items.length === 0) {
|
|
2867
|
+
need_to_wrap = true;
|
|
2868
|
+
} else {
|
|
2869
|
+
const first = group.items[0];
|
|
2870
|
+
const last = group.items[group.items.length - 1];
|
|
2871
|
+
if (is_delimiter(first) && is_delimiter(last)) {
|
|
2872
|
+
need_to_wrap = false;
|
|
2873
|
+
}
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
if (need_to_wrap) {
|
|
2877
|
+
return new TypstLeftright(null, {
|
|
2878
|
+
left: TYPST_LEFT_PARENTHESIS3,
|
|
2879
|
+
right: TYPST_RIGHT_PARENTHESIS3,
|
|
2880
|
+
body: node
|
|
2881
|
+
});
|
|
2882
|
+
} else {
|
|
2883
|
+
return node;
|
|
2884
|
+
}
|
|
2885
|
+
}
|
|
2877
2886
|
function convert_tex_node_to_typst(abstractNode, options = {}) {
|
|
2878
2887
|
switch (abstractNode.type) {
|
|
2879
2888
|
case "terminal": {
|
|
@@ -2914,6 +2923,13 @@ function convert_tex_node_to_typst(abstractNode, options = {}) {
|
|
|
2914
2923
|
sup: sup ? convert_tex_node_to_typst(sup, options) : null,
|
|
2915
2924
|
sub: sub ? convert_tex_node_to_typst(sub, options) : null
|
|
2916
2925
|
};
|
|
2926
|
+
data.base = appendWithBracketsIfNeeded(data.base);
|
|
2927
|
+
if (data.sup) {
|
|
2928
|
+
data.sup = appendWithBracketsIfNeeded(data.sup);
|
|
2929
|
+
}
|
|
2930
|
+
if (data.sub) {
|
|
2931
|
+
data.sub = appendWithBracketsIfNeeded(data.sub);
|
|
2932
|
+
}
|
|
2917
2933
|
return new TypstSupsub(data);
|
|
2918
2934
|
}
|
|
2919
2935
|
case "leftright": {
|
|
@@ -3010,6 +3026,12 @@ function convert_tex_node_to_typst(abstractNode, options = {}) {
|
|
|
3010
3026
|
if (node2.head.value === "\\substack") {
|
|
3011
3027
|
return arg0;
|
|
3012
3028
|
}
|
|
3029
|
+
if (node2.head.value === "\\set") {
|
|
3030
|
+
return new TypstLeftright(
|
|
3031
|
+
null,
|
|
3032
|
+
{ body: arg0, left: TypstToken.LEFT_BRACE, right: TypstToken.RIGHT_BRACE }
|
|
3033
|
+
);
|
|
3034
|
+
}
|
|
3013
3035
|
if (node2.head.value === "\\overset") {
|
|
3014
3036
|
return convert_overset(node2, options);
|
|
3015
3037
|
}
|
|
@@ -3018,7 +3040,7 @@ function convert_tex_node_to_typst(abstractNode, options = {}) {
|
|
|
3018
3040
|
}
|
|
3019
3041
|
if (node2.head.value === "\\frac") {
|
|
3020
3042
|
if (options.fracToSlash) {
|
|
3021
|
-
return new TypstFraction(node2.args.map((n) => convert_tex_node_to_typst(n, options)));
|
|
3043
|
+
return new TypstFraction(node2.args.map((n) => convert_tex_node_to_typst(n, options)).map(appendWithBracketsIfNeeded));
|
|
3022
3044
|
}
|
|
3023
3045
|
}
|
|
3024
3046
|
if (options.optimize) {
|
|
@@ -3511,8 +3533,8 @@ function find_closing_delim(tokens, start) {
|
|
|
3511
3533
|
return _find_closing_match(
|
|
3512
3534
|
tokens,
|
|
3513
3535
|
start,
|
|
3514
|
-
|
|
3515
|
-
|
|
3536
|
+
TypstToken.LEFT_DELIMITERS,
|
|
3537
|
+
TypstToken.RIGHT_DELIMITERS
|
|
3516
3538
|
);
|
|
3517
3539
|
}
|
|
3518
3540
|
function find_closing_parenthesis(nodes, start) {
|
|
@@ -3645,7 +3667,6 @@ var LEFT_BRACKET = new TypstToken(2 /* ELEMENT */, "[");
|
|
|
3645
3667
|
var RIGHT_BRACKET = new TypstToken(2 /* ELEMENT */, "]");
|
|
3646
3668
|
var LEFT_CURLY_BRACKET2 = new TypstToken(2 /* ELEMENT */, "{");
|
|
3647
3669
|
var RIGHT_CURLY_BRACKET2 = new TypstToken(2 /* ELEMENT */, "}");
|
|
3648
|
-
var VERTICAL_BAR = new TypstToken(2 /* ELEMENT */, "|");
|
|
3649
3670
|
var COMMA = new TypstToken(2 /* ELEMENT */, ",");
|
|
3650
3671
|
var SEMICOLON = new TypstToken(2 /* ELEMENT */, ";");
|
|
3651
3672
|
var SINGLE_SPACE = new TypstToken(6 /* SPACE */, " ");
|
|
@@ -3786,20 +3807,20 @@ var TypstParser = class {
|
|
|
3786
3807
|
// start: the position of the left parentheses
|
|
3787
3808
|
parseLrArguments(tokens, start) {
|
|
3788
3809
|
const lr_token = tokens[start];
|
|
3789
|
-
|
|
3790
|
-
|
|
3810
|
+
const end = find_closing_match2(tokens, start);
|
|
3811
|
+
if (tokens[start + 1].isOneOf(TypstToken.LEFT_DELIMITERS)) {
|
|
3791
3812
|
const inner_start = start + 1;
|
|
3792
3813
|
const inner_end = find_closing_delim(tokens, inner_start);
|
|
3793
|
-
const inner_args = this.
|
|
3814
|
+
const [inner_args, _] = this.parseGroup(tokens, inner_start + 1, inner_end);
|
|
3794
3815
|
return [
|
|
3795
|
-
new TypstLeftright(lr_token, { body:
|
|
3816
|
+
new TypstLeftright(lr_token, { body: inner_args, left: tokens[inner_start], right: tokens[inner_end] }),
|
|
3796
3817
|
end + 1
|
|
3797
3818
|
];
|
|
3798
3819
|
} else {
|
|
3799
|
-
const [
|
|
3820
|
+
const [inner_args, _] = this.parseGroup(tokens, start + 1, end - 1);
|
|
3800
3821
|
return [
|
|
3801
|
-
new TypstLeftright(lr_token, { body:
|
|
3802
|
-
end
|
|
3822
|
+
new TypstLeftright(lr_token, { body: inner_args, left: null, right: null }),
|
|
3823
|
+
end + 1
|
|
3803
3824
|
];
|
|
3804
3825
|
}
|
|
3805
3826
|
}
|
|
@@ -3923,8 +3944,11 @@ function tex2typst(tex, options) {
|
|
|
3923
3944
|
customTexMacros: {}
|
|
3924
3945
|
};
|
|
3925
3946
|
if (options !== void 0) {
|
|
3947
|
+
if (typeof options !== "object") {
|
|
3948
|
+
throw new Error("options must be an object");
|
|
3949
|
+
}
|
|
3926
3950
|
for (const key in opt) {
|
|
3927
|
-
if (
|
|
3951
|
+
if (key in options) {
|
|
3928
3952
|
opt[key] = options[key];
|
|
3929
3953
|
}
|
|
3930
3954
|
}
|