@bdocs/plugin-math 4.0.1 → 4.0.3
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/dist/client/index.d.mts +23 -5
- package/dist/client/index.mjs +60 -17
- package/dist/node/index.mjs +16 -2
- package/package.json +5 -4
package/dist/client/index.d.mts
CHANGED
|
@@ -1,20 +1,38 @@
|
|
|
1
1
|
|
|
2
|
-
import * as _$
|
|
2
|
+
import * as _$react from "react";
|
|
3
3
|
|
|
4
4
|
//#region src/client/Math.d.ts
|
|
5
5
|
interface MathProps {
|
|
6
6
|
children: string;
|
|
7
|
+
/** Pre-rendered KaTeX HTML, baked at build time by the math plugin. */
|
|
8
|
+
html?: string;
|
|
7
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Inline math. When the build-time transform has baked the KaTeX output into
|
|
12
|
+
* the `html` prop, this renders synchronously and KaTeX is never bundled into
|
|
13
|
+
* the critical path. For direct MDX usage without the bake (rare), KaTeX is
|
|
14
|
+
* imported on demand and the raw TeX stays visible until it arrives — the
|
|
15
|
+
* server and the first client render agree, so hydration stays consistent.
|
|
16
|
+
*/
|
|
8
17
|
declare function MathComponent({
|
|
9
|
-
children
|
|
10
|
-
|
|
18
|
+
children,
|
|
19
|
+
html
|
|
20
|
+
}: MathProps): _$react.JSX.Element;
|
|
11
21
|
//#endregion
|
|
12
22
|
//#region src/client/BlockMath.d.ts
|
|
13
23
|
interface BlockMathProps {
|
|
14
24
|
children: string;
|
|
25
|
+
/** Pre-rendered KaTeX HTML, baked at build time by the math plugin. */
|
|
26
|
+
html?: string;
|
|
15
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Block math. Same contract as `MathComponent`: the build-time transform bakes
|
|
30
|
+
* KaTeX into `html`, so the critical client path never bundles KaTeX; direct
|
|
31
|
+
* MDX usage falls back to an on-demand import.
|
|
32
|
+
*/
|
|
16
33
|
declare function BlockMath({
|
|
17
|
-
children
|
|
18
|
-
|
|
34
|
+
children,
|
|
35
|
+
html
|
|
36
|
+
}: BlockMathProps): _$react.JSX.Element;
|
|
19
37
|
//#endregion
|
|
20
38
|
export { BlockMath, MathComponent as Math, MathComponent };
|
package/dist/client/index.mjs
CHANGED
|
@@ -3,31 +3,74 @@
|
|
|
3
3
|
* Copyright (c) 2026 Jesus Alcala
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
7
|
-
import katex from "katex";
|
|
6
|
+
import { useEffect, useState } from "react";
|
|
8
7
|
import { jsx } from "react/jsx-runtime";
|
|
9
8
|
//#region src/client/Math.tsx
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Inline math. When the build-time transform has baked the KaTeX output into
|
|
11
|
+
* the `html` prop, this renders synchronously and KaTeX is never bundled into
|
|
12
|
+
* the critical path. For direct MDX usage without the bake (rare), KaTeX is
|
|
13
|
+
* imported on demand and the raw TeX stays visible until it arrives — the
|
|
14
|
+
* server and the first client render agree, so hydration stays consistent.
|
|
15
|
+
*/
|
|
16
|
+
function MathComponent({ children, html }) {
|
|
17
|
+
const [lazyHtml, setLazyHtml] = useState(null);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (typeof html === "string" || lazyHtml !== null) return;
|
|
20
|
+
let active = true;
|
|
21
|
+
import("katex").then((k) => {
|
|
22
|
+
if (!active) return;
|
|
23
|
+
try {
|
|
24
|
+
setLazyHtml(k.default.renderToString(children, { displayMode: false }));
|
|
25
|
+
} catch {
|
|
26
|
+
setLazyHtml(children);
|
|
27
|
+
}
|
|
28
|
+
}).catch(() => {
|
|
29
|
+
if (active) setLazyHtml(children);
|
|
30
|
+
});
|
|
31
|
+
return () => {
|
|
32
|
+
active = false;
|
|
33
|
+
};
|
|
34
|
+
}, [
|
|
35
|
+
html,
|
|
36
|
+
children,
|
|
37
|
+
lazyHtml
|
|
38
|
+
]);
|
|
39
|
+
return /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: typeof html === "string" ? html : lazyHtml ?? children } });
|
|
18
40
|
}
|
|
19
41
|
//#endregion
|
|
20
42
|
//#region src/client/BlockMath.tsx
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Block math. Same contract as `MathComponent`: the build-time transform bakes
|
|
45
|
+
* KaTeX into `html`, so the critical client path never bundles KaTeX; direct
|
|
46
|
+
* MDX usage falls back to an on-demand import.
|
|
47
|
+
*/
|
|
48
|
+
function BlockMath({ children, html }) {
|
|
49
|
+
const [lazyHtml, setLazyHtml] = useState(null);
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (typeof html === "string" || lazyHtml !== null) return;
|
|
52
|
+
let active = true;
|
|
53
|
+
import("katex").then((k) => {
|
|
54
|
+
if (!active) return;
|
|
25
55
|
try {
|
|
26
|
-
|
|
56
|
+
setLazyHtml(k.default.renderToString(children, { displayMode: true }));
|
|
27
57
|
} catch {
|
|
28
|
-
|
|
58
|
+
setLazyHtml(children);
|
|
29
59
|
}
|
|
30
|
-
}
|
|
60
|
+
}).catch(() => {
|
|
61
|
+
if (active) setLazyHtml(children);
|
|
62
|
+
});
|
|
63
|
+
return () => {
|
|
64
|
+
active = false;
|
|
65
|
+
};
|
|
66
|
+
}, [
|
|
67
|
+
html,
|
|
68
|
+
children,
|
|
69
|
+
lazyHtml
|
|
70
|
+
]);
|
|
71
|
+
return /* @__PURE__ */ jsx("div", {
|
|
72
|
+
className: "math-block my-6 flex justify-center overflow-x-auto",
|
|
73
|
+
dangerouslySetInnerHTML: { __html: typeof html === "string" ? html : lazyHtml ?? children }
|
|
31
74
|
});
|
|
32
75
|
}
|
|
33
76
|
//#endregion
|
package/dist/node/index.mjs
CHANGED
|
@@ -3,10 +3,23 @@
|
|
|
3
3
|
* Copyright (c) 2026 Jesus Alcala
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
|
+
import katex from "katex";
|
|
6
7
|
//#region src/node/source-transform.ts
|
|
7
8
|
function escapeJsString(content) {
|
|
8
9
|
return content.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n");
|
|
9
10
|
}
|
|
11
|
+
function renderMathHtml(tex, displayMode) {
|
|
12
|
+
try {
|
|
13
|
+
return katex.renderToString(tex, { displayMode });
|
|
14
|
+
} catch {
|
|
15
|
+
return tex;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Bake KaTeX output at build time. The emitted `<BlockMath>`/`<MathComponent>`
|
|
20
|
+
* tags carry the pre-rendered HTML in a `html` prop, so the client components
|
|
21
|
+
* never need to bundle KaTeX (~250 KB minified) just to display equations.
|
|
22
|
+
*/
|
|
10
23
|
function preprocessMath(source) {
|
|
11
24
|
const placeholders = [];
|
|
12
25
|
let result = source.replace(/(`{3,})[\s\S]*?\1/g, (match) => {
|
|
@@ -22,10 +35,11 @@ function preprocessMath(source) {
|
|
|
22
35
|
return `\0MATH_PH_${placeholders.length - 1}\0`;
|
|
23
36
|
});
|
|
24
37
|
result = result.replace(/\$\$([\s\S]*?)\$\$/g, (_, content) => {
|
|
25
|
-
|
|
38
|
+
const trimmed = content.trim();
|
|
39
|
+
return `<BlockMath html={"${escapeJsString(renderMathHtml(trimmed, true))}"}>{"${escapeJsString(trimmed)}"}</BlockMath>`;
|
|
26
40
|
});
|
|
27
41
|
result = result.replace(/(?<!\$)\$(?!\$)(.+?)\$(?!\$)/g, (_, content) => {
|
|
28
|
-
return `<MathComponent>{"${escapeJsString(content)}"}</MathComponent>`;
|
|
42
|
+
return `<MathComponent html={"${escapeJsString(renderMathHtml(content, false))}"}>{"${escapeJsString(content)}"}</MathComponent>`;
|
|
29
43
|
});
|
|
30
44
|
while (result.includes("\0MATH_PH_")) result = result.replace(/\0MATH_PH_(\d+)\0/g, (_, idx) => {
|
|
31
45
|
return placeholders[parseInt(idx)];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bdocs/plugin-math",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.3",
|
|
4
4
|
"description": "KaTeX math plugin for Boltdocs",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
"katex": "^0.16.11"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
|
-
"@bdocs/dui": "^0.
|
|
29
|
+
"@bdocs/dui": "^0.6.0",
|
|
30
30
|
"react": "^19.0.0",
|
|
31
31
|
"react-dom": "^19.0.0",
|
|
32
|
-
"boltdocs": "3.
|
|
32
|
+
"boltdocs": "^3.3.5"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/katex": "^0.16.7",
|
|
@@ -40,7 +40,8 @@
|
|
|
40
40
|
"react-dom": "^19.0.0",
|
|
41
41
|
"tsdown": "^0.21.7",
|
|
42
42
|
"typescript": "^5.9.3",
|
|
43
|
-
"boltdocs": "3.
|
|
43
|
+
"boltdocs": "^3.3.5",
|
|
44
|
+
"tsdown-config": "1.0.0"
|
|
44
45
|
},
|
|
45
46
|
"scripts": {
|
|
46
47
|
"build": "tsdown --config-loader unrun && node --input-type=module -e \"import fs from 'node:fs'; fs.mkdirSync('dist/client', { recursive: true }); fs.cpSync('src/client/index.css', 'dist/client/index.css');\"",
|