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

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 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
- }