Skip to content

Commit 3a4a0d6

Browse files
committed
[css-values-5] Per WG resolution, switch comma-containing productions to allowing {} wrappers, rather than semicolon upgrades. #9539
1 parent f8e266b commit 3a4a0d6

File tree

1 file changed

+72
-51
lines changed

1 file changed

+72
-51
lines changed

css-values-5/Overview.bs

+72-51
Original file line numberDiff line numberDiff line change
@@ -76,39 +76,36 @@ Functional Notation Definitions</h3>
7676
See [[css-values-4#component-functions]].
7777

7878
<h4 id=component-function-commas>
79-
Commas and Semicolons in Functions</h4>
79+
Commas in Function Arguments</h4>
8080

8181
[=Functional notation=] often uses commas
8282
to separate parts of its internal grammar.
8383
However, some functions
8484
(such as ''mix()'')
8585
allow values that, themselves,
8686
can contain commas.
87+
These values
88+
(currently <<whole-value>>, <<declaration-value>>, and <<any-value>>)
89+
are <dfn export>comma-containing productions</dfn>.
8790

8891
To accommodate these sorts of grammars unambiguously,
89-
commas in functional grammars are <em>implicitly upgradeable</em> to semicolons in Level 5;
90-
that is,
91-
commas in a [=functional notation=]'s grammar
92-
can instead be represented as <<semicolon-token>>s.
93-
This is all-or-nothing:
94-
either every comma in the [=functional notation=] must be written as a semicolon,
95-
or none of them must be.
96-
97-
When a [=functional notation=] is parsed,
98-
initially commas (<css>,</css>) and comma-multipliers (<css>#</css>)
99-
in the grammar match only <<comma-token>>s in the value,
100-
and any [=comma-containing productions=] are not allowed to contain <<comma-token>>s
101-
(the productions must be interpreted as ending before the comma).
102-
If a <<semicolon-token>> is encountered while parsing the [=functional notation=],
103-
the contents must be <em>re-interpreted</em>,
104-
with commas and comma-multipliers in the grammar matching only <<semicolon-token>>s in the value,
105-
and [=comma-containing productions=] being allowed to contain <<comma-token>>s.
106-
107-
Commas contained in productions defined as <dfn>comma-containing productions</dfn>
108-
(such as <<any-value>> or <<whole-value>>)
109-
are not implicitly upgradeable.
110-
Even when a [=functional notation=] is being re-interpreted with semicolons,
111-
these productions end when a <<semicolon-token>> is encountered.
92+
the [=comma-containing productions=] can be optionally wrapped in curly braces {}.
93+
These braces are syntactic, not part of the actual value.
94+
Specifically:
95+
96+
* A [=comma-containing production=] can either start with a "{" token, or not.
97+
* If it does not start with a "{" token,
98+
then it cannot contain commas or {} blocks,
99+
in addition to whatever specific restrictions it defines for itself.
100+
(The production stops parsing at that point,
101+
so the comma or {} block is matched by the next grammar term instead;
102+
probably the function's own argument-separating comma.)
103+
* If it does start with a "{" token,
104+
then the production matches just the {} block that the "{" token opens.
105+
It represents the <em>contents</em> of that block,
106+
and applies whatever specific restrictions it defines for itself
107+
to those contents,
108+
ignoring the {} block wrapper.
112109

113110
<div class="example">
114111
For example, the grammar of the ''random-item()'' function is:
@@ -123,56 +120,80 @@ Commas and Semicolons in Functions</h4>
123120
like:
124121

125122
<pre>
126-
list-style: random-item(--x, disc, circle, square);
127-
</pre>
128-
129-
It is <em>allowed</em>, however,
130-
to "upgrade" the commas to semicolons,
131-
like:
132-
133-
<pre>
134-
list-style: random-item(--x; disc; circle; square);
135-
</pre>
136-
137-
Both of the above mean the exact same thing.
138-
However, mixing commas and semicolons does not work;
139-
the following can produce an invalid value after substitution:
140-
141-
<pre>
142-
list-style: random-item(--x; disc, circle; square);
123+
font-family: random-item(--x, serif, sans-serif, monospace);
143124
</pre>
144125

145-
because it represents choosing between two values
146-
(<css>disc, circle</css> and <css>square</css>)
147-
and <css>disc, circle</css> is not a valid 'list-style' value.
148-
149126
However, sometimes the values you want to choose between
150127
need to include commas.
151-
For example, in 'font-family':
128+
When this is the case,
129+
wrapping the values in {}
130+
allows their commas to be distinguished
131+
from the function's argument-separating commas:
152132

153133
<pre>
154-
font-family: random-item(--x; Times, serif; Arial, sans-serif; Courier, monospace);
134+
font-family: random-item(--x, {Times, serif}, {Arial, sans-serif}, {Courier, monospace});
155135
</pre>
156136

157137
This randomly chooses one of three font-family lists:
158138
either ''Times, serif'', or ''Arial, sans-serif'', or ''Courier, monospace''.
159-
But if only single fonts were needed for each choice,
160-
commas <em>could</em> have been used to separate them:
139+
140+
This is not all-or-nothing;
141+
you can use {} around <em>some</em> arguments that need it,
142+
while leaving others bare when they don't need it.
143+
You are also allowed to use {} around a value when it's not strictly required.
144+
For example:
161145

162146
<pre>
163-
font-family: random-item(--x, serif, sans-serif, monospace);
147+
font-family: random-item(--x, {Times, serif}, sans-serif, {monospace});
164148
</pre>
165149

150+
This represents choosing between three font-family lists:
151+
either ''Times, serif'', or ''sans-serif'', or ''monospace''.
152+
153+
However, this {}-wrapping is <em>only</em> allowed for some function arguments--
154+
those defined as [=comma-containing productions=].
155+
It's not valid for any other productions;
156+
if you use {} around other function arguments,
157+
it'll just fail to match the function's grammar
158+
and become invalid.
159+
For example, the following is <strong>invalid</strong>:
160+
161+
<pre>
162+
background-image: linear-gradient(to left, {red}, magenta);
163+
</pre>
166164
</div>
167165

168-
[=Functional notations=] are serialized with commas (rather than semicolons) whenever possible.
166+
Note: Because {} wrappers are allowed even when not explicitly required,
167+
they can be used defensively around values
168+
when the author isn't sure if they'll end up containing commas or not,
169+
due to [=arbitrary-substitution functions=] like ''var()''.
170+
For example, ''font-family: random-item(--x, {var(--list1)}, monospace)''
171+
will work correctly
172+
regardless of whether the ''--list1'' custom property
173+
contains a comma-separated list or not.
174+
175+
[=Functional notations=] are serialized without {} wrappers whenever possible.
169176

170177
The following generic productions are [=comma-containing productions=]:
171178

172179
* <<any-value>>
173180
* <<whole-value>>
174181
* <<declaration-value>>
175182

183+
For legacy compat reasons,
184+
the <<declaration-value>> defined the fallback value for ''var()''
185+
is a <dfn export>non-strict comma-containing production</dfn>.
186+
It ignores the rules restricting what it can contain
187+
when it does not start with a "{" token:
188+
it is allowed to contain commas and {} blocks.
189+
It still follows the standard [=comma-containing production=] rules
190+
when it <em>does</em> start with a "{" token, however:
191+
the fallback is just the contents of the {} block,
192+
and doesn't include the {} wrapper itself.
193+
194+
Other contexts <em>may</em> define that they use [=non-strict comma-containing productions=],
195+
but it <em>should</em> be avoided unless necessary.
196+
176197
<h2 id="level-4-extensions">
177198
Extensions to Level 4 Value Types</h3>
178199

0 commit comments

Comments
 (0)