@storybook/codemod 7.0.0-rc.8 → 7.0.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.
@@ -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)&&param.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.
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],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)&&param.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 removeUnusedTemplates(csf){Object.entries(csf._templates).forEach(([template,templateExpression])=>{let references=[];if(babel2.traverse(csf._ast,{Identifier:path=>{path.node.name===template&&references.push(path)}}),references.length===1){let reference=references[0];reference.parentPath.isVariableDeclarator()&&reference.parentPath.node.init===templateExpression&&reference.parentPath.remove()}})}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&&t2.identifier(template);storyFn||(storyFn=init);let renderAnnotation=isReactGlobalRenderFn(csf,template?csf._templates[template]:storyFn)?[]:[t2.objectProperty(t2.identifier("render"),storyFn)];objectExports[key]=t2.exportNamedDeclaration(t2.variableDeclaration("const",[t2.variableDeclarator(importHelper.updateTypeTo(id,"StoryObj"),t2.objectExpression([...renderAnnotation,...annotations]))]))}}),csf._ast.program.body=csf._ast.program.body.reduce((acc,stmt)=>{let statement=stmt;if(isStoryAnnotation(statement,objectExports))return acc;let newExport=getNewExport(statement,objectExports);return newExport?(acc.push(newExport),acc):(acc.push(statement),acc)},[]),upgradeDeprecatedTypes(file),importHelper.removeDeprecatedStoryImport(),removeUnusedTemplates(csf);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-rc.8",
3
+ "version": "7.0.0",
4
4
  "description": "A collection of codemod scripts written with JSCodeshift",
5
5
  "keywords": [
6
6
  "storybook"
@@ -49,9 +49,9 @@
49
49
  "@babel/preset-env": "~7.20.2",
50
50
  "@babel/types": "~7.21.2",
51
51
  "@storybook/csf": "next",
52
- "@storybook/csf-tools": "7.0.0-rc.8",
53
- "@storybook/node-logger": "7.0.0-rc.8",
54
- "@storybook/types": "7.0.0-rc.8",
52
+ "@storybook/csf-tools": "7.0.0",
53
+ "@storybook/node-logger": "7.0.0",
54
+ "@storybook/types": "7.0.0",
55
55
  "cross-spawn": "^7.0.3",
56
56
  "globby": "^11.0.2",
57
57
  "jscodeshift": "^0.14.0",
@@ -97,5 +97,5 @@
97
97
  "cjs"
98
98
  ]
99
99
  },
100
- "gitHead": "42cc9d76db87614261e067f49b0123db30365233"
100
+ "gitHead": "4f2afa644d7f2833181fc03187f5597d442285a6"
101
101
  }
@@ -136,14 +136,60 @@ describe('csf-2-to-3', () => {
136
136
  `)
137
137
  ).toMatchInlineSnapshot(`
138
138
  export default { title: 'Cat' };
139
+ const Template = (args) => <Cat {...args} />;
139
140
 
140
141
  export const A = {
141
- render: (args) => <Cat {...args} />,
142
+ render: Template,
142
143
  args: { isPrimary: false },
143
144
  };
144
145
  `);
145
146
  });
146
147
 
148
+ it('should reuse the template when there are multiple Template.bind references but no component defined', () => {
149
+ expect(
150
+ jsTransform(dedent`
151
+ export default { title: 'Cat' };
152
+ const Template = (args) => <Cat {...args} />;
153
+
154
+ export const A = Template.bind({});
155
+ A.args = { isPrimary: false };
156
+
157
+ export const B = Template.bind({});
158
+ B.args = { isPrimary: true };
159
+
160
+
161
+ export const C = Template.bind({});
162
+ C.args = { bla: true };
163
+
164
+ export const D = Template.bind({});
165
+ D.args = { bla: false };
166
+ `)
167
+ ).toMatchInlineSnapshot(`
168
+ export default { title: 'Cat' };
169
+ const Template = (args) => <Cat {...args} />;
170
+
171
+ export const A = {
172
+ render: Template,
173
+ args: { isPrimary: false },
174
+ };
175
+
176
+ export const B = {
177
+ render: Template,
178
+ args: { isPrimary: true },
179
+ };
180
+
181
+ export const C = {
182
+ render: Template,
183
+ args: { bla: true },
184
+ };
185
+
186
+ export const D = {
187
+ render: Template,
188
+ args: { bla: false },
189
+ };
190
+ `);
191
+ });
192
+
147
193
  it('should remove implicit global render for template.bind', () => {
148
194
  expect(
149
195
  jsTransform(dedent`
@@ -166,8 +212,10 @@ describe('csf-2-to-3', () => {
166
212
  args: { isPrimary: false },
167
213
  };
168
214
 
215
+ const Template2 = (args) => <Banana {...args} />;
216
+
169
217
  export const B = {
170
- render: (args) => <Banana {...args} />,
218
+ render: Template2,
171
219
  args: { isPrimary: true },
172
220
  };
173
221
  `);
@@ -359,5 +407,33 @@ describe('csf-2-to-3', () => {
359
407
  };
360
408
  `);
361
409
  });
410
+
411
+ it('migrate Story type to StoryFn when used in an not exported Template function', () => {
412
+ expect(
413
+ tsTransform(dedent`
414
+ import { Story, Meta } from '@storybook/react'
415
+
416
+ export default {
417
+ component: Cat,
418
+ } satisfies Meta
419
+
420
+ const Template: Story = () => <div>Hello World</div>;
421
+
422
+ export const Default = Template.bind({})
423
+ `)
424
+ ).toMatchInlineSnapshot(`
425
+ import { StoryFn, Meta } from '@storybook/react';
426
+
427
+ export default {
428
+ component: Cat,
429
+ } satisfies Meta;
430
+
431
+ const Template: StoryFn = () => <div>Hello World</div>;
432
+
433
+ export const Default = {
434
+ render: Template,
435
+ };
436
+ `);
437
+ });
362
438
  });
363
439
  });
@@ -38,12 +38,6 @@ const isStoryAnnotation = (stmt: t.Statement, objectExports: Record<string, any>
38
38
  t.isIdentifier(stmt.expression.left.object) &&
39
39
  objectExports[stmt.expression.left.object.name];
40
40
 
41
- const isTemplateDeclaration = (stmt: t.Statement, templates: Record<string, any>) =>
42
- t.isVariableDeclaration(stmt) &&
43
- stmt.declarations.length === 1 &&
44
- t.isIdentifier(stmt.declarations[0].id) &&
45
- templates[stmt.declarations[0].id.name];
46
-
47
41
  const getNewExport = (stmt: t.Statement, objectExports: Record<string, any>) => {
48
42
  if (
49
43
  t.isExportNamedDeclaration(stmt) &&
@@ -94,6 +88,28 @@ const isReactGlobalRenderFn = (csf: CsfFile, storyFn: t.Expression) => {
94
88
  const isSimpleCSFStory = (init: t.Expression, annotations: t.ObjectProperty[]) =>
95
89
  annotations.length === 0 && t.isArrowFunctionExpression(init) && init.params.length === 0;
96
90
 
91
+ function removeUnusedTemplates(csf: CsfFile) {
92
+ Object.entries(csf._templates).forEach(([template, templateExpression]) => {
93
+ const references: NodePath[] = [];
94
+ babel.traverse(csf._ast, {
95
+ Identifier: (path) => {
96
+ if (path.node.name === template) references.push(path);
97
+ },
98
+ });
99
+ // if there is only one reference and this reference is the variable declaration initializing the template
100
+ // then we are sure the template is unused
101
+ if (references.length === 1) {
102
+ const reference = references[0];
103
+ if (
104
+ reference.parentPath.isVariableDeclarator() &&
105
+ reference.parentPath.node.init === templateExpression
106
+ ) {
107
+ reference.parentPath.remove();
108
+ }
109
+ }
110
+ });
111
+ }
112
+
97
113
  export default function transform(info: FileInfo, api: API, options: { parser?: string }) {
98
114
  const makeTitle = (userTitle?: string) => {
99
115
  return userTitle || 'FIXME';
@@ -137,15 +153,18 @@ export default function transform(info: FileInfo, api: API, options: { parser?:
137
153
  return;
138
154
  }
139
155
 
140
- // Remove the render function when we can hoist the template
141
- // const Template = (args) => <Cat {...args} />;
142
- // export const A = Template.bind({});
143
- let storyFn: t.Expression = template && (csf._templates[template] as any as t.Expression);
156
+ let storyFn: t.Expression = template && t.identifier(template);
144
157
  if (!storyFn) {
145
158
  storyFn = init;
146
159
  }
147
160
 
148
- const renderAnnotation = isReactGlobalRenderFn(csf, storyFn)
161
+ // Remove the render function when we can hoist the template
162
+ // const Template = (args) => <Cat {...args} />;
163
+ // export const A = Template.bind({});
164
+ const renderAnnotation = isReactGlobalRenderFn(
165
+ csf,
166
+ template ? csf._templates[template] : storyFn
167
+ )
149
168
  ? []
150
169
  : [t.objectProperty(t.identifier('render'), storyFn)];
151
170
 
@@ -160,15 +179,10 @@ export default function transform(info: FileInfo, api: API, options: { parser?:
160
179
  }
161
180
  });
162
181
 
163
- importHelper.removeDeprecatedStoryImport();
164
-
165
182
  csf._ast.program.body = csf._ast.program.body.reduce((acc, stmt) => {
166
183
  const statement = stmt as t.Statement;
167
184
  // remove story annotations & template declarations
168
- if (
169
- isStoryAnnotation(statement, objectExports) ||
170
- isTemplateDeclaration(statement, csf._templates)
171
- ) {
185
+ if (isStoryAnnotation(statement, objectExports)) {
172
186
  return acc;
173
187
  }
174
188
 
@@ -185,6 +199,8 @@ export default function transform(info: FileInfo, api: API, options: { parser?:
185
199
  }, []);
186
200
 
187
201
  upgradeDeprecatedTypes(file);
202
+ importHelper.removeDeprecatedStoryImport();
203
+ removeUnusedTemplates(csf);
188
204
 
189
205
  let output = recast.print(csf._ast, {}).code;
190
206