2019-02-20 21:43:29 +00:00
|
|
|
# Variables
|
|
|
|
|
|
|
|
## Table of Contents
|
|
|
|
|
|
|
|
* [Syntax](#syntax)
|
|
|
|
* [Definitions](#definitions)
|
|
|
|
* [Scope](#scope)
|
|
|
|
* [Global Scope](#global-scope)
|
2019-11-27 01:34:49 +00:00
|
|
|
* [Semantics](#semantics)
|
|
|
|
* [Executing a Variable Declaration](#executing-a-variable-declaration)
|
|
|
|
* [Evaluating a Variable](#evaluating-a-variable)
|
2019-02-20 21:43:29 +00:00
|
|
|
|
|
|
|
## Syntax
|
|
|
|
|
|
|
|
<x><pre>
|
2019-11-27 01:34:49 +00:00
|
|
|
**Variable** ::= '$' Identifier | NamespacedVariable
|
|
|
|
**NamespacedVariable** ::= Identifier '.$' [PublicIdentifier][]
|
2019-02-20 21:43:29 +00:00
|
|
|
**VariableDeclaration** ::= Variable ':' Expression ('!global' | '!default')*
|
|
|
|
</pre></x>
|
|
|
|
|
2019-11-27 01:34:49 +00:00
|
|
|
[PublicIdentifier]: modules.md#syntax
|
|
|
|
|
|
|
|
No whitespace is allowed after the `$` or before or after the `.$` in
|
|
|
|
`Variable`. Each of `!global` and `!default` is allowed at most once in
|
|
|
|
`VariableDeclaration`. As with all statements, a `VariableDeclaration` must be
|
|
|
|
separated from other statements with a semicolon.
|
2019-02-20 21:43:29 +00:00
|
|
|
|
|
|
|
## Definitions
|
|
|
|
|
|
|
|
### Scope
|
|
|
|
|
|
|
|
A *scope* is a mapping from variable names to values. Every block of statements
|
|
|
|
delimited by `{` and `}` in SCSS or by indentation in the indented syntax has an
|
|
|
|
associated scope.
|
|
|
|
|
|
|
|
### Global Scope
|
|
|
|
|
|
|
|
The *global scope* is the scope shared among the top level of all Sass files.
|
|
|
|
|
2019-11-27 01:34:49 +00:00
|
|
|
## Semantics
|
|
|
|
|
|
|
|
### Executing a Variable Declaration
|
|
|
|
|
|
|
|
To execute a `VariableDeclaration` `declaration`:
|
|
|
|
|
|
|
|
* Let `value` be the result of evaluating `declaration`'s `Expression`.
|
|
|
|
|
|
|
|
* Let `name` be `declaration`'s `Variable`.
|
|
|
|
|
|
|
|
* If `name` is a `NamespacedVariable` and `declaration` has a `!global` flag,
|
|
|
|
throw an error.
|
|
|
|
|
|
|
|
* Otherwise, if `declaration` is outside of any block of statements, *or*
|
|
|
|
`declaration` has a `!global` flag, *or* `name` is a `NamespacedVariable`:
|
|
|
|
|
2019-11-27 03:35:36 +00:00
|
|
|
* Let `resolved` be the result of [resolving a variable][] named `name` using
|
2019-11-27 01:34:49 +00:00
|
|
|
`file`, `uses`, and `import`.
|
|
|
|
|
|
|
|
* If `declaration` has a `!default` flag, `resolved` isn't null, *and*
|
|
|
|
`resolved`'s value isn't null, do nothing.
|
|
|
|
|
|
|
|
* Otherwise, if `resolved` is a variable in another module:
|
|
|
|
|
|
|
|
* Evaluate `declaration`'s value and set `resolved`'s value to the result.
|
2019-02-20 21:43:29 +00:00
|
|
|
|
2019-11-27 01:34:49 +00:00
|
|
|
* Otherwise:
|
2019-02-20 21:43:29 +00:00
|
|
|
|
2019-11-27 01:34:49 +00:00
|
|
|
* If `declaration` is outside of any block of statements, it has a
|
|
|
|
`!default` flag, *and* `config` contains a variable named `name` whose
|
|
|
|
value is not null:
|
2019-02-20 21:43:29 +00:00
|
|
|
|
2019-11-27 01:34:49 +00:00
|
|
|
* Let `value` be the value of `config`'s variable named `name`.
|
2019-02-20 21:43:29 +00:00
|
|
|
|
2019-11-27 01:34:49 +00:00
|
|
|
* Otherwise, let `value` be the result of evaluating `declaration`'s value.
|
2019-02-21 23:16:54 +00:00
|
|
|
|
2019-11-27 01:34:49 +00:00
|
|
|
* If `name` *doesn't* begin with `-` or `_`, add a variable with name `name`
|
|
|
|
and value `value` to `module`.
|
2019-02-21 23:16:54 +00:00
|
|
|
|
2019-11-27 01:34:49 +00:00
|
|
|
> This overrides the previous definition, if one exists.
|
2019-02-21 23:16:54 +00:00
|
|
|
|
2019-11-27 01:34:49 +00:00
|
|
|
* Add a variable with name `name` and value `value` to `import`.
|
2019-02-21 23:16:54 +00:00
|
|
|
|
2019-11-27 01:34:49 +00:00
|
|
|
> This also overrides the previous definition.
|
2019-02-20 21:43:29 +00:00
|
|
|
|
2019-11-27 04:32:39 +00:00
|
|
|
[resolving a variable]: modules.md#resolving-a-member
|
|
|
|
|
2019-02-20 21:43:29 +00:00
|
|
|
* Otherwise, if `declaration` is within one or more blocks associated with
|
2019-11-27 01:34:49 +00:00
|
|
|
`@if`, `@each`, `@for`, and/or `@while` rules *and no other blocks*:
|
|
|
|
|
2019-11-27 04:32:39 +00:00
|
|
|
* Let `resolved` be the result of [resolving a variable][] named `name`.
|
2019-11-27 01:34:49 +00:00
|
|
|
|
|
|
|
* If `resolved` is not null:
|
|
|
|
|
|
|
|
* If `declaration` has a `!default` flag and `resolved`'s value isn't
|
|
|
|
null, do nothing.
|
|
|
|
|
|
|
|
* Otherwise, let `value` be the result of evaluating `declaration`'s value.
|
|
|
|
|
|
|
|
* If `name` *doesn't* begin with `-` or `_`, add a variable with name `name`
|
|
|
|
and value `value` to `module`.
|
|
|
|
|
|
|
|
> This overrides the previous definition, if one exists.
|
|
|
|
|
|
|
|
* Add a variable with name `name` and value `value` to `import`.
|
|
|
|
|
|
|
|
> This also overrides the previous definition.
|
|
|
|
|
2019-11-27 04:32:39 +00:00
|
|
|
* Otherwise, if no block containing `declaration` has a [scope](#scope) with a
|
2019-02-20 21:43:29 +00:00
|
|
|
variable named `name`, set the innermost block's scope's variable `name` to
|
|
|
|
`value`.
|
|
|
|
|
|
|
|
* Otherwise, let `scope` be the scope of the innermost block such that `scope`
|
2019-11-27 01:34:49 +00:00
|
|
|
already has a variable named `name`.
|
2019-02-20 21:43:29 +00:00
|
|
|
|
2019-11-27 01:34:49 +00:00
|
|
|
* Set `scope`'s variable `name` to `value`.
|
2019-02-20 21:43:29 +00:00
|
|
|
|
2019-11-27 01:34:49 +00:00
|
|
|
### Evaluating a Variable
|
2019-02-20 21:43:29 +00:00
|
|
|
|
2019-11-27 01:34:49 +00:00
|
|
|
To evaluate a `Variable` `variable`:
|
2019-02-20 21:43:29 +00:00
|
|
|
|
2019-11-27 01:34:49 +00:00
|
|
|
* Let `definition` be the result of [resolving a variable][] named `variable`.
|
|
|
|
If this returns null, throw an error.
|
2019-02-20 21:43:29 +00:00
|
|
|
|
2019-11-27 01:34:49 +00:00
|
|
|
* Return `definition`'s value.
|