This document outlines the concept of a Semantic Model for CSS.
In Biome, a semantic model is a data structure that stores information such as scope, variable references, and global references. This model processes SyntaxNode
data generated from code parsing.
We have already implemented this model for JavaScript.
Warning
This is still an idea and requires a feasibility check.
The primary use case will likely be as a linter. The model tracks invalid CSS and is utilized by some lint rules via Semantic or SemanticService.
The model stores semantic information about selectors, properties.. and more, then those are utilized by some lint rules via Semantic or SemanticService.
Here are examples of what it can track:
Here are some examples of what rules can do using a model:
We need to consider the appropriate data structures for storing this information and how we will access them.
// For https://stylelint.io/user-guide/rules/declaration-block-no-duplicate-custom-properties/
impl Rule for SampleRule {
type Query = CssSemanticServices;
type State = RuleState;
type Signals = Vec<()>;
type Options = ();
fn run(ctx: &RuleContext<Self>) -> Self::Signals {
let duplicated_custom_properties = ctx.query().all_duplicated_custom_properties();
// ....
}
}
// For https://stylelint.io/user-guide/rules/custom-property-no-missing-var-function/
impl Rule for SampleRule {
type Query = Semantic<CssDashedIdentifier>;
type State = RuleState;
type Signals = Vec<()>;
type Options = ();
fn run(ctx: &RuleContext<Self>) -> Self::Signals {
let node = ctx.query();
let is_missed_var_func = true;
let at_properties = ctx.model().at_properties();
if at_properties.empty() && is_missed_var_func {
return node;
}
// ....
}
}
In many cases, CSS variables are defined in a :root
selector for global styles and referenced from other files, as shown below:
// global.css
:root {
--custom-color: #FFFFF
}
/* main.css */
a {
color: var(--costom-color)
}
The model can't analyze across multiple files because it only focuses on a single file. Therefore, we can't implement the noUnresolvedReference
rule for CSS variables at this stage. To achieve this, we need to implement multi-file support.
The model does not have access to HTML or the DOM, so it can't interpret the use of CSS in these contexts. For example, it can't handle cases like the one below:
// index.html
<body>
<div>Div 1</div>
<div>Div 2</div>
</body>
/* main.css */
body {
--bgColor: limegreen;
}
div {
background: var(--bgColor); // This works even though the variable is not declared in this selector's scope because div is a child of body.
}
Feel free to share your thought and idea about the model:)
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too