math-core 0.5.4 → 0.5.5
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 +212 -0
- package/dist/math_core.js +6 -6
- package/dist/math_core_bg.wasm +0 -0
- package/package.json +1 -1
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.
|
package/dist/math_core.js
CHANGED
|
@@ -167,7 +167,7 @@ function __wbg_get_imports() {
|
|
|
167
167
|
__wbg___wbindgen_throw_be289d5034ed271b: function(arg0, arg1) {
|
|
168
168
|
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
169
169
|
},
|
|
170
|
-
|
|
170
|
+
__wbg_annotation_3729a93467c2a7e2: function(arg0) {
|
|
171
171
|
const ret = arg0.annotation;
|
|
172
172
|
return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
|
|
173
173
|
},
|
|
@@ -187,7 +187,7 @@ function __wbg_get_imports() {
|
|
|
187
187
|
const ret = arg0[arg1 >>> 0];
|
|
188
188
|
return ret;
|
|
189
189
|
},
|
|
190
|
-
|
|
190
|
+
__wbg_ignoreUnknownCommands_8103fe9dca3ebf56: function(arg0) {
|
|
191
191
|
const ret = arg0.ignoreUnknownCommands;
|
|
192
192
|
return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
|
|
193
193
|
},
|
|
@@ -199,7 +199,7 @@ function __wbg_get_imports() {
|
|
|
199
199
|
const ret = LatexError.__wrap(arg0);
|
|
200
200
|
return ret;
|
|
201
201
|
},
|
|
202
|
-
|
|
202
|
+
__wbg_macros_f3b2728f74b026de: function(arg0) {
|
|
203
203
|
const ret = arg0.macros;
|
|
204
204
|
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
|
205
205
|
},
|
|
@@ -207,7 +207,7 @@ function __wbg_get_imports() {
|
|
|
207
207
|
const ret = arg0.next();
|
|
208
208
|
return ret;
|
|
209
209
|
}, arguments); },
|
|
210
|
-
|
|
210
|
+
__wbg_prettyPrint_8d18909f3209309b: function(arg0, arg1) {
|
|
211
211
|
const ret = arg1.prettyPrint;
|
|
212
212
|
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
213
213
|
var len1 = WASM_VECTOR_LEN;
|
|
@@ -218,7 +218,7 @@ function __wbg_get_imports() {
|
|
|
218
218
|
const ret = arg0.size;
|
|
219
219
|
return ret;
|
|
220
220
|
},
|
|
221
|
-
|
|
221
|
+
__wbg_throwOnError_87df5074a88bb287: function(arg0) {
|
|
222
222
|
const ret = arg0.throwOnError;
|
|
223
223
|
return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
|
|
224
224
|
},
|
|
@@ -226,7 +226,7 @@ function __wbg_get_imports() {
|
|
|
226
226
|
const ret = arg0.value;
|
|
227
227
|
return ret;
|
|
228
228
|
},
|
|
229
|
-
|
|
229
|
+
__wbg_xmlNamespace_bfd87d5bd54f31d1: function(arg0) {
|
|
230
230
|
const ret = arg0.xmlNamespace;
|
|
231
231
|
return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
|
|
232
232
|
},
|
package/dist/math_core_bg.wasm
CHANGED
|
Binary file
|