mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-05 07:01:27 +08:00
Merge pull request #16159 from storybookjs/15762-mdx-csf3-support
MDX: Support CSF3 play/render functions
This commit is contained in:
commit
8395c06d04
@ -22,11 +22,7 @@ export const storyBlockIdFromId = (storyId: string) => `story--${storyId}`;
|
||||
|
||||
type PureStoryProps = ComponentProps<typeof PureStory>;
|
||||
|
||||
type Annotations = Pick<
|
||||
StoryAnnotations,
|
||||
'decorators' | 'parameters' | 'args' | 'argTypes' | 'loaders'
|
||||
>;
|
||||
type CommonProps = Annotations & {
|
||||
type CommonProps = StoryAnnotations & {
|
||||
height?: string;
|
||||
inline?: boolean;
|
||||
};
|
||||
|
@ -0,0 +1,28 @@
|
||||
import { Meta, Story } from '@storybook/addon-docs';
|
||||
import Button from '../../components/TsButton';
|
||||
|
||||
<Meta
|
||||
title="csf3"
|
||||
component={Button}
|
||||
play={() => console.log('component play')}
|
||||
render={(args) => (
|
||||
<div style={{ border: '5px solid green' }}>
|
||||
<Button {...args} />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
|
||||
# CSF3 Features
|
||||
|
||||
<Story name="Inherited Render" />
|
||||
|
||||
<Story
|
||||
name="Story Render"
|
||||
render={(args) => (
|
||||
<div style={{ border: '5px solid red' }}>
|
||||
<Button {...args} />
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Story name="Story Play" play={() => console.log('story play')} />
|
@ -0,0 +1,45 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`docs-mdx-compiler-plugin csf3 auto-title-docs-only.mdx 1`] = `
|
||||
"/* @jsxRuntime classic */
|
||||
/* @jsx mdx */
|
||||
import { assertIsFn, AddContext } from '@storybook/addon-docs';
|
||||
|
||||
const layoutProps = {};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<pre>
|
||||
<code parentName=\\"pre\\" {...{}}>{\` import { Meta } from '@storybook/addon-docs';
|
||||
|
||||
<Meta />
|
||||
|
||||
# Auto-title Docs Only
|
||||
|
||||
Spme **markdown** here!
|
||||
\`}</code>
|
||||
</pre>
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
const componentMeta = { includeStories: [] };
|
||||
|
||||
const mdxStoryNameToKey = {};
|
||||
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = {
|
||||
...(componentMeta.parameters.docs || {}),
|
||||
page: () => (
|
||||
<AddContext mdxStoryNameToKey={mdxStoryNameToKey} mdxComponentAnnotations={componentMeta}>
|
||||
<MDXContent />
|
||||
</AddContext>
|
||||
),
|
||||
};
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
@ -0,0 +1,46 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`docs-mdx-compiler-plugin csf3 auto-title.mdx 1`] = `
|
||||
"/* @jsxRuntime classic */
|
||||
/* @jsx mdx */
|
||||
import { assertIsFn, AddContext } from '@storybook/addon-docs';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs';
|
||||
|
||||
const layoutProps = {};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<Meta component={Button} mdxType=\\"Meta\\" />
|
||||
<Story name=\\"Basic\\" mdxType=\\"Story\\">
|
||||
<Button mdxType=\\"Button\\">Basic</Button>
|
||||
</Story>
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const basic = () => <Button>Basic</Button>;
|
||||
basic.storyName = 'Basic';
|
||||
basic.parameters = { storySource: { source: '<Button>Basic</Button>' } };
|
||||
|
||||
const componentMeta = { component: Button, includeStories: ['basic'] };
|
||||
|
||||
const mdxStoryNameToKey = { Basic: 'basic' };
|
||||
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = {
|
||||
...(componentMeta.parameters.docs || {}),
|
||||
page: () => (
|
||||
<AddContext mdxStoryNameToKey={mdxStoryNameToKey} mdxComponentAnnotations={componentMeta}>
|
||||
<MDXContent />
|
||||
</AddContext>
|
||||
),
|
||||
};
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
@ -0,0 +1,54 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`docs-mdx-compiler-plugin csf3 component-render.mdx 1`] = `
|
||||
"/* @jsxRuntime classic */
|
||||
/* @jsx mdx */
|
||||
import { assertIsFn, AddContext } from '@storybook/addon-docs';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs';
|
||||
|
||||
const layoutProps = {};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<Meta
|
||||
title=\\"Button\\"
|
||||
component={Button}
|
||||
render={(args) => <Button {...args} mdxType=\\"Button\\" />}
|
||||
mdxType=\\"Meta\\"
|
||||
/>
|
||||
<Story name=\\"Basic\\" mdxType=\\"Story\\" />
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const basic = {};
|
||||
basic.storyName = 'Basic';
|
||||
basic.parameters = { storySource: { source: '{}' } };
|
||||
|
||||
const componentMeta = {
|
||||
title: 'Button',
|
||||
component: Button,
|
||||
render: (args) => <Button {...args} />,
|
||||
includeStories: ['basic'],
|
||||
};
|
||||
|
||||
const mdxStoryNameToKey = { Basic: 'basic' };
|
||||
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = {
|
||||
...(componentMeta.parameters.docs || {}),
|
||||
page: () => (
|
||||
<AddContext mdxStoryNameToKey={mdxStoryNameToKey} mdxComponentAnnotations={componentMeta}>
|
||||
<MDXContent />
|
||||
</AddContext>
|
||||
),
|
||||
};
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
@ -0,0 +1,44 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`docs-mdx-compiler-plugin csf3 default-render.mdx 1`] = `
|
||||
"/* @jsxRuntime classic */
|
||||
/* @jsx mdx */
|
||||
import { assertIsFn, AddContext } from '@storybook/addon-docs';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs';
|
||||
|
||||
const layoutProps = {};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<Meta title=\\"Button\\" component={Button} mdxType=\\"Meta\\" />
|
||||
<Story name=\\"Basic\\" mdxType=\\"Story\\" />
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const basic = {};
|
||||
basic.storyName = 'Basic';
|
||||
basic.parameters = { storySource: { source: '{}' } };
|
||||
|
||||
const componentMeta = { title: 'Button', component: Button, includeStories: ['basic'] };
|
||||
|
||||
const mdxStoryNameToKey = { Basic: 'basic' };
|
||||
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = {
|
||||
...(componentMeta.parameters.docs || {}),
|
||||
page: () => (
|
||||
<AddContext mdxStoryNameToKey={mdxStoryNameToKey} mdxComponentAnnotations={componentMeta}>
|
||||
<MDXContent />
|
||||
</AddContext>
|
||||
),
|
||||
};
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
@ -0,0 +1,45 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`docs-mdx-compiler-plugin csf3 story-play.mdx 1`] = `
|
||||
"/* @jsxRuntime classic */
|
||||
/* @jsx mdx */
|
||||
import { assertIsFn, AddContext } from '@storybook/addon-docs';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs';
|
||||
|
||||
const layoutProps = {};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<Meta title=\\"Button\\" component={Button} mdxType=\\"Meta\\" />
|
||||
<Story name=\\"Basic\\" play={() => console.log('play')} mdxType=\\"Story\\" />
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const basic = {};
|
||||
basic.storyName = 'Basic';
|
||||
basic.parameters = { storySource: { source: '{}' } };
|
||||
basic.play = () => console.log('play');
|
||||
|
||||
const componentMeta = { title: 'Button', component: Button, includeStories: ['basic'] };
|
||||
|
||||
const mdxStoryNameToKey = { Basic: 'basic' };
|
||||
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = {
|
||||
...(componentMeta.parameters.docs || {}),
|
||||
page: () => (
|
||||
<AddContext mdxStoryNameToKey={mdxStoryNameToKey} mdxComponentAnnotations={componentMeta}>
|
||||
<MDXContent />
|
||||
</AddContext>
|
||||
),
|
||||
};
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
@ -0,0 +1,49 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`docs-mdx-compiler-plugin csf3 story-render.mdx 1`] = `
|
||||
"/* @jsxRuntime classic */
|
||||
/* @jsx mdx */
|
||||
import { assertIsFn, AddContext } from '@storybook/addon-docs';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs';
|
||||
|
||||
const layoutProps = {};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<Meta title=\\"Button\\" component={Button} mdxType=\\"Meta\\" />
|
||||
<Story
|
||||
name=\\"Basic\\"
|
||||
render={(args) => <Button {...args} mdxType=\\"Button\\" />}
|
||||
mdxType=\\"Story\\"
|
||||
/>
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const basic = {};
|
||||
basic.storyName = 'Basic';
|
||||
basic.parameters = { storySource: { source: '{}' } };
|
||||
basic.render = (args) => <Button {...args} />;
|
||||
|
||||
const componentMeta = { title: 'Button', component: Button, includeStories: ['basic'] };
|
||||
|
||||
const mdxStoryNameToKey = { Basic: 'basic' };
|
||||
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = {
|
||||
...(componentMeta.parameters.docs || {}),
|
||||
page: () => (
|
||||
<AddContext mdxStoryNameToKey={mdxStoryNameToKey} mdxComponentAnnotations={componentMeta}>
|
||||
<MDXContent />
|
||||
</AddContext>
|
||||
),
|
||||
};
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
@ -426,4 +426,87 @@ describe('docs-mdx-compiler-plugin', () => {
|
||||
`)
|
||||
).rejects.toThrow('Expected a Story name, id, or story attribute');
|
||||
});
|
||||
|
||||
describe('csf3', () => {
|
||||
it('auto-title-docs-only.mdx', () => {
|
||||
expect(
|
||||
generate(dedent`
|
||||
import { Meta } from '@storybook/addon-docs';
|
||||
|
||||
<Meta />
|
||||
|
||||
# Auto-title Docs Only
|
||||
|
||||
Spme **markdown** here!
|
||||
`)
|
||||
).toMatchSpecificSnapshot(snap('auto-title-docs-only'));
|
||||
});
|
||||
|
||||
it('auto-title.mdx', () => {
|
||||
expect(
|
||||
generate(dedent`
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs';
|
||||
|
||||
<Meta component={Button} />
|
||||
|
||||
<Story name="Basic">
|
||||
<Button>Basic</Button>
|
||||
</Story>
|
||||
`)
|
||||
).toMatchSpecificSnapshot(snap('auto-title'));
|
||||
});
|
||||
|
||||
it('default-render.mdx', () => {
|
||||
expect(
|
||||
generate(dedent`
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs';
|
||||
|
||||
<Meta title="Button" component={Button} />
|
||||
|
||||
<Story name="Basic" />
|
||||
`)
|
||||
).toMatchSpecificSnapshot(snap('default-render'));
|
||||
});
|
||||
|
||||
it('component-render.mdx', () => {
|
||||
expect(
|
||||
generate(dedent`
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs';
|
||||
|
||||
<Meta title="Button" component={Button} render={(args) => <Button {...args} />} />
|
||||
|
||||
<Story name="Basic" />
|
||||
`)
|
||||
).toMatchSpecificSnapshot(snap('component-render'));
|
||||
});
|
||||
|
||||
it('story-render.mdx', () => {
|
||||
expect(
|
||||
generate(dedent`
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs';
|
||||
|
||||
<Meta title="Button" component={Button} />
|
||||
|
||||
<Story name="Basic" render={(args) => <Button {...args} />} />
|
||||
`)
|
||||
).toMatchSpecificSnapshot(snap('story-render'));
|
||||
});
|
||||
|
||||
it('story-play.mdx', () => {
|
||||
expect(
|
||||
generate(dedent`
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs';
|
||||
|
||||
<Meta title="Button" component={Button} />
|
||||
|
||||
<Story name="Basic" play={() => console.log('play')} />
|
||||
`)
|
||||
).toMatchSpecificSnapshot(snap('story-play'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -152,6 +152,7 @@ function genStoryExport(ast: t.JSXElement, context: Context) {
|
||||
let sourceCode = null;
|
||||
let storyVal = null;
|
||||
if (!bodyNodes.length) {
|
||||
if (ast.children.length > 0) {
|
||||
// plain text node
|
||||
const { code } = generate(ast.children[0], {});
|
||||
storyCode = `'${code}'`;
|
||||
@ -159,6 +160,10 @@ function genStoryExport(ast: t.JSXElement, context: Context) {
|
||||
storyVal = `() => (
|
||||
${storyCode}
|
||||
)`;
|
||||
} else {
|
||||
sourceCode = '{}';
|
||||
storyVal = '{}';
|
||||
}
|
||||
} else {
|
||||
const bodyParts = bodyNodes.map((bodyNode) => getBodyPart(bodyNode, context));
|
||||
// if we have more than two children
|
||||
@ -222,6 +227,18 @@ function genStoryExport(ast: t.JSXElement, context: Context) {
|
||||
statements.push(`${storyKey}.loaders = ${loaderCode};`);
|
||||
}
|
||||
|
||||
const play = expressionOrNull(getAttr(ast.openingElement, 'play'));
|
||||
if (play) {
|
||||
const { code: playCode } = generate(play, {});
|
||||
statements.push(`${storyKey}.play = ${playCode};`);
|
||||
}
|
||||
|
||||
const render = expressionOrNull(getAttr(ast.openingElement, 'render'));
|
||||
if (render) {
|
||||
const { code: renderCode } = generate(render, {});
|
||||
statements.push(`${storyKey}.render = ${renderCode};`);
|
||||
}
|
||||
|
||||
context.storyNameToKey[storyName] = storyKey;
|
||||
|
||||
return {
|
||||
@ -282,6 +299,7 @@ function genMeta(ast: t.JSXElement, options: CompilerOptions) {
|
||||
const subcomponents = genAttribute('subcomponents', ast.openingElement);
|
||||
const args = genAttribute('args', ast.openingElement);
|
||||
const argTypes = genAttribute('argTypes', ast.openingElement);
|
||||
const render = genAttribute('render', ast.openingElement);
|
||||
|
||||
return {
|
||||
title,
|
||||
@ -293,6 +311,7 @@ function genMeta(ast: t.JSXElement, options: CompilerOptions) {
|
||||
subcomponents,
|
||||
args,
|
||||
argTypes,
|
||||
render,
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user