Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pull childless @layer rules to the top of the output stylesheet #3843

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 38 additions & 9 deletions spec/at-rules/extend.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ many interacting layers and a lot of intricate case analysis.
* [Extension](#extension)
* [Extendee](#extendee)
* [The `extend()` Function](#the-extend-function)
* [Initial Rule](#initial-rule)
* [Semantics](#semantics)
* [Executing an `@extend` Rule](#executing-an-extend-rule)
* [Resolving a Module's Extensions](#resolving-a-modules-extensions)
Expand Down Expand Up @@ -86,6 +87,11 @@ shorthands:
* `extend(extendee, extensions)` for iteratively running `extendee =
extend(extendee, extension)` for each `extension` in `extensions`.

### Initial Rule

An "initial rule" is a CSS at-rule that is either an `@import` or a `@layer`
rule with no children.

## Semantics

The `@extend` rule means that all elements matching the [extender](#extender)
Expand Down Expand Up @@ -208,26 +214,49 @@ that includes CSS for *all* modules transitively used or forwarded by
> Because this traverses modules depth-first, it emits CSS in reverse
> topological order.

* Let `initial-imports` be the longest initial subsequence of top-level
statements in `domestic`'s CSS tree that contains only comments and
`@import` rules *and* that ends with an `@import` rule.
* Let `initial` be the longest initial subsequence of top-level statements in
`domestic`'s CSS tree that contains only comments and [initial rules], *and*
that ends with an initial rule.

* If `initial` contains a `@layer` rule `layer`:

* If `css` already contains a `@layer` rule without children, throw an
error.

* Otherwise, if `layer` is preceded only by comments, remove those comment
and `layer` from `initial` and insert a copy of them at the beginning of
`css` after any existing comments.

* Insert a copy of `initial-imports` in `css` after the last `@import` rule, or
at the beginning of `css` if it doesn't contain any `@import` rules.
* Otherwise, remove `layer` from `initial` and insert a copy of it at the
beginning of `css` after any comments.

* Insert a copy of `initial` in `css` after the last initial rule, or at the
beginning of `css` after any comments if it doesn't contain any initial
rules.

* For each top-level statement `statement` in `domestic`'s CSS tree after
`initial-imports`:
`initial`:

* If `statement` is a `@layer` rule without children:

* If `css` already contains a `@layer` rule without children, throw an
error.

* If `statement` is an `@import` rule, insert a copy of `statement` in `css`
after the last `@import` rule, or at the beginning of `css` if it doesn't
contain any `@import` rules.
* Otherwise, insert a copy of `statement` at the beginning of `css` after
any comments.

* Otherwise, If `statement` is an `@import` rule, insert a copy of
`statement` in `css` after the last initial rule, or at the beginning of
`css` after any comments if it doesn't contain any initial rules.

* Otherwise, add a copy of `statement` to the end of `css`, with any style
rules' selectors replaced with the corresponding selectors in
`new-selectors`.

* Return `css`.

[initial rules]: #initial-rule

### Extending a Selector

This algorithm takes a selector list `extendee`, a simple selector `target`, and
Expand Down