From 1d5e9f8d179ef19175d2c2bb6bc3ba8a9d511e35 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 29 Feb 2024 11:44:19 +0100 Subject: [PATCH 01/17] filter docgen import resolution files to only JS --- code/frameworks/react-vite/package.json | 3 +- .../react-vite/src/plugins/docgen-resolver.ts | 60 +++++++++++++++++++ .../react-vite/src/plugins/react-docgen.ts | 19 ++++-- code/yarn.lock | 5 +- 4 files changed, 78 insertions(+), 9 deletions(-) create mode 100644 code/frameworks/react-vite/src/plugins/docgen-resolver.ts diff --git a/code/frameworks/react-vite/package.json b/code/frameworks/react-vite/package.json index b502a6fe4e48..e560d1eacb8a 100644 --- a/code/frameworks/react-vite/package.json +++ b/code/frameworks/react-vite/package.json @@ -52,7 +52,8 @@ "@storybook/builder-vite": "workspace:*", "@storybook/react": "workspace:*", "magic-string": "^0.30.0", - "react-docgen": "^7.0.0" + "react-docgen": "^7.0.0", + "resolve": "^1.22.8" }, "devDependencies": { "@types/node": "^18.0.0", diff --git a/code/frameworks/react-vite/src/plugins/docgen-resolver.ts b/code/frameworks/react-vite/src/plugins/docgen-resolver.ts new file mode 100644 index 000000000000..176dcb7f6467 --- /dev/null +++ b/code/frameworks/react-vite/src/plugins/docgen-resolver.ts @@ -0,0 +1,60 @@ +import { extname } from 'path'; +import resolve from 'resolve'; + +export class ReactDocgenResolveError extends Error { + // the magic string that react-docgen uses to check if a module is ignored + readonly code = 'MODULE_NOT_FOUND'; + + constructor(filename: string) { + super(`'${filename}' was ignored by react-docgen.`); + } +} + +/* The below code was copied from: + * https://github.com/reactjs/react-docgen/blob/df2daa8b6f0af693ecc3c4dc49f2246f60552bcb/packages/react-docgen/src/importer/makeFsImporter.ts#L14-L63 + * because it wasn't exported from the react-docgen package. + */ + +// These extensions are sorted by priority +// resolve() will check for files in the order these extensions are sorted +const RESOLVE_EXTENSIONS = ['.js', '.ts', '.tsx', '.mjs', '.cjs', '.mts', '.cts', '.jsx']; + +export function defaultLookupModule(filename: string, basedir: string): string { + const resolveOptions = { + basedir, + extensions: RESOLVE_EXTENSIONS, + // we do not need to check core modules as we cannot import them anyway + includeCoreModules: false, + }; + + try { + return resolve.sync(filename, resolveOptions); + } catch (error) { + const ext = extname(filename); + let newFilename: string; + + // if we try to import a JavaScript file it might be that we are actually pointing to + // a TypeScript file. This can happen in ES modules as TypeScript requires to import other + // TypeScript files with .js extensions + // https://www.typescriptlang.org/docs/handbook/esm-node.html#type-in-packagejson-and-new-extensions + switch (ext) { + case '.js': + case '.mjs': + case '.cjs': + newFilename = `${filename.slice(0, -2)}ts`; + break; + + case '.jsx': + newFilename = `${filename.slice(0, -3)}tsx`; + break; + default: + throw error; + } + + return resolve.sync(newFilename, { + ...resolveOptions, + // we already know that there is an extension at this point, so no need to check other extensions + extensions: [], + }); + } +} diff --git a/code/frameworks/react-vite/src/plugins/react-docgen.ts b/code/frameworks/react-vite/src/plugins/react-docgen.ts index 5be555fbd081..b56075efe777 100644 --- a/code/frameworks/react-vite/src/plugins/react-docgen.ts +++ b/code/frameworks/react-vite/src/plugins/react-docgen.ts @@ -1,4 +1,4 @@ -import path from 'path'; +import path, { join } from 'path'; import { createFilter } from '@rollup/pluginutils'; import type { Documentation } from 'react-docgen'; import { @@ -6,18 +6,18 @@ import { parse, builtinHandlers as docgenHandlers, builtinResolvers as docgenResolver, - builtinImporters as docgenImporters, + makeFsImporter, } from 'react-docgen'; import MagicString from 'magic-string'; import type { PluginOption } from 'vite'; import actualNameHandler from './docgen-handlers/actualNameHandler'; +import { ReactDocgenResolveError, defaultLookupModule } from './docgen-resolver'; type DocObj = Documentation & { actualName: string }; // TODO: None of these are able to be overridden, so `default` is aspirational here. const defaultHandlers = Object.values(docgenHandlers).map((handler) => handler); const defaultResolver = new docgenResolver.FindExportedDefinitionsResolver(); -const defaultImporter = docgenImporters.fsImporter; const handlers = [...defaultHandlers, actualNameHandler]; type Options = { @@ -36,14 +36,21 @@ export function reactDocgen({ name: 'storybook:react-docgen-plugin', enforce: 'pre', async transform(src: string, id: string) { - const relPath = path.relative(cwd, id); - if (!filter(relPath)) return; + if (!filter(path.relative(cwd, id))) { + return; + } try { const docgenResults = parse(src, { resolver: defaultResolver, handlers, - importer: defaultImporter, + importer: makeFsImporter((filename, basedir) => { + if (!filter(path.relative(cwd, join(basedir, filename)))) { + throw new ReactDocgenResolveError(filename); + } + + return defaultLookupModule(filename, basedir); + }), filename: id, }) as DocObj[]; const s = new MagicString(src); diff --git a/code/yarn.lock b/code/yarn.lock index c0338dabe0c4..7450ad6886f4 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -6491,6 +6491,7 @@ __metadata: "@types/node": "npm:^18.0.0" magic-string: "npm:^0.30.0" react-docgen: "npm:^7.0.0" + resolve: "npm:^1.22.8" typescript: "npm:^5.3.2" vite: "npm:^4.0.0" peerDependencies: @@ -25657,7 +25658,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:1.22.8, resolve@npm:^1.10.0, resolve@npm:^1.13.1, resolve@npm:^1.14.2, resolve@npm:^1.15.1, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.22.1, resolve@npm:^1.22.4, resolve@npm:^1.4.0": +"resolve@npm:1.22.8, resolve@npm:^1.10.0, resolve@npm:^1.13.1, resolve@npm:^1.14.2, resolve@npm:^1.15.1, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.22.1, resolve@npm:^1.22.4, resolve@npm:^1.22.8, resolve@npm:^1.4.0": version: 1.22.8 resolution: "resolve@npm:1.22.8" dependencies: @@ -25683,7 +25684,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@npm%3A1.22.8#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.13.1#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.15.1#optional!builtin, resolve@patch:resolve@npm%3A^1.17.0#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin, resolve@patch:resolve@npm%3A^1.4.0#optional!builtin": +"resolve@patch:resolve@npm%3A1.22.8#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.13.1#optional!builtin, resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.15.1#optional!builtin, resolve@patch:resolve@npm%3A^1.17.0#optional!builtin, resolve@patch:resolve@npm%3A^1.19.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin, resolve@patch:resolve@npm%3A^1.22.8#optional!builtin, resolve@patch:resolve@npm%3A^1.4.0#optional!builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" dependencies: From 7246a179ec91178caab30212e9f641b0981c9ac6 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 29 Feb 2024 13:20:30 +0100 Subject: [PATCH 02/17] making a little simplification, see if it causes a regression too --- code/frameworks/react-vite/src/plugins/react-docgen.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/frameworks/react-vite/src/plugins/react-docgen.ts b/code/frameworks/react-vite/src/plugins/react-docgen.ts index b56075efe777..4eac1709c870 100644 --- a/code/frameworks/react-vite/src/plugins/react-docgen.ts +++ b/code/frameworks/react-vite/src/plugins/react-docgen.ts @@ -45,7 +45,7 @@ export function reactDocgen({ resolver: defaultResolver, handlers, importer: makeFsImporter((filename, basedir) => { - if (!filter(path.relative(cwd, join(basedir, filename)))) { + if (!filename.match(/\.(mjs|tsx?|jsx?)$/)) { throw new ReactDocgenResolveError(filename); } From dd3ba902d1c4b6e6375c8a6e8ef3399e957359dd Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 29 Feb 2024 13:31:52 +0100 Subject: [PATCH 03/17] fix --- code/frameworks/react-vite/src/plugins/react-docgen.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/frameworks/react-vite/src/plugins/react-docgen.ts b/code/frameworks/react-vite/src/plugins/react-docgen.ts index 4eac1709c870..4e9388d7df90 100644 --- a/code/frameworks/react-vite/src/plugins/react-docgen.ts +++ b/code/frameworks/react-vite/src/plugins/react-docgen.ts @@ -1,4 +1,4 @@ -import path, { join } from 'path'; +import path from 'path'; import { createFilter } from '@rollup/pluginutils'; import type { Documentation } from 'react-docgen'; import { From 686867f6d014346b64d375a91ef041cc9bf8fd31 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 29 Feb 2024 14:03:00 +0100 Subject: [PATCH 04/17] fix issue with files without extension --- code/frameworks/react-vite/src/plugins/react-docgen.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/frameworks/react-vite/src/plugins/react-docgen.ts b/code/frameworks/react-vite/src/plugins/react-docgen.ts index 4e9388d7df90..d4b88fa6efab 100644 --- a/code/frameworks/react-vite/src/plugins/react-docgen.ts +++ b/code/frameworks/react-vite/src/plugins/react-docgen.ts @@ -45,11 +45,13 @@ export function reactDocgen({ resolver: defaultResolver, handlers, importer: makeFsImporter((filename, basedir) => { - if (!filename.match(/\.(mjs|tsx?|jsx?)$/)) { + const result = defaultLookupModule(filename, basedir); + + if (!result.match(/\.(mjs|tsx?|jsx?)$/)) { throw new ReactDocgenResolveError(filename); } - return defaultLookupModule(filename, basedir); + return result; }), filename: id, }) as DocObj[]; From 5fa9f5be2a7af34a6cd1e650055e44bcb74b42cf Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 29 Feb 2024 14:48:04 +0100 Subject: [PATCH 05/17] add regression test for import of css file --- .../template/stories/docgen-components/imported.module.css | 3 +++ .../stories/docgen-components/ts-function-component/input.tsx | 4 ++++ 2 files changed, 7 insertions(+) create mode 100644 code/renderers/react/template/stories/docgen-components/imported.module.css diff --git a/code/renderers/react/template/stories/docgen-components/imported.module.css b/code/renderers/react/template/stories/docgen-components/imported.module.css new file mode 100644 index 000000000000..a15c877ac01f --- /dev/null +++ b/code/renderers/react/template/stories/docgen-components/imported.module.css @@ -0,0 +1,3 @@ +.foo { + color: red; +} diff --git a/code/renderers/react/template/stories/docgen-components/ts-function-component/input.tsx b/code/renderers/react/template/stories/docgen-components/ts-function-component/input.tsx index 9f0c2598ff07..8c9ee7a45d35 100644 --- a/code/renderers/react/template/stories/docgen-components/ts-function-component/input.tsx +++ b/code/renderers/react/template/stories/docgen-components/ts-function-component/input.tsx @@ -1,6 +1,8 @@ import React from 'react'; import { imported } from '../imported'; +// @ts-expect-error (css import not supported in TS) +import styles from '../imported.module.css'; const local = 'local-value'; @@ -26,6 +28,7 @@ interface PropsWriterProps { importedReference?: string; globalReference?: any; stringGlobalName?: string; + myClass: typeof styles.foo; } /** @@ -47,6 +50,7 @@ PropsWriter.defaultProps = { importedReference: imported, globalReference: Date, stringGlobalName: 'top', + myClass: styles.foo, }; export const component = PropsWriter; From 0d52b8058dbf3ad89e35f3dfa735f3c32b5c4a77 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 29 Feb 2024 15:03:33 +0100 Subject: [PATCH 06/17] remove it --- .../stories/docgen-components/ts-function-component/input.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/code/renderers/react/template/stories/docgen-components/ts-function-component/input.tsx b/code/renderers/react/template/stories/docgen-components/ts-function-component/input.tsx index 8c9ee7a45d35..f7fef63ace91 100644 --- a/code/renderers/react/template/stories/docgen-components/ts-function-component/input.tsx +++ b/code/renderers/react/template/stories/docgen-components/ts-function-component/input.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { imported } from '../imported'; -// @ts-expect-error (css import not supported in TS) import styles from '../imported.module.css'; const local = 'local-value'; From 6a6e4cffa4e3f0c7e86fd24534bdb3a07f27dda8 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 29 Feb 2024 15:15:41 +0100 Subject: [PATCH 07/17] fix --- .../stories/docgen-components/ts-function-component/input.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/renderers/react/template/stories/docgen-components/ts-function-component/input.tsx b/code/renderers/react/template/stories/docgen-components/ts-function-component/input.tsx index f7fef63ace91..193c2e2c71ae 100644 --- a/code/renderers/react/template/stories/docgen-components/ts-function-component/input.tsx +++ b/code/renderers/react/template/stories/docgen-components/ts-function-component/input.tsx @@ -1,6 +1,8 @@ import React from 'react'; import { imported } from '../imported'; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore (css import not supported in TS) import styles from '../imported.module.css'; const local = 'local-value'; From 470ff2344b0e58ba4035aab23a79080c15b3cd00 Mon Sep 17 00:00:00 2001 From: jonniebigodes Date: Thu, 29 Feb 2024 14:30:28 +0000 Subject: [PATCH 08/17] Docs: Snippets fix testing package imports --- .../common/my-component-play-function-with-canvas.js.mdx | 2 +- docs/snippets/react/login-form-with-play-function.ts-4-9.mdx | 4 +--- docs/snippets/react/login-form-with-play-function.ts.mdx | 4 +--- docs/snippets/svelte/login-form-with-play-function.js.mdx | 3 +-- docs/snippets/svelte/login-form-with-play-function.ts-4-9.mdx | 3 +-- docs/snippets/svelte/login-form-with-play-function.ts.mdx | 3 +-- .../my-component-play-function-with-canvas.js.mdx | 2 +- 7 files changed, 7 insertions(+), 14 deletions(-) diff --git a/docs/snippets/common/my-component-play-function-with-canvas.js.mdx b/docs/snippets/common/my-component-play-function-with-canvas.js.mdx index 26ec005f70fa..a5da1d3eed5f 100644 --- a/docs/snippets/common/my-component-play-function-with-canvas.js.mdx +++ b/docs/snippets/common/my-component-play-function-with-canvas.js.mdx @@ -1,7 +1,7 @@ ```js // MyComponent.stories.js|jsx -import { getByRole, userEvent, within } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/test'; import { MyComponent } from './MyComponent'; diff --git a/docs/snippets/react/login-form-with-play-function.ts-4-9.mdx b/docs/snippets/react/login-form-with-play-function.ts-4-9.mdx index d6a86876817c..84dffad550b1 100644 --- a/docs/snippets/react/login-form-with-play-function.ts-4-9.mdx +++ b/docs/snippets/react/login-form-with-play-function.ts-4-9.mdx @@ -3,9 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react'; -import { within, userEvent } from '@storybook/testing-library'; - -import { expect } from '@storybook/test'; +import { userEvent, within, expect } from '@storybook/test'; import { LoginForm } from './LoginForm'; diff --git a/docs/snippets/react/login-form-with-play-function.ts.mdx b/docs/snippets/react/login-form-with-play-function.ts.mdx index f31a2a8fcbe2..de6854f0e180 100644 --- a/docs/snippets/react/login-form-with-play-function.ts.mdx +++ b/docs/snippets/react/login-form-with-play-function.ts.mdx @@ -3,9 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react'; -import { within, userEvent } from '@storybook/testing-library'; - -import { expect } from '@storybook/test'; +import { userEvent, within, expect } from '@storybook/test'; import { LoginForm } from './LoginForm'; diff --git a/docs/snippets/svelte/login-form-with-play-function.js.mdx b/docs/snippets/svelte/login-form-with-play-function.js.mdx index e65f60e9a3cb..4408fc6261a0 100644 --- a/docs/snippets/svelte/login-form-with-play-function.js.mdx +++ b/docs/snippets/svelte/login-form-with-play-function.js.mdx @@ -1,8 +1,7 @@ ```js // LoginForm.stories.js -import { userEvent, within } from '@storybook/testing-library'; -import { expect } from '@storybook/test'; +import { expect, userEvent, within } from '@storybook/test'; import LoginForm from './LoginForm.svelte'; diff --git a/docs/snippets/svelte/login-form-with-play-function.ts-4-9.mdx b/docs/snippets/svelte/login-form-with-play-function.ts-4-9.mdx index 265d8fa36b9d..b975337dc799 100644 --- a/docs/snippets/svelte/login-form-with-play-function.ts-4-9.mdx +++ b/docs/snippets/svelte/login-form-with-play-function.ts-4-9.mdx @@ -2,8 +2,7 @@ // LoginForm.stories.ts import type { Meta, StoryObj } from '@storybook/svelte'; -import { userEvent, within } from '@storybook/testing-library'; -import { expect } from '@storybook/test'; +import { expect, userEvent, within } from '@storybook/test'; import LoginForm from './LoginForm.svelte'; diff --git a/docs/snippets/svelte/login-form-with-play-function.ts.mdx b/docs/snippets/svelte/login-form-with-play-function.ts.mdx index ff5891c617d8..24bcd6c1d41a 100644 --- a/docs/snippets/svelte/login-form-with-play-function.ts.mdx +++ b/docs/snippets/svelte/login-form-with-play-function.ts.mdx @@ -2,8 +2,7 @@ // LoginForm.stories.ts import type { Meta, StoryObj } from '@storybook/svelte'; -import { userEvent, within } from '@storybook/testing-library'; -import { expect } from '@storybook/test'; +import { expect, userEvent, within } from '@storybook/test'; import LoginForm from './LoginForm.svelte'; diff --git a/docs/snippets/web-components/my-component-play-function-with-canvas.js.mdx b/docs/snippets/web-components/my-component-play-function-with-canvas.js.mdx index 2ed5c0bec08d..d3812d7d1af0 100644 --- a/docs/snippets/web-components/my-component-play-function-with-canvas.js.mdx +++ b/docs/snippets/web-components/my-component-play-function-with-canvas.js.mdx @@ -1,7 +1,7 @@ ```js // MyComponent.stories.js -import { getByRole, userEvent, within } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/test'; export default { component: 'demo-my-component', From cea28271e0ff055b6060f97f8452604a443aed2e Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 29 Feb 2024 15:46:06 +0100 Subject: [PATCH 09/17] fix for webpack as well! --- .../src/loaders/react-docgen-loader.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/code/presets/react-webpack/src/loaders/react-docgen-loader.ts b/code/presets/react-webpack/src/loaders/react-docgen-loader.ts index fd22ca12bf5d..d9cf24dc5aa6 100644 --- a/code/presets/react-webpack/src/loaders/react-docgen-loader.ts +++ b/code/presets/react-webpack/src/loaders/react-docgen-loader.ts @@ -2,7 +2,7 @@ import { parse, builtinResolvers as docgenResolver, builtinHandlers as docgenHandlers, - builtinImporters as docgenImporters, + makeFsImporter, ERROR_CODES, utils, } from 'react-docgen'; @@ -11,6 +11,11 @@ import type { LoaderContext } from 'webpack'; import type { Handler, NodePath, babelTypes as t, Documentation } from 'react-docgen'; import { logger } from '@storybook/node-logger'; +import { + ReactDocgenResolveError, + defaultLookupModule, +} from '../../../../frameworks/react-vite/src/plugins/docgen-resolver'; + const { getNameOrValue, isReactForwardRefCall } = utils; const actualNameHandler: Handler = function actualNameHandler(documentation, componentDefinition) { @@ -54,7 +59,6 @@ type DocObj = Documentation & { actualName: string }; const defaultHandlers = Object.values(docgenHandlers).map((handler) => handler); const defaultResolver = new docgenResolver.FindExportedDefinitionsResolver(); -const defaultImporter = docgenImporters.fsImporter; const handlers = [...defaultHandlers, actualNameHandler]; export default async function reactDocgenLoader( @@ -71,7 +75,15 @@ export default async function reactDocgenLoader( filename: this.resourcePath, resolver: defaultResolver, handlers, - importer: defaultImporter, + importer: makeFsImporter((filename, basedir) => { + const result = defaultLookupModule(filename, basedir); + + if (!result.match(/\.(mjs|tsx?|jsx?)$/)) { + throw new ReactDocgenResolveError(filename); + } + + return result; + }), babelOptions: { babelrc: false, configFile: false, From b7cdb946802ab83dbfe5baab23d56a375a7013f3 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Thu, 29 Feb 2024 15:54:58 +0100 Subject: [PATCH 10/17] Fix addon compatibility check error reporting in storybook dev --- .../cli/src/doctor/getIncompatibleAddons.ts | 82 ------------------- .../getIncompatibleStorybookPackages.ts | 2 +- 2 files changed, 1 insertion(+), 83 deletions(-) delete mode 100644 code/lib/cli/src/doctor/getIncompatibleAddons.ts diff --git a/code/lib/cli/src/doctor/getIncompatibleAddons.ts b/code/lib/cli/src/doctor/getIncompatibleAddons.ts deleted file mode 100644 index e46297e94087..000000000000 --- a/code/lib/cli/src/doctor/getIncompatibleAddons.ts +++ /dev/null @@ -1,82 +0,0 @@ -import type { StorybookConfig } from '@storybook/types'; -import type { SemVer } from 'semver'; -import semver from 'semver'; -import { getAddonNames } from '../automigrate/helpers/mainConfigFile'; -import { JsPackageManagerFactory } from '@storybook/core-common'; - -export const getIncompatibleAddons = async ( - mainConfig: StorybookConfig, - packageManager = JsPackageManagerFactory.getPackageManager() -) => { - // TODO: Keep this up to date with https://github.com/storybookjs/storybook/issues/20529 in case more addons get added - const incompatibleList = { - '@storybook/addon-knobs': '6.4.0', - '@storybook/addon-postcss': '2.0.0', - 'storybook-addon-next-router': '4.0.2', - 'storybook-addon-outline': '1.4.2', // (deprecated) - '@storybook/addon-info': '5.3.21', - 'storybook-addon-designs': '6.3.1', - 'storybook-addon-next': '1.7.0', // (deprecated)' - 'storybook-docs-toc': '1.7.0', - '@storybook/addon-google-analytics': '6.2.9', - 'storybook-addon-pseudo-states': '1.15.5', - 'storybook-dark-mode': '2.1.1', - 'storybook-addon-gatsby': '0.0.5', - '@etchteam/storybook-addon-css-variables-theme': '1.4.0', - '@storybook/addon-cssresources': '6.2.9', - 'storybook-addon-grid': '0.3.1', - 'storybook-multilevel-sort': '1.2.0', - 'storybook-addon-i18next': '1.3.0', - 'storybook-source-link': '2.0.8', - 'babel-plugin-storybook-csf-title': '2.1.0', - '@urql/storybook-addon': '2.0.1', - 'storybook-addon-intl': '2.4.1', - 'storybook-addon-mock': '3.2.0', - '@chakra-ui/storybook-addon': '4.0.16', - 'storybook-mobile-addon': '1.0.2', - '@storybook/addon-queryparams': '6.2.9', - }; - - const addons = getAddonNames(mainConfig).filter( - (addon): addon is keyof typeof incompatibleList => addon in incompatibleList - ); - - const dependencies = await packageManager.getAllDependencies(); - const storybookPackages = Object.keys(dependencies).filter((dep) => dep.includes('storybook')); - - const packagesToCheck = [...new Set([...addons, ...storybookPackages])]; - - const addonVersions = await Promise.all( - packagesToCheck.map( - async (addon) => - ({ - name: addon, - version: await packageManager.getPackageVersion(addon), - }) as { name: keyof typeof incompatibleList; version: string } - ) - ); - - if (addonVersions.length === 0) { - return []; - } - - const incompatibleAddons: { name: string; version: string }[] = []; - addonVersions.forEach(({ name, version: installedVersion }) => { - if (installedVersion === null) { - return; - } - - const addonVersion = incompatibleList[name]; - try { - if ( - semver.lte(semver.coerce(installedVersion) as SemVer, semver.coerce(addonVersion) as SemVer) - ) { - incompatibleAddons.push({ name, version: installedVersion }); - } - } catch (err) { - // we tried our best but if we can't compare, we just no-op for that addon - } - }); - - return incompatibleAddons; -}; diff --git a/code/lib/cli/src/doctor/getIncompatibleStorybookPackages.ts b/code/lib/cli/src/doctor/getIncompatibleStorybookPackages.ts index d481fae93c82..d27694136074 100644 --- a/code/lib/cli/src/doctor/getIncompatibleStorybookPackages.ts +++ b/code/lib/cli/src/doctor/getIncompatibleStorybookPackages.ts @@ -88,7 +88,7 @@ export const getIncompatibleStorybookPackages = async ( const allDeps = await packageManager.getAllDependencies(); const storybookLikeDeps = Object.keys(allDeps).filter((dep) => dep.includes('storybook')); - if (storybookLikeDeps.length === 0) { + if (storybookLikeDeps.length === 0 && !context.skipErrors) { throw new Error('No Storybook dependencies found in the package.json'); } From 899ba75db383b8745d6d5514b1f2226d41614522 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 29 Feb 2024 20:11:37 +0100 Subject: [PATCH 11/17] make use of RESOLVE_EXTENSIONS as requested --- .../react-vite/src/plugins/docgen-resolver.ts | 2 +- .../react-vite/src/plugins/react-docgen.ts | 12 ++++++++---- .../react-webpack/src/loaders/react-docgen-loader.ts | 7 ++++--- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/code/frameworks/react-vite/src/plugins/docgen-resolver.ts b/code/frameworks/react-vite/src/plugins/docgen-resolver.ts index 176dcb7f6467..9e6d798384a5 100644 --- a/code/frameworks/react-vite/src/plugins/docgen-resolver.ts +++ b/code/frameworks/react-vite/src/plugins/docgen-resolver.ts @@ -17,7 +17,7 @@ export class ReactDocgenResolveError extends Error { // These extensions are sorted by priority // resolve() will check for files in the order these extensions are sorted -const RESOLVE_EXTENSIONS = ['.js', '.ts', '.tsx', '.mjs', '.cjs', '.mts', '.cts', '.jsx']; +export const RESOLVE_EXTENSIONS = ['.js', '.ts', '.tsx', '.mjs', '.cjs', '.mts', '.cts', '.jsx']; export function defaultLookupModule(filename: string, basedir: string): string { const resolveOptions = { diff --git a/code/frameworks/react-vite/src/plugins/react-docgen.ts b/code/frameworks/react-vite/src/plugins/react-docgen.ts index d4b88fa6efab..8ef7a1159aaf 100644 --- a/code/frameworks/react-vite/src/plugins/react-docgen.ts +++ b/code/frameworks/react-vite/src/plugins/react-docgen.ts @@ -11,7 +11,11 @@ import { import MagicString from 'magic-string'; import type { PluginOption } from 'vite'; import actualNameHandler from './docgen-handlers/actualNameHandler'; -import { ReactDocgenResolveError, defaultLookupModule } from './docgen-resolver'; +import { + RESOLVE_EXTENSIONS, + ReactDocgenResolveError, + defaultLookupModule, +} from './docgen-resolver'; type DocObj = Documentation & { actualName: string }; @@ -47,11 +51,11 @@ export function reactDocgen({ importer: makeFsImporter((filename, basedir) => { const result = defaultLookupModule(filename, basedir); - if (!result.match(/\.(mjs|tsx?|jsx?)$/)) { - throw new ReactDocgenResolveError(filename); + if (RESOLVE_EXTENSIONS.find((ext) => result.endsWith(ext)) === undefined) { + return result; } - return result; + throw new ReactDocgenResolveError(filename); }), filename: id, }) as DocObj[]; diff --git a/code/presets/react-webpack/src/loaders/react-docgen-loader.ts b/code/presets/react-webpack/src/loaders/react-docgen-loader.ts index d9cf24dc5aa6..073ef5893f56 100644 --- a/code/presets/react-webpack/src/loaders/react-docgen-loader.ts +++ b/code/presets/react-webpack/src/loaders/react-docgen-loader.ts @@ -12,6 +12,7 @@ import type { Handler, NodePath, babelTypes as t, Documentation } from 'react-do import { logger } from '@storybook/node-logger'; import { + RESOLVE_EXTENSIONS, ReactDocgenResolveError, defaultLookupModule, } from '../../../../frameworks/react-vite/src/plugins/docgen-resolver'; @@ -78,11 +79,11 @@ export default async function reactDocgenLoader( importer: makeFsImporter((filename, basedir) => { const result = defaultLookupModule(filename, basedir); - if (!result.match(/\.(mjs|tsx?|jsx?)$/)) { - throw new ReactDocgenResolveError(filename); + if (RESOLVE_EXTENSIONS.find((ext) => result.endsWith(ext)) === undefined) { + return result; } - return result; + throw new ReactDocgenResolveError(filename); }), babelOptions: { babelrc: false, From ef36c364c266e8712b1c48678c1e76325bf352e9 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 29 Feb 2024 20:55:14 +0100 Subject: [PATCH 12/17] add dependency --- code/presets/react-webpack/package.json | 1 + code/yarn.lock | 1 + 2 files changed, 2 insertions(+) diff --git a/code/presets/react-webpack/package.json b/code/presets/react-webpack/package.json index c2cc403a16ec..a79480cf13dc 100644 --- a/code/presets/react-webpack/package.json +++ b/code/presets/react-webpack/package.json @@ -74,6 +74,7 @@ "fs-extra": "^11.1.0", "magic-string": "^0.30.5", "react-docgen": "^7.0.0", + "resolve": "^1.22.8", "semver": "^7.3.7", "webpack": "5" }, diff --git a/code/yarn.lock b/code/yarn.lock index 7450ad6886f4..039c28a0c940 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -6343,6 +6343,7 @@ __metadata: fs-extra: "npm:^11.1.0" magic-string: "npm:^0.30.5" react-docgen: "npm:^7.0.0" + resolve: "npm:^1.22.8" semver: "npm:^7.3.7" typescript: "npm:^5.3.2" webpack: "npm:5" From 463d4887cc0fe7666d768a0759c736968ad2ea90 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 29 Feb 2024 21:00:32 +0100 Subject: [PATCH 13/17] duplicated to code to prevent ugly import --- .../react-vite/src/plugins/docgen-resolver.ts | 1 + .../src/loaders/docgen-resolver.ts | 61 +++++++++++++++++++ .../src/loaders/react-docgen-loader.ts | 2 +- 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 code/presets/react-webpack/src/loaders/docgen-resolver.ts diff --git a/code/frameworks/react-vite/src/plugins/docgen-resolver.ts b/code/frameworks/react-vite/src/plugins/docgen-resolver.ts index 9e6d798384a5..e0b577fbcbee 100644 --- a/code/frameworks/react-vite/src/plugins/docgen-resolver.ts +++ b/code/frameworks/react-vite/src/plugins/docgen-resolver.ts @@ -13,6 +13,7 @@ export class ReactDocgenResolveError extends Error { /* The below code was copied from: * https://github.com/reactjs/react-docgen/blob/df2daa8b6f0af693ecc3c4dc49f2246f60552bcb/packages/react-docgen/src/importer/makeFsImporter.ts#L14-L63 * because it wasn't exported from the react-docgen package. + * watch out: when updating this code, also update the code in code/presets/react-webpack/src/loaders/docgen-resolver.ts */ // These extensions are sorted by priority diff --git a/code/presets/react-webpack/src/loaders/docgen-resolver.ts b/code/presets/react-webpack/src/loaders/docgen-resolver.ts new file mode 100644 index 000000000000..fc86496fab9e --- /dev/null +++ b/code/presets/react-webpack/src/loaders/docgen-resolver.ts @@ -0,0 +1,61 @@ +import { extname } from 'path'; +import resolve from 'resolve'; + +export class ReactDocgenResolveError extends Error { + // the magic string that react-docgen uses to check if a module is ignored + readonly code = 'MODULE_NOT_FOUND'; + + constructor(filename: string) { + super(`'${filename}' was ignored by react-docgen.`); + } +} + +/* The below code was copied from: + * https://github.com/reactjs/react-docgen/blob/df2daa8b6f0af693ecc3c4dc49f2246f60552bcb/packages/react-docgen/src/importer/makeFsImporter.ts#L14-L63 + * because it wasn't exported from the react-docgen package. + * watch out: when updating this code, also update the code in code/frameworks/react-vite/src/plugins/docgen-resolver.ts + */ + +// These extensions are sorted by priority +// resolve() will check for files in the order these extensions are sorted +export const RESOLVE_EXTENSIONS = ['.js', '.ts', '.tsx', '.mjs', '.cjs', '.mts', '.cts', '.jsx']; + +export function defaultLookupModule(filename: string, basedir: string): string { + const resolveOptions = { + basedir, + extensions: RESOLVE_EXTENSIONS, + // we do not need to check core modules as we cannot import them anyway + includeCoreModules: false, + }; + + try { + return resolve.sync(filename, resolveOptions); + } catch (error) { + const ext = extname(filename); + let newFilename: string; + + // if we try to import a JavaScript file it might be that we are actually pointing to + // a TypeScript file. This can happen in ES modules as TypeScript requires to import other + // TypeScript files with .js extensions + // https://www.typescriptlang.org/docs/handbook/esm-node.html#type-in-packagejson-and-new-extensions + switch (ext) { + case '.js': + case '.mjs': + case '.cjs': + newFilename = `${filename.slice(0, -2)}ts`; + break; + + case '.jsx': + newFilename = `${filename.slice(0, -3)}tsx`; + break; + default: + throw error; + } + + return resolve.sync(newFilename, { + ...resolveOptions, + // we already know that there is an extension at this point, so no need to check other extensions + extensions: [], + }); + } +} diff --git a/code/presets/react-webpack/src/loaders/react-docgen-loader.ts b/code/presets/react-webpack/src/loaders/react-docgen-loader.ts index 073ef5893f56..81fa0b335a58 100644 --- a/code/presets/react-webpack/src/loaders/react-docgen-loader.ts +++ b/code/presets/react-webpack/src/loaders/react-docgen-loader.ts @@ -15,7 +15,7 @@ import { RESOLVE_EXTENSIONS, ReactDocgenResolveError, defaultLookupModule, -} from '../../../../frameworks/react-vite/src/plugins/docgen-resolver'; +} from './docgen-resolver'; const { getNameOrValue, isReactForwardRefCall } = utils; From da5ee529f0a4b7480fd5a9306e42355fcba8c255 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 29 Feb 2024 21:09:07 +0100 Subject: [PATCH 14/17] added extra extensions --- .../react-vite/src/plugins/docgen-resolver.ts | 15 ++++++++++++++- .../react-webpack/src/loaders/docgen-resolver.ts | 15 ++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/code/frameworks/react-vite/src/plugins/docgen-resolver.ts b/code/frameworks/react-vite/src/plugins/docgen-resolver.ts index e0b577fbcbee..ab0fda807cf8 100644 --- a/code/frameworks/react-vite/src/plugins/docgen-resolver.ts +++ b/code/frameworks/react-vite/src/plugins/docgen-resolver.ts @@ -18,7 +18,20 @@ export class ReactDocgenResolveError extends Error { // These extensions are sorted by priority // resolve() will check for files in the order these extensions are sorted -export const RESOLVE_EXTENSIONS = ['.js', '.ts', '.tsx', '.mjs', '.cjs', '.mts', '.cts', '.jsx']; +export const RESOLVE_EXTENSIONS = [ + '.js', + '.cts', // These were originally not in the code, I added them + '.mts', // These were originally not in the code, I added them + '.ctsx', // These were originally not in the code, I added them + '.mtsx', // These were originally not in the code, I added them + '.ts', + '.tsx', + '.mjs', + '.cjs', + '.mts', + '.cts', + '.jsx', +]; export function defaultLookupModule(filename: string, basedir: string): string { const resolveOptions = { diff --git a/code/presets/react-webpack/src/loaders/docgen-resolver.ts b/code/presets/react-webpack/src/loaders/docgen-resolver.ts index fc86496fab9e..71e2bde5d742 100644 --- a/code/presets/react-webpack/src/loaders/docgen-resolver.ts +++ b/code/presets/react-webpack/src/loaders/docgen-resolver.ts @@ -18,7 +18,20 @@ export class ReactDocgenResolveError extends Error { // These extensions are sorted by priority // resolve() will check for files in the order these extensions are sorted -export const RESOLVE_EXTENSIONS = ['.js', '.ts', '.tsx', '.mjs', '.cjs', '.mts', '.cts', '.jsx']; +export const RESOLVE_EXTENSIONS = [ + '.js', + '.cts', // These were originally not in the code, I added them + '.mts', // These were originally not in the code, I added them + '.ctsx', // These were originally not in the code, I added them + '.mtsx', // These were originally not in the code, I added them + '.ts', + '.tsx', + '.mjs', + '.cjs', + '.mts', + '.cts', + '.jsx', +]; export function defaultLookupModule(filename: string, basedir: string): string { const resolveOptions = { From 70ee50f155412703026059adc978980090ae2759 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 29 Feb 2024 21:22:17 +0100 Subject: [PATCH 15/17] fix filter logic --- code/frameworks/react-vite/src/plugins/react-docgen.ts | 2 +- code/presets/react-webpack/src/loaders/react-docgen-loader.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/frameworks/react-vite/src/plugins/react-docgen.ts b/code/frameworks/react-vite/src/plugins/react-docgen.ts index 8ef7a1159aaf..9d2242ce2654 100644 --- a/code/frameworks/react-vite/src/plugins/react-docgen.ts +++ b/code/frameworks/react-vite/src/plugins/react-docgen.ts @@ -51,7 +51,7 @@ export function reactDocgen({ importer: makeFsImporter((filename, basedir) => { const result = defaultLookupModule(filename, basedir); - if (RESOLVE_EXTENSIONS.find((ext) => result.endsWith(ext)) === undefined) { + if (RESOLVE_EXTENSIONS.find((ext) => result.endsWith(ext))) { return result; } diff --git a/code/presets/react-webpack/src/loaders/react-docgen-loader.ts b/code/presets/react-webpack/src/loaders/react-docgen-loader.ts index 81fa0b335a58..12ab911fd546 100644 --- a/code/presets/react-webpack/src/loaders/react-docgen-loader.ts +++ b/code/presets/react-webpack/src/loaders/react-docgen-loader.ts @@ -79,7 +79,7 @@ export default async function reactDocgenLoader( importer: makeFsImporter((filename, basedir) => { const result = defaultLookupModule(filename, basedir); - if (RESOLVE_EXTENSIONS.find((ext) => result.endsWith(ext)) === undefined) { + if (RESOLVE_EXTENSIONS.find((ext) => result.endsWith(ext))) { return result; } From c3335f7dec8368a1ad203d59e9fef542bcc2c7f6 Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Sat, 2 Mar 2024 08:24:59 +0800 Subject: [PATCH 16/17] Onboarding: Fix manager dist reference --- code/addons/onboarding/preset.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/addons/onboarding/preset.js b/code/addons/onboarding/preset.js index 2c7ea670f4a6..87f1602c2f26 100644 --- a/code/addons/onboarding/preset.js +++ b/code/addons/onboarding/preset.js @@ -1,5 +1,5 @@ function managerEntries(entry = []) { - return [...entry, require.resolve('./dist/manager.mjs')]; + return [...entry, require.resolve('./dist/manager.js')]; } module.exports = { From 2d75e1fd15f21f6817ead1e6baffce95566f10fe Mon Sep 17 00:00:00 2001 From: storybook-bot <32066757+storybook-bot@users.noreply.github.com> Date: Sat, 2 Mar 2024 00:53:52 +0000 Subject: [PATCH 17/17] Write changelog for 8.0.0-rc.1 [skip ci] --- CHANGELOG.prerelease.md | 6 ++++++ code/package.json | 3 ++- docs/versions/next.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md index bd3066ba9728..6e9e1eb4ba44 100644 --- a/CHANGELOG.prerelease.md +++ b/CHANGELOG.prerelease.md @@ -1,3 +1,9 @@ +## 8.0.0-rc.1 + +- CLI: Fix addon compatibility check error reporting in storybook dev - [#26258](https://github.com/storybookjs/storybook/pull/26258), thanks [@yannbf](https://github.com/yannbf)! +- Onboarding: Fix manager dist reference - [#26282](https://github.com/storybookjs/storybook/pull/26282), thanks [@shilman](https://github.com/shilman)! +- ReactVite: Docgen ignore un-parsable files - [#26254](https://github.com/storybookjs/storybook/pull/26254), thanks [@ndelangen](https://github.com/ndelangen)! + ## 8.0.0-rc.0 Bumping 8.0.0-beta.6 to 8.0.0-rc.0. Please refer to the changelogs of previous beta releases. diff --git a/code/package.json b/code/package.json index 071cf4a60003..3f0d826438ec 100644 --- a/code/package.json +++ b/code/package.json @@ -294,5 +294,6 @@ "Dependency Upgrades" ] ] - } + }, + "deferredNextVersion": "8.0.0-rc.1" } diff --git a/docs/versions/next.json b/docs/versions/next.json index 7e6974b261e7..a1c6e9350e50 100644 --- a/docs/versions/next.json +++ b/docs/versions/next.json @@ -1 +1 @@ -{"version":"8.0.0-rc.0","info":{"plain":"Bumping 8.0.0-beta.6 to 8.0.0-rc.0. Please refer to the changelogs of previous beta releases."}} +{"version":"8.0.0-rc.1","info":{"plain":"- CLI: Fix addon compatibility check error reporting in storybook dev - [#26258](https://github.com/storybookjs/storybook/pull/26258), thanks [@yannbf](https://github.com/yannbf)!\n- Onboarding: Fix manager dist reference - [#26282](https://github.com/storybookjs/storybook/pull/26282), thanks [@shilman](https://github.com/shilman)!\n- ReactVite: Docgen ignore un-parsable files - [#26254](https://github.com/storybookjs/storybook/pull/26254), thanks [@ndelangen](https://github.com/ndelangen)!"}}