From 22989e33f19d6a299d45da1ba0cc3c303f047a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Malek?= Date: Tue, 22 Aug 2023 11:54:34 +0200 Subject: [PATCH 1/9] chore: bump jscodeshift to 0.15.0 --- package-lock.json | 332 +++------------------------------------------- package.json | 4 +- 2 files changed, 18 insertions(+), 318 deletions(-) diff --git a/package-lock.json b/package-lock.json index ce4be7140..809f978aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -76,7 +76,7 @@ "jest-axe": "^3.4.0", "jest-date-mock": "^1.0.8", "jest-styled-components": "^7.0.2", - "jscodeshift": "^0.13.0", + "jscodeshift": "^0.15.0", "minimatch": "^3.0.4", "prettier": "^2.0.2", "pretty-quick": "^2.0.1", @@ -22451,9 +22451,9 @@ } }, "node_modules/jscodeshift": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.13.1.tgz", - "integrity": "sha512-lGyiEbGOvmMRKgWk4vf+lUrCWO/8YR8sUR3FKF1Cq5fovjZDlIcw3Hu5ppLHAnEXshVffvaM0eyuY/AbOeYpnQ==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.0.tgz", + "integrity": "sha512-t337Wx7Vy1ffhas7E1KZUHaR9YPdeCfxPvxz9k6DKwYW88pcs1piR1eR9d+7GQZGSQIZd6a+cfIM3XpMe9rFKQ==", "dev": true, "dependencies": { "@babel/core": "^7.13.16", @@ -22469,10 +22469,10 @@ "chalk": "^4.1.2", "flow-parser": "0.*", "graceful-fs": "^4.2.4", - "micromatch": "^3.1.10", + "micromatch": "^4.0.4", "neo-async": "^2.5.0", "node-dir": "^0.1.17", - "recast": "^0.20.4", + "recast": "^0.23.1", "temp": "^0.8.4", "write-file-atomic": "^2.3.0" }, @@ -22481,6 +22481,11 @@ }, "peerDependencies": { "@babel/preset-env": "^7.1.6" + }, + "peerDependenciesMeta": { + "@babel/preset-env": { + "optional": true + } } }, "node_modules/jscodeshift/node_modules/ansi-styles": { @@ -22498,27 +22503,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jscodeshift/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/jscodeshift/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -22553,21 +22537,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/jscodeshift/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/jscodeshift/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -22577,118 +22546,6 @@ "node": ">=8" } }, - "node_modules/jscodeshift/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/jscodeshift/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jscodeshift/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jscodeshift/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jscodeshift/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jscodeshift/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jscodeshift/node_modules/micromatch/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jscodeshift/node_modules/recast": { - "version": "0.20.5", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.20.5.tgz", - "integrity": "sha512-E5qICoPoNL4yU0H0NoBDntNB0Q5oMSNh9usFctYniLBluTthi3RsQVBXIJNbApOlvSwW/RGxIuokPcAc59J5fQ==", - "dev": true, - "dependencies": { - "ast-types": "0.14.2", - "esprima": "~4.0.0", - "source-map": "~0.6.1", - "tslib": "^2.0.1" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/jscodeshift/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/jscodeshift/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -22701,25 +22558,6 @@ "node": ">=8" } }, - "node_modules/jscodeshift/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jscodeshift/node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true - }, "node_modules/jscodeshift/node_modules/write-file-atomic": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", @@ -50929,9 +50767,9 @@ } }, "jscodeshift": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.13.1.tgz", - "integrity": "sha512-lGyiEbGOvmMRKgWk4vf+lUrCWO/8YR8sUR3FKF1Cq5fovjZDlIcw3Hu5ppLHAnEXshVffvaM0eyuY/AbOeYpnQ==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.0.tgz", + "integrity": "sha512-t337Wx7Vy1ffhas7E1KZUHaR9YPdeCfxPvxz9k6DKwYW88pcs1piR1eR9d+7GQZGSQIZd6a+cfIM3XpMe9rFKQ==", "dev": true, "requires": { "@babel/core": "^7.13.16", @@ -50947,10 +50785,10 @@ "chalk": "^4.1.2", "flow-parser": "0.*", "graceful-fs": "^4.2.4", - "micromatch": "^3.1.10", + "micromatch": "^4.0.4", "neo-async": "^2.5.0", "node-dir": "^0.1.17", - "recast": "^0.20.4", + "recast": "^0.23.1", "temp": "^0.8.4", "write-file-atomic": "^2.3.0" }, @@ -50964,24 +50802,6 @@ "color-convert": "^2.0.1" } }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - } - }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -51007,116 +50827,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - } - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - } - } - }, - "recast": { - "version": "0.20.5", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.20.5.tgz", - "integrity": "sha512-E5qICoPoNL4yU0H0NoBDntNB0Q5oMSNh9usFctYniLBluTthi3RsQVBXIJNbApOlvSwW/RGxIuokPcAc59J5fQ==", - "dev": true, - "requires": { - "ast-types": "0.14.2", - "esprima": "~4.0.0", - "source-map": "~0.6.1", - "tslib": "^2.0.1" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -51126,22 +50842,6 @@ "has-flag": "^4.0.0" } }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true - }, "write-file-atomic": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", diff --git a/package.json b/package.json index 053b09f27..a01bbecda 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "@types/babel__traverse": "7.17.1", "@types/jest": "^25.1.4", "@types/jest-axe": "^3.2.1", - "@types/jscodeshift": "^0.11.1", + "@types/jscodeshift": "^0.11.6", "@types/node": "^17.0.41", "@types/react": "^18.0.28", "@types/react-dom": "^18.0.11", @@ -105,7 +105,7 @@ "jest-axe": "^3.4.0", "jest-date-mock": "^1.0.8", "jest-styled-components": "^7.0.2", - "jscodeshift": "^0.13.0", + "jscodeshift": "^0.15.0", "minimatch": "^3.0.4", "prettier": "^2.0.2", "pretty-quick": "^2.0.1", From 0ae4665a4af7267d4a40141ea6a00ab897c681b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Malek?= Date: Tue, 22 Aug 2023 13:49:44 +0200 Subject: [PATCH 2/9] test: cover block property transform --- .../block-to-width-100.input.tsx | 8 +++ .../block-to-width-100.output.tsx | 8 +++ codemods/__tests__/block-to-width-100-test.ts | 4 ++ codemods/block-to-width-100.ts | 57 ++++++++++++++++ codemods/v2.ts | 67 +------------------ jest.config.js | 2 +- package-lock.json | 2 +- package.json | 1 + 8 files changed, 83 insertions(+), 66 deletions(-) create mode 100644 codemods/__testfixtures__/block-to-width-100.input.tsx create mode 100644 codemods/__testfixtures__/block-to-width-100.output.tsx create mode 100644 codemods/__tests__/block-to-width-100-test.ts create mode 100644 codemods/block-to-width-100.ts diff --git a/codemods/__testfixtures__/block-to-width-100.input.tsx b/codemods/__testfixtures__/block-to-width-100.input.tsx new file mode 100644 index 000000000..88d862eb7 --- /dev/null +++ b/codemods/__testfixtures__/block-to-width-100.input.tsx @@ -0,0 +1,8 @@ +import { Button } from '@freenow/wave'; +import React from 'react'; + +export const ButtonTest = (): JSX.Element => ( + +); diff --git a/codemods/__testfixtures__/block-to-width-100.output.tsx b/codemods/__testfixtures__/block-to-width-100.output.tsx new file mode 100644 index 000000000..c1833e9b6 --- /dev/null +++ b/codemods/__testfixtures__/block-to-width-100.output.tsx @@ -0,0 +1,8 @@ +import { Button } from '@freenow/wave'; +import React from 'react'; + +export const ButtonTest = (): JSX.Element => ( + +); diff --git a/codemods/__tests__/block-to-width-100-test.ts b/codemods/__tests__/block-to-width-100-test.ts new file mode 100644 index 000000000..ea349f4b5 --- /dev/null +++ b/codemods/__tests__/block-to-width-100-test.ts @@ -0,0 +1,4 @@ +jest.autoMockOff(); +const { defineTest } = require('jscodeshift/dist/testUtils'); + +defineTest(__dirname, 'block-to-width-100', null, 'block-to-width-100', { parser: 'tsx' }); diff --git a/codemods/block-to-width-100.ts b/codemods/block-to-width-100.ts new file mode 100644 index 000000000..2e10cda87 --- /dev/null +++ b/codemods/block-to-width-100.ts @@ -0,0 +1,57 @@ +import { API, FileInfo } from 'jscodeshift'; + +module.exports = (file: FileInfo, api: API) => { + const j = api.jscodeshift; + const ast = j(file.source); + + const localButtonNames = []; + + const fullWidthProp = { + type: 'JSXAttribute', + name: 'width', + value: { + type: 'StringLiteral', + value: '100%' + } + }; + + ast.find(j.ImportDeclaration, decl => decl.source.value === '@freenow/wave').forEach(decl => { + j(decl) + .find(j.ImportSpecifier) + .forEach(spec => { + if (spec.node.imported.name === 'Button' || spec.node.imported.name === 'TextButton') { + localButtonNames.push(spec.node.local.name); + } + }); + }); + + ast.find(j.JSXElement, { + openingElement: { + name: { + name: name => localButtonNames.includes(name) + } + } + }).forEach(el => { + j(el) + .find(j.JSXAttribute, { + name: name => name.name === 'block' + }) + .forEach(attr => { + if (attr.value.value) { + j(attr) + .find(j.Literal) + .forEach(literal => { + if (literal.value.value === false) { + j(attr).remove(); + } else { + j(attr).replaceWith(fullWidthProp); + } + }); + } else { + j(attr).replaceWith(fullWidthProp); + } + }); + }); + + return ast.toSource({ quote: 'single' }); +}; diff --git a/codemods/v2.ts b/codemods/v2.ts index 145fb5193..26316fd92 100644 --- a/codemods/v2.ts +++ b/codemods/v2.ts @@ -1,68 +1,7 @@ -import { API, Collection, FileInfo, JSCodeshift } from 'jscodeshift'; - -function transformBlockProperty(j: JSCodeshift, ast: Collection) { - const localButtonNames = []; - - const fullWidthProp = { - type: 'JSXAttribute', - name: 'width', - value: { - type: 'StringLiteral', - value: '100%' - } - }; - - ast - .find(j.ImportDeclaration, decl => decl.source.value === '@freenow/wave') - .forEach(decl => { - j(decl) - .find(j.ImportSpecifier) - .forEach(spec => { - if (spec.node.imported.name === 'Button' || spec.node.imported.name === 'TextButton') { - localButtonNames.push(spec.node.local.name); - } - }); - }); - - ast - .find(j.JSXElement, { - openingElement: { - name: { - name: name => { - return localButtonNames.includes(name); - } - } - } - }) - .forEach(el => { - j(el) - .find(j.JSXAttribute, { - name: name => { - return name.name === 'block'; - } - }) - .forEach(attr => { - if (attr.value.value) { - j(attr).find(j.Literal).forEach((literal) => { - if (literal.value.value === false) { - j(attr).remove(); - } else { - j(attr).replaceWith(fullWidthProp); - } - }); - } else { - j(attr).replaceWith(fullWidthProp); - } - }); - }); -} +import { API, FileInfo } from 'jscodeshift'; +const blockToWidth100Transform = require('./block-to-width-100'); module.exports = (file: FileInfo, api: API) => { - const j = api.jscodeshift; - const ast = j(file.source); - - transformBlockProperty(j, ast) - - return ast.toSource() + return blockToWidth100Transform(file, api); }; diff --git a/jest.config.js b/jest.config.js index 1d94854b0..1ce4f6c43 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,5 @@ module.exports = { - roots: ['/src'], + roots: ['/src', '/codemods'], transform: { '^.+\\.tsx?$': 'ts-jest', '^.+\\.svg$': '/svgTransform.js' diff --git a/package-lock.json b/package-lock.json index 809f978aa..586c44f0d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,7 +50,7 @@ "@types/babel__traverse": "7.17.1", "@types/jest": "^25.1.4", "@types/jest-axe": "^3.2.1", - "@types/jscodeshift": "^0.11.1", + "@types/jscodeshift": "^0.11.6", "@types/node": "^17.0.41", "@types/react": "^18.0.28", "@types/react-dom": "^18.0.11", diff --git a/package.json b/package.json index a01bbecda..964234075 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "test": "jest", "test:fixture": "./scripts/run_fixtures.sh", "test:watch": "jest --watch", + "test:codemods": "jest codemods", "lint": "npx concurrently \"npm run lint:eslint\" \"npm run lint:stylelint\"", "lint:stylelint": "stylelint --config .stylelintrc 'src/**/*.ts?(x)'", "lint:eslint": "eslint --format pretty --ext .js,.jsx,.ts,.tsx src/", From 6d8ba44c236788e68aaa616a74e3707fe5729719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Malek?= Date: Fri, 25 Aug 2023 11:54:44 +0200 Subject: [PATCH 3/9] feat: replace colors in template string for css vars --- .../color-in-JSX-multi-import.input.tsx | 5 + .../color-in-JSX-multi-import.output.tsx | 5 + .../color-in-JSX-single-import.input.tsx | 9 + .../color-in-JSX-single-import.output.tsx | 7 + .../template-multi-quasis.input.tsx | 28 +++ .../template-multi-quasis.output.tsx | 28 +++ .../template-single-quasis.input.tsx | 6 + .../template-single-quasis.output.tsx | 5 + codemods/__tests__/colors-to-css-vars-test.ts | 17 ++ codemods/colors-to-css-vars.ts | 166 ++++++++++++++++++ 10 files changed, 276 insertions(+) create mode 100644 codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.input.tsx create mode 100644 codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.output.tsx create mode 100644 codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.input.tsx create mode 100644 codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.output.tsx create mode 100644 codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis.input.tsx create mode 100644 codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis.output.tsx create mode 100644 codemods/__testfixtures__/colors-to-css-vars/template-single-quasis.input.tsx create mode 100644 codemods/__testfixtures__/colors-to-css-vars/template-single-quasis.output.tsx create mode 100644 codemods/__tests__/colors-to-css-vars-test.ts create mode 100644 codemods/colors-to-css-vars.ts diff --git a/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.input.tsx b/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.input.tsx new file mode 100644 index 000000000..6cf25eab2 --- /dev/null +++ b/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.input.tsx @@ -0,0 +1,5 @@ +import { CloseIcon, Colors } from '@freenow/wave'; + +export const CloseIconWrapper = () => ( + +); diff --git a/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.output.tsx b/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.output.tsx new file mode 100644 index 000000000..147508193 --- /dev/null +++ b/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.output.tsx @@ -0,0 +1,5 @@ +import { CloseIcon } from '@freenow/wave'; + +export const CloseIconWrapper = () => ( + +); diff --git a/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.input.tsx b/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.input.tsx new file mode 100644 index 000000000..aafd4aa12 --- /dev/null +++ b/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.input.tsx @@ -0,0 +1,9 @@ +import { Colors } from '@freenow/wave'; + +export const GhostIcon = () => ( + + + + + +); diff --git a/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.output.tsx b/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.output.tsx new file mode 100644 index 000000000..b66b7cc48 --- /dev/null +++ b/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.output.tsx @@ -0,0 +1,7 @@ +export const GhostIcon = () => ( + + + + + +); diff --git a/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis.input.tsx b/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis.input.tsx new file mode 100644 index 000000000..db9579054 --- /dev/null +++ b/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis.input.tsx @@ -0,0 +1,28 @@ +import { Colors, Spaces, TextButton, TextButtonProps } from '@freenow/wave'; +import styled from 'styled-components'; + +export const NavigationLink: React.FC = styled(TextButton)<{ active: boolean }>` + display: flex; + align-items: center; + justify-content: flex-start; + + width: 100%; + + padding: ${Spaces[2]}; + padding-left: ${({ active }) => (active ? '20px' : Spaces[3])}; + + font-size: 14px; + font-weight: normal; + text-decoration: none; + + ${props => + props.active && + ` + border-left: 4px solid ${Colors.ACTION_BLUE_900}; + `} + + :hover :first-of-type { + text-decoration: none; + color: ${Colors.ACTION_BLUE_900}; + } +`; diff --git a/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis.output.tsx b/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis.output.tsx new file mode 100644 index 000000000..10f95e96a --- /dev/null +++ b/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis.output.tsx @@ -0,0 +1,28 @@ +import { Spaces, TextButton, TextButtonProps } from '@freenow/wave'; +import styled from 'styled-components'; + +export const NavigationLink: React.FC = styled(TextButton)<{ active: boolean }>` + display: flex; + align-items: center; + justify-content: flex-start; + + width: 100%; + + padding: ${Spaces[2]}; + padding-left: ${({ active }) => (active ? '20px' : Spaces[3])}; + + font-size: 14px; + font-weight: normal; + text-decoration: none; + + ${props => + props.active && + ` + border-left: 4px solid var(--wave-b-color-blue-secondary-900); + `} + + :hover :first-of-type { + text-decoration: none; + color: var(--wave-b-color-blue-secondary-900); + } +`; diff --git a/codemods/__testfixtures__/colors-to-css-vars/template-single-quasis.input.tsx b/codemods/__testfixtures__/colors-to-css-vars/template-single-quasis.input.tsx new file mode 100644 index 000000000..73ba30fb5 --- /dev/null +++ b/codemods/__testfixtures__/colors-to-css-vars/template-single-quasis.input.tsx @@ -0,0 +1,6 @@ +import { Colors } from '@freenow/wave'; +import styled from 'styled-components'; + +export const GreyList = styled.ul` + color: ${Colors.AUTHENTIC_BLUE_550}; +`; diff --git a/codemods/__testfixtures__/colors-to-css-vars/template-single-quasis.output.tsx b/codemods/__testfixtures__/colors-to-css-vars/template-single-quasis.output.tsx new file mode 100644 index 000000000..3d6f0afc8 --- /dev/null +++ b/codemods/__testfixtures__/colors-to-css-vars/template-single-quasis.output.tsx @@ -0,0 +1,5 @@ +import styled from 'styled-components'; + +export const GreyList = styled.ul` + color: var(--wave-b-color-blue-primary-550); +`; diff --git a/codemods/__tests__/colors-to-css-vars-test.ts b/codemods/__tests__/colors-to-css-vars-test.ts new file mode 100644 index 000000000..fa979983d --- /dev/null +++ b/codemods/__tests__/colors-to-css-vars-test.ts @@ -0,0 +1,17 @@ +jest.autoMockOff(); +const { defineTest } = require('jscodeshift/dist/testUtils'); + +const tests = [ + 'color-in-JSX-multi-import', + 'color-in-JSX-single-import', + 'template-multi-quasis', + 'template-single-quasis' +]; + +describe('colors-to-css-vars', () => { + tests.forEach(test => + defineTest(__dirname, 'colors-to-css-vars', { quote: 'single' }, `colors-to-css-vars/${test}`, { + parser: 'tsx' + }) + ); +}); diff --git a/codemods/colors-to-css-vars.ts b/codemods/colors-to-css-vars.ts new file mode 100644 index 000000000..77ea73db4 --- /dev/null +++ b/codemods/colors-to-css-vars.ts @@ -0,0 +1,166 @@ +import { API, FileInfo, Identifier, JSCodeshift, MemberExpression, TemplateLiteral } from 'jscodeshift'; +import { Options } from 'recast'; + +const ColorsToCssVariablesMap = { + WHITE: 'var(--wave-b-color-white)', + BLACK: 'var(--wave-b-color-black)', + AUTHENTIC_BLUE_1100: 'var(--wave-b-color-blue-primary-1100)', + AUTHENTIC_BLUE_900: 'var(--wave-b-color-blue-primary-900)', + AUTHENTIC_BLUE_550: 'var(--wave-b-color-blue-primary-550)', + AUTHENTIC_BLUE_350: 'var(--wave-b-color-blue-primary-350)', + AUTHENTIC_BLUE_200: 'var(--wave-b-color-blue-primary-200)', + AUTHENTIC_BLUE_50: 'var(--wave-b-color-blue-primary-50)', + FREEDOM_RED_1000: 'var(--wave-b-color-red-1000)', + FREEDOM_RED_900: 'var(--wave-b-color-red-900)', + ACTION_BLUE_1000: 'var(--wave-b-color-blue-secondary-1000)', + ACTION_BLUE_900: 'var(--wave-b-color-blue-secondary-900)', + ACTION_BLUE_350: 'var(--wave-b-color-blue-secondary-350)', + ACTION_BLUE_150: 'var(--wave-b-color-blue-secondary-150)', + ACTION_BLUE_100: 'var(--wave-b-color-blue-secondary-100)', + ACTION_BLUE_50: 'var(--wave-b-color-blue-secondary-50)', + BUMPY_MAGENTA_1000: 'var(--wave-b-color-magenta-1000)', + BUMPY_MAGENTA_900: 'var(--wave-b-color-magenta-900)', + BUMPY_MAGENTA_350: 'var(--wave-b-color-magenta-350)', + BUMPY_MAGENTA_50: 'var(--wave-b-color-magenta-50)', + POSITIVE_GREEN_1000: 'var(--wave-b-color-green-1000)', + POSITIVE_GREEN_900: 'var(--wave-b-color-green-900)', + POSITIVE_GREEN_350: 'var(--wave-b-color-green-350)', + POSITIVE_GREEN_50: 'var(--wave-b-color-green-50)', + ATTENTION_YELLOW_900: 'var(--wave-b-color-yellow-900)', + ATTENTION_YELLOW_350: 'var(--wave-b-color-yellow-350)', + ATTENTION_YELLOW_50: 'var(--wave-b-color-yellow-50)', + NEGATIVE_ORANGE_1000: 'var(--wave-b-color-orange-1000)', + NEGATIVE_ORANGE_900: 'var(--wave-b-color-orange-900)', + NEGATIVE_ORANGE_350: 'var(--wave-b-color-orange-350)', + NEGATIVE_ORANGE_50: 'var(--wave-b-color-orange-50)' +}; + +const replaceColorsForCssVarsInTemplateLiterals = ( + j: JSCodeshift, + localColorNames: string[], + templateLiteral: TemplateLiteral, + n?: number +) => { + const quasis = templateLiteral.quasis; + const expressions = templateLiteral.expressions; + + const expressionsToRemoveIndexes: number[] = []; + const quasisToRemoveIndexes: number[] = []; + + // Iterate over the quasis of the template string (the parts before the `${` and after the `}`) + // e.g. in the template string `color: ${Colors.x};` there are 2 quasis, `color: ` and `;`, the `Colors.x` is an expression + quasis.forEach((el, index) => { + const expressionAfterQuasis = expressions[index]; + const isSecondToLastQuasis = index === quasis.length - 2; + + // Check if there are arrow functions inside the template string, since they can also have nested template string + if (expressionAfterQuasis && expressionAfterQuasis.type === 'ArrowFunctionExpression') { + const templateExpressions = j(expressionAfterQuasis).find(j.TemplateLiteral); + + // For every template string in the arrow function recursively replace colors for css vars + templateExpressions.forEach(ex => + replaceColorsForCssVarsInTemplateLiterals(j, localColorNames, ex.node, 2) + ); + } + + // Check if the expression is a MemberExpression (regular object property access) + if (expressionAfterQuasis && expressionAfterQuasis.type === 'MemberExpression') { + const expressionObject = (expressionAfterQuasis as MemberExpression).object as Identifier; + + // Identify if it's a usage of Colors + const isColorsExpression = localColorNames.includes(expressionObject.name); + + if (isColorsExpression) { + // Find the color being used + const color = ((expressionAfterQuasis as MemberExpression).property as Identifier).name; + const cssVar = ColorsToCssVariablesMap[color]; + + if (!cssVar) return; + + // Add the mapped css var at the end of the quasis (where the color expression is) + el.value.raw = el.value.raw + cssVar; + + // Flag the color expression so that it is removed afterwards + expressionsToRemoveIndexes.push(index); + + if (isSecondToLastQuasis) { + const lastQuasisValue = quasis[index + 1].value.raw; + + // In case the next quasis is the last one, append it's value to the current value and mark the last quasis to be removed + el.value.raw = el.value.raw + lastQuasisValue; + quasisToRemoveIndexes.push(index + 1); + } + } + } + }); + + // Check if there are any expression that have to be removed and remove them + expressionsToRemoveIndexes.forEach(indexToRemove => { + expressions.splice(indexToRemove, 1); + }); + + // Check if there are any quasis that have to be removed and remove them + quasisToRemoveIndexes.forEach(indexToRemove => { + quasis.splice(indexToRemove, 1); + }); +}; + +export default (file: FileInfo, api: API, options: Options) => { + const j = api.jscodeshift; + const ast = j(file.source); + const printOptions = options ?? { quote: 'single' }; + + const localColorNames: string[] = []; + + // Find @freenow/wave imports + const waveImports = ast.find(j.ImportDeclaration, { + source: { + value: '@freenow/wave' + } + }); + + const waveNamedImports = waveImports.find(j.ImportSpecifier); + + // Find Colors named imports in @freenow/wave imports + const colorsImports = waveNamedImports.filter(path => path.node.imported.name === 'Colors'); + + // Get the local Colors import names + colorsImports.forEach(spec => { + if (spec.node.local?.name) localColorNames.push(spec.node.local.name); + }); + + // Iterate over template strings + ast.find(j.TaggedTemplateExpression).forEach(el => { + // Get template literals in template expression + const templateLiteral = el.node.quasi; + replaceColorsForCssVarsInTemplateLiterals(j, localColorNames, templateLiteral); + }); + + // Find all remaining Colors usage + ast.find(j.MemberExpression, { + object: { + name: (colorName: string) => localColorNames.includes(colorName) + } + }).forEach(ex => { + // Map the Color to a css var + const color = (ex.node.property as Identifier).name; + const cssVar = ColorsToCssVariablesMap[color]; + + if (!cssVar) return; + + // Replace the Colors usage for a string literal (e.g. 'var(--wave-b-color-y)') + const cssVarStringNode = j.stringLiteral(ColorsToCssVariablesMap[color]); + ex.replace(cssVarStringNode); + }); + + // If it is the only named import from wave, remove the whole Wave import + if (waveImports.size() === 1 && waveNamedImports.size() === 1 && colorsImports.size() === 1) { + waveImports.remove(); + + // If there are other named imports from wave, remove only the Colors named import + } else if (waveNamedImports.size() > 1) { + colorsImports.remove(); + } + + return ast.toSource(printOptions); +}; From 34ddfc80bd0e22e9ac313115cc2857f3502de029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Malek?= Date: Fri, 25 Aug 2023 16:23:41 +0200 Subject: [PATCH 4/9] fix: adapt codemod to cover templates with an even number of quasis --- .../template-multi-quasis-even.input.tsx | 25 +++++++++++++++++++ .../template-multi-quasis-even.output.tsx | 25 +++++++++++++++++++ ...sx => template-multi-quasis-odd.input.tsx} | 0 ...x => template-multi-quasis-odd.output.tsx} | 0 codemods/__tests__/colors-to-css-vars-test.ts | 3 ++- codemods/colors-to-css-vars.ts | 25 +++++++------------ codemods/v2.ts | 7 ------ 7 files changed, 61 insertions(+), 24 deletions(-) create mode 100644 codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.input.tsx create mode 100644 codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.output.tsx rename codemods/__testfixtures__/colors-to-css-vars/{template-multi-quasis.input.tsx => template-multi-quasis-odd.input.tsx} (100%) rename codemods/__testfixtures__/colors-to-css-vars/{template-multi-quasis.output.tsx => template-multi-quasis-odd.output.tsx} (100%) delete mode 100644 codemods/v2.ts diff --git a/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.input.tsx b/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.input.tsx new file mode 100644 index 000000000..019f79ab1 --- /dev/null +++ b/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.input.tsx @@ -0,0 +1,25 @@ +import { Button, Colors, Spaces } from '@freenow/wave'; +import styled from 'styled-components'; + +interface Props { + label: string; + disabled?: boolean; + onClick: () => void; +} + +const Action = styled(Button)` + justify-content: flex-start; + + color: ${Colors.AUTHENTIC_BLUE_900}; + font-weight: normal; + line-height: 1.43; + + border-radius: 0; + padding: ${Spaces[2]}; +`; + +export const ActionItem = ({ label, onClick, disabled = false }: Props): JSX.Element => ( + + {label} + +); diff --git a/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.output.tsx b/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.output.tsx new file mode 100644 index 000000000..b79c5221c --- /dev/null +++ b/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.output.tsx @@ -0,0 +1,25 @@ +import { Button, Spaces } from '@freenow/wave'; +import styled from 'styled-components'; + +interface Props { + label: string; + disabled?: boolean; + onClick: () => void; +} + +const Action = styled(Button)` + justify-content: flex-start; + + color: var(--wave-b-color-blue-primary-900); + font-weight: normal; + line-height: 1.43; + + border-radius: 0; + padding: ${Spaces[2]}; +`; + +export const ActionItem = ({ label, onClick, disabled = false }: Props): JSX.Element => ( + + {label} + +); diff --git a/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis.input.tsx b/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-odd.input.tsx similarity index 100% rename from codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis.input.tsx rename to codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-odd.input.tsx diff --git a/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis.output.tsx b/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-odd.output.tsx similarity index 100% rename from codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis.output.tsx rename to codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-odd.output.tsx diff --git a/codemods/__tests__/colors-to-css-vars-test.ts b/codemods/__tests__/colors-to-css-vars-test.ts index fa979983d..43b702203 100644 --- a/codemods/__tests__/colors-to-css-vars-test.ts +++ b/codemods/__tests__/colors-to-css-vars-test.ts @@ -4,7 +4,8 @@ const { defineTest } = require('jscodeshift/dist/testUtils'); const tests = [ 'color-in-JSX-multi-import', 'color-in-JSX-single-import', - 'template-multi-quasis', + 'template-multi-quasis-even', + 'template-multi-quasis-odd', 'template-single-quasis' ]; diff --git a/codemods/colors-to-css-vars.ts b/codemods/colors-to-css-vars.ts index 77ea73db4..c50844815 100644 --- a/codemods/colors-to-css-vars.ts +++ b/codemods/colors-to-css-vars.ts @@ -38,8 +38,7 @@ const ColorsToCssVariablesMap = { const replaceColorsForCssVarsInTemplateLiterals = ( j: JSCodeshift, localColorNames: string[], - templateLiteral: TemplateLiteral, - n?: number + templateLiteral: TemplateLiteral ) => { const quasis = templateLiteral.quasis; const expressions = templateLiteral.expressions; @@ -51,16 +50,13 @@ const replaceColorsForCssVarsInTemplateLiterals = ( // e.g. in the template string `color: ${Colors.x};` there are 2 quasis, `color: ` and `;`, the `Colors.x` is an expression quasis.forEach((el, index) => { const expressionAfterQuasis = expressions[index]; - const isSecondToLastQuasis = index === quasis.length - 2; // Check if there are arrow functions inside the template string, since they can also have nested template string if (expressionAfterQuasis && expressionAfterQuasis.type === 'ArrowFunctionExpression') { const templateExpressions = j(expressionAfterQuasis).find(j.TemplateLiteral); // For every template string in the arrow function recursively replace colors for css vars - templateExpressions.forEach(ex => - replaceColorsForCssVarsInTemplateLiterals(j, localColorNames, ex.node, 2) - ); + templateExpressions.forEach(ex => replaceColorsForCssVarsInTemplateLiterals(j, localColorNames, ex.node)); } // Check if the expression is a MemberExpression (regular object property access) @@ -77,19 +73,16 @@ const replaceColorsForCssVarsInTemplateLiterals = ( if (!cssVar) return; - // Add the mapped css var at the end of the quasis (where the color expression is) - el.value.raw = el.value.raw + cssVar; + const nextQuasisValue = quasis[index + 1].value.raw; + // Append the mapped css var and the value of the next quasis to the end of the current quasis (where the color expression is) + el.value.raw = el.value.raw + cssVar + nextQuasisValue; - // Flag the color expression so that it is removed afterwards + // Since the color is mapped to the css var we don't need the expression anymore, so we flag it for removal later expressionsToRemoveIndexes.push(index); - if (isSecondToLastQuasis) { - const lastQuasisValue = quasis[index + 1].value.raw; - - // In case the next quasis is the last one, append it's value to the current value and mark the last quasis to be removed - el.value.raw = el.value.raw + lastQuasisValue; - quasisToRemoveIndexes.push(index + 1); - } + // The number of quasis always has to match the number of expressions + 1, since we've flagged the expression for removal we need to + // flag the next quasis for removal as well, we've already appended it's value to the current one so we don't lose information + quasisToRemoveIndexes.push(index + 1); } } }); diff --git a/codemods/v2.ts b/codemods/v2.ts deleted file mode 100644 index 26316fd92..000000000 --- a/codemods/v2.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { API, FileInfo } from 'jscodeshift'; - -const blockToWidth100Transform = require('./block-to-width-100'); - -module.exports = (file: FileInfo, api: API) => { - return blockToWidth100Transform(file, api); -}; From 99e23eb076014135e132dbec96be7e07e0c4957d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Malek?= Date: Fri, 25 Aug 2023 16:40:02 +0200 Subject: [PATCH 5/9] chore: add single quote config option to block codemod --- codemods/__tests__/block-to-width-100-test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codemods/__tests__/block-to-width-100-test.ts b/codemods/__tests__/block-to-width-100-test.ts index ea349f4b5..340e6446b 100644 --- a/codemods/__tests__/block-to-width-100-test.ts +++ b/codemods/__tests__/block-to-width-100-test.ts @@ -1,4 +1,4 @@ jest.autoMockOff(); const { defineTest } = require('jscodeshift/dist/testUtils'); -defineTest(__dirname, 'block-to-width-100', null, 'block-to-width-100', { parser: 'tsx' }); +defineTest(__dirname, 'block-to-width-100', { quote: 'single' }, 'block-to-width-100', { parser: 'tsx' }); From 698dae9a0af6fa164a588347ba2d6e1335bd0378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Malek?= Date: Fri, 25 Aug 2023 17:54:30 +0200 Subject: [PATCH 6/9] build: include codemods in build --- .eslintignore | 2 ++ .../color-in-JSX-multi-import.output.tsx | 5 ----- jest.config.js | 2 +- .../__testfixtures__/block-to-width-100.input.tsx | 0 .../__testfixtures__/block-to-width-100.output.tsx | 0 .../color-in-JSX-multi-import.input.tsx | 0 .../color-in-JSX-multi-import.output.tsx | 5 +++++ .../color-in-JSX-single-import.input.tsx | 0 .../color-in-JSX-single-import.output.tsx | 4 ++-- .../template-multi-quasis-even.input.tsx | 0 .../template-multi-quasis-even.output.tsx | 0 .../template-multi-quasis-odd.input.tsx | 0 .../template-multi-quasis-odd.output.tsx | 0 .../template-single-quasis.input.tsx | 0 .../template-single-quasis.output.tsx | 0 .../codemods}/__tests__/block-to-width-100-test.ts | 2 ++ .../codemods}/__tests__/colors-to-css-vars-test.ts | 0 {codemods => src/codemods}/block-to-width-100.ts | 0 {codemods => src/codemods}/colors-to-css-vars.ts | 12 ++++++------ tsconfig.json | 2 +- 20 files changed, 19 insertions(+), 15 deletions(-) delete mode 100644 codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.output.tsx rename {codemods => src/codemods}/__testfixtures__/block-to-width-100.input.tsx (100%) rename {codemods => src/codemods}/__testfixtures__/block-to-width-100.output.tsx (100%) rename {codemods => src/codemods}/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.input.tsx (100%) create mode 100644 src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.output.tsx rename {codemods => src/codemods}/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.input.tsx (100%) rename {codemods => src/codemods}/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.output.tsx (55%) rename {codemods => src/codemods}/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.input.tsx (100%) rename {codemods => src/codemods}/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.output.tsx (100%) rename {codemods => src/codemods}/__testfixtures__/colors-to-css-vars/template-multi-quasis-odd.input.tsx (100%) rename {codemods => src/codemods}/__testfixtures__/colors-to-css-vars/template-multi-quasis-odd.output.tsx (100%) rename {codemods => src/codemods}/__testfixtures__/colors-to-css-vars/template-single-quasis.input.tsx (100%) rename {codemods => src/codemods}/__testfixtures__/colors-to-css-vars/template-single-quasis.output.tsx (100%) rename {codemods => src/codemods}/__tests__/block-to-width-100-test.ts (76%) rename {codemods => src/codemods}/__tests__/colors-to-css-vars-test.ts (100%) rename {codemods => src/codemods}/block-to-width-100.ts (100%) rename {codemods => src/codemods}/colors-to-css-vars.ts (93%) diff --git a/.eslintignore b/.eslintignore index 1cd74997d..dfccc9844 100644 --- a/.eslintignore +++ b/.eslintignore @@ -12,3 +12,5 @@ assets/ fixtures/ src/icons/ + +src/codemods/ \ No newline at end of file diff --git a/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.output.tsx b/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.output.tsx deleted file mode 100644 index 147508193..000000000 --- a/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.output.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { CloseIcon } from '@freenow/wave'; - -export const CloseIconWrapper = () => ( - -); diff --git a/jest.config.js b/jest.config.js index 1ce4f6c43..1d94854b0 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,5 @@ module.exports = { - roots: ['/src', '/codemods'], + roots: ['/src'], transform: { '^.+\\.tsx?$': 'ts-jest', '^.+\\.svg$': '/svgTransform.js' diff --git a/codemods/__testfixtures__/block-to-width-100.input.tsx b/src/codemods/__testfixtures__/block-to-width-100.input.tsx similarity index 100% rename from codemods/__testfixtures__/block-to-width-100.input.tsx rename to src/codemods/__testfixtures__/block-to-width-100.input.tsx diff --git a/codemods/__testfixtures__/block-to-width-100.output.tsx b/src/codemods/__testfixtures__/block-to-width-100.output.tsx similarity index 100% rename from codemods/__testfixtures__/block-to-width-100.output.tsx rename to src/codemods/__testfixtures__/block-to-width-100.output.tsx diff --git a/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.input.tsx b/src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.input.tsx similarity index 100% rename from codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.input.tsx rename to src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.input.tsx diff --git a/src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.output.tsx b/src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.output.tsx new file mode 100644 index 000000000..f57ac1ae4 --- /dev/null +++ b/src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.output.tsx @@ -0,0 +1,5 @@ +import { CloseIcon } from '@freenow/wave'; + +export const CloseIconWrapper = () => ( + +); diff --git a/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.input.tsx b/src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.input.tsx similarity index 100% rename from codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.input.tsx rename to src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.input.tsx diff --git a/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.output.tsx b/src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.output.tsx similarity index 55% rename from codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.output.tsx rename to src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.output.tsx index b66b7cc48..357f19c13 100644 --- a/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.output.tsx +++ b/src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.output.tsx @@ -1,7 +1,7 @@ export const GhostIcon = () => ( - - + + ); diff --git a/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.input.tsx b/src/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.input.tsx similarity index 100% rename from codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.input.tsx rename to src/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.input.tsx diff --git a/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.output.tsx b/src/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.output.tsx similarity index 100% rename from codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.output.tsx rename to src/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-even.output.tsx diff --git a/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-odd.input.tsx b/src/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-odd.input.tsx similarity index 100% rename from codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-odd.input.tsx rename to src/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-odd.input.tsx diff --git a/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-odd.output.tsx b/src/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-odd.output.tsx similarity index 100% rename from codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-odd.output.tsx rename to src/codemods/__testfixtures__/colors-to-css-vars/template-multi-quasis-odd.output.tsx diff --git a/codemods/__testfixtures__/colors-to-css-vars/template-single-quasis.input.tsx b/src/codemods/__testfixtures__/colors-to-css-vars/template-single-quasis.input.tsx similarity index 100% rename from codemods/__testfixtures__/colors-to-css-vars/template-single-quasis.input.tsx rename to src/codemods/__testfixtures__/colors-to-css-vars/template-single-quasis.input.tsx diff --git a/codemods/__testfixtures__/colors-to-css-vars/template-single-quasis.output.tsx b/src/codemods/__testfixtures__/colors-to-css-vars/template-single-quasis.output.tsx similarity index 100% rename from codemods/__testfixtures__/colors-to-css-vars/template-single-quasis.output.tsx rename to src/codemods/__testfixtures__/colors-to-css-vars/template-single-quasis.output.tsx diff --git a/codemods/__tests__/block-to-width-100-test.ts b/src/codemods/__tests__/block-to-width-100-test.ts similarity index 76% rename from codemods/__tests__/block-to-width-100-test.ts rename to src/codemods/__tests__/block-to-width-100-test.ts index 340e6446b..e4aefa652 100644 --- a/codemods/__tests__/block-to-width-100-test.ts +++ b/src/codemods/__tests__/block-to-width-100-test.ts @@ -1,3 +1,5 @@ +// import { defineTest } from 'jscodeshift/dist/testUtils' + jest.autoMockOff(); const { defineTest } = require('jscodeshift/dist/testUtils'); diff --git a/codemods/__tests__/colors-to-css-vars-test.ts b/src/codemods/__tests__/colors-to-css-vars-test.ts similarity index 100% rename from codemods/__tests__/colors-to-css-vars-test.ts rename to src/codemods/__tests__/colors-to-css-vars-test.ts diff --git a/codemods/block-to-width-100.ts b/src/codemods/block-to-width-100.ts similarity index 100% rename from codemods/block-to-width-100.ts rename to src/codemods/block-to-width-100.ts diff --git a/codemods/colors-to-css-vars.ts b/src/codemods/colors-to-css-vars.ts similarity index 93% rename from codemods/colors-to-css-vars.ts rename to src/codemods/colors-to-css-vars.ts index c50844815..a82c1ce2b 100644 --- a/codemods/colors-to-css-vars.ts +++ b/src/codemods/colors-to-css-vars.ts @@ -1,4 +1,4 @@ -import { API, FileInfo, Identifier, JSCodeshift, MemberExpression, TemplateLiteral } from 'jscodeshift'; +import { API, FileInfo, Identifier, JSCodeshift, TemplateLiteral } from 'jscodeshift'; import { Options } from 'recast'; const ColorsToCssVariablesMap = { @@ -40,8 +40,8 @@ const replaceColorsForCssVarsInTemplateLiterals = ( localColorNames: string[], templateLiteral: TemplateLiteral ) => { - const quasis = templateLiteral.quasis; - const expressions = templateLiteral.expressions; + const { quasis } = templateLiteral; + const { expressions } = templateLiteral; const expressionsToRemoveIndexes: number[] = []; const quasisToRemoveIndexes: number[] = []; @@ -61,15 +61,15 @@ const replaceColorsForCssVarsInTemplateLiterals = ( // Check if the expression is a MemberExpression (regular object property access) if (expressionAfterQuasis && expressionAfterQuasis.type === 'MemberExpression') { - const expressionObject = (expressionAfterQuasis as MemberExpression).object as Identifier; + const expressionObject = expressionAfterQuasis.object as Identifier; // Identify if it's a usage of Colors const isColorsExpression = localColorNames.includes(expressionObject.name); if (isColorsExpression) { // Find the color being used - const color = ((expressionAfterQuasis as MemberExpression).property as Identifier).name; - const cssVar = ColorsToCssVariablesMap[color]; + const color = (expressionAfterQuasis.property as Identifier).name; + const cssVar: string = ColorsToCssVariablesMap[color]; if (!cssVar) return; diff --git a/tsconfig.json b/tsconfig.json index 1b12576c9..ddec86e8c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,5 +20,5 @@ ] }, "include": ["src/**/*"], - "exclude": ["src/**/docs", "**/node_modules"] + "exclude": ["src/**/docs", "**/node_modules", "src/codemods/__*"] } From 3ff89eadcfc3bdf35cf3d853740c499992b1807e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Malek?= Date: Fri, 25 Aug 2023 18:17:33 +0200 Subject: [PATCH 7/9] docs: add new codemod info in migrating docs --- docs/migrating.storybook.mdx | 38 +++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/docs/migrating.storybook.mdx b/docs/migrating.storybook.mdx index 3c267c3d2..f14aee04b 100644 --- a/docs/migrating.storybook.mdx +++ b/docs/migrating.storybook.mdx @@ -4,20 +4,7 @@ import { Meta } from '@storybook/blocks'; # Migrating -Migrating from one major version to the next with ease. - -## From v1 to v2 - -A codemod exists to upgrade your components for this version. - -```bash -npx jscodeshift -t node_modules/@freenow/wave/codemods/v2.ts path/to/src -``` - -### Button and TextButton - -The `block` property used to act as a shortcut to give the button components a width of 100%. In the future, use the `width` property -directly. It uses the styled-system variable, which is a lot more flexible than just the boolean flag. +Migrate to the next Wave major version with ease. ## Codemods @@ -28,3 +15,26 @@ previous major versions first. Beware that codemods are not 100% fool-proof and If you're working in a typescript environment, you need to add `--parser=tsx` to the command in each codemod command to allow jscodeshift to parse your typescript/jsx files. + +## From v1 to v2 + +Two codemods exist to upgrade your components for version 2. In order to apply the transformations in your project you simply need to run the +command for your desired codemod pointing to your project's source path. + +### Button and TextButton block property + +The `block` property used to act as a shortcut to give the button components a width of 100%. In the future, use the `width` property +directly. It uses the styled-system variable, which is a lot more flexible than just the boolean flag. + +```bash +npx jscodeshift -t node_modules/@freenow/wave/lib/cjs/codemods/block-to-width-100.js path/to/src +``` + +### Colors to CSS variables + +Our theme colors structure has changed significantly in this major. In order to use Wave colors in your project you should now use the CSS variables +that our theme brings. + +```bash +npx jscodeshift -t node_modules/@freenow/wave/lib/cjs/codemods/colors-to-css-vars.js path/to/src +``` From f81d034d704213cb35173d44c61b68b35129110b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Malek?= Date: Tue, 29 Aug 2023 11:12:55 +0200 Subject: [PATCH 8/9] docs: add semantic tokens recommendation in migration docs --- docs/migrating.storybook.mdx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/migrating.storybook.mdx b/docs/migrating.storybook.mdx index f14aee04b..ced28dba1 100644 --- a/docs/migrating.storybook.mdx +++ b/docs/migrating.storybook.mdx @@ -38,3 +38,6 @@ that our theme brings. ```bash npx jscodeshift -t node_modules/@freenow/wave/lib/cjs/codemods/colors-to-css-vars.js path/to/src ``` + +Disclaimer: This codemod transforms usages of `Colors` to our bare colors CSS variables to ensure we don't introduce breaking changes, that being said, +we recommend using semantic tokens instead as a best practice and offer a `getSemanticValue` API for just that. From 24e4f2b155df410f0325c3c97bb332f49657ddae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Malek?= Date: Tue, 29 Aug 2023 12:44:11 +0200 Subject: [PATCH 9/9] feat: pass print options to block codemod --- .../colors-to-css-vars/color-in-JSX-multi-import.output.tsx | 2 +- .../color-in-JSX-single-import.output.tsx | 4 ++-- src/codemods/block-to-width-100.ts | 6 ++++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.output.tsx b/src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.output.tsx index f57ac1ae4..147508193 100644 --- a/src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.output.tsx +++ b/src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-multi-import.output.tsx @@ -1,5 +1,5 @@ import { CloseIcon } from '@freenow/wave'; export const CloseIconWrapper = () => ( - + ); diff --git a/src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.output.tsx b/src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.output.tsx index 357f19c13..b66b7cc48 100644 --- a/src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.output.tsx +++ b/src/codemods/__testfixtures__/colors-to-css-vars/color-in-JSX-single-import.output.tsx @@ -1,7 +1,7 @@ export const GhostIcon = () => ( - - + + ); diff --git a/src/codemods/block-to-width-100.ts b/src/codemods/block-to-width-100.ts index 2e10cda87..68d921cda 100644 --- a/src/codemods/block-to-width-100.ts +++ b/src/codemods/block-to-width-100.ts @@ -1,8 +1,10 @@ import { API, FileInfo } from 'jscodeshift'; +import { Options } from 'recast'; -module.exports = (file: FileInfo, api: API) => { +module.exports = (file: FileInfo, api: API, options: Options) => { const j = api.jscodeshift; const ast = j(file.source); + const printOptions = options ?? { quote: 'single' }; const localButtonNames = []; @@ -53,5 +55,5 @@ module.exports = (file: FileInfo, api: API) => { }); }); - return ast.toSource({ quote: 'single' }); + return ast.toSource(printOptions); };