tex2typst 0.5.4 → 0.5.6

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
@@ -584,7 +584,9 @@ var TEX_UNARY_COMMANDS = [
584
584
  "Bra",
585
585
  "Ket",
586
586
  "Braket",
587
- "Set"
587
+ "Set",
588
+ "pmod",
589
+ "cancel"
588
590
  ];
589
591
  var TEX_BINARY_COMMANDS = [
590
592
  "frac",
@@ -727,7 +729,7 @@ function eat_whitespaces(tokens, start) {
727
729
  }
728
730
  function eat_parenthesis(tokens, start) {
729
731
  const firstToken = tokens[start];
730
- if (firstToken.type === 1 /* ELEMENT */ && ["(", ")", "[", "]", "|", "\\{", "\\}", ".", "\\|"].includes(firstToken.value)) {
732
+ if (firstToken.type === 1 /* ELEMENT */ && ["(", ")", "[", "]", "|", "\\{", "\\}", ".", "\\|", "<", ">"].includes(firstToken.value)) {
731
733
  return firstToken;
732
734
  } else if (firstToken.type === 2 /* COMMAND */ && ["lfloor", "rfloor", "lceil", "rceil", "langle", "rangle", "lparen", "rparen", "lbrace", "rbrace"].includes(firstToken.value.slice(1))) {
733
735
  return firstToken;
@@ -742,6 +744,29 @@ function eat_primes(tokens, start) {
742
744
  }
743
745
  return pos - start;
744
746
  }
747
+ function process_styled_parts(nodes) {
748
+ let style_token = null;
749
+ let bucket = [];
750
+ let res = [];
751
+ let i = 0;
752
+ while (true) {
753
+ if (i === nodes.length || nodes[i].head.eq(TexToken.COMMAND_DISPLAYSTYLE) || nodes[i].head.eq(TexToken.COMMAND_TEXTSTYLE)) {
754
+ if (bucket.length > 0) {
755
+ const g = bucket.length === 1 ? bucket[0] : new TexGroup(bucket);
756
+ res.push(style_token ? new TexFuncCall(style_token, [g]) : g);
757
+ }
758
+ if (i === nodes.length) {
759
+ break;
760
+ }
761
+ bucket = [];
762
+ style_token = nodes[i].head;
763
+ } else {
764
+ bucket.push(nodes[i]);
765
+ }
766
+ i++;
767
+ }
768
+ return res;
769
+ }
745
770
  var LEFT_COMMAND = new TexToken(2 /* COMMAND */, "\\left");
746
771
  var RIGHT_COMMAND = new TexToken(2 /* COMMAND */, "\\right");
747
772
  var BEGIN_COMMAND = new TexToken(2 /* COMMAND */, "\\begin");
@@ -803,7 +828,7 @@ var LatexParser = class {
803
828
  if (pos >= tokens.length && closingToken !== null) {
804
829
  return [EMPTY_NODE, -1];
805
830
  }
806
- const styledResults = this.applyStyleCommands(results);
831
+ const styledResults = process_styled_parts(results);
807
832
  let node;
808
833
  if (styledResults.length === 1) {
809
834
  node = styledResults[0];
@@ -1089,34 +1114,6 @@ var LatexParser = class {
1089
1114
  this.alignmentDepth--;
1090
1115
  return [allRows, pos];
1091
1116
  }
1092
- applyStyleCommands(nodes) {
1093
- for (let i = 0; i < nodes.length; i++) {
1094
- const styleToken = this.getStyleToken(nodes[i]);
1095
- if (styleToken) {
1096
- const before = this.applyStyleCommands(nodes.slice(0, i));
1097
- const after = this.applyStyleCommands(nodes.slice(i + 1));
1098
- let body;
1099
- if (after.length === 0) {
1100
- body = EMPTY_NODE;
1101
- } else if (after.length === 1) {
1102
- body = after[0];
1103
- } else {
1104
- body = new TexGroup(after);
1105
- }
1106
- const funcCall = new TexFuncCall(styleToken, [body]);
1107
- return before.concat(funcCall);
1108
- }
1109
- }
1110
- return nodes;
1111
- }
1112
- getStyleToken(node) {
1113
- if (node.type === "terminal") {
1114
- if (node.head.eq(TexToken.COMMAND_DISPLAYSTYLE) || node.head.eq(TexToken.COMMAND_TEXTSTYLE)) {
1115
- return node.head;
1116
- }
1117
- }
1118
- return null;
1119
- }
1120
1117
  };
1121
1118
  function passIgnoreWhitespaceBeforeScriptMark(tokens) {
1122
1119
  const is_script_mark = (token) => token.eq(SUB_SYMBOL) || token.eq(SUP_SYMBOL);
@@ -1174,6 +1171,8 @@ var shorthandMap = /* @__PURE__ */ new Map([
1174
1171
  ["dots.h", "..."],
1175
1172
  ["gt.triple", ">>>"],
1176
1173
  ["lt.triple", "<<<"],
1174
+ ["arrow.l.r", "<->"],
1175
+ // Typst's documentation doesn't include this. Wondering why
1177
1176
  ["arrow.r", "->"],
1178
1177
  ["arrow.r.double", "=>"],
1179
1178
  ["arrow.r.squiggly", "~>"],
@@ -1191,9 +1190,7 @@ var shorthandMap = /* @__PURE__ */ new Map([
1191
1190
  ["lt.eq", "<="],
1192
1191
  ["ast.op", "*"],
1193
1192
  ["minus", "-"],
1194
- ["tilde.op", "~"],
1195
- // Typst's documentation doesn't include this. Wondering why
1196
- ["arrow.l.r", "<->"]
1193
+ ["tilde.op", "~"]
1197
1194
  ]);
1198
1195
  var reverseShorthandMap = /* @__PURE__ */ new Map();
1199
1196
  for (const [key, value] of shorthandMap.entries()) {
@@ -1233,6 +1230,8 @@ var TypstToken = class _TypstToken {
1233
1230
  static EMPTY = new _TypstToken(2 /* ELEMENT */, "");
1234
1231
  static LEFT_BRACE = new _TypstToken(2 /* ELEMENT */, "{");
1235
1232
  static RIGHT_BRACE = new _TypstToken(2 /* ELEMENT */, "}");
1233
+ static LEFT_PAREN = new _TypstToken(2 /* ELEMENT */, "(");
1234
+ static RIGHT_PAREN = new _TypstToken(2 /* ELEMENT */, ")");
1236
1235
  static LEFT_ANGLE = new _TypstToken(1 /* SYMBOL */, "chevron.l");
1237
1236
  static RIGHT_ANGLE = new _TypstToken(1 /* SYMBOL */, "chevron.r");
1238
1237
  static VERTICAL_BAR = new _TypstToken(2 /* ELEMENT */, "|");
@@ -1240,7 +1239,7 @@ var TypstToken = class _TypstToken {
1240
1239
  static MINUS = new _TypstToken(2 /* ELEMENT */, "-");
1241
1240
  static LR = new _TypstToken(1 /* SYMBOL */, "lr");
1242
1241
  static LEFT_DELIMITERS = [
1243
- new _TypstToken(2 /* ELEMENT */, "("),
1242
+ _TypstToken.LEFT_PAREN,
1244
1243
  new _TypstToken(2 /* ELEMENT */, "["),
1245
1244
  _TypstToken.LEFT_BRACE,
1246
1245
  _TypstToken.VERTICAL_BAR,
@@ -1249,7 +1248,7 @@ var TypstToken = class _TypstToken {
1249
1248
  new _TypstToken(1 /* SYMBOL */, "brace.l")
1250
1249
  ];
1251
1250
  static RIGHT_DELIMITERS = [
1252
- new _TypstToken(2 /* ELEMENT */, ")"),
1251
+ _TypstToken.RIGHT_PAREN,
1253
1252
  new _TypstToken(2 /* ELEMENT */, "]"),
1254
1253
  _TypstToken.RIGHT_BRACE,
1255
1254
  _TypstToken.VERTICAL_BAR,
@@ -1303,7 +1302,7 @@ var TypstTerminal = class extends TypstNode {
1303
1302
  return true;
1304
1303
  case 1 /* SYMBOL */:
1305
1304
  case 2 /* ELEMENT */: {
1306
- if (["(", "!", "}", "]"].includes(this.head.value)) {
1305
+ if (["(", "!", ",", ")", "}", "]"].includes(this.head.value)) {
1307
1306
  return false;
1308
1307
  }
1309
1308
  return true;
@@ -1333,7 +1332,7 @@ var TypstTerminal = class extends TypstNode {
1333
1332
  serialize(env, options) {
1334
1333
  if (this.head.type === 2 /* ELEMENT */) {
1335
1334
  if (this.head.value === "," && env.insideFunctionDepth > 0) {
1336
- return [new TypstToken(1 /* SYMBOL */, "comma")];
1335
+ return [SOFT_SPACE, new TypstToken(1 /* SYMBOL */, "comma")];
1337
1336
  }
1338
1337
  } else if (this.head.type === 1 /* SYMBOL */) {
1339
1338
  let symbol_name = this.head.value;
@@ -1364,6 +1363,40 @@ var TypstTerminal = class extends TypstNode {
1364
1363
  return [this.head];
1365
1364
  }
1366
1365
  };
1366
+ var TypstTokenQueue = class {
1367
+ queue = [];
1368
+ pushSoftSpace() {
1369
+ if (this.queue.length === 0) {
1370
+ return;
1371
+ } else if (this.queue.at(-1).eq(SOFT_SPACE)) {
1372
+ return;
1373
+ } else if (["(", "{", "["].includes(this.queue.at(-1).value)) {
1374
+ return;
1375
+ }
1376
+ this.queue.push(SOFT_SPACE);
1377
+ }
1378
+ pushAll(tokens) {
1379
+ if (tokens.length == 0) {
1380
+ return;
1381
+ } else if (tokens[0].eq(SOFT_SPACE) && this.queue.length === 0) {
1382
+ this.queue.push(...tokens.slice(1));
1383
+ } else {
1384
+ if ([")", "}", "]"].includes(tokens[0].value)) {
1385
+ while (this.queue.at(-1)?.eq(SOFT_SPACE)) {
1386
+ this.queue.pop();
1387
+ }
1388
+ }
1389
+ this.queue.push(...tokens);
1390
+ }
1391
+ }
1392
+ getQueue() {
1393
+ const res = Array.from(this.queue);
1394
+ while (res.at(-1)?.eq(SOFT_SPACE)) {
1395
+ res.pop();
1396
+ }
1397
+ return res;
1398
+ }
1399
+ };
1367
1400
  var TypstGroup = class extends TypstNode {
1368
1401
  items;
1369
1402
  constructor(items) {
@@ -1389,28 +1422,19 @@ var TypstGroup = class extends TypstNode {
1389
1422
  if (this.items.length === 0) {
1390
1423
  return [];
1391
1424
  }
1392
- const queue = [];
1425
+ const q = new TypstTokenQueue();
1393
1426
  for (let i = 0; i < this.items.length; i++) {
1394
1427
  const n = this.items[i];
1395
1428
  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
- }
1429
+ if (n.isLeftSpaceful()) {
1430
+ q.pushSoftSpace();
1406
1431
  }
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
- }
1432
+ q.pushAll(tokens);
1433
+ if (n.isRightSpaceful()) {
1434
+ q.pushSoftSpace();
1412
1435
  }
1413
1436
  }
1437
+ const queue = q.getQueue();
1414
1438
  if (queue.length > 0 && (queue[0].eq(TypstToken.MINUS) || queue[0].eq(TypstToken.PLUS))) {
1415
1439
  while (queue.length > 1 && queue[1].eq(SOFT_SPACE)) {
1416
1440
  queue.splice(1, 1);
@@ -1615,7 +1639,9 @@ var TypstMatrixLike = class _TypstMatrixLike extends TypstNode {
1615
1639
  row.forEach((cell, j) => {
1616
1640
  queue.push(...cell.serialize(env, options));
1617
1641
  if (j < row.length - 1) {
1618
- queue.push(SOFT_SPACE);
1642
+ if (cell_sep.value === "&") {
1643
+ queue.push(SOFT_SPACE);
1644
+ }
1619
1645
  queue.push(cell_sep);
1620
1646
  queue.push(SOFT_SPACE);
1621
1647
  } else {
@@ -1688,9 +1714,6 @@ var TypstMarkupFunc = class extends TypstNode {
1688
1714
  };
1689
1715
 
1690
1716
  // src/typst-writer.ts
1691
- var TYPST_LEFT_PARENTHESIS2 = new TypstToken(2 /* ELEMENT */, "(");
1692
- var TYPST_RIGHT_PARENTHESIS2 = new TypstToken(2 /* ELEMENT */, ")");
1693
- var TYPST_COMMA = new TypstToken(2 /* ELEMENT */, ",");
1694
1717
  var TYPST_NEWLINE = new TypstToken(1 /* SYMBOL */, "\n");
1695
1718
  var SOFT_SPACE2 = new TypstToken(7 /* CONTROL */, " ");
1696
1719
  var TypstWriter = class {
@@ -1718,15 +1741,13 @@ var TypstWriter = class {
1718
1741
  for (let i = 0; i < qu.length; i++) {
1719
1742
  let token = qu[i];
1720
1743
  if (token.eq(SOFT_SPACE2)) {
1721
- 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]);
1744
+ const to_delete = i === 0 || i === qu.length - 1 || qu[i - 1].type === 6 /* SPACE */ || qu[i - 1].eq(TYPST_NEWLINE) || qu[i + 1].eq(TYPST_NEWLINE);
1722
1745
  if (to_delete) {
1723
1746
  qu[i] = dummy_token;
1724
1747
  }
1725
1748
  }
1726
1749
  }
1727
- qu = qu.filter((token) => !token.eq(dummy_token));
1728
- for (let i = 0; i < qu.length; i++) {
1729
- let token = qu[i];
1750
+ for (const token of qu) {
1730
1751
  this.buffer += token.toString();
1731
1752
  }
1732
1753
  this.queue = [];
@@ -1803,6 +1824,7 @@ var symbolMap = /* @__PURE__ */ new Map([
1803
1824
  ["tilde", "tilde"],
1804
1825
  ["hat", "hat"],
1805
1826
  ["sqrt", "sqrt"],
1827
+ ["bmod", "mod"],
1806
1828
  ["nonumber", ""],
1807
1829
  ["vec", "arrow"],
1808
1830
  ["neq", "eq.not"],
@@ -1827,6 +1849,7 @@ var symbolMap = /* @__PURE__ */ new Map([
1827
1849
  ["tbinom", "binom"],
1828
1850
  ["dfrac", "frac"],
1829
1851
  ["tfrac", "frac"],
1852
+ ["cancel", "cancel"],
1830
1853
  ["operatorname", "op"],
1831
1854
  ["operatorname*", "op"],
1832
1855
  ["boldsymbol", "bold"],
@@ -3048,14 +3071,14 @@ function convert_tex_array_align_literal(alignLiteral) {
3048
3071
  }
3049
3072
  return np;
3050
3073
  }
3051
- var TYPST_LEFT_PARENTHESIS3 = new TypstToken(2 /* ELEMENT */, "(");
3052
- var TYPST_RIGHT_PARENTHESIS3 = new TypstToken(2 /* ELEMENT */, ")");
3074
+ var TYPST_LEFT_PARENTHESIS2 = new TypstToken(2 /* ELEMENT */, "(");
3075
+ var TYPST_RIGHT_PARENTHESIS2 = new TypstToken(2 /* ELEMENT */, ")");
3053
3076
  function appendWithBracketsIfNeeded(node) {
3054
3077
  let need_to_wrap = ["group", "supsub", "matrixLike", "fraction", "empty"].includes(node.type);
3055
3078
  if (need_to_wrap) {
3056
3079
  return new TypstLeftright(null, {
3057
- left: TYPST_LEFT_PARENTHESIS3,
3058
- right: TYPST_RIGHT_PARENTHESIS3,
3080
+ left: TYPST_LEFT_PARENTHESIS2,
3081
+ right: TYPST_RIGHT_PARENTHESIS2,
3059
3082
  body: node
3060
3083
  });
3061
3084
  } else {
@@ -3136,6 +3159,12 @@ function convert_tex_node_to_typst(abstractNode, options) {
3136
3159
  };
3137
3160
  let typ_left = left ? tex_token_to_typst(left, options) : null;
3138
3161
  let typ_right = right ? tex_token_to_typst(right, options) : null;
3162
+ if (typ_left && typ_left.value === "<") {
3163
+ typ_left = new TypstToken(1 /* SYMBOL */, "chevron.l");
3164
+ }
3165
+ if (typ_right && typ_right.value === ">") {
3166
+ typ_right = new TypstToken(1 /* SYMBOL */, "chevron.r");
3167
+ }
3139
3168
  if (typ_left === null && typ_right !== null) {
3140
3169
  typ_right = escape_curly_or_paren(typ_right);
3141
3170
  }
@@ -3240,6 +3269,13 @@ function convert_tex_node_to_typst(abstractNode, options) {
3240
3269
  }
3241
3270
  }
3242
3271
  }
3272
+ if (node2.head.value === "\\pmod") {
3273
+ const g = new TypstGroup([new TypstToken(1 /* SYMBOL */, "mod").toNode(), arg0]);
3274
+ return new TypstLeftright(
3275
+ null,
3276
+ { body: g, left: TypstToken.LEFT_PAREN, right: TypstToken.RIGHT_PAREN }
3277
+ );
3278
+ }
3243
3279
  if (node2.head.value === "\\overset") {
3244
3280
  return convert_overset(node2, options);
3245
3281
  }
@@ -3247,7 +3283,7 @@ function convert_tex_node_to_typst(abstractNode, options) {
3247
3283
  return convert_underset(node2, options);
3248
3284
  }
3249
3285
  if (["\\bra", "\\ket", "\\braket", "\\set", "\\Bra", "\\Ket", "\\Braket", "\\Set"].includes(node2.head.value)) {
3250
- let process_vertical_bar2 = function(n) {
3286
+ let process_vertical_bar2 = function(n, once) {
3251
3287
  const mid_bar = new TypstFuncCall(
3252
3288
  new TypstToken(1 /* SYMBOL */, "mid"),
3253
3289
  [TypstToken.VERTICAL_BAR.toNode()]
@@ -3259,6 +3295,9 @@ function convert_tex_node_to_typst(abstractNode, options) {
3259
3295
  for (let i = 0; i < group.items.length; i++) {
3260
3296
  if (group.items[i].type === "terminal" && group.items[i].head.eq(TypstToken.VERTICAL_BAR)) {
3261
3297
  group.items[i] = mid_bar;
3298
+ if (once) {
3299
+ break;
3300
+ }
3262
3301
  }
3263
3302
  }
3264
3303
  return group;
@@ -3291,22 +3330,22 @@ function convert_tex_node_to_typst(abstractNode, options) {
3291
3330
  case "\\Bra":
3292
3331
  return new TypstLeftright(
3293
3332
  TypstToken.LR,
3294
- { body: process_vertical_bar2(arg0), left: TypstToken.LEFT_ANGLE, right: TypstToken.VERTICAL_BAR }
3333
+ { body: arg0, left: TypstToken.LEFT_ANGLE, right: TypstToken.VERTICAL_BAR }
3295
3334
  );
3296
3335
  case "\\Ket":
3297
3336
  return new TypstLeftright(
3298
3337
  TypstToken.LR,
3299
- { body: process_vertical_bar2(arg0), left: TypstToken.VERTICAL_BAR, right: TypstToken.RIGHT_ANGLE }
3338
+ { body: arg0, left: TypstToken.VERTICAL_BAR, right: TypstToken.RIGHT_ANGLE }
3300
3339
  );
3301
3340
  case "\\Braket":
3302
3341
  return new TypstLeftright(
3303
3342
  TypstToken.LR,
3304
- { body: process_vertical_bar2(arg0), left: TypstToken.LEFT_ANGLE, right: TypstToken.RIGHT_ANGLE }
3343
+ { body: process_vertical_bar2(arg0, false), left: TypstToken.LEFT_ANGLE, right: TypstToken.RIGHT_ANGLE }
3305
3344
  );
3306
3345
  case "\\Set":
3307
3346
  return new TypstLeftright(
3308
3347
  TypstToken.LR,
3309
- { body: process_vertical_bar2(arg0), left: TypstToken.LEFT_BRACE, right: TypstToken.RIGHT_BRACE }
3348
+ { body: process_vertical_bar2(arg0, true), left: TypstToken.LEFT_BRACE, right: TypstToken.RIGHT_BRACE }
3310
3349
  );
3311
3350
  default:
3312
3351
  }
@@ -4218,14 +4257,6 @@ var TexWriter = class {
4218
4257
  this.queue = this.queue.concat(node.serialize());
4219
4258
  }
4220
4259
  flushQueue() {
4221
- while (this.queue.length > 0) {
4222
- const last_token = this.queue[this.queue.length - 1];
4223
- if (last_token.eq(TexToken.COMMAND_DISPLAYSTYLE) || last_token.eq(TexToken.COMMAND_TEXTSTYLE)) {
4224
- this.queue.pop();
4225
- } else {
4226
- break;
4227
- }
4228
- }
4229
4260
  for (let i = 0; i < this.queue.length; i++) {
4230
4261
  this.buffer = writeTexTokenBuffer(this.buffer, this.queue[i]);
4231
4262
  }
@@ -4233,6 +4264,10 @@ var TexWriter = class {
4233
4264
  }
4234
4265
  finalize() {
4235
4266
  this.flushQueue();
4267
+ this.buffer = this.buffer.replace(/\\displaystyle \\displaystyle/g, "\\displaystyle");
4268
+ this.buffer = this.buffer.replace(/\\textstyle \\textstyle/g, "\\textstyle");
4269
+ this.buffer = this.buffer.replace(/\s?\\textstyle\s?$/, "");
4270
+ this.buffer = this.buffer.replace(/\s?\\displaystyle\s?$/, "");
4236
4271
  return this.buffer;
4237
4272
  }
4238
4273
  };