From c992646c037877041ab9130b4778f9e18732ebb4 Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Tue, 27 Aug 2019 18:02:34 +0800 Subject: [PATCH 1/5] CSF: Transform CSF named exports with a `displayName` option --- addons/docs/src/mdx/mdx-compiler-plugin.js | 5 ++--- .../configurations/options-parameter/index.md | 8 ++++++++ lib/client-api/src/client_api.test.ts | 14 +++++++++++++- lib/client-api/src/client_api.ts | 7 +++++++ lib/components/src/blocks/Source.stories.tsx | 2 -- lib/core/src/client/preview/start.js | 5 ++++- 6 files changed, 34 insertions(+), 7 deletions(-) diff --git a/addons/docs/src/mdx/mdx-compiler-plugin.js b/addons/docs/src/mdx/mdx-compiler-plugin.js index cacd34a1fd7c..4d2a2b4ded32 100644 --- a/addons/docs/src/mdx/mdx-compiler-plugin.js +++ b/addons/docs/src/mdx/mdx-compiler-plugin.js @@ -72,9 +72,8 @@ function genStoryExport(ast, counter) { } statements.push(`${storyKey}.story = {};`); - if (storyName !== storyKey) { - statements.push(`${storyKey}.story.name = '${storyName}';`); - } + // always preserve the name, since CSF exports can get modified by displayName + statements.push(`${storyKey}.story.name = '${storyName}';`); let parameters = getAttr(ast.openingElement, 'parameters'); parameters = parameters && parameters.expression; diff --git a/docs/src/pages/configurations/options-parameter/index.md b/docs/src/pages/configurations/options-parameter/index.md index a4586badd353..fa4972b73905 100644 --- a/docs/src/pages/configurations/options-parameter/index.md +++ b/docs/src/pages/configurations/options-parameter/index.md @@ -82,6 +82,14 @@ addParameters({ * @type {Function} */ storySort: undefined + + /** + * Function to transform Component Story Format named exports (typically camel-case + * variables) into display names. If the story specifies a `story.name` option, that + * will not be transformed and will always take precedence over a named export. + * @type {Function} + */ + displayName: lodash.startCase }, }); ``` diff --git a/lib/client-api/src/client_api.test.ts b/lib/client-api/src/client_api.test.ts index 42e4ae7a7f76..e19ff1c24233 100644 --- a/lib/client-api/src/client_api.test.ts +++ b/lib/client-api/src/client_api.test.ts @@ -1,7 +1,7 @@ /* eslint-disable no-underscore-dangle */ import { logger } from '@storybook/client-logger'; import addons, { mockChannel } from '@storybook/addons'; -import ClientApi from './client_api'; +import ClientApi, { defaultDisplayName } from './client_api'; import ConfigApi from './config_api'; import StoryStore from './story_store'; @@ -26,6 +26,18 @@ jest.mock('@storybook/client-logger', () => ({ })); describe('preview.client_api', () => { + describe('defaultDisplayName', () => { + it('should format CSF with sensible defaults', () => { + const testCases = { + name: 'Name', + someName: 'Some Name', + someNAME: 'Some NAME', + some_custom_NAME: 'Some Custom NAME', + }; + Object.entries(testCases).forEach(([key, val]) => expect(defaultDisplayName(key)).toBe(val)); + }); + }); + describe('setAddon', () => { it('should register addons', () => { const { clientApi } = getContext(undefined); diff --git a/lib/client-api/src/client_api.ts b/lib/client-api/src/client_api.ts index 84592f1c2051..0352f723e973 100644 --- a/lib/client-api/src/client_api.ts +++ b/lib/client-api/src/client_api.ts @@ -1,6 +1,7 @@ /* eslint no-underscore-dangle: 0 */ import deprecate from 'util-deprecate'; import isPlainObject from 'is-plain-object'; +import startCase from 'lodash/startCase'; import { logger } from '@storybook/client-logger'; import addons, { StoryContext, StoryFn, Parameters, OptionsParameter } from '@storybook/addons'; import Events from '@storybook/core-events'; @@ -82,6 +83,8 @@ const withSubscriptionTracking = (storyFn: StoryFn) => { return result; }; +export const defaultDisplayName = key => startCase(key); + export default class ClientApi { private _storyStore: StoryStore; @@ -123,6 +126,10 @@ export default class ClientApi { this._globalParameters.options ); + getDisplayName = () => + (this._globalParameters.options && this._globalParameters.options.displayName) || + defaultDisplayName; + addDecorator = (decorator: DecoratorFunction) => { this._globalDecorators.push(decorator); }; diff --git a/lib/components/src/blocks/Source.stories.tsx b/lib/components/src/blocks/Source.stories.tsx index 7024c3b21e7e..bad3ea4acaeb 100644 --- a/lib/components/src/blocks/Source.stories.tsx +++ b/lib/components/src/blocks/Source.stories.tsx @@ -32,7 +32,5 @@ const cssCode = ` export const css = () => ; export const noStory = () => ; -noStory.story = { name: 'no story' }; export const sourceUnavailable = () => ; -sourceUnavailable.story = { name: 'source unavailable' }; diff --git a/lib/core/src/client/preview/start.js b/lib/core/src/client/preview/start.js index e07dc0fbe803..a867d96a3f25 100644 --- a/lib/core/src/client/preview/start.js +++ b/lib/core/src/client/preview/start.js @@ -398,6 +398,9 @@ export default function start(render, { decorateStory } = {}) { // We pass true here to avoid the warning about HMR. It's cool clientApi, we got this const kind = clientApi.storiesOf(kindName, true); + // Transform the CSF named export if the user hasn't specified a name + const displayName = clientApi.getDisplayName(); + // we should always have a framework, rest optional kind.addParameters({ framework, component, ...params }); @@ -414,7 +417,7 @@ export default function start(render, { decorateStory } = {}) { `${kindName} => ${name || key}: story.parameters.decorators is deprecated; use story.decorators instead.`)(); } const decoratorParams = decorators ? { decorators } : null; - kind.add(name || key, storyFn, { ...parameters, ...decoratorParams }); + kind.add(name || displayName(key), storyFn, { ...parameters, ...decoratorParams }); } }); }); From dea0634b07c2294bbc25fceb7df6f50d9e6c8a90 Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Tue, 27 Aug 2019 18:05:36 +0800 Subject: [PATCH 2/5] Update snapshots --- .../mdx-compiler-plugin.test.js.snap | 5 ++ .../__snapshots__/htmlshots.test.js.snap | 10 ++-- .../__snapshots__/svelteshots.test.js.snap | 6 +- .../__snapshots__/vueshots.test.js.snap | 56 +++++++++---------- 4 files changed, 41 insertions(+), 36 deletions(-) diff --git a/addons/docs/src/mdx/__snapshots__/mdx-compiler-plugin.test.js.snap b/addons/docs/src/mdx/__snapshots__/mdx-compiler-plugin.test.js.snap index fd74553dda9a..b8012e8691cf 100644 --- a/addons/docs/src/mdx/__snapshots__/mdx-compiler-plugin.test.js.snap +++ b/addons/docs/src/mdx/__snapshots__/mdx-compiler-plugin.test.js.snap @@ -53,6 +53,7 @@ MDXContent.isMDXComponent = true; export const one = () => ; one.story = {}; +one.story.name = 'one'; one.story.parameters = { mdxSource: '' }; one.story.decorators = [storyFn =>
{storyFn()}
]; @@ -177,6 +178,7 @@ MDXContent.isMDXComponent = true; export const one = () => ; one.story = {}; +one.story.name = 'one'; one.story.parameters = { mdxSource: '' }; export const helloStory = () => ; @@ -334,6 +336,7 @@ helloButton.story.parameters = { mdxSource: '' }; export const two = () => ; two.story = {}; +two.story.name = 'two'; two.story.parameters = { mdxSource: '' }; const componentMeta = { @@ -431,6 +434,7 @@ MDXContent.isMDXComponent = true; export const text = () => 'Plain text'; text.story = {}; +text.story.name = 'text'; text.story.parameters = { mdxSource: \\"'Plain text'\\" }; const componentMeta = { title: 'Text', includeStories: ['text'] }; @@ -487,6 +491,7 @@ MDXContent.isMDXComponent = true; export const one = () => ; one.story = {}; +one.story.name = 'one'; one.story.parameters = { mdxSource: '' }; export const helloStory = () => ; diff --git a/examples/html-kitchen-sink/tests/__snapshots__/htmlshots.test.js.snap b/examples/html-kitchen-sink/tests/__snapshots__/htmlshots.test.js.snap index f4a8859c0f4e..eb7e582bd341 100644 --- a/examples/html-kitchen-sink/tests/__snapshots__/htmlshots.test.js.snap +++ b/examples/html-kitchen-sink/tests/__snapshots__/htmlshots.test.js.snap @@ -98,7 +98,7 @@ exports[`Storyshots Addons|Events Logger 1`] = ` `; -exports[`Storyshots Addons|Jest withTests 1`] = `This story shows test results`; +exports[`Storyshots Addons|Jest With Tests 1`] = `This story shows test results`; exports[`Storyshots Addons|Knobs All knobs 1`] = `
`; -exports[`Storyshots Demo button 1`] = ` +exports[`Storyshots Demo Button 1`] = ` `; -exports[`Storyshots Demo effect 1`] = ` +exports[`Storyshots Demo Effect 1`] = ` `; -exports[`Storyshots Demo heading 1`] = ` +exports[`Storyshots Demo Heading 1`] = `

Hello World

`; -exports[`Storyshots Demo headings 1`] = ` +exports[`Storyshots Demo Headings 1`] = `

Hello World diff --git a/examples/svelte-kitchen-sink/__snapshots__/svelteshots.test.js.snap b/examples/svelte-kitchen-sink/__snapshots__/svelteshots.test.js.snap index 380555d1b05e..c732d5c30a82 100644 --- a/examples/svelte-kitchen-sink/__snapshots__/svelteshots.test.js.snap +++ b/examples/svelte-kitchen-sink/__snapshots__/svelteshots.test.js.snap @@ -103,7 +103,7 @@ exports[`Storyshots Addon|Backgrounds story 1 1`] = `

`; -exports[`Storyshots Addon|Centered rounded 1`] = ` +exports[`Storyshots Addon|Centered Rounded 1`] = `
@@ -267,7 +267,7 @@ exports[`Storyshots Addon|Notes Simple note 1`] = `
`; -exports[`Storyshots Button rounded 1`] = ` +exports[`Storyshots Button Rounded 1`] = `
@@ -309,7 +309,7 @@ exports[`Storyshots Button rounded 1`] = `
`; -exports[`Storyshots Button square 1`] = ` +exports[`Storyshots Button Square 1`] = `
diff --git a/examples/vue-kitchen-sink/__snapshots__/vueshots.test.js.snap b/examples/vue-kitchen-sink/__snapshots__/vueshots.test.js.snap index 589366792ca5..bc0b461c4489 100644 --- a/examples/vue-kitchen-sink/__snapshots__/vueshots.test.js.snap +++ b/examples/vue-kitchen-sink/__snapshots__/vueshots.test.js.snap @@ -48,7 +48,7 @@ exports[`Storyshots Addon|Backgrounds story 2 1`] = ` `; -exports[`Storyshots Addon|Centered rounded 1`] = ` +exports[`Storyshots Addon|Centered Rounded 1`] = `
@@ -260,7 +260,7 @@ exports[`Storyshots App App 1`] = `
`; -exports[`Storyshots Button rounded 1`] = ` +exports[`Storyshots Button Rounded 1`] = ` `; +exports[`Storyshots Custom|Method for rendering Vue Render 1`] = ` +
+ renders a div with some text in it.. +
+`; + +exports[`Storyshots Custom|Method for rendering Vue Template 1`] = ` +
+

+ A template +

+ +

+ rendered in vue in storybook +

+
+`; + exports[`Storyshots Custom|Method for rendering Vue pre-registered component 1`] = `

@@ -393,12 +411,6 @@ exports[`Storyshots Custom|Method for rendering Vue render + component 1`] = ` `; -exports[`Storyshots Custom|Method for rendering Vue render 1`] = ` -

- renders a div with some text in it.. -
-`; - exports[`Storyshots Custom|Method for rendering Vue template + component 1`] = ` `; -exports[`Storyshots Addons|Actions Decorated actions 1`] = ` +exports[`Storyshots Addons|Actions story2 1`] = ` `; -exports[`Storyshots Addons|Actions Hello World 1`] = ` +exports[`Storyshots Addons|Actions story3 1`] = ` `; -exports[`Storyshots Addons|Actions Multiple actions + config 1`] = ` +exports[`Storyshots Addons|Actions story4 1`] = ` `; -exports[`Storyshots Addons|Actions Multiple actions 1`] = ` +exports[`Storyshots Addons|Actions story5 1`] = ` + + +`; + +exports[`Storyshots Addons|Actions story6 1`] = ` `; -exports[`Storyshots Addons|Actions Multiple actions, object + config 1`] = ` +exports[`Storyshots Addons|Actions story7 1`] = ` `; -exports[`Storyshots Addons|Actions Multiple actions, object 1`] = ` +exports[`Storyshots Addons|Actions story8 1`] = ` `; -exports[`Storyshots Addons|Actions Multiple actions, selector 1`] = ` - - -`; - -exports[`Storyshots Addons|Backgrounds story 1 1`] = ` +exports[`Storyshots Addons|Backgrounds story1 1`] = ` @@ -69,7 +69,7 @@ exports[`Storyshots Addons|Backgrounds story 1 1`] = ` `; -exports[`Storyshots Addons|Backgrounds story 2 1`] = ` +exports[`Storyshots Addons|Backgrounds story2 1`] = ` @@ -77,7 +77,7 @@ exports[`Storyshots Addons|Backgrounds story 2 1`] = ` `; -exports[`Storyshots Addons|Centered button in center 1`] = ` +exports[`Storyshots Addons|Centered story1 1`] = `
+ John Doe +

+`; + +exports[`Storyshots Addons|Knobs Simple 1`] = ` +
+ I am John Doe and I'm 44 years old. +
+`; + +exports[`Storyshots Addons|Knobs story3 1`] = ` +

+ John Doe +

+`; + +exports[`Storyshots Addons|Knobs story4 1`] = `
@@ -147,29 +167,9 @@ exports[`Storyshots Addons|Knobs All knobs 1`] = `
`; -exports[`Storyshots Addons|Knobs CSS transitions 1`] = ` -

- John Doe -

-`; - -exports[`Storyshots Addons|Knobs DOM 1`] = ` -

- John Doe -

-`; - -exports[`Storyshots Addons|Knobs Simple 1`] = ` -
- I am John Doe and I'm 44 years old. -
-`; - -exports[`Storyshots Addons|Knobs XSS safety 1`] = `<img src=x onerror="alert('XSS Attack')" >`; +exports[`Storyshots Addons|Knobs story5 1`] = `<img src=x onerror="alert('XSS Attack')" >`; -exports[`Storyshots Addons|Notes Simple note 1`] = ` +exports[`Storyshots Addons|Notes story1 1`] = `

@@ -185,8 +185,6 @@ exports[`Storyshots Addons|Notes Simple note 1`] = ` exports[`Storyshots Addons|a11y Default 1`] = ` `; -exports[`Storyshots Addons|a11y Label 1`] = ` - `; -exports[`Storyshots Demo Button 1`] = ` +exports[`Storyshots Addons|a11y story5 1`] = `

`; + +exports[`Storyshots Demo button 1`] = ` `; -exports[`Storyshots Demo Effect 1`] = ` +exports[`Storyshots Demo effect 1`] = ` `; -exports[`Storyshots Demo Heading 1`] = ` +exports[`Storyshots Demo heading 1`] = `

Hello World

`; -exports[`Storyshots Demo Headings 1`] = ` +exports[`Storyshots Demo headings 1`] = `

Hello World diff --git a/examples/official-storybook/config.js b/examples/official-storybook/config.js index 7cabbbb918de..2e61f87c49dc 100644 --- a/examples/official-storybook/config.js +++ b/examples/official-storybook/config.js @@ -1,4 +1,5 @@ import React from 'react'; +import startCase from 'lodash/startCase'; import { configure, addDecorator, addParameters } from '@storybook/react'; import { Global, ThemeProvider, themes, createReset, convert } from '@storybook/theming'; import { withCssResources } from '@storybook/addon-cssresources'; @@ -52,6 +53,7 @@ addParameters({ theme: themes.light, // { base: 'dark', brandTitle: 'Storybook!' }, storySort: (a, b) => a[1].kind === b[1].kind ? 0 : a[1].id.localeCompare(b[1].id, { numeric: true }), + displayName: key => startCase(key).toLowerCase(), }, backgrounds: [ { name: 'storybook app', value: themes.light.appBg, default: true }, diff --git a/examples/official-storybook/package.json b/examples/official-storybook/package.json index 141129452149..8e138f93799a 100644 --- a/examples/official-storybook/package.json +++ b/examples/official-storybook/package.json @@ -53,6 +53,7 @@ "global": "^4.3.2", "graphql": "^14.1.1", "jest-emotion": "^10.0.11", + "lodash": "^4.17.11", "paths.macro": "^2.0.2", "prop-types": "^15.7.2", "react": "^16.8.3", diff --git a/examples/preact-kitchen-sink/__snapshots__/preactshots.test.js.snap b/examples/preact-kitchen-sink/__snapshots__/preactshots.test.js.snap index b2a8566165f5..03e16240ac8a 100644 --- a/examples/preact-kitchen-sink/__snapshots__/preactshots.test.js.snap +++ b/examples/preact-kitchen-sink/__snapshots__/preactshots.test.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addons|Actions Action and method 1`] = ` +exports[`Storyshots Addons|Actions actionAndMethod 1`] = ` `; -exports[`Storyshots Addons|Backgrounds Example 2 1`] = ` +exports[`Storyshots Addons|Backgrounds example2 1`] = ` `; -exports[`Storyshots Addons|Centered Button 1`] = ` +exports[`Storyshots Addons|Centered button 1`] = `
`; -exports[`Storyshots Addons|Contexts Simple CSS Theming 1`] = ` +exports[`Storyshots Addons|Contexts simpleCssTheming 1`] = `
`; -exports[`Storyshots Addons|Knobs All knobs 1`] = ` +exports[`Storyshots Addons|Knobs Simple 1`] = ` +
+ I am John Doe and I'm 44 years old. +
+`; + +exports[`Storyshots Addons|Knobs allKnobs 1`] = `
@@ -136,13 +142,7 @@ exports[`Storyshots Addons|Knobs All knobs 1`] = `
`; -exports[`Storyshots Addons|Knobs Simple 1`] = ` -
- I am John Doe and I'm 44 years old. -
-`; - -exports[`Storyshots Addons|Links Go to welcome 1`] = ` +exports[`Storyshots Addons|Links goToWelcome 1`] = `

`; -exports[`Storyshots Addon|Actions Action on view method 1`] = ` +exports[`Storyshots Addon|Actions actionOnViewMethod 1`] = `
@@ -61,7 +61,7 @@ exports[`Storyshots Addon|Actions Action on view method 1`] = `
`; -exports[`Storyshots Addon|Backgrounds story 1 1`] = ` +exports[`Storyshots Addon|Backgrounds story1 1`] = `
@@ -103,7 +103,7 @@ exports[`Storyshots Addon|Backgrounds story 1 1`] = `
`; -exports[`Storyshots Addon|Centered Rounded 1`] = ` +exports[`Storyshots Addon|Centered rounded 1`] = `
@@ -122,7 +122,7 @@ exports[`Storyshots Addon|Centered Rounded 1`] = `
`; -exports[`Storyshots Addon|Centered with action 1`] = ` +exports[`Storyshots Addon|Centered withAction 1`] = `
@@ -155,7 +155,7 @@ exports[`Storyshots Addon|Knobs Simple 1`] = `
`; -exports[`Storyshots Addon|Links Go to welcome view 1`] = ` +exports[`Storyshots Addon|Links goToWelcomeView 1`] = `
@@ -183,7 +183,7 @@ exports[`Storyshots Addon|Links Go to welcome view 1`] = `
`; -exports[`Storyshots Addon|Notes Note with HTML 1`] = ` +exports[`Storyshots Addon|Notes noteWithHtml 1`] = `
@@ -225,7 +225,7 @@ exports[`Storyshots Addon|Notes Note with HTML 1`] = `
`; -exports[`Storyshots Addon|Notes Simple note 1`] = ` +exports[`Storyshots Addon|Notes simpleNote 1`] = `
@@ -267,7 +267,7 @@ exports[`Storyshots Addon|Notes Simple note 1`] = `
`; -exports[`Storyshots Button Rounded 1`] = ` +exports[`Storyshots Button rounded 1`] = `
@@ -309,7 +309,7 @@ exports[`Storyshots Button Rounded 1`] = `
`; -exports[`Storyshots Button Square 1`] = ` +exports[`Storyshots Button square 1`] = `
diff --git a/examples/vue-kitchen-sink/__snapshots__/vueshots.test.js.snap b/examples/vue-kitchen-sink/__snapshots__/vueshots.test.js.snap index bc0b461c4489..159ad8a0a3f6 100644 --- a/examples/vue-kitchen-sink/__snapshots__/vueshots.test.js.snap +++ b/examples/vue-kitchen-sink/__snapshots__/vueshots.test.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Storyshots Addon|Actions Action and method 1`] = ` +exports[`Storyshots Addon|Actions actionAndMethod 1`] = ` `; -exports[`Storyshots Addon|Backgrounds story 2 1`] = ` +exports[`Storyshots Addon|Backgrounds story2 1`] = ` `; -exports[`Storyshots Addon|Centered Rounded 1`] = ` +exports[`Storyshots Addon|Centered rounded 1`] = `
@@ -77,7 +77,7 @@ exports[`Storyshots Addon|Contexts Languages 1`] = `
`; -exports[`Storyshots Addon|Contexts Simple CSS Theming 1`] = ` +exports[`Storyshots Addon|Contexts simpleCssTheming 1`] = `
@@ -87,7 +87,13 @@ exports[`Storyshots Addon|Contexts Simple CSS Theming 1`] = `
`; -exports[`Storyshots Addon|Knobs All knobs 1`] = ` +exports[`Storyshots Addon|Knobs Simple 1`] = ` +
+ I am John Doe and I'm 40 years old. +
+`; + +exports[`Storyshots Addon|Knobs allKnobs 1`] = `
@@ -125,19 +131,13 @@ exports[`Storyshots Addon|Knobs All knobs 1`] = `
`; -exports[`Storyshots Addon|Knobs Simple 1`] = ` -
- I am John Doe and I'm 40 years old. -
-`; - -exports[`Storyshots Addon|Knobs XSS safety 1`] = ` +exports[`Storyshots Addon|Knobs xssSafety 1`] = `
<img src=x onerror="alert('XSS Attack')" >
`; -exports[`Storyshots Addon|Links Go to welcome 1`] = ` +exports[`Storyshots Addon|Links goToWelcome 1`] = ` `; -exports[`Storyshots Custom|Method for rendering Vue Render 1`] = ` -
- renders a div with some text in it.. -
-`; - -exports[`Storyshots Custom|Method for rendering Vue Template 1`] = ` -
-

- A template -

- -

- rendered in vue in storybook -

-
-`; - -exports[`Storyshots Custom|Method for rendering Vue pre-registered component 1`] = ` +exports[`Storyshots Custom|Method for rendering Vue preRegisteredComponent 1`] = `

This component was pre-registered in .storybook/config.js @@ -402,7 +385,13 @@ exports[`Storyshots Custom|Method for rendering Vue pre-registered component 1`]

`; -exports[`Storyshots Custom|Method for rendering Vue render + component 1`] = ` +exports[`Storyshots Custom|Method for rendering Vue render 1`] = ` +
+ renders a div with some text in it.. +
+`; + +exports[`Storyshots Custom|Method for rendering Vue renderComponent 1`] = `