xmmath 1.0.9 → 1.1.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/package.json CHANGED
@@ -1,29 +1,40 @@
1
1
  {
2
- "name": "xmmath",
3
- "version": "1.0.9",
4
- "description": "",
5
- "main": "./dist/xmmath.umd.js",
6
- "module": "./dist/xmmath.es.js",
7
- "exports": {
8
- ".": {
9
- "import": "./dist/xmmath.es.js",
10
- "require": "./dist/xmmath.umd.js"
11
- }
12
- },
13
- "homepage": "https://github.com/xushengfeng/xmmath",
14
- "type": "module",
15
- "types": "./src/main.ts",
16
- "scripts": {
17
- "test": "vite ",
18
- "dev": "vite --host 0.0.0.0",
19
- "build": "tsc && vite build",
20
- "preview": "vite preview"
21
- },
22
- "keywords": [],
23
- "author": "",
24
- "license": "Apache-2.0",
25
- "devDependencies": {
26
- "typescript": "^5.4.5",
27
- "vite": "^4.3.9"
28
- }
2
+ "name": "xmmath",
3
+ "version": "1.1.2",
4
+ "description": "",
5
+ "main": "./dist/xmmath.umd.js",
6
+ "module": "./dist/xmmath.es.js",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/xmmath.es.js",
10
+ "require": "./dist/xmmath.umd.js"
11
+ }
12
+ },
13
+ "homepage": "https://github.com/xushengfeng/xmmath",
14
+ "repository": {
15
+ "url": "https://github.com/xushengfeng/xmmath"
16
+ },
17
+ "type": "module",
18
+ "types": "./src/main.ts",
19
+ "scripts": {
20
+ "test": "vitest run",
21
+ "test:watch": "vitest",
22
+ "review": "vite --host 0.0.0.0 --open /test/review/index.html",
23
+ "sync:symbols": "node test/symbols/gen.mjs",
24
+ "render:typst": "node test/typst/render.mjs",
25
+ "render:xmmath": "node test/xmmath/render.mjs",
26
+ "dev": "vite --host 0.0.0.0",
27
+ "build": "tsc && vite build",
28
+ "preview": "vite preview"
29
+ },
30
+ "keywords": [],
31
+ "author": "",
32
+ "license": "Apache-2.0",
33
+ "devDependencies": {
34
+ "@biomejs/biome": "^2.5.14",
35
+ "jsdom": "^30.1.1",
36
+ "typescript": "^5.4.5",
37
+ "vite": "^4.3.9",
38
+ "vitest": "^1.6.1"
39
+ }
29
40
  }
@@ -0,0 +1,2 @@
1
+ allowBuilds:
2
+ esbuild: false
package/readme.md CHANGED
@@ -87,11 +87,12 @@ For more details, please go to [typst docs](https://typst.app/docs) for more inf
87
87
  ## 使用(use)
88
88
 
89
89
  ```typescript
90
- xmmath.toMMLHTML("e^(i pi)=-1"); // 输出html
90
+ xmmath.toMMLHTML("e^(i pi)=-1"); // 输出html(默认块级 display="block")
91
+ xmmath.toMMLHTML("e^(i pi)=-1", true); // 行内:不写 display 属性
91
92
  ```
92
93
 
93
94
  ```typescript
94
- xmmath.toMML("e^(i pi)=-1"); // 输出mathml元素
95
+ xmmath.toMML("e^(i pi)=-1"); // 输出mathml元素(第二个参数同样可传 inline)
95
96
  ```
96
97
 
97
98
  ```typescript
package/src/ast.ts ADDED
@@ -0,0 +1,161 @@
1
+ export type vtype =
2
+ | ""
3
+ | "str"
4
+ | "v"
5
+ | "f"
6
+ | "blank"
7
+ | "group"
8
+ | "group1"
9
+ | "sharp";
10
+ export type tree = {
11
+ type: vtype;
12
+ value: string;
13
+ children?: tree;
14
+ esc?: boolean;
15
+ kh?: string;
16
+ src?: string;
17
+ }[];
18
+
19
+ const Segmenter = Intl.Segmenter;
20
+ const segmenter = new Segmenter("emoji", { granularity: "grapheme" });
21
+
22
+ export const init_c: { emoji: (str: string) => string } = {
23
+ emoji: null,
24
+ };
25
+
26
+ export function ast(str: string): tree {
27
+ const v = /[a-zA-Z]/;
28
+ const kh = /[(){}[\]]/;
29
+ const khl = /[({[]/;
30
+ const khr = /[)}\]]/;
31
+ const blank = /^[ \t\n\r]+$/;
32
+ let type: vtype = "";
33
+ let ignore: false | "line" | "block" = false;
34
+ const o: tree = [];
35
+ const p_tree: { tree: tree; close: boolean }[] = [];
36
+ let now_tree = o;
37
+ let tmp_str = "";
38
+
39
+ str = str.replace(/(\\u\{[\dA-Fa-f]+\})/g, (v) => {
40
+ const codePoint = parseInt(v.slice(3, -1), 16);
41
+ return String.fromCodePoint(codePoint);
42
+ });
43
+
44
+ let strl = init_c.emoji
45
+ ? init_c.emoji(str)
46
+ : Array.from(segmenter.segment(str)).map((w) => w.segment);
47
+ const strl2 = [];
48
+ for (const i of strl) {
49
+ if (i.length > 1 && i.includes(",")) strl2.push(...i);
50
+ else strl2.push(i);
51
+ }
52
+ strl = strl2;
53
+
54
+ for (let i = 0; i < strl.length; i++) {
55
+ const t = strl[i];
56
+ const next = strl[i + 1];
57
+ if (t === "/" && next === "/") ignore = "line";
58
+ if (ignore === "line" && t === "\n") {
59
+ ignore = false;
60
+ continue;
61
+ }
62
+ if (t === "/" && next === "*") ignore = "block";
63
+ if (ignore === "block" && t === "*" && next === "/") {
64
+ i++;
65
+ ignore = false;
66
+ continue;
67
+ }
68
+
69
+ if (ignore) continue;
70
+
71
+ if (type === "blank" && !t.match(blank)) {
72
+ now_tree.push({ type, value: "" });
73
+ type = "";
74
+ }
75
+ if (t === '"' && strl[i - 1] !== "\\") {
76
+ if (type !== "str") {
77
+ type = "str";
78
+ } else {
79
+ now_tree.push({ type, value: tmp_str });
80
+ type = "";
81
+ tmp_str = "";
82
+ }
83
+ continue;
84
+ }
85
+ if (type === "str") {
86
+ tmp_str += t;
87
+ continue;
88
+ }
89
+
90
+ if (t.match(blank)) {
91
+ type = "blank";
92
+ }
93
+
94
+ if (t === "#") {
95
+ now_tree.push({ type: "sharp", value: "" });
96
+ continue;
97
+ }
98
+
99
+ if (
100
+ type === "" &&
101
+ (!strl[i - 1] || !strl[i - 1].match(v)) &&
102
+ (!strl[i + 1] || !strl[i + 1].match(v)) &&
103
+ !t.match(kh)
104
+ ) {
105
+ now_tree.push({ type: "v", value: t });
106
+ continue;
107
+ }
108
+ if (type === "" && !t.match(v) && !t.match(kh)) {
109
+ now_tree.push({ type: "v", value: t });
110
+ continue;
111
+ }
112
+
113
+ if (
114
+ ((strl[i - 1] && strl[i - 1].match(v)) ||
115
+ (strl[i + 1] && strl[i + 1].match(v))) &&
116
+ t.match(v)
117
+ ) {
118
+ type = "f";
119
+ }
120
+ if (type === "f") {
121
+ tmp_str += t;
122
+ }
123
+ if (type === "f" && (!strl[i + 1] || !strl[i + 1].match(v))) {
124
+ now_tree.push({ type, value: tmp_str });
125
+ type = "";
126
+ tmp_str = "";
127
+ }
128
+
129
+ if (t.match(khl)) {
130
+ if (strl[i - 1] === "\\") {
131
+ now_tree.push({ type: "v", value: t, esc: true });
132
+ } else {
133
+ // 开括号一律起组,直到遇到闭括号;到行尾仍没遇到(typst
134
+ // `math_delimited` 走到 eof 的分支)就留成未闭合组,由渲染
135
+ // 阶段只画开括号。旧实现把未配对的开括号退化成普通字符,
136
+ // 会让 `1/(2 (x)` 的分母只剩一个 `(`。
137
+ p_tree.push({ tree: now_tree, close: false });
138
+ now_tree.push({ type: "group", value: tmp_str, children: [], kh: t });
139
+ now_tree = now_tree.at(-1).children;
140
+ tmp_str = "";
141
+ continue;
142
+ }
143
+ }
144
+ if (t.match(khr)) {
145
+ if (strl[i - 1] === "\\") {
146
+ now_tree.push({ type: "v", value: t, esc: true });
147
+ } else if (p_tree.at(-1)) {
148
+ if (p_tree.at(-1).close === false) {
149
+ p_tree.at(-1).close = true;
150
+ now_tree = p_tree.at(-1).tree;
151
+ now_tree.at(-1).kh += t;
152
+ p_tree.pop();
153
+ }
154
+ } else {
155
+ now_tree.push({ type: "v", value: t });
156
+ }
157
+ }
158
+ }
159
+
160
+ return o;
161
+ }