mirror of https://github.com/sveltejs/svelte
The other part of #13395 This implements scoping for selectors inside `:not(...)`. The approach is almot the same as for `:is/where(...)`. This is a breaking change because people could've used `:not(.unknown)` with `.unknown` not appearing in the HTML, and so they need to do `:not(:global(.unknown))` instead. While implementing it I also discovered a few bugs, which are fixed in this PR: - `foo :is(bar baz)` wasn't properly handled. This selector can mean `foo bar baz` but it can also mean `bar foo baz` (super weird, but it is what it is). Since our current algorithm isn't suited for handling this, we just assume it matches and scope it. Worst case is we missed a prune - `bar` in `:global(foo):is(bar)` was always marked as unused, even if it matchedscope-not
parent
3d436d6916
commit
7383239c88
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
breaking: scope `:not(...)` selectors
|
@ -1,4 +1,34 @@
|
||||
|
||||
x.svelte-xyz :is(y:where(.svelte-xyz) /* (unused) z*/) {
|
||||
color: purple;
|
||||
x.svelte-xyz :is(y:where(.svelte-xyz)) {
|
||||
color: green;
|
||||
}
|
||||
x.svelte-xyz :is(y:where(.svelte-xyz) /* (unused) .unused*/) {
|
||||
color: green;
|
||||
}
|
||||
/* (unused) x :is(.unused) {
|
||||
color: red;
|
||||
}*/
|
||||
|
||||
x.svelte-xyz :is(y) {
|
||||
color: green;
|
||||
}
|
||||
x.svelte-xyz :is(.foo) {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.foo :is(x.svelte-xyz) {
|
||||
color: green;
|
||||
}
|
||||
/* (unused) :global(.foo) :is(.unused) {
|
||||
color: red;
|
||||
}*/
|
||||
|
||||
x.svelte-xyz :is(html *) {
|
||||
color: green;
|
||||
}
|
||||
x.svelte-xyz :is(html:where(.svelte-xyz) :where(.svelte-xyz)) {
|
||||
color: red; /* TODO would be nice to prune this one day */
|
||||
}
|
||||
y.svelte-xyz :is(x:where(.svelte-xyz) :where(.svelte-xyz)) {
|
||||
color: green; /* matches z */
|
||||
}
|
||||
|
@ -1,9 +1,41 @@
|
||||
<x>
|
||||
<y></y>
|
||||
<y>
|
||||
<z></z>
|
||||
</y>
|
||||
</x>
|
||||
|
||||
<style>
|
||||
x :is(y, z) {
|
||||
color: purple;
|
||||
x :is(y) {
|
||||
color: green;
|
||||
}
|
||||
x :is(y, .unused) {
|
||||
color: green;
|
||||
}
|
||||
x :is(.unused) {
|
||||
color: red;
|
||||
}
|
||||
|
||||
x :is(:global(y)) {
|
||||
color: green;
|
||||
}
|
||||
x :is(:global(.foo)) {
|
||||
color: green;
|
||||
}
|
||||
|
||||
:global(.foo) :is(x) {
|
||||
color: green;
|
||||
}
|
||||
:global(.foo) :is(.unused) {
|
||||
color: red;
|
||||
}
|
||||
|
||||
x :is(:global(html *)) {
|
||||
color: green;
|
||||
}
|
||||
x :is(html *) {
|
||||
color: red; /* TODO would be nice to prune this one day */
|
||||
}
|
||||
y :is(x *) {
|
||||
color: green; /* matches z */
|
||||
}
|
||||
</style>
|
||||
|
@ -0,0 +1,62 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
warnings: [
|
||||
{
|
||||
code: 'css_unused_selector',
|
||||
message: 'Unused CSS selector ":not(.unused)"',
|
||||
start: {
|
||||
line: 8,
|
||||
column: 1,
|
||||
character: 89
|
||||
},
|
||||
end: {
|
||||
line: 8,
|
||||
column: 14,
|
||||
character: 102
|
||||
}
|
||||
},
|
||||
{
|
||||
code: 'css_unused_selector',
|
||||
message: 'Unused CSS selector ":not(.foo):not(.unused)"',
|
||||
start: {
|
||||
line: 18,
|
||||
column: 1,
|
||||
character: 221
|
||||
},
|
||||
end: {
|
||||
line: 18,
|
||||
column: 24,
|
||||
character: 244
|
||||
}
|
||||
},
|
||||
{
|
||||
code: 'css_unused_selector',
|
||||
message: 'Unused CSS selector "p :not(.foo)"',
|
||||
start: {
|
||||
line: 25,
|
||||
column: 1,
|
||||
character: 300
|
||||
},
|
||||
end: {
|
||||
line: 25,
|
||||
column: 13,
|
||||
character: 312
|
||||
}
|
||||
},
|
||||
{
|
||||
code: 'css_unused_selector',
|
||||
message: 'Unused CSS selector ":global(.x) :not(.unused)"',
|
||||
start: {
|
||||
line: 34,
|
||||
column: 1,
|
||||
character: 469
|
||||
},
|
||||
end: {
|
||||
line: 34,
|
||||
column: 26,
|
||||
character: 494
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
@ -1,3 +1,33 @@
|
||||
|
||||
.svelte-xyz:not(.foo:where(.svelte-xyz)) {
|
||||
color: green;
|
||||
}
|
||||
/* (unused) :not(.unused) {
|
||||
color: red;
|
||||
}*/
|
||||
.svelte-xyz:not(.foo) {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.svelte-xyz:not(.foo:where(.svelte-xyz)):not(.unused) {
|
||||
color: green;
|
||||
}
|
||||
/* (unused) :not(.foo):not(.unused) {
|
||||
color: red;
|
||||
}*/
|
||||
|
||||
p.svelte-xyz:not(.foo:where(.svelte-xyz)) {
|
||||
color: green;
|
||||
}
|
||||
/* (unused) p :not(.foo) {
|
||||
color: red;
|
||||
}*/
|
||||
.x:not(.foo.svelte-xyz) {
|
||||
color: green;
|
||||
}
|
||||
.x:not(.unused.svelte-xyz) {
|
||||
color: red; /* TODO would be nice to prune this one day */
|
||||
}
|
||||
/* (unused) :global(.x) :not(.unused) {
|
||||
color: red;
|
||||
}*/
|
||||
|
Loading…
Reference in new issue