@wordpress/eslint-plugin 24.3.1-next.v.202603102151.0 → 24.4.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 +5 -0
- package/package.json +5 -5
- package/rules/__tests__/no-dom-globals-in-constructor.js +56 -0
- package/rules/__tests__/no-dom-globals-in-module-scope.js +117 -0
- package/rules/__tests__/no-dom-globals-in-react-cc-render.js +51 -0
- package/rules/__tests__/no-dom-globals-in-react-fc.js +77 -0
- package/rules/__tests__/no-i18n-in-save.js +0 -14
- package/rules/__tests__/no-setting-ds-tokens.js +33 -0
- package/rules/__tests__/no-unknown-ds-tokens.js +58 -0
- package/rules/__tests__/no-unsafe-wp-apis.js +0 -5
- package/rules/__tests__/use-recommended-components.js +91 -0
- package/rules/data-no-store-string-literals.js +8 -5
- package/rules/dependency-group.js +3 -4
- package/rules/i18n-translator-comments.js +6 -2
- package/rules/no-dom-globals-in-constructor.js +17 -0
- package/rules/no-dom-globals-in-module-scope.js +12 -0
- package/rules/no-dom-globals-in-react-cc-render.js +26 -0
- package/rules/no-dom-globals-in-react-fc.js +17 -0
- package/rules/no-i18n-in-save.js +1 -1
- package/rules/no-setting-ds-tokens.js +2 -4
- package/rules/no-unknown-ds-tokens.js +68 -19
- package/rules/no-unused-vars-before-return.js +7 -6
- package/rules/react-no-unsafe-timeout.js +1 -1
- package/rules/use-recommended-components.js +114 -0
- package/utils/dom-globals.js +156 -0
package/README.md
CHANGED
|
@@ -82,11 +82,16 @@ The granular rulesets will not define any environment globals. As such, if they
|
|
|
82
82
|
| [i18n-text-domain](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-text-domain.md) | Enforce passing valid text domains. | ✓ |
|
|
83
83
|
| [i18n-translator-comments](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/i18n-translator-comments.md) | Enforce adding translator comments. | ✓ |
|
|
84
84
|
| [no-base-control-with-label-without-id](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-base-control-with-label-without-id.md) | Disallow the usage of BaseControl component with a label prop set but omitting the id property. | ✓ |
|
|
85
|
+
| [no-dom-globals-in-constructor](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-dom-globals-in-constructor.md) | Disallow use of DOM globals in class constructors. | |
|
|
86
|
+
| [no-dom-globals-in-module-scope](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-dom-globals-in-module-scope.md) | Disallow use of DOM globals in module scope. | |
|
|
87
|
+
| [no-dom-globals-in-react-cc-render](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/no-dom-globals-in-react-cc-render.md) | Disallow use of DOM globals in React class component render methods. | |
|
|
88
|
+
| [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. | |
|
|
85
89
|
| [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. | ✓ |
|
|
86
90
|
| [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`. | ✓ |
|
|
87
91
|
| [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. | |
|
|
88
92
|
| [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. | ✓ |
|
|
89
93
|
| [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 | ✓ |
|
|
94
|
+
| [use-recommended-components](https://github.com/WordPress/gutenberg/tree/HEAD/packages/eslint-plugin/docs/rules/use-recommended-components.md) | Encourage the use of recommended UI components in a WordPress environment. | |
|
|
90
95
|
| [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. | ✓ |
|
|
91
96
|
| [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`. | ✓ |
|
|
92
97
|
| [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. | |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/eslint-plugin",
|
|
3
|
-
"version": "24.
|
|
3
|
+
"version": "24.4.0",
|
|
4
4
|
"description": "ESLint plugin for WordPress development.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"@babel/eslint-parser": "7.25.7",
|
|
41
41
|
"@typescript-eslint/eslint-plugin": "^6.4.1",
|
|
42
42
|
"@typescript-eslint/parser": "^6.4.1",
|
|
43
|
-
"@wordpress/babel-preset-default": "^8.
|
|
44
|
-
"@wordpress/prettier-config": "^4.
|
|
45
|
-
"@wordpress/theme": "^0.
|
|
43
|
+
"@wordpress/babel-preset-default": "^8.42.0",
|
|
44
|
+
"@wordpress/prettier-config": "^4.42.0",
|
|
45
|
+
"@wordpress/theme": "^0.9.0",
|
|
46
46
|
"cosmiconfig": "^7.0.0",
|
|
47
47
|
"eslint-config-prettier": "^8.3.0",
|
|
48
48
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
@@ -78,5 +78,5 @@
|
|
|
78
78
|
"publishConfig": {
|
|
79
79
|
"access": "public"
|
|
80
80
|
},
|
|
81
|
-
"gitHead": "
|
|
81
|
+
"gitHead": "c20787b1778ae64c2db65643b1c236309d68e6ba"
|
|
82
82
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { RuleTester } from 'eslint';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import rule from '../no-dom-globals-in-constructor';
|
|
10
|
+
|
|
11
|
+
const ruleTester = new RuleTester( {
|
|
12
|
+
parserOptions: {
|
|
13
|
+
ecmaVersion: 2020,
|
|
14
|
+
sourceType: 'module',
|
|
15
|
+
ecmaFeatures: { jsx: true },
|
|
16
|
+
},
|
|
17
|
+
} );
|
|
18
|
+
|
|
19
|
+
ruleTester.run( 'no-dom-globals-in-constructor', rule, {
|
|
20
|
+
valid: [
|
|
21
|
+
{
|
|
22
|
+
code: `class Foo {
|
|
23
|
+
method() { document.title = "test"; }
|
|
24
|
+
}`,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
code: `class Foo {
|
|
28
|
+
constructor() { this.name = "test"; }
|
|
29
|
+
}`,
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
invalid: [
|
|
33
|
+
{
|
|
34
|
+
code: `class Foo {
|
|
35
|
+
constructor() { document.title = "test"; }
|
|
36
|
+
}`,
|
|
37
|
+
errors: [
|
|
38
|
+
{
|
|
39
|
+
messageId: 'defaultMessage',
|
|
40
|
+
data: { name: 'document' },
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
code: `class Foo {
|
|
46
|
+
constructor() { window.addEventListener("resize", () => {}); }
|
|
47
|
+
}`,
|
|
48
|
+
errors: [
|
|
49
|
+
{
|
|
50
|
+
messageId: 'defaultMessage',
|
|
51
|
+
data: { name: 'window' },
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
} );
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { RuleTester } from 'eslint';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import rule from '../no-dom-globals-in-module-scope';
|
|
10
|
+
|
|
11
|
+
const ruleTester = new RuleTester( {
|
|
12
|
+
parserOptions: {
|
|
13
|
+
ecmaVersion: 2020,
|
|
14
|
+
sourceType: 'module',
|
|
15
|
+
ecmaFeatures: { jsx: true },
|
|
16
|
+
},
|
|
17
|
+
} );
|
|
18
|
+
|
|
19
|
+
ruleTester.run( 'no-dom-globals-in-module-scope', rule, {
|
|
20
|
+
valid: [
|
|
21
|
+
{
|
|
22
|
+
code: 'function foo() { window.scrollTo(0, 0); }',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
code: 'if (typeof window !== "undefined") {}',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
code: 'const isClient = typeof document !== "undefined";',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
code: 'function effect() { const el = document.createElement("div"); }',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
// Function scope in a script file should not be flagged.
|
|
35
|
+
code: 'function foo() { window.scrollTo(0, 0); }',
|
|
36
|
+
parserOptions: { ecmaVersion: 2020, sourceType: 'script' },
|
|
37
|
+
},
|
|
38
|
+
// Shared globals (browser + node) should NOT be flagged.
|
|
39
|
+
{
|
|
40
|
+
code: 'console.log("hello");',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
code: 'setTimeout(() => {}, 100);',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
code: 'const u = new URL("https://example.com");',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
code: 'fetch("/api/data");',
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
invalid: [
|
|
53
|
+
{
|
|
54
|
+
code: 'const width = window.innerWidth;',
|
|
55
|
+
errors: [
|
|
56
|
+
{
|
|
57
|
+
messageId: 'defaultMessage',
|
|
58
|
+
data: { name: 'window' },
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
code: 'const el = document.createElement("div");',
|
|
64
|
+
errors: [
|
|
65
|
+
{
|
|
66
|
+
messageId: 'defaultMessage',
|
|
67
|
+
data: { name: 'document' },
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
code: 'navigator.userAgent;',
|
|
73
|
+
errors: [
|
|
74
|
+
{
|
|
75
|
+
messageId: 'defaultMessage',
|
|
76
|
+
data: { name: 'navigator' },
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
code: 'localStorage.getItem("key");',
|
|
82
|
+
errors: [
|
|
83
|
+
{
|
|
84
|
+
messageId: 'defaultMessage',
|
|
85
|
+
data: { name: 'localStorage' },
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
code: 'sessionStorage.setItem("key", "value");',
|
|
91
|
+
errors: [
|
|
92
|
+
{
|
|
93
|
+
messageId: 'defaultMessage',
|
|
94
|
+
data: { name: 'sessionStorage' },
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
code: 'history.pushState({}, "", "/new");',
|
|
100
|
+
errors: [
|
|
101
|
+
{
|
|
102
|
+
messageId: 'defaultMessage',
|
|
103
|
+
data: { name: 'history' },
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
code: 'location.href = "/";',
|
|
109
|
+
errors: [
|
|
110
|
+
{
|
|
111
|
+
messageId: 'defaultMessage',
|
|
112
|
+
data: { name: 'location' },
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
} );
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { RuleTester } from 'eslint';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import rule from '../no-dom-globals-in-react-cc-render';
|
|
10
|
+
|
|
11
|
+
const ruleTester = new RuleTester( {
|
|
12
|
+
parserOptions: {
|
|
13
|
+
ecmaVersion: 2020,
|
|
14
|
+
sourceType: 'module',
|
|
15
|
+
ecmaFeatures: { jsx: true },
|
|
16
|
+
},
|
|
17
|
+
} );
|
|
18
|
+
|
|
19
|
+
ruleTester.run( 'no-dom-globals-in-react-cc-render', rule, {
|
|
20
|
+
valid: [
|
|
21
|
+
{
|
|
22
|
+
code: `class Foo {
|
|
23
|
+
render() { const x = 1; return <div>{x}</div>; }
|
|
24
|
+
}`,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
code: `class Foo {
|
|
28
|
+
componentDidMount() { window.scrollTo(0, 0); }
|
|
29
|
+
render() { return <div />; }
|
|
30
|
+
}`,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
code: `class Foo {
|
|
34
|
+
render() { return "not jsx"; }
|
|
35
|
+
}`,
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
invalid: [
|
|
39
|
+
{
|
|
40
|
+
code: `class Foo {
|
|
41
|
+
render() { const w = window.innerWidth; return <div>{w}</div>; }
|
|
42
|
+
}`,
|
|
43
|
+
errors: [
|
|
44
|
+
{
|
|
45
|
+
messageId: 'defaultMessage',
|
|
46
|
+
data: { name: 'window' },
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
} );
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { RuleTester } from 'eslint';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import rule from '../no-dom-globals-in-react-fc';
|
|
10
|
+
|
|
11
|
+
const ruleTester = new RuleTester( {
|
|
12
|
+
parserOptions: {
|
|
13
|
+
ecmaVersion: 2020,
|
|
14
|
+
sourceType: 'module',
|
|
15
|
+
ecmaFeatures: { jsx: true },
|
|
16
|
+
},
|
|
17
|
+
} );
|
|
18
|
+
|
|
19
|
+
ruleTester.run( 'no-dom-globals-in-react-fc', rule, {
|
|
20
|
+
valid: [
|
|
21
|
+
{
|
|
22
|
+
code: 'function notAComponent() { window.scrollTo(0, 0); }',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
code: 'function Component() { return <div />; }',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
code: `function Component() {
|
|
29
|
+
useEffect(() => { window.scrollTo(0, 0); });
|
|
30
|
+
return <div />;
|
|
31
|
+
}`,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
// DOM global inside a nested callback (event handler) inside FC
|
|
35
|
+
// is allowed — the handler runs at event time, not render time.
|
|
36
|
+
code: `function Component() {
|
|
37
|
+
const onClick = () => { document.title = "clicked"; };
|
|
38
|
+
return <button onClick={onClick} />;
|
|
39
|
+
}`,
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
invalid: [
|
|
43
|
+
{
|
|
44
|
+
code: `function Component() {
|
|
45
|
+
window.addEventListener("resize", () => {});
|
|
46
|
+
return <div />;
|
|
47
|
+
}`,
|
|
48
|
+
errors: [
|
|
49
|
+
{
|
|
50
|
+
messageId: 'defaultMessage',
|
|
51
|
+
data: { name: 'window' },
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
code: `const Header = () => {
|
|
57
|
+
const w = document.body.clientWidth;
|
|
58
|
+
return <header>{w}</header>;
|
|
59
|
+
}`,
|
|
60
|
+
errors: [
|
|
61
|
+
{
|
|
62
|
+
messageId: 'defaultMessage',
|
|
63
|
+
data: { name: 'document' },
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
code: `const Icon = ( { name } ) => <span className={ window.iconPrefix + name } />;`,
|
|
69
|
+
errors: [
|
|
70
|
+
{
|
|
71
|
+
messageId: 'defaultMessage',
|
|
72
|
+
data: { name: 'window' },
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
} );
|
|
@@ -90,7 +90,6 @@ function render() {
|
|
|
90
90
|
errors: [
|
|
91
91
|
{
|
|
92
92
|
messageId: 'noI18nInSave',
|
|
93
|
-
type: 'CallExpression',
|
|
94
93
|
},
|
|
95
94
|
],
|
|
96
95
|
},
|
|
@@ -103,7 +102,6 @@ function save() {
|
|
|
103
102
|
errors: [
|
|
104
103
|
{
|
|
105
104
|
messageId: 'noI18nInSave',
|
|
106
|
-
type: 'CallExpression',
|
|
107
105
|
},
|
|
108
106
|
],
|
|
109
107
|
},
|
|
@@ -116,7 +114,6 @@ const save = () => {
|
|
|
116
114
|
errors: [
|
|
117
115
|
{
|
|
118
116
|
messageId: 'noI18nInSave',
|
|
119
|
-
type: 'CallExpression',
|
|
120
117
|
},
|
|
121
118
|
],
|
|
122
119
|
},
|
|
@@ -129,7 +126,6 @@ const save = function() {
|
|
|
129
126
|
errors: [
|
|
130
127
|
{
|
|
131
128
|
messageId: 'noI18nInSave',
|
|
132
|
-
type: 'CallExpression',
|
|
133
129
|
},
|
|
134
130
|
],
|
|
135
131
|
},
|
|
@@ -142,7 +138,6 @@ export default function save() {
|
|
|
142
138
|
errors: [
|
|
143
139
|
{
|
|
144
140
|
messageId: 'noI18nInSave',
|
|
145
|
-
type: 'CallExpression',
|
|
146
141
|
},
|
|
147
142
|
],
|
|
148
143
|
},
|
|
@@ -157,7 +152,6 @@ const settings = {
|
|
|
157
152
|
errors: [
|
|
158
153
|
{
|
|
159
154
|
messageId: 'noI18nInSave',
|
|
160
|
-
type: 'CallExpression',
|
|
161
155
|
},
|
|
162
156
|
],
|
|
163
157
|
},
|
|
@@ -170,7 +164,6 @@ const settings = {
|
|
|
170
164
|
errors: [
|
|
171
165
|
{
|
|
172
166
|
messageId: 'noI18nInSave',
|
|
173
|
-
type: 'CallExpression',
|
|
174
167
|
},
|
|
175
168
|
],
|
|
176
169
|
},
|
|
@@ -183,7 +176,6 @@ function save() {
|
|
|
183
176
|
errors: [
|
|
184
177
|
{
|
|
185
178
|
messageId: 'noI18nInSave',
|
|
186
|
-
type: 'CallExpression',
|
|
187
179
|
},
|
|
188
180
|
],
|
|
189
181
|
},
|
|
@@ -197,7 +189,6 @@ function save() {
|
|
|
197
189
|
errors: [
|
|
198
190
|
{
|
|
199
191
|
messageId: 'noI18nInSave',
|
|
200
|
-
type: 'CallExpression',
|
|
201
192
|
},
|
|
202
193
|
],
|
|
203
194
|
},
|
|
@@ -211,7 +202,6 @@ function save() {
|
|
|
211
202
|
errors: [
|
|
212
203
|
{
|
|
213
204
|
messageId: 'noI18nInSave',
|
|
214
|
-
type: 'CallExpression',
|
|
215
205
|
},
|
|
216
206
|
],
|
|
217
207
|
},
|
|
@@ -228,7 +218,6 @@ function save() {
|
|
|
228
218
|
errors: [
|
|
229
219
|
{
|
|
230
220
|
messageId: 'noI18nInSave',
|
|
231
|
-
type: 'CallExpression',
|
|
232
221
|
},
|
|
233
222
|
],
|
|
234
223
|
},
|
|
@@ -243,11 +232,9 @@ function save() {
|
|
|
243
232
|
errors: [
|
|
244
233
|
{
|
|
245
234
|
messageId: 'noI18nInSave',
|
|
246
|
-
type: 'CallExpression',
|
|
247
235
|
},
|
|
248
236
|
{
|
|
249
237
|
messageId: 'noI18nInSave',
|
|
250
|
-
type: 'CallExpression',
|
|
251
238
|
},
|
|
252
239
|
],
|
|
253
240
|
},
|
|
@@ -262,7 +249,6 @@ function save() {
|
|
|
262
249
|
errors: [
|
|
263
250
|
{
|
|
264
251
|
messageId: 'noI18nInSave',
|
|
265
|
-
type: 'CallExpression',
|
|
266
252
|
},
|
|
267
253
|
],
|
|
268
254
|
},
|
|
@@ -24,6 +24,15 @@ ruleTester.run( 'no-setting-ds-tokens', rule, {
|
|
|
24
24
|
{
|
|
25
25
|
code: `<div style={ { margin: '10px' } } />`,
|
|
26
26
|
},
|
|
27
|
+
{
|
|
28
|
+
code: `const styles = { '--my-custom-prop': 'value' };`,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
code: `const styles = { color: 'var(--wpds-color-fg-content-neutral)' };`,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
code: `const { '--wpds-color-fg-content-neutral': neutralColor } = styles;`,
|
|
35
|
+
},
|
|
27
36
|
],
|
|
28
37
|
invalid: [
|
|
29
38
|
{
|
|
@@ -42,5 +51,29 @@ ruleTester.run( 'no-setting-ds-tokens', rule, {
|
|
|
42
51
|
},
|
|
43
52
|
],
|
|
44
53
|
},
|
|
54
|
+
{
|
|
55
|
+
code: `const styles = { '--wpds-color-fg-content-neutral': 'red' };`,
|
|
56
|
+
errors: [
|
|
57
|
+
{
|
|
58
|
+
messageId: 'disallowedSet',
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
code: `function getStyles() { return { '--wpds-font-size-md': '10px' }; }`,
|
|
64
|
+
errors: [
|
|
65
|
+
{
|
|
66
|
+
messageId: 'disallowedSet',
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
code: `const config = { inner: { '--wpds-color-fg-content-neutral': 'red' } };`,
|
|
72
|
+
errors: [
|
|
73
|
+
{
|
|
74
|
+
messageId: 'disallowedSet',
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
},
|
|
45
78
|
],
|
|
46
79
|
} );
|
|
@@ -39,6 +39,9 @@ ruleTester.run( 'no-unknown-ds-tokens', rule, {
|
|
|
39
39
|
{
|
|
40
40
|
code: '`var(--wpds-color-fg-content-neutral) ${ suffix }`',
|
|
41
41
|
},
|
|
42
|
+
{
|
|
43
|
+
code: `const style = { '--wpds-color-fg-content-neutral': 'red' };`,
|
|
44
|
+
},
|
|
42
45
|
],
|
|
43
46
|
invalid: [
|
|
44
47
|
{
|
|
@@ -142,5 +145,60 @@ ruleTester.run( 'no-unknown-ds-tokens', rule, {
|
|
|
142
145
|
},
|
|
143
146
|
],
|
|
144
147
|
},
|
|
148
|
+
{
|
|
149
|
+
code: `const token = '--wpds-color-fg-content-neutral';`,
|
|
150
|
+
errors: [
|
|
151
|
+
{
|
|
152
|
+
messageId: 'bareToken',
|
|
153
|
+
data: {
|
|
154
|
+
tokenNames: "'--wpds-color-fg-content-neutral'",
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
code: 'const token = `--wpds-color-fg-content-neutral`;',
|
|
161
|
+
errors: [
|
|
162
|
+
{
|
|
163
|
+
messageId: 'bareToken',
|
|
164
|
+
data: {
|
|
165
|
+
tokenNames: "'--wpds-color-fg-content-neutral'",
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
code: '<div style={ { gap: `--wpds-color-fg-content-neutral` } } />',
|
|
172
|
+
errors: [
|
|
173
|
+
{
|
|
174
|
+
messageId: 'bareToken',
|
|
175
|
+
data: {
|
|
176
|
+
tokenNames: "'--wpds-color-fg-content-neutral'",
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
code: '`${ prefix }: --wpds-color-fg-content-neutral`',
|
|
183
|
+
errors: [
|
|
184
|
+
{
|
|
185
|
+
messageId: 'bareToken',
|
|
186
|
+
data: {
|
|
187
|
+
tokenNames: "'--wpds-color-fg-content-neutral'",
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
code: '`var(--wpds-color-fg-content-neutral) --wpds-color-fg-content-neutral ${ x }`',
|
|
194
|
+
errors: [
|
|
195
|
+
{
|
|
196
|
+
messageId: 'bareToken',
|
|
197
|
+
data: {
|
|
198
|
+
tokenNames: "'--wpds-color-fg-content-neutral'",
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
],
|
|
202
|
+
},
|
|
145
203
|
],
|
|
146
204
|
} );
|
|
@@ -64,7 +64,6 @@ ruleTester.run( 'no-unsafe-wp-apis', rule, {
|
|
|
64
64
|
{
|
|
65
65
|
message: `Usage of \`__experimentalUnsafe\` from \`@wordpress/package\` is not allowed.
|
|
66
66
|
See https://developer.wordpress.org/block-editor/contributors/develop/coding-guidelines/#experimental-and-unstable-apis for details.`,
|
|
67
|
-
type: 'ImportSpecifier',
|
|
68
67
|
},
|
|
69
68
|
],
|
|
70
69
|
},
|
|
@@ -75,7 +74,6 @@ See https://developer.wordpress.org/block-editor/contributors/develop/coding-gui
|
|
|
75
74
|
{
|
|
76
75
|
message: `Usage of \`__experimentalSafe\` from \`@wordpress/unsafe\` is not allowed.
|
|
77
76
|
See https://developer.wordpress.org/block-editor/contributors/develop/coding-guidelines/#experimental-and-unstable-apis for details.`,
|
|
78
|
-
type: 'ImportSpecifier',
|
|
79
77
|
},
|
|
80
78
|
],
|
|
81
79
|
},
|
|
@@ -86,7 +84,6 @@ See https://developer.wordpress.org/block-editor/contributors/develop/coding-gui
|
|
|
86
84
|
{
|
|
87
85
|
message: `Usage of \`__experimentalSafe\` from \`@wordpress/unsafe\` is not allowed.
|
|
88
86
|
See https://developer.wordpress.org/block-editor/contributors/develop/coding-guidelines/#experimental-and-unstable-apis for details.`,
|
|
89
|
-
type: 'ImportSpecifier',
|
|
90
87
|
},
|
|
91
88
|
],
|
|
92
89
|
},
|
|
@@ -97,7 +94,6 @@ See https://developer.wordpress.org/block-editor/contributors/develop/coding-gui
|
|
|
97
94
|
{
|
|
98
95
|
message: `Usage of \`__experimentalUnsafe\` from \`@wordpress/package\` is not allowed.
|
|
99
96
|
See https://developer.wordpress.org/block-editor/contributors/develop/coding-guidelines/#experimental-and-unstable-apis for details.`,
|
|
100
|
-
type: 'ImportSpecifier',
|
|
101
97
|
},
|
|
102
98
|
],
|
|
103
99
|
},
|
|
@@ -108,7 +104,6 @@ See https://developer.wordpress.org/block-editor/contributors/develop/coding-gui
|
|
|
108
104
|
{
|
|
109
105
|
message: `Usage of \`__unstableFeature\` from \`@wordpress/package\` is not allowed.
|
|
110
106
|
See https://developer.wordpress.org/block-editor/contributors/develop/coding-guidelines/#experimental-and-unstable-apis for details.`,
|
|
111
|
-
type: 'ImportSpecifier',
|
|
112
107
|
},
|
|
113
108
|
],
|
|
114
109
|
},
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/* eslint-env jest */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* External dependencies
|
|
5
|
+
*/
|
|
6
|
+
import { RuleTester } from 'eslint';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Internal dependencies
|
|
10
|
+
*/
|
|
11
|
+
import rule, { ALLOWLIST, DENYLIST } from '../use-recommended-components';
|
|
12
|
+
|
|
13
|
+
const ruleTester = new RuleTester( {
|
|
14
|
+
parserOptions: {
|
|
15
|
+
sourceType: 'module',
|
|
16
|
+
ecmaVersion: 6,
|
|
17
|
+
},
|
|
18
|
+
} );
|
|
19
|
+
|
|
20
|
+
ruleTester.run( 'use-recommended-components', rule, {
|
|
21
|
+
valid: [
|
|
22
|
+
// Unrelated packages are not affected.
|
|
23
|
+
"import { Anything } from 'other-package';",
|
|
24
|
+
"import { Button } from '@wordpress/components';",
|
|
25
|
+
|
|
26
|
+
// Default and namespace imports are not affected.
|
|
27
|
+
"import UI from '@wordpress/ui';",
|
|
28
|
+
"import * as UI from '@wordpress/ui';",
|
|
29
|
+
|
|
30
|
+
// Allowed @wordpress/ui components.
|
|
31
|
+
"import { Badge } from '@wordpress/ui';",
|
|
32
|
+
"import { Stack } from '@wordpress/ui';",
|
|
33
|
+
"import { Badge, Stack } from '@wordpress/ui';",
|
|
34
|
+
],
|
|
35
|
+
|
|
36
|
+
invalid: [
|
|
37
|
+
// Allowlist: non-allowed @wordpress/ui imports are flagged.
|
|
38
|
+
{
|
|
39
|
+
code: "import { SomeComponent } from '@wordpress/ui';",
|
|
40
|
+
errors: [
|
|
41
|
+
{
|
|
42
|
+
message:
|
|
43
|
+
'`SomeComponent` from `@wordpress/ui` is not yet recommended for use in a WordPress environment.',
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
code: "import { Foo, Bar } from '@wordpress/ui';",
|
|
49
|
+
errors: [
|
|
50
|
+
{
|
|
51
|
+
message:
|
|
52
|
+
'`Foo` from `@wordpress/ui` is not yet recommended for use in a WordPress environment.',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
message:
|
|
56
|
+
'`Bar` from `@wordpress/ui` is not yet recommended for use in a WordPress environment.',
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
// Denylist: denied components are flagged with their message.
|
|
61
|
+
{
|
|
62
|
+
code: "import { __experimentalZStack } from '@wordpress/components';",
|
|
63
|
+
errors: [
|
|
64
|
+
{
|
|
65
|
+
message:
|
|
66
|
+
'__experimentalZStack is planned for deprecation. Write your own CSS instead.',
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
code: "import { __experimentalZStack as ZStack } from '@wordpress/components';",
|
|
72
|
+
errors: [
|
|
73
|
+
{
|
|
74
|
+
message:
|
|
75
|
+
'__experimentalZStack is planned for deprecation. Write your own CSS instead.',
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
} );
|
|
81
|
+
|
|
82
|
+
describe( 'ALLOWLIST and DENYLIST', () => {
|
|
83
|
+
it( 'should not have overlapping package keys', () => {
|
|
84
|
+
const allowlistPackages = Object.keys( ALLOWLIST );
|
|
85
|
+
const denylistPackages = Object.keys( DENYLIST );
|
|
86
|
+
const overlap = allowlistPackages.filter( ( pkg ) =>
|
|
87
|
+
denylistPackages.includes( pkg )
|
|
88
|
+
);
|
|
89
|
+
expect( overlap ).toEqual( [] );
|
|
90
|
+
} );
|
|
91
|
+
} );
|