pub fn scope_css(css: &str, scope_id: &str) -> StringExpand description
Rewrite a CSS stylesheet so every selector compound carries the scope attribute, preserving combinators between compounds:
.header h1 { ... } -> .header[data-v-x] h1[data-v-x] { ... }
div > .card { ... } -> div[data-v-x] > .card[data-v-x] { ... }
h1, .a { ... } -> h1[data-v-x], .a[data-v-x] { ... }Declaration blocks are copied verbatim. @keyframes blocks keep their
inner keyframe selectors (from/to/percent offsets) unscoped, while
@media preludes pass through and only their inner style-rule selectors
are scoped. Appending the attribute to every compound confines the rule to
elements that all belong to this component — every element rendered from
this component’s template is tagged with the same data-v-* attribute, so
a rule like .header h1[data-v-*] could otherwise leak across component
boundaries via an un-tagged ancestor.
CSS comments are replaced by a space before anything else happens (see
[strip_css_comments]). Without that, a comment between two rules is glued
onto the front of the next rule’s prelude, and the per-compound tokenizer
then appends the scope attribute to the comment’s own */ as though it were
a compound selector: .dark .app was emitted as
[data-v-x] .dark[data-v-x] .app[data-v-x], a three-part descendant
selector requiring a scope-tagged ancestor strictly above the .dark
carrier. The carrier is the tree root, whose ancestor list is empty, so
match_prefix finds no candidate and the rule can never match.