tex2typst 0.0.18 → 0.1.20

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
@@ -7,23 +7,38 @@ A Web UI wrapper is available at [https://qwinsi.github.io/tex2typst-webapp/](ht
7
7
 
8
8
  ## Installation
9
9
 
10
+ ## Installing it in a Node.js project
11
+
10
12
  ```bash
11
13
  npm install tex2typst
12
14
  ```
13
15
 
16
+ ## Or just loading it in a web page
17
+
18
+ ```html
19
+ <script src="https://cdn.jsdelivr.net/npm/tex2typst@0.1.20/dist/tex2typst.min.js"></script>
20
+ <!-- or -->
21
+ <script src="https://unpkg.com/tex2typst@0.1.20/dist/tex2typst.min.js"></script>
22
+ ```
23
+
24
+ Replace `0.1.20` with the latest version number in case this README is outdated.
25
+
14
26
  ## Usage
15
27
 
16
28
  ### Basic usage
17
29
 
18
30
  ```javascript
19
- import { parseTex, tex2typst } from 'tex2typst';
31
+ import { tex2typst } from 'tex2typst';
20
32
 
21
33
  let output = tex2typst("\\zeta(s) = \\sum_{n=1}^{\\infty}\\frac{1}{n^s}");
22
34
  console.log(output);
23
35
  // zeta(s) = sum_(n = 1)^infinity frac(1, n^s)
24
36
  ```
25
37
 
26
- ### Advanced settings
38
+ If you are using the library in a web page via a `<script>` tag, you don't need the line of `import`, function `tex2typst` should be available in the global scope.
39
+
40
+
41
+ ### Advanced options
27
42
 
28
43
  - custom TeX macros/commands
29
44
 
@@ -33,7 +48,7 @@ let macros = {
33
48
  "\\sgn": "\\operatorname{sgn}"
34
49
  };
35
50
  let input = "y = \\sgn(x)";
36
- const output = tex2typst(input, {customTexMacros: macros});
51
+ let output = tex2typst(input, {customTexMacros: macros});
37
52
  console.log(output);
38
53
  // y = op("sgn")(x)
39
54
  ```
package/dist/index.js CHANGED
@@ -187,6 +187,10 @@ function katexNodeToTexNode(node) {
187
187
  }
188
188
  }
189
189
  throw new KatexNodeToTexNodeError(`Unknown error type in parsed result:`, node);
190
+ case "comment":
191
+ res.type = "comment";
192
+ res.content = node.text;
193
+ break;
190
194
  default:
191
195
  throw new KatexNodeToTexNodeError(`Unknown node type: ${node.type}`, node);
192
196
  break;
@@ -196,6 +200,44 @@ function katexNodeToTexNode(node) {
196
200
  throw e;
197
201
  }
198
202
  }
203
+ function splitTex(tex) {
204
+ const lines = tex.split("\n");
205
+ const out_tex_list = [];
206
+ let current_tex = "";
207
+ for (let i = 0;i < lines.length; i++) {
208
+ const line = lines[i];
209
+ let index = -1;
210
+ while (index + 1 < line.length) {
211
+ index = line.indexOf("%", index + 1);
212
+ if (index === -1) {
213
+ break;
214
+ }
215
+ if (index === 0 || line[index - 1] !== "\\") {
216
+ break;
217
+ }
218
+ }
219
+ if (index !== -1) {
220
+ current_tex += line.substring(0, index);
221
+ const comment = line.substring(index);
222
+ out_tex_list.push(current_tex);
223
+ current_tex = "";
224
+ out_tex_list.push(comment);
225
+ } else {
226
+ current_tex += line;
227
+ }
228
+ if (i < lines.length - 1) {
229
+ const has_begin_command = line.includes("\\begin{");
230
+ const followed_by_end_command = lines[i + 1].includes("\\end{");
231
+ if (!has_begin_command && !followed_by_end_command) {
232
+ current_tex += "\\SyMbOlNeWlInE ";
233
+ }
234
+ }
235
+ }
236
+ if (current_tex.length > 0) {
237
+ out_tex_list.push(current_tex);
238
+ }
239
+ return out_tex_list;
240
+ }
199
241
  function parseTex(tex, customTexMacros) {
200
242
  const macros = {
201
243
  "\\mod": "\\operatorname{SyMb01-mod}",
@@ -213,6 +255,7 @@ function parseTex(tex, customTexMacros) {
213
255
  "\\slash": "\\operatorname{SyMb01-slash}",
214
256
  "\\LaTeX": "\\operatorname{SyMb01-LaTeX}",
215
257
  "\\TeX": "\\operatorname{SyMb01-TeX}",
258
+ "\\SyMbOlNeWlInE": "\\operatorname{SyMb01-newline}",
216
259
  ...customTexMacros
217
260
  };
218
261
  const options = {
@@ -221,7 +264,21 @@ function parseTex(tex, customTexMacros) {
221
264
  strict: "ignore",
222
265
  throwOnError: false
223
266
  };
224
- let treeArray = generateParseTree(tex, options);
267
+ const tex_list = splitTex(tex);
268
+ let treeArray = [];
269
+ for (const tex_item of tex_list) {
270
+ if (tex_item.startsWith("%")) {
271
+ const tex_node = {
272
+ type: "comment",
273
+ mode: "math",
274
+ text: tex_item.substring(1)
275
+ };
276
+ treeArray.push(tex_node);
277
+ continue;
278
+ }
279
+ const trees = generateParseTree(tex_item, options);
280
+ treeArray = treeArray.concat(trees);
281
+ }
225
282
  let t = {
226
283
  type: "ordgroup",
227
284
  mode: "math",
@@ -246,9 +303,6 @@ var symbolMap = new Map([
246
303
  ["gets", "arrow.l"],
247
304
  ["nonumber", ""],
248
305
  ["vec", "arrow"],
249
- ["mathbf", "bold"],
250
- ["boldsymbol", "bold"],
251
- ["mathfrak", "frak"],
252
306
  ["neq", "eq.not"],
253
307
  ["dot", "dot"],
254
308
  ["ddot", "dot.double"],
@@ -266,8 +320,13 @@ var symbolMap = new Map([
266
320
  ["overline", "overline"],
267
321
  ["underline", "underline"],
268
322
  ["bar", "macron"],
323
+ ["boldsymbol", "bold"],
324
+ ["mathbf", "bold"],
269
325
  ["mathbb", "bb"],
270
326
  ["mathcal", "cal"],
327
+ ["mathfrak", "frak"],
328
+ ["mathsf", "sans"],
329
+ ["mathtt", "mono"],
271
330
  ["mathrm", "upright"],
272
331
  ["rm", "upright"],
273
332
  ["pmb", "bold"],
@@ -512,7 +571,9 @@ function convertToken(token) {
512
571
  if (/^[a-zA-Z0-9]$/.test(token)) {
513
572
  return token;
514
573
  } else if (token === "\\\\") {
515
- return "\\\n";
574
+ return "\\";
575
+ } else if (token == "/") {
576
+ return "\\/";
516
577
  } else if (["\\$", "\\#", "\\&", "\\_"].includes(token)) {
517
578
  return token;
518
579
  } else if (token.startsWith("\\")) {
@@ -565,6 +626,7 @@ class TypstWriter {
565
626
  no_need_space ||= str === "'";
566
627
  no_need_space ||= /[0-9]$/.test(this.buffer) && /^[0-9]/.test(str);
567
628
  no_need_space ||= /[\(\[{]\s*(-|\+)$/.test(this.buffer) || this.buffer === "-" || this.buffer === "+";
629
+ no_need_space ||= str.startsWith("\n");
568
630
  no_need_space ||= this.buffer === "";
569
631
  no_need_space ||= /[\s"_^{\(]$/.test(this.buffer);
570
632
  if (!no_need_space) {
@@ -664,6 +726,19 @@ class TypstWriter {
664
726
  this.queue.push({ type: "atom", content: ")" });
665
727
  this.insideFunctionDepth--;
666
728
  return;
729
+ } else if (node.content === "\\mathbf") {
730
+ this.append({ type: "symbol", content: "upright" });
731
+ this.insideFunctionDepth++;
732
+ this.queue.push({ type: "atom", content: "(" });
733
+ this.queue.push(func_symbol);
734
+ this.insideFunctionDepth++;
735
+ this.queue.push({ type: "atom", content: "(" });
736
+ this.append(arg0);
737
+ this.queue.push({ type: "atom", content: ")" });
738
+ this.insideFunctionDepth--;
739
+ this.queue.push({ type: "atom", content: ")" });
740
+ this.insideFunctionDepth--;
741
+ return;
667
742
  } else if (node.content === "\\mathbb") {
668
743
  const body = node.args[0];
669
744
  if (body.type === "symbol" && /^[A-Z]$/.test(body.content)) {
@@ -682,7 +757,12 @@ class TypstWriter {
682
757
  if (this.preferTypstIntrinsic && TYPST_INTRINSIC_SYMBOLS.includes(text)) {
683
758
  this.queue.push({ type: "symbol", content: text });
684
759
  } else if (text.startsWith("SyMb01-")) {
685
- this.queue.push({ type: "symbol", content: "\\" + text.substring(7) });
760
+ const special_symbol = text.substring(7);
761
+ if (special_symbol === "newline") {
762
+ this.queue.push({ type: "newline", content: "\n" });
763
+ return;
764
+ }
765
+ this.queue.push({ type: "symbol", content: "\\" + special_symbol });
686
766
  } else {
687
767
  this.queue.push({ type: "symbol", content: "op" });
688
768
  this.queue.push({ type: "atom", content: "(" });
@@ -719,6 +799,7 @@ class TypstWriter {
719
799
  matrix.forEach((row, i) => {
720
800
  row.forEach((cell, j) => {
721
801
  if (cell.type === "ordgroup" && cell.args.length === 0) {
802
+ this.queue.push({ type: "atom", content: "," });
722
803
  return;
723
804
  }
724
805
  this.append(cell);
@@ -739,6 +820,8 @@ class TypstWriter {
739
820
  } else {
740
821
  throw new TypstWriterError(`Unknown macro: ${node.content}`, node);
741
822
  }
823
+ } else if (node.type === "comment") {
824
+ this.queue.push({ type: "comment", content: node.content });
742
825
  } else {
743
826
  throw new TypstWriterError(`Unimplemented node type to append: ${node.type}`, node);
744
827
  }
@@ -760,6 +843,12 @@ class TypstWriter {
760
843
  this.needSpaceAfterSingleItemScript = true;
761
844
  str = "";
762
845
  break;
846
+ case "comment":
847
+ str = `//${node.content}`;
848
+ break;
849
+ case "newline":
850
+ str = "\n";
851
+ break;
763
852
  default:
764
853
  throw new TypstWriterError(`Unexpected node type to stringify: ${node.type}`, node);
765
854
  }
@@ -829,9 +918,6 @@ function tex2typst(tex, options) {
829
918
  writer2.append(t);
830
919
  return writer2.finalize();
831
920
  }
832
- if (typeof window !== "undefined") {
833
- window.tex2typst = tex2typst;
834
- }
835
921
  export {
836
922
  tex2typst
837
923
  };