From 977846b22496374a7af1f3a1169788db5e2bd787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Connor=20B=C3=A4r?= Date: Fri, 17 Jul 2020 17:32:53 +0200 Subject: [PATCH] feat(cli): add codemods for theme changes (#641) * feat(cli): add theme-grid-tera codemod feature/migration-theme * feat(cli): add theme-icon-sizes codemod feature/migration-theme * feat(cli): add theme-to-design-tokens codemod feature/migration-theme * docs(cli): remove in progress label feature/migration-theme feature/migration-theme * feat(cli): rename other theme name feature/migration-theme --- MIGRATION.md | 8 +- .../__testfixtures__/theme-grid-tera.input.js | 17 +++++ .../theme-grid-tera.output.js | 25 +++++++ .../theme-icon-sizes.input.js | 8 ++ .../theme-icon-sizes.output.js | 8 ++ .../theme-to-design-tokens-1.input.js | 11 +++ .../theme-to-design-tokens-1.output.js | 11 +++ .../theme-to-design-tokens-2.input.js | 15 ++++ .../theme-to-design-tokens-2.output.js | 16 ++++ src/cli/migrate/__tests__/transforms.spec.js | 14 ++++ src/cli/migrate/theme-grid-tera.ts | 58 +++++++++++++++ src/cli/migrate/theme-icon-sizes.ts | 31 ++++++++ src/cli/migrate/theme-to-design-tokens.ts | 73 +++++++++++++++++++ 13 files changed, 290 insertions(+), 5 deletions(-) create mode 100644 src/cli/migrate/__testfixtures__/theme-grid-tera.input.js create mode 100644 src/cli/migrate/__testfixtures__/theme-grid-tera.output.js create mode 100644 src/cli/migrate/__testfixtures__/theme-icon-sizes.input.js create mode 100644 src/cli/migrate/__testfixtures__/theme-icon-sizes.output.js create mode 100644 src/cli/migrate/__testfixtures__/theme-to-design-tokens-1.input.js create mode 100644 src/cli/migrate/__testfixtures__/theme-to-design-tokens-1.output.js create mode 100644 src/cli/migrate/__testfixtures__/theme-to-design-tokens-2.input.js create mode 100644 src/cli/migrate/__testfixtures__/theme-to-design-tokens-2.output.js create mode 100644 src/cli/migrate/theme-grid-tera.ts create mode 100644 src/cli/migrate/theme-icon-sizes.ts create mode 100644 src/cli/migrate/theme-to-design-tokens.ts diff --git a/MIGRATION.md b/MIGRATION.md index bbb0ba3e07..add87d30c4 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -145,8 +145,6 @@ The affected components are: Badge, Blockquote, Button, ButtonGroup, Card, CardF ### Theme changes -(_in writing_) - -- The themes have been moved to [@sumup/design-tokens](https://www.npmjs.com/package/@sumup/design-tokens). Import them from there instead (🤖 _TODO_) -- The `iconSizes.byte` theme value has been removed. Use `iconSizes.kilo` instead (🤖 _TODO_) -- The `grid.afterTera` theme value has been renamed to `grid.tera` (🤖 _TODO_) +- The themes have been moved to [@sumup/design-tokens](https://www.npmjs.com/package/@sumup/design-tokens). Import them from there instead (🤖 _theme-to-design-tokens_) +- The `iconSizes.byte` theme value has been removed. Use `iconSizes.kilo` instead (🤖 _theme-icon-sizes_) +- The `grid.afterTera` theme value has been renamed to `grid.tera` (🤖 _theme-grid-tera_) diff --git a/src/cli/migrate/__testfixtures__/theme-grid-tera.input.js b/src/cli/migrate/__testfixtures__/theme-grid-tera.input.js new file mode 100644 index 0000000000..a1d661ffe6 --- /dev/null +++ b/src/cli/migrate/__testfixtures__/theme-grid-tera.input.js @@ -0,0 +1,17 @@ +import React from 'react'; +import styled from '@emotion/styled'; +import { css } from '@emotion/core'; +import { Col } from '@sumup/circuit-ui'; + +function fakeGrid(theme) { + const gridStyles = theme.grid.afterTera; +} + +const App = ({ children }) => ( + + {children} + +); diff --git a/src/cli/migrate/__testfixtures__/theme-grid-tera.output.js b/src/cli/migrate/__testfixtures__/theme-grid-tera.output.js new file mode 100644 index 0000000000..b5391425e1 --- /dev/null +++ b/src/cli/migrate/__testfixtures__/theme-grid-tera.output.js @@ -0,0 +1,25 @@ +import React from 'react'; +import styled from '@emotion/styled'; +import { css } from '@emotion/core'; +import { Col } from '@sumup/circuit-ui'; + +function fakeGrid(theme) { + const gridStyles = theme.grid.tera; +} + +const App = ({ children }) => ( + + {children} + +); diff --git a/src/cli/migrate/__testfixtures__/theme-icon-sizes.input.js b/src/cli/migrate/__testfixtures__/theme-icon-sizes.input.js new file mode 100644 index 0000000000..f0669329d7 --- /dev/null +++ b/src/cli/migrate/__testfixtures__/theme-icon-sizes.input.js @@ -0,0 +1,8 @@ +import styled from '@emotion/styled'; +import { css } from '@emotion/core'; + +const iconStyles = ({ theme }) => css` + width: ${theme.iconSizes.byte}; +`; + +const Icon = styled.div(iconStyles); diff --git a/src/cli/migrate/__testfixtures__/theme-icon-sizes.output.js b/src/cli/migrate/__testfixtures__/theme-icon-sizes.output.js new file mode 100644 index 0000000000..4325e147d0 --- /dev/null +++ b/src/cli/migrate/__testfixtures__/theme-icon-sizes.output.js @@ -0,0 +1,8 @@ +import styled from '@emotion/styled'; +import { css } from '@emotion/core'; + +const iconStyles = ({ theme }) => css` + width: ${theme.iconSizes.kilo}; +`; + +const Icon = styled.div(iconStyles); diff --git a/src/cli/migrate/__testfixtures__/theme-to-design-tokens-1.input.js b/src/cli/migrate/__testfixtures__/theme-to-design-tokens-1.input.js new file mode 100644 index 0000000000..dff096e8d4 --- /dev/null +++ b/src/cli/migrate/__testfixtures__/theme-to-design-tokens-1.input.js @@ -0,0 +1,11 @@ +import React from 'react'; +import { ThemeProvider } from 'emotion-theming'; +import { theme } from '@sumup/circuit-ui'; + +const App = ({ children }) => ( + {children} +); + +const App2 = ({ children }) => ( + {children} +); diff --git a/src/cli/migrate/__testfixtures__/theme-to-design-tokens-1.output.js b/src/cli/migrate/__testfixtures__/theme-to-design-tokens-1.output.js new file mode 100644 index 0000000000..241ad7b9fc --- /dev/null +++ b/src/cli/migrate/__testfixtures__/theme-to-design-tokens-1.output.js @@ -0,0 +1,11 @@ +import React from 'react'; +import { ThemeProvider } from 'emotion-theming'; +import { light } from '@sumup/design-tokens'; + +const App = ({ children }) => ( + {children} +); + +const App2 = ({ children }) => ( + {children} +); diff --git a/src/cli/migrate/__testfixtures__/theme-to-design-tokens-2.input.js b/src/cli/migrate/__testfixtures__/theme-to-design-tokens-2.input.js new file mode 100644 index 0000000000..94bd8952bc --- /dev/null +++ b/src/cli/migrate/__testfixtures__/theme-to-design-tokens-2.input.js @@ -0,0 +1,15 @@ +import React from 'react'; +import { ThemeProvider } from 'emotion-theming'; +import { theme, Text } from '@sumup/circuit-ui'; + +const App = ({ children }) => ( + + {children} + +); + +const App2 = ({ children }) => ( + + {children} + +); diff --git a/src/cli/migrate/__testfixtures__/theme-to-design-tokens-2.output.js b/src/cli/migrate/__testfixtures__/theme-to-design-tokens-2.output.js new file mode 100644 index 0000000000..39d161b4f4 --- /dev/null +++ b/src/cli/migrate/__testfixtures__/theme-to-design-tokens-2.output.js @@ -0,0 +1,16 @@ +import React from 'react'; +import { ThemeProvider } from 'emotion-theming'; +import { Text } from '@sumup/circuit-ui'; +import { light } from '@sumup/design-tokens'; + +const App = ({ children }) => ( + + {children} + +); + +const App2 = ({ children }) => ( + + {children} + +); diff --git a/src/cli/migrate/__tests__/transforms.spec.js b/src/cli/migrate/__tests__/transforms.spec.js index fed9ca5174..1afea8c9b1 100644 --- a/src/cli/migrate/__tests__/transforms.spec.js +++ b/src/cli/migrate/__tests__/transforms.spec.js @@ -30,3 +30,17 @@ defineTest(__dirname, 'component-static-properties'); defineTest(__dirname, 'toggle-checked-prop'); defineTest(__dirname, 'badge-variant-enum'); defineTest(__dirname, 'inline-message-variant-enum'); +defineTest(__dirname, 'theme-grid-tera'); +defineTest( + __dirname, + 'theme-to-design-tokens', + null, + 'theme-to-design-tokens-1', +); +defineTest( + __dirname, + 'theme-to-design-tokens', + null, + 'theme-to-design-tokens-2', +); +defineTest(__dirname, 'theme-icon-sizes'); diff --git a/src/cli/migrate/theme-grid-tera.ts b/src/cli/migrate/theme-grid-tera.ts new file mode 100644 index 0000000000..b4de01f253 --- /dev/null +++ b/src/cli/migrate/theme-grid-tera.ts @@ -0,0 +1,58 @@ +/** + * Copyright 2020, SumUp Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Transform } from 'jscodeshift'; + +import { findProperty, findLocalNames } from './utils'; + +const transform: Transform = (file, api) => { + const j = api.jscodeshift; + const root = j(file.source); + + findProperty(j, root, 'theme.grid.afterTera').replaceWith( + j.identifier('theme.grid.tera'), + ); + + const components = findLocalNames(j, root, 'Col'); + const props = ['span', 'skip']; + + if (components) { + components.forEach((component) => { + props.forEach((prop) => { + root + .findJSXElements(component) + .find(j.JSXAttribute, { + name: { + type: 'JSXIdentifier', + name: prop, + }, + }) + .find(j.Property, { + key: { + type: 'Identifier', + name: 'afterTera', + }, + }) + .replaceWith((nodePath) => + j.objectProperty(j.identifier('tera'), nodePath.node.value), + ); + }); + }); + } + + return root.toSource({ trailingComma: true }); +}; + +export default transform; diff --git a/src/cli/migrate/theme-icon-sizes.ts b/src/cli/migrate/theme-icon-sizes.ts new file mode 100644 index 0000000000..aee6f44a1d --- /dev/null +++ b/src/cli/migrate/theme-icon-sizes.ts @@ -0,0 +1,31 @@ +/** + * Copyright 2020, SumUp Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Transform } from 'jscodeshift'; + +import { findProperty } from './utils'; + +const transform: Transform = (file, api) => { + const j = api.jscodeshift; + const root = j(file.source); + + findProperty(j, root, 'theme.iconSizes.byte').replaceWith( + j.identifier('theme.iconSizes.kilo'), + ); + + return root.toSource(); +}; + +export default transform; diff --git a/src/cli/migrate/theme-to-design-tokens.ts b/src/cli/migrate/theme-to-design-tokens.ts new file mode 100644 index 0000000000..d76b80185a --- /dev/null +++ b/src/cli/migrate/theme-to-design-tokens.ts @@ -0,0 +1,73 @@ +/** + * Copyright 2020, SumUp Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Transform } from 'jscodeshift'; + +import { findImportsByPath } from './utils'; + +const transform: Transform = (file, api) => { + const j = api.jscodeshift; + const root = j(file.source); + + const imports = findImportsByPath(j, root, '@sumup/circuit-ui'); + + const themeImport = imports.find((i) => i.name === 'theme'); + + if (!themeImport) { + return; + } + + ['circuit', 'standard'].forEach((themeName) => { + root + .find(j.MemberExpression, { + object: { + name: themeImport.local, + }, + property: { + name: themeName, + }, + }) + .replaceWith(j.identifier('light')); + }); + const circuitImport = root.find(j.ImportDeclaration, { + source: { + value: '@sumup/circuit-ui', + }, + }); + + const designTokensImport = j.importDeclaration( + [j.importSpecifier(j.identifier('light'))], + j.literal('@sumup/design-tokens'), + ); + + if (imports.length === 1) { + circuitImport.replaceWith(designTokensImport); + } else { + circuitImport.forEach((importNodePath) => { + j(importNodePath) + .find(j.ImportSpecifier) + .forEach((importSpecifierNodePath) => { + if (importSpecifierNodePath.node.imported.name === 'theme') { + j(importSpecifierNodePath).remove(); + } + }); + }); + circuitImport.insertAfter(designTokensImport); + } + + return root.toSource({ quote: 'single', reuseWhitespace: false }); +}; + +export default transform;