math-core 0.5.4 → 0.6.0

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 ADDED
@@ -0,0 +1,212 @@
1
+ # math-core
2
+
3
+ A Node.js library for converting LaTeX math expressions to MathML Core.
4
+
5
+ ## Overview
6
+
7
+ `math-core` converts LaTeX mathematical expressions into MathML Core, a streamlined subset of MathML that is supported by all major web browsers. It lets you render mathematical content on the web without requiring JavaScript libraries or polyfills.
8
+
9
+ ## Features
10
+
11
+ - Convert LaTeX math expressions to MathML Core
12
+ - Support for both inline and display (block) math
13
+ - Define custom LaTeX macros for extended functionality
14
+ - Global and local counter for numbered equations
15
+ - Pretty-printing option for readable MathML output
16
+ - Comprehensive error handling with descriptive error messages
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm i math-core
22
+ ```
23
+
24
+ > **Note:** This package is for Node.js (and compatible runtimes like Bun) only. It cannot be used in the browser, because it uses `readFileSync` from `node:fs` to load the underlying WASM module.
25
+
26
+ ## Quick Start
27
+
28
+ ```javascript
29
+ import { LatexToMathML } from "math-core";
30
+
31
+ const converter = new LatexToMathML({});
32
+
33
+ // Convert inline math
34
+ const inline = converter.convert_with_local_counter("x^2 + y^2 = z^2", false);
35
+ console.log(inline);
36
+ // Output: <math><msup><mi>x</mi><mn>2</mn></msup><mo>+</mo><msup><mi>y</mi><mn>2</mn></msup><mo>=</mo><msup><mi>z</mi><mn>2</mn></msup></math>
37
+
38
+ // Convert display math
39
+ const display = converter.convert_with_local_counter("\\frac{1}{2}", true);
40
+ console.log(display);
41
+ // Output: <math display="block"><mfrac><mn>1</mn><mn>2</mn></mfrac></math>
42
+ ```
43
+
44
+ ## Usage
45
+
46
+ ### Basic Usage
47
+
48
+ ```javascript
49
+ import { LatexToMathML } from "math-core";
50
+
51
+ const converter = new LatexToMathML({ prettyPrint: "always" });
52
+
53
+ try {
54
+ const mathml = converter.convert_with_local_counter("\\sqrt{x^2 + 1}", false);
55
+ console.log(mathml);
56
+ } catch (e) {
57
+ console.error(`Conversion error: ${e.message}`);
58
+ }
59
+ ```
60
+
61
+ ### Custom LaTeX Macros
62
+
63
+ Define custom macros to extend or modify LaTeX command behavior:
64
+
65
+ ```javascript
66
+ const macros = new Map();
67
+ macros.set("d", "\\mathrm{d}"); // Differential d
68
+ macros.set("R", "\\mathbb{R}"); // Real numbers
69
+ macros.set("vec", "\\mathbf{#1}"); // Vector notation
70
+
71
+ const converter = new LatexToMathML({ macros });
72
+ const mathml = converter.convert_with_local_counter("\\d x", false);
73
+ ```
74
+
75
+ ### Numbered Equations with Global Counter
76
+
77
+ For documents with multiple numbered equations:
78
+
79
+ ```javascript
80
+ const converter = new LatexToMathML({});
81
+
82
+ // First equation gets (1)
83
+ const eq1 = converter.convert_with_global_counter(
84
+ "\\begin{align}E = mc^2\\end{align}",
85
+ true,
86
+ );
87
+
88
+ // Second equation gets (2)
89
+ const eq2 = converter.convert_with_global_counter(
90
+ "\\begin{align}F = ma\\end{align}",
91
+ true,
92
+ );
93
+
94
+ // Reset counter when starting a new chapter/section
95
+ converter.reset_global_counter();
96
+
97
+ // This equation gets (1) again
98
+ const eq3 = converter.convert_with_global_counter(
99
+ "\\begin{align}p = mv\\end{align}",
100
+ true,
101
+ );
102
+ ```
103
+
104
+ ### Local Counter for Independent Numbering
105
+
106
+ Use local counters when equation numbers should restart within each conversion:
107
+
108
+ ```javascript
109
+ const converter = new LatexToMathML({});
110
+
111
+ // Each conversion has independent numbering
112
+ const doc1 = converter.convert_with_local_counter(
113
+ "\\begin{align}a &= b\\\\c &= d\\end{align}",
114
+ true,
115
+ ); // Contains (1) and (2)
116
+
117
+ const doc2 = converter.convert_with_local_counter(
118
+ "\\begin{align}x &= y\\\\z &= w\\end{align}",
119
+ true,
120
+ ); // Also contains (1) and (2)
121
+ ```
122
+
123
+ ### Error Handling
124
+
125
+ By default, conversion errors throw a `LatexError` with detailed diagnostics:
126
+
127
+ ```javascript
128
+ const converter = new LatexToMathML({});
129
+
130
+ try {
131
+ converter.convert_with_local_counter("\\begin{foobar}", false);
132
+ } catch (e) {
133
+ console.log(e.message); // 'Unknown environment "foobar".'
134
+ console.log(e.report); // Formatted diagnostic with source spans
135
+ console.log(e.context); // The relevant LaTeX source
136
+ console.log(e.start); // Start offset of the error
137
+ console.log(e.end); // End offset of the error
138
+ }
139
+ ```
140
+
141
+ Set `throwOnError: false` to return an HTML error snippet instead of throwing:
142
+
143
+ ```javascript
144
+ const converter = new LatexToMathML({ throwOnError: false });
145
+ const result = converter.convert_with_local_counter("\\invalid", false);
146
+ // Returns: <span class="math-core-error" title="..."><code>\invalid</code></span>
147
+ ```
148
+
149
+ ## API Reference
150
+
151
+ ### `LatexToMathML`
152
+
153
+ The main converter class.
154
+
155
+ **Constructor:**
156
+
157
+ ```typescript
158
+ new LatexToMathML(options: MathCoreOptions)
159
+ ```
160
+
161
+ **Options:**
162
+
163
+ | Option | Type | Default | Description |
164
+ |---|---|---|---|
165
+ | `prettyPrint` | `"never" \| "always" \| "auto"` | `"never"` | Whether to pretty-print the MathML output. `"auto"` pretty-prints block equations only. |
166
+ | `macros` | `Map<string, string>` | — | Custom LaTeX macros. |
167
+ | `xmlNamespace` | `boolean` | `false` | Include `xmlns="http://www.w3.org/1998/Math/MathML"` in the `<math>` tag. |
168
+ | `throwOnError` | `boolean` | `true` | Throw `LatexError` on conversion errors. If `false`, returns an HTML error snippet instead. |
169
+ | `ignoreUnknownCommands` | `boolean` | `false` | Render unknown commands as red text instead of erroring. |
170
+ | `annotation` | `boolean` | `false` | Include the original LaTeX as an annotation in the MathML output. |
171
+
172
+ **Methods:**
173
+
174
+ - `convert_with_global_counter(latex: string, displaystyle: boolean): string` — Convert LaTeX to MathML using a global equation counter.
175
+ - `convert_with_local_counter(latex: string, displaystyle: boolean): string` — Convert LaTeX to MathML using a local equation counter.
176
+ - `reset_global_counter(): void` — Reset the global equation counter to zero.
177
+
178
+ ### `LatexError`
179
+
180
+ Error thrown when LaTeX parsing or conversion fails.
181
+
182
+ **Properties:**
183
+
184
+ | Property | Type | Description |
185
+ |---|---|---|
186
+ | `message` | `string` | Description of the error. |
187
+ | `report` | `string \| undefined` | Formatted diagnostic report with source spans. |
188
+ | `context` | `string \| undefined` | The relevant LaTeX source. |
189
+ | `start` | `number` | Start offset of the error in the source. |
190
+ | `end` | `number` | End offset of the error in the source. |
191
+
192
+ ## Why MathML Core?
193
+
194
+ MathML Core is a carefully selected subset of MathML 4 that focuses on essential mathematical notation while ensuring consistent rendering across browsers. Unlike full MathML or JavaScript-based solutions:
195
+
196
+ - **Native browser support**: No JavaScript required
197
+ - **Accessibility**: Better screen reader support
198
+ - **Performance**: Faster rendering than JS solutions
199
+ - **SEO-friendly**: Search engines can index mathematical content
200
+ - **Future-proof**: Part of web standards with ongoing browser support
201
+
202
+ ## Browser Support
203
+
204
+ Firefox currently has the most complete support for MathML Core, with Chrome close behind. Safari has the least support and some rendering issues exist when using MathML Core, but it is improving with each release.
205
+
206
+ ## Contributing
207
+
208
+ Contributions are welcome! Please feel free to submit a Pull Request.
209
+
210
+ ## License
211
+
212
+ This project is licensed under the MIT License - see the LICENSE file for details.
@@ -8,6 +8,7 @@ interface MathCoreOptions {
8
8
  throwOnError?: boolean;
9
9
  ignoreUnknownCommands?: boolean;
10
10
  annotation?: boolean;
11
+ allowUnreliableRendering?: boolean;
11
12
  }
12
13
 
13
14
 
package/dist/math_core.js CHANGED
@@ -167,7 +167,11 @@ function __wbg_get_imports() {
167
167
  __wbg___wbindgen_throw_be289d5034ed271b: function(arg0, arg1) {
168
168
  throw new Error(getStringFromWasm0(arg0, arg1));
169
169
  },
170
- __wbg_annotation_0f240a9bc62ef511: function(arg0) {
170
+ __wbg_allowUnreliableRendering_b5f73be018b1a1f7: function(arg0) {
171
+ const ret = arg0.allowUnreliableRendering;
172
+ return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
173
+ },
174
+ __wbg_annotation_13d93d90da1897e4: function(arg0) {
171
175
  const ret = arg0.annotation;
172
176
  return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
173
177
  },
@@ -187,7 +191,7 @@ function __wbg_get_imports() {
187
191
  const ret = arg0[arg1 >>> 0];
188
192
  return ret;
189
193
  },
190
- __wbg_ignoreUnknownCommands_e2f38f95235accd2: function(arg0) {
194
+ __wbg_ignoreUnknownCommands_243d0f7135c2947f: function(arg0) {
191
195
  const ret = arg0.ignoreUnknownCommands;
192
196
  return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
193
197
  },
@@ -199,7 +203,7 @@ function __wbg_get_imports() {
199
203
  const ret = LatexError.__wrap(arg0);
200
204
  return ret;
201
205
  },
202
- __wbg_macros_4d915c0571da66e0: function(arg0) {
206
+ __wbg_macros_10ee7add3368cc46: function(arg0) {
203
207
  const ret = arg0.macros;
204
208
  return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
205
209
  },
@@ -207,7 +211,7 @@ function __wbg_get_imports() {
207
211
  const ret = arg0.next();
208
212
  return ret;
209
213
  }, arguments); },
210
- __wbg_prettyPrint_50b3da85527dbcc4: function(arg0, arg1) {
214
+ __wbg_prettyPrint_4613329951709336: function(arg0, arg1) {
211
215
  const ret = arg1.prettyPrint;
212
216
  var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
213
217
  var len1 = WASM_VECTOR_LEN;
@@ -218,7 +222,7 @@ function __wbg_get_imports() {
218
222
  const ret = arg0.size;
219
223
  return ret;
220
224
  },
221
- __wbg_throwOnError_48cbacea44678108: function(arg0) {
225
+ __wbg_throwOnError_3140ddd7aadfd89a: function(arg0) {
222
226
  const ret = arg0.throwOnError;
223
227
  return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
224
228
  },
@@ -226,7 +230,7 @@ function __wbg_get_imports() {
226
230
  const ret = arg0.value;
227
231
  return ret;
228
232
  },
229
- __wbg_xmlNamespace_87aeb5924c1bbfbe: function(arg0) {
233
+ __wbg_xmlNamespace_d5ce6698d3af3315: function(arg0) {
230
234
  const ret = arg0.xmlNamespace;
231
235
  return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
232
236
  },
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "math-core",
3
- "version": "0.5.4",
3
+ "version": "0.6.0",
4
4
  "description": "Convert LaTeX to MathML Core",
5
5
  "homepage": "https://github.com/tmke8/math-core#readme",
6
6
  "bugs": {