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
f75fdfe
d3b5f72
3c92e31
0373528
7021245
e950a5b
9dee5b3
61d1313
5b38b15
ba8c7ec
8264a7d
bbfefbd
0ff2efe
3ee935a
1cab9fb
4a4598d
96ceaa0
51250c3
cd671ed
2c912e6
edfc735
7dbc41e
6b11ce5
276faed
a5a0238
fbbaf14
4f74f53
3914149
6585fdf
902f287
5096419
45e54e3
ad0fe03
6beb1cd
e96609a
7d07a9f
c75a315
51923e4
13ce60d
08f8657
c19ca2f
2174d46
b283dcc
07e5fd8
d4c7b23
fb0d728
e87de52
e312de0
efd3c93
9742529
2deae6d
17d3864
31ebec9
fa968e2
6ffd6f7
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( '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', [ | ||
| 'postcss:core' | ||
| 'postcss:core', | ||
| 'lint:css', | ||
| ] ); | ||
|
|
||
| grunt.registerTask( 'precommit:php', [ | ||
|
|
@@ -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
Member
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 👍