@storybook/codemod 6.5.6 → 7.0.0-alpha.0
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/{ts3.9 → types}/lib/utils.d.ts +0 -0
- package/dist/{ts3.9 → types}/transforms/csf-2-to-3.d.ts +0 -0
- package/package.json +4 -5
- package/dist/modern/index.js +0 -99
- package/dist/modern/lib/utils.js +0 -25
- package/dist/modern/transforms/add-component-parameters.js +0 -57
- package/dist/modern/transforms/csf-2-to-3.js +0 -159
- package/dist/modern/transforms/csf-hoist-story-annotations.js +0 -86
- package/dist/modern/transforms/csf-to-mdx.js +0 -188
- package/dist/modern/transforms/mdx-to-csf.js +0 -139
- package/dist/modern/transforms/move-builtin-addons.js +0 -50
- package/dist/modern/transforms/storiesof-to-csf.js +0 -287
- package/dist/modern/transforms/update-addon-info.js +0 -94
- package/dist/modern/transforms/update-organisation-name.js +0 -74
- package/dist/modern/transforms/upgrade-hierarchy-separators.js +0 -35
- package/dist/ts3.4/lib/utils.d.ts +0 -2
- package/dist/ts3.4/transforms/csf-2-to-3.d.ts +0 -6
File without changes
|
File without changes
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@storybook/codemod",
|
3
|
-
"version": "
|
3
|
+
"version": "7.0.0-alpha.0",
|
4
4
|
"description": "A collection of codemod scripts written with JSCodeshift",
|
5
5
|
"keywords": [
|
6
6
|
"storybook"
|
@@ -44,8 +44,8 @@
|
|
44
44
|
"@babel/types": "^7.12.11",
|
45
45
|
"@mdx-js/mdx": "^1.6.22",
|
46
46
|
"@storybook/csf": "0.0.2--canary.4566f4d.1",
|
47
|
-
"@storybook/csf-tools": "
|
48
|
-
"@storybook/node-logger": "
|
47
|
+
"@storybook/csf-tools": "7.0.0-alpha.0",
|
48
|
+
"@storybook/node-logger": "7.0.0-alpha.0",
|
49
49
|
"core-js": "^3.8.2",
|
50
50
|
"cross-spawn": "^7.0.3",
|
51
51
|
"globby": "^11.0.2",
|
@@ -62,6 +62,5 @@
|
|
62
62
|
"publishConfig": {
|
63
63
|
"access": "public"
|
64
64
|
},
|
65
|
-
"gitHead": "
|
66
|
-
"sbmodern": "dist/modern/index.js"
|
65
|
+
"gitHead": "c82d897ea765da8cf4fbbcc2af1f28c808a93e23"
|
67
66
|
}
|
package/dist/modern/index.js
DELETED
@@ -1,99 +0,0 @@
|
|
1
|
-
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
2
|
-
|
3
|
-
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."); }
|
4
|
-
|
5
|
-
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); }
|
6
|
-
|
7
|
-
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; }
|
8
|
-
|
9
|
-
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_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; }
|
10
|
-
|
11
|
-
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
12
|
-
|
13
|
-
import "core-js/modules/es.promise.js";
|
14
|
-
import "core-js/modules/es.symbol.description.js";
|
15
|
-
|
16
|
-
/* eslint import/prefer-default-export: "off" */
|
17
|
-
import fs from 'fs';
|
18
|
-
import path from 'path';
|
19
|
-
import { promisify } from 'util';
|
20
|
-
import globby from 'globby';
|
21
|
-
import { sync as spawnSync } from 'cross-spawn';
|
22
|
-
import { jscodeshiftToPrettierParser } from './lib/utils';
|
23
|
-
export { default as updateOrganisationName, packageNames } from './transforms/update-organisation-name';
|
24
|
-
export { default as updateAddonInfo } from './transforms/update-addon-info';
|
25
|
-
var TRANSFORM_DIR = `${__dirname}/transforms`;
|
26
|
-
export function listCodemods() {
|
27
|
-
return fs.readdirSync(TRANSFORM_DIR).filter(function (fname) {
|
28
|
-
return fname.endsWith('.js');
|
29
|
-
}).map(function (fname) {
|
30
|
-
return fname.slice(0, -3);
|
31
|
-
});
|
32
|
-
}
|
33
|
-
var renameAsync = promisify(fs.rename);
|
34
|
-
|
35
|
-
async function renameFile(file, from, to, {
|
36
|
-
logger: logger
|
37
|
-
}) {
|
38
|
-
var newFile = file.replace(from, to);
|
39
|
-
logger.log(`Rename: ${file} ${newFile}`);
|
40
|
-
return renameAsync(file, newFile);
|
41
|
-
}
|
42
|
-
|
43
|
-
export async function runCodemod(codemod, {
|
44
|
-
glob: glob,
|
45
|
-
logger: logger,
|
46
|
-
dryRun: dryRun,
|
47
|
-
rename: rename,
|
48
|
-
parser: parser
|
49
|
-
}) {
|
50
|
-
var codemods = listCodemods();
|
51
|
-
|
52
|
-
if (!codemods.includes(codemod)) {
|
53
|
-
throw new Error(`Unknown codemod ${codemod}. Run --list for options.`);
|
54
|
-
}
|
55
|
-
|
56
|
-
var renameParts = null;
|
57
|
-
|
58
|
-
if (rename) {
|
59
|
-
renameParts = rename.split(':');
|
60
|
-
|
61
|
-
if (renameParts.length !== 2) {
|
62
|
-
throw new Error(`Codemod rename: expected format "from:to", got "${rename}"`);
|
63
|
-
}
|
64
|
-
} // jscodeshift/prettier know how to handle .ts/.tsx extensions,
|
65
|
-
// so if the user uses one of those globs, we can auto-infer
|
66
|
-
|
67
|
-
|
68
|
-
var inferredParser = parser;
|
69
|
-
|
70
|
-
if (!parser) {
|
71
|
-
var extension = path.extname(glob).slice(1);
|
72
|
-
var knownParser = jscodeshiftToPrettierParser(extension);
|
73
|
-
if (knownParser !== 'babel') inferredParser = extension;
|
74
|
-
}
|
75
|
-
|
76
|
-
var files = await globby([glob, '!**/node_modules', '!**/dist']);
|
77
|
-
logger.log(`=> Applying ${codemod}: ${files.length} files`);
|
78
|
-
|
79
|
-
if (!dryRun) {
|
80
|
-
var parserArgs = inferredParser ? ['--parser', inferredParser] : [];
|
81
|
-
spawnSync('npx', ['jscodeshift', '-t', `${TRANSFORM_DIR}/${codemod}.js`, ...parserArgs, ...files], {
|
82
|
-
stdio: 'inherit'
|
83
|
-
});
|
84
|
-
}
|
85
|
-
|
86
|
-
if (renameParts) {
|
87
|
-
var _renameParts = renameParts,
|
88
|
-
_renameParts2 = _slicedToArray(_renameParts, 2),
|
89
|
-
from = _renameParts2[0],
|
90
|
-
to = _renameParts2[1];
|
91
|
-
|
92
|
-
logger.log(`=> Renaming ${rename}: ${files.length} files`);
|
93
|
-
await Promise.all(files.map(function (file) {
|
94
|
-
return renameFile(file, new RegExp(`${from}$`), to, {
|
95
|
-
logger: logger
|
96
|
-
});
|
97
|
-
}));
|
98
|
-
}
|
99
|
-
}
|
package/dist/modern/lib/utils.js
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
import camelCase from 'lodash/camelCase';
|
2
|
-
import upperFirst from 'lodash/upperFirst';
|
3
|
-
export var sanitizeName = function (name) {
|
4
|
-
var key = upperFirst(camelCase(name)); // prepend _ if name starts with a digit
|
5
|
-
|
6
|
-
if (/^\d/.test(key)) {
|
7
|
-
key = `_${key}`;
|
8
|
-
} // prepend _ if name starts with a digit
|
9
|
-
|
10
|
-
|
11
|
-
if (/^\d/.test(key)) {
|
12
|
-
key = `_${key}`;
|
13
|
-
}
|
14
|
-
|
15
|
-
return key;
|
16
|
-
};
|
17
|
-
export function jscodeshiftToPrettierParser(parser) {
|
18
|
-
var parserMap = {
|
19
|
-
babylon: 'babel',
|
20
|
-
flow: 'flow',
|
21
|
-
ts: 'typescript',
|
22
|
-
tsx: 'typescript'
|
23
|
-
};
|
24
|
-
return parserMap[parser] || 'babel';
|
25
|
-
}
|
@@ -1,57 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Adds a `component` parameter for each storiesOf(...) call.
|
3
|
-
*
|
4
|
-
* For example:
|
5
|
-
*
|
6
|
-
* input { Button } from './Button';
|
7
|
-
* storiesOf('Button', module).add('story', () => <Button label="The Button" />);
|
8
|
-
*
|
9
|
-
* Becomes:
|
10
|
-
*
|
11
|
-
* input { Button } from './Button';
|
12
|
-
* storiesOf('Button', module)
|
13
|
-
* .addParameters({ component: Button })
|
14
|
-
* .add('story', () => <Button label="The Button" />);
|
15
|
-
*
|
16
|
-
* Heuristics:
|
17
|
-
* - The storiesOf "kind" name must be Button
|
18
|
-
* - Button must be imported in the file
|
19
|
-
*/
|
20
|
-
export default function transformer(file, api) {
|
21
|
-
var j = api.jscodeshift;
|
22
|
-
var root = j(file.source); // Create a dictionary whose keys are all the named imports in the file.
|
23
|
-
// For instance:
|
24
|
-
//
|
25
|
-
// import foo from 'foo';
|
26
|
-
// import { bar, baz } from 'zoo';
|
27
|
-
//
|
28
|
-
// => { foo: true, bar: true, baz: true }
|
29
|
-
|
30
|
-
var importMap = {};
|
31
|
-
root.find(j.ImportDeclaration).forEach(function (imp) {
|
32
|
-
return imp.node.specifiers.forEach(function (spec) {
|
33
|
-
importMap[spec.local.name] = true;
|
34
|
-
});
|
35
|
-
});
|
36
|
-
|
37
|
-
function getLeafName(string) {
|
38
|
-
var parts = string.split(/\/|\.|\|/);
|
39
|
-
return parts[parts.length - 1];
|
40
|
-
}
|
41
|
-
|
42
|
-
function addComponentParameter(call) {
|
43
|
-
var node = call.node;
|
44
|
-
var leafName = getLeafName(node.arguments[0].value);
|
45
|
-
return j.callExpression(j.memberExpression(node, j.identifier('addParameters')), [j.objectExpression([j.property('init', j.identifier('component'), j.identifier(leafName))])]);
|
46
|
-
}
|
47
|
-
|
48
|
-
var storiesOfCalls = root.find(j.CallExpression).filter(function (call) {
|
49
|
-
return call.node.callee.name === 'storiesOf';
|
50
|
-
}).filter(function (call) {
|
51
|
-
return call.node.arguments.length > 0 && call.node.arguments[0].type === 'Literal';
|
52
|
-
}).filter(function (call) {
|
53
|
-
var leafName = getLeafName(call.node.arguments[0].value);
|
54
|
-
return importMap[leafName];
|
55
|
-
}).replaceWith(addComponentParameter);
|
56
|
-
return root.toSource();
|
57
|
-
}
|
@@ -1,159 +0,0 @@
|
|
1
|
-
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); 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 = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : 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 makeTitle = function (userTitle) {
|
75
|
-
return userTitle || 'FIXME';
|
76
|
-
};
|
77
|
-
|
78
|
-
var csf = loadCsf(source, {
|
79
|
-
makeTitle: makeTitle
|
80
|
-
});
|
81
|
-
|
82
|
-
try {
|
83
|
-
csf.parse();
|
84
|
-
} catch (err) {
|
85
|
-
logger.log(`Error ${err}, skipping`);
|
86
|
-
return source;
|
87
|
-
}
|
88
|
-
|
89
|
-
var objectExports = {};
|
90
|
-
Object.entries(csf._storyExports).forEach(function ([key, decl]) {
|
91
|
-
var annotations = Object.entries(csf._storyAnnotations[key]).map(function ([annotation, val]) {
|
92
|
-
return t.objectProperty(t.identifier(_rename(annotation)), val);
|
93
|
-
});
|
94
|
-
|
95
|
-
if (t.isVariableDeclarator(decl)) {
|
96
|
-
var init = decl.init,
|
97
|
-
id = decl.id; // only replace arrow function expressions && template
|
98
|
-
// ignore no-arg stories without annotations
|
99
|
-
|
100
|
-
var template = getTemplateBindVariable(init);
|
101
|
-
|
102
|
-
if (!t.isArrowFunctionExpression(init) && !template || isSimpleCSFStory(init, annotations)) {
|
103
|
-
return;
|
104
|
-
} // Remove the render function when we can hoist the template
|
105
|
-
// const Template = (args) => <Cat {...args} />;
|
106
|
-
// export const A = Template.bind({});
|
107
|
-
|
108
|
-
|
109
|
-
var storyFn = template && csf._templates[template];
|
110
|
-
if (!storyFn) storyFn = init;
|
111
|
-
var keyId = t.identifier(key); // @ts-ignore
|
112
|
-
|
113
|
-
var typeAnnotation = id.typeAnnotation;
|
114
|
-
|
115
|
-
if (typeAnnotation) {
|
116
|
-
keyId.typeAnnotation = typeAnnotation;
|
117
|
-
}
|
118
|
-
|
119
|
-
var renderAnnotation = isReactGlobalRenderFn(csf, storyFn) ? [] : [t.objectProperty(t.identifier('render'), storyFn)];
|
120
|
-
objectExports[key] = t.exportNamedDeclaration(t.variableDeclaration('const', [t.variableDeclarator(keyId, t.objectExpression([...renderAnnotation, ...annotations]))]));
|
121
|
-
}
|
122
|
-
});
|
123
|
-
|
124
|
-
var updatedBody = csf._ast.program.body.reduce(function (acc, stmt) {
|
125
|
-
// remove story annotations & template declarations
|
126
|
-
if (isStoryAnnotation(stmt, objectExports) || isTemplateDeclaration(stmt, csf._templates)) {
|
127
|
-
return acc;
|
128
|
-
} // replace story exports with new object exports
|
129
|
-
|
130
|
-
|
131
|
-
var newExport = getNewExport(stmt, objectExports);
|
132
|
-
|
133
|
-
if (newExport) {
|
134
|
-
acc.push(newExport);
|
135
|
-
return acc;
|
136
|
-
} // include unknown statements
|
137
|
-
|
138
|
-
|
139
|
-
acc.push(stmt);
|
140
|
-
return acc;
|
141
|
-
}, []);
|
142
|
-
|
143
|
-
csf._ast.program.body = updatedBody;
|
144
|
-
var output = formatCsf(csf);
|
145
|
-
var prettierConfig = prettier.resolveConfig.sync('.', {
|
146
|
-
editorconfig: true
|
147
|
-
}) || {
|
148
|
-
printWidth: 100,
|
149
|
-
tabWidth: 2,
|
150
|
-
bracketSpacing: true,
|
151
|
-
trailingComma: 'es5',
|
152
|
-
singleQuote: true
|
153
|
-
};
|
154
|
-
return prettier.format(output, _objectSpread(_objectSpread({}, prettierConfig), {}, {
|
155
|
-
parser: jscodeshiftToPrettierParser(options === null || options === void 0 ? void 0 : options.parser)
|
156
|
-
}));
|
157
|
-
}
|
158
|
-
|
159
|
-
export default transform;
|
@@ -1,86 +0,0 @@
|
|
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
|
-
}
|
@@ -1,188 +0,0 @@
|
|
1
|
-
import { prettyPrint } from 'recast';
|
2
|
-
import { isExportStory } from '@storybook/csf';
|
3
|
-
|
4
|
-
function exportMdx(root, options) {
|
5
|
-
// eslint-disable-next-line no-underscore-dangle
|
6
|
-
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
|
-
}
|
@@ -1,139 +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
|
-
* 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
|
-
}
|
@@ -1,50 +0,0 @@
|
|
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) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_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
|
-
}
|
@@ -1,287 +0,0 @@
|
|
1
|
-
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); 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 = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : 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
|
-
import prettier from 'prettier';
|
8
|
-
import { logger } from '@storybook/node-logger';
|
9
|
-
import { storyNameFromExport } from '@storybook/csf';
|
10
|
-
import { sanitizeName, jscodeshiftToPrettierParser } from '../lib/utils';
|
11
|
-
/**
|
12
|
-
* Convert a legacy story API to component story format
|
13
|
-
*
|
14
|
-
* For example:
|
15
|
-
*
|
16
|
-
* ```
|
17
|
-
* input { Button } from './Button';
|
18
|
-
* storiesOf('Button', module).add('story', () => <Button label="The Button" />);
|
19
|
-
* ```
|
20
|
-
*
|
21
|
-
* Becomes:
|
22
|
-
*
|
23
|
-
* ```
|
24
|
-
* input { Button } from './Button';
|
25
|
-
* export default {
|
26
|
-
* title: 'Button'
|
27
|
-
* }
|
28
|
-
* export const story = () => <Button label="The Button" />;
|
29
|
-
*
|
30
|
-
* NOTES: only support chained storiesOf() calls
|
31
|
-
*/
|
32
|
-
|
33
|
-
export default function transformer(file, api, options) {
|
34
|
-
var LITERAL = ['ts', 'tsx'].includes(options.parser) ? 'StringLiteral' : 'Literal';
|
35
|
-
var j = api.jscodeshift;
|
36
|
-
var root = j(file.source);
|
37
|
-
|
38
|
-
function extractDecorators(parameters) {
|
39
|
-
if (!parameters) {
|
40
|
-
return {};
|
41
|
-
}
|
42
|
-
|
43
|
-
if (!parameters.properties) {
|
44
|
-
return {
|
45
|
-
storyParams: parameters
|
46
|
-
};
|
47
|
-
}
|
48
|
-
|
49
|
-
var storyDecorators = parameters.properties.find(function (p) {
|
50
|
-
return p.key.name === 'decorators';
|
51
|
-
});
|
52
|
-
|
53
|
-
if (!storyDecorators) {
|
54
|
-
return {
|
55
|
-
storyParams: parameters
|
56
|
-
};
|
57
|
-
}
|
58
|
-
|
59
|
-
storyDecorators = storyDecorators.value;
|
60
|
-
|
61
|
-
var storyParams = _objectSpread({}, parameters);
|
62
|
-
|
63
|
-
storyParams.properties = storyParams.properties.filter(function (p) {
|
64
|
-
return p.key.name !== 'decorators';
|
65
|
-
});
|
66
|
-
|
67
|
-
if (storyParams.properties.length === 0) {
|
68
|
-
return {
|
69
|
-
storyDecorators: storyDecorators
|
70
|
-
};
|
71
|
-
}
|
72
|
-
|
73
|
-
return {
|
74
|
-
storyParams: storyParams,
|
75
|
-
storyDecorators: storyDecorators
|
76
|
-
};
|
77
|
-
}
|
78
|
-
|
79
|
-
function convertToModuleExports(path, originalExports) {
|
80
|
-
var base = j(path);
|
81
|
-
var statements = [];
|
82
|
-
var extraExports = []; // .addDecorator
|
83
|
-
|
84
|
-
var decorators = [];
|
85
|
-
base.find(j.CallExpression).filter(function (call) {
|
86
|
-
return call.node.callee.property && call.node.callee.property.name === 'addDecorator';
|
87
|
-
}).forEach(function (add) {
|
88
|
-
var decorator = add.node.arguments[0];
|
89
|
-
decorators.push(decorator);
|
90
|
-
});
|
91
|
-
|
92
|
-
if (decorators.length > 0) {
|
93
|
-
decorators.reverse();
|
94
|
-
extraExports.push(j.property('init', j.identifier('decorators'), j.arrayExpression(decorators)));
|
95
|
-
} // .addParameters
|
96
|
-
|
97
|
-
|
98
|
-
var parameters = [];
|
99
|
-
base.find(j.CallExpression).filter(function (call) {
|
100
|
-
return call.node.callee.property && call.node.callee.property.name === 'addParameters';
|
101
|
-
}).forEach(function (add) {
|
102
|
-
// jscodeshift gives us the find results in reverse, but these args come in
|
103
|
-
// order, so we double reverse here. ugh.
|
104
|
-
var params = [...add.node.arguments[0].properties];
|
105
|
-
params.reverse();
|
106
|
-
params.forEach(function (prop) {
|
107
|
-
return parameters.push(prop);
|
108
|
-
});
|
109
|
-
});
|
110
|
-
|
111
|
-
if (parameters.length > 0) {
|
112
|
-
parameters.reverse();
|
113
|
-
extraExports.push(j.property('init', j.identifier('parameters'), j.objectExpression(parameters)));
|
114
|
-
}
|
115
|
-
|
116
|
-
if (originalExports.length > 0) {
|
117
|
-
extraExports.push(j.property('init', j.identifier('excludeStories'), j.arrayExpression(originalExports.map(function (exp) {
|
118
|
-
return j.literal(exp);
|
119
|
-
}))));
|
120
|
-
} // storiesOf(...)
|
121
|
-
|
122
|
-
|
123
|
-
base.find(j.CallExpression).filter(function (call) {
|
124
|
-
return call.node.callee.name === 'storiesOf';
|
125
|
-
}).filter(function (call) {
|
126
|
-
return call.node.arguments.length > 0 && call.node.arguments[0].type === LITERAL;
|
127
|
-
}).forEach(function (storiesOf) {
|
128
|
-
var title = storiesOf.node.arguments[0].value;
|
129
|
-
statements.push(j.exportDefaultDeclaration(j.objectExpression([j.property('init', j.identifier('title'), j.literal(title)), ...extraExports])));
|
130
|
-
}); // .add(...)
|
131
|
-
|
132
|
-
var adds = [];
|
133
|
-
base.find(j.CallExpression).filter(function (add) {
|
134
|
-
return add.node.callee.property && add.node.callee.property.name === 'add';
|
135
|
-
}).filter(function (add) {
|
136
|
-
return add.node.arguments.length >= 2 && add.node.arguments[0].type === LITERAL;
|
137
|
-
}).forEach(function (add) {
|
138
|
-
return adds.push(add);
|
139
|
-
});
|
140
|
-
adds.reverse();
|
141
|
-
adds.push(path);
|
142
|
-
var identifiers = new Set();
|
143
|
-
root.find(j.Identifier).forEach(function ({
|
144
|
-
value: value
|
145
|
-
}) {
|
146
|
-
return identifiers.add(value.name);
|
147
|
-
});
|
148
|
-
adds.forEach(function (add) {
|
149
|
-
var name = add.node.arguments[0].value;
|
150
|
-
var key = sanitizeName(name);
|
151
|
-
|
152
|
-
while (identifiers.has(key)) {
|
153
|
-
key = `_${key}`;
|
154
|
-
}
|
155
|
-
|
156
|
-
identifiers.add(key);
|
157
|
-
|
158
|
-
if (storyNameFromExport(key) === name) {
|
159
|
-
name = null;
|
160
|
-
}
|
161
|
-
|
162
|
-
var val = add.node.arguments[1];
|
163
|
-
statements.push(j.exportDeclaration(false, j.variableDeclaration('const', [j.variableDeclarator(j.identifier(key), val)])));
|
164
|
-
var storyAnnotations = [];
|
165
|
-
|
166
|
-
if (name) {
|
167
|
-
storyAnnotations.push(j.property('init', j.identifier('name'), j.literal(name)));
|
168
|
-
}
|
169
|
-
|
170
|
-
if (add.node.arguments.length > 2) {
|
171
|
-
var originalStoryParams = add.node.arguments[2];
|
172
|
-
|
173
|
-
var _extractDecorators = extractDecorators(originalStoryParams),
|
174
|
-
storyParams = _extractDecorators.storyParams,
|
175
|
-
storyDecorators = _extractDecorators.storyDecorators;
|
176
|
-
|
177
|
-
if (storyParams) {
|
178
|
-
storyAnnotations.push(j.property('init', j.identifier('parameters'), storyParams));
|
179
|
-
}
|
180
|
-
|
181
|
-
if (storyDecorators) {
|
182
|
-
storyAnnotations.push(j.property('init', j.identifier('decorators'), storyDecorators));
|
183
|
-
}
|
184
|
-
}
|
185
|
-
|
186
|
-
if (storyAnnotations.length > 0) {
|
187
|
-
statements.push(j.assignmentStatement('=', j.memberExpression(j.identifier(key), j.identifier('story')), j.objectExpression(storyAnnotations)));
|
188
|
-
}
|
189
|
-
});
|
190
|
-
var stmt = path.parent.node.type === 'VariableDeclarator' ? path.parent.parent : path.parent;
|
191
|
-
statements.reverse();
|
192
|
-
statements.forEach(function (s) {
|
193
|
-
return stmt.insertAfter(s);
|
194
|
-
});
|
195
|
-
j(stmt).remove();
|
196
|
-
} // Save the original storiesOf
|
197
|
-
|
198
|
-
|
199
|
-
var initialStoriesOf = root.find(j.CallExpression).filter(function (call) {
|
200
|
-
return call.node.callee.name === 'storiesOf';
|
201
|
-
});
|
202
|
-
var defaultExports = root.find(j.ExportDefaultDeclaration); // If there's already a default export
|
203
|
-
|
204
|
-
if (defaultExports.size() > 0) {
|
205
|
-
if (initialStoriesOf.size() > 0) {
|
206
|
-
logger.warn(`Found ${initialStoriesOf.size()} 'storiesOf' calls but existing default export, SKIPPING: '${file.path}'`);
|
207
|
-
}
|
208
|
-
|
209
|
-
return root.toSource();
|
210
|
-
} // Exclude all the original named exports
|
211
|
-
|
212
|
-
|
213
|
-
var originalExports = [];
|
214
|
-
root.find(j.ExportNamedDeclaration).forEach(function (exp) {
|
215
|
-
var _exp$node = exp.node,
|
216
|
-
declaration = _exp$node.declaration,
|
217
|
-
specifiers = _exp$node.specifiers;
|
218
|
-
|
219
|
-
if (declaration) {
|
220
|
-
var id = declaration.id,
|
221
|
-
declarations = declaration.declarations;
|
222
|
-
|
223
|
-
if (declarations) {
|
224
|
-
declarations.forEach(function (decl) {
|
225
|
-
var _decl$id = decl.id,
|
226
|
-
name = _decl$id.name,
|
227
|
-
properties = _decl$id.properties;
|
228
|
-
|
229
|
-
if (name) {
|
230
|
-
originalExports.push(name);
|
231
|
-
} else if (properties) {
|
232
|
-
properties.forEach(function (prop) {
|
233
|
-
return originalExports.push(prop.key.name);
|
234
|
-
});
|
235
|
-
}
|
236
|
-
});
|
237
|
-
} else if (id) {
|
238
|
-
originalExports.push(id.name);
|
239
|
-
}
|
240
|
-
} else if (specifiers) {
|
241
|
-
specifiers.forEach(function (spec) {
|
242
|
-
return originalExports.push(spec.exported.name);
|
243
|
-
});
|
244
|
-
}
|
245
|
-
}); // each top-level add expression corresponds to the last "add" of the chain.
|
246
|
-
// replace it with the entire export statements
|
247
|
-
|
248
|
-
root.find(j.CallExpression).filter(function (add) {
|
249
|
-
return add.node.callee.property && add.node.callee.property.name === 'add';
|
250
|
-
}).filter(function (add) {
|
251
|
-
return add.node.arguments.length >= 2 && add.node.arguments[0].type === LITERAL;
|
252
|
-
}).filter(function (add) {
|
253
|
-
return ['ExpressionStatement', 'VariableDeclarator'].includes(add.parentPath.node.type);
|
254
|
-
}).forEach(function (path) {
|
255
|
-
return convertToModuleExports(path, originalExports);
|
256
|
-
}); // remove storiesOf import
|
257
|
-
|
258
|
-
root.find(j.ImportSpecifier).filter(function (spec) {
|
259
|
-
return spec.node.imported.name === 'storiesOf' && spec.parent.node.source.value.startsWith('@storybook/');
|
260
|
-
}).forEach(function (spec) {
|
261
|
-
var toRemove = spec.parent.node.specifiers.length > 1 ? spec : spec.parent;
|
262
|
-
j(toRemove).remove();
|
263
|
-
});
|
264
|
-
var source = root.toSource({
|
265
|
-
trailingComma: true,
|
266
|
-
quote: 'single',
|
267
|
-
tabWidth: 2
|
268
|
-
});
|
269
|
-
|
270
|
-
if (initialStoriesOf.size() > 1) {
|
271
|
-
logger.warn(`Found ${initialStoriesOf.size()} 'storiesOf' calls, PLEASE FIX BY HAND: '${file.path}'`);
|
272
|
-
return source;
|
273
|
-
}
|
274
|
-
|
275
|
-
var prettierConfig = prettier.resolveConfig.sync('.', {
|
276
|
-
editorconfig: true
|
277
|
-
}) || {
|
278
|
-
printWidth: 100,
|
279
|
-
tabWidth: 2,
|
280
|
-
bracketSpacing: true,
|
281
|
-
trailingComma: 'es5',
|
282
|
-
singleQuote: true
|
283
|
-
};
|
284
|
-
return prettier.format(source, _objectSpread(_objectSpread({}, prettierConfig), {}, {
|
285
|
-
parser: jscodeshiftToPrettierParser(options.parser) || 'babel'
|
286
|
-
}));
|
287
|
-
}
|
@@ -1,94 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Takes the deprecated addon-info API, addWithInfo, and
|
3
|
-
* converts to the new withInfo API.
|
4
|
-
*
|
5
|
-
* Example of deprecated addWithInfo API:
|
6
|
-
*
|
7
|
-
* storiesOf('Button')
|
8
|
-
* .addWithInfo(
|
9
|
-
* 'story name',
|
10
|
-
* 'Story description.',
|
11
|
-
* () => (
|
12
|
-
* <Button label="The Button" />
|
13
|
-
* )
|
14
|
-
* )
|
15
|
-
*
|
16
|
-
* Converts to the new withInfo API:
|
17
|
-
*
|
18
|
-
* storiesOf('Button')
|
19
|
-
* .add('story name', withInfo(
|
20
|
-
* 'Story description.'
|
21
|
-
* )(() => (
|
22
|
-
* <Button label="The Button" />
|
23
|
-
* )))
|
24
|
-
*/
|
25
|
-
export default function transformer(file, api) {
|
26
|
-
var j = api.jscodeshift;
|
27
|
-
var root = j(file.source);
|
28
|
-
/**
|
29
|
-
* Returns a list of parameters for the withInfo function. The contents
|
30
|
-
* of this list is either the second argument from the original
|
31
|
-
* addWithInfo function, if no additional options were used, or a
|
32
|
-
* combined object of all the options from the original function.
|
33
|
-
* @param {list} args - original addWithInfo function parameters
|
34
|
-
* @return {list} the modified list of parameters for the new function
|
35
|
-
*/
|
36
|
-
|
37
|
-
var getOptions = function (args) {
|
38
|
-
if (args[3] === undefined) {
|
39
|
-
if (args[2] === undefined) {
|
40
|
-
// when the optional description string is not supplied for addWithInfo, use story name
|
41
|
-
return [args[0]];
|
42
|
-
}
|
43
|
-
|
44
|
-
return [args[1]];
|
45
|
-
}
|
46
|
-
|
47
|
-
return [j.objectExpression([j.property('init', j.identifier('text'), args[1]), ...args[3].properties])];
|
48
|
-
};
|
49
|
-
/**
|
50
|
-
* Constructs the new withInfo function from the parameters of the
|
51
|
-
* original addWithInfo function.
|
52
|
-
* @param {CallExpression} addWithInfoExpression - original function
|
53
|
-
* @returns {CallExpression} the new withInfo function
|
54
|
-
*/
|
55
|
-
|
56
|
-
|
57
|
-
var withInfo = function (addWithInfoExpression) {
|
58
|
-
var node = addWithInfoExpression.node;
|
59
|
-
var args = node.arguments; // if optional description string is not supplied, the story component becomes second arg
|
60
|
-
|
61
|
-
var storyComponent = args[2] ? args[2] : args[1];
|
62
|
-
node.callee.property.name = 'add';
|
63
|
-
node.arguments = [args[0], j.callExpression(j.callExpression(j.identifier('withInfo'), getOptions(args)), [storyComponent])];
|
64
|
-
return node;
|
65
|
-
};
|
66
|
-
/**
|
67
|
-
* Checks for - import { withInfo } from "@storybook/addon-info";
|
68
|
-
* Adds the import if necessary.
|
69
|
-
*/
|
70
|
-
|
71
|
-
|
72
|
-
var checkWithInfoImport = function () {
|
73
|
-
var importExists = root.find(j.ImportDeclaration).filter(function (imp) {
|
74
|
-
return imp.node.source.value === '@storybook/addon-info';
|
75
|
-
}).size();
|
76
|
-
if (importExists) return;
|
77
|
-
root.find(j.ImportDeclaration).at(-1).insertAfter(j.importDeclaration([j.importSpecifier(j.identifier('withInfo'))], j.literal('@storybook/addon-info')));
|
78
|
-
};
|
79
|
-
|
80
|
-
var addWithInfoExpressions = root.find(j.CallExpression, {
|
81
|
-
callee: {
|
82
|
-
property: {
|
83
|
-
name: 'addWithInfo'
|
84
|
-
}
|
85
|
-
}
|
86
|
-
});
|
87
|
-
|
88
|
-
if (addWithInfoExpressions.size()) {
|
89
|
-
checkWithInfoImport();
|
90
|
-
addWithInfoExpressions.replaceWith(withInfo);
|
91
|
-
}
|
92
|
-
|
93
|
-
return root.toSource();
|
94
|
-
}
|
@@ -1,74 +0,0 @@
|
|
1
|
-
export var packageNames = {
|
2
|
-
'@kadira/react-storybook-decorator-centered': '@storybook/addon-centered',
|
3
|
-
'@kadira/storybook-addons': '@storybook/addons',
|
4
|
-
'@kadira/storybook-addon-actions': '@storybook/addon-actions',
|
5
|
-
'@kadira/storybook-addon-comments': '@storybook/addon-comments',
|
6
|
-
'@kadira/storybook-addon-graphql': '@storybook/addon-graphql',
|
7
|
-
'@kadira/storybook-addon-info': '@storybook/addon-info',
|
8
|
-
'@kadira/storybook-addon-knobs': '@storybook/addon-knobs',
|
9
|
-
'@kadira/storybook-addon-links': '@storybook/addon-links',
|
10
|
-
'@kadira/storybook-addon-notes': '@storybook/addon-notes',
|
11
|
-
'@kadira/storybook-addon-options': '@storybook/addon-options',
|
12
|
-
'@kadira/storybook-channels': '@storybook/channels',
|
13
|
-
'@kadira/storybook-channel-postmsg': '@storybook/channel-postmessage',
|
14
|
-
'@kadira/storybook-channel-websocket': '@storybook/channel-websocket',
|
15
|
-
'@kadira/storybook-ui': '@storybook/ui',
|
16
|
-
'@kadira/react-native-storybook': '@storybook/react-native',
|
17
|
-
'@kadira/react-storybook': '@storybook/react',
|
18
|
-
'@kadira/getstorybook': '@storybook/cli',
|
19
|
-
'@kadira/storybook': '@storybook/react',
|
20
|
-
storyshots: '@storybook/addon-storyshots',
|
21
|
-
getstorybook: '@storybook/cli'
|
22
|
-
};
|
23
|
-
export default function transformer(file, api) {
|
24
|
-
var j = api.jscodeshift;
|
25
|
-
var packageNamesKeys = Object.keys(packageNames);
|
26
|
-
/**
|
27
|
-
* Checks whether the node value matches a Storybook package
|
28
|
-
* @param {string} the import declaration node
|
29
|
-
* @returns {string} whether the node value matches a Storybook package
|
30
|
-
*/
|
31
|
-
|
32
|
-
var getMatch = function (oldpart) {
|
33
|
-
return packageNamesKeys.find(function (newpart) {
|
34
|
-
return oldpart.match(newpart);
|
35
|
-
});
|
36
|
-
};
|
37
|
-
/**
|
38
|
-
* Returns the name of the Storybook packages with the organisation name,
|
39
|
-
* replacing the old `@kadira/` prefix.
|
40
|
-
* @param {string} oldPackageName the name of the old package
|
41
|
-
* @return {string} the new package name
|
42
|
-
* @example
|
43
|
-
* // returns '@storybook/storybook'
|
44
|
-
* getNewPackageName('@kadira/storybook')
|
45
|
-
*/
|
46
|
-
|
47
|
-
|
48
|
-
var getNewPackageName = function (oldPackageName) {
|
49
|
-
var match = getMatch(oldPackageName);
|
50
|
-
|
51
|
-
if (match) {
|
52
|
-
var replacement = packageNames[match];
|
53
|
-
return oldPackageName.replace(match, replacement);
|
54
|
-
}
|
55
|
-
|
56
|
-
return oldPackageName;
|
57
|
-
};
|
58
|
-
/**
|
59
|
-
* updatePackageName - updates the source name of the Storybook packages
|
60
|
-
* @param {ImportDeclaration} declaration the import declaration
|
61
|
-
* @returns {ImportDeclaration.Node} the import declaration node
|
62
|
-
*/
|
63
|
-
|
64
|
-
|
65
|
-
var updatePackageName = function (declaration) {
|
66
|
-
// eslint-disable-next-line no-param-reassign
|
67
|
-
declaration.node.source.value = getNewPackageName(declaration.node.source.value);
|
68
|
-
return declaration.node;
|
69
|
-
};
|
70
|
-
|
71
|
-
return j(file.source).find(j.ImportDeclaration).replaceWith(updatePackageName).toSource({
|
72
|
-
quote: 'single'
|
73
|
-
});
|
74
|
-
}
|
@@ -1,35 +0,0 @@
|
|
1
|
-
function upgradeSeparator(path) {
|
2
|
-
return path.replace(/[|.]/g, '/');
|
3
|
-
}
|
4
|
-
|
5
|
-
export default function transformer(file, api, options) {
|
6
|
-
var j = api.jscodeshift;
|
7
|
-
var root = j(file.source); // storiesOf(...)
|
8
|
-
|
9
|
-
root.find(j.CallExpression).filter(function (call) {
|
10
|
-
return call.node.callee.name === 'storiesOf';
|
11
|
-
}).filter(function (call) {
|
12
|
-
return call.node.arguments.length > 0 && ['Literal', 'StringLiteral'].includes(call.node.arguments[0].type);
|
13
|
-
}).forEach(function (call) {
|
14
|
-
var arg0 = call.node.arguments[0];
|
15
|
-
arg0.value = upgradeSeparator(arg0.value);
|
16
|
-
}); // export default { title: ... }
|
17
|
-
|
18
|
-
root.find(j.ExportDefaultDeclaration).filter(function (def) {
|
19
|
-
return def.node.declaration.properties.map(function (p) {
|
20
|
-
return p.key.name;
|
21
|
-
}).includes('title');
|
22
|
-
}).forEach(function (def) {
|
23
|
-
if (def.node.declaration && def.node.declaration.properties) {
|
24
|
-
def.node.declaration.properties.forEach(function (p) {
|
25
|
-
if (p.key.name === 'title') {
|
26
|
-
// eslint-disable-next-line no-param-reassign
|
27
|
-
p.value.value = upgradeSeparator(p.value.value);
|
28
|
-
}
|
29
|
-
});
|
30
|
-
}
|
31
|
-
});
|
32
|
-
return root.toSource({
|
33
|
-
quote: 'single'
|
34
|
-
});
|
35
|
-
}
|