@sciexpr/renderer 0.1.0 → 0.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/dist/index.cjs CHANGED
@@ -92,8 +92,37 @@ var LatexReverseRenderer = class {
92
92
  switch (n.kind) {
93
93
  case "root":
94
94
  return n.children.map((c) => this.renderNode(c)).join("");
95
- case "symbol":
96
- return n.value;
95
+ case "symbol": {
96
+ const v = n.value;
97
+ const delimiterPrefixes = /* @__PURE__ */ new Set([
98
+ "\\left",
99
+ "\\right",
100
+ "\\middle",
101
+ "\\big",
102
+ "\\Big",
103
+ "\\bigg",
104
+ "\\Bigg",
105
+ "\\bigl",
106
+ "\\Bigl",
107
+ "\\biggl",
108
+ "\\Biggl",
109
+ "\\bigr",
110
+ "\\Bigr",
111
+ "\\biggr",
112
+ "\\Biggr",
113
+ "\\bigm",
114
+ "\\Bigm",
115
+ "\\biggm",
116
+ "\\Biggm"
117
+ ]);
118
+ if (v.startsWith("\\") && /[a-zA-Z]$/.test(v)) {
119
+ if (delimiterPrefixes.has(v)) {
120
+ return v;
121
+ }
122
+ return v + " ";
123
+ }
124
+ return v;
125
+ }
97
126
  case "frac":
98
127
  return `\\frac{${this.renderNode(n.numerator)}}{${this.renderNode(n.denominator)}}`;
99
128
  case "script": {
@@ -112,8 +141,11 @@ var LatexReverseRenderer = class {
112
141
  }
113
142
  return `\\sqrt{${this.renderNode(n.radicand)}}`;
114
143
  }
115
- case "delimiter":
116
- return `${n.left}${this.renderNode(n.body)}${n.right}`;
144
+ case "delimiter": {
145
+ const bodyNode = n.body;
146
+ const bodyLatex = bodyNode.kind === "group" ? bodyNode.children.map((c) => this.renderNode(c)).join("") : this.renderNode(n.body);
147
+ return `${n.left}${bodyLatex}${n.right}`;
148
+ }
117
149
  case "matrix": {
118
150
  const cols = n.columnAlign ? `{${n.columnAlign.join("")}}` : "";
119
151
  const type = n.matrixType ?? "matrix";
@@ -121,6 +153,7 @@ var LatexReverseRenderer = class {
121
153
  return `\\begin{${type}}${cols}${rows}\\end{${type}}`;
122
154
  }
123
155
  case "text":
156
+ if (n.content === "&") return "&";
124
157
  return `\\text{${n.content}}`;
125
158
  case "space":
126
159
  return n.width === 1 ? "\\," : "\\quad";
@@ -146,7 +179,7 @@ var LatexReverseRenderer = class {
146
179
  case "chem-element": {
147
180
  let result = n.symbol;
148
181
  if (n.count && n.count > 1) {
149
- result += n.count;
182
+ result += `_{${n.count}}`;
150
183
  }
151
184
  if (n.charge) {
152
185
  result += `^{${n.charge}${n.chargeSign ?? "+"}}`;
@@ -193,12 +226,15 @@ var KatexRenderer = class {
193
226
  latexRenderer = new LatexReverseRenderer();
194
227
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
195
228
  katexInstance = null;
229
+ /** Promise that resolves when KaTeX is loaded (or fails) */
230
+ ready;
196
231
  constructor() {
197
- this.loadKatex();
232
+ this.ready = this.loadKatex();
198
233
  }
199
234
  async loadKatex() {
200
235
  try {
201
236
  this.katexInstance = await import("katex");
237
+ await import("katex/contrib/mhchem");
202
238
  } catch {
203
239
  this.katexInstance = null;
204
240
  }
@@ -415,17 +451,16 @@ var MathMLRenderer = class {
415
451
  case "frac":
416
452
  return `<mfrac><mrow>${this.renderNode(n.numerator)}</mrow><mrow>${this.renderNode(n.denominator)}</mrow></mfrac>`;
417
453
  case "script": {
418
- let result = this.renderNode(n.base);
454
+ if (n.sub && n.super) {
455
+ return `<msubsup>${this.renderNode(n.base)}<mrow>${this.renderNode(n.sub)}</mrow><mrow>${this.renderNode(n.super)}</mrow></msubsup>`;
456
+ }
419
457
  if (n.sub) {
420
- result = `<msub>${result}<mrow>${this.renderNode(n.sub)}</mrow></msub>`;
458
+ return `<msub>${this.renderNode(n.base)}<mrow>${this.renderNode(n.sub)}</mrow></msub>`;
421
459
  }
422
460
  if (n.super) {
423
- result = `<msup>${result}<mrow>${this.renderNode(n.super)}</mrow></msup>`;
424
- }
425
- if (n.sub && n.super) {
426
- result = `<msubsup>${this.renderNode(n.base)}<mrow>${this.renderNode(n.sub)}</mrow><mrow>${this.renderNode(n.super)}</mrow></msubsup>`;
461
+ return `<msup>${this.renderNode(n.base)}<mrow>${this.renderNode(n.super)}</mrow></msup>`;
427
462
  }
428
- return result;
463
+ return this.renderNode(n.base);
429
464
  }
430
465
  case "radical": {
431
466
  if (n.index) {
package/dist/index.d.cts CHANGED
@@ -109,6 +109,8 @@ declare class KatexRenderer implements IRenderer {
109
109
  readonly outputFormat: "html";
110
110
  private latexRenderer;
111
111
  private katexInstance;
112
+ /** Promise that resolves when KaTeX is loaded (or fails) */
113
+ readonly ready: Promise<void>;
112
114
  constructor();
113
115
  private loadKatex;
114
116
  /** 手动设置 KaTeX 实例 */
package/dist/index.d.ts CHANGED
@@ -109,6 +109,8 @@ declare class KatexRenderer implements IRenderer {
109
109
  readonly outputFormat: "html";
110
110
  private latexRenderer;
111
111
  private katexInstance;
112
+ /** Promise that resolves when KaTeX is loaded (or fails) */
113
+ readonly ready: Promise<void>;
112
114
  constructor();
113
115
  private loadKatex;
114
116
  /** 手动设置 KaTeX 实例 */
package/dist/index.js CHANGED
@@ -52,8 +52,37 @@ var LatexReverseRenderer = class {
52
52
  switch (n.kind) {
53
53
  case "root":
54
54
  return n.children.map((c) => this.renderNode(c)).join("");
55
- case "symbol":
56
- return n.value;
55
+ case "symbol": {
56
+ const v = n.value;
57
+ const delimiterPrefixes = /* @__PURE__ */ new Set([
58
+ "\\left",
59
+ "\\right",
60
+ "\\middle",
61
+ "\\big",
62
+ "\\Big",
63
+ "\\bigg",
64
+ "\\Bigg",
65
+ "\\bigl",
66
+ "\\Bigl",
67
+ "\\biggl",
68
+ "\\Biggl",
69
+ "\\bigr",
70
+ "\\Bigr",
71
+ "\\biggr",
72
+ "\\Biggr",
73
+ "\\bigm",
74
+ "\\Bigm",
75
+ "\\biggm",
76
+ "\\Biggm"
77
+ ]);
78
+ if (v.startsWith("\\") && /[a-zA-Z]$/.test(v)) {
79
+ if (delimiterPrefixes.has(v)) {
80
+ return v;
81
+ }
82
+ return v + " ";
83
+ }
84
+ return v;
85
+ }
57
86
  case "frac":
58
87
  return `\\frac{${this.renderNode(n.numerator)}}{${this.renderNode(n.denominator)}}`;
59
88
  case "script": {
@@ -72,8 +101,11 @@ var LatexReverseRenderer = class {
72
101
  }
73
102
  return `\\sqrt{${this.renderNode(n.radicand)}}`;
74
103
  }
75
- case "delimiter":
76
- return `${n.left}${this.renderNode(n.body)}${n.right}`;
104
+ case "delimiter": {
105
+ const bodyNode = n.body;
106
+ const bodyLatex = bodyNode.kind === "group" ? bodyNode.children.map((c) => this.renderNode(c)).join("") : this.renderNode(n.body);
107
+ return `${n.left}${bodyLatex}${n.right}`;
108
+ }
77
109
  case "matrix": {
78
110
  const cols = n.columnAlign ? `{${n.columnAlign.join("")}}` : "";
79
111
  const type = n.matrixType ?? "matrix";
@@ -81,6 +113,7 @@ var LatexReverseRenderer = class {
81
113
  return `\\begin{${type}}${cols}${rows}\\end{${type}}`;
82
114
  }
83
115
  case "text":
116
+ if (n.content === "&") return "&";
84
117
  return `\\text{${n.content}}`;
85
118
  case "space":
86
119
  return n.width === 1 ? "\\," : "\\quad";
@@ -106,7 +139,7 @@ var LatexReverseRenderer = class {
106
139
  case "chem-element": {
107
140
  let result = n.symbol;
108
141
  if (n.count && n.count > 1) {
109
- result += n.count;
142
+ result += `_{${n.count}}`;
110
143
  }
111
144
  if (n.charge) {
112
145
  result += `^{${n.charge}${n.chargeSign ?? "+"}}`;
@@ -153,12 +186,15 @@ var KatexRenderer = class {
153
186
  latexRenderer = new LatexReverseRenderer();
154
187
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
155
188
  katexInstance = null;
189
+ /** Promise that resolves when KaTeX is loaded (or fails) */
190
+ ready;
156
191
  constructor() {
157
- this.loadKatex();
192
+ this.ready = this.loadKatex();
158
193
  }
159
194
  async loadKatex() {
160
195
  try {
161
196
  this.katexInstance = await import("katex");
197
+ await import("katex/contrib/mhchem");
162
198
  } catch {
163
199
  this.katexInstance = null;
164
200
  }
@@ -375,17 +411,16 @@ var MathMLRenderer = class {
375
411
  case "frac":
376
412
  return `<mfrac><mrow>${this.renderNode(n.numerator)}</mrow><mrow>${this.renderNode(n.denominator)}</mrow></mfrac>`;
377
413
  case "script": {
378
- let result = this.renderNode(n.base);
414
+ if (n.sub && n.super) {
415
+ return `<msubsup>${this.renderNode(n.base)}<mrow>${this.renderNode(n.sub)}</mrow><mrow>${this.renderNode(n.super)}</mrow></msubsup>`;
416
+ }
379
417
  if (n.sub) {
380
- result = `<msub>${result}<mrow>${this.renderNode(n.sub)}</mrow></msub>`;
418
+ return `<msub>${this.renderNode(n.base)}<mrow>${this.renderNode(n.sub)}</mrow></msub>`;
381
419
  }
382
420
  if (n.super) {
383
- result = `<msup>${result}<mrow>${this.renderNode(n.super)}</mrow></msup>`;
384
- }
385
- if (n.sub && n.super) {
386
- result = `<msubsup>${this.renderNode(n.base)}<mrow>${this.renderNode(n.sub)}</mrow><mrow>${this.renderNode(n.super)}</mrow></msubsup>`;
421
+ return `<msup>${this.renderNode(n.base)}<mrow>${this.renderNode(n.super)}</mrow></msup>`;
387
422
  }
388
- return result;
423
+ return this.renderNode(n.base);
389
424
  }
390
425
  case "radical": {
391
426
  if (n.index) {
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@sciexpr/renderer",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Scientific Expression Engine - Multi-format renderer (KaTeX, Unicode, MathML, LaTeX)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
7
- "module": "./dist/index.mjs",
7
+ "module": "./dist/index.js",
8
8
  "types": "./dist/index.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
11
  "types": "./dist/index.d.ts",
12
- "import": "./dist/index.mjs",
12
+ "import": "./dist/index.js",
13
13
  "require": "./dist/index.cjs"
14
14
  }
15
15
  },
@@ -44,7 +44,7 @@
44
44
  "access": "public"
45
45
  },
46
46
  "dependencies": {
47
- "@sciexpr/core": "0.1.0"
47
+ "@sciexpr/core": "0.1.1"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "katex": "^0.16.0"