Skip to content

Commit

Permalink
feat(cli): add codemods for theme changes (#641)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
connor-baer authored Jul 17, 2020
1 parent 183b33a commit 977846b
Show file tree
Hide file tree
Showing 13 changed files with 290 additions and 5 deletions.
8 changes: 3 additions & 5 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -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_)
17 changes: 17 additions & 0 deletions src/cli/migrate/__testfixtures__/theme-grid-tera.input.js
Original file line number Diff line number Diff line change
@@ -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 }) => (
<Col
span={{ default: 0, kilo: 3, afterTera: 6 }}
skip={{ default: 0, kilo: 3, afterTera: 6 }}
>
{children}
</Col>
);
25 changes: 25 additions & 0 deletions src/cli/migrate/__testfixtures__/theme-grid-tera.output.js
Original file line number Diff line number Diff line change
@@ -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 }) => (
<Col
span={{
default: 0,
kilo: 3,
tera: 6,
}}
skip={{
default: 0,
kilo: 3,
tera: 6,
}}
>
{children}
</Col>
);
8 changes: 8 additions & 0 deletions src/cli/migrate/__testfixtures__/theme-icon-sizes.input.js
Original file line number Diff line number Diff line change
@@ -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);
8 changes: 8 additions & 0 deletions src/cli/migrate/__testfixtures__/theme-icon-sizes.output.js
Original file line number Diff line number Diff line change
@@ -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);
11 changes: 11 additions & 0 deletions src/cli/migrate/__testfixtures__/theme-to-design-tokens-1.input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import { ThemeProvider } from 'emotion-theming';
import { theme } from '@sumup/circuit-ui';

const App = ({ children }) => (
<ThemeProvider theme={theme.circuit}>{children}</ThemeProvider>
);

const App2 = ({ children }) => (
<ThemeProvider theme={theme.standard}>{children}</ThemeProvider>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import { ThemeProvider } from 'emotion-theming';
import { light } from '@sumup/design-tokens';

const App = ({ children }) => (
<ThemeProvider theme={light}>{children}</ThemeProvider>
);

const App2 = ({ children }) => (
<ThemeProvider theme={light}>{children}</ThemeProvider>
);
15 changes: 15 additions & 0 deletions src/cli/migrate/__testfixtures__/theme-to-design-tokens-2.input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { ThemeProvider } from 'emotion-theming';
import { theme, Text } from '@sumup/circuit-ui';

const App = ({ children }) => (
<ThemeProvider theme={theme.circuit}>
<Text>{children}</Text>
</ThemeProvider>
);

const App2 = ({ children }) => (
<ThemeProvider theme={theme.standard}>
<Text>{children}</Text>
</ThemeProvider>
);
Original file line number Diff line number Diff line change
@@ -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 }) => (
<ThemeProvider theme={light}>
<Text>{children}</Text>
</ThemeProvider>
);

const App2 = ({ children }) => (
<ThemeProvider theme={light}>
<Text>{children}</Text>
</ThemeProvider>
);
14 changes: 14 additions & 0 deletions src/cli/migrate/__tests__/transforms.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
58 changes: 58 additions & 0 deletions src/cli/migrate/theme-grid-tera.ts
Original file line number Diff line number Diff line change
@@ -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;
31 changes: 31 additions & 0 deletions src/cli/migrate/theme-icon-sizes.ts
Original file line number Diff line number Diff line change
@@ -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;
73 changes: 73 additions & 0 deletions src/cli/migrate/theme-to-design-tokens.ts
Original file line number Diff line number Diff line change
@@ -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;

0 comments on commit 977846b

Please sign in to comment.