diff --git a/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js b/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js index b58672dd65..97efe0015a 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js +++ b/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js @@ -78,18 +78,6 @@ function apply_selector(relative_selectors, element, stylesheet) { return false; } - /** - * Mark both the compound selector and the node it selects as encapsulated, - * for transformation in a later step - * @param {import('#compiler').Css.RelativeSelector} relative_selector - * @param {import('#compiler').RegularElement | import('#compiler').SvelteElement} element - */ - function mark(relative_selector, element) { - relative_selector.metadata.scoped = true; - element.metadata.scoped = true; - return true; - } - if (applies === UNKNOWN_SELECTOR) { return mark(relative_selector, element); } @@ -186,6 +174,18 @@ function apply_selector(relative_selectors, element, stylesheet) { return mark(relative_selector, element); } +/** + * Mark both the compound selector and the node it selects as encapsulated, + * for transformation in a later step + * @param {import('#compiler').Css.RelativeSelector} relative_selector + * @param {import('#compiler').RegularElement | import('#compiler').SvelteElement} element + */ +function mark(relative_selector, element) { + relative_selector.metadata.scoped = true; + element.metadata.scoped = true; + return true; +} + const regex_backslash_and_following_character = /\\(.)/g; /** diff --git a/packages/svelte/src/compiler/phases/3-transform/css/index.js b/packages/svelte/src/compiler/phases/3-transform/css/index.js index 40f9776006..40b171b9f7 100644 --- a/packages/svelte/src/compiler/phases/3-transform/css/index.js +++ b/packages/svelte/src/compiler/phases/3-transform/css/index.js @@ -122,12 +122,17 @@ const visitors = { return; } - if (used.length < node.prelude.children.length) { + next(); + }, + SelectorList(node, { state, next }) { + const used = node.children.filter((s) => s.metadata.used); + + if (used.length < node.children.length) { let pruning = false; - let last = node.prelude.children[0].start; + let last = node.children[0].start; - for (let i = 0; i < node.prelude.children.length; i += 1) { - const selector = node.prelude.children[i]; + for (let i = 0; i < node.children.length; i += 1) { + const selector = node.children[i]; if (selector.metadata.used === pruning) { if (pruning) { @@ -172,6 +177,17 @@ const visitors = { } if (relative_selector.metadata.scoped) { + if (relative_selector.selectors.length === 1) { + // skip standalone :is/:where + const selector = relative_selector.selectors[0]; + if ( + selector.type === 'PseudoClassSelector' && + (selector.name === 'is' || selector.name === 'where') + ) { + continue; + } + } + // for the first occurrence, we use a classname selector, so that every // encapsulated selector gets a +0-1-0 specificity bump. thereafter, // we use a `:where` selector, which does not affect specificity @@ -214,6 +230,11 @@ const visitors = { } context.next(); + }, + PseudoClassSelector(node, context) { + if (node.name === 'is' || node.name === 'where') { + context.next(); + } } };