@storybook/codemod 7.0.0-beta.8 → 7.0.0-rc.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +0 -39
- package/dist/index.js +1 -1
- package/dist/transforms/add-component-parameters.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/csf-hoist-story-annotations.js +1 -1
- package/dist/transforms/mdx-to-csf.d.ts +7 -0
- package/dist/transforms/mdx-to-csf.js +55 -0
- package/dist/transforms/move-builtin-addons.js +1 -1
- package/dist/transforms/storiesof-to-csf.js +1 -1
- package/dist/transforms/update-addon-info.js +1 -1
- package/dist/transforms/update-organisation-name.js +1 -1
- package/dist/transforms/upgrade-deprecated-types.d.ts +10 -0
- package/dist/transforms/upgrade-deprecated-types.js +2 -0
- package/dist/transforms/upgrade-hierarchy-separators.js +1 -1
- package/jest.config.js +2 -0
- package/package.json +31 -15
- 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
|
-
}
|