Skip to content

Add experimental referenceFiles to configuration object#9179

Merged
jeddy3 merged 31 commits into
mainfrom
add-semantic
Apr 15, 2026
Merged

Add experimental referenceFiles to configuration object#9179
jeddy3 merged 31 commits into
mainfrom
add-semantic

Conversation

@jeddy3
Copy link
Copy Markdown
Member

@jeddy3 jeddy3 commented Mar 25, 2026

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

Closes #4088

Is there anything in the PR that needs further explanation?

I figured I'd start on this long-standing issue.

I've used semantics semanticFiles and semanticRoots to convey that they provide additional meaning to rules. I wanted to avoid:

  • "inject" as the contents of the files aren't added to the current source
  • "resolve/import" as the feature is unrelated to dependency graphs or @import

It's a simpler implementation than the latter, which will work for most use cases.

I've reused patterns and mechanics we already have, and haven't added anything novel:

  • the semantics semanticFilesconfiguration property shape and tests are based on the overrides one
  • semanticRoots aligns with the lexer (see #9067)
  • the docs align with what we do for languageOptions and overrides

I've implemented semanticRoots in:

  • no-unknown-animations
  • no-unknown-custom-media
  • no-unknown-custom-properties

These are the three rules that are seldom used by people because of the limitation this PR removes. Rules such as declaration-property-value-no-unknown and custom-property-no-missing-var-function only have false negatives that we can address later down the line.

I think I've documented the feature in all the relevant spots: configuring, customising, writing rules, rule READMEs, etc.

One thing to note... unlike parse errors in linted files, which are caught and displayed as lint problems, parse errors in semantic files will throw an exception. They can't be displayed as lint problems, and throwing felt like a better user experience than silently ignoring them.

For example:

ConfigurationError: Failed to parse semantic file "/code/tokens.css": /tokens.css:17:1: Unclosed block

I've marked the feature as experimental so we can iron out behaviour like this over time.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Mar 25, 2026

🦋 Changeset detected

Latest commit: 8759a24

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 Mar 25, 2026

This PR is packaged and the instant preview is available (8759a24). View the demo website.

Install it locally:

npm i -D https://pkg.pr.new/stylelint@8759a24

@jeddy3 jeddy3 changed the title Add experimental semantics to configuration object Add experimental semanticFiles to configuration object Mar 26, 2026
@jeddy3
Copy link
Copy Markdown
Member Author

jeddy3 commented Mar 26, 2026

I've pushed a commit to change the configuration property name to semanticFiles, which is hopefully less abstract than semantics, and:

  • mirrors semanticRoots
  • aligns with the proposal for a future top-level files property (see #3860)
  • provides a cleaner config when using CSS (our primary use case)
export default {
  extends: ["stylelint-config-standard"],
  semanticFiles: ["tokens/*.css"],
  rules: {
   "no-unknown-animations": true,
   "no-unknown-custom-properties": true,
   "no-unknown-custom-media": true
 }
}

Copy link
Copy Markdown
Member

@romainmenke romainmenke left a comment

Choose a reason for hiding this comment

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

Just a quick comment to thank you for working on this!
It looks great and when I tried it out on a project it immediately found a bug!

Image

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.

[question] How would semanticFiles work with overrides?

@jeddy3
Copy link
Copy Markdown
Member Author

jeddy3 commented Mar 30, 2026

@ybiquitous It replaces the semanticFiles for any matching files.

I've pushed a commit to add a second overrides test, this one for a top-level semanticFiles being overridden.

For example, the files in components only use the animations tokens:

{
  "semanticFiles": ["tokens/*css"],
  "rules": {
    "no-unknown-animations": true,
    "no-unknown-custom-properties": true
  },
  "overrides": [
    {
      "files": ["components/*.css"],
      "semanticFiles": ["tokens/animations.css"]
    }
  ]
}

Leveraging overrides felt more appropriate than the secondary option approach in the original proposal (#4088 (comment)):

an optional secondary option on rules so that users can customise what roots are used (if any)

@ybiquitous
Copy link
Copy Markdown
Member

Thanks @jeddy3. Still, I'm curious how we should handle customSyntax in overrides when using semanticFiles. For example, would the following be reasonable? 🤔

{
  overrides: {
    files: ["**/*.scss"],
    customSyntax: "postcss-scss",
    semanticFiles: [
      { files: ["root.scss"], customSyntax: "postcss-scss" }
    ]
  }
}

@ybiquitous
Copy link
Copy Markdown
Member

I've used semantics semanticFiles and semanticRoots to convey that they provide additional meaning to rules.

About the naming of the new property, as the description above mentions, let me show my personal idea.

Personally, the "semantic" word seems a bit too serious and unclear to me. For example, what about contextFiles instead? It might read as "files that provide additional context to the linter", without sounding academic ("semantic").

@jeddy3
Copy link
Copy Markdown
Member Author

jeddy3 commented Mar 31, 2026

@ybiquitous Good questions, thank you!

For example, would the following be reasonable?

I'm leaning towards yes, as the alternative is to implicitly couple and inherit customSyntax into semanticFiles. Explicit is generally better, even if there's some redundancy in certain configurations when not linting CSS.

For example, what about contextFiles instead?

It's a good suggestion, but my concern is that we already have context and overloading the word may confuse plugin authors as they're unrelated features. What about referenceFiles: [] and referenceRoots, as in "files the linter references for additional information"?

Am I right in thinking that "reference" is a more common and universally understood word than "semantic"?

@ybiquitous
Copy link
Copy Markdown
Member

What about referenceFiles: [] and referenceRoots, as in "files the linter references for additional information"?

Yeah, they're definitely better! 👍🏼
I missed that we already have context for a different purpose.

@ybiquitous
Copy link
Copy Markdown
Member

About possibly redundant customSyntax in overrides and semanticFiles.

Considering that we often use overrides and customSyntax at the same time, it might be simpler for people if we could move customSyntax out of semanticFiles instead. 🤔

For example, users might expect the following config:

{
  overrides: [
    // Standard CSS sources
    {
      files: ["**/*.css"],
      semanticFiles: ["root.css"],
    },

    // Non-standard SCSS sources
    {
      files: ["**/*.scss"],
      customSyntax: "postcss-scss",

      // Parsed by `postcss-scss`, as well as `files`, in the same `overrides` entry
      semanticFiles: ["root.scss"],
    }
  ]
}

We might consider the following case, but I believe it's an edge case:

{
  overrides: [
    {
      files: ["app/**/*.css"],

      // This should be parsed by `postcss-scss`, but `customSyntax` is not allowed here
      semanticFiles: ["root.scss"],
    }
  ]
}

What do you think? @jeddy3

@jeddy3
Copy link
Copy Markdown
Member Author

jeddy3 commented Mar 31, 2026

It's a good point.

I wonder whether it's not redundant when we're favouring explicitness over implicit coupling, though.

Another case is:

{
  customSyntax: "postcss-scss",
  overrides: [
    {
      files: ["new/**/*.scss"],
      // This should be parsed by the default parser but will inherit the top-level `customSyntax`
      semanticFiles: ["root.css"],
    }
  ]
}

e.g., a team is migrating a project from SCSS to CSS and has started with their variables file, but most of the other files are still SCSS, so they use customSyntax at the top level.

It feels like we can avoid these wrinkles by being explicit: "these are the reference files, and this is the custom syntax I want to use on them":

referenceFiles: [
  "custom-properties.css",
  { files: ["dollar-variables.scss"], customSyntax: "postcss-scss" }
]

Both approaches feel like compromises, though. Is there a third approach perhaps?

@jeddy3
Copy link
Copy Markdown
Member Author

jeddy3 commented Mar 31, 2026

I've pushed a commit to rename to reference.

@jeddy3 jeddy3 changed the title Add experimental semanticFiles to configuration object Add experimental referenceFiles to configuration object Mar 31, 2026
@ybiquitous
Copy link
Copy Markdown
Member

Got it. Given the cases I missed, being explicit with customSyntax in referenceFiles seems preferable, even if redundant customSyntax settings may arise.

If we don't have a third approach, let's keep the original idea as-is. We can revisit it later, as the feature is still experimental. 👍🏼

Comment thread docs/contributor-guide/rules.md Outdated
Comment thread docs/user-guide/configure.md
Comment thread lib/__tests__/referenceFiles.test.mjs Outdated
Comment thread types/stylelint/index.d.ts
Comment thread lib/augmentConfig.mjs
jeddy3 and others added 11 commits April 3, 2026 18:36
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 Author

jeddy3 commented Apr 3, 2026

@ybiquitous Those were all fantastic review suggestions, thank you.

I've pushed commits for all of 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 for addressing my reviews! LGTM 👍🏼

I've left one more suggestion, but it's probably minor.


In follow-up PRs, we should add test cases with referenceFiles for updated rules such as no-unknown-animations.

To achieve it, we have to add a new referenceFiles option before updating the tests, like languageOptions:
https://github.com/stylelint/jest-preset-stylelint/blob/b813dd8380d5e1c0fa09b608e2d685d2cca98d03/getTestRule.js#L34

Comment thread lib/utils/getReferenceRoots.mjs Outdated
Comment thread lib/utils/getReferenceRoots.mjs Outdated
jeddy3 and others added 2 commits April 4, 2026 07:04
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
Copy link
Copy Markdown
Member

@romainmenke romainmenke left a comment

Choose a reason for hiding this comment

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

One question, but I don't think it is blocking as everything seems to work as intended :)

Really nice work on this feature 🙇

Comment thread lib/utils/getReferenceRoots.mjs Outdated
@jeddy3 jeddy3 merged commit 23d8e99 into main Apr 15, 2026
18 of 19 checks passed
@jeddy3 jeddy3 deleted the add-semantic branch April 15, 2026 13:27
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 resolver to configuration

3 participants