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