@storybook/codemod 7.0.0-alpha.39 → 7.0.0-alpha.40

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -240,42 +240,6 @@ import { Meta, Story } from '@storybook/addon-docs';
240
240
  </Story>
241
241
  ```
242
242
 
243
- ### mdx-to-csf
244
-
245
- This converts all your MDX stories into Component Story Format.
246
-
247
- ```sh
248
- ./node_modules/.bin/jscodeshift -t ./node_modules/@storybook/codemod/dist/transforms/mdx-to-csf.js . --ignore-pattern "node_modules|dist" --extensions=mdx
249
- ```
250
-
251
- For example:
252
-
253
- ```js
254
- import React from 'react';
255
- import Button from './Button';
256
- import { Meta, Story } from '@storybook/addon-docs';
257
-
258
- <Meta title='Button' />
259
-
260
- <Story name='basic stories'><Button label='The Button' /></Story>
261
- ```
262
-
263
- Becomes:
264
-
265
- ```js
266
- import React from 'react';
267
- import Button from './Button';
268
-
269
- export default {
270
- title: 'Button',
271
- };
272
-
273
- export const basicStory = () => <Button label="The Button" />;
274
- basicStory.story = {
275
- name: 'basic stories',
276
- };
277
- ```
278
-
279
243
  ### upgrade-hierarchy-separators
280
244
 
281
245
  Starting in 5.3, Storybook is moving to using a single path separator, `/`, to specify the story hierarchy. It previously defaulted to `|` for story "roots" (optional) and either `/` or `.` for denoting paths. This codemod updates the old default to the new default.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/codemod",
3
- "version": "7.0.0-alpha.39",
3
+ "version": "7.0.0-alpha.40",
4
4
  "description": "A collection of codemod scripts written with JSCodeshift",
5
5
  "keywords": [
6
6
  "storybook"
@@ -38,10 +38,9 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@babel/types": "^7.12.11",
41
- "@mdx-js/mdx": "^1.6.22",
42
41
  "@storybook/csf": "0.0.2--canary.49.258942b.0",
43
- "@storybook/csf-tools": "7.0.0-alpha.39",
44
- "@storybook/node-logger": "7.0.0-alpha.39",
42
+ "@storybook/csf-tools": "7.0.0-alpha.40",
43
+ "@storybook/node-logger": "7.0.0-alpha.40",
45
44
  "cross-spawn": "^7.0.3",
46
45
  "globby": "^11.0.2",
47
46
  "jscodeshift": "^0.13.1",
@@ -64,5 +63,5 @@
64
63
  "./src/index.js"
65
64
  ]
66
65
  },
67
- "gitHead": "47386bd49d141ea70daac41ab3e4d52749fc5da9"
66
+ "gitHead": "8f6d8629f1ad7e776c39e2c7621f4a0d538aa93c"
68
67
  }
@@ -9,6 +9,9 @@ const inputRegExp = /\.input\.js$/;
9
9
 
10
10
  const fixturesDir = path.resolve(__dirname, '../__testfixtures__');
11
11
  fs.readdirSync(fixturesDir).forEach((transformName) => {
12
+ // FIXME: delete after https://github.com/storybookjs/storybook/issues/19497
13
+ if (transformName === 'mdx-to-csf') return;
14
+
12
15
  const transformFixturesDir = path.join(fixturesDir, transformName);
13
16
  describe(transformName, () =>
14
17
  fs
@@ -1,184 +0,0 @@
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
- /**
7
- * Convert a component's MDX file into module story format
8
- */
9
- export default function transformer(file, api) {
10
- const j = api.jscodeshift;
11
- const code = mdx.sync(file.source, {});
12
- const root = j(code);
13
-
14
- function parseJsxAttributes(attributes) {
15
- const result = {};
16
- attributes.forEach((attr) => {
17
- const key = attr.name.name;
18
- const 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(
26
- Object.entries(attrs).map(([key, val]) => j.property('init', j.identifier(key), val))
27
- );
28
- }
29
-
30
- function convertToStories(path) {
31
- const base = j(path);
32
-
33
- const meta = {};
34
- const includeStories = [];
35
- const storyStatements = [];
36
-
37
- // get rid of all mdxType junk
38
- base
39
- .find(j.JSXAttribute)
40
- .filter((attr) => attr.node.name.name === 'mdxType')
41
- .remove();
42
-
43
- // parse <Meta title="..." />
44
- base
45
- .find(j.JSXElement)
46
- .filter((elt) => elt.node.openingElement.name.name === 'Meta')
47
- .forEach((elt) => {
48
- const attrs = parseJsxAttributes(elt.node.openingElement.attributes);
49
- Object.assign(meta, attrs);
50
- });
51
-
52
- // parse <Story name="..." />
53
- base
54
- .find(j.JSXElement)
55
- .filter((elt) => elt.node.openingElement.name.name === 'Story')
56
- .forEach((elt) => {
57
- const attrs = parseJsxAttributes(elt.node.openingElement.attributes);
58
- if (attrs.name) {
59
- const storyKey = sanitizeName(attrs.name.value);
60
- includeStories.push(storyKey);
61
- if (storyKey === attrs.name.value) {
62
- delete attrs.name;
63
- }
64
- let body =
65
- elt.node.children.find((n) => n.type !== 'JSXText') ||
66
- j.literal(elt.node.children[0].value);
67
-
68
- if (body.type === 'JSXExpressionContainer') {
69
- body = body.expression;
70
- }
71
-
72
- storyStatements.push(
73
- j.exportDeclaration(
74
- false,
75
- j.variableDeclaration('const', [
76
- j.variableDeclarator(
77
- j.identifier(storyKey),
78
- body.type === 'ArrowFunctionExpression'
79
- ? body
80
- : j.arrowFunctionExpression([], body)
81
- ),
82
- ])
83
- )
84
- );
85
- if (Object.keys(attrs).length > 0) {
86
- storyStatements.push(
87
- j.assignmentStatement(
88
- '=',
89
- j.memberExpression(j.identifier(storyKey), j.identifier('story')),
90
- genObjectExpression(attrs)
91
- )
92
- );
93
- }
94
- storyStatements.push(j.emptyStatement());
95
- }
96
- });
97
-
98
- if (root.find(j.ExportNamedDeclaration).size() > 0) {
99
- meta.includeStories = j.arrayExpression(includeStories.map((key) => j.literal(key)));
100
- }
101
- const statements = [
102
- j.exportDefaultDeclaration(genObjectExpression(meta)),
103
- j.emptyStatement(),
104
- ...storyStatements,
105
- ];
106
-
107
- const lastStatement = root.find(j.Statement).at(-1);
108
- statements.reverse().forEach((stmt) => {
109
- lastStatement.insertAfter(stmt);
110
- });
111
- base.remove();
112
- }
113
-
114
- root.find(j.ExportDefaultDeclaration).forEach(convertToStories);
115
-
116
- // strip out Story/Meta import and MDX junk
117
-
118
- // /* @jsx mdx */
119
- root
120
- .find(j.ImportDeclaration)
121
- .at(0)
122
- .replaceWith((exp) => j.importDeclaration(exp.node.specifiers, exp.node.source));
123
-
124
- // import { Story, Meta } from '@storybook/addon-docs';
125
- root
126
- .find(j.ImportDeclaration)
127
- .filter((exp) => exp.node.source.value === '@storybook/addon-docs')
128
- .remove();
129
-
130
- // const makeShortcode = ...
131
- // const layoutProps = {};
132
- // const MDXLayout = 'wrapper';
133
- const MDX_DECLS = ['makeShortcode', 'layoutProps', 'MDXLayout'];
134
- root
135
- .find(j.VariableDeclaration)
136
- .filter(
137
- (decl) =>
138
- decl.node.declarations.length === 1 && MDX_DECLS.includes(decl.node.declarations[0].id.name)
139
- )
140
- .remove();
141
-
142
- // const Source = makeShortcode('Source');
143
- root
144
- .find(j.VariableDeclarator)
145
- .filter(
146
- (expr) =>
147
- expr.node.init.type === 'CallExpression' &&
148
- expr.node.init.callee.type === 'Identifier' &&
149
- expr.node.init.callee.name === 'makeShortcode'
150
- )
151
- .remove();
152
-
153
- // MDXContent.isMDXComponent = true;
154
- root
155
- .find(j.AssignmentExpression)
156
- .filter(
157
- (expr) =>
158
- expr.node.left.type === 'MemberExpression' &&
159
- expr.node.left.object.type === 'Identifier' &&
160
- expr.node.left.object.name === 'MDXContent'
161
- )
162
- .remove();
163
-
164
- // Add back `import React from 'react';` which is implicit in MDX
165
- const react = root.find(j.ImportDeclaration).filter((decl) => decl.node.source.value === 'react');
166
- if (react.size() === 0) {
167
- root
168
- .find(j.Statement)
169
- .at(0)
170
- .insertBefore(
171
- j.importDeclaration([j.importDefaultSpecifier(j.identifier('React'))], j.literal('react'))
172
- );
173
- }
174
-
175
- const source = root.toSource({ trailingComma: true, quote: 'single', tabWidth: 2 });
176
- return prettier.format(source, {
177
- parser: 'babel',
178
- printWidth: 100,
179
- tabWidth: 2,
180
- bracketSpacing: true,
181
- trailingComma: 'es5',
182
- singleQuote: true,
183
- });
184
- }