@clearstory/drywall-react 7.1.0 → 7.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/eslint-config/index.js +14 -6
- package/dist/eslint-config/no-shorthand-spacing.d.ts +3 -0
- package/dist/eslint-config/no-shorthand-spacing.js +57 -0
- package/dist/eslint-config/no-system-props.js +28 -59
- package/dist/eslint-config/prefer-logical-properties.d.ts +3 -0
- package/dist/eslint-config/prefer-logical-properties.js +72 -0
- package/dist/eslint-config/prefer-vars-palette.js +71 -131
- package/dist/eslint-config/sx-utils.d.ts +53 -0
- package/dist/eslint-config/sx-utils.js +67 -0
- package/package.json +1 -1
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import e from "./no-
|
|
2
|
-
import l from "./
|
|
1
|
+
import e from "./no-shorthand-spacing.js";
|
|
2
|
+
import l from "./no-system-props.js";
|
|
3
|
+
import a from "./prefer-logical-properties.js";
|
|
4
|
+
import o from "./prefer-vars-palette.js";
|
|
3
5
|
const r = {
|
|
4
6
|
rules: {
|
|
5
|
-
"no-
|
|
6
|
-
"
|
|
7
|
+
"no-shorthand-spacing": e,
|
|
8
|
+
"no-system-props": l,
|
|
9
|
+
"prefer-logical-properties": a,
|
|
10
|
+
"prefer-vars-palette": o
|
|
7
11
|
},
|
|
8
12
|
configs: {}
|
|
9
13
|
};
|
|
@@ -13,21 +17,25 @@ r.configs.recommended = {
|
|
|
13
17
|
"@clearstory/drywall-react": r
|
|
14
18
|
},
|
|
15
19
|
rules: {
|
|
20
|
+
"@clearstory/drywall-react/no-shorthand-spacing": "error",
|
|
16
21
|
"@clearstory/drywall-react/no-system-props": "error",
|
|
22
|
+
"@clearstory/drywall-react/prefer-logical-properties": "error",
|
|
17
23
|
"@clearstory/drywall-react/prefer-vars-palette": "error"
|
|
18
24
|
}
|
|
19
25
|
};
|
|
20
|
-
const
|
|
26
|
+
const y = {
|
|
21
27
|
name: "@clearstory/drywall-react",
|
|
22
28
|
plugins: {
|
|
23
29
|
"@clearstory/drywall-react": r
|
|
24
30
|
},
|
|
25
31
|
rules: {
|
|
32
|
+
"@clearstory/drywall-react/no-shorthand-spacing": "error",
|
|
26
33
|
"@clearstory/drywall-react/no-system-props": "error",
|
|
34
|
+
"@clearstory/drywall-react/prefer-logical-properties": "error",
|
|
27
35
|
"@clearstory/drywall-react/prefer-vars-palette": "error"
|
|
28
36
|
}
|
|
29
37
|
};
|
|
30
38
|
export {
|
|
31
|
-
|
|
39
|
+
y as default,
|
|
32
40
|
r as plugin
|
|
33
41
|
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { createSxVisitor as i } from "./sx-utils.js";
|
|
2
|
+
const s = {
|
|
3
|
+
p: "padding",
|
|
4
|
+
pt: "paddingTop",
|
|
5
|
+
pr: "paddingRight",
|
|
6
|
+
pb: "paddingBottom",
|
|
7
|
+
pl: "paddingLeft",
|
|
8
|
+
px: "paddingX",
|
|
9
|
+
py: "paddingY",
|
|
10
|
+
m: "margin",
|
|
11
|
+
mt: "marginTop",
|
|
12
|
+
mr: "marginRight",
|
|
13
|
+
mb: "marginBottom",
|
|
14
|
+
ml: "marginLeft",
|
|
15
|
+
mx: "marginX",
|
|
16
|
+
my: "marginY"
|
|
17
|
+
}, g = {
|
|
18
|
+
meta: {
|
|
19
|
+
type: "suggestion",
|
|
20
|
+
fixable: "code",
|
|
21
|
+
docs: {
|
|
22
|
+
description: "Disallow MUI spacing shorthands (p, pt, m, mx, etc.) in sx props",
|
|
23
|
+
category: "Best Practices",
|
|
24
|
+
recommended: !0
|
|
25
|
+
},
|
|
26
|
+
messages: {
|
|
27
|
+
shorthandSpacing: 'Use "{{replacement}}" instead of shorthand "{{property}}" in sx for readability.'
|
|
28
|
+
},
|
|
29
|
+
schema: []
|
|
30
|
+
},
|
|
31
|
+
create(a) {
|
|
32
|
+
return i({
|
|
33
|
+
onProperty(n, e) {
|
|
34
|
+
const t = s[n];
|
|
35
|
+
t && a.report({
|
|
36
|
+
node: e,
|
|
37
|
+
messageId: "shorthandSpacing",
|
|
38
|
+
data: { property: n, replacement: t },
|
|
39
|
+
fix(p) {
|
|
40
|
+
const r = e;
|
|
41
|
+
if (e.type === "Literal") {
|
|
42
|
+
const o = a.sourceCode.getText(r)[0];
|
|
43
|
+
return p.replaceText(
|
|
44
|
+
r,
|
|
45
|
+
`${o}${t}${o}`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return p.replaceText(r, t);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
export {
|
|
56
|
+
g as default
|
|
57
|
+
};
|
|
@@ -14,7 +14,6 @@ const g = [
|
|
|
14
14
|
"outlineColor",
|
|
15
15
|
"borderRadius",
|
|
16
16
|
// colors
|
|
17
|
-
"color",
|
|
18
17
|
"bgcolor",
|
|
19
18
|
"backgroundColor",
|
|
20
19
|
// spacing
|
|
@@ -122,11 +121,12 @@ const g = [
|
|
|
122
121
|
"typography",
|
|
123
122
|
// other common system props
|
|
124
123
|
"spacing"
|
|
125
|
-
],
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
124
|
+
], c = {
|
|
125
|
+
Container: ["maxWidth"],
|
|
126
|
+
Dialog: ["maxWidth"],
|
|
127
|
+
InputAdornment: ["position"],
|
|
128
|
+
TableCell: ["padding"]
|
|
129
|
+
}, f = {
|
|
130
130
|
meta: {
|
|
131
131
|
type: "problem",
|
|
132
132
|
docs: {
|
|
@@ -139,48 +139,41 @@ const g = [
|
|
|
139
139
|
},
|
|
140
140
|
schema: []
|
|
141
141
|
},
|
|
142
|
-
create(
|
|
143
|
-
const
|
|
142
|
+
create(l) {
|
|
143
|
+
const r = /* @__PURE__ */ new Map(), m = /* @__PURE__ */ new Set();
|
|
144
144
|
return {
|
|
145
|
-
ImportDeclaration(
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
e.type === "ImportSpecifier" && e.imported
|
|
145
|
+
ImportDeclaration(i) {
|
|
146
|
+
const o = i;
|
|
147
|
+
o.source.value === "@clearstory/drywall-react" && o.specifiers.forEach((e) => {
|
|
148
|
+
e.type === "ImportSpecifier" && e.imported ? r.set(e.local.name, e.imported.name) : e.type === "ImportNamespaceSpecifier" && m.add(e.local.name);
|
|
149
149
|
});
|
|
150
150
|
},
|
|
151
|
-
JSXOpeningElement(
|
|
152
|
-
const
|
|
151
|
+
JSXOpeningElement(i) {
|
|
152
|
+
const o = i;
|
|
153
153
|
let e;
|
|
154
|
-
if ("name" in
|
|
155
|
-
if (e =
|
|
154
|
+
if ("name" in o.name) {
|
|
155
|
+
if (e = o.name.name, !r.has(e))
|
|
156
156
|
return;
|
|
157
|
-
} else if (
|
|
158
|
-
const t =
|
|
159
|
-
if (e =
|
|
157
|
+
} else if (o.name.type === "JSXMemberExpression") {
|
|
158
|
+
const t = o.name.object.name;
|
|
159
|
+
if (e = o.name.property.name, !m.has(t))
|
|
160
160
|
return;
|
|
161
161
|
} else
|
|
162
162
|
return;
|
|
163
163
|
const p = [];
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
if (
|
|
164
|
+
o.attributes.forEach((t) => {
|
|
165
|
+
const n = t;
|
|
166
|
+
if (n.type !== "JSXAttribute" || !n.name)
|
|
167
167
|
return;
|
|
168
|
-
const a =
|
|
168
|
+
const a = n.name.name;
|
|
169
169
|
if (a === "sx" || !g.includes(a))
|
|
170
170
|
return;
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const c = f(i.value);
|
|
175
|
-
if (y(c))
|
|
176
|
-
return;
|
|
177
|
-
} else
|
|
178
|
-
return;
|
|
179
|
-
p.push(
|
|
180
|
-
i
|
|
171
|
+
const s = r.get(e) ?? e, d = c[s];
|
|
172
|
+
d && d.includes(a) || p.push(
|
|
173
|
+
n
|
|
181
174
|
);
|
|
182
175
|
}), p.forEach((t) => {
|
|
183
|
-
|
|
176
|
+
l.report({
|
|
184
177
|
node: t,
|
|
185
178
|
messageId: "systemProp",
|
|
186
179
|
data: {
|
|
@@ -193,30 +186,6 @@ const g = [
|
|
|
193
186
|
};
|
|
194
187
|
}
|
|
195
188
|
};
|
|
196
|
-
function f(n) {
|
|
197
|
-
if (!n) return null;
|
|
198
|
-
const o = n;
|
|
199
|
-
if (o.type === "Literal")
|
|
200
|
-
return String(o.value);
|
|
201
|
-
if (o.type === "JSXExpressionContainer" && o.expression) {
|
|
202
|
-
if (o.expression.type === "Literal")
|
|
203
|
-
return String(o.expression.value);
|
|
204
|
-
if (o.expression.type === "Identifier")
|
|
205
|
-
return o.expression.name || null;
|
|
206
|
-
}
|
|
207
|
-
return null;
|
|
208
|
-
}
|
|
209
|
-
function y(n) {
|
|
210
|
-
return [
|
|
211
|
-
"inherit",
|
|
212
|
-
"primary",
|
|
213
|
-
"secondary",
|
|
214
|
-
"error",
|
|
215
|
-
"warning",
|
|
216
|
-
"info",
|
|
217
|
-
"success"
|
|
218
|
-
].includes(n || "");
|
|
219
|
-
}
|
|
220
189
|
export {
|
|
221
|
-
|
|
190
|
+
f as default
|
|
222
191
|
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { createSxVisitor as d } from "./sx-utils.js";
|
|
2
|
+
const l = {
|
|
3
|
+
// Positioning (inset)
|
|
4
|
+
top: "insetBlockStart",
|
|
5
|
+
bottom: "insetBlockEnd",
|
|
6
|
+
left: "insetInlineStart",
|
|
7
|
+
right: "insetInlineEnd",
|
|
8
|
+
// Padding
|
|
9
|
+
paddingTop: "paddingBlockStart",
|
|
10
|
+
paddingBottom: "paddingBlockEnd",
|
|
11
|
+
paddingLeft: "paddingInlineStart",
|
|
12
|
+
paddingRight: "paddingInlineEnd",
|
|
13
|
+
paddingX: "paddingInline",
|
|
14
|
+
paddingY: "paddingBlock",
|
|
15
|
+
// Margin
|
|
16
|
+
marginTop: "marginBlockStart",
|
|
17
|
+
marginBottom: "marginBlockEnd",
|
|
18
|
+
marginLeft: "marginInlineStart",
|
|
19
|
+
marginRight: "marginInlineEnd",
|
|
20
|
+
marginX: "marginInline",
|
|
21
|
+
marginY: "marginBlock",
|
|
22
|
+
// Border
|
|
23
|
+
borderTop: "borderBlockStart",
|
|
24
|
+
borderBottom: "borderBlockEnd",
|
|
25
|
+
borderLeft: "borderInlineStart",
|
|
26
|
+
borderRight: "borderInlineEnd",
|
|
27
|
+
// Border color
|
|
28
|
+
borderTopColor: "borderBlockStartColor",
|
|
29
|
+
borderBottomColor: "borderBlockEndColor",
|
|
30
|
+
borderLeftColor: "borderInlineStartColor",
|
|
31
|
+
borderRightColor: "borderInlineEndColor"
|
|
32
|
+
}, g = {
|
|
33
|
+
meta: {
|
|
34
|
+
type: "suggestion",
|
|
35
|
+
fixable: "code",
|
|
36
|
+
docs: {
|
|
37
|
+
description: "Enforce CSS logical properties instead of physical direction properties in sx props",
|
|
38
|
+
category: "Best Practices",
|
|
39
|
+
recommended: !0
|
|
40
|
+
},
|
|
41
|
+
messages: {
|
|
42
|
+
physicalProperty: 'Use logical property "{{replacement}}" instead of "{{property}}" in sx for RTL support.'
|
|
43
|
+
},
|
|
44
|
+
schema: []
|
|
45
|
+
},
|
|
46
|
+
create(t) {
|
|
47
|
+
return d({
|
|
48
|
+
onProperty(n, o) {
|
|
49
|
+
const r = l[n];
|
|
50
|
+
r && t.report({
|
|
51
|
+
node: o,
|
|
52
|
+
messageId: "physicalProperty",
|
|
53
|
+
data: { property: n, replacement: r },
|
|
54
|
+
fix(i) {
|
|
55
|
+
const e = o;
|
|
56
|
+
if (o.type === "Literal") {
|
|
57
|
+
const a = t.sourceCode.getText(e)[0];
|
|
58
|
+
return i.replaceText(
|
|
59
|
+
e,
|
|
60
|
+
`${a}${r}${a}`
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
return i.replaceText(e, r);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
export {
|
|
71
|
+
g as default
|
|
72
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { createSxVisitor as l } from "./sx-utils.js";
|
|
2
|
+
const f = /* @__PURE__ */ new Set([
|
|
2
3
|
"color",
|
|
3
4
|
"backgroundColor",
|
|
4
5
|
"bgcolor",
|
|
@@ -22,7 +23,7 @@ const b = /* @__PURE__ */ new Set([
|
|
|
22
23
|
"initial",
|
|
23
24
|
"unset",
|
|
24
25
|
"none"
|
|
25
|
-
]),
|
|
26
|
+
]), d = {
|
|
26
27
|
meta: {
|
|
27
28
|
type: "suggestion",
|
|
28
29
|
docs: {
|
|
@@ -36,155 +37,94 @@ const b = /* @__PURE__ */ new Set([
|
|
|
36
37
|
},
|
|
37
38
|
schema: []
|
|
38
39
|
},
|
|
39
|
-
create(
|
|
40
|
-
return {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const o = r.value;
|
|
47
|
-
if (o && o.type === "JSXExpressionContainer") {
|
|
48
|
-
const s = o.expression;
|
|
49
|
-
y(t, s);
|
|
50
|
-
}
|
|
40
|
+
create(s) {
|
|
41
|
+
return l({
|
|
42
|
+
onProperty(t, r, e) {
|
|
43
|
+
f.has(t) && i(s, t, e);
|
|
44
|
+
},
|
|
45
|
+
onCallback(t) {
|
|
46
|
+
c(s, t);
|
|
51
47
|
}
|
|
52
|
-
};
|
|
48
|
+
});
|
|
53
49
|
}
|
|
54
50
|
};
|
|
55
|
-
function
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
case "ArrowFunctionExpression":
|
|
62
|
-
case "FunctionExpression": {
|
|
63
|
-
d(t, e);
|
|
64
|
-
const n = g(e);
|
|
65
|
-
n && u(t, n);
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
case "ArrayExpression": {
|
|
69
|
-
e.elements.forEach((r) => {
|
|
70
|
-
r && y(t, r);
|
|
71
|
-
});
|
|
72
|
-
break;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
function u(t, e) {
|
|
77
|
-
e.properties.forEach((r) => {
|
|
78
|
-
if (r.type !== "Property") return;
|
|
79
|
-
const o = r, s = m(o.key, o.computed);
|
|
80
|
-
if (!s) return;
|
|
81
|
-
const i = o.value;
|
|
82
|
-
if (i.type === "ObjectExpression") {
|
|
83
|
-
u(t, i);
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
if (b.has(s)) {
|
|
87
|
-
if (i.type === "ArrowFunctionExpression" || i.type === "FunctionExpression") {
|
|
88
|
-
d(t, i);
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
if (i.type === "Literal") {
|
|
92
|
-
const a = i.value;
|
|
93
|
-
typeof a == "string" && !p.has(a) && t.report({
|
|
94
|
-
node: i,
|
|
95
|
-
messageId: "stringColor",
|
|
96
|
-
data: { value: a, property: s }
|
|
97
|
-
});
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
if (i.type === "TemplateLiteral") {
|
|
101
|
-
const a = i;
|
|
102
|
-
if (a.expressions.length === 0) {
|
|
103
|
-
const c = a.quasis[0]?.value.raw;
|
|
104
|
-
c && !p.has(c) && t.report({
|
|
105
|
-
node: i,
|
|
106
|
-
messageId: "stringColor",
|
|
107
|
-
data: { value: c, property: s }
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
if (i.type === "ConditionalExpression") {
|
|
113
|
-
const a = i;
|
|
114
|
-
l(t, a.consequent, s), l(t, a.alternate, s);
|
|
115
|
-
}
|
|
51
|
+
function i(s, t, r) {
|
|
52
|
+
if (r.type === "ObjectExpression") {
|
|
53
|
+
const e = r.properties;
|
|
54
|
+
for (const o of e) {
|
|
55
|
+
if (o.type === "SpreadElement" || o.type !== "Property") continue;
|
|
56
|
+
i(s, t, o.value);
|
|
116
57
|
}
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (r.type === "ArrowFunctionExpression" || r.type === "FunctionExpression") {
|
|
61
|
+
c(s, r);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (r.type === "Literal") {
|
|
65
|
+
const e = r.value;
|
|
66
|
+
typeof e == "string" && !p.has(e) && s.report({
|
|
67
|
+
node: r,
|
|
124
68
|
messageId: "stringColor",
|
|
125
|
-
data: { value:
|
|
69
|
+
data: { value: e, property: t }
|
|
126
70
|
});
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (r.type === "TemplateLiteral") {
|
|
74
|
+
const e = r;
|
|
75
|
+
if (e.expressions.length === 0) {
|
|
76
|
+
const o = e.quasis[0]?.value.raw;
|
|
77
|
+
o && !p.has(o) && s.report({
|
|
78
|
+
node: r,
|
|
79
|
+
messageId: "stringColor",
|
|
80
|
+
data: { value: o, property: t }
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (r.type === "ConditionalExpression") {
|
|
86
|
+
const e = r;
|
|
87
|
+
i(s, t, e.consequent), i(s, t, e.alternate);
|
|
130
88
|
}
|
|
131
89
|
}
|
|
132
|
-
function
|
|
133
|
-
const
|
|
134
|
-
if (!
|
|
135
|
-
const
|
|
136
|
-
if (
|
|
137
|
-
const o =
|
|
138
|
-
|
|
139
|
-
} else
|
|
140
|
-
if (
|
|
141
|
-
|
|
142
|
-
node:
|
|
90
|
+
function c(s, t) {
|
|
91
|
+
const r = t.params;
|
|
92
|
+
if (!r || r.length === 0) return;
|
|
93
|
+
const e = r[0];
|
|
94
|
+
if (e.type === "Identifier") {
|
|
95
|
+
const o = e.name, n = t.body;
|
|
96
|
+
a(s, n, o);
|
|
97
|
+
} else e.type === "ObjectPattern" && e.properties.forEach((n) => {
|
|
98
|
+
if (n.type !== "Property") return;
|
|
99
|
+
n.key.name === "palette" && s.report({
|
|
100
|
+
node: n,
|
|
143
101
|
messageId: "useVarsPalette",
|
|
144
102
|
data: { access: "destructured palette" }
|
|
145
103
|
});
|
|
146
104
|
});
|
|
147
105
|
}
|
|
148
|
-
function
|
|
149
|
-
if (!(!
|
|
150
|
-
if (
|
|
151
|
-
const
|
|
152
|
-
if (
|
|
153
|
-
|
|
154
|
-
node:
|
|
106
|
+
function a(s, t, r) {
|
|
107
|
+
if (!(!t || typeof t != "object")) {
|
|
108
|
+
if (t.type === "MemberExpression") {
|
|
109
|
+
const e = t.object, o = t.property;
|
|
110
|
+
if (e.type === "Identifier" && e.name === r && o.name === "palette") {
|
|
111
|
+
s.report({
|
|
112
|
+
node: t,
|
|
155
113
|
messageId: "useVarsPalette",
|
|
156
|
-
data: { access: `${
|
|
114
|
+
data: { access: `${r}.palette` }
|
|
157
115
|
});
|
|
158
116
|
return;
|
|
159
117
|
}
|
|
160
118
|
}
|
|
161
|
-
for (const
|
|
162
|
-
if (
|
|
163
|
-
const o = e
|
|
164
|
-
o && typeof o == "object" && (Array.isArray(o) ? o.forEach((
|
|
165
|
-
|
|
166
|
-
}) : "type" in o &&
|
|
119
|
+
for (const e of Object.keys(t)) {
|
|
120
|
+
if (e === "parent") continue;
|
|
121
|
+
const o = t[e];
|
|
122
|
+
o && typeof o == "object" && (Array.isArray(o) ? o.forEach((n) => {
|
|
123
|
+
n && typeof n == "object" && "type" in n && a(s, n, r);
|
|
124
|
+
}) : "type" in o && a(s, o, r));
|
|
167
125
|
}
|
|
168
126
|
}
|
|
169
127
|
}
|
|
170
|
-
function g(t) {
|
|
171
|
-
const e = t.body;
|
|
172
|
-
if (e.type === "ObjectExpression")
|
|
173
|
-
return e;
|
|
174
|
-
if (e.type === "BlockStatement") {
|
|
175
|
-
const n = e.body;
|
|
176
|
-
for (const r of n)
|
|
177
|
-
if (r.type === "ReturnStatement") {
|
|
178
|
-
const o = r.argument;
|
|
179
|
-
if (o?.type === "ObjectExpression")
|
|
180
|
-
return o;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return null;
|
|
184
|
-
}
|
|
185
|
-
function m(t, e) {
|
|
186
|
-
return t.type === "Identifier" && !e ? t.name || null : t.type === "Literal" && typeof t.value == "string" ? t.value : null;
|
|
187
|
-
}
|
|
188
128
|
export {
|
|
189
|
-
|
|
129
|
+
d as default
|
|
190
130
|
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Rule } from 'eslint';
|
|
2
|
+
/**
|
|
3
|
+
* Shared AST traversal utilities for ESLint rules that inspect MUI `sx` props.
|
|
4
|
+
*
|
|
5
|
+
* Provides a visitor pattern that:
|
|
6
|
+
* 1. Finds the `sx` attribute on JSXOpeningElement nodes
|
|
7
|
+
* 2. Traverses the expression (object, callback, or array)
|
|
8
|
+
* 3. Recurses into nested objects (pseudo-selectors like "&:hover")
|
|
9
|
+
* 4. Calls rule-specific callbacks for each property encountered
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Minimal AST node type for traversal within ESLint rules.
|
|
13
|
+
*/
|
|
14
|
+
export type ASTNode = Record<string, unknown> & {
|
|
15
|
+
type: string;
|
|
16
|
+
};
|
|
17
|
+
export interface SxVisitorCallbacks {
|
|
18
|
+
/**
|
|
19
|
+
* Called for each property in an sx object expression, including properties
|
|
20
|
+
* inside nested objects (pseudo-selectors like "&:hover").
|
|
21
|
+
* Recursion into nested objects is handled automatically by the visitor.
|
|
22
|
+
*/
|
|
23
|
+
onProperty: (keyName: string, keyNode: ASTNode, valueNode: ASTNode) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Called when the sx value (or an array element) is a callback function
|
|
26
|
+
* (ArrowFunctionExpression or FunctionExpression). Fires before the
|
|
27
|
+
* returned object's properties are visited via onProperty.
|
|
28
|
+
*/
|
|
29
|
+
onCallback?: (func: ASTNode) => void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Creates a JSXOpeningElement visitor that locates the `sx` attribute
|
|
33
|
+
* and walks its value, invoking the provided callbacks for each property.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createSxVisitor(callbacks: SxVisitorCallbacks): Rule.RuleListener;
|
|
36
|
+
/**
|
|
37
|
+
* Walk an sx value expression (object, callback, or array) and invoke
|
|
38
|
+
* the provided callbacks for each property encountered.
|
|
39
|
+
*/
|
|
40
|
+
export declare function visitSxValue(node: ASTNode, callbacks: SxVisitorCallbacks): void;
|
|
41
|
+
/**
|
|
42
|
+
* Extract the returned ObjectExpression from a function/arrow function body.
|
|
43
|
+
*/
|
|
44
|
+
export declare function getReturnedObjectExpression(func: ASTNode): ASTNode | null;
|
|
45
|
+
/**
|
|
46
|
+
* Get the string name of a property key.
|
|
47
|
+
* Returns null for computed keys or non-string keys.
|
|
48
|
+
*/
|
|
49
|
+
export declare function getKeyName(key: {
|
|
50
|
+
type: string;
|
|
51
|
+
name?: string;
|
|
52
|
+
value?: string;
|
|
53
|
+
}, computed: boolean): string | null;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
function f(e) {
|
|
2
|
+
return {
|
|
3
|
+
JSXOpeningElement(t) {
|
|
4
|
+
const n = t.attributes.find(
|
|
5
|
+
(i) => i.type === "JSXAttribute" && i.name?.name === "sx"
|
|
6
|
+
);
|
|
7
|
+
if (!n) return;
|
|
8
|
+
const r = n.value;
|
|
9
|
+
if (r && r.type === "JSXExpressionContainer") {
|
|
10
|
+
const i = r.expression;
|
|
11
|
+
u(i, e);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function u(e, t) {
|
|
17
|
+
if (e)
|
|
18
|
+
switch (e.type) {
|
|
19
|
+
case "ObjectExpression":
|
|
20
|
+
o(e, t);
|
|
21
|
+
break;
|
|
22
|
+
case "ArrowFunctionExpression":
|
|
23
|
+
case "FunctionExpression": {
|
|
24
|
+
t.onCallback?.(e);
|
|
25
|
+
const s = p(e);
|
|
26
|
+
s && o(s, t);
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
case "ArrayExpression": {
|
|
30
|
+
e.elements.forEach((n) => {
|
|
31
|
+
n && u(n, t);
|
|
32
|
+
});
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function o(e, t) {
|
|
38
|
+
e.properties.forEach((n) => {
|
|
39
|
+
if (n.type !== "Property") return;
|
|
40
|
+
const r = n, i = c(r.key, r.computed);
|
|
41
|
+
i && (r.value.type === "ObjectExpression" && o(r.value, t), t.onProperty(i, r.key, r.value));
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function p(e) {
|
|
45
|
+
const t = e.body;
|
|
46
|
+
if (t.type === "ObjectExpression")
|
|
47
|
+
return t;
|
|
48
|
+
if (t.type === "BlockStatement") {
|
|
49
|
+
const s = t.body;
|
|
50
|
+
for (const n of s)
|
|
51
|
+
if (n.type === "ReturnStatement") {
|
|
52
|
+
const r = n.argument;
|
|
53
|
+
if (r?.type === "ObjectExpression")
|
|
54
|
+
return r;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
function c(e, t) {
|
|
60
|
+
return e.type === "Identifier" && !t ? e.name || null : e.type === "Literal" && typeof e.value == "string" ? e.value : null;
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
f as createSxVisitor,
|
|
64
|
+
c as getKeyName,
|
|
65
|
+
p as getReturnedObjectExpression,
|
|
66
|
+
u as visitSxValue
|
|
67
|
+
};
|