tex2typst 0.3.1 → 0.3.2

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 CHANGED
@@ -1,4 +1,5 @@
1
- # tex2typst
1
+ # tex2typst.js
2
+
2
3
  JavaScript library for conversion between TeX/LaTeX and Typst math formula code.
3
4
 
4
5
  Despite the name `tex2typst` due to the initial goal of converting TeX to Typst, the library can also convert Typst to TeX since version 0.3.0.
@@ -28,14 +29,13 @@ Replace `0.3.0` with the latest version number in case this README is outdated.
28
29
 
29
30
  ## Usage
30
31
 
31
-
32
32
  ```javascript
33
33
  import { tex2typst, typst2tex } from 'tex2typst';
34
34
 
35
35
  let tex = "e \overset{\text{def}}{=} \lim_{{n \to \infty}} \left(1 + \frac{1}{n}\right)^n";
36
36
  let typst = tex2typst(tex);
37
37
  console.log(typst);
38
- // e eq.def lim_(n arrow.r infinity)(1 + frac(1, n))^n
38
+ // e eq.def lim_(n arrow.r infinity)(1 + 1/n)^n
39
39
 
40
40
  let tex_recovered = typst2tex(typst);
41
41
  console.log(tex_recovered);
@@ -44,6 +44,8 @@ console.log(tex_recovered);
44
44
 
45
45
  If you are using the library in a web page via a `<script>` tag, you don't need the line of `import`, function `tex2typst` and `typst2tex` should be available in the global scope.
46
46
 
47
+ tex2typst.js supports some advanced options to customize the conversion. For more details, please refer to the [API Reference](docs/api-reference.md).
48
+
47
49
  ## Open-source license
48
50
 
49
51
  GPL v3. See [LICENSE](LICENSE) for details.
package/dist/index.js CHANGED
@@ -1,5 +1,16 @@
1
1
  // src/map.ts
2
2
  var symbolMap = /* @__PURE__ */ new Map([
3
+ ["cos", "cos"],
4
+ ["sin", "sin"],
5
+ ["tan", "tan"],
6
+ ["cot", "cot"],
7
+ ["sec", "sec"],
8
+ ["csc", "csc"],
9
+ ["mod", "mod"],
10
+ ["omicron", "omicron"],
11
+ ["Xi", "Xi"],
12
+ ["Upsilon", "Upsilon"],
13
+ ["lim", "lim"],
3
14
  ["nonumber", ""],
4
15
  ["vec", "arrow"],
5
16
  ["neq", "eq.not"],
@@ -59,44 +70,16 @@ var symbolMap = /* @__PURE__ */ new Map([
59
70
  ["propto", "prop"],
60
71
  /* arrows */
61
72
  ["gets", "arrow.l"],
62
- ["hookleftarrow", "arrow.l.hook"],
63
- ["leftharpoonup", "harpoon.lt"],
64
- ["leftharpoondown", "harpoon.lb"],
65
- ["rightleftharpoons", "harpoons.rtlb"],
66
- ["longleftarrow", "arrow.l.long"],
67
- ["longrightarrow", "arrow.r.long"],
68
- ["longleftrightarrow", "arrow.l.r.long"],
69
- ["Longleftarrow", "arrow.l.double.long"],
70
- ["Longrightarrow", "arrow.r.double.long"],
71
- ["Longleftrightarrow", "arrow.l.r.double.long"],
72
73
  // ['longmapsto', 'arrow.r.bar'],
73
- ["hookrightarrow", "arrow.r.hook"],
74
- ["rightharpoonup", "harpoon.rt"],
75
- ["rightharpoondown", "harpoon.rb"],
76
74
  ["iff", "arrow.l.r.double.long"],
77
75
  ["implies", "arrow.r.double.long"],
78
- ["uparrow", "arrow.t"],
79
- ["downarrow", "arrow.b"],
80
- ["updownarrow", "arrow.t.b"],
81
- ["Uparrow", "arrow.t.double"],
82
- ["Downarrow", "arrow.b.double"],
83
- ["Updownarrow", "arrow.t.b.double"],
84
- ["nearrow", "arrow.tr"],
85
- ["searrow", "arrow.br"],
86
- ["swarrow", "arrow.bl"],
87
- ["nwarrow", "arrow.tl"],
88
76
  ["leadsto", "arrow.squiggly"],
89
- ["leftleftarrows", "arrows.ll"],
90
- ["rightrightarrows", "arrows.rr"],
91
77
  ["Cap", "sect.double"],
92
78
  ["Cup", "union.double"],
93
79
  ["Delta", "Delta"],
94
80
  ["Gamma", "Gamma"],
95
81
  ["Join", "join"],
96
82
  ["Lambda", "Lambda"],
97
- ["Leftarrow", "arrow.l.double"],
98
- ["Leftrightarrow", "arrow.l.r.double"],
99
- ["Longrightarrow", "arrow.r.double.long"],
100
83
  ["Omega", "Omega"],
101
84
  ["P", "pilcrow"],
102
85
  ["Phi", "Phi"],
@@ -152,7 +135,6 @@ var symbolMap = /* @__PURE__ */ new Map([
152
135
  ["div", "div"],
153
136
  ["divideontimes", "times.div"],
154
137
  ["dotplus", "plus.dot"],
155
- ["downarrow", "arrow.b"],
156
138
  ["ell", "ell"],
157
139
  ["emptyset", "nothing"],
158
140
  ["epsilon", "epsilon.alt"],
@@ -186,8 +168,6 @@ var symbolMap = /* @__PURE__ */ new Map([
186
168
  ["lbrack", "bracket.l"],
187
169
  ["ldots", "dots.h"],
188
170
  ["le", "lt.eq"],
189
- ["leadsto", "arrow.squiggly"],
190
- ["leftarrow", "arrow.l"],
191
171
  ["leftthreetimes", "times.three.l"],
192
172
  ["leftrightarrow", "arrow.l.r"],
193
173
  ["leq", "lt.eq"],
@@ -224,7 +204,6 @@ var symbolMap = /* @__PURE__ */ new Map([
224
204
  ["nu", "nu"],
225
205
  ["ntriangleleft", "lt.tri.not"],
226
206
  ["ntriangleright", "gt.tri.not"],
227
- ["nwarrow", "arrow.tl"],
228
207
  ["odot", "dot.circle"],
229
208
  ["oint", "integral.cont"],
230
209
  ["oiint", "integral.surf"],
@@ -277,7 +256,6 @@ var symbolMap = /* @__PURE__ */ new Map([
277
256
  ["supset", "supset"],
278
257
  ["supseteq", "supset.eq"],
279
258
  ["supsetneq", "supset.neq"],
280
- ["swarrow", "arrow.bl"],
281
259
  ["tau", "tau"],
282
260
  ["theta", "theta"],
283
261
  ["times", "times"],
@@ -288,8 +266,6 @@ var symbolMap = /* @__PURE__ */ new Map([
288
266
  // ['triangleleft', 'triangle.l.small'],
289
267
  // ['triangleright', 'triangle.r.small'],
290
268
  ["twoheadrightarrow", "arrow.r.twohead"],
291
- ["uparrow", "arrow.t"],
292
- ["updownarrow", "arrow.t.b"],
293
269
  ["upharpoonright", "harpoon.tr"],
294
270
  ["uplus", "union.plus"],
295
271
  ["upsilon", "upsilon"],
@@ -1081,6 +1057,7 @@ for (const [key, value] of Array.from(symbolMap.entries()).reverse()) {
1081
1057
  reverseSymbolMap.set(value, key);
1082
1058
  }
1083
1059
  reverseSymbolMap.set("dif", "mathrm{d}");
1060
+ reverseSymbolMap.set("oo", "infty");
1084
1061
  var typst_to_tex_map = /* @__PURE__ */ new Map([
1085
1062
  ["top", "top"],
1086
1063
  ["frac", "frac"],
@@ -1977,17 +1954,55 @@ function parseTex(tex, customTexMacros) {
1977
1954
  return parser.parse(tokens);
1978
1955
  }
1979
1956
 
1957
+ // src/typst-shorthands.ts
1958
+ var shorthandMap = /* @__PURE__ */ new Map([
1959
+ ["arrow.l.r.double.long", "<==>"],
1960
+ ["arrow.l.r.long", "<-->"],
1961
+ ["arrow.r.bar", "|->"],
1962
+ ["arrow.r.double.bar", "|=>"],
1963
+ ["arrow.r.double.long", "==>"],
1964
+ ["arrow.r.long", "-->"],
1965
+ ["arrow.r.long.squiggly", "~~>"],
1966
+ ["arrow.r.tail", ">->"],
1967
+ ["arrow.r.twohead", "->>"],
1968
+ ["arrow.l.double.long", "<=="],
1969
+ ["arrow.l.long", "<--"],
1970
+ ["arrow.l.long.squiggly", "<~~"],
1971
+ ["arrow.l.tail", "<-<"],
1972
+ ["arrow.l.twohead", "<<-"],
1973
+ ["arrow.l.r", "<->"],
1974
+ ["arrow.l.r.double", "<=>"],
1975
+ ["colon.double.eq", "::="],
1976
+ ["dots.h", "..."],
1977
+ ["gt.triple", ">>>"],
1978
+ ["lt.triple", "<<<"],
1979
+ ["arrow.r", "->"],
1980
+ ["arrow.r.double", "=>"],
1981
+ ["arrow.r.squiggly", "~>"],
1982
+ ["arrow.l", "<-"],
1983
+ ["arrow.l.squiggly", "<~"],
1984
+ ["bar.v.double", "||"],
1985
+ ["bracket.l.double", "[|"],
1986
+ ["bracket.r.double", "|]"],
1987
+ ["colon.eq", ":="],
1988
+ ["eq.colon", "=:"],
1989
+ ["eq.not", "!="],
1990
+ ["gt.double", ">>"],
1991
+ ["gt.eq", ">="],
1992
+ ["lt.double", "<<"],
1993
+ ["lt.eq", "<="],
1994
+ ["ast.op", "*"],
1995
+ ["minus", "-"],
1996
+ ["tilde.op", "~"]
1997
+ ]);
1998
+ var reverseShorthandMap = /* @__PURE__ */ new Map();
1999
+ for (const [key, value] of shorthandMap.entries()) {
2000
+ if (value.length > 1) {
2001
+ reverseShorthandMap.set(value, key);
2002
+ }
2003
+ }
2004
+
1980
2005
  // src/typst-writer.ts
1981
- var TYPST_INTRINSIC_SYMBOLS = [
1982
- "dim",
1983
- "id",
1984
- "im",
1985
- "mod",
1986
- "Pr",
1987
- "sech",
1988
- "csch"
1989
- // 'sgn
1990
- ];
1991
2006
  function is_delimiter(c) {
1992
2007
  return c.type === "atom" && ["(", ")", "[", "]", "{", "}", "|", "\u230A", "\u230B", "\u2308", "\u2309"].includes(c.content);
1993
2008
  }
@@ -2006,6 +2021,8 @@ function typst_primitive_to_string(value) {
2006
2021
  default:
2007
2022
  if (value === null) {
2008
2023
  return "#none";
2024
+ } else if (value instanceof TypstToken) {
2025
+ return value.toString();
2009
2026
  }
2010
2027
  throw new TypstWriterError(`Invalid primitive value: ${value}`, value);
2011
2028
  }
@@ -2018,13 +2035,14 @@ var TypstWriterError = class extends Error {
2018
2035
  }
2019
2036
  };
2020
2037
  var TypstWriter = class {
2021
- constructor(nonStrict, preferTypstIntrinsic, keepSpaces) {
2038
+ constructor(opt) {
2022
2039
  this.buffer = "";
2023
2040
  this.queue = [];
2024
2041
  this.insideFunctionDepth = 0;
2025
- this.nonStrict = nonStrict;
2026
- this.preferTypstIntrinsic = preferTypstIntrinsic;
2027
- this.keepSpaces = keepSpaces;
2042
+ this.nonStrict = opt.nonStrict;
2043
+ this.preferShorthands = opt.preferShorthands;
2044
+ this.keepSpaces = opt.keepSpaces;
2045
+ this.inftyToOo = opt.inftyToOo;
2028
2046
  }
2029
2047
  writeBuffer(token) {
2030
2048
  const str = token.toString();
@@ -2063,9 +2081,19 @@ var TypstWriter = class {
2063
2081
  }
2064
2082
  break;
2065
2083
  }
2066
- case "symbol":
2067
- this.queue.push(new TypstToken(0 /* SYMBOL */, node.content));
2084
+ case "symbol": {
2085
+ let content = node.content;
2086
+ if (this.preferShorthands) {
2087
+ if (shorthandMap.has(content)) {
2088
+ content = shorthandMap.get(content);
2089
+ }
2090
+ }
2091
+ if (this.inftyToOo && content === "infinity") {
2092
+ content = "oo";
2093
+ }
2094
+ this.queue.push(new TypstToken(0 /* SYMBOL */, content));
2068
2095
  break;
2096
+ }
2069
2097
  case "text":
2070
2098
  this.queue.push(new TypstToken(2 /* TEXT */, node.content));
2071
2099
  break;
@@ -2267,6 +2295,16 @@ var TypstWriter = class {
2267
2295
  };
2268
2296
 
2269
2297
  // src/convert.ts
2298
+ var TYPST_INTRINSIC_SYMBOLS = [
2299
+ "dim",
2300
+ "id",
2301
+ "im",
2302
+ "mod",
2303
+ "Pr",
2304
+ "sech",
2305
+ "csch"
2306
+ // 'sgn
2307
+ ];
2270
2308
  function tex_token_to_typst(token) {
2271
2309
  if (/^[a-zA-Z0-9]$/.test(token)) {
2272
2310
  return token;
@@ -2495,14 +2533,8 @@ function convert_tex_node_to_typst(node, options = {}) {
2495
2533
  delim = "|";
2496
2534
  break;
2497
2535
  case "Vmatrix": {
2498
- const matrix2 = new TypstNode("matrix", "", [], data);
2499
- matrix2.setOptions({ "delim": TYPST_NONE });
2500
- const group = new TypstNode("group", "", [
2501
- new TypstNode("symbol", "||"),
2502
- matrix2,
2503
- new TypstNode("symbol", "||")
2504
- ]);
2505
- return new TypstNode("funcCall", "lr", [group]);
2536
+ delim = new TypstToken(0 /* SYMBOL */, "bar.v.double");
2537
+ break;
2506
2538
  }
2507
2539
  default:
2508
2540
  throw new TypstWriterError(`Unimplemented beginend: ${node.content}`, node);
@@ -2731,6 +2763,8 @@ function convert_typst_node_to_tex(node) {
2731
2763
  }
2732
2764
 
2733
2765
  // src/typst-parser.ts
2766
+ var TYPST_EMPTY_NODE = new TypstNode("empty", "");
2767
+ var TYPST_SHORTHANDS = Array.from(reverseShorthandMap.keys());
2734
2768
  function eat_primes2(tokens, start) {
2735
2769
  let pos = start;
2736
2770
  while (pos < tokens.length && tokens[pos].eq(new TypstToken(1 /* ELEMENT */, "'"))) {
@@ -2745,7 +2779,14 @@ function eat_identifier_name(typst, start) {
2745
2779
  }
2746
2780
  return typst.substring(start, pos);
2747
2781
  }
2748
- var TYPST_EMPTY_NODE = new TypstNode("empty", "");
2782
+ function try_eat_shorthand(typst, start) {
2783
+ for (const shorthand of TYPST_SHORTHANDS) {
2784
+ if (typst.startsWith(shorthand, start)) {
2785
+ return shorthand;
2786
+ }
2787
+ }
2788
+ return null;
2789
+ }
2749
2790
  function tokenize_typst(typst) {
2750
2791
  const tokens = [];
2751
2792
  let pos = 0;
@@ -2831,6 +2872,12 @@ function tokenize_typst(typst) {
2831
2872
  break;
2832
2873
  }
2833
2874
  default: {
2875
+ const shorthand = try_eat_shorthand(typst, pos);
2876
+ if (shorthand !== null) {
2877
+ token = new TypstToken(0 /* SYMBOL */, reverseShorthandMap.get(shorthand));
2878
+ pos += shorthand.length;
2879
+ break;
2880
+ }
2834
2881
  if (isdigit(firstChar)) {
2835
2882
  let newPos = pos;
2836
2883
  while (newPos < typst.length && isdigit(typst[newPos])) {
@@ -3279,27 +3326,22 @@ function tex2typst(tex, options) {
3279
3326
  const opt = {
3280
3327
  nonStrict: true,
3281
3328
  preferTypstIntrinsic: true,
3329
+ preferShorthands: true,
3282
3330
  keepSpaces: false,
3283
3331
  fracToSlash: true,
3332
+ inftyToOo: false,
3284
3333
  customTexMacros: {}
3285
3334
  };
3286
- if (options) {
3287
- if (options.nonStrict) {
3288
- opt.nonStrict = options.nonStrict;
3289
- }
3290
- if (options.preferTypstIntrinsic) {
3291
- opt.preferTypstIntrinsic = options.preferTypstIntrinsic;
3292
- }
3293
- if (options.customTexMacros) {
3294
- opt.customTexMacros = options.customTexMacros;
3295
- }
3296
- if (options.fracToSlash !== void 0) {
3297
- opt.fracToSlash = options.fracToSlash;
3335
+ if (options !== void 0) {
3336
+ for (const key in opt) {
3337
+ if (options[key] !== void 0) {
3338
+ opt[key] = options[key];
3339
+ }
3298
3340
  }
3299
3341
  }
3300
3342
  const texTree = parseTex(tex, opt.customTexMacros);
3301
3343
  const typstTree = convert_tex_node_to_typst(texTree, opt);
3302
- const writer = new TypstWriter(opt.nonStrict, opt.preferTypstIntrinsic, opt.keepSpaces);
3344
+ const writer = new TypstWriter(opt);
3303
3345
  writer.serialize(typstTree);
3304
3346
  return writer.finalize();
3305
3347
  }