diff --git a/.changeset/rare-squids-tell.md b/.changeset/rare-squids-tell.md new file mode 100644 index 0000000000..caafeede7a --- /dev/null +++ b/.changeset/rare-squids-tell.md @@ -0,0 +1,5 @@ +--- +"stylelint": major +--- + +Removed: 76 rules deprecated in 15.0.0 diff --git a/docs/migration-guide/to-15.md b/docs/migration-guide/to-15.md index 0c5d432e0a..7462e893be 100644 --- a/docs/migration-guide/to-15.md +++ b/docs/migration-guide/to-15.md @@ -11,7 +11,84 @@ Two significant changes may affect you: ### Deprecated stylistic rules -We've deprecated [76 of the rules that enforce stylistic conventions](../user-guide/rules.md#deprecated), e.g. `indentation`. +We've deprecated 76 of the rules that enforce stylistic conventions: + +- `at-rule-name-case` +- `at-rule-name-newline-after` +- `at-rule-name-space-after` +- `at-rule-semicolon-newline-after` +- `at-rule-semicolon-space-before` +- `block-closing-brace-empty-line-before` +- `block-closing-brace-newline-after` +- `block-closing-brace-newline-before` +- `block-closing-brace-space-after` +- `block-closing-brace-space-before` +- `block-opening-brace-newline-after` +- `block-opening-brace-newline-before` +- `block-opening-brace-space-after` +- `block-opening-brace-space-before` +- `color-hex-case` +- `declaration-bang-space-after` +- `declaration-bang-space-before` +- `declaration-block-semicolon-newline-after` +- `declaration-block-semicolon-newline-before` +- `declaration-block-semicolon-space-after` +- `declaration-block-semicolon-space-before` +- `declaration-block-trailing-semicolon` +- `declaration-colon-newline-after` +- `declaration-colon-space-after` +- `declaration-colon-space-before` +- `function-comma-newline-after` +- `function-comma-newline-before` +- `function-comma-space-after` +- `function-comma-space-before` +- `function-max-empty-lines` +- `function-parentheses-newline-inside` +- `function-parentheses-space-inside` +- `function-whitespace-after` +- `indentation` +- `linebreaks` +- `max-empty-lines` +- `max-line-length` +- `media-feature-colon-space-after` +- `media-feature-colon-space-before` +- `media-feature-name-case` +- `media-feature-parentheses-space-inside` +- `media-feature-range-operator-space-after` +- `media-feature-range-operator-space-before` +- `media-query-list-comma-newline-after` +- `media-query-list-comma-newline-before` +- `media-query-list-comma-space-after` +- `media-query-list-comma-space-before` +- `no-empty-first-line` +- `no-eol-whitespace` +- `no-extra-semicolons` +- `no-missing-end-of-source-newline` +- `number-leading-zero` +- `number-no-trailing-zeros` +- `property-case` +- `selector-attribute-brackets-space-inside` +- `selector-attribute-operator-space-after` +- `selector-attribute-operator-space-before` +- `selector-combinator-space-after` +- `selector-combinator-space-before` +- `selector-descendant-combinator-no-non-space` +- `selector-list-comma-newline-after` +- `selector-list-comma-newline-before` +- `selector-list-comma-space-after` +- `selector-list-comma-space-before` +- `selector-max-empty-lines` +- `selector-pseudo-class-case` +- `selector-pseudo-class-parentheses-space-inside` +- `selector-pseudo-element-case` +- `string-quotes` +- `unicode-bom` +- `unit-case` +- `value-list-comma-newline-after` +- `value-list-comma-newline-before` +- `value-list-comma-space-after` +- `value-list-comma-space-before` +- `value-list-max-empty-lines` When we created these rules, pretty printers (like [Prettier](https://prettier.io/)) didn't exist. They now offer a better way to consistently format code, especially whitespace. Linters and pretty printers are complementary tools that work together to help you write consistent and error-free code. @@ -20,7 +97,7 @@ By deprecating these rules, we can: - focus on writing and maintaining rules that help you [avoid errors](../user-guide/rules.md#avoid-errors) and [enforce (non-stylistic) conventions](../user-guide/rules.md#enforce-conventions), both of which are unique to Stylelint - modernize our codebase, e.g. move to ESM so that we can update our dependencies and keep Stylelint secure for you -The [deprecated rules](../user-guide/rules.md#deprecated) will still work in this release (with a deprecation warning). In preparation for the next major release, when we'll remove the rules from Stylelint, we suggest: +The deprecated rules will still work in this release (with a deprecation warning). In preparation for the next major release, when we'll remove the rules from Stylelint, we suggest: - extending the [standard config](https://www.npmjs.com/package/stylelint-config-standard) in your configuration object, if you don't already - removing the deprecated rules from your configuration object @@ -43,7 +120,7 @@ Additionally, you may no longer need to extend [Prettier's Stylelint config](htt } ``` -We've removed the [deprecated rules](../user-guide/rules.md#deprecated) from the latest version of the [standard config](https://www.npmjs.com/package/stylelint-config-standard). It still helps you write consistent CSS by turning on many of the [other rules that enforce conventions](../user-guide/rules.md#enforce-conventions), e.g. most of the [`*-notation`](../user-guide/rules.md#notation), [`*-pattern`](../user-guide/rules.md#pattern) and [`*-quotes`](../user-guide/rules.md#quotes) rules. +We've removed the deprecated rules from the latest version of the [standard config](https://www.npmjs.com/package/stylelint-config-standard). It still helps you write consistent CSS by turning on many of the [other rules that enforce conventions](../user-guide/rules.md#enforce-conventions), e.g. most of the [`*-notation`](../user-guide/rules.md#notation), [`*-pattern`](../user-guide/rules.md#pattern) and [`*-quotes`](../user-guide/rules.md#quotes) rules. There are lots of other rules we don't turn on in the [standard config](https://www.npmjs.com/package/stylelint-config-standard) and you can learn more about using them to customize Stylelint to your exact needs in our [new guide](../user-guide/customize.md). diff --git a/docs/migration-guide/to-16.md b/docs/migration-guide/to-16.md new file mode 100644 index 0000000000..d566609977 --- /dev/null +++ b/docs/migration-guide/to-16.md @@ -0,0 +1,7 @@ +# Migrating to 16.0.0 + +This release contains breaking changes. + +## Removed deprecated stylistic rules + +We've removed the stylistic rules we deprecated in 15.0.0. See the [15.0.0 migration guide](./to-15.md) for details on how to migrate. diff --git a/docs/user-guide/options.md b/docs/user-guide/options.md index ea3ced9cb3..ba8cd77129 100644 --- a/docs/user-guide/options.md +++ b/docs/user-guide/options.md @@ -42,7 +42,7 @@ When using the Node.js API, the autofixed code is available as the value of the If a source contains a: -- scoped disable comment, e.g. `/* stylelint-disable indentation */`, any problems reported by the scoped rules will not be automatically fixed anywhere in the source +- scoped disable comment, e.g. `/* stylelint-disable color-named */`, any problems reported by the scoped rules will not be automatically fixed anywhere in the source - unscoped disable comment, i.e. `/* stylelint-disable */`, the entirety of source will not be automatically fixed This limitation in being tracked in [issue #2643](https://github.com/stylelint/stylelint/issues/2643). diff --git a/docs/user-guide/rules.md b/docs/user-guide/rules.md index 575b1b12d8..c75ce43ed5 100644 --- a/docs/user-guide/rules.md +++ b/docs/user-guide/rules.md @@ -388,196 +388,4 @@ Require or disallow whitespace on the inside with this `whitespace-inside` rule. | | | | | :-- | :-: | :-: | | [`comment-whitespace-inside`](../../lib/rules/comment-whitespace-inside/README.md)
Require or disallow whitespace on the inside of comment markers. | ✅ | 🔧 | - -## Deprecated - -These rules are deprecated — we won't fix bugs nor add options, and we will remove them in the next major release. We recommend you use a pretty printer (like Prettier) alongside Stylelint rather than these rules. - - -### Color - - -| | | | -| :-- | :-: | :-: | -| [`color-hex-case`](../../lib/rules/color-hex-case/README.md)
Specify lowercase or uppercase for hex colors. | | 🔧 | - - -### Function - - -| | | | -| :-- | :-: | :-: | -| [`function-comma-newline-after`](../../lib/rules/function-comma-newline-after/README.md)
Require a newline or disallow whitespace after the commas of functions. | | 🔧 | -| [`function-comma-newline-before`](../../lib/rules/function-comma-newline-before/README.md)
Require a newline or disallow whitespace before the commas of functions. | | 🔧 | -| [`function-comma-space-after`](../../lib/rules/function-comma-space-after/README.md)
Require a single space or disallow whitespace after the commas of functions. | | 🔧 | -| [`function-comma-space-before`](../../lib/rules/function-comma-space-before/README.md)
Require a single space or disallow whitespace before the commas of functions. | | 🔧 | -| [`function-max-empty-lines`](../../lib/rules/function-max-empty-lines/README.md)
Limit the number of adjacent empty lines within functions. | | 🔧 | -| [`function-parentheses-newline-inside`](../../lib/rules/function-parentheses-newline-inside/README.md)
Require a newline or disallow whitespace on the inside of the parentheses of functions. | | 🔧 | -| [`function-parentheses-space-inside`](../../lib/rules/function-parentheses-space-inside/README.md)
Require a single space or disallow whitespace on the inside of the parentheses of functions. | | 🔧 | -| [`function-whitespace-after`](../../lib/rules/function-whitespace-after/README.md)
Require or disallow whitespace after functions. | | 🔧 | - - -### Number - - -| | | | -| :-- | :-: | :-: | -| [`number-leading-zero`](../../lib/rules/number-leading-zero/README.md)
Require or disallow a leading zero for fractional numbers less than 1. | | 🔧 | -| [`number-no-trailing-zeros`](../../lib/rules/number-no-trailing-zeros/README.md)
Disallow trailing zeros in numbers. | | 🔧 | - - -### String - - -| | | | -| :-- | :-: | :-: | -| [`string-quotes`](../../lib/rules/string-quotes/README.md)
Specify single or double quotes around strings. | | 🔧 | - - -### Unit - - -| | | | -| :-- | :-: | :-: | -| [`unit-case`](../../lib/rules/unit-case/README.md)
Specify lowercase or uppercase for units. | | 🔧 | - - -### Value list - - -| | | | -| :-- | :-: | :-: | -| [`value-list-comma-newline-after`](../../lib/rules/value-list-comma-newline-after/README.md)
Require a newline or disallow whitespace after the commas of value lists. | | 🔧 | -| [`value-list-comma-newline-before`](../../lib/rules/value-list-comma-newline-before/README.md)
Require a newline or disallow whitespace before the commas of value lists. | | | -| [`value-list-comma-space-after`](../../lib/rules/value-list-comma-space-after/README.md)
Require a single space or disallow whitespace after the commas of value lists. | | 🔧 | -| [`value-list-comma-space-before`](../../lib/rules/value-list-comma-space-before/README.md)
Require a single space or disallow whitespace before the commas of value lists. | | 🔧 | -| [`value-list-max-empty-lines`](../../lib/rules/value-list-max-empty-lines/README.md)
Limit the number of adjacent empty lines within value lists. | | 🔧 | - - -### Property - - -| | | | -| :-- | :-: | :-: | -| [`property-case`](../../lib/rules/property-case/README.md)
Specify lowercase or uppercase for properties. | | 🔧 | - - -### Declaration - - -| | | | -| :-- | :-: | :-: | -| [`declaration-bang-space-after`](../../lib/rules/declaration-bang-space-after/README.md)
Require a single space or disallow whitespace after the bang of declarations. | | 🔧 | -| [`declaration-bang-space-before`](../../lib/rules/declaration-bang-space-before/README.md)
Require a single space or disallow whitespace before the bang of declarations. | | 🔧 | -| [`declaration-colon-newline-after`](../../lib/rules/declaration-colon-newline-after/README.md)
Require a newline or disallow whitespace after the colon of declarations. | | 🔧 | -| [`declaration-colon-space-after`](../../lib/rules/declaration-colon-space-after/README.md)
Require a single space or disallow whitespace after the colon of declarations. | | 🔧 | -| [`declaration-colon-space-before`](../../lib/rules/declaration-colon-space-before/README.md)
Require a single space or disallow whitespace before the colon of declarations. | | 🔧 | - - -### Declaration block - - -| | | | -| :-- | :-: | :-: | -| [`declaration-block-semicolon-newline-after`](../../lib/rules/declaration-block-semicolon-newline-after/README.md)
Require a newline or disallow whitespace after the semicolons of declaration blocks. | | 🔧 | -| [`declaration-block-semicolon-newline-before`](../../lib/rules/declaration-block-semicolon-newline-before/README.md)
Require a newline or disallow whitespace before the semicolons of declaration blocks. | | | -| [`declaration-block-semicolon-space-after`](../../lib/rules/declaration-block-semicolon-space-after/README.md)
Require a single space or disallow whitespace after the semicolons of declaration blocks. | | 🔧 | -| [`declaration-block-semicolon-space-before`](../../lib/rules/declaration-block-semicolon-space-before/README.md)
Require a single space or disallow whitespace before the semicolons of declaration blocks. | | 🔧 | -| [`declaration-block-trailing-semicolon`](../../lib/rules/declaration-block-trailing-semicolon/README.md)
Require or disallow a trailing semicolon within declaration blocks. | | 🔧 | - - -### Block - - -| | | | -| :-- | :-: | :-: | -| [`block-closing-brace-empty-line-before`](../../lib/rules/block-closing-brace-empty-line-before/README.md)
Require or disallow an empty line before the closing brace of blocks. | | 🔧 | -| [`block-closing-brace-newline-after`](../../lib/rules/block-closing-brace-newline-after/README.md)
Require a newline or disallow whitespace after the closing brace of blocks. | | 🔧 | -| [`block-closing-brace-newline-before`](../../lib/rules/block-closing-brace-newline-before/README.md)
Require a newline or disallow whitespace before the closing brace of blocks. | | 🔧 | -| [`block-closing-brace-space-after`](../../lib/rules/block-closing-brace-space-after/README.md)
Require a single space or disallow whitespace after the closing brace of blocks. | | | -| [`block-closing-brace-space-before`](../../lib/rules/block-closing-brace-space-before/README.md)
Require a single space or disallow whitespace before the closing brace of blocks. | | 🔧 | -| [`block-opening-brace-newline-after`](../../lib/rules/block-opening-brace-newline-after/README.md)
Require a newline after the opening brace of blocks. | | 🔧 | -| [`block-opening-brace-newline-before`](../../lib/rules/block-opening-brace-newline-before/README.md)
Require a newline or disallow whitespace before the opening brace of blocks. | | 🔧 | -| [`block-opening-brace-space-after`](../../lib/rules/block-opening-brace-space-after/README.md)
Require a single space or disallow whitespace after the opening brace of blocks. | | 🔧 | -| [`block-opening-brace-space-before`](../../lib/rules/block-opening-brace-space-before/README.md)
Require a single space or disallow whitespace before the opening brace of blocks. | | 🔧 | - - -### Selector - - -| | | | -| :-- | :-: | :-: | -| [`selector-attribute-brackets-space-inside`](../../lib/rules/selector-attribute-brackets-space-inside/README.md)
Require a single space or disallow whitespace on the inside of the brackets within attribute selectors. | | 🔧 | -| [`selector-attribute-operator-space-after`](../../lib/rules/selector-attribute-operator-space-after/README.md)
Require a single space or disallow whitespace after operators within attribute selectors. | | 🔧 | -| [`selector-attribute-operator-space-before`](../../lib/rules/selector-attribute-operator-space-before/README.md)
Require a single space or disallow whitespace before operators within attribute selectors. | | 🔧 | -| [`selector-combinator-space-after`](../../lib/rules/selector-combinator-space-after/README.md)
Require a single space or disallow whitespace after the combinators of selectors. | | 🔧 | -| [`selector-combinator-space-before`](../../lib/rules/selector-combinator-space-before/README.md)
Require a single space or disallow whitespace before the combinators of selectors. | | 🔧 | -| [`selector-descendant-combinator-no-non-space`](../../lib/rules/selector-descendant-combinator-no-non-space/README.md)
Disallow non-space characters for descendant combinators of selectors. | | 🔧 | -| [`selector-max-empty-lines`](../../lib/rules/selector-max-empty-lines/README.md)
Limit the number of adjacent empty lines within selectors. | | 🔧 | -| [`selector-pseudo-class-case`](../../lib/rules/selector-pseudo-class-case/README.md)
Specify lowercase or uppercase for pseudo-class selectors. | | 🔧 | -| [`selector-pseudo-class-parentheses-space-inside`](../../lib/rules/selector-pseudo-class-parentheses-space-inside/README.md)
Require a single space or disallow whitespace on the inside of the parentheses within pseudo-class selectors. | | 🔧 | -| [`selector-pseudo-element-case`](../../lib/rules/selector-pseudo-element-case/README.md)
Specify lowercase or uppercase for pseudo-element selectors. | | 🔧 | - - -### Selector list - - -| | | | -| :-- | :-: | :-: | -| [`selector-list-comma-newline-after`](../../lib/rules/selector-list-comma-newline-after/README.md)
Require a newline or disallow whitespace after the commas of selector lists. | | 🔧 | -| [`selector-list-comma-newline-before`](../../lib/rules/selector-list-comma-newline-before/README.md)
Require a newline or disallow whitespace before the commas of selector lists. | | 🔧 | -| [`selector-list-comma-space-after`](../../lib/rules/selector-list-comma-space-after/README.md)
Require a single space or disallow whitespace after the commas of selector lists. | | 🔧 | -| [`selector-list-comma-space-before`](../../lib/rules/selector-list-comma-space-before/README.md)
Require a single space or disallow whitespace before the commas of selector lists. | | 🔧 | - - -### Media feature - - -| | | | -| :-- | :-: | :-: | -| [`media-feature-colon-space-after`](../../lib/rules/media-feature-colon-space-after/README.md)
Require a single space or disallow whitespace after the colon in media features. | | 🔧 | -| [`media-feature-colon-space-before`](../../lib/rules/media-feature-colon-space-before/README.md)
Require a single space or disallow whitespace before the colon in media features. | | 🔧 | -| [`media-feature-name-case`](../../lib/rules/media-feature-name-case/README.md)
Specify lowercase or uppercase for media feature names. | | 🔧 | -| [`media-feature-parentheses-space-inside`](../../lib/rules/media-feature-parentheses-space-inside/README.md)
Require a single space or disallow whitespace on the inside of the parentheses within media features. | | 🔧 | -| [`media-feature-range-operator-space-after`](../../lib/rules/media-feature-range-operator-space-after/README.md)
Require a single space or disallow whitespace after the range operator in media features. | | 🔧 | -| [`media-feature-range-operator-space-before`](../../lib/rules/media-feature-range-operator-space-before/README.md)
Require a single space or disallow whitespace before the range operator in media features. | | 🔧 | - - -### Media query list - - -| | | | -| :-- | :-: | :-: | -| [`media-query-list-comma-newline-after`](../../lib/rules/media-query-list-comma-newline-after/README.md)
Require a newline or disallow whitespace after the commas of media query lists. | | 🔧 | -| [`media-query-list-comma-newline-before`](../../lib/rules/media-query-list-comma-newline-before/README.md)
Require a newline or disallow whitespace before the commas of media query lists. | | | -| [`media-query-list-comma-space-after`](../../lib/rules/media-query-list-comma-space-after/README.md)
Require a single space or disallow whitespace after the commas of media query lists. | | 🔧 | -| [`media-query-list-comma-space-before`](../../lib/rules/media-query-list-comma-space-before/README.md)
Require a single space or disallow whitespace before the commas of media query lists. | | 🔧 | - - -### At-rule - - -| | | | -| :-- | :-: | :-: | -| [`at-rule-name-case`](../../lib/rules/at-rule-name-case/README.md)
Specify lowercase or uppercase for at-rules names. | | 🔧 | -| [`at-rule-name-newline-after`](../../lib/rules/at-rule-name-newline-after/README.md)
Require a newline after at-rule names. | | | -| [`at-rule-name-space-after`](../../lib/rules/at-rule-name-space-after/README.md)
Require a single space after at-rule names. | | 🔧 | -| [`at-rule-semicolon-newline-after`](../../lib/rules/at-rule-semicolon-newline-after/README.md)
Require a newline after the semicolon of at-rules. | | 🔧 | -| [`at-rule-semicolon-space-before`](../../lib/rules/at-rule-semicolon-space-before/README.md)
Require a single space or disallow whitespace before the semicolons of at-rules. | | | - - -### General / Sheet - - -| | | | -| :-- | :-: | :-: | -| [`indentation`](../../lib/rules/indentation/README.md)
Specify indentation. | | 🔧 | -| [`linebreaks`](../../lib/rules/linebreaks/README.md)
Specify unix or windows linebreaks. | | 🔧 | -| [`max-empty-lines`](../../lib/rules/max-empty-lines/README.md)
Limit the number of adjacent empty lines. | | 🔧 | -| [`max-line-length`](../../lib/rules/max-line-length/README.md)
Limit the length of a line. | | | -| [`no-empty-first-line`](../../lib/rules/no-empty-first-line/README.md)
Disallow empty first lines. | | 🔧 | -| [`no-eol-whitespace`](../../lib/rules/no-eol-whitespace/README.md)
Disallow end-of-line whitespace. | | 🔧 | -| [`no-extra-semicolons`](../../lib/rules/no-extra-semicolons/README.md)
Disallow extra semicolons. | | 🔧 | -| [`no-missing-end-of-source-newline`](../../lib/rules/no-missing-end-of-source-newline/README.md)
Disallow missing end-of-source newlines. | | 🔧 | -| [`unicode-bom`](../../lib/rules/unicode-bom/README.md)
Require or disallow Unicode BOM. | | | diff --git a/lib/__tests__/disableRanges-integration.test.mjs b/lib/__tests__/disableRanges-integration.test.mjs index 51ee6ccaec..e263f47015 100644 --- a/lib/__tests__/disableRanges-integration.test.mjs +++ b/lib/__tests__/disableRanges-integration.test.mjs @@ -1,7 +1,7 @@ import blockNoEmpty from '../rules/block-no-empty/index.js'; -import maxLineLength from '../rules/max-line-length/index.js'; -import selectorCombinatorSpaceBefore from '../rules/selector-combinator-space-before/index.js'; -import stringQuotes from '../rules/string-quotes/index.js'; +import noDuplicateSelectors from '../rules/no-duplicate-selectors/index.js'; +import numberMaxPrecision from '../rules/number-max-precision/index.js'; +import stringNoNewline from '../rules/string-no-newline/index.js'; // disabling all rules testRule({ @@ -92,13 +92,13 @@ testRule({ }); testRule({ - ruleName: selectorCombinatorSpaceBefore.ruleName, - config: ['always'], + ruleName: noDuplicateSelectors.ruleName, + config: true, reject: [ { - code: 'a> b {}', - message: selectorCombinatorSpaceBefore.messages.expectedBefore('>'), + code: 'a, a {}', + message: noDuplicateSelectors.messages.rejected('a', 1), }, ], }); @@ -141,29 +141,29 @@ testRule({ }); testRule({ - ruleName: selectorCombinatorSpaceBefore.ruleName, - config: ['always'], + ruleName: noDuplicateSelectors.ruleName, + config: true, accept: [ { - code: '/* stylelint-disable declaration-no-important, selector-combinator-space-before */ a> b {}', + code: '/* stylelint-disable declaration-no-important, no-duplicate-selectors */ a, a {}', }, { - code: '/* stylelint-disable-line declaration-no-important, selector-combinator-space-before */ a> b {}', + code: '/* stylelint-disable-line declaration-no-important, no-duplicate-selectors */ a, a {}', }, { - code: 'a> b {} /* stylelint-disable-line declaration-no-important, selector-combinator-space-before */', + code: 'a, a {} /* stylelint-disable-line declaration-no-important, no-duplicate-selectors */', }, ], reject: [ { - code: '/* stylelint-disable declaration-no-important */ a> b {}', - message: selectorCombinatorSpaceBefore.messages.expectedBefore('>'), + code: '/* stylelint-disable declaration-no-important */ a, a {}', + message: noDuplicateSelectors.messages.rejected('a', 1), }, { - code: '/* stylelint-disable-line declaration-no-important */\na> b {}', - message: selectorCombinatorSpaceBefore.messages.expectedBefore('>'), + code: '/* stylelint-disable-line declaration-no-important */\na, a {}', + message: noDuplicateSelectors.messages.rejected('a', 2), }, ], }); @@ -199,38 +199,38 @@ testRule({ }); testRule({ - ruleName: maxLineLength.ruleName, - config: [80], + ruleName: numberMaxPrecision.ruleName, + config: [2], accept: [ { code: ` /* stylelint-disable */ - .abracadabracadabra { background: linear-gradient(to top, rgba(255, 255, 255, 0.1), rgba (255, 255, 255, 1)); } + a { top: 0.123px; } /* stylelint-enable */ `, }, { code: ` - /* stylelint-disable-line */ .abracadabracadabra { background: linear-gradient(to top, rgba(255, 255, 255, 0.1), rgba (255, 255, 255, 1)); } + /* stylelint-disable-line */ a { top: 0.123px; } `, }, { code: ` - /* stylelint-disable max-line-length */ - .abracadabracadabra { background: linear-gradient(to top, rgba(255, 255, 255, 0.1), rgba (255, 255, 255, 1)); } - /* stylelint-enable max-line-length */ + /* stylelint-disable number-max-precision */ + a { top: 0.123px; } + /* stylelint-enable number-max-precision */ `, }, { code: ` - .abracadabracadabra { background: linear-gradient(to top, rgba(255, 255, 255, 0.1), rgba (255, 255, 255, 1)); } /* stylelint-disable-line max-line-length */ + a { top: 0.123px; } /* stylelint-disable-line number-max-precision */ `, }, { code: ` - /* stylelint-disable-next-line max-line-length */ - .abracadabracadabra { background: linear-gradient(to top, rgba(255, 255, 255, 0.1), rgba (255, 255, 255, 1)); } + /* stylelint-disable-next-line number-max-precision */ + a { top: 0.123px; } `, }, ], @@ -239,67 +239,67 @@ testRule({ { code: ` /* stylelint-disable block-no-empty */ - .abracadabracadabra { background: linear-gradient(to top, rgba(255, 255, 255, 0.1), rgba (255, 255, 255, 1)); } + a { top: 0.123px; } /* stylelint-enable block-no-empty */ `, - message: maxLineLength.messages.expected(80), + message: numberMaxPrecision.messages.expected('0.123', '0.12'), }, { code: ` /* stylelint-disable-line */ - .abracadabracadabra { background: linear-gradient(to top, rgba(255, 255, 255, 0.1), rgba (255, 255, 255, 1)); } + a { top: 0.123px; } `, - message: maxLineLength.messages.expected(80), + message: numberMaxPrecision.messages.expected('0.123', '0.12'), }, { code: ` - .abracadabracadabra { background: linear-gradient(to top, rgba(255, 255, 255, 0.1), rgba (255, 255, 255, 1)); } + a { top: 0.123px; } /* stylelint-disable-line */ `, - message: maxLineLength.messages.expected(80), + message: numberMaxPrecision.messages.expected('0.123', '0.12'), }, { code: ` - /* stylelint-disable max-line-length */ - .abracadabracadabra { background: linear-gradient(to top, rgba(255, 255, 255, 0.1), rgba (255, 255, 255, 1)); } - /* stylelint-enable max-line-length */ - .abracadabracadabra { background: linear-gradient(to top, rgba(255, 255, 255, 0.1), rgba (255, 255, 255, 1)); } + /* stylelint-disable number-max-precision */ + a { top: 0.123px; } + /* stylelint-enable number-max-precision */ + a { top: 0.123px; } `, - message: maxLineLength.messages.expected(80), + message: numberMaxPrecision.messages.expected('0.123', '0.12'), }, { code: ` - /* stylelint-disable-next-line max-line-length */ - .abracadabracadabra { background: linear-gradient(to top, rgba(255, 255, 255, 0.1), rgba (255, 255, 255, 1)); } - .abracadabracadabra { background: linear-gradient(to top, rgba(255, 255, 255, 0.1), rgba (255, 255, 255, 1)); } + /* stylelint-disable-next-line number-max-precision */ + a { top: 0.123px; } + a { top: 0.123px; } `, - message: maxLineLength.messages.expected(80), + message: numberMaxPrecision.messages.expected('0.123', '0.12'), }, ], }); testRule({ - ruleName: stringQuotes.ruleName, - config: ['single'], + ruleName: stringNoNewline.ruleName, + config: true, accept: [ { code: ` /* stylelint-disable */ - .foo { content: "horse"; } + .foo { content: "horse \n"; } /* stylelint-enable */ `, }, { code: ` - /* stylelint-disable string-quotes */ - .foo { content: "horse"; } - /* stylelint-enable string-quotes */ + /* stylelint-disable string-no-newline */ + .foo { content: "horse \n"; } + /* stylelint-enable string-no-newline */ `, }, ], @@ -308,21 +308,21 @@ testRule({ { code: ` /* stylelint-disable block-no-empty */ - .foo { content: "horse"; } + .foo { content: "horse \n"; } /* stylelint-enable block-no-empty */ `, - message: stringQuotes.messages.expected('single'), + message: stringNoNewline.messages.rejected, }, { code: ` - /* stylelint-disable string-quotes */ - .foo { content: "horse"; } - /* stylelint-enable string-quotes */ - .foo { content: "horse"; } + /* stylelint-disable string-no-newline */ + .foo { content: "horse \n"; } + /* stylelint-enable string-no-newline */ + .foo { content: "horse \n"; } `, - message: stringQuotes.messages.expected('single'), + message: stringNoNewline.messages.rejected, }, ], }); diff --git a/lib/__tests__/extends.test.mjs b/lib/__tests__/extends.test.mjs index 8a57823769..f471bc1025 100644 --- a/lib/__tests__/extends.test.mjs +++ b/lib/__tests__/extends.test.mjs @@ -77,10 +77,10 @@ it('extending configuration and no configBasedir', () => { it('extending a config that is overridden', async () => { const linted = await standalone({ - code: 'a { b: "c" }', + code: 'a { top: 0px; }', config: { - extends: [`${fixturesPath}/config-string-quotes-single`], - rules: { 'string-quotes': 'double' }, + extends: [`${fixturesPath}/config-length-zero-no-unit-true`], + rules: { 'length-zero-no-unit': false }, }, }); @@ -92,9 +92,9 @@ describe('extending a config from process.cwd', () => { it('works', async () => { const linted = await standalone({ - code: 'a { b: "c" }', + code: 'a { top: 0px; }', config: { - extends: ['./fixtures/config-string-quotes-single'], + extends: ['./fixtures/config-length-zero-no-unit-true'], }, }); @@ -105,9 +105,9 @@ describe('extending a config from process.cwd', () => { describe('extending a config from options.cwd', () => { it('works', async () => { const linted = await standalone({ - code: 'a { b: "c" }', + code: 'a { top: 0px; }', config: { - extends: ['./fixtures/config-string-quotes-single'], + extends: ['./fixtures/config-length-zero-no-unit-true'], }, cwd: fileURLToPath(new URL('.', import.meta.url)), }); diff --git a/lib/__tests__/fixtures/config-length-zero-no-unit-true.json b/lib/__tests__/fixtures/config-length-zero-no-unit-true.json new file mode 100644 index 0000000000..95574487ec --- /dev/null +++ b/lib/__tests__/fixtures/config-length-zero-no-unit-true.json @@ -0,0 +1,5 @@ +{ + "rules": { + "length-zero-no-unit": true + } +} diff --git a/lib/__tests__/fixtures/config-overrides/indent4.json b/lib/__tests__/fixtures/config-overrides/indent4.json deleted file mode 100644 index 9c99262695..0000000000 --- a/lib/__tests__/fixtures/config-overrides/indent4.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rules": { - "indentation": 4 - } -} diff --git a/lib/__tests__/fixtures/config-overrides/indent8.json b/lib/__tests__/fixtures/config-overrides/indent8.json deleted file mode 100644 index 9f42107a1f..0000000000 --- a/lib/__tests__/fixtures/config-overrides/indent8.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rules": { - "indentation": 8 - } -} diff --git a/lib/__tests__/fixtures/config-overrides/number-max-precision-4.json b/lib/__tests__/fixtures/config-overrides/number-max-precision-4.json new file mode 100644 index 0000000000..0d417f6da1 --- /dev/null +++ b/lib/__tests__/fixtures/config-overrides/number-max-precision-4.json @@ -0,0 +1,5 @@ +{ + "rules": { + "number-max-precision": 4 + } +} diff --git a/lib/__tests__/fixtures/config-overrides/number-max-precision-8.json b/lib/__tests__/fixtures/config-overrides/number-max-precision-8.json new file mode 100644 index 0000000000..d68b33e7e7 --- /dev/null +++ b/lib/__tests__/fixtures/config-overrides/number-max-precision-8.json @@ -0,0 +1,5 @@ +{ + "rules": { + "number-max-precision": 8 + } +} diff --git a/lib/__tests__/fixtures/config-overrides/precision.css b/lib/__tests__/fixtures/config-overrides/precision.css new file mode 100644 index 0000000000..adccacdbd8 --- /dev/null +++ b/lib/__tests__/fixtures/config-overrides/precision.css @@ -0,0 +1 @@ +a { top: 0.123456789px; } diff --git a/lib/__tests__/fixtures/config-string-quotes-single.json b/lib/__tests__/fixtures/config-string-quotes-single.json deleted file mode 100644 index 68195ea878..0000000000 --- a/lib/__tests__/fixtures/config-string-quotes-single.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rules": { - "string-quotes": "single" - } -} diff --git a/lib/__tests__/fixtures/plugin-array.js b/lib/__tests__/fixtures/plugin-array.js index 3f73cb9d30..17b07c3758 100644 --- a/lib/__tests__/fixtures/plugin-array.js +++ b/lib/__tests__/fixtures/plugin-array.js @@ -1,6 +1,6 @@ 'use strict'; -const conditionallyCheckColorHexCase = require('./plugin-conditionally-check-color-hex-case'); +const conditionallyCheckColorNamed = require('./plugin-conditionally-check-color-named'); const warnAboutFoo = require('./plugin-warn-about-foo'); -module.exports = [conditionallyCheckColorHexCase, warnAboutFoo]; +module.exports = [conditionallyCheckColorNamed, warnAboutFoo]; diff --git a/lib/__tests__/fixtures/plugin-conditionally-check-color-hex-case.js b/lib/__tests__/fixtures/plugin-conditionally-check-color-hex-case.js deleted file mode 100644 index 13ac58df39..0000000000 --- a/lib/__tests__/fixtures/plugin-conditionally-check-color-hex-case.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -const stylelint = require('../..'); - -const ruleName = 'plugin/conditionally-check-color-hex-case'; - -module.exports = stylelint.createPlugin(ruleName, (expectation, options, context) => { - const colorHexCaseRule = stylelint.rules['color-hex-case'](expectation, options, context); - - return (root, result) => { - if (!root.toString().includes('@@check-color-hex-case')) return; - - colorHexCaseRule(root, result); - }; -}); diff --git a/lib/__tests__/fixtures/plugin-conditionally-check-color-named.js b/lib/__tests__/fixtures/plugin-conditionally-check-color-named.js new file mode 100644 index 0000000000..86969ac4d0 --- /dev/null +++ b/lib/__tests__/fixtures/plugin-conditionally-check-color-named.js @@ -0,0 +1,15 @@ +'use strict'; + +const stylelint = require('../..'); + +const ruleName = 'plugin/conditionally-check-color-named'; + +module.exports = stylelint.createPlugin(ruleName, (expectation, options, context) => { + const colorNamedRule = stylelint.rules['color-named'](expectation, options, context); + + return (root, result) => { + if (!root.toString().includes('@@check-color-named')) return; + + colorNamedRule(root, result); + }; +}); diff --git a/lib/__tests__/integration.test.mjs b/lib/__tests__/integration.test.mjs index fb414f6cb4..0ec6077380 100644 --- a/lib/__tests__/integration.test.mjs +++ b/lib/__tests__/integration.test.mjs @@ -14,7 +14,7 @@ const fixtures = (...elem) => const config = { rules: { - 'block-opening-brace-newline-after': 'always', + 'color-named': 'always-where-possible', 'declaration-property-unit-disallowed-list': { width: ['px', 'em'], }, @@ -32,7 +32,9 @@ const config = { }; const css = stripIndent` - a { background: pink; } + a { + color: #000; + } b { height: 1rem; @@ -61,16 +63,16 @@ describe('integration test expecting warnings', () => { }); it('number and type', () => { - expect(result.messages).toHaveLength(6); + expect(result.messages).toHaveLength(5); expect(result.messages.every((m) => m.type === 'warning')).toBeTruthy(); expect(result.messages.every((m) => m.plugin === 'stylelint')).toBeTruthy(); }); - it('block-opening-brace-newline-after - string primary option', () => { - const error = result.messages.find((msg) => msg.rule === 'block-opening-brace-newline-after'); + it('color-named - string primary option', () => { + const error = result.messages.find((msg) => msg.rule === 'color-named'); expect(error).toBeTruthy(); - expect(error.text).toBe('Expected newline after "{" (block-opening-brace-newline-after)'); + expect(error.text).toBe('Expected "#000" to be "black" (color-named)'); expect(error.severity).toBe('error'); }); diff --git a/lib/__tests__/needlessDisables.test.mjs b/lib/__tests__/needlessDisables.test.mjs index 20858d76eb..67f7ceb73d 100644 --- a/lib/__tests__/needlessDisables.test.mjs +++ b/lib/__tests__/needlessDisables.test.mjs @@ -262,7 +262,7 @@ it('needlessDisables ignored case', async () => { it('needlessDisables true except', async () => { const config = { - rules: { 'color-hex-case': true }, + rules: { 'color-named': 'always-where-possible' }, }; const css = stripIndent` @@ -276,7 +276,7 @@ it('needlessDisables true except', async () => { a { color: pink; } /* stylelint-enable */ a { - b { color: pink; } /* stylelint-disable-line color-hex-case */ + b { color: pink; } /* stylelint-disable-line color-named */ } `; @@ -310,8 +310,8 @@ it('needlessDisables true except', async () => { line: 11, column: 21, endLine: 11, - endColumn: 63, - text: 'Needless disable for "color-hex-case"', + endColumn: 60, + text: 'Needless disable for "color-named"', rule: '--report-needless-disables', severity: 'error', }, @@ -320,7 +320,7 @@ it('needlessDisables true except', async () => { it('needlessDisables false except', async () => { const config = { - rules: { 'color-hex-case': true }, + rules: { 'color-named': 'always-where-possible' }, }; const css = stripIndent` @@ -334,14 +334,14 @@ it('needlessDisables false except', async () => { a { color: pink; } /* stylelint-enable */ a { - b { color: pink; } /* stylelint-disable-line color-hex-case */ + b { color: pink; } /* stylelint-disable-line color-named */ } `; const { results } = await standalone({ config, code: css, - reportNeedlessDisables: [false, { except: 'color-hex-case' }], + reportNeedlessDisables: [false, { except: 'color-named' }], }); expect(results).toHaveLength(1); @@ -350,8 +350,8 @@ it('needlessDisables false except', async () => { line: 11, column: 21, endLine: 11, - endColumn: 63, - text: 'Needless disable for "color-hex-case"', + endColumn: 60, + text: 'Needless disable for "color-named"', rule: '--report-needless-disables', severity: 'error', }, diff --git a/lib/__tests__/overrides.test.mjs b/lib/__tests__/overrides.test.mjs index 247154c732..bf27234c22 100644 --- a/lib/__tests__/overrides.test.mjs +++ b/lib/__tests__/overrides.test.mjs @@ -131,13 +131,13 @@ describe('single input file. all overrides are matching', () => { it('priority to apply overrides: apply overrides extends', async () => { const linted = await standalone({ - files: [path.join(fixturesPath, 'style.css')], + files: [path.join(fixturesPath, 'precision.css')], config: { - extends: [path.join(fixturesPath, 'indent4.json')], + extends: [path.join(fixturesPath, 'number-max-precision-4.json')], overrides: [ { files: ['*.css'], - extends: [path.join(fixturesPath, 'indent8.json')], + extends: [path.join(fixturesPath, 'number-max-precision-8.json')], }, ], }, @@ -146,26 +146,26 @@ describe('single input file. all overrides are matching', () => { expect(linted.results).toHaveLength(1); expect(linted.results[0].warnings).toHaveLength(1); - expect(linted.results[0].warnings[0].rule).toBe('indentation'); + expect(linted.results[0].warnings[0].rule).toBe('number-max-precision'); expect(linted.results[0].warnings[0].text).toBe( - 'Expected indentation of 8 spaces (indentation)', + 'Expected "0.123456789" to be "0.12345679" (number-max-precision)', ); }); it('priority to apply overrides: apply overrides rules', async () => { const linted = await standalone({ - files: [path.join(fixturesPath, 'style.css')], + files: [path.join(fixturesPath, 'precision.css')], config: { - extends: [path.join(fixturesPath, 'indent4.json')], + extends: [path.join(fixturesPath, 'number-max-precision-4.json')], rules: { - indentation: 3, + 'number-max-precision': 1, }, overrides: [ { files: ['*.css'], - extends: [path.join(fixturesPath, 'indent8.json')], + extends: [path.join(fixturesPath, 'number-max-precision-8.json')], rules: { - indentation: 'tab', + 'number-max-precision': 2, }, }, ], @@ -175,22 +175,24 @@ describe('single input file. all overrides are matching', () => { expect(linted.results).toHaveLength(1); expect(linted.results[0].warnings).toHaveLength(1); - expect(linted.results[0].warnings[0].rule).toBe('indentation'); - expect(linted.results[0].warnings[0].text).toBe('Expected indentation of 1 tab (indentation)'); + expect(linted.results[0].warnings[0].rule).toBe('number-max-precision'); + expect(linted.results[0].warnings[0].text).toBe( + 'Expected "0.123456789" to be "0.12" (number-max-precision)', + ); }); it('priority to apply overrides: apply rules', async () => { const linted = await standalone({ - files: [path.join(fixturesPath, 'style.css')], + files: [path.join(fixturesPath, 'precision.css')], config: { - extends: [path.join(fixturesPath, 'indent4.json')], + extends: [path.join(fixturesPath, 'number-max-precision-4.json')], rules: { - indentation: 'tab', + 'number-max-precision': 1, }, overrides: [ { files: ['*.css'], - extends: [path.join(fixturesPath, 'indent8.json')], + extends: [path.join(fixturesPath, 'number-max-precision-8.json')], }, ], }, @@ -199,8 +201,10 @@ describe('single input file. all overrides are matching', () => { expect(linted.results).toHaveLength(1); expect(linted.results[0].warnings).toHaveLength(1); - expect(linted.results[0].warnings[0].rule).toBe('indentation'); - expect(linted.results[0].warnings[0].text).toBe('Expected indentation of 1 tab (indentation)'); + expect(linted.results[0].warnings[0].rule).toBe('number-max-precision'); + expect(linted.results[0].warnings[0].text).toBe( + 'Expected "0.123456789" to be "0.1" (number-max-precision)', + ); }); // https://github.com/stylelint/stylelint/issues/5656 diff --git a/lib/__tests__/plugins.test.mjs b/lib/__tests__/plugins.test.mjs index ae91ca6c3a..d226f5e6da 100644 --- a/lib/__tests__/plugins.test.mjs +++ b/lib/__tests__/plugins.test.mjs @@ -155,65 +155,65 @@ it('plugin with ESM import()', async () => { }); describe('plugin using exposed rules via stylelint.rules', () => { - const cssWithDirectiveLower = '/** @@check-color-hex-case */ a { color: #eee; }'; - const cssWithDirectiveUpper = '/** @@check-color-hex-case */ a { color: #EEE; }'; - const cssWithoutDirectiveLower = 'a { color: #eee; }'; - const cssWithoutDirectiveUpper = 'a { color: #EEE; }'; + const cssWithDirectiveNever = '/** @@check-color-named */ a { color: #000; }'; + const cssWithDirectiveAlways = '/** @@check-color-named */ a { color: black; }'; + const cssWithoutDirectiveNever = 'a { color: #000; }'; + const cssWithoutDirectiveAlways = 'a { color: black; }'; const config = (expectation) => ({ config: { - plugins: [path.join(__dirname, 'fixtures/plugin-conditionally-check-color-hex-case')], + plugins: [path.join(__dirname, 'fixtures/plugin-conditionally-check-color-named')], rules: { - 'plugin/conditionally-check-color-hex-case': expectation, + 'plugin/conditionally-check-color-named': expectation, }, }, }); - it('with uppercase expectation and lowercase color', async () => { + it('with always expectation and never color', async () => { const result = await postcss() - .use(stylelint(config('upper'))) - .process(cssWithDirectiveLower, { from: undefined }); + .use(stylelint(config('always-where-possible'))) + .process(cssWithDirectiveNever, { from: undefined }); expect(result.warnings()).toHaveLength(1); - expect(result.warnings()[0].text).toBe('Expected "#eee" to be "#EEE" (color-hex-case)'); + expect(result.warnings()[0].text).toBe('Expected "#000" to be "black" (color-named)'); }); - it('with uppercase expectation and uppercase color', async () => { + it('with always expectation and always color', async () => { const result = await postcss() - .use(stylelint(config('upper'))) - .process(cssWithDirectiveUpper, { from: undefined }); + .use(stylelint(config('always-where-possible'))) + .process(cssWithDirectiveAlways, { from: undefined }); expect(result.warnings()).toHaveLength(0); }); - it('with lowercase expectation and uppercase color', async () => { + it('with never expectation and always color', async () => { const result = await postcss() - .use(stylelint(config('lower'))) - .process(cssWithDirectiveUpper, { from: undefined }); + .use(stylelint(config('never'))) + .process(cssWithDirectiveAlways, { from: undefined }); expect(result.warnings()).toHaveLength(1); - expect(result.warnings()[0].text).toBe('Expected "#EEE" to be "#eee" (color-hex-case)'); + expect(result.warnings()[0].text).toBe('Unexpected named color "black" (color-named)'); }); - it('with lowercase expectation and lowercase color', async () => { + it('with never expectation and never color', async () => { const result = await postcss() - .use(stylelint(config('lower'))) - .process(cssWithDirectiveLower, { from: undefined }); + .use(stylelint(config('never'))) + .process(cssWithDirectiveNever, { from: undefined }); expect(result.warnings()).toHaveLength(0); }); - it('with uppercase expectation and lowercase color without directive', async () => { + it('with always expectation and never color without directive', async () => { const result = await postcss() - .use(stylelint(config('upper'))) - .process(cssWithoutDirectiveLower, { from: undefined }); + .use(stylelint(config('always-where-possible'))) + .process(cssWithoutDirectiveNever, { from: undefined }); expect(result.warnings()).toHaveLength(0); }); - it('with uppercase expectation and uppercase color without directive', async () => { + it('with always expectation and always color without directive', async () => { const result = await postcss() - .use(stylelint(config('lower'))) - .process(cssWithoutDirectiveUpper, { from: undefined }); + .use(stylelint(config('never'))) + .process(cssWithoutDirectiveAlways, { from: undefined }); expect(result.warnings()).toHaveLength(0); }); @@ -223,7 +223,7 @@ describe('module providing an array of plugins', () => { const config = { plugins: [path.join(__dirname, 'fixtures/plugin-array')], rules: { - 'plugin/conditionally-check-color-hex-case': 'upper', + 'plugin/conditionally-check-color-named': 'always-where-possible', 'plugin/warn-about-foo': 'always', }, }; @@ -231,10 +231,10 @@ describe('module providing an array of plugins', () => { it('first plugin works', async () => { const result = await postcss() .use(stylelint(config)) - .process('@@check-color-hex-case a { color: #eee; }', { from: undefined }); + .process('@@check-color-named a { color: #000; }', { from: undefined }); expect(result.warnings()).toHaveLength(1); - expect(result.warnings()[0].text).toBe('Expected "#eee" to be "#EEE" (color-hex-case)'); + expect(result.warnings()[0].text).toBe('Expected "#000" to be "black" (color-named)'); }); it('second plugin works', async () => { diff --git a/lib/__tests__/reportUnknownRuleNames.test.mjs b/lib/__tests__/reportUnknownRuleNames.test.mjs index 64255dbb60..a3784592a0 100644 --- a/lib/__tests__/reportUnknownRuleNames.test.mjs +++ b/lib/__tests__/reportUnknownRuleNames.test.mjs @@ -3,7 +3,7 @@ import standalone from '../standalone.js'; it('test case (1)', async () => { const config = { rules: { - 'color-hex-cas': ['upper'], + 'color-namd': ['always-where-possible'], 'function-allowed-lst': ['scale'], }, }; @@ -21,8 +21,8 @@ it('test case (1)', async () => { endLine: 1, endColumn: 6, severity: 'error', - rule: 'color-hex-cas', - text: 'Unknown rule color-hex-cas. Did you mean color-hex-case?', + rule: 'color-namd', + text: 'Unknown rule color-namd. Did you mean color-named?', }); expect(results[0].warnings).toContainEqual({ line: 1, @@ -38,7 +38,7 @@ it('test case (1)', async () => { it('test case (2)', async () => { const config = { rules: { - 'color-hex-case': ['upper'], + 'color-named': ['always-where-possible'], 'function-allowed-lst': ['rgb'], }, }; @@ -62,7 +62,7 @@ it('test case (2)', async () => { expect(results[0].warnings).toContainEqual( expect.objectContaining({ severity: 'error', - rule: 'color-hex-case', + rule: 'color-named', }), ); }); diff --git a/lib/__tests__/standalone-fix.test.mjs b/lib/__tests__/standalone-fix.test.mjs index 8ec2071d2c..76ca3cf8fd 100644 --- a/lib/__tests__/standalone-fix.test.mjs +++ b/lib/__tests__/standalone-fix.test.mjs @@ -2,8 +2,6 @@ import { copyFile, readFile, rm } from 'fs/promises'; import { fileURLToPath } from 'node:url'; import path from 'node:path'; -import { stripIndent, stripIndents } from 'common-tags'; - import replaceBackslashes from '../testUtils/replaceBackslashes.mjs'; import safeChdir from '../testUtils/safeChdir.mjs'; import standalone from '../standalone.js'; @@ -14,16 +12,16 @@ const fixturesPath = (...elems) => it('outputs fixed code when input is code string', async () => { const result = await standalone({ - code: ' a { color: red; }', + code: 'a { color: #ffffff; }', config: { rules: { - indentation: 2, + 'color-hex-length': 'short', }, }, fix: true, }); - expect(result.output).toBe('a { color: red; }'); + expect(result.output).toBe('a { color: #fff; }'); }); it('fixes when enabled in config', async () => { @@ -39,35 +37,16 @@ it('fixes when enabled in config', async () => { expect(output).toBe('a { color: #fff; }'); }); -it('apply indentation autofix at last', async () => { - const result = await standalone({ - code: 'a {\nbox-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.2), inset 0 1px 2px 0 rgba(0, 0, 0, 0.1);\n}', - config: { - rules: { - indentation: 2, - 'value-list-comma-newline-after': 'always', - }, - }, - fix: true, - }); - - expect(result.output).toBe( - 'a {\n box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.1),\n 0 0 0 1px rgba(0, 0, 0, 0.2),\n inset 0 1px 2px 0 rgba(0, 0, 0, 0.1);\n}', - ); -}); - it("doesn't fix with stylelint-disable commands", async () => { const code = ` /* stylelint-disable */ - a { - color: red; - }`; + a { color: #ffffff; }`; const result = await standalone({ code, config: { rules: { - indentation: 2, + 'color-hex-length': 'short', }, }, fix: true, @@ -78,16 +57,14 @@ it("doesn't fix with stylelint-disable commands", async () => { it("doesn't fix with scoped stylelint-disable commands", async () => { const code = ` - /* stylelint-disable indentation */ - a { - color: red; - }`; + /* stylelint-disable color-hex-length */ + a { color: #ffffff; }`; const result = await standalone({ code, config: { rules: { - indentation: 2, + 'color-hex-length': 'short', }, }, fix: true, @@ -98,17 +75,18 @@ it("doesn't fix with scoped stylelint-disable commands", async () => { it("doesn't fix with multiple scoped stylelint-disable commands", async () => { const code = ` - /* stylelint-disable indentation, color-hex-length */ + /* stylelint-disable declaration-block-no-duplicate-properties, color-hex-length */ a { color: #ffffff; + color: orange; }`; const result = await standalone({ code, config: { rules: { - indentation: 2, 'color-hex-length': 'short', + 'declaration-block-no-duplicate-properties': true, }, }, fix: true, @@ -117,50 +95,21 @@ it("doesn't fix with multiple scoped stylelint-disable commands", async () => { expect(result.output).toBe(code); }); -it("the color-hex-length rule doesn't fix with scoped stylelint-disable commands", async () => { - const result = await standalone({ - code: stripIndent` - /* stylelint-disable color-hex-length */ - a { - color: #ffffff; - }`, - config: { - rules: { - indentation: 2, - 'color-hex-length': 'short', - }, - }, - fix: true, - }); - - expect(result.output).toBe(stripIndent` - /* stylelint-disable color-hex-length */ - a { - color: #ffffff; - }`); -}); - -it("the indentation rule doesn't fix with scoped stylelint-disable commands", async () => { +it("doesn't fix with a scoped stylelint-disable command, but does fix other rules", async () => { const result = await standalone({ - code: stripIndent` - /* stylelint-disable indentation */ - a { - color: #ffffff; - }`, + code: '/* stylelint-disable declaration-block-no-duplicate-properties */ a { color: #ffffff; color: orange; }', config: { rules: { - indentation: 2, 'color-hex-length': 'short', + 'declaration-block-no-duplicate-properties': true, }, }, fix: true, }); - expect(result.output).toBe(stripIndent` - /* stylelint-disable indentation */ - a { - color: #fff; - }`); + expect(result.output).toBe( + '/* stylelint-disable declaration-block-no-duplicate-properties */ a { color: #fff; color: orange; }', + ); }); describe('writing fixes to files', () => { @@ -241,15 +190,15 @@ describe('writing fixes to files', () => { it('one rule being disabled', async () => { const code = ` a { - color: red; + color: #ffffff; }`; const result = await standalone({ code, config: { rules: { - indentation: [ - 2, + 'color-hex-length': [ + 'short', { disableFix: true, }, @@ -265,22 +214,22 @@ it('one rule being disabled', async () => { it('two rules being disabled', async () => { const code = ` - a { - COLOR: red; + a, a { + color: #ffffff; }`; const result = await standalone({ code, config: { rules: { - indentation: [ - 2, + 'color-hex-length': [ + 'short', { disableFix: true, }, ], - 'property-case': [ - 'lower', + 'no-duplicate-selectors': [ + true, { disableFix: true, }, @@ -292,29 +241,32 @@ it('two rules being disabled', async () => { const warnings = result.results[0].warnings; - expect(warnings.some((w) => w.text === 'Expected indentation of 0 spaces (indentation)')).toBe( - true, - ); - expect(warnings.some((w) => w.text === 'Expected "COLOR" to be "color" (property-case)')).toBe( - true, - ); + expect( + warnings.some((w) => w.text === 'Expected "#ffffff" to be "#fff" (color-hex-length)'), + ).toBe(true); + expect( + warnings.some( + (w) => + w.text === + 'Unexpected duplicate selector "a", first used at line 2 (no-duplicate-selectors)', + ), + ).toBe(true); expect(result.output).toBe(code); }); it('one rule being disabled and another still autofixing', async () => { - // use stripIndent to remove first linebreak that is also removed in the stripIndents expect - const code = stripIndent` - a { - COLOR: red; + const code = ` + a, a { + color: #ffffff; }`; const result = await standalone({ code, config: { rules: { - indentation: [0], - 'property-case': [ - 'lower', + 'color-hex-length': ['short'], + 'no-duplicate-selectors': [ + true, { disableFix: true, }, @@ -326,11 +278,19 @@ it('one rule being disabled and another still autofixing', async () => { const warnings = result.results[0].warnings; - expect(warnings.some((w) => w.text === 'Expected indentation of 0 spaces (indentation)')).toBe( - false, - ); - expect(warnings.some((w) => w.text === 'Expected "COLOR" to be "color" (property-case)')).toBe( - true, - ); - expect(result.output).toBe(stripIndents(code)); + expect( + warnings.some((w) => w.text === 'Expected "#ffffff" to be "#fff" (color-hex-length)'), + ).toBe(false); + expect( + warnings.some( + (w) => + w.text === + 'Unexpected duplicate selector "a", first used at line 2 (no-duplicate-selectors)', + ), + ).toBe(true); + + expect(result.output).toBe(` + a, a { + color: #fff; + }`); }); diff --git a/lib/__tests__/standalone-quiet-deprecation-warnings.test.mjs b/lib/__tests__/standalone-quiet-deprecation-warnings.test.mjs index 07e0e77e1a..760a08ef29 100644 --- a/lib/__tests__/standalone-quiet-deprecation-warnings.test.mjs +++ b/lib/__tests__/standalone-quiet-deprecation-warnings.test.mjs @@ -1,9 +1,30 @@ +import { createRequire } from 'node:module'; +import { jest } from '@jest/globals'; +import report from '../utils/report.js'; import standalone from '../standalone.js'; +jest.mock('../rules/block-no-empty'); + +const require = createRequire(import.meta.url); +const deprecatedRule = require('../rules/block-no-empty/index.js'); + +deprecatedRule.mockImplementation(() => { + return (root, result) => { + report({ + ruleName: 'block-no-empty', + message: 'Foo bar', + node: root, + result, + }); + }; +}); + +deprecatedRule.meta = { deprecated: true }; + it('standalone does not silence deprecation warnings by default', async () => { const config = { rules: { - 'color-hex-case': 'lower', + 'block-no-empty': true, }, }; @@ -16,7 +37,7 @@ it('standalone does not silence deprecation warnings by default', async () => { it('standalone silences deprecation warnings when passed --quiet-deprecation-warnings', async () => { const config = { rules: { - 'color-hex-case': 'lower', + 'block-no-empty': true, }, }; diff --git a/lib/rules/__tests__/index.test.mjs b/lib/rules/__tests__/index.test.mjs index 9af63d30d1..ca3e4458d8 100644 --- a/lib/rules/__tests__/index.test.mjs +++ b/lib/rules/__tests__/index.test.mjs @@ -46,7 +46,8 @@ describe('fixable rules', () => { }); }); -describe('deprecated rules', () => { +// eslint-disable-next-line jest/no-disabled-tests --- Leaving for future cases of deprecated rules. +describe.skip('deprecated rules', () => { const deprecatedRules = ruleEntries.filter(([, rule]) => rule.meta.deprecated); test.each(deprecatedRules)('"%s" should describe deprecation in the rules doc', async (name) => { diff --git a/lib/rules/at-rule-empty-line-before/README.md b/lib/rules/at-rule-empty-line-before/README.md index be564caf6a..ab06ed8e37 100644 --- a/lib/rules/at-rule-empty-line-before/README.md +++ b/lib/rules/at-rule-empty-line-before/README.md @@ -16,7 +16,7 @@ This rule ignores: - at-rules that are the very first node in the source - `@import` in Less. -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. We recommend to enable [`indentation`](../indentation/README.md) rule for better autofixing results with this rule. +The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. ## Options diff --git a/lib/rules/at-rule-name-case/README.md b/lib/rules/at-rule-name-case/README.md deleted file mode 100644 index ceeaf64d45..0000000000 --- a/lib/rules/at-rule-name-case/README.md +++ /dev/null @@ -1,112 +0,0 @@ -# at-rule-name-case - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Specify lowercase or uppercase for at-rules names. - - -```css - @media (min-width: 10px) {} -/** ↑ - * This at-rule name */ -``` - -Only lowercase at-rule names are valid in SCSS. - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix some of the problems reported by this rule. - -## Options - -`string`: `"lower"|"upper"` - -### `"lower"` - -The following patterns are considered problems: - - -```css -@Charset 'UTF-8'; -``` - - -```css -@cHarSeT 'UTF-8'; -``` - - -```css -@CHARSET 'UTF-8'; -``` - - -```css -@Media (min-width: 50em) {} -``` - - -```css -@mEdIa (min-width: 50em) {} -``` - - -```css -@MEDIA (min-width: 50em) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@charset 'UTF-8'; -``` - - -```css -@media (min-width: 50em) {} -``` - -### `"upper"` - -The following patterns are considered problems: - - -```css -@Charset 'UTF-8'; -``` - - -```css -@cHarSeT 'UTF-8'; -``` - - -```css -@charset 'UTF-8'; -``` - - -```css -@Media (min-width: 50em) {} -``` - - -```css -@mEdIa (min-width: 50em) {} -``` - - -```css -@media (min-width: 50em) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@CHARSET 'UTF-8'; -``` - - -```css -@MEDIA (min-width: 50em) {} -``` diff --git a/lib/rules/at-rule-name-case/__tests__/index.js b/lib/rules/at-rule-name-case/__tests__/index.js deleted file mode 100644 index a6747c62dd..0000000000 --- a/lib/rules/at-rule-name-case/__tests__/index.js +++ /dev/null @@ -1,295 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['lower'], - fix: true, - - accept: [ - { - code: "@charset 'UTF-8';", - }, - { - code: "@import 'test.css'", - }, - { - code: '@namespace url(XML-namespace-URL);', - }, - { - code: '@media screen {}', - }, - { - code: '@media (min-width: 50em) {}', - }, - { - code: '@media only screen and (min-width: 415px) { @keyframes pace-anim { 100% { opacity: 0; } } }', - }, - { - code: '@supports (animation-name: test) {}', - }, - { - code: "@document url(http://www.w3.org/), url-prefix(http://www.w3.org/Style/), domain(mozilla.org), regexp('https:.*')", - }, - { - code: '@page :first { margin: 1cm; }', - }, - { - code: '@keyframes { 0% { top: 0; } }', - }, - { - code: '@-webkit-keyframes { 0% { top: 0; } }', - }, - { - code: '@viewport { orientation: landscape; }', - }, - { - code: "@counter-style win-list { system: fixed; symbols: url(gold-medal.svg) url(silver-medal.svg) ; suffix: ' ';}", - }, - { - code: '@font-feature-values Font One { @styleset { nice-style: 12; } }', - }, - ], - - reject: [ - { - code: "@Charset 'UTF-8';", - fixed: "@charset 'UTF-8';", - message: messages.expected('Charset', 'charset'), - line: 1, - column: 1, - }, - { - code: "@cHaRsEt 'UTF-8';", - fixed: "@charset 'UTF-8';", - message: messages.expected('cHaRsEt', 'charset'), - line: 1, - column: 1, - }, - { - code: "@CHARSET 'UTF-8';", - fixed: "@charset 'UTF-8';", - message: messages.expected('CHARSET', 'charset'), - line: 1, - column: 1, - }, - { - code: '@Media screen {}', - fixed: '@media screen {}', - message: messages.expected('Media', 'media'), - line: 1, - column: 1, - }, - { - code: '@mEdIa screen {}', - fixed: '@media screen {}', - message: messages.expected('mEdIa', 'media'), - line: 1, - column: 1, - }, - { - code: '@MEDIA screen {}', - fixed: '@media screen {}', - message: messages.expected('MEDIA', 'media'), - line: 1, - column: 1, - }, - { - code: '@media only screen and (min-width: 415px) { @Keyframes pace-anim { 100% { opacity: 0; } } }', - fixed: - '@media only screen and (min-width: 415px) { @keyframes pace-anim { 100% { opacity: 0; } } }', - message: messages.expected('Keyframes', 'keyframes'), - line: 1, - column: 45, - }, - { - code: '@media only screen and (min-width: 415px) { @kEyFrAmEs pace-anim { 100% { opacity: 0; } } }', - fixed: - '@media only screen and (min-width: 415px) { @keyframes pace-anim { 100% { opacity: 0; } } }', - message: messages.expected('kEyFrAmEs', 'keyframes'), - line: 1, - column: 45, - }, - { - code: '@media only screen and (min-width: 415px) { @KEYFRAMES pace-anim { 100% { opacity: 0; } } }', - fixed: - '@media only screen and (min-width: 415px) { @keyframes pace-anim { 100% { opacity: 0; } } }', - message: messages.expected('KEYFRAMES', 'keyframes'), - line: 1, - column: 45, - }, - { - code: '@-WEBKIT-keyframes { 0% { top: 0; } }', - fixed: '@-webkit-keyframes { 0% { top: 0; } }', - message: messages.expected('-WEBKIT-keyframes', '-webkit-keyframes'), - line: 1, - column: 1, - }, - { - code: '@-WEBKIT-KEYFRAMES { 0% { top: 0; } }', - fixed: '@-webkit-keyframes { 0% { top: 0; } }', - message: messages.expected('-WEBKIT-KEYFRAMES', '-webkit-keyframes'), - line: 1, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: ['upper'], - fix: true, - - accept: [ - { - code: "@CHARSET 'UTF-8';", - }, - { - code: "@IMPORT 'test.css'", - }, - { - code: '@NAMESPACE url(XML-namespace-URL);', - }, - { - code: '@MEDIA screen {}', - }, - { - code: '@MEDIA (min-width: 50em) {}', - }, - { - code: '@MEDIA only screen and (min-width: 415px) { @KEYFRAMES pace-anim { 100% { opacity: 0; } } }', - }, - { - code: '@SUPPORTS (animation-name: test) {}', - }, - { - code: "@DOCUMENT url(http://www.w3.org/), url-prefix(http://www.w3.org/Style/), domain(mozilla.org), regexp('https:.*')", - }, - { - code: '@PAGE :first { margin: 1cm; }', - }, - { - code: '@KEYFRAMES { 0% { top: 0; } }', - }, - { - code: '@-WEBKIT-KEYFRAMES { 0% { top: 0; } }', - }, - { - code: '@VIEWPORT { orientation: landscape; }', - }, - { - code: "@COUNTER-STYLE win-list { system: fixed; symbols: url(gold-medal.svg) url(silver-medal.svg) ; suffix: ' ';}", - }, - { - code: '@FONT-FEATURE-VALUES Font One { @STYLESET { nice-style: 12; } }', - }, - ], - - reject: [ - { - code: "@Charset 'UTF-8';", - fixed: "@CHARSET 'UTF-8';", - message: messages.expected('Charset', 'CHARSET'), - line: 1, - column: 1, - }, - { - code: "@cHaRsEt 'UTF-8';", - fixed: "@CHARSET 'UTF-8';", - message: messages.expected('cHaRsEt', 'CHARSET'), - line: 1, - column: 1, - }, - { - code: "@charset 'UTF-8';", - fixed: "@CHARSET 'UTF-8';", - message: messages.expected('charset', 'CHARSET'), - line: 1, - column: 1, - }, - { - code: '@Media screen {}', - fixed: '@MEDIA screen {}', - message: messages.expected('Media', 'MEDIA'), - line: 1, - column: 1, - }, - { - code: '@mEdIa screen {}', - fixed: '@MEDIA screen {}', - message: messages.expected('mEdIa', 'MEDIA'), - line: 1, - column: 1, - }, - { - code: '@media screen {}', - fixed: '@MEDIA screen {}', - message: messages.expected('media', 'MEDIA'), - line: 1, - column: 1, - }, - { - code: '@MEDIA only screen and (min-width: 415px) { @Keyframes pace-anim { 100% { opacity: 0; } } }', - fixed: - '@MEDIA only screen and (min-width: 415px) { @KEYFRAMES pace-anim { 100% { opacity: 0; } } }', - message: messages.expected('Keyframes', 'KEYFRAMES'), - line: 1, - column: 45, - }, - { - code: '@MEDIA only screen and (min-width: 415px) { @kEyFrAmEs pace-anim { 100% { opacity: 0; } } }', - fixed: - '@MEDIA only screen and (min-width: 415px) { @KEYFRAMES pace-anim { 100% { opacity: 0; } } }', - message: messages.expected('kEyFrAmEs', 'KEYFRAMES'), - line: 1, - column: 45, - }, - { - code: '@MEDIA only screen and (min-width: 415px) { @keyframes pace-anim { 100% { opacity: 0; } } }', - fixed: - '@MEDIA only screen and (min-width: 415px) { @KEYFRAMES pace-anim { 100% { opacity: 0; } } }', - message: messages.expected('keyframes', 'KEYFRAMES'), - line: 1, - column: 45, - }, - { - code: '@-webkit-KEYFRAMES { 0% { top: 0; } }', - fixed: '@-WEBKIT-KEYFRAMES { 0% { top: 0; } }', - message: messages.expected('-webkit-KEYFRAMES', '-WEBKIT-KEYFRAMES'), - line: 1, - column: 1, - }, - { - code: '@-webkit-keyframes { 0% { top: 0; } }', - fixed: '@-WEBKIT-KEYFRAMES { 0% { top: 0; } }', - message: messages.expected('-webkit-keyframes', '-WEBKIT-KEYFRAMES'), - line: 1, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-less', - config: ['lower'], - - accept: [ - { - code: ` - .someMixin() { margin: 0; } - - span { .someMixin(); } - `, - description: 'ignore Less mixin', - }, - { - code: ` - @myVariable: #f7f8f9; - span { background-color: @myVariable; } - `, - description: 'ignore Less variable', - }, - ], -}); diff --git a/lib/rules/at-rule-name-case/index.js b/lib/rules/at-rule-name-case/index.js deleted file mode 100644 index fd73f46518..0000000000 --- a/lib/rules/at-rule-name-case/index.js +++ /dev/null @@ -1,67 +0,0 @@ -'use strict'; - -const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'at-rule-name-case'; - -const messages = ruleMessages(ruleName, { - expected: (actual, expected) => `Expected "${actual}" to be "${expected}"`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/at-rule-name-case', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondary, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['lower', 'upper'], - }); - - if (!validOptions) { - return; - } - - /** @type {'lower' | 'upper'} */ - const expectation = primary; - - root.walkAtRules((atRule) => { - if (!isStandardSyntaxAtRule(atRule)) { - return; - } - - const name = atRule.name; - - const expectedName = expectation === 'lower' ? name.toLowerCase() : name.toUpperCase(); - - if (name === expectedName) { - return; - } - - if (context.fix) { - atRule.name = expectedName; - - return; - } - - report({ - message: messages.expected(name, expectedName), - node: atRule, - ruleName, - result, - }); - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/at-rule-name-newline-after/README.md b/lib/rules/at-rule-name-newline-after/README.md deleted file mode 100644 index a9bfe63e2a..0000000000 --- a/lib/rules/at-rule-name-newline-after/README.md +++ /dev/null @@ -1,110 +0,0 @@ -# at-rule-name-newline-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline after at-rule names. - - -```css - @media - /*↑*/ (max-width: 600px) {} -/** ↑ - * The newline after this at-rule name */ -``` - -## Options - -`string`: `"always"|"always-multi-line"` - -### `"always"` - -There _must always_ be a newline after at-rule names. - -The following patterns are considered problems: - - -```css -@charset "UTF-8"; -``` - - -```css -@media (min-width: 700px) and - (orientation: landscape) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@charset - "UTF-8"; -``` - - -```css -@import - "x.css" screen and - (orientation:landscape); -``` - - -```css -@media - (min-width: 700px) and (orientation: landscape) {} -``` - - -```css -@media - (min-width: 700px) and - (orientation: landscape) {} -``` - -### `"always-multi-line"` - -There _must always_ be a newline after at-rule names in at-rules with multi-line parameters. - -The following patterns are considered problems: - - -```css -@import "x.css" screen and - (orientation:landscape); -``` - - -```css -@media (min-width: 700px) and - (orientation: landscape) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@charset "UTF-8"; -``` - - -```css -@charset - "UTF-8"; -``` - - -```css -@import "x.css" screen and (orientation:landscape); -``` - - -```css -@media (min-width: 700px) and (orientation: landscape) {} -``` - - -```css -@media - (min-width: 700px) and - (orientation: landscape) {} -``` diff --git a/lib/rules/at-rule-name-newline-after/__tests__/index.js b/lib/rules/at-rule-name-newline-after/__tests__/index.js deleted file mode 100644 index 4d6366b858..0000000000 --- a/lib/rules/at-rule-name-newline-after/__tests__/index.js +++ /dev/null @@ -1,397 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - - accept: [ - { - code: '@charset\n"UTF-8";', - }, - { - code: '@charset\r\n"UTF-8";', - }, - { - code: '@import\n"x.css";', - }, - { - code: '@import\n"x.css" screen and (orientation:landscape);', - }, - { - code: '@import\nurl("x.css");', - }, - { - code: '@import\nurl("x.css") screen and (orientation:landscape);', - }, - { - code: '@namespace\nurl(XML-namespace-URL);', - }, - { - code: '@media\n(min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@media\n(min-width: 700px)\nand (orientation: landscape) { }', - }, - { - code: '@media\r\n(min-width: 700px)\r\nand (orientation: landscape) { }', - }, - { - code: '@media\n(min-width: 700px) and\n(orientation: landscape) { }', - }, - { - code: '@media\n(min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@media\n(min-width: 700px) and (orientation: landscape)\n{ }', - }, - { - code: '@media\n(min-width: 700px) and (orientation: landscape)\r\n{ }', - }, - { - code: '@media\n(min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@media\n(min-width: 700px)\nand (orientation: landscape) { }', - }, - { - code: '@media\n(min-width: 700px)\r\nand (orientation: landscape) { }', - }, - { - code: '@supports\n(animation-name: test) { }', - }, - { - code: '@keyframes\nidentifier { }', - }, - { - code: '@-webkit-keyframes\nidentifier { }', - }, - { - code: '@viewport { }', - }, - { - code: '@viewport{ }', - }, - { - code: '@viewport\n{ }', - }, - { - code: '@viewport\r\n\r\n{ }', - }, - { - code: '@counter-style\nwinners-list { }', - }, - { - code: '@font-face { };', - }, - { - code: '@unknown\n"ident";', - }, - { - code: '@unknown\nident { };', - }, - { - code: 'a { color: pink; @crazy-custom-at-rule; }', - }, - { - code: '@charset\n\n"UTF-8";', - }, - { - code: '@charset\r\n\r\n"UTF-8";', - }, - { - code: '@media\n\n(width <= 100px) { }', - }, - ], - - reject: [ - { - code: '@charset "UTF-8";', - message: messages.expectedAfter('@charset'), - line: 1, - column: 8, - }, - { - code: '@charset"UTF-8";', - message: messages.expectedAfter('@charset'), - line: 1, - column: 8, - }, - { - code: '@charset "UTF-8";', - message: messages.expectedAfter('@charset'), - line: 1, - column: 8, - }, - { - code: '@media (width <= 100px) { }', - message: messages.expectedAfter('@media'), - line: 1, - column: 6, - }, - { - code: '@media(width <= 100px) { }', - message: messages.expectedAfter('@media'), - line: 1, - column: 6, - }, - { - code: '@media (width <= 100px) { }', - message: messages.expectedAfter('@media'), - line: 1, - column: 6, - }, - { - code: '@unknown "ident";', - message: messages.expectedAfter('@unknown'), - line: 1, - column: 8, - }, - { - code: '@unknown"ident";', - message: messages.expectedAfter('@unknown'), - line: 1, - column: 8, - }, - { - code: '@unknown"ident" { };', - message: messages.expectedAfter('@unknown'), - line: 1, - column: 8, - }, - { - code: '@unknown ident { };', - message: messages.expectedAfter('@unknown'), - line: 1, - column: 8, - }, - { - code: '@unknown ident { };', - message: messages.expectedAfter('@unknown'), - line: 1, - column: 8, - }, - { - code: '@-webkit-keyframes identifier { }', - message: messages.expectedAfter('@-webkit-keyframes'), - line: 1, - column: 18, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-less', - config: ['always'], - - accept: [ - { - code: '@nice-blue:#5B83AD;', - description: 'ignore variables', - }, - { - code: '@nice-blue: #5B83AD;', - description: 'ignore variables', - }, - { - code: '@nice-blue:\n#5B83AD;', - description: 'ignore variables', - }, - { - code: '@variable: .bucket; .@{variable} { }', - description: 'ignore interpolation', - }, - { - code: '@detached-ruleset: { background: red; }; .top { @detached-ruleset(); }', - description: 'ignore passing rulesets to mixins', - }, - { - code: '@my-ruleset: { .my-selector { background-color: black; } };', - }, - { - code: '.class1 { .mixin(#ddd) }', - description: 'ignore mixins', - }, - { - code: '.button { &-ok {} }', - description: 'ignore parent selectors', - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-scss', - config: ['always'], - - accept: [ - { - code: '@mixin\nmixin() { @content; }; .colors { @include\nmixin { color: $color; }}', - description: 'ignore content blocks', - }, - { - code: '@mixin\r\nmixin() { @content; }; .colors { @include\r\nmixin { color: $color; }}', - description: 'ignore content blocks', - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - - accept: [ - { - code: '@charset "UTF-8";', - }, - { - code: '@charset "UTF-8"\n;', - }, - { - code: '@charset "UTF-8";', - }, - { - code: '@charset"UTF-8";', - }, - { - code: '@charset\n"UTF-8";', - }, - { - code: '@charset\r\n"UTF-8";', - }, - { - code: '@import"x.css";', - }, - { - code: '@import "x.css";', - }, - { - code: '@import "x.css" screen and (orientation:landscape);', - }, - { - code: '@import url("x.css");', - }, - { - code: '@import\nurl("x.css");', - }, - { - code: '@import url("x.css") screen and (orientation:landscape);', - }, - { - code: '@namespace url(XML-namespace-URL);', - }, - { - code: '@media(min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@media (min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@media (min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@media (min-width: 700px) and (orientation: landscape)\n{ }', - }, - { - code: '@media\n(min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@media\r\n(min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@supports (animation-name: test) { }', - }, - { - code: '@supports(animation-name: test) { }', - }, - { - code: '@keyframes identifier { }', - }, - { - code: '@-webkit-keyframes identifier { }', - }, - { - code: '@viewport { }', - }, - { - code: '@viewport{ }', - }, - { - code: '@viewport\n{ }', - }, - { - code: '@viewport\n\n{ }', - }, - { - code: '@counter-style winners-list { }', - }, - { - code: '@font-face { };', - }, - { - code: '@unknown "ident";', - }, - { - code: '@unknown"ident";', - }, - { - code: '@unknown ident { };', - }, - { - code: '@charset\n\n"UTF-8";', - }, - { - code: '@charset\r\n\r\n"UTF-8";', - }, - { - code: '@media\n\n(min-width: 700px) and (orientation: landscape) { }', - }, - ], - - reject: [ - { - code: '@import url("x.css")\nscreen and (orientation:landscape);', - message: messages.expectedAfter('@import'), - line: 1, - column: 7, - }, - { - code: '@import url("x.css")\r\nscreen and (orientation:landscape);', - message: messages.expectedAfter('@import'), - line: 1, - column: 7, - }, - { - code: '@media (\nmin-width: 700px) and (orientation: landscape) { }', - message: messages.expectedAfter('@media'), - line: 1, - column: 6, - }, - { - code: '@media (\r\nmin-width: 700px) and (orientation: landscape) { }', - message: messages.expectedAfter('@media'), - line: 1, - column: 6, - }, - { - code: '@media (min-width: 700px\n) and (orientation: landscape) { }', - message: messages.expectedAfter('@media'), - line: 1, - column: 6, - }, - { - code: '@media (min-width\n: 700px) and (orientation: landscape) { }', - message: messages.expectedAfter('@media'), - line: 1, - column: 6, - }, - { - code: '@media (min-width:\n700px) and (orientation: landscape) { }', - message: messages.expectedAfter('@media'), - line: 1, - column: 6, - }, - ], -}); diff --git a/lib/rules/at-rule-name-newline-after/index.js b/lib/rules/at-rule-name-newline-after/index.js deleted file mode 100644 index d04dbb312c..0000000000 --- a/lib/rules/at-rule-name-newline-after/index.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict'; - -const atRuleNameSpaceChecker = require('../atRuleNameSpaceChecker'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'at-rule-name-newline-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: (name) => `Expected newline after at-rule name "${name}"`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/at-rule-name-newline-after', - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary) => { - const checker = whitespaceChecker('newline', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'always-multi-line'], - }); - - if (!validOptions) { - return; - } - - atRuleNameSpaceChecker({ - root, - result, - locationChecker: checker.afterOneOnly, - checkedRuleName: ruleName, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/at-rule-name-space-after/README.md b/lib/rules/at-rule-name-space-after/README.md deleted file mode 100644 index 4f55d4156d..0000000000 --- a/lib/rules/at-rule-name-space-after/README.md +++ /dev/null @@ -1,119 +0,0 @@ -# at-rule-name-space-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space after at-rule names. - - -```css -@media (max-width: 600px) {} -/** ↑ - * The space after at-rule names */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"always-single-line"` - -### `"always"` - -There _must always_ be a single space after at-rule names. - -The following patterns are considered problems: - - -```css -@charset"UTF-8"; -``` - - -```css -@media(min-width: 700px) {} -``` - - -```css -@media (min-width: 700px) {} -``` - - -```css -@media -(min-width: 700px) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@charset "UTF-8"; -``` - - -```css -@import url("x.css"); -``` - - -```css -@media (min-width: 700px) {} -``` - -### `"always-single-line"` - -There _must always_ be a single space after at-rule names in single-line declaration blocks. - -The following patterns are considered problems: - - -```css -@charset"UTF-8"; -``` - - -```css -@media(min-width: 700px) {} -``` - - -```css -@media (min-width: 700px) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@charset "UTF-8"; -``` - - -```css -@import url("x.css"); -``` - - -```css -@media (min-width: 700px) {} -``` - - -```css -@media -(min-width: 700px) {} -``` - - -```css -@media(min-width: 700px) and - (orientation: portrait) {} -``` - - -```css -@media - (min-width: 700px) and - (orientation: portrait) {} -``` diff --git a/lib/rules/at-rule-name-space-after/__tests__/index.js b/lib/rules/at-rule-name-space-after/__tests__/index.js deleted file mode 100644 index b976655235..0000000000 --- a/lib/rules/at-rule-name-space-after/__tests__/index.js +++ /dev/null @@ -1,468 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: '@charset "UTF-8";', - }, - { - code: '@charset "UTF-8";', - }, - { - code: '@import "x.css";', - }, - { - code: '@import "x.css" screen and (orientation:landscape);', - }, - { - code: '@import url("x.css");', - }, - { - code: '@import url("x.css") screen and (orientation:landscape);', - }, - { - code: '@namespace url(XML-namespace-URL);', - }, - { - code: '@media (min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@media (min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@media (min-width: 700px) and (orientation: landscape)\n{ }', - }, - { - code: '@media (min-width: 700px) and (orientation: landscape)\r\n{ }', - }, - { - code: '@media (min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@media (min-width: 700px)\nand (orientation: landscape) { }', - }, - { - code: '@media (min-width: 700px)\r\nand (orientation: landscape) { }', - }, - { - code: '@supports (animation-name: test) { }', - }, - { - code: '@keyframes identifier { }', - }, - { - code: '@-webkit-keyframes identifier { }', - }, - { - code: '@viewport { }', - }, - { - code: '@viewport{ }', - }, - { - code: '@viewport\n{ }', - }, - { - code: '@viewport\r\n{ }', - }, - { - code: '@viewport\n\n{ }', - }, - { - code: '@viewport\r\n\r\n{ }', - }, - { - code: '@counter-style winners-list { }', - }, - { - code: '@font-face { };', - }, - { - code: '@unknown "ident";', - }, - { - code: '@unknown ident { };', - }, - { - code: 'a { color: pink; @crazy-custom-at-rule; }', - }, - ], - - reject: [ - { - code: '@charset"UTF-8";', - fixed: '@charset "UTF-8";', - message: messages.expectedAfter('@charset'), - line: 1, - column: 8, - }, - { - code: '@charset"UTF-8";', - fixed: '@charset "UTF-8";', - message: messages.expectedAfter('@charset'), - line: 1, - column: 8, - }, - { - code: '@charset "UTF-8";', - fixed: '@charset "UTF-8";', - message: messages.expectedAfter('@charset'), - line: 1, - column: 8, - }, - { - code: '@charset\n"UTF-8";', - fixed: '@charset "UTF-8";', - message: messages.expectedAfter('@charset'), - line: 1, - column: 8, - }, - { - code: '@charset\r\n"UTF-8";', - fixed: '@charset "UTF-8";', - message: messages.expectedAfter('@charset'), - line: 1, - column: 8, - }, - { - code: '@charset\n\n"UTF-8";', - fixed: '@charset "UTF-8";', - message: messages.expectedAfter('@charset'), - line: 1, - column: 8, - }, - { - code: '@charset\r\n\r\n"UTF-8";', - fixed: '@charset "UTF-8";', - message: messages.expectedAfter('@charset'), - line: 1, - column: 8, - }, - { - code: '@media(width <= 100px) { }', - fixed: '@media (width <= 100px) { }', - message: messages.expectedAfter('@media'), - line: 1, - column: 6, - }, - { - code: '@media\n(width <= 100px) { }', - fixed: '@media (width <= 100px) { }', - message: messages.expectedAfter('@media'), - line: 1, - column: 6, - }, - { - code: '@media\r\n(width <= 100px) { }', - fixed: '@media (width <= 100px) { }', - message: messages.expectedAfter('@media'), - line: 1, - column: 6, - }, - { - code: '@media (width <= 100px) { }', - fixed: '@media (width <= 100px) { }', - message: messages.expectedAfter('@media'), - line: 1, - column: 6, - }, - { - code: '@unknown"ident";', - fixed: '@unknown "ident";', - message: messages.expectedAfter('@unknown'), - line: 1, - column: 8, - }, - { - code: '@unknown"ident" { };', - fixed: '@unknown "ident" { };', - message: messages.expectedAfter('@unknown'), - line: 1, - column: 8, - }, - { - code: '@unknown ident { };', - fixed: '@unknown ident { };', - message: messages.expectedAfter('@unknown'), - line: 1, - column: 8, - }, - { - code: '@-webkit-keyframes ident { };', - fixed: '@-webkit-keyframes ident { };', - message: messages.expectedAfter('@-webkit-keyframes'), - line: 1, - column: 18, - }, - { - code: '@media/*comment*/(width <= 100px) { }', - fixed: '@media /*comment*/(width <= 100px) { }', - message: messages.expectedAfter('@media'), - line: 1, - column: 6, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-less', - config: ['always'], - - accept: [ - { - code: '@nice-blue:#5B83AD;', - description: 'ignore variables', - }, - { - code: '@nice-blue: #5B83AD;', - description: 'ignore variables', - }, - { - code: '@nice-blue:\n#5B83AD;', - description: 'ignore variables', - }, - { - code: '@variable: .bucket; .@{variable} { }', - description: 'ignore interpolation', - }, - { - code: '@detached-ruleset: { background: red; }; .top { @detached-ruleset(); }', - description: 'ignore passing rulesets to mixins', - }, - { - code: '@my-ruleset: { .my-selector { background-color: black; } };', - }, - { - code: '.class1 { .mixin(#ddd) }', - description: 'ignore mixins', - }, - { - code: '.button { &-ok {} }', - description: 'ignore parent selectors', - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-scss', - config: ['always'], - - accept: [ - { - code: '@mixin mixin() { @content; }; .colors { @include mixin { color: $color; }}', - description: 'ignore content blocks', - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: '@charset "UTF-8";', - }, - { - code: '@charset\n"UTF-8";', - }, - { - code: '@charset\r\n"UTF-8";', - }, - { - code: '@charset\n\n"UTF-8";', - }, - { - code: '@charset\r\n\r\n"UTF-8";', - }, - { - code: '@charset "UTF-8";', - }, - { - code: '@charset\n"UTF-8";', - }, - { - code: '@charset\r\n"UTF-8";', - }, - { - code: '@charset\n\n"UTF-8";', - }, - { - code: '@charset\r\n\r\n"UTF-8";', - }, - { - code: '@import "x.css";', - }, - { - code: '@import "x.css" screen and (orientation:landscape);', - }, - { - code: '@import url("x.css");', - }, - { - code: '@import\nurl("x.css");', - }, - { - code: '@import\r\nurl("x.css");', - }, - { - code: '@import url("x.css") screen and (orientation:landscape);', - }, - { - code: '@namespace url(XML-namespace-URL);', - }, - { - code: '@media (min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@media (min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@media (min-width: 700px) and (orientation: landscape)\n{ }', - }, - { - code: '@media (min-width: 700px) and (orientation: landscape)\r\n{ }', - }, - { - code: '@media (min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@media (min-width: 700px)\nand (orientation: landscape) { }', - }, - { - code: '@media (min-width: 700px)\r\nand (orientation: landscape) { }', - }, - { - code: '@media(min-width: 700px)\nand (orientation: landscape) { }', - }, - { - code: '@media(min-width: 700px)\r\nand (orientation: landscape) { }', - }, - { - code: '@media(min-width: 700px) and\n(orientation: landscape) { }', - }, - { - code: '@media(min-width: 700px) and\r\n(orientation: landscape) { }', - }, - { - code: '@media\n(min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@media\r\n(min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@supports (animation-name: test) { }', - }, - { - code: '@keyframes identifier { }', - }, - { - code: '@-webkit-keyframes identifier { }', - }, - { - code: '@viewport { }', - }, - { - code: '@viewport{ }', - }, - { - code: '@viewport\n{ }', - }, - { - code: '@viewport\r\n{ }', - }, - { - code: '@viewport\n\n{ }', - }, - { - code: '@viewport\r\n\r\n{ }', - }, - { - code: '@counter-style winners-list { }', - }, - { - code: '@font-face { };', - }, - { - code: '@unknown "ident";', - }, - { - code: '@unknown ident { };', - }, - ], - - reject: [ - { - code: '@charset"UTF-8";', - fixed: '@charset "UTF-8";', - message: messages.expectedAfter('@charset'), - line: 1, - column: 8, - }, - { - code: '@charset"UTF-8";', - fixed: '@charset "UTF-8";', - message: messages.expectedAfter('@charset'), - line: 1, - column: 8, - }, - { - code: '@charset "UTF-8";', - fixed: '@charset "UTF-8";', - message: messages.expectedAfter('@charset'), - line: 1, - column: 8, - }, - { - code: '@media(width <= 100px) { }', - fixed: '@media (width <= 100px) { }', - message: messages.expectedAfter('@media'), - line: 1, - column: 6, - }, - { - code: '@media (width <= 100px) { }', - fixed: '@media (width <= 100px) { }', - message: messages.expectedAfter('@media'), - line: 1, - column: 6, - }, - { - code: '@unknown"ident";', - fixed: '@unknown "ident";', - message: messages.expectedAfter('@unknown'), - line: 1, - column: 8, - }, - { - code: '@unknown"ident" { };', - fixed: '@unknown "ident" { };', - message: messages.expectedAfter('@unknown'), - line: 1, - column: 8, - }, - { - code: '@unknown ident { };', - fixed: '@unknown ident { };', - message: messages.expectedAfter('@unknown'), - line: 1, - column: 8, - }, - { - code: '@-webkit-keyframes ident { };', - fixed: '@-webkit-keyframes ident { };', - message: messages.expectedAfter('@-webkit-keyframes'), - line: 1, - column: 18, - }, - ], -}); diff --git a/lib/rules/at-rule-name-space-after/index.js b/lib/rules/at-rule-name-space-after/index.js deleted file mode 100644 index 473457dc70..0000000000 --- a/lib/rules/at-rule-name-space-after/index.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -const atRuleNameSpaceChecker = require('../atRuleNameSpaceChecker'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'at-rule-name-space-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: (name) => `Expected single space after at-rule name "${name}"`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/at-rule-name-space-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondary, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'always-single-line'], - }); - - if (!validOptions) { - return; - } - - atRuleNameSpaceChecker({ - root, - result, - locationChecker: checker.after, - checkedRuleName: ruleName, - fix: context.fix - ? (atRule) => { - if (typeof atRule.raws.afterName === 'string') { - atRule.raws.afterName = atRule.raws.afterName.replace(/^\s*/, ' '); - } - } - : null, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/at-rule-semicolon-newline-after/README.md b/lib/rules/at-rule-semicolon-newline-after/README.md deleted file mode 100644 index afebd702c8..0000000000 --- a/lib/rules/at-rule-semicolon-newline-after/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# at-rule-semicolon-newline-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline after the semicolon of at-rules. - - -```css -@import url("x.css"); -@import url("y.css"); -/** ↑ - * The newline after these semicolons */ -``` - -This rule allows an end-of-line comment followed by a newline. For example: - - -```css -@import url("x.css"); /* end-of-line comment */ - -a {} -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"` - -### `"always"` - -There _must always_ be a newline after the semicolon. - -The following patterns are considered problems: - - -```css -@import url("x.css"); @import url("y.css"); -``` - - -```css -@import url("x.css"); a {} -``` - -The following patterns are _not_ considered problems: - - -```css -@import url("x.css"); -@import url("y.css"); -``` - - -```css -@import url("x.css"); /* end-of-line comment */ -a {} -``` - - -```css -@import url("x.css"); - -a {} -``` diff --git a/lib/rules/at-rule-semicolon-newline-after/__tests__/index.js b/lib/rules/at-rule-semicolon-newline-after/__tests__/index.js deleted file mode 100644 index ed2ee5ab7d..0000000000 --- a/lib/rules/at-rule-semicolon-newline-after/__tests__/index.js +++ /dev/null @@ -1,147 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - accept: [ - { - code: '@foo;\na {}', - }, - { - code: "@import 'x.css';\na {}", - }, - { - code: "@iMpOrT 'x.css';\na {}", - }, - { - code: "@IMPORT 'x.css';\na {}", - }, - { - code: "@charset 'UTF-8';\na {}", - }, - { - code: "@charset 'UTF-8';\n@import 'x.css'", - }, - { - code: "@charset 'UTF-8';\n@import 'x.css'\na {}", - }, - { - code: '@namespace url(XML-namespace-URL);\na {}', - }, - { - code: "@import 'x.css'); /* comment */\n", - }, - { - code: "@import 'x.css');/* comment */\n", - }, - { - code: "@import 'x.css'); /* comment */\n", - }, - { - code: "@import 'x.css');\t/* comment */\n", - }, - { - code: "@import 'x.css'); \t/* comment */\n", - }, - { - code: "@charset 'UTF-8';\n@media {}", - }, - { - code: "@import 'x.css';\r\n", - description: 'windows', - }, - { - code: "@import 'x.css'; /* comment */\r\n", - description: 'windows', - }, - { - code: "@import 'x.css';", - description: 'single blockless rule', - }, - { - code: 'a{\n@extend .b;\n@extend .c\n}', - description: 'non-standard nested rule', - }, - { - code: '@font-face {}; a {}', - description: 'ignore at-rule with block', - }, - ], - - reject: [ - { - code: '@mixin foo; a {}', - fixed: '@mixin foo;\n a {}', - message: messages.expectedAfter(), - line: 1, - column: 12, - }, - { - code: '@mIxIn foo; a {}', - fixed: '@mIxIn foo;\n a {}', - message: messages.expectedAfter(), - line: 1, - column: 12, - }, - { - code: '@MIXIN foo; a {}', - fixed: '@MIXIN foo;\n a {}', - message: messages.expectedAfter(), - line: 1, - column: 12, - }, - { - code: '@import url("x.css"); @charset "UTF-8";', - fixed: '@import url("x.css");\n @charset "UTF-8";', - message: messages.expectedAfter(), - line: 1, - column: 22, - }, - { - code: '@charset "UTF-8"; a {};', - fixed: '@charset "UTF-8";\n a {};', - message: messages.expectedAfter(), - line: 1, - column: 18, - }, - { - code: 'a{\n@extend .b; @extend .c\n}', - fixed: 'a{\n@extend .b;\n @extend .c\n}', - message: messages.expectedAfter(), - line: 2, - column: 12, - }, - { - code: 'a{\r\n@extend .b; @extend .c\r\n}', - fixed: 'a{\r\n@extend .b;\r\n @extend .c\r\n}', - message: messages.expectedAfter(), - line: 2, - column: 12, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-less', - config: ['always'], - accept: [ - { - code: ` - .someMixin() { margin: 0; } - span { .someMixin(); } - `, - description: 'ignore Less mixin', - }, - { - code: ` - @myVariable: #f7f8f9; - span { background-color: @myVariable; } - `, - description: 'ignore Less variable', - }, - ], -}); diff --git a/lib/rules/at-rule-semicolon-newline-after/index.js b/lib/rules/at-rule-semicolon-newline-after/index.js deleted file mode 100644 index 0b93de65a0..0000000000 --- a/lib/rules/at-rule-semicolon-newline-after/index.js +++ /dev/null @@ -1,84 +0,0 @@ -'use strict'; - -const hasBlock = require('../../utils/hasBlock'); -const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule'); -const nextNonCommentNode = require('../../utils/nextNonCommentNode'); -const rawNodeString = require('../../utils/rawNodeString'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'at-rule-semicolon-newline-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected newline after ";"', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/at-rule-semicolon-newline-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondary, context) => { - const checker = whitespaceChecker('newline', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always'], - }); - - if (!validOptions) { - return; - } - - root.walkAtRules((atRule) => { - const nextNode = atRule.next(); - - if (!nextNode) { - return; - } - - if (hasBlock(atRule)) { - return; - } - - if (!isStandardSyntaxAtRule(atRule)) { - return; - } - - // Allow an end-of-line comment - const nodeToCheck = nextNonCommentNode(nextNode); - - if (!nodeToCheck) { - return; - } - - checker.afterOneOnly({ - source: rawNodeString(nodeToCheck), - index: -1, - err: (msg) => { - if (context.fix) { - nodeToCheck.raws.before = context.newline + nodeToCheck.raws.before; - } else { - report({ - message: msg, - node: atRule, - index: atRule.toString().length + 1, - result, - ruleName, - }); - } - }, - }); - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/at-rule-semicolon-space-before/README.md b/lib/rules/at-rule-semicolon-space-before/README.md deleted file mode 100644 index 2ee3251ef7..0000000000 --- a/lib/rules/at-rule-semicolon-space-before/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# at-rule-semicolon-space-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace before the semicolons of at-rules. - - -```css -@import "components/buttons"; -/** ↑ - * The space before this semicolon */ -``` - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a single space before the semicolons. - -The following pattern is considered a problem: - - -```css -@import "components/buttons"; -``` - -The following pattern is _not_ considered a problem: - - -```css -@import "components/buttons" ; -``` - -### `"never"` - -There _must never_ be a single space before the semicolons. - -The following pattern is considered a problem: - - -```css -@import "components/buttons" ; -``` - -The following pattern is _not_ considered a problem: - - -```css -@import "components/buttons"; -``` diff --git a/lib/rules/at-rule-semicolon-space-before/__tests__/index.js b/lib/rules/at-rule-semicolon-space-before/__tests__/index.js deleted file mode 100644 index 1d3102b73f..0000000000 --- a/lib/rules/at-rule-semicolon-space-before/__tests__/index.js +++ /dev/null @@ -1,170 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - - accept: [ - { - code: '@import "styles/mystyle" ;', - }, - { - code: '@font-face {\n font-family: "MyFont"; src: url("myfont.woff2") format("woff2");\n}', - }, - { - code: '@font-face {\n font-family: "MyFont"; src: url("myfont.woff2") format("woff2");\n};', - }, - { - code: 'a { color: @brand-primary; }', - }, - { - code: '@myatrule "valuehassemicolon;" ;', - }, - { - code: '@import url(http://www.example.com/location;withsemicolon) ;', - }, - { - code: '@import /*my styles;*/ "styles/mystyle" ;', - }, - { - code: "@import\nurl('landscape.css')\nprojection ;", - }, - ], - - reject: [ - { - code: '@import "styles/mystyle";', - message: messages.expectedBefore(), - line: 1, - column: 24, - }, - { - code: '@import "styles/mystyle" ;', - message: messages.expectedBefore(), - line: 1, - column: 26, - }, - { - code: '@import "styles/mystyle"\t;', - message: messages.expectedBefore(), - line: 1, - column: 25, - }, - { - code: '@import "styles/mystyle"\n;', - message: messages.expectedBefore(), - line: 1, - column: 25, - }, - { - code: '@import "styles/mystyle"\r\n;', - description: 'CRLF', - message: messages.expectedBefore(), - line: 1, - column: 26, - }, - { - code: "@import\nurl('landscape.css')\nprojection;", - message: messages.expectedBefore(), - line: 3, - column: 10, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - - accept: [ - { - code: '@import "styles/mystyle";', - }, - { - code: '@font-face {\n font-family: "MyFont" ; src: url("myfont.woff2") format("woff2") ;\n}', - }, - { - code: '@font-face {\n font-family: "MyFont" ; src: url("myfont.woff2") format("woff2") ;\n} ;', - }, - { - code: 'a { color: @brand-primary ; }', - }, - { - code: '@myatrule "valuehassemicolon ;";', - }, - { - code: '@import url(http://www.example.com/location+;withsemicolon);', - }, - { - code: '@import /*my styles ;*/ "styles/mystyle";', - }, - { - code: "@import\nurl('landscape.css')\nprojection;", - }, - ], - - reject: [ - { - code: '@import "styles/mystyle" ;', - message: messages.rejectedBefore(), - line: 1, - column: 25, - }, - { - code: '@import "styles/mystyle" ;', - message: messages.rejectedBefore(), - line: 1, - column: 26, - }, - { - code: '@import "styles/mystyle"\t;', - message: messages.rejectedBefore(), - line: 1, - column: 25, - }, - { - code: '@import "styles/mystyle"\n;', - message: messages.rejectedBefore(), - line: 1, - column: 25, - }, - { - code: '@import "styles/mystyle"\r\n;', - description: 'CRLF', - message: messages.rejectedBefore(), - line: 1, - column: 26, - }, - { - code: "@import\nurl('landscape.css')\nprojection ;", - message: messages.rejectedBefore(), - line: 3, - column: 11, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-less', - config: ['always'], - - accept: [ - { - code: ` - .someMixin() { margin: 0; } - span { .someMixin(); } - `, - description: 'ignore Less mixin', - }, - { - code: ` - @myVariable: #f7f8f9; - span { background-color: @myVariable; } - `, - description: 'ignore Less variable', - }, - ], -}); diff --git a/lib/rules/at-rule-semicolon-space-before/index.js b/lib/rules/at-rule-semicolon-space-before/index.js deleted file mode 100644 index b75d385317..0000000000 --- a/lib/rules/at-rule-semicolon-space-before/index.js +++ /dev/null @@ -1,68 +0,0 @@ -'use strict'; - -const hasBlock = require('../../utils/hasBlock'); -const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule'); -const rawNodeString = require('../../utils/rawNodeString'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'at-rule-semicolon-space-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected single space before ";"', - rejectedBefore: () => 'Unexpected whitespace before ";"', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/at-rule-semicolon-space-before', - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - root.walkAtRules((atRule) => { - if (hasBlock(atRule)) { - return; - } - - if (!isStandardSyntaxAtRule(atRule)) { - return; - } - - const nodeString = rawNodeString(atRule); - - checker.before({ - source: nodeString, - index: nodeString.length, - err: (m) => { - report({ - message: m, - node: atRule, - index: nodeString.length - 1, - result, - ruleName, - }); - }, - }); - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/atRuleNameSpaceChecker.js b/lib/rules/atRuleNameSpaceChecker.js deleted file mode 100644 index e9213a453a..0000000000 --- a/lib/rules/atRuleNameSpaceChecker.js +++ /dev/null @@ -1,55 +0,0 @@ -'use strict'; - -const isStandardSyntaxAtRule = require('../utils/isStandardSyntaxAtRule'); -const report = require('../utils/report'); - -/** - * @param {{ - * root: import('postcss').Root, - * locationChecker: (opts: { source: string, index: number, err: (msg: string) => void, errTarget: string }) => void, - * result: import('stylelint').PostcssResult, - * checkedRuleName: string, - * fix?: ((atRule: import('postcss').AtRule) => void) | null, - * }} options - */ -module.exports = function atRuleNameSpaceChecker(options) { - options.root.walkAtRules((atRule) => { - if (!isStandardSyntaxAtRule(atRule)) { - return; - } - - checkColon( - `@${atRule.name}${atRule.raws.afterName || ''}${atRule.params}`, - atRule.name.length, - atRule, - ); - }); - - /** - * @param {string} source - * @param {number} index - * @param {import('postcss').AtRule} node - */ - function checkColon(source, index, node) { - options.locationChecker({ - source, - index, - err: (m) => { - if (options.fix) { - options.fix(node); - - return; - } - - report({ - message: m, - node, - index, - result: options.result, - ruleName: options.checkedRuleName, - }); - }, - errTarget: `@${node.name}`, - }); - } -}; diff --git a/lib/rules/block-closing-brace-empty-line-before/README.md b/lib/rules/block-closing-brace-empty-line-before/README.md deleted file mode 100644 index 015df7db5f..0000000000 --- a/lib/rules/block-closing-brace-empty-line-before/README.md +++ /dev/null @@ -1,240 +0,0 @@ -# block-closing-brace-empty-line-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require or disallow an empty line before the closing brace of blocks. - - -```css -a { - color: pink; - /* ← */ -} /* ↑ */ -/** ↑ - * This line */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always-multi-line"|"never"` - -### `always-multi-line` - -The following patterns are considered problems: - - -```css -a { - color: pink; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { - color: pink; - -} -``` - - -```css -a { color: pink; } -``` - -### `never` - -The following patterns are considered problems: - - -```css -a { - color: pink; - -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { - color: pink; -} -``` - - -```css -a { color: pink; } -``` - -## Optional secondary options - -### `except: ["after-closing-brace"]` - -When a rule is nested, `after-closing-brace` brace will reverse the primary option. - -For example, with `"never"` and `except: ["after-closing-brace"]`: - -The following patterns are considered problems: - - -```css -@media print { - - a { - color: aquamarine; - } -} -``` - - -```css -@supports (animation-name: test) { - - a { - color: aquamarine; - } -} -``` - - -```css -@keyframes test { - - 100% { - color: aquamarine; - } -} -``` - -The following patterns are _not_ considered problems: - - -```css -@media print { - - a { - color: aquamarine; - } - -} -``` - - -```css -@font-face { - font-family: "MyFont"; - src: url("myfont.woff2") format("woff2"); -} -``` - - -```css -@supports (animation-name: test) { - - a { - color: aquamarine; - } - -} -``` - - -```css -@keyframes test { - - 100% { - color: aquamarine; - } - -} -``` - -For example, with `"always-multi-line"` and `except: ["after-closing-brace"]`: - -The following patterns are considered problems: - - -```css -@media print { - - a { - color: aquamarine; - - } - -} -``` - - -```css -@supports (animation-name: test) { - - a { - color: aquamarine; - - } - -} -``` - - -```css -@keyframes test { - - 100% { - color: aquamarine; - - } - -} -``` - -The following patterns are _not_ considered problems: - - -```css -@media print { - - a { - color: aquamarine; - - } -} -``` - - -```css -@font-face { - font-family: "MyFont"; - src: url("myfont.woff2") format("woff2"); - -} -``` - - -```css -@supports (animation-name: test) { - - a { - color: aquamarine; - - } -} -``` - - -```css -@keyframes test { - - 100% { - color: aquamarine; - - } -} -``` diff --git a/lib/rules/block-closing-brace-empty-line-before/__tests__/index.js b/lib/rules/block-closing-brace-empty-line-before/__tests__/index.js deleted file mode 100644 index aec615c397..0000000000 --- a/lib/rules/block-closing-brace-empty-line-before/__tests__/index.js +++ /dev/null @@ -1,420 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink;\n\n}', - }, - { - code: 'a { color: pink;; ;\n\n}', - }, - { - code: 'a { color: pink;;\n\n;}', - }, - { - code: 'a {color: pink;\r\n\r\n}', - }, - { - code: 'a {\ncolor: pink;\n\n}', - }, - { - code: 'a {\r\ncolor: pink;\r\n\r\n}', - }, - { - code: 'a { color: pink;\n\n}b { color: red;\n\n}', - }, - { - code: 'a {\ncolor: pink;\n\n\n\n}', - description: 'one *or more* empty lines are allowed', - }, - { - code: '@media print {\n a {\n color: pink;\n\n }\n\n}', - description: 'indentation after the newline before the closing braces', - }, - { - code: '@media print {\n\ta {\n\t\tcolor: pink;\n\t\t&:hover{\n\t\t\tcolor: red;\n\n\t\t\t}\n\n\t\t}\n\n}', - description: - '3 level deep nesting with indentation after the newline before the closing braces', - }, - ], - - reject: [ - { - code: 'a { color: pink;\n}', - fixed: 'a { color: pink;\n\n}', - message: messages.expected, - line: 2, - column: 1, - }, - { - code: 'a { color: pink;\r\n}', - fixed: 'a { color: pink;\r\n\r\n}', - message: messages.expected, - line: 2, - column: 1, - }, - { - code: 'a { color: pink;\n }', - fixed: 'a { color: pink;\n\n }', - message: messages.expected, - line: 2, - column: 2, - }, - { - code: 'a { color: pink;\n\t}', - fixed: 'a { color: pink;\n\n\t}', - message: messages.expected, - line: 2, - column: 2, - }, - { - code: 'a { color: pink;\r\n }', - fixed: 'a { color: pink;\r\n\r\n }', - message: messages.expected, - line: 2, - column: 3, - }, - { - code: 'a { color: pink;\n;}', - fixed: 'a { color: pink;\n;\n\n}', - message: messages.expected, - line: 2, - column: 2, - }, - { - code: 'a {\ncolor: pink;\n}', - fixed: 'a {\ncolor: pink;\n\n}', - message: messages.expected, - line: 3, - column: 1, - }, - { - code: 'a {\n\ncolor: pink;\n}', - fixed: 'a {\n\ncolor: pink;\n\n}', - message: messages.expected, - line: 4, - column: 1, - }, - { - code: 'a { color: pink;\n\n/* comment here*/\n}', - fixed: 'a { color: pink;\n\n/* comment here*/\n\n}', - message: messages.expected, - line: 4, - column: 1, - }, - { - code: 'a { color: pink;\r\n\r\n/* comment here*/\r\n}', - fixed: 'a { color: pink;\r\n\r\n/* comment here*/\r\n\r\n}', - message: messages.expected, - line: 4, - column: 1, - }, - { - code: '@media print {\n a {\n color: pink;\n/* comment here*/\n }\n}', - fixed: '@media print {\n a {\n color: pink;\n/* comment here*/\n\n }\n\n}', - warnings: [ - { - message: messages.expected, - line: 5, - column: 3, - }, - { - message: messages.expected, - line: 6, - column: 1, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink;\n}', - }, - { - code: 'a { color: pink;; ;\n}', - }, - { - code: 'a { color: pink;;\n;}', - }, - { - code: 'a {color: pink;\r\n}', - }, - { - code: 'a {\ncolor: pink;\n}', - }, - { - code: 'a {\r\ncolor: pink;\r\n}', - }, - { - code: 'a { color: pink;\n}b { color: red;\n}', - }, - { - code: '@media print {\n a {\n color: pink;\n }\n}', - description: 'indentation after the newline before the closing braces', - }, - { - code: '@media print {\n\ta {\n\t\tcolor: pink;\n\t\t&:hover{\n\t\t\tcolor: red;\n\t\t\t}\n\t\t}\n}', - description: - '3 level deep nesting with indentation after the newline before the closing braces', - }, - ], - - reject: [ - { - code: 'a { color: pink;\n\n}', - fixed: 'a { color: pink;\n}', - message: messages.rejected, - line: 3, - column: 1, - }, - { - code: 'a { color: pink;\r\n\r\n}', - fixed: 'a { color: pink;\r\n}', - message: messages.rejected, - line: 3, - column: 1, - }, - { - code: 'a { color: pink;\n\n }', - fixed: 'a { color: pink;\n }', - message: messages.rejected, - line: 3, - column: 2, - }, - { - code: 'a { color: pink;\n\n\t}', - fixed: 'a { color: pink;\n\t}', - message: messages.rejected, - line: 3, - column: 2, - }, - { - code: 'a { color: pink;\r\n\r\n }', - fixed: 'a { color: pink;\r\n }', - message: messages.rejected, - line: 3, - column: 3, - }, - { - code: 'a { color: pink;\n\n;}', - fixed: 'a { color: pink;\n;}', - message: messages.rejected, - line: 3, - column: 2, - }, - { - code: 'a {\ncolor: pink;\n\n}', - fixed: 'a {\ncolor: pink;\n}', - message: messages.rejected, - line: 4, - column: 1, - }, - { - code: 'a {\n\ncolor: pink;\n\n}', - fixed: 'a {\n\ncolor: pink;\n}', - message: messages.rejected, - line: 5, - column: 1, - }, - { - code: '@media print {\n a {\n color: pink;\n\n }\n\n}', - fixed: '@media print {\n a {\n color: pink;\n }\n}', - warnings: [ - { - message: messages.rejected, - line: 5, - column: 3, - }, - { - message: messages.rejected, - line: 7, - column: 1, - }, - ], - }, - { - code: 'a {\n\ncolor: pink;\n\n/* comment here */\n\n}', - fixed: 'a {\n\ncolor: pink;\n\n/* comment here */\n}', - message: messages.rejected, - line: 7, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: ['never', { except: ['after-closing-brace'] }], - fix: true, - - accept: [ - { - code: 'a {\n\tcolor: aquamarine;\n}', - }, - { - code: '@media print {\n\n\ta {\n\t\tcolor: aquamarine;\n\t}\n\n}', - }, - { - code: '@font-face {\n\tfont-family: "MyFont";\n\tsrc: url("myfont.woff2") format("woff2");\n}', - }, - { - code: '@supports (animation-name: test) {\n\n\ta {\n\t\tcolor: aquamarine;\n\t}\n\n}', - }, - { - code: '@keyframes test {\n\n\t100% {\n\t\tcolor: aquamarine;\n\t}\n\n}', - }, - ], - - reject: [ - { - code: 'a {\n\tcolor: aquamarine;\n\n}', - fixed: 'a {\n\tcolor: aquamarine;\n}', - message: messages.rejected, - line: 4, - column: 1, - }, - { - code: '@media print {\n\n\ta {\n\t\tcolor: aquamarine;\n\t}\n}', - fixed: '@media print {\n\n\ta {\n\t\tcolor: aquamarine;\n\t}\n\n}', - message: messages.expected, - line: 6, - column: 1, - }, - { - code: '@media print {\n\n\ta {\n\t\tcolor: aquamarine;\n\t}\n\n\tb {\n\t\tcolor: hotpink;\n\t}\n}', - fixed: - '@media print {\n\n\ta {\n\t\tcolor: aquamarine;\n\t}\n\n\tb {\n\t\tcolor: hotpink;\n\t}\n\n}', - warnings: [ - { - message: messages.expected, - line: 10, - column: 1, - }, - ], - }, - { - code: '@media print {\n\n\ta {\n\t\tcolor: aquamarine;\n\t}\n\n\tb {\n\t\tcolor: hotpink;\n\n\t}\n}', - fixed: - '@media print {\n\n\ta {\n\t\tcolor: aquamarine;\n\t}\n\n\tb {\n\t\tcolor: hotpink;\n\t}\n\n}', - warnings: [ - { - message: messages.rejected, - line: 10, - column: 2, - }, - { - message: messages.expected, - line: 11, - column: 1, - }, - ], - }, - { - code: '@supports (animation-name: test) {\n\n\ta {\n\t\tcolor: aquamarine;\n\t}\n}', - fixed: '@supports (animation-name: test) {\n\n\ta {\n\t\tcolor: aquamarine;\n\t}\n\n}', - message: messages.expected, - line: 6, - column: 1, - }, - { - code: '@keyframes test {\n\n\t100% {\n\t\tcolor: aquamarine;\n\t}\n}', - fixed: '@keyframes test {\n\n\t100% {\n\t\tcolor: aquamarine;\n\t}\n\n}', - message: messages.expected, - line: 6, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line', { except: ['after-closing-brace'] }], - fix: true, - - accept: [ - { - code: 'a {\n\tcolor: aquamarine;\n\n}', - }, - { - code: 'a { color: aquamarine; }', - }, - { - code: '@media print {\n\n\ta {\n\t\tcolor: aquamarine;\n\n\t}\n}', - }, - { - code: '@font-face {\n\tfont-family: "MyFont";\n\tsrc: url("myfont.woff2") format("woff2");\n\n}', - }, - { - code: '@supports (animation-name: test) {\n\n\ta {\n\t\tcolor: aquamarine;\n\n\t}\n}', - }, - { - code: '@keyframes test {\n\n\t100% {\n\t\tcolor: aquamarine;\n\n\t}\n}', - }, - ], - - reject: [ - { - code: 'a {\n\tcolor: aquamarine;\n}', - fixed: 'a {\n\tcolor: aquamarine;\n\n}', - message: messages.expected, - line: 3, - column: 1, - }, - { - code: '@media print {\n\n\ta {\n\t\tcolor: aquamarine;\n\n\t}\n\n}', - fixed: '@media print {\n\n\ta {\n\t\tcolor: aquamarine;\n\n\t}\n}', - message: messages.rejected, - line: 8, - column: 1, - }, - { - code: '@media print {\n\n\ta {\n\t\tcolor: aquamarine;\n\n\t}\n\n\tb {\n\t\tcolor: hotpink;\n\n\t}\n\n}', - fixed: - '@media print {\n\n\ta {\n\t\tcolor: aquamarine;\n\n\t}\n\n\tb {\n\t\tcolor: hotpink;\n\n\t}\n}', - message: messages.rejected, - line: 13, - column: 1, - }, - { - code: '@media print {\n\n\ta {\n\t\tcolor: aquamarine;\n\n\t}\n\n\tb {\n\t\tcolor: hotpink;\n\n\t}\n\n}', - fixed: - '@media print {\n\n\ta {\n\t\tcolor: aquamarine;\n\n\t}\n\n\tb {\n\t\tcolor: hotpink;\n\n\t}\n}', - message: messages.rejected, - line: 13, - column: 1, - }, - { - code: '@supports (animation-name: test) {\n\n\ta {\n\t\tcolor: aquamarine;\n\n\t}\n\n}', - fixed: '@supports (animation-name: test) {\n\n\ta {\n\t\tcolor: aquamarine;\n\n\t}\n}', - message: messages.rejected, - line: 8, - column: 1, - }, - { - code: '@keyframes test {\n\n\t100% {\n\t\tcolor: aquamarine;\n\n\t}\n\n}', - fixed: '@keyframes test {\n\n\t100% {\n\t\tcolor: aquamarine;\n\n\t}\n}', - message: messages.rejected, - line: 8, - column: 1, - }, - ], -}); diff --git a/lib/rules/block-closing-brace-empty-line-before/index.js b/lib/rules/block-closing-brace-empty-line-before/index.js deleted file mode 100644 index e33a1c398e..0000000000 --- a/lib/rules/block-closing-brace-empty-line-before/index.js +++ /dev/null @@ -1,129 +0,0 @@ -'use strict'; - -const addEmptyLineAfter = require('../../utils/addEmptyLineAfter'); -const blockString = require('../../utils/blockString'); -const hasBlock = require('../../utils/hasBlock'); -const hasEmptyBlock = require('../../utils/hasEmptyBlock'); -const hasEmptyLine = require('../../utils/hasEmptyLine'); -const isSingleLineString = require('../../utils/isSingleLineString'); -const optionsMatches = require('../../utils/optionsMatches'); -const removeEmptyLinesAfter = require('../../utils/removeEmptyLinesAfter'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'block-closing-brace-empty-line-before'; - -const messages = ruleMessages(ruleName, { - expected: 'Expected empty line before closing brace', - rejected: 'Unexpected empty line before closing brace', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/block-closing-brace-empty-line-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions( - result, - ruleName, - { - actual: primary, - possible: ['always-multi-line', 'never'], - }, - { - actual: secondaryOptions, - possible: { - except: ['after-closing-brace'], - }, - optional: true, - }, - ); - - if (!validOptions) { - return; - } - - // Check both kinds of statements: rules and at-rules - root.walkRules(check); - root.walkAtRules(check); - - /** - * @param {import('postcss').Rule | import('postcss').AtRule} statement - */ - function check(statement) { - // Return early if blockless or has empty block - if (!hasBlock(statement) || hasEmptyBlock(statement)) { - return; - } - - // Get whitespace after ""}", ignoring extra semicolon - const before = (statement.raws.after || '').replace(/;+/, ''); - - // Calculate index - const statementString = statement.toString(); - let index = statementString.length - 1; - - if (statementString[index - 1] === '\r') { - index -= 1; - } - - // Set expectation - const expectEmptyLineBefore = (() => { - const childNodeTypes = statement.nodes.map((item) => item.type); - - // Reverse the primary options if `after-closing-brace` is set - if ( - optionsMatches(secondaryOptions, 'except', 'after-closing-brace') && - statement.type === 'atrule' && - !childNodeTypes.includes('decl') - ) { - return primary === 'never'; - } - - return primary === 'always-multi-line' && !isSingleLineString(blockString(statement)); - })(); - - // Check for at least one empty line - const hasEmptyLineBefore = hasEmptyLine(before); - - // Return if the expectation is met - if (expectEmptyLineBefore === hasEmptyLineBefore) { - return; - } - - if (context.fix) { - const { newline } = context; - - if (typeof newline !== 'string') return; - - if (expectEmptyLineBefore) { - addEmptyLineAfter(statement, newline); - } else { - removeEmptyLinesAfter(statement, newline); - } - - return; - } - - const message = expectEmptyLineBefore ? messages.expected : messages.rejected; - - report({ - message, - result, - ruleName, - node: statement, - index, - }); - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/block-closing-brace-newline-after/README.md b/lib/rules/block-closing-brace-newline-after/README.md deleted file mode 100644 index 939c7a84e5..0000000000 --- a/lib/rules/block-closing-brace-newline-after/README.md +++ /dev/null @@ -1,198 +0,0 @@ -# block-closing-brace-newline-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline or disallow whitespace after the closing brace of blocks. - - -```css -a { color: pink; } -a { color: red; }↑ -/** ↑ - * The newline after this brace */ -``` - -This rule allows an end-of-line comment separated from the closing brace by spaces, as long as the comment contains no newlines. For example, - - -```css -a { - color: pink; -} /* end-of-line comment */ -``` - -This rule allows a trailing semicolon after the closing brace of a block. For example, - - -```css -:root { - --toolbar-theme: { - background-color: hsl(120, 70%, 95%); - }; -/* ↑ - * This semicolon */ -} -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"always-single-line"|"never-single-line"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a newline after the closing brace. - -The following patterns are considered problems: - - -```css -a { color: pink; }b { color: red; } -``` - - -```css -a { color: pink; -} b { color: red; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -b { color: red; } -``` - -### `"always-single-line"` - -There _must always_ be a newline after the closing brace in single-line blocks. - -The following patterns are considered problems: - - -```css -a { color: pink; } b { color: red; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; -} b { color: red; } -``` - - -```css -a { color: pink; } -b { color: red; } -``` - -### `"never-single-line"` - -There _must never_ be whitespace after the closing brace in single-line blocks. - -The following patterns are considered problems: - - -```css -a { color: pink; } b { color: red; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; }b { color: red; } -``` - - -```css -a { color: pink; -} b { color: red; } -``` - -### `"always-multi-line"` - -There _must always_ be a newline after the closing brace in multi-line blocks. - -The following patterns are considered problems: - - -```css -a { color: pink; -}b { color: red; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; }b { color: red; } -``` - - -```css -a { color: pink; -} -b { color: red; } -``` - -### `"never-multi-line"` - -There _must never_ be whitespace after the closing brace in multi-line blocks. - -The following patterns are considered problems: - - -```css -a { color: pink; -} b { color: red; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } b { color: red; } -``` - - -```css -a { color: pink; -}b { color: red; } -``` - -## Optional secondary options - -### `ignoreAtRules: ["/regex/", "non-regex"]` - -Ignore specified at-rules. - -For example, with `"always"` or `"always-multi-line"`. - -Given: - -```json -["if", "else"] -``` - -The following patterns are _not_ considered problems: - - -```css -@if ($var) { - color: pink; -} @else if ($var2) { - color: red; -} @else { - color: blue; -} -``` - - -```css -@if ($var) { color: pink; } @else { color: blue; } -``` diff --git a/lib/rules/block-closing-brace-newline-after/__tests__/index.js b/lib/rules/block-closing-brace-newline-after/__tests__/index.js deleted file mode 100644 index 0d16a8332c..0000000000 --- a/lib/rules/block-closing-brace-newline-after/__tests__/index.js +++ /dev/null @@ -1,518 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink; }\nb { color: red; }', - }, - { - code: 'a { color: pink; }\r\nb { color: red; }', - description: 'CRLF', - }, - { - code: 'a { color: pink; }\n\nb { color: red; }', - }, - { - code: 'a { color: pink; }\r\n\r\nb { color: red; }', - description: 'CRLF', - }, - { - code: 'a { color: pink;}\n\t\tb { color: red;}', - }, - { - code: 'a { color: pink;}\r\n\t\tb { color: red;}', - description: 'CRLF', - }, - { - code: 'a { @extend foo; color: pink; }', - }, - { - code: 'a { @extend foo; /* comment */\ncolor: pink; }', - }, - { - code: '@media print { a { color: pink; }\nb { color: red; }}', - }, - { - code: '@media print { a { color: pink; }}\n@media screen { b { color: red; }}', - }, - { - code: '.a {} /* comment */', - }, - { - code: '.a {} /* comment */\n b {}', - }, - { - code: ':root {\n --x { color: pink; };\n --y { color: red; };\n }', - description: 'Allow a trailing semicolon after the closing brace of a block', - }, - { - code: ':root {\n --x { color: pink; } ;\n --y { color: red; };\n }', - description: 'Allow a spaced trailing semicolon after the closing brace of an at-apply block', - }, - { - code: '.foo {\n --my-theme: { color: red; };\n --toolbar-theme: { color: green; };\n }', - description: 'Make sure trailing semicolon works well for blocks outside :root', - }, - ], - - reject: [ - { - code: 'a { color: pink; }b { color: red; }', - fixed: 'a { color: pink; }\nb { color: red; }', - message: messages.expectedAfter(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; } b { color: red; }', - fixed: 'a { color: pink; }\n b { color: red; }', - message: messages.expectedAfter(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; } b { color: red; }', - fixed: 'a { color: pink; }\n b { color: red; }', - message: messages.expectedAfter(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; }\tb { color: red; }', - fixed: 'a { color: pink; }\n\tb { color: red; }', - message: messages.expectedAfter(), - line: 1, - column: 19, - }, - { - code: '@media print { a { color: pink; } b { color: red; }}', - fixed: '@media print { a { color: pink; }\n b { color: red; }}', - message: messages.expectedAfter(), - line: 1, - column: 34, - }, - { - code: '@media print { a { color: pink; }} @media screen { b { color: red; }}', - fixed: '@media print { a { color: pink; }}\n @media screen { b { color: red; }}', - message: messages.expectedAfter(), - line: 1, - column: 35, - }, - { - code: '.a {} /* comment */ b {}', - fixed: '.a {} /* comment */\n b {}', - message: messages.expectedAfter(), - line: 1, - column: 6, - }, - ], -}); - -testRule({ - ruleName, - config: ['always', { ignoreAtRules: ['if', 'else'] }], - fix: true, - - accept: [ - { - code: 'a { color: pink; }\nb {}', - }, - { - code: '@if ... { color: pink; } @else {}', - }, - { - code: '@if ... { color: pink; } @else if {} else {}', - }, - { - code: '@if ... {\r\n color: pink; \n} @else if {\n color: pink;\n} else {}', - }, - ], - - reject: [ - { - code: 'a { color: pink; }b{}', - fixed: 'a { color: pink; }\nb{}', - message: messages.expectedAfter(), - line: 1, - column: 19, - }, - ], -}); - -testRule({ - ruleName, - config: ['always', { ignoreAtRules: '/if/' }], - fix: true, - - accept: [ - { - code: 'a { color: pink; }\nb {}', - }, - { - code: '@if ... { color: pink; } @else {}', - }, - ], - - reject: [ - { - code: 'a { color: pink; }b{}', - fixed: 'a { color: pink; }\nb{}', - message: messages.expectedAfter(), - line: 1, - column: 19, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink; }\nb { color: red; }', - }, - { - code: 'a { color: pink; }\r\nb { color: red; }', - description: 'CRLF', - }, - { - code: 'a { color: pink;}\n\t\tb { color: red;}', - }, - { - code: 'a { color: pink;}\r\n\t\tb { color: red;}', - description: 'CRLF', - }, - { - code: '@media print { a { color: pink; }\nb { color: red; }}', - }, - { - code: '@media print { a { color: pink; }}\n@media screen { b { color: red; }}', - }, - { - code: 'a { color: pink;\ntop: 0; }b { color: red; }', - }, - { - code: 'a { color: pink;\ntop: 0;}b { color: red;}', - }, - { - code: 'a { color: pink;\r\ntop: 0;}b { color: red;}', - description: 'CRLF', - }, - ], - - reject: [ - { - code: 'a { color: pink; }b { color: red; }', - fixed: 'a { color: pink; }\nb { color: red; }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; } b { color: red; }', - fixed: 'a { color: pink; }\n b { color: red; }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; } b { color: red; }', - fixed: 'a { color: pink; }\n b { color: red; }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; }\tb { color: red; }', - fixed: 'a { color: pink; }\n\tb { color: red; }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 19, - }, - { - code: '@media print { a { color: pink; } b { color: red; }}', - fixed: '@media print { a { color: pink; }\n b { color: red; }}', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 34, - }, - { - code: '@media print { a { color: pink; }} @media screen { b { color: red; }}', - fixed: '@media print { a { color: pink; }}\n @media screen { b { color: red; }}', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 35, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink; }b { color: red; }', - }, - { - code: 'a { color: pink;}b { color: red;}', - }, - { - code: '@media print { a { color: pink; }b { color: red; }}', - }, - { - code: '@media print { a { color: pink; }}@media screen { b { color: red; }}', - }, - { - code: 'a { color: pink;\ntop: 0; }\nb { color: red; }', - }, - { - code: 'a { color: pink;\ntop: 0;} b { color: red;}', - }, - ], - - reject: [ - { - code: 'a { color: pink; }\nb { color: red; }', - fixed: 'a { color: pink; }b { color: red; }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; } b { color: red; }', - fixed: 'a { color: pink; }b { color: red; }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; } b { color: red; }', - fixed: 'a { color: pink; }b { color: red; }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; }\tb { color: red; }', - fixed: 'a { color: pink; }b { color: red; }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 19, - }, - { - code: '@media print { a { color: pink; }\nb { color: red; }}', - fixed: '@media print { a { color: pink; }b { color: red; }}', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 34, - }, - { - code: '@media print { a { color: pink; }}\n @media screen { b { color: red; }}', - fixed: '@media print { a { color: pink; }}@media screen { b { color: red; }}', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 35, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink;\ntop: 0; }', - }, - { - code: 'a { color: pink;\ntop: 0; }\nb { color: red; }', - }, - { - code: 'a { color: pink;\r\ntop: 0; }\r\nb { color: red; }', - description: 'CRLF', - }, - { - code: 'a { color: pink;\ntop: 0;}\n\t\tb { color: red;}', - }, - { - code: '@media print { a {\ncolor: pink; }\nb { color: red; }}', - }, - { - code: '@media print { a {\ncolor: pink; }}\n@media screen { b { color: red; }}', - }, - { - code: 'a { color: pink; }\nb { color: red; }', - }, - { - code: 'a { color: pink; }b { color: red;}', - }, - ], - - reject: [ - { - code: 'a { color: pink;\ntop: 0; }b { color: red; }', - fixed: 'a { color: pink;\ntop: 0; }\nb { color: red; }', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 10, - }, - { - code: 'a { color: pink;\r\ntop: 0; }b { color: red; }', - fixed: 'a { color: pink;\r\ntop: 0; }\r\nb { color: red; }', - description: 'CRLF', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 10, - }, - { - code: 'a { color: pink;\ntop: 0; } b { color: red; }', - fixed: 'a { color: pink;\ntop: 0; }\n b { color: red; }', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 10, - }, - { - code: 'a { color: pink;\ntop: 0; } b { color: red; }', - fixed: 'a { color: pink;\ntop: 0; }\n b { color: red; }', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 10, - }, - { - code: 'a { color: pink;\ntop: 0; }\tb { color: red; }', - fixed: 'a { color: pink;\ntop: 0; }\n\tb { color: red; }', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 10, - }, - { - code: '@media print { a {\ncolor: pink; } b { color: red; }}', - fixed: '@media print { a {\ncolor: pink; }\n b { color: red; }}', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 15, - }, - { - code: '@media print { a {\ncolor: pink; }} @media screen { b {\ncolor: red; }}', - fixed: '@media print { a {\ncolor: pink; }}\n @media screen { b {\ncolor: red; }}', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 16, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink;\ntop: 0; }', - }, - { - code: 'a { color: pink;\ntop: 0; }b { color: red; }', - }, - { - code: 'a { color: pink;\ntop: 0;}b { color: red;}', - }, - { - code: 'a { color: pink;\r\ntop: 0;}b { color: red;}', - description: 'CRLF', - }, - { - code: '@media print { a {\ncolor: pink; }b { color: red; }}', - }, - { - code: '@media print { a {\ncolor: pink; }}@media screen { b { color: red; }}', - }, - { - code: '@media print { a {\r\ncolor: pink; }}@media screen { b { color: red; }}', - description: 'CRLF', - }, - { - code: 'a { color: pink; }\nb { color: red; }', - }, - { - code: 'a { color: pink; }\r\nb { color: red; }', - description: 'CRLF', - }, - { - code: 'a { color: pink;} b { color: red;}', - }, - ], - - reject: [ - { - code: 'a { color: pink;\ntop: 0; }\nb { color: red; }', - fixed: 'a { color: pink;\ntop: 0; }b { color: red; }', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 10, - }, - { - code: 'a { color: pink;\r\ntop: 0; }\r\nb { color: red; }', - fixed: 'a { color: pink;\r\ntop: 0; }b { color: red; }', - description: 'CRLF', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 10, - }, - { - code: 'a { color: pink;\ntop: 0; } b { color: red; }', - fixed: 'a { color: pink;\ntop: 0; }b { color: red; }', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 10, - }, - { - code: 'a { color: pink;\ntop: 0; } b { color: red; }', - fixed: 'a { color: pink;\ntop: 0; }b { color: red; }', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 10, - }, - { - code: 'a { color: pink;\ntop: 0; }\tb { color: red; }', - fixed: 'a { color: pink;\ntop: 0; }b { color: red; }', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 10, - }, - { - code: '@media print { a {\ncolor: pink; }\nb { color: red; }}', - fixed: '@media print { a {\ncolor: pink; }b { color: red; }}', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 15, - }, - { - code: '@media print { a {\ncolor: pink; }}\n@media screen { b {\ncolor: red; }}', - fixed: '@media print { a {\ncolor: pink; }}@media screen { b {\ncolor: red; }}', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 16, - }, - ], -}); diff --git a/lib/rules/block-closing-brace-newline-after/index.js b/lib/rules/block-closing-brace-newline-after/index.js deleted file mode 100644 index 47a0495e13..0000000000 --- a/lib/rules/block-closing-brace-newline-after/index.js +++ /dev/null @@ -1,152 +0,0 @@ -'use strict'; - -const blockString = require('../../utils/blockString'); -const hasBlock = require('../../utils/hasBlock'); -const optionsMatches = require('../../utils/optionsMatches'); -const rawNodeString = require('../../utils/rawNodeString'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); -const { isString } = require('../../utils/validateTypes'); - -const ruleName = 'block-closing-brace-newline-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected newline after "}"', - expectedAfterSingleLine: () => 'Expected newline after "}" of a single-line block', - rejectedAfterSingleLine: () => 'Unexpected whitespace after "}" of a single-line block', - expectedAfterMultiLine: () => 'Expected newline after "}" of a multi-line block', - rejectedAfterMultiLine: () => 'Unexpected whitespace after "}" of a multi-line block', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/block-closing-brace-newline-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, secondaryOptions, context) => { - const checker = whitespaceChecker('newline', primary, messages); - - return (root, result) => { - const validOptions = validateOptions( - result, - ruleName, - { - actual: primary, - possible: [ - 'always', - 'always-single-line', - 'never-single-line', - 'always-multi-line', - 'never-multi-line', - ], - }, - { - actual: secondaryOptions, - possible: { - ignoreAtRules: [isString], - }, - optional: true, - }, - ); - - if (!validOptions) { - return; - } - - // Check both kinds of statements: rules and at-rules - root.walkRules(check); - root.walkAtRules(check); - - /** - * @param {import('postcss').Rule | import('postcss').AtRule} statement - */ - function check(statement) { - if (!hasBlock(statement)) { - return; - } - - if ( - statement.type === 'atrule' && - optionsMatches(secondaryOptions, 'ignoreAtRules', statement.name) - ) { - return; - } - - const nextNode = statement.next(); - - if (!nextNode) { - return; - } - - // Allow an end-of-line comment x spaces after the brace - const nextNodeIsSingleLineComment = - nextNode.type === 'comment' && - !/[^ ]/.test(nextNode.raws.before || '') && - !nextNode.toString().includes('\n'); - - const nodeToCheck = nextNodeIsSingleLineComment ? nextNode.next() : nextNode; - - if (!nodeToCheck) { - return; - } - - let reportIndex = statement.toString().length; - let source = rawNodeString(nodeToCheck); - - // Skip a semicolon at the beginning, if any - if (source && source.startsWith(';')) { - source = source.slice(1); - reportIndex++; - } - - // Only check one after, because there might be other - // spaces handled by the indentation rule - checker.afterOneOnly({ - source, - index: -1, - lineCheckStr: blockString(statement), - err: (msg) => { - if (context.fix) { - const nodeToCheckRaws = nodeToCheck.raws; - - if (typeof nodeToCheckRaws.before !== 'string') return; - - if (primary.startsWith('always')) { - const index = nodeToCheckRaws.before.search(/\r?\n/); - - nodeToCheckRaws.before = - index >= 0 - ? nodeToCheckRaws.before.slice(index) - : context.newline + nodeToCheckRaws.before; - - return; - } - - if (primary.startsWith('never')) { - nodeToCheckRaws.before = ''; - - return; - } - } - - report({ - message: msg, - node: statement, - index: reportIndex, - result, - ruleName, - }); - }, - }); - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/block-closing-brace-newline-before/README.md b/lib/rules/block-closing-brace-newline-before/README.md deleted file mode 100644 index 936ba1978e..0000000000 --- a/lib/rules/block-closing-brace-newline-before/README.md +++ /dev/null @@ -1,95 +0,0 @@ -# block-closing-brace-newline-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline or disallow whitespace before the closing brace of blocks. - - -```css - a { color: pink; - } -/** ↑ - * The newline before this brace */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a newline before the closing brace. - -The following patterns are considered problems: - - -```css -a { color: pink;} -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; -} -``` - - -```css -a { -color: pink; -} -``` - -### `"always-multi-line"` - -There _must always_ be a newline before the closing brace in multi-line blocks. - -The following patterns are considered problems: - - -```css -a { -color: pink;} -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { color: pink; -} -``` - -### `"never-multi-line"` - -There _must never_ be whitespace before the closing brace in multi-line blocks. - -The following patterns are considered problems: - - -```css -a { -color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { -color: pink;} -``` diff --git a/lib/rules/block-closing-brace-newline-before/__tests__/index.js b/lib/rules/block-closing-brace-newline-before/__tests__/index.js deleted file mode 100644 index 8c4f3ef8a1..0000000000 --- a/lib/rules/block-closing-brace-newline-before/__tests__/index.js +++ /dev/null @@ -1,386 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a { color: pink;\n}', - }, - { - code: 'a { color: pink;;\n}', - }, - { - code: 'a { color: pink;;;\n}', - }, - { - code: 'a { color: pink;\r\n}', - description: 'CRLF', - }, - { - code: 'a { color: pink;\n\n}', - }, - { - code: 'a { color: pink;\r\n\r\n}', - description: 'CRLF', - }, - { - code: 'a { color: pink;\n\t\t}', - }, - { - code: 'a { color: pink;\n} b { color: red;\n}', - }, - { - code: 'a { color: pink;\n}b { color: red;\n}', - }, - { - code: '@media print {\n a {\n color: pink;\n }\n}', - description: 'indentation after the newline before the closing braces', - }, - { - code: '@media print {\n\ta {\n\t\tcolor: pink;\n\t\t{\n\t\t\t&:hover;\n\t\t\t}\n\t\t}\n}', - description: - '3 level deep nesting with indentation after the newline before the closing braces', - }, - ], - - reject: [ - { - code: 'a { color: pink;}', - fixed: 'a { color: pink;\n}', - message: messages.expectedBefore, - line: 1, - column: 16, - }, - { - code: 'a { color: pink;;}', - fixed: 'a { color: pink;;\n}', - message: messages.expectedBefore, - line: 1, - column: 17, - }, - { - code: 'a { color: pink; }', - fixed: 'a { color: pink;\n }', - message: messages.expectedBefore, - line: 1, - column: 17, - }, - { - code: 'a { color: pink; \n}', - fixed: 'a { color: pink;\n}', - message: messages.expectedBefore, - line: 1, - column: 18, - }, - { - code: 'a { color: pink; \r\n}', - fixed: 'a { color: pink;\r\n}', - description: 'CRLF', - message: messages.expectedBefore, - line: 1, - column: 18, - }, - { - code: 'a { color: pink; }', - fixed: 'a { color: pink;\n }', - message: messages.expectedBefore, - line: 1, - column: 18, - }, - { - code: 'a { color: pink;\t}', - fixed: 'a { color: pink;\n\t}', - message: messages.expectedBefore, - line: 1, - column: 17, - }, - { - code: 'a { color: pink;\n} b { color: red; }', - fixed: 'a { color: pink;\n} b { color: red;\n }', - message: messages.expectedBefore, - line: 2, - column: 18, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink;\ntop: 0;\n}', - }, - { - code: 'a { color: pink;\r\ntop: 0;\r\n}', - description: 'CRLF', - }, - { - code: 'a { color: pink;;\ntop: 0;;\n}', - }, - { - code: 'a { color: pink;;\r\ntop: 0;;\r\n}', - description: 'CRLF', - }, - { - code: 'a { color: pink;;;\ntop: 0;;;\n}', - }, - { - code: 'a { color: pink;;;\r\ntop: 0;;;\r\n}', - description: 'CRLF', - }, - { - code: 'a { color: pink;\ntop: 0;\n\t\t}', - }, - { - code: 'a { color: pink;\r\ntop: 0;\r\n\t\t}', - description: 'CRLF', - }, - { - code: 'a { color: pink;\ntop: 0;\n} b { color: red;\n}', - }, - { - code: 'a { color: pink;\ntop: 0;\n}b { color: red;\n}', - }, - { - code: 'a { color: pink;}', - }, - { - code: 'a { color: pink;;}', - }, - { - code: 'a { color: pink;;;}', - }, - { - code: 'a { color: pink;} b { color: red;}', - }, - { - code: 'a { color: pink;}b { color: red;}', - }, - ], - - reject: [ - { - code: 'a { color: pink;\ntop: 0;}', - fixed: 'a { color: pink;\ntop: 0;\n}', - message: messages.expectedBeforeMultiLine, - line: 2, - column: 7, - }, - { - code: 'a { color: pink;\r\ntop: 0;}', - fixed: 'a { color: pink;\r\ntop: 0;\r\n}', - description: 'CRLF', - message: messages.expectedBeforeMultiLine, - line: 2, - column: 7, - }, - { - code: 'a { color: pink;;\ntop: 0;;}', - fixed: 'a { color: pink;;\ntop: 0;;\n}', - message: messages.expectedBeforeMultiLine, - line: 2, - column: 8, - }, - { - code: 'a { color: pink;;\r\ntop: 0;;}', - fixed: 'a { color: pink;;\r\ntop: 0;;\r\n}', - description: 'CRLF', - message: messages.expectedBeforeMultiLine, - line: 2, - column: 8, - }, - { - code: 'a { color: pink;;;\ntop: 0;;;}', - fixed: 'a { color: pink;;;\ntop: 0;;;\n}', - message: messages.expectedBeforeMultiLine, - line: 2, - column: 9, - }, - { - code: 'a { color: pink;;;\r\ntop: 0;;;}', - fixed: 'a { color: pink;;;\r\ntop: 0;;;\r\n}', - description: 'CRLF', - message: messages.expectedBeforeMultiLine, - line: 2, - column: 9, - }, - { - code: 'a { color: pink;\ntop: 0; }', - fixed: 'a { color: pink;\ntop: 0;\n }', - message: messages.expectedBeforeMultiLine, - line: 2, - column: 8, - }, - { - code: 'a { color: pink;\ntop: 0; \n}', - fixed: 'a { color: pink;\ntop: 0;\n}', - message: messages.expectedBeforeMultiLine, - line: 2, - column: 9, - }, - { - code: 'a { color: pink;\ntop: 0; }', - fixed: 'a { color: pink;\ntop: 0;\n }', - message: messages.expectedBeforeMultiLine, - line: 2, - column: 9, - }, - { - code: 'a { color: pink;\ntop: 0;\t}', - fixed: 'a { color: pink;\ntop: 0;\n\t}', - message: messages.expectedBeforeMultiLine, - line: 2, - column: 8, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink;\ntop: 0;}', - }, - { - code: 'a { color: pink;\r\ntop: 0;}', - description: 'CRLF', - }, - { - code: 'a { color: pink;;\ntop: 0;;}', - }, - { - code: 'a { color: pink;;\r\ntop: 0;;}', - description: 'CRLF', - }, - { - code: 'a { color: pink;;;\ntop: 0;;;}', - }, - { - code: 'a { color: pink;;;\r\ntop: 0;;;}', - description: 'CRLF', - }, - { - code: 'a { color: pink;\ntop: 0;} b { color: red;\ntop: 0;}', - }, - { - code: 'a { color: pink;\ntop: 0;}b { color: red;\ntop: 0;}', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink;\t}', - }, - { - code: 'a { color: pink; }', - }, - ], - - reject: [ - { - code: 'a { color: pink;\ntop: 0; }', - fixed: 'a { color: pink;\ntop: 0;}', - message: messages.rejectedBeforeMultiLine, - line: 2, - column: 8, - }, - { - code: 'a { color: pink;\r\ntop: 0; }', - fixed: 'a { color: pink;\r\ntop: 0;}', - description: 'CRLF', - message: messages.rejectedBeforeMultiLine, - line: 2, - column: 8, - }, - { - code: 'a { color: pink;;\ntop: 0;; }', - fixed: 'a { color: pink;;\ntop: 0;;}', - message: messages.rejectedBeforeMultiLine, - line: 2, - column: 9, - }, - { - code: 'a { color: pink;;\r\ntop: 0;; }', - fixed: 'a { color: pink;;\r\ntop: 0;;}', - description: 'CRLF', - message: messages.rejectedBeforeMultiLine, - line: 2, - column: 9, - }, - { - code: 'a { color: pink;;;\ntop: 0;;; }', - fixed: 'a { color: pink;;;\ntop: 0;;;}', - message: messages.rejectedBeforeMultiLine, - line: 2, - column: 10, - }, - { - code: 'a { color: pink;;;\r\ntop: 0;;; }', - fixed: 'a { color: pink;;;\r\ntop: 0;;;}', - description: 'CRLF', - message: messages.rejectedBeforeMultiLine, - line: 2, - column: 10, - }, - { - code: 'a { color: pink;\ntop: 0;\n}', - fixed: 'a { color: pink;\ntop: 0;}', - message: messages.rejectedBeforeMultiLine, - line: 2, - column: 8, - }, - { - code: 'a { color: pink;\ntop: 0; }', - fixed: 'a { color: pink;\ntop: 0;}', - message: messages.rejectedBeforeMultiLine, - line: 2, - column: 9, - }, - { - code: 'a { color: pink;\ntop: 0;\t}', - fixed: 'a { color: pink;\ntop: 0;}', - message: messages.rejectedBeforeMultiLine, - line: 2, - column: 8, - }, - { - code: 'a { color: pink;\ntop: 0;} b { color: red;\ntop: 0;\n}', - fixed: 'a { color: pink;\ntop: 0;} b { color: red;\ntop: 0;}', - message: messages.rejectedBeforeMultiLine, - line: 3, - column: 8, - }, - { - code: 'a { color: pink;;;\ntop: 0; ;;}', - fixed: 'a { color: pink;;;\ntop: 0;;;}', - message: messages.rejectedBeforeMultiLine, - line: 2, - column: 10, - }, - { - code: 'a { color: pink;;;\ntop: 0;; ;}', - fixed: 'a { color: pink;;;\ntop: 0;;;}', - message: messages.rejectedBeforeMultiLine, - line: 2, - column: 10, - }, - { - code: 'a { color: pink;;;\ntop: 0; ; ; }', - fixed: 'a { color: pink;;;\ntop: 0;;;}', - message: messages.rejectedBeforeMultiLine, - line: 2, - column: 12, - }, - ], -}); diff --git a/lib/rules/block-closing-brace-newline-before/index.js b/lib/rules/block-closing-brace-newline-before/index.js deleted file mode 100644 index e6f96aad9b..0000000000 --- a/lib/rules/block-closing-brace-newline-before/index.js +++ /dev/null @@ -1,132 +0,0 @@ -'use strict'; - -const blockString = require('../../utils/blockString'); -const hasBlock = require('../../utils/hasBlock'); -const hasEmptyBlock = require('../../utils/hasEmptyBlock'); -const isSingleLineString = require('../../utils/isSingleLineString'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'block-closing-brace-newline-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: 'Expected newline before "}"', - expectedBeforeMultiLine: 'Expected newline before "}" of a multi-line block', - rejectedBeforeMultiLine: 'Unexpected whitespace before "}" of a multi-line block', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/block-closing-brace-newline-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'always-multi-line', 'never-multi-line'], - }); - - if (!validOptions) { - return; - } - - // Check both kinds of statements: rules and at-rules - root.walkRules(check); - root.walkAtRules(check); - - /** - * @param {import('postcss').Rule | import('postcss').AtRule} statement - */ - function check(statement) { - // Return early if blockless or has empty block - if (!hasBlock(statement) || hasEmptyBlock(statement)) { - return; - } - - // Ignore extra semicolon - const after = (statement.raws.after || '').replace(/;+/, ''); - - if (after === undefined) { - return; - } - - const blockIsMultiLine = !isSingleLineString(blockString(statement)); - const statementString = statement.toString(); - - let index = statementString.length - 2; - - if (statementString[index - 1] === '\r') { - index -= 1; - } - - // We're really just checking whether a - // newline *starts* the block's final space -- between - // the last declaration and the closing brace. We can - // ignore any other whitespace between them, because that - // will be checked by the indentation rule. - if (!after.startsWith('\n') && !after.startsWith('\r\n')) { - if (primary === 'always') { - complain(messages.expectedBefore); - } else if (blockIsMultiLine && primary === 'always-multi-line') { - complain(messages.expectedBeforeMultiLine); - } - } - - if (after !== '' && blockIsMultiLine && primary === 'never-multi-line') { - complain(messages.rejectedBeforeMultiLine); - } - - /** - * @param {string} message - */ - function complain(message) { - if (context.fix) { - const statementRaws = statement.raws; - - if (typeof statementRaws.after !== 'string') return; - - if (primary.startsWith('always')) { - const firstWhitespaceIndex = statementRaws.after.search(/\s/); - const newlineBefore = - firstWhitespaceIndex >= 0 - ? statementRaws.after.slice(0, firstWhitespaceIndex) - : statementRaws.after; - const newlineAfter = - firstWhitespaceIndex >= 0 ? statementRaws.after.slice(firstWhitespaceIndex) : ''; - const newlineIndex = newlineAfter.search(/\r?\n/); - - statementRaws.after = - newlineIndex >= 0 - ? newlineBefore + newlineAfter.slice(newlineIndex) - : newlineBefore + context.newline + newlineAfter; - - return; - } - - if (primary === 'never-multi-line') { - statementRaws.after = statementRaws.after.replace(/\s/g, ''); - - return; - } - } - - report({ - message, - result, - ruleName, - node: statement, - index, - }); - } - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/block-closing-brace-space-after/README.md b/lib/rules/block-closing-brace-space-after/README.md deleted file mode 100644 index b566960f96..0000000000 --- a/lib/rules/block-closing-brace-space-after/README.md +++ /dev/null @@ -1,181 +0,0 @@ -# block-closing-brace-space-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace after the closing brace of blocks. - - -```css -a { color: pink; } -/** ↑ - * The space after this brace */ -``` - -This rule allows a trailing semicolon after the closing brace of a block. For example, - - -```css -:root { - --toolbar-theme: { - background-color: hsl(120, 70%, 95%); - }; -/* ↑ - * This semicolon */ -} -``` - -## Options - -`string`: `"always"|"never"|"always-single-line"|"never-single-line"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a single space after the closing brace. - -The following patterns are considered problems: - - -```css -a { color: pink; }b { color: red; } -``` - - -```css -a { color: pink; } -b { color: red; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } b { color: red; } -``` - -### `"never"` - -There _must never_ be whitespace after the closing brace. - -The following patterns are considered problems: - - -```css -a { color: pink; } b { color: red; } -``` - - -```css -a { color: pink; } -b { color: red; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; }b { color: red; } -``` - - -```css -a { color: pink; -}b { color: red; } -``` - -### `"always-single-line"` - -There _must always_ be a single space after the closing brace in single-line blocks. - -The following patterns are considered problems: - - -```css -a { color: pink; }b { color: red; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } b { color: red; } -``` - - -```css -a { color: pink; -}b { color: red; } -``` - -### `"never-single-line"` - -There _must never_ be whitespace after the closing brace in single-line blocks. - -The following patterns are considered problems: - - -```css -a { color: pink; } b { color: red; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; }b { color: red; } -``` - - -```css -a { color: pink; -} b { color: red; } -``` - -### `"always-multi-line"` - -There _must always_ be a single space after the closing brace in multi-line blocks. - -The following patterns are considered problems: - - -```css -a { color: pink; -}b { color: red; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; }b { color: red; } -``` - - -```css -a { color: pink; -} b { color: red; } -``` - -### `"never-multi-line"` - -There _must never_ be whitespace after the closing brace in multi-line blocks. - -The following patterns are considered problems: - - -```css -a { color: pink; -} b { color: red; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } b { color: red; } -``` - - -```css -a { color: pink; -}b { color: red; } -``` diff --git a/lib/rules/block-closing-brace-space-after/__tests__/index.js b/lib/rules/block-closing-brace-space-after/__tests__/index.js deleted file mode 100644 index 6f5f57af60..0000000000 --- a/lib/rules/block-closing-brace-space-after/__tests__/index.js +++ /dev/null @@ -1,472 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink; } b { color: red; }', - }, - { - code: 'a { color: pink;} b { color: red;}', - }, - { - code: '@media print { a { color: pink; } b { color: red; } }', - }, - { - code: '@media print { a { color: pink; } } @media screen { b { color: red; } }', - }, - { - code: "@import 'foo.css';\n@import 'bar.css';", - description: 'two blockless statements', - }, - { - code: '@media print { a { color: pink; } b { color: red; }}', - }, - { - code: '@media print { a { color: pink; }} @media screen { b { color: red; }}', - }, - { - code: '.a {} /* stylelint-disable-line block-no-empty */', - }, - ], - - reject: [ - { - code: 'a { color: pink; }b { color: red; }', - message: messages.expectedAfter(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; } b { color: red; }', - message: messages.expectedAfter(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; }\nb { color: red; }', - message: messages.expectedAfter(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; }\r\nb { color: red; }', - description: 'CRLF', - message: messages.expectedAfter(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; }\tb { color: red; }', - message: messages.expectedAfter(), - line: 1, - column: 19, - }, - { - code: '@media print { a { color: pink; }b { color: red; }}', - message: messages.expectedAfter(), - line: 1, - column: 34, - }, - { - code: '@media print { a { color: pink; }}@media screen { b { color: red; }}', - message: messages.expectedAfter(), - line: 1, - column: 35, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink; }b { color: red; }', - }, - { - code: 'a { color: pink;}b { color: red;}', - }, - { - code: '@media print { a { color: pink; }b { color: red; } }', - }, - { - code: '@media print { a { color: pink; } }@media screen { b { color: red; } }', - }, - ], - - reject: [ - { - code: 'a { color: pink; } b { color: red; }', - message: messages.rejectedAfter(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; } b { color: red; }', - message: messages.rejectedAfter(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; }\nb { color: red; }', - message: messages.rejectedAfter(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; }\r\nb { color: red; }', - description: 'CRLF', - message: messages.rejectedAfter(), - line: 1, - column: 19, - }, - { - code: 'a { color: pink; }\tb { color: red; }', - message: messages.rejectedAfter(), - line: 1, - column: 19, - }, - { - code: '@media print { a { color: pink; } b { color: red; }}', - message: messages.rejectedAfter(), - line: 1, - column: 34, - }, - { - code: '@media print { a { color: pink; }} @media screen { b { color: red; }}', - message: messages.rejectedAfter(), - line: 1, - column: 35, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - - accept: [ - { - code: 'a { color: pink; background: orange; }', - }, - { - code: 'a { color: pink; background: orange; } b { color: red; }', - }, - { - code: 'a { color: pink; background: orange;} b { color: red;}', - }, - { - code: 'a { color:\npink;}', - }, - { - code: 'a { color:\r\npink;}', - description: 'CRLF', - }, - { - code: 'a { color:\npink;}b { color: red; }', - }, - { - code: 'a { color:\npink;}b { color:\nred;}', - }, - { - code: '@media print { a {\ncolor: pink; } b { color: red;}}', - }, - { - code: '@media print { a {\ncolor: pink; }} @media screen { b { color: red;}}', - }, - { - code: '@media print { a {\r\ncolor: pink; }} @media screen { b { color: red;}}', - description: 'CRLF', - }, - ], - - reject: [ - { - code: 'a { color: pink; background: orange;}b { color: red; }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 38, - }, - { - code: 'a { color: pink; background: orange;} b { color: red; }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 38, - }, - { - code: 'a { color: pink; background: orange;}\tb { color: red; }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 38, - }, - { - code: '@media print { a { color: pink; }b { color: red; }}', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 34, - }, - { - code: '@media print { a { color: pink; }}@media screen { b { color: red; }}', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 35, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - - accept: [ - { - code: 'a { color: pink; background: orange; }', - }, - { - code: 'a { color: pink; background: orange; }b { color: red; }', - }, - { - code: 'a { color: pink; background: orange;}b { color: red;}', - }, - { - code: 'a { color:\npink;}', - }, - { - code: 'a { color:\r\npink;}', - description: 'CRLF', - }, - { - code: 'a { color:\npink;} b { color: red; }', - }, - { - code: 'a { color:\npink;} b { color:\nred;}', - }, - { - code: '@media print { a {\ncolor: pink;} b { color: red;} }', - }, - { - code: '@media print { a {\r\ncolor: pink;} b { color: red;} }', - description: 'CRLF', - }, - { - code: '@media print { a {\ncolor: pink;} } @media screen { b { color: red;} }', - }, - ], - - reject: [ - { - code: 'a { color: pink; background: orange;} b { color: red; }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 38, - }, - { - code: 'a { color: pink; background: orange;} b { color: red; }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 38, - }, - { - code: 'a { color: pink; background: orange;}\tb { color: red; }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 38, - }, - { - code: '@media print { a { color: pink; } b { color: red; }}', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 34, - }, - { - code: '@media print { a { color: pink; }} @media screen { b { color: red; }}', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 35, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - - accept: [ - { - code: 'a { color: pink;\nbackground: orange; }', - }, - { - code: 'a { color: pink;\r\nbackground: orange; }', - description: 'CRLF', - }, - { - code: 'a { color: pink;\nbackground: orange; } b { color: red; }', - }, - { - code: 'a { color: pink;\nbackground: orange;} b { color: red;}', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink; }b { color: red; }', - }, - { - code: 'a { color: pink;}b { color: red;}', - }, - { - code: '@media print { a {\ncolor: pink; } b { color: red; }}', - }, - { - code: '@media print { a {\r\ncolor: pink; } b { color: red; }}', - description: 'CRLF', - }, - { - code: '@media print { a {\ncolor: pink; }} @media screen { b { color: red; }}', - }, - ], - - reject: [ - { - code: 'a { color: pink;\nbackground: orange;}b { color: red; }', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 21, - }, - { - code: 'a { color: pink;\nbackground: orange;} b { color: red; }', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 21, - }, - { - code: 'a { color: pink;\nbackground: orange;}\nb { color: red; }', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 21, - }, - { - code: 'a { color: pink;\r\nbackground: orange;}\r\nb { color: red; }', - description: 'CRLF', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 21, - }, - { - code: 'a { color: pink;\nbackground: orange;}\tb { color: red; }', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 21, - }, - { - code: '@media print { a {\ncolor: pink; }b { color: red; }}', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 15, - }, - { - code: '@media print { a {\ncolor: pink; }}@media screen { b {\ncolor: red; }}', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 16, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - - accept: [ - { - code: 'a { color: pink;\nbackground: orange; }', - }, - { - code: 'a { color: pink;\r\nbackground: orange; }', - description: 'CRLF', - }, - { - code: 'a { color: pink;\nbackground: orange; }b { color: red; }', - }, - { - code: 'a { color: pink;\nbackground: orange;}b { color: red;}', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink; } b { color: red; }', - }, - { - code: 'a { color: pink;} b { color: red;}', - }, - { - code: '@media print { a {\ncolor: pink; }b { color: red; } }', - }, - { - code: '@media print { a {\r\ncolor: pink; }b { color: red; } }', - description: 'CRLF', - }, - { - code: '@media print { a {\ncolor: pink; }}@media screen { b { color: red; } }', - }, - ], - - reject: [ - { - code: 'a { color: pink;\nbackground: orange;} b { color: red; }', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 21, - }, - { - code: 'a { color: pink;\nbackground: orange;} b { color: red; }', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 21, - }, - { - code: 'a { color: pink;\nbackground: orange;}\nb { color: red; }', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 21, - }, - { - code: 'a { color: pink;\nbackground: orange;}\tb { color: red; }', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 21, - }, - { - code: '@media print { a {\ncolor: pink; } b { color: red; }}', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 15, - }, - { - code: '@media print { a {\ncolor: pink; }} @media screen { b {\ncolor: red; }}', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 16, - }, - { - code: '@media print { a {\r\ncolor: pink; }} @media screen { b {\r\ncolor: red; }}', - description: 'CRLF', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 16, - }, - ], -}); diff --git a/lib/rules/block-closing-brace-space-after/index.js b/lib/rules/block-closing-brace-space-after/index.js deleted file mode 100644 index f285d06723..0000000000 --- a/lib/rules/block-closing-brace-space-after/index.js +++ /dev/null @@ -1,96 +0,0 @@ -'use strict'; - -const blockString = require('../../utils/blockString'); -const hasBlock = require('../../utils/hasBlock'); -const rawNodeString = require('../../utils/rawNodeString'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'block-closing-brace-space-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected single space after "}"', - rejectedAfter: () => 'Unexpected whitespace after "}"', - expectedAfterSingleLine: () => 'Expected single space after "}" of a single-line block', - rejectedAfterSingleLine: () => 'Unexpected whitespace after "}" of a single-line block', - expectedAfterMultiLine: () => 'Expected single space after "}" of a multi-line block', - rejectedAfterMultiLine: () => 'Unexpected whitespace after "}" of a multi-line block', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/block-closing-brace-space-after', - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: [ - 'always', - 'never', - 'always-single-line', - 'never-single-line', - 'always-multi-line', - 'never-multi-line', - ], - }); - - if (!validOptions) { - return; - } - - // Check both kinds of statements: rules and at-rules - root.walkRules(check); - root.walkAtRules(check); - - /** - * @param {import('postcss').Rule | import('postcss').AtRule} statement - */ - function check(statement) { - const nextNode = statement.next(); - - if (!nextNode) { - return; - } - - if (!hasBlock(statement)) { - return; - } - - let reportIndex = statement.toString().length; - let source = rawNodeString(nextNode); - - // Skip a semicolon at the beginning, if any - if (source && source.startsWith(';')) { - source = source.slice(1); - reportIndex++; - } - - checker.after({ - source, - index: -1, - lineCheckStr: blockString(statement), - err: (msg) => { - report({ - message: msg, - node: statement, - index: reportIndex, - result, - ruleName, - }); - }, - }); - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/block-closing-brace-space-before/README.md b/lib/rules/block-closing-brace-space-before/README.md deleted file mode 100644 index c765edfb93..0000000000 --- a/lib/rules/block-closing-brace-space-before/README.md +++ /dev/null @@ -1,176 +0,0 @@ -# block-closing-brace-space-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace before the closing brace of blocks. - - -```css -a { color: pink; } -/** ↑ - * The space before this brace */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"|"always-single-line"|"never-single-line"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a single space before the closing brace. - -The following patterns are considered problems: - - -```css -a { color: pink;} -``` - - -```css -a -{ color: pink;} -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { -color: pink; } -``` - -### `"never"` - -There _must never_ be whitespace before the closing brace. - -The following patterns are considered problems: - - -```css -a { color: pink; } -``` - - -```css -a -{ color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a{ color: pink;} -``` - - -```css -a{ -color: pink;} -``` - -### `"always-single-line"` - -There _must always_ be a single space before the closing brace in single-line blocks. - -The following patterns are considered problems: - - -```css -a { color: pink;} -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { -color: pink;} -``` - -### `"never-single-line"` - -There _must never_ be whitespace before the closing brace in single-line blocks. - -The following patterns are considered problems: - - -```css -a { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink;} -``` - - -```css -a { -color: pink; } -``` - -### `"always-multi-line"` - -There _must always_ be a single space before the closing brace in multi-line blocks. - -The following patterns are considered problems: - - -```css -a { -color: pink;} -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink;} -``` - - -```css -a { -color: pink; } -``` - -### `"never-multi-line"` - -There _must never_ be whitespace before the closing brace in multi-line blocks. - -The following patterns are considered problems: - - -```css -a { -color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { -color: pink;} -``` diff --git a/lib/rules/block-closing-brace-space-before/__tests__/index.js b/lib/rules/block-closing-brace-space-before/__tests__/index.js deleted file mode 100644 index d5cd400889..0000000000 --- a/lib/rules/block-closing-brace-space-before/__tests__/index.js +++ /dev/null @@ -1,514 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink; } b { color: red; }', - }, - { - code: 'a { color: pink; }b { color: red; }', - }, - ], - - reject: [ - { - code: 'a { color: pink;}', - fixed: 'a { color: pink; }', - message: messages.expectedBefore(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedBefore(), - line: 1, - column: 18, - }, - { - code: 'a { color: pink;\n}', - fixed: 'a { color: pink; }', - message: messages.expectedBefore(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink;\r\n}', - fixed: 'a { color: pink; }', - description: 'CRLF', - message: messages.expectedBefore(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink;\t}', - fixed: 'a { color: pink; }', - message: messages.expectedBefore(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink; } b { color: red;}', - fixed: 'a { color: pink; } b { color: red; }', - message: messages.expectedBefore(), - line: 1, - column: 34, - }, - { - code: 'a { color: pink;} b { color: red;}', - fixed: 'a { color: pink; } b { color: red; }', - warnings: [ - { - message: messages.expectedBefore(), - line: 1, - column: 16, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 33, - }, - ], - }, - { - code: 'a { color: pink;/*comment*/}', - fixed: 'a { color: pink;/*comment*/ }', - message: messages.expectedBefore(), - line: 1, - column: 27, - }, - { - code: 'a { color: pink;;;}', - fixed: 'a { color: pink;;; }', - message: messages.expectedBefore(), - line: 1, - column: 18, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a { color: pink;}', - }, - { - code: 'a { color: pink;} b { color: red;}', - }, - { - code: 'a { color: pink;}b { color: red;}', - }, - ], - - reject: [ - { - code: 'a { color: pink; }', - fixed: 'a { color: pink;}', - message: messages.rejectedBefore(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink; }', - fixed: 'a { color: pink;}', - message: messages.rejectedBefore(), - line: 1, - column: 18, - }, - { - code: 'a { color: pink;\n}', - fixed: 'a { color: pink;}', - message: messages.rejectedBefore(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink;\r\n}', - fixed: 'a { color: pink;}', - description: 'CRLF', - message: messages.rejectedBefore(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink;\t}', - fixed: 'a { color: pink;}', - message: messages.rejectedBefore(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink;} b { color: red; }', - fixed: 'a { color: pink;} b { color: red;}', - message: messages.rejectedBefore(), - line: 1, - column: 34, - }, - { - code: 'a { color: pink; } b { color: red; }', - fixed: 'a { color: pink;} b { color: red;}', - warnings: [ - { - message: messages.rejectedBefore(), - line: 1, - column: 17, - }, - { - message: messages.rejectedBefore(), - line: 1, - column: 35, - }, - ], - }, - { - code: 'a { color: pink; /*comment*/ }', - fixed: 'a { color: pink; /*comment*/}', - message: messages.rejectedBefore(), - line: 1, - column: 29, - }, - { - code: 'a { color: pink ; ; ; }', - fixed: 'a { color: pink ; ; ;}', - message: messages.rejectedBefore(), - line: 1, - column: 22, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink; } b { color: red; }', - }, - { - code: 'a { color: pink; }b { color: red; }', - }, - { - code: 'a,\nb { color: pink; } c { color: red; }', - description: 'multi-line rule, single-line block', - }, - { - code: 'a { color: pink;\ntop: 0;}', - }, - { - code: 'a { color: pink;\n\ntop: 0;}', - description: 'CRLF', - }, - { - code: 'a { color: pink;\ntop: 0; } b { color: red; }', - }, - { - code: 'a { color: pink;\ntop: 0;\n}b { color: red; }', - }, - ], - - reject: [ - { - code: 'a { color: pink;}', - fixed: 'a { color: pink; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 16, - }, - { - code: 'a,\nb { color: pink;}', - fixed: 'a,\nb { color: pink; }', - message: messages.expectedBeforeSingleLine(), - line: 2, - column: 16, - }, - { - code: 'a,\r\nb { color: pink;}', - fixed: 'a,\r\nb { color: pink; }', - description: 'CRLF', - message: messages.expectedBeforeSingleLine(), - line: 2, - column: 16, - }, - { - code: 'a { color: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 18, - }, - { - code: 'a { color: pink;\t}', - fixed: 'a { color: pink; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink; } b { color: red;}', - fixed: 'a { color: pink; } b { color: red; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 34, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink;}', - }, - { - code: 'a { color: pink;} b { color: red;}', - }, - { - code: 'a { color: pink;}b { color: red;}', - }, - { - code: 'a,\nb { color: pink;} b { color: red;}', - description: 'multi-line rule, single-line block', - }, - { - code: 'a { color: pink;\ntop: 0; }', - }, - { - code: 'a { color: pink;\r\ntop: 0; }', - description: 'CRLF', - }, - { - code: 'a { color: pink;\ntop: 0; } b { color: red;}', - }, - { - code: 'a { color: pink;\ntop: 0;\n}b { color: red;}', - }, - ], - - reject: [ - { - code: 'a { color: pink; }', - fixed: 'a { color: pink;}', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 17, - }, - { - code: 'a,\nb { color: pink; }', - fixed: 'a,\nb { color: pink;}', - message: messages.rejectedBeforeSingleLine(), - line: 2, - column: 17, - }, - { - code: 'a,\r\nb { color: pink; }', - fixed: 'a,\r\nb { color: pink;}', - description: 'CRLF', - message: messages.rejectedBeforeSingleLine(), - line: 2, - column: 17, - }, - { - code: 'a { color: pink; }', - fixed: 'a { color: pink;}', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 18, - }, - { - code: 'a { color: pink;\t}', - fixed: 'a { color: pink;}', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink;} b { color: red;\t}', - fixed: 'a { color: pink;} b { color: red;}', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 34, - }, - { - code: 'a { color: pink; } b { color: red;}', - fixed: 'a { color: pink;} b { color: red;}', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 18, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink;\ntop: 0; }', - }, - { - code: 'a { color: pink;\ntop: 0; } b { color: red; }', - }, - { - code: 'a { color: pink;\ntop: 0; }b { color: red; }', - }, - { - code: 'a { color: pink;\r\ntop: 0; }b { color: red; }', - description: 'CRLF', - }, - { - code: 'a { color: pink;}', - }, - { - code: 'a { color: pink; } b { color: red; }', - }, - { - code: 'a { color: pink;\t}b { color: red; }', - }, - ], - - reject: [ - { - code: 'a { color: pink;\ntop: 0;}', - fixed: 'a { color: pink;\ntop: 0; }', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 7, - }, - { - code: 'a { color: pink;\ntop: 0; }', - fixed: 'a { color: pink;\ntop: 0; }', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 9, - }, - { - code: 'a { color: pink;\ntop: 0;\t}', - fixed: 'a { color: pink;\ntop: 0; }', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 8, - }, - { - code: 'a { color: pink; } b { color: red;\ntop: 0;}', - fixed: 'a { color: pink; } b { color: red;\ntop: 0; }', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 7, - }, - { - code: 'a { color: pink;\ntop: 0;} b { color: red; }', - fixed: 'a { color: pink;\ntop: 0; } b { color: red; }', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 7, - }, - { - code: 'a { color: pink;\r\ntop: 0;} b { color: red; }', - fixed: 'a { color: pink;\r\ntop: 0; } b { color: red; }', - description: 'CRLF', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 7, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink;\ntop: 0;}', - }, - { - code: 'a { color: pink;\ntop: 0;} b { color: red;}', - }, - { - code: 'a { color: pink;\r\ntop: 0;} b { color: red;}', - description: 'CRLF', - }, - { - code: 'a { color: pink;\ntop: 0;}b { color: red;}', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink; } b { color: red; }', - }, - { - code: 'a { color: pink;\t}b { color: red; }', - }, - ], - - reject: [ - { - code: 'a { color: pink;\ntop: 0; }', - fixed: 'a { color: pink;\ntop: 0;}', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 8, - }, - { - code: 'a { color: pink;\ntop: 0; }', - fixed: 'a { color: pink;\ntop: 0;}', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 9, - }, - { - code: 'a { color: pink;\ntop: 0;\t}', - fixed: 'a { color: pink;\ntop: 0;}', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 8, - }, - { - code: 'a { color: pink;\r\ntop: 0;\t}', - fixed: 'a { color: pink;\r\ntop: 0;}', - description: 'CRLF', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 8, - }, - { - code: 'a { color: pink; } b { color: red;\ntop: 0; }', - fixed: 'a { color: pink; } b { color: red;\ntop: 0;}', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 8, - }, - { - code: 'a { color: pink;\ntop: 0; } b { color: red; }', - fixed: 'a { color: pink;\ntop: 0;} b { color: red; }', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 8, - }, - ], -}); diff --git a/lib/rules/block-closing-brace-space-before/index.js b/lib/rules/block-closing-brace-space-before/index.js deleted file mode 100644 index 03ac08f1f8..0000000000 --- a/lib/rules/block-closing-brace-space-before/index.js +++ /dev/null @@ -1,109 +0,0 @@ -'use strict'; - -const blockString = require('../../utils/blockString'); -const hasBlock = require('../../utils/hasBlock'); -const hasEmptyBlock = require('../../utils/hasEmptyBlock'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'block-closing-brace-space-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected single space before "}"', - rejectedBefore: () => 'Unexpected whitespace before "}"', - expectedBeforeSingleLine: () => 'Expected single space before "}" of a single-line block', - rejectedBeforeSingleLine: () => 'Unexpected whitespace before "}" of a single-line block', - expectedBeforeMultiLine: () => 'Expected single space before "}" of a multi-line block', - rejectedBeforeMultiLine: () => 'Unexpected whitespace before "}" of a multi-line block', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/block-closing-brace-space-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: [ - 'always', - 'never', - 'always-single-line', - 'never-single-line', - 'always-multi-line', - 'never-multi-line', - ], - }); - - if (!validOptions) { - return; - } - - // Check both kinds of statement: rules and at-rules - root.walkRules(check); - root.walkAtRules(check); - - /** - * @param {import('postcss').Rule | import('postcss').AtRule} statement - */ - function check(statement) { - // Return early if blockless or has empty block - if (!hasBlock(statement) || hasEmptyBlock(statement)) { - return; - } - - const source = blockString(statement); - const statementString = statement.toString(); - - let index = statementString.length - 2; - - if (statementString[index - 1] === '\r') { - index -= 1; - } - - checker.before({ - source, - index: source.length - 1, - err: (msg) => { - if (context.fix) { - const statementRaws = statement.raws; - - if (typeof statementRaws.after !== 'string') return; - - if (primary.startsWith('always')) { - statementRaws.after = statementRaws.after.replace(/\s*$/, ' '); - - return; - } - - if (primary.startsWith('never')) { - statementRaws.after = statementRaws.after.replace(/\s*$/, ''); - - return; - } - } - - report({ - message: msg, - node: statement, - index, - result, - ruleName, - }); - }, - }); - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/block-opening-brace-newline-after/README.md b/lib/rules/block-opening-brace-newline-after/README.md deleted file mode 100644 index b93548c3bb..0000000000 --- a/lib/rules/block-opening-brace-newline-after/README.md +++ /dev/null @@ -1,140 +0,0 @@ -# block-opening-brace-newline-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline after the opening brace of blocks. - - -```css - a { - ↑ color: pink; } -/** ↑ - * The newline after this brace */ -``` - -This rule allows an end-of-line comment followed by a newline. For example, - - -```css -a { /* end-of-line comment */ - color: pink; -} -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a newline after the opening brace. - -The following patterns are considered problems: - - -```css -a{ color: pink; } -``` - - -```css -a{ color: pink; -} -``` - - -```css -a{ /* end-of-line comment - with a newline */ - color: pink; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { -color: pink; } -``` - - -```css -a -{ -color: pink; } -``` - - -```css -a { /* end-of-line comment */ - color: pink; -} -``` - -### `"always-multi-line"` - -There _must always_ be a newline after the opening brace in multi-line blocks. - -The following patterns are considered problems: - - -```css -a{color: pink; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { -color: pink; } -``` - -### `"never-multi-line"` - -There _must never_ be whitespace after the opening brace in multi-line blocks. - -The following patterns are considered problems: - - -```css -a { color: pink; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a {color: pink; -} -``` - -## Optional secondary options - -### `ignore: ["rules"]` - -Ignore the opening brace of rules. - -For example, with `"always"`: - -The following pattern is _not_ considered a problem: - - -```css -a { color: pink; } -``` diff --git a/lib/rules/block-opening-brace-newline-after/__tests__/index.js b/lib/rules/block-opening-brace-newline-after/__tests__/index.js deleted file mode 100644 index c91c26816d..0000000000 --- a/lib/rules/block-opening-brace-newline-after/__tests__/index.js +++ /dev/null @@ -1,460 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: '@import url(x.css)', - }, - { - code: 'a {\ncolor: pink; }', - }, - { - code: 'a {\r\ncolor: pink; }', - description: 'CRLF', - }, - { - code: 'a {\n\ncolor: pink; }', - }, - { - code: 'a {\r\n\r\ncolor: pink; }', - description: 'CRLF', - }, - { - code: 'a{\ncolor: pink; }', - }, - { - code: 'a{\n\tcolor: pink; }', - }, - { - code: 'a{\n color: pink; }', - }, - { - code: 'a{\r\n color: pink; }', - description: 'CRLF', - }, - { - code: '@media print {\na {\ncolor: pink; } }', - }, - { - code: '@media print{\na{\ncolor: pink; } }', - }, - { - code: '@media print{\r\na{\r\ncolor: pink; } }', - description: 'CRLF', - }, - { - code: '@media print{\n\ta{\n color: pink; } }', - }, - { - code: 'a { /* 1 */\n color: pink;\n}', - description: 'end-of-line comment', - }, - { - code: 'a { /* 1 */\n color: pink;\n}', - description: 'end-of-line comment with multiple spaces before', - }, - { - code: 'a {\n /* 1 */\n color: pink;\n}', - description: 'next-line comment', - }, - { - code: 'a {\r\n /* 1 */\r\n color: pink;\r\n}', - description: 'next-line comment and CRLF', - }, - { - code: '.a {\n/*.b*/.c {\n color: pink; }\n }', - description: 'next-line comment with quasi-qualified selector', - }, - { - code: '.a {\r\n/*.b*/.c {\r\n color: pink; }\r\n }', - description: 'next-line comment and CRLF with quasi-qualified selector', - }, - { - code: '@media print {\n /*.test2*/.a {\n color: pink;\n }\n }', - }, - { - code: '@media print {\r\n /*.test2*/.a {\r\n color: pink;\r\n }\r\n }', - }, - { - code: '@media print {\n /*.test2*/\n .a {\n color: pink;\n }\n }', - }, - { - code: '@media print {\r\n /*.test2*/\r\n .a {\r\n color: pink;\r\n }\r\n }', - }, - { - code: '@media print {\r\n /*.test2*/\r\n .a {\r\n color: pink;\r\n }\r\n }', - }, - ], - - reject: [ - { - code: 'a { color: pink; }', - fixed: 'a {\n color: pink; }', - message: messages.expectedAfter(), - line: 1, - column: 4, - }, - { - code: 'a {color: pink; }', - fixed: 'a {\ncolor: pink; }', - message: messages.expectedAfter(), - line: 1, - column: 4, - }, - { - code: 'a { color: pink; }', - fixed: 'a {\n color: pink; }', - message: messages.expectedAfter(), - line: 1, - column: 4, - }, - { - code: 'a {\tcolor: pink; }', - fixed: 'a {\n\tcolor: pink; }', - message: messages.expectedAfter(), - line: 1, - column: 4, - }, - { - code: '@media print { a {\ncolor: pink; } }', - fixed: '@media print {\n a {\ncolor: pink; } }', - message: messages.expectedAfter(), - line: 1, - column: 15, - }, - { - code: '@media print {\na { color: pink; } }', - fixed: '@media print {\na {\n color: pink; } }', - message: messages.expectedAfter(), - line: 2, - column: 4, - }, - { - code: '@media print {\r\na { color: pink; } }', - fixed: '@media print {\r\na {\r\n color: pink; } }', - description: 'CRLF', - message: messages.expectedAfter(), - line: 2, - column: 4, - }, - { - code: 'a { /* 1 */ color: pink; }', - fixed: 'a { /* 1 */\n color: pink; }', - description: 'next node is comment without newline after', - message: messages.expectedAfter(), - line: 1, - column: 4, - }, - { - code: '.a {/*.b*/.c { color: pink; } }', - fixed: '.a {/*.b*/\n.c {\n color: pink; } }', - description: 'next node is quasi-qualified selector without newline after', - warnings: [ - { - message: messages.expectedAfter(), - line: 1, - column: 5, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 15, - }, - ], - }, - { - code: '.a {/*.b*/\n.c { color: pink; } }', - fixed: '.a {/*.b*/\n.c {\n color: pink; } }', - description: 'next node is quasi-qualified selector with newline', - message: messages.expectedAfter(), - line: 2, - column: 5, - }, - { - code: '.a {/*.b*/\r\n.c { color: pink; } }', - fixed: '.a {/*.b*/\r\n.c {\r\n color: pink; } }', - description: 'next node is quasi-qualified selector with CRLF', - message: messages.expectedAfter(), - line: 2, - column: 5, - }, - { - code: 'a { \ncolor: pink; }', - fixed: 'a {\ncolor: pink; }', - description: 'space before a newline', - message: messages.expectedAfter(), - line: 1, - column: 4, - }, - { - code: 'a { \r\ncolor: pink; }', - fixed: 'a {\r\ncolor: pink; }', - description: 'space before a CRLF', - message: messages.expectedAfter(), - line: 1, - column: 4, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: 'a {\ncolor: pink; }', - }, - { - code: 'a {\n color: pink;\n background: orange; }', - }, - { - code: 'a {\r\n color: pink;\r\n background: orange; }', - description: 'CRLF', - }, - { - code: 'a{\ncolor: pink; }', - }, - { - code: 'a{\n\tcolor: pink; }', - }, - { - code: 'a{\n color: pink; }', - }, - { - code: '@media print {\na {\ncolor: pink; } }', - }, - { - code: '@media print {\r\na {\r\ncolor: pink; } }', - description: 'CRLF', - }, - { - code: '@media print{\na{\ncolor: pink; } }', - }, - { - code: '@media print{\n\ta{\n color: pink; } }', - }, - { - code: '@media print{\r\n\ta{\r\n color: pink; } }', - description: 'CRLF', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a {\tcolor: pink; }', - }, - { - code: 'a { color: pink; background: orange; }', - }, - { - code: 'a { /* 1 */ color: pink; }', - }, - { - code: '.a {/*.b*/.c { color: pink; } }', - }, - ], - - reject: [ - { - code: 'a { color: pink;\nbackground: orange; }', - fixed: 'a {\n color: pink;\nbackground: orange; }', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a {color: pink;\nbackground: orange; }', - fixed: 'a {\ncolor: pink;\nbackground: orange; }', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a { color: pink;\nbackground: orange; }', - fixed: 'a {\n color: pink;\nbackground: orange; }', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a {\tcolor: pink;\nbackground: orange; }', - fixed: 'a {\n\tcolor: pink;\nbackground: orange; }', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a {\tcolor: pink;\r\nbackground: orange; }', - fixed: 'a {\r\n\tcolor: pink;\r\nbackground: orange; }', - description: 'CRLF', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: '@media print { a {\ncolor:\npink; } }', - fixed: '@media print {\n a {\ncolor:\npink; } }', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 15, - }, - { - code: '@media print {\na { color:\npink; } }', - fixed: '@media print {\na {\n color:\npink; } }', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 4, - }, - { - code: '@media print {\r\na { color:\r\npink; } }', - fixed: '@media print {\r\na {\r\n color:\r\npink; } }', - description: 'CRLF', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 4, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - fix: true, - - accept: [ - { - code: 'a {color: pink;\nbackground: orange; }', - }, - { - code: 'a {color: pink;\r\nbackground: orange; }', - description: 'CRLF', - }, - { - code: 'a{color: pink;\nbackground: orange; }', - }, - { - code: '@media print {a {color: pink;\nbackground: orange; } }', - }, - { - code: '@media print{a{color: pink;\nbackground: orange; } }', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a {\tcolor: pink; }', - }, - { - code: '@media print { a { color: pink; } }', - }, - { - code: '@media print {\ta {\tcolor: pink; } }', - }, - ], - - reject: [ - { - code: 'a { color: pink;\nbackground: orange; }', - fixed: 'a {color: pink;\nbackground: orange; }', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a {\ncolor: pink;\nbackground: orange; }', - fixed: 'a {color: pink;\nbackground: orange; }', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a {\r\ncolor: pink;\r\nbackground: orange; }', - fixed: 'a {color: pink;\r\nbackground: orange; }', - description: 'CRLF', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a { color: pink;\nbackground: orange; }', - fixed: 'a {color: pink;\nbackground: orange; }', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a {\tcolor: pink;\nbackground: orange; }', - fixed: 'a {color: pink;\nbackground: orange; }', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: '@media print {\na {color: pink;\nbackground: orange; } }', - fixed: '@media print {a {color: pink;\nbackground: orange; } }', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 15, - }, - { - code: '@media print {a {\ncolor: pink;\nbackground: orange; } }', - fixed: '@media print {a {color: pink;\nbackground: orange; } }', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 18, - }, - { - code: 'a {\n/*comment*/ color: pink;\nbackground: orange; }', - fixed: 'a {/*comment*/color: pink;\nbackground: orange; }', - description: 'include comment', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a {\n /*c1*/ /*c2*/ \n\n /*c3*/ color: pink;\nbackground: orange; }', - fixed: 'a { /*c1*/ /*c2*/ /*c3*/color: pink;\nbackground: orange; }', - description: 'multi comments', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 4, - }, - ], -}); - -testRule({ - ruleName, - config: ['always', { ignore: ['rules'] }], - fix: true, - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a {\ncolor: pink; }', - }, - { - code: '@media print {\na {\ncolor: pink; } }', - }, - ], - reject: [ - { - code: '@media print { a { color: pink; } }', - fixed: '@media print {\n a { color: pink; } }', - message: messages.expectedAfter(), - line: 1, - column: 15, - }, - ], -}); diff --git a/lib/rules/block-opening-brace-newline-after/index.js b/lib/rules/block-opening-brace-newline-after/index.js deleted file mode 100644 index fc6984e7b4..0000000000 --- a/lib/rules/block-opening-brace-newline-after/index.js +++ /dev/null @@ -1,182 +0,0 @@ -'use strict'; - -const beforeBlockString = require('../../utils/beforeBlockString'); -const blockString = require('../../utils/blockString'); -const hasBlock = require('../../utils/hasBlock'); -const hasEmptyBlock = require('../../utils/hasEmptyBlock'); -const optionsMatches = require('../../utils/optionsMatches'); -const rawNodeString = require('../../utils/rawNodeString'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'block-opening-brace-newline-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected newline after "{"', - expectedAfterMultiLine: () => 'Expected newline after "{" of a multi-line block', - rejectedAfterMultiLine: () => 'Unexpected whitespace after "{" of a multi-line block', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/block-opening-brace-newline-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, secondaryOptions, context) => { - const checker = whitespaceChecker('newline', primary, messages); - - return (root, result) => { - const validOptions = validateOptions( - result, - ruleName, - { - actual: primary, - possible: ['always', 'rules', 'always-multi-line', 'never-multi-line'], - }, - { - actual: secondaryOptions, - possible: { - ignore: ['rules'], - }, - optional: true, - }, - ); - - if (!validOptions) { - return; - } - - // Check both kinds of statement: rules and at-rules - if (!optionsMatches(secondaryOptions, 'ignore', 'rules')) { - root.walkRules(check); - } - - root.walkAtRules(check); - - /** - * @param {import('postcss').Rule | import('postcss').AtRule} statement - */ - function check(statement) { - // Return early if blockless or has an empty block - if (!hasBlock(statement) || hasEmptyBlock(statement)) { - return; - } - - const backupCommentNextBefores = new Map(); - - /** - * next node with checking newlines after comment - * - * @param {import('postcss').ChildNode | undefined} startNode - * @returns {import('postcss').ChildNode | undefined} - */ - function nextNode(startNode) { - if (!startNode || !startNode.next) return; - - if (startNode.type === 'comment') { - const reNewLine = /\r?\n/; - const newLineMatch = reNewLine.test(startNode.raws.before || ''); - - const next = startNode.next(); - - if (next && newLineMatch && !reNewLine.test(next.raws.before || '')) { - backupCommentNextBefores.set(next, next.raws.before); - next.raws.before = startNode.raws.before; - } - - return nextNode(next); - } - - return startNode; - } - - // Allow an end-of-line comment - const nodeToCheck = nextNode(statement.first); - - if (!nodeToCheck) { - return; - } - - checker.afterOneOnly({ - source: rawNodeString(nodeToCheck), - index: -1, - lineCheckStr: blockString(statement), - err: (m) => { - if (context.fix) { - const nodeToCheckRaws = nodeToCheck.raws; - - if (typeof nodeToCheckRaws.before !== 'string') return; - - if (primary.startsWith('always')) { - const index = nodeToCheckRaws.before.search(/\r?\n/); - - nodeToCheckRaws.before = - index >= 0 - ? nodeToCheckRaws.before.slice(index) - : context.newline + nodeToCheckRaws.before; - - backupCommentNextBefores.delete(nodeToCheck); - - return; - } - - if (primary === 'never-multi-line') { - // Restore the `before` of the node next to the comment node. - for (const [node, before] of backupCommentNextBefores.entries()) { - node.raws.before = before; - } - - backupCommentNextBefores.clear(); - - // Fix - const reNewLine = /\r?\n/; - let fixTarget = statement.first; - - while (fixTarget) { - const fixTargetRaws = fixTarget.raws; - - if (typeof fixTargetRaws.before !== 'string') continue; - - if (reNewLine.test(fixTargetRaws.before || '')) { - fixTargetRaws.before = fixTargetRaws.before.replace(/\r?\n/g, ''); - } - - if (fixTarget.type !== 'comment') { - break; - } - - fixTarget = fixTarget.next(); - } - - nodeToCheckRaws.before = ''; - - return; - } - } - - report({ - message: m, - node: statement, - index: beforeBlockString(statement, { noRawBefore: true }).length + 1, - result, - ruleName, - }); - }, - }); - - // Restore the `before` of the node next to the comment node. - for (const [node, before] of backupCommentNextBefores.entries()) { - node.raws.before = before; - } - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/block-opening-brace-newline-before/README.md b/lib/rules/block-opening-brace-newline-before/README.md deleted file mode 100644 index 503cf250d9..0000000000 --- a/lib/rules/block-opening-brace-newline-before/README.md +++ /dev/null @@ -1,176 +0,0 @@ -# block-opening-brace-newline-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline or disallow whitespace before the opening brace of blocks. - - -```css - a - { color: pink; } -/** ↑ - * The newline before this brace */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"always-single-line"|"never-single-line"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a newline before the opening brace. - -The following patterns are considered problems: - - -```css -a{ color: pink; } -``` - - -```css -a{ color: pink; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a -{ color: pink; } -``` - - -```css -a -{ -color: pink; } -``` - - -```css -a /* foo */ - { - color: pink; - } -``` - -### `"always-single-line"` - -There _must always_ be a newline before the opening brace in single-line blocks. - -The following patterns are considered problems: - - -```css -a{ color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a -{ color: pink; } -``` - - -```css -a{ -color: pink; } -``` - -### `"never-single-line"` - -There _must never_ be whitespace before the opening brace in single-line blocks. - -The following patterns are considered problems: - - -```css -a { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a{ color: pink; } -``` - - -```css -a { -color: pink; } -``` - -### `"always-multi-line"` - -There _must always_ be a newline before the opening brace in multi-line blocks. - -The following patterns are considered problems: - - -```css -a{ -color: pink; } -``` - - -```css -a { -color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a{ color: pink; } -``` - - -```css -a { color: pink; } -``` - - -```css -a -{ color: pink; } -``` - - -```css -a -{ -color: pink; } -``` - -### `"never-multi-line"` - -There _must never_ be whitespace before the opening brace in multi-line blocks. - -The following patterns are considered problems: - - -```css -a { -color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a{ -color: pink;} -``` diff --git a/lib/rules/block-opening-brace-newline-before/__tests__/index.js b/lib/rules/block-opening-brace-newline-before/__tests__/index.js deleted file mode 100644 index f71900584e..0000000000 --- a/lib/rules/block-opening-brace-newline-before/__tests__/index.js +++ /dev/null @@ -1,572 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: '@import url(x.css)', - }, - { - code: 'a\n{ color: pink; }', - }, - { - code: 'a\r\n{ color: pink; }', - description: 'CRLF', - }, - { - code: 'a\n\n{ color: pink; }', - }, - { - code: 'a\r\n\r\n{ color: pink; }', - description: 'CRLF', - }, - { - code: 'a\n{color: pink; }', - }, - { - code: '@media print\n{ a\n{ color: pink; } }', - }, - { - code: '@media print\r\n{ a\r\n{ color: pink; } }', - description: 'CRLF', - }, - { - code: '@media print\n{a\n{color: pink; } }', - }, - { - code: '@media print\n\t{a\n\t\t{color: pink; } }', - description: 'indentation after the newline before the opening braces', - }, - { - code: '@media print\n\t{a\n\t\t{color: pink;\n\t\t&:hover\n\t\t\t{\n\t\t\t\tcolor:black;} } }', - description: '3 level deep indentation after the newline before the opening braces', - }, - { - code: '@media print\r\n\t{a\r\n\t\t{color: pink;\r\n\t\t&:hover\r\n\t\t\t{\r\n\t\t\t\tcolor:black;} } }', - description: '3 level deep indentation after the newline before the opening braces and CRLF', - }, - { - code: 'a\n{ &:hover\n{ color: pink; }}', - }, - { - code: 'a\n{ color: red; &:hover\n{ color: pink; }}', - }, - { - code: 'a /* x */\n{ color: pink; }', - description: 'end-of-line comment after selector', - }, - ], - - reject: [ - { - code: 'a { color: pink; }', - fixed: 'a\n { color: pink; }', - message: messages.expectedBefore(), - line: 1, - column: 2, - }, - { - code: 'a{ color: pink; }', - fixed: 'a\n{ color: pink; }', - message: messages.expectedBefore(), - line: 1, - column: 1, - }, - { - code: 'a { color: pink; }', - fixed: 'a\n { color: pink; }', - message: messages.expectedBefore(), - line: 1, - column: 3, - }, - { - code: 'a\t{ color: pink; }', - fixed: 'a\n\t{ color: pink; }', - message: messages.expectedBefore(), - line: 1, - column: 2, - }, - { - code: '@media print { a\n{ color: pink; } }', - fixed: '@media print\n { a\n{ color: pink; } }', - message: messages.expectedBefore(), - line: 1, - column: 13, - }, - { - code: '@media print { a\r\n{ color: pink; } }', - fixed: '@media print\r\n { a\r\n{ color: pink; } }', - description: 'CRLF', - message: messages.expectedBefore(), - line: 1, - column: 13, - }, - { - code: '@media print\n{ a { color: pink; } }', - fixed: '@media print\n{ a\n { color: pink; } }', - message: messages.expectedBefore(), - line: 2, - column: 4, - }, - { - code: '@media print{ a\n{ color: pink; } }', - fixed: '@media print\n{ a\n{ color: pink; } }', - message: messages.expectedBefore(), - line: 1, - column: 12, - }, - { - code: '@media print{ a\r\n{ color: pink; } }', - fixed: '@media print\r\n{ a\r\n{ color: pink; } }', - description: 'CRLF', - message: messages.expectedBefore(), - line: 1, - column: 12, - }, - { - code: '@media print\n{ a{ color: pink; } }', - fixed: '@media print\n{ a\n{ color: pink; } }', - message: messages.expectedBefore(), - line: 2, - column: 3, - }, - { - code: 'a\n/* foo */{ color: pink; }', - fixed: 'a\n/* foo */\n{ color: pink; }', - message: messages.expectedBefore(), - line: 2, - column: 9, - }, - { - code: 'a\r\n/* foo */{ color: pink; }', - fixed: 'a\r\n/* foo */\r\n{ color: pink; }', - description: 'CRLF', - message: messages.expectedBefore(), - line: 2, - column: 9, - }, - { - code: '@media print /* foo */ { a /* foo */ { color: pink; } }', - fixed: '@media print /* foo */\n { a /* foo */\n { color: pink; } }', - warnings: [ - { - message: messages.expectedBefore(), - line: 1, - column: 37, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 23, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: 'a\n{ color: pink; }', - }, - { - code: 'a\n{color: pink; }', - }, - { - code: '@media print\n{ a\n{ color: pink; } }', - }, - { - code: '@media print\r\n{ a\r\n{ color: pink; } }', - description: 'CRLF', - }, - { - code: '@media print\n{a\n{color: pink; } }', - }, - { - code: 'a{ color: pink;\nbackground:orange; }', - }, - { - code: '@media print { a{ color: pink;\nbackground:orange; } }', - }, - { - code: '@media print{ a { color: pink;\nbackground:orange; } }', - }, - { - code: '@media print{\na\n{ color: pink; } }', - }, - { - code: '@media print{\r\na\r\n{ color: pink; } }', - description: 'CRLF', - }, - ], - - reject: [ - { - code: 'a { color: pink; }', - fixed: 'a\n { color: pink; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 2, - }, - { - code: 'a{ color: pink; }', - fixed: 'a\n{ color: pink; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 1, - }, - { - code: 'a { color: pink; }', - fixed: 'a\n { color: pink; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 3, - }, - { - code: 'a\t{ color: pink; }', - fixed: 'a\n\t{ color: pink; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 2, - }, - { - code: '@media print\n{ a { color: pink; } }', - fixed: '@media print\n{ a\n { color: pink; } }', - message: messages.expectedBeforeSingleLine(), - line: 2, - column: 4, - }, - { - code: '@media print\n{ a{ color: pink; } }', - fixed: '@media print\n{ a\n{ color: pink; } }', - message: messages.expectedBeforeSingleLine(), - line: 2, - column: 3, - }, - { - code: '@media print\r\n{ a{ color: pink; } }', - fixed: '@media print\r\n{ a\r\n{ color: pink; } }', - description: 'CRLF', - message: messages.expectedBeforeSingleLine(), - line: 2, - column: 3, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - fix: true, - - accept: [ - { - code: 'a{ color: pink; }', - }, - { - code: 'a{color: pink; }', - }, - { - code: '@media print{ a{ color: pink; } }', - }, - { - code: '@media print{a{color: pink; } }', - }, - { - code: 'a\n{ color: pink;\nbackground:orange; }', - }, - { - code: 'a\r\n{ color: pink;\r\nbackground:orange; }', - description: 'CRLF', - }, - { - code: '@media print { a\n{ color: pink;\nbackground:orange; } }', - }, - { - code: '@media print{ a\n{ color: pink;\nbackground:orange; } }', - }, - { - code: '@media print{\na{ color: pink; } }', - }, - { - code: '@media print{\r\na{ color: pink; } }', - description: 'CRLF', - }, - ], - - reject: [ - { - code: 'a\n{ color: pink; }', - fixed: 'a{ color: pink; }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 2, - }, - { - code: 'a\r\n{ color: pink; }', - fixed: 'a{ color: pink; }', - description: 'CRLF', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 2, - }, - { - code: 'a { color: pink; }', - fixed: 'a{ color: pink; }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 2, - }, - { - code: 'a { color: pink; }', - fixed: 'a{ color: pink; }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 3, - }, - { - code: 'a\t{ color: pink; }', - fixed: 'a{ color: pink; }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 2, - }, - { - code: '@media print\n{ a\n{ color: pink; } }', - fixed: '@media print{ a{ color: pink; } }', - message: messages.rejectedBeforeSingleLine(), - line: 2, - column: 4, - }, - { - code: '@media print\r\n{ a\r\n{ color: pink; } }', - fixed: '@media print{ a{ color: pink; } }', - description: 'CRLF', - message: messages.rejectedBeforeSingleLine(), - line: 2, - column: 4, - }, - { - code: '@media print { a\n{ color: pink; } }', - fixed: '@media print{ a{ color: pink; } }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 17, - }, - { - code: '@media print/*comment*/ { a/*comment*/\n{ color: pink; } }', - fixed: '@media print/*comment*/{ a/*comment*/{ color: pink; } }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 39, - }, - { - code: '@media print /*comment*/ { a /*comment*/\n{ color: pink; } }', - fixed: '@media print /*comment*/{ a /*comment*/{ color: pink; } }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 41, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: 'a\n{ color: pink;\nbackground: orange; }', - }, - { - code: 'a\r\n{ color: pink;\nbackground: orange; }', - description: 'CRLF', - }, - { - code: '@media print\n{\na\n{ color: pink;\nbackground: orange } }', - }, - { - code: 'a { color: pink; }', - }, - { - code: '@media print { a { color: pink; } }', - }, - { - code: 'a{ color: pink; }', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a\t{ color: pink; }', - }, - { - code: 'a /* foo */\n {\n color: pink;\n }', - }, - ], - - reject: [ - { - code: 'a{ color: pink;\nbackground: orange; }', - fixed: 'a\n{ color: pink;\nbackground: orange; }', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 1, - }, - { - code: 'a { color: pink;\nbackground: orange; }', - fixed: 'a\n { color: pink;\nbackground: orange; }', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 3, - }, - { - code: 'a\t{ color: pink;\nbackground: orange; }', - fixed: 'a\n\t{ color: pink;\nbackground: orange; }', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 2, - }, - { - code: 'a { color: pink;\nbackground: orange; }', - fixed: 'a\n { color: pink;\nbackground: orange; }', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 2, - }, - { - code: 'a { color: pink;\r\nbackground: orange; }', - fixed: 'a\r\n { color: pink;\r\nbackground: orange; }', - description: 'CRLF', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 2, - }, - { - code: '@media print\n{\na { color: pink;\nbackground: orange; } }', - fixed: '@media print\n{\na\n { color: pink;\nbackground: orange; } }', - message: messages.expectedBeforeMultiLine(), - line: 3, - column: 2, - }, - { - code: '@media print { a\n{ color: pink;\nbackground: orange; } }', - fixed: '@media print\n { a\n{ color: pink;\nbackground: orange; } }', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 13, - }, - { - code: '@media print { a\r\n{ color: pink;\r\nbackground: orange; } }', - fixed: '@media print\r\n { a\r\n{ color: pink;\r\nbackground: orange; } }', - description: 'CRLF', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 13, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - fix: true, - - accept: [ - { - code: 'a{ color: pink;\nbackground: orange; }', - }, - { - code: 'a{ color: pink;\r\nbackground: orange; }', - description: 'CRLF', - }, - { - code: '@media print{\na{ color: pink;\nbackground: orange } }', - }, - { - code: 'a { color: pink; }', - }, - { - code: '@media print { a { color: pink; } }', - }, - { - code: 'a{ color: pink; }', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a\t{ color: pink; }', - }, - ], - - reject: [ - { - code: 'a { color: pink;\nbackground: orange; }', - fixed: 'a{ color: pink;\nbackground: orange; }', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 2, - }, - { - code: 'a { color: pink;\r\nbackground: orange; }', - fixed: 'a{ color: pink;\r\nbackground: orange; }', - description: 'CRLF', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 2, - }, - { - code: 'a { color: pink;\nbackground: orange; }', - fixed: 'a{ color: pink;\nbackground: orange; }', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 3, - }, - { - code: 'a\t{ color: pink;\nbackground: orange; }', - fixed: 'a{ color: pink;\nbackground: orange; }', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 2, - }, - { - code: 'a\n{ color: pink;\nbackground: orange; }', - fixed: 'a{ color: pink;\nbackground: orange; }', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 2, - }, - { - code: '@media print\n{\na{ color: pink;\nbackground: orange; } }', - fixed: '@media print{\na{ color: pink;\nbackground: orange; } }', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 13, - }, - { - code: '@media print{ a\n{ color: pink;\nbackground: orange; } }', - fixed: '@media print{ a{ color: pink;\nbackground: orange; } }', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 16, - }, - { - code: '@media print{ a\r\n{ color: pink;\r\nbackground: orange; } }', - fixed: '@media print{ a{ color: pink;\r\nbackground: orange; } }', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 16, - }, - ], -}); diff --git a/lib/rules/block-opening-brace-newline-before/index.js b/lib/rules/block-opening-brace-newline-before/index.js deleted file mode 100644 index 1bc9aa8d4f..0000000000 --- a/lib/rules/block-opening-brace-newline-before/index.js +++ /dev/null @@ -1,120 +0,0 @@ -'use strict'; - -const beforeBlockString = require('../../utils/beforeBlockString'); -const blockString = require('../../utils/blockString'); -const hasBlock = require('../../utils/hasBlock'); -const hasEmptyBlock = require('../../utils/hasEmptyBlock'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'block-opening-brace-newline-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected newline before "{"', - expectedBeforeSingleLine: () => 'Expected newline before "{" of a single-line block', - rejectedBeforeSingleLine: () => 'Unexpected whitespace before "{" of a single-line block', - expectedBeforeMultiLine: () => 'Expected newline before "{" of a multi-line block', - rejectedBeforeMultiLine: () => 'Unexpected whitespace before "{" of a multi-line block', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/block-opening-brace-newline-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('newline', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: [ - 'always', - 'always-single-line', - 'never-single-line', - 'always-multi-line', - 'never-multi-line', - ], - }); - - if (!validOptions) { - return; - } - - // Check both kinds of statement: rules and at-rules - root.walkRules(check); - root.walkAtRules(check); - - /** - * @param {import('postcss').Rule | import('postcss').AtRule} statement - */ - function check(statement) { - // Return early if blockless or has an empty block - if (!hasBlock(statement) || hasEmptyBlock(statement)) { - return; - } - - const source = beforeBlockString(statement); - const beforeBraceNoRaw = beforeBlockString(statement, { - noRawBefore: true, - }); - - let index = beforeBraceNoRaw.length - 1; - - if (beforeBraceNoRaw[index - 1] === '\r') { - index -= 1; - } - - checker.beforeAllowingIndentation({ - lineCheckStr: blockString(statement), - source, - index: source.length, - err: (m) => { - if (context.fix) { - const statementRaws = statement.raws; - - if (typeof statementRaws.between !== 'string') return; - - if (primary.startsWith('always')) { - const spaceIndex = statementRaws.between.search(/\s+$/); - - if (spaceIndex >= 0) { - statement.raws.between = - statementRaws.between.slice(0, spaceIndex) + - context.newline + - statementRaws.between.slice(spaceIndex); - } else { - statementRaws.between += context.newline; - } - - return; - } - - if (primary.startsWith('never')) { - statementRaws.between = statementRaws.between.replace(/\s*$/, ''); - - return; - } - } - - report({ - message: m, - node: statement, - index, - result, - ruleName, - }); - }, - }); - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/block-opening-brace-space-after/README.md b/lib/rules/block-opening-brace-space-after/README.md deleted file mode 100644 index 946219f5a9..0000000000 --- a/lib/rules/block-opening-brace-space-after/README.md +++ /dev/null @@ -1,193 +0,0 @@ -# block-opening-brace-space-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace after the opening brace of blocks. - - -```css - a { color: pink; } -/** ↑ - * The space after this brace */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"|"always-single-line"|"never-single-line"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a single space after the opening brace. - -The following patterns are considered problems: - - -```css -a {color: pink; } -``` - - -```css -a { -color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { color: pink; -} -``` - -### `"never"` - -There _must never_ be whitespace after the opening brace. - -The following patterns are considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { -color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a {color: pink; } -``` - - -```css -a -{color: pink; } -``` - -### `"always-single-line"` - -There _must always_ be a single space after the opening brace in single-line blocks. - -The following patterns are considered problems: - - -```css -a {color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a {color: pink; -} -``` - -### `"never-single-line"` - -There _must never_ be whitespace after the opening brace in single-line blocks. - -The following patterns are considered problems: - - -```css -a { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a {color: pink; } -``` - - -```css -a { color: pink; -} -``` - -### `"always-multi-line"` - -There _must always_ be a single space after the opening brace in multi-line blocks. - -The following patterns are considered problems: - - -```css -a {color: pink; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a {color: pink; } -``` - - -```css -a { color: pink; -} -``` - -### `"never-multi-line"` - -There _must never_ be whitespace after the opening brace in multi-line blocks. - -The following patterns are considered problems: - - -```css -a { color: pink; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a {color: pink; -} -``` - -## Optional secondary options - -### `ignore: ["at-rules"]` - -Ignore the opening brace of at-rules. - -For example, with `"always"`: - -The following pattern is _not_ considered a problem: - - -```css -@media print { - a { color: pink; } -} -``` diff --git a/lib/rules/block-opening-brace-space-after/__tests__/index.js b/lib/rules/block-opening-brace-space-after/__tests__/index.js deleted file mode 100644 index 25b14243c9..0000000000 --- a/lib/rules/block-opening-brace-space-after/__tests__/index.js +++ /dev/null @@ -1,495 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: '@import url(x.css)', - }, - { - code: 'a { color: pink; }', - }, - { - code: '@media print { a { color: pink; } }', - }, - ], - - reject: [ - { - code: 'a {color: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedAfter(), - line: 1, - column: 4, - }, - { - code: 'a { color: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedAfter(), - line: 1, - column: 4, - }, - { - code: 'a {\tcolor: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedAfter(), - line: 1, - column: 4, - }, - { - code: 'a {\ncolor: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedAfter(), - line: 1, - column: 4, - }, - { - code: 'a {\r\ncolor: pink; }', - fixed: 'a { color: pink; }', - description: 'CRLF', - message: messages.expectedAfter(), - line: 1, - column: 4, - }, - { - code: '@media print {\na { color: pink; } }', - fixed: '@media print { a { color: pink; } }', - message: messages.expectedAfter(), - line: 1, - column: 15, - }, - { - code: '@media print { a {\ncolor: pink; } }', - fixed: '@media print { a { color: pink; } }', - message: messages.expectedAfter(), - line: 1, - column: 19, - }, - { - code: '@media print { a {\r\ncolor: pink; } }', - fixed: '@media print { a { color: pink; } }', - description: 'CRLF', - message: messages.expectedAfter(), - line: 1, - column: 19, - }, - { - code: 'a {/*comment*/ color: pink; }', - fixed: 'a { /*comment*/ color: pink; }', - message: messages.expectedAfter(), - line: 1, - column: 4, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a {color: pink; }', - }, - { - code: '@media print {a {color: pink; } }', - }, - ], - - reject: [ - { - code: 'a { color: pink; }', - fixed: 'a {color: pink; }', - message: messages.rejectedAfter(), - line: 1, - column: 4, - }, - { - code: 'a { color: pink; }', - fixed: 'a {color: pink; }', - message: messages.rejectedAfter(), - line: 1, - column: 4, - }, - { - code: 'a {\tcolor: pink; }', - fixed: 'a {color: pink; }', - message: messages.rejectedAfter(), - line: 1, - column: 4, - }, - { - code: 'a {\ncolor: pink; }', - fixed: 'a {color: pink; }', - message: messages.rejectedAfter(), - line: 1, - column: 4, - }, - { - code: 'a {\r\ncolor: pink; }', - fixed: 'a {color: pink; }', - description: 'CRLF', - message: messages.rejectedAfter(), - line: 1, - column: 4, - }, - { - code: '@media print {\na {color: pink; } }', - fixed: '@media print {a {color: pink; } }', - message: messages.rejectedAfter(), - line: 1, - column: 15, - }, - { - code: '@media print {a {\ncolor: pink; } }', - fixed: '@media print {a {color: pink; } }', - message: messages.rejectedAfter(), - line: 1, - column: 18, - }, - { - code: 'a { /*comment*/ color: pink; }', - fixed: 'a {/*comment*/ color: pink; }', - message: messages.rejectedAfter(), - line: 1, - column: 4, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: '@media print { a { color: pink; } }', - }, - { - code: 'a {\ncolor: pink; }', - }, - { - code: 'a {\r\ncolor: pink; }', - description: 'CRLF', - }, - { - code: 'a {color:\npink; }', - }, - { - code: '@media print {a {color:\npink; } }', - }, - { - code: '@media print{a {color:\npink; } }', - }, - ], - - reject: [ - { - code: 'a {color: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 4, - }, - { - code: 'a { color: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 4, - }, - { - code: 'a {\tcolor: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 4, - }, - { - code: '@media print {\ta { color: pink; } }', - fixed: '@media print { a { color: pink; } }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 15, - }, - { - code: '@media print { a {\tcolor: pink; } }', - fixed: '@media print { a { color: pink; } }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 19, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - fix: true, - - accept: [ - { - code: 'a {color: pink; }', - }, - { - code: '@media print {a {color: pink; } }', - }, - { - code: 'a { color:\npink; }', - }, - { - code: '@media print { a { color:\npink; } }', - }, - { - code: '@media print { a\n{color: pink; } }', - }, - { - code: '@media print { a\r\n{color: pink; } }', - description: 'CRLF', - }, - ], - - reject: [ - { - code: 'a { color: pink; }', - fixed: 'a {color: pink; }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 4, - }, - { - code: 'a { color: pink; }', - fixed: 'a {color: pink; }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 4, - }, - { - code: 'a {\tcolor: pink; }', - fixed: 'a {color: pink; }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 4, - }, - { - code: '@media print { a {color: pink; } }', - fixed: '@media print {a {color: pink; } }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 15, - }, - { - code: '@media print {a { color: pink; } }', - fixed: '@media print {a {color: pink; } }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 18, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink;\nbackground: orange; }', - }, - { - code: '@media print { a { color: pink;\nbackground: orange } }', - }, - { - code: 'a {color: pink; }', - }, - { - code: '@media print {a {color: pink; } }', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a {\tcolor: pink; }', - }, - ], - - reject: [ - { - code: 'a {color: pink;\nbackground: orange; }', - fixed: 'a { color: pink;\nbackground: orange; }', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a { color: pink;\nbackground: orange; }', - fixed: 'a { color: pink;\nbackground: orange; }', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a {\tcolor: pink;\nbackground: orange; }', - fixed: 'a { color: pink;\nbackground: orange; }', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a {\ncolor: pink;\nbackground: orange; }', - fixed: 'a { color: pink;\nbackground: orange; }', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a {\r\ncolor: pink;\r\nbackground: orange; }', - fixed: 'a { color: pink;\r\nbackground: orange; }', - description: 'CRLF', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: '@media print\n{a { color: pink;\nbackground: orange; } }', - fixed: '@media print\n{ a { color: pink;\nbackground: orange; } }', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 2, - }, - { - code: '@media print { a\n{color: pink;\nbackground: orange; } }', - fixed: '@media print { a\n{ color: pink;\nbackground: orange; } }', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - fix: true, - - accept: [ - { - code: 'a {color: pink;\nbackground: orange; }', - }, - { - code: '@media print {a\n{color: pink;\nbackground: orange } }', - }, - { - code: '@media print {a\r\n{color: pink;\r\nbackground: orange } }', - description: 'CRLF', - }, - { - code: 'a { color: pink; }', - }, - { - code: '@media print { a { color: pink; } }', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a {\tcolor: pink; }', - }, - ], - - reject: [ - { - code: 'a { color: pink;\nbackground: orange; }', - fixed: 'a {color: pink;\nbackground: orange; }', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a { color: pink;\nbackground: orange; }', - fixed: 'a {color: pink;\nbackground: orange; }', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a {\tcolor: pink;\nbackground: orange; }', - fixed: 'a {color: pink;\nbackground: orange; }', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a {\tcolor: pink;\r\nbackground: orange; }', - fixed: 'a {color: pink;\r\nbackground: orange; }', - description: 'CRLF', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: 'a {\ncolor: pink;\nbackground: orange; }', - fixed: 'a {color: pink;\nbackground: orange; }', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 4, - }, - { - code: '@media print\n{ a {color: pink;\nbackground: orange; } }', - fixed: '@media print\n{a {color: pink;\nbackground: orange; } }', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 2, - }, - { - code: '@media print{a\n{ color: pink;\nbackground: orange; } }', - fixed: '@media print{a\n{color: pink;\nbackground: orange; } }', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: ['always', { ignore: ['at-rules'] }], - fix: true, - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: '@media print { a { color: pink; } }', - }, - { - code: '@media print {\na { color: pink; } }', - }, - ], - reject: [ - { - code: '@media print {\n a {color: pink; } }', - fixed: '@media print {\n a { color: pink; } }', - message: messages.expectedAfter(), - line: 2, - column: 6, - }, - ], -}); diff --git a/lib/rules/block-opening-brace-space-after/index.js b/lib/rules/block-opening-brace-space-after/index.js deleted file mode 100644 index 02fc149ead..0000000000 --- a/lib/rules/block-opening-brace-space-after/index.js +++ /dev/null @@ -1,116 +0,0 @@ -'use strict'; - -const beforeBlockString = require('../../utils/beforeBlockString'); -const blockString = require('../../utils/blockString'); -const hasBlock = require('../../utils/hasBlock'); -const hasEmptyBlock = require('../../utils/hasEmptyBlock'); -const optionsMatches = require('../../utils/optionsMatches'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'block-opening-brace-space-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected single space after "{"', - rejectedAfter: () => 'Unexpected whitespace after "{"', - expectedAfterSingleLine: () => 'Expected single space after "{" of a single-line block', - rejectedAfterSingleLine: () => 'Unexpected whitespace after "{" of a single-line block', - expectedAfterMultiLine: () => 'Expected single space after "{" of a multi-line block', - rejectedAfterMultiLine: () => 'Unexpected whitespace after "{" of a multi-line block', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/block-opening-brace-space-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions( - result, - ruleName, - { - actual: primary, - possible: [ - 'always', - 'never', - 'always-single-line', - 'never-single-line', - 'always-multi-line', - 'never-multi-line', - ], - }, - { - actual: secondaryOptions, - possible: { - ignore: ['at-rules'], - }, - optional: true, - }, - ); - - if (!validOptions) { - return; - } - - // Check both kinds of statements: rules and at-rules - root.walkRules(check); - - if (!optionsMatches(secondaryOptions, 'ignore', 'at-rules')) { - root.walkAtRules(check); - } - - /** - * @param {import('postcss').Rule | import('postcss').AtRule} statement - */ - function check(statement) { - // Return early if blockless or has an empty block - if (!hasBlock(statement) || hasEmptyBlock(statement)) { - return; - } - - checker.after({ - source: blockString(statement), - index: 0, - err: (m) => { - if (context.fix) { - const statementFirst = statement.first; - - if (statementFirst == null) return; - - if (primary.startsWith('always')) { - statementFirst.raws.before = ' '; - - return; - } - - if (primary.startsWith('never')) { - statementFirst.raws.before = ''; - - return; - } - } - - report({ - message: m, - node: statement, - index: beforeBlockString(statement, { noRawBefore: true }).length + 1, - result, - ruleName, - }); - }, - }); - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/block-opening-brace-space-before/README.md b/lib/rules/block-opening-brace-space-before/README.md deleted file mode 100644 index 82bccdc1a1..0000000000 --- a/lib/rules/block-opening-brace-space-before/README.md +++ /dev/null @@ -1,220 +0,0 @@ -# block-opening-brace-space-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace before the opening brace of blocks. - - -```css - a { color: pink; } -/** ↑ - * The space before this brace */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"|"always-single-line"|"never-single-line"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a single space before the opening brace. - -The following patterns are considered problems: - - -```css -a{ color: pink; } -``` - - -```css -a -{ color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { -color: pink; } -``` - -### `"never"` - -There _must never_ be whitespace before the opening brace. - -The following patterns are considered problems: - - -```css -a { color: pink; } -``` - - -```css -a -{ color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a{ color: pink; } -``` - - -```css -a{ -color: pink; } -``` - -### `"always-single-line"` - -There _must always_ be a single space before the opening brace in single-line blocks. - -The following patterns are considered problems: - - -```css -a{ color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a{ -color: pink; } -``` - -### `"never-single-line"` - -There _must never_ be whitespace before the opening brace in single-line blocks. - -The following patterns are considered problems: - - -```css -a { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a{ color: pink; } -``` - - -```css -a { -color: pink; } -``` - -### `"always-multi-line"` - -There _must always_ be a single space before the opening brace in multi-line blocks. - -The following patterns are considered problems: - - -```css -a{ -color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a{ color: pink; } -``` - - -```css -a { -color: pink; } -``` - -### `"never-multi-line"` - -There _must never_ be whitespace before the opening brace in multi-line blocks. - -The following patterns are considered problems: - - -```css -a { -color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a{ -color: pink;} -``` - -## Optional secondary options - -### `ignoreAtRules: ["/regex/", /regex/, "non-regex"]` - -Given: - -```json -["/for/i"] -``` - -The following patterns are _not_ considered problems: - - -```css -@for ... -{} -``` - - -```css -@for ...{} -``` - -### `ignoreSelectors: ["/regex/", /regex/, "non-regex"]` - -Given: - -```json -[":root"] -``` - -The following patterns are _not_ considered problems: - - -```css -:root -{} -``` - - -```css -:root{} -``` diff --git a/lib/rules/block-opening-brace-space-before/__tests__/index.js b/lib/rules/block-opening-brace-space-before/__tests__/index.js deleted file mode 100644 index df07c7621b..0000000000 --- a/lib/rules/block-opening-brace-space-before/__tests__/index.js +++ /dev/null @@ -1,552 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: '@import url(x.css)', - }, - { - code: 'a { color: pink; }', - }, - { - code: '@media print { a { color: pink; } }', - }, - { - code: 'a {{ &:hover { color: pink; }}}', - }, - { - code: 'a {\n&:hover { color: pink; }}', - }, - ], - - reject: [ - { - code: 'a{ color: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedBefore(), - line: 1, - column: 1, - }, - { - code: 'a { color: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedBefore(), - line: 1, - column: 3, - }, - { - code: 'a\t{ color: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedBefore(), - line: 1, - column: 2, - }, - { - code: 'a\n{ color: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedBefore(), - line: 1, - column: 2, - }, - { - code: 'a\r\n{ color: pink; }', - fixed: 'a { color: pink; }', - description: 'CRLF', - message: messages.expectedBefore(), - line: 1, - column: 2, - }, - { - code: '@media print\n{ a { color: pink; } }', - fixed: '@media print { a { color: pink; } }', - message: messages.expectedBefore(), - line: 1, - column: 13, - }, - { - code: '@media print { a\n{ color: pink; } }', - fixed: '@media print { a { color: pink; } }', - message: messages.expectedBefore(), - line: 1, - column: 17, - }, - ], -}); - -testRule({ - ruleName, - config: ['always', { ignoreAtRules: ['for', '/for/i', /for/i] }], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: '@for ...\n{ color: pink; }', - }, - { - code: '@for ...\r\n{ color: pink; }', - }, - ], - - reject: [ - { - code: 'a{ color: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedBefore(), - line: 1, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: ['always', { ignoreSelectors: ['a', '/a/', /a/] }], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a{ color: pink; }', - }, - { - code: 'a\n{ color: pink; }', - }, - { - code: 'a\r\n{ color: pink; }', - }, - ], - - reject: [ - { - code: 'b{ color: pink; }', - fixed: 'b { color: pink; }', - message: messages.expectedBefore(), - line: 1, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a{ color: pink; }', - }, - { - code: '@media print{ a{ color: pink; } }', - }, - ], - - reject: [ - { - code: 'a { color: pink; }', - fixed: 'a{ color: pink; }', - message: messages.rejectedBefore(), - line: 1, - column: 2, - }, - { - code: 'a { color: pink; }', - fixed: 'a{ color: pink; }', - message: messages.rejectedBefore(), - line: 1, - column: 3, - }, - { - code: 'a\t{ color: pink; }', - fixed: 'a{ color: pink; }', - message: messages.rejectedBefore(), - line: 1, - column: 2, - }, - { - code: 'a\n{ color: pink; }', - fixed: 'a{ color: pink; }', - message: messages.rejectedBefore(), - line: 1, - column: 2, - }, - { - code: 'a\r\n{ color: pink; }', - fixed: 'a{ color: pink; }', - description: 'CRLF', - message: messages.rejectedBefore(), - line: 1, - column: 2, - }, - { - code: '@media print { a{ color: pink; } }', - fixed: '@media print{ a{ color: pink; } }', - message: messages.rejectedBefore(), - line: 1, - column: 13, - }, - { - code: '@media print{ a { color: pink; } }', - fixed: '@media print{ a{ color: pink; } }', - message: messages.rejectedBefore(), - line: 1, - column: 16, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: '@media print { a { color: pink; } }', - }, - { - code: 'a{ color:\npink; }', - }, - { - code: '@media print { a{ color:\npink; } }', - }, - { - code: '@media print{ a { color:\npink; } }', - }, - { - code: '@media print{\na { color: pink; } }', - }, - ], - - reject: [ - { - code: 'a{ color: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 1, - }, - { - code: 'a { color: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 3, - }, - { - code: 'a\t{ color: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 2, - }, - { - code: 'a\n{ color: pink; }', - fixed: 'a { color: pink; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 2, - }, - { - code: 'a\r\n{ color: pink; }', - fixed: 'a { color: pink; }', - description: 'CRLF', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 2, - }, - { - code: '@media print\n{ a { color: pink; } }', - fixed: '@media print { a { color: pink; } }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 13, - }, - { - code: '@media print { a\n{ color: pink; } }', - fixed: '@media print { a { color: pink; } }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 17, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - fix: true, - - accept: [ - { - code: 'a{ color: pink; }', - }, - { - code: '@media print{ a{ color: pink; } }', - }, - { - code: 'a { color:\npink; }', - }, - { - code: 'a { color:\r\npink; }', - description: 'CRLF', - }, - { - code: '@media print { a { color:\npink; } }', - }, - { - code: '@media print{ a{ color:\npink; } }', - }, - { - code: '@media print {\na{ color: pink; } }', - }, - { - code: '@media print{\na{ color: pink; } }', - }, - { - code: '@media print{\r\na{ color: pink; } }', - description: 'CRLF', - }, - ], - - reject: [ - { - code: 'a { color: pink; }', - fixed: 'a{ color: pink; }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 2, - }, - { - code: 'a { color: pink; }', - fixed: 'a{ color: pink; }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 3, - }, - { - code: 'a\t{ color: pink; }', - fixed: 'a{ color: pink; }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 2, - }, - { - code: 'a\n{ color: pink; }', - fixed: 'a{ color: pink; }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 2, - }, - { - code: 'a\r\n{ color: pink; }', - fixed: 'a{ color: pink; }', - description: 'CRLF', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 2, - }, - { - code: '@media print { a{ color: pink; } }', - fixed: '@media print{ a{ color: pink; } }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 13, - }, - { - code: '@media print{ a { color: pink; } }', - fixed: '@media print{ a{ color: pink; } }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 16, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink;\nbackground: orange; }', - }, - { - code: '@media print {\na { color: pink;\nbackground: orange } }', - }, - { - code: '@media print {\r\na { color: pink;\r\nbackground: orange } }', - description: 'CRLF', - }, - { - code: 'a { color: pink; }', - }, - { - code: '@media print { a { color: pink; } }', - }, - { - code: 'a{ color: pink; }', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a\t{ color: pink; }', - }, - ], - - reject: [ - { - code: 'a{ color: pink;\nbackground: orange; }', - fixed: 'a { color: pink;\nbackground: orange; }', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 1, - }, - { - code: 'a { color: pink;\nbackground: orange; }', - fixed: 'a { color: pink;\nbackground: orange; }', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 3, - }, - { - code: 'a\t{ color: pink;\nbackground: orange; }', - fixed: 'a { color: pink;\nbackground: orange; }', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 2, - }, - { - code: 'a\n{ color: pink;\nbackground: orange; }', - fixed: 'a { color: pink;\nbackground: orange; }', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 2, - }, - { - code: 'a\r\n{ color: pink;\r\nbackground: orange; }', - fixed: 'a { color: pink;\r\nbackground: orange; }', - description: 'CRLF', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 2, - }, - { - code: '@media print\n{\na { color: pink;\nbackground: orange; } }', - fixed: '@media print {\na { color: pink;\nbackground: orange; } }', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 13, - }, - { - code: '@media print { a\n{ color: pink;\nbackground: orange; } }', - fixed: '@media print { a { color: pink;\nbackground: orange; } }', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 17, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - fix: true, - - accept: [ - { - code: 'a{ color: pink;\nbackground: orange; }', - }, - { - code: '@media print{\na{ color: pink;\nbackground: orange } }', - }, - { - code: '@media print{\r\na{ color: pink;\r\nbackground: orange } }', - description: 'CRLF', - }, - { - code: 'a { color: pink; }', - }, - { - code: '@media print { a { color: pink; } }', - }, - { - code: 'a{ color: pink; }', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a\t{ color: pink; }', - }, - ], - - reject: [ - { - code: 'a { color: pink;\nbackground: orange; }', - fixed: 'a{ color: pink;\nbackground: orange; }', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 2, - }, - { - code: 'a { color: pink;\nbackground: orange; }', - fixed: 'a{ color: pink;\nbackground: orange; }', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 3, - }, - { - code: 'a\t{ color: pink;\nbackground: orange; }', - fixed: 'a{ color: pink;\nbackground: orange; }', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 2, - }, - { - code: 'a\n{ color: pink;\nbackground: orange; }', - fixed: 'a{ color: pink;\nbackground: orange; }', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 2, - }, - { - code: '@media print\n{\na{ color: pink;\nbackground: orange; } }', - fixed: '@media print{\na{ color: pink;\nbackground: orange; } }', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 13, - }, - { - code: '@media print{ a\n{ color: pink;\nbackground: orange; } }', - fixed: '@media print{ a{ color: pink;\nbackground: orange; } }', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 16, - }, - { - code: '@media print{ a\r\n{ color: pink;\r\nbackground: orange; } }', - fixed: '@media print{ a{ color: pink;\r\nbackground: orange; } }', - description: 'CRLF', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 16, - }, - ], -}); diff --git a/lib/rules/block-opening-brace-space-before/index.js b/lib/rules/block-opening-brace-space-before/index.js deleted file mode 100644 index fcde4e48d0..0000000000 --- a/lib/rules/block-opening-brace-space-before/index.js +++ /dev/null @@ -1,139 +0,0 @@ -'use strict'; - -const beforeBlockString = require('../../utils/beforeBlockString'); -const blockString = require('../../utils/blockString'); -const hasBlock = require('../../utils/hasBlock'); -const hasEmptyBlock = require('../../utils/hasEmptyBlock'); -const optionsMatches = require('../../utils/optionsMatches'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); -const { isRegExp, isString } = require('../../utils/validateTypes'); - -const ruleName = 'block-opening-brace-space-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected single space before "{"', - rejectedBefore: () => 'Unexpected whitespace before "{"', - expectedBeforeSingleLine: () => 'Expected single space before "{" of a single-line block', - rejectedBeforeSingleLine: () => 'Unexpected whitespace before "{" of a single-line block', - expectedBeforeMultiLine: () => 'Expected single space before "{" of a multi-line block', - rejectedBeforeMultiLine: () => 'Unexpected whitespace before "{" of a multi-line block', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/block-opening-brace-space-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions( - result, - ruleName, - { - actual: primary, - possible: [ - 'always', - 'never', - 'always-single-line', - 'never-single-line', - 'always-multi-line', - 'never-multi-line', - ], - }, - { - actual: secondaryOptions, - possible: { - ignoreAtRules: [isString, isRegExp], - ignoreSelectors: [isString, isRegExp], - }, - optional: true, - }, - ); - - if (!validOptions) { - return; - } - - // Check both kinds of statements: rules and at-rules - root.walkRules(check); - root.walkAtRules(check); - - /** - * @param {import('postcss').Rule | import('postcss').AtRule} statement - */ - function check(statement) { - // Return early if blockless or has an empty block - if (!hasBlock(statement) || hasEmptyBlock(statement)) { - return; - } - - // Return early if at-rule is to be ignored - if ( - statement.type === 'atrule' && - optionsMatches(secondaryOptions, 'ignoreAtRules', statement.name) - ) { - return; - } - - // Return early if selector is to be ignored - if ( - statement.type === 'rule' && - optionsMatches(secondaryOptions, 'ignoreSelectors', statement.selector) - ) { - return; - } - - const source = beforeBlockString(statement); - const beforeBraceNoRaw = beforeBlockString(statement, { - noRawBefore: true, - }); - - let index = beforeBraceNoRaw.length - 1; - - if (beforeBraceNoRaw[index - 1] === '\r') { - index -= 1; - } - - checker.before({ - source, - index: source.length, - lineCheckStr: blockString(statement), - err: (m) => { - if (context.fix) { - if (primary.startsWith('always')) { - statement.raws.between = ' '; - - return; - } - - if (primary.startsWith('never')) { - statement.raws.between = ''; - - return; - } - } - - report({ - message: m, - node: statement, - index, - result, - ruleName, - }); - }, - }); - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/color-hex-case/README.md b/lib/rules/color-hex-case/README.md deleted file mode 100644 index 27fc375baf..0000000000 --- a/lib/rules/color-hex-case/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# color-hex-case - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Specify lowercase or uppercase for hex colors. - - -```css -a { color: #fff } -/** ↑ - * This hex color */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"lower"|"upper"` - -### `"lower"` - -The following patterns are considered problems: - - -```css -a { color: #FFF; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: #000; } -``` - - -```css -a { color: #fff; } -``` - -### `"upper"` - -The following patterns are considered problems: - - -```css -a { color: #fff; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: #000; } -``` - - -```css -a { color: #FFF; } -``` diff --git a/lib/rules/color-hex-case/__tests__/index.js b/lib/rules/color-hex-case/__tests__/index.js deleted file mode 100644 index af5572a3f8..0000000000 --- a/lib/rules/color-hex-case/__tests__/index.js +++ /dev/null @@ -1,166 +0,0 @@ -'use strict'; - -const mergeTestDescriptions = require('../../../testUtils/mergeTestDescriptions'); - -const { messages, ruleName } = require('..'); - -const sharedTests = { - accept: [ - { - code: 'a { border-#$side: 0; }', - description: 'ignore sass-like interpolation', - }, - { - code: 'a { box-sizing: #$type-box; }', - description: 'ignore sass-like interpolation', - }, - { - code: 'a { stroke: url(#gradientA) }', - description: 'SVG reference interaction', - }, - ], -}; - -testRule( - mergeTestDescriptions(sharedTests, { - ruleName, - config: ['lower'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: #000; }', - }, - { - code: 'a { something: #000, #fff, #ababab; }', - }, - { - code: 'a { color: #0000ffcc; }', - description: 'eight digits', - }, - { - code: 'a { color: #00fc; }', - description: 'four digits', - }, - { - code: 'a { padding: 000; }', - }, - { - code: 'a::before { content: "#ABABA"; }', - }, - { - code: 'a { color: white /* #FFF */; }', - }, - ], - - reject: [ - { - code: 'a { color: #Ababa; }', - fixed: 'a { color: #ababa; }', - - message: messages.expected('#Ababa', '#ababa'), - line: 1, - column: 12, - }, - { - code: 'a { something: #000F, #fff, #ababab; }', - fixed: 'a { something: #000f, #fff, #ababab; }', - - message: messages.expected('#000F', '#000f'), - line: 1, - column: 16, - }, - { - code: 'a { something: #000, #FFFFAZ, #ababab; }', - fixed: 'a { something: #000, #ffffaz, #ababab; }', - - message: messages.expected('#FFFFAZ', '#ffffaz'), - line: 1, - column: 22, - }, - { - code: 'a { something: #000, #fff, #12345AA; }', - fixed: 'a { something: #000, #fff, #12345aa; }', - - message: messages.expected('#12345AA', '#12345aa'), - line: 1, - column: 28, - }, - ], - }), -); - -testRule( - mergeTestDescriptions(sharedTests, { - ruleName, - config: ['upper'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: #000; }', - }, - { - code: 'a { something: #000, #FFF, #ABABAB; }', - }, - { - code: 'a { color: #0000FFCC; }', - description: 'eight digits', - }, - { - code: 'a { color: #00FC; }', - description: 'four digits', - }, - { - code: 'a { padding: 000; }', - }, - { - code: 'a::before { content: "#ababa"; }', - }, - { - code: 'a { color: white /* #fff */; }', - }, - ], - - reject: [ - { - code: 'a { color: #aBABA; }', - fixed: 'a { color: #ABABA; }', - - message: messages.expected('#aBABA', '#ABABA'), - line: 1, - column: 12, - }, - { - code: 'a { something: #000f, #FFF, #ABABAB; }', - fixed: 'a { something: #000F, #FFF, #ABABAB; }', - - message: messages.expected('#000f', '#000F'), - line: 1, - column: 16, - }, - { - code: 'a { something: #000, #ffffaz, #ABABAB; }', - fixed: 'a { something: #000, #FFFFAZ, #ABABAB; }', - - message: messages.expected('#ffffaz', '#FFFFAZ'), - line: 1, - column: 22, - }, - { - code: 'a { something: #000, #FFF, #12345aa; }', - fixed: 'a { something: #000, #FFF, #12345AA; }', - - message: messages.expected('#12345aa', '#12345AA'), - line: 1, - column: 28, - }, - ], - }), -); diff --git a/lib/rules/color-hex-case/index.js b/lib/rules/color-hex-case/index.js deleted file mode 100644 index 662a14f18c..0000000000 --- a/lib/rules/color-hex-case/index.js +++ /dev/null @@ -1,97 +0,0 @@ -'use strict'; - -const valueParser = require('postcss-value-parser'); - -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const getDeclarationValue = require('../../utils/getDeclarationValue'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const setDeclarationValue = require('../../utils/setDeclarationValue'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'color-hex-case'; - -const messages = ruleMessages(ruleName, { - expected: (actual, expected) => `Expected "${actual}" to be "${expected}"`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/color-hex-case', - fixable: true, - deprecated: true, -}; - -const HEX = /^#[\da-z]+/i; -const CONTAINS_HEX = /#[\da-z]+/i; -const IGNORED_FUNCTIONS = new Set(['url']); - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['lower', 'upper'], - }); - - if (!validOptions) { - return; - } - - root.walkDecls((decl) => { - if (!CONTAINS_HEX.test(decl.value)) return; - - const parsedValue = valueParser(getDeclarationValue(decl)); - let needsFix = false; - - parsedValue.walk((node) => { - const { value } = node; - - if (isIgnoredFunction(node)) return false; - - if (!isHexColor(node)) return; - - const expected = primary === 'lower' ? value.toLowerCase() : value.toUpperCase(); - - if (value === expected) return; - - if (context.fix) { - node.value = expected; - needsFix = true; - - return; - } - - report({ - message: messages.expected(value, expected), - node: decl, - index: declarationValueIndex(decl) + node.sourceIndex, - result, - ruleName, - }); - }); - - if (needsFix) { - setDeclarationValue(decl, parsedValue.toString()); - } - }); - }; -}; - -/** - * @param {import('postcss-value-parser').Node} node - */ -function isIgnoredFunction({ type, value }) { - return type === 'function' && IGNORED_FUNCTIONS.has(value.toLowerCase()); -} - -/** - * @param {import('postcss-value-parser').Node} node - */ -function isHexColor({ type, value }) { - return type === 'word' && HEX.test(value); -} - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/comment-empty-line-before/README.md b/lib/rules/comment-empty-line-before/README.md index 6cc7b69a80..726cd460dd 100644 --- a/lib/rules/comment-empty-line-before/README.md +++ b/lib/rules/comment-empty-line-before/README.md @@ -18,7 +18,7 @@ This rule ignores: - single-line comments with `//` (when you're using a custom syntax that supports them) - comments within selector and value lists -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. We recommend to enable [`indentation`](../indentation/README.md) rule for better autofixing results with this rule. +The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. ## Options diff --git a/lib/rules/custom-property-empty-line-before/README.md b/lib/rules/custom-property-empty-line-before/README.md index 127fbc2227..d608226430 100644 --- a/lib/rules/custom-property-empty-line-before/README.md +++ b/lib/rules/custom-property-empty-line-before/README.md @@ -13,7 +13,7 @@ a { * This line */ ``` -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. We recommend to enable [`indentation`](../indentation/README.md) rule for better autofixing results with this rule. +The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. ## Options diff --git a/lib/rules/declaration-bang-space-after/README.md b/lib/rules/declaration-bang-space-after/README.md deleted file mode 100644 index 599c731a47..0000000000 --- a/lib/rules/declaration-bang-space-after/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# declaration-bang-space-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace after the bang of declarations. - - -```css -a { color: pink !important; } -/** ↑ - * The space after this exclamation mark */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a single space after the bang. - -The following patterns are considered problems: - - -```css -a { color: pink !important; } -``` - - -```css -a { color: pink !important; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink ! important; } -``` - - -```css -a { color: pink! important; } -``` - -### `"never"` - -There _must never_ be whitespace after the bang. - -The following patterns are considered problems: - - -```css -a { color: pink ! important; } -``` - - -```css -a { color: pink! important; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink !important; } -``` - - -```css -a { color:pink!important; } -``` diff --git a/lib/rules/declaration-bang-space-after/__tests__/index.js b/lib/rules/declaration-bang-space-after/__tests__/index.js deleted file mode 100644 index 0ead24fa07..0000000000 --- a/lib/rules/declaration-bang-space-after/__tests__/index.js +++ /dev/null @@ -1,163 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - description: 'no !important', - }, - { - code: 'a { color: pink! important; }', - description: 'space only after', - }, - { - code: 'a { color: pink ! default; }', - description: 'space before and after', - }, - { - code: 'a { color: pink\n! important; }', - description: 'newline before and space after', - }, - { - code: 'a { color: pink\r\n! optional; }', - description: 'CRLF before and space after', - }, - { - code: 'a::before { content: "!!!" ! important; }', - description: 'ignores string', - }, - { - code: 'a { color: pink /* !important */;}', - description: 'violating comment', - }, - ], - - reject: [ - { - code: 'a { color: pink!important; }', - fixed: 'a { color: pink! important; }', - description: 'no space after', - message: messages.expectedAfter(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink! global; }', - fixed: 'a { color: pink! global; }', - description: 'two spaces after', - message: messages.expectedAfter(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink!\nimportant; }', - fixed: 'a { color: pink! important; }', - description: 'newline after', - message: messages.expectedAfter(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink!\r\nexciting; }', - fixed: 'a { color: pink! exciting; }', - description: 'CRLF after', - message: messages.expectedAfter(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink !/*comment*/important; }', - fixed: 'a { color: pink ! /*comment*/important; }', - description: 'comment after', - message: messages.expectedAfter(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink !/*comment*/global; }', - fixed: 'a { color: pink ! /*comment*/global; }', - description: 'comment after', - message: messages.expectedAfter(), - line: 1, - column: 17, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - description: 'no !important', - }, - { - code: 'a { color: pink!important; }', - description: 'no space before or after', - }, - { - code: 'a { color: pink !important; }', - description: 'space before and none after', - }, - { - code: 'a { color: pink\n!important; }', - description: 'newline before and none after', - }, - { - code: 'a { color: pink\r\n!important; }', - description: 'CRLF before and none after', - }, - ], - - reject: [ - { - code: 'a { color: pink! important; }', - fixed: 'a { color: pink!important; }', - description: 'space after', - message: messages.rejectedAfter(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink!\nimportant; }', - fixed: 'a { color: pink!important; }', - description: 'newline after', - message: messages.rejectedAfter(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink!\r\nimportant; }', - fixed: 'a { color: pink!important; }', - description: 'CRLF after', - message: messages.rejectedAfter(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink ! /*comment*/important; }', - fixed: 'a { color: pink !/*comment*/important; }', - description: 'comment after', - message: messages.rejectedAfter(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink ! /*comment*/global; }', - fixed: 'a { color: pink !/*comment*/global; }', - description: 'comment after', - message: messages.rejectedAfter(), - line: 1, - column: 17, - }, - ], -}); diff --git a/lib/rules/declaration-bang-space-after/index.js b/lib/rules/declaration-bang-space-after/index.js deleted file mode 100644 index 6ce8334333..0000000000 --- a/lib/rules/declaration-bang-space-after/index.js +++ /dev/null @@ -1,91 +0,0 @@ -'use strict'; - -const declarationBangSpaceChecker = require('../declarationBangSpaceChecker'); -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const getDeclarationValue = require('../../utils/getDeclarationValue'); -const ruleMessages = require('../../utils/ruleMessages'); -const setDeclarationValue = require('../../utils/setDeclarationValue'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'declaration-bang-space-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected single space after "!"', - rejectedAfter: () => 'Unexpected whitespace after "!"', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/declaration-bang-space-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - declarationBangSpaceChecker({ - root, - result, - locationChecker: checker.after, - checkedRuleName: ruleName, - fix: context.fix - ? (decl, index) => { - let bangIndex = index - declarationValueIndex(decl); - const declValue = getDeclarationValue(decl); - let target; - /** @type {(value: string) => void} */ - let setFixed; - - if (bangIndex < declValue.length) { - target = declValue; - setFixed = (value) => { - setDeclarationValue(decl, value); - }; - } else if (decl.important) { - target = decl.raws.important || ' !important'; - bangIndex -= declValue.length; - setFixed = (value) => { - decl.raws.important = value; - }; - } else { - return false; // not standard - } - - const targetBefore = target.slice(0, bangIndex + 1); - const targetAfter = target.slice(bangIndex + 1); - - if (primary === 'always') { - setFixed(targetBefore + targetAfter.replace(/^\s*/, ' ')); - - return true; - } - - if (primary === 'never') { - setFixed(targetBefore + targetAfter.replace(/^\s*/, '')); - - return true; - } - - return false; - } - : null, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/declaration-bang-space-before/README.md b/lib/rules/declaration-bang-space-before/README.md deleted file mode 100644 index 6947bff328..0000000000 --- a/lib/rules/declaration-bang-space-before/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# declaration-bang-space-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace before the bang of declarations. - - -```css -a { color: pink !important; } -/** ↑ - * The space before this exclamation mark */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a single space before the bang. - -The following patterns are considered problems: - - -```css -a { color: pink!important; } -``` - - -```css -a { color: pink ! important; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink !important; } -``` - - -```css -a { color:pink ! important; } -``` - -### `"never"` - -There _must never_ be whitespace before the bang. - -The following patterns are considered problems: - - -```css -a { color : pink !important; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink!important; } -``` - - -```css -a { color: pink! important; } -``` diff --git a/lib/rules/declaration-bang-space-before/__tests__/index.js b/lib/rules/declaration-bang-space-before/__tests__/index.js deleted file mode 100644 index f98458d60e..0000000000 --- a/lib/rules/declaration-bang-space-before/__tests__/index.js +++ /dev/null @@ -1,229 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - description: 'no !important', - }, - { - code: 'a { color: pink !important; }', - description: 'space only before', - }, - { - code: 'a { color: pink ! important; }', - description: 'space before and after', - }, - { - code: 'a { color: pink !\noptional; }', - description: 'space before and newline after', - }, - { - code: 'a { color: pink !\r\nimportant; }', - description: 'space before and CRLF after', - }, - { - code: 'a::before { content: "!!!" !default; }', - description: 'ignores string', - }, - { - code: 'a { color: pink/*!important */;}', - description: 'violating comment', - }, - ], - - reject: [ - { - code: 'a { color: pink !important; }', - fixed: 'a { color: pink !important; }', - description: 'two spaces before', - message: messages.expectedBefore(), - line: 1, - column: 18, - }, - { - code: 'a { color: pink!default; }', - fixed: 'a { color: pink !default; }', - description: 'no space before', - message: messages.expectedBefore(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink\n!important; }', - fixed: 'a { color: pink !important; }', - description: 'newline before', - message: messages.expectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a { color: pink\r\n!something; }', - fixed: 'a { color: pink !something; }', - description: 'CRLF before', - message: messages.expectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a { color: pink/*comment*/!important; }', - fixed: 'a { color: pink/*comment*/ !important; }', - description: 'comment before', - message: messages.expectedBefore(), - line: 1, - column: 27, - }, - { - code: 'a { color: pink/*comment*/!something; }', - fixed: 'a { color: pink/*comment*/ !something; }', - description: 'comment before', - message: messages.expectedBefore(), - line: 1, - column: 27, - }, - { - code: 'a { color: pink\n/*comment*/!important; }', - fixed: 'a { color: pink\n/*comment*/ !important; }', - description: 'comment before', - message: messages.expectedBefore(), - line: 2, - column: 12, - }, - { - code: 'a { color: pink\n/*comment*/!something; }', - fixed: 'a { color: pink\n/*comment*/ !something; }', - description: 'comment before', - message: messages.expectedBefore(), - line: 2, - column: 12, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - description: 'no !important', - }, - { - code: 'a { color: pink!important; }', - description: 'no spaces', - }, - { - code: 'a { color: pink! important; }', - description: 'no space before and after', - }, - { - code: 'a { color: pink!\nimportant; }', - description: 'no space before and newline after', - }, - { - code: 'a { color: pink!\r\nimportant; }', - description: 'no space before and CRLF after', - }, - ], - - reject: [ - { - code: 'a { color: pink !important; }', - fixed: 'a { color: pink!important; }', - description: 'space before', - message: messages.rejectedBefore(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink\n!important; }', - fixed: 'a { color: pink!important; }', - description: 'newline before', - message: messages.rejectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a { color: pink\r\n!important; }', - fixed: 'a { color: pink!important; }', - description: 'CRLF before', - message: messages.rejectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a { color: pink/*comment*/ !important; }', - fixed: 'a { color: pink/*comment*/!important; }', - description: 'comment before', - message: messages.rejectedBefore(), - line: 1, - column: 28, - }, - { - code: 'a { color: pink/*comment*/ !something; }', - fixed: 'a { color: pink/*comment*/!something; }', - description: 'comment before', - message: messages.rejectedBefore(), - line: 1, - column: 28, - }, - { - code: 'a { color: pink\n/*comment*/\n!important; }', - fixed: 'a { color: pink\n/*comment*/!important; }', - description: 'comment before', - message: messages.rejectedBefore(), - line: 3, - column: 1, - }, - { - code: 'a { color: pink\n/*comment*/\n!something; }', - fixed: 'a { color: pink\n/*comment*/!something; }', - description: 'comment before', - message: messages.rejectedBefore(), - line: 3, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: ['always'], - customSyntax: 'postcss-sass', - fix: true, - - reject: [ - { - code: '$color: pink!default', - fixed: '$color: pink !default', - message: messages.expectedBefore(), - line: 1, - column: 13, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - customSyntax: 'postcss-sass', - fix: true, - - reject: [ - { - code: '$color: pink !default', - fixed: '$color: pink!default', - message: messages.rejectedBefore(), - line: 1, - column: 14, - }, - ], -}); diff --git a/lib/rules/declaration-bang-space-before/index.js b/lib/rules/declaration-bang-space-before/index.js deleted file mode 100644 index 3d6216f485..0000000000 --- a/lib/rules/declaration-bang-space-before/index.js +++ /dev/null @@ -1,92 +0,0 @@ -'use strict'; - -const declarationBangSpaceChecker = require('../declarationBangSpaceChecker'); -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const getDeclarationValue = require('../../utils/getDeclarationValue'); -const ruleMessages = require('../../utils/ruleMessages'); -const setDeclarationValue = require('../../utils/setDeclarationValue'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'declaration-bang-space-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected single space before "!"', - rejectedBefore: () => 'Unexpected whitespace before "!"', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/declaration-bang-space-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - declarationBangSpaceChecker({ - root, - result, - locationChecker: checker.before, - checkedRuleName: ruleName, - fix: context.fix - ? (decl, index) => { - let bangIndex = index - declarationValueIndex(decl); - const value = getDeclarationValue(decl); - let target; - /** @type {(val: string) => void} */ - let setFixed; - - if (bangIndex < value.length) { - target = value; - setFixed = (val) => { - setDeclarationValue(decl, val); - }; - } else if (decl.important) { - target = decl.raws.important || ' !important'; - bangIndex -= value.length; - setFixed = (val) => { - decl.raws.important = val; - }; - } else { - return false; // not standard - } - - const targetBefore = target.slice(0, bangIndex); - const targetAfter = target.slice(bangIndex); - - if (primary === 'always') { - // eslint-disable-next-line prefer-template - setFixed(targetBefore.replace(/\s*$/, '') + ' ' + targetAfter); - - return true; - } - - if (primary === 'never') { - setFixed(targetBefore.replace(/\s*$/, '') + targetAfter); - - return true; - } - - return false; - } - : null, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/declaration-block-semicolon-newline-after/README.md b/lib/rules/declaration-block-semicolon-newline-after/README.md deleted file mode 100644 index 2466458bea..0000000000 --- a/lib/rules/declaration-block-semicolon-newline-after/README.md +++ /dev/null @@ -1,143 +0,0 @@ -# declaration-block-semicolon-newline-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline or disallow whitespace after the semicolons of declaration blocks. - - -```css -a { - color: pink; - top: 0; ↑ -} ↑ -/** ↑ - * The newline after this semicolon */ -``` - -This rule ignores: - -- semicolons that are preceded by Less mixins -- the last semicolon of declaration blocks - -Use the `block-closing-brace-*-before` rules to control the whitespace between the last semicolon and the closing brace instead. - -This rule allows an end-of-line comment followed by a newline. For example, - - -```css -a { - color: pink; /* end-of-line comment */ - top: 0; -} -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a newline after the semicolon. - -The following patterns are considered problems: - - -```css -a { color: pink; top: 0; } -``` - - -```css -a { - color: pink; /* end-of-line comment - containing a newline */ - top: 0; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { - color: pink; - top: 0; -} -``` - - -```css -a { - color: pink; /* end-of-line comment */ - top: 0; -} -``` - -### `"always-multi-line"` - -There _must always_ be a newline after the semicolon in multi-line rules. - -The following patterns are considered problems: - - -```css -a { - color: pink; top: 0; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { color: pink; top: 0; } -``` - - -```css -a { - color: pink; - top: 0; -} -``` - -### `"never-multi-line"` - -There _must never_ be whitespace after the semicolon in multi-line rules. - -The following patterns are considered problems: - - -```css -a { - color: pink; - top: 0; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { color: pink; top: 0; } -``` - - -```css -a { - color: pink - ; top: 0; -} -``` diff --git a/lib/rules/declaration-block-semicolon-newline-after/__tests__/index.js b/lib/rules/declaration-block-semicolon-newline-after/__tests__/index.js deleted file mode 100644 index 11427abf22..0000000000 --- a/lib/rules/declaration-block-semicolon-newline-after/__tests__/index.js +++ /dev/null @@ -1,346 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a { color: pink;\n}', - }, - { - code: 'a { color: pink;\r\n}', - description: 'CRLF', - }, - { - code: 'a { color: pink;\n\n}', - }, - { - code: 'a { color: pink;\r\n\r\n}', - description: 'CRLF', - }, - { - code: 'a::before { content: ";a";\n}', - }, - { - code: 'a {\ncolor: pink;\n top:0;\n}', - }, - { - code: 'a {\ncolor: pink;\n top:0;\n}', - }, - { - code: 'a {\ncolor: pink;\n\ttop:0;\n}', - }, - { - code: 'a {\r\ncolor: pink;\r\n\ttop:0;\r\n}', - description: 'CRLF', - }, - { - code: 'a { color: pink;\ntop: 0; }', - description: 'space between trailing semicolon and closing brace', - }, - { - code: 'a { color: pink;\ntop: 0;}', - description: 'no space between trailing semicolon and closing brace', - }, - { - code: 'a { color: pink;\r\ntop: 0;}', - description: 'no space between trailing semicolon and closing brace and CRLF', - }, - { - code: 'a { color: pink;\ntop: 0}', - }, - { - code: 'a {\n color: pink; /* 1 */\n top: 0\n}', - description: 'end-of-line comment', - }, - { - code: 'a {\n color: pink; /* 1 */\n top: 0\n}', - description: 'end-of-line comment a few spaces after', - }, - { - code: 'a {\r\n color: pink;\t/* 1 */\r\n top: 0\r\n}', - description: 'end-of-line comment and CRLF', - }, - { - code: 'a {\n color: pink;\n /* 1 */\n top: 0\n}', - description: 'next-line comment', - }, - { - code: 'a,\nb { color: pink;\ntop: 0}', - description: 'multi-line rule, multi-line declaration-block', - }, - { - code: 'a,\r\nb { color: pink;\r\ntop: 0}', - description: 'multi-line rule, multi-line declaration-block and CRLF', - }, - ], - - reject: [ - { - code: 'a { color: pink;top: 0; }', - fixed: 'a { color: pink;\ntop: 0; }', - message: messages.expectedAfter(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink; top: 0; }', - fixed: 'a { color: pink;\n top: 0; }', - message: messages.expectedAfter(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink; top: 0; }', - fixed: 'a { color: pink;\n top: 0; }', - message: messages.expectedAfter(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink;\ttop: 0; }', - fixed: 'a { color: pink;\n\ttop: 0; }', - message: messages.expectedAfter(), - line: 1, - column: 17, - }, - { - code: 'a {\n color: pink; /* 1 */ top: 0\n}', - fixed: 'a {\n color: pink; /* 1 */\n top: 0\n}', - description: 'next node is comment without newline after', - message: messages.expectedAfter(), - line: 2, - column: 15, - }, - { - code: 'a {\r\n color: pink; /* 1 */ top: 0\r\n}', - fixed: 'a {\r\n color: pink; /* 1 */\r\n top: 0\r\n}', - description: 'CRLF and next node is comment without newline after', - message: messages.expectedAfter(), - line: 2, - column: 15, - }, - { - code: 'a { color: pink; \n top: 0; }', - fixed: 'a { color: pink;\n top: 0; }', - message: messages.expectedAfter(), - line: 1, - column: 17, - }, - { - code: 'a {\n color: pink; /* 1 */ /* 2 */ top: 0\n}', - fixed: 'a {\n color: pink; /* 1 */ /* 2 */\n top: 0\n}', - description: 'next*2 node is comment', - message: messages.expectedAfter(), - line: 2, - column: 15, - }, - { - code: 'a {\n color: pink; /* 1 */ \n top: 0\n}', - fixed: 'a {\n color: pink; /* 1 */\n top: 0\n}', - message: messages.expectedAfter(), - line: 2, - column: 15, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: 'a {\ncolor: pink;\n}', - }, - { - code: 'a::before {\ncontent: ";a";\n}', - }, - { - code: 'a::before {\r\ncontent: ";a";\r\n}', - description: 'CRLF', - }, - { - code: 'a {\ncolor: pink;\n top:0;\n}', - }, - { - code: 'a {\ncolor: pink;\n top:0;\n}', - }, - { - code: 'a {\r\ncolor: pink;\r\n top:0;\r\n}', - description: 'CRLF', - }, - { - code: 'a {\ncolor: pink;\n\ttop:0;\n}', - }, - { - code: 'a {\ncolor: pink;\ntop: 0; }', - description: 'space between trailing semicolon and closing brace', - }, - { - code: 'a {\ncolor: pink;\ntop: 0;}', - description: 'no space between trailing semicolon and closing brace', - }, - { - code: 'a { color: pink; top: 0; }', - }, - { - code: 'a { color: pink; /* 1 */ top: 0; }', - }, - { - code: 'a,\nb { color: pink; top: 0}', - description: 'multi-line rule, single-line declaration-block', - }, - { - code: 'a,\r\nb { color: pink; top: 0}', - description: 'multi-line rule, single-line declaration-block and CRLF', - }, - ], - - reject: [ - { - code: 'a {\ncolor: pink;top: 0;\n}', - fixed: 'a {\ncolor: pink;\ntop: 0;\n}', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 13, - }, - { - code: 'a {\ncolor: pink; top: 0;\n}', - fixed: 'a {\ncolor: pink;\n top: 0;\n}', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 13, - }, - { - code: 'a {\r\ncolor: pink; top: 0;\r\n}', - fixed: 'a {\r\ncolor: pink;\r\n top: 0;\r\n}', - description: 'CRLF', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 13, - }, - { - code: 'a {\ncolor: pink; top: 0;\n}', - fixed: 'a {\ncolor: pink;\n top: 0;\n}', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 13, - }, - { - code: 'a {\ncolor: pink;\ttop: 0;\n}', - fixed: 'a {\ncolor: pink;\n\ttop: 0;\n}', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 13, - }, - { - code: 'a {\r\ncolor: pink;\ttop: 0;\r\n}', - fixed: 'a {\r\ncolor: pink;\r\n\ttop: 0;\r\n}', - description: 'CRLF', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 13, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - fix: true, - - accept: [ - { - code: 'a {\ncolor: pink;\n}', - }, - { - code: 'a {\r\ncolor: pink;\r\n}', - description: 'CRLF', - }, - { - code: 'a::before {\ncontent: ";\na";\n}', - }, - { - code: 'a {\ncolor: pink;top: 0; }', - description: 'space between trailing semicolon and closing brace', - }, - { - code: 'a {\ncolor: pink;top: 0;}', - description: 'no space between trailing semicolon and closing brace', - }, - { - code: 'a { color: pink; top: 0; }', - }, - { - code: 'a,\nb { color: pink; top: 0}', - description: 'multi-line rule, single-line declaration-block', - }, - ], - - reject: [ - { - code: 'a {\ncolor: pink; top: 0;\n}', - fixed: 'a {\ncolor: pink;top: 0;\n}', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 13, - }, - { - code: 'a {\ncolor: pink; top: 0;\n}', - fixed: 'a {\ncolor: pink;top: 0;\n}', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 13, - }, - { - code: 'a {\ncolor: pink;\ntop: 0;\n}', - fixed: 'a {\ncolor: pink;top: 0;\n}', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 13, - }, - { - code: 'a {\r\ncolor: pink;\r\ntop: 0;\r\n}', - fixed: 'a {\r\ncolor: pink;top: 0;\r\n}', - description: 'CRLF', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 13, - }, - { - code: 'a {\ncolor: pink;\ttop: 0;\n}', - fixed: 'a {\ncolor: pink;top: 0;\n}', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 13, - }, - { - code: 'a {\ncolor: pink; /*comment*/ top: 0;\n}', - fixed: 'a {\ncolor: pink; /*comment*/top: 0;\n}', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 13, - }, - { - code: 'a {\n color: pink; /* 1 */ /* 2 */\ntop: 0\n}', - fixed: 'a {\n color: pink; /* 1 */ /* 2 */top: 0\n}', - description: 'next*2 node is comment', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 15, - }, - { - code: 'a {\n color: pink; /* 1 */ \n top: 0\n}', - fixed: 'a {\n color: pink; /* 1 */top: 0\n}', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 15, - }, - ], -}); diff --git a/lib/rules/declaration-block-semicolon-newline-after/index.js b/lib/rules/declaration-block-semicolon-newline-after/index.js deleted file mode 100644 index fa218039bb..0000000000 --- a/lib/rules/declaration-block-semicolon-newline-after/index.js +++ /dev/null @@ -1,107 +0,0 @@ -'use strict'; - -const blockString = require('../../utils/blockString'); -const nextNonCommentNode = require('../../utils/nextNonCommentNode'); -const rawNodeString = require('../../utils/rawNodeString'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); -const { isAtRule, isRule } = require('../../utils/typeGuards'); - -const ruleName = 'declaration-block-semicolon-newline-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected newline after ";"', - expectedAfterMultiLine: () => 'Expected newline after ";" in a multi-line declaration block', - rejectedAfterMultiLine: () => 'Unexpected newline after ";" in a multi-line declaration block', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/declaration-block-semicolon-newline-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('newline', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'always-multi-line', 'never-multi-line'], - }); - - if (!validOptions) { - return; - } - - root.walkDecls((decl) => { - // Ignore last declaration if there's no trailing semicolon - const parentRule = decl.parent; - - if (!parentRule) throw new Error('A parent node must be present'); - - if (!isAtRule(parentRule) && !isRule(parentRule)) { - return; - } - - if (!parentRule.raws.semicolon && parentRule.last === decl) { - return; - } - - const nextNode = decl.next(); - - if (!nextNode) { - return; - } - - // Allow end-of-line comment - const nodeToCheck = nextNonCommentNode(nextNode); - - if (!nodeToCheck) { - return; - } - - checker.afterOneOnly({ - source: rawNodeString(nodeToCheck), - index: -1, - lineCheckStr: blockString(parentRule), - err: (m) => { - if (context.fix) { - if (primary.startsWith('always')) { - const index = nodeToCheck.raws.before.search(/\r?\n/); - - nodeToCheck.raws.before = - index >= 0 - ? nodeToCheck.raws.before.slice(index) - : context.newline + nodeToCheck.raws.before; - - return; - } - - if (primary === 'never-multi-line') { - nodeToCheck.raws.before = ''; - - return; - } - } - - report({ - message: m, - node: decl, - index: decl.toString().length + 1, - result, - ruleName, - }); - }, - }); - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/declaration-block-semicolon-newline-before/README.md b/lib/rules/declaration-block-semicolon-newline-before/README.md deleted file mode 100644 index 4b66fdc2a4..0000000000 --- a/lib/rules/declaration-block-semicolon-newline-before/README.md +++ /dev/null @@ -1,122 +0,0 @@ -# declaration-block-semicolon-newline-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline or disallow whitespace before the semicolons of declaration blocks. - - -```css - a { - color: pink - ; top: 0; - } ↑ -/** ↑ - * The newline before this semicolon */ -``` - -This rule ignores semicolons that are preceded by Less mixins. - -## Options - -`string`: `"always"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a newline before the semicolons. - -The following patterns are considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { - color: pink; top: 0; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink -; } -``` - - -```css -a { - color: pink - ; top: 0; -} -``` - -### `"always-multi-line"` - -There _must always_ be a newline before the semicolons in multi-line rules. - -The following patterns are considered problems: - - -```css -a { - color: pink; top: 0; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { color: pink; top: 0; } -``` - - -```css -a { - color: pink - ; top: 0; -} -``` - -### `"never-multi-line"` - -There _must never_ be whitespace before the semicolons in multi-line rules. - -The following patterns are considered problems: - - -```css -a { - color: pink - ; top: 0; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { color: pink; top: 0; } -``` - - -```css -a { - color: pink; - top: 0; -} -``` diff --git a/lib/rules/declaration-block-semicolon-newline-before/__tests__/index.js b/lib/rules/declaration-block-semicolon-newline-before/__tests__/index.js deleted file mode 100644 index fcad0f5b79..0000000000 --- a/lib/rules/declaration-block-semicolon-newline-before/__tests__/index.js +++ /dev/null @@ -1,226 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - - accept: [ - { - code: 'color: pink\n;', - description: 'declaration on root', - }, - { - code: 'a { color: pink\n; }', - }, - { - code: 'a { color: pink\n\n; }', - }, - { - code: 'a::before { content: ";a"\n; }', - }, - { - code: 'a { color: pink\n;top: 0 }', - }, - { - code: 'a { color: pink\n;top: 0}', - }, - { - code: 'a { color: pink\r\n;top: 0}', - description: 'CRLF', - }, - { - code: 'a { color: pink\r\n\r\n;top: 0}', - description: 'CRLF', - }, - { - code: 'a,\nb { color: pink\n;top: 0}', - description: 'multi-line rule, multi-line declaration-block', - }, - ], - - reject: [ - { - code: 'a { color: pink;top: 0 }', - message: messages.expectedBefore(), - line: 1, - column: 15, - }, - { - code: 'a { color: pink ;top: 0 }', - message: messages.expectedBefore(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink ;top: 0 }', - message: messages.expectedBefore(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink\t;top: 0 }', - message: messages.expectedBefore(), - line: 1, - column: 16, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - - accept: [ - { - code: 'color: pink\n;', - description: 'declaration on root', - }, - { - code: 'a {\ncolor: pink\n; }', - }, - { - code: 'a::before {\ncontent: ";a"\n; }', - }, - { - code: 'a::before {\r\ncontent: ";a"\r\n; }', - description: 'CRLF', - }, - { - code: 'a {\ncolor: pink\n;top: 0 }', - }, - { - code: 'a {\ncolor: pink\n;top: 0}', - }, - { - code: 'a {\r\ncolor: pink\r\n;top: 0}', - description: 'CRLF', - }, - { - code: 'a { color: pink;top: 0; }', - }, - { - code: 'a,\nb { color: pink; top: 0}', - description: 'multi-line rule, single-line declaration-block', - }, - { - code: 'a,\r\nb { color: pink; top: 0}', - description: 'multi-line rule, single-line declaration-block and CRLF', - }, - ], - - reject: [ - { - code: 'a {\ncolor: pink;top: 0\n}', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 11, - }, - { - code: 'a {\ncolor: pink ;top: 0\n}', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 12, - }, - { - code: 'a {\ncolor: pink ;top: 0\n}', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 13, - }, - { - code: 'a {\r\ncolor: pink ;top: 0\r\n}', - description: 'CRLF', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 13, - }, - { - code: 'a {\ncolor: pink\t;top: 0\n}', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 12, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - - accept: [ - { - code: 'color: pink;', - description: 'declaration on root', - }, - { - code: 'a {\ncolor: pink;\n}', - }, - { - code: 'a {\r\ncolor: pink;\r\n}', - description: 'CRLF', - }, - { - code: 'a::before {\ncontent: ";a";\n}', - }, - { - code: 'a {\ncolor: pink;\ntop: 0 }', - }, - { - code: 'a {\ncolor: pink;\ntop: 0}', - }, - { - code: 'a {\r\ncolor: pink;\r\ntop: 0}', - description: 'CRLF', - }, - { - code: 'a { color: pink; top: 0; }', - }, - { - code: 'a,\nb { color: pink ;top: 0}', - description: 'multi-line rule, single-line declaration-block', - }, - ], - - reject: [ - { - code: 'a {\ncolor: pink\n;top: 0\n}', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 12, - }, - { - code: 'a {\ncolor: pink ;top: 0\n}', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 12, - }, - { - code: 'a {\r\ncolor: pink ;top: 0\r\n}', - description: 'CRLF', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 12, - }, - { - code: 'a {\ncolor: pink ;top: 0\n}', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 13, - }, - { - code: 'a {\ncolor: pink\t;top: 0\n}', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 12, - }, - { - code: 'a {\r\ncolor: pink\t;top: 0\r\n}', - description: 'CRLF', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 12, - }, - ], -}); diff --git a/lib/rules/declaration-block-semicolon-newline-before/index.js b/lib/rules/declaration-block-semicolon-newline-before/index.js deleted file mode 100644 index 9e75fb2935..0000000000 --- a/lib/rules/declaration-block-semicolon-newline-before/index.js +++ /dev/null @@ -1,74 +0,0 @@ -'use strict'; - -const blockString = require('../../utils/blockString'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); -const { isAtRule, isRule } = require('../../utils/typeGuards'); - -const ruleName = 'declaration-block-semicolon-newline-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected newline before ";"', - expectedBeforeMultiLine: () => 'Expected newline before ";" in a multi-line declaration block', - rejectedBeforeMultiLine: () => - 'Unexpected whitespace before ";" in a multi-line declaration block', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/declaration-block-semicolon-newline-before', - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary) => { - const checker = whitespaceChecker('newline', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'always-multi-line', 'never-multi-line'], - }); - - if (!validOptions) { - return; - } - - root.walkDecls((decl) => { - const parentRule = decl.parent; - - if (!parentRule) throw new Error('A parent node must be present'); - - if (!isAtRule(parentRule) && !isRule(parentRule)) { - return; - } - - if (!parentRule.raws.semicolon && parentRule.last === decl) { - return; - } - - const declString = decl.toString(); - - checker.beforeAllowingIndentation({ - source: declString, - index: declString.length, - lineCheckStr: blockString(parentRule), - err: (m) => { - report({ - message: m, - node: decl, - index: decl.toString().length - 1, - result, - ruleName, - }); - }, - }); - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/declaration-block-semicolon-space-after/README.md b/lib/rules/declaration-block-semicolon-space-after/README.md deleted file mode 100644 index 70ec855575..0000000000 --- a/lib/rules/declaration-block-semicolon-space-after/README.md +++ /dev/null @@ -1,149 +0,0 @@ -# declaration-block-semicolon-space-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace after the semicolons of declaration blocks. - - -```css -a { color: pink; top: 0; } -/** ↑ - * The space after this semicolon */ -``` - -This rule ignores: - -- semicolons that are preceded by Less mixins -- the last semicolon of declaration blocks - -Use the `block-closing-brace-*-before` rules to control the whitespace between the last semicolon and the closing brace instead. - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"|"always-single-line"|"never-single-line"` - -### `"always"` - -There _must always_ be a single space after the semicolon. - -The following patterns are considered problems: - - -```css -a { color: pink;top: 0; } -``` - - -```css -a { - color: pink; - top: 0; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink;} -``` - - -```css -a { color: pink; } -``` - - -```css -a { color: pink; top: 0; } -``` - -### `"never"` - -There _must never_ be whitespace after the semicolon. - -The following patterns are considered problems: - - -```css -a { color: pink; top: 0; } -``` - - -```css -a { - color: pink; - top: 0; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink;} -``` - - -```css -a { color: pink; } -``` - - -```css -a { color: pink;top: 0; } -``` - -### `"always-single-line"` - -There _must always_ be a single space after the semicolon in single-line declaration blocks. - -The following patterns are considered problems: - - -```css -a { color: pink;top: 0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; top: 0; } -``` - - -```css -a { - color: pink; - top: 0; -} -``` - -### `"never-single-line"` - -There _must never_ be whitespace after the semicolon in single-line declaration blocks. - -The following patterns are considered problems: - - -```css -a { color: pink; top: 0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink;top: 0; } -``` - - -```css -a { - color: pink; - top: 0; -} -``` diff --git a/lib/rules/declaration-block-semicolon-space-after/__tests__/index.js b/lib/rules/declaration-block-semicolon-space-after/__tests__/index.js deleted file mode 100644 index 0d57bff353..0000000000 --- a/lib/rules/declaration-block-semicolon-space-after/__tests__/index.js +++ /dev/null @@ -1,248 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a::before { content: ";a"; }', - }, - { - code: 'a { color: pink; top: 0;}', - description: 'no space between trailing semicolon and closing brace', - }, - { - code: 'a { color: pink; top: 0}', - }, - ], - - reject: [ - { - code: 'a { color: pink;top: 0; }', - fixed: 'a { color: pink; top: 0; }', - message: messages.expectedAfter(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink; top: 0; }', - fixed: 'a { color: pink; top: 0; }', - message: messages.expectedAfter(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink;\ntop: 0; }', - fixed: 'a { color: pink; top: 0; }', - message: messages.expectedAfter(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink;\r\ntop: 0; }', - fixed: 'a { color: pink; top: 0; }', - description: 'CRLF', - message: messages.expectedAfter(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink;\ttop: 0; }', - fixed: 'a { color: pink; top: 0; }', - message: messages.expectedAfter(), - line: 1, - column: 17, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'color: pink;', - description: 'declaration on root', - }, - { - code: 'a { color: pink;}', - }, - { - code: 'a::before { content: ";a";}', - }, - { - code: 'a { color: pink;top: 0;}', - }, - ], - - reject: [ - { - code: 'a { color: pink;\n top: 0; }', - fixed: 'a { color: pink;top: 0; }', - message: messages.rejectedAfter(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink; top: 0; }', - fixed: 'a { color: pink;top: 0; }', - message: messages.rejectedAfter(), - line: 1, - column: 17, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a::before { content: ";a"; }', - }, - { - code: 'a { color: pink; top: 0;}', - description: 'no space between trailing semicolon and closing brace', - }, - { - code: 'a,\nb { color: pink; top: 0; }', - description: 'multi-line rule, single-line declaration-block', - }, - { - code: 'a,\r\nb { color: pink; top: 0; }', - description: 'multi-line rule, single-line declaration-block and CRLF', - }, - { - code: 'a {\n color: pink;\n top: 0;\n}', - }, - { - code: 'a {\r\n color: pink;\r\n top: 0;\r\n}', - description: 'CRLF', - }, - ], - - reject: [ - { - code: 'a { color: pink;top: 0; }', - fixed: 'a { color: pink; top: 0; }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 17, - }, - { - code: 'a,\nb { color: pink;top: 0; }', - fixed: 'a,\nb { color: pink; top: 0; }', - message: messages.expectedAfterSingleLine(), - line: 2, - column: 17, - }, - { - code: 'a,\r\nb { color: pink;top: 0; }', - fixed: 'a,\r\nb { color: pink; top: 0; }', - description: 'CRLF', - message: messages.expectedAfterSingleLine(), - line: 2, - column: 17, - }, - { - code: 'a { color: pink; top: 0; }', - fixed: 'a { color: pink; top: 0; }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink;\ttop: 0; }', - fixed: 'a { color: pink; top: 0; }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 17, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a::before { content: "; a"; }', - }, - { - code: 'a { color: pink;top: 0; }', - description: 'space between trailing semicolon and closing brace', - }, - { - code: 'a,\nb { color: pink;top: 0; }', - description: 'multi-line rule, single-line declaration-block', - }, - { - code: 'a {\n color: pink; top: 0;\n}', - }, - { - code: 'a {\r\n color: pink; top: 0;\r\n}', - description: 'CRLF', - }, - ], - - reject: [ - { - code: 'a { color: pink; top: 0; }', - fixed: 'a { color: pink;top: 0; }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 17, - }, - { - code: 'a,\nb { color: pink; top: 0; }', - fixed: 'a,\nb { color: pink;top: 0; }', - message: messages.rejectedAfterSingleLine(), - line: 2, - column: 17, - }, - { - code: 'a,\r\nb { color: pink; top: 0; }', - fixed: 'a,\r\nb { color: pink;top: 0; }', - description: 'CRLF', - message: messages.rejectedAfterSingleLine(), - line: 2, - column: 17, - }, - { - code: 'a { color: pink; top: 0; }', - fixed: 'a { color: pink;top: 0; }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink;\ttop: 0; }', - fixed: 'a { color: pink;top: 0; }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 17, - }, - ], -}); diff --git a/lib/rules/declaration-block-semicolon-space-after/index.js b/lib/rules/declaration-block-semicolon-space-after/index.js deleted file mode 100644 index 97a16bdc2e..0000000000 --- a/lib/rules/declaration-block-semicolon-space-after/index.js +++ /dev/null @@ -1,97 +0,0 @@ -'use strict'; - -const blockString = require('../../utils/blockString'); -const rawNodeString = require('../../utils/rawNodeString'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); -const { isAtRule, isRule } = require('../../utils/typeGuards'); - -const ruleName = 'declaration-block-semicolon-space-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected single space after ";"', - rejectedAfter: () => 'Unexpected whitespace after ";"', - expectedAfterSingleLine: () => - 'Expected single space after ";" in a single-line declaration block', - rejectedAfterSingleLine: () => - 'Unexpected whitespace after ";" in a single-line declaration block', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/declaration-block-semicolon-space-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never', 'always-single-line', 'never-single-line'], - }); - - if (!validOptions) { - return; - } - - root.walkDecls((decl) => { - // Ignore last declaration if there's no trailing semicolon - const parentRule = decl.parent; - - if (!parentRule) throw new Error('A parent node must be present'); - - if (!isAtRule(parentRule) && !isRule(parentRule)) { - return; - } - - if (!parentRule.raws.semicolon && parentRule.last === decl) { - return; - } - - const nextDecl = decl.next(); - - if (!nextDecl) { - return; - } - - checker.after({ - source: rawNodeString(nextDecl), - index: -1, - lineCheckStr: blockString(parentRule), - err: (m) => { - if (context.fix) { - if (primary.startsWith('always')) { - nextDecl.raws.before = ' '; - - return; - } - - if (primary.startsWith('never')) { - nextDecl.raws.before = ''; - - return; - } - } - - report({ - message: m, - node: decl, - index: decl.toString().length + 1, - result, - ruleName, - }); - }, - }); - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/declaration-block-semicolon-space-before/README.md b/lib/rules/declaration-block-semicolon-space-before/README.md deleted file mode 100644 index 2f6e064287..0000000000 --- a/lib/rules/declaration-block-semicolon-space-before/README.md +++ /dev/null @@ -1,132 +0,0 @@ -# declaration-block-semicolon-space-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace before the semicolons of declaration blocks. - - -```css -a { color: pink; } -/** ↑ - * The space before this semicolon */ -``` - -This rule ignores semicolons that are preceded by Less mixins. - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"|"always-single-line"|"never-single-line"` - -### `"always"` - -There _must always_ be a single space before the semicolons. - -The following patterns are considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { color: pink; top: 0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink ; } -``` - - -```css -a { color: pink ; top: 0 ; } -``` - -### `"never"` - -There _must never_ be whitespace before the semicolons. - -The following patterns are considered problems: - - -```css -a { color: pink ; } -``` - - -```css -a { color: pink ; top: 0 ; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { color: pink; top: 0; } -``` - -### `"always-single-line"` - -There _must always_ be a single space before the semicolons in single-line declaration blocks. - -The following patterns are considered problems: - - -```css -a { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink ; } -``` - - -```css -a { color: pink; top: 0; } -``` - - -```css -a { color: pink ; top: 0 ; } -``` - -### `"never-single-line"` - -There _must never_ be whitespace before the semicolons in single-line declaration blocks. - -The following patterns are considered problems: - - -```css -a { color: pink ; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { color: pink; top: 0; } -``` - - -```css -a { color: pink ; top: 0 ; } -``` diff --git a/lib/rules/declaration-block-semicolon-space-before/__tests__/index.js b/lib/rules/declaration-block-semicolon-space-before/__tests__/index.js deleted file mode 100644 index a8c69cce13..0000000000 --- a/lib/rules/declaration-block-semicolon-space-before/__tests__/index.js +++ /dev/null @@ -1,394 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'color: pink ;', - description: 'declaration on root', - }, - { - code: 'a { color: pink ; }', - }, - { - code: 'a::before { content: ";a" ; }', - }, - { - code: 'a { color: pink ; top: 0 ; }', - }, - { - code: 'a { color: pink ; top: 0}', - }, - { - code: 'a { width: 50% !important ;}', - }, - ], - - reject: [ - { - code: 'a { color: pink; }', - fixed: 'a { color: pink ; }', - message: messages.expectedBefore(), - line: 1, - column: 15, - }, - { - code: 'a { color: pink ; }', - fixed: 'a { color: pink ; }', - message: messages.expectedBefore(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink\t; }', - fixed: 'a { color: pink ; }', - message: messages.expectedBefore(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink\n; }', - fixed: 'a { color: pink ; }', - message: messages.expectedBefore(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink\r\n; }', - fixed: 'a { color: pink ; }', - description: 'CRLF', - message: messages.expectedBefore(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink ; top: 0; }', - fixed: 'a { color: pink ; top: 0 ; }', - message: messages.expectedBefore(), - line: 1, - column: 24, - }, - { - code: 'a { color: pink/*comment*/; }', - fixed: 'a { color: pink/*comment*/ ; }', - description: 'comment', - message: messages.expectedBefore(), - line: 1, - column: 26, - }, - { - code: 'a { color: pink /*comment*/; }', - fixed: 'a { color: pink /*comment*/ ; }', - description: 'comment', - message: messages.expectedBefore(), - line: 1, - column: 27, - }, - { - code: 'a { width: 50% !important; }', - fixed: 'a { width: 50% !important ; }', - description: 'important', - message: messages.expectedBefore(), - line: 1, - column: 25, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'color: pink;', - description: 'declaration on root', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a::before { content: ";a"; }', - }, - { - code: 'a { color: pink; top: 0; }', - }, - { - code: 'a { width: 50% !important;}', - }, - ], - - reject: [ - { - code: 'a { color: pink ; }', - fixed: 'a { color: pink; }', - message: messages.rejectedBefore(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink ; }', - fixed: 'a { color: pink; }', - message: messages.rejectedBefore(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink\t; }', - fixed: 'a { color: pink; }', - message: messages.rejectedBefore(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink\n; }', - fixed: 'a { color: pink; }', - message: messages.rejectedBefore(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink\r\n; }', - fixed: 'a { color: pink; }', - description: 'CRLF', - message: messages.rejectedBefore(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink; top: 0 ; }', - fixed: 'a { color: pink; top: 0; }', - message: messages.rejectedBefore(), - line: 1, - column: 24, - }, - { - code: 'a { color: pink/*comment*/ ; }', - fixed: 'a { color: pink/*comment*/; }', - description: 'comment', - message: messages.rejectedBefore(), - line: 1, - column: 27, - }, - { - code: 'a { color: pink /*comment*/ ; }', - fixed: 'a { color: pink /*comment*/; }', - description: 'comment', - message: messages.rejectedBefore(), - line: 1, - column: 28, - }, - { - code: 'a { width: 50% !important ; }', - fixed: 'a { width: 50% !important; }', - description: 'important', - message: messages.rejectedBefore(), - line: 1, - column: 26, - }, - { - code: 'a { width: 50% !important ; }', - fixed: 'a { width: 50% !important; }', - description: 'important', - message: messages.rejectedBefore(), - line: 1, - column: 30, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: 'color: pink ;', - description: 'declaration on root', - }, - { - code: 'a { color: pink ; }', - }, - { - code: 'a::before { content: ";a" ; }', - }, - { - code: 'a { color: pink ; top: 0 ; }', - }, - { - code: 'a,\nb { color: pink ; top: 0 ; }', - description: 'multi-line rule, single-line declaration-block', - }, - { - code: 'a {\n color: pink;\n top: 0;\n}', - }, - { - code: 'a {\r\n color: pink;\r\n top: 0;\r\n}', - description: 'CRLF', - }, - { - code: 'a { width: 50% !important ; }', - }, - { - code: 'a {\n width: 50% !important;\n}', - }, - ], - - reject: [ - { - code: 'a { color: pink; }', - fixed: 'a { color: pink ; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 15, - }, - { - code: 'a,\nb { color: pink; }', - fixed: 'a,\nb { color: pink ; }', - message: messages.expectedBeforeSingleLine(), - line: 2, - column: 15, - }, - { - code: 'a,\r\nb { color: pink; }', - fixed: 'a,\r\nb { color: pink ; }', - description: 'CRLF', - message: messages.expectedBeforeSingleLine(), - line: 2, - column: 15, - }, - { - code: 'a { color: pink ; }', - fixed: 'a { color: pink ; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink\t; }', - fixed: 'a { color: pink ; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink ; top: 0; }', - fixed: 'a { color: pink ; top: 0 ; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 24, - }, - { - code: 'a { width: 50% !important; }', - fixed: 'a { width: 50% !important ; }', - description: 'important', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 25, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - fix: true, - - accept: [ - { - code: 'color: pink;', - description: 'declaration on root', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a::before { content: ";a"; }', - }, - { - code: 'a { color: pink; top: 0; }', - }, - { - code: 'a,\nb { color: pink; top: 0; }', - description: 'multi-line rule, single-line declaration-block', - }, - { - code: 'a {\n color: pink ;\n top: 0 ;\n}', - }, - { - code: 'a { width: 50% !important; }', - }, - { - code: 'a {\n width: 50% !important ;\n}', - }, - ], - - reject: [ - { - code: 'a { color: pink ; }', - fixed: 'a { color: pink; }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 16, - }, - { - code: 'a,\nb { color: pink ; }', - fixed: 'a,\nb { color: pink; }', - message: messages.rejectedBeforeSingleLine(), - line: 2, - column: 16, - }, - { - code: 'a,\r\nb { color: pink ; }', - fixed: 'a,\r\nb { color: pink; }', - description: 'CRLF', - message: messages.rejectedBeforeSingleLine(), - line: 2, - column: 16, - }, - { - code: 'a { color: pink ; }', - fixed: 'a { color: pink; }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 17, - }, - { - code: 'a { color: pink\t; }', - fixed: 'a { color: pink; }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 16, - }, - { - code: 'a { color: pink; top: 0 ; }', - fixed: 'a { color: pink; top: 0; }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 24, - }, - { - code: 'a { width: 50% !important ; }', - fixed: 'a { width: 50% !important; }', - description: 'important', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 26, - }, - { - code: 'a { width: 50% !important ; }', - fixed: 'a { width: 50% !important; }', - description: 'important', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 30, - }, - ], -}); diff --git a/lib/rules/declaration-block-semicolon-space-before/index.js b/lib/rules/declaration-block-semicolon-space-before/index.js deleted file mode 100644 index 56426dc3b3..0000000000 --- a/lib/rules/declaration-block-semicolon-space-before/index.js +++ /dev/null @@ -1,104 +0,0 @@ -'use strict'; - -const blockString = require('../../utils/blockString'); -const getDeclarationValue = require('../../utils/getDeclarationValue'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const setDeclarationValue = require('../../utils/setDeclarationValue'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); -const { isAtRule, isRule } = require('../../utils/typeGuards'); - -const ruleName = 'declaration-block-semicolon-space-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected single space before ";"', - rejectedBefore: () => 'Unexpected whitespace before ";"', - expectedBeforeSingleLine: () => - 'Expected single space before ";" in a single-line declaration block', - rejectedBeforeSingleLine: () => - 'Unexpected whitespace before ";" in a single-line declaration block', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/declaration-block-semicolon-space-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never', 'always-single-line', 'never-single-line'], - }); - - if (!validOptions) { - return; - } - - root.walkDecls((decl) => { - // Ignore last declaration if there's no trailing semicolon - const parentRule = decl.parent; - - if (!parentRule) throw new Error('A parent node must be present'); - - if (!isAtRule(parentRule) && !isRule(parentRule)) { - return; - } - - if (!parentRule.raws.semicolon && parentRule.last === decl) { - return; - } - - const declString = decl.toString(); - - checker.before({ - source: declString, - index: declString.length, - lineCheckStr: blockString(parentRule), - err: (m) => { - if (context.fix) { - const value = getDeclarationValue(decl); - - if (primary.startsWith('always')) { - if (decl.important) { - decl.raws.important = ' !important '; - } else { - setDeclarationValue(decl, value.replace(/\s*$/, ' ')); - } - - return; - } - - if (primary.startsWith('never')) { - if (decl.raws.important) { - decl.raws.important = decl.raws.important.replace(/\s*$/, ''); - } else { - setDeclarationValue(decl, value.replace(/\s*$/, '')); - } - - return; - } - } - - report({ - message: m, - node: decl, - index: decl.toString().length - 1, - result, - ruleName, - }); - }, - }); - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/declaration-block-trailing-semicolon/README.md b/lib/rules/declaration-block-trailing-semicolon/README.md deleted file mode 100644 index 22caa75631..0000000000 --- a/lib/rules/declaration-block-trailing-semicolon/README.md +++ /dev/null @@ -1,110 +0,0 @@ -# declaration-block-trailing-semicolon - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require or disallow a trailing semicolon within declaration blocks. - - -```css -a { background: orange; color: pink; } -/** ↑ - * This semicolon */ -``` - -The trailing semicolon is the _last_ semicolon in a declaration block and it is optional. - -This rule ignores: - -- Less mixins -- trailing `//` comments -- declaration blocks containing nested (at-)rules - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a trailing semicolon. - -The following patterns are considered problems: - - -```css -a { color: pink } -``` - - -```css -a { background: orange; color: pink } -``` - - -```css -a { @include foo } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { background: orange; color: pink; } -``` - - -```css -a { @include foo; } -``` - -### `"never"` - -There _must never_ be a trailing semicolon. - -The following patterns are considered problems: - - -```css -a { color: pink; } -``` - - -```css -a { background: orange; color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink } -``` - - -```css -a { background: orange; color: pink } -``` - -## Optional secondary options - -### `ignore: ["single-declaration"]` - -Ignore declaration blocks that contain a single declaration. - -The following patterns are _not_ considered problems: - - -```css -a { color: pink } -``` - - -```css -a { color: pink; } -``` diff --git a/lib/rules/declaration-block-trailing-semicolon/__tests__/index.js b/lib/rules/declaration-block-trailing-semicolon/__tests__/index.js deleted file mode 100644 index 413e286ed5..0000000000 --- a/lib/rules/declaration-block-trailing-semicolon/__tests__/index.js +++ /dev/null @@ -1,225 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - description: 'single declaration block with trailing semicolon', - }, - { - code: 'a { background: orange; color: pink; }', - description: 'multi declaration block with trailing semicolon', - }, - { - code: 'a { &:hover { color: pink; }}', - description: 'nesting without first-level decl', - }, - { - code: 'a { color: red; &:hover { color: pink; }}', - description: 'nesting with first-level decl', - }, - ], - - reject: [ - { - code: 'a { color: pink }', - fixed: 'a { color: pink; }', - description: 'single declaration block without trailing semicolon', - message: messages.expected, - line: 1, - column: 15, - }, - { - code: 'a { background: orange; color: pink }', - fixed: 'a { background: orange; color: pink; }', - description: 'multi declaration block without trailing semicolon', - message: messages.expected, - line: 1, - column: 35, - }, - { - code: 'a { &:hover { color: pink }}', - fixed: 'a { &:hover { color: pink; }}', - description: 'nesting without first-level decl', - message: messages.expected, - line: 1, - column: 25, - }, - { - code: 'a { color: red; &:hover { color: pink }}', - fixed: 'a { color: red; &:hover { color: pink; }}', - description: 'nesting with first-level decl', - message: messages.expected, - line: 1, - column: 37, - }, - ], -}); - -testRule({ - ruleName, - config: ['always', { ignore: 'single-declaration' }], - fix: true, - - accept: [ - { - code: 'a { color: pink }', - description: 'single declaration without trailing semicolon', - }, - { - code: 'a { color: pink; }', - description: 'single declaration with trailing semicolon', - }, - { - code: '@keyframes foo { from { top: 0px } to { top: 1px; } }', - description: 'inconsistent case (with and without)', - }, - ], - - reject: [ - { - code: 'a { background: orange; color: pink }', - fixed: 'a { background: orange; color: pink; }', - description: 'multi declaration block without trailing semicolon', - message: messages.expected, - line: 1, - column: 35, - }, - ], -}); - -testRule({ - ruleName, - config: ['never', { ignore: ['single-declaration'] }], - - accept: [ - { - code: 'a { color: pink }', - description: 'single declaration without trailing semicolon', - }, - { - code: 'a { color: pink; }', - description: 'single declaration with trailing semicolon', - }, - { - code: '@keyframes foo { from { top: 0px } to { top: 1px; } }', - description: 'inconsistent case (with and without)', - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a { color: pink }', - description: 'single-line declaration block without trailing semicolon', - }, - { - code: 'a { background: orange; color: pink }', - description: 'multi-line declaration block without trailing semicolon', - }, - ], - - reject: [ - { - code: 'a { color: pink; }', - fixed: 'a { color: pink }', - description: 'single-line declaration block with trailing semicolon', - message: messages.rejected, - line: 1, - column: 15, - }, - { - code: 'a { background: orange; color: pink; }', - fixed: 'a { background: orange; color: pink }', - description: 'multi-line declaration block with trailing semicolon', - message: messages.rejected, - line: 1, - column: 35, - }, - ], -}); - -testRule({ - ruleName, - config: ['always'], - customSyntax: 'postcss-scss', - fix: true, - - accept: [ - { - code: 'a { @includes foo; }', - description: 'at-rule with trailing semicolon', - }, - { - code: 'a { @foo { color: pink; } }', - description: 'at-rule with decl block with trailing semicolon', - }, - ], - - reject: [ - { - code: 'a { @includes foo }', - fixed: 'a { @includes foo; }', - description: 'at-rule without trailing semicolon', - message: messages.expected, - line: 1, - column: 17, - }, - { - code: 'a { @foo { color: pink } }', - fixed: 'a { @foo { color: pink; } }', - description: 'at-rule with decl block without trailing semicolon', - message: messages.expected, - line: 1, - column: 22, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - customSyntax: 'postcss-scss', - fix: true, - - accept: [ - { - code: 'a { @includes foo }', - description: 'at-rule without trailing semicolon', - }, - { - code: 'a { @foo { color: pink } }', - description: 'at-rule with decl block without trailing semicolon', - }, - ], - - reject: [ - { - code: 'a { @includes foo; }', - fixed: 'a { @includes foo }', - description: 'at-rule with trailing semicolon', - message: messages.rejected, - line: 1, - column: 17, - }, - { - code: 'a { @foo { color: pink; } }', - fixed: 'a { @foo { color: pink } }', - description: 'at-rule with decl block with trailing semicolon', - message: messages.rejected, - line: 1, - column: 22, - }, - ], -}); diff --git a/lib/rules/declaration-block-trailing-semicolon/index.js b/lib/rules/declaration-block-trailing-semicolon/index.js deleted file mode 100644 index acc45e646f..0000000000 --- a/lib/rules/declaration-block-trailing-semicolon/index.js +++ /dev/null @@ -1,146 +0,0 @@ -'use strict'; - -const hasBlock = require('../../utils/hasBlock'); -const optionsMatches = require('../../utils/optionsMatches'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const { isAtRule } = require('../../utils/typeGuards'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'declaration-block-trailing-semicolon'; - -const messages = ruleMessages(ruleName, { - expected: 'Expected a trailing semicolon', - rejected: 'Unexpected trailing semicolon', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/declaration-block-trailing-semicolon', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions( - result, - ruleName, - { - actual: primary, - possible: ['always', 'never'], - }, - { - actual: secondaryOptions, - possible: { - ignore: ['single-declaration'], - }, - optional: true, - }, - ); - - if (!validOptions) { - return; - } - - root.walkAtRules((atRule) => { - if (!atRule.parent) throw new Error('A parent node must be present'); - - if (atRule.parent === root) { - return; - } - - if (atRule !== atRule.parent.last) { - return; - } - - if (hasBlock(atRule)) { - return; - } - - checkLastNode(atRule); - }); - - root.walkDecls((decl) => { - if (!decl.parent) throw new Error('A parent node must be present'); - - if (decl.parent.type === 'object') { - return; - } - - if (decl !== decl.parent.last) { - return; - } - - checkLastNode(decl); - }); - - /** - * @param {import('postcss').Node} node - */ - function checkLastNode(node) { - if (!node.parent) throw new Error('A parent node must be present'); - - const hasSemicolon = node.parent.raws.semicolon; - const ignoreSingleDeclaration = optionsMatches( - secondaryOptions, - 'ignore', - 'single-declaration', - ); - - if (ignoreSingleDeclaration && node.parent.first === node) { - return; - } - - let message; - - if (primary === 'always') { - if (hasSemicolon) { - return; - } - - // auto-fix - if (context.fix) { - node.parent.raws.semicolon = true; - - if (isAtRule(node)) { - node.raws.between = ''; - node.parent.raws.after = ' '; - } - - return; - } - - message = messages.expected; - } else if (primary === 'never') { - if (!hasSemicolon) { - return; - } - - // auto-fix - if (context.fix) { - node.parent.raws.semicolon = false; - - return; - } - - message = messages.rejected; - } else { - throw new Error(`Unexpected primary option: "${primary}"`); - } - - report({ - message, - node, - index: node.toString().trim().length - 1, - result, - ruleName, - }); - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/declaration-colon-newline-after/README.md b/lib/rules/declaration-colon-newline-after/README.md deleted file mode 100644 index dde51452d2..0000000000 --- a/lib/rules/declaration-colon-newline-after/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# declaration-colon-newline-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline or disallow whitespace after the colon of declarations. - - -```css -a { - box-shadow: - 0 0 0 1px #5b9dd9, - 0 0 2px 1px rgba(30, 140, 190, 0.8); -} /* ↑ */ -/** ↑ - * The newline after this colon */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"always-multi-line"` - -### `"always"` - -There _must always_ be a newline after the colon. - -The following patterns are considered problems: - - -```css -a { color:pink; } -``` - - -```css -a { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { - color: - pink; -} -``` - -### `"always-multi-line"` - -There _must always_ be a newline after the colon _if the declaration's value is multi-line_. - -The following patterns are considered problems: - - -```css -a { - box-shadow: 0 0 0 1px #5b9dd9, - 0 0 2px 1px rgba(30, 140, 190, 0.8); -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { - box-shadow: - 0 0 0 1px #5b9dd9, - 0 0 2px 1px rgba(30, 140, 190, 0.8); -} -``` - - -```css -a { - color: pink; -} -``` diff --git a/lib/rules/declaration-colon-newline-after/__tests__/index.js b/lib/rules/declaration-colon-newline-after/__tests__/index.js deleted file mode 100644 index b87b8f6ada..0000000000 --- a/lib/rules/declaration-colon-newline-after/__tests__/index.js +++ /dev/null @@ -1,211 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a {\n' + ' color:\n' + ' pink\n' + '}', - - description: 'newline and spaces after', - }, - { - code: 'a { color :\npink }', - description: 'space before and newline after', - }, - { - code: 'a { color\n:\npink }', - description: 'newline before after', - }, - { - code: 'a { color\r\n:\r\npink }', - description: 'CRLF before and after', - }, - { - code: 'a { color\n\n:\n\npink }', - description: 'double newline before after', - }, - { - code: 'a { color\r\n\r\n:\r\n\r\npink }', - description: 'double CRLF before and after', - }, - { - code: '$map: (key: value)', - description: 'SCSS map with no newlines', - }, - { - code: 'a { background:\n url(data:application/font-woff;...); }', - description: 'data URI', - }, - ], - - reject: [ - { - code: 'a { color :pink; }', - fixed: 'a { color :\npink; }', - description: 'no newline after', - message: messages.expectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color : pink; }', - fixed: 'a { color :\n pink; }', - description: 'two spaces after', - message: messages.expectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color :\tpink; }', - fixed: 'a { color :\n\tpink; }', - description: 'tab after', - message: messages.expectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color : pink; }', - fixed: 'a { color :\n pink; }', - description: 'space after', - message: messages.expectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color : \npink; }', - fixed: 'a { color :\npink; }', - description: 'space and newline after', - message: messages.expectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color : \r\npink; }', - fixed: 'a { color :\r\npink; }', - description: 'space and CRLF after', - message: messages.expectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color : \t\n\t\npink; }', - fixed: 'a { color :\n\t\npink; }', - description: 'space and newline tab after', - message: messages.expectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color :/*comment*/pink; }', - fixed: 'a { color :/*comment*/\npink; }', - description: 'comment', - message: messages.expectedAfter(), - line: 1, - column: 22, - }, - { - code: 'a { color : /*comment*/ pink; }', - fixed: 'a { color : /*comment*/\n pink; }', - description: 'comment', - message: messages.expectedAfter(), - line: 1, - column: 23, - }, - { - code: 'a { color : \n/*comment*/ pink; }', - fixed: 'a { color :\n/*comment*/ pink; }', - description: 'comment before newline', - message: messages.expectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color : pink; }', - fixed: 'a { color :\n pink; }', - description: 'multi space', - message: messages.expectedAfter(), - line: 1, - column: 18, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: 'a {\n' + ' color: pink\n' + '}', - }, - { - code: - 'a {\n' + - ' box-shadow:\n' + - ' 0 0 0 1px #5b9dd9\n' + - ' 0 0 2px 1px rgba(30, 140, 190, 0.8);\n' + - '}', - }, - { - code: '$map\n: (\nkey: value,\nkey2 :value2)', - description: 'SCSS map with newlines', - }, - { - code: "$list: (\n'value1',\n'value2',\n)", - description: 'SCSS list with newlines', - }, - { - code: 'a { color:pink }', - }, - { - code: 'a { color :\tpink }', - }, - { - code: 'a { color\n: pink }', - }, - { - code: 'a { color\r\n: pink }', - }, - ], - - reject: [ - { - code: - 'a {\n' + - ' box-shadow: 0 0 0 1px #5b9dd9\n' + - ' 0 0 2px 1px rgba(30, 140, 190, 0.8);\n' + - '}', - fixed: - 'a {\n' + - ' box-shadow:\n' + - ' 0 0 0 1px #5b9dd9\n' + - ' 0 0 2px 1px rgba(30, 140, 190, 0.8);\n' + - '}', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 13, - }, - { - code: - 'a {\n' + - ' box-shadow:0 0 0 1px #5b9dd9\n' + - ' 0 0 2px 1px rgba(30, 140, 190, 0.8);\n' + - '}', - fixed: - 'a {\n' + - ' box-shadow:\n' + - '0 0 0 1px #5b9dd9\n' + - ' 0 0 2px 1px rgba(30, 140, 190, 0.8);\n' + - '}', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 13, - }, - ], -}); diff --git a/lib/rules/declaration-colon-newline-after/index.js b/lib/rules/declaration-colon-newline-after/index.js deleted file mode 100644 index acfa40465b..0000000000 --- a/lib/rules/declaration-colon-newline-after/index.js +++ /dev/null @@ -1,97 +0,0 @@ -'use strict'; - -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const isStandardSyntaxDeclaration = require('../../utils/isStandardSyntaxDeclaration'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'declaration-colon-newline-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected newline after ":"', - expectedAfterMultiLine: () => 'Expected newline after ":" with a multi-line declaration', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/declaration-colon-newline-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('newline', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'always-multi-line'], - }); - - if (!validOptions) { - return; - } - - root.walkDecls((decl) => { - if (!isStandardSyntaxDeclaration(decl)) { - return; - } - - // Get the raw prop, and only the prop - const endOfPropIndex = declarationValueIndex(decl) + (decl.raws.between || '').length - 1; - - // The extra characters tacked onto the end ensure that there is a character to check - // after the colon. Otherwise, with `background:pink` the character after the - const propPlusColon = `${decl.toString().slice(0, endOfPropIndex)}xxx`; - - for (let i = 0, l = propPlusColon.length; i < l; i++) { - if (propPlusColon[i] !== ':') { - continue; - } - - const indexToCheck = /^[^\S\r\n]*\/\*/.test(propPlusColon.slice(i + 1)) - ? propPlusColon.indexOf('*/', i) + 1 - : i; - - checker.afterOneOnly({ - source: propPlusColon, - index: indexToCheck, - lineCheckStr: decl.value, - err: (m) => { - if (context.fix) { - const between = decl.raws.between; - - if (between == null) throw new Error('`between` must be present'); - - const betweenStart = declarationValueIndex(decl) - between.length; - const sliceIndex = indexToCheck - betweenStart + 1; - const betweenBefore = between.slice(0, sliceIndex); - const betweenAfter = between.slice(sliceIndex); - - decl.raws.between = /^\s*\n/.test(betweenAfter) - ? betweenBefore + betweenAfter.replace(/^[^\S\r\n]*/, '') - : betweenBefore + context.newline + betweenAfter; - - return; - } - - report({ - message: m, - node: decl, - index: indexToCheck, - result, - ruleName, - }); - }, - }); - } - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/declaration-colon-space-after/README.md b/lib/rules/declaration-colon-space-after/README.md deleted file mode 100644 index d8918bcb3e..0000000000 --- a/lib/rules/declaration-colon-space-after/README.md +++ /dev/null @@ -1,113 +0,0 @@ -# declaration-colon-space-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace after the colon of declarations. - - -```css -a { color: pink } -/** ↑ - * The space after this colon */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"|"always-single-line"` - -### `"always"` - -There _must always_ be a single space after the colon. - -The following patterns are considered problems: - - -```css -a { color :pink } -``` - - -```css -a { color:pink } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color : pink } -``` - - -```css -a { color: pink } -``` - -### `"never"` - -There _must never_ be whitespace after the colon. - -The following patterns are considered problems: - - -```css -a { color : pink } -``` - - -```css -a { color: pink } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color :pink } -``` - - -```css -a { color:pink } -``` - -### `"always-single-line"` - -There _must always_ be a single space after the colon _if the declaration's value is single-line_. - -The following patterns are considered problems: - - -```css -a { - box-shadow:0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, 0.8); -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { - box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, 0.8); -} -``` - - -```css -a { - box-shadow: - 0 0 0 1px #5b9dd9, - 0 0 2px 1px rgba(30, 140, 190, 0.8); -} -``` - - -```css -a { - box-shadow:0 0 0 1px #5b9dd9, - 0 0 2px 1px rgba(30, 140, 190, 0.8); -} -``` diff --git a/lib/rules/declaration-colon-space-after/__tests__/index.js b/lib/rules/declaration-colon-space-after/__tests__/index.js deleted file mode 100644 index 7b1bd81467..0000000000 --- a/lib/rules/declaration-colon-space-after/__tests__/index.js +++ /dev/null @@ -1,267 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a { color: pink }', - description: 'space only after', - }, - { - code: 'a { color : pink }', - description: 'space before and after', - }, - { - code: 'a { color\n: pink }', - description: 'newline before and space after', - }, - { - code: 'a { color\r\n: pink }', - description: 'CRLF before and space after', - }, - { - code: '$map:(key:value)', - description: 'SCSS map with no newlines', - }, - { - code: "$list:('value1', 'value2')", - description: 'SCSS lst with no newlines', - }, - { - code: 'a { background: url(data:application/font-woff;...); }', - description: 'data URI', - }, - ], - - reject: [ - { - code: 'a { color :pink; }', - fixed: 'a { color : pink; }', - description: 'no space after', - message: messages.expectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color : pink; }', - fixed: 'a { color : pink; }', - description: 'two spaces after', - message: messages.expectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color :\tpink; }', - fixed: 'a { color : pink; }', - description: 'tab after', - message: messages.expectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color :\npink; }', - fixed: 'a { color : pink; }', - description: 'newline after', - message: messages.expectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color :\r\npink; }', - fixed: 'a { color : pink; }', - description: 'CRLF after', - message: messages.expectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color:pink; }', - fixed: 'a { color: pink; }', - description: 'no space after', - message: messages.expectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color/*comment*/:/*comment*/pink; }', - fixed: 'a { color/*comment*/: /*comment*/pink; }', - description: 'comment', - message: messages.expectedAfter(), - line: 1, - column: 11, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a { color:pink }', - description: 'no space before and after', - }, - { - code: 'a { color :pink }', - description: 'space before and no space after', - }, - { - code: 'a { color\n:pink }', - description: 'newline before and no space after', - }, - { - code: 'a { color\r\n:pink }', - description: 'CRLF before and no space after', - }, - { - code: '$map: (key: value)', - description: 'SCSS map with no newlines', - }, - ], - - reject: [ - { - code: 'a { color : pink; }', - fixed: 'a { color :pink; }', - description: 'space after', - message: messages.rejectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color: pink; }', - fixed: 'a { color:pink; }', - description: 'two spaces after', - message: messages.rejectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color :\tpink; }', - fixed: 'a { color :pink; }', - description: 'tab after', - message: messages.rejectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color :\npink; }', - fixed: 'a { color :pink; }', - description: 'newline after', - message: messages.rejectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color :\r\npink; }', - fixed: 'a { color :pink; }', - description: 'CRLF after', - message: messages.rejectedAfter(), - line: 1, - column: 11, - }, - { - code: 'a { color/*comment*/ : /*comment*/pink; }', - fixed: 'a { color/*comment*/ :/*comment*/pink; }', - description: 'comment', - message: messages.rejectedAfter(), - line: 1, - column: 11, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: 'a { color: pink }', - description: 'space only after single-line', - }, - { - code: 'a { transition: color 1s,\n\twidth 2s; }', - description: 'space after mult-line', - }, - { - code: 'a { transition:color 1s,\n\twidth 2s; }', - description: 'no space after mult-line', - }, - { - code: 'a { transition:color 1s,\r\n\twidth 2s; }', - description: 'no space after mult-line CRLF', - }, - { - code: 'a { transition:\tcolor 1s,\n\twidth 2s; }', - description: 'tab after mult-line', - }, - ], - - reject: [ - { - code: 'a { color :pink; }', - fixed: 'a { color : pink; }', - description: 'no space after single-line', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 11, - }, - { - code: 'a { color : pink; }', - fixed: 'a { color : pink; }', - description: 'two spaces after single-line', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 11, - }, - { - code: 'a { color :\tpink; }', - fixed: 'a { color : pink; }', - description: 'tab after single-line', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 11, - }, - { - code: 'a { color :\npink; }', - fixed: 'a { color : pink; }', - description: 'newline after single-line', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 11, - }, - { - code: 'a { color :\r\npink; }', - fixed: 'a { color : pink; }', - description: 'CRLF after single-line', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 11, - }, - { - code: 'a { color:pink; }', - fixed: 'a { color: pink; }', - description: 'no space after', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 11, - }, - { - code: 'a { color/*comment*/:/*comment*/pink; }', - fixed: 'a { color/*comment*/: /*comment*/pink; }', - description: 'comment', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 11, - }, - ], -}); diff --git a/lib/rules/declaration-colon-space-after/index.js b/lib/rules/declaration-colon-space-after/index.js deleted file mode 100644 index 93bda5ffc2..0000000000 --- a/lib/rules/declaration-colon-space-after/index.js +++ /dev/null @@ -1,73 +0,0 @@ -'use strict'; - -const declarationColonSpaceChecker = require('../declarationColonSpaceChecker'); -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'declaration-colon-space-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected single space after ":"', - rejectedAfter: () => 'Unexpected whitespace after ":"', - expectedAfterSingleLine: () => 'Expected single space after ":" with a single-line declaration', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/declaration-colon-space-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never', 'always-single-line'], - }); - - if (!validOptions) { - return; - } - - declarationColonSpaceChecker({ - root, - result, - locationChecker: checker.after, - checkedRuleName: ruleName, - fix: context.fix - ? (decl, index) => { - const colonIndex = index - declarationValueIndex(decl); - const between = decl.raws.between; - - if (between == null) throw new Error('`between` must be present'); - - if (primary.startsWith('always')) { - decl.raws.between = - between.slice(0, colonIndex) + between.slice(colonIndex).replace(/^:\s*/, ': '); - - return true; - } - - if (primary === 'never') { - decl.raws.between = - between.slice(0, colonIndex) + between.slice(colonIndex).replace(/^:\s*/, ':'); - - return true; - } - - return false; - } - : null, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/declaration-colon-space-before/README.md b/lib/rules/declaration-colon-space-before/README.md deleted file mode 100644 index 8c07819e45..0000000000 --- a/lib/rules/declaration-colon-space-before/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# declaration-colon-space-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace before the colon of declarations. - - -```css -a { color :pink } -/** ↑ - * The space before this colon */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a single space before the colon. - -The following patterns are considered problems: - - -```css -a { color: pink } -``` - - -```css -a { color:pink } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color : pink } -``` - - -```css -a { color :pink } -``` - -### `"never"` - -There _must never_ be whitespace before the colon. - -The following patterns are considered problems: - - -```css -a { color : pink } -``` - - -```css -a { color :pink } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink } -``` - - -```css -a { color:pink } -``` diff --git a/lib/rules/declaration-colon-space-before/__tests__/index.js b/lib/rules/declaration-colon-space-before/__tests__/index.js deleted file mode 100644 index 77c56596a0..0000000000 --- a/lib/rules/declaration-colon-space-before/__tests__/index.js +++ /dev/null @@ -1,171 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a { color :pink }', - description: 'space only before', - }, - { - code: 'a { color : pink }', - description: 'space before and after', - }, - { - code: 'a { color :\npink }', - description: 'space before and newline after', - }, - { - code: 'a { color :\r\npink }', - description: 'space before and CRLF after', - }, - { - code: '$map:(key:value)', - description: 'SCSS map with no newlines', - }, - { - code: "$list:('value1', 'value2')", - description: 'SCSS list with no newlines', - }, - { - code: 'a { background : url(data:application/font-woff;...); }', - description: 'data URI', - }, - ], - - reject: [ - { - code: 'a { color: pink; }', - fixed: 'a { color : pink; }', - description: 'no space before', - message: messages.expectedBefore(), - line: 1, - column: 11, - }, - { - code: 'a { color : pink; }', - fixed: 'a { color : pink; }', - description: 'two spaces before', - message: messages.expectedBefore(), - line: 1, - column: 11, - }, - { - code: 'a { color\t: pink; }', - fixed: 'a { color : pink; }', - description: 'tab before', - message: messages.expectedBefore(), - line: 1, - column: 11, - }, - { - code: 'a { color\n: pink; }', - fixed: 'a { color : pink; }', - description: 'newline before', - message: messages.expectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a { color\r\n: pink; }', - fixed: 'a { color : pink; }', - description: 'CRLF before', - message: messages.expectedBefore(), - line: 1, - column: 11, - }, - { - code: 'a { color/*comment*/:/*comment*/pink; }', - fixed: 'a { color/*comment*/ :/*comment*/pink; }', - description: 'comment', - message: messages.expectedBefore(), - line: 1, - column: 11, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a { color:pink }', - description: 'no space before and after', - }, - { - code: 'a { color: pink }', - description: 'no space before and space after', - }, - { - code: 'a { color:\npink }', - description: 'no space before and newline after', - }, - { - code: 'a { color:\r\npink }', - description: 'no space before and CRLF after', - }, - { - code: '$map :(key :value)', - description: 'SCSS map with no newlines', - }, - ], - - reject: [ - { - code: 'a { color : pink; }', - fixed: 'a { color: pink; }', - description: 'space before', - message: messages.rejectedBefore(), - line: 1, - column: 11, - }, - { - code: 'a { color : pink; }', - fixed: 'a { color: pink; }', - description: 'two spaces before', - message: messages.rejectedBefore(), - line: 1, - column: 11, - }, - { - code: 'a { color\t: pink; }', - fixed: 'a { color: pink; }', - description: 'tab before', - message: messages.rejectedBefore(), - line: 1, - column: 11, - }, - { - code: 'a { color\n: pink; }', - fixed: 'a { color: pink; }', - description: 'newline before', - message: messages.rejectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a { color\r\n: pink; }', - fixed: 'a { color: pink; }', - description: 'CRLF before', - message: messages.rejectedBefore(), - line: 1, - column: 11, - }, - { - code: 'a { color/*comment*/ :/*comment*/pink; }', - fixed: 'a { color/*comment*/:/*comment*/pink; }', - description: 'comment', - message: messages.rejectedBefore(), - line: 1, - column: 11, - }, - ], -}); diff --git a/lib/rules/declaration-colon-space-before/index.js b/lib/rules/declaration-colon-space-before/index.js deleted file mode 100644 index 38e8966958..0000000000 --- a/lib/rules/declaration-colon-space-before/index.js +++ /dev/null @@ -1,72 +0,0 @@ -'use strict'; - -const declarationColonSpaceChecker = require('../declarationColonSpaceChecker'); -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'declaration-colon-space-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected single space before ":"', - rejectedBefore: () => 'Unexpected whitespace before ":"', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/declaration-colon-space-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - declarationColonSpaceChecker({ - root, - result, - locationChecker: checker.before, - checkedRuleName: ruleName, - fix: context.fix - ? (decl, index) => { - const colonIndex = index - declarationValueIndex(decl); - const between = decl.raws.between; - - if (between == null) throw new Error('`between` must be present'); - - if (primary === 'always') { - decl.raws.between = - between.slice(0, colonIndex).replace(/\s*$/, ' ') + between.slice(colonIndex); - - return true; - } - - if (primary === 'never') { - decl.raws.between = - between.slice(0, colonIndex).replace(/\s*$/, '') + between.slice(colonIndex); - - return true; - } - - return false; - } - : null, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/declaration-empty-line-before/README.md b/lib/rules/declaration-empty-line-before/README.md index 4586f7a210..4f0b369efd 100644 --- a/lib/rules/declaration-empty-line-before/README.md +++ b/lib/rules/declaration-empty-line-before/README.md @@ -15,7 +15,7 @@ a { This rule only applies to standard property declarations. Use the [`custom-property-empty-line-before`](../custom-property-empty-line-before/README.md) rule for custom property declarations. -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. We recommend to enable [`indentation`](../indentation/README.md) rule for better autofixing results with this rule. +The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. ## Options diff --git a/lib/rules/declarationBangSpaceChecker.js b/lib/rules/declarationBangSpaceChecker.js deleted file mode 100644 index ad17cd22ff..0000000000 --- a/lib/rules/declarationBangSpaceChecker.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; - -const declarationValueIndex = require('../utils/declarationValueIndex'); -const report = require('../utils/report'); -const styleSearch = require('style-search'); - -/** @typedef {import('postcss').Declaration} Declaration */ - -/** @typedef {(args: { source: string, index: number, err: (message: string) => void }) => void} LocationChecker */ - -/** - * @param {{ - * root: import('postcss').Root, - * locationChecker: LocationChecker, - * result: import('stylelint').PostcssResult, - * checkedRuleName: string, - * fix: ((decl: Declaration, index: number) => boolean) | null, - * }} opts - * @returns {void} - */ -module.exports = function declarationBangSpaceChecker(opts) { - opts.root.walkDecls((decl) => { - const indexOffset = declarationValueIndex(decl); - const declString = decl.toString(); - const valueString = decl.toString().slice(indexOffset); - - if (!valueString.includes('!')) { - return; - } - - styleSearch({ source: valueString, target: '!' }, (match) => { - check(declString, match.startIndex + indexOffset, decl); - }); - }); - - /** - * @param {string} source - * @param {number} index - * @param {Declaration} decl - */ - function check(source, index, decl) { - opts.locationChecker({ - source, - index, - err: (message) => { - if (opts.fix && opts.fix(decl, index)) { - return; - } - - report({ - message, - node: decl, - index, - result: opts.result, - ruleName: opts.checkedRuleName, - }); - }, - }); - } -}; diff --git a/lib/rules/declarationColonSpaceChecker.js b/lib/rules/declarationColonSpaceChecker.js deleted file mode 100644 index 1f84e1d300..0000000000 --- a/lib/rules/declarationColonSpaceChecker.js +++ /dev/null @@ -1,57 +0,0 @@ -'use strict'; - -const declarationValueIndex = require('../utils/declarationValueIndex'); -const isStandardSyntaxDeclaration = require('../utils/isStandardSyntaxDeclaration'); -const report = require('../utils/report'); - -/** @typedef {(args: { source: string, index: number, lineCheckStr: string, err: (message: string) => void }) => void} LocationChecker */ - -/** - * @param {{ - * root: import('postcss').Root, - * locationChecker: LocationChecker, - * fix: ((decl: import('postcss').Declaration, index: number) => boolean) | null, - * result: import('stylelint').PostcssResult, - * checkedRuleName: string, - * }} opts - */ -module.exports = function declarationColonSpaceChecker(opts) { - opts.root.walkDecls((decl) => { - if (!isStandardSyntaxDeclaration(decl)) { - return; - } - - // Get the raw prop, and only the prop - const endOfPropIndex = declarationValueIndex(decl) + (decl.raws.between || '').length - 1; - - // The extra characters tacked onto the end ensure that there is a character to check - // after the colon. Otherwise, with `background:pink` the character after the - const propPlusColon = `${decl.toString().slice(0, endOfPropIndex)}xxx`; - - for (let i = 0, l = propPlusColon.length; i < l; i++) { - if (propPlusColon[i] !== ':') { - continue; - } - - opts.locationChecker({ - source: propPlusColon, - index: i, - lineCheckStr: decl.value, - err: (message) => { - if (opts.fix && opts.fix(decl, i)) { - return; - } - - report({ - message, - node: decl, - index: decl.prop.toString().length + 1, - result: opts.result, - ruleName: opts.checkedRuleName, - }); - }, - }); - break; - } - }); -}; diff --git a/lib/rules/findMediaOperator.js b/lib/rules/findMediaOperator.js deleted file mode 100644 index 698ea8b0be..0000000000 --- a/lib/rules/findMediaOperator.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -const styleSearch = require('style-search'); - -const rangeOperators = ['>=', '<=', '>', '<', '=']; - -/** @typedef {import('style-search').StyleSearchMatch} StyleSearchMatch */ - -/** - * @template {import('postcss').AtRule} T - * @param {T} atRule - * @param {(match: StyleSearchMatch, params: string, atRule: T) => void} cb - */ -module.exports = function findMediaOperator(atRule, cb) { - if (atRule.name.toLowerCase() !== 'media') { - return; - } - - const params = atRule.raws.params ? atRule.raws.params.raw : atRule.params; - - styleSearch({ source: params, target: rangeOperators }, (match) => { - const before = params[match.startIndex - 1]; - - if (before === '>' || before === '<') { - return; - } - - cb(match, params, atRule); - }); -}; diff --git a/lib/rules/function-comma-newline-after/README.md b/lib/rules/function-comma-newline-after/README.md deleted file mode 100644 index 75b4e7b2ab..0000000000 --- a/lib/rules/function-comma-newline-after/README.md +++ /dev/null @@ -1,115 +0,0 @@ -# function-comma-newline-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline or disallow whitespace after the commas of functions. - - -```css -a { transform: translate(1, - 1) } /* ↑ */ -/** ↑ - * These commas */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a newline after the commas. - -The following patterns are considered problems: - - -```css -a { transform: translate(1,1) } -``` - - -```css -a { transform: translate(1 ,1) } -``` - - -```css -a { transform: translate(1 - ,1) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { - transform: translate(1, - 1) -} -``` - -### `"always-multi-line"` - -There _must always_ be a newline after the commas in multi-line functions. - -The following patterns are considered problems: - - -```css -a { transform: translate(1 - ,1) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1,1) } -``` - - -```css -a { transform: translate(1 ,1) } -``` - - -```css -a { - transform: translate(1, - 1) -} -``` - -### `"never-multi-line"` - -There _must never_ be whitespace after the commas in multi-line functions. - -The following patterns are considered problems: - - -```css -a { transform: translate(1 - , 1) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1, 1) } -``` - - -```css -a { transform: translate(1 , 1) } -``` - - -```css -a { - transform: translate(1 - ,1) -} -``` diff --git a/lib/rules/function-comma-newline-after/__tests__/index.js b/lib/rules/function-comma-newline-after/__tests__/index.js deleted file mode 100644 index 2c370dafd1..0000000000 --- a/lib/rules/function-comma-newline-after/__tests__/index.js +++ /dev/null @@ -1,432 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a::before { content: "func(foo, bar, baz)"; }', - }, - { - code: "a::before { background: url('func(foo,bar,baz)'); }", - }, - { - code: 'a { background-size: 0,\n 0,\n 0; }', - }, - { - code: 'a { transform: translate(1 ,\n1); }', - }, - { - code: 'a { transform: translate(1 ,\n\n1); }', - }, - { - code: 'a { transform: translate(\n 1,\n 1\n); }', - }, - { - code: 'a { transform: translate(1,\r\n1); }', - description: 'CRLF', - }, - { - code: 'a { transform: translate(1,\r\n\r\n1); }', - description: 'CRLF', - }, - { - code: 'a { transform: color(rgb(0 ,\n\t0,\n\t0) lightness(50%)); }', - }, - { - code: 'a { background: linear-gradient(45deg,\n rgba(0,\n 0,\n 0,\n 1),\n red); }', - }, - { - code: ` - a { - transform: translate( - 1px, /* comment */ - 1px - ); - } - `, - description: 'eol comments', - }, - ], - - reject: [ - { - code: 'a { transform: translate(1,1); }', - fixed: 'a { transform: translate(1,\n1); }', - message: messages.expectedAfter(), - line: 1, - column: 27, - }, - { - code: 'a { transform: translate(1, 1); }', - fixed: 'a { transform: translate(1,\n1); }', - message: messages.expectedAfter(), - line: 1, - column: 27, - }, - { - code: 'a { transform: translate(1, 1); }', - fixed: 'a { transform: translate(1,\n1); }', - message: messages.expectedAfter(), - line: 1, - column: 27, - }, - { - code: 'a\r\n{ transform: translate(1, 1); }', - fixed: 'a\r\n{ transform: translate(1,\r\n1); }', - description: 'CRLF', - message: messages.expectedAfter(), - line: 2, - column: 25, - }, - { - code: 'a { transform: translate(1,\t1); }', - fixed: 'a { transform: translate(1,\n1); }', - message: messages.expectedAfter(), - line: 1, - column: 27, - }, - { - code: 'a { transform: color(rgb(0 , 0 ,\n0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0 ,\n0 ,\n0) lightness(50%)); }', - message: messages.expectedAfter(), - line: 1, - column: 28, - }, - { - code: 'a { transform: color(lightness(50%) rgb(0 ,\n 0 ,0)); }', - fixed: 'a { transform: color(lightness(50%) rgb(0 ,\n 0 ,\n0)); }', - message: messages.expectedAfter(), - line: 2, - column: 4, - }, - { - code: 'a { background: linear-gradient(45deg,\n rgba(0,\n 0, 0,\n 1),\n red); }', - fixed: 'a { background: linear-gradient(45deg,\n rgba(0,\n 0,\n0,\n 1),\n red); }', - message: messages.expectedAfter(), - line: 3, - column: 3, - }, - { - code: 'a { transform: translate(\n 1,1\n); }', - fixed: 'a { transform: translate(\n 1,\n1\n); }', - message: messages.expectedAfter(), - line: 2, - column: 4, - }, - { - code: - 'a {\n transform: translate(\n 1px, /* comment (with trailing space) */ \n' + - ' 1px\n );\n}', - fixed: - 'a {\n transform: translate(\n 1px,\n/* comment (with trailing space) */ \n' + - ' 1px\n );\n}', - description: 'eol comments', - message: messages.expectedAfter(), - }, - ], -}); - -testRule({ - ruleName, - config: ['always'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: '$map: (key: value, key2: value2)', - description: 'sass map ignored', - }, - { - code: '$list: (value, value2)', - description: 'sass list ignored', - }, - { - code: ` - a { - transform: translate( - 1px, // line comment - 1px - ); - } - `, - description: 'eol comments', - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: 'a::before { content: "func(foo, bar, baz)"; }', - }, - { - code: "a::before { background: url('func(foo,bar,baz)'); }", - }, - { - code: 'a { background-size: 0,\n 0,\n 0; }', - }, - { - code: 'a { transform: translate(1 ,\n1); }', - }, - { - code: 'a { transform: translate(1,\r\n1); }', - description: 'CRLF', - }, - { - code: 'a { transform: color(rgb(0 ,\n\t0,\n\t0) lightness(50%)); }', - }, - { - code: 'a { transform: translate(1,1); }', - }, - { - code: 'a { transform: translate(1, 1); }', - }, - { - code: 'a { transform: translate(1, 1); }', - }, - { - code: 'a { transform: translate(1,\t1); }', - }, - { - code: 'a {\r\n transform:\r\n translate(1,1)\r\n scale(3);\r\n}', - description: 'CRLF', - }, - { - code: ` - .foo { - box-shadow: - inset 0 8px 8px -8px rgba(0, 0, 0, 1) - inset 0 -10px 12px 0 #f00; - } - `, - }, - { - code: ` - .foo { - background-image: - repeating-linear-gradient( - -45deg, - transparent, - rgba(0, 0, 0, 1) 5px - ); - } - `, - }, - { - code: ` - a { - transform: translate( - 1px, /* comment */ - 1px - ); - } - `, - description: 'eol comments', - }, - ], - - reject: [ - { - code: 'a { transform: color(rgb(0 , 0 ,\n0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0 ,\n0 ,\n0) lightness(50%)); }', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 28, - }, - { - code: 'a\r\n{ transform: color(rgb(0 , 0 ,\r\n0) lightness(50%)); }', - fixed: 'a\r\n{ transform: color(rgb(0 ,\r\n0 ,\r\n0) lightness(50%)); }', - description: 'CRLF', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 26, - }, - { - code: 'a { transform: color(lightness(50%) rgb(0 ,\n 0 ,0)); }', - fixed: 'a { transform: color(lightness(50%) rgb(0 ,\n 0 ,\n0)); }', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 4, - }, - { - code: 'a { background-image: repeating-linear-gradient(\n-45deg,\ntransparent, rgba(0, 0, 0, 1) 5px\n);}', - fixed: - 'a { background-image: repeating-linear-gradient(\n-45deg,\ntransparent,\nrgba(0, 0, 0, 1) 5px\n);}', - message: messages.expectedAfterMultiLine(), - line: 3, - column: 12, - }, - { - code: 'a { background: linear-gradient(45deg,rgba(0,\n0 ,\n 0 ,\n 1)); }', - fixed: 'a { background: linear-gradient(45deg,\nrgba(0,\n0 ,\n 0 ,\n 1)); }', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 38, - }, - { - code: 'a { transform: translate(\n 1,1\n); }', - fixed: 'a { transform: translate(\n 1,\n1\n); }', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 4, - }, - { - code: - 'a {\n transform: translate(\n 1px, /* comment (with trailing space) */ \n' + - ' 1px\n );\n}', - fixed: - 'a {\n transform: translate(\n 1px,\n/* comment (with trailing space) */ \n' + - ' 1px\n );\n}', - description: 'eol comments', - message: messages.expectedAfterMultiLine(), - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: '$map: (key: value\n, key2: value2)', - description: 'sass map', - }, - { - code: ` - a { - transform: translate( - 1px, // line comment - 1px - ); - } - `, - description: 'eol comments', - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - fix: true, - - accept: [ - { - code: 'a::before { content: "func(foo,\n bar,\n baz)"; }', - }, - { - code: "a::before { background: url('func(foo,\nbar,\nbaz)'); }", - }, - { - code: 'a { background-size: 0\n, 0\n, 0; }', - }, - { - code: 'a { transform: translate(1\r\n,1); }', - description: 'CRLF', - }, - { - code: 'a { transform: color(rgb(0\n\t,0\n\t,0) lightness(50%)); }', - }, - { - code: 'a { transform: translate(1,1); }', - }, - { - code: 'a { transform: translate(1, 1); }', - }, - { - code: 'a { transform: translate(1, 1); }', - }, - { - code: 'a { transform: translate(1,\t1); }', - }, - { - code: 'a { background: linear-gradient(45deg\n,rgba(0, 0, 0, 1),red); }', - }, - { - code: ` - a { - transform: translate(1px, 1px); /* comment */ - } - `, - description: 'eol comments', - }, - ], - - reject: [ - { - code: 'a { transform: color(rgb(0 ,0 ,\n0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0 ,0 ,0) lightness(50%)); }', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 31, - }, - { - code: 'a { transform: color(rgb(0 ,0 ,\r\n0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0 ,0 ,0) lightness(50%)); }', - description: 'CRLF', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 31, - }, - { - code: 'a { transform: color(lightness(50%) rgb(0 ,\n 0 ,0)); }', - fixed: 'a { transform: color(lightness(50%) rgb(0 ,0 ,0)); }', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 43, - }, - { - code: 'a { transform: color(rgb(0\n,0 ,\n0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0\n,0 ,0) lightness(50%)); }', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 4, - }, - { - code: 'a { transform: color(lightness(50%) rgb(0 ,\n 0\n,0)); }', - fixed: 'a { transform: color(lightness(50%) rgb(0 ,0\n,0)); }', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 43, - }, - { - code: 'a { background: linear-gradient(45deg\n,rgba(0,0 , 0, 1), red); }', - fixed: 'a { background: linear-gradient(45deg\n,rgba(0,0 , 0, 1),red); }', - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 18, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: '$map: (key: value,\nkey2: value2)', - description: 'sass map', - }, - { - code: ` - a { - transform: translate(1px, 1px); // line comment - } - `, - description: 'eol comments', - }, - ], -}); diff --git a/lib/rules/function-comma-newline-after/index.js b/lib/rules/function-comma-newline-after/index.js deleted file mode 100644 index 1852dc22c4..0000000000 --- a/lib/rules/function-comma-newline-after/index.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; - -const fixer = require('../functionCommaSpaceFix'); -const functionCommaSpaceChecker = require('../functionCommaSpaceChecker'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'function-comma-newline-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected newline after ","', - expectedAfterMultiLine: () => 'Expected newline after "," in a multi-line function', - rejectedAfterMultiLine: () => 'Unexpected whitespace after "," in a multi-line function', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/function-comma-newline-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('newline', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'always-multi-line', 'never-multi-line'], - }); - - if (!validOptions) { - return; - } - - functionCommaSpaceChecker({ - root, - result, - locationChecker: checker.afterOneOnly, - checkedRuleName: ruleName, - fix: context.fix - ? (div, index, nodes) => - fixer({ - div, - index, - nodes, - expectation: primary, - position: 'after', - symb: context.newline || '', - }) - : null, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/function-comma-newline-before/README.md b/lib/rules/function-comma-newline-before/README.md deleted file mode 100644 index 091b274065..0000000000 --- a/lib/rules/function-comma-newline-before/README.md +++ /dev/null @@ -1,131 +0,0 @@ -# function-comma-newline-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline or disallow whitespace before the commas of functions. - - -```css - a { transform: translate(1 - , 1) } -/** ↑ - * This comma */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a newline before the commas. - -The following patterns are considered problems: - - -```css -a { transform: translate(1,1) } -``` - - -```css -a { transform: translate(1 ,1) } -``` - - -```css -a { transform: translate(1, - 1) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { - transform: translate(1 - ,1) -} -``` - - -```css -a { - transform: translate(1 - , 1) -} -``` - -### `"always-multi-line"` - -There _must always_ be a newline before the commas in multi-line functions. - -The following patterns are considered problems: - - -```css -a { transform: translate(1, - 1) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1,1) } -``` - - -```css -a { transform: translate(1 ,1) } -``` - - -```css -a { - transform: translate(1 - ,1) -} -``` - - -```css -a { - transform: translate(1 - , 1) -} -``` - -### `"never-multi-line"` - -There _must never_ be whitespace before the commas in multi-line functions. - -The following patterns are considered problems: - - -```css -a { transform: translate(1 , - 1) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1 ,1) } -``` - - -```css -a { transform: translate(1 , 1) } -``` - - -```css -a { - transform: translate(1, - 1) -} -``` diff --git a/lib/rules/function-comma-newline-before/__tests__/index.js b/lib/rules/function-comma-newline-before/__tests__/index.js deleted file mode 100644 index 107f8865fa..0000000000 --- a/lib/rules/function-comma-newline-before/__tests__/index.js +++ /dev/null @@ -1,320 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a::before { content: "func(foo ,bar ,baz)"; }', - }, - { - code: "a::before { background: url('func(foo,bar,baz)'); }", - }, - { - code: 'a { background-size: 0\n, 0\n, 0; }', - }, - { - code: 'a { transform: translate(1\n,1); }', - }, - { - code: 'a { transform: translate(1\r\n, 1); }', - description: 'CRLF', - }, - { - code: 'a { transform: translate(1\n\n,1); }', - }, - { - code: 'a { transform: translate(1\r\n\r\n, 1); }', - description: 'CRLF', - }, - { - code: 'a { transform: color(rgb(0\n\t, 0\n\t,0) lightness(50%)); }', - }, - { - code: 'a { transform: color(rgb(0\n , 0\n ,0) lightness(50%)); }', - }, - { - code: ` - a { - transform: translate( - 1px /* comment */ - ,1px - ); - } - `, - description: 'eol comments', - }, - ], - - reject: [ - { - code: 'a { transform: translate(1,1); }', - fixed: 'a { transform: translate(1\n,1); }', - message: messages.expectedBefore(), - line: 1, - column: 27, - }, - { - code: 'a\r\n{ transform: translate(1,1); }', - fixed: 'a\r\n{ transform: translate(1\r\n,1); }', - description: 'CRLF', - message: messages.expectedBefore(), - line: 2, - column: 25, - }, - { - code: 'a { transform: translate(1 ,1); }', - fixed: 'a { transform: translate(1\n,1); }', - message: messages.expectedBefore(), - line: 1, - column: 29, - }, - { - code: 'a { transform: translate(1 ,1); }', - fixed: 'a { transform: translate(1\n,1); }', - message: messages.expectedBefore(), - line: 1, - column: 28, - }, - { - code: 'a { transform: translate(1\t,1); }', - fixed: 'a { transform: translate(1\n,1); }', - message: messages.expectedBefore(), - line: 1, - column: 28, - }, - { - code: 'a { transform: color(rgb(0 , 0 \n,0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0\n, 0 \n,0) lightness(50%)); }', - message: messages.expectedBefore(), - line: 1, - column: 28, - }, - { - code: 'a { transform: color(lightness(50%) rgb(0\n, 0,0)); }', - fixed: 'a { transform: color(lightness(50%) rgb(0\n, 0\n,0)); }', - message: messages.expectedBefore(), - line: 2, - column: 4, - }, - ], -}); - -testRule({ - ruleName, - config: ['always'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: '$map: (key: value, key2: value2)', - description: 'Sass map ignored', - }, - { - code: '$list: (value, value2)', - description: 'Sass list ignored', - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: 'a::before { content: "func(foo ,bar ,baz)"; }', - }, - { - code: "a::before { background: url('func(foo,bar,baz)'); }", - }, - { - code: 'a { background-size: 0\n, 0\n, 0; }', - }, - { - code: 'a { transform: translate(1\n,1); }', - }, - { - code: 'a { transform: translate(1\r\n, 1); }', - description: 'CRLF', - }, - { - code: 'a { transform: color(rgb(0\n\t, 0\n\t,0) lightness(50%)); }', - }, - { - code: 'a { transform: color(rgb(0\n , 0\n ,0) lightness(50%)); }', - }, - { - code: 'a { transform: translate(1,1); }', - }, - { - code: 'a { transform: translate(1 ,1); }', - }, - { - code: 'a { transform: translate(1 , 1); }', - }, - { - code: 'a { transform: translate(1\t,1); }', - }, - { - code: 'a { background: linear-gradient(45deg\n, rgba(0, 0, 0, 1)\n, red); }', - }, - { - code: ` - a { - transform: translate( - 1px /* comment */ - ,1px - ); - } - `, - description: 'eol comments', - }, - ], - - reject: [ - { - code: 'a { transform: color(rgb(0\n, 0, 0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0\n, 0\n, 0) lightness(50%)); }', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 4, - }, - { - code: 'a { transform: color(rgb(0\r\n, 0, 0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0\r\n, 0\r\n, 0) lightness(50%)); }', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 4, - }, - { - code: 'a { transform: color(lightness(50%) rgb(0,0\n,0)); }', - fixed: 'a { transform: color(lightness(50%) rgb(0\n,0\n,0)); }', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 42, - }, - { - code: 'a { background: linear-gradient(45deg\n, rgba(0\n, 0, 0\n, 1)\n, red); }', - fixed: 'a { background: linear-gradient(45deg\n, rgba(0\n, 0\n, 0\n, 1)\n, red); }', - message: messages.expectedBeforeMultiLine(), - line: 3, - column: 4, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: '$map: (key: value,\nkey2: value2)', - description: 'SCSS map', - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - fix: true, - - accept: [ - { - code: 'a::before { content: "func(foo\n,bar\n,baz)"; }', - }, - { - code: "a::before { background: url('func(foo\n,bar,baz)'); }", - }, - { - code: 'a { transform: translate(1,1); }', - }, - { - code: 'a { transform: translate(1 ,1); }', - }, - { - code: 'a { transform: translate(1 , 1); }', - }, - { - code: 'a { transform: translate(1\t,1); }', - }, - ], - - reject: [ - { - code: 'a { transform: color(rgb(0,0\n,0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0,0,0) lightness(50%)); }', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 1, - }, - { - code: 'a { transform: color(rgb(0,0\r\n,0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0,0,0) lightness(50%)); }', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 1, - }, - { - code: 'a { transform: color(lightness(50%) rgb(0\n, 0, 0)); }', - fixed: 'a { transform: color(lightness(50%) rgb(0, 0, 0)); }', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 1, - }, - { - code: 'a { transform: color(rgb(0\n,0,\n0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0,0,\n0) lightness(50%)); }', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 1, - }, - { - code: 'a { transform: color(lightness(50%) rgb(0,\n 0\n,0)); }', - fixed: 'a { transform: color(lightness(50%) rgb(0,\n 0,0)); }', - message: messages.rejectedBeforeMultiLine(), - line: 3, - column: 1, - }, - { - code: ` - a { - transform: translate( - 1px /* comment */ - , 1px - ); - } - `, - fixed: ` - a { - transform: translate( - 1px /* comment */, 1px - ); - } - `, - description: 'eol comments', - message: messages.rejectedBeforeMultiLine(), - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: '$map: (key: value\n,key2: value2)', - description: 'SCSS map', - }, - ], -}); diff --git a/lib/rules/function-comma-newline-before/index.js b/lib/rules/function-comma-newline-before/index.js deleted file mode 100644 index a94d55bfd3..0000000000 --- a/lib/rules/function-comma-newline-before/index.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; - -const fixer = require('../functionCommaSpaceFix'); -const functionCommaSpaceChecker = require('../functionCommaSpaceChecker'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'function-comma-newline-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected newline before ","', - expectedBeforeMultiLine: () => 'Expected newline before "," in a multi-line function', - rejectedBeforeMultiLine: () => 'Unexpected whitespace before "," in a multi-line function', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/function-comma-newline-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('newline', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'always-multi-line', 'never-multi-line'], - }); - - if (!validOptions) { - return; - } - - functionCommaSpaceChecker({ - root, - result, - locationChecker: checker.beforeAllowingIndentation, - checkedRuleName: ruleName, - fix: context.fix - ? (div, index, nodes) => - fixer({ - div, - index, - nodes, - expectation: primary, - position: 'before', - symb: context.newline || '', - }) - : null, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/function-comma-space-after/README.md b/lib/rules/function-comma-space-after/README.md deleted file mode 100644 index 5f0998fe5d..0000000000 --- a/lib/rules/function-comma-space-after/README.md +++ /dev/null @@ -1,146 +0,0 @@ -# function-comma-space-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace after the commas of functions. - - -```css -a { transform: translate(1, 1) } -/** ↑ - * The space after this comma */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"|"always-single-line"|"never-single-line"` - -### `"always"` - -There _must always_ be a single space after the commas. - -The following patterns are considered problems: - - -```css -a { transform: translate(1,1) } -``` - - -```css -a { transform: translate(1 ,1) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1, 1) } -``` - - -```css -a { transform: translate(1 , 1) } -``` - -### `"never"` - -There _must never_ be whitespace after the commas. - -The following patterns are considered problems: - - -```css -a { transform: translate(1, 1) } -``` - - -```css -a { transform: translate(1 , 1) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1,1) } -``` - - -```css -a { transform: translate(1 ,1) } -``` - -### `"always-single-line"` - -There _must always_ be a single space after the commas in single-line functions. - -The following patterns are considered problems: - - -```css -a { transform: translate(1,1) } -``` - - -```css -a { transform: translate(1 ,1) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1, 1) } -``` - - -```css -a { transform: translate(1 , 1) } -``` - - -```css -a { - transform: translate(1 - ,1) -} -``` - -### `"never-single-line"` - -There _must never_ be whitespace after the commas in single-line functions. - -The following patterns are considered problems: - - -```css -a { transform: translate(1, 1) } -``` - - -```css -a { transform: translate(1 , 1) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1,1) } -``` - - -```css -a { transform: translate(1 ,1) } -``` - - -```css -a { - transform: translate(1 - , 1) -} -``` diff --git a/lib/rules/function-comma-space-after/__tests__/index.js b/lib/rules/function-comma-space-after/__tests__/index.js deleted file mode 100644 index 9f5af35546..0000000000 --- a/lib/rules/function-comma-space-after/__tests__/index.js +++ /dev/null @@ -1,480 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a::before { content: "func(foo,bar,baz)"; }', - }, - { - code: "a::before { background: url('func(foo,bar,baz)'); }", - }, - { - code: 'a { background-size: 0,0,0; }', - }, - { - code: 'a { transform: translate(1 , 1); }', - }, - { - code: 'a { transform: translate(1, 1); }', - }, - { - code: 'a { transform: color(rgb(0 , 0, 0) lightness(50%)); }', - }, - { - code: 'a { background: url(data:image/svg+xml;charset=utf8,%3Csvg%20xmlns); }', - description: 'data URI with spaceless comma', - }, - { - code: 'a { transform: translate(1, /* comment */1); }', - description: 'comments', - }, - ], - - reject: [ - { - code: 'a { transform: translate(1,1); }', - fixed: 'a { transform: translate(1, 1); }', - message: messages.expectedAfter(), - line: 1, - column: 27, - }, - { - code: 'a { transform: translate(1, 1); }', - fixed: 'a { transform: translate(1, 1); }', - message: messages.expectedAfter(), - line: 1, - column: 27, - }, - { - code: 'a { transform: translate(1,\n1); }', - fixed: 'a { transform: translate(1, 1); }', - message: messages.expectedAfter(), - line: 1, - column: 27, - }, - { - code: 'a { transform: translate(1,\r\n1); }', - fixed: 'a { transform: translate(1, 1); }', - description: 'CRLF', - message: messages.expectedAfter(), - line: 1, - column: 27, - }, - { - code: 'a { transform: translate(1,\t1); }', - fixed: 'a { transform: translate(1, 1); }', - message: messages.expectedAfter(), - line: 1, - column: 27, - }, - { - code: 'a { transform: color(rgb(0 , 0 ,0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0 , 0 , 0) lightness(50%)); }', - message: messages.expectedAfter(), - line: 1, - column: 32, - }, - { - code: 'a { transform: color(lightness(50%) rgb(0 , 0 ,0)); }', - fixed: 'a { transform: color(lightness(50%) rgb(0 , 0 , 0)); }', - message: messages.expectedAfter(), - line: 1, - column: 47, - }, - { - code: 'a { transform: translate(1,/* comment */1); }', - fixed: 'a { transform: translate(1, /* comment */1); }', - description: 'comments', - message: messages.expectedAfter(), - }, - { - code: 'a { color: rgba(0,0,0,0); }', - fixed: 'a { color: rgba(0, 0, 0, 0); }', - warnings: [ - { - message: messages.expectedAfter(), - line: 1, - column: 18, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 20, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 22, - }, - ], - }, - { - code: 'a { background: linear-gradient(45deg,rgba(0,0,0,1),red); }', - fixed: 'a { background: linear-gradient(45deg, rgba(0, 0, 0, 1), red); }', - warnings: [ - { - message: messages.expectedAfter(), - line: 1, - column: 38, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 52, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 45, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 47, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 49, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['always'], - customSyntax: 'postcss-scss', - fix: true, - - accept: [ - { - code: '$map: (key: value,key2: value2)', - description: 'Sass map ignored', - }, - { - code: '$list: (value,value2)', - description: 'Sass list ignored', - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a::before { content: "func(foo, bar, baz)"; }', - }, - { - code: "a::before { background: url('func(foo, bar, baz)'); }", - }, - { - code: 'a { background-size: 0, 0, 0; }', - }, - { - code: 'a { transform: translate(1 ,1); }', - }, - { - code: 'a { transform: translate(1,1); }', - }, - { - code: 'a { transform: color(rgb(0 ,0,0) lightness(50%)); }', - }, - { - code: 'a { transform: translate(1,/* comment */1); }', - description: 'comments', - }, - ], - - reject: [ - { - code: 'a { transform: translate(1, 1); }', - fixed: 'a { transform: translate(1,1); }', - message: messages.rejectedAfter(), - line: 1, - column: 27, - }, - { - code: 'a { transform: translate(1, 1); }', - fixed: 'a { transform: translate(1,1); }', - message: messages.rejectedAfter(), - line: 1, - column: 27, - }, - { - code: 'a { transform: translate(1,\n1); }', - fixed: 'a { transform: translate(1,1); }', - message: messages.rejectedAfter(), - line: 1, - column: 27, - }, - { - code: 'a { transform: translate(1,\r\n1); }', - fixed: 'a { transform: translate(1,1); }', - description: 'CRLF', - message: messages.rejectedAfter(), - line: 1, - column: 27, - }, - { - code: 'a { transform: translate(1,\t1); }', - fixed: 'a { transform: translate(1,1); }', - message: messages.rejectedAfter(), - line: 1, - column: 27, - }, - { - code: 'a { transform: color(rgb(0 , 0 ,0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0 ,0 ,0) lightness(50%)); }', - message: messages.rejectedAfter(), - line: 1, - column: 28, - }, - { - code: 'a { transform: lightness(50%) color(rgb(0 , 0 ,0) ); }', - fixed: 'a { transform: lightness(50%) color(rgb(0 ,0 ,0) ); }', - message: messages.rejectedAfter(), - line: 1, - column: 43, - }, - { - code: 'a { transform: translate(1, /* comment */1); }', - fixed: 'a { transform: translate(1,/* comment */1); }', - description: 'comments', - message: messages.rejectedAfter(), - }, - { - code: 'a { transform: translate(1, /* comment */ 1); }', - fixed: 'a { transform: translate(1,/* comment */1); }', - description: 'comments', - message: messages.rejectedAfter(), - }, - { - code: 'a { transform: translate(1, /* 1 */\n/* 2 */ /* 3 */ 1); }', - fixed: 'a { transform: translate(1,/* 1 *//* 2 *//* 3 */1); }', - description: 'comments', - message: messages.rejectedAfter(), - }, - { - code: 'a { background: linear-gradient(45deg , rgba(0 , 0 , 0 , 1) , red); }', - fixed: 'a { background: linear-gradient(45deg ,rgba(0 ,0 ,0 ,1) ,red); }', - warnings: [ - { - message: messages.rejectedAfter(), - line: 1, - column: 39, - }, - { - message: messages.rejectedAfter(), - line: 1, - column: 61, - }, - { - message: messages.rejectedAfter(), - line: 1, - column: 48, - }, - { - message: messages.rejectedAfter(), - line: 1, - column: 52, - }, - { - message: messages.rejectedAfter(), - line: 1, - column: 56, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: '$map: (key: value, key2: value2)', - description: 'SCSS map', - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: 'a::before { content: "func(foo,bar,baz)"; }', - }, - { - code: "a::before { background: url('func(foo,bar,baz)'); }", - }, - { - code: 'a { background-size: 0,0,0; }', - }, - { - code: 'a { transform: translate(1 , 1); }', - }, - { - code: 'a { transform: translate(1, 1); }', - }, - { - code: 'a { transform: color(rgb(0 , 0, 0) lightness(50%)); }', - }, - { - code: 'a { transform: translate(1,\n1); }', - }, - { - code: 'a { transform: translate(1\n,1); }', - }, - { - code: 'a { transform: translate(1,\r\n1); }', - description: 'CRLF', - }, - { - code: 'a { color: rgba(0,0\n,0); }', - description: 'CRLF', - }, - { - code: 'a { color: rgba(0\n,0,0); }', - description: 'CRLF', - }, - { - code: 'a { background: linear-gradient(45deg\n,rgba(0, 0, 0, 1)\n,red); }', - }, - ], - - reject: [ - { - code: 'a { transform: color(rgb(0 , 0 ,0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0 , 0 , 0) lightness(50%)); }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 32, - }, - { - code: 'a { transform: color(lightness(50%) rgb(0 , 0 ,0)); }', - fixed: 'a { transform: color(lightness(50%) rgb(0 , 0 , 0)); }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 47, - }, - { - code: 'a { background: linear-gradient(45deg\n,rgba(0, 0,0, 1),red); }', - fixed: 'a { background: linear-gradient(45deg\n,rgba(0, 0, 0, 1),red); }', - message: messages.expectedAfterSingleLine(), - line: 2, - column: 11, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: '$map: (key: value,key2: value2)', - description: 'SCSS map', - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - fix: true, - - accept: [ - { - code: 'a::before { content: "func(foo, bar, baz)"; }', - }, - { - code: "a::before { background: url('func(foo, bar, baz)'); }", - }, - { - code: 'a { background-size: 0, 0, 0; }', - }, - { - code: 'a { transform: translate(1 ,1); }', - }, - { - code: 'a { transform: translate(1,1); }', - }, - { - code: 'a { transform: color(rgb(0 ,0,0) lightness(50%)); }', - }, - { - code: 'a { transform: translate(1,\n1); }', - }, - { - code: 'a { transform: translate(1\n, 1); }', - }, - { - code: 'a { transform: translate(1\r\n, 1); }', - description: 'CRLF', - }, - { - code: 'a { color: rgba(0, 0\n, 0); }', - description: 'CRLF', - }, - { - code: 'a { color: rgba(0\n, 0, 0); }', - description: 'CRLF', - }, - ], - - reject: [ - { - code: 'a { transform: color(rgb(0 , 0 ,0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0 ,0 ,0) lightness(50%)); }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 28, - }, - { - code: 'a { transform: lightness(50%) color(rgb(0 , 0 ,0) ); }', - fixed: 'a { transform: lightness(50%) color(rgb(0 ,0 ,0) ); }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 43, - }, - { - code: 'a { transform: lightness(50%)\ncolor(rgb(0 , 0 ,0) ); }', - fixed: 'a { transform: lightness(50%)\ncolor(rgb(0 ,0 ,0) ); }', - message: messages.rejectedAfterSingleLine(), - line: 2, - column: 13, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: '$map: (key: value, key2: value2)', - description: 'SCSS map', - }, - ], -}); diff --git a/lib/rules/function-comma-space-after/index.js b/lib/rules/function-comma-space-after/index.js deleted file mode 100644 index 3f4d4122cc..0000000000 --- a/lib/rules/function-comma-space-after/index.js +++ /dev/null @@ -1,61 +0,0 @@ -'use strict'; - -const fixer = require('../functionCommaSpaceFix'); -const functionCommaSpaceChecker = require('../functionCommaSpaceChecker'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'function-comma-space-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected single space after ","', - rejectedAfter: () => 'Unexpected whitespace after ","', - expectedAfterSingleLine: () => 'Expected single space after "," in a single-line function', - rejectedAfterSingleLine: () => 'Unexpected whitespace after "," in a single-line function', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/function-comma-space-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never', 'always-single-line', 'never-single-line'], - }); - - if (!validOptions) { - return; - } - - functionCommaSpaceChecker({ - root, - result, - locationChecker: checker.after, - checkedRuleName: ruleName, - fix: context.fix - ? (div, index, nodes) => - fixer({ - div, - index, - nodes, - expectation: primary, - position: 'after', - symb: ' ', - }) - : null, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/function-comma-space-before/README.md b/lib/rules/function-comma-space-before/README.md deleted file mode 100644 index 91c8e9d3c9..0000000000 --- a/lib/rules/function-comma-space-before/README.md +++ /dev/null @@ -1,146 +0,0 @@ -# function-comma-space-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace before the commas of functions. - - -```css -a { transform: translate(1 ,1) } -/** ↑ - * The space before this comma */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"|"always-single-line"|"never-single-line"` - -### `"always"` - -There _must always_ be a single space before the commas. - -The following patterns are considered problems: - - -```css -a { transform: translate(1,1) } -``` - - -```css -a { transform: translate(1, 1) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1 ,1) } -``` - - -```css -a { transform: translate(1 , 1) } -``` - -### `"never"` - -There _must never_ be whitespace before the commas. - -The following patterns are considered problems: - - -```css -a { transform: translate(1 ,1) } -``` - - -```css -a { transform: translate(1 , 1) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1,1) } -``` - - -```css -a { transform: translate(1, 1) } -``` - -### `"always-single-line"` - -There _must always_ be a single space before the commas in single-line functions. - -The following patterns are considered problems: - - -```css -a { transform: translate(1,1) } -``` - - -```css -a { transform: translate(1, 1) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1 ,1) } -``` - - -```css -a { transform: translate(1 , 1) } -``` - - -```css -a { - transform: translate(1, - 1) -} -``` - -### `"never-single-line"` - -There _must never_ be whitespace before the commas in single-line functions. - -The following patterns are considered problems: - - -```css -a { transform: translate(1 ,1) } -``` - - -```css -a { transform: translate(1 , 1) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1,1) } -``` - - -```css -a { transform: translate(1, 1) } -``` - - -```css -a { - transform: translate(1 , - 1) -} -``` diff --git a/lib/rules/function-comma-space-before/__tests__/index.js b/lib/rules/function-comma-space-before/__tests__/index.js deleted file mode 100644 index 14f4987e9c..0000000000 --- a/lib/rules/function-comma-space-before/__tests__/index.js +++ /dev/null @@ -1,386 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a::before { content: "func(foo,bar,baz)"; }', - }, - { - code: "a::before { background: url('func(foo,bar,baz)'); }", - }, - { - code: 'a { background-size: 0, 0, 0; }', - }, - { - code: 'a { transform: translate(1 , 1); }', - }, - { - code: 'a { transform: translate(1 ,1); }', - }, - { - code: 'a { transform: color(rgb(0 , 0 ,0) lightness(50%)); }', - }, - { - code: 'a { background: url(data:image/svg+xml;charset=utf8,%3Csvg%20xmlns); }', - description: 'data URI with spaceless comma', - }, - ], - - reject: [ - { - code: 'a { transform: translate(1, 1); }', - fixed: 'a { transform: translate(1 , 1); }', - message: messages.expectedBefore(), - line: 1, - column: 27, - }, - { - code: 'a { transform: translate(1 , 1); }', - fixed: 'a { transform: translate(1 , 1); }', - message: messages.expectedBefore(), - line: 1, - column: 29, - }, - { - code: 'a { transform: translate(1\n, 1); }', - fixed: 'a { transform: translate(1 , 1); }', - message: messages.expectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a { transform: translate(1\r\n, 1); }', - fixed: 'a { transform: translate(1 , 1); }', - description: 'CRLF', - message: messages.expectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a { transform: translate(1\t, 1); }', - fixed: 'a { transform: translate(1 , 1); }', - message: messages.expectedBefore(), - line: 1, - column: 28, - }, - { - code: 'a { transform: color(rgb(0 , 0, 0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0 , 0 , 0) lightness(50%)); }', - message: messages.expectedBefore(), - line: 1, - column: 31, - }, - { - code: 'a { transform: color(lightness(50%) rgb(0 , 0, 0)); }', - fixed: 'a { transform: color(lightness(50%) rgb(0 , 0 , 0)); }', - message: messages.expectedBefore(), - line: 1, - column: 46, - }, - { - code: ` - a { - transform: translate( - 1px /* comment */ - ,1px - ); - } - `, - fixed: ` - a { - transform: translate( - 1px /* comment */ ,1px - ); - } - `, - description: 'eol comments', - message: messages.expectedBefore(), - }, - ], -}); - -testRule({ - ruleName, - config: ['always'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: '$map: (key: value,key2: value2)', - description: 'Sass map ignored', - }, - { - code: '$list: (value, value2)', - description: 'Sass list ignored', - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a::before { content: "func(foo ,bar ,baz)"; }', - }, - { - code: "a::before { background: url('func(foo ,bar ,baz)'); }", - }, - { - code: 'a { background-size: 0 , 0 , 0; }', - }, - { - code: 'a { transform: translate(1, 1); }', - }, - { - code: 'a { transform: translate(1,1); }', - }, - { - code: 'a { transform: color(rgb(0, 0,0) lightness(50%)); }', - }, - ], - - reject: [ - { - code: 'a { transform: translate(1 , 1); }', - fixed: 'a { transform: translate(1, 1); }', - message: messages.rejectedBefore(), - line: 1, - column: 28, - }, - { - code: 'a { transform: translate(1 , 1); }', - fixed: 'a { transform: translate(1, 1); }', - message: messages.rejectedBefore(), - line: 1, - column: 29, - }, - { - code: 'a { transform: translate(1\n, 1); }', - fixed: 'a { transform: translate(1, 1); }', - message: messages.rejectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a { transform: translate(1\r\n, 1); }', - fixed: 'a { transform: translate(1, 1); }', - description: 'CRLF', - message: messages.rejectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a { transform: translate(1\t, 1); }', - fixed: 'a { transform: translate(1, 1); }', - message: messages.rejectedBefore(), - line: 1, - column: 28, - }, - { - code: 'a { transform: color(rgb(0, 0 , 0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0, 0, 0) lightness(50%)); }', - message: messages.rejectedBefore(), - line: 1, - column: 31, - }, - { - code: 'a { transform: color(lightness(50%) rgb(0, 0 , 0)); }', - fixed: 'a { transform: color(lightness(50%) rgb(0, 0, 0)); }', - message: messages.rejectedBefore(), - line: 1, - column: 46, - }, - { - code: 'a { transform: translate(1 /*comment*/ , 1); }', - fixed: 'a { transform: translate(1 /*comment*/, 1); }', - message: messages.rejectedBefore(), - line: 1, - column: 40, - }, - { - code: 'a { transform: translate(1 /*c*/ /*c*/ , 1); }', - fixed: 'a { transform: translate(1 /*c*/ /*c*/, 1); }', - message: messages.rejectedBefore(), - line: 1, - column: 40, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: '$map: (key: value ,key2: value2)', - description: 'SCSS map', - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: 'a::before { content: "func(foo,bar,baz)"; }', - }, - { - code: "a::before { background: url('func(foo,bar,baz)'); }", - }, - { - code: 'a { background-size: 0, 0, 0; }', - }, - { - code: 'a { transform: translate(1 , 1); }', - }, - { - code: 'a { transform: translate(1 ,1); }', - }, - { - code: 'a { transform: color(rgb(0 , 0 ,0) lightness(50%)); }', - }, - { - code: 'a { transform: translate(1,\n1); }', - }, - { - code: 'a { transform: translate(1 ,\n1); }', - }, - { - code: 'a { transform: translate(1\t,\r\n1); }', - description: 'CRLF', - }, - { - code: 'a { transform: translate(1\n, 1); }', - }, - { - code: 'a { transform: translate(1\n,\n1); }', - }, - { - code: 'a { background: linear-gradient(45deg,\nrgba(0 , 0 , 0 ,1)\n,red); }', - }, - ], - - reject: [ - { - code: 'a { transform: color(rgb(0 , 0, 0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0 , 0 , 0) lightness(50%)); }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 31, - }, - { - code: 'a { transform: color(lightness(50%) rgb(0 , 0, 0)); }', - fixed: 'a { transform: color(lightness(50%) rgb(0 , 0 , 0)); }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 46, - }, - { - code: 'a { background: linear-gradient(45deg,\nrgba(0 , 0,0 ,1),red); }', - fixed: 'a { background: linear-gradient(45deg,\nrgba(0 , 0 ,0 ,1),red); }', - message: messages.expectedBeforeSingleLine(), - line: 2, - column: 11, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: '$map: (key: value,key2: value2)', - description: 'SCSS map', - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - fix: true, - - accept: [ - { - code: 'a::before { content: "func(foo ,bar ,baz)"; }', - }, - { - code: "a::before { background: url('func(foo ,bar ,baz)'); }", - }, - { - code: 'a { background-size: 0 , 0 , 0; }', - }, - { - code: 'a { transform: translate(1, 1); }', - }, - { - code: 'a { transform: translate(1,1); }', - }, - { - code: 'a { transform: color(rgb(0, 0,0) lightness(50%)); }', - }, - { - code: 'a { transform: translate(1 ,\n1); }', - }, - { - code: 'a { transform: translate(1 ,\n1); }', - }, - { - code: 'a { transform: translate(1\t,\r\n1); }', - description: 'CRLF', - }, - { - code: 'a { transform: translate(1\n, 1); }', - }, - { - code: 'a { transform: translate(1\n,\n1); }', - }, - ], - - reject: [ - { - code: 'a { transform: color(rgb(0, 0 , 0) lightness(50%)); }', - fixed: 'a { transform: color(rgb(0, 0, 0) lightness(50%)); }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 31, - }, - { - code: 'a { transform: color(lightness(50%) rgb(0, 0 , 0)); }', - fixed: 'a { transform: color(lightness(50%) rgb(0, 0, 0)); }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 46, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: '$map: (key: value ,key2: value2)', - description: 'SCSS map', - }, - ], -}); diff --git a/lib/rules/function-comma-space-before/index.js b/lib/rules/function-comma-space-before/index.js deleted file mode 100644 index ca97bcc265..0000000000 --- a/lib/rules/function-comma-space-before/index.js +++ /dev/null @@ -1,61 +0,0 @@ -'use strict'; - -const fixer = require('../functionCommaSpaceFix'); -const functionCommaSpaceChecker = require('../functionCommaSpaceChecker'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'function-comma-space-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected single space before ","', - rejectedBefore: () => 'Unexpected whitespace before ","', - expectedBeforeSingleLine: () => 'Expected single space before "," in a single-line function', - rejectedBeforeSingleLine: () => 'Unexpected whitespace before "," in a single-line function', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/function-comma-space-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never', 'always-single-line', 'never-single-line'], - }); - - if (!validOptions) { - return; - } - - functionCommaSpaceChecker({ - root, - result, - locationChecker: checker.before, - checkedRuleName: ruleName, - fix: context.fix - ? (div, index, nodes) => - fixer({ - div, - index, - nodes, - expectation: primary, - position: 'before', - symb: ' ', - }) - : null, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/function-max-empty-lines/README.md b/lib/rules/function-max-empty-lines/README.md deleted file mode 100644 index 4b169c595b..0000000000 --- a/lib/rules/function-max-empty-lines/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# function-max-empty-lines - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Limit the number of adjacent empty lines within functions. - - -```css -a { - transform: - translate( - /* ← */ - 1, /* ↑ */ - /* ← */ - 1 /* ↑ */ - /* ← */ - ); /* ↑ */ -} /* ↑ */ -/** ↑ - * These lines */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`int`: Maximum number of adjacent empty lines allowed. - -For example, with `0`: - -The following patterns are considered problems: - - -```css -a { - transform: - translate( - - 1, - 1 - ); -} -``` - - -```css -a { - transform: - translate( - 1, - - 1 - ); -} -``` - - -```css -a { - transform: - translate( - 1, - 1 - - ); -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { - transform: - translate( - 1, - 1 - ); -} -``` diff --git a/lib/rules/function-max-empty-lines/__tests__/index.js b/lib/rules/function-max-empty-lines/__tests__/index.js deleted file mode 100644 index 441ce23334..0000000000 --- a/lib/rules/function-max-empty-lines/__tests__/index.js +++ /dev/null @@ -1,356 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: [0], - fix: true, - - accept: [ - { - code: 'a { transform: translate(1, 1); }', - }, - { - code: 'a { transform: translate(\n1\n,\n1\n); }', - }, - { - code: 'a { transform: translate(\r\n1\r\n,\r\n1\r\n); }', - }, - { - code: 'a { transform: translate\n\n(1, 1); }', - }, - { - code: 'a { transform: translate\r\n\r\n(1, 1); }', - }, - { - code: 'a { transform: translate(1, 1)\n\n; }', - }, - { - code: 'a { transform: translate(1, 1)\r\n\r\n; }', - }, - { - code: 'a { transform:\n\ntranslate(1, 1); }', - }, - { - code: 'a { transform:\r\n\r\ntranslate(1, 1); }', - }, - { - code: 'a { background: blah,\n\nfoo; }', - }, - { - code: 'a { background: blah,\r\n\r\nfoo; }', - }, - { - code: '$list: (value,\n\n\nvalue2)', - description: 'Sass list ignored', - }, - ], - - reject: [ - { - code: 'a { transform: translate(/*c*/\n\n\n1,1); }', - fixed: 'a { transform: translate(/*c*/\n1,1); }', - message: messages.expected(0), - line: 1, - column: 15, - }, - { - code: 'a { transform: /*c*/translate(\n\n\n1,1); }', - fixed: 'a { transform: /*c*/translate(\n1,1); }', - message: messages.expected(0), - line: 1, - column: 20, - }, - { - code: 'a { transform: translate(\n\n1\n,\n1\n); }', - fixed: 'a { transform: translate(\n1\n,\n1\n); }', - message: messages.expected(0), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\n\n1\n,\n1\n\n); }', - fixed: 'a { transform: translate(\n1\n,\n1\n); }', - message: messages.expected(0), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\n\n1\n\n,\n1\n\n); }', - fixed: 'a { transform: translate(\n1\n,\n1\n); }', - message: messages.expected(0), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\r\n\r\n1\r\n,\r\n1\r\n); }', - fixed: 'a { transform: translate(\r\n1\r\n,\r\n1\r\n); }', - message: messages.expected(0), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\n1\n\n,\n1\n); }', - fixed: 'a { transform: translate(\n1\n,\n1\n); }', - message: messages.expected(0), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\r\n1\r\n\r\n,\r\n1\r\n); }', - fixed: 'a { transform: translate(\r\n1\r\n,\r\n1\r\n); }', - message: messages.expected(0), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\n1\n,\n\n1\n); }', - fixed: 'a { transform: translate(\n1\n,\n1\n); }', - message: messages.expected(0), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\r\n1\r\n,\r\n\r\n1\r\n); }', - fixed: 'a { transform: translate(\r\n1\r\n,\r\n1\r\n); }', - message: messages.expected(0), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\n1\n,\n1\n\n); }', - fixed: 'a { transform: translate(\n1\n,\n1\n); }', - message: messages.expected(0), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\r\n1\r\n,\r\n1\r\n\r\n); }', - fixed: 'a { transform: translate(\r\n1\r\n,\r\n1\r\n); }', - message: messages.expected(0), - line: 1, - column: 15, - }, - ], -}); - -testRule({ - ruleName, - config: [1], - fix: true, - - accept: [ - { - code: 'a { transform: translate(\n1\n,\n1\n); }', - }, - { - code: 'a { transform: translate(\r\n1\r\n,\r\n1\r\n); }', - }, - { - code: 'a { transform: translate(\n\n1\n,\n1\n); }', - }, - { - code: 'a { transform: translate(\r\n\r\n1\r\n,\r\n1\r\n); }', - }, - { - code: 'a { transform: translate(\n1\n\n,\n1\n); }', - }, - { - code: 'a { transform: translate(\r\n1\r\n\r\n,\r\n1\r\n); }', - }, - { - code: 'a { transform: translate(\n1\n,\n\n1\n); }', - }, - { - code: 'a { transform: translate(\r\n1\r\n,\r\n\r\n1\r\n); }', - }, - { - code: 'a { transform: translate(\n1\n,\n1\n\n); }', - }, - { - code: 'a { transform: translate(\r\n1\r\n,\r\n1\r\n\r\n); }', - }, - ], - - reject: [ - { - code: 'a { transform: translate(\n\n\n1\n,\n1\n); }', - fixed: 'a { transform: translate(\n\n1\n,\n1\n); }', - message: messages.expected(1), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\r\n\r\n\r\n1\r\n,\r\n1\r\n); }', - fixed: 'a { transform: translate(\r\n\r\n1\r\n,\r\n1\r\n); }', - message: messages.expected(1), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\n1\n\n\n,\n1\n); }', - fixed: 'a { transform: translate(\n1\n\n,\n1\n); }', - message: messages.expected(1), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\r\n1\r\n\r\n\r\n,\r\n1\r\n); }', - fixed: 'a { transform: translate(\r\n1\r\n\r\n,\r\n1\r\n); }', - message: messages.expected(1), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\n1\n,\n\n\n1\n); }', - fixed: 'a { transform: translate(\n1\n,\n\n1\n); }', - message: messages.expected(1), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\r\n1\r\n,\r\n\r\n\r\n1\r\n); }', - fixed: 'a { transform: translate(\r\n1\r\n,\r\n\r\n1\r\n); }', - message: messages.expected(1), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\n1\n,\n1\n\n\n); }', - fixed: 'a { transform: translate(\n1\n,\n1\n\n); }', - message: messages.expected(1), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\r\n1\r\n,\r\n1\r\n\r\n\r\n); }', - fixed: 'a { transform: translate(\r\n1\r\n,\r\n1\r\n\r\n); }', - message: messages.expected(1), - line: 1, - column: 15, - }, - ], -}); - -testRule({ - ruleName, - config: [2], - fix: true, - - accept: [ - { - code: 'a { transform: translate(\n1\n,\n1\n); }', - }, - { - code: 'a { transform: translate(\r\n1\r\n,\r\n1\r\n); }', - }, - { - code: 'a { transform: translate(\n\n1\n,\n1\n); }', - }, - { - code: 'a { transform: translate(\r\n\r\n1\r\n,\r\n1\r\n); }', - }, - { - code: 'a { transform: translate(\n1\n\n,\n1\n); }', - }, - { - code: 'a { transform: translate(\r\n1\r\n\r\n,\r\n1\r\n); }', - }, - { - code: 'a { transform: translate(\n1\n,\n\n1\n); }', - }, - { - code: 'a { transform: translate(\r\n1\r\n,\r\n\r\n1\r\n); }', - }, - { - code: 'a { transform: translate(\n1\n,\n1\n\n); }', - }, - { - code: 'a { transform: translate(\r\n1\r\n,\r\n1\r\n\r\n); }', - }, - { - code: 'a { transform: translate(\n\n\n1\n,\n1\n); }', - }, - { - code: 'a { transform: translate(\r\n\r\n\r\n1\r\n,\r\n1\r\n); }', - }, - { - code: 'a { transform: translate(\n1\n\n\n,\n1\n); }', - }, - { - code: 'a { transform: translate(\r\n1\r\n\r\n\r\n,\r\n1\r\n); }', - }, - { - code: 'a { transform: translate(\n1\n,\n\n\n1\n); }', - }, - { - code: 'a { transform: translate(\r\n1\r\n,\r\n\r\n\r\n1\r\n); }', - }, - { - code: 'a { transform: translate(\n1\n,\n1\n\n\n); }', - }, - { - code: 'a { transform: translate(\r\n1\r\n,\r\n1\r\n\r\n\r\n); }', - }, - ], - - reject: [ - { - code: 'a { transform: translate(\n\n\n\n1\n,\n1\n); }', - fixed: 'a { transform: translate(\n\n\n1\n,\n1\n); }', - message: messages.expected(2), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\r\n\r\n\r\n\r\n1\r\n,\r\n1\r\n); }', - fixed: 'a { transform: translate(\r\n\r\n\r\n1\r\n,\r\n1\r\n); }', - message: messages.expected(2), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\n1\n\n\n\n,\n1\n); }', - fixed: 'a { transform: translate(\n1\n\n\n,\n1\n); }', - message: messages.expected(2), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\r\n1\r\n\r\n\r\n\r\n,\r\n1\r\n); }', - fixed: 'a { transform: translate(\r\n1\r\n\r\n\r\n,\r\n1\r\n); }', - message: messages.expected(2), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\n1\n,\n\n\n\n1\n); }', - fixed: 'a { transform: translate(\n1\n,\n\n\n1\n); }', - message: messages.expected(2), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\r\n1\r\n,\r\n\r\n\r\n\r\n1\r\n); }', - fixed: 'a { transform: translate(\r\n1\r\n,\r\n\r\n\r\n1\r\n); }', - message: messages.expected(2), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\n1\n,\n1\n\n\n\n); }', - fixed: 'a { transform: translate(\n1\n,\n1\n\n\n); }', - message: messages.expected(2), - line: 1, - column: 15, - }, - { - code: 'a { transform: translate(\r\n1\r\n,\r\n1\r\n\r\n\r\n\r\n); }', - fixed: 'a { transform: translate(\r\n1\r\n,\r\n1\r\n\r\n\r\n); }', - message: messages.expected(2), - line: 1, - column: 15, - }, - ], -}); diff --git a/lib/rules/function-max-empty-lines/index.js b/lib/rules/function-max-empty-lines/index.js deleted file mode 100644 index c20341375e..0000000000 --- a/lib/rules/function-max-empty-lines/index.js +++ /dev/null @@ -1,113 +0,0 @@ -'use strict'; - -const getDeclarationValue = require('../../utils/getDeclarationValue'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const setDeclarationValue = require('../../utils/setDeclarationValue'); -const validateOptions = require('../../utils/validateOptions'); -const valueParser = require('postcss-value-parser'); -const { isNumber } = require('../../utils/validateTypes'); - -const ruleName = 'function-max-empty-lines'; - -const messages = ruleMessages(ruleName, { - expected: (max) => `Expected no more than ${max} empty ${max === 1 ? 'line' : 'lines'}`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/function-max-empty-lines', - fixable: true, - deprecated: true, -}; - -/** - * @param {import('postcss').Declaration} decl - */ -function placeIndexOnValueStart(decl) { - if (decl.raws.between == null) throw new Error('`between` must be present'); - - return decl.prop.length + decl.raws.between.length - 1; -} - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const maxAdjacentNewlines = primary + 1; - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: isNumber, - }); - - if (!validOptions) { - return; - } - - const violatedCRLFNewLinesRegex = new RegExp(`(?:\r\n){${maxAdjacentNewlines + 1},}`); - const violatedLFNewLinesRegex = new RegExp(`\n{${maxAdjacentNewlines + 1},}`); - const allowedLFNewLinesString = context.fix ? '\n'.repeat(maxAdjacentNewlines) : ''; - const allowedCRLFNewLinesString = context.fix ? '\r\n'.repeat(maxAdjacentNewlines) : ''; - - root.walkDecls((decl) => { - if (!decl.value.includes('(')) { - return; - } - - const stringValue = getDeclarationValue(decl); - /** @type {Array<[string, string]>} */ - const splittedValue = []; - let sourceIndexStart = 0; - - valueParser(stringValue).walk((node) => { - if ( - node.type !== 'function' /* ignore non functions */ || - node.value.length === 0 /* ignore sass lists */ - ) { - return; - } - - const stringifiedNode = valueParser.stringify(node); - - if ( - !violatedLFNewLinesRegex.test(stringifiedNode) && - !violatedCRLFNewLinesRegex.test(stringifiedNode) - ) { - return; - } - - if (context.fix) { - const newNodeString = stringifiedNode - .replace(new RegExp(violatedLFNewLinesRegex, 'gm'), allowedLFNewLinesString) - .replace(new RegExp(violatedCRLFNewLinesRegex, 'gm'), allowedCRLFNewLinesString); - - splittedValue.push([ - stringValue.slice(sourceIndexStart, node.sourceIndex), - newNodeString, - ]); - sourceIndexStart = node.sourceIndex + stringifiedNode.length; - } else { - report({ - message: messages.expected(primary), - node: decl, - index: placeIndexOnValueStart(decl) + node.sourceIndex, - result, - ruleName, - }); - } - }); - - if (context.fix && splittedValue.length > 0) { - const updatedValue = - splittedValue.reduce((acc, curr) => acc + curr[0] + curr[1], '') + - stringValue.slice(sourceIndexStart); - - setDeclarationValue(decl, updatedValue); - } - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/function-parentheses-newline-inside/README.md b/lib/rules/function-parentheses-newline-inside/README.md deleted file mode 100644 index fc39fecda5..0000000000 --- a/lib/rules/function-parentheses-newline-inside/README.md +++ /dev/null @@ -1,146 +0,0 @@ -# function-parentheses-newline-inside - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline or disallow whitespace on the inside of the parentheses of functions. - - -```css - a { - transform: translate( - 1, /* ↑ */ - 1 /* ↑ */ - ); /* ↑ */ - } /* ↑ */ -/** ↑ ↑ - * The newline inside these two parentheses */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a newline inside the parentheses. - -The following patterns are considered problems: - - -```css -a { transform: translate(1, 1); } -``` - - -```css -a { transform: translate(1, - 1 - ); } -``` - -The following patterns are _not_ considered problems: - - -```css -a { - transform: translate( - 1, 1 - ); -} -``` - - -```css -a { - transform: translate( - 1, - 1 - ); -} -``` - -### `"always-multi-line"` - -There _must always_ be a newline inside the parentheses of multi-line functions. - -The following patterns are considered problems: - - -```css -a { transform: translate(1, - 1) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1, 1) } -``` - - -```css -a { transform: translate( 1, 1 ) } -``` - - -```css -a { - transform: translate( - 1, 1 - ); -} -``` - - -```css -a { - transform: translate( - 1, - 1 - ); -} -``` - -### `"never-multi-line"` - -The following patterns are considered problems: - - -```css -a { - transform: translate( - 1, 1 - ); -} -``` - - -```css -a { - transform: translate( - 1, - 1 - ); -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1, 1) } -``` - - -```css -a { transform: translate( 1, 1 ) } -``` - - -```css -a { transform: translate(1, - 1) } -``` diff --git a/lib/rules/function-parentheses-newline-inside/__tests__/index.js b/lib/rules/function-parentheses-newline-inside/__tests__/index.js deleted file mode 100644 index c1be9363b9..0000000000 --- a/lib/rules/function-parentheses-newline-inside/__tests__/index.js +++ /dev/null @@ -1,414 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a::before { content: "(a) ( a)"; }', - }, - { - code: "a::before { background: url(\n'asdf( Vcxvsd)ASD'\n); }", - }, - { - code: 'a { transform: translate(\n1, 1\n); }', - }, - { - code: 'a { transform: translate(\n\n1, 1\n\n); }', - }, - { - code: 'a { transform: translate(\r\n1, 1\r\n); }', - description: 'CRLF', - }, - { - code: 'a { transform: translate(\r\n\r\n1, 1\r\n\r\n); }', - description: 'CRLF', - }, - { - code: 'a { color: color(\nrgb(\n0, 0, 0\n) lightness(\n50%\n)\n); }', - }, - { - code: '$map: (key: value,key2: value2)', - description: 'Sass map ignored', - }, - { - code: '$list: (value, value2)', - description: 'Sass list ignored', - }, - { - code: 'a { transform: translate( /*comment*/\n1,\n 1\n); }', - }, - ], - - reject: [ - { - code: 'a { transform: translate(1, 1\n); }', - fixed: 'a { transform: translate(\n1, 1\n); }', - message: messages.expectedOpening, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate(\n1, 1); }', - fixed: 'a { transform: translate(\n1, 1\n); }', - message: messages.expectedClosing, - line: 2, - column: 4, - }, - { - code: 'a { transform: translate( 1, 1\n); }', - fixed: 'a { transform: translate(\n 1, 1\n); }', - message: messages.expectedOpening, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate(\n1,\n1\t); }', - fixed: 'a { transform: translate(\n1,\n1\n\t); }', - message: messages.expectedClosing, - line: 3, - column: 2, - }, - { - code: 'a { color: color(rgb(\n0, 0, 0\n) lightness(\n50%\n)\n); }', - fixed: 'a { color: color(\nrgb(\n0, 0, 0\n) lightness(\n50%\n)\n); }', - message: messages.expectedOpening, - line: 1, - column: 18, - }, - { - code: 'a { color: color(\nrgb(\n0, 0, 0\n) lightness(50%\n)\n); }', - fixed: 'a { color: color(\nrgb(\n0, 0, 0\n) lightness(\n50%\n)\n); }', - message: messages.expectedOpening, - line: 4, - column: 13, - }, - { - code: 'a::before { content: attr(data-foo\n); }', - fixed: 'a::before { content: attr(\ndata-foo\n); }', - message: messages.expectedOpening, - line: 1, - column: 27, - }, - { - code: 'a::before { content: attr(\n\tdata-foo); }', - fixed: 'a::before { content: attr(\n\tdata-foo\n); }', - message: messages.expectedClosing, - line: 2, - column: 9, - }, - { - code: 'a { transform: translate( 1,\n 1\n); }', - fixed: 'a { transform: translate(\n 1,\n 1\n); }', - message: messages.expectedOpening, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate(1,\r\n1\n); }', - fixed: 'a { transform: translate(\r\n1,\r\n1\n); }', - description: 'CRLF', - message: messages.expectedOpening, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate( /*comment*/ 1,\n 1\n); }', - fixed: 'a { transform: translate( /*comment*/\n 1,\n 1\n); }', - message: messages.expectedOpening, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate( /*c1*/ /*c2*/ 1,1 /*c3*/ /*c4*/ ); }', - fixed: 'a { transform: translate( /*c1*/ /*c2*/\n 1,1 /*c3*/ /*c4*/\n ); }', - warnings: [ - { - message: messages.expectedOpening, - line: 1, - column: 26, - }, - { - message: messages.expectedClosing, - line: 1, - column: 58, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: 'a::before { content: "(a) ( a)"; }', - }, - { - code: "a::before { background: url(\n'asdf( Vcxvsd)ASD'\n); }", - }, - { - code: 'a { transform: translate(\n1, 1\n); }', - }, - { - code: 'a { transform: translate(\r\n1, 1\r\n); }', - description: 'CRLF', - }, - { - code: 'a { color: color(\nrgb(\n0, 0, 0\n) lightness(\n50%\n)\n); }', - }, - { - code: 'a { transform: translate(1, 1); }', - }, - { - code: 'a { transform: translate( 1, 1\t); }', - }, - { - code: '$map: (key: value,\nkey2: value2)', - description: 'SCSS map', - }, - { - code: 'a { transform: translate(\n/*comment*/ 1,1\n); }', - }, - { - code: 'a { transform: translate( /*comment*/\n1,1\n); }', - }, - { - code: 'a { transform: translate(\n1,1\n/*comment*/ ); }', - }, - { - code: 'a { transform: translate(\n1,1 /*comment*/\n); }', - }, - ], - - reject: [ - { - code: 'a { transform: translate(1, 1\n); }', - fixed: 'a { transform: translate(\n1, 1\n); }', - message: messages.expectedOpeningMultiLine, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate(\n1, 1); }', - fixed: 'a { transform: translate(\n1, 1\n); }', - message: messages.expectedClosingMultiLine, - line: 2, - column: 4, - }, - { - code: 'a { transform: translate( 1, 1\n); }', - fixed: 'a { transform: translate(\n 1, 1\n); }', - message: messages.expectedOpeningMultiLine, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate(\n1,\n1\t); }', - fixed: 'a { transform: translate(\n1,\n1\n\t); }', - message: messages.expectedClosingMultiLine, - line: 3, - column: 2, - }, - { - code: 'a { color: color(rgb(\n0, 0, 0\n) lightness(\n50%\n)\n); }', - fixed: 'a { color: color(\nrgb(\n0, 0, 0\n) lightness(\n50%\n)\n); }', - message: messages.expectedOpeningMultiLine, - line: 1, - column: 18, - }, - { - code: 'a { color: color(\nrgb(\n0, 0, 0\n) lightness(50%\n)\n); }', - fixed: 'a { color: color(\nrgb(\n0, 0, 0\n) lightness(\n50%\n)\n); }', - message: messages.expectedOpeningMultiLine, - line: 4, - column: 13, - }, - { - code: 'a::before { content: attr(data-foo\n); }', - fixed: 'a::before { content: attr(\ndata-foo\n); }', - message: messages.expectedOpeningMultiLine, - line: 1, - column: 27, - }, - { - code: 'a::before { content: attr(\n\tdata-foo); }', - fixed: 'a::before { content: attr(\n\tdata-foo\n); }', - message: messages.expectedClosingMultiLine, - line: 2, - column: 9, - }, - { - code: 'a { transform: translate( 1,\n 1\n); }', - fixed: 'a { transform: translate(\n 1,\n 1\n); }', - message: messages.expectedOpeningMultiLine, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate(1,\r\n1\n); }', - fixed: 'a { transform: translate(\r\n1,\r\n1\n); }', - description: 'CRLF', - message: messages.expectedOpeningMultiLine, - line: 1, - column: 26, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - fix: true, - - accept: [ - { - code: 'a::before { content: "(a) ( a)"; }', - }, - { - code: "a::before { background: url('asdf(Vcxv\nsd\n)ASD'); }", - }, - { - code: 'a { transform: translate(1, 1); }', - }, - { - code: 'a { transform: translate(1,\r\n1); }', - description: 'CRLF', - }, - { - code: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - }, - { - code: 'a { transform: translate(1,\n 1); }', - }, - { - code: 'a { transform: translate(1,\n\t\t1); }', - }, - { - code: '$map: (\nkey: value,\nkey2: value2\n)', - description: 'SCSS map', - }, - { - code: 'a { transform: translate(/*comment*/1,\n1); }', - }, - { - code: 'a { transform: translate(1,\n1/*comment*/); }', - }, - ], - - reject: [ - { - code: 'a { transform: translate(\n 1,\n 1); }', - fixed: 'a { transform: translate(1,\n 1); }', - message: messages.rejectedOpeningMultiLine, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate( \n 1,\n 1); }', - fixed: 'a { transform: translate(1,\n 1); }', - message: messages.rejectedOpeningMultiLine, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate(1,\n 1\n); }', - fixed: 'a { transform: translate(1,\n 1); }', - message: messages.rejectedClosingMultiLine, - line: 2, - column: 4, - }, - { - code: 'a { transform: translate(1,\r\n1\t); }', - fixed: 'a { transform: translate(1,\r\n1); }', - message: messages.rejectedClosingMultiLine, - line: 2, - column: 2, - }, - { - code: 'a { color: color(rgb(0,\r\n 0,\r\n 0\r\n) lightness(50%)); }', - fixed: 'a { color: color(rgb(0,\r\n 0,\r\n 0) lightness(50%)); }', - message: messages.rejectedClosingMultiLine, - line: 3, - column: 5, - }, - { - code: 'a { color: color(rgb(0, 0, 0) lightness(\n50%)); }', - fixed: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - message: messages.rejectedOpeningMultiLine, - line: 1, - column: 41, - }, - { - code: 'a { transform: translate( /*c1*/ /*c2*/ 1,\n1 /*c3*/ /*c4*/ ); }', - fixed: 'a { transform: translate(/*c1*//*c2*/1,\n1/*c3*//*c4*/); }', - warnings: [ - { - message: messages.rejectedOpeningMultiLine, - line: 1, - column: 26, - }, - { - message: messages.rejectedClosingMultiLine, - line: 2, - column: 16, - }, - ], - }, - { - code: 'a { transform: translate( /*c1*//*c2*/1,\n1/*c3*//*c4*/ ); }', - fixed: 'a { transform: translate(/*c1*//*c2*/1,\n1/*c3*//*c4*/); }', - warnings: [ - { - message: messages.rejectedOpeningMultiLine, - line: 1, - column: 26, - }, - { - message: messages.rejectedClosingMultiLine, - line: 2, - column: 14, - }, - ], - }, - { - code: 'a { transform: translate(/*c1*//*c2*/ 1,\n1 /*c3*//*c4*/); }', - fixed: 'a { transform: translate(/*c1*//*c2*/1,\n1/*c3*//*c4*/); }', - warnings: [ - { - message: messages.rejectedOpeningMultiLine, - line: 1, - column: 26, - }, - { - message: messages.rejectedClosingMultiLine, - line: 2, - column: 14, - }, - ], - }, - { - code: 'a { transform: translate(/*c1*/ /*c2*/1,\n1/*c3*/ /*c4*/); }', - fixed: 'a { transform: translate(/*c1*//*c2*/1,\n1/*c3*//*c4*/); }', - warnings: [ - { - message: messages.rejectedOpeningMultiLine, - line: 1, - column: 26, - }, - { - message: messages.rejectedClosingMultiLine, - line: 2, - column: 14, - }, - ], - }, - ], -}); diff --git a/lib/rules/function-parentheses-newline-inside/index.js b/lib/rules/function-parentheses-newline-inside/index.js deleted file mode 100644 index 67dd51e946..0000000000 --- a/lib/rules/function-parentheses-newline-inside/index.js +++ /dev/null @@ -1,276 +0,0 @@ -'use strict'; - -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const getDeclarationValue = require('../../utils/getDeclarationValue'); -const isSingleLineString = require('../../utils/isSingleLineString'); -const isStandardSyntaxFunction = require('../../utils/isStandardSyntaxFunction'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const setDeclarationValue = require('../../utils/setDeclarationValue'); -const validateOptions = require('../../utils/validateOptions'); -const valueParser = require('postcss-value-parser'); - -const ruleName = 'function-parentheses-newline-inside'; - -const messages = ruleMessages(ruleName, { - expectedOpening: 'Expected newline after "("', - expectedClosing: 'Expected newline before ")"', - expectedOpeningMultiLine: 'Expected newline after "(" in a multi-line function', - rejectedOpeningMultiLine: 'Unexpected whitespace after "(" in a multi-line function', - expectedClosingMultiLine: 'Expected newline before ")" in a multi-line function', - rejectedClosingMultiLine: 'Unexpected whitespace before ")" in a multi-line function', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/function-parentheses-newline-inside', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'always-multi-line', 'never-multi-line'], - }); - - if (!validOptions) { - return; - } - - root.walkDecls((decl) => { - if (!decl.value.includes('(')) { - return; - } - - let hasFixed = false; - const declValue = getDeclarationValue(decl); - const parsedValue = valueParser(declValue); - - parsedValue.walk((valueNode) => { - if (valueNode.type !== 'function') { - return; - } - - if (!isStandardSyntaxFunction(valueNode)) { - return; - } - - const functionString = valueParser.stringify(valueNode); - const isMultiLine = !isSingleLineString(functionString); - const containsNewline = (/** @type {string} */ str) => str.includes('\n'); - - // Check opening ... - - const openingIndex = valueNode.sourceIndex + valueNode.value.length + 1; - const checkBefore = getCheckBefore(valueNode); - - if (primary === 'always' && !containsNewline(checkBefore)) { - if (context.fix) { - hasFixed = true; - fixBeforeForAlways(valueNode, context.newline || ''); - } else { - complain(messages.expectedOpening, openingIndex); - } - } - - if (isMultiLine && primary === 'always-multi-line' && !containsNewline(checkBefore)) { - if (context.fix) { - hasFixed = true; - fixBeforeForAlways(valueNode, context.newline || ''); - } else { - complain(messages.expectedOpeningMultiLine, openingIndex); - } - } - - if (isMultiLine && primary === 'never-multi-line' && checkBefore !== '') { - if (context.fix) { - hasFixed = true; - fixBeforeForNever(valueNode); - } else { - complain(messages.rejectedOpeningMultiLine, openingIndex); - } - } - - // Check closing ... - - const closingIndex = valueNode.sourceIndex + functionString.length - 2; - const checkAfter = getCheckAfter(valueNode); - - if (primary === 'always' && !containsNewline(checkAfter)) { - if (context.fix) { - hasFixed = true; - fixAfterForAlways(valueNode, context.newline || ''); - } else { - complain(messages.expectedClosing, closingIndex); - } - } - - if (isMultiLine && primary === 'always-multi-line' && !containsNewline(checkAfter)) { - if (context.fix) { - hasFixed = true; - fixAfterForAlways(valueNode, context.newline || ''); - } else { - complain(messages.expectedClosingMultiLine, closingIndex); - } - } - - if (isMultiLine && primary === 'never-multi-line' && checkAfter !== '') { - if (context.fix) { - hasFixed = true; - fixAfterForNever(valueNode); - } else { - complain(messages.rejectedClosingMultiLine, closingIndex); - } - } - }); - - if (hasFixed) { - setDeclarationValue(decl, parsedValue.toString()); - } - - /** - * @param {string} message - * @param {number} offset - */ - function complain(message, offset) { - report({ - ruleName, - result, - message, - node: decl, - index: declarationValueIndex(decl) + offset, - }); - } - }); - }; -}; - -/** @typedef {import('postcss-value-parser').FunctionNode} FunctionNode */ - -/** - * @param {FunctionNode} valueNode - */ -function getCheckBefore(valueNode) { - let before = valueNode.before; - - for (const node of valueNode.nodes) { - if (node.type === 'comment') { - continue; - } - - if (node.type === 'space') { - before += node.value; - continue; - } - - break; - } - - return before; -} - -/** - * @param {FunctionNode} valueNode - */ -function getCheckAfter(valueNode) { - let after = ''; - - for (const node of [...valueNode.nodes].reverse()) { - if (node.type === 'comment') { - continue; - } - - if (node.type === 'space') { - after = node.value + after; - continue; - } - - break; - } - - after += valueNode.after; - - return after; -} - -/** - * @param {FunctionNode} valueNode - * @param {string} newline - */ -function fixBeforeForAlways(valueNode, newline) { - let target; - - for (const node of valueNode.nodes) { - if (node.type === 'comment') { - continue; - } - - if (node.type === 'space') { - target = node; - continue; - } - - break; - } - - if (target) { - target.value = newline + target.value; - } else { - valueNode.before = newline + valueNode.before; - } -} - -/** - * @param {FunctionNode} valueNode - */ -function fixBeforeForNever(valueNode) { - valueNode.before = ''; - - for (const node of valueNode.nodes) { - if (node.type === 'comment') { - continue; - } - - if (node.type === 'space') { - node.value = ''; - continue; - } - - break; - } -} - -/** - * @param {FunctionNode} valueNode - * @param {string} newline - */ -function fixAfterForAlways(valueNode, newline) { - valueNode.after = newline + valueNode.after; -} - -/** - * @param {FunctionNode} valueNode - */ -function fixAfterForNever(valueNode) { - valueNode.after = ''; - - for (const node of [...valueNode.nodes].reverse()) { - if (node.type === 'comment') { - continue; - } - - if (node.type === 'space') { - node.value = ''; - continue; - } - - break; - } -} - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/function-parentheses-space-inside/README.md b/lib/rules/function-parentheses-space-inside/README.md deleted file mode 100644 index 0904931a0b..0000000000 --- a/lib/rules/function-parentheses-space-inside/README.md +++ /dev/null @@ -1,142 +0,0 @@ -# function-parentheses-space-inside - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace on the inside of the parentheses of functions. - - -```css -a { transform: translate( 1, 1 ); } -/** ↑ ↑ - * The space inside these two parentheses */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"|"always-single-line"|"never-single-line"` - -### `"always"` - -There _must always_ be a single space inside of the parentheses. - -The following patterns are considered problems: - - -```css -a { transform: translate(1, 1); } -``` - - -```css -a { transform: translate(1, 1 ); } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate( 1, 1 ); } -``` - -### `"never"` - -There _must never_ be whitespace on the inside of the parentheses. - -The following patterns are considered problems: - - -```css -a { transform: translate( 1, 1 ); } -``` - - -```css -a { transform: translate(1, 1 ); } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1, 1); } -``` - -### `"always-single-line"` - -There _must always_ be a single space inside the parentheses of single-line functions. - -The following patterns are considered problems: - - -```css -a { transform: translate(1, 1) } -``` - - -```css -a { transform: translate(1, 1 ) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate( 1, 1 ) } -``` - - -```css -a { transform: translate(1, - 1) } -``` - - -```css -a { - transform: translate( - 1, - 1 - ) -} -``` - -### `"never-single-line"` - -There _must never_ be whitespace inside the parentheses of single-line functions. - -The following patterns are considered problems: - - -```css -a { transform: translate( 1, 1 ) } -``` - - -```css -a { transform: translate(1, 1 ) } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1, 1) } -``` - - -```css -a { transform: translate( 1, - 1) } -``` - - -```css -a { - transform: translate( - 1, - 1 - ) -} -``` diff --git a/lib/rules/function-parentheses-space-inside/__tests__/index.js b/lib/rules/function-parentheses-space-inside/__tests__/index.js deleted file mode 100644 index d129b224c3..0000000000 --- a/lib/rules/function-parentheses-space-inside/__tests__/index.js +++ /dev/null @@ -1,599 +0,0 @@ -'use strict'; - -const mergeTestDescriptions = require('../../../testUtils/mergeTestDescriptions'); - -const { messages, ruleName } = require('..'); - -const alwaysTests = { - accept: [ - { - code: 'a { filter: grayscale(); }', - description: 'ignore function without parameters', - }, - { - code: 'a { filter: grayscale( ); }', - description: 'ignore function without parameters', - }, - ], -}; - -testRule( - mergeTestDescriptions(alwaysTests, { - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a::before { content: "(a) ( a )"; }', - }, - { - code: "a::before { background: url( 'asdf(Vcxvsd)ASD' ); }", - }, - { - code: 'a { transform: translate( 1, 1 ); }', - }, - { - code: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50% ) ); }', - }, - { - code: '$map: (key: value, key2: value2)', - description: 'SCSS map', - }, - { - code: '$list: (value, value2)', - description: 'Sass list ignored', - }, - ], - - reject: [ - { - code: 'a { transform: translate(1, 1 ); }', - fixed: 'a { transform: translate( 1, 1 ); }', - message: messages.expectedOpening, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate( 1, 1); }', - fixed: 'a { transform: translate( 1, 1 ); }', - message: messages.expectedClosing, - line: 1, - column: 30, - }, - { - code: 'a { transform: translate( 1, 1 ); }', - fixed: 'a { transform: translate( 1, 1 ); }', - message: messages.expectedOpening, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate( 1, 1 ); }', - fixed: 'a { transform: translate( 1, 1 ); }', - message: messages.expectedClosing, - line: 1, - column: 32, - }, - { - code: 'a { color: color(rgb( 0, 0, 0 ) lightness( 50% ) ); }', - fixed: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50% ) ); }', - message: messages.expectedOpening, - line: 1, - column: 18, - }, - { - code: 'a { color: color( rgb(0, 0, 0 ) lightness( 50% ) ); }', - fixed: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50% ) ); }', - message: messages.expectedOpening, - line: 1, - column: 23, - }, - { - code: 'a { color: color( rgb( 0, 0, 0) lightness( 50% ) ); }', - fixed: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50% ) ); }', - message: messages.expectedClosing, - line: 1, - column: 30, - }, - { - code: 'a { color: color( rgb( 0, 0, 0 ) lightness(50% ) ); }', - fixed: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50% ) ); }', - message: messages.expectedOpening, - line: 1, - column: 44, - }, - { - code: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50%) ); }', - fixed: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50% ) ); }', - message: messages.expectedClosing, - line: 1, - column: 47, - }, - { - code: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50% )); }', - fixed: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50% ) ); }', - message: messages.expectedClosing, - line: 1, - column: 49, - }, - { - code: 'a::before { content: attr(data-foo ); }', - fixed: 'a::before { content: attr( data-foo ); }', - message: messages.expectedOpening, - line: 1, - column: 27, - }, - { - code: 'a::before { content: attr( data-foo); }', - fixed: 'a::before { content: attr( data-foo ); }', - message: messages.expectedClosing, - line: 1, - column: 35, - }, - { - code: 'a { transform: translate(\n 1,\n 1 ); }', - fixed: 'a { transform: translate( 1,\n 1 ); }', - message: messages.expectedOpening, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate( 1,\n 1\n\t); }', - fixed: 'a { transform: translate( 1,\n 1 ); }', - message: messages.expectedClosing, - line: 3, - column: 1, - }, - { - code: 'a { transform: translate(1,\r\n1 ); }', - fixed: 'a { transform: translate( 1,\r\n1 ); }', - description: 'CRLF', - message: messages.expectedOpening, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate(/*comment*/1, 1/*comment*/); }', - fixed: 'a { transform: translate( /*comment*/1, 1/*comment*/ ); }', - description: 'comments', - warnings: [ - { - message: messages.expectedOpening, - line: 1, - column: 26, - }, - { - message: messages.expectedClosing, - line: 1, - column: 51, - }, - ], - }, - ], - }), -); - -testRule( - mergeTestDescriptions(alwaysTests, { - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: 'a::before { content: "(a) ( a )"; }', - }, - { - code: "a::before { background: url( 'asdf(Vcxvsd)ASD' ); }", - }, - { - code: 'a { transform: translate( 1, 1 ); }', - }, - { - code: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50% ) ); }', - }, - { - code: 'a { transform: translate(\n 1,\n 1\n); }', - }, - { - code: 'a { transform: translate( \n 1,\n 1\n\t); }', - }, - { - code: 'a { transform: translate(1,\r\n1); }', - description: 'CRLF', - }, - { - code: 'a { color: color(rgb(0,\n0,\n0 ) lightness( 50% )); }', - }, - { - code: '$map: (key: value, key2: value2)', - description: 'SCSS map', - }, - ], - - reject: [ - { - code: 'a { color: color(rgb(0,\n0,\n0 ) lightness(50% )); }', - fixed: 'a { color: color(rgb(0,\n0,\n0 ) lightness( 50% )); }', - message: messages.expectedOpeningSingleLine, - line: 3, - column: 15, - }, - { - code: 'a { transform: translate(1, 1 ); }', - fixed: 'a { transform: translate( 1, 1 ); }', - message: messages.expectedOpeningSingleLine, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate( 1, 1); }', - fixed: 'a { transform: translate( 1, 1 ); }', - message: messages.expectedClosingSingleLine, - line: 1, - column: 30, - }, - { - code: 'a { transform: translate( 1, 1 ); }', - fixed: 'a { transform: translate( 1, 1 ); }', - message: messages.expectedOpeningSingleLine, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate( 1, 1 ); }', - fixed: 'a { transform: translate( 1, 1 ); }', - message: messages.expectedClosingSingleLine, - line: 1, - column: 32, - }, - { - code: 'a { color: color(rgb( 0, 0, 0 ) lightness( 50% ) ); }', - fixed: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50% ) ); }', - message: messages.expectedOpeningSingleLine, - line: 1, - column: 18, - }, - { - code: 'a { color: color( rgb(0, 0, 0 ) lightness( 50% ) ); }', - fixed: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50% ) ); }', - message: messages.expectedOpeningSingleLine, - line: 1, - column: 23, - }, - { - code: 'a { color: color( rgb( 0, 0, 0) lightness( 50% ) ); }', - fixed: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50% ) ); }', - message: messages.expectedClosingSingleLine, - line: 1, - column: 30, - }, - { - code: 'a { color: color( rgb( 0, 0, 0 ) lightness(50% ) ); }', - fixed: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50% ) ); }', - message: messages.expectedOpeningSingleLine, - line: 1, - column: 44, - }, - { - code: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50%) ); }', - fixed: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50% ) ); }', - message: messages.expectedClosingSingleLine, - line: 1, - column: 47, - }, - { - code: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50% )); }', - fixed: 'a { color: color( rgb( 0, 0, 0 ) lightness( 50% ) ); }', - message: messages.expectedClosingSingleLine, - line: 1, - column: 49, - }, - { - code: 'a::before { content: attr(data-foo ); }', - fixed: 'a::before { content: attr( data-foo ); }', - message: messages.expectedOpeningSingleLine, - line: 1, - column: 27, - }, - { - code: 'a::before { content: attr( data-foo); }', - fixed: 'a::before { content: attr( data-foo ); }', - message: messages.expectedClosingSingleLine, - line: 1, - column: 35, - }, - ], - }), -); - -testRule( - mergeTestDescriptions(alwaysTests, { - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a::before { content: "(a) ( a )"; }', - }, - { - code: "a::before { background: url('asdf( Vcxvsd )ASD'); }", - }, - { - code: 'a::before { content: "(a) ( a )"; }', - }, - { - code: 'a { transform: translate(1, 1); }', - }, - { - code: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - }, - { - code: '$map: ( key: value, key2: value2 )', - description: 'SCSS map', - }, - ], - - reject: [ - { - code: 'a { transform: translate( 1, 1); }', - fixed: 'a { transform: translate(1, 1); }', - message: messages.rejectedOpening, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate( 1, 1); }', - fixed: 'a { transform: translate(1, 1); }', - message: messages.rejectedOpening, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate(1, 1 ); }', - fixed: 'a { transform: translate(1, 1); }', - message: messages.rejectedClosing, - line: 1, - column: 30, - }, - { - code: 'a { transform: translate(1, 1 ); }', - fixed: 'a { transform: translate(1, 1); }', - message: messages.rejectedClosing, - line: 1, - column: 31, - }, - { - code: 'a { color: color( rgb(0, 0, 0) lightness(50%)); }', - fixed: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - message: messages.rejectedOpening, - line: 1, - column: 18, - }, - { - code: 'a { color: color(rgb( 0, 0, 0) lightness(50%)); }', - fixed: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - message: messages.rejectedOpening, - line: 1, - column: 22, - }, - { - code: 'a { color: color(rgb(0, 0, 0 ) lightness(50%)); }', - fixed: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - message: messages.rejectedClosing, - line: 1, - column: 29, - }, - { - code: 'a { color: color(rgb(0, 0, 0) lightness( 50%)); }', - fixed: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - message: messages.rejectedOpening, - line: 1, - column: 41, - }, - { - code: 'a { color: color(rgb(0, 0, 0) lightness(50% )); }', - fixed: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - message: messages.rejectedClosing, - line: 1, - column: 44, - }, - { - code: 'a { color: color(rgb(0, 0, 0) lightness(50%) ); }', - fixed: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - message: messages.rejectedClosing, - line: 1, - column: 45, - }, - { - code: 'a::before { content: attr(data-foo ); }', - fixed: 'a::before { content: attr(data-foo); }', - message: messages.rejectedClosing, - line: 1, - column: 35, - }, - { - code: 'a::before { content: attr( data-foo); }', - fixed: 'a::before { content: attr(data-foo); }', - message: messages.rejectedOpening, - line: 1, - column: 27, - }, - { - code: 'a { transform: translate( 1,\n1); }', - fixed: 'a { transform: translate(1,\n1); }', - message: messages.rejectedOpening, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate(1,\r\n 1\r\n); }', - fixed: 'a { transform: translate(1,\r\n 1); }', - description: 'CRLF', - message: messages.rejectedClosing, - line: 2, - column: 5, - }, - { - code: 'a { color: color(rgb(0,\n0,\n0 ) lightness(50%)); }', - fixed: 'a { color: color(rgb(0,\n0,\n0) lightness(50%)); }', - message: messages.rejectedClosing, - line: 3, - column: 2, - }, - { - code: 'a { transform: translate( /*comment*/ 1, 1 /*comment*/ ); }', - fixed: 'a { transform: translate(/*comment*/ 1, 1 /*comment*/); }', - description: 'comments', - warnings: [ - { - message: messages.rejectedOpening, - line: 1, - column: 26, - }, - { - message: messages.rejectedClosing, - line: 1, - column: 55, - }, - ], - }, - ], - }), -); - -testRule( - mergeTestDescriptions(alwaysTests, { - ruleName, - config: ['never-single-line'], - fix: true, - - accept: [ - { - code: 'a::before { content: "(a) ( a )"; }', - }, - { - code: "a::before { background: url('asdf( Vcxvsd )ASD'); }", - }, - { - code: 'a::before { content: "(a) ( a )"; }', - }, - { - code: 'a { transform: translate(1, 1); }', - }, - { - code: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - }, - { - code: 'a { transform: translate( 1,\n1 ); }', - }, - { - code: 'a { transform: translate(\r\n 1,\r\n 1\r\n); }', - description: 'CRLF', - }, - { - code: 'a { color: color(rgb(0,\n0,\n0 ) lightness(50%)); }', - }, - { - code: '$map: ( key: value, key2: value2 )', - description: 'SCSS map', - }, - ], - - reject: [ - { - code: 'a { color: color(rgb(0,\n0,\n0) lightness( 50%)); }', - fixed: 'a { color: color(rgb(0,\n0,\n0) lightness(50%)); }', - message: messages.rejectedOpeningSingleLine, - line: 3, - column: 14, - }, - { - code: 'a { transform: translate( 1, 1); }', - fixed: 'a { transform: translate(1, 1); }', - message: messages.rejectedOpeningSingleLine, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate( 1, 1); }', - fixed: 'a { transform: translate(1, 1); }', - message: messages.rejectedOpeningSingleLine, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate(1, 1 ); }', - fixed: 'a { transform: translate(1, 1); }', - message: messages.rejectedClosingSingleLine, - line: 1, - column: 30, - }, - { - code: 'a { transform: translate(1, 1 ); }', - fixed: 'a { transform: translate(1, 1); }', - message: messages.rejectedClosingSingleLine, - line: 1, - column: 31, - }, - { - code: 'a { color: color( rgb(0, 0, 0) lightness(50%)); }', - fixed: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - message: messages.rejectedOpeningSingleLine, - line: 1, - column: 18, - }, - { - code: 'a { color: color(rgb( 0, 0, 0) lightness(50%)); }', - fixed: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - message: messages.rejectedOpeningSingleLine, - line: 1, - column: 22, - }, - { - code: 'a { color: color(rgb(0, 0, 0 ) lightness(50%)); }', - fixed: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - message: messages.rejectedClosingSingleLine, - line: 1, - column: 29, - }, - { - code: 'a { color: color(rgb(0, 0, 0) lightness( 50%)); }', - fixed: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - message: messages.rejectedOpeningSingleLine, - line: 1, - column: 41, - }, - { - code: 'a { color: color(rgb(0, 0, 0) lightness(50% )); }', - fixed: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - message: messages.rejectedClosingSingleLine, - line: 1, - column: 44, - }, - { - code: 'a { color: color(rgb(0, 0, 0) lightness(50%) ); }', - fixed: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', - message: messages.rejectedClosingSingleLine, - line: 1, - column: 45, - }, - { - code: 'a::before { content: attr(data-foo ); }', - fixed: 'a::before { content: attr(data-foo); }', - message: messages.rejectedClosingSingleLine, - line: 1, - column: 35, - }, - { - code: 'a::before { content: attr( data-foo); }', - fixed: 'a::before { content: attr(data-foo); }', - message: messages.rejectedOpeningSingleLine, - line: 1, - column: 27, - }, - ], - }), -); diff --git a/lib/rules/function-parentheses-space-inside/index.js b/lib/rules/function-parentheses-space-inside/index.js deleted file mode 100644 index 4974e7a235..0000000000 --- a/lib/rules/function-parentheses-space-inside/index.js +++ /dev/null @@ -1,175 +0,0 @@ -'use strict'; - -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const getDeclarationValue = require('../../utils/getDeclarationValue'); -const isSingleLineString = require('../../utils/isSingleLineString'); -const isStandardSyntaxFunction = require('../../utils/isStandardSyntaxFunction'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const setDeclarationValue = require('../../utils/setDeclarationValue'); -const validateOptions = require('../../utils/validateOptions'); -const valueParser = require('postcss-value-parser'); - -const ruleName = 'function-parentheses-space-inside'; - -const messages = ruleMessages(ruleName, { - expectedOpening: 'Expected single space after "("', - rejectedOpening: 'Unexpected whitespace after "("', - expectedClosing: 'Expected single space before ")"', - rejectedClosing: 'Unexpected whitespace before ")"', - expectedOpeningSingleLine: 'Expected single space after "(" in a single-line function', - rejectedOpeningSingleLine: 'Unexpected whitespace after "(" in a single-line function', - expectedClosingSingleLine: 'Expected single space before ")" in a single-line function', - rejectedClosingSingleLine: 'Unexpected whitespace before ")" in a single-line function', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/function-parentheses-space-inside', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never', 'always-single-line', 'never-single-line'], - }); - - if (!validOptions) { - return; - } - - root.walkDecls((decl) => { - if (!decl.value.includes('(')) { - return; - } - - let hasFixed = false; - const declValue = getDeclarationValue(decl); - const parsedValue = valueParser(declValue); - - parsedValue.walk((valueNode) => { - if (valueNode.type !== 'function') { - return; - } - - if (!isStandardSyntaxFunction(valueNode)) { - return; - } - - // Ignore function without parameters - if (!valueNode.nodes.length) { - return; - } - - const functionString = valueParser.stringify(valueNode); - const isSingleLine = isSingleLineString(functionString); - - // Check opening ... - - const openingIndex = valueNode.sourceIndex + valueNode.value.length + 1; - - if (primary === 'always' && valueNode.before !== ' ') { - if (context.fix) { - hasFixed = true; - valueNode.before = ' '; - } else { - complain(messages.expectedOpening, openingIndex); - } - } - - if (primary === 'never' && valueNode.before !== '') { - if (context.fix) { - hasFixed = true; - valueNode.before = ''; - } else { - complain(messages.rejectedOpening, openingIndex); - } - } - - if (isSingleLine && primary === 'always-single-line' && valueNode.before !== ' ') { - if (context.fix) { - hasFixed = true; - valueNode.before = ' '; - } else { - complain(messages.expectedOpeningSingleLine, openingIndex); - } - } - - if (isSingleLine && primary === 'never-single-line' && valueNode.before !== '') { - if (context.fix) { - hasFixed = true; - valueNode.before = ''; - } else { - complain(messages.rejectedOpeningSingleLine, openingIndex); - } - } - - // Check closing ... - - const closingIndex = valueNode.sourceIndex + functionString.length - 2; - - if (primary === 'always' && valueNode.after !== ' ') { - if (context.fix) { - hasFixed = true; - valueNode.after = ' '; - } else { - complain(messages.expectedClosing, closingIndex); - } - } - - if (primary === 'never' && valueNode.after !== '') { - if (context.fix) { - hasFixed = true; - valueNode.after = ''; - } else { - complain(messages.rejectedClosing, closingIndex); - } - } - - if (isSingleLine && primary === 'always-single-line' && valueNode.after !== ' ') { - if (context.fix) { - hasFixed = true; - valueNode.after = ' '; - } else { - complain(messages.expectedClosingSingleLine, closingIndex); - } - } - - if (isSingleLine && primary === 'never-single-line' && valueNode.after !== '') { - if (context.fix) { - hasFixed = true; - valueNode.after = ''; - } else { - complain(messages.rejectedClosingSingleLine, closingIndex); - } - } - }); - - if (hasFixed) { - setDeclarationValue(decl, parsedValue.toString()); - } - - /** - * @param {string} message - * @param {number} offset - */ - function complain(message, offset) { - report({ - ruleName, - result, - message, - node: decl, - index: declarationValueIndex(decl) + offset, - }); - } - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/function-whitespace-after/README.md b/lib/rules/function-whitespace-after/README.md deleted file mode 100644 index e4be492a57..0000000000 --- a/lib/rules/function-whitespace-after/README.md +++ /dev/null @@ -1,82 +0,0 @@ -# function-whitespace-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require or disallow whitespace after functions. - - -```css -a { transform: translate(1, 1) scale(3); } -/** ↑ - * This space */ -``` - -This rule does not check for space immediately after `)` if the very next character is `,`, `)`, `/` or `}`, allowing some of the patterns exemplified below. - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be whitespace after the function. - -The following patterns are considered problems: - - -```css -a { transform: translate(1, 1)scale(3); } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1, 1) scale(3); } -``` - - -```css -a { transform: translate(1, 1) scale(3); } -``` - - -```css -a { - transform: - translate(1, 1) - scale(3); -} -``` - - -```css -/* notice the two closing parentheses without a space between */ -a { top: calc(1 * (1 + 3)); } -``` - - -```css -/* notice the ), with no space after the closing parenthesis */ -a { padding: calc(1 * 2px), calc(2 * 5px); } -``` - -### `"never"` - -There _must never_ be whitespace after the function. - -The following patterns are considered problems: - - -```css -a { transform: translate(1, 1) scale(3); } -``` - -The following patterns are _not_ considered problems: - - -```css -a { transform: translate(1, 1)scale(3); } -``` diff --git a/lib/rules/function-whitespace-after/__tests__/index.js b/lib/rules/function-whitespace-after/__tests__/index.js deleted file mode 100644 index 5a42353a20..0000000000 --- a/lib/rules/function-whitespace-after/__tests__/index.js +++ /dev/null @@ -1,338 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a::before { content: "var(--hoot)color(blue)"; }', - }, - { - code: "a::before { background: url('var(--hoot)color(blue)'); }", - }, - { - code: 'a::before { content: attr(data-foo); }', - }, - { - code: 'a { transform: translate(1, 1); }', - }, - { - code: 'a { transform: translate(1, 1) }', - }, - { - code: 'a { transform: translate(1, 1)}', - }, - { - code: 'a { transform: translate(1, 1) scale(3); }', - }, - { - code: 'a { color: color(rgb(0,0,0) lightness(50%)) };', - }, - { - code: 'a { background-image: linear-gradient(#f3c, #4ec), linear-gradient(#f3c, #4ec); }', - description: 'multiple comma-separated functions ', - }, - { - code: 'a { border-color: color(rgb(0,0,0) lightness(50%)) red pink orange; }', - description: 'function within a function as one of multiple space-separated values', - }, - { - code: 'a { transform: translate(1, 1) scale(3); }', - }, - { - code: 'a { transform: translate(1, 1)\nscale(3); }', - }, - { - code: 'a { transform: translate(1, 1)\r\nscale(3); }', - }, - { - code: 'a { color: color(rgb(0,0,0) lightness(50%)) };', - }, - { - code: 'a { color: color(rgb(0,0,0)\nlightness(50%)) };', - }, - { - code: 'a { color: color(rgb(0,0,0)\r\nlightness(50%)) };', - }, - { - code: '@import url(example.css) screen;', - }, - { - code: '$list: (value, value2);$thingTwo: 0px', - description: 'Sass list ignored', - }, - { - code: '.foo { $(x): calc(1px + 0px); }', - description: 'postcss-simple-vars interpolation as property name', - }, - { - code: '.foo { border-$(x)-left: 10px; }', - description: 'postcss-simple-vars interpolation within property name', - }, - { - code: '.foo { font: calc(16px + .2vw)/1 }', - description: 'after calc in `font` property (line-height shorthand value)', - }, - ], - - reject: [ - { - code: 'a { transform: translate(1, 1)scale(3); }', - fixed: 'a { transform: translate(1, 1) scale(3); }', - message: messages.expected, - line: 1, - column: 31, - }, - { - code: 'a { color: color(rgb(0,0,0)lightness(50%)) };', - fixed: 'a { color: color(rgb(0,0,0) lightness(50%)) };', - message: messages.expected, - line: 1, - column: 28, - }, - { - code: '@import url(example.css)screen;', - fixed: '@import url(example.css) screen;', - message: messages.expected, - line: 1, - column: 25, - }, - { - code: 'a { transform: translateX(1)translateY(1)scale(3); }', - fixed: 'a { transform: translateX(1) translateY(1) scale(3); }', - warnings: [ - { - message: messages.expected, - line: 1, - column: 29, - }, - { - message: messages.expected, - line: 1, - column: 42, - }, - ], - }, - { - code: '@import url(example.css)scree/**/n;', - fixed: '@import url(example.css) scree/**/n;', - message: messages.expected, - line: 1, - column: 25, - }, - { - code: 'a { transform: translate(1/**/, 1)scale(3); }', - fixed: 'a { transform: translate(1/**/, 1) scale(3); }', - message: messages.expected, - line: 1, - column: 35, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a::before { content: "var(--hoot) color(blue)"; }', - }, - { - code: "a::before { background: url('var(--hoot) color(blue)'); }", - }, - { - code: 'a::before { content: attr(data-foo); }', - }, - { - code: 'a { transform: translate(1, 1); }', - }, - { - code: 'a { transform: translate(1, 1) }', - }, - { - code: 'a { transform: translate(1, 1)}', - }, - { - code: 'a { transform: translate(1, 1)scale(3); }', - }, - { - code: 'a { color: color(rgb(0,0,0)lightness(50%)) };', - }, - { - code: '.foo { font: calc(16px + .2vw)/1 }', - description: 'after calc in `font` property (line-height shorthand value)', - }, - ], - - reject: [ - { - code: 'a { transform: translate(1, 1) scale(3); }', - fixed: 'a { transform: translate(1, 1)scale(3); }', - message: messages.rejected, - line: 1, - column: 31, - }, - { - code: 'a { transform: translate(1, 1) scale(3); }', - fixed: 'a { transform: translate(1, 1)scale(3); }', - message: messages.rejected, - line: 1, - column: 31, - }, - { - code: 'a { transform: translate(1, 1)\nscale(3); }', - fixed: 'a { transform: translate(1, 1)scale(3); }', - message: messages.rejected, - line: 1, - column: 31, - }, - { - code: 'a { transform: translate(1, 1)\r\nscale(3); }', - fixed: 'a { transform: translate(1, 1)scale(3); }', - description: 'CRLF', - message: messages.rejected, - line: 1, - column: 31, - }, - { - code: 'a { color: color(rgb(0,0,0) lightness(50%)) };', - fixed: 'a { color: color(rgb(0,0,0)lightness(50%)) };', - message: messages.rejected, - line: 1, - column: 28, - }, - { - code: 'a { color: color(rgb(0,0,0) lightness(50%)) };', - fixed: 'a { color: color(rgb(0,0,0)lightness(50%)) };', - message: messages.rejected, - line: 1, - column: 28, - }, - { - code: 'a { color: color(rgb(0,0,0)\nlightness(50%)) };', - fixed: 'a { color: color(rgb(0,0,0)lightness(50%)) };', - message: messages.rejected, - line: 1, - column: 28, - }, - { - code: 'a { transform: translateX(1) translateY(1) scale(3); }', - fixed: 'a { transform: translateX(1)translateY(1)scale(3); }', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 29, - }, - { - message: messages.rejected, - line: 1, - column: 43, - }, - ], - }, - { - code: 'a { transform: /**/ translateX(1) /**/ translateY(1) /**/ scale(3); }', - fixed: 'a { transform: /**/ translateX(1)/**/ translateY(1)/**/ scale(3); }', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 34, - }, - { - message: messages.rejected, - line: 1, - column: 53, - }, - ], - }, - { - code: '@import url(example.css) screen;', - fixed: '@import url(example.css)screen;', - message: messages.rejected, - line: 1, - column: 25, - }, - { - code: '@import url(example.css) /**/ screen;', - fixed: '@import url(example.css)/**/ screen;', - message: messages.rejected, - line: 1, - column: 25, - }, - ], -}); - -testRule({ - ruleName, - config: ['always'], - customSyntax: 'postcss-scss', - fix: true, - - accept: [ - { - code: 'h1 { max-height: #{($line-height) * ($lines-to-show)}em; }', - description: 'Sass-style interpolation with curly braces', - }, - ], - - reject: [ - { - code: 'a { padding:\n 10px\n /* comment one*/\n /* comment two*/\n var(--boo)orange}', - fixed: 'a { padding:\n 10px\n /* comment one*/\n /* comment two*/\n var(--boo) orange}', - message: messages.expected, - line: 5, - column: 13, - }, - ], -}); - -testRule({ - ruleName, - config: ['always'], - customSyntax: 'postcss-scss', - - reject: [ - { - code: 'a { padding:\n 10px\n // comment one\n // comment two\n var(--boo)orange}', - // can't fix on scss - // fixed: - // "a { padding:\n 10px\n // comment one\n // comment two\n var(--boo) orange}", - message: messages.expected, - line: 5, - column: 13, - }, - ], -}); - -testRule({ - ruleName, - config: ['always'], - customSyntax: 'postcss-less', - fix: true, - - accept: [ - // temporarily disable this test until this is fully supported in stylelint - // { - // code: "h1 { max-height: ((@line-height) * (@lines-to-show))em; }", - // description: "Less-style interpolation", - // }, - ], - - reject: [ - { - code: 'a { padding:\n 10px\n // comment one\n // comment two\n var(--boo)orange}', - fixed: 'a { padding:\n 10px\n // comment one\n // comment two\n var(--boo) orange}', - message: messages.expected, - line: 5, - column: 13, - }, - ], -}); diff --git a/lib/rules/function-whitespace-after/index.js b/lib/rules/function-whitespace-after/index.js deleted file mode 100644 index 3e5e2aaa83..0000000000 --- a/lib/rules/function-whitespace-after/index.js +++ /dev/null @@ -1,194 +0,0 @@ -'use strict'; - -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const getDeclarationValue = require('../../utils/getDeclarationValue'); -const isWhitespace = require('../../utils/isWhitespace'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const setDeclarationValue = require('../../utils/setDeclarationValue'); -const styleSearch = require('style-search'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'function-whitespace-after'; - -const messages = ruleMessages(ruleName, { - expected: 'Expected whitespace after ")"', - rejected: 'Unexpected whitespace after ")"', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/function-whitespace-after', - fixable: true, - deprecated: true, -}; - -const ACCEPTABLE_AFTER_CLOSING_PAREN = new Set([')', ',', '}', ':', '/', undefined]); - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - /** - * @param {import('postcss').Node} node - * @param {string} value - * @param {number} nodeIndex - * @param {((index: number) => void) | undefined} fix - */ - function check(node, value, nodeIndex, fix) { - styleSearch( - { - source: value, - target: ')', - functionArguments: 'only', - }, - (match) => { - checkClosingParen(value, match.startIndex + 1, node, nodeIndex, fix); - }, - ); - } - - /** - * @param {string} source - * @param {number} index - * @param {import('postcss').Node} node - * @param {number} nodeIndex - * @param {((index: number) => void) | undefined} fix - */ - function checkClosingParen(source, index, node, nodeIndex, fix) { - const nextChar = source.charAt(index); - - if (!nextChar) return; - - if (primary === 'always') { - // Allow for the next character to be a single empty space, - // another closing parenthesis, a comma, or the end of the value - if (nextChar === ' ') { - return; - } - - if (nextChar === '\n') { - return; - } - - if (source.slice(index, index + 2) === '\r\n') { - return; - } - - if (ACCEPTABLE_AFTER_CLOSING_PAREN.has(nextChar)) { - return; - } - - if (fix) { - fix(index); - - return; - } - - report({ - message: messages.expected, - node, - index: nodeIndex + index, - result, - ruleName, - }); - } else if (primary === 'never' && isWhitespace(nextChar)) { - if (fix) { - fix(index); - - return; - } - - report({ - message: messages.rejected, - node, - index: nodeIndex + index, - result, - ruleName, - }); - } - } - - /** - * @param {string} value - */ - function createFixer(value) { - let fixed = ''; - let lastIndex = 0; - /** @type {(index: number) => void} */ - let applyFix; - - if (primary === 'always') { - applyFix = (index) => { - // eslint-disable-next-line prefer-template - fixed += value.slice(lastIndex, index) + ' '; - lastIndex = index; - }; - } else if (primary === 'never') { - applyFix = (index) => { - let whitespaceEndIndex = index + 1; - - while ( - whitespaceEndIndex < value.length && - isWhitespace(value.charAt(whitespaceEndIndex)) - ) { - whitespaceEndIndex++; - } - - fixed += value.slice(lastIndex, index); - lastIndex = whitespaceEndIndex; - }; - } else { - throw new Error(`Unexpected option: "${primary}"`); - } - - return { - applyFix, - get hasFixed() { - return Boolean(lastIndex); - }, - get fixed() { - return fixed + value.slice(lastIndex); - }, - }; - } - - root.walkAtRules(/^import$/i, (atRule) => { - const param = (atRule.raws.params && atRule.raws.params.raw) || atRule.params; - const fixer = context.fix && createFixer(param); - - check(atRule, param, atRuleParamIndex(atRule), fixer ? fixer.applyFix : undefined); - - if (fixer && fixer.hasFixed) { - if (atRule.raws.params) { - atRule.raws.params.raw = fixer.fixed; - } else { - atRule.params = fixer.fixed; - } - } - }); - root.walkDecls((decl) => { - const value = getDeclarationValue(decl); - const fixer = context.fix && createFixer(value); - - check(decl, value, declarationValueIndex(decl), fixer ? fixer.applyFix : undefined); - - if (fixer && fixer.hasFixed) { - setDeclarationValue(decl, fixer.fixed); - } - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/functionCommaSpaceChecker.js b/lib/rules/functionCommaSpaceChecker.js deleted file mode 100644 index 1c004fa86b..0000000000 --- a/lib/rules/functionCommaSpaceChecker.js +++ /dev/null @@ -1,123 +0,0 @@ -'use strict'; - -const declarationValueIndex = require('../utils/declarationValueIndex'); -const getDeclarationValue = require('../utils/getDeclarationValue'); -const isStandardSyntaxFunction = require('../utils/isStandardSyntaxFunction'); -const report = require('../utils/report'); -const setDeclarationValue = require('../utils/setDeclarationValue'); -const valueParser = require('postcss-value-parser'); - -/** @typedef {import('postcss-value-parser').Node} ValueParserNode */ -/** @typedef {import('postcss-value-parser').DivNode} ValueParserDivNode */ -/** @typedef {(args: { source: string, index: number, err: (message: string) => void }) => void} LocationChecker */ - -/** - * @param {{ - * root: import('postcss').Root, - * locationChecker: LocationChecker, - * fix: ((node: ValueParserDivNode, index: number, nodes: ValueParserNode[]) => boolean) | null, - * result: import('stylelint').PostcssResult, - * checkedRuleName: string, - * }} opts - */ -module.exports = function functionCommaSpaceChecker(opts) { - opts.root.walkDecls((decl) => { - const declValue = getDeclarationValue(decl); - - let hasFixed; - const parsedValue = valueParser(declValue); - - parsedValue.walk((valueNode) => { - if (valueNode.type !== 'function') { - return; - } - - if (!isStandardSyntaxFunction(valueNode)) { - return; - } - - // Ignore `url()` arguments, which may contain data URIs or other funky stuff - if (valueNode.value.toLowerCase() === 'url') { - return; - } - - const argumentStrings = valueNode.nodes.map((node) => valueParser.stringify(node)); - - const functionArguments = (() => { - // Remove function name and parens - let result = valueNode.before + argumentStrings.join('') + valueNode.after; - - // 1. Remove comments including preceding whitespace (when only succeeded by whitespace) - // 2. Remove all other comments, but leave adjacent whitespace intact - // eslint-disable-next-line regexp/no-dupe-disjunctions -- TODO: Possible to simplify the regex. - result = result.replace(/( *\/(\*.*\*\/(?!\S)|\/.*)|(\/(\*.*\*\/|\/.*)))/, ''); - - return result; - })(); - - /** - * Gets the index of the comma for checking. - * @param {ValueParserDivNode} commaNode The comma node - * @param {number} nodeIndex The index of the comma node - * @returns {number} The index of the comma for checking - */ - const getCommaCheckIndex = (commaNode, nodeIndex) => { - let commaBefore = - valueNode.before + argumentStrings.slice(0, nodeIndex).join('') + commaNode.before; - - // 1. Remove comments including preceding whitespace (when only succeeded by whitespace) - // 2. Remove all other comments, but leave adjacent whitespace intact - // eslint-disable-next-line regexp/no-dupe-disjunctions -- TODO: Possible to simplify the regex. - commaBefore = commaBefore.replace(/( *\/(\*.*\*\/(?!\S)|\/.*)|(\/(\*.*\*\/|\/.*)))/, ''); - - return commaBefore.length; - }; - - /** @type {{ commaNode: ValueParserDivNode, checkIndex: number, nodeIndex: number }[]} */ - const commaDataList = []; - - for (const [nodeIndex, node] of valueNode.nodes.entries()) { - if (node.type !== 'div' || node.value !== ',') { - continue; - } - - const checkIndex = getCommaCheckIndex(node, nodeIndex); - - commaDataList.push({ - commaNode: node, - checkIndex, - nodeIndex, - }); - } - - for (const { commaNode, checkIndex, nodeIndex } of commaDataList) { - opts.locationChecker({ - source: functionArguments, - index: checkIndex, - err: (message) => { - const index = - declarationValueIndex(decl) + commaNode.sourceIndex + commaNode.before.length; - - if (opts.fix && opts.fix(commaNode, nodeIndex, valueNode.nodes)) { - hasFixed = true; - - return; - } - - report({ - index, - message, - node: decl, - result: opts.result, - ruleName: opts.checkedRuleName, - }); - }, - }); - } - }); - - if (hasFixed) { - setDeclarationValue(decl, parsedValue.toString()); - } - }); -}; diff --git a/lib/rules/functionCommaSpaceFix.js b/lib/rules/functionCommaSpaceFix.js deleted file mode 100644 index b4ad08c68a..0000000000 --- a/lib/rules/functionCommaSpaceFix.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict'; - -/** - * @param {{ - * div: import('postcss-value-parser').DivNode, - * index: number, - * nodes: import('postcss-value-parser').Node[], - * expectation: string, - * position: 'before' | 'after', - * symb: string, - * }} params - * @returns {boolean} - */ -module.exports = function functionCommaSpaceFix(params) { - const { div, index, nodes, expectation, position, symb } = params; - - if (expectation.startsWith('always')) { - div[position] = symb; - - return true; - } - - if (expectation.startsWith('never')) { - div[position] = ''; - - for (let i = index + 1; i < nodes.length; i++) { - const node = nodes[i]; - - if (node === undefined) { - continue; - } - - if (node.type === 'comment') { - continue; - } - - if (node.type === 'space') { - node.value = ''; - continue; - } - - break; - } - - return true; - } - - return false; -}; diff --git a/lib/rules/indentation/README.md b/lib/rules/indentation/README.md deleted file mode 100644 index a954b14bbc..0000000000 --- a/lib/rules/indentation/README.md +++ /dev/null @@ -1,340 +0,0 @@ -# indentation - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Specify indentation. - - -```css - |@media print { - | a { - | ↑ background-position: top left, - | ↑ ↑ top right; - | ↑}↑ ↑ - |}↑ ↑ ↑ -/** ↑ ↑ ↑ - * The indentation at these three points */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`int|"tab"`, where `int` is the number of spaces - -### `2` - -Always indent at-rules, rules, comments, declarations, inside parentheses and multi-line values by 2 spaces. - -The following patterns are considered problems: - - -```css -@media print { -a { -background-position: top left, -top right; -} -} -``` - - -```css -@media print { -a { - background-position: top left, - top right; - } -} -``` - - -```css -@media print { - a { - background-position: top left, - top right; - } -} -``` - - -```css -@media print { - a, - b { - background-position: top left, - top right; - } -} -``` - - -```css -a { -/* blergh */ - color: pink; -} - /* blergh */ -``` - - -```css -@media print, -(-webkit-min-device-pixel-ratio: 1.25), -(min-resolution: 120dpi) {} -``` - - -```css -a { - color: rgb( - 255, - 255, - 255 - ); - top: 0; -} -``` - -The following patterns are _not_ considered problems: - - -```css -@media print { - a { - background-position: top left, - top right; - } -} -``` - - -```css -@media print { - a, - b { - background-position: top left, - top right; - } -} -``` - - -```css -a { - /* blergh */ - color: pink; -} -/* blergh */ -``` - - -```css -@media print, - (-webkit-min-device-pixel-ratio: 1.25), - (min-resolution: 120dpi) {} -``` - - -```css -a { - color: rgb( - 255, - 255, - 255 - ); - top: 0; -} -``` - -## Optional secondary options - -### `baseIndentLevel: int|"auto"` - -By default, the indent level of the CSS code block in non-CSS-like files is determined by the shortest indent of non-empty line. The setting `baseIndentLevel` allows you to define a relative indent level based on CSS code block opening or closing line. - -For example, with `[ 2, { baseIndentLevel: 1 } ]`, CSS should be indented 1 levels higher than ` - - -``` - -### `indentInsideParens: "twice"|"once-at-root-twice-in-block"` - -By default, _one extra_ indentation (of your specified type) is expected after newlines inside parentheses, and the closing parenthesis is expected to have no extra indentation. - -If you would like to change the quantity of extra indentation inside parentheses, use this option. - -`"twice"` means you expect two extra indentations (of your specified type) after newlines inside parentheses, and expect the closing parenthesis to have one extra indentation. For example: - - -```css -a { - color: rgb( - 255, - 255, - 255 - ); - top: 0; -} -``` - -`"once-at-root-twice-in-block"` means two things: You want the behavior of `"once"`, as documented above, when the parenthetical expression is part of a node that is an immediate descendent of the root — i.e. not inside a block. And you want the behavior of `"twice"`, as documented above, when the parenthetical expression is part of a node that is inside a block. For example: - - -```css -@import ( - "foo.css" -); - -a { - color: rgb( - 255, - 255, - 255 - ); - top: 0; -} -``` - -### `indentClosingBrace: true|false` - -If `true`, the closing brace of a block (rule or at-rule) will be expected at the same indentation level as the block's inner nodes. - -For example, with `indentClosingBrace: true`. - -The following patterns are considered problems: - - -```css -a { - color: pink; -} -``` - - -```css -@media print { - a { - color: pink; - } -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { - color: pink; - } -``` - - -```css -@media print { - a { - color: pink; - } - } -``` - -### `except: ["block", "param", "value"]` - -Do _not_ indent for these things. - -For example, with `2`. - -The following patterns are considered problems: - - -```css -@media print, - (-webkit-min-device-pixel-ratio: 1.25), - (min-resolution: 120dpi) { - a { - background-position: top left, - top right; - } -} -``` - -The following patterns are _not_ considered problems: - - -```css -@media print, -(-webkit-min-device-pixel-ratio: 1.25), -(min-resolution: 120dpi) { -a { -background-position: top left, -top right; -} -} -``` - -### `ignore: ["inside-parens", "param", "value"]` - -#### `"inside-parens"` - -Ignore the indentation inside parentheses. - -For example, with `2`. - -The following patterns are _not_ considered problems: - - -```css -a { - color: rgb( -255, - 255, - 255 - ); - top: 0; -} -``` - -#### `"param"` - -Ignore the indentation of at-rule params. - -For example, with `2`. - -The following patterns are _not_ considered problems: - - -```css -@media print, - (-webkit-min-device-pixel-ratio: 1.25), - (min-resolution: 120dpi) { -} -``` - -#### `"value"` - -Ignore the indentation of values. - -For example, with `2`. - -The following patterns are _not_ considered problems: - - -```css -a { - background-position: top left, -top right, - bottom left, - bottom right; -} -``` diff --git a/lib/rules/indentation/__tests__/at-rules.js b/lib/rules/indentation/__tests__/at-rules.js deleted file mode 100644 index b902b3a55e..0000000000 --- a/lib/rules/indentation/__tests__/at-rules.js +++ /dev/null @@ -1,346 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: [2], - fix: true, - - accept: [ - { - code: '@media print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + '}', - }, - { - code: '@media\n' + ' print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + '}', - }, - { - code: - '@media print {\n' + - ' a {\n' + - ' color: pink;\n' + - ' }\n' + - '}\n' + - '\n' + - '@media screen {\n' + - ' b { color: orange; }\n' + - '}', - }, - { - code: '@media print {\r\n' + ' a {\r\n' + ' color: pink;\r\n' + ' }\r\n' + '}', - }, - { - code: '@media\r\n' + ' print {\r\n' + ' a {\r\n' + ' color: pink;\r\n' + ' }\r\n' + '}', - }, - { - code: - '@media print {\r\n' + - ' a {\r\n' + - ' color: pink;\r\n' + - ' }\r\n' + - '}\r\n' + - '\r\n' + - '@media screen {\r\n' + - ' b { color: orange; }\r\n' + - '}', - }, - ], - - reject: [ - { - code: '\n' + ' @media print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + '}', - fixed: '\n' + '@media print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + '}', - - message: messages.expected('0 spaces'), - line: 2, - column: 3, - }, - { - code: '@media print {\n' + 'a {\n' + ' color: pink;\n' + ' }\n' + '}', - fixed: '@media print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + '}', - - message: messages.expected('2 spaces'), - line: 2, - column: 1, - }, - { - code: '@media print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + '}', - fixed: '@media print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + '}', - - message: messages.expected('4 spaces'), - line: 3, - column: 3, - }, - { - code: '@media print {\n' + ' a {\n' + ' color: pink;\n' + '}\n' + '}', - fixed: '@media print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + '}', - - message: messages.expected('2 spaces'), - line: 4, - column: 1, - }, - { - code: '@media print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + '\t}', - fixed: '@media print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + '}', - - message: messages.expected('0 spaces'), - line: 5, - column: 2, - }, - { - code: - '\r\n' + ' @media print {\r\n' + ' a {\r\n' + ' color: pink;\r\n' + ' }\r\n' + '}', - fixed: '\r\n' + '@media print {\r\n' + ' a {\r\n' + ' color: pink;\r\n' + ' }\r\n' + '}', - - message: messages.expected('0 spaces'), - line: 2, - column: 3, - }, - { - code: '@media print {\r\n' + 'a {\r\n' + ' color: pink;\r\n' + ' }\r\n' + '}', - fixed: '@media print {\r\n' + ' a {\r\n' + ' color: pink;\r\n' + ' }\r\n' + '}', - - message: messages.expected('2 spaces'), - line: 2, - column: 1, - }, - { - code: '@media print {\r\n' + ' a {\r\n' + ' color: pink;\r\n' + ' }\r\n' + '}', - fixed: '@media print {\r\n' + ' a {\r\n' + ' color: pink;\r\n' + ' }\r\n' + '}', - - message: messages.expected('4 spaces'), - line: 3, - column: 3, - }, - { - code: '@media print {\r\n' + ' a {\r\n' + ' color: pink;\r\n' + '}\r\n' + '}', - fixed: '@media print {\r\n' + ' a {\r\n' + ' color: pink;\r\n' + ' }\r\n' + '}', - - message: messages.expected('2 spaces'), - line: 4, - column: 1, - }, - { - code: '@media print {\r\n' + ' a {\r\n' + ' color: pink;\r\n' + ' }\r\n' + '\t}', - fixed: '@media print {\r\n' + ' a {\r\n' + ' color: pink;\r\n' + ' }\r\n' + '}', - - message: messages.expected('0 spaces'), - line: 5, - column: 2, - }, - { - code: '@media\n' + ' print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + '}', - fixed: '@media\n' + ' print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + '}', - description: 'at-rule parameters on the next line', - - message: messages.expected('2 spaces'), - line: 2, - column: 2, - }, - { - code: '@media\r\n' + ' print {\r\n' + ' a {\r\n' + ' color: pink;\r\n' + ' }\r\n' + '}', - fixed: - '@media\r\n' + ' print {\r\n' + ' a {\r\n' + ' color: pink;\r\n' + ' }\r\n' + '}', - description: 'at-rule parameters on the next line (CRLF)', - - message: messages.expected('2 spaces'), - line: 2, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: ['tab', { except: ['block'] }], - fix: true, - - accept: [ - { - code: '@media print {\n' + '\n' + 'a {\n' + '\tcolor: pink;\n' + '}\n' + '\n' + '}', - }, - { - code: - '@media print,\n' + - '\t(-webkit-min-device-pixel-ratio: 1.25),\n' + - '\t(min-resolution: 120dpi) {}', - }, - ], - - reject: [ - { - code: '@media print {\n' + '\n' + '\ta {\n' + '\tcolor: pink;\n' + '}\n' + '\n' + '}', - fixed: '@media print {\n' + '\n' + 'a {\n' + '\tcolor: pink;\n' + '}\n' + '\n' + '}', - - message: messages.expected('0 tabs'), - line: 3, - column: 2, - }, - { - code: '@media print {\n' + '\n' + 'a {\n' + 'color: pink;\n' + '}\n' + '\n' + '}', - fixed: '@media print {\n' + '\n' + 'a {\n' + '\tcolor: pink;\n' + '}\n' + '\n' + '}', - - message: messages.expected('1 tab'), - line: 4, - column: 1, - }, - { - code: - '@media print,\n' + - ' (-webkit-min-device-pixel-ratio: 1.25),\n' + - '\t(min-resolution: 120dpi) {}', - fixed: - '@media print,\n' + - '\t(-webkit-min-device-pixel-ratio: 1.25),\n' + - '\t(min-resolution: 120dpi) {}', - - description: 'multi-line at-rule params', - message: messages.expected('1 tab'), - line: 2, - column: 3, - }, - { - code: - '@media print,\r\n' + - ' (-webkit-min-device-pixel-ratio: 1.25),\r\n' + - '\t(min-resolution: 120dpi) {}', - fixed: - '@media print,\r\n' + - '\t(-webkit-min-device-pixel-ratio: 1.25),\r\n' + - '\t(min-resolution: 120dpi) {}', - - description: 'multi-line at-rule params (CRLF)', - message: messages.expected('1 tab'), - line: 2, - column: 3, - }, - ], -}); - -testRule({ - ruleName, - config: [4, { except: ['param'] }], - fix: true, - - accept: [ - { - code: - '@media print,\n' + - '(-webkit-min-device-pixel-ratio: 1.25),\n' + - '(min-resolution: 120dpi) {}', - }, - ], - - reject: [ - { - code: - '@media print,\n' + - ' (-webkit-min-device-pixel-ratio: 1.25),\n' + - '(min-resolution: 120dpi) {}', - fixed: - '@media print,\n' + - '(-webkit-min-device-pixel-ratio: 1.25),\n' + - '(min-resolution: 120dpi) {}', - - description: 'multi-line at-rule params, no params indent', - message: messages.expected('0 spaces'), - line: 2, - column: 3, - }, - { - code: - '@media print,\r\n' + - ' (-webkit-min-device-pixel-ratio: 1.25),\r\n' + - '(min-resolution: 120dpi) {}', - fixed: - '@media print,\r\n' + - '(-webkit-min-device-pixel-ratio: 1.25),\r\n' + - '(min-resolution: 120dpi) {}', - - description: 'multi-line at-rule params, no params indent (CRLF)', - message: messages.expected('0 spaces'), - line: 2, - column: 3, - }, - ], -}); - -testRule({ - ruleName, - config: [2, { ignore: ['param'] }], - fix: true, - - accept: [ - { - code: - '@media print,\n' + - '(-webkit-min-device-pixel-ratio: 1.25),\n' + - '(min-resolution: 120dpi) {}', - }, - { - code: - '@media print,\n' + - ' (-webkit-min-device-pixel-ratio: 1.25),\n' + - '(min-resolution: 120dpi) {}', - }, - ], - - reject: [ - { - code: '\n' + ' @media print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + '}', - fixed: '\n' + '@media print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + '}', - - message: messages.expected('0 spaces'), - line: 2, - column: 3, - }, - ], -}); - -testRule({ - ruleName, - config: [ - 2, - { - indentClosingBrace: true, - }, - ], - fix: true, - - accept: [ - { - code: '@media print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + ' }', - }, - { - code: - '@media print {\n' + - ' a {\n' + - ' color: pink;\n' + - ' }\n' + - ' }\n' + - '\n' + - '@media screen {\n' + - ' b { color: orange; }\n' + - ' }', - }, - ], - - reject: [ - { - code: '\n' + '@media print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + ' }', - fixed: '\n' + '@media print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + ' }', - - message: messages.expected('2 spaces'), - line: 6, - column: 2, - }, - { - code: '@media print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + ' }', - fixed: '@media print {\n' + ' a {\n' + ' color: pink;\n' + ' }\n' + ' }', - - message: messages.expected('4 spaces'), - line: 4, - column: 4, - }, - ], -}); diff --git a/lib/rules/indentation/__tests__/comments.js b/lib/rules/indentation/__tests__/comments.js deleted file mode 100644 index 49b47d4cf3..0000000000 --- a/lib/rules/indentation/__tests__/comments.js +++ /dev/null @@ -1,93 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['tab'], - fix: true, - - accept: [ - { - code: '/* blergh */', - }, - { - code: '.foo {\n' + '\t/* blergh */\n' + '\ttop: 0;\n' + '}', - }, - { - code: - '@media print {\n' + '\t.foo {\n' + '\t\t/* blergh */\n' + '\t\ttop: 0;\n' + '\t}\n' + '}', - }, - { - code: '/* blergh */', - }, - { - code: '.foo {\r\n' + '\t/* blergh */\r\n' + '\ttop: 0;\r\n' + '}', - }, - { - code: - '@media print {\r\n' + - '\t.foo {\r\n' + - '\t\t/* blergh */\r\n' + - '\t\ttop: 0;\r\n' + - '\t}\r\n' + - '}', - }, - ], - - reject: [ - { - code: ' /* blergh */', - fixed: '/* blergh */', - message: messages.expected('0 tabs'), - line: 1, - column: 2, - }, - { - code: '.foo {\n' + '\t\t/* blergh */\n' + '\ttop: 0;\n' + '}', - fixed: '.foo {\n' + '\t/* blergh */\n' + '\ttop: 0;\n' + '}', - - message: messages.expected('1 tab'), - line: 2, - column: 3, - }, - { - code: - '@media print {\n' + '\t.foo {\n' + '\t/* blergh */\n' + '\t\ttop: 0;\n' + '\t}\n' + '}', - fixed: - '@media print {\n' + '\t.foo {\n' + '\t\t/* blergh */\n' + '\t\ttop: 0;\n' + '\t}\n' + '}', - - message: messages.expected('2 tabs'), - line: 3, - column: 2, - }, - { - code: '.foo {\r\n' + '\t\t/* blergh */\r\n' + '\ttop: 0;\r\n' + '}', - fixed: '.foo {\r\n' + '\t/* blergh */\r\n' + '\ttop: 0;\r\n' + '}', - - message: messages.expected('1 tab'), - line: 2, - column: 3, - }, - { - code: - '@media print {\r\n' + - '\t.foo {\r\n' + - '\t/* blergh */\r\n' + - '\t\ttop: 0;\r\n' + - '\t}\r\n' + - '}', - fixed: - '@media print {\r\n' + - '\t.foo {\r\n' + - '\t\t/* blergh */\r\n' + - '\t\ttop: 0;\r\n' + - '\t}\r\n' + - '}', - - message: messages.expected('2 tabs'), - line: 3, - column: 2, - }, - ], -}); diff --git a/lib/rules/indentation/__tests__/document-with-roots.js b/lib/rules/indentation/__tests__/document-with-roots.js deleted file mode 100644 index 0aa7d7040c..0000000000 --- a/lib/rules/indentation/__tests__/document-with-roots.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -const { parse: postcssParse, stringify, Document, Input } = require('postcss'); -const { ruleName } = require('..'); - -const parse = (source, opts) => { - const doc = new Document(); - const root = postcssParse(source, opts); - - root.parent = doc; - root.document = doc; - doc.nodes.push(root); - doc.source = { - input: new Input(source, opts), - start: { line: 1, column: 1, offset: 0 }, - }; - - return doc; -}; - -testRule({ - ruleName, - config: [2], - fix: true, - customSyntax: { - parse, - stringify, - }, - - accept: [ - { - code: '.foo {\n' + ' color: hotpink;\n' + '}', - }, - ], - - reject: [], -}); diff --git a/lib/rules/indentation/__tests__/functions.js b/lib/rules/indentation/__tests__/functions.js deleted file mode 100644 index d4b75846d7..0000000000 --- a/lib/rules/indentation/__tests__/functions.js +++ /dev/null @@ -1,792 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: [2], - fix: true, - - accept: [ - { - code: '.foo {\n' + ' color: rgb(0, 0, 0);\n' + '}', - }, - { - code: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - '}', - }, - { - code: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ');', - description: 'sass-list', - }, - { - code: - '$colors: (\n' + - ' primary: (\n' + - ' base: $route;\n' + - ' contrast: $white\n' + - ' )\n' + - ');', - description: 'nested Sass map', - }, - { - code: - 'background:\n' + - ' linear-gradient(\n' + - ' to bottom,\n' + - ' transparentize($gray-dark, 1) 0%,\n' + - ' transparentize($gray-dark, 0.1) 100%\n' + - ' );', - description: 'nested parenthetical inside multiline value', - }, - { - code: '.foo {\r\n' + ' color: rgb(0, 0, 0);\r\n' + '}', - }, - { - code: - '.foo {\r\n' + - ' color: rgb(\r\n' + - ' 0,\r\n' + - ' 0,\r\n' + - ' 0\r\n' + - ' );\r\n' + - ' top: 0;\r\n' + - '}', - }, - { - code: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ');', - description: 'sass-list', - }, - { - code: - '$colors: (\r\n' + - ' primary: (\r\n' + - ' base: $route;\r\n' + - ' contrast: $white\r\n' + - ' )\r\n' + - ');', - description: 'nested Sass map', - }, - { - code: - 'background:\r\n' + - ' linear-gradient(\r\n' + - ' to bottom,\r\n' + - ' transparentize($gray-dark, 1) 0%,\r\n' + - ' transparentize($gray-dark, 0.1) 100%\r\n' + - ' );', - description: 'nested parenthetical inside multiline value', - }, - ], - - reject: [ - { - code: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - '0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - '}', - fixed: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - '}', - message: messages.expected('4 spaces'), - line: 4, - column: 1, - }, - { - code: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - '}', - fixed: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - '}', - message: messages.expected('2 spaces'), - line: 6, - column: 5, - }, - { - code: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ');', - fixed: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ');', - description: 'sass-list', - message: messages.expected('2 spaces'), - line: 4, - column: 2, - }, - { - code: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ' );', - fixed: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ');', - description: 'sass-list', - message: messages.expected('0 spaces'), - line: 5, - column: 3, - }, - { - code: - '.foo {\r\n' + - ' color: rgb(\r\n' + - ' 0,\r\n' + - '0,\r\n' + - ' 0\r\n' + - ' );\r\n' + - ' top: 0;\r\n' + - '}', - fixed: - '.foo {\r\n' + - ' color: rgb(\r\n' + - ' 0,\r\n' + - ' 0,\r\n' + - ' 0\r\n' + - ' );\r\n' + - ' top: 0;\r\n' + - '}', - message: messages.expected('4 spaces'), - line: 4, - column: 1, - }, - { - code: - '.foo {\r\n' + - ' color: rgb(\r\n' + - ' 0,\r\n' + - ' 0,\r\n' + - ' 0\r\n' + - ' );\r\n' + - ' top: 0;\r\n' + - '}', - fixed: - '.foo {\r\n' + - ' color: rgb(\r\n' + - ' 0,\r\n' + - ' 0,\r\n' + - ' 0\r\n' + - ' );\r\n' + - ' top: 0;\r\n' + - '}', - message: messages.expected('2 spaces'), - line: 6, - column: 5, - }, - { - code: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ');', - fixed: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ');', - description: 'sass-list', - message: messages.expected('2 spaces'), - line: 4, - column: 2, - }, - { - code: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ' );', - fixed: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ');', - description: 'sass-list', - message: messages.expected('0 spaces'), - line: 5, - column: 3, - }, - { - code: - 'background:\n' + - 'linear-gradient(\n' + - ' to bottom,\n' + - ' transparentize($gray-dark, 1) 0%,\n' + - ' transparentize($gray-dark, 0.1) 100%\n' + - ' );', - fixed: - 'background:\n' + - ' linear-gradient(\n' + - ' to bottom,\n' + - ' transparentize($gray-dark, 1) 0%,\n' + - ' transparentize($gray-dark, 0.1) 100%\n' + - ' );', - - message: messages.expected('2 spaces'), - line: 2, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: [2, { ignore: ['inside-parens'] }], - fix: true, - - accept: [ - { - code: '.foo {\n' + ' color: rgb(\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ' );\n' + '}', - }, - { - code: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - '}', - }, - { - code: '.foo {\n' + ' color: rgb(\n' + '0,\n' + '0,\n' + '0\n' + ' );\n' + '}', - }, - { - code: - '.foo {\n' + - ' color: bar(\n' + - ' rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' )\n' + - ' );\n' + - '}', - }, - { - code: - '.foo {\n' + - ' color: bar(\n' + - ' rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' )\n' + - ' );\n' + - '}', - }, - { - code: - '$tooltip-default-settings: (\n' + - ' tooltip-gutter: 8px 10px,\n' + - ' tooltip-border: 1px solid,\n' + - ');', - description: 'Sass maps ignored', - }, - ], -}); - -testRule({ - ruleName, - config: ['tab', { indentClosingBrace: false }], - fix: true, - - accept: [ - { - code: '$some-list: (\n' + '\tvar: value,\n' + '\tvar: value,\n' + '\tvar: value\n' + ');', - description: 'tabbed sass-list with property value pairs', - }, - ], - - reject: [ - { - code: '$some-list: (\n' + '\tvar: value,\n' + '\tvar: value,\n' + '\t\tvar: value\n' + ');', - fixed: '$some-list: (\n' + '\tvar: value,\n' + '\tvar: value,\n' + '\tvar: value\n' + ');', - description: 'tabbed sass-list with property value pairs', - message: messages.expected('1 tab'), - line: 4, - column: 3, - }, - ], -}); - -testRule({ - ruleName, - config: [2, { indentInsideParens: 'twice' }], - fix: true, - - accept: [ - { - code: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - '}', - }, - { - code: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ' );', - description: 'sass-list', - }, - { - code: - '.foo {\r\n' + - ' color: rgb(\r\n' + - ' 0,\r\n' + - ' 0,\r\n' + - ' 0\r\n' + - ' );\r\n' + - ' top: 0;\r\n' + - '}', - }, - { - code: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ' );', - description: 'sass-list', - }, - ], - - reject: [ - { - code: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - '}', - fixed: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - '}', - message: messages.expected('6 spaces'), - line: 4, - column: 5, - }, - { - code: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - '}', - fixed: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - '}', - message: messages.expected('4 spaces'), - line: 6, - column: 6, - }, - { - code: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ' );', - fixed: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ' );', - description: 'sass-list', - message: messages.expected('4 spaces'), - line: 4, - column: 4, - }, - { - code: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ' );', - fixed: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ' );', - description: 'sass-list', - message: messages.expected('2 spaces'), - line: 5, - column: 2, - }, - { - code: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ' );', - fixed: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ' );', - description: 'sass-list', - message: messages.expected('4 spaces'), - line: 4, - column: 4, - }, - { - code: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ' );', - fixed: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ' );', - description: 'sass-list', - message: messages.expected('2 spaces'), - line: 5, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: [2, { indentInsideParens: 'once-at-root-twice-in-block' }], - fix: true, - - accept: [ - { - code: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - '}', - }, - { - code: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ');', - description: 'sass-list', - }, - { - code: - '.foo {\r\n' + - ' color: rgb(\r\n' + - ' 0,\r\n' + - ' 0,\r\n' + - ' 0\r\n' + - ' );\r\n' + - ' top: 0;\r\n' + - '}', - }, - { - code: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ');', - description: 'sass-list', - }, - ], - - reject: [ - { - code: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - '}', - fixed: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - '}', - message: messages.expected('6 spaces'), - line: 4, - column: 5, - }, - { - code: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - '}', - fixed: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - '}', - message: messages.expected('4 spaces'), - line: 6, - column: 6, - }, - { - code: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ' );', - fixed: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ');', - description: 'sass-list', - message: messages.expected('0 spaces'), - line: 5, - column: 3, - }, - { - code: - '.foo {\r\n' + - ' color: rgb(\r\n' + - ' 0,\r\n' + - ' 0,\r\n' + - ' 0\r\n' + - ' );\r\n' + - ' top: 0;\r\n' + - '}', - fixed: - '.foo {\r\n' + - ' color: rgb(\r\n' + - ' 0,\r\n' + - ' 0,\r\n' + - ' 0\r\n' + - ' );\r\n' + - ' top: 0;\r\n' + - '}', - message: messages.expected('6 spaces'), - line: 4, - column: 5, - }, - { - code: - '.foo {\r\n' + - ' color: rgb(\r\n' + - ' 0,\r\n' + - ' 0,\r\n' + - ' 0\r\n' + - ' );\r\n' + - ' top: 0;\r\n' + - '}', - fixed: - '.foo {\r\n' + - ' color: rgb(\r\n' + - ' 0,\r\n' + - ' 0,\r\n' + - ' 0\r\n' + - ' );\r\n' + - ' top: 0;\r\n' + - '}', - message: messages.expected('4 spaces'), - line: 6, - column: 6, - }, - { - code: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ' );', - fixed: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ');', - description: 'sass-list', - message: messages.expected('0 spaces'), - line: 5, - column: 3, - }, - ], -}); - -testRule({ - ruleName, - config: [ - 2, - { - indentInsideParens: 'once-at-root-twice-in-block', - indentClosingBrace: true, - }, - ], - fix: true, - - accept: [ - { - code: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - ' }', - }, - { - code: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ' );', - description: 'sass-list', - }, - { - code: '$some-list: (\r\n' + ' 0,\r\n' + ' 0\r\n' + ' );', - description: 'sass-list', - }, - ], - - reject: [ - { - code: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - ' }', - fixed: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - ' }', - message: messages.expected('6 spaces'), - line: 4, - column: 5, - }, - { - code: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - ' }', - fixed: - '.foo {\n' + - ' color: rgb(\n' + - ' 0,\n' + - ' 0,\n' + - ' 0\n' + - ' );\n' + - ' top: 0;\n' + - ' }', - message: messages.expected('6 spaces'), - line: 6, - column: 6, - }, - { - code: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ' );', - fixed: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ' );', - description: 'sass-list', - message: messages.expected('2 spaces'), - line: 4, - column: 2, - }, - { - code: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ');', - fixed: '$some-list: (\n' + ' 0,\n' + ' 0,\n' + ' 0\n' + ' );', - description: 'sass-list', - message: messages.expected('2 spaces'), - line: 5, - column: 1, - }, - { - code: - '.foo {\r\n' + - ' color: rgb(\r\n' + - ' 0,\r\n' + - ' 0,\r\n' + - ' 0\r\n' + - ' );\r\n' + - ' top: 0;\r\n' + - ' }', - fixed: - '.foo {\r\n' + - ' color: rgb(\r\n' + - ' 0,\r\n' + - ' 0,\r\n' + - ' 0\r\n' + - ' );\r\n' + - ' top: 0;\r\n' + - ' }', - message: messages.expected('6 spaces'), - line: 4, - column: 5, - }, - { - code: - '.foo {\r\n' + - ' color: rgb(\r\n' + - ' 0,\r\n' + - ' 0,\r\n' + - ' 0\r\n' + - ' );\r\n' + - ' top: 0;\r\n' + - ' }', - fixed: - '.foo {\r\n' + - ' color: rgb(\r\n' + - ' 0,\r\n' + - ' 0,\r\n' + - ' 0\r\n' + - ' );\r\n' + - ' top: 0;\r\n' + - ' }', - message: messages.expected('6 spaces'), - line: 6, - column: 6, - }, - { - code: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ' );', - fixed: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ' );', - description: 'sass-list', - message: messages.expected('2 spaces'), - line: 4, - column: 2, - }, - { - code: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ');', - fixed: '$some-list: (\r\n' + ' 0,\r\n' + ' 0,\r\n' + ' 0\r\n' + ' );', - description: 'sass-list', - message: messages.expected('2 spaces'), - line: 5, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: [2], - customSyntax: 'postcss-less', - // fix: true, - - accept: [ - { - code: - '.foo {\n' + ' .mixin(\n' + ' @foo,\n' + ' @bar,\n' + ' @baz\n' + ' );\n' + '}', - description: 'Less mixin with multi-line arguments', - }, - { - code: - '.foo {\r\n' + - ' .mixin(\r\n' + - ' @foo,\r\n' + - ' @bar,\r\n' + - ' @baz\r\n' + - ' );\r\n' + - '}', - description: 'Less mixin with multi-line arguments', - }, - { - code: - '.foo {\r\n' + - ' .mixin(\r\n' + - ' {\r\n' + - ' @baz\r\n' + - ' }\r\n' + - ' );\r\n' + - '}', - description: 'Less mixin with multi-line arguments with rule parameter', - }, - { - code: '.foo {\r\n' + ' .mixin(@foo, {\r\n' + ' @baz\r\n' + ' });\r\n' + '}', - description: 'Less mixin with multi-line arguments with rule parameter 2', - }, - { - code: '.mixin({\r\n' + ' @foo\r\n' + '}, @bar);', - description: 'Less mixin with multi-line arguments with rule parameter 3', - }, - ], -}); diff --git a/lib/rules/indentation/__tests__/html.js b/lib/rules/indentation/__tests__/html.js deleted file mode 100644 index 256cb0fb11..0000000000 --- a/lib/rules/indentation/__tests__/html.js +++ /dev/null @@ -1,627 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['tab'], - customSyntax: 'postcss-html', - fix: true, - - accept: [ - { - code: ` -`, - }, - { - code: ` -`, - }, - { - code: ` -`, - }, - { - code: '', - }, - ], - - reject: [ - { - code: ` -`, - fixed: ` -`, - message: messages.expected('2 tabs'), - line: 4, - column: 2, - }, - { - code: ` -`, - fixed: ` -`, - warnings: [ - { - message: messages.expected('1 tab'), - line: 3, - column: 3, - }, - { - message: messages.expected('1 tab'), - line: 5, - column: 5, - }, - { - message: messages.expected('2 tabs'), - line: 4, - column: 7, - }, - ], - }, - { - code: ` -`, - fixed: ` -`, - message: messages.expected('1 tab'), - line: 4, - column: 1, - }, - { - code: ` -`, - fixed: ` -`, - warnings: [ - { - message: messages.expected('1 tab'), - line: 3, - column: 3, - }, - { - message: messages.expected('1 tab'), - line: 5, - column: 3, - }, - { - message: messages.expected('2 tabs'), - line: 4, - column: 3, - }, - ], - }, - { - code: ` -\t`, - fixed: ` -\t`, - warnings: [ - { - message: messages.expected('1 tab'), - line: 3, - column: 5, - }, - { - message: messages.expected('1 tab'), - line: 5, - column: 5, - }, - { - message: messages.expected('2 tabs'), - line: 4, - column: 9, - }, - { - message: messages.expected('1 tab'), - line: 6, - column: 5, - }, - { - message: messages.expected('1 tab'), - line: 8, - column: 5, - }, - { - message: messages.expected('2 tabs'), - line: 7, - column: 7, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: [2], - customSyntax: 'postcss-html', - fix: true, - - accept: [ - { - code: ` -`, - }, - { - code: ` -`, - }, - { - code: ` -`, - }, - ], - reject: [ - { - code: ` -`, - fixed: ` -`, - message: messages.expected('2 spaces'), - line: 3, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: [ - 'tab', - { - baseIndentLevel: 1, - }, - ], - customSyntax: 'postcss-html', - fix: true, - - accept: [ - { - code: ` -`, - }, - { - code: ` -\t`, - }, - { - code: ` -`, - }, - { - code: ` -`, - }, - { - code: ` -`, - }, - { - code: ` -\t`, - }, - { - code: ` -`, - }, - ], - reject: [ - { - code: ` -`, - fixed: ` -`, - warnings: [ - { - message: messages.expected('1 tab'), - line: 3, - column: 1, - }, - { - message: messages.expected('1 tab'), - line: 5, - column: 1, - }, - { - message: messages.expected('2 tabs'), - line: 4, - column: 2, - }, - ], - }, - { - code: ` -\t`, - fixed: ` -\t`, - warnings: [ - { - message: messages.expected('2 tabs'), - line: 3, - column: 2, - }, - { - message: messages.expected('2 tabs'), - line: 5, - column: 2, - }, - { - message: messages.expected('3 tabs'), - line: 4, - column: 3, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: [ - 'tab', - { - baseIndentLevel: 0, - }, - ], - customSyntax: 'postcss-html', - fix: true, - - accept: [ - { - code: ` -`, - }, - { - code: ` -\t`, - }, - ], - reject: [ - { - code: ` -`, - fixed: ` -`, - warnings: [ - { - message: messages.expected('0 tabs'), - line: 3, - column: 2, - }, - { - message: messages.expected('0 tabs'), - line: 5, - column: 2, - }, - { - message: messages.expected('1 tab'), - line: 4, - column: 3, - }, - ], - }, - { - code: ` -\t`, - fixed: ` -\t`, - warnings: [ - { - message: messages.expected('1 tab'), - line: 3, - column: 3, - }, - { - message: messages.expected('1 tab'), - line: 5, - column: 3, - }, - { - message: messages.expected('2 tabs'), - line: 4, - column: 4, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: [ - 2, - { - baseIndentLevel: 1, - }, - ], - customSyntax: 'postcss-html', - fix: true, - - accept: [ - { - code: ` -`, - }, - { - code: ` - `, - }, - { - code: ` -`, - }, - { - code: ` -`, - }, - { - code: ` -`, - }, - { - code: ` - `, - }, - { - code: ` -`, - }, - ], - reject: [ - { - code: ` -`, - fixed: ` -`, - warnings: [ - { - message: messages.expected('2 spaces'), - line: 3, - column: 1, - }, - { - message: messages.expected('2 spaces'), - line: 5, - column: 1, - }, - { - message: messages.expected('4 spaces'), - line: 4, - column: 3, - }, - ], - }, - { - code: ` - `, - fixed: ` - `, - warnings: [ - { - message: messages.expected('4 spaces'), - line: 4, - column: 7, - }, - { - message: messages.expected('4 spaces'), - line: 6, - column: 7, - }, - { - message: messages.expected('6 spaces'), - line: 5, - column: 9, - }, - ], - }, - ], -}); diff --git a/lib/rules/indentation/__tests__/rules.js b/lib/rules/indentation/__tests__/rules.js deleted file mode 100644 index 4dece20394..0000000000 --- a/lib/rules/indentation/__tests__/rules.js +++ /dev/null @@ -1,678 +0,0 @@ -'use strict'; - -const stripIndent = require('common-tags').stripIndent; -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: [2], - fix: true, - - accept: [ - { - code: '/* anything\n' + ' goes\n' + '\t\t\twithin a comment */\n', - }, - { - code: 'a { top: 0; } b { top: 1px; }', - }, - { - code: 'a {\n' + ' top: 0;\n' + '}\n' + 'b { top: 1px; bottom: 4px; }', - }, - { - code: 'a {\n' + ' top: 0;\n' + '} b { top: 1px; }', - }, - { - code: 'a {\n' + ' color: pink;\n' + '}', - }, - { - code: 'a { color: pink;\n' + '}', - }, - { - code: 'a {\n' + ' color: pink;\n' + '} b { top: 0; }', - }, - { - code: 'a { color: pink;\n' + ' top: 0; background: orange;\n' + '}', - }, - { - code: - 'a {\n' + ' color: pink;\n' + '}\n' + '\n' + '\n' + 'b {\n' + ' color: orange\n' + '}', - }, - { - code: 'a {\n' + ' color: pink;}', - }, - { - code: - 'a {\n' + - ' background-position: top left,\n' + - ' top right,\n' + - ' bottom left;\n' + - ' color: pink;\n' + - '}', - }, - { - code: - 'a {\n' + - ' background-position: top left,\n' + - ' top right,\n' + - ' bottom left\n' + - ' ;\n' + - '}', - }, - { - code: - 'a {\n' + - ' background-position: top left,\n' + - ' top right,\n' + - '\n' + - ' bottom left\n' + - ' ;\n' + - '}', - - description: 'weird empty line', - }, - { - code: 'a {\n' + ' *top: 1px;\n' + '}', - }, - { - code: 'a {\n' + ' _top: 1px;\n' + '}', - }, - { - code: '* { top: 0; }', - }, - { - code: '@media print {\n' + ' * { color: pink; }\n' + '}', - }, - { - code: 'a {\n' + ' @media print { color: pink; }\n' + '}', - }, - { - code: '/* anything\r\n' + ' goes\r\n' + '\t\t\twithin a comment */\r\n', - }, - { - code: 'a {\r\n' + ' top: 0;\r\n' + '}\r\n' + 'b { top: 1px; bottom: 4px; }', - }, - { - code: 'a {\r\n' + ' top: 0;\r\n' + '} b { top: 1px; }', - }, - { - code: 'a {\r\n' + ' color: pink;\r\n' + '}', - }, - { - code: 'a { color: pink;\r\n' + '}', - }, - { - code: 'a {\r\n' + ' color: pink;\r\n' + '} b { top: 0; }', - }, - { - code: 'a { color: pink;\r\n' + ' top: 0; background: orange;\r\n' + '}', - }, - { - code: - 'a {\r\n' + - ' color: pink;\r\n' + - '}\r\n' + - '\r\n' + - '\r\n' + - 'b {\r\n' + - ' color: orange\r\n' + - '}', - }, - { - code: 'a {\r\n' + ' color: pink;}', - }, - { - code: - 'a {\r\n' + - ' background-position: top left,\r\n' + - ' top right,\r\n' + - ' bottom left;\r\n' + - ' color: pink;\r\n' + - '}', - }, - { - code: - 'a {\r\n' + - ' background-position: top left,\r\n' + - ' top right,\r\n' + - ' bottom left\r\n' + - ' ;\r\n' + - '}', - }, - { - code: - 'a {\r\n' + - ' background-position: top left,\r\n' + - ' top right,\r\n' + - '\r\n' + - ' bottom left\r\n' + - ' ;\r\n' + - '}', - - description: 'weird empty line', - }, - { - code: 'a {\r\n' + ' *top: 1px;\r\n' + '}', - }, - { - code: 'a {\r\n' + ' _top: 1px;\r\n' + '}', - }, - { - code: '* { top: 0; }', - }, - { - code: '@media print {\r\n' + ' * { color: pink; }\r\n' + '}', - }, - { - code: '.a[disabled],\n' + '.b {\n' + ' color: pink;\n' + '}', - }, - { - code: stripIndent` - :not(.enabled - ) { - color: pink; - } - `, - }, - ], - - reject: [ - { - code: '\ta {\n' + ' color: pink;\n' + '}', - fixed: 'a {\n' + ' color: pink;\n' + '}', - - message: messages.expected('0 spaces'), - line: 1, - column: 2, - }, - { - code: 'a {\n' + ' color: pink;\n' + ' }', - fixed: 'a {\n' + ' color: pink;\n' + '}', - - message: messages.expected('0 spaces'), - line: 3, - column: 3, - }, - { - code: 'a,\n' + 'b {\n' + ' color: pink;\n' + ' }', - fixed: 'a,\n' + 'b {\n' + ' color: pink;\n' + '}', - - message: messages.expected('0 spaces'), - line: 4, - column: 3, - }, - { - code: 'a { color: pink;\n' + ' }', - fixed: 'a { color: pink;\n' + '}', - - message: messages.expected('0 spaces'), - line: 2, - column: 3, - }, - { - code: 'a {\n' + ' color: pink\n' + '}\n' + ' b {\n' + ' color: orange\n' + '}', - fixed: 'a {\n' + ' color: pink\n' + '}\n' + 'b {\n' + ' color: orange\n' + '}', - - message: messages.expected('0 spaces'), - line: 4, - column: 2, - }, - { - code: 'a {\n' + ' color: pink\n' + '}\n' + 'b {\n' + ' color: orange\n' + ' }', - fixed: 'a {\n' + ' color: pink\n' + '}\n' + 'b {\n' + ' color: orange\n' + '}', - - message: messages.expected('0 spaces'), - line: 6, - column: 2, - }, - { - code: 'a {\n' + 'color: pink;\n' + '}', - fixed: 'a {\n' + ' color: pink;\n' + '}', - - message: messages.expected('2 spaces'), - line: 2, - column: 1, - }, - { - code: 'a {\n' + '\tcolor: pink;\n' + '}', - fixed: 'a {\n' + ' color: pink;\n' + '}', - - message: messages.expected('2 spaces'), - line: 2, - column: 2, - }, - { - code: 'a {\n' + ' color: pink;\n' + ' background: orange;\n' + '}', - fixed: 'a {\n' + ' color: pink;\n' + ' background: orange;\n' + '}', - - message: messages.expected('2 spaces'), - line: 3, - column: 2, - }, - { - code: - 'a {\n' + - ' background-position: top left,\n' + - ' top right,\n' + - ' bottom left;\n' + - ' color: pink;\n' + - '}', - fixed: - 'a {\n' + - ' background-position: top left,\n' + - ' top right,\n' + - ' bottom left;\n' + - ' color: pink;\n' + - '}', - - message: messages.expected('4 spaces'), - line: 3, - column: 3, - }, - { - code: - 'a {\n' + - ' background-position: top left,\n' + - ' top right,\n' + - ' bottom left;\n' + - ' color: pink;\n' + - '}', - fixed: - 'a {\n' + - ' background-position: top left,\n' + - ' top right,\n' + - ' bottom left;\n' + - ' color: pink;\n' + - '}', - - message: messages.expected('4 spaces'), - line: 4, - column: 3, - }, - { - code: '@media print {\n' + ' * { color: pink; }\n' + '}', - fixed: '@media print {\n' + ' * { color: pink; }\n' + '}', - - message: messages.expected('2 spaces'), - line: 2, - column: 4, - }, - { - code: 'a {\n' + ' @media print { color: pink; }\n' + '}', - fixed: 'a {\n' + ' @media print { color: pink; }\n' + '}', - - message: messages.expected('2 spaces'), - line: 2, - column: 2, - }, - { - code: '\ta {\r\n' + ' color: pink;\r\n' + '}', - fixed: 'a {\r\n' + ' color: pink;\r\n' + '}', - - message: messages.expected('0 spaces'), - line: 1, - column: 2, - }, - { - code: 'a {\r\n' + ' color: pink;\r\n' + ' }', - fixed: 'a {\r\n' + ' color: pink;\r\n' + '}', - - message: messages.expected('0 spaces'), - line: 3, - column: 3, - }, - { - code: 'a,\r\n' + 'b {\r\n' + ' color: pink;\r\n' + ' }', - fixed: 'a,\r\n' + 'b {\r\n' + ' color: pink;\r\n' + '}', - - message: messages.expected('0 spaces'), - line: 4, - column: 3, - }, - { - code: 'a { color: pink;\r\n' + ' }', - fixed: 'a { color: pink;\r\n' + '}', - - message: messages.expected('0 spaces'), - line: 2, - column: 3, - }, - { - code: 'a {\r\n' + ' color: pink\r\n' + '}\r\n' + ' b {\r\n' + ' color: orange\r\n' + '}', - fixed: 'a {\r\n' + ' color: pink\r\n' + '}\r\n' + 'b {\r\n' + ' color: orange\r\n' + '}', - - message: messages.expected('0 spaces'), - line: 4, - column: 2, - }, - { - code: 'a {\r\n' + ' color: pink\r\n' + '}\r\n' + 'b {\r\n' + ' color: orange\r\n' + ' }', - fixed: 'a {\r\n' + ' color: pink\r\n' + '}\r\n' + 'b {\r\n' + ' color: orange\r\n' + '}', - - message: messages.expected('0 spaces'), - line: 6, - column: 2, - }, - { - code: 'a {\r\n' + 'color: pink;\r\n' + '}', - fixed: 'a {\r\n' + ' color: pink;\r\n' + '}', - - message: messages.expected('2 spaces'), - line: 2, - column: 1, - }, - { - code: 'a {\r\n' + '\tcolor: pink;\r\n' + '}', - fixed: 'a {\r\n' + ' color: pink;\r\n' + '}', - - message: messages.expected('2 spaces'), - line: 2, - column: 2, - }, - { - code: 'a {\r\n' + ' color: pink;\r\n' + ' background: orange;\r\n' + '}', - fixed: 'a {\r\n' + ' color: pink;\r\n' + ' background: orange;\r\n' + '}', - - message: messages.expected('2 spaces'), - line: 3, - column: 2, - }, - { - code: - 'a {\r\n' + - ' background-position: top left,\r\n' + - ' top right,\r\n' + - ' bottom left;\r\n' + - ' color: pink;\r\n' + - '}', - fixed: - 'a {\r\n' + - ' background-position: top left,\r\n' + - ' top right,\r\n' + - ' bottom left;\r\n' + - ' color: pink;\r\n' + - '}', - - message: messages.expected('4 spaces'), - line: 3, - column: 3, - }, - { - code: - 'a {\r\n' + - ' background-position: top left,\r\n' + - ' top right,\r\n' + - ' bottom left;\r\n' + - ' color: pink;\r\n' + - '}', - fixed: - 'a {\r\n' + - ' background-position: top left,\r\n' + - ' top right,\r\n' + - ' bottom left;\r\n' + - ' color: pink;\r\n' + - '}', - - message: messages.expected('4 spaces'), - line: 4, - column: 3, - }, - { - code: '@media print {\r\n' + ' * { color: pink; }\r\n' + '}', - fixed: '@media print {\r\n' + ' * { color: pink; }\r\n' + '}', - - message: messages.expected('2 spaces'), - line: 2, - column: 4, - }, - ], -}); - -testRule({ - ruleName, - config: ['tab'], - fix: true, - - accept: [ - { - code: '', - }, - { - code: 'a {color: pink;}', - }, - { - code: 'a {\n' + '\tcolor: pink;\n' + '}', - }, - { - code: 'a {\n' + '\tcolor: pink;\n' + '}\n' + '\n' + 'b {\n' + '\tcolor: orange\n' + '}', - }, - { - code: 'a {\n' + '\tcolor: pink;}', - }, - ], - - reject: [ - { - code: '\ta {\n' + '\tcolor: pink;\n' + '}', - fixed: 'a {\n' + '\tcolor: pink;\n' + '}', - - message: messages.expected('0 tabs'), - line: 1, - column: 2, - }, - { - code: 'a {\n' + '\tcolor: pink;\n' + ' }', - fixed: 'a {\n' + '\tcolor: pink;\n' + '}', - - message: messages.expected('0 tabs'), - line: 3, - column: 3, - }, - { - code: 'a {\n' + '\tcolor: pink\n' + '}\n' + ' b {\n' + '\tcolor: orange\n' + '}', - fixed: 'a {\n' + '\tcolor: pink\n' + '}\n' + 'b {\n' + '\tcolor: orange\n' + '}', - - message: messages.expected('0 tabs'), - line: 4, - column: 2, - }, - { - code: 'a {\n' + '\tcolor: pink\n' + '}\n' + 'b {\n' + '\tcolor: orange\n' + ' }', - fixed: 'a {\n' + '\tcolor: pink\n' + '}\n' + 'b {\n' + '\tcolor: orange\n' + '}', - - message: messages.expected('0 tabs'), - line: 6, - column: 2, - }, - { - code: 'a {\n' + 'color: pink;\n' + '}', - fixed: 'a {\n' + '\tcolor: pink;\n' + '}', - - message: messages.expected('1 tab'), - line: 2, - column: 1, - }, - { - code: 'a {\n' + ' color: pink;\n' + '}', - fixed: 'a {\n' + '\tcolor: pink;\n' + '}', - - message: messages.expected('1 tab'), - line: 2, - column: 3, - }, - { - code: 'a {\n' + '\tcolor: pink;\n' + ' background: orange;\n' + '}', - fixed: 'a {\n' + '\tcolor: pink;\n' + '\tbackground: orange;\n' + '}', - - message: messages.expected('1 tab'), - line: 3, - column: 2, - }, - { - code: 'a { color: pink;\n' + 'top: 0; background: orange;\n' + '}', - fixed: 'a { color: pink;\n' + '\ttop: 0; background: orange;\n' + '}', - - message: messages.expected('1 tab'), - line: 2, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: [2, { except: ['value'] }], - fix: true, - - accept: [ - { - code: - 'a {\n' + - ' background-position: top left, top right, bottom left;\n' + - ' color: pink;\n' + - '}', - }, - { - code: - 'a {\n' + - ' background-position: top left,\n' + - ' top right,\n' + - ' bottom left;\n' + - ' color: pink;\n' + - '}', - }, - ], - - reject: [ - { - code: - 'a {\n' + - ' background-position: top left,\n' + - ' top right,\n' + - ' bottom left;\n' + - ' color: pink;\n' + - '}', - fixed: - 'a {\n' + - ' background-position: top left,\n' + - ' top right,\n' + - ' bottom left;\n' + - ' color: pink;\n' + - '}', - - message: messages.expected('2 spaces'), - line: 3, - column: 5, - }, - { - code: - 'a {\n' + - ' background-position: top left,\n' + - ' top right,\n' + - ' bottom left;\n' + - ' color: pink;\n' + - '}', - fixed: - 'a {\n' + - ' background-position: top left,\n' + - ' top right,\n' + - ' bottom left;\n' + - ' color: pink;\n' + - '}', - - message: messages.expected('2 spaces'), - line: 4, - column: 5, - }, - ], -}); - -testRule({ - ruleName, - config: [2, { ignore: ['value'] }], - fix: true, - - accept: [ - { - code: - 'a {\n' + - ' background-position: top left, top right, bottom left;\n' + - ' color: pink;\n' + - '}', - }, - { - code: - 'a {\n' + - ' background-position: top left,\n' + - ' top right,\n' + - ' bottom left;\n' + - ' color: pink;\n' + - '}', - }, - { - code: - 'a {\n' + - ' background-position: top left,\n' + - ' top right,\n' + - ' bottom left;\n' + - ' color: pink;\n' + - '}', - }, - { - code: - 'a {\n' + - ' background-position: top left,\n' + - ' top right,\n' + - ' bottom left;\n' + - ' color: pink;\n' + - '}', - }, - ], - - reject: [ - { - code: '\ta {\n' + ' color: pink;\n' + '}', - fixed: 'a {\n' + ' color: pink;\n' + '}', - - message: messages.expected('0 spaces'), - line: 1, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: [ - 2, - { - indentClosingBrace: true, - }, - ], - fix: true, - - accept: [ - { - code: 'a {\n' + ' color: pink;\n' + ' }', - }, - { - code: 'a {\n' + ' color: pink;\n' + ' & b {\n' + ' top: 0;\n' + ' }\n' + ' }', - }, - ], - - reject: [ - { - code: 'a {\n' + ' color: pink;\n' + '}', - fixed: 'a {\n' + ' color: pink;\n' + ' }', - message: messages.expected('2 spaces'), - line: 3, - column: 1, - }, - { - code: 'a {\n' + ' color: pink;\n' + ' & b {\n' + ' top: 0;\n' + ' }\n' + ' }', - fixed: 'a {\n' + ' color: pink;\n' + ' & b {\n' + ' top: 0;\n' + ' }\n' + ' }', - message: messages.expected('4 spaces'), - line: 5, - column: 4, - }, - ], -}); diff --git a/lib/rules/indentation/__tests__/selectors.js b/lib/rules/indentation/__tests__/selectors.js deleted file mode 100644 index 09d6cf6a51..0000000000 --- a/lib/rules/indentation/__tests__/selectors.js +++ /dev/null @@ -1,191 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: [2], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a,\n' + 'b { color: pink; }', - }, - { - code: 'a,\n' + 'b,\n' + 'c { color: pink; }', - }, - { - code: '@media print {\n' + ' a,\n' + ' b { color: pink;}\n' + '}', - }, - { - code: 'a {\n' + ' @nest b & ,\n' + ' &.foo {\n' + ' color: pink;\n' + ' }\n' + '}', - }, - { - code: 'a {\n' + ' @at-root b & ,\n' + ' &.foo {\n' + ' color: pink;\n' + ' }\n' + '}', - }, - { - code: 'a,\r\n' + 'b { color: pink; }', - }, - { - code: 'a,\r\n' + 'b,\r\n' + 'c { color: pink; }', - }, - { - code: '@media print {\r\n' + ' a,\r\n' + ' b { color: pink;}\r\n' + '}', - }, - { - code: - 'a {\r\n' + - ' @nest b & ,\r\n' + - ' &.foo {\r\n' + - ' color: pink;\r\n' + - ' }\r\n' + - '}', - }, - { - code: - 'a {\r\n' + - ' @at-root b & ,\r\n' + - ' &.foo {\r\n' + - ' color: pink;\r\n' + - ' }\r\n' + - '}', - }, - ], - - reject: [ - { - code: 'a,\n' + ' b { color: pink; }', - fixed: 'a,\n' + 'b { color: pink; }', - - message: messages.expected('0 spaces'), - line: 2, - column: 3, - }, - { - code: 'a,\n' + 'b,\n' + ' c { color: pink; }', - fixed: 'a,\n' + 'b,\n' + 'c { color: pink; }', - - message: messages.expected('0 spaces'), - line: 3, - column: 2, - }, - { - code: '@media print {\n' + ' a,\n' + 'b { color: pink;}\n' + '}', - fixed: '@media print {\n' + ' a,\n' + ' b { color: pink;}\n' + '}', - - message: messages.expected('2 spaces'), - line: 3, - column: 1, - }, - { - code: '@media print {\n' + ' a,\n' + ' b { color: pink;}\n' + '}', - fixed: '@media print {\n' + ' a,\n' + ' b { color: pink;}\n' + '}', - - message: messages.expected('2 spaces'), - line: 3, - column: 4, - }, - { - code: '@media print {\n' + ' a,\n' + ' b { color: pink;}\n' + '}', - fixed: '@media print {\n' + ' a,\n' + ' b { color: pink;}\n' + '}', - - message: messages.expected('2 spaces'), - line: 2, - column: 4, - }, - { - code: 'a {\n' + '@nest b & ,\n' + ' &.foo {\n' + ' color: pink;\n' + ' }\n' + '}', - fixed: 'a {\n' + ' @nest b & ,\n' + ' &.foo {\n' + ' color: pink;\n' + ' }\n' + '}', - - message: messages.expected('2 spaces'), - line: 2, - column: 1, - }, - { - code: 'a {\n' + '@at-root b & ,\n' + ' &.foo {\n' + ' color: pink;\n' + ' }\n' + '}', - fixed: 'a {\n' + ' @at-root b & ,\n' + ' &.foo {\n' + ' color: pink;\n' + ' }\n' + '}', - - message: messages.expected('2 spaces'), - line: 2, - column: 1, - }, - { - code: 'a,\r\n' + ' b { color: pink; }', - fixed: 'a,\r\n' + 'b { color: pink; }', - - message: messages.expected('0 spaces'), - line: 2, - column: 3, - }, - { - code: 'a,\r\n' + 'b,\r\n' + ' c { color: pink; }', - fixed: 'a,\r\n' + 'b,\r\n' + 'c { color: pink; }', - - message: messages.expected('0 spaces'), - line: 3, - column: 2, - }, - { - code: '@media print {\r\n' + ' a,\r\n' + 'b { color: pink;}\r\n' + '}', - fixed: '@media print {\r\n' + ' a,\r\n' + ' b { color: pink;}\r\n' + '}', - - message: messages.expected('2 spaces'), - line: 3, - column: 1, - }, - { - code: '@media print {\r\n' + ' a,\r\n' + ' b { color: pink;}\r\n' + '}', - fixed: '@media print {\r\n' + ' a,\r\n' + ' b { color: pink;}\r\n' + '}', - - message: messages.expected('2 spaces'), - line: 3, - column: 4, - }, - { - code: '@media print {\r\n' + ' a,\r\n' + ' b { color: pink;}\r\n' + '}', - fixed: '@media print {\r\n' + ' a,\r\n' + ' b { color: pink;}\r\n' + '}', - - message: messages.expected('2 spaces'), - line: 2, - column: 4, - }, - { - code: - 'a {\r\n' + '@nest b & ,\r\n' + ' &.foo {\r\n' + ' color: pink;\r\n' + ' }\r\n' + '}', - fixed: - 'a {\r\n' + - ' @nest b & ,\r\n' + - ' &.foo {\r\n' + - ' color: pink;\r\n' + - ' }\r\n' + - '}', - - message: messages.expected('2 spaces'), - line: 2, - column: 1, - }, - { - code: - 'a {\r\n' + - '@at-root b & ,\r\n' + - ' &.foo {\r\n' + - ' color: pink;\r\n' + - ' }\r\n' + - '}', - fixed: - 'a {\r\n' + - ' @at-root b & ,\r\n' + - ' &.foo {\r\n' + - ' color: pink;\r\n' + - ' }\r\n' + - '}', - - message: messages.expected('2 spaces'), - line: 2, - column: 1, - }, - ], -}); diff --git a/lib/rules/indentation/index.js b/lib/rules/indentation/index.js deleted file mode 100644 index f6c01c515c..0000000000 --- a/lib/rules/indentation/index.js +++ /dev/null @@ -1,733 +0,0 @@ -'use strict'; - -const beforeBlockString = require('../../utils/beforeBlockString'); -const hasBlock = require('../../utils/hasBlock'); -const optionsMatches = require('../../utils/optionsMatches'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const styleSearch = require('style-search'); -const validateOptions = require('../../utils/validateOptions'); -const { isAtRule, isDeclaration, isRoot, isRule } = require('../../utils/typeGuards'); -const { isBoolean, isNumber, isString, assertString } = require('../../utils/validateTypes'); - -const ruleName = 'indentation'; -const messages = ruleMessages(ruleName, { - expected: (x) => `Expected indentation of ${x}`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/indentation', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, secondaryOptions = {}, context) => { - return (root, result) => { - const validOptions = validateOptions( - result, - ruleName, - { - actual: primary, - possible: [isNumber, 'tab'], - }, - { - actual: secondaryOptions, - possible: { - baseIndentLevel: [isNumber, 'auto'], - except: ['block', 'value', 'param'], - ignore: ['value', 'param', 'inside-parens'], - indentInsideParens: ['twice', 'once-at-root-twice-in-block'], - indentClosingBrace: [isBoolean], - }, - optional: true, - }, - ); - - if (!validOptions) { - return; - } - - const spaceCount = isNumber(primary) ? primary : null; - const indentChar = spaceCount == null ? '\t' : ' '.repeat(spaceCount); - const warningWord = primary === 'tab' ? 'tab' : 'space'; - - /** @type {number | 'auto'} */ - const baseIndentLevel = secondaryOptions.baseIndentLevel; - /** @type {boolean} */ - const indentClosingBrace = secondaryOptions.indentClosingBrace; - - /** - * @param {number} level - */ - const legibleExpectation = (level) => { - const count = spaceCount == null ? level : level * spaceCount; - const quantifiedWarningWord = count === 1 ? warningWord : `${warningWord}s`; - - return `${count} ${quantifiedWarningWord}`; - }; - - // Cycle through all nodes using walk. - root.walk((node) => { - if (isRoot(node)) { - // Ignore nested template literals root in css-in-js lang - return; - } - - const nodeLevel = indentationLevel(node); - - // Cut out any * and _ hacks from `before` - const before = (node.raws.before || '').replace(/[*_]$/, ''); - const after = typeof node.raws.after === 'string' ? node.raws.after : ''; - const parent = node.parent; - - if (!parent) throw new Error('A parent node must be present'); - - const expectedOpeningBraceIndentation = indentChar.repeat(nodeLevel); - - // Only inspect the spaces before the node - // if this is the first node in root - // or there is a newline in the `before` string. - // (If there is no newline before a node, - // there is no "indentation" to check.) - const isFirstChild = parent.type === 'root' && parent.first === node; - const lastIndexOfNewline = before.lastIndexOf('\n'); - - // Inspect whitespace in the `before` string that is - // *after* the *last* newline character, - // because anything besides that is not indentation for this node: - // it is some other kind of separation, checked by some separate rule - if ( - (lastIndexOfNewline !== -1 || - (isFirstChild && - (!getDocument(parent) || - (parent.raws.codeBefore && parent.raws.codeBefore.endsWith('\n'))))) && - before.slice(lastIndexOfNewline + 1) !== expectedOpeningBraceIndentation - ) { - if (context.fix) { - if (isFirstChild && isString(node.raws.before)) { - node.raws.before = node.raws.before.replace( - /^[ \t]*(?=\S|$)/, - expectedOpeningBraceIndentation, - ); - } - - node.raws.before = fixIndentation(node.raws.before, expectedOpeningBraceIndentation); - } else { - report({ - message: messages.expected(legibleExpectation(nodeLevel)), - node, - result, - ruleName, - }); - } - } - - // Only blocks have the `after` string to check. - // Only inspect `after` strings that start with a newline; - // otherwise there's no indentation involved. - // And check `indentClosingBrace` to see if it should be indented an extra level. - const closingBraceLevel = indentClosingBrace ? nodeLevel + 1 : nodeLevel; - const expectedClosingBraceIndentation = indentChar.repeat(closingBraceLevel); - - if ( - (isRule(node) || isAtRule(node)) && - hasBlock(node) && - after && - after.includes('\n') && - after.slice(after.lastIndexOf('\n') + 1) !== expectedClosingBraceIndentation - ) { - if (context.fix) { - node.raws.after = fixIndentation(node.raws.after, expectedClosingBraceIndentation); - } else { - report({ - message: messages.expected(legibleExpectation(closingBraceLevel)), - node, - index: node.toString().length - 1, - result, - ruleName, - }); - } - } - - // If this is a declaration, check the value - if (isDeclaration(node)) { - checkValue(node, nodeLevel); - } - - // If this is a rule, check the selector - if (isRule(node)) { - checkSelector(node, nodeLevel); - } - - // If this is an at rule, check the params - if (isAtRule(node)) { - checkAtRuleParams(node, nodeLevel); - } - }); - - /** - * @param {import('postcss').Node} node - * @param {number} level - * @returns {number} - */ - function indentationLevel(node, level = 0) { - if (!node.parent) throw new Error('A parent node must be present'); - - if (isRoot(node.parent)) { - return level + getRootBaseIndentLevel(node.parent, baseIndentLevel, primary); - } - - let calculatedLevel; - - // Indentation level equals the ancestor nodes - // separating this node from root; so recursively - // run this operation - calculatedLevel = indentationLevel(node.parent, level + 1); - - // If `secondaryOptions.except` includes "block", - // blocks are taken down one from their calculated level - // (all blocks are the same level as their parents) - if ( - optionsMatches(secondaryOptions, 'except', 'block') && - (isRule(node) || isAtRule(node)) && - hasBlock(node) - ) { - calculatedLevel--; - } - - return calculatedLevel; - } - - /** - * @param {import('postcss').Declaration} decl - * @param {number} declLevel - */ - function checkValue(decl, declLevel) { - if (!decl.value.includes('\n')) { - return; - } - - if (optionsMatches(secondaryOptions, 'ignore', 'value')) { - return; - } - - const declString = decl.toString(); - const valueLevel = optionsMatches(secondaryOptions, 'except', 'value') - ? declLevel - : declLevel + 1; - - checkMultilineBit(declString, valueLevel, decl); - } - - /** - * @param {import('postcss').Rule} ruleNode - * @param {number} ruleLevel - */ - function checkSelector(ruleNode, ruleLevel) { - const selector = ruleNode.selector; - - // Less mixins have params, and they should be indented extra - // @ts-expect-error -- TS2339: Property 'params' does not exist on type 'Rule'. - if (ruleNode.params) { - ruleLevel += 1; - } - - checkMultilineBit(selector, ruleLevel, ruleNode); - } - - /** - * @param {import('postcss').AtRule} atRule - * @param {number} ruleLevel - */ - function checkAtRuleParams(atRule, ruleLevel) { - if (optionsMatches(secondaryOptions, 'ignore', 'param')) { - return; - } - - // @nest and SCSS's @at-root rules should be treated like regular rules, not expected - // to have their params (selectors) indented - const paramLevel = - optionsMatches(secondaryOptions, 'except', 'param') || - atRule.name === 'nest' || - atRule.name === 'at-root' - ? ruleLevel - : ruleLevel + 1; - - checkMultilineBit(beforeBlockString(atRule).trim(), paramLevel, atRule); - } - - /** - * @param {string} source - * @param {number} newlineIndentLevel - * @param {import('postcss').Node} node - */ - function checkMultilineBit(source, newlineIndentLevel, node) { - if (!source.includes('\n')) { - return; - } - - // Data for current node fixing - /** @type {Array<{ expectedIndentation: string, currentIndentation: string, startIndex: number }>} */ - const fixPositions = []; - - // `outsideParens` because function arguments and also non-standard parenthesized stuff like - // Sass maps are ignored to allow for arbitrary indentation - let parentheticalDepth = 0; - - const ignoreInsideParans = optionsMatches(secondaryOptions, 'ignore', 'inside-parens'); - - styleSearch( - { - source, - target: '\n', - // @ts-expect-error -- The `outsideParens` option is unsupported. Why? - outsideParens: ignoreInsideParans, - }, - (match, matchCount) => { - const precedesClosingParenthesis = /^[ \t]*\)/.test(source.slice(match.startIndex + 1)); - - if (ignoreInsideParans && (precedesClosingParenthesis || match.insideParens)) { - return; - } - - let expectedIndentLevel = newlineIndentLevel; - - // Modififications for parenthetical content - if (!ignoreInsideParans && match.insideParens) { - // If the first match in is within parentheses, reduce the parenthesis penalty - if (matchCount === 1) parentheticalDepth -= 1; - - // Account for windows line endings - let newlineIndex = match.startIndex; - - if (source[match.startIndex - 1] === '\r') { - newlineIndex--; - } - - const followsOpeningParenthesis = /\([ \t]*$/.test(source.slice(0, newlineIndex)); - - if (followsOpeningParenthesis) { - parentheticalDepth += 1; - } - - const followsOpeningBrace = /\{[ \t]*$/.test(source.slice(0, newlineIndex)); - - if (followsOpeningBrace) { - parentheticalDepth += 1; - } - - const startingClosingBrace = /^[ \t]*\}/.test(source.slice(match.startIndex + 1)); - - if (startingClosingBrace) { - parentheticalDepth -= 1; - } - - expectedIndentLevel += parentheticalDepth; - - // Past this point, adjustments to parentheticalDepth affect next line - - if (precedesClosingParenthesis) { - parentheticalDepth -= 1; - } - - switch (secondaryOptions.indentInsideParens) { - case 'twice': - if (!precedesClosingParenthesis || indentClosingBrace) { - expectedIndentLevel += 1; - } - - break; - case 'once-at-root-twice-in-block': - if (node.parent === node.root()) { - if (precedesClosingParenthesis && !indentClosingBrace) { - expectedIndentLevel -= 1; - } - - break; - } - - if (!precedesClosingParenthesis || indentClosingBrace) { - expectedIndentLevel += 1; - } - - break; - default: - if (precedesClosingParenthesis && !indentClosingBrace) { - expectedIndentLevel -= 1; - } - } - } - - // Starting at the index after the newline, we want to - // check that the whitespace characters (excluding newlines) before the first - // non-whitespace character equal the expected indentation - const afterNewlineSpaceMatches = /^([ \t]*)\S/.exec(source.slice(match.startIndex + 1)); - - if (!afterNewlineSpaceMatches) { - return; - } - - const afterNewlineSpace = afterNewlineSpaceMatches[1] || ''; - const expectedIndentation = indentChar.repeat( - expectedIndentLevel > 0 ? expectedIndentLevel : 0, - ); - - if (afterNewlineSpace !== expectedIndentation) { - if (context.fix) { - // Adding fixes position in reverse order, because if we change indent in the beginning of the string it will break all following fixes for that string - fixPositions.unshift({ - expectedIndentation, - currentIndentation: afterNewlineSpace, - startIndex: match.startIndex, - }); - } else { - report({ - message: messages.expected(legibleExpectation(expectedIndentLevel)), - node, - index: match.startIndex + afterNewlineSpace.length + 1, - result, - ruleName, - }); - } - } - }, - ); - - if (fixPositions.length) { - if (isRule(node)) { - for (const fixPosition of fixPositions) { - node.selector = replaceIndentation( - node.selector, - fixPosition.currentIndentation, - fixPosition.expectedIndentation, - fixPosition.startIndex, - ); - } - } - - if (isDeclaration(node)) { - const declProp = node.prop; - const declBetween = node.raws.between; - - if (!isString(declBetween)) { - throw new TypeError('The `between` property must be a string'); - } - - for (const fixPosition of fixPositions) { - if (fixPosition.startIndex < declProp.length + declBetween.length) { - node.raws.between = replaceIndentation( - declBetween, - fixPosition.currentIndentation, - fixPosition.expectedIndentation, - fixPosition.startIndex - declProp.length, - ); - } else { - node.value = replaceIndentation( - node.value, - fixPosition.currentIndentation, - fixPosition.expectedIndentation, - fixPosition.startIndex - declProp.length - declBetween.length, - ); - } - } - } - - if (isAtRule(node)) { - const atRuleName = node.name; - const atRuleAfterName = node.raws.afterName; - const atRuleParams = node.params; - - if (!isString(atRuleAfterName)) { - throw new TypeError('The `afterName` property must be a string'); - } - - for (const fixPosition of fixPositions) { - // 1 — it's a @ length - if (fixPosition.startIndex < 1 + atRuleName.length + atRuleAfterName.length) { - node.raws.afterName = replaceIndentation( - atRuleAfterName, - fixPosition.currentIndentation, - fixPosition.expectedIndentation, - fixPosition.startIndex - atRuleName.length - 1, - ); - } else { - node.params = replaceIndentation( - atRuleParams, - fixPosition.currentIndentation, - fixPosition.expectedIndentation, - fixPosition.startIndex - atRuleName.length - atRuleAfterName.length - 1, - ); - } - } - } - } - } - }; -}; - -/** - * @param {import('postcss').Root} root - * @param {number | 'auto'} baseIndentLevel - * @param {string} space - * @returns {number} - */ -function getRootBaseIndentLevel(root, baseIndentLevel, space) { - const document = getDocument(root); - - if (!document) { - return 0; - } - - if (!root.source) { - throw new Error('The root node must have a source'); - } - - /** @type {import('postcss').Source & { baseIndentLevel?: number }} */ - const source = root.source; - - const indentLevel = source.baseIndentLevel; - - if (isNumber(indentLevel) && Number.isSafeInteger(indentLevel)) { - return indentLevel; - } - - const newIndentLevel = inferRootIndentLevel(root, baseIndentLevel, () => - inferDocIndentSize(document, space), - ); - - source.baseIndentLevel = newIndentLevel; - - return newIndentLevel; -} - -/** - * @param {import('postcss').Node} node - */ -function getDocument(node) { - // @ts-expect-error -- TS2339: Property 'document' does not exist on type 'Node'. - const document = node.document; - - if (document) { - return document; - } - - const root = node.root(); - - // @ts-expect-error -- TS2339: Property 'document' does not exist on type 'Node'. - return root && root.document; -} - -/** - * @param {import('postcss').Document} document - * @param {string} space - * returns {number} - */ -function inferDocIndentSize(document, space) { - if (!document.source) throw new Error('The document node must have a source'); - - /** @type {import('postcss').Source & { indentSize?: number }} */ - const docSource = document.source; - - let indentSize = docSource.indentSize; - - if (isNumber(indentSize) && Number.isSafeInteger(indentSize)) { - return indentSize; - } - - const source = document.source.input.css; - const indents = source.match(/^ *(?=\S)/gm); - - if (indents) { - /** @type {Map} */ - const scores = new Map(); - let lastIndentSize = 0; - let lastLeadingSpacesLength = 0; - - /** - * @param {number} leadingSpacesLength - */ - const vote = (leadingSpacesLength) => { - if (leadingSpacesLength) { - lastIndentSize = Math.abs(leadingSpacesLength - lastLeadingSpacesLength) || lastIndentSize; - - if (lastIndentSize > 1) { - const score = scores.get(lastIndentSize); - - if (score) { - scores.set(lastIndentSize, score + 1); - } else { - scores.set(lastIndentSize, 1); - } - } - } else { - lastIndentSize = 0; - } - - lastLeadingSpacesLength = leadingSpacesLength; - }; - - for (const leadingSpaces of indents) { - vote(leadingSpaces.length); - } - - let bestScore = 0; - - for (const [indentSizeDate, score] of scores.entries()) { - if (score > bestScore) { - bestScore = score; - indentSize = indentSizeDate; - } - } - } - - indentSize = - Number(indentSize) || (indents && indents[0] && indents[0].length) || Number(space) || 2; - docSource.indentSize = indentSize; - - return indentSize; -} - -/** - * @param {import('postcss').Root} root - * @param {number | 'auto'} baseIndentLevel - * @param {() => number} indentSize - * @returns {number} - */ -function inferRootIndentLevel(root, baseIndentLevel, indentSize) { - /** - * @param {string} indent - */ - function getIndentLevel(indent) { - const tabMatch = indent.match(/\t/g); - const tabCount = tabMatch ? tabMatch.length : 0; - - const spaceMatch = indent.match(/ /g); - const spaceCount = spaceMatch ? Math.round(spaceMatch.length / indentSize()) : 0; - - return tabCount + spaceCount; - } - - let newBaseIndentLevel = 0; - - if (!isNumber(baseIndentLevel) || !Number.isSafeInteger(baseIndentLevel)) { - if (!root.source) throw new Error('The root node must have a source'); - - let source = root.source.input.css; - - source = source.replace(/^[^\r\n]+/, (firstLine) => { - const match = root.raws.codeBefore && /(?:^|\n)([ \t]*)$/.exec(root.raws.codeBefore); - - if (match) { - return match[1] + firstLine; - } - - return ''; - }); - - const indents = source.match(/^[ \t]*(?=\S)/gm); - - if (indents) { - return Math.min(...indents.map((indent) => getIndentLevel(indent))); - } - - newBaseIndentLevel = 1; - } else { - newBaseIndentLevel = baseIndentLevel; - } - - const indents = []; - const foundIndents = root.raws.codeBefore && /(?:^|\n)([ \t]*)\S/m.exec(root.raws.codeBefore); - - // The indent level of the CSS code block in non-CSS-like files is determined by the shortest indent of non-empty line. - if (foundIndents) { - let shortest = Number.MAX_SAFE_INTEGER; - let i = 0; - - while (++i < foundIndents.length) { - const foundIndent = foundIndents[i]; - - assertString(foundIndent); - const current = getIndentLevel(foundIndent); - - if (current < shortest) { - shortest = current; - - if (shortest === 0) { - break; - } - } - } - - if (shortest !== Number.MAX_SAFE_INTEGER) { - indents.push(new Array(shortest).fill(' ').join('')); - } - } - - const after = root.raws.after; - - if (after) { - let afterEnd; - - if (after.endsWith('\n')) { - // @ts-expect-error -- TS2339: Property 'document' does not exist on type 'Root'. - const document = root.document; - - if (document) { - const nextRoot = document.nodes[document.nodes.indexOf(root) + 1]; - - afterEnd = nextRoot ? nextRoot.raws.codeBefore : document.raws.codeAfter; - } else { - // Nested root node in css-in-js lang - const parent = root.parent; - - if (!parent) throw new Error('The root node must have a parent'); - - const nextRoot = parent.nodes[parent.nodes.indexOf(root) + 1]; - - afterEnd = nextRoot ? nextRoot.raws.codeBefore : root.raws.codeAfter; - } - } else { - afterEnd = after; - } - - if (afterEnd) indents.push(afterEnd.match(/^[ \t]*/)[0]); - } - - if (indents.length) { - return Math.max(...indents.map((indent) => getIndentLevel(indent))) + newBaseIndentLevel; - } - - return newBaseIndentLevel; -} - -/** - * @param {string | undefined} str - * @param {string} whitespace - */ -function fixIndentation(str, whitespace) { - if (!isString(str)) { - return str; - } - - return str.replace(/\n[ \t]*(?=\S|$)/g, `\n${whitespace}`); -} - -/** - * @param {string} input - * @param {string} searchString - * @param {string} replaceString - * @param {number} startIndex - */ -function replaceIndentation(input, searchString, replaceString, startIndex) { - const offset = startIndex + 1; - const stringStart = input.slice(0, offset); - const stringEnd = input.slice(offset + searchString.length); - - return stringStart + replaceString + stringEnd; -} - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/index.js b/lib/rules/index.js index 6693e5f47b..1ba84f681e 100644 --- a/lib/rules/index.js +++ b/lib/rules/index.js @@ -9,47 +9,12 @@ const rules = { 'at-rule-allowed-list': importLazy(() => require('./at-rule-allowed-list'))(), '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'))(), - 'at-rule-name-newline-after': importLazy(() => require('./at-rule-name-newline-after'))(), - 'at-rule-semicolon-space-before': importLazy(() => require('./at-rule-semicolon-space-before'))(), - 'at-rule-name-space-after': importLazy(() => require('./at-rule-name-space-after'))(), '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-semicolon-newline-after': importLazy(() => - require('./at-rule-semicolon-newline-after'), - )(), - 'block-closing-brace-empty-line-before': importLazy(() => - require('./block-closing-brace-empty-line-before'), - )(), - 'block-closing-brace-newline-after': importLazy(() => - require('./block-closing-brace-newline-after'), - )(), - 'block-closing-brace-newline-before': importLazy(() => - require('./block-closing-brace-newline-before'), - )(), - 'block-closing-brace-space-after': importLazy(() => - require('./block-closing-brace-space-after'), - )(), - 'block-closing-brace-space-before': importLazy(() => - require('./block-closing-brace-space-before'), - )(), 'block-no-empty': importLazy(() => require('./block-no-empty'))(), - 'block-opening-brace-newline-after': importLazy(() => - require('./block-opening-brace-newline-after'), - )(), - 'block-opening-brace-newline-before': importLazy(() => - require('./block-opening-brace-newline-before'), - )(), - 'block-opening-brace-space-after': importLazy(() => - require('./block-opening-brace-space-after'), - )(), - 'block-opening-brace-space-before': importLazy(() => - require('./block-opening-brace-space-before'), - )(), 'color-function-notation': importLazy(() => require('./color-function-notation'))(), 'color-hex-alpha': importLazy(() => require('./color-hex-alpha'))(), - 'color-hex-case': importLazy(() => require('./color-hex-case'))(), 'color-hex-length': importLazy(() => require('./color-hex-length'))(), 'color-named': importLazy(() => require('./color-named'))(), 'color-no-hex': importLazy(() => require('./color-no-hex'))(), @@ -67,8 +32,6 @@ const rules = { require('./custom-property-no-missing-var-function'), )(), 'custom-property-pattern': importLazy(() => require('./custom-property-pattern'))(), - 'declaration-bang-space-after': importLazy(() => require('./declaration-bang-space-after'))(), - 'declaration-bang-space-before': importLazy(() => require('./declaration-bang-space-before'))(), 'declaration-block-no-duplicate-custom-properties': importLazy(() => require('./declaration-block-no-duplicate-custom-properties'), )(), @@ -81,29 +44,9 @@ const rules = { 'declaration-block-no-shorthand-property-overrides': importLazy(() => require('./declaration-block-no-shorthand-property-overrides'), )(), - 'declaration-block-semicolon-newline-after': importLazy(() => - require('./declaration-block-semicolon-newline-after'), - )(), - 'declaration-block-semicolon-newline-before': importLazy(() => - require('./declaration-block-semicolon-newline-before'), - )(), - 'declaration-block-semicolon-space-after': importLazy(() => - require('./declaration-block-semicolon-space-after'), - )(), - 'declaration-block-semicolon-space-before': importLazy(() => - require('./declaration-block-semicolon-space-before'), - )(), 'declaration-block-single-line-max-declarations': importLazy(() => require('./declaration-block-single-line-max-declarations'), )(), - 'declaration-block-trailing-semicolon': importLazy(() => - require('./declaration-block-trailing-semicolon'), - )(), - 'declaration-colon-newline-after': importLazy(() => - require('./declaration-colon-newline-after'), - )(), - 'declaration-colon-space-after': importLazy(() => require('./declaration-colon-space-after'))(), - 'declaration-colon-space-before': importLazy(() => require('./declaration-colon-space-before'))(), 'declaration-empty-line-before': importLazy(() => require('./declaration-empty-line-before'))(), 'declaration-no-important': importLazy(() => require('./declaration-no-important'))(), 'declaration-property-max-values': importLazy(() => @@ -134,23 +77,15 @@ const rules = { 'function-calc-no-unspaced-operator': importLazy(() => require('./function-calc-no-unspaced-operator'), )(), - 'function-comma-newline-after': importLazy(() => require('./function-comma-newline-after'))(), - 'function-comma-newline-before': importLazy(() => require('./function-comma-newline-before'))(), - 'function-comma-space-after': importLazy(() => require('./function-comma-space-after'))(), - 'function-comma-space-before': importLazy(() => require('./function-comma-space-before'))(), + 'function-disallowed-list': importLazy(() => require('./function-disallowed-list'))(), 'function-linear-gradient-no-nonstandard-direction': importLazy(() => require('./function-linear-gradient-no-nonstandard-direction'), )(), - 'function-max-empty-lines': importLazy(() => require('./function-max-empty-lines'))(), + 'function-name-case': importLazy(() => require('./function-name-case'))(), 'function-no-unknown': importLazy(() => require('./function-no-unknown'))(), - 'function-parentheses-newline-inside': importLazy(() => - require('./function-parentheses-newline-inside'), - )(), - 'function-parentheses-space-inside': importLazy(() => - require('./function-parentheses-space-inside'), - )(), + 'function-url-no-scheme-relative': importLazy(() => require('./function-url-no-scheme-relative'), )(), @@ -161,7 +96,7 @@ const rules = { 'function-url-scheme-disallowed-list': importLazy(() => require('./function-url-scheme-disallowed-list'), )(), - 'function-whitespace-after': importLazy(() => require('./function-whitespace-after'))(), + 'hue-degree-notation': importLazy(() => require('./hue-degree-notation'))(), 'import-notation': importLazy(() => require('./import-notation'))(), 'keyframe-block-no-duplicate-selectors': importLazy(() => @@ -173,20 +108,10 @@ const rules = { 'keyframe-selector-notation': importLazy(() => require('./keyframe-selector-notation'))(), 'keyframes-name-pattern': importLazy(() => require('./keyframes-name-pattern'))(), 'length-zero-no-unit': importLazy(() => require('./length-zero-no-unit'))(), - linebreaks: importLazy(() => require('./linebreaks'))(), - 'max-empty-lines': importLazy(() => require('./max-empty-lines'))(), - 'max-line-length': importLazy(() => require('./max-line-length'))(), 'max-nesting-depth': importLazy(() => require('./max-nesting-depth'))(), - 'media-feature-colon-space-after': importLazy(() => - require('./media-feature-colon-space-after'), - )(), - 'media-feature-colon-space-before': importLazy(() => - require('./media-feature-colon-space-before'), - )(), 'media-feature-name-allowed-list': importLazy(() => require('./media-feature-name-allowed-list'), )(), - 'media-feature-name-case': importLazy(() => require('./media-feature-name-case'))(), 'media-feature-name-disallowed-list': importLazy(() => require('./media-feature-name-disallowed-list'), )(), @@ -203,37 +128,14 @@ const rules = { 'media-feature-name-value-no-unknown': importLazy(() => require('./media-feature-name-value-no-unknown'), )(), - 'media-feature-parentheses-space-inside': importLazy(() => - require('./media-feature-parentheses-space-inside'), - )(), 'media-feature-range-notation': importLazy(() => require('./media-feature-range-notation'))(), - 'media-feature-range-operator-space-after': importLazy(() => - require('./media-feature-range-operator-space-after'), - )(), - 'media-feature-range-operator-space-before': importLazy(() => - require('./media-feature-range-operator-space-before'), - )(), - 'media-query-list-comma-newline-after': importLazy(() => - require('./media-query-list-comma-newline-after'), - )(), - 'media-query-list-comma-newline-before': importLazy(() => - require('./media-query-list-comma-newline-before'), - )(), - 'media-query-list-comma-space-after': importLazy(() => - require('./media-query-list-comma-space-after'), - )(), - 'media-query-list-comma-space-before': importLazy(() => - require('./media-query-list-comma-space-before'), - )(), + 'media-query-no-invalid': importLazy(() => require('./media-query-no-invalid'))(), 'named-grid-areas-no-invalid': importLazy(() => require('./named-grid-areas-no-invalid'))(), 'no-descending-specificity': importLazy(() => require('./no-descending-specificity'))(), 'no-duplicate-at-import-rules': importLazy(() => require('./no-duplicate-at-import-rules'))(), 'no-duplicate-selectors': importLazy(() => require('./no-duplicate-selectors'))(), 'no-empty-source': importLazy(() => require('./no-empty-source'))(), - 'no-empty-first-line': importLazy(() => require('./no-empty-first-line'))(), - 'no-eol-whitespace': importLazy(() => require('./no-eol-whitespace'))(), - 'no-extra-semicolons': importLazy(() => require('./no-extra-semicolons'))(), 'no-invalid-double-slash-comments': importLazy(() => require('./no-invalid-double-slash-comments'), )(), @@ -241,16 +143,10 @@ const rules = { require('./no-invalid-position-at-import-rule'), )(), 'no-irregular-whitespace': importLazy(() => require('./no-irregular-whitespace'))(), - 'no-missing-end-of-source-newline': importLazy(() => - require('./no-missing-end-of-source-newline'), - )(), 'no-unknown-animations': importLazy(() => require('./no-unknown-animations'))(), 'no-unknown-custom-properties': importLazy(() => require('./no-unknown-custom-properties'))(), - 'number-leading-zero': importLazy(() => require('./number-leading-zero'))(), '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-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'))(), @@ -259,9 +155,6 @@ const rules = { require('./rule-selector-property-disallowed-list'), )(), 'selector-anb-no-unmatchable': importLazy(() => require('./selector-anb-no-unmatchable'))(), - 'selector-attribute-brackets-space-inside': importLazy(() => - require('./selector-attribute-brackets-space-inside'), - )(), 'selector-attribute-name-disallowed-list': importLazy(() => require('./selector-attribute-name-disallowed-list'), )(), @@ -271,12 +164,6 @@ const rules = { 'selector-attribute-operator-disallowed-list': importLazy(() => require('./selector-attribute-operator-disallowed-list'), )(), - 'selector-attribute-operator-space-after': importLazy(() => - require('./selector-attribute-operator-space-after'), - )(), - 'selector-attribute-operator-space-before': importLazy(() => - require('./selector-attribute-operator-space-before'), - )(), 'selector-attribute-quotes': importLazy(() => require('./selector-attribute-quotes'))(), 'selector-class-pattern': importLazy(() => require('./selector-class-pattern'))(), 'selector-combinator-allowed-list': importLazy(() => @@ -285,36 +172,17 @@ const rules = { 'selector-combinator-disallowed-list': importLazy(() => require('./selector-combinator-disallowed-list'), )(), - 'selector-combinator-space-after': importLazy(() => - require('./selector-combinator-space-after'), - )(), - 'selector-combinator-space-before': importLazy(() => - require('./selector-combinator-space-before'), - )(), - 'selector-descendant-combinator-no-non-space': importLazy(() => - require('./selector-descendant-combinator-no-non-space'), - )(), + 'selector-disallowed-list': importLazy(() => require('./selector-disallowed-list'))(), 'selector-id-pattern': importLazy(() => require('./selector-id-pattern'))(), - 'selector-list-comma-newline-after': importLazy(() => - require('./selector-list-comma-newline-after'), - )(), - 'selector-list-comma-newline-before': importLazy(() => - require('./selector-list-comma-newline-before'), - )(), - 'selector-list-comma-space-after': importLazy(() => - require('./selector-list-comma-space-after'), - )(), - 'selector-list-comma-space-before': importLazy(() => - require('./selector-list-comma-space-before'), - )(), + 'selector-max-attribute': importLazy(() => require('./selector-max-attribute'))(), 'selector-max-class': importLazy(() => require('./selector-max-class'))(), 'selector-max-combinators': importLazy(() => require('./selector-max-combinators'))(), 'selector-max-compound-selectors': importLazy(() => require('./selector-max-compound-selectors'), )(), - 'selector-max-empty-lines': importLazy(() => require('./selector-max-empty-lines'))(), + 'selector-max-id': importLazy(() => require('./selector-max-id'))(), 'selector-max-pseudo-class': importLazy(() => require('./selector-max-pseudo-class'))(), 'selector-max-specificity': importLazy(() => require('./selector-max-specificity'))(), @@ -327,20 +195,15 @@ const rules = { 'selector-pseudo-class-allowed-list': importLazy(() => require('./selector-pseudo-class-allowed-list'), )(), - 'selector-pseudo-class-case': importLazy(() => require('./selector-pseudo-class-case'))(), 'selector-pseudo-class-disallowed-list': importLazy(() => require('./selector-pseudo-class-disallowed-list'), )(), 'selector-pseudo-class-no-unknown': importLazy(() => require('./selector-pseudo-class-no-unknown'), )(), - 'selector-pseudo-class-parentheses-space-inside': importLazy(() => - require('./selector-pseudo-class-parentheses-space-inside'), - )(), 'selector-pseudo-element-allowed-list': importLazy(() => require('./selector-pseudo-element-allowed-list'), )(), - 'selector-pseudo-element-case': importLazy(() => require('./selector-pseudo-element-case'))(), 'selector-pseudo-element-colon-notation': importLazy(() => require('./selector-pseudo-element-colon-notation'), )(), @@ -356,23 +219,12 @@ const rules = { require('./shorthand-property-no-redundant-values'), )(), 'string-no-newline': importLazy(() => require('./string-no-newline'))(), - 'string-quotes': importLazy(() => require('./string-quotes'))(), 'time-min-milliseconds': importLazy(() => require('./time-min-milliseconds'))(), - 'unicode-bom': importLazy(() => require('./unicode-bom'))(), 'unit-allowed-list': importLazy(() => require('./unit-allowed-list'))(), - 'unit-case': importLazy(() => require('./unit-case'))(), 'unit-disallowed-list': importLazy(() => require('./unit-disallowed-list'))(), 'unit-no-unknown': importLazy(() => require('./unit-no-unknown'))(), '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(() => - require('./value-list-comma-newline-before'), - )(), - 'value-list-comma-space-after': importLazy(() => require('./value-list-comma-space-after'))(), - 'value-list-comma-space-before': importLazy(() => require('./value-list-comma-space-before'))(), - 'value-list-max-empty-lines': importLazy(() => require('./value-list-max-empty-lines'))(), 'value-no-vendor-prefix': importLazy(() => require('./value-no-vendor-prefix'))(), - indentation: importLazy(() => require('./indentation'))(), }; module.exports = rules; diff --git a/lib/rules/linebreaks/README.md b/lib/rules/linebreaks/README.md deleted file mode 100644 index d195339453..0000000000 --- a/lib/rules/linebreaks/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# linebreaks - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Specify unix or windows linebreaks. - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"unix"|"windows"` - -### `"unix"` - -Linebreaks _must always_ be LF (`\n`). - -Lines with CRLF linebreaks are considered problems. - -### `"windows"` - -Linebreaks _must always_ be CRLF (`\r\n`). - -Lines with LF linebreaks are considered problems. diff --git a/lib/rules/linebreaks/__tests__/index.js b/lib/rules/linebreaks/__tests__/index.js deleted file mode 100644 index e286184526..0000000000 --- a/lib/rules/linebreaks/__tests__/index.js +++ /dev/null @@ -1,493 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['unix'], - fix: true, - - accept: [ - { - code: 'a {}\nb {}', - description: 'single unix newline between rules', - }, - { - code: 'a {}\n\nb{}', - description: 'two unix newlines between rules', - }, - { - code: '/** horse */\n\nb{}', - description: 'two unix newlines after a comment', - }, - { - code: 'a{}\n\n/** horse */\n\nb{}', - description: 'multiple unix newlines with a comment between rules', - }, - { - code: '\n\na {}\n\nb{}\n\n\n\n\n\n', - description: 'multiple unix newlines', - }, - { - code: 'a { border: 1px\n solid \nred; }', - description: 'newlines between property values', - }, - { - code: '.foo\n .bar { }', - description: 'newline between selectors', - }, - { - code: 'a {\n}', - description: 'newline after open curly brackets', - }, - { - code: 'a {}\n b {}', - description: 'newline after close curly brackets', - }, - ], - - reject: [ - { - code: 'a {}\r\nb {}', - fixed: 'a {}\nb {}', - message: messages.expected('unix'), - description: 'CRLF in the first line after a rule', - line: 1, - column: 5, - }, - { - code: 'a {}\n\r\nb{}', - fixed: 'a {}\n\nb{}', - message: messages.expected('unix'), - description: 'Blank line with CRLF', - line: 2, - column: 1, - }, - { - code: '/** horse */\r\n\nb{}', - fixed: '/** horse */\n\nb{}', - message: messages.expected('unix'), - description: 'CRLF after a comment in the first line', - line: 1, - column: 13, - }, - { - code: 'a{}\n\n/** horse */\r\n\nb{}', - fixed: 'a{}\n\n/** horse */\n\nb{}', - message: messages.expected('unix'), - description: 'CRLF after a comment in the third line', - line: 3, - column: 13, - }, - { - code: '\n\na {}\r\n\nb{}', - fixed: '\n\na {}\n\nb{}', - message: messages.expected('unix'), - description: 'CRLF after a rule in the third line', - line: 3, - column: 5, - }, - - { - code: '/* This is a\r\ncomment*/\na {}', - fixed: '/* This is a\ncomment*/\na {}', - message: messages.expected('unix'), - description: 'CRLF inside a comment string in the second line', - line: 1, - column: 13, - }, - { - code: '/* This is a\r\ncomment*/\na {}', - fixed: '/* This is a\ncomment*/\na {}', - message: messages.expected('unix'), - description: - 'CRLF inside a comment string with several spaces in the beginning in the first line', - line: 1, - column: 16, - }, - { - code: '/*This is a\r\ncomment*/\na {}', - fixed: '/*This is a\ncomment*/\na {}', - message: messages.expected('unix'), - description: 'CRLF inside a comment string without spaces in the beginning in the first line', - line: 1, - column: 12, - }, - { - code: '\n\n/* This is\na\r\ncomment*/\na {}', - fixed: '\n\n/* This is\na\ncomment*/\na {}', - message: messages.expected('unix'), - description: 'CRLF inside a comment string in the fourth line', - line: 4, - column: 2, - }, - { - code: '/* This is\na comment*/\r\na {}', - fixed: '/* This is\na comment*/\na {}', - message: messages.expected('unix'), - description: 'CRLF after a comment in the second line', - line: 2, - column: 12, - }, - { - code: '\r\n\n\n\n\n/* This is\na comment*/', - fixed: '\n\n\n\n\n/* This is\na comment*/', - message: messages.expected('unix'), - description: 'CRLF before a comment at the beginning of the file', - line: 1, - column: 1, - }, - { - code: '\n\r\n\n\n\n/* This is\na comment*/', - fixed: '\n\n\n\n\n/* This is\na comment*/', - message: messages.expected('unix'), - description: 'CRLF before a comment in one of the first empty lines of the file', - line: 2, - column: 1, - }, - { - code: '\r\n\n\n\n\n\n\n\n\n\n\na {}', - fixed: '\n\n\n\n\n\n\n\n\n\n\na {}', - message: messages.expected('unix'), - description: 'CRLF before a rule at the beginning of the file', - line: 1, - column: 1, - }, - { - code: '\n\n\n\n\n\n\n\r\n\n\n\na {}', - fixed: '\n\n\n\n\n\n\n\n\n\n\na {}', - message: messages.expected('unix'), - description: 'CRLF before a rule in one of the first empty lines of the file', - line: 8, - column: 1, - }, - { - code: 'a {}\n\n\r\n\n\n', - fixed: 'a {}\n\n\n\n\n', - message: messages.expected('unix'), - description: 'CRLF in one of the last empty lines of the file', - line: 3, - column: 1, - }, - { - code: 'a {}\n\n\r\n', - fixed: 'a {}\n\n\n', - message: messages.expected('unix'), - description: 'CRLF in the last line of the file', - line: 3, - column: 1, - }, - { - code: '.foo\r\n .bar {}', - fixed: '.foo\n .bar {}', - message: messages.expected('unix'), - description: 'CRLF between selectors in the first line', - line: 1, - column: 5, - }, - { - code: '\n\n\n.foo\r\n .bar {}', - fixed: '\n\n\n.foo\n .bar {}', - message: messages.expected('unix'), - description: 'CRLF between selectors in the fourth line', - line: 4, - column: 5, - }, - { - code: '\n\n\n.foo\n .bar\r\n .baz {}', - fixed: '\n\n\n.foo\n .bar\n .baz {}', - message: messages.expected('unix'), - description: 'CRLF between selectors, additional test', - line: 5, - column: 6, - }, - { - code: 'a { border: 1px\r\n solid red; }', - fixed: 'a { border: 1px\n solid red; }', - message: messages.expected('unix'), - description: 'CRLF between property values in the first line', - line: 1, - column: 16, - }, - { - code: '\n\n\na { border: 1px\r\n solid red; }', - fixed: '\n\n\na { border: 1px\n solid red; }', - message: messages.expected('unix'), - description: 'CRLF between property values in the fourth line', - line: 4, - column: 16, - }, - { - code: '\n\n\na { border: 1px\n solid \r\nred; }', - fixed: '\n\n\na { border: 1px\n solid \nred; }', - message: messages.expected('unix'), - description: 'CRLF between property values, additional test', - line: 5, - column: 8, - }, - { - code: '\n\na {\r\n}', - fixed: '\n\na {\n}', - message: messages.expected('unix'), - description: 'CRLF after open curly brackets', - line: 3, - column: 4, - }, - { - code: '\n\na {\n}\r\nb {\n}', - fixed: '\n\na {\n}\nb {\n}', - message: messages.expected('unix'), - description: 'CRLF after close curly brackets', - line: 4, - column: 2, - }, - { - code: '\r\na {color:red;}', - fixed: '\na {color:red;}', - message: messages.expected('unix'), - line: 1, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: ['windows'], - fix: true, - - accept: [ - { - code: 'a {}\r\nb {}', - description: 'single windows newline between rules', - }, - { - code: 'a {}\r\n\r\nb{}', - description: 'two windows newlines between rules', - }, - { - code: '/** horse */\r\n\r\nb{}', - description: 'two windows newlines after a comment', - }, - { - code: 'a{}\r\n\r\n/** horse */\r\n\r\nb{}', - description: 'multiple windows newlines with a comment between rules', - }, - { - code: '\r\n\r\na {}\r\n\r\nb{}\r\n\r\n\r\n\r\n\r\n\r\n', - description: 'multiple windows newlines', - }, - { - code: 'a { border: 1px\r\n solid \r\nred; }', - description: 'newlines between property values', - }, - { - code: '.foo\r\n .bar { }', - description: 'newline between selectors', - }, - { - code: 'a {\r\n}', - description: 'newline after open curly brackets', - }, - { - code: 'a {}\r\n b {}', - description: 'newline after close curly brackets', - }, - ], - reject: [ - { - code: 'a {}\nb {}', - fixed: 'a {}\r\nb {}', - message: messages.expected('windows'), - description: 'LF in the first line after a rule', - line: 1, - column: 5, - }, - { - code: 'a {}\r\n\nb{}', - fixed: 'a {}\r\n\r\nb{}', - message: messages.expected('windows'), - description: 'Blank line with LF', - line: 2, - column: 1, - }, - { - code: '/** horse */\n\r\nb{}', - fixed: '/** horse */\r\n\r\nb{}', - message: messages.expected('windows'), - description: 'LF after a comment in the first line', - line: 1, - column: 13, - }, - { - code: 'a{}\r\n\r\n/** horse */\n\r\nb{}', - fixed: 'a{}\r\n\r\n/** horse */\r\n\r\nb{}', - message: messages.expected('windows'), - description: 'LF after a comment in the third line', - line: 3, - column: 13, - }, - { - code: '\r\n\r\na {}\n\r\nb{}', - fixed: '\r\n\r\na {}\r\n\r\nb{}', - message: messages.expected('windows'), - description: 'LF after a rule in the third line', - line: 3, - column: 5, - }, - - { - code: '/* This is a\ncomment*/\r\na {}', - fixed: '/* This is a\r\ncomment*/\r\na {}', - message: messages.expected('windows'), - description: 'LF inside a comment string in the second line', - line: 1, - column: 13, - }, - { - code: '/* This is a\ncomment*/\r\na {}', - fixed: '/* This is a\r\ncomment*/\r\na {}', - message: messages.expected('windows'), - description: - 'LF inside a comment string with several spaces in the beginning in the first line', - line: 1, - column: 16, - }, - { - code: '/*This is a\ncomment*/\r\na {}', - fixed: '/*This is a\r\ncomment*/\r\na {}', - message: messages.expected('windows'), - description: 'LF inside a comment string without spaces in the beginning in the first line', - line: 1, - column: 12, - }, - { - code: '\r\n\r\n/* This is\r\na\ncomment*/\r\na {}', - fixed: '\r\n\r\n/* This is\r\na\r\ncomment*/\r\na {}', - message: messages.expected('windows'), - description: 'LF inside a comment string in the fourth line', - line: 4, - column: 2, - }, - { - code: '/* This is\r\na comment*/\na {}', - fixed: '/* This is\r\na comment*/\r\na {}', - message: messages.expected('windows'), - description: 'LF after a comment in the second line', - line: 2, - column: 12, - }, - { - code: '\n\r\n\r\n\r\n\r\n/* This is\r\na comment*/', - fixed: '\r\n\r\n\r\n\r\n\r\n/* This is\r\na comment*/', - message: messages.expected('windows'), - description: 'LF before a comment at the beginning of the file', - line: 1, - column: 1, - }, - { - code: '\r\n\n\r\n\r\n\r\n/* This is\r\na comment*/', - fixed: '\r\n\r\n\r\n\r\n\r\n/* This is\r\na comment*/', - message: messages.expected('windows'), - description: 'LF before a comment in one of the first empty lines of the file', - line: 2, - column: 1, - }, - { - code: '\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\na {}', - fixed: '\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\na {}', - message: messages.expected('windows'), - description: 'LF before a rule at the beginning of the file', - line: 1, - column: 1, - }, - { - code: '\r\n\r\n\r\n\r\n\r\n\r\n\r\n\n\r\n\r\n\r\na {}', - fixed: '\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\na {}', - message: messages.expected('windows'), - description: 'LF before a rule in one of the first empty lines of the file', - line: 8, - column: 1, - }, - { - code: 'a {}\r\n\r\n\n\r\n\r\n', - fixed: 'a {}\r\n\r\n\r\n\r\n\r\n', - message: messages.expected('windows'), - description: 'LF in one of the last empty lines of the file', - line: 3, - column: 1, - }, - { - code: 'a {}\r\n\r\n\n', - fixed: 'a {}\r\n\r\n\r\n', - message: messages.expected('windows'), - description: 'LF in the last line of the file', - line: 3, - column: 1, - }, - { - code: '.foo\n .bar {}', - fixed: '.foo\r\n .bar {}', - message: messages.expected('windows'), - description: 'LF between selectors in the first line', - line: 1, - column: 5, - }, - { - code: '\r\n\r\n\r\n.foo\n .bar {}', - fixed: '\r\n\r\n\r\n.foo\r\n .bar {}', - message: messages.expected('windows'), - description: 'LF between selectors in the fourth line', - line: 4, - column: 5, - }, - { - code: '\r\n\r\n\r\n.foo\r\n .bar\n .baz {}', - fixed: '\r\n\r\n\r\n.foo\r\n .bar\r\n .baz {}', - message: messages.expected('windows'), - description: 'LF between selectors, additional test', - line: 5, - column: 6, - }, - { - code: 'a { border: 1px\n solid red; }', - fixed: 'a { border: 1px\r\n solid red; }', - message: messages.expected('windows'), - description: 'LF between property values in the first line', - line: 1, - column: 16, - }, - { - code: '\r\n\r\n\r\na { border: 1px\n solid red; }', - fixed: '\r\n\r\n\r\na { border: 1px\r\n solid red; }', - message: messages.expected('windows'), - description: 'LF between property values in the fourth line', - line: 4, - column: 16, - }, - { - code: '\r\n\r\n\r\na { border: 1px\r\n solid \nred; }', - fixed: '\r\n\r\n\r\na { border: 1px\r\n solid \r\nred; }', - message: messages.expected('windows'), - description: 'LF between property values, additional test', - line: 5, - column: 8, - }, - { - code: '\r\n\r\na {\n}', - fixed: '\r\n\r\na {\r\n}', - message: messages.expected('windows'), - description: 'LF after open curly brackets', - line: 3, - column: 4, - }, - { - code: '\r\n\r\na {\r\n}\nb {\r\n}', - fixed: '\r\n\r\na {\r\n}\r\nb {\r\n}', - message: messages.expected('windows'), - description: 'LF after close curly brackets', - line: 4, - column: 2, - }, - ], -}); diff --git a/lib/rules/linebreaks/__tests__/integration.test.js b/lib/rules/linebreaks/__tests__/integration.test.js deleted file mode 100644 index 283fd9ea5d..0000000000 --- a/lib/rules/linebreaks/__tests__/integration.test.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; - -const stylelint = require('../../../..'); - -describe('integration tests for linebrakes', () => { - it('should not be an error (issues/3635).', async () => { - const { output } = await stylelint.lint({ - code: 'a{color:red;}', - config: { - rules: { - linebreaks: 'unix', - 'block-closing-brace-newline-before': 'always', - }, - }, - fix: true, - }); - - expect(output).toBe('a{color:red;\n}'); - }); -}); diff --git a/lib/rules/linebreaks/index.js b/lib/rules/linebreaks/index.js deleted file mode 100644 index e16dee79c7..0000000000 --- a/lib/rules/linebreaks/index.js +++ /dev/null @@ -1,132 +0,0 @@ -'use strict'; - -const postcss = require('postcss'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'linebreaks'; - -const messages = ruleMessages(ruleName, { - expected: (linebreak) => `Expected linebreak to be ${linebreak}`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/linebreaks', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['unix', 'windows'], - }); - - if (!validOptions) { - return; - } - - const shouldHaveCR = primary === 'windows'; - - if (context.fix) { - root.walk((node) => { - if ('selector' in node) { - node.selector = fixData(node.selector); - } - - if ('value' in node) { - node.value = fixData(node.value); - } - - if ('text' in node) { - node.text = fixData(node.text); - } - - if (node.raws.before) { - node.raws.before = fixData(node.raws.before); - } - - if (typeof node.raws.after === 'string') { - node.raws.after = fixData(node.raws.after); - } - }); - - if (typeof root.raws.after === 'string') { - root.raws.after = fixData(root.raws.after); - } - } else { - if (root.source == null) throw new Error('The root node must have a source'); - - const lines = root.source.input.css.split('\n'); - - for (let [i, line] of lines.entries()) { - if (i < lines.length - 1 && !line.includes('\r')) { - line += '\n'; - } - - if (hasError(line)) { - const lineNum = i + 1; - const colNum = line.length; - - reportNewlineError(lineNum, colNum); - } - } - } - - /** - * @param {string} dataToCheck - */ - function hasError(dataToCheck) { - const hasNewlineToVerify = /[\r\n]/.test(dataToCheck); - const hasCR = hasNewlineToVerify ? /\r/.test(dataToCheck) : false; - - return hasNewlineToVerify && hasCR !== shouldHaveCR; - } - - /** - * @param {string} data - */ - function fixData(data) { - if (data) { - let res = data.replace(/\r/g, ''); - - if (shouldHaveCR) { - res = res.replace(/\n/g, '\r\n'); - } - - return res; - } - - return data; - } - - /** - * @param {number} line - * @param {number} column - */ - function reportNewlineError(line, column) { - // Creating a node manually helps us to point to empty lines. - const node = postcss.rule({ - source: { - start: { line, column, offset: 0 }, - input: new postcss.Input(''), - }, - }); - - report({ - message: messages.expected(primary), - node, - result, - ruleName, - }); - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/max-empty-lines/README.md b/lib/rules/max-empty-lines/README.md deleted file mode 100644 index 3288a1d2f9..0000000000 --- a/lib/rules/max-empty-lines/README.md +++ /dev/null @@ -1,118 +0,0 @@ -# max-empty-lines - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Limit the number of adjacent empty lines. - - -```css -a {} - /* ← */ - /* ← */ -a {} /* ↑ */ -/** ↑ - * These lines */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`int`: Maximum number of adjacent empty lines allowed. - -For example, with `2`: - -The following patterns are considered problems: - - -```css -a {} - - - -b {} -``` - -Comment strings are also checked -- so the following is a problem: - - -```css -/* - Call me Ishmael. - - - - Some years ago--never mind how long precisely-—... - */ -``` - -The following patterns are _not_ considered problems: - - -```css -a {} -b {} -``` - - -```css -a {} - -b {} -``` - - -```css -a {} - - -b {} -``` - -## Optional secondary options - -### `ignore: ["comments"]` - -Only enforce the adjacent empty lines limit for lines that are not comments. - -For example, with `2` adjacent empty lines: - -The following patterns are considered problems: - - -```css -/* horse */ -a {} - - - -b {} -``` - -The following patterns are _not_ considered problems: - - -```css -/* - Call me Ishmael. - - - - Some years ago -- never mind how long precisely -- ... - */ -``` - - -```css -a { - /* - Comment - - - - - inside the declaration with a lot of empty lines... - */ - color: pink; -} -``` diff --git a/lib/rules/max-empty-lines/__tests__/index.js b/lib/rules/max-empty-lines/__tests__/index.js deleted file mode 100644 index 223d447cb0..0000000000 --- a/lib/rules/max-empty-lines/__tests__/index.js +++ /dev/null @@ -1,468 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: [0], - fix: true, - - accept: [ - { - code: 'a {}\n', - }, - ], - reject: [ - { - code: '\na {}', - fixed: 'a {}', - message: messages.expected(0), - line: 1, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: [1], - fix: true, - - accept: [ - { - code: '\na {}', - }, - { - code: '\r\na {}', - }, - { - code: 'a {}\n', - }, - { - code: 'a {}\r\n', - }, - { - code: 'a {}\nb {}', - }, - { - code: 'a {}\r\nb {}', - }, - { - code: 'a {}\n\nb {}', - }, - { - code: 'a {}\r\n\r\nb {}', - }, - { - code: '/** horse */\n\nb {}', - }, - { - code: '/** horse */\r\n\r\nb {}', - }, - { - code: 'a {}\n\n/** horse */\n\nb {}', - }, - { - code: 'a {}\r\n\r\n/** horse */\r\n\r\nb {}', - }, - ], - - reject: [ - { - code: '\n\na {}', - fixed: '\na {}', - message: messages.expected(1), - line: 2, - column: 1, - }, - { - code: '\r\n\r\na {}', - fixed: '\r\na {}', - message: messages.expected(1), - line: 2, - column: 1, - }, - { - code: 'a {}\n\n', - fixed: 'a {}\n', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: 'a {}\r\n\r\n', - fixed: 'a {}\r\n', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: 'a {}\n\n\nb {}', - fixed: 'a {}\n\nb {}', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: 'a {}\r\n\r\n\r\nb {}', - fixed: 'a {}\r\n\r\nb {}', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: 'a {}\n\n/** horse */\n\n\nb {}', - fixed: 'a {}\n\n/** horse */\n\nb {}', - message: messages.expected(1), - line: 5, - column: 1, - }, - { - code: 'a {}\n\n\n/** horse */\n\nb {}', - fixed: 'a {}\n\n/** horse */\n\nb {}', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: 'a {}\r\n\r\n/** horse */\r\n\r\n\r\nb {}', - fixed: 'a {}\r\n\r\n/** horse */\r\n\r\nb {}', - message: messages.expected(1), - line: 5, - column: 1, - }, - { - code: '/* horse\n\n\n */\na {}', - fixed: '/* horse\n\n */\na {}', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: '/* horse\r\n\r\n\r\n */\r\na {}', - fixed: '/* horse\r\n\r\n */\r\na {}', - message: messages.expected(1), - line: 3, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: [1], - customSyntax: 'postcss-html', - fix: true, - - accept: [ - { - code: `
- - - - - - - - -
`, - }, - { - code: `
- -
`, - }, - { - code: `
- - -
`, - }, - { - code: ` - -`, - fixed: `
- -
`, - message: messages.expected(1), - line: 5, - column: 1, - }, - - { - code: `
-
`, - fixed: `
-
`, - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: `
- - -
`, - fixed: `
- - -
`, - message: messages.expected(1), - line: 9, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: [2], - fix: true, - - accept: [ - { - code: 'a {}\nb {}', - }, - { - code: 'a {}\n\nb {}', - }, - { - code: 'a {}\n\n\nb {}', - }, - { - code: 'a {}\r\n\r\n\r\nb {}', - }, - { - code: 'a {}\n\n\n/** horse */\n\n\nb {}', - }, - { - code: 'a {}\r\n\r\n\r\n/** horse */\r\n\r\n\r\nb {}', - }, - ], - - reject: [ - { - code: 'a {}\n\n\n\nb {}', - fixed: 'a {}\n\n\nb {}', - message: messages.expected(2), - line: 4, - column: 1, - }, - { - code: 'a {}\r\n\r\n\r\n\r\nb {}', - fixed: 'a {}\r\n\r\n\r\nb {}', - message: messages.expected(2), - line: 4, - column: 1, - }, - { - code: 'a {}\n\n/** horse */\n\n\n\nb {}', - fixed: 'a {}\n\n/** horse */\n\n\nb {}', - message: messages.expected(2), - line: 6, - column: 1, - }, - { - code: 'a {}\r\n\r\n/** horse */\r\n\r\n\r\n\r\nb {}', - fixed: 'a {}\r\n\r\n/** horse */\r\n\r\n\r\nb {}', - message: messages.expected(2), - line: 6, - column: 1, - }, - { - code: '/* horse\n\n\n\n */\na {}', - fixed: '/* horse\n\n\n */\na {}', - message: messages.expected(2), - line: 4, - column: 1, - }, - { - code: '/* horse\r\n\r\n\r\n\r\n */\r\na {}', - fixed: '/* horse\r\n\r\n\r\n */\r\na {}', - message: messages.expected(2), - line: 4, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: [2], - customSyntax: 'postcss-scss', - fix: true, - - accept: [ - { - code: '\n\n// one', - }, - { - code: '// one\n\n', - }, - { - code: '// one\n\n\n// two\n', - }, - ], - - reject: [ - { - code: '\n\n\n// one', - fixed: '\n\n// one', - message: messages.expected(2), - line: 3, - column: 1, - }, - { - code: '// one\n\n\n', - fixed: '// one\n\n', - message: messages.expected(2), - line: 4, - column: 1, - }, - { - code: '// one\n\n\n\n// two\n', - fixed: '// one\n\n\n// two\n', - message: messages.expected(2), - line: 4, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: [2], - customSyntax: 'sugarss', - fix: true, - - accept: [ - { - code: '\n\n// one', - }, - { - code: '// one\n\n', - }, - { - code: '// one\n\n\n// two\n', - }, - ], - - reject: [ - { - code: '\n\n\n// one', - fixed: '\n\n// one', - message: messages.expected(2), - line: 3, - column: 1, - }, - { - code: '// one\n\n\n', - fixed: '// one\n\n', - message: messages.expected(2), - line: 4, - column: 1, - }, - { - code: '// one\n\n\n\n// two\n', - fixed: '// one\n\n\n// two\n', - message: messages.expected(2), - line: 4, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: [2, { ignore: 'comments' }], - fix: true, - - accept: [ - { - code: 'a {}\n\n/*\n\n\n\n*/\n\nb {}', - }, - { - code: 'a {}\r\n\r\n/*\r\n\r\n\r\n\r\n*/\r\n\r\nb {}', - }, - { - code: 'a {}\n\n/**\n\n\n\n\n\n\n*/\n\nb {}', - }, - { - code: 'a {}\r\n\r\n/**\r\n\r\n\r\n\r\n\r\n\r\n\r\n*/\r\n\r\nb {}', - }, - { - code: 'a {\n display: block;\n /*\n\n\n\n */\n}\n\n', - }, - { - code: 'a {\r\n display: block;\r\n /*\r\n\r\n\r\n\r\n */\r\n}\r\n\r\n', - }, - ], - - reject: [ - { - code: 'a {}\n\n/*\n\n\n\n\n*/\n\n\n\nb {}', - fixed: 'a {}\n\n/*\n\n\n\n\n*/\n\n\nb {}', - message: messages.expected(2), - line: 11, - column: 1, - }, - { - code: 'a {}\r\n\r\n/**\r\n\r\n\r\n\r\n\r\n*/\r\n\r\n\r\n\r\nb {}', - fixed: 'a {}\r\n\r\n/**\r\n\r\n\r\n\r\n\r\n*/\r\n\r\n\r\nb {}', - message: messages.expected(2), - line: 11, - column: 1, - }, - ], -}); diff --git a/lib/rules/max-empty-lines/index.js b/lib/rules/max-empty-lines/index.js deleted file mode 100644 index e68be55544..0000000000 --- a/lib/rules/max-empty-lines/index.js +++ /dev/null @@ -1,219 +0,0 @@ -'use strict'; - -const optionsMatches = require('../../utils/optionsMatches'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const styleSearch = require('style-search'); -const validateOptions = require('../../utils/validateOptions'); -const { isNumber } = require('../../utils/validateTypes'); - -const ruleName = 'max-empty-lines'; - -const messages = ruleMessages(ruleName, { - expected: (max) => `Expected no more than ${max} empty ${max === 1 ? 'line' : 'lines'}`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/max-empty-lines', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, secondaryOptions, context) => { - let emptyLines = 0; - let lastIndex = -1; - - return (root, result) => { - const validOptions = validateOptions( - result, - ruleName, - { - actual: primary, - possible: isNumber, - }, - { - actual: secondaryOptions, - possible: { - ignore: ['comments'], - }, - optional: true, - }, - ); - - if (!validOptions) { - return; - } - - const ignoreComments = optionsMatches(secondaryOptions, 'ignore', 'comments'); - const getChars = replaceEmptyLines.bind(null, primary); - - /** - * 1. walk nodes & replace enterchar - * 2. deal with special case. - */ - if (context.fix) { - root.walk((node) => { - if (node.type === 'comment' && !ignoreComments) { - node.raws.left = getChars(node.raws.left); - node.raws.right = getChars(node.raws.right); - } - - if (node.raws.before) { - node.raws.before = getChars(node.raws.before); - } - }); - - // first node - const firstNodeRawsBefore = root.first && root.first.raws.before; - // root raws - const rootRawsAfter = root.raws.after; - - // not document node - // @ts-expect-error -- TS2339: Property 'document' does not exist on type 'Root'. - if ((root.document && root.document.constructor.name) !== 'Document') { - if (firstNodeRawsBefore) { - root.first.raws.before = getChars(firstNodeRawsBefore, true); - } - - if (rootRawsAfter) { - // when max set 0, should be treated as 1 in this situation. - root.raws.after = replaceEmptyLines(primary === 0 ? 1 : primary, rootRawsAfter, true); - } - } else if (rootRawsAfter) { - // `css in js` or `html` - root.raws.after = replaceEmptyLines(primary === 0 ? 1 : primary, rootRawsAfter); - } - - return; - } - - emptyLines = 0; - lastIndex = -1; - const rootString = root.toString(); - - styleSearch( - { - source: rootString, - target: /\r\n/.test(rootString) ? '\r\n' : '\n', - comments: ignoreComments ? 'skip' : 'check', - }, - (match) => { - checkMatch(rootString, match.startIndex, match.endIndex, root); - }, - ); - - /** - * @param {string} source - * @param {number} matchStartIndex - * @param {number} matchEndIndex - * @param {import('postcss').Root} node - */ - function checkMatch(source, matchStartIndex, matchEndIndex, node) { - const eof = matchEndIndex === source.length; - let problem = false; - - // Additional check for beginning of file - if (!matchStartIndex || lastIndex === matchStartIndex) { - emptyLines++; - } else { - emptyLines = 0; - } - - lastIndex = matchEndIndex; - - if (emptyLines > primary) problem = true; - - if (!eof && !problem) return; - - if (problem) { - report({ - message: messages.expected(primary), - node, - index: matchStartIndex, - result, - ruleName, - }); - } - - // Additional check for end of file - if (eof && primary) { - emptyLines++; - - if (emptyLines > primary && isEofNode(result.root, node)) { - report({ - message: messages.expected(primary), - node, - index: matchEndIndex, - result, - ruleName, - }); - } - } - } - - /** - * @param {number} maxLines - * @param {unknown} str - * @param {boolean?} isSpecialCase - */ - function replaceEmptyLines(maxLines, str, isSpecialCase = false) { - const repeatTimes = isSpecialCase ? maxLines : maxLines + 1; - - if (repeatTimes === 0 || typeof str !== 'string') { - return ''; - } - - const emptyLFLines = '\n'.repeat(repeatTimes); - const emptyCRLFLines = '\r\n'.repeat(repeatTimes); - - return /(?:\r\n)+/.test(str) - ? str.replace(/(\r\n)+/g, ($1) => { - if ($1.length / 2 > repeatTimes) { - return emptyCRLFLines; - } - - return $1; - }) - : str.replace(/(\n)+/g, ($1) => { - if ($1.length > repeatTimes) { - return emptyLFLines; - } - - return $1; - }); - } - }; -}; - -/** - * Checks whether the given node is the last node of file. - * @param {import('stylelint').PostcssResult['root']} document - the document node with `postcss-html` and `postcss-jsx`. - * @param {import('postcss').Root} root - the root node of css - */ -function isEofNode(document, root) { - if (!document || document.constructor.name !== 'Document' || !('type' in document)) { - return true; - } - - // In the `postcss-html` and `postcss-jsx` syntax, checks that there is text after the given node. - let after; - - if (root === document.last) { - after = document.raws && document.raws.codeAfter; - } else { - // @ts-expect-error -- TS2345: Argument of type 'Root' is not assignable to parameter of type 'number | ChildNode'. - const rootIndex = document.index(root); - - const nextNode = document.nodes[rootIndex + 1]; - - after = nextNode && nextNode.raws && nextNode.raws.codeBefore; - } - - return !String(after).trim(); -} - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/max-line-length/README.md b/lib/rules/max-line-length/README.md deleted file mode 100644 index c38f34f058..0000000000 --- a/lib/rules/max-line-length/README.md +++ /dev/null @@ -1,153 +0,0 @@ -# max-line-length - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Limit the length of a line. - - -```css -a { color: red } -/** ↑ - * The end */ -``` - -Lines that exceed the maximum length but contain no whitespace (other than at the beginning of the line) are ignored. - -When evaluating the line length, the arguments of any `url(...)` functions are excluded from the calculation, because typically you have no control over the length of these arguments. This means that long `url()` functions should not contribute to problems. - -## Options - -`int`: Maximum number of characters allowed. - -For example, with `20`: - -The following patterns are considered problems: - - -```css -a { color: 0; top: 0; } -``` - - -```css -a { - background: linear-gradient(red, blue); -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { - color: 0; - top: 0; -} -``` - - -```css -a { - background: url(a-url-that-is-over-20-characters-long); -} -``` - -## Optional secondary options - -### `ignore: ["non-comments"]` - -Only enforce the line-length limit for lines within comments. - -This does not apply to comments that are stuck in between other stuff, only to lines that begin at the beginning or in the middle of a comment. - -For example, with a maximum length of `30`. - -The following patterns are considered problems: - -Each have only one problem. - - -```css -/* This line is too long for my rule */ -a { color: pink; background: orange; } -a { color: pink; /* this comment is also long but not on its own line */ } -``` - - -```css -a { color: pink; background: orange; } -/** - * This line is short, - * but this line is too long for my liking, - * though this one is fine - */ -a { color: pink; /* this comment is also long but not on its own line */ } -``` - -### `ignore: ["comments"]` - -Only enforce the line-length limit for lines that are not comments. - -This also applies to comments that are between code on the same line. - -For example, with a maximum length of `30`. - -The following patterns are considered problems: - - -```css -a { color: pink; } /* comment that is too long */ -``` - - -```css -a { /* this comment is too long for the max length */ } -``` - -The following patterns are _not_ considered problems: - - -```css -/* comment that is too long for my rule*/ -a { color: pink; } -``` - - -```css -/* - * comment that is too long the max length - * comment that is too long the max length - * - */ -a { color: pink; } -``` - -### `ignorePattern: "/regex/"` - -Ignore any line that matches the given regex pattern, regardless of whether it is comment or not. The regex may be passed as a string (for JSON configuration) by enclosing in forward-slashes, or an ordinary JavaScript RegExp may be used. - -Given: - -```json -"/^@import\\s+/" -``` - -The following pattern is _not_ considered a problem: - - -```css -@import "../../../../another/css/or/scss/file/or/something.css"; -``` - -Given the following, with a maximum length of `20`. - -```js -["/https?://[0-9,a-z]*.*/"]; -``` - -The following pattern is _not_ considered a problem: - - -```css -/* ignore urls https://www.example.com */ -``` diff --git a/lib/rules/max-line-length/__tests__/index.js b/lib/rules/max-line-length/__tests__/index.js deleted file mode 100644 index 665d5989a4..0000000000 --- a/lib/rules/max-line-length/__tests__/index.js +++ /dev/null @@ -1,540 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -const testUrl = 'somethingsomething something\tsomething'; -const _21whitespaces = Array.from({ length: 21 }).fill('\u0020').join(''); - -testRule({ - ruleName, - config: [20], - - accept: [ - { - code: 'a { color: 0; }', - }, - { - code: 'a { color : 0 ; }', - }, - { - code: 'a { color: 0;\n top: 0; }', - }, - { - code: '@media print {\n a {\n color: pink;\n }\n}', - }, - { - code: `a {\n background: url("${testUrl}");\n}`, - }, - { - code: `@import '${testUrl}';\na {\n background: url("${testUrl}");\n}`, - }, - { - code: `a {\n background: uRl("${testUrl}");\n}`, - }, - { - code: `a {\n background: URL("${testUrl}");\n}`, - }, - { - code: `a {\n background: url(\n "${testUrl}"\n );\n}`, - }, - { - code: `a {\n background: uRl(\n "${testUrl}"\n );\n}`, - }, - { - code: `a {\n background: URL(\n "${testUrl}"\n );\n}`, - }, - { - code: `a {\n background: URL(\n "${testUrl}"\n );\nbackground: url(\n "${testUrl}"\n);\n}`, - }, - { - code: 'a { margin: 0 2px; }\r\n', - }, - { - code: 'a { margin: 0 2px; }\r\na { margin: 4px 0; }\n', - }, - { - code: `@import url("${testUrl}") print;`, - }, - { - code: `@import '${testUrl}';`, - }, - { - code: `@import "${testUrl}";`, - }, - { - code: `@import url("${testUrl}");`, - }, - { - code: '@import \'svg-something\' projection;', - }, - { - code: `a {\n background-image:\nurl(\n${_21whitespaces.slice(0, 20)}"${testUrl}"\n); }`, - description: 'exactly 20 whitespaces', - }, - { - code: `a {\n background-image:\nurl(\n"${testUrl}"${_21whitespaces.slice(0, 20)}\n); }`, - description: 'exactly 20 whitespaces', - }, - ], - - reject: [ - { - code: 'a { color : 0 ;}', - message: messages.expected(20), - line: 1, - column: 21, - }, - { - code: 'a { color: 0; top: 0; }', - message: messages.expected(20), - line: 1, - column: 23, - }, - { - code: 'a { color: 0;\n top: 0; bottom: 0; right: 0; \n left: 0; }', - message: messages.expected(20), - line: 2, - column: 31, - }, - { - code: 'a { color: 0;\n top: 0;\n left: 0; bottom: 0; right: 0; }', - message: messages.expected(20), - line: 3, - column: 33, - }, - { - code: `a {\n background: URL(\n "${testUrl}"\n );\n background: url(\n "${testUrl}"\n);\n}`, - message: messages.expected(20), - line: 5, - column: 27, - }, - { - code: '@media print {\n a {\n color: pink; background: orange;\n }\n}', - message: messages.expected(20), - line: 3, - column: 36, - }, - { - code: '@media (min-width: 30px) and screen {}', - message: messages.expected(20), - line: 1, - column: 38, - }, - { - code: 'a { margin: 0 2rem; }\r\n', - message: messages.expected(20), - line: 1, - column: 21, - }, - { - code: `@import url("${testUrl}") projection, tv;`, - message: messages.expected(20), - line: 1, - column: 69, - }, - { - code: `@import '${testUrl}' projection, tv;`, - message: messages.expected(20), - line: 1, - column: 64, - }, - { - code: `@import "${testUrl}" projection, tv;`, - message: messages.expected(20), - line: 1, - column: 64, - }, - { - code: '@import \'svg-something\' screens, tv;', - message: messages.expected(20), - line: 1, - column: 48, - }, - { - code: `a { background-image: url("${testUrl}"); }`, - message: messages.expected(20), - line: 1, - column: 70, - }, - { - code: 'a {\n /* Lorem ipsum dolor sit amet. The comment Lorem ipsum dolor sit amet, consectetur adipisicing elit. Praesentium officia fugiat unde deserunt sit, tenetur! Incidunt similique blanditiis placeat ad quia possimus libero, reiciendis excepturi non esse deserunt a odit. */\n}', - message: messages.expected(20), - line: 2, - column: 272, - }, - { - code: `a { - background-image: - url( - ${_21whitespaces}"${testUrl}" - ); - }`, - description: 'more than 20 whitespaces', - message: messages.expected(20), - line: 4, - column: 69, - }, - { - code: `a { - background-image: - url( - "${testUrl}"${_21whitespaces} - ); - }`, - description: 'more than 20 whitespaces', - message: messages.expected(20), - line: 4, - column: 69, - }, - { - code: `@import '${testUrl}';\na {\n background: url("${testUrl}"${_21whitespaces});\n}`, - warnings: [ - { - message: messages.expected(20), - line: 3, - column: 80, - }, - ], - }, - { - code: `@import url("${testUrl}"${_21whitespaces});`, - warnings: [ - { - message: messages.expected(20), - line: 1, - column: 75, - }, - ], - }, - { - code: `@import '${testUrl}'${_21whitespaces};\na {\n background: url("${testUrl}"${_21whitespaces});\n}`, - warnings: [ - { - message: messages.expected(20), - line: 1, - column: 70, - }, - { - message: messages.expected(20), - line: 3, - column: 80, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: [20], - customSyntax: 'postcss-html', - - accept: [ - { - code: `
-
Very very very very very very very very very very very very very long line
- - -
`, - }, - ], - - reject: [ - { - code: `
- - -
`, - message: messages.expected(20), - line: 4, - column: 23, - }, - { - code: `
-
Very very very very very very very very very very very very very long line
-
Very very very very very very very very very very very very very long line
- - -
`, - message: messages.expected(20), - line: 6, - column: 23, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-scss', - config: [20], - - reject: [ - { - code: 'a {\n // Lorem ipsum dolor sit amet. The comment Lorem ipsum dolor sit amet, consectetur adipisicing elit. Praesentium officia fugiat unde deserunt sit, tenetur! Incidunt similique blanditiis placeat ad quia possimus libero, reiciendis excepturi non esse deserunt a odit.\n}', - message: messages.expected(20), - line: 2, - column: 269, - }, - ], -}); - -testRule({ - ruleName, - config: [30], - - accept: [ - { - code: 'a { color: 0;\n top: 0; left: 0; right: 0; \n bottom: 0; }', - }, - { - code: '@import url("somethingsomethingsomethingsomething.css") print;', - }, - { - code: '@import url("somethingsomethingsomethingsomething.css") projection, tv;', - }, - { - code: '@import url("chrome://somethingsomethingsomethingsomething/");', - }, - { - code: '@import "somethingsomethingsomethingsomething.css" screen, projection;', - }, - ], - - reject: [ - { - code: 'a { color: 0;\n top: 0; left: 0; right: 0; background: pink; \n bottom: 0; }', - message: messages.expected(30), - line: 2, - column: 47, - }, - { - code: '@import url("somethingsomethingsomethingsomething.css") projection, screen;', - message: messages.expected(30), - line: 1, - column: 75, - }, - { - code: '@import "somethingsomethingsomethingsomething.css" screen, projection, tv;', - message: messages.expected(30), - line: 1, - column: 74, - }, - ], -}); - -testRule({ - ruleName, - config: [20, { ignore: 'non-comments' }], - - accept: [ - { - code: 'a { color: 0; top: 0; bottom: 0; }', - }, - { - code: 'a { color: 0; top: 0; /* too long comment here */ bottom: 0; }', - }, - { - code: '/* short nuff */', - }, - { - code: '/* short\nnuff */', - }, - { - code: '/**\n * each line\n * short nuff\n */', - }, - { - code: 'a { color: 0; }\n/* short nuff */\nb {}', - }, - { - code: 'a {}\n/**\n * each line\n * short nuff\n */\nb {}', - }, - { - code: 'a { /* this comment is too long for the max length */ }', - }, - ], - - reject: [ - { - code: '/* comment that is too long */', - message: messages.expected(20), - line: 1, - column: 30, - }, - { - code: 'a {}\n /* comment that is too long */\nb {}', - message: messages.expected(20), - line: 2, - column: 32, - }, - { - code: '/* this comment is too long for the max length */', - message: messages.expected(20), - line: 1, - column: 49, - }, - { - code: 'a {}\n/**\n * each line\n * short nuff\n * except this one which is too long\n */\nb {}', - message: messages.expected(20), - line: 5, - column: 36, - }, - ], -}); - -testRule({ - ruleName, - config: [20, { ignore: 'comments' }], - - accept: [ - { - code: '/* comment that is too long */', - }, - { - code: ' /* comment that is too long */', - }, - { - code: '/* short */ a { color: 0; }', - }, - { - code: 'a {}\n/* comment that is too long\n*/ a { color: 0; top: 0; }', - }, - { - code: '/**\n comment that is too long #1\n comment that is too long #2 */', - }, - ], - - reject: [ - { - code: 'a { color: 0; } /* comment that is too long */', - message: messages.expected(20), - line: 1, - column: 46, - }, - { - code: 'a { /* this comment is too long for the max length */ }', - message: messages.expected(20), - line: 1, - column: 55, - }, - ], -}); - -testRule({ - ruleName, - config: [30, { ignorePattern: '/^my-/' }], - - accept: [ - { - code: 'my-property: has-a-really-long-declaration-value-for-some-reason', - }, - ], -}); - -testRule({ - ruleName, - config: [20, { ignorePattern: '/https?://[0-9,a-z]*.*/' }], - - accept: [ - { - code: '/* ignore urls https://www.example.com */', - }, - ], - - reject: [ - { - code: "/* don't ignore lines without urls something something */", - message: messages.expected(20), - line: 1, - column: 57, - }, - ], -}); - -testRule({ - ruleName, - config: [30, { ignorePattern: '/@import\\s+/' }], - - accept: [ - { - code: '@import "../../../something/something/something/something.css" screen, projection, tv;', - }, - ], - - reject: [ - { - code: 'a { color: 0;\n top: 0; left: 0; right: 0; background: pink; \n bottom: 0; }', - message: messages.expected(30), - line: 2, - column: 47, - }, - { - code: '@import "../../../something/something/something/something.css";\na { color: 0;\n top: 0; left: 0; right: 0; background: pink; \n bottom: 0; }', - message: messages.expected(30), - line: 3, - column: 47, - }, - ], -}); - -testRule({ - ruleName, - config: [20, { ignorePattern: '/(Multiple:.+)|(Should:.+)/' }], - - accept: [ - { - code: '/*\n Multiple: lines in multiline comments\n Should: be able to be ignored\n*/', - }, - ], - - reject: [ - { - code: '/*\n multiple: lines in multiline comments\n Should: be able to be ignored\n*/', - message: messages.expected(20), - line: 2, - column: 38, - }, - ], -}); - -testRule({ - ruleName, - config: [30, { ignorePattern: /^my-/ }], - - accept: [ - { - code: 'my-property: has-a-really-long-declaration-value-for-some-reason', - }, - ], -}); - -testRule({ - ruleName, - config: [20, { ignorePattern: /(Multiple:.+)|(Should:.+)/ }], - - accept: [ - { - code: '/*\n Multiple: lines in multiline comments\n Should: be able to be ignored\n*/', - }, - ], - - reject: [ - { - code: '/*\n multiple: lines in multiline comments\n Should: be able to be ignored\n*/', - message: messages.expected(20), - line: 2, - column: 38, - }, - ], -}); diff --git a/lib/rules/max-line-length/index.js b/lib/rules/max-line-length/index.js deleted file mode 100644 index 87aa7c8bc8..0000000000 --- a/lib/rules/max-line-length/index.js +++ /dev/null @@ -1,203 +0,0 @@ -'use strict'; - -const optionsMatches = require('../../utils/optionsMatches'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const styleSearch = require('style-search'); -const validateOptions = require('../../utils/validateOptions'); -const { isNumber, isRegExp, isString, assert } = require('../../utils/validateTypes'); - -const ruleName = 'max-line-length'; - -const messages = ruleMessages(ruleName, { - expected: (max) => - `Expected line length to be no more than ${max} ${max === 1 ? 'character' : 'characters'}`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/max-line-length', - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions( - result, - ruleName, - { - actual: primary, - possible: isNumber, - }, - { - actual: secondaryOptions, - possible: { - ignore: ['non-comments', 'comments'], - ignorePattern: [isString, isRegExp], - }, - optional: true, - }, - ); - - if (!validOptions) { - return; - } - - if (root.source == null) { - throw new Error('The root node must have a source'); - } - - const EXCLUDED_PATTERNS = [ - /url\(\s*(\S.*\S)\s*\)/gi, // allow tab, whitespace in url content - /@import\s+(['"].*['"])/gi, - ]; - - const ignoreNonComments = optionsMatches(secondaryOptions, 'ignore', 'non-comments'); - const ignoreComments = optionsMatches(secondaryOptions, 'ignore', 'comments'); - const rootString = context.fix ? root.toString() : root.source.input.css; - // Array of skipped sub strings, i.e `url(...)`, `@import "..."` - /** @type {Array<[number, number]>} */ - let skippedSubStrings = []; - let skippedSubStringsIndex = 0; - - for (const pattern of EXCLUDED_PATTERNS) { - for (const match of rootString.matchAll(pattern)) { - const subMatch = match[1] || ''; - const startOfSubString = (match.index || 0) + (match[0] || '').indexOf(subMatch); - - skippedSubStrings.push([startOfSubString, startOfSubString + subMatch.length]); - } - } - - skippedSubStrings = skippedSubStrings.sort((a, b) => a[0] - b[0]); - - // Check first line - checkNewline({ endIndex: 0 }); - // Check subsequent lines - styleSearch({ source: rootString, target: ['\n'], comments: 'check' }, (match) => - checkNewline(match), - ); - - /** - * @param {number} index - */ - function complain(index) { - report({ - index, - result, - ruleName, - message: messages.expected(primary), - node: root, - }); - } - - /** - * @param {number} start - * @param {number} end - */ - function tryToPopSubString(start, end) { - const skippedSubString = skippedSubStrings[skippedSubStringsIndex]; - - assert(skippedSubString); - const [startSubString, endSubString] = skippedSubString; - - // Excluded substring does not presented in current line - if (end < startSubString) { - return 0; - } - - // Compute excluded substring size regarding to current line indexes - const excluded = Math.min(end, endSubString) - Math.max(start, startSubString); - - // Current substring is out of range for next lines - if (endSubString <= end) { - skippedSubStringsIndex++; - } - - return excluded; - } - - /** - * @param {import('style-search').StyleSearchMatch | { endIndex: number }} match - */ - function checkNewline(match) { - let nextNewlineIndex = rootString.indexOf('\n', match.endIndex); - - if (rootString[nextNewlineIndex - 1] === '\r') { - nextNewlineIndex -= 1; - } - - // Accommodate last line - if (nextNewlineIndex === -1) { - nextNewlineIndex = rootString.length; - } - - const rawLineLength = nextNewlineIndex - match.endIndex; - const excludedLength = skippedSubStrings[skippedSubStringsIndex] - ? tryToPopSubString(match.endIndex, nextNewlineIndex) - : 0; - const lineText = rootString.slice(match.endIndex, nextNewlineIndex); - - // Case sensitive ignorePattern match - if (optionsMatches(secondaryOptions, 'ignorePattern', lineText)) { - return; - } - - // If the line's length is less than or equal to the specified - // max, ignore it ... So anything below is liable to be complained about. - // **Note that the length of any url arguments or import urls - // are excluded from the calculation.** - if (rawLineLength - excludedLength <= primary) { - return; - } - - const complaintIndex = nextNewlineIndex - 1; - - if (ignoreComments) { - if ('insideComment' in match && match.insideComment) { - return; - } - - // This trimming business is to notice when the line starts a - // comment but that comment is indented, e.g. - // /* something here */ - const nextTwoChars = rootString.slice(match.endIndex).trim().slice(0, 2); - - if (nextTwoChars === '/*' || nextTwoChars === '//') { - return; - } - } - - if (ignoreNonComments) { - if ('insideComment' in match && match.insideComment) { - return complain(complaintIndex); - } - - // This trimming business is to notice when the line starts a - // comment but that comment is indented, e.g. - // /* something here */ - const nextTwoChars = rootString.slice(match.endIndex).trim().slice(0, 2); - - if (nextTwoChars !== '/*' && nextTwoChars !== '//') { - return; - } - - return complain(complaintIndex); - } - - // If there are no spaces besides initial (indent) spaces, ignore it - const lineString = rootString.slice(match.endIndex, nextNewlineIndex); - - if (!lineString.replace(/^\s+/, '').includes(' ')) { - return; - } - - return complain(complaintIndex); - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/media-feature-colon-space-after/README.md b/lib/rules/media-feature-colon-space-after/README.md deleted file mode 100644 index ea4002b8a1..0000000000 --- a/lib/rules/media-feature-colon-space-after/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# media-feature-colon-space-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace after the colon in media features. - - -```css -@media (max-width: 600px) {} -/** ↑ - * The space after this colon */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a single space after the colon. - -The following patterns are considered problems: - - -```css -@media (max-width:600px) {} -``` - - -```css -@media (max-width :600px) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media (max-width: 600px) {} -``` - - -```css -@media (max-width : 600px) {} -``` - -### `"never"` - -There _must never_ be whitespace after the colon. - -The following patterns are considered problems: - - -```css -@media (max-width: 600px) {} -``` - - -```css -@media (max-width : 600px) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media (max-width:600px) {} -``` - - -```css -@media (max-width :600px) {} -``` diff --git a/lib/rules/media-feature-colon-space-after/__tests__/index.js b/lib/rules/media-feature-colon-space-after/__tests__/index.js deleted file mode 100644 index a574881c75..0000000000 --- a/lib/rules/media-feature-colon-space-after/__tests__/index.js +++ /dev/null @@ -1,250 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: '@media (max-width: 600px) {}', - }, - { - code: '@mEdIa (max-width: 600px) {}', - }, - { - code: '@MEDIA (max-width: 600px) {}', - }, - { - code: '@media (max-width : 600px) {}', - }, - { - code: '@media (max-width: 600px) and (min-width: 3em) {}', - }, - { - code: '@custom-selector :--enter :hover;', - }, - ], - - reject: [ - { - code: '@media (max-width:600px) {}', - fixed: '@media (max-width: 600px) {}', - message: messages.expectedAfter(), - line: 1, - column: 18, - }, - { - code: '@mEdIa (max-width:600px) {}', - fixed: '@mEdIa (max-width: 600px) {}', - message: messages.expectedAfter(), - line: 1, - column: 18, - }, - { - code: '@MEDIA (max-width:600px) {}', - fixed: '@MEDIA (max-width: 600px) {}', - message: messages.expectedAfter(), - line: 1, - column: 18, - }, - { - code: '@media (max-width: 600px) {}', - fixed: '@media (max-width: 600px) {}', - message: messages.expectedAfter(), - line: 1, - column: 18, - }, - { - code: '@media (max-width:\t600px) {}', - fixed: '@media (max-width: 600px) {}', - message: messages.expectedAfter(), - line: 1, - column: 18, - }, - { - code: '@media (max-width:\n600px) {}', - fixed: '@media (max-width: 600px) {}', - message: messages.expectedAfter(), - line: 1, - column: 18, - }, - { - code: '@media (max-width:\r\n600px) {}', - fixed: '@media (max-width: 600px) {}', - description: 'CRLF', - message: messages.expectedAfter(), - line: 1, - column: 18, - }, - { - code: '@media (max-width:600px) and (min-width: 3em) {}', - fixed: '@media (max-width: 600px) and (min-width: 3em) {}', - message: messages.expectedAfter(), - line: 1, - column: 18, - }, - { - code: '@media (max-width: 600px) and (min-width:3em) {}', - fixed: '@media (max-width: 600px) and (min-width: 3em) {}', - message: messages.expectedAfter(), - line: 1, - column: 41, - }, - { - code: '@media (max-width:600px) and (min-width:3em) {}', - fixed: '@media (max-width: 600px) and (min-width: 3em) {}', - warnings: [ - { - message: messages.expectedAfter(), - line: 1, - column: 18, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 40, - }, - ], - }, - { - code: '@media(p:600px) and (prop:600px) {}', - fixed: '@media(p: 600px) and (prop: 600px) {}', - warnings: [ - { - message: messages.expectedAfter(), - line: 1, - column: 9, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - ], - }, - { - code: '@media (max-width:/*comment*/600px) {}', - fixed: '@media (max-width: /*comment*/600px) {}', - message: messages.expectedAfter(), - line: 1, - column: 18, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: '@media (max-width:600px) {}', - }, - { - code: '@mEdIa (max-width:600px) {}', - }, - { - code: '@MEDIA (max-width:600px) {}', - }, - { - code: '@media (max-width:600px) and (min-width:3em) {}', - }, - { - code: '@custom-selector : --enter :hover;', - }, - ], - - reject: [ - { - code: '@media (max-width: 600px) {}', - fixed: '@media (max-width:600px) {}', - message: messages.rejectedAfter(), - line: 1, - column: 18, - }, - { - code: '@mEdIa (max-width: 600px) {}', - fixed: '@mEdIa (max-width:600px) {}', - message: messages.rejectedAfter(), - line: 1, - column: 18, - }, - { - code: '@MEDIA (max-width: 600px) {}', - fixed: '@MEDIA (max-width:600px) {}', - message: messages.rejectedAfter(), - line: 1, - column: 18, - }, - { - code: '@media (max-width: 600px) {}', - fixed: '@media (max-width:600px) {}', - message: messages.rejectedAfter(), - line: 1, - column: 18, - }, - { - code: '@media (max-width:\t600px) {}', - fixed: '@media (max-width:600px) {}', - message: messages.rejectedAfter(), - line: 1, - column: 18, - }, - { - code: '@media (max-width:\n600px) {}', - fixed: '@media (max-width:600px) {}', - message: messages.rejectedAfter(), - line: 1, - column: 18, - }, - { - code: '@media (max-width:\r\n600px) {}', - fixed: '@media (max-width:600px) {}', - description: 'CRLF', - message: messages.rejectedAfter(), - line: 1, - column: 18, - }, - { - code: '@media (max-width:600px) and (min-width: 3em) {}', - fixed: '@media (max-width:600px) and (min-width:3em) {}', - message: messages.rejectedAfter(), - line: 1, - column: 40, - }, - { - code: '@media (max-width: 600px) and (min-width:3em) {}', - fixed: '@media (max-width:600px) and (min-width:3em) {}', - message: messages.rejectedAfter(), - line: 1, - column: 18, - }, - { - code: '@media (max-width: 600px) and (min-width: 3em) {}', - fixed: '@media (max-width:600px) and (min-width:3em) {}', - warnings: [ - { - message: messages.rejectedAfter(), - line: 1, - column: 18, - }, - { - message: messages.rejectedAfter(), - line: 1, - column: 41, - }, - ], - }, - { - code: '@media (max-width: /*comment*/ 600px) {}', - fixed: '@media (max-width:/*comment*/ 600px) {}', - message: messages.rejectedAfter(), - line: 1, - column: 18, - }, - ], -}); diff --git a/lib/rules/media-feature-colon-space-after/index.js b/lib/rules/media-feature-colon-space-after/index.js deleted file mode 100644 index f456adf0de..0000000000 --- a/lib/rules/media-feature-colon-space-after/index.js +++ /dev/null @@ -1,87 +0,0 @@ -'use strict'; - -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const mediaFeatureColonSpaceChecker = require('../mediaFeatureColonSpaceChecker'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'media-feature-colon-space-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected single space after ":"', - rejectedAfter: () => 'Unexpected whitespace after ":"', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/media-feature-colon-space-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - /** @type {Map | undefined} */ - let fixData; - - mediaFeatureColonSpaceChecker({ - root, - result, - locationChecker: checker.after, - checkedRuleName: ruleName, - fix: context.fix - ? (atRule, index) => { - const paramColonIndex = index - atRuleParamIndex(atRule); - - fixData = fixData || new Map(); - const colonIndices = fixData.get(atRule) || []; - - colonIndices.push(paramColonIndex); - fixData.set(atRule, colonIndices); - - return true; - } - : null, - }); - - if (fixData) { - for (const [atRule, colonIndices] of fixData.entries()) { - let params = atRule.raws.params ? atRule.raws.params.raw : atRule.params; - - for (const index of colonIndices.sort((a, b) => b - a)) { - const beforeColon = params.slice(0, index + 1); - const afterColon = params.slice(index + 1); - - if (primary === 'always') { - params = beforeColon + afterColon.replace(/^\s*/, ' '); - } else if (primary === 'never') { - params = beforeColon + afterColon.replace(/^\s*/, ''); - } - } - - if (atRule.raws.params) { - atRule.raws.params.raw = params; - } else { - atRule.params = params; - } - } - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/media-feature-colon-space-before/README.md b/lib/rules/media-feature-colon-space-before/README.md deleted file mode 100644 index 99a3089359..0000000000 --- a/lib/rules/media-feature-colon-space-before/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# media-feature-colon-space-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace before the colon in media features. - - -```css -@media (max-width :600px) {} -/** ↑ - * The space before this colon */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a single space before the colon. - -The following patterns are considered problems: - - -```css -@media (max-width:600px) {} -``` - - -```css -@media (max-width: 600px) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media (max-width :600px) {} -``` - - -```css -@media (max-width : 600px) {} -``` - -### `"never"` - -There _must never_ be whitespace before the colon. - -The following patterns are considered problems: - - -```css -@media (max-width :600px) {} -``` - - -```css -@media (max-width : 600px) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media (max-width:600px) {} -``` - - -```css -@media (max-width: 600px) {} -``` diff --git a/lib/rules/media-feature-colon-space-before/__tests__/index.js b/lib/rules/media-feature-colon-space-before/__tests__/index.js deleted file mode 100644 index e8feff1107..0000000000 --- a/lib/rules/media-feature-colon-space-before/__tests__/index.js +++ /dev/null @@ -1,237 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: '@media (max-width :600px) {}', - }, - { - code: '@mEdIa (max-width :600px) {}', - }, - { - code: '@MEDIA (max-width :600px) {}', - }, - { - code: '@media (max-width : 600px) {}', - }, - { - code: '@media (max-width :600px) and (min-width :3em) {}', - }, - { - code: '@custom-selector:--enter :hover;', - }, - ], - - reject: [ - { - code: '@media (max-width:600px) {}', - fixed: '@media (max-width :600px) {}', - message: messages.expectedBefore(), - line: 1, - column: 18, - }, - { - code: '@mEdIa (max-width:600px) {}', - fixed: '@mEdIa (max-width :600px) {}', - message: messages.expectedBefore(), - line: 1, - column: 18, - }, - { - code: '@MEDIA (max-width:600px) {}', - fixed: '@MEDIA (max-width :600px) {}', - message: messages.expectedBefore(), - line: 1, - column: 18, - }, - { - code: '@media (max-width :600px) {}', - fixed: '@media (max-width :600px) {}', - message: messages.expectedBefore(), - line: 1, - column: 20, - }, - { - code: '@media (max-width\t:600px) {}', - fixed: '@media (max-width :600px) {}', - message: messages.expectedBefore(), - line: 1, - column: 19, - }, - { - code: '@media (max-width\n:600px) {}', - fixed: '@media (max-width :600px) {}', - message: messages.expectedBefore(), - line: 2, - column: 1, - }, - { - code: '@media (max-width\r\n:600px) {}', - fixed: '@media (max-width :600px) {}', - description: 'CRLF', - message: messages.expectedBefore(), - line: 2, - column: 1, - }, - { - code: '@media (max-width:600px) and (min-width :3em) {}', - fixed: '@media (max-width :600px) and (min-width :3em) {}', - message: messages.expectedBefore(), - line: 1, - column: 18, - }, - { - code: '@media (max-width :600px) and (min-width:3em) {}', - fixed: '@media (max-width :600px) and (min-width :3em) {}', - message: messages.expectedBefore(), - line: 1, - column: 41, - }, - { - code: '@media (max-width:600px) and (min-width:3em) {}', - fixed: '@media (max-width :600px) and (min-width :3em) {}', - warnings: [ - { - message: messages.expectedBefore(), - line: 1, - column: 18, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 40, - }, - ], - }, - { - code: '@media (max-width/*comment*/:600px) {}', - fixed: '@media (max-width/*comment*/ :600px) {}', - message: messages.expectedBefore(), - line: 1, - column: 29, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: '@media (max-width:600px) {}', - }, - { - code: '@mEdIa (max-width:600px) {}', - }, - { - code: '@MEDIA (max-width:600px) {}', - }, - { - code: '@media (max-width: 600px) {}', - }, - { - code: '@media (max-width:600px) and (min-width:3em) {}', - }, - { - code: '@custom-selector :--enter :hover;', - }, - ], - - reject: [ - { - code: '@media (max-width :600px) {}', - fixed: '@media (max-width:600px) {}', - message: messages.rejectedBefore(), - line: 1, - column: 19, - }, - { - code: '@mEdIa (max-width :600px) {}', - fixed: '@mEdIa (max-width:600px) {}', - message: messages.rejectedBefore(), - line: 1, - column: 19, - }, - { - code: '@MEDIA (max-width :600px) {}', - fixed: '@MEDIA (max-width:600px) {}', - message: messages.rejectedBefore(), - line: 1, - column: 19, - }, - { - code: '@media (max-width :600px) {}', - fixed: '@media (max-width:600px) {}', - message: messages.rejectedBefore(), - line: 1, - column: 20, - }, - { - code: '@media (max-width\t:600px) {}', - fixed: '@media (max-width:600px) {}', - message: messages.rejectedBefore(), - line: 1, - column: 19, - }, - { - code: '@media (max-width\n:600px) {}', - fixed: '@media (max-width:600px) {}', - message: messages.rejectedBefore(), - line: 2, - column: 1, - }, - { - code: '@media (max-width\r\n:600px) {}', - fixed: '@media (max-width:600px) {}', - description: 'CRLF', - message: messages.rejectedBefore(), - line: 2, - column: 1, - }, - { - code: '@media (max-width:600px) and (min-width :3em) {}', - fixed: '@media (max-width:600px) and (min-width:3em) {}', - message: messages.rejectedBefore(), - line: 1, - column: 41, - }, - { - code: '@media (max-width :600px) and (min-width:3em) {}', - fixed: '@media (max-width:600px) and (min-width:3em) {}', - message: messages.rejectedBefore(), - line: 1, - column: 19, - }, - { - code: '@media (max-width :600px) and (min-width :3em) {}', - fixed: '@media (max-width:600px) and (min-width:3em) {}', - warnings: [ - { - message: messages.rejectedBefore(), - line: 1, - column: 19, - }, - { - message: messages.rejectedBefore(), - line: 1, - column: 42, - }, - ], - }, - { - code: '@media (max-width /*comment*/ :600px) {}', - fixed: '@media (max-width /*comment*/:600px) {}', - message: messages.rejectedBefore(), - line: 1, - column: 31, - }, - ], -}); diff --git a/lib/rules/media-feature-colon-space-before/index.js b/lib/rules/media-feature-colon-space-before/index.js deleted file mode 100644 index 4bdc41b999..0000000000 --- a/lib/rules/media-feature-colon-space-before/index.js +++ /dev/null @@ -1,87 +0,0 @@ -'use strict'; - -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const mediaFeatureColonSpaceChecker = require('../mediaFeatureColonSpaceChecker'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'media-feature-colon-space-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected single space before ":"', - rejectedBefore: () => 'Unexpected whitespace before ":"', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/media-feature-colon-space-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - /** @type {Map | undefined} */ - let fixData; - - mediaFeatureColonSpaceChecker({ - root, - result, - locationChecker: checker.before, - checkedRuleName: ruleName, - fix: context.fix - ? (atRule, index) => { - const paramColonIndex = index - atRuleParamIndex(atRule); - - fixData = fixData || new Map(); - const colonIndices = fixData.get(atRule) || []; - - colonIndices.push(paramColonIndex); - fixData.set(atRule, colonIndices); - - return true; - } - : null, - }); - - if (fixData) { - for (const [atRule, colonIndices] of fixData.entries()) { - let params = atRule.raws.params ? atRule.raws.params.raw : atRule.params; - - for (const index of colonIndices.sort((a, b) => b - a)) { - const beforeColon = params.slice(0, index); - const afterColon = params.slice(index); - - if (primary === 'always') { - params = beforeColon.replace(/\s*$/, ' ') + afterColon; - } else if (primary === 'never') { - params = beforeColon.replace(/\s*$/, '') + afterColon; - } - } - - if (atRule.raws.params) { - atRule.raws.params.raw = params; - } else { - atRule.params = params; - } - } - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/media-feature-name-case/README.md b/lib/rules/media-feature-name-case/README.md deleted file mode 100644 index 256698bf55..0000000000 --- a/lib/rules/media-feature-name-case/README.md +++ /dev/null @@ -1,110 +0,0 @@ -# media-feature-name-case - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Specify lowercase or uppercase for media feature names. - - -```css -@media (min-width: 700px) {} -/** ↑ - * This media feature name */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"lower"|"upper"` - -### `"lower"` - -The following patterns are considered problems: - - -```css -@media (MIN-WIDTH: 700px) {} -``` - - -```css -@media not all and (MONOCHROME) {} -``` - - -```css -@media (min-width: 700px) and (ORIENTATION: landscape) {} -``` - - -```css -@media (WIDTH > 10em) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media (min-width: 700px) {} -``` - - -```css -@media not all and (monochrome) {} -``` - - -```css -@media (min-width: 700px) and (orientation: landscape) {} -``` - - -```css -@media (width > 10em) {} -``` - -### `"upper"` - -The following patterns are considered problems: - - -```css -@media (min-width: 700px) {} -``` - - -```css -@media not all and (monochrome) {} -``` - - -```css -@media (MIN-WIDTH: 700px) and (orientation: landscape) {} -``` - - -```css -@media (10em < width <= 50em) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media (MIN-WIDTH: 700px) {} -``` - - -```css -@media not all and (MONOCHROME) {} -``` - - -```css -@media (MIN-WIDTH: 700px) and (ORIENTATION: landscape) {} -``` - - -```css -@media (10em < WIDTH <= 50em) {} -``` diff --git a/lib/rules/media-feature-name-case/__tests__/index.js b/lib/rules/media-feature-name-case/__tests__/index.js deleted file mode 100644 index dcea6fc7c1..0000000000 --- a/lib/rules/media-feature-name-case/__tests__/index.js +++ /dev/null @@ -1,656 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['lower'], - fix: true, - - accept: [ - { - code: '@media not all and (monochrome) { }', - }, - { - code: '@media (min-width: 700px) { }', - }, - { - code: '@media (min-width: 700PX) { }', - }, - { - code: '@media (width < 100px) { }', - }, - { - code: '@media (width = 100px) { }', - }, - { - code: '@media (width <= 100px) { }', - }, - { - code: '@media (10px <= width <= 100px) { }', - }, - { - code: '@media (min-width: 700px) and (orientation: landscape) { }', - }, - { - code: '@media (min-width: 700px) /* comments */ and (orientation: landscape) {}', - }, - { - code: '@media /* comments */ (min-width: 700px) and (orientation: landscape) {}', - }, - { - code: '@media (min-width: 700px), print and (orientation: landscape) { }', - }, - { - code: '@media (min-width: 700px), PRINT and (orientation: landscape) { }', - }, - { - code: '@media (-webkit-min-device-pixel-ratio: 2) { }', - }, - { - code: '@not-media (MIN-WIDTH: 700px) { }', - description: 'ignore non media at-rule', - }, - { - code: '@media (--viewport-medium) { }', - description: 'ignore css variables', - }, - { - code: '@media (--VIEWPORT-MEDIUM) { }', - description: 'ignore css variables', - }, - ], - - reject: [ - { - code: '@media not all and (MONOCHROME) { }', - fixed: '@media not all and (monochrome) { }', - message: messages.expected('MONOCHROME', 'monochrome'), - line: 1, - column: 21, - endLine: 1, - endColumn: 31, - }, - { - code: '@media not all and (mOnOcHrOmE) { }', - fixed: '@media not all and (monochrome) { }', - message: messages.expected('mOnOcHrOmE', 'monochrome'), - line: 1, - column: 21, - endLine: 1, - endColumn: 31, - }, - { - code: '@media (MIN-WIDTH: 700px) { }', - fixed: '@media (min-width: 700px) { }', - message: messages.expected('MIN-WIDTH', 'min-width'), - line: 1, - column: 9, - endLine: 1, - endColumn: 18, - }, - { - code: '@media (mIn-WiDtH: 700px) { }', - fixed: '@media (min-width: 700px) { }', - message: messages.expected('mIn-WiDtH', 'min-width'), - line: 1, - column: 9, - endLine: 1, - endColumn: 18, - }, - { - code: '@media (MIN-WIDTH: 700px) and (orientation: landscape) { }', - fixed: '@media (min-width: 700px) and (orientation: landscape) { }', - message: messages.expected('MIN-WIDTH', 'min-width'), - line: 1, - column: 9, - endLine: 1, - endColumn: 18, - }, - { - code: '@media (min-width: 700px) and (ORIENTATION: landscape) { }', - fixed: '@media (min-width: 700px) and (orientation: landscape) { }', - message: messages.expected('ORIENTATION', 'orientation'), - line: 1, - column: 32, - endLine: 1, - endColumn: 43, - }, - { - code: '@media (min-width: 700px) /* comments */ and (ORIENTATION: landscape) {}', - fixed: '@media (min-width: 700px) /* comments */ and (orientation: landscape) {}', - message: messages.expected('ORIENTATION', 'orientation'), - line: 1, - column: 47, - endLine: 1, - endColumn: 58, - }, - { - code: '@media /* comments */ (MIN-WIDTH: 700px) and (orientation: landscape) {}', - fixed: '@media /* comments */ (min-width: 700px) and (orientation: landscape) {}', - message: messages.expected('MIN-WIDTH', 'min-width'), - line: 1, - column: 24, - endLine: 1, - endColumn: 33, - }, - { - code: '@media (-WEBKIT-MIN-DEVICE-PIXEL-RATION: 2) { }', - fixed: '@media (-webkit-min-device-pixel-ration: 2) { }', - message: messages.expected( - '-WEBKIT-MIN-DEVICE-PIXEL-RATION', - '-webkit-min-device-pixel-ration', - ), - line: 1, - column: 9, - endLine: 1, - endColumn: 40, - }, - { - code: '@media (height: 50em) and (orientation: landscape) and (WIDTH: 25em) {}', - fixed: '@media (height: 50em) and (orientation: landscape) and (width: 25em) {}', - message: messages.expected('WIDTH', 'width'), - line: 1, - column: 57, - endLine: 1, - endColumn: 62, - }, - { - code: '@media (WIDTH > 50em) {}', - fixed: '@media (width > 50em) {}', - message: messages.expected('WIDTH', 'width'), - line: 1, - column: 9, - endLine: 1, - endColumn: 14, - }, - { - code: '@media (10em < WIDTH <= 50em) {}', - fixed: '@media (10em < width <= 50em) {}', - message: messages.expected('WIDTH', 'width'), - line: 1, - column: 16, - endLine: 1, - endColumn: 21, - }, - { - code: '@media (width > 10em) and (WIDTH < 50em) {}', - fixed: '@media (width > 10em) and (width < 50em) {}', - message: messages.expected('WIDTH', 'width'), - line: 1, - column: 28, - endLine: 1, - endColumn: 33, - }, - { - code: '@media (10em < WIDTH) {}', - fixed: '@media (10em < width) {}', - message: messages.expected('WIDTH', 'width'), - line: 1, - column: 16, - endLine: 1, - endColumn: 21, - }, - { - code: '@media not all and (\\MONOCHROME) {}', - fixed: '@media not all and (monochrome) {}', - message: messages.expected('MONOCHROME', 'monochrome'), - line: 1, - column: 21, - endLine: 1, - endColumn: 32, - }, - { - code: '@media not all and (\\@MONOCHROME) {}', - fixed: '@media not all and (\\40 monochrome) {}', - message: messages.expected('@MONOCHROME', '@monochrome'), - line: 1, - column: 21, - endLine: 1, - endColumn: 33, - }, - { - code: '@media not all and (\\40MONOCHROME) {}', - fixed: '@media not all and (\\40 monochrome) {}', - message: messages.expected('@MONOCHROME', '@monochrome'), - line: 1, - column: 21, - endLine: 1, - endColumn: 34, - }, - ], -}); - -testRule({ - ruleName, - config: ['lower'], - customSyntax: 'postcss-less', - fix: true, - - accept: [ - { - code: '@media (min-width: @tablet) { }', - }, - { - code: '@media (min-width: (@value + 10px)) { }', - }, - { - code: '@media @smartphones and (orientation: landscape) { }', - }, - { - code: '@media @smartphones { }', - }, - { - code: '@media @smartphones /* comments */ and (orientation: landscape) {}', - }, - ], - - reject: [ - { - code: '@media (MIN-WIDTH: @tablet) { }', - fixed: '@media (min-width: @tablet) { }', - message: messages.expected('MIN-WIDTH', 'min-width'), - line: 1, - column: 9, - }, - { - code: '@media (MIN-WIDTH: (@value + 10px)) { }', - fixed: '@media (min-width: (@value + 10px)) { }', - message: messages.expected('MIN-WIDTH', 'min-width'), - line: 1, - column: 9, - }, - { - code: '@media @smartphones and (ORIENTATION: landscape) { }', - fixed: '@media @smartphones and (orientation: landscape) { }', - message: messages.expected('ORIENTATION', 'orientation'), - line: 1, - column: 26, - }, - { - code: '@media @smartphones /* comments */ and (ORIENTATION: landscape) {}', - fixed: '@media @smartphones /* comments */ and (orientation: landscape) {}', - message: messages.expected('ORIENTATION', 'orientation'), - line: 1, - column: 41, - }, - ], -}); - -testRule({ - ruleName, - config: ['lower'], - customSyntax: 'postcss-scss', - fix: true, - - accept: [ - { - code: '@media not all and ($monochrome) { }', - }, - { - code: '@media not all and ($MONOCHROME) { }', - }, - { - code: '@media not all and (#{$monochrome}) { }', - }, - { - code: '@media not all and (#{$MONOCHROME}) { }', - }, - { - code: '@media not all /* comments */ and (#{$MONOCHROME}) { }', - }, - { - code: '@media (min-width: $var) { }', - }, - { - code: '@media (min-width: $var + 10px) { }', - }, - { - code: '@media (min-width: ($var + 10px)) { }', - }, - { - 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} { }', - }, - ], - - reject: [ - { - code: '@media (MIN-WIDTH: $var) { }', - fixed: '@media (min-width: $var) { }', - message: messages.expected('MIN-WIDTH', 'min-width'), - line: 1, - column: 9, - }, - { - code: '@media (MIN-WIDTH: $var + 10px) { }', - fixed: '@media (min-width: $var + 10px) { }', - message: messages.expected('MIN-WIDTH', 'min-width'), - line: 1, - column: 9, - }, - { - code: '@media (MIN-WIDTH: ($var + 10px)) { }', - fixed: '@media (min-width: ($var + 10px)) { }', - message: messages.expected('MIN-WIDTH', 'min-width'), - line: 1, - column: 9, - }, - { - code: '@media (MIN-WIDTH: ($var + 10px)) and /* comments */ (#{$MONOCHROME}) { }', - fixed: '@media (min-width: ($var + 10px)) and /* comments */ (#{$MONOCHROME}) { }', - message: messages.expected('MIN-WIDTH', 'min-width'), - line: 1, - column: 9, - }, - ], -}); - -testRule({ - ruleName, - config: ['upper'], - fix: true, - - accept: [ - { - code: '@media not all and (MONOCHROME) { }', - }, - { - code: '@media (MIN-WIDTH: 700px) { }', - }, - { - code: '@media (MIN-WIDTH: 700PX) { }', - }, - { - code: '@media (MIN-WIDTH: 700px) and (ORIENTATION: landscape) { }', - }, - { - code: '@media (MIN-WIDTH: 700px), print and (ORIENTATION: landscape) { }', - }, - { - code: '@media (MIN-WIDTH: 700px), PRINT and (ORIENTATION: landscape) { }', - }, - { - code: '@media (MIN-WIDTH: 700px), PRINT and /* comments */ (ORIENTATION: landscape) { }', - }, - { - code: '@media (MIN-WIDTH: 700px), /* comments */ PRINT and (ORIENTATION: landscape) { }', - }, - { - code: '@media (-WEBKIT-MIN-DEVICE-PIXEL-RATION: 2) { }', - }, - { - code: '@not-media (min-width: 700px) { }', - description: 'ignore non media at-rule', - }, - { - code: '@media (--viewport-medium) { }', - description: 'ignore css variables', - }, - { - code: '@media (--VIEWPORT-MEDIUM) { }', - description: 'ignore css variables', - }, - ], - - reject: [ - { - code: '@media not all and (monochrome) { }', - fixed: '@media not all and (MONOCHROME) { }', - message: messages.expected('monochrome', 'MONOCHROME'), - line: 1, - column: 21, - }, - { - code: '@media not all and (mOnOcHrOmE) { }', - fixed: '@media not all and (MONOCHROME) { }', - message: messages.expected('mOnOcHrOmE', 'MONOCHROME'), - line: 1, - column: 21, - }, - { - code: '@media (min-width: 700px) { }', - fixed: '@media (MIN-WIDTH: 700px) { }', - message: messages.expected('min-width', 'MIN-WIDTH'), - line: 1, - column: 9, - }, - { - code: '@media (mIn-WiDtH: 700px) { }', - fixed: '@media (MIN-WIDTH: 700px) { }', - message: messages.expected('mIn-WiDtH', 'MIN-WIDTH'), - line: 1, - column: 9, - }, - { - code: '@media (min-width: 700px) and (ORIENTATION: landscape) { }', - fixed: '@media (MIN-WIDTH: 700px) and (ORIENTATION: landscape) { }', - message: messages.expected('min-width', 'MIN-WIDTH'), - line: 1, - column: 9, - }, - { - code: '@media (min-width: 700px), PRINT and /* comments */ (ORIENTATION: landscape) { }', - fixed: '@media (MIN-WIDTH: 700px), PRINT and /* comments */ (ORIENTATION: landscape) { }', - message: messages.expected('min-width', 'MIN-WIDTH'), - line: 1, - column: 9, - }, - { - code: '@media (MIN-WIDTH: 700px), /* comments */ PRINT and (orientation: landscape) { }', - fixed: '@media (MIN-WIDTH: 700px), /* comments */ PRINT and (ORIENTATION: landscape) { }', - message: messages.expected('orientation', 'ORIENTATION'), - line: 1, - column: 54, - }, - { - code: '@media (MIN-WIDTH: 700px) and (orientation: landscape) { }', - fixed: '@media (MIN-WIDTH: 700px) and (ORIENTATION: landscape) { }', - message: messages.expected('orientation', 'ORIENTATION'), - line: 1, - column: 32, - }, - { - code: '@media (-webkit-min-device-pixel-ration: 2) { }', - fixed: '@media (-WEBKIT-MIN-DEVICE-PIXEL-RATION: 2) { }', - message: messages.expected( - '-webkit-min-device-pixel-ration', - '-WEBKIT-MIN-DEVICE-PIXEL-RATION', - ), - line: 1, - column: 9, - }, - ], -}); - -testRule({ - ruleName, - config: ['upper'], - customSyntax: 'postcss-less', - fix: true, - - accept: [ - { - code: '@media (MIN-WIDTH: @tablet) { }', - }, - { - code: '@media (MIN-WIDTH: (@value + 10px)) { }', - }, - { - code: '@media @smartphones and (ORIENTATION: landscape) { }', - }, - { - code: '@media @smartphones /* comments */ and (ORIENTATION: landscape) { }', - }, - { - code: '@media @smartphones { }', - }, - ], - - reject: [ - { - code: '@media (min-width: @tablet) { }', - fixed: '@media (MIN-WIDTH: @tablet) { }', - message: messages.expected('min-width', 'MIN-WIDTH'), - line: 1, - column: 9, - }, - { - code: '@media (min-width: (@value + 10px)) { }', - fixed: '@media (MIN-WIDTH: (@value + 10px)) { }', - message: messages.expected('min-width', 'MIN-WIDTH'), - line: 1, - column: 9, - }, - { - code: '@media @smartphones and (orientation: landscape) { }', - fixed: '@media @smartphones and (ORIENTATION: landscape) { }', - message: messages.expected('orientation', 'ORIENTATION'), - line: 1, - column: 26, - }, - { - code: '@media @smartphones /* comments */ and (orientation: landscape) { }', - fixed: '@media @smartphones /* comments */ and (ORIENTATION: landscape) { }', - message: messages.expected('orientation', 'ORIENTATION'), - line: 1, - column: 41, - }, - { - code: '@media @@smartphones /* comments */ and (orientation: landscape) { }', - fixed: '@media @@smartphones /* comments */ and (ORIENTATION: landscape) { }', - message: messages.expected('orientation', 'ORIENTATION'), - line: 1, - column: 42, - endLine: 1, - endColumn: 53, - }, - ], -}); - -testRule({ - ruleName, - config: ['upper'], - customSyntax: 'postcss-scss', - fix: true, - - accept: [ - { - code: '@media not all and ($monochrome) { }', - }, - { - code: '@media not all and ($MONOCHROME) { }', - }, - { - code: '@media not all and (#{$monochrome}) { }', - }, - { - code: '@media not all and (#{$MONOCHROME}) { }', - }, - { - code: '@media not all and /* comments */ (#{$MONOCHROME}) { }', - }, - { - code: '@media (MIN-WIDTH: $var) { }', - }, - { - code: '@media (MIN-WIDTH: $var + 10px) { }', - }, - { - code: '@media (MIN-WIDTH: ($var + 10px)) { }', - }, - { - 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} { }', - }, - ], - - reject: [ - { - code: '@media (min-width: $var) { }', - fixed: '@media (MIN-WIDTH: $var) { }', - message: messages.expected('min-width', 'MIN-WIDTH'), - line: 1, - column: 9, - }, - { - code: '@media (min-width: $var + 10px) { }', - fixed: '@media (MIN-WIDTH: $var + 10px) { }', - message: messages.expected('min-width', 'MIN-WIDTH'), - line: 1, - column: 9, - }, - { - code: '@media (min-width: ($var + 10px)) { }', - fixed: '@media (MIN-WIDTH: ($var + 10px)) { }', - message: messages.expected('min-width', 'MIN-WIDTH'), - line: 1, - column: 9, - }, - { - code: '@media (MIN-WIDTH: ($var + 10px)) and /* comments */ (orientation: landscape){ }', - fixed: '@media (MIN-WIDTH: ($var + 10px)) and /* comments */ (ORIENTATION: landscape){ }', - message: messages.expected('orientation', 'ORIENTATION'), - line: 1, - column: 55, - }, - ], -}); diff --git a/lib/rules/media-feature-name-case/index.js b/lib/rules/media-feature-name-case/index.js deleted file mode 100644 index b2befcca1d..0000000000 --- a/lib/rules/media-feature-name-case/index.js +++ /dev/null @@ -1,93 +0,0 @@ -'use strict'; - -const { mutateIdent } = require('@csstools/css-tokenizer'); - -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const findMediaFeatureNames = require('../../utils/findMediaFeatureNames'); -const isCustomMediaQuery = require('../../utils/isCustomMediaQuery'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'media-feature-name-case'; - -const messages = ruleMessages(ruleName, { - expected: (actual, expected) => `Expected "${actual}" to be "${expected}"`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/media-feature-name-case', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['lower', 'upper'], - }); - - if (!validOptions) { - return; - } - - root.walkAtRules(/^media$/i, (atRule) => { - let hasComments = atRule.raws.params?.raw; - let mediaRule = hasComments ? hasComments : atRule.params; - - let hasFixes = false; - - mediaRule = findMediaFeatureNames(mediaRule, (mediaFeatureNameToken) => { - const [, , startIndex, endIndex, { value: featureName }] = mediaFeatureNameToken; - - if (isCustomMediaQuery(featureName)) { - return; - } - - const expectedFeatureName = - primary === 'lower' ? featureName.toLowerCase() : featureName.toUpperCase(); - - if (featureName === expectedFeatureName) { - return; - } - - if (context.fix) { - mutateIdent(mediaFeatureNameToken, expectedFeatureName); - hasFixes = true; - - return; - } - - const atRuleIndex = atRuleParamIndex(atRule); - - report({ - message: messages.expected(featureName, expectedFeatureName), - node: atRule, - index: atRuleIndex + startIndex, - endIndex: atRuleIndex + endIndex + 1, - ruleName, - result, - }); - }).stringify(); - - if (hasFixes) { - if (hasComments) { - if (atRule.raws.params == null) { - throw new Error('The `AtRuleRaws` node must have a `params` property'); - } - - atRule.raws.params.raw = mediaRule; - } else { - atRule.params = mediaRule; - } - } - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/media-feature-parentheses-space-inside/README.md b/lib/rules/media-feature-parentheses-space-inside/README.md deleted file mode 100644 index 2f00116012..0000000000 --- a/lib/rules/media-feature-parentheses-space-inside/README.md +++ /dev/null @@ -1,64 +0,0 @@ -# media-feature-parentheses-space-inside - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace on the inside of the parentheses within media features. - - -```css -@media ( max-width: 300px ) {} -/** ↑ ↑ - * The space inside these two parentheses */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a single space inside the parentheses. - -The following patterns are considered problems: - - -```css -@media (max-width: 300px) {} -``` - - -```css -@media (max-width: 300px ) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media ( max-width: 300px ) {} -``` - -### `"never"` - -There _must never_ be whitespace on the inside the parentheses. - -The following patterns are considered problems: - - -```css -@media ( max-width: 300px ) {} -``` - - -```css -@media ( max-width: 300px) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media (max-width: 300px) {} -``` diff --git a/lib/rules/media-feature-parentheses-space-inside/__tests__/index.js b/lib/rules/media-feature-parentheses-space-inside/__tests__/index.js deleted file mode 100644 index e297efb372..0000000000 --- a/lib/rules/media-feature-parentheses-space-inside/__tests__/index.js +++ /dev/null @@ -1,243 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - accept: [ - { - code: '@media ( max-width: 300px ) {}', - }, - { - code: '@mEdIa ( max-width: 300px ) {}', - }, - { - code: '@MEDIA ( max-width: 300px ) {}', - }, - { - code: '@media screen and ( color ), projection and ( color ) {}', - }, - { - code: '@media ( grid ) and ( max-width: 15em ) {}', - }, - { - code: '@media ( max-width: /*comment*/ ) {}', - }, - ], - - reject: [ - { - code: '@media (max-width: 300px ) {}', - fixed: '@media ( max-width: 300px ) {}', - message: messages.expectedOpening, - line: 1, - column: 9, - }, - { - code: '@mEdIa (max-width: 300px ) {}', - fixed: '@mEdIa ( max-width: 300px ) {}', - message: messages.expectedOpening, - line: 1, - column: 9, - }, - { - code: '@MEDIA (max-width: /*comment*/ ) {}', - fixed: '@MEDIA ( max-width: /*comment*/ ) {}', - message: messages.expectedOpening, - line: 1, - column: 9, - }, - { - code: '@MEDIA (max-width: 300px ) {}', - fixed: '@MEDIA ( max-width: 300px ) {}', - message: messages.expectedOpening, - line: 1, - column: 9, - }, - { - code: '@media ( max-width: 300px) {}', - fixed: '@media ( max-width: 300px ) {}', - message: messages.expectedClosing, - line: 1, - column: 25, - }, - { - code: '@media ( max-width: /*comment*/) {}', - fixed: '@media ( max-width: /*comment*/ ) {}', - message: messages.expectedClosing, - line: 1, - column: 31, - }, - { - code: '@media screen and (color ), projection and ( color ) {}', - fixed: '@media screen and ( color ), projection and ( color ) {}', - message: messages.expectedOpening, - line: 1, - column: 20, - }, - { - code: '@media screen and ( color), projection and ( color ) {}', - fixed: '@media screen and ( color ), projection and ( color ) {}', - message: messages.expectedClosing, - line: 1, - column: 25, - }, - { - code: '@media screen and ( color ), projection and (color ) {}', - fixed: '@media screen and ( color ), projection and ( color ) {}', - message: messages.expectedOpening, - line: 1, - column: 46, - }, - { - code: '@media screen and ( color ), projection and ( color) {}', - fixed: '@media screen and ( color ), projection and ( color ) {}', - message: messages.expectedClosing, - line: 1, - column: 51, - }, - { - code: '@media ( grid ) and (max-width: 15em ) {}', - fixed: '@media ( grid ) and ( max-width: 15em ) {}', - message: messages.expectedOpening, - line: 1, - column: 22, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - accept: [ - { - code: '@media (max-width: 300px) {}', - }, - { - code: '@mEdIa (max-width: 300px) {}', - }, - { - code: '@MEDIA (max-width: 300px) {}', - }, - { - code: '@MEDIA (max-width: /*comment*/) {}', - }, - { - code: '@media screen and (color), projection and (color) {}', - }, - { - code: '@media (grid) and (max-width: 15em) {}', - }, - ], - - reject: [ - { - code: '@media ( min-width: 700px) {}', - fixed: '@media (min-width: 700px) {}', - message: messages.rejectedOpening, - line: 1, - column: 9, - }, - { - code: '@media (min-width: 700px ) {}', - fixed: '@media (min-width: 700px) {}', - message: messages.rejectedClosing, - line: 1, - column: 26, - }, - { - code: '@media (\t min-width: 700px) {}', - fixed: '@media (min-width: 700px) {}', - message: messages.rejectedOpening, - line: 1, - column: 9, - }, - { - code: '@media (min-width: 700px\t) {}', - fixed: '@media (min-width: 700px) {}', - message: messages.rejectedClosing, - line: 1, - column: 25, - }, - { - code: '@media (max-width: 300px ) {}', - fixed: '@media (max-width: 300px) {}', - message: messages.rejectedClosing, - line: 1, - column: 25, - }, - { - code: '@mEdIa (max-width: 300px ) {}', - fixed: '@mEdIa (max-width: 300px) {}', - message: messages.rejectedClosing, - line: 1, - column: 25, - }, - { - code: '@MEDIA (max-width: /*comment*/ ) {}', - fixed: '@MEDIA (max-width: /*comment*/) {}', - message: messages.rejectedClosing, - line: 1, - column: 31, - }, - { - code: '@MEDIA (max-width: 300px ) {}', - fixed: '@MEDIA (max-width: 300px) {}', - message: messages.rejectedClosing, - line: 1, - column: 25, - }, - { - code: '@media ( max-width: 300px) {}', - fixed: '@media (max-width: 300px) {}', - message: messages.rejectedOpening, - line: 1, - column: 9, - }, - { - code: '@media ( max-width: /*comment*/) {}', - fixed: '@media (max-width: /*comment*/) {}', - message: messages.rejectedOpening, - line: 1, - column: 9, - }, - { - code: '@media screen and (color ), projection and (color) {}', - fixed: '@media screen and (color), projection and (color) {}', - message: messages.rejectedClosing, - line: 1, - column: 25, - }, - { - code: '@media screen and ( color), projection and (color) {}', - fixed: '@media screen and (color), projection and (color) {}', - message: messages.rejectedOpening, - line: 1, - column: 20, - }, - { - code: '@media screen and (color), projection and (color ) {}', - fixed: '@media screen and (color), projection and (color) {}', - message: messages.rejectedClosing, - line: 1, - column: 49, - }, - { - code: '@media screen and (color), projection and ( color) {}', - fixed: '@media screen and (color), projection and (color) {}', - message: messages.rejectedOpening, - line: 1, - column: 44, - }, - { - code: '@media (grid) and (max-width: 15em ) {}', - fixed: '@media (grid) and (max-width: 15em) {}', - message: messages.rejectedClosing, - line: 1, - column: 35, - }, - ], -}); diff --git a/lib/rules/media-feature-parentheses-space-inside/index.js b/lib/rules/media-feature-parentheses-space-inside/index.js deleted file mode 100644 index 800823b8e9..0000000000 --- a/lib/rules/media-feature-parentheses-space-inside/index.js +++ /dev/null @@ -1,112 +0,0 @@ -'use strict'; - -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const valueParser = require('postcss-value-parser'); - -const ruleName = 'media-feature-parentheses-space-inside'; - -const messages = ruleMessages(ruleName, { - expectedOpening: 'Expected single space after "("', - rejectedOpening: 'Unexpected whitespace after "("', - expectedClosing: 'Expected single space before ")"', - rejectedClosing: 'Unexpected whitespace before ")"', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/media-feature-parentheses-space-inside', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - root.walkAtRules(/^media$/i, (atRule) => { - // If there are comments in the params, the complete string - // will be at atRule.raws.params.raw - const params = (atRule.raws.params && atRule.raws.params.raw) || atRule.params; - const indexBoost = atRuleParamIndex(atRule); - /** @type {Array<{ message: string, index: number }>} */ - const problems = []; - - const parsedParams = valueParser(params).walk((node) => { - if (node.type === 'function') { - const len = valueParser.stringify(node).length; - - if (primary === 'never') { - if (/[ \t]/.test(node.before)) { - if (context.fix) node.before = ''; - - problems.push({ - message: messages.rejectedOpening, - index: node.sourceIndex + 1 + indexBoost, - }); - } - - if (/[ \t]/.test(node.after)) { - if (context.fix) node.after = ''; - - problems.push({ - message: messages.rejectedClosing, - index: node.sourceIndex - 2 + len + indexBoost, - }); - } - } else if (primary === 'always') { - if (node.before === '') { - if (context.fix) node.before = ' '; - - problems.push({ - message: messages.expectedOpening, - index: node.sourceIndex + 1 + indexBoost, - }); - } - - if (node.after === '') { - if (context.fix) node.after = ' '; - - problems.push({ - message: messages.expectedClosing, - index: node.sourceIndex - 2 + len + indexBoost, - }); - } - } - } - }); - - if (problems.length) { - if (context.fix) { - atRule.params = parsedParams.toString(); - - return; - } - - for (const err of problems) { - report({ - message: err.message, - node: atRule, - index: err.index, - result, - ruleName, - }); - } - } - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/media-feature-range-operator-space-after/README.md b/lib/rules/media-feature-range-operator-space-after/README.md deleted file mode 100644 index ca72cb6e6f..0000000000 --- a/lib/rules/media-feature-range-operator-space-after/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# media-feature-range-operator-space-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace after the range operator in media features. - - -```css -@media (width >= 600px) {} -/** ↑ - * The space after this operator */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a single space after the range operator. - -The following patterns are considered problems: - - -```css -@media (width>=600px) {} -``` - - -```css -@media (width >=600px) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media (width>= 600px) {} -``` - - -```css -@media (width >= 600px) {} -``` - -### `"never"` - -There _must never_ be whitespace after the range operator. - -The following patterns are considered problems: - - -```css -@media (width>= 600px) {} -``` - - -```css -@media (width >= 600px) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media (width>=600px) {} -``` - - -```css -@media (width >=600px) {} -``` diff --git a/lib/rules/media-feature-range-operator-space-after/__tests__/index.js b/lib/rules/media-feature-range-operator-space-after/__tests__/index.js deleted file mode 100644 index ec00256fa1..0000000000 --- a/lib/rules/media-feature-range-operator-space-after/__tests__/index.js +++ /dev/null @@ -1,249 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: '@media (width= 600px) {}', - }, - { - code: '@mEdIa (width= 600px) {}', - }, - { - code: '@MEDIA (width= 600px) {}', - }, - { - code: '@media (width > 600px) {}', - }, - { - code: '@media (width>= 600px) and (width<= 3em) {}', - }, - { - code: '@media /*(width>=600px) and*/ (width <= 3em) {}', - }, - { - code: '@media (width >= 600px) /*and (width<3em)*/ {}', - }, - { - code: '@media (width >= /*>*/ 600px) {}', - }, - ], - - reject: [ - { - code: '@media (width<600px) {}', - fixed: '@media (width< 600px) {}', - message: messages.expectedAfter(), - line: 1, - column: 15, - }, - { - code: '@mEdIa (width<600px) {}', - fixed: '@mEdIa (width< 600px) {}', - message: messages.expectedAfter(), - line: 1, - column: 15, - }, - { - code: '@MEDIA (width<600px) {}', - fixed: '@MEDIA (width< 600px) {}', - message: messages.expectedAfter(), - line: 1, - column: 15, - }, - { - code: '@media (width<= 600px) {}', - fixed: '@media (width<= 600px) {}', - message: messages.expectedAfter(), - line: 1, - column: 16, - }, - { - code: '@media (width=\t600px) {}', - fixed: '@media (width= 600px) {}', - message: messages.expectedAfter(), - line: 1, - column: 15, - }, - { - code: '@media (width>\n600px) {}', - fixed: '@media (width> 600px) {}', - message: messages.expectedAfter(), - line: 1, - column: 15, - }, - { - code: '@media (width>\r\n600px) {}', - fixed: '@media (width> 600px) {}', - description: 'CRLF', - message: messages.expectedAfter(), - line: 1, - column: 15, - }, - { - code: '@media (width>=600px) and (width< 3em) {}', - fixed: '@media (width>= 600px) and (width< 3em) {}', - message: messages.expectedAfter(), - line: 1, - column: 16, - }, - { - code: '@media (width> 600px) and (width=3em) {}', - fixed: '@media (width> 600px) and (width= 3em) {}', - message: messages.expectedAfter(), - line: 1, - column: 34, - }, - { - code: '@media (width>=600px) and (width<3em) {}', - fixed: '@media (width>= 600px) and (width< 3em) {}', - warnings: [ - { - message: messages.expectedAfter(), - line: 1, - column: 16, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 34, - }, - ], - }, - { - code: '@media (width600px) {}', - }, - { - code: '@media (width >=600px) and (width <=3em) {}', - }, - { - code: '@media /*(width >= 600px) and*/ (width<=3em) {}', - }, - { - code: '@media (width>=600px) /*and (width < 3em)*/ {}', - }, - { - code: '@media (width>=/* > */ 600px) {}', - }, - ], - - reject: [ - { - code: '@media (width < 600px) {}', - fixed: '@media (width <600px) {}', - message: messages.rejectedAfter(), - line: 1, - column: 16, - }, - { - code: '@mEdIa (width < 600px) {}', - fixed: '@mEdIa (width <600px) {}', - message: messages.rejectedAfter(), - line: 1, - column: 16, - }, - { - code: '@MEDIA (width < 600px) {}', - fixed: '@MEDIA (width <600px) {}', - message: messages.rejectedAfter(), - line: 1, - column: 16, - }, - { - code: '@media (width <= 600px) {}', - fixed: '@media (width <=600px) {}', - message: messages.rejectedAfter(), - line: 1, - column: 17, - }, - { - code: '@media (width =\t600px) {}', - fixed: '@media (width =600px) {}', - message: messages.rejectedAfter(), - line: 1, - column: 16, - }, - { - code: '@media (width >\n600px) {}', - fixed: '@media (width >600px) {}', - message: messages.rejectedAfter(), - line: 1, - column: 16, - }, - { - code: '@media (width >\r\n600px) {}', - fixed: '@media (width >600px) {}', - description: 'CRLF', - message: messages.rejectedAfter(), - line: 1, - column: 16, - }, - { - code: '@media (width >= 600px) and (width <3em) {}', - fixed: '@media (width >=600px) and (width <3em) {}', - message: messages.rejectedAfter(), - line: 1, - column: 17, - }, - { - code: '@media (width >600px) and (width = 3em) {}', - fixed: '@media (width >600px) and (width =3em) {}', - message: messages.rejectedAfter(), - line: 1, - column: 35, - }, - { - code: '@media (width >= 600px) and (width < 3em) {}', - fixed: '@media (width >=600px) and (width <3em) {}', - warnings: [ - { - message: messages.rejectedAfter(), - line: 1, - column: 17, - }, - { - message: messages.rejectedAfter(), - line: 1, - column: 37, - }, - ], - }, - { - code: '@media (width = /**/ 600px) {}', - fixed: '@media (width =/**/ 600px) {}', - message: messages.rejectedAfter(), - line: 1, - column: 16, - }, - ], -}); diff --git a/lib/rules/media-feature-range-operator-space-after/index.js b/lib/rules/media-feature-range-operator-space-after/index.js deleted file mode 100644 index 95ba711619..0000000000 --- a/lib/rules/media-feature-range-operator-space-after/index.js +++ /dev/null @@ -1,104 +0,0 @@ -'use strict'; - -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const findMediaOperator = require('../findMediaOperator'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'media-feature-range-operator-space-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected single space after range operator', - rejectedAfter: () => 'Unexpected whitespace after range operator', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/media-feature-range-operator-space-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - root.walkAtRules(/^media$/i, (atRule) => { - /** @type {number[]} */ - const fixOperatorIndices = []; - /** @type {((index: number) => void) | null} */ - const fix = context.fix ? (index) => fixOperatorIndices.push(index) : null; - - findMediaOperator(atRule, (match, params, node) => { - checkAfterOperator(match, params, node, fix); - }); - - if (fixOperatorIndices.length) { - let params = atRule.raws.params ? atRule.raws.params.raw : atRule.params; - - for (const index of fixOperatorIndices.sort((a, b) => b - a)) { - const beforeOperator = params.slice(0, index + 1); - const afterOperator = params.slice(index + 1); - - if (primary === 'always') { - params = beforeOperator + afterOperator.replace(/^\s*/, ' '); - } else if (primary === 'never') { - params = beforeOperator + afterOperator.replace(/^\s*/, ''); - } - } - - if (atRule.raws.params) { - atRule.raws.params.raw = params; - } else { - atRule.params = params; - } - } - }); - - /** - * @param {import('style-search').StyleSearchMatch} match - * @param {string} params - * @param {import('postcss').AtRule} node - * @param {((index: number) => void) | null} fix - */ - function checkAfterOperator(match, params, node, fix) { - const endIndex = match.startIndex + match.target.length - 1; - - checker.after({ - source: params, - index: endIndex, - err: (m) => { - if (fix) { - fix(endIndex); - - return; - } - - report({ - message: m, - node, - index: endIndex + atRuleParamIndex(node) + 1, - result, - ruleName, - }); - }, - }); - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/media-feature-range-operator-space-before/README.md b/lib/rules/media-feature-range-operator-space-before/README.md deleted file mode 100644 index f2414b9990..0000000000 --- a/lib/rules/media-feature-range-operator-space-before/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# media-feature-range-operator-space-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace before the range operator in media features. - - -```css -@media (width >= 600px) {} -/** ↑ - * The space before this operator */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a single space before the range operator. - -The following patterns are considered problems: - - -```css -@media (width>=600px) {} -``` - - -```css -@media (width>= 600px) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media (width >=600px) {} -``` - - -```css -@media (width >= 600px) {} -``` - -### `"never"` - -There _must never_ be whitespace before the range operator. - -The following patterns are considered problems: - - -```css -@media (width >=600px) {} -``` - - -```css -@media (width >= 600px) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media (width>=600px) {} -``` - - -```css -@media (width>= 600px) {} -``` diff --git a/lib/rules/media-feature-range-operator-space-before/__tests__/index.js b/lib/rules/media-feature-range-operator-space-before/__tests__/index.js deleted file mode 100644 index bfd14e37b3..0000000000 --- a/lib/rules/media-feature-range-operator-space-before/__tests__/index.js +++ /dev/null @@ -1,249 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: '@media (width = 600px) {}', - }, - { - code: '@mEdIa (width = 600px) {}', - }, - { - code: '@MEDIA (width = 600px) {}', - }, - { - code: '@media (width >600px) {}', - }, - { - code: '@media (width >= 600px) and (width <= 3em) {}', - }, - { - code: '@media /*(width>=600px) and*/ (width <= 3em) {}', - }, - { - code: '@media (width >= 600px) /*and (width<=3em)*/ {}', - }, - { - code: '@media (width >= /*>*/ 600px) {}', - }, - ], - - reject: [ - { - code: '@media (width< 600px) {}', - fixed: '@media (width < 600px) {}', - message: messages.expectedBefore(), - line: 1, - column: 13, - }, - { - code: '@mEdIa (width< 600px) {}', - fixed: '@mEdIa (width < 600px) {}', - message: messages.expectedBefore(), - line: 1, - column: 13, - }, - { - code: '@MEDIA (width< 600px) {}', - fixed: '@MEDIA (width < 600px) {}', - message: messages.expectedBefore(), - line: 1, - column: 13, - }, - { - code: '@media (width <= 600px) {}', - fixed: '@media (width <= 600px) {}', - message: messages.expectedBefore(), - line: 1, - column: 15, - }, - { - code: '@media (width\t= 600px) {}', - fixed: '@media (width = 600px) {}', - message: messages.expectedBefore(), - line: 1, - column: 14, - }, - { - code: '@media (width\n> 600px) {}', - fixed: '@media (width > 600px) {}', - message: messages.expectedBefore(), - line: 1, - column: 14, - }, - { - code: '@media (width\r\n> 600px) {}', - fixed: '@media (width > 600px) {}', - description: 'CRLF', - message: messages.expectedBefore(), - line: 1, - column: 15, - }, - { - code: '@media (width>= 600px) and (width < 3em) {}', - fixed: '@media (width >= 600px) and (width < 3em) {}', - message: messages.expectedBefore(), - line: 1, - column: 13, - }, - { - code: '@media (width > 600px) and (width= 3em) {}', - fixed: '@media (width > 600px) and (width = 3em) {}', - message: messages.expectedBefore(), - line: 1, - column: 33, - }, - { - code: '@media (width> 600px) and (width= 3em) {}', - fixed: '@media (width > 600px) and (width = 3em) {}', - warnings: [ - { - message: messages.expectedBefore(), - line: 1, - column: 13, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 32, - }, - ], - }, - { - code: '@media (width/**/< 600px) {}', - fixed: '@media (width/**/ < 600px) {}', - message: messages.expectedBefore(), - line: 1, - column: 17, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: '@media (width= 600px) {}', - }, - { - code: '@mEdIa (width= 600px) {}', - }, - { - code: '@MEDIA (width= 600px) {}', - }, - { - code: '@media (width>600px) {}', - }, - { - code: '@media (width>= 600px) and (width<= 3em) {}', - }, - { - code: '@media /*(width >= 600px) and*/ (width<= 3em) {}', - }, - { - code: '@media (width>= 600px) /*and (width <= 3em)*/ {}', - }, - { - code: '@media (width>= /* > */ 600px) {}', - }, - ], - - reject: [ - { - code: '@media (width < 600px) {}', - fixed: '@media (width< 600px) {}', - message: messages.rejectedBefore(), - line: 1, - column: 14, - }, - { - code: '@mEdIa (width < 600px) {}', - fixed: '@mEdIa (width< 600px) {}', - message: messages.rejectedBefore(), - line: 1, - column: 14, - }, - { - code: '@MEDIA (width < 600px) {}', - fixed: '@MEDIA (width< 600px) {}', - message: messages.rejectedBefore(), - line: 1, - column: 14, - }, - { - code: '@media (width <= 600px) {}', - fixed: '@media (width<= 600px) {}', - message: messages.rejectedBefore(), - line: 1, - column: 15, - }, - { - code: '@media (width\t= 600px) {}', - fixed: '@media (width= 600px) {}', - message: messages.rejectedBefore(), - line: 1, - column: 14, - }, - { - code: '@media (width\n> 600px) {}', - fixed: '@media (width> 600px) {}', - message: messages.rejectedBefore(), - line: 1, - column: 14, - }, - { - code: '@media (width\r\n> 600px) {}', - fixed: '@media (width> 600px) {}', - description: 'CRLF', - message: messages.rejectedBefore(), - line: 1, - column: 15, - }, - { - code: '@media (width>= 600px) and (width < 3em) {}', - fixed: '@media (width>= 600px) and (width< 3em) {}', - message: messages.rejectedBefore(), - line: 1, - column: 34, - }, - { - code: '@media (width > 600px) and (width= 3em) {}', - fixed: '@media (width> 600px) and (width= 3em) {}', - message: messages.rejectedBefore(), - line: 1, - column: 14, - }, - { - code: '@media (width >= 600px) and (width < 3em) {}', - fixed: '@media (width>= 600px) and (width< 3em) {}', - warnings: [ - { - message: messages.rejectedBefore(), - line: 1, - column: 14, - }, - { - message: messages.rejectedBefore(), - line: 1, - column: 35, - }, - ], - }, - { - code: '@media (width /**/ = 600px) {}', - fixed: '@media (width /**/= 600px) {}', - message: messages.rejectedBefore(), - line: 1, - column: 19, - }, - ], -}); diff --git a/lib/rules/media-feature-range-operator-space-before/index.js b/lib/rules/media-feature-range-operator-space-before/index.js deleted file mode 100644 index 5ddcbfd9ca..0000000000 --- a/lib/rules/media-feature-range-operator-space-before/index.js +++ /dev/null @@ -1,104 +0,0 @@ -'use strict'; - -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const findMediaOperator = require('../findMediaOperator'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'media-feature-range-operator-space-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected single space before range operator', - rejectedBefore: () => 'Unexpected whitespace before range operator', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/media-feature-range-operator-space-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - root.walkAtRules(/^media$/i, (atRule) => { - /** @type {number[]} */ - const fixOperatorIndices = []; - /** @type {((index: number) => void) | null} */ - const fix = context.fix ? (index) => fixOperatorIndices.push(index) : null; - - findMediaOperator(atRule, (match, params, node) => { - checkBeforeOperator(match, params, node, fix); - }); - - if (fixOperatorIndices.length) { - let params = atRule.raws.params ? atRule.raws.params.raw : atRule.params; - - for (const index of fixOperatorIndices.sort((a, b) => b - a)) { - const beforeOperator = params.slice(0, index); - const afterOperator = params.slice(index); - - if (primary === 'always') { - params = beforeOperator.replace(/\s*$/, ' ') + afterOperator; - } else if (primary === 'never') { - params = beforeOperator.replace(/\s*$/, '') + afterOperator; - } - } - - if (atRule.raws.params) { - atRule.raws.params.raw = params; - } else { - atRule.params = params; - } - } - }); - - /** - * @param {import('style-search').StyleSearchMatch} match - * @param {string} params - * @param {import('postcss').AtRule} node - * @param {((index: number) => void) | null} fix - */ - function checkBeforeOperator(match, params, node, fix) { - // The extra `+ 1` is because the match itself contains - // the character before the operator - checker.before({ - source: params, - index: match.startIndex, - err: (m) => { - if (fix) { - fix(match.startIndex); - - return; - } - - report({ - message: m, - node, - index: match.startIndex - 1 + atRuleParamIndex(node), - result, - ruleName, - }); - }, - }); - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/media-query-list-comma-newline-after/README.md b/lib/rules/media-query-list-comma-newline-after/README.md deleted file mode 100644 index 9fe500c348..0000000000 --- a/lib/rules/media-query-list-comma-newline-after/README.md +++ /dev/null @@ -1,115 +0,0 @@ -# media-query-list-comma-newline-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline or disallow whitespace after the commas of media query lists. - - -```css -@media screen and (color), - projection {} /* ↑ */ -/** ↑ - * These commas */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a newline after the commas. - -The following patterns are considered problems: - - -```css -@media screen and (color), projection and (color) {} -``` - - -```css -@media screen and (color) -, projection and (color) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media screen and (color), -projection and (color) {} -``` - - -```css -@media screen and (color) -, -projection and (color) {} -``` - -### `"always-multi-line"` - -There _must always_ be a newline after the commas in multi-line media query lists. - -The following patterns are considered problems: - - -```css -@media screen and (color) -, projection and (color) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media screen and (color), projection and (color) {} -``` - - -```css -@media screen and (color), -projection and (color) {} -``` - - -```css -@media screen and (color) -, -projection and (color) {} -``` - -### `"never-multi-line"` - -There _must never_ be whitespace after the commas in multi-line media query lists. - -The following patterns are considered problems: - - -```css -@media screen and (color), -projection and (color) {} -``` - - -```css -@media screen and (color) -, -projection and (color) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media screen and (color), projection and (color) {} -``` - - -```css -@media screen and (color) -,projection and (color) {} -``` diff --git a/lib/rules/media-query-list-comma-newline-after/__tests__/index.js b/lib/rules/media-query-list-comma-newline-after/__tests__/index.js deleted file mode 100644 index 0c75a81ed9..0000000000 --- a/lib/rules/media-query-list-comma-newline-after/__tests__/index.js +++ /dev/null @@ -1,458 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: '@import url(x.com?a=b,c=d)', - }, - { - code: '@media (max-width: 600px) {}', - }, - { - code: '@mEdIa (max-width: 600px) {}', - }, - { - code: '@MEDIA (max-width: 600px) {}', - }, - { - code: '@media screen and (color),\nprojection and (color) {}', - }, - { - code: '@media screen and (color),\n\nprojection and (color) {}', - }, - { - code: '@media screen and (color) ,\n projection and (color) {}', - }, - { - code: '@media screen and (color) ,\r\n projection and (color) {}', - description: 'CRLF', - }, - { - code: '@media screen and (color) ,\r\n\r\n projection and (color) {}', - description: 'CRLF', - }, - { - code: '@media screen and (color)\n,\n\t\t\tprojection and (color) {}', - description: 'indentation after the newline after the comma', - }, - { - code: '@media screen and (color)\r\n,\r\n\t\t\tprojection and (color) {}', - description: 'indentation after the CRLF after the comma', - }, - { - code: '@non-media screen and (color),projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - { - code: '@media-non screen and (color),projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - { - code: '@media screen and (color),/*comment*/\nprojection and (color) {}', - }, - { - code: '@media screen and (color), /*comment*/\nprojection and (color) {}', - }, - { - code: '@media screen and (color), /*comment1*/ /*comment2*/\nprojection and (color) {}', - }, - { - code: '@media screen and (color),/*comment*/\r\nprojection and (color) {}', - }, - { - code: '@media screen and (color), /*comment*/\r\nprojection and (color) {}', - }, - { - code: '@media screen and (color), /*comment1*/ /*com\r\nment2*/\r\nprojection and (color) {}', - }, - ], - - reject: [ - { - code: '@media screen and (color),projection and (color) {}', - fixed: '@media screen and (color),\nprojection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@mEdIa screen and (color),projection and (color) {}', - fixed: '@mEdIa screen and (color),\nprojection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@MEDIA screen and (color),projection and (color) {}', - fixed: '@MEDIA screen and (color),\nprojection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color), projection and (color) {}', - fixed: '@media screen and (color),\n projection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color), projection and (color) {}', - fixed: '@media screen and (color),\n projection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color),\tprojection and (color) {}', - fixed: '@media screen and (color),\n\tprojection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color), \n\tprojection and (color) {}', - fixed: '@media screen and (color),\n\tprojection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color),projection and (color) {\r\n}', - fixed: '@media screen and (color),\r\nprojection and (color) {\r\n}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color), \r\n\tprojection and (color) {}', - fixed: '@media screen and (color),\r\n\tprojection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color),/**/projection and (color) {}', - fixed: '@media screen and (color),/**/\nprojection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 30, - }, - { - code: '@media screen and (color),/**/ \nprojection and (color) {}', - fixed: '@media screen and (color),/**/\nprojection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 30, - }, - { - code: '@media screen and (color), /*comment1*/ /*comment2*/ projection and (color) {}', - fixed: '@media screen and (color), /*comment1*/ /*comment2*/\n projection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 52, - }, - { - code: '@media screen and (color),\t/*comment1*/\t/*comment2*/ \nprojection and (color) {}', - fixed: '@media screen and (color),\t/*comment1*/\t/*comment2*/\nprojection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 52, - }, - { - code: '@media screen and (color),\t \n/*comment*/\nprojection and (color) {}', - fixed: '@media screen and (color),\n/*comment*/\nprojection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media tv,tv,tv,print {}', - fixed: '@media tv,\ntv,\ntv,\nprint {}', - warnings: [ - { - message: messages.expectedAfter(), - line: 1, - column: 10, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 13, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 16, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: '@media screen and (color),\nprojection and (color) {}', - description: 'multi-line list, single-line block', - }, - { - code: '@mEdIa screen and (color),\nprojection and (color) {}', - description: 'multi-line list, single-line block', - }, - { - code: '@MEDIA screen and (color),\nprojection and (color) {}', - description: 'multi-line list, single-line block', - }, - { - code: '@media screen and (color),\r\nprojection and (color) {}', - description: 'multi-line list, single-line block and CRLF', - }, - { - code: '@media screen and (color),\nprojection and (color) {\n}', - description: 'multi-line list, multi-line block', - }, - { - code: '@media screen and (color),projection and (color) {}', - description: 'ignore single line list, single-lint block', - }, - { - code: '@media screen and (color),projection and (color) {\n}', - description: 'ignore single line list, multi-line block', - }, - { - code: '@media screen and (color),projection and (color) {\r\n}', - description: 'ignore single line list, multi-line block and CRLF', - }, - { - code: '@non-media screen and (color),projection and (color),\nprint {}', - description: 'ignore at-rules contain media in name', - }, - { - code: '@media-non screen and (color),projection and (color),\nprint {}', - description: 'ignore at-rules contain media in name', - }, - ], - - reject: [ - { - code: '@media screen and (color),projection and (color),\nprint {}', - fixed: '@media screen and (color),\nprojection and (color),\nprint {}', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 26, - }, - { - code: '@mEdIa screen and (color),projection and (color),\nprint {}', - fixed: '@mEdIa screen and (color),\nprojection and (color),\nprint {}', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 26, - }, - { - code: '@MEDIA screen and (color),projection and (color),\nprint {}', - fixed: '@MEDIA screen and (color),\nprojection and (color),\nprint {}', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color),projection and (color),\nprint {\n}', - fixed: '@media screen and (color),\nprojection and (color),\nprint {\n}', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color),projection and (color),\r\nprint {\r\n}', - fixed: '@media screen and (color),\r\nprojection and (color),\r\nprint {\r\n}', - description: 'CRLF', - message: messages.expectedAfterMultiLine(), - line: 1, - column: 26, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - fix: true, - - accept: [ - { - code: '@media screen and (color)\n,projection and (color) {}', - description: 'multi-line list, single-line block', - }, - { - code: '@mEdIa screen and (color)\n,projection and (color) {}', - description: 'multi-line list, single-line block', - }, - { - code: '@MEDIA screen and (color)\n,projection and (color) {}', - description: 'multi-line list, single-line block', - }, - { - code: '@media screen and (color)\r\n,projection and (color) {}', - description: 'multi-line list, single-line block and CRLF', - }, - { - code: '@media screen and (color)\n,projection and (color) {\n}', - description: 'multi-line list, multi-line block', - }, - { - code: '@media screen and (color)\r\n,projection and (color) {\r\n}', - description: 'multi-line list, multi-line block and CRLF', - }, - { - code: '@media screen and (color), projection and (color) {}', - description: 'ignore single line list, single-lint block', - }, - { - code: '@media screen and (color), projection and (color) {\n}', - description: 'ignore single line list, multi-line block', - }, - { - code: '@non-media screen and (color) ,projection and (color),\nprint {}', - description: 'ignore at-rules contain media in name', - }, - { - code: '@media-non screen and (color) ,projection and (color),\nprint {}', - description: 'ignore at-rules contain media in name', - }, - ], - - reject: [ - { - code: '@media screen and (color) ,projection and (color),\nprint {}', - fixed: '@media screen and (color) ,projection and (color),print {}', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 50, - }, - { - code: '@mEdIa screen and (color) ,projection and (color),\nprint {}', - fixed: '@mEdIa screen and (color) ,projection and (color),print {}', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 50, - }, - { - code: '@MEDIA screen and (color) ,projection and (color),\nprint {}', - fixed: '@MEDIA screen and (color) ,projection and (color),print {}', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 50, - }, - { - code: '@media screen and (color) ,projection and (color),\nprint {\n}', - fixed: '@media screen and (color) ,projection and (color),print {\n}', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 50, - }, - { - code: '@media screen and (color) ,projection and (color),\r\nprint {\r\n}', - fixed: '@media screen and (color) ,projection and (color),print {\r\n}', - description: 'CRLF', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 50, - }, - { - code: '@media screen and (color),\t\n projection and (color) {}', - fixed: '@media screen and (color),projection and (color) {}', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color),\t\r\n projection and (color) {}', - fixed: '@media screen and (color),projection and (color) {}', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color),\n/**/\nprojection and (color) {}', - fixed: '@media screen and (color),/**/\nprojection and (color) {}', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color), /*comment1*/\n/*comment2*/\nprojection and (color) {}', - fixed: '@media screen and (color),/*comment1*/\n/*comment2*/\nprojection and (color) {}', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 26, - }, - { - code: '@media tv,\ntv,\ntv,\nprint {\n}', - fixed: '@media tv,tv,tv,print {\n}', - warnings: [ - { - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 10, - }, - { - message: messages.rejectedAfterMultiLine(), - line: 2, - column: 3, - }, - { - message: messages.rejectedAfterMultiLine(), - line: 3, - column: 3, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-scss', - config: ['always'], - - accept: [ - { - code: '@media screen and (color),// scss\n projection and (color) {}', - }, - { - code: '@media screen and (color),\t // scss\n projection and (color) {}', - }, - { - code: '@media screen and (color),\n// scss\n projection and (color) {}', - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-less', - config: ['always'], - - accept: [ - { - code: '@media screen and (color),// less\n projection and (color) {}', - }, - { - code: '@media screen and (color),\t // less\r\n projection and (color) {}', - }, - { - code: '@media screen and (color),\n// less\n projection and (color) {}', - }, - ], -}); diff --git a/lib/rules/media-query-list-comma-newline-after/index.js b/lib/rules/media-query-list-comma-newline-after/index.js deleted file mode 100644 index c9c8dcdcb9..0000000000 --- a/lib/rules/media-query-list-comma-newline-after/index.js +++ /dev/null @@ -1,93 +0,0 @@ -'use strict'; - -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const mediaQueryListCommaWhitespaceChecker = require('../mediaQueryListCommaWhitespaceChecker'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'media-query-list-comma-newline-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected newline after ","', - expectedAfterMultiLine: () => 'Expected newline after "," in a multi-line list', - rejectedAfterMultiLine: () => 'Unexpected whitespace after "," in a multi-line list', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/media-query-list-comma-newline-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('newline', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'always-multi-line', 'never-multi-line'], - }); - - if (!validOptions) { - return; - } - - // Only check for the newline after the comma, while allowing - // arbitrary indentation after the newline - /** @type {Map | undefined} */ - let fixData; - - mediaQueryListCommaWhitespaceChecker({ - root, - result, - locationChecker: checker.afterOneOnly, - checkedRuleName: ruleName, - allowTrailingComments: primary.startsWith('always'), - fix: context.fix - ? (atRule, index) => { - const paramCommaIndex = index - atRuleParamIndex(atRule); - - fixData = fixData || new Map(); - const commaIndices = fixData.get(atRule) || []; - - commaIndices.push(paramCommaIndex); - fixData.set(atRule, commaIndices); - - return true; - } - : null, - }); - - if (fixData) { - for (const [atRule, commaIndices] of fixData.entries()) { - let params = atRule.raws.params ? atRule.raws.params.raw : atRule.params; - - for (const index of commaIndices.sort((a, b) => b - a)) { - const beforeComma = params.slice(0, index + 1); - const afterComma = params.slice(index + 1); - - if (primary.startsWith('always')) { - params = /^\s*\n/.test(afterComma) - ? beforeComma + afterComma.replace(/^[^\S\r\n]*/, '') - : beforeComma + context.newline + afterComma; - } else if (primary.startsWith('never')) { - params = beforeComma + afterComma.replace(/^\s*/, ''); - } - } - - if (atRule.raws.params) { - atRule.raws.params.raw = params; - } else { - atRule.params = params; - } - } - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/media-query-list-comma-newline-before/README.md b/lib/rules/media-query-list-comma-newline-before/README.md deleted file mode 100644 index 8b500a180a..0000000000 --- a/lib/rules/media-query-list-comma-newline-before/README.md +++ /dev/null @@ -1,113 +0,0 @@ -# media-query-list-comma-newline-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline or disallow whitespace before the commas of media query lists. - - -```css - @media screen and (color) - , projection and (color) {} -/** ↑ - * This comma */ -``` - -## Options - -`string`: `"always"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a newline before the commas. - -The following patterns are considered problems: - - -```css -@media screen and (color), projection and (color) {} -``` - - -```css -@media screen and (color), -projection and (color) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media screen and (color) -,projection and (color) {} -``` - - -```css -@media screen and (color) -, -projection and (color) {} -``` - -### `"always-multi-line"` - -There _must always_ be a newline before the commas in multi-line media query lists. - -The following patterns are considered problems: - - -```css -@media screen and (color), -projection and (color) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media screen and (color), projection and (color) {} -``` - - -```css -@media screen and (color) -,projection and (color) {} -``` - - -```css -@media screen and (color) -, -projection and (color) {} -``` - -### `"never-multi-line"` - -There _must never_ be whitespace before the commas in multi-line media query lists. - -The following patterns are considered problems: - - -```css -@media screen and (color) -,projection and (color) {} -``` - - -```css -@media screen and (color) -, -projection and (color) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media screen and (color), projection and (color) {} -``` - - -```css -@media screen and (color), -projection and (color) {} -``` diff --git a/lib/rules/media-query-list-comma-newline-before/__tests__/index.js b/lib/rules/media-query-list-comma-newline-before/__tests__/index.js deleted file mode 100644 index 9e62db7564..0000000000 --- a/lib/rules/media-query-list-comma-newline-before/__tests__/index.js +++ /dev/null @@ -1,248 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - - accept: [ - { - code: '@import url(x.com?a=b,c=d)', - }, - { - code: '@media (max-width: 600px) {}', - }, - { - code: '@mEdIa (max-width: 600px) {}', - }, - { - code: '@MEDIA (max-width: 600px) {}', - }, - { - code: '@media screen and (color)\n, projection and (color) {}', - }, - { - code: '@media screen and (color)\n\n, projection and (color) {}', - }, - { - code: '@media screen and (color)\r\n, projection and (color) {}', - description: 'CRLF', - }, - { - code: '@media screen and (color)\r\n\r\n, projection and (color) {}', - description: 'CRLF', - }, - { - code: '@media screen and (color)\n , projection and (color) {}', - }, - { - code: '@media screen and (color)\n\t\t,\nprojection and (color) {}', - description: 'indentation after the newline before the comma', - }, - { - code: '@media screen and (color)\r\n\t\t,\r\nprojection and (color) {}', - description: 'indentation after the CRLF before the comma', - }, - { - code: '@media screen and (color)\n\n, projection and (color)', - }, - { - code: '@non-media screen and (color), projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - { - code: '@media-non screen and (color), projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - ], - - reject: [ - { - code: '@media screen and (color), projection and (color) {}', - message: messages.expectedBefore(), - line: 1, - column: 26, - }, - { - code: '@mEdIa screen and (color), projection and (color) {}', - message: messages.expectedBefore(), - line: 1, - column: 26, - }, - { - code: '@MEDIA screen and (color), projection and (color) {}', - message: messages.expectedBefore(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color) , projection and (color) {}', - message: messages.expectedBefore(), - line: 1, - column: 28, - }, - { - code: '@media screen and (color)\t, projection and (color) {}', - message: messages.expectedBefore(), - line: 1, - column: 27, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - - accept: [ - { - code: '@media screen and (color)\n, projection and (color) {}', - description: 'multi-line list, single-line block', - }, - { - code: '@mEdIa screen and (color)\n, projection and (color) {}', - description: 'multi-line list, single-line block', - }, - { - code: '@MEDIA screen and (color)\n, projection and (color) {}', - description: 'multi-line list, single-line block', - }, - { - code: '@media screen and (color)\r\n, projection and (color) {}', - description: 'multi-line list, single-line block and CRLF', - }, - { - code: '@media screen and (color)\n, projection and (color) {\n}', - description: 'multi-line list, multi-line block', - }, - { - code: '@media screen and (color),projection and (color) {}', - description: 'ignore single line list, single-lint block', - }, - { - code: '@media screen and (color),projection and (color) {\n}', - description: 'ignore single line list, multi-line block', - }, - { - code: '@non-media screen and (color),projection and (color)\n, print {}', - description: 'ignore at-rules contain media in name', - }, - { - code: '@media-non screen and (color),projection and (color)\n, print {}', - description: 'ignore at-rules contain media in name', - }, - ], - - reject: [ - { - code: '@media screen and (color),projection and (color)\n, print {}', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 26, - }, - { - code: '@mEdIa screen and (color),projection and (color)\n, print {}', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 26, - }, - { - code: '@MEDIA screen and (color),projection and (color)\n, print {}', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color),projection and (color)\r\n, print {}', - description: 'CRLF', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color),projection and (color)\n, print {\n}', - message: messages.expectedBeforeMultiLine(), - line: 1, - column: 26, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - - accept: [ - { - code: '@media screen and (color),\nprojection and (color) {}', - description: 'multi-line list, single-line block', - }, - { - code: '@mEdIa screen and (color),\nprojection and (color) {}', - description: 'multi-line list, single-line block', - }, - { - code: '@MEDIA screen and (color),\nprojection and (color) {}', - description: 'multi-line list, single-line block', - }, - { - code: '@media screen and (color),\nprojection and (color) {\n}', - description: 'multi-line list, multi-line block', - }, - { - code: '@media screen and (color),\r\nprojection and (color) {\r\n}', - description: 'multi-line list, multi-line block and CRLF', - }, - { - code: '@media screen and (color) ,projection and (color) {}', - description: 'ignore single line list, single-lint block', - }, - { - code: '@media screen and (color) ,projection and (color) {\n}', - description: 'ignore single line list, multi-line block', - }, - { - code: '@non-media screen and (color) ,projection and (color),\nprint {}', - description: 'ignore at-rules contain media in name', - }, - { - code: '@media-non screen and (color) ,projection and (color),\nprint {}', - description: 'ignore at-rules contain media in name', - }, - ], - - reject: [ - { - code: '@media screen and (color) ,projection and (color),\nprint {}', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 27, - }, - { - code: '@mEdIa screen and (color) ,projection and (color),\nprint {}', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 27, - }, - { - code: '@MEDIA screen and (color) ,projection and (color),\nprint {}', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 27, - }, - { - code: '@media screen and (color) ,projection and (color),\nprint {\n}', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 27, - }, - { - code: '@media screen and (color) ,projection and (color),\r\nprint {\r\n}', - description: 'CRLF', - message: messages.rejectedBeforeMultiLine(), - line: 1, - column: 27, - }, - ], -}); diff --git a/lib/rules/media-query-list-comma-newline-before/index.js b/lib/rules/media-query-list-comma-newline-before/index.js deleted file mode 100644 index 6b155498d8..0000000000 --- a/lib/rules/media-query-list-comma-newline-before/index.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -const mediaQueryListCommaWhitespaceChecker = require('../mediaQueryListCommaWhitespaceChecker'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'media-query-list-comma-newline-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected newline before ","', - expectedBeforeMultiLine: () => 'Expected newline before "," in a multi-line list', - rejectedBeforeMultiLine: () => 'Unexpected whitespace before "," in a multi-line list', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/media-query-list-comma-newline-before', - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary) => { - const checker = whitespaceChecker('newline', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'always-multi-line', 'never-multi-line'], - }); - - if (!validOptions) { - return; - } - - mediaQueryListCommaWhitespaceChecker({ - root, - result, - locationChecker: checker.beforeAllowingIndentation, - checkedRuleName: ruleName, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/media-query-list-comma-space-after/README.md b/lib/rules/media-query-list-comma-space-after/README.md deleted file mode 100644 index 668aed9532..0000000000 --- a/lib/rules/media-query-list-comma-space-after/README.md +++ /dev/null @@ -1,138 +0,0 @@ -# media-query-list-comma-space-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace after the commas of media query lists. - - -```css -@media screen and (color), projection and (color) {} -/** ↑ - * The space after this comma */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"|"always-single-line"|"never-single-line"` - -### `"always"` - -There _must always_ be a single space after the commas. - -The following patterns are considered problems: - - -```css -@media screen and (color),projection and (color) {} -``` - - -```css -@media screen and (color) -,projection and (color) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media screen and (color), projection and (color) {} -``` - - -```css -@media screen and (color) -, projection and (color) {} -``` - -### `"never"` - -There _must never_ be whitespace after the commas. - -The following patterns are considered problems: - - -```css -@media screen and (color), projection and (color) {} -``` - - -```css -@media screen and (color) -, projection and (color) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media screen and (color),projection and (color) {} -``` - - -```css -@media screen and (color) -,projection and (color) {} -``` - -### `"always-single-line"` - -There _must always_ be a single space after the commas in single-line media query lists. - -The following patterns are considered problems: - - -```css -@media screen and (color),projection and (color) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media screen and (color), projection and (color) {} -``` - - -```css -@media screen and (color) -, projection and (color) {} -``` - - -```css -@media screen and (color) -,projection and (color) {} -``` - -### `"never-single-line"` - -There _must never_ be whitespace after the commas in single-line media query lists. - -The following patterns are considered problems: - - -```css -@media screen and (color), projection and (color) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media screen and (color),projection and (color) {} -``` - - -```css -@media screen and (color) -,projection and (color) {} -``` - - -```css -@media screen and (color) -, projection and (color) {} -``` diff --git a/lib/rules/media-query-list-comma-space-after/__tests__/index.js b/lib/rules/media-query-list-comma-space-after/__tests__/index.js deleted file mode 100644 index bd8ad84778..0000000000 --- a/lib/rules/media-query-list-comma-space-after/__tests__/index.js +++ /dev/null @@ -1,392 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: '@import url(x.com?a=b,c=d)', - }, - { - code: '@media (max-width: 600px) {}', - }, - { - code: '@mEdIa (max-width: 600px) {}', - }, - { - code: '@MEDIA (max-width: 600px) {}', - }, - { - code: '@media screen and (color), projection and (color) {}', - }, - { - code: '@media screen and (color) , projection and (color) {}', - }, - { - code: '@media screen and (color)\n, projection and (color) {}', - }, - { - code: '@media screen and (color)\r\n, projection and (color) {}', - description: 'CRLF', - }, - { - code: '@non-media screen and (color),projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - { - code: '@media-non screen and (color),projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - ], - - reject: [ - { - code: '@media screen and (color),projection and (color) {}', - fixed: '@media screen and (color), projection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@mEdIa screen and (color),projection and (color) {}', - fixed: '@mEdIa screen and (color), projection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@MEDIA screen and (color),projection and (color) {}', - fixed: '@MEDIA screen and (color), projection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color), projection and (color) {}', - fixed: '@media screen and (color), projection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color),\nprojection and (color) {}', - fixed: '@media screen and (color), projection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color),\r\nprojection and (color) {}', - fixed: '@media screen and (color), projection and (color) {}', - description: 'CRLF', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color),\tprojection and (color) {}', - fixed: '@media screen and (color), projection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color),/*comment*/projection and (color) {}', - fixed: '@media screen and (color), /*comment*/projection and (color) {}', - message: messages.expectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media tv,tv,tv,, print {}', - fixed: '@media tv, tv, tv, , print {}', - warnings: [ - { - message: messages.expectedAfter(), - line: 1, - column: 10, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 13, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 16, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: '@import url(x.com?a=b, c=d)', - }, - { - code: '@media (max-width: 600px) {}', - }, - { - code: '@mEdIa (max-width: 600px) {}', - }, - { - code: '@MEDIA (max-width: 600px) {}', - }, - { - code: '@media screen and (color),projection and (color) {}', - }, - { - code: '@media screen and (color) ,projection and (color) {}', - }, - { - code: '@media screen and (color)\n,projection and (color) {}', - }, - { - code: '@media screen and (color)\r\n,projection and (color) {}', - description: 'CRLF', - }, - { - code: '@non-media screen and (color), projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - { - code: '@media-non screen and (color), projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - ], - - reject: [ - { - code: '@media screen and (color), projection and (color) {}', - fixed: '@media screen and (color),projection and (color) {}', - message: messages.rejectedAfter(), - line: 1, - column: 26, - }, - { - code: '@mEdIa screen and (color), projection and (color) {}', - fixed: '@mEdIa screen and (color),projection and (color) {}', - message: messages.rejectedAfter(), - line: 1, - column: 26, - }, - { - code: '@MEDIA screen and (color), projection and (color) {}', - fixed: '@MEDIA screen and (color),projection and (color) {}', - message: messages.rejectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color), projection and (color) {}', - fixed: '@media screen and (color),projection and (color) {}', - message: messages.rejectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color),\nprojection and (color) {}', - fixed: '@media screen and (color),projection and (color) {}', - message: messages.rejectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color),\r\nprojection and (color) {}', - fixed: '@media screen and (color),projection and (color) {}', - description: 'CRLF', - message: messages.rejectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color),\tprojection and (color) {}', - fixed: '@media screen and (color),projection and (color) {}', - message: messages.rejectedAfter(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color), /*comment*/ projection and (color) {}', - fixed: '@media screen and (color),/*comment*/ projection and (color) {}', - message: messages.rejectedAfter(), - line: 1, - column: 26, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: '@media screen and (color), projection and (color) {}', - }, - { - code: '@mEdIa screen and (color), projection and (color) {}', - }, - { - code: '@MEDIA screen and (color), projection and (color) {}', - }, - { - code: '@media screen and (color), projection and (color) {\n}', - description: 'single-line list, multi-line block', - }, - { - code: '@media screen and (color), projection and (color) {\r\n}', - description: 'single-line list, multi-line block and CRLF', - }, - { - code: '@media screen and (color)\n,projection and (color) {}', - description: 'ignore multi-line', - }, - { - code: '@media screen and (color)\r\n,projection and (color) {}', - description: 'ignore multi-line and CRLF', - }, - { - code: '@non-media screen and (color) ,projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - { - code: '@media-non screen and (color) ,projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - ], - - reject: [ - { - code: '@media screen and (color) ,projection and (color) {}', - fixed: '@media screen and (color) , projection and (color) {}', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 27, - }, - { - code: '@mEdIa screen and (color) ,projection and (color) {}', - fixed: '@mEdIa screen and (color) , projection and (color) {}', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 27, - }, - { - code: '@MEDIA screen and (color) ,projection and (color) {}', - fixed: '@MEDIA screen and (color) , projection and (color) {}', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 27, - }, - { - code: '@media screen and (color) ,projection and (color) {\n}', - fixed: '@media screen and (color) , projection and (color) {\n}', - description: 'single-line list, multi-line block', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 27, - }, - { - code: '@media screen and (color) ,projection and (color) {\r\n}', - fixed: '@media screen and (color) , projection and (color) {\r\n}', - description: 'single-line list, multi-line block and CRLF', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 27, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - fix: true, - - accept: [ - { - code: '@media screen and (color) ,projection and (color) {}', - }, - { - code: '@mEdIa screen and (color) ,projection and (color) {}', - }, - { - code: '@MEDIA screen and (color) ,projection and (color) {}', - }, - { - code: '@media screen and (color) ,projection and (color) {\n}', - description: 'single-line list, multi-line block', - }, - { - code: '@media screen and (color) ,projection and (color) {\r\n}', - description: 'single-line list, multi-line block and CRLF', - }, - { - code: '@media screen and (color),\nprojection and (color) {}', - description: 'ignore multi-line', - }, - { - code: '@media screen and (color),\r\nprojection and (color) {}', - description: 'ignore multi-line and CRLF', - }, - { - code: '@non-media screen and (color), projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - { - code: '@media-non screen and (color), projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - ], - - reject: [ - { - code: '@media screen and (color), projection and (color) {}', - fixed: '@media screen and (color),projection and (color) {}', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 26, - }, - { - code: '@mEdIa screen and (color), projection and (color) {}', - fixed: '@mEdIa screen and (color),projection and (color) {}', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 26, - }, - { - code: '@MEDIA screen and (color), projection and (color) {}', - fixed: '@MEDIA screen and (color),projection and (color) {}', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color), projection and (color) {\n}', - fixed: '@media screen and (color),projection and (color) {\n}', - description: 'single-line list, multi-line block', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color), projection and (color) {\r\n}', - fixed: '@media screen and (color),projection and (color) {\r\n}', - description: 'single-line list, multi-line block and CRLF', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 26, - }, - ], -}); diff --git a/lib/rules/media-query-list-comma-space-after/index.js b/lib/rules/media-query-list-comma-space-after/index.js deleted file mode 100644 index 4eb0d4ac9a..0000000000 --- a/lib/rules/media-query-list-comma-space-after/index.js +++ /dev/null @@ -1,89 +0,0 @@ -'use strict'; - -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const mediaQueryListCommaWhitespaceChecker = require('../mediaQueryListCommaWhitespaceChecker'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'media-query-list-comma-space-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected single space after ","', - rejectedAfter: () => 'Unexpected whitespace after ","', - expectedAfterSingleLine: () => 'Expected single space after "," in a single-line list', - rejectedAfterSingleLine: () => 'Unexpected whitespace after "," in a single-line list', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/media-query-list-comma-space-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never', 'always-single-line', 'never-single-line'], - }); - - if (!validOptions) { - return; - } - - /** @type {Map | undefined} */ - let fixData; - - mediaQueryListCommaWhitespaceChecker({ - root, - result, - locationChecker: checker.after, - checkedRuleName: ruleName, - fix: context.fix - ? (atRule, index) => { - const paramCommaIndex = index - atRuleParamIndex(atRule); - - fixData = fixData || new Map(); - const commaIndices = fixData.get(atRule) || []; - - commaIndices.push(paramCommaIndex); - fixData.set(atRule, commaIndices); - - return true; - } - : null, - }); - - if (fixData) { - for (const [atRule, commaIndices] of fixData.entries()) { - let params = atRule.raws.params ? atRule.raws.params.raw : atRule.params; - - for (const index of commaIndices.sort((a, b) => b - a)) { - const beforeComma = params.slice(0, index + 1); - const afterComma = params.slice(index + 1); - - if (primary.startsWith('always')) { - params = beforeComma + afterComma.replace(/^\s*/, ' '); - } else if (primary.startsWith('never')) { - params = beforeComma + afterComma.replace(/^\s*/, ''); - } - } - - if (atRule.raws.params) { - atRule.raws.params.raw = params; - } else { - atRule.params = params; - } - } - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/media-query-list-comma-space-before/README.md b/lib/rules/media-query-list-comma-space-before/README.md deleted file mode 100644 index 839b8a3ed4..0000000000 --- a/lib/rules/media-query-list-comma-space-before/README.md +++ /dev/null @@ -1,138 +0,0 @@ -# media-query-list-comma-space-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace before the commas of media query lists. - - -```css -@media screen and (color) ,projection and (color) {} -/** ↑ - * The space before this comma */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"|"always-single-line"|"never-single-line"` - -### `"always"` - -There _must always_ be a single space before the commas. - -The following patterns are considered problems: - - -```css -@media screen and (color),projection and (color) {} -``` - - -```css -@media screen and (color) -,projection and (color) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media screen and (color) ,projection and (color) {} -``` - - -```css -@media screen and (color) , -projection and (color) {} -``` - -### `"never"` - -There _must never_ be whitespace before the commas. - -The following patterns are considered problems: - - -```css -@media screen and (color) ,projection and (color) {} -``` - - -```css -@media screen and (color) -, projection and (color) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media screen and (color),projection and (color) {} -``` - - -```css -@media screen and (color), -projection and (color) {} -``` - -### `"always-single-line"` - -There _must always_ be a single space before the commas in single-line media query lists. - -The following patterns are considered problems: - - -```css -@media screen and (color),projection and (color) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media screen and (color) ,projection and (color) {} -``` - - -```css -@media screen and (color) -, projection and (color) {} -``` - - -```css -@media screen and (color) -,projection and (color) {} -``` - -### `"never-single-line"` - -There _must never_ be whitespace before the commas in single-line media query lists. - -The following patterns are considered problems: - - -```css -@media screen and (color) , projection and (color) {} -``` - -The following patterns are _not_ considered problems: - - -```css -@media screen and (color),projection and (color) {} -``` - - -```css -@media screen and (color) -,projection and (color) {} -``` - - -```css -@media screen and (color) -, projection and (color) {} -``` diff --git a/lib/rules/media-query-list-comma-space-before/__tests__/index.js b/lib/rules/media-query-list-comma-space-before/__tests__/index.js deleted file mode 100644 index 442f85949b..0000000000 --- a/lib/rules/media-query-list-comma-space-before/__tests__/index.js +++ /dev/null @@ -1,413 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: '@import url(x.com?a=b,c=d)', - }, - { - code: '@media (max-width: 600px) {}', - }, - { - code: '@mEdIa (max-width: 600px) {}', - }, - { - code: '@MEDIA (max-width: 600px) {}', - }, - { - code: '@media screen and (color) , projection and (color) {}', - }, - { - code: '@media screen and (color) , projection and (color) {}', - }, - { - code: '@media screen and (color) ,\nprojection and (color) {}', - }, - { - code: '@media screen and (color) ,\r\nprojection and (color) {}', - description: 'CRLF', - }, - { - code: '@non-media screen and (color), projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - { - code: '@media-non screen and (color), projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - ], - - reject: [ - { - code: '@media screen and (color), projection and (color) {}', - fixed: '@media screen and (color) , projection and (color) {}', - message: messages.expectedBefore(), - line: 1, - column: 26, - }, - { - code: '@mEdIa screen and (color), projection and (color) {}', - fixed: '@mEdIa screen and (color) , projection and (color) {}', - message: messages.expectedBefore(), - line: 1, - column: 26, - }, - { - code: '@MEDIA screen and (color), projection and (color) {}', - fixed: '@MEDIA screen and (color) , projection and (color) {}', - message: messages.expectedBefore(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color) , projection and (color) {}', - fixed: '@media screen and (color) , projection and (color) {}', - message: messages.expectedBefore(), - line: 1, - column: 28, - }, - { - code: '@media screen and (color)\n, projection and (color) {}', - fixed: '@media screen and (color) , projection and (color) {}', - message: messages.expectedBefore(), - line: 2, - column: 1, - }, - { - code: '@media screen and (color)\r\n, projection and (color) {}', - fixed: '@media screen and (color) , projection and (color) {}', - description: 'CRLF', - message: messages.expectedBefore(), - line: 2, - column: 1, - }, - { - code: '@media screen and (color)\t, projection and (color) {}', - fixed: '@media screen and (color) , projection and (color) {}', - message: messages.expectedBefore(), - line: 1, - column: 27, - }, - { - code: '@media screen and (color)/*comment*/, projection and (color) {}', - fixed: '@media screen and (color)/*comment*/ , projection and (color) {}', - message: messages.expectedBefore(), - line: 1, - column: 37, - }, - { - code: '@media tv,tv,tv,print {}', - fixed: '@media tv ,tv ,tv ,print {}', - warnings: [ - { - message: messages.expectedBefore(), - line: 1, - column: 10, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 13, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 16, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: '@import url(x.com?a=b ,c=d)', - }, - { - code: '@media (max-width: 600px) {}', - }, - { - code: '@mEdIa (max-width: 600px) {}', - }, - { - code: '@MEDIA (max-width: 600px) {}', - }, - { - code: '@media screen and (color),projection and (color) {}', - }, - { - code: '@media screen and (color), projection and (color) {}', - }, - { - code: '@media screen and (color),\nprojection and (color) {}', - }, - { - code: '@media screen and (color),\r\nprojection and (color) {}', - description: 'CRLF', - }, - { - code: '@non-media screen and (color) , projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - { - code: '@media-non screen and (color) , projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - ], - - reject: [ - { - code: '@media screen and (color) , projection and (color) {}', - fixed: '@media screen and (color), projection and (color) {}', - message: messages.rejectedBefore(), - line: 1, - column: 27, - }, - { - code: '@mEdIa screen and (color) , projection and (color) {}', - fixed: '@mEdIa screen and (color), projection and (color) {}', - message: messages.rejectedBefore(), - line: 1, - column: 27, - }, - { - code: '@MEDIA screen and (color) , projection and (color) {}', - fixed: '@MEDIA screen and (color), projection and (color) {}', - message: messages.rejectedBefore(), - line: 1, - column: 27, - }, - { - code: '@media screen and (color) , projection and (color) {}', - fixed: '@media screen and (color), projection and (color) {}', - message: messages.rejectedBefore(), - line: 1, - column: 28, - }, - { - code: '@media screen and (color)\n, projection and (color) {}', - fixed: '@media screen and (color), projection and (color) {}', - message: messages.rejectedBefore(), - line: 2, - column: 1, - }, - { - code: '@media screen and (color)\r\n, projection and (color) {}', - fixed: '@media screen and (color), projection and (color) {}', - description: 'CRLF', - message: messages.rejectedBefore(), - line: 2, - column: 1, - }, - { - code: '@media screen and (color)\t, projection and (color) {}', - fixed: '@media screen and (color), projection and (color) {}', - message: messages.rejectedBefore(), - line: 1, - column: 27, - }, - { - code: '@media screen and (color) /*comment*/ , projection and (color) {}', - fixed: '@media screen and (color) /*comment*/, projection and (color) {}', - message: messages.rejectedBefore(), - line: 1, - column: 39, - }, - { - code: '@media tv ,tv ,tv ,print {}', - fixed: '@media tv,tv,tv,print {}', - warnings: [ - { - message: messages.rejectedBefore(), - line: 1, - column: 11, - }, - { - message: messages.rejectedBefore(), - line: 1, - column: 15, - }, - { - message: messages.rejectedBefore(), - line: 1, - column: 19, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: '@media screen and (color) ,projection and (color) {}', - }, - { - code: '@mEdIa screen and (color) ,projection and (color) {}', - }, - { - code: '@MEDIA screen and (color) ,projection and (color) {}', - }, - { - code: '@media screen and (color) ,projection and (color) {\n}', - description: 'single-line list, multi-line block', - }, - { - code: '@media screen and (color) ,projection and (color) {\r\n}', - description: 'single-line list, multi-line block and CRLF', - }, - { - code: '@media screen and (color),\nprojection and (color) {}', - description: 'ignore multi-line', - }, - { - code: '@media screen and (color),\r\nprojection and (color) {}', - description: 'ignore multi-line', - }, - { - code: '@non-media screen and (color), projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - { - code: '@media-non screen and (color), projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - ], - - reject: [ - { - code: '@media screen and (color), projection and (color) {}', - fixed: '@media screen and (color) , projection and (color) {}', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 26, - }, - { - code: '@mEdIa screen and (color), projection and (color) {}', - fixed: '@mEdIa screen and (color) , projection and (color) {}', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 26, - }, - { - code: '@MEDIA screen and (color), projection and (color) {}', - fixed: '@MEDIA screen and (color) , projection and (color) {}', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color), projection and (color) {\n}', - fixed: '@media screen and (color) , projection and (color) {\n}', - description: 'single-line list, multi-line block', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 26, - }, - { - code: '@media screen and (color), projection and (color) {\r\n}', - fixed: '@media screen and (color) , projection and (color) {\r\n}', - description: 'single-line list, multi-line block and CRLF', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 26, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - fix: true, - - accept: [ - { - code: '@media screen and (color), projection and (color) {}', - }, - { - code: '@mEdIa screen and (color), projection and (color) {}', - }, - { - code: '@MEDIA screen and (color), projection and (color) {}', - }, - { - code: '@media screen and (color), projection and (color) {\n}', - description: 'single-line list, multi-line block', - }, - { - code: '@media screen and (color), projection and (color) {\r\n}', - description: 'single-line list, multi-line block and CRLF', - }, - { - code: '@media screen and (color)\n,projection and (color) {}', - description: 'ignore multi-line', - }, - { - code: '@media screen and (color)\r\n,projection and (color) {}', - description: 'ignore multi-line and CRLF', - }, - { - code: '@non-media screen and (color) ,projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - { - code: '@media-non screen and (color) ,projection and (color) {}', - description: 'ignore at-rules contain media in name', - }, - ], - - reject: [ - { - code: '@media screen and (color) ,projection and (color) {}', - fixed: '@media screen and (color),projection and (color) {}', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 27, - }, - { - code: '@mEdIa screen and (color) ,projection and (color) {}', - fixed: '@mEdIa screen and (color),projection and (color) {}', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 27, - }, - { - code: '@MEDIA screen and (color) ,projection and (color) {}', - fixed: '@MEDIA screen and (color),projection and (color) {}', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 27, - }, - { - code: '@media screen and (color) ,projection and (color) {\n}', - fixed: '@media screen and (color),projection and (color) {\n}', - description: 'single-line list, multi-line block', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 27, - }, - { - code: '@media screen and (color) ,projection and (color) {\r\n}', - fixed: '@media screen and (color),projection and (color) {\r\n}', - description: 'single-line list, multi-line block and CRLF', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 27, - }, - ], -}); diff --git a/lib/rules/media-query-list-comma-space-before/index.js b/lib/rules/media-query-list-comma-space-before/index.js deleted file mode 100644 index b292e117b9..0000000000 --- a/lib/rules/media-query-list-comma-space-before/index.js +++ /dev/null @@ -1,89 +0,0 @@ -'use strict'; - -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const mediaQueryListCommaWhitespaceChecker = require('../mediaQueryListCommaWhitespaceChecker'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'media-query-list-comma-space-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected single space before ","', - rejectedBefore: () => 'Unexpected whitespace before ","', - expectedBeforeSingleLine: () => 'Expected single space before "," in a single-line list', - rejectedBeforeSingleLine: () => 'Unexpected whitespace before "," in a single-line list', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/media-query-list-comma-space-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never', 'always-single-line', 'never-single-line'], - }); - - if (!validOptions) { - return; - } - - /** @type {Map | undefined} */ - let fixData; - - mediaQueryListCommaWhitespaceChecker({ - root, - result, - locationChecker: checker.before, - checkedRuleName: ruleName, - fix: context.fix - ? (atRule, index) => { - const paramCommaIndex = index - atRuleParamIndex(atRule); - - fixData = fixData || new Map(); - const commaIndices = fixData.get(atRule) || []; - - commaIndices.push(paramCommaIndex); - fixData.set(atRule, commaIndices); - - return true; - } - : null, - }); - - if (fixData) { - for (const [atRule, commaIndices] of fixData.entries()) { - let params = atRule.raws.params ? atRule.raws.params.raw : atRule.params; - - for (const index of commaIndices.sort((a, b) => b - a)) { - const beforeComma = params.slice(0, index); - const afterComma = params.slice(index); - - if (primary.startsWith('always')) { - params = beforeComma.replace(/\s*$/, ' ') + afterComma; - } else if (primary.startsWith('never')) { - params = beforeComma.replace(/\s*$/, '') + afterComma; - } - } - - if (atRule.raws.params) { - atRule.raws.params.raw = params; - } else { - atRule.params = params; - } - } - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/mediaFeatureColonSpaceChecker.js b/lib/rules/mediaFeatureColonSpaceChecker.js deleted file mode 100644 index 8d72c90a5f..0000000000 --- a/lib/rules/mediaFeatureColonSpaceChecker.js +++ /dev/null @@ -1,51 +0,0 @@ -'use strict'; - -const atRuleParamIndex = require('../utils/atRuleParamIndex'); -const report = require('../utils/report'); -const styleSearch = require('style-search'); - -/** - * @param {{ - * root: import('postcss').Root, - * locationChecker: (args: { source: string, index: number, err: (message: string) => void }) => void, - * fix: ((node: import('postcss').AtRule, index: number) => boolean) | null, - * result: import('stylelint').PostcssResult, - * checkedRuleName: string, - * }} opts - */ -module.exports = function mediaFeatureColonSpaceChecker(opts) { - opts.root.walkAtRules(/^media$/i, (atRule) => { - const params = atRule.raws.params ? atRule.raws.params.raw : atRule.params; - - styleSearch({ source: params, target: ':' }, (match) => { - checkColon(params, match.startIndex, atRule); - }); - }); - - /** - * @param {string} source - * @param {number} index - * @param {import('postcss').AtRule} node - */ - function checkColon(source, index, node) { - opts.locationChecker({ - source, - index, - err: (message) => { - const colonIndex = index + atRuleParamIndex(node); - - if (opts.fix && opts.fix(node, colonIndex)) { - return; - } - - report({ - message, - node, - index: colonIndex, - result: opts.result, - ruleName: opts.checkedRuleName, - }); - }, - }); - } -}; diff --git a/lib/rules/mediaQueryListCommaWhitespaceChecker.js b/lib/rules/mediaQueryListCommaWhitespaceChecker.js deleted file mode 100644 index 7c84b1924b..0000000000 --- a/lib/rules/mediaQueryListCommaWhitespaceChecker.js +++ /dev/null @@ -1,71 +0,0 @@ -'use strict'; - -const styleSearch = require('style-search'); - -const atRuleParamIndex = require('../utils/atRuleParamIndex'); -const report = require('../utils/report'); -const { assertString } = require('../utils/validateTypes'); - -/** - * @param {{ - * root: import('postcss').Root, - * result: import('stylelint').PostcssResult, - * locationChecker: (args: { source: string, index: number, err: (message: string) => void }) => void, - * checkedRuleName: string, - * fix?: ((atRule: import('postcss').AtRule, index: number) => boolean) | null | undefined, - * allowTrailingComments?: boolean, - * }} opts - */ -module.exports = function mediaQueryListCommaWhitespaceChecker(opts) { - opts.root.walkAtRules(/^media$/i, (atRule) => { - const params = atRule.raws.params ? atRule.raws.params.raw : atRule.params; - - styleSearch({ source: params, target: ',' }, (match) => { - let index = match.startIndex; - - if (opts.allowTrailingComments) { - // if there is a comment on the same line at after the comma, check the space after the comment. - let execResult; - - while ((execResult = /^[^\S\r\n]*\/\*([\s\S]*?)\*\//.exec(params.slice(index + 1)))) { - assertString(execResult[0]); - index += execResult[0].length; - } - - if ((execResult = /^([^\S\r\n]*\/\/[\s\S]*?)\r?\n/.exec(params.slice(index + 1)))) { - assertString(execResult[1]); - index += execResult[1].length; - } - } - - checkComma(params, index, atRule); - }); - }); - - /** - * @param {string} source - * @param {number} index - * @param {import('postcss').AtRule} node - */ - function checkComma(source, index, node) { - opts.locationChecker({ - source, - index, - err: (message) => { - const commaIndex = index + atRuleParamIndex(node); - - if (opts.fix && opts.fix(node, commaIndex)) { - return; - } - - report({ - message, - node, - index: commaIndex, - result: opts.result, - ruleName: opts.checkedRuleName, - }); - }, - }); - } -}; diff --git a/lib/rules/no-empty-first-line/README.md b/lib/rules/no-empty-first-line/README.md deleted file mode 100644 index eceb134ca1..0000000000 --- a/lib/rules/no-empty-first-line/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# no-empty-first-line - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Disallow empty first lines. - - -```css - \n - /** ↑ - * This newline */ - a { color: pink; } -``` - -This rule ignores empty sources. Use the [`no-empty-source`](../no-empty-source/README.md) rule to disallow these. - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -### `true` - -The following patterns are considered problems: - - -```css -\n -a { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` diff --git a/lib/rules/no-empty-first-line/__tests__/index.js b/lib/rules/no-empty-first-line/__tests__/index.js deleted file mode 100644 index 845f4f0a4a..0000000000 --- a/lib/rules/no-empty-first-line/__tests__/index.js +++ /dev/null @@ -1,94 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: [true], - fix: true, - - accept: [ - { - code: '', - }, - { - code: ' ', - }, - { - code: '\n', - }, - { - code: '\n\n', - }, - { - code: '.class {}', - }, - { - code: '\t.class {} ', - }, - { - code: ' .class {} ', - }, - { - code: '/* comment */', - }, - ], - reject: [ - { - code: '\n.class {} \n', - fixed: '.class {} \n', - description: 'empty first line', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: '\r\n.class {}', - fixed: '.class {}', - description: 'empty first line', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: '\n/*some comment*/\n', - fixed: '/*some comment*/\n', - description: 'empty first line with comment', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: '\n/*some comment*/.class {}\na {}\n', - fixed: '/*some comment*/.class {}\na {}\n', - description: 'empty first line with comment and css content', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: '\r\n\r\n\r\n\r\n.class {}', - fixed: '.class {}', - description: 'multiple empty first lines', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: ' \r\n\r\n\r\n\r\n.class {}', - fixed: '.class {}', - description: 'multiple empty first lines with initial whitespace', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: ' \n.class {}', - fixed: '.class {}', - description: 'empty first line with multiple initial whitespaces', - message: messages.rejected, - line: 1, - column: 1, - }, - ], -}); diff --git a/lib/rules/no-empty-first-line/index.js b/lib/rules/no-empty-first-line/index.js deleted file mode 100644 index ee90c6e991..0000000000 --- a/lib/rules/no-empty-first-line/index.js +++ /dev/null @@ -1,64 +0,0 @@ -'use strict'; - -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'no-empty-first-line'; -const noEmptyFirstLineTest = /^\s*[\r\n]/; - -const messages = ruleMessages(ruleName, { - rejected: 'Unexpected empty line', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/no-empty-first-line', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { actual: primary }); - - // @ts-expect-error -- TS2339: Property 'inline' does not exist on type 'Source'. Property 'lang' does not exist on type 'Source'. - if (!validOptions || root.source.inline || root.source.lang === 'object-literal') { - return; - } - - const rootString = context.fix ? root.toString() : (root.source && root.source.input.css) || ''; - - if (!rootString.trim()) { - return; - } - - if (noEmptyFirstLineTest.test(rootString)) { - if (context.fix) { - if (root.first == null) { - throw new Error('The root node must have the first node.'); - } - - if (root.first.raws.before == null) { - throw new Error('The first node must have spaces before.'); - } - - root.first.raws.before = root.first.raws.before.trimStart(); - - return; - } - - report({ - message: messages.rejected, - node: root, - result, - ruleName, - }); - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/no-eol-whitespace/README.md b/lib/rules/no-eol-whitespace/README.md deleted file mode 100644 index 5e81e2e078..0000000000 --- a/lib/rules/no-eol-whitespace/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# no-eol-whitespace - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Disallow end-of-line whitespace. - - -```css -a { color: pink; }··· -/** ↑ - * This whitespace */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix most of the problems reported by this rule. - -## Options - -### `true` - -The following patterns are considered problems: - - -```css -a { color: pink; }· -``` - - -```css -a { color: pink; }···· -``` - -Comment strings are also checked -- so the following is a problem: - - -```css -/* something···· - * something else */ -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -``` - - -```css -/* something - * something else */ -``` - -## Optional secondary options - -### `ignore: ["empty-lines"]` - -#### `"empty-lines"` - -Allow end-of-line whitespace for lines that are only whitespace, "empty" lines. - -The following patterns are _not_ considered problems: - - -```css -a { - color: pink; -·· - background: orange; -} -``` - - -```css -···· -``` - - -```css -a { color: pink; } -···· -``` diff --git a/lib/rules/no-eol-whitespace/__tests__/index.js b/lib/rules/no-eol-whitespace/__tests__/index.js deleted file mode 100644 index 61c8d07601..0000000000 --- a/lib/rules/no-eol-whitespace/__tests__/index.js +++ /dev/null @@ -1,644 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: [true], - fix: true, - - accept: [ - { - code: '', - description: 'empty string', - }, - { - code: '\n', - description: 'no nodes', - }, - { - code: 'a {}', - description: 'no newline', - }, - { - code: 'a::before { content: " \n\t\n"; }', - description: 'breaking the rule within a string', - }, - { - code: 'a,\nb {}', - description: 'selector delimiter', - }, - { - code: 'a\n{}', - description: 'before opening brace', - }, - { - code: 'a {\n color: pink; }', - description: 'after opening brace with space after newline', - }, - { - code: 'a { color: pink;\n}', - description: 'before closing brace', - }, - { - code: 'a { color: pink; }\nb { color: orange; }', - description: 'after closing brace', - }, - { - code: 'a { color: pink; }\n\n\nb { color: orange; }', - description: 'multiple newlines after closing brace', - }, - { - code: 'a { color: pink;\n top: 0; }', - description: 'between declarations with two spaces after newline', - }, - { - code: 'a { color:\n\tpink; }', - description: 'between properties and values with tab after newline', - }, - { - code: 'a { background-position: top left,\ntop right; }', - description: 'within values', - }, - { - code: '@media print,\nscreen {}', - description: 'within media query list', - }, - { - code: '@media print {\n a { color: pink; } }', - description: 'after opening brace of media query with space after newline', - }, - { - code: 'a\r{}', - description: 'carriage return opening brace', - }, - { - code: 'a\n{\n\tcolor: pink;\n\ttop: 0;\n}', - }, - { - code: '@media print {\n a {\n color: pink;\n }\n}\n\n@media screen {\n b { color: orange; }\n}', - }, - { - code: '/* comment\n*/', - }, - { - code: '/* comment\r\n*/\r\n', - }, - ], - - reject: [ - { - code: ' \n', - fixed: '\n', - description: 'no nodes with space before newline', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: '/* foo \nbar */ a { color: pink; }', - fixed: '/* foo\nbar */ a { color: pink; }', - description: 'eol-whitespace within a comment', - message: messages.rejected, - line: 1, - column: 8, - }, - { - code: '/* \nfoo */ a { color: pink; }', - fixed: '/*\nfoo */ a { color: pink; }', - description: 'eol-whitespace within a comment left', - message: messages.rejected, - line: 1, - column: 3, - }, - { - code: 'a, \nb {}', - fixed: 'a,\nb {}', - description: 'selector delimiter with space before newline', - message: messages.rejected, - line: 1, - column: 3, - }, - { - code: 'a\t\n{}', - fixed: 'a\n{}', - description: 'before opening brace with tab before newline', - message: messages.rejected, - line: 1, - column: 2, - }, - { - code: 'a { \n color: pink; }', - fixed: 'a {\n color: pink; }', - description: 'after opening brace with space before and after newline', - message: messages.rejected, - line: 1, - column: 4, - }, - { - code: 'a { color: pink; \n}', - fixed: 'a { color: pink;\n}', - description: 'before closing brace with space before newline', - message: messages.rejected, - line: 1, - column: 17, - }, - { - code: 'a { color: pink; }\t\nb { color: orange; }', - fixed: 'a { color: pink; }\nb { color: orange; }', - description: 'after closing brace with tab before newline', - message: messages.rejected, - line: 1, - column: 19, - }, - { - code: 'a { color: pink; } \n\n\nb { color: orange; }', - fixed: 'a { color: pink; }\n\n\nb { color: orange; }', - message: messages.rejected, - line: 1, - column: 19, - }, - { - code: 'a { color: pink; }\n \n\nb { color: orange; }', - fixed: 'a { color: pink; }\n\n\nb { color: orange; }', - message: messages.rejected, - line: 2, - column: 1, - }, - { - code: 'a { color: pink; }\n\n \nb { color: orange; }', - fixed: 'a { color: pink; }\n\n\nb { color: orange; }', - message: messages.rejected, - line: 3, - column: 1, - }, - { - code: 'a { color: pink; \n top: 0; }', - fixed: 'a { color: pink;\n top: 0; }', - description: 'between declarations with space before and two after newline', - message: messages.rejected, - line: 1, - column: 17, - }, - { - code: 'a { color:\t\n\tpink; }', - fixed: 'a { color:\n\tpink; }', - description: 'between properties and values with tab before and after newline', - message: messages.rejected, - line: 1, - column: 11, - }, - { - code: 'a { background-position: top left, \ntop right; }', - fixed: 'a { background-position: top left,\ntop right; }', - description: 'within values with space before newline', - message: messages.rejected, - line: 1, - column: 35, - }, - { - code: '@media print, \nscreen {}', - fixed: '@media print,\nscreen {}', - description: 'within media query list with space before newline', - message: messages.rejected, - line: 1, - column: 14, - }, - { - code: '@media print { \n a { color: pink; } }', - fixed: '@media print {\n a { color: pink; } }', - description: 'after opening brace of media query with space before and after newline', - message: messages.rejected, - line: 1, - column: 15, - }, - { - code: 'a\t\r{}', - fixed: 'a\r{}', - description: 'tab before carriage return before opening brace', - message: messages.rejected, - line: 1, - column: 2, - }, - { - code: 'a \n{\n\tcolor: pink;\n\ttop: 0;\n}', - fixed: 'a\n{\n\tcolor: pink;\n\ttop: 0;\n}', - message: messages.rejected, - line: 1, - column: 2, - }, - { - code: 'a\n{\t\n\tcolor: pink;\n\ttop: 0;\n}', - fixed: 'a\n{\n\tcolor: pink;\n\ttop: 0;\n}', - message: messages.rejected, - line: 2, - column: 2, - }, - { - code: 'a\n{\n\tcolor: pink; \n\ttop: 0;\n}', - fixed: 'a\n{\n\tcolor: pink;\n\ttop: 0;\n}', - message: messages.rejected, - line: 3, - column: 14, - }, - { - code: 'a\n{\n\tcolor: pink;\n\ttop: 0; \n}', - fixed: 'a\n{\n\tcolor: pink;\n\ttop: 0;\n}', - message: messages.rejected, - line: 4, - column: 10, - }, - { - code: '@media print { \n a {\n color: pink;\n }\n}\n\n@media screen {\n b { color: orange; }\n}', - fixed: - '@media print {\n a {\n color: pink;\n }\n}\n\n@media screen {\n b { color: orange; }\n}', - message: messages.rejected, - line: 1, - column: 15, - }, - { - code: '@media print {\n a { \n color: pink;\n }\n}\n\n@media screen {\n b { color: orange; }\n}', - fixed: - '@media print {\n a {\n color: pink;\n }\n}\n\n@media screen {\n b { color: orange; }\n}', - message: messages.rejected, - line: 2, - column: 6, - }, - { - code: '@media print {\n a {\n color: pink; \n }\n}\n\n@media screen {\n b { color: orange; }\n}', - fixed: - '@media print {\n a {\n color: pink;\n }\n}\n\n@media screen {\n b { color: orange; }\n}', - message: messages.rejected, - line: 3, - column: 15, - }, - { - code: '@media print {\n a {\n color: pink;\n } \n}\n\n@media screen {\n b { color: orange; }\n}', - fixed: - '@media print {\n a {\n color: pink;\n }\n}\n\n@media screen {\n b { color: orange; }\n}', - message: messages.rejected, - line: 4, - column: 4, - }, - { - code: '@media print {\n a {\n color: pink;\n }\n} \n\n@media screen {\n b { color: orange; }\n}', - fixed: - '@media print {\n a {\n color: pink;\n }\n}\n\n@media screen {\n b { color: orange; }\n}', - message: messages.rejected, - line: 5, - column: 2, - }, - { - code: '@media print {\n a {\n color: pink;\n }\n}\n \n@media screen {\n b { color: orange; }\n}', - fixed: - '@media print {\n a {\n color: pink;\n }\n}\n\n@media screen {\n b { color: orange; }\n}', - message: messages.rejected, - line: 6, - column: 1, - }, - { - code: '@media print {\n a {\n color: pink;\n }\n}\n\n@media screen { \n b { color: orange; }\n}', - fixed: - '@media print {\n a {\n color: pink;\n }\n}\n\n@media screen {\n b { color: orange; }\n}', - message: messages.rejected, - line: 7, - column: 16, - }, - { - code: '@media print {\n a {\n color: pink;\n }\n}\n\n@media screen {\n b { color: orange; } \n}', - fixed: - '@media print {\n a {\n color: pink;\n }\n}\n\n@media screen {\n b { color: orange; }\n}', - message: messages.rejected, - line: 8, - column: 23, - }, - { - code: 'a { color \n: \npink; }', - fixed: 'a { color\n:\npink; }', - description: 'between before and after newline', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 10, - }, - { - message: messages.rejected, - line: 2, - column: 2, - }, - ], - }, - { - code: 'a { padding: 0 \n0 \n0 \n0 \n; }', - fixed: 'a { padding: 0\n0\n0\n0\n; }', - description: 'values newline', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 15, - }, - { - message: messages.rejected, - line: 2, - column: 2, - }, - { - message: messages.rejected, - line: 3, - column: 2, - }, - { - message: messages.rejected, - line: 4, - column: 2, - }, - ], - }, - { - code: 'a { padding: 0 /* \n \n*/0 0 0; }', - fixed: 'a { padding: 0 /*\n\n*/0 0 0; }', - description: 'values comment newline', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 18, - }, - { - message: messages.rejected, - line: 2, - column: 1, - }, - ], - }, - { - code: 'a/* \n*/ \n.b { }', - fixed: 'a/*\n*/\n.b { }', - description: 'raws selector', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 4, - }, - { - message: messages.rejected, - line: 2, - column: 3, - }, - ], - }, - { - code: '@media \n print {}', - fixed: '@media\n print {}', - description: 'afterName', - message: messages.rejected, - line: 1, - column: 7, - }, - { - code: '@media/* \n*/ print {}', - fixed: '@media/*\n*/ print {}', - description: 'afterName', - message: messages.rejected, - line: 1, - column: 9, - }, - { - code: '@media print, \nscreen {}', - fixed: '@media print,\nscreen {}', - description: 'params', - message: messages.rejected, - line: 1, - column: 14, - }, - { - code: '@media print,/* \n*/screen {}', - fixed: '@media print,/*\n*/screen {}', - description: 'raws params', - message: messages.rejected, - line: 1, - column: 16, - }, - { - code: '/* comment \n*/ \n', - fixed: '/* comment\n*/\n', - description: 'comments fix properly (1)', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 16, - }, - { - message: messages.rejected, - line: 2, - column: 5, - }, - ], - }, - { - code: '/* comment \n*/ ', - fixed: '/* comment\n*/', - description: 'comments fix properly (2)', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 16, - }, - { - message: messages.rejected, - line: 2, - column: 5, - }, - ], - }, - { - code: '/* comment \r\n*/ \r\n', - fixed: '/* comment\r\n*/\r\n', - description: 'comments fix properly (3)', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 16, - }, - { - message: messages.rejected, - line: 2, - column: 5, - }, - ], - }, - { - code: '/* comment \r\n*/ ', - fixed: '/* comment\r\n*/', - description: 'comments fix properly (4)', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 16, - }, - { - message: messages.rejected, - line: 2, - column: 5, - }, - ], - }, - { - code: 'a\n{ color: red \n} ', - fixed: 'a\n{ color: red\n}', - description: 'fix properly without trailing EOL', - warnings: [ - { - message: messages.rejected, - line: 2, - column: 13, - }, - { - message: messages.rejected, - line: 3, - column: 3, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: [true], - customSyntax: 'postcss-scss', - fix: true, - - accept: [ - { - code: '// comment 1\n', - description: 'scss comment (1)', - }, - { - code: '//\n//comment\n a\n{ color: red\n}', - description: 'scss comment (2)', - }, - ], - - reject: [ - { - code: '// comment 2 ', - fixed: '// comment 2', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 14, - }, - ], - }, - { - code: '// comment 3 \r\n', - fixed: '// comment 3\r\n', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 14, - }, - ], - }, - { - code: '// comment 3 \ra {color: red} ', - fixed: '// comment 3\ra {color: red}', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 14, - }, - { - message: messages.rejected, - line: 1, - column: 31, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: [true], - customSyntax: 'postcss-html', - fix: true, - - accept: [ - { - code: `
/* After this comment we have eol whitespace */ - - -
`, - }, - ], - - reject: [ - { - code: '', - fixed: '', - message: messages.rejected, - line: 3, - column: 14, - }, - ], -}); - -testRule({ - ruleName, - config: [true, { ignore: ['empty-lines'] }], - fix: true, - - accept: [ - { - code: 'a {}\n \nb {}', - description: 'empty line with spaces', - }, - { - code: 'a {}\r\n\t\r\nb {}', - description: 'empty line with a tab and CRLF', - }, - { - code: 'a {}\n \t\nb {}', - description: 'empty line with spaces and a tab', - }, - { - code: ' \n', - description: 'no nodes with space before newline', - }, - ], - - reject: [ - { - code: 'a { color: pink; \n}', - fixed: 'a { color: pink;\n}', - description: 'typical rejection #1', - message: messages.rejected, - line: 1, - column: 17, - }, - { - code: 'a { color: pink; }\t\n', - fixed: 'a { color: pink; }\n', - description: 'typical rejection #2', - message: messages.rejected, - line: 1, - column: 19, - }, - ], -}); diff --git a/lib/rules/no-eol-whitespace/index.js b/lib/rules/no-eol-whitespace/index.js deleted file mode 100644 index 9eb58e67ef..0000000000 --- a/lib/rules/no-eol-whitespace/index.js +++ /dev/null @@ -1,297 +0,0 @@ -'use strict'; - -const styleSearch = require('style-search'); - -const isOnlyWhitespace = require('../../utils/isOnlyWhitespace'); -const isStandardSyntaxComment = require('../../utils/isStandardSyntaxComment'); -const optionsMatches = require('../../utils/optionsMatches'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const { isAtRule, isComment, isDeclaration, isRule } = require('../../utils/typeGuards'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'no-eol-whitespace'; - -const messages = ruleMessages(ruleName, { - rejected: 'Unexpected whitespace at end of line', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/no-eol-whitespace', - fixable: true, - deprecated: true, -}; - -const whitespacesToReject = new Set([' ', '\t']); - -/** - * @param {string} str - * @returns {string} - */ -function fixString(str) { - return str.replace(/[ \t]+$/, ''); -} - -/** - * @param {number} lastEOLIndex - * @param {string} string - * @param {{ ignoreEmptyLines: boolean, isRootFirst: boolean }} options - * @returns {number} - */ -function findErrorStartIndex(lastEOLIndex, string, { ignoreEmptyLines, isRootFirst }) { - const eolWhitespaceIndex = lastEOLIndex - 1; - - // If the character before newline is not whitespace, ignore - if (!whitespacesToReject.has(string.charAt(eolWhitespaceIndex))) { - return -1; - } - - if (ignoreEmptyLines) { - // If there is only whitespace between the previous newline and - // this newline, ignore - const beforeNewlineIndex = string.lastIndexOf('\n', eolWhitespaceIndex); - - if (beforeNewlineIndex >= 0 || isRootFirst) { - const line = string.substring(beforeNewlineIndex, eolWhitespaceIndex); - - if (isOnlyWhitespace(line)) { - return -1; - } - } - } - - return eolWhitespaceIndex; -} - -/** @type {import('stylelint').Rule} */ -const rule = (primary, secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions( - result, - ruleName, - { - actual: primary, - }, - { - optional: true, - actual: secondaryOptions, - possible: { - ignore: ['empty-lines'], - }, - }, - ); - - if (!validOptions) { - return; - } - - const ignoreEmptyLines = optionsMatches(secondaryOptions, 'ignore', 'empty-lines'); - - if (context.fix) { - fix(root); - } - - const rootString = context.fix ? root.toString() : (root.source && root.source.input.css) || ''; - - /** - * @param {number} index - */ - const reportFromIndex = (index) => { - report({ - message: messages.rejected, - node: root, - index, - result, - ruleName, - }); - }; - - eachEolWhitespace(rootString, reportFromIndex, true); - - const errorIndex = findErrorStartIndex(rootString.length, rootString, { - ignoreEmptyLines, - isRootFirst: true, - }); - - if (errorIndex > -1) { - reportFromIndex(errorIndex); - } - - /** - * Iterate each whitespace at the end of each line of the given string. - * @param {string} string - the source code string - * @param {(index: number) => void} callback - callback the whitespace index at the end of each line. - * @param {boolean} isRootFirst - set `true` if the given string is the first token of the root. - * @returns {void} - */ - function eachEolWhitespace(string, callback, isRootFirst) { - styleSearch( - { - source: string, - target: ['\n', '\r'], - comments: 'check', - }, - (match) => { - const index = findErrorStartIndex(match.startIndex, string, { - ignoreEmptyLines, - isRootFirst, - }); - - if (index > -1) { - callback(index); - } - }, - ); - } - - /** - * @param {import('postcss').Root} rootNode - */ - function fix(rootNode) { - let isRootFirst = true; - - rootNode.walk((node) => { - fixText( - node.raws.before, - (fixed) => { - node.raws.before = fixed; - }, - isRootFirst, - ); - isRootFirst = false; - - if (isAtRule(node)) { - fixText(node.raws.afterName, (fixed) => { - node.raws.afterName = fixed; - }); - - const rawsParams = node.raws.params; - - if (rawsParams) { - fixText(rawsParams.raw, (fixed) => { - rawsParams.raw = fixed; - }); - } else { - fixText(node.params, (fixed) => { - node.params = fixed; - }); - } - } - - if (isRule(node)) { - const rawsSelector = node.raws.selector; - - if (rawsSelector) { - fixText(rawsSelector.raw, (fixed) => { - rawsSelector.raw = fixed; - }); - } else { - fixText(node.selector, (fixed) => { - node.selector = fixed; - }); - } - } - - if (isAtRule(node) || isRule(node) || isDeclaration(node)) { - fixText(node.raws.between, (fixed) => { - node.raws.between = fixed; - }); - } - - if (isDeclaration(node)) { - const rawsValue = node.raws.value; - - if (rawsValue) { - fixText(rawsValue.raw, (fixed) => { - rawsValue.raw = fixed; - }); - } else { - fixText(node.value, (fixed) => { - node.value = fixed; - }); - } - } - - if (isComment(node)) { - fixText(node.raws.left, (fixed) => { - node.raws.left = fixed; - }); - - if (!isStandardSyntaxComment(node)) { - node.raws.right = node.raws.right && fixString(node.raws.right); - } else { - fixText(node.raws.right, (fixed) => { - node.raws.right = fixed; - }); - } - - fixText(node.text, (fixed) => { - node.text = fixed; - }); - } - - if (isAtRule(node) || isRule(node)) { - fixText(node.raws.after, (fixed) => { - node.raws.after = fixed; - }); - } - }); - - fixText( - rootNode.raws.after, - (fixed) => { - rootNode.raws.after = fixed; - }, - isRootFirst, - ); - - if (typeof rootNode.raws.after === 'string') { - const lastEOL = Math.max( - rootNode.raws.after.lastIndexOf('\n'), - rootNode.raws.after.lastIndexOf('\r'), - ); - - if (lastEOL !== rootNode.raws.after.length - 1) { - rootNode.raws.after = - rootNode.raws.after.slice(0, lastEOL + 1) + - fixString(rootNode.raws.after.slice(lastEOL + 1)); - } - } - } - - /** - * @param {string | undefined} value - * @param {(text: string) => void} fixFn - * @param {boolean} isRootFirst - */ - function fixText(value, fixFn, isRootFirst = false) { - if (!value) { - return; - } - - let fixed = ''; - let lastIndex = 0; - - eachEolWhitespace( - value, - (index) => { - const newlineIndex = index + 1; - - fixed += fixString(value.slice(lastIndex, newlineIndex)); - lastIndex = newlineIndex; - }, - isRootFirst, - ); - - if (lastIndex) { - fixed += value.slice(lastIndex); - fixFn(fixed); - } - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/no-extra-semicolons/README.md b/lib/rules/no-extra-semicolons/README.md deleted file mode 100644 index a2cd914740..0000000000 --- a/lib/rules/no-extra-semicolons/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# no-extra-semicolons - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Disallow extra semicolons. - - -```css -a { color: pink;; } -/** ↑ - * This semicolons */ -``` - -This rule ignores semicolons after Less mixins. - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -### `true` - -The following patterns are considered problems: - - -```css -@import "x.css";; -``` - - -```css -@import "x.css"; -; -``` - - -```css -a { - color: pink;; -} -``` - - -```css -a { - ;color: pink; -} -``` - - -```css -a { - color: pink; - ; -} -``` - - -```css -a { - color: red; -} -; -b { - color: white; -} -``` - -The following patterns are _not_ considered problems: - - -```css -@import "x.css"; -``` - - -```css -a { - color: pink; -} -``` diff --git a/lib/rules/no-extra-semicolons/__tests__/index.js b/lib/rules/no-extra-semicolons/__tests__/index.js deleted file mode 100644 index c1ea5a4e80..0000000000 --- a/lib/rules/no-extra-semicolons/__tests__/index.js +++ /dev/null @@ -1,1033 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: [true], - fix: true, - - accept: [ - { - code: "@import 'x.css';", - }, - { - code: '.foo { color: red }', - }, - { - code: '.foo { color: red; }', - }, - { - code: '.foo { color: red; display: block; }', - }, - { - code: '.foo { color: red; display: block }', - }, - { - code: '@media screen { a { color: red; } }', - }, - { - code: '/* comment */', - }, - { - code: '/* comment; */', - }, - { - code: '/* ;;comment;; words;; */', - }, - { - code: "a { content: ''; }", - }, - { - code: "a { content: ';'; }", - }, - { - code: "a { content: ';;'; }", - }, - { - code: "a { content: ';\t; ;'; }", - }, - { - code: ':root { --foo: red; --bar: blue; }', - }, - { - code: ':root { --foo: { color: red }; --bar: { color: blue }; --foo-bar: { color: blue }; --bar-foo: { color: red }; }', - }, - { - code: ':root { --foo: { color: red }; /* comment */ --bar: { color: blue };/* comment */ --foo-bar: { color: blue }; --bar-foo: { color: red }; }', - }, - ], - - reject: [ - { - code: ';', - fixed: '', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: ' ;', - fixed: ' ', - message: messages.rejected, - line: 1, - column: 2, - }, - { - code: ' ;', - fixed: ' ', - message: messages.rejected, - line: 1, - column: 3, - }, - { - code: '\n;', - fixed: '\n', - message: messages.rejected, - line: 2, - column: 1, - }, - { - code: '\n\n;', - fixed: '\n\n', - message: messages.rejected, - line: 3, - column: 1, - }, - { - code: '\r\n;', - fixed: '\r\n', - message: messages.rejected, - line: 2, - column: 1, - }, - { - code: '\r\n\r\n;', - fixed: '\r\n\r\n', - message: messages.rejected, - line: 3, - column: 1, - }, - { - code: '\r;', - fixed: '\r', - message: messages.rejected, - line: 1, - column: 2, - }, - { - code: '\r\r;', - fixed: '\r\r', - message: messages.rejected, - line: 1, - column: 3, - }, - { - code: '\t;', - fixed: '\t', - message: messages.rejected, - line: 1, - column: 2, - }, - { - code: '\t\t;', - fixed: '\t\t', - message: messages.rejected, - line: 1, - column: 3, - }, - { - code: '; ; ;', - fixed: ' ', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 1, - }, - { - message: messages.rejected, - line: 1, - column: 3, - }, - { - message: messages.rejected, - line: 1, - column: 5, - }, - ], - }, - { - code: 'a {;}', - fixed: 'a {}', - message: messages.rejected, - line: 1, - column: 4, - }, - { - code: 'a { ;}', - fixed: 'a { }', - message: messages.rejected, - line: 1, - column: 5, - }, - { - code: 'a {; }', - fixed: 'a { }', - message: messages.rejected, - line: 1, - column: 4, - }, - { - code: 'a { ; }', - fixed: 'a { }', - message: messages.rejected, - line: 1, - column: 5, - }, - { - code: 'a { ;}', - fixed: 'a { }', - message: messages.rejected, - line: 1, - column: 6, - }, - { - code: 'a {; }', - fixed: 'a { }', - message: messages.rejected, - line: 1, - column: 4, - }, - { - code: 'a { ; }', - fixed: 'a { }', - message: messages.rejected, - line: 1, - column: 6, - }, - { - code: 'a { ; }', - fixed: 'a { }', - message: messages.rejected, - line: 1, - column: 7, - }, - { - code: 'a {\n;}', - fixed: 'a {\n}', - message: messages.rejected, - line: 2, - column: 1, - }, - { - code: 'a {;\n}', - fixed: 'a {\n}', - message: messages.rejected, - line: 1, - column: 4, - }, - { - code: 'a {\n;\n}', - fixed: 'a {\n\n}', - message: messages.rejected, - line: 2, - column: 1, - }, - { - code: 'a {\r\n;}', - fixed: 'a {\r\n}', - message: messages.rejected, - line: 2, - column: 1, - }, - { - code: 'a {;\r\n}', - fixed: 'a {\r\n}', - message: messages.rejected, - line: 1, - column: 4, - }, - { - code: 'a {\r\n;\r\n}', - fixed: 'a {\r\n\r\n}', - message: messages.rejected, - line: 2, - column: 1, - }, - { - code: 'a {\t;}', - fixed: 'a {\t}', - message: messages.rejected, - line: 1, - column: 5, - }, - { - code: 'a {;\t}', - fixed: 'a {\t}', - message: messages.rejected, - line: 1, - column: 4, - }, - { - code: 'a {\t;\t}', - fixed: 'a {\t\t}', - message: messages.rejected, - line: 1, - column: 5, - }, - { - code: 'a { ;\n;\t; }', - fixed: 'a { \n\t }', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 5, - }, - { - message: messages.rejected, - line: 2, - column: 1, - }, - { - message: messages.rejected, - line: 2, - column: 3, - }, - ], - }, - { - code: 'a { color: red; };', - fixed: 'a { color: red; }', - message: messages.rejected, - line: 1, - column: 18, - }, - { - code: 'a { color: red; } ;', - fixed: 'a { color: red; } ', - message: messages.rejected, - line: 1, - column: 19, - }, - { - code: 'a { color: red; }\n;', - fixed: 'a { color: red; }\n', - message: messages.rejected, - line: 2, - column: 1, - }, - { - code: 'a { color: red; }\n\n;', - fixed: 'a { color: red; }\n\n', - message: messages.rejected, - line: 3, - column: 1, - }, - { - code: 'a { color: red; }\r\n;', - fixed: 'a { color: red; }\r\n', - message: messages.rejected, - line: 2, - column: 1, - }, - { - code: 'a { color: red; }\r\n\r\n;', - fixed: 'a { color: red; }\r\n\r\n', - message: messages.rejected, - line: 3, - column: 1, - }, - { - code: 'a { color: red; }\r;', - fixed: 'a { color: red; }\r', - message: messages.rejected, - line: 1, - column: 19, - }, - { - code: 'a { color: red; }\r\r;', - fixed: 'a { color: red; }\r\r', - message: messages.rejected, - line: 1, - column: 20, - }, - { - code: 'a { color: red; }\t;', - fixed: 'a { color: red; }\t', - message: messages.rejected, - line: 1, - column: 19, - }, - { - code: 'a { color: red; }\t\t;', - fixed: 'a { color: red; }\t\t', - message: messages.rejected, - line: 1, - column: 20, - }, - { - code: 'a { color: red; };\t;\n; ;', - fixed: 'a { color: red; }\t\n ', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 20, - }, - { - message: messages.rejected, - line: 2, - column: 1, - }, - { - message: messages.rejected, - line: 2, - column: 3, - }, - { - message: messages.rejected, - line: 1, - column: 18, - }, - ], - }, - { - code: ';a { color: red; }', - fixed: 'a { color: red; }', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: '; a { color: red; }', - fixed: ' a { color: red; }', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: '; a { color: red; }', - fixed: ' a { color: red; }', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: ';\na { color: red; }', - fixed: '\na { color: red; }', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: ';\n\na { color: red; }', - fixed: '\n\na { color: red; }', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: ';\r\na { color: red; }', - fixed: '\r\na { color: red; }', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: ';\r\n\r\na { color: red; }', - fixed: '\r\n\r\na { color: red; }', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: ';\ta { color: red; }', - fixed: '\ta { color: red; }', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: ';\t\ta { color: red; }', - fixed: '\t\ta { color: red; }', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: ';\n;\t; ;a { color: red; }', - fixed: '\n\t a { color: red; }', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 1, - }, - { - message: messages.rejected, - line: 2, - column: 1, - }, - { - message: messages.rejected, - line: 2, - column: 3, - }, - { - message: messages.rejected, - line: 2, - column: 5, - }, - ], - }, - { - code: '/*comment*/\n;\t; ;a { color: red; }', - fixed: '/*comment*/\n\t a { color: red; }', - warnings: [ - { - message: messages.rejected, - line: 2, - column: 1, - }, - { - message: messages.rejected, - line: 2, - column: 3, - }, - { - message: messages.rejected, - line: 2, - column: 5, - }, - ], - }, - { - code: ';/*comment*/\n;\t; ;a { color: red; }', - fixed: '/*comment*/\n\t a { color: red; }', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 1, - }, - { - message: messages.rejected, - line: 2, - column: 1, - }, - { - message: messages.rejected, - line: 2, - column: 3, - }, - { - message: messages.rejected, - line: 2, - column: 5, - }, - ], - }, - { - code: '@media screen { ; }', - fixed: '@media screen { }', - message: messages.rejected, - line: 1, - column: 17, - }, - { - code: '@media screen { ;a { color: red; } }', - fixed: '@media screen { a { color: red; } }', - message: messages.rejected, - line: 1, - column: 17, - }, - { - code: '@media screen { a { color: red; }; }', - fixed: '@media screen { a { color: red; } }', - message: messages.rejected, - line: 1, - column: 34, - }, - { - code: '@media screen { };', - fixed: '@media screen { }', - message: messages.rejected, - line: 1, - column: 18, - }, - { - code: ';@media screen { }', - fixed: '@media screen { }', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: ';/* comment */', - fixed: '/* comment */', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: '/* comment */;', - fixed: '/* comment */', - message: messages.rejected, - line: 1, - column: 14, - }, - { - code: '/* comment */ ; /*comment */', - fixed: '/* comment */ /*comment */', - message: messages.rejected, - line: 1, - column: 15, - }, - { - code: '/* comment */\n;\n/* comment */', - fixed: '/* comment */\n\n/* comment */', - message: messages.rejected, - line: 2, - column: 1, - }, - { - code: '/* comment */\r\n;\r\n/* comment */', - fixed: '/* comment */\r\n\r\n/* comment */', - message: messages.rejected, - line: 2, - column: 1, - }, - { - code: '/* comment */\t;\t/* comment */', - fixed: '/* comment */\t\t/* comment */', - message: messages.rejected, - line: 1, - column: 15, - }, - { - code: 'a {;/*c*/;/*c*/; color: red;; }', - fixed: 'a {/*c*//*c*/ color: red; }', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 29, - }, - { - message: messages.rejected, - line: 1, - column: 4, - }, - { - message: messages.rejected, - line: 1, - column: 10, - }, - { - message: messages.rejected, - line: 1, - column: 16, - }, - ], - }, - { - code: 'a { color: red;; }', - fixed: 'a { color: red; }', - message: messages.rejected, - line: 1, - column: 16, - }, - { - code: 'a { color: red; ; }', - fixed: 'a { color: red; }', - message: messages.rejected, - line: 1, - column: 17, - }, - { - code: 'a { color: red; ; }', - fixed: 'a { color: red; }', - message: messages.rejected, - line: 1, - column: 18, - }, - { - code: 'a { color: red;\n; }', - fixed: 'a { color: red;\n }', - message: messages.rejected, - line: 2, - column: 1, - }, - { - code: 'a { color: red;\n\n; }', - fixed: 'a { color: red;\n\n }', - message: messages.rejected, - line: 3, - column: 1, - }, - { - code: 'a { color: red;\r\n; }', - fixed: 'a { color: red;\r\n }', - message: messages.rejected, - line: 2, - column: 1, - }, - { - code: 'a { color: red;\r\n\r\n; }', - fixed: 'a { color: red;\r\n\r\n }', - message: messages.rejected, - line: 3, - column: 1, - }, - { - code: 'a { color: red;\t; }', - fixed: 'a { color: red;\t }', - message: messages.rejected, - line: 1, - column: 17, - }, - { - code: 'a { color: red;\t\t; }', - fixed: 'a { color: red;\t\t }', - message: messages.rejected, - line: 1, - column: 18, - }, - { - code: 'a { color: red ;; }', - fixed: 'a { color: red ; }', - message: messages.rejected, - line: 1, - column: 17, - }, - { - code: 'a { color: red ;; }', - fixed: 'a { color: red ; }', - message: messages.rejected, - line: 1, - column: 18, - }, - { - code: 'a { color: red ;; }', - fixed: 'a { color: red ; }', - message: messages.rejected, - line: 1, - column: 19, - }, - { - code: 'a { color: red\n;; }', - fixed: 'a { color: red\n; }', - message: messages.rejected, - line: 2, - column: 2, - }, - { - code: 'a { color: red\n\n;; }', - fixed: 'a { color: red\n\n; }', - message: messages.rejected, - line: 3, - column: 2, - }, - { - code: 'a { color: red\r\n;; }', - fixed: 'a { color: red\r\n; }', - message: messages.rejected, - line: 2, - column: 2, - }, - { - code: 'a { color: red\r\n\r\n;; }', - fixed: 'a { color: red\r\n\r\n; }', - message: messages.rejected, - line: 3, - column: 2, - }, - { - code: 'a { color: red\t;; }', - fixed: 'a { color: red\t; }', - message: messages.rejected, - line: 1, - column: 17, - }, - { - code: 'a { color: red;\t\t; }', - fixed: 'a { color: red;\t\t }', - message: messages.rejected, - line: 1, - column: 18, - }, - { - code: 'a {\n color: #FFF;;\n /* foo */\n /* bar */\n}', - fixed: 'a {\n color: #FFF;\n /* foo */\n /* bar */\n}', - message: messages.rejected, - line: 2, - column: 15, - }, - { - code: 'a {\n /* foo */\n /* bar */\n color: #FFF;;\n}', - fixed: 'a {\n /* foo */\n /* bar */\n color: #FFF;\n}', - message: messages.rejected, - line: 4, - column: 15, - }, - { - code: 'a {\n /* foo */\n color: #FFF;;\n /* bar */\n}', - fixed: 'a {\n /* foo */\n color: #FFF;\n /* bar */\n}', - message: messages.rejected, - line: 3, - column: 15, - }, - { - code: "@import 'x.css';;", - fixed: "@import 'x.css';", - message: messages.rejected, - line: 1, - column: 17, - }, - { - code: "@import 'x.css'; ;", - fixed: "@import 'x.css'; ", - message: messages.rejected, - line: 1, - column: 18, - }, - { - code: "@import 'x.css'; ;", - fixed: "@import 'x.css'; ", - message: messages.rejected, - line: 1, - column: 19, - }, - { - code: "@import 'x.css';\n;", - fixed: "@import 'x.css';\n", - message: messages.rejected, - line: 2, - column: 1, - }, - { - code: "@import 'x.css';\n\n;", - fixed: "@import 'x.css';\n\n", - message: messages.rejected, - line: 3, - column: 1, - }, - { - code: "@import 'x.css';\r\n;", - fixed: "@import 'x.css';\r\n", - message: messages.rejected, - line: 2, - column: 1, - }, - { - code: "@import 'x.css';\r\n\r\n;", - fixed: "@import 'x.css';\r\n\r\n", - message: messages.rejected, - line: 3, - column: 1, - }, - { - code: "@import 'x.css';\t;", - fixed: "@import 'x.css';\t", - message: messages.rejected, - line: 1, - column: 18, - }, - { - code: 'div a {\n float: left;\n}\ndiv {\n float: left;;\n}', - fixed: 'div a {\n float: left;\n}\ndiv {\n float: left;\n}', - message: messages.rejected, - line: 5, - column: 15, - }, - { - code: 'div a {\n float: left;\n}\ndiv {\n float: left; ;\n}', - fixed: 'div a {\n float: left;\n}\ndiv {\n float: left; \n}', - message: messages.rejected, - line: 5, - column: 17, - }, - { - code: 'div a {\n float: left;\n}\ndiv {\n float: left;\n;\n}', - fixed: 'div a {\n float: left;\n}\ndiv {\n float: left;\n\n}', - message: messages.rejected, - line: 6, - column: 1, - }, - { - code: ':root { --foo: red;; --bar: blue; }', - fixed: ':root { --foo: red; --bar: blue; }', - message: messages.rejected, - line: 1, - column: 20, - }, - { - code: ':root { --foo: red; --bar: blue;; }', - fixed: ':root { --foo: red; --bar: blue; }', - message: messages.rejected, - line: 1, - column: 33, - }, - { - code: ':root {; --foo: { color: red }; --bar: { color: blue }; --bar-foo: { color: red }; }', - fixed: ':root { --foo: { color: red }; --bar: { color: blue }; --bar-foo: { color: red }; }', - message: messages.rejected, - line: 1, - column: 8, - }, - { - code: ':root { --foo: { color: red };; --bar: { color: blue }; --bar-foo: { color: red }; }', - fixed: ':root { --foo: { color: red }; --bar: { color: blue }; --bar-foo: { color: red }; }', - message: messages.rejected, - line: 1, - column: 31, - }, - { - code: ':root { --foo: { color: red }; --bar: { color: blue };; --bar-foo: { color: red }; }', - fixed: ':root { --foo: { color: red }; --bar: { color: blue }; --bar-foo: { color: red }; }', - message: messages.rejected, - line: 1, - column: 55, - }, - { - code: ':root { --foo: { color: red };/* comment */;}', - fixed: ':root { --foo: { color: red };/* comment */}', - message: messages.rejected, - line: 1, - column: 44, - }, - { - code: ':root { --foo: { color: red };/* comment */;/* comment */}', - fixed: ':root { --foo: { color: red };/* comment *//* comment */}', - message: messages.rejected, - line: 1, - column: 44, - }, - { - code: ':root { --foo: { color: red };/* comment */; --bar: { color: blue }; --bar-foo: { color: red }; }', - fixed: - ':root { --foo: { color: red };/* comment */ --bar: { color: blue }; --bar-foo: { color: red }; }', - message: messages.rejected, - line: 1, - column: 44, - }, - { - code: ':root { --foo: { color: red }; --bar: { color: blue };/* comment 1 */ /* comment 2 */; --bar-foo: { color: red }; }', - fixed: - ':root { --foo: { color: red }; --bar: { color: blue };/* comment 1 */ /* comment 2 */ --bar-foo: { color: red }; }', - message: messages.rejected, - line: 1, - column: 86, - }, - { - code: ':root { --foo: { color: red }; --bar: { color: blue }/* comment 1 */; /* comment 2 */; --bar-foo: { color: red }; }', - fixed: - ':root { --foo: { color: red }; --bar: { color: blue }/* comment 1 */; /* comment 2 */ --bar-foo: { color: red }; }', - message: messages.rejected, - line: 1, - column: 86, - }, - { - code: ':root { --foo: { color: red }; --bar: { color: blue }; --bar-foo: { color: red };; }', - fixed: ':root { --foo: { color: red }; --bar: { color: blue }; --bar-foo: { color: red }; }', - message: messages.rejected, - line: 1, - column: 82, - }, - { - code: 'a { --foo: { color: red }; --bar: { color: blue }; --bar-foo: { color: red };; }', - fixed: 'a { --foo: { color: red }; --bar: { color: blue }; --bar-foo: { color: red }; }', - message: messages.rejected, - line: 1, - column: 78, - }, - ], -}); - -testRule({ - ruleName, - config: [true], - customSyntax: 'postcss-html', - fix: true, - - accept: [ - { - code: `
- -
`, - }, - ], - - reject: [ - { - code: `
- -
`, - fixed: `
- -
`, - message: messages.rejected, - line: 3, - column: 1, - }, - { - code: `
- -
`, - fixed: `
- -
`, - message: messages.rejected, - line: 4, - column: 14, - }, - ], -}); - -testRule({ - ruleName, - config: [true], - customSyntax: 'postcss-less', - fix: true, - - accept: [ - { - code: "@import 'x.css';", - }, - { - code: 'a { .mixin(); .mixin2; }', - }, - { - code: 'a { .mixin();; .mixin2;; }', - description: 'ignore less mixins', - }, - ], - - reject: [ - { - code: 'a { .mixin();\ncolor: red;; }', - fixed: 'a { .mixin();\ncolor: red; }', - message: messages.rejected, - line: 2, - column: 12, - }, - ], -}); diff --git a/lib/rules/no-extra-semicolons/index.js b/lib/rules/no-extra-semicolons/index.js deleted file mode 100644 index eba41e3a46..0000000000 --- a/lib/rules/no-extra-semicolons/index.js +++ /dev/null @@ -1,244 +0,0 @@ -'use strict'; - -const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule'); -const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const styleSearch = require('style-search'); -const validateOptions = require('../../utils/validateOptions'); -const { isAtRule } = require('../../utils/typeGuards'); - -const ruleName = 'no-extra-semicolons'; - -const messages = ruleMessages(ruleName, { - rejected: 'Unexpected extra semicolon', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/no-extra-semicolons', - fixable: true, - deprecated: true, -}; - -/** - * @param {import('postcss').Node} node - * @returns {number} - */ -function getOffsetByNode(node) { - // @ts-expect-error -- TS2339: Property 'document' does not exist on type 'Document | Container' - if (node.parent && node.parent.document) { - return 0; - } - - const root = node.root(); - - if (!root.source) throw new Error('The root node must have a source'); - - if (!node.source) throw new Error('The node must have a source'); - - if (!node.source.start) throw new Error('The source must have a start position'); - - const string = root.source.input.css; - const nodeColumn = node.source.start.column; - const nodeLine = node.source.start.line; - let line = 1; - let column = 1; - let index = 0; - - for (let i = 0; i < string.length; i++) { - if (column === nodeColumn && nodeLine === line) { - index = i; - break; - } - - if (string[i] === '\n') { - column = 1; - line += 1; - } else { - column += 1; - } - } - - return index; -} - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { actual: primary }); - - if (!validOptions) { - return; - } - - if (root.raws.after && root.raws.after.trim().length !== 0) { - const rawAfterRoot = root.raws.after; - - /** @type {number[]} */ - const fixSemiIndices = []; - - styleSearch({ source: rawAfterRoot, target: ';' }, (match) => { - if (context.fix) { - fixSemiIndices.push(match.startIndex); - - return; - } - - if (!root.source) throw new Error('The root node must have a source'); - - complain(root.source.input.css.length - rawAfterRoot.length + match.startIndex); - }); - - // fix - if (fixSemiIndices.length) { - root.raws.after = removeIndices(rawAfterRoot, fixSemiIndices); - } - } - - root.walk((node) => { - if (isAtRule(node) && !isStandardSyntaxAtRule(node)) { - return; - } - - if (node.type === 'rule' && !isStandardSyntaxRule(node)) { - return; - } - - if (node.raws.before && node.raws.before.trim().length !== 0) { - const rawBeforeNode = node.raws.before; - const allowedSemi = 0; - - const rawBeforeIndexStart = 0; - - /** @type {number[]} */ - const fixSemiIndices = []; - - styleSearch({ source: rawBeforeNode, target: ';' }, (match, count) => { - if (count === allowedSemi) { - return; - } - - if (context.fix) { - fixSemiIndices.push(match.startIndex - rawBeforeIndexStart); - - return; - } - - complain(getOffsetByNode(node) - rawBeforeNode.length + match.startIndex); - }); - - // fix - if (fixSemiIndices.length) { - node.raws.before = removeIndices(rawBeforeNode, fixSemiIndices); - } - } - - if (typeof node.raws.after === 'string' && node.raws.after.trim().length !== 0) { - const rawAfterNode = node.raws.after; - - /** - * If the last child is a Less mixin followed by more than one semicolon, - * node.raws.after will be populated with that semicolon. - * Since we ignore Less mixins, exit here - */ - if ( - 'last' in node && - node.last && - node.last.type === 'atrule' && - !isStandardSyntaxAtRule(node.last) - ) { - return; - } - - /** @type {number[]} */ - const fixSemiIndices = []; - - styleSearch({ source: rawAfterNode, target: ';' }, (match) => { - if (context.fix) { - fixSemiIndices.push(match.startIndex); - - return; - } - - const index = - getOffsetByNode(node) + - node.toString().length - - 1 - - rawAfterNode.length + - match.startIndex; - - complain(index); - }); - - // fix - if (fixSemiIndices.length) { - node.raws.after = removeIndices(rawAfterNode, fixSemiIndices); - } - } - - if (typeof node.raws.ownSemicolon === 'string') { - const rawOwnSemicolon = node.raws.ownSemicolon; - const allowedSemi = 0; - - /** @type {number[]} */ - const fixSemiIndices = []; - - styleSearch({ source: rawOwnSemicolon, target: ';' }, (match, count) => { - if (count === allowedSemi) { - return; - } - - if (context.fix) { - fixSemiIndices.push(match.startIndex); - - return; - } - - const index = - getOffsetByNode(node) + - node.toString().length - - rawOwnSemicolon.length + - match.startIndex; - - complain(index); - }); - - // fix - if (fixSemiIndices.length) { - node.raws.ownSemicolon = removeIndices(rawOwnSemicolon, fixSemiIndices); - } - } - }); - - /** - * @param {number} index - */ - function complain(index) { - report({ - message: messages.rejected, - node: root, - index, - result, - ruleName, - }); - } - - /** - * @param {string} str - * @param {number[]} indices - * @returns {string} - */ - function removeIndices(str, indices) { - for (const index of indices.reverse()) { - str = str.slice(0, index) + str.slice(index + 1); - } - - return str; - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/no-missing-end-of-source-newline/README.md b/lib/rules/no-missing-end-of-source-newline/README.md deleted file mode 100644 index 4ab3a87293..0000000000 --- a/lib/rules/no-missing-end-of-source-newline/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# no-missing-end-of-source-newline - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Disallow missing end-of-source newlines. - - -```css - a { color: pink; } - \n -/** ↑ - * This newline */ -``` - -Completely empty files are not considered problems. - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -### `true` - -The following patterns are considered problems: - - -```css -a { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { color: pink; } -\n -``` diff --git a/lib/rules/no-missing-end-of-source-newline/__tests__/index.js b/lib/rules/no-missing-end-of-source-newline/__tests__/index.js deleted file mode 100644 index c58e981f8c..0000000000 --- a/lib/rules/no-missing-end-of-source-newline/__tests__/index.js +++ /dev/null @@ -1,144 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: [true], - fix: true, - - accept: [ - { - code: '', - }, - { - code: '\n', - }, - { - code: 'a { color: pink; }\n', - }, - { - code: 'a { color: pink; }\r\n', - }, - { - code: 'a { color: pink; }\n\n\n', - }, - { - code: 'a { color: pink; }\r\n\r\n\r\n', - }, - ], - - reject: [ - { - code: 'a { color: pink; }', - fixed: 'a { color: pink; }\n', - message: messages.rejected, - line: 1, - column: 18, - }, - { - code: 'a { color: pink; }\n\n\nb{ color: orange; }', - fixed: 'a { color: pink; }\n\n\nb{ color: orange; }\n', - message: messages.rejected, - line: 4, - column: 19, - }, - { - code: 'a { color: pink; }\r\n\r\n\r\nb{ color: orange; }', - fixed: 'a { color: pink; }\r\n\r\n\r\nb{ color: orange; }\r\n', - message: messages.rejected, - line: 4, - column: 19, - }, - { - code: '&.active {\n top:\n .tab {}\n}', - fixed: '&.active {\n top:\n .tab {}\n}\n', - message: messages.rejected, - line: 4, - column: 1, - }, - { - code: '&.active {\r\n top:\r\n .tab {}\r\n}', - fixed: '&.active {\r\n top:\r\n .tab {}\r\n}\r\n', - message: messages.rejected, - line: 4, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: [true], - customSyntax: 'postcss-html', - - accept: [ - { - code: `
- - -
`, - }, - { - code: '', - }, - ], - - reject: [ - { - code: `
- - -
`, - message: messages.rejected, - line: 4, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: [true], - customSyntax: 'sugarss', - fix: true, - - accept: [ - { - code: 'a\n', - }, - { - code: 'a\r\n', - }, - ], - - reject: [ - { - code: 'a', - fixed: 'a\n', - message: messages.rejected, - line: 1, - column: 1, - }, - { - code: 'body\n padding: 5% 2% 5%', - fixed: 'body\n padding: 5% 2% 5%\n', - message: messages.rejected, - line: 2, - column: 17, - }, - { - code: 'body\r\n padding: 5% 2% 5%', - fixed: 'body\r\n padding: 5% 2% 5%\r\n', - message: messages.rejected, - line: 2, - column: 17, - }, - ], -}); diff --git a/lib/rules/no-missing-end-of-source-newline/index.js b/lib/rules/no-missing-end-of-source-newline/index.js deleted file mode 100644 index 10c576afc0..0000000000 --- a/lib/rules/no-missing-end-of-source-newline/index.js +++ /dev/null @@ -1,63 +0,0 @@ -'use strict'; - -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'no-missing-end-of-source-newline'; - -const messages = ruleMessages(ruleName, { - rejected: 'Unexpected missing end-of-source newline', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/no-missing-end-of-source-newline', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { actual: primary }); - - if (!validOptions) { - return; - } - - if (root.source == null) { - throw new Error('The root node must have a source property'); - } - - // @ts-expect-error -- TS2339: Property 'inline' does not exist on type 'Source'. - if (root.source.inline || root.source.lang === 'object-literal') { - return; - } - - const rootString = context.fix ? root.toString() : root.source.input.css; - - if (!rootString.trim() || rootString.endsWith('\n')) { - return; - } - - // Fix - if (context.fix) { - root.raws.after = context.newline; - - return; - } - - report({ - message: messages.rejected, - node: root, - index: rootString.length - 1, - result, - ruleName, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/number-leading-zero/README.md b/lib/rules/number-leading-zero/README.md deleted file mode 100644 index ec9d7d8d3e..0000000000 --- a/lib/rules/number-leading-zero/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# number-leading-zero - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require or disallow a leading zero for fractional numbers less than 1. - - -```css -a { line-height: 0.5; } -/** ↑ - * This leading zero */ -``` - -This rule ignores mixin parameters in Less. - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a leading zero. - -The following patterns are considered problems: - - -```css -a { line-height: .5; } -``` - - -```css -a { transform: translate(2px, .4px); } -``` - -The following patterns are _not_ considered problems: - - -```css -a { line-height: 0.5; } -``` - - -```css -a { transform: translate(2px, 0.4px); } -``` - -### `"never"` - -There _must never_ be a leading zero. - -The following patterns are considered problems: - - -```css -a { line-height: 0.5; } -``` - - -```css -a { transform: translate(2px, 0.4px); } -``` - -The following patterns are _not_ considered problems: - - -```css -a { line-height: .5; } -``` - - -```css -a { transform: translate(2px, .4px); } -``` diff --git a/lib/rules/number-leading-zero/__tests__/index.js b/lib/rules/number-leading-zero/__tests__/index.js deleted file mode 100644 index 596f25edd7..0000000000 --- a/lib/rules/number-leading-zero/__tests__/index.js +++ /dev/null @@ -1,347 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - accept: [ - { - code: 'a { margin: 0; }', - description: 'plain zero', - }, - { - code: 'a { line-height: 2; }', - description: 'plain integer', - }, - { - code: 'a { margin: 2px; }', - description: 'integer with units', - }, - { - code: 'a { line-height: 0.5; }', - description: 'unitless fractional value with leading zero', - }, - { - code: 'a { line-height: -0.5; }', - description: 'negative unitless fractional value with leading zero', - }, - { - code: 'a { margin: 0.5px; }', - description: 'fractional value with `px` units with leading zero', - }, - { - code: 'a { margin: 0.5em; }', - description: 'fractional value with `em` units with leading zero', - }, - { - code: 'a { line-height: 1.5; }', - description: 'unitless fractional value greater than 1', - }, - { - code: 'a { margin: 1.5px; }', - description: 'fractional value greater than 1 with units', - }, - { - code: 'a { line-height: 10.5; }', - description: 'unitless fractional value greater than 1 with a zero before the decimal', - }, - { - code: 'a { margin: 10.5px; }', - description: 'fractional value greater than 1 with a zero before the decimal and units', - }, - { - code: 'a { margin: 0.3em 0.123px 0.999999px; }', - description: 'multiple fractional values with leading zeros', - }, - { - code: 'a { transform: translate(0.4px, 0.8px); }', - description: 'multiple fractional values with leading zeros in a function', - }, - { - code: '@media (min-width: 0.01em)', - description: 'media feature', - }, - { - code: 'a { background: url(data:image/svg+xml;...0.5); }', - description: 'data URI containing leading zero', - }, - { - code: 'a { background: uRl(data:image/svg+xml;...0.5); }', - description: 'data URI containing leading zero', - }, - { - code: 'a { background: URL(data:image/svg+xml;...0.5); }', - description: 'data URI containing leading zero', - }, - { - code: "@import 'testfile.0.3.css'", - description: 'ignore @import at-rules', - }, - { - code: "@iMpOrT 'testfile.0.3.css'", - description: 'ignore @import at-rules', - }, - { - code: "@IMPORT 'testfile.0.3.css'", - description: 'ignore @import at-rules', - }, - { - code: 'a { margin: 0.5em /*.6em*/ 0.7em; }', - description: 'should ignore comments', - }, - { - code: 'a::before { content: ".9em"; }', - description: 'should ignore strings', - }, - { - code: 'a { my-string: ".1"; }', - description: "ignore all strings rather than only in 'content'", - }, - ], - - reject: [ - { - code: 'a { line-height: .5; }', - fixed: 'a { line-height: 0.5; }', - description: 'unitless fractional value without leading zero', - message: messages.expected, - line: 1, - column: 18, - }, - { - code: 'a { line-height: -.5; }', - fixed: 'a { line-height: -0.5; }', - description: 'negative unitless fractional value without leading zero', - message: messages.expected, - line: 1, - column: 19, - }, - { - code: 'a { margin: .5px; }', - fixed: 'a { margin: 0.5px; }', - description: 'fractional value with units without leading zero', - message: messages.expected, - line: 1, - column: 13, - }, - { - code: 'a { margin: 1px .5px; }', - fixed: 'a { margin: 1px 0.5px; }', - description: 'fractional value without leading zero in the middle of a list', - message: messages.expected, - line: 1, - column: 17, - }, - { - code: 'a { transform: translate(.4px, 2px); }', - fixed: 'a { transform: translate(0.4px, 2px); }', - description: 'fractional value without leading zero at the beginning of a function', - message: messages.expected, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate(2px, .4px); }', - fixed: 'a { transform: translate(2px, 0.4px); }', - description: 'fractional value without leading zero in the middle of a function', - message: messages.expected, - line: 1, - column: 31, - }, - { - code: 'a { transform: translate(.4px, .8px); }', - fixed: 'a { transform: translate(0.4px, 0.8px); }', - description: 'multiple fractional values without leading zeros in a function', - warnings: [ - { - message: messages.expected, - line: 1, - column: 26, - }, - { - message: messages.expected, - line: 1, - column: 32, - }, - ], - }, - { - code: '@media (min-width: .01em)', - fixed: '@media (min-width: 0.01em)', - description: 'media feature', - message: messages.expected, - line: 1, - column: 20, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - accept: [ - { - code: 'a { margin: 0; }', - description: 'plain zero', - }, - { - code: 'a { line-height: 2; }', - description: 'plain integer', - }, - { - code: 'a { margin: 2px; }', - description: 'integer with units', - }, - { - code: 'a { line-height: .5; }', - description: 'unitless fractional value without leading zero', - }, - { - code: 'a { line-height: -.5; }', - description: 'negative unitless fractional value without leading zero', - }, - { - code: 'a { margin: .5px; }', - description: 'fractional value with `px` units without leading zero', - }, - { - code: 'a { margin: .5em; }', - description: 'fractional value with `em` units without leading zero', - }, - { - code: 'a { line-height: 1.5; }', - description: 'unitless fractional value greater than 1', - }, - { - code: 'a { margin: 1.5px; }', - description: 'fractional value greater than 1 with units', - }, - { - code: 'a { line-height: 10.5; }', - description: 'unitless fractional value greater than 1 with a zero before the decimal', - }, - { - code: 'a { margin: 10.5px; }', - description: 'fractional value greater than 1 with a zero before the decimal and units', - }, - { - code: 'a { margin: .3em .123px .999999px; }', - description: 'multiple fractional values without leading zeros', - }, - { - code: 'a { transform: translate(.4px, .8px); }', - description: 'multiple fractional values without leading zeros in a function', - }, - { - code: 'a { background: url(data:image/svg+xml;...0.5); }', - description: 'data URI containing leading zero', - }, - { - code: 'a { background: uRl(data:image/svg+xml;...0.5); }', - description: 'data URI containing leading zero', - }, - { - code: 'a { background: URL(data:image/svg+xml;...0.5); }', - description: 'data URI containing leading zero', - }, - { - code: "@import 'testfile.0.3.css'", - description: 'ignore @import at-rules', - }, - { - code: "@iMpOrT 'testfile.0.3.css'", - description: 'ignore @import at-rules', - }, - { - code: "@IMPORT 'testfile.0.3.css'", - description: 'ignore @import at-rules', - }, - ], - - reject: [ - { - code: 'a { line-height: 0.5; }', - fixed: 'a { line-height: .5; }', - description: 'unitless fractional value with leading zero', - message: messages.rejected, - line: 1, - column: 18, - }, - { - code: 'a { line-height: -0.5; }', - fixed: 'a { line-height: -.5; }', - description: 'negative unitless fractional value with leading zero', - message: messages.rejected, - line: 1, - column: 19, - }, - { - code: 'a { margin: 0.5px; }', - fixed: 'a { margin: .5px; }', - description: 'fractional value with units with leading zero', - message: messages.rejected, - line: 1, - column: 13, - }, - { - code: 'a { margin: 1px 0.5px; }', - fixed: 'a { margin: 1px .5px; }', - description: 'fractional value with leading zero in the middle of a list', - message: messages.rejected, - line: 1, - column: 17, - }, - { - code: 'a { transform: translate(0.4px, 2px); }', - fixed: 'a { transform: translate(.4px, 2px); }', - description: 'fractional value with leading zero at the beginning of a function', - message: messages.rejected, - line: 1, - column: 26, - }, - { - code: 'a { transform: translate(2px, 0.8px); }', - fixed: 'a { transform: translate(2px, .8px); }', - description: 'fractional value with leading zero in the middle of a function', - message: messages.rejected, - line: 1, - column: 31, - }, - { - code: 'a { transform: translate(0.4px, 0.8px); }', - fixed: 'a { transform: translate(.4px, .8px); }', - description: 'multiple fractional values with leading zeros in a function', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 26, - }, - { - message: messages.rejected, - line: 1, - column: 33, - }, - ], - }, - { - code: 'a { line-height: 000.5; }', - fixed: 'a { line-height: .5; }', - description: 'multiple leading zeros', - message: messages.rejected, - line: 1, - column: 18, - }, - { - code: '@media (min-width: 0.01em)', - fixed: '@media (min-width: .01em)', - description: 'media feature', - message: messages.rejected, - line: 1, - column: 20, - }, - ], -}); diff --git a/lib/rules/number-leading-zero/index.js b/lib/rules/number-leading-zero/index.js deleted file mode 100644 index 82ccc2ed76..0000000000 --- a/lib/rules/number-leading-zero/index.js +++ /dev/null @@ -1,197 +0,0 @@ -'use strict'; - -const valueParser = require('postcss-value-parser'); - -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const { isAtRule } = require('../../utils/typeGuards'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'number-leading-zero'; - -const messages = ruleMessages(ruleName, { - expected: 'Expected a leading zero', - rejected: 'Unexpected leading zero', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/number-leading-zero', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - root.walkAtRules((atRule) => { - if (atRule.name.toLowerCase() === 'import') { - return; - } - - check(atRule, atRule.params); - }); - - root.walkDecls((decl) => check(decl, decl.value)); - - /** - * @param {import('postcss').AtRule | import('postcss').Declaration} node - * @param {string} value - */ - function check(node, value) { - /** @type {Array<{ startIndex: number, endIndex: number }>} */ - const neverFixPositions = []; - /** @type {Array<{ index: number }>} */ - const alwaysFixPositions = []; - - // Get out quickly if there are no periods - if (!value.includes('.')) { - return; - } - - valueParser(value).walk((valueNode) => { - // Ignore `url` function - if (valueNode.type === 'function' && valueNode.value.toLowerCase() === 'url') { - return false; - } - - // Ignore strings, comments, etc - if (valueNode.type !== 'word') { - return; - } - - // Check leading zero - if (primary === 'always') { - const match = /(?:\D|^)(\.\d+)/.exec(valueNode.value); - - if (match == null || match[0] == null || match[1] == null) { - return; - } - - // The regexp above consists of 2 capturing groups (or capturing parentheses). - // We need the index of the second group. This makes sanse when we have "-.5" as an input - // for regex. And we need the index of ".5". - const capturingGroupIndex = match[0].length - match[1].length; - - const index = valueNode.sourceIndex + match.index + capturingGroupIndex; - - if (context.fix) { - alwaysFixPositions.unshift({ - index, - }); - - return; - } - - const baseIndex = isAtRule(node) ? atRuleParamIndex(node) : declarationValueIndex(node); - - complain(messages.expected, node, baseIndex + index); - } - - if (primary === 'never') { - const match = /(?:\D|^)(0+)(\.\d+)/.exec(valueNode.value); - - if (match == null || match[0] == null || match[1] == null || match[2] == null) { - return; - } - - // The regexp above consists of 3 capturing groups (or capturing parentheses). - // We need the index of the second group. This makes sanse when we have "-00.5" - // as an input for regex. And we need the index of "00". - const capturingGroupIndex = match[0].length - (match[1].length + match[2].length); - - const index = valueNode.sourceIndex + match.index + capturingGroupIndex; - - if (context.fix) { - neverFixPositions.unshift({ - startIndex: index, - // match[1].length is the length of our matched zero(s) - endIndex: index + match[1].length, - }); - - return; - } - - const baseIndex = isAtRule(node) ? atRuleParamIndex(node) : declarationValueIndex(node); - - complain(messages.rejected, node, baseIndex + index); - } - }); - - if (alwaysFixPositions.length) { - for (const fixPosition of alwaysFixPositions) { - const index = fixPosition.index; - - if (isAtRule(node)) { - node.params = addLeadingZero(node.params, index); - } else { - node.value = addLeadingZero(node.value, index); - } - } - } - - if (neverFixPositions.length) { - for (const fixPosition of neverFixPositions) { - const startIndex = fixPosition.startIndex; - const endIndex = fixPosition.endIndex; - - if (isAtRule(node)) { - node.params = removeLeadingZeros(node.params, startIndex, endIndex); - } else { - node.value = removeLeadingZeros(node.value, startIndex, endIndex); - } - } - } - } - - /** - * @param {string} message - * @param {import('postcss').Node} node - * @param {number} index - */ - function complain(message, node, index) { - report({ - result, - ruleName, - message, - node, - index, - }); - } - }; -}; - -/** - * @param {string} input - * @param {number} index - * @returns {string} - */ -function addLeadingZero(input, index) { - // eslint-disable-next-line prefer-template - return input.slice(0, index) + '0' + input.slice(index); -} - -/** - * @param {string} input - * @param {number} startIndex - * @param {number} endIndex - * @returns {string} - */ -function removeLeadingZeros(input, startIndex, endIndex) { - return input.slice(0, startIndex) + input.slice(endIndex); -} - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/number-no-trailing-zeros/README.md b/lib/rules/number-no-trailing-zeros/README.md deleted file mode 100644 index 49ca157953..0000000000 --- a/lib/rules/number-no-trailing-zeros/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# number-no-trailing-zeros - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Disallow trailing zeros in numbers. - - -```css -a { top: 0.5000px; bottom: 1.0px; } -/** ↑ ↑ - * These trailing zeros */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix some of the problems reported by this rule. - -## Options - -### `true` - -The following patterns are considered problems: - - -```css -a { top: 1.0px } -``` - - -```css -a { top: 1.01000px } -``` - -The following patterns are _not_ considered problems: - - -```css -a { top: 1px } -``` - - -```css -a { top: 1.01px } -``` diff --git a/lib/rules/number-no-trailing-zeros/__tests__/index.js b/lib/rules/number-no-trailing-zeros/__tests__/index.js deleted file mode 100644 index 621b2bfb45..0000000000 --- a/lib/rules/number-no-trailing-zeros/__tests__/index.js +++ /dev/null @@ -1,181 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: [true], - fix: true, - accept: [ - { - code: 'a { padding: 1px; }', - }, - { - code: 'a { padding: 10px; }', - }, - { - code: 'a { padding: 10.01px; }', - }, - { - code: 'a { padding: 10px 1px 1.05px 3.00003em; }', - }, - { - code: 'a { padding: 0.01px; }', - }, - { - code: 'a { padding: .01px; }', - }, - { - code: '@media (min-width: 100px) {}', - }, - { - code: '@import "0.10.css";', - }, - { - code: '@iMpOrT "0.10.css";', - }, - { - code: '@IMPORT "0.10.css";', - }, - { - code: '@import url(0.10.css);', - }, - { - code: 'a { background: url(data:image/svg+xml;...1.0); }', - description: 'data URI containing trailing zero', - }, - { - code: 'a { background: uRl(data:image/svg+xml;...1.0); }', - description: 'data URI containing trailing zero', - }, - { - code: 'a { background: URL(data:image/svg+xml;...1.0); }', - description: 'data URI containing trailing zero', - }, - { - code: 'a { margin: 0.5em /* 1.600em */ 0.7em; }', - description: 'should ignore comments', - }, - { - code: 'a::before { content: ".90em"; }', - description: 'should ignore strings', - }, - { - code: 'a { my-string: "1.00"; }', - description: "ignore all strings rather than only in 'content'", - }, - ], - - reject: [ - { - code: 'a { padding: 1.0px; }', - fixed: 'a { padding: 1px; }', - message: messages.rejected, - line: 1, - column: 16, - }, - { - code: 'a { padding: 1.000px; }', - fixed: 'a { padding: 1px; }', - message: messages.rejected, - line: 1, - column: 16, - }, - { - code: 'a { padding: 10.0px; }', - fixed: 'a { padding: 10px; }', - message: messages.rejected, - line: 1, - column: 17, - }, - { - code: 'a { padding: 10.010px; }', - fixed: 'a { padding: 10.01px; }', - message: messages.rejected, - line: 1, - column: 19, - }, - { - code: 'a { padding: 0.010px; }', - fixed: 'a { padding: 0.01px; }', - message: messages.rejected, - line: 1, - column: 18, - }, - { - code: 'a { padding: .010px; }', - fixed: 'a { padding: .01px; }', - message: messages.rejected, - line: 1, - column: 17, - }, - { - code: 'a { transform: translate(2px, 0.40px); }', - fixed: 'a { transform: translate(2px, 0.4px); }', - message: messages.rejected, - line: 1, - column: 34, - }, - { - code: 'a { transform: translate(2.0px, 0.40px); }', - fixed: 'a { transform: translate(2px, 0.4px); }', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 28, - }, - { - message: messages.rejected, - line: 1, - column: 36, - }, - ], - }, - { - code: 'a { padding: 10px 1px 10.010px 3.00003em; }', - fixed: 'a { padding: 10px 1px 10.01px 3.00003em; }', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 28, - }, - ], - }, - { - code: 'a { padding: 10px 1px 10.01px 3.000030em; }', - fixed: 'a { padding: 10px 1px 10.01px 3.00003em; }', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 38, - }, - ], - }, - { - code: 'a { padding: 10px 1px 10.010px 3.000030em; }', - fixed: 'a { padding: 10px 1px 10.01px 3.00003em; }', - warnings: [ - { - message: messages.rejected, - line: 1, - column: 28, - }, - { - message: messages.rejected, - line: 1, - column: 39, - }, - ], - }, - { - code: '@media (min-width: 100.0px) {}', - fixed: '@media (min-width: 100px) {}', - message: messages.rejected, - line: 1, - column: 24, - }, - ], -}); diff --git a/lib/rules/number-no-trailing-zeros/index.js b/lib/rules/number-no-trailing-zeros/index.js deleted file mode 100644 index 287ce07a4f..0000000000 --- a/lib/rules/number-no-trailing-zeros/index.js +++ /dev/null @@ -1,140 +0,0 @@ -'use strict'; - -const valueParser = require('postcss-value-parser'); - -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const { isAtRule } = require('../../utils/typeGuards'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'number-no-trailing-zeros'; - -const messages = ruleMessages(ruleName, { - rejected: 'Unexpected trailing zero(s)', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/number-no-trailing-zeros', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { actual: primary }); - - if (!validOptions) { - return; - } - - root.walkAtRules((atRule) => { - if (atRule.name.toLowerCase() === 'import') { - return; - } - - check(atRule, atRule.params); - }); - - root.walkDecls((decl) => check(decl, decl.value)); - - /** - * @param {import('postcss').AtRule | import('postcss').Declaration} node - * @param {string} value - */ - function check(node, value) { - /** @type {Array<{ startIndex: number, endIndex: number }>} */ - const fixPositions = []; - - // Get out quickly if there are no periods - if (!value.includes('.')) { - return; - } - - valueParser(value).walk((valueNode) => { - // Ignore `url` function - if (valueNode.type === 'function' && valueNode.value.toLowerCase() === 'url') { - return false; - } - - // Ignore strings, comments, etc - if (valueNode.type !== 'word') { - return; - } - - const match = /\.(\d{0,100}?)(0+)(?:\D|$)/.exec(valueNode.value); - - // match[1] is any numbers between the decimal and our trailing zero, could be empty - // match[2] is our trailing zero(s) - if (match == null || match[1] == null || match[2] == null) { - return; - } - - // our index is: - // the index of our valueNode + - // the index of our match + - // 1 for our decimal + - // the length of our potential non-zero number match (match[1]) - const index = valueNode.sourceIndex + match.index + 1 + match[1].length; - - // our startIndex is identical to our index except when we have only - // trailing zeros after our decimal. in that case we don't need the decimal - // either so we move our index back by 1. - const startIndex = match[1].length > 0 ? index : index - 1; - - // our end index is our original index + the length of our trailing zeros - const endIndex = index + match[2].length; - - if (context.fix) { - fixPositions.unshift({ - startIndex, - endIndex, - }); - - return; - } - - const baseIndex = isAtRule(node) ? atRuleParamIndex(node) : declarationValueIndex(node); - - report({ - message: messages.rejected, - node, - // this is the index of the _first_ trailing zero - index: baseIndex + index, - result, - ruleName, - }); - }); - - if (fixPositions.length) { - for (const fixPosition of fixPositions) { - const startIndex = fixPosition.startIndex; - const endIndex = fixPosition.endIndex; - - if (isAtRule(node)) { - node.params = removeTrailingZeros(node.params, startIndex, endIndex); - } else { - node.value = removeTrailingZeros(node.value, startIndex, endIndex); - } - } - } - } - }; -}; - -/** - * @param {string} input - * @param {number} startIndex - * @param {number} endIndex - * @returns {string} - */ -function removeTrailingZeros(input, startIndex, endIndex) { - return input.slice(0, startIndex) + input.slice(endIndex); -} - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/property-case/README.md b/lib/rules/property-case/README.md deleted file mode 100644 index 0692269ec3..0000000000 --- a/lib/rules/property-case/README.md +++ /dev/null @@ -1,194 +0,0 @@ -# property-case - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Specify lowercase or uppercase for properties. - - -```css - a { width: 1px; } -/** ↑ - * This property */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"lower"|"upper"` - -### `"lower"` - -The following patterns are considered problems: - - -```css -a { - Width: 1px -} -``` - - -```css -a { - WIDTH: 1px -} -``` - - -```css -a { - widtH: 1px -} -``` - - -```css -a { - border-Radius: 5px; -} -``` - - -```css -a { - -WEBKIT-animation-duration: 3s; -} -``` - - -```css -@media screen and (orientation: landscape) { - WiDtH: 500px; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { - width: 1px -} -``` - - -```css -a { - border-radius: 5px; -} -``` - - -```css -a { - -webkit-animation-duration: 3s; -} -``` - - -```css -@media screen and (orientation: landscape) { - width: 500px; -} -``` - -### `"upper"` - -The following patterns are considered problems: - - -```css -a { - Width: 1px -} -``` - - -```css -a { - width: 1px -} -``` - - -```css -a { - widtH: 1px -} -``` - - -```css -a { - border-Radius: 5px; -} -``` - - -```css -a { - -WEBKIT-animation-duration: 3s; -} -``` - - -```css -@media screen and (orientation: landscape) { - WiDtH: 500px; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { - WIDTH: 1px -} -``` - - -```css -a { - BORDER-RADIUS: 5px; -} -``` - - -```css -a { - -WEBKIT-ANIMATION-DURATION: 3s; -} -``` - - -```css -@media screen and (orientation: landscape) { - WIDTH: 500px; -} -``` - -## Optional secondary options - -### `ignoreSelectors: ["/regex/", /regex/, "string"]` - -Given: - -```json -[ - "lower", - { - "ignoreSelectors": [":export"] - } -] -``` - -The following patterns are _not_ considered problems: - - -```css -:export { - camelCase: value; -} -``` diff --git a/lib/rules/property-case/__tests__/index.js b/lib/rules/property-case/__tests__/index.js deleted file mode 100644 index 81e787e7af..0000000000 --- a/lib/rules/property-case/__tests__/index.js +++ /dev/null @@ -1,935 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['lower'], - fix: true, - - accept: [ - { - code: 'a { }', - }, - { - code: 'a { display: block; }', - }, - { - code: 'a { border-radius: 8px; }', - }, - { - code: 'a:hover { display: block; }', - }, - { - code: 'a:focus { display: block; }', - }, - { - code: 'a:other { display: block; }', - }, - { - code: 'a::before { display: block; }', - }, - { - code: 'a::other { display: block; }', - }, - { - code: ':root { --custom-property-set: {} }', - }, - { - code: ':root { --custom-property-name: red; }', - }, - { - code: ':root { --custom-PropertyName: red; }', - }, - { - code: 'a { -webkit-animation-duration: 3s; }', - }, - { - code: '@media screen and (orientation: landscape) { width: 500px; }', - }, - { - code: 'a { property: value; }', - description: 'non-standard property', - }, - ], - - reject: [ - { - code: 'a { Display: block; }', - fixed: 'a { display: block; }', - message: messages.expected('Display', 'display'), - line: 1, - column: 5, - endLine: 1, - endColumn: 12, - }, - { - code: 'a { DisplaY: block; }', - fixed: 'a { display: block; }', - message: messages.expected('DisplaY', 'display'), - line: 1, - column: 5, - endLine: 1, - endColumn: 12, - }, - { - code: 'a { DISPLAY: block; }', - fixed: 'a { display: block; }', - message: messages.expected('DISPLAY', 'display'), - line: 1, - column: 5, - endLine: 1, - endColumn: 12, - }, - { - code: 'a { border-Radius: block; }', - fixed: 'a { border-radius: block; }', - message: messages.expected('border-Radius', 'border-radius'), - line: 1, - column: 5, - endLine: 1, - endColumn: 18, - }, - { - code: 'a { border-RADIUS: block; }', - fixed: 'a { border-radius: block; }', - message: messages.expected('border-RADIUS', 'border-radius'), - line: 1, - column: 5, - endLine: 1, - endColumn: 18, - }, - { - code: 'a { BORDER-radius: block; }', - fixed: 'a { border-radius: block; }', - message: messages.expected('BORDER-radius', 'border-radius'), - line: 1, - column: 5, - endLine: 1, - endColumn: 18, - }, - { - code: 'a { BORDER-RADIUS: block; }', - fixed: 'a { border-radius: block; }', - message: messages.expected('BORDER-RADIUS', 'border-radius'), - line: 1, - column: 5, - endLine: 1, - endColumn: 18, - }, - { - code: 'a { -WEBKIT-animation-duration: 3s; }', - fixed: 'a { -webkit-animation-duration: 3s; }', - message: messages.expected('-WEBKIT-animation-duration', '-webkit-animation-duration'), - line: 1, - column: 5, - endLine: 1, - endColumn: 31, - }, - { - code: 'a { -webkit-Animation-duration: 3s; }', - fixed: 'a { -webkit-animation-duration: 3s; }', - message: messages.expected('-webkit-Animation-duration', '-webkit-animation-duration'), - line: 1, - column: 5, - endLine: 1, - endColumn: 31, - }, - { - code: 'a:hover { Display: block; }', - fixed: 'a:hover { display: block; }', - message: messages.expected('Display', 'display'), - line: 1, - column: 11, - endLine: 1, - endColumn: 18, - }, - { - code: 'a:focus { Display: block; }', - fixed: 'a:focus { display: block; }', - message: messages.expected('Display', 'display'), - line: 1, - column: 11, - endLine: 1, - endColumn: 18, - }, - { - code: 'a:other { Display: block; }', - fixed: 'a:other { display: block; }', - message: messages.expected('Display', 'display'), - line: 1, - column: 11, - endLine: 1, - endColumn: 18, - }, - { - code: 'a::before { Display: block; }', - fixed: 'a::before { display: block; }', - message: messages.expected('Display', 'display'), - line: 1, - column: 13, - endLine: 1, - endColumn: 20, - }, - { - code: 'a::other { Display: block; }', - fixed: 'a::other { display: block; }', - message: messages.expected('Display', 'display'), - line: 1, - column: 12, - endLine: 1, - endColumn: 19, - }, - { - code: '@media screen and (orientation: landscape) { Width: 500px; }', - fixed: '@media screen and (orientation: landscape) { width: 500px; }', - message: messages.expected('Width', 'width'), - line: 1, - column: 46, - endLine: 1, - endColumn: 51, - }, - { - code: 'a { Property: value; }', - fixed: 'a { property: value; }', - description: 'non-standard property', - message: messages.expected('Property', 'property'), - line: 1, - column: 5, - endLine: 1, - endColumn: 13, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-scss', - config: ['lower'], - fix: true, - - accept: [ - { - code: '$width: 5em;', - description: 'ignore variable', - }, - { - code: '$Width: 5em;', - description: 'ignore variable', - }, - { - code: '$map: (width: 100px);', - description: 'ignore map', - }, - { - code: '$map: (Width: 100px);', - description: 'ignore map', - }, - { - code: 'a { font: (italic bold 10px/8px) }', - description: 'list', - }, - { - code: '&-sidebar { border: 1px solid; }', - description: 'referencing parent selectors', - }, - { - code: 'a { font: { size: 30em; } }', - description: 'nested properties', - }, - { - code: 'p.#{$name} { #{$attr}-color: blue; }', - description: 'ignore interpolation', - }, - { - code: 'p.#{$name} { #{$Attr}-color: blue; }', - description: 'ignore interpolation', - }, - { - code: 'p.#{$name} { #{$attr}-Color: blue; }', - description: 'ignore interpolation', - }, - { - code: '#context a%extreme { color: red; }', - description: 'extend only selectors', - }, - { - code: '.parent { @at-root { .child1 { display: block; } } }', - description: 'as-root', - }, - { - code: '@mixin large-text { font-size: 20px; }', - description: 'inside mixin', - }, - { - code: 'p { @if 1 + 1 == 2 { border: 1px solid; } }', - description: 'inside custom at-rule', - }, - ], - - reject: [ - { - code: '&-sidebar { Border: 1px solid; }', - fixed: '&-sidebar { border: 1px solid; }', - description: 'referencing parent selectors', - message: messages.expected('Border', 'border'), - line: 1, - column: 13, - endLine: 1, - endColumn: 19, - }, - { - code: 'a { Font: (italic bold 10px/8px) }', - fixed: 'a { font: (italic bold 10px/8px) }', - message: messages.expected('Font', 'font'), - line: 1, - column: 5, - endLine: 1, - endColumn: 9, - }, - { - code: 'a { font: { Size: 30em; } }', - fixed: 'a { font: { size: 30em; } }', - description: 'nested properties', - message: messages.expected('Size', 'size'), - line: 1, - column: 13, - endLine: 1, - endColumn: 17, - }, - { - code: '#context a%extreme { Color: red; }', - fixed: '#context a%extreme { color: red; }', - description: 'extend only selectors', - message: messages.expected('Color', 'color'), - line: 1, - column: 22, - endLine: 1, - endColumn: 27, - }, - { - code: '.parent { @at-root { .child1 { Display: block; } } }', - fixed: '.parent { @at-root { .child1 { display: block; } } }', - description: 'as-root', - message: messages.expected('Display', 'display'), - line: 1, - column: 32, - endLine: 1, - endColumn: 39, - }, - { - code: '@mixin large-text { Font-size: 20px; }', - fixed: '@mixin large-text { font-size: 20px; }', - description: 'inside mixin', - message: messages.expected('Font-size', 'font-size'), - line: 1, - column: 21, - endLine: 1, - endColumn: 30, - }, - { - code: 'p { @if 1 + 1 == 2 { Border: 1px solid; } }', - fixed: 'p { @if 1 + 1 == 2 { border: 1px solid; } }', - description: 'inside custom at-rule', - message: messages.expected('Border', 'border'), - line: 1, - column: 22, - endLine: 1, - endColumn: 28, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-less', - config: ['lower'], - fix: true, - - accept: [ - { - code: '@variable: 10px', - }, - { - code: '@Variable: 10px', - }, - { - code: '@VARIABLE: 10px', - }, - { - code: 'a { color: @light-blue; }', - }, - { - code: 'a { .bordered; }', - description: 'ignore mixin', - }, - { - code: 'a { .Bordered; }', - description: 'ignore mixin', - }, - { - code: 'a { .Bordered(5px); }', - description: 'ignore mixin', - }, - { - code: '.mixin(@color: black) { color: @color; }', - description: 'inside mixin', - }, - { - code: '.@{my-selector} { font-weight: bold; }', - description: 'with selector interpolation', - }, - { - code: '.widget { @{property}: #0ee; }', - description: 'ignore property interpolation', - }, - { - code: '.widget { @{Property}: #0ee; }', - description: 'ignore property interpolation', - }, - { - code: 'a { box-shadow+: inset 0 0 10px #555; }', - description: 'mergeable property', - }, - { - code: 'a { box-shadow+_: inset 0 0 10px #555; }', - description: 'mergeable property with space', - }, - { - code: '.bucket { tr & { color: blue; } }', - description: 'nested selector', - }, - { - code: 'a { Box-shadow+: inset 0 0 10px #555; }', - description: 'mergeable property', - }, - { - code: 'a { Transform+_: scale(2); }', - description: 'mergeable property with space', - }, - ], - - reject: [ - { - code: 'a { Color: @light-blue; }', - fixed: 'a { color: @light-blue; }', - message: messages.expected('Color', 'color'), - line: 1, - column: 5, - endLine: 1, - endColumn: 10, - }, - { - code: '.@{my-selector} { Font-weight: bold; }', - fixed: '.@{my-selector} { font-weight: bold; }', - description: 'selector interpolation', - message: messages.expected('Font-weight', 'font-weight'), - line: 1, - column: 19, - endLine: 1, - endColumn: 30, - }, - { - code: '.mixin(@color: black) { Color: @color; }', - fixed: '.mixin(@color: black) { color: @color; }', - description: 'inside mixin', - message: messages.expected('Color', 'color'), - line: 1, - column: 25, - endLine: 1, - endColumn: 30, - }, - { - code: '@media screen { @media (min-width: 768px) { Color: red; }}', - fixed: '@media screen { @media (min-width: 768px) { color: red; }}', - description: 'nested directives', - message: messages.expected('Color', 'color'), - line: 1, - column: 45, - endLine: 1, - endColumn: 50, - }, - { - code: '.bucket { tr & { Color: blue; } }', - fixed: '.bucket { tr & { color: blue; } }', - description: 'nested selector', - message: messages.expected('Color', 'color'), - line: 1, - column: 18, - endLine: 1, - endColumn: 23, - }, - ], -}); - -testRule({ - ruleName, - config: ['upper'], - fix: true, - - accept: [ - { - code: 'a { }', - }, - { - code: 'a { DISPLAY: block; }', - }, - { - code: 'a { BORDER-RADIUS: 8px; }', - }, - { - code: 'a:hover { DISPLAY: block; }', - }, - { - code: 'a:focus { DISPLAY: block; }', - }, - { - code: 'a:other { DISPLAY: block; }', - }, - { - code: 'a::before { DISPLAY: block; }', - }, - { - code: 'a::other { DISPLAY: block; }', - }, - { - code: ':root { --custom-property-set: {} }', - }, - { - code: ':root { --custom-property-name: red; }', - }, - { - code: ':root { --custom-PropertyName: red; }', - }, - { - code: 'a { -WEBKIT-ANIMATION-DURATION: 3s; }', - }, - { - code: '@media screen and (orientation: landscape) { WIDTH: 500px; }', - }, - { - code: 'a { PROPERTY: value; }', - description: 'non-standard property', - }, - ], - - reject: [ - { - code: 'a { Display: block; }', - fixed: 'a { DISPLAY: block; }', - message: messages.expected('Display', 'DISPLAY'), - line: 1, - column: 5, - endLine: 1, - endColumn: 12, - }, - { - code: 'a { DisplaY: block; }', - fixed: 'a { DISPLAY: block; }', - message: messages.expected('DisplaY', 'DISPLAY'), - line: 1, - column: 5, - endLine: 1, - endColumn: 12, - }, - { - code: 'a { display: block; }', - fixed: 'a { DISPLAY: block; }', - message: messages.expected('display', 'DISPLAY'), - line: 1, - column: 5, - endLine: 1, - endColumn: 12, - }, - { - code: 'a { border-Radius: block; }', - fixed: 'a { BORDER-RADIUS: block; }', - message: messages.expected('border-Radius', 'BORDER-RADIUS'), - line: 1, - column: 5, - endLine: 1, - endColumn: 18, - }, - { - code: 'a { border-RADIUS: block; }', - fixed: 'a { BORDER-RADIUS: block; }', - message: messages.expected('border-RADIUS', 'BORDER-RADIUS'), - line: 1, - column: 5, - endLine: 1, - endColumn: 18, - }, - { - code: 'a { BORDER-radius: block; }', - fixed: 'a { BORDER-RADIUS: block; }', - message: messages.expected('BORDER-radius', 'BORDER-RADIUS'), - line: 1, - column: 5, - endLine: 1, - endColumn: 18, - }, - { - code: 'a { border-radius: block; }', - fixed: 'a { BORDER-RADIUS: block; }', - message: messages.expected('border-radius', 'BORDER-RADIUS'), - line: 1, - column: 5, - endLine: 1, - endColumn: 18, - }, - { - code: 'a { -WEBKIT-animation-duration: 3s; }', - fixed: 'a { -WEBKIT-ANIMATION-DURATION: 3s; }', - message: messages.expected('-WEBKIT-animation-duration', '-WEBKIT-ANIMATION-DURATION'), - line: 1, - column: 5, - endLine: 1, - endColumn: 31, - }, - { - code: 'a { -webkit-Animation-duration: 3s; }', - fixed: 'a { -WEBKIT-ANIMATION-DURATION: 3s; }', - message: messages.expected('-webkit-Animation-duration', '-WEBKIT-ANIMATION-DURATION'), - line: 1, - column: 5, - endLine: 1, - endColumn: 31, - }, - { - code: 'a:hover { Display: block; }', - fixed: 'a:hover { DISPLAY: block; }', - message: messages.expected('Display', 'DISPLAY'), - line: 1, - column: 11, - endLine: 1, - endColumn: 18, - }, - { - code: 'a:focus { Display: block; }', - fixed: 'a:focus { DISPLAY: block; }', - message: messages.expected('Display', 'DISPLAY'), - line: 1, - column: 11, - endLine: 1, - endColumn: 18, - }, - { - code: 'a:other { Display: block; }', - fixed: 'a:other { DISPLAY: block; }', - message: messages.expected('Display', 'DISPLAY'), - line: 1, - column: 11, - endLine: 1, - endColumn: 18, - }, - { - code: 'a::before { Display: block; }', - fixed: 'a::before { DISPLAY: block; }', - message: messages.expected('Display', 'DISPLAY'), - line: 1, - column: 13, - endLine: 1, - endColumn: 20, - }, - { - code: 'a::other { Display: block; }', - fixed: 'a::other { DISPLAY: block; }', - message: messages.expected('Display', 'DISPLAY'), - line: 1, - column: 12, - endLine: 1, - endColumn: 19, - }, - { - code: '@media screen and (orientation: landscape) { Width: 500px; }', - fixed: '@media screen and (orientation: landscape) { WIDTH: 500px; }', - message: messages.expected('Width', 'WIDTH'), - line: 1, - column: 46, - endLine: 1, - endColumn: 51, - }, - { - code: 'a { Property: value; }', - fixed: 'a { PROPERTY: value; }', - description: 'non-standard property', - message: messages.expected('Property', 'PROPERTY'), - line: 1, - column: 5, - endLine: 1, - endColumn: 13, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-scss', - config: ['upper'], - fix: true, - - accept: [ - { - code: '$width: 5em;', - description: 'ignore variable', - }, - { - code: '$Width: 5em;', - description: 'ignore variable', - }, - { - code: '$map: (width: 100px);', - description: 'ignore map', - }, - { - code: '$map: (Width: 100px);', - description: 'ignore map', - }, - { - code: 'a { FONT: (italic bold 10px/8px) }', - description: 'list', - }, - { - code: '&-sidebar { BORDER: 1px solid; }', - description: 'referencing parent selectors', - }, - { - code: 'a { font: { SIZE: 30em; } }', - description: 'nested properties', - }, - { - code: 'p.#{$name} { #{$attr}-color: blue; }', - description: 'ignore interpolation', - }, - { - code: 'p.#{$name} { #{$Attr}-color: blue; }', - description: 'ignore interpolation', - }, - { - code: 'p.#{$name} { #{$attr}-Color: blue; }', - description: 'ignore interpolation', - }, - { - code: '#context a%extreme { COLOR: red; }', - description: 'extend only selectors', - }, - { - code: '.parent { @at-root { .child1 { DISPLAY: block; } } }', - description: 'as-root', - }, - { - code: '@mixin large-text { FONT-SIZE: 20px; }', - description: 'inside mixin', - }, - { - code: 'p { @if 1 + 1 == 2 { BORDER: 1px solid; } }', - description: 'inside custom at-rule', - }, - ], - - reject: [ - { - code: '&-sidebar { Border: 1px solid; }', - fixed: '&-sidebar { BORDER: 1px solid; }', - description: 'referencing parent selectors', - message: messages.expected('Border', 'BORDER'), - line: 1, - column: 13, - endLine: 1, - endColumn: 19, - }, - { - code: 'a { Font: (italic bold 10px/8px) }', - fixed: 'a { FONT: (italic bold 10px/8px) }', - message: messages.expected('Font', 'FONT'), - line: 1, - column: 5, - endLine: 1, - endColumn: 9, - }, - { - code: 'a { font: { Size: 30em; } }', - fixed: 'a { font: { SIZE: 30em; } }', - description: 'nested properties', - message: messages.expected('Size', 'SIZE'), - line: 1, - column: 13, - endLine: 1, - endColumn: 17, - }, - { - code: '#context a%extreme { Color: red; }', - fixed: '#context a%extreme { COLOR: red; }', - description: 'extend only selectors', - message: messages.expected('Color', 'COLOR'), - line: 1, - column: 22, - endLine: 1, - endColumn: 27, - }, - { - code: '.parent { @at-root { .child1 { Display: block; } } }', - fixed: '.parent { @at-root { .child1 { DISPLAY: block; } } }', - description: 'as-root', - message: messages.expected('Display', 'DISPLAY'), - line: 1, - column: 32, - endLine: 1, - endColumn: 39, - }, - { - code: '@mixin large-text { Font-size: 20px; }', - fixed: '@mixin large-text { FONT-SIZE: 20px; }', - description: 'inside mixin', - message: messages.expected('Font-size', 'FONT-SIZE'), - line: 1, - column: 21, - endLine: 1, - endColumn: 30, - }, - { - code: 'p { @if 1 + 1 == 2 { Border: 1px solid; } }', - fixed: 'p { @if 1 + 1 == 2 { BORDER: 1px solid; } }', - description: 'inside custom at-rule', - message: messages.expected('Border', 'BORDER'), - line: 1, - column: 22, - endLine: 1, - endColumn: 28, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-less', - config: ['upper'], - fix: true, - - accept: [ - { - code: '@variable: 10px', - }, - { - code: '@Variable: 10px', - }, - { - code: '@VARIABLE: 10px', - }, - { - code: 'a { COLOR: @light-blue; }', - }, - { - code: 'a { .bordered; }', - description: 'ignore mixin', - }, - { - code: 'a { .Bordered; }', - description: 'ignore mixin', - }, - { - code: 'a { .Bordered(5px); }', - description: 'ignore mixin', - }, - { - code: '.mixin(@color: black) { COLOR: @color; }', - description: 'inside mixin', - }, - { - code: '.@{my-selector} { FONT-WEIGHT: bold; }', - description: 'with selector interpolation', - }, - { - code: '.widget { @{property}: #0ee; }', - description: 'ignore property interpolation', - }, - { - code: '.widget { @{Property}: #0ee; }', - description: 'ignore property interpolation', - }, - { - code: 'a { BOX_SHADOW+: inset 0 0 10px #555; }', - description: 'mergeable property', - }, - { - code: 'a { BOX-SHADOW+_: inset 0 0 10px #555; }', - description: 'mergeable property with space', - }, - { - code: '.bucket { tr & { COLOR: blue; } }', - description: 'nested selector', - }, - { - code: 'a { Box-shadow+: inset 0 0 10px #555; }', - description: 'mergeable property', - }, - { - code: 'a { Transform+_: scale(2); }', - description: 'mergeable property with space', - }, - ], - - reject: [ - { - code: 'a { Color: @light-blue; }', - fixed: 'a { COLOR: @light-blue; }', - message: messages.expected('Color', 'COLOR'), - line: 1, - column: 5, - endLine: 1, - endColumn: 10, - }, - { - code: '.@{my-selector} { Font-weight: bold; }', - fixed: '.@{my-selector} { FONT-WEIGHT: bold; }', - description: 'selector interpolation', - message: messages.expected('Font-weight', 'FONT-WEIGHT'), - line: 1, - column: 19, - endLine: 1, - endColumn: 30, - }, - { - code: '.mixin(@color: black) { Color: @color; }', - fixed: '.mixin(@color: black) { COLOR: @color; }', - description: 'inside mixin', - message: messages.expected('Color', 'COLOR'), - line: 1, - column: 25, - endLine: 1, - endColumn: 30, - }, - { - code: '@media screen { @media (min-width: 768px) { Color: red; }}', - fixed: '@media screen { @media (min-width: 768px) { COLOR: red; }}', - description: 'nested directives', - message: messages.expected('Color', 'COLOR'), - line: 1, - column: 45, - endLine: 1, - endColumn: 50, - }, - { - code: '.bucket { tr & { Color: blue; } }', - fixed: '.bucket { tr & { COLOR: blue; } }', - description: 'nested selector', - message: messages.expected('Color', 'COLOR'), - line: 1, - column: 18, - endLine: 1, - endColumn: 23, - }, - ], -}); - -testRule({ - ruleName, - config: ['lower', { ignoreSelectors: [':exports'] }], - fix: true, - - accept: [ - { - code: ':exports { camelCasedColorVariable: blue }', - }, - ], -}); diff --git a/lib/rules/property-case/index.js b/lib/rules/property-case/index.js deleted file mode 100644 index a52b72b262..0000000000 --- a/lib/rules/property-case/index.js +++ /dev/null @@ -1,96 +0,0 @@ -'use strict'; - -const isCustomProperty = require('../../utils/isCustomProperty'); -const isStandardSyntaxProperty = require('../../utils/isStandardSyntaxProperty'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const optionsMatches = require('../../utils/optionsMatches'); -const { isRegExp, isString } = require('../../utils/validateTypes'); -const { isRule } = require('../../utils/typeGuards'); - -const ruleName = 'property-case'; - -const messages = ruleMessages(ruleName, { - expected: (actual, expected) => `Expected "${actual}" to be "${expected}"`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/property-case', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions( - result, - ruleName, - { - actual: primary, - possible: ['lower', 'upper'], - }, - { - actual: secondaryOptions, - possible: { - ignoreSelectors: [isString, isRegExp], - }, - optional: true, - }, - ); - - if (!validOptions) { - return; - } - - root.walkDecls((decl) => { - const prop = decl.prop; - - if (!isStandardSyntaxProperty(prop)) { - return; - } - - if (isCustomProperty(prop)) { - return; - } - - const { parent } = decl; - - if (!parent) throw new Error('A parent node must be present'); - - if (isRule(parent)) { - const { selector } = parent; - - if (selector && optionsMatches(secondaryOptions, 'ignoreSelectors', selector)) { - return; - } - } - - const expectedProp = primary === 'lower' ? prop.toLowerCase() : prop.toUpperCase(); - - if (prop === expectedProp) { - return; - } - - if (context.fix) { - decl.prop = expectedProp; - - return; - } - - report({ - message: messages.expected(prop, expectedProp), - word: prop, - node: decl, - ruleName, - result, - }); - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/rule-empty-line-before/README.md b/lib/rules/rule-empty-line-before/README.md index afa65862ba..cec77bd000 100644 --- a/lib/rules/rule-empty-line-before/README.md +++ b/lib/rules/rule-empty-line-before/README.md @@ -13,7 +13,7 @@ b {} /* ↑ */ This rule ignores rules that are the very first node in a source. -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. We recommend to enable [`indentation`](../indentation/README.md) rule for better autofixing results with this rule. +The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. ## Options diff --git a/lib/rules/selector-attribute-brackets-space-inside/README.md b/lib/rules/selector-attribute-brackets-space-inside/README.md deleted file mode 100644 index 6c25937cb4..0000000000 --- a/lib/rules/selector-attribute-brackets-space-inside/README.md +++ /dev/null @@ -1,114 +0,0 @@ -# selector-attribute-brackets-space-inside - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace on the inside of the brackets within attribute selectors. - - -```css - [ target=_blank ] -/** ↑ ↑ - * The space inside these two brackets */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a single space inside the brackets. - -The following patterns are considered problems: - - -```css -[target] {} -``` - - -```css -[ target] {} -``` - - -```css -[target ] {} -``` - - -```css -[target=_blank] {} -``` - - -```css -[ target=_blank] {} -``` - - -```css -[target=_blank ] {} -``` - -The following patterns are _not_ considered problems: - - -```css -[ target ] {} -``` - - -```css -[ target=_blank ] {} -``` - -### `"never"` - -There _must never_ be whitespace on the inside the brackets. - -The following patterns are considered problems: - - -```css -[ target] {} -``` - - -```css -[target ] {} -``` - - -```css -[ target ] {} -``` - - -```css -[ target=_blank] {} -``` - - -```css -[target=_blank ] {} -``` - - -```css -[ target=_blank ] {} -``` - -The following patterns are _not_ considered problems: - - -```css -[target] {} -``` - - -```css -[target=_blank] {} -``` diff --git a/lib/rules/selector-attribute-brackets-space-inside/__tests__/index.js b/lib/rules/selector-attribute-brackets-space-inside/__tests__/index.js deleted file mode 100644 index 8015867ae9..0000000000 --- a/lib/rules/selector-attribute-brackets-space-inside/__tests__/index.js +++ /dev/null @@ -1,1035 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: '.foo { }', - }, - { - code: '[ target ] { }', - }, - { - code: '[ target ] { }', - }, - { - code: '[ target=_blank ] { }', - }, - { - code: '[ target=_blank ] { }', - }, - { - code: "[ target='_blank' ] { }", - }, - { - code: '[ target="_blank" ] { }', - }, - { - code: '[ title~=flower ] { }', - }, - { - code: '[ title|=flower ] { }', - }, - { - code: '[ title^=flower ] { }', - }, - { - code: '[ title$=flower ] { }', - }, - { - code: 'a[ href*=w3schools ] { }', - }, - { - code: 'img[ alt~=person ][ src*=lorem ] { }', - }, - { - code: '[ target=_blank ]:hover { }', - }, - { - code: '[ target=_blank ]::before { }', - }, - { - code: 'option[ data-hidden=true ] { }', - }, - { - code: 'option[ dataHidden ] { }', - }, - { - code: '@media screen and (max-width: 480px) { img[ align=right ] {} }', - }, - { - code: '[ target=_blank ] .foo { }', - }, - { - code: 'li[ aria-hidden=false ]:nth-child(1) { }', - }, - { - code: 'li[ aria-hidden=false ]:nth-child( 1) { }', - }, - { - code: 'li[ aria-hidden=false ]:nth-child(1 ) { }', - }, - { - code: 'li[ aria-hidden=false ]:nth-child( 1 ) { }', - }, - { - code: 'ul li[ aria-hidden=false ] + li[ aria-hidden=false ] a { }', - }, - { - code: '[ target ] { content: "[" }', - }, - { - code: '[ target ] { content: "]" }', - }, - { - code: '[ foo=bar i ] { }', - }, - { - 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', - }, - { - code: 'a[b=#{c}] { }', - description: 'ignore "invalid" selector (see #3130)', - }, - ], - - reject: [ - { - code: '[target ] { }', - fixed: '[ target ] { }', - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - code: '[ target] { }', - fixed: '[ target ] { }', - message: messages.expectedClosing, - line: 1, - column: 8, - }, - { - code: '[target ] { }', - fixed: '[ target ] { }', - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - code: '[ target] { }', - fixed: '[ target ] { }', - message: messages.expectedClosing, - line: 1, - column: 9, - }, - { - code: '[target=_blank ] { }', - fixed: '[ target=_blank ] { }', - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - code: '[ target=_blank] { }', - fixed: '[ target=_blank ] { }', - message: messages.expectedClosing, - line: 1, - column: 15, - }, - { - code: '[target=_blank ] { }', - fixed: '[ target=_blank ] { }', - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - code: '[ target=_blank] { }', - fixed: '[ target=_blank ] { }', - message: messages.expectedClosing, - line: 1, - column: 16, - }, - { - code: "[target='_blank' ] { }", - fixed: "[ target='_blank' ] { }", - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - code: "[ target='_blank'] { }", - fixed: "[ target='_blank' ] { }", - message: messages.expectedClosing, - line: 1, - column: 17, - }, - { - code: '[target="_blank" ] { }', - fixed: '[ target="_blank" ] { }', - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - code: '[ target="_blank"] { }', - fixed: '[ target="_blank" ] { }', - message: messages.expectedClosing, - line: 1, - column: 17, - }, - { - code: 'a[href*=w3schools ] { }', - fixed: 'a[ href*=w3schools ] { }', - message: messages.expectedOpening, - line: 1, - column: 3, - }, - { - code: 'a[ href*=w3schools] { }', - fixed: 'a[ href*=w3schools ] { }', - message: messages.expectedClosing, - line: 1, - column: 18, - }, - { - code: 'img[alt~=person ][ src*=lorem ] { }', - fixed: 'img[ alt~=person ][ src*=lorem ] { }', - message: messages.expectedOpening, - line: 1, - column: 5, - }, - { - code: 'img[ alt~=person][ src*=lorem ] { }', - fixed: 'img[ alt~=person ][ src*=lorem ] { }', - message: messages.expectedClosing, - line: 1, - column: 16, - }, - { - code: 'img[ alt~=person ][src*=lorem ] { }', - fixed: 'img[ alt~=person ][ src*=lorem ] { }', - message: messages.expectedOpening, - line: 1, - column: 20, - }, - { - code: 'img[ alt~=person ][ src*=lorem] { }', - fixed: 'img[ alt~=person ][ src*=lorem ] { }', - message: messages.expectedClosing, - line: 1, - column: 30, - }, - { - code: '[target=_blank ]:hover { }', - fixed: '[ target=_blank ]:hover { }', - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - code: '[ target=_blank]:hover { }', - fixed: '[ target=_blank ]:hover { }', - message: messages.expectedClosing, - line: 1, - column: 15, - }, - { - code: '[target=_blank ]::before { }', - fixed: '[ target=_blank ]::before { }', - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - code: '[ target=_blank]::before { }', - fixed: '[ target=_blank ]::before { }', - message: messages.expectedClosing, - line: 1, - column: 15, - }, - { - code: 'option[data-hidden=true ] { }', - fixed: 'option[ data-hidden=true ] { }', - message: messages.expectedOpening, - line: 1, - column: 8, - }, - { - code: 'option[ data-hidden=true] { }', - fixed: 'option[ data-hidden=true ] { }', - message: messages.expectedClosing, - line: 1, - column: 24, - }, - { - code: 'option[dataHidden ] { }', - fixed: 'option[ dataHidden ] { }', - message: messages.expectedOpening, - line: 1, - column: 8, - }, - { - code: 'option[ dataHidden] { }', - fixed: 'option[ dataHidden ] { }', - message: messages.expectedClosing, - line: 1, - column: 18, - }, - { - code: '@media screen and (max-width: 480px) { img[align=right ] {} }', - fixed: '@media screen and (max-width: 480px) { img[ align=right ] {} }', - message: messages.expectedOpening, - line: 1, - column: 44, - }, - { - code: '@media screen and (max-width: 480px) { img[ align=right] {} }', - fixed: '@media screen and (max-width: 480px) { img[ align=right ] {} }', - message: messages.expectedClosing, - line: 1, - column: 55, - }, - { - code: '[target=_blank ] .foo { }', - fixed: '[ target=_blank ] .foo { }', - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - code: '[ target=_blank] .foo { }', - fixed: '[ target=_blank ] .foo { }', - message: messages.expectedClosing, - line: 1, - column: 15, - }, - { - code: 'li[aria-hidden=false ]:nth-child(1) { }', - fixed: 'li[ aria-hidden=false ]:nth-child(1) { }', - message: messages.expectedOpening, - line: 1, - column: 4, - }, - { - code: 'li[ aria-hidden=false]:nth-child(1) { }', - fixed: 'li[ aria-hidden=false ]:nth-child(1) { }', - message: messages.expectedClosing, - line: 1, - column: 21, - }, - { - code: 'li[aria-hidden=false ]:nth-child( 1 ) { }', - fixed: 'li[ aria-hidden=false ]:nth-child( 1 ) { }', - message: messages.expectedOpening, - line: 1, - column: 4, - }, - { - code: 'li[ aria-hidden=false]:nth-child( 1 ) { }', - fixed: 'li[ aria-hidden=false ]:nth-child( 1 ) { }', - message: messages.expectedClosing, - line: 1, - column: 21, - }, - { - code: 'ul li[aria-hidden=false ] + li[ aria-hidden=false ] a { }', - fixed: 'ul li[ aria-hidden=false ] + li[ aria-hidden=false ] a { }', - message: messages.expectedOpening, - line: 1, - column: 7, - }, - { - code: 'ul li[ aria-hidden=false] + li[ aria-hidden=false ] a { }', - fixed: 'ul li[ aria-hidden=false ] + li[ aria-hidden=false ] a { }', - message: messages.expectedClosing, - line: 1, - column: 24, - }, - { - code: 'ul li[ aria-hidden=false ] + li[aria-hidden=false ] a { }', - fixed: 'ul li[ aria-hidden=false ] + li[ aria-hidden=false ] a { }', - message: messages.expectedOpening, - line: 1, - column: 33, - }, - { - code: 'ul li[ aria-hidden=false ] + li[ aria-hidden=false] a { }', - fixed: 'ul li[ aria-hidden=false ] + li[ aria-hidden=false ] a { }', - message: messages.expectedClosing, - line: 1, - column: 50, - }, - { - code: '[target ] { content: "[" }', - fixed: '[ target ] { content: "[" }', - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - code: '[ target] { content: "[" }', - fixed: '[ target ] { content: "[" }', - message: messages.expectedClosing, - line: 1, - column: 8, - }, - { - code: '[target ] { content: "]" }', - fixed: '[ target ] { content: "]" }', - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - code: '[ target] { content: "]" }', - fixed: '[ target ] { content: "]" }', - message: messages.expectedClosing, - line: 1, - column: 8, - }, - { - code: '[ foo=bar i] { }', - fixed: '[ foo=bar i ] { }', - message: messages.expectedClosing, - line: 1, - column: 11, - }, - { - code: '[foo=bar i ] { }', - fixed: '[ foo=bar i ] { }', - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - code: 'img[alt~=person][src*=lorem] { }', - fixed: 'img[ alt~=person ][ src*=lorem ] { }', - warnings: [ - { - message: messages.expectedOpening, - line: 1, - column: 5, - }, - { - message: messages.expectedClosing, - line: 1, - column: 15, - }, - { - message: messages.expectedOpening, - line: 1, - column: 18, - }, - { - message: messages.expectedClosing, - line: 1, - column: 27, - }, - ], - }, - { - code: '[/**/foo=bar i] { }', - fixed: '[ /**/foo=bar i ] { }', - warnings: [ - { - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - message: messages.expectedClosing, - line: 1, - column: 14, - }, - ], - }, - { - code: '[foo=bar i /**/] { }', - fixed: '[ foo=bar i /**/ ] { }', - warnings: [ - { - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - message: messages.expectedClosing, - line: 1, - column: 15, - }, - ], - }, - { - code: '[foo=bar i/**/] { }', - fixed: '[ foo=bar i/**/ ] { }', - - warnings: [ - { - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - message: messages.expectedClosing, - line: 1, - column: 14, - }, - ], - }, - { - code: '[foo=bar/**/] { }', - fixed: '[ foo=bar/**/ ] { }', - warnings: [ - { - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - message: messages.expectedClosing, - line: 1, - column: 12, - }, - ], - }, - { - code: '[foo/**/] { }', - fixed: '[ foo/**/ ] { }', - warnings: [ - { - message: messages.expectedOpening, - line: 1, - column: 2, - }, - { - message: messages.expectedClosing, - line: 1, - column: 8, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: '.foo { }', - }, - { - code: '[target] { }', - }, - { - code: '[target] { }', - }, - { - code: '[target=_blank] { }', - }, - { - code: "[target='_blank'] { }", - }, - { - code: '[target="_blank"] { }', - }, - { - code: '[title~=flower] { }', - }, - { - code: '[title|=flower] { }', - }, - { - code: '[title^=flower] { }', - }, - { - code: '[title$=flower] { }', - }, - { - code: 'a[href*=w3schools] { }', - }, - { - code: 'img[alt~=person][src*=lorem] { }', - }, - { - code: '[target=_blank]:hover { }', - }, - { - code: '[target=_blank]::before { }', - }, - { - code: 'option[data-hidden=true] { }', - }, - { - code: 'option[dataHidden] { }', - }, - { - code: '@media screen and (max-width: 480px) { img[align=right] {} }', - }, - { - code: '[target=_blank] .foo { }', - }, - { - code: 'li[aria-hidden=false]:nth-child(1) { }', - }, - { - code: 'li[aria-hidden=false]:nth-child( 1) { }', - }, - { - code: 'li[aria-hidden=false]:nth-child(1 ) { }', - }, - { - code: 'li[aria-hidden=false]:nth-child( 1 ) { }', - }, - { - code: 'ul li[aria-hidden=false] + li[aria-hidden=false] a { }', - }, - { - code: '[target] { content: "[" }', - }, - { - code: '[target] { content: "]" }', - }, - { - code: '[foo=bar i] { }', - }, - ], - - reject: [ - { - code: '[ target] { }', - fixed: '[target] { }', - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - code: '[target ] { }', - fixed: '[target] { }', - message: messages.rejectedClosing, - line: 1, - column: 8, - }, - { - code: '[ target] { }', - fixed: '[target] { }', - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - code: '[target ] { }', - fixed: '[target] { }', - message: messages.rejectedClosing, - line: 1, - column: 9, - }, - { - code: '[ target=_blank] { }', - fixed: '[target=_blank] { }', - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - code: '[target=_blank ] { }', - fixed: '[target=_blank] { }', - message: messages.rejectedClosing, - line: 1, - column: 15, - }, - { - code: '[ target=_blank] { }', - fixed: '[target=_blank] { }', - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - code: '[target=_blank ] { }', - fixed: '[target=_blank] { }', - message: messages.rejectedClosing, - line: 1, - column: 16, - }, - { - code: "[ target='_blank'] { }", - fixed: "[target='_blank'] { }", - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - code: "[target='_blank' ] { }", - fixed: "[target='_blank'] { }", - message: messages.rejectedClosing, - line: 1, - column: 17, - }, - { - code: '[ target="_blank"] { }', - fixed: '[target="_blank"] { }', - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - code: '[target="_blank" ] { }', - fixed: '[target="_blank"] { }', - message: messages.rejectedClosing, - line: 1, - column: 17, - }, - { - code: 'a[ href*=w3schools] { }', - fixed: 'a[href*=w3schools] { }', - message: messages.rejectedOpening, - line: 1, - column: 3, - }, - { - code: 'a[href*=w3schools ] { }', - fixed: 'a[href*=w3schools] { }', - message: messages.rejectedClosing, - line: 1, - column: 18, - }, - { - code: 'img[ alt~=person][src*=lorem] { }', - fixed: 'img[alt~=person][src*=lorem] { }', - message: messages.rejectedOpening, - line: 1, - column: 5, - }, - { - code: 'img[alt~=person ][src*=lorem] { }', - fixed: 'img[alt~=person][src*=lorem] { }', - message: messages.rejectedClosing, - line: 1, - column: 16, - }, - { - code: 'img[alt~=person][ src*=lorem] { }', - fixed: 'img[alt~=person][src*=lorem] { }', - message: messages.rejectedOpening, - line: 1, - column: 18, - }, - { - code: 'img[alt~=person][src*=lorem ] { }', - fixed: 'img[alt~=person][src*=lorem] { }', - message: messages.rejectedClosing, - line: 1, - column: 28, - }, - { - code: '[ target=_blank]:hover { }', - fixed: '[target=_blank]:hover { }', - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - code: '[target=_blank ]:hover { }', - fixed: '[target=_blank]:hover { }', - message: messages.rejectedClosing, - line: 1, - column: 15, - }, - { - code: '[ target=_blank]::before { }', - fixed: '[target=_blank]::before { }', - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - code: '[target=_blank ]::before { }', - fixed: '[target=_blank]::before { }', - message: messages.rejectedClosing, - line: 1, - column: 15, - }, - { - code: 'option[ data-hidden=true] { }', - fixed: 'option[data-hidden=true] { }', - message: messages.rejectedOpening, - line: 1, - column: 8, - }, - { - code: 'option[data-hidden=true ] { }', - fixed: 'option[data-hidden=true] { }', - message: messages.rejectedClosing, - line: 1, - column: 24, - }, - { - code: 'option[ dataHidden] { }', - fixed: 'option[dataHidden] { }', - message: messages.rejectedOpening, - line: 1, - column: 8, - }, - { - code: 'option[dataHidden ] { }', - fixed: 'option[dataHidden] { }', - message: messages.rejectedClosing, - line: 1, - column: 18, - }, - { - code: '@media screen and (max-width: 480px) { img[ align=right] {} }', - fixed: '@media screen and (max-width: 480px) { img[align=right] {} }', - message: messages.rejectedOpening, - line: 1, - column: 44, - }, - { - code: '@media screen and (max-width: 480px) { img[align=right ] {} }', - fixed: '@media screen and (max-width: 480px) { img[align=right] {} }', - message: messages.rejectedClosing, - line: 1, - column: 55, - }, - { - code: '[ target=_blank] .foo { }', - fixed: '[target=_blank] .foo { }', - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - code: '[target=_blank ] .foo { }', - fixed: '[target=_blank] .foo { }', - message: messages.rejectedClosing, - line: 1, - column: 15, - }, - { - code: 'li[ aria-hidden=false]:nth-child(1) { }', - fixed: 'li[aria-hidden=false]:nth-child(1) { }', - message: messages.rejectedOpening, - line: 1, - column: 4, - }, - { - code: 'li[aria-hidden=false ]:nth-child(1) { }', - fixed: 'li[aria-hidden=false]:nth-child(1) { }', - message: messages.rejectedClosing, - line: 1, - column: 21, - }, - { - code: 'li[ aria-hidden=false]:nth-child( 1 ) { }', - fixed: 'li[aria-hidden=false]:nth-child( 1 ) { }', - message: messages.rejectedOpening, - line: 1, - column: 4, - }, - { - code: 'li[aria-hidden=false ]:nth-child( 1 ) { }', - fixed: 'li[aria-hidden=false]:nth-child( 1 ) { }', - message: messages.rejectedClosing, - line: 1, - column: 21, - }, - { - code: 'ul li[ aria-hidden=false] + li[aria-hidden=false] a { }', - fixed: 'ul li[aria-hidden=false] + li[aria-hidden=false] a { }', - message: messages.rejectedOpening, - line: 1, - column: 7, - }, - { - code: 'ul li[aria-hidden=false ] + li[aria-hidden=false] a { }', - fixed: 'ul li[aria-hidden=false] + li[aria-hidden=false] a { }', - message: messages.rejectedClosing, - line: 1, - column: 24, - }, - { - code: 'ul li[aria-hidden=false] + li[ aria-hidden=false] a { }', - fixed: 'ul li[aria-hidden=false] + li[aria-hidden=false] a { }', - message: messages.rejectedOpening, - line: 1, - column: 31, - }, - { - code: 'ul li[aria-hidden=false] + li[aria-hidden=false ] a { }', - fixed: 'ul li[aria-hidden=false] + li[aria-hidden=false] a { }', - message: messages.rejectedClosing, - line: 1, - column: 48, - }, - { - code: '[ target] { content: "[" }', - fixed: '[target] { content: "[" }', - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - code: '[target ] { content: "[" }', - fixed: '[target] { content: "[" }', - message: messages.rejectedClosing, - line: 1, - column: 8, - }, - { - code: '[ target] { content: "]" }', - fixed: '[target] { content: "]" }', - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - code: '[target ] { content: "]" }', - fixed: '[target] { content: "]" }', - message: messages.rejectedClosing, - line: 1, - column: 8, - }, - { - code: '[ foo=bar i] { }', - fixed: '[foo=bar i] { }', - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - code: '[foo=bar i ] { }', - fixed: '[foo=bar i] { }', - message: messages.rejectedClosing, - line: 1, - column: 11, - }, - { - code: 'img[ alt~=person ][ src*=lorem ] { }', - fixed: 'img[alt~=person][src*=lorem] { }', - warnings: [ - { - message: messages.rejectedOpening, - line: 1, - column: 5, - }, - { - message: messages.rejectedClosing, - line: 1, - column: 17, - }, - { - message: messages.rejectedOpening, - line: 1, - column: 20, - }, - { - message: messages.rejectedClosing, - line: 1, - column: 31, - }, - ], - }, - { - code: '[ /**/foo=bar i ] { }', - fixed: '[/**/foo=bar i] { }', - warnings: [ - { - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - message: messages.rejectedClosing, - line: 1, - column: 16, - }, - ], - }, - { - code: '[ foo=bar i /**/ ] { }', - fixed: '[foo=bar i /**/] { }', - warnings: [ - { - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - message: messages.rejectedClosing, - line: 1, - column: 17, - }, - ], - }, - { - code: '[ foo=bar i/**/ ] { }', - fixed: '[foo=bar i/**/] { }', - warnings: [ - { - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - message: messages.rejectedClosing, - line: 1, - column: 16, - }, - ], - }, - { - code: '[ foo=bar/**/ ] { }', - fixed: '[foo=bar/**/] { }', - warnings: [ - { - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - message: messages.rejectedClosing, - line: 1, - column: 14, - }, - ], - }, - { - code: '[ foo/**/ ] { }', - fixed: '[foo/**/] { }', - warnings: [ - { - message: messages.rejectedOpening, - line: 1, - column: 2, - }, - { - message: messages.rejectedClosing, - line: 1, - column: 10, - }, - ], - }, - ], -}); diff --git a/lib/rules/selector-attribute-brackets-space-inside/index.js b/lib/rules/selector-attribute-brackets-space-inside/index.js deleted file mode 100644 index 2654751b59..0000000000 --- a/lib/rules/selector-attribute-brackets-space-inside/index.js +++ /dev/null @@ -1,209 +0,0 @@ -'use strict'; - -const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); -const parseSelector = require('../../utils/parseSelector'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const styleSearch = require('style-search'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'selector-attribute-brackets-space-inside'; - -const messages = ruleMessages(ruleName, { - expectedOpening: 'Expected single space after "["', - rejectedOpening: 'Unexpected whitespace after "["', - expectedClosing: 'Expected single space before "]"', - rejectedClosing: 'Unexpected whitespace before "]"', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/selector-attribute-brackets-space-inside', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - root.walkRules((ruleNode) => { - if (!isStandardSyntaxRule(ruleNode)) { - return; - } - - if (!ruleNode.selector.includes('[')) { - return; - } - - const selector = ruleNode.raws.selector ? ruleNode.raws.selector.raw : ruleNode.selector; - - let hasFixed; - const fixedSelector = parseSelector(selector, result, ruleNode, (selectorTree) => { - selectorTree.walkAttributes((attributeNode) => { - const attributeSelectorString = attributeNode.toString(); - - styleSearch({ source: attributeSelectorString, target: '[' }, (match) => { - const nextCharIsSpace = attributeSelectorString[match.startIndex + 1] === ' '; - const index = attributeNode.sourceIndex + match.startIndex + 1; - - if (nextCharIsSpace && primary === 'never') { - if (context.fix) { - hasFixed = true; - fixBefore(attributeNode); - - return; - } - - complain(messages.rejectedOpening, index); - } - - if (!nextCharIsSpace && primary === 'always') { - if (context.fix) { - hasFixed = true; - fixBefore(attributeNode); - - return; - } - - complain(messages.expectedOpening, index); - } - }); - - styleSearch({ source: attributeSelectorString, target: ']' }, (match) => { - const prevCharIsSpace = attributeSelectorString[match.startIndex - 1] === ' '; - const index = attributeNode.sourceIndex + match.startIndex - 1; - - if (prevCharIsSpace && primary === 'never') { - if (context.fix) { - hasFixed = true; - fixAfter(attributeNode); - - return; - } - - complain(messages.rejectedClosing, index); - } - - if (!prevCharIsSpace && primary === 'always') { - if (context.fix) { - hasFixed = true; - fixAfter(attributeNode); - - return; - } - - complain(messages.expectedClosing, index); - } - }); - }); - }); - - if (hasFixed && fixedSelector) { - if (!ruleNode.raws.selector) { - ruleNode.selector = fixedSelector; - } else { - ruleNode.raws.selector.raw = fixedSelector; - } - } - - /** - * @param {string} message - * @param {number} index - */ - function complain(message, index) { - report({ - message, - index, - result, - ruleName, - node: ruleNode, - }); - } - }); - }; - - /** - * @param {import('postcss-selector-parser').Attribute} attributeNode - */ - function fixBefore(attributeNode) { - const spacesAttribute = attributeNode.raws.spaces && attributeNode.raws.spaces.attribute; - const rawAttrBefore = spacesAttribute && spacesAttribute.before; - - /** @type {{ attrBefore: string, setAttrBefore: (fixed: string) => void }} */ - const { attrBefore, setAttrBefore } = rawAttrBefore - ? { - attrBefore: rawAttrBefore, - setAttrBefore(fixed) { - spacesAttribute.before = fixed; - }, - } - : { - attrBefore: - (attributeNode.spaces.attribute && attributeNode.spaces.attribute.before) || '', - setAttrBefore(fixed) { - if (!attributeNode.spaces.attribute) attributeNode.spaces.attribute = {}; - - attributeNode.spaces.attribute.before = fixed; - }, - }; - - if (primary === 'always') { - setAttrBefore(attrBefore.replace(/^\s*/, ' ')); - } else if (primary === 'never') { - setAttrBefore(attrBefore.replace(/^\s*/, '')); - } - } - - /** - * @param {import('postcss-selector-parser').Attribute} attributeNode - */ - function fixAfter(attributeNode) { - const key = attributeNode.operator - ? attributeNode.insensitive - ? 'insensitive' - : 'value' - : 'attribute'; - - const rawSpaces = attributeNode.raws.spaces && attributeNode.raws.spaces[key]; - const rawAfter = rawSpaces && rawSpaces.after; - - const spaces = attributeNode.spaces[key]; - - /** @type {{ after: string, setAfter: (fixed: string) => void }} */ - const { after, setAfter } = rawAfter - ? { - after: rawAfter, - setAfter(fixed) { - rawSpaces.after = fixed; - }, - } - : { - after: (spaces && spaces.after) || '', - setAfter(fixed) { - if (!attributeNode.spaces[key]) attributeNode.spaces[key] = {}; - - // @ts-expect-error -- TS2532: Object is possibly 'undefined'. - attributeNode.spaces[key].after = fixed; - }, - }; - - if (primary === 'always') { - setAfter(after.replace(/\s*$/, ' ')); - } else if (primary === 'never') { - setAfter(after.replace(/\s*$/, '')); - } - } -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/selector-attribute-operator-space-after/README.md b/lib/rules/selector-attribute-operator-space-after/README.md deleted file mode 100644 index c422e35218..0000000000 --- a/lib/rules/selector-attribute-operator-space-after/README.md +++ /dev/null @@ -1,164 +0,0 @@ -# selector-attribute-operator-space-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace after operators within attribute selectors. - - -```css -[target= _blank] -/** ↑ - * The space after operator */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a single space after the operator. - -The following patterns are considered problems: - - -```css -[target=_blank] {} -``` - - -```css -[target =_blank] {} -``` - - -```css -[target='_blank'] {} -``` - - -```css -[target="_blank"] {} -``` - - -```css -[target ='_blank'] {} -``` - - -```css -[target ="_blank"] {} -``` - -The following patterns are _not_ considered problems: - - -```css -[target] {} -``` - - -```css -[target= _blank] {} -``` - - -```css -[target= '_blank'] {} -``` - - -```css -[target= "_blank"] {} -``` - - -```css -[target = _blank] {} -``` - - -```css -[target = '_blank'] {} -``` - - -```css -[target = "_blank"] {} -``` - -### `"never"` - -There _must never_ be a single space after the operator. - -The following patterns are considered problems: - - -```css -[target= _blank] {} -``` - - -```css -[target = _blank] {} -``` - - -```css -[target= '_blank'] {} -``` - - -```css -[target= "_blank"] {} -``` - - -```css -[target = '_blank'] {} -``` - - -```css -[target = "_blank"] {} -``` - -The following patterns are _not_ considered problems: - - -```css -[target] {} -``` - - -```css -[target=_blank] {} -``` - - -```css -[target='_blank'] {} -``` - - -```css -[target="_blank"] {} -``` - - -```css -[target =_blank] {} -``` - - -```css -[target ='_blank'] {} -``` - - -```css -[target ="_blank"] {} -``` diff --git a/lib/rules/selector-attribute-operator-space-after/__tests__/index.js b/lib/rules/selector-attribute-operator-space-after/__tests__/index.js deleted file mode 100644 index 3cd96c3eba..0000000000 --- a/lib/rules/selector-attribute-operator-space-after/__tests__/index.js +++ /dev/null @@ -1,1663 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: '.foo {}', - }, - { - code: '[target] {}', - }, - { - code: '[ target] {}', - }, - { - code: '[target ] {}', - }, - { - code: '[ target ] {}', - }, - { - code: '[target= _blank] {}', - }, - { - code: '[target = _blank] {}', - }, - { - code: '[target= _blank ] {}', - }, - { - code: '[target = _blank ] {}', - }, - { - code: '[ target= _blank] {}', - }, - { - code: '[ target = _blank] {}', - }, - { - code: '[ target= _blank ] {}', - }, - { - code: '[ target = _blank ] {}', - }, - { - code: "[target= '_blank'] {}", - }, - { - code: "[target = '_blank'] {}", - }, - { - code: "[target= ' _blank'] {}", - }, - { - code: "[target= '_blank' ] {}", - }, - { - code: "[target= '_blank '] {}", - }, - { - code: "[target = '_blank' ] {}", - }, - { - code: "[target= ' _blank '] {}", - }, - { - code: "[ target= '_blank'] {}", - }, - { - code: "[ target = '_blank'] {}", - }, - { - code: "[ target= ' _blank'] {}", - }, - { - code: "[ target= '_blank' ] {}", - }, - { - code: "[ target= '_blank '] {}", - }, - { - code: "[ target = '_blank' ] {}", - }, - { - code: "[ target= ' _blank '] {}", - }, - { - code: '[target= "_blank"] {}', - }, - { - code: '[target = "_blank"] {}', - }, - { - code: '[target= " _blank"] {}', - }, - { - code: '[target= "_blank" ] {}', - }, - { - code: '[target= "_blank "] {}', - }, - { - code: '[target = "_blank" ] {}', - }, - { - code: '[target= " _blank "] {}', - }, - { - code: '[ target= "_blank"] {}', - }, - { - code: '[ target = "_blank"] {}', - }, - { - code: '[ target= " _blank"] {}', - }, - { - code: '[ target= "_blank" ] {}', - }, - { - code: '[ target= "_blank "] {}', - }, - { - code: '[ target = "_blank" ] {}', - }, - { - code: '[ target= " _blank "] {}', - }, - { - code: '[title~= flower] { }', - }, - { - code: '[title ~= flower] { }', - }, - { - code: '[title|= flower] { }', - }, - { - code: '[title |= flower] { }', - }, - { - code: '[title^= flower] { }', - }, - { - code: '[title ^= flower] { }', - }, - { - code: '[title$= flower] { }', - }, - { - code: '[title $= flower] { }', - }, - { - code: 'a[href*= w3schools] { }', - }, - { - code: 'a[href *= w3schools] { }', - }, - { - code: 'img[alt~= person][src*= lorem] { }', - }, - { - code: 'img[alt ~= person][src*= lorem] { }', - }, - { - code: 'img[alt~= person][src *= lorem] { }', - }, - { - code: 'img[alt ~= person][src *= lorem] { }', - }, - { - code: '[target= _blank]:hover { }', - }, - { - code: '[target = _blank]:hover { }', - }, - { - code: '[target= _blank]::before { }', - }, - { - code: '[target = _blank]::before { }', - }, - { - code: 'option[data-hidden= true] { }', - }, - { - code: 'option[data-hidden = true] { }', - }, - { - code: 'option[dataHidden] { }', - }, - { - code: '@media screen and (max-width: 480px) { img[align= right] {} }', - }, - { - code: '@media screen and (max-width: 480px) { img[align = right] {} }', - }, - { - code: '[target= _blank] .foo { }', - }, - { - code: '[target = _blank] .foo { }', - }, - { - code: 'li[aria-hidden= false]:nth-child(1) { }', - }, - { - code: 'li[aria-hidden= false]:nth-child( 1) { }', - }, - { - code: 'li[aria-hidden= false]:nth-child(1 ) { }', - }, - { - code: 'li[aria-hidden= false]:nth-child( 1 ) { }', - }, - { - code: 'li[aria-hidden = false]:nth-child(1) { }', - }, - { - code: 'li[aria-hidden = false]:nth-child( 1) { }', - }, - { - code: 'li[aria-hidden = false]:nth-child(1 ) { }', - }, - { - code: 'li[aria-hidden = false]:nth-child( 1 ) { }', - }, - { - code: 'ul li[aria-hidden= false] + li[aria-hidden= false] a { }', - }, - { - code: 'ul li[aria-hidden = false] + li[aria-hidden= false] a { }', - }, - { - code: 'ul li[aria-hidden= false] + li[aria-hidden = false] a { }', - }, - { - code: 'ul li[aria-hidden = false] + li[aria-hidden = false] a { }', - }, - { - code: '[target] { content: " " }', - }, - { - code: '[target ] { content: " " }', - }, - { - code: '[ target] { content: " " }', - }, - { - code: '[ target ] { content: " " }', - }, - { - 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', - }, - { - code: 'a[b=#{c}] { }', - description: 'ignore "invalid" selector (see #3130)', - }, - ], - - reject: [ - { - code: '[target=_blank] { }', - fixed: '[target= _blank] { }', - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target =_blank] { }', - fixed: '[target = _blank] { }', - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[target=_blank ] { }', - fixed: '[target= _blank ] { }', - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target =_blank ] { }', - fixed: '[target = _blank ] { }', - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[ target=_blank] { }', - fixed: '[ target= _blank] { }', - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[ target =_blank] { }', - fixed: '[ target = _blank] { }', - message: messages.expectedAfter('='), - line: 1, - column: 10, - }, - { - code: '[ target=_blank ] { }', - fixed: '[ target= _blank ] { }', - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[ target =_blank ] { }', - fixed: '[ target = _blank ] { }', - message: messages.expectedAfter('='), - line: 1, - column: 10, - }, - { - code: "[target='_blank'] { }", - fixed: "[target= '_blank'] { }", - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - { - code: "[target ='_blank'] { }", - fixed: "[target = '_blank'] { }", - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: "[target=' _blank'] { }", - fixed: "[target= ' _blank'] { }", - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - { - code: "[target='_blank' ] { }", - fixed: "[target= '_blank' ] { }", - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - { - code: "[target='_blank '] { }", - fixed: "[target= '_blank '] { }", - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - { - code: "[target ='_blank' ] { }", - fixed: "[target = '_blank' ] { }", - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: "[target=' _blank '] { }", - fixed: "[target= ' _blank '] { }", - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - { - code: "[ target='_blank'] { }", - fixed: "[ target= '_blank'] { }", - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: "[ target ='_blank'] { }", - fixed: "[ target = '_blank'] { }", - message: messages.expectedAfter('='), - line: 1, - column: 10, - }, - { - code: "[ target=' _blank'] { }", - fixed: "[ target= ' _blank'] { }", - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: "[ target='_blank' ] { }", - fixed: "[ target= '_blank' ] { }", - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: "[ target='_blank '] { }", - fixed: "[ target= '_blank '] { }", - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: "[ target ='_blank' ] { }", - fixed: "[ target = '_blank' ] { }", - message: messages.expectedAfter('='), - line: 1, - column: 10, - }, - { - code: "[ target=' _blank '] { }", - fixed: "[ target= ' _blank '] { }", - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[target="_blank"] { }', - fixed: '[target= "_blank"] { }', - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target ="_blank"] { }', - fixed: '[target = "_blank"] { }', - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[target=" _blank"] { }', - fixed: '[target= " _blank"] { }', - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target="_blank" ] { }', - fixed: '[target= "_blank" ] { }', - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target="_blank "] { }', - fixed: '[target= "_blank "] { }', - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target ="_blank" ] { }', - fixed: '[target = "_blank" ] { }', - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[target=" _blank "] { }', - fixed: '[target= " _blank "] { }', - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[ target="_blank"] { }', - fixed: '[ target= "_blank"] { }', - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[ target ="_blank"] { }', - fixed: '[ target = "_blank"] { }', - message: messages.expectedAfter('='), - line: 1, - column: 10, - }, - { - code: '[ target=" _blank"] { }', - fixed: '[ target= " _blank"] { }', - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[ target="_blank" ] { }', - fixed: '[ target= "_blank" ] { }', - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[ target="_blank "] { }', - fixed: '[ target= "_blank "] { }', - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[ target ="_blank" ] { }', - fixed: '[ target = "_blank" ] { }', - message: messages.expectedAfter('='), - line: 1, - column: 10, - }, - { - code: '[ target=" _blank "] { }', - fixed: '[ target= " _blank "] { }', - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[title~=flower] { }', - fixed: '[title~= flower] { }', - message: messages.expectedAfter('~='), - line: 1, - column: 8, - }, - { - code: '[title ~=flower] { }', - fixed: '[title ~= flower] { }', - message: messages.expectedAfter('~='), - line: 1, - column: 9, - }, - { - code: '[title|=flower] { }', - fixed: '[title|= flower] { }', - message: messages.expectedAfter('|='), - line: 1, - column: 8, - }, - { - code: '[title |=flower] { }', - fixed: '[title |= flower] { }', - message: messages.expectedAfter('|='), - line: 1, - column: 9, - }, - { - code: '[title^=flower] { }', - fixed: '[title^= flower] { }', - message: messages.expectedAfter('^='), - line: 1, - column: 8, - }, - { - code: '[title ^=flower] { }', - fixed: '[title ^= flower] { }', - message: messages.expectedAfter('^='), - line: 1, - column: 9, - }, - { - code: '[title$=flower] { }', - fixed: '[title$= flower] { }', - message: messages.expectedAfter('$='), - line: 1, - column: 8, - }, - { - code: '[title $=flower] { }', - fixed: '[title $= flower] { }', - message: messages.expectedAfter('$='), - line: 1, - column: 9, - }, - { - code: 'a[href*=w3schools] { }', - fixed: 'a[href*= w3schools] { }', - message: messages.expectedAfter('*='), - line: 1, - column: 8, - }, - { - code: 'a[href *=w3schools] { }', - fixed: 'a[href *= w3schools] { }', - message: messages.expectedAfter('*='), - line: 1, - column: 9, - }, - { - code: 'img[alt~=person][src*= lorem] { }', - fixed: 'img[alt~= person][src*= lorem] { }', - message: messages.expectedAfter('~='), - line: 1, - column: 9, - }, - { - code: 'img[alt ~=person][src*= lorem] { }', - fixed: 'img[alt ~= person][src*= lorem] { }', - message: messages.expectedAfter('~='), - line: 1, - column: 10, - }, - { - code: 'img[alt~= person][src *=lorem] { }', - fixed: 'img[alt~= person][src *= lorem] { }', - message: messages.expectedAfter('*='), - line: 1, - column: 24, - }, - { - code: 'img[alt ~= person][src *=lorem] { }', - fixed: 'img[alt ~= person][src *= lorem] { }', - message: messages.expectedAfter('*='), - line: 1, - column: 25, - }, - { - code: '[target=_blank]:hover { }', - fixed: '[target= _blank]:hover { }', - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target =_blank]:hover { }', - fixed: '[target = _blank]:hover { }', - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[target=_blank]::before { }', - fixed: '[target= _blank]::before { }', - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target =_blank]::before { }', - fixed: '[target = _blank]::before { }', - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: 'option[data-hidden=true] { }', - fixed: 'option[data-hidden= true] { }', - message: messages.expectedAfter('='), - line: 1, - column: 19, - }, - { - code: 'option[data-hidden =true] { }', - fixed: 'option[data-hidden = true] { }', - message: messages.expectedAfter('='), - line: 1, - column: 20, - }, - { - code: '@media screen and (max-width: 480px) { img[align=right] {} }', - fixed: '@media screen and (max-width: 480px) { img[align= right] {} }', - message: messages.expectedAfter('='), - line: 1, - column: 49, - }, - { - code: '@media screen and (max-width: 480px) { img[align =right] {} }', - fixed: '@media screen and (max-width: 480px) { img[align = right] {} }', - message: messages.expectedAfter('='), - line: 1, - column: 50, - }, - { - code: '[target=_blank] .foo { }', - fixed: '[target= _blank] .foo { }', - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target =_blank] .foo { }', - fixed: '[target = _blank] .foo { }', - message: messages.expectedAfter('='), - line: 1, - column: 9, - }, - { - code: 'li[aria-hidden=false]:nth-child(1) { }', - fixed: 'li[aria-hidden= false]:nth-child(1) { }', - message: messages.expectedAfter('='), - line: 1, - column: 15, - }, - { - code: 'li[aria-hidden=false]:nth-child( 1) { }', - fixed: 'li[aria-hidden= false]:nth-child( 1) { }', - message: messages.expectedAfter('='), - line: 1, - column: 15, - }, - { - code: 'li[aria-hidden=false]:nth-child(1 ) { }', - fixed: 'li[aria-hidden= false]:nth-child(1 ) { }', - message: messages.expectedAfter('='), - line: 1, - column: 15, - }, - { - code: 'li[aria-hidden=false]:nth-child( 1 ) { }', - fixed: 'li[aria-hidden= false]:nth-child( 1 ) { }', - message: messages.expectedAfter('='), - line: 1, - column: 15, - }, - { - code: 'li[aria-hidden =false]:nth-child(1) { }', - fixed: 'li[aria-hidden = false]:nth-child(1) { }', - message: messages.expectedAfter('='), - line: 1, - column: 16, - }, - { - code: 'li[aria-hidden =false]:nth-child( 1) { }', - fixed: 'li[aria-hidden = false]:nth-child( 1) { }', - message: messages.expectedAfter('='), - line: 1, - column: 16, - }, - { - code: 'li[aria-hidden =false]:nth-child(1 ) { }', - fixed: 'li[aria-hidden = false]:nth-child(1 ) { }', - message: messages.expectedAfter('='), - line: 1, - column: 16, - }, - { - code: 'li[aria-hidden =false]:nth-child( 1 ) { }', - fixed: 'li[aria-hidden = false]:nth-child( 1 ) { }', - message: messages.expectedAfter('='), - line: 1, - column: 16, - }, - { - code: 'ul li[aria-hidden=false] + li[aria-hidden= false] a { }', - fixed: 'ul li[aria-hidden= false] + li[aria-hidden= false] a { }', - message: messages.expectedAfter('='), - line: 1, - column: 18, - }, - { - code: 'ul li[aria-hidden= false] + li[aria-hidden=false] a { }', - fixed: 'ul li[aria-hidden= false] + li[aria-hidden= false] a { }', - message: messages.expectedAfter('='), - line: 1, - column: 43, - }, - { - code: 'ul li[aria-hidden =false] + li[aria-hidden= false] a { }', - fixed: 'ul li[aria-hidden = false] + li[aria-hidden= false] a { }', - message: messages.expectedAfter('='), - line: 1, - column: 19, - }, - { - code: 'ul li[aria-hidden = false] + li[aria-hidden=false] a { }', - fixed: 'ul li[aria-hidden = false] + li[aria-hidden= false] a { }', - message: messages.expectedAfter('='), - line: 1, - column: 44, - }, - { - code: 'ul li[aria-hidden=false] + li[aria-hidden = false] a { }', - fixed: 'ul li[aria-hidden= false] + li[aria-hidden = false] a { }', - message: messages.expectedAfter('='), - line: 1, - column: 18, - }, - { - code: 'ul li[aria-hidden= false] + li[aria-hidden =false] a { }', - fixed: 'ul li[aria-hidden= false] + li[aria-hidden = false] a { }', - message: messages.expectedAfter('='), - line: 1, - column: 44, - }, - { - code: 'ul li[aria-hidden =false] + li[aria-hidden = false] a { }', - fixed: 'ul li[aria-hidden = false] + li[aria-hidden = false] a { }', - message: messages.expectedAfter('='), - line: 1, - column: 19, - }, - { - code: 'ul li[aria-hidden = false] + li[aria-hidden =false] a { }', - fixed: 'ul li[aria-hidden = false] + li[aria-hidden = false] a { }', - message: messages.expectedAfter('='), - line: 1, - column: 45, - }, - { - code: 'ul li[aria-hidden=false] + li[aria-hidden=false] a { }', - fixed: 'ul li[aria-hidden= false] + li[aria-hidden= false] a { }', - warnings: [ - { - message: messages.expectedAfter('='), - line: 1, - column: 18, - }, - { - message: messages.expectedAfter('='), - line: 1, - column: 42, - }, - ], - }, - { - code: '[target=/**/"_blank"] { }', - fixed: '[target= /**/"_blank"] { }', - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target=/**/ "_blank"] { }', - fixed: '[target= /**/ "_blank"] { }', - message: messages.expectedAfter('='), - line: 1, - column: 8, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: '.foo { }', - }, - { - code: '[target] { }', - }, - { - code: '[ target] { }', - }, - { - code: '[target ] { }', - }, - { - code: '[ target ] { }', - }, - { - code: '[target=_blank] { }', - }, - { - code: '[target =_blank] { }', - }, - { - code: '[target=_blank ] { }', - }, - { - code: '[target =_blank ] { }', - }, - { - code: '[ target=_blank] { }', - }, - { - code: '[ target =_blank] { }', - }, - { - code: '[ target=_blank ] { }', - }, - { - code: '[ target =_blank ] { }', - }, - { - code: "[target='_blank'] { }", - }, - { - code: "[target ='_blank'] { }", - }, - { - code: "[target=' _blank'] { }", - }, - { - code: "[target='_blank' ] { }", - }, - { - code: "[target='_blank '] { }", - }, - { - code: "[target ='_blank' ] { }", - }, - { - code: "[target=' _blank '] { }", - }, - { - code: "[ target='_blank'] { }", - }, - { - code: "[ target ='_blank'] { }", - }, - { - code: "[ target=' _blank'] { }", - }, - { - code: "[ target='_blank' ] { }", - }, - { - code: "[ target='_blank '] { }", - }, - { - code: "[ target ='_blank' ] { }", - }, - { - code: "[ target=' _blank '] { }", - }, - { - code: '[target="_blank"] { }', - }, - { - code: '[target ="_blank"] { }', - }, - { - code: '[target=" _blank"] { }', - }, - { - code: '[target="_blank" ] { }', - }, - { - code: '[target="_blank "] { }', - }, - { - code: '[target ="_blank" ] { }', - }, - { - code: '[target=" _blank "] { }', - }, - { - code: '[ target="_blank"] { }', - }, - { - code: '[ target ="_blank"] { }', - }, - { - code: '[ target=" _blank"] { }', - }, - { - code: '[ target="_blank" ] { }', - }, - { - code: '[ target="_blank "] { }', - }, - { - code: '[ target ="_blank" ] { }', - }, - { - code: '[ target=" _blank "] { }', - }, - { - code: '[title~=flower] { }', - }, - { - code: '[title ~=flower] { }', - }, - { - code: '[title|=flower] { }', - }, - { - code: '[title |=flower] { }', - }, - { - code: '[title^=flower] { }', - }, - { - code: '[title ^=flower] { }', - }, - { - code: '[title$=flower] { }', - }, - { - code: '[title $=flower] { }', - }, - { - code: 'a[href*=w3schools] { }', - }, - { - code: 'a[href *=w3schools] { }', - }, - { - code: 'img[alt~=person][src*=lorem] { }', - }, - { - code: 'img[alt ~=person][src*=lorem] { }', - }, - { - code: 'img[alt~=person][src *=lorem] { }', - }, - { - code: 'img[alt ~=person][src *=lorem] { }', - }, - { - code: '[target=_blank]:hover { }', - }, - { - code: '[target =_blank]:hover { }', - }, - { - code: '[target=_blank]::before { }', - }, - { - code: '[target =_blank]::before { }', - }, - { - code: 'option[data-hidden=true] { }', - }, - { - code: 'option[data-hidden =true] { }', - }, - { - code: 'option[dataHidden] { }', - }, - { - code: '@media screen and (max-width: 480px) { img[align=right] {} }', - }, - { - code: '@media screen and (max-width: 480px) { img[align =right] {} }', - }, - { - code: '[target=_blank] .foo { }', - }, - { - code: '[target =_blank] .foo { }', - }, - { - code: 'li[aria-hidden=false]:nth-child(1) { }', - }, - { - code: 'li[aria-hidden=false]:nth-child( 1) { }', - }, - { - code: 'li[aria-hidden=false]:nth-child(1 ) { }', - }, - { - code: 'li[aria-hidden=false]:nth-child( 1 ) { }', - }, - { - code: 'li[aria-hidden =false]:nth-child(1) { }', - }, - { - code: 'li[aria-hidden =false]:nth-child( 1) { }', - }, - { - code: 'li[aria-hidden =false]:nth-child(1 ) { }', - }, - { - code: 'li[aria-hidden =false]:nth-child( 1 ) { }', - }, - { - code: 'ul li[aria-hidden=false] + li[aria-hidden=false] a { }', - }, - { - code: 'ul li[aria-hidden =false] + li[aria-hidden=false] a { }', - }, - { - code: 'ul li[aria-hidden=false] + li[aria-hidden =false] a { }', - }, - { - code: 'ul li[aria-hidden =false] + li[aria-hidden =false] a { }', - }, - { - code: '[target] { content: " " }', - }, - { - code: '[target ] { content: " " }', - }, - { - code: '[ target] { content: " " }', - }, - { - code: '[ target ] { content: " " }', - }, - ], - - reject: [ - { - code: '[target= _blank] { }', - fixed: '[target=_blank] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target = _blank] { }', - fixed: '[target =_blank] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[target= _blank ] { }', - fixed: '[target=_blank ] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target = _blank ] { }', - fixed: '[target =_blank ] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[ target= _blank] { }', - fixed: '[ target=_blank] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[ target = _blank] { }', - fixed: '[ target =_blank] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 10, - }, - { - code: '[ target= _blank ] { }', - fixed: '[ target=_blank ] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[ target = _blank ] { }', - fixed: '[ target =_blank ] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 10, - }, - { - code: "[target= '_blank'] { }", - fixed: "[target='_blank'] { }", - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - { - code: "[target = '_blank'] { }", - fixed: "[target ='_blank'] { }", - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: "[target= ' _blank'] { }", - fixed: "[target=' _blank'] { }", - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - { - code: "[target= '_blank' ] { }", - fixed: "[target='_blank' ] { }", - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - { - code: "[target= '_blank '] { }", - fixed: "[target='_blank '] { }", - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - { - code: "[target = '_blank' ] { }", - fixed: "[target ='_blank' ] { }", - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: "[target= ' _blank '] { }", - fixed: "[target=' _blank '] { }", - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - { - code: "[ target= '_blank'] { }", - fixed: "[ target='_blank'] { }", - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: "[ target = '_blank'] { }", - fixed: "[ target ='_blank'] { }", - message: messages.rejectedAfter('='), - line: 1, - column: 10, - }, - { - code: "[ target= ' _blank'] { }", - fixed: "[ target=' _blank'] { }", - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: "[ target= '_blank' ] { }", - fixed: "[ target='_blank' ] { }", - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: "[ target= '_blank '] { }", - fixed: "[ target='_blank '] { }", - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: "[ target = '_blank' ] { }", - fixed: "[ target ='_blank' ] { }", - message: messages.rejectedAfter('='), - line: 1, - column: 10, - }, - { - code: "[ target= ' _blank '] { }", - fixed: "[ target=' _blank '] { }", - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[target= "_blank"] { }', - fixed: '[target="_blank"] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target = "_blank"] { }', - fixed: '[target ="_blank"] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[target= " _blank"] { }', - fixed: '[target=" _blank"] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target= "_blank" ] { }', - fixed: '[target="_blank" ] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target= "_blank "] { }', - fixed: '[target="_blank "] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target = "_blank" ] { }', - fixed: '[target ="_blank" ] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[target= " _blank "] { }', - fixed: '[target=" _blank "] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[ target= "_blank"] { }', - fixed: '[ target="_blank"] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[ target = "_blank"] { }', - fixed: '[ target ="_blank"] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 10, - }, - { - code: '[ target= " _blank"] { }', - fixed: '[ target=" _blank"] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[ target= "_blank" ] { }', - fixed: '[ target="_blank" ] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[ target= "_blank "] { }', - fixed: '[ target="_blank "] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[ target = "_blank" ] { }', - fixed: '[ target ="_blank" ] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 10, - }, - { - code: '[ target= " _blank "] { }', - fixed: '[ target=" _blank "] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[title~= flower] { }', - fixed: '[title~=flower] { }', - message: messages.rejectedAfter('~='), - line: 1, - column: 8, - }, - { - code: '[title ~= flower] { }', - fixed: '[title ~=flower] { }', - message: messages.rejectedAfter('~='), - line: 1, - column: 9, - }, - { - code: '[title|= flower] { }', - fixed: '[title|=flower] { }', - message: messages.rejectedAfter('|='), - line: 1, - column: 8, - }, - { - code: '[title |= flower] { }', - fixed: '[title |=flower] { }', - message: messages.rejectedAfter('|='), - line: 1, - column: 9, - }, - { - code: '[title^= flower] { }', - fixed: '[title^=flower] { }', - message: messages.rejectedAfter('^='), - line: 1, - column: 8, - }, - { - code: '[title ^= flower] { }', - fixed: '[title ^=flower] { }', - message: messages.rejectedAfter('^='), - line: 1, - column: 9, - }, - { - code: '[title$= flower] { }', - fixed: '[title$=flower] { }', - message: messages.rejectedAfter('$='), - line: 1, - column: 8, - }, - { - code: '[title $= flower] { }', - fixed: '[title $=flower] { }', - message: messages.rejectedAfter('$='), - line: 1, - column: 9, - }, - { - code: 'a[href*= w3schools] { }', - fixed: 'a[href*=w3schools] { }', - message: messages.rejectedAfter('*='), - line: 1, - column: 8, - }, - { - code: 'a[href *= w3schools] { }', - fixed: 'a[href *=w3schools] { }', - message: messages.rejectedAfter('*='), - line: 1, - column: 9, - }, - { - code: 'img[alt~= person][src*=lorem] { }', - fixed: 'img[alt~=person][src*=lorem] { }', - message: messages.rejectedAfter('~='), - line: 1, - column: 9, - }, - { - code: 'img[alt ~= person][src*=lorem] { }', - fixed: 'img[alt ~=person][src*=lorem] { }', - message: messages.rejectedAfter('~='), - line: 1, - column: 10, - }, - { - code: 'img[alt~=person][src *= lorem] { }', - fixed: 'img[alt~=person][src *=lorem] { }', - message: messages.rejectedAfter('*='), - line: 1, - column: 23, - }, - { - code: 'img[alt ~=person][src *= lorem] { }', - fixed: 'img[alt ~=person][src *=lorem] { }', - message: messages.rejectedAfter('*='), - line: 1, - column: 24, - }, - { - code: '[target= _blank]:hover { }', - fixed: '[target=_blank]:hover { }', - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target = _blank]:hover { }', - fixed: '[target =_blank]:hover { }', - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: '[target= _blank]::before { }', - fixed: '[target=_blank]::before { }', - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target = _blank]::before { }', - fixed: '[target =_blank]::before { }', - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: 'option[data-hidden= true] { }', - fixed: 'option[data-hidden=true] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 19, - }, - { - code: 'option[data-hidden = true] { }', - fixed: 'option[data-hidden =true] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 20, - }, - { - code: '@media screen and (max-width: 480px) { img[align= right] {} }', - fixed: '@media screen and (max-width: 480px) { img[align=right] {} }', - message: messages.rejectedAfter('='), - line: 1, - column: 49, - }, - { - code: '@media screen and (max-width: 480px) { img[align = right] {} }', - fixed: '@media screen and (max-width: 480px) { img[align =right] {} }', - message: messages.rejectedAfter('='), - line: 1, - column: 50, - }, - { - code: '[target= _blank] .foo { }', - fixed: '[target=_blank] .foo { }', - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target = _blank] .foo { }', - fixed: '[target =_blank] .foo { }', - message: messages.rejectedAfter('='), - line: 1, - column: 9, - }, - { - code: 'li[aria-hidden= false]:nth-child(1) { }', - fixed: 'li[aria-hidden=false]:nth-child(1) { }', - message: messages.rejectedAfter('='), - line: 1, - column: 15, - }, - { - code: 'li[aria-hidden= false]:nth-child( 1) { }', - fixed: 'li[aria-hidden=false]:nth-child( 1) { }', - message: messages.rejectedAfter('='), - line: 1, - column: 15, - }, - { - code: 'li[aria-hidden= false]:nth-child(1 ) { }', - fixed: 'li[aria-hidden=false]:nth-child(1 ) { }', - message: messages.rejectedAfter('='), - line: 1, - column: 15, - }, - { - code: 'li[aria-hidden= false]:nth-child( 1 ) { }', - fixed: 'li[aria-hidden=false]:nth-child( 1 ) { }', - message: messages.rejectedAfter('='), - line: 1, - column: 15, - }, - { - code: 'li[aria-hidden = false]:nth-child(1) { }', - fixed: 'li[aria-hidden =false]:nth-child(1) { }', - message: messages.rejectedAfter('='), - line: 1, - column: 16, - }, - { - code: 'li[aria-hidden = false]:nth-child( 1) { }', - fixed: 'li[aria-hidden =false]:nth-child( 1) { }', - message: messages.rejectedAfter('='), - line: 1, - column: 16, - }, - { - code: 'li[aria-hidden = false]:nth-child(1 ) { }', - fixed: 'li[aria-hidden =false]:nth-child(1 ) { }', - message: messages.rejectedAfter('='), - line: 1, - column: 16, - }, - { - code: 'li[aria-hidden = false]:nth-child( 1 ) { }', - fixed: 'li[aria-hidden =false]:nth-child( 1 ) { }', - message: messages.rejectedAfter('='), - line: 1, - column: 16, - }, - { - code: 'ul li[aria-hidden= false] + li[aria-hidden=false] a { }', - fixed: 'ul li[aria-hidden=false] + li[aria-hidden=false] a { }', - message: messages.rejectedAfter('='), - line: 1, - column: 18, - }, - { - code: 'ul li[aria-hidden=false] + li[aria-hidden= false] a { }', - fixed: 'ul li[aria-hidden=false] + li[aria-hidden=false] a { }', - message: messages.rejectedAfter('='), - line: 1, - column: 42, - }, - { - code: 'ul li[aria-hidden = false] + li[aria-hidden=false] a { }', - fixed: 'ul li[aria-hidden =false] + li[aria-hidden=false] a { }', - message: messages.rejectedAfter('='), - line: 1, - column: 19, - }, - { - code: 'ul li[aria-hidden =false] + li[aria-hidden= false] a { }', - fixed: 'ul li[aria-hidden =false] + li[aria-hidden=false] a { }', - message: messages.rejectedAfter('='), - line: 1, - column: 43, - }, - { - code: 'ul li[aria-hidden= false] + li[aria-hidden =false] a { }', - fixed: 'ul li[aria-hidden=false] + li[aria-hidden =false] a { }', - message: messages.rejectedAfter('='), - line: 1, - column: 18, - }, - { - code: 'ul li[aria-hidden=false] + li[aria-hidden = false] a { }', - fixed: 'ul li[aria-hidden=false] + li[aria-hidden =false] a { }', - message: messages.rejectedAfter('='), - line: 1, - column: 43, - }, - { - code: 'ul li[aria-hidden = false] + li[aria-hidden =false] a { }', - fixed: 'ul li[aria-hidden =false] + li[aria-hidden =false] a { }', - message: messages.rejectedAfter('='), - line: 1, - column: 19, - }, - { - code: 'ul li[aria-hidden =false] + li[aria-hidden = false] a { }', - fixed: 'ul li[aria-hidden =false] + li[aria-hidden =false] a { }', - message: messages.rejectedAfter('='), - line: 1, - column: 44, - }, - { - code: 'ul li[aria-hidden = false] + li[aria-hidden = false] a { }', - fixed: 'ul li[aria-hidden =false] + li[aria-hidden =false] a { }', - warnings: [ - { - message: messages.rejectedAfter('='), - line: 1, - column: 19, - }, - { - message: messages.rejectedAfter('='), - line: 1, - column: 45, - }, - ], - }, - { - code: '[target= /**/"_blank"] { }', - fixed: '[target=/**/"_blank"] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - { - code: '[target= /**/ "_blank"] { }', - fixed: '[target=/**/ "_blank"] { }', - message: messages.rejectedAfter('='), - line: 1, - column: 8, - }, - ], -}); diff --git a/lib/rules/selector-attribute-operator-space-after/index.js b/lib/rules/selector-attribute-operator-space-after/index.js deleted file mode 100644 index e5c84f2b43..0000000000 --- a/lib/rules/selector-attribute-operator-space-after/index.js +++ /dev/null @@ -1,110 +0,0 @@ -'use strict'; - -const ruleMessages = require('../../utils/ruleMessages'); -const selectorAttributeOperatorSpaceChecker = require('../selectorAttributeOperatorSpaceChecker'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'selector-attribute-operator-space-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: (operator) => `Expected single space after "${operator}"`, - rejectedAfter: (operator) => `Unexpected whitespace after "${operator}"`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/selector-attribute-operator-space-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const checker = whitespaceChecker('space', primary, messages); - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - selectorAttributeOperatorSpaceChecker({ - root, - result, - locationChecker: checker.after, - checkedRuleName: ruleName, - checkBeforeOperator: false, - fix: context.fix - ? (attributeNode) => { - /** @type {{ operatorAfter: string, setOperatorAfter: (fixed: string) => void }} */ - const { operatorAfter, setOperatorAfter } = (() => { - const rawOperator = attributeNode.raws.operator; - - if (rawOperator) { - return { - operatorAfter: rawOperator.slice( - attributeNode.operator ? attributeNode.operator.length : 0, - ), - setOperatorAfter(fixed) { - delete attributeNode.raws.operator; - - if (!attributeNode.raws.spaces) attributeNode.raws.spaces = {}; - - if (!attributeNode.raws.spaces.operator) - attributeNode.raws.spaces.operator = {}; - - attributeNode.raws.spaces.operator.after = fixed; - }, - }; - } - - const rawSpacesOperator = - attributeNode.raws.spaces && attributeNode.raws.spaces.operator; - const rawOperatorAfter = rawSpacesOperator && rawSpacesOperator.after; - - if (rawOperatorAfter) { - return { - operatorAfter: rawOperatorAfter, - setOperatorAfter(fixed) { - rawSpacesOperator.after = fixed; - }, - }; - } - - return { - operatorAfter: - (attributeNode.spaces.operator && attributeNode.spaces.operator.after) || '', - setOperatorAfter(fixed) { - if (!attributeNode.spaces.operator) attributeNode.spaces.operator = {}; - - attributeNode.spaces.operator.after = fixed; - }, - }; - })(); - - if (primary === 'always') { - setOperatorAfter(operatorAfter.replace(/^\s*/, ' ')); - - return true; - } - - if (primary === 'never') { - setOperatorAfter(operatorAfter.replace(/^\s*/, '')); - - return true; - } - - return false; - } - : null, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/selector-attribute-operator-space-before/README.md b/lib/rules/selector-attribute-operator-space-before/README.md deleted file mode 100644 index 5753b98f08..0000000000 --- a/lib/rules/selector-attribute-operator-space-before/README.md +++ /dev/null @@ -1,164 +0,0 @@ -# selector-attribute-operator-space-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace before operators within attribute selectors. - - -```css -[target =_blank] -/** ↑ - * The space before operator */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a single space before the operator. - -The following patterns are considered problems: - - -```css -[target=_blank] {} -``` - - -```css -[target= _blank] {} -``` - - -```css -[target='_blank'] {} -``` - - -```css -[target="_blank"] {} -``` - - -```css -[target= '_blank'] {} -``` - - -```css -[target= "_blank"] {} -``` - -The following patterns are _not_ considered problems: - - -```css -[target] {} -``` - - -```css -[target =_blank] {} -``` - - -```css -[target ='_blank'] {} -``` - - -```css -[target ="_blank"] {} -``` - - -```css -[target = _blank] {} -``` - - -```css -[target = '_blank'] {} -``` - - -```css -[target = "_blank"] {} -``` - -### `"never"` - -There _must never_ be a single space before the operator. - -The following patterns are considered problems: - - -```css -[target =_blank] {} -``` - - -```css -[target = _blank] {} -``` - - -```css -[target ='_blank'] {} -``` - - -```css -[target ="_blank"] {} -``` - - -```css -[target = '_blank'] {} -``` - - -```css -[target = "_blank"] {} -``` - -The following patterns are _not_ considered problems: - - -```css -[target] {} -``` - - -```css -[target=_blank] {} -``` - - -```css -[target='_blank'] {} -``` - - -```css -[target="_blank"] {} -``` - - -```css -[target= _blank] {} -``` - - -```css -[target= '_blank'] {} -``` - - -```css -[target= "_blank"] {} -``` diff --git a/lib/rules/selector-attribute-operator-space-before/__tests__/index.js b/lib/rules/selector-attribute-operator-space-before/__tests__/index.js deleted file mode 100644 index 37104ca393..0000000000 --- a/lib/rules/selector-attribute-operator-space-before/__tests__/index.js +++ /dev/null @@ -1,1663 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: '.foo { }', - }, - { - code: '[target] { }', - }, - { - code: '[ target] { }', - }, - { - code: '[target ] { }', - }, - { - code: '[ target ] { }', - }, - { - code: '[target =_blank] { }', - }, - { - code: '[target = _blank] { }', - }, - { - code: '[target =_blank ] { }', - }, - { - code: '[target = _blank ] { }', - }, - { - code: '[ target =_blank] { }', - }, - { - code: '[ target = _blank] { }', - }, - { - code: '[ target =_blank ] { }', - }, - { - code: '[ target = _blank ] { }', - }, - { - code: "[target ='_blank'] { }", - }, - { - code: "[target = '_blank'] { }", - }, - { - code: "[target =' _blank'] { }", - }, - { - code: "[target ='_blank' ] { }", - }, - { - code: "[target ='_blank '] { }", - }, - { - code: "[target = '_blank' ] { }", - }, - { - code: "[target =' _blank '] { }", - }, - { - code: "[ target ='_blank'] { }", - }, - { - code: "[ target = '_blank'] { }", - }, - { - code: "[ target =' _blank'] { }", - }, - { - code: "[ target ='_blank' ] { }", - }, - { - code: "[ target ='_blank '] { }", - }, - { - code: "[ target = '_blank' ] { }", - }, - { - code: "[ target =' _blank '] { }", - }, - { - code: '[target ="_blank"] { }', - }, - { - code: '[target = "_blank"] { }', - }, - { - code: '[target =" _blank"] { }', - }, - { - code: '[target ="_blank" ] { }', - }, - { - code: '[target ="_blank "] { }', - }, - { - code: '[target = "_blank" ] { }', - }, - { - code: '[target =" _blank "] { }', - }, - { - code: '[ target ="_blank"] { }', - }, - { - code: '[ target = "_blank"] { }', - }, - { - code: '[ target =" _blank"] { }', - }, - { - code: '[ target ="_blank" ] { }', - }, - { - code: '[ target ="_blank "] { }', - }, - { - code: '[ target = "_blank" ] { }', - }, - { - code: '[ target =" _blank "] { }', - }, - { - code: '[title ~=flower] { }', - }, - { - code: '[title ~= flower] { }', - }, - { - code: '[title |=flower] { }', - }, - { - code: '[title |= flower] { }', - }, - { - code: '[title ^=flower] { }', - }, - { - code: '[title ^= flower] { }', - }, - { - code: '[title $=flower] { }', - }, - { - code: '[title $= flower] { }', - }, - { - code: 'a[href *=w3schools] { }', - }, - { - code: 'a[href *= w3schools] { }', - }, - { - code: 'img[alt ~=person][src *=lorem] { }', - }, - { - code: 'img[alt ~= person][src *=lorem] { }', - }, - { - code: 'img[alt ~=person][src *= lorem] { }', - }, - { - code: 'img[alt ~= person][src *= lorem] { }', - }, - { - code: '[target =_blank]:hover { }', - }, - { - code: '[target = _blank]:hover { }', - }, - { - code: '[target =_blank]::before { }', - }, - { - code: '[target = _blank]::before { }', - }, - { - code: 'option[data-hidden =true] { }', - }, - { - code: 'option[data-hidden = true] { }', - }, - { - code: 'option[dataHidden] { }', - }, - { - code: '@media screen and (max-width: 480px) { img[align =right] {} }', - }, - { - code: '@media screen and (max-width: 480px) { img[align = right] {} }', - }, - { - code: '[target =_blank] .foo { }', - }, - { - code: '[target = _blank] .foo { }', - }, - { - code: 'li[aria-hidden =false]:nth-child(1) { }', - }, - { - code: 'li[aria-hidden =false]:nth-child( 1) { }', - }, - { - code: 'li[aria-hidden =false]:nth-child(1 ) { }', - }, - { - code: 'li[aria-hidden =false]:nth-child( 1 ) { }', - }, - { - code: 'li[aria-hidden = false]:nth-child(1) { }', - }, - { - code: 'li[aria-hidden = false]:nth-child( 1) { }', - }, - { - code: 'li[aria-hidden = false]:nth-child(1 ) { }', - }, - { - code: 'li[aria-hidden = false]:nth-child( 1 ) { }', - }, - { - code: 'ul li[aria-hidden =false] + li[aria-hidden =false] a { }', - }, - { - code: 'ul li[aria-hidden = false] + li[aria-hidden =false] a { }', - }, - { - code: 'ul li[aria-hidden =false] + li[aria-hidden = false] a { }', - }, - { - code: 'ul li[aria-hidden = false] + li[aria-hidden = false] a { }', - }, - { - code: '[target] { content: " " }', - }, - { - code: '[target ] { content: " " }', - }, - { - code: '[ target] { content: " " }', - }, - { - code: '[ target ] { content: " " }', - }, - { - 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', - }, - { - code: 'a[b=#{c}] { }', - description: 'ignore "invalid" selector (see #3130)', - }, - ], - - reject: [ - { - code: '[target=_blank] { }', - fixed: '[target =_blank] { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: '[target= _blank] { }', - fixed: '[target = _blank] { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: '[target=_blank ] { }', - fixed: '[target =_blank ] { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: '[target= _blank ] { }', - fixed: '[target = _blank ] { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: '[ target=_blank] { }', - fixed: '[ target =_blank] { }', - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[ target= _blank] { }', - fixed: '[ target = _blank] { }', - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[ target=_blank ] { }', - fixed: '[ target =_blank ] { }', - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[ target= _blank ] { }', - fixed: '[ target = _blank ] { }', - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: "[target='_blank'] { }", - fixed: "[target ='_blank'] { }", - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: "[target= '_blank'] { }", - fixed: "[target = '_blank'] { }", - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: "[target=' _blank'] { }", - fixed: "[target =' _blank'] { }", - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: "[target='_blank' ] { }", - fixed: "[target ='_blank' ] { }", - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: "[target='_blank '] { }", - fixed: "[target ='_blank '] { }", - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: "[target= '_blank' ] { }", - fixed: "[target = '_blank' ] { }", - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: "[target=' _blank '] { }", - fixed: "[target =' _blank '] { }", - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: "[ target='_blank'] { }", - fixed: "[ target ='_blank'] { }", - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: "[ target= '_blank'] { }", - fixed: "[ target = '_blank'] { }", - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: "[ target=' _blank'] { }", - fixed: "[ target =' _blank'] { }", - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: "[ target='_blank' ] { }", - fixed: "[ target ='_blank' ] { }", - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: "[ target='_blank '] { }", - fixed: "[ target ='_blank '] { }", - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: "[ target= '_blank' ] { }", - fixed: "[ target = '_blank' ] { }", - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: "[ target=' _blank '] { }", - fixed: "[ target =' _blank '] { }", - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[target="_blank"] { }', - fixed: '[target ="_blank"] { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: '[target= "_blank"] { }', - fixed: '[target = "_blank"] { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: '[target=" _blank"] { }', - fixed: '[target =" _blank"] { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: '[target="_blank" ] { }', - fixed: '[target ="_blank" ] { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: '[target="_blank "] { }', - fixed: '[target ="_blank "] { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: '[target= "_blank" ] { }', - fixed: '[target = "_blank" ] { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: '[target=" _blank "] { }', - fixed: '[target =" _blank "] { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: '[ target="_blank"] { }', - fixed: '[ target ="_blank"] { }', - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[ target= "_blank"] { }', - fixed: '[ target = "_blank"] { }', - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[ target=" _blank"] { }', - fixed: '[ target =" _blank"] { }', - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[ target="_blank" ] { }', - fixed: '[ target ="_blank" ] { }', - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[ target="_blank "] { }', - fixed: '[ target ="_blank "] { }', - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[ target= "_blank" ] { }', - fixed: '[ target = "_blank" ] { }', - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[ target=" _blank "] { }', - fixed: '[ target =" _blank "] { }', - message: messages.expectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[title~=flower] { }', - fixed: '[title ~=flower] { }', - message: messages.expectedBefore('~='), - line: 1, - column: 7, - }, - { - code: '[title~= flower] { }', - fixed: '[title ~= flower] { }', - message: messages.expectedBefore('~='), - line: 1, - column: 7, - }, - { - code: '[title|=flower] { }', - fixed: '[title |=flower] { }', - message: messages.expectedBefore('|='), - line: 1, - column: 7, - }, - { - code: '[title|= flower] { }', - fixed: '[title |= flower] { }', - message: messages.expectedBefore('|='), - line: 1, - column: 7, - }, - { - code: '[title^=flower] { }', - fixed: '[title ^=flower] { }', - message: messages.expectedBefore('^='), - line: 1, - column: 7, - }, - { - code: '[title^= flower] { }', - fixed: '[title ^= flower] { }', - message: messages.expectedBefore('^='), - line: 1, - column: 7, - }, - { - code: '[title$=flower] { }', - fixed: '[title $=flower] { }', - message: messages.expectedBefore('$='), - line: 1, - column: 7, - }, - { - code: '[title$= flower] { }', - fixed: '[title $= flower] { }', - message: messages.expectedBefore('$='), - line: 1, - column: 7, - }, - { - code: 'a[href*=w3schools] { }', - fixed: 'a[href *=w3schools] { }', - message: messages.expectedBefore('*='), - line: 1, - column: 7, - }, - { - code: 'a[href*= w3schools] { }', - fixed: 'a[href *= w3schools] { }', - message: messages.expectedBefore('*='), - line: 1, - column: 7, - }, - { - code: 'img[alt~=person][src *=lorem] { }', - fixed: 'img[alt ~=person][src *=lorem] { }', - message: messages.expectedBefore('~='), - line: 1, - column: 8, - }, - { - code: 'img[alt~= person][src *=lorem] { }', - fixed: 'img[alt ~= person][src *=lorem] { }', - message: messages.expectedBefore('~='), - line: 1, - column: 8, - }, - { - code: 'img[alt ~=person][src*= lorem] { }', - fixed: 'img[alt ~=person][src *= lorem] { }', - message: messages.expectedBefore('*='), - line: 1, - column: 22, - }, - { - code: 'img[alt ~= person][src*= lorem] { }', - fixed: 'img[alt ~= person][src *= lorem] { }', - message: messages.expectedBefore('*='), - line: 1, - column: 23, - }, - { - code: '[target=_blank]:hover { }', - fixed: '[target =_blank]:hover { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: '[target= _blank]:hover { }', - fixed: '[target = _blank]:hover { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: '[target=_blank]::before { }', - fixed: '[target =_blank]::before { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: '[target= _blank]::before { }', - fixed: '[target = _blank]::before { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: 'option[data-hidden=true] { }', - fixed: 'option[data-hidden =true] { }', - message: messages.expectedBefore('='), - line: 1, - column: 19, - }, - { - code: 'option[data-hidden= true] { }', - fixed: 'option[data-hidden = true] { }', - message: messages.expectedBefore('='), - line: 1, - column: 19, - }, - { - code: '@media screen and (max-width: 480px) { img[align=right] {} }', - fixed: '@media screen and (max-width: 480px) { img[align =right] {} }', - message: messages.expectedBefore('='), - line: 1, - column: 49, - }, - { - code: '@media screen and (max-width: 480px) { img[align= right] {} }', - fixed: '@media screen and (max-width: 480px) { img[align = right] {} }', - message: messages.expectedBefore('='), - line: 1, - column: 49, - }, - { - code: '[target=_blank] .foo { }', - fixed: '[target =_blank] .foo { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: '[target= _blank] .foo { }', - fixed: '[target = _blank] .foo { }', - message: messages.expectedBefore('='), - line: 1, - column: 8, - }, - { - code: 'li[aria-hidden=false]:nth-child(1) { }', - fixed: 'li[aria-hidden =false]:nth-child(1) { }', - message: messages.expectedBefore('='), - line: 1, - column: 15, - }, - { - code: 'li[aria-hidden=false]:nth-child( 1) { }', - fixed: 'li[aria-hidden =false]:nth-child( 1) { }', - message: messages.expectedBefore('='), - line: 1, - column: 15, - }, - { - code: 'li[aria-hidden=false]:nth-child(1 ) { }', - fixed: 'li[aria-hidden =false]:nth-child(1 ) { }', - message: messages.expectedBefore('='), - line: 1, - column: 15, - }, - { - code: 'li[aria-hidden=false]:nth-child( 1 ) { }', - fixed: 'li[aria-hidden =false]:nth-child( 1 ) { }', - message: messages.expectedBefore('='), - line: 1, - column: 15, - }, - { - code: 'li[aria-hidden= false]:nth-child(1) { }', - fixed: 'li[aria-hidden = false]:nth-child(1) { }', - message: messages.expectedBefore('='), - line: 1, - column: 15, - }, - { - code: 'li[aria-hidden= false]:nth-child( 1) { }', - fixed: 'li[aria-hidden = false]:nth-child( 1) { }', - message: messages.expectedBefore('='), - line: 1, - column: 15, - }, - { - code: 'li[aria-hidden= false]:nth-child(1 ) { }', - fixed: 'li[aria-hidden = false]:nth-child(1 ) { }', - message: messages.expectedBefore('='), - line: 1, - column: 15, - }, - { - code: 'li[aria-hidden= false]:nth-child( 1 ) { }', - fixed: 'li[aria-hidden = false]:nth-child( 1 ) { }', - message: messages.expectedBefore('='), - line: 1, - column: 15, - }, - { - code: 'ul li[aria-hidden=false] + li[aria-hidden =false] a { }', - fixed: 'ul li[aria-hidden =false] + li[aria-hidden =false] a { }', - message: messages.expectedBefore('='), - line: 1, - column: 18, - }, - { - code: 'ul li[aria-hidden =false] + li[aria-hidden=false] a { }', - fixed: 'ul li[aria-hidden =false] + li[aria-hidden =false] a { }', - message: messages.expectedBefore('='), - line: 1, - column: 43, - }, - { - code: 'ul li[aria-hidden= false] + li[aria-hidden =false] a { }', - fixed: 'ul li[aria-hidden = false] + li[aria-hidden =false] a { }', - message: messages.expectedBefore('='), - line: 1, - column: 18, - }, - { - code: 'ul li[aria-hidden = false] + li[aria-hidden=false] a { }', - fixed: 'ul li[aria-hidden = false] + li[aria-hidden =false] a { }', - message: messages.expectedBefore('='), - line: 1, - column: 44, - }, - { - code: 'ul li[aria-hidden=false] + li[aria-hidden = false] a { }', - fixed: 'ul li[aria-hidden =false] + li[aria-hidden = false] a { }', - message: messages.expectedBefore('='), - line: 1, - column: 18, - }, - { - code: 'ul li[aria-hidden =false] + li[aria-hidden= false] a { }', - fixed: 'ul li[aria-hidden =false] + li[aria-hidden = false] a { }', - message: messages.expectedBefore('='), - line: 1, - column: 43, - }, - { - code: 'ul li[aria-hidden= false] + li[aria-hidden = false] a { }', - fixed: 'ul li[aria-hidden = false] + li[aria-hidden = false] a { }', - message: messages.expectedBefore('='), - line: 1, - column: 18, - }, - { - code: 'ul li[aria-hidden = false] + li[aria-hidden= false] a { }', - fixed: 'ul li[aria-hidden = false] + li[aria-hidden = false] a { }', - message: messages.expectedBefore('='), - line: 1, - column: 44, - }, - { - code: 'ul li[aria-hidden= false] + li[aria-hidden= false] a { }', - fixed: 'ul li[aria-hidden = false] + li[aria-hidden = false] a { }', - warnings: [ - { - message: messages.expectedBefore('='), - line: 1, - column: 18, - }, - { - message: messages.expectedBefore('='), - line: 1, - column: 43, - }, - ], - }, - { - code: '[target/**/="_blank"] { }', - fixed: '[target/**/ ="_blank"] { }', - message: messages.expectedBefore('='), - line: 1, - column: 12, - }, - { - code: '[target /**/="_blank"] { }', - fixed: '[target /**/ ="_blank"] { }', - message: messages.expectedBefore('='), - line: 1, - column: 13, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: '.foo { }', - }, - { - code: '[target] { }', - }, - { - code: '[ target] { }', - }, - { - code: '[target ] { }', - }, - { - code: '[ target ] { }', - }, - { - code: '[target=_blank] { }', - }, - { - code: '[target= _blank] { }', - }, - { - code: '[target=_blank ] { }', - }, - { - code: '[target= _blank ] { }', - }, - { - code: '[ target=_blank] { }', - }, - { - code: '[ target= _blank] { }', - }, - { - code: '[ target=_blank ] { }', - }, - { - code: '[ target= _blank ] { }', - }, - { - code: "[target='_blank'] { }", - }, - { - code: "[target= '_blank'] { }", - }, - { - code: "[target=' _blank'] { }", - }, - { - code: "[target='_blank' ] { }", - }, - { - code: "[target='_blank '] { }", - }, - { - code: "[target= '_blank' ] { }", - }, - { - code: "[target=' _blank '] { }", - }, - { - code: "[ target='_blank'] { }", - }, - { - code: "[ target= '_blank'] { }", - }, - { - code: "[ target=' _blank'] { }", - }, - { - code: "[ target='_blank' ] { }", - }, - { - code: "[ target='_blank '] { }", - }, - { - code: "[ target= '_blank' ] { }", - }, - { - code: "[ target=' _blank '] { }", - }, - { - code: '[target="_blank"] { }', - }, - { - code: '[target= "_blank"] { }', - }, - { - code: '[target=" _blank"] { }', - }, - { - code: '[target="_blank" ] { }', - }, - { - code: '[target="_blank "] { }', - }, - { - code: '[target= "_blank" ] { }', - }, - { - code: '[target=" _blank "] { }', - }, - { - code: '[ target="_blank"] { }', - }, - { - code: '[ target= "_blank"] { }', - }, - { - code: '[ target=" _blank"] { }', - }, - { - code: '[ target="_blank" ] { }', - }, - { - code: '[ target="_blank "] { }', - }, - { - code: '[ target= "_blank" ] { }', - }, - { - code: '[ target=" _blank "] { }', - }, - { - code: '[title~=flower] { }', - }, - { - code: '[title~= flower] { }', - }, - { - code: '[title|=flower] { }', - }, - { - code: '[title|= flower] { }', - }, - { - code: '[title^=flower] { }', - }, - { - code: '[title^= flower] { }', - }, - { - code: '[title$=flower] { }', - }, - { - code: '[title$= flower] { }', - }, - { - code: 'a[href*=w3schools] { }', - }, - { - code: 'a[href*= w3schools] { }', - }, - { - code: 'img[alt~=person][src*=lorem] { }', - }, - { - code: 'img[alt~= person][src*=lorem] { }', - }, - { - code: 'img[alt~=person][src*= lorem] { }', - }, - { - code: 'img[alt~= person][src*= lorem] { }', - }, - { - code: '[target=_blank]:hover { }', - }, - { - code: '[target= _blank]:hover { }', - }, - { - code: '[target=_blank]::before { }', - }, - { - code: '[target= _blank]::before { }', - }, - { - code: 'option[data-hidden=true] { }', - }, - { - code: 'option[data-hidden= true] { }', - }, - { - code: 'option[dataHidden] { }', - }, - { - code: '@media screen and (max-width: 480px) { img[align=right] {} }', - }, - { - code: '@media screen and (max-width: 480px) { img[align= right] {} }', - }, - { - code: '[target=_blank] .foo { }', - }, - { - code: '[target= _blank] .foo { }', - }, - { - code: 'li[aria-hidden=false]:nth-child(1) { }', - }, - { - code: 'li[aria-hidden=false]:nth-child( 1) { }', - }, - { - code: 'li[aria-hidden=false]:nth-child(1 ) { }', - }, - { - code: 'li[aria-hidden=false]:nth-child( 1 ) { }', - }, - { - code: 'li[aria-hidden= false]:nth-child(1) { }', - }, - { - code: 'li[aria-hidden= false]:nth-child( 1) { }', - }, - { - code: 'li[aria-hidden= false]:nth-child(1 ) { }', - }, - { - code: 'li[aria-hidden= false]:nth-child( 1 ) { }', - }, - { - code: 'ul li[aria-hidden=false] + li[aria-hidden=false] a { }', - }, - { - code: 'ul li[aria-hidden= false] + li[aria-hidden=false] a { }', - }, - { - code: 'ul li[aria-hidden=false] + li[aria-hidden= false] a { }', - }, - { - code: 'ul li[aria-hidden= false] + li[aria-hidden= false] a { }', - }, - { - code: '[target] { content: " " }', - }, - { - code: '[target ] { content: " " }', - }, - { - code: '[ target] { content: " " }', - }, - { - code: '[ target ] { content: " " }', - }, - ], - - reject: [ - { - code: '[target =_blank] { }', - fixed: '[target=_blank] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[target = _blank] { }', - fixed: '[target= _blank] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[target =_blank ] { }', - fixed: '[target=_blank ] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[target = _blank ] { }', - fixed: '[target= _blank ] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[ target =_blank] { }', - fixed: '[ target=_blank] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: '[ target = _blank] { }', - fixed: '[ target= _blank] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: '[ target =_blank ] { }', - fixed: '[ target=_blank ] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: '[ target = _blank ] { }', - fixed: '[ target= _blank ] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: "[target ='_blank'] { }", - fixed: "[target='_blank'] { }", - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: "[target = '_blank'] { }", - fixed: "[target= '_blank'] { }", - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: "[target =' _blank'] { }", - fixed: "[target=' _blank'] { }", - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: "[target ='_blank' ] { }", - fixed: "[target='_blank' ] { }", - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: "[target ='_blank '] { }", - fixed: "[target='_blank '] { }", - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: "[target = '_blank' ] { }", - fixed: "[target= '_blank' ] { }", - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: "[target =' _blank '] { }", - fixed: "[target=' _blank '] { }", - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: "[ target ='_blank'] { }", - fixed: "[ target='_blank'] { }", - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: "[ target = '_blank'] { }", - fixed: "[ target= '_blank'] { }", - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: "[ target =' _blank'] { }", - fixed: "[ target=' _blank'] { }", - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: "[ target ='_blank' ] { }", - fixed: "[ target='_blank' ] { }", - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: "[ target ='_blank '] { }", - fixed: "[ target='_blank '] { }", - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: "[ target = '_blank' ] { }", - fixed: "[ target= '_blank' ] { }", - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: "[ target =' _blank '] { }", - fixed: "[ target=' _blank '] { }", - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: '[target ="_blank"] { }', - fixed: '[target="_blank"] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[target = "_blank"] { }', - fixed: '[target= "_blank"] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[target =" _blank"] { }', - fixed: '[target=" _blank"] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[target ="_blank" ] { }', - fixed: '[target="_blank" ] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[target ="_blank "] { }', - fixed: '[target="_blank "] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[target = "_blank" ] { }', - fixed: '[target= "_blank" ] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[target =" _blank "] { }', - fixed: '[target=" _blank "] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[ target ="_blank"] { }', - fixed: '[ target="_blank"] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: '[ target = "_blank"] { }', - fixed: '[ target= "_blank"] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: '[ target =" _blank"] { }', - fixed: '[ target=" _blank"] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: '[ target ="_blank" ] { }', - fixed: '[ target="_blank" ] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: '[ target ="_blank "] { }', - fixed: '[ target="_blank "] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: '[ target = "_blank" ] { }', - fixed: '[ target= "_blank" ] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: '[ target =" _blank "] { }', - fixed: '[ target=" _blank "] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 10, - }, - { - code: '[title ~=flower] { }', - fixed: '[title~=flower] { }', - message: messages.rejectedBefore('~='), - line: 1, - column: 8, - }, - { - code: '[title ~= flower] { }', - fixed: '[title~= flower] { }', - message: messages.rejectedBefore('~='), - line: 1, - column: 8, - }, - { - code: '[title |=flower] { }', - fixed: '[title|=flower] { }', - message: messages.rejectedBefore('|='), - line: 1, - column: 8, - }, - { - code: '[title |= flower] { }', - fixed: '[title|= flower] { }', - message: messages.rejectedBefore('|='), - line: 1, - column: 8, - }, - { - code: '[title ^=flower] { }', - fixed: '[title^=flower] { }', - message: messages.rejectedBefore('^='), - line: 1, - column: 8, - }, - { - code: '[title ^= flower] { }', - fixed: '[title^= flower] { }', - message: messages.rejectedBefore('^='), - line: 1, - column: 8, - }, - { - code: '[title $=flower] { }', - fixed: '[title$=flower] { }', - message: messages.rejectedBefore('$='), - line: 1, - column: 8, - }, - { - code: '[title $= flower] { }', - fixed: '[title$= flower] { }', - message: messages.rejectedBefore('$='), - line: 1, - column: 8, - }, - { - code: 'a[href *=w3schools] { }', - fixed: 'a[href*=w3schools] { }', - message: messages.rejectedBefore('*='), - line: 1, - column: 8, - }, - { - code: 'a[href *= w3schools] { }', - fixed: 'a[href*= w3schools] { }', - message: messages.rejectedBefore('*='), - line: 1, - column: 8, - }, - { - code: 'img[alt ~=person][src*=lorem] { }', - fixed: 'img[alt~=person][src*=lorem] { }', - message: messages.rejectedBefore('~='), - line: 1, - column: 9, - }, - { - code: 'img[alt ~= person][src*=lorem] { }', - fixed: 'img[alt~= person][src*=lorem] { }', - message: messages.rejectedBefore('~='), - line: 1, - column: 9, - }, - { - code: 'img[alt~=person][src *= lorem] { }', - fixed: 'img[alt~=person][src*= lorem] { }', - message: messages.rejectedBefore('*='), - line: 1, - column: 22, - }, - { - code: 'img[alt~= person][src *= lorem] { }', - fixed: 'img[alt~= person][src*= lorem] { }', - message: messages.rejectedBefore('*='), - line: 1, - column: 23, - }, - { - code: '[target =_blank]:hover { }', - fixed: '[target=_blank]:hover { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[target = _blank]:hover { }', - fixed: '[target= _blank]:hover { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[target =_blank]::before { }', - fixed: '[target=_blank]::before { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[target = _blank]::before { }', - fixed: '[target= _blank]::before { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: 'option[data-hidden =true] { }', - fixed: 'option[data-hidden=true] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 20, - }, - { - code: 'option[data-hidden = true] { }', - fixed: 'option[data-hidden= true] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 20, - }, - { - code: '@media screen and (max-width: 480px) { img[align =right] {} }', - fixed: '@media screen and (max-width: 480px) { img[align=right] {} }', - message: messages.rejectedBefore('='), - line: 1, - column: 50, - }, - { - code: '@media screen and (max-width: 480px) { img[align = right] {} }', - fixed: '@media screen and (max-width: 480px) { img[align= right] {} }', - message: messages.rejectedBefore('='), - line: 1, - column: 50, - }, - { - code: '[target =_blank] .foo { }', - fixed: '[target=_blank] .foo { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: '[target = _blank] .foo { }', - fixed: '[target= _blank] .foo { }', - message: messages.rejectedBefore('='), - line: 1, - column: 9, - }, - { - code: 'li[aria-hidden =false]:nth-child(1) { }', - fixed: 'li[aria-hidden=false]:nth-child(1) { }', - message: messages.rejectedBefore('='), - line: 1, - column: 16, - }, - { - code: 'li[aria-hidden =false]:nth-child( 1) { }', - fixed: 'li[aria-hidden=false]:nth-child( 1) { }', - message: messages.rejectedBefore('='), - line: 1, - column: 16, - }, - { - code: 'li[aria-hidden =false]:nth-child(1 ) { }', - fixed: 'li[aria-hidden=false]:nth-child(1 ) { }', - message: messages.rejectedBefore('='), - line: 1, - column: 16, - }, - { - code: 'li[aria-hidden =false]:nth-child( 1 ) { }', - fixed: 'li[aria-hidden=false]:nth-child( 1 ) { }', - message: messages.rejectedBefore('='), - line: 1, - column: 16, - }, - { - code: 'li[aria-hidden = false]:nth-child(1) { }', - fixed: 'li[aria-hidden= false]:nth-child(1) { }', - message: messages.rejectedBefore('='), - line: 1, - column: 16, - }, - { - code: 'li[aria-hidden = false]:nth-child( 1) { }', - fixed: 'li[aria-hidden= false]:nth-child( 1) { }', - message: messages.rejectedBefore('='), - line: 1, - column: 16, - }, - { - code: 'li[aria-hidden = false]:nth-child(1 ) { }', - fixed: 'li[aria-hidden= false]:nth-child(1 ) { }', - message: messages.rejectedBefore('='), - line: 1, - column: 16, - }, - { - code: 'li[aria-hidden = false]:nth-child( 1 ) { }', - fixed: 'li[aria-hidden= false]:nth-child( 1 ) { }', - message: messages.rejectedBefore('='), - line: 1, - column: 16, - }, - { - code: 'ul li[aria-hidden =false] + li[aria-hidden=false] a { }', - fixed: 'ul li[aria-hidden=false] + li[aria-hidden=false] a { }', - message: messages.rejectedBefore('='), - line: 1, - column: 19, - }, - { - code: 'ul li[aria-hidden=false] + li[aria-hidden =false] a { }', - fixed: 'ul li[aria-hidden=false] + li[aria-hidden=false] a { }', - message: messages.rejectedBefore('='), - line: 1, - column: 43, - }, - { - code: 'ul li[aria-hidden = false] + li[aria-hidden=false] a { }', - fixed: 'ul li[aria-hidden= false] + li[aria-hidden=false] a { }', - message: messages.rejectedBefore('='), - line: 1, - column: 19, - }, - { - code: 'ul li[aria-hidden= false] + li[aria-hidden =false] a { }', - fixed: 'ul li[aria-hidden= false] + li[aria-hidden=false] a { }', - message: messages.rejectedBefore('='), - line: 1, - column: 44, - }, - { - code: 'ul li[aria-hidden =false] + li[aria-hidden= false] a { }', - fixed: 'ul li[aria-hidden=false] + li[aria-hidden= false] a { }', - message: messages.rejectedBefore('='), - line: 1, - column: 19, - }, - { - code: 'ul li[aria-hidden=false] + li[aria-hidden = false] a { }', - fixed: 'ul li[aria-hidden=false] + li[aria-hidden= false] a { }', - message: messages.rejectedBefore('='), - line: 1, - column: 43, - }, - { - code: 'ul li[aria-hidden = false] + li[aria-hidden= false] a { }', - fixed: 'ul li[aria-hidden= false] + li[aria-hidden= false] a { }', - message: messages.rejectedBefore('='), - line: 1, - column: 19, - }, - { - code: 'ul li[aria-hidden= false] + li[aria-hidden = false] a { }', - fixed: 'ul li[aria-hidden= false] + li[aria-hidden= false] a { }', - message: messages.rejectedBefore('='), - line: 1, - column: 44, - }, - { - code: 'ul li[aria-hidden = false] + li[aria-hidden = false] a { }', - fixed: 'ul li[aria-hidden= false] + li[aria-hidden= false] a { }', - warnings: [ - { - message: messages.rejectedBefore('='), - line: 1, - column: 19, - }, - { - message: messages.rejectedBefore('='), - line: 1, - column: 45, - }, - ], - }, - { - code: '[target/**/ ="_blank"] { }', - fixed: '[target/**/="_blank"] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 13, - }, - { - code: '[target /**/ ="_blank"] { }', - fixed: '[target /**/="_blank"] { }', - message: messages.rejectedBefore('='), - line: 1, - column: 14, - }, - ], -}); diff --git a/lib/rules/selector-attribute-operator-space-before/index.js b/lib/rules/selector-attribute-operator-space-before/index.js deleted file mode 100644 index 8ad04b1689..0000000000 --- a/lib/rules/selector-attribute-operator-space-before/index.js +++ /dev/null @@ -1,86 +0,0 @@ -'use strict'; - -const ruleMessages = require('../../utils/ruleMessages'); -const selectorAttributeOperatorSpaceChecker = require('../selectorAttributeOperatorSpaceChecker'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'selector-attribute-operator-space-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: (operator) => `Expected single space before "${operator}"`, - rejectedBefore: (operator) => `Unexpected whitespace before "${operator}"`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/selector-attribute-operator-space-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - selectorAttributeOperatorSpaceChecker({ - root, - result, - locationChecker: checker.before, - checkedRuleName: ruleName, - checkBeforeOperator: true, - fix: context.fix - ? (attributeNode) => { - const rawAttr = attributeNode.raws.spaces && attributeNode.raws.spaces.attribute; - const rawAttrAfter = rawAttr && rawAttr.after; - - /** @type {{ attrAfter: string, setAttrAfter: (fixed: string) => void }} */ - const { attrAfter, setAttrAfter } = rawAttrAfter - ? { - attrAfter: rawAttrAfter, - setAttrAfter(fixed) { - rawAttr.after = fixed; - }, - } - : { - attrAfter: - (attributeNode.spaces.attribute && attributeNode.spaces.attribute.after) || '', - setAttrAfter(fixed) { - if (!attributeNode.spaces.attribute) attributeNode.spaces.attribute = {}; - - attributeNode.spaces.attribute.after = fixed; - }, - }; - - if (primary === 'always') { - setAttrAfter(attrAfter.replace(/\s*$/, ' ')); - - return true; - } - - if (primary === 'never') { - setAttrAfter(attrAfter.replace(/\s*$/, '')); - - return true; - } - - return false; - } - : null, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/selector-combinator-space-after/README.md b/lib/rules/selector-combinator-space-after/README.md deleted file mode 100644 index 3371f8444d..0000000000 --- a/lib/rules/selector-combinator-space-after/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# selector-combinator-space-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace after the combinators of selectors. - - -```css - a > b + c ~ d e >>> f { color: pink; } -/** ↑ ↑ ↑ ↑ ↑ - * These are combinators */ -``` - -Combinators are used to combine several different selectors into new and more specific ones. There are several types of combinators, including: child (`>`), adjacent sibling (`+`), general sibling (`~`), and descendant (which is represented by a blank space between two selectors). - -The descendant combinator is _not_ checked by this rule. - -Also, `+` and `-` signs within `:nth-*()` arguments are not checked (e.g. `a:nth-child(2n+1)`). - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a single space after the combinators. - -The following patterns are considered problems: - - -```css -a +b { color: pink; } -``` - - -```css -a>b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a + b { color: pink; } -``` - - -```css -a> b { color: pink; } -``` - -### `"never"` - -There _must never_ be whitespace after the combinators. - -The following patterns are considered problems: - - -```css -a + b { color: pink; } -``` - - -```css -a> b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a +b { color: pink; } -``` - - -```css -a>b { color: pink; } -``` diff --git a/lib/rules/selector-combinator-space-after/__tests__/index.js b/lib/rules/selector-combinator-space-after/__tests__/index.js deleted file mode 100644 index 9e5e57f671..0000000000 --- a/lib/rules/selector-combinator-space-after/__tests__/index.js +++ /dev/null @@ -1,580 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a + a {}', - description: 'space before and after + combinator', - }, - { - code: 'a > a {}', - description: 'space before and after > combinator', - }, - { - code: 'a ~ a {}', - description: 'space before and after ~ combinator', - }, - { - code: 'a >>> a {}', - description: 'shadow-piercing descendant combinator', - }, - { - code: '.foo ~ a + bar {}', - description: 'multiple spaced combinators', - }, - { - code: 'a+ a {}', - description: 'no before and one after + combinator', - }, - { - code: 'a> a {}', - description: 'no before and one after > combinator', - }, - { - code: 'a~ a {}', - description: 'no before and one after ~ combinator', - }, - { - code: 'a>>> a {}', - description: 'no before and one after >>> combinator', - }, - { - code: 'a\n+ a {}', - description: 'newline before space after + combinator', - }, - { - code: 'a\r\n+ a {}', - description: 'CRLF before space after + combinator', - }, - { - code: 'a\n> a {}', - description: 'newline before space after > combinator', - }, - { - code: 'a\r\n> a {}', - description: 'CRLF before space after > combinator', - }, - { - code: 'a\n~ a {}', - description: 'newline before space after ~ combinator', - }, - { - code: 'a\n>>> a {}', - description: 'newline before space after >>> combinator', - }, - { - code: 'a\r\n>>> a {}', - description: 'CRLF before space after >>> combinator', - }, - { - code: 'a~ a+ bar {}', - description: 'multiple combinators with no space before and one after', - }, - { - code: '.foo:nth-child(2n+1) {}', - description: 'unspaced + in nth-child argument', - }, - { - code: '.foo:nth-child(2n-1) {}', - description: 'unspaced - in nth-child argument', - }, - { - code: "a[rel~='copyright'] {}", - description: 'attribute selector with ~=', - }, - { - code: '.foo\\+bar {}', - description: 'escaped combinator-like character', - }, - { - code: "a [type='button'] {}", - description: 'combinator between selectors and attribute selector', - }, - { - code: 'a a {}', - description: 'combinator selector contain multiple spaces', - }, - { - code: 'a\na {}', - description: 'combinator selector contain newline', - }, - { - code: 'a\r\na {}', - description: 'combinator selector contain CRLF', - }, - { - code: 'a\n\na {}', - description: 'combinator selector contain multiple newline', - }, - { - code: 'a\r\n\r\na {}', - description: 'combinator selector contain multiple CRLF', - }, - { - 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', - }, - { - code: 'namespace|type#id > .foo {}', - description: 'qualified ID with namespace', - }, - { - code: '.a { &.b {} }', - description: 'nesting and no combinators', - }, - { - code: '.a { & .b {} }', - description: 'nesting and no combinators', - }, - { - code: '.a { &:first-child {} }', - description: 'nesting and no combinators', - }, - { - code: 'a[b=#{c}] { }', - description: 'ignore "invalid" selector (see #3130)', - }, - ], - - reject: [ - { - code: 'a+ a {}', - fixed: 'a+ a {}', - description: 'two spaces after + combinator', - message: messages.expectedAfter('+'), - line: 1, - column: 2, - }, - { - code: 'a+\na {}', - fixed: 'a+ a {}', - description: 'newline after + combinator', - message: messages.expectedAfter('+'), - line: 1, - column: 2, - }, - { - code: 'a+a {}', - fixed: 'a+ a {}', - description: 'no space after + combinator', - message: messages.expectedAfter('+'), - line: 1, - column: 2, - }, - { - code: 'a>a {}', - fixed: 'a> a {}', - description: 'no space after > combinator', - message: messages.expectedAfter('>'), - line: 1, - column: 2, - }, - { - code: 'a~a {}', - fixed: 'a~ a {}', - description: 'no space after ~ combinator', - message: messages.expectedAfter('~'), - line: 1, - column: 2, - }, - { - code: 'a + .foo.bar ~a {}', - fixed: 'a + .foo.bar ~ a {}', - description: 'multiple combinators: no space after ~ combinator', - message: messages.expectedAfter('~'), - line: 1, - column: 14, - }, - { - code: '#foo +.foo.bar ~ a {}', - fixed: '#foo + .foo.bar ~ a {}', - description: 'multiple combinators: no space after + combinator', - message: messages.expectedAfter('+'), - line: 1, - column: 6, - }, - { - code: 'a >>>a {}', - fixed: 'a >>> a {}', - description: 'shadow-piercing descendant combinator', - message: messages.expectedAfter('>>>'), - line: 1, - column: 3, - }, - { - code: 'namespace|type#id >.foo {}', - fixed: 'namespace|type#id > .foo {}', - description: 'qualified ID with namespace', - message: messages.expectedAfter('>'), - line: 1, - column: 19, - }, - { - code: 'a >a >a {}', - fixed: 'a > a > a {}', - warnings: [ - { - message: messages.expectedAfter('>'), - line: 1, - column: 3, - }, - { - message: messages.expectedAfter('>'), - line: 1, - column: 6, - }, - ], - }, - { - code: '.a { &>.b {} }', - fixed: '.a { &> .b {} }', - description: 'nesting', - message: messages.expectedAfter('>'), - line: 1, - column: 7, - }, - { - code: '.a { &+.b {} }', - fixed: '.a { &+ .b {} }', - description: 'nesting', - message: messages.expectedAfter('+'), - line: 1, - column: 7, - }, - { - code: 'a/*comment*/>/*comment*/a {}', - fixed: 'a/*comment*/> /*comment*/a {}', - description: 'comment', - message: messages.expectedAfter('>'), - line: 1, - column: 13, - }, - { - code: 'a/*comment*/>/*comment*/a, b/*comment*/>/*comment*/b {}', - fixed: 'a/*comment*/> /*comment*/a, b/*comment*/> /*comment*/b {}', - description: 'comment', - warnings: [ - { - message: messages.expectedAfter('>'), - line: 1, - column: 13, - }, - { - message: messages.expectedAfter('>'), - line: 1, - column: 40, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a +a {}', - description: 'space before none after + combinator', - }, - { - code: 'a >a {}', - description: 'space before none after > combinator', - }, - { - code: 'a ~a {}', - description: 'space before none after ~ combinator', - }, - { - code: 'a >>>a {}', - description: 'space before none after >>> combinator', - }, - { - code: '.foo ~a +bar {}', - description: 'multiple combinators with no space after', - }, - { - code: 'a+a {}', - description: 'no space before or after + combinator', - }, - { - code: 'a>a {}', - description: 'no space before or after > combinator', - }, - { - code: 'a~a {}', - description: 'no space before or after ~ combinator', - }, - { - code: 'a\n+a {}', - description: 'newline before and no space after + combinator', - }, - { - code: 'a\r\n+a {}', - description: 'CRLF before and no space after + combinator', - }, - { - code: 'a\n>a {}', - description: 'newline before and no space after > combinator', - }, - { - code: 'a\n~a {}', - description: 'newline before and no space after ~ combinator', - }, - { - code: 'a\r\n~a {}', - description: 'CRLF before and no space after ~ combinator', - }, - { - code: 'a\n>>>a {}', - description: 'newline before and no space after >>> combinator', - }, - { - code: 'a\r\n>>>a {}', - description: 'CRLF before and no space after >>> combinator', - }, - { - code: '.foo:nth-child(2n + 1) {}', - description: 'spaced + in nth-child argument', - }, - { - code: '.foo:nth-child(2n - 1) {}', - description: 'spaced - in nth-child argument', - }, - { - code: "a[rel~='copyright'] {}", - description: 'attribute selector with ~=', - }, - { - code: "a [type='button'] {}", - description: 'combinator between selectors and attribute selector', - }, - { - code: 'a a {}', - description: 'combinator selector contain multiple spaces', - }, - { - code: 'a\na {}', - description: 'combinator selector contain newline', - }, - { - code: 'a\r\na {}', - description: 'combinator selector contain CRLF', - }, - { - code: 'a\n\na {}', - description: 'combinator selector contain multiple newline', - }, - { - code: 'a\r\n\r\na {}', - description: 'combinator selector contain multiple CRLF', - }, - { - code: 'namespace|type#id >.foo {}', - description: 'qualified ID with namespace', - }, - ], - - reject: [ - { - code: 'a+ a {}', - fixed: 'a+a {}', - description: 'space after + combinator', - message: messages.rejectedAfter('+'), - line: 1, - column: 2, - }, - { - code: 'a> a {}', - fixed: 'a>a {}', - description: 'space after > combinator', - message: messages.rejectedAfter('>'), - line: 1, - column: 2, - }, - { - code: 'a~ a {}', - fixed: 'a~a {}', - description: 'space after ~ combinator', - message: messages.rejectedAfter('~'), - line: 1, - column: 2, - }, - { - code: 'a+\na{}', - fixed: 'a+a{}', - description: 'newline after + combinator', - message: messages.rejectedAfter('+'), - line: 1, - column: 2, - }, - { - code: 'a+\r\na{}', - fixed: 'a+a{}', - description: 'CRLF after + combinator', - message: messages.rejectedAfter('+'), - line: 1, - column: 2, - }, - { - code: 'a>\na{}', - fixed: 'a>a{}', - description: 'newline after > combinator', - message: messages.rejectedAfter('>'), - line: 1, - column: 2, - }, - { - code: 'a>\r\na{}', - fixed: 'a>a{}', - description: 'newline after > combinator', - message: messages.rejectedAfter('>'), - line: 1, - column: 2, - }, - { - code: 'a~\na{}', - fixed: 'a~a{}', - description: 'newline after ~ combinator', - message: messages.rejectedAfter('~'), - line: 1, - column: 2, - }, - { - code: 'a~\r\na{}', - fixed: 'a~a{}', - description: 'CRLF after ~ combinator', - message: messages.rejectedAfter('~'), - line: 1, - column: 2, - }, - { - code: 'a + .foo.bar ~a {}', - fixed: 'a +.foo.bar ~a {}', - description: 'multiple combinators: space after + combinator', - message: messages.rejectedAfter('+'), - line: 1, - column: 3, - }, - { - code: '#foo +.foo.bar ~ a {}', - fixed: '#foo +.foo.bar ~a {}', - description: 'multiple combinators: no space after ~ combinator', - message: messages.rejectedAfter('~'), - line: 1, - column: 16, - }, - { - code: 'a >>> a {}', - fixed: 'a >>>a {}', - description: 'space after >>> combinator', - message: messages.rejectedAfter('>>>'), - line: 1, - column: 3, - }, - { - code: 'a/*comment*/ > /*comment*/a {}', - fixed: 'a/*comment*/ >/*comment*/a {}', - description: 'comment', - message: messages.rejectedAfter('>'), - line: 1, - column: 14, - }, - { - code: 'a/*comment*/ > /*comment*/a, b/*comment*/ > /*comment*/b {}', - fixed: 'a/*comment*/ >/*comment*/a, b/*comment*/ >/*comment*/b {}', - description: 'comment', - warnings: [ - { - message: messages.rejectedAfter('>'), - line: 1, - column: 14, - }, - { - message: messages.rejectedAfter('>'), - line: 1, - column: 43, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-less', - config: ['always'], - fix: true, - - accept: [ - { - code: '.a when (@size>=60) and (@size<102) {}', - description: 'ignore constructs', - }, - ], - - reject: [ - { - code: 'a+ a {}', - fixed: 'a+ a {}', - description: 'two spaces after + combinator', - message: messages.expectedAfter('+'), - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-scss', - config: ['always'], - fix: true, - - accept: [ - { - code: 'a { > /*comment*/a, > /*comment*/.b{} }', - description: 'scss nesting and comment', - }, - { - code: 'a ~, b {}', - description: 'scss trailing combinator', - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-scss', - config: ['never'], - fix: true, - - accept: [ - { - code: 'a { >/*comment*/a, >/*comment*/.b {} }', - description: 'scss nesting and comment', - }, - { - code: 'a ~, b {}', - description: 'scss trailing combinator', - }, - ], -}); diff --git a/lib/rules/selector-combinator-space-after/index.js b/lib/rules/selector-combinator-space-after/index.js deleted file mode 100644 index aeb0049738..0000000000 --- a/lib/rules/selector-combinator-space-after/index.js +++ /dev/null @@ -1,65 +0,0 @@ -'use strict'; - -const ruleMessages = require('../../utils/ruleMessages'); -const selectorCombinatorSpaceChecker = require('../selectorCombinatorSpaceChecker'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'selector-combinator-space-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: (combinator) => `Expected single space after "${combinator}"`, - rejectedAfter: (combinator) => `Unexpected whitespace after "${combinator}"`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/selector-combinator-space-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - selectorCombinatorSpaceChecker({ - root, - result, - locationChecker: checker.after, - locationType: 'after', - checkedRuleName: ruleName, - fix: context.fix - ? (combinator) => { - if (primary === 'always') { - combinator.spaces.after = ' '; - - return true; - } - - if (primary === 'never') { - combinator.spaces.after = ''; - - return true; - } - - return false; - } - : null, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/selector-combinator-space-before/README.md b/lib/rules/selector-combinator-space-before/README.md deleted file mode 100644 index 5cbe8b737d..0000000000 --- a/lib/rules/selector-combinator-space-before/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# selector-combinator-space-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace before the combinators of selectors. - - -```css - a > b + c ~ d e >>> f { color: pink; } -/** ↑ ↑ ↑ ↑ ↑ - * These are combinators */ -``` - -Combinators are used to combine several different selectors into new and more specific ones. There are several types of combinators, including: child (`>`), adjacent sibling (`+`), general sibling (`~`), and descendant (which is represented by a blank space between two selectors). - -The descendant combinator is _not_ checked by this rule. - -Also, `+` and `-` signs within `:nth-*()` arguments are not checked (e.g. `a:nth-child(2n+1)`). - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a single space before the combinators. - -The following patterns are considered problems: - - -```css -a+ b { color: pink; } -``` - - -```css -a>b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a + b { color: pink; } -``` - - -```css -a >b { color: pink; } -``` - -### `"never"` - -There _must never_ be whitespace before the combinators. - -The following patterns are considered problems: - - -```css -a + b { color: pink; } -``` - - -```css -a >b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a+ b { color: pink; } -``` - - -```css -a>b { color: pink; } -``` diff --git a/lib/rules/selector-combinator-space-before/__tests__/index.js b/lib/rules/selector-combinator-space-before/__tests__/index.js deleted file mode 100644 index 97a89196ed..0000000000 --- a/lib/rules/selector-combinator-space-before/__tests__/index.js +++ /dev/null @@ -1,520 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a + a {}', - description: 'space before and after + combinator', - }, - { - code: 'a > a {}', - description: 'space before and after > combinator', - }, - { - code: 'a ~ a {}', - description: 'space before and after ~ combinator', - }, - { - code: 'a >>> a {}', - description: 'shadow-piercing descendant combinator', - }, - { - code: '.foo ~ a + bar {}', - description: 'multiple spaced combinators', - }, - { - code: 'a +a {}', - description: 'space before and none after + combinator', - }, - { - code: 'a >a {}', - description: 'space before and none after > combinator', - }, - { - code: 'a ~a {}', - description: 'space before and none after ~ combinator', - }, - { - code: 'a >>>a {}', - description: 'space before and none after >>> combinator', - }, - { - code: 'a +\na {}', - description: 'space before and newline after + combinator', - }, - { - code: 'a +\r\na {}', - description: 'space before and CRLF after + combinator', - }, - { - code: 'a >\na {}', - description: 'space before and newline after > combinator', - }, - { - code: 'a ~\na {}', - description: 'space before and newline after ~ combinator', - }, - { - code: 'a ~\r\na {}', - description: 'space before and CRLF after ~ combinator', - }, - { - code: 'a >>>\na {}', - description: 'space before and newline after >>> combinator', - }, - { - code: 'a >>>\r\na {}', - description: 'space before and CRLF after >>> combinator', - }, - { - code: 'a ~a +bar {}', - description: 'multiple combinators with space before and none after', - }, - { - code: '.foo:nth-child(2n+1) {}', - description: 'unspaced + in nth-child argument', - }, - { - code: '.foo:nth-child(2n-1) {}', - description: 'unspaced - in nth-child argument', - }, - { - code: "a[rel~='copyright'] {}", - description: 'attribute selector with ~=', - }, - { - code: '.foo {\n\t> span,\n\t> b { color:pink; } }', - description: 'nested selectors starting with combinator', - }, - { - code: '.foo\\+bar {}', - description: 'escaped combinator-like character', - }, - { - code: "a [type='button'] {}", - description: 'combinator between selectors and attribute selector', - }, - { - code: 'a a {}', - description: 'combinator selector contain multiple spaces', - }, - { - code: 'a\na {}', - description: 'combinator selector contain newline', - }, - { - code: 'a\r\na {}', - description: 'combinator selector contain CRLF', - }, - { - code: 'a\n\na {}', - description: 'combinator selector contain multiple newline', - }, - { - code: 'a\r\n\r\na {}', - description: 'combinator selector contain multiple CRLF', - }, - { - 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', - }, - { - code: 'a[b=#{c}] { }', - description: 'ignore "invalid" selector (see #3130)', - }, - { - code: 'namespace|type#id > .foo {}', - description: 'qualified ID with namespace', - }, - { - code: 'namespace|type#id > .foo {}, space|customtype#id_withunder > a {}', - description: 'qualified ID with namespace selector list', - }, - ], - - reject: [ - { - code: 'a +a {}', - fixed: 'a +a {}', - description: 'two spaces before + combinator', - message: messages.expectedBefore('+'), - line: 1, - column: 4, - }, - { - code: 'a\n+ a {}', - fixed: 'a + a {}', - description: 'newline before + combinator', - message: messages.expectedBefore('+'), - line: 2, - column: 1, - }, - { - code: 'a\r\n+ a {}', - fixed: 'a + a {}', - description: 'CRLF before + combinator', - message: messages.expectedBefore('+'), - line: 2, - column: 1, - }, - { - code: 'a+a {}', - fixed: 'a +a {}', - description: 'no space before + combinator', - message: messages.expectedBefore('+'), - line: 1, - column: 2, - }, - { - code: 'a>a {}', - fixed: 'a >a {}', - description: 'no space before > combinator', - message: messages.expectedBefore('>'), - line: 1, - column: 2, - }, - { - code: 'a~a {}', - fixed: 'a ~a {}', - description: 'no space before ~ combinator', - message: messages.expectedBefore('~'), - line: 1, - column: 2, - }, - { - code: 'a + .foo.bar~ a {}', - fixed: 'a + .foo.bar ~ a {}', - description: 'multiple combinators: no space before ~ combinator', - message: messages.expectedBefore('~'), - line: 1, - column: 13, - }, - { - code: '#foo+ .foo.bar ~ a {}', - fixed: '#foo + .foo.bar ~ a {}', - description: 'multiple combinators: no space before + combinator', - message: messages.expectedBefore('+'), - line: 1, - column: 5, - }, - { - code: 'a>>> a {}', - fixed: 'a >>> a {}', - description: 'shadow-piercing descendant combinator', - message: messages.expectedBefore('>>>'), - line: 1, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a+ a {}', - description: 'no space before one after + combinator', - }, - { - code: 'a> a {}', - description: 'no space before one after > combinator', - }, - { - code: 'a~ a {}', - description: 'no space before one after ~ combinator', - }, - { - code: 'a>>> a {}', - description: 'shadow-piercing descendant combinator', - }, - { - code: '.foo~ a+ bar {}', - description: 'multiple combinators with no space after', - }, - { - code: 'a+a {}', - description: 'no space before or after + combinator', - }, - { - code: 'a>a {}', - description: 'no space before or after > combinator', - }, - { - code: 'a~a {}', - description: 'no space before or after ~ combinator', - }, - { - code: 'a+\na {}', - description: 'no space before and newline after + combinator', - }, - { - code: 'a>\na {}', - description: 'no space before and newline after > combinator', - }, - { - code: 'a>\r\na {}', - description: 'no space before and CRLF after > combinator', - }, - { - code: 'a~\na {}', - description: 'no space before and newline after ~ combinator', - }, - { - code: 'a>>>\na {}', - description: 'no space before and newline after >>> combinator', - }, - { - code: 'a>>>\r\na {}', - description: 'no space before and CRLF after >>> combinator', - }, - { - code: '.foo:nth-child(2n + 1) {}', - description: 'spaced + in nth-child argument', - }, - { - code: '.foo:nth-child(2n - 1) {}', - description: 'spaced - in nth-child argument', - }, - { - code: "a[rel~='copyright'] {}", - description: 'attribute selector with ~=', - }, - { - code: "a [type='button'] {}", - description: 'combinator between selectors and attribute selector', - }, - { - code: 'a a {}', - description: 'combinator selector contain multiple spaces', - }, - { - code: 'a\na {}', - description: 'combinator selector contain newline', - }, - { - code: 'a\r\na {}', - description: 'combinator selector contain CRLF', - }, - { - code: 'a\n\na {}', - description: 'combinator selector contain multiple newline', - }, - { - code: 'a\r\n\r\na {}', - description: 'combinator selector contain multiple CRLF', - }, - { - code: 'namespace|type#id> .foo {}', - description: 'qualified ID with namespace', - }, - ], - - reject: [ - { - code: 'a +a {}', - fixed: 'a+a {}', - description: 'space before + combinator', - message: messages.rejectedBefore('+'), - line: 1, - column: 3, - }, - { - code: 'a >a {}', - fixed: 'a>a {}', - description: 'space before > combinator', - message: messages.rejectedBefore('>'), - line: 1, - column: 3, - }, - { - code: 'a ~a {}', - fixed: 'a~a {}', - description: 'space before ~ combinator', - message: messages.rejectedBefore('~'), - line: 1, - column: 3, - }, - { - code: 'a\n+a {}', - fixed: 'a+a {}', - description: 'newline before + combinator', - message: messages.rejectedBefore('+'), - line: 2, - column: 1, - }, - { - code: 'a\r\n+a {}', - fixed: 'a+a {}', - description: 'CRLF before + combinator', - message: messages.rejectedBefore('+'), - line: 2, - column: 1, - }, - { - code: 'a\n>a {}', - fixed: 'a>a {}', - description: 'newline before > combinator', - message: messages.rejectedBefore('>'), - line: 2, - column: 1, - }, - { - code: 'a\r\n>a {}', - fixed: 'a>a {}', - description: 'CRLF before > combinator', - message: messages.rejectedBefore('>'), - line: 2, - column: 1, - }, - { - code: 'a\n~a {}', - fixed: 'a~a {}', - description: 'newline before ~ combinator', - message: messages.rejectedBefore('~'), - line: 2, - column: 1, - }, - { - code: 'a\r\n~a {}', - fixed: 'a~a {}', - description: 'CRLF before ~ combinator', - message: messages.rejectedBefore('~'), - line: 2, - column: 1, - }, - { - code: 'a + .foo.bar~ a {}', - fixed: 'a+ .foo.bar~ a {}', - description: 'multiple combinators: space before + combinator', - message: messages.rejectedBefore('+'), - line: 1, - column: 3, - }, - { - code: '#foo+ .foo.bar ~ a {}', - fixed: '#foo+ .foo.bar~ a {}', - description: 'multiple combinators: no space before ~ combinator', - message: messages.rejectedBefore('~'), - line: 1, - column: 16, - }, - { - code: 'a >>> a {}', - fixed: 'a>>> a {}', - description: 'space before >>> combinator', - message: messages.rejectedBefore('>>>'), - line: 1, - column: 3, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-less', - config: ['always'], - fix: true, - - accept: [ - { - code: '.a when (@size>=60) and (@size<102) {}', - description: 'ignore constructs', - }, - ], - - reject: [ - { - code: 'a +a {}', - fixed: 'a +a {}', - description: 'two spaces before + combinator', - message: messages.expectedBefore('+'), - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-scss', - config: ['always'], - fix: true, - - accept: [ - { - code: 'a {> a {}}', - description: 'scss nesting', - }, - { - code: 'a {> a,> .b {}}', - description: 'scss nesting', - }, - { - code: 'a {> /*comment*/ a,> /*comment*/ .b {}}', - description: 'scss nesting, comment and comma', - }, - ], - - reject: [ - { - code: 'a {> /*comment*/ a,> /*comment*/ .b> .c {}}', - fixed: 'a {> /*comment*/ a,> /*comment*/ .b > .c {}}', - description: 'scss nesting, comment and comma', - message: messages.expectedBefore('>'), - line: 1, - column: 36, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-scss', - config: ['never'], - fix: true, - - accept: [ - { - code: 'a { > a {}}', - description: 'scss nesting', - }, - { - code: 'a { > a, > .b {}}', - description: 'scss nesting', - }, - { - code: 'a { > /*comment*/ a, > /*commenttest*/ .b {}}', - description: 'scss nesting, comment and comma', - }, - ], - - reject: [ - { - code: 'a { > /*comment*/ a, > /*comment*/ .b >.c {}}', - fixed: 'a { > /*comment*/ a, > /*comment*/ .b>.c {}}', - description: 'scss nesting, comment and comma', - message: messages.rejectedBefore('>'), - line: 1, - column: 39, - }, - ], -}); diff --git a/lib/rules/selector-combinator-space-before/index.js b/lib/rules/selector-combinator-space-before/index.js deleted file mode 100644 index ad75dc0222..0000000000 --- a/lib/rules/selector-combinator-space-before/index.js +++ /dev/null @@ -1,65 +0,0 @@ -'use strict'; - -const ruleMessages = require('../../utils/ruleMessages'); -const selectorCombinatorSpaceChecker = require('../selectorCombinatorSpaceChecker'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'selector-combinator-space-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: (combinator) => `Expected single space before "${combinator}"`, - rejectedBefore: (combinator) => `Unexpected whitespace before "${combinator}"`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/selector-combinator-space-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - selectorCombinatorSpaceChecker({ - root, - result, - locationChecker: checker.before, - locationType: 'before', - checkedRuleName: ruleName, - fix: context.fix - ? (combinator) => { - if (primary === 'always') { - combinator.spaces.before = ' '; - - return true; - } - - if (primary === 'never') { - combinator.spaces.before = ''; - - return true; - } - - return false; - } - : null, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/selector-descendant-combinator-no-non-space/README.md b/lib/rules/selector-descendant-combinator-no-non-space/README.md deleted file mode 100644 index f89a2b9168..0000000000 --- a/lib/rules/selector-descendant-combinator-no-non-space/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# selector-descendant-combinator-no-non-space - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Disallow non-space characters for descendant combinators of selectors. - - -```css -.foo .bar .baz {} -/** ↑ ↑ -* These descendant combinators */ -``` - -This rule ensures that only a single space is used and ensures no tabs, newlines, nor multiple spaces are used for descendant combinators of selectors. - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix most of the problems reported by this rule. - -This rule currently ignores selectors containing comments. - -## Options - -### `true` - -The following patterns are considered problems: - - -```css -.foo .bar {} -``` - - -```css -.foo -.bar {} -``` - -The following patterns are _not_ considered problems: - - -```css -.foo .bar {} -``` diff --git a/lib/rules/selector-descendant-combinator-no-non-space/__tests__/index.js b/lib/rules/selector-descendant-combinator-no-non-space/__tests__/index.js deleted file mode 100644 index 0a896defa6..0000000000 --- a/lib/rules/selector-descendant-combinator-no-non-space/__tests__/index.js +++ /dev/null @@ -1,178 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: [true], - fix: true, - - accept: [ - { - code: '.foo.bar {}', - }, - { - code: '.foo .bar {}', - }, - { - code: '.foo>.bar {}', - }, - { - code: '.foo > .bar {}', - }, - { - code: '.foo > .bar {}', - }, - { - code: '.foo\n>\n.bar {}', - }, - { - code: '.foo\r\n>\r\n.bar {}', - }, - { - code: '.foo >>> .bar {}', - description: 'shadow-piercing descendant combinator', - }, - { - code: '.foo >>> .bar {}', - description: 'shadow-piercing descendant combinator', - }, - { - 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', - }, - { - code: 'div > :nth-child(2n + 1) {}', - }, - { - code: '.foo > .bar {}', - }, - { - code: '.foo /*comment*/ > .bar {}', - }, - { - code: '.foo >\n/*comment*/\n.bar {}', - }, - { - code: '.foo /*c*/ /*c*/ > /*c*/ /*c*/ .bar {}', - }, - { - code: ` - button, - html [type="button"], /* 1 */ - [type="reset"], - [type="submit"] { - -webkit-appearance: button; /* 2 */ - } - `, - }, - { - code: 'a[b=#{c}] { }', - description: 'ignore "invalid" selector (see #3130)', - }, - // Tests for workaround for parser incompatibility - { - code: '.foo > /*comment*/ .bar {}', - }, - { - code: '.foo >\n/**/\n.bar {}', - }, - ], - - reject: [ - { - code: '.foo .bar {}', - fixed: '.foo .bar {}', - message: messages.rejected(' '), - line: 1, - column: 5, - }, - { - code: '.foo\t.bar {}', - fixed: '.foo .bar {}', - message: messages.rejected('\t'), - line: 1, - column: 5, - }, - { - code: '.foo\n.bar {}', - fixed: '.foo .bar {}', - message: messages.rejected('\n'), - line: 1, - column: 5, - }, - { - code: '.foo\r\n.bar {}', - fixed: '.foo .bar {}', - message: messages.rejected('\r\n'), - line: 1, - column: 5, - }, - { - skip: true, - code: '.foo /*comment*/ /*comment*/ .bar > /*comment*/ .buz {}', - fixed: '.foo /*comment*/ /*comment*/ .bar > /*comment*/ .buz {}', - - warnings: [ - { - message: messages.rejected(' '), - line: 1, - column: 17, - }, - { - message: messages.rejected(' '), - line: 1, - column: 47, - }, - ], - }, - { - skip: true, - code: '.foo ( ) .bar {}', - unfixable: true, // can't fix - description: 'illegal combinator', - message: messages.rejected(' ( )'), - line: 1, - column: 5, - }, - ], -}); - -testRule({ - ruleName, - config: [true], - customSyntax: 'postcss-scss', - - accept: [ - { - code: 'div > :nth-child(#{$i + ($column - 1)}) {}', - }, - ], -}); - -testRule({ - ruleName, - config: [true], - customSyntax: 'postcss-less', - - accept: [ - { - code: ':hover when (@variable = true) { color: red; }', - }, - { - code: 'a:hover when (@variable = true) { color: red; }', - }, - ], -}); diff --git a/lib/rules/selector-descendant-combinator-no-non-space/index.js b/lib/rules/selector-descendant-combinator-no-non-space/index.js deleted file mode 100644 index a31255e29c..0000000000 --- a/lib/rules/selector-descendant-combinator-no-non-space/index.js +++ /dev/null @@ -1,95 +0,0 @@ -'use strict'; - -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-descendant-combinator-no-non-space'; - -const messages = ruleMessages(ruleName, { - rejected: (nonSpaceCharacter) => `Unexpected "${nonSpaceCharacter}"`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/selector-descendant-combinator-no-non-space', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - }); - - if (!validOptions) { - return; - } - - root.walkRules((ruleNode) => { - if (!isStandardSyntaxRule(ruleNode)) { - return; - } - - let hasFixed = false; - const selector = ruleNode.raws.selector ? ruleNode.raws.selector.raw : ruleNode.selector; - - // Return early for selectors containing comments - // TODO: re-enable when parser and stylelint are compatible - if (selector.includes('/*')) return; - - const fixedSelector = parseSelector(selector, result, ruleNode, (fullSelector) => { - fullSelector.walkCombinators((combinatorNode) => { - if (combinatorNode.value !== ' ') { - return; - } - - const value = combinatorNode.toString(); - - if ( - value.includes(' ') || - value.includes('\t') || - value.includes('\n') || - value.includes('\r') - ) { - if (context.fix && /^\s+$/.test(value)) { - hasFixed = true; - - if (!combinatorNode.raws) combinatorNode.raws = {}; - - combinatorNode.raws.value = ' '; - combinatorNode.rawSpaceBefore = combinatorNode.rawSpaceBefore.replace(/^\s+/, ''); - combinatorNode.rawSpaceAfter = combinatorNode.rawSpaceAfter.replace(/\s+$/, ''); - - return; - } - - report({ - result, - ruleName, - message: messages.rejected(value), - node: ruleNode, - index: combinatorNode.sourceIndex, - }); - } - }); - }); - - if (hasFixed && fixedSelector) { - if (!ruleNode.raws.selector) { - ruleNode.selector = fixedSelector; - } else { - ruleNode.raws.selector.raw = fixedSelector; - } - } - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/selector-list-comma-newline-after/README.md b/lib/rules/selector-list-comma-newline-after/README.md deleted file mode 100644 index 82d4079244..0000000000 --- a/lib/rules/selector-list-comma-newline-after/README.md +++ /dev/null @@ -1,122 +0,0 @@ -# selector-list-comma-newline-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline or disallow whitespace after the commas of selector lists. - - -```css - a, - b↑{ color: pink; } -/** ↑ - * The newline after this comma */ -``` - -End-of-line comments are allowed one space after the comma. - - -```css -a, /* comment */ -b { color: pink; } -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a newline after the commas. - -The following patterns are considered problems: - - -```css -a, b { color: pink; } -``` - - -```css -a -, b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a, -b { color: pink; } -``` - - -```css -a -, -b { color: pink; } -``` - -### `"always-multi-line"` - -There _must always_ be a newline after the commas in multi-line selector lists. - -The following patterns are considered problems: - - -```css -a -, b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a, b { color: pink; } -``` - - -```css -a, -b { color: pink; } -``` - - -```css -a -, -b { color: pink; } -``` - -### `"never-multi-line"` - -There _must never_ be whitespace after the commas in multi-line selector lists. - -The following patterns are considered problems: - - -```css -a -, b { color: pink; } -``` - - -```css -a, -b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a,b { color: pink; } -``` - - -```css -a -,b { color: pink; } -``` diff --git a/lib/rules/selector-list-comma-newline-after/__tests__/index.js b/lib/rules/selector-list-comma-newline-after/__tests__/index.js deleted file mode 100644 index 5a306a7299..0000000000 --- a/lib/rules/selector-list-comma-newline-after/__tests__/index.js +++ /dev/null @@ -1,408 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a,\nb {}', - }, - { - code: 'a,\n\nb {}', - }, - { - code: 'a,\r\nb {}', - description: 'CRLF', - }, - { - code: 'a,\r\n\r\nb {}', - description: 'Double CRLF', - }, - { - code: 'a,\nb,\nc {}', - }, - { - code: 'a ,\nb {}', - }, - { - code: 'a\n,\nb {}', - }, - { - code: 'a\r\n,\r\nb {}', - description: 'CRLF', - }, - { - code: 'a,\nb[data-foo="tr,tr"] {}', - }, - { - code: 'a {\n &:hover,\n &:focus {\n color: pink; }\n}', - description: 'nested in rule set', - }, - { - code: '@media (min-width: 10px) {\n a,\n b {}\n}', - description: 'nested in at-rule', - }, - { - code: '@media (min-width: 10px) {\r\n a,\r\n b {}\r\n}', - description: 'nested in at-rule and CRLF', - }, - { - code: '\ta,\n\tb {}', - description: 'indented statement', - }, - { - code: 'a, /* comment */\nb {}', - description: 'with end-of-line comment with newline after', - }, - { - code: 'a, /* comment */\nb {}', - description: 'with end-of-line and few spaces /* comment */ with newline after', - }, - { - code: 'a,\t/* comment */\nb {}', - description: 'with end-of-line and a tab /* comment */ with newline after', - }, - { - code: 'a,\t\t/* comment */\nb {}', - description: 'with end-of-line and few tabs /* comment */ with newline after', - }, - { - code: 'a, \t \t /* comment */\nb {}', - description: 'with end-of-line and few tabs and spaces /* comment */ with newline after', - }, - { - code: 'a, /* comment\n commentline2 */\nb {}', - description: 'with end-of-line multi-line comment with newline after', - }, - { - code: 'a, /* comment\n commentline2 */\nb {}', - description: 'with end-of-line and few spaces multi-line comment with newline after', - }, - { - code: 'a,\t/* comment\n commentline2 */\nb {}', - description: 'with end-of-line and a tab multi-line comment with newline after', - }, - { - code: 'a,\t\t/* comment\n commentline2 */\nb {}', - description: 'with end-of-line and few tabs multi-line comment with newline after', - }, - { - code: 'a, \t \t /* comment\n commentline2 */\nb {}', - description: 'with end-of-line and few tabs and spaces multi-line comment with newline after', - }, - { - code: 'a:matches(:hover, :focus) {}', - description: 'comma inside :matches()', - }, - { - code: ':not(:hover, :focus) {}', - description: 'comma inside :not()', - }, - { - 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,b {}', - fixed: 'a,\nb {}', - message: messages.expectedAfter(), - line: 1, - column: 2, - }, - { - code: 'a, b {}', - fixed: 'a,\n b {}', - message: messages.expectedAfter(), - line: 1, - column: 2, - }, - { - code: 'a, b {}', - fixed: 'a,\n b {}', - message: messages.expectedAfter(), - line: 1, - column: 2, - }, - { - code: 'a,\tb {}', - fixed: 'a,\n\tb {}', - message: messages.expectedAfter(), - line: 1, - column: 2, - }, - { - code: 'a,\nb,c {}', - fixed: 'a,\nb,\nc {}', - message: messages.expectedAfter(), - line: 2, - column: 2, - }, - { - code: 'a,\r\nb,c {}', - fixed: 'a,\r\nb,\r\nc {}', - description: 'CRLF', - message: messages.expectedAfter(), - line: 2, - column: 2, - }, - { - code: 'a, /* comment */ b {}', - fixed: 'a, /* comment */\n b {}', - description: 'with post-comma comment without newline after', - message: messages.expectedAfter(), - line: 1, - column: 2, - }, - { - code: 'a, /* comment\n commentline2 */b {}', - fixed: 'a, /* comment\n commentline2 */\nb {}', - description: 'with post-comma multi-line comment without newline after', - message: messages.expectedAfter(), - line: 1, - column: 2, - }, - { - code: 'a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z {\n}', - fixed: - 'a,\nb,\nc,\nd,\ne,\nf,\ng,\nh,\ni,\nj,\nk,\nl,\nm,\nn,\no,\np,\nq,\nr,\ns,\nt,\nu,\nv,\nw,\nx,\ny,\nz {\n}', - warnings: Array.from({ length: 25 }) - .fill(0) - .map((_, i) => ({ - message: messages.expectedAfter(), - line: 1, - column: 2 * (i + 1), - })), - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: 'a,\nb {}', - }, - { - code: 'a,\r\nb {}', - description: 'CRLF', - }, - { - code: 'a, b {}', - description: 'ignores single-line', - }, - { - code: 'a, b {\n}', - description: 'ignores single-line selector list, multi-line block', - }, - { - code: 'a, b {\r\n}', - description: 'ignores single-line selector list, multi-line block with CRLF', - }, - { - code: '\ta,\n\tb {\n}', - description: 'indented statement', - }, - ], - - reject: [ - { - code: 'a,\nb, c {}', - fixed: 'a,\nb,\n c {}', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 2, - }, - { - code: 'a,\nb, c {\n}', - fixed: 'a,\nb,\n c {\n}', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 2, - }, - { - code: 'a,\r\nb, c {\r\n}', - fixed: 'a,\r\nb,\r\n c {\r\n}', - description: 'CRLF', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - fix: true, - - accept: [ - { - code: 'a\n,b {}', - }, - { - code: 'a ,b {}', - description: 'ignores single-line', - }, - { - code: 'a ,b {\n}', - description: 'ignores single-line selector list, multi-line block', - }, - { - code: 'a:matches(:hover, :focus) {}', - description: 'comma inside :matches()', - }, - { - code: ':not(:hover, :focus) {}', - description: 'comma inside :not()', - }, - ], - - reject: [ - { - code: 'a,\nb ,c {}', - fixed: 'a,b ,c {}', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 2, - }, - { - code: 'a,\r\nb ,c {}', - fixed: 'a,b ,c {}', - description: 'CRLF', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 2, - }, - { - code: 'a,\nb ,c {\n}', - fixed: 'a,b ,c {\n}', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 2, - }, - { - code: 'a,\n\n \t b ,c {\n}', - fixed: 'a,b ,c {\n}', - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 2, - }, - { - code: 'a,\n/*comment*/\nb ,\nc {\n}', - fixed: 'a,\n/*comment*/b ,c {\n}', - warnings: [ - { - message: messages.rejectedAfterMultiLine(), - line: 1, - column: 2, - }, - { - message: messages.rejectedAfterMultiLine(), - line: 3, - column: 3, - }, - ], - }, - { - code: 'a,\nb,\nc,\nd,\ne,\nf,\ng,\nh,\ni,\nj,\nk,\nl,\nm,\nn,\no,\np,\nq,\nr,\ns,\nt,\nu,\nv,\nw,\nx,\ny,\nz {\n}', - fixed: 'a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z {\n}', - warnings: Array.from({ length: 25 }) - .fill(0) - .map((_, i) => ({ - message: messages.rejectedAfterMultiLine(), - line: 1 + i, - column: 2, - })), - }, - ], -}); - -testRule({ - ruleName, - config: ['always'], - customSyntax: 'postcss-scss', - fix: true, - - accept: [ - { - code: 'a, // comment\nb {}', - description: 'with end-of-line // comment with newline after', - }, - { - code: 'a, // comment\nb {}', - description: 'with end-of-line and few spaces // comment with newline after', - }, - { - code: 'a,\t// comment\nb {}', - description: 'with end-of-line and a tab // comment with newline after', - }, - { - code: 'a,\t\t// comment\nb {}', - description: 'with end-of-line and few tabs // comment with newline after', - }, - { - code: 'a, \t \t // comment\nb {}', - description: 'with end-of-line and few tabs and spaces // comment with newline after', - }, - ], -}); - -testRule({ - ruleName, - config: ['always'], - customSyntax: 'postcss-less', - fix: true, - - accept: [ - { - code: 'a, // comment\nb {}', - description: 'with end-of-line // comment with newline after', - }, - { - code: 'a, // comment\nb {}', - description: 'with end-of-line and few spaces // comment with newline after', - }, - { - code: 'a,\t// comment\nb {}', - description: 'with end-of-line and a tab // comment with newline after', - }, - { - code: 'a,\t\t// comment\nb {}', - description: 'with end-of-line and few tabs // comment with newline after', - }, - { - code: 'a, \t \t // comment\nb {}', - description: 'with end-of-line and few tabs and spaces // comment with newline after', - }, - { - code: '.col( @a, @b ) {}', - description: 'mixin ending in a char', - }, - { - code: '.col3( @a, @b ) {}', - description: 'mixin ending in a number', - }, - ], -}); diff --git a/lib/rules/selector-list-comma-newline-after/index.js b/lib/rules/selector-list-comma-newline-after/index.js deleted file mode 100644 index 5901f32fea..0000000000 --- a/lib/rules/selector-list-comma-newline-after/index.js +++ /dev/null @@ -1,122 +0,0 @@ -'use strict'; - -const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const styleSearch = require('style-search'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'selector-list-comma-newline-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected newline after ","', - expectedAfterMultiLine: () => 'Expected newline after "," in a multi-line list', - rejectedAfterMultiLine: () => 'Unexpected whitespace after "," in a multi-line list', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/selector-list-comma-newline-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('newline', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'always-multi-line', 'never-multi-line'], - }); - - if (!validOptions) { - return; - } - - root.walkRules((ruleNode) => { - if (!isStandardSyntaxRule(ruleNode)) { - return; - } - - // Get raw selector so we can allow end-of-line comments, e.g. - // a, /* comment */ - // b {} - const selector = ruleNode.raws.selector ? ruleNode.raws.selector.raw : ruleNode.selector; - - /** @type {number[]} */ - const fixIndices = []; - - styleSearch( - { - source: selector, - target: ',', - functionArguments: 'skip', - }, - (match) => { - const nextChars = selector.slice(match.endIndex); - - // If there's a // comment, that means there has to be a newline - // ending the comment so we're fine - if (/^\s+\/\//.test(nextChars)) { - return; - } - - // If there are spaces and then a comment begins, look for the newline - const indextoCheckAfter = /^\s+\/\*/.test(nextChars) - ? selector.indexOf('*/', match.endIndex) + 1 - : match.startIndex; - - checker.afterOneOnly({ - source: selector, - index: indextoCheckAfter, - err: (m) => { - if (context.fix) { - fixIndices.push(indextoCheckAfter + 1); - - return; - } - - report({ - message: m, - node: ruleNode, - index: match.startIndex, - result, - ruleName, - }); - }, - }); - }, - ); - - if (fixIndices.length) { - let fixedSelector = selector; - - for (const index of fixIndices.sort((a, b) => b - a)) { - const beforeSelector = fixedSelector.slice(0, index); - let afterSelector = fixedSelector.slice(index); - - if (primary.startsWith('always')) { - afterSelector = context.newline + afterSelector; - } else if (primary.startsWith('never-multi-line')) { - afterSelector = afterSelector.replace(/^\s*/, ''); - } - - fixedSelector = beforeSelector + afterSelector; - } - - if (ruleNode.raws.selector) { - ruleNode.raws.selector.raw = fixedSelector; - } else { - ruleNode.selector = fixedSelector; - } - } - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/selector-list-comma-newline-before/README.md b/lib/rules/selector-list-comma-newline-before/README.md deleted file mode 100644 index e2e495b940..0000000000 --- a/lib/rules/selector-list-comma-newline-before/README.md +++ /dev/null @@ -1,114 +0,0 @@ -# selector-list-comma-newline-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline or disallow whitespace before the commas of selector lists. - - -```css - a - , b { color: pink; } -/** ↑ - * The newline before this comma */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a newline before the commas. - -The following patterns are considered problems: - - -```css -a, b { color: pink; } -``` - - -```css -a, -b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a -, b { color: pink; } -``` - - -```css -a -,b { color: pink; } -``` - -### `"always-multi-line"` - -There _must always_ be a newline before the commas in multi-line selector lists. - -The following patterns are considered problems: - - -```css -a, -b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a, b { color: pink; } -``` - - -```css -a -,b { color: pink; } -``` - - -```css -a -, -b { color: pink; } -``` - -### `"never-multi-line"` - -There _must never_ be whitespace before the commas in multi-line selector lists. - -The following patterns are considered problems: - - -```css -a -, b { color: pink; } -``` - - -```css -a -, -b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a,b { color: pink; } -``` - - -```css -a, -b { color: pink; } -``` diff --git a/lib/rules/selector-list-comma-newline-before/__tests__/index.js b/lib/rules/selector-list-comma-newline-before/__tests__/index.js deleted file mode 100644 index f685ac6bb1..0000000000 --- a/lib/rules/selector-list-comma-newline-before/__tests__/index.js +++ /dev/null @@ -1,298 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a\n,b {}', - }, - { - code: 'a\n\n,b {}', - }, - { - code: 'a\n,b\n,c {}', - }, - { - code: 'a\r\n,b\r\n,c {}', - description: 'CRLF', - }, - { - code: 'a\r\n\r\n,b\r\n,c {}', - description: 'Double CRLF', - }, - { - code: 'a\n, b {}', - }, - { - code: 'a\n,\nb {}', - }, - { - code: 'a\r\n,\r\nb {}', - description: 'CRLF', - }, - { - code: 'a\n,b[data-foo="tr,tr"] {}', - }, - { - code: 'a\n ,b {}', - description: 'indentation after the newline before the comma', - }, - { - code: 'a\r\n ,b {}', - description: 'indentation after the CRLF before the comma', - }, - { - code: 'a\n\t\t,b {}', - description: 'indentation after the newline before the comma', - }, - { - code: '\ta\n\t, b {}', - description: 'indented statement', - }, - { - code: 'a:matches(:hover, :focus) {}', - description: 'comma inside :matches()', - }, - { - code: ':not(:hover, :focus) {}', - description: 'comma inside :not()', - }, - { - 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', - }, - { - code: 'a/*comment,comment*/\n,/*comment*/b {}', - description: 'comment', - }, - ], - - reject: [ - { - code: 'a,b {}', - fixed: 'a\n,b {}', - message: messages.expectedBefore(), - line: 1, - column: 2, - }, - { - code: 'a ,b {}', - fixed: 'a\n ,b {}', - message: messages.expectedBefore(), - line: 1, - column: 3, - }, - { - code: 'a ,b {}', - fixed: 'a\n ,b {}', - message: messages.expectedBefore(), - line: 1, - column: 4, - }, - { - code: 'a\t,b {}', - fixed: 'a\n\t,b {}', - message: messages.expectedBefore(), - line: 1, - column: 3, - }, - { - code: 'a\n,b,c {}', - fixed: 'a\n,b\n,c {}', - message: messages.expectedBefore(), - line: 2, - column: 3, - }, - { - code: 'a\r\n,b,c {}', - fixed: 'a\r\n,b\r\n,c {}', - description: 'CRLF', - message: messages.expectedBefore(), - line: 2, - column: 3, - }, - { - code: 'a/*comment*/,/*comment*/b {}', - fixed: 'a/*comment*/\n,/*comment*/b {}', - description: 'comment', - message: messages.expectedBefore(), - line: 1, - column: 13, - }, - { - code: 'a,b,c,d,e,f,g {}', - fixed: 'a\n,b\n,c\n,d\n,e\n,f\n,g {}', - warnings: [ - { - message: messages.expectedBefore(), - line: 1, - column: 2, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 4, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 6, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 8, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 10, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 12, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: 'a\n,b {}', - }, - { - code: 'a\r\n,b {}', - description: 'CRLF', - }, - { - code: 'a, b {}', - description: 'ignores single-line', - }, - { - code: 'a, b {\n}', - description: 'ignores single-line selector list, multi-line block', - }, - { - code: '\ta\n\t, b {\n}', - description: 'indented statement', - }, - ], - - reject: [ - { - code: 'a\n,b, c {}', - fixed: 'a\n,b\n, c {}', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 3, - }, - { - code: 'a\r\n,b, c {}', - fixed: 'a\r\n,b\r\n, c {}', - description: 'CRLF', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 3, - }, - { - code: 'a\n,b, c {\n}', - fixed: 'a\n,b\n, c {\n}', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 3, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - fix: true, - - accept: [ - { - code: 'a,\nb {}', - }, - { - code: 'a ,b {}', - description: 'ignores single-line', - }, - { - code: 'a ,b {\n}', - description: 'ignores single-line selector list, multi-line block', - }, - { - code: 'a ,b {\r\n}', - description: 'ignores single-line selector list, multi-line block with CRLF', - }, - { - code: 'a:matches(:hover, :focus) {}', - description: 'comma inside :matches()', - }, - { - code: ':not(:hover, :focus) {}', - description: 'comma inside :not()', - }, - { - code: 'a/*comment\n,comment*/,/*comment*/b {\n}', - description: 'comment', - }, - ], - - reject: [ - { - code: 'a,\nb , c {}', - fixed: 'a,\nb, c {}', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 3, - }, - { - code: 'a,\nb , c {\n}', - fixed: 'a,\nb, c {\n}', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 3, - }, - { - code: 'a,\r\nb , c {\r\n}', - fixed: 'a,\r\nb, c {\r\n}', - description: 'CRLF', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 3, - }, - { - code: 'a/*comment*/\n,/*comment*/b {\n}', - fixed: 'a/*comment*/,/*comment*/b {\n}', - description: 'comment', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 1, - }, - ], -}); diff --git a/lib/rules/selector-list-comma-newline-before/index.js b/lib/rules/selector-list-comma-newline-before/index.js deleted file mode 100644 index becc7c568e..0000000000 --- a/lib/rules/selector-list-comma-newline-before/index.js +++ /dev/null @@ -1,96 +0,0 @@ -'use strict'; - -const ruleMessages = require('../../utils/ruleMessages'); -const selectorListCommaWhitespaceChecker = require('../selectorListCommaWhitespaceChecker'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'selector-list-comma-newline-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected newline before ","', - expectedBeforeMultiLine: () => 'Expected newline before "," in a multi-line list', - rejectedBeforeMultiLine: () => 'Unexpected whitespace before "," in a multi-line list', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/selector-list-comma-newline-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('newline', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'always-multi-line', 'never-multi-line'], - }); - - if (!validOptions) { - return; - } - - /** @type {Map | undefined} */ - let fixData; - - selectorListCommaWhitespaceChecker({ - root, - result, - locationChecker: checker.beforeAllowingIndentation, - checkedRuleName: ruleName, - fix: context.fix - ? (ruleNode, index) => { - fixData = fixData || new Map(); - const commaIndices = fixData.get(ruleNode) || []; - - commaIndices.push(index); - fixData.set(ruleNode, commaIndices); - - return true; - } - : null, - }); - - if (fixData) { - for (const [ruleNode, commaIndices] of fixData.entries()) { - let selector = ruleNode.raws.selector ? ruleNode.raws.selector.raw : ruleNode.selector; - - for (const index of commaIndices.sort((a, b) => b - a)) { - let beforeSelector = selector.slice(0, index); - const afterSelector = selector.slice(index); - - if (primary.startsWith('always')) { - const spaceIndex = beforeSelector.search(/\s+$/); - - if (spaceIndex >= 0) { - beforeSelector = - beforeSelector.slice(0, spaceIndex) + - context.newline + - beforeSelector.slice(spaceIndex); - } else { - beforeSelector += context.newline; - } - } else if (primary === 'never-multi-line') { - beforeSelector = beforeSelector.replace(/\s*$/, ''); - } - - selector = beforeSelector + afterSelector; - } - - if (ruleNode.raws.selector) { - ruleNode.raws.selector.raw = selector; - } else { - ruleNode.selector = selector; - } - } - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/selector-list-comma-space-after/README.md b/lib/rules/selector-list-comma-space-after/README.md deleted file mode 100644 index 321752060e..0000000000 --- a/lib/rules/selector-list-comma-space-after/README.md +++ /dev/null @@ -1,112 +0,0 @@ -# selector-list-comma-space-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace after the commas of selector lists. - - -```css - a, b { color: pink; } -/** ↑ - * The space after this comma */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"|"always-single-line"|"never-single-line"` - -### `"always"` - -There _must always_ be a single space after the commas. - -The following patterns are considered problems: - - -```css -a,b { color: pink; } -``` - - -```css -a ,b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a, b { color: pink; } -``` - - -```css -a , b { color: pink; } -``` - -### `"never"` - -There _must never_ be whitespace after the commas. - -The following patterns are considered problems: - - -```css -a, b { color: pink; } -``` - - -```css -a , b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a,b { color: pink; } -``` - - -```css -a ,b { color: pink; } -``` - -### `"always-single-line"` - -There _must always_ be a single space after the commas in single-line selector lists. - -The following patterns are considered problems: - - -```css -a,b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a -,b { color: pink; } -``` - -### `"never-single-line"` - -There _must never_ be a single space after the commas in single-line selector lists. - -The following patterns are considered problems: - - -```css -a, b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a -, b { color: pink; } -``` diff --git a/lib/rules/selector-list-comma-space-after/__tests__/index.js b/lib/rules/selector-list-comma-space-after/__tests__/index.js deleted file mode 100644 index a0e63bb50f..0000000000 --- a/lib/rules/selector-list-comma-space-after/__tests__/index.js +++ /dev/null @@ -1,396 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a, b {}', - }, - { - code: 'a, b, c {}', - }, - { - code: 'a , b {}', - }, - { - code: 'a\n, b {}', - }, - { - code: 'a\r\n, b {}', - description: 'CRLF', - }, - { - code: 'a, b[data-foo="tr,tr"] {}', - description: 'string', - }, - { - code: 'a:matches(:hover,:focus) {}', - description: 'comma inside :matches()', - }, - { - code: ':not(:hover,:focus) {}', - description: 'comma inside :not()', - }, - { - 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', - }, - { - code: 'a/*comment,comment*/, /*comment*/b {}', - description: 'comment', - }, - ], - - reject: [ - { - code: 'a,b {}', - fixed: 'a, b {}', - message: messages.expectedAfter(), - line: 1, - column: 2, - }, - { - code: 'a, b {}', - fixed: 'a, b {}', - message: messages.expectedAfter(), - line: 1, - column: 2, - }, - { - code: 'a,\nb {}', - fixed: 'a, b {}', - message: messages.expectedAfter(), - line: 1, - column: 2, - }, - { - code: 'a,\r\nb {}', - fixed: 'a, b {}', - description: 'CRLF', - message: messages.expectedAfter(), - line: 1, - column: 2, - }, - { - code: 'a,\tb {}', - fixed: 'a, b {}', - message: messages.expectedAfter(), - line: 1, - column: 2, - }, - { - code: 'a, b,c {}', - fixed: 'a, b, c {}', - message: messages.expectedAfter(), - line: 1, - column: 5, - }, - { - code: 'a, b, c {}', - fixed: 'a, b, c {}', - message: messages.expectedAfter(), - line: 1, - column: 5, - }, - { - code: 'a/*comment*/,/*comment*/b {}', - fixed: 'a/*comment*/, /*comment*/b {}', - message: messages.expectedAfter(), - line: 1, - column: 13, - }, - { - code: 'a,b,c {}', - fixed: 'a, b, c {}', - warnings: [ - { - message: messages.expectedAfter(), - line: 1, - column: 2, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 4, - }, - ], - }, - { - code: 'a,b,c,d,e,f,g {}', - fixed: 'a, b, c, d, e, f, g {}', - warnings: [ - { - message: messages.expectedAfter(), - line: 1, - column: 2, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 4, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 6, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 8, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 10, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 12, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a,b {}', - }, - { - code: 'a,b,c {}', - }, - { - code: 'a ,b {}', - }, - { - code: 'a\n,b {}', - }, - { - code: 'a\r\n,b {}', - description: 'CRLF', - }, - { - code: 'a,b[data-foo="tr, tr"] {}', - description: 'string', - }, - { - code: 'a:matches(:hover, :focus) {}', - description: 'comma inside :matches()', - }, - { - code: ':not(:hover, :focus) {}', - description: 'comma inside :not()', - }, - { - code: 'a/*comment, comment*/,/*comment*/b {}', - description: 'comment', - }, - ], - - reject: [ - { - code: 'a, b {}', - fixed: 'a,b {}', - message: messages.rejectedAfter(), - line: 1, - column: 2, - }, - { - code: 'a, b {}', - fixed: 'a,b {}', - message: messages.rejectedAfter(), - line: 1, - column: 2, - }, - { - code: 'a,\nb {}', - fixed: 'a,b {}', - message: messages.rejectedAfter(), - line: 1, - column: 2, - }, - { - code: 'a,\r\nb {}', - fixed: 'a,b {}', - description: 'CRLF', - message: messages.rejectedAfter(), - line: 1, - column: 2, - }, - { - code: 'a,\tb {}', - fixed: 'a,b {}', - message: messages.rejectedAfter(), - line: 1, - column: 2, - }, - { - code: 'a,b, c {}', - fixed: 'a,b,c {}', - message: messages.rejectedAfter(), - line: 1, - column: 4, - }, - { - code: 'a,b, c {}', - fixed: 'a,b,c {}', - message: messages.rejectedAfter(), - line: 1, - column: 4, - }, - { - code: 'a/*comment*/, /*comment*/b {}', - fixed: 'a/*comment*/,/*comment*/b {}', - message: messages.rejectedAfter(), - line: 1, - column: 13, - }, - { - code: 'a, b, c {}', - fixed: 'a,b,c {}', - warnings: [ - { - message: messages.rejectedAfter(), - line: 1, - column: 2, - }, - { - message: messages.rejectedAfter(), - line: 1, - column: 5, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: 'a, b {}', - }, - { - code: 'a, b {\n}', - description: 'single-line selector list, multi-line block', - }, - { - code: 'a, b {\r\n}', - description: 'single-line selector list, multi-line block with CRLF', - }, - ], - - reject: [ - { - code: 'a,b {}', - fixed: 'a, b {}', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 2, - }, - { - code: 'a,b {\n}', - fixed: 'a, b {\n}', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 2, - }, - { - code: 'a,b {\r\n}', - fixed: 'a, b {\r\n}', - description: 'CRLF', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - fix: true, - - accept: [ - { - code: 'a,b {}', - }, - { - code: 'a,b {\n}', - description: 'single-line selector list, multi-line block', - }, - { - code: 'a,b {\r\n}', - description: 'single-line selector list, multi-line block with CRLF', - }, - ], - - reject: [ - { - code: 'a, b {}', - fixed: 'a,b {}', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 2, - }, - { - code: 'a, b {\n}', - fixed: 'a,b {\n}', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 2, - }, - { - code: 'a, b {\r\n}', - fixed: 'a,b {\r\n}', - description: 'CRLF', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: ['always'], - customSyntax: 'postcss-less', - - accept: [ - { - code: '.col( @a,@b ) {}', - description: 'mixin ending in a char', - }, - { - code: '.col3( @a,@b ) {}', - description: 'mixin ending in a number', - }, - ], -}); diff --git a/lib/rules/selector-list-comma-space-after/index.js b/lib/rules/selector-list-comma-space-after/index.js deleted file mode 100644 index c50d707905..0000000000 --- a/lib/rules/selector-list-comma-space-after/index.js +++ /dev/null @@ -1,88 +0,0 @@ -'use strict'; - -const ruleMessages = require('../../utils/ruleMessages'); -const selectorListCommaWhitespaceChecker = require('../selectorListCommaWhitespaceChecker'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'selector-list-comma-space-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected single space after ","', - rejectedAfter: () => 'Unexpected whitespace after ","', - expectedAfterSingleLine: () => 'Expected single space after "," in a single-line list', - rejectedAfterSingleLine: () => 'Unexpected whitespace after "," in a single-line list', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/selector-list-comma-space-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never', 'always-single-line', 'never-single-line'], - }); - - if (!validOptions) { - return; - } - - /** @type {Map | undefined} */ - let fixData; - - selectorListCommaWhitespaceChecker({ - root, - result, - locationChecker: checker.after, - checkedRuleName: ruleName, - fix: context.fix - ? (ruleNode, index) => { - fixData = fixData || new Map(); - const commaIndices = fixData.get(ruleNode) || []; - - commaIndices.push(index); - fixData.set(ruleNode, commaIndices); - - return true; - } - : null, - }); - - if (fixData) { - for (const [ruleNode, commaIndices] of fixData.entries()) { - let selector = ruleNode.raws.selector ? ruleNode.raws.selector.raw : ruleNode.selector; - - for (const index of commaIndices.sort((a, b) => b - a)) { - const beforeSelector = selector.slice(0, index + 1); - let afterSelector = selector.slice(index + 1); - - if (primary.startsWith('always')) { - afterSelector = afterSelector.replace(/^\s*/, ' '); - } else if (primary.startsWith('never')) { - afterSelector = afterSelector.replace(/^\s*/, ''); - } - - selector = beforeSelector + afterSelector; - } - - if (ruleNode.raws.selector) { - ruleNode.raws.selector.raw = selector; - } else { - ruleNode.selector = selector; - } - } - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/selector-list-comma-space-before/README.md b/lib/rules/selector-list-comma-space-before/README.md deleted file mode 100644 index 51891907dc..0000000000 --- a/lib/rules/selector-list-comma-space-before/README.md +++ /dev/null @@ -1,112 +0,0 @@ -# selector-list-comma-space-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace before the commas of selector lists. - - -```css - a ,b { color: pink; } -/** ↑ - * The space before this comma */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"|"always-single-line"|"never-single-line"` - -### `"always"` - -There _must always_ be a single space before the commas. - -The following patterns are considered problems: - - -```css -a,b { color: pink; } -``` - - -```css -a, b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a ,b { color: pink; } -``` - - -```css -a , b { color: pink; } -``` - -### `"never"` - -There _must never_ be whitespace before the commas. - -The following patterns are considered problems: - - -```css -a ,b { color: pink; } -``` - - -```css -a , b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a,b { color: pink; } -``` - - -```css -a, b { color: pink; } -``` - -### `"always-single-line"` - -There _must always_ be a single space before the commas in single-line selector lists. - -The following patterns are considered problems: - - -```css -a,b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a, -b { color: pink; } -``` - -### `"never-single-line"` - -There _must never_ be a single space before the commas in single-line selector lists. - -The following patterns are considered problems: - - -```css -a ,b { color: pink; } -``` - -The following patterns are _not_ considered problems: - - -```css -a , -b { color: pink; } -``` diff --git a/lib/rules/selector-list-comma-space-before/__tests__/index.js b/lib/rules/selector-list-comma-space-before/__tests__/index.js deleted file mode 100644 index 0e9268c527..0000000000 --- a/lib/rules/selector-list-comma-space-before/__tests__/index.js +++ /dev/null @@ -1,377 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a ,b {}', - }, - { - code: 'a ,b ,c {}', - }, - { - code: 'a , b {}', - }, - { - code: 'a ,\nb {}', - }, - { - code: 'a ,\r\nb {}', - description: 'CRLF', - }, - { - code: 'a ,b[data-foo="tr,tr"] {}', - description: 'string', - }, - { - code: 'a:matches(:hover, :focus) {}', - description: 'comma inside :matches()', - }, - { - code: ':not(:hover, :focus) {}', - description: 'comma inside :not()', - }, - { - 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', - }, - { - code: 'a/*comment,comment*/ ,/*comment*/b {}', - description: 'comment', - }, - ], - - reject: [ - { - code: 'a,b {}', - fixed: 'a ,b {}', - message: messages.expectedBefore(), - line: 1, - column: 2, - }, - { - code: 'a ,b {}', - fixed: 'a ,b {}', - message: messages.expectedBefore(), - line: 1, - column: 4, - }, - { - code: 'a\n,b {}', - fixed: 'a ,b {}', - message: messages.expectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a\r\n,b {}', - fixed: 'a ,b {}', - description: 'CRLF', - message: messages.expectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a\t,b {}', - fixed: 'a ,b {}', - message: messages.expectedBefore(), - line: 1, - column: 3, - }, - { - code: 'a ,b,c {}', - fixed: 'a ,b ,c {}', - message: messages.expectedBefore(), - line: 1, - column: 5, - }, - { - code: 'a ,b ,c {}', - fixed: 'a ,b ,c {}', - message: messages.expectedBefore(), - line: 1, - column: 7, - }, - { - code: 'a,b,c {}', - fixed: 'a ,b ,c {}', - warnings: [ - { - message: messages.expectedBefore(), - line: 1, - column: 2, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 4, - }, - ], - }, - { - code: 'a/*comment*/,/*comment*/b {}', - fixed: 'a/*comment*/ ,/*comment*/b {}', - message: messages.expectedBefore(), - line: 1, - column: 13, - }, - { - code: 'a,b,c,d,e,f,g {}', - fixed: 'a ,b ,c ,d ,e ,f ,g {}', - warnings: [ - { - message: messages.expectedBefore(), - line: 1, - column: 2, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 4, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 6, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 8, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 10, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 12, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a,b {}', - }, - { - code: 'a,b,c {}', - }, - { - code: 'a, b {}', - }, - { - code: 'a,\nb {}', - }, - { - code: 'a,\r\nb {}', - description: 'CRLF', - }, - { - code: 'a,b[data-foo="tr ,tr"] {}', - description: 'string', - }, - { - code: 'a:matches(:hover , :focus) {}', - description: 'comma inside :matches()', - }, - { - code: ':not(:hover , :focus) {}', - description: 'comma inside :not()', - }, - { - code: 'a/*comment ,comment*/,/*comment*/b {}', - description: 'comment', - }, - ], - - reject: [ - { - code: 'a ,b {}', - fixed: 'a,b {}', - message: messages.rejectedBefore(), - line: 1, - column: 3, - }, - { - code: 'a ,b {}', - fixed: 'a,b {}', - message: messages.rejectedBefore(), - line: 1, - column: 4, - }, - { - code: 'a\n,b {}', - fixed: 'a,b {}', - message: messages.rejectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a\r\n,b {}', - fixed: 'a,b {}', - description: 'CRLF', - message: messages.rejectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a\t,b {}', - fixed: 'a,b {}', - message: messages.rejectedBefore(), - line: 1, - column: 3, - }, - { - code: 'a,b ,c {}', - fixed: 'a,b,c {}', - message: messages.rejectedBefore(), - line: 1, - column: 5, - }, - { - code: 'a,b ,c {}', - fixed: 'a,b,c {}', - message: messages.rejectedBefore(), - line: 1, - column: 6, - }, - { - code: 'a/*comment*/ ,/*comment*/b {}', - fixed: 'a/*comment*/,/*comment*/b {}', - message: messages.rejectedBefore(), - line: 1, - column: 14, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: 'a ,b {}', - }, - { - code: 'a ,b {\n}', - description: 'single-line selector list, multi-line block', - }, - { - code: 'a ,b {\r\n}', - description: 'single-line selector list, multi-line block with CRLF', - }, - ], - - reject: [ - { - code: 'a,b {}', - fixed: 'a ,b {}', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 2, - }, - { - code: 'a,b {\n}', - fixed: 'a ,b {\n}', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 2, - }, - { - code: 'a,b {\r\n}', - fixed: 'a ,b {\r\n}', - description: 'CRLF', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 2, - }, - { - code: 'a/*comment*/,/*comment*/b {\n}', - fixed: 'a/*comment*/ ,/*comment*/b {\n}', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 13, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - fix: true, - - accept: [ - { - code: 'a,b {}', - }, - { - code: 'a,b {\n}', - description: 'single-line selector list, multi-line block', - }, - { - code: 'a,b {\r\n}', - description: 'single-line selector list, multi-line block with CRLF', - }, - ], - - reject: [ - { - code: 'a ,b {}', - fixed: 'a,b {}', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 3, - }, - { - code: 'a ,b {\n}', - fixed: 'a,b {\n}', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 3, - }, - { - code: 'a ,b {\r\n}', - fixed: 'a,b {\r\n}', - description: 'CRLF', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 3, - }, - { - code: 'a/*comment*/ ,/*comment*/b {\n}', - fixed: 'a/*comment*/,/*comment*/b {\n}', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 14, - }, - ], -}); diff --git a/lib/rules/selector-list-comma-space-before/index.js b/lib/rules/selector-list-comma-space-before/index.js deleted file mode 100644 index e8e8cbe5bd..0000000000 --- a/lib/rules/selector-list-comma-space-before/index.js +++ /dev/null @@ -1,88 +0,0 @@ -'use strict'; - -const ruleMessages = require('../../utils/ruleMessages'); -const selectorListCommaWhitespaceChecker = require('../selectorListCommaWhitespaceChecker'); -const validateOptions = require('../../utils/validateOptions'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'selector-list-comma-space-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected single space before ","', - rejectedBefore: () => 'Unexpected whitespace before ","', - expectedBeforeSingleLine: () => 'Expected single space before "," in a single-line list', - rejectedBeforeSingleLine: () => 'Unexpected whitespace before "," in a single-line list', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/selector-list-comma-space-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never', 'always-single-line', 'never-single-line'], - }); - - if (!validOptions) { - return; - } - - /** @type {Map | undefined} */ - let fixData; - - selectorListCommaWhitespaceChecker({ - root, - result, - locationChecker: checker.before, - checkedRuleName: ruleName, - fix: context.fix - ? (ruleNode, index) => { - fixData = fixData || new Map(); - const commaIndices = fixData.get(ruleNode) || []; - - commaIndices.push(index); - fixData.set(ruleNode, commaIndices); - - return true; - } - : null, - }); - - if (fixData) { - for (const [ruleNode, commaIndices] of fixData.entries()) { - let selector = ruleNode.raws.selector ? ruleNode.raws.selector.raw : ruleNode.selector; - - for (const index of commaIndices.sort((a, b) => b - a)) { - let beforeSelector = selector.slice(0, index); - const afterSelector = selector.slice(index); - - if (primary.includes('always')) { - beforeSelector = beforeSelector.replace(/\s*$/, ' '); - } else if (primary.includes('never')) { - beforeSelector = beforeSelector.replace(/\s*$/, ''); - } - - selector = beforeSelector + afterSelector; - } - - if (ruleNode.raws.selector) { - ruleNode.raws.selector.raw = selector; - } else { - ruleNode.selector = selector; - } - } - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/selector-max-empty-lines/README.md b/lib/rules/selector-max-empty-lines/README.md deleted file mode 100644 index e457bc1948..0000000000 --- a/lib/rules/selector-max-empty-lines/README.md +++ /dev/null @@ -1,105 +0,0 @@ -# selector-max-empty-lines - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Limit the number of adjacent empty lines within selectors. - - -```css -a, - /* ← */ -b { /* ↑ */ - color: red; /* ↑ */ -} /* ↑ */ -/** ↑ - * This empty line */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`int`: Maximum number of adjacent empty lines allowed. - -For example, with `0`: - -The following patterns are considered problems: - - -```css -a - -b { - color: red; -} -``` - - -```css -a, - -b { - color: red; -} -``` - - -```css -a - -> -b { - color: red; -} -``` - - -```css -a -> - -b { - color: red; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a b { - color: red; -} -``` - - -```css -a -b { - color: red; -} -``` - - -```css -a, -b { - color: red; -} -``` - - -```css -a > b { - color: red; -} -``` - - -```css -a -> -b { - color: red; -} -``` diff --git a/lib/rules/selector-max-empty-lines/__tests__/index.js b/lib/rules/selector-max-empty-lines/__tests__/index.js deleted file mode 100644 index b2ddde920f..0000000000 --- a/lib/rules/selector-max-empty-lines/__tests__/index.js +++ /dev/null @@ -1,2417 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: [0], - fix: true, - - accept: [ - { - code: '\n.foo { }', - }, - { - code: '\r\n.foo { }', - }, - { - code: '\n\n.foo { }', - }, - { - code: '\r\n\r\n.foo { }', - }, - { - code: '\n\n\n.foo { }', - }, - { - code: '\r\n\r\n\r\n.foo { }', - }, - { - code: '.foo\n{ }', - }, - { - code: '.foo\r\n{ }', - }, - { - code: '.foo\n\n{ }', - }, - { - code: '.foo\r\n\r\n{ }', - }, - { - code: '.foo\n\n\n{ }', - }, - { - code: '.foo\r\n\r\n\r\n{ }', - }, - { - code: '.foo\n\n\n{ }', - }, - { - code: '.foo\r\n\r\n\r\n{ }', - }, - { - code: '.foo {\n}', - }, - { - code: '.foo {\r\n}', - }, - { - code: '.foo {\n\n}', - }, - { - code: '.foo {\r\n\r\n}', - }, - { - code: '.foo {\n\n\n}', - }, - { - code: '.foo {\r\n\r\n\r\n}', - }, - { - code: '.foo {\n\n\n}', - }, - { - code: '.foo {\r\n\r\n\r\n}', - }, - { - code: '.foo { }\n', - }, - { - code: '.foo { }\r\n', - }, - { - code: '.foo { }\n\n', - }, - { - code: '.foo { }\r\n\r\n', - }, - { - code: '.foo { }\n\n\n', - }, - { - code: '.foo { }\r\n\r\n\r\n', - }, - { - code: '.foo { }\n\n\n', - }, - { - code: '.foo { }\r\n\r\n\r\n', - }, - { - code: '\n.foo, .bar { }', - }, - { - code: '\r\n.foo, .bar { }', - }, - { - code: '\n\n.foo, .bar { }', - }, - { - code: '\r\n\r\n.foo, .bar { }', - }, - { - code: '\n\n\n.foo, .bar { }', - }, - { - code: '\r\n\r\n\r\n.foo, .bar { }', - }, - { - code: '.foo, .bar { }', - }, - { - code: '.foo,\n.bar { }', - }, - { - code: '.foo,\r\n.bar { }', - }, - { - code: '.foo, .bar\n{ }', - }, - { - code: '.foo, .bar\r\n{ }', - }, - { - code: '.foo, .bar\n\n{ }', - }, - { - code: '.foo, .bar\r\n\r\n{ }', - }, - { - code: '.foo, .bar\n\n\n{ }', - }, - { - code: '.foo, .bar\r\n\r\n\r\n{ }', - }, - { - code: '.foo, .bar {\n}', - }, - { - code: '.foo, .bar {\r\n}', - }, - { - code: '.foo, .bar {\n\n}', - }, - { - code: '.foo, .bar {\r\n\r\n}', - }, - { - code: '.foo, .bar {\n\n\n}', - }, - { - code: '.foo, .bar {\r\n\r\n\r\n}', - }, - { - code: '.foo, .bar { }\n', - }, - { - code: '.foo, .bar { }\r\n', - }, - { - code: '.foo, .bar { }\n\n', - }, - { - code: '.foo, .bar { }\r\n\r\n', - }, - { - code: '.foo, .bar { }\n\n\n', - }, - { - code: '.foo, .bar { }\r\n\r\n\r\n', - }, - { - code: '.foo .bar { }', - }, - { - code: '.foo\n.bar { }', - }, - { - code: '.foo\r\n.bar { }', - }, - { - code: '\n.foo .bar { }', - }, - { - code: '\r\n.foo .bar { }', - }, - { - code: '\n\n.foo .bar { }', - }, - { - code: '\r\n\r\n.foo .bar { }', - }, - { - code: '\n\n\n.foo .bar { }', - }, - { - code: '\r\n\r\n\r\n.foo .bar { }', - }, - { - code: '.foo .bar\n{ }', - }, - { - code: '.foo .bar\r\n{ }', - }, - { - code: '.foo .bar\n\n{ }', - }, - { - code: '.foo .bar\r\n\r\n{ }', - }, - { - code: '.foo .bar\n\n\n{ }', - }, - { - code: '.foo .bar\r\n\r\n\r\n{ }', - }, - { - code: '.foo .bar {\n}', - }, - { - code: '.foo .bar {\r\n}', - }, - { - code: '.foo .bar {\n\n}', - }, - { - code: '.foo .bar {\r\n\r\n}', - }, - { - code: '.foo .bar {\n\n\n}', - }, - { - code: '.foo .bar {\r\n\r\n\r\n}', - }, - { - code: '.foo .bar { }\n', - }, - { - code: '.foo .bar { }\r\n', - }, - { - code: '.foo .bar { }\n\n', - }, - { - code: '.foo .bar { }\r\n\r\n', - }, - { - code: '.foo .bar { }\n\n\n', - }, - { - code: '.foo .bar { }\r\n\r\n\r\n', - }, - { - code: '.foo > .bar { }', - }, - { - code: '\n.foo > .bar { }', - }, - { - code: '\r\n.foo > .bar { }', - }, - { - code: '\n\n.foo > .bar { }', - }, - { - code: '\r\n\r\n.foo > .bar { }', - }, - { - code: '\n\n\n.foo > .bar { }', - }, - { - code: '\r\n\r\n\r\n.foo > .bar { }', - }, - { - code: '.foo\n> .bar { }', - }, - { - code: '.foo\r\n> .bar { }', - }, - { - code: '.foo >\n.bar { }', - }, - { - code: '.foo >\r\n.bar { }', - }, - { - code: '.foo > .bar\n{ }', - }, - { - code: '.foo > .bar\r\n{ }', - }, - { - code: '.foo > .bar\n\n{ }', - }, - { - code: '.foo > .bar\r\n\r\n{ }', - }, - { - code: '.foo > .bar\n\n\n{ }', - }, - { - code: '.foo > .bar\r\n\r\n\r\n{ }', - }, - { - code: '.foo > .bar {\n}', - }, - { - code: '.foo > .bar {\r\n}', - }, - { - code: '.foo > .bar {\n\n}', - }, - { - code: '.foo > .bar {\r\n\r\n}', - }, - { - code: '.foo > .bar {\n\n\n}', - }, - { - code: '.foo > .bar {\r\n\r\n\r\n}', - }, - { - code: '.foo > .bar { }\n', - }, - { - code: '.foo > .bar { }\r\n', - }, - { - code: '.foo > .bar { }\n\n', - }, - { - code: '.foo > .bar { }\r\n\r\n', - }, - { - code: '.foo > .bar { }\n\n\n', - }, - { - code: '.foo > .bar { }\r\n\r\n\r\n', - }, - { - code: '\na[itemprop=url] { }', - }, - { - code: '\r\na[itemprop=url] { }', - }, - { - code: '\n\na[itemprop=url] { }', - }, - { - code: '\r\n\r\na[itemprop=url] { }', - }, - { - code: '\n\n\na[itemprop=url] { }', - }, - { - code: '\r\n\r\n\r\na[itemprop=url] { }', - }, - { - code: 'a\n[itemprop=url] { }', - }, - { - code: 'a\r\n[itemprop=url] { }', - }, - { - code: 'a[\nitemprop=url] { }', - }, - { - code: 'a[\r\nitemprop=url] { }', - }, - { - code: 'a[itemprop\n=url] { }', - }, - { - code: 'a[itemprop\r\n=url] { }', - }, - { - code: 'a[itemprop=\nurl] { }', - }, - { - code: 'a[itemprop=\r\nurl] { }', - }, - { - code: 'a[itemprop=url\n] { }', - }, - { - code: 'a[itemprop=url\r\n] { }', - }, - { - code: 'a[itemprop=url]\n{ }', - }, - { - code: 'a[itemprop=url]\r\n{ }', - }, - { - code: 'a[itemprop=url]\n\n{ }', - }, - { - code: 'a[itemprop=url]\r\n\r\n{ }', - }, - { - code: 'a[itemprop=url]\n\n\n{ }', - }, - { - code: 'a[itemprop=url]\r\n\r\n\r\n{ }', - }, - { - code: '\na:hover { }', - }, - { - code: '\r\na:hover { }', - }, - { - code: '\n\na:hover { }', - }, - { - code: '\r\n\r\na:hover { }', - }, - { - code: '\n\n\na:hover { }', - }, - { - code: '\r\n\r\n\r\na:hover { }', - }, - { - code: 'a\n:hover { }', - }, - { - code: 'a\r\n:hover { }', - }, - { - code: 'a:\nhover { }', - }, - { - code: 'a:\r\nhover { }', - }, - { - code: 'a:hover\n{ }', - }, - { - code: 'a:hover\r\n{ }', - }, - { - code: 'a:hover\n\n{ }', - }, - { - code: 'a:hover\r\n\r\n{ }', - }, - { - code: 'a:hover\n\n\n{ }', - }, - { - code: 'a:hover\r\n\r\n\r\n{ }', - }, - { - code: '\na::before { }', - }, - { - code: '\r\na::before { }', - }, - { - code: '\n\na::before { }', - }, - { - code: '\r\n\r\na::before { }', - }, - { - code: '\n\n\na::before { }', - }, - { - code: '\r\n\r\n\r\na::before { }', - }, - { - code: 'a\n::before { }', - }, - { - code: 'a\r\n::before { }', - }, - { - code: 'a::\nbefore { }', - }, - { - code: 'a::\r\nbefore { }', - }, - { - code: 'a::before\n{ }', - }, - { - code: 'a::before\r\n{ }', - }, - { - code: 'a::before\n\n{ }', - }, - { - code: 'a::before\r\n\r\n{ }', - }, - { - code: 'a::before\n\n\n{ }', - }, - { - code: 'a::before\r\n\r\n\r\n{ }', - }, - { - 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', - }, - { - code: '/*comment*/\n.foo{ }', - }, - { - code: '/*comment*/\r\n.foo{ }', - }, - { - code: '.foo \n/*comment*/\n .bar { }', - }, - { - code: '.foo \r\n/*comment*/\n\r .bar { }', - }, - ], - - reject: [ - { - code: '.foo\n\n.bar { }', - fixed: '.foo\n.bar { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\r\n\r\n.bar { }', - fixed: '.foo\r\n.bar { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo,\n\n.bar { }', - fixed: '.foo,\n.bar { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo,\r\n\r\n.bar { }', - fixed: '.foo,\r\n.bar { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\n\n,.bar { }', - fixed: '.foo\n,.bar { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\r\n\r\n,.bar { }', - fixed: '.foo\r\n,.bar { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo, .bar,\n\n.other { }', - fixed: '.foo, .bar,\n.other { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo, .bar,\r\n\r\n.other { }', - fixed: '.foo, .bar,\r\n.other { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo,\n.bar,\n\n.other { }', - fixed: '.foo,\n.bar,\n.other { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo,\r\n.bar,\r\n\r\n.other { }', - fixed: '.foo,\r\n.bar,\r\n.other { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo,\n.bar,\n\n.other\n{ }', - fixed: '.foo,\n.bar,\n.other\n{ }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo,\r\n.bar,\r\n\r\n.other\r\n{ }', - fixed: '.foo,\r\n.bar,\r\n.other\r\n{ }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo,\n.bar,\n\n.other\n\n{ }', - fixed: '.foo,\n.bar,\n.other\n\n{ }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo,\r\n.bar,\r\n\r\n.other\r\n\r\n{ }', - fixed: '.foo,\r\n.bar,\r\n.other\r\n\r\n{ }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '\n.foo,\n.bar,\n\n.other\n\n{ }', - fixed: '\n.foo,\n.bar,\n.other\n\n{ }', - message: messages.expected(0), - line: 2, - column: 1, - }, - { - code: '\r\n.foo,\r\n.bar,\r\n\r\n.other\r\n\r\n{ }', - fixed: '\r\n.foo,\r\n.bar,\r\n.other\r\n\r\n{ }', - message: messages.expected(0), - line: 2, - column: 1, - }, - { - code: '\n\n.foo,\n.bar,\n\n.other\n\n{ }', - fixed: '\n\n.foo,\n.bar,\n.other\n\n{ }', - message: messages.expected(0), - line: 3, - column: 1, - }, - { - code: '\r\n\r\n.foo,\r\n.bar,\r\n\r\n.other\r\n\r\n{ }', - fixed: '\r\n\r\n.foo,\r\n.bar,\r\n.other\r\n\r\n{ }', - message: messages.expected(0), - line: 3, - column: 1, - }, - { - code: '.foo\n\n.bar { }', - fixed: '.foo\n.bar { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\r\n\r\n.bar { }', - fixed: '.foo\r\n.bar { }', - message: messages.expected(0), - }, - { - code: '.foo .bar\n\n.other { }', - fixed: '.foo .bar\n.other { }', - message: messages.expected(0), - }, - { - code: '.foo .bar\r\n\r\n.other { }', - fixed: '.foo .bar\r\n.other { }', - message: messages.expected(0), - }, - { - code: '.foo\n.bar\n\n.other { }', - fixed: '.foo\n.bar\n.other { }', - message: messages.expected(0), - }, - { - code: '.foo\r\n.bar\r\n\r\n.other { }', - fixed: '.foo\r\n.bar\r\n.other { }', - message: messages.expected(0), - }, - { - code: '.foo\n.bar\n\n.other\n{ }', - fixed: '.foo\n.bar\n.other\n{ }', - message: messages.expected(0), - }, - { - code: '.foo\r\n.bar\r\n\r\n.other\r\n{ }', - fixed: '.foo\r\n.bar\r\n.other\r\n{ }', - message: messages.expected(0), - }, - { - code: '.foo\n.bar\n\n.other\n\n{ }', - fixed: '.foo\n.bar\n.other\n\n{ }', - message: messages.expected(0), - }, - { - code: '.foo\r\n.bar\r\n\r\n.other\r\n\r\n{ }', - fixed: '.foo\r\n.bar\r\n.other\r\n\r\n{ }', - message: messages.expected(0), - }, - { - code: '\n.foo\n.bar\n\n.other\n\n{ }', - fixed: '\n.foo\n.bar\n.other\n\n{ }', - message: messages.expected(0), - }, - { - code: '\r\n.foo\r\n.bar\r\n\r\n.other\r\n\r\n{ }', - fixed: '\r\n.foo\r\n.bar\r\n.other\r\n\r\n{ }', - message: messages.expected(0), - }, - { - code: '\n\n.foo\n.bar\n\n.other\n\n{ }', - fixed: '\n\n.foo\n.bar\n.other\n\n{ }', - message: messages.expected(0), - }, - { - code: '\r\n\r\n.foo\r\n.bar\r\n\r\n.other\r\n\r\n{ }', - fixed: '\r\n\r\n.foo\r\n.bar\r\n.other\r\n\r\n{ }', - message: messages.expected(0), - }, - { - code: '.foo >\n\n.bar { }', - fixed: '.foo >\n.bar { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo >\r\n\r\n.bar { }', - fixed: '.foo >\r\n.bar { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\n\n>.bar { }', - fixed: '.foo\n>.bar { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\r\n\r\n> .bar { }', - fixed: '.foo\r\n> .bar { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo .bar >\n\n.other { }', - fixed: '.foo .bar >\n.other { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo .bar >\r\n\r\n .other { }', - fixed: '.foo .bar >\r\n .other { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo .bar\n\n> .other { }', - fixed: '.foo .bar\n> .other { }', - message: messages.expected(0), - }, - { - code: '.foo .bar\r\n\r\n> .other { }', - fixed: '.foo .bar\r\n> .other { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\n.bar >\n\n.other { }', - fixed: '.foo\n.bar >\n.other { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\r\n.bar >\r\n\r\n.other { }', - fixed: '.foo\r\n.bar >\r\n.other { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\n.bar\n\n> .other { }', - fixed: '.foo\n.bar\n> .other { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\r\n.bar\r\n\r\n> .other { }', - fixed: '.foo\r\n.bar\r\n> .other { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\n.bar >\n\n.other\n{ }', - fixed: '.foo\n.bar >\n.other\n{ }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\r\n.bar >\r\n\r\n.other\r\n{ }', - fixed: '.foo\r\n.bar >\r\n.other\r\n{ }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\n.bar\n\n> .other\n{ }', - fixed: '.foo\n.bar\n> .other\n{ }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\r\n.bar\r\n\r\n > .other\r\n{ }', - fixed: '.foo\r\n.bar\r\n > .other\r\n{ }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\n.bar >\n\n.other\n\n{ }', - fixed: '.foo\n.bar >\n.other\n\n{ }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\r\n.bar >\r\n\r\n.other\r\n\r\n{ }', - fixed: '.foo\r\n.bar >\r\n.other\r\n\r\n{ }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\n.bar\n\n> .other\n\n{ }', - fixed: '.foo\n.bar\n> .other\n\n{ }', - message: messages.expected(0), - }, - { - code: '.foo\r\n.bar\r\n\r\n> .other\r\n\r\n{ }', - fixed: '.foo\r\n.bar\r\n> .other\r\n\r\n{ }', - message: messages.expected(0), - }, - { - code: '\n.foo\n.bar >\n\n.other\n\n{ }', - fixed: '\n.foo\n.bar >\n.other\n\n{ }', - message: messages.expected(0), - }, - { - code: '\r\n.foo\r\n.bar >\r\n\r\n.other\r\n\r\n{ }', - fixed: '\r\n.foo\r\n.bar >\r\n.other\r\n\r\n{ }', - message: messages.expected(0), - line: 2, - column: 1, - }, - { - code: '\n.foo\n.bar\n\n> .other\n\n{ }', - fixed: '\n.foo\n.bar\n> .other\n\n{ }', - message: messages.expected(0), - line: 2, - column: 1, - }, - { - code: '\r\n.foo\r\n.bar\r\n\r\n> .other\r\n\r\n{ }', - fixed: '\r\n.foo\r\n.bar\r\n> .other\r\n\r\n{ }', - message: messages.expected(0), - line: 2, - column: 1, - }, - { - code: '\n\n.foo\n.bar >\n\n.other\n\n{ }', - fixed: '\n\n.foo\n.bar >\n.other\n\n{ }', - message: messages.expected(0), - line: 3, - column: 1, - }, - { - code: '\r\n\r\n.foo\r\n.bar >\r\n\r\n.other\r\n\r\n{ }', - fixed: '\r\n\r\n.foo\r\n.bar >\r\n.other\r\n\r\n{ }', - message: messages.expected(0), - line: 3, - column: 1, - }, - { - code: '\n\n.foo\n.bar\n\n >.other\n\n{ }', - fixed: '\n\n.foo\n.bar\n >.other\n\n{ }', - message: messages.expected(0), - }, - { - code: '\r\n\r\n.foo\r\n.bar\r\n\r\n> .other\r\n\r\n{ }', - fixed: '\r\n\r\n.foo\r\n.bar\r\n> .other\r\n\r\n{ }', - message: messages.expected(0), - }, - { - code: 'a[\n\nitemprop=url] { }', - fixed: 'a[\nitemprop=url] { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: 'a[\r\n\r\nitemprop=url] { }', - fixed: 'a[\r\nitemprop=url] { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: 'a[itemprop\n\n=url] { }', - fixed: 'a[itemprop\n=url] { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: 'a[itemprop\r\n\r\n=url] { }', - fixed: 'a[itemprop\r\n=url] { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: 'a[itemprop=\n\nurl] { }', - fixed: 'a[itemprop=\nurl] { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: 'a[itemprop=\r\n\r\nurl] { }', - fixed: 'a[itemprop=\r\nurl] { }', - message: messages.expected(0), - }, - { - code: 'a[itemprop=url\n\n] { }', - fixed: 'a[itemprop=url\n] { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: 'a[itemprop=url\r\n\r\n] { }', - fixed: 'a[itemprop=url\r\n] { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: 'a\n\n:hover { }', - fixed: 'a\n:hover { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: 'a\r\n\r\n:hover { }', - fixed: 'a\r\n:hover { }', - message: messages.expected(0), - }, - { - code: 'a:\n\nhover { }', - fixed: 'a:\nhover { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: 'a:\r\n\r\nhover { }', - fixed: 'a:\r\nhover { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: 'a\n\n::before { }', - fixed: 'a\n::before { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: 'a\r\n\r\n::before { }', - fixed: 'a\r\n::before { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: 'a { }\na::\n\nbefore { }', - fixed: 'a { }\na::\nbefore { }', - message: messages.expected(0), - line: 2, - column: 1, - }, - { - code: 'a::\r\n\r\nbefore { }', - fixed: 'a::\r\nbefore { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\n\n/*comment*/ .bar { }', - fixed: '.foo\n/*comment*/ .bar { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\n/*comment*/\n\n.bar { }', - fixed: '.foo\n/*comment*/\n.bar { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\r\n\r\n/*comment*/ .bar { }', - fixed: '.foo\r\n/*comment*/ .bar { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - { - code: '.foo\r\n/*comment*/\r\n\r\n.bar { }', - fixed: '.foo\r\n/*comment*/\r\n.bar { }', - message: messages.expected(0), - line: 1, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: [1], - fix: true, - - accept: [ - { - code: '\n.foo { }', - }, - { - code: '\r\n.foo { }', - }, - { - code: '\n\n.foo { }', - }, - { - code: '\r\n\r\n.foo { }', - }, - { - code: '\n\n\n.foo { }', - }, - { - code: '\r\n\r\n\r\n.foo { }', - }, - { - code: '.foo\n{ }', - }, - { - code: '.foo\r\n{ }', - }, - { - code: '.foo\n\n{ }', - }, - { - code: '.foo\r\n\r\n{ }', - }, - { - code: '.foo\n\n\n{ }', - }, - { - code: '.foo\r\n\r\n\r\n{ }', - }, - { - code: '.foo\n\n\n{ }', - }, - { - code: '.foo\r\n\r\n\r\n{ }', - }, - { - code: '.foo {\n}', - }, - { - code: '.foo {\r\n}', - }, - { - code: '.foo {\n\n}', - }, - { - code: '.foo {\r\n\r\n}', - }, - { - code: '.foo {\n\n\n}', - }, - { - code: '.foo {\r\n\r\n\r\n}', - }, - { - code: '.foo {\n\n\n}', - }, - { - code: '.foo {\r\n\r\n\r\n}', - }, - { - code: '.foo { }\n', - }, - { - code: '.foo { }\r\n', - }, - { - code: '.foo { }\n\n', - }, - { - code: '.foo { }\r\n\r\n', - }, - { - code: '.foo { }\n\n\n', - }, - { - code: '.foo { }\r\n\r\n\r\n', - }, - { - code: '.foo { }\n\n\n', - }, - { - code: '.foo { }\r\n\r\n\r\n', - }, - { - code: '\n.foo, .bar { }', - }, - { - code: '\r\n.foo, .bar { }', - }, - { - code: '\n\n.foo, .bar { }', - }, - { - code: '\r\n\r\n.foo, .bar { }', - }, - { - code: '\n\n\n.foo, .bar { }', - }, - { - code: '\r\n\r\n\r\n.foo, .bar { }', - }, - { - code: '.foo, .bar { }', - }, - { - code: '.foo,\n.bar { }', - }, - { - code: '.foo,\r\n.bar { }', - }, - { - code: '.foo,\n\n.bar { }', - }, - { - code: '.foo,\r\n\r\n.bar { }', - }, - { - code: '.foo, .bar\n{ }', - }, - { - code: '.foo, .bar\r\n{ }', - }, - { - code: '.foo, .bar\n\n{ }', - }, - { - code: '.foo, .bar\r\n\r\n{ }', - }, - { - code: '.foo, .bar\n\n\n{ }', - }, - { - code: '.foo, .bar\r\n\r\n\r\n{ }', - }, - { - code: '.foo, .bar {\n}', - }, - { - code: '.foo, .bar {\r\n}', - }, - { - code: '.foo, .bar {\n\n}', - }, - { - code: '.foo, .bar {\r\n\r\n}', - }, - { - code: '.foo, .bar {\n\n\n}', - }, - { - code: '.foo, .bar {\r\n\r\n\r\n}', - }, - { - code: '.foo, .bar { }\n', - }, - { - code: '.foo, .bar { }\r\n', - }, - { - code: '.foo, .bar { }\n\n', - }, - { - code: '.foo, .bar { }\r\n\r\n', - }, - { - code: '.foo, .bar { }\n\n\n', - }, - { - code: '.foo, .bar { }\r\n\r\n\r\n', - }, - { - code: '.foo .bar { }', - }, - { - code: '.foo\n.bar { }', - }, - { - code: '.foo\r\n.bar { }', - }, - { - code: '.foo\n\n.bar { }', - }, - { - code: '.foo\r\n\r\n.bar { }', - }, - { - code: '\n.foo .bar { }', - }, - { - code: '\r\n.foo .bar { }', - }, - { - code: '\n\n.foo .bar { }', - }, - { - code: '\r\n\r\n.foo .bar { }', - }, - { - code: '\n\n\n.foo .bar { }', - }, - { - code: '\r\n\r\n\r\n.foo .bar { }', - }, - { - code: '.foo .bar\n{ }', - }, - { - code: '.foo .bar\r\n{ }', - }, - { - code: '.foo .bar\n\n{ }', - }, - { - code: '.foo .bar\r\n\r\n{ }', - }, - { - code: '.foo .bar\n\n\n{ }', - }, - { - code: '.foo .bar\r\n\r\n\r\n{ }', - }, - { - code: '.foo .bar {\n}', - }, - { - code: '.foo .bar {\r\n}', - }, - { - code: '.foo .bar {\n\n}', - }, - { - code: '.foo .bar {\r\n\r\n}', - }, - { - code: '.foo .bar {\n\n\n}', - }, - { - code: '.foo .bar {\r\n\r\n\r\n}', - }, - { - code: '.foo .bar { }\n', - }, - { - code: '.foo .bar { }\r\n', - }, - { - code: '.foo .bar { }\n\n', - }, - { - code: '.foo .bar { }\r\n\r\n', - }, - { - code: '.foo .bar { }\n\n\n', - }, - { - code: '.foo .bar { }\r\n\r\n\r\n', - }, - { - code: '.foo > .bar { }', - }, - { - code: '\n.foo > .bar { }', - }, - { - code: '\r\n.foo > .bar { }', - }, - { - code: '\n\n.foo > .bar { }', - }, - { - code: '\r\n\r\n.foo > .bar { }', - }, - { - code: '\n\n\n.foo > .bar { }', - }, - { - code: '\r\n\r\n\r\n.foo > .bar { }', - }, - { - code: '.foo\n> .bar { }', - }, - { - code: '.foo\r\n> .bar { }', - }, - { - code: '.foo\n\n> .bar { }', - }, - { - code: '.foo\r\n\r\n> .bar { }', - }, - { - code: '.foo >\n.bar { }', - }, - { - code: '.foo >\r\n.bar { }', - }, - { - code: '.foo >\n\n.bar { }', - }, - { - code: '.foo >\r\n\r\n.bar { }', - }, - { - code: '.foo > .bar\n{ }', - }, - { - code: '.foo > .bar\r\n{ }', - }, - { - code: '.foo > .bar\n\n{ }', - }, - { - code: '.foo > .bar\r\n\r\n{ }', - }, - { - code: '.foo > .bar\n\n\n{ }', - }, - { - code: '.foo > .bar\r\n\r\n\r\n{ }', - }, - { - code: '.foo > .bar {\n}', - }, - { - code: '.foo > .bar {\r\n}', - }, - { - code: '.foo > .bar {\n\n}', - }, - { - code: '.foo > .bar {\r\n\r\n}', - }, - { - code: '.foo > .bar {\n\n\n}', - }, - { - code: '.foo > .bar {\r\n\r\n\r\n}', - }, - { - code: '.foo > .bar { }\n', - }, - { - code: '.foo > .bar { }\r\n', - }, - { - code: '.foo > .bar { }\n\n', - }, - { - code: '.foo > .bar { }\r\n\r\n', - }, - { - code: '.foo > .bar { }\n\n\n', - }, - { - code: '.foo > .bar { }\r\n\r\n\r\n', - }, - { - code: '\na[itemprop=url] { }', - }, - { - code: '\r\na[itemprop=url] { }', - }, - { - code: '\n\na[itemprop=url] { }', - }, - { - code: '\r\n\r\na[itemprop=url] { }', - }, - { - code: '\n\n\na[itemprop=url] { }', - }, - { - code: '\r\n\r\n\r\na[itemprop=url] { }', - }, - { - code: 'a\n[itemprop=url] { }', - }, - { - code: 'a\r\n[itemprop=url] { }', - }, - { - code: 'a\n\n[itemprop=url] { }', - }, - { - code: 'a\r\n\r\n[itemprop=url] { }', - }, - { - code: 'a[\nitemprop=url] { }', - }, - { - code: 'a[\r\nitemprop=url] { }', - }, - { - code: 'a[\n\nitemprop=url] { }', - }, - { - code: 'a[\r\n\r\nitemprop=url] { }', - }, - { - code: 'a[itemprop\n=url] { }', - }, - { - code: 'a[itemprop\r\n=url] { }', - }, - { - code: 'a[itemprop\n\n=url] { }', - }, - { - code: 'a[itemprop\r\n\r\n=url] { }', - }, - { - code: 'a[itemprop=\nurl] { }', - }, - { - code: 'a[itemprop=\r\nurl] { }', - }, - { - code: 'a[itemprop=\n\nurl] { }', - }, - { - code: 'a[itemprop=\r\n\r\nurl] { }', - }, - { - code: 'a[itemprop=url\n] { }', - }, - { - code: 'a[itemprop=url\r\n] { }', - }, - { - code: 'a[itemprop=url\n\n] { }', - }, - { - code: 'a[itemprop=url\r\n\r\n] { }', - }, - { - code: 'a[itemprop=url]\n{ }', - }, - { - code: 'a[itemprop=url]\r\n{ }', - }, - { - code: 'a[itemprop=url]\n\n{ }', - }, - { - code: 'a[itemprop=url]\r\n\r\n{ }', - }, - { - code: 'a[itemprop=url]\n\n\n{ }', - }, - { - code: 'a[itemprop=url]\r\n\r\n\r\n{ }', - }, - { - code: '\na:hover { }', - }, - { - code: '\r\na:hover { }', - }, - { - code: '\n\na:hover { }', - }, - { - code: '\r\n\r\na:hover { }', - }, - { - code: '\n\n\na:hover { }', - }, - { - code: '\r\n\r\n\r\na:hover { }', - }, - { - code: 'a\n:hover { }', - }, - { - code: 'a\r\n:hover { }', - }, - { - code: 'a\n\n:hover { }', - }, - { - code: 'a\r\n\r\n:hover { }', - }, - { - code: 'a:\nhover { }', - }, - { - code: 'a:\r\nhover { }', - }, - { - code: 'a:\n\nhover { }', - }, - { - code: 'a:\r\n\r\nhover { }', - }, - { - code: 'a:hover\n{ }', - }, - { - code: 'a:hover\r\n{ }', - }, - { - code: 'a:hover\n\n{ }', - }, - { - code: 'a:hover\r\n\r\n{ }', - }, - { - code: 'a:hover\n\n\n{ }', - }, - { - code: 'a:hover\r\n\r\n\r\n{ }', - }, - { - code: '\na::before { }', - }, - { - code: '\r\na::before { }', - }, - { - code: '\n\na::before { }', - }, - { - code: '\r\n\r\na::before { }', - }, - { - code: '\n\n\na::before { }', - }, - { - code: '\r\n\r\n\r\na::before { }', - }, - { - code: 'a\n::before { }', - }, - { - code: 'a\r\n::before { }', - }, - { - code: 'a\n\n::before { }', - }, - { - code: 'a\r\n\r\n::before { }', - }, - { - code: 'a::\nbefore { }', - }, - { - code: 'a::\r\nbefore { }', - }, - { - code: 'a::\n\nbefore { }', - }, - { - code: 'a::\r\n\r\nbefore { }', - }, - { - code: 'a::before\n{ }', - }, - { - code: 'a::before\r\n{ }', - }, - { - code: 'a::before\n\n{ }', - }, - { - code: 'a::before\r\n\r\n{ }', - }, - { - code: 'a::before\n\n\n{ }', - }, - { - code: 'a::before\r\n\r\n\r\n{ }', - }, - { - code: '\n/*comment*/\n.foo { }', - }, - { - code: '\n\n/*comment*/\n\n.foo { }', - }, - { - code: '\n\n\n/*comment*/\n\n\n.foo { }', - }, - { - code: '\r\n/*comment*/\r\n.foo { }', - }, - { - code: '\r\n\r\n/*comment*/\r\n\r\n.foo { }', - }, - { - code: '\r\n\r\n\r\n/*comment*/\r\n\r\n\r\n.foo { }', - }, - { - code: '.foo\n/*comment*/\n{ }', - }, - { - code: '.foo\n\n/*comment*/\n\n{ }', - }, - { - code: '.foo\n\n\n/*comment*/\n\n\n{ }', - }, - { - code: '.foo\r\n/*comment*/\r\n{ }', - }, - { - code: '.foo\r\n\r\n/*comment*/\r\n\r\n{ }', - }, - { - code: '.foo\r\n\r\n\r\n/*comment*/\r\n\r\n\r\n{ }', - }, - { - code: '.foo\n/*comment*/\n.bar{ }', - }, - { - code: '.foo\n\n/*comment*/\n\n.bar{ }', - }, - { - code: '.foo\r\n/*comment*/\r\n.bar{ }', - }, - { - code: '.foo\r\n\r\n/*comment*/\r\n\r\n.bar{ }', - }, - ], - - reject: [ - { - code: '.foo\n\n\n.bar { }', - fixed: '.foo\n\n.bar { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\r\n\r\n\r\n.bar { }', - fixed: '.foo\r\n\r\n.bar { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo,\n\n\n.bar { }', - fixed: '.foo,\n\n.bar { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo,\r\n\r\n\r\n.bar { }', - fixed: '.foo,\r\n\r\n.bar { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo, .bar,\n\n\n.other { }', - fixed: '.foo, .bar,\n\n.other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo, .bar,\r\n\r\n\r\n.other { }', - fixed: '.foo, .bar,\r\n\r\n.other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo,\n.bar,\n\n\n.other { }', - fixed: '.foo,\n.bar,\n\n.other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo,\r\n.bar,\r\n\r\n\r\n.other { }', - fixed: '.foo,\r\n.bar,\r\n\r\n.other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo,\n\n.bar,\n\n\n.other { }', - fixed: '.foo,\n\n.bar,\n\n.other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo,\r\n\r\n.bar,\r\n\r\n\r\n.other { }', - fixed: '.foo,\r\n\r\n.bar,\r\n\r\n.other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo,\n.bar,\n\n\n.other\n{ }', - fixed: '.foo,\n.bar,\n\n.other\n{ }', - message: messages.expected(1), - }, - { - code: '.foo,\r\n.bar,\r\n\r\n\r\n.other\r\n{ }', - fixed: '.foo,\r\n.bar,\r\n\r\n.other\r\n{ }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo,\n\n.bar,\n\n\n.other\n{ }', - fixed: '.foo,\n\n.bar,\n\n.other\n{ }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo,\r\n\r\n.bar,\r\n\r\n\r\n.other\r\n{ }', - fixed: '.foo,\r\n\r\n.bar,\r\n\r\n.other\r\n{ }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo,\n.bar,\n\n\n.other\n\n{ }', - fixed: '.foo,\n.bar,\n\n.other\n\n{ }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo,\r\n.bar,\r\n\r\n\r\n.other\r\n\r\n{ }', - fixed: '.foo,\r\n.bar,\r\n\r\n.other\r\n\r\n{ }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo,\n\n.bar,\n\n\n.other\n\n\n{ }', - fixed: '.foo,\n\n.bar,\n\n.other\n\n\n{ }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo,\r\n\r\n.bar,\r\n\r\n\r\n.other\r\n\r\n\r\n{ }', - fixed: '.foo,\r\n\r\n.bar,\r\n\r\n.other\r\n\r\n\r\n{ }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '\n.foo,\n.bar,\n\n\n.other\n\n{ }', - fixed: '\n.foo,\n.bar,\n\n.other\n\n{ }', - message: messages.expected(1), - }, - { - code: '\r\n.foo,\r\n.bar,\r\n\r\n\r\n.other\r\n\r\n{ }', - fixed: '\r\n.foo,\r\n.bar,\r\n\r\n.other\r\n\r\n{ }', - message: messages.expected(1), - line: 2, - column: 1, - }, - { - code: '\n\n.foo,\n\n.bar,\n\n\n.other\n\n\n{ }', - fixed: '\n\n.foo,\n\n.bar,\n\n.other\n\n\n{ }', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: '\r\n\r\n.foo,\r\n\r\n.bar,\r\n\r\n\r\n.other\r\n\r\n\r\n{ }', - fixed: '\r\n\r\n.foo,\r\n\r\n.bar,\r\n\r\n.other\r\n\r\n\r\n{ }', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: '\n\n.foo,\n.bar,\n\n\n.other\n\n{ }', - fixed: '\n\n.foo,\n.bar,\n\n.other\n\n{ }', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: '\r\n\r\n.foo,\r\n.bar,\r\n\r\n\r\n.other\r\n\r\n{ }', - fixed: '\r\n\r\n.foo,\r\n.bar,\r\n\r\n.other\r\n\r\n{ }', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: '\n\n\n.foo,\n\n.bar,\n\n\n.other\n\n\n{ }', - fixed: '\n\n\n.foo,\n\n.bar,\n\n.other\n\n\n{ }', - message: messages.expected(1), - line: 4, - column: 1, - }, - { - code: '\r\n\r\n\r\n.foo,\r\n\r\n.bar,\r\n\r\n\r\n.other\r\n\r\n\r\n{ }', - fixed: '\r\n\r\n\r\n.foo,\r\n\r\n.bar,\r\n\r\n.other\r\n\r\n\r\n{ }', - message: messages.expected(1), - line: 4, - column: 1, - }, - { - code: '.foo .bar\n\n\n.other { }', - fixed: '.foo .bar\n\n.other { }', - message: messages.expected(1), - }, - { - code: '.foo .bar\r\n\r\n\r\n.other { }', - fixed: '.foo .bar\r\n\r\n.other { }', - message: messages.expected(1), - }, - { - code: '.foo\n.bar\n\n\n.other { }', - fixed: '.foo\n.bar\n\n.other { }', - message: messages.expected(1), - }, - { - code: '.foo\r\n.bar\r\n\r\n\r\n.other { }', - fixed: '.foo\r\n.bar\r\n\r\n.other { }', - message: messages.expected(1), - }, - { - code: '.foo\n\n.bar\n\n\n.other { }', - fixed: '.foo\n\n.bar\n\n.other { }', - message: messages.expected(1), - }, - { - code: '.foo\r\n\r\n.bar\r\n\r\n\r\n.other { }', - fixed: '.foo\r\n\r\n.bar\r\n\r\n.other { }', - message: messages.expected(1), - }, - { - code: '.foo\n.bar\n\n\n.other\n{ }', - fixed: '.foo\n.bar\n\n.other\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\r\n.bar\r\n\r\n\r\n.other\r\n{ }', - fixed: '.foo\r\n.bar\r\n\r\n.other\r\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\n\n.bar\n\n\n.other\n\n{ }', - fixed: '.foo\n\n.bar\n\n.other\n\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\r\n\r\n.bar\r\n\r\n\r\n.other\r\n\r\n{ }', - fixed: '.foo\r\n\r\n.bar\r\n\r\n.other\r\n\r\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\n.bar\n\n\n.other\n\n{ }', - fixed: '.foo\n.bar\n\n.other\n\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\r\n.bar\r\n\r\n\r\n.other\r\n\r\n{ }', - fixed: '.foo\r\n.bar\r\n\r\n.other\r\n\r\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\n\n.bar\n\n\n.other\n\n\n{ }', - fixed: '.foo\n\n.bar\n\n.other\n\n\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\r\n\r\n.bar\r\n\r\n\r\n.other\r\n\r\n\r\n{ }', - fixed: '.foo\r\n\r\n.bar\r\n\r\n.other\r\n\r\n\r\n{ }', - message: messages.expected(1), - }, - { - code: '\n.foo\n.bar\n\n\n.other\n\n{ }', - fixed: '\n.foo\n.bar\n\n.other\n\n{ }', - message: messages.expected(1), - }, - { - code: '\r\n.foo\r\n.bar\r\n\r\n\r\n.other\r\n\r\n{ }', - fixed: '\r\n.foo\r\n.bar\r\n\r\n.other\r\n\r\n{ }', - message: messages.expected(1), - }, - { - code: '\n\n.foo\n\n.bar\n\n\n.other\n\n\n{ }', - fixed: '\n\n.foo\n\n.bar\n\n.other\n\n\n{ }', - message: messages.expected(1), - }, - { - code: '\r\n\r\n.foo\r\n\r\n.bar\r\n\r\n\r\n.other\r\n\r\n\r\n{ }', - fixed: '\r\n\r\n.foo\r\n\r\n.bar\r\n\r\n.other\r\n\r\n\r\n{ }', - message: messages.expected(1), - }, - { - code: '\n\n.foo\n.bar\n\n\n.other\n\n{ }', - fixed: '\n\n.foo\n.bar\n\n.other\n\n{ }', - message: messages.expected(1), - }, - { - code: '\r\n\r\n.foo\r\n.bar\r\n\r\n\r\n.other\r\n\r\n{ }', - fixed: '\r\n\r\n.foo\r\n.bar\r\n\r\n.other\r\n\r\n{ }', - message: messages.expected(1), - }, - { - code: '\n\n\n.foo\n\n.bar\n\n\n.other\n\n\n{ }', - fixed: '\n\n\n.foo\n\n.bar\n\n.other\n\n\n{ }', - message: messages.expected(1), - }, - { - code: '\r\n\r\n\r\n.foo\r\n\r\n.bar\r\n\r\n\r\n.other\r\n\r\n\r\n{ }', - fixed: '\r\n\r\n\r\n.foo\r\n\r\n.bar\r\n\r\n.other\r\n\r\n\r\n{ }', - message: messages.expected(1), - }, - { - code: '.foo >\n\n\n.bar { }', - fixed: '.foo >\n\n.bar { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo >\r\n\r\n\r\n.bar { }', - fixed: '.foo >\r\n\r\n.bar { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\n\n\n>.bar { }', - fixed: '.foo\n\n>.bar { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\r\n\r\n\r\n> .bar { }', - fixed: '.foo\r\n\r\n> .bar { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo .bar >\n\n\n.other { }', - fixed: '.foo .bar >\n\n.other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo .bar >\r\n\r\n\r\n .other { }', - fixed: '.foo .bar >\r\n\r\n .other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo .bar\n\n\n> .other { }', - fixed: '.foo .bar\n\n> .other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo .bar\r\n\r\n\r\n> .other { }', - fixed: '.foo .bar\r\n\r\n> .other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\n.bar >\n\n\n.other { }', - fixed: '.foo\n.bar >\n\n.other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\r\n.bar >\r\n\r\n\r\n.other { }', - fixed: '.foo\r\n.bar >\r\n\r\n.other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\n\n.bar >\n\n\n.other { }', - fixed: '.foo\n\n.bar >\n\n.other { }', - message: messages.expected(1), - }, - { - code: '.foo\r\n\r\n.bar >\r\n\r\n\r\n.other { }', - fixed: '.foo\r\n\r\n.bar >\r\n\r\n.other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\n.bar\n\n\n> .other { }', - fixed: '.foo\n.bar\n\n> .other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\r\n.bar\r\n\r\n\r\n> .other { }', - fixed: '.foo\r\n.bar\r\n\r\n> .other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\n\n.bar\n\n\n> .other { }', - fixed: '.foo\n\n.bar\n\n> .other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\r\n\r\n.bar\r\n\r\n\r\n> .other { }', - fixed: '.foo\r\n\r\n.bar\r\n\r\n> .other { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\n.bar >\n\n\n.other\n{ }', - fixed: '.foo\n.bar >\n\n.other\n{ }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\r\n.bar >\r\n\r\n\r\n.other\r\n{ }', - fixed: '.foo\r\n.bar >\r\n\r\n.other\r\n{ }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\n\n.bar >\n\n\n.other\n\n{ }', - fixed: '.foo\n\n.bar >\n\n.other\n\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\r\n\r\n.bar >\r\n\r\n\r\n.other\r\n\r\n{ }', - fixed: '.foo\r\n\r\n.bar >\r\n\r\n.other\r\n\r\n{ }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\n.bar\n\n\n> .other\n{ }', - fixed: '.foo\n.bar\n\n> .other\n{ }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\r\n.bar\r\n\r\n\r\n > .other\r\n{ }', - fixed: '.foo\r\n.bar\r\n\r\n > .other\r\n{ }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\n\n.bar\n\n\n> .other\n\n{ }', - fixed: '.foo\n\n.bar\n\n> .other\n\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\r\n\r\n.bar\r\n\r\n\r\n > .other\r\n\r\n{ }', - fixed: '.foo\r\n\r\n.bar\r\n\r\n > .other\r\n\r\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\n.bar >\n\n\n.other\n\n{ }', - fixed: '.foo\n.bar >\n\n.other\n\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\r\n.bar >\r\n\r\n\r\n.other\r\n\r\n{ }', - fixed: '.foo\r\n.bar >\r\n\r\n.other\r\n\r\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\n\n.bar >\n\n\n.other\n\n\n{ }', - fixed: '.foo\n\n.bar >\n\n.other\n\n\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\r\n\r\n.bar >\r\n\r\n\r\n.other\r\n\r\n\r\n{ }', - fixed: '.foo\r\n\r\n.bar >\r\n\r\n.other\r\n\r\n\r\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\n.bar\n\n\n> .other\n\n{ }', - fixed: '.foo\n.bar\n\n> .other\n\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\r\n.bar\r\n\r\n\r\n> .other\r\n\r\n{ }', - fixed: '.foo\r\n.bar\r\n\r\n> .other\r\n\r\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\n\n.bar\n\n\n> .other\n\n\n{ }', - fixed: '.foo\n\n.bar\n\n> .other\n\n\n{ }', - message: messages.expected(1), - }, - { - code: '.foo\r\n\r\n.bar\r\n\r\n\r\n> .other\r\n\r\n\r\n{ }', - fixed: '.foo\r\n\r\n.bar\r\n\r\n> .other\r\n\r\n\r\n{ }', - message: messages.expected(1), - }, - { - code: '\n.foo\n.bar >\n\n\n.other\n\n{ }', - fixed: '\n.foo\n.bar >\n\n.other\n\n{ }', - message: messages.expected(1), - }, - { - code: '\r\n.foo\r\n.bar >\r\n\r\n\r\n.other\r\n\r\n{ }', - fixed: '\r\n.foo\r\n.bar >\r\n\r\n.other\r\n\r\n{ }', - message: messages.expected(1), - line: 2, - column: 1, - }, - { - code: '\n\n.foo\n\n.bar >\n\n\n.other\n\n\n{ }', - fixed: '\n\n.foo\n\n.bar >\n\n.other\n\n\n{ }', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: '\r\n\r\n.foo\r\n\r\n.bar >\r\n\r\n\r\n.other\r\n\r\n\r\n{ }', - fixed: '\r\n\r\n.foo\r\n\r\n.bar >\r\n\r\n.other\r\n\r\n\r\n{ }', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: '\n.foo\n.bar\n\n\n> .other\n\n{ }', - fixed: '\n.foo\n.bar\n\n> .other\n\n{ }', - message: messages.expected(1), - }, - { - code: '\r\n.foo\r\n.bar\r\n\r\n\r\n> .other\r\n\r\n{ }', - fixed: '\r\n.foo\r\n.bar\r\n\r\n> .other\r\n\r\n{ }', - message: messages.expected(1), - line: 2, - column: 1, - }, - { - code: '\n\n.foo\n\n.bar\n\n\n> .other\n\n\n{ }', - fixed: '\n\n.foo\n\n.bar\n\n> .other\n\n\n{ }', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: '\r\n\r\n.foo\r\n\r\n.bar\r\n\r\n\r\n> .other\r\n\r\n\r\n{ }', - fixed: '\r\n\r\n.foo\r\n\r\n.bar\r\n\r\n> .other\r\n\r\n\r\n{ }', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: '\n\n.foo\n.bar >\n\n\n.other\n\n{ }', - fixed: '\n\n.foo\n.bar >\n\n.other\n\n{ }', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: '\r\n\r\n.foo\r\n.bar >\r\n\r\n\r\n.other\r\n\r\n{ }', - fixed: '\r\n\r\n.foo\r\n.bar >\r\n\r\n.other\r\n\r\n{ }', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: '\n\n\n.foo\n\n.bar >\n\n\n.other\n\n\n{ }', - fixed: '\n\n\n.foo\n\n.bar >\n\n.other\n\n\n{ }', - message: messages.expected(1), - line: 4, - column: 1, - }, - { - code: '\r\n\r\n\r\n.foo\r\n\r\n.bar >\r\n\r\n\r\n.other\r\n\r\n\r\n{ }', - fixed: '\r\n\r\n\r\n.foo\r\n\r\n.bar >\r\n\r\n.other\r\n\r\n\r\n{ }', - message: messages.expected(1), - line: 4, - column: 1, - }, - { - code: '\n\n.foo\n.bar\n\n\n >.other\n\n{ }', - fixed: '\n\n.foo\n.bar\n\n >.other\n\n{ }', - message: messages.expected(1), - line: 3, - column: 1, - }, - { - code: '\r\n\r\n.foo\r\n.bar\r\n\r\n\r\n> .other\r\n\r\n{ }', - fixed: '\r\n\r\n.foo\r\n.bar\r\n\r\n> .other\r\n\r\n{ }', - message: messages.expected(1), - }, - { - code: '\n\n\n.foo\n\n.bar\n\n\n >.other\n\n\n{ }', - fixed: '\n\n\n.foo\n\n.bar\n\n >.other\n\n\n{ }', - message: messages.expected(1), - }, - { - code: '\r\n\r\n\r\n.foo\r\n\r\n.bar\r\n\r\n\r\n> .other\r\n\r\n\r\n{ }', - fixed: '\r\n\r\n\r\n.foo\r\n\r\n.bar\r\n\r\n> .other\r\n\r\n\r\n{ }', - message: messages.expected(1), - }, - { - code: 'a[\n\n\nitemprop=url] { }', - fixed: 'a[\n\nitemprop=url] { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: 'a[\r\n\r\n\r\nitemprop=url] { }', - fixed: 'a[\r\n\r\nitemprop=url] { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: 'a[itemprop\n\n\n=url] { }', - fixed: 'a[itemprop\n\n=url] { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: 'a[itemprop\r\n\r\n\r\n=url] { }', - fixed: 'a[itemprop\r\n\r\n=url] { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: 'a[itemprop=\n\n\nurl] { }', - fixed: 'a[itemprop=\n\nurl] { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: 'a[itemprop=\r\n\r\n\r\nurl] { }', - fixed: 'a[itemprop=\r\n\r\nurl] { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: 'a[itemprop=url\n\n\n] { }', - fixed: 'a[itemprop=url\n\n] { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: 'a[itemprop=url\r\n\r\n\r\n] { }', - fixed: 'a[itemprop=url\r\n\r\n] { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: 'a\n\n\n:hover { }', - fixed: 'a\n\n:hover { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: 'a\r\n\r\n\r\n:hover { }', - fixed: 'a\r\n\r\n:hover { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: 'a:\n\n\nhover { }', - fixed: 'a:\n\nhover { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: 'a:\r\n\r\n\r\nhover { }', - fixed: 'a:\r\n\r\nhover { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: 'a\n\n\n::before { }', - fixed: 'a\n\n::before { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: 'a\r\n\r\n\r\n::before { }', - fixed: 'a\r\n\r\n::before { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: 'a::\n\n\nbefore { }', - fixed: 'a::\n\nbefore { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: 'a::\r\n\r\n\r\nbefore { }', - fixed: 'a::\r\n\r\nbefore { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\n\n\n/*comment*/.bar { }', - fixed: '.foo\n\n/*comment*/.bar { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - { - code: '.foo\r\n\r\n\r\n/*comment*/.bar { }', - fixed: '.foo\r\n\r\n/*comment*/.bar { }', - message: messages.expected(1), - line: 1, - column: 1, - }, - ], -}); diff --git a/lib/rules/selector-max-empty-lines/index.js b/lib/rules/selector-max-empty-lines/index.js deleted file mode 100644 index efc4ec661c..0000000000 --- a/lib/rules/selector-max-empty-lines/index.js +++ /dev/null @@ -1,71 +0,0 @@ -'use strict'; - -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const { isNumber } = require('../../utils/validateTypes'); - -const ruleName = 'selector-max-empty-lines'; - -const messages = ruleMessages(ruleName, { - expected: (max) => `Expected no more than ${max} empty ${max === 1 ? 'line' : 'lines'}`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/selector-max-empty-lines', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const maxAdjacentNewlines = primary + 1; - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: isNumber, - }); - - if (!validOptions) { - return; - } - - const violatedCRLFNewLinesRegex = new RegExp(`(?:\r\n){${maxAdjacentNewlines + 1},}`); - const violatedLFNewLinesRegex = new RegExp(`\n{${maxAdjacentNewlines + 1},}`); - const allowedLFNewLinesString = context.fix ? '\n'.repeat(maxAdjacentNewlines) : ''; - const allowedCRLFNewLinesString = context.fix ? '\r\n'.repeat(maxAdjacentNewlines) : ''; - - root.walkRules((ruleNode) => { - const selector = ruleNode.raws.selector ? ruleNode.raws.selector.raw : ruleNode.selector; - - if (context.fix) { - const newSelectorString = selector - .replace(new RegExp(violatedLFNewLinesRegex, 'gm'), allowedLFNewLinesString) - .replace(new RegExp(violatedCRLFNewLinesRegex, 'gm'), allowedCRLFNewLinesString); - - if (ruleNode.raws.selector) { - ruleNode.raws.selector.raw = newSelectorString; - } else { - ruleNode.selector = newSelectorString; - } - } else if ( - violatedLFNewLinesRegex.test(selector) || - violatedCRLFNewLinesRegex.test(selector) - ) { - report({ - message: messages.expected(primary), - node: ruleNode, - index: 0, - result, - ruleName, - }); - } - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/selector-pseudo-class-case/README.md b/lib/rules/selector-pseudo-class-case/README.md deleted file mode 100644 index b80b445743..0000000000 --- a/lib/rules/selector-pseudo-class-case/README.md +++ /dev/null @@ -1,110 +0,0 @@ -# selector-pseudo-class-case - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Specify lowercase or uppercase for pseudo-class selectors. - - -```css - a:hover {} -/** ↑ - * This pseudo-class selector */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"lower"|"upper"` - -### `"lower"` - -The following patterns are considered problems: - - -```css -a:Hover {} -``` - - -```css -a:hOvEr {} -``` - - -```css -a:HOVER {} -``` - - -```css -:ROOT {} -``` - - -```css -:-MS-INPUT-PLACEHOLDER {} -``` - -The following patterns are _not_ considered problems: - - -```css -a:hover {} -``` - - -```css -:root {} -``` - - -```css -:-ms-input-placeholder {} -``` - -### `"upper"` - -The following patterns are considered problems: - - -```css -a:Hover {} -``` - - -```css -a:hOvEr {} -``` - - -```css -a:hover {} -``` - - -```css -:root {} -``` - - -```css -:-ms-input-placeholder {} -``` - -The following patterns are _not_ considered problems: - - -```css -a:HOVER {} -``` - - -```css -:ROOT {} -``` - - -```css -:-MS-INPUT-PLACEHOLDER {} -``` diff --git a/lib/rules/selector-pseudo-class-case/__tests__/index.js b/lib/rules/selector-pseudo-class-case/__tests__/index.js deleted file mode 100644 index f8a51eeee6..0000000000 --- a/lib/rules/selector-pseudo-class-case/__tests__/index.js +++ /dev/null @@ -1,916 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['lower'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a:hover { color: pink; }', - }, - { - code: 'a:focus { color: pink; }', - }, - { - code: 'a:before { color: pink; }', - }, - { - code: 'a:BEFORE { color: pink; }', - }, - { - code: 'a:after { color: pink; }', - }, - { - code: 'a:AFTER { color: pink; }', - }, - { - code: 'a:first-letter { color: pink; }', - }, - { - code: 'a:FIRST-LETTER { color: pink; }', - }, - { - code: 'a:first-line { color: pink; }', - }, - { - code: 'a:FIRST-LINE { color: pink; }', - }, - { - code: 'a::before { color: pink; }', - }, - { - code: 'a::BEFORE { color: pink; }', - }, - { - code: 'a::some-pseudo-element { }', - }, - { - code: 'a::SOME-PSEUDO-ELEMENT { }', - }, - { - code: 'p:first-child:before { }', - }, - { - code: 'p:first-child:BEFORE { }', - }, - { - code: 'h1:not(h2, h3) { }', - }, - { - code: 'p:nth-child(3n+0) { }', - }, - { - code: 'p:nth-child(odd) { }', - }, - { - code: 'input::-moz-placeholder { color: pink; }', - }, - { - code: 'input::-MOZ-PLACEHOLDER { color: pink; }', - }, - { - code: ':root { background: #ff0000; }', - }, - { - code: 'a:some-pseudo-class { }', - }, - { - code: ':some-pseudo-class { }', - }, - { - code: 'input[type=file]:active::-webkit-file-upload-button { }', - }, - { - code: 'input[type=file]:active::-WEBKIT-FILE-UPLOAD-BUTTON { }', - }, - { - code: ':-ms-input-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 { color: pink; }', - fixed: 'a:hover { color: pink; }', - message: messages.expected(':Hover', ':hover'), - line: 1, - column: 2, - }, - { - code: '/* comment */ a:Hover { color: pink; }', - fixed: '/* comment */ a:hover { color: pink; }', - message: messages.expected(':Hover', ':hover'), - line: 1, - column: 16, - }, - { - code: 'a:Hover,/*comment*/ .b {color: pink;}', - fixed: 'a:hover,/*comment*/ .b {color: pink;}', - message: messages.expected(':Hover', ':hover'), - line: 1, - column: 2, - }, - { - code: 'a:Hover /* comment */ { color: pink; }', - fixed: 'a:hover /* comment */ { color: pink; }', - message: messages.expected(':Hover', ':hover'), - line: 1, - column: 2, - }, - { - code: '.foo > /* comment */ a:Hover { color: pink; }', - fixed: '.foo > /* comment */ a:hover { color: pink; }', - message: messages.expected(':Hover', ':hover'), - line: 1, - column: 23, - }, - { - code: 'a:First-child:Hover { color: pink; }', - fixed: 'a:first-child:hover { color: pink; }', - warnings: [ - { - message: messages.expected(':First-child', ':first-child'), - line: 1, - column: 2, - }, - { - message: messages.expected(':Hover', ':hover'), - line: 1, - column: 14, - }, - ], - }, - { - code: 'a:hOvEr { color: pink; }', - fixed: 'a:hover { color: pink; }', - message: messages.expected(':hOvEr', ':hover'), - line: 1, - column: 2, - }, - { - code: 'a:HOVER { color: pink; }', - fixed: 'a:hover { color: pink; }', - message: messages.expected(':HOVER', ':hover'), - line: 1, - column: 2, - }, - { - code: 'p:First-child:before { }', - fixed: 'p:first-child:before { }', - message: messages.expected(':First-child', ':first-child'), - line: 1, - column: 2, - }, - { - code: 'p:First-child:BEFORE { }', - fixed: 'p:first-child:BEFORE { }', - message: messages.expected(':First-child', ':first-child'), - line: 1, - column: 2, - }, - { - code: 'h1:Not(h2, h3) { }', - fixed: 'h1:not(h2, h3) { }', - message: messages.expected(':Not', ':not'), - line: 1, - column: 3, - }, - { - code: 'h1:nOt(h2, h3) { }', - fixed: 'h1:not(h2, h3) { }', - message: messages.expected(':nOt', ':not'), - line: 1, - column: 3, - }, - { - code: 'h1:NOT(h2, h3) { }', - fixed: 'h1:not(h2, h3) { }', - message: messages.expected(':NOT', ':not'), - line: 1, - column: 3, - }, - { - code: ':matcheS(a, .foo) { }', - fixed: ':matches(a, .foo) { }', - message: messages.expected(':matcheS', ':matches'), - line: 1, - column: 1, - }, - { - code: ':Matches(a, .foo) { }', - fixed: ':matches(a, .foo) { }', - message: messages.expected(':Matches', ':matches'), - line: 1, - column: 1, - }, - { - code: 'a:hAs(> img) { }', - fixed: 'a:has(> img) { }', - message: messages.expected(':hAs', ':has'), - line: 1, - column: 2, - }, - { - code: 'a:HAS(> img) {\n}', - fixed: 'a:has(> img) {\n}', - message: messages.expected(':HAS', ':has'), - line: 1, - column: 2, - }, - { - code: ':Root { background: #ff0000; }', - fixed: ':root { background: #ff0000; }', - message: messages.expected(':Root', ':root'), - line: 1, - column: 1, - }, - { - code: ':rOoT { background: #ff0000; }', - fixed: ':root { background: #ff0000; }', - message: messages.expected(':rOoT', ':root'), - line: 1, - column: 1, - }, - { - code: ':ROOT { background: #ff0000; }', - fixed: ':root { background: #ff0000; }', - message: messages.expected(':ROOT', ':root'), - line: 1, - column: 1, - }, - { - code: 'a:Some-pseudo-class { }', - fixed: 'a:some-pseudo-class { }', - message: messages.expected(':Some-pseudo-class', ':some-pseudo-class'), - line: 1, - column: 2, - }, - { - code: 'a:sOmE-pSeUdO-cLaSs { }', - fixed: 'a:some-pseudo-class { }', - message: messages.expected(':sOmE-pSeUdO-cLaSs', ':some-pseudo-class'), - line: 1, - column: 2, - }, - { - code: 'a:SOME-PSEUDO-CLASS { }', - fixed: 'a:some-pseudo-class { }', - message: messages.expected(':SOME-PSEUDO-CLASS', ':some-pseudo-class'), - line: 1, - column: 2, - }, - { - code: ':Some-pseudo-class { }', - fixed: ':some-pseudo-class { }', - message: messages.expected(':Some-pseudo-class', ':some-pseudo-class'), - line: 1, - column: 1, - }, - { - code: ':sOmE-pSeUdO-cLaSs { }', - fixed: ':some-pseudo-class { }', - message: messages.expected(':sOmE-pSeUdO-cLaSs', ':some-pseudo-class'), - line: 1, - column: 1, - }, - { - code: ':SOME-PSEUDO-CLASS { }', - fixed: ':some-pseudo-class { }', - message: messages.expected(':SOME-PSEUDO-CLASS', ':some-pseudo-class'), - line: 1, - column: 1, - }, - { - code: 'input[type=file]:Active::-webkit-file-upload-button { }', - fixed: 'input[type=file]:active::-webkit-file-upload-button { }', - message: messages.expected(':Active', ':active'), - line: 1, - column: 17, - }, - { - code: 'input[type=file]:Active::-WEBKIT-FILE-UPLOAD-BUTTON { }', - fixed: 'input[type=file]:active::-WEBKIT-FILE-UPLOAD-BUTTON { }', - message: messages.expected(':Active', ':active'), - line: 1, - column: 17, - }, - { - code: ':-Ms-input-placeholder { }', - fixed: ':-ms-input-placeholder { }', - message: messages.expected(':-Ms-input-placeholder', ':-ms-input-placeholder'), - line: 1, - column: 1, - }, - { - code: ':-mS-iNpUt-PlAcEhOlDer { }', - fixed: ':-ms-input-placeholder { }', - message: messages.expected(':-mS-iNpUt-PlAcEhOlDer', ':-ms-input-placeholder'), - line: 1, - column: 1, - }, - { - code: ':-MS-INPUT-PLACEHOLDER { }', - fixed: ':-ms-input-placeholder { }', - message: messages.expected(':-MS-INPUT-PLACEHOLDER', ':-ms-input-placeholder'), - line: 1, - column: 1, - }, - { - code: 'a::FIRST-LETTER, a:FIRST {color: pink;}', - fixed: 'a::FIRST-LETTER, a:first {color: pink;}', - message: messages.expected(':FIRST', ':first'), - line: 1, - column: 19, - }, - { - code: 'a::FIRST-LETTER:Hover, a:FIRST {color: pink;}', - fixed: 'a::FIRST-LETTER:hover, a:first {color: pink;}', - warnings: [ - { - message: messages.expected(':Hover', ':hover'), - line: 1, - column: 16, - }, - { - message: messages.expected(':FIRST', ':first'), - line: 1, - column: 25, - }, - ], - }, - { - code: 'a::FIRST-LETTER:Hover,/*comment*/ a:FIRST {color: pink;}', - fixed: 'a::FIRST-LETTER:hover,/*comment*/ a:first {color: pink;}', - warnings: [ - { - message: messages.expected(':Hover', ':hover'), - line: 1, - column: 16, - }, - { - message: messages.expected(':FIRST', ':first'), - line: 1, - column: 36, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['upper'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a:HOVER { color: pink; }', - }, - { - code: 'a:FOCUS { color: pink; }', - }, - { - code: 'a:before { color: pink; }', - }, - { - code: 'a:BEFORE { color: pink; }', - }, - { - code: 'a:after { color: pink; }', - }, - { - code: 'a:AFTER { color: pink; }', - }, - { - code: 'a:first-letter { color: pink; }', - }, - { - code: 'a:FIRST-LETTER { color: pink; }', - }, - { - code: 'a:first-line { color: pink; }', - }, - { - code: 'a:FIRST-LINE { color: pink; }', - }, - { - code: 'a::before { color: pink; }', - }, - { - code: 'a::BEFORE { color: pink; }', - }, - { - code: 'a::some-pseudo-element { }', - }, - { - code: 'a::SOME-PSEUDO-ELEMENT { }', - }, - { - code: 'p:FIRST-CHILD:before { }', - }, - { - code: 'p:FIRST-CHILD:BEFORE { }', - }, - { - code: 'h1:NOT(h2, h3) { }', - }, - { - code: 'p:NTH-CHILD(3n+0) { }', - }, - { - code: 'p:NTH-CHILD(odd) { }', - }, - { - code: 'input::-moz-placeholder { color: pink; }', - }, - { - code: 'input::-MOZ-PLACEHOLDER { color: pink; }', - }, - { - code: ':ROOT { background: #ff0000; }', - }, - { - code: 'a:SOME-PSEUDO-CLASS { }', - }, - { - code: ':SOME-PSEUDO-CLASS { }', - }, - { - code: 'input[type=file]:ACTIVE::-webkit-file-upload-button { }', - }, - { - code: 'input[type=file]:ACTIVE::-WEBKIT-FILE-UPLOAD-BUTTON { }', - }, - { - code: ':-MS-INPUT-PLACEHOLDER { }', - }, - ], - - reject: [ - { - code: 'a:Hover { color: pink; }', - fixed: 'a:HOVER { color: pink; }', - message: messages.expected(':Hover', ':HOVER'), - line: 1, - column: 2, - }, - { - code: 'a:hOvEr { color: pink; }', - fixed: 'a:HOVER { color: pink; }', - message: messages.expected(':hOvEr', ':HOVER'), - line: 1, - column: 2, - }, - { - code: 'a:hover { color: pink; }', - fixed: 'a:HOVER { color: pink; }', - message: messages.expected(':hover', ':HOVER'), - line: 1, - column: 2, - }, - { - code: 'p:First-child:before { }', - fixed: 'p:FIRST-CHILD:before { }', - message: messages.expected(':First-child', ':FIRST-CHILD'), - line: 1, - column: 2, - }, - { - code: 'p:First-child:BEFORE { }', - fixed: 'p:FIRST-CHILD:BEFORE { }', - message: messages.expected(':First-child', ':FIRST-CHILD'), - line: 1, - column: 2, - }, - { - code: 'h1:Not(h2, h3) { }', - fixed: 'h1:NOT(h2, h3) { }', - message: messages.expected(':Not', ':NOT'), - line: 1, - column: 3, - }, - { - code: 'h1:nOt(h2, h3) { }', - fixed: 'h1:NOT(h2, h3) { }', - message: messages.expected(':nOt', ':NOT'), - line: 1, - column: 3, - }, - { - code: 'h1:not(h2, h3) { }', - fixed: 'h1:NOT(h2, h3) { }', - message: messages.expected(':not', ':NOT'), - line: 1, - column: 3, - }, - { - code: ':Root { background: #ff0000; }', - fixed: ':ROOT { background: #ff0000; }', - message: messages.expected(':Root', ':ROOT'), - line: 1, - column: 1, - }, - { - code: ':rOoT { background: #ff0000; }', - fixed: ':ROOT { background: #ff0000; }', - message: messages.expected(':rOoT', ':ROOT'), - line: 1, - column: 1, - }, - { - code: ':root { background: #ff0000; }', - fixed: ':ROOT { background: #ff0000; }', - message: messages.expected(':root', ':ROOT'), - line: 1, - column: 1, - }, - { - code: 'a:Some-pseudo-class { }', - fixed: 'a:SOME-PSEUDO-CLASS { }', - message: messages.expected(':Some-pseudo-class', ':SOME-PSEUDO-CLASS'), - line: 1, - column: 2, - }, - { - code: 'a:sOmE-pSeUdO-cLaSs { }', - fixed: 'a:SOME-PSEUDO-CLASS { }', - message: messages.expected(':sOmE-pSeUdO-cLaSs', ':SOME-PSEUDO-CLASS'), - line: 1, - column: 2, - }, - { - code: 'a:some-pseudo-class { }', - fixed: 'a:SOME-PSEUDO-CLASS { }', - message: messages.expected(':some-pseudo-class', ':SOME-PSEUDO-CLASS'), - line: 1, - column: 2, - }, - { - code: ':Some-pseudo-class { }', - fixed: ':SOME-PSEUDO-CLASS { }', - message: messages.expected(':Some-pseudo-class', ':SOME-PSEUDO-CLASS'), - line: 1, - column: 1, - }, - { - code: ':sOmE-pSeUdO-cLaSs { }', - fixed: ':SOME-PSEUDO-CLASS { }', - message: messages.expected(':sOmE-pSeUdO-cLaSs', ':SOME-PSEUDO-CLASS'), - line: 1, - column: 1, - }, - { - code: ':some-pseudo-class { }', - fixed: ':SOME-PSEUDO-CLASS { }', - message: messages.expected(':some-pseudo-class', ':SOME-PSEUDO-CLASS'), - line: 1, - column: 1, - }, - { - code: 'input[type=file]:Active::-webkit-file-upload-button { }', - fixed: 'input[type=file]:ACTIVE::-webkit-file-upload-button { }', - message: messages.expected(':Active', ':ACTIVE'), - line: 1, - column: 17, - }, - { - code: 'input[type=file]:Active::-WEBKIT-FILE-UPLOAD-BUTTON { }', - fixed: 'input[type=file]:ACTIVE::-WEBKIT-FILE-UPLOAD-BUTTON { }', - message: messages.expected(':Active', ':ACTIVE'), - line: 1, - column: 17, - }, - { - code: ':-Ms-input-placeholder { }', - fixed: ':-MS-INPUT-PLACEHOLDER { }', - message: messages.expected(':-Ms-input-placeholder', ':-MS-INPUT-PLACEHOLDER'), - line: 1, - column: 1, - }, - { - code: ':-mS-iNpUt-PlAcEhOlDer { }', - fixed: ':-MS-INPUT-PLACEHOLDER { }', - message: messages.expected(':-mS-iNpUt-PlAcEhOlDer', ':-MS-INPUT-PLACEHOLDER'), - line: 1, - column: 1, - }, - { - code: ':-ms-input-placeholder { }', - fixed: ':-MS-INPUT-PLACEHOLDER { }', - message: messages.expected(':-ms-input-placeholder', ':-MS-INPUT-PLACEHOLDER'), - line: 1, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: ['lower'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: ':#{$variable} {}', - }, - { - code: ':#{$VARIABLE} {}', - }, - { - code: 'a:#{$variable} {}', - }, - ], -}); - -testRule({ - ruleName, - config: ['lower'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a:hover { color: pink; }', - }, - { - code: 'a:focus { color: pink; }', - }, - { - code: 'a:before { color: pink; }', - }, - { - code: 'a:BEFORE { color: pink; }', - }, - { - code: 'a:after { color: pink; }', - }, - { - code: 'a:AFTER { color: pink; }', - }, - { - code: 'a:first-letter { color: pink; }', - }, - { - code: 'a:FIRST-LETTER { color: pink; }', - }, - { - code: 'a:first-line { color: pink; }', - }, - { - code: 'a:FIRST-LINE { color: pink; }', - }, - { - code: 'a::before { color: pink; }', - }, - { - code: 'a::BEFORE { color: pink; }', - }, - { - code: 'a::some-pseudo-element { }', - }, - { - code: 'a::SOME-PSEUDO-ELEMENT { }', - }, - { - code: 'p:first-child:before { }', - }, - { - code: 'p:first-child:BEFORE { }', - }, - { - code: 'h1:not(h2, h3) { }', - }, - { - code: 'p:nth-child(3n+0) { }', - }, - { - code: 'p:nth-child(odd) { }', - }, - { - code: 'input::-moz-placeholder { color: pink; }', - }, - { - code: 'input::-MOZ-PLACEHOLDER { color: pink; }', - }, - { - code: ':root { background: #ff0000; }', - }, - { - code: 'a:some-pseudo-class { }', - }, - { - code: ':some-pseudo-class { }', - }, - { - code: 'input[type=file]:active::-webkit-file-upload-button { }', - }, - { - code: 'input[type=file]:active::-WEBKIT-FILE-UPLOAD-BUTTON { }', - }, - { - code: ':-ms-input-placeholder { }', - }, - ], - - reject: [ - { - code: 'a:Hover { color: pink; }', - fixed: 'a:hover { color: pink; }', - message: messages.expected(':Hover', ':hover'), - line: 1, - column: 2, - }, - { - code: 'a:hOvEr { color: pink; }', - fixed: 'a:hover { color: pink; }', - message: messages.expected(':hOvEr', ':hover'), - line: 1, - column: 2, - }, - { - code: 'a:HOVER { color: pink; }', - fixed: 'a:hover { color: pink; }', - message: messages.expected(':HOVER', ':hover'), - line: 1, - column: 2, - }, - { - code: 'p:First-child:before { }', - fixed: 'p:first-child:before { }', - message: messages.expected(':First-child', ':first-child'), - line: 1, - column: 2, - }, - { - code: 'p:First-child:BEFORE { }', - fixed: 'p:first-child:BEFORE { }', - message: messages.expected(':First-child', ':first-child'), - line: 1, - column: 2, - }, - { - code: 'h1:Not(h2, h3) { }', - fixed: 'h1:not(h2, h3) { }', - message: messages.expected(':Not', ':not'), - line: 1, - column: 3, - }, - { - code: 'h1:nOt(h2, h3) { }', - fixed: 'h1:not(h2, h3) { }', - message: messages.expected(':nOt', ':not'), - line: 1, - column: 3, - }, - { - code: 'h1:NOT(h2, h3) { }', - fixed: 'h1:not(h2, h3) { }', - message: messages.expected(':NOT', ':not'), - line: 1, - column: 3, - }, - { - code: ':Root { background: #ff0000; }', - fixed: ':root { background: #ff0000; }', - message: messages.expected(':Root', ':root'), - line: 1, - column: 1, - }, - { - code: ':rOoT { background: #ff0000; }', - fixed: ':root { background: #ff0000; }', - message: messages.expected(':rOoT', ':root'), - line: 1, - column: 1, - }, - { - code: ':ROOT { background: #ff0000; }', - fixed: ':root { background: #ff0000; }', - message: messages.expected(':ROOT', ':root'), - line: 1, - column: 1, - }, - { - code: 'a:Some-pseudo-class { }', - fixed: 'a:some-pseudo-class { }', - message: messages.expected(':Some-pseudo-class', ':some-pseudo-class'), - line: 1, - column: 2, - }, - { - code: 'a:sOmE-pSeUdO-cLaSs { }', - fixed: 'a:some-pseudo-class { }', - message: messages.expected(':sOmE-pSeUdO-cLaSs', ':some-pseudo-class'), - line: 1, - column: 2, - }, - { - code: 'a:SOME-PSEUDO-CLASS { }', - fixed: 'a:some-pseudo-class { }', - message: messages.expected(':SOME-PSEUDO-CLASS', ':some-pseudo-class'), - line: 1, - column: 2, - }, - { - code: ':Some-pseudo-class { }', - fixed: ':some-pseudo-class { }', - message: messages.expected(':Some-pseudo-class', ':some-pseudo-class'), - line: 1, - column: 1, - }, - { - code: ':sOmE-pSeUdO-cLaSs { }', - fixed: ':some-pseudo-class { }', - message: messages.expected(':sOmE-pSeUdO-cLaSs', ':some-pseudo-class'), - line: 1, - column: 1, - }, - { - code: ':SOME-PSEUDO-CLASS { }', - fixed: ':some-pseudo-class { }', - message: messages.expected(':SOME-PSEUDO-CLASS', ':some-pseudo-class'), - line: 1, - column: 1, - }, - { - code: 'input[type=file]:Active::-webkit-file-upload-button { }', - fixed: 'input[type=file]:active::-webkit-file-upload-button { }', - message: messages.expected(':Active', ':active'), - line: 1, - column: 17, - }, - { - code: 'input[type=file]:Active::-WEBKIT-FILE-UPLOAD-BUTTON { }', - fixed: 'input[type=file]:active::-WEBKIT-FILE-UPLOAD-BUTTON { }', - message: messages.expected(':Active', ':active'), - line: 1, - column: 17, - }, - { - code: ':-Ms-input-placeholder { }', - fixed: ':-ms-input-placeholder { }', - message: messages.expected(':-Ms-input-placeholder', ':-ms-input-placeholder'), - line: 1, - column: 1, - }, - { - code: ':-mS-iNpUt-PlAcEhOlDer { }', - fixed: ':-ms-input-placeholder { }', - message: messages.expected(':-mS-iNpUt-PlAcEhOlDer', ':-ms-input-placeholder'), - line: 1, - column: 1, - }, - { - code: ':-MS-INPUT-PLACEHOLDER { }', - fixed: ':-ms-input-placeholder { }', - message: messages.expected(':-MS-INPUT-PLACEHOLDER', ':-ms-input-placeholder'), - line: 1, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: ['upper'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: ':#{$variable} {}', - }, - { - code: ':#{$VARIABLE} {}', - }, - { - code: 'a:#{$variable} {}', - }, - ], -}); diff --git a/lib/rules/selector-pseudo-class-case/index.js b/lib/rules/selector-pseudo-class-case/index.js deleted file mode 100644 index 1aefb07f8f..0000000000 --- a/lib/rules/selector-pseudo-class-case/index.js +++ /dev/null @@ -1,103 +0,0 @@ -'use strict'; - -const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); -const isStandardSyntaxSelector = require('../../utils/isStandardSyntaxSelector'); -const { levelOneAndTwoPseudoElements } = require('../../reference/selectors'); -const parseSelector = require('../../utils/parseSelector'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'selector-pseudo-class-case'; - -const messages = ruleMessages(ruleName, { - expected: (actual, expected) => `Expected "${actual}" to be "${expected}"`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/selector-pseudo-class-case', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['lower', 'upper'], - }); - - if (!validOptions) { - return; - } - - root.walkRules((ruleNode) => { - if (!isStandardSyntaxRule(ruleNode)) { - return; - } - - const selector = ruleNode.selector; - - if (!selector.includes(':')) { - return; - } - - const fixedSelector = parseSelector( - ruleNode.raws.selector ? ruleNode.raws.selector.raw : ruleNode.selector, - result, - ruleNode, - (selectorTree) => { - selectorTree.walkPseudos((pseudoNode) => { - const pseudo = pseudoNode.value; - - if (!isStandardSyntaxSelector(pseudo)) { - return; - } - - if ( - pseudo.includes('::') || - levelOneAndTwoPseudoElements.has(pseudo.toLowerCase().slice(1)) - ) { - return; - } - - const expectedPseudo = - primary === 'lower' ? pseudo.toLowerCase() : pseudo.toUpperCase(); - - if (pseudo === expectedPseudo) { - return; - } - - if (context.fix) { - pseudoNode.value = expectedPseudo; - - return; - } - - report({ - message: messages.expected(pseudo, expectedPseudo), - node: ruleNode, - index: pseudoNode.sourceIndex, - ruleName, - result, - }); - }); - }, - ); - - if (context.fix && fixedSelector) { - if (ruleNode.raws.selector) { - ruleNode.raws.selector.raw = fixedSelector; - } else { - ruleNode.selector = fixedSelector; - } - } - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/selector-pseudo-class-parentheses-space-inside/README.md b/lib/rules/selector-pseudo-class-parentheses-space-inside/README.md deleted file mode 100644 index 2c0e9c3a7c..0000000000 --- a/lib/rules/selector-pseudo-class-parentheses-space-inside/README.md +++ /dev/null @@ -1,64 +0,0 @@ -# selector-pseudo-class-parentheses-space-inside - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace on the inside of the parentheses within pseudo-class selectors. - - -```css -input:not( [type="submit"] ) {} -/** ↑ ↑ - * The space inside these two parentheses */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix most of the problems reported by this rule. It won't fix pseudo elements containing comments. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -There _must always_ be a single space inside the parentheses. - -The following patterns are considered problems: - - -```css -input:not([type="submit"]) {} -``` - - -```css -input:not([type="submit"] ) {} -``` - -The following patterns are _not_ considered problems: - - -```css -input:not( [type="submit"] ) {} -``` - -### `"never"` - -There _must never_ be whitespace on the inside the parentheses. - -The following patterns are considered problems: - - -```css -input:not( [type="submit"] ) {} -``` - - -```css -input:not( [type="submit"]) {} -``` - -The following patterns are _not_ considered problems: - - -```css -input:not([type="submit"]) {} -``` diff --git a/lib/rules/selector-pseudo-class-parentheses-space-inside/__tests__/index.js b/lib/rules/selector-pseudo-class-parentheses-space-inside/__tests__/index.js deleted file mode 100644 index f2514de044..0000000000 --- a/lib/rules/selector-pseudo-class-parentheses-space-inside/__tests__/index.js +++ /dev/null @@ -1,414 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: "input:not( [type='submit'] ) { }", - }, - { - code: "input:not( [type='submit'], [type='text'] ) { }", - }, - { - code: "input:not( [type='submit'], [type='text'] ) { }", - }, - { - code: 'p:lang( it ) { }', - }, - { - code: 'section:not( :has( h1, h2 ) ) { }', - }, - { - code: "input:not( [type='radio'] ):not( [type='checkbox'] ) { }", - }, - { - code: 'a:hover:not( .active ) { }', - }, - { - 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', - }, - { - code: 'a[b=#{c}] { }', - description: 'ignore "invalid" selector (see #3130)', - }, - ], - - reject: [ - { - code: "input:not([type='submit'] ) { }", - fixed: "input:not( [type='submit'] ) { }", - message: messages.expectedOpening, - line: 1, - column: 11, - }, - { - code: "input:not( [type='submit']) { }", - fixed: "input:not( [type='submit'] ) { }", - message: messages.expectedClosing, - line: 1, - column: 26, - }, - { - code: "input:not([type='submit'], [type='text'] ) { }", - fixed: "input:not( [type='submit'], [type='text'] ) { }", - message: messages.expectedOpening, - line: 1, - column: 11, - }, - { - code: "input:not( [type='submit'], [type='text']) { }", - fixed: "input:not( [type='submit'], [type='text'] ) { }", - message: messages.expectedClosing, - line: 1, - column: 41, - }, - { - code: "input:not( [type='submit']) { }", - fixed: "input:not( [type='submit'] ) { }", - message: messages.expectedClosing, - line: 1, - column: 27, - }, - { - code: 'section:not(:has( h1, h2 ) ) { }', - fixed: 'section:not( :has( h1, h2 ) ) { }', - message: messages.expectedOpening, - line: 1, - column: 13, - }, - { - code: 'section:not( :has( h1, h2 )) { }', - fixed: 'section:not( :has( h1, h2 ) ) { }', - message: messages.expectedClosing, - line: 1, - column: 27, - }, - { - code: 'section:not( :has(h1, h2 ) ) { }', - fixed: 'section:not( :has( h1, h2 ) ) { }', - message: messages.expectedOpening, - line: 1, - column: 19, - }, - { - code: ':matches( a, ul, :has(h1, h2 ) ) { }', - fixed: ':matches( a, ul, :has( h1, h2 ) ) { }', - message: messages.expectedOpening, - line: 1, - column: 23, - }, - { - code: 'section:not( :has( h1, h2) ) { }', - fixed: 'section:not( :has( h1, h2 ) ) { }', - message: messages.expectedClosing, - line: 1, - column: 25, - }, - { - code: 'section:not(:has(h1, h2)) { }', - fixed: 'section:not( :has( h1, h2 ) ) { }', - warnings: [ - { - message: messages.expectedOpening, - line: 1, - column: 13, - }, - { - message: messages.expectedClosing, - line: 1, - column: 24, - }, - { - message: messages.expectedOpening, - line: 1, - column: 18, - }, - { - message: messages.expectedClosing, - line: 1, - column: 23, - }, - ], - }, - { - code: "input:not([type='radio'] ):not( [type='checkbox'] ) { }", - fixed: "input:not( [type='radio'] ):not( [type='checkbox'] ) { }", - message: messages.expectedOpening, - line: 1, - column: 11, - }, - { - code: "input:not( [type='radio']):not( [type='checkbox'] ) { }", - fixed: "input:not( [type='radio'] ):not( [type='checkbox'] ) { }", - message: messages.expectedClosing, - line: 1, - column: 25, - }, - { - code: "input:not( [type='radio'] ):not([type='checkbox'] ) { }", - fixed: "input:not( [type='radio'] ):not( [type='checkbox'] ) { }", - message: messages.expectedOpening, - line: 1, - column: 33, - }, - { - code: "input:not( [type='radio'] ):not( [type='checkbox']) { }", - fixed: "input:not( [type='radio'] ):not( [type='checkbox'] ) { }", - message: messages.expectedClosing, - line: 1, - column: 50, - }, - { - code: 'a:hover:not(.active ) { }', - fixed: 'a:hover:not( .active ) { }', - message: messages.expectedOpening, - line: 1, - column: 13, - }, - { - code: 'a:hover:not( .active) { }', - fixed: 'a:hover:not( .active ) { }', - message: messages.expectedClosing, - line: 1, - column: 20, - }, - { - code: 'section:not(/**/:has(/**/h1, h2/**/)/**/) { }', - fixed: 'section:not( /**/:has( /**/h1, h2/**/ )/**/ ) { }', - warnings: [ - { - message: messages.expectedOpening, - line: 1, - column: 13, - }, - { - message: messages.expectedClosing, - line: 1, - column: 40, - }, - { - message: messages.expectedOpening, - line: 1, - column: 22, - }, - { - message: messages.expectedClosing, - line: 1, - column: 35, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: "input:not([type='submit']) { }", - }, - { - code: "input:not([type='submit'], [type='text']) { }", - }, - { - code: "input:not([type='submit'], [type='text']) { }", - }, - { - code: 'p:lang(it) { }', - }, - { - code: 'section:not(:has(h1, h2)) { }', - }, - { - code: "input:not([type='radio']):not([type='checkbox']) { }", - }, - { - code: 'a:hover:not(.active) { }', - }, - { - code: ':matches(a, ul, :has(h1, h2)) { }', - }, - ], - - reject: [ - { - code: "input:not([type='submit'] ) { }", - fixed: "input:not([type='submit']) { }", - message: messages.rejectedClosing, - line: 1, - column: 26, - }, - { - code: "input:not( [type='submit']) { }", - fixed: "input:not([type='submit']) { }", - message: messages.rejectedOpening, - line: 1, - column: 11, - }, - { - code: "input:not([type='submit'], [type='text'] ) { }", - fixed: "input:not([type='submit'], [type='text']) { }", - message: messages.rejectedClosing, - line: 1, - column: 41, - }, - { - code: "input:not( [type='submit'], [type='text']) { }", - fixed: "input:not([type='submit'], [type='text']) { }", - message: messages.rejectedOpening, - line: 1, - column: 11, - }, - { - code: "input:not( [type='submit']) { }", - fixed: "input:not([type='submit']) { }", - message: messages.rejectedOpening, - line: 1, - column: 11, - }, - { - code: 'section:not( :has(h1, h2)) { }', - fixed: 'section:not(:has(h1, h2)) { }', - message: messages.rejectedOpening, - line: 1, - column: 13, - }, - { - code: 'section:not(:has( h1, h2)) { }', - fixed: 'section:not(:has(h1, h2)) { }', - message: messages.rejectedOpening, - line: 1, - column: 18, - }, - { - code: 'section:not(:has(h1, h2) ) { }', - fixed: 'section:not(:has(h1, h2)) { }', - message: messages.rejectedClosing, - line: 1, - column: 25, - }, - { - code: 'section:not(:has(h1, h2 )) { }', - fixed: 'section:not(:has(h1, h2)) { }', - message: messages.rejectedClosing, - line: 1, - column: 24, - }, - { - code: 'section:not( :has( h1, h2 ) ) { }', - fixed: 'section:not(:has(h1, h2)) { }', - warnings: [ - { - message: messages.rejectedOpening, - line: 1, - column: 13, - }, - { - message: messages.rejectedClosing, - line: 1, - column: 28, - }, - { - message: messages.rejectedOpening, - line: 1, - column: 19, - }, - { - message: messages.rejectedClosing, - line: 1, - column: 26, - }, - ], - }, - { - code: "input:not( [type='radio']):not([type='checkbox']) { }", - fixed: "input:not([type='radio']):not([type='checkbox']) { }", - message: messages.rejectedOpening, - line: 1, - column: 11, - }, - { - code: "input:not([type='radio'] ):not([type='checkbox']) { }", - fixed: "input:not([type='radio']):not([type='checkbox']) { }", - message: messages.rejectedClosing, - line: 1, - column: 25, - }, - { - code: "input:not([type='radio']):not( [type='checkbox']) { }", - fixed: "input:not([type='radio']):not([type='checkbox']) { }", - message: messages.rejectedOpening, - line: 1, - column: 31, - }, - { - code: "input:not([type='radio']):not([type='checkbox'] ) { }", - fixed: "input:not([type='radio']):not([type='checkbox']) { }", - message: messages.rejectedClosing, - line: 1, - column: 48, - }, - { - code: 'a:hover:not( .active) { }', - fixed: 'a:hover:not(.active) { }', - message: messages.rejectedOpening, - line: 1, - column: 13, - }, - { - code: 'a:hover:not(.active ) { }', - fixed: 'a:hover:not(.active) { }', - message: messages.rejectedClosing, - line: 1, - column: 20, - }, - { - skip: true, - code: 'section:not( /**/ :has( /**/ h1, h2 /**/ ) /**/ ) { }', - fixed: 'section:not(/**/ :has(/**/ h1, h2 /**/) /**/) { }', - warnings: [ - { - message: messages.rejectedOpening, - line: 1, - column: 13, - }, - { - message: messages.rejectedClosing, - line: 1, - column: 48, - }, - { - message: messages.rejectedOpening, - line: 1, - column: 24, - }, - { - message: messages.rejectedClosing, - line: 1, - column: 41, - }, - ], - }, - ], -}); diff --git a/lib/rules/selector-pseudo-class-parentheses-space-inside/index.js b/lib/rules/selector-pseudo-class-parentheses-space-inside/index.js deleted file mode 100644 index 26ab0c7fb3..0000000000 --- a/lib/rules/selector-pseudo-class-parentheses-space-inside/index.js +++ /dev/null @@ -1,156 +0,0 @@ -'use strict'; - -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-pseudo-class-parentheses-space-inside'; - -const messages = ruleMessages(ruleName, { - expectedOpening: 'Expected single space after "("', - rejectedOpening: 'Unexpected whitespace after "("', - expectedClosing: 'Expected single space before ")"', - rejectedClosing: 'Unexpected whitespace before ")"', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/selector-pseudo-class-parentheses-space-inside', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if (!validOptions) { - return; - } - - root.walkRules((ruleNode) => { - if (!isStandardSyntaxRule(ruleNode)) { - return; - } - - if (!ruleNode.selector.includes('(')) { - return; - } - - let hasFixed = false; - const selector = ruleNode.raws.selector ? ruleNode.raws.selector.raw : ruleNode.selector; - const fixedSelector = parseSelector(selector, result, ruleNode, (selectorTree) => { - selectorTree.walkPseudos((pseudoNode) => { - if (!pseudoNode.length) { - return; - } - - const paramString = pseudoNode.map((node) => String(node)).join(','); - const nextCharIsSpace = paramString.startsWith(' '); - const openIndex = pseudoNode.sourceIndex + pseudoNode.value.length + 1; - - if (nextCharIsSpace && primary === 'never') { - if (context.fix) { - hasFixed = true; - setFirstNodeSpaceBefore(pseudoNode, ''); - } else { - complain(messages.rejectedOpening, openIndex); - } - } - - if (!nextCharIsSpace && primary === 'always') { - if (context.fix) { - hasFixed = true; - setFirstNodeSpaceBefore(pseudoNode, ' '); - } else { - complain(messages.expectedOpening, openIndex); - } - } - - const prevCharIsSpace = paramString.endsWith(' '); - const closeIndex = openIndex + paramString.length - 1; - - if (prevCharIsSpace && primary === 'never') { - if (context.fix) { - hasFixed = true; - setLastNodeSpaceAfter(pseudoNode, ''); - } else { - complain(messages.rejectedClosing, closeIndex); - } - } - - if (!prevCharIsSpace && primary === 'always') { - if (context.fix) { - hasFixed = true; - setLastNodeSpaceAfter(pseudoNode, ' '); - } else { - complain(messages.expectedClosing, closeIndex); - } - } - }); - }); - - if (hasFixed && fixedSelector) { - if (!ruleNode.raws.selector) { - ruleNode.selector = fixedSelector; - } else { - ruleNode.raws.selector.raw = fixedSelector; - } - } - - /** - * @param {string} message - * @param {number} index - */ - function complain(message, index) { - report({ - message, - index, - result, - ruleName, - node: ruleNode, - }); - } - }); - }; -}; - -/** - * @param {import('postcss-selector-parser').Container} node - * @param {string} value - * @returns {void} - */ -function setFirstNodeSpaceBefore(node, value) { - const target = node.first; - - if (target.type === 'selector') { - setFirstNodeSpaceBefore(target, value); - } else { - target.spaces.before = value; - } -} - -/** - * @param {import('postcss-selector-parser').Container} node - * @param {string} value - * @returns {void} - */ -function setLastNodeSpaceAfter(node, value) { - const target = node.last; - - if (target.type === 'selector') { - setLastNodeSpaceAfter(target, value); - } else { - target.spaces.after = value; - } -} - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/selector-pseudo-element-case/README.md b/lib/rules/selector-pseudo-element-case/README.md deleted file mode 100644 index a4a7469d20..0000000000 --- a/lib/rules/selector-pseudo-element-case/README.md +++ /dev/null @@ -1,130 +0,0 @@ -# selector-pseudo-element-case - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Specify lowercase or uppercase for pseudo-element selectors. - - -```css - a::before {} -/** ↑ - * This pseudo-element selector */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`string`: `"lower"|"upper"` - -### `"lower"` - -The following patterns are considered problems: - - -```css -a:Before {} -``` - - -```css -a:bEfOrE {} -``` - - -```css -a:BEFORE {} -``` - - -```css -a::Before {} -``` - - -```css -a::bEfOrE {} -``` - - -```css -a::BEFORE {} -``` - - -```css -input::-MOZ-PLACEHOLDER {} -``` - -The following patterns are _not_ considered problems: - - -```css -a:before {} -``` - - -```css -a::before {} -``` - - -```css -input::-moz-placeholder {} -``` - -### `"upper"` - -The following patterns are considered problems: - - -```css -a:Before {} -``` - - -```css -a:bEfOrE {} -``` - - -```css -a:BEFORE {} -``` - - -```css -a::Before {} -``` - - -```css -a::bEfOrE {} -``` - - -```css -a::before {} -``` - - -```css -input::-moz-placeholder {} -``` - -The following patterns are _not_ considered problems: - - -```css -a:BEFORE {} -``` - - -```css -a::BEFORE {} -``` - - -```css -input::-MOZ-PLACEHOLDER {} -``` diff --git a/lib/rules/selector-pseudo-element-case/__tests__/index.js b/lib/rules/selector-pseudo-element-case/__tests__/index.js deleted file mode 100644 index 9db2529b0c..0000000000 --- a/lib/rules/selector-pseudo-element-case/__tests__/index.js +++ /dev/null @@ -1,592 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['lower'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a:before { color: pink; }', - }, - { - code: 'a:after { color: pink; }', - }, - { - code: 'a:first-letter { color: pink; }', - }, - { - code: 'a:first-line { color: pink; }', - }, - { - code: "a:before, a[data-before='BEFORE'] { color: pink; }", - }, - { - code: 'a::before { color: pink; }', - }, - { - code: 'a::after { color: pink; }', - }, - { - code: 'a::first-letter { color: pink; }', - }, - { - code: 'a::first-line { color: pink; }', - }, - { - code: '::selection { }', - }, - { - code: 'a::spelling-error { color: pink; }', - }, - { - code: 'a::grammar-error { color: pink; }', - }, - { - code: 'li::marker { font-variant-numeric: tabular-nums; }', - }, - { - code: 'a::some-pseudo-element { }', - }, - { - code: 'p:first-child:before { }', - }, - { - code: 'h1:not(h2, h3) { }', - }, - { - code: 'h1:NOT(h2, h3) { }', - }, - { - code: 'a:focus { }', - }, - { - code: 'a:FOCUS { }', - }, - { - code: 'input::-moz-placeholder { color: pink; }', - }, - { - 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', - }, - { - code: 'html/*comment*/ { }', - }, - ], - - reject: [ - { - code: 'a:Before { color: pink; }', - fixed: 'a:before { color: pink; }', - message: messages.expected(':Before', ':before'), - line: 1, - column: 2, - }, - { - code: 'a:bEfOrE { color: pink; }', - fixed: 'a:before { color: pink; }', - message: messages.expected(':bEfOrE', ':before'), - line: 1, - column: 2, - }, - { - code: 'a:BEFORE { color: pink; }', - fixed: 'a:before { color: pink; }', - message: messages.expected(':BEFORE', ':before'), - line: 1, - column: 2, - }, - { - code: 'a:After { color: pink; }', - fixed: 'a:after { color: pink; }', - message: messages.expected(':After', ':after'), - line: 1, - column: 2, - }, - { - code: 'a:First-letter { color: pink; }', - fixed: 'a:first-letter { color: pink; }', - message: messages.expected(':First-letter', ':first-letter'), - line: 1, - column: 2, - }, - { - code: 'a:First-line { color: pink; }', - fixed: 'a:first-line { color: pink; }', - message: messages.expected(':First-line', ':first-line'), - line: 1, - column: 2, - }, - { - code: 'a::Before { color: pink; }', - fixed: 'a::before { color: pink; }', - message: messages.expected('::Before', '::before'), - line: 1, - column: 2, - }, - { - code: 'a::bEfOrE { color: pink; }', - fixed: 'a::before { color: pink; }', - message: messages.expected('::bEfOrE', '::before'), - line: 1, - column: 2, - }, - { - code: 'a::BEFORE { color: pink; }', - fixed: 'a::before { color: pink; }', - message: messages.expected('::BEFORE', '::before'), - line: 1, - column: 2, - }, - { - code: 'a::After { color: pink; }', - fixed: 'a::after { color: pink; }', - message: messages.expected('::After', '::after'), - line: 1, - column: 2, - }, - { - code: 'a::First-letter { color: pink; }', - fixed: 'a::first-letter { color: pink; }', - message: messages.expected('::First-letter', '::first-letter'), - line: 1, - column: 2, - }, - { - code: 'a::First-line { color: pink; }', - fixed: 'a::first-line { color: pink; }', - message: messages.expected('::First-line', '::first-line'), - line: 1, - column: 2, - }, - { - code: '::Selection { }', - fixed: '::selection { }', - message: messages.expected('::Selection', '::selection'), - line: 1, - column: 1, - }, - { - code: '::sElEcTiOn { }', - fixed: '::selection { }', - message: messages.expected('::sElEcTiOn', '::selection'), - line: 1, - column: 1, - }, - { - code: '::SELECTION { }', - fixed: '::selection { }', - message: messages.expected('::SELECTION', '::selection'), - line: 1, - column: 1, - }, - { - code: 'a::Spelling-error { color: pink; }', - fixed: 'a::spelling-error { color: pink; }', - message: messages.expected('::Spelling-error', '::spelling-error'), - line: 1, - column: 2, - }, - { - code: 'a::Grammar-error { color: pink; }', - fixed: 'a::grammar-error { color: pink; }', - message: messages.expected('::Grammar-error', '::grammar-error'), - line: 1, - column: 2, - }, - { - code: 'li::Marker { font-variant-numeric: tabular-nums; }', - fixed: 'li::marker { font-variant-numeric: tabular-nums; }', - message: messages.expected('::Marker', '::marker'), - line: 1, - column: 3, - }, - { - code: 'a::Some-pseudo-element { }', - fixed: 'a::some-pseudo-element { }', - message: messages.expected('::Some-pseudo-element', '::some-pseudo-element'), - line: 1, - column: 2, - }, - { - code: 'a::sOmE-pSeUdO-eLeMenT { }', - fixed: 'a::some-pseudo-element { }', - message: messages.expected('::sOmE-pSeUdO-eLeMenT', '::some-pseudo-element'), - line: 1, - column: 2, - }, - { - code: 'a::SOME-PSEUDO-ELEMENT { }', - fixed: 'a::some-pseudo-element { }', - message: messages.expected('::SOME-PSEUDO-ELEMENT', '::some-pseudo-element'), - line: 1, - column: 2, - }, - { - code: 'p:first-child:Before { }', - fixed: 'p:first-child:before { }', - message: messages.expected(':Before', ':before'), - line: 1, - column: 14, - }, - { - code: 'p:First-child:Before { }', - fixed: 'p:First-child:before { }', - message: messages.expected(':Before', ':before'), - line: 1, - column: 14, - }, - { - code: 'p:first-child::Before { }', - fixed: 'p:first-child::before { }', - message: messages.expected('::Before', '::before'), - line: 1, - column: 14, - }, - { - code: 'p:First-child::Before { }', - fixed: 'p:First-child::before { }', - message: messages.expected('::Before', '::before'), - line: 1, - column: 14, - }, - { - code: 'input::-MOZ-PLACEHOLDER { color: pink; }', - fixed: 'input::-moz-placeholder { color: pink; }', - message: messages.expected('::-MOZ-PLACEHOLDER', '::-moz-placeholder'), - line: 1, - column: 6, - }, - { - code: 'a::bEfOrE/*comment*/ { color: pink; }', - fixed: 'a::before/*comment*/ { color: pink; }', - message: messages.expected('::bEfOrE', '::before'), - line: 1, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: ['lower'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: '::#{$variable} {}', - }, - { - code: '::#{$VARIABLE} {}', - }, - { - code: 'a::#{$variable} {}', - }, - { - code: 'a::#{$variable}/*comment*/ {}', - }, - ], -}); - -testRule({ - ruleName, - config: ['upper'], - fix: true, - - accept: [ - { - code: 'a { color: pink; }', - }, - { - code: 'a:BEFORE { color: pink; }', - }, - { - code: 'a:AFTER { color: pink; }', - }, - { - code: 'a:FIRST-LETTER { color: pink; }', - }, - { - code: 'a:FIRST-LINE { color: pink; }', - }, - { - code: "a:BEFORE, a[data-before='before'] { color: pink; }", - }, - { - code: 'a::BEFORE { color: pink; }', - }, - { - code: 'a::AFTER { color: pink; }', - }, - { - code: 'a::FIRST-LETTER { color: pink; }', - }, - { - code: 'a::FIRST-LINE { color: pink; }', - }, - { - code: '::SELECTION { }', - }, - { - code: 'a::SPELLING-ERROR { color: pink; }', - }, - { - code: 'a::GRAMMAR-ERROR { color: pink; }', - }, - { - code: 'li::MARKER { font-variant-numeric: tabular-nums; }', - }, - { - code: 'a::SOME-PSEUDO-ELEMENT { }', - }, - { - code: 'p:first-child:BEFORE { }', - }, - { - code: 'h1:not(h2, h3) { }', - }, - { - code: 'h1:NOT(h2, h3) { }', - }, - { - code: 'a:focus { }', - }, - { - code: 'a:FOCUS { }', - }, - { - code: 'input::-MOZ-PLACEHOLDER { color: pink; }', - }, - { - code: 'a:FOCUS/*comment*/ { }', - }, - ], - - reject: [ - { - code: 'a:Before { color: pink; }', - fixed: 'a:BEFORE { color: pink; }', - message: messages.expected(':Before', ':BEFORE'), - line: 1, - column: 2, - }, - { - code: 'a:bEfOrE { color: pink; }', - fixed: 'a:BEFORE { color: pink; }', - message: messages.expected(':bEfOrE', ':BEFORE'), - line: 1, - column: 2, - }, - { - code: 'a:before { color: pink; }', - fixed: 'a:BEFORE { color: pink; }', - message: messages.expected(':before', ':BEFORE'), - line: 1, - column: 2, - }, - { - code: 'a:After { color: pink; }', - fixed: 'a:AFTER { color: pink; }', - message: messages.expected(':After', ':AFTER'), - line: 1, - column: 2, - }, - { - code: 'a:First-letter { color: pink; }', - fixed: 'a:FIRST-LETTER { color: pink; }', - message: messages.expected(':First-letter', ':FIRST-LETTER'), - line: 1, - column: 2, - }, - { - code: 'a:First-line { color: pink; }', - fixed: 'a:FIRST-LINE { color: pink; }', - message: messages.expected(':First-line', ':FIRST-LINE'), - line: 1, - column: 2, - }, - { - code: 'a::Before { color: pink; }', - fixed: 'a::BEFORE { color: pink; }', - message: messages.expected('::Before', '::BEFORE'), - line: 1, - column: 2, - }, - { - code: 'a::bEfOrE { color: pink; }', - fixed: 'a::BEFORE { color: pink; }', - message: messages.expected('::bEfOrE', '::BEFORE'), - line: 1, - column: 2, - }, - { - code: 'a::before { color: pink; }', - fixed: 'a::BEFORE { color: pink; }', - message: messages.expected('::before', '::BEFORE'), - line: 1, - column: 2, - }, - { - code: 'a::After { color: pink; }', - fixed: 'a::AFTER { color: pink; }', - message: messages.expected('::After', '::AFTER'), - line: 1, - column: 2, - }, - { - code: 'a::First-letter { color: pink; }', - fixed: 'a::FIRST-LETTER { color: pink; }', - message: messages.expected('::First-letter', '::FIRST-LETTER'), - line: 1, - column: 2, - }, - { - code: 'a::First-line { color: pink; }', - fixed: 'a::FIRST-LINE { color: pink; }', - message: messages.expected('::First-line', '::FIRST-LINE'), - line: 1, - column: 2, - }, - { - code: '::Selection { }', - fixed: '::SELECTION { }', - message: messages.expected('::Selection', '::SELECTION'), - line: 1, - column: 1, - }, - { - code: '::sElEcTiOn { }', - fixed: '::SELECTION { }', - message: messages.expected('::sElEcTiOn', '::SELECTION'), - line: 1, - column: 1, - }, - { - code: '::selection { }', - fixed: '::SELECTION { }', - message: messages.expected('::selection', '::SELECTION'), - line: 1, - column: 1, - }, - { - code: 'a::Spelling-error { color: pink; }', - fixed: 'a::SPELLING-ERROR { color: pink; }', - message: messages.expected('::Spelling-error', '::SPELLING-ERROR'), - line: 1, - column: 2, - }, - { - code: 'a::Grammar-error { color: pink; }', - fixed: 'a::GRAMMAR-ERROR { color: pink; }', - message: messages.expected('::Grammar-error', '::GRAMMAR-ERROR'), - line: 1, - column: 2, - }, - { - code: 'li::Marker { font-variant-numeric: tabular-nums; }', - fixed: 'li::MARKER { font-variant-numeric: tabular-nums; }', - message: messages.expected('::Marker', '::MARKER'), - line: 1, - column: 3, - }, - { - code: 'a::Some-pseudo-element { }', - fixed: 'a::SOME-PSEUDO-ELEMENT { }', - message: messages.expected('::Some-pseudo-element', '::SOME-PSEUDO-ELEMENT'), - line: 1, - column: 2, - }, - { - code: 'a::sOmE-pSeUdO-eLeMenT { }', - fixed: 'a::SOME-PSEUDO-ELEMENT { }', - message: messages.expected('::sOmE-pSeUdO-eLeMenT', '::SOME-PSEUDO-ELEMENT'), - line: 1, - column: 2, - }, - { - code: 'a::some-pseudo-element { }', - fixed: 'a::SOME-PSEUDO-ELEMENT { }', - message: messages.expected('::some-pseudo-element', '::SOME-PSEUDO-ELEMENT'), - line: 1, - column: 2, - }, - { - code: 'p:first-child:Before { }', - fixed: 'p:first-child:BEFORE { }', - message: messages.expected(':Before', ':BEFORE'), - line: 1, - column: 14, - }, - { - code: 'p:First-child:Before { }', - fixed: 'p:First-child:BEFORE { }', - message: messages.expected(':Before', ':BEFORE'), - line: 1, - column: 14, - }, - { - code: 'p:first-child::Before { }', - fixed: 'p:first-child::BEFORE { }', - message: messages.expected('::Before', '::BEFORE'), - line: 1, - column: 14, - }, - { - code: 'p:First-child::Before { }', - fixed: 'p:First-child::BEFORE { }', - message: messages.expected('::Before', '::BEFORE'), - line: 1, - column: 14, - }, - { - code: 'input::-moz-placeholder { color: pink; }', - fixed: 'input::-MOZ-PLACEHOLDER { color: pink; }', - message: messages.expected('::-moz-placeholder', '::-MOZ-PLACEHOLDER'), - line: 1, - column: 6, - }, - { - code: '::Selection/*comment*/ { }', - fixed: '::SELECTION/*comment*/ { }', - message: messages.expected('::Selection', '::SELECTION'), - line: 1, - column: 1, - }, - ], -}); - -testRule({ - ruleName, - config: ['upper'], - customSyntax: 'postcss-scss', - - accept: [ - { - code: '::#{$variable} {}', - }, - { - code: '::#{$VARIABLE} {}', - }, - { - code: 'a::#{$variable} {}', - }, - ], -}); diff --git a/lib/rules/selector-pseudo-element-case/index.js b/lib/rules/selector-pseudo-element-case/index.js deleted file mode 100644 index 37cee6b0bd..0000000000 --- a/lib/rules/selector-pseudo-element-case/index.js +++ /dev/null @@ -1,90 +0,0 @@ -'use strict'; - -const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); -const isStandardSyntaxSelector = require('../../utils/isStandardSyntaxSelector'); -const { levelOneAndTwoPseudoElements } = require('../../reference/selectors'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const transformSelector = require('../../utils/transformSelector'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'selector-pseudo-element-case'; - -const messages = ruleMessages(ruleName, { - expected: (actual, expected) => `Expected "${actual}" to be "${expected}"`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/selector-pseudo-element-case', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['lower', 'upper'], - }); - - if (!validOptions) { - return; - } - - root.walkRules((ruleNode) => { - if (!isStandardSyntaxRule(ruleNode)) { - return; - } - - const selector = ruleNode.selector; - - if (!selector.includes(':')) { - return; - } - - transformSelector(result, ruleNode, (selectorTree) => { - selectorTree.walkPseudos((pseudoNode) => { - const pseudoElement = pseudoNode.value; - - if (!isStandardSyntaxSelector(pseudoElement)) { - return; - } - - if ( - !pseudoElement.includes('::') && - !levelOneAndTwoPseudoElements.has(pseudoElement.toLowerCase().slice(1)) - ) { - return; - } - - const expectedPseudoElement = - primary === 'lower' ? pseudoElement.toLowerCase() : pseudoElement.toUpperCase(); - - if (pseudoElement === expectedPseudoElement) { - return; - } - - if (context.fix) { - pseudoNode.value = expectedPseudoElement; - - return; - } - - report({ - message: messages.expected(pseudoElement, expectedPseudoElement), - node: ruleNode, - index: pseudoNode.sourceIndex, - ruleName, - result, - }); - }); - }); - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/selectorAttributeOperatorSpaceChecker.js b/lib/rules/selectorAttributeOperatorSpaceChecker.js deleted file mode 100644 index 25e36b2e72..0000000000 --- a/lib/rules/selectorAttributeOperatorSpaceChecker.js +++ /dev/null @@ -1,92 +0,0 @@ -'use strict'; - -const isStandardSyntaxRule = require('../utils/isStandardSyntaxRule'); -const parseSelector = require('../utils/parseSelector'); -const report = require('../utils/report'); -const styleSearch = require('style-search'); - -/** - * @param {{ - * root: import('postcss').Root, - * result: import('stylelint').PostcssResult, - * locationChecker: (opts: { source: string, index: number, err: (msg: string) => void }) => void, - * checkedRuleName: string, - * checkBeforeOperator: boolean, - * fix: ((attributeNode: import('postcss-selector-parser').Attribute) => boolean) | null, - * }} options - * @returns {void} - */ -module.exports = function selectorAttributeOperatorSpaceChecker(options) { - options.root.walkRules((rule) => { - if (!isStandardSyntaxRule(rule)) { - return; - } - - if (!rule.selector.includes('[') || !rule.selector.includes('=')) { - return; - } - - let hasFixed = false; - const selector = rule.raws.selector ? rule.raws.selector.raw : rule.selector; - - const fixedSelector = parseSelector(selector, options.result, rule, (selectorTree) => { - selectorTree.walkAttributes((attributeNode) => { - const operator = attributeNode.operator; - - if (!operator) { - return; - } - - const attributeNodeString = attributeNode.toString(); - - styleSearch({ source: attributeNodeString, target: operator }, (match) => { - const index = options.checkBeforeOperator ? match.startIndex : match.endIndex - 1; - - checkOperator(attributeNodeString, index, rule, attributeNode, operator); - }); - }); - }); - - if (hasFixed && fixedSelector) { - if (!rule.raws.selector) { - rule.selector = fixedSelector; - } else { - rule.raws.selector.raw = fixedSelector; - } - } - - /** - * @param {string} source - * @param {number} index - * @param {import('postcss').Node} node - * @param {import('postcss-selector-parser').Attribute} attributeNode - * @param {string} operator - */ - function checkOperator(source, index, node, attributeNode, operator) { - options.locationChecker({ - source, - index, - err: (msg) => { - if (options.fix && options.fix(attributeNode)) { - hasFixed = true; - - return; - } - - report({ - message: msg.replace( - options.checkBeforeOperator - ? operator.charAt(0) - : operator.charAt(operator.length - 1), - operator, - ), - node, - index: attributeNode.sourceIndex + index, - result: options.result, - ruleName: options.checkedRuleName, - }); - }, - }); - } - }); -}; diff --git a/lib/rules/selectorCombinatorSpaceChecker.js b/lib/rules/selectorCombinatorSpaceChecker.js deleted file mode 100644 index b8f469a84c..0000000000 --- a/lib/rules/selectorCombinatorSpaceChecker.js +++ /dev/null @@ -1,105 +0,0 @@ -'use strict'; - -const isStandardSyntaxCombinator = require('../utils/isStandardSyntaxCombinator'); -const isStandardSyntaxRule = require('../utils/isStandardSyntaxRule'); -const parseSelector = require('../utils/parseSelector'); -const report = require('../utils/report'); - -/** - * @typedef {(args: { source: string, index: number, errTarget: string, err: (message: string) => void }) => void} LocationChecker - * - * @param {{ - * root: import('postcss').Root, - * result: import('stylelint').PostcssResult, - * locationChecker: LocationChecker, - * locationType: 'before' | 'after', - * checkedRuleName: string, - * fix: ((combinator: import('postcss-selector-parser').Combinator) => boolean) | null, - * }} opts - * @returns {void} - */ -module.exports = function selectorCombinatorSpaceChecker(opts) { - let hasFixed; - - opts.root.walkRules((rule) => { - if (!isStandardSyntaxRule(rule)) { - return; - } - - hasFixed = false; - const selector = rule.raws.selector ? rule.raws.selector.raw : rule.selector; - - const fixedSelector = parseSelector(selector, opts.result, rule, (selectorTree) => { - selectorTree.walkCombinators((node) => { - // Ignore non-standard combinators - if (!isStandardSyntaxCombinator(node)) { - return; - } - - // Ignore spaced descendant combinator - if (/\s/.test(node.value)) { - return; - } - - // Check the exist of node in prev of the combinator. - // in case some that aren't the first begin with combinators (nesting syntax) - if (opts.locationType === 'before' && !node.prev()) { - return; - } - - const parentParentNode = node.parent && node.parent.parent; - - // Ignore pseudo-classes selector like `.foo:nth-child(2n + 1) {}` - if (parentParentNode && parentParentNode.type === 'pseudo') { - return; - } - - const sourceIndex = node.sourceIndex; - const index = - node.value.length > 1 && opts.locationType === 'before' - ? sourceIndex - : sourceIndex + node.value.length - 1; - - check(selector, node, index, rule, sourceIndex); - }); - }); - - if (hasFixed && fixedSelector) { - if (!rule.raws.selector) { - rule.selector = fixedSelector; - } else { - rule.raws.selector.raw = fixedSelector; - } - } - }); - - /** - * @param {string} source - * @param {import('postcss-selector-parser').Combinator} combinator - * @param {number} index - * @param {import('postcss').Node} node - * @param {number} sourceIndex - */ - function check(source, combinator, index, node, sourceIndex) { - opts.locationChecker({ - source, - index, - errTarget: combinator.value, - err: (message) => { - if (opts.fix && opts.fix(combinator)) { - hasFixed = true; - - return; - } - - report({ - message, - node, - index: sourceIndex, - result: opts.result, - ruleName: opts.checkedRuleName, - }); - }, - }); - } -}; diff --git a/lib/rules/selectorListCommaWhitespaceChecker.js b/lib/rules/selectorListCommaWhitespaceChecker.js deleted file mode 100644 index 432252b4eb..0000000000 --- a/lib/rules/selectorListCommaWhitespaceChecker.js +++ /dev/null @@ -1,61 +0,0 @@ -'use strict'; - -const isStandardSyntaxRule = require('../utils/isStandardSyntaxRule'); -const report = require('../utils/report'); -const styleSearch = require('style-search'); - -/** - * @param {{ - * root: import('postcss').Root, - * result: import('stylelint').PostcssResult, - * locationChecker: (opts: { source: string, index: number, err: (msg: string) => void }) => void, - * checkedRuleName: string, - * fix: ((rule: import('postcss').Rule, index: number) => boolean) | null, - * }} opts - * @returns {void} - */ -module.exports = function selectorListCommaWhitespaceChecker(opts) { - opts.root.walkRules((rule) => { - if (!isStandardSyntaxRule(rule)) { - return; - } - - const selector = rule.raws.selector ? rule.raws.selector.raw : rule.selector; - - styleSearch( - { - source: selector, - target: ',', - functionArguments: 'skip', - }, - (match) => { - checkDelimiter(selector, match.startIndex, rule); - }, - ); - }); - - /** - * @param {string} source - * @param {number} index - * @param {import('postcss').Rule} node - */ - function checkDelimiter(source, index, node) { - opts.locationChecker({ - source, - index, - err: (message) => { - if (opts.fix && opts.fix(node, index)) { - return; - } - - report({ - message, - node, - index, - result: opts.result, - ruleName: opts.checkedRuleName, - }); - }, - }); - } -}; diff --git a/lib/rules/string-quotes/README.md b/lib/rules/string-quotes/README.md deleted file mode 100644 index 3b89b74e00..0000000000 --- a/lib/rules/string-quotes/README.md +++ /dev/null @@ -1,132 +0,0 @@ -# string-quotes - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Specify single or double quotes around strings. - - -```css -a[id="foo"] { content: "x"; } -/** ↑ ↑ ↑ ↑ - * These quotes and these quotes */ -``` - -Quotes within comments are ignored. - - -```css -/* "This is fine" */ -/* 'And this is also fine' */ -``` - -Single quotes in a charset @-rule are ignored as using single quotes in this context is incorrect according the [CSS specification](https://www.w3.org/TR/CSS2/syndata.html#x57). - - -```css -@charset "utf-8" -/* fine regardless of configuration */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix most of the problems reported by this rule. - -## Options - -`string`: `"single"|"double"` - -### `"single"` - -Strings _must always_ be wrapped with single quotes. - -The following patterns are considered problems: - - -```css -a { content: "x"; } -``` - - -```css -a[id="foo"] {} -``` - -The following patterns are _not_ considered problems: - - -```css -a { content: 'x'; } -``` - - -```css -a[id='foo'] {} -``` - - -```css -a { content: "x'y'z"; } -``` - -### `"double"` - -Strings _must always_ be wrapped with double quotes. - -The following patterns are considered problems: - - -```css -a { content: 'x'; } -``` - - -```css -a[id='foo'] {} -``` - -The following patterns are _not_ considered problems: - - -```css -a { content: "x"; } -``` - - -```css -a[id="foo"] {} -``` - - -```css -a { content: 'x"y"z'; } -``` - -## Optional secondary options - -### `avoidEscape`: `true|false`, defaults to `true` - -Allows strings to use single-quotes or double-quotes so long as the string contains a quote that would have to be escaped otherwise. - -For example, with `"single", { "avoidEscape" : false }`. - -The following patterns are considered problems: - - -```css -a { content: "x'y'z"; } -``` - - -```css -a[id="foo'bar'baz"] {} -``` - -The following patterns are _not_ considered problems: - - -```css -a { content: 'x'; } -``` - - -```css -a[id='foo'] {} -``` diff --git a/lib/rules/string-quotes/__tests__/index.js b/lib/rules/string-quotes/__tests__/index.js deleted file mode 100644 index 034a1aef8c..0000000000 --- a/lib/rules/string-quotes/__tests__/index.js +++ /dev/null @@ -1,314 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['single'], - fix: true, - accept: [ - { - code: '', - }, - { - code: 'a {}', - }, - { - code: '@import url(foo.css);', - }, - { - code: 'a { color: pink; }', - }, - { - code: "a::before { content: 'foo'; }", - }, - { - code: "a { background: url('foo'); }", - }, - { - code: "a[id='foo'] {}", - }, - { - code: `a::before { content: 'foo"horse"cow'; }`, - description: 'declaration string in strings', - }, - { - code: `@import 'foo"horse"cow.css'`, - description: 'at-rule string in strings', - }, - { - code: `a[foo='foo"horse"cow'] {}`, - description: 'rule string in strings', - }, - { - code: 'a { /* "horse" */ }', - description: 'ignores comment', - }, - { - code: '@charset "utf-8"', - description: 'ignore @charset rules', - }, - { - code: 'a[b=#{c}][d="e"] { }', - description: 'ignore "invalid" selector (see #3130)', - }, - ], - - reject: [ - { - code: 'a::before { content: "foo"; }', - fixed: "a::before { content: 'foo'; }", - message: messages.expected('single'), - line: 1, - column: 22, - }, - { - code: 'a::before\n{\n content: "foo";\n}', - fixed: "a::before\n{\n content: 'foo';\n}", - message: messages.expected('single'), - line: 3, - column: 12, - }, - { - code: 'a[id="foo"] {}', - fixed: "a[id='foo'] {}", - message: messages.expected('single'), - line: 1, - column: 6, - }, - { - code: 'a[ id="foo" ] {}', - fixed: "a[ id='foo' ] {}", - message: messages.expected('single'), - line: 1, - column: 7, - }, - { - code: 'a\n{ background: url("foo"); }', - fixed: "a\n{ background: url('foo'); }", - message: messages.expected('single'), - line: 2, - column: 19, - }, - { - code: '@import "base.css"', - fixed: "@import 'base.css'", - message: messages.expected('single'), - line: 1, - column: 9, - }, - ], -}); - -testRule({ - ruleName, - config: ['double'], - fix: true, - accept: [ - { - code: '', - }, - { - code: 'a {}', - }, - { - code: '@import url(foo.css);', - }, - { - code: 'a { color: pink; }', - }, - { - code: 'a::before { content: "foo"; }', - }, - { - code: 'a { background: url("foo"); }', - }, - { - code: 'a[id="foo"] {}', - }, - { - code: `a::before { content: "foo'horse'cow"; }`, - description: 'declaration string in strings', - }, - { - code: `@import "foo'horse'cow.css"`, - description: 'at-rule string in strings', - }, - { - code: `a[foo="foo'horse'cow"] {}`, - description: 'rule string in strings', - }, - { - code: "a { /* 'horse' */ }", - description: 'ignores comment', - }, - { - code: '@charset "utf-8"', - description: 'ignore @charset rules', - }, - ], - - reject: [ - { - code: "a::before { content: 'foo'; }", - fixed: 'a::before { content: "foo"; }', - message: messages.expected('double'), - line: 1, - column: 22, - }, - { - code: "a::before\n{\n content: 'foo';\n}", - fixed: 'a::before\n{\n content: "foo";\n}', - message: messages.expected('double'), - line: 3, - column: 12, - }, - { - code: "a[id='foo'] {}", - fixed: 'a[id="foo"] {}', - message: messages.expected('double'), - line: 1, - column: 6, - }, - { - code: "a { background: url('foo'); }", - fixed: 'a { background: url("foo"); }', - message: messages.expected('double'), - line: 1, - column: 21, - }, - { - code: "@import 'base.css'", - fixed: '@import "base.css"', - message: messages.expected('double'), - line: 1, - column: 9, - }, - ], -}); - -// No fix: true here because styles which require escaping aren't autofixed, only reported. -testRule({ - ruleName, - config: ['single', { avoidEscape: false }], - reject: [ - { - code: `a::before { content: "foo'horse'cow"; }`, - description: 'declaration string in strings', - message: messages.expected('single'), - line: 1, - column: 22, - }, - { - code: `@import "foo'horse'cow.css";`, - description: 'at-rule string in strings', - message: messages.expected('single'), - line: 1, - column: 9, - }, - { - code: `a[foo="foo'horse'cow"] {}`, - description: 'rule string in strings', - message: messages.expected('single'), - line: 1, - column: 7, - }, - ], -}); - -// No fix: true here because styles which require escaping aren't autofixed, only reported. -testRule({ - ruleName, - config: ['double', { avoidEscape: false }], - reject: [ - { - code: `a::before { content: 'foo"horse"cow'; }`, - description: 'declaration string in strings', - message: messages.expected('double'), - line: 1, - column: 22, - }, - { - code: `@import 'foo"horse"cow.css';`, - description: 'at-rule string in strings', - message: messages.expected('double'), - line: 1, - column: 9, - }, - { - code: `a[foo='foo"horse"cow'] {}`, - description: 'rule string in strings', - message: messages.expected('double'), - line: 1, - column: 7, - }, - ], -}); - -testRule({ - ruleName, - config: ['double'], - customSyntax: 'postcss-scss', - fix: true, - accept: [ - { - code: "a {\n // 'horse'\n}", - description: 'ignores single-line SCSS comment', - }, - { - code: '@charset "utf-8"', - description: 'ignore @charset rules', - }, - ], - - reject: [ - { - code: "a::before {\n // 'horse'\n content: 'thing'; }", - fixed: 'a::before {\n // \'horse\'\n content: "thing"; }', - description: 'pays attention when single-line SCSS comment ends', - message: messages.expected('double'), - line: 3, - column: 12, - }, - { - code: "a::before {\n// one\n// two\n// three\n content: 'thing'; }", - fixed: 'a::before {\n// one\n// two\n// three\n content: "thing"; }', - description: 'accurate position after // comments', - message: messages.expected('double'), - line: 5, - column: 12, - }, - ], -}); - -testRule({ - ruleName, - config: ['double'], - customSyntax: 'postcss-less', - fix: true, - accept: [ - { - code: "a {\n // 'horse'\n}", - description: 'ignores single-line Less comment', - }, - ], - - reject: [ - { - code: "a::before {\n // 'horse'\n content: 'thing'; }", - fixed: 'a::before {\n // \'horse\'\n content: "thing"; }', - description: 'pays attention when single-line Less comment ends', - message: messages.expected('double'), - line: 3, - column: 12, - }, - { - code: "a::before {\n// one\n// two\n// three\n content: 'thing'; }", - fixed: 'a::before {\n// one\n// two\n// three\n content: "thing"; }', - description: 'accurate position after // comments', - message: messages.expected('double'), - line: 5, - column: 12, - }, - ], -}); diff --git a/lib/rules/string-quotes/index.js b/lib/rules/string-quotes/index.js deleted file mode 100644 index 8069699575..0000000000 --- a/lib/rules/string-quotes/index.js +++ /dev/null @@ -1,250 +0,0 @@ -'use strict'; - -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const declarationValueIndex = require('../../utils/declarationValueIndex'); -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 valueParser = require('postcss-value-parser'); -const { isBoolean, assertString } = require('../../utils/validateTypes'); -const { isAtRule } = require('../../utils/typeGuards'); - -const ruleName = 'string-quotes'; - -const messages = ruleMessages(ruleName, { - expected: (q) => `Expected ${q} quotes`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/string-quotes', - fixable: true, - deprecated: true, -}; - -const singleQuote = `'`; -const doubleQuote = `"`; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, secondaryOptions, context) => { - const correctQuote = primary === 'single' ? singleQuote : doubleQuote; - const erroneousQuote = primary === 'single' ? doubleQuote : singleQuote; - - return (root, result) => { - const validOptions = validateOptions( - result, - ruleName, - { - actual: primary, - possible: ['single', 'double'], - }, - { - actual: secondaryOptions, - possible: { - avoidEscape: [isBoolean], - }, - optional: true, - }, - ); - - if (!validOptions) { - return; - } - - const avoidEscape = - secondaryOptions && secondaryOptions.avoidEscape !== undefined - ? secondaryOptions.avoidEscape - : true; - - root.walk((node) => { - switch (node.type) { - case 'atrule': - checkDeclOrAtRule(node, node.params, atRuleParamIndex); - break; - case 'decl': - checkDeclOrAtRule(node, node.value, declarationValueIndex); - break; - case 'rule': - checkRule(node); - break; - } - }); - - /** - * @param {import('postcss').Rule} ruleNode - * @returns {void} - */ - function checkRule(ruleNode) { - if (!isStandardSyntaxRule(ruleNode)) { - return; - } - - if (!ruleNode.selector.includes('[') || !ruleNode.selector.includes('=')) { - return; - } - - /** @type {number[]} */ - const fixPositions = []; - - parseSelector(ruleNode.selector, result, ruleNode, (selectorTree) => { - let selectorFixed = false; - - selectorTree.walkAttributes((attributeNode) => { - if (!attributeNode.quoted) { - return; - } - - if (attributeNode.quoteMark === correctQuote && avoidEscape) { - assertString(attributeNode.value); - const needsCorrectEscape = attributeNode.value.includes(correctQuote); - const needsOtherEscape = attributeNode.value.includes(erroneousQuote); - - if (needsOtherEscape) { - return; - } - - if (needsCorrectEscape) { - if (context.fix) { - selectorFixed = true; - attributeNode.quoteMark = erroneousQuote; - } else { - report({ - message: messages.expected(primary === 'single' ? 'double' : primary), - node: ruleNode, - index: attributeNode.sourceIndex + attributeNode.offsetOf('value'), - result, - ruleName, - }); - } - } - } - - if (attributeNode.quoteMark === erroneousQuote) { - if (avoidEscape) { - assertString(attributeNode.value); - const needsCorrectEscape = attributeNode.value.includes(correctQuote); - const needsOtherEscape = attributeNode.value.includes(erroneousQuote); - - if (needsOtherEscape) { - if (context.fix) { - selectorFixed = true; - attributeNode.quoteMark = correctQuote; - } else { - report({ - message: messages.expected(primary), - node: ruleNode, - index: attributeNode.sourceIndex + attributeNode.offsetOf('value'), - result, - ruleName, - }); - } - - return; - } - - if (needsCorrectEscape) { - return; - } - } - - if (context.fix) { - selectorFixed = true; - attributeNode.quoteMark = correctQuote; - } else { - report({ - message: messages.expected(primary), - node: ruleNode, - index: attributeNode.sourceIndex + attributeNode.offsetOf('value'), - result, - ruleName, - }); - } - } - }); - - if (selectorFixed) { - ruleNode.selector = selectorTree.toString(); - } - }); - - for (const fixIndex of fixPositions) { - ruleNode.selector = replaceQuote(ruleNode.selector, fixIndex, correctQuote); - } - } - - /** - * @template {import('postcss').AtRule | import('postcss').Declaration} T - * @param {T} node - * @param {string} value - * @param {(node: T) => number} getIndex - * @returns {void} - */ - function checkDeclOrAtRule(node, value, getIndex) { - /** @type {number[]} */ - const fixPositions = []; - - // Get out quickly if there are no erroneous quotes - if (!value.includes(erroneousQuote)) { - return; - } - - if (isAtRule(node) && node.name === 'charset') { - // allow @charset rules to have double quotes, in spite of the configuration - // TODO: @charset should always use double-quotes, see https://github.com/stylelint/stylelint/issues/2788 - return; - } - - valueParser(value).walk((valueNode) => { - if (valueNode.type === 'string' && valueNode.quote === erroneousQuote) { - const needsEscape = valueNode.value.includes(correctQuote); - - if (avoidEscape && needsEscape) { - // don't consider this an error - return; - } - - const openIndex = valueNode.sourceIndex; - - // we currently don't fix escapes - if (context.fix && !needsEscape) { - const closeIndex = openIndex + valueNode.value.length + erroneousQuote.length; - - fixPositions.push(openIndex, closeIndex); - } else { - report({ - message: messages.expected(primary), - node, - index: getIndex(node) + openIndex, - result, - ruleName, - }); - } - } - }); - - for (const fixIndex of fixPositions) { - if (isAtRule(node)) { - node.params = replaceQuote(node.params, fixIndex, correctQuote); - } else { - node.value = replaceQuote(node.value, fixIndex, correctQuote); - } - } - } - }; -}; - -/** - * @param {string} string - * @param {number} index - * @param {string} replace - * @returns {string} - */ -function replaceQuote(string, index, replace) { - return string.substring(0, index) + replace + string.substring(index + replace.length); -} - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/unicode-bom/README.md b/lib/rules/unicode-bom/README.md deleted file mode 100644 index 71de472474..0000000000 --- a/lib/rules/unicode-bom/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# unicode-bom - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require or disallow the Unicode Byte Order Mark. - -## Options - -`string`: `"always"|"never"` - -### `"always"` - -The following pattern is considered a problem: - - -```css -a {} -``` - -The following pattern is _not_ considered a problem: - - -```css -U+FEFF -a {} -``` - -### `"never"` - -The following pattern is considered a problem: - - -```css -U+FEFF -a {} -``` - -The following pattern is _not_ considered a problem: - - -```css -a {} -``` diff --git a/lib/rules/unicode-bom/__tests__/index.js b/lib/rules/unicode-bom/__tests__/index.js deleted file mode 100644 index 5dbc060bf1..0000000000 --- a/lib/rules/unicode-bom/__tests__/index.js +++ /dev/null @@ -1,111 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - - accept: [ - { - code: '\uFEFF', - description: 'empty with BOM', - }, - { - code: '\uFEFFa{}', - description: 'with BOM', - }, - ], - - reject: [ - { - code: '', - description: 'empty without BOM', - message: messages.expected, - }, - { - code: 'a{}', - description: 'without BOM', - message: messages.expected, - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - - accept: [ - { - code: '', - description: 'empty without BOM', - }, - { - code: 'a{}', - description: 'without BOM', - }, - ], - - reject: [ - { - code: '\uFEFF', - description: 'empty with BOM', - message: messages.rejected, - }, - { - code: '\uFEFFa{}', - description: 'with BOM', - message: messages.rejected, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-html', - config: ['always'], - - accept: [ - { - code: '', - description: 'without BOM', - }, - { - code: '', - description: 'with BOM', - }, - { - code: ``, - description: 'without BOM', - }, - { - code: ``, - description: 'with BOM', - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-html', - config: ['never'], - - accept: [ - { - code: '', - description: 'without BOM', - }, - { - code: '', - description: 'with BOM', - }, - { - code: ``, - description: 'without BOM', - }, - { - code: ``, - description: 'with BOM', - }, - ], -}); diff --git a/lib/rules/unicode-bom/index.js b/lib/rules/unicode-bom/index.js deleted file mode 100644 index 94063cab90..0000000000 --- a/lib/rules/unicode-bom/index.js +++ /dev/null @@ -1,68 +0,0 @@ -'use strict'; - -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); - -const ruleName = 'unicode-bom'; - -const messages = ruleMessages(ruleName, { - expected: 'Expected Unicode BOM', - rejected: 'Unexpected Unicode BOM', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/unicode-bom', - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never'], - }); - - if ( - !validOptions || - !root.source || - // @ts-expect-error -- TS2339: Property 'inline' does not exist on type 'Source'. - root.source.inline || - // @ts-expect-error -- TS2339: Property 'lang' does not exist on type 'Source'. - root.source.lang === 'object-literal' || - // Ignore HTML documents - // @ts-expect-error -- TS2339: Property 'document' does not exist on type 'Root'. - root.document !== undefined - ) { - return; - } - - const { hasBOM } = root.source.input; - - if (primary === 'always' && !hasBOM) { - report({ - result, - ruleName, - message: messages.expected, - node: root, - line: 1, - }); - } - - if (primary === 'never' && hasBOM) { - report({ - result, - ruleName, - message: messages.rejected, - node: root, - line: 1, - }); - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/unit-case/README.md b/lib/rules/unit-case/README.md deleted file mode 100644 index 48f9b42455..0000000000 --- a/lib/rules/unit-case/README.md +++ /dev/null @@ -1,128 +0,0 @@ -# unit-case - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Specify lowercase or uppercase for units. - - -```css - a { width: 10px; } -/** ↑ - * These units */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix most of the problems reported by this rule. - -## Options - -`string`: `"lower"|"upper"` - -### `"lower"` - -The following patterns are considered problems: - - -```css -a { - width: 10PX; -} -``` - - -```css -a { - width: 10Px; -} -``` - - -```css -a { - width: 10pX; -} -``` - - -```css -a { - width: 10PIXEL; -} -``` - - -```css -a { - width: calc(10PX * 2); -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { - width: 10px; -} -``` - - -```css -a { - width: calc(10px * 2); -} -``` - -### `"upper"` - -The following patterns are considered problems: - - -```css -a { - width: 10px; -} -``` - - -```css -a { - width: 10Px; -} -``` - - -```css -a { - width: 10pX; -} -``` - - -```css -a { - width: 10pixel; -} -``` - - -```css -a { - width: calc(10px * 2); -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { - width: 10PX; -} -``` - - -```css -a { - width: calc(10PX * 2); -} -``` diff --git a/lib/rules/unit-case/__tests__/index.js b/lib/rules/unit-case/__tests__/index.js deleted file mode 100644 index 339bbf4ea8..0000000000 --- a/lib/rules/unit-case/__tests__/index.js +++ /dev/null @@ -1,873 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['lower'], - fix: true, - - accept: [ - { - code: 'a { line-height: 1; }', - }, - { - code: 'a { color: #000; }', - }, - { - code: 'a { font-size: 100%; }', - }, - { - code: 'a { font-size: .5rem; }', - }, - { - code: 'a { font-size: 0.5rem; }', - }, - { - code: 'a { width: 10px; }', - }, - { - 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(10px*2rem); }', - }, - { - code: 'a { background-image: linear-gradient(to right, white calc(100% - 50em), silver); }', - }, - { - code: 'a { transform: rotate(90deg); }', - }, - { - code: 'a { color: green; }', - description: 'ignore keyword', - }, - { - code: 'a { color: green10PX; }', - description: 'ignore unit within keyword', - }, - { - 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: @fs10PX; }', - description: 'ignore preprocessor variable includes unit', - }, - { - code: 'a { font-size: var(--some-fs-10PX); }', - description: 'ignore css variable includes unit', - }, - { - code: 'a { margin: url(13PX); }', - description: 'ignore url function', - }, - { - code: 'a { margin: uRl(13PX); }', - description: 'ignore url function', - }, - { - code: 'a { margin: URL(13PX); }', - description: 'ignore url function', - }, - { - code: 'a { marginPX: 10px; }', - description: 'ignore property include unit', - }, - { - code: 'a10PX { margin: 10px; }', - description: 'ignore type selector include unit', - }, - { - code: '#a10PX { margin: 10px; }', - description: 'ignore class selector include unit', - }, - { - code: '.a10PX { margin: 10px; }', - description: 'ignore class selector include unit', - }, - { - code: 'input[type=10PX] { margin: 10px; }', - description: 'ignore class selector include unit', - }, - { - code: 'a:hover10PX { margin: 10px; }', - description: 'ignore pseudo-class include unit', - }, - { - code: 'a::before10PX { margin: 10px; }', - description: 'ignore pseudo-class include unit', - }, - { - code: 'a { margin: 13xpx; }', - description: 'work with unknown units', - }, - { - code: '@media (min-width: 10px) {}', - description: 'check @media', - }, - { - code: '@media (min-width: 10px)\n and (max-width: 20px) {}', - description: 'check complex @media', - }, - { - code: '@media not screen and (min-width: 100px) {}', - description: 'negation @media', - }, - { - code: "@import 'foo.css'", - description: 'ignore non-media and non-variable at-rule', - }, - ], - - reject: [ - { - code: 'a { width: 10pX; }', - fixed: 'a { width: 10px; }', - message: messages.expected('pX', 'px'), - line: 1, - column: 14, - endLine: 1, - endColumn: 16, - }, - { - code: 'a { width: 10Px; }', - fixed: 'a { width: 10px; }', - message: messages.expected('Px', 'px'), - line: 1, - column: 14, - endLine: 1, - endColumn: 16, - }, - { - code: 'a { width: 10PX; }', - fixed: 'a { width: 10px; }', - message: messages.expected('PX', 'px'), - line: 1, - column: 14, - endLine: 1, - endColumn: 16, - }, - { - code: 'a { margin: 10px 10PX; }', - fixed: 'a { margin: 10px 10px; }', - message: messages.expected('PX', 'px'), - line: 1, - column: 20, - endLine: 1, - endColumn: 22, - }, - { - code: 'a { font-size: .5REM; }', - fixed: 'a { font-size: .5rem; }', - message: messages.expected('REM', 'rem'), - line: 1, - column: 18, - endLine: 1, - endColumn: 21, - }, - { - code: 'a { font-size: 0.5REM; }', - fixed: 'a { font-size: 0.5rem; }', - message: messages.expected('REM', 'rem'), - line: 1, - column: 19, - endLine: 1, - endColumn: 22, - }, - { - code: 'a { margin: calc(10px + 10PX); }', - fixed: 'a { margin: calc(10px + 10px); }', - message: messages.expected('PX', 'px'), - line: 1, - column: 27, - endLine: 1, - endColumn: 29, - }, - { - code: 'a { top: calc(10px*2REM); }', - fixed: 'a { top: calc(10px*2rem); }', - message: messages.expected('REM', 'rem'), - line: 1, - column: 21, - endLine: 1, - endColumn: 24, - }, - { - code: 'a { margin: -webkit-calc(13PX + 10px); }', - fixed: 'a { margin: -webkit-calc(13px + 10px); }', - message: messages.expected('PX', 'px'), - line: 1, - column: 28, - endLine: 1, - endColumn: 30, - }, - { - code: 'a { margin: some-function(13PX + 10px); }', - fixed: 'a { margin: some-function(13px + 10px); }', - message: messages.expected('PX', 'px'), - line: 1, - column: 29, - endLine: 1, - endColumn: 31, - }, - { - code: 'root { --margin: 10PX; }', - fixed: 'root { --margin: 10px; }', - message: messages.expected('PX', 'px'), - line: 1, - column: 20, - endLine: 1, - endColumn: 22, - }, - { - code: 'root { --margin: 10px + 10PX; }', - fixed: 'root { --margin: 10px + 10px; }', - message: messages.expected('PX', 'px'), - line: 1, - column: 27, - endLine: 1, - endColumn: 29, - }, - { - code: 'a { margin: 13XPX; }', - fixed: 'a { margin: 13xpx; }', - message: messages.expected('XPX', 'xpx'), - description: 'work with unknown units', - line: 1, - column: 15, - endLine: 1, - endColumn: 18, - }, - { - code: '@media (min-width: 13PX) {}', - fixed: '@media (min-width: 13px) {}', - message: messages.expected('PX', 'px'), - description: '@media', - line: 1, - column: 22, - endLine: 1, - endColumn: 24, - }, - { - code: '@media (min-width: 10px)\n and (max-width: 20PX) {}', - fixed: '@media (min-width: 10px)\n and (max-width: 20px) {}', - message: messages.expected('PX', 'px'), - description: 'complex @media', - line: 2, - column: 21, - endLine: 2, - endColumn: 23, - }, - { - code: '@media (width < 10.01REM) {}', - fixed: '@media (width < 10.01rem) {}', - message: messages.expected('REM', 'rem'), - description: 'media feature range', - line: 1, - column: 22, - endLine: 1, - endColumn: 25, - }, - { - code: '@media not screen and (min-width: 100PX) {}', - fixed: '@media not screen and (min-width: 100px) {}', - message: messages.expected('PX', 'px'), - description: 'negation @media', - line: 1, - column: 38, - endLine: 1, - endColumn: 40, - }, - { - code: '@media not screen and (min-width: 100PX) { width: 100Px; }', - fixed: '@media not screen and (min-width: 100px) { width: 100px; }', - description: 'negation @media', - warnings: [ - { - message: messages.expected('PX', 'px'), - line: 1, - column: 38, - endLine: 1, - endColumn: 40, - }, - { - message: messages.expected('Px', 'px'), - line: 1, - column: 54, - endLine: 1, - endColumn: 56, - }, - ], - }, - { - code: 'a { background: url("10PX.png") 10PX 20px no-repeat; }', - fixed: 'a { background: url("10PX.png") 10px 20px no-repeat; }', - message: messages.expected('PX', 'px'), - line: 1, - column: 35, - endLine: 1, - endColumn: 37, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-scss', - config: ['lower'], - fix: true, - - accept: [ - { - code: 'a { width: 1em; \n// width: 10PX\n }', - description: 'ignore unit within comments', - }, - { - code: 'a { margin: calc(100% - #{$margin * 2}); }', - description: 'work with interpolation', - }, - ], - - reject: [ - { - code: 'a { margin: 10PX; }', - fixed: 'a { margin: 10px; }', - message: messages.expected('PX', 'px'), - line: 1, - column: 15, - endLine: 1, - endColumn: 17, - }, - { - code: 'a { margin: 10pX; }', - fixed: 'a { margin: 10px; }', - message: messages.expected('pX', 'px'), - line: 1, - column: 15, - endLine: 1, - endColumn: 17, - }, - { - code: 'a { margin: 10Px; }', - fixed: 'a { margin: 10px; }', - message: messages.expected('Px', 'px'), - line: 1, - column: 15, - endLine: 1, - endColumn: 17, - }, - { - code: 'a { margin: 10PX + 10px; }', - fixed: 'a { margin: 10px + 10px; }', - message: messages.expected('PX', 'px'), - line: 1, - column: 15, - endLine: 1, - endColumn: 17, - }, - { - code: 'a { $margin: 10PX; }', - fixed: 'a { $margin: 10px; }', - message: messages.expected('PX', 'px'), - line: 1, - column: 16, - endLine: 1, - endColumn: 18, - }, - { - code: 'a { $margin: 10px + 10PX; }', - fixed: 'a { $margin: 10px + 10px; }', - message: messages.expected('PX', 'px'), - line: 1, - column: 23, - endLine: 1, - endColumn: 25, - }, - { - code: 'a { margin: $margin + 10PX; }', - fixed: 'a { margin: $margin + 10px; }', - message: messages.expected('PX', 'px'), - line: 1, - column: 25, - endLine: 1, - endColumn: 27, - }, - { - code: '$breakpoints: ( small: 767px, medium: 992PX, large: 1200px );', - fixed: '$breakpoints: ( small: 767px, medium: 992px, large: 1200px );', - message: messages.expected('PX', 'px'), - line: 1, - column: 42, - endLine: 1, - endColumn: 44, - }, - { - code: 'a { font: (italic bold 10px/8PX) }', - fixed: 'a { font: (italic bold 10px/8px) }', - message: messages.expected('PX', 'px'), - line: 1, - column: 30, - endLine: 1, - endColumn: 32, - }, - { - code: 'font: 14PX/#{$line-height};', - fixed: 'font: 14px/#{$line-height};', - message: messages.expected('PX', 'px'), - line: 1, - column: 9, - endLine: 1, - endColumn: 11, - }, - { - code: 'a { margin: calc(100% - #{$margin * 2PX}); }', - fixed: 'a { margin: calc(100% - #{$margin * 2px}); }', - message: messages.expected('PX', 'px'), - line: 1, - column: 38, - endLine: 1, - endColumn: 41, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-less', - config: ['lower'], - fix: true, - - accept: [ - { - code: 'a { width: 1em; \n// width: 10PX\n }', - description: 'ignore unit within comments', - }, - ], - - reject: [ - { - code: '@variable: 10PX', - fixed: '@variable: 10px', - message: messages.expected('PX', 'px'), - line: 1, - column: 14, - endLine: 1, - endColumn: 16, - }, - { - code: '@variable: 10pX', - fixed: '@variable: 10px', - message: messages.expected('pX', 'px'), - line: 1, - column: 14, - endLine: 1, - endColumn: 16, - }, - { - code: '@variable: 10Px', - fixed: '@variable: 10px', - message: messages.expected('Px', 'px'), - line: 1, - column: 14, - endLine: 1, - endColumn: 16, - }, - ], -}); - -testRule({ - ruleName, - config: ['upper'], - fix: true, - - accept: [ - { - code: 'a { line-height: 1; }', - }, - { - code: 'a { color: #000; }', - }, - { - code: 'a { font-size: 100%; }', - }, - { - code: 'a { font-size: .5REM; }', - }, - { - code: 'a { font-size: 0.5REM; }', - }, - { - code: 'a { width: 10PX; }', - }, - { - code: 'a { margin: 0 10EM 5REM 2IN; }', - }, - { - code: 'a { background-position: top right, 1EM 5VH; }', - }, - { - code: 'a { top: calc(10EM - 3EM); }', - }, - { - code: 'a { background-image: linear-gradient(to right, white calc(100% - 50EM), silver); }', - }, - { - code: 'a { transform: rotate(90DEG); }', - }, - { - code: 'a { color: green; }', - description: 'ignore keyword', - }, - { - code: 'a { color: green10px; }', - description: 'ignore unit within keyword', - }, - { - 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: @fs10px; }', - description: 'ignore preprocessor variable includes unit', - }, - { - code: 'a { font-size: var(--some-fs-10px); }', - description: 'ignore css variable includes unit', - }, - { - code: 'a { margin: url(13px); }', - description: 'ignore url function', - }, - { - code: 'a { margin10px: 10PX; }', - description: 'ignore property include unit', - }, - { - code: 'a10px { margin: 10PX; }', - description: 'ignore type selector include unit', - }, - { - code: '#a10px { margin: 10PX; }', - description: 'ignore class selector include unit', - }, - { - code: '.a10px { margin: 10PX; }', - description: 'ignore class selector include unit', - }, - { - code: 'input[type=10px] { margin: 10PX; }', - description: 'ignore class selector include unit', - }, - { - code: 'a:hover10px { margin: 10PX; }', - description: 'ignore pseudo-class include unit', - }, - { - code: 'a::before10px { margin: 10PX; }', - description: 'ignore pseudo-class include unit', - }, - { - code: 'a { margin: 13XPX; }', - description: 'work with unknown units', - }, - ], - - reject: [ - { - code: 'a { width: 10pX; }', - fixed: 'a { width: 10PX; }', - message: messages.expected('pX', 'PX'), - line: 1, - column: 14, - endLine: 1, - endColumn: 16, - }, - { - code: 'a { width: 10Px; }', - fixed: 'a { width: 10PX; }', - message: messages.expected('Px', 'PX'), - line: 1, - column: 14, - endLine: 1, - endColumn: 16, - }, - { - code: 'a { width: 10px; }', - fixed: 'a { width: 10PX; }', - message: messages.expected('px', 'PX'), - line: 1, - column: 14, - endLine: 1, - endColumn: 16, - }, - { - code: 'a { font-size: .5rem; }', - fixed: 'a { font-size: .5REM; }', - message: messages.expected('rem', 'REM'), - line: 1, - column: 18, - endLine: 1, - endColumn: 21, - }, - { - code: 'a { font-size: 0.5rem; }', - fixed: 'a { font-size: 0.5REM; }', - message: messages.expected('rem', 'REM'), - line: 1, - column: 19, - endLine: 1, - endColumn: 22, - }, - { - code: 'a { margin: 10PX 10px; }', - fixed: 'a { margin: 10PX 10PX; }', - message: messages.expected('px', 'PX'), - line: 1, - column: 20, - endLine: 1, - endColumn: 22, - }, - { - code: 'a { margin: calc(10PX + 10px); }', - fixed: 'a { margin: calc(10PX + 10PX); }', - message: messages.expected('px', 'PX'), - line: 1, - column: 27, - endLine: 1, - endColumn: 29, - }, - { - code: 'a { margin: -webkit-calc(13px + 10PX); }', - fixed: 'a { margin: -webkit-calc(13PX + 10PX); }', - message: messages.expected('px', 'PX'), - line: 1, - column: 28, - endLine: 1, - endColumn: 30, - }, - { - code: 'a { margin: some-function(13px + 10PX); }', - fixed: 'a { margin: some-function(13PX + 10PX); }', - message: messages.expected('px', 'PX'), - line: 1, - column: 29, - endLine: 1, - endColumn: 31, - }, - { - code: 'root { --margin: 10px; }', - fixed: 'root { --margin: 10PX; }', - message: messages.expected('px', 'PX'), - line: 1, - column: 20, - endLine: 1, - endColumn: 22, - }, - { - code: 'root { --margin: 10PX + 10px; }', - fixed: 'root { --margin: 10PX + 10PX; }', - message: messages.expected('px', 'PX'), - line: 1, - column: 27, - endLine: 1, - endColumn: 29, - }, - { - code: 'a { margin: 13xpx; }', - fixed: 'a { margin: 13XPX; }', - message: messages.expected('xpx', 'XPX'), - description: 'work with unknown units', - line: 1, - column: 15, - endLine: 1, - endColumn: 18, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-scss', - config: ['upper'], - fix: true, - - accept: [ - { - code: 'a { width: 1EM; \n// width: 10px\n }', - description: 'ignore unit within comments', - }, - { - code: 'a { margin: calc(100% - #{$margin * 2}); }', - description: 'work with interpolation', - }, - ], - - reject: [ - { - code: 'a { margin: 10px; }', - fixed: 'a { margin: 10PX; }', - message: messages.expected('px', 'PX'), - line: 1, - column: 15, - endLine: 1, - endColumn: 17, - }, - { - code: 'a { margin: 10pX; }', - fixed: 'a { margin: 10PX; }', - message: messages.expected('pX', 'PX'), - line: 1, - column: 15, - endLine: 1, - endColumn: 17, - }, - { - code: 'a { margin: 10Px; }', - fixed: 'a { margin: 10PX; }', - message: messages.expected('Px', 'PX'), - line: 1, - column: 15, - endLine: 1, - endColumn: 17, - }, - { - code: 'a { margin: 10px + 10PX; }', - fixed: 'a { margin: 10PX + 10PX; }', - message: messages.expected('px', 'PX'), - line: 1, - column: 15, - endLine: 1, - endColumn: 17, - }, - { - code: 'a { $margin: 10px; }', - fixed: 'a { $margin: 10PX; }', - message: messages.expected('px', 'PX'), - line: 1, - column: 16, - endLine: 1, - endColumn: 18, - }, - { - code: 'a { $margin: 10PX + 10px; }', - fixed: 'a { $margin: 10PX + 10PX; }', - message: messages.expected('px', 'PX'), - line: 1, - column: 23, - endLine: 1, - endColumn: 25, - }, - { - code: 'a { margin: $margin + 10px; }', - fixed: 'a { margin: $margin + 10PX; }', - message: messages.expected('px', 'PX'), - line: 1, - column: 25, - endLine: 1, - endColumn: 27, - }, - { - code: '$breakpoints: ( small: 767PX, medium: 992px, large: 1200PX );', - fixed: '$breakpoints: ( small: 767PX, medium: 992PX, large: 1200PX );', - message: messages.expected('px', 'PX'), - line: 1, - column: 42, - endLine: 1, - endColumn: 44, - }, - { - code: 'a { font: (italic bold 10PX/8px) }', - fixed: 'a { font: (italic bold 10PX/8PX) }', - message: messages.expected('px', 'PX'), - line: 1, - column: 30, - endLine: 1, - endColumn: 32, - }, - { - code: 'font: 14px/#{$line-height};', - fixed: 'font: 14PX/#{$line-height};', - message: messages.expected('px', 'PX'), - line: 1, - column: 9, - endLine: 1, - endColumn: 11, - }, - { - code: 'a { margin: calc(100% - #{$margin * 2px}); }', - fixed: 'a { margin: calc(100% - #{$margin * 2PX}); }', - message: messages.expected('px', 'PX'), - line: 1, - column: 38, - endLine: 1, - endColumn: 41, - }, - ], -}); - -testRule({ - ruleName, - customSyntax: 'postcss-less', - config: ['upper'], - fix: true, - - accept: [ - { - code: 'a { width: 1EM; \n// width: 10px\n }', - description: 'ignore unit within comments', - }, - ], - - reject: [ - { - code: '@variable: 10px', - fixed: '@variable: 10PX', - message: messages.expected('px', 'PX'), - line: 1, - column: 14, - endLine: 1, - endColumn: 16, - }, - { - code: '@variable: 10pX', - fixed: '@variable: 10PX', - message: messages.expected('pX', 'PX'), - line: 1, - column: 14, - endLine: 1, - endColumn: 16, - }, - { - code: '@variable: 10Px', - fixed: '@variable: 10PX', - message: messages.expected('Px', 'PX'), - line: 1, - column: 14, - endLine: 1, - endColumn: 16, - }, - ], -}); diff --git a/lib/rules/unit-case/index.js b/lib/rules/unit-case/index.js deleted file mode 100644 index 640383b5b3..0000000000 --- a/lib/rules/unit-case/index.js +++ /dev/null @@ -1,134 +0,0 @@ -'use strict'; - -const atRuleParamIndex = require('../../utils/atRuleParamIndex'); -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const getDimension = require('../../utils/getDimension'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const valueParser = require('postcss-value-parser'); - -const ruleName = 'unit-case'; - -const messages = ruleMessages(ruleName, { - expected: (actual, expected) => `Expected "${actual}" to be "${expected}"`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/unit-case', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['lower', 'upper'], - }); - - if (!validOptions) { - return; - } - - /** - * @template {import('postcss').AtRule | import('postcss').Declaration} T - * @param {T} node - * @param {string} checkedValue - * @param {(node: T) => number} getIndex - * @returns {void} - */ - function check(node, checkedValue, getIndex) { - /** @type {Array<{ index: number, endIndex: number, message: string }>} */ - const problems = []; - - /** - * @param {import('postcss-value-parser').Node} valueNode - * @returns {boolean} - */ - function processValue(valueNode) { - const { number, unit } = getDimension(valueNode); - - if (!number || !unit) return false; - - const expectedUnit = primary === 'lower' ? unit.toLowerCase() : unit.toUpperCase(); - - if (unit === expectedUnit) { - return false; - } - - const index = getIndex(node); - - problems.push({ - index: index + valueNode.sourceIndex + number.length, - endIndex: index + valueNode.sourceEndIndex, - message: messages.expected(unit, expectedUnit), - }); - - return true; - } - - const parsedValue = valueParser(checkedValue).walk((valueNode) => { - // Ignore wrong units within `url` function - let needFix = false; - const value = valueNode.value; - - if (valueNode.type === 'function' && value.toLowerCase() === 'url') { - return false; - } - - if (value.includes('*')) { - value.split('*').some((val) => { - return processValue({ - ...valueNode, - sourceIndex: value.indexOf(val) + val.length + 1, - value: val, - }); - }); - } - - needFix = processValue(valueNode); - - if (needFix && context.fix) { - valueNode.value = primary === 'lower' ? value.toLowerCase() : value.toUpperCase(); - } - }); - - if (problems.length) { - if (context.fix) { - if ('name' in node && node.name === 'media') { - node.params = parsedValue.toString(); - } else if ('value' in node) { - node.value = parsedValue.toString(); - } - } else { - for (const err of problems) { - report({ - index: err.index, - endIndex: err.endIndex, - message: err.message, - node, - result, - ruleName, - }); - } - } - } - } - - root.walkAtRules((atRule) => { - if (!/^media$/i.test(atRule.name) && !('variable' in atRule)) { - return; - } - - check(atRule, atRule.params, atRuleParamIndex); - }); - root.walkDecls((decl) => check(decl, decl.value, declarationValueIndex)); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/value-list-comma-newline-after/README.md b/lib/rules/value-list-comma-newline-after/README.md deleted file mode 100644 index da7e30dba5..0000000000 --- a/lib/rules/value-list-comma-newline-after/README.md +++ /dev/null @@ -1,104 +0,0 @@ -# value-list-comma-newline-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline or disallow whitespace after the commas of value lists. - - -```css -a { background-size: 0, - 0; } ↑ -/** ↑ - * The newline after this comma */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix most of the problems reported by this rule. - -## Options - -`string`: `"always"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a newline after the commas. - -The following patterns are considered problems: - - -```css -a { background-size: 0,0; } -``` - - -```css -a { background-size: 0 - , 0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { background-size: 0, - 0; } -``` - -### `"always-multi-line"` - -There _must always_ be a newline after the commas in multi-line value lists. - -The following patterns are considered problems: - - -```css -a { background-size: 0 - , 0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { background-size: 0, 0; } -``` - - -```css -a { background-size: 0,0; } -``` - - -```css -a { background-size: 0, - 0; } -``` - -### `"never-multi-line"` - -There _must never_ be whitespace after the commas in multi-line value lists. - -The following patterns are considered problems: - - -```css -a { background-size: 0 - , 0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { background-size: 0,0; } -``` - - -```css -a { background-size: 0, 0; } -``` - - -```css -a { background-size: 0 - ,0; } -``` diff --git a/lib/rules/value-list-comma-newline-after/__tests__/index.js b/lib/rules/value-list-comma-newline-after/__tests__/index.js deleted file mode 100644 index fae9087bc9..0000000000 --- a/lib/rules/value-list-comma-newline-after/__tests__/index.js +++ /dev/null @@ -1,224 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a { background-size: 0,\n0; }', - }, - { - code: 'a { background-size: 0,\n\n0; }', - }, - { - code: 'a { background-size: 0 ,\n 0; }', - }, - { - code: 'a { background-size: 0 ,\r\n 0; }', - description: 'CRLF', - }, - { - code: 'a { background-size: 0 ,\r\n\r\n 0; }', - description: 'Double CRLF', - }, - { - code: 'a::before { content: "foo,bar,baz"; }', - description: 'string', - }, - { - code: 'a { transform: translate(1,1); }', - description: 'ignores function', - }, - { - code: '$grid-breakpoints: (\n(xs),\n(sm, 768px)\n) !default;', - description: 'ignores scss maps', - }, - { - code: 'a { background-size: 0, //\n0; }', - description: 'ignores single line comments', - }, - { - code: 'a { background-size: 0, /**/\n0; }', - description: 'ignores multi line comments', - }, - ], - - reject: [ - { - code: 'a { background-size: 0, 0; }', - fixed: 'a { background-size: 0,\n 0; }', - message: messages.expectedAfter(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0, 0; }', - fixed: 'a { background-size: 0,\n 0; }', - message: messages.expectedAfter(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0,\t0; }', - fixed: 'a { background-size: 0,\n\t0; }', - message: messages.expectedAfter(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0, /**/0; }', - fixed: 'a { background-size: 0, /**/\n0; }', - message: messages.expectedAfter(), - description: 'ignores multi line comments', - line: 1, - column: 28, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - fix: true, - - accept: [ - { - code: 'a { background-size: 0,\n0,\n0; }', - }, - { - code: 'a { background-size: 0, //\n0, /**/\n0; }', - description: 'with comments', - }, - { - code: 'a { background-size: 0 ,\n 0,\n0; }', - }, - { - code: 'a { background-size: 0 ,\r\n 0,\r\n0; }', - description: 'CRLF', - }, - { - code: 'a { background-size: 0, 0; }', - description: 'ignores single-line', - }, - { - code: 'a { background-size: 0, 0;\n}', - description: 'ignores single-line list, multi-line block', - }, - { - code: 'a { background-size: 0, 0;\r\n}', - description: 'ignores single-line list, multi-line block with CRLF', - }, - { - code: 'a { background-size: 0, /**/ 0; }', - description: 'ignores single-line list, multi-line block with comment', - }, - ], - - reject: [ - { - code: 'a { background-size: 0,\n0, 0; }', - fixed: 'a { background-size: 0,\n0,\n 0; }', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 2, - }, - { - code: 'a { background-size: 0, //\n0, /**/0; }', - fixed: 'a { background-size: 0, //\n0, /**/\n0; }', - description: 'with comments', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 7, - }, - { - code: 'a { background-size: 0,\n0, 0; }', - fixed: 'a { background-size: 0,\n0,\n 0; }', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 2, - }, - { - code: 'a { background-size: 0,\n0,\t0; }', - fixed: 'a { background-size: 0,\n0,\n\t0; }', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 2, - }, - { - code: 'a { background-size: 0,\r\n0,\t0; }', - fixed: 'a { background-size: 0,\r\n0,\r\n\t0; }', - description: 'CRLF', - message: messages.expectedAfterMultiLine(), - line: 2, - column: 2, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - fix: true, - - accept: [ - { - code: 'a { background-size: 0\n,0\n,0; }', - }, - { - code: 'a { background-size: 0 //\n,0 /**/\n,0; }', - description: 'with comments', - }, - { - code: 'a { background-size: 0\r\n,0\r\n,0; }', - description: 'CRLF', - }, - { - code: 'a { background-size: 0, 0; }', - description: 'ignores single-line', - }, - { - code: 'a { background-size: 0, 0;\n}', - description: 'ignores single-line list, multi-line block', - }, - { - code: 'a { background-size: 0, 0;\r\n}', - description: 'ignores single-line list, multi-line block with CRLF', - }, - ], - - reject: [ - { - code: 'a { background-size: 0\n,0\n, 0; }', - fixed: 'a { background-size: 0\n,0\n,0; }', - message: messages.rejectedAfterMultiLine(), - line: 3, - column: 1, - }, - { - code: 'a { background-size: 0\n,0\n, 0; }', - fixed: 'a { background-size: 0\n,0\n,0; }', - message: messages.rejectedAfterMultiLine(), - line: 3, - column: 1, - }, - { - code: 'a { background-size: 0\r\n,0\r\n, 0; }', - fixed: 'a { background-size: 0\r\n,0\r\n,0; }', - description: 'CRLF', - message: messages.rejectedAfterMultiLine(), - line: 3, - column: 1, - }, - { - code: 'a { background-size: 0\n,0\n,\t0; }', - fixed: 'a { background-size: 0\n,0\n,0; }', - message: messages.rejectedAfterMultiLine(), - line: 3, - column: 1, - }, - ], -}); diff --git a/lib/rules/value-list-comma-newline-after/index.js b/lib/rules/value-list-comma-newline-after/index.js deleted file mode 100644 index 87dcb697a6..0000000000 --- a/lib/rules/value-list-comma-newline-after/index.js +++ /dev/null @@ -1,104 +0,0 @@ -'use strict'; - -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const getDeclarationValue = require('../../utils/getDeclarationValue'); -const ruleMessages = require('../../utils/ruleMessages'); -const setDeclarationValue = require('../../utils/setDeclarationValue'); -const validateOptions = require('../../utils/validateOptions'); -const valueListCommaWhitespaceChecker = require('../valueListCommaWhitespaceChecker'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'value-list-comma-newline-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected newline after ","', - expectedAfterMultiLine: () => 'Expected newline after "," in a multi-line list', - rejectedAfterMultiLine: () => 'Unexpected whitespace after "," in a multi-line list', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/value-list-comma-newline-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('newline', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'always-multi-line', 'never-multi-line'], - }); - - if (!validOptions) { - return; - } - - /** @type {Map | undefined} */ - let fixData; - - valueListCommaWhitespaceChecker({ - root, - result, - locationChecker: checker.afterOneOnly, - checkedRuleName: ruleName, - fix: context.fix - ? (declNode, index) => { - const valueIndex = declarationValueIndex(declNode); - - if (index <= valueIndex) { - return false; - } - - fixData = fixData || new Map(); - const commaIndices = fixData.get(declNode) || []; - - commaIndices.push(index); - fixData.set(declNode, commaIndices); - - return true; - } - : null, - determineIndex: (declString, match) => { - const nextChars = declString.substring(match.endIndex, declString.length); - - // If there's a // comment, that means there has to be a newline - // ending the comment so we're fine - if (/^[ \t]*\/\//.test(nextChars)) { - return false; - } - - // If there are spaces and then a comment begins, look for the newline - return /^[ \t]*\/\*/.test(nextChars) - ? declString.indexOf('*/', match.endIndex) + 1 - : match.startIndex; - }, - }); - - if (fixData) { - for (const [decl, commaIndices] of fixData.entries()) { - for (const index of commaIndices.sort((a, b) => a - b).reverse()) { - const value = getDeclarationValue(decl); - const valueIndex = index - declarationValueIndex(decl); - const beforeValue = value.slice(0, valueIndex + 1); - let afterValue = value.slice(valueIndex + 1); - - if (primary.startsWith('always')) { - afterValue = context.newline + afterValue; - } else if (primary.startsWith('never-multi-line')) { - afterValue = afterValue.replace(/^\s*/, ''); - } - - setDeclarationValue(decl, beforeValue + afterValue); - } - } - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/value-list-comma-newline-before/README.md b/lib/rules/value-list-comma-newline-before/README.md deleted file mode 100644 index 4c6cdbd183..0000000000 --- a/lib/rules/value-list-comma-newline-before/README.md +++ /dev/null @@ -1,102 +0,0 @@ -# value-list-comma-newline-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a newline or disallow whitespace before the commas of value lists. - - -```css - a { background-size: 0 - , 0; } -/** ↑ - * The newline before this comma */ -``` - -## Options - -`string`: `"always"|"always-multi-line"|"never-multi-line"` - -### `"always"` - -There _must always_ be a newline before the commas. - -The following patterns are considered problems: - - -```css -a { background-size: 0,0; } -``` - - -```css -a { background-size: 0, - 0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { background-size: 0 - , 0; } -``` - -### `"always-multi-line"` - -There _must always_ be a newline before the commas in multi-line value lists. - -The following patterns are considered problems: - - -```css -a { background-size: 0, - 0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { background-size: 0, 0; } -``` - - -```css -a { background-size: 0,0; } -``` - - -```css -a { background-size: 0 - , 0; } -``` - -### `"never-multi-line"` - -There _must never_ be whitespace before the commas in multi-line value lists. - -The following patterns are considered problems: - - -```css -a { background-size: 0 - , 0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { background-size: 0,0; } -``` - - -```css -a { background-size: 0, 0; } -``` - - -```css -a { background-size: 0, - 0; } -``` diff --git a/lib/rules/value-list-comma-newline-before/__tests__/index.js b/lib/rules/value-list-comma-newline-before/__tests__/index.js deleted file mode 100644 index 2f45a1ba0b..0000000000 --- a/lib/rules/value-list-comma-newline-before/__tests__/index.js +++ /dev/null @@ -1,181 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - - accept: [ - { - code: 'a { background-size: 0\n,0\n,0; }', - }, - { - code: 'a { background-size: 0\n\n,0\n\n,0; }', - }, - { - code: 'a { background-size: 0\n, 0\n,\t0; }', - }, - { - code: 'a { background-size: 0\r\n, 0\r\n,\t0; }', - description: 'CRLF', - }, - { - code: 'a { background-size: 0\r\n\r\n, 0\r\n,\t0; }', - description: 'Double CRLF', - }, - { - code: 'a { background-size: 0\n ,0\n,0; }', - description: 'indentation after the newline before the comma', - }, - { - code: 'a { background-size: 0\n\t\t,0\n,0; }', - description: 'indentation after the newline before the comma', - }, - { - code: 'a { background-size: 0\r\n\t\t,0\r\n,0; }', - description: 'indentation after the CRLF before the comma', - }, - { - code: 'a::before { content: "foo,bar,baz"; }', - description: 'string', - }, - { - code: 'a { transform: translate(1,1); }', - description: 'function arguments', - }, - ], - - reject: [ - { - code: 'a { background-size: 0, 0; }', - message: messages.expectedBefore(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0 , 0; }', - message: messages.expectedBefore(), - line: 1, - column: 24, - }, - { - code: 'a { background-size: 0 , 0; }', - message: messages.expectedBefore(), - line: 1, - column: 25, - }, - { - code: 'a { background-size: 0\t, 0; }', - message: messages.expectedBefore(), - line: 1, - column: 24, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-multi-line'], - - accept: [ - { - code: 'a { background-size: 0\n,0\n,0; }', - }, - { - code: 'a { background-size: 0\n, 0\n,\t0; }', - }, - { - code: 'a { background-size: 0\r\n, 0\r\n,\t0; }', - description: 'CRLF', - }, - { - code: 'a { background-size: 0, 0; }', - description: 'ignores single-line', - }, - { - code: 'a { background-size: 0, 0;\n}', - description: 'ignores single-line list, multi-line block', - }, - { - code: 'a { background-size: 0, 0;\r\n}', - description: 'ignores single-line list, multi-line block with CRLF', - }, - ], - - reject: [ - { - code: 'a { background-size: 0\n, 0, 0; }', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 4, - }, - { - code: 'a { background-size: 0\n, 0 , 0; }', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 5, - }, - { - code: 'a { background-size: 0\r\n, 0 , 0; }', - description: 'CRLF', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 5, - }, - { - code: 'a { background-size: 0\n, 0\t, 0; }', - message: messages.expectedBeforeMultiLine(), - line: 2, - column: 5, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-multi-line'], - - accept: [ - { - code: 'a { background-size: 0,\n0,\n0; }', - }, - { - code: 'a { background-size: 0 ,0; }', - description: 'ignores single-line', - }, - { - code: 'a { background-size: 0 ,0;\n}', - description: 'ignores single-line list, multi-line block', - }, - ], - - reject: [ - { - code: 'a { background-size: 0,\n0\n, 0; }', - message: messages.rejectedBeforeMultiLine(), - line: 3, - column: 1, - }, - { - code: 'a { background-size: 0,\r\n0\r\n, 0; }', - description: 'CRLF', - message: messages.rejectedBeforeMultiLine(), - line: 3, - column: 1, - }, - { - code: 'a { background-size: 0\n,\t0,\n0; }', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 1, - }, - { - code: 'a { background-size: 0\r\n,\t0,\r\n0; }', - description: 'CRLF', - message: messages.rejectedBeforeMultiLine(), - line: 2, - column: 1, - }, - ], -}); diff --git a/lib/rules/value-list-comma-newline-before/index.js b/lib/rules/value-list-comma-newline-before/index.js deleted file mode 100644 index 1285b33cc7..0000000000 --- a/lib/rules/value-list-comma-newline-before/index.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -const ruleMessages = require('../../utils/ruleMessages'); -const validateOptions = require('../../utils/validateOptions'); -const valueListCommaWhitespaceChecker = require('../valueListCommaWhitespaceChecker'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'value-list-comma-newline-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected newline before ","', - expectedBeforeMultiLine: () => 'Expected newline before "," in a multi-line list', - rejectedBeforeMultiLine: () => 'Unexpected whitespace before "," in a multi-line list', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/value-list-comma-newline-before', - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary) => { - const checker = whitespaceChecker('newline', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'always-multi-line', 'never-multi-line'], - }); - - if (!validOptions) { - return; - } - - valueListCommaWhitespaceChecker({ - root, - result, - locationChecker: checker.beforeAllowingIndentation, - checkedRuleName: ruleName, - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/value-list-comma-space-after/README.md b/lib/rules/value-list-comma-space-after/README.md deleted file mode 100644 index e7df5b9498..0000000000 --- a/lib/rules/value-list-comma-space-after/README.md +++ /dev/null @@ -1,138 +0,0 @@ -# value-list-comma-space-after - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace after the commas of value lists. - - -```css -a { background-size: 0, 0; } -/** ↑ - * The space after this comma */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix most of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"|"always-single-line"|"never-single-line"` - -### `"always"` - -There _must always_ be a single space after the commas. - -The following patterns are considered problems: - - -```css -a { background-size: 0,0; } -``` - - -```css -a { background-size: 0 - , 0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { background-size: 0, 0; } -``` - - -```css -a { background-size: 0 - , 0; } -``` - -### `"never"` - -There _must never_ be whitespace after the commas. - -The following patterns are considered problems: - - -```css -a { background-size: 0, 0; } -``` - - -```css -a { background-size: 0 , - 0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { background-size: 0,0; } -``` - - -```css -a { background-size: 0 - ,0; } -``` - -### `"always-single-line"` - -There _must always_ be a single space after the commas in single-line value lists. - -The following patterns are considered problems: - - -```css -a { background-size: 0,0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { background-size: 0, 0; } -``` - - -```css -a { background-size: 0 - , 0; } -``` - - -```css -a { background-size: 0 - ,0; } -``` - -### `"never-single-line"` - -There _must never_ be whitespace after the commas in single-line value lists. - -The following patterns are considered problems: - - -```css -a { background-size: 0, 0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { background-size: 0,0; } -``` - - -```css -a { background-size: 0 - ,0; } -``` - - -```css -a { background-size: 0 - , 0; } -``` diff --git a/lib/rules/value-list-comma-space-after/__tests__/index.js b/lib/rules/value-list-comma-space-after/__tests__/index.js deleted file mode 100644 index f5511b5352..0000000000 --- a/lib/rules/value-list-comma-space-after/__tests__/index.js +++ /dev/null @@ -1,411 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a { background-size: 0 , 0; }', - }, - { - code: 'a { background-size: 0, 0; }', - }, - { - code: 'a::before { content: "foo,bar,baz"; }', - description: 'strings', - }, - { - code: 'a { transform: translate(1,1); }', - description: 'function arguments', - }, - ], - - reject: [ - { - code: 'a { background-size: 0,0; }', - fixed: 'a { background-size: 0, 0; }', - message: messages.expectedAfter(), - line: 1, - column: 23, - }, - { - code: 'a { background-size:\n\t0, 0; }', - fixed: 'a { background-size:\n\t0, 0; }', - message: messages.expectedAfter(), - line: 2, - column: 3, - }, - { - code: 'a { background-size: 0,\n0; }', - fixed: 'a { background-size: 0, 0; }', - message: messages.expectedAfter(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0,\r\n0; }', - fixed: 'a { background-size: 0, 0; }', - description: 'CRLF', - message: messages.expectedAfter(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0,\t0; }', - fixed: 'a { background-size: 0, 0; }', - message: messages.expectedAfter(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0,/*1*/0; }', - fixed: 'a { background-size: 0, /*1*/0; }', - message: messages.expectedAfter(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0,0,0,0; }', - fixed: 'a { background-size: 0, 0, 0, 0; }', - warnings: [ - { - message: messages.expectedAfter(), - line: 1, - column: 23, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 25, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 27, - }, - ], - }, - { - code: ':root { --variable: 0,0; }', - fixed: ':root { --variable: 0, 0; }', - message: messages.expectedAfter(), - line: 1, - column: 22, - }, - { - code: 'a { pr,op: 0,0; }', - fixed: 'a { pr,op: 0, 0; }', - description: 'edge case', - warnings: [ - { - message: messages.expectedAfter(), - line: 1, - column: 7, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 13, - }, - ], - }, - { - code: 'a{b: 0,0,0,0,0,0,0,0; }', - fixed: 'a{b: 0, 0, 0, 0, 0, 0, 0, 0; }', - warnings: [ - { - message: messages.expectedAfter(), - line: 1, - column: 7, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 9, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 11, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 13, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 15, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 17, - }, - { - message: messages.expectedAfter(), - line: 1, - column: 19, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a { background-size: 0 ,0; }', - }, - { - code: 'a { background-size: 0,0; }', - }, - { - code: 'a::before { content: "foo, bar, baz"; }', - description: 'strings', - }, - { - code: 'a { transform: translate(1, 1); }', - description: 'function arguments', - }, - ], - - reject: [ - { - code: 'a { background-size: 0, 0; }', - fixed: 'a { background-size: 0,0; }', - message: messages.rejectedAfter(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0, 0; }', - fixed: 'a { background-size: 0,0; }', - message: messages.rejectedAfter(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0,\n0; }', - fixed: 'a { background-size: 0,0; }', - message: messages.rejectedAfter(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0,\r\n0; }', - fixed: 'a { background-size: 0,0; }', - description: 'CRLF', - message: messages.rejectedAfter(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0,\t0; }', - fixed: 'a { background-size: 0,0; }', - message: messages.rejectedAfter(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0, /*1*/ 0; }', - fixed: 'a { background-size: 0,/*1*/ 0; }', - message: messages.rejectedAfter(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0, 0, 0, 0 ; }', - fixed: 'a { background-size: 0,0,0,0 ; }', - warnings: [ - { - message: messages.rejectedAfter(), - line: 1, - column: 23, - }, - { - message: messages.rejectedAfter(), - line: 1, - column: 26, - }, - { - message: messages.rejectedAfter(), - line: 1, - column: 29, - }, - ], - }, - { - code: ':root { --variable: 0, 0; }', - fixed: ':root { --variable: 0,0; }', - message: messages.rejectedAfter(), - line: 1, - column: 22, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: 'a { background-size: 0 , 0; }', - }, - { - code: 'a { background-size: 0, 0; }', - }, - { - code: 'a { background-size: 0, 0;\n}', - description: 'single-line list, multi-line block', - }, - { - code: 'a { background-size: 0, 0;\r\n}', - description: 'single-line list, multi-line block with CRLF', - }, - { - code: 'a { background-size: 0\n,0}', - description: 'ignores multi-line', - }, - { - code: 'a { background-size: 0\r\n,0}', - description: 'ignores multi-line with CRLF', - }, - { - code: 'a::before { content: "foo,bar,baz"; }', - description: 'strings', - }, - { - code: 'a { transform: translate(1,1); }', - description: 'function arguments', - }, - ], - - reject: [ - { - code: 'a { background-size: 0,0; }', - fixed: 'a { background-size: 0, 0; }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0,0;\n}', - fixed: 'a { background-size: 0, 0;\n}', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0,0;\r\n}', - fixed: 'a { background-size: 0, 0;\r\n}', - description: 'CRLF', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0, 0; }', - fixed: 'a { background-size: 0, 0; }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0,\t0; }', - fixed: 'a { background-size: 0, 0; }', - message: messages.expectedAfterSingleLine(), - line: 1, - column: 23, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - fix: true, - - accept: [ - { - code: 'a { background-size: 0 ,0; }', - }, - { - code: 'a { background-size: 0,0; }', - }, - { - code: 'a { background-size: 0,0;\n}', - description: 'single-line list, multi-line block', - }, - { - code: 'a { background-size: 0,0;\r\n}', - description: 'single-line list, multi-line block with CRLF', - }, - { - code: 'a { background-size: 0\n, 0}', - description: 'ignores multi-line values', - }, - { - code: 'a { background-size: 0\r\n, 0}', - description: 'ignores multi-line values with CRLF', - }, - { - code: 'a::before { content: "foo, bar, baz"; }', - description: 'strings', - }, - { - code: 'a { transform: translate(1, 1); }', - description: 'function arguments', - }, - ], - - reject: [ - { - code: 'a { background-size: 0, 0; }', - fixed: 'a { background-size: 0,0; }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0, 0;\n}', - fixed: 'a { background-size: 0,0;\n}', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0, 0;\r\n}', - fixed: 'a { background-size: 0,0;\r\n}', - description: 'CRLF', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0, 0; }', - fixed: 'a { background-size: 0,0; }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0,\t0; }', - fixed: 'a { background-size: 0,0; }', - message: messages.rejectedAfterSingleLine(), - line: 1, - column: 23, - }, - ], -}); diff --git a/lib/rules/value-list-comma-space-after/index.js b/lib/rules/value-list-comma-space-after/index.js deleted file mode 100644 index 8674a4d202..0000000000 --- a/lib/rules/value-list-comma-space-after/index.js +++ /dev/null @@ -1,91 +0,0 @@ -'use strict'; - -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const getDeclarationValue = require('../../utils/getDeclarationValue'); -const ruleMessages = require('../../utils/ruleMessages'); -const setDeclarationValue = require('../../utils/setDeclarationValue'); -const validateOptions = require('../../utils/validateOptions'); -const valueListCommaWhitespaceChecker = require('../valueListCommaWhitespaceChecker'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'value-list-comma-space-after'; - -const messages = ruleMessages(ruleName, { - expectedAfter: () => 'Expected single space after ","', - rejectedAfter: () => 'Unexpected whitespace after ","', - expectedAfterSingleLine: () => 'Expected single space after "," in a single-line list', - rejectedAfterSingleLine: () => 'Unexpected whitespace after "," in a single-line list', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/value-list-comma-space-after', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never', 'always-single-line', 'never-single-line'], - }); - - if (!validOptions) { - return; - } - - /** @type {Map | undefined} */ - let fixData; - - valueListCommaWhitespaceChecker({ - root, - result, - locationChecker: checker.after, - checkedRuleName: ruleName, - fix: context.fix - ? (declNode, index) => { - const valueIndex = declarationValueIndex(declNode); - - if (index <= valueIndex) { - return false; - } - - fixData = fixData || new Map(); - const commaIndices = fixData.get(declNode) || []; - - commaIndices.push(index); - fixData.set(declNode, commaIndices); - - return true; - } - : null, - }); - - if (fixData) { - for (const [decl, commaIndices] of fixData.entries()) { - for (const index of commaIndices.sort((a, b) => b - a)) { - const value = getDeclarationValue(decl); - const valueIndex = index - declarationValueIndex(decl); - const beforeValue = value.slice(0, valueIndex + 1); - let afterValue = value.slice(valueIndex + 1); - - if (primary.startsWith('always')) { - afterValue = afterValue.replace(/^\s*/, ' '); - } else if (primary.startsWith('never')) { - afterValue = afterValue.replace(/^\s*/, ''); - } - - setDeclarationValue(decl, beforeValue + afterValue); - } - } - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/value-list-comma-space-before/README.md b/lib/rules/value-list-comma-space-before/README.md deleted file mode 100644 index 376b0ebeea..0000000000 --- a/lib/rules/value-list-comma-space-before/README.md +++ /dev/null @@ -1,138 +0,0 @@ -# value-list-comma-space-before - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Require a single space or disallow whitespace before the commas of value lists. - - -```css -a { background-size: 0 ,0; } -/** ↑ - * The space before this comma */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix most of the problems reported by this rule. - -## Options - -`string`: `"always"|"never"|"always-single-line"|"never-single-line"` - -### `"always"` - -There _must always_ be a single space before the commas. - -The following patterns are considered problems: - - -```css -a { background-size: 0,0; } -``` - - -```css -a { background-size: 0 - , 0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { background-size: 0 ,0; } -``` - - -```css -a { background-size: 0 , - 0; } -``` - -### `"never"` - -There _must never_ be whitespace before the commas. - -The following patterns are considered problems: - - -```css -a { background-size: 0 ,0; } -``` - - -```css -a { background-size: 0 , - 0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { background-size: 0,0; } -``` - - -```css -a { background-size: 0, - 0; } -``` - -### `"always-single-line"` - -There _must always_ be a single space before the commas in single-line value lists. - -The following patterns are considered problems: - - -```css -a { background-size: 0,0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { background-size: 0 ,0; } -``` - - -```css -a { background-size: 0 , - 0; } -``` - - -```css -a { background-size: 0 - , 0; } -``` - -### `"never-single-line"` - -There _must never_ be whitespace before the commas in single-line value lists. - -The following patterns are considered problems: - - -```css -a { background-size: 0 ,0; } -``` - -The following patterns are _not_ considered problems: - - -```css -a { background-size: 0,0; } -``` - - -```css -a { background-size: 0, - 0; } -``` - - -```css -a { background-size: 0 , - 0; } -``` diff --git a/lib/rules/value-list-comma-space-before/__tests__/index.js b/lib/rules/value-list-comma-space-before/__tests__/index.js deleted file mode 100644 index 2dfbc93cfc..0000000000 --- a/lib/rules/value-list-comma-space-before/__tests__/index.js +++ /dev/null @@ -1,340 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: ['always'], - fix: true, - - accept: [ - { - code: 'a { background-size: 0 , 0; }', - }, - { - code: 'a { background-size: 0 ,0; }', - }, - { - code: 'a::before { content: "foo,bar,baz"; }', - description: 'strings', - }, - { - code: 'a { transform: translate(1,1); }', - description: 'function arguments', - }, - ], - - reject: [ - { - code: 'a { background-size: 0, 0; }', - fixed: 'a { background-size: 0 , 0; }', - message: messages.expectedBefore(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0 , 0; }', - fixed: 'a { background-size: 0 , 0; }', - message: messages.expectedBefore(), - line: 1, - column: 25, - }, - { - code: 'a { background-size: 0\n, 0; }', - fixed: 'a { background-size: 0 , 0; }', - message: messages.expectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a { background-size: 0\r\n, 0; }', - fixed: 'a { background-size: 0 , 0; }', - description: 'CRLF', - message: messages.expectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a { background-size: 0\t, 0; }', - fixed: 'a { background-size: 0 , 0; }', - message: messages.expectedBefore(), - line: 1, - column: 24, - }, - { - code: 'a { background-size: 0/*comment*/, 0; }', - fixed: 'a { background-size: 0/*comment*/ , 0; }', - description: 'comment', - message: messages.expectedBefore(), - line: 1, - column: 34, - }, - { - code: 'a{b: 0,0,0,0,0,0,0,0; }', - fixed: 'a{b: 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0; }', - warnings: [ - { - message: messages.expectedBefore(), - line: 1, - column: 7, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 9, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 11, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 13, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 15, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 17, - }, - { - message: messages.expectedBefore(), - line: 1, - column: 19, - }, - ], - }, - ], -}); - -testRule({ - ruleName, - config: ['never'], - fix: true, - - accept: [ - { - code: 'a { background-size: 0, 0; }', - }, - { - code: 'a { background-size: 0,0; }', - }, - { - code: 'a::before { content: "foo ,bar ,baz"; }', - description: 'strings', - }, - { - code: 'a { transform: translate(1 ,1); }', - description: 'function arguments', - }, - ], - - reject: [ - { - code: 'a { background-size: 0 , 0; }', - fixed: 'a { background-size: 0, 0; }', - message: messages.rejectedBefore(), - line: 1, - column: 24, - }, - { - code: 'a { background-size: 0 , 0; }', - fixed: 'a { background-size: 0, 0; }', - message: messages.rejectedBefore(), - line: 1, - column: 25, - }, - { - code: 'a { background-size: 0\n, 0; }', - fixed: 'a { background-size: 0, 0; }', - message: messages.rejectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a { background-size: 0\r\n, 0; }', - fixed: 'a { background-size: 0, 0; }', - description: 'CRLF', - message: messages.rejectedBefore(), - line: 2, - column: 1, - }, - { - code: 'a { background-size: 0\t, 0; }', - fixed: 'a { background-size: 0, 0; }', - message: messages.rejectedBefore(), - line: 1, - column: 24, - }, - { - code: 'a { background-size: 0 /*comment*/ , 0; }', - fixed: 'a { background-size: 0 /*comment*/, 0; }', - description: 'comment', - message: messages.rejectedBefore(), - line: 1, - column: 36, - }, - ], -}); - -testRule({ - ruleName, - config: ['always-single-line'], - fix: true, - - accept: [ - { - code: 'a { background-size: 0 , 0; }', - }, - { - code: 'a { background-size: 0 ,0; }', - }, - { - code: 'a { background-size: 0 ,0;\n}', - description: 'single-line list, multi-line block', - }, - { - code: 'a { background-size: 0 ,0;\r\n}', - description: 'single-line list, multi-line block with CRLF', - }, - { - code: 'a { background-size: 0,\n0; }', - description: 'ignores multi-line list', - }, - { - code: 'a { background-size: 0,\r\n0; }', - description: 'ignores multi-line list with CRLF', - }, - { - code: 'a::before { content: "foo,bar,baz"; }', - description: 'strings', - }, - { - code: 'a { transform: translate(1,1); }', - description: 'function arguments', - }, - ], - - reject: [ - { - code: 'a { background-size: 0, 0; }', - fixed: 'a { background-size: 0 , 0; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0, 0;\n}', - fixed: 'a { background-size: 0 , 0;\n}', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0, 0;\r\n}', - fixed: 'a { background-size: 0 , 0;\r\n}', - description: 'CRLF', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 23, - }, - { - code: 'a { background-size: 0 , 0; }', - fixed: 'a { background-size: 0 , 0; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 25, - }, - { - code: 'a { background-size: 0\t, 0; }', - fixed: 'a { background-size: 0 , 0; }', - message: messages.expectedBeforeSingleLine(), - line: 1, - column: 24, - }, - ], -}); - -testRule({ - ruleName, - config: ['never-single-line'], - fix: true, - - accept: [ - { - code: 'a { background-size: 0, 0; }', - }, - { - code: 'a { background-size: 0,0; }', - }, - { - code: 'a { background-size: 0,0;\n}', - description: 'single-line list, multi-line block', - }, - { - code: 'a { background-size: 0,0;\r\n}', - description: 'single-line list, multi-line block with CRLF', - }, - { - code: 'a { background-size: 0 ,\n0; }', - description: 'ignores multi-line list', - }, - { - code: 'a { background-size: 0 ,\r\n0; }', - description: 'ignores multi-line list with CRLF', - }, - { - code: 'a::before { content: "foo ,bar ,baz"; }', - description: 'strings', - }, - { - code: 'a { transform: translate(1 ,1); }', - description: 'function arguments', - }, - ], - - reject: [ - { - code: 'a { background-size: 0 , 0; }', - fixed: 'a { background-size: 0, 0; }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 24, - }, - { - code: 'a { background-size: 0 , 0;\n}', - fixed: 'a { background-size: 0, 0;\n}', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 24, - }, - { - code: 'a { background-size: 0 , 0;\r\n}', - fixed: 'a { background-size: 0, 0;\r\n}', - description: 'CRLF', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 24, - }, - { - code: 'a { background-size: 0 , 0; }', - fixed: 'a { background-size: 0, 0; }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 25, - }, - { - code: 'a { background-size: 0\t, 0; }', - fixed: 'a { background-size: 0, 0; }', - message: messages.rejectedBeforeSingleLine(), - line: 1, - column: 24, - }, - ], -}); diff --git a/lib/rules/value-list-comma-space-before/index.js b/lib/rules/value-list-comma-space-before/index.js deleted file mode 100644 index 46ff6c50a5..0000000000 --- a/lib/rules/value-list-comma-space-before/index.js +++ /dev/null @@ -1,91 +0,0 @@ -'use strict'; - -const declarationValueIndex = require('../../utils/declarationValueIndex'); -const getDeclarationValue = require('../../utils/getDeclarationValue'); -const ruleMessages = require('../../utils/ruleMessages'); -const setDeclarationValue = require('../../utils/setDeclarationValue'); -const validateOptions = require('../../utils/validateOptions'); -const valueListCommaWhitespaceChecker = require('../valueListCommaWhitespaceChecker'); -const whitespaceChecker = require('../../utils/whitespaceChecker'); - -const ruleName = 'value-list-comma-space-before'; - -const messages = ruleMessages(ruleName, { - expectedBefore: () => 'Expected single space before ","', - rejectedBefore: () => 'Unexpected whitespace before ","', - expectedBeforeSingleLine: () => 'Unexpected whitespace before "," in a single-line list', - rejectedBeforeSingleLine: () => 'Unexpected whitespace before "," in a single-line list', -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/value-list-comma-space-before', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const checker = whitespaceChecker('space', primary, messages); - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: ['always', 'never', 'always-single-line', 'never-single-line'], - }); - - if (!validOptions) { - return; - } - - /** @type {Map | undefined} */ - let fixData; - - valueListCommaWhitespaceChecker({ - root, - result, - locationChecker: checker.before, - checkedRuleName: ruleName, - fix: context.fix - ? (declNode, index) => { - const valueIndex = declarationValueIndex(declNode); - - if (index <= valueIndex) { - return false; - } - - fixData = fixData || new Map(); - const commaIndices = fixData.get(declNode) || []; - - commaIndices.push(index); - fixData.set(declNode, commaIndices); - - return true; - } - : null, - }); - - if (fixData) { - for (const [decl, commaIndices] of fixData.entries()) { - for (const index of commaIndices.sort((a, b) => b - a)) { - const value = getDeclarationValue(decl); - const valueIndex = index - declarationValueIndex(decl); - let beforeValue = value.slice(0, valueIndex); - const afterValue = value.slice(valueIndex); - - if (primary.startsWith('always')) { - beforeValue = beforeValue.replace(/\s*$/, ' '); - } else if (primary.startsWith('never')) { - beforeValue = beforeValue.replace(/\s*$/, ''); - } - - setDeclarationValue(decl, beforeValue + afterValue); - } - } - } - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/value-list-max-empty-lines/README.md b/lib/rules/value-list-max-empty-lines/README.md deleted file mode 100644 index df9a490ef8..0000000000 --- a/lib/rules/value-list-max-empty-lines/README.md +++ /dev/null @@ -1,123 +0,0 @@ -# value-list-max-empty-lines - -> **Warning** This rule is deprecated and will be removed in the future. See [the migration guide](../../../docs/migration-guide/to-15.md). - -Limit the number of adjacent empty lines within value lists. - - -```css -a { - box-shadow: - inset 0 2px 0 #dcffa6, - /* ← */ - 0 2px 5px #000; /* ↑ */ -} /* ↑ */ -/** ↑ - * This empty line */ -``` - -The [`fix` option](../../../docs/user-guide/options.md#fix) can automatically fix all of the problems reported by this rule. - -## Options - -`int`: Maximum number of adjacent empty lines allowed. - -For example, with `0`: - -The following patterns are considered problems: - - -```css -a { - padding: 10px - - 10px - 10px - 10px -} -``` - - -```css -a { - padding: - 10px - 10px - 10px - - 10px -} -``` - - -```css -a { - box-shadow: inset 0 2px 0 #dcffa6, - - 0 2px 5px #000; -} -``` - - -```css -a { - box-shadow: - inset 0 2px 0 #dcffa6, - - 0 2px 5px #000; -} -``` - -The following patterns are _not_ considered problems: - - -```css -a { - padding: 10px 10px 10px 10px -} -``` - - -```css -a { - padding: 10px - 10px - 10px - 10px -} -``` - - -```css -a { - padding: - 10px - 10px - 10px - 10px -} -``` - - -```css -a { - box-shadow: inset 0 2px 0 #dcffa6, 0 2px 5px #000; -} -``` - - -```css -a { - box-shadow: inset 0 2px 0 #dcffa6, - 0 2px 5px #000; -} -``` - - -```css -a { - box-shadow: - inset 0 2px 0 #dcffa6, - 0 2px 5px #000; -} -``` diff --git a/lib/rules/value-list-max-empty-lines/__tests__/index.js b/lib/rules/value-list-max-empty-lines/__tests__/index.js deleted file mode 100644 index faaf39bde0..0000000000 --- a/lib/rules/value-list-max-empty-lines/__tests__/index.js +++ /dev/null @@ -1,224 +0,0 @@ -'use strict'; - -const { messages, ruleName } = require('..'); - -testRule({ - ruleName, - config: [0], - fix: true, - - accept: [ - { - code: 'a { padding: 10px 10px 10px 10px }', - }, - { - code: 'a { padding:\n10px 10px 10px 10px }', - }, - { - code: 'a { padding:\n\n10px 10px 10px 10px }', - }, - { - code: 'a { padding:\r\n10px 10px 10px 10px }', - }, - { - code: 'a { padding:\r\n\r\n10px 10px 10px 10px }', - }, - { - code: 'a { padding: 10px 10px 10px 10px\n }', - }, - { - code: 'a { padding: 10px 10px 10px 10px\r\n }', - }, - { - code: 'a { padding: 10px 10px 10px 10px\n\n }', - }, - { - code: 'a { padding: 10px 10px 10px 10px\r\n\r\n }', - }, - { - code: 'a { padding: 10px\n10px\n10px\n10px }', - }, - { - code: 'a { padding: 10px\r\n10px\r\n10px\r\n10px }', - }, - { - code: 'a { box-shadow: inset 0 2px 0 #dcffa6, 0 2px 5px #000; }', - }, - { - code: 'a { box-shadow: inset 0 2px 0 #dcffa6,\n0 2px 5px #000; }', - }, - { - code: 'a { box-shadow: inset 0 2px 0 #dcffa6,\r\n0 2px 5px #000; }', - }, - ], - - reject: [ - { - code: 'a { padding: 10px /*\n\n\n\n\n\n*/ 10px 10px 10px }', - fixed: 'a { padding: 10px /*\n*/ 10px 10px 10px }', - description: 'comments are not skipped', - message: messages.expected(0), - line: 1, - column: 5, - }, - { - code: 'a { padding: 10px\n\n10px 10px 10px }', - fixed: 'a { padding: 10px\n10px 10px 10px }', - message: messages.expected(0), - line: 1, - column: 5, - }, - { - code: 'a { padding: 10px\r\n\r\n10px 10px 10px }', - fixed: 'a { padding: 10px\r\n10px 10px 10px }', - message: messages.expected(0), - line: 1, - column: 5, - }, - { - code: 'a { padding: 10px 10px 10px\n\n10px }', - fixed: 'a { padding: 10px 10px 10px\n10px }', - message: messages.expected(0), - line: 1, - column: 5, - }, - { - code: 'a { padding: 10px 10px 10px\r\n\r\n10px }', - fixed: 'a { padding: 10px 10px 10px\r\n10px }', - message: messages.expected(0), - line: 1, - column: 5, - }, - { - code: 'a { box-shadow: inset 0 2px 0 #dcffa6,\n\n0 2px 5px #000; }', - fixed: 'a { box-shadow: inset 0 2px 0 #dcffa6,\n0 2px 5px #000; }', - message: messages.expected(0), - line: 1, - column: 5, - }, - { - code: 'a { box-shadow: inset 0 2px 0 #dcffa6,\r\n\r\n0 2px 5px #000; }', - fixed: 'a { box-shadow: inset 0 2px 0 #dcffa6,\r\n0 2px 5px #000; }', - message: messages.expected(0), - line: 1, - column: 5, - }, - { - code: 'a { padding: 10px\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n10px 10px 10px }', - fixed: 'a { padding: 10px\n10px 10px 10px }', - message: messages.expected(0), - line: 1, - column: 5, - }, - { - code: 'a { padding: 10px\n\n\n\n10px\n\n\n10px\n\n10px }', - fixed: 'a { padding: 10px\n10px\n10px\n10px }', - message: messages.expected(0), - line: 1, - column: 5, - }, - { - code: 'a { padding: 10px\r\n\r\n\r\n\r\n10px\r\n\r\n\r\n10px\r\n\r\n10px }', - fixed: 'a { padding: 10px\r\n10px\r\n10px\r\n10px }', - message: messages.expected(0), - line: 1, - column: 5, - }, - { - code: 'a { padding: 10px\n\n /*comment*/ 10px 10px 10px }', - fixed: 'a { padding: 10px\n /*comment*/ 10px 10px 10px }', - message: messages.expected(0), - line: 1, - column: 5, - }, - { - code: 'a { padding: 10px\r\n\r\n /*comment*/ 10px 10px 10px }', - fixed: 'a { padding: 10px\r\n /*comment*/ 10px 10px 10px }', - message: messages.expected(0), - line: 1, - column: 5, - }, - { - code: 'a { padding: 10px\n\n \n\n\t\n\n10px 10px 10px }', - fixed: 'a { padding: 10px\n \n\t\n10px 10px 10px }', - message: messages.expected(0), - line: 1, - column: 5, - }, - ], -}); - -testRule({ - ruleName, - config: [1], - fix: true, - - accept: [ - { - code: 'a { padding: 10px\n10px\n10px\n10px }', - }, - { - code: 'a { padding: 10px\r\n10px\r\n10px\r\n10px }', - }, - { - code: 'a { padding: 10px\n\n10px\n\n10px\n\n10px }', - }, - { - code: 'a { padding: 10px\r\n\r\n10px\r\n\r\n10px\r\n\r\n10px }', - }, - { - code: 'a { box-shadow: inset 0 2px 0 #dcffa6, 0 2px 5px #000; }', - }, - { - code: 'a { box-shadow: inset 0 2px 0 #dcffa6,\n\n0 2px 5px #000; }', - }, - { - code: 'a { box-shadow: inset 0 2px 0 #dcffa6,\r\n\r\n0 2px 5px #000; }', - }, - ], - - reject: [ - { - code: 'a { padding: 10px\n\n\n10px 10px 10px }', - fixed: 'a { padding: 10px\n\n10px 10px 10px }', - message: messages.expected(1), - line: 1, - column: 5, - }, - { - code: 'a { padding: 10px\r\n\r\n\r\n10px 10px 10px }', - fixed: 'a { padding: 10px\r\n\r\n10px 10px 10px }', - message: messages.expected(1), - line: 1, - column: 5, - }, - { - code: 'a { padding: 10px 10px 10px\n\n\n10px }', - fixed: 'a { padding: 10px 10px 10px\n\n10px }', - message: messages.expected(1), - line: 1, - column: 5, - }, - { - code: 'a { padding: 10px 10px 10px\r\n\r\n\r\n10px }', - fixed: 'a { padding: 10px 10px 10px\r\n\r\n10px }', - message: messages.expected(1), - line: 1, - column: 5, - }, - { - code: 'a { box-shadow: inset 0 2px 0 #dcffa6,\n\n\n0 2px 5px #000; }', - fixed: 'a { box-shadow: inset 0 2px 0 #dcffa6,\n\n0 2px 5px #000; }', - message: messages.expected(1), - line: 1, - column: 5, - }, - { - code: 'a { box-shadow: inset 0 2px 0 #dcffa6,\r\n\r\n\r\n0 2px 5px #000; }', - fixed: 'a { box-shadow: inset 0 2px 0 #dcffa6,\r\n\r\n0 2px 5px #000; }', - message: messages.expected(1), - line: 1, - column: 5, - }, - ], -}); diff --git a/lib/rules/value-list-max-empty-lines/index.js b/lib/rules/value-list-max-empty-lines/index.js deleted file mode 100644 index 08fbbb262f..0000000000 --- a/lib/rules/value-list-max-empty-lines/index.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; - -const getDeclarationValue = require('../../utils/getDeclarationValue'); -const report = require('../../utils/report'); -const ruleMessages = require('../../utils/ruleMessages'); -const setDeclarationValue = require('../../utils/setDeclarationValue'); -const validateOptions = require('../../utils/validateOptions'); -const { isNumber } = require('../../utils/validateTypes'); - -const ruleName = 'value-list-max-empty-lines'; - -const messages = ruleMessages(ruleName, { - expected: (max) => `Expected no more than ${max} empty ${max === 1 ? 'line' : 'lines'}`, -}); - -const meta = { - url: 'https://stylelint.io/user-guide/rules/value-list-max-empty-lines', - fixable: true, - deprecated: true, -}; - -/** @type {import('stylelint').Rule} */ -const rule = (primary, _secondaryOptions, context) => { - const maxAdjacentNewlines = primary + 1; - - return (root, result) => { - const validOptions = validateOptions(result, ruleName, { - actual: primary, - possible: isNumber, - }); - - if (!validOptions) { - return; - } - - const violatedCRLFNewLinesRegex = new RegExp(`(?:\r\n){${maxAdjacentNewlines + 1},}`); - const violatedLFNewLinesRegex = new RegExp(`\n{${maxAdjacentNewlines + 1},}`); - const allowedLFNewLinesString = context.fix ? '\n'.repeat(maxAdjacentNewlines) : ''; - const allowedCRLFNewLinesString = context.fix ? '\r\n'.repeat(maxAdjacentNewlines) : ''; - - root.walkDecls((decl) => { - const value = getDeclarationValue(decl); - - if (context.fix) { - const newValueString = value - .replace(new RegExp(violatedLFNewLinesRegex, 'gm'), allowedLFNewLinesString) - .replace(new RegExp(violatedCRLFNewLinesRegex, 'gm'), allowedCRLFNewLinesString); - - setDeclarationValue(decl, newValueString); - } else if (violatedLFNewLinesRegex.test(value) || violatedCRLFNewLinesRegex.test(value)) { - report({ - message: messages.expected(primary), - node: decl, - index: 0, - result, - ruleName, - }); - } - }); - }; -}; - -rule.ruleName = ruleName; -rule.messages = messages; -rule.meta = meta; -module.exports = rule; diff --git a/lib/rules/valueListCommaWhitespaceChecker.js b/lib/rules/valueListCommaWhitespaceChecker.js deleted file mode 100644 index b537a67999..0000000000 --- a/lib/rules/valueListCommaWhitespaceChecker.js +++ /dev/null @@ -1,71 +0,0 @@ -'use strict'; - -const isStandardSyntaxDeclaration = require('../utils/isStandardSyntaxDeclaration'); -const isStandardSyntaxProperty = require('../utils/isStandardSyntaxProperty'); -const report = require('../utils/report'); -const styleSearch = require('style-search'); - -/** - * @param {{ - * root: import('postcss').Root, - * result: import('stylelint').PostcssResult, - * locationChecker: (opts: { source: string, index: number, err: (msg: string) => void }) => void, - * checkedRuleName: string, - * fix?: ((node: import('postcss').Declaration, index: number) => boolean) | null, - * determineIndex?: (declString: string, match: import('style-search').StyleSearchMatch) => number | false, - * }} opts - */ -module.exports = function valueListCommaWhitespaceChecker(opts) { - opts.root.walkDecls((decl) => { - if (!isStandardSyntaxDeclaration(decl) || !isStandardSyntaxProperty(decl.prop)) { - return; - } - - const declString = decl.toString(); - - styleSearch( - { - source: declString, - target: ',', - functionArguments: 'skip', - }, - (match) => { - const indexToCheckAfter = opts.determineIndex - ? opts.determineIndex(declString, match) - : match.startIndex; - - if (indexToCheckAfter === false) { - return; - } - - checkComma(declString, indexToCheckAfter, decl); - }, - ); - }); - - /** - * @param {string} source - * @param {number} index - * @param {import('postcss').Declaration} node - * @returns {void} - */ - function checkComma(source, index, node) { - opts.locationChecker({ - source, - index, - err: (message) => { - if (opts.fix && opts.fix(node, index)) { - return; - } - - report({ - message, - node, - index, - result: opts.result, - ruleName: opts.checkedRuleName, - }); - }, - }); - } -}; diff --git a/lib/utils/__tests__/checkAgainstRule.test.mjs b/lib/utils/__tests__/checkAgainstRule.test.mjs index 33375397da..a051d35451 100644 --- a/lib/utils/__tests__/checkAgainstRule.test.mjs +++ b/lib/utils/__tests__/checkAgainstRule.test.mjs @@ -30,14 +30,14 @@ const mockResult = { describe('checkAgainstRule', () => { it('does nothing with no errors', () => { - const root = postcss.parse('a {} @media {}'); + const root = postcss.parse('a { color: black }'); const warnings = []; checkAgainstRule( { - ruleName: 'at-rule-name-case', - ruleSettings: 'lower', + ruleName: 'color-named', + ruleSettings: 'always-where-possible', root, }, (warning) => warnings.push(warning), @@ -47,23 +47,23 @@ describe('checkAgainstRule', () => { }); it('handles non-array rule settings', () => { - const root = postcss.parse('a {} @media {}'); + const root = postcss.parse('a { color: black }'); const warnings = []; checkAgainstRule( { - ruleName: 'at-rule-name-case', - ruleSettings: 'upper', + ruleName: 'color-named', + ruleSettings: 'never', root, }, (warning) => warnings.push(warning), ); expect(warnings).toHaveLength(1); - expect(warnings[0].rule).toBe('at-rule-name-case'); + expect(warnings[0].rule).toBe('color-named'); expect(warnings[0].line).toBe(1); - expect(warnings[0].column).toBe(6); + expect(warnings[0].column).toBe(12); }); it('handles array rule settings', () => { @@ -87,15 +87,15 @@ describe('checkAgainstRule', () => { }); it('outputs fixed code when provided a context object', () => { - const root = postcss.parse(' a { color: red; }'); + const root = postcss.parse('a { top: 0px; }'); const context = { fix: true }; const warnings = []; checkAgainstRule( { - ruleName: 'indentation', - ruleSettings: 2, + ruleName: 'length-zero-no-unit', + ruleSettings: true, root, context, }, @@ -103,7 +103,7 @@ describe('checkAgainstRule', () => { ); expect(warnings).toHaveLength(0); - expect(root.toString()).toBe('a { color: red; }'); + expect(root.toString()).toBe('a { top: 0; }'); }); it('checks against custom rule (passing)', () => { diff --git a/lib/utils/whitespaceChecker.js b/lib/utils/whitespaceChecker.js deleted file mode 100644 index cf72eecf4f..0000000000 --- a/lib/utils/whitespaceChecker.js +++ /dev/null @@ -1,340 +0,0 @@ -'use strict'; - -const configurationError = require('./configurationError'); -const isSingleLineString = require('./isSingleLineString'); -const isWhitespace = require('./isWhitespace'); -const { assertFunction, isNullish } = require('./validateTypes'); - -/** - * @typedef {(message: string) => string} MessageFunction - */ - -/** - * @typedef {Object} Messages - * @property {MessageFunction} [expectedBefore] - * @property {MessageFunction} [rejectedBefore] - * @property {MessageFunction} [expectedAfter] - * @property {MessageFunction} [rejectedAfter] - * @property {MessageFunction} [expectedBeforeSingleLine] - * @property {MessageFunction} [rejectedBeforeSingleLine] - * @property {MessageFunction} [expectedBeforeMultiLine] - * @property {MessageFunction} [rejectedBeforeMultiLine] - * @property {MessageFunction} [expectedAfterSingleLine] - * @property {MessageFunction} [rejectedAfterSingleLine] - * @property {MessageFunction} [expectedAfterMultiLine] - * @property {MessageFunction} [rejectedAfterMultiLine] - */ - -/** - * @typedef {Object} WhitespaceCheckerArgs - * @property {string} source - The source string - * @property {number} index - The index of the character to check before - * @property {(message: string) => void} err - If a problem is found, this callback - * will be invoked with the relevant warning message. - * Typically this callback will report() the problem. - * @property {string} [errTarget] - If a problem is found, this string - * will be sent to the relevant warning message. - * @property {string} [lineCheckStr] - Single- and multi-line checkers - * will use this string to determine whether they should proceed, - * i.e. if this string is one line only, single-line checkers will check, - * multi-line checkers will ignore. - * If none is passed, they will use `source`. - * @property {boolean} [onlyOneChar=false] - Only check *one* character before. - * By default, "always-*" checks will look for the `targetWhitespace` one - * before and then ensure there is no whitespace two before. This option - * bypasses that second check. - * @property {boolean} [allowIndentation=false] - Allow arbitrary indentation - * between the `targetWhitespace` (almost definitely a newline) and the `index`. - * With this option, the checker will see if a newline *begins* the whitespace before - * the `index`. - */ - -/** - * @typedef {(args: WhitespaceCheckerArgs) => void} WhitespaceChecker - */ - -/** - * @typedef {{ - * before: WhitespaceChecker, - * beforeAllowingIndentation: WhitespaceChecker, - * after: WhitespaceChecker, - * afterOneOnly: WhitespaceChecker, - * }} WhitespaceCheckers - */ - -/** - * Create a whitespaceChecker, which exposes the following functions: - * - `before()` - * - `beforeAllowingIndentation()` - * - `after()` - * - `afterOneOnly()` - * - * @param {"space" | "newline"} targetWhitespace - This is a keyword instead - * of the actual character (e.g. " ") in order to accommodate - * different styles of newline ("\n" vs "\r\n") - * @param {"always" | "never" | "always-single-line" | "always-multi-line" | "never-single-line" | "never-multi-line"} expectation - * @param {Messages} messages - An object of message functions; - * calling `before*()` or `after*()` and the `expectation` that is passed - * determines which message functions are required - * - * @returns {WhitespaceCheckers} The checker, with its exposed checking functions - */ -module.exports = function whitespaceChecker(targetWhitespace, expectation, messages) { - // Keep track of active arguments in order to avoid passing - // too much stuff around, making signatures long and confusing. - // This variable gets reset anytime a checking function is called. - /** @type {WhitespaceCheckerArgs} */ - let activeArgs; - - /** - * Check for whitespace *before* a character. - * @type {WhitespaceChecker} - */ - function before({ - source, - index, - err, - errTarget, - lineCheckStr, - onlyOneChar = false, - allowIndentation = false, - }) { - activeArgs = { - source, - index, - err, - errTarget, - onlyOneChar, - allowIndentation, - }; - - switch (expectation) { - case 'always': - expectBefore(); - break; - case 'never': - rejectBefore(); - break; - case 'always-single-line': - if (!isSingleLineString(lineCheckStr || source)) { - return; - } - - expectBefore(messages.expectedBeforeSingleLine); - break; - case 'never-single-line': - if (!isSingleLineString(lineCheckStr || source)) { - return; - } - - rejectBefore(messages.rejectedBeforeSingleLine); - break; - case 'always-multi-line': - if (isSingleLineString(lineCheckStr || source)) { - return; - } - - expectBefore(messages.expectedBeforeMultiLine); - break; - case 'never-multi-line': - if (isSingleLineString(lineCheckStr || source)) { - return; - } - - rejectBefore(messages.rejectedBeforeMultiLine); - break; - default: - throw configurationError(`Unknown expectation "${expectation}"`); - } - } - - /** - * Check for whitespace *after* a character. - * @type {WhitespaceChecker} - */ - function after({ source, index, err, errTarget, lineCheckStr, onlyOneChar = false }) { - activeArgs = { source, index, err, errTarget, onlyOneChar }; - - switch (expectation) { - case 'always': - expectAfter(); - break; - case 'never': - rejectAfter(); - break; - case 'always-single-line': - if (!isSingleLineString(lineCheckStr || source)) { - return; - } - - expectAfter(messages.expectedAfterSingleLine); - break; - case 'never-single-line': - if (!isSingleLineString(lineCheckStr || source)) { - return; - } - - rejectAfter(messages.rejectedAfterSingleLine); - break; - case 'always-multi-line': - if (isSingleLineString(lineCheckStr || source)) { - return; - } - - expectAfter(messages.expectedAfterMultiLine); - break; - case 'never-multi-line': - if (isSingleLineString(lineCheckStr || source)) { - return; - } - - rejectAfter(messages.rejectedAfterMultiLine); - break; - default: - throw configurationError(`Unknown expectation "${expectation}"`); - } - } - - /** - * @type {WhitespaceChecker} - */ - function beforeAllowingIndentation(obj) { - before({ ...obj, allowIndentation: true }); - } - - function expectBefore(messageFunc = messages.expectedBefore) { - if (activeArgs.allowIndentation) { - expectBeforeAllowingIndentation(messageFunc); - - return; - } - - const _activeArgs = activeArgs; - const source = _activeArgs.source; - const index = _activeArgs.index; - - const oneCharBefore = source[index - 1]; - const twoCharsBefore = source[index - 2]; - - if (isNullish(oneCharBefore)) { - return; - } - - if ( - targetWhitespace === 'space' && - oneCharBefore === ' ' && - (activeArgs.onlyOneChar || isNullish(twoCharsBefore) || !isWhitespace(twoCharsBefore)) - ) { - return; - } - - assertFunction(messageFunc); - activeArgs.err(messageFunc(activeArgs.errTarget || source.charAt(index))); - } - - function expectBeforeAllowingIndentation(messageFunc = messages.expectedBefore) { - const _activeArgs2 = activeArgs; - const source = _activeArgs2.source; - const index = _activeArgs2.index; - const err = _activeArgs2.err; - - const expectedChar = targetWhitespace === 'newline' ? '\n' : undefined; - let i = index - 1; - - while (source[i] !== expectedChar) { - if (source[i] === '\t' || source[i] === ' ') { - i--; - continue; - } - - assertFunction(messageFunc); - err(messageFunc(activeArgs.errTarget || source.charAt(index))); - - return; - } - } - - function rejectBefore(messageFunc = messages.rejectedBefore) { - const _activeArgs3 = activeArgs; - const source = _activeArgs3.source; - const index = _activeArgs3.index; - - const oneCharBefore = source[index - 1]; - - if (!isNullish(oneCharBefore) && isWhitespace(oneCharBefore)) { - assertFunction(messageFunc); - activeArgs.err(messageFunc(activeArgs.errTarget || source.charAt(index))); - } - } - - /** - * @type {WhitespaceChecker} - */ - function afterOneOnly(obj) { - after({ ...obj, onlyOneChar: true }); - } - - function expectAfter(messageFunc = messages.expectedAfter) { - const _activeArgs4 = activeArgs; - const source = _activeArgs4.source; - const index = _activeArgs4.index; - - const oneCharAfter = source[index + 1]; - const twoCharsAfter = source[index + 2]; - const threeCharsAfter = source[index + 3]; - - if (isNullish(oneCharAfter)) { - return; - } - - if (targetWhitespace === 'newline') { - // If index is followed by a Windows CR-LF ... - if ( - oneCharAfter === '\r' && - twoCharsAfter === '\n' && - (activeArgs.onlyOneChar || isNullish(threeCharsAfter) || !isWhitespace(threeCharsAfter)) - ) { - return; - } - - // If index is followed by a Unix LF ... - if ( - oneCharAfter === '\n' && - (activeArgs.onlyOneChar || isNullish(twoCharsAfter) || !isWhitespace(twoCharsAfter)) - ) { - return; - } - } - - if ( - targetWhitespace === 'space' && - oneCharAfter === ' ' && - (activeArgs.onlyOneChar || isNullish(twoCharsAfter) || !isWhitespace(twoCharsAfter)) - ) { - return; - } - - assertFunction(messageFunc); - activeArgs.err(messageFunc(activeArgs.errTarget || source.charAt(index))); - } - - function rejectAfter(messageFunc = messages.rejectedAfter) { - const _activeArgs5 = activeArgs; - const source = _activeArgs5.source; - const index = _activeArgs5.index; - - const oneCharAfter = source[index + 1]; - - if (!isNullish(oneCharAfter) && isWhitespace(oneCharAfter)) { - assertFunction(messageFunc); - activeArgs.err(messageFunc(activeArgs.errTarget || source.charAt(index))); - } - } - - return { - before, - beforeAllowingIndentation, - after, - afterOneOnly, - }; -}; diff --git a/package-lock.json b/package-lock.json index f2e96dc401..0e922c34ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,7 +44,6 @@ "resolve-from": "^5.0.0", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", - "style-search": "^0.1.0", "supports-hyperlinks": "^3.0.0", "svg-tags": "^1.0.0", "table": "^6.8.1", @@ -71,7 +70,6 @@ "@types/postcss-less": "^4.0.2", "@types/postcss-resolve-nested-selector": "^0.1.0", "@types/postcss-safe-parser": "^5.0.1", - "@types/style-search": "^0.1.3", "@types/svg-tags": "^1.0.0", "@types/write-file-atomic": "^4.0.0", "benchmark": "^2.1.4", @@ -2899,12 +2897,6 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, - "node_modules/@types/style-search": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@types/style-search/-/style-search-0.1.3.tgz", - "integrity": "sha512-IcAsQKBFcoAWb843esJs2qhgiWWECtcFktAo4ks3xPTPlsbxfc1UESSNEXdwAPt/MnG7fZCGTJsTjH/3i5NzGA==", - "dev": true - }, "node_modules/@types/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/@types/supports-color/-/supports-color-8.1.1.tgz", @@ -16249,11 +16241,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/style-search": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", - "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==" - }, "node_modules/sugarss": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-4.0.1.tgz", diff --git a/package.json b/package.json index 6dffc33f83..099b1640f1 100644 --- a/package.json +++ b/package.json @@ -169,7 +169,6 @@ "resolve-from": "^5.0.0", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", - "style-search": "^0.1.0", "supports-hyperlinks": "^3.0.0", "svg-tags": "^1.0.0", "table": "^6.8.1", @@ -193,7 +192,6 @@ "@types/postcss-less": "^4.0.2", "@types/postcss-resolve-nested-selector": "^0.1.0", "@types/postcss-safe-parser": "^5.0.1", - "@types/style-search": "^0.1.3", "@types/svg-tags": "^1.0.0", "@types/write-file-atomic": "^4.0.0", "benchmark": "^2.1.4", diff --git a/system-tests/001/__snapshots__/fs.test.mjs.snap b/system-tests/001/__snapshots__/fs.test.mjs.snap index a1f9161080..7d53ad80f9 100644 --- a/system-tests/001/__snapshots__/fs.test.mjs.snap +++ b/system-tests/001/__snapshots__/fs.test.mjs.snap @@ -6,191 +6,7 @@ exports[`fs - valid sanitize.css and their config 1`] = ` "errored": false, "output": [ { - "deprecations": [ - { - "text": "The "at-rule-name-case" rule is deprecated.", - }, - { - "text": "The "at-rule-name-space-after" rule is deprecated.", - }, - { - "text": "The "at-rule-semicolon-newline-after" rule is deprecated.", - }, - { - "text": "The "block-closing-brace-empty-line-before" rule is deprecated.", - }, - { - "text": "The "block-closing-brace-newline-after" rule is deprecated.", - }, - { - "text": "The "block-closing-brace-newline-before" rule is deprecated.", - }, - { - "text": "The "block-closing-brace-space-before" rule is deprecated.", - }, - { - "text": "The "block-opening-brace-newline-after" rule is deprecated.", - }, - { - "text": "The "block-opening-brace-space-after" rule is deprecated.", - }, - { - "text": "The "block-opening-brace-space-before" rule is deprecated.", - }, - { - "text": "The "color-hex-case" rule is deprecated.", - }, - { - "text": "The "declaration-bang-space-after" rule is deprecated.", - }, - { - "text": "The "declaration-bang-space-before" rule is deprecated.", - }, - { - "text": "The "declaration-block-semicolon-newline-after" rule is deprecated.", - }, - { - "text": "The "declaration-block-semicolon-space-after" rule is deprecated.", - }, - { - "text": "The "declaration-block-semicolon-space-before" rule is deprecated.", - }, - { - "text": "The "declaration-block-trailing-semicolon" rule is deprecated.", - }, - { - "text": "The "declaration-colon-newline-after" rule is deprecated.", - }, - { - "text": "The "declaration-colon-space-after" rule is deprecated.", - }, - { - "text": "The "declaration-colon-space-before" rule is deprecated.", - }, - { - "text": "The "function-comma-newline-after" rule is deprecated.", - }, - { - "text": "The "function-comma-space-after" rule is deprecated.", - }, - { - "text": "The "function-comma-space-before" rule is deprecated.", - }, - { - "text": "The "function-max-empty-lines" rule is deprecated.", - }, - { - "text": "The "function-parentheses-newline-inside" rule is deprecated.", - }, - { - "text": "The "function-parentheses-space-inside" rule is deprecated.", - }, - { - "text": "The "function-whitespace-after" rule is deprecated.", - }, - { - "text": "The "max-empty-lines" rule is deprecated.", - }, - { - "text": "The "media-feature-colon-space-after" rule is deprecated.", - }, - { - "text": "The "media-feature-colon-space-before" rule is deprecated.", - }, - { - "text": "The "media-feature-name-case" rule is deprecated.", - }, - { - "text": "The "media-feature-parentheses-space-inside" rule is deprecated.", - }, - { - "text": "The "media-feature-range-operator-space-after" rule is deprecated.", - }, - { - "text": "The "media-feature-range-operator-space-before" rule is deprecated.", - }, - { - "text": "The "media-query-list-comma-newline-after" rule is deprecated.", - }, - { - "text": "The "media-query-list-comma-space-after" rule is deprecated.", - }, - { - "text": "The "media-query-list-comma-space-before" rule is deprecated.", - }, - { - "text": "The "no-eol-whitespace" rule is deprecated.", - }, - { - "text": "The "no-extra-semicolons" rule is deprecated.", - }, - { - "text": "The "no-missing-end-of-source-newline" rule is deprecated.", - }, - { - "text": "The "number-leading-zero" rule is deprecated.", - }, - { - "text": "The "number-no-trailing-zeros" rule is deprecated.", - }, - { - "text": "The "property-case" rule is deprecated.", - }, - { - "text": "The "selector-attribute-brackets-space-inside" rule is deprecated.", - }, - { - "text": "The "selector-attribute-operator-space-after" rule is deprecated.", - }, - { - "text": "The "selector-attribute-operator-space-before" rule is deprecated.", - }, - { - "text": "The "selector-combinator-space-after" rule is deprecated.", - }, - { - "text": "The "selector-combinator-space-before" rule is deprecated.", - }, - { - "text": "The "selector-descendant-combinator-no-non-space" rule is deprecated.", - }, - { - "text": "The "selector-list-comma-newline-after" rule is deprecated.", - }, - { - "text": "The "selector-list-comma-space-before" rule is deprecated.", - }, - { - "text": "The "selector-max-empty-lines" rule is deprecated.", - }, - { - "text": "The "selector-pseudo-class-case" rule is deprecated.", - }, - { - "text": "The "selector-pseudo-class-parentheses-space-inside" rule is deprecated.", - }, - { - "text": "The "selector-pseudo-element-case" rule is deprecated.", - }, - { - "text": "The "unit-case" rule is deprecated.", - }, - { - "text": "The "value-list-comma-newline-after" rule is deprecated.", - }, - { - "text": "The "value-list-comma-space-after" rule is deprecated.", - }, - { - "text": "The "value-list-comma-space-before" rule is deprecated.", - }, - { - "text": "The "value-list-max-empty-lines" rule is deprecated.", - }, - { - "text": "The "indentation" rule is deprecated.", - }, - ], + "deprecations": [], "errored": false, "invalidOptionWarnings": [], "parseErrors": [], @@ -200,252 +16,7 @@ exports[`fs - valid sanitize.css and their config 1`] = ` "reportedDisables": [], "results": [ { - "deprecations": [ - { - "reference": undefined, - "text": "The "at-rule-name-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "at-rule-name-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "at-rule-semicolon-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-closing-brace-empty-line-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-closing-brace-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-closing-brace-newline-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-closing-brace-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-opening-brace-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-opening-brace-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-opening-brace-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "color-hex-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-bang-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-bang-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-semicolon-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-semicolon-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-semicolon-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-trailing-semicolon" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-colon-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-colon-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-colon-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-comma-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-parentheses-newline-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-parentheses-space-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-whitespace-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-colon-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-colon-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-name-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-parentheses-space-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-range-operator-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-range-operator-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-query-list-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-query-list-comma-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-query-list-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "no-eol-whitespace" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "no-extra-semicolons" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "no-missing-end-of-source-newline" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "number-leading-zero" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "number-no-trailing-zeros" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "property-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-attribute-brackets-space-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-attribute-operator-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-attribute-operator-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-combinator-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-combinator-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-descendant-combinator-no-non-space" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-list-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-list-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-pseudo-class-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-pseudo-class-parentheses-space-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-pseudo-element-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "unit-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "indentation" rule is deprecated.", - }, - ], + "deprecations": [], "errored": false, "ignored": undefined, "invalidOptionWarnings": [], @@ -458,67 +29,12 @@ exports[`fs - valid sanitize.css and their config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/at-rule-empty-line-before", }, - "at-rule-name-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/at-rule-name-case", - }, - "at-rule-name-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/at-rule-name-space-after", - }, "at-rule-no-unknown": { "url": "https://stylelint.io/user-guide/rules/at-rule-no-unknown", }, - "at-rule-semicolon-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/at-rule-semicolon-newline-after", - }, - "block-closing-brace-empty-line-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-closing-brace-empty-line-before", - }, - "block-closing-brace-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-closing-brace-newline-after", - }, - "block-closing-brace-newline-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-closing-brace-newline-before", - }, - "block-closing-brace-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-closing-brace-space-before", - }, "block-no-empty": { "url": "https://stylelint.io/user-guide/rules/block-no-empty", }, - "block-opening-brace-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-opening-brace-newline-after", - }, - "block-opening-brace-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-opening-brace-space-after", - }, - "block-opening-brace-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-opening-brace-space-before", - }, - "color-hex-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/color-hex-case", - }, "color-hex-length": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/color-hex-length", @@ -541,16 +57,6 @@ exports[`fs - valid sanitize.css and their config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/custom-property-empty-line-before", }, - "declaration-bang-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-bang-space-after", - }, - "declaration-bang-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-bang-space-before", - }, "declaration-block-no-duplicate-properties": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/declaration-block-no-duplicate-properties", @@ -558,44 +64,9 @@ exports[`fs - valid sanitize.css and their config 1`] = ` "declaration-block-no-shorthand-property-overrides": { "url": "https://stylelint.io/user-guide/rules/declaration-block-no-shorthand-property-overrides", }, - "declaration-block-semicolon-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-semicolon-newline-after", - }, - "declaration-block-semicolon-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-semicolon-space-after", - }, - "declaration-block-semicolon-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-semicolon-space-before", - }, "declaration-block-single-line-max-declarations": { "url": "https://stylelint.io/user-guide/rules/declaration-block-single-line-max-declarations", }, - "declaration-block-trailing-semicolon": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-trailing-semicolon", - }, - "declaration-colon-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-colon-newline-after", - }, - "declaration-colon-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-colon-space-after", - }, - "declaration-colon-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-colon-space-before", - }, "declaration-empty-line-before": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/declaration-empty-line-before", @@ -610,53 +81,13 @@ exports[`fs - valid sanitize.css and their config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/function-calc-no-unspaced-operator", }, - "function-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-comma-newline-after", - }, - "function-comma-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-comma-space-after", - }, - "function-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-comma-space-before", - }, "function-linear-gradient-no-nonstandard-direction": { "url": "https://stylelint.io/user-guide/rules/function-linear-gradient-no-nonstandard-direction", }, - "function-max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-max-empty-lines", - }, "function-name-case": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/function-name-case", }, - "function-parentheses-newline-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-parentheses-newline-inside", - }, - "function-parentheses-space-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-parentheses-space-inside", - }, - "function-whitespace-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-whitespace-after", - }, - "indentation": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/indentation", - }, "keyframe-declaration-no-important": { "url": "https://stylelint.io/user-guide/rules/keyframe-declaration-no-important", }, @@ -664,59 +95,9 @@ exports[`fs - valid sanitize.css and their config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/length-zero-no-unit", }, - "max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/max-empty-lines", - }, - "media-feature-colon-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-colon-space-after", - }, - "media-feature-colon-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-colon-space-before", - }, - "media-feature-name-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-name-case", - }, "media-feature-name-no-unknown": { "url": "https://stylelint.io/user-guide/rules/media-feature-name-no-unknown", }, - "media-feature-parentheses-space-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-parentheses-space-inside", - }, - "media-feature-range-operator-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-range-operator-space-after", - }, - "media-feature-range-operator-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-range-operator-space-before", - }, - "media-query-list-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-query-list-comma-newline-after", - }, - "media-query-list-comma-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-query-list-comma-space-after", - }, - "media-query-list-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-query-list-comma-space-before", - }, "no-duplicate-at-import-rules": { "url": "https://stylelint.io/user-guide/rules/no-duplicate-at-import-rules", }, @@ -726,39 +107,9 @@ exports[`fs - valid sanitize.css and their config 1`] = ` "no-empty-source": { "url": "https://stylelint.io/user-guide/rules/no-empty-source", }, - "no-eol-whitespace": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/no-eol-whitespace", - }, - "no-extra-semicolons": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/no-extra-semicolons", - }, "no-invalid-double-slash-comments": { "url": "https://stylelint.io/user-guide/rules/no-invalid-double-slash-comments", }, - "no-missing-end-of-source-newline": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/no-missing-end-of-source-newline", - }, - "number-leading-zero": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/number-leading-zero", - }, - "number-no-trailing-zeros": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/number-no-trailing-zeros", - }, - "property-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/property-case", - }, "property-no-unknown": { "url": "https://stylelint.io/user-guide/rules/property-no-unknown", }, @@ -766,69 +117,9 @@ exports[`fs - valid sanitize.css and their config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/rule-empty-line-before", }, - "selector-attribute-brackets-space-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-attribute-brackets-space-inside", - }, - "selector-attribute-operator-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-attribute-operator-space-after", - }, - "selector-attribute-operator-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-attribute-operator-space-before", - }, - "selector-combinator-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-combinator-space-after", - }, - "selector-combinator-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-combinator-space-before", - }, - "selector-descendant-combinator-no-non-space": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-descendant-combinator-no-non-space", - }, - "selector-list-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-list-comma-newline-after", - }, - "selector-list-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-list-comma-space-before", - }, - "selector-max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-max-empty-lines", - }, - "selector-pseudo-class-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-pseudo-class-case", - }, "selector-pseudo-class-no-unknown": { "url": "https://stylelint.io/user-guide/rules/selector-pseudo-class-no-unknown", }, - "selector-pseudo-class-parentheses-space-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-pseudo-class-parentheses-space-inside", - }, - "selector-pseudo-element-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-pseudo-element-case", - }, "selector-pseudo-element-colon-notation": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/selector-pseudo-element-colon-notation", @@ -846,11 +137,6 @@ exports[`fs - valid sanitize.css and their config 1`] = ` "string-no-newline": { "url": "https://stylelint.io/user-guide/rules/string-no-newline", }, - "unit-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/unit-case", - }, "unit-no-unknown": { "url": "https://stylelint.io/user-guide/rules/unit-no-unknown", }, @@ -858,26 +144,6 @@ exports[`fs - valid sanitize.css and their config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/value-keyword-case", }, - "value-list-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-newline-after", - }, - "value-list-comma-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-space-after", - }, - "value-list-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-space-before", - }, - "value-list-max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-max-empty-lines", - }, }, } `; diff --git a/system-tests/001/__snapshots__/no-fs.test.mjs.snap b/system-tests/001/__snapshots__/no-fs.test.mjs.snap index f670e62a31..191729442e 100644 --- a/system-tests/001/__snapshots__/no-fs.test.mjs.snap +++ b/system-tests/001/__snapshots__/no-fs.test.mjs.snap @@ -6,191 +6,7 @@ exports[`no-fs - valid sanitize.css and their config 1`] = ` "errored": false, "output": [ { - "deprecations": [ - { - "text": "The "at-rule-name-case" rule is deprecated.", - }, - { - "text": "The "at-rule-name-space-after" rule is deprecated.", - }, - { - "text": "The "at-rule-semicolon-newline-after" rule is deprecated.", - }, - { - "text": "The "block-closing-brace-empty-line-before" rule is deprecated.", - }, - { - "text": "The "block-closing-brace-newline-after" rule is deprecated.", - }, - { - "text": "The "block-closing-brace-newline-before" rule is deprecated.", - }, - { - "text": "The "block-closing-brace-space-before" rule is deprecated.", - }, - { - "text": "The "block-opening-brace-newline-after" rule is deprecated.", - }, - { - "text": "The "block-opening-brace-space-after" rule is deprecated.", - }, - { - "text": "The "block-opening-brace-space-before" rule is deprecated.", - }, - { - "text": "The "color-hex-case" rule is deprecated.", - }, - { - "text": "The "declaration-bang-space-after" rule is deprecated.", - }, - { - "text": "The "declaration-bang-space-before" rule is deprecated.", - }, - { - "text": "The "declaration-block-semicolon-newline-after" rule is deprecated.", - }, - { - "text": "The "declaration-block-semicolon-space-after" rule is deprecated.", - }, - { - "text": "The "declaration-block-semicolon-space-before" rule is deprecated.", - }, - { - "text": "The "declaration-block-trailing-semicolon" rule is deprecated.", - }, - { - "text": "The "declaration-colon-newline-after" rule is deprecated.", - }, - { - "text": "The "declaration-colon-space-after" rule is deprecated.", - }, - { - "text": "The "declaration-colon-space-before" rule is deprecated.", - }, - { - "text": "The "function-comma-newline-after" rule is deprecated.", - }, - { - "text": "The "function-comma-space-after" rule is deprecated.", - }, - { - "text": "The "function-comma-space-before" rule is deprecated.", - }, - { - "text": "The "function-max-empty-lines" rule is deprecated.", - }, - { - "text": "The "function-parentheses-newline-inside" rule is deprecated.", - }, - { - "text": "The "function-parentheses-space-inside" rule is deprecated.", - }, - { - "text": "The "function-whitespace-after" rule is deprecated.", - }, - { - "text": "The "max-empty-lines" rule is deprecated.", - }, - { - "text": "The "media-feature-colon-space-after" rule is deprecated.", - }, - { - "text": "The "media-feature-colon-space-before" rule is deprecated.", - }, - { - "text": "The "media-feature-name-case" rule is deprecated.", - }, - { - "text": "The "media-feature-parentheses-space-inside" rule is deprecated.", - }, - { - "text": "The "media-feature-range-operator-space-after" rule is deprecated.", - }, - { - "text": "The "media-feature-range-operator-space-before" rule is deprecated.", - }, - { - "text": "The "media-query-list-comma-newline-after" rule is deprecated.", - }, - { - "text": "The "media-query-list-comma-space-after" rule is deprecated.", - }, - { - "text": "The "media-query-list-comma-space-before" rule is deprecated.", - }, - { - "text": "The "no-eol-whitespace" rule is deprecated.", - }, - { - "text": "The "no-extra-semicolons" rule is deprecated.", - }, - { - "text": "The "no-missing-end-of-source-newline" rule is deprecated.", - }, - { - "text": "The "number-leading-zero" rule is deprecated.", - }, - { - "text": "The "number-no-trailing-zeros" rule is deprecated.", - }, - { - "text": "The "property-case" rule is deprecated.", - }, - { - "text": "The "selector-attribute-brackets-space-inside" rule is deprecated.", - }, - { - "text": "The "selector-attribute-operator-space-after" rule is deprecated.", - }, - { - "text": "The "selector-attribute-operator-space-before" rule is deprecated.", - }, - { - "text": "The "selector-combinator-space-after" rule is deprecated.", - }, - { - "text": "The "selector-combinator-space-before" rule is deprecated.", - }, - { - "text": "The "selector-descendant-combinator-no-non-space" rule is deprecated.", - }, - { - "text": "The "selector-list-comma-newline-after" rule is deprecated.", - }, - { - "text": "The "selector-list-comma-space-before" rule is deprecated.", - }, - { - "text": "The "selector-max-empty-lines" rule is deprecated.", - }, - { - "text": "The "selector-pseudo-class-case" rule is deprecated.", - }, - { - "text": "The "selector-pseudo-class-parentheses-space-inside" rule is deprecated.", - }, - { - "text": "The "selector-pseudo-element-case" rule is deprecated.", - }, - { - "text": "The "unit-case" rule is deprecated.", - }, - { - "text": "The "value-list-comma-newline-after" rule is deprecated.", - }, - { - "text": "The "value-list-comma-space-after" rule is deprecated.", - }, - { - "text": "The "value-list-comma-space-before" rule is deprecated.", - }, - { - "text": "The "value-list-max-empty-lines" rule is deprecated.", - }, - { - "text": "The "indentation" rule is deprecated.", - }, - ], + "deprecations": [], "errored": false, "invalidOptionWarnings": [], "parseErrors": [], @@ -200,252 +16,7 @@ exports[`no-fs - valid sanitize.css and their config 1`] = ` "reportedDisables": [], "results": [ { - "deprecations": [ - { - "reference": undefined, - "text": "The "at-rule-name-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "at-rule-name-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "at-rule-semicolon-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-closing-brace-empty-line-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-closing-brace-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-closing-brace-newline-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-closing-brace-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-opening-brace-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-opening-brace-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-opening-brace-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "color-hex-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-bang-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-bang-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-semicolon-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-semicolon-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-semicolon-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-trailing-semicolon" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-colon-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-colon-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-colon-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-comma-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-parentheses-newline-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-parentheses-space-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-whitespace-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-colon-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-colon-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-name-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-parentheses-space-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-range-operator-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-range-operator-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-query-list-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-query-list-comma-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-query-list-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "no-eol-whitespace" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "no-extra-semicolons" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "no-missing-end-of-source-newline" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "number-leading-zero" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "number-no-trailing-zeros" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "property-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-attribute-brackets-space-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-attribute-operator-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-attribute-operator-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-combinator-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-combinator-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-descendant-combinator-no-non-space" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-list-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-list-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-pseudo-class-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-pseudo-class-parentheses-space-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-pseudo-element-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "unit-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "indentation" rule is deprecated.", - }, - ], + "deprecations": [], "errored": false, "ignored": undefined, "invalidOptionWarnings": [], @@ -458,67 +29,12 @@ exports[`no-fs - valid sanitize.css and their config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/at-rule-empty-line-before", }, - "at-rule-name-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/at-rule-name-case", - }, - "at-rule-name-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/at-rule-name-space-after", - }, "at-rule-no-unknown": { "url": "https://stylelint.io/user-guide/rules/at-rule-no-unknown", }, - "at-rule-semicolon-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/at-rule-semicolon-newline-after", - }, - "block-closing-brace-empty-line-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-closing-brace-empty-line-before", - }, - "block-closing-brace-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-closing-brace-newline-after", - }, - "block-closing-brace-newline-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-closing-brace-newline-before", - }, - "block-closing-brace-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-closing-brace-space-before", - }, "block-no-empty": { "url": "https://stylelint.io/user-guide/rules/block-no-empty", }, - "block-opening-brace-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-opening-brace-newline-after", - }, - "block-opening-brace-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-opening-brace-space-after", - }, - "block-opening-brace-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-opening-brace-space-before", - }, - "color-hex-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/color-hex-case", - }, "color-hex-length": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/color-hex-length", @@ -541,16 +57,6 @@ exports[`no-fs - valid sanitize.css and their config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/custom-property-empty-line-before", }, - "declaration-bang-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-bang-space-after", - }, - "declaration-bang-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-bang-space-before", - }, "declaration-block-no-duplicate-properties": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/declaration-block-no-duplicate-properties", @@ -558,44 +64,9 @@ exports[`no-fs - valid sanitize.css and their config 1`] = ` "declaration-block-no-shorthand-property-overrides": { "url": "https://stylelint.io/user-guide/rules/declaration-block-no-shorthand-property-overrides", }, - "declaration-block-semicolon-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-semicolon-newline-after", - }, - "declaration-block-semicolon-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-semicolon-space-after", - }, - "declaration-block-semicolon-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-semicolon-space-before", - }, "declaration-block-single-line-max-declarations": { "url": "https://stylelint.io/user-guide/rules/declaration-block-single-line-max-declarations", }, - "declaration-block-trailing-semicolon": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-trailing-semicolon", - }, - "declaration-colon-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-colon-newline-after", - }, - "declaration-colon-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-colon-space-after", - }, - "declaration-colon-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-colon-space-before", - }, "declaration-empty-line-before": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/declaration-empty-line-before", @@ -610,53 +81,13 @@ exports[`no-fs - valid sanitize.css and their config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/function-calc-no-unspaced-operator", }, - "function-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-comma-newline-after", - }, - "function-comma-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-comma-space-after", - }, - "function-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-comma-space-before", - }, "function-linear-gradient-no-nonstandard-direction": { "url": "https://stylelint.io/user-guide/rules/function-linear-gradient-no-nonstandard-direction", }, - "function-max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-max-empty-lines", - }, "function-name-case": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/function-name-case", }, - "function-parentheses-newline-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-parentheses-newline-inside", - }, - "function-parentheses-space-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-parentheses-space-inside", - }, - "function-whitespace-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-whitespace-after", - }, - "indentation": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/indentation", - }, "keyframe-declaration-no-important": { "url": "https://stylelint.io/user-guide/rules/keyframe-declaration-no-important", }, @@ -664,59 +95,9 @@ exports[`no-fs - valid sanitize.css and their config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/length-zero-no-unit", }, - "max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/max-empty-lines", - }, - "media-feature-colon-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-colon-space-after", - }, - "media-feature-colon-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-colon-space-before", - }, - "media-feature-name-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-name-case", - }, "media-feature-name-no-unknown": { "url": "https://stylelint.io/user-guide/rules/media-feature-name-no-unknown", }, - "media-feature-parentheses-space-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-parentheses-space-inside", - }, - "media-feature-range-operator-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-range-operator-space-after", - }, - "media-feature-range-operator-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-range-operator-space-before", - }, - "media-query-list-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-query-list-comma-newline-after", - }, - "media-query-list-comma-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-query-list-comma-space-after", - }, - "media-query-list-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-query-list-comma-space-before", - }, "no-duplicate-at-import-rules": { "url": "https://stylelint.io/user-guide/rules/no-duplicate-at-import-rules", }, @@ -726,39 +107,9 @@ exports[`no-fs - valid sanitize.css and their config 1`] = ` "no-empty-source": { "url": "https://stylelint.io/user-guide/rules/no-empty-source", }, - "no-eol-whitespace": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/no-eol-whitespace", - }, - "no-extra-semicolons": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/no-extra-semicolons", - }, "no-invalid-double-slash-comments": { "url": "https://stylelint.io/user-guide/rules/no-invalid-double-slash-comments", }, - "no-missing-end-of-source-newline": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/no-missing-end-of-source-newline", - }, - "number-leading-zero": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/number-leading-zero", - }, - "number-no-trailing-zeros": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/number-no-trailing-zeros", - }, - "property-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/property-case", - }, "property-no-unknown": { "url": "https://stylelint.io/user-guide/rules/property-no-unknown", }, @@ -766,69 +117,9 @@ exports[`no-fs - valid sanitize.css and their config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/rule-empty-line-before", }, - "selector-attribute-brackets-space-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-attribute-brackets-space-inside", - }, - "selector-attribute-operator-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-attribute-operator-space-after", - }, - "selector-attribute-operator-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-attribute-operator-space-before", - }, - "selector-combinator-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-combinator-space-after", - }, - "selector-combinator-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-combinator-space-before", - }, - "selector-descendant-combinator-no-non-space": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-descendant-combinator-no-non-space", - }, - "selector-list-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-list-comma-newline-after", - }, - "selector-list-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-list-comma-space-before", - }, - "selector-max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-max-empty-lines", - }, - "selector-pseudo-class-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-pseudo-class-case", - }, "selector-pseudo-class-no-unknown": { "url": "https://stylelint.io/user-guide/rules/selector-pseudo-class-no-unknown", }, - "selector-pseudo-class-parentheses-space-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-pseudo-class-parentheses-space-inside", - }, - "selector-pseudo-element-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-pseudo-element-case", - }, "selector-pseudo-element-colon-notation": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/selector-pseudo-element-colon-notation", @@ -846,11 +137,6 @@ exports[`no-fs - valid sanitize.css and their config 1`] = ` "string-no-newline": { "url": "https://stylelint.io/user-guide/rules/string-no-newline", }, - "unit-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/unit-case", - }, "unit-no-unknown": { "url": "https://stylelint.io/user-guide/rules/unit-no-unknown", }, @@ -858,26 +144,6 @@ exports[`no-fs - valid sanitize.css and their config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/value-keyword-case", }, - "value-list-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-newline-after", - }, - "value-list-comma-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-space-after", - }, - "value-list-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-space-before", - }, - "value-list-max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-max-empty-lines", - }, }, } `; diff --git a/system-tests/001/config.json b/system-tests/001/config.json index e87af7947c..2ccc9ce89b 100644 --- a/system-tests/001/config.json +++ b/system-tests/001/config.json @@ -7,19 +7,8 @@ "ignore": ["after-comment"] } ], - "at-rule-name-case": "lower", - "at-rule-name-space-after": "always-single-line", "at-rule-no-unknown": true, - "at-rule-semicolon-newline-after": "always", - "block-closing-brace-empty-line-before": "never", - "block-closing-brace-newline-after": "always", - "block-closing-brace-newline-before": "always-multi-line", - "block-closing-brace-space-before": "always-single-line", "block-no-empty": true, - "block-opening-brace-newline-after": "always-multi-line", - "block-opening-brace-space-after": "always-single-line", - "block-opening-brace-space-before": "always", - "color-hex-case": "lower", "color-hex-length": "short", "color-no-invalid-hex": true, "comment-empty-line-before": [ @@ -38,8 +27,6 @@ "ignore": ["after-comment", "inside-single-line-block"] } ], - "declaration-bang-space-after": "never", - "declaration-bang-space-before": "always", "declaration-block-no-duplicate-properties": [ true, { @@ -47,14 +34,7 @@ } ], "declaration-block-no-shorthand-property-overrides": true, - "declaration-block-semicolon-newline-after": "always-multi-line", - "declaration-block-semicolon-space-after": "always-single-line", - "declaration-block-semicolon-space-before": "never", "declaration-block-single-line-max-declarations": 1, - "declaration-block-trailing-semicolon": "always", - "declaration-colon-newline-after": "always-multi-line", - "declaration-colon-space-after": "always-single-line", - "declaration-colon-space-before": "never", "declaration-empty-line-before": [ "always", { @@ -70,39 +50,15 @@ ], "font-family-no-missing-generic-family-keyword": true, "function-calc-no-unspaced-operator": true, - "function-comma-newline-after": "always-multi-line", - "function-comma-space-after": "always-single-line", - "function-comma-space-before": "never", "function-linear-gradient-no-nonstandard-direction": true, - "function-max-empty-lines": 0, "function-name-case": "lower", - "function-parentheses-newline-inside": "always-multi-line", - "function-parentheses-space-inside": "never-single-line", - "function-whitespace-after": "always", - "indentation": 2, "keyframe-declaration-no-important": true, "length-zero-no-unit": true, - "max-empty-lines": 1, - "media-feature-colon-space-after": "always", - "media-feature-colon-space-before": "never", - "media-feature-name-case": "lower", "media-feature-name-no-unknown": true, - "media-feature-parentheses-space-inside": "never", - "media-feature-range-operator-space-after": "always", - "media-feature-range-operator-space-before": "always", - "media-query-list-comma-newline-after": "always-multi-line", - "media-query-list-comma-space-after": "always-single-line", - "media-query-list-comma-space-before": "never", "no-duplicate-at-import-rules": true, "no-duplicate-selectors": true, "no-empty-source": true, - "no-eol-whitespace": true, - "no-extra-semicolons": true, "no-invalid-double-slash-comments": true, - "no-missing-end-of-source-newline": true, - "number-leading-zero": "always", - "number-no-trailing-zeros": true, - "property-case": "lower", "property-no-unknown": true, "rule-empty-line-before": [ "always-multi-line", @@ -111,30 +67,13 @@ "ignore": ["after-comment"] } ], - "selector-attribute-brackets-space-inside": "never", - "selector-attribute-operator-space-after": "never", - "selector-attribute-operator-space-before": "never", - "selector-combinator-space-after": "always", - "selector-combinator-space-before": "always", - "selector-descendant-combinator-no-non-space": true, - "selector-list-comma-newline-after": "always", - "selector-list-comma-space-before": "never", - "selector-max-empty-lines": 0, - "selector-pseudo-class-case": "lower", "selector-pseudo-class-no-unknown": true, - "selector-pseudo-class-parentheses-space-inside": "never", - "selector-pseudo-element-case": "lower", "selector-pseudo-element-colon-notation": "double", "selector-pseudo-element-no-unknown": true, "selector-type-case": "lower", "selector-type-no-unknown": true, "string-no-newline": true, - "unit-case": "lower", "unit-no-unknown": true, - "value-keyword-case": ["lower", { "camelCaseSvgKeywords": true }], - "value-list-comma-newline-after": "always-multi-line", - "value-list-comma-space-after": "always-single-line", - "value-list-comma-space-before": "never", - "value-list-max-empty-lines": 0 + "value-keyword-case": ["lower", { "camelCaseSvgKeywords": true }] } } diff --git a/system-tests/002/__snapshots__/fs.test.mjs.snap b/system-tests/002/__snapshots__/fs.test.mjs.snap index 3d5cb66377..e070e13da9 100644 --- a/system-tests/002/__snapshots__/fs.test.mjs.snap +++ b/system-tests/002/__snapshots__/fs.test.mjs.snap @@ -6,47 +6,7 @@ exports[`fs - invalid twbs buttons and their config 1`] = ` "errored": true, "output": [ { - "deprecations": [ - { - "text": "The "at-rule-semicolon-space-before" rule is deprecated.", - }, - { - "text": "The "at-rule-name-space-after" rule is deprecated.", - }, - { - "text": "The "declaration-block-semicolon-newline-before" rule is deprecated.", - }, - { - "text": "The "max-empty-lines" rule is deprecated.", - }, - { - "text": "The "number-leading-zero" rule is deprecated.", - }, - { - "text": "The "selector-list-comma-newline-before" rule is deprecated.", - }, - { - "text": "The "selector-list-comma-space-after" rule is deprecated.", - }, - { - "text": "The "selector-list-comma-space-before" rule is deprecated.", - }, - { - "text": "The "string-quotes" rule is deprecated.", - }, - { - "text": "The "unicode-bom" rule is deprecated.", - }, - { - "text": "The "value-list-comma-newline-after" rule is deprecated.", - }, - { - "text": "The "value-list-comma-newline-before" rule is deprecated.", - }, - { - "text": "The "value-list-comma-space-after" rule is deprecated.", - }, - ], + "deprecations": [], "errored": true, "invalidOptionWarnings": [], "parseErrors": [], @@ -84,60 +44,7 @@ exports[`fs - invalid twbs buttons and their config 1`] = ` "reportedDisables": [], "results": [ { - "deprecations": [ - { - "reference": undefined, - "text": "The "at-rule-semicolon-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "at-rule-name-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-semicolon-newline-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "number-leading-zero" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-list-comma-newline-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-list-comma-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-list-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "string-quotes" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "unicode-bom" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-newline-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-space-after" rule is deprecated.", - }, - ], + "deprecations": [], "errored": true, "ignored": undefined, "invalidOptionWarnings": [], @@ -174,26 +81,13 @@ exports[`fs - invalid twbs buttons and their config 1`] = ` }, ], "ruleMetadata": { - "at-rule-name-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/at-rule-name-space-after", - }, "at-rule-no-vendor-prefix": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/at-rule-no-vendor-prefix", }, - "at-rule-semicolon-space-before": { - "deprecated": true, - "url": "https://stylelint.io/user-guide/rules/at-rule-semicolon-space-before", - }, "color-named": { "url": "https://stylelint.io/user-guide/rules/color-named", }, - "declaration-block-semicolon-newline-before": { - "deprecated": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-semicolon-newline-before", - }, "declaration-no-important": { "url": "https://stylelint.io/user-guide/rules/declaration-no-important", }, @@ -212,20 +106,10 @@ exports[`fs - invalid twbs buttons and their config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/function-url-quotes", }, - "max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/max-empty-lines", - }, "media-feature-name-no-vendor-prefix": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/media-feature-name-no-vendor-prefix", }, - "number-leading-zero": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/number-leading-zero", - }, "property-no-vendor-prefix": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/property-no-vendor-prefix", @@ -237,21 +121,6 @@ exports[`fs - invalid twbs buttons and their config 1`] = ` "selector-class-pattern": { "url": "https://stylelint.io/user-guide/rules/selector-class-pattern", }, - "selector-list-comma-newline-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-list-comma-newline-before", - }, - "selector-list-comma-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-list-comma-space-after", - }, - "selector-list-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-list-comma-space-before", - }, "selector-max-attribute": { "url": "https://stylelint.io/user-guide/rules/selector-max-attribute", }, @@ -284,29 +153,6 @@ exports[`fs - invalid twbs buttons and their config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/shorthand-property-no-redundant-values", }, - "string-quotes": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/string-quotes", - }, - "unicode-bom": { - "deprecated": true, - "url": "https://stylelint.io/user-guide/rules/unicode-bom", - }, - "value-list-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-newline-after", - }, - "value-list-comma-newline-before": { - "deprecated": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-newline-before", - }, - "value-list-comma-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-space-after", - }, "value-no-vendor-prefix": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/value-no-vendor-prefix", diff --git a/system-tests/002/__snapshots__/no-fs.test.mjs.snap b/system-tests/002/__snapshots__/no-fs.test.mjs.snap index 1fb9b3ff90..d8f3d3bb18 100644 --- a/system-tests/002/__snapshots__/no-fs.test.mjs.snap +++ b/system-tests/002/__snapshots__/no-fs.test.mjs.snap @@ -6,47 +6,7 @@ exports[`no-fs - invalid twbs buttons and their config 1`] = ` "errored": true, "output": [ { - "deprecations": [ - { - "text": "The "at-rule-semicolon-space-before" rule is deprecated.", - }, - { - "text": "The "at-rule-name-space-after" rule is deprecated.", - }, - { - "text": "The "declaration-block-semicolon-newline-before" rule is deprecated.", - }, - { - "text": "The "max-empty-lines" rule is deprecated.", - }, - { - "text": "The "number-leading-zero" rule is deprecated.", - }, - { - "text": "The "selector-list-comma-newline-before" rule is deprecated.", - }, - { - "text": "The "selector-list-comma-space-after" rule is deprecated.", - }, - { - "text": "The "selector-list-comma-space-before" rule is deprecated.", - }, - { - "text": "The "string-quotes" rule is deprecated.", - }, - { - "text": "The "unicode-bom" rule is deprecated.", - }, - { - "text": "The "value-list-comma-newline-after" rule is deprecated.", - }, - { - "text": "The "value-list-comma-newline-before" rule is deprecated.", - }, - { - "text": "The "value-list-comma-space-after" rule is deprecated.", - }, - ], + "deprecations": [], "errored": true, "invalidOptionWarnings": [], "parseErrors": [], @@ -84,60 +44,7 @@ exports[`no-fs - invalid twbs buttons and their config 1`] = ` "reportedDisables": [], "results": [ { - "deprecations": [ - { - "reference": undefined, - "text": "The "at-rule-semicolon-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "at-rule-name-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-semicolon-newline-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "number-leading-zero" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-list-comma-newline-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-list-comma-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-list-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "string-quotes" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "unicode-bom" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-newline-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-space-after" rule is deprecated.", - }, - ], + "deprecations": [], "errored": true, "ignored": undefined, "invalidOptionWarnings": [], @@ -174,26 +81,13 @@ exports[`no-fs - invalid twbs buttons and their config 1`] = ` }, ], "ruleMetadata": { - "at-rule-name-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/at-rule-name-space-after", - }, "at-rule-no-vendor-prefix": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/at-rule-no-vendor-prefix", }, - "at-rule-semicolon-space-before": { - "deprecated": true, - "url": "https://stylelint.io/user-guide/rules/at-rule-semicolon-space-before", - }, "color-named": { "url": "https://stylelint.io/user-guide/rules/color-named", }, - "declaration-block-semicolon-newline-before": { - "deprecated": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-semicolon-newline-before", - }, "declaration-no-important": { "url": "https://stylelint.io/user-guide/rules/declaration-no-important", }, @@ -212,20 +106,10 @@ exports[`no-fs - invalid twbs buttons and their config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/function-url-quotes", }, - "max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/max-empty-lines", - }, "media-feature-name-no-vendor-prefix": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/media-feature-name-no-vendor-prefix", }, - "number-leading-zero": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/number-leading-zero", - }, "property-no-vendor-prefix": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/property-no-vendor-prefix", @@ -237,21 +121,6 @@ exports[`no-fs - invalid twbs buttons and their config 1`] = ` "selector-class-pattern": { "url": "https://stylelint.io/user-guide/rules/selector-class-pattern", }, - "selector-list-comma-newline-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-list-comma-newline-before", - }, - "selector-list-comma-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-list-comma-space-after", - }, - "selector-list-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-list-comma-space-before", - }, "selector-max-attribute": { "url": "https://stylelint.io/user-guide/rules/selector-max-attribute", }, @@ -284,29 +153,6 @@ exports[`no-fs - invalid twbs buttons and their config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/shorthand-property-no-redundant-values", }, - "string-quotes": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/string-quotes", - }, - "unicode-bom": { - "deprecated": true, - "url": "https://stylelint.io/user-guide/rules/unicode-bom", - }, - "value-list-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-newline-after", - }, - "value-list-comma-newline-before": { - "deprecated": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-newline-before", - }, - "value-list-comma-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-space-after", - }, "value-no-vendor-prefix": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/value-no-vendor-prefix", diff --git a/system-tests/002/config.json b/system-tests/002/config.json index 26b7570f32..44a262d773 100755 --- a/system-tests/002/config.json +++ b/system-tests/002/config.json @@ -1,10 +1,7 @@ { "rules": { - "at-rule-name-space-after": "always", "at-rule-no-vendor-prefix": true, - "at-rule-semicolon-space-before": "never", "color-named": "never", - "declaration-block-semicolon-newline-before": "never-multi-line", "declaration-no-important": true, "font-family-name-quotes": "always-where-recommended", "font-weight-notation": [ @@ -15,15 +12,10 @@ ], "function-url-no-scheme-relative": true, "function-url-quotes": "always", - "max-empty-lines": 2, "media-feature-name-no-vendor-prefix": true, - "number-leading-zero": "never", "property-no-vendor-prefix": true, "selector-attribute-quotes": "always", "selector-class-pattern": "^[a-z][a-z0-9\\-]*[a-z0-9]$", - "selector-list-comma-newline-before": "never-multi-line", - "selector-list-comma-space-after": "always-single-line", - "selector-list-comma-space-before": "never-single-line", "selector-max-attribute": 2, "selector-max-class": 4, "selector-max-combinators": 4, @@ -34,11 +26,6 @@ "selector-no-qualifying-type": true, "selector-no-vendor-prefix": true, "shorthand-property-no-redundant-values": true, - "string-quotes": "double", - "unicode-bom": "never", - "value-list-comma-newline-after": "never-multi-line", - "value-list-comma-newline-before": "never-multi-line", - "value-list-comma-space-after": "always", "value-no-vendor-prefix": true } } diff --git a/system-tests/003/__snapshots__/fs.test.mjs.snap b/system-tests/003/__snapshots__/fs.test.mjs.snap index 058e80cbfc..48bf0e1c06 100644 --- a/system-tests/003/__snapshots__/fs.test.mjs.snap +++ b/system-tests/003/__snapshots__/fs.test.mjs.snap @@ -6,191 +6,7 @@ exports[`fs - zen garden CSS with standard config 1`] = ` "errored": true, "output": [ { - "deprecations": [ - { - "text": "The "at-rule-name-case" rule is deprecated.", - }, - { - "text": "The "at-rule-name-space-after" rule is deprecated.", - }, - { - "text": "The "at-rule-semicolon-newline-after" rule is deprecated.", - }, - { - "text": "The "block-closing-brace-empty-line-before" rule is deprecated.", - }, - { - "text": "The "block-closing-brace-newline-after" rule is deprecated.", - }, - { - "text": "The "block-closing-brace-newline-before" rule is deprecated.", - }, - { - "text": "The "block-closing-brace-space-before" rule is deprecated.", - }, - { - "text": "The "block-opening-brace-newline-after" rule is deprecated.", - }, - { - "text": "The "block-opening-brace-space-after" rule is deprecated.", - }, - { - "text": "The "block-opening-brace-space-before" rule is deprecated.", - }, - { - "text": "The "color-hex-case" rule is deprecated.", - }, - { - "text": "The "declaration-bang-space-after" rule is deprecated.", - }, - { - "text": "The "declaration-bang-space-before" rule is deprecated.", - }, - { - "text": "The "declaration-block-semicolon-newline-after" rule is deprecated.", - }, - { - "text": "The "declaration-block-semicolon-space-after" rule is deprecated.", - }, - { - "text": "The "declaration-block-semicolon-space-before" rule is deprecated.", - }, - { - "text": "The "declaration-block-trailing-semicolon" rule is deprecated.", - }, - { - "text": "The "declaration-colon-newline-after" rule is deprecated.", - }, - { - "text": "The "declaration-colon-space-after" rule is deprecated.", - }, - { - "text": "The "declaration-colon-space-before" rule is deprecated.", - }, - { - "text": "The "function-comma-newline-after" rule is deprecated.", - }, - { - "text": "The "function-comma-space-after" rule is deprecated.", - }, - { - "text": "The "function-comma-space-before" rule is deprecated.", - }, - { - "text": "The "function-max-empty-lines" rule is deprecated.", - }, - { - "text": "The "function-parentheses-newline-inside" rule is deprecated.", - }, - { - "text": "The "function-parentheses-space-inside" rule is deprecated.", - }, - { - "text": "The "function-whitespace-after" rule is deprecated.", - }, - { - "text": "The "max-empty-lines" rule is deprecated.", - }, - { - "text": "The "media-feature-colon-space-after" rule is deprecated.", - }, - { - "text": "The "media-feature-colon-space-before" rule is deprecated.", - }, - { - "text": "The "media-feature-name-case" rule is deprecated.", - }, - { - "text": "The "media-feature-parentheses-space-inside" rule is deprecated.", - }, - { - "text": "The "media-feature-range-operator-space-after" rule is deprecated.", - }, - { - "text": "The "media-feature-range-operator-space-before" rule is deprecated.", - }, - { - "text": "The "media-query-list-comma-newline-after" rule is deprecated.", - }, - { - "text": "The "media-query-list-comma-space-after" rule is deprecated.", - }, - { - "text": "The "media-query-list-comma-space-before" rule is deprecated.", - }, - { - "text": "The "no-eol-whitespace" rule is deprecated.", - }, - { - "text": "The "no-extra-semicolons" rule is deprecated.", - }, - { - "text": "The "no-missing-end-of-source-newline" rule is deprecated.", - }, - { - "text": "The "number-leading-zero" rule is deprecated.", - }, - { - "text": "The "number-no-trailing-zeros" rule is deprecated.", - }, - { - "text": "The "property-case" rule is deprecated.", - }, - { - "text": "The "selector-attribute-brackets-space-inside" rule is deprecated.", - }, - { - "text": "The "selector-attribute-operator-space-after" rule is deprecated.", - }, - { - "text": "The "selector-attribute-operator-space-before" rule is deprecated.", - }, - { - "text": "The "selector-combinator-space-after" rule is deprecated.", - }, - { - "text": "The "selector-combinator-space-before" rule is deprecated.", - }, - { - "text": "The "selector-descendant-combinator-no-non-space" rule is deprecated.", - }, - { - "text": "The "selector-list-comma-newline-after" rule is deprecated.", - }, - { - "text": "The "selector-list-comma-space-before" rule is deprecated.", - }, - { - "text": "The "selector-max-empty-lines" rule is deprecated.", - }, - { - "text": "The "selector-pseudo-class-case" rule is deprecated.", - }, - { - "text": "The "selector-pseudo-class-parentheses-space-inside" rule is deprecated.", - }, - { - "text": "The "selector-pseudo-element-case" rule is deprecated.", - }, - { - "text": "The "unit-case" rule is deprecated.", - }, - { - "text": "The "value-list-comma-newline-after" rule is deprecated.", - }, - { - "text": "The "value-list-comma-space-after" rule is deprecated.", - }, - { - "text": "The "value-list-comma-space-before" rule is deprecated.", - }, - { - "text": "The "value-list-max-empty-lines" rule is deprecated.", - }, - { - "text": "The "indentation" rule is deprecated.", - }, - ], + "deprecations": [], "errored": true, "invalidOptionWarnings": [], "parseErrors": [], @@ -210,252 +26,7 @@ exports[`fs - zen garden CSS with standard config 1`] = ` "reportedDisables": [], "results": [ { - "deprecations": [ - { - "reference": undefined, - "text": "The "at-rule-name-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "at-rule-name-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "at-rule-semicolon-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-closing-brace-empty-line-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-closing-brace-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-closing-brace-newline-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-closing-brace-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-opening-brace-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-opening-brace-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-opening-brace-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "color-hex-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-bang-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-bang-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-semicolon-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-semicolon-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-semicolon-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-trailing-semicolon" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-colon-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-colon-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-colon-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-comma-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-parentheses-newline-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-parentheses-space-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-whitespace-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-colon-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-colon-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-name-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-parentheses-space-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-range-operator-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-range-operator-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-query-list-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-query-list-comma-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-query-list-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "no-eol-whitespace" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "no-extra-semicolons" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "no-missing-end-of-source-newline" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "number-leading-zero" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "number-no-trailing-zeros" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "property-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-attribute-brackets-space-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-attribute-operator-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-attribute-operator-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-combinator-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-combinator-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-descendant-combinator-no-non-space" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-list-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-list-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-pseudo-class-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-pseudo-class-parentheses-space-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-pseudo-element-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "unit-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "indentation" rule is deprecated.", - }, - ], + "deprecations": [], "errored": true, "ignored": undefined, "invalidOptionWarnings": [], @@ -478,67 +49,12 @@ exports[`fs - zen garden CSS with standard config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/at-rule-empty-line-before", }, - "at-rule-name-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/at-rule-name-case", - }, - "at-rule-name-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/at-rule-name-space-after", - }, "at-rule-no-unknown": { "url": "https://stylelint.io/user-guide/rules/at-rule-no-unknown", }, - "at-rule-semicolon-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/at-rule-semicolon-newline-after", - }, - "block-closing-brace-empty-line-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-closing-brace-empty-line-before", - }, - "block-closing-brace-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-closing-brace-newline-after", - }, - "block-closing-brace-newline-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-closing-brace-newline-before", - }, - "block-closing-brace-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-closing-brace-space-before", - }, "block-no-empty": { "url": "https://stylelint.io/user-guide/rules/block-no-empty", }, - "block-opening-brace-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-opening-brace-newline-after", - }, - "block-opening-brace-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-opening-brace-space-after", - }, - "block-opening-brace-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-opening-brace-space-before", - }, - "color-hex-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/color-hex-case", - }, "color-hex-length": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/color-hex-length", @@ -561,16 +77,6 @@ exports[`fs - zen garden CSS with standard config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/custom-property-empty-line-before", }, - "declaration-bang-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-bang-space-after", - }, - "declaration-bang-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-bang-space-before", - }, "declaration-block-no-duplicate-properties": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/declaration-block-no-duplicate-properties", @@ -578,44 +84,9 @@ exports[`fs - zen garden CSS with standard config 1`] = ` "declaration-block-no-shorthand-property-overrides": { "url": "https://stylelint.io/user-guide/rules/declaration-block-no-shorthand-property-overrides", }, - "declaration-block-semicolon-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-semicolon-newline-after", - }, - "declaration-block-semicolon-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-semicolon-space-after", - }, - "declaration-block-semicolon-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-semicolon-space-before", - }, "declaration-block-single-line-max-declarations": { "url": "https://stylelint.io/user-guide/rules/declaration-block-single-line-max-declarations", }, - "declaration-block-trailing-semicolon": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-trailing-semicolon", - }, - "declaration-colon-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-colon-newline-after", - }, - "declaration-colon-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-colon-space-after", - }, - "declaration-colon-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-colon-space-before", - }, "declaration-empty-line-before": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/declaration-empty-line-before", @@ -630,53 +101,13 @@ exports[`fs - zen garden CSS with standard config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/function-calc-no-unspaced-operator", }, - "function-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-comma-newline-after", - }, - "function-comma-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-comma-space-after", - }, - "function-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-comma-space-before", - }, "function-linear-gradient-no-nonstandard-direction": { "url": "https://stylelint.io/user-guide/rules/function-linear-gradient-no-nonstandard-direction", }, - "function-max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-max-empty-lines", - }, "function-name-case": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/function-name-case", }, - "function-parentheses-newline-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-parentheses-newline-inside", - }, - "function-parentheses-space-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-parentheses-space-inside", - }, - "function-whitespace-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-whitespace-after", - }, - "indentation": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/indentation", - }, "keyframe-declaration-no-important": { "url": "https://stylelint.io/user-guide/rules/keyframe-declaration-no-important", }, @@ -684,59 +115,9 @@ exports[`fs - zen garden CSS with standard config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/length-zero-no-unit", }, - "max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/max-empty-lines", - }, - "media-feature-colon-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-colon-space-after", - }, - "media-feature-colon-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-colon-space-before", - }, - "media-feature-name-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-name-case", - }, "media-feature-name-no-unknown": { "url": "https://stylelint.io/user-guide/rules/media-feature-name-no-unknown", }, - "media-feature-parentheses-space-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-parentheses-space-inside", - }, - "media-feature-range-operator-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-range-operator-space-after", - }, - "media-feature-range-operator-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-range-operator-space-before", - }, - "media-query-list-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-query-list-comma-newline-after", - }, - "media-query-list-comma-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-query-list-comma-space-after", - }, - "media-query-list-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-query-list-comma-space-before", - }, "no-descending-specificity": { "url": "https://stylelint.io/user-guide/rules/no-descending-specificity", }, @@ -749,39 +130,9 @@ exports[`fs - zen garden CSS with standard config 1`] = ` "no-empty-source": { "url": "https://stylelint.io/user-guide/rules/no-empty-source", }, - "no-eol-whitespace": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/no-eol-whitespace", - }, - "no-extra-semicolons": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/no-extra-semicolons", - }, "no-invalid-double-slash-comments": { "url": "https://stylelint.io/user-guide/rules/no-invalid-double-slash-comments", }, - "no-missing-end-of-source-newline": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/no-missing-end-of-source-newline", - }, - "number-leading-zero": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/number-leading-zero", - }, - "number-no-trailing-zeros": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/number-no-trailing-zeros", - }, - "property-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/property-case", - }, "property-no-unknown": { "url": "https://stylelint.io/user-guide/rules/property-no-unknown", }, @@ -789,69 +140,9 @@ exports[`fs - zen garden CSS with standard config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/rule-empty-line-before", }, - "selector-attribute-brackets-space-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-attribute-brackets-space-inside", - }, - "selector-attribute-operator-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-attribute-operator-space-after", - }, - "selector-attribute-operator-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-attribute-operator-space-before", - }, - "selector-combinator-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-combinator-space-after", - }, - "selector-combinator-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-combinator-space-before", - }, - "selector-descendant-combinator-no-non-space": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-descendant-combinator-no-non-space", - }, - "selector-list-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-list-comma-newline-after", - }, - "selector-list-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-list-comma-space-before", - }, - "selector-max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-max-empty-lines", - }, - "selector-pseudo-class-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-pseudo-class-case", - }, "selector-pseudo-class-no-unknown": { "url": "https://stylelint.io/user-guide/rules/selector-pseudo-class-no-unknown", }, - "selector-pseudo-class-parentheses-space-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-pseudo-class-parentheses-space-inside", - }, - "selector-pseudo-element-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-pseudo-element-case", - }, "selector-pseudo-element-colon-notation": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/selector-pseudo-element-colon-notation", @@ -869,11 +160,6 @@ exports[`fs - zen garden CSS with standard config 1`] = ` "string-no-newline": { "url": "https://stylelint.io/user-guide/rules/string-no-newline", }, - "unit-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/unit-case", - }, "unit-no-unknown": { "url": "https://stylelint.io/user-guide/rules/unit-no-unknown", }, @@ -881,26 +167,6 @@ exports[`fs - zen garden CSS with standard config 1`] = ` "fixable": true, "url": "https://stylelint.io/user-guide/rules/value-keyword-case", }, - "value-list-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-newline-after", - }, - "value-list-comma-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-space-after", - }, - "value-list-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-space-before", - }, - "value-list-max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-max-empty-lines", - }, }, } `; diff --git a/system-tests/003/__snapshots__/no-fs.test.mjs.snap b/system-tests/003/__snapshots__/no-fs.test.mjs.snap index dc4f461296..26a8f91f98 100644 --- a/system-tests/003/__snapshots__/no-fs.test.mjs.snap +++ b/system-tests/003/__snapshots__/no-fs.test.mjs.snap @@ -16,454 +16,210 @@ exports[`no-fs - zen garden CSS with standard config 1`] = ` /* Your images should be linked as if the CSS file sits in the same folder as the images. ie. no paths. */ + /* basic elements */ html { - margin: 0; - padding: 0; -} + margin: 0; + padding: 0; + } body { - font: 75% georgia, sans-serif; - line-height: 1.88889; - color: #555753; - background: #fff url(http://csszengarden.com/001/blossoms.jpg) no-repeat bottom right; - margin: 0; - padding: 0; -} + font: 75% georgia, sans-serif; + line-height: 1.88889; + color: #555753; + background: #fff url(http://csszengarden.com/001/blossoms.jpg) no-repeat bottom right; + margin: 0; + padding: 0; + } p { - margin-top: 0; - text-align: justify; -} + margin-top: 0; + text-align: justify; + } h3 { - font: italic normal 1.4em georgia, sans-serif; - letter-spacing: 1px; - margin-bottom: 0; - color: #7d775c; -} + font: italic normal 1.4em georgia, sans-serif; + letter-spacing: 1px; + margin-bottom: 0; + color: #7D775C; + } a:link { - font-weight: bold; - text-decoration: none; - color: #b7a5df; -} + font-weight: bold; + text-decoration: none; + color: #B7A5DF; + } a:visited { - font-weight: bold; - text-decoration: none; - color: #d4cddc; -} + font-weight: bold; + text-decoration: none; + color: #D4CDDC; + } -a:hover, -a:focus, -a:active { - text-decoration: underline; - color: #9685ba; -} +a:hover, a:focus, a:active { + text-decoration: underline; + color: #9685BA; + } abbr { - border-bottom: none; -} + border-bottom: none; + } + /* specific divs */ .page-wrapper { - background: url(http://csszengarden.com/001/zen-bg.jpg) no-repeat top left; - padding: 0 175px 0 110px; - margin: 0; - position: relative; -} + background: url(http://csszengarden.com/001/zen-bg.jpg) no-repeat top left; + padding: 0 175px 0 110px; + margin: 0; + position: relative; + } .intro { - min-width: 470px; - width: 100%; -} + min-width: 470px; + width: 100%; + } header h1 { - background: transparent url(http://csszengarden.com/001/h1.gif) no-repeat top left; - margin-top: 10px; - display: block; - width: 219px; - height: 87px; - float: left; - text-indent: 100%; - white-space: nowrap; - overflow: hidden; -} + background: transparent url(http://csszengarden.com/001/h1.gif) no-repeat top left; + margin-top: 10px; + display: block; + width: 219px; + height: 87px; + float: left; + text-indent: 100%; + white-space: nowrap; + overflow: hidden; + } header h2 { - background: transparent url(http://csszengarden.com/001/h2.gif) no-repeat top left; - margin-top: 58px; - margin-bottom: 40px; - width: 200px; - height: 18px; - float: right; - text-indent: 100%; - white-space: nowrap; - overflow: hidden; -} + background: transparent url(http://csszengarden.com/001/h2.gif) no-repeat top left; + margin-top: 58px; + margin-bottom: 40px; + width: 200px; + height: 18px; + float: right; + text-indent: 100%; + white-space: nowrap; + overflow: hidden; + } header { - padding-top: 20px; - height: 87px; + padding-top: 20px; + height: 87px; } .summary { - clear: both; - margin: 20px 20px 20px 10px; - width: 160px; - float: left; -} + clear: both; + margin: 20px 20px 20px 10px; + width: 160px; + float: left; + } .summary p { - font: italic 1.1em/2.2 georgia; - text-align: center; -} + font: italic 1.1em/2.2 georgia; + text-align: center; + } .preamble { - clear: right; - padding: 0 10px 0; -} + clear: right; + padding: 0 10px 0; + } .supporting { - padding-left: 10px; - margin-bottom: 40px; -} + padding-left: 10px; + margin-bottom: 40px; + } footer { - text-align: center; -} + text-align: center; + } -footer a:link, -footer a:visited { - margin-right: 20px; -} +footer a:link, footer a:visited { + margin-right: 20px; + } .sidebar { - margin-left: 600px; - position: absolute; - top: 0; - right: 0; -} + margin-left: 600px; + position: absolute; + top: 0; + right: 0; + } .sidebar .wrapper { - font: 10px verdana, sans-serif; - background: transparent url(http://csszengarden.com/001/paper-bg.jpg) top left repeat-y; - padding: 10px; - margin-top: 150px; - width: 130px; -} + font: 10px verdana, sans-serif; + background: transparent url(http://csszengarden.com/001/paper-bg.jpg) top left repeat-y; + padding: 10px; + margin-top: 150px; + width: 130px; + } .sidebar h3.select { - background: transparent url(http://csszengarden.com/001/h3.gif) no-repeat top left; - margin: 10px 0 5px; - width: 97px; - height: 16px; - text-indent: 100%; - white-space: nowrap; - overflow: hidden; -} + background: transparent url(http://csszengarden.com/001/h3.gif) no-repeat top left; + margin: 10px 0 5px; + width: 97px; + height: 16px; + text-indent: 100%; + white-space: nowrap; + overflow: hidden; + } .sidebar h3.archives { - background: transparent url(http://csszengarden.com/001/h5.gif) no-repeat top left; - margin: 25px 0 5px; - width: 57px; - height: 14px; - text-indent: 100%; - white-space: nowrap; - overflow: hidden; -} + background: transparent url(http://csszengarden.com/001/h5.gif) no-repeat top left; + margin: 25px 0 5px; + width:57px; + height: 14px; + text-indent: 100%; + white-space: nowrap; + overflow: hidden; + } .sidebar h3.resources { - background: transparent url(http://csszengarden.com/001/h6.gif) no-repeat top left; - margin: 25px 0 5px; - width: 63px; - height: 10px; - text-indent: 100%; - white-space: nowrap; - overflow: hidden; -} + background: transparent url(http://csszengarden.com/001/h6.gif) no-repeat top left; + margin: 25px 0 5px; + width:63px; + height: 10px; + text-indent: 100%; + white-space: nowrap; + overflow: hidden; + } + .sidebar ul { - margin: 0; - padding: 0; -} + margin: 0; + padding: 0; + } .sidebar li { - line-height: 1.3em; - background: transparent url(http://csszengarden.com/001/cr1.gif) no-repeat top center; - display: block; - padding-top: 5px; - margin-bottom: 5px; - list-style-type: none; -} + line-height: 1.3em; + background: transparent url(http://csszengarden.com/001/cr1.gif) no-repeat top center; + display: block; + padding-top: 5px; + margin-bottom: 5px; + list-style-type: none; + } .sidebar li a:link { - color: #988f5e; -} + color: #988F5E; + } .sidebar li a:visited { - color: #b3ae94; -} + color: #B3AE94; + } + .extra1 { - background: transparent url(http://csszengarden.com/001/cr2.gif) top left no-repeat; - position: absolute; - top: 40px; - right: 0; - width: 148px; - height: 110px; -} + background: transparent url(http://csszengarden.com/001/cr2.gif) top left no-repeat; + position: absolute; + top: 40px; + right: 0; + width: 148px; + height: 110px; + } ", "reportedDisables": [], "results": [ { - "deprecations": [ - { - "reference": undefined, - "text": "The "at-rule-name-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "at-rule-name-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "at-rule-semicolon-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-closing-brace-empty-line-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-closing-brace-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-closing-brace-newline-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-closing-brace-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-opening-brace-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-opening-brace-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "block-opening-brace-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "color-hex-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-bang-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-bang-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-semicolon-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-semicolon-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-semicolon-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-block-trailing-semicolon" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-colon-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-colon-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "declaration-colon-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-comma-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-parentheses-newline-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-parentheses-space-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "function-whitespace-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-colon-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-colon-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-name-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-parentheses-space-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-range-operator-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-feature-range-operator-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-query-list-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-query-list-comma-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "media-query-list-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "no-eol-whitespace" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "no-extra-semicolons" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "no-missing-end-of-source-newline" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "number-leading-zero" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "number-no-trailing-zeros" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "property-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-attribute-brackets-space-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-attribute-operator-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-attribute-operator-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-combinator-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-combinator-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-descendant-combinator-no-non-space" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-list-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-list-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-pseudo-class-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-pseudo-class-parentheses-space-inside" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "selector-pseudo-element-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "unit-case" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-newline-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-space-after" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-comma-space-before" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "value-list-max-empty-lines" rule is deprecated.", - }, - { - "reference": undefined, - "text": "The "indentation" rule is deprecated.", - }, - ], + "deprecations": [], "errored": true, "ignored": undefined, "invalidOptionWarnings": [], @@ -486,67 +242,12 @@ footer a:visited { "fixable": true, "url": "https://stylelint.io/user-guide/rules/at-rule-empty-line-before", }, - "at-rule-name-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/at-rule-name-case", - }, - "at-rule-name-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/at-rule-name-space-after", - }, "at-rule-no-unknown": { "url": "https://stylelint.io/user-guide/rules/at-rule-no-unknown", }, - "at-rule-semicolon-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/at-rule-semicolon-newline-after", - }, - "block-closing-brace-empty-line-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-closing-brace-empty-line-before", - }, - "block-closing-brace-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-closing-brace-newline-after", - }, - "block-closing-brace-newline-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-closing-brace-newline-before", - }, - "block-closing-brace-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-closing-brace-space-before", - }, "block-no-empty": { "url": "https://stylelint.io/user-guide/rules/block-no-empty", }, - "block-opening-brace-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-opening-brace-newline-after", - }, - "block-opening-brace-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-opening-brace-space-after", - }, - "block-opening-brace-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/block-opening-brace-space-before", - }, - "color-hex-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/color-hex-case", - }, "color-hex-length": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/color-hex-length", @@ -569,16 +270,6 @@ footer a:visited { "fixable": true, "url": "https://stylelint.io/user-guide/rules/custom-property-empty-line-before", }, - "declaration-bang-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-bang-space-after", - }, - "declaration-bang-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-bang-space-before", - }, "declaration-block-no-duplicate-properties": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/declaration-block-no-duplicate-properties", @@ -586,44 +277,9 @@ footer a:visited { "declaration-block-no-shorthand-property-overrides": { "url": "https://stylelint.io/user-guide/rules/declaration-block-no-shorthand-property-overrides", }, - "declaration-block-semicolon-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-semicolon-newline-after", - }, - "declaration-block-semicolon-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-semicolon-space-after", - }, - "declaration-block-semicolon-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-semicolon-space-before", - }, "declaration-block-single-line-max-declarations": { "url": "https://stylelint.io/user-guide/rules/declaration-block-single-line-max-declarations", }, - "declaration-block-trailing-semicolon": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-block-trailing-semicolon", - }, - "declaration-colon-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-colon-newline-after", - }, - "declaration-colon-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-colon-space-after", - }, - "declaration-colon-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/declaration-colon-space-before", - }, "declaration-empty-line-before": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/declaration-empty-line-before", @@ -638,53 +294,13 @@ footer a:visited { "fixable": true, "url": "https://stylelint.io/user-guide/rules/function-calc-no-unspaced-operator", }, - "function-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-comma-newline-after", - }, - "function-comma-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-comma-space-after", - }, - "function-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-comma-space-before", - }, "function-linear-gradient-no-nonstandard-direction": { "url": "https://stylelint.io/user-guide/rules/function-linear-gradient-no-nonstandard-direction", }, - "function-max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-max-empty-lines", - }, "function-name-case": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/function-name-case", }, - "function-parentheses-newline-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-parentheses-newline-inside", - }, - "function-parentheses-space-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-parentheses-space-inside", - }, - "function-whitespace-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/function-whitespace-after", - }, - "indentation": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/indentation", - }, "keyframe-declaration-no-important": { "url": "https://stylelint.io/user-guide/rules/keyframe-declaration-no-important", }, @@ -692,59 +308,9 @@ footer a:visited { "fixable": true, "url": "https://stylelint.io/user-guide/rules/length-zero-no-unit", }, - "max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/max-empty-lines", - }, - "media-feature-colon-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-colon-space-after", - }, - "media-feature-colon-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-colon-space-before", - }, - "media-feature-name-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-name-case", - }, "media-feature-name-no-unknown": { "url": "https://stylelint.io/user-guide/rules/media-feature-name-no-unknown", }, - "media-feature-parentheses-space-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-parentheses-space-inside", - }, - "media-feature-range-operator-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-range-operator-space-after", - }, - "media-feature-range-operator-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-feature-range-operator-space-before", - }, - "media-query-list-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-query-list-comma-newline-after", - }, - "media-query-list-comma-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-query-list-comma-space-after", - }, - "media-query-list-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/media-query-list-comma-space-before", - }, "no-descending-specificity": { "url": "https://stylelint.io/user-guide/rules/no-descending-specificity", }, @@ -757,39 +323,9 @@ footer a:visited { "no-empty-source": { "url": "https://stylelint.io/user-guide/rules/no-empty-source", }, - "no-eol-whitespace": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/no-eol-whitespace", - }, - "no-extra-semicolons": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/no-extra-semicolons", - }, "no-invalid-double-slash-comments": { "url": "https://stylelint.io/user-guide/rules/no-invalid-double-slash-comments", }, - "no-missing-end-of-source-newline": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/no-missing-end-of-source-newline", - }, - "number-leading-zero": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/number-leading-zero", - }, - "number-no-trailing-zeros": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/number-no-trailing-zeros", - }, - "property-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/property-case", - }, "property-no-unknown": { "url": "https://stylelint.io/user-guide/rules/property-no-unknown", }, @@ -797,69 +333,9 @@ footer a:visited { "fixable": true, "url": "https://stylelint.io/user-guide/rules/rule-empty-line-before", }, - "selector-attribute-brackets-space-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-attribute-brackets-space-inside", - }, - "selector-attribute-operator-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-attribute-operator-space-after", - }, - "selector-attribute-operator-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-attribute-operator-space-before", - }, - "selector-combinator-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-combinator-space-after", - }, - "selector-combinator-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-combinator-space-before", - }, - "selector-descendant-combinator-no-non-space": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-descendant-combinator-no-non-space", - }, - "selector-list-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-list-comma-newline-after", - }, - "selector-list-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-list-comma-space-before", - }, - "selector-max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-max-empty-lines", - }, - "selector-pseudo-class-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-pseudo-class-case", - }, "selector-pseudo-class-no-unknown": { "url": "https://stylelint.io/user-guide/rules/selector-pseudo-class-no-unknown", }, - "selector-pseudo-class-parentheses-space-inside": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-pseudo-class-parentheses-space-inside", - }, - "selector-pseudo-element-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/selector-pseudo-element-case", - }, "selector-pseudo-element-colon-notation": { "fixable": true, "url": "https://stylelint.io/user-guide/rules/selector-pseudo-element-colon-notation", @@ -877,11 +353,6 @@ footer a:visited { "string-no-newline": { "url": "https://stylelint.io/user-guide/rules/string-no-newline", }, - "unit-case": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/unit-case", - }, "unit-no-unknown": { "url": "https://stylelint.io/user-guide/rules/unit-no-unknown", }, @@ -889,26 +360,6 @@ footer a:visited { "fixable": true, "url": "https://stylelint.io/user-guide/rules/value-keyword-case", }, - "value-list-comma-newline-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-newline-after", - }, - "value-list-comma-space-after": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-space-after", - }, - "value-list-comma-space-before": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-comma-space-before", - }, - "value-list-max-empty-lines": { - "deprecated": true, - "fixable": true, - "url": "https://stylelint.io/user-guide/rules/value-list-max-empty-lines", - }, }, } `; diff --git a/system-tests/003/config.json b/system-tests/003/config.json index 2f5fdd5158..027d4623b4 100755 --- a/system-tests/003/config.json +++ b/system-tests/003/config.json @@ -7,19 +7,8 @@ "ignore": ["after-comment"] } ], - "at-rule-name-case": "lower", - "at-rule-name-space-after": "always-single-line", "at-rule-no-unknown": true, - "at-rule-semicolon-newline-after": "always", - "block-closing-brace-empty-line-before": "never", - "block-closing-brace-newline-after": "always", - "block-closing-brace-newline-before": "always-multi-line", - "block-closing-brace-space-before": "always-single-line", "block-no-empty": true, - "block-opening-brace-newline-after": "always-multi-line", - "block-opening-brace-space-after": "always-single-line", - "block-opening-brace-space-before": "always", - "color-hex-case": "lower", "color-hex-length": "short", "color-no-invalid-hex": true, "comment-empty-line-before": [ @@ -38,8 +27,6 @@ "ignore": ["after-comment", "inside-single-line-block"] } ], - "declaration-bang-space-after": "never", - "declaration-bang-space-before": "always", "declaration-block-no-duplicate-properties": [ true, { @@ -47,14 +34,7 @@ } ], "declaration-block-no-shorthand-property-overrides": true, - "declaration-block-semicolon-newline-after": "always-multi-line", - "declaration-block-semicolon-space-after": "always-single-line", - "declaration-block-semicolon-space-before": "never", "declaration-block-single-line-max-declarations": 1, - "declaration-block-trailing-semicolon": "always", - "declaration-colon-newline-after": "always-multi-line", - "declaration-colon-space-after": "always-single-line", - "declaration-colon-space-before": "never", "declaration-empty-line-before": [ "always", { @@ -65,40 +45,16 @@ "font-family-no-duplicate-names": true, "font-family-no-missing-generic-family-keyword": true, "function-calc-no-unspaced-operator": true, - "function-comma-newline-after": "always-multi-line", - "function-comma-space-after": "always-single-line", - "function-comma-space-before": "never", "function-linear-gradient-no-nonstandard-direction": true, - "function-max-empty-lines": 0, "function-name-case": "lower", - "function-parentheses-newline-inside": "always-multi-line", - "function-parentheses-space-inside": "never-single-line", - "function-whitespace-after": "always", - "indentation": 2, "keyframe-declaration-no-important": true, "length-zero-no-unit": true, - "max-empty-lines": 1, - "media-feature-colon-space-after": "always", - "media-feature-colon-space-before": "never", - "media-feature-name-case": "lower", "media-feature-name-no-unknown": true, - "media-feature-parentheses-space-inside": "never", - "media-feature-range-operator-space-after": "always", - "media-feature-range-operator-space-before": "always", - "media-query-list-comma-newline-after": "always-multi-line", - "media-query-list-comma-space-after": "always-single-line", - "media-query-list-comma-space-before": "never", "no-descending-specificity": true, "no-duplicate-at-import-rules": true, "no-duplicate-selectors": true, "no-empty-source": true, - "no-eol-whitespace": true, - "no-extra-semicolons": true, "no-invalid-double-slash-comments": true, - "no-missing-end-of-source-newline": true, - "number-leading-zero": "always", - "number-no-trailing-zeros": true, - "property-case": "lower", "property-no-unknown": true, "rule-empty-line-before": [ "always-multi-line", @@ -107,30 +63,13 @@ "ignore": ["after-comment"] } ], - "selector-attribute-brackets-space-inside": "never", - "selector-attribute-operator-space-after": "never", - "selector-attribute-operator-space-before": "never", - "selector-combinator-space-after": "always", - "selector-combinator-space-before": "always", - "selector-descendant-combinator-no-non-space": true, - "selector-list-comma-newline-after": "always", - "selector-list-comma-space-before": "never", - "selector-max-empty-lines": 0, - "selector-pseudo-class-case": "lower", "selector-pseudo-class-no-unknown": true, - "selector-pseudo-class-parentheses-space-inside": "never", - "selector-pseudo-element-case": "lower", "selector-pseudo-element-colon-notation": "double", "selector-pseudo-element-no-unknown": true, "selector-type-case": "lower", "selector-type-no-unknown": true, "string-no-newline": true, - "unit-case": "lower", "unit-no-unknown": true, - "value-keyword-case": "lower", - "value-list-comma-newline-after": "always-multi-line", - "value-list-comma-space-after": "always-single-line", - "value-list-comma-space-before": "never", - "value-list-max-empty-lines": 0 + "value-keyword-case": "lower" } }