dwml-ts 0.4.0 → 0.4.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/README.md +178 -178
- package/dist/index.cjs +2495 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +114 -10
- package/dist/index.js.map +1 -1
- package/package.json +47 -37
package/README.md
CHANGED
|
@@ -1,178 +1,178 @@
|
|
|
1
|
-
# dwml-ts
|
|
2
|
-
|
|
3
|
-
Convert **MS Office OMML** (Office Math Markup Language, the `<m:oMath>` markup used
|
|
4
|
-
in `.docx` / `.pptx` / `.xlsx`) to **LaTeX** — in TypeScript.
|
|
5
|
-
|
|
6
|
-
A faithful port of the Python [`dwml`](https://github.com/xiilei/dwml) library with
|
|
7
|
-
**100% output fidelity** on its reference fixtures, hardened for real-world OOXML
|
|
8
|
-
import pipelines (PowerPoint, Word).
|
|
9
|
-
|
|
10
|
-
- **Pure, synchronous, deterministic** — no async, no config singletons.
|
|
11
|
-
- **DOM-free** — runs identically in the browser bundle and in Node. No
|
|
12
|
-
`DOMParser` / `XMLSerializer` / `xmldom`.
|
|
13
|
-
- **One tiny runtime dep**: [`txml`](https://github.com/TobiasNickel/tXml) for parsing
|
|
14
|
-
(which [PPTist](https://github.com/pipipi-pikachu/PPTist) already ships — zero new bytes).
|
|
15
|
-
- **Never throws on unknown constructs** — degrades per-node to concatenated text
|
|
16
|
-
content, so one odd `<m:oMath>` can't kill a whole paragraph import.
|
|
17
|
-
|
|
18
|
-
## Install
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
npm install dwml-ts
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## API
|
|
25
|
-
|
|
26
|
-
All output is **bare LaTeX** — no `$`/`$$` delimiters, no trailing whitespace. The
|
|
27
|
-
caller decides inline vs. display math (e.g. PPTist wraps it in its own
|
|
28
|
-
`span.pptist-math[data-latex]` element).
|
|
29
|
-
|
|
30
|
-
### `ommlToLatex(xml, options?): string`
|
|
31
|
-
|
|
32
|
-
Convert one OMML fragment to bare LaTeX. Accepts `<m:oMath>`, `<m:oMathPara>` or the
|
|
33
|
-
`<a14:m>` wrapper as an XML string, and tolerates **missing `xmlns` declarations**
|
|
34
|
-
(fragments sliced out of slide XML where the namespace lives on a root you don't have).
|
|
35
|
-
|
|
36
|
-
```ts
|
|
37
|
-
import { ommlToLatex } from 'dwml-ts';
|
|
38
|
-
|
|
39
|
-
ommlToLatex('<m:oMath><m:r><m:t>x+1</m:t></m:r></m:oMath>');
|
|
40
|
-
// => 'x+1'
|
|
41
|
-
|
|
42
|
-
ommlToLatex('<m:oMath><m:rad><m:radPr><m:degHide m:val="1"/></m:radPr><m:deg/><m:e><m:r><m:t>5</m:t></m:r></m:e></m:rad></m:oMath>');
|
|
43
|
-
// => '\\sqrt{5}'
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### `ommlNodeToLatex(node, options?): string`
|
|
47
|
-
|
|
48
|
-
Node-level entry: convert an **already-parsed txml `TNode`**. This is the important one
|
|
49
|
-
for import pipelines — walk each `<a:p>` of the slide XML yourself to preserve run order
|
|
50
|
-
(text run → math → text run), and pass math nodes straight in. One parse per slide, no
|
|
51
|
-
re-parsing fragments.
|
|
52
|
-
|
|
53
|
-
```ts
|
|
54
|
-
import { parse } from 'txml';
|
|
55
|
-
import { ommlNodeToLatex } from 'dwml-ts';
|
|
56
|
-
|
|
57
|
-
const nodes = parse(slideXml);
|
|
58
|
-
// ... find the <m:oMath> node(s) you care about, then:
|
|
59
|
-
const latex = ommlNodeToLatex(omathNode);
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### `extractOmmlLatex(xml, options?): string[]`
|
|
63
|
-
|
|
64
|
-
Batch: find and convert every `<m:oMath>` in any OOXML document/fragment, returning one
|
|
65
|
-
bare LaTeX string per formula, in document order.
|
|
66
|
-
|
|
67
|
-
```ts
|
|
68
|
-
import { extractOmmlLatex } from 'dwml-ts';
|
|
69
|
-
|
|
70
|
-
const [first, second] = extractOmmlLatex(documentXml);
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### `OmmlToLatexOptions`
|
|
74
|
-
|
|
75
|
-
```ts
|
|
76
|
-
export interface OmmlToLatexOptions {
|
|
77
|
-
/** Called once per element local-name the converter had to degrade. */
|
|
78
|
-
onUnsupported?: (localName: string) => void;
|
|
79
|
-
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## Behavior guarantees
|
|
83
|
-
|
|
84
|
-
| Guarantee | Notes |
|
|
85
|
-
| --- | --- |
|
|
86
|
-
| **Bare LaTeX out** | No delimiters, no trailing whitespace. |
|
|
87
|
-
| **Never throws** | Unknown constructs degrade per-node to concatenated text (`m:borderBox`, `m:phant`, unknown `m:fName`, unknown `m:limLow` base, …). A dropped `\frac` bar is recoverable; an exception is not. |
|
|
88
|
-
| **Namespace by local name** | Matches `oMath` / `f` / `r` / … regardless of prefix (`m:`, none, or re-prefixed). Real-world producers vary. |
|
|
89
|
-
| **Namespace-agnostic attributes** | `m:val` / `val` / re-prefixed attributes resolve by local name. |
|
|
90
|
-
|
|
91
|
-
## Supported OMML constructs
|
|
92
|
-
|
|
93
|
-
`m:oMath` / `m:oMathPara` / `<a14:m>` wrappers, and:
|
|
94
|
-
|
|
95
|
-
- **Runs** — `m:r` / `m:t` with Unicode→LaTeX symbol mapping (see below)
|
|
96
|
-
- **Fractions** — `m:f` with `m:fPr` types `bar` (default, `\frac`), `skw` (`^{n}/_{d}`),
|
|
97
|
-
`noBar` (`\genfrac`, binomial), `lin` (`{n}/{d}`)
|
|
98
|
-
- **Scripts** — `m:sSub`, `m:sSup`, `m:sSubSup` (and `m:sPre`, degraded)
|
|
99
|
-
- **Radicals** — `m:rad` with `m:deg` and `degHide` (`\sqrt`, `\sqrt[n]`)
|
|
100
|
-
- **N-ary** — `m:nary` (`\sum`, `\int`, `\prod`, … via `CHR_BO`)
|
|
101
|
-
- **Delimiters** — `m:d` with `begChr` / `endChr` / `sepChr` (`\left…\right`)
|
|
102
|
-
- **Functions** — `m:func` / `m:fName` (`\sin`, `\cos`, `\log`, `\ln`, …)
|
|
103
|
-
- **Accents** — `m:acc` (`\hat`, `\tilde`, `\vec`, … via `CHR`)
|
|
104
|
-
- **Bars** — `m:bar` (`\overline` / `\underline`)
|
|
105
|
-
- **Limits** — `m:limLow` (`\lim_{…}`), `m:limUpp` (`\overset`)
|
|
106
|
-
- **Matrix** — `m:m` / `m:mr` (`\begin{matrix}…\end{matrix}`)
|
|
107
|
-
- **Equation array** — `m:eqArr` (`\begin{array}{c}…\end{array}`)
|
|
108
|
-
- **Group char** — `m:groupChr` (`\overbrace`, `\underbrace`, …)
|
|
109
|
-
- **Box** — `m:box` (passthrough)
|
|
110
|
-
|
|
111
|
-
## Unicode → LaTeX mapping
|
|
112
|
-
|
|
113
|
-
Run text is mapped to LaTeX with a two-tier lookup (per Unicode code point, so
|
|
114
|
-
astral-plane Mathematical Alphanumeric Symbols are handled correctly):
|
|
115
|
-
|
|
116
|
-
1. **dwml's symbol table** (`src/latex-dict.ts`) — Mathematical Alphanumeric Symbols
|
|
117
|
-
`U+1D400–U+1D7FF` → ASCII (`𝐴→A`, `𝑥→x`), Greek (`π→\pi`, both plain `U+03B1..` and
|
|
118
|
-
math-italic `U+1D6FC..`), relation/operator symbols (`≤→\leq`, `≥→\geq`, `≠→\ne`,
|
|
119
|
-
`·→\cdot`, `×→\times`, `∞→\infty`, `→→\rightarrow`, …).
|
|
120
|
-
2. **pylatexenc's builtin map** (`src/uni2latex.generated.ts`, internalized from
|
|
121
|
-
pylatexenc 2.x, MIT) — everything else with a known LaTeX escape.
|
|
122
|
-
|
|
123
|
-
LaTeX-special characters in runs (`%`, `&`, `_`, `{`, `}`, `#`, `$`, `~`, `^`) are escaped
|
|
124
|
-
via dwml's `escape_latex` (`a%` → `a\%`).
|
|
125
|
-
|
|
126
|
-
## Examples
|
|
127
|
-
|
|
128
|
-
| OMML input | LaTeX output |
|
|
129
|
-
| --- | --- |
|
|
130
|
-
| `\sin(\sqrt[3]{x})^{x^{11}}/_{b}x_{m}^{n}` fixture | `\sin(\sqrt[3]{x})^{x^{11}}/_{b}x_{m}^{n}` |
|
|
131
|
-
| group fixture | `A\overbrace{123}\underbrace{456}=\left\{a+b\right)` |
|
|
132
|
-
| matrix fixture | `A=\left(\begin{matrix}1&2&3\\4&5&6\end{matrix}\right)\sum_{1}^{20}x` |
|
|
133
|
-
| no-bar fraction (binomial) | `\left(x+a\right)^{n}=\sum_{k=0}^{n}\left(\genfrac{}{}{0pt}{}{n}{k}\right)x^{k}a^{n-k}` |
|
|
134
|
-
|
|
135
|
-
## Project layout
|
|
136
|
-
|
|
137
|
-
```
|
|
138
|
-
src/
|
|
139
|
-
index.ts public API (ommlToLatex / ommlNodeToLatex / extractOmmlLatex)
|
|
140
|
-
omml.ts the converter (never-throw, namespace-agnostic)
|
|
141
|
-
latex-dict.ts dwml symbol dictionaries
|
|
142
|
-
latex-encode.ts pylatexenc-derived unicode->latex encoder
|
|
143
|
-
uni2latex.generated.ts generated pylatexenc map (do not edit by hand)
|
|
144
|
-
tests/
|
|
145
|
-
api.test.ts consumer contract + dwml reference fidelity
|
|
146
|
-
constructs.test.ts per-construct coverage
|
|
147
|
-
ground-truth.json Python dwml reference outputs
|
|
148
|
-
reference/ original Python sources (base + two forks + canonical merge)
|
|
149
|
-
scripts/
|
|
150
|
-
gen_uni2latex.py regenerate the unicode map from pylatexenc
|
|
151
|
-
gen_ground_truth.py regenerate tests/ground-truth.json from Python dwml
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## Development
|
|
155
|
-
|
|
156
|
-
```bash
|
|
157
|
-
npm install
|
|
158
|
-
npm test # rstest
|
|
159
|
-
npm run build # rslib -> dist/{index.js,index.d.ts} (ESM only)
|
|
160
|
-
|
|
161
|
-
# regenerate the unicode map / ground truth (requires Python + pylatexenc)
|
|
162
|
-
npm run gen:unicode
|
|
163
|
-
npm run gen:groundtruth
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
## Attribution
|
|
167
|
-
|
|
168
|
-
- Port of [`dwml`](https://github.com/xiilei/dwml) (Apache-2.0), incorporating fixes from
|
|
169
|
-
the [`xavier-bw/dwml`](https://github.com/xavier-bw/dwml) fork (log/ln functions) and
|
|
170
|
-
[`bazingarj/OMML-to-Latex-py`](https://github.com/bazingarj/OMML-to-Latex-py) fork
|
|
171
|
-
(whitespace-tolerant function names). Test fixtures under `reference/tests-base/` are
|
|
172
|
-
Apache-2.0, from the original project.
|
|
173
|
-
- The Unicode→LaTeX map is derived from [`pylatexenc`](https://github.com/phfaist/pylatexenc)
|
|
174
|
-
(MIT, © Philippe Faist).
|
|
175
|
-
|
|
176
|
-
## License
|
|
177
|
-
|
|
178
|
-
Apache-2.0
|
|
1
|
+
# dwml-ts
|
|
2
|
+
|
|
3
|
+
Convert **MS Office OMML** (Office Math Markup Language, the `<m:oMath>` markup used
|
|
4
|
+
in `.docx` / `.pptx` / `.xlsx`) to **LaTeX** — in TypeScript.
|
|
5
|
+
|
|
6
|
+
A faithful port of the Python [`dwml`](https://github.com/xiilei/dwml) library with
|
|
7
|
+
**100% output fidelity** on its reference fixtures, hardened for real-world OOXML
|
|
8
|
+
import pipelines (PowerPoint, Word).
|
|
9
|
+
|
|
10
|
+
- **Pure, synchronous, deterministic** — no async, no config singletons.
|
|
11
|
+
- **DOM-free** — runs identically in the browser bundle and in Node. No
|
|
12
|
+
`DOMParser` / `XMLSerializer` / `xmldom`.
|
|
13
|
+
- **One tiny runtime dep**: [`txml`](https://github.com/TobiasNickel/tXml) for parsing
|
|
14
|
+
(which [PPTist](https://github.com/pipipi-pikachu/PPTist) already ships — zero new bytes).
|
|
15
|
+
- **Never throws on unknown constructs** — degrades per-node to concatenated text
|
|
16
|
+
content, so one odd `<m:oMath>` can't kill a whole paragraph import.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install dwml-ts
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## API
|
|
25
|
+
|
|
26
|
+
All output is **bare LaTeX** — no `$`/`$$` delimiters, no trailing whitespace. The
|
|
27
|
+
caller decides inline vs. display math (e.g. PPTist wraps it in its own
|
|
28
|
+
`span.pptist-math[data-latex]` element).
|
|
29
|
+
|
|
30
|
+
### `ommlToLatex(xml, options?): string`
|
|
31
|
+
|
|
32
|
+
Convert one OMML fragment to bare LaTeX. Accepts `<m:oMath>`, `<m:oMathPara>` or the
|
|
33
|
+
`<a14:m>` wrapper as an XML string, and tolerates **missing `xmlns` declarations**
|
|
34
|
+
(fragments sliced out of slide XML where the namespace lives on a root you don't have).
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { ommlToLatex } from 'dwml-ts';
|
|
38
|
+
|
|
39
|
+
ommlToLatex('<m:oMath><m:r><m:t>x+1</m:t></m:r></m:oMath>');
|
|
40
|
+
// => 'x+1'
|
|
41
|
+
|
|
42
|
+
ommlToLatex('<m:oMath><m:rad><m:radPr><m:degHide m:val="1"/></m:radPr><m:deg/><m:e><m:r><m:t>5</m:t></m:r></m:e></m:rad></m:oMath>');
|
|
43
|
+
// => '\\sqrt{5}'
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### `ommlNodeToLatex(node, options?): string`
|
|
47
|
+
|
|
48
|
+
Node-level entry: convert an **already-parsed txml `TNode`**. This is the important one
|
|
49
|
+
for import pipelines — walk each `<a:p>` of the slide XML yourself to preserve run order
|
|
50
|
+
(text run → math → text run), and pass math nodes straight in. One parse per slide, no
|
|
51
|
+
re-parsing fragments.
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { parse } from 'txml';
|
|
55
|
+
import { ommlNodeToLatex } from 'dwml-ts';
|
|
56
|
+
|
|
57
|
+
const nodes = parse(slideXml);
|
|
58
|
+
// ... find the <m:oMath> node(s) you care about, then:
|
|
59
|
+
const latex = ommlNodeToLatex(omathNode);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### `extractOmmlLatex(xml, options?): string[]`
|
|
63
|
+
|
|
64
|
+
Batch: find and convert every `<m:oMath>` in any OOXML document/fragment, returning one
|
|
65
|
+
bare LaTeX string per formula, in document order.
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { extractOmmlLatex } from 'dwml-ts';
|
|
69
|
+
|
|
70
|
+
const [first, second] = extractOmmlLatex(documentXml);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### `OmmlToLatexOptions`
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
export interface OmmlToLatexOptions {
|
|
77
|
+
/** Called once per element local-name the converter had to degrade. */
|
|
78
|
+
onUnsupported?: (localName: string) => void;
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Behavior guarantees
|
|
83
|
+
|
|
84
|
+
| Guarantee | Notes |
|
|
85
|
+
| --- | --- |
|
|
86
|
+
| **Bare LaTeX out** | No delimiters, no trailing whitespace. |
|
|
87
|
+
| **Never throws** | Unknown constructs degrade per-node to concatenated text (`m:borderBox`, `m:phant`, unknown `m:fName`, unknown `m:limLow` base, …). A dropped `\frac` bar is recoverable; an exception is not. |
|
|
88
|
+
| **Namespace by local name** | Matches `oMath` / `f` / `r` / … regardless of prefix (`m:`, none, or re-prefixed). Real-world producers vary. |
|
|
89
|
+
| **Namespace-agnostic attributes** | `m:val` / `val` / re-prefixed attributes resolve by local name. |
|
|
90
|
+
|
|
91
|
+
## Supported OMML constructs
|
|
92
|
+
|
|
93
|
+
`m:oMath` / `m:oMathPara` / `<a14:m>` wrappers, and:
|
|
94
|
+
|
|
95
|
+
- **Runs** — `m:r` / `m:t` with Unicode→LaTeX symbol mapping (see below)
|
|
96
|
+
- **Fractions** — `m:f` with `m:fPr` types `bar` (default, `\frac`), `skw` (`^{n}/_{d}`),
|
|
97
|
+
`noBar` (`\genfrac`, binomial), `lin` (`{n}/{d}`)
|
|
98
|
+
- **Scripts** — `m:sSub`, `m:sSup`, `m:sSubSup` (and `m:sPre`, degraded)
|
|
99
|
+
- **Radicals** — `m:rad` with `m:deg` and `degHide` (`\sqrt`, `\sqrt[n]`)
|
|
100
|
+
- **N-ary** — `m:nary` (`\sum`, `\int`, `\prod`, … via `CHR_BO`)
|
|
101
|
+
- **Delimiters** — `m:d` with `begChr` / `endChr` / `sepChr` (`\left…\right`)
|
|
102
|
+
- **Functions** — `m:func` / `m:fName` (`\sin`, `\cos`, `\log`, `\ln`, …)
|
|
103
|
+
- **Accents** — `m:acc` (`\hat`, `\tilde`, `\vec`, … via `CHR`)
|
|
104
|
+
- **Bars** — `m:bar` (`\overline` / `\underline`)
|
|
105
|
+
- **Limits** — `m:limLow` (`\lim_{…}`), `m:limUpp` (`\overset`)
|
|
106
|
+
- **Matrix** — `m:m` / `m:mr` (`\begin{matrix}…\end{matrix}`)
|
|
107
|
+
- **Equation array** — `m:eqArr` (`\begin{array}{c}…\end{array}`)
|
|
108
|
+
- **Group char** — `m:groupChr` (`\overbrace`, `\underbrace`, …)
|
|
109
|
+
- **Box** — `m:box` (passthrough)
|
|
110
|
+
|
|
111
|
+
## Unicode → LaTeX mapping
|
|
112
|
+
|
|
113
|
+
Run text is mapped to LaTeX with a two-tier lookup (per Unicode code point, so
|
|
114
|
+
astral-plane Mathematical Alphanumeric Symbols are handled correctly):
|
|
115
|
+
|
|
116
|
+
1. **dwml's symbol table** (`src/latex-dict.ts`) — Mathematical Alphanumeric Symbols
|
|
117
|
+
`U+1D400–U+1D7FF` → ASCII (`𝐴→A`, `𝑥→x`), Greek (`π→\pi`, both plain `U+03B1..` and
|
|
118
|
+
math-italic `U+1D6FC..`), relation/operator symbols (`≤→\leq`, `≥→\geq`, `≠→\ne`,
|
|
119
|
+
`·→\cdot`, `×→\times`, `∞→\infty`, `→→\rightarrow`, …).
|
|
120
|
+
2. **pylatexenc's builtin map** (`src/uni2latex.generated.ts`, internalized from
|
|
121
|
+
pylatexenc 2.x, MIT) — everything else with a known LaTeX escape.
|
|
122
|
+
|
|
123
|
+
LaTeX-special characters in runs (`%`, `&`, `_`, `{`, `}`, `#`, `$`, `~`, `^`) are escaped
|
|
124
|
+
via dwml's `escape_latex` (`a%` → `a\%`).
|
|
125
|
+
|
|
126
|
+
## Examples
|
|
127
|
+
|
|
128
|
+
| OMML input | LaTeX output |
|
|
129
|
+
| --- | --- |
|
|
130
|
+
| `\sin(\sqrt[3]{x})^{x^{11}}/_{b}x_{m}^{n}` fixture | `\sin(\sqrt[3]{x})^{x^{11}}/_{b}x_{m}^{n}` |
|
|
131
|
+
| group fixture | `A\overbrace{123}\underbrace{456}=\left\{a+b\right)` |
|
|
132
|
+
| matrix fixture | `A=\left(\begin{matrix}1&2&3\\4&5&6\end{matrix}\right)\sum_{1}^{20}x` |
|
|
133
|
+
| no-bar fraction (binomial) | `\left(x+a\right)^{n}=\sum_{k=0}^{n}\left(\genfrac{}{}{0pt}{}{n}{k}\right)x^{k}a^{n-k}` |
|
|
134
|
+
|
|
135
|
+
## Project layout
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
src/
|
|
139
|
+
index.ts public API (ommlToLatex / ommlNodeToLatex / extractOmmlLatex)
|
|
140
|
+
omml.ts the converter (never-throw, namespace-agnostic)
|
|
141
|
+
latex-dict.ts dwml symbol dictionaries
|
|
142
|
+
latex-encode.ts pylatexenc-derived unicode->latex encoder
|
|
143
|
+
uni2latex.generated.ts generated pylatexenc map (do not edit by hand)
|
|
144
|
+
tests/
|
|
145
|
+
api.test.ts consumer contract + dwml reference fidelity
|
|
146
|
+
constructs.test.ts per-construct coverage
|
|
147
|
+
ground-truth.json Python dwml reference outputs
|
|
148
|
+
reference/ original Python sources (base + two forks + canonical merge)
|
|
149
|
+
scripts/
|
|
150
|
+
gen_uni2latex.py regenerate the unicode map from pylatexenc
|
|
151
|
+
gen_ground_truth.py regenerate tests/ground-truth.json from Python dwml
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Development
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npm install
|
|
158
|
+
npm test # rstest
|
|
159
|
+
npm run build # rslib -> dist/{index.js,index.d.ts} (ESM only)
|
|
160
|
+
|
|
161
|
+
# regenerate the unicode map / ground truth (requires Python + pylatexenc)
|
|
162
|
+
npm run gen:unicode
|
|
163
|
+
npm run gen:groundtruth
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Attribution
|
|
167
|
+
|
|
168
|
+
- Port of [`dwml`](https://github.com/xiilei/dwml) (Apache-2.0), incorporating fixes from
|
|
169
|
+
the [`xavier-bw/dwml`](https://github.com/xavier-bw/dwml) fork (log/ln functions) and
|
|
170
|
+
[`bazingarj/OMML-to-Latex-py`](https://github.com/bazingarj/OMML-to-Latex-py) fork
|
|
171
|
+
(whitespace-tolerant function names). Test fixtures under `reference/tests-base/` are
|
|
172
|
+
Apache-2.0, from the original project.
|
|
173
|
+
- The Unicode→LaTeX map is derived from [`pylatexenc`](https://github.com/phfaist/pylatexenc)
|
|
174
|
+
(MIT, © Philippe Faist).
|
|
175
|
+
|
|
176
|
+
## License
|
|
177
|
+
|
|
178
|
+
Apache-2.0
|