Skip to content

Add relative-selector-nesting-notation rule#8730

Merged
jeddy3 merged 22 commits into
stylelint:mainfrom
sw1tch3roo:feature/selector-nesting-notation
Apr 14, 2026
Merged

Add relative-selector-nesting-notation rule#8730
jeddy3 merged 22 commits into
stylelint:mainfrom
sw1tch3roo:feature/selector-nesting-notation

Conversation

@sw1tch3roo
Copy link
Copy Markdown
Contributor

Which issue, if any, is this issue related to?

Closes #8161.

Is there anything in the PR that needs further explanation?

No, it's self-explanatory.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Aug 14, 2025

🦋 Changeset detected

Latest commit: 5b3d7ea

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
stylelint Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Aug 14, 2025

This PR is packaged and the instant preview is available (5b3d7ea). View the demo website.

Install it locally:

npm i -D https://pkg.pr.new/stylelint@5b3d7ea

Comment thread docs/user-guide/rules.md Outdated
Copy link
Copy Markdown
Member

@jeddy3 jeddy3 left a comment

Choose a reason for hiding this comment

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

@sw1tch3roo Thanks for starting on this!

When a rule autofixes, we should consider non-significant whitespace and comments as we're autofixing source files. See the commonly overlooked cases in the developer guide.

I've highlighted a few other edge cases in comments below.

Comment thread lib/rules/selector-nesting-notation/README.md Outdated
Comment thread lib/rules/selector-nesting-notation/README.md Outdated
Comment thread lib/rules/selector-nesting-notation/README.md Outdated
Comment thread lib/rules/selector-nesting-notation/index.mjs Outdated
Comment thread lib/rules/selector-nesting-notation/index.mjs Outdated
Comment thread lib/rules/selector-nesting-notation/index.mjs Outdated
Comment thread lib/rules/selector-nesting-notation/index.mjs Outdated
@jeddy3
Copy link
Copy Markdown
Member

jeddy3 commented Aug 16, 2025

Here's a version of the rule that uses the PostCSS Selector parser to account for some of the cases I've highlighted above, especially around preserving comments and whitespace. It simplifies a few things, but adds complexity back in to manage whitespace and comments in cases like:

a { > .foo, /* bar */ + .baz {} }

Managing whitespace and comments is typically a complex part of a rule. I used selector-not-notation as a blueprint, which also dedicates a chunk of code towards this.

There are likely more edge cases to uncover and opportunities to refactor, but this should give you a starting point and direction when using the PostCSS selector parser. Once it's dropped in, it'd be good to look for more edge cases and/or shoring up the test coverage, as it's a rough cut:

Rule
import parser from 'postcss-selector-parser';

import findNodeUpToRoot from '../../utils/findNodeUpToRoot.mjs';
import getRuleSelector from '../../utils/getRuleSelector.mjs';
import isStandardSyntaxRule from '../../utils/isStandardSyntaxRule.mjs';
import parseSelector from '../../utils/parseSelector.mjs';
import report from '../../utils/report.mjs';
import ruleMessages from '../../utils/ruleMessages.mjs';
import validateOptions from '../../utils/validateOptions.mjs';

const ruleName = 'selector-nesting-notation';

const messages = ruleMessages(ruleName, {
	expected: (primary) => `Expected ${primary} nesting selector notation`,
});

const meta = {
	url: 'https://stylelint.io/user-guide/rules/selector-nesting-notation',
	fixable: true,
};

/** @type {import('stylelint').CoreRules[ruleName]} */
const rule = (primary) => {
	return (root, result) => {
		const validOptions = validateOptions(result, ruleName, {
			actual: primary,
			possible: ['explicit', 'implicit'],
		});

		if (!validOptions) return;

		root.walkRules((ruleNode) => {
			if (!isStandardSyntaxRule(ruleNode)) return;

			if (!isNestedStyleRule(ruleNode)) return;

			const selectorRoot = parseSelector(getRuleSelector(ruleNode), result, ruleNode);

			if (!selectorRoot) return;

			selectorRoot.each((selector) => {
				if (selector.type !== 'selector') return;

				const hasNesting = isNestContaining(selector);
				const startsWithComb = startsWithCombinator(selector);
				const startsWithNesting = canUseImplicitNesting(selector);

				let fix;

				if (primary === 'explicit') {
					if (hasNesting && !startsWithComb) return;

					fix = () => fixExplicit(selector, ruleNode, selectorRoot);
				}

				if (primary === 'implicit') {
					if (startsWithComb || !startsWithNesting) return;

					fix = () => fixImplicit(selector, ruleNode, selectorRoot);
				}

				const index = selector.sourceIndex;
				const endIndex = index + selector.toString().trim().length;

				report({
					message: messages.expected,
					messageArgs: [primary],
					node: ruleNode,
					index,
					endIndex,
					ruleName,
					result,
					fix: {
						apply: fix,
						node: ruleNode,
					},
				});
			});
		});
	};
};

/**
 * Check if a rule is a nested style rule
 *
 * @param {import('postcss').Rule} ruleNode
 * @returns {boolean}
 */
function isNestedStyleRule(ruleNode) {
	return Boolean(findNodeUpToRoot(ruleNode, ({ type }) => type === 'rule'));
}

/**
 * Check if a selector contains the nesting selector
 *
 * @param {import('postcss-selector-parser').Selector} selector
 * @returns {boolean}
 */
function isNestContaining(selector) {
	let hasNestingSelector = false;

	selector.walkNesting(() => (hasNestingSelector = true));

	return hasNestingSelector;
}

/**
 * Check if a selector starts with a combinator
 *
 * @param {import('postcss-selector-parser').Selector} selector
 * @returns {boolean}
 */
function startsWithCombinator(selector) {
	const firstSignificantNode = selector.nodes.find((node) => node.type !== 'comment');

	return firstSignificantNode?.type === 'combinator';
}

/**
 * Check if a selector can use implicit nesting, i.e.
 * has a combinator after any comments or nesting selectors
 *
 * @param {import('postcss-selector-parser').Selector} selector
 * @returns {boolean}
 */
function canUseImplicitNesting(selector) {
	const foundNode = selector.nodes.find(
		(node) => node.type !== 'comment' && node.type !== 'nesting',
	);

	return foundNode?.type === 'combinator';
}

/**
 * Fix selector to use explicit nesting notation
 *
 * @param {import('postcss-selector-parser').Selector} selector
 * @param {import('postcss').Rule} ruleNode
 * @param {import('postcss-selector-parser').Root} selectorRoot
 */
function fixExplicit(selector, ruleNode, selectorRoot) {
	const firstSignificantNode = selector.nodes.find(
		(node) => !['comment', 'selector', 'root'].includes(node.type),
	);

	if (firstSignificantNode) {
		const { before } = firstSignificantNode.spaces;

		selector.insertBefore(
			firstSignificantNode,
			parser.nesting({
				spaces: {
					after: ' ',
					before,
				},
			}),
		);
		firstSignificantNode.spaces.before = '';
	}

	ruleNode.selector = selectorRoot.toString();
}

/**
 * Fix selector to use implicit nesting notation
 *
 * @param {import('postcss-selector-parser').Selector} selector
 * @param {import('postcss').Rule} ruleNode
 * @param {import('postcss-selector-parser').Root} selectorRoot
 */
function fixImplicit(selector, ruleNode, selectorRoot) {
	const firstNestingNode = selector.nodes.find((node) => node.type === 'nesting');
	let spaceBeforeFirstNestingNode = '';

	// Remove the first nesting node and store its spaces.before
	if (firstNestingNode) {
		spaceBeforeFirstNestingNode = firstNestingNode.spaces.before;
		firstNestingNode.remove();
	}

	const firstCombinatorNode = selector.nodes.find((node) => node.type === 'combinator');

	// Remove the first combinator node and update the next node's spaces
	if (firstCombinatorNode) {
		const nextNode = firstCombinatorNode.next();

		if (nextNode) {
			nextNode.spaces.before = spaceBeforeFirstNestingNode;
		}

		// If it's a descendant combinator remove it, otherwise clear its before space
		if (firstCombinatorNode.value === ' ') {
			firstCombinatorNode.remove();
		} else {
			firstCombinatorNode.spaces.before = '';
		}
	}

	ruleNode.selector = selectorRoot.toString();
}

rule.ruleName = ruleName;
rule.messages = messages;
rule.meta = meta;
export default rule;

And here some revised tests that:

  1. adhere to our conventions
  2. have testcase for some of the cases I've mentioned
Tests:
import { stripIndent } from 'common-tags';

import rule from '../index.mjs';
const { messages, ruleName } = rule;

testRule({
	ruleName,
	config: ['explicit'],
	fix: true,
	computeEditInfo: true,

	accept: [
		{
			code: 'a {}',
			description: 'non-nested rule',
		},
		{
			code: '@media all { a {} }',
			description: 'rule in at-rule',
		},
		{
			code: 'a { & a {} }',
			description: 'explicit nesting with descendant combinator',
		},
		{
			code: 'a { & > a {} }',
			description: 'explicit nesting with child combinator',
		},
		{
			code: 'a { &:hover {} }',
			description: 'nesting with pseudo-class',
		},
		{
			code: 'a { &.foo {} }',
			description: 'nesting with class',
		},
		{
			code: 'a { :not(&) {} }',
			description: 'nesting in pseudo-class',
		},
		{
			code: 'a { a & {} }',
			description: 'nesting selector as parent',
		},
		{
			code: 'a { & /* foo */ a, .bar /* baz */ & {} }',
			description: 'nesting selector in list with comment',
		},
		{
			code: 'a { /* bar */ & a, /* baz */ .foo & {} }',
			description: 'nesting selector in list with starting comments',
		},
		{
			code: stripIndent`
				.a {
					& .foo {
						& > #bar {}
					}
				}
			`,
			description: 'multiple levels of explicit nesting',
		},
	],

	reject: [
		{
			code: 'a { a {} }',
			fixed: 'a { & a {} }',
			message: messages.expected('explicit'),
			line: 1,
			column: 5,
			endLine: 1,
			endColumn: 6,
			fix: {
				range: [4, 5],
				text: '& a',
			},
		},
		{
			code: 'a { > a {} }',
			fixed: 'a { & > a {} }',
			message: messages.expected('explicit'),
			line: 1,
			column: 5,
			endLine: 1,
			endColumn: 8,
			fix: {
				range: [4, 5],
				text: '& >',
			},
		},
		{
			code: 'a { [foo] {} }',
			fixed: 'a { & [foo] {} }',
			message: messages.expected('explicit'),
			line: 1,
			column: 5,
			endLine: 1,
			endColumn: 10,
			fix: {
				range: [4, 5],
				text: '& [',
			},
		},
		{
			code: 'a { + a & {} }',
			fixed: 'a { & + a & {} }',
			description: 'nesting as parent and implicit inital & before combinator',
			message: messages.expected('explicit'),
			line: 1,
			column: 5,
			endLine: 1,
			endColumn: 10,
			fix: {
				range: [4, 5],
				text: '& +',
			},
		},
		{
			code: 'a { @media all { a {} } }',
			fixed: 'a { @media all { & a {} } }',
			description: 'nesting in media query',
			message: messages.expected('explicit'),
			line: 1,
			column: 18,
			endLine: 1,
			endColumn: 19,
			fix: {
				range: [17, 18],
				text: '& a',
			},
		},
		{
			code: 'a { ~ /* foo */ a {} }',
			fixed: 'a { & ~ /* foo */ a {} }',
			description: 'comment in selector',
			message: messages.expected('explicit'),
			line: 1,
			column: 5,
			endLine: 1,
			endColumn: 18,
			fix: {
				range: [4, 5],
				text: '& ~',
			},
		},
		{
			code: 'a { > .foo, /* bar */ + .baz {} }',
			fixed: 'a { & > .foo, /* bar */ & + .baz {} }',
			description: 'selector list with comments ',
			warnings: [
				{
					message: messages.expected('explicit'),
					line: 1,
					column: 5,
					endLine: 1,
					endColumn: 11,
					fix: {
						range: [4, 5],
						text: '& >',
					},
				},
				{
					message: messages.expected('explicit'),
					line: 1,
					column: 12,
					endLine: 1,
					endColumn: 28,
				},
			],
		},
		{
			code: stripIndent`
				a {
					>  .foo {}
					+
					.bar {}
				}
			`,
			fixed: stripIndent`
				a {
					& >  .foo {}
					& +
					.bar {}
				}
			`,
			description: 'extra spacing in selector',
			warnings: [
				{
					message: messages.expected('explicit'),
					line: 2,
					column: 2,
					endLine: 2,
					endColumn: 9,
					fix: {
						range: [5, 6],
						text: '& >',
					},
				},
				{
					message: messages.expected('explicit'),
					line: 3,
					column: 2,
					endLine: 4,
					endColumn: 6,
					fix: {
						range: [17, 18],
						text: '& +',
					},
				},
			],
		},
	],
});

testRule({
	ruleName,
	config: ['implicit'],
	fix: true,
	computeEditInfo: true,

	accept: [
		{
			code: 'a {}',
			description: 'non-nested rule',
		},
		{
			code: 'a { a {} }',
			description: 'nested rule with implied descendant combinator',
		},
		{
			code: 'a { > a {} }',
			description: 'implicit nesting with child combinator',
		},
		{
			code: 'a { &:hover {} }',
			description: 'nesting with pseudo-class (& required)',
		},
		{
			code: 'a { &.foo {} }',
			description: 'nesting with class (& required)',
		},
		{
			code: 'a { :not(&) {} }',
			description: 'nesting in pseudo-class',
		},
		{
			code: 'a { [foo] {} }',
			description: 'nesting in attribute selector',
		},
		{
			code: 'a { a & {} }',
			description: 'nesting selector as parent',
		},
		{
			code: 'a { + a & {} }',
			description: 'nesting selector as parent and implied initial &',
		},
		{
			code: 'a { a, .foo /* bar */ {} }',
			description: 'nesting selector in list with comment',
		},
		{
			code: 'a { /* bar */ a, /* baz */ .foo {} }',
			description: 'nesting selector in list with starting comments',
		},
	],

	reject: [
		{
			code: 'a { & a {} }',
			fixed: 'a { a {} }',
			message: messages.expected('implicit'),
			line: 1,
			column: 5,
			endLine: 1,
			endColumn: 8,
			fix: {
				range: [4, 6],
				text: '',
			},
		},
		{
			code: 'a { & > a {} }',
			fixed: 'a { > a {} }',
			message: messages.expected('implicit'),
			line: 1,
			column: 5,
			endLine: 1,
			endColumn: 10,
			fix: {
				range: [4, 6],
				text: '',
			},
		},
		{
			code: 'a { & > a & {} }',
			fixed: 'a { > a & {} }',
			message: messages.expected('implicit'),
			line: 1,
			column: 5,
			endLine: 1,
			endColumn: 12,
			fix: {
				range: [4, 6],
				text: '',
			},
		},
		{
			code: 'a { & .foo, /* bar */ & .baz {} }',
			fixed: 'a { .foo, /* bar */ .baz {} }',
			warnings: [
				{
					message: messages.expected('implicit'),
					line: 1,
					column: 5,
					endLine: 1,
					endColumn: 11,
					fix: {
						range: [4, 6],
						text: '',
					},
				},
				{
					message: messages.expected('implicit'),
					line: 1,
					column: 12,
					endLine: 1,
					endColumn: 28,
				},
			],
		},
		{
			code: stripIndent`
				a {
					& .foo {}
					& .bar {}
				}
			`,
			fixed: stripIndent`
				a {
					.foo {}
					.bar {}
				}
			`,
			warnings: [
				{
					message: messages.expected('implicit'),
					line: 2,
					column: 2,
					endLine: 2,
					endColumn: 8,
					fix: {
						range: [5, 7],
						text: '',
					},
				},
				{
					message: messages.expected('implicit'),
					line: 3,
					column: 2,
					endLine: 3,
					endColumn: 8,
					fix: {
						range: [16, 18],
						text: '',
					},
				},
			],
		},
	],
});

@jeddy3 jeddy3 changed the title add selector-nesting-notation rule Add selector-nesting-notation rule Aug 16, 2025
@jeddy3 jeddy3 force-pushed the feature/selector-nesting-notation branch from fff9ff5 to d743b9e Compare March 31, 2026 16:00
@jeddy3 jeddy3 changed the title Add selector-nesting-notation rule Add relative-selector-nesting-notation rule Mar 31, 2026
@jeddy3 jeddy3 mentioned this pull request Apr 1, 2026
4 tasks
@jeddy3
Copy link
Copy Markdown
Member

jeddy3 commented Apr 1, 2026

I've pushed some commits to:

  • use the PostCSS Selector parser so that we can maintain comments and whitespace
  • adhere to our latest conventions
  • addressed the remaining review comments

Copy link
Copy Markdown
Member

@ybiquitous ybiquitous left a comment

Choose a reason for hiding this comment

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

Overall LGTM 👍🏼

Suggesting some minor refactorings, can you look at them?

Comment thread lib/rules/relative-selector-nesting-notation/index.mjs Outdated
Comment thread lib/rules/relative-selector-nesting-notation/index.mjs Outdated
Comment thread lib/rules/relative-selector-nesting-notation/index.mjs Outdated
Comment thread lib/rules/relative-selector-nesting-notation/index.mjs Outdated
jeddy3 and others added 6 commits April 4, 2026 07:10
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
@jeddy3
Copy link
Copy Markdown
Member

jeddy3 commented Apr 4, 2026

@ybiquitous Thank you for the review. I've committed all the suggestions.

(I've made a note for myself about the type guards as I often forget about them 😓.)

Copy link
Copy Markdown
Member

@ybiquitous ybiquitous left a comment

Choose a reason for hiding this comment

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

Thank you! I also missed other code where we should have used type guards. 😅

I think it's ready to merge now. 👍🏼

Comment thread lib/rules/relative-selector-nesting-notation/index.mjs Outdated
Comment thread lib/rules/relative-selector-nesting-notation/index.mjs Outdated
Comment thread lib/rules/relative-selector-nesting-notation/index.mjs Outdated
Comment thread lib/rules/relative-selector-nesting-notation/index.mjs Outdated
Comment thread lib/rules/relative-selector-nesting-notation/index.mjs Outdated
jeddy3 and others added 6 commits April 4, 2026 19:52
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
@jeddy3
Copy link
Copy Markdown
Member

jeddy3 commented Apr 4, 2026

I think it's ready to merge now. 👍🏼

Fantastic. Let's hold off on merging the rules for now so we can group them and decide whether they belong in our configs.

Let's shoot for getting the following into the next release instead:

@sw1tch3roo
Copy link
Copy Markdown
Contributor Author

Wow, thanks for your help with my PRs. Now that I'm free, I think we can continue to implement other features. 👀

@jeddy3 jeddy3 merged commit 9ca941e into stylelint:main Apr 14, 2026
16 checks passed
renovate Bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Apr 15, 2026
| datasource | package   | from   | to     |
| ---------- | --------- | ------ | ------ |
| npm        | stylelint | 17.4.0 | 17.8.0 |


## [v17.8.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1780---2026-04-15)

It adds 3 new rules and 1 configuration property.

- Added: `languageOptions.directionality` configuration property ([#8687](stylelint/stylelint#8687)) ([@sw1tch3roo](https://github.com/sw1tch3roo)).
- Added: `property-layout-mappings` rule ([#8687](stylelint/stylelint#8687)) ([@sw1tch3roo](https://github.com/sw1tch3roo)).
- Added: `relative-selector-nesting-notation` rule ([#8730](stylelint/stylelint#8730)) ([@sw1tch3roo](https://github.com/sw1tch3roo)).
- Added: `selector-no-deprecated` rule ([#8694](stylelint/stylelint#8694)) ([@immitsu](https://github.com/immitsu)).


## [v17.7.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1770---2026-04-12)

It fixes 4 bugs, including clearer problem messages by removing filler words and leading with the problem. We've also released `1.0.0` of [create-stylelint](https://github.com/stylelint/create-stylelint) to help with first-time Stylelint setup.

- Fixed: clarity of problem messages ([#9199](stylelint/stylelint#9199)) ([@jeddy3](https://github.com/jeddy3)).
- Fixed: `--print-config` CLI flag to hide internal properties ([#9194](stylelint/stylelint#9194)) ([@ybiquitous](https://github.com/ybiquitous)).
- Fixed: `function-url-quotes` false positives when URLs have modifiers ([#8702](stylelint/stylelint#8702)) ([@immitsu](https://github.com/immitsu)).
- Fixed: `selector-no-qualifying-type` false positives for `:has()` ([#9182](stylelint/stylelint#9182)) ([@romainmenke](https://github.com/romainmenke)).


## [v17.6.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1760---2026-03-26)

It adds support for extending units in `languageOptions`, which then apply to rules like `declaration-property-value-no-unknown`, and fixes 2 bugs.

- Added: support for extending units to `languageOptions` ([#9166](stylelint/stylelint#9166)) ([@jeddy3](https://github.com/jeddy3)).
- Fixed: missing `ruleMetadata` when linting multiple files with overrides ([#9154](stylelint/stylelint#9154)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `custom-property-no-missing-var-function` false positives for `timeline-scope` and `animation-timeline` ([#9164](stylelint/stylelint#9164)) ([@splincode](https://github.com/splincode)).


## [v17.5.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1750---2026-03-19)

It deprecates two rule options, adds 1 rule option and fixes 7 bugs. We've also released [`2.1.0`](https://github.com/stylelint/vscode-stylelint/releases/tag/2.1.0) of [our VS Code extension](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint), which adds 8 new requested features, and our [first release](https://www.npmjs.com/package/@stylelint/language-server) of the Stylelint Language Server.

- Deprecated: `*syntax` options from `declaration-property-value-no-unknown` ([#9102](stylelint/stylelint#9102)) ([@ragini-pandey](https://github.com/ragini-pandey)).
- Added: `ignoreMediaFeatureNameValues: {}` to `media-feature-name-value-no-unknown` ([#8976](stylelint/stylelint#8976)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `node_modules` not ignored when using `codeFilename` in Node.js API ([#9130](stylelint/stylelint#9130)) ([@adalinesimonian](https://github.com/adalinesimonian)).
- Fixed: `Error TS7016` for imported `css-tree` types ([#9133](stylelint/stylelint#9133)) ([@ragini-pandey](https://github.com/ragini-pandey)).
- Fixed: `declaration-property-value-keyword-no-deprecated` false positives for function arguments ([#9116](stylelint/stylelint#9116)) ([@ragini-pandey](https://github.com/ragini-pandey)).
- Fixed: `declaration-property-value-no-unknown` false positives for `calc-size()` containing `size` keyword ([#9105](stylelint/stylelint#9105)) ([@hriztam](https://github.com/hriztam)).
- Fixed: `no-descending-specificity` & `no-duplicate-selectors` false negatives for equivalent compound selectors ([#8977](stylelint/stylelint#8977)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `no-invalid-position-declaration` false positives for `@mixin` and `@scope` ([#9120](stylelint/stylelint#9120)) ([@ragini-pandey](https://github.com/ragini-pandey)).
- Fixed: `property-no-unknown` false negatives for `types` ([#9117](stylelint/stylelint#9117)) ([@Mouvedia](https://github.com/Mouvedia)).
robbevp pushed a commit to robbevp/website-robbevanpetegem that referenced this pull request Apr 18, 2026
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [eslint](https://eslint.org) ([source](https://github.com/eslint/eslint)) | devDependencies | patch | [`9.39.3` -> `9.39.4`](https://renovatebot.com/diffs/npm/eslint/9.39.3/9.39.4) |
| [prettier](https://prettier.io) ([source](https://github.com/prettier/prettier)) | devDependencies | patch | [`3.8.1` -> `3.8.3`](https://renovatebot.com/diffs/npm/prettier/3.8.1/3.8.3) |
| [stylelint](https://stylelint.io) ([source](https://github.com/stylelint/stylelint)) | devDependencies | minor | [`17.4.0` -> `17.8.0`](https://renovatebot.com/diffs/npm/stylelint/17.4.0/17.8.0) |

---

### Release Notes

<details>
<summary>eslint/eslint (eslint)</summary>

### [`v9.39.4`](https://github.com/eslint/eslint/releases/tag/v9.39.4)

[Compare Source](eslint/eslint@v9.39.3...v9.39.4)

#### Bug Fixes

- [`f18f6c8`](eslint/eslint@f18f6c8) fix: update dependency minimatch to ^3.1.5 ([#&#8203;20564](eslint/eslint#20564)) (Milos Djermanovic)
- [`a3c868f`](eslint/eslint@a3c868f) fix: update dependency [@&#8203;eslint/eslintrc](https://github.com/eslint/eslintrc) to ^3.3.4 ([#&#8203;20554](eslint/eslint#20554)) (Milos Djermanovic)
- [`234d005`](eslint/eslint@234d005) fix: minimatch security vulnerability patch for v9.x ([#&#8203;20549](eslint/eslint#20549)) (Andrej Beles)
- [`b1b37ee`](eslint/eslint@b1b37ee) fix: update `ajv` to `6.14.0` to address security vulnerabilities ([#&#8203;20538](eslint/eslint#20538)) (루밀LuMir)

#### Documentation

- [`4675152`](eslint/eslint@4675152) docs: add deprecation notice partial ([#&#8203;20520](eslint/eslint#20520)) (Milos Djermanovic)

#### Chores

- [`b8b4eb1`](eslint/eslint@b8b4eb1) chore: update dependencies for ESLint v9.39.4 ([#&#8203;20596](eslint/eslint#20596)) (Francesco Trotta)
- [`71b2f6b`](eslint/eslint@71b2f6b) chore: package.json update for [@&#8203;eslint/js](https://github.com/eslint/js) release (Jenkins)
- [`1d16c2f`](eslint/eslint@1d16c2f) ci: pin Node.js 25.6.1 ([#&#8203;20563](eslint/eslint#20563)) (Milos Djermanovic)

</details>

<details>
<summary>prettier/prettier (prettier)</summary>

### [`v3.8.3`](https://github.com/prettier/prettier/blob/HEAD/CHANGELOG.md#383)

[Compare Source](prettier/prettier@3.8.2...3.8.3)

[diff](prettier/prettier@3.8.2...3.8.3)

##### SCSS: Prevent trailing comma in `if()` function ([#&#8203;18471](prettier/prettier#18471) by [@&#8203;kovsu](https://github.com/kovsu))

<!-- prettier-ignore -->

```scss
// Input
$value: if(sass(false): 1; else: -1);

// Prettier 3.8.2
$value: if(
  sass(false): 1; else: -1,
);

// Prettier 3.8.3
$value: if(sass(false): 1; else: -1);
```

### [`v3.8.2`](https://github.com/prettier/prettier/blob/HEAD/CHANGELOG.md#382)

[Compare Source](prettier/prettier@3.8.1...3.8.2)

[diff](prettier/prettier@3.8.1...3.8.2)

##### Angular: Support Angular v21.2 ([#&#8203;18722](prettier/prettier#18722), [#&#8203;19034](prettier/prettier#19034) by [@&#8203;fisker](https://github.com/fisker))

Exhaustive typechecking with `@default never;`

<!-- prettier-ignore -->

```html
<!-- Input -->
@&#8203;switch (foo) {
  @&#8203;case (1) {}
  @&#8203;default never;
}

<!-- Prettier 3.8.1 -->
SyntaxError: Incomplete block "default never". If you meant to write the @&#8203; character, you should use the "&#&#8203;64;" HTML entity instead. (3:3)

<!-- Prettier 3.8.2 -->
@&#8203;switch (foo) {
  @&#8203;case (1) {}
  @&#8203;default never;
}
```

`arrow function` and `instanceof` expressions.

<!-- prettier-ignore -->

```html
<!-- Input -->
@&#8203;let fn = (a) =>        a?    1:2;

{{ fn ( a         instanceof b)}}

<!-- Prettier 3.8.1 -->
@&#8203;let fn = (a) =>        a?    1:2;

{{ fn ( a         instanceof b)}}

<!-- Prettier 3.8.2 -->
@&#8203;let fn = (a) => (a ? 1 : 2);

{{ fn(a instanceof b) }}
```

</details>

<details>
<summary>stylelint/stylelint (stylelint)</summary>

### [`v17.8.0`](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1780---2026-04-15)

[Compare Source](stylelint/stylelint@17.7.0...17.8.0)

It adds 3 new rules and 1 configuration property.

- Added: `languageOptions.directionality` configuration property ([#&#8203;8687](stylelint/stylelint#8687)) ([@&#8203;sw1tch3roo](https://github.com/sw1tch3roo)).
- Added: `property-layout-mappings` rule ([#&#8203;8687](stylelint/stylelint#8687)) ([@&#8203;sw1tch3roo](https://github.com/sw1tch3roo)).
- Added: `relative-selector-nesting-notation` rule ([#&#8203;8730](stylelint/stylelint#8730)) ([@&#8203;sw1tch3roo](https://github.com/sw1tch3roo)).
- Added: `selector-no-deprecated` rule ([#&#8203;8694](stylelint/stylelint#8694)) ([@&#8203;immitsu](https://github.com/immitsu)).

### [`v17.7.0`](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1770---2026-04-12)

[Compare Source](stylelint/stylelint@17.6.0...17.7.0)

It fixes 4 bugs, including clearer problem messages by removing filler words and leading with the problem. We've also released `1.0.0` of [create-stylelint](https://github.com/stylelint/create-stylelint) to help with first-time Stylelint setup.

- Fixed: clarity of problem messages ([#&#8203;9199](stylelint/stylelint#9199)) ([@&#8203;jeddy3](https://github.com/jeddy3)).
- Fixed: `--print-config` CLI flag to hide internal properties ([#&#8203;9194](stylelint/stylelint#9194)) ([@&#8203;ybiquitous](https://github.com/ybiquitous)).
- Fixed: `function-url-quotes` false positives when URLs have modifiers ([#&#8203;8702](stylelint/stylelint#8702)) ([@&#8203;immitsu](https://github.com/immitsu)).
- Fixed: `selector-no-qualifying-type` false positives for `:has()` ([#&#8203;9182](stylelint/stylelint#9182)) ([@&#8203;romainmenke](https://github.com/romainmenke)).

### [`v17.6.0`](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1760---2026-03-26)

[Compare Source](stylelint/stylelint@17.5.0...17.6.0)

It adds support for extending units in `languageOptions`, which then apply to rules like `declaration-property-value-no-unknown`, and fixes 2 bugs.

- Added: support for extending units to `languageOptions` ([#&#8203;9166](stylelint/stylelint#9166)) ([@&#8203;jeddy3](https://github.com/jeddy3)).
- Fixed: missing `ruleMetadata` when linting multiple files with overrides ([#&#8203;9154](stylelint/stylelint#9154)) ([@&#8203;kovsu](https://github.com/kovsu)).
- Fixed: `custom-property-no-missing-var-function` false positives for `timeline-scope` and `animation-timeline` ([#&#8203;9164](stylelint/stylelint#9164)) ([@&#8203;splincode](https://github.com/splincode)).

### [`v17.5.0`](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1750---2026-03-19)

[Compare Source](stylelint/stylelint@17.4.0...17.5.0)

It deprecates two rule options, adds 1 rule option and fixes 7 bugs. We've also released [`2.1.0`](https://github.com/stylelint/vscode-stylelint/releases/tag/2.1.0) of [our VS Code extension](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint), which adds 8 new requested features, and our [first release](https://www.npmjs.com/package/@&#8203;stylelint/language-server) of the Stylelint Language Server.

- Deprecated: `*syntax` options from `declaration-property-value-no-unknown` ([#&#8203;9102](stylelint/stylelint#9102)) ([@&#8203;ragini-pandey](https://github.com/ragini-pandey)).
- Added: `ignoreMediaFeatureNameValues: {}` to `media-feature-name-value-no-unknown` ([#&#8203;8976](stylelint/stylelint#8976)) ([@&#8203;kovsu](https://github.com/kovsu)).
- Fixed: `node_modules` not ignored when using `codeFilename` in Node.js API ([#&#8203;9130](stylelint/stylelint#9130)) ([@&#8203;adalinesimonian](https://github.com/adalinesimonian)).
- Fixed: `Error TS7016` for imported `css-tree` types ([#&#8203;9133](stylelint/stylelint#9133)) ([@&#8203;ragini-pandey](https://github.com/ragini-pandey)).
- Fixed: `declaration-property-value-keyword-no-deprecated` false positives for function arguments ([#&#8203;9116](stylelint/stylelint#9116)) ([@&#8203;ragini-pandey](https://github.com/ragini-pandey)).
- Fixed: `declaration-property-value-no-unknown` false positives for `calc-size()` containing `size` keyword ([#&#8203;9105](stylelint/stylelint#9105)) ([@&#8203;hriztam](https://github.com/hriztam)).
- Fixed: `no-descending-specificity` & `no-duplicate-selectors` false negatives for equivalent compound selectors ([#&#8203;8977](stylelint/stylelint#8977)) ([@&#8203;kovsu](https://github.com/kovsu)).
- Fixed: `no-invalid-position-declaration` false positives for `@mixin` and `@scope` ([#&#8203;9120](stylelint/stylelint#9120)) ([@&#8203;ragini-pandey](https://github.com/ragini-pandey)).
- Fixed: `property-no-unknown` false negatives for `types` ([#&#8203;9117](stylelint/stylelint#9117)) ([@&#8203;Mouvedia](https://github.com/Mouvedia)).

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS42MS4wIiwidXBkYXRlZEluVmVyIjoiNDEuNjEuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://git.robbevp.be/robbevp/website-robbevanpetegem/pulls/508
Co-authored-by: Renovate Bot <renovate@robbevp.be>
Co-committed-by: Renovate Bot <renovate@robbevp.be>
renovate Bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Apr 19, 2026
| datasource | package   | from   | to     |
| ---------- | --------- | ------ | ------ |
| npm        | stylelint | 17.4.0 | 17.8.0 |


## [v17.8.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1780---2026-04-15)

It adds 3 new rules and 1 configuration property.

- Added: `languageOptions.directionality` configuration property ([#8687](stylelint/stylelint#8687)) ([@sw1tch3roo](https://github.com/sw1tch3roo)).
- Added: `property-layout-mappings` rule ([#8687](stylelint/stylelint#8687)) ([@sw1tch3roo](https://github.com/sw1tch3roo)).
- Added: `relative-selector-nesting-notation` rule ([#8730](stylelint/stylelint#8730)) ([@sw1tch3roo](https://github.com/sw1tch3roo)).
- Added: `selector-no-deprecated` rule ([#8694](stylelint/stylelint#8694)) ([@immitsu](https://github.com/immitsu)).


## [v17.7.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1770---2026-04-12)

It fixes 4 bugs, including clearer problem messages by removing filler words and leading with the problem. We've also released `1.0.0` of [create-stylelint](https://github.com/stylelint/create-stylelint) to help with first-time Stylelint setup.

- Fixed: clarity of problem messages ([#9199](stylelint/stylelint#9199)) ([@jeddy3](https://github.com/jeddy3)).
- Fixed: `--print-config` CLI flag to hide internal properties ([#9194](stylelint/stylelint#9194)) ([@ybiquitous](https://github.com/ybiquitous)).
- Fixed: `function-url-quotes` false positives when URLs have modifiers ([#8702](stylelint/stylelint#8702)) ([@immitsu](https://github.com/immitsu)).
- Fixed: `selector-no-qualifying-type` false positives for `:has()` ([#9182](stylelint/stylelint#9182)) ([@romainmenke](https://github.com/romainmenke)).


## [v17.6.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1760---2026-03-26)

It adds support for extending units in `languageOptions`, which then apply to rules like `declaration-property-value-no-unknown`, and fixes 2 bugs.

- Added: support for extending units to `languageOptions` ([#9166](stylelint/stylelint#9166)) ([@jeddy3](https://github.com/jeddy3)).
- Fixed: missing `ruleMetadata` when linting multiple files with overrides ([#9154](stylelint/stylelint#9154)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `custom-property-no-missing-var-function` false positives for `timeline-scope` and `animation-timeline` ([#9164](stylelint/stylelint#9164)) ([@splincode](https://github.com/splincode)).


## [v17.5.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1750---2026-03-19)

It deprecates two rule options, adds 1 rule option and fixes 7 bugs. We've also released [`2.1.0`](https://github.com/stylelint/vscode-stylelint/releases/tag/2.1.0) of [our VS Code extension](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint), which adds 8 new requested features, and our [first release](https://www.npmjs.com/package/@stylelint/language-server) of the Stylelint Language Server.

- Deprecated: `*syntax` options from `declaration-property-value-no-unknown` ([#9102](stylelint/stylelint#9102)) ([@ragini-pandey](https://github.com/ragini-pandey)).
- Added: `ignoreMediaFeatureNameValues: {}` to `media-feature-name-value-no-unknown` ([#8976](stylelint/stylelint#8976)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `node_modules` not ignored when using `codeFilename` in Node.js API ([#9130](stylelint/stylelint#9130)) ([@adalinesimonian](https://github.com/adalinesimonian)).
- Fixed: `Error TS7016` for imported `css-tree` types ([#9133](stylelint/stylelint#9133)) ([@ragini-pandey](https://github.com/ragini-pandey)).
- Fixed: `declaration-property-value-keyword-no-deprecated` false positives for function arguments ([#9116](stylelint/stylelint#9116)) ([@ragini-pandey](https://github.com/ragini-pandey)).
- Fixed: `declaration-property-value-no-unknown` false positives for `calc-size()` containing `size` keyword ([#9105](stylelint/stylelint#9105)) ([@hriztam](https://github.com/hriztam)).
- Fixed: `no-descending-specificity` & `no-duplicate-selectors` false negatives for equivalent compound selectors ([#8977](stylelint/stylelint#8977)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `no-invalid-position-declaration` false positives for `@mixin` and `@scope` ([#9120](stylelint/stylelint#9120)) ([@ragini-pandey](https://github.com/ragini-pandey)).
- Fixed: `property-no-unknown` false negatives for `types` ([#9117](stylelint/stylelint#9117)) ([@Mouvedia](https://github.com/Mouvedia)).
renovate Bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Apr 30, 2026
| datasource | package   | from   | to     |
| ---------- | --------- | ------ | ------ |
| npm        | stylelint | 17.4.0 | 17.9.1 |


## [v17.9.1](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1791---2026-04-27)

It fixes 4 bugs. We also documented the `messageArgs` each rule provides to the `message` configuration property.

- Fixed: `ConfigurationError` regression for custom syntaxes ([#9245](stylelint/stylelint#9245)) ([@jeddy3](https://github.com/jeddy3)).
- Fixed: MD5 hash algorithm to SHA256 for caching ([#9241](stylelint/stylelint#9241)) ([@rkdfx](https://github.com/rkdfx)).
- Fixed: `property-no-deprecated` autofix for `page-break-*: always` ([#9214](stylelint/stylelint#9214)) ([@rkdfx](https://github.com/rkdfx)).
- Fixed: `selector-no-deprecated` false positives for `::part()` ([#9227](stylelint/stylelint#9227)) ([@SaekiTominaga](https://github.com/SaekiTominaga)).


## [v17.9.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1790---2026-04-23)

It adds 3 new features. Adding the `referenceFiles` property to your configuration object makes the `no-unknown-animations`, `no-unknown-custom-media` and `no-unknown-custom-properties` rules more useful.

- Added: experimental `referenceFiles` to configuration object ([#9179](stylelint/stylelint#9179)) ([@jeddy3](https://github.com/jeddy3)).
- Added: experimental `abortSignal` option to Node.js API for cancellation support ([#9213](stylelint/stylelint#9213)) ([@adalinesimonian](https://github.com/adalinesimonian)).
- Added: `maxWarnings` to configuration object ([#9181](stylelint/stylelint#9181)) ([@mrginglymus](https://github.com/mrginglymus)).


## [v17.8.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1780---2026-04-15)

It adds 3 new rules and 1 configuration property.

- Added: `languageOptions.directionality` configuration property ([#8687](stylelint/stylelint#8687)) ([@sw1tch3roo](https://github.com/sw1tch3roo)).
- Added: `property-layout-mappings` rule ([#8687](stylelint/stylelint#8687)) ([@sw1tch3roo](https://github.com/sw1tch3roo)).
- Added: `relative-selector-nesting-notation` rule ([#8730](stylelint/stylelint#8730)) ([@sw1tch3roo](https://github.com/sw1tch3roo)).
- Added: `selector-no-deprecated` rule ([#8694](stylelint/stylelint#8694)) ([@immitsu](https://github.com/immitsu)).


## [v17.7.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1770---2026-04-12)

It fixes 4 bugs, including clearer problem messages by removing filler words and leading with the problem. We've also released `1.0.0` of [create-stylelint](https://github.com/stylelint/create-stylelint) to help with first-time Stylelint setup.

- Fixed: clarity of problem messages ([#9199](stylelint/stylelint#9199)) ([@jeddy3](https://github.com/jeddy3)).
- Fixed: `--print-config` CLI flag to hide internal properties ([#9194](stylelint/stylelint#9194)) ([@ybiquitous](https://github.com/ybiquitous)).
- Fixed: `function-url-quotes` false positives when URLs have modifiers ([#8702](stylelint/stylelint#8702)) ([@immitsu](https://github.com/immitsu)).
- Fixed: `selector-no-qualifying-type` false positives for `:has()` ([#9182](stylelint/stylelint#9182)) ([@romainmenke](https://github.com/romainmenke)).


## [v17.6.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1760---2026-03-26)

It adds support for extending units in `languageOptions`, which then apply to rules like `declaration-property-value-no-unknown`, and fixes 2 bugs.

- Added: support for extending units to `languageOptions` ([#9166](stylelint/stylelint#9166)) ([@jeddy3](https://github.com/jeddy3)).
- Fixed: missing `ruleMetadata` when linting multiple files with overrides ([#9154](stylelint/stylelint#9154)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `custom-property-no-missing-var-function` false positives for `timeline-scope` and `animation-timeline` ([#9164](stylelint/stylelint#9164)) ([@splincode](https://github.com/splincode)).


## [v17.5.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1750---2026-03-19)

It deprecates two rule options, adds 1 rule option and fixes 7 bugs. We've also released [`2.1.0`](https://github.com/stylelint/vscode-stylelint/releases/tag/2.1.0) of [our VS Code extension](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint), which adds 8 new requested features, and our [first release](https://www.npmjs.com/package/@stylelint/language-server) of the Stylelint Language Server.

- Deprecated: `*syntax` options from `declaration-property-value-no-unknown` ([#9102](stylelint/stylelint#9102)) ([@ragini-pandey](https://github.com/ragini-pandey)).
- Added: `ignoreMediaFeatureNameValues: {}` to `media-feature-name-value-no-unknown` ([#8976](stylelint/stylelint#8976)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `node_modules` not ignored when using `codeFilename` in Node.js API ([#9130](stylelint/stylelint#9130)) ([@adalinesimonian](https://github.com/adalinesimonian)).
- Fixed: `Error TS7016` for imported `css-tree` types ([#9133](stylelint/stylelint#9133)) ([@ragini-pandey](https://github.com/ragini-pandey)).
- Fixed: `declaration-property-value-keyword-no-deprecated` false positives for function arguments ([#9116](stylelint/stylelint#9116)) ([@ragini-pandey](https://github.com/ragini-pandey)).
- Fixed: `declaration-property-value-no-unknown` false positives for `calc-size()` containing `size` keyword ([#9105](stylelint/stylelint#9105)) ([@hriztam](https://github.com/hriztam)).
- Fixed: `no-descending-specificity` & `no-duplicate-selectors` false negatives for equivalent compound selectors ([#8977](stylelint/stylelint#8977)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `no-invalid-position-declaration` false positives for `@mixin` and `@scope` ([#9120](stylelint/stylelint#9120)) ([@ragini-pandey](https://github.com/ragini-pandey)).
- Fixed: `property-no-unknown` false negatives for `types` ([#9117](stylelint/stylelint#9117)) ([@Mouvedia](https://github.com/Mouvedia)).
renovate Bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request May 2, 2026
| datasource | package   | from   | to     |
| ---------- | --------- | ------ | ------ |
| npm        | stylelint | 17.4.0 | 17.9.1 |


## [v17.9.1](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1791---2026-04-27)

It fixes 4 bugs. We also documented the `messageArgs` each rule provides to the `message` configuration property.

- Fixed: `ConfigurationError` regression for custom syntaxes ([#9245](stylelint/stylelint#9245)) ([@jeddy3](https://github.com/jeddy3)).
- Fixed: MD5 hash algorithm to SHA256 for caching ([#9241](stylelint/stylelint#9241)) ([@rkdfx](https://github.com/rkdfx)).
- Fixed: `property-no-deprecated` autofix for `page-break-*: always` ([#9214](stylelint/stylelint#9214)) ([@rkdfx](https://github.com/rkdfx)).
- Fixed: `selector-no-deprecated` false positives for `::part()` ([#9227](stylelint/stylelint#9227)) ([@SaekiTominaga](https://github.com/SaekiTominaga)).


## [v17.9.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1790---2026-04-23)

It adds 3 new features. Adding the `referenceFiles` property to your configuration object makes the `no-unknown-animations`, `no-unknown-custom-media` and `no-unknown-custom-properties` rules more useful.

- Added: experimental `referenceFiles` to configuration object ([#9179](stylelint/stylelint#9179)) ([@jeddy3](https://github.com/jeddy3)).
- Added: experimental `abortSignal` option to Node.js API for cancellation support ([#9213](stylelint/stylelint#9213)) ([@adalinesimonian](https://github.com/adalinesimonian)).
- Added: `maxWarnings` to configuration object ([#9181](stylelint/stylelint#9181)) ([@mrginglymus](https://github.com/mrginglymus)).


## [v17.8.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1780---2026-04-15)

It adds 3 new rules and 1 configuration property.

- Added: `languageOptions.directionality` configuration property ([#8687](stylelint/stylelint#8687)) ([@sw1tch3roo](https://github.com/sw1tch3roo)).
- Added: `property-layout-mappings` rule ([#8687](stylelint/stylelint#8687)) ([@sw1tch3roo](https://github.com/sw1tch3roo)).
- Added: `relative-selector-nesting-notation` rule ([#8730](stylelint/stylelint#8730)) ([@sw1tch3roo](https://github.com/sw1tch3roo)).
- Added: `selector-no-deprecated` rule ([#8694](stylelint/stylelint#8694)) ([@immitsu](https://github.com/immitsu)).


## [v17.7.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1770---2026-04-12)

It fixes 4 bugs, including clearer problem messages by removing filler words and leading with the problem. We've also released `1.0.0` of [create-stylelint](https://github.com/stylelint/create-stylelint) to help with first-time Stylelint setup.

- Fixed: clarity of problem messages ([#9199](stylelint/stylelint#9199)) ([@jeddy3](https://github.com/jeddy3)).
- Fixed: `--print-config` CLI flag to hide internal properties ([#9194](stylelint/stylelint#9194)) ([@ybiquitous](https://github.com/ybiquitous)).
- Fixed: `function-url-quotes` false positives when URLs have modifiers ([#8702](stylelint/stylelint#8702)) ([@immitsu](https://github.com/immitsu)).
- Fixed: `selector-no-qualifying-type` false positives for `:has()` ([#9182](stylelint/stylelint#9182)) ([@romainmenke](https://github.com/romainmenke)).


## [v17.6.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1760---2026-03-26)

It adds support for extending units in `languageOptions`, which then apply to rules like `declaration-property-value-no-unknown`, and fixes 2 bugs.

- Added: support for extending units to `languageOptions` ([#9166](stylelint/stylelint#9166)) ([@jeddy3](https://github.com/jeddy3)).
- Fixed: missing `ruleMetadata` when linting multiple files with overrides ([#9154](stylelint/stylelint#9154)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `custom-property-no-missing-var-function` false positives for `timeline-scope` and `animation-timeline` ([#9164](stylelint/stylelint#9164)) ([@splincode](https://github.com/splincode)).


## [v17.5.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1750---2026-03-19)

It deprecates two rule options, adds 1 rule option and fixes 7 bugs. We've also released [`2.1.0`](https://github.com/stylelint/vscode-stylelint/releases/tag/2.1.0) of [our VS Code extension](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint), which adds 8 new requested features, and our [first release](https://www.npmjs.com/package/@stylelint/language-server) of the Stylelint Language Server.

- Deprecated: `*syntax` options from `declaration-property-value-no-unknown` ([#9102](stylelint/stylelint#9102)) ([@ragini-pandey](https://github.com/ragini-pandey)).
- Added: `ignoreMediaFeatureNameValues: {}` to `media-feature-name-value-no-unknown` ([#8976](stylelint/stylelint#8976)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `node_modules` not ignored when using `codeFilename` in Node.js API ([#9130](stylelint/stylelint#9130)) ([@adalinesimonian](https://github.com/adalinesimonian)).
- Fixed: `Error TS7016` for imported `css-tree` types ([#9133](stylelint/stylelint#9133)) ([@ragini-pandey](https://github.com/ragini-pandey)).
- Fixed: `declaration-property-value-keyword-no-deprecated` false positives for function arguments ([#9116](stylelint/stylelint#9116)) ([@ragini-pandey](https://github.com/ragini-pandey)).
- Fixed: `declaration-property-value-no-unknown` false positives for `calc-size()` containing `size` keyword ([#9105](stylelint/stylelint#9105)) ([@hriztam](https://github.com/hriztam)).
- Fixed: `no-descending-specificity` & `no-duplicate-selectors` false negatives for equivalent compound selectors ([#8977](stylelint/stylelint#8977)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `no-invalid-position-declaration` false positives for `@mixin` and `@scope` ([#9120](stylelint/stylelint#9120)) ([@ragini-pandey](https://github.com/ragini-pandey)).
- Fixed: `property-no-unknown` false negatives for `types` ([#9117](stylelint/stylelint#9117)) ([@Mouvedia](https://github.com/Mouvedia)).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Add selector-nesting-notation

4 participants