Skip to content

Commit be53018

Browse files
authored
feat: Add a lint for unsupported CSS Module selector (parcel-bundler#784)
1 parent 3e62347 commit be53018

File tree

4 files changed

+41
-0
lines changed

4 files changed

+41
-0
lines changed

selectors/parser.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ pub enum SelectorParseErrorKind<'i> {
198198
UnexpectedTokenInAttributeSelector(Token<'i>),
199199
PseudoElementExpectedIdent(Token<'i>),
200200
UnsupportedPseudoClassOrElement(CowRcStr<'i>),
201+
AmbiguousCssModuleClass(CowRcStr<'i>),
201202
UnexpectedIdent(CowRcStr<'i>),
202203
ExpectedNamespace(CowRcStr<'i>),
203204
ExpectedBarInAttr(Token<'i>),

src/error.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ pub enum SelectorError<'i> {
232232
),
233233
/// An unsupported pseudo class or pseudo element was encountered.
234234
UnsupportedPseudoClassOrElement(CowArcStr<'i>),
235+
236+
/// Ambiguous CSS module class.
237+
AmbiguousCssModuleClass(CowArcStr<'i>),
235238
}
236239

237240
impl<'i> fmt::Display for SelectorError<'i> {
@@ -257,6 +260,7 @@ impl<'i> fmt::Display for SelectorError<'i> {
257260
UnexpectedIdent(name) => write!(f, "Unexpected identifier: {}", name),
258261
UnexpectedTokenInAttributeSelector(token) => write!(f, "Unexpected token in attribute selector: {:?}", token),
259262
UnsupportedPseudoClassOrElement(name) => write!(f, "Unsupported pseudo class or element: {}", name),
263+
AmbiguousCssModuleClass(_) => write!(f, "Ambiguous CSS module class not supported"),
260264
}
261265
}
262266
}
@@ -297,6 +301,7 @@ impl<'i> From<SelectorParseErrorKind<'i>> for SelectorError<'i> {
297301
SelectorError::ExplicitNamespaceUnexpectedToken(t.into())
298302
}
299303
SelectorParseErrorKind::ClassNeedsIdent(t) => SelectorError::ClassNeedsIdent(t.into()),
304+
SelectorParseErrorKind::AmbiguousCssModuleClass(name) => SelectorError::AmbiguousCssModuleClass(name.into()),
300305
}
301306
}
302307
}

src/selector.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,10 @@ impl<'a, 'o, 'i> parcel_selectors::parser::Parser<'i> for SelectorParser<'a, 'o,
190190
"corner-present" => WebKitScrollbar(WebKitScrollbarPseudoClass::CornerPresent),
191191
"window-inactive" => WebKitScrollbar(WebKitScrollbarPseudoClass::WindowInactive),
192192

193+
"local" | "global" if self.options.css_modules.is_some() => {
194+
return Err(loc.new_custom_error(SelectorParseErrorKind::AmbiguousCssModuleClass(name.clone())))
195+
},
196+
193197
_ => {
194198
if !name.starts_with('-') {
195199
self.options.warn(loc.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name.clone())));

tests/cli_integration_tests.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,37 @@ fn css_modules_pattern() -> Result<(), Box<dyn std::error::Error>> {
389389
Ok(())
390390
}
391391

392+
#[test]
393+
fn css_modules_next_64299() -> Result<(), Box<dyn std::error::Error>> {
394+
let file = assert_fs::NamedTempFile::new("test.css")?;
395+
file.write_str(
396+
"
397+
.blue {
398+
background: blue;
399+
400+
:global {
401+
.red {
402+
background: red;
403+
}
404+
}
405+
406+
&:global {
407+
&.green {
408+
background: green;
409+
}
410+
}
411+
}
412+
",
413+
)?;
414+
415+
let mut cmd = Command::cargo_bin("lightningcss")?;
416+
cmd.arg(file.path());
417+
cmd.arg("--css-modules");
418+
cmd.assert().failure();
419+
420+
Ok(())
421+
}
422+
392423
#[test]
393424
fn sourcemap() -> Result<(), Box<dyn std::error::Error>> {
394425
let (input, _, _) = css_module_test_vals();

0 commit comments

Comments
 (0)