2018-10-15 20:14:46 +00:00
|
|
|
# `@content` Arguments: Draft 1
|
|
|
|
|
|
|
|
*([Issue](https://github.com/sass/sass/issues/871))*
|
|
|
|
|
|
|
|
## Table of Contents
|
|
|
|
|
|
|
|
* [Summary](#summary)
|
|
|
|
* [Design Decisions](#design-decisions)
|
|
|
|
* [Syntax](#syntax)
|
|
|
|
* [Semantics](#semantics)
|
|
|
|
|
|
|
|
## Summary
|
|
|
|
|
|
|
|
> This section is non-normative.
|
|
|
|
|
|
|
|
This proposal adds the ability for mixins to pass arguments to their `@content`
|
|
|
|
blocks. These arguments are passed using the normal argument syntax, and
|
|
|
|
accepted using a new `using` syntax for `@include`:
|
|
|
|
|
|
|
|
```scss
|
|
|
|
@mixin accepts-content {
|
|
|
|
@for $i from 1 to 5 {
|
|
|
|
@content($i, 360deg * $i / 5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@include accepts-content using ($number, $hue) {
|
|
|
|
.color-#{$number} {
|
|
|
|
background-color: hsl($hue, 75%, 90%);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
The argument list for `using` supports all the features of a normal argument list
|
|
|
|
declaration.
|
|
|
|
|
|
|
|
### Design Decisions
|
|
|
|
|
|
|
|
While the syntax for passing arguments to `@content` was pretty obvious, a
|
|
|
|
number of different syntaxes were considered for declaring which arguments are
|
|
|
|
accepted by an `@include`, including:
|
|
|
|
|
|
|
|
```scss
|
|
|
|
// Adding a new at-rule:
|
|
|
|
@include accepts-content {
|
|
|
|
@receive ($number, $hue);
|
|
|
|
// ...
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adopting Ruby's block syntax:
|
|
|
|
@include accepts-content { |$number, $hue|
|
|
|
|
// ...
|
|
|
|
}
|
|
|
|
|
|
|
|
// A Haskell-like punctuation syntax:
|
|
|
|
@include accepts-content -> ($number, $hue) {
|
|
|
|
// ...
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
We decided on `using` over `@receive` because it reads clearer to have the
|
|
|
|
arguments be part of the `@include` syntax rather than in the mixin body. We
|
|
|
|
chose it over Ruby- or Haskell-style because we generally prefer the use of
|
|
|
|
words over punctuation in Sass.
|
|
|
|
|
|
|
|
We decided to use `using` as opposed to another word because it's relatively
|
|
|
|
terse while still being clear. We considered `as` instead, but decided the
|
|
|
|
meaning of the word didn't match the semantics; and we considered `with`, but
|
|
|
|
decided that it was both semantically ambiguous and confusing because the
|
2024-06-18 00:49:23 +00:00
|
|
|
[module system proposal] uses to declare an argument *invocation* rather than
|
2018-10-15 20:14:46 +00:00
|
|
|
an argument *declaration*.
|
|
|
|
|
2021-01-12 22:14:57 +00:00
|
|
|
[module system proposal]: module-system.md
|
2018-10-15 20:14:46 +00:00
|
|
|
|
|
|
|
## Syntax
|
|
|
|
|
|
|
|
This proposal updates the syntax for `@content` and `@include` as follows:
|
|
|
|
|
|
|
|
<x><pre>
|
|
|
|
**ContentRule** ::= '@content' ArgumentInvocation?
|
|
|
|
**IncludeRule** ::= '@include' Identifier ArgumentInvocation? ContentBlock?
|
|
|
|
**ContentBlock** ::= UsingDeclaration? '{' Statements '}'
|
|
|
|
**UsingDeclaration** ::= 'using' ArgumentDeclaration
|
|
|
|
</pre></x>
|
|
|
|
|
|
|
|
## Semantics
|
|
|
|
|
|
|
|
This proposal defines a new algorithm for evaluating a `@content` rule. Given a
|
|
|
|
`@content` rule `content` within a mixin that's invoked with an `@include` rule
|
|
|
|
`include`:
|
|
|
|
|
|
|
|
* Let `invocation` be `content`'s `ArgumentInvocation`, or an invocation with no
|
|
|
|
arguments if `content` has no `ArgumentInvocation`.
|
|
|
|
|
|
|
|
> This means that `@content` and `@content()` are interpreted identically.
|
|
|
|
|
|
|
|
* Let `declaration` be `include`'s `UsingDeclaration`'s `ArgumentDeclaration`,
|
|
|
|
or a declaration with no arguments if `include` has no `UsingDeclaration`.
|
|
|
|
|
|
|
|
> This means that `@include foo { ... }` and `@include foo using () { ... }`
|
|
|
|
> are interpreted identically.
|
|
|
|
|
|
|
|
* Let `arguments` be the result of applying `invocation` to `declaration`.
|
|
|
|
|
|
|
|
> This means `arguments` is a mapping from variable names to values. If
|
|
|
|
> `invocation` isn't a valid invocation of `declaration`, this will throw an
|
|
|
|
> error that should be surfaced to the user.
|
|
|
|
|
|
|
|
* If `include` has no `ContentBlock`, do nothing.
|
|
|
|
|
|
|
|
> Exiting here rather than earlier means that `@content(value)` is an error if
|
|
|
|
> `include` has no content block.
|
|
|
|
|
|
|
|
* Otherwise, let `scope` be a new scope that's a child of `include`'s scope.
|
|
|
|
|
|
|
|
* For each pair `variable` and `value` in `arguments`:
|
|
|
|
|
|
|
|
* Set `variable` to `value` in `scope`.
|
|
|
|
|
|
|
|
* Evaluate `include`'s `ContentBlock` statements in `scope`.
|