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 +18 -3
- package/dist/index.js +95 -9
- package/dist/tex2typst.min.js +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +2 -2
- package/src/index.ts +0 -5
- package/src/map.ts +5 -3
- package/src/parser.ts +79 -1
- package/src/tex2typst.ts +9 -0
- package/src/types.ts +1 -1
- package/src/writer.ts +36 -2
- package/tool/dist/dist/ka.js +13654 -0
- package/tool/dist/ka.js +13634 -0
- package/tsconfig.json +1 -0
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 "
|
|
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
|
-
|
|
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
|
};
|