@storybook/codemod 7.0.0-rc.1 → 7.0.0-rc.3
Sign up to get free protection for your applications and to get access to all the features.
@@ -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
|
];
|