@storybook/codemod 7.0.0-beta.56 → 7.0.0-beta.58
Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
|
|
1
1
|
var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __getProtoOf=Object.getPrototypeOf,__hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},__copyProps=(to,from,except,desc)=>{if(from&&typeof from=="object"||typeof from=="function")for(let key of __getOwnPropNames(from))!__hasOwnProp.call(to,key)&&key!==except&&__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to};var __toESM=(mod,isNodeMode,target)=>(target=mod!=null?__create(__getProtoOf(mod)):{},__copyProps(isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:!0}):target,mod)),__toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:!0}),mod);var csf_2_to_3_exports={};__export(csf_2_to_3_exports,{default:()=>transform,parser:()=>parser});module.exports=__toCommonJS(csf_2_to_3_exports);var import_prettier2=__toESM(require("prettier")),t2=__toESM(require("@babel/types")),import_types=require("@babel/types"),import_csf_tools2=require("@storybook/csf-tools"),babel2=__toESM(require("@babel/core")),recast2=__toESM(require("recast"));var import_prettier=__toESM(require("prettier")),babel=__toESM(require("@babel/core")),import_csf_tools=require("@storybook/csf-tools"),recast=__toESM(require("recast")),t=__toESM(require("@babel/types"));var deprecatedTypes=["ComponentStory","ComponentStoryFn","ComponentStoryObj","ComponentMeta","Story"];function migrateType(oldType){return oldType==="Story"||oldType==="ComponentStory"?"StoryFn":oldType.replace("Component","")}function upgradeDeprecatedTypes(file){let importedNamespaces=new Set,typeReferencesToUpdate=new Set,existingImports=[];file.path.traverse({ImportDeclaration:path=>{existingImports.push(...path.get("specifiers").map(specifier=>({name:specifier.node.local.name,isAlias:!(specifier.isImportSpecifier()&&t.isIdentifier(specifier.node.imported)&&specifier.node.local.name===specifier.node.imported.name),path:specifier}))),path.node.source.value.startsWith("@storybook")&&path.get("specifiers").forEach(specifier=>{if(specifier.isImportNamespaceSpecifier()&&importedNamespaces.add(specifier.node.local.name),!specifier.isImportSpecifier())return;let imported=specifier.get("imported");if(imported.isIdentifier()&&deprecatedTypes.includes(imported.node.name)){imported.node.name===specifier.node.local.name&&typeReferencesToUpdate.add(specifier.node.local.name);let newType=migrateType(imported.node.name);if(!existingImports.some(it=>it.name===newType))imported.replaceWith(t.identifier(newType)),existingImports.push({name:newType,isAlias:!1,path:specifier});else{let existingImport=existingImports.find(it=>it.name===newType&&it.isAlias);if(existingImport)throw existingImport.path.buildCodeFrameError(`This codemod does not support local imports that are called the same as a storybook import.
|
2
|
-
Rename this local import and try again.`);specifier.remove()}}})}}),file.path.traverse({TSTypeReference:path=>{let typeName=path.get("typeName");if(typeName.isIdentifier())typeReferencesToUpdate.has(typeName.node.name)&&typeName.replaceWith(t.identifier(migrateType(typeName.node.name)));else if(typeName.isTSQualifiedName()){let namespace=typeName.get("left");if(namespace.isIdentifier()&&importedNamespaces.has(namespace.node.name)){let right=typeName.get("right");deprecatedTypes.includes(right.node.name)&&right.replaceWith(t.identifier(migrateType(right.node.name)))}}}})}var logger=console,renameAnnotation=annotation=>annotation==="storyName"?"name":annotation,getTemplateBindVariable=init=>t2.isCallExpression(init)&&t2.isMemberExpression(init.callee)&&t2.isIdentifier(init.callee.object)&&t2.isIdentifier(init.callee.property)&&init.callee.property.name==="bind"&&(init.arguments.length===0||init.arguments.length===1&&t2.isObjectExpression(init.arguments[0])&&init.arguments[0].properties.length===0)?init.callee.object.name:null,isStoryAnnotation=(stmt,objectExports)=>t2.isExpressionStatement(stmt)&&t2.isAssignmentExpression(stmt.expression)&&t2.isMemberExpression(stmt.expression.left)&&t2.isIdentifier(stmt.expression.left.object)&&objectExports[stmt.expression.left.object.name],isTemplateDeclaration=(stmt,templates)=>t2.isVariableDeclaration(stmt)&&stmt.declarations.length===1&&t2.isIdentifier(stmt.declarations[0].id)&&templates[stmt.declarations[0].id.name],getNewExport=(stmt,objectExports)=>{if(t2.isExportNamedDeclaration(stmt)&&t2.isVariableDeclaration(stmt.declaration)&&stmt.declaration.declarations.length===1){let decl=stmt.declaration.declarations[0];if(t2.isVariableDeclarator(decl)&&t2.isIdentifier(decl.id))return objectExports[decl.id.name]}return null},isReactGlobalRenderFn=(csf,storyFn)=>{var _a;if((_a=csf._meta)!=null&&_a.component&&t2.isArrowFunctionExpression(storyFn)&&storyFn.params.length===1&&t2.isJSXElement(storyFn.body)){let{openingElement}=storyFn.body;if(openingElement.selfClosing&&t2.isJSXIdentifier(openingElement.name)&&openingElement.attributes.length===1){let attr=openingElement.attributes[0],param=storyFn.params[0];if(t2.isJSXSpreadAttribute(attr)&&t2.isIdentifier(attr.argument)&&t2.isIdentifier(param)&¶m.name===attr.argument.name&&csf._meta.component===openingElement.name.name)return!0}}return!1},isSimpleCSFStory=(init,annotations)=>annotations.length===0&&t2.isArrowFunctionExpression(init)&&init.params.length===0;function transform(info,api,options){let makeTitle=userTitle=>userTitle||"FIXME",csf=(0,import_csf_tools2.loadCsf)(info.source,{makeTitle});try{csf.parse()}catch(err){return logger.log(`Error ${err}, skipping`),info.source}let file=new babel2.File({filename:info.path},{code:info.source,ast:csf._ast}),importHelper=new StorybookImportHelper(file,info),objectExports={};Object.entries(csf._storyExports).forEach(([key,decl])=>{let annotations=Object.entries(csf._storyAnnotations[key]).map(([annotation,val])=>t2.objectProperty(t2.identifier(renameAnnotation(annotation)),val));if(t2.isVariableDeclarator(decl)){let{init,id}=decl,template=getTemplateBindVariable(init);if(!t2.isArrowFunctionExpression(init)&&!template)return;if(isSimpleCSFStory(init,annotations)){objectExports[key]=t2.exportNamedDeclaration(t2.variableDeclaration("const",[t2.variableDeclarator(importHelper.updateTypeTo(id,"StoryFn"),init)]));return}let storyFn=template&&csf._templates[template];storyFn||(storyFn=init);let renderAnnotation=isReactGlobalRenderFn(csf,storyFn)?[]:[t2.objectProperty(t2.identifier("render"),storyFn)];objectExports[key]=t2.exportNamedDeclaration(t2.variableDeclaration("const",[t2.variableDeclarator(importHelper.updateTypeTo(id,"StoryObj"),t2.objectExpression([...renderAnnotation,...annotations]))]))}}),importHelper.removeDeprecatedStoryImport(),csf._ast.program.body=csf._ast.program.body.reduce((acc,stmt)=>{if(isStoryAnnotation(
|
2
|
+
Rename this local import and try again.`);specifier.remove()}}})}}),file.path.traverse({TSTypeReference:path=>{let typeName=path.get("typeName");if(typeName.isIdentifier())typeReferencesToUpdate.has(typeName.node.name)&&typeName.replaceWith(t.identifier(migrateType(typeName.node.name)));else if(typeName.isTSQualifiedName()){let namespace=typeName.get("left");if(namespace.isIdentifier()&&importedNamespaces.has(namespace.node.name)){let right=typeName.get("right");deprecatedTypes.includes(right.node.name)&&right.replaceWith(t.identifier(migrateType(right.node.name)))}}}})}var logger=console,renameAnnotation=annotation=>annotation==="storyName"?"name":annotation,getTemplateBindVariable=init=>t2.isCallExpression(init)&&t2.isMemberExpression(init.callee)&&t2.isIdentifier(init.callee.object)&&t2.isIdentifier(init.callee.property)&&init.callee.property.name==="bind"&&(init.arguments.length===0||init.arguments.length===1&&t2.isObjectExpression(init.arguments[0])&&init.arguments[0].properties.length===0)?init.callee.object.name:null,isStoryAnnotation=(stmt,objectExports)=>t2.isExpressionStatement(stmt)&&t2.isAssignmentExpression(stmt.expression)&&t2.isMemberExpression(stmt.expression.left)&&t2.isIdentifier(stmt.expression.left.object)&&objectExports[stmt.expression.left.object.name],isTemplateDeclaration=(stmt,templates)=>t2.isVariableDeclaration(stmt)&&stmt.declarations.length===1&&t2.isIdentifier(stmt.declarations[0].id)&&templates[stmt.declarations[0].id.name],getNewExport=(stmt,objectExports)=>{if(t2.isExportNamedDeclaration(stmt)&&t2.isVariableDeclaration(stmt.declaration)&&stmt.declaration.declarations.length===1){let decl=stmt.declaration.declarations[0];if(t2.isVariableDeclarator(decl)&&t2.isIdentifier(decl.id))return objectExports[decl.id.name]}return null},isReactGlobalRenderFn=(csf,storyFn)=>{var _a;if((_a=csf._meta)!=null&&_a.component&&t2.isArrowFunctionExpression(storyFn)&&storyFn.params.length===1&&t2.isJSXElement(storyFn.body)){let{openingElement}=storyFn.body;if(openingElement.selfClosing&&t2.isJSXIdentifier(openingElement.name)&&openingElement.attributes.length===1){let attr=openingElement.attributes[0],param=storyFn.params[0];if(t2.isJSXSpreadAttribute(attr)&&t2.isIdentifier(attr.argument)&&t2.isIdentifier(param)&¶m.name===attr.argument.name&&csf._meta.component===openingElement.name.name)return!0}}return!1},isSimpleCSFStory=(init,annotations)=>annotations.length===0&&t2.isArrowFunctionExpression(init)&&init.params.length===0;function transform(info,api,options){let makeTitle=userTitle=>userTitle||"FIXME",csf=(0,import_csf_tools2.loadCsf)(info.source,{makeTitle});try{csf.parse()}catch(err){return logger.log(`Error ${err}, skipping`),info.source}let file=new babel2.File({filename:info.path},{code:info.source,ast:csf._ast}),importHelper=new StorybookImportHelper(file,info),objectExports={};Object.entries(csf._storyExports).forEach(([key,decl])=>{let annotations=Object.entries(csf._storyAnnotations[key]).map(([annotation,val])=>t2.objectProperty(t2.identifier(renameAnnotation(annotation)),val));if(t2.isVariableDeclarator(decl)){let{init,id}=decl,template=getTemplateBindVariable(init);if(!t2.isArrowFunctionExpression(init)&&!template)return;if(isSimpleCSFStory(init,annotations)){objectExports[key]=t2.exportNamedDeclaration(t2.variableDeclaration("const",[t2.variableDeclarator(importHelper.updateTypeTo(id,"StoryFn"),init)]));return}let storyFn=template&&csf._templates[template];storyFn||(storyFn=init);let renderAnnotation=isReactGlobalRenderFn(csf,storyFn)?[]:[t2.objectProperty(t2.identifier("render"),storyFn)];objectExports[key]=t2.exportNamedDeclaration(t2.variableDeclaration("const",[t2.variableDeclarator(importHelper.updateTypeTo(id,"StoryObj"),t2.objectExpression([...renderAnnotation,...annotations]))]))}}),importHelper.removeDeprecatedStoryImport(),csf._ast.program.body=csf._ast.program.body.reduce((acc,stmt)=>{let statement=stmt;if(isStoryAnnotation(statement,objectExports)||isTemplateDeclaration(statement,csf._templates))return acc;let newExport=getNewExport(statement,objectExports);return newExport?(acc.push(newExport),acc):(acc.push(statement),acc)},[]),upgradeDeprecatedTypes(file);let output=recast2.print(csf._ast,{}).code;try{let prettierConfig=import_prettier2.default.resolveConfig.sync(".",{editorconfig:!0})||{printWidth:100,tabWidth:2,bracketSpacing:!0,trailingComma:"es5",singleQuote:!0};output=import_prettier2.default.format(output,{...prettierConfig,filepath:info.path})}catch{logger.log(`Failed applying prettier to ${info.path}.`)}return output}var StorybookImportHelper=class{constructor(file,info){this.getAllSbImportDeclarations=file=>{let found=[];return file.path.traverse({ImportDeclaration:path=>{let source=path.node.source.value;if(source.startsWith("@storybook/csf")||!source.startsWith("@storybook"))return;path.get("specifiers").some(specifier=>{if(specifier.isImportNamespaceSpecifier())throw new Error(`This codemod does not support namespace imports for a ${path.node.source.value} package.
|
3
3
|
Replace the namespace import with named imports and try again.`);if(!specifier.isImportSpecifier())return!1;let imported=specifier.get("imported");return imported.isIdentifier()?["Story","StoryFn","StoryObj","Meta","ComponentStory","ComponentStoryFn","ComponentStoryObj","ComponentMeta"].includes(imported.node.name):!1})&&found.push(path)}}),found};this.getOrAddImport=type=>{let sbImport=this.sbImportDeclarations.find(path=>path.node.importKind==="type")??this.sbImportDeclarations[0];if(sbImport==null)return;let specifiers=sbImport.get("specifiers"),importSpecifier2=specifiers.find(specifier=>{if(!specifier.isImportSpecifier())return!1;let imported=specifier.get("imported");return imported.isIdentifier()?imported.node.name===type:!1});return importSpecifier2?importSpecifier2.node.local.name:(specifiers[0].insertBefore(t2.importSpecifier(t2.identifier(type),t2.identifier(type))),type)};this.removeDeprecatedStoryImport=()=>{this.sbImportDeclarations.flatMap(it=>it.get("specifiers")).filter(specifier=>{if(!specifier.isImportSpecifier())return!1;let imported=specifier.get("imported");return imported.isIdentifier()?imported.node.name==="Story":!1}).forEach(path=>path.remove())};this.getAllLocalImports=()=>this.sbImportDeclarations.flatMap(it=>it.get("specifiers")).map(it=>it.node.local.name);this.updateTypeTo=(id,type)=>{if((0,import_types.isIdentifier)(id)&&(0,import_types.isTSTypeAnnotation)(id.typeAnnotation)&&(0,import_types.isTSTypeReference)(id.typeAnnotation.typeAnnotation)&&(0,import_types.isIdentifier)(id.typeAnnotation.typeAnnotation.typeName)){let{name}=id.typeAnnotation.typeAnnotation.typeName;if(this.getAllLocalImports().includes(name)){let localTypeImport=this.getOrAddImport(type);return{...id,typeAnnotation:t2.tsTypeAnnotation(t2.tsTypeReference(t2.identifier(localTypeImport),id.typeAnnotation.typeAnnotation.typeParameters))}}}return id};this.sbImportDeclarations=this.getAllSbImportDeclarations(file)}},parser="tsx";0&&(module.exports={parser});
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@storybook/codemod",
|
3
|
-
"version": "7.0.0-beta.
|
3
|
+
"version": "7.0.0-beta.58",
|
4
4
|
"description": "A collection of codemod scripts written with JSCodeshift",
|
5
5
|
"keywords": [
|
6
6
|
"storybook"
|
@@ -45,20 +45,19 @@
|
|
45
45
|
"prep": "../../../scripts/prepare/bundle.ts"
|
46
46
|
},
|
47
47
|
"dependencies": {
|
48
|
-
"@babel/core": "
|
49
|
-
"@babel/preset-env": "
|
50
|
-
"@babel/types": "
|
48
|
+
"@babel/core": "~7.21.0",
|
49
|
+
"@babel/preset-env": "~7.20.2",
|
50
|
+
"@babel/types": "~7.21.2",
|
51
51
|
"@storybook/csf": "next",
|
52
|
-
"@storybook/csf-tools": "7.0.0-beta.
|
53
|
-
"@storybook/node-logger": "7.0.0-beta.
|
54
|
-
"@storybook/types": "7.0.0-beta.
|
52
|
+
"@storybook/csf-tools": "7.0.0-beta.58",
|
53
|
+
"@storybook/node-logger": "7.0.0-beta.58",
|
54
|
+
"@storybook/types": "7.0.0-beta.58",
|
55
55
|
"cross-spawn": "^7.0.3",
|
56
56
|
"globby": "^11.0.2",
|
57
57
|
"jscodeshift": "^0.14.0",
|
58
58
|
"lodash": "^4.17.21",
|
59
59
|
"prettier": "^2.8.0",
|
60
|
-
"recast": "^0.23.1"
|
61
|
-
"util": "^0.12.4"
|
60
|
+
"recast": "^0.23.1"
|
62
61
|
},
|
63
62
|
"devDependencies": {
|
64
63
|
"@types/jscodeshift": "^0.11.6",
|
@@ -74,6 +73,7 @@
|
|
74
73
|
"unist-util-is": "^5.2.0",
|
75
74
|
"unist-util-select": "^4.0.3",
|
76
75
|
"unist-util-visit": "^4.1.2",
|
76
|
+
"util": "^0.12.4",
|
77
77
|
"vfile": "^5.3.7"
|
78
78
|
},
|
79
79
|
"publishConfig": {
|
@@ -97,5 +97,5 @@
|
|
97
97
|
"cjs"
|
98
98
|
]
|
99
99
|
},
|
100
|
-
"gitHead": "
|
100
|
+
"gitHead": "a447c4d622b3c1010459047df9c8b7022e76a10d"
|
101
101
|
}
|
@@ -235,11 +235,6 @@ describe('csf-2-to-3', () => {
|
|
235
235
|
).toThrowErrorMatchingInlineSnapshot(`
|
236
236
|
This codemod does not support namespace imports for a @storybook/react package.
|
237
237
|
Replace the namespace import with named imports and try again.
|
238
|
-
> 1 | import * as SB from '@storybook/react';
|
239
|
-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
240
|
-
2 | import { CatProps } from './Cat';
|
241
|
-
3 |
|
242
|
-
4 | const meta = { title: 'Cat', component: Cat } as Meta<CatProps>
|
243
238
|
`);
|
244
239
|
});
|
245
240
|
it('should keep local names', () => {
|
@@ -140,7 +140,7 @@ export default function transform(info: FileInfo, api: API, options: { parser?:
|
|
140
140
|
// Remove the render function when we can hoist the template
|
141
141
|
// const Template = (args) => <Cat {...args} />;
|
142
142
|
// export const A = Template.bind({});
|
143
|
-
let storyFn = template && csf._templates[template];
|
143
|
+
let storyFn: t.Expression = template && (csf._templates[template] as any as t.Expression);
|
144
144
|
if (!storyFn) {
|
145
145
|
storyFn = init;
|
146
146
|
}
|
@@ -163,20 +163,24 @@ export default function transform(info: FileInfo, api: API, options: { parser?:
|
|
163
163
|
importHelper.removeDeprecatedStoryImport();
|
164
164
|
|
165
165
|
csf._ast.program.body = csf._ast.program.body.reduce((acc, stmt) => {
|
166
|
+
const statement = stmt as t.Statement;
|
166
167
|
// remove story annotations & template declarations
|
167
|
-
if (
|
168
|
+
if (
|
169
|
+
isStoryAnnotation(statement, objectExports) ||
|
170
|
+
isTemplateDeclaration(statement, csf._templates)
|
171
|
+
) {
|
168
172
|
return acc;
|
169
173
|
}
|
170
174
|
|
171
175
|
// replace story exports with new object exports
|
172
|
-
const newExport = getNewExport(
|
176
|
+
const newExport = getNewExport(statement, objectExports);
|
173
177
|
if (newExport) {
|
174
178
|
acc.push(newExport);
|
175
179
|
return acc;
|
176
180
|
}
|
177
181
|
|
178
182
|
// include unknown statements
|
179
|
-
acc.push(
|
183
|
+
acc.push(statement);
|
180
184
|
return acc;
|
181
185
|
}, []);
|
182
186
|
|
@@ -221,7 +225,11 @@ class StorybookImportHelper {
|
|
221
225
|
if (source.startsWith('@storybook/csf') || !source.startsWith('@storybook')) return;
|
222
226
|
const isRendererImport = path.get('specifiers').some((specifier) => {
|
223
227
|
if (specifier.isImportNamespaceSpecifier()) {
|
224
|
-
throw path.buildCodeFrameError(
|
228
|
+
// throw path.buildCodeFrameError(
|
229
|
+
// `This codemod does not support namespace imports for a ${path.node.source.value} package.\n` +
|
230
|
+
// 'Replace the namespace import with named imports and try again.'
|
231
|
+
// );
|
232
|
+
throw new Error(
|
225
233
|
`This codemod does not support namespace imports for a ${path.node.source.value} package.\n` +
|
226
234
|
'Replace the namespace import with named imports and try again.'
|
227
235
|
);
|
@@ -179,7 +179,10 @@ export function transform(source: string, baseName: string): [mdx: string, csf:
|
|
179
179
|
return [t.objectProperty(t.identifier(attribute.name), t.stringLiteral(attribute.value))];
|
180
180
|
}
|
181
181
|
return [
|
182
|
-
t.objectProperty(
|
182
|
+
t.objectProperty(
|
183
|
+
t.identifier(attribute.name),
|
184
|
+
babelParseExpression(attribute.value.value) as any as t.Expression
|
185
|
+
),
|
183
186
|
];
|
184
187
|
}
|
185
188
|
return [];
|
@@ -216,7 +219,7 @@ export function transform(source: string, baseName: string): [mdx: string, csf:
|
|
216
219
|
return t.arrowFunctionExpression([], t.stringLiteral(child.value));
|
217
220
|
}
|
218
221
|
if (child.type === 'mdxFlowExpression' || child.type === 'mdxTextExpression') {
|
219
|
-
const expression = babelParseExpression(child.value);
|
222
|
+
const expression = babelParseExpression(child.value) as any as t.Expression;
|
220
223
|
|
221
224
|
// Recreating those lines: https://github.com/storybookjs/mdx1-csf/blob/f408fc97e9a63097ca1ee577df9315a3cccca975/src/sb-mdx-plugin.ts#L185-L198
|
222
225
|
const BIND_REGEX = /\.bind\(.*\)/;
|
@@ -234,7 +237,7 @@ export function transform(source: string, baseName: string): [mdx: string, csf:
|
|
234
237
|
|
235
238
|
const expression = babelParseExpression(
|
236
239
|
mdxProcessor.stringify({ type: 'root', children: [child] })
|
237
|
-
);
|
240
|
+
) as any as t.Expression;
|
238
241
|
return t.arrowFunctionExpression([], expression);
|
239
242
|
}
|
240
243
|
|
@@ -272,7 +275,7 @@ export function transform(source: string, baseName: string): [mdx: string, csf:
|
|
272
275
|
return [
|
273
276
|
t.objectProperty(
|
274
277
|
t.identifier(attribute.name),
|
275
|
-
babelParseExpression(attribute.value.value)
|
278
|
+
babelParseExpression(attribute.value.value) as any as t.Expression
|
276
279
|
),
|
277
280
|
];
|
278
281
|
}
|