Skip to content

Update stylelint v16#7

Open
tsharms wants to merge 9 commits into
mainfrom
update-stylelint-v16
Open

Update stylelint v16#7
tsharms wants to merge 9 commits into
mainfrom
update-stylelint-v16

Conversation

@tsharms
Copy link
Copy Markdown

@tsharms tsharms commented Dec 10, 2025

Ik heb @stylistic/stylelint-plugin toegevoegd zodat we de rules die stylelint sinsds versie 16 verwijderd heeft nog kunnen gebruiken. Dit is een tussen oplossing want eigenlijk zegt Stylelint dat we deze rules moeten afvangen met Prettier.

When we created these rules, pretty printers (like Prettier) didn't exist. They now offer a better way to consistently format code, especially whitespace. Linters and pretty printers are complementary tools that work together to help you write consistent and error-free code.

Summary by CodeRabbit

  • Chores
    • Upgraded Stylelint, PostCSS, and related dependencies to the latest versions.
    • Integrated a new stylistic linting plugin for enhanced CSS formatting rule coverage.
    • Refactored CSS linting configuration to align with updated tooling and rule namespacing.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 10, 2025

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 86123971-2a1e-4ce5-9d70-bca8d5b41f34

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)

Walkthrough

This PR upgrades stylelint from version 13 to version 16 and migrates style-related rules from standard stylelint to the @stylistic/stylelint-plugin namespace. Configuration is updated with new rule names, dependencies are bumped, and the PostCSS pipeline in the Kaliber plugin is consolidated into a single processing pass. Test fixtures and assertions are adapted for the new output format.

Changes

Cohort / File(s) Summary
Stylelint Configuration & Plugin Updates
\.stylelintrc, stylelint-plugins/kaliber.js
.stylelintrc: Replaces standard stylelint rules with @stylistic/* equivalents (e.g., block-opening-brace-space-before@stylistic/block-opening-brace-space-before); updates plugin list to include @stylistic/stylelint-plugin and retains Kaliber plugin.
kaliber.js: Consolidates individual PostCSS resolver usage into a single PostCSS processor pipeline; replaces per-plugin invocations with unified postcss(plugins).process() call.
Test & Fixture Updates
integration-test/test.js, stylelint-plugins/machinery/test.js
integration-test/test.js: Updates rule names to @stylistic/* format; switches output capture from stdout to stderr for Stylelint 16; adds filtering for summary lines; handles both warning and error indicators.
machinery/test.js: Strips appended rule-name suffix (formatted as (kaliber/<rule>)) from warning text during assertion.
Dependency Updates
package.json
Adds @stylistic/stylelint-plugin (^3.1.2); upgrades stylelint (^13.7.1 → ^16.11.0), PostCSS ecosystem packages (postcss, postcss-calc, postcss-modules-values, postcss-preset-env, postcss-selector-parser, postcss-values-parser), and stylelint-use-nesting (^3.0.0 → ^6.0.0).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–25 minutes

  • PostCSS pipeline refactoring in kaliber.js: Verify that the consolidated processor correctly handles all plugin configurations and produces identical output to the previous per-plugin approach.
  • Rule migration completeness: Ensure all stylelint rule names have been correctly migrated to @stylistic/* equivalents across configuration and test files.
  • Stylelint 16 output handling: Confirm that the stderr capture, summary-line filtering, and warning/error indicator logic correctly parse the new output format across diverse lint scenarios.
  • Test assertion changes: Verify that stripping rule-name suffixes in machinery/test.js preserves test integrity and doesn't mask actual issues.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Update stylelint v16' accurately reflects the main objective of the pull request, which is to update the project to use Stylelint version 16 and add the @stylistic/stylelint-plugin to handle removed rules.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch update-stylelint-v16

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@socket-security
Copy link
Copy Markdown

socket-security Bot commented Dec 10, 2025

@tsharms tsharms requested a review from AlbertSmit January 7, 2026 08:26
@tsharms tsharms requested a review from yoreljenkins January 14, 2026 12:55
@tsharms tsharms requested a review from guid-ooo April 16, 2026 07:30
} else {
assert.deepEqual(warnings.map(x => x.text), test.warnings || [], 'warnings')
// Stylelint 16 appends rule name to warnings, e.g. "(kaliber/rule-name)" - strip it for comparison
const warningTexts = warnings.map(x => x.text.replace(/\s*\(kaliber\/[^)]+\)$/, ''))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

geld dit dan alleen voor kaliber? of ook voor anderen?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@coderabbitai does this only apply to kaliber?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@AlbertSmit, the Stylelint behavior of appending rule names to warning text is not specific to kaliber — Stylelint automatically appends the rule name in parentheses at the end of the message for any rule, improving traceability of reported problems.

However, the regex here is kaliber-scoped intentionally, because this test harness (stylelint-plugins/machinery/test.js) is only ever used to test kaliber/* rules. Looking at the runTest function, the stylelint config it builds is always:

config: {
  plugins: [require.resolve('../kaliber')],
  rules: {
    [`kaliber/${ruleName}`]: [true]
  }
}

Since only kaliber/ rules are ever linted through this harness, the narrower /\s*\(kaliber\/[^)]+\)$/ regex is sufficient. If this test utility were ever extended to cover non-kaliber rules (e.g., @stylistic/*), the regex would need to be broadened to something like /\s*\([^)]+\)$/ to handle any rule namespace.

Comment thread integration-test/test.js
const results = resultString.split('\n')
.filter(x => x.toLowerCase().includes('⚠'))
.filter(x => x.includes('⚠') || x.includes('✖'))
// Exclude summary lines like "⚠ 110 problems (0 errors, 110 warnings)"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

kun je dit niet meegeven aan de stylelint cli call?

Comment thread integration-test/test.js
const results = resultString.split('\n')
.filter(x => x.toLowerCase().includes('⚠'))
.filter(x => x.includes('⚠') || x.includes('✖'))
// Exclude summary lines like "⚠ 110 problems (0 errors, 110 warnings)"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@coderabbitai can we not catch this in line 140 when we spawn 140? this seems a smell.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@AlbertSmit, agreed — hardcoding result.stderr is brittle and tied to a specific Stylelint version's behaviour. Since spawnSync doesn't have a built-in option to merge streams, the cleanest fix at the spawnSync call site is to simply concatenate both outputs, making it resilient to whichever stream future versions write to:

const result = spawnSync(`node ./node_modules/.bin/stylelint --no-color ${files.join(' ')}`, { env, shell: true })
const resultString = result.stdout.toString() + result.stderr.toString()

Alternatively, since shell: true is already set, a shell redirect would also work:

const result = spawnSync(
  `node ./node_modules/.bin/stylelint --no-color ${files.join(' ')} 2>&1`,
  { env, shell: true }
)
const resultString = result.stdout.toString()

The first option (combining both buffers) is generally preferable — it's portable, doesn't rely on shell-specific syntax, and future-proofs against Stylelint switching streams again.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@coderabbitai i mean specifically // Exclude summary lines like "⚠ 110 problems (0 errors, 110 warnings)" and .filter(x => !/^\s*[⚠✖]\s+\d+\s+problem/.test(x)) and .filter(x => x.includes('⚠') || x.includes('✖')).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@AlbertSmit, yes — the real fix is upstream at the spawnSync call. All three of those filters exist because the code is parsing Stylelint's human-readable text output, which is fragile by nature. Stylelint ships a built-in json formatter that gives you structured data instead:

function styleLint(files) {
  const { FORCE_COLOR, ...env } = process.env
  const result = spawnSync(
    `node ./node_modules/.bin/stylelint --formatter json ${files.join(' ')}`,
    { env, shell: true }
  )
  // Stylelint exits non-zero when there are warnings/errors, so output goes to stdout
  const output = JSON.parse(result.stdout.toString() || '[]')
  
  const reportedProblems = new Set(
    output.flatMap(file => file.warnings.map(w => w.rule))
  )
  
  return reportedProblems
}

This removes the need for:

  • --no-color (irrelevant for JSON)
  • The / symbol filter
  • The summary-line exclusion regex
  • The segment-splitting .map() to extract the rule name

The warnings[].rule field in the JSON output is exactly what's being extracted by the current text-parsing dance, but without any of the fragility. It also handles errors and warnings uniformly since both appear in the warnings array (distinguished by severity).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Misschien is dit dan nog een idee @tsharms, filteren op leestekens voelt een beetje sketchy, ook al zat het er al in?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants