mirror of
https://github.com/sass/sass.git
synced 2024-09-21 10:37:22 +00:00
Add a "Resolving Extends" section.
This commit is contained in:
parent
a4e6690afa
commit
d20ae8030b
56
README.md
56
README.md
@ -336,3 +336,59 @@ The downside to hyphens are that they look like normal identifiers, which makes
|
|||||||
it less locally clear what's a namespace and what's a normal member name. It
|
it less locally clear what's a namespace and what's a normal member name. It
|
||||||
also allows module prefixes to shadow other members, and introduces the
|
also allows module prefixes to shadow other members, and introduces the
|
||||||
possibility of conflicting prefixes between modules.
|
possibility of conflicting prefixes between modules.
|
||||||
|
|
||||||
|
### Resolving Extends
|
||||||
|
|
||||||
|
The module system also scopes the resolution of the `@extend` directive. This
|
||||||
|
helps satisfy locality, making selector extension more predictable than it is
|
||||||
|
using `@import`s.
|
||||||
|
|
||||||
|
Extension is scoped to CSS in [module](#module)s *transitively used* by the
|
||||||
|
module in which the `@extend` appears. This transitivity is necessary because
|
||||||
|
CSS is not considered a [member](#member) of a module, and can't be controlled
|
||||||
|
as explicitly as members can. Extending all transitively-used modules means that
|
||||||
|
the `@extend` affects exactly that CSS that is guaranteed to exist by the `@use`
|
||||||
|
directives.
|
||||||
|
|
||||||
|
Specifically, once all modules have been loaded, do a global pass to resolve the
|
||||||
|
extends.
|
||||||
|
|
||||||
|
* For each module that contains CSS (call it the *extended module*):
|
||||||
|
|
||||||
|
* Set this module's *virtual selectors* to the set of selectors in all of its
|
||||||
|
CSS rules. These virtual selectors remember the original selector they were
|
||||||
|
generated from.
|
||||||
|
|
||||||
|
* Take the subgraph of the module graph that can transitively reach the
|
||||||
|
extended module.
|
||||||
|
|
||||||
|
* For every module in this subgraph (call it the *extending module*) in
|
||||||
|
reverse [topological][] order:
|
||||||
|
|
||||||
|
* For each of the extended module's selectors:
|
||||||
|
|
||||||
|
* Take the corresponding virtual selector from each module used by the
|
||||||
|
extending module, if it has such a selector set.
|
||||||
|
|
||||||
|
* Create a new selector that matches the union of all elements matched by
|
||||||
|
these virtual selectors, and set it as a virtual selector of this
|
||||||
|
subgraph.
|
||||||
|
|
||||||
|
* Replace the selectors in the extended module's rules with the corresponding
|
||||||
|
virtual selectors of the [entrypoint module](#entrypoint-module).
|
||||||
|
|
||||||
|
[topological]: https://en.wikipedia.org/wiki/Topological_sorting
|
||||||
|
|
||||||
|
> **Implementation note:**
|
||||||
|
>
|
||||||
|
> This process as written is O(n²) for the number of modules in the compilation,
|
||||||
|
> and in a pathological case this is accurate. However, it's intended to be
|
||||||
|
> tightly constrained by the number and scope of the extensions the user chooses
|
||||||
|
> to write. Even a relatively naïve implementation should be able to keep it to
|
||||||
|
> O(n×m) for extending modules and extended modules. It's possible there's even
|
||||||
|
> an O(n) implementation that integrates extension with compilation, but that's
|
||||||
|
> beyond the scope of this document.
|
||||||
|
|
||||||
|
There is intentionally no way for a module to affect the extensions of another
|
||||||
|
module that doesn't transitively use it. This promotes locality, and matches the
|
||||||
|
behavior of mixins and functions in that monkey-patching is disallowed.
|
||||||
|
Loading…
Reference in New Issue
Block a user