@storybook/codemod 7.0.0-beta.9 → 7.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -39
- package/dist/index.js +1 -1
- package/dist/transforms/csf-2-to-3.d.ts +5 -4
- package/dist/transforms/csf-2-to-3.js +3 -1
- package/dist/transforms/mdx-to-csf.d.ts +7 -0
- package/dist/transforms/mdx-to-csf.js +55 -0
- package/dist/transforms/storiesof-to-csf.js +1 -1
- package/dist/transforms/upgrade-deprecated-types.d.ts +10 -0
- package/dist/transforms/upgrade-deprecated-types.js +2 -0
- package/jest.config.js +2 -0
- package/package.json +31 -16
- package/project.json +6 -0
- package/src/index.js +30 -4
- package/src/lib/utils.ts +2 -2
- package/src/transforms/__testfixtures__/storiesof-to-csf/decorators.input.js +1 -1
- package/src/transforms/__testfixtures__/storiesof-to-csf/export-function.input.js +1 -1
- package/src/transforms/__testfixtures__/storiesof-to-csf/story-decorators.input.js +1 -1
- package/src/transforms/__testfixtures__/update-addon-info/update-addon-info.input.js +34 -48
- package/src/transforms/__testfixtures__/update-addon-info/update-addon-info.output.snapshot +33 -47
- package/src/transforms/__tests__/csf-2-to-3.test.ts +170 -57
- package/src/transforms/__tests__/mdx-to-csf.test.ts +611 -0
- package/src/transforms/__tests__/upgrade-deprecated-types.test.ts +170 -0
- package/src/transforms/csf-2-to-3.ts +173 -37
- package/src/transforms/mdx-to-csf.ts +342 -0
- package/src/transforms/upgrade-deprecated-types.ts +142 -0
- package/dist/chunk-3OPQTROG.mjs +0 -1
- package/dist/chunk-B5FMQ3BX.mjs +0 -1
- package/dist/chunk-CO6EPEMB.mjs +0 -1
- package/dist/index.mjs +0 -1
- package/dist/transforms/add-component-parameters.mjs +0 -1
- package/dist/transforms/csf-2-to-3.mjs +0 -1
- package/dist/transforms/csf-hoist-story-annotations.mjs +0 -1
- package/dist/transforms/csf-to-mdx.d.ts +0 -29
- package/dist/transforms/csf-to-mdx.js +0 -3
- package/dist/transforms/csf-to-mdx.mjs +0 -3
- package/dist/transforms/move-builtin-addons.mjs +0 -1
- package/dist/transforms/storiesof-to-csf.mjs +0 -1
- package/dist/transforms/update-addon-info.mjs +0 -1
- package/dist/transforms/update-organisation-name.mjs +0 -1
- package/dist/transforms/upgrade-hierarchy-separators.mjs +0 -1
- package/src/transforms/__testfixtures__/csf-to-mdx/basic.input.js +0 -20
- package/src/transforms/__testfixtures__/csf-to-mdx/basic.output.snapshot +0 -18
- package/src/transforms/__testfixtures__/csf-to-mdx/component-id.input.js +0 -9
- package/src/transforms/__testfixtures__/csf-to-mdx/component-id.output.snapshot +0 -10
- package/src/transforms/__testfixtures__/csf-to-mdx/decorators.input.js +0 -13
- package/src/transforms/__testfixtures__/csf-to-mdx/decorators.output.snapshot +0 -12
- package/src/transforms/__testfixtures__/csf-to-mdx/exclude-stories.input.js +0 -23
- package/src/transforms/__testfixtures__/csf-to-mdx/exclude-stories.output.snapshot +0 -22
- package/src/transforms/__testfixtures__/csf-to-mdx/parameters.input.js +0 -16
- package/src/transforms/__testfixtures__/csf-to-mdx/parameters.output.snapshot +0 -17
- package/src/transforms/__testfixtures__/csf-to-mdx/story-function.input.js +0 -19
- package/src/transforms/__testfixtures__/csf-to-mdx/story-function.output.snapshot +0 -18
- package/src/transforms/__testfixtures__/csf-to-mdx/story-parameters.input.js +0 -24
- package/src/transforms/__testfixtures__/csf-to-mdx/story-parameters.output.snapshot +0 -22
- package/src/transforms/csf-to-mdx.js +0 -190
@@ -1,10 +0,0 @@
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
-
|
3
|
-
exports[`csf-to-mdx transforms correctly using "component-id.input.js" data 1`] = `
|
4
|
-
"import Button from './Button';
|
5
|
-
import { Meta, Story } from '@storybook/addon-docs';
|
6
|
-
|
7
|
-
<Meta title='Button' id='button-id' />
|
8
|
-
|
9
|
-
<Story name='someStory'><Button label='Story 1' /></Story>"
|
10
|
-
`;
|
@@ -1,13 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import Button from './Button';
|
3
|
-
|
4
|
-
export default {
|
5
|
-
title: 'Some.Button',
|
6
|
-
decorators: [withKnobs, storyFn => <div className="foo">{storyFn}</div>],
|
7
|
-
};
|
8
|
-
|
9
|
-
export const story1 = () => <Button label="The Button" />;
|
10
|
-
story1.story = {
|
11
|
-
name: 'with decorator',
|
12
|
-
decorators: [withKnobs],
|
13
|
-
};
|
@@ -1,12 +0,0 @@
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
-
|
3
|
-
exports[`csf-to-mdx transforms correctly using "decorators.input.js" data 1`] = `
|
4
|
-
"import Button from './Button';
|
5
|
-
import { Meta, Story } from '@storybook/addon-docs';
|
6
|
-
|
7
|
-
<Meta
|
8
|
-
title='Some.Button'
|
9
|
-
decorators={[withKnobs, storyFn => <div className='foo'>{storyFn}</div>]} />
|
10
|
-
|
11
|
-
<Story name='with decorator' decorators={[withKnobs]}><Button label='The Button' /></Story>"
|
12
|
-
`;
|
@@ -1,23 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import Button from './Button';
|
3
|
-
import { action } from '@storybook/addon-actions';
|
4
|
-
|
5
|
-
export default {
|
6
|
-
title: 'Button',
|
7
|
-
excludeStories: /.*Data$/,
|
8
|
-
};
|
9
|
-
|
10
|
-
export const rowData = { col1: 'a', col2: 2 };
|
11
|
-
|
12
|
-
export const story1 = () => <Button label="Story 1" />;
|
13
|
-
|
14
|
-
export const story2 = () => <Button label="Story 2" onClick={action('click')} />;
|
15
|
-
story2.story = { name: 'second story' };
|
16
|
-
|
17
|
-
export const story3 = () => (
|
18
|
-
<div>
|
19
|
-
<Button label="The Button" onClick={action('onClick')} />
|
20
|
-
<br />
|
21
|
-
</div>
|
22
|
-
);
|
23
|
-
story3.story = { name: 'complex story' };
|
@@ -1,22 +0,0 @@
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
-
|
3
|
-
exports[`csf-to-mdx transforms correctly using "exclude-stories.input.js" data 1`] = `
|
4
|
-
"import Button from './Button';
|
5
|
-
import { action } from '@storybook/addon-actions';
|
6
|
-
import { Meta, Story } from '@storybook/addon-docs';
|
7
|
-
|
8
|
-
<Meta title='Button' />
|
9
|
-
|
10
|
-
export const rowData = {
|
11
|
-
col1: 'a',
|
12
|
-
col2: 2,
|
13
|
-
};
|
14
|
-
<Story name='story1'><Button label='Story 1' /></Story>
|
15
|
-
|
16
|
-
<Story name='second story'><Button label='Story 2' onClick={action('click')} /></Story>
|
17
|
-
|
18
|
-
<Story name='complex story'><div>
|
19
|
-
<Button label='The Button' onClick={action('onClick')} />
|
20
|
-
<br />
|
21
|
-
</div></Story>"
|
22
|
-
`;
|
@@ -1,16 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import Button from './Button';
|
3
|
-
|
4
|
-
import { storiesOf } from '@storybook/react';
|
5
|
-
|
6
|
-
export default {
|
7
|
-
title: 'Button',
|
8
|
-
component: Button,
|
9
|
-
parameters: {
|
10
|
-
foo: 1,
|
11
|
-
bar: 2,
|
12
|
-
},
|
13
|
-
};
|
14
|
-
|
15
|
-
export const story1 = () => <Button label="The Button" />;
|
16
|
-
story1.story = { name: 'with kind parameters' };
|
@@ -1,17 +0,0 @@
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
-
|
3
|
-
exports[`csf-to-mdx transforms correctly using "parameters.input.js" data 1`] = `
|
4
|
-
"import Button from './Button';
|
5
|
-
import { storiesOf } from '@storybook/react';
|
6
|
-
import { Meta, Story } from '@storybook/addon-docs';
|
7
|
-
|
8
|
-
<Meta
|
9
|
-
title='Button'
|
10
|
-
component={Button}
|
11
|
-
parameters={{
|
12
|
-
foo: 1,
|
13
|
-
bar: 2,
|
14
|
-
}} />
|
15
|
-
|
16
|
-
<Story name='with kind parameters'><Button label='The Button' /></Story>"
|
17
|
-
`;
|
@@ -1,19 +0,0 @@
|
|
1
|
-
import global from 'global';
|
2
|
-
|
3
|
-
const { document } = global;
|
4
|
-
|
5
|
-
export default {
|
6
|
-
title: 'Function',
|
7
|
-
};
|
8
|
-
|
9
|
-
export const functionStory = () => {
|
10
|
-
const btn = document.createElement('button');
|
11
|
-
btn.innerHTML = 'Hello Button';
|
12
|
-
btn.addEventListener('click', action('Click'));
|
13
|
-
return btn;
|
14
|
-
};
|
15
|
-
|
16
|
-
functionStory.story = {
|
17
|
-
name: 'function',
|
18
|
-
height: '100px',
|
19
|
-
};
|
@@ -1,18 +0,0 @@
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
-
|
3
|
-
exports[`csf-to-mdx transforms correctly using "story-function.input.js" data 1`] = `
|
4
|
-
"import global from 'global';
|
5
|
-
import { Meta, Story } from '@storybook/addon-docs';
|
6
|
-
|
7
|
-
const {
|
8
|
-
document,
|
9
|
-
} = global;
|
10
|
-
<Meta title='Function' />
|
11
|
-
|
12
|
-
<Story name='function' height='100px'>{() => {
|
13
|
-
const btn = document.createElement('button');
|
14
|
-
btn.innerHTML = 'Hello Button';
|
15
|
-
btn.addEventListener('click', action('Click'));
|
16
|
-
return btn;
|
17
|
-
}}</Story>"
|
18
|
-
`;
|
@@ -1,24 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import Button from './Button';
|
3
|
-
|
4
|
-
import { storiesOf } from '@storybook/react';
|
5
|
-
|
6
|
-
export default {
|
7
|
-
title: 'Button',
|
8
|
-
};
|
9
|
-
|
10
|
-
export const story1 = () => <Button label="The Button" />;
|
11
|
-
story1.story = {
|
12
|
-
name: 'with story parameters',
|
13
|
-
parameters: {
|
14
|
-
header: false,
|
15
|
-
inline: true,
|
16
|
-
},
|
17
|
-
};
|
18
|
-
|
19
|
-
export const foo = () => <Button label="Foo" />;
|
20
|
-
foo.story = {
|
21
|
-
parameters: {
|
22
|
-
bar: 1,
|
23
|
-
},
|
24
|
-
};
|
@@ -1,22 +0,0 @@
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
-
|
3
|
-
exports[`csf-to-mdx transforms correctly using "story-parameters.input.js" data 1`] = `
|
4
|
-
"import Button from './Button';
|
5
|
-
import { storiesOf } from '@storybook/react';
|
6
|
-
import { Meta, Story } from '@storybook/addon-docs';
|
7
|
-
|
8
|
-
<Meta title='Button' />
|
9
|
-
|
10
|
-
<Story
|
11
|
-
name='with story parameters'
|
12
|
-
parameters={{
|
13
|
-
header: false,
|
14
|
-
inline: true,
|
15
|
-
}}><Button label='The Button' /></Story>
|
16
|
-
|
17
|
-
<Story
|
18
|
-
name='foo'
|
19
|
-
parameters={{
|
20
|
-
bar: 1,
|
21
|
-
}}><Button label='Foo' /></Story>"
|
22
|
-
`;
|
@@ -1,190 +0,0 @@
|
|
1
|
-
import { prettyPrint } from 'recast';
|
2
|
-
import { isExportStory } from '@storybook/csf';
|
3
|
-
|
4
|
-
function exportMdx(root, options) {
|
5
|
-
// eslint-disable-next-line no-underscore-dangle
|
6
|
-
const path = root.__paths[0];
|
7
|
-
|
8
|
-
// FIXME: insert the title as markdown after all of the imports
|
9
|
-
return path.node.program.body
|
10
|
-
.map((n) => {
|
11
|
-
const { code } = prettyPrint(n, options);
|
12
|
-
if (n.type === 'JSXElement') {
|
13
|
-
return `${code}\n`;
|
14
|
-
}
|
15
|
-
return code;
|
16
|
-
})
|
17
|
-
.join('\n');
|
18
|
-
}
|
19
|
-
|
20
|
-
function parseIncludeExclude(prop) {
|
21
|
-
const { code } = prettyPrint(prop, {});
|
22
|
-
// eslint-disable-next-line no-eval
|
23
|
-
return (0, eval)(code);
|
24
|
-
}
|
25
|
-
|
26
|
-
/**
|
27
|
-
* Convert a component's module story file into an MDX file
|
28
|
-
*
|
29
|
-
* For example:
|
30
|
-
*
|
31
|
-
* ```
|
32
|
-
* input { Button } from './Button';
|
33
|
-
* export default {
|
34
|
-
* title: 'Button'
|
35
|
-
* }
|
36
|
-
* export const story = () => <Button label="The Button" />;
|
37
|
-
* ```
|
38
|
-
*
|
39
|
-
* Becomes:
|
40
|
-
*
|
41
|
-
* ```
|
42
|
-
* import { Meta, Story } from '@storybook/addon-docs';
|
43
|
-
* input { Button } from './Button';
|
44
|
-
*
|
45
|
-
* <Meta title='Button' />
|
46
|
-
*
|
47
|
-
* <Story name='story'>
|
48
|
-
* <Button label="The Button" />
|
49
|
-
* </Story>
|
50
|
-
* ```
|
51
|
-
*/
|
52
|
-
export default function transformer(file, api) {
|
53
|
-
const j = api.jscodeshift;
|
54
|
-
const root = j(file.source);
|
55
|
-
|
56
|
-
// FIXME: save out all the storyFn.story = { ... }
|
57
|
-
const storyKeyToStory = {};
|
58
|
-
// save out includeStories / excludeStories
|
59
|
-
const meta = {};
|
60
|
-
|
61
|
-
function makeAttr(key, val) {
|
62
|
-
return j.jsxAttribute(
|
63
|
-
j.jsxIdentifier(key),
|
64
|
-
val.type === 'Literal' ? val : j.jsxExpressionContainer(val)
|
65
|
-
);
|
66
|
-
}
|
67
|
-
|
68
|
-
function getStoryContents(node) {
|
69
|
-
return node.type === 'ArrowFunctionExpression' && node.body.type === 'JSXElement'
|
70
|
-
? node.body
|
71
|
-
: j.jsxExpressionContainer(node);
|
72
|
-
}
|
73
|
-
|
74
|
-
function getName(storyKey) {
|
75
|
-
const story = storyKeyToStory[storyKey];
|
76
|
-
if (story) {
|
77
|
-
const name = story.properties.find((prop) => prop.key.name === 'name');
|
78
|
-
if (name && name.value.type === 'Literal') {
|
79
|
-
return name.value.value;
|
80
|
-
}
|
81
|
-
}
|
82
|
-
return storyKey;
|
83
|
-
}
|
84
|
-
|
85
|
-
function getStoryAttrs(storyKey) {
|
86
|
-
const attrs = [];
|
87
|
-
const story = storyKeyToStory[storyKey];
|
88
|
-
if (story) {
|
89
|
-
story.properties.forEach((prop) => {
|
90
|
-
const { key, value } = prop;
|
91
|
-
if (key.name !== 'name') {
|
92
|
-
attrs.push(makeAttr(key.name, value));
|
93
|
-
}
|
94
|
-
});
|
95
|
-
}
|
96
|
-
return attrs;
|
97
|
-
}
|
98
|
-
|
99
|
-
// 1. If the program does not have `export default { title: '....' }, skip it
|
100
|
-
const defaultExportWithTitle = root
|
101
|
-
.find(j.ExportDefaultDeclaration)
|
102
|
-
.filter((def) => def.node.declaration.properties.map((p) => p.key.name).includes('title'));
|
103
|
-
if (defaultExportWithTitle.size() === 0) {
|
104
|
-
return root.toSource();
|
105
|
-
}
|
106
|
-
|
107
|
-
// 2a. Add imports from '@storybook/addon-docs'
|
108
|
-
root
|
109
|
-
.find(j.ImportDeclaration)
|
110
|
-
.at(-1)
|
111
|
-
.insertAfter(j.emptyStatement())
|
112
|
-
.insertAfter(
|
113
|
-
j.importDeclaration(
|
114
|
-
[j.importSpecifier(j.identifier('Meta')), j.importSpecifier(j.identifier('Story'))],
|
115
|
-
j.literal('@storybook/addon-docs')
|
116
|
-
)
|
117
|
-
);
|
118
|
-
// 2b. Remove react import which is implicit
|
119
|
-
root
|
120
|
-
.find(j.ImportDeclaration)
|
121
|
-
.filter((decl) => decl.node.source.value === 'react')
|
122
|
-
.remove();
|
123
|
-
|
124
|
-
// 3. Save out all the excluded stories
|
125
|
-
defaultExportWithTitle.forEach((exp) => {
|
126
|
-
exp.node.declaration.properties.forEach((p) => {
|
127
|
-
if (['includeStories', 'excludeStories'].includes(p.key.name)) {
|
128
|
-
meta[p.key.name] = parseIncludeExclude(p.value);
|
129
|
-
}
|
130
|
-
});
|
131
|
-
});
|
132
|
-
|
133
|
-
// 4. Collect all the story exports in storyKeyToStory[key] = null;
|
134
|
-
const namedExports = root.find(j.ExportNamedDeclaration);
|
135
|
-
namedExports.forEach((exp) => {
|
136
|
-
const storyKey = exp.node.declaration.declarations[0].id.name;
|
137
|
-
if (isExportStory(storyKey, meta)) {
|
138
|
-
storyKeyToStory[storyKey] = null;
|
139
|
-
}
|
140
|
-
});
|
141
|
-
|
142
|
-
// 5. Collect all the storyKey.story in storyKeyToStory and also remove them
|
143
|
-
const storyAssignments = root.find(j.AssignmentExpression).filter((exp) => {
|
144
|
-
const { left } = exp.node;
|
145
|
-
return (
|
146
|
-
left.type === 'MemberExpression' &&
|
147
|
-
left.object.type === 'Identifier' &&
|
148
|
-
left.object.name in storyKeyToStory &&
|
149
|
-
left.property.type === 'Identifier' &&
|
150
|
-
left.property.name === 'story'
|
151
|
-
);
|
152
|
-
});
|
153
|
-
storyAssignments.forEach((exp) => {
|
154
|
-
const { left, right } = exp.node;
|
155
|
-
storyKeyToStory[left.object.name] = right;
|
156
|
-
});
|
157
|
-
storyAssignments.remove();
|
158
|
-
|
159
|
-
// 6. Convert the default export to <Meta />
|
160
|
-
defaultExportWithTitle.replaceWith((exp) => {
|
161
|
-
const jsxId = j.jsxIdentifier('Meta');
|
162
|
-
const attrs = [];
|
163
|
-
exp.node.declaration.properties.forEach((prop) => {
|
164
|
-
const { key, value } = prop;
|
165
|
-
if (!['includeStories', 'excludeStories'].includes(key.name)) {
|
166
|
-
attrs.push(makeAttr(key.name, value));
|
167
|
-
}
|
168
|
-
});
|
169
|
-
const opening = j.jsxOpeningElement(jsxId, attrs);
|
170
|
-
opening.selfClosing = true;
|
171
|
-
return j.jsxElement(opening);
|
172
|
-
});
|
173
|
-
|
174
|
-
// 7. Convert all the named exports to <Story>...</Story>
|
175
|
-
namedExports.replaceWith((exp) => {
|
176
|
-
const storyKey = exp.node.declaration.declarations[0].id.name;
|
177
|
-
if (!isExportStory(storyKey, meta)) {
|
178
|
-
return exp.node;
|
179
|
-
}
|
180
|
-
const jsxId = j.jsxIdentifier('Story');
|
181
|
-
const name = getName(storyKey);
|
182
|
-
const attributes = [makeAttr('name', j.literal(name)), ...getStoryAttrs(storyKey)];
|
183
|
-
const opening = j.jsxOpeningElement(jsxId, attributes);
|
184
|
-
const closing = j.jsxClosingElement(jsxId);
|
185
|
-
const children = [getStoryContents(exp.node.declaration.declarations[0].init)];
|
186
|
-
return j.jsxElement(opening, closing, children);
|
187
|
-
});
|
188
|
-
|
189
|
-
return exportMdx(root, { quote: 'single', trailingComma: 'true', tabWidth: 2 });
|
190
|
-
}
|