Skip to content

Commit e7e95ed

Browse files
committed
Update jsx-dollar rule to handle two-child case
1 parent a195c2e commit e7e95ed

File tree

3 files changed

+57
-18
lines changed

3 files changed

+57
-18
lines changed

packages/plugins/eslint-plugin-react-x/src/rules/jsx-dollar.mdx

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,51 +53,44 @@ import React from "react";
5353

5454
function MyComponent({ user }) {
5555
return <div>Hello ${user.name}</div>;
56-
// ^^^^^^^^^^^^^^
56+
// ^^^^^^^
5757
// - Possible unnecessary '$' character before expression.
5858
}
5959
```
6060

61-
### Passing
62-
6361
```tsx
6462
import React from "react";
6563

6664
function MyComponent({ user }) {
67-
return `Hello ${user.name}`;
65+
return <div>${user.name} is your name</div>;
66+
// ^
67+
// - Possible unnecessary '$' character before expression.
6868
}
6969
```
7070

71+
### Passing
72+
7173
```tsx
7274
import React from "react";
7375

7476
function MyComponent({ user }) {
75-
return <div>Hello {user.name}</div>;
77+
return `Hello ${user.name}`;
7678
}
7779
```
7880

7981
```tsx
8082
import React from "react";
8183

82-
function MyComponent({ price }) {
83-
return <div>${price}</div>;
84+
function MyComponent({ user }) {
85+
return <div>Hello {user.name}</div>;
8486
}
8587
```
8688

87-
### Legitimate uses
88-
89-
If you legitimately need to output a dollar sign before an expression (for example, to display a price), you can wrap it in a template literal or use a string literal.
90-
9189
```tsx
9290
import React from "react";
9391

9492
function MyComponent({ price }) {
95-
// 🟢 Good: This is a legitimate use of the '$' character.
96-
return <div>{`$${price}`}</div>;
97-
}
98-
99-
function AnotherComponent({ price }) {
100-
// 🟢 Good: Another legitimate way to display a price.
93+
// 🟢 Good: If there are only two children (the dollar sign and the expression) it doesn't seem to be split from a template literal
10194
return <div>${price}</div>;
10295
}
10396
```

packages/plugins/eslint-plugin-react-x/src/rules/jsx-dollar.spec.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,50 @@ ruleTester.run(RULE_NAME, rule, {
4545
},
4646
],
4747
},
48+
{
49+
code: tsx`
50+
const App = (props) => {
51+
return <div>\${props.name} is your name</div>;
52+
};
53+
`,
54+
errors: [
55+
{
56+
messageId: "jsxDollar",
57+
suggestions: [
58+
{
59+
messageId: "removeDollarSign",
60+
output: tsx`
61+
const App = (props) => {
62+
return <div>{props.name} is your name</div>;
63+
};
64+
`,
65+
},
66+
],
67+
},
68+
],
69+
},
70+
{
71+
code: tsx`
72+
const App = (props) => {
73+
return <div>Hello \${props.name} is your name</div>;
74+
};
75+
`,
76+
errors: [
77+
{
78+
messageId: "jsxDollar",
79+
suggestions: [
80+
{
81+
messageId: "removeDollarSign",
82+
output: tsx`
83+
const App = (props) => {
84+
return <div>Hello {props.name} is your name</div>;
85+
};
86+
`,
87+
},
88+
],
89+
},
90+
],
91+
},
4892
],
4993
valid: [
5094
...allValid,

packages/plugins/eslint-plugin-react-x/src/rules/jsx-dollar.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@ export function create(context: RuleContext<MessageID, []>): RuleListener {
4141
*/
4242
const visitorFunction = (node: TSESTree.JSXElement | TSESTree.JSXFragment) => {
4343
for (const [index, child] of node.children.entries()) {
44-
if (child.type !== T.JSXText || child.raw === "$" || !child.raw.endsWith("$")) continue;
44+
if (child.type !== T.JSXText || !child.value.endsWith("$")) continue;
4545
// Ensure the next sibling is a JSXExpressionContainer
4646
if (node.children[index + 1]?.type !== T.JSXExpressionContainer) continue;
47+
// Skip if there are only two children (the dollar sign and the expression) it doesn't seem to be split from a template literal
48+
if (child.value === "$" && node.children.length === 2) continue;
4749
context.report({
4850
messageId: "jsxDollar",
4951
node: child,

0 commit comments

Comments
 (0)