From bfe1678d82a7475cf973008f929d110ade6edf15 Mon Sep 17 00:00:00 2001 From: Matthew Manuel Date: Sat, 10 Sep 2022 13:53:12 +1000 Subject: [PATCH 1/8] Add ignore inside-block and iterateThroughSelectorList option to selector-disallowed-list --- lib/rules/selector-disallowed-list/README.md | 55 ++++++++++++++ .../__tests__/index.js | 60 +++++++++++++++ lib/rules/selector-disallowed-list/index.js | 73 ++++++++++++++----- 3 files changed, 170 insertions(+), 18 deletions(-) diff --git a/lib/rules/selector-disallowed-list/README.md b/lib/rules/selector-disallowed-list/README.md index ba430d5060..07ec3d335e 100644 --- a/lib/rules/selector-disallowed-list/README.md +++ b/lib/rules/selector-disallowed-list/README.md @@ -66,3 +66,58 @@ a ```css a[href] {} ``` + +## Optional secondary options + +### `iterateThroughSelectorList: true | false` (default: `false`) + +This option will apply your configuration to each individual selector in a selector list where each selector is seperated by a comma separated value. ',' + +For example, with 'true'. + +Given the string: + +```json +.foo +``` + +The following patterns are considered problems: + + +```css +.bar, .foo { } +``` + +The following patterns are _not_ considered problems: + + +```css +.bar .foo { } + +### `ignore: ["inside-block"]` + +Excludes any selectors that are inside a block. Use this if you only want to target selectors at the root level. + +Given the string: + +```json +.foo +``` + +The following patterns are considered problems: + + +```css +.foo { } +``` + +The following patterns are _not_ considered problems: + + +```css +.bar { + .foo { + + } +} +``` diff --git a/lib/rules/selector-disallowed-list/__tests__/index.js b/lib/rules/selector-disallowed-list/__tests__/index.js index 1987ef7f82..9a4900e7e5 100644 --- a/lib/rules/selector-disallowed-list/__tests__/index.js +++ b/lib/rules/selector-disallowed-list/__tests__/index.js @@ -66,6 +66,66 @@ testRule({ ], }); +testRule({ + ruleName, + config: [ + /^\.(foo)[,\s]?(?!\w).*$/, + { ignore: ['inside-block'], iterateThroughSelectorList: true }, + ], + accept: [ + { + code: 'a.foo{}', + }, + { + code: 'a\n>\n.foo {}', + }, + { + code: '.bar > a > .foo {}', + }, + { + code: '.bar { .foo {} }', + }, + { + code: '.fooo {}', + }, + ], + + reject: [ + { + code: '.foo {}', + message: messages.rejected('.foo'), + line: 1, + column: 1, + endLine: 1, + endColumn: 5, + }, + { + code: '.foo > .bar {}', + message: messages.rejected('.foo > .bar'), + line: 1, + column: 1, + endLine: 1, + endColumn: 12, + }, + { + code: '.foo, .bar {}', + message: messages.rejected('.foo'), + line: 1, + column: 1, + endLine: 1, + endColumn: 5, + }, + { + code: '.bar, .foo {}', + message: messages.rejected('.foo'), + line: 1, + column: 7, + endColumn: 11, + endLine: 1, + }, + ], +}); + testRule({ ruleName, config: /\.foo[^>]*>.*\.bar/, diff --git a/lib/rules/selector-disallowed-list/index.js b/lib/rules/selector-disallowed-list/index.js index 74981ba922..7091bda238 100644 --- a/lib/rules/selector-disallowed-list/index.js +++ b/lib/rules/selector-disallowed-list/index.js @@ -3,9 +3,10 @@ const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); const report = require('../../utils/report'); +const optionsMatches = require('../../utils/optionsMatches'); const ruleMessages = require('../../utils/ruleMessages'); const validateOptions = require('../../utils/validateOptions'); -const { isRegExp, isString } = require('../../utils/validateTypes'); +const { isRegExp, isString, isBoolean } = require('../../utils/validateTypes'); const ruleName = 'selector-disallowed-list'; @@ -17,13 +18,25 @@ const meta = { url: 'https://stylelint.io/user-guide/rules/list/selector-disallowed-list', }; -/** @type {import('stylelint').Rule>} */ -const rule = (primary) => { +/** @type {import('stylelint').Rule, { iterateThroughSelectorList: boolean, ignore: string[] }>} */ +const rule = (primary, secondaryOptions) => { return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: [isString, isRegExp], - }); + const validOptions = validateOptions( + result, + ruleName, + { + actual: primary, + possible: [isString, isRegExp], + }, + { + actual: secondaryOptions, + possible: { + ignore: ['inside-block'], + iterateThroughSelectorList: [isBoolean], + }, + optional: true, + }, + ); if (!validOptions) { return; @@ -34,21 +47,45 @@ const rule = (primary) => { return; } - const { selector, raws } = ruleNode; + if (optionsMatches(secondaryOptions, 'ignore', 'inside-block')) { + const { parent } = ruleNode; + const isInsideBlock = parent && parent.type !== 'root'; - if (!matchesStringOrRegExp(selector, primary)) { - return; + if (isInsideBlock) { + return; + } } - const word = (raws.selector && raws.selector.raw) || selector; + const iterateThroughSelectorList = + secondaryOptions && secondaryOptions.iterateThroughSelectorList; + + if (iterateThroughSelectorList) { + ruleNode.selectors.forEach((selector) => { + if (matchesStringOrRegExp(selector, primary)) { + report({ + result, + ruleName, + message: messages.rejected(selector), + node: ruleNode, + word: selector, + }); + } + }); + } else { + const { selector, raws } = ruleNode; - report({ - result, - ruleName, - message: messages.rejected(selector), - node: ruleNode, - word, - }); + if (matchesStringOrRegExp(selector, primary)) { + const word = (raws.selector && raws.selector.raw) || selector; + + report({ + result, + ruleName, + message: messages.rejected(selector), + node: ruleNode, + word, + }); + } + } }); }; }; From fff98a8eea40961241743bef6a95ca7e211894f8 Mon Sep 17 00:00:00 2001 From: Matthew Manuel Date: Sat, 10 Sep 2022 19:28:31 +1000 Subject: [PATCH 2/8] Apply suggestions from code review Co-authored-by: Richard Hallows --- lib/rules/selector-disallowed-list/README.md | 35 +++++++------------ .../__tests__/index.js | 2 +- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/lib/rules/selector-disallowed-list/README.md b/lib/rules/selector-disallowed-list/README.md index 07ec3d335e..9fa5404a9c 100644 --- a/lib/rules/selector-disallowed-list/README.md +++ b/lib/rules/selector-disallowed-list/README.md @@ -71,53 +71,44 @@ a[href] {} ### `iterateThroughSelectorList: true | false` (default: `false`) -This option will apply your configuration to each individual selector in a selector list where each selector is seperated by a comma separated value. ',' +Iterate through each individual selector in a selector list. -For example, with 'true'. +For example, with `true`. -Given the string: +Given: ```json -.foo +[".foo"] ``` -The following patterns are considered problems: +The following pattern is considered a problem: ```css -.bar, .foo { } +.bar, .foo {} ``` -The following patterns are _not_ considered problems: +The following pattern is _not_ considered a problem: ```css -.bar .foo { } +.bar .foo {} ### `ignore: ["inside-block"]` -Excludes any selectors that are inside a block. Use this if you only want to target selectors at the root level. +Ignore selectors that are inside a block. -Given the string: +Given: ```json -.foo -``` - -The following patterns are considered problems: - - -```css -.foo { } +[".foo"] ``` -The following patterns are _not_ considered problems: +The following pattern is _not_ considered a problem: ```css .bar { - .foo { - - } + .foo {} } ``` diff --git a/lib/rules/selector-disallowed-list/__tests__/index.js b/lib/rules/selector-disallowed-list/__tests__/index.js index 9a4900e7e5..864226e438 100644 --- a/lib/rules/selector-disallowed-list/__tests__/index.js +++ b/lib/rules/selector-disallowed-list/__tests__/index.js @@ -74,7 +74,7 @@ testRule({ ], accept: [ { - code: 'a.foo{}', + code: 'a.foo {}', }, { code: 'a\n>\n.foo {}', From 22f14c88a04302d1b5842375a69b22bc5c902159 Mon Sep 17 00:00:00 2001 From: Matthew Manuel Date: Sat, 10 Sep 2022 20:10:20 +1000 Subject: [PATCH 3/8] Renamed iterateThroughSelectorList into iterateThroughList for conciseness in selector-disallowed-list --- lib/rules/selector-disallowed-list/README.md | 2 +- lib/rules/selector-disallowed-list/__tests__/index.js | 5 +---- lib/rules/selector-disallowed-list/index.js | 9 ++++----- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/rules/selector-disallowed-list/README.md b/lib/rules/selector-disallowed-list/README.md index 9fa5404a9c..e002906ba4 100644 --- a/lib/rules/selector-disallowed-list/README.md +++ b/lib/rules/selector-disallowed-list/README.md @@ -69,7 +69,7 @@ a[href] {} ## Optional secondary options -### `iterateThroughSelectorList: true | false` (default: `false`) +### `iterateThroughList: true | false` (default: `false`) Iterate through each individual selector in a selector list. diff --git a/lib/rules/selector-disallowed-list/__tests__/index.js b/lib/rules/selector-disallowed-list/__tests__/index.js index 864226e438..c96354c3c4 100644 --- a/lib/rules/selector-disallowed-list/__tests__/index.js +++ b/lib/rules/selector-disallowed-list/__tests__/index.js @@ -68,10 +68,7 @@ testRule({ testRule({ ruleName, - config: [ - /^\.(foo)[,\s]?(?!\w).*$/, - { ignore: ['inside-block'], iterateThroughSelectorList: true }, - ], + config: [/^\.(foo)[,\s]?(?!\w).*$/, { ignore: ['inside-block'], iterateThroughList: true }], accept: [ { code: 'a.foo {}', diff --git a/lib/rules/selector-disallowed-list/index.js b/lib/rules/selector-disallowed-list/index.js index 7091bda238..e4cd10c716 100644 --- a/lib/rules/selector-disallowed-list/index.js +++ b/lib/rules/selector-disallowed-list/index.js @@ -18,7 +18,7 @@ const meta = { url: 'https://stylelint.io/user-guide/rules/list/selector-disallowed-list', }; -/** @type {import('stylelint').Rule, { iterateThroughSelectorList: boolean, ignore: string[] }>} */ +/** @type {import('stylelint').Rule, { iterateThroughList: boolean, ignore: string[] }>} */ const rule = (primary, secondaryOptions) => { return (root, result) => { const validOptions = validateOptions( @@ -32,7 +32,7 @@ const rule = (primary, secondaryOptions) => { actual: secondaryOptions, possible: { ignore: ['inside-block'], - iterateThroughSelectorList: [isBoolean], + iterateThroughList: [isBoolean], }, optional: true, }, @@ -56,10 +56,9 @@ const rule = (primary, secondaryOptions) => { } } - const iterateThroughSelectorList = - secondaryOptions && secondaryOptions.iterateThroughSelectorList; + const iterateThroughList = secondaryOptions && secondaryOptions.iterateThroughList; - if (iterateThroughSelectorList) { + if (iterateThroughList) { ruleNode.selectors.forEach((selector) => { if (matchesStringOrRegExp(selector, primary)) { report({ From a258701f06b8fd1605c3d138911392f900356609 Mon Sep 17 00:00:00 2001 From: Richard Hallows Date: Mon, 12 Sep 2022 11:19:50 +0100 Subject: [PATCH 4/8] Create unlucky-dolphins-fetch.md --- .changeset/unlucky-dolphins-fetch.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/unlucky-dolphins-fetch.md diff --git a/.changeset/unlucky-dolphins-fetch.md b/.changeset/unlucky-dolphins-fetch.md new file mode 100644 index 0000000000..b21872e6de --- /dev/null +++ b/.changeset/unlucky-dolphins-fetch.md @@ -0,0 +1,5 @@ +--- +"stylelint": minor +--- + +Added: `ignore: ["inside-block"]` and `splitList` to `selector-disallowed-list` From c6c2af275d5d71e6eaaf0d77be14894c8add79d0 Mon Sep 17 00:00:00 2001 From: Matthew Manuel Date: Tue, 13 Sep 2022 09:44:22 +1000 Subject: [PATCH 5/8] Rename option from iterateThroughList to splitList. Refactored some code and fixed typo --- lib/rules/selector-disallowed-list/README.md | 4 ++-- .../selector-disallowed-list/__tests__/index.js | 2 +- lib/rules/selector-disallowed-list/index.js | 13 +++++++------ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/rules/selector-disallowed-list/README.md b/lib/rules/selector-disallowed-list/README.md index e002906ba4..62fd7118ce 100644 --- a/lib/rules/selector-disallowed-list/README.md +++ b/lib/rules/selector-disallowed-list/README.md @@ -69,7 +69,7 @@ a[href] {} ## Optional secondary options -### `iterateThroughList: true | false` (default: `false`) +### `splitList: true | false` (default: `false`) Iterate through each individual selector in a selector list. @@ -94,7 +94,7 @@ The following pattern is _not_ considered a problem: ```css .bar .foo {} -### `ignore: ["inside-block"]` +### `ignore: ["inside-block"]` Ignore selectors that are inside a block. diff --git a/lib/rules/selector-disallowed-list/__tests__/index.js b/lib/rules/selector-disallowed-list/__tests__/index.js index c96354c3c4..3668436749 100644 --- a/lib/rules/selector-disallowed-list/__tests__/index.js +++ b/lib/rules/selector-disallowed-list/__tests__/index.js @@ -68,7 +68,7 @@ testRule({ testRule({ ruleName, - config: [/^\.(foo)[,\s]?(?!\w).*$/, { ignore: ['inside-block'], iterateThroughList: true }], + config: [/^\.(foo)[,\s]?(?!\w).*$/, { ignore: ['inside-block'], splitList: true }], accept: [ { code: 'a.foo {}', diff --git a/lib/rules/selector-disallowed-list/index.js b/lib/rules/selector-disallowed-list/index.js index e4cd10c716..66ae43acc6 100644 --- a/lib/rules/selector-disallowed-list/index.js +++ b/lib/rules/selector-disallowed-list/index.js @@ -18,7 +18,7 @@ const meta = { url: 'https://stylelint.io/user-guide/rules/list/selector-disallowed-list', }; -/** @type {import('stylelint').Rule, { iterateThroughList: boolean, ignore: string[] }>} */ +/** @type {import('stylelint').Rule, { splitList: boolean, ignore: string[] }>} */ const rule = (primary, secondaryOptions) => { return (root, result) => { const validOptions = validateOptions( @@ -32,7 +32,7 @@ const rule = (primary, secondaryOptions) => { actual: secondaryOptions, possible: { ignore: ['inside-block'], - iterateThroughList: [isBoolean], + splitList: [isBoolean], }, optional: true, }, @@ -42,12 +42,15 @@ const rule = (primary, secondaryOptions) => { return; } + const ignoreInsideBlock = optionsMatches(secondaryOptions, 'ignore', 'inside-block'); + const splitList = secondaryOptions && secondaryOptions.splitList; + root.walkRules((ruleNode) => { if (!isStandardSyntaxRule(ruleNode)) { return; } - if (optionsMatches(secondaryOptions, 'ignore', 'inside-block')) { + if (ignoreInsideBlock) { const { parent } = ruleNode; const isInsideBlock = parent && parent.type !== 'root'; @@ -56,9 +59,7 @@ const rule = (primary, secondaryOptions) => { } } - const iterateThroughList = secondaryOptions && secondaryOptions.iterateThroughList; - - if (iterateThroughList) { + if (splitList) { ruleNode.selectors.forEach((selector) => { if (matchesStringOrRegExp(selector, primary)) { report({ From 51bc1835231f169f879c341da1d2157c7c5e5e42 Mon Sep 17 00:00:00 2001 From: Matthew Manuel Date: Tue, 13 Sep 2022 10:14:43 +1000 Subject: [PATCH 6/8] Update lib/rules/selector-disallowed-list/README.md Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com> --- lib/rules/selector-disallowed-list/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/rules/selector-disallowed-list/README.md b/lib/rules/selector-disallowed-list/README.md index 62fd7118ce..8942a27d68 100644 --- a/lib/rules/selector-disallowed-list/README.md +++ b/lib/rules/selector-disallowed-list/README.md @@ -93,6 +93,7 @@ The following pattern is _not_ considered a problem: ```css .bar .foo {} +``` ### `ignore: ["inside-block"]` From 4ac02572bcd92ccaa3aa0d82f86a1933d0979e1b Mon Sep 17 00:00:00 2001 From: Matthew Manuel Date: Tue, 13 Sep 2022 15:36:34 +1000 Subject: [PATCH 7/8] Ran npm run format and applied changes to README.md --- lib/rules/selector-disallowed-list/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rules/selector-disallowed-list/README.md b/lib/rules/selector-disallowed-list/README.md index 8942a27d68..afb25760bd 100644 --- a/lib/rules/selector-disallowed-list/README.md +++ b/lib/rules/selector-disallowed-list/README.md @@ -97,7 +97,7 @@ The following pattern is _not_ considered a problem: ### `ignore: ["inside-block"]` -Ignore selectors that are inside a block. +Ignore selectors that are inside a block. Given: From c78c7643684eb79b6ed80ab3f666b8090032eaf2 Mon Sep 17 00:00:00 2001 From: Richard Hallows Date: Tue, 13 Sep 2022 11:28:00 +0100 Subject: [PATCH 8/8] Update lib/rules/selector-disallowed-list/README.md --- lib/rules/selector-disallowed-list/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rules/selector-disallowed-list/README.md b/lib/rules/selector-disallowed-list/README.md index afb25760bd..4cf479abd9 100644 --- a/lib/rules/selector-disallowed-list/README.md +++ b/lib/rules/selector-disallowed-list/README.md @@ -71,7 +71,7 @@ a[href] {} ### `splitList: true | false` (default: `false`) -Iterate through each individual selector in a selector list. +Split selector lists into individual selectors. For example, with `true`.