@poveste/shared 0.13.0 → 0.14.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.
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Escape a string so a `RegExp` built from it matches that string literally.
3
+ *
4
+ * `RegExp.escape` does exactly this and would be the obvious call, but it
5
+ * landed in Node 24 and every package here still accepts `^22.22.2` — so a
6
+ * contributor on the floor version gets `TypeError: RegExp.escape is not a
7
+ * function` rather than a diagnostic. (TypeScript 5.6 does not type it either,
8
+ * which is the half you notice first and the one that matters less.)
9
+ *
10
+ * It lives in `shared` because four call sites across three packages build a
11
+ * pattern from a name they did not choose, and one of them from the consumer's
12
+ * own project path.
13
+ */
14
+ export declare function escapeRegExp(value: string): string;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Escape a string so a `RegExp` built from it matches that string literally.
3
+ *
4
+ * `RegExp.escape` does exactly this and would be the obvious call, but it
5
+ * landed in Node 24 and every package here still accepts `^22.22.2` — so a
6
+ * contributor on the floor version gets `TypeError: RegExp.escape is not a
7
+ * function` rather than a diagnostic. (TypeScript 5.6 does not type it either,
8
+ * which is the half you notice first and the one that matters less.)
9
+ *
10
+ * It lives in `shared` because four call sites across three packages build a
11
+ * pattern from a name they did not choose, and one of them from the consumer's
12
+ * own project path.
13
+ */
14
+ export function escapeRegExp(value) {
15
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
16
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './codegen/index.js';
2
+ export * from './escape-regexp.js';
2
3
  export * from './setup.js';
3
4
  export * from './state.js';
4
5
  export * from './story-error.js';
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './codegen/index.js';
2
+ export * from './escape-regexp.js';
2
3
  export * from './setup.js';
3
4
  export * from './state.js';
4
5
  export * from './story-error.js';
@@ -23,8 +23,16 @@ export interface ClientCommandOptions extends CommonCommandOptions {
23
23
  export type ClientCommand = Command & ClientCommandOptions;
24
24
  export interface ClientCommandContext {
25
25
  route: RouteLocationNormalizedLoaded;
26
- currentStory: Story;
27
- currentVariant: Variant;
26
+ /**
27
+ * The story the route names, or undefined on any route that names none — the
28
+ * home page, or a story id that is not loaded. Declared non-optional here
29
+ * until #667: the app has always filled it from a `.find()`, so a plugin
30
+ * writing `ctx.currentStory.id` in `showIf` was reading a value the type
31
+ * promised and the app did not always supply.
32
+ */
33
+ currentStory: Story | undefined;
34
+ /** The selected variant, or undefined. Null in the tick between a story being routed to and its variant being chosen. */
35
+ currentVariant: Variant | undefined;
28
36
  }
29
37
  export interface PluginCommand<TParams = Record<string, any>> extends Command {
30
38
  serverAction?: (params: TParams) => unknown;
@@ -14,7 +14,7 @@ export type GrayColorKeys = ColorKeys | '750' | '850' | '950';
14
14
  export interface ResponsivePreset {
15
15
  label: string;
16
16
  width: number;
17
- height?: number;
17
+ height?: number | null;
18
18
  }
19
19
  export interface BackgroundPreset {
20
20
  label: string;
@@ -76,7 +76,7 @@ export interface PovesteConfig {
76
76
  groups?: TreeGroupConfig[];
77
77
  };
78
78
  /**
79
- * Customize the look of the histoire book.
79
+ * Customize the look of the book.
80
80
  */
81
81
  theme: {
82
82
  /**
@@ -7,6 +7,11 @@ 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
9
  import type { ServerStory, ServerStoryFile, ServerVariant } from './story.js';
10
+ /**
11
+ * A framework's collection strategy: how a story file written for that framework
12
+ * is imported and mounted. `@poveste/plugin-vue` and `@poveste/plugin-svelte`
13
+ * each expose one, and `supportMatch` in the config decides which files it claims.
14
+ */
10
15
  export interface SupportPlugin {
11
16
  id: string;
12
17
  moduleName: string;
@@ -14,13 +19,35 @@ export interface SupportPlugin {
14
19
  importStoriesPrepend?: string;
15
20
  importStoryComponent: (file: ServerStoryFile, index: number) => string;
16
21
  }
22
+ /**
23
+ * A {@link SupportPlugin} after Poveste has resolved it. Identical to the
24
+ * declared shape today; it exists so resolution can add fields without changing
25
+ * what a plugin author writes.
26
+ */
17
27
  export interface FinalSupportPlugin extends SupportPlugin {
18
28
  }
29
+ /**
30
+ * Loads a module through Vite, so a plugin can read a user's `.ts` or `.vue`
31
+ * file the way the collector does rather than reaching for `import`.
32
+ *
33
+ * `loadModule` resolves to `undefined` on an error it has already logged, so a
34
+ * caller that needs to fail has to check the result. `clearCache` invalidates
35
+ * Vite's module graph as well as the runner's, which is what makes a re-read
36
+ * after a file change return the new contents.
37
+ */
19
38
  export interface ModuleLoader {
20
39
  clearCache: () => void;
21
40
  loadModule: (file: string) => Promise<any>;
22
41
  destroy: () => void;
23
42
  }
43
+ /**
44
+ * What every plugin hook receives. `colors`, `path` and `fs` are Poveste's own
45
+ * picocolors, pathe and fs-extra, handed over so a plugin can use them without
46
+ * adding a second copy to the tree.
47
+ *
48
+ * Prefer `log`/`warn`/`error` over `console`: they prefix the plugin's name, so
49
+ * a line in a busy build says what printed it.
50
+ */
24
51
  export interface PluginApiBase {
25
52
  colors: typeof pc;
26
53
  path: typeof path;
@@ -34,17 +61,42 @@ export interface PluginApiBase {
34
61
  addStoryFile: (file: string) => void;
35
62
  getConfig: () => PovesteConfig;
36
63
  }
64
+ /**
65
+ * {@link PluginApiBase} plus the file watcher, passed to `onDev`. Only the dev
66
+ * server has one — a build never watches.
67
+ */
37
68
  export interface PluginApiDev extends PluginApiBase {
38
69
  watcher: typeof chokidar;
39
70
  }
71
+ /**
72
+ * Mutates the Vite config Poveste is about to build with. Registered through
73
+ * `changeViteConfig`, and run once, before the build starts.
74
+ */
40
75
  export type ChangeViteConfigCallback = (config: ViteInlineConfig) => Awaitable<void>;
76
+ /**
77
+ * Runs after a build **succeeds**. A build that fails never reaches it, which is
78
+ * why anything that must be released belongs in `onCleanup` instead (#434).
79
+ */
41
80
  export type BuildEndCallback = () => Awaitable<void>;
81
+ /**
82
+ * Runs once per variant **after** the build has finished, against a preview
83
+ * server started for the purpose, with the URL that variant is served from.
84
+ * This is the hook a screenshot or visual-diff plugin uses.
85
+ *
86
+ * Registering one is what makes the build start that server at all, so a plugin
87
+ * that registers unconditionally adds a preview boot to every build.
88
+ */
42
89
  export type PreviewStoryCallback = (payload: {
43
90
  file: string;
44
91
  story: ServerStory;
45
92
  variant: ServerVariant;
46
93
  url: string;
47
94
  }) => Awaitable<void>;
95
+ /**
96
+ * {@link PluginApiBase} plus the build hooks, passed to `onBuild`. The three
97
+ * arrays are the registered callbacks; the three functions are how a plugin adds
98
+ * to them.
99
+ */
48
100
  export interface PluginApiBuild extends PluginApiBase {
49
101
  changeViteConfigCallbacks: ChangeViteConfigCallback[];
50
102
  buildEndCallbacks: BuildEndCallback[];
@@ -53,17 +105,29 @@ export interface PluginApiBuild extends PluginApiBase {
53
105
  onBuildEnd: (cb: BuildEndCallback) => void;
54
106
  onPreviewStory: (cb: PreviewStoryCallback) => void;
55
107
  }
108
+ /**
109
+ * {@link PluginApiBase} plus the event that triggered the hook, passed to
110
+ * `onDevEvent`. `payload` is whatever the client sent to `sendEvent`, unvalidated.
111
+ */
56
112
  export interface PluginApiDevEvent extends PluginApiBase {
57
113
  event: string;
58
114
  payload: any;
59
115
  }
116
+ /**
117
+ * A Poveste plugin: a name and whichever hooks it needs. Listed in `plugins` in
118
+ * `poveste.config.ts`, and every hook is optional.
119
+ *
120
+ * The hooks below run in the order they are declared — `defaultConfig`, `config`
121
+ * and `configResolved` while the config settles, then `onDev`, `onBuild` or
122
+ * `onPreview` depending on the command.
123
+ */
60
124
  export interface Plugin {
61
125
  /**
62
126
  * Name of the plugin
63
127
  */
64
128
  name: string;
65
129
  /**
66
- * Modify histoire default config. The hook can either mutate the passed config or
130
+ * Modify Poveste's default config. The hook can either mutate the passed config or
67
131
  * return a partial config object that will be deeply merged into the existing
68
132
  * config. User config will have higher priority than default config.
69
133
  *
@@ -72,7 +136,7 @@ export interface Plugin {
72
136
  */
73
137
  defaultConfig?: (defaultConfig: PovesteConfig, mode: ConfigMode) => Partial<PovesteConfig> | null | void | Promise<Partial<PovesteConfig> | null | void>;
74
138
  /**
75
- * Modify histoire config. The hook can either mutate the passed config or
139
+ * Modify the Poveste config. The hook can either mutate the passed config or
76
140
  * return a partial config object that will be deeply merged into the existing
77
141
  * config.
78
142
  *
@@ -81,7 +145,7 @@ export interface Plugin {
81
145
  */
82
146
  config?: (config: PovesteConfig, mode: ConfigMode) => Partial<PovesteConfig> | null | void | Promise<Partial<PovesteConfig> | null | void>;
83
147
  /**
84
- * Use this hook to read and store the final resolved histoire config.
148
+ * Use this hook to read and store the final resolved Poveste config.
85
149
  */
86
150
  configResolved?: (config: PovesteConfig) => Awaitable<void>;
87
151
  /**
@@ -91,8 +155,7 @@ export interface Plugin {
91
155
  onDev?: (api: PluginApiDev, onCleanup: (cb: () => Awaitable<void>) => void) => Awaitable<void>;
92
156
  /**
93
157
  * Use this hook to do processing during production build.
94
- */
95
- /**
158
+ *
96
159
  * `onCleanup` runs however the build ends, including when it fails. Anything a
97
160
  * plugin opened belongs there rather than in `onBuildEnd`, which only runs when
98
161
  * the build succeeded — a plugin holding a framework instance or a watcher kept
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@poveste/shared",
3
3
  "type": "module",
4
- "version": "0.13.0",
4
+ "version": "0.14.0",
5
5
  "description": "Shared utilities for Poveste",
6
6
  "author": {
7
7
  "name": "Sorin Gitlan",
@@ -39,7 +39,7 @@
39
39
  "vite": "^8.0.0"
40
40
  },
41
41
  "dependencies": {
42
- "@poveste/vendors": "^0.13.0",
42
+ "@poveste/vendors": "^0.14.0",
43
43
  "@types/fs-extra": "^11.0.4",
44
44
  "@types/markdown-it": "^14.1.2",
45
45
  "chokidar": "^4.0.1",
@@ -50,7 +50,7 @@
50
50
  "devDependencies": {
51
51
  "typescript": "5.6.3",
52
52
  "vite": "^8.2.0",
53
- "vitest": "^4.1.10"
53
+ "vitest": "^5.0.0"
54
54
  },
55
55
  "scripts": {
56
56
  "build": "rimraf dist && tsc",