Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
b3db81a
First pass at adding a stylelint script.
afercia Aug 6, 2026
45d5e4a
Remove custom rule from gutenberg.
afercia Aug 6, 2026
a2cac53
Clean up stylelintignore.
afercia Aug 6, 2026
c5ab528
Clean up config.
afercia Aug 6, 2026
f632781
Add Grunt task and clean up.
afercia Aug 7, 2026
193e2d8
Remove stylelint-config-wordpress package.
afercia Aug 7, 2026
7d8fd9c
Ignore admin color scheme auto generated files.
afercia Aug 8, 2026
6b4b29c
Ignore files copied to wp-includes js.
afercia Aug 8, 2026
e10c54b
Remove Stylelint configuration from Twenty Twenty theme.
afercia Aug 9, 2026
1c668cd
Remove Stylelint configuration from Twenty Twenty-One theme.
afercia Aug 9, 2026
9312594
Remove comments.
afercia Aug 9, 2026
90c2a53
Add lint:css:themes script for bundled themes.
afercia Aug 9, 2026
6c662f6
Build theme files.
afercia Aug 9, 2026
77b0a6e
Use the root stylelintrc for twentytwentyone.
afercia Aug 9, 2026
a58cbf7
For twentytwentyone try adding a postcss script and run it twice.
afercia Aug 10, 2026
ff55009
Start refining rules.
afercia Aug 10, 2026
1f63acc
Add rules for empty lines before.
afercia Aug 10, 2026
2c68784
Solve the indentation and leading space issues avoiding to run postcs…
afercia Aug 10, 2026
22cd9cf
Improve comment-empty-line-before.
afercia Aug 10, 2026
2e1a7d3
Improve comment.
afercia Aug 10, 2026
18a880e
Improve selector-list-comma-space-after.
afercia Aug 10, 2026
66b3e41
Refine empty libe before rule.
afercia Aug 11, 2026
810107e
Add selector-no-qualifying-type warning.
afercia Aug 11, 2026
6bcd949
Refine more rules.
afercia Aug 11, 2026
b1c32e1
Improve order of rules related to indentation.
afercia Aug 11, 2026
8b0e232
Reduce max-empty-lines to 1.
afercia Aug 11, 2026
caf5e54
Disable comment-empty-line-before.
afercia Aug 11, 2026
75f955c
Run stylelint directly so that it walks upwards until it finds the ro…
afercia Aug 11, 2026
3759209
Update test-and-zip-default-themes gh action.
afercia Aug 11, 2026
1eb9ea6
Add bacl @wordpress/scripts to twentytwentyone.
afercia Aug 11, 2026
0fa278a
Add stylelint-plugin-logical-css to twentytwentyone.
afercia Aug 11, 2026
584c7bd
Update twentytwentyone styles.
afercia Aug 11, 2026
c1a2754
Pass the glob as a quoted pattern.
afercia Aug 11, 2026
56e075f
Add optimizeLegibility to value-keyword-case exceptions.
afercia Aug 12, 2026
6ac981c
Add @stylistic/selector-descendant-combinator-no-non-space true.
afercia Aug 12, 2026
04e6451
Adjust a few rules.
afercia Aug 17, 2026
8450d5a
Ignore dashicons font-family.
afercia Aug 17, 2026
8ead133
Apply a few minor JS coding standards to stylelintrc.js.
afercia Aug 17, 2026
2f47585
Try warnings threshold mechanism.
afercia Aug 19, 2026
6dbccd8
Normalize the glob path for Windows on CI.
afercia Aug 19, 2026
755b7c0
Increase warnings threshold.
afercia Sep 5, 2026
53d6651
Remove all changes related to themes.
afercia Sep 11, 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
114 changes: 114 additions & 0 deletions .stylelintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/** @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 class segments separated with hyphens, double hyphens, or double underscores',
},
],
'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,
{
severity: 'warning',
},
],
'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,
ignorePath: '.stylelintignore',
};


15 changes: 14 additions & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -1775,8 +1775,21 @@ module.exports = function(grunt) {
'qunit:compiled'
] );

grunt.registerTask( 'lint:css', 'Runs Stylelint on core CSS and checks warning-level rule thresholds.', 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', [
Expand Down
12 changes: 12 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@
"sinon": "16.1.3",
"sinon-test": "~3.1.6",
"source-map-loader": "5.0.0",
"stylelint": "16.26.1",
"stylelint-plugin-logical-css": "2.1.0",
"typescript": "6.0.3",
"update-browserslist-db": "1.3.1",
"uuid": "14.0.1",
Expand Down Expand Up @@ -126,6 +128,10 @@
"grunt": "grunt",
"lint:jsdoc": "wp-scripts lint-js",
"lint:jsdoc:fix": "wp-scripts lint-js --fix",
"lint:css": "node ./tools/stylelint/lint-css.js",
"lint:css:fix": "wp-scripts lint-style \"src/**/*.{css,scss}\" --fix",
"lint:css:thresholds": "node ./tools/stylelint/check-warning-thresholds.js",
"lint:css:thresholds:update": "node ./tools/stylelint/check-warning-thresholds.js --update",
"typecheck:js": "tsc --build",
"env:start": "node ./tools/local-env/scripts/start.js && node ./tools/local-env/scripts/docker.js run -T --rm php composer update -W",
"env:stop": "node ./tools/local-env/scripts/docker.js down",
Expand Down
35 changes: 35 additions & 0 deletions tools/stylelint/check-warning-thresholds.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* CLI entry point for checking or updating Stylelint warning-level rule thresholds.
* See tools/stylelint/lib/warning-thresholds.js for the underlying logic.
*/

const {
lintCss,
getWarningLevelRules,
countWarnings,
checkThresholds,
updateThresholds,
} = require( './lib/warning-thresholds' );

const shouldUpdate = process.argv.includes( '--update' );

async function main() {
console.log( 'Checking Stylelint warnings thresholds...' );

const warningLevelRules = getWarningLevelRules();
const { results } = await lintCss();
const actualCounts = countWarnings( results, warningLevelRules );

const success = shouldUpdate
? updateThresholds( actualCounts )
: checkThresholds( actualCounts, warningLevelRules );

if ( ! success ) {
process.exitCode = 1;
}
}

main().catch( ( error ) => {
console.error( error );
process.exitCode = 1;
} );
Loading
Loading