Stejně jako učitelé chtěli, aby žáci psali krásně a čitelně, i programátoři chtějí, aby všichni psali kód čistě a přehledně. Každý si pod tím ale může představit něco trochu jiného. Někdo chce složené závorky na novém řádku, jiný ne. CSS pravidla seřazené abecedně nebo mít omezenou maximální délku řádku. Někdy může být i náročné na vše pamatovat, a v tu chvíli pomůže Stylelint. Nástroj, který definovaná pravidla kontroluje, upozorní na jejich nedodržení a někdy i opraví.
Stylelint + Webpack a Laravel Mix
Stylelint se chlubí, že jej používá Facebook a na Githubu najdete pravidla, která používá samotný Github (Primer) či Wordpress. Nejedná se tedy o žádné ořezávátko. Osobně jsem jej použil při tvorbě tohoto blogu. A zprovoznění je jednodušší než dodržování samotných pravidel.
.stylelintrc + .stylelintignore
Nejdůležitějším souborem je .stylelintrc, který je ve formátu YAML a obsahuje všechna pravidla. Jejich úplný seznam lze najít v dokumentaci ale výhodné je rozšířit existující soubor pravidel a také používat pluginy. Dále soubor .stylelintignore může obsahovat soubory, které při lintování ignorovat, nejčastěji stažené knihovny apod. Soubor může vypadat třeba tako
---
extends: stylelint-config-standard
plugins:
- stylelint-order
- stylelint-scss
rules:
####
# Basic rules
####
at-rule-empty-line-before:
- always
- except:
- first-nested
ignore:
- after-comment
ignoreAtRules:
- else
- import
at-rule-no-unknown: null
at-rule-no-vendor-prefix: true
block-closing-brace-newline-before: always
block-opening-brace-newline-after: always
color-hex-case: lower
color-hex-length: long
color-named: never
comment-whitespace-inside: always
declaration-block-no-redundant-longhand-properties: true
declaration-block-trailing-semicolon: always
declaration-block-semicolon-newline-after: always
declaration-block-single-line-max-declarations: 1
declaration-colon-space-before: never
declaration-colon-space-after: always
function-calc-no-invalid: true
function-url-no-scheme-relative: true
function-url-quotes: always
# font-family-name-quotes: always-where-required
indentation: 4
linebreaks: unix
max-line-length: 120
media-feature-range-operator-space-before: always
media-feature-range-operator-space-after: always
media-feature-parentheses-space-inside: never
media-feature-name-no-vendor-prefix: true
media-feature-colon-space-before: never
media-feature-colon-space-after: always
no-empty-first-line: true
no-eol-whitespace: true
no-descending-specificity: null
no-duplicate-selectors: true
number-leading-zero: always
property-no-vendor-prefix: true
rule-empty-line-before:
- always-multi-line
- except:
- after-single-line-comment
- first-nested
ignore:
- after-comment
selector-attribute-quotes: always
selector-attribute-operator-space-before: never
selector-attribute-operator-space-after: never
selector-attribute-brackets-space-inside: never
selector-class-pattern: "^(?!js-)[a-z0-9-]+$"
selector-list-comma-newline-after: null # Disable check
selector-max-id: 0
selector-no-vendor-prefix: true
selector-combinator-space-after: always
selector-pseudo-element-colon-notation: double
selector-pseudo-class-parentheses-space-inside: never
string-quotes: single
value-keyword-case: lower
value-no-vendor-prefix: true
####
# Order plugin
####
order/properties-alphabetical-order: true
order/order:
- custom-properties
- dollar-variables
- declarations
- type: rule
selector: '^&:[\w-]+$'
- rules
# - at-rules
####
# Scss plugin
####
scss/at-function-parentheses-space-before: never
scss/at-function-pattern: "^[a-z0-9-]+$"
scss/at-import-no-partial-leading-underscore: true
scss/at-rule-no-unknown: true
scss/dollar-variable-colon-newline-after: always-multi-line
scss/dollar-variable-colon-space-after: always-single-line
scss/dollar-variable-colon-space-before: never
scss/dollar-variable-pattern: "^[a-z0-9_]+$"
scss/declaration-nested-properties: never
scss/function-quote-no-quoted-strings-inside: true
scss/operator-no-newline-after: true
scss/operator-no-newline-before: true
scss/selector-no-redundant-nesting-selector: true
scss/no-duplicate-dollar-variables:
- true
- ignoreInside: at-rule
# SCSS plugin example config
block-opening-brace-space-before: always
block-closing-brace-newline-after:
- always
- ignoreAtRules:
- if
- else
at-rule-name-space-after: always
scss/at-else-closing-brace-newline-after: always-last-in-chain
scss/at-else-closing-brace-space-after: always-intermediate
scss/at-else-empty-line-before: never
scss/at-if-closing-brace-newline-after: always-last-in-chain
scss/at-if-closing-brace-space-after: always-intermediate
Instalace
Základ je nainstalovat Stylelint pomocí NPM. Při použití mého configu zmíněného výše je potřeba doinstalovat pluginy a výchozí pravidla a také Stylelint SCSS pokud bude použito SCSS.
npm i stylelint stylelint-config-standard stylelint-order stylelint-scss --save-dev
Kromě kontroly umí Stylelint i některé chyby sám opravit. K tomu stačí při spuštění přidat přepínač --fix. Nejjednodušší spuštění je z příkazové řádky s adresou k souborům.
# Spuštění lintu
npx stylelint resources/sass/
# Spuštění lintu s automatickou opravou
npx stylelint resources/sass/ --fix
Spouštění z Webpacku - Laravel Mixu
Přiznám se, s Webpackem neumím, proto následující ukázka obsahuje pouze konfiguraci pro Laravel Mix, který ale Webpack používá. Je tedy nutné nainstalovat webpack plugin a také registrovat do Mixu. Pokud je některé pravidlo porušeno, je zobrazena chyba i s popisem. Výsledné CSS ale je i přesto vygenerováno.
npm i stylelint-webpack-plugin --save-dev
// Tento kód přidat do webpack.mix.js
const StyleLintPlugin = require('stylelint-webpack-plugin');
mix.extend('styleLint', (config) => { config.plugins.push(new StyleLintPlugin({ files: 'resources/sass/**/*.s?(a|c)ss' })); });
mix.styleLint();
Osobní zkušenosti se Stylelintem či jinými CSS lintery můžete sdílet v komentářích
K tomuto článku již není možné přidávat další komentáře