accepted/attr-type.md
This section is non-normative.
CSS Values and Units 5 defines the <attr-type> production, which includes
two different productions that aren't valid in any other CSS expression context
and as such which aren't currently valid SassScript. Specifically:
The <syntax> production, which mimics the CSS spec's own syntax for
declaring syntactic productions and so involves characters like <, *, #,
and +. Fortunately, this is always contained in a type() function call so
is unambiguous in practice.
The <attr-unit> production, which is mostly just identifiers but also
includes % as a value in its own right. This character is already used in
SassScript as the modulo operator.
This is further complicated by the fact that the attr() function (in which the
<attr-type> production appears) has been supported in browsers for a number of
years with a more constrained syntax, so changing it to use a substantially
different parsing schema would be a breaking change.
This proposal defines the type() function as a special function like
expression() or element() which is parsed as an unquoted string. Because CSS
doesn't use the type() function name elsewhere, we consider this relatively
low-risk. However, because it will prevent authors from declaring their own
functions named type(), it is a breaking change and will go through a standard
three-month CSS compatibility deprecation period.
We will parse % as an unquoted string only in contexts where it's not
potentially ambiguous with an operation. This will satisfy CSS compatibility
because the only case where CSS currently allows it is in the attr() function,
where it must appear before either a comma or a closing parenthesis. We don't
anticipate that a single % will be widely used in other contexts, so we don't
plan to deprecate the modulo operator, although that path is open in the future
if CSS starts using this value more widely.
Add attr( to the list of unquoted string prefixes that qualify as special
numbers.
SpecialFunctionExpressionChange the SpecialFunctionName production to be:
<x><pre> SpecialFunctionName¹ ::= VendorPrefix? ('element(' | 'expression(') | VendorPrefix 'calc(' | 'type(' </pre></x>
No browser has yet supported
type()with a vendor prefix, nor are they likely to do so in the future given that vendor prefixes are largely unpopular now.
SingleExpressionAdd Percent as a production to SingleExpression with the following
annotation:
If this is ambiguous with part of ProductExpression, parse ProductExpression
preferentially. If this is followed by a Whitespace that contains a
LineBreak, do not parse that Whitespace as part of an IndentSame or
IndentMore production.
This effectively means that the unquoted string
%is allowed everywhere except in a middle element of a space-separated list, since that would be ambiguous with a modulo operation. The whitespace clause ensures that a%at the end of a line in the indented syntax always looks at the next token, for backwards-compatibility with parsing it as an operator and so that whether the statement ends on that line or not doesn't depend on the first token of the next line.
Percent<x><pre> Percent ::= '%' </pre></x>
PercentTo evaluate a Percent, return an unquoted string with the value %.
@functionIn the semantics for @function, add a bullet point below the second:
name is case-insensitively equal to type, throw an error.Unlike other forbidden function names, this doesn't cover vendor prefixes. This is for two reasons: first, we don't expect to add special parsing for
type()with vendor prefixes. Second, "type" is a relatively common word, so it's likely for private function names to end with-typein a way that could be indistinguishable from a vendor prefix.
The deprecation process will be divided into two phases:
This phase adds no breaking changes. Its purpose is to notify users of the upcoming changes to behavior and give them a chance to move towards passing future-proof units.
Phase 1 does not change the syntax for SpecialFunctionName or the semantics
for @function. Instead, if a function is defined with the name type, emit a
deprecation warning named type-function.
Phase 2 implements the full changes described above. Per the Dart Sass compatibility policy, it won't be released until at least three months after the first release with the deprecation warning.