@burojs/ui-shadcn 0.3.0 → 0.4.0
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 +4 -2
- package/dist/index.cjs +15044 -16998
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3488 -3105
- package/dist/index.d.ts +3488 -3105
- package/dist/index.js +14965 -16860
- package/dist/index.js.map +1 -1
- package/dist/layout/theme-storage-key.cjs +5 -10
- package/dist/layout/theme-storage-key.cjs.map +1 -1
- package/dist/layout/theme-storage-key.d.cts +2 -23
- package/dist/layout/theme-storage-key.d.ts +2 -23
- package/dist/layout/theme-storage-key.js +5 -2
- package/dist/layout/theme-storage-key.js.map +1 -1
- package/dist/markdown/index.cjs +424 -511
- package/dist/markdown/index.cjs.map +1 -1
- package/dist/markdown/index.d.cts +1072 -34
- package/dist/markdown/index.d.ts +1072 -34
- package/dist/markdown/index.js +411 -459
- package/dist/markdown/index.js.map +1 -1
- package/dist/rich-text-IDFvyvRE.js +454 -0
- package/dist/rich-text-IDFvyvRE.js.map +1 -0
- package/dist/rich-text-lndbYqzR.cjs +457 -0
- package/dist/rich-text-lndbYqzR.cjs.map +1 -0
- package/dist/styles.css +14 -8
- package/dist/theme/theme-css.cjs +95 -96
- package/dist/theme/theme-css.cjs.map +1 -1
- package/dist/theme/theme-css.d.cts +10 -8
- package/dist/theme/theme-css.d.ts +10 -8
- package/dist/theme/theme-css.js +94 -94
- package/dist/theme/theme-css.js.map +1 -1
- package/dist/theme/theme-storage.cjs +34 -39
- package/dist/theme/theme-storage.cjs.map +1 -1
- package/dist/theme/theme-storage.d.cts +3 -1
- package/dist/theme/theme-storage.d.ts +3 -1
- package/dist/theme/theme-storage.js +33 -37
- package/dist/theme/theme-storage.js.map +1 -1
- package/dist/theme-storage-key-pYlp4aDS.d.cts +31 -0
- package/dist/theme-storage-key-pYlp4aDS.d.ts +31 -0
- package/dist/use-theme-BwPWinB2.cjs +246 -0
- package/dist/use-theme-BwPWinB2.cjs.map +1 -0
- package/dist/use-theme-IHmtrhEt.js +170 -0
- package/dist/use-theme-IHmtrhEt.js.map +1 -0
- package/package.json +10 -11
- package/dist/chunk-ABUQPOOE.js +0 -11
- package/dist/chunk-ABUQPOOE.js.map +0 -1
- package/dist/chunk-DBGGWBFG.cjs +0 -199
- package/dist/chunk-DBGGWBFG.cjs.map +0 -1
- package/dist/chunk-FMX4GLCQ.js +0 -6
- package/dist/chunk-FMX4GLCQ.js.map +0 -1
- package/dist/chunk-UC57Z243.js +0 -143
- package/dist/chunk-UC57Z243.js.map +0 -1
- package/dist/chunk-UPGPO75B.js +0 -164
- package/dist/chunk-UPGPO75B.js.map +0 -1
- package/dist/chunk-VXJAXJ3U.cjs +0 -8
- package/dist/chunk-VXJAXJ3U.cjs.map +0 -1
- package/dist/chunk-W7AEYE7A.cjs +0 -13
- package/dist/chunk-W7AEYE7A.cjs.map +0 -1
- package/dist/chunk-YF5IW525.cjs +0 -155
- package/dist/chunk-YF5IW525.cjs.map +0 -1
- package/dist/rich-text-6V7WZ3WV.cjs +0 -518
- package/dist/rich-text-6V7WZ3WV.cjs.map +0 -1
- package/dist/rich-text-N2FZEJJV.js +0 -491
- package/dist/rich-text-N2FZEJJV.js.map +0 -1
package/dist/markdown/index.js
CHANGED
|
@@ -1,492 +1,444 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"data-testid": `doc-anchor:${slug}`,
|
|
53
|
-
"data-copied": copied ? "true" : void 0,
|
|
54
|
-
className: cn(
|
|
55
|
-
"ml-2 inline-flex shrink-0 items-center rounded-sm p-0.5 align-middle no-underline",
|
|
56
|
-
"text-muted-foreground transition-opacity hover:text-foreground",
|
|
57
|
-
// Hidden until the reader is at this heading — a permanent « # » beside
|
|
58
|
-
// every heading reads as scaffolding. `focus-visible` keeps it
|
|
59
|
-
// reachable by keyboard, where there is no hover to reveal it.
|
|
60
|
-
"opacity-0 group-hover/anchor:opacity-100 focus-visible:opacity-100",
|
|
61
|
-
"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
|
|
62
|
-
copied && "text-primary opacity-100",
|
|
63
|
-
className
|
|
64
|
-
),
|
|
65
|
-
children: [
|
|
66
|
-
copied ? /* @__PURE__ */ jsx(IconCheck, { className: "size-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ jsx(IconLink, { className: "size-3.5", "aria-hidden": "true" }),
|
|
67
|
-
/* @__PURE__ */ jsx("span", { role: "status", className: "sr-only", children: copied ? t("docPanel.linkCopied", { defaultValue: "Link copied" }) : "" })
|
|
68
|
-
]
|
|
69
|
-
}
|
|
70
|
-
);
|
|
1
|
+
"use client";
|
|
2
|
+
import { a as findDocAnchor, c as cn, i as docSlug, n as DOC_ID_PREFIX, o as readDocHash, r as docShareUrl, s as scrollToDocAnchor, t as useTheme } from "../use-theme-IHmtrhEt.js";
|
|
3
|
+
import { useOptionalT } from "@burojs/react";
|
|
4
|
+
import { IconCheck, IconChevronDown, IconLink } from "@tabler/icons-react";
|
|
5
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
6
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import Markdown from "react-markdown";
|
|
8
|
+
import rehypeSanitize, { defaultSchema } from "rehype-sanitize";
|
|
9
|
+
import rehypeSlug from "rehype-slug";
|
|
10
|
+
import remarkDirective from "remark-directive";
|
|
11
|
+
import remarkGfm from "remark-gfm";
|
|
12
|
+
import { visit } from "unist-util-visit";
|
|
13
|
+
import * as AccordionPrimitive from "@radix-ui/react-accordion";
|
|
14
|
+
//#region src/markdown/anchor-link.tsx
|
|
15
|
+
function DocAnchorLink({ slug, stopPropagation, className }) {
|
|
16
|
+
const t = useOptionalT();
|
|
17
|
+
const [copied, setCopied] = useState(false);
|
|
18
|
+
const timer = useRef(null);
|
|
19
|
+
useEffect(() => () => {
|
|
20
|
+
if (timer.current) clearTimeout(timer.current);
|
|
21
|
+
}, []);
|
|
22
|
+
const onClick = useCallback((event) => {
|
|
23
|
+
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
|
|
24
|
+
if (stopPropagation) event.stopPropagation();
|
|
25
|
+
navigator.clipboard?.writeText(docShareUrl(slug)).then(() => {
|
|
26
|
+
setCopied(true);
|
|
27
|
+
if (timer.current) clearTimeout(timer.current);
|
|
28
|
+
timer.current = setTimeout(() => setCopied(false), 1600);
|
|
29
|
+
}).catch(() => {});
|
|
30
|
+
}, [slug, stopPropagation]);
|
|
31
|
+
const label = copied ? t("docPanel.linkCopied", { defaultValue: "Link copied" }) : t("docPanel.copyLink", { defaultValue: "Copy link to this section" });
|
|
32
|
+
return jsxs("a", {
|
|
33
|
+
href: `#${slug}`,
|
|
34
|
+
onClick,
|
|
35
|
+
title: label,
|
|
36
|
+
"aria-label": label,
|
|
37
|
+
"data-testid": `doc-anchor:${slug}`,
|
|
38
|
+
"data-copied": copied ? "true" : void 0,
|
|
39
|
+
className: cn("ml-2 inline-flex shrink-0 items-center rounded-sm p-0.5 align-middle no-underline", "text-muted-foreground transition-opacity hover:text-foreground", "opacity-0 group-hover/anchor:opacity-100 focus-visible:opacity-100", "focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring", copied && "text-primary opacity-100", className),
|
|
40
|
+
children: [copied ? jsx(IconCheck, {
|
|
41
|
+
className: "size-3.5",
|
|
42
|
+
"aria-hidden": "true"
|
|
43
|
+
}) : jsx(IconLink, {
|
|
44
|
+
className: "size-3.5",
|
|
45
|
+
"aria-hidden": "true"
|
|
46
|
+
}), jsx("span", {
|
|
47
|
+
role: "status",
|
|
48
|
+
className: "sr-only",
|
|
49
|
+
children: copied ? t("docPanel.linkCopied", { defaultValue: "Link copied" }) : ""
|
|
50
|
+
})]
|
|
51
|
+
});
|
|
71
52
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/lib/css-color.ts
|
|
55
|
+
const OKLCH = /^oklch\(\s*([^\s/]+)\s+([^\s/]+)\s+([^\s/]+)\s*(?:\/\s*([^\s/]+)\s*)?\)$/i;
|
|
56
|
+
const KHROMA_SAFE = /^(#|rgba?\(|hsla?\(|[a-z]+$)/i;
|
|
76
57
|
function component(raw, pct) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
58
|
+
if (raw.toLowerCase() === "none") return 0;
|
|
59
|
+
const percent = raw.endsWith("%");
|
|
60
|
+
const n = Number.parseFloat(percent ? raw.slice(0, -1) : raw);
|
|
61
|
+
if (!Number.isFinite(n)) return null;
|
|
62
|
+
return percent ? n / 100 * pct : n;
|
|
82
63
|
}
|
|
83
64
|
function hueDegrees(raw) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return n * 360;
|
|
96
|
-
default:
|
|
97
|
-
return n;
|
|
98
|
-
}
|
|
65
|
+
if (raw.toLowerCase() === "none") return 0;
|
|
66
|
+
const match = /^(-?[\d.]+)(deg|rad|grad|turn)?$/i.exec(raw);
|
|
67
|
+
if (match === null) return null;
|
|
68
|
+
const n = Number.parseFloat(match[1]);
|
|
69
|
+
if (!Number.isFinite(n)) return null;
|
|
70
|
+
switch ((match[2] ?? "deg").toLowerCase()) {
|
|
71
|
+
case "rad": return n * 180 / Math.PI;
|
|
72
|
+
case "grad": return n * .9;
|
|
73
|
+
case "turn": return n * 360;
|
|
74
|
+
default: return n;
|
|
75
|
+
}
|
|
99
76
|
}
|
|
100
77
|
function encode(channel) {
|
|
101
|
-
|
|
102
|
-
|
|
78
|
+
const v = channel <= .0031308 ? 12.92 * channel : 1.055 * channel ** (1 / 2.4) - .055;
|
|
79
|
+
return Math.round(Math.min(1, Math.max(0, v)) * 255);
|
|
103
80
|
}
|
|
104
81
|
function hex2(value) {
|
|
105
|
-
|
|
82
|
+
return value.toString(16).padStart(2, "0");
|
|
106
83
|
}
|
|
107
84
|
function oklchToHex(value) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
85
|
+
const match = OKLCH.exec(value.trim());
|
|
86
|
+
if (match === null) return null;
|
|
87
|
+
const L = component(match[1], 1);
|
|
88
|
+
const C = component(match[2], .4);
|
|
89
|
+
const H = hueDegrees(match[3]);
|
|
90
|
+
const A = match[4] === void 0 ? 1 : component(match[4], 1);
|
|
91
|
+
if (L === null || C === null || H === null || A === null) return null;
|
|
92
|
+
const rad = H * Math.PI / 180;
|
|
93
|
+
const a = C * Math.cos(rad);
|
|
94
|
+
const b = C * Math.sin(rad);
|
|
95
|
+
const l = (L + .3963377774 * a + .2158037573 * b) ** 3;
|
|
96
|
+
const m = (L - .1055613458 * a - .0638541728 * b) ** 3;
|
|
97
|
+
const s = (L - .0894841775 * a - 1.291485548 * b) ** 3;
|
|
98
|
+
const r = encode(4.0767416621 * l - 3.3077115913 * m + .2309699292 * s);
|
|
99
|
+
const g = encode(-1.2684380046 * l + 2.6097574011 * m - .3413193965 * s);
|
|
100
|
+
const bl = encode(-.0041960863 * l - .7034186147 * m + 1.707614701 * s);
|
|
101
|
+
const alpha = Math.min(1, Math.max(0, A));
|
|
102
|
+
const suffix = alpha === 1 ? "" : hex2(Math.round(alpha * 255));
|
|
103
|
+
return `#${hex2(r)}${hex2(g)}${hex2(bl)}${suffix}`;
|
|
127
104
|
}
|
|
128
105
|
function toLegacyColor(value) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
106
|
+
const trimmed = value.trim();
|
|
107
|
+
if (trimmed === "") return null;
|
|
108
|
+
if (KHROMA_SAFE.test(trimmed)) return trimmed;
|
|
109
|
+
return oklchToHex(trimmed);
|
|
133
110
|
}
|
|
111
|
+
//#endregion
|
|
112
|
+
//#region src/markdown/mermaid.tsx
|
|
134
113
|
function cssVar(styles, name, fallback) {
|
|
135
|
-
|
|
114
|
+
return toLegacyColor(styles.getPropertyValue(name)) ?? fallback;
|
|
136
115
|
}
|
|
137
|
-
|
|
116
|
+
let seq = 0;
|
|
138
117
|
function MermaidDiagram({ code, className }) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
"data-testid": "mermaid:loading",
|
|
202
|
-
"aria-hidden": "true"
|
|
203
|
-
}
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
return /* @__PURE__ */ jsx(
|
|
207
|
-
"figure",
|
|
208
|
-
{
|
|
209
|
-
className: cn(
|
|
210
|
-
"not-prose my-4 overflow-x-auto rounded-md border bg-card/40 text-card-foreground p-4",
|
|
211
|
-
// Mermaid emits an intrinsic width; letting it scale down keeps a wide
|
|
212
|
-
// graph inside the column instead of pushing the article sideways.
|
|
213
|
-
"[&_svg]:mx-auto [&_svg]:h-auto [&_svg]:max-w-full",
|
|
214
|
-
className
|
|
215
|
-
),
|
|
216
|
-
"data-testid": "mermaid:diagram",
|
|
217
|
-
dangerouslySetInnerHTML: { __html: svg }
|
|
218
|
-
}
|
|
219
|
-
);
|
|
118
|
+
const [svg, setSvg] = useState(null);
|
|
119
|
+
const [failed, setFailed] = useState(null);
|
|
120
|
+
const { resolved: theme } = useTheme();
|
|
121
|
+
const idRef = useRef(null);
|
|
122
|
+
idRef.current ??= `buro-mermaid-${seq += 1}`;
|
|
123
|
+
useEffect(() => {
|
|
124
|
+
let cancelled = false;
|
|
125
|
+
(async () => {
|
|
126
|
+
try {
|
|
127
|
+
const mermaid = (await import("mermaid")).default;
|
|
128
|
+
const styles = getComputedStyle(document.documentElement);
|
|
129
|
+
const dark = theme === "dark";
|
|
130
|
+
mermaid.initialize({
|
|
131
|
+
startOnLoad: false,
|
|
132
|
+
securityLevel: "strict",
|
|
133
|
+
fontFamily: "inherit",
|
|
134
|
+
theme: "base",
|
|
135
|
+
darkMode: dark,
|
|
136
|
+
themeVariables: {
|
|
137
|
+
background: cssVar(styles, "--background", dark ? "#0b0b0c" : "#ffffff"),
|
|
138
|
+
primaryColor: cssVar(styles, "--muted", dark ? "#1c1c1f" : "#f4f4f5"),
|
|
139
|
+
primaryTextColor: cssVar(styles, "--foreground", dark ? "#fafafa" : "#09090b"),
|
|
140
|
+
primaryBorderColor: cssVar(styles, "--border", dark ? "#27272a" : "#e4e4e7"),
|
|
141
|
+
lineColor: cssVar(styles, "--muted-foreground", dark ? "#a1a1aa" : "#71717a"),
|
|
142
|
+
secondaryColor: cssVar(styles, "--secondary", dark ? "#18181b" : "#f4f4f5"),
|
|
143
|
+
tertiaryColor: cssVar(styles, "--accent", dark ? "#18181b" : "#fafafa"),
|
|
144
|
+
fontSize: "13px"
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
await mermaid.parse(code);
|
|
148
|
+
const { svg: out } = await mermaid.render(idRef.current, code);
|
|
149
|
+
if (!cancelled) {
|
|
150
|
+
setSvg(out);
|
|
151
|
+
setFailed(null);
|
|
152
|
+
}
|
|
153
|
+
} catch (error) {
|
|
154
|
+
if (!cancelled) {
|
|
155
|
+
setSvg(null);
|
|
156
|
+
setFailed(error instanceof Error ? error.message : String(error));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
})();
|
|
160
|
+
return () => {
|
|
161
|
+
cancelled = true;
|
|
162
|
+
};
|
|
163
|
+
}, [code, theme]);
|
|
164
|
+
if (failed !== null) return jsx("pre", {
|
|
165
|
+
className: cn("overflow-x-auto rounded-md border border-dashed p-3 text-xs", className),
|
|
166
|
+
title: failed,
|
|
167
|
+
"data-testid": "mermaid:failed",
|
|
168
|
+
children: jsx("code", { children: code })
|
|
169
|
+
});
|
|
170
|
+
if (svg === null) return jsx("div", {
|
|
171
|
+
className: cn("h-24 animate-pulse rounded-md border bg-muted/40", className),
|
|
172
|
+
"data-testid": "mermaid:loading",
|
|
173
|
+
"aria-hidden": "true"
|
|
174
|
+
});
|
|
175
|
+
return jsx("figure", {
|
|
176
|
+
className: cn("not-prose my-4 overflow-x-auto rounded-md border bg-card/40 text-card-foreground p-4", "[&_svg]:mx-auto [&_svg]:h-auto [&_svg]:max-w-full", className),
|
|
177
|
+
"data-testid": "mermaid:diagram",
|
|
178
|
+
dangerouslySetInnerHTML: { __html: svg }
|
|
179
|
+
});
|
|
220
180
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
181
|
+
//#endregion
|
|
182
|
+
//#region src/markdown/sanitize-schema.ts
|
|
183
|
+
const VIDEO_ATTRIBUTES = [
|
|
184
|
+
"src",
|
|
185
|
+
"poster",
|
|
186
|
+
"controls",
|
|
187
|
+
"loop",
|
|
188
|
+
"muted",
|
|
189
|
+
"autoPlay",
|
|
190
|
+
"playsInline",
|
|
191
|
+
"preload",
|
|
192
|
+
"width",
|
|
193
|
+
"height"
|
|
232
194
|
];
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
// allowed explicitly or the attribute is stripped and every image in a
|
|
247
|
-
// long article loads at once.
|
|
248
|
-
img: [...defaultSchema.attributes?.img ?? [], "loading"]
|
|
249
|
-
}
|
|
195
|
+
const docSanitizeSchema = {
|
|
196
|
+
...defaultSchema,
|
|
197
|
+
tagNames: [...defaultSchema.tagNames ?? [], "video"],
|
|
198
|
+
attributes: {
|
|
199
|
+
...defaultSchema.attributes,
|
|
200
|
+
video: [...VIDEO_ATTRIBUTES],
|
|
201
|
+
source: [
|
|
202
|
+
...defaultSchema.attributes?.source ?? [],
|
|
203
|
+
"src",
|
|
204
|
+
"type"
|
|
205
|
+
],
|
|
206
|
+
img: [...defaultSchema.attributes?.img ?? [], "loading"]
|
|
207
|
+
}
|
|
250
208
|
};
|
|
251
|
-
|
|
209
|
+
//#endregion
|
|
210
|
+
//#region src/markdown/video-directive.ts
|
|
211
|
+
const ALLOWED = [
|
|
212
|
+
"src",
|
|
213
|
+
"poster",
|
|
214
|
+
"width",
|
|
215
|
+
"height"
|
|
216
|
+
];
|
|
252
217
|
function remarkVideoDirective() {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
218
|
+
return (tree) => {
|
|
219
|
+
visit(tree, (node) => {
|
|
220
|
+
const directive = node;
|
|
221
|
+
if (directive.type !== "leafDirective" && directive.type !== "containerDirective" && directive.type !== "textDirective") return;
|
|
222
|
+
if (directive.name !== "video") return;
|
|
223
|
+
const attrs = directive.attributes ?? {};
|
|
224
|
+
const props = {
|
|
225
|
+
controls: true,
|
|
226
|
+
preload: "metadata"
|
|
227
|
+
};
|
|
228
|
+
for (const key of ALLOWED) {
|
|
229
|
+
const value = attrs[key];
|
|
230
|
+
if (typeof value === "string" && value.length > 0) props[key] = value;
|
|
231
|
+
}
|
|
232
|
+
if (typeof props.src !== "string") return;
|
|
233
|
+
directive.data = {
|
|
234
|
+
...directive.data,
|
|
235
|
+
hName: "video",
|
|
236
|
+
hProperties: props
|
|
237
|
+
};
|
|
238
|
+
});
|
|
239
|
+
};
|
|
275
240
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
className: cn("border-b border-border/60 last:border-b-0", className),
|
|
285
|
-
...props
|
|
286
|
-
}
|
|
287
|
-
);
|
|
241
|
+
//#endregion
|
|
242
|
+
//#region src/primitives/accordion.tsx
|
|
243
|
+
const Accordion = AccordionPrimitive.Root;
|
|
244
|
+
function AccordionItem({ className, ...props }) {
|
|
245
|
+
return jsx(AccordionPrimitive.Item, {
|
|
246
|
+
className: cn("border-b border-border/60 last:border-b-0", className),
|
|
247
|
+
...props
|
|
248
|
+
});
|
|
288
249
|
}
|
|
289
|
-
function AccordionTrigger({
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
"rounded-sm [&[data-state=open]>svg]:rotate-180",
|
|
302
|
-
className
|
|
303
|
-
),
|
|
304
|
-
...props,
|
|
305
|
-
children: [
|
|
306
|
-
children,
|
|
307
|
-
/* @__PURE__ */ jsx(
|
|
308
|
-
IconChevronDown,
|
|
309
|
-
{
|
|
310
|
-
className: "mt-0.5 size-4 shrink-0 text-muted-foreground transition-transform duration-200",
|
|
311
|
-
"aria-hidden": "true"
|
|
312
|
-
}
|
|
313
|
-
)
|
|
314
|
-
]
|
|
315
|
-
}
|
|
316
|
-
) });
|
|
250
|
+
function AccordionTrigger({ className, children, ...props }) {
|
|
251
|
+
return jsx(AccordionPrimitive.Header, {
|
|
252
|
+
className: "flex",
|
|
253
|
+
children: jsxs(AccordionPrimitive.Trigger, {
|
|
254
|
+
className: cn("flex flex-1 items-start justify-between gap-3 py-3 text-left", "text-[0.9375rem] font-medium leading-snug transition-colors", "hover:text-primary focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring", "rounded-sm [&[data-state=open]>svg]:rotate-180", className),
|
|
255
|
+
...props,
|
|
256
|
+
children: [children, jsx(IconChevronDown, {
|
|
257
|
+
className: "mt-0.5 size-4 shrink-0 text-muted-foreground transition-transform duration-200",
|
|
258
|
+
"aria-hidden": "true"
|
|
259
|
+
})]
|
|
260
|
+
})
|
|
261
|
+
});
|
|
317
262
|
}
|
|
318
|
-
function AccordionContent({
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
"overflow-hidden",
|
|
328
|
-
"data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
|
|
329
|
-
),
|
|
330
|
-
...props,
|
|
331
|
-
children: /* @__PURE__ */ jsx("div", { className: cn("pb-3.5 pt-0", className), children })
|
|
332
|
-
}
|
|
333
|
-
);
|
|
263
|
+
function AccordionContent({ className, children, ...props }) {
|
|
264
|
+
return jsx(AccordionPrimitive.Content, {
|
|
265
|
+
className: cn("overflow-hidden", "data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"),
|
|
266
|
+
...props,
|
|
267
|
+
children: jsx("div", {
|
|
268
|
+
className: cn("pb-3.5 pt-0", className),
|
|
269
|
+
children
|
|
270
|
+
})
|
|
271
|
+
});
|
|
334
272
|
}
|
|
273
|
+
//#endregion
|
|
274
|
+
//#region src/markdown/faq.tsx
|
|
335
275
|
function splitFaq(markdown) {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
276
|
+
const lines = markdown.split("\n");
|
|
277
|
+
const preamble = [];
|
|
278
|
+
const sections = [];
|
|
279
|
+
let current;
|
|
280
|
+
let fence;
|
|
281
|
+
for (const line of lines) {
|
|
282
|
+
const fenceMatch = /^\s{0,3}(`{3,}|~{3,})/.exec(line);
|
|
283
|
+
if (fenceMatch?.[1] !== void 0) {
|
|
284
|
+
const marker = fenceMatch[1][0];
|
|
285
|
+
if (fence === void 0) fence = marker;
|
|
286
|
+
else if (fence === marker) fence = void 0;
|
|
287
|
+
}
|
|
288
|
+
const heading = fence === void 0 ? /^##\s+(.+?)\s*$/.exec(line) : null;
|
|
289
|
+
if (heading?.[1] !== void 0) {
|
|
290
|
+
if (current) sections.push({
|
|
291
|
+
question: current.question,
|
|
292
|
+
answer: current.answer.join("\n")
|
|
293
|
+
});
|
|
294
|
+
current = {
|
|
295
|
+
question: heading[1],
|
|
296
|
+
answer: []
|
|
297
|
+
};
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
if (current) current.answer.push(line);
|
|
301
|
+
else preamble.push(line);
|
|
302
|
+
}
|
|
303
|
+
if (current) sections.push({
|
|
304
|
+
question: current.question,
|
|
305
|
+
answer: current.answer.join("\n")
|
|
306
|
+
});
|
|
307
|
+
return {
|
|
308
|
+
preamble: preamble.join("\n").trim(),
|
|
309
|
+
sections
|
|
310
|
+
};
|
|
359
311
|
}
|
|
360
312
|
function DocFaq({ children, className }) {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
313
|
+
const { preamble, sections } = splitFaq(children);
|
|
314
|
+
const slugs = useMemo(() => sections.map((s) => docSlug(s.question)), [sections]);
|
|
315
|
+
const [open, setOpen] = useState([]);
|
|
316
|
+
useEffect(() => {
|
|
317
|
+
if (typeof window === "undefined") return;
|
|
318
|
+
const sync = () => {
|
|
319
|
+
const id = readDocHash();
|
|
320
|
+
if (id === "") return;
|
|
321
|
+
const i = slugs.indexOf(id);
|
|
322
|
+
if (i === -1) return;
|
|
323
|
+
setOpen((prev) => prev.includes(`q${i}`) ? prev : [...prev, `q${i}`]);
|
|
324
|
+
scrollToDocAnchor(id, document.body);
|
|
325
|
+
};
|
|
326
|
+
sync();
|
|
327
|
+
window.addEventListener("hashchange", sync);
|
|
328
|
+
return () => window.removeEventListener("hashchange", sync);
|
|
329
|
+
}, [slugs]);
|
|
330
|
+
if (sections.length === 0) return jsx(DocMarkdown, {
|
|
331
|
+
className,
|
|
332
|
+
children
|
|
333
|
+
});
|
|
334
|
+
return jsxs("div", {
|
|
335
|
+
className: cn("flex flex-col", className),
|
|
336
|
+
"data-testid": "doc-faq",
|
|
337
|
+
children: [preamble !== "" && jsx(DocMarkdown, {
|
|
338
|
+
className: "mb-2",
|
|
339
|
+
children: preamble
|
|
340
|
+
}), jsx(Accordion, {
|
|
341
|
+
type: "multiple",
|
|
342
|
+
value: open,
|
|
343
|
+
onValueChange: setOpen,
|
|
344
|
+
className: "w-full",
|
|
345
|
+
children: sections.map((s, i) => jsxs(AccordionItem, {
|
|
346
|
+
value: `q${i}`,
|
|
347
|
+
id: slugs[i],
|
|
348
|
+
className: "group/anchor scroll-mt-4",
|
|
349
|
+
"data-testid": `doc-faq:item:${i}`,
|
|
350
|
+
children: [jsxs(AccordionTrigger, { children: [jsx("span", {
|
|
351
|
+
className: "min-w-0",
|
|
352
|
+
children: s.question
|
|
353
|
+
}), jsx(DocAnchorLink, {
|
|
354
|
+
slug: slugs[i],
|
|
355
|
+
stopPropagation: true,
|
|
356
|
+
className: "ml-auto mr-1"
|
|
357
|
+
})] }), jsx(AccordionContent, { children: jsx(DocMarkdown, {
|
|
358
|
+
className: "prose-p:my-2 first:prose-p:mt-0 last:prose-p:mb-0",
|
|
359
|
+
children: s.answer
|
|
360
|
+
}) })]
|
|
361
|
+
}, `${i}-${s.question}`))
|
|
362
|
+
})]
|
|
363
|
+
});
|
|
399
364
|
}
|
|
365
|
+
//#endregion
|
|
366
|
+
//#region src/markdown/index.tsx
|
|
400
367
|
function DocMarkdown({ children, className }) {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
pre: ({ children: kids, ...rest }) => {
|
|
464
|
-
const only = Array.isArray(kids) ? kids[0] : kids;
|
|
465
|
-
const cls = typeof only === "object" && only !== null && "props" in only ? only.props?.className ?? "" : "";
|
|
466
|
-
if (/\blanguage-mermaid\b/.test(cls)) return /* @__PURE__ */ jsx(Fragment, { children: kids });
|
|
467
|
-
return /* @__PURE__ */ jsx("pre", { ...rest, children: kids });
|
|
468
|
-
}
|
|
469
|
-
},
|
|
470
|
-
children
|
|
471
|
-
}
|
|
472
|
-
)
|
|
473
|
-
}
|
|
474
|
-
);
|
|
368
|
+
return jsx("div", {
|
|
369
|
+
className: cn("prose prose-sm max-w-none dark:prose-invert", "prose-headings:scroll-mt-4 prose-headings:font-semibold", "prose-h1:text-base prose-h2:text-[0.9375rem] prose-h3:text-sm", "prose-p:leading-[1.65]", "prose-a:font-medium prose-a:underline-offset-2", "prose-img:rounded-md prose-img:border", "prose-video:rounded-md prose-video:border prose-video:w-full", "prose-table:text-[0.8125rem]", className),
|
|
370
|
+
children: jsx(Markdown, {
|
|
371
|
+
remarkPlugins: [
|
|
372
|
+
remarkGfm,
|
|
373
|
+
remarkDirective,
|
|
374
|
+
remarkVideoDirective
|
|
375
|
+
],
|
|
376
|
+
rehypePlugins: [rehypeSlug, [rehypeSanitize, docSanitizeSchema]],
|
|
377
|
+
components: {
|
|
378
|
+
a: ({ href, children: kids, ...rest }) => jsx("a", {
|
|
379
|
+
href,
|
|
380
|
+
target: "_blank",
|
|
381
|
+
rel: "noopener noreferrer",
|
|
382
|
+
...rest,
|
|
383
|
+
children: kids
|
|
384
|
+
}),
|
|
385
|
+
img: ({ ...rest }) => jsx("img", {
|
|
386
|
+
loading: "lazy",
|
|
387
|
+
...rest,
|
|
388
|
+
alt: rest.alt ?? ""
|
|
389
|
+
}),
|
|
390
|
+
table: ({ children: kids, ...rest }) => jsx("div", {
|
|
391
|
+
className: "overflow-x-auto",
|
|
392
|
+
children: jsx("table", {
|
|
393
|
+
...rest,
|
|
394
|
+
children: kids
|
|
395
|
+
})
|
|
396
|
+
}),
|
|
397
|
+
code: ({ className: cls, children: kids, ...rest }) => {
|
|
398
|
+
if (/\blanguage-mermaid\b/.test(cls ?? "")) return jsx(MermaidDiagram, { code: String(kids).replace(/\n$/, "") });
|
|
399
|
+
return jsx("code", {
|
|
400
|
+
className: cls,
|
|
401
|
+
...rest,
|
|
402
|
+
children: kids
|
|
403
|
+
});
|
|
404
|
+
},
|
|
405
|
+
h2: ({ children: kids, id, ...rest }) => jsx(HeadingWithAnchor, {
|
|
406
|
+
level: 2,
|
|
407
|
+
id,
|
|
408
|
+
...rest,
|
|
409
|
+
children: kids
|
|
410
|
+
}),
|
|
411
|
+
h3: ({ children: kids, id, ...rest }) => jsx(HeadingWithAnchor, {
|
|
412
|
+
level: 3,
|
|
413
|
+
id,
|
|
414
|
+
...rest,
|
|
415
|
+
children: kids
|
|
416
|
+
}),
|
|
417
|
+
pre: ({ children: kids, ...rest }) => {
|
|
418
|
+
const only = Array.isArray(kids) ? kids[0] : kids;
|
|
419
|
+
const cls = typeof only === "object" && only !== null && "props" in only ? only.props?.className ?? "" : "";
|
|
420
|
+
if (/\blanguage-mermaid\b/.test(cls)) return jsx(Fragment$1, { children: kids });
|
|
421
|
+
return jsx("pre", {
|
|
422
|
+
...rest,
|
|
423
|
+
children: kids
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
},
|
|
427
|
+
children
|
|
428
|
+
})
|
|
429
|
+
});
|
|
475
430
|
}
|
|
476
|
-
function HeadingWithAnchor({
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
children,
|
|
486
|
-
slug !== void 0 && slug !== "" && /* @__PURE__ */ jsx(DocAnchorLink, { slug })
|
|
487
|
-
] });
|
|
431
|
+
function HeadingWithAnchor({ level, id, children, ...rest }) {
|
|
432
|
+
const Tag = level === 2 ? "h2" : "h3";
|
|
433
|
+
const slug = id?.startsWith("user-content-") ? id.slice(DOC_ID_PREFIX.length) : id;
|
|
434
|
+
return jsxs(Tag, {
|
|
435
|
+
id,
|
|
436
|
+
className: "group/anchor scroll-mt-4",
|
|
437
|
+
...rest,
|
|
438
|
+
children: [children, slug !== void 0 && slug !== "" && jsx(DocAnchorLink, { slug })]
|
|
439
|
+
});
|
|
488
440
|
}
|
|
441
|
+
//#endregion
|
|
442
|
+
export { DOC_ID_PREFIX, DocAnchorLink, DocFaq, DocMarkdown, MermaidDiagram, docSanitizeSchema, docShareUrl, docSlug, findDocAnchor, readDocHash, remarkVideoDirective, scrollToDocAnchor, splitFaq };
|
|
489
443
|
|
|
490
|
-
export { DocAnchorLink, DocFaq, DocMarkdown, MermaidDiagram, docSanitizeSchema, remarkVideoDirective, splitFaq };
|
|
491
|
-
//# sourceMappingURL=index.js.map
|
|
492
444
|
//# sourceMappingURL=index.js.map
|