Skip to content

Commit 5a20c30

Browse files
authored
fix(textReplaceWithContent): fix nested JSXElements handling (#726)
1 parent bfd2bcc commit 5a20c30

File tree

4 files changed

+134
-78
lines changed

4 files changed

+134
-78
lines changed

packages/eslint-plugin-pf-codemods/src/rules/v6/textReplaceWithContent/text-replace-with-content.test.ts

Lines changed: 102 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ const importDeclarationError = {
66
message: errorMessage,
77
type: "ImportDeclaration",
88
};
9-
const jsxElementError = {
9+
const jsxOpeningElementError = {
1010
message: errorMessage,
11-
type: "JSXElement",
11+
type: "JSXOpeningElement",
12+
};
13+
const jsxClosingElementError = {
14+
message: errorMessage,
15+
type: "JSXClosingElement",
1216
};
1317
const identifierError = {
1418
message: errorMessage,
@@ -28,78 +32,109 @@ ruleTester.run("text-replace-with-content", rule, {
2832
{
2933
code: `import { Text } from '@patternfly/react-core'; <Text>Abc</Text>`,
3034
output: `import { Content } from '@patternfly/react-core'; <Content component="p">Abc</Content>`,
31-
errors: [importDeclarationError, jsxElementError],
35+
errors: [
36+
importDeclarationError,
37+
jsxOpeningElementError,
38+
jsxClosingElementError,
39+
],
3240
},
3341
{
3442
code: `import { Text } from '@patternfly/react-core'; <Text component="h3">Abc</Text>`,
3543
output: `import { Content } from '@patternfly/react-core'; <Content component="h3">Abc</Content>`,
36-
errors: [importDeclarationError, jsxElementError],
44+
errors: [
45+
importDeclarationError,
46+
jsxOpeningElementError,
47+
jsxClosingElementError,
48+
],
49+
},
50+
{
51+
code: `import { Text, TextContent } from '@patternfly/react-core';
52+
<TextContent>
53+
<Text component="h3">Abc</Text>
54+
</TextContent>`,
55+
output: `import { Content, TextContent } from '@patternfly/react-core';
56+
<Content>
57+
<Content component="h3">Abc</Content>
58+
</Content>`,
59+
errors: [
60+
importDeclarationError,
61+
jsxOpeningElementError,
62+
jsxOpeningElementError,
63+
jsxClosingElementError,
64+
jsxClosingElementError,
65+
],
3766
},
38-
// {
39-
// code: `import { Text, TextContent } from '@patternfly/react-core';
40-
// <TextContent>
41-
// <Text component="h3">Abc</Text>
42-
// </TextContent>`,
43-
// output: `import { Content, TextContent } from '@patternfly/react-core';
44-
// <Content>
45-
// <Content component="h3">Abc</Content>
46-
// </Content>`,
47-
// errors: [importDeclarationError, jsxElementError, jsxElementError],
48-
// },
4967
{
5068
code: `import { TextContent } from '@patternfly/react-core'; <TextContent isVisited></TextContent>`,
5169
output: `import { Content } from '@patternfly/react-core'; <Content isVisitedLink></Content>`,
52-
errors: [importDeclarationError, jsxElementError],
70+
errors: [
71+
importDeclarationError,
72+
jsxOpeningElementError,
73+
jsxClosingElementError,
74+
],
75+
},
76+
{
77+
code: `import { TextList, TextListItem } from '@patternfly/react-core';
78+
<TextList>
79+
<TextListItem>A</TextListItem>
80+
<TextListItem>B</TextListItem>
81+
<TextListItem>C</TextListItem>
82+
</TextList>`,
83+
output: `import { Content, TextListItem } from '@patternfly/react-core';
84+
<Content component="ul">
85+
<Content component="li">A</Content>
86+
<Content component="li">B</Content>
87+
<Content component="li">C</Content>
88+
</Content>`,
89+
errors: [
90+
importDeclarationError,
91+
jsxOpeningElementError,
92+
jsxOpeningElementError,
93+
jsxClosingElementError,
94+
jsxOpeningElementError,
95+
jsxClosingElementError,
96+
jsxOpeningElementError,
97+
jsxClosingElementError,
98+
jsxClosingElementError,
99+
],
100+
},
101+
{
102+
code: `import { TextList, TextListItem } from '@patternfly/react-core';
103+
<TextList component="dl">
104+
<TextListItem component="dt">A</TextListItem>
105+
<TextListItem component="dd">letter A</TextListItem>
106+
<TextListItem component="dt">B</TextListItem>
107+
<TextListItem component="dd">letter B</TextListItem>
108+
</TextList>`,
109+
output: `import { Content, TextListItem } from '@patternfly/react-core';
110+
<Content component="dl">
111+
<Content component="dt">A</Content>
112+
<Content component="dd">letter A</Content>
113+
<Content component="dt">B</Content>
114+
<Content component="dd">letter B</Content>
115+
</Content>`,
116+
errors: [
117+
importDeclarationError,
118+
jsxOpeningElementError,
119+
jsxOpeningElementError,
120+
jsxClosingElementError,
121+
jsxOpeningElementError,
122+
jsxClosingElementError,
123+
jsxOpeningElementError,
124+
jsxClosingElementError,
125+
jsxOpeningElementError,
126+
jsxClosingElementError,
127+
jsxClosingElementError,
128+
],
53129
},
54-
// {
55-
// code: `import { TextList, TextListItem } from '@patternfly/react-core';
56-
// <TextList>
57-
// <TextListItem>A</TextListItem>
58-
// <TextListItem>B</TextListItem>
59-
// <TextListItem>C</TextListItem>
60-
// </TextList>`,
61-
// output: `import { Content, TextListItem } from '@patternfly/react-core';
62-
// <Content component="ul">
63-
// <Content component="li">A</Content>
64-
// <Content component="li">B</Content>
65-
// <Content component="li">C</Content>
66-
// </Content>`,
67-
// errors: [
68-
// importDeclarationError,
69-
// jsxElementError,
70-
// jsxElementError,
71-
// jsxElementError,
72-
// jsxElementError,
73-
// ],
74-
// },
75-
// {
76-
// code: `import { TextList, TextListItem } from '@patternfly/react-core';
77-
// <TextList component="dl">
78-
// <TextListItem component="dt">A</TextListItem>
79-
// <TextListItem component="dd">letter A</TextListItem>
80-
// <TextListItem component="dt">B</TextListItem>
81-
// <TextListItem component="dd">letter B</TextListItem>
82-
// </TextList>`,
83-
// output: `import { Content, TextListItem } from '@patternfly/react-core';
84-
// <Content component="dl">
85-
// <Content component="dt">A</Content>
86-
// <Content component="dd">letter A</Content>
87-
// <Content component="dt">B</Content>
88-
// <Content component="dd">letter B</Content>
89-
// </Content>`,
90-
// errors: [
91-
// importDeclarationError,
92-
// jsxElementError,
93-
// jsxElementError,
94-
// jsxElementError,
95-
// jsxElementError,
96-
// jsxElementError,
97-
// ],
98-
// },
99130
{
100131
code: `import { TextList } from '@patternfly/react-core'; <TextList isPlain></TextList>`,
101132
output: `import { Content } from '@patternfly/react-core'; <Content component="ul" isPlainList></Content>`,
102-
errors: [importDeclarationError, jsxElementError],
133+
errors: [
134+
importDeclarationError,
135+
jsxOpeningElementError,
136+
jsxClosingElementError,
137+
],
103138
},
104139
{
105140
code: `import { TextVariants } from '@patternfly/react-core'; const foo = TextVariants.h1`,
@@ -115,7 +150,11 @@ ruleTester.run("text-replace-with-content", rule, {
115150
{
116151
code: `import { Text as PFText } from '@patternfly/react-core'; <PFText>Abc</PFText>`,
117152
output: `import { Content } from '@patternfly/react-core'; <Content component="p">Abc</Content>`,
118-
errors: [importDeclarationError, jsxElementError],
153+
errors: [
154+
importDeclarationError,
155+
jsxOpeningElementError,
156+
jsxClosingElementError,
157+
],
119158
},
120159
],
121160
});

packages/eslint-plugin-pf-codemods/src/rules/v6/textReplaceWithContent/text-replace-with-content.ts

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import { Rule } from "eslint";
22
import {
33
ImportDeclaration,
44
ImportSpecifier,
5-
JSXElement,
5+
JSXClosingElement,
66
JSXIdentifier,
7+
JSXOpeningElement,
78
} from "estree-jsx";
89
import {
910
getAttribute,
@@ -65,14 +66,10 @@ module.exports = {
6566
});
6667
}
6768
},
68-
JSXElement(node: JSXElement) {
69-
const openingElement = node.openingElement;
70-
const closingElement = node.closingElement;
71-
72-
if (openingElement.name.type === "JSXIdentifier") {
69+
JSXOpeningElement(node: JSXOpeningElement) {
70+
if (node.name.type === "JSXIdentifier") {
7371
const componentImport = textImports.find(
74-
(imp) =>
75-
imp.local.name === (openingElement.name as JSXIdentifier).name
72+
(imp) => imp.local.name === (node.name as JSXIdentifier).name
7673
);
7774

7875
if (!componentImport) {
@@ -102,7 +99,7 @@ module.exports = {
10299

103100
fixes.push(
104101
fixer.insertTextAfter(
105-
openingElement.name,
102+
node.name,
106103
` component="${componentMap[componentName]}"`
107104
)
108105
);
@@ -129,18 +126,32 @@ module.exports = {
129126
}
130127
}
131128

132-
fixes.push(fixer.replaceText(openingElement.name, "Content"));
133-
if (closingElement) {
134-
fixes.push(
135-
fixer.replaceText(closingElement.name, "Content")
136-
);
137-
}
129+
fixes.push(fixer.replaceText(node.name, "Content"));
138130

139131
return fixes;
140132
},
141133
});
142134
}
143135
},
136+
JSXClosingElement(node: JSXClosingElement) {
137+
if (node.name.type === "JSXIdentifier") {
138+
const componentImport = textImports.find(
139+
(imp) => imp.local.name === (node.name as JSXIdentifier).name
140+
);
141+
142+
if (!componentImport) {
143+
return;
144+
}
145+
146+
context.report({
147+
node,
148+
message: errorMessage,
149+
fix(fixer) {
150+
return fixer.replaceText(node.name, "Content");
151+
},
152+
});
153+
}
154+
},
144155
Identifier(node: IdentifierWithParent) {
145156
const textImport = textImports.find(
146157
(imp) => imp.local.name === node.name

packages/eslint-plugin-pf-codemods/src/rules/v6/textReplaceWithContent/textReplaceWithContentInput.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ export const TextReplaceWithContentInput = () => {
1515
<Text component="h3">Abc</Text>
1616
<Text>Abc</Text>
1717
<TextContent>Abc</TextContent>
18+
<TextContent>
19+
<Text>Some text</Text>
20+
</TextContent>
1821
<TextContent isVisited>Abc</TextContent>
1922
<TextList>Abc</TextList>
2023
<TextList isPlain>Abc</TextList>

packages/eslint-plugin-pf-codemods/src/rules/v6/textReplaceWithContent/textReplaceWithContentOutput.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ export const TextReplaceWithContentInput = () => {
1515
<Content component="h3">Abc</Content>
1616
<Content component="p">Abc</Content>
1717
<Content>Abc</Content>
18+
<Content>
19+
<Content component="p">Some text</Content>
20+
</Content>
1821
<Content isVisitedLink>Abc</Content>
1922
<Content component="ul">Abc</Content>
2023
<Content component="ul" isPlainList>Abc</Content>

0 commit comments

Comments
 (0)