Skip to content

Commit

Permalink
feat: codemod to replace slug prop to decorator (#18535)
Browse files Browse the repository at this point in the history
  • Loading branch information
riddhybansal authored Feb 11, 2025
1 parent 6a145c0 commit 32f0e85
Show file tree
Hide file tree
Showing 7 changed files with 270 additions and 0 deletions.
47 changes: 47 additions & 0 deletions packages/upgrade/src/upgrades.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,53 @@ export const upgrades = [
});
},
},
{
name: 'slug-prop-to-decorator-prop',
description: `
Replace slug prop with decorator
Transforms:
<Component slug="value">
content
</Component>
Into:
<Component decorator="value">
content
</Component>
`,
migrate: async (options) => {
const transform = path.join(
TRANSFORM_DIR,
'slug-prop-to-decorator-prop.js'
);
const paths =
Array.isArray(options.paths) && options.paths.length > 0
? options.paths
: await glob(['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'], {
cwd: options.workspaceDir,
ignore: [
'**/es/**',
'**/lib/**',
'**/umd/**',
'**/node_modules/**',
'**/storybook-static/**',
'**/dist/**',
'**/build/**',
'**/*.d.ts',
'**/coverage/**',
],
});

await run({
dry: !options.write,
transform,
paths,
verbose: options.verbose,
parser: 'tsx',
});
},
},
{
name: 'refactor-light-to-layer',
description: `
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import { Dropdown, Checkbox, Tag } from '@carbon/react';

function TestComponent() {
return (
//prettier-ignore
<div>
{/* Basic Dropdown usage */}
<Dropdown
label="Select an option"
slug="dropdown-1"
items={['Option 1', 'Option 2']}
id="dropdown-1"
titleText="Dropdown"
/>
{/* Checkbox with expression */}
<Checkbox
labelText="Check me"
slug={'checkbox-1'}
id="checkbox-1"
/>
{/* Tag with string literal */}
<Tag slug={'static-tag'} type="red">
Important
</Tag>
{/* Nested structure */}
<div>
<Tag slug="tag-1" type="blue">
Active
</Tag>
<Checkbox
slug="checkbox-2"
labelText="Enable feature"
id="checkbox-2"
/>
</div>
</div>
);
}

export default TestComponent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import { Dropdown, Checkbox, Tag } from '@carbon/react';

const TestComponent: React.FC = () => {
return (
//prettier-ignore
<div>
{/* Basic Dropdown usage */}
<Dropdown
label="Select an option"
slug="dropdown-1"
items={['Option 1', 'Option 2']}
id="dropdown-1"
titleText="Dropdown"
/>
{/* Checkbox with expression */}
<Checkbox
labelText="Check me"
slug={'checkbox-1'}
id="checkbox-1"
/>
{/* Tag with string literal */}
<Tag slug={'static-tag'} type="red">
Important
</Tag>
{/* Nested structure */}
<div>
<Tag slug="tag-1" type="blue">
Active
</Tag>
<Checkbox
slug="checkbox-2"
labelText="Enable feature"
id="checkbox-2"
/>
</div>
</div>
);
};

export default TestComponent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import { Dropdown, Checkbox, Tag } from '@carbon/react';

function TestComponent() {
return (
//prettier-ignore
(<div>
{/* Basic Dropdown usage */}
<Dropdown
label="Select an option"
decorator="dropdown-1"
items={['Option 1', 'Option 2']}
id="dropdown-1"
titleText="Dropdown"
/>
{/* Checkbox with expression */}
<Checkbox
labelText="Check me"
decorator={'checkbox-1'}
id="checkbox-1"
/>
{/* Tag with string literal */}
<Tag decorator={'static-tag'} type="red">
Important
</Tag>
{/* Nested structure */}
<div>
<Tag decorator="tag-1" type="blue">
Active
</Tag>
<Checkbox
decorator="checkbox-2"
labelText="Enable feature"
id="checkbox-2"
/>
</div>
</div>)
);
}

export default TestComponent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import { Dropdown, Checkbox, Tag } from '@carbon/react';

const TestComponent: React.FC = () => {
return (
//prettier-ignore
(<div>
{/* Basic Dropdown usage */}
<Dropdown
label="Select an option"
decorator="dropdown-1"
items={['Option 1', 'Option 2']}
id="dropdown-1"
titleText="Dropdown"
/>
{/* Checkbox with expression */}
<Checkbox
labelText="Check me"
decorator={'checkbox-1'}
id="checkbox-1"
/>
{/* Tag with string literal */}
<Tag decorator={'static-tag'} type="red">
Important
</Tag>
{/* Nested structure */}
<div>
<Tag decorator="tag-1" type="blue">
Active
</Tag>
<Checkbox
decorator="checkbox-2"
labelText="Enable feature"
id="checkbox-2"
/>
</div>
</div>)
);
};

export default TestComponent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Copyright IBM Corp. 2025
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

const { defineTest } = require('jscodeshift/dist/testUtils');

defineTest(__dirname, 'slug-prop-to-decorator-prop');
47 changes: 47 additions & 0 deletions packages/upgrade/transforms/slug-prop-to-decorator-prop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Copyright IBM Corp. 2025
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*
* Replace slug prop with decorator
*/

'use strict';

const defaultOptions = {
quote: 'single',
trailingComma: true,
};

function transform(fileInfo, api, options) {
const j = api.jscodeshift;
const root = j(fileInfo.source);
const printOptions = options.printOptions || defaultOptions;

// Early return if no JSX elements with slug prop found
if (!root.find(j.JSXAttribute, { name: { name: 'slug' } }).size()) {
return null;
}

// Replace slug with decorator
root
.find(j.JSXAttribute, {
name: { name: 'slug' },
})
.forEach((path) => {
// Create new decorator attribute with same value as slug
const newAttribute = j.jsxAttribute(
j.jsxIdentifier('decorator'),
path.node.value
);

// Replace the slug attribute with decorator
j(path).replaceWith(newAttribute);
});

return root.toSource(printOptions);
}

module.exports = transform;
module.exports.parser = 'tsx';

0 comments on commit 32f0e85

Please sign in to comment.