@storybook/codemod 6.5.6 → 7.0.0-alpha.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/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
|
-
}
|