@storybook/builder-vite 0.1.23 → 0.1.26

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
@@ -21,6 +21,7 @@ To manually migrate:
21
21
  Requirements:
22
22
 
23
23
  - Vite 2.5 or newer
24
+ - Storybook 6.4.0 or newer (for storybook 6.3, use `storybook-builder-vite@0.1.16)
24
25
 
25
26
  ```bash
26
27
  npm install @storybook/builder-vite --save-dev
@@ -58,13 +59,18 @@ In `.storybook/main.js` (or whatever your Storybook config file is named)
58
59
  you can override the Vite config:
59
60
 
60
61
  ```javascript
62
+ // use `mergeConfig` to recursively merge Vite options
63
+ const { mergeConfig } = require('vite');
64
+
61
65
  module.exports = {
62
66
  async viteFinal(config, { configType }) {
63
- // customize the Vite config here
64
- config.resolve.alias.foo = 'bar';
65
-
66
67
  // return the customized config
67
- return config;
68
+ return mergeConfig(config, {
69
+ // customize the Vite config here
70
+ resolve: {
71
+ alias: { foo: 'bar' },
72
+ },
73
+ });
68
74
  },
69
75
  // ... other options here
70
76
  };
@@ -15,6 +15,7 @@ import { virtualAddonSetupFile, virtualFileId, virtualPreviewFile, virtualStorie
15
15
  export function codeGeneratorPlugin(options: ExtendedOptions): Plugin {
16
16
  const iframePath = path.resolve(__dirname, '..', 'input', 'iframe.html');
17
17
  let iframeId: string;
18
+ let projRoot: string;
18
19
 
19
20
  // noinspection JSUnusedGlobalSymbols
20
21
  return {
@@ -50,6 +51,7 @@ export function codeGeneratorPlugin(options: ExtendedOptions): Plugin {
50
51
  }
51
52
  },
52
53
  configResolved(config) {
54
+ projRoot = config.root;
53
55
  iframeId = `${config.root}/iframe.html`;
54
56
  },
55
57
  resolveId(source) {
@@ -63,6 +65,14 @@ export function codeGeneratorPlugin(options: ExtendedOptions): Plugin {
63
65
  return virtualPreviewFile;
64
66
  } else if (source === virtualAddonSetupFile) {
65
67
  return virtualAddonSetupFile;
68
+ // Avoid error in react < 18 projects
69
+ } else if (source === 'react-dom/client') {
70
+ try {
71
+ return require.resolve('react-dom/client', { paths: [projRoot] });
72
+ } catch (e) {
73
+ // This is not a react 18 project, need to stub out to avoid error
74
+ return path.resolve(__dirname, '..', 'input', 'react-dom-client-placeholder.js');
75
+ }
66
76
  }
67
77
  },
68
78
  async load(id) {
@@ -9,17 +9,14 @@ const absoluteFilesToImport = (files: string[], name: string) =>
9
9
  files.map((el, i) => `import ${name ? `* as ${name}_${i} from ` : ''}'/@fs/${normalizePath(el)}'`).join('\n');
10
10
 
11
11
  export async function generateVirtualStoryEntryCode(options: ExtendedOptions) {
12
- const { frameworkPath, framework } = options;
13
12
  const storyEntries = await listStories(options);
14
13
  const resolveMap = storyEntries.reduce<Record<string, string>>(
15
14
  (prev, entry) => ({ ...prev, [entry]: entry.replace(slash(process.cwd()), '.') }),
16
15
  {}
17
16
  );
18
17
  const modules = storyEntries.map((entry, i) => `${JSON.stringify(entry)}: story_${i}`).join(',');
19
- const frameworkImportPath = frameworkPath || `@storybook/${framework}`;
20
18
 
21
19
  return `
22
- import { configure } from '${frameworkImportPath}';
23
20
  ${absoluteFilesToImport(storyEntries, 'story')}
24
21
 
25
22
  function loadable(key) {
@@ -31,7 +28,7 @@ export async function generateVirtualStoryEntryCode(options: ExtendedOptions) {
31
28
  resolve: (key) => (${JSON.stringify(resolveMap)}[key])
32
29
  });
33
30
 
34
- export function configStories() {
31
+ export function configStories(configure) {
35
32
  configure(loadable, { hot: import.meta.hot }, false);
36
33
  }
37
34
  `.trim();
@@ -1,16 +1,27 @@
1
+ import path from 'path';
1
2
  import { normalizePath } from 'vite';
2
- import { virtualPreviewFile, virtualStoriesFile, virtualAddonSetupFile } from './virtual-file-names';
3
+ import { virtualPreviewFile, virtualStoriesFile } from './virtual-file-names';
3
4
 
4
5
  import type { ExtendedOptions } from './types';
5
6
 
7
+ // We need to convert from an absolute path, to a traditional node module import path,
8
+ // so that vite can correctly pre-bundle/optimize
9
+ function transformPath(absPath: string) {
10
+ const splits = absPath.split(`node_modules${path.sep}`);
11
+ // Return everything after the final "node_modules/"
12
+ const module = normalizePath(splits[splits.length - 1]);
13
+ return module;
14
+ }
15
+
6
16
  export async function generateIframeScriptCode(options: ExtendedOptions) {
7
- const { presets } = options;
17
+ const { presets, frameworkPath, framework } = options;
18
+ const frameworkImportPath = frameworkPath || `@storybook/${framework}`;
8
19
 
9
20
  const presetEntries = await presets.apply('config', [], options);
10
21
  const configEntries = [...presetEntries].filter(Boolean);
11
22
 
12
23
  const absoluteFilesToImport = (files: string[], name: string) =>
13
- files.map((el, i) => `import ${name ? `* as ${name}_${i} from ` : ''}'/@fs/${normalizePath(el)}'`).join('\n');
24
+ files.map((el, i) => `import ${name ? `* as ${name}_${i} from ` : ''}'${transformPath(el)}'`).join('\n');
14
25
 
15
26
  const importArray = (name: string, length: number) => new Array(length).fill(0).map((_, i) => `${name}_${i}`);
16
27
 
@@ -18,7 +29,10 @@ export async function generateIframeScriptCode(options: ExtendedOptions) {
18
29
  /** @todo Inline variable and remove `noinspection` */
19
30
  // language=JavaScript
20
31
  const code = `
21
- import '${virtualAddonSetupFile}';
32
+ // Ensure that the client API is initialized by the framework before any other iframe code
33
+ // is loaded. That way our client-apis can assume the existence of the API+store
34
+ import { configure } from '${frameworkImportPath}';
35
+
22
36
  import {
23
37
  addDecorator,
24
38
  addParameters,
@@ -29,7 +43,6 @@ export async function generateIframeScriptCode(options: ExtendedOptions) {
29
43
  import { logger } from '@storybook/client-logger';
30
44
  ${absoluteFilesToImport(configEntries, 'config')}
31
45
  import * as preview from '${virtualPreviewFile}';
32
- // This import should occur after the config imports above
33
46
  import { configStories } from '${virtualStoriesFile}';
34
47
 
35
48
  const configs = [${importArray('config', configEntries.length).concat('preview.default').join(',')}].filter(Boolean)
@@ -81,7 +94,7 @@ export async function generateIframeScriptCode(options: ExtendedOptions) {
81
94
  }
82
95
  */
83
96
 
84
- configStories();
97
+ configStories(configure);
85
98
  `.trim();
86
99
  return code;
87
100
  }
@@ -32,6 +32,7 @@ const virtual_file_names_1 = require("./virtual-file-names");
32
32
  function codeGeneratorPlugin(options) {
33
33
  const iframePath = path.resolve(__dirname, '..', 'input', 'iframe.html');
34
34
  let iframeId;
35
+ let projRoot;
35
36
  // noinspection JSUnusedGlobalSymbols
36
37
  return {
37
38
  name: 'storybook-vite-code-generator-plugin',
@@ -66,6 +67,7 @@ function codeGeneratorPlugin(options) {
66
67
  }
67
68
  },
68
69
  configResolved(config) {
70
+ projRoot = config.root;
69
71
  iframeId = `${config.root}/iframe.html`;
70
72
  },
71
73
  resolveId(source) {
@@ -83,6 +85,16 @@ function codeGeneratorPlugin(options) {
83
85
  }
84
86
  else if (source === virtual_file_names_1.virtualAddonSetupFile) {
85
87
  return virtual_file_names_1.virtualAddonSetupFile;
88
+ // Avoid error in react < 18 projects
89
+ }
90
+ else if (source === 'react-dom/client') {
91
+ try {
92
+ return require.resolve('react-dom/client', { paths: [projRoot] });
93
+ }
94
+ catch (e) {
95
+ // This is not a react 18 project, need to stub out to avoid error
96
+ return path.resolve(__dirname, '..', 'input', 'react-dom-client-placeholder.js');
97
+ }
86
98
  }
87
99
  },
88
100
  async load(id) {
@@ -1 +1 @@
1
- {"version":3,"file":"code-generator-plugin.js","sourceRoot":"","sources":["../code-generator-plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { transformIframeHtml } from './transform-iframe-html';\nimport { generateIframeScriptCode } from './codegen-iframe-script';\nimport { generateModernIframeScriptCode } from './codegen-modern-iframe-script';\nimport { generateImportFnScriptCode } from './codegen-importfn-script';\nimport { generateVirtualStoryEntryCode, generatePreviewEntryCode } from './codegen-entries';\nimport { generateAddonSetupCode } from './codegen-set-addon-channel';\n\nimport type { Plugin } from 'vite';\nimport type { ExtendedOptions } from './types';\n\nimport { virtualAddonSetupFile, virtualFileId, virtualPreviewFile, virtualStoriesFile } from './virtual-file-names';\n\nexport function codeGeneratorPlugin(options: ExtendedOptions): Plugin {\n const iframePath = path.resolve(__dirname, '..', 'input', 'iframe.html');\n let iframeId: string;\n\n // noinspection JSUnusedGlobalSymbols\n return {\n name: 'storybook-vite-code-generator-plugin',\n enforce: 'pre',\n configureServer(server) {\n // invalidate the whole vite-app.js script on every file change.\n // (this might be a little too aggressive?)\n server.watcher.on('change', (_e) => {\n const { moduleGraph } = server;\n const appModule = moduleGraph.getModuleById(virtualFileId);\n if (appModule) {\n server.moduleGraph.invalidateModule(appModule);\n }\n const storiesModule = moduleGraph.getModuleById(virtualStoriesFile);\n if (storiesModule) {\n server.moduleGraph.invalidateModule(storiesModule);\n }\n });\n },\n config(config, { command }) {\n // If we are building the static distribution, add iframe.html as an entry.\n // In development mode, it's not an entry - instead, we use an express middleware\n // to serve iframe.html. The reason is that Vite's dev server (at the time of writing)\n // does not support virtual files as entry points.\n if (command === 'build') {\n if (!config.build) {\n config.build = {};\n }\n config.build.rollupOptions = {\n input: iframePath,\n };\n }\n },\n configResolved(config) {\n iframeId = `${config.root}/iframe.html`;\n },\n resolveId(source) {\n if (source === virtualFileId) {\n return virtualFileId;\n } else if (source === iframePath) {\n return iframeId;\n } else if (source === virtualStoriesFile) {\n return virtualStoriesFile;\n } else if (source === virtualPreviewFile) {\n return virtualPreviewFile;\n } else if (source === virtualAddonSetupFile) {\n return virtualAddonSetupFile;\n }\n },\n async load(id) {\n const storyStoreV7 = options.features?.storyStoreV7;\n if (id === virtualStoriesFile) {\n if (storyStoreV7) {\n return generateImportFnScriptCode(options);\n } else {\n return generateVirtualStoryEntryCode(options);\n }\n }\n\n if (id === virtualAddonSetupFile) {\n return generateAddonSetupCode();\n }\n\n if (id === virtualPreviewFile && !storyStoreV7) {\n return generatePreviewEntryCode(options);\n }\n\n if (id === virtualFileId) {\n if (storyStoreV7) {\n return generateModernIframeScriptCode(options);\n } else {\n return generateIframeScriptCode(options);\n }\n }\n\n if (id === iframeId) {\n return fs.readFileSync(path.resolve(__dirname, '..', 'input', 'iframe.html'), 'utf-8');\n }\n },\n async transformIndexHtml(html, ctx) {\n if (ctx.path !== '/iframe.html') {\n return;\n }\n return transformIframeHtml(html, options);\n },\n };\n}\n"]}
1
+ {"version":3,"file":"code-generator-plugin.js","sourceRoot":"","sources":["../code-generator-plugin.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { transformIframeHtml } from './transform-iframe-html';\nimport { generateIframeScriptCode } from './codegen-iframe-script';\nimport { generateModernIframeScriptCode } from './codegen-modern-iframe-script';\nimport { generateImportFnScriptCode } from './codegen-importfn-script';\nimport { generateVirtualStoryEntryCode, generatePreviewEntryCode } from './codegen-entries';\nimport { generateAddonSetupCode } from './codegen-set-addon-channel';\n\nimport type { Plugin } from 'vite';\nimport type { ExtendedOptions } from './types';\n\nimport { virtualAddonSetupFile, virtualFileId, virtualPreviewFile, virtualStoriesFile } from './virtual-file-names';\n\nexport function codeGeneratorPlugin(options: ExtendedOptions): Plugin {\n const iframePath = path.resolve(__dirname, '..', 'input', 'iframe.html');\n let iframeId: string;\n let projRoot: string;\n\n // noinspection JSUnusedGlobalSymbols\n return {\n name: 'storybook-vite-code-generator-plugin',\n enforce: 'pre',\n configureServer(server) {\n // invalidate the whole vite-app.js script on every file change.\n // (this might be a little too aggressive?)\n server.watcher.on('change', (_e) => {\n const { moduleGraph } = server;\n const appModule = moduleGraph.getModuleById(virtualFileId);\n if (appModule) {\n server.moduleGraph.invalidateModule(appModule);\n }\n const storiesModule = moduleGraph.getModuleById(virtualStoriesFile);\n if (storiesModule) {\n server.moduleGraph.invalidateModule(storiesModule);\n }\n });\n },\n config(config, { command }) {\n // If we are building the static distribution, add iframe.html as an entry.\n // In development mode, it's not an entry - instead, we use an express middleware\n // to serve iframe.html. The reason is that Vite's dev server (at the time of writing)\n // does not support virtual files as entry points.\n if (command === 'build') {\n if (!config.build) {\n config.build = {};\n }\n config.build.rollupOptions = {\n input: iframePath,\n };\n }\n },\n configResolved(config) {\n projRoot = config.root;\n iframeId = `${config.root}/iframe.html`;\n },\n resolveId(source) {\n if (source === virtualFileId) {\n return virtualFileId;\n } else if (source === iframePath) {\n return iframeId;\n } else if (source === virtualStoriesFile) {\n return virtualStoriesFile;\n } else if (source === virtualPreviewFile) {\n return virtualPreviewFile;\n } else if (source === virtualAddonSetupFile) {\n return virtualAddonSetupFile;\n // Avoid error in react < 18 projects\n } else if (source === 'react-dom/client') {\n try {\n return require.resolve('react-dom/client', { paths: [projRoot] });\n } catch (e) {\n // This is not a react 18 project, need to stub out to avoid error\n return path.resolve(__dirname, '..', 'input', 'react-dom-client-placeholder.js');\n }\n }\n },\n async load(id) {\n const storyStoreV7 = options.features?.storyStoreV7;\n if (id === virtualStoriesFile) {\n if (storyStoreV7) {\n return generateImportFnScriptCode(options);\n } else {\n return generateVirtualStoryEntryCode(options);\n }\n }\n\n if (id === virtualAddonSetupFile) {\n return generateAddonSetupCode();\n }\n\n if (id === virtualPreviewFile && !storyStoreV7) {\n return generatePreviewEntryCode(options);\n }\n\n if (id === virtualFileId) {\n if (storyStoreV7) {\n return generateModernIframeScriptCode(options);\n } else {\n return generateIframeScriptCode(options);\n }\n }\n\n if (id === iframeId) {\n return fs.readFileSync(path.resolve(__dirname, '..', 'input', 'iframe.html'), 'utf-8');\n }\n },\n async transformIndexHtml(html, ctx) {\n if (ctx.path !== '/iframe.html') {\n return;\n }\n return transformIframeHtml(html, options);\n },\n };\n}\n"]}
@@ -10,13 +10,10 @@ const vite_1 = require("vite");
10
10
  const list_stories_1 = require("./list-stories");
11
11
  const absoluteFilesToImport = (files, name) => files.map((el, i) => `import ${name ? `* as ${name}_${i} from ` : ''}'/@fs/${(0, vite_1.normalizePath)(el)}'`).join('\n');
12
12
  async function generateVirtualStoryEntryCode(options) {
13
- const { frameworkPath, framework } = options;
14
13
  const storyEntries = await (0, list_stories_1.listStories)(options);
15
14
  const resolveMap = storyEntries.reduce((prev, entry) => ({ ...prev, [entry]: entry.replace((0, slash_1.default)(process.cwd()), '.') }), {});
16
15
  const modules = storyEntries.map((entry, i) => `${JSON.stringify(entry)}: story_${i}`).join(',');
17
- const frameworkImportPath = frameworkPath || `@storybook/${framework}`;
18
16
  return `
19
- import { configure } from '${frameworkImportPath}';
20
17
  ${absoluteFilesToImport(storyEntries, 'story')}
21
18
 
22
19
  function loadable(key) {
@@ -28,7 +25,7 @@ async function generateVirtualStoryEntryCode(options) {
28
25
  resolve: (key) => (${JSON.stringify(resolveMap)}[key])
29
26
  });
30
27
 
31
- export function configStories() {
28
+ export function configStories(configure) {
32
29
  configure(loadable, { hot: import.meta.hot }, false);
33
30
  }
34
31
  `.trim();
@@ -1 +1 @@
1
- {"version":3,"file":"codegen-entries.js","sourceRoot":"","sources":["../codegen-entries.ts"],"names":[],"mappings":";;;;;;AAAA,wDAAiE;AAEjE,kDAA0B;AAC1B,+BAAqC;AAErC,iDAA6C;AAE7C,MAAM,qBAAqB,GAAG,CAAC,KAAe,EAAE,IAAY,EAAE,EAAE,CAC9D,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,IAAA,oBAAa,EAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEzG,KAAK,UAAU,6BAA6B,CAAC,OAAwB;IAC1E,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAC7C,MAAM,YAAY,GAAG,MAAM,IAAA,0BAAW,EAAC,OAAO,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CACpC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,IAAA,eAAK,EAAC,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EACjF,EAAE,CACH,CAAC;IACF,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjG,MAAM,mBAAmB,GAAG,aAAa,IAAI,cAAc,SAAS,EAAE,CAAC;IAEvE,OAAO;iCACwB,mBAAmB;MAC9C,qBAAqB,CAAC,YAAY,EAAE,OAAO,CAAC;;;gBAGlC,OAAO;;;;qBAIF,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;2BACjC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;;;;;;GAMlD,CAAC,IAAI,EAAE,CAAC;AACX,CAAC;AA3BD,sEA2BC;AAEM,KAAK,UAAU,wBAAwB,CAAC,EAAE,SAAS,EAAW;IACnE,MAAM,WAAW,GAAG,IAAA,qCAAuB,EAAC,EAAE,SAAS,EAAE,CAAC,CAAC;IAC3D,IAAI,CAAC,WAAW;QAAE,OAAO,EAAE,CAAC;IAE5B,OAAO,6BAA6B,IAAA,eAAK,EAAC,WAAW,CAAC;0BAC9B,CAAC;AAC3B,CAAC;AAND,4DAMC","sourcesContent":["import { loadPreviewOrConfigFile } from '@storybook/core-common';\nimport type { Options } from '@storybook/core-common';\nimport slash from 'slash';\nimport { normalizePath } from 'vite';\nimport type { ExtendedOptions } from './types';\nimport { listStories } from './list-stories';\n\nconst absoluteFilesToImport = (files: string[], name: string) =>\n files.map((el, i) => `import ${name ? `* as ${name}_${i} from ` : ''}'/@fs/${normalizePath(el)}'`).join('\\n');\n\nexport async function generateVirtualStoryEntryCode(options: ExtendedOptions) {\n const { frameworkPath, framework } = options;\n const storyEntries = await listStories(options);\n const resolveMap = storyEntries.reduce<Record<string, string>>(\n (prev, entry) => ({ ...prev, [entry]: entry.replace(slash(process.cwd()), '.') }),\n {}\n );\n const modules = storyEntries.map((entry, i) => `${JSON.stringify(entry)}: story_${i}`).join(',');\n const frameworkImportPath = frameworkPath || `@storybook/${framework}`;\n\n return `\n import { configure } from '${frameworkImportPath}';\n ${absoluteFilesToImport(storyEntries, 'story')}\n\n function loadable(key) {\n return {${modules}}[key];\n }\n \n Object.assign(loadable, {\n keys: () => (${JSON.stringify(Object.keys(resolveMap))}),\n resolve: (key) => (${JSON.stringify(resolveMap)}[key])\n });\n\n export function configStories() {\n configure(loadable, { hot: import.meta.hot }, false);\n }\n `.trim();\n}\n\nexport async function generatePreviewEntryCode({ configDir }: Options) {\n const previewFile = loadPreviewOrConfigFile({ configDir });\n if (!previewFile) return '';\n\n return `import * as preview from '${slash(previewFile)}';\n export default preview;`;\n}\n"]}
1
+ {"version":3,"file":"codegen-entries.js","sourceRoot":"","sources":["../codegen-entries.ts"],"names":[],"mappings":";;;;;;AAAA,wDAAiE;AAEjE,kDAA0B;AAC1B,+BAAqC;AAErC,iDAA6C;AAE7C,MAAM,qBAAqB,GAAG,CAAC,KAAe,EAAE,IAAY,EAAE,EAAE,CAC9D,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,IAAA,oBAAa,EAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEzG,KAAK,UAAU,6BAA6B,CAAC,OAAwB;IAC1E,MAAM,YAAY,GAAG,MAAM,IAAA,0BAAW,EAAC,OAAO,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CACpC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,IAAA,eAAK,EAAC,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EACjF,EAAE,CACH,CAAC;IACF,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEjG,OAAO;MACH,qBAAqB,CAAC,YAAY,EAAE,OAAO,CAAC;;;gBAGlC,OAAO;;;;qBAIF,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;2BACjC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;;;;;;GAMlD,CAAC,IAAI,EAAE,CAAC;AACX,CAAC;AAxBD,sEAwBC;AAEM,KAAK,UAAU,wBAAwB,CAAC,EAAE,SAAS,EAAW;IACnE,MAAM,WAAW,GAAG,IAAA,qCAAuB,EAAC,EAAE,SAAS,EAAE,CAAC,CAAC;IAC3D,IAAI,CAAC,WAAW;QAAE,OAAO,EAAE,CAAC;IAE5B,OAAO,6BAA6B,IAAA,eAAK,EAAC,WAAW,CAAC;0BAC9B,CAAC;AAC3B,CAAC;AAND,4DAMC","sourcesContent":["import { loadPreviewOrConfigFile } from '@storybook/core-common';\nimport type { Options } from '@storybook/core-common';\nimport slash from 'slash';\nimport { normalizePath } from 'vite';\nimport type { ExtendedOptions } from './types';\nimport { listStories } from './list-stories';\n\nconst absoluteFilesToImport = (files: string[], name: string) =>\n files.map((el, i) => `import ${name ? `* as ${name}_${i} from ` : ''}'/@fs/${normalizePath(el)}'`).join('\\n');\n\nexport async function generateVirtualStoryEntryCode(options: ExtendedOptions) {\n const storyEntries = await listStories(options);\n const resolveMap = storyEntries.reduce<Record<string, string>>(\n (prev, entry) => ({ ...prev, [entry]: entry.replace(slash(process.cwd()), '.') }),\n {}\n );\n const modules = storyEntries.map((entry, i) => `${JSON.stringify(entry)}: story_${i}`).join(',');\n\n return `\n ${absoluteFilesToImport(storyEntries, 'story')}\n\n function loadable(key) {\n return {${modules}}[key];\n }\n \n Object.assign(loadable, {\n keys: () => (${JSON.stringify(Object.keys(resolveMap))}),\n resolve: (key) => (${JSON.stringify(resolveMap)}[key])\n });\n\n export function configStories(configure) {\n configure(loadable, { hot: import.meta.hot }, false);\n }\n `.trim();\n}\n\nexport async function generatePreviewEntryCode({ configDir }: Options) {\n const previewFile = loadPreviewOrConfigFile({ configDir });\n if (!previewFile) return '';\n\n return `import * as preview from '${slash(previewFile)}';\n export default preview;`;\n}\n"]}
@@ -1,19 +1,35 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.generateIframeScriptCode = void 0;
7
+ const path_1 = __importDefault(require("path"));
4
8
  const vite_1 = require("vite");
5
9
  const virtual_file_names_1 = require("./virtual-file-names");
10
+ // We need to convert from an absolute path, to a traditional node module import path,
11
+ // so that vite can correctly pre-bundle/optimize
12
+ function transformPath(absPath) {
13
+ const splits = absPath.split(`node_modules${path_1.default.sep}`);
14
+ // Return everything after the final "node_modules/"
15
+ const module = (0, vite_1.normalizePath)(splits[splits.length - 1]);
16
+ return module;
17
+ }
6
18
  async function generateIframeScriptCode(options) {
7
- const { presets } = options;
19
+ const { presets, frameworkPath, framework } = options;
20
+ const frameworkImportPath = frameworkPath || `@storybook/${framework}`;
8
21
  const presetEntries = await presets.apply('config', [], options);
9
22
  const configEntries = [...presetEntries].filter(Boolean);
10
- const absoluteFilesToImport = (files, name) => files.map((el, i) => `import ${name ? `* as ${name}_${i} from ` : ''}'/@fs/${(0, vite_1.normalizePath)(el)}'`).join('\n');
23
+ const absoluteFilesToImport = (files, name) => files.map((el, i) => `import ${name ? `* as ${name}_${i} from ` : ''}'${transformPath(el)}'`).join('\n');
11
24
  const importArray = (name, length) => new Array(length).fill(0).map((_, i) => `${name}_${i}`);
12
25
  // noinspection UnnecessaryLocalVariableJS
13
26
  /** @todo Inline variable and remove `noinspection` */
14
27
  // language=JavaScript
15
28
  const code = `
16
- import '${virtual_file_names_1.virtualAddonSetupFile}';
29
+ // Ensure that the client API is initialized by the framework before any other iframe code
30
+ // is loaded. That way our client-apis can assume the existence of the API+store
31
+ import { configure } from '${frameworkImportPath}';
32
+
17
33
  import {
18
34
  addDecorator,
19
35
  addParameters,
@@ -24,7 +40,6 @@ async function generateIframeScriptCode(options) {
24
40
  import { logger } from '@storybook/client-logger';
25
41
  ${absoluteFilesToImport(configEntries, 'config')}
26
42
  import * as preview from '${virtual_file_names_1.virtualPreviewFile}';
27
- // This import should occur after the config imports above
28
43
  import { configStories } from '${virtual_file_names_1.virtualStoriesFile}';
29
44
 
30
45
  const configs = [${importArray('config', configEntries.length).concat('preview.default').join(',')}].filter(Boolean)
@@ -76,7 +91,7 @@ async function generateIframeScriptCode(options) {
76
91
  }
77
92
  */
78
93
 
79
- configStories();
94
+ configStories(configure);
80
95
  `.trim();
81
96
  return code;
82
97
  }
@@ -1 +1 @@
1
- {"version":3,"file":"codegen-iframe-script.js","sourceRoot":"","sources":["../codegen-iframe-script.ts"],"names":[],"mappings":";;;AAAA,+BAAqC;AACrC,6DAAqG;AAI9F,KAAK,UAAU,wBAAwB,CAAC,OAAwB;IACrE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAE5B,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IACjE,MAAM,aAAa,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEzD,MAAM,qBAAqB,GAAG,CAAC,KAAe,EAAE,IAAY,EAAE,EAAE,CAC9D,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,IAAA,oBAAa,EAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEhH,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,MAAc,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;IAE9G,0CAA0C;IAC1C,sDAAsD;IACtD,sBAAsB;IACtB,MAAM,IAAI,GAAG;cACD,0CAAqB;;;;;;;;;MAS7B,qBAAqB,CAAC,aAAa,EAAE,QAAQ,CAAC;gCACpB,uCAAkB;;qCAEb,uCAAkB;;uBAEhC,WAAW,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAkDjG,CAAC,IAAI,EAAE,CAAC;IACX,OAAO,IAAI,CAAC;AACd,CAAC;AAjFD,4DAiFC","sourcesContent":["import { normalizePath } from 'vite';\nimport { virtualPreviewFile, virtualStoriesFile, virtualAddonSetupFile } from './virtual-file-names';\n\nimport type { ExtendedOptions } from './types';\n\nexport async function generateIframeScriptCode(options: ExtendedOptions) {\n const { presets } = options;\n\n const presetEntries = await presets.apply('config', [], options);\n const configEntries = [...presetEntries].filter(Boolean);\n\n const absoluteFilesToImport = (files: string[], name: string) =>\n files.map((el, i) => `import ${name ? `* as ${name}_${i} from ` : ''}'/@fs/${normalizePath(el)}'`).join('\\n');\n\n const importArray = (name: string, length: number) => new Array(length).fill(0).map((_, i) => `${name}_${i}`);\n\n // noinspection UnnecessaryLocalVariableJS\n /** @todo Inline variable and remove `noinspection` */\n // language=JavaScript\n const code = `\n import '${virtualAddonSetupFile}';\n import {\n addDecorator,\n addParameters,\n addLoader,\n addArgTypesEnhancer,\n addArgsEnhancer\n } from '@storybook/client-api';\n import { logger } from '@storybook/client-logger';\n ${absoluteFilesToImport(configEntries, 'config')}\n import * as preview from '${virtualPreviewFile}';\n // This import should occur after the config imports above\n import { configStories } from '${virtualStoriesFile}';\n\n const configs = [${importArray('config', configEntries.length).concat('preview.default').join(',')}].filter(Boolean)\n\n configs.forEach(config => {\n Object.keys(config).forEach((key) => {\n const value = config[key];\n switch (key) {\n case 'args':\n case 'argTypes': {\n return logger.warn('Invalid args/argTypes in config, ignoring.', JSON.stringify(value));\n }\n case 'decorators': {\n return value.forEach((decorator) => addDecorator(decorator, false));\n }\n case 'loaders': {\n return value.forEach((loader) => addLoader(loader, false));\n }\n case 'parameters': {\n return addParameters({ ...value }, false);\n }\n case 'argTypesEnhancers': {\n return value.forEach((enhancer) => addArgTypesEnhancer(enhancer));\n }\n case 'argsEnhancers': {\n return value.forEach((enhancer) => addArgsEnhancer(enhancer))\n }\n case 'globals':\n case 'globalTypes': {\n const v = {};\n v[key] = value;\n return addParameters(v, false);\n }\n case 'decorateStory':\n case 'renderToDOM': {\n return null; // This key is not handled directly in v6 mode.\n }\n default: {\n // eslint-disable-next-line prefer-template\n return console.log(key + ' was not supported :( !');\n }\n }\n });\n })\n \n /* TODO: not quite sure what to do with this, to fix HMR\n if (import.meta.hot) {\n import.meta.hot.accept(); \n }\n */\n\n configStories();\n `.trim();\n return code;\n}\n"]}
1
+ {"version":3,"file":"codegen-iframe-script.js","sourceRoot":"","sources":["../codegen-iframe-script.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AACxB,+BAAqC;AACrC,6DAA8E;AAI9E,sFAAsF;AACtF,iDAAiD;AACjD,SAAS,aAAa,CAAC,OAAe;IACpC,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,eAAe,cAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACxD,oDAAoD;IACpD,MAAM,MAAM,GAAG,IAAA,oBAAa,EAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IACxD,OAAO,MAAM,CAAC;AAChB,CAAC;AAEM,KAAK,UAAU,wBAAwB,CAAC,OAAwB;IACrE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IACtD,MAAM,mBAAmB,GAAG,aAAa,IAAI,cAAc,SAAS,EAAE,CAAC;IAEvE,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IACjE,MAAM,aAAa,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEzD,MAAM,qBAAqB,GAAG,CAAC,KAAe,EAAE,IAAY,EAAE,EAAE,CAC9D,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE3G,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,MAAc,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;IAE9G,0CAA0C;IAC1C,sDAAsD;IACtD,sBAAsB;IACtB,MAAM,IAAI,GAAG;;;iCAGkB,mBAAmB;;;;;;;;;;MAU9C,qBAAqB,CAAC,aAAa,EAAE,QAAQ,CAAC;gCACpB,uCAAkB;qCACb,uCAAkB;;uBAEhC,WAAW,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAkDjG,CAAC,IAAI,EAAE,CAAC;IACX,OAAO,IAAI,CAAC;AACd,CAAC;AApFD,4DAoFC","sourcesContent":["import path from 'path';\nimport { normalizePath } from 'vite';\nimport { virtualPreviewFile, virtualStoriesFile } from './virtual-file-names';\n\nimport type { ExtendedOptions } from './types';\n\n// We need to convert from an absolute path, to a traditional node module import path,\n// so that vite can correctly pre-bundle/optimize\nfunction transformPath(absPath: string) {\n const splits = absPath.split(`node_modules${path.sep}`);\n // Return everything after the final \"node_modules/\"\n const module = normalizePath(splits[splits.length - 1]);\n return module;\n}\n\nexport async function generateIframeScriptCode(options: ExtendedOptions) {\n const { presets, frameworkPath, framework } = options;\n const frameworkImportPath = frameworkPath || `@storybook/${framework}`;\n\n const presetEntries = await presets.apply('config', [], options);\n const configEntries = [...presetEntries].filter(Boolean);\n\n const absoluteFilesToImport = (files: string[], name: string) =>\n files.map((el, i) => `import ${name ? `* as ${name}_${i} from ` : ''}'${transformPath(el)}'`).join('\\n');\n\n const importArray = (name: string, length: number) => new Array(length).fill(0).map((_, i) => `${name}_${i}`);\n\n // noinspection UnnecessaryLocalVariableJS\n /** @todo Inline variable and remove `noinspection` */\n // language=JavaScript\n const code = `\n // Ensure that the client API is initialized by the framework before any other iframe code\n // is loaded. That way our client-apis can assume the existence of the API+store\n import { configure } from '${frameworkImportPath}';\n\n import {\n addDecorator,\n addParameters,\n addLoader,\n addArgTypesEnhancer,\n addArgsEnhancer\n } from '@storybook/client-api';\n import { logger } from '@storybook/client-logger';\n ${absoluteFilesToImport(configEntries, 'config')}\n import * as preview from '${virtualPreviewFile}';\n import { configStories } from '${virtualStoriesFile}';\n\n const configs = [${importArray('config', configEntries.length).concat('preview.default').join(',')}].filter(Boolean)\n\n configs.forEach(config => {\n Object.keys(config).forEach((key) => {\n const value = config[key];\n switch (key) {\n case 'args':\n case 'argTypes': {\n return logger.warn('Invalid args/argTypes in config, ignoring.', JSON.stringify(value));\n }\n case 'decorators': {\n return value.forEach((decorator) => addDecorator(decorator, false));\n }\n case 'loaders': {\n return value.forEach((loader) => addLoader(loader, false));\n }\n case 'parameters': {\n return addParameters({ ...value }, false);\n }\n case 'argTypesEnhancers': {\n return value.forEach((enhancer) => addArgTypesEnhancer(enhancer));\n }\n case 'argsEnhancers': {\n return value.forEach((enhancer) => addArgsEnhancer(enhancer))\n }\n case 'globals':\n case 'globalTypes': {\n const v = {};\n v[key] = value;\n return addParameters(v, false);\n }\n case 'decorateStory':\n case 'renderToDOM': {\n return null; // This key is not handled directly in v6 mode.\n }\n default: {\n // eslint-disable-next-line prefer-template\n return console.log(key + ' was not supported :( !');\n }\n }\n });\n })\n \n /* TODO: not quite sure what to do with this, to fix HMR\n if (import.meta.hot) {\n import.meta.hot.accept(); \n }\n */\n\n configStories(configure);\n `.trim();\n return code;\n}\n"]}
@@ -6,4 +6,5 @@ export declare function getOptimizeDeps(config: UserConfig & {
6
6
  }, options: ExtendedOptions): Promise<{
7
7
  entries: string[];
8
8
  include: string[];
9
+ exclude: string[];
9
10
  }>;
@@ -18,31 +18,22 @@ var __importStar = (this && this.__importStar) || function (mod) {
18
18
  __setModuleDefault(result, mod);
19
19
  return result;
20
20
  };
21
+ var __importDefault = (this && this.__importDefault) || function (mod) {
22
+ return (mod && mod.__esModule) ? mod : { "default": mod };
23
+ };
21
24
  Object.defineProperty(exports, "__esModule", { value: true });
22
25
  exports.getOptimizeDeps = void 0;
23
26
  const path = __importStar(require("path"));
24
27
  const vite_1 = require("vite");
25
28
  const list_stories_1 = require("./list-stories");
29
+ const semver_1 = __importDefault(require("semver"));
26
30
  const INCLUDE_CANDIDATES = [
27
31
  '@base2/pretty-print-object',
28
32
  '@emotion/core',
29
33
  '@emotion/is-prop-valid',
30
34
  '@emotion/styled',
31
35
  '@mdx-js/react',
32
- '@storybook/addon-docs > acorn-jsx',
33
- '@storybook/addon-docs',
34
- '@storybook/addons',
35
- '@storybook/channel-postmessage',
36
- '@storybook/channel-websocket',
37
- '@storybook/client-api',
38
- '@storybook/client-logger',
39
- '@storybook/core/client',
40
36
  '@storybook/csf',
41
- '@storybook/preview-web',
42
- '@storybook/react > acorn-jsx',
43
- '@storybook/react',
44
- '@storybook/svelte',
45
- '@storybook/vue3',
46
37
  'acorn-jsx',
47
38
  'acorn-walk',
48
39
  'acorn',
@@ -82,6 +73,7 @@ const INCLUDE_CANDIDATES = [
82
73
  'prop-types',
83
74
  'qs',
84
75
  'react-dom',
76
+ 'react-dom/client',
85
77
  'react-fast-compare',
86
78
  'react-is',
87
79
  'react-textarea-autosize',
@@ -116,6 +108,7 @@ const INCLUDE_CANDIDATES = [
116
108
  */
117
109
  const asyncFilter = async (arr, predicate) => Promise.all(arr.map(predicate)).then((results) => arr.filter((_v, index) => results[index]));
118
110
  async function getOptimizeDeps(config, options) {
111
+ var _a;
119
112
  const { root } = config;
120
113
  const absoluteStories = await (0, list_stories_1.listStories)(options);
121
114
  const stories = absoluteStories.map((storyPath) => (0, vite_1.normalizePath)(path.relative(root, storyPath)));
@@ -124,13 +117,48 @@ async function getOptimizeDeps(config, options) {
124
117
  // See https://github.com/vitejs/vite/blob/67d164392e8e9081dc3f0338c4b4b8eea6c5f7da/packages/vite/src/node/optimizer/index.ts#L182-L199
125
118
  const resolve = resolvedConfig.createResolver({ asSrc: false });
126
119
  const include = await asyncFilter(INCLUDE_CANDIDATES, async (id) => Boolean(await resolve(id)));
120
+ // We can exclude some packages which otherwise are optimized
121
+ const exclude = [
122
+ '@storybook/addon-docs',
123
+ '@storybook/client-api',
124
+ '@storybook/client-logger',
125
+ '@storybook/preview-web',
126
+ '@storybook/channel-postmessage',
127
+ '@storybook/channel-websocket',
128
+ '@storybook/addons',
129
+ ];
130
+ // This is necessary to support react < 18 with new versions of @storybook/react that support react 18.
131
+ // TODO: narrow this down to just framework === 'react'. But causes a vue dev start problem in this monorepo.
132
+ try {
133
+ require.resolve('react-dom/client', { paths: [config.root] });
134
+ }
135
+ catch (e) {
136
+ if (isNodeError(e) && e.code === 'MODULE_NOT_FOUND') {
137
+ exclude.push('react-dom/client');
138
+ }
139
+ }
140
+ // Depending on the user's storybook version, we can also exclude the framework from prebundling
141
+ // See https://github.com/storybookjs/storybook/pull/17875
142
+ const { frameworkPath, framework } = options;
143
+ const frameworkPackageName = frameworkPath || `@storybook/${framework}`;
144
+ const sbVersion = (_a = (await Promise.resolve().then(() => __importStar(require(`${frameworkPackageName}/package.json`))))) === null || _a === void 0 ? void 0 : _a.version;
145
+ if (sbVersion && semver_1.default.gte(sbVersion, '6.5.0-alpha.58', { includePrerelease: true })) {
146
+ exclude.push(frameworkPackageName);
147
+ }
148
+ else {
149
+ include.push(frameworkPackageName);
150
+ }
127
151
  return {
128
152
  // We don't need to resolve the glob since vite supports globs for entries.
129
153
  entries: stories,
130
154
  // We need Vite to precompile these dependencies, because they contain non-ESM code that would break
131
155
  // if we served it directly to the browser.
132
156
  include,
157
+ // In some cases we need to prevent deps from being pre-bundled
158
+ exclude,
133
159
  };
134
160
  }
135
161
  exports.getOptimizeDeps = getOptimizeDeps;
162
+ // Refines an error received from 'catch' to be a NodeJS exception
163
+ const isNodeError = (error) => error instanceof Error;
136
164
  //# sourceMappingURL=optimizeDeps.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"optimizeDeps.js","sourceRoot":"","sources":["../optimizeDeps.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA6B;AAC7B,+BAAgE;AAChE,iDAA6C;AAI7C,MAAM,kBAAkB,GAAG;IACzB,4BAA4B;IAC5B,eAAe;IACf,wBAAwB;IACxB,iBAAiB;IACjB,eAAe;IACf,mCAAmC;IACnC,uBAAuB;IACvB,mBAAmB;IACnB,gCAAgC;IAChC,8BAA8B;IAC9B,uBAAuB;IACvB,0BAA0B;IAC1B,wBAAwB;IACxB,gBAAgB;IAChB,wBAAwB;IACxB,8BAA8B;IAC9B,kBAAkB;IAClB,mBAAmB;IACnB,iBAAiB;IACjB,WAAW;IACX,YAAY;IACZ,OAAO;IACP,iBAAiB;IACjB,cAAc;IACd,UAAU;IACV,eAAe;IACf,kBAAkB;IAClB,UAAU;IACV,iBAAiB;IACjB,WAAW;IACX,YAAY;IACZ,iBAAiB;IACjB,QAAQ;IACR,WAAW;IACX,UAAU;IACV,WAAW;IACX,cAAc;IACd,kBAAkB;IAClB,mBAAmB;IACnB,sBAAsB;IACtB,iBAAiB;IACjB,gBAAgB;IAChB,kBAAkB;IAClB,aAAa;IACb,eAAe;IACf,kBAAkB;IAClB,iBAAiB;IACjB,aAAa;IACb,iBAAiB;IACjB,cAAc;IACd,mBAAmB;IACnB,UAAU;IACV,uBAAuB;IACvB,sBAAsB;IACtB,4BAA4B;IAC5B,YAAY;IACZ,IAAI;IACJ,WAAW;IACX,oBAAoB;IACpB,UAAU;IACV,yBAAyB;IACzB,OAAO;IACP,gBAAgB;IAChB,wBAAwB;IACxB,uBAAuB;IACvB,2BAA2B;IAC3B,6BAA6B;IAC7B,wBAAwB;IACxB,uBAAuB;IACvB,4BAA4B;IAC5B,0BAA0B;IAC1B,uBAAuB;IACvB,8BAA8B;IAC9B,wBAAwB;IACxB,gCAAgC;IAChC,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,qBAAqB;IACrB,UAAU;IACV,WAAW;IACX,SAAS;IACT,gBAAgB;IAChB,iBAAiB;IACjB,KAAK;IACL,SAAS;CACV,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,GAAG,KAAK,EAAE,GAAa,EAAE,SAA4C,EAAE,EAAE,CACxF,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAExF,KAAK,UAAU,eAAe,CACnC,MAAwD,EACxD,OAAwB;IAExB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;IACxB,MAAM,eAAe,GAAG,MAAM,IAAA,0BAAW,EAAC,OAAO,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,IAAA,oBAAa,EAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IAClG,MAAM,cAAc,GAAG,MAAM,IAAA,oBAAa,EAAC,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;IAE3E,6FAA6F;IAC7F,uIAAuI;IACvI,MAAM,OAAO,GAAG,cAAc,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,kBAAkB,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAEhG,OAAO;QACL,2EAA2E;QAC3E,OAAO,EAAE,OAAO;QAChB,oGAAoG;QACpG,2CAA2C;QAC3C,OAAO;KACR,CAAC;AACJ,CAAC;AArBD,0CAqBC","sourcesContent":["import * as path from 'path';\nimport { normalizePath, resolveConfig, UserConfig } from 'vite';\nimport { listStories } from './list-stories';\n\nimport type { ExtendedOptions } from './types';\n\nconst INCLUDE_CANDIDATES = [\n '@base2/pretty-print-object',\n '@emotion/core',\n '@emotion/is-prop-valid',\n '@emotion/styled',\n '@mdx-js/react',\n '@storybook/addon-docs > acorn-jsx',\n '@storybook/addon-docs',\n '@storybook/addons',\n '@storybook/channel-postmessage',\n '@storybook/channel-websocket',\n '@storybook/client-api',\n '@storybook/client-logger',\n '@storybook/core/client',\n '@storybook/csf',\n '@storybook/preview-web',\n '@storybook/react > acorn-jsx',\n '@storybook/react',\n '@storybook/svelte',\n '@storybook/vue3',\n 'acorn-jsx',\n 'acorn-walk',\n 'acorn',\n 'airbnb-js-shims',\n 'ansi-to-html',\n 'axe-core',\n 'color-convert',\n 'deep-object-diff',\n 'doctrine',\n 'emotion-theming',\n 'escodegen',\n 'estraverse',\n 'fast-deep-equal',\n 'global',\n 'html-tags',\n 'isobject',\n 'jest-mock',\n 'loader-utils',\n 'lodash/cloneDeep',\n 'lodash/isFunction',\n 'lodash/isPlainObject',\n 'lodash/isString',\n 'lodash/mapKeys',\n 'lodash/mapValues',\n 'lodash/pick',\n 'lodash/pickBy',\n 'lodash/startCase',\n 'lodash/throttle',\n 'lodash/uniq',\n 'markdown-to-jsx',\n 'memoizerific',\n 'overlayscrollbars',\n 'polished',\n 'prettier/parser-babel',\n 'prettier/parser-flow',\n 'prettier/parser-typescript',\n 'prop-types',\n 'qs',\n 'react-dom',\n 'react-fast-compare',\n 'react-is',\n 'react-textarea-autosize',\n 'react',\n 'refractor/core',\n 'refractor/lang/bash.js',\n 'refractor/lang/css.js',\n 'refractor/lang/graphql.js',\n 'refractor/lang/js-extras.js',\n 'refractor/lang/json.js',\n 'refractor/lang/jsx.js',\n 'refractor/lang/markdown.js',\n 'refractor/lang/markup.js',\n 'refractor/lang/tsx.js',\n 'refractor/lang/typescript.js',\n 'refractor/lang/yaml.js',\n 'regenerator-runtime/runtime.js',\n 'slash',\n 'stable',\n 'store2',\n 'synchronous-promise',\n 'telejson',\n 'ts-dedent',\n 'unfetch',\n 'util-deprecate',\n 'uuid-browser/v4',\n 'vue',\n 'warning',\n];\n\n/**\n * Helper function which allows us to `filter` with an async predicate. Uses Promise.all for performance.\n */\nconst asyncFilter = async (arr: string[], predicate: (val: string) => Promise<boolean>) =>\n Promise.all(arr.map(predicate)).then((results) => arr.filter((_v, index) => results[index]));\n\nexport async function getOptimizeDeps(\n config: UserConfig & { configFile: false; root: string },\n options: ExtendedOptions\n) {\n const { root } = config;\n const absoluteStories = await listStories(options);\n const stories = absoluteStories.map((storyPath) => normalizePath(path.relative(root, storyPath)));\n const resolvedConfig = await resolveConfig(config, 'serve', 'development');\n\n // This function converts ids which might include ` > ` to a real path, if it exists on disk.\n // See https://github.com/vitejs/vite/blob/67d164392e8e9081dc3f0338c4b4b8eea6c5f7da/packages/vite/src/node/optimizer/index.ts#L182-L199\n const resolve = resolvedConfig.createResolver({ asSrc: false });\n const include = await asyncFilter(INCLUDE_CANDIDATES, async (id) => Boolean(await resolve(id)));\n\n return {\n // We don't need to resolve the glob since vite supports globs for entries.\n entries: stories,\n // We need Vite to precompile these dependencies, because they contain non-ESM code that would break\n // if we served it directly to the browser.\n include,\n };\n}\n"]}
1
+ {"version":3,"file":"optimizeDeps.js","sourceRoot":"","sources":["../optimizeDeps.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport { normalizePath, resolveConfig, UserConfig } from 'vite';\nimport { listStories } from './list-stories';\nimport semver from 'semver';\n\nimport type { ExtendedOptions } from './types';\n\nconst INCLUDE_CANDIDATES = [\n '@base2/pretty-print-object',\n '@emotion/core',\n '@emotion/is-prop-valid',\n '@emotion/styled',\n '@mdx-js/react',\n '@storybook/csf',\n 'acorn-jsx',\n 'acorn-walk',\n 'acorn',\n 'airbnb-js-shims',\n 'ansi-to-html',\n 'axe-core',\n 'color-convert',\n 'deep-object-diff',\n 'doctrine',\n 'emotion-theming',\n 'escodegen',\n 'estraverse',\n 'fast-deep-equal',\n 'global',\n 'html-tags',\n 'isobject',\n 'jest-mock',\n 'loader-utils',\n 'lodash/cloneDeep',\n 'lodash/isFunction',\n 'lodash/isPlainObject',\n 'lodash/isString',\n 'lodash/mapKeys',\n 'lodash/mapValues',\n 'lodash/pick',\n 'lodash/pickBy',\n 'lodash/startCase',\n 'lodash/throttle',\n 'lodash/uniq',\n 'markdown-to-jsx',\n 'memoizerific',\n 'overlayscrollbars',\n 'polished',\n 'prettier/parser-babel',\n 'prettier/parser-flow',\n 'prettier/parser-typescript',\n 'prop-types',\n 'qs',\n 'react-dom',\n 'react-dom/client',\n 'react-fast-compare',\n 'react-is',\n 'react-textarea-autosize',\n 'react',\n 'refractor/core',\n 'refractor/lang/bash.js',\n 'refractor/lang/css.js',\n 'refractor/lang/graphql.js',\n 'refractor/lang/js-extras.js',\n 'refractor/lang/json.js',\n 'refractor/lang/jsx.js',\n 'refractor/lang/markdown.js',\n 'refractor/lang/markup.js',\n 'refractor/lang/tsx.js',\n 'refractor/lang/typescript.js',\n 'refractor/lang/yaml.js',\n 'regenerator-runtime/runtime.js',\n 'slash',\n 'stable',\n 'store2',\n 'synchronous-promise',\n 'telejson',\n 'ts-dedent',\n 'unfetch',\n 'util-deprecate',\n 'uuid-browser/v4',\n 'vue',\n 'warning',\n];\n\n/**\n * Helper function which allows us to `filter` with an async predicate. Uses Promise.all for performance.\n */\nconst asyncFilter = async (arr: string[], predicate: (val: string) => Promise<boolean>) =>\n Promise.all(arr.map(predicate)).then((results) => arr.filter((_v, index) => results[index]));\n\nexport async function getOptimizeDeps(\n config: UserConfig & { configFile: false; root: string },\n options: ExtendedOptions\n) {\n const { root } = config;\n const absoluteStories = await listStories(options);\n const stories = absoluteStories.map((storyPath) => normalizePath(path.relative(root, storyPath)));\n const resolvedConfig = await resolveConfig(config, 'serve', 'development');\n\n // This function converts ids which might include ` > ` to a real path, if it exists on disk.\n // See https://github.com/vitejs/vite/blob/67d164392e8e9081dc3f0338c4b4b8eea6c5f7da/packages/vite/src/node/optimizer/index.ts#L182-L199\n const resolve = resolvedConfig.createResolver({ asSrc: false });\n const include = await asyncFilter(INCLUDE_CANDIDATES, async (id) => Boolean(await resolve(id)));\n\n // We can exclude some packages which otherwise are optimized\n const exclude = [\n '@storybook/addon-docs',\n '@storybook/client-api',\n '@storybook/client-logger',\n '@storybook/preview-web',\n '@storybook/channel-postmessage',\n '@storybook/channel-websocket',\n '@storybook/addons',\n ];\n // This is necessary to support react < 18 with new versions of @storybook/react that support react 18.\n // TODO: narrow this down to just framework === 'react'. But causes a vue dev start problem in this monorepo.\n try {\n require.resolve('react-dom/client', { paths: [config.root] });\n } catch (e) {\n if (isNodeError(e) && e.code === 'MODULE_NOT_FOUND') {\n exclude.push('react-dom/client');\n }\n }\n // Depending on the user's storybook version, we can also exclude the framework from prebundling\n // See https://github.com/storybookjs/storybook/pull/17875\n const { frameworkPath, framework } = options;\n const frameworkPackageName = frameworkPath || `@storybook/${framework}`;\n const sbVersion: string | undefined = (await import(`${frameworkPackageName}/package.json`))?.version;\n if (sbVersion && semver.gte(sbVersion, '6.5.0-alpha.58', { includePrerelease: true })) {\n exclude.push(frameworkPackageName);\n } else {\n include.push(frameworkPackageName);\n }\n\n return {\n // We don't need to resolve the glob since vite supports globs for entries.\n entries: stories,\n // We need Vite to precompile these dependencies, because they contain non-ESM code that would break\n // if we served it directly to the browser.\n include,\n // In some cases we need to prevent deps from being pre-bundled\n exclude,\n };\n}\n\n// Refines an error received from 'catch' to be a NodeJS exception\nconst isNodeError = (error: unknown): error is NodeJS.ErrnoException => error instanceof Error;\n"]}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * This is heavily based on the react-docgen `displayNameHandler`
3
+ * (https://github.com/reactjs/react-docgen/blob/26c90c0dd105bf83499a83826f2a6ff7a724620d/src/handlers/displayNameHandler.ts)
4
+ * but instead defines an `actualName` property on the generated docs that is taken first from the component's actual name.
5
+ * This addresses an issue where the name that the generated docs are stored under is incorrectly named with the `displayName`
6
+ * and not the component's actual name.
7
+ *
8
+ * This is inspired by `actualNameHandler` from https://github.com/storybookjs/babel-plugin-react-docgen, but is modified
9
+ * directly from displayNameHandler, using the same approach as babel-plugin-react-docgen.
10
+ */
11
+ import type { NodePath } from 'ast-types/lib/node-path';
12
+ import type { Importer } from 'react-docgen/dist/parse';
13
+ import type Documentation from 'react-docgen/lib/Documentation';
14
+ export default function actualNameHandler(documentation: Documentation, path: NodePath, importer: Importer): void;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ /**
3
+ * This is heavily based on the react-docgen `displayNameHandler`
4
+ * (https://github.com/reactjs/react-docgen/blob/26c90c0dd105bf83499a83826f2a6ff7a724620d/src/handlers/displayNameHandler.ts)
5
+ * but instead defines an `actualName` property on the generated docs that is taken first from the component's actual name.
6
+ * This addresses an issue where the name that the generated docs are stored under is incorrectly named with the `displayName`
7
+ * and not the component's actual name.
8
+ *
9
+ * This is inspired by `actualNameHandler` from https://github.com/storybookjs/babel-plugin-react-docgen, but is modified
10
+ * directly from displayNameHandler, using the same approach as babel-plugin-react-docgen.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ const ast_types_1 = require("ast-types");
14
+ const utils_1 = require("react-docgen/dist/utils");
15
+ function actualNameHandler(documentation, path, importer) {
16
+ if (ast_types_1.namedTypes.ClassDeclaration.check(path.node) || ast_types_1.namedTypes.FunctionDeclaration.check(path.node)) {
17
+ documentation.set('actualName', (0, utils_1.getNameOrValue)(path.get('id')));
18
+ }
19
+ else if (ast_types_1.namedTypes.ArrowFunctionExpression.check(path.node) ||
20
+ ast_types_1.namedTypes.FunctionExpression.check(path.node) ||
21
+ (0, utils_1.isReactForwardRefCall)(path, importer)) {
22
+ let currentPath = path;
23
+ while (currentPath.parent) {
24
+ if (ast_types_1.namedTypes.VariableDeclarator.check(currentPath.parent.node)) {
25
+ documentation.set('actualName', (0, utils_1.getNameOrValue)(currentPath.parent.get('id')));
26
+ return;
27
+ }
28
+ else if (ast_types_1.namedTypes.AssignmentExpression.check(currentPath.parent.node)) {
29
+ const leftPath = currentPath.parent.get('left');
30
+ if (ast_types_1.namedTypes.Identifier.check(leftPath.node) || ast_types_1.namedTypes.Literal.check(leftPath.node)) {
31
+ documentation.set('actualName', (0, utils_1.getNameOrValue)(leftPath));
32
+ return;
33
+ }
34
+ }
35
+ currentPath = currentPath.parent;
36
+ }
37
+ // Could not find an actual name
38
+ documentation.set('actualName', '');
39
+ }
40
+ return;
41
+ }
42
+ exports.default = actualNameHandler;
43
+ //# sourceMappingURL=actualNameHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actualNameHandler.js","sourceRoot":"","sources":["../../../plugins/docgen-handlers/actualNameHandler.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;AAEH,yCAA4C;AAE5C,mDAAgF;AAMhF,SAAwB,iBAAiB,CAAC,aAA4B,EAAE,IAAc,EAAE,QAAkB;IACxG,IAAI,sBAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,sBAAC,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACjF,aAAa,CAAC,GAAG,CAAC,YAAY,EAAE,IAAA,sBAAc,EAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KACjE;SAAM,IACL,sBAAC,CAAC,uBAAuB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QAC1C,sBAAC,CAAC,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QACrC,IAAA,6BAAqB,EAAC,IAAI,EAAE,QAAQ,CAAC,EACrC;QACA,IAAI,WAAW,GAAG,IAAI,CAAC;QACvB,OAAO,WAAW,CAAC,MAAM,EAAE;YACzB,IAAI,sBAAC,CAAC,kBAAkB,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;gBACvD,aAAa,CAAC,GAAG,CAAC,YAAY,EAAE,IAAA,sBAAc,EAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAC9E,OAAO;aACR;iBAAM,IAAI,sBAAC,CAAC,oBAAoB,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;gBAChE,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAChD,IAAI,sBAAC,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,sBAAC,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;oBACvE,aAAa,CAAC,GAAG,CAAC,YAAY,EAAE,IAAA,sBAAc,EAAC,QAAQ,CAAC,CAAC,CAAC;oBAC1D,OAAO;iBACR;aACF;YACD,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC;SAClC;QACD,gCAAgC;QAChC,aAAa,CAAC,GAAG,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;KACrC;IACD,OAAO;AACT,CAAC;AA1BD,oCA0BC","sourcesContent":["/**\n * This is heavily based on the react-docgen `displayNameHandler`\n * (https://github.com/reactjs/react-docgen/blob/26c90c0dd105bf83499a83826f2a6ff7a724620d/src/handlers/displayNameHandler.ts)\n * but instead defines an `actualName` property on the generated docs that is taken first from the component's actual name.\n * This addresses an issue where the name that the generated docs are stored under is incorrectly named with the `displayName`\n * and not the component's actual name.\n *\n * This is inspired by `actualNameHandler` from https://github.com/storybookjs/babel-plugin-react-docgen, but is modified\n * directly from displayNameHandler, using the same approach as babel-plugin-react-docgen.\n */\n\nimport { namedTypes as t } from 'ast-types';\nimport type { NodePath } from 'ast-types/lib/node-path';\nimport { getNameOrValue, isReactForwardRefCall } from 'react-docgen/dist/utils';\n// import { getNameOrValue, isReactForwardRefCall } from 'react-docgen/lib/utils';\nimport type { Importer } from 'react-docgen/dist/parse';\n// import type { Importer } from 'react-docgen/lib/parse';\nimport type Documentation from 'react-docgen/lib/Documentation';\n\nexport default function actualNameHandler(documentation: Documentation, path: NodePath, importer: Importer): void {\n if (t.ClassDeclaration.check(path.node) || t.FunctionDeclaration.check(path.node)) {\n documentation.set('actualName', getNameOrValue(path.get('id')));\n } else if (\n t.ArrowFunctionExpression.check(path.node) ||\n t.FunctionExpression.check(path.node) ||\n isReactForwardRefCall(path, importer)\n ) {\n let currentPath = path;\n while (currentPath.parent) {\n if (t.VariableDeclarator.check(currentPath.parent.node)) {\n documentation.set('actualName', getNameOrValue(currentPath.parent.get('id')));\n return;\n } else if (t.AssignmentExpression.check(currentPath.parent.node)) {\n const leftPath = currentPath.parent.get('left');\n if (t.Identifier.check(leftPath.node) || t.Literal.check(leftPath.node)) {\n documentation.set('actualName', getNameOrValue(leftPath));\n return;\n }\n }\n currentPath = currentPath.parent;\n }\n // Could not find an actual name\n documentation.set('actualName', '');\n }\n return;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import type { Plugin } from 'vite';
2
+ export declare function reactDocgen(): Plugin;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.reactDocgen = void 0;
7
+ const react_docgen_1 = require("react-docgen");
8
+ const magic_string_1 = __importDefault(require("magic-string"));
9
+ const actualNameHandler_1 = __importDefault(require("./docgen-handlers/actualNameHandler"));
10
+ // TODO: None of these are able to be overridden, so `default` is aspirational here.
11
+ const defaultHandlers = Object.values(react_docgen_1.handlers).map((handler) => handler);
12
+ const defaultResolver = react_docgen_1.resolver.findAllExportedComponentDefinitions;
13
+ const defaultImporter = react_docgen_1.importers.makeFsImporter();
14
+ const handlers = [...defaultHandlers, actualNameHandler_1.default];
15
+ function reactDocgen() {
16
+ return {
17
+ name: 'react-docgen',
18
+ enforce: 'pre',
19
+ async transform(src, id) {
20
+ // JSX syntax is only allowed in .tsx and .jsx, but components can technically be created without JSX
21
+ if (/\.(mjs|tsx?|jsx?)$/.test(id)) {
22
+ try {
23
+ // Since we're using `findAllExportedComponentDefinitions`, this will always be an array.
24
+ const docgenResults = (0, react_docgen_1.parse)(src, defaultResolver, handlers, { importer: defaultImporter, filename: id });
25
+ const s = new magic_string_1.default(src);
26
+ docgenResults.forEach((info) => {
27
+ const { actualName, ...docgenInfo } = info;
28
+ if (actualName) {
29
+ const docNode = JSON.stringify(docgenInfo);
30
+ s.append(`;${actualName}.__docgenInfo=${docNode}`);
31
+ }
32
+ });
33
+ return {
34
+ code: s.toString(),
35
+ map: s.generateMap(),
36
+ };
37
+ }
38
+ catch (e) {
39
+ // Usually this is just an error from react-docgen that it couldn't find a component
40
+ // Only uncomment for troubleshooting
41
+ // console.error(e);
42
+ }
43
+ }
44
+ },
45
+ };
46
+ }
47
+ exports.reactDocgen = reactDocgen;
48
+ //# sourceMappingURL=react-docgen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-docgen.js","sourceRoot":"","sources":["../../plugins/react-docgen.ts"],"names":[],"mappings":";;;;;;AAAA,+CAKsB;AAEtB,gEAAuC;AAEvC,4FAAoE;AAIpE,oFAAoF;AACpF,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,uBAAc,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;AAChF,MAAM,eAAe,GAAG,uBAAc,CAAC,mCAAmC,CAAC;AAC3E,MAAM,eAAe,GAAG,wBAAe,CAAC,cAAc,EAAE,CAAC;AACzD,MAAM,QAAQ,GAAG,CAAC,GAAG,eAAe,EAAE,2BAAiB,CAAC,CAAC;AAEzD,SAAgB,WAAW;IACzB,OAAO;QACL,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,KAAK;QACd,KAAK,CAAC,SAAS,CAAC,GAAW,EAAE,EAAU;YACrC,qGAAqG;YACrG,IAAI,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;gBACjC,IAAI;oBACF,yFAAyF;oBACzF,MAAM,aAAa,GAAG,IAAA,oBAAK,EAAC,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,EAAE,EAAE,CAC3F,CAAC;oBACb,MAAM,CAAC,GAAG,IAAI,sBAAW,CAAC,GAAG,CAAC,CAAC;oBAE/B,aAAa,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;wBAC7B,MAAM,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,GAAG,IAAI,CAAC;wBAC3C,IAAI,UAAU,EAAE;4BACd,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;4BAC3C,CAAC,CAAC,MAAM,CAAC,IAAI,UAAU,iBAAiB,OAAO,EAAE,CAAC,CAAC;yBACpD;oBACH,CAAC,CAAC,CAAC;oBAEH,OAAO;wBACL,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE;wBAClB,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE;qBACrB,CAAC;iBACH;gBAAC,OAAO,CAAC,EAAE;oBACV,oFAAoF;oBACpF,qCAAqC;oBACrC,oBAAoB;iBACrB;aACF;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAjCD,kCAiCC","sourcesContent":["import {\n parse,\n handlers as docgenHandlers,\n resolver as docgenResolver,\n importers as docgenImporters,\n} from 'react-docgen';\nimport type { DocumentationObject } from 'react-docgen/lib/Documentation';\nimport MagicString from 'magic-string';\nimport type { Plugin } from 'vite';\nimport actualNameHandler from './docgen-handlers/actualNameHandler';\n\ntype DocObj = DocumentationObject & { actualName: string };\n\n// TODO: None of these are able to be overridden, so `default` is aspirational here.\nconst defaultHandlers = Object.values(docgenHandlers).map((handler) => handler);\nconst defaultResolver = docgenResolver.findAllExportedComponentDefinitions;\nconst defaultImporter = docgenImporters.makeFsImporter();\nconst handlers = [...defaultHandlers, actualNameHandler];\n\nexport function reactDocgen(): Plugin {\n return {\n name: 'react-docgen',\n enforce: 'pre',\n async transform(src: string, id: string) {\n // JSX syntax is only allowed in .tsx and .jsx, but components can technically be created without JSX\n if (/\\.(mjs|tsx?|jsx?)$/.test(id)) {\n try {\n // Since we're using `findAllExportedComponentDefinitions`, this will always be an array.\n const docgenResults = parse(src, defaultResolver, handlers, { importer: defaultImporter, filename: id }) as\n | DocObj[];\n const s = new MagicString(src);\n\n docgenResults.forEach((info) => {\n const { actualName, ...docgenInfo } = info;\n if (actualName) {\n const docNode = JSON.stringify(docgenInfo);\n s.append(`;${actualName}.__docgenInfo=${docNode}`);\n }\n });\n\n return {\n code: s.toString(),\n map: s.generateMap(),\n };\n } catch (e) {\n // Usually this is just an error from react-docgen that it couldn't find a component\n // Only uncomment for troubleshooting\n // console.error(e);\n }\n }\n },\n };\n}\n"]}
@@ -1,4 +1,2 @@
1
- export declare function vueDocgen(): {
2
- name: string;
3
- transform(src: string, id: string): Promise<string | undefined>;
4
- };
1
+ import type { Plugin } from 'vite';
2
+ export declare function vueDocgen(): Plugin;
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.vueDocgen = void 0;
4
7
  const vue_docgen_api_1 = require("vue-docgen-api");
8
+ const magic_string_1 = __importDefault(require("magic-string"));
5
9
  function vueDocgen() {
6
10
  return {
7
11
  name: 'vue-docgen',
@@ -9,7 +13,12 @@ function vueDocgen() {
9
13
  if (/\.(vue)$/.test(id)) {
10
14
  const metaData = await (0, vue_docgen_api_1.parse)(id);
11
15
  const metaSource = JSON.stringify(metaData);
12
- return `${src};_sfc_main.__docgenInfo = ${metaSource}`;
16
+ const s = new magic_string_1.default(src);
17
+ s.append(`;_sfc_main.__docgenInfo = ${metaSource}`);
18
+ return {
19
+ code: s.toString(),
20
+ map: s.generateMap(),
21
+ };
13
22
  }
14
23
  },
15
24
  };
@@ -1 +1 @@
1
- {"version":3,"file":"vue-docgen.js","sourceRoot":"","sources":["../../plugins/vue-docgen.ts"],"names":[],"mappings":";;;AAAA,mDAAuC;AAEvC,SAAgB,SAAS;IACvB,OAAO;QACL,IAAI,EAAE,YAAY;QAElB,KAAK,CAAC,SAAS,CAAC,GAAW,EAAE,EAAU;YACrC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;gBACvB,MAAM,QAAQ,GAAG,MAAM,IAAA,sBAAK,EAAC,EAAE,CAAC,CAAC;gBACjC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;gBAE5C,OAAO,GAAG,GAAG,6BAA6B,UAAU,EAAE,CAAC;aACxD;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAbD,8BAaC","sourcesContent":["import { parse } from 'vue-docgen-api';\n\nexport function vueDocgen() {\n return {\n name: 'vue-docgen',\n\n async transform(src: string, id: string) {\n if (/\\.(vue)$/.test(id)) {\n const metaData = await parse(id);\n const metaSource = JSON.stringify(metaData);\n\n return `${src};_sfc_main.__docgenInfo = ${metaSource}`;\n }\n },\n };\n}\n"]}
1
+ {"version":3,"file":"vue-docgen.js","sourceRoot":"","sources":["../../plugins/vue-docgen.ts"],"names":[],"mappings":";;;;;;AAAA,mDAAuC;AAEvC,gEAAuC;AAEvC,SAAgB,SAAS;IACvB,OAAO;QACL,IAAI,EAAE,YAAY;QAElB,KAAK,CAAC,SAAS,CAAC,GAAW,EAAE,EAAU;YACrC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;gBACvB,MAAM,QAAQ,GAAG,MAAM,IAAA,sBAAK,EAAC,EAAE,CAAC,CAAC;gBACjC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;gBAC5C,MAAM,CAAC,GAAG,IAAI,sBAAW,CAAC,GAAG,CAAC,CAAC;gBAC/B,CAAC,CAAC,MAAM,CAAC,6BAA6B,UAAU,EAAE,CAAC,CAAC;gBAEpD,OAAO;oBACL,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE;oBAClB,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE;iBACrB,CAAC;aACH;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAlBD,8BAkBC","sourcesContent":["import { parse } from 'vue-docgen-api';\nimport type { Plugin } from 'vite';\nimport MagicString from 'magic-string';\n\nexport function vueDocgen(): Plugin {\n return {\n name: 'vue-docgen',\n\n async transform(src: string, id: string) {\n if (/\\.(vue)$/.test(id)) {\n const metaData = await parse(id);\n const metaSource = JSON.stringify(metaData);\n const s = new MagicString(src);\n s.append(`;_sfc_main.__docgenInfo = ${metaSource}`);\n\n return {\n code: s.toString(),\n map: s.generateMap(),\n };\n }\n },\n };\n}\n"]}
@@ -2,6 +2,7 @@ import { Plugin } from 'vite';
2
2
  import type { UserConfig } from 'vite';
3
3
  import type { ExtendedOptions } from './types';
4
4
  export declare type PluginConfigType = 'build' | 'development';
5
+ export declare function readPackageJson(): Record<string, any> | false;
5
6
  export declare function commonConfig(options: ExtendedOptions, _type: PluginConfigType): Promise<UserConfig & {
6
7
  configFile: false;
7
8
  root: string;
@@ -18,15 +18,28 @@ var __importStar = (this && this.__importStar) || function (mod) {
18
18
  __setModuleDefault(result, mod);
19
19
  return result;
20
20
  };
21
+ var __importDefault = (this && this.__importDefault) || function (mod) {
22
+ return (mod && mod.__esModule) ? mod : { "default": mod };
23
+ };
21
24
  Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.pluginConfig = exports.commonConfig = void 0;
25
+ exports.pluginConfig = exports.commonConfig = exports.readPackageJson = void 0;
23
26
  const path = __importStar(require("path"));
27
+ const fs_1 = __importDefault(require("fs"));
24
28
  const envs_1 = require("./envs");
25
29
  const mock_core_js_1 = require("./mock-core-js");
26
30
  const code_generator_plugin_1 = require("./code-generator-plugin");
27
31
  const inject_export_order_plugin_1 = require("./inject-export-order-plugin");
28
32
  const mdx_plugin_1 = require("./mdx-plugin");
29
33
  const source_loader_plugin_1 = require("./source-loader-plugin");
34
+ function readPackageJson() {
35
+ const packageJsonPath = path.resolve('package.json');
36
+ if (!fs_1.default.existsSync(packageJsonPath)) {
37
+ return false;
38
+ }
39
+ const jsonContent = fs_1.default.readFileSync(packageJsonPath, 'utf8');
40
+ return JSON.parse(jsonContent);
41
+ }
42
+ exports.readPackageJson = readPackageJson;
30
43
  // Vite config that is common to development and production mode
31
44
  async function commonConfig(options, _type) {
32
45
  const { framework } = options;
@@ -48,6 +61,7 @@ async function commonConfig(options, _type) {
48
61
  }
49
62
  exports.commonConfig = commonConfig;
50
63
  async function pluginConfig(options, _type) {
64
+ var _a, _b;
51
65
  const { framework, presets } = options;
52
66
  const svelteOptions = await presets.apply('svelteOptions', {}, options);
53
67
  const plugins = [
@@ -106,8 +120,8 @@ async function pluginConfig(options, _type) {
106
120
  const { reactDocgen, reactDocgenTypescriptOptions } = await presets.apply('typescript', {});
107
121
  let typescriptPresent;
108
122
  try {
109
- require.resolve('typescript');
110
- typescriptPresent = true;
123
+ const pkgJson = readPackageJson();
124
+ typescriptPresent = pkgJson && (((_a = pkgJson === null || pkgJson === void 0 ? void 0 : pkgJson.devDependencies) === null || _a === void 0 ? void 0 : _a.typescript) || ((_b = pkgJson === null || pkgJson === void 0 ? void 0 : pkgJson.dependencies) === null || _b === void 0 ? void 0 : _b.typescript));
111
125
  }
112
126
  catch (e) {
113
127
  typescriptPresent = false;
@@ -115,6 +129,11 @@ async function pluginConfig(options, _type) {
115
129
  if (reactDocgen === 'react-docgen-typescript' && typescriptPresent) {
116
130
  plugins.push(require('@joshwooding/vite-plugin-react-docgen-typescript').default(reactDocgenTypescriptOptions));
117
131
  }
132
+ else if (reactDocgen) {
133
+ const { reactDocgen } = await Promise.resolve().then(() => __importStar(require('./plugins/react-docgen')));
134
+ // Needs to run before the react plugin, so add to the front
135
+ plugins.unshift(reactDocgen());
136
+ }
118
137
  }
119
138
  if (framework === 'glimmerx') {
120
139
  const plugin = require('vite-plugin-glimmerx/index.cjs');
@@ -1 +1 @@
1
- {"version":3,"file":"vite-config.js","sourceRoot":"","sources":["../vite-config.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport { Plugin } from 'vite';\nimport { allowedEnvPrefix as envPrefix } from './envs';\nimport { TypescriptConfig } from '@storybook/core-common';\nimport { mockCoreJs } from './mock-core-js';\nimport { codeGeneratorPlugin } from './code-generator-plugin';\nimport { injectExportOrderPlugin } from './inject-export-order-plugin';\nimport { mdxPlugin } from './mdx-plugin';\nimport { sourceLoaderPlugin } from './source-loader-plugin';\n\nimport type { UserConfig } from 'vite';\nimport type { ExtendedOptions } from './types';\n\nexport type PluginConfigType = 'build' | 'development';\n\n// Vite config that is common to development and production mode\nexport async function commonConfig(\n options: ExtendedOptions,\n _type: PluginConfigType\n): Promise<UserConfig & { configFile: false; root: string }> {\n const { framework } = options;\n\n return {\n configFile: false,\n root: path.resolve(options.configDir, '..'),\n cacheDir: 'node_modules/.vite-storybook',\n envPrefix,\n define: {},\n resolve:\n framework === 'vue3'\n ? {\n alias: {\n vue: 'vue/dist/vue.esm-bundler.js',\n },\n }\n : {},\n plugins: await pluginConfig(options, _type),\n };\n}\n\nexport async function pluginConfig(options: ExtendedOptions, _type: PluginConfigType) {\n const { framework, presets } = options;\n const svelteOptions = await presets.apply('svelteOptions', {}, options);\n\n const plugins = [\n codeGeneratorPlugin(options),\n mockCoreJs(),\n sourceLoaderPlugin(),\n mdxPlugin(),\n injectExportOrderPlugin,\n ] as Plugin[];\n if (framework === 'vue' || framework === 'vue3') {\n try {\n const vuePlugin = require('@vitejs/plugin-vue');\n plugins.push(vuePlugin());\n const { vueDocgen } = await import('./plugins/vue-docgen');\n plugins.push(vueDocgen());\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'MODULE_NOT_FOUND') {\n throw new Error(\n '@storybook/builder-vite requires @vitejs/plugin-vue to be installed ' +\n 'when using @storybook/vue or @storybook/vue3.' +\n ' Please install it and start storybook again.'\n );\n }\n throw err;\n }\n }\n if (framework === 'svelte') {\n try {\n const sveltePlugin = require('@sveltejs/vite-plugin-svelte').svelte;\n plugins.push(sveltePlugin(svelteOptions));\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'MODULE_NOT_FOUND') {\n throw new Error(\n '@storybook/builder-vite requires @sveltejs/vite-plugin-svelte to be installed' +\n ' when using @storybook/svelte.' +\n ' Please install it and start storybook again.'\n );\n }\n throw err;\n }\n\n try {\n const csfPlugin = require('./svelte/csf-plugin').default;\n plugins.push(csfPlugin(svelteOptions));\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'MODULE_NOT_FOUND') {\n throw new Error(\n '@storybook/builder-vite requires @storybook/addon-svelte-csf to be installed when using @storybook/svelte.' +\n ' Please install it and start storybook again.'\n );\n }\n throw err;\n }\n }\n\n if (framework === 'react') {\n plugins.push(\n require('@vitejs/plugin-react')({\n // Do not treat story files as HMR boundaries, storybook itself needs to handle them.\n exclude: [/\\.stories\\.([tj])sx?$/, /node_modules/],\n })\n );\n\n const { reactDocgen, reactDocgenTypescriptOptions } = await presets.apply('typescript', {} as TypescriptConfig);\n\n let typescriptPresent;\n\n try {\n require.resolve('typescript');\n typescriptPresent = true;\n } catch (e) {\n typescriptPresent = false;\n }\n\n if (reactDocgen === 'react-docgen-typescript' && typescriptPresent) {\n plugins.push(require('@joshwooding/vite-plugin-react-docgen-typescript').default(reactDocgenTypescriptOptions));\n }\n }\n\n if (framework === 'glimmerx') {\n const plugin = require('vite-plugin-glimmerx/index.cjs');\n plugins.push(plugin.default());\n }\n\n return plugins;\n}\n"]}
1
+ {"version":3,"file":"vite-config.js","sourceRoot":"","sources":["../vite-config.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport fs from 'fs';\nimport { Plugin } from 'vite';\nimport { allowedEnvPrefix as envPrefix } from './envs';\nimport { TypescriptConfig } from '@storybook/core-common';\nimport { mockCoreJs } from './mock-core-js';\nimport { codeGeneratorPlugin } from './code-generator-plugin';\nimport { injectExportOrderPlugin } from './inject-export-order-plugin';\nimport { mdxPlugin } from './mdx-plugin';\nimport { sourceLoaderPlugin } from './source-loader-plugin';\n\nimport type { UserConfig } from 'vite';\nimport type { ExtendedOptions } from './types';\n\nexport type PluginConfigType = 'build' | 'development';\n\nexport function readPackageJson(): Record<string, any> | false {\n const packageJsonPath = path.resolve('package.json');\n if (!fs.existsSync(packageJsonPath)) {\n return false;\n }\n\n const jsonContent = fs.readFileSync(packageJsonPath, 'utf8');\n return JSON.parse(jsonContent);\n}\n\n// Vite config that is common to development and production mode\nexport async function commonConfig(\n options: ExtendedOptions,\n _type: PluginConfigType\n): Promise<UserConfig & { configFile: false; root: string }> {\n const { framework } = options;\n\n return {\n configFile: false,\n root: path.resolve(options.configDir, '..'),\n cacheDir: 'node_modules/.vite-storybook',\n envPrefix,\n define: {},\n resolve:\n framework === 'vue3'\n ? {\n alias: {\n vue: 'vue/dist/vue.esm-bundler.js',\n },\n }\n : {},\n plugins: await pluginConfig(options, _type),\n };\n}\n\nexport async function pluginConfig(options: ExtendedOptions, _type: PluginConfigType) {\n const { framework, presets } = options;\n const svelteOptions = await presets.apply('svelteOptions', {}, options);\n\n const plugins = [\n codeGeneratorPlugin(options),\n mockCoreJs(),\n sourceLoaderPlugin(),\n mdxPlugin(),\n injectExportOrderPlugin,\n ] as Plugin[];\n if (framework === 'vue' || framework === 'vue3') {\n try {\n const vuePlugin = require('@vitejs/plugin-vue');\n plugins.push(vuePlugin());\n const { vueDocgen } = await import('./plugins/vue-docgen');\n plugins.push(vueDocgen());\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'MODULE_NOT_FOUND') {\n throw new Error(\n '@storybook/builder-vite requires @vitejs/plugin-vue to be installed ' +\n 'when using @storybook/vue or @storybook/vue3.' +\n ' Please install it and start storybook again.'\n );\n }\n throw err;\n }\n }\n if (framework === 'svelte') {\n try {\n const sveltePlugin = require('@sveltejs/vite-plugin-svelte').svelte;\n plugins.push(sveltePlugin(svelteOptions));\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'MODULE_NOT_FOUND') {\n throw new Error(\n '@storybook/builder-vite requires @sveltejs/vite-plugin-svelte to be installed' +\n ' when using @storybook/svelte.' +\n ' Please install it and start storybook again.'\n );\n }\n throw err;\n }\n\n try {\n const csfPlugin = require('./svelte/csf-plugin').default;\n plugins.push(csfPlugin(svelteOptions));\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'MODULE_NOT_FOUND') {\n throw new Error(\n '@storybook/builder-vite requires @storybook/addon-svelte-csf to be installed when using @storybook/svelte.' +\n ' Please install it and start storybook again.'\n );\n }\n throw err;\n }\n }\n\n if (framework === 'react') {\n plugins.push(\n require('@vitejs/plugin-react')({\n // Do not treat story files as HMR boundaries, storybook itself needs to handle them.\n exclude: [/\\.stories\\.([tj])sx?$/, /node_modules/],\n })\n );\n\n const { reactDocgen, reactDocgenTypescriptOptions } = await presets.apply('typescript', {} as TypescriptConfig);\n\n let typescriptPresent;\n\n try {\n const pkgJson = readPackageJson();\n typescriptPresent = pkgJson && (pkgJson?.devDependencies?.typescript || pkgJson?.dependencies?.typescript);\n } catch (e) {\n typescriptPresent = false;\n }\n\n if (reactDocgen === 'react-docgen-typescript' && typescriptPresent) {\n plugins.push(require('@joshwooding/vite-plugin-react-docgen-typescript').default(reactDocgenTypescriptOptions));\n } else if (reactDocgen) {\n const { reactDocgen } = await import('./plugins/react-docgen');\n // Needs to run before the react plugin, so add to the front\n plugins.unshift(reactDocgen());\n }\n }\n\n if (framework === 'glimmerx') {\n const plugin = require('vite-plugin-glimmerx/index.cjs');\n plugins.push(plugin.default());\n }\n\n return plugins;\n}\n"]}
@@ -0,0 +1,3 @@
1
+ // This file is to work around https://github.com/vitejs/vite/issues/6007
2
+ // For react < 18 projects, where `react-dom/client` does not exist, yet is
3
+ // conditionally imported by @storybook/react.
package/optimizeDeps.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as path from 'path';
2
2
  import { normalizePath, resolveConfig, UserConfig } from 'vite';
3
3
  import { listStories } from './list-stories';
4
+ import semver from 'semver';
4
5
 
5
6
  import type { ExtendedOptions } from './types';
6
7
 
@@ -10,20 +11,7 @@ const INCLUDE_CANDIDATES = [
10
11
  '@emotion/is-prop-valid',
11
12
  '@emotion/styled',
12
13
  '@mdx-js/react',
13
- '@storybook/addon-docs > acorn-jsx',
14
- '@storybook/addon-docs',
15
- '@storybook/addons',
16
- '@storybook/channel-postmessage',
17
- '@storybook/channel-websocket',
18
- '@storybook/client-api',
19
- '@storybook/client-logger',
20
- '@storybook/core/client',
21
14
  '@storybook/csf',
22
- '@storybook/preview-web',
23
- '@storybook/react > acorn-jsx',
24
- '@storybook/react',
25
- '@storybook/svelte',
26
- '@storybook/vue3',
27
15
  'acorn-jsx',
28
16
  'acorn-walk',
29
17
  'acorn',
@@ -63,6 +51,7 @@ const INCLUDE_CANDIDATES = [
63
51
  'prop-types',
64
52
  'qs',
65
53
  'react-dom',
54
+ 'react-dom/client',
66
55
  'react-fast-compare',
67
56
  'react-is',
68
57
  'react-textarea-autosize',
@@ -113,11 +102,46 @@ export async function getOptimizeDeps(
113
102
  const resolve = resolvedConfig.createResolver({ asSrc: false });
114
103
  const include = await asyncFilter(INCLUDE_CANDIDATES, async (id) => Boolean(await resolve(id)));
115
104
 
105
+ // We can exclude some packages which otherwise are optimized
106
+ const exclude = [
107
+ '@storybook/addon-docs',
108
+ '@storybook/client-api',
109
+ '@storybook/client-logger',
110
+ '@storybook/preview-web',
111
+ '@storybook/channel-postmessage',
112
+ '@storybook/channel-websocket',
113
+ '@storybook/addons',
114
+ ];
115
+ // This is necessary to support react < 18 with new versions of @storybook/react that support react 18.
116
+ // TODO: narrow this down to just framework === 'react'. But causes a vue dev start problem in this monorepo.
117
+ try {
118
+ require.resolve('react-dom/client', { paths: [config.root] });
119
+ } catch (e) {
120
+ if (isNodeError(e) && e.code === 'MODULE_NOT_FOUND') {
121
+ exclude.push('react-dom/client');
122
+ }
123
+ }
124
+ // Depending on the user's storybook version, we can also exclude the framework from prebundling
125
+ // See https://github.com/storybookjs/storybook/pull/17875
126
+ const { frameworkPath, framework } = options;
127
+ const frameworkPackageName = frameworkPath || `@storybook/${framework}`;
128
+ const sbVersion: string | undefined = (await import(`${frameworkPackageName}/package.json`))?.version;
129
+ if (sbVersion && semver.gte(sbVersion, '6.5.0-alpha.58', { includePrerelease: true })) {
130
+ exclude.push(frameworkPackageName);
131
+ } else {
132
+ include.push(frameworkPackageName);
133
+ }
134
+
116
135
  return {
117
136
  // We don't need to resolve the glob since vite supports globs for entries.
118
137
  entries: stories,
119
138
  // We need Vite to precompile these dependencies, because they contain non-ESM code that would break
120
139
  // if we served it directly to the browser.
121
140
  include,
141
+ // In some cases we need to prevent deps from being pre-bundled
142
+ exclude,
122
143
  };
123
144
  }
145
+
146
+ // Refines an error received from 'catch' to be a NodeJS exception
147
+ const isNodeError = (error: unknown): error is NodeJS.ErrnoException => error instanceof Error;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/builder-vite",
3
- "version": "0.1.23",
3
+ "version": "0.1.26",
4
4
  "description": "An experimental plugin to run and build Storybooks with Vite",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -13,19 +13,25 @@
13
13
  },
14
14
  "homepage": "https://github.com/storybookjs/builder-vite/#readme",
15
15
  "dependencies": {
16
- "@joshwooding/vite-plugin-react-docgen-typescript": "0.0.2",
16
+ "@joshwooding/vite-plugin-react-docgen-typescript": "0.0.4",
17
17
  "@mdx-js/mdx": "^1.6.22",
18
18
  "@storybook/csf-tools": "^6.3.3",
19
19
  "@storybook/source-loader": "^6.3.12",
20
20
  "@vitejs/plugin-react": "^1.0.8",
21
+ "ast-types": "^0.14.2",
21
22
  "es-module-lexer": "^0.9.3",
22
23
  "glob": "^7.2.0",
23
24
  "glob-promise": "^4.2.0",
25
+ "magic-string": "^0.26.1",
26
+ "react-docgen": "^6.0.0-alpha.0",
27
+ "semver": "^7.3.5",
24
28
  "slash": "^3.0.0",
25
29
  "vite-plugin-mdx": "^3.5.6"
26
30
  },
27
31
  "devDependencies": {
28
32
  "@types/express": "^4.17.13",
33
+ "@types/node": "^17.0.23",
34
+ "@types/semver": "^7.3.9",
29
35
  "vue-docgen-api": "^4.40.0"
30
36
  },
31
37
  "peerDependencies": {
@@ -0,0 +1,46 @@
1
+ /**
2
+ * This is heavily based on the react-docgen `displayNameHandler`
3
+ * (https://github.com/reactjs/react-docgen/blob/26c90c0dd105bf83499a83826f2a6ff7a724620d/src/handlers/displayNameHandler.ts)
4
+ * but instead defines an `actualName` property on the generated docs that is taken first from the component's actual name.
5
+ * This addresses an issue where the name that the generated docs are stored under is incorrectly named with the `displayName`
6
+ * and not the component's actual name.
7
+ *
8
+ * This is inspired by `actualNameHandler` from https://github.com/storybookjs/babel-plugin-react-docgen, but is modified
9
+ * directly from displayNameHandler, using the same approach as babel-plugin-react-docgen.
10
+ */
11
+
12
+ import { namedTypes as t } from 'ast-types';
13
+ import type { NodePath } from 'ast-types/lib/node-path';
14
+ import { getNameOrValue, isReactForwardRefCall } from 'react-docgen/dist/utils';
15
+ // import { getNameOrValue, isReactForwardRefCall } from 'react-docgen/lib/utils';
16
+ import type { Importer } from 'react-docgen/dist/parse';
17
+ // import type { Importer } from 'react-docgen/lib/parse';
18
+ import type Documentation from 'react-docgen/lib/Documentation';
19
+
20
+ export default function actualNameHandler(documentation: Documentation, path: NodePath, importer: Importer): void {
21
+ if (t.ClassDeclaration.check(path.node) || t.FunctionDeclaration.check(path.node)) {
22
+ documentation.set('actualName', getNameOrValue(path.get('id')));
23
+ } else if (
24
+ t.ArrowFunctionExpression.check(path.node) ||
25
+ t.FunctionExpression.check(path.node) ||
26
+ isReactForwardRefCall(path, importer)
27
+ ) {
28
+ let currentPath = path;
29
+ while (currentPath.parent) {
30
+ if (t.VariableDeclarator.check(currentPath.parent.node)) {
31
+ documentation.set('actualName', getNameOrValue(currentPath.parent.get('id')));
32
+ return;
33
+ } else if (t.AssignmentExpression.check(currentPath.parent.node)) {
34
+ const leftPath = currentPath.parent.get('left');
35
+ if (t.Identifier.check(leftPath.node) || t.Literal.check(leftPath.node)) {
36
+ documentation.set('actualName', getNameOrValue(leftPath));
37
+ return;
38
+ }
39
+ }
40
+ currentPath = currentPath.parent;
41
+ }
42
+ // Could not find an actual name
43
+ documentation.set('actualName', '');
44
+ }
45
+ return;
46
+ }
@@ -0,0 +1,53 @@
1
+ import {
2
+ parse,
3
+ handlers as docgenHandlers,
4
+ resolver as docgenResolver,
5
+ importers as docgenImporters,
6
+ } from 'react-docgen';
7
+ import type { DocumentationObject } from 'react-docgen/lib/Documentation';
8
+ import MagicString from 'magic-string';
9
+ import type { Plugin } from 'vite';
10
+ import actualNameHandler from './docgen-handlers/actualNameHandler';
11
+
12
+ type DocObj = DocumentationObject & { actualName: string };
13
+
14
+ // TODO: None of these are able to be overridden, so `default` is aspirational here.
15
+ const defaultHandlers = Object.values(docgenHandlers).map((handler) => handler);
16
+ const defaultResolver = docgenResolver.findAllExportedComponentDefinitions;
17
+ const defaultImporter = docgenImporters.makeFsImporter();
18
+ const handlers = [...defaultHandlers, actualNameHandler];
19
+
20
+ export function reactDocgen(): Plugin {
21
+ return {
22
+ name: 'react-docgen',
23
+ enforce: 'pre',
24
+ async transform(src: string, id: string) {
25
+ // JSX syntax is only allowed in .tsx and .jsx, but components can technically be created without JSX
26
+ if (/\.(mjs|tsx?|jsx?)$/.test(id)) {
27
+ try {
28
+ // Since we're using `findAllExportedComponentDefinitions`, this will always be an array.
29
+ const docgenResults = parse(src, defaultResolver, handlers, { importer: defaultImporter, filename: id }) as
30
+ | DocObj[];
31
+ const s = new MagicString(src);
32
+
33
+ docgenResults.forEach((info) => {
34
+ const { actualName, ...docgenInfo } = info;
35
+ if (actualName) {
36
+ const docNode = JSON.stringify(docgenInfo);
37
+ s.append(`;${actualName}.__docgenInfo=${docNode}`);
38
+ }
39
+ });
40
+
41
+ return {
42
+ code: s.toString(),
43
+ map: s.generateMap(),
44
+ };
45
+ } catch (e) {
46
+ // Usually this is just an error from react-docgen that it couldn't find a component
47
+ // Only uncomment for troubleshooting
48
+ // console.error(e);
49
+ }
50
+ }
51
+ },
52
+ };
53
+ }
@@ -1,6 +1,8 @@
1
1
  import { parse } from 'vue-docgen-api';
2
+ import type { Plugin } from 'vite';
3
+ import MagicString from 'magic-string';
2
4
 
3
- export function vueDocgen() {
5
+ export function vueDocgen(): Plugin {
4
6
  return {
5
7
  name: 'vue-docgen',
6
8
 
@@ -8,8 +10,13 @@ export function vueDocgen() {
8
10
  if (/\.(vue)$/.test(id)) {
9
11
  const metaData = await parse(id);
10
12
  const metaSource = JSON.stringify(metaData);
13
+ const s = new MagicString(src);
14
+ s.append(`;_sfc_main.__docgenInfo = ${metaSource}`);
11
15
 
12
- return `${src};_sfc_main.__docgenInfo = ${metaSource}`;
16
+ return {
17
+ code: s.toString(),
18
+ map: s.generateMap(),
19
+ };
13
20
  }
14
21
  },
15
22
  };
@@ -0,0 +1,22 @@
1
+ // TODO: delete this stub file once a new alpha of react-docgen is released (will include ts types).
2
+
3
+ declare module 'react-docgen' {
4
+ declare const parse;
5
+ declare const handlers;
6
+ declare const resolver;
7
+ declare const importers;
8
+ }
9
+
10
+ declare module 'react-docgen/lib/Documentation' {
11
+ export type DocumentationObject = Record<string, any>;
12
+ export default Documentation;
13
+ }
14
+
15
+ declare module 'react-docgen/dist/utils' {
16
+ declare const getNameOrValue;
17
+ declare const isReactForwardRefCall;
18
+ }
19
+
20
+ declare module 'react-docgen/dist/parse' {
21
+ declare type Importer = any;
22
+ }
package/vite-config.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as path from 'path';
2
+ import fs from 'fs';
2
3
  import { Plugin } from 'vite';
3
4
  import { allowedEnvPrefix as envPrefix } from './envs';
4
5
  import { TypescriptConfig } from '@storybook/core-common';
@@ -13,6 +14,16 @@ import type { ExtendedOptions } from './types';
13
14
 
14
15
  export type PluginConfigType = 'build' | 'development';
15
16
 
17
+ export function readPackageJson(): Record<string, any> | false {
18
+ const packageJsonPath = path.resolve('package.json');
19
+ if (!fs.existsSync(packageJsonPath)) {
20
+ return false;
21
+ }
22
+
23
+ const jsonContent = fs.readFileSync(packageJsonPath, 'utf8');
24
+ return JSON.parse(jsonContent);
25
+ }
26
+
16
27
  // Vite config that is common to development and production mode
17
28
  export async function commonConfig(
18
29
  options: ExtendedOptions,
@@ -108,14 +119,18 @@ export async function pluginConfig(options: ExtendedOptions, _type: PluginConfig
108
119
  let typescriptPresent;
109
120
 
110
121
  try {
111
- require.resolve('typescript');
112
- typescriptPresent = true;
122
+ const pkgJson = readPackageJson();
123
+ typescriptPresent = pkgJson && (pkgJson?.devDependencies?.typescript || pkgJson?.dependencies?.typescript);
113
124
  } catch (e) {
114
125
  typescriptPresent = false;
115
126
  }
116
127
 
117
128
  if (reactDocgen === 'react-docgen-typescript' && typescriptPresent) {
118
129
  plugins.push(require('@joshwooding/vite-plugin-react-docgen-typescript').default(reactDocgenTypescriptOptions));
130
+ } else if (reactDocgen) {
131
+ const { reactDocgen } = await import('./plugins/react-docgen');
132
+ // Needs to run before the react plugin, so add to the front
133
+ plugins.unshift(reactDocgen());
119
134
  }
120
135
  }
121
136