diff --git a/.stylelintrc.json b/.stylelintrc.json new file mode 100644 index 0000000..352fbe6 --- /dev/null +++ b/.stylelintrc.json @@ -0,0 +1,38 @@ +{ + "extends": "stylelint-config-standard-scss", + "rules": { + "declaration-colon-newline-after": null, + "selector-list-comma-newline-after": null, + + "at-rule-empty-line-before": null, + "declaration-colon-space-before": null, + "declaration-empty-line-before": null, + "custom-property-empty-line-before": null, + "comment-empty-line-before": null, + "scss/double-slash-comment-empty-line-before": null, + "scss/dollar-variable-colon-space-after": null, + + "custom-property-pattern": null, + "declaration-block-no-duplicate-properties": null, + "declaration-block-no-redundant-longhand-properties": null, + "declaration-block-no-shorthand-property-overrides": null, + "declaration-block-single-line-max-declarations": null, + "font-family-no-duplicate-names": null, + "function-url-quotes": null, + "indentation": null, + "keyframes-name-pattern": null, + "max-line-length": null, + "no-descending-specificity": null, + "no-duplicate-selectors": null, + "scss/at-extend-no-missing-placeholder": null, + "scss/at-import-partial-extension": null, + "scss/at-mixin-pattern": null, + "scss/comment-no-empty": null, + "scss/dollar-variable-pattern": null, + "scss/double-slash-comment-whitespace-inside": null, + "scss/no-global-function-names": null, + "scss/operator-no-unspaced": null, + "selector-class-pattern": null, + "selector-id-pattern": null + } +} diff --git a/README.md b/README.md index dede86d..a0524bb 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,29 @@ Violations of some rules can be fixed automatically by: Rules configuration can be found in the `.eslintrc.json` file. +## Running stylelint + +Cockpit uses [Stylelint](https://stylelint.io/) to automatically check CSS code +style in `.css` and `scss` files. + +The linter is executed within every build as a webpack preloader. + +For developer convenience, the Stylelint can be started explicitly by: + + $ npm run stylelint + +Violations of some rules can be fixed automatically by: + + $ npm run stylelint:fix + +Rules configuration can be found in the `.stylelintrc.json` file. + +During fast iterative development, you can also choose to not run stylelint. +This speeds up the build and avoids build failures due to e. g. ill-formatted +css or other issues: + + $ make STYLELINT=0 + # Running tests locally Run `make check` to build an RPM, install it into a standard Cockpit test VM diff --git a/package.json b/package.json index f0e2456..a40263a 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,9 @@ "watch": "webpack --watch --progress", "build": "webpack", "eslint": "eslint --ext .js --ext .jsx src/", - "eslint:fix": "eslint --fix --ext .js --ext .jsx src/" + "eslint:fix": "eslint --fix --ext .js --ext .jsx src/", + "stylelint": "stylelint src/*{.css,scss}", + "stylelint:fix": "stylelint --fix src/*{.css,scss}" }, "devDependencies": { "@babel/core": "^7.5.4", @@ -43,6 +45,7 @@ "sass-loader": "^12.1.0", "sizzle": "^2.3.3", "string-replace-loader": "^3.0.0", + "stylelint": "^14.9.1", "terser-webpack-plugin": "^5.1.4", "webpack": "^5.54.0", "webpack-cli": "^4.9.1" @@ -51,6 +54,8 @@ "@patternfly/patternfly": "4.203.4", "@patternfly/react-core": "4.225.4", "react": "17.0.2", - "react-dom": "17.0.2" + "react-dom": "17.0.2", + "stylelint-config-standard-scss": "^5.0.0", + "stylelint-webpack-plugin": "^3.3.0" } } diff --git a/webpack.config.js b/webpack.config.js index c1210ff..6ddfde2 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -9,6 +9,7 @@ const CompressionPlugin = require("compression-webpack-plugin"); const ESLintPlugin = require('eslint-webpack-plugin'); const CockpitPoPlugin = require("./pkg/lib/cockpit-po-plugin"); const CockpitRsyncPlugin = require("./pkg/lib/cockpit-rsync-plugin"); +const StylelintPlugin = require('stylelint-webpack-plugin'); /* A standard nodejs and webpack pattern */ const production = process.env.NODE_ENV === 'production'; @@ -16,6 +17,9 @@ const production = process.env.NODE_ENV === 'production'; /* development options for faster iteration */ const eslint = process.env.ESLINT !== '0'; +/* Default to disable csslint for faster production builds */ +const stylelint = process.env.STYLELINT ? (process.env.STYLELINT !== '0') : !production; + // Obtain package name from package.json const packageJson = JSON.parse(fs.readFileSync('package.json')); @@ -36,6 +40,12 @@ if (eslint) { plugins.push(new ESLintPlugin({ extensions: ["js", "jsx"], failOnWarning: true, })); } +if (stylelint) { + plugins.push(new StylelintPlugin({ + context: "src/", + })); +} + /* Only minimize when in production mode */ if (production) { plugins.unshift(new CompressionPlugin({