@poveste/shared 0.19.1 → 0.21.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/dist/index.d.ts CHANGED
@@ -5,3 +5,4 @@ export * from './story-error.js';
5
5
  export * from './story.js';
6
6
  export * from './type-utils.js';
7
7
  export * from './types/index.js';
8
+ export * from './virtual.js';
package/dist/index.js CHANGED
@@ -5,3 +5,4 @@ export * from './story-error.js';
5
5
  export * from './story.js';
6
6
  export * from './type-utils.js';
7
7
  export * from './types/index.js';
8
+ export * from './virtual.js';
package/dist/story.js CHANGED
@@ -7,6 +7,8 @@ export const omitInheritStoryProps = [
7
7
  'file',
8
8
  'slots',
9
9
  'lastSelectedVariant',
10
+ // The Docs tab belongs to the story, not to a variant (#1398).
11
+ 'autoDocs',
10
12
  ];
11
13
  /**
12
14
  * Auto-props bookkeeping, which is not story state.
@@ -1,6 +1,7 @@
1
1
  import type { MarkdownIt } from 'markdown-it';
2
2
  import type { UseHeadInput } from 'unhead/types';
3
3
  import type { UserConfig as ViteConfig, ConfigEnv as ViteConfigEnv } from 'vite';
4
+ import type { AutoDocsOptions } from './docgen.js';
4
5
  import type { Plugin } from './plugin.js';
5
6
  import type { ServerTreeFile, StoryProps } from './story.js';
6
7
  export interface SupportMatchPattern {
@@ -89,6 +90,13 @@ export interface PovesteConfig {
89
90
  * in iframes. Set to false to restore pre-1.0 behavior. See guide/css.md.
90
91
  */
91
92
  isolateStyles?: boolean;
93
+ /**
94
+ * Auto-docs: a props, slots and events table read from each component's types.
95
+ * Extraction starts the first time a reader opens a story's docs, in a worker,
96
+ * and only for the components that story imports; it holds a type checker while
97
+ * it runs. Set to false to turn it off. Default: on.
98
+ */
99
+ autoDocs?: boolean | AutoDocsOptions;
92
100
  /**
93
101
  * CSS files loaded into the main app (not into stories). Wrapped in
94
102
  * @layer poveste-user-globals — lower priority than chrome.
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Auto-docs: what a framework extractor reads off a component, and the contract
3
+ * between it and the shell that decides when it runs (#159, #1159).
4
+ */
5
+ export interface DocTag {
6
+ name: string;
7
+ text?: string;
8
+ }
9
+ export interface DocProp {
10
+ name: string;
11
+ description?: string;
12
+ type: string;
13
+ required: boolean;
14
+ /** The default the code applies, which wins over the tag when both exist. */
15
+ default?: string;
16
+ /** The default a `@default` or `@defaultValue` tag states. */
17
+ defaultTag?: string;
18
+ /** Both defaults exist and say different things: the code's is shown, and this flags it. */
19
+ defaultConflict?: boolean;
20
+ tags: DocTag[];
21
+ }
22
+ export interface DocSlot {
23
+ name: string;
24
+ description?: string;
25
+ type?: string;
26
+ /**
27
+ * What it passes its content, `open` in `<template #default="{ open }">`, one row each,
28
+ * so the JSDoc on each shows (#1436).
29
+ */
30
+ props?: {
31
+ name: string;
32
+ type: string;
33
+ description?: string;
34
+ }[];
35
+ tags: DocTag[];
36
+ }
37
+ export interface DocEvent {
38
+ name: string;
39
+ description?: string;
40
+ type?: string;
41
+ tags: DocTag[];
42
+ }
43
+ export interface ComponentDoc {
44
+ /** The component's own name, when the file it was read from is not named after it. */
45
+ name?: string;
46
+ /** Its type parameters as the source declares them, `T extends string = string`, when it has any. */
47
+ generic?: string;
48
+ props: DocProp[];
49
+ slots: DocSlot[];
50
+ events: DocEvent[];
51
+ }
52
+ /**
53
+ * One framework's extractor, created inside the docgen worker the first time a
54
+ * component of its kind is asked for. It may hold a type checker, which is the
55
+ * memory this whole design is about: `dispose` must let it go.
56
+ */
57
+ export interface DocgenExtractor {
58
+ /**
59
+ * A failure is thrown. When the file is not named after the component, as with a
60
+ * JSX story, an error carrying a `component` string names it for the reader.
61
+ */
62
+ extract: (file: string) => ComponentDoc | undefined | Promise<ComponentDoc | undefined>;
63
+ /** A file changed on disk. Called for any file, not only components. */
64
+ update?: (file: string) => void | Promise<void>;
65
+ /**
66
+ * The files its program read, outside `node_modules`. The dev server watches
67
+ * them: a types file the browser never loads, or one outside the book's root,
68
+ * is otherwise never seen to change (#1190).
69
+ */
70
+ sources?: () => string[] | Promise<string[]>;
71
+ dispose: () => void | Promise<void>;
72
+ }
73
+ export interface DocgenExtractorContext {
74
+ /** The book's root. */
75
+ root: string;
76
+ /** Whatever the plugin passed as `docgen.options`. */
77
+ options: unknown;
78
+ }
79
+ /** The shape of the module a plugin names in `docgen.module`. */
80
+ export interface DocgenExtractorModule {
81
+ createExtractor: (context: DocgenExtractorContext) => DocgenExtractor | Promise<DocgenExtractor>;
82
+ }
83
+ export interface PluginDocgen {
84
+ /**
85
+ * What a request hands the extractor. `imports`: each file the story's module
86
+ * imports that `match` accepts, as a Vue story imports its `.vue` files.
87
+ * `story`: the story file itself, for a story collection gave to this plugin's
88
+ * `supportPlugin` and that `match` accepts, in a format whose story names its
89
+ * component in a `component` field the extractor resolves. `autoDocs.exclude`
90
+ * reaches the extractor in its options, since only it knows the component's file.
91
+ */
92
+ scope?: 'imports' | 'story';
93
+ /** Whether a resolved file is one this plugin documents. */
94
+ match: (file: string) => boolean;
95
+ /**
96
+ * An absolute path or `file:` URL to a module exporting `createExtractor`. It is
97
+ * imported in a worker thread, so it travels as a specifier rather than a function.
98
+ */
99
+ module: string;
100
+ /** Passed to `createExtractor`; it has to survive a structured clone. */
101
+ options?: unknown;
102
+ /**
103
+ * Where the extractor loads `typescript` from, when it reads types with it: a file
104
+ * whose `require` it uses, or `'book'` for the book's own root. In a book where that
105
+ * finds no TypeScript, or one newer than 6, auto-docs is off for this plugin with one
106
+ * log line (#1382, #1401). A value rather than a function, so a plugin whose entry
107
+ * also runs in the browser can declare it.
108
+ */
109
+ typescript?: 'book' | (string & {});
110
+ /**
111
+ * Type packages the book must have for the extractor to read its framework's types,
112
+ * such as `@types/react`. Missing one, auto-docs is off for this plugin with one log
113
+ * line naming it, rather than an error under every component it would read as `any`.
114
+ */
115
+ types?: string[];
116
+ /**
117
+ * Why this plugin cannot document the book at `root`, or nothing when it can.
118
+ * With a reason, auto-docs is off for this plugin and the reason is logged once,
119
+ * in place of an error under every component (#1382).
120
+ */
121
+ unavailable?: (root: string) => string | undefined;
122
+ }
123
+ /** `autoDocs` in the config, when it is more than on or off. */
124
+ export interface AutoDocsOptions {
125
+ /**
126
+ * Packages whose props are documented although they are declared under
127
+ * `node_modules`: a design system a library builds on, such as `reka-ui`.
128
+ */
129
+ allow?: string[];
130
+ /** Component files to leave out, matched as substrings of the path. */
131
+ exclude?: string[];
132
+ }
133
+ /**
134
+ * The field a story format uses to name the component it documents, shared by
135
+ * the JSX formats so Solid and React spell it the same way (#1110, #1161).
136
+ */
137
+ export interface StoryComponentOptions<C> {
138
+ /** The component this story documents. Auto-docs reads its props from its type. */
139
+ component?: C;
140
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Auto-docs: what a framework extractor reads off a component, and the contract
3
+ * between it and the shell that decides when it runs (#159, #1159).
4
+ */
5
+ export {};
@@ -1,5 +1,6 @@
1
1
  export * from './command.js';
2
2
  export * from './config.js';
3
+ export * from './docgen.js';
3
4
  export * from './plugin.js';
4
5
  export * from './prompt.js';
5
6
  export * from './story.js';
@@ -1,5 +1,6 @@
1
1
  export * from './command.js';
2
2
  export * from './config.js';
3
+ export * from './docgen.js';
3
4
  export * from './plugin.js';
4
5
  export * from './prompt.js';
5
6
  export * from './story.js';
@@ -6,6 +6,7 @@ import type { InlineConfig as ViteInlineConfig, Plugin as VitePlugin } from 'vit
6
6
  import type { Awaitable } from '../type-utils.js';
7
7
  import type { PluginCommand } from './command.js';
8
8
  import type { ConfigMode, PovesteConfig } from './config.js';
9
+ import type { PluginDocgen } from './docgen.js';
9
10
  import type { ServerStory, ServerStoryFile, ServerVariant, Variant } from './story.js';
10
11
  /**
11
12
  * A framework's collection strategy: how a story file written for that framework
@@ -233,6 +234,11 @@ export interface Plugin {
233
234
  * Handle a custom event from the client in development mode.
234
235
  */
235
236
  onDevEvent?: (api: PluginApiDevEvent) => Awaitable<any>;
237
+ /**
238
+ * Auto-docs for this framework's components: which files it documents, and the
239
+ * module that extracts them, run lazily in a worker (#1159).
240
+ */
241
+ docgen?: PluginDocgen;
236
242
  /**
237
243
  * Use this hook to manipulate Vite plugins before they are passed to Vite.
238
244
  */
@@ -41,10 +41,18 @@ export interface InheritedProps {
41
41
  }
42
42
  export interface VariantProps extends CommonProps, InheritedProps {
43
43
  }
44
+ /** A section of the auto-docs table on a story's Docs tab. */
45
+ export type AutoDocsSection = 'props' | 'slots' | 'events';
44
46
  export interface StoryProps extends CommonProps, InheritedProps {
45
47
  group?: string;
46
48
  layout?: StoryLayout;
47
49
  docsOnly?: boolean;
50
+ /**
51
+ * The auto-docs table on this story's Docs tab: `false` for none, never extracting
52
+ * the story's components; an array for only those sections. Left out, the story
53
+ * follows the book's `autoDocs`, which a story cannot turn on (#1398).
54
+ */
55
+ autoDocs?: boolean | AutoDocsSection[];
48
56
  }
49
57
  export interface CommonMeta {
50
58
  }
@@ -65,9 +73,15 @@ export interface Story {
65
73
  icon?: string;
66
74
  iconColor?: string;
67
75
  docsOnly?: boolean;
76
+ autoDocs?: boolean | AutoDocsSection[] | undefined;
68
77
  file?: StoryFile;
69
78
  lastSelectedVariant?: Variant;
70
- slots?: () => any;
79
+ /** The story's own slots. Any of the three can be absent: a story may define none. */
80
+ slots?: () => {
81
+ default?: any;
82
+ controls?: any;
83
+ source?: any;
84
+ };
71
85
  meta?: StoryMeta;
72
86
  }
73
87
  export interface VariantMeta extends CommonMeta {
@@ -78,10 +92,11 @@ export interface Variant {
78
92
  icon?: string | undefined;
79
93
  iconColor?: string | undefined;
80
94
  setupApp?: ((payload: any) => unknown) | undefined;
95
+ /** The variant's own slots. Any of the three can be absent: a variant may define none. */
81
96
  slots?: (() => {
82
- default: any;
83
- controls: any;
84
- source: any;
97
+ default?: any;
98
+ controls?: any;
99
+ source?: any;
85
100
  }) | undefined;
86
101
  state: any;
87
102
  source?: string | undefined;
@@ -168,6 +183,7 @@ export interface ServerStory {
168
183
  icon?: string | undefined;
169
184
  iconColor?: string | undefined;
170
185
  docsOnly?: boolean | undefined;
186
+ autoDocs?: boolean | AutoDocsSection[] | undefined;
171
187
  docsText?: string | undefined;
172
188
  meta?: StoryMeta | undefined;
173
189
  }
@@ -0,0 +1,37 @@
1
+ import type { PovesteConfig } from './types/config.js';
2
+ /**
3
+ * The virtual modules Poveste's client imports, by the ids core serves them
4
+ * under. A story test's Vite plugin serves the same ones, from this list.
5
+ */
6
+ export declare const VIRTUAL_IDS: {
7
+ readonly setup: "virtual:$poveste-setup";
8
+ readonly generatedGlobalSetup: "virtual:$poveste-generated-global-setup";
9
+ readonly config: "virtual:$poveste-config";
10
+ readonly markdownFiles: "virtual:$poveste-markdown-files";
11
+ readonly componentDocs: "virtual:$poveste-component-docs";
12
+ readonly supportPluginsClient: "virtual:$poveste-support-plugins-client";
13
+ };
14
+ /**
15
+ * The config as the browser gets it: the fields `@poveste/app` reads, and no
16
+ * others. The rest is build-side, and holds paths on the machine that built the
17
+ * book (`outDir`, each plugin's modules, the logo files), which a built book
18
+ * published in full (#1383). The logos reach the browser as `logos`, below.
19
+ */
20
+ export declare function clientConfig(config: Partial<PovesteConfig>): {
21
+ theme: {
22
+ title: string | undefined;
23
+ logoHref: string | undefined;
24
+ defaultColorScheme: "light" | "dark" | "auto" | undefined;
25
+ hideColorSchemeSwitch: boolean | undefined;
26
+ storeColorScheme: boolean | undefined;
27
+ darkClass: string | undefined;
28
+ };
29
+ routerMode: "history" | "hash" | undefined;
30
+ autoApplyContrastColor: boolean | undefined;
31
+ responsivePresets: import("./index.js").ResponsivePreset[] | undefined;
32
+ backgroundPresets: import("./index.js").BackgroundPreset[] | undefined;
33
+ defaultBackgroundColor: string | undefined;
34
+ preview: import("./index.js").PreviewConfig | undefined;
35
+ isolateStyles: boolean | undefined;
36
+ sandboxDarkClass: string | undefined;
37
+ };
@@ -0,0 +1,41 @@
1
+ /**
2
+ * The virtual modules Poveste's client imports, by the ids core serves them
3
+ * under. A story test's Vite plugin serves the same ones, from this list.
4
+ */
5
+ export const VIRTUAL_IDS = {
6
+ setup: 'virtual:$poveste-setup',
7
+ generatedGlobalSetup: 'virtual:$poveste-generated-global-setup',
8
+ config: 'virtual:$poveste-config',
9
+ markdownFiles: 'virtual:$poveste-markdown-files',
10
+ componentDocs: 'virtual:$poveste-component-docs',
11
+ supportPluginsClient: 'virtual:$poveste-support-plugins-client',
12
+ };
13
+ /**
14
+ * The config as the browser gets it: the fields `@poveste/app` reads, and no
15
+ * others. The rest is build-side, and holds paths on the machine that built the
16
+ * book (`outDir`, each plugin's modules, the logo files), which a built book
17
+ * published in full (#1383). The logos reach the browser as `logos`, below.
18
+ */
19
+ export function clientConfig(config) {
20
+ const theme = config.theme ?? {};
21
+ return {
22
+ theme: {
23
+ title: theme.title,
24
+ logoHref: theme.logoHref,
25
+ defaultColorScheme: theme.defaultColorScheme,
26
+ hideColorSchemeSwitch: theme.hideColorSchemeSwitch,
27
+ storeColorScheme: theme.storeColorScheme,
28
+ darkClass: theme.darkClass,
29
+ },
30
+ routerMode: config.routerMode,
31
+ autoApplyContrastColor: config.autoApplyContrastColor,
32
+ responsivePresets: config.responsivePresets,
33
+ backgroundPresets: config.backgroundPresets,
34
+ // eslint-disable-next-line ts/no-deprecated -- the app still reads it as a fallback
35
+ defaultBackgroundColor: config.defaultBackgroundColor,
36
+ preview: config.preview,
37
+ isolateStyles: config.isolateStyles,
38
+ // eslint-disable-next-line ts/no-deprecated -- the app still reads it as a fallback
39
+ sandboxDarkClass: config.sandboxDarkClass,
40
+ };
41
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@poveste/shared",
3
3
  "type": "module",
4
- "version": "0.19.1",
4
+ "version": "0.21.0",
5
5
  "description": "Shared utilities for Poveste",
6
6
  "author": {
7
7
  "name": "Sorin Gitlan",
@@ -39,20 +39,20 @@
39
39
  "vite": "^8.0.0"
40
40
  },
41
41
  "dependencies": {
42
- "@poveste/vendors": "^0.19.1",
42
+ "@poveste/vendors": "^0.21.0",
43
43
  "@types/fs-extra": "^11.0.4",
44
44
  "chokidar": "^5.0.0",
45
- "markdown-it": "^15.0.2",
45
+ "markdown-it": "^15.0.3",
46
46
  "pathe": "^2.0.3",
47
47
  "picocolors": "^1.1.1",
48
- "unhead": "^3.4.1"
48
+ "unhead": "^3.4.3"
49
49
  },
50
50
  "devDependencies": {
51
- "@types/node": "^26.6.3",
51
+ "@types/node": "^26.6.5",
52
52
  "typescript": "6.0.3",
53
- "vite": "^8.3.1",
54
- "vitest": "^5.0.2",
55
- "vue-router": "^5.3.1"
53
+ "vite": "^8.3.4",
54
+ "vitest": "^5.0.5",
55
+ "vue-router": "^5.4.0"
56
56
  },
57
57
  "scripts": {
58
58
  "build": "rimraf dist && tsc",