tex2typst 0.5.2 → 0.5.4

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
@@ -570,13 +570,21 @@ var TEX_UNARY_COMMANDS = [
570
570
  "overrightarrow",
571
571
  "hspace",
572
572
  "substack",
573
- "set",
574
573
  "displaylines",
575
574
  "mathinner",
576
575
  "mathrel",
577
576
  "mathbin",
578
577
  "mathop",
579
- "not"
578
+ "not",
579
+ // the braket package
580
+ "bra",
581
+ "ket",
582
+ "braket",
583
+ "set",
584
+ "Bra",
585
+ "Ket",
586
+ "Braket",
587
+ "Set"
580
588
  ];
581
589
  var TEX_BINARY_COMMANDS = [
582
590
  "frac",
@@ -1225,21 +1233,27 @@ var TypstToken = class _TypstToken {
1225
1233
  static EMPTY = new _TypstToken(2 /* ELEMENT */, "");
1226
1234
  static LEFT_BRACE = new _TypstToken(2 /* ELEMENT */, "{");
1227
1235
  static RIGHT_BRACE = new _TypstToken(2 /* ELEMENT */, "}");
1236
+ static LEFT_ANGLE = new _TypstToken(1 /* SYMBOL */, "chevron.l");
1237
+ static RIGHT_ANGLE = new _TypstToken(1 /* SYMBOL */, "chevron.r");
1238
+ static VERTICAL_BAR = new _TypstToken(2 /* ELEMENT */, "|");
1239
+ static PLUS = new _TypstToken(2 /* ELEMENT */, "+");
1240
+ static MINUS = new _TypstToken(2 /* ELEMENT */, "-");
1241
+ static LR = new _TypstToken(1 /* SYMBOL */, "lr");
1228
1242
  static LEFT_DELIMITERS = [
1229
1243
  new _TypstToken(2 /* ELEMENT */, "("),
1230
1244
  new _TypstToken(2 /* ELEMENT */, "["),
1231
- new _TypstToken(2 /* ELEMENT */, "{"),
1232
- new _TypstToken(2 /* ELEMENT */, "|"),
1233
- new _TypstToken(1 /* SYMBOL */, "chevron.l"),
1245
+ _TypstToken.LEFT_BRACE,
1246
+ _TypstToken.VERTICAL_BAR,
1247
+ _TypstToken.LEFT_ANGLE,
1234
1248
  new _TypstToken(1 /* SYMBOL */, "paren.l"),
1235
1249
  new _TypstToken(1 /* SYMBOL */, "brace.l")
1236
1250
  ];
1237
1251
  static RIGHT_DELIMITERS = [
1238
1252
  new _TypstToken(2 /* ELEMENT */, ")"),
1239
1253
  new _TypstToken(2 /* ELEMENT */, "]"),
1240
- new _TypstToken(2 /* ELEMENT */, "}"),
1241
- new _TypstToken(2 /* ELEMENT */, "|"),
1242
- new _TypstToken(1 /* SYMBOL */, "chevron.r"),
1254
+ _TypstToken.RIGHT_BRACE,
1255
+ _TypstToken.VERTICAL_BAR,
1256
+ _TypstToken.RIGHT_ANGLE,
1243
1257
  new _TypstToken(1 /* SYMBOL */, "paren.r"),
1244
1258
  new _TypstToken(1 /* SYMBOL */, "brace.r")
1245
1259
  ];
@@ -1280,6 +1294,39 @@ var TypstTerminal = class extends TypstNode {
1280
1294
  isOverHigh() {
1281
1295
  return false;
1282
1296
  }
1297
+ isLeftSpaceful() {
1298
+ switch (this.head.type) {
1299
+ case 6 /* SPACE */:
1300
+ case 8 /* NEWLINE */:
1301
+ return false;
1302
+ case 4 /* TEXT */:
1303
+ return true;
1304
+ case 1 /* SYMBOL */:
1305
+ case 2 /* ELEMENT */: {
1306
+ if (["(", "!", "}", "]"].includes(this.head.value)) {
1307
+ return false;
1308
+ }
1309
+ return true;
1310
+ }
1311
+ default:
1312
+ return true;
1313
+ }
1314
+ }
1315
+ isRightSpaceful() {
1316
+ switch (this.head.type) {
1317
+ case 6 /* SPACE */:
1318
+ case 8 /* NEWLINE */:
1319
+ return false;
1320
+ case 4 /* TEXT */:
1321
+ return true;
1322
+ case 1 /* SYMBOL */:
1323
+ case 2 /* ELEMENT */: {
1324
+ return ["+", "=", ",", "\\/", "dot", "dot.op", "arrow", "arrow.r"].includes(this.head.value);
1325
+ }
1326
+ default:
1327
+ return false;
1328
+ }
1329
+ }
1283
1330
  toString() {
1284
1331
  return this.head.toString();
1285
1332
  }
@@ -1326,13 +1373,48 @@ var TypstGroup = class extends TypstNode {
1326
1373
  isOverHigh() {
1327
1374
  return this.items.some((n) => n.isOverHigh());
1328
1375
  }
1376
+ isLeftSpaceful() {
1377
+ if (this.items.length === 0) {
1378
+ return false;
1379
+ }
1380
+ return this.items[0].isLeftSpaceful();
1381
+ }
1382
+ isRightSpaceful() {
1383
+ if (this.items.length === 0) {
1384
+ return false;
1385
+ }
1386
+ return this.items.at(-1).isRightSpaceful();
1387
+ }
1329
1388
  serialize(env, options) {
1330
- const queue = this.items.flatMap((n) => n.serialize(env, options));
1331
- if (queue.length > 0 && queue[0].eq(SOFT_SPACE)) {
1332
- queue.shift();
1389
+ if (this.items.length === 0) {
1390
+ return [];
1391
+ }
1392
+ const queue = [];
1393
+ for (let i = 0; i < this.items.length; i++) {
1394
+ const n = this.items[i];
1395
+ const tokens = n.serialize(env, options);
1396
+ if (n.isLeftSpaceful() && i > 0) {
1397
+ if (queue.length > 0) {
1398
+ const top = queue.at(-1);
1399
+ let no_need_space = false;
1400
+ no_need_space ||= top.eq(SOFT_SPACE);
1401
+ no_need_space ||= ["{", "["].includes(top.value);
1402
+ if (!no_need_space) {
1403
+ queue.push(SOFT_SPACE);
1404
+ }
1405
+ }
1406
+ }
1407
+ queue.push(...tokens);
1408
+ if (n.isRightSpaceful() && i < this.items.length - 1) {
1409
+ if (!queue.at(-1)?.eq(SOFT_SPACE)) {
1410
+ queue.push(SOFT_SPACE);
1411
+ }
1412
+ }
1333
1413
  }
1334
- if (queue.length > 0 && queue[queue.length - 1].eq(SOFT_SPACE)) {
1335
- queue.pop();
1414
+ if (queue.length > 0 && (queue[0].eq(TypstToken.MINUS) || queue[0].eq(TypstToken.PLUS))) {
1415
+ while (queue.length > 1 && queue[1].eq(SOFT_SPACE)) {
1416
+ queue.splice(1, 1);
1417
+ }
1336
1418
  }
1337
1419
  return queue;
1338
1420
  }
@@ -1350,6 +1432,12 @@ var TypstSupsub = class extends TypstNode {
1350
1432
  isOverHigh() {
1351
1433
  return this.base.isOverHigh();
1352
1434
  }
1435
+ isLeftSpaceful() {
1436
+ return true;
1437
+ }
1438
+ isRightSpaceful() {
1439
+ return true;
1440
+ }
1353
1441
  serialize(env, options) {
1354
1442
  const queue = [];
1355
1443
  let { base, sup, sub } = this;
@@ -1366,7 +1454,6 @@ var TypstSupsub = class extends TypstNode {
1366
1454
  queue.push(new TypstToken(2 /* ELEMENT */, "^"));
1367
1455
  queue.push(...sup.serialize(env, options));
1368
1456
  }
1369
- queue.push(SOFT_SPACE);
1370
1457
  return queue;
1371
1458
  }
1372
1459
  };
@@ -1382,6 +1469,12 @@ var TypstFuncCall = class extends TypstNode {
1382
1469
  }
1383
1470
  return this.args.some((n) => n.isOverHigh());
1384
1471
  }
1472
+ isLeftSpaceful() {
1473
+ return true;
1474
+ }
1475
+ isRightSpaceful() {
1476
+ return !["op", "bold", "dot"].includes(this.head.value);
1477
+ }
1385
1478
  serialize(env, options) {
1386
1479
  const queue = [];
1387
1480
  const func_symbol = this.head;
@@ -1392,6 +1485,7 @@ var TypstFuncCall = class extends TypstNode {
1392
1485
  queue.push(...this.args[i].serialize(env, options));
1393
1486
  if (i < this.args.length - 1) {
1394
1487
  queue.push(new TypstToken(2 /* ELEMENT */, ","));
1488
+ queue.push(SOFT_SPACE);
1395
1489
  }
1396
1490
  }
1397
1491
  if (this.options) {
@@ -1413,14 +1507,18 @@ var TypstFraction = class extends TypstNode {
1413
1507
  isOverHigh() {
1414
1508
  return true;
1415
1509
  }
1510
+ isLeftSpaceful() {
1511
+ return true;
1512
+ }
1513
+ isRightSpaceful() {
1514
+ return true;
1515
+ }
1416
1516
  serialize(env, options) {
1417
1517
  const queue = [];
1418
1518
  const [numerator, denominator] = this.args;
1419
- queue.push(SOFT_SPACE);
1420
1519
  queue.push(...numerator.serialize(env, options));
1421
1520
  queue.push(new TypstToken(2 /* ELEMENT */, "/"));
1422
1521
  queue.push(...denominator.serialize(env, options));
1423
- queue.push(SOFT_SPACE);
1424
1522
  return queue;
1425
1523
  }
1426
1524
  };
@@ -1440,6 +1538,12 @@ var TypstLeftright = class extends TypstNode {
1440
1538
  isOverHigh() {
1441
1539
  return this.body.isOverHigh();
1442
1540
  }
1541
+ isLeftSpaceful() {
1542
+ return true;
1543
+ }
1544
+ isRightSpaceful() {
1545
+ return true;
1546
+ }
1443
1547
  serialize(env, options) {
1444
1548
  const queue = [];
1445
1549
  const LR = new TypstToken(1 /* SYMBOL */, "lr");
@@ -1450,9 +1554,15 @@ var TypstLeftright = class extends TypstNode {
1450
1554
  }
1451
1555
  if (left) {
1452
1556
  queue.push(left);
1557
+ if (isalpha(left.value[0])) {
1558
+ queue.push(SOFT_SPACE);
1559
+ }
1453
1560
  }
1454
1561
  queue.push(...this.body.serialize(env, options));
1455
1562
  if (right) {
1563
+ if (isalpha(right.value[0])) {
1564
+ queue.push(SOFT_SPACE);
1565
+ }
1456
1566
  queue.push(right);
1457
1567
  }
1458
1568
  if (this.head.eq(LR)) {
@@ -1471,6 +1581,12 @@ var TypstMatrixLike = class _TypstMatrixLike extends TypstNode {
1471
1581
  isOverHigh() {
1472
1582
  return true;
1473
1583
  }
1584
+ isLeftSpaceful() {
1585
+ return true;
1586
+ }
1587
+ isRightSpaceful() {
1588
+ return false;
1589
+ }
1474
1590
  serialize(env, options) {
1475
1591
  const queue = [];
1476
1592
  let cell_sep;
@@ -1499,10 +1615,16 @@ var TypstMatrixLike = class _TypstMatrixLike extends TypstNode {
1499
1615
  row.forEach((cell, j) => {
1500
1616
  queue.push(...cell.serialize(env, options));
1501
1617
  if (j < row.length - 1) {
1618
+ queue.push(SOFT_SPACE);
1502
1619
  queue.push(cell_sep);
1620
+ queue.push(SOFT_SPACE);
1503
1621
  } else {
1504
1622
  if (i < this.matrix.length - 1) {
1623
+ if (row_sep.value === "\\") {
1624
+ queue.push(SOFT_SPACE);
1625
+ }
1505
1626
  queue.push(row_sep);
1627
+ queue.push(SOFT_SPACE);
1506
1628
  }
1507
1629
  }
1508
1630
  });
@@ -1532,6 +1654,12 @@ var TypstMarkupFunc = class extends TypstNode {
1532
1654
  isOverHigh() {
1533
1655
  return this.fragments.some((n) => n.isOverHigh());
1534
1656
  }
1657
+ isLeftSpaceful() {
1658
+ return true;
1659
+ }
1660
+ isRightSpaceful() {
1661
+ return true;
1662
+ }
1535
1663
  serialize(env, options) {
1536
1664
  const queue = [];
1537
1665
  queue.push(this.head);
@@ -1572,41 +1700,15 @@ var TypstWriter = class {
1572
1700
  constructor(options) {
1573
1701
  this.options = options;
1574
1702
  }
1575
- writeBuffer(previousToken, token) {
1576
- const str = token.toString();
1577
- if (str === "") {
1578
- return;
1579
- }
1580
- let no_need_space = false;
1581
- no_need_space ||= /[\(\[\|]$/.test(this.buffer) && /^\w/.test(str);
1582
- no_need_space ||= /^[})\]\|]$/.test(str);
1583
- no_need_space ||= /[^=]$/.test(this.buffer) && str === "(";
1584
- no_need_space ||= /^[_^,;!]$/.test(str);
1585
- no_need_space ||= str === "'";
1586
- no_need_space ||= /[\(\[{]\s*(-|\+)$/.test(this.buffer) || this.buffer === "-" || this.buffer === "+";
1587
- no_need_space ||= str.startsWith("\n");
1588
- no_need_space ||= this.buffer === "";
1589
- no_need_space ||= /\s$/.test(this.buffer) || /^\s/.test(str);
1590
- no_need_space ||= this.buffer.endsWith("&") && str === "=";
1591
- no_need_space ||= this.buffer.endsWith("/") || str === "/";
1592
- no_need_space ||= token.type === 3 /* LITERAL */;
1593
- no_need_space ||= /[\s_^{\(]$/.test(this.buffer);
1594
- if (previousToken !== null) {
1595
- no_need_space ||= previousToken.type === 3 /* LITERAL */;
1596
- }
1597
- if (!no_need_space) {
1598
- this.buffer += " ";
1599
- }
1600
- this.buffer += str;
1601
- }
1602
1703
  // Serialize a tree of TypstNode into a list of TypstToken
1603
1704
  serialize(abstractNode) {
1604
1705
  const env = { insideFunctionDepth: 0 };
1605
1706
  this.queue.push(...abstractNode.serialize(env, this.options));
1606
1707
  }
1607
1708
  flushQueue() {
1709
+ const queue1 = this.queue.filter((token) => token.value !== "");
1608
1710
  let qu = [];
1609
- for (const token of this.queue) {
1711
+ for (const token of queue1) {
1610
1712
  if (token.eq(SOFT_SPACE2) && qu.length > 0 && qu[qu.length - 1].eq(SOFT_SPACE2)) {
1611
1713
  continue;
1612
1714
  }
@@ -1625,8 +1727,7 @@ var TypstWriter = class {
1625
1727
  qu = qu.filter((token) => !token.eq(dummy_token));
1626
1728
  for (let i = 0; i < qu.length; i++) {
1627
1729
  let token = qu[i];
1628
- let previous_token = i === 0 ? null : qu[i - 1];
1629
- this.writeBuffer(previous_token, token);
1730
+ this.buffer += token.toString();
1630
1731
  }
1631
1732
  this.queue = [];
1632
1733
  }
@@ -1653,6 +1754,7 @@ var TypstWriter = class {
1653
1754
  this.buffer = pass(this.buffer);
1654
1755
  }
1655
1756
  }
1757
+ this.buffer = this.buffer.replace(/& =/g, "&=");
1656
1758
  return this.buffer;
1657
1759
  }
1658
1760
  };
@@ -3041,7 +3143,7 @@ function convert_tex_node_to_typst(abstractNode, options) {
3041
3143
  typ_left = escape_curly_or_paren(typ_left);
3042
3144
  }
3043
3145
  return new TypstLeftright(
3044
- new TypstToken(1 /* SYMBOL */, "lr"),
3146
+ TypstToken.LR,
3045
3147
  { body: typ_body, left: typ_left, right: typ_right }
3046
3148
  );
3047
3149
  }
@@ -3124,12 +3226,6 @@ function convert_tex_node_to_typst(abstractNode, options) {
3124
3226
  [new TypstToken(4 /* TEXT */, "large").toNode(), arg0]
3125
3227
  );
3126
3228
  }
3127
- if (node2.head.value === "\\set") {
3128
- return new TypstLeftright(
3129
- null,
3130
- { body: arg0, left: TypstToken.LEFT_BRACE, right: TypstToken.RIGHT_BRACE }
3131
- );
3132
- }
3133
3229
  if (node2.head.value === "\\not") {
3134
3230
  const sym = convert_tex_node_to_typst(node2.args[0], options);
3135
3231
  assert(sym.type === "terminal");
@@ -3150,6 +3246,71 @@ function convert_tex_node_to_typst(abstractNode, options) {
3150
3246
  if (node2.head.value === "\\underset") {
3151
3247
  return convert_underset(node2, options);
3152
3248
  }
3249
+ if (["\\bra", "\\ket", "\\braket", "\\set", "\\Bra", "\\Ket", "\\Braket", "\\Set"].includes(node2.head.value)) {
3250
+ let process_vertical_bar2 = function(n) {
3251
+ const mid_bar = new TypstFuncCall(
3252
+ new TypstToken(1 /* SYMBOL */, "mid"),
3253
+ [TypstToken.VERTICAL_BAR.toNode()]
3254
+ );
3255
+ if (n.type === "terminal" && n.head.eq(TypstToken.VERTICAL_BAR)) {
3256
+ return mid_bar;
3257
+ } else if (n.type === "group") {
3258
+ const group = n;
3259
+ for (let i = 0; i < group.items.length; i++) {
3260
+ if (group.items[i].type === "terminal" && group.items[i].head.eq(TypstToken.VERTICAL_BAR)) {
3261
+ group.items[i] = mid_bar;
3262
+ }
3263
+ }
3264
+ return group;
3265
+ } else {
3266
+ return n;
3267
+ }
3268
+ };
3269
+ var process_vertical_bar = process_vertical_bar2;
3270
+ switch (node2.head.value) {
3271
+ case "\\bra":
3272
+ return new TypstLeftright(
3273
+ null,
3274
+ { body: arg0, left: TypstToken.LEFT_ANGLE, right: TypstToken.VERTICAL_BAR }
3275
+ );
3276
+ case "\\ket":
3277
+ return new TypstLeftright(
3278
+ null,
3279
+ { body: arg0, left: TypstToken.VERTICAL_BAR, right: TypstToken.RIGHT_ANGLE }
3280
+ );
3281
+ case "\\braket":
3282
+ return new TypstLeftright(
3283
+ null,
3284
+ { body: arg0, left: TypstToken.LEFT_ANGLE, right: TypstToken.RIGHT_ANGLE }
3285
+ );
3286
+ case "\\set":
3287
+ return new TypstLeftright(
3288
+ null,
3289
+ { body: arg0, left: TypstToken.LEFT_BRACE, right: TypstToken.RIGHT_BRACE }
3290
+ );
3291
+ case "\\Bra":
3292
+ return new TypstLeftright(
3293
+ TypstToken.LR,
3294
+ { body: process_vertical_bar2(arg0), left: TypstToken.LEFT_ANGLE, right: TypstToken.VERTICAL_BAR }
3295
+ );
3296
+ case "\\Ket":
3297
+ return new TypstLeftright(
3298
+ TypstToken.LR,
3299
+ { body: process_vertical_bar2(arg0), left: TypstToken.VERTICAL_BAR, right: TypstToken.RIGHT_ANGLE }
3300
+ );
3301
+ case "\\Braket":
3302
+ return new TypstLeftright(
3303
+ TypstToken.LR,
3304
+ { body: process_vertical_bar2(arg0), left: TypstToken.LEFT_ANGLE, right: TypstToken.RIGHT_ANGLE }
3305
+ );
3306
+ case "\\Set":
3307
+ return new TypstLeftright(
3308
+ TypstToken.LR,
3309
+ { body: process_vertical_bar2(arg0), left: TypstToken.LEFT_BRACE, right: TypstToken.RIGHT_BRACE }
3310
+ );
3311
+ default:
3312
+ }
3313
+ }
3153
3314
  if (node2.head.value === "\\frac") {
3154
3315
  if (options.fracToSlash) {
3155
3316
  return new TypstFraction(node2.args.map((n) => convert_tex_node_to_typst(n, options)).map(appendWithBracketsIfNeeded));