From 76214c712e7ebade1f8520601cedba0cc225dd66 Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Tue, 16 Jan 2024 16:24:46 +0800 Subject: [PATCH] Merge pull request #25590 from storybookjs/shilman/fix-configfile-export-specifier ConfigFile: Fix export specifiers (cherry picked from commit cb97367c1d29fef0eca6432902cda9922c1dbb7a) --- code/lib/csf-tools/src/ConfigFile.test.ts | 29 ++++++++++++++++++ code/lib/csf-tools/src/ConfigFile.ts | 30 +++++++++++++++---- .../csf-tools/src/getStorySortParameter.ts | 3 ++ 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/code/lib/csf-tools/src/ConfigFile.test.ts b/code/lib/csf-tools/src/ConfigFile.test.ts index 10b2c5e8d025..40e04cac23dc 100644 --- a/code/lib/csf-tools/src/ConfigFile.test.ts +++ b/code/lib/csf-tools/src/ConfigFile.test.ts @@ -217,6 +217,17 @@ describe('ConfigFile', () => { ) ).toEqual([{ directory: '../src', titlePrefix: 'Demo' }]); }); + it('export specfier', () => { + expect( + getField( + ['foo'], + dedent` + const foo = 'bar'; + export { foo }; + ` + ) + ).toEqual('bar'); + }); }); }); @@ -436,6 +447,24 @@ describe('ConfigFile', () => { `); }); }); + + describe('export specifiers', () => { + it('found object', () => { + expect( + setField( + ['core', 'builder'], + 'webpack5', + dedent` + const core = { builder: 'webpack4' }; + export { core }; + ` + ) + ).toMatchInlineSnapshot(` + const core = { builder: 'webpack5' }; + export { core }; + `); + }); + }); }); describe('appendToArray', () => { diff --git a/code/lib/csf-tools/src/ConfigFile.ts b/code/lib/csf-tools/src/ConfigFile.ts index eb2921b4e06d..9ba498a493d0 100644 --- a/code/lib/csf-tools/src/ConfigFile.ts +++ b/code/lib/csf-tools/src/ConfigFile.ts @@ -78,10 +78,12 @@ const _getPathProperties = (path: string[], node: t.Node): t.ObjectProperty[] | } return undefined; }; - // eslint-disable-next-line @typescript-eslint/naming-convention -const _findVarInitialization = (identifier: string, program: t.Program) => { - let init: t.Expression | null | undefined = null; +const _findVarDeclarator = ( + identifier: string, + program: t.Program +): t.VariableDeclarator | null | undefined => { + let declarator: t.VariableDeclarator | null | undefined = null; let declarations: t.VariableDeclarator[] | null = null; program.body.find((node: t.Node) => { if (t.isVariableDeclaration(node)) { @@ -92,20 +94,26 @@ const _findVarInitialization = (identifier: string, program: t.Program) => { return ( declarations && - declarations.find((decl: t.Node) => { + declarations.find((decl: t.VariableDeclarator) => { if ( t.isVariableDeclarator(decl) && t.isIdentifier(decl.id) && decl.id.name === identifier ) { - init = decl.init; + declarator = decl; return true; // stop looking } return false; }) ); }); - return init; + return declarator; +}; + +// eslint-disable-next-line @typescript-eslint/naming-convention +const _findVarInitialization = (identifier: string, program: t.Program) => { + const declarator = _findVarDeclarator(identifier, program); + return declarator?.init; }; // eslint-disable-next-line @typescript-eslint/naming-convention @@ -213,6 +221,16 @@ export class ConfigFile { self._exportDecls[exportName] = decl; } }); + } else if (node.specifiers) { + // export { X }; + node.specifiers.forEach((spec) => { + if (t.isExportSpecifier(spec) && t.isIdentifier(spec.exported)) { + const { name: exportName } = spec.exported; + const decl = _findVarDeclarator(exportName, parent as t.Program) as any; + self._exports[exportName] = decl.init; + self._exportDecls[exportName] = decl; + } + }); } else { logger.warn( getCsfParsingErrorMessage({ diff --git a/code/lib/csf-tools/src/getStorySortParameter.ts b/code/lib/csf-tools/src/getStorySortParameter.ts index 426017c5f410..6b04c6eaa390 100644 --- a/code/lib/csf-tools/src/getStorySortParameter.ts +++ b/code/lib/csf-tools/src/getStorySortParameter.ts @@ -96,6 +96,9 @@ const parseDefault = (defaultExpr: t.Expression, program: t.Program): t.Expressi }; export const getStorySortParameter = (previewCode: string) => { + // don't even try to process the file + if (!previewCode.includes('storySort')) return undefined; + let storySort: t.Expression | undefined; const ast = babelParse(previewCode); traverse.default(ast, {