@storybook/codemod 7.0.0-beta.9 → 7.0.0-rc.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. package/README.md +0 -39
  2. package/dist/index.js +1 -1
  3. package/dist/transforms/csf-2-to-3.d.ts +5 -4
  4. package/dist/transforms/csf-2-to-3.js +3 -1
  5. package/dist/transforms/mdx-to-csf.d.ts +7 -0
  6. package/dist/transforms/mdx-to-csf.js +55 -0
  7. package/dist/transforms/storiesof-to-csf.js +1 -1
  8. package/dist/transforms/upgrade-deprecated-types.d.ts +10 -0
  9. package/dist/transforms/upgrade-deprecated-types.js +2 -0
  10. package/jest.config.js +2 -0
  11. package/package.json +31 -16
  12. package/project.json +6 -0
  13. package/src/index.js +30 -4
  14. package/src/lib/utils.ts +2 -2
  15. package/src/transforms/__testfixtures__/storiesof-to-csf/decorators.input.js +1 -1
  16. package/src/transforms/__testfixtures__/storiesof-to-csf/export-function.input.js +1 -1
  17. package/src/transforms/__testfixtures__/storiesof-to-csf/story-decorators.input.js +1 -1
  18. package/src/transforms/__testfixtures__/update-addon-info/update-addon-info.input.js +34 -48
  19. package/src/transforms/__testfixtures__/update-addon-info/update-addon-info.output.snapshot +33 -47
  20. package/src/transforms/__tests__/csf-2-to-3.test.ts +170 -57
  21. package/src/transforms/__tests__/mdx-to-csf.test.ts +611 -0
  22. package/src/transforms/__tests__/upgrade-deprecated-types.test.ts +170 -0
  23. package/src/transforms/csf-2-to-3.ts +173 -37
  24. package/src/transforms/mdx-to-csf.ts +342 -0
  25. package/src/transforms/upgrade-deprecated-types.ts +142 -0
  26. package/dist/chunk-3OPQTROG.mjs +0 -1
  27. package/dist/chunk-B5FMQ3BX.mjs +0 -1
  28. package/dist/chunk-CO6EPEMB.mjs +0 -1
  29. package/dist/index.mjs +0 -1
  30. package/dist/transforms/add-component-parameters.mjs +0 -1
  31. package/dist/transforms/csf-2-to-3.mjs +0 -1
  32. package/dist/transforms/csf-hoist-story-annotations.mjs +0 -1
  33. package/dist/transforms/csf-to-mdx.d.ts +0 -29
  34. package/dist/transforms/csf-to-mdx.js +0 -3
  35. package/dist/transforms/csf-to-mdx.mjs +0 -3
  36. package/dist/transforms/move-builtin-addons.mjs +0 -1
  37. package/dist/transforms/storiesof-to-csf.mjs +0 -1
  38. package/dist/transforms/update-addon-info.mjs +0 -1
  39. package/dist/transforms/update-organisation-name.mjs +0 -1
  40. package/dist/transforms/upgrade-hierarchy-separators.mjs +0 -1
  41. package/src/transforms/__testfixtures__/csf-to-mdx/basic.input.js +0 -20
  42. package/src/transforms/__testfixtures__/csf-to-mdx/basic.output.snapshot +0 -18
  43. package/src/transforms/__testfixtures__/csf-to-mdx/component-id.input.js +0 -9
  44. package/src/transforms/__testfixtures__/csf-to-mdx/component-id.output.snapshot +0 -10
  45. package/src/transforms/__testfixtures__/csf-to-mdx/decorators.input.js +0 -13
  46. package/src/transforms/__testfixtures__/csf-to-mdx/decorators.output.snapshot +0 -12
  47. package/src/transforms/__testfixtures__/csf-to-mdx/exclude-stories.input.js +0 -23
  48. package/src/transforms/__testfixtures__/csf-to-mdx/exclude-stories.output.snapshot +0 -22
  49. package/src/transforms/__testfixtures__/csf-to-mdx/parameters.input.js +0 -16
  50. package/src/transforms/__testfixtures__/csf-to-mdx/parameters.output.snapshot +0 -17
  51. package/src/transforms/__testfixtures__/csf-to-mdx/story-function.input.js +0 -19
  52. package/src/transforms/__testfixtures__/csf-to-mdx/story-function.output.snapshot +0 -18
  53. package/src/transforms/__testfixtures__/csf-to-mdx/story-parameters.input.js +0 -24
  54. package/src/transforms/__testfixtures__/csf-to-mdx/story-parameters.output.snapshot +0 -22
  55. package/src/transforms/csf-to-mdx.js +0 -190
@@ -1,9 +0,0 @@
1
- import React from 'react';
2
- import Button from './Button';
3
-
4
- export default {
5
- title: 'Button',
6
- id: 'button-id',
7
- };
8
-
9
- export const someStory = () => <Button label="Story 1" />;
@@ -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
- }