@storybook/codemod 6.4.0-beta.24 → 6.4.0-beta.28

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.
Files changed (41) hide show
  1. package/dist/cjs/index.js +142 -0
  2. package/dist/cjs/lib/utils.js +40 -0
  3. package/dist/cjs/transforms/add-component-parameters.js +64 -0
  4. package/dist/cjs/transforms/csf-2-to-3.js +169 -0
  5. package/dist/cjs/transforms/csf-hoist-story-annotations.js +93 -0
  6. package/dist/cjs/transforms/csf-to-mdx.js +196 -0
  7. package/dist/cjs/transforms/mdx-to-csf.js +153 -0
  8. package/dist/cjs/transforms/move-builtin-addons.js +57 -0
  9. package/dist/cjs/transforms/storiesof-to-csf.js +300 -0
  10. package/dist/cjs/transforms/update-addon-info.js +101 -0
  11. package/dist/cjs/transforms/update-organisation-name.js +83 -0
  12. package/dist/cjs/transforms/upgrade-hierarchy-separators.js +42 -0
  13. package/dist/esm/index.js +99 -0
  14. package/dist/esm/lib/utils.js +25 -0
  15. package/dist/esm/transforms/add-component-parameters.js +57 -0
  16. package/dist/esm/transforms/csf-2-to-3.js +152 -0
  17. package/dist/esm/transforms/csf-hoist-story-annotations.js +86 -0
  18. package/dist/esm/transforms/csf-to-mdx.js +188 -0
  19. package/dist/esm/transforms/mdx-to-csf.js +139 -0
  20. package/dist/esm/transforms/move-builtin-addons.js +50 -0
  21. package/dist/esm/transforms/storiesof-to-csf.js +287 -0
  22. package/dist/esm/transforms/update-addon-info.js +94 -0
  23. package/dist/esm/transforms/update-organisation-name.js +74 -0
  24. package/dist/esm/transforms/upgrade-hierarchy-separators.js +35 -0
  25. package/dist/modern/index.js +99 -0
  26. package/dist/modern/lib/utils.js +25 -0
  27. package/dist/modern/transforms/add-component-parameters.js +57 -0
  28. package/dist/modern/transforms/csf-2-to-3.js +152 -0
  29. package/dist/modern/transforms/csf-hoist-story-annotations.js +86 -0
  30. package/dist/modern/transforms/csf-to-mdx.js +188 -0
  31. package/dist/modern/transforms/mdx-to-csf.js +139 -0
  32. package/dist/modern/transforms/move-builtin-addons.js +50 -0
  33. package/dist/modern/transforms/storiesof-to-csf.js +287 -0
  34. package/dist/modern/transforms/update-addon-info.js +94 -0
  35. package/dist/modern/transforms/update-organisation-name.js +74 -0
  36. package/dist/modern/transforms/upgrade-hierarchy-separators.js +35 -0
  37. package/dist/ts3.4/lib/utils.d.ts +2 -0
  38. package/dist/ts3.4/transforms/csf-2-to-3.d.ts +6 -0
  39. package/dist/ts3.9/lib/utils.d.ts +2 -0
  40. package/dist/ts3.9/transforms/csf-2-to-3.d.ts +6 -0
  41. package/package.json +4 -4
@@ -0,0 +1,152 @@
1
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
2
+
3
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
4
+
5
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
+
7
+ /* eslint-disable no-underscore-dangle */
8
+ import prettier from 'prettier';
9
+ import * as t from '@babel/types';
10
+ import { formatCsf, loadCsf } from '@storybook/csf-tools';
11
+ import { jscodeshiftToPrettierParser } from '../lib/utils';
12
+ var logger = console;
13
+
14
+ var _rename = function (annotation) {
15
+ return annotation === 'storyName' ? 'name' : annotation;
16
+ };
17
+
18
+ var getTemplateBindVariable = function (init) {
19
+ return t.isCallExpression(init) && t.isMemberExpression(init.callee) && t.isIdentifier(init.callee.object) && t.isIdentifier(init.callee.property) && init.callee.property.name === 'bind' && (init.arguments.length === 0 || init.arguments.length === 1 && t.isObjectExpression(init.arguments[0]) && init.arguments[0].properties.length === 0) ? init.callee.object.name : null;
20
+ }; // export const A = ...
21
+ // A.parameters = { ... }; <===
22
+
23
+
24
+ var isStoryAnnotation = function (stmt, objectExports) {
25
+ return t.isExpressionStatement(stmt) && t.isAssignmentExpression(stmt.expression) && t.isMemberExpression(stmt.expression.left) && t.isIdentifier(stmt.expression.left.object) && objectExports[stmt.expression.left.object.name];
26
+ };
27
+
28
+ var isTemplateDeclaration = function (stmt, templates) {
29
+ return t.isVariableDeclaration(stmt) && stmt.declarations.length === 1 && t.isIdentifier(stmt.declarations[0].id) && templates[stmt.declarations[0].id.name];
30
+ };
31
+
32
+ var getNewExport = function (stmt, objectExports) {
33
+ if (t.isExportNamedDeclaration(stmt) && t.isVariableDeclaration(stmt.declaration) && stmt.declaration.declarations.length === 1) {
34
+ var decl = stmt.declaration.declarations[0];
35
+
36
+ if (t.isVariableDeclarator(decl) && t.isIdentifier(decl.id)) {
37
+ return objectExports[decl.id.name];
38
+ }
39
+ }
40
+
41
+ return null;
42
+ }; // Remove render function when it matches the global render function in react
43
+ // export default { component: Cat };
44
+ // export const A = (args) => <Cat {...args} />;
45
+
46
+
47
+ var isReactGlobalRenderFn = function (csf, storyFn) {
48
+ var _csf$_meta;
49
+
50
+ if ((_csf$_meta = csf._meta) !== null && _csf$_meta !== void 0 && _csf$_meta.component && t.isArrowFunctionExpression(storyFn) && storyFn.params.length === 1 && t.isJSXElement(storyFn.body)) {
51
+ var openingElement = storyFn.body.openingElement;
52
+
53
+ if (openingElement.selfClosing && t.isJSXIdentifier(openingElement.name) && openingElement.attributes.length === 1) {
54
+ var attr = openingElement.attributes[0];
55
+ var param = storyFn.params[0];
56
+
57
+ if (t.isJSXSpreadAttribute(attr) && t.isIdentifier(attr.argument) && t.isIdentifier(param) && param.name === attr.argument.name && csf._meta.component === openingElement.name.name) {
58
+ return true;
59
+ }
60
+ }
61
+ }
62
+
63
+ return false;
64
+ }; // A simple CSF story is a no-arg story without any extra annotations (params, args, etc.)
65
+
66
+
67
+ var isSimpleCSFStory = function (init, annotations) {
68
+ return annotations.length === 0 && t.isArrowFunctionExpression(init) && init.params.length === 0;
69
+ };
70
+
71
+ function transform({
72
+ source: source
73
+ }, api, options) {
74
+ var csf = loadCsf(source, {
75
+ defaultTitle: 'FIXME'
76
+ });
77
+
78
+ try {
79
+ csf.parse();
80
+ } catch (err) {
81
+ logger.log(`Error ${err}, skipping`);
82
+ return source;
83
+ }
84
+
85
+ var objectExports = {};
86
+ Object.entries(csf._storyExports).forEach(function ([key, decl]) {
87
+ var annotations = Object.entries(csf._storyAnnotations[key]).map(function ([annotation, val]) {
88
+ return t.objectProperty(t.identifier(_rename(annotation)), val);
89
+ });
90
+ var init = decl.init,
91
+ id = decl.id; // only replace arrow function expressions && template
92
+ // ignore no-arg stories without annotations
93
+
94
+ var template = getTemplateBindVariable(init);
95
+
96
+ if (!t.isArrowFunctionExpression(init) && !template || isSimpleCSFStory(init, annotations)) {
97
+ return;
98
+ } // Remove the render function when we can hoist the template
99
+ // const Template = (args) => <Cat {...args} />;
100
+ // export const A = Template.bind({});
101
+
102
+
103
+ var storyFn = template && csf._templates[template];
104
+ if (!storyFn) storyFn = init;
105
+ var keyId = t.identifier(key); // @ts-ignore
106
+
107
+ var typeAnnotation = id.typeAnnotation;
108
+
109
+ if (typeAnnotation) {
110
+ keyId.typeAnnotation = typeAnnotation;
111
+ }
112
+
113
+ var renderAnnotation = isReactGlobalRenderFn(csf, storyFn) ? [] : [t.objectProperty(t.identifier('render'), storyFn)];
114
+ objectExports[key] = t.exportNamedDeclaration(t.variableDeclaration('const', [t.variableDeclarator(keyId, t.objectExpression([...renderAnnotation, ...annotations]))]));
115
+ });
116
+
117
+ var updatedBody = csf._ast.program.body.reduce(function (acc, stmt) {
118
+ // remove story annotations & template declarations
119
+ if (isStoryAnnotation(stmt, objectExports) || isTemplateDeclaration(stmt, csf._templates)) {
120
+ return acc;
121
+ } // replace story exports with new object exports
122
+
123
+
124
+ var newExport = getNewExport(stmt, objectExports);
125
+
126
+ if (newExport) {
127
+ acc.push(newExport);
128
+ return acc;
129
+ } // include unknown statements
130
+
131
+
132
+ acc.push(stmt);
133
+ return acc;
134
+ }, []);
135
+
136
+ csf._ast.program.body = updatedBody;
137
+ var output = formatCsf(csf);
138
+ var prettierConfig = prettier.resolveConfig.sync('.', {
139
+ editorconfig: true
140
+ }) || {
141
+ printWidth: 100,
142
+ tabWidth: 2,
143
+ bracketSpacing: true,
144
+ trailingComma: 'es5',
145
+ singleQuote: true
146
+ };
147
+ return prettier.format(output, _objectSpread(_objectSpread({}, prettierConfig), {}, {
148
+ parser: jscodeshiftToPrettierParser(options === null || options === void 0 ? void 0 : options.parser)
149
+ }));
150
+ }
151
+
152
+ export default transform;
@@ -0,0 +1,86 @@
1
+ var getContainingStatement = function (n) {
2
+ if (n.node.type.endsWith('Statement')) {
3
+ return n;
4
+ }
5
+
6
+ return getContainingStatement(n.parent);
7
+ };
8
+ /**
9
+ * Hoist CSF .story annotations
10
+ *
11
+ * For example:
12
+ *
13
+ * ```
14
+ * export const Basic = () => <Button />
15
+ * Basic.story = {
16
+ * name: 'foo',
17
+ * parameters: { ... },
18
+ * decorators = [ ... ],
19
+ * };
20
+ * ```
21
+ *
22
+ * Becomes:
23
+ *
24
+ * ```
25
+ * export const Basic = () => <Button />
26
+ * Basic.storyName = 'foo';
27
+ * Basic.parameters = { ... };
28
+ * Basic.decorators = [ ... ];
29
+ * ```
30
+ */
31
+
32
+
33
+ export default function transformer(file, api) {
34
+ var j = api.jscodeshift;
35
+ var root = j(file.source);
36
+
37
+ var renameKey = function (exp) {
38
+ return exp.type === 'Identifier' && exp.name === 'name' ? j.identifier('storyName') : exp;
39
+ }; // 1. If the program does not have `export default { title: '....' }, skip it
40
+
41
+
42
+ var defaultExportWithTitle = root.find(j.ExportDefaultDeclaration).filter(function (def) {
43
+ return def.node.declaration.type === 'ObjectExpression' && def.node.declaration.properties.map(function (p) {
44
+ return p.key.name;
45
+ }).includes('title');
46
+ });
47
+
48
+ if (defaultExportWithTitle.size() === 0) {
49
+ return root.toSource();
50
+ } // 2. Replace each Foo.story = { x: xVal } with Foo.x = xVal;
51
+
52
+
53
+ var storyAssignments = root.find(j.AssignmentExpression).filter(function (exp) {
54
+ var _exp$node = exp.node,
55
+ left = _exp$node.left,
56
+ right = _exp$node.right;
57
+ return left.type === 'MemberExpression' && left.object.type === 'Identifier' && left.property.type === 'Identifier' && left.property.name === 'story' && right.type === 'ObjectExpression';
58
+ });
59
+ storyAssignments.forEach(function (exp) {
60
+ var _exp$node2 = exp.node,
61
+ left = _exp$node2.left,
62
+ right = _exp$node2.right;
63
+ right.properties.forEach(function (prop) {
64
+ var stmt = getContainingStatement(exp);
65
+ stmt.insertBefore(j.assignmentStatement('=', j.memberExpression(left.object, renameKey(prop.key)), prop.value));
66
+ });
67
+ }); // 3. Remove the .story annotations
68
+
69
+ storyAssignments.remove(); // 4. Replace each Foo.story.x with Foo.x;
70
+
71
+ var storyOverrides = root.find(j.AssignmentExpression).filter(function (exp) {
72
+ var left = exp.node.left;
73
+ return left.type === 'MemberExpression' && left.object.type === 'MemberExpression' && left.object.property.type === 'Identifier' && left.object.property.name === 'story' && left.property.type === 'Identifier' // ?? ANNOTATION_FIELDS.includes(right.property.name)
74
+ ;
75
+ });
76
+ storyOverrides.replaceWith(function (exp) {
77
+ var _exp$node3 = exp.node,
78
+ left = _exp$node3.left,
79
+ right = _exp$node3.right;
80
+ return j.assignmentExpression('=', j.memberExpression(left.object.object, renameKey(left.property)), right);
81
+ }); // 4. Render the updated tree
82
+
83
+ return root.toSource({
84
+ quote: 'single'
85
+ });
86
+ }
@@ -0,0 +1,188 @@
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
+ var path = root.__paths[0]; // FIXME: insert the title as markdown after all of the imports
7
+
8
+ return path.node.program.body.map(function (n) {
9
+ var _prettyPrint = prettyPrint(n, options),
10
+ code = _prettyPrint.code;
11
+
12
+ if (n.type === 'JSXElement') {
13
+ return `${code}\n`;
14
+ }
15
+
16
+ return code;
17
+ }).join('\n');
18
+ }
19
+
20
+ function parseIncludeExclude(prop) {
21
+ var _prettyPrint2 = prettyPrint(prop, {}),
22
+ code = _prettyPrint2.code; // eslint-disable-next-line no-eval
23
+
24
+
25
+ return eval(code);
26
+ }
27
+ /**
28
+ * Convert a component's module story file into an MDX file
29
+ *
30
+ * For example:
31
+ *
32
+ * ```
33
+ * input { Button } from './Button';
34
+ * export default {
35
+ * title: 'Button'
36
+ * }
37
+ * export const story = () => <Button label="The Button" />;
38
+ * ```
39
+ *
40
+ * Becomes:
41
+ *
42
+ * ```
43
+ * import { Meta, Story } from '@storybook/addon-docs';
44
+ * input { Button } from './Button';
45
+ *
46
+ * <Meta title='Button' />
47
+ *
48
+ * <Story name='story'>
49
+ * <Button label="The Button" />
50
+ * </Story>
51
+ * ```
52
+ */
53
+
54
+
55
+ export default function transformer(file, api) {
56
+ var j = api.jscodeshift;
57
+ var root = j(file.source); // FIXME: save out all the storyFn.story = { ... }
58
+
59
+ var storyKeyToStory = {}; // save out includeStories / excludeStories
60
+
61
+ var meta = {};
62
+
63
+ function makeAttr(key, val) {
64
+ return j.jsxAttribute(j.jsxIdentifier(key), val.type === 'Literal' ? val : j.jsxExpressionContainer(val));
65
+ }
66
+
67
+ function getStoryContents(node) {
68
+ return node.type === 'ArrowFunctionExpression' && node.body.type === 'JSXElement' ? node.body : j.jsxExpressionContainer(node);
69
+ }
70
+
71
+ function getName(storyKey) {
72
+ var story = storyKeyToStory[storyKey];
73
+
74
+ if (story) {
75
+ var name = story.properties.find(function (prop) {
76
+ return prop.key.name === 'name';
77
+ });
78
+
79
+ if (name && name.value.type === 'Literal') {
80
+ return name.value.value;
81
+ }
82
+ }
83
+
84
+ return storyKey;
85
+ }
86
+
87
+ function getStoryAttrs(storyKey) {
88
+ var attrs = [];
89
+ var story = storyKeyToStory[storyKey];
90
+
91
+ if (story) {
92
+ story.properties.forEach(function (prop) {
93
+ var key = prop.key,
94
+ value = prop.value;
95
+
96
+ if (key.name !== 'name') {
97
+ attrs.push(makeAttr(key.name, value));
98
+ }
99
+ });
100
+ }
101
+
102
+ return attrs;
103
+ } // 1. If the program does not have `export default { title: '....' }, skip it
104
+
105
+
106
+ var defaultExportWithTitle = root.find(j.ExportDefaultDeclaration).filter(function (def) {
107
+ return def.node.declaration.properties.map(function (p) {
108
+ return p.key.name;
109
+ }).includes('title');
110
+ });
111
+
112
+ if (defaultExportWithTitle.size() === 0) {
113
+ return root.toSource();
114
+ } // 2a. Add imports from '@storybook/addon-docs'
115
+
116
+
117
+ root.find(j.ImportDeclaration).at(-1).insertAfter(j.emptyStatement()).insertAfter(j.importDeclaration([j.importSpecifier(j.identifier('Meta')), j.importSpecifier(j.identifier('Story'))], j.literal('@storybook/addon-docs'))); // 2b. Remove react import which is implicit
118
+
119
+ root.find(j.ImportDeclaration).filter(function (decl) {
120
+ return decl.node.source.value === 'react';
121
+ }).remove(); // 3. Save out all the excluded stories
122
+
123
+ defaultExportWithTitle.forEach(function (exp) {
124
+ exp.node.declaration.properties.forEach(function (p) {
125
+ if (['includeStories', 'excludeStories'].includes(p.key.name)) {
126
+ meta[p.key.name] = parseIncludeExclude(p.value);
127
+ }
128
+ });
129
+ }); // 4. Collect all the story exports in storyKeyToStory[key] = null;
130
+
131
+ var namedExports = root.find(j.ExportNamedDeclaration);
132
+ namedExports.forEach(function (exp) {
133
+ var storyKey = exp.node.declaration.declarations[0].id.name;
134
+
135
+ if (isExportStory(storyKey, meta)) {
136
+ storyKeyToStory[storyKey] = null;
137
+ }
138
+ }); // 5. Collect all the storyKey.story in storyKeyToStory and also remove them
139
+
140
+ var storyAssignments = root.find(j.AssignmentExpression).filter(function (exp) {
141
+ var left = exp.node.left;
142
+ return left.type === 'MemberExpression' && left.object.type === 'Identifier' && left.object.name in storyKeyToStory && left.property.type === 'Identifier' && left.property.name === 'story';
143
+ });
144
+ storyAssignments.forEach(function (exp) {
145
+ var _exp$node = exp.node,
146
+ left = _exp$node.left,
147
+ right = _exp$node.right;
148
+ storyKeyToStory[left.object.name] = right;
149
+ });
150
+ storyAssignments.remove(); // 6. Convert the default export to <Meta />
151
+
152
+ defaultExportWithTitle.replaceWith(function (exp) {
153
+ var jsxId = j.jsxIdentifier('Meta');
154
+ var attrs = [];
155
+ exp.node.declaration.properties.forEach(function (prop) {
156
+ var key = prop.key,
157
+ value = prop.value;
158
+
159
+ if (!['includeStories', 'excludeStories'].includes(key.name)) {
160
+ attrs.push(makeAttr(key.name, value));
161
+ }
162
+ });
163
+ var opening = j.jsxOpeningElement(jsxId, attrs);
164
+ opening.selfClosing = true;
165
+ return j.jsxElement(opening);
166
+ }); // 7. Convert all the named exports to <Story>...</Story>
167
+
168
+ namedExports.replaceWith(function (exp) {
169
+ var storyKey = exp.node.declaration.declarations[0].id.name;
170
+
171
+ if (!isExportStory(storyKey, meta)) {
172
+ return exp.node;
173
+ }
174
+
175
+ var jsxId = j.jsxIdentifier('Story');
176
+ var name = getName(storyKey);
177
+ var attributes = [makeAttr('name', j.literal(name)), ...getStoryAttrs(storyKey)];
178
+ var opening = j.jsxOpeningElement(jsxId, attributes);
179
+ var closing = j.jsxClosingElement(jsxId);
180
+ var children = [getStoryContents(exp.node.declaration.declarations[0].init)];
181
+ return j.jsxElement(opening, closing, children);
182
+ });
183
+ return exportMdx(root, {
184
+ quote: 'single',
185
+ trailingComma: 'true',
186
+ tabWidth: 2
187
+ });
188
+ }
@@ -0,0 +1,139 @@
1
+ // import recast from 'recast';
2
+ import mdx from '@mdx-js/mdx';
3
+ import prettier from 'prettier';
4
+ import { sanitizeName } from '../lib/utils';
5
+ /**
6
+ * Convert a component's MDX file into module story format
7
+ */
8
+
9
+ export default function transformer(file, api) {
10
+ var j = api.jscodeshift;
11
+ var code = mdx.sync(file.source, {});
12
+ var root = j(code);
13
+
14
+ function parseJsxAttributes(attributes) {
15
+ var result = {};
16
+ attributes.forEach(function (attr) {
17
+ var key = attr.name.name;
18
+ var val = attr.value.type === 'JSXExpressionContainer' ? attr.value.expression : attr.value;
19
+ result[key] = val;
20
+ });
21
+ return result;
22
+ }
23
+
24
+ function genObjectExpression(attrs) {
25
+ return j.objectExpression(Object.entries(attrs).map(function ([key, val]) {
26
+ return j.property('init', j.identifier(key), val);
27
+ }));
28
+ }
29
+
30
+ function convertToStories(path) {
31
+ var base = j(path);
32
+ var meta = {};
33
+ var includeStories = [];
34
+ var storyStatements = []; // get rid of all mdxType junk
35
+
36
+ base.find(j.JSXAttribute).filter(function (attr) {
37
+ return attr.node.name.name === 'mdxType';
38
+ }).remove(); // parse <Meta title="..." />
39
+
40
+ base.find(j.JSXElement).filter(function (elt) {
41
+ return elt.node.openingElement.name.name === 'Meta';
42
+ }).forEach(function (elt) {
43
+ var attrs = parseJsxAttributes(elt.node.openingElement.attributes);
44
+ Object.assign(meta, attrs);
45
+ }); // parse <Story name="..." />
46
+
47
+ base.find(j.JSXElement).filter(function (elt) {
48
+ return elt.node.openingElement.name.name === 'Story';
49
+ }).forEach(function (elt) {
50
+ var attrs = parseJsxAttributes(elt.node.openingElement.attributes);
51
+
52
+ if (attrs.name) {
53
+ var storyKey = sanitizeName(attrs.name.value);
54
+ includeStories.push(storyKey);
55
+
56
+ if (storyKey === attrs.name.value) {
57
+ delete attrs.name;
58
+ }
59
+
60
+ var body = elt.node.children.find(function (n) {
61
+ return n.type !== 'JSXText';
62
+ }) || j.literal(elt.node.children[0].value);
63
+
64
+ if (body.type === 'JSXExpressionContainer') {
65
+ body = body.expression;
66
+ }
67
+
68
+ storyStatements.push(j.exportDeclaration(false, j.variableDeclaration('const', [j.variableDeclarator(j.identifier(storyKey), body.type === 'ArrowFunctionExpression' ? body : j.arrowFunctionExpression([], body))])));
69
+
70
+ if (Object.keys(attrs).length > 0) {
71
+ storyStatements.push(j.assignmentStatement('=', j.memberExpression(j.identifier(storyKey), j.identifier('story')), genObjectExpression(attrs)));
72
+ }
73
+
74
+ storyStatements.push(j.emptyStatement());
75
+ }
76
+ });
77
+
78
+ if (root.find(j.ExportNamedDeclaration).size() > 0) {
79
+ meta.includeStories = j.arrayExpression(includeStories.map(function (key) {
80
+ return j.literal(key);
81
+ }));
82
+ }
83
+
84
+ var statements = [j.exportDefaultDeclaration(genObjectExpression(meta)), j.emptyStatement(), ...storyStatements];
85
+ var lastStatement = root.find(j.Statement).at(-1);
86
+ statements.reverse().forEach(function (stmt) {
87
+ lastStatement.insertAfter(stmt);
88
+ });
89
+ base.remove();
90
+ }
91
+
92
+ root.find(j.ExportDefaultDeclaration).forEach(convertToStories); // strip out Story/Meta import and MDX junk
93
+ // /* @jsx mdx */
94
+
95
+ root.find(j.ImportDeclaration).at(0).replaceWith(function (exp) {
96
+ return j.importDeclaration(exp.node.specifiers, exp.node.source);
97
+ }); // import { Story, Meta } from '@storybook/addon-docs';
98
+
99
+ root.find(j.ImportDeclaration).filter(function (exp) {
100
+ return exp.node.source.value === '@storybook/addon-docs';
101
+ }).remove(); // const makeShortcode = ...
102
+ // const layoutProps = {};
103
+ // const MDXLayout = 'wrapper';
104
+
105
+ var MDX_DECLS = ['makeShortcode', 'layoutProps', 'MDXLayout'];
106
+ root.find(j.VariableDeclaration).filter(function (decl) {
107
+ return decl.node.declarations.length === 1 && MDX_DECLS.includes(decl.node.declarations[0].id.name);
108
+ }).remove(); // const Source = makeShortcode('Source');
109
+
110
+ root.find(j.VariableDeclarator).filter(function (expr) {
111
+ return expr.node.init.type === 'CallExpression' && expr.node.init.callee.type === 'Identifier' && expr.node.init.callee.name === 'makeShortcode';
112
+ }).remove(); // MDXContent.isMDXComponent = true;
113
+
114
+ root.find(j.AssignmentExpression).filter(function (expr) {
115
+ return expr.node.left.type === 'MemberExpression' && expr.node.left.object.type === 'Identifier' && expr.node.left.object.name === 'MDXContent';
116
+ }).remove(); // Add back `import React from 'react';` which is implicit in MDX
117
+
118
+ var react = root.find(j.ImportDeclaration).filter(function (decl) {
119
+ return decl.node.source.value === 'react';
120
+ });
121
+
122
+ if (react.size() === 0) {
123
+ root.find(j.Statement).at(0).insertBefore(j.importDeclaration([j.importDefaultSpecifier(j.identifier('React'))], j.literal('react')));
124
+ }
125
+
126
+ var source = root.toSource({
127
+ trailingComma: true,
128
+ quote: 'single',
129
+ tabWidth: 2
130
+ });
131
+ return prettier.format(source, {
132
+ parser: 'babel',
133
+ printWidth: 100,
134
+ tabWidth: 2,
135
+ bracketSpacing: true,
136
+ trailingComma: 'es5',
137
+ singleQuote: true
138
+ });
139
+ }
@@ -0,0 +1,50 @@
1
+ import "core-js/modules/es.symbol.description.js";
2
+
3
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
4
+
5
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
6
+
7
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
8
+
9
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
10
+
11
+ function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
12
+
13
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
14
+
15
+ export default function transformer(file, api) {
16
+ var j = api.jscodeshift;
17
+
18
+ var createImportDeclaration = function (specifiers, source) {
19
+ return j.importDeclaration(specifiers.map(function (s) {
20
+ return j.importSpecifier(j.identifier(s));
21
+ }), j.literal(source));
22
+ };
23
+
24
+ var deprecates = {
25
+ action: [['action'], '@storybook/addon-actions'],
26
+ linkTo: [['linkTo'], '@storybook/addon-links']
27
+ };
28
+ var transform = j(file.source).find(j.ImportDeclaration).filter(function (i) {
29
+ return i.value.source.value === '@storybook/react';
30
+ }).forEach(function (i) {
31
+ var importStatement = i.value;
32
+ importStatement.specifiers = importStatement.specifiers.filter(function (specifier) {
33
+ var item = deprecates[specifier.local.name];
34
+
35
+ if (item) {
36
+ var _item = _slicedToArray(item, 2),
37
+ specifiers = _item[0],
38
+ moduleName = _item[1];
39
+
40
+ i.insertAfter(createImportDeclaration(specifiers, moduleName));
41
+ return false;
42
+ }
43
+
44
+ return specifier;
45
+ });
46
+ });
47
+ return transform.toSource({
48
+ quote: 'single'
49
+ });
50
+ }