Repository navigation
Add stylelint CSS linting #12934
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Add stylelint CSS linting #12934
Changes from all commits
d709e08
924456f
77641ab
0ea2128
e4973f6
b1504c0
de7af7d
232e4eb
589d421
d195193
ed042db
39861e2
6cebfbb
af0a7b3
8dc7c43
c1631fe
07958fa
06e4061
89e8bcb
ec155f9
97b4cdb
0f193e3
9e09e74
a030f5b
ebad69a
a37ca03
260ec95
19d3192
0cd7fe6
40577cf
e7ecedb
cef2e43
5dd99f2
f62f559
2ccaf03
5ab7cc1
85b68cf
f2e5972
042f3a9
f60b5e7
5700328
1099050
86d062c
f037a79
5f02002
ba34681
4d56106
daba169
9787390
8315e1a
109539c
3cf1c64
41a2a3d
ce1ed3b
1f83aba
0d465c0
ca4c161
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # Ignore WordPress plugin files. | ||
| src/wp-content/plugins/**/* | ||
|
|
||
| # Ignore WordPress theme files. | ||
| src/wp-content/themes/**/* | ||
|
|
||
| # Ignore WordPress block files. | ||
| src/wp-includes/blocks/**/* | ||
|
|
||
| # Ignore admin color schemes auto generated files. | ||
| src/wp-admin/css/colors/*/*.css | ||
|
|
||
| # Ignore WordPress included dist files. | ||
| src/wp-includes/css/dist/**/* | ||
|
|
||
| # Ignore files copied to wp-includes js. | ||
| src/wp-includes/js/**/* | ||
|
|
||
| # Ignore WordPress JS vendor files. | ||
| src/js/_enqueues/vendor/**/* | ||
|
|
||
| # Ignore minified CSS files. | ||
| **/*.min.css | ||
|
|
||
| # Ignore RTL CSS files. | ||
| **/*-rtl.css | ||
| **/*-rtl.min.css |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| /** @type {import('stylelint').Config} */ | ||
| module.exports = { | ||
| extends: '@wordpress/stylelint-config/scss-stylistic', | ||
| plugins: [ | ||
| 'stylelint-plugin-logical-css', | ||
| '@wordpress/theme/stylelint-plugins/no-token-fallback-values', | ||
| ], | ||
| reportNeedlessDisables: true, | ||
| rules: { | ||
| 'at-rule-empty-line-before': [ | ||
| 'always', | ||
| { | ||
| except: [ 'blockless-after-blockless' ], | ||
| ignore: [ 'first-nested', 'after-comment' ], | ||
| }, | ||
| ], | ||
| 'at-rule-no-unknown': null, | ||
| 'comment-empty-line-before': null, | ||
| 'declaration-property-unit-allowed-list': [ | ||
| { | ||
| 'line-height': [], | ||
| }, | ||
| ], | ||
| 'declaration-property-value-allowed-list': [ | ||
| { | ||
| 'flex-direction': '/^(?!(row|column)-reverse).*$/', | ||
| }, | ||
| { | ||
| message: ( property, value ) => | ||
| `Avoid "${ value }" value for the "${ property }" property. For accessibility reasons, visual, reading, and DOM order must match. Only use the reverse values when they do not affect reading order, meaning, and interaction.`, | ||
| }, | ||
| ], | ||
| 'font-family-no-missing-generic-family-keyword': [ | ||
| true, | ||
| { | ||
| ignoreFontFamilies: [ 'dashicons' ], | ||
| }, | ||
| ], | ||
| 'font-weight-notation': 'numeric', | ||
| 'function-disallowed-list': [ 'rgb' ], | ||
| 'no-descending-specificity': null, | ||
| 'no-invalid-position-at-import-rule': null, | ||
| 'property-disallowed-list': [ | ||
| [ 'order' ], | ||
| { | ||
| message: | ||
| 'Avoid the order property. For accessibility reasons, visual, reading, and DOM order must match. Only use the order property when it does not affect reading order, meaning, and interaction.', | ||
| }, | ||
| ], | ||
| 'rule-empty-line-before': [ | ||
| 'always', | ||
| { | ||
| except: [ 'first-nested' ], | ||
| ignore: [ 'after-comment' ], | ||
| }, | ||
| ], | ||
| 'selector-class-pattern': [ | ||
| '^([a-z][a-z0-9]*)(-[a-z0-9]+)*$', | ||
| { | ||
| message: | ||
| 'Class selector should use lowercase and separate words with hyphens', | ||
| }, | ||
| ], | ||
| 'selector-id-pattern': [ | ||
| '^([a-z][a-z0-9]*)(-[a-z0-9]+)*$', | ||
| { | ||
| message: | ||
| 'ID selector should use lowercase and separate words with hyphens', | ||
| }, | ||
| ], | ||
| 'selector-no-qualifying-type': true, | ||
| 'value-keyword-case': [ | ||
| 'lower', | ||
| { | ||
| ignoreKeywords: [ | ||
| 'currentColor', | ||
| 'optimizeLegibility', | ||
| ], | ||
| }, | ||
| ], | ||
| 'scss/at-else-empty-line-before': null, | ||
| 'scss/at-extend-no-missing-placeholder': null, | ||
| 'scss/at-if-closing-brace-newline-after': null, | ||
| 'scss/at-if-closing-brace-space-after': null, | ||
| 'scss/comment-no-empty': null, | ||
| 'scss/load-partial-extension': null, | ||
| 'scss/no-global-function-names': null, | ||
| 'scss/operator-no-newline-after': null, | ||
| 'scss/operator-no-unspaced': null, | ||
| 'scss/selector-no-redundant-nesting-selector': null, | ||
| '@stylistic/max-empty-lines': 1, | ||
| '@stylistic/max-line-length': null, | ||
| '@stylistic/selector-descendant-combinator-no-non-space': true, | ||
| // Keep these lines. Don't change their order otherwise indentation will break. | ||
| // It's not about a literal 'execution order', but rather a compatibility issue. | ||
| '@stylistic/block-closing-brace-newline-before': 'always', | ||
| '@stylistic/block-opening-brace-newline-after': 'always', | ||
| '@stylistic/declaration-block-semicolon-newline-after': 'always', | ||
| '@stylistic/selector-list-comma-space-after': 'always-single-line', | ||
| '@stylistic/selector-list-comma-newline-after': 'always', | ||
| '@stylistic/declaration-colon-newline-after': 'always-multi-line', | ||
| '@stylistic/indentation': 'tab', | ||
| // End keep these lines. | ||
| }, | ||
| reportDescriptionlessDisables: true, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1823,8 +1823,21 @@ module.exports = function(grunt) { | |
| 'qunit:compiled' | ||
| ] ); | ||
|
|
||
| grunt.registerTask( 'precommit:css', 'Processes core CSS files with PostCSS in preparation for a commit.', [ | ||
| 'postcss:core' | ||
| grunt.registerTask( 'lint:css', 'Runs Stylelint on core CSS.', function() { | ||
| var done = this.async(); | ||
|
|
||
| grunt.util.spawn( { | ||
| cmd: 'node', | ||
| args: [ 'tools/stylelint/lint-css.js' ], | ||
| opts: { stdio: 'inherit' } | ||
| }, function( error ) { | ||
| done( ! error ); | ||
| } ); | ||
| } ); | ||
|
|
||
| grunt.registerTask( 'precommit:css', 'Processes core CSS files with PostCSS and Stylelint in preparation for a commit.', [ | ||
| 'postcss:core', | ||
| 'lint:css', | ||
| ] ); | ||
|
|
||
| grunt.registerTask( 'precommit:php', 'Runs PHPStan and PHPUnit tests in preparation for a commit.', [ | ||
|
|
@@ -1921,7 +1934,7 @@ module.exports = function(grunt) { | |
| } | ||
|
|
||
| if ( code === 0 ) { | ||
| if ( [ 'package.json', 'Gruntfile.js', 'composer.json' ].some( testPath ) ) { | ||
| if ( [ 'package.json', 'Gruntfile.js', 'composer.json', '.stylelintrc.js', '.stylelintignore' ].some( testPath ) ) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changing the Stylelint config triggers the full
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added by @lancewillett in 71bcf1a yes, worth considering adding |
||
| grunt.log.writeln( 'Configuration files modified. Running `prerelease`.' ); | ||
| taskList.push( 'prerelease' ); | ||
| } else { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The stylistic configs used in Gutenberg's config were used for backwards compatibility. Stylelint v16 removed all stylistic rules (rules to do with formatting instead of linting errors), but before that point, they were included in the base recommended stylelint config.
Stylelint's stylistic rules directly conflict with Prettier which also applies formatting to CSS files. If we're adding Stylelint rules where ones were not present before, I would recommend using the base config for your extends (
@wordpress/stylelint-config/scss) which doesn't contain any stylistic rules, and keep Prettier as the source of truth for formatting.Alternatively, you could make Stylelint the source of truth for formatting CSS files and disable Prettier for CSS.
I believe there are some small rules which Stylelint implements which Prettier will not (lines between selectors being the one I can think of off the top of my head) so imo the best approach would be to use the scss config and then specifically add any rules you need from the stylistic config explicitly.
I am looking to create an issue/PR to do the same in the Gutenberg config as and when I have time for the same reasons, I just haven't gotten around to it yet.
You can consider this a suggestion, if you want to move forward with your PR anyway, don't consider me a blocker 👍