@storybook/codemod 7.0.0-rc.1 → 7.0.0-rc.3
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.
@@ -49,7 +49,7 @@ Defaulting to 2020, but this will stop working in the future.`)),options.ecmaVer
|
|
49
49
|
`),map3)):attributesOnOneLine&&(value+=tracker.move(" "+attributesOnOneLine)),attributesOnTheirOwnLine&&(value+=tracker.move(`
|
50
50
|
`)),selfClosing&&(value+=tracker.move((tightSelfClosing||attributesOnTheirOwnLine?"":" ")+"/")),value+=tracker.move(">"),node3.children&&node3.children.length>0&&(node3.type==="mdxJsxFlowElement"?(tracker.shift(2),value+=tracker.move(`
|
51
51
|
`),value+=tracker.move(indentLines(containerFlow(node3,context,tracker.current()),map3)),value+=tracker.move(`
|
52
|
-
`)):value+=tracker.move(containerPhrasing(node3,context,{...tracker.current(),before:"<",after:">"}))),selfClosing||(value+=tracker.move("</"+(node3.name||"")+">")),exit2(),value}function map3(line,_,blank){return(blank?"":" ")+line}function peekElement(){return"<"}}var mdxjsEsmFromMarkdown={enter:{mdxjsEsm:enterMdxjsEsm},exit:{mdxjsEsm:exitMdxjsEsm,mdxjsEsmData:exitMdxjsEsmData}},mdxjsEsmToMarkdown={handlers:{mdxjsEsm:handleMdxjsEsm}};function enterMdxjsEsm(token){this.enter({type:"mdxjsEsm",value:""},token),this.buffer()}function exitMdxjsEsm(token){let value=this.resume(),node3=this.exit(token),estree=token.estree;node3.value=value,estree&&(node3.data={estree})}function exitMdxjsEsmData(token){this.config.enter.data.call(this,token),this.config.exit.data.call(this,token)}function handleMdxjsEsm(node3){return node3.value||""}function mdxFromMarkdown(){return[mdxExpressionFromMarkdown,mdxJsxFromMarkdown(),mdxjsEsmFromMarkdown]}function mdxToMarkdown(options){return{extensions:[mdxExpressionToMarkdown,mdxJsxToMarkdown(options),mdxjsEsmToMarkdown]}}function remarkMdx(options){let data2=this.data();add("micromarkExtensions",mdxjs(options)),add("fromMarkdownExtensions",mdxFromMarkdown()),add("toMarkdownExtensions",mdxToMarkdown(options));function add(field,value){(data2[field]?data2[field]:data2[field]=[]).push(value)}}var t=__toESM(require("@babel/types")),babel=__toESM(require("@babel/core")),recast=__toESM(require("recast")),path=__toESM(require("path")),import_prettier=__toESM(require("prettier")),fs=__toESM(require("fs")),import_camelCase=__toESM(require("lodash/camelCase")),mdxProcessor=remark().use(remarkMdx);function jscodeshift(info){let parsed=path.parse(info.path),baseName=path.join(parsed.dir,parsed.name.replace(".mdx","").replace(".stories","").replace(".story",""));for(;fs.existsSync(`${baseName}.stories.js`);)baseName+="_";let result=transform(info.source,path.basename(baseName))
|
52
|
+
`)):value+=tracker.move(containerPhrasing(node3,context,{...tracker.current(),before:"<",after:">"}))),selfClosing||(value+=tracker.move("</"+(node3.name||"")+">")),exit2(),value}function map3(line,_,blank){return(blank?"":" ")+line}function peekElement(){return"<"}}var mdxjsEsmFromMarkdown={enter:{mdxjsEsm:enterMdxjsEsm},exit:{mdxjsEsm:exitMdxjsEsm,mdxjsEsmData:exitMdxjsEsmData}},mdxjsEsmToMarkdown={handlers:{mdxjsEsm:handleMdxjsEsm}};function enterMdxjsEsm(token){this.enter({type:"mdxjsEsm",value:""},token),this.buffer()}function exitMdxjsEsm(token){let value=this.resume(),node3=this.exit(token),estree=token.estree;node3.value=value,estree&&(node3.data={estree})}function exitMdxjsEsmData(token){this.config.enter.data.call(this,token),this.config.exit.data.call(this,token)}function handleMdxjsEsm(node3){return node3.value||""}function mdxFromMarkdown(){return[mdxExpressionFromMarkdown,mdxJsxFromMarkdown(),mdxjsEsmFromMarkdown]}function mdxToMarkdown(options){return{extensions:[mdxExpressionToMarkdown,mdxJsxToMarkdown(options),mdxjsEsmToMarkdown]}}function remarkMdx(options){let data2=this.data();add("micromarkExtensions",mdxjs(options)),add("fromMarkdownExtensions",mdxFromMarkdown()),add("toMarkdownExtensions",mdxToMarkdown(options));function add(field,value){(data2[field]?data2[field]:data2[field]=[]).push(value)}}var t=__toESM(require("@babel/types")),babel=__toESM(require("@babel/core")),recast=__toESM(require("recast")),path=__toESM(require("path")),import_prettier=__toESM(require("prettier")),fs=__toESM(require("fs")),import_camelCase=__toESM(require("lodash/camelCase")),mdxProcessor=remark().use(remarkMdx);function jscodeshift(info){let parsed=path.parse(info.path),baseName=path.join(parsed.dir,parsed.name.replace(".mdx","").replace(".stories","").replace(".story",""));for(;fs.existsSync(`${baseName}.stories.js`);)baseName+="_";let result=transform(info.source,path.basename(baseName)),[mdx,csf]=result;return csf!=null&&fs.writeFileSync(`${baseName}.stories.js`,csf),mdx}function transform(source,baseName){let root2=mdxProcessor.parse(source),storyNamespaceName=nameToValidExport(`${baseName}Stories`),metaAttributes=[],storiesMap=new Map;visit(root2,["mdxjsEsm"],node3=>{node3.value=node3.value.replaceAll("@storybook/addon-docs/blocks","@storybook/blocks").replaceAll("@storybook/addon-docs","@storybook/blocks")});let file=getEsmAst(root2);visit(root2,["mdxJsxFlowElement","mdxJsxTextElement"],(node3,index4,parent)=>{if(is(node3,{name:"Meta"})&&(metaAttributes.push(...node3.attributes),node3.attributes=[{type:"mdxJsxAttribute",name:"of",value:{type:"mdxJsxAttributeValueExpression",value:storyNamespaceName}}]),is(node3,{name:"Story"})){let nameAttribute=node3.attributes.find(it=>it.type==="mdxJsxAttribute"&&it.name==="name"),idAttribute=node3.attributes.find(it=>it.type==="mdxJsxAttribute"&&it.name==="id"),storyAttribute=node3.attributes.find(it=>it.type==="mdxJsxAttribute"&&it.name==="story");if(typeof(nameAttribute==null?void 0:nameAttribute.value)=="string"){let name2=nameToValidExport(nameAttribute.value);for(;variableNameExists(name2);)name2+="_";storiesMap.set(name2,{type:"value",attributes:node3.attributes,children:node3.children}),node3.attributes=[{type:"mdxJsxAttribute",name:"of",value:{type:"mdxJsxAttributeValueExpression",value:`${storyNamespaceName}.${name2}`}}],node3.children=[]}else if(idAttribute!=null&&idAttribute.value){let newNode={type:"mdxFlowExpression",value:`/* ${mdxProcessor.stringify({type:"root",children:[node3]}).trim()} is deprecated, please migrate it to <Story of={referenceToStory} /> see: https://storybook.js.org/migration-guides/7.0 */`};return storiesMap.set(idAttribute.value,{type:"id"}),parent.children.splice(index4,0,newNode),[SKIP,index4+2]}else if((storyAttribute==null?void 0:storyAttribute.type)==="mdxJsxAttribute"&&typeof storyAttribute.value=="object"&&storyAttribute.value.type==="mdxJsxAttributeValueExpression"){let name2=storyAttribute.value.value;node3.attributes=[{type:"mdxJsxAttribute",name:"of",value:{type:"mdxJsxAttributeValueExpression",value:`${storyNamespaceName}.${name2}`}}],node3.children=[],storiesMap.set(name2,{type:"reference"})}else return parent.children.splice(index4,1),[SKIP,index4]}});let metaProperties=metaAttributes.flatMap(attribute=>attribute.type==="mdxJsxAttribute"?typeof attribute.value=="string"?[t.objectProperty(t.identifier(attribute.name),t.stringLiteral(attribute.value))]:[t.objectProperty(t.identifier(attribute.name),(0,import_csf_tools.babelParseExpression)(attribute.value.value))]:[]);if(file.path.traverse({ImportDeclaration(path2){path2.node.source.value==="@storybook/blocks"&&path2.remove()},ExportNamedDeclaration(path2){path2.replaceWith(path2.node.declaration)}}),storiesMap.size===0&&metaAttributes.length===0)return[mdxProcessor.stringify(root2),null];addStoriesImport(root2,baseName,storyNamespaceName);let newStatements=[t.exportDefaultDeclaration(t.objectExpression(metaProperties))];function mapChildrenToRender(children){let child=children[0];if(!child)return;if(child.type==="text")return t.arrowFunctionExpression([],t.stringLiteral(child.value));if(child.type==="mdxFlowExpression"||child.type==="mdxTextExpression"){let expression2=(0,import_csf_tools.babelParseExpression)(child.value);return/\.bind\(.*\)/.test(child.value)||t.isIdentifier(expression2)||t.isArrowFunctionExpression(expression2)?expression2:t.arrowFunctionExpression([],expression2)}let expression=(0,import_csf_tools.babelParseExpression)(mdxProcessor.stringify({type:"root",children:[child]}));return t.arrowFunctionExpression([],expression)}function variableNameExists(name2){let found=!1;return file.path.traverse({VariableDeclarator:path2=>{let lVal=path2.node.id;t.isIdentifier(lVal)&&lVal.name===name2&&(found=!0)}}),found}newStatements.push(...[...storiesMap].flatMap(([key,value])=>{if(value.type==="id")return[];if(value.type==="reference")return[t.exportNamedDeclaration(null,[t.exportSpecifier(t.identifier(key),t.identifier(key))])];let renderProperty=mapChildrenToRender(value.children),newObject=t.objectExpression([...renderProperty?[t.objectProperty(t.identifier("render"),mapChildrenToRender(value.children))]:[],...value.attributes.flatMap(attribute=>attribute.type==="mdxJsxAttribute"?typeof attribute.value=="string"?[t.objectProperty(t.identifier(attribute.name),t.stringLiteral(attribute.value))]:[t.objectProperty(t.identifier(attribute.name),(0,import_csf_tools.babelParseExpression)(attribute.value.value))]:[])]);return[t.exportNamedDeclaration(t.variableDeclaration("const",[t.variableDeclarator(t.identifier(key),newObject)]))]})),file.path.node.body=[...file.path.node.body,...newStatements];let newMdx=mdxProcessor.stringify(root2),output=recast.print(file.path.node).code,prettierConfig=import_prettier.default.resolveConfig.sync(".",{editorconfig:!0})||{printWidth:100,tabWidth:2,bracketSpacing:!0,trailingComma:"es5",singleQuote:!0};return output=import_prettier.default.format(output,{...prettierConfig,filepath:"file.jsx"}),[newMdx,output]}function getEsmAst(root2){let esm=[];visit(root2,["mdxjsEsm"],node3=>{esm.push(node3.value)});let esmSource=`${esm.join(`
|
53
53
|
|
54
54
|
`)}`;return new babel.File({filename:"info.path"},{code:esmSource,ast:(0,import_csf_tools.babelParse)(esmSource)})}function addStoriesImport(root2,baseName,storyNamespaceName){let found=!1;visit(root2,["mdxjsEsm"],node3=>{found||(node3.value+=`
|
55
55
|
import * as ${storyNamespaceName} from './${baseName}.stories';`,found=!0)})}function nameToValidExport(name2){let[first,...rest]=Array.from((0,import_camelCase.default)(name2));return`${first.match(/[a-zA-Z_$]/)?first.toUpperCase():`$${first}`}${rest.join("")}`}0&&(module.exports={nameToValidExport,transform});
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@storybook/codemod",
|
3
|
-
"version": "7.0.0-rc.
|
3
|
+
"version": "7.0.0-rc.3",
|
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.
|
53
|
-
"@storybook/node-logger": "7.0.0-rc.
|
54
|
-
"@storybook/types": "7.0.0-rc.
|
52
|
+
"@storybook/csf-tools": "7.0.0-rc.3",
|
53
|
+
"@storybook/node-logger": "7.0.0-rc.3",
|
54
|
+
"@storybook/types": "7.0.0-rc.3",
|
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": "
|
100
|
+
"gitHead": "94e99533b214c24691cc9edb3a026d04f20154b6"
|
101
101
|
}
|
@@ -15,22 +15,39 @@ beforeEach(() => {
|
|
15
15
|
fs.existsSync.mockImplementation(() => false);
|
16
16
|
});
|
17
17
|
|
18
|
+
test('update import even when no stories can be extracted', () => {
|
19
|
+
const input = dedent`
|
20
|
+
import { Heading } from '@storybook/addon-docs';
|
21
|
+
|
22
|
+
<Heading />
|
23
|
+
`;
|
24
|
+
|
25
|
+
const mdx = jscodeshift({ source: input, path: 'Foobar.stories.mdx' });
|
26
|
+
|
27
|
+
expect(mdx).toMatchInlineSnapshot(`
|
28
|
+
import { Heading } from '@storybook/blocks';
|
29
|
+
|
30
|
+
<Heading />
|
31
|
+
|
32
|
+
`);
|
33
|
+
});
|
34
|
+
|
18
35
|
test('drop invalid story nodes', () => {
|
19
36
|
const input = dedent`
|
20
|
-
import { Meta } from '@storybook/addon-docs';
|
37
|
+
import { Meta, Story } from '@storybook/addon-docs';
|
21
38
|
|
22
39
|
<Meta title="Foobar" />
|
23
40
|
|
24
41
|
<Story>No name!</Story>
|
25
42
|
|
26
|
-
<Story name="Primary">Story</Story>
|
27
|
-
|
43
|
+
<Story name="Primary">Story</Story>
|
28
44
|
`;
|
29
45
|
|
30
46
|
const mdx = jscodeshift({ source: input, path: 'Foobar.stories.mdx' });
|
31
47
|
|
32
48
|
expect(mdx).toMatchInlineSnapshot(`
|
33
|
-
import { Meta } from '@storybook/
|
49
|
+
import { Meta, Story } from '@storybook/blocks';
|
50
|
+
import * as FoobarStories from './Foobar.stories';
|
34
51
|
|
35
52
|
<Meta of={FoobarStories} />
|
36
53
|
|
@@ -96,7 +113,7 @@ test('Comment out story nodes with id', () => {
|
|
96
113
|
|
97
114
|
<Meta of={FoobarStories} />
|
98
115
|
|
99
|
-
{/* <Story id="button--primary" /> is deprecated, please migrate it to <Story of={referenceToStory} /> */}
|
116
|
+
{/* <Story id="button--primary" /> is deprecated, please migrate it to <Story of={referenceToStory} /> see: https://storybook.js.org/migration-guides/7.0 */}
|
100
117
|
|
101
118
|
<Story id="button--primary" />
|
102
119
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
/* eslint-disable no-param-reassign,@typescript-eslint/no-shadow
|
1
|
+
/* eslint-disable no-param-reassign,@typescript-eslint/no-shadow */
|
2
2
|
import type { FileInfo } from 'jscodeshift';
|
3
3
|
import { babelParse, babelParseExpression } from '@storybook/csf-tools';
|
4
4
|
import { remark } from 'remark';
|
@@ -40,14 +40,11 @@ export default function jscodeshift(info: FileInfo) {
|
|
40
40
|
|
41
41
|
const result = transform(info.source, path.basename(baseName));
|
42
42
|
|
43
|
-
if (result == null) {
|
44
|
-
// We can not make a valid migration.
|
45
|
-
return;
|
46
|
-
}
|
47
|
-
|
48
43
|
const [mdx, csf] = result;
|
49
44
|
|
50
|
-
|
45
|
+
if (csf != null) {
|
46
|
+
fs.writeFileSync(`${baseName}.stories.js`, csf);
|
47
|
+
}
|
51
48
|
|
52
49
|
return mdx;
|
53
50
|
}
|
@@ -80,7 +77,6 @@ export function transform(source: string, baseName: string): [mdx: string, csf:
|
|
80
77
|
});
|
81
78
|
|
82
79
|
const file = getEsmAst(root);
|
83
|
-
addStoriesImport(root, baseName, storyNamespaceName);
|
84
80
|
|
85
81
|
visit(
|
86
82
|
root,
|
@@ -135,7 +131,7 @@ export function transform(source: string, baseName: string): [mdx: string, csf:
|
|
135
131
|
const nodeString = mdxProcessor.stringify({ type: 'root', children: [node] }).trim();
|
136
132
|
const newNode: MdxFlowExpression = {
|
137
133
|
type: 'mdxFlowExpression',
|
138
|
-
value: `/* ${nodeString} is deprecated, please migrate it to <Story of={referenceToStory} /> */`,
|
134
|
+
value: `/* ${nodeString} is deprecated, please migrate it to <Story of={referenceToStory} /> see: https://storybook.js.org/migration-guides/7.0 */`,
|
139
135
|
};
|
140
136
|
storiesMap.set(idAttribute.value as string, { type: 'id' });
|
141
137
|
parent.children.splice(index, 0, newNode);
|
@@ -201,11 +197,13 @@ export function transform(source: string, baseName: string): [mdx: string, csf:
|
|
201
197
|
},
|
202
198
|
});
|
203
199
|
|
204
|
-
if (storiesMap.size === 0) {
|
200
|
+
if (storiesMap.size === 0 && metaAttributes.length === 0) {
|
205
201
|
// A CSF file must have at least one story, so skip migrating if this is the case.
|
206
|
-
return null;
|
202
|
+
return [mdxProcessor.stringify(root), null];
|
207
203
|
}
|
208
204
|
|
205
|
+
addStoriesImport(root, baseName, storyNamespaceName);
|
206
|
+
|
209
207
|
const newStatements: t.Statement[] = [
|
210
208
|
t.exportDefaultDeclaration(t.objectExpression(metaProperties)),
|
211
209
|
];
|