@webc.site/math 0.1.20 → 0.1.22
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 +95 -783
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,882 +4,194 @@
|
|
|
4
4
|
|
|
5
5
|
<a id="en"></a>
|
|
6
6
|
|
|
7
|
-
# @webc.site/math
|
|
7
|
+
# @webc.site/math : The world's smallest and fastest web Markdown formula renderer
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## 1. Features
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
<a href="https://github.com/webc-site/math" target="_blank"><img src="https://raw.githubusercontent.com/webc-site/math/dev/readme/en/svg/badge.github.svg" alt="github" /></a>
|
|
14
|
-
|
|
15
|
-
<a href="https://math.webc.site" target="_blank"><img src="https://raw.githubusercontent.com/webc-site/math/dev/readme/en/svg/badge.demo.svg" alt="demo" /></a>
|
|
11
|
+
This project compiles LaTeX math formulas into browser-native MathML Core markup, achieving zero-overhead rendering without client-side layout engines.
|
|
16
12
|
|
|
17
|
-
|
|
13
|
+
- **High Performance**: Compiles TeX formulas directly to native MathML. Processing speed reaches ~329,000 operations per second, which is approximately 3.6 times faster than KaTeX and 48 times faster than MathJax.
|
|
14
|
+
- **Ultra-lightweight**: The package size is 7.78 KB (3.58 KB gzipped), minimizing initial page load times.
|
|
15
|
+
- **Zero Runtime Dependencies**: Renders math using the browser's native C++ layout engine instead of loading heavy client-side JavaScript formatting libraries.
|
|
16
|
+
- **Robust Fault Tolerance**: Automatically catches syntax errors like unclosed brackets, reverting to raw TeX string output to prevent application crashes.
|
|
17
|
+
- **Universal Compatibility**: Generates standard MathML tags suitable for Server-Side Rendering (SSR), Static Site Generation (SSG), and Client-Side Rendering (CSR).
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
- [What is MathML?](#what-is-mathml)
|
|
21
|
-
- [Why Compile TeX Formulas to MathML?](#why-compile-tex-formulas-to-mathml)
|
|
22
|
-
- [Benchmark](#benchmark)
|
|
23
|
-
- [1. Size Comparison (Gzipped)](#1-size-comparison-gzipped)
|
|
24
|
-
- [2. Generation Speed (Ops/sec)](#2-generation-speed-opssec)
|
|
25
|
-
- [Usage](#usage)
|
|
26
|
-
- [JavaScript Examples](#javascript-examples)
|
|
27
|
-
- [CSS and Math Font Configuration](#css-and-math-font-configuration)
|
|
28
|
-
- [Markdown Parser Plugins](#markdown-parser-plugins)
|
|
29
|
-
- [Features](#features)
|
|
30
|
-
- [Supported Syntax List](#supported-syntax-list)
|
|
31
|
-
- [Unsupported Syntax](#unsupported-syntax)
|
|
32
|
-
- [Error Handling and Fault Tolerance](#error-handling-and-fault-tolerance)
|
|
33
|
-
- [Internal Error Codes](#internal-error-codes)
|
|
34
|
-
- [Design and Workflow](#design-and-workflow)
|
|
35
|
-
- [Module Stages](#module-stages)
|
|
36
|
-
- [Adding New Syntax](#adding-new-syntax)
|
|
37
|
-
- [1. Constant Definitions](#1-constant-definitions)
|
|
38
|
-
- [2. Lexer](#2-lexer)
|
|
39
|
-
- [3. Parser](#3-parser)
|
|
40
|
-
- [4. Codegen](#4-codegen)
|
|
41
|
-
- [Tech Stack](#tech-stack)
|
|
42
|
-
- [Directory Structure](#directory-structure)
|
|
43
|
-
- [Historical Background](#historical-background)
|
|
19
|
+
## 2. Usage
|
|
44
20
|
|
|
45
|
-
|
|
21
|
+
### Compilation Examples
|
|
46
22
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
MathML (Mathematical Markup Language) is an XML-based standard for describing math formulas on the Web.
|
|
50
|
-
Since January 2023 (following Chrome 109's native support for MathML Core), all major browser engines (Blink, Gecko, WebKit) natively support MathML. Pages can render formulas without loading third-party JavaScript layout libraries.
|
|
51
|
-
|
|
52
|
-
### Why Compile TeX Formulas to MathML?
|
|
53
|
-
|
|
54
|
-
While MathML renders natively, its XML-based syntax is too verbose for direct writing. TeX remains the standard for authoring formulas (e.g., `$e^{i\pi} + 1 = 0$`).
|
|
55
|
-
Traditional solutions (like MathJax or KaTeX) require loading hundreds of KB of JS/CSS layout engines and consume CPU for DOM calculations.
|
|
56
|
-
`@webc.site/math` compiles TeX to MathML, offering several advantages for Client-Side Rendering (CSR):
|
|
57
|
-
|
|
58
|
-
- **Lightweight**: Only 7.78 KB raw size (3.58 KB gzipped), with zero footprint on initial page load times.
|
|
59
|
-
- **Zero Runtime Dependencies**: Performs translation at compile time, delegating all rendering, positioning, and layout to the browser's native C++ engine. No JS layout engine runs on the client.
|
|
60
|
-
- **Low CPU Overhead**: Designed for high-frequency rendering scenarios like WYSIWYG editors, running smoothly even on low-end mobile devices.
|
|
61
|
-
- **SSR-Friendly**: Outputs standard HTML MathML tags, working identically for client-side dynamic rendering or static server-side building (SSR/SSG).
|
|
62
|
-
|
|
63
|
-
## Benchmark
|
|
64
|
-
|
|
65
|
-
### 1. Size Comparison (Gzipped)
|
|
66
|
-
|
|
67
|
-
| Library | Raw Size | Gzip Size | Size Ratio |
|
|
68
|
-
| :---------------------------------------------------------- | :-------: | :-------: | :--------: |
|
|
69
|
-
| [@webc.site/math](https://github.com/webc-site/math) (Ours) | 7.78 KB | 3.58 KB | 1.0 ⭐️ |
|
|
70
|
-
| [KaTeX](https://github.com/KaTeX/KaTeX) | 264.79 KB | 75.15 KB | 21.0 |
|
|
71
|
-
| [MathJax](https://github.com/mathjax/MathJax) | 971.04 KB | 278.39 KB | 77.7 |
|
|
72
|
-
|
|
73
|
-

|
|
74
|
-
|
|
75
|
-
### 2. Generation Speed (Ops/sec)
|
|
76
|
-
|
|
77
|
-
Based on compiling standard test equations (measured using [sh/bench/pk.js](https://github.com/webc-site/math/blob/dev/sh/bench/pk.js)):
|
|
78
|
-
|
|
79
|
-
- **@webc.site/math (Ours)**: ~329,000 ops/s (1.0 ⭐️)
|
|
80
|
-
- **[KaTeX](https://github.com/KaTeX/KaTeX)**: ~92,000 ops/s (~3.6x slower)
|
|
81
|
-
- **[MathJax](https://github.com/mathjax/MathJax)**: ~6,700 ops/s (~48.8x slower)
|
|
82
|
-
|
|
83
|
-

|
|
84
|
-
|
|
85
|
-
## Usage
|
|
86
|
-
|
|
87
|
-
### JavaScript Examples
|
|
88
|
-
|
|
89
|
-
#### 1. Render TeX Formulas Directly
|
|
90
|
-
|
|
91
|
-
Use `@webc.site/math` to compile TeX formulas directly into MathML (ideal for Markdown parser plugins):
|
|
23
|
+
#### Render TeX Formulas Directly
|
|
92
24
|
|
|
93
25
|
```javascript
|
|
94
26
|
import mathml from "@webc.site/math";
|
|
95
27
|
|
|
96
|
-
const
|
|
97
|
-
const html = mathml(tex, true); // true for block math, false/empty for inline math
|
|
28
|
+
const html = mathml("e^{i\\pi} + 1 = 0", true); // Second parameter sets block style
|
|
98
29
|
```
|
|
99
30
|
|
|
100
|
-
####
|
|
101
|
-
|
|
102
|
-
Use `@webc.site/math/md.js` to automatically detect and replace inline/block formulas in Markdown text with MathML (requires passing the math compiler):
|
|
31
|
+
#### Replace Formulas in Markdown Text
|
|
103
32
|
|
|
104
33
|
```javascript
|
|
105
34
|
import mdMath from "@webc.site/math/md.js";
|
|
106
35
|
import compile from "@webc.site/math";
|
|
107
36
|
|
|
108
|
-
const
|
|
109
|
-
const html = mdMath(markdown, compile);
|
|
110
|
-
|
|
111
|
-
console.log(html);
|
|
112
|
-
// Output: Euler's identity: <math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msup><mi>e</mi><mrow><mi>i</mi><mi>π</mi></mrow></msup><mo>+</mo><mn>1</mn><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">e^{i\pi} + 1 = 0</annotation></semantics></math>
|
|
37
|
+
const html = mdMath("Euler's identity: $$e^{i\\pi} + 1 = 0$$", compile);
|
|
113
38
|
```
|
|
114
39
|
|
|
115
|
-
###
|
|
40
|
+
### Font and CSS Configuration
|
|
116
41
|
|
|
117
|
-
To ensure
|
|
42
|
+
To ensure optimal layout and typesetting, configure math fonts. It is recommended to use the OpenType **Latin Modern Math** font from the `18s` package.
|
|
118
43
|
|
|
119
|
-
####
|
|
120
|
-
|
|
121
|
-
Import the online font in CSS:
|
|
122
|
-
|
|
123
|
-
```css
|
|
124
|
-
/* Import the bundle (includes Source Han Sans t, monospace c, and math font m) */
|
|
125
|
-
@import url("//registry.npmmirror.com/18s/0.2.24/files/_.css");
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
Or import the math font `m` only:
|
|
129
|
-
|
|
130
|
-
```css
|
|
131
|
-
@import url("//registry.npmmirror.com/18s/0.2.24/files/m.css");
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
#### 2. Configure CSS Style
|
|
135
|
-
|
|
136
|
-
Set the font family for the `math` tag in your global CSS stylesheet.
|
|
137
|
-
|
|
138
|
-
##### Option A: Using Online Fonts (Recommended for best visual quality)
|
|
139
|
-
|
|
140
|
-
For projects importing the `18s` font assets (which contains the optimized math font `m` and Source Han Sans `t`):
|
|
44
|
+
#### CSS Font Styling
|
|
141
45
|
|
|
142
46
|
```css
|
|
143
47
|
math {
|
|
144
|
-
/* m is the math font, t is Source Han Sans (optimized with font slicing for Chinese characters to boost loading performance), math is system math font, sans-serif is default fallback */
|
|
145
48
|
font-family: m, t, math, sans-serif;
|
|
146
49
|
}
|
|
147
50
|
```
|
|
148
51
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
Leverage system-default math fonts to minimize loading size:
|
|
152
|
-
|
|
153
|
-
```css
|
|
154
|
-
math {
|
|
155
|
-
/* Prioritize system-built-in math fonts, fallback to standard CSS 'math' generic font family, and use sans-serif as a final fallback */
|
|
156
|
-
font-family: "STIX Two Math", "Latin Modern Math", "Cambria Math", math, sans-serif;
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
#### 3. Integration with Build Tools
|
|
161
|
-
|
|
162
|
-
Install the `18s` font package via npm, and import it at your project entry using build tools like Vite or Webpack:
|
|
163
|
-
|
|
164
|
-
```bash
|
|
165
|
-
npm install 18s
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
Import font styles in your project entry file:
|
|
169
|
-
|
|
170
|
-
##### Method A: Import in JS/TS Entry File
|
|
171
|
-
|
|
172
|
-
```javascript
|
|
173
|
-
// Import the bundle (includes Source Han Sans t, monospace c, and math font m)
|
|
174
|
-
import "18s/_.css";
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
Or import math font `m` only:
|
|
178
|
-
|
|
179
|
-
```javascript
|
|
180
|
-
import "18s/m.css";
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
##### Method B: Import in CSS Stylesheet
|
|
184
|
-
|
|
185
|
-
```css
|
|
186
|
-
/* Import the bundle (includes Source Han Sans t, monospace c, and math font m) */
|
|
187
|
-
@import "18s/_.css";
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
Or import math font `m` only:
|
|
191
|
-
|
|
192
|
-
```css
|
|
193
|
-
@import "18s/m.css";
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### Markdown Parser Plugins
|
|
197
|
-
|
|
198
|
-
#### 1. Marked Extension
|
|
199
|
-
|
|
200
|
-
Use [`@webc.site/math-marked`](https://www.npmjs.com/package/@webc.site/math-marked) to automatically parse and compile inline (`$...$`) and block (`$$...$$`) formulas:
|
|
201
|
-
|
|
202
|
-
```javascript
|
|
203
|
-
import { marked } from "marked";
|
|
204
|
-
import mathMarked from "@webc.site/math-marked";
|
|
205
|
-
|
|
206
|
-
marked.use(mathMarked());
|
|
207
|
-
|
|
208
|
-
const html = marked.parse("Euler's identity: $$e^{i\\pi} + 1 = 0$$");
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
#### 2. Remark Plugin
|
|
212
|
-
|
|
213
|
-
Use [`@webc.site/math-remark`](https://www.npmjs.com/package/@webc.site/math-remark) to replace `inlineMath` and `math` nodes in Unified/Remark AST with native MathML HTML:
|
|
214
|
-
|
|
215
|
-
```javascript
|
|
216
|
-
import { unified } from "unified";
|
|
217
|
-
import remarkParse from "remark-parse";
|
|
218
|
-
import remarkMath from "remark-math";
|
|
219
|
-
import mathRemark from "@webc.site/math-remark";
|
|
220
|
-
import remarkHtml from "remark-html";
|
|
221
|
-
|
|
222
|
-
const html = await unified()
|
|
223
|
-
.use(remarkParse)
|
|
224
|
-
.use(remarkMath)
|
|
225
|
-
.use(mathRemark)
|
|
226
|
-
.use(remarkHtml, { sanitize: false })
|
|
227
|
-
.process("Euler's identity: $$e^{i\\pi} + 1 = 0$$");
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
#### 3. Markdown-it Plugin
|
|
52
|
+
## 3. Design
|
|
231
53
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
```javascript
|
|
235
|
-
import markdownit from "markdown-it";
|
|
236
|
-
import mathMarkdownIt from "@webc.site/math-markdown-it";
|
|
237
|
-
|
|
238
|
-
const md = markdownit().use(mathMarkdownIt);
|
|
239
|
-
|
|
240
|
-
const html = md.render("Euler's identity: $$e^{i\\pi} + 1 = 0$$");
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
## Features
|
|
244
|
-
|
|
245
|
-
- **Highly Complete**: Successfully compiles thousands of math formulas from KaTeX/MathJax official test suites (see [extract](https://github.com/webc-site/math/tree/dev/extract)).
|
|
246
|
-
- **Fault-Tolerant**: Syntax errors (such as unclosed `\left`/`\right`) are automatically caught and degraded to display raw TeX code, preventing application crashes.
|
|
247
|
-
- **Fast Compiler**: Compiles TeX formulas directly to semantic MathML without external parser dependencies.
|
|
248
|
-
- **Markdown Integration**: Automatically parses inline math (`$formula$`) and block math (`$$formula$$`) in Markdown text.
|
|
249
|
-
- **Standard Compatibility**: Outputs valid MathML elements supported natively by modern browsers.
|
|
250
|
-
|
|
251
|
-
## Supported Syntax List
|
|
252
|
-
|
|
253
|
-
Designed to be extremely lightweight, this library supports the most commonly used math typesetting syntaxes:
|
|
254
|
-
|
|
255
|
-
- **Basic Arithmetic & Symbols**: Numbers, English letters, basic operators (`+`, `-`, `*`, `/`, `=`, `<`, `>`, `(`, `)`, `[`, `]`, `.`). Note that `-` automatically maps to minus sign `\u2212`, `*` maps to asterisk `\u2217`, and `/` is rendered in upright normal font.
|
|
256
|
-
- **Subscripts & Superscripts**:
|
|
257
|
-
- Superscript `^` (e.g., `x^2`)
|
|
258
|
-
- Subscript `_` (e.g., `x_i`)
|
|
259
|
-
- Both subscripts and superscripts (e.g., `x_i^2` or `x^2_i`)
|
|
260
|
-
- Subscripts/superscripts of sum, integration, and other big operators will automatically appear in limits form (e.g., `\sum_{i=1}^n`, `\int_a^b`)
|
|
261
|
-
- **Fractions**: `\frac{numerator}{denominator}` (e.g., `\frac{a}{b}`)
|
|
262
|
-
- **Roots**: Square root `\sqrt{x}` and $n$-th root `\sqrt[n]{x}`
|
|
263
|
-
- **Overlines & Bars**: `\overline{x}` and the shorthand `\bar{x}`
|
|
264
|
-
- **Delimiters & Brackets**: `\left` and `\right` structures (e.g., `\left( ... \right)`). Supported delimiters include:
|
|
265
|
-
- Parentheses: `(` and `)`
|
|
266
|
-
- Square brackets: `[` and `]`
|
|
267
|
-
- Braces: `\{` and `\}`
|
|
268
|
-
- Angle brackets: `<` and `>`
|
|
269
|
-
- Vertical bars: `|` or `\|`
|
|
270
|
-
- Empty delimiter: `.` (hides the delimiter on that side, e.g., `\left. \frac{df}{dx} \right| _0`)
|
|
271
|
-
- **Text Mode**: `\text{...}` (e.g., `\text{if }`), extracts literal text inside braces and renders it as MathML `<mtext>` in normal upright font.
|
|
272
|
-
- **Horizontal Spacing**: Supports `\quad` (1em spacing) and `\qquad` (2em spacing).
|
|
273
|
-
- **Styles, Strikethroughs & Phantom**:
|
|
274
|
-
- Border: `\boxed{...}` (adds a border around the formula, e.g., `\boxed{x+y}`)
|
|
275
|
-
- Strikethroughs: `\cancel{...}` (strikes through with a slash, e.g., `\cancel{x}`) and `\sout{...}` (strikes through with a horizontal line, e.g., `\sout{y}`)
|
|
276
|
-
- Hiding & Spacing: `\phantom{...}` (creates an invisible space with the same width and height, e.g., `\phantom{x}`)
|
|
277
|
-
- **Common Functions**: `\sin`, `\cos`, `\tan`, `\cot`, `\sec`, `\csc`, `\log`, `\lg`, `\ln`, `\lim`, `\exp`, `\max`, `\min`, `\sup`, `\inf`, `\det`, `\gcd`, `\arcsin`, `\arccos`, `\arctan`, `\sinh`, `\cosh`, `\tanh`, `\coth`, `\deg`, `\arg`. Subscripts/superscripts of limit-like operators (`\lim`, `\max`, `\min`, `\sup`, `\inf`) appear as limits (directly below/above) in display mode.
|
|
278
|
-
- **Modulo**: `\pmod{...}` (adds a modulo parenthesis, e.g., `\pmod{m}` renders as $(mod\ m)$)
|
|
279
|
-
- **Greek Letters**:
|
|
280
|
-
- Lowercase: `\alpha` ($\alpha$), `\beta` ($\beta$), `\gamma` ($\gamma$), `\delta` ($\delta$), `\epsilon` ($\epsilon$), `\zeta` ($\zeta$), `\eta` ($\eta$), `\theta` ($\theta$), `\iota` ($\iota$), `\kappa` ($\kappa$), `\lambda` ($\lambda$), `\mu` ($\mu$), `\nu` ($\nu$), `\xi` ($\xi$), `\pi` ($\pi$), `\rho` ($\rho$), `\sigma` ($\sigma$), `\tau` ($\tau$), `\upsilon` ($\upsilon$), `\phi` ($\phi$), `\chi` ($\chi$), `\psi` ($\psi$), `\omega` ($\omega$)
|
|
281
|
-
- Uppercase (rendered in normal upright font): `\Delta` ($\Delta$), `\Gamma` ($\Gamma$), `\Theta` ($\Theta$), `\Lambda` ($\Lambda$), `\Xi` ($\Xi$), `\Pi` ($\Pi$), `\Sigma` ($\Sigma$), `\Upsilon` ($\Upsilon$), `\Phi` ($\Phi$), `\Psi` ($\Psi$), `\Omega` ($\Omega$)
|
|
282
|
-
- **Operators & Relations**:
|
|
283
|
-
- `\le` / `\leq` ($\le$), `\ge` / `\geq` ($\ge$), `\ne` / `\neq` ($\ne$)
|
|
284
|
-
- `\cdot` ($\cdot$), `\times` ($\times$), `\pm` ($\pm$), `\mp` ($\mp$), `\div` ($\div$), `\infty` ($\infty$)
|
|
285
|
-
- `\approx` ($\approx$), `\sim` ($\sim$), `\cong` ($\cong$), `\propto` ($\propto$), `\equiv` ($\equiv$), `\perp` ($\perp$), `\parallel` ($\parallel$)
|
|
286
|
-
- **Calculus, Sets & Logic**:
|
|
287
|
-
- Gradient: `\nabla` ($\nabla$), partial differential: `\partial` ($\partial$)
|
|
288
|
-
- Quantifiers & operations: `\forall` ($\forall$), `\exists` ($\exists$), `\neg` ($\neg$), `\land` ($\land$), `\lor` ($\lor$)
|
|
289
|
-
- Set relations: `\in` ($\in$), `\notin` ($\notin$), `\ni` ($\ni$), `\subset` ($\subset$), `\supset` ($\supset$), `\subseteq` ($\subseteq$), `\supseteq` ($\supseteq$)
|
|
290
|
-
- Set operations: `\cup` ($\cup$), `\cap` ($\cap$), empty set: `\emptyset` ($\emptyset$)
|
|
291
|
-
- Special variables & constants: `\ell` ($\ell$), `\hbar` ($\hbar$)
|
|
292
|
-
- Large operators: summation `\sum` ($\sum$), integration `\int` ($\int$)
|
|
293
|
-
- **Arrows**:
|
|
294
|
-
- Single arrows: `\to` / `\rightarrow` ($\rightarrow$), `\leftarrow` / `\gets` ($\leftarrow$), `\Leftarrow` ($\Leftarrow$), `\Rightarrow` ($\Rightarrow$)
|
|
295
|
-
- Double arrows: `\leftrightarrow` ($\leftrightarrow$), `\Leftrightarrow` ($\Leftrightarrow$)
|
|
296
|
-
- **Dots**:
|
|
297
|
-
- Baseline dots: `\dots` / `\ldots` ($\dots$)
|
|
298
|
-
- Centered dots: `\cdots` ($\cdots$)
|
|
299
|
-
- **Matrices & Multi-line Layouts**:
|
|
300
|
-
- Matrix environments: `matrix`, `pmatrix`, `bmatrix`, `vmatrix`, `Vmatrix` (e.g., `\begin{pmatrix} a & b \\ c & d \end{pmatrix}`)
|
|
301
|
-
- Cases: `cases` (e.g., `\begin{cases} x & x \ge 0 \\ -x & x < 0 \end{cases}`)
|
|
302
|
-
- General arrays: `array`
|
|
303
|
-
- Line breaks & alignment: Use `\\`, `\\*` or `\\[width]` (e.g., `\\[10px]`) for line breaks, and `&` for column alignment.
|
|
304
|
-
|
|
305
|
-
## Unsupported Syntax
|
|
306
|
-
|
|
307
|
-
Currently, the following LaTeX extensions, macros, or fine-tuning style directives are not supported:
|
|
308
|
-
|
|
309
|
-
1. **Macro Definitions**: `\newcommand`, `\renewcommand`, `\providecommand`, `\gdef`, `\let`, etc.
|
|
310
|
-
2. **Background Colors & Advanced Borders**: `\colorbox`, `\fcolorbox`, `\cellcolor`, etc. (while `\boxed` is supported).
|
|
311
|
-
3. **Other Strikethroughs**: `\bcancel`, `\xcancel`, etc. (while `\cancel` and `\sout` are supported).
|
|
312
|
-
4. **Advanced Layouts & Spacing**: `\hphantom`, `\vphantom`, `\smash`, etc. (while `\phantom` is supported).
|
|
313
|
-
5. **Chemistry Package Extensions**: Chemical formula macros like `\ce{...}` (mhchem).
|
|
314
|
-
6. **Verbatim Text**: `\verb`, etc.
|
|
315
|
-
7. **Advanced Positionings**: `\sideset`, `\prescript`, `\cramped`, `\flatfrac`, etc.
|
|
316
|
-
8. **Equation Numbering & Custom Tags**: `\tag`, `\newtagform`, `\usetagform`, etc.
|
|
317
|
-
9. **Arbitrary Operator Limits**: Except for predefined big operators (`\sum`, `\int`) and limit-like operators (`\lim`), using `\limits` on arbitrary commands or structures is not supported.
|
|
318
|
-
|
|
319
|
-
## Error Handling and Fault Tolerance
|
|
320
|
-
|
|
321
|
-
When parsing Markdown text using `@webc.site/math/md.js`, syntax errors (such as an unclosed `\left`) are automatically caught and degraded to display raw TeX code (e.g., `$$x + \left( y$$`), without throwing JS exceptions. Therefore, you **do not** need to wrap it in a `try...catch` block.
|
|
322
|
-
|
|
323
|
-
If you call the compiler core `@webc.site/math` directly with invalid LaTeX, it will throw an array containing an error code (see table below). Wrap direct core compiler calls in a `try...catch` block.
|
|
324
|
-
|
|
325
|
-
### Internal Error Codes
|
|
326
|
-
|
|
327
|
-
| Error Code | Constant | Description | Trigger Example |
|
|
328
|
-
| :--------: | :------------------ | :-------------------------------------------- | :------------------------------------ |
|
|
329
|
-
| `0` | `ERR_EXTRA_END` | Extra or invalid `\end` command | `\end{matrix}` (no matching `\begin`) |
|
|
330
|
-
| `1` | `ERR_MISSING_RIGHT` | `\left` delimiter missing a matching `\right` | `\left( x` |
|
|
331
|
-
| `2` | `ERR_EXTRA_RIGHT` | Extra or invalid `\right` command | `x \right)` (no matching `\left`) |
|
|
332
|
-
| `3` | `ERR_MISSING_BRACE` | Command missing required curly brace `{}` | `\text x` (missing braces) |
|
|
333
|
-
|
|
334
|
-
## Design and Workflow
|
|
335
|
-
|
|
336
|
-
The parser processes the input Markdown string, isolates TeX expressions, and translates them into MathML structures.
|
|
54
|
+
The compiler extracts TeX math formulas from input Markdown text, runs lexical and syntax analyses, and generates semantic MathML markup.
|
|
337
55
|
|
|
338
56
|
```mermaid
|
|
339
57
|
graph TD
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
58
|
+
Input[Input Markdown] --> Scanner[Scanner: Locates Delimiters]
|
|
59
|
+
Scanner -- Plain Text --> Buffer[Output Buffer]
|
|
60
|
+
Scanner -- TeX Formula --> Lexer[Lexer: Tokenizes Input]
|
|
61
|
+
Lexer --> Parser[Parser: Builds AST]
|
|
62
|
+
Parser --> Codegen[Codegen: Translates to MathML Tags]
|
|
63
|
+
Codegen --> Wrapper[Semantic Wrapper]
|
|
64
|
+
Wrapper --> MathML[MathML Output]
|
|
65
|
+
Buffer --> Output[Final HTML]
|
|
66
|
+
MathML --> Output
|
|
349
67
|
```
|
|
350
68
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
1. **Scanner**: Scans the input string to locate formula delimiters (`$` and `$$`).
|
|
354
|
-
2. **Lexer**: Breaks the TeX string into tokens like numbers, variables, operators, and control commands.
|
|
355
|
-
3. **Parser**: Translates tokens into an Abstract Syntax Tree (AST), supporting operations like subscripts, superscripts, fractions, and built-in functions.
|
|
356
|
-
4. **Codegen**: Maps AST nodes to standard MathML Core elements (`<mi>`, `<mo>`, `<mn>`, `<mfrac>`, `<msup>`, `<msub>`, `<msubsup>`).
|
|
357
|
-
|
|
358
|
-
## Adding New Syntax
|
|
359
|
-
|
|
360
|
-
To add support for a new LaTeX command, modify the following four core parts in order:
|
|
361
|
-
|
|
362
|
-
### 1. Constant Definitions
|
|
363
|
-
|
|
364
|
-
Define the corresponding lexical token, AST node type, function name, or symbol mapping:
|
|
365
|
-
|
|
366
|
-
- **Token Type**: Defined in [const/TOK.js](https://github.com/webc-site/math/blob/dev/src/const/TOK.js) (e.g., `export const TOK_MY_CMD = ...`).
|
|
367
|
-
- **AST Node Type**: Defined in [const/TYPE.js](https://github.com/webc-site/math/blob/dev/src/const/TYPE.js) (e.g., `export const TYPE_MY_NODE = ...`).
|
|
368
|
-
- **Environment Delimiters**: If adding a new environment (like a matrix or bracket type), configure its left and right delimiters in `ENV_DELIMS` inside [mathml.js](https://github.com/webc-site/math/blob/dev/src/mathml.js).
|
|
369
|
-
- **Symbol Mapping**: For simple operators or symbols, map the command name to its Unicode character in `SYM_MAP` inside [const/SYM.js](https://github.com/webc-site/math/blob/dev/src/const/SYM.js).
|
|
370
|
-
- **Math Function Name**: Define in `FUNC_NAMES` inside [const/FUNC.js](https://github.com/webc-site/math/blob/dev/src/const/FUNC.js).
|
|
371
|
-
|
|
372
|
-
### 2. Lexer
|
|
373
|
-
|
|
374
|
-
The `lex(str)` function cuts the input LaTeX string into a token array. It is located in [lex.js](https://github.com/webc-site/math/blob/dev/src/lex.js).
|
|
375
|
-
|
|
376
|
-
- If introducing a new special character or structure, update character matching logic in `lex` to push the correct `TOK_*` type and its literal value to the `tokens` array.
|
|
377
|
-
|
|
378
|
-
### 3. Parser
|
|
379
|
-
|
|
380
|
-
The `parse(tokens, state)` function translates tokens into AST nodes. It is located in [parse.js](https://github.com/webc-site/math/blob/dev/src/parse.js).
|
|
381
|
-
|
|
382
|
-
- **Command Parsing**: Handled primarily inside the `TOK_MAP[TOK_CMD]` function. When matching your command (e.g., `\mycmd`), read its arguments (using `read(tokens, state_ref)` or `grab(tokens, state_ref)`) and return the node array: `[TYPE_MY_NODE, arg1, arg2]`.
|
|
383
|
-
|
|
384
|
-
### 4. Codegen
|
|
385
|
-
|
|
386
|
-
The `SHOW_MAP` dictionary maps AST nodes to standard MathML markup strings. It is located in [mathml.js](https://github.com/webc-site/math/blob/dev/src/mathml.js).
|
|
387
|
-
|
|
388
|
-
- Register a renderer function: `[TYPE_MY_NODE]: ([_, arg1, arg2]) => nest("mylabel", arg1, arg2)`, formatting node data into native MathML tags.
|
|
389
|
-
|
|
390
|
-
## Tech Stack
|
|
69
|
+
## 4. Tech Stack
|
|
391
70
|
|
|
392
71
|
- **Runtime**: Bun, Node.js
|
|
393
|
-
- **
|
|
394
|
-
- **
|
|
72
|
+
- **Linter & Formatter**: oxlint, oxfmt
|
|
73
|
+
- **Build Tool**: Vite, Rolldown, Lightning CSS
|
|
395
74
|
|
|
396
|
-
##
|
|
75
|
+
## 5. Code Structure
|
|
397
76
|
|
|
398
77
|
```
|
|
399
78
|
.
|
|
400
|
-
├── demo/ # Interactive demo
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
│ ├──
|
|
404
|
-
│
|
|
405
|
-
│ └── style.styl # Styling and themes
|
|
406
|
-
├── extract/ # Test case extraction scripts (from KaTeX / MathJax)
|
|
407
|
-
├── lib/ # Compilation output directory
|
|
408
|
-
│ ├── package.json # Lightweight package.json for npm publication
|
|
409
|
-
│ ├── README.md # Automatically generated distribution README
|
|
410
|
-
│ ├── mathml.js # Minified core TeX compiler
|
|
411
|
-
│ ├── mathml.js.map # Source map for mathml.js
|
|
412
|
-
│ ├── md.js # Minified Markdown parser
|
|
413
|
-
│ └── md.js.map # Source map for md.js
|
|
79
|
+
├── demo/ # Interactive demo page
|
|
80
|
+
├── extract/ # Test cases extraction scripts
|
|
81
|
+
├── lib/ # Compiled distribution files
|
|
82
|
+
│ ├── mathml.js # Core compiler (minified)
|
|
83
|
+
│ └── md.js # Markdown math formula parser (minified)
|
|
414
84
|
├── src/ # Source code
|
|
415
|
-
│ ├── const/ # Tokens, AST types,
|
|
85
|
+
│ ├── const/ # Tokens, AST types, symbols and functions constants
|
|
416
86
|
│ ├── lex.js # LaTeX lexer
|
|
417
|
-
│ ├── parse.js # LaTeX parser (AST
|
|
418
|
-
│ ├── mathml.js # TeX-to-MathML compiler
|
|
419
|
-
│ └── md.js # Markdown
|
|
87
|
+
│ ├── parse.js # LaTeX parser (AST builder)
|
|
88
|
+
│ ├── mathml.js # Core TeX-to-MathML compiler
|
|
89
|
+
│ └── md.js # Markdown parser entry
|
|
420
90
|
├── sh/ # Scripts
|
|
421
|
-
│
|
|
422
|
-
|
|
423
|
-
│ │ ├── self.js # Regression tests
|
|
424
|
-
│ │ ├── util.js # Shared helpers
|
|
425
|
-
│ │ ├── chart.js # SVG chart component
|
|
426
|
-
│ │ └── history.yml # YAML historical benchmark records
|
|
427
|
-
│ └── check.js # Language file validation script
|
|
428
|
-
├── dev.js # Dev server script (Vite)
|
|
429
|
-
├── dist.js # Publish helper script (versioning and template rendering)
|
|
430
|
-
├── minify.js # Bundle compression script
|
|
431
|
-
├── package.json # Project package config
|
|
432
|
-
├── README.md # Automatically generated root README
|
|
433
|
-
├── README.mdt # Compilation template for README
|
|
434
|
-
└── test.sh # Formatting, linting, and unit test execution script
|
|
91
|
+
│ └── bench/ # Benchmark suites and historical data
|
|
92
|
+
└── test.sh # Quality verification and test runner
|
|
435
93
|
```
|
|
436
94
|
|
|
437
|
-
## Historical Background
|
|
438
|
-
|
|
439
|
-
Web-based math formula rendering traditionally relied on MathJax or KaTeX. These libraries load large JS/CSS packages and perform complex client-side calculations, causing noticeable loading delay or page layout shifting.
|
|
95
|
+
## 6. Historical Background
|
|
440
96
|
|
|
441
|
-
MathML
|
|
97
|
+
In the early history of the World Wide Web Consortium (W3C), MathML was proposed as a standard for mathematical notation in HTML5. However, implementation complexity caused fragmented support across browser engines. Chromium removed its initial MathML code in 2013 due to architectural and security issues, forcing web applications to load large, heavy layout libraries such as MathJax or KaTeX to calculate page styles and position symbols.
|
|
442
98
|
|
|
443
|
-
|
|
99
|
+
A decade later, in January 2023, Chrome 109 reintroduced native support for the MathML Core specification, which defines a subset of MathML optimized for browser performance. With WebKit (Safari), Gecko (Firefox), and Blink (Chrome/Edge) all supporting MathML Core natively, pages no longer require client-side JavaScript layout calculations. This project was created to compile LaTeX directly into native MathML tags at compile time, eliminating layout engine dependencies.
|
|
444
100
|
|
|
445
101
|
---
|
|
446
102
|
|
|
447
103
|
<a id="zh"></a>
|
|
448
104
|
|
|
449
|
-
# @webc.site/math
|
|
105
|
+
# @webc.site/math : 全球最小最快的网页Markdown公式渲染器
|
|
450
106
|
|
|
451
|
-
|
|
107
|
+
## 1. 功能介绍
|
|
452
108
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
<a href="https://github.com/webc-site/math" target="_blank"><img src="https://raw.githubusercontent.com/webc-site/math/dev/readme/zh/svg/badge.github.svg" alt="github" /></a>
|
|
456
|
-
|
|
457
|
-
<a href="https://math.webc.site" target="_blank"><img src="https://raw.githubusercontent.com/webc-site/math/dev/readme/zh/svg/badge.demo.svg" alt="demo" /></a>
|
|
109
|
+
项目将 LaTeX 数学公式编译为浏览器原生支持的 MathML Core 标记,无需前端排版引擎,实现零运行开销渲染。
|
|
458
110
|
|
|
459
|
-
|
|
111
|
+
- **高性能**:直接将 TeX 公式翻译为原生 MathML 标签。处理速度达每秒 329,000 次操作,较 KaTeX 快 3.6 倍,较 MathJax 快 48 倍。
|
|
112
|
+
- **体积小**:包体积仅 7.78 KB(Gzip 压缩后 3.58 KB),不影响页面首次加载性能。
|
|
113
|
+
- **无运行时依赖**:利用浏览器底层的 C++ 原生引擎进行布局和渲染,免去加载前端 JavaScript 排版库的步骤。
|
|
114
|
+
- **健壮容错**:自动捕获未闭合括号等语法错误,降级输出原始 TeX 字符串,防止页面程序崩溃。
|
|
115
|
+
- **通用兼容**:输出标准的 MathML 元素,适用于服务端渲染(SSR)、静态站点生成(SSG)和前端动态转换。
|
|
460
116
|
|
|
461
|
-
|
|
462
|
-
- [什么是 MathML?](#什么是-mathml)
|
|
463
|
-
- [为什么将 TeX 编译为 MathML?](#为什么将-tex-编译为-mathml)
|
|
464
|
-
- [性能对比](#性能对比)
|
|
465
|
-
- [1. 体积对比(Gzip 压缩)](#1-体积对比gzip-压缩)
|
|
466
|
-
- [2. 生成速度对比](#2-生成速度对比)
|
|
467
|
-
- [使用方法](#使用方法)
|
|
468
|
-
- [JavaScript 示例](#javascript-示例)
|
|
469
|
-
- [CSS 与数学字体配置](#css-与数学字体配置)
|
|
470
|
-
- [Markdown 解析器插件](#markdown-解析器插件)
|
|
471
|
-
- [功能特性](#功能特性)
|
|
472
|
-
- [支持的语法清单](#支持的语法清单)
|
|
473
|
-
- [不支持的语法](#不支持的语法)
|
|
474
|
-
- [错误处理与容错机制](#错误处理与容错机制)
|
|
475
|
-
- [内部错误码](#内部错误码)
|
|
476
|
-
- [设计思路与调用流程](#设计思路与调用流程)
|
|
477
|
-
- [模块运行流程](#模块运行流程)
|
|
478
|
-
- [如何添加新语法](#如何添加新语法)
|
|
479
|
-
- [1. 常量定义](#1-常量定义)
|
|
480
|
-
- [2. 词法分析](#2-词法分析)
|
|
481
|
-
- [3. 语法分析](#3-语法分析)
|
|
482
|
-
- [4. 代码渲染](#4-代码渲染)
|
|
483
|
-
- [技术堆栈](#技术堆栈)
|
|
484
|
-
- [目录结构](#目录结构)
|
|
485
|
-
- [历史背景](#历史背景)
|
|
117
|
+
## 2. 使用演示
|
|
486
118
|
|
|
487
|
-
|
|
119
|
+
### 编译示例
|
|
488
120
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
MathML(数学标记语言)是描述数学公式结构与语义的 XML 标准。
|
|
492
|
-
自 Chrome 109(2023年1月)起,所有主流浏览器引擎(Blink、Gecko、WebKit)均已原生支持 MathML Core 标准。页面无需加载 JS 排版库即可渲染公式。
|
|
493
|
-
|
|
494
|
-
### 为什么将 TeX 编译为 MathML?
|
|
495
|
-
|
|
496
|
-
MathML 语法基于 XML,不便于直接书写。日常书写的公式标准是 TeX 语法(如 `$e^{i\pi} + 1 = 0$`)。
|
|
497
|
-
传统库(如 MathJax、KaTeX)在前端运行时,需加载数百 KB 的排版引擎,并消耗 CPU 进行布局计算。
|
|
498
|
-
本库将 TeX 直接编译为 MathML,具有以下优势:
|
|
499
|
-
|
|
500
|
-
- **体积小**:包体积仅 7.78 KB(Gzip 3.58 KB),不影响首屏加载。
|
|
501
|
-
- **零运行依赖**:仅在编译期进行标签翻译,排版布局完全由浏览器底层的 C++ 原生引擎渲染,无需前端 JS 引擎介入,释放主线程。
|
|
502
|
-
- **低 CPU 开销**:适用于编辑器实时预览等高频渲染场景,低配移动设备运行流畅。
|
|
503
|
-
- **前后端通用**:输出标准 MathML 元素,适用于前端动态转换与服务端静态编译(SSR/SSG)。
|
|
504
|
-
|
|
505
|
-
## 性能对比
|
|
506
|
-
|
|
507
|
-
### 1. 体积对比(Gzip 压缩)
|
|
508
|
-
|
|
509
|
-
| 库 | 原始体积 | Gzip 体积 | 尺寸比 |
|
|
510
|
-
| :---------------------------------------------------------- | :-------: | :-------: | :----: |
|
|
511
|
-
| [@webc.site/math](https://github.com/webc-site/math) (本库) | 7.78 KB | 3.58 KB | 1.0 ⭐️ |
|
|
512
|
-
| [KaTeX](https://github.com/KaTeX/KaTeX) | 264.79 KB | 75.15 KB | 21.0 |
|
|
513
|
-
| [MathJax](https://github.com/mathjax/MathJax) | 971.04 KB | 278.39 KB | 77.7 |
|
|
514
|
-
|
|
515
|
-

|
|
516
|
-
|
|
517
|
-
### 2. 生成速度对比
|
|
518
|
-
|
|
519
|
-
基于经典公式循环编译测试(使用 [sh/bench/pk.js](https://github.com/webc-site/math/blob/dev/sh/bench/pk.js) 测得):
|
|
520
|
-
|
|
521
|
-
- **@webc.site/math (本库)**: ~329,000 ops/s (1.0 ⭐️)
|
|
522
|
-
- **[KaTeX](https://github.com/KaTeX/KaTeX)**: ~92,000 ops/s (约 3.6x 较慢)
|
|
523
|
-
- **[MathJax](https://github.com/mathjax/MathJax)**: ~6,700 ops/s (约 48.8x 较慢)
|
|
524
|
-
|
|
525
|
-

|
|
526
|
-
|
|
527
|
-
## 使用方法
|
|
528
|
-
|
|
529
|
-
### JavaScript 示例
|
|
530
|
-
|
|
531
|
-
#### 1. 直接渲染 TeX 公式
|
|
532
|
-
|
|
533
|
-
使用 `@webc.site/math` 将 TeX 公式编译为 MathML(适用于 Markdown 渲染插件开发):
|
|
121
|
+
#### 直接渲染 TeX 公式
|
|
534
122
|
|
|
535
123
|
```javascript
|
|
536
124
|
import mathml from "@webc.site/math";
|
|
537
125
|
|
|
538
|
-
const
|
|
539
|
-
const html = mathml(tex, true); // 第二个参数传 true 表示块级公式,传 false 或不传表示行内公式
|
|
126
|
+
const html = mathml("e^{i\\pi} + 1 = 0", true); // 第二参数设为 true 表示块级公式
|
|
540
127
|
```
|
|
541
128
|
|
|
542
|
-
####
|
|
543
|
-
|
|
544
|
-
使用 `@webc.site/math/md.js` 自动识别 Markdown 文本中的行内/块级公式并替换为 MathML(需传入公式编译器):
|
|
129
|
+
#### 替换 Markdown 文本中的公式
|
|
545
130
|
|
|
546
131
|
```javascript
|
|
547
132
|
import mdMath from "@webc.site/math/md.js";
|
|
548
133
|
import compile from "@webc.site/math";
|
|
549
134
|
|
|
550
|
-
const
|
|
551
|
-
const html = mdMath(markdown, compile);
|
|
552
|
-
|
|
553
|
-
console.log(html);
|
|
554
|
-
// 输出: 欧拉恒等式:<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msup><mi>e</mi><mrow><mi>i</mi><mi>π</mi></mrow></msup><mo>+</mo><mn>1</mn><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">e^{i\pi} + 1 = 0</annotation></semantics></math>
|
|
135
|
+
const html = mdMath("欧拉恒等式:$$e^{i\\pi} + 1 = 0$$", compile);
|
|
555
136
|
```
|
|
556
137
|
|
|
557
|
-
### CSS
|
|
138
|
+
### 字体与 CSS 配置
|
|
558
139
|
|
|
559
|
-
|
|
140
|
+
配置数学字体可确保排版美观。推荐使用 `18s` 字体包中的 **Latin Modern Math** 字体。
|
|
560
141
|
|
|
561
|
-
####
|
|
562
|
-
|
|
563
|
-
在 CSS 中通过 `@import` 引入在线字体:
|
|
564
|
-
|
|
565
|
-
```css
|
|
566
|
-
/* 引入合并后的字体 CSS(包含思源黑体 t、代码字体 c 及数学字体 m) */
|
|
567
|
-
@import url("//registry.npmmirror.com/18s/0.2.24/files/_.css");
|
|
568
|
-
```
|
|
569
|
-
|
|
570
|
-
或者仅按需引入数学字体 `m`:
|
|
571
|
-
|
|
572
|
-
```css
|
|
573
|
-
@import url("//registry.npmmirror.com/18s/0.2.24/files/m.css");
|
|
574
|
-
```
|
|
575
|
-
|
|
576
|
-
#### 2. 配置 CSS 样式
|
|
577
|
-
|
|
578
|
-
在全局 CSS 样式表中,为 `math` 标签指定数学字体。
|
|
579
|
-
|
|
580
|
-
##### 方案 A:使用在线字体(推荐,效果最完美)
|
|
581
|
-
|
|
582
|
-
引入 `18s` 提供的字体包(含切片优化思源黑体 `t` 与数学字体 `m`):
|
|
142
|
+
#### CSS 字体样式设置
|
|
583
143
|
|
|
584
144
|
```css
|
|
585
145
|
math {
|
|
586
|
-
/* m 为数学字体,t 为思源黑体(对中文字符进行了切片优化以提升加载性能),math 为系统数学字体,sans-serif 为系统默认无衬线字体 */
|
|
587
146
|
font-family: m, t, math, sans-serif;
|
|
588
147
|
}
|
|
589
148
|
```
|
|
590
149
|
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
直接使用系统内置数学字体以最小化体积:
|
|
594
|
-
|
|
595
|
-
```css
|
|
596
|
-
math {
|
|
597
|
-
/* 优先使用各平台内置的数学字体,其次降级到 CSS 标准 math 泛型,最后以系统默认无衬线字体作为后备 */
|
|
598
|
-
font-family: "STIX Two Math", "Latin Modern Math", "Cambria Math", math, sans-serif;
|
|
599
|
-
}
|
|
600
|
-
```
|
|
601
|
-
|
|
602
|
-
#### 3. 配合构建工具引用
|
|
603
|
-
|
|
604
|
-
通过 npm 安装 `18s` 字体包,配合 Vite、Webpack 等构建工具在项目入口中引入:
|
|
605
|
-
|
|
606
|
-
```bash
|
|
607
|
-
npm install 18s
|
|
608
|
-
```
|
|
609
|
-
|
|
610
|
-
在项目入口文件中引入字体样式:
|
|
611
|
-
|
|
612
|
-
##### 方式 A:在 JS/TS 入口中引入
|
|
613
|
-
|
|
614
|
-
```javascript
|
|
615
|
-
// 引入合并后的字体 CSS(包含思源黑体 t、代码字体 c 及数学字体 m)
|
|
616
|
-
import "18s/_.css";
|
|
617
|
-
```
|
|
618
|
-
|
|
619
|
-
或者仅按需引入数学字体 `m`:
|
|
620
|
-
|
|
621
|
-
```javascript
|
|
622
|
-
import "18s/m.css";
|
|
623
|
-
```
|
|
624
|
-
|
|
625
|
-
##### 方式 B:在 CSS 入口中引入
|
|
626
|
-
|
|
627
|
-
```css
|
|
628
|
-
/* 引入合并后的字体 CSS(包含思源黑体 t、代码字体 c 及数学字体 m) */
|
|
629
|
-
@import "18s/_.css";
|
|
630
|
-
```
|
|
631
|
-
|
|
632
|
-
或者仅按需引入数学字体 `m`:
|
|
633
|
-
|
|
634
|
-
```css
|
|
635
|
-
@import "18s/m.css";
|
|
636
|
-
```
|
|
637
|
-
|
|
638
|
-
### Markdown 解析器插件
|
|
639
|
-
|
|
640
|
-
#### 1. Marked 插件
|
|
641
|
-
|
|
642
|
-
使用 [`@webc.site/math-marked`](https://www.npmjs.com/package/@webc.site/math-marked) 自动解析并编译行内(`$...$`)与块级(`$$...$$`)公式:
|
|
643
|
-
|
|
644
|
-
```javascript
|
|
645
|
-
import { marked } from "marked";
|
|
646
|
-
import mathMarked from "@webc.site/math-marked";
|
|
647
|
-
|
|
648
|
-
marked.use(mathMarked());
|
|
649
|
-
|
|
650
|
-
const html = marked.parse("欧拉恒等式:$$e^{i\\pi} + 1 = 0$$");
|
|
651
|
-
```
|
|
652
|
-
|
|
653
|
-
#### 2. Remark 插件
|
|
654
|
-
|
|
655
|
-
使用 [`@webc.site/math-remark`](https://www.npmjs.com/package/@webc.site/math-remark) 将 Unified/Remark AST 中的 `inlineMath` 与 `math` 节点替换为原生 MathML HTML:
|
|
656
|
-
|
|
657
|
-
```javascript
|
|
658
|
-
import { unified } from "unified";
|
|
659
|
-
import remarkParse from "remark-parse";
|
|
660
|
-
import remarkMath from "remark-math";
|
|
661
|
-
import mathRemark from "@webc.site/math-remark";
|
|
662
|
-
import remarkHtml from "remark-html";
|
|
663
|
-
|
|
664
|
-
const html = await unified()
|
|
665
|
-
.use(remarkParse)
|
|
666
|
-
.use(remarkMath)
|
|
667
|
-
.use(mathRemark)
|
|
668
|
-
.use(remarkHtml, { sanitize: false })
|
|
669
|
-
.process("欧拉恒等式:$$e^{i\\pi} + 1 = 0$$");
|
|
670
|
-
```
|
|
671
|
-
|
|
672
|
-
#### 3. Markdown-it 插件
|
|
150
|
+
## 3. 设计思路
|
|
673
151
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
```javascript
|
|
677
|
-
import markdownit from "markdown-it";
|
|
678
|
-
import mathMarkdownIt from "@webc.site/math-markdown-it";
|
|
679
|
-
|
|
680
|
-
const md = markdownit().use(mathMarkdownIt);
|
|
681
|
-
|
|
682
|
-
const html = md.render("欧拉恒等式:$$e^{i\\pi} + 1 = 0$$");
|
|
683
|
-
```
|
|
684
|
-
|
|
685
|
-
## 功能特性
|
|
686
|
-
|
|
687
|
-
- **功能完备**:通过数千个 KaTeX/MathJax 官方测试用例(详见 [extract](https://github.com/webc-site/math/tree/dev/extract))。
|
|
688
|
-
- **健壮容错**:公式语法错误(如未闭合的 `\left`/`\right`)会自动捕获并降级显示原始公式,不抛出异常,防止应用崩溃。
|
|
689
|
-
- **快速编译**:无需外部依赖,直接将 TeX 公式编译为语义化 MathML。
|
|
690
|
-
- **Markdown 集成**:自动解析 Markdown 中的行内公式(`$ 公式 $`)和块级公式(`$$ 公式 $$`)。
|
|
691
|
-
- **标准兼容**:输出现代浏览器原生支持的标准 MathML 元素。
|
|
692
|
-
|
|
693
|
-
## 支持的语法清单
|
|
694
|
-
|
|
695
|
-
本库在极简的包体积下,支持最常用的数学公式排版语法:
|
|
696
|
-
|
|
697
|
-
- **基础算术与符号**:数字、英文字母、基础运算符(`+`, `-`, `*`, `/`, `=`, `<`, `>`, `(`, `)`, `[`, `]`, `.`)。其中 `-` 自动映射为减号 `\u2212`,`*` 映射为星号 `\u2217`,`/` 以直立体呈现。
|
|
698
|
-
- **上下标**:
|
|
699
|
-
- 上标 `^`(如 `x^2`)
|
|
700
|
-
- 下标 `_`(如 `x_i`)
|
|
701
|
-
- 同时存在上下标(如 `x_i^2` 或 `x^2_i`)
|
|
702
|
-
- 对于求和与积分等大型运算符,上下标会自动以限位上下标形式呈现(如 `\sum_{i=1}^n`,`\int_a^b`)
|
|
703
|
-
- **分式**:`\frac{分子}{分母}`(如 `\frac{a}{b}`)
|
|
704
|
-
- **开根号**:平方根 `\sqrt{x}` 以及 $n$ 次方根 `\sqrt[n]{x}`
|
|
705
|
-
- **上划线与横线**:`\overline{x}` 及简写形式 `\bar{x}`
|
|
706
|
-
- **自适应括号与定界符**:`\left` 和 `\right` 结构(如 `\left( ... \right)`)。支持的定界符包括:
|
|
707
|
-
- 圆括号:`(` 和 `)`
|
|
708
|
-
- 方括号:`[` 和 `]`
|
|
709
|
-
- 花括号:`\{` 和 `\}`
|
|
710
|
-
- 尖括号:`<` 和 `>`
|
|
711
|
-
- 竖线:`|` 或 `\|`
|
|
712
|
-
- 空白定界符:`.`(表示不显示该侧定界符,例如 `\left. \frac{df}{dx} \right| _0`)
|
|
713
|
-
- **文本模式**:`\text{...}`(如 `\text{if }`),提取大括号中的字面文本,渲染为 MathML `<mtext>`,以常规直立体呈现。
|
|
714
|
-
- **水平间距**:支持 `\quad`(1em 间距)和 `\qquad`(2em 间距)的空格占位。
|
|
715
|
-
- **样式、删除线与占位隐藏**:
|
|
716
|
-
- 边框:`\boxed{...}`(在公式周围加上边框,如 `\boxed{x+y}`)
|
|
717
|
-
- 删除线与取消线:`\cancel{...}`(通过斜线划掉,如 `\cancel{x}`)和 `\sout{...}`(通过水平线划掉,如 `\sout{y}`)
|
|
718
|
-
- 隐藏与占位:`\phantom{...}`(生成与输入内容相同宽高的不可见占位空间,如 `\phantom{x}`)
|
|
719
|
-
- **常用数学函数**:`\sin`, `\cos`, `\tan`, `\cot`, `\sec`, `\csc`, `\log`, `\lg`, `\ln`, `\lim`, `\exp`, `\max`, `\min`, `\sup`, `\inf`, `\det`, `\gcd`, `\arcsin`, `\arccos`, `\arctan`, `\sinh`, `\cosh`, `\tanh`, `\coth`, `\deg`, `\arg`。其中 `\lim`, `\max`, `\min`, `\sup`, `\inf` 作为极限算子,其上下标定位在行间/块级公式中会自动以 limits 形式显示在算子正下方。
|
|
720
|
-
- **同余括号**:`\pmod{...}`(生成带括号的同余占位,如 `\pmod{m}` 渲染为 $(mod\ m)$)
|
|
721
|
-
- **希腊字母**:
|
|
722
|
-
- 小写希腊字母:`\alpha` ($\alpha$), `\beta` ($\beta$), `\gamma` ($\gamma$), `\delta` ($\delta$), `\epsilon` ($\epsilon$), `\zeta` ($\zeta$), `\eta` ($\eta$), `\theta` ($\theta$), `\iota` ($\iota$), `\kappa` ($\kappa$), `\lambda` ($\lambda$), `\mu` ($\mu$), `\nu` ($\nu$), `\xi` ($\xi$), `\pi` ($\pi$), `\rho` ($\rho$), `\sigma` ($\sigma$), `\tau` ($\tau$), `\upsilon` ($\upsilon$), `\phi` ($\phi$), `\chi` ($\chi$), `\psi` ($\psi$), `\omega` ($\omega$)
|
|
723
|
-
- 大写希腊字母(以直立体呈现):`\Delta` ($\Delta$), `\Gamma` ($\Gamma$), `\Theta` ($\Theta$), `\Lambda` ($\Lambda$), `\Xi` ($\Xi$), `\Pi` ($\Pi$), `\Sigma` ($\Sigma$), `\Upsilon` ($\Upsilon$), `\Phi` ($\Phi$), `\Psi` ($\Psi$), `\Omega` ($\Omega$)
|
|
724
|
-
- **算术运算符与关系符**:
|
|
725
|
-
- `\le` / `\leq` ($\le$), `\ge` / `\geq` ($\ge$), `\ne` / `\neq` ($\ne$)
|
|
726
|
-
- `\cdot` ($\cdot$), `\times` ($\times$), `\pm` ($\pm$), `\mp` ($\mp$), `\div` ($\div$), `\infty` ($\infty$)
|
|
727
|
-
- `\approx` ($\approx$), `\sim` ($\sim$), `\cong` ($\cong$), `\propto` ($\propto$), `\equiv` ($\equiv$), `\perp` ($\perp$), `\parallel` ($\parallel$)
|
|
728
|
-
- **微积分、集合与逻辑符号**:
|
|
729
|
-
- 梯度:`\nabla` ($\nabla$),偏微分:`\partial` ($\partial$)
|
|
730
|
-
- 逻辑量词与运算:`\forall` ($\forall$),`\exists` ($\exists$),`\neg` ($\neg$),`\land` ($\land$),`\lor` ($\lor$)
|
|
731
|
-
- 集合关系:`\in` ($\in$),`\notin` ($\notin$),`\ni` ($\ni$),`\subset` ($\subset$),`\supset` ($\supset$),`\subseteq` ($\subseteq$),`\supseteq` ($\supseteq$)
|
|
732
|
-
- 集合运算:`\cup` ($\cup$),`\cap` ($\cap$),空集:`\emptyset` ($\emptyset$)
|
|
733
|
-
- 特殊变量与常量:`\ell` ($\ell$), `\hbar` ($\hbar$)
|
|
734
|
-
- 大型运算符:求和 `\sum` ($\sum$),积分 `\int` ($\int$)
|
|
735
|
-
- **箭头符号**:
|
|
736
|
-
- 单向箭头:`\to` / `\rightarrow` ($\rightarrow$), `\leftarrow` / `\gets` ($\leftarrow$), `\Leftarrow` ($\Leftarrow$), `\Rightarrow` ($\Rightarrow$)
|
|
737
|
-
- 双向箭头:`\leftrightarrow` ($\leftrightarrow$), `\Leftrightarrow` ($\Leftrightarrow$)
|
|
738
|
-
- **省略号**:
|
|
739
|
-
- 基线省略号:`\dots` / `\ldots` ($\dots$)
|
|
740
|
-
- 居中省略号:`\cdots` ($\cdots$)
|
|
741
|
-
- **矩阵与多行排版**:
|
|
742
|
-
- 矩阵环境:`matrix`, `pmatrix`, `bmatrix`, `vmatrix`, `Vmatrix`(如 `\begin{pmatrix} a & b \\ c & d \end{pmatrix}`)
|
|
743
|
-
- 方程组与条件分支:`cases`(如 `\begin{cases} x & x \ge 0 \\ -x & x < 0 \end{cases}`)
|
|
744
|
-
- 通用数组排版:`array`
|
|
745
|
-
- 换行与对齐:使用 `\\`、`\\*` 或 `\\[width]` 进行换行,以及使用 `&` 进行列对齐
|
|
746
|
-
|
|
747
|
-
## 不支持的语法
|
|
748
|
-
|
|
749
|
-
目前不支持以下 LaTeX 扩展、宏定义或样式微调指令:
|
|
750
|
-
|
|
751
|
-
1. **宏定义命令**:`\newcommand`, `\renewcommand`, `\providecommand`, `\gdef`, `\let` 等。
|
|
752
|
-
2. **背景色与高级边框**:`\colorbox`, `\fcolorbox`, `\cellcolor` 等(支持 `\boxed`)。
|
|
753
|
-
3. **其他删除线**:`\bcancel`, `\xcancel` 等(支持 `\cancel` 和 `\sout`)。
|
|
754
|
-
4. **高级布局与隐藏**:`\hphantom`, `\vphantom`, `\smash` 等(支持 `\phantom`)。
|
|
755
|
-
5. **化学公式扩展**:化学宏包 `\ce{...}` (mhchem)。
|
|
756
|
-
6. **代码/文本抄录**:`\verb` 等。
|
|
757
|
-
7. **高级上/下标定位**:`\sideset`, `\prescript`, `\cramped`, `\flatfrac` 等。
|
|
758
|
-
8. **公式编号与自定义标签**:`\tag`, `\newtagform`, `\usetagform` 等。
|
|
759
|
-
9. **任意运算符的限位强制调整**:除预设的 `\sum`, `\int` 等大型运算符和 `\lim` 等极限算子外,不支持对任意自定义命令或结构使用 `\limits` 强制限位。
|
|
760
|
-
|
|
761
|
-
## 错误处理与容错机制
|
|
762
|
-
|
|
763
|
-
使用 `@webc.site/math/md.js` 解析 Markdown 文本时,若包含非法 LaTeX 语法,内部会自动捕获错误并退化为原始公式文本(如 `$$x + \left( y$$`),不抛出 JS 异常。因此,调用时**无需**包裹 `try...catch`。
|
|
764
|
-
|
|
765
|
-
如直接调用 `@webc.site/math` 编译非法 LaTeX,则会抛出错误码数组(详见下表),建议使用 `try...catch` 包裹。
|
|
766
|
-
|
|
767
|
-
### 内部错误码
|
|
768
|
-
|
|
769
|
-
| 错误码 | 常量名 | 含义 | 触发示例 |
|
|
770
|
-
| :----: | :------------------ | :-------------------------------- | :--------------------------------- |
|
|
771
|
-
| `0` | `ERR_EXTRA_END` | 多余或非法的 `\end` 指令 | `\end{matrix}` (无对应的 `\begin`) |
|
|
772
|
-
| `1` | `ERR_MISSING_RIGHT` | `\left` 定界符缺少配对的 `\right` | `\left( x` |
|
|
773
|
-
| `2` | `ERR_EXTRA_RIGHT` | 多余或非法的 `\right` 指令 | `x \right)` (无对应的 `\left`) |
|
|
774
|
-
| `3` | `ERR_MISSING_BRACE` | 命令缺少必填的大括号参数 | `\text x` (缺少 `{}`) |
|
|
775
|
-
|
|
776
|
-
## 设计思路与调用流程
|
|
777
|
-
|
|
778
|
-
解析器处理输入的 Markdown 字符串,隔离 TeX 表达式,并将其转换为 MathML 结构。
|
|
152
|
+
编译器从输入的 Markdown 文本中提取 TeX 公式,执行词法分析和语法分析,生成对应的语义化 MathML 标记。
|
|
779
153
|
|
|
780
154
|
```mermaid
|
|
781
155
|
graph TD
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
156
|
+
Input[输入 Markdown] --> Scanner[扫描器: 定位定界符]
|
|
157
|
+
Scanner -- 普通文本 --> Buffer[输出缓冲区]
|
|
158
|
+
Scanner -- TeX 公式 --> Lexer[词法分析: 生成 Token]
|
|
159
|
+
Lexer --> Parser[语法分析: 生成 AST]
|
|
160
|
+
Parser --> Codegen[代码生成: 映射 MathML 标签]
|
|
161
|
+
Codegen --> Wrapper[语义包装]
|
|
162
|
+
Wrapper --> MathML[MathML 输出]
|
|
163
|
+
Buffer --> Output[最终 HTML]
|
|
164
|
+
MathML --> Output
|
|
791
165
|
```
|
|
792
166
|
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
1. **扫描器**:扫描输入字符串,定位公式定界符(`$` 和 `$$`)。
|
|
796
|
-
2. **词法分析**:将 TeX 字符串分解为数字、变量、运算符和控制命令等 Token。
|
|
797
|
-
3. **语法分析**:将 Token 转换为抽象语法树(AST)节点,支持分式、上下标及预设数学函数。
|
|
798
|
-
4. **代码生成**:将 AST 节点映射为标准 XML 节点(`<mi>`、`<mo>`、`<mn>`、`<mfrac>`、`<msup>`、`<msub>`、`<msubsup>`)。
|
|
799
|
-
|
|
800
|
-
## 如何添加新语法
|
|
801
|
-
|
|
802
|
-
添加新的 LaTeX 语法支持需要按顺序修改以下四个核心部分:
|
|
803
|
-
|
|
804
|
-
### 1. 常量定义
|
|
805
|
-
|
|
806
|
-
定义相应的词法 Token、语法节点类型、函数名或符号映射表:
|
|
807
|
-
|
|
808
|
-
- **Token 类型**:在 [const/TOK.js](https://github.com/webc-site/math/blob/dev/src/const/TOK.js) 中定义(如 `export const TOK_MY_CMD = ...`)。
|
|
809
|
-
- **节点类型**:在 [const/TYPE.js](https://github.com/webc-site/math/blob/dev/src/const/TYPE.js) 中定义(如 `export const TYPE_MY_NODE = ...`)。
|
|
810
|
-
- **环境定界符**:若添加新的环境(如新矩阵或括号类型),需在 [mathml.js](https://github.com/webc-site/math/blob/dev/src/mathml.js) 的 `ENV_DELIMS` 中配置其左右定界符。
|
|
811
|
-
- **符号映射表**:如果是普通数学符号或简单命令,只需在 [const/SYM.js](https://github.com/webc-site/math/blob/dev/src/const/SYM.js) 的 `SYM_MAP` 中将命令名映射为对应的 Unicode 字符。
|
|
812
|
-
- **数学函数名**:在 [const/FUNC.js](https://github.com/webc-site/math/blob/dev/src/const/FUNC.js) 的 `FUNC_NAMES` 集合中定义。
|
|
167
|
+
## 4. 技术栈
|
|
813
168
|
|
|
814
|
-
|
|
169
|
+
- **运行环境**:Bun, Node.js
|
|
170
|
+
- **语法检查与格式化**:oxlint, oxfmt
|
|
171
|
+
- **构建工具**:Vite, Rolldown, Lightning CSS
|
|
815
172
|
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
- 如果引入了新的特殊字符或不同结构,需要更新 `lex` 函数中的字符匹配逻辑,让其识别并向 `tokens` 数组中推送相应的 `TOK_*` 类型和其字面值。
|
|
819
|
-
|
|
820
|
-
### 3. 语法分析
|
|
821
|
-
|
|
822
|
-
`parse(tokens, state)` 函数负责将 Token 转换为抽象语法树(AST)节点。它位于 [parse.js](https://github.com/webc-site/math/blob/dev/src/parse.js)。
|
|
823
|
-
|
|
824
|
-
- **命令解析**:主要在 [parse.js](https://github.com/webc-site/math/blob/dev/src/parse.js) 的 `TOK_MAP[TOK_CMD]` 函数中处理。当解析到对应的 LaTeX 命令(如 `\mycmd`)时,读取其参数(可使用 `read(tokens, state_ref)` 或 `grab(tokens, state_ref)`),并返回一个表示该节点的数组:`[TYPE_MY_NODE, arg1, arg2]`。
|
|
825
|
-
|
|
826
|
-
### 4. 代码渲染
|
|
827
|
-
|
|
828
|
-
`SHOW_MAP` 字典负责将 AST 节点转换为标准的 MathML 标签字符串。它位于 [mathml.js](https://github.com/webc-site/math/blob/dev/src/mathml.js)。
|
|
829
|
-
|
|
830
|
-
- 注册新的节点渲染函数:`[TYPE_MY_NODE]: ([_, arg1, arg2]) => nest("mylabel", arg1, arg2)`,将节点数据格式化为对应的标准 MathML 标记。
|
|
831
|
-
|
|
832
|
-
## 技术堆栈
|
|
833
|
-
|
|
834
|
-
- **运行环境**:Bun、Node.js
|
|
835
|
-
- **构建与打包**:SWC(代码压缩)、Vite(演示页面)
|
|
836
|
-
- **开发工具**:oxlint、oxfmt
|
|
837
|
-
|
|
838
|
-
## 目录结构
|
|
173
|
+
## 5. 代码结构
|
|
839
174
|
|
|
840
175
|
```
|
|
841
176
|
.
|
|
842
|
-
├── demo/ #
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
│ ├──
|
|
846
|
-
│
|
|
847
|
-
|
|
848
|
-
├──
|
|
849
|
-
├──
|
|
850
|
-
│ ├──
|
|
851
|
-
│ ├──
|
|
852
|
-
│
|
|
853
|
-
│ ├── mathml.js.map # 独立 SourceMap
|
|
854
|
-
│ ├── md.js # 压缩版 JS (Markdown 解析器)
|
|
855
|
-
│ └── md.js.map # 独立 SourceMap
|
|
856
|
-
├── src/ # 源代码目录
|
|
857
|
-
│ ├── const/ # 常量定义(Token 类型、AST 节点类型、符号映射、函数名等)
|
|
858
|
-
│ ├── lex.js # LaTeX 公式词法分析器
|
|
859
|
-
│ ├── parse.js # LaTeX 公式语法分析器(生成 AST)
|
|
860
|
-
│ ├── mathml.js # TeX-to-MathML 编译器
|
|
861
|
-
│ └── md.js # Markdown 数学公式解析入口
|
|
177
|
+
├── demo/ # 演示页面
|
|
178
|
+
├── extract/ # 测试用例提取脚本
|
|
179
|
+
├── lib/ # 编译产物目录
|
|
180
|
+
│ ├── mathml.js # 核心编译器(压缩版)
|
|
181
|
+
│ └── md.js # Markdown 公式解析器(压缩版)
|
|
182
|
+
├── src/ # 源代码
|
|
183
|
+
│ ├── const/ # Token、AST 节点、符号和函数常量定义
|
|
184
|
+
│ ├── lex.js # LaTeX 词法分析器
|
|
185
|
+
│ ├── parse.js # LaTeX 语法分析器(生成 AST)
|
|
186
|
+
│ ├── mathml.js # TeX 至 MathML 核心编译器
|
|
187
|
+
│ └── md.js # Markdown 公式解析入口
|
|
862
188
|
├── sh/ # 脚本目录
|
|
863
|
-
│
|
|
864
|
-
|
|
865
|
-
│ │ ├── self.js # 体积/性能回归测试脚本
|
|
866
|
-
│ │ ├── util.js # 评测共享工具库
|
|
867
|
-
│ │ ├── chart.js # SVG 柱状图生成组件
|
|
868
|
-
│ │ └── history.yml # YAML 格式历史基准数据
|
|
869
|
-
│ └── check.js # 语言文件校验脚本
|
|
870
|
-
├── dev.js # 启动 Vite 开发服务器脚本
|
|
871
|
-
├── dist.js # 打包发布辅助脚本(自动递增版本、渲染模板)
|
|
872
|
-
├── minify.js # 代码打包压缩脚本
|
|
873
|
-
├── package.json # 项目配置文件
|
|
874
|
-
├── README.md # 同步生成的根目录项目说明
|
|
875
|
-
├── README.mdt # 用于合并中英文及介绍文件的 Markdown 模板
|
|
876
|
-
└── test.sh # 格式化、代码检查及测试运行脚本
|
|
189
|
+
│ └── bench/ # 性能基准测试与历史数据
|
|
190
|
+
└── test.sh # 代码规范检查与测试运行脚本
|
|
877
191
|
```
|
|
878
192
|
|
|
879
|
-
##
|
|
880
|
-
|
|
881
|
-
传统的 Web 数学公式渲染多依赖 MathJax 或 KaTeX。这类库体积较大,需要加载大量 JS 文件并执行复杂的排版计算,容易导致页面渲染出现延迟与白屏。
|
|
193
|
+
## 6. 历史故事
|
|
882
194
|
|
|
883
|
-
MathML
|
|
195
|
+
在万维网联盟(W3C)早期历史中,MathML 曾被提议为 HTML5 标准数学排版规范。但因其实现复杂度高,各浏览器引擎对该规范的支持程度参差不齐。2013 年,Chromium 项目以系统架构和安全隐患为由移除了原有的 MathML 渲染实现。导致网页渲染公式时,必须依赖 MathJax 或 KaTeX 等体积庞大的 JavaScript 排版库在前端进行复杂的样式布局和字符定位计算。
|
|
884
196
|
|
|
885
|
-
|
|
197
|
+
十年后,即 2023 年 1 月,Chrome 109 重新引入了对 MathML Core 标准的原生支持。该标准精简并优化了数学渲染逻辑,使其在现代浏览器引擎中表现更为高效。随着 WebKit (Safari)、Gecko (Firefox) 和 Blink (Chrome/Edge) 对 MathML Core 规范实现全面覆盖,前端不再需要引入重型的 JavaScript 排版引擎。该项目应运而生,在编译期将 LaTeX 直接转换为原生 MathML 标签,去除运行时排版库依赖。
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@webc.site/math","version":"0.1.
|
|
1
|
+
{"name":"@webc.site/math","version":"0.1.22","description":"The world's smallest and fastest web Markdown formula renderer / 全球最小最快的网页Markdown公式渲染器","keywords":["markdown","math","mathml","render","tex"],"homepage":"https://math.webc.site","license":"MulanPSL-2.0","author":"i18n.site@gmail.com","repository":{"type":"git","url":"git+https://github.com/webc-site/math.git"},"type":"module","exports":{".":{"types":"./mathml.d.ts","default":"./mathml.js"},"./md.js":{"types":"./md.d.ts","default":"./md.js"},"./*":"./*"},"dependencies":{}}
|