tex2typst 0.2.13 → 0.2.16

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/index.js CHANGED
@@ -160,7 +160,7 @@ var symbolMap = new Map([
160
160
  ["langle", "angle.l"],
161
161
  ["lbrace", "brace.l"],
162
162
  ["lbrack", "bracket.l"],
163
- ["ldots", "dots.l"],
163
+ ["ldots", "dots.h"],
164
164
  ["le", "lt.eq"],
165
165
  ["leadsto", "arrow.squiggly"],
166
166
  ["leftarrow", "arrow.l"],
@@ -1034,7 +1034,73 @@ for (const [key, value] of map_from_official_docs) {
1034
1034
  }
1035
1035
  }
1036
1036
 
1037
- // src/parser.ts
1037
+ // src/types.ts
1038
+ class TexNode {
1039
+ type;
1040
+ content;
1041
+ args;
1042
+ data;
1043
+ constructor(type, content, args, data) {
1044
+ this.type = type;
1045
+ this.content = content;
1046
+ this.args = args;
1047
+ this.data = data;
1048
+ }
1049
+ eq_shallow(other) {
1050
+ return this.type === other.type && this.content === other.content;
1051
+ }
1052
+ toString() {
1053
+ switch (this.type) {
1054
+ case "text":
1055
+ return `\\text{${this.content}}`;
1056
+ default:
1057
+ throw new Error(`toString() is not implemented for type ${this.type}`);
1058
+ }
1059
+ }
1060
+ }
1061
+ class TypstToken {
1062
+ type;
1063
+ content;
1064
+ constructor(type, content) {
1065
+ this.type = type;
1066
+ this.content = content;
1067
+ }
1068
+ eq(other) {
1069
+ return this.type === other.type && this.content === other.content;
1070
+ }
1071
+ isOneOf(tokens) {
1072
+ let found = false;
1073
+ for (const token of tokens) {
1074
+ if (this.eq(token)) {
1075
+ found = true;
1076
+ break;
1077
+ }
1078
+ }
1079
+ return found;
1080
+ }
1081
+ }
1082
+
1083
+ class TypstNode {
1084
+ type;
1085
+ content;
1086
+ args;
1087
+ data;
1088
+ options;
1089
+ constructor(type, content, args, data) {
1090
+ this.type = type;
1091
+ this.content = content;
1092
+ this.args = args;
1093
+ this.data = data;
1094
+ }
1095
+ setOptions(options) {
1096
+ this.options = options;
1097
+ }
1098
+ eq_shallow(other) {
1099
+ return this.type === other.type && this.content === other.content;
1100
+ }
1101
+ }
1102
+
1103
+ // src/tex-parser.ts
1038
1104
  function assert(condition, message = "") {
1039
1105
  if (!condition) {
1040
1106
  throw new LatexParserError(message);
@@ -1091,7 +1157,7 @@ function isdigit(char) {
1091
1157
  }
1092
1158
  function eat_whitespaces(tokens, start) {
1093
1159
  let pos = start;
1094
- while (pos < tokens.length && [4 /* WHITESPACE */, 5 /* NEWLINE */].includes(tokens[pos].type)) {
1160
+ while (pos < tokens.length && [4 /* SPACE */, 5 /* NEWLINE */].includes(tokens[pos].type)) {
1095
1161
  pos++;
1096
1162
  }
1097
1163
  return tokens.slice(start, pos);
@@ -1108,7 +1174,7 @@ function eat_parenthesis(tokens, start) {
1108
1174
  }
1109
1175
  function eat_primes(tokens, start) {
1110
1176
  let pos = start;
1111
- while (pos < tokens.length && tokens[pos].eq(new Token(0 /* ELEMENT */, "'"))) {
1177
+ while (pos < tokens.length && tokens[pos].eq(new TexToken(0 /* ELEMENT */, "'"))) {
1112
1178
  pos += 1;
1113
1179
  }
1114
1180
  return pos - start;
@@ -1185,7 +1251,7 @@ function tokenize(latex) {
1185
1251
  while (newPos < latex.length && latex[newPos] !== "\n") {
1186
1252
  newPos += 1;
1187
1253
  }
1188
- token = new Token(3 /* COMMENT */, latex.slice(pos + 1, newPos));
1254
+ token = new TexToken(3 /* COMMENT */, latex.slice(pos + 1, newPos));
1189
1255
  pos = newPos;
1190
1256
  break;
1191
1257
  }
@@ -1194,19 +1260,19 @@ function tokenize(latex) {
1194
1260
  case "_":
1195
1261
  case "^":
1196
1262
  case "&":
1197
- token = new Token(6 /* CONTROL */, firstChar);
1263
+ token = new TexToken(6 /* CONTROL */, firstChar);
1198
1264
  pos++;
1199
1265
  break;
1200
1266
  case "\n":
1201
- token = new Token(5 /* NEWLINE */, firstChar);
1267
+ token = new TexToken(5 /* NEWLINE */, firstChar);
1202
1268
  pos++;
1203
1269
  break;
1204
1270
  case "\r": {
1205
1271
  if (pos + 1 < latex.length && latex[pos + 1] === "\n") {
1206
- token = new Token(5 /* NEWLINE */, "\n");
1272
+ token = new TexToken(5 /* NEWLINE */, "\n");
1207
1273
  pos += 2;
1208
1274
  } else {
1209
- token = new Token(5 /* NEWLINE */, "\n");
1275
+ token = new TexToken(5 /* NEWLINE */, "\n");
1210
1276
  pos++;
1211
1277
  }
1212
1278
  break;
@@ -1216,7 +1282,7 @@ function tokenize(latex) {
1216
1282
  while (newPos < latex.length && latex[newPos] === " ") {
1217
1283
  newPos += 1;
1218
1284
  }
1219
- token = new Token(4 /* WHITESPACE */, latex.slice(pos, newPos));
1285
+ token = new TexToken(4 /* SPACE */, latex.slice(pos, newPos));
1220
1286
  pos = newPos;
1221
1287
  break;
1222
1288
  }
@@ -1226,12 +1292,12 @@ function tokenize(latex) {
1226
1292
  }
1227
1293
  const firstTwoChars = latex.slice(pos, pos + 2);
1228
1294
  if (["\\\\", "\\,"].includes(firstTwoChars)) {
1229
- token = new Token(6 /* CONTROL */, firstTwoChars);
1295
+ token = new TexToken(6 /* CONTROL */, firstTwoChars);
1230
1296
  } else if (["\\{", "\\}", "\\%", "\\$", "\\&", "\\#", "\\_", "\\|"].includes(firstTwoChars)) {
1231
- token = new Token(0 /* ELEMENT */, firstTwoChars);
1297
+ token = new TexToken(0 /* ELEMENT */, firstTwoChars);
1232
1298
  } else {
1233
1299
  const command = eat_command_name(latex, pos + 1);
1234
- token = new Token(1 /* COMMAND */, "\\" + command);
1300
+ token = new TexToken(1 /* COMMAND */, "\\" + command);
1235
1301
  }
1236
1302
  pos += token.value.length;
1237
1303
  break;
@@ -1242,13 +1308,13 @@ function tokenize(latex) {
1242
1308
  while (newPos < latex.length && isdigit(latex[newPos])) {
1243
1309
  newPos += 1;
1244
1310
  }
1245
- token = new Token(0 /* ELEMENT */, latex.slice(pos, newPos));
1311
+ token = new TexToken(0 /* ELEMENT */, latex.slice(pos, newPos));
1246
1312
  } else if (isalpha(firstChar)) {
1247
- token = new Token(0 /* ELEMENT */, firstChar);
1313
+ token = new TexToken(0 /* ELEMENT */, firstChar);
1248
1314
  } else if ("+-*/=\'<>!.,;?()[]|".includes(firstChar)) {
1249
- token = new Token(0 /* ELEMENT */, firstChar);
1315
+ token = new TexToken(0 /* ELEMENT */, firstChar);
1250
1316
  } else {
1251
- token = new Token(7 /* UNKNOWN */, firstChar);
1317
+ token = new TexToken(7 /* UNKNOWN */, firstChar);
1252
1318
  }
1253
1319
  pos += token.value.length;
1254
1320
  }
@@ -1258,7 +1324,7 @@ function tokenize(latex) {
1258
1324
  if (pos >= latex.length || latex[pos] !== "{") {
1259
1325
  throw new LatexParserError(`No content for ${token.value} command`);
1260
1326
  }
1261
- tokens.push(new Token(6 /* CONTROL */, "{"));
1327
+ tokens.push(new TexToken(6 /* CONTROL */, "{"));
1262
1328
  const posClosingBracket = find_closing_curly_bracket_char(latex, pos);
1263
1329
  pos++;
1264
1330
  let textInside = latex.slice(pos, posClosingBracket);
@@ -1266,8 +1332,8 @@ function tokenize(latex) {
1266
1332
  for (const char of chars) {
1267
1333
  textInside = textInside.replaceAll("\\" + char, char);
1268
1334
  }
1269
- tokens.push(new Token(2 /* TEXT */, textInside));
1270
- tokens.push(new Token(6 /* CONTROL */, "}"));
1335
+ tokens.push(new TexToken(2 /* TEXT */, textInside));
1336
+ tokens.push(new TexToken(6 /* CONTROL */, "}"));
1271
1337
  pos = posClosingBracket + 1;
1272
1338
  }
1273
1339
  }
@@ -1277,10 +1343,10 @@ function passIgnoreWhitespaceBeforeScriptMark(tokens) {
1277
1343
  const is_script_mark = (token) => token.eq(SUB_SYMBOL) || token.eq(SUP_SYMBOL);
1278
1344
  let out_tokens = [];
1279
1345
  for (let i = 0;i < tokens.length; i++) {
1280
- if (tokens[i].type === 4 /* WHITESPACE */ && i + 1 < tokens.length && is_script_mark(tokens[i + 1])) {
1346
+ if (tokens[i].type === 4 /* SPACE */ && i + 1 < tokens.length && is_script_mark(tokens[i + 1])) {
1281
1347
  continue;
1282
1348
  }
1283
- if (tokens[i].type === 4 /* WHITESPACE */ && i - 1 >= 0 && is_script_mark(tokens[i - 1])) {
1349
+ if (tokens[i].type === 4 /* SPACE */ && i - 1 >= 0 && is_script_mark(tokens[i - 1])) {
1284
1350
  continue;
1285
1351
  }
1286
1352
  out_tokens.push(tokens[i]);
@@ -1346,7 +1412,7 @@ var BINARY_COMMANDS = [
1346
1412
  "overset"
1347
1413
  ];
1348
1414
 
1349
- class Token {
1415
+ class TexToken {
1350
1416
  type;
1351
1417
  value;
1352
1418
  constructor(type, value) {
@@ -1357,15 +1423,15 @@ class Token {
1357
1423
  return this.type === token.type && this.value === token.value;
1358
1424
  }
1359
1425
  }
1360
- var EMPTY_NODE = { type: "empty", content: "" };
1361
- var LEFT_CURLY_BRACKET = new Token(6 /* CONTROL */, "{");
1362
- var RIGHT_CURLY_BRACKET = new Token(6 /* CONTROL */, "}");
1363
- var LEFT_SQUARE_BRACKET = new Token(0 /* ELEMENT */, "[");
1364
- var RIGHT_SQUARE_BRACKET = new Token(0 /* ELEMENT */, "]");
1365
- var LEFT_COMMAND = new Token(1 /* COMMAND */, "\\left");
1366
- var RIGHT_COMMAND = new Token(1 /* COMMAND */, "\\right");
1367
- var BEGIN_COMMAND = new Token(1 /* COMMAND */, "\\begin");
1368
- var END_COMMAND = new Token(1 /* COMMAND */, "\\end");
1426
+ var EMPTY_NODE = new TexNode("empty", "");
1427
+ var LEFT_CURLY_BRACKET = new TexToken(6 /* CONTROL */, "{");
1428
+ var RIGHT_CURLY_BRACKET = new TexToken(6 /* CONTROL */, "}");
1429
+ var LEFT_SQUARE_BRACKET = new TexToken(0 /* ELEMENT */, "[");
1430
+ var RIGHT_SQUARE_BRACKET = new TexToken(0 /* ELEMENT */, "]");
1431
+ var LEFT_COMMAND = new TexToken(1 /* COMMAND */, "\\left");
1432
+ var RIGHT_COMMAND = new TexToken(1 /* COMMAND */, "\\right");
1433
+ var BEGIN_COMMAND = new TexToken(1 /* COMMAND */, "\\begin");
1434
+ var END_COMMAND = new TexToken(1 /* COMMAND */, "\\end");
1369
1435
 
1370
1436
  class LatexParserError extends Error {
1371
1437
  constructor(message) {
@@ -1373,8 +1439,8 @@ class LatexParserError extends Error {
1373
1439
  this.name = "LatexParserError";
1374
1440
  }
1375
1441
  }
1376
- var SUB_SYMBOL = new Token(6 /* CONTROL */, "_");
1377
- var SUP_SYMBOL = new Token(6 /* CONTROL */, "^");
1442
+ var SUB_SYMBOL = new TexToken(6 /* CONTROL */, "_");
1443
+ var SUP_SYMBOL = new TexToken(6 /* CONTROL */, "^");
1378
1444
 
1379
1445
  class LatexParser {
1380
1446
  space_sensitive;
@@ -1392,11 +1458,13 @@ class LatexParser {
1392
1458
  while (pos2 < tokens.length) {
1393
1459
  const [res, newPos] = this.parseNextExpr(tokens, pos2);
1394
1460
  pos2 = newPos;
1395
- if (!this.space_sensitive && res.type === "whitespace") {
1396
- continue;
1397
- }
1398
- if (!this.newline_sensitive && res.type === "newline") {
1399
- continue;
1461
+ if (res.type === "whitespace") {
1462
+ if (!this.space_sensitive && res.content.replace(/ /g, "").length === 0) {
1463
+ continue;
1464
+ }
1465
+ if (!this.newline_sensitive && res.content === "\n") {
1466
+ continue;
1467
+ }
1400
1468
  }
1401
1469
  if (res.type === "control" && res.content === "&") {
1402
1470
  throw new LatexParserError("Unexpected & outside of an alignment");
@@ -1408,7 +1476,7 @@ class LatexParser {
1408
1476
  } else if (results2.length === 1) {
1409
1477
  return results2[0];
1410
1478
  } else {
1411
- return { type: "ordgroup", content: "", args: results2 };
1479
+ return new TexNode("ordgroup", "", results2);
1412
1480
  }
1413
1481
  }
1414
1482
  if (results.length === 0) {
@@ -1416,7 +1484,7 @@ class LatexParser {
1416
1484
  } else if (results.length === 1) {
1417
1485
  return results[0];
1418
1486
  } else {
1419
- return { type: "ordgroup", content: "", args: results };
1487
+ return new TexNode("ordgroup", "", results);
1420
1488
  }
1421
1489
  }
1422
1490
  parseNextExpr(tokens, start) {
@@ -1454,9 +1522,9 @@ class LatexParser {
1454
1522
  res.sub = sub;
1455
1523
  }
1456
1524
  if (num_prime > 0) {
1457
- res.sup = { type: "ordgroup", content: "", args: [] };
1525
+ res.sup = new TexNode("ordgroup", "", []);
1458
1526
  for (let i = 0;i < num_prime; i++) {
1459
- res.sup.args.push({ type: "element", content: "'" });
1527
+ res.sup.args.push(new TexNode("element", "'"));
1460
1528
  }
1461
1529
  if (sup) {
1462
1530
  res.sup.args.push(sup);
@@ -1467,7 +1535,7 @@ class LatexParser {
1467
1535
  } else if (sup) {
1468
1536
  res.sup = sup;
1469
1537
  }
1470
- return [{ type: "supsub", content: "", data: res }, pos];
1538
+ return [new TexNode("supsub", "", [], res), pos];
1471
1539
  } else {
1472
1540
  return [base, pos];
1473
1541
  }
@@ -1477,15 +1545,14 @@ class LatexParser {
1477
1545
  const tokenType = firstToken.type;
1478
1546
  switch (tokenType) {
1479
1547
  case 0 /* ELEMENT */:
1480
- return [{ type: "element", content: firstToken.value }, start + 1];
1548
+ return [new TexNode("element", firstToken.value), start + 1];
1481
1549
  case 2 /* TEXT */:
1482
- return [{ type: "text", content: firstToken.value }, start + 1];
1550
+ return [new TexNode("text", firstToken.value), start + 1];
1483
1551
  case 3 /* COMMENT */:
1484
- return [{ type: "comment", content: firstToken.value }, start + 1];
1485
- case 4 /* WHITESPACE */:
1486
- return [{ type: "whitespace", content: firstToken.value }, start + 1];
1552
+ return [new TexNode("comment", firstToken.value), start + 1];
1553
+ case 4 /* SPACE */:
1487
1554
  case 5 /* NEWLINE */:
1488
- return [{ type: "newline", content: firstToken.value }, start + 1];
1555
+ return [new TexNode("whitespace", firstToken.value), start + 1];
1489
1556
  case 1 /* COMMAND */:
1490
1557
  if (firstToken.eq(BEGIN_COMMAND)) {
1491
1558
  return this.parseBeginEndExpr(tokens, start);
@@ -1504,9 +1571,9 @@ class LatexParser {
1504
1571
  case "}":
1505
1572
  throw new LatexParserError("Unmatched '}'");
1506
1573
  case "\\\\":
1507
- return [{ type: "control", content: "\\\\" }, start + 1];
1574
+ return [new TexNode("control", "\\\\"), start + 1];
1508
1575
  case "\\,":
1509
- return [{ type: "control", content: "\\," }, start + 1];
1576
+ return [new TexNode("control", "\\,"), start + 1];
1510
1577
  case "_": {
1511
1578
  return [EMPTY_NODE, start];
1512
1579
  }
@@ -1514,7 +1581,7 @@ class LatexParser {
1514
1581
  return [EMPTY_NODE, start];
1515
1582
  }
1516
1583
  case "&":
1517
- return [{ type: "control", content: "&" }, start + 1];
1584
+ return [new TexNode("control", "&"), start + 1];
1518
1585
  default:
1519
1586
  throw new LatexParserError("Unknown control sequence");
1520
1587
  }
@@ -1533,9 +1600,9 @@ class LatexParser {
1533
1600
  switch (paramNum) {
1534
1601
  case 0:
1535
1602
  if (!symbolMap.has(command.slice(1))) {
1536
- return [{ type: "unknownMacro", content: command }, pos];
1603
+ return [new TexNode("unknownMacro", command), pos];
1537
1604
  }
1538
- return [{ type: "symbol", content: command }, pos];
1605
+ return [new TexNode("symbol", command), pos];
1539
1606
  case 1: {
1540
1607
  if (command === "\\sqrt" && pos < tokens.length && tokens[pos].eq(LEFT_SQUARE_BRACKET)) {
1541
1608
  const posLeftSquareBracket = pos;
@@ -1543,7 +1610,7 @@ class LatexParser {
1543
1610
  const exprInside = tokens.slice(posLeftSquareBracket + 1, posRightSquareBracket);
1544
1611
  const exponent = this.parse(exprInside);
1545
1612
  const [arg12, newPos2] = this.parseNextExprWithoutSupSub(tokens, posRightSquareBracket + 1);
1546
- return [{ type: "unaryFunc", content: command, args: [arg12], data: exponent }, newPos2];
1613
+ return [new TexNode("unaryFunc", command, [arg12], exponent), newPos2];
1547
1614
  } else if (command === "\\text") {
1548
1615
  if (pos + 2 >= tokens.length) {
1549
1616
  throw new LatexParserError("Expecting content for \\text command");
@@ -1552,15 +1619,15 @@ class LatexParser {
1552
1619
  assert(tokens[pos + 1].type === 2 /* TEXT */);
1553
1620
  assert(tokens[pos + 2].eq(RIGHT_CURLY_BRACKET));
1554
1621
  const text = tokens[pos + 1].value;
1555
- return [{ type: "text", content: text }, pos + 3];
1622
+ return [new TexNode("text", text), pos + 3];
1556
1623
  }
1557
1624
  let [arg1, newPos] = this.parseNextExprWithoutSupSub(tokens, pos);
1558
- return [{ type: "unaryFunc", content: command, args: [arg1] }, newPos];
1625
+ return [new TexNode("unaryFunc", command, [arg1]), newPos];
1559
1626
  }
1560
1627
  case 2: {
1561
1628
  const [arg1, pos1] = this.parseNextExprWithoutSupSub(tokens, pos);
1562
1629
  const [arg2, pos2] = this.parseNextExprWithoutSupSub(tokens, pos1);
1563
- return [{ type: "binaryFunc", content: command, args: [arg1, arg2] }, pos2];
1630
+ return [new TexNode("binaryFunc", command, [arg1, arg2]), pos2];
1564
1631
  }
1565
1632
  default:
1566
1633
  throw new Error("Invalid number of parameters");
@@ -1597,11 +1664,11 @@ class LatexParser {
1597
1664
  const exprInside = tokens.slice(exprInsideStart, exprInsideEnd);
1598
1665
  const body = this.parse(exprInside);
1599
1666
  const args = [
1600
- { type: "element", content: leftDelimiter.value },
1667
+ new TexNode("element", leftDelimiter.value),
1601
1668
  body,
1602
- { type: "element", content: rightDelimiter.value }
1669
+ new TexNode("element", rightDelimiter.value)
1603
1670
  ];
1604
- const res = { type: "leftright", content: "", args };
1671
+ const res = new TexNode("leftright", "", args);
1605
1672
  return [res, pos];
1606
1673
  }
1607
1674
  parseBeginEndExpr(tokens, start) {
@@ -1628,11 +1695,11 @@ class LatexParser {
1628
1695
  }
1629
1696
  pos += 3;
1630
1697
  const exprInside = tokens.slice(exprInsideStart, exprInsideEnd);
1631
- while (exprInside.length > 0 && [4 /* WHITESPACE */, 5 /* NEWLINE */].includes(exprInside[exprInside.length - 1].type)) {
1698
+ while (exprInside.length > 0 && [4 /* SPACE */, 5 /* NEWLINE */].includes(exprInside[exprInside.length - 1].type)) {
1632
1699
  exprInside.pop();
1633
1700
  }
1634
1701
  const body = this.parseAligned(exprInside);
1635
- const res = { type: "beginend", content: envName, data: body };
1702
+ const res = new TexNode("beginend", envName, [], body);
1636
1703
  return [res, pos];
1637
1704
  }
1638
1705
  parseAligned(tokens) {
@@ -1640,22 +1707,26 @@ class LatexParser {
1640
1707
  const allRows = [];
1641
1708
  let row = [];
1642
1709
  allRows.push(row);
1643
- let group = { type: "ordgroup", content: "", args: [] };
1710
+ let group = new TexNode("ordgroup", "", []);
1644
1711
  row.push(group);
1645
1712
  while (pos < tokens.length) {
1646
1713
  const [res, newPos] = this.parseNextExpr(tokens, pos);
1647
1714
  pos = newPos;
1648
1715
  if (res.type === "whitespace") {
1649
- continue;
1650
- } else if (res.type === "newline" && !this.newline_sensitive) {
1651
- continue;
1652
- } else if (res.type === "control" && res.content === "\\\\") {
1716
+ if (!this.space_sensitive && res.content.replace(/ /g, "").length === 0) {
1717
+ continue;
1718
+ }
1719
+ if (!this.newline_sensitive && res.content === "\n") {
1720
+ continue;
1721
+ }
1722
+ }
1723
+ if (res.type === "control" && res.content === "\\\\") {
1653
1724
  row = [];
1654
- group = { type: "ordgroup", content: "", args: [] };
1725
+ group = new TexNode("ordgroup", "", []);
1655
1726
  row.push(group);
1656
1727
  allRows.push(row);
1657
1728
  } else if (res.type === "control" && res.content === "&") {
1658
- group = { type: "ordgroup", content: "", args: [] };
1729
+ group = new TexNode("ordgroup", "", []);
1659
1730
  row.push(group);
1660
1731
  } else {
1661
1732
  group.args.push(res);
@@ -1669,87 +1740,62 @@ class LatexParser {
1669
1740
  function is_delimiter(c) {
1670
1741
  return c.type === "atom" && ["(", ")", "[", "]", "{", "}", "|", "\u230A", "\u230B", "\u2308", "\u2309"].includes(c.content);
1671
1742
  }
1672
- function text_node_shallow_eq(a, b) {
1673
- return a.type === b.type && a.content === b.content;
1674
- }
1675
1743
  function convert_overset(node) {
1676
1744
  const [sup, base] = node.args;
1677
1745
  const is_def = (n) => {
1678
- if (n.type === "text" && n.content === "def") {
1746
+ if (n.eq_shallow(new TexNode("text", "def"))) {
1679
1747
  return true;
1680
1748
  }
1681
1749
  if (n.type === "ordgroup" && n.args.length === 3) {
1682
1750
  const [a1, a2, a3] = n.args;
1683
- const d = { type: "element", content: "d" };
1684
- const e = { type: "element", content: "e" };
1685
- const f = { type: "element", content: "f" };
1686
- if (text_node_shallow_eq(a1, d) && text_node_shallow_eq(a2, e) && text_node_shallow_eq(a3, f)) {
1751
+ const d = new TexNode("element", "d");
1752
+ const e = new TexNode("element", "e");
1753
+ const f = new TexNode("element", "f");
1754
+ if (a1.eq_shallow(d) && a2.eq_shallow(e) && a3.eq_shallow(f)) {
1687
1755
  return true;
1688
1756
  }
1689
1757
  }
1690
1758
  return false;
1691
1759
  };
1692
- const is_eq = (n) => n.type === "element" && n.content === "=";
1760
+ const is_eq = (n) => n.eq_shallow(new TexNode("element", "="));
1693
1761
  if (is_def(sup) && is_eq(base)) {
1694
- return {
1695
- type: "symbol",
1696
- content: "eq.def"
1697
- };
1762
+ return new TypstNode("symbol", "eq.def");
1698
1763
  }
1699
- const op_call = {
1700
- type: "unaryFunc",
1701
- content: "op",
1702
- args: [convertTree(base)],
1703
- options: { limits: "#true" }
1704
- };
1705
- return {
1706
- type: "supsub",
1707
- content: "",
1708
- data: {
1709
- base: op_call,
1710
- sup: convertTree(sup)
1711
- }
1712
- };
1764
+ const op_call = new TypstNode("unaryFunc", "op", [convertTree(base)]);
1765
+ op_call.setOptions({ limits: "#true" });
1766
+ return new TypstNode("supsub", "", [], {
1767
+ base: op_call,
1768
+ sup: convertTree(sup)
1769
+ });
1713
1770
  }
1714
1771
  function convertTree(node) {
1715
1772
  switch (node.type) {
1716
1773
  case "empty":
1774
+ return new TypstNode("empty", "");
1717
1775
  case "whitespace":
1718
- return { type: "empty", content: "" };
1776
+ return new TypstNode("whitespace", node.content);
1719
1777
  case "ordgroup":
1720
- return {
1721
- type: "group",
1722
- content: "",
1723
- args: node.args.map(convertTree)
1724
- };
1778
+ return new TypstNode("group", "", node.args.map(convertTree));
1725
1779
  case "element":
1726
- return { type: "atom", content: convertToken(node.content) };
1780
+ return new TypstNode("atom", convertToken(node.content));
1727
1781
  case "symbol":
1728
- return { type: "symbol", content: convertToken(node.content) };
1782
+ return new TypstNode("symbol", convertToken(node.content));
1729
1783
  case "text":
1730
- return { type: "text", content: node.content };
1784
+ return new TypstNode("text", node.content);
1731
1785
  case "comment":
1732
- return { type: "comment", content: node.content };
1786
+ return new TypstNode("comment", node.content);
1733
1787
  case "supsub": {
1734
1788
  let { base, sup, sub } = node.data;
1735
1789
  if (base && base.type === "unaryFunc" && base.content === "\\overbrace" && sup) {
1736
- return {
1737
- type: "binaryFunc",
1738
- content: "overbrace",
1739
- args: [convertTree(base.args[0]), convertTree(sup)]
1740
- };
1790
+ return new TypstNode("binaryFunc", "overbrace", [convertTree(base.args[0]), convertTree(sup)]);
1741
1791
  } else if (base && base.type === "unaryFunc" && base.content === "\\underbrace" && sub) {
1742
- return {
1743
- type: "binaryFunc",
1744
- content: "underbrace",
1745
- args: [convertTree(base.args[0]), convertTree(sub)]
1746
- };
1792
+ return new TypstNode("binaryFunc", "underbrace", [convertTree(base.args[0]), convertTree(sub)]);
1747
1793
  }
1748
1794
  const data = {
1749
1795
  base: convertTree(base)
1750
1796
  };
1751
1797
  if (data.base.type === "empty") {
1752
- data.base = { type: "text", content: "" };
1798
+ data.base = new TypstNode("text", "");
1753
1799
  }
1754
1800
  if (sup) {
1755
1801
  data.sup = convertTree(sup);
@@ -1757,19 +1803,11 @@ function convertTree(node) {
1757
1803
  if (sub) {
1758
1804
  data.sub = convertTree(sub);
1759
1805
  }
1760
- return {
1761
- type: "supsub",
1762
- content: "",
1763
- data
1764
- };
1806
+ return new TypstNode("supsub", "", [], data);
1765
1807
  }
1766
1808
  case "leftright": {
1767
1809
  const [left, body, right] = node.args;
1768
- const group = {
1769
- type: "group",
1770
- content: "",
1771
- args: node.args.map(convertTree)
1772
- };
1810
+ const group = new TypstNode("group", "", node.args.map(convertTree));
1773
1811
  if ([
1774
1812
  "[]",
1775
1813
  "()",
@@ -1780,49 +1818,26 @@ function convertTree(node) {
1780
1818
  ].includes(left.content + right.content)) {
1781
1819
  return group;
1782
1820
  }
1783
- return {
1784
- type: "unaryFunc",
1785
- content: "lr",
1786
- args: [group]
1787
- };
1821
+ return new TypstNode("unaryFunc", "lr", [group]);
1788
1822
  }
1789
1823
  case "binaryFunc": {
1790
1824
  if (node.content === "\\overset") {
1791
1825
  return convert_overset(node);
1792
1826
  }
1793
- return {
1794
- type: "binaryFunc",
1795
- content: convertToken(node.content),
1796
- args: node.args.map(convertTree)
1797
- };
1827
+ return new TypstNode("binaryFunc", convertToken(node.content), node.args.map(convertTree));
1798
1828
  }
1799
1829
  case "unaryFunc": {
1800
1830
  const arg0 = convertTree(node.args[0]);
1801
1831
  if (node.content === "\\sqrt" && node.data) {
1802
1832
  const data = convertTree(node.data);
1803
- return {
1804
- type: "binaryFunc",
1805
- content: "root",
1806
- args: [data, arg0]
1807
- };
1833
+ return new TypstNode("binaryFunc", "root", [data, arg0]);
1808
1834
  }
1809
1835
  if (node.content === "\\mathbf") {
1810
- const inner = {
1811
- type: "unaryFunc",
1812
- content: "bold",
1813
- args: [arg0]
1814
- };
1815
- return {
1816
- type: "unaryFunc",
1817
- content: "upright",
1818
- args: [inner]
1819
- };
1836
+ const inner = new TypstNode("unaryFunc", "bold", [arg0]);
1837
+ return new TypstNode("unaryFunc", "upright", [inner]);
1820
1838
  }
1821
1839
  if (node.content === "\\mathbb" && arg0.type === "atom" && /^[A-Z]$/.test(arg0.content)) {
1822
- return {
1823
- type: "symbol",
1824
- content: arg0.content + arg0.content
1825
- };
1840
+ return new TypstNode("symbol", arg0.content + arg0.content);
1826
1841
  }
1827
1842
  if (node.content === "\\operatorname") {
1828
1843
  const body = node.args;
@@ -1831,50 +1846,31 @@ function convertTree(node) {
1831
1846
  }
1832
1847
  const text = body[0].content;
1833
1848
  if (TYPST_INTRINSIC_SYMBOLS.includes(text)) {
1834
- return {
1835
- type: "symbol",
1836
- content: text
1837
- };
1849
+ return new TypstNode("symbol", text);
1838
1850
  } else {
1839
- return {
1840
- type: "unaryFunc",
1841
- content: "op",
1842
- args: [{ type: "text", content: text }]
1843
- };
1851
+ return new TypstNode("unaryFunc", "op", [new TypstNode("text", text)]);
1844
1852
  }
1845
1853
  }
1846
- return {
1847
- type: "unaryFunc",
1848
- content: convertToken(node.content),
1849
- args: node.args.map(convertTree)
1850
- };
1854
+ return new TypstNode("unaryFunc", convertToken(node.content), node.args.map(convertTree));
1851
1855
  }
1852
- case "newline":
1853
- return { type: "newline", content: "\n" };
1854
1856
  case "beginend": {
1855
1857
  const matrix = node.data;
1856
1858
  const data = matrix.map((row) => row.map(convertTree));
1857
1859
  if (node.content.startsWith("align")) {
1858
- return {
1859
- type: "align",
1860
- content: "",
1861
- data
1862
- };
1860
+ return new TypstNode("align", "", [], data);
1863
1861
  } else {
1864
- return {
1865
- type: "matrix",
1866
- content: "mat",
1867
- data
1868
- };
1862
+ const res = new TypstNode("matrix", "", [], data);
1863
+ res.setOptions({ delim: "#none" });
1864
+ return res;
1869
1865
  }
1870
1866
  }
1871
1867
  case "unknownMacro":
1872
- return { type: "unknown", content: convertToken(node.content) };
1868
+ return new TypstNode("unknown", convertToken(node.content));
1873
1869
  case "control":
1874
1870
  if (node.content === "\\\\") {
1875
- return { type: "symbol", content: "\\" };
1871
+ return new TypstNode("symbol", "\\");
1876
1872
  } else if (node.content === "\\,") {
1877
- return { type: "symbol", content: "thin" };
1873
+ return new TypstNode("symbol", "thin");
1878
1874
  } else {
1879
1875
  throw new TypstWriterError(`Unknown control sequence: ${node.content}`, node);
1880
1876
  }
@@ -1889,6 +1885,8 @@ function convertToken(token) {
1889
1885
  return "\\/";
1890
1886
  } else if (token === "\\|") {
1891
1887
  return "parallel";
1888
+ } else if (token === "\\colon") {
1889
+ return ":";
1892
1890
  } else if (token === "\\\\") {
1893
1891
  return "\\";
1894
1892
  } else if (["\\$", "\\#", "\\&", "\\_"].includes(token)) {
@@ -1912,6 +1910,10 @@ var TYPST_INTRINSIC_SYMBOLS = [
1912
1910
  "sech",
1913
1911
  "csch"
1914
1912
  ];
1913
+ var TYPST_LEFT_PARENTHESIS = new TypstToken(1 /* ATOM */, "(");
1914
+ var TYPST_RIGHT_PARENTHESIS = new TypstToken(1 /* ATOM */, ")");
1915
+ var TYPST_COMMA = new TypstToken(1 /* ATOM */, ",");
1916
+ var TYPST_NEWLINE = new TypstToken(0 /* SYMBOL */, "\n");
1915
1917
 
1916
1918
  class TypstWriterError extends Error {
1917
1919
  node;
@@ -1925,57 +1927,72 @@ class TypstWriterError extends Error {
1925
1927
  class TypstWriter {
1926
1928
  nonStrict;
1927
1929
  preferTypstIntrinsic;
1930
+ keepSpaces;
1928
1931
  buffer = "";
1929
1932
  queue = [];
1930
- needSpaceAfterSingleItemScript = false;
1931
1933
  insideFunctionDepth = 0;
1932
- constructor(nonStrict, preferTypstIntrinsic) {
1934
+ constructor(nonStrict, preferTypstIntrinsic, keepSpaces) {
1933
1935
  this.nonStrict = nonStrict;
1934
1936
  this.preferTypstIntrinsic = preferTypstIntrinsic;
1937
+ this.keepSpaces = keepSpaces;
1935
1938
  }
1936
- writeBuffer(str) {
1937
- if (this.needSpaceAfterSingleItemScript && /^[0-9a-zA-Z\(]/.test(str)) {
1938
- this.buffer += " ";
1939
- } else {
1940
- let no_need_space = false;
1941
- no_need_space ||= /[\(\|]$/.test(this.buffer) && /^\w/.test(str);
1942
- no_need_space ||= /^[}()_^,;!\|]$/.test(str);
1943
- no_need_space ||= str === "'";
1944
- no_need_space ||= /[0-9]$/.test(this.buffer) && /^[0-9]/.test(str);
1945
- no_need_space ||= /[\(\[{]\s*(-|\+)$/.test(this.buffer) || this.buffer === "-" || this.buffer === "+";
1946
- no_need_space ||= str.startsWith("\n");
1947
- no_need_space ||= this.buffer === "";
1948
- no_need_space ||= /[\s_^{\(]$/.test(this.buffer);
1949
- if (!no_need_space) {
1950
- this.buffer += " ";
1951
- }
1939
+ writeBuffer(token) {
1940
+ const str = token.content;
1941
+ if (str === "") {
1942
+ return;
1952
1943
  }
1953
- if (this.needSpaceAfterSingleItemScript) {
1954
- this.needSpaceAfterSingleItemScript = false;
1944
+ let no_need_space = false;
1945
+ no_need_space ||= /[\(\|]$/.test(this.buffer) && /^\w/.test(str);
1946
+ no_need_space ||= /^[}()_^,;!\|]$/.test(str);
1947
+ no_need_space ||= str === "'";
1948
+ no_need_space ||= /[0-9]$/.test(this.buffer) && /^[0-9]/.test(str);
1949
+ no_need_space ||= /[\(\[{]\s*(-|\+)$/.test(this.buffer) || this.buffer === "-" || this.buffer === "+";
1950
+ no_need_space ||= str.startsWith("\n");
1951
+ no_need_space ||= this.buffer === "";
1952
+ no_need_space ||= /^\s/.test(str);
1953
+ no_need_space ||= /[\s_^{\(]$/.test(this.buffer);
1954
+ if (!no_need_space) {
1955
+ this.buffer += " ";
1955
1956
  }
1956
1957
  this.buffer += str;
1957
1958
  }
1958
- append(node) {
1959
+ serialize(node) {
1959
1960
  switch (node.type) {
1960
1961
  case "empty":
1961
1962
  break;
1962
1963
  case "atom": {
1963
1964
  if (node.content === "," && this.insideFunctionDepth > 0) {
1964
- this.queue.push({ type: "symbol", content: "comma" });
1965
+ this.queue.push(new TypstToken(0 /* SYMBOL */, "comma"));
1965
1966
  } else {
1966
- this.queue.push({ type: "atom", content: node.content });
1967
+ this.queue.push(new TypstToken(1 /* ATOM */, node.content));
1967
1968
  }
1968
1969
  break;
1969
1970
  }
1970
1971
  case "symbol":
1972
+ this.queue.push(new TypstToken(0 /* SYMBOL */, node.content));
1973
+ break;
1971
1974
  case "text":
1975
+ this.queue.push(new TypstToken(2 /* TEXT */, `"${node.content}"`));
1976
+ break;
1972
1977
  case "comment":
1973
- case "newline":
1974
- this.queue.push(node);
1978
+ this.queue.push(new TypstToken(3 /* COMMENT */, `//${node.content}`));
1979
+ break;
1980
+ case "whitespace":
1981
+ for (const c of node.content) {
1982
+ if (c === " ") {
1983
+ if (this.keepSpaces) {
1984
+ this.queue.push(new TypstToken(4 /* SPACE */, c));
1985
+ }
1986
+ } else if (c === "\n") {
1987
+ this.queue.push(new TypstToken(0 /* SYMBOL */, c));
1988
+ } else {
1989
+ throw new TypstWriterError(`Unexpected whitespace character: ${c}`, node);
1990
+ }
1991
+ }
1975
1992
  break;
1976
1993
  case "group":
1977
1994
  for (const item of node.args) {
1978
- this.append(item);
1995
+ this.serialize(item);
1979
1996
  }
1980
1997
  break;
1981
1998
  case "supsub": {
@@ -1984,48 +2001,48 @@ class TypstWriter {
1984
2001
  let trailing_space_needed = false;
1985
2002
  const has_prime = sup && sup.type === "atom" && sup.content === "\'";
1986
2003
  if (has_prime) {
1987
- this.queue.push({ type: "atom", content: "\'" });
2004
+ this.queue.push(new TypstToken(1 /* ATOM */, "\'"));
1988
2005
  trailing_space_needed = false;
1989
2006
  }
1990
2007
  if (sub) {
1991
- this.queue.push({ type: "atom", content: "_" });
2008
+ this.queue.push(new TypstToken(1 /* ATOM */, "_"));
1992
2009
  trailing_space_needed = this.appendWithBracketsIfNeeded(sub);
1993
2010
  }
1994
2011
  if (sup && !has_prime) {
1995
- this.queue.push({ type: "atom", content: "^" });
2012
+ this.queue.push(new TypstToken(1 /* ATOM */, "^"));
1996
2013
  trailing_space_needed = this.appendWithBracketsIfNeeded(sup);
1997
2014
  }
1998
2015
  if (trailing_space_needed) {
1999
- this.queue.push({ type: "softSpace", content: "" });
2016
+ this.queue.push(new TypstToken(6 /* CONTROL */, " "));
2000
2017
  }
2001
2018
  break;
2002
2019
  }
2003
2020
  case "binaryFunc": {
2004
- const func_symbol = { type: "symbol", content: node.content };
2021
+ const func_symbol = new TypstToken(0 /* SYMBOL */, node.content);
2005
2022
  const [arg0, arg1] = node.args;
2006
2023
  this.queue.push(func_symbol);
2007
2024
  this.insideFunctionDepth++;
2008
- this.queue.push({ type: "atom", content: "(" });
2009
- this.append(arg0);
2010
- this.queue.push({ type: "atom", content: "," });
2011
- this.append(arg1);
2012
- this.queue.push({ type: "atom", content: ")" });
2025
+ this.queue.push(TYPST_LEFT_PARENTHESIS);
2026
+ this.serialize(arg0);
2027
+ this.queue.push(new TypstToken(1 /* ATOM */, ","));
2028
+ this.serialize(arg1);
2029
+ this.queue.push(TYPST_RIGHT_PARENTHESIS);
2013
2030
  this.insideFunctionDepth--;
2014
2031
  break;
2015
2032
  }
2016
2033
  case "unaryFunc": {
2017
- const func_symbol = { type: "symbol", content: node.content };
2034
+ const func_symbol = new TypstToken(0 /* SYMBOL */, node.content);
2018
2035
  const arg0 = node.args[0];
2019
2036
  this.queue.push(func_symbol);
2020
2037
  this.insideFunctionDepth++;
2021
- this.queue.push({ type: "atom", content: "(" });
2022
- this.append(arg0);
2038
+ this.queue.push(TYPST_LEFT_PARENTHESIS);
2039
+ this.serialize(arg0);
2023
2040
  if (node.options) {
2024
2041
  for (const [key, value] of Object.entries(node.options)) {
2025
- this.queue.push({ type: "symbol", content: `, ${key}: ${value}` });
2042
+ this.queue.push(new TypstToken(0 /* SYMBOL */, `, ${key}: ${value}`));
2026
2043
  }
2027
2044
  }
2028
- this.queue.push({ type: "atom", content: ")" });
2045
+ this.queue.push(TYPST_RIGHT_PARENTHESIS);
2029
2046
  this.insideFunctionDepth--;
2030
2047
  break;
2031
2048
  }
@@ -2034,41 +2051,45 @@ class TypstWriter {
2034
2051
  matrix.forEach((row, i) => {
2035
2052
  row.forEach((cell, j) => {
2036
2053
  if (j > 0) {
2037
- this.queue.push({ type: "atom", content: "&" });
2054
+ this.queue.push(new TypstToken(1 /* ATOM */, "&"));
2038
2055
  }
2039
- this.append(cell);
2056
+ this.serialize(cell);
2040
2057
  });
2041
2058
  if (i < matrix.length - 1) {
2042
- this.queue.push({ type: "symbol", content: "\\" });
2059
+ this.queue.push(new TypstToken(0 /* SYMBOL */, "\\"));
2043
2060
  }
2044
2061
  });
2045
2062
  break;
2046
2063
  }
2047
2064
  case "matrix": {
2048
2065
  const matrix = node.data;
2049
- this.queue.push({ type: "symbol", content: "mat" });
2066
+ this.queue.push(new TypstToken(0 /* SYMBOL */, "mat"));
2050
2067
  this.insideFunctionDepth++;
2051
- this.queue.push({ type: "atom", content: "(" });
2052
- this.queue.push({ type: "symbol", content: "delim: #none, " });
2068
+ this.queue.push(TYPST_LEFT_PARENTHESIS);
2069
+ if (node.options) {
2070
+ for (const [key, value] of Object.entries(node.options)) {
2071
+ this.queue.push(new TypstToken(0 /* SYMBOL */, `${key}: ${value}, `));
2072
+ }
2073
+ }
2053
2074
  matrix.forEach((row, i) => {
2054
2075
  row.forEach((cell, j) => {
2055
- this.append(cell);
2076
+ this.serialize(cell);
2056
2077
  if (j < row.length - 1) {
2057
- this.queue.push({ type: "atom", content: "," });
2078
+ this.queue.push(new TypstToken(1 /* ATOM */, ","));
2058
2079
  } else {
2059
2080
  if (i < matrix.length - 1) {
2060
- this.queue.push({ type: "atom", content: ";" });
2081
+ this.queue.push(new TypstToken(1 /* ATOM */, ";"));
2061
2082
  }
2062
2083
  }
2063
2084
  });
2064
2085
  });
2065
- this.queue.push({ type: "atom", content: ")" });
2086
+ this.queue.push(TYPST_RIGHT_PARENTHESIS);
2066
2087
  this.insideFunctionDepth--;
2067
2088
  break;
2068
2089
  }
2069
2090
  case "unknown": {
2070
2091
  if (this.nonStrict) {
2071
- this.queue.push({ type: "symbol", content: node.content });
2092
+ this.queue.push(new TypstToken(0 /* SYMBOL */, node.content));
2072
2093
  } else {
2073
2094
  throw new TypstWriterError(`Unknown macro: ${node.content}`, node);
2074
2095
  }
@@ -2088,41 +2109,28 @@ class TypstWriter {
2088
2109
  }
2089
2110
  }
2090
2111
  if (need_to_wrap) {
2091
- this.queue.push({ type: "atom", content: "(" });
2092
- this.append(node);
2093
- this.queue.push({ type: "atom", content: ")" });
2112
+ this.queue.push(TYPST_LEFT_PARENTHESIS);
2113
+ this.serialize(node);
2114
+ this.queue.push(TYPST_RIGHT_PARENTHESIS);
2094
2115
  } else {
2095
- this.append(node);
2116
+ this.serialize(node);
2096
2117
  }
2097
2118
  return !need_to_wrap;
2098
2119
  }
2099
2120
  flushQueue() {
2100
- this.queue.forEach((node) => {
2101
- let str = "";
2102
- switch (node.type) {
2103
- case "atom":
2104
- case "symbol":
2105
- str = node.content;
2106
- break;
2107
- case "text":
2108
- str = `"${node.content}"`;
2109
- break;
2110
- case "softSpace":
2111
- this.needSpaceAfterSingleItemScript = true;
2112
- str = "";
2113
- break;
2114
- case "comment":
2115
- str = `//${node.content}`;
2116
- break;
2117
- case "newline":
2118
- str = "\n";
2119
- break;
2120
- default:
2121
- throw new TypstWriterError(`Unexpected node type to stringify: ${node.type}`, node);
2122
- }
2123
- if (str !== "") {
2124
- this.writeBuffer(str);
2121
+ const SOFT_SPACE = new TypstToken(6 /* CONTROL */, " ");
2122
+ for (let i = 0;i < this.queue.length; i++) {
2123
+ let token = this.queue[i];
2124
+ if (token.eq(SOFT_SPACE)) {
2125
+ if (i === this.queue.length - 1) {
2126
+ this.queue[i].content = "";
2127
+ } else if (this.queue[i + 1].isOneOf([TYPST_RIGHT_PARENTHESIS, TYPST_COMMA, TYPST_NEWLINE])) {
2128
+ this.queue[i].content = "";
2129
+ }
2125
2130
  }
2131
+ }
2132
+ this.queue.forEach((token) => {
2133
+ this.writeBuffer(token);
2126
2134
  });
2127
2135
  this.queue = [];
2128
2136
  }
@@ -2156,6 +2164,7 @@ function tex2typst(tex, options) {
2156
2164
  const opt = {
2157
2165
  nonStrict: true,
2158
2166
  preferTypstIntrinsic: true,
2167
+ keepSpaces: false,
2159
2168
  customTexMacros: {}
2160
2169
  };
2161
2170
  if (options) {
@@ -2171,8 +2180,8 @@ function tex2typst(tex, options) {
2171
2180
  }
2172
2181
  const texTree = parseTex(tex, opt.customTexMacros);
2173
2182
  const typstTree = convertTree(texTree);
2174
- const writer2 = new TypstWriter(opt.nonStrict, opt.preferTypstIntrinsic);
2175
- writer2.append(typstTree);
2183
+ const writer2 = new TypstWriter(opt.nonStrict, opt.preferTypstIntrinsic, opt.keepSpaces);
2184
+ writer2.serialize(typstTree);
2176
2185
  return writer2.finalize();
2177
2186
  }
2178
2187
  export {