Skip to content

feat: Validate property values containing variables #148

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jun 10, 2025
Merged

Conversation

nzakas
Copy link
Member

@nzakas nzakas commented May 22, 2025

Prerequisites checklist

What is the purpose of this pull request?

To enable validation of CSS property values containing var(). Previously, we just skipped validating these completely. For this to work, the custom property must be defined before it's used, such as:

:root {
  --color: red
}

a {
    color: var(--color);
}

If a custom property is not defined before it's used, a lint violation is reported.

What changes did you make? (Give an overview)

  • Updated no-invalid-properties to track custom property values and use them as replacements for the value that is validated
  • Added tests for these changes
  • Updated the docs to indicate how var() is validated

Related Issues

Is there anything you'd like reviewers to focus on?

The highlighted section of code for a violation is different when there is a var() vs. when there isn't.

  • When there isn't a var() (as in HEAD), the individual incorrect value is highlighted. So for border-top: 1px solid foo, it's foo that is indicated in the location information.
  • When there is a var():
    • If the var() is the violation, then it's location is highlighted and the replacement value is reported in the message.
    • If any other part of the value is the violation, then the entire value is highlighted. This is because I couldn't figure out an efficient way to track the calculated location after variable replacement. The message still contains the exact part of the value that is the problem.

@github-project-automation github-project-automation bot moved this to Needs Triage in Triage May 22, 2025
@nzakas nzakas requested a review from Copilot May 22, 2025 21:02
@nzakas nzakas changed the title feat: Validation property values containing variables feat: Validate property values containing variables May 22, 2025
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Enables validation of CSS property values that use var() by tracking custom property definitions and replacing variables before validation.

  • Tracks var() function calls per declaration and substitutes known custom property values for validation.
  • Reports errors for unknown variables (unknownVar) and invalid substituted values (invalidPropertyValue).
  • Adds tests and updates documentation to describe variable validation behavior.

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
tests/rules/no-invalid-properties.test.js Added valid and invalid test cases covering custom property usage
src/rules/no-invalid-properties.js Implemented var() tracking, replacement logic, and new error type
docs/rules/no-invalid-properties.md Updated limitations section to explain var() validation behavior
Comments suppressed due to low confidence (2)

src/rules/no-invalid-properties.js:17

  • JSDoc tags use '@import' which is non-standard; consider using '@typedef {import("../types.js").CSSRuleDefinition}' or the equivalent JSDoc import syntax for proper type declarations.
* @import { CSSRuleDefinition } from "../types.js"

src/rules/no-invalid-properties.js:143

  • [nitpick] Using var as a data property key can be confusing since it's a reserved term; consider renaming it to varName or customProperty for clarity.
data: { var: name },

@nzakas nzakas marked this pull request as draft May 23, 2025 18:32
@nzakas nzakas requested a review from Copilot May 23, 2025 18:41
@nzakas nzakas marked this pull request as ready for review May 23, 2025 18:42
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This pull request enables validation of CSS property values that include variable references through var(), ensuring that defined custom properties are used correctly.

  • Introduces variable tracking and replacement in the no-invalid-properties rule
  • Adds comprehensive tests covering various cases with var() usages
  • Updates documentation to clarify the behavior when custom properties are defined or missing

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
tests/rules/no-invalid-properties.test.js Adds test cases for validating both defined and undefined var() usage
src/rules/no-invalid-properties.js Implements custom property tracking and replacement logic for var() in declarations
docs/rules/no-invalid-properties.md Updates documentation to explain how var() validation is handled
Comments suppressed due to low confidence (1)

src/rules/no-invalid-properties.js:143

  • Instead of returning immediately after encountering an unknown variable, consider reporting all unknown variable errors in the block to provide comprehensive feedback.
context.report({ loc: func.children[0].loc, messageId: "unknownVar", data: { var: name }, });

@lumirlumir lumirlumir added the accepted There is consensus among the team that this change meets the criteria for inclusion label May 26, 2025
@snitin315
Copy link
Contributor

We have one false positive when we have spaces inside var():

/* eslint css/no-invalid-properties: error */

:root {
    --color: red
}

a {
    color: var(  --color ); // Unknown property 'color' found  css/no-invalid-properties
}

Co-authored-by: Nitin Kumar <snitin315@gmail.com>
@nzakas
Copy link
Member Author

nzakas commented May 28, 2025

@snitin315 nice find! I'll take a look.

@nzakas nzakas moved this from Needs Triage to Implementing in Triage May 28, 2025
snitin315
snitin315 previously approved these changes May 31, 2025
Copy link
Contributor

@snitin315 snitin315 left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

Leaving it open for the second review.

@nzakas
Copy link
Member Author

nzakas commented Jun 5, 2025

@eslint/eslint-tsc can one of you take a look at this?

@nzakas nzakas moved this from Implementing to Second Review Needed in Triage Jun 5, 2025
Comment on lines +170 to +179
/*
* When using variables, check to see if the error
* occurred at a location where a variable was replaced.
* If so, use that location; otherwise, use the error's
* reported location.
*/
loc: usingVars
? (varsFoundLocs.get(error.mismatchOffset) ??
node.value.loc)
: error.loc,
Copy link
Member

Choose a reason for hiding this comment

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

I think this doesn't quite work as expected when there are multiple replacements. For example:

a { --width: 1px; border-top: var(--width) solid var(--width); }

I can see that in this case the SyntaxError has a mismatchOffset of 10, i.e. the offset of the second var(--width) after the replacements were applied, but varsFoundLocs contains the offsets of the variables before the replacement. Thus there is no match and the rule reports the error's original location.

I think this can be fixed by ensuring that replaceWithOffsets returns the offsets of the replaced locations in the output text, rather than in the original string.

Copy link
Member Author

Choose a reason for hiding this comment

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

Just to make sure I understand what you're saying -- you're saying that when there's a second var() that contains an incorrect value the reported location is not the location of that var()?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think I got it. 👍

Copy link
Member

@fasttime fasttime left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@fasttime fasttime merged commit 9fb07fa into main Jun 10, 2025
22 checks passed
@fasttime fasttime deleted the var-validation branch June 10, 2025 14:02
@github-project-automation github-project-automation bot moved this from Second Review Needed to Complete in Triage Jun 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted There is consensus among the team that this change meets the criteria for inclusion feature
Projects
Status: Complete
Development

Successfully merging this pull request may close these issues.

4 participants