@wordpress/eslint-plugin 25.0.1-next.v.202604201441.0 → 25.2.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/README.md +7 -0
- package/configs/babel-parser-compat.js +1 -3
- package/configs/custom.js +1 -0
- package/package.json +6 -6
- package/rules/__tests__/no-non-module-stylesheet-imports.js +39 -0
- package/rules/__tests__/no-setting-ds-tokens.js +52 -0
- package/rules/__tests__/no-unknown-ds-tokens.js +54 -0
- package/rules/__tests__/no-unsafe-render-order.js +136 -0
- package/rules/__tests__/use-import-as.js +271 -0
- package/rules/__tests__/use-recommended-components.js +3 -1
- package/rules/no-ds-tokens.js +1 -3
- package/rules/no-non-module-stylesheet-imports.js +50 -0
- package/rules/no-setting-ds-tokens.js +57 -0
- package/rules/no-unknown-ds-tokens.js +86 -120
- package/rules/no-unsafe-render-order.js +158 -0
- package/rules/no-unsafe-wp-apis.js +1 -1
- package/rules/use-import-as.js +310 -0
- package/rules/use-recommended-components.js +21 -1
- package/utils/ds-token-utils.js +58 -0
package/README.md
CHANGED
|
@@ -127,7 +127,9 @@ The granular rulesets will not define any environment globals. As such, if they
|
|
|
127
127
|
| [no-dom-globals-in-react-fc](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-dom-globals-in-react-fc.md) | Disallow use of DOM globals in the render cycle of a React function component. | |
|
|
128
128
|
| [components-no-missing-40px-size-prop](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/components-no-missing-40px-size-prop.md) | Disallow missing `__next40pxDefaultSize` prop on `@wordpress/components` components. | ✓ |
|
|
129
129
|
| [components-no-unsafe-button-disabled](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/components-no-unsafe-button-disabled.md) | Disallow using `disabled` on Button without `accessibleWhenDisabled`. | ✓ |
|
|
130
|
+
| [no-unsafe-render-order](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-unsafe-render-order.md) | Prevent unsafe `render` composition orders that silently remove semantics. | ✓ |
|
|
130
131
|
| [no-i18n-in-save](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-i18n-in-save.md) | Disallow translation functions in block save methods. | |
|
|
132
|
+
| [no-non-module-stylesheet-imports](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-non-module-stylesheet-imports.md) | Disallow importing non-module stylesheets from JavaScript files. | |
|
|
131
133
|
| [no-unmerged-classname](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-unmerged-classname.md) | Disallow unmerged `className` in components that spread rest props. | |
|
|
132
134
|
| [no-unguarded-get-range-at](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-unguarded-get-range-at.md) | Disallow the usage of unguarded `getRangeAt` calls. | ✓ |
|
|
133
135
|
| [no-unsafe-wp-apis](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-unsafe-wp-apis.md) | Disallow the usage of unsafe APIs from `@wordpress/*` packages | ✓ |
|
|
@@ -135,6 +137,7 @@ The granular rulesets will not define any environment globals. As such, if they
|
|
|
135
137
|
| [no-unused-vars-before-return](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-unused-vars-before-return.md) | Disallow assigning variable values if unused before a return. | ✓ |
|
|
136
138
|
| [no-wp-process-env](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-wp-process-env.md) | Disallow legacy usage of WordPress variables via `process.env` like `process.env.SCRIPT_DEBUG`. | ✓ |
|
|
137
139
|
| [react-no-unsafe-timeout](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/react-no-unsafe-timeout.md) | Disallow unsafe `setTimeout` in component. | |
|
|
140
|
+
| [use-import-as](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/use-import-as.md) | Enforce configured `as` names for specific named imports and unlocked private APIs. | |
|
|
138
141
|
| [valid-sprintf](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/valid-sprintf.md) | Enforce valid sprintf usage. | ✓ |
|
|
139
142
|
| [wp-global-usage](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/wp-global-usage.md) | Enforce correct usage of WordPress globals like `globalThis.SCRIPT_DEBUG`. | |
|
|
140
143
|
|
|
@@ -144,6 +147,7 @@ If you are upgrading from a previous version that used `.eslintrc.*` files:
|
|
|
144
147
|
|
|
145
148
|
1. Replace your `.eslintrc.*` file with an `eslint.config.mjs` file.
|
|
146
149
|
2. Change `extends` arrays to import + spread:
|
|
150
|
+
|
|
147
151
|
```js
|
|
148
152
|
// Old (.eslintrc.js)
|
|
149
153
|
module.exports = {
|
|
@@ -154,14 +158,17 @@ If you are upgrading from a previous version that used `.eslintrc.*` files:
|
|
|
154
158
|
import wordpress from '@wordpress/eslint-plugin';
|
|
155
159
|
export default [ ...wordpress.configs.recommended ];
|
|
156
160
|
```
|
|
161
|
+
|
|
157
162
|
3. Convert `overrides` to separate config objects with `files` patterns.
|
|
158
163
|
4. Replace `env` with `languageOptions.globals` using the [`globals`](https://www.npmjs.com/package/globals) package.
|
|
159
164
|
5. Delete your `.eslintignore` file and move patterns into an `ignores` config object.
|
|
160
165
|
6. Update rule prefixes in inline comments: `eslint-comments/*` has been renamed to `@eslint-community/eslint-comments/*`. For example:
|
|
166
|
+
|
|
161
167
|
```diff
|
|
162
168
|
- /* eslint-disable eslint-comments/no-unlimited-disable */
|
|
163
169
|
+ /* eslint-disable @eslint-community/eslint-comments/no-unlimited-disable */
|
|
164
170
|
```
|
|
171
|
+
|
|
165
172
|
7. Remove any `/* eslint-env */` comments — they are no longer supported in ESLint v10. Use `languageOptions.globals` in your config instead.
|
|
166
173
|
|
|
167
174
|
For a comprehensive walkthrough with examples and troubleshooting, see the [Gutenberg ESLint v10 migration guide](https://github.com/WordPress/gutenberg/blob/HEAD/docs/how-to-guides/eslint-v10-migration.md). See also the [ESLint migration guide](https://eslint.org/docs/latest/use/configure/migration-guide) for general flat config details.
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
/* eslint-disable jsdoc/check-tag-names -- Package names containing @ are not JSDoc tags */
|
|
2
1
|
/**
|
|
3
2
|
* Wrapper around @babel/eslint-parser that ensures compatibility with
|
|
4
3
|
* ESLint v10+. ESLint v10 expects `scopeManager.addGlobals()` which is
|
|
5
4
|
* available in eslint-scope v9 bundled with ESLint v10, but
|
|
6
|
-
*
|
|
5
|
+
* `@babel/eslint-parser` v7 uses an older eslint-scope that does not have
|
|
7
6
|
* this method. This wrapper patches the scope manager when needed.
|
|
8
7
|
*
|
|
9
8
|
* TODO: Remove this wrapper when upgrading to @babel/eslint-parser v8+,
|
|
10
9
|
* which adds native ESLint v10 support (requires @babel/core v8).
|
|
11
10
|
* See https://github.com/babel/babel/issues/17791
|
|
12
11
|
*/
|
|
13
|
-
/* eslint-enable jsdoc/check-tag-names */
|
|
14
12
|
const babelParser = require( '@babel/eslint-parser' );
|
|
15
13
|
|
|
16
14
|
module.exports = {
|
package/configs/custom.js
CHANGED
|
@@ -16,6 +16,7 @@ module.exports = [
|
|
|
16
16
|
'@wordpress/no-unguarded-get-range-at': 'error',
|
|
17
17
|
'@wordpress/no-global-active-element': 'error',
|
|
18
18
|
'@wordpress/no-global-get-selection': 'error',
|
|
19
|
+
'@wordpress/no-unsafe-render-order': 'error',
|
|
19
20
|
'@wordpress/no-setting-ds-tokens': 'error',
|
|
20
21
|
'@wordpress/no-unknown-ds-tokens': 'error',
|
|
21
22
|
'@wordpress/no-unsafe-wp-apis': 'error',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/eslint-plugin",
|
|
3
|
-
"version": "25.
|
|
3
|
+
"version": "25.2.0",
|
|
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.4.0",
|
|
46
46
|
"@eslint/compat": "^2.0.0",
|
|
47
|
-
"@wordpress/babel-preset-default": "^8.
|
|
48
|
-
"@wordpress/prettier-config": "^4.
|
|
49
|
-
"@wordpress/theme": "^0.
|
|
47
|
+
"@wordpress/babel-preset-default": "^8.46.0",
|
|
48
|
+
"@wordpress/prettier-config": "^4.46.0",
|
|
49
|
+
"@wordpress/theme": "^0.13.0",
|
|
50
50
|
"cosmiconfig": "^7.0.0",
|
|
51
51
|
"eslint-config-prettier": "^10.0.0",
|
|
52
52
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"eslint-plugin-playwright": "^2.1.0",
|
|
58
58
|
"eslint-plugin-prettier": "^5.0.0",
|
|
59
59
|
"eslint-plugin-react": "^7.37.0",
|
|
60
|
-
"eslint-plugin-react-hooks": "
|
|
60
|
+
"eslint-plugin-react-hooks": "7.1.1",
|
|
61
61
|
"globals": "^16.0.0",
|
|
62
62
|
"requireindex": "^1.2.0",
|
|
63
63
|
"typescript-eslint": "^8.0.0"
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"publishConfig": {
|
|
84
84
|
"access": "public"
|
|
85
85
|
},
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "51264e33b95fadff9a06b68141e674ce9cde9675"
|
|
87
87
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { RuleTester } from 'eslint';
|
|
2
|
+
import rule from '../no-non-module-stylesheet-imports';
|
|
3
|
+
|
|
4
|
+
const ruleTester = new RuleTester( {
|
|
5
|
+
languageOptions: {
|
|
6
|
+
sourceType: 'module',
|
|
7
|
+
ecmaVersion: 6,
|
|
8
|
+
},
|
|
9
|
+
} );
|
|
10
|
+
|
|
11
|
+
ruleTester.run( 'no-non-module-stylesheet-imports', rule, {
|
|
12
|
+
valid: [
|
|
13
|
+
{ code: "import './component';" },
|
|
14
|
+
{ code: "import styles from './style.module.css';" },
|
|
15
|
+
{ code: "import styles from './style.module.scss';" },
|
|
16
|
+
{ code: "import styles from './style.module.sass';" },
|
|
17
|
+
{ code: "import theme from './style.module.css?inline';" },
|
|
18
|
+
{ code: "import './style.module.css';" },
|
|
19
|
+
{ code: "import './style.module.scss?inline';" },
|
|
20
|
+
],
|
|
21
|
+
invalid: [
|
|
22
|
+
{
|
|
23
|
+
code: "import './style.css';",
|
|
24
|
+
errors: [ { messageId: 'noNonModuleStylesheet' } ],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
code: "import './style.scss';",
|
|
28
|
+
errors: [ { messageId: 'noNonModuleStylesheet' } ],
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
code: "import './style.sass';",
|
|
32
|
+
errors: [ { messageId: 'noNonModuleStylesheet' } ],
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
code: "import styles from './style.scss';",
|
|
36
|
+
errors: [ { messageId: 'noNonModuleStylesheet' } ],
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
} );
|
|
@@ -35,6 +35,18 @@ ruleTester.run( 'no-setting-ds-tokens', rule, {
|
|
|
35
35
|
{
|
|
36
36
|
code: `const { '--wpds-color-fg-content-neutral': neutralColor } = styles;`,
|
|
37
37
|
},
|
|
38
|
+
{
|
|
39
|
+
code: `const css = '--my-custom-prop: red;';`,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
code: 'const css = `--my-custom-prop-${ suffix }: red;`;',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
code: 'const css = `--my-custom-prop: red;`;',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
code: '<style>{ `--my-custom-prop-${ suffix }: red;` }</style>',
|
|
49
|
+
},
|
|
38
50
|
],
|
|
39
51
|
invalid: [
|
|
40
52
|
{
|
|
@@ -77,5 +89,45 @@ ruleTester.run( 'no-setting-ds-tokens', rule, {
|
|
|
77
89
|
},
|
|
78
90
|
],
|
|
79
91
|
},
|
|
92
|
+
{
|
|
93
|
+
code: `const css = '--wpds-color-fg-content-neutral: red;';`,
|
|
94
|
+
errors: [
|
|
95
|
+
{
|
|
96
|
+
messageId: 'disallowedSet',
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
code: 'const css = `--wpds-color-fg-content-neutral: red;`;',
|
|
102
|
+
errors: [
|
|
103
|
+
{
|
|
104
|
+
messageId: 'disallowedSet',
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
code: 'const css = `--wpds-color-fg-content-neutral: ${ value };`;',
|
|
110
|
+
errors: [
|
|
111
|
+
{
|
|
112
|
+
messageId: 'disallowedSet',
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
code: 'const css = `--wpds-color-${ suffix }: red;`;',
|
|
118
|
+
errors: [
|
|
119
|
+
{
|
|
120
|
+
messageId: 'disallowedSet',
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
code: '<style>{ `--wpds-color-${ suffix }: red;` }</style>',
|
|
126
|
+
errors: [
|
|
127
|
+
{
|
|
128
|
+
messageId: 'disallowedSet',
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
},
|
|
80
132
|
],
|
|
81
133
|
} );
|
|
@@ -44,6 +44,15 @@ ruleTester.run( 'no-unknown-ds-tokens', rule, {
|
|
|
44
44
|
{
|
|
45
45
|
code: `const style = { '--wpds-color-fg-content-neutral': 'red' };`,
|
|
46
46
|
},
|
|
47
|
+
{
|
|
48
|
+
code: `const css = '--wpds-color-fg-content-neutral: red;';`,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
code: 'const css = `--wpds-color-fg-content-neutral: red;`;',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
code: 'const css = `--wpds-color-fg-content-neutral: ${ value };`;',
|
|
55
|
+
},
|
|
47
56
|
],
|
|
48
57
|
invalid: [
|
|
49
58
|
{
|
|
@@ -147,6 +156,17 @@ ruleTester.run( 'no-unknown-ds-tokens', rule, {
|
|
|
147
156
|
},
|
|
148
157
|
],
|
|
149
158
|
},
|
|
159
|
+
{
|
|
160
|
+
code: `const css = '--wpds-nonexistent-token: red;';`,
|
|
161
|
+
errors: [
|
|
162
|
+
{
|
|
163
|
+
messageId: 'onlyKnownTokens',
|
|
164
|
+
data: {
|
|
165
|
+
tokenNames: "'--wpds-nonexistent-token'",
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
},
|
|
150
170
|
{
|
|
151
171
|
code: `const token = '--wpds-color-fg-content-neutral';`,
|
|
152
172
|
errors: [
|
|
@@ -202,5 +222,39 @@ ruleTester.run( 'no-unknown-ds-tokens', rule, {
|
|
|
202
222
|
},
|
|
203
223
|
],
|
|
204
224
|
},
|
|
225
|
+
{
|
|
226
|
+
code: `const css = '--wpds-color-fg-content-neutral: red; color: --wpds-color-bg-surface-neutral;';`,
|
|
227
|
+
errors: [
|
|
228
|
+
{
|
|
229
|
+
messageId: 'bareToken',
|
|
230
|
+
data: {
|
|
231
|
+
tokenNames: "'--wpds-color-bg-surface-neutral'",
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
code: `const css = '--wpds-color-fg-content-neutral: red; background: --wpds-color-fg-content-neutral;';`,
|
|
238
|
+
errors: [
|
|
239
|
+
{
|
|
240
|
+
messageId: 'bareToken',
|
|
241
|
+
data: {
|
|
242
|
+
tokenNames: "'--wpds-color-fg-content-neutral'",
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
],
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
code: `const css = '--wpds-other-nonexistent-token: red; color: var(--wpds-nonexistent-token);';`,
|
|
249
|
+
errors: [
|
|
250
|
+
{
|
|
251
|
+
messageId: 'onlyKnownTokens',
|
|
252
|
+
data: {
|
|
253
|
+
tokenNames:
|
|
254
|
+
"'--wpds-other-nonexistent-token', '--wpds-nonexistent-token'",
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
],
|
|
258
|
+
},
|
|
205
259
|
],
|
|
206
260
|
} );
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { RuleTester } from 'eslint';
|
|
2
|
+
import rule from '../no-unsafe-render-order';
|
|
3
|
+
|
|
4
|
+
const ruleTester = new RuleTester( {
|
|
5
|
+
languageOptions: {
|
|
6
|
+
sourceType: 'module',
|
|
7
|
+
ecmaVersion: 6,
|
|
8
|
+
parserOptions: {
|
|
9
|
+
ecmaFeatures: {
|
|
10
|
+
jsx: true,
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
} );
|
|
15
|
+
|
|
16
|
+
ruleTester.run( 'no-unsafe-render-order', rule, {
|
|
17
|
+
valid: [
|
|
18
|
+
{
|
|
19
|
+
code: `
|
|
20
|
+
import { Dialog, VisuallyHidden } from '@wordpress/ui';
|
|
21
|
+
|
|
22
|
+
<VisuallyHidden render={ <Dialog.Title /> }>
|
|
23
|
+
Title
|
|
24
|
+
</VisuallyHidden>;
|
|
25
|
+
`,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
code: `
|
|
29
|
+
import { Text, Link } from '@wordpress/ui';
|
|
30
|
+
|
|
31
|
+
<Text render={ <Link href="#" /> }>Read more</Text>;
|
|
32
|
+
`,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
code: `
|
|
36
|
+
import { Popover } from '@wordpress/ui';
|
|
37
|
+
import { VisuallyHidden } from 'some-other-package';
|
|
38
|
+
|
|
39
|
+
<Popover.Title render={ <VisuallyHidden /> }>
|
|
40
|
+
Title
|
|
41
|
+
</Popover.Title>;
|
|
42
|
+
`,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
code: `
|
|
46
|
+
import { Link } from '@wordpress/ui';
|
|
47
|
+
|
|
48
|
+
<Link href="#">Read more</Link>;
|
|
49
|
+
`,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
code: `
|
|
53
|
+
import { Link } from '@wordpress/ui';
|
|
54
|
+
import { VisuallyHidden } from 'some-other-package';
|
|
55
|
+
|
|
56
|
+
<Link href="#" render={ <VisuallyHidden /> }>
|
|
57
|
+
Read more
|
|
58
|
+
</Link>;
|
|
59
|
+
`,
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
invalid: [
|
|
63
|
+
{
|
|
64
|
+
code: `
|
|
65
|
+
import { Dialog, VisuallyHidden } from '@wordpress/ui';
|
|
66
|
+
|
|
67
|
+
<Dialog.Title render={ <VisuallyHidden /> }>
|
|
68
|
+
Title
|
|
69
|
+
</Dialog.Title>;
|
|
70
|
+
`,
|
|
71
|
+
errors: [ { messageId: 'visuallyHiddenOrder' } ],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
code: `
|
|
75
|
+
import { Dialog as UIDialog, VisuallyHidden as Hidden } from '@wordpress/ui';
|
|
76
|
+
|
|
77
|
+
<UIDialog.Title render={ <Hidden /> }>
|
|
78
|
+
Title
|
|
79
|
+
</UIDialog.Title>;
|
|
80
|
+
`,
|
|
81
|
+
errors: [ { messageId: 'visuallyHiddenOrder' } ],
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
code: `
|
|
85
|
+
import { VisuallyHidden } from '@wordpress/ui';
|
|
86
|
+
|
|
87
|
+
<CustomThing render={ <VisuallyHidden /> }>
|
|
88
|
+
Hidden content
|
|
89
|
+
</CustomThing>;
|
|
90
|
+
`,
|
|
91
|
+
errors: [ { messageId: 'visuallyHiddenOrder' } ],
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
code: `
|
|
95
|
+
import { Link, Text } from '@wordpress/ui';
|
|
96
|
+
|
|
97
|
+
<Link href="#" render={ <Text /> }>
|
|
98
|
+
Read more
|
|
99
|
+
</Link>;
|
|
100
|
+
`,
|
|
101
|
+
errors: [ { messageId: 'linkTextOrder' } ],
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
code: `
|
|
105
|
+
import { Link as UILink, Text as UIText } from '@wordpress/ui';
|
|
106
|
+
|
|
107
|
+
<UILink href="#" render={ <UIText /> }>
|
|
108
|
+
Read more
|
|
109
|
+
</UILink>;
|
|
110
|
+
`,
|
|
111
|
+
errors: [ { messageId: 'linkTextOrder' } ],
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
code: `
|
|
115
|
+
import * as Field from '../index';
|
|
116
|
+
import { VisuallyHidden } from '../../../visually-hidden';
|
|
117
|
+
|
|
118
|
+
<Field.Label render={ <VisuallyHidden /> }>Name</Field.Label>;
|
|
119
|
+
`,
|
|
120
|
+
options: [ { checkLocalImports: true } ],
|
|
121
|
+
errors: [ { messageId: 'visuallyHiddenOrder' } ],
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
code: `
|
|
125
|
+
import { Link } from '../index';
|
|
126
|
+
import { Text } from '../../text';
|
|
127
|
+
|
|
128
|
+
<Link href="#" render={ <Text /> }>
|
|
129
|
+
Read more
|
|
130
|
+
</Link>;
|
|
131
|
+
`,
|
|
132
|
+
options: [ { checkLocalImports: true } ],
|
|
133
|
+
errors: [ { messageId: 'linkTextOrder' } ],
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
} );
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { RuleTester } from 'eslint';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import rule from '../use-import-as';
|
|
10
|
+
|
|
11
|
+
const ruleTester = new RuleTester( {
|
|
12
|
+
languageOptions: {
|
|
13
|
+
sourceType: 'module',
|
|
14
|
+
ecmaVersion: 2022,
|
|
15
|
+
},
|
|
16
|
+
} );
|
|
17
|
+
|
|
18
|
+
const options = [
|
|
19
|
+
{
|
|
20
|
+
'@wordpress/components': {
|
|
21
|
+
Badge: 'WCBadge',
|
|
22
|
+
VisuallyHidden: 'WCVisuallyHidden',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const withSuggestions = ( message, output, desc ) => ( {
|
|
28
|
+
message,
|
|
29
|
+
suggestions: [
|
|
30
|
+
{
|
|
31
|
+
desc,
|
|
32
|
+
output,
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
} );
|
|
36
|
+
|
|
37
|
+
ruleTester.run( 'use-import-as', rule, {
|
|
38
|
+
valid: [
|
|
39
|
+
// With no config, the rule is a no-op.
|
|
40
|
+
{
|
|
41
|
+
code: "import { VisuallyHidden } from '@wordpress/components';",
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
// Unrelated packages are not affected.
|
|
45
|
+
{
|
|
46
|
+
code: "import { VisuallyHidden } from '@wordpress/ui';",
|
|
47
|
+
options,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
code: "import { Button } from '@wordpress/components';",
|
|
51
|
+
options,
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
// Default and namespace imports are not affected.
|
|
55
|
+
{
|
|
56
|
+
code: "import Components from '@wordpress/components';",
|
|
57
|
+
options,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
code: "import * as Components from '@wordpress/components';",
|
|
61
|
+
options,
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
// Configured `as` names are allowed.
|
|
65
|
+
{
|
|
66
|
+
code: "import { VisuallyHidden as WCVisuallyHidden } from '@wordpress/components';",
|
|
67
|
+
options,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
code: 'import { "VisuallyHidden" as WCVisuallyHidden } from \'@wordpress/components\';',
|
|
71
|
+
options,
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
code: "import { Button, VisuallyHidden as WCVisuallyHidden } from '@wordpress/components';",
|
|
75
|
+
options,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
code: `
|
|
79
|
+
import { privateApis as componentsPrivateApis } from '@wordpress/components';
|
|
80
|
+
import { unlock } from '../../lock-unlock';
|
|
81
|
+
|
|
82
|
+
const { Badge: WCBadge } = unlock( componentsPrivateApis );
|
|
83
|
+
`,
|
|
84
|
+
options,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
code: `
|
|
88
|
+
import { privateApis } from '@wordpress/components';
|
|
89
|
+
import { unlock } from '../../lock-unlock';
|
|
90
|
+
|
|
91
|
+
const { Badge: WCBadge } = unlock( privateApis );
|
|
92
|
+
`,
|
|
93
|
+
options,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
code: `
|
|
97
|
+
import { privateApis } from '@wordpress/components';
|
|
98
|
+
import { unlock as open } from '../../lock-unlock';
|
|
99
|
+
|
|
100
|
+
const { Badge: WCBadge = fallbackBadge } = open( privateApis );
|
|
101
|
+
`,
|
|
102
|
+
options,
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
code: `
|
|
106
|
+
import { privateApis as uiPrivateApis } from '@wordpress/ui';
|
|
107
|
+
import { unlock } from '../../lock-unlock';
|
|
108
|
+
|
|
109
|
+
const { Badge } = unlock( uiPrivateApis );
|
|
110
|
+
`,
|
|
111
|
+
options,
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
code: `
|
|
115
|
+
import { privateApis } from '@wordpress/components';
|
|
116
|
+
import { unlock } from '../../lock-unlock';
|
|
117
|
+
|
|
118
|
+
const { [ badgeKey ]: Badge } = unlock( privateApis );
|
|
119
|
+
`,
|
|
120
|
+
options,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
code: `
|
|
124
|
+
import { privateApis } from '@wordpress/components';
|
|
125
|
+
import { unlock } from '../../lock-unlock';
|
|
126
|
+
|
|
127
|
+
function test() {
|
|
128
|
+
function unlock( value ) {
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const { Badge } = unlock( privateApis );
|
|
133
|
+
|
|
134
|
+
return Badge;
|
|
135
|
+
}
|
|
136
|
+
`,
|
|
137
|
+
options,
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
|
|
141
|
+
invalid: [
|
|
142
|
+
{
|
|
143
|
+
code: "import { VisuallyHidden } from '@wordpress/components';",
|
|
144
|
+
options,
|
|
145
|
+
errors: [
|
|
146
|
+
withSuggestions(
|
|
147
|
+
'`VisuallyHidden` from `@wordpress/components` must be imported as `WCVisuallyHidden`.',
|
|
148
|
+
"import { VisuallyHidden as WCVisuallyHidden } from '@wordpress/components';",
|
|
149
|
+
'Import as `WCVisuallyHidden`.'
|
|
150
|
+
),
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
code: "import { VisuallyHidden as Hidden } from '@wordpress/components';",
|
|
155
|
+
options,
|
|
156
|
+
errors: [
|
|
157
|
+
withSuggestions(
|
|
158
|
+
'`VisuallyHidden` from `@wordpress/components` must be imported as `WCVisuallyHidden`.',
|
|
159
|
+
"import { VisuallyHidden as WCVisuallyHidden } from '@wordpress/components';",
|
|
160
|
+
'Import as `WCVisuallyHidden`.'
|
|
161
|
+
),
|
|
162
|
+
],
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
code: 'import { "VisuallyHidden" as Hidden } from \'@wordpress/components\';',
|
|
166
|
+
options,
|
|
167
|
+
errors: [
|
|
168
|
+
withSuggestions(
|
|
169
|
+
'`VisuallyHidden` from `@wordpress/components` must be imported as `WCVisuallyHidden`.',
|
|
170
|
+
'import { "VisuallyHidden" as WCVisuallyHidden } from \'@wordpress/components\';',
|
|
171
|
+
'Import as `WCVisuallyHidden`.'
|
|
172
|
+
),
|
|
173
|
+
],
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
code: "import { Button, VisuallyHidden } from '@wordpress/components';",
|
|
177
|
+
options,
|
|
178
|
+
errors: [
|
|
179
|
+
withSuggestions(
|
|
180
|
+
'`VisuallyHidden` from `@wordpress/components` must be imported as `WCVisuallyHidden`.',
|
|
181
|
+
"import { Button, VisuallyHidden as WCVisuallyHidden } from '@wordpress/components';",
|
|
182
|
+
'Import as `WCVisuallyHidden`.'
|
|
183
|
+
),
|
|
184
|
+
],
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
code: `
|
|
188
|
+
import { privateApis as componentsPrivateApis } from '@wordpress/components';
|
|
189
|
+
import { unlock } from '../../lock-unlock';
|
|
190
|
+
|
|
191
|
+
const { Badge } = unlock( componentsPrivateApis );
|
|
192
|
+
`,
|
|
193
|
+
options,
|
|
194
|
+
errors: [
|
|
195
|
+
withSuggestions(
|
|
196
|
+
'`Badge` from `@wordpress/components` must be imported as `WCBadge`.',
|
|
197
|
+
`
|
|
198
|
+
import { privateApis as componentsPrivateApis } from '@wordpress/components';
|
|
199
|
+
import { unlock } from '../../lock-unlock';
|
|
200
|
+
|
|
201
|
+
const { Badge: WCBadge } = unlock( componentsPrivateApis );
|
|
202
|
+
`,
|
|
203
|
+
'Destructure as `WCBadge`.'
|
|
204
|
+
),
|
|
205
|
+
],
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
code: `
|
|
209
|
+
import { privateApis } from '@wordpress/components';
|
|
210
|
+
import { unlock } from '../../lock-unlock';
|
|
211
|
+
|
|
212
|
+
const { Badge: HiddenBadge } = unlock( privateApis );
|
|
213
|
+
`,
|
|
214
|
+
options,
|
|
215
|
+
errors: [
|
|
216
|
+
withSuggestions(
|
|
217
|
+
'`Badge` from `@wordpress/components` must be imported as `WCBadge`.',
|
|
218
|
+
`
|
|
219
|
+
import { privateApis } from '@wordpress/components';
|
|
220
|
+
import { unlock } from '../../lock-unlock';
|
|
221
|
+
|
|
222
|
+
const { Badge: WCBadge } = unlock( privateApis );
|
|
223
|
+
`,
|
|
224
|
+
'Destructure as `WCBadge`.'
|
|
225
|
+
),
|
|
226
|
+
],
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
code: `
|
|
230
|
+
import { privateApis } from '@wordpress/components';
|
|
231
|
+
import { unlock } from '../../lock-unlock';
|
|
232
|
+
|
|
233
|
+
const { Badge: HiddenBadge = fallbackBadge } = unlock( privateApis );
|
|
234
|
+
`,
|
|
235
|
+
options,
|
|
236
|
+
errors: [
|
|
237
|
+
withSuggestions(
|
|
238
|
+
'`Badge` from `@wordpress/components` must be imported as `WCBadge`.',
|
|
239
|
+
`
|
|
240
|
+
import { privateApis } from '@wordpress/components';
|
|
241
|
+
import { unlock } from '../../lock-unlock';
|
|
242
|
+
|
|
243
|
+
const { Badge: WCBadge = fallbackBadge } = unlock( privateApis );
|
|
244
|
+
`,
|
|
245
|
+
'Destructure as `WCBadge`.'
|
|
246
|
+
),
|
|
247
|
+
],
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
code: `
|
|
251
|
+
import { privateApis } from '@wordpress/components';
|
|
252
|
+
import { unlock } from '../../lock-unlock';
|
|
253
|
+
|
|
254
|
+
const { Badge = fallbackBadge } = unlock( privateApis );
|
|
255
|
+
`,
|
|
256
|
+
options,
|
|
257
|
+
errors: [
|
|
258
|
+
withSuggestions(
|
|
259
|
+
'`Badge` from `@wordpress/components` must be imported as `WCBadge`.',
|
|
260
|
+
`
|
|
261
|
+
import { privateApis } from '@wordpress/components';
|
|
262
|
+
import { unlock } from '../../lock-unlock';
|
|
263
|
+
|
|
264
|
+
const { Badge: WCBadge = fallbackBadge } = unlock( privateApis );
|
|
265
|
+
`,
|
|
266
|
+
'Destructure as `WCBadge`.'
|
|
267
|
+
),
|
|
268
|
+
],
|
|
269
|
+
},
|
|
270
|
+
],
|
|
271
|
+
} );
|