@wordpress/eslint-plugin 25.5.1 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/eslint-plugin",
3
- "version": "25.5.1",
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.49.0",
48
- "@wordpress/prettier-config": "^4.49.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.5",
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": "9a75283890dda96ae1d37197b5070fae8c9cf66f"
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
- <BorderBoxControl __next40pxDefaultSize />
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 __next40pxDefaultSize />
144
- <SelectControl __next40pxDefaultSize />
145
- <ToggleGroupControl __next40pxDefaultSize />
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 { SelectControl } from '@wordpress/components';
182
- <SelectControl __next40pxDefaultSize={false} />
153
+ import { Button } from '@wordpress/components';
154
+ <Button __next40pxDefaultSize={false} />
183
155
  `,
184
156
  errors: [
185
157
  {
186
158
  messageId: 'missingProp',
187
- data: { component: 'SelectControl' },
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 ( ALL_TRACKED_COMPONENTS.has( pascalCase ) ) {
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 ( ALL_TRACKED_COMPONENTS.has( localName ) ) {
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 (
@@ -23,6 +23,7 @@ const ALLOWLIST = {
23
23
  'EmptyState',
24
24
  'Icon',
25
25
  'Link',
26
+ 'Skeleton',
26
27
  'Stack',
27
28
  'Tabs',
28
29
  'Text',