@webc.site/math 0.1.13 → 0.1.18
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 +303 -322
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
<a id="en"></a>
|
|
6
|
+
|
|
6
7
|
# @webc.site/math
|
|
7
8
|
|
|
8
9
|
### The world's smallest and fastest web Markdown formula renderer
|
|
@@ -13,40 +14,81 @@
|
|
|
13
14
|
|
|
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>
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
No need to load hundreds of KB of KaTeX/MathJax and large font packages. At just ~4KB (Gzipped), it compiles LaTeX equations into native MathML supported by modern browsers, achieving zero-overhead rendering.
|
|
17
18
|
|
|
19
|
+
- [Core Advantages](#core-advantages)
|
|
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)
|
|
18
25
|
- [Usage](#usage)
|
|
19
|
-
- [JavaScript
|
|
26
|
+
- [JavaScript Examples](#javascript-examples)
|
|
20
27
|
- [Markdown Parser Plugins](#markdown-parser-plugins)
|
|
21
28
|
- [CSS and Math Font Configuration](#css-and-math-font-configuration)
|
|
22
29
|
- [Features](#features)
|
|
23
30
|
- [Supported Syntax List](#supported-syntax-list)
|
|
24
|
-
|
|
31
|
+
- [Unsupported Syntax](#unsupported-syntax)
|
|
25
32
|
- [Error Handling and Fault Tolerance](#error-handling-and-fault-tolerance)
|
|
26
33
|
- [Internal Error Codes](#internal-error-codes)
|
|
27
|
-
- [
|
|
28
|
-
- [
|
|
29
|
-
- [
|
|
30
|
-
- [1.
|
|
31
|
-
- [2. Generation Speed (Ops/sec)](#2-generation-speed-opssec)
|
|
32
|
-
- [Design and Calling Process](#design-and-calling-process)
|
|
33
|
-
- [Module Flow](#module-flow)
|
|
34
|
-
- [How to Add Syntax Support](#how-to-add-syntax-support)
|
|
35
|
-
- [1. Constants](#1-constants)
|
|
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)
|
|
36
38
|
- [2. Lexer](#2-lexer)
|
|
37
39
|
- [3. Parser](#3-parser)
|
|
38
|
-
- [4.
|
|
40
|
+
- [4. Codegen](#4-codegen)
|
|
39
41
|
- [Tech Stack](#tech-stack)
|
|
40
42
|
- [Directory Structure](#directory-structure)
|
|
41
|
-
- [
|
|
43
|
+
- [Historical Background](#historical-background)
|
|
44
|
+
|
|
45
|
+
## Core Advantages
|
|
46
|
+
|
|
47
|
+
### What is MathML?
|
|
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
|
+

|
|
42
84
|
|
|
43
85
|
## Usage
|
|
44
86
|
|
|
45
|
-
### JavaScript
|
|
87
|
+
### JavaScript Examples
|
|
46
88
|
|
|
47
89
|
#### 1. Render TeX Formulas Directly
|
|
48
90
|
|
|
49
|
-
|
|
91
|
+
Use `@webc.site/math` to compile TeX formulas directly into MathML (ideal for Markdown parser plugins):
|
|
50
92
|
|
|
51
93
|
```javascript
|
|
52
94
|
import mathml from "@webc.site/math";
|
|
@@ -57,7 +99,7 @@ const html = mathml(tex, true); // true for block math, false/empty for inline m
|
|
|
57
99
|
|
|
58
100
|
#### 2. Replace Formulas in Markdown
|
|
59
101
|
|
|
60
|
-
|
|
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):
|
|
61
103
|
|
|
62
104
|
```javascript
|
|
63
105
|
import mdMath from "@webc.site/math/md.js";
|
|
@@ -74,7 +116,7 @@ console.log(html);
|
|
|
74
116
|
|
|
75
117
|
#### 1. Marked Extension
|
|
76
118
|
|
|
77
|
-
|
|
119
|
+
Use [`@webc.site/math-marked`](https://www.npmjs.com/package/@webc.site/math-marked) to automatically parse and compile inline (`$...$`) and block (`$$...$$`) formulas:
|
|
78
120
|
|
|
79
121
|
```javascript
|
|
80
122
|
import { marked } from "marked";
|
|
@@ -87,7 +129,7 @@ const html = marked.parse("Euler's identity: $$e^{i\\pi} + 1 = 0$$");
|
|
|
87
129
|
|
|
88
130
|
#### 2. Remark Plugin
|
|
89
131
|
|
|
90
|
-
|
|
132
|
+
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:
|
|
91
133
|
|
|
92
134
|
```javascript
|
|
93
135
|
import { unified } from "unified";
|
|
@@ -106,7 +148,7 @@ const html = await unified()
|
|
|
106
148
|
|
|
107
149
|
#### 3. Markdown-it Plugin
|
|
108
150
|
|
|
109
|
-
|
|
151
|
+
Use [`@webc.site/math-markdown-it`](https://www.npmjs.com/package/@webc.site/math-markdown-it) to automatically parse and render inline/block formulas in `markdown-it`:
|
|
110
152
|
|
|
111
153
|
```javascript
|
|
112
154
|
import markdownit from "markdown-it";
|
|
@@ -119,11 +161,11 @@ const html = md.render("Euler's identity: $$e^{i\\pi} + 1 = 0$$");
|
|
|
119
161
|
|
|
120
162
|
### CSS and Math Font Configuration
|
|
121
163
|
|
|
122
|
-
|
|
164
|
+
To ensure beautifully typeset browser-native math equations, using a math font is recommended. We recommend the **Latin Modern Math** font from the `18s` package (derived from Donald Knuth's classical Computer Modern, supporting OpenType MATH table features).
|
|
123
165
|
|
|
124
166
|
#### 1. Online Reference (Recommended)
|
|
125
167
|
|
|
126
|
-
|
|
168
|
+
Import the online font in CSS:
|
|
127
169
|
|
|
128
170
|
```css
|
|
129
171
|
/* Import the bundle (includes Source Han Sans t, monospace c, and math font m) */
|
|
@@ -144,7 +186,7 @@ npm install 18s
|
|
|
144
186
|
|
|
145
187
|
##### Import Local Font
|
|
146
188
|
|
|
147
|
-
|
|
189
|
+
Choose one of the following methods (Note: do not mix JS and CSS imports):
|
|
148
190
|
|
|
149
191
|
###### Method 1: Import in JS/TS Entry File
|
|
150
192
|
|
|
@@ -174,32 +216,37 @@ Or import math font `m` only:
|
|
|
174
216
|
|
|
175
217
|
#### 3. Configure CSS Style
|
|
176
218
|
|
|
177
|
-
Set the
|
|
219
|
+
Set the font family for the `math` tag in your global CSS stylesheet.
|
|
220
|
+
|
|
221
|
+
##### Option A: Using Hosted/Local Fonts (Recommended for best visual quality)
|
|
222
|
+
|
|
223
|
+
For projects importing the `18s` font assets (which contains the optimized math font `m` and Source Han Sans `t`):
|
|
178
224
|
|
|
179
225
|
```css
|
|
180
226
|
math {
|
|
181
|
-
/* m is the math font, t is Source Han Sans (optimized with font slicing for Chinese characters to boost loading performance), sans-serif is default fallback */
|
|
182
|
-
font-family: m, t, sans-serif;
|
|
227
|
+
/* 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 */
|
|
228
|
+
font-family: m, t, math, sans-serif;
|
|
183
229
|
}
|
|
184
230
|
```
|
|
185
231
|
|
|
186
|
-
|
|
232
|
+
##### Option B: Using System Math Fonts (Zero external font assets)
|
|
187
233
|
|
|
188
|
-
-
|
|
189
|
-
- **Robust & Fault-Tolerant**: When parsing Markdown text, syntax errors (such as unclosed `\left`/`\right` or invalid syntax) are caught automatically and gracefully degraded, returning the raw TeX code to prevent application crashes.
|
|
190
|
-
- **Fast Compiler**: Compiles TeX formulas directly to semantic MathML without external parser dependencies.
|
|
191
|
-
- **Markdown Integration**: Automatically parses inline math (`$formula$`) and block math (`$$formula$$`) in Markdown text.
|
|
192
|
-
- **High Performance**: Only 7.78 KB raw size (3.58 KB gzipped), far smaller than KaTeX and MathJax (see size comparison chart below):
|
|
234
|
+
Leverage system-default math fonts to minimize loading size:
|
|
193
235
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
236
|
+
```css
|
|
237
|
+
math {
|
|
238
|
+
/* Prioritize system-built-in math fonts, fallback to standard CSS 'math' generic font family */
|
|
239
|
+
font-family: "STIX Two Math", "Latin Modern Math", "Cambria Math", math;
|
|
240
|
+
}
|
|
241
|
+
```
|
|
199
242
|
|
|
200
|
-
|
|
243
|
+
## Features
|
|
201
244
|
|
|
202
|
-
- **
|
|
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.
|
|
203
250
|
|
|
204
251
|
## Supported Syntax List
|
|
205
252
|
|
|
@@ -209,55 +256,55 @@ Designed to be extremely lightweight, this library supports the most commonly us
|
|
|
209
256
|
- **Subscripts & Superscripts**:
|
|
210
257
|
- Superscript `^` (e.g., `x^2`)
|
|
211
258
|
- Subscript `_` (e.g., `x_i`)
|
|
212
|
-
-
|
|
213
|
-
-
|
|
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`)
|
|
214
261
|
- **Fractions**: `\frac{numerator}{denominator}` (e.g., `\frac{a}{b}`)
|
|
215
|
-
- **
|
|
262
|
+
- **Roots**: Square root `\sqrt{x}` and $n$-th root `\sqrt[n]{x}`
|
|
216
263
|
- **Overlines & Bars**: `\overline{x}` and the shorthand `\bar{x}`
|
|
217
|
-
- **
|
|
264
|
+
- **Delimiters & Brackets**: `\left` and `\right` structures (e.g., `\left( ... \right)`). Supported delimiters include:
|
|
218
265
|
- Parentheses: `(` and `)`
|
|
219
266
|
- Square brackets: `[` and `]`
|
|
220
|
-
-
|
|
221
|
-
- Angle brackets: `<`
|
|
267
|
+
- Braces: `\{` and `\}`
|
|
268
|
+
- Angle brackets: `<` and `>`
|
|
222
269
|
- Vertical bars: `|` or `\|`
|
|
223
|
-
-
|
|
270
|
+
- Empty delimiter: `.` (hides the delimiter on that side, e.g., `\left. \frac{df}{dx} \right| _0`)
|
|
224
271
|
- **Text Mode**: `\text{...}` (e.g., `\text{if }`), extracts literal text inside braces and renders it as MathML `<mtext>` in normal upright font.
|
|
225
|
-
- **Horizontal Spacing**: Supports `\quad` (1em
|
|
272
|
+
- **Horizontal Spacing**: Supports `\quad` (1em spacing) and `\qquad` (2em spacing).
|
|
226
273
|
- **Styles, Strikethroughs & Phantom**:
|
|
227
|
-
-
|
|
228
|
-
- Strikethroughs: `\cancel{...}` (
|
|
229
|
-
- Hiding & Spacing: `\phantom{...}` (
|
|
230
|
-
- **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`.
|
|
231
|
-
- **Modulo
|
|
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)$)
|
|
232
279
|
- **Greek Letters**:
|
|
233
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$)
|
|
234
|
-
- Uppercase (rendered upright): `\Delta` ($\Delta$), `\Gamma` ($\Gamma$), `\Theta` ($\Theta$), `\Lambda` ($\Lambda$), `\Xi` ($\Xi$), `\Pi` ($\Pi$), `\Sigma` ($\Sigma$), `\Upsilon` ($\Upsilon$), `\Phi` ($\Phi$), `\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$)
|
|
235
282
|
- **Operators & Relations**:
|
|
236
283
|
- `\le` / `\leq` ($\le$), `\ge` / `\geq` ($\ge$), `\ne` / `\neq` ($\ne$)
|
|
237
284
|
- `\cdot` ($\cdot$), `\times` ($\times$), `\pm` ($\pm$), `\mp` ($\mp$), `\div` ($\div$), `\infty` ($\infty$)
|
|
238
285
|
- `\approx` ($\approx$), `\sim` ($\sim$), `\cong` ($\cong$), `\propto` ($\propto$), `\equiv` ($\equiv$), `\perp` ($\perp$), `\parallel` ($\parallel$)
|
|
239
286
|
- **Calculus, Sets & Logic**:
|
|
240
|
-
- Gradient: `\nabla` ($\nabla$),
|
|
241
|
-
-
|
|
287
|
+
- Gradient: `\nabla` ($\nabla$), partial differential: `\partial` ($\partial$)
|
|
288
|
+
- Quantifiers & operations: `\forall` ($\forall$), `\exists` ($\exists$), `\neg` ($\neg$), `\land` ($\land$), `\lor` ($\lor$)
|
|
242
289
|
- Set relations: `\in` ($\in$), `\notin` ($\notin$), `\ni` ($\ni$), `\subset` ($\subset$), `\supset` ($\supset$), `\subseteq` ($\subseteq$), `\supseteq` ($\supseteq$)
|
|
243
|
-
- Set operations: `\cup` ($\cup$), `\cap` ($\cap$),
|
|
290
|
+
- Set operations: `\cup` ($\cup$), `\cap` ($\cap$), empty set: `\emptyset` ($\emptyset$)
|
|
244
291
|
- Special variables & constants: `\ell` ($\ell$), `\hbar` ($\hbar$)
|
|
245
|
-
-
|
|
292
|
+
- Large operators: summation `\sum` ($\sum$), integration `\int` ($\int$)
|
|
246
293
|
- **Arrows**:
|
|
247
|
-
-
|
|
248
|
-
-
|
|
249
|
-
- **
|
|
294
|
+
- Single arrows: `\to` / `\rightarrow` ($\rightarrow$), `\leftarrow` / `\gets` ($\leftarrow$), `\Leftarrow` ($\Leftarrow$), `\Rightarrow` ($\Rightarrow$)
|
|
295
|
+
- Double arrows: `\leftrightarrow` ($\leftrightarrow$), `\Leftrightarrow` ($\Leftrightarrow$)
|
|
296
|
+
- **Dots**:
|
|
250
297
|
- Baseline dots: `\dots` / `\ldots` ($\dots$)
|
|
251
|
-
-
|
|
298
|
+
- Centered dots: `\cdots` ($\cdots$)
|
|
252
299
|
- **Matrices & Multi-line Layouts**:
|
|
253
300
|
- Matrix environments: `matrix`, `pmatrix`, `bmatrix`, `vmatrix`, `Vmatrix` (e.g., `\begin{pmatrix} a & b \\ c & d \end{pmatrix}`)
|
|
254
|
-
-
|
|
255
|
-
- General
|
|
256
|
-
- Line breaks &
|
|
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.
|
|
257
304
|
|
|
258
|
-
|
|
305
|
+
## Unsupported Syntax
|
|
259
306
|
|
|
260
|
-
Currently, the following LaTeX extensions,
|
|
307
|
+
Currently, the following LaTeX extensions, macros, or fine-tuning style directives are not supported:
|
|
261
308
|
|
|
262
309
|
1. **Macro Definitions**: `\newcommand`, `\renewcommand`, `\providecommand`, `\gdef`, `\let`, etc.
|
|
263
310
|
2. **Background Colors & Advanced Borders**: `\colorbox`, `\fcolorbox`, `\cellcolor`, etc. (while `\boxed` is supported).
|
|
@@ -267,18 +314,16 @@ Currently, the following LaTeX extensions, macro definitions, or custom styling
|
|
|
267
314
|
6. **Verbatim Text**: `\verb`, etc.
|
|
268
315
|
7. **Advanced Positionings**: `\sideset`, `\prescript`, `\cramped`, `\flatfrac`, etc.
|
|
269
316
|
8. **Equation Numbering & Custom Tags**: `\tag`, `\newtagform`, `\usetagform`, etc.
|
|
270
|
-
9. **Arbitrary Operator Limits**: Except for predefined big operators (`\sum`, `\int`) and limit-like operators (`\lim`), using `\limits` on arbitrary commands or structures
|
|
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.
|
|
271
318
|
|
|
272
319
|
## Error Handling and Fault Tolerance
|
|
273
320
|
|
|
274
|
-
When parsing Markdown text using `@webc.site/math/md.js`,
|
|
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.
|
|
275
322
|
|
|
276
|
-
|
|
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.
|
|
277
324
|
|
|
278
325
|
### Internal Error Codes
|
|
279
326
|
|
|
280
|
-
The following error codes are used internally during the compilation phase to signal specific syntax issues. These are primarily useful for development, debugging, and testing:
|
|
281
|
-
|
|
282
327
|
| Error Code | Constant | Description | Trigger Example |
|
|
283
328
|
| :--------: | :------------------ | :-------------------------------------------- | :------------------------------------ |
|
|
284
329
|
| `0` | `ERR_EXTRA_END` | Extra or invalid `\end` command | `\end{matrix}` (no matching `\begin`) |
|
|
@@ -286,175 +331,121 @@ The following error codes are used internally during the compilation phase to si
|
|
|
286
331
|
| `2` | `ERR_EXTRA_RIGHT` | Extra or invalid `\right` command | `x \right)` (no matching `\left`) |
|
|
287
332
|
| `3` | `ERR_MISSING_BRACE` | Command missing required curly brace `{}` | `\text x` (missing braces) |
|
|
288
333
|
|
|
289
|
-
##
|
|
290
|
-
|
|
291
|
-
MathML (Mathematical Markup Language) is an XML-based standard for describing mathematical notations and capturing both its structure and content on the web.
|
|
292
|
-
|
|
293
|
-
**Since January 2023** (with the release of Chrome 109 and native Blink engine support), MathML Core has been fully supported natively across all three major web rendering engines (Chromium/Blink, Gecko/Firefox, and WebKit/Safari). This ensures highly efficient and native rendering of mathematical equations across most desktop/mobile devices and modern browser versions without needing heavy client-side JavaScript rendering engines.
|
|
294
|
-
|
|
295
|
-
### Why Compile TeX Formulas to MathML?
|
|
296
|
-
|
|
297
|
-
While MathML is the native web standard for mathematical typesetting, its XML-based syntax is too verbose for direct human authoring. TeX/LaTeX syntax remains the de facto standard for writing mathematical formulas (e.g., writing `$e^{i\pi} + 1 = 0$` in Markdown).
|
|
298
|
-
|
|
299
|
-
Traditional web math solutions (such as MathJax or KaTeX) require loading hundreds of kilobytes to several megabytes of JS/CSS typesetting engines in the frontend, consuming substantial client-side CPU cycles for DOM mutations and layout calculations.
|
|
300
|
-
|
|
301
|
-
By compiling TeX directly to native MathML using `@webc.site/math`, you get the best of both worlds—especially in **client-side (frontend) rendering** scenarios:
|
|
302
|
-
|
|
303
|
-
#### 1. Extremely Lightweight (~1.8 KB Gzip) & Zero Dependencies
|
|
304
|
-
|
|
305
|
-
Compared to KaTeX (300 KB+) and MathJax (several MBs), `@webc.site/math` has a virtually negligible footprint. It can be bundled directly into any frontend/SPA app without hurting initial page load times.
|
|
306
|
-
|
|
307
|
-
#### 2. Native Browser Layout (No Heavy Client-Side Rendering Engine)
|
|
308
|
-
|
|
309
|
-
Traditional math libraries pack not only a TeX parser but also a heavy client-side layout engine to calculate font metrics, alignment, and spacing, producing massive DOM trees or SVG elements.
|
|
310
|
-
Our compiler acts as a translator that turns TeX into standard MathML tags on the client, leaving all the heavy rendering, typography, and positioning tasks to the browser's native C++ layout engine. This drastically reduces JavaScript execution time.
|
|
311
|
-
|
|
312
|
-
#### 3. Seamless Real-Time Frontend Previews & Low CPU Overhead
|
|
313
|
-
|
|
314
|
-
Because the compilation is purely a fast tag-mapping step and layout is handled natively, CPU usage is minimal. This makes it ideal for **WYSIWYG editors, live markdown previewers, and interactive apps** where formulas need to be rendered dynamically on every keystroke without lag—even on low-end mobile devices.
|
|
315
|
-
|
|
316
|
-
#### 4. Unified Frontend and SSR Capabilities
|
|
317
|
-
|
|
318
|
-
Since the output is standard HTML with MathML elements, the same compiler works seamlessly for dynamic client-side rendering (CSR), server-side rendering (SSR), and static site generation (SSG) alike.
|
|
319
|
-
|
|
320
|
-
## Benchmark
|
|
321
|
-
|
|
322
|
-
Since KaTeX and MathJax are pure TeX compilers (without Markdown parsing features), to ensure a fair comparison, our benchmark directly compares the TeX compiler core ([@webc.site/math/mathml.js](https://github.com/webc-site/math/blob/dev/src/mathml.js)) against them.
|
|
323
|
-
|
|
324
|
-
### 1. Size Comparison (Gzipped)
|
|
325
|
-
|
|
326
|
-
| Library | Raw Size | Gzip Size | Size Ratio |
|
|
327
|
-
| :-------------------------------------------- | :-------: | :-------: | :--------: |
|
|
328
|
-
| @webc.site/math (Ours) | 7.78 KB | 3.58 KB | 1.0 ⭐️ |
|
|
329
|
-
| [KaTeX](https://github.com/KaTeX/KaTeX) | 264.79 KB | 75.15 KB | 21.0 |
|
|
330
|
-
| [MathJax](https://github.com/mathjax/MathJax) | 971.04 KB | 278.39 KB | 77.7 |
|
|
331
|
-
|
|
332
|
-

|
|
333
|
-
|
|
334
|
-
### 2. Generation Speed (Ops/sec)
|
|
334
|
+
## Design and Workflow
|
|
335
335
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
- **@webc.site/math (Ours)**: ~329, 000 ops/s (1.0 ⭐️)
|
|
339
|
-
- **[KaTeX](https://github.com/KaTeX/KaTeX)**: ~92, 000 ops/s (~3.6x slower)
|
|
340
|
-
- **[MathJax](https://github.com/mathjax/MathJax)**: ~6, 700 ops/s (~48.8x slower)
|
|
341
|
-
|
|
342
|
-

|
|
343
|
-
|
|
344
|
-
## Design and Calling Process
|
|
345
|
-
|
|
346
|
-
The parser processes input Markdown string, isolates TeX expressions, and translates them to MathML structures.
|
|
336
|
+
The parser processes the input Markdown string, isolates TeX expressions, and translates them into MathML structures.
|
|
347
337
|
|
|
348
338
|
```mermaid
|
|
349
339
|
graph TD
|
|
350
340
|
A[Input Markdown] --> B{Scanner}
|
|
351
|
-
B --
|
|
352
|
-
B -- TeX Formula --> D[Lexer:
|
|
353
|
-
D --> E[Parser: AST
|
|
354
|
-
E --> F[
|
|
355
|
-
F --> G[Semantic
|
|
341
|
+
B -- Plain Text --> C[Output Buffer]
|
|
342
|
+
B -- TeX Formula --> D[Lexer: Generate Tokens]
|
|
343
|
+
D --> E[Parser: Generate AST]
|
|
344
|
+
E --> F[Codegen: Generate MathML Tags]
|
|
345
|
+
F --> G[Semantic Wrapper]
|
|
356
346
|
G --> H[MathML Output]
|
|
357
347
|
C --> I[Final HTML]
|
|
358
348
|
H --> I
|
|
359
349
|
```
|
|
360
350
|
|
|
361
|
-
### Module
|
|
351
|
+
### Module Stages
|
|
362
352
|
|
|
363
|
-
1. **Scanner**: Scans the input string to locate delimiters (`$` and `$$`).
|
|
364
|
-
2. **Lexer**:
|
|
365
|
-
3. **Parser**:
|
|
366
|
-
4. **
|
|
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>`).
|
|
367
357
|
|
|
368
|
-
##
|
|
358
|
+
## Adding New Syntax
|
|
369
359
|
|
|
370
|
-
To add support for a new LaTeX
|
|
360
|
+
To add support for a new LaTeX command, modify the following four core parts in order:
|
|
371
361
|
|
|
372
|
-
### 1.
|
|
362
|
+
### 1. Constant Definitions
|
|
373
363
|
|
|
374
|
-
Define the corresponding lexical
|
|
364
|
+
Define the corresponding lexical token, AST node type, function name, or symbol mapping:
|
|
375
365
|
|
|
376
|
-
- **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 = ...`
|
|
377
|
-
- **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 = ...`
|
|
378
|
-
- **Environment Delimiters**: If adding a new environment (
|
|
379
|
-
- **Symbol
|
|
380
|
-
- **Function
|
|
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).
|
|
381
371
|
|
|
382
372
|
### 2. Lexer
|
|
383
373
|
|
|
384
|
-
The `lex(str)` function
|
|
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).
|
|
385
375
|
|
|
386
|
-
- If
|
|
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.
|
|
387
377
|
|
|
388
378
|
### 3. Parser
|
|
389
379
|
|
|
390
|
-
The `parse(tokens, state)` function
|
|
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).
|
|
391
381
|
|
|
392
|
-
- **Command Parsing**: Handled
|
|
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]`.
|
|
393
383
|
|
|
394
|
-
### 4.
|
|
384
|
+
### 4. Codegen
|
|
395
385
|
|
|
396
|
-
The `SHOW_MAP` dictionary
|
|
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).
|
|
397
387
|
|
|
398
|
-
- Register a
|
|
388
|
+
- Register a renderer function: `[TYPE_MY_NODE]: ([_, arg1, arg2]) => nest("mylabel", arg1, arg2)`, formatting node data into native MathML tags.
|
|
399
389
|
|
|
400
390
|
## Tech Stack
|
|
401
391
|
|
|
402
392
|
- **Runtime**: Bun, Node.js
|
|
403
|
-
- **
|
|
404
|
-
- **
|
|
393
|
+
- **Build & Bundle**: SWC (compression), Vite (demo site)
|
|
394
|
+
- **Quality Assurance**: oxlint, oxfmt
|
|
405
395
|
|
|
406
396
|
## Directory Structure
|
|
407
397
|
|
|
408
398
|
```
|
|
409
399
|
.
|
|
410
|
-
├── demo/ # Interactive
|
|
411
|
-
│ ├── const/ # Constants (formulas,
|
|
412
|
-
│ ├── i18n/ #
|
|
413
|
-
│ ├── index.js #
|
|
400
|
+
├── demo/ # Interactive demo site
|
|
401
|
+
│ ├── const/ # Constants (preset formulas, language list)
|
|
402
|
+
│ ├── i18n/ # Language translation configurations
|
|
403
|
+
│ ├── index.js # Interactive demo logic
|
|
414
404
|
│ ├── index.pug # Pug HTML template
|
|
415
|
-
│ └── style.styl #
|
|
416
|
-
├── extract/ #
|
|
417
|
-
├── lib/ #
|
|
418
|
-
│ ├── package.json #
|
|
419
|
-
│ ├── README.md # Automatically
|
|
420
|
-
│ ├── mathml.js # Minified
|
|
421
|
-
│ ├── mathml.js.map # Source map for
|
|
422
|
-
│ ├── md.js # Minified
|
|
423
|
-
│ └── md.js.map # Source map for
|
|
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
|
|
424
414
|
├── src/ # Source code
|
|
425
|
-
│ ├── const/ #
|
|
426
|
-
│ ├── lex.js # LaTeX
|
|
427
|
-
│ ├── parse.js # LaTeX
|
|
415
|
+
│ ├── const/ # Tokens, AST types, symbol maps, and function names
|
|
416
|
+
│ ├── lex.js # LaTeX lexer
|
|
417
|
+
│ ├── parse.js # LaTeX parser (AST generation)
|
|
428
418
|
│ ├── mathml.js # TeX-to-MathML compiler
|
|
429
|
-
│ └── md.js # Markdown
|
|
430
|
-
├── sh/ #
|
|
431
|
-
│ ├── bench/ # Benchmark scripts,
|
|
432
|
-
│ │ ├── pk.js # Size
|
|
433
|
-
│ │ ├── self.js #
|
|
434
|
-
│ │ ├── util.js # Shared
|
|
435
|
-
│ │ ├── chart.js # SVG chart
|
|
436
|
-
│ │ └── history.yml # YAML
|
|
419
|
+
│ └── md.js # Markdown mathematical formula parser
|
|
420
|
+
├── sh/ # Scripts
|
|
421
|
+
│ ├── bench/ # Benchmark scripts, charts, and historical baseline data
|
|
422
|
+
│ │ ├── pk.js # Size and speed comparison & chart generation
|
|
423
|
+
│ │ ├── self.js # Regression tests
|
|
424
|
+
│ │ ├── util.js # Shared helpers
|
|
425
|
+
│ │ ├── chart.js # SVG chart component
|
|
426
|
+
│ │ └── history.yml # YAML historical benchmark records
|
|
437
427
|
│ └── check.js # Language file validation script
|
|
438
|
-
├── dev.js #
|
|
439
|
-
├── dist.js #
|
|
440
|
-
├── minify.js #
|
|
441
|
-
├── package.json # Project
|
|
442
|
-
├── README.md #
|
|
443
|
-
├── README.mdt #
|
|
444
|
-
└── test.sh #
|
|
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
|
|
445
435
|
```
|
|
446
436
|
|
|
447
|
-
##
|
|
437
|
+
## Historical Background
|
|
448
438
|
|
|
449
|
-
|
|
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.
|
|
450
440
|
|
|
451
|
-
MathML
|
|
441
|
+
MathML Core specifies native mathematical typesetting in the browser. In 2023, the Blink engine introduced native support, enabling Chrome, Safari, and Firefox to natively lay out equations.
|
|
452
442
|
|
|
453
|
-
|
|
443
|
+
In combination with the **Latin Modern Math** font (`m` from `18s` package), `@webc.site/math` acts as a translator, compiling TeX equations directly to native MathML Core tags to eliminate client-side rendering engines.
|
|
454
444
|
|
|
455
445
|
---
|
|
456
446
|
|
|
457
447
|
<a id="zh"></a>
|
|
448
|
+
|
|
458
449
|
# @webc.site/math
|
|
459
450
|
|
|
460
451
|
### 全球最小最快的网页 Markdown 公式渲染器
|
|
@@ -465,40 +456,81 @@ The `18s` project provides a optimized math font `m` (Latin Modern Math, derived
|
|
|
465
456
|
|
|
466
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>
|
|
467
458
|
|
|
468
|
-
|
|
459
|
+
无需引入数百 KB 的 KaTeX/MathJax 及庞大的字体包。包体积仅约 4KB (Gzip),将 LaTeX 公式编译为浏览器原生支持的 MathML,实现零运行开销的公式渲染。
|
|
469
460
|
|
|
461
|
+
- [核心优势](#核心优势)
|
|
462
|
+
- [什么是 MathML?](#什么是-mathml)
|
|
463
|
+
- [为什么将 TeX 编译为 MathML?](#为什么将-tex-编译为-mathml)
|
|
464
|
+
- [性能对比](#性能对比)
|
|
465
|
+
- [1. 体积对比(Gzip 压缩)](#1-体积对比gzip-压缩)
|
|
466
|
+
- [2. 生成速度对比](#2-生成速度对比)
|
|
470
467
|
- [使用方法](#使用方法)
|
|
471
468
|
- [JavaScript 示例](#javascript-示例)
|
|
472
469
|
- [Markdown 解析器插件](#markdown-解析器插件)
|
|
473
470
|
- [CSS 与数学字体配置](#css-与数学字体配置)
|
|
474
471
|
- [功能特性](#功能特性)
|
|
475
472
|
- [支持的语法清单](#支持的语法清单)
|
|
476
|
-
|
|
473
|
+
- [不支持的语法](#不支持的语法)
|
|
477
474
|
- [错误处理与容错机制](#错误处理与容错机制)
|
|
478
475
|
- [内部错误码](#内部错误码)
|
|
479
|
-
- [什么是 MathML?](#什么是-mathml)
|
|
480
|
-
- [为什么需要 TeX 公式转 MathML?](#为什么需要-tex-公式转-mathml)
|
|
481
|
-
- [性能对比](#性能对比)
|
|
482
|
-
- [1. 体积对比(Gzip 压缩后)](#1-体积对比gzip-压缩后)
|
|
483
|
-
- [2. 生成速度对比 (Ops/sec)](#2-生成速度对比-opssec)
|
|
484
476
|
- [设计思路与调用流程](#设计思路与调用流程)
|
|
485
477
|
- [模块运行流程](#模块运行流程)
|
|
486
|
-
- [
|
|
487
|
-
- [1. 常量定义
|
|
488
|
-
- [2. 词法分析
|
|
489
|
-
- [3. 语法分析
|
|
490
|
-
- [4. 代码渲染
|
|
478
|
+
- [如何添加新语法](#如何添加新语法)
|
|
479
|
+
- [1. 常量定义](#1-常量定义)
|
|
480
|
+
- [2. 词法分析](#2-词法分析)
|
|
481
|
+
- [3. 语法分析](#3-语法分析)
|
|
482
|
+
- [4. 代码渲染](#4-代码渲染)
|
|
491
483
|
- [技术堆栈](#技术堆栈)
|
|
492
484
|
- [目录结构](#目录结构)
|
|
493
485
|
- [历史背景](#历史背景)
|
|
494
486
|
|
|
487
|
+
## 核心优势
|
|
488
|
+
|
|
489
|
+
### 什么是 MathML?
|
|
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
|
+
|
|
495
527
|
## 使用方法
|
|
496
528
|
|
|
497
529
|
### JavaScript 示例
|
|
498
530
|
|
|
499
531
|
#### 1. 直接渲染 TeX 公式
|
|
500
532
|
|
|
501
|
-
使用 `@webc.site/math
|
|
533
|
+
使用 `@webc.site/math` 将 TeX 公式编译为 MathML(适用于 Markdown 渲染插件开发):
|
|
502
534
|
|
|
503
535
|
```javascript
|
|
504
536
|
import mathml from "@webc.site/math";
|
|
@@ -509,7 +541,7 @@ const html = mathml(tex, true); // 第二个参数传 true 表示块级公式,
|
|
|
509
541
|
|
|
510
542
|
#### 2. 替换 Markdown 中的公式
|
|
511
543
|
|
|
512
|
-
使用 `@webc.site/math/md.js
|
|
544
|
+
使用 `@webc.site/math/md.js` 自动识别 Markdown 文本中的行内/块级公式并替换为 MathML(需传入公式编译器):
|
|
513
545
|
|
|
514
546
|
```javascript
|
|
515
547
|
import mdMath from "@webc.site/math/md.js";
|
|
@@ -526,7 +558,7 @@ console.log(html);
|
|
|
526
558
|
|
|
527
559
|
#### 1. Marked 插件
|
|
528
560
|
|
|
529
|
-
使用 [`@webc.site/math-marked`](https://www.npmjs.com/package/@webc.site/math-marked)
|
|
561
|
+
使用 [`@webc.site/math-marked`](https://www.npmjs.com/package/@webc.site/math-marked) 自动解析并编译行内(`$...$`)与块级(`$$...$$`)公式:
|
|
530
562
|
|
|
531
563
|
```javascript
|
|
532
564
|
import { marked } from "marked";
|
|
@@ -539,7 +571,7 @@ const html = marked.parse("欧拉恒等式:$$e^{i\\pi} + 1 = 0$$");
|
|
|
539
571
|
|
|
540
572
|
#### 2. Remark 插件
|
|
541
573
|
|
|
542
|
-
使用 [`@webc.site/math-remark`](https://www.npmjs.com/package/@webc.site/math-remark)
|
|
574
|
+
使用 [`@webc.site/math-remark`](https://www.npmjs.com/package/@webc.site/math-remark) 将 Unified/Remark AST 中的 `inlineMath` 与 `math` 节点替换为原生 MathML HTML:
|
|
543
575
|
|
|
544
576
|
```javascript
|
|
545
577
|
import { unified } from "unified";
|
|
@@ -558,7 +590,7 @@ const html = await unified()
|
|
|
558
590
|
|
|
559
591
|
#### 3. Markdown-it 插件
|
|
560
592
|
|
|
561
|
-
使用 [`@webc.site/math-markdown-it`](https://www.npmjs.com/package/@webc.site/math-markdown-it)
|
|
593
|
+
使用 [`@webc.site/math-markdown-it`](https://www.npmjs.com/package/@webc.site/math-markdown-it) 自动解析并渲染 `markdown-it` 中的行内与块级公式:
|
|
562
594
|
|
|
563
595
|
```javascript
|
|
564
596
|
import markdownit from "markdown-it";
|
|
@@ -571,11 +603,11 @@ const html = md.render("欧拉恒等式:$$e^{i\\pi} + 1 = 0$$");
|
|
|
571
603
|
|
|
572
604
|
### CSS 与数学字体配置
|
|
573
605
|
|
|
574
|
-
|
|
606
|
+
为保证浏览器原生数学公式的排版,建议配置数学字体。推荐使用 `18s` 字体包的 **Latin Modern Math**(源自高德纳的 Computer Modern 字体,支持 OpenType 数学排版特性)。
|
|
575
607
|
|
|
576
|
-
#### 1.
|
|
608
|
+
#### 1. 在线引用
|
|
577
609
|
|
|
578
|
-
|
|
610
|
+
在 CSS 中通过 `@import` 引入在线字体:
|
|
579
611
|
|
|
580
612
|
```css
|
|
581
613
|
/* 引入合并后的字体 CSS(包含思源黑体 t、代码字体 c 及数学字体 m) */
|
|
@@ -596,7 +628,7 @@ npm install 18s
|
|
|
596
628
|
|
|
597
629
|
##### 引入本地字体
|
|
598
630
|
|
|
599
|
-
|
|
631
|
+
选择以下一种方式引入字体映射(注意:请勿混用 JS 与 CSS 引入):
|
|
600
632
|
|
|
601
633
|
###### 方式 1:在项目入口 JS/TS 文件中引入
|
|
602
634
|
|
|
@@ -626,90 +658,95 @@ import "18s/m.css";
|
|
|
626
658
|
|
|
627
659
|
#### 3. 配置 CSS 样式
|
|
628
660
|
|
|
629
|
-
在全局 CSS 样式表中,为 `math`
|
|
661
|
+
在全局 CSS 样式表中,为 `math` 标签指定数学字体。
|
|
662
|
+
|
|
663
|
+
##### 方案 A:使用托管/本地字体(推荐,效果最完美)
|
|
664
|
+
|
|
665
|
+
引入 `18s` 提供的字体包(含切片优化思源黑体 `t` 与数学字体 `m`):
|
|
630
666
|
|
|
631
667
|
```css
|
|
632
668
|
math {
|
|
633
|
-
/* m 为数学字体,t 为思源黑体(对中文字符进行了切片优化以提升加载性能),sans-serif 为系统默认无衬线字体 */
|
|
634
|
-
font-family: m, t, sans-serif;
|
|
669
|
+
/* m 为数学字体,t 为思源黑体(对中文字符进行了切片优化以提升加载性能),math 为系统数学字体,sans-serif 为系统默认无衬线字体 */
|
|
670
|
+
font-family: m, t, math, sans-serif;
|
|
635
671
|
}
|
|
636
672
|
```
|
|
637
673
|
|
|
638
|
-
|
|
674
|
+
##### 方案 B:使用系统数学字体(免引入外部资源)
|
|
639
675
|
|
|
640
|
-
|
|
641
|
-
- **健壮容错**:在解析 Markdown 文本时,公式中的语法错误(如未闭合的 `\left`/`\right` 或其他非法语法)会被自动捕获并优雅退化,直接返回原始的 TeX 代码而不抛出 JavaScript 异常,防止前端应用崩溃。
|
|
642
|
-
- **快速编译**:直接编译 TeX 公式为语义化 MathML,无外部解析器依赖。
|
|
643
|
-
- **Markdown 集成**:自动解析 Markdown 文本中的行内公式(`$ 公式 $`)和块级公式(`$$ 公式 $$`)。
|
|
644
|
-
- **高性能**:原始体积仅 7.78 KB(Gzip 压缩后 3.58 KB),体积远小于 KaTeX 和 MathJax(见下图体积对比):
|
|
676
|
+
直接使用系统内置数学字体以最小化体积:
|
|
645
677
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
678
|
+
```css
|
|
679
|
+
math {
|
|
680
|
+
/* 优先使用各平台内置的数学字体,最后降级到 CSS 标准 math 泛型字体 */
|
|
681
|
+
font-family: "STIX Two Math", "Latin Modern Math", "Cambria Math", math;
|
|
682
|
+
}
|
|
683
|
+
```
|
|
651
684
|
|
|
652
|
-
|
|
685
|
+
## 功能特性
|
|
653
686
|
|
|
654
|
-
-
|
|
687
|
+
- **功能完备**:通过数千个 KaTeX/MathJax 官方测试用例(详见 [extract](https://github.com/webc-site/math/tree/dev/extract))。
|
|
688
|
+
- **健壮容错**:公式语法错误(如未闭合的 `\left`/`\right`)会自动捕获并降级显示原始公式,不抛出异常,防止应用崩溃。
|
|
689
|
+
- **快速编译**:无需外部依赖,直接将 TeX 公式编译为语义化 MathML。
|
|
690
|
+
- **Markdown 集成**:自动解析 Markdown 中的行内公式(`$ 公式 $`)和块级公式(`$$ 公式 $$`)。
|
|
691
|
+
- **标准兼容**:输出现代浏览器原生支持的标准 MathML 元素。
|
|
655
692
|
|
|
656
693
|
## 支持的语法清单
|
|
657
694
|
|
|
658
|
-
|
|
695
|
+
本库在极简的包体积下,支持最常用的数学公式排版语法:
|
|
659
696
|
|
|
660
697
|
- **基础算术与符号**:数字、英文字母、基础运算符(`+`, `-`, `*`, `/`, `=`, `<`, `>`, `(`, `)`, `[`, `]`, `.`)。其中 `-` 自动映射为减号 `\u2212`,`*` 映射为星号 `\u2217`,`/` 以直立体呈现。
|
|
661
|
-
-
|
|
698
|
+
- **上下标**:
|
|
662
699
|
- 上标 `^`(如 `x^2`)
|
|
663
700
|
- 下标 `_`(如 `x_i`)
|
|
664
701
|
- 同时存在上下标(如 `x_i^2` 或 `x^2_i`)
|
|
665
|
-
-
|
|
666
|
-
-
|
|
667
|
-
-
|
|
668
|
-
-
|
|
669
|
-
-
|
|
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)`)。支持的定界符包括:
|
|
670
707
|
- 圆括号:`(` 和 `)`
|
|
671
708
|
- 方括号:`[` 和 `]`
|
|
672
709
|
- 花括号:`\{` 和 `\}`
|
|
673
|
-
- 尖括号:`<`
|
|
710
|
+
- 尖括号:`<` 和 `>`
|
|
674
711
|
- 竖线:`|` 或 `\|`
|
|
675
712
|
- 空白定界符:`.`(表示不显示该侧定界符,例如 `\left. \frac{df}{dx} \right| _0`)
|
|
676
|
-
-
|
|
677
|
-
-
|
|
678
|
-
-
|
|
713
|
+
- **文本模式**:`\text{...}`(如 `\text{if }`),提取大括号中的字面文本,渲染为 MathML `<mtext>`,以常规直立体呈现。
|
|
714
|
+
- **水平间距**:支持 `\quad`(1em 间距)和 `\qquad`(2em 间距)的空格占位。
|
|
715
|
+
- **样式、删除线与占位隐藏**:
|
|
679
716
|
- 边框:`\boxed{...}`(在公式周围加上边框,如 `\boxed{x+y}`)
|
|
680
717
|
- 删除线与取消线:`\cancel{...}`(通过斜线划掉,如 `\cancel{x}`)和 `\sout{...}`(通过水平线划掉,如 `\sout{y}`)
|
|
681
718
|
- 隐藏与占位:`\phantom{...}`(生成与输入内容相同宽高的不可见占位空间,如 `\phantom{x}`)
|
|
682
|
-
-
|
|
683
|
-
-
|
|
684
|
-
-
|
|
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
|
+
- **希腊字母**:
|
|
685
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$)
|
|
686
723
|
- 大写希腊字母(以直立体呈现):`\Delta` ($\Delta$), `\Gamma` ($\Gamma$), `\Theta` ($\Theta$), `\Lambda` ($\Lambda$), `\Xi` ($\Xi$), `\Pi` ($\Pi$), `\Sigma` ($\Sigma$), `\Upsilon` ($\Upsilon$), `\Phi` ($\Phi$), `\Psi` ($\Psi$), `\Omega` ($\Omega$)
|
|
687
|
-
-
|
|
724
|
+
- **算术运算符与关系符**:
|
|
688
725
|
- `\le` / `\leq` ($\le$), `\ge` / `\geq` ($\ge$), `\ne` / `\neq` ($\ne$)
|
|
689
726
|
- `\cdot` ($\cdot$), `\times` ($\times$), `\pm` ($\pm$), `\mp` ($\mp$), `\div` ($\div$), `\infty` ($\infty$)
|
|
690
727
|
- `\approx` ($\approx$), `\sim` ($\sim$), `\cong` ($\cong$), `\propto` ($\propto$), `\equiv` ($\equiv$), `\perp` ($\perp$), `\parallel` ($\parallel$)
|
|
691
|
-
-
|
|
728
|
+
- **微积分、集合与逻辑符号**:
|
|
692
729
|
- 梯度:`\nabla` ($\nabla$),偏微分:`\partial` ($\partial$)
|
|
693
730
|
- 逻辑量词与运算:`\forall` ($\forall$),`\exists` ($\exists$),`\neg` ($\neg$),`\land` ($\land$),`\lor` ($\lor$)
|
|
694
731
|
- 集合关系:`\in` ($\in$),`\notin` ($\notin$),`\ni` ($\ni$),`\subset` ($\subset$),`\supset` ($\supset$),`\subseteq` ($\subseteq$),`\supseteq` ($\supseteq$)
|
|
695
732
|
- 集合运算:`\cup` ($\cup$),`\cap` ($\cap$),空集:`\emptyset` ($\emptyset$)
|
|
696
733
|
- 特殊变量与常量:`\ell` ($\ell$), `\hbar` ($\hbar$)
|
|
697
734
|
- 大型运算符:求和 `\sum` ($\sum$),积分 `\int` ($\int$)
|
|
698
|
-
-
|
|
735
|
+
- **箭头符号**:
|
|
699
736
|
- 单向箭头:`\to` / `\rightarrow` ($\rightarrow$), `\leftarrow` / `\gets` ($\leftarrow$), `\Leftarrow` ($\Leftarrow$), `\Rightarrow` ($\Rightarrow$)
|
|
700
737
|
- 双向箭头:`\leftrightarrow` ($\leftrightarrow$), `\Leftrightarrow` ($\Leftrightarrow$)
|
|
701
|
-
-
|
|
738
|
+
- **省略号**:
|
|
702
739
|
- 基线省略号:`\dots` / `\ldots` ($\dots$)
|
|
703
740
|
- 居中省略号:`\cdots` ($\cdots$)
|
|
704
|
-
-
|
|
741
|
+
- **矩阵与多行排版**:
|
|
705
742
|
- 矩阵环境:`matrix`, `pmatrix`, `bmatrix`, `vmatrix`, `Vmatrix`(如 `\begin{pmatrix} a & b \\ c & d \end{pmatrix}`)
|
|
706
743
|
- 方程组与条件分支:`cases`(如 `\begin{cases} x & x \ge 0 \\ -x & x < 0 \end{cases}`)
|
|
707
744
|
- 通用数组排版:`array`
|
|
708
|
-
- 换行与对齐:使用 `\\`、`\\*` 或 `\\[width]
|
|
745
|
+
- 换行与对齐:使用 `\\`、`\\*` 或 `\\[width]` 进行换行,以及使用 `&` 进行列对齐
|
|
709
746
|
|
|
710
|
-
|
|
747
|
+
## 不支持的语法
|
|
711
748
|
|
|
712
|
-
|
|
749
|
+
目前不支持以下 LaTeX 扩展、宏定义或样式微调指令:
|
|
713
750
|
|
|
714
751
|
1. **宏定义命令**:`\newcommand`, `\renewcommand`, `\providecommand`, `\gdef`, `\let` 等。
|
|
715
752
|
2. **背景色与高级边框**:`\colorbox`, `\fcolorbox`, `\cellcolor` 等(支持 `\boxed`)。
|
|
@@ -719,18 +756,16 @@ math {
|
|
|
719
756
|
6. **代码/文本抄录**:`\verb` 等。
|
|
720
757
|
7. **高级上/下标定位**:`\sideset`, `\prescript`, `\cramped`, `\flatfrac` 等。
|
|
721
758
|
8. **公式编号与自定义标签**:`\tag`, `\newtagform`, `\usetagform` 等。
|
|
722
|
-
9.
|
|
759
|
+
9. **任意运算符的限位强制调整**:除预设的 `\sum`, `\int` 等大型运算符和 `\lim` 等极限算子外,不支持对任意自定义命令或结构使用 `\limits` 强制限位。
|
|
723
760
|
|
|
724
761
|
## 错误处理与容错机制
|
|
725
762
|
|
|
726
|
-
|
|
763
|
+
使用 `@webc.site/math/md.js` 解析 Markdown 文本时,若包含非法 LaTeX 语法,内部会自动捕获错误并退化为原始公式文本(如 `$$x + \left( y$$`),不抛出 JS 异常。因此,调用时**无需**包裹 `try...catch`。
|
|
727
764
|
|
|
728
|
-
|
|
765
|
+
如直接调用 `@webc.site/math` 编译非法 LaTeX,则会抛出错误码数组(详见下表),建议使用 `try...catch` 包裹。
|
|
729
766
|
|
|
730
767
|
### 内部错误码
|
|
731
768
|
|
|
732
|
-
在解析器内部编译公式时,可能会产生以下错误码。这些错误码主要在开发或单元测试时用于指示语法错误的具体类型:
|
|
733
|
-
|
|
734
769
|
| 错误码 | 常量名 | 含义 | 触发示例 |
|
|
735
770
|
| :----: | :------------------ | :-------------------------------- | :--------------------------------- |
|
|
736
771
|
| `0` | `ERR_EXTRA_END` | 多余或非法的 `\end` 指令 | `\end{matrix}` (无对应的 `\begin`) |
|
|
@@ -738,60 +773,6 @@ math {
|
|
|
738
773
|
| `2` | `ERR_EXTRA_RIGHT` | 多余或非法的 `\right` 指令 | `x \right)` (无对应的 `\left`) |
|
|
739
774
|
| `3` | `ERR_MISSING_BRACE` | 命令缺少必填的大括号参数 | `\text x` (缺少 `{}`) |
|
|
740
775
|
|
|
741
|
-
## 什么是 MathML?
|
|
742
|
-
|
|
743
|
-
MathML(Mathematical Markup Language,数学标记语言)是一种基于 XML 的标准,用于在 Web 页面中描述数学公式的结构与语义。
|
|
744
|
-
|
|
745
|
-
**自 2023 年 1 月起**(随着 Chrome 109 正式启用对 MathML Core 的原生支持),此特性已被所有主流浏览器渲染引擎(Chromium/Blink、Gecko/Firefox、WebKit/Safari)全面且原生支持,这标志着无需加载任何 JavaScript 排版库,即可在绝大多数桌面端、移动端设备及主流浏览器版本中正常、快速地呈现数学公式。
|
|
746
|
-
|
|
747
|
-
### 为什么需要 TeX 公式转 MathML?
|
|
748
|
-
|
|
749
|
-
虽然 MathML 是浏览器原生支持的数学排版标准,但它的 XML 语法极其繁琐,不适合人类直接书写。人类书写数学公式的事实标准是 **TeX/LaTeX** 语法(例如在 Markdown 中书写 `$e^{i\pi} + 1 = 0$`)。
|
|
750
|
-
|
|
751
|
-
传统的网页公式解决方案(如 MathJax 或 KaTeX)在前端运行,需要加载数以百 KB 甚至数 MB 的 JS/CSS 排版引擎,并消耗大量客户端 CPU 进行复杂的 DOM 重绘与排版计算,非常臃肿。
|
|
752
|
-
|
|
753
|
-
使用 `@webc.site/math` 将 TeX 编译为 MathML,可以完美解决这些痛点,尤其在**前端渲染(Client-side Rendering)**场景下具有压倒性优势:
|
|
754
|
-
|
|
755
|
-
#### 1. 极致轻量(~1.8 KB Gzip)与零运行依赖
|
|
756
|
-
|
|
757
|
-
相比于 KaTeX (300 KB+) 和 MathJax (数 MB) 的庞大体积,`@webc.site/math` 极其微小。你可以轻松地将它打包进任何前端/单页应用(SPA)中,几乎不增加首屏加载时间。
|
|
758
|
-
|
|
759
|
-
#### 2. 利用浏览器原生排版,省去前端渲染引擎
|
|
760
|
-
|
|
761
|
-
传统的公式库不仅是个“解析器”,还包含一整套“前端排版引擎”(用于计算字符宽高、间距,并使用绝对定位生成成百上千个 DOM 节点或 SVG 元素)。而本库只负责在前端将 TeX 代码“翻译”成标准的 MathML 语义标签,具体的排版布局完全交由浏览器底层的 C++ 原生引擎渲染。这极大地解放了浏览器的 JS 线程和主线程。
|
|
762
|
-
|
|
763
|
-
#### 3. 流畅的前端实时预览与极低 CPU 消耗
|
|
764
|
-
|
|
765
|
-
因为只做简单的标签翻译,且将排版工作外包给了浏览器原生引擎,本库在前端执行速度极快、CPU 开销极低。这使得它非常适合用于**公式编辑器、Markdown 编辑器等实时预览场景**,输入公式时可以做到瞬时无缝渲染,即使在配置较低的移动端设备上也能保持极高的流畅度。
|
|
766
|
-
|
|
767
|
-
#### 4. 前后端通用,统一的技术栈
|
|
768
|
-
|
|
769
|
-
由于编译输出的是纯 HTML 标准的 MathML 元素,无论是作为前端排版(在浏览器端动态转换并插入 DOM),还是在构建期(SSR/SSG)静态编译为 HTML,都能保持完全一致的高效表现。
|
|
770
|
-
|
|
771
|
-
## 性能对比
|
|
772
|
-
|
|
773
|
-
由于 KaTeX 和 MathJax 本身是 TeX 公式编译器(不包含 Markdown 解析功能),为了确保基准测试的公平性,我们使用本库的 TeX 编译器核心([@webc.site/math/mathml.js](https://github.com/webc-site/math/blob/dev/src/mathml.js))直接与它们进行对比。
|
|
774
|
-
|
|
775
|
-
### 1. 体积对比(Gzip 压缩后)
|
|
776
|
-
|
|
777
|
-
| 库 | 原始体积 | Gzip 体积 | 尺寸比 |
|
|
778
|
-
| :-------------------------------------------- | :-------: | :-------: | :----: |
|
|
779
|
-
| @webc.site/math (本库) | 7.78 KB | 3.58 KB | 1.0 ⭐️ |
|
|
780
|
-
| [KaTeX](https://github.com/KaTeX/KaTeX) | 264.79 KB | 75.15 KB | 21.0 |
|
|
781
|
-
| [MathJax](https://github.com/mathjax/MathJax) | 971.04 KB | 278.39 KB | 77.7 |
|
|
782
|
-
|
|
783
|
-

|
|
784
|
-
|
|
785
|
-
### 2. 生成速度对比 (Ops/sec)
|
|
786
|
-
|
|
787
|
-
基于经典公式循环编译测试(使用 [sh/bench/pk.js](https://github.com/webc-site/math/blob/dev/sh/bench/pk.js) 测得):
|
|
788
|
-
|
|
789
|
-
- **@webc.site/math (本库)**: ~329, 000 ops/s (1.0 ⭐️)
|
|
790
|
-
- **[KaTeX](https://github.com/KaTeX/KaTeX)**: ~92, 000 ops/s (约 3.6x 较慢)
|
|
791
|
-
- **[MathJax](https://github.com/mathjax/MathJax)**: ~6, 700 ops/s (约 48.8x 较慢)
|
|
792
|
-
|
|
793
|
-

|
|
794
|
-
|
|
795
776
|
## 设计思路与调用流程
|
|
796
777
|
|
|
797
778
|
解析器处理输入的 Markdown 字符串,隔离 TeX 表达式,并将其转换为 MathML 结构。
|
|
@@ -816,37 +797,37 @@ graph TD
|
|
|
816
797
|
3. **语法分析**:将 Token 转换为抽象语法树(AST)节点,支持分式、上下标及预设数学函数。
|
|
817
798
|
4. **代码生成**:将 AST 节点映射为标准 XML 节点(`<mi>`、`<mo>`、`<mn>`、`<mfrac>`、`<msup>`、`<msub>`、`<msubsup>`)。
|
|
818
799
|
|
|
819
|
-
##
|
|
800
|
+
## 如何添加新语法
|
|
820
801
|
|
|
821
802
|
添加新的 LaTeX 语法支持需要按顺序修改以下四个核心部分:
|
|
822
803
|
|
|
823
|
-
### 1. 常量定义
|
|
804
|
+
### 1. 常量定义
|
|
824
805
|
|
|
825
806
|
定义相应的词法 Token、语法节点类型、函数名或符号映射表:
|
|
826
807
|
|
|
827
|
-
- **Token 类型**:在 [const/TOK.js](https://github.com/webc-site/math/blob/dev/src/const/TOK.js) 中定义(如 `export const TOK_MY_CMD =
|
|
828
|
-
-
|
|
829
|
-
- **环境定界符**:若添加新的环境(如新矩阵或括号类型),需在 [mathml.js](https://github.com/webc-site/math/blob/dev/src/mathml.js)
|
|
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` 中配置其左右定界符。
|
|
830
811
|
- **符号映射表**:如果是普通数学符号或简单命令,只需在 [const/SYM.js](https://github.com/webc-site/math/blob/dev/src/const/SYM.js) 的 `SYM_MAP` 中将命令名映射为对应的 Unicode 字符。
|
|
831
812
|
- **数学函数名**:在 [const/FUNC.js](https://github.com/webc-site/math/blob/dev/src/const/FUNC.js) 的 `FUNC_NAMES` 集合中定义。
|
|
832
813
|
|
|
833
|
-
### 2. 词法分析
|
|
814
|
+
### 2. 词法分析
|
|
834
815
|
|
|
835
816
|
`lex(str)` 函数负责将 LaTeX 输入字符串切割为 Token 数组。它位于 [lex.js](https://github.com/webc-site/math/blob/dev/src/lex.js)。
|
|
836
817
|
|
|
837
818
|
- 如果引入了新的特殊字符或不同结构,需要更新 `lex` 函数中的字符匹配逻辑,让其识别并向 `tokens` 数组中推送相应的 `TOK_*` 类型和其字面值。
|
|
838
819
|
|
|
839
|
-
### 3. 语法分析
|
|
820
|
+
### 3. 语法分析
|
|
840
821
|
|
|
841
822
|
`parse(tokens, state)` 函数负责将 Token 转换为抽象语法树(AST)节点。它位于 [parse.js](https://github.com/webc-site/math/blob/dev/src/parse.js)。
|
|
842
823
|
|
|
843
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]`。
|
|
844
825
|
|
|
845
|
-
### 4. 代码渲染
|
|
826
|
+
### 4. 代码渲染
|
|
846
827
|
|
|
847
|
-
`SHOW_MAP` 字典负责将 AST 节点转换为标准的 MathML 标签字符串。它位于 [mathml.js](https://github.com/webc-site/math/blob/dev/src/mathml.js)
|
|
828
|
+
`SHOW_MAP` 字典负责将 AST 节点转换为标准的 MathML 标签字符串。它位于 [mathml.js](https://github.com/webc-site/math/blob/dev/src/mathml.js)。
|
|
848
829
|
|
|
849
|
-
- 注册新的节点渲染函数:`[TYPE_MY_NODE]: ([_, arg1, arg2]) => nest("mylabel", arg1, arg2)
|
|
830
|
+
- 注册新的节点渲染函数:`[TYPE_MY_NODE]: ([_, arg1, arg2]) => nest("mylabel", arg1, arg2)`,将节点数据格式化为对应的标准 MathML 标记。
|
|
850
831
|
|
|
851
832
|
## 技术堆栈
|
|
852
833
|
|
|
@@ -897,8 +878,8 @@ graph TD
|
|
|
897
878
|
|
|
898
879
|
## 历史背景
|
|
899
880
|
|
|
900
|
-
传统的 Web 数学公式渲染多依赖 MathJax 或 KaTeX
|
|
881
|
+
传统的 Web 数学公式渲染多依赖 MathJax 或 KaTeX。这类库体积较大,需要加载大量 JS 文件并执行复杂的排版计算,容易导致页面渲染出现延迟与白屏。
|
|
901
882
|
|
|
902
|
-
MathML(数学标记语言)规范旨在通过浏览器原生支持渲染数学符号。2023
|
|
883
|
+
MathML(数学标记语言)规范旨在通过浏览器原生支持渲染数学符号。2023年,Blink 引擎正式支持 MathML Core 标准,标志着 Chrome、Safari 和 Firefox 等主流浏览器全面实现了原生的数学公式排版。
|
|
903
884
|
|
|
904
|
-
配合 `18s` 项目提供的数学字体 `m`(Latin Modern Math,源自高德纳的 Computer Modern 经典字体),`@webc.site/math` 编译器能够将 TeX 公式直接转换为原生的 MathML
|
|
885
|
+
配合 `18s` 项目提供的数学字体 `m`(Latin Modern Math,源自高德纳的 Computer Modern 经典字体),`@webc.site/math` 编译器能够将 TeX 公式直接转换为原生的 MathML 元素,完全利用浏览器底层的排版能力,消除了对运行时排版库的依赖。
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@webc.site/math","version":"0.1.
|
|
1
|
+
{"name":"@webc.site/math","version":"0.1.18","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":{}}
|