@storybook/codemod 7.0.0-beta.9 → 7.0.0-rc.0
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 +0 -39
- package/dist/index.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/mdx-to-csf.d.ts +7 -0
- package/dist/transforms/mdx-to-csf.js +55 -0
- package/dist/transforms/storiesof-to-csf.js +1 -1
- package/dist/transforms/upgrade-deprecated-types.d.ts +10 -0
- package/dist/transforms/upgrade-deprecated-types.js +2 -0
- package/jest.config.js +2 -0
- package/package.json +31 -16
- 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
@@ -0,0 +1,342 @@
|
|
1
|
+
/* eslint-disable no-param-reassign,@typescript-eslint/no-shadow,consistent-return */
|
2
|
+
import type { FileInfo } from 'jscodeshift';
|
3
|
+
import { babelParse, babelParseExpression } from '@storybook/csf-tools';
|
4
|
+
import { remark } from 'remark';
|
5
|
+
import type { Root } from 'remark-mdx';
|
6
|
+
import remarkMdx from 'remark-mdx';
|
7
|
+
import { SKIP, visit } from 'unist-util-visit';
|
8
|
+
import { is } from 'unist-util-is';
|
9
|
+
import type {
|
10
|
+
MdxJsxAttribute,
|
11
|
+
MdxJsxExpressionAttribute,
|
12
|
+
MdxJsxFlowElement,
|
13
|
+
MdxJsxTextElement,
|
14
|
+
} from 'mdast-util-mdx-jsx';
|
15
|
+
import type { MdxjsEsm } from 'mdast-util-mdxjs-esm';
|
16
|
+
import * as t from '@babel/types';
|
17
|
+
import type { BabelFile } from '@babel/core';
|
18
|
+
import * as babel from '@babel/core';
|
19
|
+
import * as recast from 'recast';
|
20
|
+
import * as path from 'node:path';
|
21
|
+
import prettier from 'prettier';
|
22
|
+
import * as fs from 'node:fs';
|
23
|
+
import camelCase from 'lodash/camelCase';
|
24
|
+
import type { MdxFlowExpression } from 'mdast-util-mdx-expression';
|
25
|
+
|
26
|
+
const mdxProcessor = remark().use(remarkMdx) as ReturnType<typeof remark>;
|
27
|
+
|
28
|
+
export default function jscodeshift(info: FileInfo) {
|
29
|
+
const parsed = path.parse(info.path);
|
30
|
+
|
31
|
+
let baseName = path.join(
|
32
|
+
parsed.dir,
|
33
|
+
parsed.name.replace('.mdx', '').replace('.stories', '').replace('.story', '')
|
34
|
+
);
|
35
|
+
|
36
|
+
// make sure the new csf file we are going to create exists
|
37
|
+
while (fs.existsSync(`${baseName}.stories.js`)) {
|
38
|
+
baseName += '_';
|
39
|
+
}
|
40
|
+
|
41
|
+
const result = transform(info.source, path.basename(baseName));
|
42
|
+
|
43
|
+
if (result == null) {
|
44
|
+
// We can not make a valid migration.
|
45
|
+
return;
|
46
|
+
}
|
47
|
+
|
48
|
+
const [mdx, csf] = result;
|
49
|
+
|
50
|
+
fs.writeFileSync(`${baseName}.stories.js`, csf);
|
51
|
+
|
52
|
+
return mdx;
|
53
|
+
}
|
54
|
+
|
55
|
+
export function transform(source: string, baseName: string): [mdx: string, csf: string] {
|
56
|
+
const root = mdxProcessor.parse(source);
|
57
|
+
const storyNamespaceName = nameToValidExport(`${baseName}Stories`);
|
58
|
+
|
59
|
+
const metaAttributes: Array<MdxJsxAttribute | MdxJsxExpressionAttribute> = [];
|
60
|
+
const storiesMap = new Map<
|
61
|
+
string,
|
62
|
+
| {
|
63
|
+
type: 'value';
|
64
|
+
attributes: Array<MdxJsxAttribute | MdxJsxExpressionAttribute>;
|
65
|
+
children: (MdxJsxFlowElement | MdxJsxTextElement)['children'];
|
66
|
+
}
|
67
|
+
| {
|
68
|
+
type: 'reference';
|
69
|
+
}
|
70
|
+
| {
|
71
|
+
type: 'id';
|
72
|
+
}
|
73
|
+
>();
|
74
|
+
|
75
|
+
// rewrite addon docs import
|
76
|
+
visit(root, ['mdxjsEsm'], (node: MdxjsEsm) => {
|
77
|
+
node.value = node.value
|
78
|
+
.replaceAll('@storybook/addon-docs/blocks', '@storybook/blocks')
|
79
|
+
.replaceAll('@storybook/addon-docs', '@storybook/blocks');
|
80
|
+
});
|
81
|
+
|
82
|
+
const file = getEsmAst(root);
|
83
|
+
addStoriesImport(root, baseName, storyNamespaceName);
|
84
|
+
|
85
|
+
visit(
|
86
|
+
root,
|
87
|
+
['mdxJsxFlowElement', 'mdxJsxTextElement'],
|
88
|
+
(node: MdxJsxFlowElement | MdxJsxTextElement, index, parent) => {
|
89
|
+
if (is(node, { name: 'Meta' })) {
|
90
|
+
metaAttributes.push(...node.attributes);
|
91
|
+
node.attributes = [
|
92
|
+
{
|
93
|
+
type: 'mdxJsxAttribute',
|
94
|
+
name: 'of',
|
95
|
+
value: {
|
96
|
+
type: 'mdxJsxAttributeValueExpression',
|
97
|
+
value: storyNamespaceName,
|
98
|
+
},
|
99
|
+
},
|
100
|
+
];
|
101
|
+
}
|
102
|
+
if (is(node, { name: 'Story' })) {
|
103
|
+
const nameAttribute = node.attributes.find(
|
104
|
+
(it) => it.type === 'mdxJsxAttribute' && it.name === 'name'
|
105
|
+
);
|
106
|
+
const idAttribute = node.attributes.find(
|
107
|
+
(it) => it.type === 'mdxJsxAttribute' && it.name === 'id'
|
108
|
+
);
|
109
|
+
const storyAttribute = node.attributes.find(
|
110
|
+
(it) => it.type === 'mdxJsxAttribute' && it.name === 'story'
|
111
|
+
);
|
112
|
+
if (typeof nameAttribute?.value === 'string') {
|
113
|
+
let name = nameToValidExport(nameAttribute.value);
|
114
|
+
while (variableNameExists(name)) name += '_';
|
115
|
+
|
116
|
+
storiesMap.set(name, {
|
117
|
+
type: 'value',
|
118
|
+
attributes: node.attributes,
|
119
|
+
children: node.children,
|
120
|
+
});
|
121
|
+
node.attributes = [
|
122
|
+
{
|
123
|
+
type: 'mdxJsxAttribute',
|
124
|
+
name: 'of',
|
125
|
+
value: {
|
126
|
+
type: 'mdxJsxAttributeValueExpression',
|
127
|
+
value: `${storyNamespaceName}.${name}`,
|
128
|
+
},
|
129
|
+
},
|
130
|
+
];
|
131
|
+
node.children = [];
|
132
|
+
} else if (idAttribute?.value) {
|
133
|
+
// e.g. <Story id="button--primary" />
|
134
|
+
// should be migrated manually as it is very hard to find out where the definition of such a string id is located
|
135
|
+
const nodeString = mdxProcessor.stringify({ type: 'root', children: [node] }).trim();
|
136
|
+
const newNode: MdxFlowExpression = {
|
137
|
+
type: 'mdxFlowExpression',
|
138
|
+
value: `/* ${nodeString} is deprecated, please migrate it to <Story of={referenceToStory} /> */`,
|
139
|
+
};
|
140
|
+
storiesMap.set(idAttribute.value as string, { type: 'id' });
|
141
|
+
parent.children.splice(index, 0, newNode);
|
142
|
+
// current index is the new comment, and index + 1 is current node
|
143
|
+
// SKIP traversing current node, and continue with the node after that
|
144
|
+
return [SKIP, index + 2];
|
145
|
+
} else if (
|
146
|
+
storyAttribute?.type === 'mdxJsxAttribute' &&
|
147
|
+
typeof storyAttribute.value === 'object' &&
|
148
|
+
storyAttribute.value.type === 'mdxJsxAttributeValueExpression'
|
149
|
+
) {
|
150
|
+
// e.g. <Story story={Primary} />
|
151
|
+
|
152
|
+
const name = storyAttribute.value.value;
|
153
|
+
node.attributes = [
|
154
|
+
{
|
155
|
+
type: 'mdxJsxAttribute',
|
156
|
+
name: 'of',
|
157
|
+
value: {
|
158
|
+
type: 'mdxJsxAttributeValueExpression',
|
159
|
+
value: `${storyNamespaceName}.${name}`,
|
160
|
+
},
|
161
|
+
},
|
162
|
+
];
|
163
|
+
node.children = [];
|
164
|
+
|
165
|
+
storiesMap.set(name, { type: 'reference' });
|
166
|
+
} else {
|
167
|
+
parent.children.splice(index, 1);
|
168
|
+
// Do not traverse `node`, continue at the node *now* at `index`.
|
169
|
+
return [SKIP, index];
|
170
|
+
}
|
171
|
+
}
|
172
|
+
return undefined;
|
173
|
+
}
|
174
|
+
);
|
175
|
+
|
176
|
+
const metaProperties = metaAttributes.flatMap((attribute) => {
|
177
|
+
if (attribute.type === 'mdxJsxAttribute') {
|
178
|
+
if (typeof attribute.value === 'string') {
|
179
|
+
return [t.objectProperty(t.identifier(attribute.name), t.stringLiteral(attribute.value))];
|
180
|
+
}
|
181
|
+
return [
|
182
|
+
t.objectProperty(
|
183
|
+
t.identifier(attribute.name),
|
184
|
+
babelParseExpression(attribute.value.value) as any as t.Expression
|
185
|
+
),
|
186
|
+
];
|
187
|
+
}
|
188
|
+
return [];
|
189
|
+
});
|
190
|
+
|
191
|
+
file.path.traverse({
|
192
|
+
// remove mdx imports from csf
|
193
|
+
ImportDeclaration(path) {
|
194
|
+
if (path.node.source.value === '@storybook/blocks') {
|
195
|
+
path.remove();
|
196
|
+
}
|
197
|
+
},
|
198
|
+
// remove exports from csf file
|
199
|
+
ExportNamedDeclaration(path) {
|
200
|
+
path.replaceWith(path.node.declaration);
|
201
|
+
},
|
202
|
+
});
|
203
|
+
|
204
|
+
if (storiesMap.size === 0) {
|
205
|
+
// A CSF file must have at least one story, so skip migrating if this is the case.
|
206
|
+
return null;
|
207
|
+
}
|
208
|
+
|
209
|
+
const newStatements: t.Statement[] = [
|
210
|
+
t.exportDefaultDeclaration(t.objectExpression(metaProperties)),
|
211
|
+
];
|
212
|
+
|
213
|
+
function mapChildrenToRender(children: (MdxJsxFlowElement | MdxJsxTextElement)['children']) {
|
214
|
+
const child = children[0];
|
215
|
+
|
216
|
+
if (!child) return undefined;
|
217
|
+
|
218
|
+
if (child.type === 'text') {
|
219
|
+
return t.arrowFunctionExpression([], t.stringLiteral(child.value));
|
220
|
+
}
|
221
|
+
if (child.type === 'mdxFlowExpression' || child.type === 'mdxTextExpression') {
|
222
|
+
const expression = babelParseExpression(child.value) as any as t.Expression;
|
223
|
+
|
224
|
+
// Recreating those lines: https://github.com/storybookjs/mdx1-csf/blob/f408fc97e9a63097ca1ee577df9315a3cccca975/src/sb-mdx-plugin.ts#L185-L198
|
225
|
+
const BIND_REGEX = /\.bind\(.*\)/;
|
226
|
+
if (BIND_REGEX.test(child.value)) {
|
227
|
+
return expression;
|
228
|
+
}
|
229
|
+
if (t.isIdentifier(expression)) {
|
230
|
+
return expression;
|
231
|
+
}
|
232
|
+
if (t.isArrowFunctionExpression(expression)) {
|
233
|
+
return expression;
|
234
|
+
}
|
235
|
+
return t.arrowFunctionExpression([], expression);
|
236
|
+
}
|
237
|
+
|
238
|
+
const expression = babelParseExpression(
|
239
|
+
mdxProcessor.stringify({ type: 'root', children: [child] })
|
240
|
+
) as any as t.Expression;
|
241
|
+
return t.arrowFunctionExpression([], expression);
|
242
|
+
}
|
243
|
+
|
244
|
+
function variableNameExists(name: string) {
|
245
|
+
let found = false;
|
246
|
+
file.path.traverse({
|
247
|
+
VariableDeclarator: (path) => {
|
248
|
+
const lVal = path.node.id;
|
249
|
+
if (t.isIdentifier(lVal) && lVal.name === name) found = true;
|
250
|
+
},
|
251
|
+
});
|
252
|
+
return found;
|
253
|
+
}
|
254
|
+
|
255
|
+
newStatements.push(
|
256
|
+
...[...storiesMap].flatMap(([key, value]) => {
|
257
|
+
if (value.type === 'id') return [];
|
258
|
+
if (value.type === 'reference') {
|
259
|
+
return [
|
260
|
+
t.exportNamedDeclaration(null, [t.exportSpecifier(t.identifier(key), t.identifier(key))]),
|
261
|
+
];
|
262
|
+
}
|
263
|
+
const renderProperty = mapChildrenToRender(value.children);
|
264
|
+
const newObject = t.objectExpression([
|
265
|
+
...(renderProperty
|
266
|
+
? [t.objectProperty(t.identifier('render'), mapChildrenToRender(value.children))]
|
267
|
+
: []),
|
268
|
+
...value.attributes.flatMap((attribute) => {
|
269
|
+
if (attribute.type === 'mdxJsxAttribute') {
|
270
|
+
if (typeof attribute.value === 'string') {
|
271
|
+
return [
|
272
|
+
t.objectProperty(t.identifier(attribute.name), t.stringLiteral(attribute.value)),
|
273
|
+
];
|
274
|
+
}
|
275
|
+
return [
|
276
|
+
t.objectProperty(
|
277
|
+
t.identifier(attribute.name),
|
278
|
+
babelParseExpression(attribute.value.value) as any as t.Expression
|
279
|
+
),
|
280
|
+
];
|
281
|
+
}
|
282
|
+
return [];
|
283
|
+
}),
|
284
|
+
]);
|
285
|
+
|
286
|
+
return [
|
287
|
+
t.exportNamedDeclaration(
|
288
|
+
t.variableDeclaration('const', [t.variableDeclarator(t.identifier(key), newObject)])
|
289
|
+
),
|
290
|
+
];
|
291
|
+
})
|
292
|
+
);
|
293
|
+
|
294
|
+
file.path.node.body = [...file.path.node.body, ...newStatements];
|
295
|
+
|
296
|
+
const newMdx = mdxProcessor.stringify(root);
|
297
|
+
let output = recast.print(file.path.node).code;
|
298
|
+
|
299
|
+
const prettierConfig = prettier.resolveConfig.sync('.', { editorconfig: true }) || {
|
300
|
+
printWidth: 100,
|
301
|
+
tabWidth: 2,
|
302
|
+
bracketSpacing: true,
|
303
|
+
trailingComma: 'es5',
|
304
|
+
singleQuote: true,
|
305
|
+
};
|
306
|
+
|
307
|
+
output = prettier.format(output, { ...prettierConfig, filepath: `file.jsx` });
|
308
|
+
|
309
|
+
return [newMdx, output];
|
310
|
+
}
|
311
|
+
|
312
|
+
function getEsmAst(root: Root) {
|
313
|
+
const esm: string[] = [];
|
314
|
+
visit(root, ['mdxjsEsm'], (node: MdxjsEsm) => {
|
315
|
+
esm.push(node.value);
|
316
|
+
});
|
317
|
+
const esmSource = `${esm.join('\n\n')}`;
|
318
|
+
|
319
|
+
// @ts-expect-error File is not yet exposed, see https://github.com/babel/babel/issues/11350#issuecomment-644118606
|
320
|
+
const file: BabelFile = new babel.File(
|
321
|
+
{ filename: 'info.path' },
|
322
|
+
{ code: esmSource, ast: babelParse(esmSource) }
|
323
|
+
);
|
324
|
+
return file;
|
325
|
+
}
|
326
|
+
|
327
|
+
function addStoriesImport(root: Root, baseName: string, storyNamespaceName: string): void {
|
328
|
+
let found = false;
|
329
|
+
|
330
|
+
visit(root, ['mdxjsEsm'], (node: MdxjsEsm) => {
|
331
|
+
if (!found) {
|
332
|
+
node.value += `\nimport * as ${storyNamespaceName} from './${baseName}.stories';`;
|
333
|
+
found = true;
|
334
|
+
}
|
335
|
+
});
|
336
|
+
}
|
337
|
+
|
338
|
+
export function nameToValidExport(name: string) {
|
339
|
+
const [first, ...rest] = Array.from(camelCase(name));
|
340
|
+
|
341
|
+
return `${first.match(/[a-zA-Z_$]/) ? first.toUpperCase() : `$${first}`}${rest.join('')}`;
|
342
|
+
}
|
@@ -0,0 +1,142 @@
|
|
1
|
+
/* eslint-disable no-underscore-dangle */
|
2
|
+
import prettier from 'prettier';
|
3
|
+
import type { API, FileInfo } from 'jscodeshift';
|
4
|
+
import type { BabelFile, NodePath } from '@babel/core';
|
5
|
+
import * as babel from '@babel/core';
|
6
|
+
import { loadCsf } from '@storybook/csf-tools';
|
7
|
+
import * as recast from 'recast';
|
8
|
+
import * as t from '@babel/types';
|
9
|
+
|
10
|
+
const logger = console;
|
11
|
+
|
12
|
+
const deprecatedTypes = [
|
13
|
+
'ComponentStory',
|
14
|
+
'ComponentStoryFn',
|
15
|
+
'ComponentStoryObj',
|
16
|
+
'ComponentMeta',
|
17
|
+
'Story',
|
18
|
+
];
|
19
|
+
|
20
|
+
function migrateType(oldType: string) {
|
21
|
+
if (oldType === 'Story' || oldType === 'ComponentStory') return 'StoryFn';
|
22
|
+
return oldType.replace('Component', '');
|
23
|
+
}
|
24
|
+
|
25
|
+
export default function transform(info: FileInfo, api: API, options: { parser?: string }) {
|
26
|
+
// TODO what do I need to with the title?
|
27
|
+
const fileNode = loadCsf(info.source, { makeTitle: (title) => title })._ast;
|
28
|
+
// @ts-expect-error File is not yet exposed, see https://github.com/babel/babel/issues/11350#issuecomment-644118606
|
29
|
+
const file: BabelFile = new babel.File(
|
30
|
+
{ filename: info.path },
|
31
|
+
{ code: info.source, ast: fileNode }
|
32
|
+
);
|
33
|
+
|
34
|
+
upgradeDeprecatedTypes(file);
|
35
|
+
|
36
|
+
let output = recast.print(file.path.node).code;
|
37
|
+
|
38
|
+
try {
|
39
|
+
const prettierConfig = prettier.resolveConfig.sync('.', { editorconfig: true }) || {
|
40
|
+
printWidth: 100,
|
41
|
+
tabWidth: 2,
|
42
|
+
bracketSpacing: true,
|
43
|
+
trailingComma: 'es5',
|
44
|
+
singleQuote: true,
|
45
|
+
};
|
46
|
+
|
47
|
+
output = prettier.format(output, { ...prettierConfig, filepath: info.path });
|
48
|
+
} catch (e) {
|
49
|
+
logger.log(`Failed applying prettier to ${info.path}.`);
|
50
|
+
}
|
51
|
+
|
52
|
+
return output;
|
53
|
+
}
|
54
|
+
|
55
|
+
export const parser = 'tsx';
|
56
|
+
|
57
|
+
export function upgradeDeprecatedTypes(file: BabelFile) {
|
58
|
+
const importedNamespaces: Set<string> = new Set();
|
59
|
+
const typeReferencesToUpdate: Set<string> = new Set();
|
60
|
+
const existingImports: { name: string; isAlias: boolean; path: NodePath }[] = [];
|
61
|
+
|
62
|
+
file.path.traverse({
|
63
|
+
ImportDeclaration: (path) => {
|
64
|
+
existingImports.push(
|
65
|
+
...path.get('specifiers').map((specifier) => ({
|
66
|
+
name: specifier.node.local.name,
|
67
|
+
isAlias: !(
|
68
|
+
specifier.isImportSpecifier() &&
|
69
|
+
t.isIdentifier(specifier.node.imported) &&
|
70
|
+
specifier.node.local.name === specifier.node.imported.name
|
71
|
+
),
|
72
|
+
path: specifier,
|
73
|
+
}))
|
74
|
+
);
|
75
|
+
|
76
|
+
const source = path.node.source.value;
|
77
|
+
if (!source.startsWith('@storybook')) return;
|
78
|
+
|
79
|
+
path.get('specifiers').forEach((specifier) => {
|
80
|
+
if (specifier.isImportNamespaceSpecifier()) {
|
81
|
+
importedNamespaces.add(specifier.node.local.name);
|
82
|
+
}
|
83
|
+
if (!specifier.isImportSpecifier()) return;
|
84
|
+
const imported = specifier.get('imported');
|
85
|
+
if (!imported.isIdentifier()) return;
|
86
|
+
|
87
|
+
// if we find a deprecated import
|
88
|
+
if (deprecatedTypes.includes(imported.node.name)) {
|
89
|
+
// we don't have to rewrite type references for aliased imports
|
90
|
+
if (imported.node.name === specifier.node.local.name) {
|
91
|
+
typeReferencesToUpdate.add(specifier.node.local.name);
|
92
|
+
}
|
93
|
+
|
94
|
+
const newType = migrateType(imported.node.name);
|
95
|
+
|
96
|
+
// replace the deprecated import type when the new type isn't yet imported
|
97
|
+
// note that we don't replace the local name of the specifier
|
98
|
+
if (!existingImports.some((it) => it.name === newType)) {
|
99
|
+
imported.replaceWith(t.identifier(newType));
|
100
|
+
existingImports.push({ name: newType, isAlias: false, path: specifier });
|
101
|
+
} else {
|
102
|
+
// if the existing import has the same local name but is an alias we throw
|
103
|
+
// we could have imported the type with an alias, but seems to much effort
|
104
|
+
const existingImport = existingImports.find((it) => it.name === newType && it.isAlias);
|
105
|
+
if (existingImport) {
|
106
|
+
throw existingImport.path.buildCodeFrameError(
|
107
|
+
'This codemod does not support local imports that are called the same as a storybook import.\n' +
|
108
|
+
'Rename this local import and try again.'
|
109
|
+
);
|
110
|
+
} else {
|
111
|
+
// if the type already exists, without being aliased
|
112
|
+
// we can safely remove the deprecated import now
|
113
|
+
specifier.remove();
|
114
|
+
}
|
115
|
+
}
|
116
|
+
}
|
117
|
+
});
|
118
|
+
},
|
119
|
+
});
|
120
|
+
|
121
|
+
file.path.traverse({
|
122
|
+
TSTypeReference: (path) => {
|
123
|
+
const typeName = path.get('typeName');
|
124
|
+
if (typeName.isIdentifier()) {
|
125
|
+
if (typeReferencesToUpdate.has(typeName.node.name)) {
|
126
|
+
typeName.replaceWith(t.identifier(migrateType(typeName.node.name)));
|
127
|
+
}
|
128
|
+
} else if (typeName.isTSQualifiedName()) {
|
129
|
+
// For example SB.StoryObj
|
130
|
+
const namespace = typeName.get('left');
|
131
|
+
if (namespace.isIdentifier()) {
|
132
|
+
if (importedNamespaces.has(namespace.node.name)) {
|
133
|
+
const right = typeName.get('right');
|
134
|
+
if (deprecatedTypes.includes(right.node.name)) {
|
135
|
+
right.replaceWith(t.identifier(migrateType(right.node.name)));
|
136
|
+
}
|
137
|
+
}
|
138
|
+
}
|
139
|
+
}
|
140
|
+
},
|
141
|
+
});
|
142
|
+
}
|
package/dist/chunk-3OPQTROG.mjs
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
var packageNames={"@kadira/react-storybook-decorator-centered":"@storybook/addon-centered","@kadira/storybook-addons":"@storybook/preview-api","@kadira/storybook-addon-actions":"@storybook/addon-actions","@kadira/storybook-addon-comments":"@storybook/addon-comments","@kadira/storybook-addon-graphql":"@storybook/addon-graphql","@kadira/storybook-addon-info":"@storybook/addon-info","@kadira/storybook-addon-knobs":"@storybook/addon-knobs","@kadira/storybook-addon-links":"@storybook/addon-links","@kadira/storybook-addon-notes":"@storybook/addon-notes","@kadira/storybook-addon-options":"@storybook/addon-options","@kadira/storybook-channels":"@storybook/channels","@kadira/storybook-channel-postmsg":"@storybook/channel-postmessage","@kadira/storybook-channel-websocket":"@storybook/channel-websocket","@kadira/storybook-ui":"@storybook/manager","@kadira/react-native-storybook":"@storybook/react-native","@kadira/react-storybook":"@storybook/react","@kadira/getstorybook":"@storybook/cli","@kadira/storybook":"@storybook/react",storyshots:"@storybook/addon-storyshots",getstorybook:"@storybook/cli"};function transformer(file,api){let j=api.jscodeshift,packageNamesKeys=Object.keys(packageNames),getMatch=oldpart=>packageNamesKeys.find(newpart=>oldpart.match(newpart)),getNewPackageName=oldPackageName=>{let match=getMatch(oldPackageName);if(match){let replacement=packageNames[match];return oldPackageName.replace(match,replacement)}return oldPackageName},updatePackageName=declaration=>(declaration.node.source.value=getNewPackageName(declaration.node.source.value),declaration.node);return j(file.source).find(j.ImportDeclaration).replaceWith(updatePackageName).toSource({quote:"single"})}export{packageNames,transformer};
|
package/dist/chunk-B5FMQ3BX.mjs
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
function transformer(file,api){let j=api.jscodeshift,root=j(file.source),getOptions=args=>args[3]===void 0?args[2]===void 0?[args[0]]:[args[1]]:[j.objectExpression([j.property("init",j.identifier("text"),args[1]),...args[3].properties])],withInfo=addWithInfoExpression=>{let{node}=addWithInfoExpression,args=node.arguments,storyComponent=args[2]?args[2]:args[1];return node.callee.property.name="add",node.arguments=[args[0],j.callExpression(j.callExpression(j.identifier("withInfo"),getOptions(args)),[storyComponent])],node},checkWithInfoImport=()=>{root.find(j.ImportDeclaration).filter(imp=>imp.node.source.value==="@storybook/addon-info").size()||root.find(j.ImportDeclaration).at(-1).insertAfter(j.importDeclaration([j.importSpecifier(j.identifier("withInfo"))],j.literal("@storybook/addon-info")))},addWithInfoExpressions=root.find(j.CallExpression,{callee:{property:{name:"addWithInfo"}}});return addWithInfoExpressions.size()&&(checkWithInfoImport(),addWithInfoExpressions.replaceWith(withInfo)),root.toSource()}export{transformer};
|
package/dist/chunk-CO6EPEMB.mjs
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
import camelCase from"lodash/camelCase";import upperFirst from"lodash/upperFirst";var sanitizeName=name=>{let key=upperFirst(camelCase(name));return/^\d/.test(key)&&(key=`_${key}`),/^\d/.test(key)&&(key=`_${key}`),key};function jscodeshiftToPrettierParser(parser){let parserMap={babylon:"babel",flow:"flow",ts:"typescript",tsx:"typescript"};return parser&&parserMap[parser]||"babel"}export{sanitizeName,jscodeshiftToPrettierParser};
|
package/dist/index.mjs
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
import{packageNames,transformer}from"./chunk-3OPQTROG.mjs";import{jscodeshiftToPrettierParser}from"./chunk-CO6EPEMB.mjs";import{transformer as transformer2}from"./chunk-B5FMQ3BX.mjs";import fs from"fs";import path from"path";import{promisify}from"util";import globby from"globby";import{sync as spawnSync}from"cross-spawn";var TRANSFORM_DIR=`${__dirname}/transforms`;function listCodemods(){return fs.readdirSync(TRANSFORM_DIR).filter(fname=>fname.endsWith(".js")).map(fname=>fname.slice(0,-3))}var renameAsync=promisify(fs.rename);async function renameFile(file,from,to,{logger}){let newFile=file.replace(from,to);return logger.log(`Rename: ${file} ${newFile}`),renameAsync(file,newFile)}async function runCodemod(codemod,{glob,logger,dryRun,rename,parser}){if(!listCodemods().includes(codemod))throw new Error(`Unknown codemod ${codemod}. Run --list for options.`);let renameParts=null;if(rename&&(renameParts=rename.split(":"),renameParts.length!==2))throw new Error(`Codemod rename: expected format "from:to", got "${rename}"`);let inferredParser=parser;if(!parser){let extension=path.extname(glob).slice(1);jscodeshiftToPrettierParser(extension)!=="babel"&&(inferredParser=extension)}let files=await globby([glob,"!**/node_modules","!**/dist"]);if(logger.log(`=> Applying ${codemod}: ${files.length} files`),!dryRun){let parserArgs=inferredParser?["--parser",inferredParser]:[];spawnSync("npx",["jscodeshift","-t",`${TRANSFORM_DIR}/${codemod}.js`,...parserArgs,...files],{stdio:"inherit",shell:!0})}if(renameParts){let[from,to]=renameParts;logger.log(`=> Renaming ${rename}: ${files.length} files`),await Promise.all(files.map(file=>renameFile(file,new RegExp(`${from}$`),to,{logger})))}}export{listCodemods,packageNames,runCodemod,transformer2 as updateAddonInfo,transformer as updateOrganisationName};
|
@@ -1 +0,0 @@
|
|
1
|
-
function transformer(file,api){let j=api.jscodeshift,root=j(file.source),importMap={};root.find(j.ImportDeclaration).forEach(imp=>imp.node.specifiers.forEach(spec=>{importMap[spec.local.name]=!0}));function getLeafName(string){let parts=string.split(/\/|\.|\|/);return parts[parts.length-1]}function addComponentParameter(call){let{node}=call,leafName=getLeafName(node.arguments[0].value);return j.callExpression(j.memberExpression(node,j.identifier("addParameters")),[j.objectExpression([j.property("init",j.identifier("component"),j.identifier(leafName))])])}return root.find(j.CallExpression).filter(call=>call.node.callee.name==="storiesOf").filter(call=>call.node.arguments.length>0&&call.node.arguments[0].type==="Literal").filter(call=>{let leafName=getLeafName(call.node.arguments[0].value);return importMap[leafName]}).replaceWith(addComponentParameter),root.toSource()}export{transformer as default};
|
@@ -1 +0,0 @@
|
|
1
|
-
import{jscodeshiftToPrettierParser}from"../chunk-CO6EPEMB.mjs";import prettier from"prettier";import*as t from"@babel/types";import{formatCsf,loadCsf}from"@storybook/csf-tools";var logger=console,renameAnnotation=annotation=>annotation==="storyName"?"name":annotation,getTemplateBindVariable=init=>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,isStoryAnnotation=(stmt,objectExports)=>t.isExpressionStatement(stmt)&&t.isAssignmentExpression(stmt.expression)&&t.isMemberExpression(stmt.expression.left)&&t.isIdentifier(stmt.expression.left.object)&&objectExports[stmt.expression.left.object.name],isTemplateDeclaration=(stmt,templates)=>t.isVariableDeclaration(stmt)&&stmt.declarations.length===1&&t.isIdentifier(stmt.declarations[0].id)&&templates[stmt.declarations[0].id.name],getNewExport=(stmt,objectExports)=>{if(t.isExportNamedDeclaration(stmt)&&t.isVariableDeclaration(stmt.declaration)&&stmt.declaration.declarations.length===1){let decl=stmt.declaration.declarations[0];if(t.isVariableDeclarator(decl)&&t.isIdentifier(decl.id))return objectExports[decl.id.name]}return null},isReactGlobalRenderFn=(csf,storyFn)=>{if(csf._meta?.component&&t.isArrowFunctionExpression(storyFn)&&storyFn.params.length===1&&t.isJSXElement(storyFn.body)){let{openingElement}=storyFn.body;if(openingElement.selfClosing&&t.isJSXIdentifier(openingElement.name)&&openingElement.attributes.length===1){let attr=openingElement.attributes[0],param=storyFn.params[0];if(t.isJSXSpreadAttribute(attr)&&t.isIdentifier(attr.argument)&&t.isIdentifier(param)&¶m.name===attr.argument.name&&csf._meta.component===openingElement.name.name)return!0}}return!1},isSimpleCSFStory=(init,annotations)=>annotations.length===0&&t.isArrowFunctionExpression(init)&&init.params.length===0;function transform({source},api,options){let csf=loadCsf(source,{makeTitle:userTitle=>userTitle||"FIXME"});try{csf.parse()}catch(err){return logger.log(`Error ${err}, skipping`),source}let objectExports={};Object.entries(csf._storyExports).forEach(([key,decl])=>{let annotations=Object.entries(csf._storyAnnotations[key]).map(([annotation,val])=>t.objectProperty(t.identifier(renameAnnotation(annotation)),val));if(t.isVariableDeclarator(decl)){let{init,id}=decl,template=getTemplateBindVariable(init);if(!t.isArrowFunctionExpression(init)&&!template||isSimpleCSFStory(init,annotations))return;let storyFn=template&&csf._templates[template];storyFn||(storyFn=init);let keyId=t.identifier(key),{typeAnnotation}=id;typeAnnotation&&(keyId.typeAnnotation=typeAnnotation);let renderAnnotation=isReactGlobalRenderFn(csf,storyFn)?[]:[t.objectProperty(t.identifier("render"),storyFn)];objectExports[key]=t.exportNamedDeclaration(t.variableDeclaration("const",[t.variableDeclarator(keyId,t.objectExpression([...renderAnnotation,...annotations]))]))}});let updatedBody=csf._ast.program.body.reduce((acc,stmt)=>{if(isStoryAnnotation(stmt,objectExports)||isTemplateDeclaration(stmt,csf._templates))return acc;let newExport=getNewExport(stmt,objectExports);return newExport?(acc.push(newExport),acc):(acc.push(stmt),acc)},[]);csf._ast.program.body=updatedBody;let output=formatCsf(csf),prettierConfig=prettier.resolveConfig.sync(".",{editorconfig:!0})||{printWidth:100,tabWidth:2,bracketSpacing:!0,trailingComma:"es5",singleQuote:!0};return prettier.format(output,{...prettierConfig,parser:jscodeshiftToPrettierParser(options?.parser)})}var csf_2_to_3_default=transform;export{csf_2_to_3_default as default};
|
@@ -1 +0,0 @@
|
|
1
|
-
var getContainingStatement=n=>n.node.type.endsWith("Statement")?n:getContainingStatement(n.parent);function transformer(file,api){let j=api.jscodeshift,root=j(file.source),renameKey=exp=>exp.type==="Identifier"&&exp.name==="name"?j.identifier("storyName"):exp;if(root.find(j.ExportDefaultDeclaration).filter(def=>def.node.declaration.type==="ObjectExpression"&&def.node.declaration.properties.map(p=>p.key.name).includes("title")).size()===0)return root.toSource();let storyAssignments=root.find(j.AssignmentExpression).filter(exp=>{let{left,right}=exp.node;return left.type==="MemberExpression"&&left.object.type==="Identifier"&&left.property.type==="Identifier"&&left.property.name==="story"&&right.type==="ObjectExpression"});return storyAssignments.forEach(exp=>{let{left,right}=exp.node;right.properties.forEach(prop=>{getContainingStatement(exp).insertBefore(j.assignmentStatement("=",j.memberExpression(left.object,renameKey(prop.key)),prop.value))})}),storyAssignments.remove(),root.find(j.AssignmentExpression).filter(exp=>{let{left}=exp.node;return left.type==="MemberExpression"&&left.object.type==="MemberExpression"&&left.object.property.type==="Identifier"&&left.object.property.name==="story"&&left.property.type==="Identifier"}).replaceWith(exp=>{let{left,right}=exp.node;return j.assignmentExpression("=",j.memberExpression(left.object.object,renameKey(left.property)),right)}),root.toSource({quote:"single"})}export{transformer as default};
|
@@ -1,29 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Convert a component's module story file into an MDX file
|
3
|
-
*
|
4
|
-
* For example:
|
5
|
-
*
|
6
|
-
* ```
|
7
|
-
* input { Button } from './Button';
|
8
|
-
* export default {
|
9
|
-
* title: 'Button'
|
10
|
-
* }
|
11
|
-
* export const story = () => <Button label="The Button" />;
|
12
|
-
* ```
|
13
|
-
*
|
14
|
-
* Becomes:
|
15
|
-
*
|
16
|
-
* ```
|
17
|
-
* import { Meta, Story } from '@storybook/addon-docs';
|
18
|
-
* input { Button } from './Button';
|
19
|
-
*
|
20
|
-
* <Meta title='Button' />
|
21
|
-
*
|
22
|
-
* <Story name='story'>
|
23
|
-
* <Button label="The Button" />
|
24
|
-
* </Story>
|
25
|
-
* ```
|
26
|
-
*/
|
27
|
-
declare function transformer(file: any, api: any): any;
|
28
|
-
|
29
|
-
export { transformer as default };
|
@@ -1,3 +0,0 @@
|
|
1
|
-
var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},__copyProps=(to,from,except,desc)=>{if(from&&typeof from=="object"||typeof from=="function")for(let key of __getOwnPropNames(from))!__hasOwnProp.call(to,key)&&key!==except&&__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:!0}),mod);var csf_to_mdx_exports={};__export(csf_to_mdx_exports,{default:()=>transformer});module.exports=__toCommonJS(csf_to_mdx_exports);var import_recast=require("recast"),import_csf=require("@storybook/csf");function exportMdx(root,options){return root.__paths[0].node.program.body.map(n=>{let{code}=(0,import_recast.prettyPrint)(n,options);return n.type==="JSXElement"?`${code}
|
2
|
-
`:code}).join(`
|
3
|
-
`)}function parseIncludeExclude(prop){let{code}=(0,import_recast.prettyPrint)(prop,{});return(0,eval)(code)}function transformer(file,api){let j=api.jscodeshift,root=j(file.source),storyKeyToStory={},meta={};function makeAttr(key,val){return j.jsxAttribute(j.jsxIdentifier(key),val.type==="Literal"?val:j.jsxExpressionContainer(val))}function getStoryContents(node){return node.type==="ArrowFunctionExpression"&&node.body.type==="JSXElement"?node.body:j.jsxExpressionContainer(node)}function getName(storyKey){let story=storyKeyToStory[storyKey];if(story){let name=story.properties.find(prop=>prop.key.name==="name");if(name&&name.value.type==="Literal")return name.value.value}return storyKey}function getStoryAttrs(storyKey){let attrs=[],story=storyKeyToStory[storyKey];return story&&story.properties.forEach(prop=>{let{key,value}=prop;key.name!=="name"&&attrs.push(makeAttr(key.name,value))}),attrs}let defaultExportWithTitle=root.find(j.ExportDefaultDeclaration).filter(def=>def.node.declaration.properties.map(p=>p.key.name).includes("title"));if(defaultExportWithTitle.size()===0)return root.toSource();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"))),root.find(j.ImportDeclaration).filter(decl=>decl.node.source.value==="react").remove(),defaultExportWithTitle.forEach(exp=>{exp.node.declaration.properties.forEach(p=>{["includeStories","excludeStories"].includes(p.key.name)&&(meta[p.key.name]=parseIncludeExclude(p.value))})});let namedExports=root.find(j.ExportNamedDeclaration);namedExports.forEach(exp=>{let storyKey=exp.node.declaration.declarations[0].id.name;(0,import_csf.isExportStory)(storyKey,meta)&&(storyKeyToStory[storyKey]=null)});let storyAssignments=root.find(j.AssignmentExpression).filter(exp=>{let{left}=exp.node;return left.type==="MemberExpression"&&left.object.type==="Identifier"&&left.object.name in storyKeyToStory&&left.property.type==="Identifier"&&left.property.name==="story"});return storyAssignments.forEach(exp=>{let{left,right}=exp.node;storyKeyToStory[left.object.name]=right}),storyAssignments.remove(),defaultExportWithTitle.replaceWith(exp=>{let jsxId=j.jsxIdentifier("Meta"),attrs=[];exp.node.declaration.properties.forEach(prop=>{let{key,value}=prop;["includeStories","excludeStories"].includes(key.name)||attrs.push(makeAttr(key.name,value))});let opening=j.jsxOpeningElement(jsxId,attrs);return opening.selfClosing=!0,j.jsxElement(opening)}),namedExports.replaceWith(exp=>{let storyKey=exp.node.declaration.declarations[0].id.name;if(!(0,import_csf.isExportStory)(storyKey,meta))return exp.node;let jsxId=j.jsxIdentifier("Story"),name=getName(storyKey),attributes=[makeAttr("name",j.literal(name)),...getStoryAttrs(storyKey)],opening=j.jsxOpeningElement(jsxId,attributes),closing=j.jsxClosingElement(jsxId),children=[getStoryContents(exp.node.declaration.declarations[0].init)];return j.jsxElement(opening,closing,children)}),exportMdx(root,{quote:"single",trailingComma:"true",tabWidth:2})}0&&(module.exports={});
|
@@ -1,3 +0,0 @@
|
|
1
|
-
import{prettyPrint}from"recast";import{isExportStory}from"@storybook/csf";function exportMdx(root,options){return root.__paths[0].node.program.body.map(n=>{let{code}=prettyPrint(n,options);return n.type==="JSXElement"?`${code}
|
2
|
-
`:code}).join(`
|
3
|
-
`)}function parseIncludeExclude(prop){let{code}=prettyPrint(prop,{});return(0,eval)(code)}function transformer(file,api){let j=api.jscodeshift,root=j(file.source),storyKeyToStory={},meta={};function makeAttr(key,val){return j.jsxAttribute(j.jsxIdentifier(key),val.type==="Literal"?val:j.jsxExpressionContainer(val))}function getStoryContents(node){return node.type==="ArrowFunctionExpression"&&node.body.type==="JSXElement"?node.body:j.jsxExpressionContainer(node)}function getName(storyKey){let story=storyKeyToStory[storyKey];if(story){let name=story.properties.find(prop=>prop.key.name==="name");if(name&&name.value.type==="Literal")return name.value.value}return storyKey}function getStoryAttrs(storyKey){let attrs=[],story=storyKeyToStory[storyKey];return story&&story.properties.forEach(prop=>{let{key,value}=prop;key.name!=="name"&&attrs.push(makeAttr(key.name,value))}),attrs}let defaultExportWithTitle=root.find(j.ExportDefaultDeclaration).filter(def=>def.node.declaration.properties.map(p=>p.key.name).includes("title"));if(defaultExportWithTitle.size()===0)return root.toSource();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"))),root.find(j.ImportDeclaration).filter(decl=>decl.node.source.value==="react").remove(),defaultExportWithTitle.forEach(exp=>{exp.node.declaration.properties.forEach(p=>{["includeStories","excludeStories"].includes(p.key.name)&&(meta[p.key.name]=parseIncludeExclude(p.value))})});let namedExports=root.find(j.ExportNamedDeclaration);namedExports.forEach(exp=>{let storyKey=exp.node.declaration.declarations[0].id.name;isExportStory(storyKey,meta)&&(storyKeyToStory[storyKey]=null)});let storyAssignments=root.find(j.AssignmentExpression).filter(exp=>{let{left}=exp.node;return left.type==="MemberExpression"&&left.object.type==="Identifier"&&left.object.name in storyKeyToStory&&left.property.type==="Identifier"&&left.property.name==="story"});return storyAssignments.forEach(exp=>{let{left,right}=exp.node;storyKeyToStory[left.object.name]=right}),storyAssignments.remove(),defaultExportWithTitle.replaceWith(exp=>{let jsxId=j.jsxIdentifier("Meta"),attrs=[];exp.node.declaration.properties.forEach(prop=>{let{key,value}=prop;["includeStories","excludeStories"].includes(key.name)||attrs.push(makeAttr(key.name,value))});let opening=j.jsxOpeningElement(jsxId,attrs);return opening.selfClosing=!0,j.jsxElement(opening)}),namedExports.replaceWith(exp=>{let storyKey=exp.node.declaration.declarations[0].id.name;if(!isExportStory(storyKey,meta))return exp.node;let jsxId=j.jsxIdentifier("Story"),name=getName(storyKey),attributes=[makeAttr("name",j.literal(name)),...getStoryAttrs(storyKey)],opening=j.jsxOpeningElement(jsxId,attributes),closing=j.jsxClosingElement(jsxId),children=[getStoryContents(exp.node.declaration.declarations[0].init)];return j.jsxElement(opening,closing,children)}),exportMdx(root,{quote:"single",trailingComma:"true",tabWidth:2})}export{transformer as default};
|
@@ -1 +0,0 @@
|
|
1
|
-
function transformer(file,api){let j=api.jscodeshift,createImportDeclaration=(specifiers,source)=>j.importDeclaration(specifiers.map(s=>j.importSpecifier(j.identifier(s))),j.literal(source)),deprecates={action:[["action"],"@storybook/addon-actions"],linkTo:[["linkTo"],"@storybook/addon-links"]};return j(file.source).find(j.ImportDeclaration).filter(i=>i.value.source.value==="@storybook/react").forEach(i=>{let importStatement=i.value;importStatement.specifiers=importStatement.specifiers.filter(specifier=>{let item=deprecates[specifier.local.name];if(item){let[specifiers,moduleName]=item;return i.insertAfter(createImportDeclaration(specifiers,moduleName)),!1}return specifier})}).toSource({quote:"single"})}export{transformer as default};
|
@@ -1 +0,0 @@
|
|
1
|
-
import{jscodeshiftToPrettierParser,sanitizeName}from"../chunk-CO6EPEMB.mjs";import prettier from"prettier";import{logger}from"@storybook/node-logger";import{storyNameFromExport}from"@storybook/csf";function transformer(file,api,options){let LITERAL=["ts","tsx"].includes(options.parser)?"StringLiteral":"Literal",j=api.jscodeshift,root=j(file.source);function extractDecorators(parameters){if(!parameters)return{};if(!parameters.properties)return{storyParams:parameters};let storyDecorators=parameters.properties.find(p=>p.key.name==="decorators");if(!storyDecorators)return{storyParams:parameters};storyDecorators=storyDecorators.value;let storyParams={...parameters};return storyParams.properties=storyParams.properties.filter(p=>p.key.name!=="decorators"),storyParams.properties.length===0?{storyDecorators}:{storyParams,storyDecorators}}function convertToModuleExports(path,originalExports2){let base=j(path),statements=[],extraExports=[],decorators=[];base.find(j.CallExpression).filter(call=>call.node.callee.property&&call.node.callee.property.name==="addDecorator").forEach(add=>{let decorator=add.node.arguments[0];decorators.push(decorator)}),decorators.length>0&&(decorators.reverse(),extraExports.push(j.property("init",j.identifier("decorators"),j.arrayExpression(decorators))));let parameters=[];base.find(j.CallExpression).filter(call=>call.node.callee.property&&call.node.callee.property.name==="addParameters").forEach(add=>{let params=[...add.node.arguments[0].properties];params.reverse(),params.forEach(prop=>parameters.push(prop))}),parameters.length>0&&(parameters.reverse(),extraExports.push(j.property("init",j.identifier("parameters"),j.objectExpression(parameters)))),originalExports2.length>0&&extraExports.push(j.property("init",j.identifier("excludeStories"),j.arrayExpression(originalExports2.map(exp=>j.literal(exp))))),base.find(j.CallExpression).filter(call=>call.node.callee.name==="storiesOf").filter(call=>call.node.arguments.length>0&&call.node.arguments[0].type===LITERAL).forEach(storiesOf=>{let title=storiesOf.node.arguments[0].value;statements.push(j.exportDefaultDeclaration(j.objectExpression([j.property("init",j.identifier("title"),j.literal(title)),...extraExports])))});let adds=[];base.find(j.CallExpression).filter(add=>add.node.callee.property&&add.node.callee.property.name==="add").filter(add=>add.node.arguments.length>=2&&add.node.arguments[0].type===LITERAL).forEach(add=>adds.push(add)),adds.reverse(),adds.push(path);let identifiers=new Set;root.find(j.Identifier).forEach(({value})=>identifiers.add(value.name)),adds.forEach(add=>{let name=add.node.arguments[0].value,key=sanitizeName(name);for(;identifiers.has(key);)key=`_${key}`;identifiers.add(key),storyNameFromExport(key)===name&&(name=null);let val=add.node.arguments[1];statements.push(j.exportDeclaration(!1,j.variableDeclaration("const",[j.variableDeclarator(j.identifier(key),val)])));let storyAnnotations=[];if(name&&storyAnnotations.push(j.property("init",j.identifier("name"),j.literal(name))),add.node.arguments.length>2){let originalStoryParams=add.node.arguments[2],{storyParams,storyDecorators}=extractDecorators(originalStoryParams);storyParams&&storyAnnotations.push(j.property("init",j.identifier("parameters"),storyParams)),storyDecorators&&storyAnnotations.push(j.property("init",j.identifier("decorators"),storyDecorators))}storyAnnotations.length>0&&statements.push(j.assignmentStatement("=",j.memberExpression(j.identifier(key),j.identifier("story")),j.objectExpression(storyAnnotations)))});let stmt=path.parent.node.type==="VariableDeclarator"?path.parent.parent:path.parent;statements.reverse(),statements.forEach(s=>stmt.insertAfter(s)),j(stmt).remove()}let initialStoriesOf=root.find(j.CallExpression).filter(call=>call.node.callee.name==="storiesOf");if(root.find(j.ExportDefaultDeclaration).size()>0)return initialStoriesOf.size()>0&&logger.warn(`Found ${initialStoriesOf.size()} 'storiesOf' calls but existing default export, SKIPPING: '${file.path}'`),root.toSource();let originalExports=[];root.find(j.ExportNamedDeclaration).forEach(exp=>{let{declaration,specifiers}=exp.node;if(declaration){let{id,declarations}=declaration;declarations?declarations.forEach(decl=>{let{name,properties}=decl.id;name?originalExports.push(name):properties&&properties.forEach(prop=>originalExports.push(prop.key.name))}):id&&originalExports.push(id.name)}else specifiers&&specifiers.forEach(spec=>originalExports.push(spec.exported.name))}),root.find(j.CallExpression).filter(add=>add.node.callee.property&&add.node.callee.property.name==="add").filter(add=>add.node.arguments.length>=2&&add.node.arguments[0].type===LITERAL).filter(add=>["ExpressionStatement","VariableDeclarator"].includes(add.parentPath.node.type)).forEach(path=>convertToModuleExports(path,originalExports)),root.find(j.ImportSpecifier).filter(spec=>spec.node.imported.name==="storiesOf"&&spec.parent.node.source.value.startsWith("@storybook/")).forEach(spec=>{let toRemove=spec.parent.node.specifiers.length>1?spec:spec.parent;j(toRemove).remove()});let source=root.toSource({trailingComma:!0,quote:"single",tabWidth:2});if(initialStoriesOf.size()>1)return logger.warn(`Found ${initialStoriesOf.size()} 'storiesOf' calls, PLEASE FIX BY HAND: '${file.path}'`),source;let prettierConfig=prettier.resolveConfig.sync(".",{editorconfig:!0})||{printWidth:100,tabWidth:2,bracketSpacing:!0,trailingComma:"es5",singleQuote:!0};return prettier.format(source,{...prettierConfig,parser:jscodeshiftToPrettierParser(options.parser)})}export{transformer as default};
|
@@ -1 +0,0 @@
|
|
1
|
-
import{transformer}from"../chunk-B5FMQ3BX.mjs";export{transformer as default};
|
@@ -1 +0,0 @@
|
|
1
|
-
import{packageNames,transformer}from"../chunk-3OPQTROG.mjs";export{transformer as default,packageNames};
|
@@ -1 +0,0 @@
|
|
1
|
-
function upgradeSeparator(path){return path.replace(/[|.]/g,"/")}function transformer(file,api,options){let j=api.jscodeshift,root=j(file.source);return root.find(j.CallExpression).filter(call=>call.node.callee.name==="storiesOf").filter(call=>call.node.arguments.length>0&&["Literal","StringLiteral"].includes(call.node.arguments[0].type)).forEach(call=>{let arg0=call.node.arguments[0];arg0.value=upgradeSeparator(arg0.value)}),root.find(j.ExportDefaultDeclaration).filter(def=>def.node.declaration.properties.map(p=>p.key.name).includes("title")).forEach(def=>{def.node.declaration&&def.node.declaration.properties&&def.node.declaration.properties.forEach(p=>{p.key.name==="title"&&(p.value.value=upgradeSeparator(p.value.value))})}),root.toSource({quote:"single"})}export{transformer as default};
|
@@ -1,20 +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
|
-
};
|
8
|
-
|
9
|
-
export const story1 = () => <Button label="Story 1" />;
|
10
|
-
|
11
|
-
export const story2 = () => <Button label="Story 2" onClick={action('click')} />;
|
12
|
-
story2.story = { name: 'second story' };
|
13
|
-
|
14
|
-
export const story3 = () => (
|
15
|
-
<div>
|
16
|
-
<Button label="The Button" onClick={action('onClick')} />
|
17
|
-
<br />
|
18
|
-
</div>
|
19
|
-
);
|
20
|
-
story3.story = { name: 'complex story' };
|
@@ -1,18 +0,0 @@
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
-
|
3
|
-
exports[`csf-to-mdx transforms correctly using "basic.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
|
-
<Story name='story1'><Button label='Story 1' /></Story>
|
11
|
-
|
12
|
-
<Story name='second story'><Button label='Story 2' onClick={action('click')} /></Story>
|
13
|
-
|
14
|
-
<Story name='complex story'><div>
|
15
|
-
<Button label='The Button' onClick={action('onClick')} />
|
16
|
-
<br />
|
17
|
-
</div></Story>"
|
18
|
-
`;
|