@brett_lamy/docstream 0.7.0 → 1.1.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 CHANGED
@@ -255,6 +255,104 @@ const client = createBundledSourceClient({
255
255
  Entries may also be lazy import functions. Keys can be `mount:path` (recommended)
256
256
  or just `path` when names cannot collide.
257
257
 
258
+ ### File-backed live demos
259
+
260
+ `{% demo %}` puts a live example into a page while the page stays **one Markdown
261
+ document**. The example is a folder of real files. The component renders in-page
262
+ (same React tree, lazily loaded near the viewport), and the Code view shows the
263
+ actual file contents.
264
+
265
+ ```md
266
+ {% demo src="button/sizes" %}
267
+
268
+ {% demo src="blocks/inbox" title="Inbox" description="…" height="420" layout="auto" variants="full:Full,compact:Compact" viewport="tablet" %}
269
+ ```
270
+
271
+ Only `src` (`<page>/<example>`) is required. `title`, `description`, `height`
272
+ and `variants` default to the folder's `meta.json`. `layout="auto"` (the default)
273
+ uses the **multi-file viewer** for two or more source files: Preview | Code,
274
+ desktop/tablet/phone widths, a draggable resize handle with a width readout,
275
+ variants, copy, a fullscreen overlay and an optional deep link. Code view has a
276
+ file tree (entry first) with a copy button per file. A single file gets the
277
+ **single-file card**: the preview with a collapsible code panel underneath.
278
+ `variant` is passed to the component as a prop. Frames are CSS size containers,
279
+ so a demo's `@container` queries respond to the preview width. The tag
280
+ round-trips through `parseMarkdown`/`serializeMarkdown`, and while streaming, a
281
+ half-arrived tag is hidden rather than shown as text.
282
+
283
+ ```txt
284
+ examples/button/sizes/
285
+ index.tsx ← default export: ({ variant }) => …
286
+ Sizes.css
287
+ meta.json ← { title, description, height, variants: [{ id, label }], entry, layout, bleed }
288
+ ```
289
+
290
+ Tell docstream where demos live with a `DemoResolver`. With Vite, three
291
+ `import.meta.glob` maps are enough:
292
+
293
+ ```tsx
294
+ import { MarkdownContent, createGlobDemoResolver, demoHref } from "@brett_lamy/docstream"
295
+
296
+ const demoResolver = createGlobDemoResolver({
297
+ root: "./examples", // ids are <page>/<example> below this prefix
298
+ modules: import.meta.glob("./examples/*/*/index.tsx"),
299
+ sources: import.meta.glob("./examples/*/*/**/*.{ts,tsx,css,json}", { query: "?raw", import: "default" }),
300
+ metas: import.meta.glob("./examples/*/*/meta.json", { eager: true, import: "default" }),
301
+ href: (src) => demoHref(src), // optional "?demo=<src>" deep link → route it to <DemoFullscreen src={src} />
302
+ })
303
+
304
+ <MarkdownContent markdown={page} demoResolver={demoResolver} pageActions />
305
+ ```
306
+
307
+ `demoResolver` is accepted by `DocsRenderer`, `MarkdownContent`,
308
+ `GitbookStreamdown` and the playground renderer, and it's provided through
309
+ `DocstreamDemoContext`, so nested renderers inherit it. You can also write a
310
+ resolver by hand:
311
+ `{ list?(), meta(src), files(src), load(src), href?(src, { variant }) }`.
312
+ `createGlobDemoResolver` is plain TypeScript, so it's exported from the package
313
+ root and from `@brett_lamy/docstream/demo`, not from the Node-only `./vite` entry.
314
+
315
+ ### Page actions
316
+
317
+ `pageActions` renders a shadcn-style **Copy page ▾** above the content, with
318
+ Copy as Markdown, View as Markdown, Open in ChatGPT and Open in Claude. Pass
319
+ `true`, or pass options such as `{ markdownUrl, pageUrl, prompt, actions, transform }`.
320
+ You can also place `<DocPageActions markdown={page} />` yourself. Copying
321
+ resolves every `{% demo %}` into its real files as titled fences, so the copied
322
+ page is self-contained. The same resolution is available as a pure helper for
323
+ build-time `.md` or `llms.txt` generation:
324
+
325
+ ```ts
326
+ import { resolveDemosToMarkdown } from "@brett_lamy/docstream/demo"
327
+
328
+ const md = await resolveDemosToMarkdown(page, demoResolver)
329
+ ```
330
+
331
+ ### Synced tabs (install instructions)
332
+
333
+ When every tab in a tab set is a single code block, the tabs render as one code
334
+ block, with pill tabs, a terminal glyph for shell code, and a copy button in its
335
+ header. Add `sync="<key>"` and every tab set with the same key follows the
336
+ reader's choice. The choice is matched by tab title and is remembered in
337
+ `localStorage` across the page and across visits:
338
+
339
+ ````md
340
+ {% tabs sync="pm" %}
341
+ {% tab title="npm" %}
342
+ ```sh
343
+ npm install @brett_lamy/docstream
344
+ ```
345
+ {% endtab %}
346
+ {% tab title="pnpm" %}
347
+ ```sh
348
+ pnpm add @brett_lamy/docstream
349
+ ```
350
+ {% endtab %}
351
+ {% endtabs %}
352
+ ````
353
+
354
+ Every code block now also has a copy button.
355
+
258
356
  ## Assets and OpenAPI Specs
259
357
 
260
358
  Relative image and OpenAPI spec paths can be resolved against an asset base:
@@ -278,6 +376,10 @@ You can also resolve paths yourself with `resolveAsset`.
278
376
  - `SourcePreview`: Imports and renders a mounted component or CSF story export.
279
377
  - `createViteSourceClient`: Reads, writes, and imports files exposed by the Vite plugin.
280
378
  - `createBundledSourceClient`: Imports bundled source modules in read-only production builds.
379
+ - `DemoViewer` / `DemoFullscreen`: The `{% demo %}` viewer, and one demo filling the viewport (for `?demo=` deep links).
380
+ - `createGlobDemoResolver`, `demoHref`, `demoFromSearch`: Build a `DemoResolver` from `import.meta.glob` maps; deep-link helpers.
381
+ - `resolveDemosToMarkdown(markdown, resolver)`: Inlines each `{% demo %}` as its real files (pure, async).
382
+ - `DocPageActions`: The "Copy page ▾" menu.
281
383
 
282
384
  ### Parser and Serializer
283
385
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brett_lamy/docstream",
3
- "version": "0.7.0",
3
+ "version": "1.1.0",
4
4
  "description": "GitBook-aware readonly markdown and AI stream renderer.",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -65,6 +65,10 @@
65
65
  "types": "./src/source/index.ts",
66
66
  "import": "./src/source/index.ts"
67
67
  },
68
+ "./demo": {
69
+ "types": "./src/demo/index.ts",
70
+ "import": "./src/demo/index.ts"
71
+ },
68
72
  "./vite": {
69
73
  "types": "./src/vite/index.ts",
70
74
  "import": "./src/vite/index.ts"
@@ -74,8 +78,8 @@
74
78
  "dependencies": {
75
79
  "@brett_lamy/viz-engine": ">=0.2.0",
76
80
  "framer-motion": "^13.1.1",
77
- "katex": "^0.18.5",
78
81
  "gpu-lexer": "^0.0.2",
82
+ "katex": "^0.18.5",
79
83
  "lucide-react": "^1.17.0",
80
84
  "mermaid": "^11.15.0",
81
85
  "rrweb": "2.0.0-alpha.20",