From 8469fc360435440972b0ff7d8e591bce96b6babe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kry=C5=A1p=C3=ADn?= Date: Tue, 9 Apr 2024 16:31:58 +0200 Subject: [PATCH] Feat(codemods): Add codemod to remove breakpoint props from Grid #DS-1068 --- .../grid-breakpoint-props.input.tsx | 13 ++++ .../grid-breakpoint-props.output.tsx | 20 ++++++ .../__tests__/grid-breakpoint-props.test.ts | 3 + .../v2/web-react/grid-breakpoint-props.ts | 69 +++++++++++++++++++ packages/web-react/DEPRECATIONS-v2.md | 10 ++- 5 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 packages/codemods/src/transforms/v2/web-react/__testfixtures__/grid-breakpoint-props.input.tsx create mode 100644 packages/codemods/src/transforms/v2/web-react/__testfixtures__/grid-breakpoint-props.output.tsx create mode 100644 packages/codemods/src/transforms/v2/web-react/__tests__/grid-breakpoint-props.test.ts create mode 100644 packages/codemods/src/transforms/v2/web-react/grid-breakpoint-props.ts diff --git a/packages/codemods/src/transforms/v2/web-react/__testfixtures__/grid-breakpoint-props.input.tsx b/packages/codemods/src/transforms/v2/web-react/__testfixtures__/grid-breakpoint-props.input.tsx new file mode 100644 index 0000000000..5f657293c5 --- /dev/null +++ b/packages/codemods/src/transforms/v2/web-react/__testfixtures__/grid-breakpoint-props.input.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +// @ts-ignore: No declaration -- The library is not installed; we don't need to install it for fixtures. +import { Grid } from '@lmc-eu/spirit-web-react'; + +export const MyComponent = () => ( + <> + + Grid + + Grid + Grid + +); diff --git a/packages/codemods/src/transforms/v2/web-react/__testfixtures__/grid-breakpoint-props.output.tsx b/packages/codemods/src/transforms/v2/web-react/__testfixtures__/grid-breakpoint-props.output.tsx new file mode 100644 index 0000000000..c0f0a4a971 --- /dev/null +++ b/packages/codemods/src/transforms/v2/web-react/__testfixtures__/grid-breakpoint-props.output.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +// @ts-ignore: No declaration -- The library is not installed; we don't need to install it for fixtures. +import { Grid } from '@lmc-eu/spirit-web-react'; + +export const MyComponent = () => ( + <> + + Grid + + Grid + Grid + +); diff --git a/packages/codemods/src/transforms/v2/web-react/__tests__/grid-breakpoint-props.test.ts b/packages/codemods/src/transforms/v2/web-react/__tests__/grid-breakpoint-props.test.ts new file mode 100644 index 0000000000..536737a35e --- /dev/null +++ b/packages/codemods/src/transforms/v2/web-react/__tests__/grid-breakpoint-props.test.ts @@ -0,0 +1,3 @@ +import { testTransform } from '../../../../../tests/testUtils'; + +testTransform(__dirname, 'grid-breakpoint-props'); diff --git a/packages/codemods/src/transforms/v2/web-react/grid-breakpoint-props.ts b/packages/codemods/src/transforms/v2/web-react/grid-breakpoint-props.ts new file mode 100644 index 0000000000..a7e3db49fc --- /dev/null +++ b/packages/codemods/src/transforms/v2/web-react/grid-breakpoint-props.ts @@ -0,0 +1,69 @@ +import { API, FileInfo, JSXExpressionContainer } from 'jscodeshift'; + +const transform = (fileInfo: FileInfo, api: API) => { + const j = api.jscodeshift; + const root = j(fileInfo.source); + + root + .find(j.JSXOpeningElement, { + name: { + type: 'JSXIdentifier', + name: 'Grid', + }, + }) + .forEach((path) => { + let colsValue: JSXExpressionContainer['expression'] | null = null; + let tabletValue: JSXExpressionContainer['expression'] | null = null; + let desktopValue: JSXExpressionContainer['expression'] | null = null; + + if (path.node && path.node.attributes) { + // Filtering attributes + path.node.attributes = path.node.attributes.filter((attr) => { + if (attr.type === 'JSXAttribute' && attr.value?.type === 'JSXExpressionContainer') { + const { + name, + value: { expression }, + } = attr; + if (name.name === 'cols') { + colsValue = expression; + + return true; // keep cols + } + if (name.name === 'tablet') { + tabletValue = expression; + } else if (name.name === 'desktop') { + desktopValue = expression; + } + + return name.name !== 'tablet' && name.name !== 'desktop'; // remove tablet and desktop + } + + return true; + }); + + if (tabletValue || desktopValue) { + const colsObjectProperties = []; + if (colsValue) colsObjectProperties.push(j.objectProperty(j.identifier('mobile'), colsValue)); + if (tabletValue) colsObjectProperties.push(j.objectProperty(j.identifier('tablet'), tabletValue)); + if (desktopValue) colsObjectProperties.push(j.objectProperty(j.identifier('desktop'), desktopValue)); + + // Ensure colsAttribute exists or create it + let colsAttribute = path.node.attributes.find( + (attr) => attr.type === 'JSXAttribute' && attr.name.name === 'cols', + ); + if (!colsAttribute) { + colsAttribute = j.jsxAttribute(j.jsxIdentifier('cols'), null); + path.node.attributes.push(colsAttribute); + } + + if (colsAttribute && colsAttribute.type === 'JSXAttribute') { + colsAttribute.value = j.jsxExpressionContainer(j.objectExpression(colsObjectProperties)); + } + } + } + }); + + return root.toSource({ quote: 'single' }); +}; + +export default transform; diff --git a/packages/web-react/DEPRECATIONS-v2.md b/packages/web-react/DEPRECATIONS-v2.md index b69fb2a532..efe7b76703 100644 --- a/packages/web-react/DEPRECATIONS-v2.md +++ b/packages/web-react/DEPRECATIONS-v2.md @@ -171,7 +171,15 @@ The `tablet` and `desktop` props will be removed in the next major version. #### Migration Guide -Replace `tablet` and `desktop` props with the `cols` object prop. +Use codemod to automatically update your codebase. + +```sh +npx @lmc-eu/spirit-codemods -p -t v2/web-react/grid-breakpoint-props +``` + +See [Codemods documentation][readme-codemods] for more details. + +Or manually replace `tablet` and `desktop` props with the `cols` object prop. - `` → `` - `` → ``