From fea63f8059eb08ecdc6d1f4cd16cbac424fe25e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Malek?= Date: Tue, 19 Sep 2023 11:57:55 +0200 Subject: [PATCH 1/6] feat: add codemod for weak prop replacement in text --- .../weak-to-secondary/basic-usage.input.tsx | 7 +++ .../weak-to-secondary/basic-usage.output.tsx | 7 +++ .../weak-to-secondary/boolean-false.input.tsx | 7 +++ .../boolean-false.output.tsx | 3 + .../weak-to-secondary/boolean-true.input.tsx | 7 +++ .../weak-to-secondary/boolean-true.output.tsx | 7 +++ .../weak-to-secondary/local-rename.input.tsx | 7 +++ .../weak-to-secondary/local-rename.output.tsx | 7 +++ .../__tests__/weak-to-secondary-test.ts | 12 ++++ src/codemods/weak-to-secondary.ts | 61 +++++++++++++++++++ 10 files changed, 125 insertions(+) create mode 100644 src/codemods/__testfixtures__/weak-to-secondary/basic-usage.input.tsx create mode 100644 src/codemods/__testfixtures__/weak-to-secondary/basic-usage.output.tsx create mode 100644 src/codemods/__testfixtures__/weak-to-secondary/boolean-false.input.tsx create mode 100644 src/codemods/__testfixtures__/weak-to-secondary/boolean-false.output.tsx create mode 100644 src/codemods/__testfixtures__/weak-to-secondary/boolean-true.input.tsx create mode 100644 src/codemods/__testfixtures__/weak-to-secondary/boolean-true.output.tsx create mode 100644 src/codemods/__testfixtures__/weak-to-secondary/local-rename.input.tsx create mode 100644 src/codemods/__testfixtures__/weak-to-secondary/local-rename.output.tsx create mode 100644 src/codemods/__tests__/weak-to-secondary-test.ts create mode 100644 src/codemods/weak-to-secondary.ts diff --git a/src/codemods/__testfixtures__/weak-to-secondary/basic-usage.input.tsx b/src/codemods/__testfixtures__/weak-to-secondary/basic-usage.input.tsx new file mode 100644 index 000000000..1647c4678 --- /dev/null +++ b/src/codemods/__testfixtures__/weak-to-secondary/basic-usage.input.tsx @@ -0,0 +1,7 @@ +import { Text } from '@freenow/wave'; + +export const TextTest = () => ( + + Just a text + +); diff --git a/src/codemods/__testfixtures__/weak-to-secondary/basic-usage.output.tsx b/src/codemods/__testfixtures__/weak-to-secondary/basic-usage.output.tsx new file mode 100644 index 000000000..b9d1ac9d0 --- /dev/null +++ b/src/codemods/__testfixtures__/weak-to-secondary/basic-usage.output.tsx @@ -0,0 +1,7 @@ +import { Text } from '@freenow/wave'; + +export const TextTest = () => ( + + Just a text + +); diff --git a/src/codemods/__testfixtures__/weak-to-secondary/boolean-false.input.tsx b/src/codemods/__testfixtures__/weak-to-secondary/boolean-false.input.tsx new file mode 100644 index 000000000..809ad9921 --- /dev/null +++ b/src/codemods/__testfixtures__/weak-to-secondary/boolean-false.input.tsx @@ -0,0 +1,7 @@ +import { Text } from '@freenow/wave'; + +export const TextTest = () => ( + + Just a text + +); diff --git a/src/codemods/__testfixtures__/weak-to-secondary/boolean-false.output.tsx b/src/codemods/__testfixtures__/weak-to-secondary/boolean-false.output.tsx new file mode 100644 index 000000000..ec43446bc --- /dev/null +++ b/src/codemods/__testfixtures__/weak-to-secondary/boolean-false.output.tsx @@ -0,0 +1,3 @@ +import { Text } from '@freenow/wave'; + +export const TextTest = () => Just a text; diff --git a/src/codemods/__testfixtures__/weak-to-secondary/boolean-true.input.tsx b/src/codemods/__testfixtures__/weak-to-secondary/boolean-true.input.tsx new file mode 100644 index 000000000..75160a6bd --- /dev/null +++ b/src/codemods/__testfixtures__/weak-to-secondary/boolean-true.input.tsx @@ -0,0 +1,7 @@ +import { Text } from '@freenow/wave'; + +export const TextTest = () => ( + + Just a text + +); diff --git a/src/codemods/__testfixtures__/weak-to-secondary/boolean-true.output.tsx b/src/codemods/__testfixtures__/weak-to-secondary/boolean-true.output.tsx new file mode 100644 index 000000000..b9d1ac9d0 --- /dev/null +++ b/src/codemods/__testfixtures__/weak-to-secondary/boolean-true.output.tsx @@ -0,0 +1,7 @@ +import { Text } from '@freenow/wave'; + +export const TextTest = () => ( + + Just a text + +); diff --git a/src/codemods/__testfixtures__/weak-to-secondary/local-rename.input.tsx b/src/codemods/__testfixtures__/weak-to-secondary/local-rename.input.tsx new file mode 100644 index 000000000..d69c875c5 --- /dev/null +++ b/src/codemods/__testfixtures__/weak-to-secondary/local-rename.input.tsx @@ -0,0 +1,7 @@ +import { Text as WaveText } from '@freenow/wave'; + +export const TextTest = () => ( + + Just a text + +); diff --git a/src/codemods/__testfixtures__/weak-to-secondary/local-rename.output.tsx b/src/codemods/__testfixtures__/weak-to-secondary/local-rename.output.tsx new file mode 100644 index 000000000..ce2eeb4ea --- /dev/null +++ b/src/codemods/__testfixtures__/weak-to-secondary/local-rename.output.tsx @@ -0,0 +1,7 @@ +import { Text as WaveText } from '@freenow/wave'; + +export const TextTest = () => ( + + Just a text + +); diff --git a/src/codemods/__tests__/weak-to-secondary-test.ts b/src/codemods/__tests__/weak-to-secondary-test.ts new file mode 100644 index 000000000..e07796b5f --- /dev/null +++ b/src/codemods/__tests__/weak-to-secondary-test.ts @@ -0,0 +1,12 @@ +jest.autoMockOff(); +const { defineTest } = require('jscodeshift/dist/testUtils'); + +const tests = ['basic-usage', 'local-rename', 'boolean-true', 'boolean-false']; + +describe('weak-to-secondary', () => { + tests.forEach(test => + defineTest(__dirname, 'weak-to-secondary', { quote: 'single' }, `weak-to-secondary/${test}`, { + parser: 'tsx' + }) + ); +}); diff --git a/src/codemods/weak-to-secondary.ts b/src/codemods/weak-to-secondary.ts new file mode 100644 index 000000000..f9a86c192 --- /dev/null +++ b/src/codemods/weak-to-secondary.ts @@ -0,0 +1,61 @@ +import { API, FileInfo } from 'jscodeshift'; +import { Options } from 'recast'; + +module.exports = (file: FileInfo, api: API, options: Options) => { + const j = api.jscodeshift; + const ast = j(file.source); + const printOptions = options ?? { quote: 'single' }; + + const localTextNames = []; + + const secondaryProp = { + type: 'JSXAttribute', + name: 'secondary' + }; + + // Find Wave Text imports and store the local names + ast.find(j.ImportDeclaration, decl => decl.source.value === '@freenow/wave').forEach(decl => { + j(decl) + .find(j.ImportSpecifier) + .forEach(spec => { + if (spec.node.imported.name === 'Text') localTextNames.push(spec.node.local.name); + }); + }); + + // Search for usages of Text + ast.find(j.JSXElement, { + openingElement: { + name: { + name: name => localTextNames.includes(name) + } + } + }).forEach(el => { + j(el) + // Find weak props being used + .find(j.JSXAttribute, { + name: name => name.name === 'weak' + }) + .forEach(attr => { + const mutableAttr = j(attr); + + // In case it's implicitly true () + if (!attr.node.value) { + // Replace with secondary prop + mutableAttr.replaceWith(secondaryProp); + } + + // In case it has a value (weak={false} or weak={true}) + if ( + attr.node.value?.type === 'JSXExpressionContainer' && + attr.node.value.expression.type === 'BooleanLiteral' + ) { + // If weak={true} replace with secondary prop + if (attr.node.value.expression.value) mutableAttr.replaceWith(secondaryProp); + // Else (weak={false}) remove altogether + else mutableAttr.remove(); + } + }); + }); + + return ast.toSource(printOptions); +}; From e31e550e428984a2a99e4c0c1b391d7ce3f4f981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Malek?= Date: Tue, 19 Sep 2023 12:20:27 +0200 Subject: [PATCH 2/6] docs: add migrating description of weak-to-secondary codemod --- docs/migrating.storybook.mdx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/migrating.storybook.mdx b/docs/migrating.storybook.mdx index 092cd5e17..b8ff1ec04 100644 --- a/docs/migrating.storybook.mdx +++ b/docs/migrating.storybook.mdx @@ -50,3 +50,12 @@ This won't change how your icons look in any way since we already exported the d ```bash npx jscodeshift -t node_modules/@freenow/wave/lib/cjs/codemods/deprecated-icons.js path/to/src ``` + +### Text weak property + +The `weak` property was the initial way to indicate secondary information in a `Text` component, it has been deprecated for a while in favour of +the more semantic `secondary` prop. + +```bash +npx jscodeshift -t node_modules/@freenow/wave/lib/cjs/codemods/weak-to-secondary.js path/to/src +``` From 4f8e1ffca4a5be3d6dd45e20c4a4ed35bce18e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Malek?= Date: Tue, 19 Sep 2023 13:03:50 +0200 Subject: [PATCH 3/6] feat: cover dynamic values in weak prop codemod and simplify it --- .prettierignore | 1 + .../weak-to-secondary/dynamic-value.input.tsx | 7 ++++++ .../dynamic-value.output.tsx | 7 ++++++ .../__tests__/weak-to-secondary-test.ts | 2 +- src/codemods/weak-to-secondary.ts | 22 ++++++++++++------- 5 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 src/codemods/__testfixtures__/weak-to-secondary/dynamic-value.input.tsx create mode 100644 src/codemods/__testfixtures__/weak-to-secondary/dynamic-value.output.tsx diff --git a/.prettierignore b/.prettierignore index 483a9c42c..ba95377be 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1 +1,2 @@ +codemods/__testfixtures__ package-lock.json \ No newline at end of file diff --git a/src/codemods/__testfixtures__/weak-to-secondary/dynamic-value.input.tsx b/src/codemods/__testfixtures__/weak-to-secondary/dynamic-value.input.tsx new file mode 100644 index 000000000..869c4f9ab --- /dev/null +++ b/src/codemods/__testfixtures__/weak-to-secondary/dynamic-value.input.tsx @@ -0,0 +1,7 @@ +import { Text } from '@freenow/wave'; + +export const TextTest = () => ( + + Just a text + +); diff --git a/src/codemods/__testfixtures__/weak-to-secondary/dynamic-value.output.tsx b/src/codemods/__testfixtures__/weak-to-secondary/dynamic-value.output.tsx new file mode 100644 index 000000000..e9d34b6af --- /dev/null +++ b/src/codemods/__testfixtures__/weak-to-secondary/dynamic-value.output.tsx @@ -0,0 +1,7 @@ +import { Text } from '@freenow/wave'; + +export const TextTest = () => ( + + Just a text + +); diff --git a/src/codemods/__tests__/weak-to-secondary-test.ts b/src/codemods/__tests__/weak-to-secondary-test.ts index e07796b5f..461b9c39d 100644 --- a/src/codemods/__tests__/weak-to-secondary-test.ts +++ b/src/codemods/__tests__/weak-to-secondary-test.ts @@ -1,7 +1,7 @@ jest.autoMockOff(); const { defineTest } = require('jscodeshift/dist/testUtils'); -const tests = ['basic-usage', 'local-rename', 'boolean-true', 'boolean-false']; +const tests = ['basic-usage', 'local-rename', 'boolean-true', 'boolean-false', 'dynamic-value']; describe('weak-to-secondary', () => { tests.forEach(test => diff --git a/src/codemods/weak-to-secondary.ts b/src/codemods/weak-to-secondary.ts index f9a86c192..da273e625 100644 --- a/src/codemods/weak-to-secondary.ts +++ b/src/codemods/weak-to-secondary.ts @@ -1,4 +1,4 @@ -import { API, FileInfo } from 'jscodeshift'; +import { API, ASTPath, FileInfo, JSXIdentifier } from 'jscodeshift'; import { Options } from 'recast'; module.exports = (file: FileInfo, api: API, options: Options) => { @@ -38,22 +38,28 @@ module.exports = (file: FileInfo, api: API, options: Options) => { .forEach(attr => { const mutableAttr = j(attr); - // In case it's implicitly true () - if (!attr.node.value) { - // Replace with secondary prop - mutableAttr.replaceWith(secondaryProp); - } + // Find the identifier (where the prop name is kept) + const identifier: ASTPath = mutableAttr + .find(j.JSXIdentifier, { + name: 'weak' + }) + .get(0).node; - // In case it has a value (weak={false} or weak={true}) + // In case it has a boolean value (weak={false} or weak={true}) if ( attr.node.value?.type === 'JSXExpressionContainer' && attr.node.value.expression.type === 'BooleanLiteral' ) { // If weak={true} replace with secondary prop if (attr.node.value.expression.value) mutableAttr.replaceWith(secondaryProp); - // Else (weak={false}) remove altogether + // Otherwise (weak={false}) remove altogether else mutableAttr.remove(); + return; } + + // For other cases, e.g. implicit value (weak), dynamic value (weak={Date.now() % 2 === 0}) + // Replace the name of the prop + identifier.name = 'secondary'; }); }); From 2a818c34fbd0ba68221f39224a939fa2175314b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Malek?= Date: Tue, 19 Sep 2023 13:10:23 +0200 Subject: [PATCH 4/6] test: fix codemods tests styling --- src/codemods/__testfixtures__/block-to-width-100.output.tsx | 2 +- .../weak-to-secondary/boolean-false.output.tsx | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/codemods/__testfixtures__/block-to-width-100.output.tsx b/src/codemods/__testfixtures__/block-to-width-100.output.tsx index c1833e9b6..08218ab00 100644 --- a/src/codemods/__testfixtures__/block-to-width-100.output.tsx +++ b/src/codemods/__testfixtures__/block-to-width-100.output.tsx @@ -2,7 +2,7 @@ import { Button } from '@freenow/wave'; import React from 'react'; export const ButtonTest = (): JSX.Element => ( - ); diff --git a/src/codemods/__testfixtures__/weak-to-secondary/boolean-false.output.tsx b/src/codemods/__testfixtures__/weak-to-secondary/boolean-false.output.tsx index ec43446bc..cb3fde51b 100644 --- a/src/codemods/__testfixtures__/weak-to-secondary/boolean-false.output.tsx +++ b/src/codemods/__testfixtures__/weak-to-secondary/boolean-false.output.tsx @@ -1,3 +1,7 @@ import { Text } from '@freenow/wave'; -export const TextTest = () => Just a text; +export const TextTest = () => ( + + Just a text + +); From e5477d05432067dd90e60cc827f9836082f18588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Malek?= Date: Tue, 19 Sep 2023 13:35:55 +0200 Subject: [PATCH 5/6] chore: remove unused .prettierignore entry --- .prettierignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.prettierignore b/.prettierignore index ba95377be..483a9c42c 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,2 +1 @@ -codemods/__testfixtures__ package-lock.json \ No newline at end of file From f58cec07a210c920baab63f535c36fb3f48c2af5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Malek?= Date: Fri, 29 Sep 2023 13:53:43 +0200 Subject: [PATCH 6/6] feat!: remove weak prop from Text --- src/components/Text/Text.tsx | 14 ++------------ src/components/Text/docs/Text.stories.tsx | 5 ----- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/components/Text/Text.tsx b/src/components/Text/Text.tsx index e21b9b58e..87b519697 100644 --- a/src/components/Text/Text.tsx +++ b/src/components/Text/Text.tsx @@ -15,7 +15,6 @@ import { } from 'styled-system'; import { theme } from '../../essentials/theme'; import { get } from '../../utils/themeGet'; -import { deprecatedProperty } from '../../utils/deprecatedProperty'; import { getSemanticValue } from '../../utils/cssVariables'; interface TextProps @@ -33,11 +32,6 @@ interface TextProps * Adjust color for display on a dark background */ inverted?: boolean; - /** - * Adjust color to indicate secondary information - * @deprecated use `secondary` instead - */ - weak?: boolean; /** * Adjust color to indicate secondary information */ @@ -49,16 +43,12 @@ interface TextProps } function determineTextColor(props: TextProps) { - const { weak, secondary, inverted, disabled } = props; - if (weak !== undefined) { - deprecatedProperty('Text', weak, 'weak', 'secondary', 'Rename `weak` to `secondary` to remove the warning.'); - } - + const { secondary, inverted, disabled } = props; if (disabled) { return getSemanticValue('foreground-disabled'); } - if (secondary || weak) { + if (secondary) { return getSemanticValue(inverted ? 'foreground-neutral-faded' : 'foreground-neutral-emphasized'); } diff --git a/src/components/Text/docs/Text.stories.tsx b/src/components/Text/docs/Text.stories.tsx index 13b31cd41..67758229b 100644 --- a/src/components/Text/docs/Text.stories.tsx +++ b/src/components/Text/docs/Text.stories.tsx @@ -52,11 +52,6 @@ const meta: Meta = { disable: true } }, - weak: { - table: { - disable: true - } - } }, args: { children: 'Sign up to FREENOW'