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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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 cea28271e0ff055b6060f97f8452604a443aed2e Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 29 Feb 2024 15:46:06 +0100 Subject: [PATCH 08/13] 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 899ba75db383b8745d6d5514b1f2226d41614522 Mon Sep 17 00:00:00 2001 From: Norbert de Langen Date: Thu, 29 Feb 2024 20:11:37 +0100 Subject: [PATCH 09/13] 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 10/13] 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 11/13] 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 12/13] 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 13/13] 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; }