diff --git a/docs/user-guide/rules/list.md b/docs/user-guide/rules/list.md index c8218dd614..af7025223f 100644 --- a/docs/user-guide/rules/list.md +++ b/docs/user-guide/rules/list.md @@ -108,14 +108,10 @@ Grouped first by the following categories and then by the [_thing_](http://apps. ### Function - [`function-allowed-list`](../../../lib/rules/function-allowed-list/README.md): Specify a list of allowed functions. -- [`function-blacklist`](../../../lib/rules/function-blacklist/README.md): Specify a list of disallowed functions. **(deprecated)** - [`function-disallowed-list`](../../../lib/rules/function-disallowed-list/README.md): Specify a list of disallowed functions. - [`function-url-no-scheme-relative`](../../../lib/rules/function-url-no-scheme-relative/README.md): Disallow scheme-relative urls. - [`function-url-scheme-allowed-list`](../../../lib/rules/function-url-scheme-allowed-list/README.md): Specify a list of allowed URL schemes. -- [`function-url-scheme-blacklist`](../../../lib/rules/function-url-scheme-blacklist/README.md): Specify a list of disallowed URL schemes. **(deprecated)** - [`function-url-scheme-disallowed-list`](../../../lib/rules/function-url-scheme-disallowed-list/README.md): Specify a list of disallowed URL schemes. -- [`function-url-scheme-whitelist`](../../../lib/rules/function-url-scheme-whitelist/README.md): Specify a list of allowed URL schemes. **(deprecated)** -- [`function-whitelist`](../../../lib/rules/function-whitelist/README.md): Specify a list of allowed functions. **(deprecated)** ### Keyframes @@ -132,9 +128,7 @@ Grouped first by the following categories and then by the [_thing_](http://apps. ### Unit - [`unit-allowed-list`](../../../lib/rules/unit-allowed-list/README.md): Specify a list of allowed units. -- [`unit-blacklist`](../../../lib/rules/unit-blacklist/README.md): Specify a list of disallowed units. **(deprecated)** - [`unit-disallowed-list`](../../../lib/rules/unit-disallowed-list/README.md): Specify a list of disallowed units. -- [`unit-whitelist`](../../../lib/rules/unit-whitelist/README.md): Specify a list of allowed units. **(deprecated)** ### Shorthand property @@ -151,23 +145,17 @@ Grouped first by the following categories and then by the [_thing_](http://apps. ### Property - [`property-allowed-list`](../../../lib/rules/property-allowed-list/README.md): Specify a list of allowed properties. -- [`property-blacklist`](../../../lib/rules/property-blacklist/README.md): Specify a list of disallowed properties. **(deprecated)** - [`property-disallowed-list`](../../../lib/rules/property-disallowed-list/README.md): Specify a list of disallowed properties. - [`property-no-vendor-prefix`](../../../lib/rules/property-no-vendor-prefix/README.md): Disallow vendor prefixes for properties (Autofixable). -- [`property-whitelist`](../../../lib/rules/property-whitelist/README.md): Specify a list of allowed properties. **(deprecated)** ### Declaration - [`declaration-block-no-redundant-longhand-properties`](../../../lib/rules/declaration-block-no-redundant-longhand-properties/README.md): Disallow longhand properties that can be combined into one shorthand property. - [`declaration-no-important`](../../../lib/rules/declaration-no-important/README.md): Disallow `!important` within declarations. - [`declaration-property-unit-allowed-list`](../../../lib/rules/declaration-property-unit-allowed-list/README.md): Specify a list of allowed property and unit pairs within declarations. -- [`declaration-property-unit-blacklist`](../../../lib/rules/declaration-property-unit-blacklist/README.md): Specify a list of disallowed property and unit pairs within declarations. **(deprecated)** - [`declaration-property-unit-disallowed-list`](../../../lib/rules/declaration-property-unit-disallowed-list/README.md): Specify a list of disallowed property and unit pairs within declarations. -- [`declaration-property-unit-whitelist`](../../../lib/rules/declaration-property-unit-whitelist/README.md): Specify a list of allowed property and unit pairs within declarations. **(deprecated)** - [`declaration-property-value-allowed-list`](../../../lib/rules/declaration-property-value-allowed-list/README.md): Specify a list of allowed property and value pairs within declarations. -- [`declaration-property-value-blacklist`](../../../lib/rules/declaration-property-value-blacklist/README.md): Specify a list of disallowed property and value pairs within declarations. **(deprecated)** - [`declaration-property-value-disallowed-list`](../../../lib/rules/declaration-property-value-disallowed-list/README.md): Specify a list of disallowed property and value pairs within declarations. -- [`declaration-property-value-whitelist`](../../../lib/rules/declaration-property-value-whitelist/README.md): Specify a list of allowed property and value pairs within declarations. **(deprecated)** ### Declaration block @@ -177,14 +165,10 @@ Grouped first by the following categories and then by the [_thing_](http://apps. - [`selector-attribute-name-disallowed-list`](../../../lib/rules/selector-attribute-name-disallowed-list/README.md): Specify a list of disallowed attribute names. - [`selector-attribute-operator-allowed-list`](../../../lib/rules/selector-attribute-operator-allowed-list/README.md): Specify a list of allowed attribute operators. -- [`selector-attribute-operator-blacklist`](../../../lib/rules/selector-attribute-operator-blacklist/README.md): Specify a list of disallowed attribute operators. **(deprecated)** - [`selector-attribute-operator-disallowed-list`](../../../lib/rules/selector-attribute-operator-disallowed-list/README.md): Specify a list of disallowed attribute operators. -- [`selector-attribute-operator-whitelist`](../../../lib/rules/selector-attribute-operator-whitelist/README.md): Specify a list of allowed attribute operators. **(deprecated)** - [`selector-class-pattern`](../../../lib/rules/selector-class-pattern/README.md): Specify a pattern for class selectors. - [`selector-combinator-allowed-list`](../../../lib/rules/selector-combinator-allowed-list/README.md): Specify a list of allowed combinators. -- [`selector-combinator-blacklist`](../../../lib/rules/selector-combinator-blacklist/README.md): Specify a list of disallowed combinators. **(deprecated)** - [`selector-combinator-disallowed-list`](../../../lib/rules/selector-combinator-disallowed-list/README.md): Specify a list of disallowed combinators. -- [`selector-combinator-whitelist`](../../../lib/rules/selector-combinator-whitelist/README.md): Specify a list of allowed combinators. **(deprecated)** - [`selector-disallowed-list`](../../../lib/rules/selector-disallowed-list/README.md): Specify a list of disallowed selectors. - [`selector-id-pattern`](../../../lib/rules/selector-id-pattern/README.md): Specify a pattern for ID selectors. - [`selector-max-attribute`](../../../lib/rules/selector-max-attribute/README.md): Limit the number of attribute selectors in a selector. @@ -201,24 +185,17 @@ Grouped first by the following categories and then by the [_thing_](http://apps. - [`selector-no-qualifying-type`](../../../lib/rules/selector-no-qualifying-type/README.md): Disallow qualifying a selector by type. - [`selector-no-vendor-prefix`](../../../lib/rules/selector-no-vendor-prefix/README.md): Disallow vendor prefixes for selectors (Autofixable). - [`selector-pseudo-class-allowed-list`](../../../lib/rules/selector-pseudo-class-allowed-list/README.md): Specify a list of allowed pseudo-class selectors. -- [`selector-pseudo-class-blacklist`](../../../lib/rules/selector-pseudo-class-blacklist/README.md): Specify a list of disallowed pseudo-class selectors. **(deprecated)** - [`selector-pseudo-class-disallowed-list`](../../../lib/rules/selector-pseudo-class-disallowed-list/README.md): Specify a list of disallowed pseudo-class selectors. -- [`selector-pseudo-class-whitelist`](../../../lib/rules/selector-pseudo-class-whitelist/README.md): Specify a list of allowed pseudo-class selectors. **(deprecated)** - [`selector-pseudo-element-allowed-list`](../../../lib/rules/selector-pseudo-element-allowed-list/README.md): Specify a list of allowed pseudo-element selectors. -- [`selector-pseudo-element-blacklist`](../../../lib/rules/selector-pseudo-element-blacklist/README.md): Specify a list of disallowed pseudo-element selectors. **(deprecated)** - [`selector-pseudo-element-colon-notation`](../../../lib/rules/selector-pseudo-element-colon-notation/README.md): Specify single or double colon notation for applicable pseudo-elements (Autofixable). - [`selector-pseudo-element-disallowed-list`](../../../lib/rules/selector-pseudo-element-disallowed-list/README.md): Specify a list of disallowed pseudo-element selectors. -- [`selector-pseudo-element-whitelist`](../../../lib/rules/selector-pseudo-element-whitelist/README.md): Specify a list of allowed pseudo-element selectors. **(deprecated)** ### Media feature - [`media-feature-name-allowed-list`](../../../lib/rules/media-feature-name-allowed-list/README.md): Specify a list of allowed media feature names. -- [`media-feature-name-blacklist`](../../../lib/rules/media-feature-name-blacklist/README.md): Specify a list of disallowed media feature names. **(deprecated)** - [`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 @@ -227,17 +204,13 @@ Grouped first by the following categories and then by the [_thing_](http://apps. ### At-rule - [`at-rule-allowed-list`](../../../lib/rules/at-rule-allowed-list/README.md): Specify a list of allowed at-rules. -- [`at-rule-blacklist`](../../../lib/rules/at-rule-blacklist/README.md): Specify a list of disallowed at-rules. **(deprecated)** - [`at-rule-disallowed-list`](../../../lib/rules/at-rule-disallowed-list/README.md): Specify a list of disallowed at-rules. - [`at-rule-no-vendor-prefix`](../../../lib/rules/at-rule-no-vendor-prefix/README.md): Disallow vendor prefixes for at-rules (Autofixable). - [`at-rule-property-required-list`](../../../lib/rules/at-rule-property-required-list/README.md): Specify a list of required properties for an at-rule. -- [`at-rule-property-requirelist`](../../../lib/rules/at-rule-property-requirelist/README.md): Specify a list of required properties for an at-rule. **(deprecated)** -- [`at-rule-whitelist`](../../../lib/rules/at-rule-whitelist/README.md): Specify a list of allowed at-rules. **(deprecated)** ### Comment - [`comment-pattern`](../../../lib/rules/comment-pattern/README.md): Specify a pattern for comments. -- [`comment-word-blacklist`](../../../lib/rules/comment-word-blacklist/README.md): Specify a list of disallowed words within comments. **(deprecated)** - [`comment-word-disallowed-list`](../../../lib/rules/comment-word-disallowed-list/README.md): Specify a list of disallowed words within comments. ### General / Sheet diff --git a/lib/rules/at-rule-blacklist/README.md b/lib/rules/at-rule-blacklist/README.md deleted file mode 100644 index 454160549b..0000000000 --- a/lib/rules/at-rule-blacklist/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# at-rule-blacklist - -**_Deprecated: Instead use the [`at-rule-disallowed-list`](../at-rule-disallowed-list/README.md) rule._** - -Specify a list of disallowed at-rules. - - -```css - @keyframes name {} -/** ↑ - * At-rules like this */ -``` - -## Options - -`array|string`: `["array", "of", "unprefixed", "at-rules"]|"at-rule"` - -Given: - -``` -["extend", "keyframes"] -``` - -The following patterns are considered violations: - - -```css -a { @extend placeholder; } -``` - - -```css -@keyframes name { - from { top: 10px; } - to { top: 20px; } -} -``` - - -```css -@-moz-keyframes name { - from { top: 10px; } - to { top: 20px; } -} -``` - -The following patterns are _not_ considered violations: - - -```css -@import "path/to/file.css"; -``` diff --git a/lib/rules/at-rule-blacklist/__tests__/index.js b/lib/rules/at-rule-blacklist/__tests__/index.js deleted file mode 100644 index d0900a78a7..0000000000 --- a/lib/rules/at-rule-blacklist/__tests__/index.js +++ /dev/null @@ -1,202 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['extend'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'at-rule-disallowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - - config: ['extend', 'supports', 'keyframes'], - - accept: [ - { - code: 'a { color: pink; }', - description: 'Some random code.', - }, - { - code: '@mixin name ($p) {}', - description: '@rule not from a disallowed list.', - }, - ], - - reject: [ - { - code: 'a { @extend %placeholder; }', - message: messages.rejected('extend'), - line: 1, - column: 5, - description: '@rule from a disallowed list, is a Sass directive.', - }, - { - code: ` - a { - @extend - %placeholder; - } - `, - message: messages.rejected('extend'), - line: 3, - column: 9, - description: '@rule from a disallowed list; newline after its name.', - }, - { - code: ` - @keyframes name { - from { top: 10px; } - to { top: 20px; } - } - `, - message: messages.rejected('keyframes'), - line: 2, - description: '@rule from a disallowed list; independent rule.', - }, - { - code: ` - @Keyframes name { - from { top: 10px; } - to { top: 20px; } - } - `, - message: messages.rejected('Keyframes'), - line: 2, - column: 7, - description: '@rule from a disallowed list; independent rule; messed case.', - }, - { - code: ` - @-moz-keyframes name { - from { top: 10px; } - to { top: 20px; } - } - `, - message: messages.rejected('-moz-keyframes'), - line: 2, - column: 7, - description: '@rule from a disallowed list; independent rule; has vendor prefix.', - }, - { - code: ` - @-WEBKET-KEYFRAMES name { - from { top: 10px; } - to { top: 20px; } - } - `, - message: messages.rejected('-WEBKET-KEYFRAMES'), - line: 2, - column: 7, - description: '@rule from a disallowed list; independent rule; has vendor prefix.', - }, - ], -}); - -testRule({ - ruleName, - - config: ['keyframes'], - - accept: [ - { - code: 'a { color: pink; }', - description: 'Some random code.', - }, - { - code: '@mixin name ($p) {}', - description: '@rule not from a disallowed list.', - }, - ], - - reject: [ - { - code: ` - @keyframes name { - from { top: 10px; } - to { top: 20px; } - } - `, - message: messages.rejected('keyframes'), - line: 2, - column: 7, - description: '@rule from a disallowed list; independent rule.', - }, - { - code: ` - @Keyframes name { - from { top: 10px; } - to { top: 20px; } - } - `, - message: messages.rejected('Keyframes'), - line: 2, - column: 7, - description: '@rule from a disallowed list; independent rule; messed case.', - }, - { - code: ` - @-moz-keyframes name { - from { top: 10px; } - to { top: 20px; } - } - `, - message: messages.rejected('-moz-keyframes'), - line: 2, - column: 7, - description: '@rule from a disallowed list; independent rule; has vendor prefix.', - }, - { - code: ` - @-WEBKET-KEYFRAMES name { - from { top: 10px; } - to { top: 20px; } - } - `, - message: messages.rejected('-WEBKET-KEYFRAMES'), - line: 2, - column: 7, - description: '@rule from a disallowed list; independent rule; has vendor prefix.', - }, - ], -}); - -testRule({ - ruleName, - syntax: 'less', - config: ['keyframes'], - - accept: [ - { - code: ` - .keyframes() { margin: 0; } - - span { .keyframes(); } - `, - description: 'ignore Less mixin which are treated as at-rule', - }, - ], -}); diff --git a/lib/rules/at-rule-blacklist/index.js b/lib/rules/at-rule-blacklist/index.js deleted file mode 100644 index ee90505aeb..0000000000 --- a/lib/rules/at-rule-blacklist/index.js +++ /dev/null @@ -1,64 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const vendor = require('../../utils/vendor'); - -const ruleName = 'at-rule-blacklist'; - -const messages = ruleMessages(ruleName, { - rejected: (name) => `Unexpected at-rule "${name}"`, -}); - -function rule(listInput) { - // To allow for just a string as a parameter (not only arrays of strings) - const list = [].concat(listInput); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString], - }); - - if (!validOptions) { - return; - } - - result.warn(`'${ruleName}' has been deprecated. Instead use 'at-rule-disallowed-list'.`, { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }); - - root.walkAtRules((atRule) => { - const name = atRule.name; - - if (!isStandardSyntaxAtRule(atRule)) { - return; - } - - if (!list.includes(vendor.unprefixed(name).toLowerCase())) { - return; - } - - report({ - message: messages.rejected(name), - node: atRule, - result, - ruleName, - }); - }); - }; -} - -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/README.md b/lib/rules/at-rule-property-requirelist/README.md deleted file mode 100644 index 6108023b72..0000000000 --- a/lib/rules/at-rule-property-requirelist/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# at-rule-property-requirelist - -**_Deprecated: Instead use the [`at-rule-property-required-list`](../at-rule-property-required-list/README.md) rule._** - -Specify a list of required properties for an at-rule. - - -```css - @font-face { font-display: swap; font-family: 'foo'; } -/** ↑ ↑ ↑ - * At-rule and required property names */ -``` - -## Options - -`object`: `{ "at-rule-name": ["array", "of", "properties"] }` - -Given: - -``` -{ - "font-face": ["font-display", "font-family", "font-style"] -} -``` - -The following patterns are considered violations: - - -```css -@font-face { - font-family: 'foo'; - src: url('./fonts/foo.woff2') format('woff2'); -} -``` - - -```css -@font-face { - font-family: 'foo'; - font-style: normal; - src: url('./fonts/foo.woff2') format('woff2'); -} -``` - -The following patterns are _not_ considered violations: - - -```css -@font-face { - font-display: swap; - font-family: 'foo'; - font-style: normal; - src: url('./fonts/foo.woff2') format('woff2'); -} -``` diff --git a/lib/rules/at-rule-property-requirelist/__tests__/index.js b/lib/rules/at-rule-property-requirelist/__tests__/index.js deleted file mode 100644 index 751f3ce403..0000000000 --- a/lib/rules/at-rule-property-requirelist/__tests__/index.js +++ /dev/null @@ -1,89 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: { page: ['margin'] }, - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'at-rule-property-required-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - config: { - 'font-face': ['font-display', 'font-family'], - page: ['margin'], - }, - - accept: [ - { - code: "@font-face { font-display: auto; font-family: 'Arvo'; }", - description: '@font-face with both required properties', - }, - { - code: "@font-face { font-display: auto; font-family: 'Arvo'; src: url('abc'); /* IE9 */ }", - description: '@font-face with inner comment', - }, - { - code: "@FONT-FACE { FONT-DISPLAY: AUTO; FONT-FAMILY: 'ARVO'; }", - description: '@font-face with both required properties (case-sensitive)', - }, - { - code: '@page { padding: 0.5cm; margin: 1cm; }', - description: '@page with required property', - }, - { - code: '@counter-style counter { system: cyclic; }', - description: 'at-rule not specified in config', - }, - { - code: '@mixin invalid-at-rule { @content; }', - description: '@mixin with invalid at-rule', - }, - ], - - reject: [ - { - code: '@font-face { font-display: auto; }', - description: '@font-face with missing property', - message: messages.expected('font-family', 'font-face'), - }, - { - code: '@FONT-FACE { FONT-DISPLAY: AUTO; }', - description: '@font-face with missing property (case-sensitive)', - message: messages.expected('font-family', 'font-face'), - }, - { - code: "@font-face { font-family: 'Arvo'; font-weight: normal }", - description: '@font-face with missing property', - message: messages.expected('font-display', 'font-face'), - }, - { - code: '@page { padding: 0.5cm }', - description: '@page with missing property', - message: messages.expected('margin', 'page'), - }, - ], -}); diff --git a/lib/rules/at-rule-property-requirelist/index.js b/lib/rules/at-rule-property-requirelist/index.js deleted file mode 100644 index fec1038679..0000000000 --- a/lib/rules/at-rule-property-requirelist/index.js +++ /dev/null @@ -1,74 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'at-rule-property-requirelist'; - -const messages = ruleMessages(ruleName, { - expected: (property, atRule) => `Expected property "${property}" for at-rule "${atRule}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isObject], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'at-rule-property-required-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkAtRules((atRule) => { - if (!isStandardSyntaxAtRule(atRule)) { - return; - } - - const { name, nodes } = atRule; - const atRuleName = name.toLowerCase(); - - if (!list[atRuleName]) { - return; - } - - list[atRuleName].forEach((property) => { - const propertyName = property.toLowerCase(); - - const hasProperty = nodes.find( - ({ type, prop }) => type === 'decl' && prop.toLowerCase() === propertyName, - ); - - if (hasProperty) { - return; - } - - return report({ - message: messages.expected(propertyName, atRuleName), - node: atRule, - result, - ruleName, - }); - }); - }); - }; -} - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = { deprecated: true }; - -module.exports = rule; diff --git a/lib/rules/at-rule-whitelist/README.md b/lib/rules/at-rule-whitelist/README.md deleted file mode 100644 index f6e0a006a3..0000000000 --- a/lib/rules/at-rule-whitelist/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# at-rule-whitelist - -**_Deprecated: Instead use the [`at-rule-allowed-list`](../at-rule-allowed-list/README.md) rule._** - -Specify a list of allowed at-rules. - - -```css - @keyframes name {} -/** ↑ - * At-rules like this */ -``` - -## Options - -`array|string`: `["array", "of", "unprefixed", "at-rules"]|"at-rule"` - -Given: - -``` -["extend", "keyframes"] -``` - -The following patterns are considered violations: - - -```css -@import "path/to/file.css"; -``` - - -```css -@media screen and (max-width: 1024px) { - a { display: none; } -} -``` - -The following patterns are _not_ considered violations: - - -```css -a { @extend placeholder; } -``` - - -```css -@keyframes name { - from { top: 10px; } - to { top: 20px; } -} -``` - - -```css -@KEYFRAMES name { - from { top: 10px; } - to { top: 20px; } -} -``` - - -```css -@-moz-keyframes name { - from { top: 10px; } - to { top: 20px; } -} -``` diff --git a/lib/rules/at-rule-whitelist/__tests__/index.js b/lib/rules/at-rule-whitelist/__tests__/index.js deleted file mode 100644 index cf2ca77dea..0000000000 --- a/lib/rules/at-rule-whitelist/__tests__/index.js +++ /dev/null @@ -1,195 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['extend'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'at-rule-allowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - - config: ['extend', 'import', 'keyframes'], - - accept: [ - { - code: 'a { color: pink; }', - description: 'Some random code.', - }, - { - code: 'a { @extend %placeholder; }', - description: '@rule from an allowed list, is a Sass directive.', - }, - { - code: ` - a { - @extend - %placeholder; - } - `, - description: '@rule from an allowed list; newline after its name.', - }, - { - code: ` - @keyframes name { - from { top: 10px; } - to { top: 20px; } - } - `, - description: '@rule from an allowed list; independent rule.', - }, - { - code: ` - @Keyframes name { - from { top: 10px; } - to { top: 20px; } - } - `, - description: '@rule from an allowed list; independent rule; messed case.', - }, - { - code: ` - @-moz-keyframes name { - from { top: 10px; } - to { top: 20px; } - } - `, - description: '@rule from an allowed list; independent rule; has vendor prefix.', - }, - { - code: ` - @-WEBKET-KEYFRAMES name { - from { top: 10px; } - to { top: 20px; } - } - `, - description: '@rule from an allowed list; independent rule; has vendor prefix.', - }, - ], - - reject: [ - { - code: ` - @mixin name () {} - `, - line: 2, - columt: 7, - message: messages.rejected('mixin'), - description: '@rule not from an allowed list; independent rule.', - }, - ], -}); - -testRule({ - ruleName, - skipBasicChecks: true, - - config: ['keyframes'], - - accept: [ - { - code: ` - @keyframes name { - from { top: 10px; } - to { top: 20px; } - } - `, - description: '@rule from an allowed list; independent rule.', - }, - { - code: ` - @Keyframes name { - from { top: 10px; } - to { top: 20px; } - } - `, - description: '@rule from an allowed list; independent rule; messed case.', - }, - { - code: ` - @-moz-keyframes name { - from { top: 10px; } - to { top: 20px; } - } - `, - description: '@rule from an allowed list; independent rule; has vendor prefix.', - }, - { - code: ` - @-WEBKET-KEYFRAMES name { - from { top: 10px; } - to { top: 20px; } - } - `, - description: '@rule from an allowed list; independent rule; has vendor prefix.', - }, - ], - - reject: [ - { - code: ` - @mixin name ($p) {} - `, - message: messages.rejected('mixin'), - line: 2, - column: 7, - description: '@rule not from an allowed list.', - }, - { - code: "@import 'path/to/file.css';", - message: messages.rejected('import'), - line: 1, - column: 1, - description: '@rule not from an allowed list.', - }, - { - code: '@media screen and (max-witdh: 1000px) {}', - message: messages.rejected('media'), - line: 1, - column: 1, - description: '@rule not from an allowed list.', - }, - ], -}); - -testRule({ - ruleName, - syntax: 'less', - config: ['keyframes'], - skipBasicChecks: true, - - accept: [ - { - code: ` - .mixin() { margin: 0; } - - span { .mixin(); } - `, - description: 'ignore Less mixin which are treated as at-rule', - }, - ], -}); diff --git a/lib/rules/at-rule-whitelist/index.js b/lib/rules/at-rule-whitelist/index.js deleted file mode 100644 index afba56047c..0000000000 --- a/lib/rules/at-rule-whitelist/index.js +++ /dev/null @@ -1,64 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const vendor = require('../../utils/vendor'); - -const ruleName = 'at-rule-whitelist'; - -const messages = ruleMessages(ruleName, { - rejected: (name) => `Unexpected at-rule "${name}"`, -}); - -function rule(listInput) { - // To allow for just a string as a parameter (not only arrays of strings) - const list = [].concat(listInput); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString], - }); - - if (!validOptions) { - return; - } - - result.warn(`'${ruleName}' has been deprecated. Instead use 'at-rule-allowed-list'.`, { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }); - - root.walkAtRules((atRule) => { - const name = atRule.name; - - if (!isStandardSyntaxAtRule(atRule)) { - return; - } - - if (list.includes(vendor.unprefixed(name).toLowerCase())) { - return; - } - - report({ - message: messages.rejected(name), - node: atRule, - result, - ruleName, - }); - }); - }; -} - -rule.primaryOptionArray = true; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = { deprecated: true }; - -module.exports = rule; diff --git a/lib/rules/comment-word-blacklist/README.md b/lib/rules/comment-word-blacklist/README.md deleted file mode 100644 index bcac8e8b90..0000000000 --- a/lib/rules/comment-word-blacklist/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# comment-word-blacklist - -**_Deprecated: Instead use the [`comment-word-disallowed-list`](../comment-word-disallowed-list/README.md) rule._** - -Specify a list of disallowed words within comments. - - -```css - /* words within comments */ -/** ↑ ↑ ↑ - * These three words */ -``` - -**Caveat:** Comments within _selector and value lists_ are currently ignored. - -## Options - -`array|string|regexp`: `["array", "of", "words", /or/, "/regex/"]|"word"|"/regex/"` - -If a string is surrounded with `"/"` (e.g. `"/^TODO:/"`), it is interpreted as a regular expression. - -Given: - -``` -["/^TODO:/", "badword"] -``` - -The following patterns are considered violations: - - -```css -/* TODO: */ -``` - - -```css -/* TODO: add fallback */ -``` - - -```css -/* some badword */ -``` - -The following patterns are _not_ considered violations: - - -```css -/* comment */ -``` diff --git a/lib/rules/comment-word-blacklist/__tests__/index.js b/lib/rules/comment-word-blacklist/__tests__/index.js deleted file mode 100644 index 2e5a7288c1..0000000000 --- a/lib/rules/comment-word-blacklist/__tests__/index.js +++ /dev/null @@ -1,352 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['bad-word'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'comment-word-disallowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -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'], - - accept: [ - { - code: '/* comment */', - }, - { - code: '/*# bad-word */', - }, - ], - - reject: [ - { - code: '/* Comment with bad-word */', - message: messages.rejected('bad-word'), - line: 1, - column: 1, - }, - { - code: '/* bad-word */', - message: messages.rejected('bad-word'), - line: 1, - column: 1, - }, - { - code: '/*** bad-word ***/', - message: messages.rejected('bad-word'), - line: 1, - column: 1, - }, - { - code: '/*! bad-word */', - message: messages.rejected('bad-word'), - line: 1, - column: 1, - }, - { - code: '/** bad-word **/', - message: messages.rejected('bad-word'), - line: 1, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: ['/^TODO:/', 'bad-word'], - - accept: [ - { - code: '/* comment */', - }, - { - code: '/* comment comment */', - }, - { - code: '/* comment\ncomment */', - }, - { - code: '/* comment\n\ncomment */', - }, - { - code: '/** comment */', - }, - { - code: '/**** comment ***/', - }, - { - code: '/*\ncomment\n*/', - }, - { - code: '/*\tcomment */', - }, - { - code: '/*! copyright */', - }, - { - code: '/*# sourcemap */', - }, - { - code: '/*# sourcemap bad-word */', - }, - { - code: 'a { color: pink; /* comment */\ntop: 0; }', - }, - { - code: 'a {} /* comment */', - }, - { - code: '/* todo */', - }, - { - code: '/* todo: */', - }, - { - code: '/* todo: comment */', - }, - { - code: '/* tOdO: comment */', - }, - { - code: '/* Todo: comment */', - }, - { - code: '/*! Todo: comment */', - }, - { - code: '/*# Todo: comment */', - }, - { - code: '/** TODO: comment **/', - }, - { - code: '/*** TODO: comment ***/', - }, - ], - - reject: [ - { - code: '/* TODO: */', - message: messages.rejected('/^TODO:/'), - line: 1, - column: 1, - }, - { - code: '/* TODO: comment */', - message: messages.rejected('/^TODO:/'), - line: 1, - column: 1, - }, - { - code: '/* TODO: comment\n next line */', - message: messages.rejected('/^TODO:/'), - line: 1, - column: 1, - }, - { - code: '/* TODO: comment\n next line */', - message: messages.rejected('/^TODO:/'), - line: 1, - column: 1, - }, - { - code: '/* TODO: comment\r\n next line */', - message: messages.rejected('/^TODO:/'), - line: 1, - column: 1, - }, - { - code: '/* TODO: comment\n\n next line */', - message: messages.rejected('/^TODO:/'), - line: 1, - column: 1, - }, - { - code: '/*\n TODO: comment */', - message: messages.rejected('/^TODO:/'), - line: 1, - column: 1, - }, - { - code: '/*\r\n TODO: comment */', - message: messages.rejected('/^TODO:/'), - line: 1, - column: 1, - }, - { - code: '/*\n\n TODO: comment */', - message: messages.rejected('/^TODO:/'), - line: 1, - column: 1, - }, - { - code: '/*\r\n\r\n TODO: comment */', - message: messages.rejected('/^TODO:/'), - line: 1, - column: 1, - }, - { - code: '/* bad-word */', - message: messages.rejected('bad-word'), - line: 1, - column: 1, - }, - { - code: '/* Comment with bad-word */', - message: messages.rejected('bad-word'), - line: 1, - column: 1, - }, - { - code: '/*! copyright bad-word */', - message: messages.rejected('bad-word'), - line: 1, - column: 1, - }, - { - code: '/** bad-word **/', - message: messages.rejected('bad-word'), - line: 1, - column: 1, - }, - { - code: '/*** bad-word ***/', - message: messages.rejected('bad-word'), - line: 1, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - syntax: 'scss', - config: [['/^TODO:/', 'bad-word']], - - accept: [ - { - code: '// comment', - }, - { - code: '// todo', - }, - { - code: '// todo:', - }, - { - code: '// Todo:', - }, - { - code: '// tOdO:', - }, - ], - - reject: [ - { - code: '// TODO:', - message: messages.rejected('/^TODO:/'), - line: 1, - column: 1, - }, - { - code: '// TODO: comment', - message: messages.rejected('/^TODO:/'), - line: 1, - column: 1, - }, - { - code: '// bad-word', - message: messages.rejected('bad-word'), - line: 1, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - syntax: 'less', - config: ['/^TODO:/', 'bad-word'], - - accept: [ - { - code: '// comment', - }, - { - code: '// todo:', - }, - { - code: '// Todo:', - }, - { - code: '// tOdO:', - }, - ], - - reject: [ - { - code: '// TODO:', - message: messages.rejected('/^TODO:/'), - line: 1, - column: 1, - }, - { - code: '// TODO: comment', - message: messages.rejected('/^TODO:/'), - line: 1, - column: 1, - }, - { - code: '// bad-word', - message: messages.rejected('bad-word'), - line: 1, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: [/^TODO:/, 'bad-word'], - - accept: [ - { - code: '/* comment */', - }, - ], - - reject: [ - { - code: '/* TODO: */', - message: messages.rejected(/^TODO:/), - line: 1, - column: 1, - }, - ], -}); diff --git a/lib/rules/comment-word-blacklist/index.js b/lib/rules/comment-word-blacklist/index.js deleted file mode 100644 index ba75f9611e..0000000000 --- a/lib/rules/comment-word-blacklist/index.js +++ /dev/null @@ -1,66 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const containsString = require('../../utils/containsString'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'comment-word-blacklist'; - -const messages = ruleMessages(ruleName, { - rejected: (pattern) => `Unexpected word matching pattern "${pattern}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString, _.isRegExp], - }); - - if (!validOptions) { - return; - } - - result.warn(`'${ruleName}' has been deprecated. Instead use 'comment-word-disallowed-list'.`, { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }); - - root.walkComments((comment) => { - const text = comment.text; - const rawComment = comment.toString(); - const firstFourChars = rawComment.substr(0, 4); - - // Return early if sourcemap - if (firstFourChars === '/*# ') { - return; - } - - const matchesWord = matchesStringOrRegExp(text, list) || containsString(text, list); - - if (!matchesWord) { - return; - } - - report({ - message: messages.rejected(matchesWord.pattern), - node: comment, - result, - ruleName, - }); - }); - }; -} - -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/README.md b/lib/rules/declaration-property-unit-blacklist/README.md deleted file mode 100644 index 7537255e43..0000000000 --- a/lib/rules/declaration-property-unit-blacklist/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# declaration-property-unit-blacklist - -**_Deprecated: Instead use the [`declaration-property-unit-disallowed-list`](../declaration-property-unit-disallowed-list/README.md) rule._** - -Specify a list of disallowed property and unit pairs within declarations. - - -```css -a { width: 100px; } -/** ↑ ↑ - * These properties and these units */ -``` - -## Options - -`object`: `{ "unprefixed-property-name": ["array", "of", "units"] }` - -If a property name is surrounded with `"/"` (e.g. `"/^animation/"`), it is interpreted as a regular expression. This allows, for example, easy targeting of shorthands: `/^animation/` will match `animation`, `animation-duration`, `animation-timing-function`, etc. - -Given: - -``` -{ - "font-size": ["em", "px"], - "/^animation/": ["s"] -} -``` - -The following patterns are considered violations: - - -```css -a { font-size: 1em; } -``` - - -```css -a { animation: animation-name 5s ease; } -``` - - -```css -a { -webkit-animation: animation-name 5s ease; } -``` - - -```css -a { animation-duration: 5s; } -``` - -The following patterns are _not_ considered violations: - - -```css -a { font-size: 1.2rem; } -``` - - -```css -a { height: 100px; } -``` - - -```css -a { animation: animation-name 500ms ease; } -``` - - -```css -a { -webkit-animation: animation-name 500ms ease; } -``` - - -```css -a { animation-duration: 500ms; } -``` diff --git a/lib/rules/declaration-property-unit-blacklist/__tests__/index.js b/lib/rules/declaration-property-unit-blacklist/__tests__/index.js deleted file mode 100644 index 3e09c79fe8..0000000000 --- a/lib/rules/declaration-property-unit-blacklist/__tests__/index.js +++ /dev/null @@ -1,200 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: [{ margin: ['em'] }], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'declaration-property-unit-disallowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - - config: [ - { - 'font-size': ['px', 'em'], - margin: ['em'], - 'background-position': ['%'], - animation: ['s'], - }, - ], - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { top: 0; }', - }, - { - code: 'a { color: #000; }', - }, - { - code: 'a { margin: 0 0 0 0 }', - }, - { - code: 'a { margin: 0 10px 5rem 2in; }', - }, - { - code: 'a { margin: 0 10pX 5rem 2in; }', - }, - { - code: 'a { margin: 0 10PX 5rem 2in; }', - }, - { - code: 'a { background-position: top right, 1em 5vh; }', - }, - { - code: 'a { margin: calc(30vh - 10vh); }', - }, - { - code: 'a { animation: animation-name 300ms ease; }', - }, - { - code: 'a { -webkit-animation: animation-name 300ms ease; }', - }, - { - code: 'a { animation-duration: 3s; }', - }, - { - code: 'a { -webkit-animation-duration: 3s; }', - }, - { - code: 'a { font-size: /* 100px */ 1.2rem; }', - description: 'ignore unit within comments', - }, - { - code: 'a::before { font-size: "10px"}', - description: 'ignore unit within quotes', - }, - { - code: 'a { font-size: $fs10px; }', - description: 'ignore preprocessor variable includes unit', - }, - { - code: 'a { font-size: --some-fs-10px; }', - description: 'ignore css variable includes unit', - }, - ], - - reject: [ - { - code: 'a { font-size: 12px; }', - message: messages.rejected('font-size', 'px'), - line: 1, - column: 16, - }, - { - code: 'a { font-size: 12pX; }', - message: messages.rejected('font-size', 'pX'), - line: 1, - column: 16, - }, - { - code: 'a { font-size: 12PX; }', - message: messages.rejected('font-size', 'PX'), - line: 1, - column: 16, - }, - { - code: 'a { margin: 10px 0 5em; }', - message: messages.rejected('margin', 'em'), - line: 1, - column: 20, - }, - { - code: 'a { background-position: 0 10%; }', - message: messages.rejected('background-position', '%'), - line: 1, - column: 28, - }, - { - code: 'a { background-position: top right, 0 10%; }', - message: messages.rejected('background-position', '%'), - line: 1, - column: 39, - }, - { - code: 'a { margin: calc(10vh - 10em); }', - message: messages.rejected('margin', 'em'), - column: 25, - }, - { - code: 'a { animation: foo 3s; }', - message: messages.rejected('animation', 's'), - }, - { - code: 'a { -webkit-animation: foo 3s; }', - message: messages.rejected('-webkit-animation', 's'), - }, - ], -}); - -testRule({ - ruleName, - - config: [ - { - '/^animation/': ['s'], - }, - ], - - skipBasicChecks: true, - - accept: [ - { - code: 'a { animation: animation-name 300ms ease; }', - }, - { - code: 'a { -webkit-animation: animation-name 300ms ease; }', - }, - { - code: 'a { animation-duration: 300ms; }', - }, - { - code: 'a { -webkit-animation-duration: 300ms; }', - }, - ], - - reject: [ - { - code: 'a { animation: animation-name 3s ease; }', - message: messages.rejected('animation', 's'), - }, - { - code: 'a { -webkit-animation: animation-name 3s ease; }', - message: messages.rejected('-webkit-animation', 's'), - }, - { - code: 'a { animation-duration: 3s; }', - message: messages.rejected('animation-duration', 's'), - }, - { - code: 'a { -webkit-animation-duration: 3s; }', - message: messages.rejected('-webkit-animation-duration', 's'), - }, - ], -}); diff --git a/lib/rules/declaration-property-unit-blacklist/index.js b/lib/rules/declaration-property-unit-blacklist/index.js deleted file mode 100644 index 15eaf928c5..0000000000 --- a/lib/rules/declaration-property-unit-blacklist/index.js +++ /dev/null @@ -1,86 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const getUnitFromValueNode = require('../../utils/getUnitFromValueNode'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const valueParser = require('postcss-value-parser'); -const vendor = require('../../utils/vendor'); - -const ruleName = 'declaration-property-unit-blacklist'; - -const messages = ruleMessages(ruleName, { - rejected: (property, unit) => `Unexpected unit "${unit}" for property "${property}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isObject], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'declaration-property-unit-disallowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkDecls((decl) => { - const prop = decl.prop; - const value = decl.value; - - const unprefixedProp = vendor.unprefixed(prop); - - const propList = _.find(list, (units, propIdentifier) => - matchesStringOrRegExp(unprefixedProp, propIdentifier), - ); - - if (!propList) { - return; - } - - valueParser(value).walk((node) => { - // Ignore wrong units within `url` function - if (node.type === 'function' && node.value.toLowerCase() === 'url') { - return false; - } - - if (node.type === 'string') { - return; - } - - const unit = getUnitFromValueNode(node); - - if (!unit || (unit && !propList.includes(unit.toLowerCase()))) { - return; - } - - report({ - message: messages.rejected(prop, unit), - node: decl, - index: declarationValueIndex(decl) + node.sourceIndex, - result, - ruleName, - }); - }); - }); - }; -} - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = { deprecated: true }; - -module.exports = rule; diff --git a/lib/rules/declaration-property-unit-whitelist/README.md b/lib/rules/declaration-property-unit-whitelist/README.md deleted file mode 100644 index da73901d63..0000000000 --- a/lib/rules/declaration-property-unit-whitelist/README.md +++ /dev/null @@ -1,87 +0,0 @@ -# declaration-property-unit-whitelist - -**_Deprecated: Instead use the [`declaration-property-unit-allowed-list`](../declaration-property-unit-allowed-list/README.md) rule._** - -Specify a list of allowed property and unit pairs within declarations. - - -```css -a { width: 100px; } -/** ↑ ↑ - * These properties and these units */ -``` - -## Options - -`object`: `{ "unprefixed-property-name": ["array", "of", "units"] }` - -If a property name is surrounded with `"/"` (e.g. `"/^animation/"`), it is interpreted as a regular expression. This allows, for example, easy targeting of shorthands: `/^animation/` will match `animation`, `animation-duration`, `animation-timing-function`, etc. - -Given: - -``` -{ - "font-size": ["em", "px"], - "/^animation/": ["s"], - "line-height": [] -} -``` - -The following patterns are considered violations: - - -```css -a { font-size: 1.2rem; } -``` - - -```css -a { animation: animation-name 500ms ease; } -``` - - -```css -a { -webkit-animation: animation-name 500ms ease; } -``` - - -```css -a { animation-duration: 500ms; } -``` - - -```css -a { line-height: 13px; } -``` - -The following patterns are _not_ considered violations: - - -```css -a { font-size: 1em; } -``` - - -```css -a { height: 100px; } -``` - - -```css -a { animation: animation-name 5s ease; } -``` - - -```css -a { -webkit-animation: animation-name 5s ease; } -``` - - -```css -a { animation-duration: 5s; } -``` - - -```css -a { line-height: 1; } -``` diff --git a/lib/rules/declaration-property-unit-whitelist/__tests__/index.js b/lib/rules/declaration-property-unit-whitelist/__tests__/index.js deleted file mode 100644 index d37f31fe4d..0000000000 --- a/lib/rules/declaration-property-unit-whitelist/__tests__/index.js +++ /dev/null @@ -1,205 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: [{ margin: ['em'] }], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'declaration-property-unit-allowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - - config: [ - { - 'font-size': ['px', 'em'], - margin: ['em'], - 'background-position': ['%'], - animation: ['s'], - 'line-height': [], - }, - ], - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { top: 0; }', - }, - { - code: 'a { color: #000; }', - }, - { - code: 'a { margin: 0 0 0 0; }', - }, - { - code: 'a { margin: 0 10em; }', - }, - { - code: 'a { margin: 0 10eM; }', - }, - { - code: 'a { margin: 0 10EM; }', - }, - { - code: 'a { background-position: top right, 0 50%; }', - }, - { - code: 'a { margin: calc(30em - 10em); }', - }, - { - code: 'a { animation: animation-name 1s ease; }', - }, - { - code: 'a { -webkit-animation: animation-name 1s ease; }', - }, - { - code: 'a { line-height: 1; }', - }, - { - code: 'a { font-size: /* 1.2rem */ 12px; }', - description: 'ignore unit within comments', - }, - { - code: 'a::before { font-size: "1.2rem"}', - description: 'ignore unit within quotes', - }, - { - code: 'a { font-size: $fs1rem; }', - description: 'ignore preprocessor variable includes unit', - }, - { - code: 'a { font-size: --some-fs-1rem; }', - description: 'ignore css variable includes unit', - }, - ], - - reject: [ - { - code: 'a { font-size: 1.2rem; }', - message: messages.rejected('font-size', 'rem'), - line: 1, - column: 16, - }, - { - code: 'a { font-size: 1.2rEm; }', - message: messages.rejected('font-size', 'rEm'), - line: 1, - column: 16, - }, - { - code: 'a { font-size: 1.2REM; }', - message: messages.rejected('font-size', 'REM'), - line: 1, - column: 16, - }, - { - code: 'a { margin: 10em 0 1rem; }', - message: messages.rejected('margin', 'rem'), - line: 1, - column: 20, - }, - { - code: 'a { background-position: 0 10px; }', - message: messages.rejected('background-position', 'px'), - line: 1, - column: 28, - }, - { - code: 'a { background-position: top right, 0 10px; }', - message: messages.rejected('background-position', 'px'), - line: 1, - column: 39, - }, - { - code: 'a { margin: calc(10em - 10px); }', - message: messages.rejected('margin', 'px'), - column: 25, - }, - { - code: 'a { animation: animation-name 300ms ease; }', - message: messages.rejected('animation', 'ms'), - column: 31, - }, - { - code: 'a { -webkit-animation: animation-name 300ms ease; }', - message: messages.rejected('-webkit-animation', 'ms'), - column: 39, - }, - { - code: 'a { line-height: 1.2em; }', - message: messages.rejected('line-height', 'em'), - column: 18, - }, - ], -}); - -testRule({ - ruleName, - - config: [ - { - '/^animation/': ['ms'], - }, - ], - - skipBasicChecks: true, - - accept: [ - { - code: 'a { animation: animation-name 300ms ease; }', - }, - { - code: 'a { -webkit-animation: animation-name 300ms ease; }', - }, - { - code: 'a { animation-duration: 300ms; }', - }, - { - code: 'a { -webkit-animation-duration: 300ms; }', - }, - ], - - reject: [ - { - code: 'a { animation: animation-name 3s ease; }', - message: messages.rejected('animation', 's'), - }, - { - code: 'a { -webkit-animation: animation-name 3s ease; }', - message: messages.rejected('-webkit-animation', 's'), - }, - { - code: 'a { animation-duration: 3s; }', - message: messages.rejected('animation-duration', 's'), - }, - { - code: 'a { -webkit-animation-duration: 3s; }', - message: messages.rejected('-webkit-animation-duration', 's'), - }, - ], -}); diff --git a/lib/rules/declaration-property-unit-whitelist/index.js b/lib/rules/declaration-property-unit-whitelist/index.js deleted file mode 100644 index a70bcfd512..0000000000 --- a/lib/rules/declaration-property-unit-whitelist/index.js +++ /dev/null @@ -1,86 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const getUnitFromValueNode = require('../../utils/getUnitFromValueNode'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const valueParser = require('postcss-value-parser'); -const vendor = require('../../utils/vendor'); - -const ruleName = 'declaration-property-unit-whitelist'; - -const messages = ruleMessages(ruleName, { - rejected: (property, unit) => `Unexpected unit "${unit}" for property "${property}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isObject], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'declaration-property-unit-allowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkDecls((decl) => { - const prop = decl.prop; - const value = decl.value; - - const unprefixedProp = vendor.unprefixed(prop); - - const propList = _.find(list, (units, propIdentifier) => - matchesStringOrRegExp(unprefixedProp, propIdentifier), - ); - - if (!propList) { - return; - } - - valueParser(value).walk((node) => { - // Ignore wrong units within `url` function - if (node.type === 'function' && node.value.toLowerCase() === 'url') { - return false; - } - - if (node.type === 'string') { - return; - } - - const unit = getUnitFromValueNode(node); - - if (!unit || (unit && propList.indexOf(unit.toLowerCase())) !== -1) { - return; - } - - report({ - message: messages.rejected(prop, unit), - node: decl, - index: declarationValueIndex(decl) + node.sourceIndex, - result, - ruleName, - }); - }); - }); - }; -} - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = { deprecated: true }; - -module.exports = rule; diff --git a/lib/rules/declaration-property-value-blacklist/README.md b/lib/rules/declaration-property-value-blacklist/README.md deleted file mode 100644 index 9edd6c9b1d..0000000000 --- a/lib/rules/declaration-property-value-blacklist/README.md +++ /dev/null @@ -1,107 +0,0 @@ -# declaration-property-value-blacklist - -**_Deprecated: Instead use the [`declaration-property-value-disallowed-list`](../declaration-property-value-disallowed-list/README.md) rule._** - -Specify a list of disallowed property and value pairs within declarations. - - -```css -a { text-transform: uppercase; } -/** ↑ ↑ - * These properties and these values */ -``` - -## Options - -`object`: `{ "unprefixed-property-name": ["array", "of", "values"], "unprefixed-property-name": ["/regex/", "non-regex", /regex/] }` - -If a property name is surrounded with `"/"` (e.g. `"/^animation/"`), it is interpreted as a regular expression. This allows, for example, easy targeting of shorthands: `/^animation/` will match `animation`, `animation-duration`, `animation-timing-function`, etc. - -The same goes for values. Keep in mind that a regular expression value is matched against the entire value of the declaration, not specific parts of it. For example, a value like `"10px solid rgba( 255 , 0 , 0 , 0.5 )"` will _not_ match `"/^solid/"` (notice beginning of the line boundary) but _will_ match `"/\\s+solid\\s+/"` or `"/\\bsolid\\b/"`. - -Be careful with regex matching not to accidentally consider quoted string values and `url()` arguments. For example, `"/red/"` will match value such as `"1px dotted red"` as well as `"\"foo\""` and `"white url(/mysite.com/red.png)"`. - -Given: - -``` -{ - "transform": ["/scale3d/", "/rotate3d/", "/translate3d/"], - "position": ["fixed"], - "color": ["/^green/"], - "/^animation/": ["/ease/"] -} -``` - -The following patterns are considered violations: - - -```css -a { position: fixed; } -``` - - -```css -a { transform: scale3d(1, 2, 3); } -``` - - -```css -a { -webkit-transform: scale3d(1, 2, 3); } -``` - - -```css -a { color: green; } -``` - - -```css -a { animation: foo 2s ease-in-out; } -``` - - -```css -a { animation-timing-function: ease-in-out; } -``` - - -```css -a { -webkit-animation-timing-function: ease-in-out; } -``` - -The following patterns are _not_ considered violations: - - -```css -a { position: relative; } -``` - - -```css -a { transform: scale(2); } -``` - - -```css -a { -webkit-transform: scale(2); } -``` - - -```css -a { color: lightgreen; } -``` - - -```css -a { animation: foo 2s linear; } -``` - - -```css -a { animation-timing-function: linear; } -``` - - -```css -a { -webkit-animation-timing-function: linear; } -``` diff --git a/lib/rules/declaration-property-value-blacklist/__tests__/index.js b/lib/rules/declaration-property-value-blacklist/__tests__/index.js deleted file mode 100644 index 5526e3a659..0000000000 --- a/lib/rules/declaration-property-value-blacklist/__tests__/index.js +++ /dev/null @@ -1,215 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: [{ color: ['red'] }], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'declaration-property-value-disallowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - - config: [ - { - // regular string - 'text-transform': ['uppercase'], - // regexes - transform: ['/scale3d/', '/rotate3d/', '/translate3d/'], - // mixed string and regex - color: ['red', 'green', 'blue', '/^sea/'], - }, - ], - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: lightgreen; }', - }, - { - code: 'a { text-transform: lowercase; }', - }, - { - code: 'a { transform: matrix(1.0, 2.0, 3.0, 4.0, 5.0, 6.0) translate(12px, 50%); }', - }, - { - code: 'a { -webkit-transform: matrix(1.0, 2.0, 3.0, 4.0, 5.0, 6.0) translate(12px, 50%); }', - }, - { - code: 'a { color: /* red */ pink; }', - description: 'ignore value within comments', - }, - { - code: 'a::before { color: "red"}', - description: 'ignore value within quotes', - }, - { - code: 'a { color: $red; }', - description: 'ignore preprocessor variable includes value', - }, - { - code: 'a { color: --some-red; }', - description: 'ignore css variable includes value', - }, - { - code: 'a { color: darkseagreen }', - }, - ], - - reject: [ - { - code: 'a { color: red; }', - message: messages.rejected('color', 'red'), - line: 1, - column: 5, - }, - { - code: 'a { color: green }', - message: messages.rejected('color', 'green'), - line: 1, - column: 5, - }, - { - code: 'a { text-transform: uppercase; }', - message: messages.rejected('text-transform', 'uppercase'), - line: 1, - column: 5, - }, - { - code: 'a { transform: scale3d(1, 2, 3) }', - message: messages.rejected('transform', 'scale3d(1, 2, 3)'), - line: 1, - column: 5, - }, - { - code: 'a { -webkit-transform: scale3d(1, 2, 3) }', - message: messages.rejected('-webkit-transform', 'scale3d(1, 2, 3)'), - column: 5, - }, - { - code: 'a { color: seagreen }', - message: messages.rejected('color', 'seagreen'), - column: 5, - }, - ], -}); - -testRule({ - ruleName, - - config: [ - { - '/^animation/': ['/ease/'], - }, - ], - - skipBasicChecks: true, - - accept: [ - { - code: 'a { animation: foo 1s linear; }', - }, - { - code: 'a { -webkit-animation: foo 1s linear; }', - }, - { - code: 'a { animation-timing-function: linear; }', - }, - { - code: 'a { -webkit-animation-timing-function: linear; }', - }, - ], - - reject: [ - { - code: 'a { animation: foo 1s ease-in-out; }', - message: messages.rejected('animation', 'foo 1s ease-in-out'), - }, - { - code: 'a { -webkit-animation: foo 1s ease-in-out; }', - message: messages.rejected('-webkit-animation', 'foo 1s ease-in-out'), - }, - { - code: 'a { animation-timing-function: ease-in-out; }', - message: messages.rejected('animation-timing-function', 'ease-in-out'), - }, - { - code: 'a { -webkit-animation-timing-function: ease-in-out; }', - message: messages.rejected('-webkit-animation-timing-function', 'ease-in-out'), - }, - ], -}); - -testRule({ - ruleName, - - config: [ - { - '/^animation/': [/ease/], - }, - ], - - skipBasicChecks: true, - - accept: [ - { - code: 'a { animation: foo 1s linear; }', - }, - ], - - reject: [ - { - code: 'a { animation: foo 1s ease-in-out; }', - message: messages.rejected('animation', 'foo 1s ease-in-out'), - }, - { - code: 'a { -webkit-animation: foo 1s ease-in-out; }', - message: messages.rejected('-webkit-animation', 'foo 1s ease-in-out'), - }, - { - code: 'a { animation-timing-function: ease-in-out; }', - message: messages.rejected('animation-timing-function', 'ease-in-out'), - }, - { - code: 'a { -webkit-animation-timing-function: ease-in-out; }', - message: messages.rejected('-webkit-animation-timing-function', 'ease-in-out'), - }, - ], -}); - -testRule({ - ruleName, - config: { position: ['fixed'] }, - skipBasicChecks: true, - accept: [ - { - code: 'a { font-size: 1em; }', - description: 'irrelevant CSS', - }, - ], -}); diff --git a/lib/rules/declaration-property-value-blacklist/index.js b/lib/rules/declaration-property-value-blacklist/index.js deleted file mode 100644 index ced1e21978..0000000000 --- a/lib/rules/declaration-property-value-blacklist/index.js +++ /dev/null @@ -1,68 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const vendor = require('../../utils/vendor'); - -const ruleName = 'declaration-property-value-blacklist'; - -const messages = ruleMessages(ruleName, { - rejected: (property, value) => `Unexpected value "${value}" for property "${property}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isObject], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'declaration-property-value-disallowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkDecls((decl) => { - const prop = decl.prop; - const value = decl.value; - - const unprefixedProp = vendor.unprefixed(prop); - const propList = _.find(list, (values, propIdentifier) => - matchesStringOrRegExp(unprefixedProp, propIdentifier), - ); - - if (_.isEmpty(propList)) { - return; - } - - if (!matchesStringOrRegExp(value, propList)) { - return; - } - - report({ - message: messages.rejected(prop, value), - node: decl, - result, - ruleName, - }); - }); - }; -} - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = { deprecated: true }; - -module.exports = rule; diff --git a/lib/rules/declaration-property-value-whitelist/README.md b/lib/rules/declaration-property-value-whitelist/README.md deleted file mode 100644 index 2e7f2b9848..0000000000 --- a/lib/rules/declaration-property-value-whitelist/README.md +++ /dev/null @@ -1,98 +0,0 @@ -# declaration-property-value-whitelist - -**_Deprecated: Instead use the [`declaration-property-value-allowed-list`](../declaration-property-value-allowed-list/README.md) rule._** - -Specify a list of allowed property and value pairs within declarations. - - -```css -a { text-transform: uppercase; } -/** ↑ ↑ - * These properties and these values */ -``` - -## Options - -`object`: `{ "unprefixed-property-name": ["array", "of", "values"], "unprefixed-property-name": ["/regex/", "non-regex"] }` - -If a property name is found in the object, only the listed property values are allowed. This rule complains about all non-matching values. (If the property name is not included in the object, anything goes.) - -If a property name is surrounded with `"/"` (e.g. `"/^animation/"`), it is interpreted as a regular expression. This allows, for example, easy targeting of shorthands: `/^animation/` will match `animation`, `animation-duration`, `animation-timing-function`, etc. - -The same goes for values. Keep in mind that a regular expression value is matched against the entire value of the declaration, not specific parts of it. For example, a value like `"10px solid rgba( 255 , 0 , 0 , 0.5 )"` will _not_ match `"/^solid/"` (notice beginning of the line boundary) but _will_ match `"/\\s+solid\\s+/"` or `"/\\bsolid\\b/"`. - -Be careful with regex matching not to accidentally consider quoted string values and `url()` arguments. For example, `"/red/"` will match value such as `"1px dotted red"` as well as `"\"red\""` and `"white url(/mysite.com/red.png)"`. - -Given: - -``` -{ - "transform": ["/scale/"], - "whitespace": ["nowrap"], - "/color/": ["/^green/"] -} -``` - -The following patterns are considered violations: - - -```css -a { whitespace: pre; } -``` - - -```css -a { transform: translate(1, 1); } -``` - - -```css -a { -webkit-transform: translate(1, 1); } -``` - - -```css -a { color: pink; } -``` - - -```css -a { background-color: pink; } -``` - -The following patterns are _not_ considered violations: - - -```css -a { color: pink; } -``` - - -```css -a { whitespace: nowrap; } -``` - - -```css -a { transform: scale(1, 1); } -``` - - -```css -a { -webkit-transform: scale(1, 1); } -``` - - -```css -a { color: green; } -``` - - -```css -a { background-color: green; } -``` - - -```css -a { background: pink; } -``` diff --git a/lib/rules/declaration-property-value-whitelist/__tests__/index.js b/lib/rules/declaration-property-value-whitelist/__tests__/index.js deleted file mode 100644 index 2daf53488e..0000000000 --- a/lib/rules/declaration-property-value-whitelist/__tests__/index.js +++ /dev/null @@ -1,106 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: [{ transform: ['/scale/'] }], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'declaration-property-value-allowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - - config: [ - { - transform: ['/scale/'], - whitespace: ['nowrap'], - '/color/': ['/^green/'], - }, - ], - - accept: [ - { - code: 'div { whitespace: nowrap; }', - }, - { - code: 'a { transform: scale(1, 1); }', - }, - { - code: 'a { -webkit-transform: scale(1, 1); }', - }, - { - code: 'a { color: green; }', - }, - { - code: 'a { background-color: green; }', - }, - ], - - reject: [ - { - code: 'div { whitespace: pre; }', - message: messages.rejected('whitespace', 'pre'), - line: 1, - column: 7, - }, - { - code: 'a { transform: translate(1, 1); }', - message: messages.rejected('transform', 'translate(1, 1)'), - line: 1, - column: 5, - }, - { - code: 'a { -webkit-transform: translate(1, 1); }', - message: messages.rejected('-webkit-transform', 'translate(1, 1)'), - line: 1, - column: 5, - }, - { - code: 'a { color: pink; }', - message: messages.rejected('color', 'pink'), - line: 1, - column: 5, - }, - { - code: 'a { background-color: pink; }', - message: messages.rejected('background-color', 'pink'), - line: 1, - column: 5, - }, - ], -}); - -testRule({ - ruleName, - config: { position: ['static'] }, - skipBasicChecks: true, - accept: [ - { - code: 'a { font-size: 1em; }', - description: 'irrelevant CSS', - }, - ], -}); diff --git a/lib/rules/declaration-property-value-whitelist/index.js b/lib/rules/declaration-property-value-whitelist/index.js deleted file mode 100644 index e6d95577e2..0000000000 --- a/lib/rules/declaration-property-value-whitelist/index.js +++ /dev/null @@ -1,68 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const vendor = require('../../utils/vendor'); - -const ruleName = 'declaration-property-value-whitelist'; - -const messages = ruleMessages(ruleName, { - rejected: (property, value) => `Unexpected value "${value}" for property "${property}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isObject], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'declaration-property-value-allowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkDecls((decl) => { - const prop = decl.prop; - const value = decl.value; - - const unprefixedProp = vendor.unprefixed(prop); - const propList = _.find(list, (values, propIdentifier) => - matchesStringOrRegExp(unprefixedProp, propIdentifier), - ); - - if (_.isEmpty(propList)) { - return; - } - - if (matchesStringOrRegExp(value, propList)) { - return; - } - - report({ - message: messages.rejected(prop, value), - node: decl, - result, - ruleName, - }); - }); - }; -} - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = { deprecated: true }; - -module.exports = rule; diff --git a/lib/rules/function-blacklist/README.md b/lib/rules/function-blacklist/README.md deleted file mode 100644 index 9cb80e361c..0000000000 --- a/lib/rules/function-blacklist/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# function-blacklist - -**_Deprecated: Instead use the [`function-disallowed-list`](../function-disallowed-list/README.md) rule._** - -Specify a list of disallowed functions. - - -```css -a { transform: scale(1); } -/** ↑ - * This function */ -``` - -## Options - -`array|string`: `["array", "of", "unprefixed", /functions/ or "regex"]|"function"|"/regex/"` - -If a string is surrounded with `"/"` (e.g. `"/^rgb/"`), it is interpreted as a regular expression. - -Given: - -``` -["scale", "rgba", "linear-gradient"] -``` - -The following patterns are considered violations: - - -```css -a { transform: scale(1); } -``` - - -```css -a { - color: rgba(0, 0, 0, 0.5); -} -``` - - -```css -a { - background: - red, - -moz-linear-gradient(45deg, blue, red); -} -``` - -The following patterns are _not_ considered violations: - - -```css -a { background: red; } -``` diff --git a/lib/rules/function-blacklist/__tests__/index.js b/lib/rules/function-blacklist/__tests__/index.js deleted file mode 100644 index 77bb83177d..0000000000 --- a/lib/rules/function-blacklist/__tests__/index.js +++ /dev/null @@ -1,248 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['rgba'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'function-disallowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - - config: ['rgba', 'scale', 'linear-gradient'], - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { transform: SCALE(1); }', - }, - { - code: 'a { transform: sCaLe(1); }', - }, - { - code: 'a { transform: rotate(7deg) }', - }, - { - code: 'a { transform: rOtAtE(7deg) }', - }, - { - code: 'a { transform: ROTATE(7deg) }', - }, - { - code: 'a { background: -webkit-radial-gradient(red, green, blue); }', - }, - { - code: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - }, - { - code: '@media (max-width: 10px) { a { color: color(rgb(0, 0, 0) lightness(50%)); } }', - }, - { - code: '$scale: (value, value2)', - description: 'Sass list ignored', - }, - ], - - reject: [ - { - code: 'a { transform: scale(1); }', - message: messages.rejected('scale'), - line: 1, - column: 16, - }, - { - code: 'a { transform : scale(1); }', - message: messages.rejected('scale'), - line: 1, - column: 17, - }, - { - code: 'a\n{ transform: scale(1); }', - message: messages.rejected('scale'), - line: 2, - column: 14, - }, - { - code: 'a { transform: scale(1); }', - message: messages.rejected('scale'), - line: 1, - column: 19, - }, - { - code: ' a { transform: scale(1); }', - message: messages.rejected('scale'), - line: 1, - column: 18, - }, - { - code: 'a { color: rgba(0, 0, 0, 0) }', - message: messages.rejected('rgba'), - line: 1, - column: 12, - }, - { - code: 'a { color: color(rgba(0, 0, 0, 0) lightness(50%)); }', - message: messages.rejected('rgba'), - line: 1, - column: 18, - }, - { - code: 'a { background: red, -moz-linear-gradient(45deg, blue, red); }', - message: messages.rejected('-moz-linear-gradient'), - line: 1, - column: 22, - }, - { - code: '@media (max-width: 10px) { a { color: color(rgba(0, 0, 0) lightness(50%)); } }', - message: messages.rejected('rgba'), - line: 1, - column: 45, - }, - ], -}); - -testRule({ - ruleName, - - config: ['/rgb/'], - - accept: [ - { - code: 'a { color: hsl(208, 100%, 97%); }', - }, - ], - - reject: [ - { - code: 'a { color: rgb(0, 0, 0); }', - message: messages.rejected('rgb'), - line: 1, - column: 12, - }, - { - code: 'a { color: rgba(0, 0, 0); }', - message: messages.rejected('rgba'), - line: 1, - column: 12, - }, - ], -}); - -testRule({ - ruleName, - - config: [/rgb/], - - accept: [ - { - code: 'a { color: hsl(208, 100%, 97%); }', - }, - ], - - reject: [ - { - code: 'a { color: rgb(0, 0, 0); }', - message: messages.rejected('rgb'), - line: 1, - column: 12, - }, - { - code: 'a { color: rgba(0, 0, 0); }', - message: messages.rejected('rgba'), - line: 1, - column: 12, - }, - ], -}); - -testRule({ - ruleName, - - config: ['skewx', 'translateX', 'SCALEX', '/rotate/i', '/MATRIX/'], - - accept: [ - { - code: 'a { transform: stewX(10deg); }', - }, - { - code: 'a { transform: translateY(5px); }', - }, - { - code: 'a { transform: scaleX(1); }', - }, - { - code: 'a { transform: matrix3d(a1); }', - }, - ], - - reject: [ - { - code: 'a { transform: skewx(10deg); }', - message: messages.rejected('skewx'), - line: 1, - column: 16, - }, - { - code: 'a { transform: translateX(5px); }', - message: messages.rejected('translateX'), - line: 1, - column: 16, - }, - { - code: 'a { transform: SCALEX(1); }', - message: messages.rejected('SCALEX'), - line: 1, - column: 16, - }, - { - code: 'a { transform: rotatex(60deg); }', - message: messages.rejected('rotatex'), - line: 1, - column: 16, - }, - { - code: 'a { transform: rotateX(60deg); }', - message: messages.rejected('rotateX'), - line: 1, - column: 16, - }, - { - code: 'a { transform: ROTATEX(60deg); }', - message: messages.rejected('ROTATEX'), - line: 1, - column: 16, - }, - { - code: 'a { transform: MATRIX3d(a1); }', - message: messages.rejected('MATRIX3d'), - line: 1, - column: 16, - }, - ], -}); diff --git a/lib/rules/function-blacklist/index.js b/lib/rules/function-blacklist/index.js deleted file mode 100644 index 1c1e09cdc9..0000000000 --- a/lib/rules/function-blacklist/index.js +++ /dev/null @@ -1,71 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const isStandardSyntaxFunction = require('../../utils/isStandardSyntaxFunction'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const valueParser = require('postcss-value-parser'); -const vendor = require('../../utils/vendor'); - -const ruleName = 'function-blacklist'; - -const messages = ruleMessages(ruleName, { - rejected: (name) => `Unexpected function "${name}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString, _.isRegExp], - }); - - if (!validOptions) { - return; - } - - result.warn(`'${ruleName}' has been deprecated. Instead use 'function-disallowed-list'.`, { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }); - - root.walkDecls((decl) => { - const value = decl.value; - - valueParser(value).walk((node) => { - if (node.type !== 'function') { - return; - } - - if (!isStandardSyntaxFunction(node)) { - return; - } - - if (!matchesStringOrRegExp(vendor.unprefixed(node.value), list)) { - return; - } - - report({ - message: messages.rejected(node.value), - node: decl, - index: declarationValueIndex(decl) + node.sourceIndex, - result, - ruleName, - }); - }); - }); - }; -} - -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/README.md b/lib/rules/function-url-scheme-blacklist/README.md deleted file mode 100644 index 14fb678310..0000000000 --- a/lib/rules/function-url-scheme-blacklist/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# function-url-scheme-blacklist - -**_Deprecated: Instead use the [`function-url-scheme-disallowed-list`](../function-url-scheme-disallowed-list/README.md) rule._** - -Specify a list of disallowed URL schemes. - - -```css -a { background-image: url('http://www.example.com/file.jpg'); } -/** ↑ - * This URL scheme */ -``` - -A [URL scheme](https://url.spec.whatwg.org/#syntax-url-scheme) consists of alphanumeric, `+`, `-`, and `.` characters. It can appear at the start of a URL and is followed by `:`. - -This rule ignores: - -- URL arguments without an existing URL scheme -- URL arguments with variables or variable interpolation (`$sass`, `@less`, `--custom-property`, `#{$var}`, `@{var}`, `$(var)`) - -## Options - -`array|string|regex`: `["array", "of", /schemes/ or "/regex/"]|"scheme"|/regex/` - -Given: - -``` -["ftp", "/^http/"] -``` - -The following patterns are considered violations: - - -```css -a { background-image: url('ftp://www.example.com/file.jpg'); } -``` - - -```css -a { background-image: url('http://www.example.com/file.jpg'); } -``` - - -```css -a { background-image: url('https://www.example.com/file.jpg'); } -``` - -The following patterns are _not_ considered violations: - - -```css -a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); } -``` - - -```css -a { background-image: url('example.com/file.jpg'); } -``` - - -```css -a { background-image: url('/example.com/file.jpg'); } -``` - - -```css -a { background-image: url('//example.com/file.jpg'); } -``` - - -```css -a { background-image: url('./path/to/file.jpg'); } -``` diff --git a/lib/rules/function-url-scheme-blacklist/__tests__/index.js b/lib/rules/function-url-scheme-blacklist/__tests__/index.js deleted file mode 100644 index fb0f9513a3..0000000000 --- a/lib/rules/function-url-scheme-blacklist/__tests__/index.js +++ /dev/null @@ -1,285 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['https'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'function-url-scheme-disallowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - config: [[]], - - accept: [ - { - code: "a { background: url('http://www.example.com/file.jpg'); }", - }, - ], -}); - -testRule({ - ruleName, - config: [''], - - accept: [ - { - code: "a { background: url('http://www.example.com/file.jpg'); }", - }, - ], -}); - -testRule({ - ruleName, - config: ['https', 'data'], - - accept: [ - { - code: 'a { background: url(); }', - }, - { - code: "a { background: url(''); }", - }, - { - code: 'a { background: url(""); }', - }, - { - code: 'a { background: url(:); }', - }, - { - code: 'a { background: url(://); }', - }, - { - code: 'a { background: url(//); }', - }, - { - code: 'a { background: url(/); }', - }, - { - code: 'a { background: url(./); }', - }, - { - code: 'a { background: url(./file.jpg); }', - }, - { - code: 'a { background: url(../file.jpg); }', - }, - { - code: 'a { background: URL(../file.jpg); }', - }, - { - code: "a { background: url('../file.jpg'); }", - }, - { - code: 'a { background: url("../file.jpg"); }', - }, - { - code: "a { background: url('/path/to/file.jpg'); }", - }, - { - code: 'a { background: url(//www.example.com/file.jpg); }', - }, - { - code: 'a { background: url("//www.example.com/file.jpg"); }', - }, - { - code: "a { background: url('http://www.example.com/file.jpg'); }", - }, - { - code: "a { background-image: url('http://example.com:3000'); }", - }, - { - code: "a { background-image: url('//example.com:3000'); }", - }, - { - code: "@font-face { font-family: 'foo'; src: url('/path/to/foo.ttf'); }", - }, - { - code: 'a { background: url(HTTP://example.com/file.jpg); }', - description: 'ignore case', - }, - { - code: 'a { background: some-url(); }', - description: 'ignore contain url function', - }, - { - code: 'a { background: url($image); }', - description: 'ignore variable', - }, - { - code: 'a { background: url(@image); }', - description: 'ignore variable', - }, - { - code: 'a { background: url(http://#{$host}/path); }', - description: 'ignore interpolation', - }, - { - code: "a { background: url('http://@{host}/path'); }", - description: 'ignore interpolation', - }, - { - code: 'a { background: url(http://$(host)/path); }', - description: 'ignore interpolation', - }, - { - code: 'a { background: url(var(--image)); }', - description: 'ignore variable', - }, - { - code: 'a { background: url(example.com); }', - description: 'schemeless url', - }, - { - code: 'a { background: url(example.com:3000); }', - description: 'schemeless url and port', - }, - { - code: 'a { background: url(http://example.com:3000); }', - description: 'url with scheme and port', - }, - ], - - reject: [ - { - code: - "a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); }", - message: messages.rejected('data'), - line: 1, - column: 27, - }, - { - code: 'a { background: url(HTTPS://www.example.com/file.jpg); }', - message: messages.rejected('https'), - line: 1, - column: 21, - }, - { - code: "a { background: url('https://www.example.com/file.jpg'); }", - message: messages.rejected('https'), - line: 1, - column: 21, - }, - { - code: 'a { background: url("https://www.example.com/file.jpg"); }', - message: messages.rejected('https'), - line: 1, - column: 21, - }, - { - code: "a { background: url('https://example.com:3000'); }", - message: messages.rejected('https'), - line: 1, - column: 21, - }, - { - code: "@font-face { font-family: 'foo'; src: url('https://www.example.com/file.jpg'); }", - message: messages.rejected('https'), - line: 1, - column: 43, - }, - { - code: "a { background: no-repeat center/80% url('https://www.example.com/file.jpg'); }", - message: messages.rejected('https'), - line: 1, - column: 42, - }, - ], -}); - -testRule({ - ruleName, - - config: [['/^http/']], - - accept: [ - { - code: - "a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); }", - }, - { - code: 'a { background: url(./file.jpg); }', - }, - ], - - reject: [ - { - code: 'a { background: url(https://example.com/file.jpg); }', - message: messages.rejected('https'), - line: 1, - column: 21, - }, - { - code: 'a { background: url(HTTPS://example.com/file.jpg); }', - message: messages.rejected('https'), - line: 1, - column: 21, - }, - { - code: 'a { background: url(http://example.com/file.jpg); }', - message: messages.rejected('http'), - line: 1, - column: 21, - }, - ], -}); - -testRule({ - ruleName, - - config: [[/^http/]], - - accept: [ - { - code: - "a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); }", - }, - { - code: 'a { background: url(./file.jpg); }', - }, - ], - - reject: [ - { - code: 'a { background: url(https://example.com/file.jpg); }', - message: messages.rejected('https'), - line: 1, - column: 21, - }, - { - code: 'a { background: url(HTTPS://example.com/file.jpg); }', - message: messages.rejected('https'), - line: 1, - column: 21, - }, - { - code: 'a { background: url(http://example.com/file.jpg); }', - message: messages.rejected('http'), - line: 1, - column: 21, - }, - ], -}); diff --git a/lib/rules/function-url-scheme-blacklist/index.js b/lib/rules/function-url-scheme-blacklist/index.js deleted file mode 100644 index 9580add5cb..0000000000 --- a/lib/rules/function-url-scheme-blacklist/index.js +++ /dev/null @@ -1,76 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const functionArgumentsSearch = require('../../utils/functionArgumentsSearch'); -const getSchemeFromUrl = require('../../utils/getSchemeFromUrl'); -const isStandardSyntaxUrl = require('../../utils/isStandardSyntaxUrl'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'function-url-scheme-blacklist'; - -const messages = ruleMessages(ruleName, { - rejected: (scheme) => `Unexpected URL scheme "${scheme}:"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString, _.isRegExp], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'function-url-scheme-disallowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkDecls((decl) => { - functionArgumentsSearch(decl.toString().toLowerCase(), 'url', (args, index) => { - const unspacedUrlString = _.trim(args, ' '); - - if (!isStandardSyntaxUrl(unspacedUrlString)) { - return; - } - - const urlString = _.trim(unspacedUrlString, '\'"'); - const scheme = getSchemeFromUrl(urlString); - - if (scheme === null) { - return; - } - - if (!matchesStringOrRegExp(scheme, list)) { - return; - } - - report({ - message: messages.rejected(scheme), - node: decl, - index, - result, - ruleName, - }); - }); - }); - }; -} - -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/README.md b/lib/rules/function-url-scheme-whitelist/README.md deleted file mode 100644 index ece68797d7..0000000000 --- a/lib/rules/function-url-scheme-whitelist/README.md +++ /dev/null @@ -1,78 +0,0 @@ -# function-url-scheme-whitelist - -**_Deprecated: Instead use the [`function-url-scheme-allowed-list`](../function-url-scheme-allowed-list/README.md) rule._** - -Specify a list of allowed URL schemes. - - -```css -a { background-image: url('http://www.example.com/file.jpg'); } -/** ↑ - * This URL scheme */ -``` - -A [URL scheme](https://url.spec.whatwg.org/#syntax-url-scheme) consists of alphanumeric, `+`, `-`, and `.` characters. It can appear at the start of a URL and is followed by `:`. - -This rule ignores: - -- URL arguments without an existing URL scheme -- URL arguments with variables or variable interpolation (`$sass`, `@less`, `--custom-property`, `#{$var}`, `@{var}`, `$(var)`) - -## Options - -`array|string|regex`: `["array", "of", /schemes/ or "/regex/"]|"scheme"|/regex/` - -Given: - -``` -["data", "/^http/"] -``` - -The following patterns are considered violations: - - -```css -a { background-image: url('file://file.jpg'); } -``` - -The following patterns are _not_ considered violations: - - -```css -a { background-image: url('example.com/file.jpg'); } -``` - - -```css -a { background-image: url('/example.com/file.jpg'); } -``` - - -```css -a { background-image: url('//example.com/file.jpg'); } -``` - - -```css -a { background-image: url('./path/to/file.jpg'); } -``` - - -```css -a { background-image: url('http://www.example.com/file.jpg'); } -``` - - -```css -a { background-image: url('https://www.example.com/file.jpg'); } -``` - - -```css -a { background-image: url('HTTPS://www.example.com/file.jpg'); } -``` - - -```css -a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); } -``` diff --git a/lib/rules/function-url-scheme-whitelist/__tests__/index.js b/lib/rules/function-url-scheme-whitelist/__tests__/index.js deleted file mode 100644 index 7cfe199c9b..0000000000 --- a/lib/rules/function-url-scheme-whitelist/__tests__/index.js +++ /dev/null @@ -1,347 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['https'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'function-url-scheme-allowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -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'], - - accept: [ - { - code: 'a { background: url(); }', - }, - { - code: "a { background: url(''); }", - }, - { - code: 'a { background: url(""); }', - }, - { - code: 'a { background: url(:); }', - }, - { - code: 'a { background: url(://); }', - }, - { - code: 'a { background: url(//); }', - }, - { - code: 'a { background: url(/); }', - }, - { - code: 'a { background: url(./); }', - }, - { - code: 'a { background: url(./file.jpg); }', - }, - { - code: 'a { background: url(../file.jpg); }', - }, - { - code: 'a { background: URL(../file.jpg); }', - }, - { - code: "a { background: url('../file.jpg'); }", - }, - { - code: 'a { background: url("../file.jpg"); }', - }, - { - code: "a { background: url('/path/to/file.jpg'); }", - }, - { - code: 'a { background: url(//www.example.com/file.jpg); }', - }, - { - code: 'a { background: url("//www.example.com/file.jpg"); }', - }, - { - code: "a { background: url('https://www.example.com/file.jpg'); }", - }, - { - code: - "a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); }", - }, - { - code: "a { background-image: url('https://example.com:3000'); }", - }, - { - code: "a { background-image: url('//example.com:3000'); }", - }, - { - code: "@font-face { font-family: 'foo'; src: url('/path/to/foo.ttf'); }", - }, - { - code: 'a { background: url(HTTPS://example.com/file.jpg); }', - description: 'ignore case', - }, - { - code: 'a { background: some-url(); }', - description: 'ignore contain url function', - }, - { - code: 'a { background: url($image); }', - description: 'ignore variable', - }, - { - code: 'a { background: url(@image); }', - description: 'ignore variable', - }, - { - code: 'a { background: url(http://#{$host}/path); }', - description: 'ignore interpolation', - }, - { - code: "a { background: url('http://@{host}/path'); }", - description: 'ignore interpolation', - }, - { - code: 'a { background: url(http://$(host)/path); }', - description: 'ignore interpolation', - }, - { - code: 'a { background: url(var(--image)); }', - description: 'ignore variable', - }, - { - code: 'a { background: url(example.com); }', - description: 'schemeless url', - }, - { - code: 'a { background: url(example.com:3000); }', - description: 'schemeless url and port', - }, - { - code: 'a { background: url(https://example.com:3000); }', - description: 'url with scheme and port', - }, - ], - - reject: [ - { - code: 'a { background: url(http://www.example.com/file.jpg); }', - message: messages.rejected('http'), - line: 1, - column: 21, - }, - { - code: "a { background: url('http://www.example.com/file.jpg'); }", - message: messages.rejected('http'), - line: 1, - column: 21, - }, - { - code: 'a { background: url("http://www.example.com/file.jpg"); }', - message: messages.rejected('http'), - line: 1, - column: 21, - }, - { - code: "a { background: url('http://example.com:3000'); }", - message: messages.rejected('http'), - line: 1, - column: 21, - }, - { - code: "@font-face { font-family: 'foo'; src: url('http://www.example.com/file.jpg'); }", - message: messages.rejected('http'), - line: 1, - column: 43, - }, - { - code: "a { background: no-repeat center/80% url('http://www.example.com/file.jpg'); }", - message: messages.rejected('http'), - line: 1, - column: 42, - }, - ], -}); - -testRule({ - ruleName, - config: [[]], - - accept: [ - { - code: "a { background: url('/path/to/file.jpg'); }", - }, - { - code: 'a { background: url(//www.example.com/file.jpg); }', - }, - { - code: 'a { background: url("//www.example.com/file.jpg"); }', - }, - { - code: 'a { background: url(example.com:3000); }', - }, - ], - - reject: [ - { - code: "a { background: url('https://www.example.com/file.jpg'); }", - message: messages.rejected('https'), - line: 1, - column: 21, - }, - { - code: - "a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); }", - message: messages.rejected('data'), - line: 1, - column: 27, - }, - ], -}); - -testRule({ - ruleName, - config: [''], - - accept: [ - { - code: "a { background: url('/path/to/file.jpg'); }", - }, - { - code: 'a { background: url(//www.example.com/file.jpg); }', - }, - { - code: 'a { background: url("//www.example.com/file.jpg"); }', - }, - { - code: 'a { background: url(example.com:3000); }', - }, - ], - - reject: [ - { - code: "a { background: url('https://www.example.com/file.jpg'); }", - message: messages.rejected('https'), - line: 1, - column: 21, - }, - { - code: - "a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); }", - message: messages.rejected('data'), - line: 1, - column: 27, - }, - ], -}); - -testRule({ - ruleName, - // primaryOptionArray - config: ['uri', 'file', 'https'], - - accept: [ - { - code: 'a { background: url(https://example.com/file.jpg); }', - }, - ], - - reject: [ - { - code: 'a { background: url(http://example.com/file.jpg); }', - message: messages.rejected('http'), - line: 1, - column: 21, - }, - ], -}); - -testRule({ - ruleName, - - config: [['/^http/']], - - accept: [ - { - code: 'a { background: url(http://example.com/file.jpg); }', - }, - { - code: 'a { background: url(HTTP://example.com/file.jpg); }', - }, - { - code: 'a { background: url(https://example.com/file.jpg); }', - }, - ], - - reject: [ - { - code: 'a { background: url(ftp://example.com/file.jpg); }', - message: messages.rejected('ftp'), - line: 1, - column: 21, - }, - { - code: - "a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); }", - message: messages.rejected('data'), - line: 1, - column: 27, - }, - ], -}); - -testRule({ - ruleName, - - config: [[/^http/]], - - accept: [ - { - code: 'a { background: url(http://example.com/file.jpg); }', - }, - { - code: 'a { background: url(HTTP://example.com/file.jpg); }', - }, - { - code: 'a { background: url(https://example.com/file.jpg); }', - }, - ], - - reject: [ - { - code: 'a { background: url(ftp://example.com/file.jpg); }', - message: messages.rejected('ftp'), - line: 1, - column: 21, - }, - { - code: - "a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); }", - message: messages.rejected('data'), - line: 1, - column: 27, - }, - ], -}); diff --git a/lib/rules/function-url-scheme-whitelist/index.js b/lib/rules/function-url-scheme-whitelist/index.js deleted file mode 100644 index 9bcadd8930..0000000000 --- a/lib/rules/function-url-scheme-whitelist/index.js +++ /dev/null @@ -1,76 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const functionArgumentsSearch = require('../../utils/functionArgumentsSearch'); -const getSchemeFromUrl = require('../../utils/getSchemeFromUrl'); -const isStandardSyntaxUrl = require('../../utils/isStandardSyntaxUrl'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'function-url-scheme-whitelist'; - -const messages = ruleMessages(ruleName, { - rejected: (scheme) => `Unexpected URL scheme "${scheme}:"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString, _.isRegExp], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'function-url-scheme-allowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkDecls((decl) => { - functionArgumentsSearch(decl.toString().toLowerCase(), 'url', (args, index) => { - const unspacedUrlString = _.trim(args, ' '); - - if (!isStandardSyntaxUrl(unspacedUrlString)) { - return; - } - - const urlString = _.trim(unspacedUrlString, '\'"'); - const scheme = getSchemeFromUrl(urlString); - - if (scheme === null) { - return; - } - - if (matchesStringOrRegExp(scheme, list)) { - return; - } - - report({ - message: messages.rejected(scheme), - node: decl, - index, - result, - ruleName, - }); - }); - }); - }; -} - -rule.primaryOptionArray = true; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = { deprecated: true }; - -module.exports = rule; diff --git a/lib/rules/function-whitelist/README.md b/lib/rules/function-whitelist/README.md deleted file mode 100644 index f3620b3b4b..0000000000 --- a/lib/rules/function-whitelist/README.md +++ /dev/null @@ -1,75 +0,0 @@ -# function-whitelist - -**_Deprecated: Instead use the [`function-allowed-list`](../function-allowed-list/README.md) rule._** - -Specify a list of allowed functions. - - -```css -a { transform: scale(1); } -/** ↑ - * This function */ -``` - -## Options - -`array|string`: `["array", "of", "unprefixed", /functions/ or "regex"]|"function"|"/regex/"` - -If a string is surrounded with `"/"` (e.g. `"/^rgb/"`), it is interpreted as a regular expression. - -Given: - -``` -["scale", "rgba", "linear-gradient"] -``` - -The following patterns are considered violations: - - -```css -a { transform: rotate(1); } -``` - - -```css -a { - color: hsla(170, 50%, 45%, 1) -} -``` - - -```css -a { - background: - red, - -webkit-radial-gradient(red, green, blue); -} -``` - -The following patterns are _not_ considered violations: - - -```css -a { background: red; } -``` - - -```css -a { transform: scale(1); } -``` - - -```css -a { - color: rgba(0, 0, 0, 0.5); -} -``` - - -```css -a { - background: - red, - -moz-linear-gradient(45deg, blue, red); -} -``` diff --git a/lib/rules/function-whitelist/__tests__/index.js b/lib/rules/function-whitelist/__tests__/index.js deleted file mode 100644 index 5563c23f1f..0000000000 --- a/lib/rules/function-whitelist/__tests__/index.js +++ /dev/null @@ -1,209 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['rgba'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'function-allowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - - config: ['rotate', 'rgb', 'radial-gradient', 'lightness', 'color'], - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { transform: rotate(7deg) }', - }, - { - code: 'a { background: -webkit-radial-gradient(red, green, blue); }', - }, - { - code: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - }, - { - code: '@media (max-width: 10px) { a { color: color(rgb(0, 0, 0) lightness(50%)); } }', - }, - { - code: '$list: (value, value2)', - description: 'Sass list ignored', - }, - ], - - reject: [ - { - code: 'a { transform: rOtAtE(7deg) }', - message: messages.rejected('rOtAtE'), - line: 1, - column: 16, - }, - { - code: 'a { transform: ROTATE(7deg) }', - message: messages.rejected('ROTATE'), - line: 1, - column: 16, - }, - { - code: 'a { transform: scale(1); }', - message: messages.rejected('scale'), - line: 1, - column: 16, - }, - { - code: 'a { transform: sCaLe(1); }', - message: messages.rejected('sCaLe'), - line: 1, - column: 16, - }, - { - code: 'a { transform: SCALE(1); }', - message: messages.rejected('SCALE'), - line: 1, - column: 16, - }, - { - code: 'a { transform : scale(1); }', - message: messages.rejected('scale'), - line: 1, - column: 17, - }, - { - code: 'a\n{ transform: scale(1); }', - message: messages.rejected('scale'), - line: 2, - column: 14, - }, - { - code: 'a { transform: scale(1); }', - message: messages.rejected('scale'), - line: 1, - column: 19, - }, - { - code: ' a { transform: scale(1); }', - message: messages.rejected('scale'), - line: 1, - column: 18, - }, - { - code: 'a { color: rgba(0, 0, 0, 0) }', - message: messages.rejected('rgba'), - line: 1, - column: 12, - }, - { - code: 'a { color: color(rgba(0, 0, 0, 0) lightness(50%)); }', - message: messages.rejected('rgba'), - line: 1, - column: 18, - }, - { - code: 'a { background: red, -moz-linear-gradient(45deg, blue, red); }', - message: messages.rejected('-moz-linear-gradient'), - line: 1, - column: 22, - }, - { - code: '@media (max-width: 10px) { a { color: color(rgba(0, 0, 0) lightness(50%)); } }', - message: messages.rejected('rgba'), - line: 1, - column: 45, - }, - ], -}); - -testRule({ - ruleName, - config: ['translate'], - skipBasicChecks: true, - - accept: [ - { - code: 'a { transform: translate(1px); }', - }, - ], - - reject: [ - { - code: 'a { transform: scale(4); }', - message: messages.rejected('scale'), - line: 1, - column: 16, - }, - ], -}); - -testRule({ - ruleName, - - config: ['/rgb/'], - - accept: [ - { - code: 'a { color: rgb(0, 0, 0); }', - }, - { - code: 'a { color: rgba(0, 0, 0, 0); }', - }, - ], - - reject: [ - { - code: 'a { color: hsl(208, 100%, 97%); }', - message: messages.rejected('hsl'), - line: 1, - column: 12, - }, - ], -}); - -testRule({ - ruleName, - - config: [/rgb/], - - accept: [ - { - code: 'a { color: rgb(0, 0, 0); }', - }, - { - code: 'a { color: rgba(0, 0, 0, 0); }', - }, - ], - - reject: [ - { - code: 'a { color: hsl(208, 100%, 97%); }', - message: messages.rejected('hsl'), - line: 1, - column: 12, - }, - ], -}); diff --git a/lib/rules/function-whitelist/index.js b/lib/rules/function-whitelist/index.js deleted file mode 100644 index d64abb84df..0000000000 --- a/lib/rules/function-whitelist/index.js +++ /dev/null @@ -1,73 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const isStandardSyntaxFunction = require('../../utils/isStandardSyntaxFunction'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const valueParser = require('postcss-value-parser'); -const vendor = require('../../utils/vendor'); - -const ruleName = 'function-whitelist'; - -const messages = ruleMessages(ruleName, { - rejected: (name) => `Unexpected function "${name}"`, -}); - -function rule(listInput) { - const list = [].concat(listInput); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString, _.isRegExp], - }); - - if (!validOptions) { - return; - } - - result.warn(`'${ruleName}' has been deprecated. Instead use 'function-allowed-list'.`, { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }); - - root.walkDecls((decl) => { - const value = decl.value; - - valueParser(value).walk((node) => { - if (node.type !== 'function') { - return; - } - - if (!isStandardSyntaxFunction(node)) { - return; - } - - if (matchesStringOrRegExp(vendor.unprefixed(node.value), list)) { - return; - } - - report({ - message: messages.rejected(node.value), - node: decl, - index: declarationValueIndex(decl) + node.sourceIndex, - result, - ruleName, - }); - }); - }); - }; -} - -rule.primaryOptionArray = true; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = { deprecated: true }; - -module.exports = rule; diff --git a/lib/rules/index.js b/lib/rules/index.js index b05ceeab21..4b1ef3e657 100644 --- a/lib/rules/index.js +++ b/lib/rules/index.js @@ -10,7 +10,6 @@ const importLazy = require('import-lazy'); const rules = { 'alpha-value-notation': importLazy(() => require('./alpha-value-notation'))(), 'at-rule-allowed-list': importLazy(() => require('./at-rule-allowed-list'))(), - 'at-rule-blacklist': importLazy(() => require('./at-rule-blacklist'))(), 'at-rule-disallowed-list': importLazy(() => require('./at-rule-disallowed-list'))(), 'at-rule-empty-line-before': importLazy(() => require('./at-rule-empty-line-before'))(), 'at-rule-name-case': importLazy(() => require('./at-rule-name-case'))(), @@ -20,11 +19,9 @@ const rules = { 'at-rule-no-unknown': importLazy(() => require('./at-rule-no-unknown'))(), 'at-rule-no-vendor-prefix': importLazy(() => require('./at-rule-no-vendor-prefix'))(), 'at-rule-property-required-list': importLazy(() => require('./at-rule-property-required-list'))(), - 'at-rule-property-requirelist': importLazy(() => require('./at-rule-property-requirelist'))(), 'at-rule-semicolon-newline-after': importLazy(() => require('./at-rule-semicolon-newline-after'), )(), - 'at-rule-whitelist': importLazy(() => require('./at-rule-whitelist'))(), 'block-closing-brace-empty-line-before': importLazy(() => require('./block-closing-brace-empty-line-before'), )(), @@ -63,7 +60,6 @@ const rules = { 'comment-no-empty': importLazy(() => require('./comment-no-empty'))(), 'comment-pattern': importLazy(() => require('./comment-pattern'))(), 'comment-whitespace-inside': importLazy(() => require('./comment-whitespace-inside'))(), - 'comment-word-blacklist': importLazy(() => require('./comment-word-blacklist'))(), 'comment-word-disallowed-list': importLazy(() => require('./comment-word-disallowed-list'))(), 'custom-media-pattern': importLazy(() => require('./custom-media-pattern'))(), 'custom-property-empty-line-before': importLazy(() => @@ -112,27 +108,15 @@ const rules = { 'declaration-property-unit-allowed-list': importLazy(() => require('./declaration-property-unit-allowed-list'), )(), - 'declaration-property-unit-blacklist': importLazy(() => - require('./declaration-property-unit-blacklist'), - )(), 'declaration-property-unit-disallowed-list': importLazy(() => require('./declaration-property-unit-disallowed-list'), )(), - 'declaration-property-unit-whitelist': importLazy(() => - require('./declaration-property-unit-whitelist'), - )(), 'declaration-property-value-allowed-list': importLazy(() => require('./declaration-property-value-allowed-list'), )(), - 'declaration-property-value-blacklist': importLazy(() => - require('./declaration-property-value-blacklist'), - )(), 'declaration-property-value-disallowed-list': importLazy(() => require('./declaration-property-value-disallowed-list'), )(), - 'declaration-property-value-whitelist': importLazy(() => - require('./declaration-property-value-whitelist'), - )(), 'font-family-no-missing-generic-family-keyword': importLazy(() => require('./font-family-no-missing-generic-family-keyword'), )(), @@ -140,7 +124,6 @@ const rules = { 'font-family-no-duplicate-names': importLazy(() => require('./font-family-no-duplicate-names'))(), 'font-weight-notation': importLazy(() => require('./font-weight-notation'))(), 'function-allowed-list': importLazy(() => require('./function-allowed-list'))(), - 'function-blacklist': importLazy(() => require('./function-blacklist'))(), 'function-calc-no-invalid': importLazy(() => require('./function-calc-no-invalid'))(), 'function-calc-no-unspaced-operator': importLazy(() => require('./function-calc-no-unspaced-operator'), @@ -168,13 +151,10 @@ const rules = { 'function-url-scheme-allowed-list': importLazy(() => require('./function-url-scheme-allowed-list'), )(), - 'function-url-scheme-blacklist': importLazy(() => require('./function-url-scheme-blacklist'))(), 'function-url-scheme-disallowed-list': importLazy(() => require('./function-url-scheme-disallowed-list'), )(), - 'function-url-scheme-whitelist': importLazy(() => require('./function-url-scheme-whitelist'))(), 'function-whitespace-after': importLazy(() => require('./function-whitespace-after'))(), - 'function-whitelist': importLazy(() => require('./function-whitelist'))(), 'hue-degree-notation': importLazy(() => require('./hue-degree-notation'))(), 'keyframe-declaration-no-important': importLazy(() => require('./keyframe-declaration-no-important'), @@ -194,7 +174,6 @@ const rules = { 'media-feature-name-allowed-list': importLazy(() => require('./media-feature-name-allowed-list'), )(), - 'media-feature-name-blacklist': importLazy(() => require('./media-feature-name-blacklist'))(), 'media-feature-name-case': importLazy(() => require('./media-feature-name-case'))(), 'media-feature-name-disallowed-list': importLazy(() => require('./media-feature-name-disallowed-list'), @@ -206,10 +185,6 @@ const rules = { 'media-feature-name-value-allowed-list': importLazy(() => require('./media-feature-name-value-allowed-list'), )(), - 'media-feature-name-value-whitelist': importLazy(() => - require('./media-feature-name-value-whitelist'), - )(), - 'media-feature-name-whitelist': importLazy(() => require('./media-feature-name-whitelist'))(), 'media-feature-parentheses-space-inside': importLazy(() => require('./media-feature-parentheses-space-inside'), )(), @@ -254,12 +229,10 @@ const rules = { 'number-max-precision': importLazy(() => require('./number-max-precision'))(), 'number-no-trailing-zeros': importLazy(() => require('./number-no-trailing-zeros'))(), 'property-allowed-list': importLazy(() => require('./property-allowed-list'))(), - 'property-blacklist': importLazy(() => require('./property-blacklist'))(), 'property-case': importLazy(() => require('./property-case'))(), 'property-disallowed-list': importLazy(() => require('./property-disallowed-list'))(), 'property-no-unknown': importLazy(() => require('./property-no-unknown'))(), 'property-no-vendor-prefix': importLazy(() => require('./property-no-vendor-prefix'))(), - 'property-whitelist': importLazy(() => require('./property-whitelist'))(), 'rule-empty-line-before': importLazy(() => require('./rule-empty-line-before'))(), 'selector-attribute-brackets-space-inside': importLazy(() => require('./selector-attribute-brackets-space-inside'), @@ -270,9 +243,6 @@ const rules = { 'selector-attribute-operator-allowed-list': importLazy(() => require('./selector-attribute-operator-allowed-list'), )(), - 'selector-attribute-operator-blacklist': importLazy(() => - require('./selector-attribute-operator-blacklist'), - )(), 'selector-attribute-operator-disallowed-list': importLazy(() => require('./selector-attribute-operator-disallowed-list'), )(), @@ -282,15 +252,11 @@ const rules = { 'selector-attribute-operator-space-before': importLazy(() => require('./selector-attribute-operator-space-before'), )(), - 'selector-attribute-operator-whitelist': importLazy(() => - require('./selector-attribute-operator-whitelist'), - )(), 'selector-attribute-quotes': importLazy(() => require('./selector-attribute-quotes'))(), 'selector-class-pattern': importLazy(() => require('./selector-class-pattern'))(), 'selector-combinator-allowed-list': importLazy(() => require('./selector-combinator-allowed-list'), )(), - 'selector-combinator-blacklist': importLazy(() => require('./selector-combinator-blacklist'))(), 'selector-combinator-disallowed-list': importLazy(() => require('./selector-combinator-disallowed-list'), )(), @@ -300,7 +266,6 @@ const rules = { 'selector-combinator-space-before': importLazy(() => require('./selector-combinator-space-before'), )(), - 'selector-combinator-whitelist': importLazy(() => require('./selector-combinator-whitelist'))(), 'selector-descendant-combinator-no-non-space': importLazy(() => require('./selector-descendant-combinator-no-non-space'), )(), @@ -336,9 +301,6 @@ const rules = { 'selector-pseudo-class-allowed-list': importLazy(() => require('./selector-pseudo-class-allowed-list'), )(), - 'selector-pseudo-class-blacklist': importLazy(() => - require('./selector-pseudo-class-blacklist'), - )(), 'selector-pseudo-class-case': importLazy(() => require('./selector-pseudo-class-case'))(), 'selector-pseudo-class-disallowed-list': importLazy(() => require('./selector-pseudo-class-disallowed-list'), @@ -349,15 +311,9 @@ const rules = { 'selector-pseudo-class-parentheses-space-inside': importLazy(() => require('./selector-pseudo-class-parentheses-space-inside'), )(), - 'selector-pseudo-class-whitelist': importLazy(() => - require('./selector-pseudo-class-whitelist'), - )(), 'selector-pseudo-element-allowed-list': importLazy(() => require('./selector-pseudo-element-allowed-list'), )(), - 'selector-pseudo-element-blacklist': importLazy(() => - require('./selector-pseudo-element-blacklist'), - )(), 'selector-pseudo-element-case': importLazy(() => require('./selector-pseudo-element-case'))(), 'selector-pseudo-element-colon-notation': importLazy(() => require('./selector-pseudo-element-colon-notation'), @@ -368,9 +324,6 @@ const rules = { 'selector-pseudo-element-no-unknown': importLazy(() => require('./selector-pseudo-element-no-unknown'), )(), - 'selector-pseudo-element-whitelist': importLazy(() => - require('./selector-pseudo-element-whitelist'), - )(), 'selector-type-case': importLazy(() => require('./selector-type-case'))(), 'selector-type-no-unknown': importLazy(() => require('./selector-type-no-unknown'))(), 'shorthand-property-no-redundant-values': importLazy(() => @@ -381,11 +334,9 @@ const rules = { 'time-min-milliseconds': importLazy(() => require('./time-min-milliseconds'))(), 'unicode-bom': importLazy(() => require('./unicode-bom'))(), 'unit-allowed-list': importLazy(() => require('./unit-allowed-list'))(), - 'unit-blacklist': importLazy(() => require('./unit-blacklist'))(), 'unit-case': importLazy(() => require('./unit-case'))(), 'unit-disallowed-list': importLazy(() => require('./unit-disallowed-list'))(), 'unit-no-unknown': importLazy(() => require('./unit-no-unknown'))(), - 'unit-whitelist': importLazy(() => require('./unit-whitelist'))(), 'value-keyword-case': importLazy(() => require('./value-keyword-case'))(), 'value-list-comma-newline-after': importLazy(() => require('./value-list-comma-newline-after'))(), 'value-list-comma-newline-before': importLazy(() => diff --git a/lib/rules/media-feature-name-blacklist/README.md b/lib/rules/media-feature-name-blacklist/README.md deleted file mode 100644 index e89f5753cf..0000000000 --- a/lib/rules/media-feature-name-blacklist/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# media-feature-name-blacklist - -**_Deprecated: Instead use the [`media-feature-name-disallowed-list`](../media-feature-name-disallowed-list/README.md) rule._** - -Specify a list of disallowed media feature names. - - -```css -@media (min-width: 700px) {} -/** ↑ - * This media feature name */ -``` - -## Options - -`array|string|regex`: `["array", "of", "unprefixed", /media-features/ or "regex"]|"media-feature"|/regex/` - -Given: - -``` -["max-width", "/^my-/"] -``` - -The following patterns are considered violations: - - -```css -@media (max-width: 50em) {} -``` - - -```css -@media (my-width: 50em) {} -``` - - -```css -@media (max-width < 50em) {} -``` - - -```css -@media (10em < my-height < 50em) {} -``` - -The following patterns are _not_ considered violations: - - -```css -@media (min-width: 50em) {} -``` - - -```css -@media print and (min-resolution: 300dpi) {} -``` - - -```css -@media (min-width >= 50em) {} -``` - - -```css -@media (10em < width < 50em) {} -``` diff --git a/lib/rules/media-feature-name-blacklist/__tests__/index.js b/lib/rules/media-feature-name-blacklist/__tests__/index.js deleted file mode 100644 index 62855b5924..0000000000 --- a/lib/rules/media-feature-name-blacklist/__tests__/index.js +++ /dev/null @@ -1,233 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['max-width'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'media-feature-name-disallowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -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'], - - accept: [ - { - code: '@media (min-width: 50em) { }', - }, - { - code: '@media (MaX-wIdTh: 50em) { }', - }, - { - code: '@media (MiN-wIdTh: 50em) { }', - }, - { - code: '@media (height <= 50em) { }', - }, - { - code: '@media (400px < height < 1000px) { }', - }, - { - code: '@media (--wide-viewport) { }', - description: 'ignore custom media query', - }, - { - code: '@media (/* max-width: 50em */ min-width: 50em) { }', - description: 'ignore comments', - }, - { - code: '@media (monochrome) { }', - description: 'boolean feature name', - }, - ], - - reject: [ - { - code: '@media (max-width: 50em) { }', - message: messages.rejected('max-width'), - line: 1, - column: 9, - }, - { - code: '@media print and (max-width: 50em) { }', - message: messages.rejected('max-width'), - line: 1, - column: 19, - }, - { - code: '@media handheld and (min-width: 20em), screen and (max-width: 20em) { }', - message: messages.rejected('max-width'), - line: 1, - column: 52, - }, - { - code: '@media (my-width: 50em) { }', - message: messages.rejected('my-width'), - line: 1, - column: 9, - }, - { - code: '@media (color) { }', - message: messages.rejected('color'), - line: 1, - column: 9, - }, - { - code: '@media (width: 50em) { }', - message: messages.rejected('width'), - line: 1, - column: 9, - }, - { - code: '@media (20em < width <= 50em) { }', - message: messages.rejected('width'), - line: 1, - column: 16, - }, - { - code: '@media (10em < max-width <= 50em) and (width > 50em) { }', - warnings: [ - { - message: messages.rejected('max-width'), - line: 1, - column: 16, - }, - { - message: messages.rejected('width'), - line: 1, - column: 40, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: [/^my-/], - - accept: [ - { - code: '@media (min-width: 50em) { }', - }, - ], - - reject: [ - { - code: '@media (my-width: 50em) { }', - message: messages.rejected('my-width'), - line: 1, - column: 9, - }, - { - code: '@media (my-width >= 50em) { }', - message: messages.rejected('my-width'), - line: 1, - column: 9, - }, - { - code: '@media (10em < my-width <= 50em) { }', - message: messages.rejected('my-width'), - line: 1, - column: 16, - }, - { - code: '@media (50em < my-width) { }', - message: messages.rejected('my-width'), - line: 1, - column: 16, - }, - ], -}); - -testRule({ - ruleName, - config: ['feature-name'], - syntax: 'less', - - accept: [ - { - code: '@media @feature-name and (orientation: landscape) { }', - }, - { - code: '@media @feature-name { }', - }, - ], -}); - -testRule({ - ruleName, - config: ['feature-name', 'width'], - syntax: 'scss', - - accept: [ - { - code: '@media not all and ($feature-name) { }', - }, - { - code: '@media not all and ($FEATURE-NAME) { }', - }, - { - code: '@media not all and (#{feature-name}) { }', - }, - { - code: '@media not all and (#{FEATURE-NAME}) { }', - }, - { - code: '@media ($feature-name: $value) { }', - }, - { - code: '@media ($FEATURE-NAME: $value) { }', - }, - { - code: '@media (#{$feature-name}: $value) { }', - }, - { - code: '@media (#{$FEATURE-NAME}: $value) { }', - }, - { - code: "@media ('min-' + $width: $value) { }", - }, - { - code: "@media ('MIN-' + $WIDTH: $value) { }", - }, - { - code: "@media ($value + 'width': $value) { }", - }, - { - code: "@media ($VALUE + 'WIDTH': $value) { }", - }, - { - code: '@media (#{$width}: $value) { }', - }, - { - code: '@media (#{$WIDTH}: $value) { }', - }, - { - code: '@media #{$feature-name} { }', - }, - ], -}); diff --git a/lib/rules/media-feature-name-blacklist/index.js b/lib/rules/media-feature-name-blacklist/index.js deleted file mode 100644 index 7dba881daa..0000000000 --- a/lib/rules/media-feature-name-blacklist/index.js +++ /dev/null @@ -1,86 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const isCustomMediaQuery = require('../../utils/isCustomMediaQuery'); -const isRangeContextMediaFeature = require('../../utils/isRangeContextMediaFeature'); -const isStandardSyntaxMediaFeatureName = require('../../utils/isStandardSyntaxMediaFeatureName'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const mediaParser = require('postcss-media-query-parser').default; -const rangeContextNodeParser = require('../rangeContextNodeParser'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'media-feature-name-blacklist'; - -const messages = ruleMessages(ruleName, { - rejected: (name) => `Unexpected media feature name "${name}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString, _.isRegExp], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'media-feature-name-disallowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkAtRules(/^media$/i, (atRule) => { - mediaParser(atRule.params).walk(/^media-feature$/i, (mediaFeatureNode) => { - const parent = mediaFeatureNode.parent; - const mediaFeatureRangeContext = isRangeContextMediaFeature(parent.value); - - let value; - let sourceIndex; - - if (mediaFeatureRangeContext) { - const parsedRangeContext = rangeContextNodeParser(mediaFeatureNode); - - value = parsedRangeContext.name.value; - sourceIndex = parsedRangeContext.name.sourceIndex; - } else { - value = mediaFeatureNode.value; - sourceIndex = mediaFeatureNode.sourceIndex; - } - - if (!isStandardSyntaxMediaFeatureName(value) || isCustomMediaQuery(value)) { - return; - } - - if (!matchesStringOrRegExp(value, list)) { - return; - } - - report({ - index: atRuleParamIndex(atRule) + sourceIndex, - message: messages.rejected(value), - node: atRule, - ruleName, - result, - }); - }); - }); - }; -} - -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/README.md b/lib/rules/media-feature-name-value-whitelist/README.md deleted file mode 100644 index 3a975e64d7..0000000000 --- a/lib/rules/media-feature-name-value-whitelist/README.md +++ /dev/null @@ -1,86 +0,0 @@ -# media-feature-name-value-whitelist - -**_Deprecated: Instead use the [`media-feature-name-value-allowed-list`](../media-feature-name-value-allowed-list/README.md) rule._** - -Specify a list of allowed media feature name and value pairs. - - -```css -@media screen and (min-width: 768px) {} -/** ↑ ↑ - * These features and values */ -``` - -## Options - -```js -{ - "unprefixed-media-feature-name": ["array", "of", "values"], - "/unprefixed-media-feature-name/": ["/regex/", "non-regex", /real-regex/] -} -``` - -If a media feature name is found in the object, only its allowed-listed values are -allowed. If the media feature name is not included in the object, anything goes. - -If a name or value is surrounded with `/` (e.g. `"/width$/"`), it is interpreted -as a regular expression. For example, `/width$/` will match `max-width` and -`min-width`. - -Given: - -``` -{ - "min-width": ["768px", "1024px"], - "/resolution/": ["/dpcm$/"] -} -``` - -The following patterns are considered violations: - - -```css -@media screen and (min-width: 1000px) {} -``` - - -```css -@media screen and (min-resolution: 2dpi) {} -``` - - -```css -@media screen and (min-width > 1000px) {} -``` - -The following patterns are _not_ considered violations: - - -```css -@media screen and (min-width: 768px) {} -``` - - -```css -@media screen and (min-width: 1024px) {} -``` - - -```css -@media screen and (orientation: portrait) {} -``` - - -```css -@media screen and (min-resolution: 2dpcm) {} -``` - - -```css -@media screen and (resolution: 10dpcm) {} -``` - - -```css -@media screen and (768px < min-width) {} -``` diff --git a/lib/rules/media-feature-name-value-whitelist/__tests__/index.js b/lib/rules/media-feature-name-value-whitelist/__tests__/index.js deleted file mode 100644 index 4aadec3d88..0000000000 --- a/lib/rules/media-feature-name-value-whitelist/__tests__/index.js +++ /dev/null @@ -1,200 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: [{ color: [] }], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'media-feature-name-value-allowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - config: [ - { - 'min-width': ['768px', '$sm'], - '/resolution/': ['/dpcm$/'], // Only dpcm unit - color: [], // Test boolean context - width: [], // Test range context - }, - ], - - accept: [ - { - code: '@media screen and (min-width: 768px) {}', - description: 'Specified media feature', - }, - { - code: '@media screen and ( min-width : 768px ) {}', - description: 'Whitespace', - }, - { - code: '@media screen and (max-width: 1000px) {}', - description: 'Unspecified media feature', - }, - { - code: '@media screen and ( min-resolution : 2dpcm ) {}', - description: 'Regex feature name and Regex value', - }, - { - code: '@media screen and (resolution: 10.1dpcm) {}', - description: 'Floating point value', - }, - { - code: '@media screen and (min-width: $sm) {}', - description: 'Non-standard syntax in allowed list', - }, - { - code: '@media (color) {}', - description: 'Boolean context, media feature in allowed list', - }, - { - code: '@media (update) {}', - description: 'Boolean context, media feature NOT in allowed list', - }, - { - code: '@media (update /* pw:ned */) {}', - description: 'Boolean context with colon in comments', - }, - { - code: '@media screen and (min-width <= 768px) {}', - description: 'Range context, media feature in allowed list', - }, - ], - - reject: [ - { - code: '@media screen and (min-width: 1000px) {}', - message: messages.rejected('min-width', '1000px'), - line: 1, - column: 31, - }, - { - code: '@media screen (min-width: 768px) and (min-width: 1000px) {}', - description: 'Media feature multiple', - message: messages.rejected('min-width', '1000px'), - line: 1, - column: 50, - }, - { - code: '@media screen (min-width: 768px)\nand (min-width: 1000px) {}', - description: 'Media feature multiline', - message: messages.rejected('min-width', '1000px'), - line: 2, - column: 17, - }, - { - code: '@media screen and (min-width: 768PX) {}', - description: 'Case sensitive', - message: messages.rejected('min-width', '768PX'), - line: 1, - column: 31, - }, - { - code: '@media screen and (min-width: $md) {}', - description: 'Non-standard syntax NOT in allowed list', - message: messages.rejected('min-width', '$md'), - line: 1, - column: 31, - }, - { - code: '@media screen and (min-resolution: 2dpi) {}', - message: messages.rejected('min-resolution', '2dpi'), - line: 1, - column: 37, - }, - { - code: '@media screen and (min-width > 500px) {}', - message: messages.rejected('min-width', '500px'), - line: 1, - column: 32, - }, - { - code: '@media screen and (400px < min-width) {}', - message: messages.rejected('min-width', '400px'), - line: 1, - column: 20, - }, - { - code: '@media (400px < min-width < 500px) and (min-width < 1200px)', - warnings: [ - { - message: messages.rejected('min-width', '400px'), - line: 1, - column: 9, - }, - { - message: messages.rejected('min-width', '500px'), - line: 1, - column: 29, - }, - { - message: messages.rejected('min-width', '1200px'), - line: 1, - column: 53, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: [ - { - '/resolution/': [/dpcm$/], // Only dpcm unit - }, - ], - - accept: [ - { - code: '@media screen and (min-width: 768px) {}', - description: 'Specified media feature', - }, - { - code: '@media screen and ( min-resolution : 2dpcm ) {}', - description: 'Regex feature name and Regex value', - }, - { - code: '@media screen and (resolution: 10.1dpcm) {}', - description: 'Floating point value', - }, - ], - - reject: [ - { - code: '@media screen and (min-resolution: 2dpi) {}', - message: messages.rejected('min-resolution', '2dpi'), - line: 1, - column: 37, - }, - { - code: '@media screen and (min-resolution > 2dpi) {}', - message: messages.rejected('min-resolution', '2dpi'), - line: 1, - column: 38, - }, - ], -}); diff --git a/lib/rules/media-feature-name-value-whitelist/index.js b/lib/rules/media-feature-name-value-whitelist/index.js deleted file mode 100644 index c410017924..0000000000 --- a/lib/rules/media-feature-name-value-whitelist/index.js +++ /dev/null @@ -1,99 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const isRangeContextMediaFeature = require('../../utils/isRangeContextMediaFeature'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const mediaParser = require('postcss-media-query-parser').default; -const rangeContextNodeParser = require('../rangeContextNodeParser'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const vendor = require('../../utils/vendor'); - -const ruleName = 'media-feature-name-value-whitelist'; - -const messages = ruleMessages(ruleName, { - rejected: (name, value) => `Unexpected value "${value}" for name "${name}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isObject], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'media-feature-name-value-allowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkAtRules(/^media$/i, (atRule) => { - mediaParser(atRule.params).walk(/^media-feature-expression$/i, (node) => { - const mediaFeatureRangeContext = isRangeContextMediaFeature(node.parent.value); - - // Ignore boolean - if (!node.value.includes(':') && !mediaFeatureRangeContext) { - return; - } - - const mediaFeatureNode = _.find(node.nodes, { type: 'media-feature' }); - - let mediaFeatureName; - let values = []; - - if (mediaFeatureRangeContext) { - const parsedRangeContext = rangeContextNodeParser(mediaFeatureNode); - - mediaFeatureName = parsedRangeContext.name.value; - values = parsedRangeContext.values; - } else { - mediaFeatureName = mediaFeatureNode.value; - values.push(_.find(node.nodes, { type: 'value' })); - } - - for (let i = 0; i < values.length; i++) { - const valueNode = values[i]; - const value = valueNode.value; - const unprefixedMediaFeatureName = vendor.unprefixed(mediaFeatureName); - - const allowedValues = _.find(list, (v, featureName) => - matchesStringOrRegExp(unprefixedMediaFeatureName, featureName), - ); - - if (allowedValues === undefined) { - return; - } - - if (matchesStringOrRegExp(value, allowedValues)) { - return; - } - - report({ - index: atRuleParamIndex(atRule) + valueNode.sourceIndex, - message: messages.rejected(mediaFeatureName, value), - node: atRule, - ruleName, - result, - }); - } - }); - }); - }; -} - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = { deprecated: true }; - -module.exports = rule; diff --git a/lib/rules/media-feature-name-whitelist/README.md b/lib/rules/media-feature-name-whitelist/README.md deleted file mode 100644 index 292ab9afe9..0000000000 --- a/lib/rules/media-feature-name-whitelist/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# media-feature-name-whitelist - -**_Deprecated: Instead use the [`media-feature-name-allowed-list`](../media-feature-name-allowed-list/README.md) rule._** - -Specify a list of allowed media feature names. - - -```css -@media (min-width: 700px) {} -/** ↑ - * This media feature name */ -``` - -## Options - -`array|string|regex`: `["array", "of", "unprefixed", /media-features/ or "regex"]|"media-feature"|/regex/` - -Given: - -``` -["max-width", "/^my-/"] -``` - -The following patterns are considered violations: - - -```css -@media (min-width: 50em) {} -``` - - -```css -@media print and (min-resolution: 300dpi) {} -``` - - -```css -@media (min-width < 50em) {} -``` - - -```css -@media (10em < min-width < 50em) {} -``` - -The following patterns are _not_ considered violations: - - -```css -@media (max-width: 50em) {} -``` - - -```css -@media (my-width: 50em) {} -``` - - -```css -@media (max-width > 50em) {} -``` - - -```css -@media (10em < my-width < 50em) {} -``` diff --git a/lib/rules/media-feature-name-whitelist/__tests__/index.js b/lib/rules/media-feature-name-whitelist/__tests__/index.js deleted file mode 100644 index b711d1cbbb..0000000000 --- a/lib/rules/media-feature-name-whitelist/__tests__/index.js +++ /dev/null @@ -1,223 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['max-width'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'media-feature-name-allowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -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'], - - accept: [ - { - code: '@media (max-width: 50em) { }', - }, - { - code: '@media (--wide-viewport) { }', - description: 'ignore custom media query', - }, - { - code: '@media (/* min-width: 50em */ max-width: 50em) { }', - description: 'ignore comments', - }, - { - code: '@media (max-width <= 50em) { }', - }, - { - code: '@media (400px < my-width < 1000px) { }', - }, - { - code: '@media (my-width: 50em) { }', - }, - { - code: '@media (my-max-width: 50em) { }', - }, - { - code: '@media print and (max-width: 50em) { }', - }, - { - code: '@media (color) { }', - }, - ], - - reject: [ - { - code: '@media (MaX-wIdTh: 50em) { }', - message: messages.rejected('MaX-wIdTh'), - line: 1, - column: 9, - }, - { - code: '@media (min-width: 50em) { }', - message: messages.rejected('min-width'), - line: 1, - column: 9, - }, - { - code: '@media (-webkit-min-device-pixel-ratio: 2) { }', - message: messages.rejected('-webkit-min-device-pixel-ratio'), - line: 1, - column: 9, - }, - { - code: '@media handheld and (max-width: 20em), screen and (min-width: 20em) { }', - message: messages.rejected('min-width'), - line: 1, - column: 52, - }, - { - code: '@media (monochrome) { }', - message: messages.rejected('monochrome'), - line: 1, - column: 9, - }, - { - code: '@media (width: 50em) { }', - message: messages.rejected('width'), - line: 1, - column: 9, - }, - { - code: '@media (50em < width) { }', - message: messages.rejected('width'), - line: 1, - column: 16, - }, - { - code: '@media (10em < width <= 50em) { }', - message: messages.rejected('width'), - line: 1, - column: 16, - }, - { - code: '@media (max-width <= 50em) and (10em < min-width < 50em) { }', - message: messages.rejected('min-width'), - line: 1, - column: 40, - }, - ], -}); - -testRule({ - ruleName, - config: [/^my-/], - - accept: [ - { - code: '@media (my-width: 50em) { }', - }, - { - code: '@media (my-max-width: 50em) { }', - }, - { - code: '@media (my-width >= 50em) { }', - }, - { - code: '@media (10em < my-max-width <= 50em) { }', - }, - ], - - reject: [ - { - code: '@media (MaX-wIdTh: 50em) { }', - message: messages.rejected('MaX-wIdTh'), - line: 1, - column: 9, - }, - ], -}); - -testRule({ - ruleName, - config: ['max-width', 'orientation'], - syntax: 'less', - - accept: [ - { - code: '@media @feature-name and (orientation: landscape) { }', - }, - { - code: '@media @feature-name { }', - }, - ], -}); - -testRule({ - ruleName, - config: ['max-width'], - syntax: 'scss', - - accept: [ - { - code: '@media not all and ($feature-name) { }', - }, - { - code: '@media not all and ($FEATURE-NAME) { }', - }, - { - code: '@media not all and (#{feature-name}) { }', - }, - { - code: '@media not all and (#{FEATURE-NAME}) { }', - }, - { - code: '@media ($feature-name: $value) { }', - }, - { - code: '@media ($FEATURE-NAME: $value) { }', - }, - { - code: '@media (#{$feature-name}: $value) { }', - }, - { - code: '@media (#{$FEATURE-NAME}: $value) { }', - }, - { - code: "@media ('min-' + $width: $value) { }", - }, - { - code: "@media ('MIN-' + $WIDTH: $value) { }", - }, - { - code: "@media ($value + 'width': $value) { }", - }, - { - code: "@media ($VALUE + 'WIDTH': $value) { }", - }, - { - code: '@media (#{$width}: $value) { }', - }, - { - code: '@media (#{$WIDTH}: $value) { }', - }, - { - code: '@media #{$feature-name} { }', - }, - ], -}); diff --git a/lib/rules/media-feature-name-whitelist/index.js b/lib/rules/media-feature-name-whitelist/index.js deleted file mode 100644 index 6dfcb91ee8..0000000000 --- a/lib/rules/media-feature-name-whitelist/index.js +++ /dev/null @@ -1,86 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const isCustomMediaQuery = require('../../utils/isCustomMediaQuery'); -const isRangeContextMediaFeature = require('../../utils/isRangeContextMediaFeature'); -const isStandardSyntaxMediaFeatureName = require('../../utils/isStandardSyntaxMediaFeatureName'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const mediaParser = require('postcss-media-query-parser').default; -const rangeContextNodeParser = require('../rangeContextNodeParser'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'media-feature-name-whitelist'; - -const messages = ruleMessages(ruleName, { - rejected: (name) => `Unexpected media feature name "${name}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString, _.isRegExp], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'media-feature-name-allowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkAtRules(/^media$/i, (atRule) => { - mediaParser(atRule.params).walk(/^media-feature$/i, (mediaFeatureNode) => { - const parent = mediaFeatureNode.parent; - const mediaFeatureRangeContext = isRangeContextMediaFeature(parent.value); - - let value; - let sourceIndex; - - if (mediaFeatureRangeContext) { - const parsedRangeContext = rangeContextNodeParser(mediaFeatureNode); - - value = parsedRangeContext.name.value; - sourceIndex = parsedRangeContext.name.sourceIndex; - } else { - value = mediaFeatureNode.value; - sourceIndex = mediaFeatureNode.sourceIndex; - } - - if (!isStandardSyntaxMediaFeatureName(value) || isCustomMediaQuery(value)) { - return; - } - - if (matchesStringOrRegExp(value, list)) { - return; - } - - report({ - index: atRuleParamIndex(atRule) + sourceIndex, - message: messages.rejected(value), - node: atRule, - ruleName, - result, - }); - }); - }); - }; -} - -rule.primaryOptionArray = true; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = { deprecated: true }; - -module.exports = rule; diff --git a/lib/rules/property-blacklist/README.md b/lib/rules/property-blacklist/README.md deleted file mode 100644 index b244fb8584..0000000000 --- a/lib/rules/property-blacklist/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# property-blacklist - -**_Deprecated: Instead use the [`property-disallowed-list`](../property-disallowed-list/README.md) rule._** - -Specify a list of disallowed properties. - - -```css -a { text-rendering: optimizeLegibility; } -/** ↑ - * This property */ -``` - -## Options - -`array|string`: `["array", "of", "unprefixed", /properties/ or "regex"]|"property"|"/regex/"`|/regex/ - -If a string is surrounded with `"/"` (e.g. `"/^background/"`), it is interpreted as a regular expression. This allows, for example, easy targeting of shorthands: `/^background/` will match `background`, `background-size`, `background-color`, etc. - -Given: - -``` -["text-rendering", "animation", "/^background/"] -``` - -The following patterns are considered violations: - - -```css -a { text-rendering: optimizeLegibility; } -``` - - -```css -a { - animation: my-animation 2s; - color: pink; -} -``` - - -```css -a { -webkit-animation: my-animation 2s; } -``` - - -```css -a { background: pink; } -``` - - -```css -a { background-size: cover; } -``` - -The following patterns are _not_ considered violations: - - -```css -a { color: pink; } -``` - - -```css -a { no-background: sure; } -``` diff --git a/lib/rules/property-blacklist/__tests__/index.js b/lib/rules/property-blacklist/__tests__/index.js deleted file mode 100644 index 208fc96dc5..0000000000 --- a/lib/rules/property-blacklist/__tests__/index.js +++ /dev/null @@ -1,187 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: [], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'property-disallowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - - config: [''], - - accept: [ - { - code: 'a { color: pink; }', - }, - ], -}); - -testRule({ - ruleName, - - config: [[]], - - accept: [ - { - code: 'a { color: pink; }', - }, - ], -}); - -testRule({ - ruleName, - - config: ['transform', 'background-size'], - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { background: red; }', - }, - { - code: 'a { top: 0; color: pink; }', - }, - { - code: 'a { $scss: 0; }', - }, - { - code: 'a { @less: 0; }', - }, - { - code: 'a { --custom-property: 0; }', - }, - ], - - reject: [ - { - code: 'a { transform: scale(1); }', - message: messages.rejected('transform'), - line: 1, - column: 5, - }, - { - code: 'a { color: pink; background-size: cover; }', - message: messages.rejected('background-size'), - line: 1, - column: 18, - }, - { - code: 'a { color: pink; -webkit-transform: scale(1); }', - message: messages.rejected('-webkit-transform'), - line: 1, - column: 18, - }, - ], -}); - -testRule({ - ruleName, - - config: [['/^background/']], - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { no-background: sure; }', - }, - { - code: 'a { $scss: 0; }', - }, - { - code: 'a { @less: 0; }', - }, - { - code: 'a { --custom-property: 0; }', - }, - ], - - reject: [ - { - code: 'a { background: pink; }', - message: messages.rejected('background'), - line: 1, - column: 5, - }, - { - code: 'a { background-size: cover; }', - message: messages.rejected('background-size'), - line: 1, - column: 5, - }, - { - code: 'a { background-image: none; }', - message: messages.rejected('background-image'), - line: 1, - column: 5, - }, - ], -}); - -testRule({ - ruleName, - - config: [[/^background/]], - - accept: [ - { - code: 'a { color: pink; }', - }, - ], - - reject: [ - { - code: 'a { background-size: cover; }', - message: messages.rejected('background-size'), - line: 1, - column: 5, - }, - ], -}); - -testRule({ - ruleName, - - config: ['/margin/'], - - accept: [ - { - code: 'a { $margin: 0; }', - }, - { - code: 'a { @margin: 0; }', - }, - { - code: 'a { --margin: 0; }', - }, - ], -}); diff --git a/lib/rules/property-blacklist/index.js b/lib/rules/property-blacklist/index.js deleted file mode 100644 index f1584acf86..0000000000 --- a/lib/rules/property-blacklist/index.js +++ /dev/null @@ -1,67 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const isCustomProperty = require('../../utils/isCustomProperty'); -const isStandardSyntaxProperty = require('../../utils/isStandardSyntaxProperty'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const vendor = require('../../utils/vendor'); - -const ruleName = 'property-blacklist'; - -const messages = ruleMessages(ruleName, { - rejected: (property) => `Unexpected property "${property}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString, _.isRegExp], - }); - - if (!validOptions) { - return; - } - - result.warn(`'${ruleName}' has been deprecated. Instead use 'property-disallowed-list'.`, { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }); - - root.walkDecls((decl) => { - const prop = decl.prop; - - if (!isStandardSyntaxProperty(prop)) { - return; - } - - if (isCustomProperty(prop)) { - return; - } - - if (!matchesStringOrRegExp(vendor.unprefixed(prop), list)) { - return; - } - - report({ - message: messages.rejected(prop), - node: decl, - result, - ruleName, - }); - }); - }; -} - -rule.primaryOptionArray = true; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = { deprecated: true }; - -module.exports = rule; diff --git a/lib/rules/property-whitelist/README.md b/lib/rules/property-whitelist/README.md deleted file mode 100644 index 1500c0ca19..0000000000 --- a/lib/rules/property-whitelist/README.md +++ /dev/null @@ -1,77 +0,0 @@ -# property-whitelist - -**_Deprecated: Instead use the [`property-allowed-list`](../property-allowed-list/README.md) rule._** - -Specify a list of allowed properties. - - -```css -a { display: block; } -/** ↑ - * This property */ -``` - -This rule ignores variables (`$sass`, `@less`, `--custom-property`). - -## Options - -`array|string`: `["array", "of", "unprefixed", /properties/ or "regex"]|"property"|"/regex/"`|/regex/ - -If a string is surrounded with `"/"` (e.g. `"/^background/"`), it is interpreted as a regular expression. This allows, for example, easy targeting of shorthands: `/^background/` will match `background`, `background-size`, `background-color`, etc. - -Given: - -``` -["display", "animation", "/^background/"] -``` - -The following patterns are considered violations: - - -```css -a { color: pink; } -``` - - -```css -a { - animation: my-animation 2s; - color: pink; -} -``` - - -```css -a { borkgrund: orange; } -``` - -The following patterns are _not_ considered violations: - - -```css -a { display: block; } -``` - - -```css -a { -webkit-animation: my-animation 2s; } -``` - - -```css -a { - animation: my-animation 2s; - -webkit-animation: my-animation 2s; - display: block; -} -``` - - -```css -a { background: pink; } -``` - - -```css -a { background-color: pink; } -``` diff --git a/lib/rules/property-whitelist/__tests__/index.js b/lib/rules/property-whitelist/__tests__/index.js deleted file mode 100644 index f66c7fea86..0000000000 --- a/lib/rules/property-whitelist/__tests__/index.js +++ /dev/null @@ -1,196 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: [], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'property-allowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - - config: [''], - - reject: [ - { - code: 'a { color: pink; }', - message: messages.rejected('color'), - line: 1, - column: 5, - }, - ], -}); - -testRule({ - ruleName, - - config: [[]], - - reject: [ - { - code: 'a { color: pink; }', - message: messages.rejected('color'), - line: 1, - column: 5, - }, - ], -}); - -testRule({ - ruleName, - - config: ['transform', 'background-size'], - - accept: [ - { - code: 'a { background-size: cover; }', - }, - { - code: 'a { transform: scale(1); }', - }, - { - code: 'a { -webkit-transform: scale(1); }', - }, - { - code: 'a { transform: scale(1); background-size: cover; }', - }, - { - code: 'a { transform: scale(1); -webkit-transform: scale(1); background-size: cover; }', - }, - { - code: 'a { $scss: 0; }', - }, - { - code: 'a { @less: 0; }', - }, - { - code: 'a { --custom-property: 0; }', - }, - ], - - reject: [ - { - code: 'a { background: pink; }', - message: messages.rejected('background'), - line: 1, - column: 5, - }, - { - code: 'a { color: pink; }', - message: messages.rejected('color'), - line: 1, - column: 5, - }, - { - code: 'a { overflow: hidden; background-size: cover; }', - message: messages.rejected('overflow'), - line: 1, - column: 5, - }, - { - code: 'a { color: orange; -webkit-transform: scale(1); }', - message: messages.rejected('color'), - line: 1, - column: 5, - }, - ], -}); - -testRule({ - ruleName, - - config: [['/^background/']], - - accept: [ - { - code: 'a { background: pink; }', - }, - { - code: 'a { background-color: pink; }', - }, - { - code: 'a { background-image: none; }', - }, - { - code: 'a { $scss: 0; }', - }, - { - code: 'a { @less: 0; }', - }, - { - code: 'a { --custom-property: 0; }', - }, - ], - - reject: [ - { - code: 'a { color: pink; }', - message: messages.rejected('color'), - line: 1, - column: 5, - }, - ], -}); - -testRule({ - ruleName, - - config: [[/^background/]], - - accept: [ - { - code: 'a { background-image: none; }', - }, - ], - - reject: [ - { - code: 'a { color: pink; }', - message: messages.rejected('color'), - line: 1, - column: 5, - }, - ], -}); - -testRule({ - ruleName, - - config: ['/margin/'], - - accept: [ - { - code: 'a { $padding: 0; }', - }, - { - code: 'a { @padding: 0; }', - }, - { - code: 'a { --padding: 0; }', - }, - ], -}); diff --git a/lib/rules/property-whitelist/index.js b/lib/rules/property-whitelist/index.js deleted file mode 100644 index 65904a4664..0000000000 --- a/lib/rules/property-whitelist/index.js +++ /dev/null @@ -1,67 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const isCustomProperty = require('../../utils/isCustomProperty'); -const isStandardSyntaxProperty = require('../../utils/isStandardSyntaxProperty'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const vendor = require('../../utils/vendor'); - -const ruleName = 'property-whitelist'; - -const messages = ruleMessages(ruleName, { - rejected: (property) => `Unexpected property "${property}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString, _.isRegExp], - }); - - if (!validOptions) { - return; - } - - result.warn(`'${ruleName}' has been deprecated. Instead use 'property-allowed-list'.`, { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }); - - root.walkDecls((decl) => { - const prop = decl.prop; - - if (!isStandardSyntaxProperty(prop)) { - return; - } - - if (isCustomProperty(prop)) { - return; - } - - if (matchesStringOrRegExp(vendor.unprefixed(prop), list)) { - return; - } - - report({ - message: messages.rejected(prop), - node: decl, - result, - ruleName, - }); - }); - }; -} - -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/README.md b/lib/rules/selector-attribute-operator-blacklist/README.md deleted file mode 100644 index f3e54f4629..0000000000 --- a/lib/rules/selector-attribute-operator-blacklist/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# selector-attribute-operator-blacklist - -**_Deprecated: Instead use the [`selector-attribute-operator-disallowed-list`](../selector-attribute-operator-disallowed-list/README.md) rule._** - -Specify a list of disallowed attribute operators. - - -```css -[target="_blank"] {} -/** ↑ - * This operator */ -``` - -## Options - -`array|string`: `["array", "of", "operators"]|"operator"` - -Given: - -``` -["*="] -``` - -The following patterns are considered violations: - - -```css -[class*="test"] {} -``` - -The following patterns are _not_ considered violations: - - -```css -[target] {} -``` - - -```css -[target="_blank"] {} -``` - - -```css -[class|="top"] {} -``` diff --git a/lib/rules/selector-attribute-operator-blacklist/__tests__/index.js b/lib/rules/selector-attribute-operator-blacklist/__tests__/index.js deleted file mode 100644 index e36f2433a8..0000000000 --- a/lib/rules/selector-attribute-operator-blacklist/__tests__/index.js +++ /dev/null @@ -1,119 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['~='], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'selector-attribute-operator-disallowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - - config: ['*=', '~='], - - accept: [ - { - code: 'a[target] { }', - }, - { - code: 'a[target="_blank"] { }', - }, - { - code: '[class|="top"] { }', - }, - { - code: '[class^=top] { }', - }, - { - code: '[class$="test"] { }', - }, - { - code: ':root { --foo: 1px; }', - description: 'custom property in root', - }, - { - code: 'html { --foo: 1px; }', - description: 'custom property in selector', - }, - { - code: ':root { --custom-property-set: {} }', - description: 'custom property set in root', - }, - { - code: 'html { --custom-property-set: {} }', - description: 'custom property set in selector', - }, - ], - - reject: [ - { - code: '[title~="flower"] { }', - message: messages.rejected('~='), - line: 1, - column: 7, - }, - { - code: '[ title~="flower" ] { }', - message: messages.rejected('~='), - line: 1, - column: 8, - }, - { - code: '[title ~= "flower"] { }', - message: messages.rejected('~='), - line: 1, - column: 8, - }, - { - code: '[class*=te] { }', - message: messages.rejected('*='), - line: 1, - column: 7, - }, - ], -}); - -testRule({ - ruleName, - - config: ['*='], - - accept: [ - { - code: 'a[target="_blank"] { }', - }, - ], - - reject: [ - { - code: '[title*="foo"] { }', - message: messages.rejected('*='), - line: 1, - column: 7, - }, - ], -}); diff --git a/lib/rules/selector-attribute-operator-blacklist/index.js b/lib/rules/selector-attribute-operator-blacklist/index.js deleted file mode 100644 index 1caed2ff5f..0000000000 --- a/lib/rules/selector-attribute-operator-blacklist/index.js +++ /dev/null @@ -1,75 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); -const parseSelector = require('../../utils/parseSelector'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'selector-attribute-operator-blacklist'; - -const messages = ruleMessages(ruleName, { - rejected: (operator) => `Unexpected operator "${operator}"`, -}); - -function rule(listInput) { - const list = [].concat(listInput); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'selector-attribute-operator-disallowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkRules((ruleNode) => { - if (!isStandardSyntaxRule(ruleNode)) { - return; - } - - if (!ruleNode.selector.includes('[') || !ruleNode.selector.includes('=')) { - return; - } - - parseSelector(ruleNode.selector, result, ruleNode, (selectorTree) => { - selectorTree.walkAttributes((attributeNode) => { - const operator = attributeNode.operator; - - if (!operator || (operator && !list.includes(operator))) { - return; - } - - report({ - message: messages.rejected(operator), - node: ruleNode, - index: attributeNode.sourceIndex + attributeNode.offsetOf('operator'), - result, - ruleName, - }); - }); - }); - }); - }; -} - -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/README.md b/lib/rules/selector-attribute-operator-whitelist/README.md deleted file mode 100644 index 364d8266e6..0000000000 --- a/lib/rules/selector-attribute-operator-whitelist/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# selector-attribute-operator-whitelist - -**_Deprecated: Instead use the [`selector-attribute-operator-allowed-list`](../selector-attribute-operator-allowed-list/README.md) rule._** - -Specify a list of allowed attribute operators. - - -```css -[target="_blank"] {} -/** ↑ - * This operator */ -``` - -## Options - -`array|string`: `["array", "of", "operators"]|"operator"` - -Given: - -``` -["=", "|="] -``` - -The following patterns are considered violations: - - -```css -[class*="test"] {} -``` - - -```css -[title~="flower"] {} -``` - - -```css -[class^="top"] {} -``` - -The following patterns are _not_ considered violations: - - -```css -[target] {} -``` - - -```css -[target="_blank"] {} -``` - - -```css -[class|="top"] {} -``` diff --git a/lib/rules/selector-attribute-operator-whitelist/__tests__/index.js b/lib/rules/selector-attribute-operator-whitelist/__tests__/index.js deleted file mode 100644 index 671b57e3e7..0000000000 --- a/lib/rules/selector-attribute-operator-whitelist/__tests__/index.js +++ /dev/null @@ -1,125 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['='], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'selector-attribute-operator-allowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - - config: ['=', '|='], - - accept: [ - { - code: 'a[target] { }', - }, - { - code: 'a[target="_blank"] { }', - }, - { - code: '[class|="top"] { }', - }, - { - code: ':root { --foo: 1px; }', - description: 'custom property in root', - }, - { - code: 'html { --foo: 1px; }', - description: 'custom property in selector', - }, - { - code: ':root { --custom-property-set: {} }', - description: 'custom property set in root', - }, - { - code: 'html { --custom-property-set: {} }', - description: 'custom property set in selector', - }, - ], - - reject: [ - { - code: '[title~="flower"] { }', - message: messages.rejected('~='), - line: 1, - column: 7, - }, - { - code: '[ title~="flower" ] { }', - message: messages.rejected('~='), - line: 1, - column: 8, - }, - { - code: '[title ~= "flower"] { }', - message: messages.rejected('~='), - line: 1, - column: 8, - }, - { - code: '[class^=top] { }', - message: messages.rejected('^='), - line: 1, - column: 7, - }, - { - code: '[class$="test"] { }', - message: messages.rejected('$='), - line: 1, - column: 7, - }, - { - code: '[class*=te] { }', - message: messages.rejected('*='), - line: 1, - column: 7, - }, - ], -}); - -testRule({ - ruleName, - - config: ['='], - - accept: [ - { - code: 'a[target="_blank"] { }', - }, - ], - - reject: [ - { - code: '[title~="flower"] { }', - message: messages.rejected('~='), - line: 1, - column: 7, - }, - ], -}); diff --git a/lib/rules/selector-attribute-operator-whitelist/index.js b/lib/rules/selector-attribute-operator-whitelist/index.js deleted file mode 100644 index bd1c360832..0000000000 --- a/lib/rules/selector-attribute-operator-whitelist/index.js +++ /dev/null @@ -1,75 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); -const parseSelector = require('../../utils/parseSelector'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'selector-attribute-operator-whitelist'; - -const messages = ruleMessages(ruleName, { - rejected: (operator) => `Unexpected operator "${operator}"`, -}); - -function rule(listInput) { - const list = [].concat(listInput); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'selector-attribute-operator-allowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkRules((ruleNode) => { - if (!isStandardSyntaxRule(ruleNode)) { - return; - } - - if (!ruleNode.selector.includes('[') || !ruleNode.selector.includes('=')) { - return; - } - - parseSelector(ruleNode.selector, result, ruleNode, (selectorTree) => { - selectorTree.walkAttributes((attributeNode) => { - const operator = attributeNode.operator; - - if (!operator || (operator && list.includes(operator))) { - return; - } - - report({ - message: messages.rejected(operator), - node: ruleNode, - index: attributeNode.sourceIndex + attributeNode.offsetOf('operator'), - result, - ruleName, - }); - }); - }); - }); - }; -} - -rule.primaryOptionArray = true; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = { deprecated: true }; - -module.exports = rule; diff --git a/lib/rules/selector-combinator-blacklist/README.md b/lib/rules/selector-combinator-blacklist/README.md deleted file mode 100644 index cb64dfe82b..0000000000 --- a/lib/rules/selector-combinator-blacklist/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# selector-combinator-blacklist - -**_Deprecated: Instead use the [`selector-combinator-disallowed-list`](../selector-combinator-disallowed-list/README.md) rule._** - -Specify a list of disallowed combinators. - - -```css - a + b {} -/** ↑ - * This combinator */ -``` - -This rule normalizes the whitespace descendant combinator to be a single space. - -This rule ignores [reference combinators](https://www.w3.org/TR/selectors4/#idref-combinators) e.g. `/for/`. - -## Options - -`array|string`: `["array", "of", "combinators"]|"combinator"` - -Given: - -``` -[">", " "] -``` - -The following patterns are considered violations: - - -```css -a > b {} -``` - - -```css -a b {} -``` - - -```css -a -b {} -``` - -The following patterns are _not_ considered violations: - - -```css -a + b {} -``` - - -```css -a ~ b {} -``` diff --git a/lib/rules/selector-combinator-blacklist/__tests__/index.js b/lib/rules/selector-combinator-blacklist/__tests__/index.js deleted file mode 100644 index 7585ee6690..0000000000 --- a/lib/rules/selector-combinator-blacklist/__tests__/index.js +++ /dev/null @@ -1,94 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['>'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'selector-combinator-disallowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - config: ['>', ' '], - skipBasicChecks: true, - - accept: [ - { - code: 'a {}', - }, - { - code: 'a, b {}', - }, - { - code: 'a /for/ b {}', - }, - { - code: 'a + b {}', - }, - { - code: 'a:not(b ~ c) {}', - }, - ], - - reject: [ - { - code: 'a b {}', - message: messages.rejected(' '), - line: 1, - column: 2, - }, - { - code: 'a\tb {}', - message: messages.rejected(' '), - line: 1, - column: 2, - }, - { - code: 'a\n\tb {}', - message: messages.rejected(' '), - line: 1, - column: 2, - }, - { - code: 'a,\nb c {}', - message: messages.rejected(' '), - line: 2, - column: 2, - }, - { - code: 'a:not(b > c) {}', - message: messages.rejected('>'), - line: 1, - column: 9, - }, - { - code: 'a > b {}', - message: messages.rejected('>'), - line: 1, - column: 3, - }, - ], -}); diff --git a/lib/rules/selector-combinator-blacklist/index.js b/lib/rules/selector-combinator-blacklist/index.js deleted file mode 100644 index c8b2e3023a..0000000000 --- a/lib/rules/selector-combinator-blacklist/index.js +++ /dev/null @@ -1,80 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const isStandardSyntaxCombinator = require('../../utils/isStandardSyntaxCombinator'); -const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); -const parseSelector = require('../../utils/parseSelector'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'selector-combinator-blacklist'; - -const messages = ruleMessages(ruleName, { - rejected: (combinator) => `Unexpected combinator "${combinator}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'selector-combinator-disallowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkRules((ruleNode) => { - if (!isStandardSyntaxRule(ruleNode)) { - return; - } - - const selector = ruleNode.selector; - - parseSelector(selector, result, ruleNode, (fullSelector) => { - fullSelector.walkCombinators((combinatorNode) => { - if (!isStandardSyntaxCombinator(combinatorNode)) { - return; - } - - const value = normalizeCombinator(combinatorNode.value); - - if (!list.includes(value)) { - return; - } - - report({ - result, - ruleName, - message: messages.rejected(value), - node: ruleNode, - index: combinatorNode.sourceIndex, - }); - }); - }); - }); - }; -} - -function normalizeCombinator(value) { - return value.replace(/\s+/g, ' '); -} - -rule.primaryOptionArray = true; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = { deprecated: true }; - -module.exports = rule; diff --git a/lib/rules/selector-combinator-whitelist/README.md b/lib/rules/selector-combinator-whitelist/README.md deleted file mode 100644 index 49454ca37a..0000000000 --- a/lib/rules/selector-combinator-whitelist/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# selector-combinator-whitelist - -**_Deprecated: Instead use the [`selector-combinator-allowed-list`](../selector-combinator-allowed-list/README.md) rule._** - -Specify a list of allowed combinators. - - -```css - a + b {} -/** ↑ - * This combinator */ -``` - -This rule normalizes the whitespace descendant combinator to be a single space. - -This rule ignores [reference combinators](https://www.w3.org/TR/selectors4/#idref-combinators) e.g. `/for/`. - -## Options - -`array|string`: `["array", "of", "combinators"]|"combinator"` - -Given: - -``` -[">", " "] -``` - -The following patterns are considered violations: - - -```css -a + b {} -``` - - -```css -a ~ b {} -``` - -The following patterns are _not_ considered violations: - - -```css -a > b {} -``` - - -```css -a b {} -``` - - -```css -a -b {} -``` diff --git a/lib/rules/selector-combinator-whitelist/__tests__/index.js b/lib/rules/selector-combinator-whitelist/__tests__/index.js deleted file mode 100644 index cbfa4b6a5c..0000000000 --- a/lib/rules/selector-combinator-whitelist/__tests__/index.js +++ /dev/null @@ -1,118 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['>'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'selector-combinator-allowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - config: ['>', ' '], - skipBasicChecks: true, - - accept: [ - { - code: 'a {}', - }, - { - code: 'a, b {}', - }, - { - code: 'a /for/ b {}', - }, - { - code: 'a > b {}', - }, - { - code: 'a:not(b > c) {}', - }, - { - code: 'a b {}', - }, - { - code: 'a\tb {}', - }, - { - code: 'a\nb {}', - }, - ], - - reject: [ - { - code: 'a ~ b {}', - message: messages.rejected('~'), - line: 1, - column: 3, - }, - { - code: 'a:not(b ~ c) {}', - message: messages.rejected('~'), - line: 1, - column: 9, - }, - { - code: 'a,\nb + c {}', - message: messages.rejected('+'), - line: 2, - column: 3, - }, - ], -}); - -testRule({ - ruleName, - config: ['~'], - skipBasicChecks: true, - - accept: [ - { - code: 'a ~ b {}', - }, - ], - - reject: [ - { - code: 'a b {}', - message: messages.rejected(' '), - line: 1, - column: 2, - }, - { - code: 'a\tb {}', - message: messages.rejected(' '), - line: 1, - column: 2, - }, - { - code: 'a\n\tb {}', - message: messages.rejected(' '), - line: 1, - column: 2, - }, - ], -}); diff --git a/lib/rules/selector-combinator-whitelist/index.js b/lib/rules/selector-combinator-whitelist/index.js deleted file mode 100644 index 7635e3ebd6..0000000000 --- a/lib/rules/selector-combinator-whitelist/index.js +++ /dev/null @@ -1,80 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const isStandardSyntaxCombinator = require('../../utils/isStandardSyntaxCombinator'); -const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); -const parseSelector = require('../../utils/parseSelector'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'selector-combinator-whitelist'; - -const messages = ruleMessages(ruleName, { - rejected: (combinator) => `Unexpected combinator "${combinator}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'selector-combinator-allowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkRules((ruleNode) => { - if (!isStandardSyntaxRule(ruleNode)) { - return; - } - - const selector = ruleNode.selector; - - parseSelector(selector, result, ruleNode, (fullSelector) => { - fullSelector.walkCombinators((combinatorNode) => { - if (!isStandardSyntaxCombinator(combinatorNode)) { - return; - } - - const value = normalizeCombinator(combinatorNode.value); - - if (list.includes(value)) { - return; - } - - report({ - result, - ruleName, - message: messages.rejected(value), - node: ruleNode, - index: combinatorNode.sourceIndex, - }); - }); - }); - }); - }; -} - -function normalizeCombinator(value) { - return value.replace(/\s+/g, ' '); -} - -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/README.md b/lib/rules/selector-pseudo-class-blacklist/README.md deleted file mode 100644 index be91d9a071..0000000000 --- a/lib/rules/selector-pseudo-class-blacklist/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# selector-pseudo-class-blacklist - -**_Deprecated: Instead use the [`selector-pseudo-class-disallowed-list`](../selector-pseudo-class-disallowed-list/README.md) rule._** - -Specify a list of disallowed pseudo-class selectors. - - -```css - a:hover {} -/** ↑ - * This pseudo-class selector */ -``` - -This rule ignores selectors that use variable interpolation e.g. `:#{$variable} {}`. - -## Options - -`array|string|regex`: `["array", "of", "unprefixed", /pseudo-classes/ or "/regex/"]|"pseudo-class"|/regex/` - -If a string is surrounded with `"/"` (e.g. `"/^nth-/"`), it is interpreted as a regular expression. This allows, for example, easy targeting of shorthands: `/^nth-/` will match `nth-child`, `nth-last-child`, `nth-of-type`, etc. - -Given: - -``` -["hover", "/^nth-/"] -``` - -The following patterns are considered violations: - - -```css -a:hover {} -``` - - -```css -a:nth-of-type(5) {} -``` - - -```css -a:nth-child(2) {} -``` - -The following patterns are _not_ considered violations: - - -```css -a:focus {} -``` - - -```css -a:first-of-type {} -``` diff --git a/lib/rules/selector-pseudo-class-blacklist/__tests__/index.js b/lib/rules/selector-pseudo-class-blacklist/__tests__/index.js deleted file mode 100644 index 74a37f09a0..0000000000 --- a/lib/rules/selector-pseudo-class-blacklist/__tests__/index.js +++ /dev/null @@ -1,252 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['focus'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'selector-pseudo-class-disallowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -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'], - skipBasicChecks: true, - - accept: [ - { - code: 'a {}', - }, - { - code: 'a:hover {}', - }, - { - code: 'a:nth-child(5) {}', - }, - { - code: 'div:nth-LAST-child {}', - }, - { - code: 'input:-Ms-INPUT-placeholder {}', - }, - { - code: ':root {}', - }, - { - code: 'a:HOVER {}', - }, - { - code: 'a:hover, a:nth-child(5) {}', - }, - { - code: 'a::before {}', - }, - { - code: 'a:nth-child(5)::before {}', - }, - { - code: 'a:-moz-placeholder {}', - }, - { - code: 'a:-MOZ-PLACEholder {}', - }, - { - code: ':root { --foo: 1px; }', - description: 'custom property in root', - }, - { - code: 'html { --foo: 1px; }', - description: 'custom property in selector', - }, - { - code: ':root { --custom-property-set: {} }', - description: 'custom property set in root', - }, - { - code: 'html { --custom-property-set: {} }', - description: 'custom property set in selector', - }, - ], - - reject: [ - { - code: 'a:focus {}', - message: messages.rejected('focus'), - line: 1, - column: 2, - }, - { - code: 'a,\n:global {}', - message: messages.rejected('global'), - line: 2, - column: 1, - }, - { - code: 'input:-ms-input-placeholder {}', - message: messages.rejected('-ms-input-placeholder'), - line: 1, - column: 6, - }, - { - code: 'a:not(::selection) {}', - message: messages.rejected('not'), - line: 1, - column: 2, - }, - { - code: 'a:has(> img) {}', - message: messages.rejected('has'), - line: 1, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: [['/^last/']], - skipBasicChecks: true, - - accept: [ - { - code: 'a {}', - }, - { - code: 'a:first-child() {}', - }, - { - code: 'a:nth-LAST-child(5) {}', - }, - ], - - reject: [ - { - code: 'a:last-child {}', - message: messages.rejected('last-child'), - line: 1, - column: 2, - }, - { - code: 'a:last-of-child {}', - message: messages.rejected('last-of-child'), - line: 1, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: [[/^last/]], - skipBasicChecks: true, - - accept: [ - { - code: 'a {}', - }, - ], - - reject: [ - { - code: 'a:last-child {}', - message: messages.rejected('last-child'), - line: 1, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: [[/(not|matches|has)/]], - skipBasicChecks: true, - - accept: [ - { - code: 'a:focus {}', - }, - ], - - reject: [ - { - code: 'a:not() {}', - message: messages.rejected('not'), - line: 1, - column: 2, - }, - { - code: 'body:not(div):has(span) {}', - warnings: [ - { - message: messages.rejected('not'), - line: 1, - column: 5, - }, - { - message: messages.rejected('has'), - line: 1, - column: 14, - }, - ], - }, - { - code: 'body:nt(div):not(span) {}', - message: messages.rejected('not'), - line: 1, - column: 13, - }, - { - code: 'a:has() {}', - message: messages.rejected('has'), - line: 1, - column: 2, - }, - { - code: 'a:matches() {}', - message: messages.rejected('matches'), - line: 1, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: ['variable'], - skipBasicChecks: true, - syntax: 'scss', - - accept: [ - { - code: ':#{$variable} {}', - }, - { - code: ':#{$VARIABLE} {}', - }, - { - code: 'a:#{$variable} {}', - }, - ], -}); diff --git a/lib/rules/selector-pseudo-class-blacklist/index.js b/lib/rules/selector-pseudo-class-blacklist/index.js deleted file mode 100644 index 0c0ce9f5cd..0000000000 --- a/lib/rules/selector-pseudo-class-blacklist/index.js +++ /dev/null @@ -1,85 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const parseSelector = require('../../utils/parseSelector'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const vendor = require('../../utils/vendor'); - -const ruleName = 'selector-pseudo-class-blacklist'; - -const messages = ruleMessages(ruleName, { - rejected: (selector) => `Unexpected pseudo-class "${selector}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString, _.isRegExp], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'selector-pseudo-class-disallowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkRules((ruleNode) => { - if (!isStandardSyntaxRule(ruleNode)) { - return; - } - - const selector = ruleNode.selector; - - if (!selector.includes(':')) { - return; - } - - parseSelector(selector, result, ruleNode, (selectorTree) => { - selectorTree.walkPseudos((pseudoNode) => { - const value = pseudoNode.value; - - // Ignore pseudo-elements - - if (value.slice(0, 2) === '::') { - return; - } - - const name = value.slice(1); - - if (!matchesStringOrRegExp(vendor.unprefixed(name), list)) { - return; - } - - report({ - index: pseudoNode.sourceIndex, - message: messages.rejected(name), - node: ruleNode, - result, - ruleName, - }); - }); - }); - }); - }; -} - -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/README.md b/lib/rules/selector-pseudo-class-whitelist/README.md deleted file mode 100644 index 294f80300a..0000000000 --- a/lib/rules/selector-pseudo-class-whitelist/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# selector-pseudo-class-whitelist - -**_Deprecated: Instead use the [`selector-pseudo-class-allowed-list`](../selector-pseudo-class-allowed-list/README.md) rule._** - -Specify a list of allowed pseudo-class selectors. - - -```css - a:hover {} -/** ↑ - * This pseudo-class selector */ -``` - -This rule ignores selectors that use variable interpolation e.g. `:#{$variable} {}`. - -## Options - -`array|string|regex`: `["array", "of", "unprefixed", /pseudo-classes/ or "/regex/"]|"pseudo-class"|/regex/` - -If a string is surrounded with `"/"` (e.g. `"/^nth-/"`), it is interpreted as a regular expression. This allows, for example, easy targeting of shorthands: `/^nth-/` will match `nth-child`, `nth-last-child`, `nth-of-type`, etc. - -Given: - -``` -["hover", "/^nth-/"] -``` - -The following patterns are considered violations: - - -```css -a:focus {} -``` - - -```css -a:first-of-type {} -``` - -The following patterns are _not_ considered violations: - - -```css -a:hover {} -``` - - -```css -a:nth-of-type(5) {} -``` - - -```css -a:nth-child(2) {} -``` diff --git a/lib/rules/selector-pseudo-class-whitelist/__tests__/index.js b/lib/rules/selector-pseudo-class-whitelist/__tests__/index.js deleted file mode 100644 index 46ca294a12..0000000000 --- a/lib/rules/selector-pseudo-class-whitelist/__tests__/index.js +++ /dev/null @@ -1,201 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['hover'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'selector-pseudo-class-allowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -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'], - skipBasicChecks: true, - - accept: [ - { - code: 'a {}', - }, - { - code: 'a:hover {}', - }, - { - code: 'a:nth-child(5) {}', - }, - { - code: ':root {}', - }, - { - code: 'a:has(#id) {}', - }, - { - code: 'a:hover, a:nth-child(5) {}', - }, - { - code: 'a::before {}', - }, - { - code: 'a:nth-child(5)::before {}', - }, - { - code: 'a:-moz-placeholder {}', - }, - { - code: ':root { --foo: 1px; }', - description: 'custom property in root', - }, - { - code: 'html { --foo: 1px; }', - description: 'custom property in selector', - }, - { - code: ':root { --custom-property-set: {} }', - description: 'custom property set in root', - }, - { - code: 'html { --custom-property-set: {} }', - description: 'custom property set in selector', - }, - ], - - reject: [ - { - code: 'a:HOVER {}', - message: messages.rejected('HOVER'), - line: 1, - column: 2, - }, - { - code: 'a:-MOZ-PLACEholder {}', - message: messages.rejected('-MOZ-PLACEholder'), - line: 1, - column: 2, - }, - { - code: 'a:focus {}', - message: messages.rejected('focus'), - line: 1, - column: 2, - }, - { - code: 'div:nth-LAST-child {}', - message: messages.rejected('nth-LAST-child'), - line: 1, - column: 4, - }, - { - code: 'a,\n:global {}', - message: messages.rejected('global'), - line: 2, - column: 1, - }, - { - code: 'input:-ms-input-placeholder {}', - message: messages.rejected('-ms-input-placeholder'), - line: 1, - column: 6, - }, - { - code: 'input:-Ms-INPUT-placeholder {}', - message: messages.rejected('-Ms-INPUT-placeholder'), - line: 1, - column: 6, - }, - { - code: 'a:not(::selection) {}', - message: messages.rejected('not'), - line: 1, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: [['/^nth/']], - skipBasicChecks: true, - - accept: [ - { - code: 'a {}', - }, - { - code: 'a:nth-child(5) {}', - }, - { - code: 'a:nth-LAST-child {}', - }, - ], - - reject: [ - { - code: 'a:hover {}', - message: messages.rejected('hover'), - line: 1, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: [[/^nth/]], - skipBasicChecks: true, - - accept: [ - { - code: 'a {}', - }, - ], - - reject: [ - { - code: 'a:hover {}', - message: messages.rejected('hover'), - line: 1, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: ['hover'], - skipBasicChecks: true, - syntax: 'scss', - - accept: [ - { - code: ':#{$variable} {}', - }, - { - code: ':#{$VARIABLE} {}', - }, - { - code: 'a:#{$variable} {}', - }, - ], -}); diff --git a/lib/rules/selector-pseudo-class-whitelist/index.js b/lib/rules/selector-pseudo-class-whitelist/index.js deleted file mode 100644 index 0afef48632..0000000000 --- a/lib/rules/selector-pseudo-class-whitelist/index.js +++ /dev/null @@ -1,84 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const parseSelector = require('../../utils/parseSelector'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const vendor = require('../../utils/vendor'); - -const ruleName = 'selector-pseudo-class-whitelist'; - -const messages = ruleMessages(ruleName, { - rejected: (selector) => `Unexpected pseudo-class "${selector}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString, _.isRegExp], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'selector-pseudo-class-allowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkRules((ruleNode) => { - if (!isStandardSyntaxRule(ruleNode)) { - return; - } - - const selector = ruleNode.selector; - - if (!selector.includes(':')) { - return; - } - - parseSelector(selector, result, ruleNode, (selectorTree) => { - selectorTree.walkPseudos((pseudoNode) => { - const value = pseudoNode.value; - - // Ignore pseudo-elements - if (value.slice(0, 2) === '::') { - return; - } - - const name = value.slice(1); - - if (matchesStringOrRegExp(vendor.unprefixed(name), list)) { - return; - } - - report({ - index: pseudoNode.sourceIndex, - message: messages.rejected(name), - node: ruleNode, - result, - ruleName, - }); - }); - }); - }); - }; -} - -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/README.md b/lib/rules/selector-pseudo-element-blacklist/README.md deleted file mode 100644 index bcb9cf2908..0000000000 --- a/lib/rules/selector-pseudo-element-blacklist/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# selector-pseudo-element-blacklist - -**_Deprecated: Instead use the [`selector-pseudo-element-disallowed-list`](../selector-pseudo-element-disallowed-list/README.md) rule._** - -Specify a list of disallowed pseudo-element selectors. - - -```css - a::before {} -/** ↑ - * This pseudo-element selector */ -``` - -This rule ignores: - -- CSS2 pseudo-elements i.e. those prefixed with a single colon -- selectors that use variable interpolation e.g. `::#{$variable} {}` - -## Options - -`array|string|regex`: `["array", "of", "unprefixed", "pseudo-elements" or "regex"]|"pseudo-element"|/regex/` - -Given: - -``` -["before", "/^my-/i"] -``` - -The following patterns are considered violations: - - -```css -a::before {} -``` - - -```css -a::my-pseudo-element {} -``` - - -```css -a::MY-OTHER-pseudo-element {} -``` - -The following patterns are _not_ considered violations: - - -```css -a::after {} -``` - - -```css -a::not-my-pseudo-element {} -``` diff --git a/lib/rules/selector-pseudo-element-blacklist/__tests__/index.js b/lib/rules/selector-pseudo-element-blacklist/__tests__/index.js deleted file mode 100644 index ad20bc0bcd..0000000000 --- a/lib/rules/selector-pseudo-element-blacklist/__tests__/index.js +++ /dev/null @@ -1,131 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['before'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'selector-pseudo-element-disallowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -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], - skipBasicChecks: true, - - accept: [ - { - code: 'a {}', - }, - { - code: 'a:hover {}', - }, - { - code: 'a::BEFORE {}', - }, - { - code: 'a::after {}', - }, - { - code: '::first-line {}', - }, - { - code: '::-webkit-first-line {}', - }, - { - code: 'a:not(::first-line) {}', - }, - { - code: 'a::their-pseudo-element {}', - }, - { - code: 'a::THEIR-other-pseudo-element {}', - }, - ], - - reject: [ - { - code: 'a::before {}', - message: messages.rejected('before'), - line: 1, - column: 2, - }, - { - code: 'a,\nb::before {}', - message: messages.rejected('before'), - line: 2, - column: 2, - }, - { - code: '::selection {}', - message: messages.rejected('selection'), - line: 1, - column: 1, - }, - { - code: '::-webkit-selection {}', - message: messages.rejected('-webkit-selection'), - line: 1, - column: 1, - }, - { - code: 'a:not(::selection) {}', - message: messages.rejected('selection'), - line: 1, - column: 7, - }, - { - code: 'a::my-pseudo-element {}', - message: messages.rejected('my-pseudo-element'), - line: 1, - column: 2, - }, - { - code: 'a::MY-OTHER-pseudo-element {}', - message: messages.rejected('MY-OTHER-pseudo-element'), - line: 1, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: ['before'], - skipBasicChecks: true, - syntax: 'scss', - - accept: [ - { - code: '::#{$variable} {}', - }, - { - code: '::#{$VARIABLE} {}', - }, - { - code: 'a::#{$variable} {}', - }, - ], -}); diff --git a/lib/rules/selector-pseudo-element-blacklist/index.js b/lib/rules/selector-pseudo-element-blacklist/index.js deleted file mode 100644 index b407dd358b..0000000000 --- a/lib/rules/selector-pseudo-element-blacklist/index.js +++ /dev/null @@ -1,84 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const parseSelector = require('../../utils/parseSelector'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const vendor = require('../../utils/vendor'); - -const ruleName = 'selector-pseudo-element-blacklist'; - -const messages = ruleMessages(ruleName, { - rejected: (selector) => `Unexpected pseudo-element "${selector}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString, _.isRegExp], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'selector-pseudo-element-disallowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkRules((ruleNode) => { - if (!isStandardSyntaxRule(ruleNode)) { - return; - } - - const selector = ruleNode.selector; - - if (!selector.includes('::')) { - return; - } - - parseSelector(selector, result, ruleNode, (selectorTree) => { - selectorTree.walkPseudos((pseudoNode) => { - const value = pseudoNode.value; - - // Ignore pseudo-classes - if (value[1] !== ':') { - return; - } - - const name = value.slice(2); - - if (!matchesStringOrRegExp(vendor.unprefixed(name), list)) { - return; - } - - report({ - index: pseudoNode.sourceIndex, - message: messages.rejected(name), - node: ruleNode, - result, - ruleName, - }); - }); - }); - }); - }; -} - -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/README.md b/lib/rules/selector-pseudo-element-whitelist/README.md deleted file mode 100644 index 2a24022cb0..0000000000 --- a/lib/rules/selector-pseudo-element-whitelist/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# selector-pseudo-element-whitelist - -**_Deprecated: Instead use the [`selector-pseudo-element-allowed-list`](../selector-pseudo-element-allowed-list/README.md) rule._** - -Specify a list of allowed pseudo-element selectors. - - -```css - a::before {} -/** ↑ - * This pseudo-element selector */ -``` - -This rule ignores: - -- CSS2 pseudo-elements i.e. those prefixed with a single colon -- selectors that use variable interpolation e.g. `::#{$variable} {}` - -## Options - -`array|string|regex`: `["array", "of", "unprefixed", "pseudo-elements" or "regex"]|"pseudo-element"|/regex/` - -Given: - -``` -["before", "/^my-/i"] -``` - -The following patterns are considered violations: - - -```css -a::after {} -``` - - -```css -a::not-my-pseudo-element {} -``` - -The following patterns are _not_ considered violations: - - -```css -a::before {} -``` - - -```css -a::my-pseudo-element {} -``` - - -```css -a::MY-OTHER-pseudo-element {} -``` diff --git a/lib/rules/selector-pseudo-element-whitelist/__tests__/index.js b/lib/rules/selector-pseudo-element-whitelist/__tests__/index.js deleted file mode 100644 index 95a1944a54..0000000000 --- a/lib/rules/selector-pseudo-element-whitelist/__tests__/index.js +++ /dev/null @@ -1,153 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['before'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'selector-pseudo-element-allowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -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], - skipBasicChecks: true, - - accept: [ - { - code: 'a {}', - }, - { - code: 'a:hover {}', - }, - { - code: 'a::before {}', - }, - { - code: '::selection {}', - }, - { - code: '::-webkit-selection {}', - }, - { - code: 'a:not(::selection) {}', - }, - { - code: 'a::my-pseudo-element {}', - }, - { - code: 'a::MY-other-pseudo-element {}', - }, - ], - - reject: [ - { - code: 'a::BEFORE {}', - message: messages.rejected('BEFORE'), - line: 1, - column: 2, - }, - { - code: 'a::after {}', - message: messages.rejected('after'), - line: 1, - column: 2, - }, - { - code: 'a::AFTER {}', - message: messages.rejected('AFTER'), - line: 1, - column: 2, - }, - { - code: 'a,\nb::after {}', - message: messages.rejected('after'), - line: 2, - column: 2, - }, - { - code: 'a::not-my-pseudo-element {}', - message: messages.rejected('not-my-pseudo-element'), - line: 1, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: /^before/, - skipBasicChecks: true, - - accept: [ - { - code: '::before {}', - }, - { - code: '::before-custom {}', - }, - ], - reject: [ - { - code: 'a::after {}', - message: messages.rejected('after'), - line: 1, - column: 2, - }, - { - code: 'a::not-before {}', - message: messages.rejected('not-before'), - line: 1, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: ['before'], - skipBasicChecks: true, - syntax: 'scss', - - accept: [ - { - code: '::#{$variable} {}', - }, - { - code: '::#{$VARIABLE} {}', - }, - { - code: 'a::#{$variable} {}', - }, - ], - reject: [ - { - code: 'a::after {}', - message: messages.rejected('after'), - line: 1, - column: 2, - }, - ], -}); diff --git a/lib/rules/selector-pseudo-element-whitelist/index.js b/lib/rules/selector-pseudo-element-whitelist/index.js deleted file mode 100644 index d7304a6c0d..0000000000 --- a/lib/rules/selector-pseudo-element-whitelist/index.js +++ /dev/null @@ -1,84 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); -const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); -const parseSelector = require('../../utils/parseSelector'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const vendor = require('../../utils/vendor'); - -const ruleName = 'selector-pseudo-element-whitelist'; - -const messages = ruleMessages(ruleName, { - rejected: (selector) => `Unexpected pseudo-element "${selector}"`, -}); - -function rule(list) { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: list, - possible: [_.isString, _.isRegExp], - }); - - if (!validOptions) { - return; - } - - result.warn( - `'${ruleName}' has been deprecated. Instead use 'selector-pseudo-element-allowed-list'.`, - { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }, - ); - - root.walkRules((ruleNode) => { - if (!isStandardSyntaxRule(ruleNode)) { - return; - } - - const selector = ruleNode.selector; - - if (!selector.includes('::')) { - return; - } - - parseSelector(selector, result, ruleNode, (selectorTree) => { - selectorTree.walkPseudos((pseudoNode) => { - const value = pseudoNode.value; - - // Ignore pseudo-classes - if (value[1] !== ':') { - return; - } - - const name = value.slice(2); - - if (matchesStringOrRegExp(vendor.unprefixed(name), list)) { - return; - } - - report({ - index: pseudoNode.sourceIndex, - message: messages.rejected(name), - node: ruleNode, - result, - ruleName, - }); - }); - }); - }); - }; -} - -rule.primaryOptionArray = true; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = { deprecated: true }; - -module.exports = rule; diff --git a/lib/rules/unit-blacklist/README.md b/lib/rules/unit-blacklist/README.md deleted file mode 100644 index bcfa8710b3..0000000000 --- a/lib/rules/unit-blacklist/README.md +++ /dev/null @@ -1,161 +0,0 @@ -# unit-blacklist - -**_Deprecated: Instead use the [`unit-disallowed-list`](../unit-disallowed-list/README.md) rule._** - -Specify a list of disallowed units. - - -```css -a { width: 100px; } -/** ↑ - * These units */ -``` - -## Options - -`array|string`: `["array", "of", "units"]|"unit"` - -Given: - -``` -["px", "em", "deg"] -``` - -The following patterns are considered violations: - - -```css -a { width: 100px; } -``` - - -```css -a { font-size: 10em; } -``` - - -```css -a { transform: rotate(30deg); } -``` - -The following patterns are _not_ considered violations: - - -```css -a { font-size: 1.2rem; } -``` - - -```css -a { line-height: 1.2; } -``` - - -```css -a { height: 100vmin; } -``` - - -```css -a { animation: animation-name 5s ease; } -``` - -## Optional secondary options - -### `ignoreProperties: { unit: ["property", "/regex/", /regex/] }` - -Ignore units in the values of declarations with the specified properties. - -For example, with `["px", "vmin"]`. - -Given: - -``` -{ - "px": [ "font-size", "/^border/" ], - "vmin": [ "width" ] -} -``` - -The following patterns are _not_ considered violations: - - -```css -a { font-size: 13px; } -``` - - -```css -a { border-bottom-width: 6px; } -``` - - -```css -a { width: 100vmin; } -``` - -The following patterns are considered violations: - - -```css -a { line-height: 12px; } -``` - - -```css -a { -moz-border-radius-topright: 40px; } -``` - - -```css -a { height: 100vmin; } -``` - -### `ignoreMediaFeatureNames: { unit: ["property", "/regex/", /regex/] }` - -Ignore units for specific feature names. - -For example, with `["px", "dpi"]`. - -Given: - -``` -{ - "px": [ "min-width", "/height$/" ], - "dpi": [ "resolution" ] -} -``` - -The following patterns are _not_ considered violations: - - -```css -@media (min-width: 960px) {} -``` - - -```css -@media (max-height: 280px) {} -``` - - -```css -@media not (resolution: 300dpi) {} -``` - -The following patterns are considered violations: - - -```css -@media screen and (max-device-width: 500px) {} -``` - - -```css -@media all and (min-width: 500px) and (max-width: 200px) {} -``` - - -```css -@media print and (max-resolution: 100dpi) {} -``` diff --git a/lib/rules/unit-blacklist/__tests__/index.js b/lib/rules/unit-blacklist/__tests__/index.js deleted file mode 100644 index 20cb4bee23..0000000000 --- a/lib/rules/unit-blacklist/__tests__/index.js +++ /dev/null @@ -1,568 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['px'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'unit-disallowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - - config: ['px', 'vmin'], - - accept: [ - { - code: 'a { line-height: 1; }', - }, - { - code: 'a { color: #000; }', - }, - { - code: 'a { top: 0; left: 0; }', - }, - { - code: 'a { font-size: 100%; }', - }, - { - code: 'a { line-height: 1.2rem; }', - }, - { - code: 'a { line-height: 1.2rEm; }', - }, - { - code: 'a { line-height: 1.2REM; }', - }, - { - code: 'a { font-size: .5rem; }', - }, - { - code: 'a { font-size: 0.5rem; }', - }, - { - code: 'a { margin: 0 10em 5rem 2in; }', - }, - { - code: 'a { background-position: top right, 1em 5vh; }', - }, - { - code: 'a { top: calc(10em - 3em); }', - }, - { - code: 'a { top: calc(10em*2rem); }', - }, - { - code: 'a { background-image: linear-gradient(to right, white calc(100% - 50em), silver); }', - }, - { - code: 'a { width: /* 100px */ 1em; }', - description: 'ignore unit within comments', - }, - { - code: 'a::before { content: "10px"}', - description: 'ignore unit within quotes', - }, - { - code: 'a { font-size: $fs10px; }', - description: 'ignore preprocessor variable includes unit', - }, - { - code: 'a { font-size: --some-fs-10px; }', - description: 'ignore css variable includes unit', - }, - { - code: 'a { background-url: url(10vmin); }', - description: 'ignore url function', - }, - { - code: 'a { background-url: uRl(10vmin); }', - description: 'ignore url function', - }, - { - code: 'a { background-url: URL(10vmin); }', - description: 'ignore url function', - }, - { - code: 'a { margin10px: 10em; }', - description: 'ignore property include wrong unit', - }, - { - code: 'a10px { margin: 10em; }', - description: 'ignore type selector include wrong unit', - }, - { - code: '#a10px { margin: 10em; }', - description: 'ignore class selector include wrong unit', - }, - { - code: '.a10px { margin: 10em; }', - description: 'ignore class selector include wrong unit', - }, - { - code: 'input[type=10px] { margin: 10em; }', - description: 'ignore class selector include wrong unit', - }, - { - code: 'a:hover10px { margin: 10em; }', - description: 'ignore pseudo-class include wrong unit', - }, - { - code: 'a::before10px { margin: 10em; }', - description: 'ignore pseudo-class include wrong unit', - }, - { - code: 'a { margin: calc(100% - #{margin * 2}); }', - description: 'work with interpolation', - }, - { - code: '@media (min-width: 10em) {}', - description: '@media', - }, - { - code: '@media (min-width: 10em)\n and (max-width: 20em) {}', - description: 'complex @media', - }, - ], - - reject: [ - { - code: 'a { font-size: 13px; }', - message: messages.rejected('px'), - line: 1, - column: 16, - }, - { - code: 'a { font-size: 13pX; }', - message: messages.rejected('pX'), - line: 1, - column: 16, - }, - { - code: 'a { font-size: 13PX; }', - message: messages.rejected('PX'), - line: 1, - column: 16, - }, - { - code: 'a { width: 100vmin; }', - message: messages.rejected('vmin'), - line: 1, - column: 12, - }, - { - code: 'a { line-height: .1px; }', - message: messages.rejected('px'), - line: 1, - column: 18, - }, - { - code: 'a { line-height: 0.1px; }', - message: messages.rejected('px'), - line: 1, - column: 18, - }, - { - code: 'a { border-left: 1px solid #ccc; }', - message: messages.rejected('px'), - line: 1, - column: 18, - }, - { - code: 'a { margin: 0 20px; }', - message: messages.rejected('px'), - line: 1, - column: 15, - }, - { - code: 'a { margin: 0 0 0 20px; }', - message: messages.rejected('px'), - line: 1, - column: 19, - }, - { - code: 'a { background-position: top right, 1em 5px; }', - message: messages.rejected('px'), - line: 1, - column: 41, - }, - { - code: 'a { top: calc(100px - 30vh); }', - message: messages.rejected('px'), - line: 1, - column: 15, - }, - { - code: 'a { top: calc(100px*2); }', - message: messages.rejected('px'), - line: 1, - column: 15, - }, - { - code: 'a { background-image: linear-gradient(to right, white calc(100vh - 5vmin), silver); }', - message: messages.rejected('vmin'), - line: 1, - column: 68, - }, - { - code: 'a { margin: calc(100% - #{$margin * 2px}); }', - message: messages.rejected('px'), - line: 1, - column: 37, - }, - { - code: '@media (min-width: 13px) {}', - message: messages.rejected('px'), - description: '@media', - line: 1, - column: 20, - }, - { - code: '@media (min-width: 10em)\n and (max-width: 20px) {}', - message: messages.rejected('px'), - description: 'complex @media', - line: 2, - column: 19, - }, - { - code: '@media (width < 10.01px) {}', - message: messages.rejected('px'), - description: 'media feature range', - line: 1, - column: 17, - }, - ], -}); - -testRule({ - ruleName, - - config: ['px'], - - accept: [ - { - code: 'a { line-height: 1em; }', - }, - ], - - reject: [ - { - code: 'a { line-height: 1px; }', - message: messages.rejected('px'), - line: 1, - column: 18, - }, - ], -}); - -testRule({ - ruleName, - - config: [ - ['px', 'vmin'], - { - ignoreProperties: { - px: ['font-size', 'margin', '/^border/'], - vmin: ['width', 'height'], - }, - }, - ], - - accept: [ - { - code: 'a { font-size: 13px; }', - }, - { - code: 'a { font-size: 13pX; }', - }, - { - code: 'a { margin: 0 20px; }', - }, - { - code: 'a { margin: 0 0 0 20Px; }', - }, - { - code: 'a { width: 100vmin; }', - }, - { - code: 'a { height: 99vmIn; }', - }, - { - code: 'a { border: 1px solid purple; }', - }, - { - code: 'a { border-bottom-width: 6px; }', - }, - ], - - reject: [ - { - code: 'a { line-height: .1px; }', - message: messages.rejected('px'), - line: 1, - column: 18, - }, - { - code: 'a { background-image: linear-gradient(to right, white calc(100vh - 5vmin), silver); }', - message: messages.rejected('vmin'), - line: 1, - column: 68, - }, - { - code: 'a { -moz-border-radius-topright: 40px; }', - message: messages.rejected('px'), - line: 1, - column: 34, - }, - ], -}); - -testRule({ - ruleName, - - config: [ - ['px', 'vmin'], - { - ignoreProperties: { - px: ['font-size', 'margin', /^border/], - vmin: ['width', 'height'], - }, - }, - ], - - accept: [ - { - code: 'a { border: 1px solid purple; }', - }, - { - code: 'a { border-bottom-width: 6px; }', - }, - ], - - reject: [ - { - code: 'a { line-height: .1px; }', - message: messages.rejected('px'), - line: 1, - column: 18, - }, - ], -}); - -testRule({ - ruleName, - - config: [ - ['px', 'dpi', '%'], - { - ignoreMediaFeatureNames: { - px: ['min-width', 'height'], - dpi: ['min-resolution', 'resolution'], - '%': ['width', '/^min/'], - }, - }, - ], - - accept: [ - { - code: '@media (min-width: 960px) { body { font-size: 13em } }', - }, - { - code: '@media (width: 960%) { /* body { font-size: 13em } */ }', - }, - { - code: '@media (min-width: 960%) { /* body { font-size: 13em } */ }', - }, - { - code: 'a { @media (min-width: 960px) { body { font-size: 13em } } }', - }, - { - code: '@media print and (min-resolution: 300dpi) { body { font-size: 13em } }', - }, - { - code: '@media print { body { font-size: 40pt } }', - }, - { - code: '@media screen, print { body { line-height: 1.2 } }', - }, - { - code: '@MEDIA (min-width: 960px) { body { font-size: 13em } }', - }, - { - code: '@media (MIN-WIDTH: 960px) { body { font-size: 13em } }', - }, - { - code: '@media (height > -100px) { body { background: green; } }', - }, - { - code: '@media not (resolution: -300dpi) { body { background: green; } }', - }, - { - code: '@media only screen and (min-width: 500px) { }', - }, - { - code: '@media only speech and (width > 20%) { }', - }, - { - code: '@media speech and (device-aspect-ratio: 16/9) { }', - }, - { - code: - '@media only screen and (min-width: 320px) and (height: 480px) and (-webkit-min-device-pixel-ratio: 2) { body { line-height: 1.4 } }', - }, - { - code: '@media screen, print { }', - }, - { - code: '@media speech and (aspect-ratio: 11/5) { }', - }, - { - code: '@media (min-width: 700px), handheld and (orientation: landscape) { }', - }, - ], - - reject: [ - { - code: '@media screen and (max-width: 500px) { }', - message: messages.rejected('px'), - line: 1, - column: 31, - }, - { - code: '@media (width: 960px) { /* body { font-size: 13em } */ }', - message: messages.rejected('px'), - line: 1, - column: 16, - }, - { - code: '@media (min-height: 960px) { /* body { font-size: 13em } */ }', - message: messages.rejected('px'), - line: 1, - column: 21, - }, - { - code: 'a { @media screen and (max-width: 500px) { } }', - message: messages.rejected('px'), - line: 1, - column: 35, - }, - { - code: '@media all and (min-width: 500px) and (max-width: 200px) { }', - message: messages.rejected('px'), - line: 1, - column: 51, - }, - { - code: '@MEDIA print { body { font-size: 60dpi } }', - message: messages.rejected('dpi'), - line: 1, - column: 34, - }, - { - code: '@media (MAX-WIDTH: 10px) { }', - message: messages.rejected('px'), - line: 1, - column: 20, - }, - { - code: '@media (min-width: 10em)\n and (max-width: 20px) { }', - message: messages.rejected('px'), - line: 2, - column: 19, - }, - { - code: '@media (width < 10.01px) {}', - message: messages.rejected('px'), - line: 1, - column: 17, - }, - { - code: '@media only speech and (max-device-width > 20%) { }', - message: messages.rejected('%'), - line: 1, - column: 44, - }, - { - code: '@media not (max-resolution: -300dpi) { body { background: green; } }', - message: messages.rejected('dpi'), - line: 1, - column: 29, - }, - { - code: - '@media only screen and (min-width: 320px) and (height: 480px) and (-webkit-min-device-pixel-ratio: 2) { body { line-height: 1.4px } }', - message: messages.rejected('px'), - line: 1, - column: 125, - }, - { - code: - '@media only screen and (min-width: 320px) and (height: 480px) and (-webkit-min-device-pixel-ratio: 2px) { body { line-height: 1.4 } }', - message: messages.rejected('px'), - line: 1, - column: 100, - }, - { - code: '@media screen and (min-width: 699px) and (min-width: 520px), (max-width: 1151px)', - message: messages.rejected('px'), - line: 1, - column: 74, - }, - ], -}); - -testRule({ - ruleName, - - config: [ - ['px', 'dpi', '%'], - { - ignoreMediaFeatureNames: { - px: ['min-width', 'height'], - dpi: ['min-resolution', 'resolution'], - '%': ['width', /^min/], - }, - }, - ], - - accept: [ - { - code: '@media (width: 960%) { /* body { font-size: 13em } */ }', - }, - { - code: '@media (min-width: 960%) { /* body { font-size: 13em } */ }', - }, - ], - - reject: [ - { - code: '@media screen and (max-width: 500px) { }', - message: messages.rejected('px'), - line: 1, - column: 31, - }, - ], -}); diff --git a/lib/rules/unit-blacklist/index.js b/lib/rules/unit-blacklist/index.js deleted file mode 100644 index dc8abc6465..0000000000 --- a/lib/rules/unit-blacklist/index.js +++ /dev/null @@ -1,132 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const getUnitFromValueNode = require('../../utils/getUnitFromValueNode'); -const mediaParser = require('postcss-media-query-parser').default; -const optionsMatches = require('../../utils/optionsMatches'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateObjectWithArrayProps = require('../../utils/validateObjectWithArrayProps'); -const validateOptions = require('../../utils/validateOptions'); -const valueParser = require('postcss-value-parser'); - -const ruleName = 'unit-blacklist'; - -const messages = ruleMessages(ruleName, { - rejected: (unit) => `Unexpected unit "${unit}"`, -}); - -// a function to retrieve only the media feature name -// could be externalized in an utils function if needed in other code -const getMediaFeatureName = (mediaFeatureNode) => { - const value = mediaFeatureNode.value.toLowerCase(); - - return /((-?\w*)*)/i.exec(value)[1]; -}; - -function rule(listInput, options) { - const list = [].concat(listInput); - - return (root, result) => { - const validOptions = validateOptions( - result, - ruleName, - { - actual: list, - possible: [_.isString], - }, - { - optional: true, - actual: options, - possible: { - ignoreProperties: validateObjectWithArrayProps([_.isString, _.isRegExp]), - ignoreMediaFeatureNames: validateObjectWithArrayProps([_.isString, _.isRegExp]), - }, - }, - ); - - if (!validOptions) { - return; - } - - result.warn(`'${ruleName}' has been deprecated. Instead use 'unit-disallowed-list'.`, { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }); - - function check(node, nodeIndex, valueNode, input, option) { - const unit = getUnitFromValueNode(valueNode); - - // There is not unit or it is not configured as a violation - if (!unit || (unit && !list.includes(unit.toLowerCase()))) { - return; - } - - // The unit has an ignore option for the specific input - if (optionsMatches(option, unit.toLowerCase(), input)) { - return; - } - - report({ - index: nodeIndex + valueNode.sourceIndex, - message: messages.rejected(unit), - node, - result, - ruleName, - }); - } - - function checkMedia(node, value, getIndex) { - mediaParser(node.params).walk(/^media-feature$/i, (mediaFeatureNode) => { - const mediaName = getMediaFeatureName(mediaFeatureNode); - const parentValue = mediaFeatureNode.parent.value; - - valueParser(value).walk((valueNode) => { - // Ignore all non-word valueNode and - // the values not included in the parentValue string - if (valueNode.type !== 'word' || !parentValue.includes(valueNode.value)) { - return; - } - - check( - node, - getIndex(node), - valueNode, - mediaName, - options ? options.ignoreMediaFeatureNames : {}, - ); - }); - }); - } - - function checkDecl(node, value, getIndex) { - // make sure multiplication operations (*) are divided - not handled - // by postcss-value-parser - value = value.replace(/\*/g, ','); - - valueParser(value).walk((valueNode) => { - // Ignore wrong units within `url` function - if (valueNode.type === 'function' && valueNode.value.toLowerCase() === 'url') { - return false; - } - - check(node, getIndex(node), valueNode, node.prop, options ? options.ignoreProperties : {}); - }); - } - - root.walkAtRules(/^media$/i, (atRule) => checkMedia(atRule, atRule.params, atRuleParamIndex)); - root.walkDecls((decl) => checkDecl(decl, decl.value, declarationValueIndex)); - }; -} - -rule.primaryOptionArray = true; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = { deprecated: true }; - -module.exports = rule; diff --git a/lib/rules/unit-whitelist/README.md b/lib/rules/unit-whitelist/README.md deleted file mode 100644 index c32c1333d7..0000000000 --- a/lib/rules/unit-whitelist/README.md +++ /dev/null @@ -1,117 +0,0 @@ -# unit-whitelist - -**_Deprecated: Instead use the [`unit-allowed-list`](../unit-allowed-list/README.md) rule._** - -Specify a list of allowed units. - - -```css -a { width: 100px; } -/** ↑ - * These units */ -``` - -## Options - -`array|string`: `["array", "of", "units"]|"unit"` - -Given: - -``` -["px", "em", "deg"] -``` - -The following patterns are considered violations: - - -```css -a { width: 100%; } -``` - - -```css -a { font-size: 10rem; } -``` - - -```css -a { animation: animation-name 5s ease; } -``` - -The following patterns are _not_ considered violations: - - -```css -a { font-size: 1.2em; } -``` - - -```css -a { line-height: 1.2; } -``` - - -```css -a { height: 100px; } -``` - - -```css -a { height: 100PX; } -``` - - -```css -a { transform: rotate(30deg); } -``` - -## Optional secondary options - -### `ignoreProperties: { unit: ["property", "/regex/", /regex/] }` - -Ignore units in the values of declarations with the specified properties. - -For example, with `["px", "em"]`. - -Given: - -``` -{ - "rem": [ "line-height", "/^border/" ], - "%": [ "width" ] -} -``` - -The following patterns are _not_ considered violations: - - -```css -a { line-height: 0.1rem; } -``` - - -```css -a { border-bottom-width: 6rem; } -``` - - -```css -a { width: 100%; } -``` - -The following patterns are considered violations: - - -```css -a { margin: 0 20rem; } -``` - - -```css -a { -moz-border-radius-topright: 20rem; } -``` - - -```css -a { height: 100%; } -``` diff --git a/lib/rules/unit-whitelist/__tests__/index.js b/lib/rules/unit-whitelist/__tests__/index.js deleted file mode 100644 index 9c5f3f79d2..0000000000 --- a/lib/rules/unit-whitelist/__tests__/index.js +++ /dev/null @@ -1,370 +0,0 @@ -'use strict'; - -const standalone = require('../../../standalone'); -const { messages, ruleName, meta } = require('..'); - -it('warns that the rule is deprecated', () => { - const config = { - rules: { - [ruleName]: ['px'], - }, - }; - - const code = ''; - - return standalone({ code, config }).then((output) => { - const result = output.results[0]; - - expect(result.deprecations).toHaveLength(1); - expect(result.deprecations[0].text).toEqual( - `'${ruleName}' has been deprecated. Instead use 'unit-allowed-list'.`, - ); - expect(result.deprecations[0].reference).toEqual( - `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - ); - }); -}); - -it('also warns that the rule is deprecated via a meta', () => { - expect(meta).not.toBeUndefined(); - expect(meta).toHaveProperty('deprecated', true); -}); - -testRule({ - ruleName, - - config: ['px', 'em'], - - accept: [ - { - code: 'a { line-height: 1; }', - }, - { - code: 'a { color: #000; }', - }, - { - code: 'a { font-size: 14px; }', - }, - { - code: 'a { font-size: 14pX; }', - }, - { - code: 'a { font-size: 14PX; }', - }, - { - code: 'a { font-size: 1.2em; }', - }, - { - code: 'a { font-size: .5em; }', - }, - { - code: 'a { font-size: 0.5em; }', - }, - { - code: 'a { margin: 0 10em 5em 2px; }', - }, - { - code: 'a { background-position: top right, 10px 20px; }', - }, - { - code: 'a { top: calc(10em - 3em); }', - }, - { - code: 'a { top: calc(10em*3); }', - }, - { - code: 'a { background-image: linear-gradient(to right, white calc(100px - 50em), silver); }', - }, - { - code: 'a { width: /* 100pc */ 1em; }', - description: 'ignore unit within comments', - }, - { - code: 'a::before { content: "10%"}', - description: 'ignore unit within quotes', - }, - { - code: 'a { font-size: $fs10%; }', - description: 'ignore preprocessor variable includes unit', - }, - { - code: 'a { font-size: --some-fs-10rem; }', - description: 'ignore css variable includes unit', - }, - { - code: 'a { background-url: url(10vmin); }', - description: 'ignore url function', - }, - { - code: 'a { background-url: uRl(10vmin); }', - description: 'ignore url function', - }, - { - code: 'a { background-url: URL(10vmin); }', - description: 'ignore url function', - }, - { - code: 'a { margin10rem: 10em; }', - description: 'ignore property include wrong unit', - }, - { - code: 'a10rem { margin: 10em; }', - description: 'ignore type selector include wrong unit', - }, - { - code: '#a10rem { margin: 10em; }', - description: 'ignore class selector include wrong unit', - }, - { - code: '.a10rem { margin: 10em; }', - description: 'ignore class selector include wrong unit', - }, - { - code: 'input[type=10rem] { margin: 10em; }', - description: 'ignore class selector include wrong unit', - }, - { - code: 'a:hover10rem { margin: 10em; }', - description: 'ignore pseudo-class include wrong unit', - }, - { - code: 'a::before10rem { margin: 10em; }', - description: 'ignore pseudo-class include wrong unit', - }, - { - code: 'a { margin: calc(100px - #{margin * 2}); }', - description: 'work with interpolation', - }, - { - code: '@media (min-width: 10em) {}', - description: '@media', - }, - { - code: '@media (min-width: 10px)\n and (max-width: 20em) {}', - description: 'complex @media', - }, - ], - - reject: [ - { - code: 'a { font-size: 80%; }', - message: messages.rejected('%'), - line: 1, - column: 16, - }, - { - code: 'a { width: 100vmin; }', - message: messages.rejected('vmin'), - line: 1, - column: 12, - }, - { - code: 'a { width: 100vMiN; }', - message: messages.rejected('vMiN'), - line: 1, - column: 12, - }, - { - code: 'a { width: 100VMIN; }', - message: messages.rejected('VMIN'), - line: 1, - column: 12, - }, - { - code: 'a { line-height: .1rem; }', - message: messages.rejected('rem'), - line: 1, - column: 18, - }, - { - code: 'a { line-height: 0.1rem; }', - message: messages.rejected('rem'), - line: 1, - column: 18, - }, - { - code: 'a { border-left: 1rem solid #ccc; }', - message: messages.rejected('rem'), - line: 1, - column: 18, - }, - { - code: 'a { margin: 0 20%; }', - message: messages.rejected('%'), - line: 1, - column: 15, - }, - { - code: 'a { margin: 0 0 0 20rem; }', - message: messages.rejected('rem'), - line: 1, - column: 19, - }, - { - code: 'a { background-position: top right, 1em 5rem; }', - message: messages.rejected('rem'), - line: 1, - column: 41, - }, - { - code: 'a { top: calc(2vh*3); }', - message: messages.rejected('vh'), - line: 1, - column: 15, - }, - { - code: 'a { top: calc(100px - 30vh); }', - message: messages.rejected('vh'), - line: 1, - column: 23, - }, - { - code: 'a { background-image: linear-gradient(to right, white calc(100px - 5vmin), silver); }', - message: messages.rejected('vmin'), - line: 1, - column: 68, - }, - { - code: 'a { margin: calc(100px - #{$margin * 2rem}); }', - message: messages.rejected('rem'), - line: 1, - column: 38, - }, - { - code: '@media (min-width: 13rem) {}', - message: messages.rejected('rem'), - description: '@media', - line: 1, - column: 20, - }, - { - code: '@media (min-width: 10em)\n and (max-width: 20rem) {}', - message: messages.rejected('rem'), - description: 'complex @media', - line: 2, - column: 19, - }, - { - code: '@media (width < 10.01REM) {}', - message: messages.rejected('REM'), - description: 'media feature range', - line: 1, - column: 17, - }, - ], -}); - -testRule({ - ruleName, - - config: ['px'], - - accept: [ - { - code: 'a { line-height: 1px; }', - }, - ], - - reject: [ - { - code: 'a { line-height: 1em; }', - message: messages.rejected('em'), - line: 1, - column: 18, - }, - ], -}); - -testRule({ - ruleName, - - config: [ - ['px', 'em'], - { - ignoreProperties: { - rem: ['line-height', 'margin', '/^border/'], - '%': ['width', 'height'], - }, - }, - ], - - accept: [ - { - code: 'a { line-height: 0.1rem; }', - }, - { - code: 'a { line-height: 0.1rEm; }', - }, - { - code: 'a { margin: 0 20rem; }', - }, - { - code: 'a { margin: 0 0 0 20reM; }', - }, - { - code: 'a { width: 100%; }', - }, - { - code: 'a { height: 50%; }', - }, - { - code: 'a { border: 1rem solid purple; }', - }, - { - code: 'a { border-bottom-width: 6rem; }', - }, - ], - - reject: [ - { - code: 'a { font-size: 80%; }', - message: messages.rejected('%'), - line: 1, - column: 16, - }, - { - code: 'a { background-image: linear-gradient(to right, white calc(100px - 5rem), silver); }', - message: messages.rejected('rem'), - line: 1, - column: 68, - }, - { - code: 'a { -moz-border-radius-topright: 40rem; }', - message: messages.rejected('rem'), - line: 1, - column: 34, - }, - ], -}); - -testRule({ - ruleName, - - config: [ - ['px', 'em'], - { - ignoreProperties: { - rem: ['line-height', 'margin', /^border/], - '%': ['width', 'height'], - }, - }, - ], - - accept: [ - { - code: 'a { border: 1rem solid purple; }', - }, - { - code: 'a { border-bottom-width: 6rem; }', - }, - ], - - reject: [ - { - code: 'a { font-size: 80%; }', - message: messages.rejected('%'), - line: 1, - column: 16, - }, - ], -}); diff --git a/lib/rules/unit-whitelist/index.js b/lib/rules/unit-whitelist/index.js deleted file mode 100644 index 86eea330e9..0000000000 --- a/lib/rules/unit-whitelist/index.js +++ /dev/null @@ -1,92 +0,0 @@ -// @ts-nocheck - -'use strict'; - -const _ = require('lodash'); -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const getUnitFromValueNode = require('../../utils/getUnitFromValueNode'); -const optionsMatches = require('../../utils/optionsMatches'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateObjectWithArrayProps = require('../../utils/validateObjectWithArrayProps'); -const validateOptions = require('../../utils/validateOptions'); -const valueParser = require('postcss-value-parser'); - -const ruleName = 'unit-whitelist'; - -const messages = ruleMessages(ruleName, { - rejected: (unit) => `Unexpected unit "${unit}"`, -}); - -function rule(listInput, options) { - const list = [].concat(listInput); - - return (root, result) => { - const validOptions = validateOptions( - result, - ruleName, - { - actual: list, - possible: [_.isString], - }, - { - optional: true, - actual: options, - possible: { - ignoreProperties: validateObjectWithArrayProps([_.isString, _.isRegExp]), - }, - }, - ); - - if (!validOptions) { - return; - } - - result.warn(`'${ruleName}' has been deprecated. Instead use 'unit-allowed-list'.`, { - stylelintType: 'deprecation', - stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, - }); - - function check(node, value, getIndex) { - // make sure multiplication operations (*) are divided - not handled - // by postcss-value-parser - value = value.replace(/\*/g, ','); - valueParser(value).walk((valueNode) => { - // Ignore wrong units within `url` function - if (valueNode.type === 'function' && valueNode.value.toLowerCase() === 'url') { - return false; - } - - const unit = getUnitFromValueNode(valueNode); - - if (!unit || (unit && list.includes(unit.toLowerCase()))) { - return; - } - - if (options && optionsMatches(options.ignoreProperties, unit.toLowerCase(), node.prop)) { - return; - } - - report({ - index: getIndex(node) + valueNode.sourceIndex, - message: messages.rejected(unit), - node, - result, - ruleName, - }); - }); - } - - root.walkAtRules(/^media$/i, (atRule) => check(atRule, atRule.params, atRuleParamIndex)); - root.walkDecls((decl) => check(decl, decl.value, declarationValueIndex)); - }; -} - -rule.primaryOptionArray = true; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = { deprecated: true }; - -module.exports = rule;