diff --git a/CHANGELOG.md b/CHANGELOG.md index d23b45d630..0234ea34d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ All notable changes to this project are documented in this file. - Added: disable comments that are reported as errors for various reasons are now reported as standard lint errors rather than a separate class of errors that must be handled specially. - Deprecated: `StylelintStandaloneReturnValue.reportedDisables`, `.descriptionlessDisables`, `.needlessDisables`, and `.invalidScopeDisables`. `.reportedDisables` will always be empty and the other properties will always be undefined, since these errors now show up in `.results` instead. + +## 13.7.2 + +- Fixed: regression for disable commands and adjacent double-slash comments ([#4950](https://github.com/stylelint/stylelint/pull/4950)). - Fixed: use of full file path without converting it to glob ([#4931](https://github.com/stylelint/stylelint/pull/4931)). ## 13.7.1 diff --git a/docs/user-guide/configure.md b/docs/user-guide/configure.md index 4811b02908..b3455dbe08 100644 --- a/docs/user-guide/configure.md +++ b/docs/user-guide/configure.md @@ -137,7 +137,7 @@ Reporters may use these severity levels to display violations or exit the proces ### `reportDisables` -You can set the `reportDisables` secondary option to report any disable comments for this rule, effectively disallowing authors to opt out of it. +You can set the `reportDisables` secondary option to report any `stylelint-disable` comments for this rule, effectively disallowing authors to opt out of it. For example: @@ -155,6 +155,8 @@ For example: } ``` +The report is included in the [`reportedDisables`](usage/node-api.md#reporteddisables) property to the returned data of Node.js API. + ## `defaultSeverity` You can set the default severity level for all rules that do not have a severity specified in their secondary options. For example, you can set the default severity to `"warning"`: diff --git a/docs/user-guide/rules/list.md b/docs/user-guide/rules/list.md index 9c4f023149..06b93637b8 100644 --- a/docs/user-guide/rules/list.md +++ b/docs/user-guide/rules/list.md @@ -209,6 +209,7 @@ Grouped first by the following categories and then by the [_thing_](http://apps. - [`media-feature-name-disallowed-list`](../../../lib/rules/media-feature-name-disallowed-list/README.md): Specify a list of disallowed media feature names. - [`media-feature-name-no-vendor-prefix`](../../../lib/rules/media-feature-name-no-vendor-prefix/README.md): Disallow vendor prefixes for media feature names (Autofixable). - [`media-feature-name-value-allowed-list`](../../../lib/rules/media-feature-name-value-allowed-list/README.md): Specify a list of allowed media feature name and value pairs. +- [`media-feature-name-value-whitelist`](../../../lib/rules/media-feature-name-value-whitelist/README.md): Specify a list of allowed media feature name and value pairs. **(deprecated)** - [`media-feature-name-whitelist`](../../../lib/rules/media-feature-name-whitelist/README.md): Specify a list of allowed media feature names. **(deprecated)** ### Custom media diff --git a/docs/user-guide/usage/options.md b/docs/user-guide/usage/options.md index 5d9eae8a1e..e708b18a61 100644 --- a/docs/user-guide/usage/options.md +++ b/docs/user-guide/usage/options.md @@ -141,7 +141,7 @@ You can use this option to see what your linting results would be like without t CLI flags: `--report-needless-disables, --rd` -Produce a report to clean up your codebase, keeping only the stylelint-disable comments that serve a purpose. +Produce a report to clean up your codebase, keeping only the `stylelint-disable` comments that serve a purpose. If needless disables are found, the: @@ -152,13 +152,52 @@ If needless disables are found, the: CLI flags: `--report-invalid-scope-disables, --risd` -Produce a report of the stylelint-disable comments that used for rules that don't exist within the configuration object. +Produce a report of the `stylelint-disable` comments that used for rules that don't exist within the configuration object. If invalid scope disables are found, the: - CLI process exits with code `2` - Node.js API adds errors to the returned data +## `reportDescriptionlessDisables` + +CLI flags: `--report-descriptionless-disables, --rdd` + +Produce a report of the `stylelint-disable` comments without a description. + +For example, when the configuration `{ block-no-empty: true }` is given, the following patterns are reported: + + +```css +/* stylelint-disable */ +a {} +``` + + +```css +/* stylelint-disable-next-line block-no-empty */ +a {} +``` + +But, the following patterns (`stylelint-disable -- `) are _not_ reported: + + +```css +/* stylelint-disable -- This violation is ignorable. */ +a {} +``` + + +```css +/* stylelint-disable-next-line block-no-empty -- This violation is ignorable. */ +a {} +``` + +If descriptionless disables are found, the: + +- CLI process exits with code `2` +- Node.js API adds a [`descriptionlessDisables`](node-api.md#descriptionlessdisables) property to the returned data + ## `codeFilename` CLI flag: `--stdin-filename` diff --git a/lib/__tests__/disableRanges.test.js b/lib/__tests__/disableRanges.test.js index e5bfaf36a8..2d40f8fa39 100644 --- a/lib/__tests__/disableRanges.test.js +++ b/lib/__tests__/disableRanges.test.js @@ -794,6 +794,29 @@ it('SCSS // disable comment (with // comment after blank line)', () => { }); }); +it('SCSS // disable comment (with // comment immediately after)', () => { + const scssSource = `a { + // stylelint-disable declaration-no-important + // Unrelated + color: pink !important; + }`; + + return postcss() + .use(assignDisabledRanges) + .process(scssSource, { syntax: scss, from: undefined }) + .then((result) => { + expect(result.stylelint.disabledRanges).toEqual({ + all: [], + 'declaration-no-important': [ + { + start: 2, + strictStart: true, + }, + ], + }); + }); +}); + it('SCSS /* disable comment (with // comment after blank line)', () => { const scssSource = `a { /* stylelint-disable declaration-no-important */ @@ -818,6 +841,122 @@ it('SCSS /* disable comment (with // comment after blank line)', () => { }); }); +it('SCSS // disable comment (with // comment immediately before)', () => { + const scssSource = `a { + // Unrelated + // stylelint-disable declaration-no-important + color: pink !important; + }`; + + return postcss() + .use(assignDisabledRanges) + .process(scssSource, { syntax: scss, from: undefined }) + .then((result) => { + expect(result.stylelint.disabledRanges).toEqual({ + all: [], + 'declaration-no-important': [ + { + start: 3, + strictStart: true, + }, + ], + }); + }); +}); + +it('SCSS two adjacent // disable comments ', () => { + const scssSource = `a { + // stylelint-disable declaration-no-important + // stylelint-disable foo-bar + color: pink !important; + }`; + + return postcss() + .use(assignDisabledRanges) + .process(scssSource, { syntax: scss, from: undefined }) + .then((result) => { + expect(result.stylelint.disabledRanges).toEqual({ + all: [], + 'declaration-no-important': [ + { + start: 2, + strictStart: true, + }, + ], + 'foo-bar': [ + { + start: 3, + strictStart: true, + }, + ], + }); + }); +}); + +it('SCSS two adjacent // disable comments with multi-line descriptions ', () => { + const scssSource = `a { + // stylelint-disable declaration-no-important -- + // Description 1 + // stylelint-disable foo-bar + // -- + // Description 2 + color: pink !important; + }`; + + return postcss() + .use(assignDisabledRanges) + .process(scssSource, { syntax: scss, from: undefined }) + .then((result) => { + expect(result.stylelint.disabledRanges).toEqual({ + all: [], + 'declaration-no-important': [ + { + start: 2, + strictStart: true, + description: 'Description 1', + }, + ], + 'foo-bar': [ + { + start: 4, + strictStart: true, + description: 'Description 2', + }, + ], + }); + }); +}); + +it('SCSS two // disable comments with an unrelated comment between them', () => { + const scssSource = `a { + // stylelint-disable declaration-no-important + // Unrelated + // stylelint-disable foo-bar + color: pink !important; + }`; + + return postcss() + .use(assignDisabledRanges) + .process(scssSource, { syntax: scss, from: undefined }) + .then((result) => { + expect(result.stylelint.disabledRanges).toEqual({ + all: [], + 'declaration-no-important': [ + { + start: 2, + strictStart: true, + }, + ], + 'foo-bar': [ + { + start: 4, + strictStart: true, + }, + ], + }); + }); +}); + it('Less // line-disabling comment (with description)', () => { const lessSource = `a { color: pink !important; // stylelint-disable-line declaration-no-important -- Description diff --git a/lib/assignDisabledRanges.js b/lib/assignDisabledRanges.js index 6c6db33b8d..5e2f23ef79 100644 --- a/lib/assignDisabledRanges.js +++ b/lib/assignDisabledRanges.js @@ -68,35 +68,53 @@ module.exports = function (root, result) { if (inlineEnd) { // Ignore comments already processed by grouping with a previous one. if (inlineEnd === comment) inlineEnd = null; - } else if (isInlineComment(comment)) { - const fullComment = comment.clone(); - let next = comment.next(); - let lastLine = (comment.source && comment.source.end && comment.source.end.line) || 0; - while (next && next.type === 'comment') { - /** @type {PostcssComment} */ - const current = next; + return; + } - if (!isInlineComment(current)) break; + const next = comment.next(); + + // If any of these conditions are not met, do not merge comments. + if ( + !( + isInlineComment(comment) && + isStylelintCommand(comment) && + next && + next.type === 'comment' && + (comment.text.includes('--') || next.text.startsWith('--')) + ) + ) { + checkComment(comment); - const currentLine = (current.source && current.source.end && current.source.end.line) || 0; + return; + } - if (lastLine + 1 !== currentLine) break; + let lastLine = (comment.source && comment.source.end && comment.source.end.line) || 0; + const fullComment = comment.clone(); - fullComment.text += `\n${current.text}`; + /** @type {PostcssComment} */ + let current = next; - if (fullComment.source && current.source) { - fullComment.source.end = current.source.end; - } + while (isInlineComment(current) && !isStylelintCommand(current)) { + const currentLine = (current.source && current.source.end && current.source.end.line) || 0; + + if (lastLine + 1 !== currentLine) break; - inlineEnd = current; - next = current.next(); - lastLine = currentLine; + fullComment.text += `\n${current.text}`; + + if (fullComment.source && current.source) { + fullComment.source.end = current.source.end; } - checkComment(fullComment); - } else { - checkComment(comment); + + inlineEnd = current; + const next = current.next(); + + if (!next || next.type !== 'comment') break; + + current = next; + lastLine = currentLine; } + checkComment(fullComment); }); return result; @@ -110,6 +128,13 @@ module.exports = function (root, result) { return comment.inline || comment.raws.inline; } + /** + * @param {PostcssComment} comment + */ + function isStylelintCommand(comment) { + return comment.text.startsWith(disableCommand) || comment.text.startsWith(enableCommand); + } + /** * @param {PostcssComment} comment */ diff --git a/lib/rules/at-rule-blacklist/__tests__/index.js b/lib/rules/at-rule-blacklist/__tests__/index.js index b7a1af7846..d0900a78a7 100644 --- a/lib/rules/at-rule-blacklist/__tests__/index.js +++ b/lib/rules/at-rule-blacklist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, diff --git a/lib/rules/at-rule-blacklist/index.js b/lib/rules/at-rule-blacklist/index.js index 3e056130e4..5f942de3ef 100644 --- a/lib/rules/at-rule-blacklist/index.js +++ b/lib/rules/at-rule-blacklist/index.js @@ -59,4 +59,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/at-rule-property-requirelist/__tests__/index.js b/lib/rules/at-rule-property-requirelist/__tests__/index.js index 183e7643b4..751f3ce403 100644 --- a/lib/rules/at-rule-property-requirelist/__tests__/index.js +++ b/lib/rules/at-rule-property-requirelist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, config: { diff --git a/lib/rules/at-rule-property-requirelist/index.js b/lib/rules/at-rule-property-requirelist/index.js index e979f78b41..fec1038679 100644 --- a/lib/rules/at-rule-property-requirelist/index.js +++ b/lib/rules/at-rule-property-requirelist/index.js @@ -69,5 +69,6 @@ function rule(list) { rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; module.exports = rule; diff --git a/lib/rules/at-rule-whitelist/__tests__/index.js b/lib/rules/at-rule-whitelist/__tests__/index.js index 74f79a3e8c..cf2ca77dea 100644 --- a/lib/rules/at-rule-whitelist/__tests__/index.js +++ b/lib/rules/at-rule-whitelist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, diff --git a/lib/rules/at-rule-whitelist/index.js b/lib/rules/at-rule-whitelist/index.js index 716ee578b7..ae28687154 100644 --- a/lib/rules/at-rule-whitelist/index.js +++ b/lib/rules/at-rule-whitelist/index.js @@ -59,4 +59,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/comment-word-blacklist/__tests__/index.js b/lib/rules/comment-word-blacklist/__tests__/index.js index 70a331716c..2e5a7288c1 100644 --- a/lib/rules/comment-word-blacklist/__tests__/index.js +++ b/lib/rules/comment-word-blacklist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, config: ['bad-word'], diff --git a/lib/rules/comment-word-blacklist/index.js b/lib/rules/comment-word-blacklist/index.js index b58df52d93..ba75f9611e 100644 --- a/lib/rules/comment-word-blacklist/index.js +++ b/lib/rules/comment-word-blacklist/index.js @@ -61,4 +61,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/declaration-property-unit-blacklist/__tests__/index.js b/lib/rules/declaration-property-unit-blacklist/__tests__/index.js index bf4f9a2fff..3e09c79fe8 100644 --- a/lib/rules/declaration-property-unit-blacklist/__tests__/index.js +++ b/lib/rules/declaration-property-unit-blacklist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, diff --git a/lib/rules/declaration-property-unit-blacklist/index.js b/lib/rules/declaration-property-unit-blacklist/index.js index db1d840dd2..6f0d883f5c 100644 --- a/lib/rules/declaration-property-unit-blacklist/index.js +++ b/lib/rules/declaration-property-unit-blacklist/index.js @@ -81,4 +81,6 @@ function rule(list) { rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/declaration-property-unit-whitelist/__tests__/index.js b/lib/rules/declaration-property-unit-whitelist/__tests__/index.js index 9850fb4cfc..d37f31fe4d 100644 --- a/lib/rules/declaration-property-unit-whitelist/__tests__/index.js +++ b/lib/rules/declaration-property-unit-whitelist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, diff --git a/lib/rules/declaration-property-unit-whitelist/index.js b/lib/rules/declaration-property-unit-whitelist/index.js index cd2dc9eef0..002e595000 100644 --- a/lib/rules/declaration-property-unit-whitelist/index.js +++ b/lib/rules/declaration-property-unit-whitelist/index.js @@ -81,4 +81,6 @@ function rule(list) { rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/declaration-property-value-blacklist/__tests__/index.js b/lib/rules/declaration-property-value-blacklist/__tests__/index.js index a1d3005a29..5526e3a659 100644 --- a/lib/rules/declaration-property-value-blacklist/__tests__/index.js +++ b/lib/rules/declaration-property-value-blacklist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, diff --git a/lib/rules/declaration-property-value-blacklist/index.js b/lib/rules/declaration-property-value-blacklist/index.js index 3550bf70e4..7c7313632f 100644 --- a/lib/rules/declaration-property-value-blacklist/index.js +++ b/lib/rules/declaration-property-value-blacklist/index.js @@ -63,4 +63,6 @@ function rule(list) { rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/declaration-property-value-whitelist/__tests__/index.js b/lib/rules/declaration-property-value-whitelist/__tests__/index.js index 7f674ab4b7..2daf53488e 100644 --- a/lib/rules/declaration-property-value-whitelist/__tests__/index.js +++ b/lib/rules/declaration-property-value-whitelist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, diff --git a/lib/rules/declaration-property-value-whitelist/index.js b/lib/rules/declaration-property-value-whitelist/index.js index 3a20e2b340..076ac04a69 100644 --- a/lib/rules/declaration-property-value-whitelist/index.js +++ b/lib/rules/declaration-property-value-whitelist/index.js @@ -63,4 +63,6 @@ function rule(list) { rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/function-blacklist/__tests__/index.js b/lib/rules/function-blacklist/__tests__/index.js index 7d7db8d4ff..77bb83177d 100644 --- a/lib/rules/function-blacklist/__tests__/index.js +++ b/lib/rules/function-blacklist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, diff --git a/lib/rules/function-blacklist/index.js b/lib/rules/function-blacklist/index.js index e26654a22d..f3e59af866 100644 --- a/lib/rules/function-blacklist/index.js +++ b/lib/rules/function-blacklist/index.js @@ -66,4 +66,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/function-url-scheme-blacklist/__tests__/index.js b/lib/rules/function-url-scheme-blacklist/__tests__/index.js index d4ec6f2dbc..fb0f9513a3 100644 --- a/lib/rules/function-url-scheme-blacklist/__tests__/index.js +++ b/lib/rules/function-url-scheme-blacklist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, config: [[]], diff --git a/lib/rules/function-url-scheme-blacklist/index.js b/lib/rules/function-url-scheme-blacklist/index.js index c85bb0f68a..9580add5cb 100644 --- a/lib/rules/function-url-scheme-blacklist/index.js +++ b/lib/rules/function-url-scheme-blacklist/index.js @@ -71,4 +71,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/function-url-scheme-whitelist/__tests__/index.js b/lib/rules/function-url-scheme-whitelist/__tests__/index.js index f6e3823f86..7cfe199c9b 100644 --- a/lib/rules/function-url-scheme-whitelist/__tests__/index.js +++ b/lib/rules/function-url-scheme-whitelist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, config: ['https', 'data'], diff --git a/lib/rules/function-url-scheme-whitelist/index.js b/lib/rules/function-url-scheme-whitelist/index.js index 320453c993..9bcadd8930 100644 --- a/lib/rules/function-url-scheme-whitelist/index.js +++ b/lib/rules/function-url-scheme-whitelist/index.js @@ -71,4 +71,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/function-whitelist/__tests__/index.js b/lib/rules/function-whitelist/__tests__/index.js index e2843265d8..5563c23f1f 100644 --- a/lib/rules/function-whitelist/__tests__/index.js +++ b/lib/rules/function-whitelist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, diff --git a/lib/rules/function-whitelist/index.js b/lib/rules/function-whitelist/index.js index 95627bb108..7a72358f1d 100644 --- a/lib/rules/function-whitelist/index.js +++ b/lib/rules/function-whitelist/index.js @@ -68,4 +68,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/media-feature-name-blacklist/__tests__/index.js b/lib/rules/media-feature-name-blacklist/__tests__/index.js index bd28913d70..62855b5924 100644 --- a/lib/rules/media-feature-name-blacklist/__tests__/index.js +++ b/lib/rules/media-feature-name-blacklist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, config: ['max-width', '--wide-viewport', 'width', '/^my-/', 'color'], diff --git a/lib/rules/media-feature-name-blacklist/index.js b/lib/rules/media-feature-name-blacklist/index.js index 40f0a54db1..7dba881daa 100644 --- a/lib/rules/media-feature-name-blacklist/index.js +++ b/lib/rules/media-feature-name-blacklist/index.js @@ -81,4 +81,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/media-feature-name-value-whitelist/__tests__/index.js b/lib/rules/media-feature-name-value-whitelist/__tests__/index.js index e7d1f0baf2..4aadec3d88 100644 --- a/lib/rules/media-feature-name-value-whitelist/__tests__/index.js +++ b/lib/rules/media-feature-name-value-whitelist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, config: [ diff --git a/lib/rules/media-feature-name-value-whitelist/index.js b/lib/rules/media-feature-name-value-whitelist/index.js index 3eb18856e5..c730fe6601 100644 --- a/lib/rules/media-feature-name-value-whitelist/index.js +++ b/lib/rules/media-feature-name-value-whitelist/index.js @@ -94,4 +94,6 @@ function rule(list) { rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/media-feature-name-whitelist/__tests__/index.js b/lib/rules/media-feature-name-whitelist/__tests__/index.js index f0af8f625b..b711d1cbbb 100644 --- a/lib/rules/media-feature-name-whitelist/__tests__/index.js +++ b/lib/rules/media-feature-name-whitelist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, config: ['max-width', '/^my-/', 'color'], diff --git a/lib/rules/media-feature-name-whitelist/index.js b/lib/rules/media-feature-name-whitelist/index.js index ebfdff9fb6..6dfcb91ee8 100644 --- a/lib/rules/media-feature-name-whitelist/index.js +++ b/lib/rules/media-feature-name-whitelist/index.js @@ -81,4 +81,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/property-blacklist/__tests__/index.js b/lib/rules/property-blacklist/__tests__/index.js index 68a3c450aa..208fc96dc5 100644 --- a/lib/rules/property-blacklist/__tests__/index.js +++ b/lib/rules/property-blacklist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, diff --git a/lib/rules/property-blacklist/index.js b/lib/rules/property-blacklist/index.js index 6744c9dc16..88653adf85 100644 --- a/lib/rules/property-blacklist/index.js +++ b/lib/rules/property-blacklist/index.js @@ -62,4 +62,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/property-whitelist/__tests__/index.js b/lib/rules/property-whitelist/__tests__/index.js index 65efbc1efb..f66c7fea86 100644 --- a/lib/rules/property-whitelist/__tests__/index.js +++ b/lib/rules/property-whitelist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, diff --git a/lib/rules/property-whitelist/index.js b/lib/rules/property-whitelist/index.js index 81f4fb0f8a..ed423d3f93 100644 --- a/lib/rules/property-whitelist/index.js +++ b/lib/rules/property-whitelist/index.js @@ -62,4 +62,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/selector-attribute-operator-blacklist/__tests__/index.js b/lib/rules/selector-attribute-operator-blacklist/__tests__/index.js index e6d9f654d3..e36f2433a8 100644 --- a/lib/rules/selector-attribute-operator-blacklist/__tests__/index.js +++ b/lib/rules/selector-attribute-operator-blacklist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, diff --git a/lib/rules/selector-attribute-operator-blacklist/index.js b/lib/rules/selector-attribute-operator-blacklist/index.js index d28b3d09ea..da21a5206a 100644 --- a/lib/rules/selector-attribute-operator-blacklist/index.js +++ b/lib/rules/selector-attribute-operator-blacklist/index.js @@ -70,4 +70,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/selector-attribute-operator-whitelist/__tests__/index.js b/lib/rules/selector-attribute-operator-whitelist/__tests__/index.js index e43b0c1683..671b57e3e7 100644 --- a/lib/rules/selector-attribute-operator-whitelist/__tests__/index.js +++ b/lib/rules/selector-attribute-operator-whitelist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, diff --git a/lib/rules/selector-attribute-operator-whitelist/index.js b/lib/rules/selector-attribute-operator-whitelist/index.js index 34a39dfcc9..528303672f 100644 --- a/lib/rules/selector-attribute-operator-whitelist/index.js +++ b/lib/rules/selector-attribute-operator-whitelist/index.js @@ -70,4 +70,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/selector-combinator-blacklist/__tests__/index.js b/lib/rules/selector-combinator-blacklist/__tests__/index.js index e3ff4b7c43..7585ee6690 100644 --- a/lib/rules/selector-combinator-blacklist/__tests__/index.js +++ b/lib/rules/selector-combinator-blacklist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -24,6 +24,12 @@ it('warns that the rule is deprecated', () => { ); }); }); + +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, config: ['>', ' '], diff --git a/lib/rules/selector-combinator-blacklist/index.js b/lib/rules/selector-combinator-blacklist/index.js index 698dc7df4c..99116483ef 100644 --- a/lib/rules/selector-combinator-blacklist/index.js +++ b/lib/rules/selector-combinator-blacklist/index.js @@ -75,4 +75,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/selector-combinator-whitelist/__tests__/index.js b/lib/rules/selector-combinator-whitelist/__tests__/index.js index e08d23c145..cbfa4b6a5c 100644 --- a/lib/rules/selector-combinator-whitelist/__tests__/index.js +++ b/lib/rules/selector-combinator-whitelist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, config: ['>', ' '], diff --git a/lib/rules/selector-combinator-whitelist/index.js b/lib/rules/selector-combinator-whitelist/index.js index a2d28034c4..427334ac24 100644 --- a/lib/rules/selector-combinator-whitelist/index.js +++ b/lib/rules/selector-combinator-whitelist/index.js @@ -75,4 +75,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/selector-pseudo-class-blacklist/__tests__/index.js b/lib/rules/selector-pseudo-class-blacklist/__tests__/index.js index 9ee952df21..74a37f09a0 100644 --- a/lib/rules/selector-pseudo-class-blacklist/__tests__/index.js +++ b/lib/rules/selector-pseudo-class-blacklist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, config: ['focus', 'global', 'input-placeholder', 'not', 'nth-last-child', 'has'], diff --git a/lib/rules/selector-pseudo-class-blacklist/index.js b/lib/rules/selector-pseudo-class-blacklist/index.js index 73040ba475..f9c1032854 100644 --- a/lib/rules/selector-pseudo-class-blacklist/index.js +++ b/lib/rules/selector-pseudo-class-blacklist/index.js @@ -80,4 +80,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/selector-pseudo-class-whitelist/__tests__/index.js b/lib/rules/selector-pseudo-class-whitelist/__tests__/index.js index 136f7392a1..46ca294a12 100644 --- a/lib/rules/selector-pseudo-class-whitelist/__tests__/index.js +++ b/lib/rules/selector-pseudo-class-whitelist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, config: ['hover', 'nth-child', 'root', 'placeholder', 'has'], diff --git a/lib/rules/selector-pseudo-class-whitelist/index.js b/lib/rules/selector-pseudo-class-whitelist/index.js index 8f9d8d8773..cd602b05ed 100644 --- a/lib/rules/selector-pseudo-class-whitelist/index.js +++ b/lib/rules/selector-pseudo-class-whitelist/index.js @@ -79,4 +79,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/selector-pseudo-element-blacklist/__tests__/index.js b/lib/rules/selector-pseudo-element-blacklist/__tests__/index.js index 77cf01b66b..ad20bc0bcd 100644 --- a/lib/rules/selector-pseudo-element-blacklist/__tests__/index.js +++ b/lib/rules/selector-pseudo-element-blacklist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, config: ['before', 'selection', /^my/i], diff --git a/lib/rules/selector-pseudo-element-blacklist/index.js b/lib/rules/selector-pseudo-element-blacklist/index.js index 8333f37bbb..41975389a4 100644 --- a/lib/rules/selector-pseudo-element-blacklist/index.js +++ b/lib/rules/selector-pseudo-element-blacklist/index.js @@ -79,4 +79,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/selector-pseudo-element-whitelist/__tests__/index.js b/lib/rules/selector-pseudo-element-whitelist/__tests__/index.js index 20823c8a20..95a1944a54 100644 --- a/lib/rules/selector-pseudo-element-whitelist/__tests__/index.js +++ b/lib/rules/selector-pseudo-element-whitelist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, config: ['before', 'selection', /^my/i], diff --git a/lib/rules/selector-pseudo-element-whitelist/index.js b/lib/rules/selector-pseudo-element-whitelist/index.js index 949785a55b..679b76a715 100644 --- a/lib/rules/selector-pseudo-element-whitelist/index.js +++ b/lib/rules/selector-pseudo-element-whitelist/index.js @@ -79,4 +79,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/unit-blacklist/__tests__/index.js b/lib/rules/unit-blacklist/__tests__/index.js index 728701be94..20cb4bee23 100644 --- a/lib/rules/unit-blacklist/__tests__/index.js +++ b/lib/rules/unit-blacklist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, diff --git a/lib/rules/unit-blacklist/index.js b/lib/rules/unit-blacklist/index.js index b27a5ae3e7..dc8abc6465 100644 --- a/lib/rules/unit-blacklist/index.js +++ b/lib/rules/unit-blacklist/index.js @@ -127,4 +127,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/rules/unit-whitelist/__tests__/index.js b/lib/rules/unit-whitelist/__tests__/index.js index 07ef614ca0..9c5f3f79d2 100644 --- a/lib/rules/unit-whitelist/__tests__/index.js +++ b/lib/rules/unit-whitelist/__tests__/index.js @@ -1,7 +1,7 @@ 'use strict'; const standalone = require('../../../standalone'); -const { messages, ruleName } = require('..'); +const { messages, ruleName, meta } = require('..'); it('warns that the rule is deprecated', () => { const config = { @@ -25,6 +25,11 @@ it('warns that the rule is deprecated', () => { }); }); +it('also warns that the rule is deprecated via a meta', () => { + expect(meta).not.toBeUndefined(); + expect(meta).toHaveProperty('deprecated', true); +}); + testRule({ ruleName, diff --git a/lib/rules/unit-whitelist/index.js b/lib/rules/unit-whitelist/index.js index b9f6b18b9f..86eea330e9 100644 --- a/lib/rules/unit-whitelist/index.js +++ b/lib/rules/unit-whitelist/index.js @@ -87,4 +87,6 @@ rule.primaryOptionArray = true; rule.ruleName = ruleName; rule.messages = messages; +rule.meta = { deprecated: true }; + module.exports = rule; diff --git a/lib/utils/__tests__/isSharedLineComment.test.js b/lib/utils/__tests__/isSharedLineComment.test.js index 435e29c34a..ee08824c00 100644 --- a/lib/utils/__tests__/isSharedLineComment.test.js +++ b/lib/utils/__tests__/isSharedLineComment.test.js @@ -5,45 +5,45 @@ const postcss = require('postcss'); describe('isSharedLineComment', () => { it('returns false for the first node', () => { - const root = postcss.parse(` + const css = ` /* comment */ - `); + `; - expect(isSharedLineComment(root.nodes[0])).toBe(false); + expect(isSharedLineComment(comment(css))).toBe(false); }); it('returns false for a non-shared-line comment before a rule', () => { - const root = postcss.parse(` + const css = ` /* comment */ a {} - `); + `; - expect(isSharedLineComment(root.nodes[0])).toBe(false); + expect(isSharedLineComment(comment(css))).toBe(false); }); it('returns false for a non-shared-line comment after a rule', () => { - const root = postcss.parse(` + const css = ` a {} /* comment */ - `); + `; - expect(isSharedLineComment(root.nodes[1])).toBe(false); + expect(isSharedLineComment(comment(css))).toBe(false); }); it('returns true for a shared-line comment before a rule', () => { - const root = postcss.parse(` + const css = ` /* comment */ a {} - `); + `; - expect(isSharedLineComment(root.nodes[0])).toBe(true); + expect(isSharedLineComment(comment(css))).toBe(true); }); it('returns true for a shared-line comment after a rule', () => { - const root = postcss.parse(` + const css = ` a {} /* comment */ - `); + `; - expect(isSharedLineComment(root.nodes[1])).toBe(true); + expect(isSharedLineComment(comment(css))).toBe(true); }); it('returns false for a shared-line non-comment', () => { @@ -56,152 +56,144 @@ describe('isSharedLineComment', () => { }); it('returns true when comment shares a line with the start of a rule block, before it', () => { - const root = postcss.parse(` + const css = ` /* comment */ a { color: pink; } - `); + `; - expect(isSharedLineComment(root.nodes[0])).toBe(true); + expect(isSharedLineComment(comment(css))).toBe(true); }); it('returns true when comment shares a line with the start of a rule block with a multiline selector, before it', () => { - const root = postcss.parse(` + const css = ` /* comment */ a, b { color: pink; } - `); + `; - root.walkComments((comment) => { - expect(isSharedLineComment(comment)).toBe(true); - }); + expect(isSharedLineComment(comment(css))).toBe(true); }); it('returns true when comment shares a line with the start of a rule block, after it', () => { - const root = postcss.parse(` + const css = ` a { /* comment */ color: pink; } - `); + `; - root.walkComments((comment) => { - expect(isSharedLineComment(comment)).toBe(true); - }); + expect(isSharedLineComment(comment(css))).toBe(true); }); it('returns true when comment shares a line with the start of a rule block with a multiline selector, after it', () => { - const root = postcss.parse(` + const css = ` a, b { /* comment */ color: pink; } - `); + `; - root.walkComments((comment) => { - expect(isSharedLineComment(comment)).toBe(true); - }); + expect(isSharedLineComment(comment(css))).toBe(true); }); it('returns true when comment shares a line with the start of an at-rule block, before it', () => { - const root = postcss.parse(` + const css = ` /* comment */ @media (min-width: 0px) { a { color: pink; } } - `); + `; - expect(isSharedLineComment(root.nodes[0])).toBe(true); + expect(isSharedLineComment(comment(css))).toBe(true); }); it('returns true when comment shares a line with the start of an at-rule block with a multiline selector, before it', () => { - const root = postcss.parse(` + const css = ` /* comment */ @media (min-width: 0px) { a { color: pink; } } - `); + `; - expect(isSharedLineComment(root.nodes[0])).toBe(true); + expect(isSharedLineComment(comment(css))).toBe(true); }); it('returns true when comment shares a line with the start of an at-rule block, after it', () => { - const root = postcss.parse(` + const css = ` @media (min-width: 0px) { /* comment */ a { color: pink; } } - `); + `; - root.walkComments((comment) => { - expect(isSharedLineComment(comment)).toBe(true); - }); + expect(isSharedLineComment(comment(css))).toBe(true); }); it('returns true when comment shares a line with the start of an at-rule block with a multiline selector, after it', () => { - const root = postcss.parse(` + const css = ` @media (min-width: 0px) { /* comment */ a { color: pink; } } - `); + `; - root.walkComments((comment) => { - expect(isSharedLineComment(comment)).toBe(true); - }); + expect(isSharedLineComment(comment(css))).toBe(true); }); it('returns false when comment shares a line with only another comment', () => { - const root = postcss.parse(` + const css = ` /* comment */ /* comment */ - `); + `; - expect(isSharedLineComment(root.nodes[0])).toBe(false); + expect(isSharedLineComment(comment(css))).toBe(false); }); it('returns true when comment shares a line with another comment and a non-comment', () => { - const root = postcss.parse(` + const css = ` /* comment */ /* comment */ a {} - `); + `; - expect(isSharedLineComment(root.nodes[0])).toBe(true); + expect(isSharedLineComment(comment(css))).toBe(true); }); it('returns true when comment shares a line with the end of a multi-line rule block, after it', () => { - const root = postcss.parse(` + const css = ` a { color: pink; } /* comment */ - `); + `; - root.walkComments((comment) => { - expect(isSharedLineComment(comment)).toBe(true); - }); + expect(isSharedLineComment(comment(css))).toBe(true); }); it('returns true when comment shares a line with the end of a multi-line property declaration, after it', () => { - const root = postcss.parse(` + const css = ` a { border-radius: 1em 0; /* comment */ } - `); + `; - root.walkComments((comment) => { - expect(isSharedLineComment(comment)).toBe(true); - }); + expect(isSharedLineComment(comment(css))).toBe(true); }); it('returns true when comment shares a line with the start of a multi-line property declaration, before it', () => { - const root = postcss.parse(` + const css = ` a { /* comment */ border-radius: 1em 0; } - `); + `; - root.walkComments((comment) => { - expect(isSharedLineComment(comment)).toBe(true); - }); + expect(isSharedLineComment(comment(css))).toBe(true); }); }); + +function comment(css) { + const comments = []; + + postcss.parse(css).walkComments((comment) => comments.push(comment)); + + return comments[0]; +} diff --git a/lib/utils/__tests__/isStandardSyntaxAtRule.test.js b/lib/utils/__tests__/isStandardSyntaxAtRule.test.js index edb0f3fa52..3244ccf732 100644 --- a/lib/utils/__tests__/isStandardSyntaxAtRule.test.js +++ b/lib/utils/__tests__/isStandardSyntaxAtRule.test.js @@ -1,136 +1,116 @@ 'use strict'; const isStandardSyntaxAtRule = require('../isStandardSyntaxAtRule'); -const less = require('postcss-less'); const postcss = require('postcss'); -const sass = require('postcss-sass'); -const scss = require('postcss-scss'); +const postcssLess = require('postcss-less'); +const postcssSass = require('postcss-sass'); +const postcssScss = require('postcss-scss'); describe('isStandardSyntaxAtRule', () => { it('non nested at-rules without quotes', () => { - atRules('@charset UTF-8;', (atRule) => { - expect(isStandardSyntaxAtRule(atRule)).toBeTruthy(); - }); + expect(isStandardSyntaxAtRule(atRule('@charset UTF-8;'))).toBeTruthy(); }); it("non nested at-rules with `'` quotes", () => { - atRules("@charset 'UTF-8';", (atRule) => { - expect(isStandardSyntaxAtRule(atRule)).toBeTruthy(); - }); + expect(isStandardSyntaxAtRule(atRule("@charset 'UTF-8';"))).toBeTruthy(); }); it('non nested at-rules with `"` quotes', () => { - atRules('@charset "UTF-8";', (atRule) => { - expect(isStandardSyntaxAtRule(atRule)).toBeTruthy(); - }); + expect(isStandardSyntaxAtRule(atRule('@charset "UTF-8";'))).toBeTruthy(); }); it("non nested at-rules with `'` quotes and without space after name", () => { - atRules("@charset'UTF-8';", (atRule) => { - expect(isStandardSyntaxAtRule(atRule)).toBeTruthy(); - }); + expect(isStandardSyntaxAtRule(atRule("@charset'UTF-8';"))).toBeTruthy(); }); it('non nested at-rules with `"` quotes and without space after name', () => { - atRules('@charset"UTF-8";', (atRule) => { - expect(isStandardSyntaxAtRule(atRule)).toBeTruthy(); - }); + expect(isStandardSyntaxAtRule(atRule('@charset"UTF-8";'))).toBeTruthy(); }); it('non nested at-rules with function and without space after name', () => { - atRules('@import url("fineprint.css") print;', (atRule) => { - expect(isStandardSyntaxAtRule(atRule)).toBeTruthy(); - }); + expect(isStandardSyntaxAtRule(atRule('@import url("fineprint.css") print;'))).toBeTruthy(); }); it('nested at-rules', () => { - atRules('@media (min-width: 100px) {};', (atRule) => { - expect(isStandardSyntaxAtRule(atRule)).toBeTruthy(); - }); + expect(isStandardSyntaxAtRule(atRule('@media (min-width: 100px) {};'))).toBeTruthy(); }); it('nested at-rules with newline after name', () => { - atRules('@media\n(min-width: 100px) {};', (atRule) => { - expect(isStandardSyntaxAtRule(atRule)).toBeTruthy(); - }); + expect(isStandardSyntaxAtRule(atRule('@media\n(min-width: 100px) {};'))).toBeTruthy(); }); it('nested at-rules with windows newline after name', () => { - atRules('@media\r\n(min-width: 100px) {};', (atRule) => { - expect(isStandardSyntaxAtRule(atRule)).toBeTruthy(); - }); + expect(isStandardSyntaxAtRule(atRule('@media\r\n(min-width: 100px) {};'))).toBeTruthy(); }); it('nested at-rules without space after name', () => { - atRules('@media(min-width: 100px) {};', (atRule) => { - expect(isStandardSyntaxAtRule(atRule)).toBeTruthy(); - }); + expect(isStandardSyntaxAtRule(atRule('@media(min-width: 100px) {};'))).toBeTruthy(); }); - it('ignore `@content` inside mixins newline', () => { - const sass = '@mixin mixin()\n @content'; + // eslint-disable-next-line jest/no-disabled-tests -- TODO: `postcss-sass` parser does not support `@mixin`. + it.skip('ignore `@content` inside mixins newline', () => { + const rules = sassAtRules('@mixin mixin()\n @content'); - sassAtRules(sass, (atRule) => { - if (atRule.name === 'mixin') { - return; - } - - expect(isStandardSyntaxAtRule(atRule)).toBeFalsy(); - }); + expect(rules).toHaveLength(2); + expect(rules.map((rule) => rule.name)).toEqual(['mixin', 'content']); + expect(isStandardSyntaxAtRule(rules[0])).toBeTruthy(); + expect(isStandardSyntaxAtRule(rules[1])).toBeFalsy(); }); it('ignore `@content` inside mixins space', () => { - const scss = '@mixin mixin() { @content; };'; - - scssAtRules(scss, (atRule) => { - if (atRule.name === 'mixin') { - return; - } + const rules = scssAtRules('@mixin mixin() { @content; };'); - expect(isStandardSyntaxAtRule(atRule)).toBeFalsy(); - }); + expect(rules).toHaveLength(2); + expect(rules.map((rule) => rule.name)).toEqual(['mixin', 'content']); + expect(isStandardSyntaxAtRule(rules[0])).toBeTruthy(); + expect(isStandardSyntaxAtRule(rules[1])).toBeFalsy(); }); it('ignore passing rulesets to mixins', () => { - const less = '@detached-ruleset: { background: red; }; .top { @detached-ruleset(); }'; + const rules = lessAtRules( + '@detached-ruleset: { background: red; }; .top { @detached-ruleset(); }', + ); - lessAtRules(less, (atRule) => { - expect(isStandardSyntaxAtRule(atRule)).toBeFalsy(); - }); + expect(rules).toHaveLength(2); + expect(isStandardSyntaxAtRule(rules[0])).toBeFalsy(); + expect(isStandardSyntaxAtRule(rules[1])).toBeFalsy(); }); it('ignore calling of mixins', () => { - const less = 'a { .mixin(); }'; + const rules = lessAtRules('a { .mixin(); }'); - lessAtRules(less, (atRule) => { - expect(isStandardSyntaxAtRule(atRule)).toBeFalsy(); - }); + expect(rules).toHaveLength(1); + expect(isStandardSyntaxAtRule(rules[0])).toBeFalsy(); }); it('ignore variables', () => { - const less = ` - @my-variable: 10px; - .top { margin-top: @my-variable; } - `; - - lessAtRules(less, (atRule) => { - expect(isStandardSyntaxAtRule(atRule)).toBeFalsy(); - }); + const rules = lessAtRules('@my-variable: 10px; .top { margin-top: @my-variable; }'); + + expect(rules).toHaveLength(1); + expect(isStandardSyntaxAtRule(rules[0])).toBeFalsy(); }); }); -function atRules(css, cb) { - postcss.parse(css).walkAtRules(cb); +function atRules(code, parser = postcss) { + const rules = []; + + parser.parse(code).walkAtRules((rule) => rules.push(rule)); + + return rules; +} + +function atRule(code) { + return atRules(code)[0]; } -function sassAtRules(css, cb) { - sass.parse(css).walkAtRules(cb); +function sassAtRules(code) { + return atRules(code, postcssSass); } -function scssAtRules(css, cb) { - scss.parse(css).walkAtRules(cb); +function scssAtRules(code) { + return atRules(code, postcssScss); } -function lessAtRules(css, cb) { - less.parse(css).walkAtRules(cb); +function lessAtRules(code) { + return atRules(code, postcssLess); } diff --git a/lib/utils/__tests__/isStandardSyntaxCombinator.test.js b/lib/utils/__tests__/isStandardSyntaxCombinator.test.js index 65b71d3454..3636a6ef01 100644 --- a/lib/utils/__tests__/isStandardSyntaxCombinator.test.js +++ b/lib/utils/__tests__/isStandardSyntaxCombinator.test.js @@ -6,86 +6,60 @@ const selectorParser = require('postcss-selector-parser'); describe('isStandardSyntaxCombinator', () => { it('tag', () => { - rules('a {}', (func) => { - expect(isStandardSyntaxCombinator(func)).toBeTruthy(); - }); + expect(isStandardSyntaxCombinator(postcss.parse('a {}').first)).toBeFalsy(); }); it('descendant', () => { - rules('a b {}', (func) => { - expect(isStandardSyntaxCombinator(func)).toBeTruthy(); - }); + expect(isStandardSyntaxCombinator(combinator('a b {}'))).toBeTruthy(); }); it('descendant tab', () => { - rules('a\tb {}', (func) => { - expect(isStandardSyntaxCombinator(func)).toBeTruthy(); - }); + expect(isStandardSyntaxCombinator(combinator('a\tb {}'))).toBeTruthy(); }); it('descendant newline', () => { - rules('a\nb {}', (func) => { - expect(isStandardSyntaxCombinator(func)).toBeTruthy(); - }); + expect(isStandardSyntaxCombinator(combinator('a\nb {}'))).toBeTruthy(); }); it('descendant (double child)', () => { - rules('a >> b {}', (func) => { - expect(isStandardSyntaxCombinator(func)).toBeTruthy(); - }); + expect(isStandardSyntaxCombinator(combinator('a >> b {}'))).toBeTruthy(); }); it('child', () => { - rules('a > b {}', (func) => { - expect(isStandardSyntaxCombinator(func)).toBeTruthy(); - }); + expect(isStandardSyntaxCombinator(combinator('a > b {}'))).toBeTruthy(); }); it('next sibling', () => { - rules('a + b {}', (func) => { - expect(isStandardSyntaxCombinator(func)).toBeTruthy(); - }); + expect(isStandardSyntaxCombinator(combinator('a + b {}'))).toBeTruthy(); }); it('subsequent-sibling', () => { - rules('a ~ b {}', (func) => { - expect(isStandardSyntaxCombinator(func)).toBeTruthy(); - }); + expect(isStandardSyntaxCombinator(combinator('a ~ b {}'))).toBeTruthy(); }); it('lowercase reference', () => { - rules('a /for/ b {}', (func) => { - expect(isStandardSyntaxCombinator(func)).toBeFalsy(); - }); + expect(isStandardSyntaxCombinator(combinator('a /for/ b {}'))).toBeFalsy(); }); it('mixedcase reference', () => { - rules('a /fOr/ b {}', (func) => { - expect(isStandardSyntaxCombinator(func)).toBeFalsy(); - }); + expect(isStandardSyntaxCombinator(combinator('a /fOr/ b {}'))).toBeFalsy(); }); it('uppercase reference', () => { - rules('a /FOR/ b {}', (func) => { - expect(isStandardSyntaxCombinator(func)).toBeFalsy(); - }); + expect(isStandardSyntaxCombinator(combinator('a /FOR/ b {}'))).toBeFalsy(); }); it('last node is combinator', () => { - rules('a ~, {}', (func) => { - expect(isStandardSyntaxCombinator(func)).toBeFalsy(); - }); + expect(isStandardSyntaxCombinator(combinator('a ~, {}'))).toBeFalsy(); }); it('first node is combinator', () => { - rules('~ b {}', (func) => { - expect(isStandardSyntaxCombinator(func)).toBeFalsy(); - }); + expect(isStandardSyntaxCombinator(combinator('~ b {}'))).toBeFalsy(); }); it('last node (in first container) is combinator', () => { - rules('a ~, b {}', (func) => { - expect(isStandardSyntaxCombinator(func)).toBeFalsy(); - }); + expect(isStandardSyntaxCombinator(combinator('a ~, b {}'))).toBeFalsy(); }); it('first node (in second container) is combinator', () => { - rules('a, ~ b {}', (func) => { - expect(isStandardSyntaxCombinator(func)).toBeFalsy(); - }); + expect(isStandardSyntaxCombinator(combinator('a, ~ b {}'))).toBeFalsy(); }); }); -function rules(css, cb) { +function combinator(css) { + const list = []; + postcss.parse(css).walkRules((rule) => { selectorParser((selectorAST) => { - selectorAST.walkCombinators(cb); + selectorAST.walkCombinators((combinator) => list.push(combinator)); }).processSync(rule.selector); }); + + return list[0]; } diff --git a/package-lock.json b/package-lock.json index f20d082ffc..37fa726f1f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "stylelint", - "version": "13.7.1", + "version": "13.7.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -952,9 +952,9 @@ "dev": true }, "@types/table": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/table/-/table-5.0.0.tgz", - "integrity": "sha512-fQLtGLZXor264zUPWI95WNDsZ3QV43/c0lJpR/h1hhLJumXRmHNsrvBfEzW2YMhb0EWCsn4U6h82IgwsajAuTA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/table/-/table-6.0.0.tgz", + "integrity": "sha512-RSmRiYetRzpcZcgNo4x6C1VSsPGBHCGGDO7Rbnz5esVLbGONxBP1CUcn8JhAkVzUVLO+AY8yOSkb27jvfauLyg==", "dev": true }, "@types/unist": { @@ -7394,13 +7394,14 @@ } }, "postcss-selector-parser": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", - "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz", + "integrity": "sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==", "requires": { "cssesc": "^3.0.0", "indexes-of": "^1.0.1", - "uniq": "^1.0.1" + "uniq": "^1.0.1", + "util-deprecate": "^1.0.2" } }, "postcss-syntax": { diff --git a/package.json b/package.json index 5efe191f87..9f5023b9ea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "stylelint", - "version": "13.7.1", + "version": "13.7.2", "description": "A mighty, modern CSS linter.", "keywords": [ "css-in-js", @@ -144,7 +144,7 @@ "postcss-safe-parser": "^4.0.2", "postcss-sass": "^0.4.4", "postcss-scss": "^2.1.1", - "postcss-selector-parser": "^6.0.2", + "postcss-selector-parser": "^6.0.4", "postcss-syntax": "^0.36.2", "postcss-value-parser": "^4.1.0", "resolve-from": "^5.0.0", @@ -175,7 +175,7 @@ "@types/postcss-safe-parser": "^4.0.0", "@types/style-search": "^0.1.1", "@types/svg-tags": "^1.0.0", - "@types/table": "^5.0.0", + "@types/table": "^6.0.0", "@types/write-file-atomic": "^3.0.1", "benchmark": "^2.1.4", "common-tags": "^1.8.0",