linter-bundle 7.9.0 → 7.10.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
CHANGED
|
@@ -6,7 +6,16 @@ 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.10.0...HEAD)
|
|
10
|
+
|
|
11
|
+
## [7.10.0] - 2025-11-19
|
|
12
|
+
|
|
13
|
+
- [eslint] Updated `@stylistic/eslint-plugin` from `5.6.0` to `5.6.1`
|
|
14
|
+
- [markdown] Updated `markdownlint-cli` from `0.45.0` to `0.46.0``
|
|
15
|
+
- [markdown] Added but disabled [`MD060 - Table column style`](https://github.com/DavidAnson/markdownlint/blob/main/doc/md060.md) rule
|
|
16
|
+
- [stylelint] Added configurable `allowCombinators` option to the `plugin/selector-tag-no-without-class` rule and enabled `>`, `+`, `~` combinators for CSS Modules to avoid false positives
|
|
17
|
+
|
|
18
|
+
[Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v7.9.0...v7.10.0)
|
|
10
19
|
|
|
11
20
|
## [7.9.0] - 2025-11-18
|
|
12
21
|
|
|
@@ -52,6 +61,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
|
52
61
|
- [stylelint] Ignore property casing for `composes` in `value-keyword-case`rule
|
|
53
62
|
- [stylelint] Add `composes` to the ignored property list of the `scss/property-no-unknown` rule
|
|
54
63
|
|
|
64
|
+
[Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v7.8.0...v7.9.0)
|
|
65
|
+
|
|
55
66
|
## [7.8.0] - 2025-08-21
|
|
56
67
|
|
|
57
68
|
### Changed
|
|
@@ -1657,7 +1668,7 @@ Beside these changes:
|
|
|
1657
1668
|
### Changed
|
|
1658
1669
|
|
|
1659
1670
|
- [eslint] Updated `@typescript-eslint` from v4.24.0 to v4.25.0
|
|
1660
|
-
- [eslint] Updated `eslint-plugin-jsdoc` from v34.8.2 to v35.0.0
|
|
1671
|
+
- [eslint] Updated `eslint-plugin-jsdoc` from v34.8.2 to v35.0.0
|
|
1661
1672
|
- [eslint] Activated `ignoreNonDOM` option for [`jsx-a11y/no-autofocus`](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/no-autofocus.md) rule
|
|
1662
1673
|
|
|
1663
1674
|
[Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v1.20.0...v1.21.0)
|
package/markdownlint/base.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "linter-bundle",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Ready-to use bundle of linting tools, containing configurations for ESLint, stylelint and markdownlint.",
|
|
6
6
|
"keywords": [
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"_test-stylelint": "node ./test-stylelint.js"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@stylistic/eslint-plugin": "5.6.
|
|
45
|
+
"@stylistic/eslint-plugin": "5.6.1",
|
|
46
46
|
"eslint": "9.39.1",
|
|
47
47
|
"eslint-formatter-unix": "9.0.1",
|
|
48
48
|
"eslint-import-resolver-typescript": "4.4.4",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"eslint-plugin-react-hooks": "7.0.1",
|
|
60
60
|
"eslint-plugin-unicorn": "62.0.0",
|
|
61
61
|
"globals": "16.5.0",
|
|
62
|
-
"markdownlint-cli": "0.
|
|
62
|
+
"markdownlint-cli": "0.46.0",
|
|
63
63
|
"micromatch": "4.0.8",
|
|
64
64
|
"postcss-scss": "4.0.9",
|
|
65
65
|
"stylelint": "16.25.0",
|
|
@@ -81,11 +81,5 @@
|
|
|
81
81
|
"@types/node": "24.10.1",
|
|
82
82
|
"stylelint-find-new-rules": "5.0.0",
|
|
83
83
|
"typescript": "5.9.3"
|
|
84
|
-
},
|
|
85
|
-
"overrides": {
|
|
86
|
-
"glob": "12.0.0"
|
|
87
|
-
},
|
|
88
|
-
"resolutions": {
|
|
89
|
-
"glob": "12.0.0"
|
|
90
84
|
}
|
|
91
85
|
}
|
package/stylelint/index.mjs
CHANGED
|
@@ -130,7 +130,7 @@ export default {
|
|
|
130
130
|
*
|
|
131
131
|
* @see https://github.com/Moxio/stylelint-selector-tag-no-without-class
|
|
132
132
|
*/
|
|
133
|
-
'plugin/selector-tag-no-without-class': ['/./']
|
|
133
|
+
'plugin/selector-tag-no-without-class': [['/./'], { allowCombinators: ['>', '+', '~'] }]
|
|
134
134
|
}
|
|
135
135
|
},
|
|
136
136
|
{
|
|
@@ -22,26 +22,121 @@ const messages = stylelint.utils.ruleMessages(ruleName, {
|
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
// @ts-expect-error -- Parameter 'primaryOption' implicitly has an 'any' type.
|
|
25
|
-
function rule (primaryOption) {
|
|
25
|
+
function rule (primaryOption, secondaryOptions = {}) {
|
|
26
26
|
// @ts-expect-error -- Parameter 'root' implicitly has an 'any' type. / Parameter 'result' implicitly has an 'any' type.
|
|
27
27
|
return (root, result) => {
|
|
28
|
-
const validOptions = stylelint.utils.validateOptions(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
const validOptions = stylelint.utils.validateOptions(
|
|
29
|
+
result,
|
|
30
|
+
ruleName,
|
|
31
|
+
{
|
|
32
|
+
actual: primaryOption,
|
|
33
|
+
possible: [(string) => (typeof string === 'string' || Object.prototype.toString.call(string) === '[object String]')]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
actual: secondaryOptions,
|
|
37
|
+
possible: {
|
|
38
|
+
allowCombinators: [' ', '+', '>', '~', '||']
|
|
39
|
+
},
|
|
40
|
+
optional: true
|
|
41
|
+
}
|
|
42
|
+
);
|
|
32
43
|
|
|
33
44
|
if (!validOptions) {
|
|
34
45
|
return;
|
|
35
46
|
}
|
|
36
47
|
|
|
48
|
+
/** @type {{ allowCombinators?: string | string[] }} */
|
|
49
|
+
const typedSecondaryOptions = secondaryOptions;
|
|
50
|
+
const allowCombinatorsOption = typedSecondaryOptions.allowCombinators;
|
|
51
|
+
const allowCombinatorValues = allowCombinatorsOption === undefined ? [] : (Array.isArray(allowCombinatorsOption) ? allowCombinatorsOption : [allowCombinatorsOption]);
|
|
52
|
+
/** @type {string[]} */
|
|
53
|
+
const normalizedAllowedCombinators = [];
|
|
54
|
+
for (const combinator of allowCombinatorValues) {
|
|
55
|
+
if (combinator.length === 0) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
normalizedAllowedCombinators.push(normalizeCombinatorValue(combinator));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const allowedCombinators = new Set(normalizedAllowedCombinators);
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @param {string | undefined} value
|
|
66
|
+
* @returns {string}
|
|
67
|
+
*/
|
|
68
|
+
function normalizeCombinatorValue (value) {
|
|
69
|
+
if (typeof value !== 'string') {
|
|
70
|
+
return '';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return value.trim() === '' ? ' ' : value.trim();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @param {import('postcss-selector-parser').Selector} selectorNode
|
|
78
|
+
*/
|
|
79
|
+
function splitSelectorIntoSegments (selectorNode) {
|
|
80
|
+
/** @type {{ nodes: import('postcss-selector-parser').Node[], leadingCombinator?: string }[]} */
|
|
81
|
+
const segments = [];
|
|
82
|
+
/** @type {import('postcss-selector-parser').Node[]} */
|
|
83
|
+
let currentSegment = [];
|
|
84
|
+
/** @type {string | undefined} */
|
|
85
|
+
let leadingCombinator;
|
|
86
|
+
|
|
87
|
+
function pushCurrentSegment () {
|
|
88
|
+
if (currentSegment.length === 0) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const segmentNodes = currentSegment;
|
|
93
|
+
currentSegment = [];
|
|
94
|
+
|
|
95
|
+
/** @type {{ nodes: import('postcss-selector-parser').Node[], leadingCombinator?: string }} */
|
|
96
|
+
const segment = { nodes: segmentNodes };
|
|
97
|
+
|
|
98
|
+
if (leadingCombinator !== undefined) {
|
|
99
|
+
segment.leadingCombinator = leadingCombinator;
|
|
100
|
+
leadingCombinator = undefined;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
segments.push(segment);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
selectorNode.each((/** @type {import('postcss-selector-parser').Node} */ child) => {
|
|
107
|
+
if (child.type === 'combinator') {
|
|
108
|
+
pushCurrentSegment();
|
|
109
|
+
leadingCombinator = normalizeCombinatorValue(child.value);
|
|
110
|
+
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
currentSegment.push(child);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
pushCurrentSegment();
|
|
118
|
+
|
|
119
|
+
return segments;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @param {string | undefined} leadingCombinator
|
|
124
|
+
*/
|
|
125
|
+
function shouldIgnoreSegment (leadingCombinator) {
|
|
126
|
+
if (!leadingCombinator || allowedCombinators.size === 0) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return allowedCombinators.has(leadingCombinator);
|
|
131
|
+
}
|
|
132
|
+
|
|
37
133
|
// @ts-expect-error -- Parameter 'selectorNode' implicitly has an 'any' type. / Parameter 'ruleNode' implicitly has an 'any' type.
|
|
38
134
|
function checkSelector (selectorNode, ruleNode) {
|
|
39
|
-
|
|
40
|
-
const combinedSegments = selectorNode.split((node) => (node.type === 'combinator'));
|
|
135
|
+
const segments = splitSelectorIntoSegments(selectorNode);
|
|
41
136
|
|
|
42
|
-
for (const segment of
|
|
137
|
+
for (const segment of segments) {
|
|
43
138
|
let unqualifiedTagNode;
|
|
44
|
-
for (const node of segment) {
|
|
139
|
+
for (const node of segment.nodes) {
|
|
45
140
|
if (node.type === 'tag' && matchesStringOrRegExp(node.value, primaryOption)) {
|
|
46
141
|
unqualifiedTagNode = node;
|
|
47
142
|
}
|
|
@@ -50,13 +145,13 @@ function rule (primaryOption) {
|
|
|
50
145
|
}
|
|
51
146
|
}
|
|
52
147
|
|
|
53
|
-
if (unqualifiedTagNode) {
|
|
148
|
+
if (unqualifiedTagNode && !shouldIgnoreSegment(segment.leadingCombinator)) {
|
|
54
149
|
stylelint.utils.report({
|
|
55
150
|
ruleName,
|
|
56
151
|
result,
|
|
57
152
|
node: ruleNode,
|
|
58
153
|
message: messages.unexpected(unqualifiedTagNode.value),
|
|
59
|
-
word: unqualifiedTagNode
|
|
154
|
+
word: unqualifiedTagNode.value
|
|
60
155
|
});
|
|
61
156
|
}
|
|
62
157
|
}
|