storybook-addon-dependency-previews 0.5.4 → 0.6.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 +19 -5
- package/dist/addon/vitePlugin.cjs +19 -3
- package/dist/addon/vitePlugin.cjs.map +1 -1
- package/dist/addon/vitePlugin.d.cts +3 -5
- package/dist/addon/vitePlugin.d.mts +3 -5
- package/dist/addon/vitePlugin.mjs +19 -3
- package/dist/addon/vitePlugin.mjs.map +1 -1
- package/dist/cli/sb-deps.cjs +112 -1
- package/dist/cli/sb-deps.cjs.map +1 -1
- package/dist/cli/sb-deps.mjs +112 -1
- package/dist/cli/sb-deps.mjs.map +1 -1
- package/dist/cli/setup/detect.cjs +50 -17
- package/dist/cli/setup/detect.cjs.map +1 -1
- package/dist/cli/setup/detect.d.cts +1 -1
- package/dist/cli/setup/detect.d.mts +1 -1
- package/dist/cli/setup/detect.mjs +50 -17
- package/dist/cli/setup/detect.mjs.map +1 -1
- package/dist/cli/setup/index.cjs +7 -2
- package/dist/cli/setup/index.cjs.map +1 -1
- package/dist/cli/setup/index.mjs +7 -2
- package/dist/cli/setup/index.mjs.map +1 -1
- package/dist/cli/setup/patchers/preview.cjs +5 -3
- package/dist/cli/setup/patchers/preview.cjs.map +1 -1
- package/dist/cli/setup/patchers/preview.mjs +5 -3
- package/dist/cli/setup/patchers/preview.mjs.map +1 -1
- package/dist/cli/setup/util.cjs +57 -9
- package/dist/cli/setup/util.cjs.map +1 -1
- package/dist/cli/setup/util.d.cts +30 -7
- package/dist/cli/setup/util.d.mts +30 -7
- package/dist/cli/setup/util.mjs +57 -9
- package/dist/cli/setup/util.mjs.map +1 -1
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.cts +17 -1
- package/dist/config.d.mts +17 -1
- package/dist/config.mjs.map +1 -1
- package/package.json +122 -122
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
A plugin for [Storybook](https://storybook.js.org/) that shows the full dependency tree in both directions (built with and used by) the components in your application.
|
|
10
10
|
|
|
11
|
-
Currently works with **React**, **Svelte**, **Angular**, and **Next.js**. The automated `sb-deps setup` wizard handles Vite-based projects (React, Svelte) end-to-end. Webpack-based projects (Angular, Next.js) need a one-time manual setup — see the [manual-setup-webpack guide](https://github.com/Dan503/storybook-addon-dependency-previews/blob/main/storybook-addon-package/docs/manual-setup-webpack.md) below.
|
|
11
|
+
Currently works with **React**, **Svelte**, **Vue 3**, **Angular**, and **Next.js**. The automated `sb-deps setup` wizard handles Vite-based projects (React, Svelte, Vue 3) end-to-end. Webpack-based projects (Angular, Next.js) need a one-time manual setup — see the [manual-setup-webpack guide](https://github.com/Dan503/storybook-addon-dependency-previews/blob/main/storybook-addon-package/docs/manual-setup-webpack.md) below.
|
|
12
12
|
|
|
13
13
|
This is what you will see in Storybook after Dependency Previews have been installed and configured:
|
|
14
14
|
|
|
@@ -28,10 +28,18 @@ The below image demonstrates what you will see when you open up some of the depe
|
|
|
28
28
|
|
|
29
29
|
#### Svelte demos
|
|
30
30
|
|
|
31
|
-
- [Svelte Storybook demo site](https://dependency-previews-storybook-svelte.netlify.app/)
|
|
31
|
+
- [Svelte Storybook demo site](https://dependency-previews-storybook-svelte.netlify.app/?path=/docs/04-templates-home-template--docs)
|
|
32
32
|
- [Svelte rendered example website](https://dependency-previews-demo-site-svelte.netlify.app/)
|
|
33
33
|
- [Svelte demo source code](https://github.com/Dan503/storybook-addon-dependency-previews/tree/main/example-site/svelte)
|
|
34
34
|
|
|
35
|
+
#### Vue demos
|
|
36
|
+
|
|
37
|
+
Vue version built for Vue 3.
|
|
38
|
+
|
|
39
|
+
- [Vue Storybook demo site](https://dependency-previews-storybook-vue.netlify.app/?path=/docs/04-templates-home-template--docs)
|
|
40
|
+
- [Vue rendered example website](https://dependency-previews-demo-site-vue.netlify.app/)
|
|
41
|
+
- [Vue demo source code](https://github.com/Dan503/storybook-addon-dependency-previews/tree/main/example-site/vue)
|
|
42
|
+
|
|
35
43
|
#### Angular demos
|
|
36
44
|
|
|
37
45
|
- [Angular Storybook demo site](https://dependency-previews-storybook-angular.netlify.app/?path=/docs/04-templates-home-template--docs)
|
|
@@ -42,7 +50,7 @@ The below image demonstrates what you will see when you open up some of the depe
|
|
|
42
50
|
|
|
43
51
|
## Installation guide
|
|
44
52
|
|
|
45
|
-
### Quick start (React and
|
|
53
|
+
### Quick start (React, Svelte, and Vue 3)
|
|
46
54
|
|
|
47
55
|
After running `npx storybook@latest init` in your project, run the setup wizard:
|
|
48
56
|
|
|
@@ -84,9 +92,9 @@ When it finishes, run `npm run sb` (or your package manager's equivalent) to sta
|
|
|
84
92
|
|
|
85
93
|
### Manual setup
|
|
86
94
|
|
|
87
|
-
The wizard supports React (`@storybook/react-vite`)
|
|
95
|
+
The wizard supports React (`@storybook/react-vite`), Svelte (`@storybook/sveltekit`, `@storybook/svelte-vite`), and Vue 3 (`@storybook/vue3-vite`) — all Vite-based. **Angular (`@storybook/angular`) and Next.js (`@storybook/nextjs`) projects are both webpack-based and require manual setup** — the wizard's preview-patcher relies on Vite's `import.meta.glob`, which webpack doesn't expose. Follow the matching guide below:
|
|
88
96
|
|
|
89
|
-
- [Manual setup — Vite (React, Svelte)](https://github.com/Dan503/storybook-addon-dependency-previews/blob/main/storybook-addon-package/docs/manual-setup-vite.md)
|
|
97
|
+
- [Manual setup — Vite (React, Svelte, Vue 3)](https://github.com/Dan503/storybook-addon-dependency-previews/blob/main/storybook-addon-package/docs/manual-setup-vite.md)
|
|
90
98
|
- [Manual setup — webpack (`@storybook/angular`, `@storybook/nextjs`)](https://github.com/Dan503/storybook-addon-dependency-previews/blob/main/storybook-addon-package/docs/manual-setup-webpack.md)
|
|
91
99
|
|
|
92
100
|
## Configuration file (optional)
|
|
@@ -176,6 +184,12 @@ export function ${componentName}({}: ${propsName}) {
|
|
|
176
184
|
/** Customize the generated .stories.svelte file */
|
|
177
185
|
story: ({ componentName, title, tags }) => '...',
|
|
178
186
|
},
|
|
187
|
+
vue: {
|
|
188
|
+
/** Customize the generated .vue component file */
|
|
189
|
+
component: ({ componentName }) => '...',
|
|
190
|
+
/** Customize the generated .stories.ts file */
|
|
191
|
+
story: ({ componentName, title, tags }) => '...',
|
|
192
|
+
},
|
|
179
193
|
angular: {
|
|
180
194
|
/** Customize the generated .component.ts file */
|
|
181
195
|
component: ({
|
|
@@ -5,6 +5,11 @@ let node_path = require("node:path");
|
|
|
5
5
|
node_path = require_rolldown_runtime.__toESM(node_path);
|
|
6
6
|
|
|
7
7
|
//#region src/addon/vitePlugin.ts
|
|
8
|
+
const jsonUrlPath = "/dependency-previews.json";
|
|
9
|
+
function readDependencyPreviewsJson() {
|
|
10
|
+
const jsonPath = (0, node_path.resolve)(process.cwd(), ".storybook/dependency-previews.json");
|
|
11
|
+
return (0, node_fs.existsSync)(jsonPath) ? (0, node_fs.readFileSync)(jsonPath, "utf8") : "{}";
|
|
12
|
+
}
|
|
8
13
|
function sbDepsVitePlugin() {
|
|
9
14
|
const virtId = "virtual:dependency-previews-json";
|
|
10
15
|
const resolved = "\0" + virtId;
|
|
@@ -15,9 +20,20 @@ function sbDepsVitePlugin() {
|
|
|
15
20
|
},
|
|
16
21
|
load(id) {
|
|
17
22
|
if (id !== resolved) return null;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
return `export default ${readDependencyPreviewsJson()};`;
|
|
24
|
+
},
|
|
25
|
+
configureServer(server) {
|
|
26
|
+
server.middlewares.use(jsonUrlPath, (_req, res) => {
|
|
27
|
+
res.setHeader("Content-Type", "application/json");
|
|
28
|
+
res.end(readDependencyPreviewsJson());
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
generateBundle() {
|
|
32
|
+
this.emitFile({
|
|
33
|
+
type: "asset",
|
|
34
|
+
fileName: "dependency-previews.json",
|
|
35
|
+
source: readDependencyPreviewsJson()
|
|
36
|
+
});
|
|
21
37
|
}
|
|
22
38
|
};
|
|
23
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitePlugin.cjs","names":[],"sources":["../../src/addon/vitePlugin.ts"],"sourcesContent":["import { readFileSync, existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nexport function sbDepsVitePlugin() {\n\tconst virtId = 'virtual:dependency-previews-json'\n\tconst resolved = '\\0' + virtId\n\treturn {\n\t\tname: 'sb-deps',\n\t\tresolveId(id: string) {\n\t\t\treturn id === virtId ? resolved : null\n\t\t},\n\t\tload(id: string) {\n\t\t\tif (id !== resolved) return null\n\t\t\
|
|
1
|
+
{"version":3,"file":"vitePlugin.cjs","names":[],"sources":["../../src/addon/vitePlugin.ts"],"sourcesContent":["import { readFileSync, existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport type { Plugin } from 'vite'\n\nconst jsonUrlPath = '/dependency-previews.json'\n\nfunction readDependencyPreviewsJson(): string {\n\tconst jsonPath = resolve(\n\t\tprocess.cwd(),\n\t\t'.storybook/dependency-previews.json',\n\t)\n\treturn existsSync(jsonPath) ? readFileSync(jsonPath, 'utf8') : '{}'\n}\n\nexport function sbDepsVitePlugin(): Plugin {\n\tconst virtId = 'virtual:dependency-previews-json'\n\tconst resolved = '\\0' + virtId\n\treturn {\n\t\tname: 'sb-deps',\n\t\tresolveId(id: string) {\n\t\t\treturn id === virtId ? resolved : null\n\t\t},\n\t\tload(id: string) {\n\t\t\tif (id !== resolved) return null\n\t\t\treturn `export default ${readDependencyPreviewsJson()};`\n\t\t},\n\t\t// The manager-side panel (GraphView) fetches the JSON over HTTP — it\n\t\t// can't import the virtual module above because the manager bundle is\n\t\t// prebuilt by Storybook, not bundled by the project's Vite config.\n\t\tconfigureServer(server) {\n\t\t\tserver.middlewares.use(jsonUrlPath, (_req, res) => {\n\t\t\t\t// Read per-request so `sb-deps --watch` regenerations are served\n\t\t\t\t// without restarting Storybook.\n\t\t\t\tres.setHeader('Content-Type', 'application/json')\n\t\t\t\tres.end(readDependencyPreviewsJson())\n\t\t\t})\n\t\t},\n\t\t// Emit the JSON into `storybook build` output so the panel's fetch also\n\t\t// works in deployed static Storybooks, mirroring the dev middleware.\n\t\tgenerateBundle() {\n\t\t\tthis.emitFile({\n\t\t\t\ttype: 'asset',\n\t\t\t\tfileName: 'dependency-previews.json',\n\t\t\t\tsource: readDependencyPreviewsJson(),\n\t\t\t})\n\t\t},\n\t}\n}\n"],"mappings":";;;;;;;AAIA,MAAM,cAAc;AAEpB,SAAS,6BAAqC;CAC7C,MAAM,kCACL,QAAQ,KAAK,EACb,sCACA;AACD,gCAAkB,SAAS,6BAAgB,UAAU,OAAO,GAAG;;AAGhE,SAAgB,mBAA2B;CAC1C,MAAM,SAAS;CACf,MAAM,WAAW,OAAO;AACxB,QAAO;EACN,MAAM;EACN,UAAU,IAAY;AACrB,UAAO,OAAO,SAAS,WAAW;;EAEnC,KAAK,IAAY;AAChB,OAAI,OAAO,SAAU,QAAO;AAC5B,UAAO,kBAAkB,4BAA4B,CAAC;;EAKvD,gBAAgB,QAAQ;AACvB,UAAO,YAAY,IAAI,cAAc,MAAM,QAAQ;AAGlD,QAAI,UAAU,gBAAgB,mBAAmB;AACjD,QAAI,IAAI,4BAA4B,CAAC;KACpC;;EAIH,iBAAiB;AAChB,QAAK,SAAS;IACb,MAAM;IACN,UAAU;IACV,QAAQ,4BAA4B;IACpC,CAAC;;EAEH"}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
+
import { Plugin } from "vite";
|
|
2
|
+
|
|
1
3
|
//#region src/addon/vitePlugin.d.ts
|
|
2
|
-
declare function sbDepsVitePlugin():
|
|
3
|
-
name: string;
|
|
4
|
-
resolveId(id: string): string | null;
|
|
5
|
-
load(id: string): string | null;
|
|
6
|
-
};
|
|
4
|
+
declare function sbDepsVitePlugin(): Plugin;
|
|
7
5
|
//#endregion
|
|
8
6
|
export { sbDepsVitePlugin };
|
|
9
7
|
//# sourceMappingURL=vitePlugin.d.cts.map
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
+
import { Plugin } from "vite";
|
|
2
|
+
|
|
1
3
|
//#region src/addon/vitePlugin.d.ts
|
|
2
|
-
declare function sbDepsVitePlugin():
|
|
3
|
-
name: string;
|
|
4
|
-
resolveId(id: string): string | null;
|
|
5
|
-
load(id: string): string | null;
|
|
6
|
-
};
|
|
4
|
+
declare function sbDepsVitePlugin(): Plugin;
|
|
7
5
|
//#endregion
|
|
8
6
|
export { sbDepsVitePlugin };
|
|
9
7
|
//# sourceMappingURL=vitePlugin.d.mts.map
|
|
@@ -2,6 +2,11 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
|
|
4
4
|
//#region src/addon/vitePlugin.ts
|
|
5
|
+
const jsonUrlPath = "/dependency-previews.json";
|
|
6
|
+
function readDependencyPreviewsJson() {
|
|
7
|
+
const jsonPath = resolve(process.cwd(), ".storybook/dependency-previews.json");
|
|
8
|
+
return existsSync(jsonPath) ? readFileSync(jsonPath, "utf8") : "{}";
|
|
9
|
+
}
|
|
5
10
|
function sbDepsVitePlugin() {
|
|
6
11
|
const virtId = "virtual:dependency-previews-json";
|
|
7
12
|
const resolved = "\0" + virtId;
|
|
@@ -12,9 +17,20 @@ function sbDepsVitePlugin() {
|
|
|
12
17
|
},
|
|
13
18
|
load(id) {
|
|
14
19
|
if (id !== resolved) return null;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
return `export default ${readDependencyPreviewsJson()};`;
|
|
21
|
+
},
|
|
22
|
+
configureServer(server) {
|
|
23
|
+
server.middlewares.use(jsonUrlPath, (_req, res) => {
|
|
24
|
+
res.setHeader("Content-Type", "application/json");
|
|
25
|
+
res.end(readDependencyPreviewsJson());
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
generateBundle() {
|
|
29
|
+
this.emitFile({
|
|
30
|
+
type: "asset",
|
|
31
|
+
fileName: "dependency-previews.json",
|
|
32
|
+
source: readDependencyPreviewsJson()
|
|
33
|
+
});
|
|
18
34
|
}
|
|
19
35
|
};
|
|
20
36
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitePlugin.mjs","names":[],"sources":["../../src/addon/vitePlugin.ts"],"sourcesContent":["import { readFileSync, existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nexport function sbDepsVitePlugin() {\n\tconst virtId = 'virtual:dependency-previews-json'\n\tconst resolved = '\\0' + virtId\n\treturn {\n\t\tname: 'sb-deps',\n\t\tresolveId(id: string) {\n\t\t\treturn id === virtId ? resolved : null\n\t\t},\n\t\tload(id: string) {\n\t\t\tif (id !== resolved) return null\n\t\t\
|
|
1
|
+
{"version":3,"file":"vitePlugin.mjs","names":[],"sources":["../../src/addon/vitePlugin.ts"],"sourcesContent":["import { readFileSync, existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport type { Plugin } from 'vite'\n\nconst jsonUrlPath = '/dependency-previews.json'\n\nfunction readDependencyPreviewsJson(): string {\n\tconst jsonPath = resolve(\n\t\tprocess.cwd(),\n\t\t'.storybook/dependency-previews.json',\n\t)\n\treturn existsSync(jsonPath) ? readFileSync(jsonPath, 'utf8') : '{}'\n}\n\nexport function sbDepsVitePlugin(): Plugin {\n\tconst virtId = 'virtual:dependency-previews-json'\n\tconst resolved = '\\0' + virtId\n\treturn {\n\t\tname: 'sb-deps',\n\t\tresolveId(id: string) {\n\t\t\treturn id === virtId ? resolved : null\n\t\t},\n\t\tload(id: string) {\n\t\t\tif (id !== resolved) return null\n\t\t\treturn `export default ${readDependencyPreviewsJson()};`\n\t\t},\n\t\t// The manager-side panel (GraphView) fetches the JSON over HTTP — it\n\t\t// can't import the virtual module above because the manager bundle is\n\t\t// prebuilt by Storybook, not bundled by the project's Vite config.\n\t\tconfigureServer(server) {\n\t\t\tserver.middlewares.use(jsonUrlPath, (_req, res) => {\n\t\t\t\t// Read per-request so `sb-deps --watch` regenerations are served\n\t\t\t\t// without restarting Storybook.\n\t\t\t\tres.setHeader('Content-Type', 'application/json')\n\t\t\t\tres.end(readDependencyPreviewsJson())\n\t\t\t})\n\t\t},\n\t\t// Emit the JSON into `storybook build` output so the panel's fetch also\n\t\t// works in deployed static Storybooks, mirroring the dev middleware.\n\t\tgenerateBundle() {\n\t\t\tthis.emitFile({\n\t\t\t\ttype: 'asset',\n\t\t\t\tfileName: 'dependency-previews.json',\n\t\t\t\tsource: readDependencyPreviewsJson(),\n\t\t\t})\n\t\t},\n\t}\n}\n"],"mappings":";;;;AAIA,MAAM,cAAc;AAEpB,SAAS,6BAAqC;CAC7C,MAAM,WAAW,QAChB,QAAQ,KAAK,EACb,sCACA;AACD,QAAO,WAAW,SAAS,GAAG,aAAa,UAAU,OAAO,GAAG;;AAGhE,SAAgB,mBAA2B;CAC1C,MAAM,SAAS;CACf,MAAM,WAAW,OAAO;AACxB,QAAO;EACN,MAAM;EACN,UAAU,IAAY;AACrB,UAAO,OAAO,SAAS,WAAW;;EAEnC,KAAK,IAAY;AAChB,OAAI,OAAO,SAAU,QAAO;AAC5B,UAAO,kBAAkB,4BAA4B,CAAC;;EAKvD,gBAAgB,QAAQ;AACvB,UAAO,YAAY,IAAI,cAAc,MAAM,QAAQ;AAGlD,QAAI,UAAU,gBAAgB,mBAAmB;AACjD,QAAI,IAAI,4BAA4B,CAAC;KACpC;;EAIH,iBAAiB;AAChB,QAAK,SAAS;IACb,MAAM;IACN,UAAU;IACV,QAAQ,4BAA4B;IACpC,CAAC;;EAEH"}
|
package/dist/cli/sb-deps.cjs
CHANGED
|
@@ -227,6 +227,10 @@ function isDecoratorSvelte(absPath) {
|
|
|
227
227
|
const norm = absPath.replace(/\\/g, "/");
|
|
228
228
|
return srcSubpathRegex("\\.decorator\\.svelte$").test(norm);
|
|
229
229
|
}
|
|
230
|
+
function isComponentsVue(absPath) {
|
|
231
|
+
const norm = absPath.replace(/\\/g, "/");
|
|
232
|
+
return srcSubpathRegex("\\.vue$").test(norm) && !STORY_FILE_REGEX.test(norm);
|
|
233
|
+
}
|
|
230
234
|
function isComponentsAngularTs(absPath) {
|
|
231
235
|
const norm = absPath.replace(/\\/g, "/");
|
|
232
236
|
return srcSubpathRegex("\\.component\\.ts$").test(norm);
|
|
@@ -241,6 +245,9 @@ function componentBaseFromComponent(absCompPath) {
|
|
|
241
245
|
function componentBaseFromSvelteComponent(absCompPath) {
|
|
242
246
|
return (0, node_path.basename)(absCompPath, ".svelte");
|
|
243
247
|
}
|
|
248
|
+
function componentBaseFromVueComponent(absCompPath) {
|
|
249
|
+
return (0, node_path.basename)(absCompPath, ".vue");
|
|
250
|
+
}
|
|
244
251
|
function componentBaseFromAngularComponent(absCompPath) {
|
|
245
252
|
return (0, node_path.basename)(absCompPath).replace(/\.component\.(ts|html)$/i, "");
|
|
246
253
|
}
|
|
@@ -278,6 +285,11 @@ function storyPathForSvelteComponent(absCompPath) {
|
|
|
278
285
|
const base = componentBaseFromSvelteComponent(absCompPath);
|
|
279
286
|
return (0, node_path.join)(dir, `${base}.stories.svelte`);
|
|
280
287
|
}
|
|
288
|
+
function storyPathForVueComponent(absCompPath) {
|
|
289
|
+
const dir = (0, node_path.dirname)(absCompPath);
|
|
290
|
+
const base = componentBaseFromVueComponent(absCompPath);
|
|
291
|
+
return (0, node_path.join)(dir, `${base}.stories.ts`);
|
|
292
|
+
}
|
|
281
293
|
function makeTitleFromComponent(absCompPath) {
|
|
282
294
|
const srcRoot = (0, node_path.join)(projectRoot, SRC_DIR) + node_path.sep;
|
|
283
295
|
const normAbs = absCompPath.replace(/\\/g, "/");
|
|
@@ -464,6 +476,91 @@ function ensureStoryForSvelteComponent(absCompPath) {
|
|
|
464
476
|
if ((0, node_fs.existsSync)(sPath)) return null;
|
|
465
477
|
return scaffoldStoryForSvelteComponent(absCompPath);
|
|
466
478
|
}
|
|
479
|
+
function scaffoldVueComponent(absCompPath) {
|
|
480
|
+
const base = componentBaseFromVueComponent(absCompPath);
|
|
481
|
+
const componentName = toPascalCase(base);
|
|
482
|
+
const tpl = SCAFFOLD_CONFIG?.vue?.component?.({ componentName }) ?? `<script setup lang="ts">
|
|
483
|
+
export interface PropsFor${componentName} {
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
const { } = defineProps<PropsFor${componentName}>()
|
|
487
|
+
<\/script>
|
|
488
|
+
|
|
489
|
+
<template>
|
|
490
|
+
<div class="${componentName}">
|
|
491
|
+
<slot />
|
|
492
|
+
</div>
|
|
493
|
+
</template>
|
|
494
|
+
`;
|
|
495
|
+
(0, node_fs.writeFileSync)(absCompPath, tpl, "utf8");
|
|
496
|
+
info(`scaffolded vue component → ${rel(absCompPath)}`);
|
|
497
|
+
}
|
|
498
|
+
function makeTitleFromVueComponent(absCompPath) {
|
|
499
|
+
const srcRoot = (0, node_path.join)(projectRoot, SRC_DIR) + node_path.sep;
|
|
500
|
+
const normAbs = absCompPath.replace(/\\/g, "/");
|
|
501
|
+
const relFromSrc = normAbs.startsWith(srcRoot.replace(/\\/g, "/")) ? normAbs.slice(srcRoot.length) : absCompPath.replace(projectRoot + node_path.sep, "").replace(/\\/g, "/");
|
|
502
|
+
const dir = node_path.posix.dirname(relFromSrc);
|
|
503
|
+
let segments = dir.split("/").filter(Boolean);
|
|
504
|
+
if (segments[0] && /^components?$/i.test(segments[0])) segments = segments.slice(1);
|
|
505
|
+
const titledFolders = segments.map((s) => toTitleCase(toWords(s)));
|
|
506
|
+
const compName = componentBaseFromVueComponent(absCompPath);
|
|
507
|
+
const compTitle = toTitleCase(toWords(compName));
|
|
508
|
+
const fullStoryPath = [...titledFolders, compTitle].filter(Boolean);
|
|
509
|
+
const dedupedStoryPath = [...new Set(fullStoryPath)];
|
|
510
|
+
return dedupedStoryPath.join(" / ");
|
|
511
|
+
}
|
|
512
|
+
function scaffoldStoryForVueComponent(absCompPath) {
|
|
513
|
+
const base = componentBaseFromVueComponent(absCompPath);
|
|
514
|
+
const componentName = toPascalCase(base);
|
|
515
|
+
const title = makeTitleFromVueComponent(absCompPath);
|
|
516
|
+
const atomic = detectAtomicTag(absCompPath);
|
|
517
|
+
const tags = ["autodocs"];
|
|
518
|
+
if (atomic) tags.push(atomic);
|
|
519
|
+
const storyTpl = SCAFFOLD_CONFIG?.vue?.story?.({
|
|
520
|
+
componentName,
|
|
521
|
+
title,
|
|
522
|
+
tags
|
|
523
|
+
}) ?? `import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
|
524
|
+
import type { StoryParameters } from 'storybook-addon-dependency-previews'
|
|
525
|
+
import ${componentName}, { type PropsFor${componentName} } from './${componentName}.vue'
|
|
526
|
+
|
|
527
|
+
const meta: Meta<typeof ${componentName}> = {
|
|
528
|
+
title: '${title}',
|
|
529
|
+
component: ${componentName},
|
|
530
|
+
tags: ${JSON.stringify(tags)},
|
|
531
|
+
parameters: {
|
|
532
|
+
layout: 'padded',
|
|
533
|
+
} satisfies StoryParameters,
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
export default meta
|
|
537
|
+
|
|
538
|
+
type Story = StoryObj<typeof meta>
|
|
539
|
+
|
|
540
|
+
export const Primary: Story = {
|
|
541
|
+
args: {} satisfies PropsFor${componentName},
|
|
542
|
+
render: (args) => ({
|
|
543
|
+
components: { ${componentName} },
|
|
544
|
+
setup() {
|
|
545
|
+
return { args }
|
|
546
|
+
},
|
|
547
|
+
template: \`
|
|
548
|
+
<${componentName} v-bind="args">
|
|
549
|
+
${componentName}
|
|
550
|
+
</${componentName}>\`,
|
|
551
|
+
}),
|
|
552
|
+
}
|
|
553
|
+
`;
|
|
554
|
+
const storyPath = storyPathForVueComponent(absCompPath);
|
|
555
|
+
(0, node_fs.writeFileSync)(storyPath, storyTpl, "utf8");
|
|
556
|
+
info(`scaffolded vue story → ${rel(storyPath)}`);
|
|
557
|
+
return storyPath;
|
|
558
|
+
}
|
|
559
|
+
function ensureStoryForVueComponent(absCompPath) {
|
|
560
|
+
const sPath = storyPathForVueComponent(absCompPath);
|
|
561
|
+
if ((0, node_fs.existsSync)(sPath)) return null;
|
|
562
|
+
return scaffoldStoryForVueComponent(absCompPath);
|
|
563
|
+
}
|
|
467
564
|
function storyPathForAngularComponent(absCompPath) {
|
|
468
565
|
const dir = (0, node_path.dirname)(absCompPath);
|
|
469
566
|
const base = componentBaseFromAngularComponent(absCompPath);
|
|
@@ -671,7 +768,7 @@ function startWatcher() {
|
|
|
671
768
|
const includeGlobs = [
|
|
672
769
|
"**/*.stories.{ts,tsx,js,jsx,mdx,svelte}",
|
|
673
770
|
"**/*.story.{ts,tsx,js,jsx,mdx,svelte}",
|
|
674
|
-
`${srcPrefix}**/*.{ts,tsx,js,jsx,svelte}`,
|
|
771
|
+
`${srcPrefix}**/*.{ts,tsx,js,jsx,svelte,vue}`,
|
|
675
772
|
`${srcPrefix}**/*.component.html`,
|
|
676
773
|
"depcruise.config.cjs",
|
|
677
774
|
".dependency-cruiser.{js,cjs}"
|
|
@@ -720,6 +817,10 @@ function startWatcher() {
|
|
|
720
817
|
await handleSvelteComponentCreation(abs, relPath);
|
|
721
818
|
continue;
|
|
722
819
|
}
|
|
820
|
+
if (isComponentsVue(abs) && ev.type === "create") {
|
|
821
|
+
await handleVueComponentCreation(abs, relPath);
|
|
822
|
+
continue;
|
|
823
|
+
}
|
|
723
824
|
if (isComponentsAngularTs(abs) && ev.type === "create") {
|
|
724
825
|
await handleAngularComponentCreation(abs, relPath, "internal");
|
|
725
826
|
continue;
|
|
@@ -771,6 +872,16 @@ function startWatcher() {
|
|
|
771
872
|
kick("create:story", createdStory);
|
|
772
873
|
}
|
|
773
874
|
}
|
|
875
|
+
async function handleVueComponentCreation(abs, relPath) {
|
|
876
|
+
if (isEmptyOrWhitespace(abs)) {
|
|
877
|
+
scaffoldVueComponent(abs);
|
|
878
|
+
}
|
|
879
|
+
console.log("Vue component creation detected:", relPath);
|
|
880
|
+
const createdStory = ensureStoryForVueComponent(abs);
|
|
881
|
+
if (createdStory) {
|
|
882
|
+
kick("create:story", createdStory);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
774
885
|
async function handleAngularComponentCreation(abs, relPath, templateStyle) {
|
|
775
886
|
if (isEmptyOrWhitespace(abs)) {
|
|
776
887
|
scaffoldAngularComponent(abs, templateStyle);
|