diff --git a/polaris-migrator/README.md b/polaris-migrator/README.md index 1ce3d472299..16558c12e5c 100644 --- a/polaris-migrator/README.md +++ b/polaris-migrator/README.md @@ -155,24 +155,63 @@ Replace legacy Typography functions and hardcoded lengths with Polaris custom pr npx @shopify/polaris-migrator styles-tokenize-fonts ``` -### `styles-tokenize-fonts` +### `styles-tokenize-shape` -Replace lengths (`px`, `rem`) and legacy Sass functions (`rem()`,`border()`, `border-width()`, `border-radius()`) in border declarations (`border`, `border-width`, and `border-radius`) with the corresponding Polaris [shape](https://polaris.shopify.com/tokens/shape) token. +Replace usage of the legacy Sass `rem()` function and hard-coded lengths (`px`, `rem`) in `border`, `border-width`, and `border-radius` declarations with corresponding Polaris [shape](https://polaris.shopify.com/tokens/shape) token. ```diff - border: 1px solid transparent; + border: var(--p-border-width-1) solid transparent; +- border-width: 0.0625rem; ++ border-width: var(--p-border-width-1); + +- border-radius: 4px; ++ border-radius: var(--p-border-radius-1); +``` + +```sh +npx @shopify/polaris-migrator replace-border-declarations +``` + +### `sass-replace-border` + +Replace usage of the legacy Sass `border()`) function in `border` declarations with corresponding Polaris [shape](https://polaris.shopify.com/tokens/shape) token. + +```diff - border: border(); + border: var(--p-border-base); -- border-width: 0.0625rem; +- border: border(divider); ++ border: var(--p-border-divider); +``` + +```sh +npx @shopify/polaris-migrator sass-replace-border +``` + +### `sass-replace-border-width` + +Replace usage of the legacy Sass `border-width()`) function in `border` and `border-width` declarations with corresponding Polaris [shape](https://polaris.shopify.com/tokens/shape) tokens. + +```diff +- border-width: border-width(); + border-width: var(--p-border-width-1); - border-width: border-width(thick); + border-width: var(--p-border-width-2); +``` -- border-radius: 4px; +```sh +npx @shopify/polaris-migrator sass-replace-border-width +``` + +### `sass-replace-border-radius` + +Replace usage of the legacy Sass `border-radius()`) function in `border-radius` declarations with corresponding Polaris [shape](https://polaris.shopify.com/tokens/shape) tokens. + +```diff +- border-radius: border-radius(); + border-radius: var(--p-border-radius-1); - border-radius: border-radius(large); @@ -180,7 +219,7 @@ Replace lengths (`px`, `rem`) and legacy Sass functions (`rem()`,`border()`, `bo ``` ```sh -npx @shopify/polaris-migrator styles-tokenize-fonts +npx @shopify/polaris-migrator sass-replace-border-radius ``` ### `scss-replace-z-index` diff --git a/polaris-migrator/src/migrations/sass-replace-border-radius/sass-replace-border-radius.ts b/polaris-migrator/src/migrations/sass-replace-border-radius/sass-replace-border-radius.ts new file mode 100644 index 00000000000..d032b5b6856 --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border-radius/sass-replace-border-radius.ts @@ -0,0 +1,128 @@ +import type {FileInfo, API, Options} from 'jscodeshift'; +import postcss, {Plugin} from 'postcss'; +import valueParser from 'postcss-value-parser'; + +import {POLARIS_MIGRATOR_COMMENT} from '../../constants'; +import { + getFunctionArgs, + isNumericOperator, + isSassFunction, + isTransformableLength, + namespace, + NamespaceOptions, + toTransformablePx, + StopWalkingFunctionNodes, + createInlineComment, +} from '../../utilities/sass'; +import {isKeyOf} from '../../utilities/type-guards'; + +export default function sassReplaceBorderRadius( + fileInfo: FileInfo, + _: API, + options: Options, +) { + return postcss(plugin(options)).process(fileInfo.source, { + syntax: require('postcss-scss'), + }).css; +} + +const processed = Symbol('processed'); + +interface PluginOptions extends Options, NamespaceOptions {} + +const plugin = (options: PluginOptions = {}): Plugin => { + const namespacedBorderRadius = namespace('border-radius', options); + + return { + postcssPlugin: 'sass-replace-border-radius', + Declaration(decl) { + // @ts-expect-error - Skip if processed so we don't process it again + if (decl[processed]) return; + + if (!borderRadiusProps.has(decl.prop)) return; + + /** + * A collection of transformable values to migrate (e.g. decl lengths, functions, etc.) + * + * Note: This is evaluated at the end of each visitor execution to determine whether + * or not to replace the declaration or insert a comment. + */ + const targets: {replaced: boolean}[] = []; + let hasNumericOperator = false; + const parsedValue = valueParser(decl.value); + + handleBorderRadiusProps(); + + if (targets.some(({replaced}) => !replaced || hasNumericOperator)) { + // Insert comment if the declaration value contains calculations + decl.before( + createInlineComment(POLARIS_MIGRATOR_COMMENT, {prose: true}), + ); + decl.before( + createInlineComment(`${decl.prop}: ${parsedValue.toString()};`), + ); + } else { + decl.value = parsedValue.toString(); + } + + // + // Handler + // + + function handleBorderRadiusProps() { + parsedValue.walk((node) => { + if (isNumericOperator(node)) { + hasNumericOperator = true; + return; + } + + if (node.type === 'function') { + if (isSassFunction(namespacedBorderRadius, node)) { + targets.push({replaced: false}); + + const args = getFunctionArgs(node); + + if (!(args.length === 0 || args.length === 1)) return; + + // `border-radius()` args reference: + // https://github.com/shopify/polaris/blob/2b14c0b60097f75d21df7eaa744dfaf84f8f53f7/documentation/guides/legacy-polaris-v8-public-api.scss#L655 + const value = args[0] ?? 'base'; + + if (!isKeyOf(borderRadiusFunctionMap, value)) return; + + node.value = 'var'; + node.nodes = [ + { + type: 'word', + value: borderRadiusFunctionMap[value], + sourceIndex: node.nodes[0]?.sourceIndex ?? 0, + sourceEndIndex: borderRadiusFunctionMap[value].length, + }, + ]; + + targets[targets.length - 1]!.replaced = true; + } + + return StopWalkingFunctionNodes; + } + }); + } + }, + }; +}; + +const borderRadiusProps = new Set([ + 'border-radius', + 'border-top-left-radius', + 'border-top-right-radius', + 'border-bottom-left-radius', + 'border-bottom-right-radius', +]); + +const borderRadiusFunctionMap = { + '': '--p-border-radius-base', + base: '--p-border-radius-base', + "'base'": '--p-border-radius-base', + large: '--p-border-radius-large', + "'large'": '--p-border-radius-large', +} as const; diff --git a/polaris-migrator/src/migrations/sass-replace-border-radius/tests/sass-replace-border-radius.input.scss b/polaris-migrator/src/migrations/sass-replace-border-radius/tests/sass-replace-border-radius.input.scss new file mode 100644 index 00000000000..92bf9a6ff91 --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border-radius/tests/sass-replace-border-radius.input.scss @@ -0,0 +1,17 @@ +/* stylelint-disable */ + +.border-radius { + /* Migrate */ + border-radius: border-radius(); + border-radius: border-radius(base); + border-radius: border-radius(large); + + /* Ignore */ + border-radius: calc(border-radius(base) * 2); + border-radius: calc(border-radius() * rem(1px)); + + /* Comment */ + border-radius: border-radius(base) * 2; + border-radius: border-radius() * rem(1px); + border-top-right-radius: border-radius() * rem(4px); +} diff --git a/polaris-migrator/src/migrations/sass-replace-border-radius/tests/sass-replace-border-radius.output.scss b/polaris-migrator/src/migrations/sass-replace-border-radius/tests/sass-replace-border-radius.output.scss new file mode 100644 index 00000000000..3c93d56ccd4 --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border-radius/tests/sass-replace-border-radius.output.scss @@ -0,0 +1,23 @@ +/* stylelint-disable */ + +.border-radius { + /* Migrate */ + border-radius: var(--p-border-radius-base); + border-radius: var(--p-border-radius-base); + border-radius: var(--p-border-radius-large); + + /* Ignore */ + border-radius: calc(border-radius(base) * 2); + border-radius: calc(border-radius() * rem(1px)); + + /* Comment */ + // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. + // border-radius: var(--p-border-radius-base) * 2; + border-radius: border-radius(base) * 2; + // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. + // border-radius: var(--p-border-radius-base) * rem(1px); + border-radius: border-radius() * rem(1px); + // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. + // border-top-right-radius: var(--p-border-radius-base) * rem(4px); + border-top-right-radius: border-radius() * rem(4px); +} diff --git a/polaris-migrator/src/migrations/replace-border-declarations/tests/replace-border-declarations.test.ts b/polaris-migrator/src/migrations/sass-replace-border-radius/tests/sass-replace-border-radius.test.ts similarity index 71% rename from polaris-migrator/src/migrations/replace-border-declarations/tests/replace-border-declarations.test.ts rename to polaris-migrator/src/migrations/sass-replace-border-radius/tests/sass-replace-border-radius.test.ts index c76267cc0e8..22388109c99 100644 --- a/polaris-migrator/src/migrations/replace-border-declarations/tests/replace-border-declarations.test.ts +++ b/polaris-migrator/src/migrations/sass-replace-border-radius/tests/sass-replace-border-radius.test.ts @@ -1,7 +1,7 @@ import {check} from '../../../utilities/testUtils'; -const migration = 'replace-border-declarations'; -const fixtures = ['replace-border-declarations', 'with-namespace']; +const migration = 'sass-replace-border-radius'; +const fixtures = ['sass-replace-border-radius', 'with-namespace']; for (const fixture of fixtures) { check(__dirname, { diff --git a/polaris-migrator/src/migrations/sass-replace-border-radius/tests/with-namespace.input.scss b/polaris-migrator/src/migrations/sass-replace-border-radius/tests/with-namespace.input.scss new file mode 100644 index 00000000000..83524fb6ab8 --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border-radius/tests/with-namespace.input.scss @@ -0,0 +1,21 @@ +/* stylelint-disable */ +@use 'global-styles/legacy-polaris-v8'; + +.border-radius { + /* Migrate */ + border-radius: legacy-polaris-v8.border-radius(); + border-radius: legacy-polaris-v8.border-radius(base); + border-radius: legacy-polaris-v8.border-radius(large); + + /* Ignore */ + border-radius: calc(legacy-polaris-v8.border-radius(base) * 2); + border-radius: calc( + legacy-polaris-v8.border-radius() * legacy-polaris-v8.rem(1px) + ); + + /* Comment */ + border-radius: legacy-polaris-v8.border-radius(base) * 2; + border-radius: legacy-polaris-v8.border-radius() * legacy-polaris-v8.rem(1px); + border-top-right-radius: legacy-polaris-v8.border-radius() * + legacy-polaris-v8.rem(4px); +} diff --git a/polaris-migrator/src/migrations/sass-replace-border-radius/tests/with-namespace.output.scss b/polaris-migrator/src/migrations/sass-replace-border-radius/tests/with-namespace.output.scss new file mode 100644 index 00000000000..8f1642d4c58 --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border-radius/tests/with-namespace.output.scss @@ -0,0 +1,27 @@ +/* stylelint-disable */ +@use 'global-styles/legacy-polaris-v8'; + +.border-radius { + /* Migrate */ + border-radius: var(--p-border-radius-base); + border-radius: var(--p-border-radius-base); + border-radius: var(--p-border-radius-large); + + /* Ignore */ + border-radius: calc(legacy-polaris-v8.border-radius(base) * 2); + border-radius: calc( + legacy-polaris-v8.border-radius() * legacy-polaris-v8.rem(1px) + ); + + /* Comment */ + // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. + // border-radius: var(--p-border-radius-base) * 2; + border-radius: legacy-polaris-v8.border-radius(base) * 2; + // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. + // border-radius: var(--p-border-radius-base) * legacy-polaris-v8.rem(1px); + border-radius: legacy-polaris-v8.border-radius() * legacy-polaris-v8.rem(1px); + // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. + // border-top-right-radius: var(--p-border-radius-base) * legacy-polaris-v8.rem(4px); + border-top-right-radius: legacy-polaris-v8.border-radius() * + legacy-polaris-v8.rem(4px); +} diff --git a/polaris-migrator/src/migrations/sass-replace-border-width/sass-replace-border-width.ts b/polaris-migrator/src/migrations/sass-replace-border-width/sass-replace-border-width.ts new file mode 100644 index 00000000000..d39d9162f02 --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border-width/sass-replace-border-width.ts @@ -0,0 +1,133 @@ +import type {FileInfo, API, Options} from 'jscodeshift'; +import postcss, {Plugin} from 'postcss'; +import valueParser from 'postcss-value-parser'; + +import {POLARIS_MIGRATOR_COMMENT} from '../../constants'; +import { + getFunctionArgs, + isSassFunction, + namespace, + isNumericOperator, + NamespaceOptions, + StopWalkingFunctionNodes, + createInlineComment, +} from '../../utilities/sass'; +import {isKeyOf} from '../../utilities/type-guards'; + +export default function sassReplaceBorderWidth( + fileInfo: FileInfo, + _: API, + options: Options, +) { + return postcss(plugin(options)).process(fileInfo.source, { + syntax: require('postcss-scss'), + }).css; +} + +const processed = Symbol('processed'); + +interface PluginOptions extends Options, NamespaceOptions {} + +const plugin = (options: PluginOptions = {}): Plugin => { + const namespacedBorderWidth = namespace('border-width', options); + + return { + postcssPlugin: 'sass-replace-border-width', + Declaration(decl) { + // @ts-expect-error - Skip if processed so we don't process it again + if (decl[processed]) return; + + if (!borderProps.has(decl.prop)) return; + + /** + * A collection of transformable values to migrate (e.g. decl lengths, functions, etc.) + * + * Note: This is evaluated at the end of each visitor execution to determine whether + * or not to replace the declaration or insert a comment. + */ + const targets: {replaced: boolean}[] = []; + let hasNumericOperator = false; + const parsedValue = valueParser(decl.value); + + handleBorderProps(); + + if (targets.some(({replaced}) => !replaced || hasNumericOperator)) { + // Insert comment if the declaration value contains calculations + decl.before( + createInlineComment(POLARIS_MIGRATOR_COMMENT, {prose: true}), + ); + decl.before( + createInlineComment(`${decl.prop}: ${parsedValue.toString()};`), + ); + } else { + decl.value = parsedValue.toString(); + } + + // + // Handlers + // + + function handleBorderProps() { + parsedValue.walk((node) => { + if (isNumericOperator(node)) { + hasNumericOperator = true; + return; + } + + if (node.type === 'function') { + if (isSassFunction(namespacedBorderWidth, node)) { + targets.push({replaced: false}); + + const args = getFunctionArgs(node); + + if (!(args.length === 0 || args.length === 1)) return; + + // `border-width()` args reference: + // https://github.com/shopify/polaris/blob/2b14c0b60097f75d21df7eaa744dfaf84f8f53f7/documentation/guides/legacy-polaris-v8-public-api.scss#L616 + const value = args[0] ?? 'base'; + + if (!isKeyOf(borderWidthFunctionMap, value)) return; + + node.value = 'var'; + node.nodes = [ + { + type: 'word', + value: borderWidthFunctionMap[value], + sourceIndex: node.nodes[0]?.sourceIndex ?? 0, + sourceEndIndex: borderWidthFunctionMap[value].length, + }, + ]; + + targets[targets.length - 1]!.replaced = true; + } + + return StopWalkingFunctionNodes; + } + }); + } + }, + }; +}; + +const borderProps = new Set([ + 'border', + 'border-top', + 'border-right', + 'border-bottom', + 'border-left', + 'border-width', + 'border-top-width', + 'border-right-width', + 'border-bottom-width', + 'border-left-width', +]); + +const borderWidthFunctionMap = { + '': '--p-border-width-1', + base: '--p-border-width-1', + "'base'": '--p-border-width-1', + thick: '--p-border-width-2', + "'thick'": '--p-border-width-2', + thicker: '--p-border-width-3', + "'thicker'": '--p-border-width-3', +} as const; diff --git a/polaris-migrator/src/migrations/sass-replace-border-width/tests/sass-replace-border-width.input.scss b/polaris-migrator/src/migrations/sass-replace-border-width/tests/sass-replace-border-width.input.scss new file mode 100644 index 00000000000..4199d2e9c82 --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border-width/tests/sass-replace-border-width.input.scss @@ -0,0 +1,15 @@ +/* stylelint-disable */ + +.border { + /* Migrate */ + border: border-width() solid var(--p-border-subdued); + border: border-width(base) solid var(--p-border-subdued); + border: border-width(thick) solid var(--p-border-subdued); + border: border-width(thicker) solid var(--p-border-subdued); + border-width: border-width('thicker'); + + /* Ignore */ + border-width: calc(-1 * border-width()); + border-width: calc($var * border-width()); + border-width: rem(1px) rem(10px - border-width()); +} diff --git a/polaris-migrator/src/migrations/sass-replace-border-width/tests/sass-replace-border-width.output.scss b/polaris-migrator/src/migrations/sass-replace-border-width/tests/sass-replace-border-width.output.scss new file mode 100644 index 00000000000..eedfbe975ea --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border-width/tests/sass-replace-border-width.output.scss @@ -0,0 +1,15 @@ +/* stylelint-disable */ + +.border { + /* Migrate */ + border: var(--p-border-width-1) solid var(--p-border-subdued); + border: var(--p-border-width-1) solid var(--p-border-subdued); + border: var(--p-border-width-2) solid var(--p-border-subdued); + border: var(--p-border-width-3) solid var(--p-border-subdued); + border-width: var(--p-border-width-3); + + /* Ignore */ + border-width: calc(-1 * border-width()); + border-width: calc($var * border-width()); + border-width: rem(1px) rem(10px - border-width()); +} diff --git a/polaris-migrator/src/migrations/sass-replace-border-width/tests/sass-replace-border-width.test.ts b/polaris-migrator/src/migrations/sass-replace-border-width/tests/sass-replace-border-width.test.ts new file mode 100644 index 00000000000..99b5baa4b1d --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border-width/tests/sass-replace-border-width.test.ts @@ -0,0 +1,17 @@ +import {check} from '../../../utilities/testUtils'; + +const migration = 'sass-replace-border-width'; +const fixtures = ['sass-replace-border-width', 'with-namespace']; + +for (const fixture of fixtures) { + check(__dirname, { + fixture, + migration, + extension: 'scss', + options: { + namespace: fixture.includes('with-namespace') + ? 'legacy-polaris-v8' + : undefined, + }, + }); +} diff --git a/polaris-migrator/src/migrations/sass-replace-border-width/tests/with-namespace.input.scss b/polaris-migrator/src/migrations/sass-replace-border-width/tests/with-namespace.input.scss new file mode 100644 index 00000000000..c38b7116114 --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border-width/tests/with-namespace.input.scss @@ -0,0 +1,17 @@ +/* stylelint-disable */ +@use 'global-styles/legacy-polaris-v8'; + +.border { + /* Migrate */ + border: legacy-polaris-v8.border-width() solid var(--p-border-subdued); + border: legacy-polaris-v8.border-width(base) solid var(--p-border-subdued); + border: legacy-polaris-v8.border-width(thick) solid var(--p-border-subdued); + border: legacy-polaris-v8.border-width(thicker) solid var(--p-border-subdued); + border-width: legacy-polaris-v8.border-width('thicker'); + + /* Ignore */ + border-width: calc(-1 * legacy-polaris-v8.border-width()); + border-width: calc($var * legacy-polaris-v8.border-width()); + border-width: legacy-polaris-v8.rem(1px) + legacy-polaris-v8.rem(10px - legacy-polaris-v8.border-width()); +} diff --git a/polaris-migrator/src/migrations/sass-replace-border-width/tests/with-namespace.output.scss b/polaris-migrator/src/migrations/sass-replace-border-width/tests/with-namespace.output.scss new file mode 100644 index 00000000000..4f673b07f1f --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border-width/tests/with-namespace.output.scss @@ -0,0 +1,17 @@ +/* stylelint-disable */ +@use 'global-styles/legacy-polaris-v8'; + +.border { + /* Migrate */ + border: var(--p-border-width-1) solid var(--p-border-subdued); + border: var(--p-border-width-1) solid var(--p-border-subdued); + border: var(--p-border-width-2) solid var(--p-border-subdued); + border: var(--p-border-width-3) solid var(--p-border-subdued); + border-width: var(--p-border-width-3); + + /* Ignore */ + border-width: calc(-1 * legacy-polaris-v8.border-width()); + border-width: calc($var * legacy-polaris-v8.border-width()); + border-width: legacy-polaris-v8.rem(1px) + legacy-polaris-v8.rem(10px - legacy-polaris-v8.border-width()); +} diff --git a/polaris-migrator/src/migrations/sass-replace-border/sass-replace-border.ts b/polaris-migrator/src/migrations/sass-replace-border/sass-replace-border.ts new file mode 100644 index 00000000000..2ac0c2ec4b1 --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border/sass-replace-border.ts @@ -0,0 +1,121 @@ +import type {FileInfo, API, Options} from 'jscodeshift'; +import postcss, {Plugin} from 'postcss'; +import valueParser from 'postcss-value-parser'; + +import {POLARIS_MIGRATOR_COMMENT} from '../../constants'; +import { + getFunctionArgs, + isSassFunction, + namespace, + NamespaceOptions, + createInlineComment, +} from '../../utilities/sass'; +import {isKeyOf} from '../../utilities/type-guards'; + +export default function replaceBorderDeclarations( + fileInfo: FileInfo, + _: API, + options: Options, +) { + return postcss(plugin(options)).process(fileInfo.source, { + syntax: require('postcss-scss'), + }).css; +} + +const processed = Symbol('processed'); + +interface PluginOptions extends Options, NamespaceOptions {} + +const plugin = (options: PluginOptions = {}): Plugin => { + const namespacedBorder = namespace('border', options); + + return { + postcssPlugin: 'sass-replace-border', + Declaration(decl) { + // @ts-expect-error - Skip if processed so we don't process it again + if (decl[processed]) return; + + if (!borderProps.has(decl.prop)) return; + + /** + * A collection of transformable values to migrate (e.g. decl lengths, functions, etc.) + * + * Note: This is evaluated at the end of each visitor execution to determine whether + * or not to replace the declaration or insert a comment. + */ + const targets: {replaced: boolean}[] = []; + const parsedValue = valueParser(decl.value); + + handleBorderProps(); + + if (targets.some(({replaced}) => !replaced)) { + // Insert comment if the declaration value contains calculations + decl.before( + createInlineComment(POLARIS_MIGRATOR_COMMENT, {prose: true}), + ); + decl.before( + createInlineComment(`${decl.prop}: ${parsedValue.toString()};`), + ); + } else { + decl.value = parsedValue.toString(); + } + + // + // Handlers + // + + function handleBorderProps() { + parsedValue.walk((node) => { + if ( + node.type === 'function' && + isSassFunction(namespacedBorder, node) + ) { + targets.push({replaced: false}); + + const args = getFunctionArgs(node); + + if (!(args.length === 0 || args.length === 1)) return; + + // `border()` args reference: + // https://github.com/shopify/polaris/blob/2b14c0b60097f75d21df7eaa744dfaf84f8f53f7/documentation/guides/legacy-polaris-v8-public-api.scss#L641 + const value = args[0] ?? 'base'; + + if (!isKeyOf(borderFunctionMap, value)) return; + + node.value = 'var'; + node.nodes = [ + { + type: 'word', + value: borderFunctionMap[value], + sourceIndex: node.nodes[0]?.sourceIndex ?? 0, + sourceEndIndex: borderFunctionMap[value].length, + }, + ]; + + targets[targets.length - 1]!.replaced = true; + } + }); + } + }, + }; +}; + +const borderProps = new Set([ + 'border', + 'border-top', + 'border-right', + 'border-bottom', + 'border-left', +]); + +const borderFunctionMap = { + '': '--p-border-base', + base: '--p-border-base', + "'base'": '--p-border-base', + dark: '--p-border-dark', + "'dark'": '--p-border-dark', + transparent: '--p-border-transparent', + "'transparent'": '--p-border-transparent', + divider: ' --p-border-divider', + "'divider'": ' --p-border-divider', +} as const; diff --git a/polaris-migrator/src/migrations/sass-replace-border/tests/sass-replace-border.input.scss b/polaris-migrator/src/migrations/sass-replace-border/tests/sass-replace-border.input.scss new file mode 100644 index 00000000000..9633ef3398b --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border/tests/sass-replace-border.input.scss @@ -0,0 +1,13 @@ +/* stylelint-disable */ + +.border { + border: border(); + border: border(base); + border: border('base'); + border: border(dark); + border: border('dark'); + border-bottom: border(transparent); + border: border('transparent'); + border: border(divider); + border-left: border('divider'); +} diff --git a/polaris-migrator/src/migrations/sass-replace-border/tests/sass-replace-border.output.scss b/polaris-migrator/src/migrations/sass-replace-border/tests/sass-replace-border.output.scss new file mode 100644 index 00000000000..b18004d14a5 --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border/tests/sass-replace-border.output.scss @@ -0,0 +1,13 @@ +/* stylelint-disable */ + +.border { + border: var(--p-border-base); + border: var(--p-border-base); + border: var(--p-border-base); + border: var(--p-border-dark); + border: var(--p-border-dark); + border-bottom: var(--p-border-transparent); + border: var(--p-border-transparent); + border: var(--p-border-divider); + border-left: var(--p-border-divider); +} diff --git a/polaris-migrator/src/migrations/sass-replace-border/tests/sass-replace-border.test.ts b/polaris-migrator/src/migrations/sass-replace-border/tests/sass-replace-border.test.ts new file mode 100644 index 00000000000..c5147b95d2d --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border/tests/sass-replace-border.test.ts @@ -0,0 +1,17 @@ +import {check} from '../../../utilities/testUtils'; + +const migration = 'sass-replace-border'; +const fixtures = ['sass-replace-border', 'with-namespace']; + +for (const fixture of fixtures) { + check(__dirname, { + fixture, + migration, + extension: 'scss', + options: { + namespace: fixture.includes('with-namespace') + ? 'legacy-polaris-v8' + : undefined, + }, + }); +} diff --git a/polaris-migrator/src/migrations/sass-replace-border/tests/with-namespace.input.scss b/polaris-migrator/src/migrations/sass-replace-border/tests/with-namespace.input.scss new file mode 100644 index 00000000000..160068c85d2 --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border/tests/with-namespace.input.scss @@ -0,0 +1,15 @@ +/* stylelint-disable */ + +@use 'global-styles/legacy-polaris-v8'; + +.border { + border: legacy-polaris-v8.border(); + border: legacy-polaris-v8.border(base); + border: legacy-polaris-v8.border('base'); + border: legacy-polaris-v8.border(dark); + border: legacy-polaris-v8.border('dark'); + border-bottom: legacy-polaris-v8.border(transparent); + border: legacy-polaris-v8.border('transparent'); + border: legacy-polaris-v8.border(divider); + border-left: legacy-polaris-v8.border('divider'); +} diff --git a/polaris-migrator/src/migrations/sass-replace-border/tests/with-namespace.output.scss b/polaris-migrator/src/migrations/sass-replace-border/tests/with-namespace.output.scss new file mode 100644 index 00000000000..749761f4ea1 --- /dev/null +++ b/polaris-migrator/src/migrations/sass-replace-border/tests/with-namespace.output.scss @@ -0,0 +1,15 @@ +/* stylelint-disable */ + +@use 'global-styles/legacy-polaris-v8'; + +.border { + border: var(--p-border-base); + border: var(--p-border-base); + border: var(--p-border-base); + border: var(--p-border-dark); + border: var(--p-border-dark); + border-bottom: var(--p-border-transparent); + border: var(--p-border-transparent); + border: var(--p-border-divider); + border-left: var(--p-border-divider); +} diff --git a/polaris-migrator/src/migrations/replace-border-declarations/replace-border-declarations.ts b/polaris-migrator/src/migrations/styles-tokenize-shape/styles-tokenize-shape.ts similarity index 61% rename from polaris-migrator/src/migrations/replace-border-declarations/replace-border-declarations.ts rename to polaris-migrator/src/migrations/styles-tokenize-shape/styles-tokenize-shape.ts index 5dcf73b8ede..0f34f13cb33 100644 --- a/polaris-migrator/src/migrations/replace-border-declarations/replace-border-declarations.ts +++ b/polaris-migrator/src/migrations/styles-tokenize-shape/styles-tokenize-shape.ts @@ -16,7 +16,7 @@ import { } from '../../utilities/sass'; import {isKeyOf} from '../../utilities/type-guards'; -export default function replaceBorderDeclarations( +export default function stylesTokenizeShape( fileInfo: FileInfo, _: API, options: Options, @@ -32,12 +32,9 @@ interface PluginOptions extends Options, NamespaceOptions {} const plugin = (options: PluginOptions = {}): Plugin => { const namespacedRem = namespace('rem', options); - const namespacedBorder = namespace('border', options); - const namespacedBorderWidth = namespace('border-width', options); - const namespacedBorderRadius = namespace('border-radius', options); return { - postcssPlugin: 'replace-border-declarations', + postcssPlugin: 'styles-tokenize-shape', Declaration(decl) { // @ts-expect-error - Skip if processed so we don't process it again if (decl[processed]) return; @@ -129,58 +126,6 @@ const plugin = (options: PluginOptions = {}): Plugin => { targets[targets.length - 1]!.replaced = true; } - if (isSassFunction(namespacedBorder, node)) { - targets.push({replaced: false}); - - const args = getFunctionArgs(node); - - if (!(args.length === 0 || args.length === 1)) return; - - // `border()` args reference: - // https://github.com/shopify/polaris/blob/2b14c0b60097f75d21df7eaa744dfaf84f8f53f7/documentation/guides/legacy-polaris-v8-public-api.scss#L641 - const value = args[0] ?? 'base'; - - if (!isKeyOf(borderFunctionMap, value)) return; - - node.value = 'var'; - node.nodes = [ - { - type: 'word', - value: borderFunctionMap[value], - sourceIndex: node.nodes[0]?.sourceIndex ?? 0, - sourceEndIndex: borderFunctionMap[value].length, - }, - ]; - - targets[targets.length - 1]!.replaced = true; - } - - if (isSassFunction(namespacedBorderWidth, node)) { - targets.push({replaced: false}); - - const args = getFunctionArgs(node); - - if (!(args.length === 0 || args.length === 1)) return; - - // `border-width()` args reference: - // https://github.com/shopify/polaris/blob/2b14c0b60097f75d21df7eaa744dfaf84f8f53f7/documentation/guides/legacy-polaris-v8-public-api.scss#L616 - const value = args[0] ?? 'base'; - - if (!isKeyOf(borderWidthFunctionMap, value)) return; - - node.value = 'var'; - node.nodes = [ - { - type: 'word', - value: borderWidthFunctionMap[value], - sourceIndex: node.nodes[0]?.sourceIndex ?? 0, - sourceEndIndex: borderWidthFunctionMap[value].length, - }, - ]; - - targets[targets.length - 1]!.replaced = true; - } - return StopWalkingFunctionNodes; } }); @@ -238,32 +183,6 @@ const plugin = (options: PluginOptions = {}): Plugin => { targets[targets.length - 1]!.replaced = true; } - if (isSassFunction(namespacedBorderRadius, node)) { - targets.push({replaced: false}); - - const args = getFunctionArgs(node); - - if (!(args.length === 0 || args.length === 1)) return; - - // `border-radius()` args reference: - // https://github.com/shopify/polaris/blob/2b14c0b60097f75d21df7eaa744dfaf84f8f53f7/documentation/guides/legacy-polaris-v8-public-api.scss#L655 - const value = args[0] ?? 'base'; - - if (!isKeyOf(borderRadiusFunctionMap, value)) return; - - node.value = 'var'; - node.nodes = [ - { - type: 'word', - value: borderRadiusFunctionMap[value], - sourceIndex: node.nodes[0]?.sourceIndex ?? 0, - sourceEndIndex: borderRadiusFunctionMap[value].length, - }, - ]; - - targets[targets.length - 1]!.replaced = true; - } - return StopWalkingFunctionNodes; } }); @@ -305,43 +224,12 @@ const borderWidthLengthMap = { const borderRadiusLengthMap = { '2px': '--p-border-radius-05', - '3px': '--p-border-radius-base', '4px': '--p-border-radius-1', - '6px': '--p-border-radius-large', '8px': '--p-border-radius-2', '12px': '--p-border-radius-3', '16px': '--p-border-radius-4', '20px': '--p-border-radius-5', '30px': '--p-border-radius-6', - '50%': '--p- border-radius-half', -} as const; - -const borderFunctionMap = { - '': '--p-border-base', - base: '--p-border-base', - "'base'": '--p-border-base', - dark: '--p-border-dark', - "'dark'": '--p-border-dark', - transparent: '--p-border-transparent', - "'transparent'": '--p-border-transparent', - divider: ' --p-border-divider', - "'divider'": ' --p-border-divider', -} as const; - -const borderWidthFunctionMap = { - '': '--p-border-width-1', - base: '--p-border-width-1', - "'base'": '--p-border-width-1', - thick: '--p-border-width-2', - "'thick'": '--p-border-width-2', - thicker: '--p-border-width-3', - "'thicker'": '--p-border-width-3', -} as const; - -const borderRadiusFunctionMap = { - '': '--p-border-radius-base', - base: '--p-border-radius-base', - "'base'": '--p-border-radius-base', - large: '--p-border-radius-large', - "'large'": '--p-border-radius-large', + '3px': '--p-border-radius-base', + '6px': '--p-border-radius-large', } as const; diff --git a/polaris-migrator/src/migrations/replace-border-declarations/tests/replace-border-declarations.input.scss b/polaris-migrator/src/migrations/styles-tokenize-shape/tests/styles-tokenize-shape.input.scss similarity index 65% rename from polaris-migrator/src/migrations/replace-border-declarations/tests/replace-border-declarations.input.scss rename to polaris-migrator/src/migrations/styles-tokenize-shape/tests/styles-tokenize-shape.input.scss index 535e4e39989..f6a88c5d3e4 100644 --- a/polaris-migrator/src/migrations/replace-border-declarations/tests/replace-border-declarations.input.scss +++ b/polaris-migrator/src/migrations/styles-tokenize-shape/tests/styles-tokenize-shape.input.scss @@ -55,32 +55,6 @@ border-width: rem(10px) -1px; border-width: rem(10px) + 1px; border-width: rem($var * 1px); - - /* --- BORDER FUNCTION --- */ - - /* Migrate */ - border: border(); - border: border(base); - border: border(dark); - border: border(transparent); - border: border(divider); - border: border('divider'); - - /* --- BORDER WIDTH FUNCTION --- */ - - /* Migrate */ - border: border-width() solid var(--p-border-subdued); - border: border-width(base) solid var(--p-border-subdued); - border: border-width(thick) solid var(--p-border-subdued); - border: border-width(thicker) solid var(--p-border-subdued); - border-width: border-width('thicker'); - - /* Ignore */ - border-width: calc(-1 * border-width()); - border-width: calc($var * border-width()); - - /* Comment */ - border-width: rem(1px) rem(10px - border-width()); } .border-radius { @@ -111,21 +85,4 @@ /* Comment */ border-radius: rem(10px) rem(4px); border-radius: rem(1px) * 5; - - /* --- BORDER-RADIUS FUNCTION --- */ - - /* Migrate */ - border-radius: border-radius(); - border-radius: border-radius(base); - border-radius: border-radius(large); - - /* Ignore */ - border-radius: calc(border-radius(base) * 2); - border-radius: calc(border-radius() * rem(1px)); - - /* Comment */ - border-radius: border-radius(base) * 2; - border-radius: border-radius() * rem(1px); - border-radius: 10px; - border-top-right-radius: border-radius() * rem(4px); } diff --git a/polaris-migrator/src/migrations/replace-border-declarations/tests/replace-border-declarations.output.scss b/polaris-migrator/src/migrations/styles-tokenize-shape/tests/styles-tokenize-shape.output.scss similarity index 69% rename from polaris-migrator/src/migrations/replace-border-declarations/tests/replace-border-declarations.output.scss rename to polaris-migrator/src/migrations/styles-tokenize-shape/tests/styles-tokenize-shape.output.scss index 313b0d45519..40cbf4d90a3 100644 --- a/polaris-migrator/src/migrations/replace-border-declarations/tests/replace-border-declarations.output.scss +++ b/polaris-migrator/src/migrations/styles-tokenize-shape/tests/styles-tokenize-shape.output.scss @@ -77,34 +77,6 @@ // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. // border-width: rem($var * var(--p-border-width-1)); border-width: rem($var * 1px); - - /* --- BORDER FUNCTION --- */ - - /* Migrate */ - border: var(--p-border-base); - border: var(--p-border-base); - border: var(--p-border-dark); - border: var(--p-border-transparent); - border: var(--p-border-divider); - border: var(--p-border-divider); - - /* --- BORDER WIDTH FUNCTION --- */ - - /* Migrate */ - border: var(--p-border-width-1) solid var(--p-border-subdued); - border: var(--p-border-width-1) solid var(--p-border-subdued); - border: var(--p-border-width-2) solid var(--p-border-subdued); - border: var(--p-border-width-3) solid var(--p-border-subdued); - border-width: var(--p-border-width-3); - - /* Ignore */ - border-width: calc(-1 * border-width()); - border-width: calc($var * border-width()); - - /* Comment */ - // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. - // border-width: var(--p-border-width-1) rem(10px - var(--p-border-width-1)); - border-width: rem(1px) rem(10px - border-width()); } .border-radius { @@ -143,29 +115,4 @@ // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. // border-radius: rem(1px) * 5; border-radius: rem(1px) * 5; - - /* --- BORDER-RADIUS FUNCTION --- */ - - /* Migrate */ - border-radius: var(--p-border-radius-base); - border-radius: var(--p-border-radius-base); - border-radius: var(--p-border-radius-large); - - /* Ignore */ - border-radius: calc(border-radius(base) * 2); - border-radius: calc(border-radius() * rem(1px)); - - /* Comment */ - // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. - // border-radius: var(--p-border-radius-base) * 2; - border-radius: border-radius(base) * 2; - // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. - // border-radius: var(--p-border-radius-base) * rem(1px); - border-radius: border-radius() * rem(1px); - // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. - // border-radius: 10px; - border-radius: 10px; - // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. - // border-top-right-radius: var(--p-border-radius-base) * var(--p-border-radius-1); - border-top-right-radius: border-radius() * rem(4px); } diff --git a/polaris-migrator/src/migrations/styles-tokenize-shape/tests/styles-tokenize-shape.test.ts b/polaris-migrator/src/migrations/styles-tokenize-shape/tests/styles-tokenize-shape.test.ts new file mode 100644 index 00000000000..152be82d18c --- /dev/null +++ b/polaris-migrator/src/migrations/styles-tokenize-shape/tests/styles-tokenize-shape.test.ts @@ -0,0 +1,17 @@ +import {check} from '../../../utilities/testUtils'; + +const migration = 'styles-tokenize-shape'; +const fixtures = ['styles-tokenize-shape', 'with-namespace']; + +for (const fixture of fixtures) { + check(__dirname, { + fixture, + migration, + extension: 'scss', + options: { + namespace: fixture.includes('with-namespace') + ? 'legacy-polaris-v8' + : undefined, + }, + }); +} diff --git a/polaris-migrator/src/migrations/replace-border-declarations/tests/with-namespace.input.scss b/polaris-migrator/src/migrations/styles-tokenize-shape/tests/with-namespace.input.scss similarity index 61% rename from polaris-migrator/src/migrations/replace-border-declarations/tests/with-namespace.input.scss rename to polaris-migrator/src/migrations/styles-tokenize-shape/tests/with-namespace.input.scss index ccff4ab2033..8111f61de2c 100644 --- a/polaris-migrator/src/migrations/replace-border-declarations/tests/with-namespace.input.scss +++ b/polaris-migrator/src/migrations/styles-tokenize-shape/tests/with-namespace.input.scss @@ -58,33 +58,6 @@ border-width: legacy-polaris-v8.rem(10px) -1px; border-width: legacy-polaris-v8.rem(10px) + 1px; border-width: legacy-polaris-v8.rem($var * 1px); - - /* --- BORDER FUNCTION --- */ - - /* Migrate */ - border: legacy-polaris-v8.border(); - border: legacy-polaris-v8.border(base); - border: legacy-polaris-v8.border(dark); - border: legacy-polaris-v8.border(transparent); - border: legacy-polaris-v8.border(divider); - border: legacy-polaris-v8.border('divider'); - - /* --- BORDER WIDTH FUNCTION --- */ - - /* Migrate */ - border: legacy-polaris-v8.border-width() solid var(--p-border-subdued); - border: legacy-polaris-v8.border-width(base) solid var(--p-border-subdued); - border: legacy-polaris-v8.border-width(thick) solid var(--p-border-subdued); - border: legacy-polaris-v8.border-width(thicker) solid var(--p-border-subdued); - border-width: legacy-polaris-v8.border-width('thicker'); - - /* Ignore */ - border-width: calc(-1 * legacy-polaris-v8.border-width()); - border-width: calc($var * legacy-polaris-v8.border-width()); - - /* Comment */ - border-width: legacy-polaris-v8.rem(1px) - legacy-polaris-v8.rem(10px - legacy-polaris-v8.border-width()); } .border-radius { @@ -115,24 +88,4 @@ /* Comment */ border-radius: legacy-polaris-v8.rem(10px) legacy-polaris-v8.rem(4px); border-radius: legacy-polaris-v8.rem(1px) * 5; - - /* --- BORDER-RADIUS FUNCTION --- */ - - /* Migrate */ - border-radius: legacy-polaris-v8.border-radius(); - border-radius: legacy-polaris-v8.border-radius(base); - border-radius: legacy-polaris-v8.border-radius(large); - - /* Ignore */ - border-radius: calc(legacy-polaris-v8.border-radius(base) * 2); - border-radius: calc( - legacy-polaris-v8.border-radius() * legacy-polaris-v8.rem(1px) - ); - - /* Comment */ - border-radius: legacy-polaris-v8.border-radius(base) * 2; - border-radius: legacy-polaris-v8.border-radius() * legacy-polaris-v8.rem(1px); - border-radius: 10px; - border-top-right-radius: legacy-polaris-v8.border-radius() * - legacy-polaris-v8.rem(4px); } diff --git a/polaris-migrator/src/migrations/replace-border-declarations/tests/with-namespace.output.scss b/polaris-migrator/src/migrations/styles-tokenize-shape/tests/with-namespace.output.scss similarity index 68% rename from polaris-migrator/src/migrations/replace-border-declarations/tests/with-namespace.output.scss rename to polaris-migrator/src/migrations/styles-tokenize-shape/tests/with-namespace.output.scss index 591b63510ab..f0427a089ed 100644 --- a/polaris-migrator/src/migrations/replace-border-declarations/tests/with-namespace.output.scss +++ b/polaris-migrator/src/migrations/styles-tokenize-shape/tests/with-namespace.output.scss @@ -80,35 +80,6 @@ // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. // border-width: legacy-polaris-v8.rem($var * var(--p-border-width-1)); border-width: legacy-polaris-v8.rem($var * 1px); - - /* --- BORDER FUNCTION --- */ - - /* Migrate */ - border: var(--p-border-base); - border: var(--p-border-base); - border: var(--p-border-dark); - border: var(--p-border-transparent); - border: var(--p-border-divider); - border: var(--p-border-divider); - - /* --- BORDER WIDTH FUNCTION --- */ - - /* Migrate */ - border: var(--p-border-width-1) solid var(--p-border-subdued); - border: var(--p-border-width-1) solid var(--p-border-subdued); - border: var(--p-border-width-2) solid var(--p-border-subdued); - border: var(--p-border-width-3) solid var(--p-border-subdued); - border-width: var(--p-border-width-3); - - /* Ignore */ - border-width: calc(-1 * legacy-polaris-v8.border-width()); - border-width: calc($var * legacy-polaris-v8.border-width()); - - /* Comment */ - // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. - // border-width: var(--p-border-width-1) legacy-polaris-v8.rem(10px - var(--p-border-width-1)); - border-width: legacy-polaris-v8.rem(1px) - legacy-polaris-v8.rem(10px - legacy-polaris-v8.border-width()); } .border-radius { @@ -147,32 +118,4 @@ // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. // border-radius: legacy-polaris-v8.rem(1px) * 5; border-radius: legacy-polaris-v8.rem(1px) * 5; - - /* --- BORDER-RADIUS FUNCTION --- */ - - /* Migrate */ - border-radius: var(--p-border-radius-base); - border-radius: var(--p-border-radius-base); - border-radius: var(--p-border-radius-large); - - /* Ignore */ - border-radius: calc(legacy-polaris-v8.border-radius(base) * 2); - border-radius: calc( - legacy-polaris-v8.border-radius() * legacy-polaris-v8.rem(1px) - ); - - /* Comment */ - // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. - // border-radius: var(--p-border-radius-base) * 2; - border-radius: legacy-polaris-v8.border-radius(base) * 2; - // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. - // border-radius: var(--p-border-radius-base) * legacy-polaris-v8.rem(1px); - border-radius: legacy-polaris-v8.border-radius() * legacy-polaris-v8.rem(1px); - // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. - // border-radius: 10px; - border-radius: 10px; - // polaris-migrator: Unable to migrate the following expression. Please upgrade manually. - // border-top-right-radius: var(--p-border-radius-base) * var(--p-border-radius-1); - border-top-right-radius: legacy-polaris-v8.border-radius() * - legacy-polaris-v8.rem(4px); }