A member is a Sass construct that's defined either by the user or the implementation and is identified by a Sass identifier. This currently includes variables, mixins, and functions (but not placeholder selectors). All members have definitions associated with them, whose specific structure depends on the type of the given member.
Two members are considered identical if they have the same name, type, source location, and were defined in or forwarded from the same original module.
Each member type has its own namespace in Sass, so for example the mixin
namedoesn't conflict with the functionnameor the variable$name.
A CSS tree is an abstract CSS syntax tree. It has multiple top-level CSS statements like at-rules or style rules. The ordering of these statements is significant. A CSS tree cannot contain any Sass-specific constructs, with the notable exception of placeholder selectors.
An empty CSS tree contains no statements.
A configuration is a map from variable names to SassScript values. An empty configuration contains no entries.
A module is a collection of various properties:
-
A set of members that contains at most one member of any given type and name.
For example, a module may not have two variables named
$name, although it may contain a function and a mixin with the same name or two functions with different names.The names (and mixin and function signatures) of a module's members are static, and can be determined without executing its associated source file. This means that any possible module for a given source file has the same member names and signatures regardless of the context in which those modules are loaded.
-
A set of extensions.
-
A CSS tree.
This tree is empty for built-in modules and user-defined modules that only define variables, functions, and mixins without including any plain CSS rules.
-
A list of references to other modules, known as the module's dependencies, in the same order as their
@userules and/or@forwardrules appear in the module's source file. If a dependency is referred to from multiple rules, its order is determined by the first such rule.Modules without a source file never have dependencies. Each dependency is guaranteed to correspond to at least one
@userule or@forwardrule. -
An optional source file.
Note that built-in modules do not have source files associated with them.
-
An absolute URL, known as the module's canonical URL. If the module has a source file, this must be the same as the source file's canonical URL.
Once a user-defined module has been returned by Executing a File, it is immutable except for its variable values. Built-in modules are always immutable.
The set of modules loaded in the course of processing a stylesheet
can be construed as a directed acyclic graph where the vertices are modules
and the edges are @use rules and/or @forward rules. We call this the
module graph.
The module graph is not allowed to contain cycles because they make it impossible to guarantee that all dependencies of a module are available before that module is loaded. Although the names and APIs of a dependency's members can be determined without executing it, Sass allows code to be executed during load, so those members may not behave correctly when invoked before the dependency is executed.
An import context is a set of members that contains at most one member of any given type and name. It's always mutable.
Import contexts serve as glue between the old
@importrule and the module system. It serves as a shared global namespace for stylesheets loaded using@importrules, while also preventing global names from leaking into or out of stylesheets loaded using@userules and/or@forwardrules.
A built-in module is a module defined either by the Sass specification or by
the host environment of the Sass compilation in some implementation-specific
way. Modules defined by the Sass specification all have the scheme sass: and
are all described in the built_in_modules directory. Modules defined
outside the Sass compilation may not use the scheme sass:.
Built-in modules may contain mixins, variables, or functions, but they may never contain CSS or extensions.
The basename of a URL is the final component of that URL's path.
The dirname of a URL is the prefix of that URL up to, but not including, the beginning of its basename.
The module system defines the following syntax for referring to names from other modules:
PublicIdentifier ::= <ident-token> that doesn't begin with '-' or '_' NamespacedIdentifier ::= Identifier | Identifier '.' PublicIdentifier
No whitespace is allowed before or after the '.' in NamespacedIdentifier.
This algorithm takes a string argument and configuration
config and returns a module:
-
If
argumentis a valid URL with schemesass:-
If
configis not empty, throw an error. -
If a built-in module exists with the exact given URL, return it.
-
Otherwise, throw an error.
-
-
Let
filebe the result of loading the file atargument. -
If
fileis null, throw an error. -
If
filehas already been executed:-
If
configis not empty, throw an error. -
Otherwise, return the module that execution produced.
-
-
If
fileis currently being executed, throw an error.This disallows circular
@uses, which ensures that modules can't be used until they're fully initialized. -
Otherwise, return the result of executing
filewithconfigand a new import context.For simplicity, the spec creates an import context for every module. Implementations are encouraged to avoid eagerly allocating resources for imports, though, to make use-cases only involving
@usemore efficient.
This algorithm takes a string, argument, and returns either a source file
or null.
-
If the scheme of the current source file's canonical URL is
file:- Let
rootbe the current source file's canonical URL.
- Let
-
Otherwise, let
rootbenull. -
Let
basesbe a list beginning withrootif it's non-null, followed by the absolutefile:URLs of all import paths. -
For each
baseinbases:-
Let
urlbe the result of parsingargumentas a URL withbaseas the base URL.If this returns a failure, throw that failure.
-
If
url's scheme is notfile, return null. -
Let
resolvedbe the result of resolvingurl. -
If
resolvedis null:-
Let
indexbedirname(url)+"index/"+basename(url). -
Set
resolvedto the result of resolvingindex.
-
-
If
resolvedis still null, continue to the next loop. -
Let
textbe the contents of the file atresolved. -
Let
astbe:- The result of parsing
textas SCSS ifresolvedends in.scss. - The result of parsing
textas the indented syntax ifresolvedends in.sass. - The result of parsing
textas CSS ifresolvedends in.css.
The algorithm for resolving a
file:URL guarantees thatresolvedwill have one of these extensions. - The result of parsing
-
Return a source file with
astas its abstract syntax tree andresolvedas its canonical URL.
-
-
Return null.
This algorithm takes a URL, url, whose scheme must be file and returns
either another URL that's guaranteed to point to a file on disk or null.
-
If
urlends in.scss,.sass, or.css:-
If this algorithm is being run for an
@import:-
Let
suffixbe the trailing.scss,.sass,.cssinurl, andprefixthe portion ofurlbeforesuffix. -
If the result of resolving
prefix+".import"+suffixfor partials is not null, return it.
-
-
Otherwise, return the result of resolving
urlfor partials.
@imports whose URLs explicitly end in.csswill have been treated as plain CSS@imports before this algorithm even runs, sourlwill only end in.cssfor@userules. -
-
If this algorithm is being run for an
@import:-
Let
sassbe the result of resolvingurl+".import.sass"for partials. -
Let
scssbe the result of resolvingurl+".import.scss"for partials. -
If neither
sassnorscssare null, throw an error. -
Otherwise, if exactly one of
sassandscssis null, return the other one. -
Otherwise, if the result of resolving
url+".import.css"for partials is not null, return it.
-
-
Otherwise, let
sassbe the result of resolvingurl+".sass"for partials. -
Let
scssbe the result of resolvingurl+".scss"for partials. -
If neither
sassnorscssare null, throw an error. -
Otherwise, if exactly one of
sassandscssis null, return the other one. -
Otherwise, return the result of resolving
url+".css"for partials. .
This algorithm takes a URL, url, whose scheme must be file and returns
either another URL that's guaranteed to point to a file on disk or null.
-
If
url's basename begins with"_":-
If a file exists on disk at
url, returnurl.Otherwise return null.
-
-
Let
partialbedirname(url)+"_"+basename(url). -
If a file exists on disk at both
urlandpartial, throw an error. -
If a file exists on disk at
url, returnurl. -
If a file exists on disk at
partial, returnpartial. -
Return null.
This algorithm takes a member name name and a member type type,
and returns a member of type type or null.
-
If
nameis a plainIdentifieror aVariablethat's not aNamespacedVariable:-
Let
scopebe the scope of the innermost block containing the current statement such thatscopehas a member of typetypenamedname, or null if no such scope exists. -
If
scopeis not null, returnscope's value of typetypenamedname.
-
-
If
nameis aNamespacedIdentifierof the formnamespace.raw-nameor aVariableof the formnamespace.$raw-name:-
Let
usebe the@userule in the current source file whose namespace isnamespace. If there isn't exactly one such rule, throw an error.Unlike other identifiers in Sass, module namespaces do not treat
-and_as equivalent. -
If
usehasn't been executed yet, throw an error. -
Otherwise, let
modulebeuse's module. -
Return the member of
modulewith typetypeand nameraw-name. If there is no such member, throw an error.
-
-
If
typeis not "variable" and the current source file contains a top-level definition of a member of typetypenamedname:Local function and mixin definitions shadow those from global
@userules, so that an upstream package adding a member is less likely to break its downstream dependencies. We exclude variables from this because a top-level variable definition will set the module's variable value rather than defining a new variable local to this module.-
If the current import context contains a member
memberof typetypenamedname, return it.This includes member definitions within the current module.
-
Otherwise, return null.
It's an error to refer to a local member before it's defined, even if a member with the same name is defined in a loaded module. The referent to a member is guaranteed not to change due to definitions later in the file.
-
-
Let
membersbe the set of unique members of typetypenamednamein modules of the global@userules. -
If the current import context contains a member
memberof typetypenamedname:-
If
membersis not empty, throw an error. -
Otherwise, return
member.
-
-
Otherwise, if
memberscontains more than one member, throw an error.This ensures that, if a new version of a library produces a conflicting name, it causes an immediate error.
-
Otherwise, if
modulescontains a single module, return the member of typetypenamednamein that module. -
Otherwise, if the implementation defines a global member
memberof typetypenamedname, return that member.This includes the global functions and mixins defined as part of the Sass spec, and may also include other members defined through the implementation's host language API.
-
Otherwise, return null.