linter-bundle 7.11.0 → 7.12.1
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/.linter-bundle.js +1 -1
- package/CHANGELOG.md +54 -1
- package/README.md +6 -6
- package/eslint/index.mjs +6 -0
- package/eslint/javascript.mjs +2 -0
- package/eslint/jest.mjs +8 -0
- package/eslint/jsdoc.mjs +1 -0
- package/eslint/rules/enforce-logical-expression-parens.mjs +0 -1
- package/eslint/rules/enforce-ternary-parens.mjs +0 -1
- package/eslint/rules/no-ternary-return.mjs +0 -1
- package/helper/get-git-files.js +2 -2
- package/package.json +21 -21
- package/stylelint/index.mjs +6 -4
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/media-feature-range-operator-space-before/index.mjs +1 -1
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-attribute-brackets-space-inside/index.mjs +80 -76
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-descendant-combinator-no-non-space/index.mjs +40 -36
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-pseudo-class-case/index.mjs +44 -41
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-pseudo-class-parentheses-space-inside/index.mjs +80 -76
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selectorAttributeOperatorSpaceChecker.mjs +18 -14
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selectorCombinatorSpaceChecker.mjs +34 -30
- package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/string-quotes/index.mjs +4 -2
- package/stylelint/plugins/stylelint-selector-tag-no-without-class.js +4 -3
package/.linter-bundle.js
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -6,7 +6,60 @@ 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/v7.
|
|
9
|
+
[Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v7.12.1...HEAD)
|
|
10
|
+
|
|
11
|
+
## [7.12.1] - 2026-02-21
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- [stylelint] Fix stylistic plugins crashing with `TypeError: selector.startsWith is not a function` due to `parseSelector` API change in stylelint 17 (callback parameter removed, now returns AST instead of string)
|
|
16
|
+
|
|
17
|
+
[Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v7.12.0...v7.12.1)
|
|
18
|
+
|
|
19
|
+
## [7.12.0] - 2026-02-20
|
|
20
|
+
|
|
21
|
+
### Breaking changes
|
|
22
|
+
|
|
23
|
+
- [general] Drop support for Node.js versions less than 20.19.0, 22.0.0-22.12.x as some of the dependencies are not supporting them anymore
|
|
24
|
+
- [stylelint] Replaced `stylelint-use-logical-spec` with [`stylelint-use-logical`](https://github.com/csstools/stylelint-use-logical). The rule name changed from `liberty/use-logical-spec` to `csstools/use-logical`.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- [eslint] Updated `@stylistic/eslint-plugin` from `5.6.1` to `5.9.0`
|
|
29
|
+
- [eslint] Updated `eslint` from `9.39.1` to `9.39.3`
|
|
30
|
+
- [eslint] Updated `eslint-plugin-jest` from `29.1.0` to `29.15.0`
|
|
31
|
+
- [eslint] Updated `eslint-plugin-jsdoc` from `61.3.0` to `62.7.0`
|
|
32
|
+
- [eslint] Updated `eslint-plugin-n` from `17.23.1` to `17.24.0`
|
|
33
|
+
- [eslint] Updated `eslint-plugin-unicorn` from `62.0.0` to `63.0.0`
|
|
34
|
+
- [eslint] Updated `globals` from `16.5.0` to `17.3.0`
|
|
35
|
+
- [eslint] Updated `typescript-eslint` from `8.47.0` to `8.56.0`
|
|
36
|
+
- [stylelint] Updated `stylelint` from `16.25.0` to `17.3.0`
|
|
37
|
+
- [stylelint] Updated `stylelint-declaration-block-no-ignored-properties` from `2.8.0` to `3.0.0`
|
|
38
|
+
- [stylelint] Updated `stylelint-high-performance-animation` from `1.11.0` to `2.0.0`
|
|
39
|
+
- [stylelint] Updated `stylelint-order` from `7.0.0` to `7.0.1`
|
|
40
|
+
- [stylelint] Updated `stylelint-scss` from `6.12.1` to `7.0.0`
|
|
41
|
+
- [markdown] Updated `markdownlint-cli` from `0.46.0` to `0.47.0`
|
|
42
|
+
- [eslint] Make use of new [`jsdoc/require-rejects`](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-rejects.md) rule
|
|
43
|
+
- [eslint] Make use of new [`unicorn/isolated-functions`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/isolated-functions.md) rule
|
|
44
|
+
- [eslint] Make use of new [`@typescript-eslint/no-unused-private-class-members`](https://typescript-eslint.io/rules/no-unused-private-class-members/) rule
|
|
45
|
+
- [eslint] Make use of new [`@typescript-eslint/no-useless-default-assignment`](https://typescript-eslint.io/rules/no-useless-default-assignment/) rule
|
|
46
|
+
- [eslint] Make use of new [`jest/no-error-equal`](https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/no-error-equal.md) rule
|
|
47
|
+
- [eslint] Make use of new [`jest/no-unneeded-async-expect-function`](https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/no-unneeded-async-expect-function.md) rule
|
|
48
|
+
- [eslint] Make use of new [`jest/no-unnecessary-assertion`](https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/no-unnecessary-assertion.md) rule
|
|
49
|
+
- [eslint] Make use of new [`jest/prefer-mock-return-shorthand`](https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/prefer-mock-return-shorthand.md) rule
|
|
50
|
+
- [eslint] Make use of new [`jest/prefer-to-have-been-called`](https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/prefer-to-have-been-called.md) rule
|
|
51
|
+
- [eslint] Make use of new [`jest/prefer-to-have-been-called-times`](https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/prefer-to-have-been-called-times.md) rule
|
|
52
|
+
- [eslint] Make use of new [`jest/valid-expect-with-promise`](https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/valid-expect-with-promise.md) rule
|
|
53
|
+
- [eslint] Make use of new [`jest/valid-mock-module-path`](https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/valid-mock-module-path.md) rule
|
|
54
|
+
- [eslint] Make use of new [`n/prefer-global/crypto`](https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/prefer-global/crypto.md) rule
|
|
55
|
+
- [eslint] Make use of new [`n/prefer-global/timers`](https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/prefer-global/timers.md) rule
|
|
56
|
+
- [eslint] Make use of new [`@typescript-eslint/strict-void-return`](https://typescript-eslint.io/rules/strict-void-return/) rule
|
|
57
|
+
- [eslint] Added but disabled [`@stylistic/jsx-props-style`](https://eslint.style/rules/jsx-props-style) rule, as it is an experimental feature
|
|
58
|
+
- [stylelint] Added but disabled [`display-notation`](https://stylelint.io/user-guide/rules/display-notation/) rule
|
|
59
|
+
- [stylelint] Added but disabled [`scss/selector-class-pattern`](https://github.com/stylelint-scss/stylelint-scss/tree/master/src/rules/selector-class-pattern) rule
|
|
60
|
+
- [stylelint] Updated forked `plugin/selector-tag-no-without-class` for stylelint 17 compatibility (adapted `parseSelector` API change)
|
|
61
|
+
|
|
62
|
+
[Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v7.11.0...v7.12.0)
|
|
10
63
|
|
|
11
64
|
## [7.11.0] - 2025-11-19
|
|
12
65
|
|
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ Beside that, the following additional rules are part of this bundle:
|
|
|
56
56
|
- [stylelint-scss](https://www.npmjs.com/package/stylelint-scss)
|
|
57
57
|
- [stylelint-selector-no-empty](https://www.npmjs.com/package/stylelint-selector-no-empty) (Forked version)
|
|
58
58
|
- [stylelint-selector-tag-no-without-class](https://www.npmjs.com/package/stylelint-selector-tag-no-without-class) (Forked version)
|
|
59
|
-
- [stylelint-use-logical
|
|
59
|
+
- [stylelint-use-logical](https://www.npmjs.com/package/stylelint-use-logical)
|
|
60
60
|
|
|
61
61
|
Beside that [72 stylistic rules](https://github.com/jens-duttke/linter-bundle/tree/main/stylelint/plugins/stylelint-15.11.0-stylistic/rules) has been forked from `stylelint@15.11.0`, which have been removed in `stylelint@16.0.0`, are part of this bundle.
|
|
62
62
|
|
|
@@ -113,8 +113,8 @@ export default [
|
|
|
113
113
|
...reactConfig,
|
|
114
114
|
...storybookConfig,
|
|
115
115
|
...typeDeclarationsConfig,
|
|
116
|
-
...workerConfig
|
|
117
|
-
...jestConfig
|
|
116
|
+
...workerConfig,
|
|
117
|
+
...jestConfig
|
|
118
118
|
]
|
|
119
119
|
```
|
|
120
120
|
|
|
@@ -668,7 +668,7 @@ To ensure the stylelint plugins are correctly loaded, you need to adjust the set
|
|
|
668
668
|
```json
|
|
669
669
|
{
|
|
670
670
|
"stylelint.enable": true,
|
|
671
|
-
"stylelint.validate": [
|
|
671
|
+
"stylelint.validate": [
|
|
672
672
|
"css",
|
|
673
673
|
"scss"
|
|
674
674
|
],
|
|
@@ -685,8 +685,8 @@ In order to fix the code according to the ESLint/stylelint rules when saving, th
|
|
|
685
685
|
```json
|
|
686
686
|
{
|
|
687
687
|
"editor.codeActionsOnSave": {
|
|
688
|
-
"source.fixAll.eslint":
|
|
689
|
-
"source.fixAll.stylelint":
|
|
688
|
+
"source.fixAll.eslint": "explicit",
|
|
689
|
+
"source.fixAll.stylelint": "explicit"
|
|
690
690
|
}
|
|
691
691
|
}
|
|
692
692
|
```
|
package/eslint/index.mjs
CHANGED
|
@@ -465,6 +465,7 @@ export default [
|
|
|
465
465
|
ignoredNodes: ['ConditionalExpression']
|
|
466
466
|
}
|
|
467
467
|
],
|
|
468
|
+
'@stylistic/jsx-props-style': 'off', // Experimental feature
|
|
468
469
|
'@stylistic/key-spacing': 'error',
|
|
469
470
|
'@stylistic/member-delimiter-style': ['error', { multiline: { delimiter: 'semi', requireLast: true }, singleline: { delimiter: 'semi', requireLast: true } }],
|
|
470
471
|
'@stylistic/no-extra-semi': 'error',
|
|
@@ -795,6 +796,7 @@ export default [
|
|
|
795
796
|
'@typescript-eslint/no-unsafe-unary-minus': 'error',
|
|
796
797
|
'@typescript-eslint/no-unused-expressions': 'error',
|
|
797
798
|
'@typescript-eslint/no-unsafe-type-assertion': 'error',
|
|
799
|
+
'@typescript-eslint/no-unused-private-class-members': 'error',
|
|
798
800
|
'@typescript-eslint/no-unused-vars': ['error', {
|
|
799
801
|
args: 'all',
|
|
800
802
|
argsIgnorePattern: '^_',
|
|
@@ -806,6 +808,7 @@ export default [
|
|
|
806
808
|
}],
|
|
807
809
|
'@typescript-eslint/no-use-before-define': ['error', { functions: false }],
|
|
808
810
|
'@typescript-eslint/no-useless-constructor': 'error',
|
|
811
|
+
'@typescript-eslint/no-useless-default-assignment': 'error',
|
|
809
812
|
'@typescript-eslint/no-useless-empty-export': 'error',
|
|
810
813
|
'@typescript-eslint/no-var-requires': 'error',
|
|
811
814
|
'@typescript-eslint/non-nullable-type-assertion-style': 'off', // Conflicts with `no-non-null-assertion`, which we prefer
|
|
@@ -841,6 +844,7 @@ export default [
|
|
|
841
844
|
'@typescript-eslint/sort-type-constituents': 'off', // Types should be sorted and grouped by priority and their meaning, not alphabetically
|
|
842
845
|
'@typescript-eslint/sort-type-union-intersection-members': 'off', // Types should be sorted and grouped by priority and their meaning, not alphabetically
|
|
843
846
|
'@typescript-eslint/strict-boolean-expressions': ['off', { allowNullable: true, allowSafe: true, ignoreRhs: true }], // @todo Doesn't work for specific code, check later after all linter warnings are fixed, maybe at some positions we can use '??'
|
|
847
|
+
'@typescript-eslint/strict-void-return': 'error',
|
|
844
848
|
'@typescript-eslint/switch-exhaustiveness-check': ['error', { considerDefaultExhaustiveForUnions: true }],
|
|
845
849
|
'@typescript-eslint/triple-slash-reference': 'error',
|
|
846
850
|
'@typescript-eslint/typedef': 'off', // We are using "noImplicitAny" in tsconfig.json instead
|
|
@@ -958,6 +962,7 @@ export default [
|
|
|
958
962
|
|
|
959
963
|
/**
|
|
960
964
|
* eslint-plugin-eslint-comments
|
|
965
|
+
*
|
|
961
966
|
* @see https://mysticatea.github.io/eslint-plugin-eslint-comments/
|
|
962
967
|
*/
|
|
963
968
|
'eslint-comments/disable-enable-pair': ['error', { allowWholeFile: true }],
|
|
@@ -1047,6 +1052,7 @@ export default [
|
|
|
1047
1052
|
}
|
|
1048
1053
|
}
|
|
1049
1054
|
}],
|
|
1055
|
+
'unicorn/isolated-functions': 'error',
|
|
1050
1056
|
'unicorn/new-for-builtins': 'error',
|
|
1051
1057
|
'unicorn/no-abusive-eslint-disable': 'error',
|
|
1052
1058
|
'unicorn/no-accessor-recursion': 'error',
|
package/eslint/javascript.mjs
CHANGED
|
@@ -86,9 +86,11 @@ export default [
|
|
|
86
86
|
'n/no-top-level-await': 'off', // Conflicts with unicorn/prefer-await
|
|
87
87
|
'n/prefer-global/buffer': 'error',
|
|
88
88
|
'n/prefer-global/console': 'error',
|
|
89
|
+
'n/prefer-global/crypto': 'error',
|
|
89
90
|
'n/prefer-global/process': 'error',
|
|
90
91
|
'n/prefer-global/text-decoder': 'error',
|
|
91
92
|
'n/prefer-global/text-encoder': 'error',
|
|
93
|
+
'n/prefer-global/timers': 'error',
|
|
92
94
|
'n/prefer-global/url-search-params': 'error',
|
|
93
95
|
'n/prefer-global/url': 'error',
|
|
94
96
|
'n/prefer-promises/dns': 'error',
|
package/eslint/jest.mjs
CHANGED
|
@@ -71,6 +71,7 @@ export default [
|
|
|
71
71
|
'jest/no-disabled-tests': 'error',
|
|
72
72
|
'jest/no-done-callback': 'error',
|
|
73
73
|
'jest/no-duplicate-hooks': 'error',
|
|
74
|
+
'jest/no-error-equal': 'error',
|
|
74
75
|
'jest/no-export': 'error',
|
|
75
76
|
'jest/no-focused-tests': 'error',
|
|
76
77
|
'jest/no-hooks': ['error', { allow: ['beforeEach', 'afterEach', 'afterAll'] }],
|
|
@@ -90,6 +91,8 @@ export default [
|
|
|
90
91
|
'jest/no-standalone-expect': 'error',
|
|
91
92
|
'jest/no-test-prefixes': 'error',
|
|
92
93
|
'jest/no-test-return-statement': 'error',
|
|
94
|
+
'jest/no-unneeded-async-expect-function': 'error',
|
|
95
|
+
'jest/no-unnecessary-assertion': 'error',
|
|
93
96
|
'jest/prefer-called-with': 'error',
|
|
94
97
|
'jest/prefer-expect-assertions': ['error', { onlyFunctionsWithAsyncKeyword: true }],
|
|
95
98
|
'jest/prefer-expect-resolves': 'off', // We prefer `expect(await promise)` enforced by 'jest/no-restricted-matchers'
|
|
@@ -102,11 +105,14 @@ export default [
|
|
|
102
105
|
'jest/prefer-importing-jest-globals': 'error',
|
|
103
106
|
'jest/prefer-jest-mocked': 'error',
|
|
104
107
|
'jest/prefer-mock-promise-shorthand': 'error',
|
|
108
|
+
'jest/prefer-mock-return-shorthand': 'error',
|
|
105
109
|
'jest/prefer-snapshot-hint': 'error',
|
|
106
110
|
'jest/prefer-spy-on': 'error',
|
|
107
111
|
'jest/prefer-strict-equal': 'error',
|
|
108
112
|
'jest/prefer-to-be': 'error',
|
|
109
113
|
'jest/prefer-to-contain': 'error',
|
|
114
|
+
'jest/prefer-to-have-been-called': 'error',
|
|
115
|
+
'jest/prefer-to-have-been-called-times': 'error',
|
|
110
116
|
'jest/prefer-to-have-length': 'error',
|
|
111
117
|
'jest/prefer-todo': 'error',
|
|
112
118
|
'jest/require-hook': 'error',
|
|
@@ -116,6 +122,8 @@ export default [
|
|
|
116
122
|
'jest/valid-describe-callback': 'error',
|
|
117
123
|
'jest/valid-expect-in-promise': 'error',
|
|
118
124
|
'jest/valid-expect': 'error',
|
|
125
|
+
'jest/valid-expect-with-promise': 'error',
|
|
126
|
+
'jest/valid-mock-module-path': 'error',
|
|
119
127
|
'jest/valid-title': 'error'
|
|
120
128
|
}
|
|
121
129
|
},
|
package/eslint/jsdoc.mjs
CHANGED
|
@@ -77,6 +77,7 @@ export default [
|
|
|
77
77
|
'jsdoc/require-returns-description': 'error',
|
|
78
78
|
'jsdoc/require-returns-type': 'error',
|
|
79
79
|
'jsdoc/require-returns': ['error', { forceReturnsWithAsync: true }],
|
|
80
|
+
'jsdoc/require-rejects': 'error',
|
|
80
81
|
'jsdoc/require-template-description': 'off',
|
|
81
82
|
'jsdoc/require-template': 'error',
|
|
82
83
|
'jsdoc/require-throws-description': 'error',
|
package/helper/get-git-files.js
CHANGED
|
@@ -34,12 +34,12 @@ export async function getGitFiles () {
|
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
if (!gitFiles) {
|
|
37
|
-
const deletedFiles = gitProcessResult.deleted.stdout.trim().split('\0');
|
|
37
|
+
const deletedFiles = new Set(gitProcessResult.deleted.stdout.trim().split('\0'));
|
|
38
38
|
|
|
39
39
|
gitFiles = [
|
|
40
40
|
...gitProcessResult.diff.stdout.trim().split('\0'),
|
|
41
41
|
...gitProcessResult.modified.stdout.trim().split('\0')
|
|
42
|
-
].filter((file, index, self) => (!deletedFiles.
|
|
42
|
+
].filter((file, index, self) => (!deletedFiles.has(file) && self.indexOf(file) === index));
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
return gitFiles;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "linter-bundle",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.12.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Ready-to use bundle of linting tools, containing configurations for ESLint, stylelint and markdownlint.",
|
|
6
6
|
"keywords": [
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"lint": "lint.js"
|
|
25
25
|
},
|
|
26
26
|
"engines": {
|
|
27
|
-
"node": "^20.
|
|
27
|
+
"node": "^20.19.0 || ^22.13.0 || >=24.0.0"
|
|
28
28
|
},
|
|
29
29
|
"repository": {
|
|
30
30
|
"type": "git",
|
|
@@ -35,40 +35,40 @@
|
|
|
35
35
|
"publish:minor": "npm version minor",
|
|
36
36
|
"publish:patch": "npm version patch",
|
|
37
37
|
"lint": "npm run _test-stylelint && npm run _stylelint-find-rules && node ./lint files tsc ts md audit --min-severity=critical",
|
|
38
|
-
"preversion": "npm run check-outdated && npm run lint",
|
|
38
|
+
"preversion": "npm whoami && npm run check-outdated && npm run lint",
|
|
39
39
|
"postversion": "git push && git push --tags && npm publish",
|
|
40
|
-
"check-outdated": "npx --yes -- check-outdated --ignore-pre-releases",
|
|
40
|
+
"check-outdated": "npx --yes -- check-outdated --ignore-pre-releases --min-age 30 --min-age-patch 1",
|
|
41
41
|
"_stylelint-find-rules": "stylelint-find-new-rules ./stylelint/index.mjs",
|
|
42
42
|
"_test-stylelint": "node ./test-stylelint.js"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@stylistic/eslint-plugin": "5.
|
|
46
|
-
"eslint": "9.39.
|
|
45
|
+
"@stylistic/eslint-plugin": "5.9.0",
|
|
46
|
+
"eslint": "9.39.3",
|
|
47
47
|
"eslint-formatter-unix": "9.0.1",
|
|
48
48
|
"eslint-import-resolver-typescript": "4.4.4",
|
|
49
49
|
"eslint-import-resolver-webpack": "0.13.10",
|
|
50
50
|
"eslint-plugin-eslint-comments": "3.2.0",
|
|
51
51
|
"eslint-plugin-functional": "9.0.2",
|
|
52
52
|
"eslint-plugin-import": "2.32.0",
|
|
53
|
-
"eslint-plugin-jest": "29.
|
|
54
|
-
"eslint-plugin-jsdoc": "
|
|
53
|
+
"eslint-plugin-jest": "29.15.0",
|
|
54
|
+
"eslint-plugin-jsdoc": "62.7.0",
|
|
55
55
|
"eslint-plugin-jsx-a11y": "6.10.2",
|
|
56
|
-
"eslint-plugin-n": "17.
|
|
56
|
+
"eslint-plugin-n": "17.24.0",
|
|
57
57
|
"eslint-plugin-promise": "7.2.1",
|
|
58
58
|
"eslint-plugin-react": "7.37.5",
|
|
59
59
|
"eslint-plugin-react-hooks": "7.0.1",
|
|
60
|
-
"eslint-plugin-unicorn": "
|
|
61
|
-
"globals": "
|
|
62
|
-
"markdownlint-cli": "0.
|
|
60
|
+
"eslint-plugin-unicorn": "63.0.0",
|
|
61
|
+
"globals": "17.3.0",
|
|
62
|
+
"markdownlint-cli": "0.47.0",
|
|
63
63
|
"micromatch": "4.0.8",
|
|
64
64
|
"postcss-scss": "4.0.9",
|
|
65
|
-
"stylelint": "
|
|
66
|
-
"stylelint-declaration-block-no-ignored-properties": "
|
|
67
|
-
"stylelint-high-performance-animation": "
|
|
68
|
-
"stylelint-order": "7.0.
|
|
69
|
-
"stylelint-scss": "
|
|
70
|
-
"stylelint-use-logical
|
|
71
|
-
"typescript-eslint": "8.
|
|
65
|
+
"stylelint": "17.3.0",
|
|
66
|
+
"stylelint-declaration-block-no-ignored-properties": "3.0.0",
|
|
67
|
+
"stylelint-high-performance-animation": "2.0.0",
|
|
68
|
+
"stylelint-order": "7.0.1",
|
|
69
|
+
"stylelint-scss": "7.0.0",
|
|
70
|
+
"stylelint-use-logical": "2.1.3",
|
|
71
|
+
"typescript-eslint": "8.56.0"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
74
|
"@typescript-eslint/utils": "*",
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"@types/eslint": "9.6.1",
|
|
80
80
|
"@types/micromatch": "4.0.10",
|
|
81
|
-
"@types/node": "
|
|
82
|
-
"stylelint-find-new-rules": "
|
|
81
|
+
"@types/node": "25.3.0",
|
|
82
|
+
"stylelint-find-new-rules": "6.0.0",
|
|
83
83
|
"typescript": "5.9.3"
|
|
84
84
|
}
|
|
85
85
|
}
|
package/stylelint/index.mjs
CHANGED
|
@@ -16,7 +16,7 @@ export default {
|
|
|
16
16
|
'stylelint-declaration-block-no-ignored-properties',
|
|
17
17
|
'stylelint-order',
|
|
18
18
|
'stylelint-scss',
|
|
19
|
-
'stylelint-use-logical
|
|
19
|
+
'stylelint-use-logical',
|
|
20
20
|
'stylelint-high-performance-animation',
|
|
21
21
|
await import('./plugins/stylelint-selector-no-empty.js'),
|
|
22
22
|
await import('./plugins/stylelint-selector-tag-no-without-class.js'),
|
|
@@ -329,6 +329,7 @@ export default {
|
|
|
329
329
|
'declaration-property-value-disallowed-list': null,
|
|
330
330
|
'declaration-property-value-keyword-no-deprecated': true,
|
|
331
331
|
'declaration-property-value-no-unknown': true,
|
|
332
|
+
'display-notation': null, // Not yet enforcing short vs. long display notation (e.g. "block flow" vs. "block")
|
|
332
333
|
'font-family-name-quotes': 'always-where-recommended',
|
|
333
334
|
'font-family-no-duplicate-names': true,
|
|
334
335
|
'font-family-no-missing-generic-family-keyword': true,
|
|
@@ -1139,6 +1140,7 @@ export default {
|
|
|
1139
1140
|
'scss/partial-no-import': null,
|
|
1140
1141
|
'scss/percent-placeholder-pattern': null,
|
|
1141
1142
|
'scss/property-no-unknown': [true, { ignoreProperties: ['composes'] }],
|
|
1143
|
+
'scss/selector-class-pattern': null, // Already handled by core selector-class-pattern rule
|
|
1142
1144
|
'scss/selector-nest-combinators': null, // Sometimes nesting does not make sense
|
|
1143
1145
|
'scss/selector-no-redundant-nesting-selector': true,
|
|
1144
1146
|
'scss/selector-no-union-class-name': null,
|
|
@@ -1158,11 +1160,11 @@ export default {
|
|
|
1158
1160
|
'plugin/selector-tag-no-without-class': null,
|
|
1159
1161
|
|
|
1160
1162
|
/**
|
|
1161
|
-
* stylelint-use-logical
|
|
1163
|
+
* stylelint-use-logical
|
|
1162
1164
|
*
|
|
1163
|
-
* @see https://github.com/
|
|
1165
|
+
* @see https://github.com/csstools/stylelint-use-logical
|
|
1164
1166
|
*/
|
|
1165
|
-
'
|
|
1167
|
+
'csstools/use-logical': ['always', { except: [
|
|
1166
1168
|
'float',
|
|
1167
1169
|
|
|
1168
1170
|
'inset',
|
|
@@ -39,7 +39,7 @@ const rule = (primary, _secondaryOptions) => {
|
|
|
39
39
|
/** @type {number[]} */
|
|
40
40
|
const fixOperatorIndices = [];
|
|
41
41
|
findMediaOperator(atRule, (match, parameters, node) => {
|
|
42
|
-
checkBeforeOperator(match, parameters, node, (index) => fixOperatorIndices.push(index));
|
|
42
|
+
checkBeforeOperator(match, parameters, node, (index) => { fixOperatorIndices.push(index); });
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
if (fixOperatorIndices.length > 0) {
|
|
@@ -47,88 +47,92 @@ const rule = (primary, _secondaryOptions) => {
|
|
|
47
47
|
const selector = ruleNode.raws.selector ? ruleNode.raws.selector.raw : ruleNode.selector;
|
|
48
48
|
|
|
49
49
|
let hasFixed;
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
50
|
+
const selectorTree = parseSelector(selector, result, ruleNode);
|
|
51
|
+
|
|
52
|
+
if (!selectorTree) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
selectorTree.walkAttributes((attributeNode) => {
|
|
57
|
+
const attributeSelectorString = attributeNode.toString();
|
|
58
|
+
|
|
59
|
+
styleSearch({ source: attributeSelectorString, target: '[' }, (match) => {
|
|
60
|
+
const nextCharIsSpace = attributeSelectorString[match.startIndex + 1] === ' ';
|
|
61
|
+
const index = attributeNode.sourceIndex + match.startIndex + 1;
|
|
62
|
+
|
|
63
|
+
if (nextCharIsSpace && primary === 'never') {
|
|
64
|
+
report({
|
|
65
|
+
message: messages.rejectedOpening,
|
|
66
|
+
index,
|
|
67
|
+
endIndex: index,
|
|
68
|
+
result,
|
|
69
|
+
ruleName,
|
|
70
|
+
node: ruleNode,
|
|
71
|
+
fix: () => {
|
|
72
|
+
hasFixed = true;
|
|
73
|
+
fixBefore(attributeNode);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!nextCharIsSpace && primary === 'always') {
|
|
79
|
+
report({
|
|
80
|
+
message: messages.expectedOpening,
|
|
81
|
+
index,
|
|
82
|
+
endIndex: index,
|
|
83
|
+
result,
|
|
84
|
+
ruleName,
|
|
85
|
+
node: ruleNode,
|
|
86
|
+
fix: () => {
|
|
87
|
+
hasFixed = true;
|
|
88
|
+
fixBefore(attributeNode);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
styleSearch({ source: attributeSelectorString, target: ']' }, (match) => {
|
|
95
|
+
const previousCharIsSpace = attributeSelectorString[match.startIndex - 1] === ' ';
|
|
96
|
+
const index = attributeNode.sourceIndex + match.startIndex - 1;
|
|
97
|
+
|
|
98
|
+
if (previousCharIsSpace && primary === 'never') {
|
|
99
|
+
report({
|
|
100
|
+
message: messages.rejectedClosing,
|
|
101
|
+
index,
|
|
102
|
+
endIndex: index,
|
|
103
|
+
result,
|
|
104
|
+
ruleName,
|
|
105
|
+
node: ruleNode,
|
|
106
|
+
fix: () => {
|
|
107
|
+
hasFixed = true;
|
|
108
|
+
fixAfter(attributeNode);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!previousCharIsSpace && primary === 'always') {
|
|
114
|
+
report({
|
|
115
|
+
message: messages.expectedClosing,
|
|
116
|
+
index,
|
|
117
|
+
endIndex: index,
|
|
118
|
+
result,
|
|
119
|
+
ruleName,
|
|
120
|
+
node: ruleNode,
|
|
121
|
+
fix: () => {
|
|
122
|
+
hasFixed = true;
|
|
123
|
+
fixAfter(attributeNode);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
123
127
|
});
|
|
124
128
|
});
|
|
125
129
|
|
|
126
|
-
if (hasFixed
|
|
130
|
+
if (hasFixed) {
|
|
127
131
|
if (!ruleNode.raws.selector) {
|
|
128
|
-
ruleNode.selector =
|
|
132
|
+
ruleNode.selector = selectorTree.toString();
|
|
129
133
|
}
|
|
130
134
|
else {
|
|
131
|
-
ruleNode.raws.selector.raw =
|
|
135
|
+
ruleNode.raws.selector.raw = selectorTree.toString();
|
|
132
136
|
}
|
|
133
137
|
}
|
|
134
138
|
});
|
|
@@ -40,47 +40,51 @@ const rule = (primary, _secondaryOptions) => (root, result) => {
|
|
|
40
40
|
// @todo re-enable when parser and stylelint are compatible
|
|
41
41
|
if (selector.includes('/*')) { return; }
|
|
42
42
|
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
43
|
+
const selectorTree = parseSelector(selector, result, ruleNode);
|
|
44
|
+
|
|
45
|
+
if (!selectorTree) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
selectorTree.walkCombinators((combinatorNode) => {
|
|
50
|
+
if (combinatorNode.value !== ' ') {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const value = combinatorNode.toString();
|
|
55
|
+
|
|
56
|
+
if (
|
|
57
|
+
value.includes(' ') ||
|
|
58
|
+
value.includes('\t') ||
|
|
59
|
+
value.includes('\n') ||
|
|
60
|
+
value.includes('\r')
|
|
61
|
+
) {
|
|
62
|
+
report({
|
|
63
|
+
result,
|
|
64
|
+
ruleName,
|
|
65
|
+
message: messages.rejected(value),
|
|
66
|
+
node: ruleNode,
|
|
67
|
+
index: combinatorNode.sourceIndex,
|
|
68
|
+
endIndex: combinatorNode.sourceIndex,
|
|
69
|
+
fix: ((/^\s+$/u).test(value) ? () => {
|
|
70
|
+
hasFixed = true;
|
|
71
|
+
|
|
72
|
+
if (!combinatorNode.raws) { combinatorNode.raws = {}; }
|
|
73
|
+
|
|
74
|
+
combinatorNode.raws.value = ' ';
|
|
75
|
+
combinatorNode.rawSpaceBefore = combinatorNode.rawSpaceBefore.replace(/^\s+/u, '');
|
|
76
|
+
combinatorNode.rawSpaceAfter = combinatorNode.rawSpaceAfter.replace(/\s+$/u, '');
|
|
77
|
+
} : undefined)
|
|
78
|
+
});
|
|
79
|
+
}
|
|
76
80
|
});
|
|
77
81
|
|
|
78
|
-
if (hasFixed
|
|
82
|
+
if (hasFixed) {
|
|
79
83
|
if (!ruleNode.raws.selector) {
|
|
80
|
-
ruleNode.selector =
|
|
84
|
+
ruleNode.selector = selectorTree.toString();
|
|
81
85
|
}
|
|
82
86
|
else {
|
|
83
|
-
ruleNode.raws.selector.raw =
|
|
87
|
+
ruleNode.raws.selector.raw = selectorTree.toString();
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
90
|
});
|
package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selector-pseudo-class-case/index.mjs
CHANGED
|
@@ -44,54 +44,57 @@ const rule = (primary, _secondaryOptions) => (root, result) => {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
let hasFixed = false;
|
|
47
|
-
const
|
|
47
|
+
const selectorTree = parseSelector(
|
|
48
48
|
ruleNode.raws.selector ? ruleNode.raws.selector.raw : ruleNode.selector,
|
|
49
49
|
result,
|
|
50
|
-
ruleNode
|
|
51
|
-
(selectorTree) => {
|
|
52
|
-
selectorTree.walkPseudos((pseudoNode) => {
|
|
53
|
-
const pseudo = pseudoNode.value;
|
|
54
|
-
|
|
55
|
-
if (!isStandardSyntaxSelector(pseudo)) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
pseudo.includes('::') ||
|
|
61
|
-
levelOneAndTwoPseudoElements.has(pseudo.toLowerCase().slice(1))
|
|
62
|
-
) {
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const expectedPseudo =
|
|
67
|
-
primary === 'lower' ? pseudo.toLowerCase() : pseudo.toUpperCase();
|
|
68
|
-
|
|
69
|
-
if (pseudo === expectedPseudo) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
report({
|
|
74
|
-
message: messages.expected(pseudo, expectedPseudo),
|
|
75
|
-
node: ruleNode,
|
|
76
|
-
index: pseudoNode.sourceIndex,
|
|
77
|
-
endIndex: pseudoNode.sourceIndex,
|
|
78
|
-
ruleName,
|
|
79
|
-
result,
|
|
80
|
-
fix: () => {
|
|
81
|
-
hasFixed = true;
|
|
82
|
-
pseudoNode.value = expectedPseudo;
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
}
|
|
50
|
+
ruleNode
|
|
87
51
|
);
|
|
88
52
|
|
|
89
|
-
if (
|
|
53
|
+
if (!selectorTree) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
selectorTree.walkPseudos((pseudoNode) => {
|
|
58
|
+
const pseudo = pseudoNode.value;
|
|
59
|
+
|
|
60
|
+
if (!isStandardSyntaxSelector(pseudo)) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (
|
|
65
|
+
pseudo.includes('::') ||
|
|
66
|
+
levelOneAndTwoPseudoElements.has(pseudo.toLowerCase().slice(1))
|
|
67
|
+
) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const expectedPseudo =
|
|
72
|
+
primary === 'lower' ? pseudo.toLowerCase() : pseudo.toUpperCase();
|
|
73
|
+
|
|
74
|
+
if (pseudo === expectedPseudo) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
report({
|
|
79
|
+
message: messages.expected(pseudo, expectedPseudo),
|
|
80
|
+
node: ruleNode,
|
|
81
|
+
index: pseudoNode.sourceIndex,
|
|
82
|
+
endIndex: pseudoNode.sourceIndex,
|
|
83
|
+
ruleName,
|
|
84
|
+
result,
|
|
85
|
+
fix: () => {
|
|
86
|
+
hasFixed = true;
|
|
87
|
+
pseudoNode.value = expectedPseudo;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (hasFixed) {
|
|
90
93
|
if (ruleNode.raws.selector) {
|
|
91
|
-
ruleNode.raws.selector.raw =
|
|
94
|
+
ruleNode.raws.selector.raw = selectorTree.toString();
|
|
92
95
|
}
|
|
93
96
|
else {
|
|
94
|
-
ruleNode.selector =
|
|
97
|
+
ruleNode.selector = selectorTree.toString();
|
|
95
98
|
}
|
|
96
99
|
}
|
|
97
100
|
});
|
|
@@ -43,87 +43,91 @@ const rule = (primary, _secondaryOptions) => (root, result) => {
|
|
|
43
43
|
|
|
44
44
|
let hasFixed = false;
|
|
45
45
|
const selector = ruleNode.raws.selector ? ruleNode.raws.selector.raw : ruleNode.selector;
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
46
|
+
const selectorTree = parseSelector(selector, result, ruleNode);
|
|
47
|
+
|
|
48
|
+
if (!selectorTree) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
selectorTree.walkPseudos((pseudoNode) => {
|
|
53
|
+
if (pseudoNode.length === 0) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const paramString = pseudoNode.map((node) => String(node)).join(',');
|
|
58
|
+
const nextCharIsSpace = paramString.startsWith(' ');
|
|
59
|
+
const openIndex = pseudoNode.sourceIndex + pseudoNode.value.length + 1;
|
|
60
|
+
|
|
61
|
+
if (nextCharIsSpace && primary === 'never') {
|
|
62
|
+
report({
|
|
63
|
+
message: messages.rejectedOpening,
|
|
64
|
+
index: openIndex,
|
|
65
|
+
endIndex: openIndex,
|
|
66
|
+
result,
|
|
67
|
+
ruleName,
|
|
68
|
+
node: ruleNode,
|
|
69
|
+
fix: () => {
|
|
70
|
+
hasFixed = true;
|
|
71
|
+
setFirstNodeSpaceBefore(pseudoNode, '');
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!nextCharIsSpace && primary === 'always') {
|
|
77
|
+
report({
|
|
78
|
+
message: messages.expectedOpening,
|
|
79
|
+
index: openIndex,
|
|
80
|
+
endIndex: openIndex,
|
|
81
|
+
result,
|
|
82
|
+
ruleName,
|
|
83
|
+
node: ruleNode,
|
|
84
|
+
fix: () => {
|
|
85
|
+
hasFixed = true;
|
|
86
|
+
setFirstNodeSpaceBefore(pseudoNode, ' ');
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const previousCharIsSpace = paramString.endsWith(' ');
|
|
92
|
+
const closeIndex = openIndex + paramString.length - 1;
|
|
93
|
+
|
|
94
|
+
if (previousCharIsSpace && primary === 'never') {
|
|
95
|
+
report({
|
|
96
|
+
message: messages.rejectedClosing,
|
|
97
|
+
index: closeIndex,
|
|
98
|
+
endIndex: closeIndex,
|
|
99
|
+
result,
|
|
100
|
+
ruleName,
|
|
101
|
+
node: ruleNode,
|
|
102
|
+
fix: () => {
|
|
103
|
+
hasFixed = true;
|
|
104
|
+
setLastNodeSpaceAfter(pseudoNode, '');
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (!previousCharIsSpace && primary === 'always') {
|
|
110
|
+
report({
|
|
111
|
+
message: messages.expectedClosing,
|
|
112
|
+
index: closeIndex,
|
|
113
|
+
endIndex: closeIndex,
|
|
114
|
+
result,
|
|
115
|
+
ruleName,
|
|
116
|
+
node: ruleNode,
|
|
117
|
+
fix: () => {
|
|
118
|
+
hasFixed = true;
|
|
119
|
+
setLastNodeSpaceAfter(pseudoNode, ' ');
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
119
123
|
});
|
|
120
124
|
|
|
121
|
-
if (hasFixed
|
|
125
|
+
if (hasFixed) {
|
|
122
126
|
if (!ruleNode.raws.selector) {
|
|
123
|
-
ruleNode.selector =
|
|
127
|
+
ruleNode.selector = selectorTree.toString();
|
|
124
128
|
}
|
|
125
129
|
else {
|
|
126
|
-
ruleNode.raws.selector.raw =
|
|
130
|
+
ruleNode.raws.selector.raw = selectorTree.toString();
|
|
127
131
|
}
|
|
128
132
|
}
|
|
129
133
|
});
|
|
@@ -30,30 +30,34 @@ export default function selectorAttributeOperatorSpaceChecker (options) {
|
|
|
30
30
|
let hasFixed = false;
|
|
31
31
|
const selector = rule.raws.selector ? rule.raws.selector.raw : rule.selector;
|
|
32
32
|
|
|
33
|
-
const
|
|
34
|
-
selectorTree.walkAttributes((attributeNode) => {
|
|
35
|
-
const operator = attributeNode.operator;
|
|
33
|
+
const selectorTree = parseSelector(selector, options.result, rule);
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
if (!selectorTree) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
selectorTree.walkAttributes((attributeNode) => {
|
|
40
|
+
const operator = attributeNode.operator;
|
|
41
|
+
|
|
42
|
+
if (!operator) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
40
45
|
|
|
41
|
-
|
|
46
|
+
const attributeNodeString = attributeNode.toString();
|
|
42
47
|
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
styleSearch({ source: attributeNodeString, target: operator }, (match) => {
|
|
49
|
+
const index = options.checkBeforeOperator ? match.startIndex : match.endIndex - 1;
|
|
45
50
|
|
|
46
|
-
|
|
47
|
-
});
|
|
51
|
+
checkOperator(attributeNodeString, index, rule, attributeNode, operator);
|
|
48
52
|
});
|
|
49
53
|
});
|
|
50
54
|
|
|
51
|
-
if (hasFixed
|
|
55
|
+
if (hasFixed) {
|
|
52
56
|
if (!rule.raws.selector) {
|
|
53
|
-
rule.selector =
|
|
57
|
+
rule.selector = selectorTree.toString();
|
|
54
58
|
}
|
|
55
59
|
else {
|
|
56
|
-
rule.raws.selector.raw =
|
|
60
|
+
rule.raws.selector.raw = selectorTree.toString();
|
|
57
61
|
}
|
|
58
62
|
}
|
|
59
63
|
|
package/stylelint/plugins/stylelint-15.11.0-stylistic/rules/selectorCombinatorSpaceChecker.mjs
CHANGED
|
@@ -28,47 +28,51 @@ export default function selectorCombinatorSpaceChecker (options) {
|
|
|
28
28
|
hasFixed = false;
|
|
29
29
|
const selector = rule.raws.selector ? rule.raws.selector.raw : rule.selector;
|
|
30
30
|
|
|
31
|
-
const
|
|
32
|
-
selectorTree.walkCombinators((node) => {
|
|
33
|
-
// Ignore non-standard combinators
|
|
34
|
-
if (!isStandardSyntaxCombinator(node)) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
31
|
+
const selectorTree = parseSelector(selector, options.result, rule);
|
|
37
32
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
33
|
+
if (!selectorTree) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
selectorTree.walkCombinators((node) => {
|
|
38
|
+
// Ignore non-standard combinators
|
|
39
|
+
if (!isStandardSyntaxCombinator(node)) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
// Ignore spaced descendant combinator
|
|
44
|
+
if ((/\s/u).test(node.value)) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Check the exist of node in prev of the combinator.
|
|
49
|
+
// in case some that aren't the first begin with combinators (nesting syntax)
|
|
50
|
+
if (options.locationType === 'before' && !node.prev()) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
48
53
|
|
|
49
|
-
|
|
54
|
+
const parentParentNode = node.parent?.parent;
|
|
50
55
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
// Ignore pseudo-classes selector like `.foo:nth-child(2n + 1) {}`
|
|
57
|
+
if (parentParentNode && parentParentNode.type === 'pseudo') {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
55
60
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
const sourceIndex = node.sourceIndex;
|
|
62
|
+
const index =
|
|
63
|
+
node.value.length > 1 && options.locationType === 'before' ?
|
|
64
|
+
sourceIndex
|
|
65
|
+
: sourceIndex + node.value.length - 1;
|
|
61
66
|
|
|
62
|
-
|
|
63
|
-
});
|
|
67
|
+
check(selector, node, index, rule, sourceIndex);
|
|
64
68
|
});
|
|
65
69
|
|
|
66
|
-
if (hasFixed
|
|
70
|
+
if (hasFixed) {
|
|
67
71
|
if (!rule.raws.selector) {
|
|
68
|
-
rule.selector =
|
|
72
|
+
rule.selector = selectorTree.toString();
|
|
69
73
|
}
|
|
70
74
|
else {
|
|
71
|
-
rule.raws.selector.raw =
|
|
75
|
+
rule.raws.selector.raw = selectorTree.toString();
|
|
72
76
|
}
|
|
73
77
|
}
|
|
74
78
|
});
|
|
@@ -86,7 +86,9 @@ const rule = (primary, secondaryOptions) => {
|
|
|
86
86
|
/** @type {number[]} */
|
|
87
87
|
const fixPositions = [];
|
|
88
88
|
|
|
89
|
-
parseSelector(ruleNode.selector, result, ruleNode
|
|
89
|
+
const selectorTree = parseSelector(ruleNode.selector, result, ruleNode);
|
|
90
|
+
|
|
91
|
+
if (selectorTree) {
|
|
90
92
|
let selectorFixed = false;
|
|
91
93
|
|
|
92
94
|
selectorTree.walkAttributes((attributeNode) => {
|
|
@@ -165,7 +167,7 @@ const rule = (primary, secondaryOptions) => {
|
|
|
165
167
|
if (selectorFixed) {
|
|
166
168
|
ruleNode.selector = selectorTree.toString();
|
|
167
169
|
}
|
|
168
|
-
}
|
|
170
|
+
}
|
|
169
171
|
|
|
170
172
|
for (const fixIndex of fixPositions) {
|
|
171
173
|
ruleNode.selector = replaceQuote(ruleNode.selector, fixIndex, correctQuote);
|
|
@@ -188,10 +188,11 @@ function rule (primaryOption, secondaryOptions = {}) {
|
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
for (const selector of ruleNode.selectors) {
|
|
191
|
-
|
|
192
|
-
|
|
191
|
+
const container = parseSelector(selector, result, ruleNode);
|
|
192
|
+
|
|
193
|
+
if (container) {
|
|
193
194
|
checkSelectorRoot(container, ruleNode);
|
|
194
|
-
}
|
|
195
|
+
}
|
|
195
196
|
}
|
|
196
197
|
});
|
|
197
198
|
};
|