diff --git a/code/lib/core-server/package.json b/code/lib/core-server/package.json index 64c7893f8523..6296522da0f6 100644 --- a/code/lib/core-server/package.json +++ b/code/lib/core-server/package.json @@ -77,6 +77,7 @@ "@types/pretty-hrtime": "^1.0.0", "@types/semver": "^7.3.4", "better-opn": "^3.0.2", + "camelcase": "^8.0.0", "chalk": "^4.1.0", "cjs-module-lexer": "^1.2.3", "cli-table3": "^0.6.1", diff --git a/code/lib/core-server/src/utils/get-component-variable-name.test.ts b/code/lib/core-server/src/utils/get-component-variable-name.test.ts new file mode 100644 index 000000000000..b58442b18507 --- /dev/null +++ b/code/lib/core-server/src/utils/get-component-variable-name.test.ts @@ -0,0 +1,11 @@ +import { describe, expect, it } from 'vitest'; +import { getComponentVariableName } from './get-component-variable-name'; + +describe('get-variable-name', () => { + it('should return a valid variable name for a given string', () => { + expect(getComponentVariableName('foo-bar')).toBe('FooBar'); + expect(getComponentVariableName('foo bar')).toBe('FooBar'); + expect(getComponentVariableName('0-foo-bar')).toBe('FooBar'); + expect(getComponentVariableName('*Foo-bar-$')).toBe('FooBar$'); + }); +}); diff --git a/code/lib/core-server/src/utils/get-component-variable-name.ts b/code/lib/core-server/src/utils/get-component-variable-name.ts new file mode 100644 index 000000000000..e37fcaf91d23 --- /dev/null +++ b/code/lib/core-server/src/utils/get-component-variable-name.ts @@ -0,0 +1,13 @@ +import camelcase from 'camelcase'; + +/** + * Get a valid variable name for a component. + * + * @param name The name of the component. + * @returns A valid variable name. + */ +export const getComponentVariableName = (name: string) => { + const camelCased = camelcase(name.replace(/^[^a-zA-Z_$]*/, ''), { pascalCase: true }); + const sanitized = camelCased.replace(/[^a-zA-Z_$]+/, ''); + return sanitized; +}; diff --git a/code/lib/core-server/src/utils/get-new-story-file.test.ts b/code/lib/core-server/src/utils/get-new-story-file.test.ts index 750ea322b264..429801ad0186 100644 --- a/code/lib/core-server/src/utils/get-new-story-file.test.ts +++ b/code/lib/core-server/src/utils/get-new-story-file.test.ts @@ -68,10 +68,10 @@ describe('get-new-story-file', () => { expect(exportedStoryName).toBe('Default'); expect(storyFileContent).toMatchInlineSnapshot(` - "import Component from './Page'; + "import Page from './Page'; const meta = { - component: Component, + component: Page, }; export default meta; diff --git a/code/lib/core-server/src/utils/new-story-templates/javascript.test.ts b/code/lib/core-server/src/utils/new-story-templates/javascript.test.ts index 2d6dc4d3f0ea..fa89588a6e89 100644 --- a/code/lib/core-server/src/utils/new-story-templates/javascript.test.ts +++ b/code/lib/core-server/src/utils/new-story-templates/javascript.test.ts @@ -11,10 +11,10 @@ describe('javascript', () => { }); expect(result).toMatchInlineSnapshot(` - "import Component from './foo'; + "import Foo from './foo'; const meta = { - component: Component, + component: Foo, }; export default meta; diff --git a/code/lib/core-server/src/utils/new-story-templates/javascript.ts b/code/lib/core-server/src/utils/new-story-templates/javascript.ts index 5563f9faa1b8..b5572c8810c1 100644 --- a/code/lib/core-server/src/utils/new-story-templates/javascript.ts +++ b/code/lib/core-server/src/utils/new-story-templates/javascript.ts @@ -1,4 +1,5 @@ import dedent from 'ts-dedent'; +import { getComponentVariableName } from '../get-component-variable-name'; interface JavaScriptTemplateData { /** The components file name without the extension */ @@ -10,7 +11,9 @@ interface JavaScriptTemplateData { } export function getJavaScriptTemplateForNewStoryFile(data: JavaScriptTemplateData) { - const importName = data.componentIsDefaultExport ? 'Component' : data.componentExportName; + const importName = data.componentIsDefaultExport + ? getComponentVariableName(data.basenameWithoutExtension) + : data.componentExportName; const importStatement = data.componentIsDefaultExport ? `import ${importName} from './${data.basenameWithoutExtension}';` : `import { ${importName} } from './${data.basenameWithoutExtension}';`; diff --git a/code/lib/core-server/src/utils/new-story-templates/typescript.test.ts b/code/lib/core-server/src/utils/new-story-templates/typescript.test.ts index 05cd39cca9f8..ed00bf61cf7a 100644 --- a/code/lib/core-server/src/utils/new-story-templates/typescript.test.ts +++ b/code/lib/core-server/src/utils/new-story-templates/typescript.test.ts @@ -14,11 +14,11 @@ describe('typescript', () => { expect(result).toMatchInlineSnapshot(` "import type { Meta, StoryObj } from '@storybook/nextjs'; - import Component from './foo'; + import Foo from './foo'; const meta = { - component: Component, - } satisfies Meta; + component: Foo, + } satisfies Meta; export default meta; diff --git a/code/lib/core-server/src/utils/new-story-templates/typescript.ts b/code/lib/core-server/src/utils/new-story-templates/typescript.ts index 38e9ffbe6e4f..03a625be178e 100644 --- a/code/lib/core-server/src/utils/new-story-templates/typescript.ts +++ b/code/lib/core-server/src/utils/new-story-templates/typescript.ts @@ -1,4 +1,5 @@ import dedent from 'ts-dedent'; +import { getComponentVariableName } from '../get-component-variable-name'; interface TypeScriptTemplateData { /** The components file name without the extension */ @@ -12,7 +13,9 @@ interface TypeScriptTemplateData { } export function getTypeScriptTemplateForNewStoryFile(data: TypeScriptTemplateData) { - const importName = data.componentIsDefaultExport ? 'Component' : data.componentExportName; + const importName = data.componentIsDefaultExport + ? getComponentVariableName(data.basenameWithoutExtension) + : data.componentExportName; const importStatement = data.componentIsDefaultExport ? `import ${importName} from './${data.basenameWithoutExtension}'` : `import { ${importName} } from './${data.basenameWithoutExtension}'`; diff --git a/code/yarn.lock b/code/yarn.lock index 7be8a5f1fd96..6914dd488853 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -5595,6 +5595,7 @@ __metadata: "@types/ws": "npm:^8" better-opn: "npm:^3.0.2" boxen: "npm:^7.1.1" + camelcase: "npm:^8.0.0" chalk: "npm:^4.1.0" cjs-module-lexer: "npm:^1.2.3" cli-table3: "npm:^0.6.1" @@ -11061,6 +11062,13 @@ __metadata: languageName: node linkType: hard +"camelcase@npm:^8.0.0": + version: 8.0.0 + resolution: "camelcase@npm:8.0.0" + checksum: 10c0/56c5fe072f0523c9908cdaac21d4a3b3fb0f608fb2e9ba90a60e792b95dd3bb3d1f3523873ab17d86d146e94171305f73ef619e2f538bd759675bc4a14b4bff3 + languageName: node + linkType: hard + "can-symlink@npm:^1.0.0": version: 1.0.0 resolution: "can-symlink@npm:1.0.0"