@wordpress/eslint-plugin 25.6.0 → 25.6.1-next.v.202607070741.0
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/package.json +7 -6
- package/rules/__tests__/components-no-missing-40px-size-prop.js +14 -66
- package/rules/__tests__/no-unsafe-wp-apis.js +7 -0
- package/rules/components-no-missing-40px-size-prop.js +3 -66
- package/rules/no-unsafe-wp-apis.js +5 -0
- package/rules/use-recommended-components.js +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/eslint-plugin",
|
|
3
|
-
"version": "25.6.0",
|
|
3
|
+
"version": "25.6.1-next.v.202607070741.0+a51d59513",
|
|
4
4
|
"description": "ESLint plugin for WordPress development.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
"@babel/eslint-parser": "^7.28.6",
|
|
45
45
|
"@eslint-community/eslint-plugin-eslint-comments": "^4.7.0",
|
|
46
46
|
"@eslint/compat": "^2.0.0",
|
|
47
|
-
"@wordpress/babel-preset-default": "^8.50.0",
|
|
48
|
-
"@wordpress/prettier-config": "^4.50.0",
|
|
49
|
-
"@wordpress/theme": "^0.17.0",
|
|
47
|
+
"@wordpress/babel-preset-default": "^8.50.1-next.v.202607070741.0+a51d59513",
|
|
48
|
+
"@wordpress/prettier-config": "^4.50.1-next.v.202607070741.0+a51d59513",
|
|
49
|
+
"@wordpress/theme": "^0.17.2-next.v.202607070741.0+a51d59513",
|
|
50
50
|
"cosmiconfig": "^7.0.0",
|
|
51
51
|
"eslint-config-prettier": "^10.0.0",
|
|
52
52
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
@@ -64,7 +64,8 @@
|
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@types/eslint": "^9",
|
|
67
|
-
"@types/estree": "^1.0.
|
|
67
|
+
"@types/estree": "^1.0.8",
|
|
68
|
+
"@typescript-eslint/parser": "^8.57.1",
|
|
68
69
|
"eslint": "^10.0.0"
|
|
69
70
|
},
|
|
70
71
|
"peerDependencies": {
|
|
@@ -84,5 +85,5 @@
|
|
|
84
85
|
"publishConfig": {
|
|
85
86
|
"access": "public"
|
|
86
87
|
},
|
|
87
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "f637726e370c8b23695ed9af82adbe171ad235d8"
|
|
88
89
|
}
|
|
@@ -36,6 +36,13 @@ ruleTester.run( 'components-no-missing-40px-size-prop', rule, {
|
|
|
36
36
|
<Button size="small" />
|
|
37
37
|
`,
|
|
38
38
|
},
|
|
39
|
+
// SelectControl no longer requires __next40pxDefaultSize
|
|
40
|
+
{
|
|
41
|
+
code: `
|
|
42
|
+
import { SelectControl } from '@wordpress/components';
|
|
43
|
+
<SelectControl />
|
|
44
|
+
`,
|
|
45
|
+
},
|
|
39
46
|
// Component with size="compact"
|
|
40
47
|
{
|
|
41
48
|
code: `
|
|
@@ -71,20 +78,6 @@ ruleTester.run( 'components-no-missing-40px-size-prop', rule, {
|
|
|
71
78
|
<WPButton __next40pxDefaultSize />
|
|
72
79
|
`,
|
|
73
80
|
},
|
|
74
|
-
// FormFileUpload with render prop (special case)
|
|
75
|
-
{
|
|
76
|
-
code: `
|
|
77
|
-
import { FormFileUpload } from '@wordpress/components';
|
|
78
|
-
<FormFileUpload render={({ open }) => <button onClick={open}>Upload</button>} />
|
|
79
|
-
`,
|
|
80
|
-
},
|
|
81
|
-
// FormFileUpload with __next40pxDefaultSize
|
|
82
|
-
{
|
|
83
|
-
code: `
|
|
84
|
-
import { FormFileUpload } from '@wordpress/components';
|
|
85
|
-
<FormFileUpload __next40pxDefaultSize />
|
|
86
|
-
`,
|
|
87
|
-
},
|
|
88
81
|
// Component with dynamic size prop (assumes it could be non-default)
|
|
89
82
|
{
|
|
90
83
|
code: `
|
|
@@ -110,40 +103,19 @@ ruleTester.run( 'components-no-missing-40px-size-prop', rule, {
|
|
|
110
103
|
{
|
|
111
104
|
code: `
|
|
112
105
|
import {
|
|
113
|
-
BorderBoxControl,
|
|
114
|
-
BorderControl,
|
|
115
|
-
ComboboxControl,
|
|
116
|
-
CustomSelectControl,
|
|
117
|
-
FontAppearanceControl,
|
|
118
|
-
FontFamilyControl,
|
|
119
|
-
FontSizePicker,
|
|
120
|
-
FormTokenField,
|
|
121
106
|
InputControl,
|
|
122
|
-
LetterSpacingControl,
|
|
123
|
-
LineHeightControl,
|
|
124
107
|
NumberControl,
|
|
125
108
|
RangeControl,
|
|
126
109
|
SelectControl,
|
|
127
110
|
ToggleGroupControl,
|
|
128
|
-
UnitControl,
|
|
129
111
|
} from '@wordpress/components';
|
|
130
112
|
<>
|
|
131
|
-
<
|
|
132
|
-
<BorderControl __next40pxDefaultSize />
|
|
133
|
-
<ComboboxControl __next40pxDefaultSize />
|
|
134
|
-
<CustomSelectControl __next40pxDefaultSize />
|
|
135
|
-
<FontAppearanceControl __next40pxDefaultSize />
|
|
136
|
-
<FontFamilyControl __next40pxDefaultSize />
|
|
137
|
-
<FontSizePicker __next40pxDefaultSize />
|
|
138
|
-
<FormTokenField __next40pxDefaultSize />
|
|
113
|
+
<FormTokenField />
|
|
139
114
|
<InputControl __next40pxDefaultSize />
|
|
140
|
-
<LetterSpacingControl __next40pxDefaultSize />
|
|
141
|
-
<LineHeightControl __next40pxDefaultSize />
|
|
142
115
|
<NumberControl __next40pxDefaultSize />
|
|
143
|
-
<RangeControl
|
|
144
|
-
<SelectControl
|
|
145
|
-
<ToggleGroupControl
|
|
146
|
-
<UnitControl __next40pxDefaultSize />
|
|
116
|
+
<RangeControl />
|
|
117
|
+
<SelectControl />
|
|
118
|
+
<ToggleGroupControl />
|
|
147
119
|
</>
|
|
148
120
|
`,
|
|
149
121
|
},
|
|
@@ -178,13 +150,13 @@ ruleTester.run( 'components-no-missing-40px-size-prop', rule, {
|
|
|
178
150
|
// Component with __next40pxDefaultSize={false}
|
|
179
151
|
{
|
|
180
152
|
code: `
|
|
181
|
-
import {
|
|
182
|
-
<
|
|
153
|
+
import { Button } from '@wordpress/components';
|
|
154
|
+
<Button __next40pxDefaultSize={false} />
|
|
183
155
|
`,
|
|
184
156
|
errors: [
|
|
185
157
|
{
|
|
186
158
|
messageId: 'missingProp',
|
|
187
|
-
data: { component: '
|
|
159
|
+
data: { component: 'Button' },
|
|
188
160
|
},
|
|
189
161
|
],
|
|
190
162
|
},
|
|
@@ -214,18 +186,6 @@ ruleTester.run( 'components-no-missing-40px-size-prop', rule, {
|
|
|
214
186
|
},
|
|
215
187
|
],
|
|
216
188
|
},
|
|
217
|
-
// FormFileUpload without __next40pxDefaultSize or render
|
|
218
|
-
{
|
|
219
|
-
code: `
|
|
220
|
-
import { FormFileUpload } from '@wordpress/components';
|
|
221
|
-
<FormFileUpload onChange={handleChange} />
|
|
222
|
-
`,
|
|
223
|
-
errors: [
|
|
224
|
-
{
|
|
225
|
-
messageId: 'missingPropFormFileUpload',
|
|
226
|
-
},
|
|
227
|
-
],
|
|
228
|
-
},
|
|
229
189
|
// Multiple components, some invalid
|
|
230
190
|
{
|
|
231
191
|
code: `
|
|
@@ -256,10 +216,6 @@ ruleTester.run( 'components-no-missing-40px-size-prop', rule, {
|
|
|
256
216
|
messageId: 'missingProp',
|
|
257
217
|
data: { component: 'Button' },
|
|
258
218
|
},
|
|
259
|
-
{
|
|
260
|
-
messageId: 'missingProp',
|
|
261
|
-
data: { component: 'SelectControl' },
|
|
262
|
-
},
|
|
263
219
|
],
|
|
264
220
|
},
|
|
265
221
|
// Relative import with checkLocalImports enabled
|
|
@@ -337,14 +293,6 @@ ruleTester.run(
|
|
|
337
293
|
<InputControl />
|
|
338
294
|
`,
|
|
339
295
|
},
|
|
340
|
-
// FormFileUpload relative import with render prop
|
|
341
|
-
{
|
|
342
|
-
code: `
|
|
343
|
-
import { FormFileUpload } from '../form-file-upload';
|
|
344
|
-
<FormFileUpload render={({ open }) => <button onClick={open}>Upload</button>} />
|
|
345
|
-
`,
|
|
346
|
-
options: [ { checkLocalImports: true } ],
|
|
347
|
-
},
|
|
348
296
|
],
|
|
349
297
|
invalid: [],
|
|
350
298
|
}
|
|
@@ -54,6 +54,13 @@ ruleTester.run( 'no-unsafe-wp-apis', rule, {
|
|
|
54
54
|
options,
|
|
55
55
|
},
|
|
56
56
|
{ code: "import * as s from '@wordpress/package';", options },
|
|
57
|
+
{
|
|
58
|
+
// String-literal imports (e.g. `import { 'a' as b }`) have a
|
|
59
|
+
// non-identifier `imported` node and are ignored by the rule.
|
|
60
|
+
code: "import { '__experimentalUnsafe' as s } from '@wordpress/package';",
|
|
61
|
+
options,
|
|
62
|
+
languageOptions: { sourceType: 'module', ecmaVersion: 2022 },
|
|
63
|
+
},
|
|
57
64
|
],
|
|
58
65
|
|
|
59
66
|
invalid: [
|
|
@@ -12,40 +12,11 @@ const { hasTruthyJsxAttribute } = require( '../utils' );
|
|
|
12
12
|
* These can be exempted if they have a non-default `size` prop.
|
|
13
13
|
*/
|
|
14
14
|
const COMPONENTS_REQUIRING_40PX = new Set( [
|
|
15
|
-
'BorderBoxControl',
|
|
16
|
-
'BorderControl',
|
|
17
15
|
'Button',
|
|
18
16
|
'ClipboardButton',
|
|
19
|
-
'ComboboxControl',
|
|
20
|
-
'CustomSelectControl',
|
|
21
|
-
'FontAppearanceControl',
|
|
22
|
-
'FontFamilyControl',
|
|
23
|
-
'FontSizePicker',
|
|
24
|
-
'FormTokenField',
|
|
25
17
|
'IconButton',
|
|
26
18
|
'InputControl',
|
|
27
|
-
'LetterSpacingControl',
|
|
28
|
-
'LineHeightControl',
|
|
29
19
|
'NumberControl',
|
|
30
|
-
'Radio',
|
|
31
|
-
'RangeControl',
|
|
32
|
-
'SelectControl',
|
|
33
|
-
'TreeSelect',
|
|
34
|
-
'ToggleGroupControl',
|
|
35
|
-
'UnitControl',
|
|
36
|
-
] );
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Components that can use the `render` prop as an alternative to __next40pxDefaultSize.
|
|
40
|
-
*/
|
|
41
|
-
const COMPONENTS_WITH_RENDER_EXEMPTION = new Set( [ 'FormFileUpload' ] );
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* All tracked component names for path-based detection.
|
|
45
|
-
*/
|
|
46
|
-
const ALL_TRACKED_COMPONENTS = new Set( [
|
|
47
|
-
...COMPONENTS_REQUIRING_40PX,
|
|
48
|
-
...COMPONENTS_WITH_RENDER_EXEMPTION,
|
|
49
20
|
] );
|
|
50
21
|
|
|
51
22
|
module.exports = {
|
|
@@ -67,8 +38,6 @@ module.exports = {
|
|
|
67
38
|
messages: {
|
|
68
39
|
missingProp:
|
|
69
40
|
'{{ component }} should have the `__next40pxDefaultSize` prop when using the default size.',
|
|
70
|
-
missingPropFormFileUpload:
|
|
71
|
-
'FormFileUpload should have the `__next40pxDefaultSize` prop to opt-in to the new default size.',
|
|
72
41
|
},
|
|
73
42
|
},
|
|
74
43
|
create( context ) {
|
|
@@ -121,7 +90,7 @@ module.exports = {
|
|
|
121
90
|
.join( '' );
|
|
122
91
|
|
|
123
92
|
// Check if it's one of our tracked components
|
|
124
|
-
if (
|
|
93
|
+
if ( COMPONENTS_REQUIRING_40PX.has( pascalCase ) ) {
|
|
125
94
|
return pascalCase;
|
|
126
95
|
}
|
|
127
96
|
|
|
@@ -166,21 +135,6 @@ module.exports = {
|
|
|
166
135
|
return false;
|
|
167
136
|
}
|
|
168
137
|
|
|
169
|
-
/**
|
|
170
|
-
* Check if the `render` prop exists.
|
|
171
|
-
*
|
|
172
|
-
* @param {Array} attributes - JSX attributes array
|
|
173
|
-
* @return {boolean} Whether render prop exists
|
|
174
|
-
*/
|
|
175
|
-
function hasRenderProp( attributes ) {
|
|
176
|
-
return attributes.some(
|
|
177
|
-
( a ) =>
|
|
178
|
-
a.type === 'JSXAttribute' &&
|
|
179
|
-
a.name &&
|
|
180
|
-
a.name.name === 'render'
|
|
181
|
-
);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
138
|
/**
|
|
185
139
|
* Check if the `variant` prop has the value "link".
|
|
186
140
|
* Button with variant="link" doesn't need __next40pxDefaultSize.
|
|
@@ -230,10 +184,7 @@ module.exports = {
|
|
|
230
184
|
const localName = specifier.local.name;
|
|
231
185
|
|
|
232
186
|
// Track components that require the prop
|
|
233
|
-
if (
|
|
234
|
-
COMPONENTS_REQUIRING_40PX.has( importedName ) ||
|
|
235
|
-
COMPONENTS_WITH_RENDER_EXEMPTION.has( importedName )
|
|
236
|
-
) {
|
|
187
|
+
if ( COMPONENTS_REQUIRING_40PX.has( importedName ) ) {
|
|
237
188
|
trackedImports.set( localName, importedName );
|
|
238
189
|
}
|
|
239
190
|
} );
|
|
@@ -254,7 +205,7 @@ module.exports = {
|
|
|
254
205
|
// Support patterns like `import ClipboardButton from '.';`
|
|
255
206
|
// (common in component folder examples/tests).
|
|
256
207
|
// If the local name matches a tracked component, treat it as such.
|
|
257
|
-
if (
|
|
208
|
+
if ( COMPONENTS_REQUIRING_40PX.has( localName ) ) {
|
|
258
209
|
trackedImports.set( localName, localName );
|
|
259
210
|
}
|
|
260
211
|
}
|
|
@@ -285,20 +236,6 @@ module.exports = {
|
|
|
285
236
|
return;
|
|
286
237
|
}
|
|
287
238
|
|
|
288
|
-
// Handle FormFileUpload special case
|
|
289
|
-
if ( COMPONENTS_WITH_RENDER_EXEMPTION.has( importedName ) ) {
|
|
290
|
-
// FormFileUpload is valid if it has a `render` prop
|
|
291
|
-
if ( hasRenderProp( attributes ) ) {
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
context.report( {
|
|
296
|
-
node,
|
|
297
|
-
messageId: 'missingPropFormFileUpload',
|
|
298
|
-
} );
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
239
|
// For other components, check if size prop has a non-default value
|
|
303
240
|
if ( hasNonDefaultSize( attributes ) ) {
|
|
304
241
|
return;
|
|
@@ -63,6 +63,11 @@ function makeListener( { allowedImports, context } ) {
|
|
|
63
63
|
return;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
/* `imported` may be a string literal (e.g. `import { 'a' as b }`); only identifiers are relevant here. */
|
|
67
|
+
if ( specifierNode.imported.type !== 'Identifier' ) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
66
71
|
const importedName = specifierNode.imported.name;
|
|
67
72
|
|
|
68
73
|
if (
|