Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI: Fix variable collisions in storiesof-to-csf #8106

Merged
merged 4 commits into from
Sep 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/cli/story.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export default {
title: 'Story',
};

export const startCase = () => 'foo';
export const camelCase = () => 'foo';

camelCase.story = {
name: 'camelCase',
};
1 change: 1 addition & 0 deletions lib/codemod/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"dependencies": {
"@mdx-js/mdx": "^1.0.0",
"@storybook/node-logger": "5.3.0-alpha.0",
"@storybook/router": "5.3.0-alpha.0",
"core-js": "^3.0.1",
"cross-spawn": "^6.0.5",
"globby": "^10.0.1",
Expand Down
4 changes: 4 additions & 0 deletions lib/codemod/src/lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,9 @@ export const sanitizeName = name => {
if (isReserved(key)) {
key = `${key}Story`;
}
// prepend _ if name starts with a digit
if (/^\d/.test(key)) {
key = `_${key}`;
}
return key;
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ storiesOf('Button', module)
<br />
</div>
))
.add('w/punctuation', () => <Button label="Story 2" onClick={action('click')} />);
.add('w/punctuation', () => <Button label="Story 2" onClick={action('click')} />)
.add('Start Case', () => <Button label="Story 2" onClick={action('click')} />);
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ export default {
};

export const story1 = () => <Button label="Story 1" />;

story1.story = {
name: 'story1',
};

export const secondStory = () => <Button label="Story 2" onClick={action('click')} />;

secondStory.story = {
Expand All @@ -32,3 +37,5 @@ export const wPunctuation = () => <Button label="Story 2" onClick={action('click
wPunctuation.story = {
name: 'w/punctuation',
};

export const startCase = () => <Button label="Story 2" onClick={action('click')} />;
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
export const foo = 1;
storiesOf('bar', module).add('foo', () => <button />);
const bar = 1;
const barStory = 1;
const baz = 1;
const bazStory1 = 1;

storiesOf('foo', module)
.add('foo', () => <button />)
.add('bar', () => <button />)
.add('bazStory', () => <button />)
.add('baz', () => <button />);
Original file line number Diff line number Diff line change
@@ -1,12 +1,34 @@
export const foo = 1;
const bar = 1;
const barStory = 1;
const baz = 1;
const bazStory1 = 1;

export default {
title: 'bar',
title: 'foo',
excludeStories: ['foo'],
};

export const story0 = () => <button />;
export const fooStory = () => <button />;

story0.story = {
fooStory.story = {
name: 'foo',
};

export const barStory1 = () => <button />;

barStory1.story = {
name: 'bar',
};

export const bazStory = () => <button />;

bazStory.story = {
name: 'bazStory',
};

export const bazStory2 = () => <button />;

bazStory2.story = {
name: 'baz',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
storiesOf('bar', module).add('1', () => <button />);
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default {
title: 'bar',
};

export const _1 = () => <button />;
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ export default {
};

export const baz = () => <button />;

baz.story = {
name: 'baz',
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,29 @@ export default {
};

export const story1 = () => <Button label="Button1.1" />;

story1.story = {
name: 'story1',
};

export const story2 = () => <Button label="Button1.2" />;

story2.story = {
name: 'story2',
};

export default {
title: 'Button2',
};

export const story1 = () => <Button label="Button2.1" />;
export const story2 = () => <Button label="Button2.2" />;
export const story1Story = () => <Button label="Button2.1" />;

story1Story.story = {
name: 'story1',
};

export const story2Story = () => <Button label="Button2.2" />;

story2Story.story = {
name: 'story2',
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ withStoryParameters.story = {
export const foo = () => <Button label="Foo" />;

foo.story = {
name: 'foo',

parameters: {
bar: 1,
},
Expand Down
27 changes: 10 additions & 17 deletions lib/codemod/src/transforms/__tests__/storiesof-to-csf.test.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
import fs from 'fs';
import path from 'path';

import { defineTest } from 'jscodeshift/dist/testUtils';

jest.mock('@storybook/node-logger');

const testNames = [
'basic',
'decorators',
'parameters',
'story-parameters',
'module',
'multi',
'default',
'exports',
'collision',
'const',
'story-decorators',
];

testNames.forEach(testName => {
defineTest(__dirname, `storiesof-to-csf`, null, `storiesof-to-csf/${testName}`);
});
fs.readdirSync(path.resolve(__dirname, '../__testfixtures__/storiesof-to-csf'))
.map(filename => filename.match(/^(.*)\.input\.js$/))
.filter(Boolean)
.map(match => match[1])
.forEach(testName => {
defineTest(__dirname, `storiesof-to-csf`, null, `storiesof-to-csf/${testName}`);
});
19 changes: 13 additions & 6 deletions lib/codemod/src/transforms/storiesof-to-csf.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import prettier from 'prettier';
import { logger } from '@storybook/node-logger';
import { storyNameFromExport } from '@storybook/router';
import { sanitizeName } from '../lib/utils';

/**
Expand Down Expand Up @@ -44,7 +45,7 @@ export default function transformer(file, api, options) {
return { storyParams, storyDecorators };
}

function convertToModuleExports(path, originalExports, counter) {
function convertToModuleExports(path, originalExports) {
const base = j(path);

const statements = [];
Expand Down Expand Up @@ -127,13 +128,19 @@ export default function transformer(file, api, options) {
adds.reverse();
adds.push(path);

const identifiers = new Set();
root.find(j.Identifier).forEach(({ value }) => identifiers.add(value.name));
adds.forEach(add => {
let name = add.node.arguments[0].value;
let key = sanitizeName(name);
if (originalExports.includes(key)) {
key = `story${counter}`;
const sanitized = sanitizeName(name);
let key = sanitized;
let counter = 0;
while (identifiers.has(key)) {
key = `${sanitized}Story${counter || ''}`;
counter += 1;
}
if (key === name) {
identifiers.add(key);
if (storyNameFromExport(key) === name) {
name = null;
}

Expand Down Expand Up @@ -209,7 +216,7 @@ export default function transformer(file, api, options) {
.filter(add => add.node.callee.property && add.node.callee.property.name === 'add')
.filter(add => add.node.arguments.length >= 2 && add.node.arguments[0].type === 'Literal')
.filter(add => add.parentPath.node.type === 'ExpressionStatement')
.forEach((path, i) => convertToModuleExports(path, originalExports, i));
.forEach(path => convertToModuleExports(path, originalExports));

// remove storiesOf import
root
Expand Down