Got CSS combinator prefixes working

Excluding CSS type element selectors

closes #9320
closes #8587
pull/9549/head
Albert Marashi 3 years ago
parent b59387b046
commit fcdc02e51b

@ -100,7 +100,7 @@ Test samples are kept in `/test/xxx/samples` folder.
> PREREQUISITE: Install chromium via playwright by running `pnpm playwright install chromium`
1. To run test, run `pnpm test`.
1. To run test for a specific feature, you can use the `-g` (aka `--grep`) option. For example, to only run test involving transitions, run `pnpm test -- -g transition`.
1. To run test for a specific feature, you can use the `-t` (aka `--testNamePattern `) option. For example, to only run test involving transitions, run `pnpm test -- -t transistion`.
##### Running solo test

@ -395,14 +395,21 @@ function read_declaration(parser) {
* @returns {import('#compiler').Css.Declaration | import('#compiler').Css.Rule}
*/
function read_declaration_or_rule(parser) {
// We will only allow css nesting using & selector for now
// We need to know if this is a rule or a declaration
// so we'll attempt to read an identifier first
// if we can't, we'll assume it's a rule
// This needs to change when we support type (element) selectors
// due to complexities with https://bugs.chromium.org/p/chromium/issues/detail?id=1427259
// as most browsers as of 17/11/2023 do not support nesting without & selector
if (parser.match('&')) {
return read_rule(parser, true)
} else {
return read_declaration(parser);
const start = parser.index;
const is_ident = !!parser.read(REGEX_VALID_IDENTIFIER_CHAR);
parser.index = start;
if (!is_ident) {
return read_rule(parser, true);
}
return read_declaration(parser);
}
/**

@ -321,6 +321,16 @@ function block_might_apply_to_node(block, node) {
return NO_MATCH;
}
if (
block.nested &&
block.selectors.length === 1 &&
block.combinator !== null
) {
// nested selector with combinator, eg: `.foo { + .bar { ... } }`
// TODO: How to handle this?
return UNKNOWN_SELECTOR;
}
if (selector.type === 'PseudoClassSelector' || selector.type === 'PseudoElementSelector') {
continue;
}
@ -831,14 +841,17 @@ class Block {
/**
* Groups selectors by combinator into blocks
* @param {import('#compiler').Css.Selector} selector
* */
*/
function group_selectors(selector) {
let block = new Block(null);
const blocks = [block];
for (const child of selector.children) {
if (child.type === 'Combinator') {
if (block.nested && !block.combinator) {
// If we start with a combinator, that means
// we're dealing with a nested selector
if(block.selectors.length === 0 && !block.combinator) {
block.nested = true;
block.combinator = child;
} else {
block = new Block(child);

@ -0,0 +1,9 @@
button.svelte-xyz {
color: red;
+ .abc.svelte-xyz {
color: purple;
}
color: black;
}

@ -0,0 +1,17 @@
<button>
<div class="foo"/>
</button>
<div class="abc">
</div>
<style>
button {
color: red;
+ .abc {
color: purple;
}
color: black;
}
</style>

@ -0,0 +1,9 @@
button.svelte-xyz {
color: red;
> .abc.svelte-xyz {
color: purple;
}
color: black;
}

@ -0,0 +1,17 @@
<button>
<div class="abc"/>
<div class="bar">
<div class="abc"/>
</div>
</button>
<style>
button {
color: red;
> .abc {
color: purple;
}
color: black;
}
</style>

@ -0,0 +1,9 @@
button.svelte-xyz {
color: red;
.hello.svelte-xyz {
color: pink;
}
color: black;
}

@ -0,0 +1,16 @@
<button>
<div class="bar">
<div class="hello"/>
</div>
</button>
<style>
button {
color: red;
.hello {
color: pink;
}
color: black;
}
</style>

@ -1,5 +1,7 @@
div.svelte-xyz {
@apply --funky-div;
/* DISABLED THIS FOR CSS NESTING */
/* @apply --funky-div; */
color: red;
}
/* (empty) div.svelte-xyz {

@ -2,7 +2,9 @@
<style>
div {
@apply --funky-div;
/* DISABLED THIS FOR CSS NESTING */
/* @apply --funky-div; */
color: red;
}
div {

@ -1,3 +1,5 @@
div.svelte-xyz {
@apply --funky-div;
/* DISABLED THIS FOR CSS NESTING */
/* @apply --funky-div; */
color: red;
}

@ -2,6 +2,8 @@
<style>
div {
@apply --funky-div;
/* DISABLED THIS FOR CSS NESTING */
/* @apply --funky-div; */
color: red;
}
</style>
Loading…
Cancel
Save