@brett_lamy/docstream 1.3.0 → 1.5.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 +79 -5
- package/dist/assets.d.ts +3 -0
- package/dist/assets.d.ts.map +1 -0
- package/dist/assets.js +20 -0
- package/dist/assets.js.map +1 -0
- package/dist/demo/DemoViewer.d.ts +78 -0
- package/dist/demo/DemoViewer.d.ts.map +1 -0
- package/dist/demo/DemoViewer.js +467 -0
- package/dist/demo/DemoViewer.js.map +1 -0
- package/dist/demo/clipboard.d.ts +70 -0
- package/dist/demo/clipboard.d.ts.map +1 -0
- package/dist/demo/clipboard.js +187 -0
- package/dist/demo/clipboard.js.map +1 -0
- package/dist/demo/context.d.ts +20 -0
- package/dist/demo/context.d.ts.map +1 -0
- package/dist/demo/context.js +31 -0
- package/dist/demo/context.js.map +1 -0
- package/dist/demo/copy-demo.d.ts +23 -0
- package/dist/demo/copy-demo.d.ts.map +1 -0
- package/dist/demo/copy-demo.js +81 -0
- package/dist/demo/copy-demo.js.map +1 -0
- package/dist/demo/glob.d.ts +60 -0
- package/dist/demo/glob.d.ts.map +1 -0
- package/dist/demo/glob.js +158 -0
- package/dist/demo/glob.js.map +1 -0
- package/dist/demo/index.d.ts +16 -0
- package/dist/demo/index.d.ts.map +1 -0
- package/dist/demo/index.js +9 -0
- package/dist/demo/index.js.map +1 -0
- package/dist/demo/markdown.d.ts +60 -0
- package/dist/demo/markdown.d.ts.map +1 -0
- package/dist/demo/markdown.js +181 -0
- package/dist/demo/markdown.js.map +1 -0
- package/dist/demo/surface.d.ts +11 -0
- package/dist/demo/surface.d.ts.map +1 -0
- package/dist/demo/surface.js +69 -0
- package/dist/demo/surface.js.map +1 -0
- package/dist/demo/types.d.ts +91 -0
- package/dist/demo/types.d.ts.map +1 -0
- package/dist/demo/types.js +2 -0
- package/dist/demo/types.js.map +1 -0
- package/dist/demo/vfs.d.ts +51 -0
- package/dist/demo/vfs.d.ts.map +1 -0
- package/dist/demo/vfs.js +156 -0
- package/dist/demo/vfs.js.map +1 -0
- package/dist/docs/CollapsibleCode.d.ts +14 -0
- package/dist/docs/CollapsibleCode.d.ts.map +1 -0
- package/dist/docs/CollapsibleCode.js +19 -0
- package/dist/docs/CollapsibleCode.js.map +1 -0
- package/dist/docs/DocsRenderer.d.ts +55 -0
- package/dist/docs/DocsRenderer.d.ts.map +1 -0
- package/dist/docs/DocsRenderer.js +279 -0
- package/dist/docs/DocsRenderer.js.map +1 -0
- package/dist/docs/HighlightedCode.d.ts +6 -0
- package/dist/docs/HighlightedCode.d.ts.map +1 -0
- package/dist/docs/HighlightedCode.js +40 -0
- package/dist/docs/HighlightedCode.js.map +1 -0
- package/dist/docs/Mermaid.d.ts +7 -0
- package/dist/docs/Mermaid.d.ts.map +1 -0
- package/dist/docs/Mermaid.js +39 -0
- package/dist/docs/Mermaid.js.map +1 -0
- package/dist/docs/PageActions.d.ts +33 -0
- package/dist/docs/PageActions.d.ts.map +1 -0
- package/dist/docs/PageActions.js +115 -0
- package/dist/docs/PageActions.js.map +1 -0
- package/dist/docs/controls.d.ts +29 -0
- package/dist/docs/controls.d.ts.map +1 -0
- package/dist/docs/controls.js +46 -0
- package/dist/docs/controls.js.map +1 -0
- package/dist/docs/copy.d.ts +24 -0
- package/dist/docs/copy.d.ts.map +1 -0
- package/dist/docs/copy.js +62 -0
- package/dist/docs/copy.js.map +1 -0
- package/dist/docs/math.d.ts +3 -0
- package/dist/docs/math.d.ts.map +1 -0
- package/dist/docs/math.js +12 -0
- package/dist/docs/math.js.map +1 -0
- package/dist/docs/reference.d.ts +27 -0
- package/dist/docs/reference.d.ts.map +1 -0
- package/dist/docs/reference.js +73 -0
- package/dist/docs/reference.js.map +1 -0
- package/dist/docs/tabs-sync.d.ts +5 -0
- package/dist/docs/tabs-sync.d.ts.map +1 -0
- package/dist/docs/tabs-sync.js +58 -0
- package/dist/docs/tabs-sync.js.map +1 -0
- package/dist/gitbook/ast.d.ts +506 -0
- package/dist/gitbook/ast.d.ts.map +1 -0
- package/dist/gitbook/ast.js +8 -0
- package/dist/gitbook/ast.js.map +1 -0
- package/dist/gitbook/attrs.d.ts +14 -0
- package/dist/gitbook/attrs.d.ts.map +1 -0
- package/dist/gitbook/attrs.js +36 -0
- package/dist/gitbook/attrs.js.map +1 -0
- package/dist/gitbook/flatten.d.ts +14 -0
- package/dist/gitbook/flatten.d.ts.map +1 -0
- package/dist/gitbook/flatten.js +45 -0
- package/dist/gitbook/flatten.js.map +1 -0
- package/dist/gitbook/index.d.ts +10 -0
- package/dist/gitbook/index.d.ts.map +1 -0
- package/dist/gitbook/index.js +8 -0
- package/dist/gitbook/index.js.map +1 -0
- package/dist/gitbook/inline.d.ts +28 -0
- package/dist/gitbook/inline.d.ts.map +1 -0
- package/dist/gitbook/inline.js +956 -0
- package/dist/gitbook/inline.js.map +1 -0
- package/dist/gitbook/outline.d.ts +16 -0
- package/dist/gitbook/outline.d.ts.map +1 -0
- package/dist/gitbook/outline.js +44 -0
- package/dist/gitbook/outline.js.map +1 -0
- package/dist/gitbook/package-managers.d.ts +12 -0
- package/dist/gitbook/package-managers.d.ts.map +1 -0
- package/dist/gitbook/package-managers.js +93 -0
- package/dist/gitbook/package-managers.js.map +1 -0
- package/dist/gitbook/parse.d.ts +44 -0
- package/dist/gitbook/parse.d.ts.map +1 -0
- package/dist/gitbook/parse.js +1113 -0
- package/dist/gitbook/parse.js.map +1 -0
- package/dist/gitbook/serialize.d.ts +23 -0
- package/dist/gitbook/serialize.d.ts.map +1 -0
- package/dist/gitbook/serialize.js +498 -0
- package/dist/gitbook/serialize.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/openapi/OpenApiOperation.d.ts +6 -0
- package/dist/openapi/OpenApiOperation.d.ts.map +1 -0
- package/dist/openapi/OpenApiOperation.js +112 -0
- package/dist/openapi/OpenApiOperation.js.map +1 -0
- package/dist/playground/InlineDemoPreview.d.ts +24 -0
- package/dist/playground/InlineDemoPreview.d.ts.map +1 -0
- package/dist/playground/InlineDemoPreview.js +48 -0
- package/dist/playground/InlineDemoPreview.js.map +1 -0
- package/dist/playground/PlaygroundStreamdown.d.ts +16 -0
- package/dist/playground/PlaygroundStreamdown.d.ts.map +1 -0
- package/dist/playground/PlaygroundStreamdown.js +22 -0
- package/dist/playground/PlaygroundStreamdown.js.map +1 -0
- package/dist/playground/ReactCodePreview.d.ts +64 -0
- package/dist/playground/ReactCodePreview.d.ts.map +1 -0
- package/dist/playground/ReactCodePreview.js +108 -0
- package/dist/playground/ReactCodePreview.js.map +1 -0
- package/dist/playground/filesystem.d.ts +27 -0
- package/dist/playground/filesystem.d.ts.map +1 -0
- package/dist/playground/filesystem.js +65 -0
- package/dist/playground/filesystem.js.map +1 -0
- package/dist/playground/index.d.ts +9 -0
- package/dist/playground/index.d.ts.map +1 -0
- package/dist/playground/index.js +7 -0
- package/dist/playground/index.js.map +1 -0
- package/dist/playground/project.d.ts +57 -0
- package/dist/playground/project.d.ts.map +1 -0
- package/dist/playground/project.js +137 -0
- package/dist/playground/project.js.map +1 -0
- package/dist/replay/NativeReplay.d.ts +9 -0
- package/dist/replay/NativeReplay.d.ts.map +1 -0
- package/dist/replay/NativeReplay.js +173 -0
- package/dist/replay/NativeReplay.js.map +1 -0
- package/dist/replay/ReplayPreview.d.ts +33 -0
- package/dist/replay/ReplayPreview.d.ts.map +1 -0
- package/dist/replay/ReplayPreview.js +91 -0
- package/dist/replay/ReplayPreview.js.map +1 -0
- package/dist/replay/index.d.ts +5 -0
- package/dist/replay/index.d.ts.map +1 -0
- package/dist/replay/index.js +4 -0
- package/dist/replay/index.js.map +1 -0
- package/dist/replay/sanitize.d.ts +4 -0
- package/dist/replay/sanitize.d.ts.map +1 -0
- package/dist/replay/sanitize.js +86 -0
- package/dist/replay/sanitize.js.map +1 -0
- package/dist/replay/url.d.ts +8 -0
- package/dist/replay/url.d.ts.map +1 -0
- package/dist/replay/url.js +41 -0
- package/dist/replay/url.js.map +1 -0
- package/dist/source/SourcePreview.d.ts +13 -0
- package/dist/source/SourcePreview.d.ts.map +1 -0
- package/dist/source/SourcePreview.js +47 -0
- package/dist/source/SourcePreview.js.map +1 -0
- package/dist/source/client.d.ts +7 -0
- package/dist/source/client.d.ts.map +1 -0
- package/dist/source/client.js +52 -0
- package/dist/source/client.js.map +1 -0
- package/dist/source/index.d.ts +6 -0
- package/dist/source/index.d.ts.map +1 -0
- package/dist/source/index.js +3 -0
- package/dist/source/index.js.map +1 -0
- package/dist/source/types.d.ts +33 -0
- package/dist/source/types.d.ts.map +1 -0
- package/dist/source/types.js +2 -0
- package/dist/source/types.js.map +1 -0
- package/dist/streamdown.d.ts +19 -0
- package/dist/streamdown.d.ts.map +1 -0
- package/dist/streamdown.js +15 -0
- package/dist/streamdown.js.map +1 -0
- package/dist/styles.css +2441 -0
- package/dist/video/VideoEmbed.d.ts +17 -0
- package/dist/video/VideoEmbed.d.ts.map +1 -0
- package/dist/video/VideoEmbed.js +12 -0
- package/dist/video/VideoEmbed.js.map +1 -0
- package/dist/video/index.d.ts +3 -0
- package/dist/video/index.d.ts.map +1 -0
- package/dist/video/index.js +2 -0
- package/dist/video/index.js.map +1 -0
- package/dist/vite/index.d.ts +21 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +137 -0
- package/dist/vite/index.js.map +1 -0
- package/dist/viz/VizEmbed.d.ts +18 -0
- package/dist/viz/VizEmbed.d.ts.map +1 -0
- package/dist/viz/VizEmbed.js +12 -0
- package/dist/viz/VizEmbed.js.map +1 -0
- package/dist/viz/index.d.ts +4 -0
- package/dist/viz/index.d.ts.map +1 -0
- package/dist/viz/index.js +3 -0
- package/dist/viz/index.js.map +1 -0
- package/package.json +65 -32
- package/src/demo/DemoViewer.tsx +56 -11
- package/src/demo/clipboard.ts +228 -0
- package/src/demo/context.ts +7 -0
- package/src/demo/copy-demo.tsx +102 -0
- package/src/demo/index.ts +29 -2
- package/src/demo/vfs.ts +197 -0
- package/src/docs/DocsRenderer.tsx +13 -4
- package/src/docs/Mermaid.tsx +5 -3
- package/src/index.ts +19 -0
- package/src/replay/ReplayPreview.tsx +0 -1
- package/src/streamdown.tsx +2 -0
- package/src/styles.css +91 -0
- package/src/replay/styles.css +0 -87
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
export interface VideoEmbedProps {
|
|
3
|
+
/** A direct media asset or a public player URL. */
|
|
4
|
+
src: string;
|
|
5
|
+
title?: string;
|
|
6
|
+
className?: string;
|
|
7
|
+
/** CSS aspect-ratio for iframe embeds. Defaults to 16 / 9. */
|
|
8
|
+
aspectRatio?: CSSProperties["aspectRatio"];
|
|
9
|
+
controls?: boolean;
|
|
10
|
+
autoplay?: boolean;
|
|
11
|
+
loop?: boolean;
|
|
12
|
+
muted?: boolean;
|
|
13
|
+
poster?: string;
|
|
14
|
+
allowFullScreen?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare function VideoEmbed({ src, title, className, aspectRatio, controls, autoplay, loop, muted, poster, allowFullScreen, }: VideoEmbedProps): import("react").JSX.Element;
|
|
17
|
+
//# sourceMappingURL=VideoEmbed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VideoEmbed.d.ts","sourceRoot":"","sources":["../../src/video/VideoEmbed.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAE1C,MAAM,WAAW,eAAe;IAC9B,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,CAAA;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAMD,wBAAgB,UAAU,CAAC,EACzB,GAAG,EACH,KAAe,EACf,SAAS,EACT,WAAsB,EACtB,QAAe,EACf,QAAgB,EAChB,IAAY,EACZ,KAAa,EACb,MAAM,EACN,eAAsB,GACvB,EAAE,eAAe,+BA6BjB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
function isDirectVideo(src) {
|
|
3
|
+
return /\.(?:mp4|webm|ogg)(?:[?#]|$)/i.test(src);
|
|
4
|
+
}
|
|
5
|
+
export function VideoEmbed({ src, title = "Video", className, aspectRatio = "16 / 9", controls = true, autoplay = false, loop = false, muted = false, poster, allowFullScreen = true, }) {
|
|
6
|
+
const mediaClass = `video-embed__media ${className ?? ""}`.trim();
|
|
7
|
+
if (isDirectVideo(src)) {
|
|
8
|
+
return (_jsx("video", { className: mediaClass, src: src, title: title, controls: controls, autoPlay: autoplay, loop: loop, muted: muted, poster: poster, playsInline: true }));
|
|
9
|
+
}
|
|
10
|
+
return (_jsx("iframe", { className: mediaClass, src: src, title: title, loading: "lazy", allow: "autoplay; fullscreen", allowFullScreen: allowFullScreen, style: { aspectRatio }, referrerPolicy: "strict-origin-when-cross-origin" }));
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=VideoEmbed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VideoEmbed.js","sourceRoot":"","sources":["../../src/video/VideoEmbed.tsx"],"names":[],"mappings":";AAiBA,SAAS,aAAa,CAAC,GAAW;IAChC,OAAO,+BAA+B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAClD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EACzB,GAAG,EACH,KAAK,GAAG,OAAO,EACf,SAAS,EACT,WAAW,GAAG,QAAQ,EACtB,QAAQ,GAAG,IAAI,EACf,QAAQ,GAAG,KAAK,EAChB,IAAI,GAAG,KAAK,EACZ,KAAK,GAAG,KAAK,EACb,MAAM,EACN,eAAe,GAAG,IAAI,GACN;IAChB,MAAM,UAAU,GAAG,sBAAsB,SAAS,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAA;IACjE,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CACL,gBACE,SAAS,EAAE,UAAU,EACrB,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,WAAW,SACX,CACH,CAAA;IACH,CAAC;IACD,OAAO,CACL,iBACE,SAAS,EAAE,UAAU,EACrB,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,KAAK,EACZ,OAAO,EAAC,MAAM,EACd,KAAK,EAAC,sBAAsB,EAC5B,eAAe,EAAE,eAAe,EAChC,KAAK,EAAE,EAAE,WAAW,EAAE,EACtB,cAAc,EAAC,iCAAiC,GAChD,CACH,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/video/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/video/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
export interface DocstreamSourceMount {
|
|
3
|
+
/** Stable name used by Markdown source references. */
|
|
4
|
+
name: string;
|
|
5
|
+
/** Real source directory. Relative paths are resolved from the Vite root. */
|
|
6
|
+
root: string;
|
|
7
|
+
/** Allow PUT requests to edit files in this mount. Defaults to true. */
|
|
8
|
+
writable?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface DocstreamSourcesOptions {
|
|
11
|
+
mounts: readonly DocstreamSourceMount[];
|
|
12
|
+
/** HTTP endpoint prefix. Defaults to `/@docstream`. */
|
|
13
|
+
apiBase?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Mount real source directories behind safe Vite dev-server endpoints.
|
|
17
|
+
* Markdown references import live modules from these files, and editor writes
|
|
18
|
+
* go back to disk so Vite's normal watcher/HMR pipeline remains authoritative.
|
|
19
|
+
*/
|
|
20
|
+
export declare function docstreamSources(options: DocstreamSourcesOptions): Plugin;
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,MAAM,CAAA;AAEjD,MAAM,WAAW,oBAAoB;IACnC,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAA;IACZ,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAA;IACZ,wEAAwE;IACxE,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,SAAS,oBAAoB,EAAE,CAAA;IACvC,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AA6GD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAgCzE"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const VIRTUAL_ID = "virtual:docstream-sources";
|
|
4
|
+
const RESOLVED_VIRTUAL_ID = "\0virtual:docstream-sources";
|
|
5
|
+
function send(response, status, body, type = "application/json; charset=utf-8") {
|
|
6
|
+
response.statusCode = status;
|
|
7
|
+
response.setHeader("content-type", type);
|
|
8
|
+
response.setHeader("cache-control", "no-store");
|
|
9
|
+
response.end(body);
|
|
10
|
+
}
|
|
11
|
+
function requestUrl(request) {
|
|
12
|
+
return new URL(request.url ?? "/", "http://docstream.local");
|
|
13
|
+
}
|
|
14
|
+
async function requestBody(request) {
|
|
15
|
+
const chunks = [];
|
|
16
|
+
for await (const chunk of request)
|
|
17
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
18
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
19
|
+
}
|
|
20
|
+
function normalizeRelativePath(value) {
|
|
21
|
+
const source = value.replaceAll("\\", "/").replace(/^\.\//, "");
|
|
22
|
+
if (!source || source.startsWith("/") || source.split("/").some((part) => part === ".." || part === "")) {
|
|
23
|
+
throw new Error(`Invalid mounted source path: ${value}`);
|
|
24
|
+
}
|
|
25
|
+
return source;
|
|
26
|
+
}
|
|
27
|
+
function sourcePath(mount, requestedPath) {
|
|
28
|
+
const relativePath = normalizeRelativePath(requestedPath);
|
|
29
|
+
const absolutePath = path.resolve(mount.root, relativePath);
|
|
30
|
+
const prefix = mount.root.endsWith(path.sep) ? mount.root : `${mount.root}${path.sep}`;
|
|
31
|
+
if (!absolutePath.startsWith(prefix))
|
|
32
|
+
throw new Error(`Source path escapes mount ${mount.name}: ${requestedPath}`);
|
|
33
|
+
return { relativePath, absolutePath };
|
|
34
|
+
}
|
|
35
|
+
function provenance(url, mount, relativePath, absolutePath, mtimeMs) {
|
|
36
|
+
return {
|
|
37
|
+
mount: mount.name,
|
|
38
|
+
path: relativePath,
|
|
39
|
+
exportName: url.searchParams.get("export") || "default",
|
|
40
|
+
kind: url.searchParams.get("kind") === "story" ? "story" : "component",
|
|
41
|
+
absolutePath,
|
|
42
|
+
mtimeMs,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function findMount(url, mounts) {
|
|
46
|
+
const name = url.searchParams.get("mount") ?? "";
|
|
47
|
+
const mount = mounts.find((candidate) => candidate.name === name);
|
|
48
|
+
if (!mount)
|
|
49
|
+
throw new Error(`Unknown Docstream source mount: ${name}`);
|
|
50
|
+
return mount;
|
|
51
|
+
}
|
|
52
|
+
function errorMessage(error) {
|
|
53
|
+
return error instanceof Error ? error.message : String(error);
|
|
54
|
+
}
|
|
55
|
+
function installMiddleware(server, apiBase, viteBase, mounts) {
|
|
56
|
+
server.middlewares.use(async (request, response, next) => {
|
|
57
|
+
const url = requestUrl(request);
|
|
58
|
+
if (url.pathname !== `${apiBase}/source` && url.pathname !== `${apiBase}/module`)
|
|
59
|
+
return next();
|
|
60
|
+
try {
|
|
61
|
+
const mount = findMount(url, mounts);
|
|
62
|
+
const requestedPath = url.searchParams.get("path") ?? "";
|
|
63
|
+
const { relativePath, absolutePath } = sourcePath(mount, requestedPath);
|
|
64
|
+
if (url.pathname === `${apiBase}/module`) {
|
|
65
|
+
if (request.method !== "GET")
|
|
66
|
+
return send(response, 405, "Method not allowed", "text/plain; charset=utf-8");
|
|
67
|
+
await fs.access(absolutePath);
|
|
68
|
+
const sourceUrl = `${viteBase.replace(/\/$/, "")}/@fs/${absolutePath.replaceAll(path.sep, "/")}?docstream=${Date.now()}`;
|
|
69
|
+
const module = `import * as source from ${JSON.stringify(sourceUrl)};\nexport default source;\n`;
|
|
70
|
+
return send(response, 200, module, "text/javascript; charset=utf-8");
|
|
71
|
+
}
|
|
72
|
+
if (request.method === "GET") {
|
|
73
|
+
const [content, stat] = await Promise.all([fs.readFile(absolutePath, "utf8"), fs.stat(absolutePath)]);
|
|
74
|
+
return send(response, 200, JSON.stringify({ content, provenance: provenance(url, mount, relativePath, absolutePath, stat.mtimeMs) }));
|
|
75
|
+
}
|
|
76
|
+
if (request.method === "PUT") {
|
|
77
|
+
if (!mount.writable)
|
|
78
|
+
return send(response, 403, `Source mount ${mount.name} is read-only`, "text/plain; charset=utf-8");
|
|
79
|
+
await fs.access(absolutePath);
|
|
80
|
+
const parsed = JSON.parse(await requestBody(request));
|
|
81
|
+
if (typeof parsed.content !== "string")
|
|
82
|
+
return send(response, 400, "Expected a JSON string field named content", "text/plain; charset=utf-8");
|
|
83
|
+
await fs.writeFile(absolutePath, parsed.content, "utf8");
|
|
84
|
+
const stat = await fs.stat(absolutePath);
|
|
85
|
+
server.watcher.add(absolutePath);
|
|
86
|
+
server.ws.send({ type: "full-reload", path: "*" });
|
|
87
|
+
return send(response, 200, JSON.stringify({ content: parsed.content, provenance: provenance(url, mount, relativePath, absolutePath, stat.mtimeMs) }));
|
|
88
|
+
}
|
|
89
|
+
return send(response, 405, "Method not allowed", "text/plain; charset=utf-8");
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
const status = error && typeof error === "object" && "code" in error && error.code === "ENOENT" ? 404 : 400;
|
|
93
|
+
return send(response, status, errorMessage(error), "text/plain; charset=utf-8");
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Mount real source directories behind safe Vite dev-server endpoints.
|
|
99
|
+
* Markdown references import live modules from these files, and editor writes
|
|
100
|
+
* go back to disk so Vite's normal watcher/HMR pipeline remains authoritative.
|
|
101
|
+
*/
|
|
102
|
+
export function docstreamSources(options) {
|
|
103
|
+
const apiBase = `/${(options.apiBase ?? "/@docstream").replace(/^\/+|\/+$/g, "")}`;
|
|
104
|
+
let mounts = [];
|
|
105
|
+
let viteBase = "/";
|
|
106
|
+
return {
|
|
107
|
+
name: "docstream-sources",
|
|
108
|
+
enforce: "pre",
|
|
109
|
+
configResolved(config) {
|
|
110
|
+
viteBase = config.base || "/";
|
|
111
|
+
const names = new Set();
|
|
112
|
+
mounts = options.mounts.map((mount) => {
|
|
113
|
+
if (!mount.name || names.has(mount.name))
|
|
114
|
+
throw new Error(`Docstream source mount names must be unique: ${mount.name}`);
|
|
115
|
+
names.add(mount.name);
|
|
116
|
+
return {
|
|
117
|
+
name: mount.name,
|
|
118
|
+
root: path.resolve(config.root, mount.root),
|
|
119
|
+
writable: mount.writable !== false,
|
|
120
|
+
};
|
|
121
|
+
});
|
|
122
|
+
},
|
|
123
|
+
configureServer(server) {
|
|
124
|
+
installMiddleware(server, apiBase, viteBase, mounts);
|
|
125
|
+
},
|
|
126
|
+
resolveId(id) {
|
|
127
|
+
if (id === VIRTUAL_ID)
|
|
128
|
+
return RESOLVED_VIRTUAL_ID;
|
|
129
|
+
},
|
|
130
|
+
load(id) {
|
|
131
|
+
if (id !== RESOLVED_VIRTUAL_ID)
|
|
132
|
+
return;
|
|
133
|
+
return `export const apiBase = ${JSON.stringify(apiBase)};\nexport const mounts = ${JSON.stringify(options.mounts.map(({ name, writable = true }) => ({ name, writable })))};\n`;
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PlayerAudio, VideoScene } from "@brett_lamy/viz-engine";
|
|
2
|
+
export interface VizEmbedProps {
|
|
3
|
+
scene: VideoScene;
|
|
4
|
+
audio?: PlayerAudio;
|
|
5
|
+
title?: string;
|
|
6
|
+
className?: string;
|
|
7
|
+
autoplay?: boolean;
|
|
8
|
+
loop?: boolean;
|
|
9
|
+
showCaptions?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Mount a deterministic VizEngine scene inside a Docstream document. This is
|
|
13
|
+
* intentionally a component API rather than a markdown escape hatch: callers
|
|
14
|
+
* choose the scene and its evidence, while Docstream supplies document chrome
|
|
15
|
+
* and accessible figure semantics.
|
|
16
|
+
*/
|
|
17
|
+
export declare function VizEmbed({ scene, audio, title, className, autoplay, loop, showCaptions, }: VizEmbedProps): import("react").JSX.Element;
|
|
18
|
+
//# sourceMappingURL=VizEmbed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VizEmbed.d.ts","sourceRoot":"","sources":["../../src/viz/VizEmbed.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAGrE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,UAAU,CAAA;IACjB,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,KAAK,EACL,KAAK,EACL,SAAS,EACT,QAAe,EACf,IAAW,EACX,YAAoB,GACrB,EAAE,aAAa,+BAcf"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { VizPlayer } from "@brett_lamy/viz-engine";
|
|
3
|
+
/**
|
|
4
|
+
* Mount a deterministic VizEngine scene inside a Docstream document. This is
|
|
5
|
+
* intentionally a component API rather than a markdown escape hatch: callers
|
|
6
|
+
* choose the scene and its evidence, while Docstream supplies document chrome
|
|
7
|
+
* and accessible figure semantics.
|
|
8
|
+
*/
|
|
9
|
+
export function VizEmbed({ scene, audio, title, className, autoplay = true, loop = true, showCaptions = false, }) {
|
|
10
|
+
return (_jsxs("figure", { className: `docstream-viz ${className ?? ""}`.trim(), children: [_jsx(VizPlayer, { scene: scene, ...(audio === undefined ? {} : { audio }), autoplay: autoplay, loop: loop, showCaptions: showCaptions, className: "docstream-viz__player" }), title && _jsx("figcaption", { children: title })] }));
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=VizEmbed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VizEmbed.js","sourceRoot":"","sources":["../../src/viz/VizEmbed.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAYlD;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,EACvB,KAAK,EACL,KAAK,EACL,KAAK,EACL,SAAS,EACT,QAAQ,GAAG,IAAI,EACf,IAAI,GAAG,IAAI,EACX,YAAY,GAAG,KAAK,GACN;IACd,OAAO,CACL,kBAAQ,SAAS,EAAE,iBAAiB,SAAS,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,aAC1D,KAAC,SAAS,IACR,KAAK,EAAE,KAAK,KACR,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAC1C,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAC,uBAAuB,GACjC,EACD,KAAK,IAAI,+BAAa,KAAK,GAAc,IACnC,CACV,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/viz/index.ts"],"names":[],"mappings":"AAAA,OAAO,mCAAmC,CAAA;AAE1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/viz/index.ts"],"names":[],"mappings":"AAAA,OAAO,mCAAmC,CAAA;AAE1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brett_lamy/docstream",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "GitBook-aware readonly markdown and AI stream renderer.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
8
8
|
"type": "module",
|
|
9
9
|
"scripts": {
|
|
10
|
+
"build": "node scripts/build.mjs",
|
|
10
11
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
11
|
-
"test": "vitest run"
|
|
12
|
+
"test": "npm run build && vitest run",
|
|
13
|
+
"prepack": "npm run build"
|
|
12
14
|
},
|
|
13
|
-
"main": "./
|
|
14
|
-
"types": "./
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
15
17
|
"files": [
|
|
18
|
+
"dist",
|
|
16
19
|
"src",
|
|
17
20
|
"!src/**/*.test.ts",
|
|
18
21
|
"!src/**/*.test.tsx",
|
|
@@ -24,58 +27,84 @@
|
|
|
24
27
|
],
|
|
25
28
|
"exports": {
|
|
26
29
|
".": {
|
|
27
|
-
"
|
|
28
|
-
"
|
|
30
|
+
"source": "./src/index.ts",
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"import": "./dist/index.js",
|
|
33
|
+
"default": "./dist/index.js"
|
|
29
34
|
},
|
|
30
35
|
"./gitbook": {
|
|
31
|
-
"
|
|
32
|
-
"
|
|
36
|
+
"source": "./src/gitbook/index.ts",
|
|
37
|
+
"types": "./dist/gitbook/index.d.ts",
|
|
38
|
+
"import": "./dist/gitbook/index.js",
|
|
39
|
+
"default": "./dist/gitbook/index.js"
|
|
33
40
|
},
|
|
34
41
|
"./streamdown": {
|
|
35
|
-
"
|
|
36
|
-
"
|
|
42
|
+
"source": "./src/streamdown.tsx",
|
|
43
|
+
"types": "./dist/streamdown.d.ts",
|
|
44
|
+
"import": "./dist/streamdown.js",
|
|
45
|
+
"default": "./dist/streamdown.js"
|
|
37
46
|
},
|
|
38
47
|
"./reference": {
|
|
39
|
-
"
|
|
40
|
-
"
|
|
48
|
+
"source": "./src/docs/reference.tsx",
|
|
49
|
+
"types": "./dist/docs/reference.d.ts",
|
|
50
|
+
"import": "./dist/docs/reference.js",
|
|
51
|
+
"default": "./dist/docs/reference.js"
|
|
41
52
|
},
|
|
42
53
|
"./assets": {
|
|
43
|
-
"
|
|
44
|
-
"
|
|
54
|
+
"source": "./src/assets.ts",
|
|
55
|
+
"types": "./dist/assets.d.ts",
|
|
56
|
+
"import": "./dist/assets.js",
|
|
57
|
+
"default": "./dist/assets.js"
|
|
45
58
|
},
|
|
46
59
|
"./openapi": {
|
|
47
|
-
"
|
|
48
|
-
"
|
|
60
|
+
"source": "./src/openapi/OpenApiOperation.tsx",
|
|
61
|
+
"types": "./dist/openapi/OpenApiOperation.d.ts",
|
|
62
|
+
"import": "./dist/openapi/OpenApiOperation.js",
|
|
63
|
+
"default": "./dist/openapi/OpenApiOperation.js"
|
|
49
64
|
},
|
|
50
65
|
"./replay": {
|
|
51
|
-
"
|
|
52
|
-
"
|
|
66
|
+
"source": "./src/replay/index.ts",
|
|
67
|
+
"types": "./dist/replay/index.d.ts",
|
|
68
|
+
"import": "./dist/replay/index.js",
|
|
69
|
+
"default": "./dist/replay/index.js"
|
|
53
70
|
},
|
|
54
71
|
"./video": {
|
|
55
|
-
"
|
|
56
|
-
"
|
|
72
|
+
"source": "./src/video/index.ts",
|
|
73
|
+
"types": "./dist/video/index.d.ts",
|
|
74
|
+
"import": "./dist/video/index.js",
|
|
75
|
+
"default": "./dist/video/index.js"
|
|
57
76
|
},
|
|
58
77
|
"./viz": {
|
|
59
|
-
"
|
|
60
|
-
"
|
|
78
|
+
"source": "./src/viz/index.ts",
|
|
79
|
+
"types": "./dist/viz/index.d.ts",
|
|
80
|
+
"import": "./dist/viz/index.js",
|
|
81
|
+
"default": "./dist/viz/index.js"
|
|
61
82
|
},
|
|
62
83
|
"./playground": {
|
|
63
|
-
"
|
|
64
|
-
"
|
|
84
|
+
"source": "./src/playground/index.ts",
|
|
85
|
+
"types": "./dist/playground/index.d.ts",
|
|
86
|
+
"import": "./dist/playground/index.js",
|
|
87
|
+
"default": "./dist/playground/index.js"
|
|
65
88
|
},
|
|
66
89
|
"./source": {
|
|
67
|
-
"
|
|
68
|
-
"
|
|
90
|
+
"source": "./src/source/index.ts",
|
|
91
|
+
"types": "./dist/source/index.d.ts",
|
|
92
|
+
"import": "./dist/source/index.js",
|
|
93
|
+
"default": "./dist/source/index.js"
|
|
69
94
|
},
|
|
70
95
|
"./demo": {
|
|
71
|
-
"
|
|
72
|
-
"
|
|
96
|
+
"source": "./src/demo/index.ts",
|
|
97
|
+
"types": "./dist/demo/index.d.ts",
|
|
98
|
+
"import": "./dist/demo/index.js",
|
|
99
|
+
"default": "./dist/demo/index.js"
|
|
73
100
|
},
|
|
74
101
|
"./vite": {
|
|
75
|
-
"
|
|
76
|
-
"
|
|
102
|
+
"source": "./src/vite/index.ts",
|
|
103
|
+
"types": "./dist/vite/index.d.ts",
|
|
104
|
+
"import": "./dist/vite/index.js",
|
|
105
|
+
"default": "./dist/vite/index.js"
|
|
77
106
|
},
|
|
78
|
-
"./styles.css": "./
|
|
107
|
+
"./styles.css": "./dist/styles.css"
|
|
79
108
|
},
|
|
80
109
|
"dependencies": {
|
|
81
110
|
"framer-motion": "^13.1.1",
|
|
@@ -83,6 +112,7 @@
|
|
|
83
112
|
"katex": "^0.18.5",
|
|
84
113
|
"lucide-react": "^1.17.0",
|
|
85
114
|
"mermaid": "^11.15.0",
|
|
115
|
+
"react-aria": "^3.52.1",
|
|
86
116
|
"rrweb": "2.0.0-alpha.20",
|
|
87
117
|
"yaml": "^2.9.0"
|
|
88
118
|
},
|
|
@@ -113,8 +143,11 @@
|
|
|
113
143
|
"@brett_lamy/viz-engine": "^0.2.1",
|
|
114
144
|
"@types/node": "^24.0.0",
|
|
115
145
|
"@types/react": "^18.3.3",
|
|
146
|
+
"@types/react-dom": "^18.3.7",
|
|
147
|
+
"happy-dom": "^20.14.5",
|
|
116
148
|
"typescript": "^5.5.4",
|
|
117
149
|
"vite": "^7.0.0",
|
|
118
150
|
"vitest": "^3.2.4"
|
|
119
|
-
}
|
|
151
|
+
},
|
|
152
|
+
"module": "./dist/index.js"
|
|
120
153
|
}
|
package/src/demo/DemoViewer.tsx
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
type KeyboardEvent as ReactKeyboardEvent,
|
|
25
25
|
type PointerEvent as ReactPointerEvent,
|
|
26
26
|
type ReactNode,
|
|
27
|
-
type
|
|
27
|
+
type Ref,
|
|
28
28
|
} from "react"
|
|
29
29
|
import { motion, useReducedMotion } from "framer-motion"
|
|
30
30
|
import { ExternalLink, FileCode2, Folder, Maximize2, Monitor, Smartphone, Tablet, X } from "lucide-react"
|
|
@@ -36,8 +36,10 @@ import { HighlightedCode } from "../docs/HighlightedCode"
|
|
|
36
36
|
import { CopyButton } from "../docs/copy"
|
|
37
37
|
import { PillTabs, Segmented, rovingKeyDown } from "../docs/controls"
|
|
38
38
|
import { useDemoResolver, useDemoRuntime } from "./context"
|
|
39
|
+
import { createDocstreamClipboard, type DemoSourceSnapshot, type DocstreamClipboard } from "./clipboard"
|
|
40
|
+
import { CopyDemoButton } from "./copy-demo"
|
|
39
41
|
import { languageForPath } from "./glob"
|
|
40
|
-
import {
|
|
42
|
+
import { useDemoVFSContext, useDemoVFSEntry, type DemoVFS } from "./vfs"
|
|
41
43
|
import { cssToSurface, surfaceStyle, surfaceToCss } from "./surface"
|
|
42
44
|
import type { DemoComponent, DemoFile, DemoMeta, DemoResolver, DemoVariant, InlineDemoRuntime } from "./types"
|
|
43
45
|
|
|
@@ -67,6 +69,11 @@ export interface DemoViewerProps {
|
|
|
67
69
|
runtime?: InlineDemoRuntime
|
|
68
70
|
/** Extra npm dependencies for the runtime, merged over `demoDependencies` from context. */
|
|
69
71
|
dependencies?: Record<string, string>
|
|
72
|
+
/**
|
|
73
|
+
* Demo files held in memory by `src` (pasted demos). Used, like inline files, when the block
|
|
74
|
+
* has none of its own and no resolver knows `src`. Defaults to the VFS in context (`demoVFS`).
|
|
75
|
+
*/
|
|
76
|
+
vfs?: DemoVFS
|
|
70
77
|
/** Class on the viewer's outer element. (The preview canvas's class is `canvasClassName`.) */
|
|
71
78
|
className?: string
|
|
72
79
|
/*
|
|
@@ -120,6 +127,32 @@ export async function preloadDemos(resolver: DemoResolver, srcs: string[]): Prom
|
|
|
120
127
|
)
|
|
121
128
|
}
|
|
122
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Fetch demos' meta and files (not their components) into the viewer's cache, so
|
|
132
|
+
* `peekDemoSource` can answer synchronously — e.g. when a copy event needs a demo's files.
|
|
133
|
+
*/
|
|
134
|
+
export async function prefetchDemoSources(resolver: DemoResolver, srcs: string[]): Promise<void> {
|
|
135
|
+
const cache = cacheFor(resolver)
|
|
136
|
+
const settle = async (key: string, run: () => Promise<unknown>) => {
|
|
137
|
+
if (cache.get(key)?.status === "ready") return
|
|
138
|
+
try {
|
|
139
|
+
cache.set(key, { status: "ready", value: await run() })
|
|
140
|
+
} catch (cause) {
|
|
141
|
+
cache.set(key, { status: "error", error: cause instanceof Error ? cause : new Error(String(cause)) })
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
await Promise.all(srcs.flatMap((src) => [settle(`meta:${src}`, () => resolver.meta(src)), settle(`files:${src}`, () => resolver.files(src))]))
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** A demo's files (and meta) if the resolver has already delivered them (viewer, `preloadDemos`, `prefetchDemoSources`). */
|
|
148
|
+
export function peekDemoSource(resolver: DemoResolver, src: string): DemoSourceSnapshot | undefined {
|
|
149
|
+
const cache = settled.get(resolver)
|
|
150
|
+
const files = cache?.get(`files:${src}`)
|
|
151
|
+
if (files?.status !== "ready" || !(files.value as DemoFile[]).length) return undefined
|
|
152
|
+
const meta = cache?.get(`meta:${src}`)
|
|
153
|
+
return { files: files.value as DemoFile[], ...(meta?.status === "ready" && meta.value ? { meta: meta.value as DemoMeta } : {}) }
|
|
154
|
+
}
|
|
155
|
+
|
|
123
156
|
/** Resolves `run()` once `active`, remembering settled values so remounts don't flash. */
|
|
124
157
|
function useResolved<T>(resolver: DemoResolver | undefined, key: string, active: boolean, run: () => Promise<T>): Loaded<T> {
|
|
125
158
|
const cached = resolver ? (cacheFor(resolver).get(key) as Loaded<T> | undefined) : undefined
|
|
@@ -165,10 +198,11 @@ const useComponent = (resolver: DemoResolver | undefined, src: string, active: b
|
|
|
165
198
|
|
|
166
199
|
/** True once the element has come within `margin` of the viewport (stays true). */
|
|
167
200
|
function useNearViewport<T extends Element>(margin = "400px 0px") {
|
|
168
|
-
|
|
201
|
+
// A callback ref, so an element that appears later (a VFS demo arriving) is observed too.
|
|
202
|
+
const [el, setEl] = useState<T | null>(null)
|
|
203
|
+
const ref = useMemo(() => (node: T | null) => setEl(node), [])
|
|
169
204
|
const [near, setNear] = useState(false)
|
|
170
205
|
useEffect(() => {
|
|
171
|
-
const el = ref.current
|
|
172
206
|
if (!el || near) return
|
|
173
207
|
if (typeof IntersectionObserver === "undefined") {
|
|
174
208
|
setNear(true)
|
|
@@ -179,7 +213,7 @@ function useNearViewport<T extends Element>(margin = "400px 0px") {
|
|
|
179
213
|
}, { rootMargin: margin })
|
|
180
214
|
observer.observe(el)
|
|
181
215
|
return () => observer.disconnect()
|
|
182
|
-
}, [near, margin])
|
|
216
|
+
}, [el, near, margin])
|
|
183
217
|
return [ref, near] as const
|
|
184
218
|
}
|
|
185
219
|
|
|
@@ -594,7 +628,12 @@ export function DemoViewer(props: DemoViewerProps) {
|
|
|
594
628
|
const runtimeOptions = useDemoRuntime({ runtime: props.runtime, dependencies: props.dependencies })
|
|
595
629
|
const { src } = props
|
|
596
630
|
const [ref, near] = useNearViewport<HTMLElement>()
|
|
597
|
-
const
|
|
631
|
+
const vfs = useDemoVFSContext(props.vfs)
|
|
632
|
+
// Pasted demos: files held by the VFS stand in for inline files the block doesn't carry.
|
|
633
|
+
const vfsEntry = useDemoVFSEntry(vfs, props.files?.length ? "" : src)
|
|
634
|
+
const ownFiles = props.files?.length ? props.files : vfsEntry?.files
|
|
635
|
+
const ownEntry = props.files?.length ? props.entry : props.entry ?? vfsEntry?.meta?.entry
|
|
636
|
+
const inlineFiles = useMemo(() => orderInline(ownFiles, ownEntry), [ownFiles, ownEntry])
|
|
598
637
|
|
|
599
638
|
// A resolver is consulted unless the block brings its own files and the resolver
|
|
600
639
|
// says (via `list()`) that it does not know this src.
|
|
@@ -607,7 +646,7 @@ export function DemoViewer(props: DemoViewerProps) {
|
|
|
607
646
|
const mode: "resolver" | "inline" | "none" =
|
|
608
647
|
tryResolver && !(inlineFiles && resolverFailed) ? "resolver" : inlineFiles ? "inline" : "none"
|
|
609
648
|
|
|
610
|
-
const metaValue = mode === "resolver"
|
|
649
|
+
const metaValue = mode === "resolver" ? (meta.status === "ready" ? meta.value : undefined) : mode === "inline" && !props.files?.length ? vfsEntry?.meta : undefined
|
|
611
650
|
const files: Loaded<DemoFile[]> = mode === "inline" ? { status: "ready", value: inlineFiles! } : resolvedFiles
|
|
612
651
|
const title = props.title ?? metaValue?.title ?? (src.split("/").pop() || "Demo")
|
|
613
652
|
const description = props.description ?? metaValue?.description
|
|
@@ -669,7 +708,12 @@ export function DemoViewer(props: DemoViewerProps) {
|
|
|
669
708
|
...(props.surface ? { surface: typeof props.surface === "string" ? props.surface : surfaceToCss(props.surface) } : {}),
|
|
670
709
|
...(props.variantsWidth !== undefined && props.variantsWidth !== "" ? { variantsWidth: String(props.variantsWidth) } : {}),
|
|
671
710
|
}
|
|
672
|
-
|
|
711
|
+
// "Copy demo": the exact block (src-only stays src-only; inline files stay inline) plus its files.
|
|
712
|
+
const copyDemo = (): DocstreamClipboard | null => {
|
|
713
|
+
if (!fileList?.length) return null
|
|
714
|
+
const exact: DemoNode = props.files?.length ? { ...node, ...(props.entry ? { entry: props.entry } : {}), files: props.files.map((f) => ({ ...f })) } : node
|
|
715
|
+
return createDocstreamClipboard({ type: "doc", children: [exact] }, { lookup: () => ({ files: fileList, ...(metaValue ? { meta: metaValue } : {}) }) })
|
|
716
|
+
}
|
|
673
717
|
|
|
674
718
|
const dialog = (
|
|
675
719
|
<FullscreenDialog
|
|
@@ -702,6 +746,7 @@ export function DemoViewer(props: DemoViewerProps) {
|
|
|
702
746
|
<span className="docs-demo-spacer" />
|
|
703
747
|
<StatusBadge status={status} />
|
|
704
748
|
<VariantSwitch variants={variants} value={variant} onChange={setVariant} title={title} width={variantsWidth} />
|
|
749
|
+
{fileList?.length ? <CopyDemoButton clipboard={copyDemo} className="docs-demo-icon-btn" /> : null}
|
|
705
750
|
{runnable ? <FullscreenButton onOpen={() => setFullscreen(true)} title={title} /> : null}
|
|
706
751
|
</header>
|
|
707
752
|
{runnable ? (
|
|
@@ -766,7 +811,7 @@ export function DemoViewer(props: DemoViewerProps) {
|
|
|
766
811
|
}
|
|
767
812
|
|
|
768
813
|
function MultiFileViewer({ rootRef, className, baseId, mode, src, title, description, variants, variant, onVariant, files, preview, near, height, viewport, bleed, look, status, variantsWidth, href, onFullscreen, copyDemo, dialog }: {
|
|
769
|
-
rootRef:
|
|
814
|
+
rootRef: Ref<HTMLElement>
|
|
770
815
|
className: string
|
|
771
816
|
baseId: string
|
|
772
817
|
mode: "resolver" | "inline"
|
|
@@ -787,7 +832,7 @@ function MultiFileViewer({ rootRef, className, baseId, mode, src, title, descrip
|
|
|
787
832
|
variantsWidth: number | string | undefined
|
|
788
833
|
href: string | undefined
|
|
789
834
|
onFullscreen: () => void
|
|
790
|
-
copyDemo: (() =>
|
|
835
|
+
copyDemo: (() => DocstreamClipboard | null) | undefined
|
|
791
836
|
dialog: ReactNode
|
|
792
837
|
}) {
|
|
793
838
|
const runnable = preview.kind !== "unavailable"
|
|
@@ -835,7 +880,7 @@ function MultiFileViewer({ rootRef, className, baseId, mode, src, title, descrip
|
|
|
835
880
|
))}
|
|
836
881
|
</div>
|
|
837
882
|
) : null}
|
|
838
|
-
{copyDemo ? <
|
|
883
|
+
{copyDemo ? <CopyDemoButton clipboard={copyDemo} className="docs-demo-icon-btn" /> : null}
|
|
839
884
|
{runnable ? <FullscreenButton onOpen={onFullscreen} title={title} /> : null}
|
|
840
885
|
<NewTabLink href={href} title={title} />
|
|
841
886
|
</div>
|