(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
invocationbecontent'sArgumentInvocation, or an invocation with no arguments ifcontenthas noArgumentInvocation.This means that
@contentand@content()are interpreted identically. -
Let
declarationbeinclude'sUsingDeclaration'sArgumentDeclaration, or a declaration with no arguments ifincludehas noUsingDeclaration.This means that
@include foo { ... }and@include foo using () { ... }are interpreted identically. -
Let
argumentsbe the result of applyinginvocationtodeclaration.This means
argumentsis a mapping from variable names to values. Ifinvocationisn't a valid invocation ofdeclaration, this will throw an error that should be surfaced to the user. -
If
includehas noContentBlock, do nothing.Exiting here rather than earlier means that
@content(value)is an error ifincludehas no content block. -
Otherwise, let
scopebe a new scope that's a child ofinclude's scope. -
For each pair
variableandvalueinarguments:- Set
variabletovalueinscope.
- Set
-
Evaluate
include'sContentBlockstatements inscope.