mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-08 11:11:53 +08:00
Merge pull request #1582 from TrevorEyre/codemod-addWithInfo
Added codemod for deprecated addon-info API
This commit is contained in:
commit
f3fa02f630
@ -38,7 +38,7 @@ Explanation:
|
||||
|
||||
## Transforms
|
||||
|
||||
### add-organisation-to-package-name
|
||||
### update-organisation-name
|
||||
|
||||
Updates package names in imports to migrate to the new package names of storybook.
|
||||
|
||||
@ -61,3 +61,58 @@ Becomes
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { linkTo } from '@storybook/addon-links';
|
||||
```
|
||||
|
||||
### update-addon-info
|
||||
|
||||
Replaces the Info addon's deprecated `addWithInfo` API with the standard `withInfo` API.
|
||||
|
||||
```sh
|
||||
./node_modules/.bin/jscodeshift -t ./node_modules/@storybook/codemod/dist/transforms/update-addon-info.js . --ignore-pattern "node_modules|dist"
|
||||
```
|
||||
|
||||
Simple example:
|
||||
|
||||
```js
|
||||
storiesOf('Button').addWithInfo(
|
||||
'simple usage',
|
||||
'This is the basic usage of the button.',
|
||||
() => (
|
||||
<Button label="The Button" />
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
Becomes
|
||||
|
||||
```js
|
||||
storiesOf('Button').add('simple usage', withInfo(
|
||||
'This is the basic usage of the button.'
|
||||
)(() => (
|
||||
<Button label="The Button" />
|
||||
)))
|
||||
```
|
||||
|
||||
With options example:
|
||||
|
||||
```js
|
||||
storiesOf('Button').addWithInfo(
|
||||
'simple usage (disable source)',
|
||||
'This is the basic usage of the button.',
|
||||
() => (
|
||||
<Button label="The Button" />
|
||||
),
|
||||
{ source: false, inline: true }
|
||||
)
|
||||
```
|
||||
|
||||
Becomes
|
||||
|
||||
```js
|
||||
storiesOf('Button').add('simple usage (disable source)', withInfo({
|
||||
text: 'This is the basic usage of the button.',
|
||||
source: false,
|
||||
inline: true
|
||||
})(() => (
|
||||
<Button label="The Button" />
|
||||
)))
|
||||
```
|
||||
|
@ -4,3 +4,7 @@ export {
|
||||
default as updateOrganisationName,
|
||||
packageNames,
|
||||
} from './transforms/update-organisation-name';
|
||||
|
||||
export {
|
||||
default as updateAddonInfo
|
||||
} from './transforms/update-addon-info';
|
||||
|
@ -0,0 +1,190 @@
|
||||
/* eslint-disable */
|
||||
import React from 'react'
|
||||
import Button from './Button'
|
||||
|
||||
import { storiesOf } from '@storybook/react'
|
||||
import { action } from '@storybook/addon-actions'
|
||||
|
||||
storiesOf(
|
||||
'Button'
|
||||
).addWithInfo(
|
||||
'simple usage',
|
||||
'This is the basic usage with the button with providing a label to show the text.',
|
||||
() => (
|
||||
<div>
|
||||
<Button label="The Button" onClick={action('onClick')} />
|
||||
<br />
|
||||
<p>
|
||||
Click the "?" mark at top-right to view the info.
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
|
||||
storiesOf('Button').addWithInfo(
|
||||
'simple usage (inline info)',
|
||||
`
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
`,
|
||||
() => <Button label="The Button" onClick={action('onClick')} />,
|
||||
{ inline: true }
|
||||
)
|
||||
|
||||
storiesOf('Button').addWithInfo(
|
||||
'simple usage (disable source)',
|
||||
`
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
`,
|
||||
() => <Button label="The Button" onClick={action('onClick')} />,
|
||||
{ source: false, inline: true }
|
||||
)
|
||||
|
||||
storiesOf('Button').addWithInfo(
|
||||
'simple usage (no header)',
|
||||
`
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
`,
|
||||
() => <Button label="The Button" onClick={action('onClick')} />,
|
||||
{ header: false, inline: true }
|
||||
)
|
||||
|
||||
storiesOf('Button').addWithInfo(
|
||||
'simple usage (no prop tables)',
|
||||
`
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
`,
|
||||
() => <Button label="The Button" onClick={action('onClick')} />,
|
||||
{ propTables: false, inline: true }
|
||||
)
|
||||
|
||||
storiesOf('Button').addWithInfo(
|
||||
'simple usage (custom propTables)',
|
||||
`
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
Since, the story source code is wrapped inside a div, info addon can't figure out propTypes on it's own.
|
||||
So, we need to give relevant React component classes manually using \`propTypes\` option as shown below:
|
||||
~~~js
|
||||
storiesOf('Button')
|
||||
.addWithInfo(
|
||||
'simple usage (custom propTables)',
|
||||
<info>,
|
||||
<storyFn>,
|
||||
{ inline: true, propTables: [Button]}
|
||||
);
|
||||
~~~
|
||||
`,
|
||||
() => (
|
||||
<div>
|
||||
<Button label="The Button" onClick={action('onClick')} />
|
||||
<br />
|
||||
</div>
|
||||
),
|
||||
{ inline: true, propTables: [Button] }
|
||||
)
|
||||
|
||||
storiesOf('Button').addWithInfo(
|
||||
'simple usage (JSX description)',
|
||||
<div>
|
||||
<h2>This is a JSX info section</h2>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed ornare massa rutrum metus commodo, a mattis velit dignissim.
|
||||
Fusce vestibulum turpis sed massa egestas pharetra. Sed at libero
|
||||
nulla.
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://github.com/storybooks/react-storybook-addon-info">
|
||||
This is a link
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<img src="http://placehold.it/350x150" />
|
||||
</p>
|
||||
</div>,
|
||||
() => (
|
||||
<div>
|
||||
<Button label="The Button" onClick={action('onClick')} />
|
||||
<br />
|
||||
<p>
|
||||
Click the "?" mark at top-right to view the info.
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
|
||||
storiesOf('Button').addWithInfo(
|
||||
'simple usage (inline JSX description)',
|
||||
<div>
|
||||
<h2>This is a JSX info section</h2>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed ornare massa rutrum metus commodo, a mattis velit dignissim.
|
||||
Fusce vestibulum turpis sed massa egestas pharetra. Sed at libero
|
||||
nulla.
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://github.com/storybooks/react-storybook-addon-info">
|
||||
This is a link
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<img src="http://placehold.it/350x150" />
|
||||
</p>
|
||||
</div>,
|
||||
() => <Button label="The Button" onClick={action('onClick')} />,
|
||||
{ inline: true }
|
||||
)
|
||||
|
||||
storiesOf('Button').addWithInfo(
|
||||
'simple usage (maxPropsInLine === 1)',
|
||||
`
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
`,
|
||||
() => <Button label="The Button" onClick={action('onClick')} />,
|
||||
{ inline: true, maxPropsIntoLine: 1 }
|
||||
)
|
||||
|
||||
storiesOf('Button').addWithInfo(
|
||||
'simple usage (maxPropObjectKeys === 5)',
|
||||
`
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
`,
|
||||
() => <Button label="The Button" object={{ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 }} />,
|
||||
{ inline: true, maxPropObjectKeys: 5 }
|
||||
)
|
||||
|
||||
storiesOf('Button').addWithInfo(
|
||||
'simple usage (maxPropArrayLength === 8)',
|
||||
`
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
`,
|
||||
() => <Button label="The Button" array={[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]} />,
|
||||
{ inline: true, maxPropArrayLength: 8 }
|
||||
)
|
||||
|
||||
storiesOf('Button').addWithInfo(
|
||||
'simple usage (maxPropStringLength === 10)',
|
||||
`
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
`,
|
||||
() => <Button label="The Button" string="1 2 3 4 5 6 7 8" />,
|
||||
{ inline: true, maxPropStringLength: 5 }
|
||||
)
|
||||
|
||||
storiesOf('Button').addWithInfo(
|
||||
'with custom styles',
|
||||
`
|
||||
This is an example of how to customize the styles of the info components.
|
||||
For the full styles available, see \`./src/components/Story.js\`
|
||||
`,
|
||||
() => <Button label="The Button" onClick={action('onClick')} />,
|
||||
{
|
||||
inline: true,
|
||||
styles: stylesheet => {
|
||||
stylesheet.infoPage = {
|
||||
backgroundColor: '#ccc'
|
||||
}
|
||||
return stylesheet
|
||||
}
|
||||
}
|
||||
)
|
@ -0,0 +1,186 @@
|
||||
/* eslint-disable */
|
||||
import React from 'react'
|
||||
import Button from './Button'
|
||||
|
||||
import { storiesOf } from '@storybook/react'
|
||||
import { action } from '@storybook/addon-actions'
|
||||
|
||||
import { withInfo } from "@storybook/addon-info";
|
||||
|
||||
storiesOf(
|
||||
'Button'
|
||||
).add('simple usage', withInfo(
|
||||
'This is the basic usage with the button with providing a label to show the text.'
|
||||
)(() => (
|
||||
<div>
|
||||
<Button label="The Button" onClick={action('onClick')} />
|
||||
<br />
|
||||
<p>
|
||||
Click the "?" mark at top-right to view the info.
|
||||
</p>
|
||||
</div>
|
||||
)))
|
||||
|
||||
storiesOf('Button').add('simple usage (inline info)', withInfo({
|
||||
text: `
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
`,
|
||||
|
||||
inline: true
|
||||
})(() => <Button label="The Button" onClick={action('onClick')} />))
|
||||
|
||||
storiesOf('Button').add('simple usage (disable source)', withInfo({
|
||||
text: `
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
`,
|
||||
|
||||
source: false,
|
||||
inline: true
|
||||
})(() => <Button label="The Button" onClick={action('onClick')} />))
|
||||
|
||||
storiesOf('Button').add('simple usage (no header)', withInfo({
|
||||
text: `
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
`,
|
||||
|
||||
header: false,
|
||||
inline: true
|
||||
})(() => <Button label="The Button" onClick={action('onClick')} />))
|
||||
|
||||
storiesOf('Button').add('simple usage (no prop tables)', withInfo({
|
||||
text: `
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
`,
|
||||
|
||||
propTables: false,
|
||||
inline: true
|
||||
})(() => <Button label="The Button" onClick={action('onClick')} />))
|
||||
|
||||
storiesOf('Button').add('simple usage (custom propTables)', withInfo({
|
||||
text: `
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
Since, the story source code is wrapped inside a div, info addon can't figure out propTypes on it's own.
|
||||
So, we need to give relevant React component classes manually using \`propTypes\` option as shown below:
|
||||
~~~js
|
||||
storiesOf('Button')
|
||||
.addWithInfo(
|
||||
'simple usage (custom propTables)',
|
||||
<info>,
|
||||
<storyFn>,
|
||||
{ inline: true, propTables: [Button]}
|
||||
);
|
||||
~~~
|
||||
`,
|
||||
|
||||
inline: true,
|
||||
propTables: [Button]
|
||||
})(() => (
|
||||
<div>
|
||||
<Button label="The Button" onClick={action('onClick')} />
|
||||
<br />
|
||||
</div>
|
||||
)))
|
||||
|
||||
storiesOf('Button').add('simple usage (JSX description)', withInfo(<div>
|
||||
<h2>This is a JSX info section</h2>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed ornare massa rutrum metus commodo, a mattis velit dignissim.
|
||||
Fusce vestibulum turpis sed massa egestas pharetra. Sed at libero
|
||||
nulla.
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://github.com/storybooks/react-storybook-addon-info">
|
||||
This is a link
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<img src="http://placehold.it/350x150" />
|
||||
</p>
|
||||
</div>)(() => (
|
||||
<div>
|
||||
<Button label="The Button" onClick={action('onClick')} />
|
||||
<br />
|
||||
<p>
|
||||
Click the "?" mark at top-right to view the info.
|
||||
</p>
|
||||
</div>
|
||||
)))
|
||||
|
||||
storiesOf('Button').add('simple usage (inline JSX description)', withInfo({
|
||||
text: <div>
|
||||
<h2>This is a JSX info section</h2>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Sed ornare massa rutrum metus commodo, a mattis velit dignissim.
|
||||
Fusce vestibulum turpis sed massa egestas pharetra. Sed at libero
|
||||
nulla.
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://github.com/storybooks/react-storybook-addon-info">
|
||||
This is a link
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<img src="http://placehold.it/350x150" />
|
||||
</p>
|
||||
</div>,
|
||||
|
||||
inline: true
|
||||
})(() => <Button label="The Button" onClick={action('onClick')} />))
|
||||
|
||||
storiesOf('Button').add('simple usage (maxPropsInLine === 1)', withInfo({
|
||||
text: `
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
`,
|
||||
|
||||
inline: true,
|
||||
maxPropsIntoLine: 1
|
||||
})(() => <Button label="The Button" onClick={action('onClick')} />))
|
||||
|
||||
storiesOf('Button').add('simple usage (maxPropObjectKeys === 5)', withInfo({
|
||||
text: `
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
`,
|
||||
|
||||
inline: true,
|
||||
maxPropObjectKeys: 5
|
||||
})(
|
||||
() => <Button label="The Button" object={{ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 }} />
|
||||
))
|
||||
|
||||
storiesOf('Button').add('simple usage (maxPropArrayLength === 8)', withInfo({
|
||||
text: `
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
`,
|
||||
|
||||
inline: true,
|
||||
maxPropArrayLength: 8
|
||||
})(
|
||||
() => <Button label="The Button" array={[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]} />
|
||||
))
|
||||
|
||||
storiesOf('Button').add('simple usage (maxPropStringLength === 10)', withInfo({
|
||||
text: `
|
||||
This is the basic usage with the button with providing a label to show the text.
|
||||
`,
|
||||
|
||||
inline: true,
|
||||
maxPropStringLength: 5
|
||||
})(() => <Button label="The Button" string="1 2 3 4 5 6 7 8" />))
|
||||
|
||||
storiesOf('Button').add('with custom styles', withInfo({
|
||||
text: `
|
||||
This is an example of how to customize the styles of the info components.
|
||||
For the full styles available, see \`./src/components/Story.js\`
|
||||
`,
|
||||
|
||||
inline: true,
|
||||
|
||||
styles: stylesheet => {
|
||||
stylesheet.infoPage = {
|
||||
backgroundColor: '#ccc'
|
||||
}
|
||||
return stylesheet
|
||||
}
|
||||
})(() => <Button label="The Button" onClick={action('onClick')} />))
|
@ -0,0 +1,8 @@
|
||||
import { defineTest } from 'jscodeshift/dist/testUtils';
|
||||
|
||||
defineTest(
|
||||
__dirname,
|
||||
'update-addon-info',
|
||||
null,
|
||||
'update-addon-info/update-addon-info'
|
||||
);
|
112
lib/codemod/src/transforms/update-addon-info.js
Normal file
112
lib/codemod/src/transforms/update-addon-info.js
Normal file
@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Takes the deprecated addon-info API, addWithInfo, and
|
||||
* converts to the new withInfo API.
|
||||
*
|
||||
* Example of deprecated addWithInfo API:
|
||||
*
|
||||
* storiesOf('Button')
|
||||
* .addWithInfo(
|
||||
* 'story name',
|
||||
* 'Story description.',
|
||||
* () => (
|
||||
* <Button label="The Button" />
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* Converts to the new withInfo API:
|
||||
*
|
||||
* storiesOf('Button')
|
||||
* .add('story name', withInfo(
|
||||
* 'Story description.'
|
||||
* )(() => (
|
||||
* <Button label="The Button" />
|
||||
* )))
|
||||
*/
|
||||
export default function transformer (file, api) {
|
||||
const j = api.jscodeshift;
|
||||
const root = j(file.source);
|
||||
|
||||
/**
|
||||
* Returns a list of parameters for the withInfo function. The contents
|
||||
* of this list is either the second argument from the original
|
||||
* addWithInfo function, if no additional options were used, or a
|
||||
* combined object of all the options from the original function.
|
||||
* @param {list} args - original addWithInfo function parameters
|
||||
* @return {list} the modified list of parameters for the new function
|
||||
*/
|
||||
const getOptions = args => {
|
||||
if (args[3] === undefined) {
|
||||
return [args[1]];
|
||||
}
|
||||
return [
|
||||
j.objectExpression([
|
||||
j.property('init', j.identifier('text'), args[1]),
|
||||
...args[3].properties
|
||||
])
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs the new withInfo function from the parameters of the
|
||||
* original addWithInfo function.
|
||||
* @param {CallExpression} addWithInfoExpression - original function
|
||||
* @returns {CallExpression} the new withInfo function
|
||||
*/
|
||||
const withInfo = addWithInfoExpression => {
|
||||
const node = addWithInfoExpression.node;
|
||||
const args = node.arguments;
|
||||
|
||||
node.callee.property.name = 'add';
|
||||
node.arguments = [
|
||||
args[0],
|
||||
j.callExpression(
|
||||
j.callExpression(
|
||||
j.identifier('withInfo'),
|
||||
getOptions(args)
|
||||
),
|
||||
[args[2]]
|
||||
)
|
||||
];
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks for - import { withInfo } from "@storybook/addon-info";
|
||||
* Adds the import if necessary.
|
||||
*/
|
||||
const checkWithInfoImport = () => {
|
||||
const importExists = root.find(j.ImportDeclaration)
|
||||
.filter(imp => imp.node.source.value === '@storybook/addon-info')
|
||||
.size();
|
||||
|
||||
if (importExists) return;
|
||||
|
||||
root.find(j.ImportDeclaration)
|
||||
.at(-1)
|
||||
.insertAfter(
|
||||
j.importDeclaration(
|
||||
[j.importSpecifier(j.identifier('withInfo'))],
|
||||
j.literal('@storybook/addon-info')
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const addWithInfoExpressions = root.find(
|
||||
j.CallExpression,
|
||||
{
|
||||
callee: {
|
||||
property: {
|
||||
name: 'addWithInfo'
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (addWithInfoExpressions.size()) {
|
||||
checkWithInfoImport();
|
||||
addWithInfoExpressions.replaceWith(withInfo);
|
||||
}
|
||||
|
||||
return root.toSource();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user