diff --git a/README.md b/README.md index 4184d21..6688efe 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,10 @@ Extends [`stylelint-config-recommended`](https://github.com/stylelint/stylelint-config-recommended). -Turns on additional rules to enforce the common stylistic conventions found within a handful of CSS styleguides, including: [The Idiomatic CSS Principles](https://github.com/necolas/idiomatic-css), +Turns on additional rules to enforce common conventions found in the specifications and in a handful of CSS styleguides, including: [The Idiomatic CSS Principles](https://github.com/necolas/idiomatic-css), [Google's CSS Style Guide](https://google.github.io/styleguide/htmlcssguide.html#CSS_Formatting_Rules), [Airbnb's Styleguide](https://github.com/airbnb/css#css), and [@mdo's Code Guide](https://codeguide.co/#css). -It favours flexibility over strictness for things like multi-line lists and single-line rulesets, and tries to avoid potentially divisive rules. - -Use it as is or as a foundation for your own config. +It favours flexibility over strictness for things like multi-line lists and single-line rulesets. To see the rules that this config uses, please read the [config itself](./index.js). @@ -19,26 +17,30 @@ To see the rules that this config uses, please read the [config itself](./index. ```css -@import url(x.css); -@import url(y.css); +@import url("x.css"); +@import url("y.css"); /** * Multi-line comment */ +:root { + --brand-red: hsl(5deg 10% 40%); +} + .selector-1, .selector-2, .selector-3[type="text"] { - background: linear-gradient(#fff, rgba(0, 0, 0, 0.8)); + background: linear-gradient(#fff, rgb(0 0 0 / 80%)); box-sizing: border-box; display: block; - color: #333; + color: var(--brand-red); } .selector-a, .selector-b:not(:first-child) { padding: 10px !important; - top: calc(calc(1em * 2) / 3); + top: calc(100% - 2rem); } .selector-x { width: 10%; } @@ -56,8 +58,8 @@ To see the rules that this config uses, please read the [config itself](./index. @media (orientation: portrait), projection and (color) { .selector-i + .selector-ii { - background: color(rgb(0, 0, 0) lightness(50%)); - font-family: helvetica, "arial black", sans-serif; + background: hsl(20deg 25% 33%); + font-family: Helvetica, "Arial Black", sans-serif; } } @@ -66,12 +68,13 @@ To see the rules that this config uses, please read the [config itself](./index. screen and (min-resolution: 192dpi), screen and (min-resolution: 2dppx) { .selector { + animation: 3s none fade-in; background-image: repeating-linear-gradient( -45deg, transparent, #fff 25px, - rgba(255, 255, 255, 1) 50px + rgb(255 255 255 / 100%) 50px ); margin: 10px; margin-bottom: 5px; @@ -84,10 +87,15 @@ To see the rules that this config uses, please read the [config itself](./index. /* Flush nested single line comment */ .selector::after { - content: '→'; - background-image: url(x.svg); + content: "→"; + background-image: url("x.svg"); } } + +@keyframes fade-in { + from { opacity: 0%; } + to { opacity: 100%; } +} ``` _Note: the config is tested against this example, as such the example contains plenty of CSS syntax, formatting and features._ @@ -100,23 +108,7 @@ npm install stylelint-config-standard --save-dev ## Usage -If you've installed `stylelint-config-standard` locally within your project, just set your `stylelint` config to: - -```json -{ - "extends": "stylelint-config-standard" -} -``` - -If you've globally installed `stylelint-config-standard` using the `-g` flag, then you'll need to use the absolute path to `stylelint-config-standard` in your config e.g. - -```json -{ - "extends": "/absolute/path/to/stylelint-config-standard" -} -``` - -Since [stylelint 9.7.0](https://github.com/stylelint/stylelint/blob/9.7.0/CHANGELOG.md#970), you can simply use the globally installed configuration name instead of the absolute path: +Set your stylelint config to: ```json { @@ -126,7 +118,7 @@ Since [stylelint 9.7.0](https://github.com/stylelint/stylelint/blob/9.7.0/CHANGE ### Extending the config -Simply add a `"rules"` key to your config, then add your overrides and additions there. +Add a `"rules"` key to your config, then add your overrides and additions there. For example, to change the `at-rule-no-unknown` rule to use its `ignoreAtRules` option, change the `indentation` to tabs, turn off the `number-leading-zero` rule,and add the `unit-allowed-list` rule: @@ -137,7 +129,7 @@ For example, to change the `at-rule-no-unknown` rule to use its `ignoreAtRules` "at-rule-no-unknown": [ true, { - "ignoreAtRules": ["extends", "ignores"] + "ignoreAtRules": ["--my-at-rule"] } ], "indentation": "tab", @@ -151,24 +143,22 @@ For example, to change the `at-rule-no-unknown` rule to use its `ignoreAtRules` `stylelint-config-standard` is a great foundation for your own config. You can extend it to create a tailored and much stricter config: -- Specify what quotes must be used using: - - [`font-family-name-quotes`](https://github.com/stylelint/stylelint/blob/master/lib/rules/font-family-name-quotes/README.md) - - [`function-url-quotes`](https://github.com/stylelint/stylelint/blob/master/lib/rules/function-url-quotes/README.md) - - [`selector-attribute-quotes`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-attribute-quotes/README.md) - - [`string-quotes`](https://github.com/stylelint/stylelint/blob/master/lib/rules/string-quotes/README.md) -- If you use [`autoprefixer`](https://github.com/postcss/autoprefixer) you'll want to disallow vendor prefixes using: - - [`at-rule-no-vendor-prefix`](https://github.com/stylelint/stylelint/blob/master/lib/rules/at-rule-no-vendor-prefix/README.md) - - [`media-feature-name-no-vendor-prefix`](https://github.com/stylelint/stylelint/blob/master/lib/rules/media-feature-name-no-vendor-prefix/README.md) - - [`property-no-vendor-prefix`](https://github.com/stylelint/stylelint/blob/master/lib/rules/property-no-vendor-prefix/README.md) - - [`selector-no-vendor-prefix`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-no-vendor-prefix/README.md) - - [`value-no-vendor-prefix`](https://github.com/stylelint/stylelint/blob/master/lib/rules/value-no-vendor-prefix/README.md) -- Control specificity using: +- Manage specificity using: - [`max-nesting-depth`](https://github.com/stylelint/stylelint/blob/master/lib/rules/max-nesting-depth/README.md) + - [`selector-max-attribute`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-max-attribute/README.md) + - [`selector-max-class`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-max-class/README.md) + - [`selector-max-combinators`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-max-combinators/README.md) - [`selector-max-compound-selectors`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-max-compound-selectors/README.md) + - [`selector-max-id`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-max-id/README.md) + - [`selector-max-pseudo-class`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-max-pseudo-class/README.md) - [`selector-max-specificity`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-max-specificity/README.md) + - [`selector-max-type`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-max-type/README.md) + - [`selector-max-universal`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-max-universal/README.md) + - [`selector-no-qualifying-type`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-no-qualifying-type/README.md) - Specify acceptable selector types, units, properties, functions and words in comments using: - [`at-rule-disallowed-list`](https://github.com/stylelint/stylelint/blob/master/lib/rules/at-rule-disallowed-list/README.md) - [`at-rule-allowed-list`](https://github.com/stylelint/stylelint/blob/master/lib/rules/at-rule-allowed-list/README.md) + - [`at-rule-property-required-list`](https://github.com/stylelint/stylelint/blob/master/lib/rules/at-rule-property-required-list/README.md) - [`color-named`](https://github.com/stylelint/stylelint/blob/master/lib/rules/color-named/README.md) - [`color-no-hex`](https://github.com/stylelint/stylelint/blob/master/lib/rules/color-no-hex/README.md) - [`comment-word-disallowed-list`](https://github.com/stylelint/stylelint/blob/master/lib/rules/comment-word-disallowed-list/README.md) @@ -189,55 +179,18 @@ For example, to change the `at-rule-no-unknown` rule to use its `ignoreAtRules` - [`selector-attribute-operator-allowed-list`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-attribute-operator-allowed-list/README.md) - [`selector-combinator-disallowed-list`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-combinator-disallowed-list/README.md) - [`selector-combinator-allowed-list`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-combinator-allowed-list/README.md) - - [`selector-max-class`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-max-class/README.md) - - [`selector-max-attribute`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-max-attribute/README.md) - - [`selector-max-combinators`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-max-combinators/README.md) - - [`selector-max-id`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-max-id/README.md) - - [`selector-max-pseudo-class`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-max-pseudo-class/README.md) - - [`selector-no-qualifying-type`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-no-qualifying-type/README.md) - - [`selector-max-type`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-max-type/README.md) - - [`selector-max-universal`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-max-universal/README.md) - [`selector-pseudo-class-disallowed-list`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-pseudo-class-disallowed-list/README.md) - [`selector-pseudo-class-allowed-list`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-pseudo-class-allowed-list/README.md) - [`selector-pseudo-element-disallowed-list`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-pseudo-element-disallowed-list/README.md) - [`selector-pseudo-element-allowed-list`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-pseudo-element-allowed-list/README.md) - [`unit-disallowed-list`](https://github.com/stylelint/stylelint/blob/master/lib/rules/unit-disallowed-list/README.md) - [`unit-allowed-list`](https://github.com/stylelint/stylelint/blob/master/lib/rules/unit-allowed-list/README.md) -- Specify acceptable naming patterns using: - - [`custom-media-pattern`](https://github.com/stylelint/stylelint/blob/master/lib/rules/custom-media-pattern/README.md) - - [`custom-property-pattern`](https://github.com/stylelint/stylelint/blob/master/lib/rules/custom-property-pattern/README.md) - - [`selector-class-pattern`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-class-pattern/README.md) - - [`selector-id-pattern`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-id-pattern/README.md) +- Specify acceptable patterns using: - [`selector-nested-pattern`](https://github.com/stylelint/stylelint/blob/master/lib/rules/selector-nested-pattern/README.md) -- Specify a notation when there are one or more valid representations using: +- Specify a notation for font weights using: - [`font-weight-notation`](https://github.com/stylelint/stylelint/blob/master/lib/rules/font-weight-notation/README.md) - Specify what types of URLs are allowed using: - [`function-url-no-scheme-relative`](https://github.com/stylelint/stylelint/blob/master/lib/rules/function-url-no-scheme-relative/README.md) -- Specify a maximum line length using: - - [`max-line-length`](https://github.com/stylelint/stylelint/blob/master/lib/rules/max-line-length/README.md) - -### Using the config with SugarSS syntax - -The config is broadly compatible with [SugarSS](https://github.com/postcss/sugarss) syntax. You _will_ need to turn off the rules that check braces and semicolons, as so: - -```json -{ - "extends": "stylelint-config-standard", - "rules": { - "block-closing-brace-empty-line-before": null, - "block-closing-brace-newline-after": null, - "block-closing-brace-newline-before": null, - "block-closing-brace-space-before": null, - "block-opening-brace-newline-after": null, - "block-opening-brace-space-after": null, - "block-opening-brace-space-before": null, - "declaration-block-semicolon-newline-after": null, - "declaration-block-semicolon-space-after": null, - "declaration-block-semicolon-space-before": null, - "declaration-block-trailing-semicolon": null - } -} -``` ## [Changelog](CHANGELOG.md) diff --git a/__tests__/css-valid.css b/__tests__/css-valid.css index 838bce2..1910827 100644 --- a/__tests__/css-valid.css +++ b/__tests__/css-valid.css @@ -1,23 +1,27 @@ -@import url(x.css); -@import url(y.css); +@import url("x.css"); +@import url("y.css"); /** * Multi-line comment */ +:root { + --brand-red: hsl(5deg 10% 40%); +} + .selector-1, .selector-2, .selector-3[type="text"] { - background: linear-gradient(#fff, rgba(0, 0, 0, 0.8)); + background: linear-gradient(#fff, rgb(0 0 0 / 80%)); box-sizing: border-box; display: block; - color: #333; + color: var(--brand-red); } .selector-a, .selector-b:not(:first-child) { padding: 10px !important; - top: calc(calc(1em * 2) / 3); + top: calc(100% - 2rem); } .selector-x { width: 10%; } @@ -35,8 +39,8 @@ @media (orientation: portrait), projection and (color) { .selector-i + .selector-ii { - background: color(rgb(0, 0, 0) lightness(50%)); - font-family: helvetica, "arial black", sans-serif; + background: hsl(20deg 25% 33%); + font-family: Helvetica, "Arial Black", sans-serif; } } @@ -45,12 +49,13 @@ screen and (min-resolution: 192dpi), screen and (min-resolution: 2dppx) { .selector { + animation: 3s none fade-in; background-image: repeating-linear-gradient( -45deg, transparent, #fff 25px, - rgba(255, 255, 255, 1) 50px + rgb(255 255 255 / 100%) 50px ); margin: 10px; margin-bottom: 5px; @@ -63,7 +68,12 @@ /* Flush nested single line comment */ .selector::after { - content: '→'; - background-image: url(x.svg); + content: "→"; + background-image: url("x.svg"); } } + +@keyframes fade-in { + from { opacity: 0%; } + to { opacity: 100%; } +} diff --git a/index.js b/index.js index b7a7c1f..c0459ba 100644 --- a/index.js +++ b/index.js @@ -3,6 +3,7 @@ module.exports = { extends: 'stylelint-config-recommended', rules: { + 'alpha-value-notation': 'percentage', 'at-rule-empty-line-before': [ 'always', { @@ -12,6 +13,7 @@ module.exports = { ], 'at-rule-name-case': 'lower', 'at-rule-name-space-after': 'always-single-line', + 'at-rule-no-vendor-prefix': true, 'at-rule-semicolon-newline-after': 'always', 'block-closing-brace-empty-line-before': 'never', 'block-closing-brace-newline-after': 'always', @@ -20,6 +22,7 @@ module.exports = { 'block-opening-brace-newline-after': 'always-multi-line', 'block-opening-brace-space-after': 'always-single-line', 'block-opening-brace-space-before': 'always', + 'color-function-notation': 'modern', 'color-hex-case': 'lower', 'color-hex-length': 'short', 'comment-empty-line-before': [ @@ -37,6 +40,8 @@ module.exports = { ignore: ['after-comment', 'inside-single-line-block'], }, ], + 'custom-media-pattern': /^([a-z][a-z0-9]*)(-[a-z0-9]+)*$/, + 'custom-property-pattern': /^([a-z][a-z0-9]*)(-[a-z0-9]+)*$/, 'declaration-bang-space-after': 'never', 'declaration-bang-space-before': 'always', 'declaration-block-semicolon-newline-after': 'always-multi-line', @@ -44,6 +49,7 @@ module.exports = { 'declaration-block-semicolon-space-before': 'never', 'declaration-block-single-line-max-declarations': 1, 'declaration-block-trailing-semicolon': 'always', + 'declaration-block-no-redundant-longhand-properties': true, 'declaration-colon-newline-after': 'always-multi-line', 'declaration-colon-space-after': 'always-single-line', 'declaration-colon-space-before': 'never', @@ -54,6 +60,7 @@ module.exports = { ignore: ['after-comment', 'inside-single-line-block'], }, ], + 'font-family-name-quotes': 'always-where-recommended', 'function-comma-newline-after': 'always-multi-line', 'function-comma-space-after': 'always-single-line', 'function-comma-space-before': 'never', @@ -61,24 +68,33 @@ module.exports = { 'function-name-case': 'lower', 'function-parentheses-newline-inside': 'always-multi-line', 'function-parentheses-space-inside': 'never-single-line', + 'function-url-quotes': 'always', 'function-whitespace-after': 'always', + 'hue-degree-notation': 'angle', indentation: 2, + 'keyframes-name-pattern': /^([a-z][a-z0-9]*)(-[a-z0-9]+)*$/, 'length-zero-no-unit': true, 'max-empty-lines': 1, + 'max-line-length': 120, 'media-feature-colon-space-after': 'always', 'media-feature-colon-space-before': 'never', 'media-feature-name-case': 'lower', + 'media-feature-name-no-vendor-prefix': 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-empty-first-line': true, 'no-eol-whitespace': true, + 'no-irregular-whitespace': true, 'no-missing-end-of-source-newline': true, 'number-leading-zero': 'always', + 'number-max-precision': 4, 'number-no-trailing-zeros': true, 'property-case': 'lower', + 'property-no-vendor-prefix': true, 'rule-empty-line-before': [ 'always-multi-line', { @@ -89,22 +105,29 @@ module.exports = { 'selector-attribute-brackets-space-inside': 'never', 'selector-attribute-operator-space-after': 'never', 'selector-attribute-operator-space-before': 'never', + 'selector-attribute-quotes': 'always', + 'selector-class-pattern': /^([a-z][a-z0-9]*)(-[a-z0-9]+)*$/, 'selector-combinator-space-after': 'always', 'selector-combinator-space-before': 'always', 'selector-descendant-combinator-no-non-space': true, + 'selector-id-pattern': /^([a-z][a-z0-9]*)(-[a-z0-9]+)*$/, 'selector-list-comma-newline-after': 'always', 'selector-list-comma-space-before': 'never', 'selector-max-empty-lines': 0, + 'selector-no-vendor-prefix': true, 'selector-pseudo-class-case': 'lower', 'selector-pseudo-class-parentheses-space-inside': 'never', 'selector-pseudo-element-case': 'lower', 'selector-pseudo-element-colon-notation': 'double', 'selector-type-case': 'lower', + 'shorthand-property-no-redundant-values': true, + 'string-quotes': 'double', 'unit-case': 'lower', '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-no-vendor-prefix': true, }, };