Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
d709e08
First pass at adding a stylelint script.
afercia Aug 6, 2026
924456f
Remove custom rule from gutenberg.
afercia Aug 6, 2026
77641ab
Clean up stylelintignore.
afercia Aug 6, 2026
0ea2128
Clean up config.
afercia Aug 6, 2026
e4973f6
Add Grunt task and clean up.
afercia Aug 7, 2026
b1504c0
Remove stylelint-config-wordpress package.
afercia Aug 7, 2026
de7af7d
Ignore admin color scheme auto generated files.
afercia Aug 8, 2026
232e4eb
Ignore files copied to wp-includes js.
afercia Aug 8, 2026
589d421
Remove Stylelint configuration from Twenty Twenty theme.
afercia Aug 9, 2026
d195193
Remove Stylelint configuration from Twenty Twenty-One theme.
afercia Aug 9, 2026
ed042db
Remove comments.
afercia Aug 9, 2026
39861e2
Add lint:css:themes script for bundled themes.
afercia Aug 9, 2026
6cebfbb
Build theme files.
afercia Aug 9, 2026
af0a7b3
Use the root stylelintrc for twentytwentyone.
afercia Aug 9, 2026
8dc7c43
For twentytwentyone try adding a postcss script and run it twice.
afercia Aug 10, 2026
c1631fe
Start refining rules.
afercia Aug 10, 2026
07958fa
Add rules for empty lines before.
afercia Aug 10, 2026
06e4061
Solve the indentation and leading space issues avoiding to run postcs…
afercia Aug 10, 2026
89e8bcb
Improve comment-empty-line-before.
afercia Aug 10, 2026
ec155f9
Improve comment.
afercia Aug 10, 2026
97b4cdb
Improve selector-list-comma-space-after.
afercia Aug 10, 2026
0f193e3
Refine empty libe before rule.
afercia Aug 11, 2026
9e09e74
Add selector-no-qualifying-type warning.
afercia Aug 11, 2026
a030f5b
Refine more rules.
afercia Aug 11, 2026
ebad69a
Improve order of rules related to indentation.
afercia Aug 11, 2026
a37ca03
Reduce max-empty-lines to 1.
afercia Aug 11, 2026
260ec95
Disable comment-empty-line-before.
afercia Aug 11, 2026
19d3192
Run stylelint directly so that it walks upwards until it finds the ro…
afercia Aug 11, 2026
0cd7fe6
Update test-and-zip-default-themes gh action.
afercia Aug 11, 2026
40577cf
Add bacl @wordpress/scripts to twentytwentyone.
afercia Aug 11, 2026
e7ecedb
Add stylelint-plugin-logical-css to twentytwentyone.
afercia Aug 11, 2026
cef2e43
Update twentytwentyone styles.
afercia Aug 11, 2026
5dd99f2
Pass the glob as a quoted pattern.
afercia Aug 11, 2026
f62f559
Add optimizeLegibility to value-keyword-case exceptions.
afercia Aug 12, 2026
2ccaf03
Add @stylistic/selector-descendant-combinator-no-non-space true.
afercia Aug 12, 2026
5ab7cc1
Adjust a few rules.
afercia Aug 17, 2026
85b68cf
Ignore dashicons font-family.
afercia Aug 17, 2026
f2e5972
Apply a few minor JS coding standards to stylelintrc.js.
afercia Aug 17, 2026
042f3a9
Try warnings threshold mechanism.
afercia Aug 19, 2026
f60b5e7
Normalize the glob path for Windows on CI.
afercia Aug 19, 2026
5700328
Increase warnings threshold.
afercia Sep 5, 2026
1099050
Remove all changes related to themes.
afercia Sep 11, 2026
86d062c
Align threshold with current trunk.
afercia Sep 23, 2026
f037a79
Build/Test Tools: Use Stylelint bulk suppressions as the CSS baseline.
lancewillett Sep 23, 2026
5f02002
Build/Test Tools: Treat the Stylelint config files as configuration i…
lancewillett Sep 23, 2026
ba34681
Make the class selector pattern match the current coding standards.
afercia Sep 28, 2026
4d56106
Revert changes to css files.
afercia Sep 28, 2026
daba169
Upgrade sylelint and stylelint-plugin-logical-css versions.
afercia Sep 28, 2026
9787390
Checkout latest css changes from trunk.
afercia Sep 29, 2026
8315e1a
Update Stylelint suppressions list.
afercia Sep 29, 2026
109539c
Rebase and update suppressions list.
afercia Oct 2, 2026
3cf1c64
Address part of CR.
afercia Oct 2, 2026
41a2a3d
Add lint:css:update-suppressions script.
afercia Oct 2, 2026
ce1ed3b
Improve error message and add instructions.
afercia Oct 5, 2026
1f83aba
Decrease suppressions count.
afercia Oct 8, 2026
0d465c0
Update suppressions count after recent changes to wp-tooltip.css.
afercia Oct 12, 2026
ca4c161
Decrease selector-no-qualifying-type suppressions count for buttons.c…
afercia Oct 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .stylelintignore
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
106 changes: 106 additions & 0 deletions .stylelintrc.js
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',

Copy link
Copy Markdown

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 👍

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,
};
19 changes: 16 additions & 3 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.', [
Expand Down Expand Up @@ -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 ) ) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the Stylelint config triggers the full prerelease here (PHP formatting, JS, CSS, images) when precommit:css would be enough. stylelint-suppressions.json isn't in the list either, so editing only the suppressions file runs no lint locally.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added by @lancewillett in 71bcf1a yes, worth considering adding stylelint-suppressions.json.

grunt.log.writeln( 'Configuration files modified. Running `prerelease`.' );
taskList.push( 'prerelease' );
} else {
Expand Down
Loading
Loading