diff --git a/packages/stylelint-config/README.md b/packages/stylelint-config/README.md new file mode 100644 index 0000000000..9911927387 --- /dev/null +++ b/packages/stylelint-config/README.md @@ -0,0 +1,104 @@ +# lucca-front / Stylelint config + +This package is a shareable stylelint configuration. + +[Stylelint](https://stylelint.io/) checks for common mistakes in CSS and CSS-like files, and allows to define rules for tools and developers. + +[Prettier should be used](https://stylelint.io/#how-itll-help-you) to handle coding style-guides when possible. + +## Install + +``` +npm uninstall stylelint && npm i --save-dev @lucca/stylelint-config +``` + +## Avoid conflicts + +Remove any pre-existing [configuration](https://stylelint.io/user-guide/configure) (file or statements in package.json). + +## Configure + +### For your local project + +Use this package in a _stylelint.config.js_ file in your repository: + +```js +module.exports = { + extends: ['@lucca/stylelint-config'], + rules: {}, +}; +``` + +### For your CI + +Add the relevant scripts to lint the code in Jenkins. Something like: + +```json +"lint": "ng lint && npm run stylelint", +"stylelint": "stylelint \"./projects/**/*.scss\"", +``` + +### Breaking the rules + +#### Overrides + +You can [apply specific rules with overrides](https://stylelint.io/user-guide/configure/#overrides) as needed. + +Rules can be disabled while incrementally fixing your code. Set them to `null`: + +```js +module.exports = { + extends: ['@lucca-front/stylelint-config'], + overrides: [ + { + files: ['some-path/**/*.scss'], + rules: { + 'no-descending-specificity': null, + } + }, + ], + rules: {}; +}; +``` + +#### Ignoring code inline + +If needed, each rule can be ignored with [stylelint-(dis|en)able](https://stylelint.io/user-guide/ignore-code). + +Please add a comment if you're doing so: use `styleling-disable[-*] -- comment`. + +## Testing locally + +In your stylelint configuration, temporarily replace `extends: ['@lucca/stylelint-config'],` by `extends: ['RELATIVE_PATH_TO/stylelint-config'],`. + +The configuration from your local repository should be applied right away. + +## Configuring your editor + +### VS Code + +⚠️ A [VSCode extension bug](https://github.com/stylelint/vscode-stylelint/issues/490#issuecomment-1966934533) issue might prevent you from using stylelint 16+. + +Follow instructions on the [extension page](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint). + +Those settings in _.vscode/settings.json_ should be fine: + +```json + "[scss]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "stylelint.vscode-stylelint", + "editor.codeActionsOnSave": { + "source.fixAll.stylelint": "explicit" + } + }, + "stylelint.reportInvalidScopeDisables": true, + "stylelint.reportNeedlessDisables": true, + "stylelint.snippet": ["css", "scss"], + "stylelint.validate": ["css", "scss"] +``` + +Please note **the VSCode extension does not take overrides into account**. + +### JetStorm + +You might need to rename _stylelint.config.js_ to _stylelint.config.cjs_ (_CommonJS_) and [adapt the code in consequence](https://stylelint.io/user-guide/configure). diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json new file mode 100644 index 0000000000..f94905454f --- /dev/null +++ b/packages/stylelint-config/package.json @@ -0,0 +1,32 @@ +{ + "name": "@lucca/stylelint-config", + "version": "0.0.0", + "description": "Lucca Front stylelint configuration", + "repository": { + "type": "git", + "url": "git+https://github.com/LuccaSA/lucca-front.git" + }, + "main": "stylelint.config.cjs", + "files": [ + "index.js" + ], + "keywords": [ + "stylelint", + "stylelint-config", + "lucca", + "scss", + "css" + ], + "public": true, + "author": "The product design team ", + "license": "MIT", + "bugs": { + "url": "https://github.com/LuccaSA/lucca-front/issues" + }, + "homepage": "https://github.com/LuccaSA/lucca-front#readme", + "peerDependencies": { + "stylelint": "^15.11.0", + "stylelint-config-prettier-scss": "^1.0.0", + "stylelint-config-standard-scss": "^11.1.0" + } +} diff --git a/packages/stylelint-config/stylelint.config.mjs b/packages/stylelint-config/stylelint.config.mjs new file mode 100644 index 0000000000..75ae1cc664 --- /dev/null +++ b/packages/stylelint-config/stylelint.config.mjs @@ -0,0 +1,82 @@ +'use strict'; + +/** @type {import('stylelint').Config} */ +export default { + extends: ['stylelint-config-standard-scss', 'stylelint-config-prettier-scss'], + + rules: { + // SCSS specific + // ============================================================================================ + 'scss/at-mixin-pattern': [ + '^([a-z][a-zA-Z0-9]*)((-(([a-z0-9]+[a-zA-Z0-9]*)|([A-Z]+))+)*)$', + { + message: (mixinName) => `Expected "${mixinName}" to match pattern --foo(-bar(Baz)*)*`, + }, + ], + 'scss/comment-no-empty': null, + + // Generic rules + // ============================================================================================ + 'alpha-value-notation': [ + 'number', + { + severity: 'warning', + }, + ], + 'at-rule-empty-line-before': [ + 'always', + { + except: ['blockless-after-blockless', 'first-nested'], + ignore: ['after-comment'], + }, + ], + 'color-hex-length': null, + 'custom-property-empty-line-before': [ + 'always', + { + severity: 'warning', + except: ['after-comment', 'after-custom-property', 'first-nested'], + }, + ], + 'custom-property-no-missing-var-function': true, + 'custom-property-pattern': [ + '^([a-z][a-zA-Z0-9]*)((-(([a-z0-9]+[a-zA-Z0-9]*)|([A-Z]+))+)*)$', + { + message: (customProperty) => `Expected "${customProperty}" to match pattern --foo(-bar(Baz)*)*`, + }, + ], + 'declaration-block-no-redundant-longhand-properties': null, + 'declaration-empty-line-before': [ + 'always', + { + severity: 'warning', + except: ['after-comment', 'after-declaration', 'first-nested'], + }, + ], + 'number-max-precision': 3, + 'property-no-unknown': [ + true, + { + ignoreProperties: ['scrollbar-3dlight-color'], + }, + ], + 'selector-class-pattern': [ + '^([a-z][a-zA-Z0-9]*)((-(([a-z0-9]+[a-zA-Z0-9]*)|([A-Z]+))+)*)$', + { + message: (selectorClass) => `Expected "${selectorClass}" to match pattern --foo(-bar(Baz)*)*`, + }, + ], + 'selector-pseudo-element-no-unknown': [ + true, + { + ignorePseudoElements: ['ng-deep'], + }, + ], + 'value-keyword-case': [ + 'lower', + { + severity: 'warning', + }, + ], + }, +};