-
Notifications
You must be signed in to change notification settings - Fork 20
feat(tokens): provide autofix for all global tokens #763
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
wise-king-sullyman
merged 8 commits into
patternfly:main
from
adamviktora:tokens-autofix
Sep 24, 2024
Merged
Changes from 1 commit
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
973e700
feat(tokens): provide autofix for global non-color tokens
adamviktora a20df70
refactor(getDefaultDeclarationString helper): rename to getImportPath
adamviktora b45b510
feat(tokens): handle color tokens autofix
adamviktora ff8e9fd
test(tokens): add tests
adamviktora 6188763
refactor(tokens)
adamviktora a2ec857
refactor(tokens): rename rule
adamviktora 9faaa83
feat(tokens): update temp_dev_tbd token to t_temp_dev_tbd
adamviktora 6906ca9
docs: update description
adamviktora File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| export * from './configs'; | ||
| export * from './ruleCuration'; | ||
| export * from './ruleCustomization' | ||
| export * from "./configs"; | ||
| export * from "./ruleCuration"; | ||
| export * from "./ruleCustomization"; | ||
| export * from "./tokenLists"; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
178 changes: 150 additions & 28 deletions
178
packages/eslint-plugin-pf-codemods/src/rules/v6/tokensWarn/tokens-warn.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,82 +1,204 @@ | ||
| import { Rule } from "eslint"; | ||
| import { | ||
| IdentifierWithParent, | ||
| getDefaultDeclarationString, | ||
| getDefaultImportsFromPackage, | ||
| getFromPackage, | ||
| } from "../../helpers"; | ||
| import { ImportDeclaration, ImportSpecifier, Literal } from "estree-jsx"; | ||
| import { oldTokens } from "./tokenLists/oldTokens"; | ||
| import { oldCssVarNamesV5 } from "./tokenLists/oldCssVarNamesV5"; | ||
| import { | ||
| Identifier, | ||
| ImportDeclaration, | ||
| ImportSpecifier, | ||
| Literal, | ||
| } from "estree-jsx"; | ||
| import { | ||
| oldTokens, | ||
| oldCssVarNamesV5, | ||
| globalNonColorTokensMap, | ||
| oldGlobalNonColorTokens, | ||
| oldGlobalNonColorCssVarNames, | ||
| globalNonColorCssVarNamesMap, | ||
| } from "../../../tokenLists"; | ||
|
|
||
| module.exports = { | ||
| meta: {}, | ||
| meta: { fixable: "code" }, | ||
| create: function (context: Rule.RuleContext) { | ||
| const tokensPackage = "@patternfly/react-tokens"; | ||
|
|
||
| const { imports: tokenSpecifiers } = getFromPackage(context, tokensPackage); | ||
|
|
||
| const defaultTokensWithDeclaration = getDefaultImportsFromPackage( | ||
| const defaultTokenImports = getDefaultImportsFromPackage( | ||
| context, | ||
| tokensPackage | ||
| ) | ||
| .map((specifier) => ({ | ||
| specifier, | ||
| path: getDefaultDeclarationString(specifier), | ||
| declaration: specifier.parent, | ||
| })) | ||
| .filter(({ path }) => path !== undefined) | ||
| .map(({ path, declaration }) => ({ | ||
| .map(({ specifier, path, declaration }) => ({ | ||
| specifier, | ||
| token: (path as string).split("/").pop() as string, | ||
| declaration, | ||
| })); | ||
|
|
||
| const getMessage = (tokenName: string) => | ||
| const getWarnMessage = (tokenName: string) => | ||
| `${tokenName} is an old CSS token. About half of our tokens have been replaced with newer ones. To find a suitable replacement token, check our new documentation https://staging-v6.patternfly.org/tokens/all-patternfly-tokens.`; | ||
|
|
||
| const getFixMessage = (oldToken: string, newToken: string) => | ||
| `${oldToken} is an old CSS token and has been replaced with ${newToken}. If you want to use a different token, check our new documentation https://staging-v6.patternfly.org/tokens/all-patternfly-tokens.`; | ||
|
|
||
| const shouldReplaceToken = (token: string) => | ||
| oldGlobalNonColorTokens.includes(token) && | ||
| globalNonColorTokensMap[token as keyof typeof globalNonColorTokensMap] !== | ||
| "SKIP"; | ||
|
|
||
| const replaceToken = ( | ||
| node: ImportDeclaration | ImportSpecifier | Identifier, | ||
| oldToken: string | ||
| ) => { | ||
| const newToken = | ||
| globalNonColorTokensMap[ | ||
| oldToken as keyof typeof globalNonColorTokensMap | ||
| ]; | ||
|
|
||
| context.report({ | ||
| node, | ||
| message: getFixMessage(oldToken, newToken), | ||
| fix(fixer) { | ||
| if (node.type === "ImportDeclaration") { | ||
| const newDeclaration = node.source.value | ||
| ?.toString() | ||
| .replace(oldToken, newToken) as string; | ||
|
|
||
| return [ | ||
| fixer.replaceText(node.specifiers[0], newToken), | ||
| fixer.replaceText(node.source, `"${newDeclaration}"`), | ||
| ]; | ||
| } | ||
|
|
||
| if (node.type === "ImportSpecifier") { | ||
| return fixer.replaceText(node.imported, newToken); | ||
| } | ||
|
|
||
| return fixer.replaceText(node, newToken); | ||
| }, | ||
| }); | ||
| }; | ||
|
|
||
| const replaceTokenOrWarn = ( | ||
| node: ImportSpecifier | ImportDeclaration, | ||
| token: string | ||
| ) => { | ||
| if (shouldReplaceToken(token)) { | ||
| replaceToken(node, token); | ||
| } else if (oldTokens.includes(token)) { | ||
| context.report({ | ||
| node, | ||
| message: getWarnMessage(token), | ||
| }); | ||
| } | ||
| }; | ||
|
|
||
| return { | ||
| ImportSpecifier(node: ImportSpecifier) { | ||
| if (tokenSpecifiers.includes(node)) { | ||
| const tokenName = node.imported.name; | ||
| if (oldTokens.includes(tokenName)) { | ||
| context.report({ | ||
| node, | ||
| message: getMessage(tokenName), | ||
| }); | ||
| } | ||
| const token = node.imported.name; | ||
| replaceTokenOrWarn(node, token); | ||
| } | ||
| }, | ||
| ImportDeclaration(node: ImportDeclaration) { | ||
| const tokenWithDeclaration = defaultTokensWithDeclaration.find( | ||
| const tokenWithDeclaration = defaultTokenImports.find( | ||
| ({ declaration }) => node.source.value === declaration?.source.value | ||
| ); | ||
|
|
||
| if (!tokenWithDeclaration) { | ||
| return; | ||
| } | ||
|
|
||
| replaceTokenOrWarn(node, tokenWithDeclaration.token); | ||
| }, | ||
| Identifier(node: Identifier) { | ||
| const parentType = (node as IdentifierWithParent).parent?.type; | ||
| // handle ImportSpecifier and ImportDeclaration separately | ||
| if ( | ||
| tokenWithDeclaration && | ||
| oldTokens.includes(tokenWithDeclaration.token) | ||
| parentType === "ImportSpecifier" || | ||
| parentType === "ImportDefaultSpecifier" | ||
| ) { | ||
| context.report({ | ||
| node, | ||
| message: getMessage(tokenWithDeclaration.token), | ||
| }); | ||
| return; | ||
| } | ||
|
|
||
| const tokenInfo = defaultTokenImports.find( | ||
| ({ specifier }) => node.name === specifier.local.name | ||
| ); | ||
|
|
||
| if (tokenInfo && shouldReplaceToken(tokenInfo.token)) { | ||
| replaceToken(node, tokenInfo.token); | ||
| } | ||
|
|
||
| const unaliasedTokenSpecifier = tokenSpecifiers.find( | ||
| (specifier) => | ||
| specifier.local.name === specifier.imported.name && | ||
| node.name === specifier.local.name | ||
| ); | ||
|
|
||
| if (unaliasedTokenSpecifier && shouldReplaceToken(node.name)) { | ||
| replaceToken(node, node.name); | ||
| } | ||
| }, | ||
| Literal(node: Literal) { | ||
| if ( | ||
| typeof node.value === "string" && | ||
| [...oldCssVarNames, ...oldCssVars].includes(node.value) | ||
| ) { | ||
| if (typeof node.value !== "string") { | ||
| return; | ||
| } | ||
|
|
||
| let varName = node.value; | ||
| const varRegex = /var\(([^)]+)\)/; | ||
| const match = node.value.match(varRegex); | ||
|
|
||
| if (match) { | ||
| varName = match[1]; | ||
| } | ||
|
|
||
| const shouldReplaceVar = | ||
| oldGlobalNonColorCssVarNames.includes(varName) && | ||
| globalNonColorCssVarNamesMap[ | ||
| varName as keyof typeof globalNonColorCssVarNamesMap | ||
| ] !== "SKIP"; | ||
|
|
||
| if (shouldReplaceVar) { | ||
| const newVarName = | ||
| globalNonColorCssVarNamesMap[ | ||
| varName as keyof typeof globalNonColorCssVarNamesMap | ||
| ]; | ||
|
|
||
| if (newVarName !== "SKIP") { | ||
wise-king-sullyman marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| context.report({ | ||
| node, | ||
| message: getFixMessage(varName, newVarName), | ||
| fix(fixer) { | ||
| return fixer.replaceText( | ||
| node, | ||
| node.value?.toString().startsWith("var") | ||
| ? `"var(${newVarName})"` | ||
| : `"${newVarName}"` | ||
| ); | ||
| }, | ||
| }); | ||
| } | ||
| } else if (oldCssVarNames.includes(varName)) { | ||
| context.report({ | ||
| node, | ||
| message: getMessage(node.value), | ||
| message: getWarnMessage(node.value), | ||
| }); | ||
| } | ||
| }, | ||
| }; | ||
| }, | ||
| }; | ||
|
|
||
| // consumers may run class-name-updater before codemods, so we have to check also old tokens with v6 prefix | ||
| // consumers may have run the old class-name-updater before codemods, so we should check also old tokens with v6 prefix | ||
| const oldCssVarNamesV6 = oldCssVarNamesV5.map((cssVarName) => | ||
| cssVarName.replace("v5", "v6") | ||
| ); | ||
| const oldCssVarNames = [...oldCssVarNamesV5, ...oldCssVarNamesV6]; | ||
| const oldCssVars = oldCssVarNames.map((cssVarName) => `var(${cssVarName})`); | ||
31 changes: 23 additions & 8 deletions
31
packages/eslint-plugin-pf-codemods/src/rules/v6/tokensWarn/tokensWarnInput.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,29 @@ | ||
| // replacements (fixable with --fix) | ||
| import global_BorderWidth_lg from "@patternfly/react-tokens/dist/esm/global_BorderWidth_lg"; | ||
| import { global_FontWeight_normal } from "@patternfly/react-tokens"; | ||
|
|
||
| global_BorderWidth_lg; | ||
| global_FontWeight_normal; | ||
|
|
||
| document.documentElement.style.setProperty("--pf-v5-global--ZIndex--lg", "3"); | ||
| <div | ||
| style={{ | ||
| borderWidth: "var(--pf-v5-global--BorderWidth--lg)", | ||
| boxShadow: "var(--pf-v5-global--BoxShadow--sm)", | ||
| marginTop: "var(--pf-v5-global--spacer--3xl)", | ||
| }} | ||
| ></div>; | ||
|
|
||
| // warnings (not fixable) | ||
| import global_warning_color_100 from "@patternfly/react-tokens/dist/esm/global_warning_color_100"; | ||
| import { c_alert__FontSize } from "@patternfly/react-tokens"; | ||
|
|
||
| global_warning_color_100; | ||
| c_alert__FontSize; | ||
|
|
||
| <> | ||
| <div | ||
| style={{ | ||
| "--pf-v5-global--success-color--200": "#abc", | ||
| }} | ||
| ></div> | ||
| <div style={{ borderWidth: "var(--pf-v5-global--BorderWidth--lg)" }}></div> | ||
| </>; | ||
| <div | ||
| style={{ | ||
| color: "var(--pf-v5-global--success-color--200)", | ||
| width: "var(--pf-v5-global--arrow--width)", | ||
| }} | ||
| ></div>; |
31 changes: 23 additions & 8 deletions
31
packages/eslint-plugin-pf-codemods/src/rules/v6/tokensWarn/tokensWarnOutput.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,29 @@ | ||
| // replacements (fixable with --fix) | ||
| import global_border_width_extra_strong from "@patternfly/react-tokens/dist/esm/global_border_width_extra_strong"; | ||
| import { global_font_weight_body_default } from "@patternfly/react-tokens"; | ||
|
|
||
| global_border_width_extra_strong; | ||
| global_font_weight_body_default; | ||
|
|
||
| document.documentElement.style.setProperty("--pf-t--global--z-index--lg", "3"); | ||
| <div | ||
| style={{ | ||
| borderWidth: "var(--pf-t--global--border--width--extra-strong)", | ||
| boxShadow: "var(--pf-t--global--box-shadow--sm)", | ||
| marginTop: "var(--pf-t--global--spacer--3xl)", | ||
| }} | ||
| ></div>; | ||
|
|
||
| // warnings (not fixable) | ||
| import global_warning_color_100 from "@patternfly/react-tokens/dist/esm/global_warning_color_100"; | ||
| import { c_alert__FontSize } from "@patternfly/react-tokens"; | ||
|
|
||
| global_warning_color_100; | ||
| c_alert__FontSize; | ||
|
|
||
| <> | ||
| <div | ||
| style={{ | ||
| "--pf-v5-global--success-color--200": "#abc", | ||
| }} | ||
| ></div> | ||
| <div style={{ borderWidth: "var(--pf-v5-global--BorderWidth--lg)" }}></div> | ||
| </>; | ||
| <div | ||
| style={{ | ||
| color: "var(--pf-v5-global--success-color--200)", | ||
| width: "var(--pf-v5-global--arrow--width)", | ||
| }} | ||
| ></div>; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| export * from "./oldCssVarNamesV5"; | ||
| export * from "./oldGlobalCssVarNames"; | ||
| export * from "./oldGlobalTokens"; | ||
| export * from "./oldTokens"; |
2 changes: 1 addition & 1 deletion
2
...tokensWarn/tokenLists/oldCssVarNamesV5.ts → ...demods/src/tokenLists/oldCssVarNamesV5.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.