As noted, the Parser can't handle the `<number>` syntax for this - it
gets parsed instead by the `<number>` branch. We can't actually resolve
the ambiguity without making the Parser aware of what type each
media-feature is, but I will get to that soon. :^)
For now, we only understand `none`, `normal`, `<image>` and `<string>`.
The various other functions and identifiers can be added later.
We can *almost* use a StyleValueList for this, except it's divided into
two parts - the content, and the optional "alt text". So, I've added a
new StyleValue for it.
This is the only dimension type besides `<length>` that is used in any
media queries in levels 4 or 5 right now. Others can be included
if/when they're needed.
This means the units are defined in a single place instead of two.
Also removed the verify that we didn't produce a bogus % dimension token
in the Tokenizer, since this has never happened and the parser is not a
tokenizer test suite. :^)
When converting this code to use Optional, I accidentally left in the
initialization, so it *always* had a value, and always created a Length
from it. Oops.
The pattern we've adopted for other multi-value properties is to run in
a loop like this, since that makes it easier to cater for values
appearing in different orders.
During the LengthPercentage split, I converted the individual-corner
`border-foo-bar-radius` properties to LengthPercentage but forgot
`border-radius` itself! Oops. Discord's CSS was doing `border-radius:
50%` a lot, so this cuts down on CSS parser spam.
Browser has a handy debug menu option to dump all stylesheets, so we
don't need to spam the console with this. (All the spam massively slows
down page loads.)
See https://www.w3.org/TR/css-values-3/#calc-type-checking
If the sub-expressions' types are incompatible, we discard the calc() as
invalid.
Had to do some minor rearranging/renaming of the Calc structs to make
the `resolve_foo_type()` templates work too.
This lets us produce valid CSS in its to_string() method, instead of
always adding commas as before. :^)
Also, finally added a Formatter for StyleValues.
This is in a slightly weird state, where Percentages are sometimes
Lengths and sometimes not, which I will be cleaning up in subsequent
commits, in an attempt not to change all of LibWeb in one go. :^)
This means you can now do queries like:
```css
@media (400px <= width < 800px) { }
```
Chromium and Firefox which I tested with both don't support this yet, so
that's cool. :^)
Past me decided that the grammar was overly verbose and I could do it
better myself. Which seemed fine until the spec changed and I didn't
know how to integrate the changes. Lesson learned! :^)
Rather than have a function for every single part of the grammar, I have
written some as lambdas, and combned `<media-condition>` and
`<media-condition-without-or>` into one function. But otherwise it's
close to the spec, with comments listing the part of the grammar being
parsed, so hopefully it will be easier to make future adjustments!
This does not add any new functionality.
Web::CSS::MediaQuery::MediaFeature::Type was getting a bit ridiculous!
Also, this moves the detection of "min-" and "max-" media-features into
the MediaFeature itself, since this is an implementation detail, not
part of the spec.
Previously, we were using StyleValues for this, which was a bit of a
hack and was brittle, breaking when I modified how custom properties
were parsed. This is better and also lets us limit the kinds of value
that can be used here, to match the spec.
If a property is custom or contains a `var()` reference, it cannot be
parsed into a proper StyleValue immediately, so we store it as an
UnresolvedStyleValue until the property is compute. Then, at compute
time, we resolve them by expanding out any `var()` references, and
parsing the result.
The implementation here is very naive, and involves copying the
UnresolvedStyleValue's tree of StyleComponentValueRules while copying
the contents of any `var()`s it finds along the way. This is quite an
expensive operation to do every time that the style is computed.
Now that we can serialize CSS tokens, we can just hold a string and then
re-parse it when the Supports is evaluated. This feels a little weird,
but it only happens once so it's not going to slow it down much, and it
keep the API cleaner.