Nothing Special   »   [go: up one dir, main page]

Skip to content

Commit

Permalink
[css-syntax-3] Per WG resolution, {} blocks are only allowed as the e…
Browse files Browse the repository at this point in the history
…ntire value of a property. #9317
  • Loading branch information
tabatkins committed Oct 9, 2023
1 parent 776b5a0 commit 77e9601
Showing 1 changed file with 94 additions and 13 deletions.
107 changes: 94 additions & 13 deletions css-syntax-3/Overview.bs
Original file line number Diff line number Diff line change
Expand Up @@ -2828,6 +2828,79 @@ Consume a block's contents</h4>
append it to |rules|.
</dl>

<details class=note>
<summary>Implementation note</summary>

This spec, as with many CSS specs,
has been written to prioritize understandability
over efficiency.
A number of algorithms,
notably the above "parse as a declaration, then parse as a rule" behavior
can be fairly inefficient
if implemented naively as described.

However, the behavior has been carefully written
to allow "early exits" as much as possible.
In particular,
and roughly in order of when the exit can occur:

* If the first non-whitespace token
isn't an <<ident-token>>
for a recognized property name (or a custom property name),
you can immediately stop parsing as a declaration
and reparse as a rule instead.
If the <em>next</em> non-whitespace token isn't a <<colon-token>>,
you can similarly immediately stop parsing as a declaration.

(That is, ''font+ ...'' is guaranteed to not be a property,
nor is <css>not-a-prop-name: ...</css>.)

* If the first two non-whitespace tokens
are a custom property name and a colon,
it's definitely a custom property
and won't ever produce a valid rule,
so even if the custom property ends up invalid
there's no need to try and reparse as a rule.

(That is, ''--foo:hover {...}'' is guaranteed to be a custom property,
not a rule.)

* If the first three non-whitespace tokens
are a valid property name, a colon, and anything other than a <<{-token>>,
and then while parsing the declaration's value you encounter a <<{-token>>,
you can immediately stop parsing as a declaration
and reparse as a rule instead.

(That is, ''font:bar {...'' is guaranteed to be an invalid property.)

* If you see a recognized property name, a colon, and a {}-block,
but the first non-whitespace tokens following that block
isn't either immediately the final semicolon,
or the !important followed by the semicolon,
you can immediately stop parsing as a declaration
and reparse as a rule instead.

(That is, ''font: {} bar ...'' is guaranteed to be an invalid property;
you don't need to keep parsing until you hit a semicolon.)

Similarly,
even tho the parsing requirements are specified
to rely on checking the grammar of the declarations
as you parse,
a <em>generic</em> processor
trying to implement a non-CSS language
on top of the generic CSS <em>syntax</em>
can still get away with just verifying that declarations
start with an ident, a colon,
and then either contain solely a {}-block
or no {}-block at all.
They'll just spent a little more time on parsing
than an implementation with grammar knowledge
in cases like ''foo:hover ... {}'',
since they can't early-exit on the first token.
</details>



<h4 id="consume-declaration">
Consume a declaration</h4>
Expand Down Expand Up @@ -2873,19 +2946,6 @@ Consume a declaration</h4>
and with <<semicolon-token>> as the stop token,
and set |decl|'s value to the result.

If |decl|'s name is a [=custom property name string=],
then set |decl|'s |original text|
to the segment of the original source text string
corresponding to the tokens
returned by the [=consume a list of component values=] call.

If |decl|'s name is an [=ASCII case-insensitive=] match for "unicode-range",
[=consume the value of a unicode-range descriptor=]
from the segment of the original source text string
corresponding to the tokens
returned by the [=consume a list of component values=] call,
and replace |decl|'s value with the result.

<li>
If the last two non-<<whitespace-token>>s in |decl|'s value are
a <<delim-token>> with the value "!"
Expand All @@ -2897,6 +2957,27 @@ Consume a declaration</h4>
While the last item in |decl|'s value is a <<whitespace-token>>,
[=list/remove=] that token.

<li>
If |decl|'s name is a [=custom property name string=],
then set |decl|'s |original text|
to the segment of the original source text string
corresponding to the tokens
of |decl|'s value.

Otherwise, if |decl|'s value contains a top-level [=simple block=]
with an associated token of <<{-token>>,
and also contains <em>any other</em> non-<<whitespace-token>> value,
return nothing.
(That is, a top-level {}-block is only allowed
as the entire value of a non-custom property.)

Otherwise, if |decl|'s name is an [=ASCII case-insensitive=] match for "unicode-range",
[=consume the value of a unicode-range descriptor=]
from the segment of the original source text string
corresponding to the tokens
returned by the [=consume a list of component values=] call,
and replace |decl|'s value with the result.

<li>
If |decl| is valid in the current context,
return it;
Expand Down

0 comments on commit 77e9601

Please sign in to comment.