-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Masthead): Update subcomponent names
- Loading branch information
1 parent
578475a
commit 7950b85
Showing
14 changed files
with
362 additions
and
1 deletion.
There are no files selected for viewing
11 changes: 11 additions & 0 deletions
11
packages/eslint-plugin-pf-codemods/src/rules/helpers/getAttributeName.ts
This file contains 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,11 @@ | ||
import { JSXAttribute } from "estree-jsx"; | ||
|
||
/** Gets the name value of a JSX attribute */ | ||
export function getAttributeName(attr: JSXAttribute) { | ||
switch (attr.name.type) { | ||
case "JSXIdentifier": | ||
return attr.name.name; | ||
case "JSXNamespacedName": | ||
return attr.name.name.name; | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
packages/eslint-plugin-pf-codemods/src/rules/helpers/getComponentImportName.ts
This file contains 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,17 @@ | ||
import { ImportSpecifier } from "estree-jsx"; | ||
import { ImportDefaultSpecifierWithParent } from "./interfaces"; | ||
import { getDeclarationString } from "./getDeclarationString"; | ||
|
||
/** Gets the name of an import based on the specifier and an array of names that should be looked for in default import paths */ | ||
export function getComponentImportName( | ||
importSpecifier: ImportSpecifier | ImportDefaultSpecifierWithParent, | ||
potentialNames: string[] | ||
) { | ||
if (importSpecifier.type === "ImportSpecifier") { | ||
return importSpecifier.imported.name; | ||
} | ||
|
||
return potentialNames.find((name) => | ||
getDeclarationString(importSpecifier)?.includes(name) | ||
); | ||
} |
8 changes: 8 additions & 0 deletions
8
packages/eslint-plugin-pf-codemods/src/rules/helpers/getDeclarationString.ts
This file contains 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,8 @@ | ||
import { ImportDefaultSpecifierWithParent } from "./interfaces"; | ||
|
||
/** Gets the import path string for a default import */ | ||
export function getDeclarationString( | ||
defaultImportSpecifier: ImportDefaultSpecifierWithParent | ||
) { | ||
return defaultImportSpecifier?.parent?.source.value?.toString(); | ||
} |
This file contains 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
23 changes: 23 additions & 0 deletions
23
packages/eslint-plugin-pf-codemods/src/rules/helpers/getNodeName.ts
This file contains 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,23 @@ | ||
import { JSXOpeningElement, JSXMemberExpression } from "estree-jsx"; | ||
|
||
/** Gets the name of an opening element or member expression */ | ||
export function getNodeName(node: JSXOpeningElement | JSXMemberExpression) { | ||
if (node.type === "JSXMemberExpression") { | ||
switch (node.object.type) { | ||
case "JSXMemberExpression": | ||
return getNodeName(node.object); | ||
case "JSXIdentifier": | ||
return node.object.name; | ||
} | ||
} | ||
|
||
switch (node.name.type) { | ||
case "JSXMemberExpression": | ||
return getNodeName(node.name); | ||
case "JSXIdentifier": | ||
case "JSXNamespacedName": | ||
return typeof node.name.name === "string" | ||
? node.name.name | ||
: node.name.name.name; | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
packages/eslint-plugin-pf-codemods/src/rules/helpers/hasCodemodDataTag.ts
This file contains 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,13 @@ | ||
import { JSXAttribute, JSXOpeningElement } from "estree-jsx"; | ||
import { getAttributeName } from "./getAttributeName"; | ||
|
||
/** Returns true if the passed opening element has a data-codemods attribute */ | ||
export function hasCodeModDataTag(openingElement: JSXOpeningElement) { | ||
const nonSpreadAttributes = openingElement.attributes.filter( | ||
(attr) => attr.type === "JSXAttribute" | ||
); | ||
const attributeNames = nonSpreadAttributes.map((attr) => | ||
getAttributeName(attr as JSXAttribute) | ||
); | ||
return attributeNames.includes("data-codemods"); | ||
} |
5 changes: 5 additions & 0 deletions
5
packages/eslint-plugin-pf-codemods/src/rules/helpers/index.ts
This file contains 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 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
113 changes: 113 additions & 0 deletions
113
packages/eslint-plugin-pf-codemods/src/rules/helpers/renameComponent.ts
This file contains 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,113 @@ | ||
import { Rule } from "eslint"; | ||
import { ImportSpecifier } from "estree-jsx"; | ||
import { getAllImportsFromPackage } from "./getFromPackage"; | ||
import { | ||
ImportDefaultSpecifierWithParent, | ||
JSXOpeningElementWithParent, | ||
} from "./interfaces"; | ||
import { | ||
getDeclarationString, | ||
getComponentImportName, | ||
getNodeName, | ||
hasCodeModDataTag, | ||
} from "./index"; | ||
|
||
interface ComponentRenames { | ||
[currentName: string]: string; | ||
} | ||
|
||
function formatDefaultMessage(oldName: string, newName: string) { | ||
return `${oldName} has been renamed to ${newName}.`; | ||
} | ||
|
||
function getFixes( | ||
fixer: Rule.RuleFixer, | ||
nodeImport: ImportSpecifier | ImportDefaultSpecifierWithParent, | ||
node: JSXOpeningElementWithParent, | ||
oldName: string, | ||
newName: string | ||
) { | ||
const fixes = []; | ||
|
||
const isNamedImport = nodeImport.type === "ImportSpecifier"; | ||
if (isNamedImport) { | ||
fixes.push(fixer.replaceText(nodeImport.imported, newName)); | ||
} else { | ||
const importDeclaration = nodeImport.parent; | ||
const newImportDeclaration = importDeclaration?.source.raw?.replace( | ||
oldName, | ||
newName | ||
); | ||
if (importDeclaration && newImportDeclaration) { | ||
fixes.push( | ||
fixer.replaceText(importDeclaration.source, newImportDeclaration) | ||
); | ||
} | ||
} | ||
|
||
const shouldRenameNode = | ||
isNamedImport && nodeImport.imported.name === nodeImport.local.name; | ||
|
||
if (shouldRenameNode) { | ||
fixes.push(fixer.replaceText(node.name, newName)); | ||
fixes.push(fixer.insertTextAfter(node.name, " data-codemods")); | ||
} | ||
|
||
const closingElement = node?.parent?.closingElement; | ||
if (shouldRenameNode && closingElement) { | ||
fixes.push(fixer.replaceText(closingElement.name, newName)); | ||
} | ||
|
||
return fixes; | ||
} | ||
|
||
export function renameComponent( | ||
renames: ComponentRenames, | ||
packageName = "@patternfly/react-core" | ||
) { | ||
return function (context: Rule.RuleContext) { | ||
const oldNames = Object.keys(renames); | ||
const imports = getAllImportsFromPackage(context, packageName, oldNames); | ||
|
||
if (imports.length === 0) { | ||
return {}; | ||
} | ||
|
||
return { | ||
JSXOpeningElement(node: JSXOpeningElementWithParent) { | ||
if (hasCodeModDataTag(node)) { | ||
return; | ||
} | ||
|
||
const nodeName = getNodeName(node); | ||
const nodeImport = imports.find((imp) => { | ||
if (imp.type === "ImportSpecifier") { | ||
return [imp.imported.name, imp.local.name].includes(nodeName); | ||
} | ||
|
||
return oldNames.some((name) => | ||
getDeclarationString(imp)?.includes(name) | ||
); | ||
}); | ||
|
||
if (!nodeImport) { | ||
return; | ||
} | ||
|
||
const oldName = getComponentImportName(nodeImport, oldNames); | ||
|
||
if (!oldName) { | ||
return; | ||
} | ||
|
||
const newName = renames[oldName]; | ||
|
||
context.report({ | ||
node, | ||
message: formatDefaultMessage(oldName, newName), | ||
fix: (fixer) => getFixes(fixer, nodeImport, node, oldName, newName), | ||
}); | ||
}, | ||
}; | ||
}; | ||
} |
18 changes: 18 additions & 0 deletions
18
...nt-plugin-pf-codemods/src/rules/v6/mastheadNameChanges/masthead-name-changes.md
This file contains 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,18 @@ | ||
### masthead-name-changes [(#10809)](https://github.com/patternfly/patternfly-react/pull/10809) | ||
|
||
The old `MastheadBrand` component has been renamed to `MastheadLogo`, and the old `MastheadMain` has been renamed to `MastheadBrand`. | ||
|
||
#### Examples | ||
|
||
In: | ||
|
||
```jsx | ||
%inputExample% | ||
``` | ||
|
||
Out: | ||
|
||
```jsx | ||
%outputExample% | ||
``` | ||
|
119 changes: 119 additions & 0 deletions
119
.../eslint-plugin-pf-codemods/src/rules/v6/mastheadNameChanges/masthead-name-changes.test.ts
This file contains 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,119 @@ | ||
const ruleTester = require("../../ruletester"); | ||
import * as rule from "./masthead-name-changes"; | ||
|
||
ruleTester.run("masthead-name-changes", rule, { | ||
valid: [ | ||
{ | ||
code: `<MastheadBrand />`, | ||
}, | ||
{ | ||
code: `<MastheadMain />`, | ||
}, | ||
{ | ||
code: `import { MastheadBrand } from '@patternfly/react-core'; <MastheadBrand data-codemods />`, | ||
}, | ||
{ | ||
code: `import { MastheadMain } from '@patternfly/react-core'; <MastheadMain data-codemods />`, | ||
}, | ||
], | ||
invalid: [ | ||
{ | ||
code: `import { MastheadBrand } from '@patternfly/react-core'; <MastheadBrand />`, | ||
output: `import { MastheadLogo } from '@patternfly/react-core'; <MastheadLogo data-codemods />`, | ||
errors: [ | ||
{ | ||
message: `MastheadBrand has been renamed to MastheadLogo.`, | ||
type: "JSXOpeningElement", | ||
}, | ||
], | ||
}, | ||
{ | ||
code: `import { MastheadMain } from '@patternfly/react-core'; <MastheadMain />`, | ||
output: `import { MastheadBrand } from '@patternfly/react-core'; <MastheadBrand data-codemods />`, | ||
errors: [ | ||
{ | ||
message: `MastheadMain has been renamed to MastheadBrand.`, | ||
type: "JSXOpeningElement", | ||
}, | ||
], | ||
}, | ||
// with other props | ||
{ | ||
code: `import { MastheadBrand } from '@patternfly/react-core'; <MastheadBrand className="foo" />`, | ||
output: `import { MastheadLogo } from '@patternfly/react-core'; <MastheadLogo data-codemods className="foo" />`, | ||
errors: [ | ||
{ | ||
message: `MastheadBrand has been renamed to MastheadLogo.`, | ||
type: "JSXOpeningElement", | ||
}, | ||
], | ||
}, | ||
// because of how the unit tests run I have to handle having both MastheadBrand and MastheadMain together in stages | ||
{ | ||
code: `import { MastheadBrand, MastheadMain } from '@patternfly/react-core'; <MastheadMain><MastheadBrand>Logo</MastheadBrand></MastheadMain>`, | ||
output: `import { MastheadLogo, MastheadMain } from '@patternfly/react-core'; <MastheadMain><MastheadLogo data-codemods>Logo</MastheadLogo></MastheadMain>`, | ||
errors: [ | ||
{ | ||
message: `MastheadMain has been renamed to MastheadBrand.`, | ||
type: "JSXOpeningElement", | ||
}, | ||
{ | ||
message: `MastheadBrand has been renamed to MastheadLogo.`, | ||
type: "JSXOpeningElement", | ||
}, | ||
], | ||
}, | ||
{ | ||
code: `import { MastheadLogo, MastheadMain } from '@patternfly/react-core'; <MastheadMain><MastheadLogo data-codemods>Logo</MastheadLogo></MastheadMain>`, | ||
output: `import { MastheadLogo, MastheadBrand } from '@patternfly/react-core'; <MastheadBrand data-codemods><MastheadLogo data-codemods>Logo</MastheadLogo></MastheadBrand>`, | ||
errors: [ | ||
{ | ||
message: `MastheadMain has been renamed to MastheadBrand.`, | ||
type: "JSXOpeningElement", | ||
}, | ||
], | ||
}, | ||
// with alias | ||
{ | ||
code: `import { MastheadBrand as MB } from '@patternfly/react-core'; <MB />`, | ||
output: `import { MastheadLogo as MB } from '@patternfly/react-core'; <MB />`, | ||
errors: [ | ||
{ | ||
message: `MastheadBrand has been renamed to MastheadLogo.`, | ||
type: "JSXOpeningElement", | ||
}, | ||
], | ||
}, | ||
// dist imports | ||
{ | ||
code: `import { MastheadBrand } from '@patternfly/react-core/dist/esm/components/Masthead/MastheadBrand'; <MastheadBrand />`, | ||
output: `import { MastheadLogo } from '@patternfly/react-core/dist/esm/components/Masthead/MastheadBrand'; <MastheadLogo data-codemods />`, | ||
errors: [ | ||
{ | ||
message: `MastheadBrand has been renamed to MastheadLogo.`, | ||
type: "JSXOpeningElement", | ||
}, | ||
], | ||
}, | ||
{ | ||
code: `import { MastheadBrand } from '@patternfly/react-core/dist/js/components/Masthead/MastheadBrand'; <MastheadBrand />`, | ||
output: `import { MastheadLogo } from '@patternfly/react-core/dist/js/components/Masthead/MastheadBrand'; <MastheadLogo data-codemods />`, | ||
errors: [ | ||
{ | ||
message: `MastheadBrand has been renamed to MastheadLogo.`, | ||
type: "JSXOpeningElement", | ||
}, | ||
], | ||
}, | ||
{ | ||
code: `import { MastheadBrand } from '@patternfly/react-core/dist/dynamic/components/Masthead/MastheadBrand'; <MastheadBrand />`, | ||
output: `import { MastheadLogo } from '@patternfly/react-core/dist/dynamic/components/Masthead/MastheadBrand'; <MastheadLogo data-codemods />`, | ||
errors: [ | ||
{ | ||
message: `MastheadBrand has been renamed to MastheadLogo.`, | ||
type: "JSXOpeningElement", | ||
}, | ||
], | ||
}, | ||
], | ||
}); |
13 changes: 13 additions & 0 deletions
13
packages/eslint-plugin-pf-codemods/src/rules/v6/mastheadNameChanges/masthead-name-changes.ts
This file contains 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,13 @@ | ||
import { renameComponent } from "../../helpers/renameComponent"; | ||
|
||
// https://github.com/patternfly/patternfly-react/pull/10809 | ||
|
||
const renames = { | ||
MastheadBrand: "MastheadLogo", | ||
MastheadMain: "MastheadBrand", | ||
}; | ||
|
||
module.exports = { | ||
meta: { fixable: "code" }, | ||
create: renameComponent(renames), | ||
}; |
Oops, something went wrong.