(Issue)
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
:
@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.
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:
// 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
module system proposal uses to declare an argument invocation rather than
an argument declaration.
This proposal updates the syntax for @content
and @include
as follows:
ContentRule ::= '@content' ArgumentInvocation? IncludeRule ::= '@include' Identifier ArgumentInvocation? ContentBlock? ContentBlock ::= UsingDeclaration? '{' Statements '}' UsingDeclaration ::= 'using' ArgumentDeclaration
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
becontent
'sArgumentInvocation
, or an invocation with no arguments ifcontent
has noArgumentInvocation
.This means that
@content
and@content()
are interpreted identically. -
Let
declaration
beinclude
'sUsingDeclaration
'sArgumentDeclaration
, or a declaration with no arguments ifinclude
has noUsingDeclaration
.This means that
@include foo { ... }
and@include foo using () { ... }
are interpreted identically. -
Let
arguments
be the result of applyinginvocation
todeclaration
.This means
arguments
is a mapping from variable names to values. Ifinvocation
isn't a valid invocation ofdeclaration
, this will throw an error that should be surfaced to the user. -
If
include
has noContentBlock
, do nothing.Exiting here rather than earlier means that
@content(value)
is an error ifinclude
has no content block. -
Otherwise, let
scope
be a new scope that's a child ofinclude
's scope. -
For each pair
variable
andvalue
inarguments
:- Set
variable
tovalue
inscope
.
- Set
-
Evaluate
include
'sContentBlock
statements inscope
.