linter-bundle 2.0.0 → 2.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/CHANGELOG.md +83 -2
- package/README.md +7 -7
- package/eslint/index.js +76 -7
- package/eslint/overrides-gatsby.js +7 -0
- package/eslint/overrides-javascript.js +1 -0
- package/eslint/overrides-jest.js +4 -1
- package/eslint/overrides-jsdoc.js +2 -2
- package/eslint/overrides-react.js +152 -1
- package/eslint/overrides-type-declarations.js +1 -0
- package/package.json +26 -19
- package/stylelint/index.js +22 -3
- package/stylelint/plugins/stylelint-high-performance-animation.js +273 -0
- package/stylelint/plugins/stylelint-selector-tag-no-without-class.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,7 +6,88 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
-
[Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v2.
|
|
9
|
+
[Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v2.4.0...HEAD)
|
|
10
|
+
|
|
11
|
+
## [2.4.0] - 2022.02.09
|
|
12
|
+
|
|
13
|
+
- [eslint] Updated `@typescript-eslint/eslint-plugin` from v5.10.1 to v5.11.0
|
|
14
|
+
- [eslint] Updated `eslint` from v8.7.0 to v8.8.0
|
|
15
|
+
- [eslint] Updated `eslint-plugin-functional` from v4.1.1 to v4.2.0
|
|
16
|
+
- [eslint] Updated `eslint-plugin-jest` from v26.0.0 to v26.1.0
|
|
17
|
+
- [eslint] Updated `eslint-plugin-jsdoc` from v37.7.0 to v37.8.1
|
|
18
|
+
- [markdownlint] Updated `markdownlint-cli` from v0.30.0 to v0.31.1, which adds the new rules `MD049` and `MD050` for consistent emphasis/strong style, and improves the rules `MD007`/`MD010`/`MD032`/`MD033`/`MD035`/`MD037`/`MD039`
|
|
19
|
+
- [stylelint] Updated `stylelint` from v14.3.0 to v14.4.0
|
|
20
|
+
- [eslint] Activated `unusedExports` option of the [`import/no-unused-modules`](https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-unused-modules.md) rule
|
|
21
|
+
- [eslint] Activate [`@typescript-eslint/explicit-function-return-type`](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-function-return-type.md) rule
|
|
22
|
+
- [eslint/react] Add React class methods (`componentDidMount`, `render` etc.) to the allowed names in the [`@typescript-eslint/explicit-function-return-type`](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/explicit-function-return-type.md) rule
|
|
23
|
+
- [eslint/jest] Make use of new [`no-conditional-in-test`](https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/no-conditional-in-test.md) rule, which deprecates `no-if`
|
|
24
|
+
- [eslint/jest] Make use of new [`prefer-snapshot-hint`](https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/prefer-snapshot-hint.md) rule
|
|
25
|
+
- [stylelint] Added but disabled new [`function-no-unknown`](https://github.com/stylelint/stylelint/blob/main/lib/rules/function-no-unknown/README.md) rule, because of false positives
|
|
26
|
+
|
|
27
|
+
[Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v2.3.1...v2.4.0)
|
|
28
|
+
|
|
29
|
+
## [2.3.1] - 2022.01.28
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- [eslint/overrides-javascript(-lazy)] Move `import/no-import-module-exports` rule to`overrides-javascript`
|
|
34
|
+
- [eslint/overrides-gatsby] Ignore '@reach/router' in `import/no-unresolved` rule
|
|
35
|
+
- [eslint] Disabled `react/require-default-props`, because of false-positive for React.forwardRef wrapped functional components
|
|
36
|
+
- [eslint] Disabled `unicorn/prefer-top-level-await`, because of false-positive on environments with Node.js below v14.8
|
|
37
|
+
- [eslint] Activated `allowThrowingUnknown` option of the [`@typescript-eslint/no-throw-literal`](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-throw-literal.md) rule
|
|
38
|
+
- [stylelint] Activate `camelCaseSvgKeywords` option of the [`value-keyword-case`](https://github.com/stylelint/stylelint/tree/main/lib/rules/value-keyword-case) rule
|
|
39
|
+
|
|
40
|
+
[Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v2.3.0...v2.3.1)
|
|
41
|
+
|
|
42
|
+
## [2.3.0] - 2022.01.27
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- [eslint] In the `.vscode/settings.json` the "configFile" option in "eslint.options" has been renamed to "overrideConfigFile"
|
|
47
|
+
- [eslint] Re-added [`eslint-plugin-jsx-a11y`](https://www.npmjs.com/package/eslint-plugin-jsx-a11y) v6.5.1
|
|
48
|
+
- [eslint] Re-added [`eslint-plugin-promise`](https://www.npmjs.com/package/eslint-plugin-promise) v6.0.0
|
|
49
|
+
- [eslint] Re-added [`eslint-plugin-react`](https://www.npmjs.com/package/eslint-plugin-react) v7.28.0
|
|
50
|
+
- [stylelint] Re-added [`stylelint-declaration-block-no-ignored-properties`](https://www.npmjs.com/package/stylelint-declaration-block-no-ignored-properties) v2.5.0
|
|
51
|
+
- [eslint] Updated `eslint-plugin-react-hooks` from v4.2.1-alpha-13455d26d-20211104 to v4.3.0
|
|
52
|
+
- [eslint] Re-added [`react/no-invalid-html-attribute`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-invalid-html-attribute.md) rule
|
|
53
|
+
- [eslint] Re-added [`react/no-arrow-function-lifecycle`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-arrow-function-lifecycle.md) rule
|
|
54
|
+
- [eslint] Re-added [`react/no-unused-class-component-methods`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/no-unused-class-component-methods.md) rule
|
|
55
|
+
- [eslint] Disabled [`unicorn/prefer-object-has-own`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-object-has-own.md) for now, because of limited engine support
|
|
56
|
+
- [eslint] Disabled `allowThrowingAny` and `allowThrowingUnknown` of the [`@typescript-eslint/no-throw-literal`](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-throw-literal.md) rule
|
|
57
|
+
- [eslint] Reactivated [`import/no-import-module-exports`](https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-import-module-exports.md) rule
|
|
58
|
+
- [eslint] Added new [`import/no-unused-modules`](https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/no-unused-modules.md) rule
|
|
59
|
+
- [eslint] Added new [`jest/prefer-comparison-matcher`](https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/prefer-comparison-matcher.md) rule
|
|
60
|
+
- [eslint] Added new [`jest/prefer-equality-matcher`](https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/prefer-equality-matcher.md) rule
|
|
61
|
+
- [eslint] Added new [`unicorn/no-await-expression-member`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-await-expression-member.md) rule
|
|
62
|
+
- [eslint] Added new [`unicorn/prefer-code-point`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-code-point.md) rule
|
|
63
|
+
- [eslint] Added new [`unicorn/no-thenable`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-thenable.md) rule
|
|
64
|
+
- [eslint] Added new [`unicorn/no-useless-promise-resolve-reject`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-useless-promise-resolve-reject.md) rule
|
|
65
|
+
- [eslint] Added new [`unicorn/relative-url-style`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/relative-url-style.md) rule
|
|
66
|
+
- [eslint] Added new [`unicorn/prefer-json-parse-buffer`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-json-parse-buffer.md) rule
|
|
67
|
+
- [eslint] Updated `@typescript-eslint` from v5.3.0 to v5.10.1
|
|
68
|
+
- [eslint] Updated `eslint` from v8.2.0 to v8.7.0
|
|
69
|
+
- [eslint] Updated `eslint-plugin-functional` from v4.0.2 to v4.1.1
|
|
70
|
+
- [eslint] Updated `eslint-plugin-import` from v2.25.2 to v2.25.4
|
|
71
|
+
- [eslint] Updated `eslint-plugin-jest` from v25.2.3 to v26.0.0
|
|
72
|
+
- [eslint] Updated `eslint-plugin-jsdoc` from v37.0.3 to v37.7.0
|
|
73
|
+
- [eslint] Updated `eslint-plugin-unicode` from v38.0.0 to v40.1.0
|
|
74
|
+
- [markdownlint] Updated `markdownlint-cli` from v0.29.0 to v0.30.0
|
|
75
|
+
- [stylelint] Updated `stylelint` from v14.0.1 to v14.3.0
|
|
76
|
+
- [stylelint] Updated `stylelint-scss` from v4.0.0 to v4.1.0
|
|
77
|
+
- [stylelint] Added new [`scss/dollar-variable-no-namespaced-assignment`](https://github.com/stylelint-scss/stylelint-scss/tree/master/src/rules/dollar-variable-no-namespaced-assignment) rule
|
|
78
|
+
- [stylelint] Added new [`scss/at-use-no-unnamespaced`](https://github.com/stylelint-scss/stylelint-scss/tree/master/src/rules/at-use-no-unnamespaced) rule
|
|
79
|
+
- [stylelint] Added but disabled [`rule-selector-property-disallowed-list`](https://github.com/stylelint/stylelint/tree/main/lib/rules/rule-selector-property-disallowed-list) rule
|
|
80
|
+
|
|
81
|
+
[Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v2.1.0...v2.3.0)
|
|
82
|
+
|
|
83
|
+
## [2.1.0] - 2021.11.07
|
|
84
|
+
|
|
85
|
+
### Changed
|
|
86
|
+
|
|
87
|
+
- [stylelint] Forked [`stylelint-high-performance-animation`](https://www.npmjs.com/package/stylelint-high-performance-animation), because it seems not to be regularly maintained anymore
|
|
88
|
+
- [eslint] Updated `eslint` from v8.1.0 to v8.2.0
|
|
89
|
+
|
|
90
|
+
[Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v2.0.0...v2.1.0)
|
|
10
91
|
|
|
11
92
|
## [2.0.0] - 2021.11.05
|
|
12
93
|
|
|
@@ -14,7 +95,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
|
14
95
|
|
|
15
96
|
- [eslint] [`eslint-plugin-jsx-a11y`](https://www.npmjs.com/package/eslint-plugin-jsx-a11y) has been removed, because it seems not to be regularly maintained anymore, which blocks us from updating to ESLint v8
|
|
16
97
|
- [eslint] [`eslint-plugin-promise`](https://www.npmjs.com/package/eslint-plugin-promise) has been removed, because it seems not to be regularly maintained anymore, which blocks us from updating to ESLint v8
|
|
17
|
-
- [eslint] [`eslint-plugin-react`](https://www.npmjs.com/package/eslint-plugin-
|
|
98
|
+
- [eslint] [`eslint-plugin-react`](https://www.npmjs.com/package/eslint-plugin-react) has been removed, because it's relying on unmaintained dependencies, which blocks us from updating to ESLint v8
|
|
18
99
|
- [stylelint] [`stylelint-declaration-block-no-ignored-properties`](https://www.npmjs.com/package/stylelint-declaration-block-no-ignored-properties) has been removed, because it seems not to be regularly maintained anymore, which blocks us from updating to Stylelint v14
|
|
19
100
|
- [stylelint] [`stylelint-use-nesting`](https://www.npmjs.com/package/stylelint-use-nesting) has been removed, because it seems not to be regularly maintained anymore, which blocks us from updating to Stylelint v14
|
|
20
101
|
|
package/README.md
CHANGED
|
@@ -28,8 +28,11 @@ This setup is using the following additional plugins:
|
|
|
28
28
|
- [eslint-plugin-import](https://www.npmjs.com/package/eslint-plugin-import)
|
|
29
29
|
- [eslint-plugin-jest](https://www.npmjs.com/package/eslint-plugin-jest)
|
|
30
30
|
- [eslint-plugin-jsdoc](https://www.npmjs.com/package/eslint-plugin-jsdoc)
|
|
31
|
+
- [eslint-plugin-jsx-a11y](https://www.npmjs.com/package/eslint-plugin-jsx-a11y)
|
|
31
32
|
- [eslint-plugin-node](https://www.npmjs.com/package/eslint-plugin-node)
|
|
33
|
+
- [eslint-plugin-promise](https://www.npmjs.com/package/eslint-plugin-promise)
|
|
32
34
|
- [eslint-plugin-react-hooks](https://www.npmjs.com/package/eslint-plugin-react-hooks)
|
|
35
|
+
- [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react)
|
|
33
36
|
- [eslint-plugin-unicorn](https://www.npmjs.com/package/eslint-plugin-unicorn)
|
|
34
37
|
|
|
35
38
|
Beside that, the following additional rules are part of this bundle:
|
|
@@ -38,22 +41,19 @@ Beside that, the following additional rules are part of this bundle:
|
|
|
38
41
|
|
|
39
42
|
### stylelint
|
|
40
43
|
|
|
41
|
-
- [stylelint-
|
|
44
|
+
- [stylelint-declaration-block-no-ignored-properties](https://www.npmjs.com/package/stylelint-declaration-block-no-ignored-properties)
|
|
45
|
+
- [stylelint-high-performance-animation](https://www.npmjs.com/package/stylelint-high-performance-animation) (Forked version)
|
|
42
46
|
- [stylelint-order](https://www.npmjs.com/package/stylelint-order)
|
|
43
47
|
- [stylelint-scss](https://www.npmjs.com/package/stylelint-scss)
|
|
44
48
|
- [stylelint-selector-no-empty](https://www.npmjs.com/package/stylelint-selector-no-empty)
|
|
45
|
-
- [stylelint-use-logical-spec](https://www.npmjs.com/package/stylelint-use-logical-spec)
|
|
46
49
|
- [stylelint-selector-tag-no-without-class](https://www.npmjs.com/package/stylelint-selector-tag-no-without-class) (Forked version)
|
|
50
|
+
- [stylelint-use-logical-spec](https://www.npmjs.com/package/stylelint-use-logical-spec)
|
|
47
51
|
|
|
48
52
|
### Previously used, but now unmaintained plugins
|
|
49
53
|
|
|
50
54
|
Unfortunately a couple of previously used plugins are not regularly maintained or depend on unmaintained third-party code which blocks them from updating, so they don't provide updates for the major releases of the linters (ESLint and Stylelint).
|
|
51
55
|
For that reason the following plugins are not used anymore:
|
|
52
56
|
|
|
53
|
-
- [eslint-plugin-jsx-a11y](https://www.npmjs.com/package/eslint-plugin-jsx-a11y) (removed on 2021-11-05)
|
|
54
|
-
- [eslint-plugin-promise](https://www.npmjs.com/package/eslint-plugin-promise) (removed on 2021-11-05)
|
|
55
|
-
- [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react) (removed on 2021-11-05)
|
|
56
|
-
- [stylelint-declaration-block-no-ignored-properties](https://www.npmjs.com/package/stylelint-declaration-block-no-ignored-properties) (removed on 2021-11-05)
|
|
57
57
|
- [stylelint-use-nesting](https://www.npmjs.com/package/stylelint-use-nesting) (removed on 2021-11-05)
|
|
58
58
|
|
|
59
59
|
If these plugins are maintained again, the plugins will also be used again.
|
|
@@ -318,7 +318,7 @@ This can be done by adding these options to your `.vscode/settings.json`:
|
|
|
318
318
|
{
|
|
319
319
|
"eslint.nodePath": "./node_modules/linter-bundle/node_modules/eslint",
|
|
320
320
|
"eslint.options": {
|
|
321
|
-
"
|
|
321
|
+
"overrideConfigFile": "./.eslintrc.js",
|
|
322
322
|
"resolvePluginsRelativeTo": "./node_modules/linter-bundle",
|
|
323
323
|
"rulePaths": ["./node_modules/linter-bundle/eslint/rules"],
|
|
324
324
|
"reportUnusedDisableDirectives": "error",
|
package/eslint/index.js
CHANGED
|
@@ -22,7 +22,10 @@ module.exports = {
|
|
|
22
22
|
'eslint-comments',
|
|
23
23
|
'functional',
|
|
24
24
|
'import',
|
|
25
|
+
'jsx-a11y',
|
|
26
|
+
'promise',
|
|
25
27
|
'react-hooks',
|
|
28
|
+
'react',
|
|
26
29
|
'unicorn'
|
|
27
30
|
],
|
|
28
31
|
extends: [
|
|
@@ -421,7 +424,7 @@ module.exports = {
|
|
|
421
424
|
'@typescript-eslint/consistent-type-exports': 'error',
|
|
422
425
|
'@typescript-eslint/consistent-type-imports': ['error', { disallowTypeAnnotations: false }],
|
|
423
426
|
'@typescript-eslint/dot-notation': 'error',
|
|
424
|
-
'@typescript-eslint/explicit-function-return-type': '
|
|
427
|
+
'@typescript-eslint/explicit-function-return-type': 'error',
|
|
425
428
|
'@typescript-eslint/explicit-member-accessibility': ['error', {
|
|
426
429
|
ignoredMethodNames: [
|
|
427
430
|
'constructor',
|
|
@@ -639,7 +642,10 @@ module.exports = {
|
|
|
639
642
|
'@typescript-eslint/no-require-imports': 'error',
|
|
640
643
|
'@typescript-eslint/no-shadow': 'error',
|
|
641
644
|
'@typescript-eslint/no-this-alias': 'error',
|
|
642
|
-
'@typescript-eslint/no-throw-literal': 'error',
|
|
645
|
+
'@typescript-eslint/no-throw-literal': ['error', {
|
|
646
|
+
allowThrowingAny: false,
|
|
647
|
+
allowThrowingUnknown: true
|
|
648
|
+
}],
|
|
643
649
|
'@typescript-eslint/no-type-alias': ['off', { // @todo There should be an option like 'sub-in-unions-and-intersections', which allows `type A = (string | number)[];`
|
|
644
650
|
allowAliases: 'always',
|
|
645
651
|
allowCallbacks: 'always',
|
|
@@ -764,7 +770,7 @@ module.exports = {
|
|
|
764
770
|
'workbox-window/utils/WorkboxEvent'
|
|
765
771
|
]
|
|
766
772
|
}],
|
|
767
|
-
'import/no-import-module-exports': 'off', //
|
|
773
|
+
'import/no-import-module-exports': 'off', // Activated only for JavaScript files
|
|
768
774
|
'import/no-mutable-exports': 'error',
|
|
769
775
|
'import/no-named-as-default-member': 'error',
|
|
770
776
|
'import/no-named-as-default': 'error',
|
|
@@ -783,7 +789,7 @@ module.exports = {
|
|
|
783
789
|
]
|
|
784
790
|
}],
|
|
785
791
|
'import/no-unresolved': ['error', { caseSensitiveStrict: true }],
|
|
786
|
-
'import/no-unused-modules': 'error',
|
|
792
|
+
'import/no-unused-modules': ['error', { unusedExports: true }],
|
|
787
793
|
'import/no-useless-path-segments': 'error',
|
|
788
794
|
'import/no-webpack-loader-syntax': 'off', // Indeed, you should avoid that, but if we do it, we have a reason for it
|
|
789
795
|
'import/order': ['error', {
|
|
@@ -809,6 +815,43 @@ module.exports = {
|
|
|
809
815
|
'import/prefer-default-export': 'off',
|
|
810
816
|
'import/unambiguous': 'off',
|
|
811
817
|
|
|
818
|
+
/**
|
|
819
|
+
* eslint-plugin-jsx-a11y
|
|
820
|
+
*
|
|
821
|
+
* @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y
|
|
822
|
+
*/
|
|
823
|
+
'jsx-a11y/alt-text': 'error',
|
|
824
|
+
'jsx-a11y/anchor-has-content': 'error',
|
|
825
|
+
'jsx-a11y/anchor-is-valid': 'error',
|
|
826
|
+
'jsx-a11y/aria-activedescendant-has-tabindex': 'error',
|
|
827
|
+
'jsx-a11y/aria-props': 'error',
|
|
828
|
+
'jsx-a11y/aria-proptypes': 'error',
|
|
829
|
+
'jsx-a11y/aria-role': 'error',
|
|
830
|
+
'jsx-a11y/aria-unsupported-elements': 'error',
|
|
831
|
+
'jsx-a11y/autocomplete-valid': 'error',
|
|
832
|
+
'jsx-a11y/click-events-have-key-events': 'error',
|
|
833
|
+
'jsx-a11y/heading-has-content': 'error',
|
|
834
|
+
'jsx-a11y/html-has-lang': 'off', // <html> elements set by react-helmet automatically have a lang attribute set
|
|
835
|
+
'jsx-a11y/iframe-has-title': 'error',
|
|
836
|
+
'jsx-a11y/img-redundant-alt': 'error',
|
|
837
|
+
'jsx-a11y/interactive-supports-focus': 'error',
|
|
838
|
+
'jsx-a11y/label-has-associated-control': 'error',
|
|
839
|
+
'jsx-a11y/media-has-caption': 'error',
|
|
840
|
+
'jsx-a11y/mouse-events-have-key-events': 'error',
|
|
841
|
+
'jsx-a11y/no-access-key': 'off', // If you explicitly specify an access key, you usually have a reason for this, so it should not be prevented by a rule
|
|
842
|
+
'jsx-a11y/no-autofocus': ['error', { ignoreNonDOM: true }],
|
|
843
|
+
'jsx-a11y/no-distracting-elements': 'error',
|
|
844
|
+
'jsx-a11y/no-interactive-element-to-noninteractive-role': 'error',
|
|
845
|
+
'jsx-a11y/no-noninteractive-element-interactions': 'error',
|
|
846
|
+
'jsx-a11y/no-noninteractive-element-to-interactive-role': 'error',
|
|
847
|
+
'jsx-a11y/no-noninteractive-tabindex': 'error',
|
|
848
|
+
'jsx-a11y/no-redundant-roles': 'error',
|
|
849
|
+
'jsx-a11y/no-static-element-interactions': 'error',
|
|
850
|
+
'jsx-a11y/role-has-required-aria-props': 'error',
|
|
851
|
+
'jsx-a11y/role-supports-aria-props': 'error',
|
|
852
|
+
'jsx-a11y/scope': 'error',
|
|
853
|
+
'jsx-a11y/tabindex-no-positive': 'error',
|
|
854
|
+
|
|
812
855
|
/**
|
|
813
856
|
* eslint-plugin-eslint-comments
|
|
814
857
|
*
|
|
@@ -824,6 +867,26 @@ module.exports = {
|
|
|
824
867
|
'eslint-comments/no-use': 'off',
|
|
825
868
|
'eslint-comments/require-description': ['error', { ignore: ['eslint-enable'] }],
|
|
826
869
|
|
|
870
|
+
/**
|
|
871
|
+
* eslint-plugin-promise
|
|
872
|
+
*
|
|
873
|
+
* @see https://github.com/xjamundx/eslint-plugin-promise
|
|
874
|
+
*/
|
|
875
|
+
'promise/always-return': 'off', // If the result of an `.then()` is not used, there is no need to return something.
|
|
876
|
+
'promise/avoid-new': 'off',
|
|
877
|
+
'promise/catch-or-return': 'error',
|
|
878
|
+
'promise/no-callback-in-promise': 'off',
|
|
879
|
+
'promise/no-native': 'off',
|
|
880
|
+
'promise/no-nesting': 'off',
|
|
881
|
+
'promise/no-new-statics': 'error',
|
|
882
|
+
'promise/no-promise-in-callback': 'off',
|
|
883
|
+
'promise/no-return-in-finally': 'error',
|
|
884
|
+
'promise/no-return-wrap': 'error',
|
|
885
|
+
'promise/param-names': 'off', // @todo Disabled until this issue is fixed: https://github.com/xjamundx/eslint-plugin-promise/issues/206
|
|
886
|
+
'promise/prefer-await-to-callbacks': 'off', // It's not always possible to use avoid callbacks.
|
|
887
|
+
'promise/prefer-await-to-then': 'off', // Depending on the use-case `.then()`/`.catch()` might be easier to understand
|
|
888
|
+
'promise/valid-params': 'off', // TypeScript ensures that
|
|
889
|
+
|
|
827
890
|
/**
|
|
828
891
|
* eslint-plugin-unicorn
|
|
829
892
|
*
|
|
@@ -852,11 +915,12 @@ module.exports = {
|
|
|
852
915
|
'unicorn/import-style': 'error',
|
|
853
916
|
'unicorn/new-for-builtins': 'error',
|
|
854
917
|
'unicorn/no-abusive-eslint-disable': 'error',
|
|
855
|
-
'unicorn/no-array-callback-reference': 'off', // If I use functions, they are
|
|
918
|
+
'unicorn/no-array-callback-reference': 'off', // If I use functions, they are the best option for this use-case
|
|
856
919
|
'unicorn/no-array-for-each': 'error',
|
|
857
920
|
'unicorn/no-array-method-this-argument': 'error',
|
|
858
921
|
'unicorn/no-array-push-push': 'error',
|
|
859
922
|
'unicorn/no-array-reduce': ['error', { allowSimpleOperations: true }],
|
|
923
|
+
'unicorn/no-await-expression-member': 'error',
|
|
860
924
|
'unicorn/no-console-spaces': 'error',
|
|
861
925
|
'unicorn/no-document-cookie': 'error',
|
|
862
926
|
'unicorn/no-empty-file': 'error',
|
|
@@ -872,11 +936,13 @@ module.exports = {
|
|
|
872
936
|
'unicorn/no-object-as-default-parameter': 'error',
|
|
873
937
|
'unicorn/no-process-exit': 'error',
|
|
874
938
|
'unicorn/no-static-only-class': 'error',
|
|
939
|
+
'unicorn/no-thenable': 'error',
|
|
875
940
|
'unicorn/no-this-assignment': 'error',
|
|
876
941
|
'unicorn/no-unreadable-array-destructuring': 'error',
|
|
877
942
|
'unicorn/no-unsafe-regex': 'off',
|
|
878
943
|
'unicorn/no-unused-properties': 'error',
|
|
879
944
|
'unicorn/no-useless-fallback-in-spread': 'error',
|
|
945
|
+
'unicorn/no-useless-promise-resolve-reject': 'error',
|
|
880
946
|
'unicorn/no-invalid-remove-event-listener': 'error',
|
|
881
947
|
'unicorn/no-useless-length-check': 'error',
|
|
882
948
|
'unicorn/no-useless-spread': 'error',
|
|
@@ -891,6 +957,7 @@ module.exports = {
|
|
|
891
957
|
'unicorn/prefer-array-index-of': 'error',
|
|
892
958
|
'unicorn/prefer-array-some': 'error',
|
|
893
959
|
'unicorn/prefer-at': 'off', // @todo Disabled for now, since `at` is not supported by TypeScript type definitions yet.
|
|
960
|
+
'unicorn/prefer-code-point': 'error',
|
|
894
961
|
'unicorn/prefer-date-now': 'error',
|
|
895
962
|
'unicorn/prefer-default-parameters': 'error',
|
|
896
963
|
'unicorn/prefer-dom-node-append': 'error',
|
|
@@ -899,13 +966,14 @@ module.exports = {
|
|
|
899
966
|
'unicorn/prefer-dom-node-text-content': 'error',
|
|
900
967
|
'unicorn/prefer-export-from': 'error',
|
|
901
968
|
'unicorn/prefer-includes': 'error',
|
|
969
|
+
'unicorn/prefer-json-parse-buffer': 'error',
|
|
902
970
|
'unicorn/prefer-keyboard-event-key': 'error',
|
|
903
971
|
'unicorn/prefer-math-trunc': 'error',
|
|
904
972
|
'unicorn/prefer-modern-dom-apis': 'error',
|
|
905
973
|
'unicorn/prefer-module': 'off',
|
|
906
974
|
'unicorn/prefer-negative-index': 'error',
|
|
907
975
|
'unicorn/prefer-number-properties': 'error',
|
|
908
|
-
'unicorn/prefer-object-has-own': '
|
|
976
|
+
'unicorn/prefer-object-has-own': 'off', // Not widely supported yet. Can be activated in 2024
|
|
909
977
|
'unicorn/prefer-object-from-entries': 'error',
|
|
910
978
|
'unicorn/prefer-optional-catch-binding': 'error',
|
|
911
979
|
'unicorn/prefer-prototype-methods': 'error',
|
|
@@ -919,10 +987,11 @@ module.exports = {
|
|
|
919
987
|
'unicorn/prefer-string-trim-start-end': 'error',
|
|
920
988
|
'unicorn/prefer-switch': 'error',
|
|
921
989
|
'unicorn/prefer-ternary': 'off', // We prefer readability over saving a few chars
|
|
922
|
-
'unicorn/prefer-top-level-await': '
|
|
990
|
+
'unicorn/prefer-top-level-await': 'off', // @todo There should be a detection that this option is only activated on Node.js v14.8 environments and above (Check for "engine" property in package.json, and "node -v")
|
|
923
991
|
'unicorn/prefer-regexp-test': 'error',
|
|
924
992
|
'unicorn/prefer-type-error': 'error',
|
|
925
993
|
'unicorn/prevent-abbreviations': ['error', { ignore: ['args', 'i', 'j', 'i18n', 'ref', 'Ref', 'params', 'props', 'Props'] }],
|
|
994
|
+
'unicorn/relative-url-style': 'error',
|
|
926
995
|
'unicorn/require-array-join-separator': 'error',
|
|
927
996
|
'unicorn/require-number-to-fixed-digits-argument': 'error',
|
|
928
997
|
'unicorn/require-post-message-target-origin': 'off', // False-positive with Workers which don't support a `targetOrigin`
|
|
@@ -33,6 +33,13 @@ module.exports = {
|
|
|
33
33
|
*/
|
|
34
34
|
'@typescript-eslint/no-confusing-void-expression': 'off', // @todo Conflicts with graphql-template strings
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* eslint-plugin-import
|
|
38
|
+
*
|
|
39
|
+
* @see https://github.com/import-js/eslint-plugin-import
|
|
40
|
+
*/
|
|
41
|
+
'import/no-unresolved': ['error', { caseSensitiveStrict: true, ignore: ['@reach/router'] }],
|
|
42
|
+
|
|
36
43
|
/**
|
|
37
44
|
* eslint-plugin-unicorn
|
|
38
45
|
*
|
package/eslint/overrides-jest.js
CHANGED
|
@@ -66,6 +66,7 @@ module.exports = {
|
|
|
66
66
|
'jest/no-alias-methods': 'error',
|
|
67
67
|
'jest/no-commented-out-tests': 'error',
|
|
68
68
|
'jest/no-conditional-expect': 'error',
|
|
69
|
+
'jest/no-conditional-in-test': 'error',
|
|
69
70
|
'jest/no-deprecated-functions': 'error',
|
|
70
71
|
'jest/no-disabled-tests': 'error',
|
|
71
72
|
'jest/no-done-callback': 'error',
|
|
@@ -74,7 +75,6 @@ module.exports = {
|
|
|
74
75
|
'jest/no-focused-tests': 'error',
|
|
75
76
|
'jest/no-hooks': ['error', { allow: ['beforeEach', 'afterEach', 'afterAll'] }],
|
|
76
77
|
'jest/no-identical-title': 'error',
|
|
77
|
-
'jest/no-if': 'error',
|
|
78
78
|
'jest/no-interpolation-in-snapshots': 'error',
|
|
79
79
|
'jest/no-jasmine-globals': 'error',
|
|
80
80
|
'jest/no-jest-import': 'error',
|
|
@@ -88,6 +88,9 @@ module.exports = {
|
|
|
88
88
|
'jest/prefer-expect-resolves': 'off', // We prefer `expect(await promise)` enforced by 'jest/no-restricted-matchers'
|
|
89
89
|
'jest/prefer-hooks-on-top': 'error',
|
|
90
90
|
'jest/require-hook': 'error',
|
|
91
|
+
'jest/prefer-comparison-matcher': 'error',
|
|
92
|
+
'jest/prefer-equality-matcher': 'error',
|
|
93
|
+
'jest/prefer-snapshot-hint': 'error',
|
|
91
94
|
'jest/prefer-spy-on': 'error',
|
|
92
95
|
'jest/prefer-strict-equal': 'error',
|
|
93
96
|
'jest/prefer-to-be': 'error',
|
|
@@ -24,8 +24,8 @@ module.exports = {
|
|
|
24
24
|
*/
|
|
25
25
|
'jsdoc/check-access': 'error',
|
|
26
26
|
'jsdoc/check-alignment': 'error',
|
|
27
|
-
'jsdoc/check-examples': 'off', // @todo
|
|
28
|
-
'jsdoc/check-indentation': ['off', { excludeTags: ['typedef'] }],
|
|
27
|
+
'jsdoc/check-examples': 'off', // @todo Need to be configured to allow text-based examples
|
|
28
|
+
'jsdoc/check-indentation': ['off', { excludeTags: ['typedef'] }], // @todo Why is this disabled?
|
|
29
29
|
'jsdoc/check-param-names': 'error',
|
|
30
30
|
'jsdoc/check-syntax': 'error',
|
|
31
31
|
'jsdoc/check-line-alignment': 'error',
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* @file Settings for React code in TypeScript (TSX) files.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
const ensureType = require('../helper/ensure-type');
|
|
6
|
+
|
|
5
7
|
module.exports = {
|
|
6
8
|
overrides: [
|
|
7
9
|
{
|
|
@@ -13,6 +15,19 @@ module.exports = {
|
|
|
13
15
|
* @see https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules
|
|
14
16
|
*/
|
|
15
17
|
'@typescript-eslint/member-ordering': 'off', // For React components we are using react/sort-comp
|
|
18
|
+
'@typescript-eslint/explicit-function-return-type': ['error', {
|
|
19
|
+
allowedNames: [
|
|
20
|
+
'componentDidCatch',
|
|
21
|
+
'componentDidMount',
|
|
22
|
+
'componentDidUpdate',
|
|
23
|
+
'componentWillUnmount',
|
|
24
|
+
'getDerivedStateFromError',
|
|
25
|
+
'getDerivedStateFromProps',
|
|
26
|
+
'getSnapshotBeforeUpdate',
|
|
27
|
+
'render',
|
|
28
|
+
'shouldComponentUpdate'
|
|
29
|
+
]
|
|
30
|
+
}],
|
|
16
31
|
|
|
17
32
|
/**
|
|
18
33
|
* eslint-plugin-react-hooks
|
|
@@ -21,7 +36,143 @@ module.exports = {
|
|
|
21
36
|
* @see https://reactjs.org/docs/hooks-rules.html
|
|
22
37
|
*/
|
|
23
38
|
'react-hooks/rules-of-hooks': 'error',
|
|
24
|
-
'react-hooks/exhaustive-deps': 'error'
|
|
39
|
+
'react-hooks/exhaustive-deps': 'error',
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* eslint-plugin-react
|
|
43
|
+
*
|
|
44
|
+
* @see https://github.com/yannickcr/eslint-plugin-react
|
|
45
|
+
*/
|
|
46
|
+
'react/boolean-prop-naming': 'error',
|
|
47
|
+
'react/button-has-type': 'error',
|
|
48
|
+
'react/default-props-match-prop-types': 'error',
|
|
49
|
+
'react/destructuring-assignment': 'off', // Sometimes destructuring makes sense, sometimes it doesn't - that depends on the context.
|
|
50
|
+
'react/display-name': 'error',
|
|
51
|
+
'react/forbid-component-props': ['error', { forbid: [
|
|
52
|
+
{
|
|
53
|
+
propName: 'className',
|
|
54
|
+
allowedFor: ensureType.array(global.linterBundleSettings?.overrides?.react?.['react/forbid-component-props']?.allowClassNameFor)
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
propName: 'style',
|
|
58
|
+
allowedFor: ensureType.array(global.linterBundleSettings?.overrides?.react?.['react/forbid-component-props']?.allowStyleFor)
|
|
59
|
+
}
|
|
60
|
+
] }],
|
|
61
|
+
'react/forbid-dom-props': 'error',
|
|
62
|
+
'react/forbid-elements': 'error',
|
|
63
|
+
'react/forbid-prop-types': 'error',
|
|
64
|
+
'react/forbid-foreign-prop-types': 'error',
|
|
65
|
+
'react/function-component-definition': ['off', { // @todo Doesn't work with Component-Factories, which shall return named components `return function MyComponent () {}`, while in modules, `const MyComponent = () => {}` shall be used
|
|
66
|
+
namedComponents: 'arrow-function',
|
|
67
|
+
unnamedComponents: 'arrow-function'
|
|
68
|
+
}],
|
|
69
|
+
'react/no-access-state-in-setstate': 'error',
|
|
70
|
+
'react/no-array-index-key': 'error',
|
|
71
|
+
'react/no-arrow-function-lifecycle': 'error',
|
|
72
|
+
'react/no-children-prop': 'error',
|
|
73
|
+
'react/no-danger': 'off',
|
|
74
|
+
'react/no-danger-with-children': 'error',
|
|
75
|
+
'react/no-deprecated': 'error',
|
|
76
|
+
'react/no-did-mount-set-state': 'error',
|
|
77
|
+
'react/no-did-update-set-state': 'error',
|
|
78
|
+
'react/no-direct-mutation-state': 'error',
|
|
79
|
+
'react/no-find-dom-node': 'error',
|
|
80
|
+
'react/no-invalid-html-attribute': 'error',
|
|
81
|
+
'react/no-is-mounted': 'error',
|
|
82
|
+
'react/no-multi-comp': 'error',
|
|
83
|
+
'react/no-namespace': 'error',
|
|
84
|
+
'react/no-redundant-should-component-update': 'error',
|
|
85
|
+
'react/no-render-return-value': 'error',
|
|
86
|
+
'react/no-set-state': 'off',
|
|
87
|
+
'react/no-typos': 'error',
|
|
88
|
+
'react/no-string-refs': 'error',
|
|
89
|
+
'react/no-this-in-sfc': 'error',
|
|
90
|
+
'react/no-unescaped-entities': 'error',
|
|
91
|
+
'react/no-unknown-property': 'error',
|
|
92
|
+
'react/no-unsafe': 'error',
|
|
93
|
+
'react/no-unstable-nested-components': 'error',
|
|
94
|
+
'react/no-unused-class-component-methods': 'error',
|
|
95
|
+
'react/no-unused-prop-types': 'error',
|
|
96
|
+
'react/no-unused-state': 'error',
|
|
97
|
+
'react/no-will-update-set-state': 'error',
|
|
98
|
+
'react/prefer-es6-class': 'error',
|
|
99
|
+
'react/prefer-exact-props': 'off', // With TypeScript interfaces, this rule is not required
|
|
100
|
+
'react/prefer-read-only-props': 'error',
|
|
101
|
+
'react/prefer-stateless-function': 'error',
|
|
102
|
+
'react/prop-types': 'off',
|
|
103
|
+
'react/react-in-jsx-scope': 'error',
|
|
104
|
+
'react/require-default-props': ['off', { forbidDefaultForRequired: true, ignoreFunctionalComponents: true }], // @see https://medium.com/@matanbobi/react-defaultprops-is-dying-whos-the-contender-443c19d9e7f1 @todo Also disabled becaues of false-positive with React.forwardRef(), create bug report?
|
|
105
|
+
'react/require-optimization': 'error',
|
|
106
|
+
'react/require-render-return': 'error',
|
|
107
|
+
'react/self-closing-comp': 'error',
|
|
108
|
+
'react/sort-comp': ['error', {
|
|
109
|
+
order: [
|
|
110
|
+
'type-annotations',
|
|
111
|
+
'static-variables',
|
|
112
|
+
'instance-variables',
|
|
113
|
+
'getters',
|
|
114
|
+
'setters',
|
|
115
|
+
'lifecycle',
|
|
116
|
+
'render',
|
|
117
|
+
'/^render.+$/',
|
|
118
|
+
'/^handle.+$/',
|
|
119
|
+
'everything-else',
|
|
120
|
+
'instance-methods',
|
|
121
|
+
'static-methods'
|
|
122
|
+
]
|
|
123
|
+
}],
|
|
124
|
+
'react/sort-prop-types': 'error',
|
|
125
|
+
'react/state-in-constructor': 'error',
|
|
126
|
+
'react/static-property-placement': 'error',
|
|
127
|
+
'react/style-prop-object': 'error',
|
|
128
|
+
'react/void-dom-elements-no-children': 'error',
|
|
129
|
+
|
|
130
|
+
// JSX-specific rules
|
|
131
|
+
'react/jsx-boolean-value': ['error', 'always'],
|
|
132
|
+
'react/jsx-child-element-spacing': 'off', // @todo Why is this disabled? Could it be, that the faulty behaviour is fixed in the meantime?
|
|
133
|
+
'react/jsx-closing-bracket-location': 'error',
|
|
134
|
+
'react/jsx-closing-tag-location': 'error',
|
|
135
|
+
'react/jsx-curly-newline': 'off',
|
|
136
|
+
'react/jsx-curly-spacing': 'error',
|
|
137
|
+
'react/jsx-equals-spacing': 'error',
|
|
138
|
+
'react/jsx-filename-extension': ['error', { extensions: ['.tsx'] }],
|
|
139
|
+
'react/jsx-first-prop-new-line': 'error',
|
|
140
|
+
'react/jsx-handler-names': 'off', // @todo There should be an option which checks if the function is used multiple times in a class (like this.closeTooltip()) - in that case, the 'handle' prefix should not be mandatory
|
|
141
|
+
'react/jsx-indent': ['error', 'tab', { checkAttributes: true, indentLogicalExpressions: true }],
|
|
142
|
+
'react/jsx-indent-props': ['error', 'tab'],
|
|
143
|
+
'react/jsx-key': ['error', { checkKeyMustBeforeSpread: true }],
|
|
144
|
+
'react/jsx-max-depth': ['error', { max: 8 }],
|
|
145
|
+
'react/jsx-max-props-per-line': ['error', { maximum: { single: 5, multi: 1 } }],
|
|
146
|
+
'react/no-adjacent-inline-elements': 'off', // @todo There is an issue if inline and block elements are mixed. Simple example: `<span>Text</span><br />` here, the space between the SPAN and BR should not be forced, because a space at the end of a line does not make sense.
|
|
147
|
+
'react/jsx-newline': 'off',
|
|
148
|
+
'react/jsx-no-bind': ['error', { ignoreDOMComponents: true }],
|
|
149
|
+
'react/jsx-no-comment-textnodes': 'error',
|
|
150
|
+
'react/jsx-no-constructed-context-values': 'error',
|
|
151
|
+
'react/jsx-no-duplicate-props': 'error',
|
|
152
|
+
'react/jsx-no-literals': 'off',
|
|
153
|
+
'react/jsx-no-script-url': 'error',
|
|
154
|
+
'react/jsx-no-target-blank': ['error', { allowReferrer: true, forms: true }],
|
|
155
|
+
'react/jsx-no-undef': 'error',
|
|
156
|
+
'react/jsx-no-useless-fragment': 'error',
|
|
157
|
+
'react/jsx-one-expression-per-line': ['off', { allow: 'single-child' }], // @todo Doesn't work with something like "Text <a href="...">Link</a> More Text", which should be valid
|
|
158
|
+
'react/jsx-curly-brace-presence': 'error',
|
|
159
|
+
'react/jsx-fragments': ['error', 'element'],
|
|
160
|
+
'react/jsx-pascal-case': ['error', { allowAllCaps: true }],
|
|
161
|
+
'react/jsx-props-no-multi-spaces': 'error',
|
|
162
|
+
'react/jsx-props-no-spreading': 'off',
|
|
163
|
+
'react/jsx-sort-default-props': 'error',
|
|
164
|
+
'react/jsx-sort-props': ['error', {
|
|
165
|
+
ignoreCase: true,
|
|
166
|
+
callbacksLast: true,
|
|
167
|
+
shorthandFirst: true,
|
|
168
|
+
shorthandLast: false,
|
|
169
|
+
noSortAlphabetically: true,
|
|
170
|
+
reservedFirst: true
|
|
171
|
+
}],
|
|
172
|
+
'react/jsx-tag-spacing': 'error',
|
|
173
|
+
'react/jsx-uses-react': 'error',
|
|
174
|
+
'react/jsx-uses-vars': 'error',
|
|
175
|
+
'react/jsx-wrap-multilines': 'error'
|
|
25
176
|
}
|
|
26
177
|
}
|
|
27
178
|
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "linter-bundle",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Ready-to use bundle of linting tools, containing configurations for ESLint, stylelint and markdownlint.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -33,38 +33,45 @@
|
|
|
33
33
|
"publish:minor": "npm version minor",
|
|
34
34
|
"publish:patch": "npm version patch",
|
|
35
35
|
"lint": "node ./lint tsc ts md audit --min-severity=critical",
|
|
36
|
-
"preversion": "npm run check-outdated && npm run lint",
|
|
36
|
+
"preversion": "npm run check-outdated && npm run stylelint-find-rules && npm run lint",
|
|
37
37
|
"postversion": "git push && git push --tags && npm publish",
|
|
38
|
+
"stylelint-find-rules": "stylelint-find-new-rules ./stylelint/index.js",
|
|
38
39
|
"check-outdated": "npx --yes -- check-outdated --ignore-pre-releases"
|
|
39
40
|
},
|
|
40
41
|
"dependencies": {
|
|
41
|
-
"@typescript-eslint/eslint-plugin": "5.
|
|
42
|
-
"@typescript-eslint/parser": "5.
|
|
43
|
-
"eslint": "8.
|
|
42
|
+
"@typescript-eslint/eslint-plugin": "5.11.0",
|
|
43
|
+
"@typescript-eslint/parser": "5.11.0",
|
|
44
|
+
"eslint": "8.8.0",
|
|
44
45
|
"eslint-import-resolver-typescript": "2.5.0",
|
|
45
46
|
"eslint-import-resolver-webpack": "0.13.2",
|
|
46
47
|
"eslint-plugin-eslint-comments": "3.2.0",
|
|
47
|
-
"eslint-plugin-functional": "4.0
|
|
48
|
-
"eslint-plugin-import": "2.25.
|
|
49
|
-
"eslint-plugin-jest": "
|
|
50
|
-
"eslint-plugin-jsdoc": "37.
|
|
48
|
+
"eslint-plugin-functional": "4.2.0",
|
|
49
|
+
"eslint-plugin-import": "2.25.4",
|
|
50
|
+
"eslint-plugin-jest": "26.1.0",
|
|
51
|
+
"eslint-plugin-jsdoc": "37.8.1",
|
|
52
|
+
"eslint-plugin-jsx-a11y": "6.5.1",
|
|
51
53
|
"eslint-plugin-node": "11.1.0",
|
|
52
|
-
"eslint-plugin-
|
|
53
|
-
"eslint-plugin-
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
54
|
+
"eslint-plugin-promise": "6.0.0",
|
|
55
|
+
"eslint-plugin-react": "7.28.0",
|
|
56
|
+
"eslint-plugin-react-hooks": "4.3.0",
|
|
57
|
+
"eslint-plugin-unicorn": "40.1.0",
|
|
58
|
+
"markdownlint-cli": "0.31.1",
|
|
59
|
+
"postcss-scss": "4.0.3",
|
|
60
|
+
"stylelint": "14.4.0",
|
|
61
|
+
"stylelint-declaration-block-no-ignored-properties": "2.5.0",
|
|
57
62
|
"stylelint-order": "5.0.0",
|
|
58
|
-
"stylelint-scss": "4.
|
|
63
|
+
"stylelint-scss": "4.1.0",
|
|
59
64
|
"stylelint-selector-no-empty": "1.0.8",
|
|
60
65
|
"stylelint-use-logical-spec": "3.2.2"
|
|
61
66
|
},
|
|
62
67
|
"peerDependencies": {
|
|
63
|
-
"typescript": "^4.0.0"
|
|
68
|
+
"typescript": "^4.0.0",
|
|
69
|
+
"postcss-value-parser": "*"
|
|
64
70
|
},
|
|
65
71
|
"devDependencies": {
|
|
66
|
-
"@types/eslint": "
|
|
67
|
-
"@types/node": "
|
|
68
|
-
"
|
|
72
|
+
"@types/eslint": "8.4.1",
|
|
73
|
+
"@types/node": "17.0.16",
|
|
74
|
+
"stylelint-find-new-rules": "^3.0.4",
|
|
75
|
+
"typescript": "4.5.5"
|
|
69
76
|
}
|
|
70
77
|
}
|
package/stylelint/index.js
CHANGED
|
@@ -4,18 +4,21 @@
|
|
|
4
4
|
|
|
5
5
|
/* eslint-disable max-lines -- The rules can be easier managed if they are all in one file */
|
|
6
6
|
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
7
9
|
module.exports = {
|
|
8
10
|
reportNeedlessDisables: true,
|
|
9
11
|
reportInvalidScopeDisables: true,
|
|
10
12
|
reportDescriptionlessDisables: true,
|
|
11
13
|
customSyntax: 'postcss-scss',
|
|
12
14
|
plugins: [
|
|
13
|
-
'stylelint-
|
|
15
|
+
'stylelint-declaration-block-no-ignored-properties',
|
|
14
16
|
'stylelint-order',
|
|
15
17
|
'stylelint-scss',
|
|
16
18
|
'stylelint-selector-no-empty',
|
|
17
19
|
'stylelint-use-logical-spec',
|
|
18
|
-
'
|
|
20
|
+
path.join(__dirname, '/plugins/stylelint-high-performance-animation.js'),
|
|
21
|
+
path.join(__dirname, '/plugins/stylelint-selector-tag-no-without-class.js')
|
|
19
22
|
],
|
|
20
23
|
overrides: [
|
|
21
24
|
{
|
|
@@ -180,6 +183,7 @@ module.exports = {
|
|
|
180
183
|
'function-linear-gradient-no-nonstandard-direction': true,
|
|
181
184
|
'function-max-empty-lines': 0,
|
|
182
185
|
'function-name-case': 'lower',
|
|
186
|
+
'function-no-unknown': false, // @todo Create issue for false positives for "color.scale"
|
|
183
187
|
'function-parentheses-newline-inside': 'always-multi-line',
|
|
184
188
|
'function-parentheses-space-inside': 'never-single-line',
|
|
185
189
|
'function-url-no-scheme-relative': true,
|
|
@@ -240,6 +244,7 @@ module.exports = {
|
|
|
240
244
|
],
|
|
241
245
|
'property-no-unknown': true,
|
|
242
246
|
'property-no-vendor-prefix': true,
|
|
247
|
+
'rule-selector-property-disallowed-list': null,
|
|
243
248
|
'rule-empty-line-before': [
|
|
244
249
|
'always-multi-line',
|
|
245
250
|
{
|
|
@@ -305,7 +310,12 @@ module.exports = {
|
|
|
305
310
|
'unit-case': 'lower',
|
|
306
311
|
'unit-disallowed-list': null,
|
|
307
312
|
'unit-no-unknown': true,
|
|
308
|
-
'value-keyword-case':
|
|
313
|
+
'value-keyword-case': [
|
|
314
|
+
'lower',
|
|
315
|
+
{
|
|
316
|
+
camelCaseSvgKeywords: true
|
|
317
|
+
}
|
|
318
|
+
],
|
|
309
319
|
'value-list-comma-newline-after': 'always-multi-line',
|
|
310
320
|
'value-list-comma-newline-before': 'never-multi-line',
|
|
311
321
|
'value-list-comma-space-after': 'always-single-line',
|
|
@@ -313,6 +323,13 @@ module.exports = {
|
|
|
313
323
|
'value-list-max-empty-lines': 0,
|
|
314
324
|
'value-no-vendor-prefix': true,
|
|
315
325
|
|
|
326
|
+
/**
|
|
327
|
+
* stylelint-declaration-block-no-ignored-properties
|
|
328
|
+
*
|
|
329
|
+
* @see https://www.npmjs.com/package/stylelint-declaration-block-no-ignored-properties
|
|
330
|
+
*/
|
|
331
|
+
'plugin/declaration-block-no-ignored-properties': true,
|
|
332
|
+
|
|
316
333
|
/**
|
|
317
334
|
* stylelint-high-performance-animation
|
|
318
335
|
*
|
|
@@ -837,6 +854,7 @@ module.exports = {
|
|
|
837
854
|
'scss/at-mixin-pattern': '^[a-z]+(-[a-z]+)*$',
|
|
838
855
|
'scss/at-rule-conditional-no-parentheses': true,
|
|
839
856
|
'scss/at-rule-no-unknown': true,
|
|
857
|
+
'scss/at-use-no-unnamespaced': true,
|
|
840
858
|
'scss/comment-no-empty': true,
|
|
841
859
|
'scss/comment-no-loud': true,
|
|
842
860
|
'scss/declaration-nested-properties-no-divided-groups': true,
|
|
@@ -860,6 +878,7 @@ module.exports = {
|
|
|
860
878
|
],
|
|
861
879
|
'scss/dollar-variable-first-in-block': [true, { ignore: ['comments', 'imports'] }],
|
|
862
880
|
'scss/dollar-variable-no-missing-interpolation': true,
|
|
881
|
+
'scss/dollar-variable-no-namespaced-assignment': true,
|
|
863
882
|
'scss/dollar-variable-pattern': '^[a-z]+(-[a-z]+)*$',
|
|
864
883
|
'scss/double-slash-comment-empty-line-before': [
|
|
865
884
|
'always',
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Fork of `stylelint-high-performance-animation` rule.
|
|
3
|
+
*
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @see https://github.com/kristerkari/stylelint-high-performance-animation
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const valueParser = require('postcss-value-parser');
|
|
9
|
+
/** @type {(declaration: import('postcss').Declaration) => number} */
|
|
10
|
+
// @ts-expect-error -- No declaration file.
|
|
11
|
+
const declarationValueIndex = require('stylelint/lib/utils/declarationValueIndex');
|
|
12
|
+
|
|
13
|
+
const stylelint = require('stylelint');
|
|
14
|
+
|
|
15
|
+
const ruleName = 'plugin/no-low-performance-animation-properties';
|
|
16
|
+
|
|
17
|
+
const messages = stylelint.utils.ruleMessages(ruleName, {
|
|
18
|
+
rejected: (type, property) => `Unexpected use of low performance ${type} property (${property}).`
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Function which ensures that a given `value` is of type "string".
|
|
23
|
+
*
|
|
24
|
+
* @param {any} value - Any value which should be ensured to be a string.
|
|
25
|
+
* @returns {boolean} - True if the value is a string, false otherwise.
|
|
26
|
+
*/
|
|
27
|
+
const isString = (value) => (typeof value === 'string');
|
|
28
|
+
|
|
29
|
+
// https://drafts.csswg.org/css-timing/
|
|
30
|
+
const cssLinearTimingFunctions = ['linear'];
|
|
31
|
+
const cssCubicBezierTimingFunctions = [
|
|
32
|
+
'ease',
|
|
33
|
+
'ease-in',
|
|
34
|
+
'ease-out',
|
|
35
|
+
'ease-in-out',
|
|
36
|
+
'cubic-bezier'
|
|
37
|
+
];
|
|
38
|
+
const cssStepTimingFunctions = ['step-start', 'step-end', 'steps'];
|
|
39
|
+
const cssFramesTimingFunctions = ['frames'];
|
|
40
|
+
const cssTimingFunctions = [
|
|
41
|
+
...cssLinearTimingFunctions,
|
|
42
|
+
...cssCubicBezierTimingFunctions,
|
|
43
|
+
...cssStepTimingFunctions,
|
|
44
|
+
...cssFramesTimingFunctions
|
|
45
|
+
];
|
|
46
|
+
const cssTimingFunctionsRE = new RegExp(`^(${cssTimingFunctions.join('|')}).*`, 'u');
|
|
47
|
+
|
|
48
|
+
const propertiesThatCauseLayout = [
|
|
49
|
+
'position',
|
|
50
|
+
'top',
|
|
51
|
+
'bottom',
|
|
52
|
+
'left',
|
|
53
|
+
'right',
|
|
54
|
+
'width',
|
|
55
|
+
'height',
|
|
56
|
+
'min-height',
|
|
57
|
+
'max-height',
|
|
58
|
+
'max-width',
|
|
59
|
+
'min-width',
|
|
60
|
+
'padding',
|
|
61
|
+
'padding-bottom',
|
|
62
|
+
'padding-left',
|
|
63
|
+
'padding-right',
|
|
64
|
+
'padding-top',
|
|
65
|
+
'margin',
|
|
66
|
+
'margin-bottom',
|
|
67
|
+
'margin-left',
|
|
68
|
+
'margin-right',
|
|
69
|
+
'margin-top',
|
|
70
|
+
'display',
|
|
71
|
+
'border-width',
|
|
72
|
+
'border-spacing',
|
|
73
|
+
'border-collapse',
|
|
74
|
+
'border',
|
|
75
|
+
'font',
|
|
76
|
+
'font-size',
|
|
77
|
+
'font-family',
|
|
78
|
+
'font-weight',
|
|
79
|
+
'font-style',
|
|
80
|
+
'float',
|
|
81
|
+
'overflow-y',
|
|
82
|
+
'overflow-x',
|
|
83
|
+
'overflow',
|
|
84
|
+
'line-height',
|
|
85
|
+
'vertical-align',
|
|
86
|
+
'clear',
|
|
87
|
+
'white-space',
|
|
88
|
+
'list-style',
|
|
89
|
+
'list-style-type',
|
|
90
|
+
'zoom',
|
|
91
|
+
'content',
|
|
92
|
+
'box-sizing',
|
|
93
|
+
'text-shadow',
|
|
94
|
+
'text-align',
|
|
95
|
+
'text-indent',
|
|
96
|
+
'text-transform',
|
|
97
|
+
'text-overflow',
|
|
98
|
+
'word-wrap',
|
|
99
|
+
'letter-spacing',
|
|
100
|
+
'appearance',
|
|
101
|
+
'direction'
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
const propsThatCausePaint = [
|
|
105
|
+
'color',
|
|
106
|
+
'border-color',
|
|
107
|
+
'border-style',
|
|
108
|
+
'border-radius',
|
|
109
|
+
'visibility',
|
|
110
|
+
'text-decoration',
|
|
111
|
+
'background',
|
|
112
|
+
'background-color',
|
|
113
|
+
'background-size',
|
|
114
|
+
'background-image',
|
|
115
|
+
'background-position',
|
|
116
|
+
'background-repeat',
|
|
117
|
+
'outline',
|
|
118
|
+
'outline-style',
|
|
119
|
+
'outline-width',
|
|
120
|
+
'outline-color',
|
|
121
|
+
'box-shadow'
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get blacklisted properties.
|
|
126
|
+
*
|
|
127
|
+
* @param {string} ignore - Property name.
|
|
128
|
+
* @returns {string[]} - Array of blacklisted properties.
|
|
129
|
+
*/
|
|
130
|
+
const getBlacklist = (ignore) => {
|
|
131
|
+
if (ignore === 'paint-properties') {
|
|
132
|
+
return propertiesThatCauseLayout;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return propertiesThatCauseLayout.concat(propsThatCausePaint);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Returns the input string stripped of its vendor prefix.
|
|
140
|
+
*
|
|
141
|
+
* @param {string} property - String with or without vendor prefix.
|
|
142
|
+
* @returns {string} String name without vendor prefixes.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* unprefixed('-moz-tab-size') //=> 'tab-size'
|
|
146
|
+
*/
|
|
147
|
+
const unprefixed = (property) => property.replace(/^-\w+-/u, '');
|
|
148
|
+
|
|
149
|
+
module.exports = stylelint.createPlugin(
|
|
150
|
+
ruleName,
|
|
151
|
+
(actual, options) => (cssRoot, result) => {
|
|
152
|
+
const validOptions = stylelint.utils.validateOptions(
|
|
153
|
+
result,
|
|
154
|
+
ruleName,
|
|
155
|
+
{ actual },
|
|
156
|
+
{
|
|
157
|
+
actual: options,
|
|
158
|
+
possible: {
|
|
159
|
+
ignore: ['paint-properties'],
|
|
160
|
+
ignoreProperties: [isString]
|
|
161
|
+
},
|
|
162
|
+
optional: true
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
if (!validOptions) { return; }
|
|
167
|
+
|
|
168
|
+
// @ts-expect-error -- Property 'ignore' comes from an index signature, so it must be accessed with ['ignore'].
|
|
169
|
+
const blacklist = getBlacklist(options.ignore);
|
|
170
|
+
// @ts-expect-error -- Property 'ignoreProperties' comes from an index signature, so it must be accessed with ['ignoreProperties'].
|
|
171
|
+
const ignored = (options.ignoreProperties ? options.ignoreProperties : []);
|
|
172
|
+
|
|
173
|
+
cssRoot.walkDecls('transition-property', (decl) => {
|
|
174
|
+
valueParser(decl.value).walk((node) => {
|
|
175
|
+
const value = unprefixed(node.value);
|
|
176
|
+
|
|
177
|
+
if (
|
|
178
|
+
node.type === 'word' &&
|
|
179
|
+
!ignored.includes(value) &&
|
|
180
|
+
(blacklist.includes(value) || value === 'all')
|
|
181
|
+
) {
|
|
182
|
+
const index = declarationValueIndex(decl) + node.sourceIndex;
|
|
183
|
+
|
|
184
|
+
stylelint.utils.report({
|
|
185
|
+
ruleName,
|
|
186
|
+
result,
|
|
187
|
+
node: decl,
|
|
188
|
+
message: messages.rejected('transition', node.value),
|
|
189
|
+
index
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
cssRoot.walkDecls('transition', (decl) => {
|
|
196
|
+
/** @type {{ index: number; value: string; }[]} */
|
|
197
|
+
const nodes = [];
|
|
198
|
+
|
|
199
|
+
valueParser(decl.value).walk((node) => {
|
|
200
|
+
if (node.type === 'word' || node.type === 'function') {
|
|
201
|
+
nodes.push({
|
|
202
|
+
index: node.sourceIndex,
|
|
203
|
+
value: node.value
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return false;
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
if (!ignored.includes('all')) {
|
|
211
|
+
const transitionProp = nodes.filter((node) => {
|
|
212
|
+
const isUnit = valueParser.unit(node.value);
|
|
213
|
+
const isTimingFunction = cssTimingFunctionsRE.test(node.value);
|
|
214
|
+
|
|
215
|
+
if (isUnit || isTimingFunction) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return node;
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
if (nodes.length > 0 && transitionProp.length === 0) {
|
|
223
|
+
stylelint.utils.report({
|
|
224
|
+
ruleName,
|
|
225
|
+
result,
|
|
226
|
+
node: decl,
|
|
227
|
+
message: messages.rejected('transition', 'all'),
|
|
228
|
+
index: declarationValueIndex(decl) + nodes[0].index
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
for (const property of nodes) {
|
|
236
|
+
const index = declarationValueIndex(decl) + property.index;
|
|
237
|
+
const value = unprefixed(property.value);
|
|
238
|
+
|
|
239
|
+
if (
|
|
240
|
+
!ignored.includes(value) &&
|
|
241
|
+
(blacklist.includes(value) || value === 'all')
|
|
242
|
+
) {
|
|
243
|
+
stylelint.utils.report({
|
|
244
|
+
ruleName,
|
|
245
|
+
result,
|
|
246
|
+
node: decl,
|
|
247
|
+
message: messages.rejected('transition', property.value),
|
|
248
|
+
index
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
cssRoot.walkAtRules(/^keyframes$/iu, (atRuleKeyframes) => {
|
|
255
|
+
atRuleKeyframes.walkDecls((decl) => {
|
|
256
|
+
const value = unprefixed(decl.prop);
|
|
257
|
+
|
|
258
|
+
if (!ignored.includes(value) && blacklist.includes(value)) {
|
|
259
|
+
stylelint.utils.report({
|
|
260
|
+
ruleName,
|
|
261
|
+
result,
|
|
262
|
+
node: decl,
|
|
263
|
+
message: messages.rejected('animation', decl.prop)
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
// @ts-expect-error -- Cannot assign to 'ruleName' because it is a read-only property.
|
|
272
|
+
module.exports.ruleName = ruleName;
|
|
273
|
+
module.exports.messages = messages;
|