When parsing the "style" attribute on elements, we'd previously ask the
CSS parser for a PropertyOwningCSSStyleDeclaration. Then we'd create a
new ElementCSSInlineStyleDeclaration and transfer the properties from
the first object to the second object.
This patch teaches the parser to make ElementCSSInlineStyleDeclaration
objects directly.
When I wrote the An+B parser, it was guaranteed to have no
non-whitespace tokens after it. This is no longer true with the `of
foo` syntax, so this patch corrects the logic when there is no `+B`
segment.
This makes this case shown on Twitter work correctly. :^)
https://twitter.com/simevidas/status/1506657566012678151
`text-shadow` does not support this, so this way we can still use the
same parsing code.
It's OK that we still assign a ShadowPlacement value to the
ShadowStyleValue, since it will just get ignored when painting
text-shadows, but if it appears in the property value then that is a
syntax error.
The `text-shadow` property is almost identical to `box-shadow`:
> Values are interpreted as for box-shadow [CSS-BACKGROUNDS-3].
> (But note that the inset keyword are not allowed.)
So, let's use the same data structures and parsing code for both. :^)
The ifs below the switch no longer functioned, so let's move everything
into the switch cases. This also means we can replace the StringBuilder
usage with String::formatted().
Dimension tokens don't make use of the m_value string for anything else,
so we can sneak the unit string in there.
- Token goes from 72 to 64 bytes
- StyleComponentValueRule goes from 80 to 72 bytes
These three are all integers - we just repeatedly multiply them by 10
and then add a digit - so using an integer here is both faster and more
accurate. :^)
There's really no reason to use doubles here, except at the time I
wanted to use doubles everywhere in CSS. I now realize that is
excessive, so everything can be floats instead.
There was no real benefit to creating the SimpleSelector early and then
modifying it, and doing so made this code harder to follow than it
needs to be.
We want to return a view to a constant object, not a constant view,
which we can implicitly copy to get a mutable reference to the object.
Clang-Tidy helpfully pointed this out.
The spec says:
> <delim-token> has a value composed of a single code point.
So using StringView is a bit overkill.
This also allows us to use switch statements in the future.
This doesn't have parsing support for multiple languages in the same
selector. Support for language subcodes is not great either. But it
does do the basics.
ID selectors need to be serialized as identifiers in the spec, but other
hash-values do not. This was causing hex colors that start with a
number, like `#54a3ff`, to serialize as `#\35 4a3ff`, which is silly
and unnecessary.
Selector serialization is done elsewhere, so this case in Token is
probably also unnecessary, but there might be situations I haven't
thought of where serializing an ID does need to happen while it's still
a Token.
`static const` variables can be computed and initialized at run-time
during initialization or the first time a function is called. Change
them to `static constexpr` to ensure they are computed at
compile-time.
This allows some removal of `strlen` because the length of the
`StringView` can be used which is pre-computed at compile-time.
In Selectors level 4, `:nth-child()` and `:nth-last-child()` can both
optionally take a selector-list argument. This selector-list acts as a
filter, so that only elements matching the list are counted. For
example, this means that the following are equivalent:
```css
:nth-child(2n+1 of p) {}
p:nth-of-type(2n+1) {}
```
`<forgiving-selector-list>` and `<forgiving-relative-selector-list>` are
the same as regular selector-lists, except that an invalid selector
does not make the whole list invalid. The former is used by the `:is()`
pseudo-class.
For example:
```css
/* This entire selector-list is invalid */
.foo, .bar, !?invalid { }
/* This is valid, but the "!?invalid" selector is removed */
:is(.foo, .bar, !?invalid) { }
```
Also as part of this, I've removed the `parse_a_selector(TokenStream)`
and `parse_a_relative_selector(TokenStream)` methods as they don't add
anything useful.
This resolves the ambiguity between whether a single number is a number
or a ratio. :^)
Also removed the "no more tokens" checks from
deea129b8c - that logic was completely
wrong, since there are always tokens after a value in the `(123 < foo <
456)` syntax.