Skip to content

Commit fd2c981

Browse files
authored
feat: enhance dom/no-string-style-prop rule to support custom components and improve attribute resolution (#1218)
1 parent d531e77 commit fd2c981

File tree

2 files changed

+33
-24
lines changed

2 files changed

+33
-24
lines changed

packages/plugins/eslint-plugin-react-dom/src/rules/no-string-style-prop.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,24 @@ ruleTester.run(RULE_NAME, rule, {
5454
return <div style={someStyle} />;
5555
}
5656
`,
57+
{
58+
// https://github.com/Rel1cx/eslint-react/issues/1217
59+
code: tsx`
60+
const a = <StatusBar style="auto" />;
61+
`,
62+
settings: {
63+
"react-x": {
64+
additionalComponents: [
65+
{
66+
name: "StatusBar",
67+
attributes: [
68+
// inform that the style attribute on StatusBar is not an intrinsic attribute but a custom one
69+
{ name: "", as: "style" },
70+
],
71+
},
72+
],
73+
},
74+
},
75+
},
5776
],
5877
});

packages/plugins/eslint-plugin-react-dom/src/rules/no-string-style-prop.ts

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { RuleListener } from "@typescript-eslint/utils/ts-eslint";
44
import type { CamelCase } from "string-ts";
55

66
import { AST_NODE_TYPES as T } from "@typescript-eslint/types";
7-
import { createRule } from "../utils";
7+
import { createJsxElementResolver, createRule, resolveAttribute } from "../utils";
88

99
export const RULE_NAME = "no-string-style-prop";
1010

@@ -30,33 +30,23 @@ export default createRule<[], MessageID>({
3030
});
3131

3232
export function create(context: RuleContext<MessageID, []>): RuleListener {
33+
const resolver = createJsxElementResolver(context);
3334
return {
34-
JSXAttribute(node) {
35-
if (node.name.name !== "style") return;
36-
const styleText = getAttributeValueText(context, node.value);
37-
if (styleText == null) return;
35+
JSXElement(node) {
36+
const { attributes } = resolver.resolve(node);
37+
const {
38+
attribute,
39+
attributeName,
40+
attributeValue,
41+
attributeValueString,
42+
} = resolveAttribute(context, attributes, node, "style");
43+
if (attributeName !== "style") return;
44+
if (attribute == null || attributeValue?.node == null) return;
45+
if (attributeValueString == null) return;
3846
context.report({
3947
messageId: "noStringStyleProp",
40-
node,
48+
node: attributeValue.node,
4149
});
4250
},
4351
};
4452
}
45-
46-
function getAttributeValueText(context: RuleContext, node: TSESTree.JSXAttribute["value"]) {
47-
if (node == null) return null;
48-
switch (true) {
49-
case node.type === T.Literal
50-
&& typeof node.value === "string":
51-
return context.sourceCode.getText(node);
52-
case node.type === T.JSXExpressionContainer
53-
&& node.expression.type === T.Literal
54-
&& typeof node.expression.value === "string":
55-
return context.sourceCode.getText(node.expression);
56-
case node.type === T.JSXExpressionContainer
57-
&& node.expression.type === T.TemplateLiteral:
58-
return context.sourceCode.getText(node.expression);
59-
default:
60-
return null;
61-
}
62-
}

0 commit comments

Comments
 (0)