A source file is a Sass abstract syntax tree along with an absolute URL, known as that file's canonical URL. A given canonical URL cannot be associated with more than one source file.
InterpolatedIdentifier ::= (<ident-token> | '-'? Interpolation) (Name | Interpolation)*
No whitespace is allowed between components of an InterpolatedIdentifier.
Name ::= (name code point | escape)+
MinMaxExpression ::= CssMinMax | FunctionExpression
CssMinMax ::= ('min(' | 'max(')¹ CalcValue (',' CalcValue)* ')'
CalcValue ::= CalcValue (('+' | '-' | '*' | '/') CalcValue)+
| '(' CalcValue ')'
| ('calc(' | 'env(' | 'var(')¹ InterpolatedDeclarationValue ')'
| CssMinMax
| Interpolation
| Number
1: The strings min(, max(, calc(, env(, and var( are matched
case-insensitively.
This algorithm takes a string, text, and returns a Sass abstract syntax tree.
This algorithm is designed with two goals in mind:
CSS imported from Sass should be as compatible with standard CSS as possible. In some cases we err even more towards CSS compatibility than SCSS does, because the CSS being imported is likely not written by someone who knows to avoid things that Sass interprets specially (such as certain
@importURLs).We should provide clear and eager feedback to users who accidentally try to use Sass features in CSS imports. We don't allow these features, and we want users to know that through error messages rather than digging through generated CSS only to find that Sass features were passed through unmodified. This is a particular concern because LibSass has historically allowed the use of Sass features in CSS imports.
The algorithm for parsing text as CSS works like parsing text as SCSS, with some modifications. The following productions should produce errors:
-
Any at-rules that are defined in Sass and not in plain CSS. At the time of writing, this means:
@at-root@content@debug@each@error@extend@for@forward@function@if@include@mixin@return@use@warn@while
-
An
@importthat contains interpolation in theurl(), the media query, or the supports query. -
An
@importthat appears within a style rule or at-rule. -
An
@importwith more than one argument. -
A declaration followed by an open curly brace (that is, a nested declaration).
-
A style rule appearing within another style rule.
-
The parent selector
&, either in a selector or a declaration value. -
Placeholder selectors.
-
All built-in functions, excluding the following:
rgb()rgba()hsl()hsla()grayscale()invert()alpha()opacity()
Note that user-defined functions are not forbidden, whether they're defined using
@functionor through a host language API. -
Any function called with keyword arguments or variable-length arguments.
-
Interpolation anywhere its contents would be evaluated. At the time of writing, this means:
- At-rule values (including
@mediaqueries) - Declaration names
- Declaration values
- Style rule selectors
- At-rule values (including
-
All SassScript operations except for:
/notorand
Note that although unary
-is forbidden, the-that appears at the beginning of a number literal is part of that literal and thus allowed. -
Parentheses in declaration values that aren't part of a CSS production.
-
Map literals.
-
The empty list literal
(,). -
Uses or declarations of Sass variables.
-
//-style ("silent") comments.
In addition, some productions should be parsed differently than they would be in SCSS:
-
All functions that don't produce errors should be parsed as plain CSS functions, regardless of whether a Sass function with that name is defined.
-
All
@imports that don't produce errors should be parsed as static CSS imports. -
The tokens
not,or,and, andnullshould be parsed as unquoted strings.The
/operation should be parsed as normal. Because variables, parentheses, functions that return numbers, and all other arithmetic expressions are disallowed, it will always compile to slash-separated values rather than performing division.
This algorithm consumes input from a stream of code points and returns a string.
This production has the same grammar as <ident-token>.
-
Let
stringbe an empty string. -
If the stream starts with
--, consume it and append it tostring. -
Otherwise:
-
If the stream starts with
-, consume it and append it tostring. -
If the stream starts with
\, consume an escaped code point with thestartflag set and append it tostring. -
Otherwise, if the stream starts with a name-start code point, consume it and append it to
string. -
Otherwise, throw an error.
-
-
Consume a name and append it to
string. -
Return
string.
This algorithm consumes input from a stream of code points and returns a
sequence of strings and/or expressions. It follows the grammar for an
InterpolatedIdentifier.
-
Let
componentsbe an empty list of strings and/or expressions. -
If the input starts with
-#{, consume a single code point and add"-"tocomponents. -
If the input starts with
#{, consume an interpolation and add its expression tocomponents. -
Otherwise, consume an identifier and add its string to
components. -
While the input starts with
#{, a name code point, or\:-
If the input starts with
#{, consume an interpolation and add its expression tocomponents. -
Otherwise, consume a name and add its string to
components.
-
-
Return
components.
This algorithm consumes input from a stream of code points and returns a string. The grammar for this production is:
Name ::= (name code point | escape)+
-
Let
stringbe an empty string. -
While the input starts with a name code point or
\:-
If the input starts with a name code point, consume it and append it to
string. -
Otherwise, consume an escaped code point and append it to
string.
-
-
Return
string.
This algorithm consumes input from a stream of code points. It takes an
optional boolean flag, start, which indicates whether it's at the beginning of
an identifier and defaults to false. It returns a string.
This production has the same grammar as escape in CSS Syntax Level 3.
-
If the stream doesn't start with a valid escape, throw an error.
-
Let
codepointbe the result of consuming an escaped code point. -
Let
characterbe the string containing onlycodepoint. -
If
codepointis a name-start code point, returncharacter. -
Otherwise, if
codepointis a name code point and thestartflag is not set, returncharacter. -
Otherwise, if
codepointis a non-printable code point, U+0009 CHARACTER TABULATION, U+000A LINE FEED, U+000D CARRIAGE RETURN, or U+000C FORM FEED; or ifcodepointis a digit and thestartflag is set:-
Let
codebe the lowercase hexadecimal representation ofcodepoint, with no leading0s. -
Return
"\"+code+" ".
Tab characters are parsed as explicit escapes in order to support a browser hack that targets IE 10 and earlier, wherein ending a declaration value with
\9would cause IE to interpret it as valid but other browsers to ignore it. -
-
Otherwise, return
"\"+character.
This algorithm consumes input from a stream of code points and returns a SassScript expression.
-
Let
expressionbe the result of consuming aMinMaxExpression. If the expression is ambiguous betweenCssMinMaxandFunctionExpression,CssMinMaxshould take precedence. -
If
expressionis aFunctionExpression, return it as-is. -
Otherwise, if
expressionis aCssMinMax, return an unquoted interpolated string expression that would be identical to the source text according to CSS semantics for all possible interpolated strings.