LibWeb: Parse the keyword 'none' in the CSS4 color functions
This updates the CSS parser to support the keyword 'none' in the CSS4 color functions. The underlying CSSColorValue already supports this keyword, meaning the parser can instantiate the color directly.
This commit is contained in:
parent
e099a452b1
commit
ff39f6cec5
Notes:
github-actions[bot]
2024-11-04 10:49:09 +00:00
Author: https://github.com/qligier Commit: https://github.com/LadybirdBrowser/ladybird/commit/ff39f6cec55 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1915 Reviewed-by: https://github.com/AtkinsSJ ✅
2 changed files with 81 additions and 26 deletions
|
@ -2388,6 +2388,7 @@ RefPtr<CSSStyleValue> Parser::parse_number_value(TokenStream<ComponentValue>& to
|
||||||
|
|
||||||
RefPtr<CSSStyleValue> Parser::parse_number_percentage_value(TokenStream<ComponentValue>& tokens)
|
RefPtr<CSSStyleValue> Parser::parse_number_percentage_value(TokenStream<ComponentValue>& tokens)
|
||||||
{
|
{
|
||||||
|
// Parses [<percentage> | <number>] (which is equivalent to [<alpha-value>])
|
||||||
auto peek_token = tokens.next_token();
|
auto peek_token = tokens.next_token();
|
||||||
if (peek_token.is(Token::Type::Number)) {
|
if (peek_token.is(Token::Type::Number)) {
|
||||||
tokens.discard_a_token(); // number
|
tokens.discard_a_token(); // number
|
||||||
|
@ -2405,6 +2406,33 @@ RefPtr<CSSStyleValue> Parser::parse_number_percentage_value(TokenStream<Componen
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RefPtr<CSSStyleValue> Parser::parse_number_percentage_none_value(TokenStream<ComponentValue>& tokens)
|
||||||
|
{
|
||||||
|
// Parses [<percentage> | <number> | none] (which is equivalent to [<alpha-value> | none])
|
||||||
|
auto peek_token = tokens.next_token();
|
||||||
|
if (peek_token.is(Token::Type::Number)) {
|
||||||
|
tokens.discard_a_token(); // number
|
||||||
|
return NumberStyleValue::create(peek_token.token().number().value());
|
||||||
|
}
|
||||||
|
if (peek_token.is(Token::Type::Percentage)) {
|
||||||
|
tokens.discard_a_token(); // percentage
|
||||||
|
return PercentageStyleValue::create(Percentage(peek_token.token().percentage()));
|
||||||
|
}
|
||||||
|
if (auto calc = parse_calculated_value(peek_token); calc && calc->resolves_to_number_percentage()) {
|
||||||
|
tokens.discard_a_token(); // calc
|
||||||
|
return calc;
|
||||||
|
}
|
||||||
|
if (peek_token.is(Token::Type::Ident)) {
|
||||||
|
auto keyword = keyword_from_string(peek_token.token().ident());
|
||||||
|
if (keyword.has_value() && keyword.value() == Keyword::None) {
|
||||||
|
tokens.discard_a_token(); // keyword none
|
||||||
|
return CSSKeywordValue::create(keyword.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<CSSStyleValue> Parser::parse_percentage_value(TokenStream<ComponentValue>& tokens)
|
RefPtr<CSSStyleValue> Parser::parse_percentage_value(TokenStream<ComponentValue>& tokens)
|
||||||
{
|
{
|
||||||
auto peek_token = tokens.next_token();
|
auto peek_token = tokens.next_token();
|
||||||
|
@ -2646,29 +2674,48 @@ RefPtr<CSSStyleValue> Parser::parse_rect_value(TokenStream<ComponentValue>& toke
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.w3.org/TR/css-color-4/#typedef-hue
|
// https://www.w3.org/TR/css-color-4/#typedef-hue
|
||||||
RefPtr<CSSStyleValue> Parser::parse_hue_value(TokenStream<ComponentValue>& tokens)
|
RefPtr<CSSStyleValue> Parser::parse_hue_none_value(TokenStream<ComponentValue>& tokens)
|
||||||
{
|
{
|
||||||
// <hue> = <number> | <angle>
|
// Parses [<hue> | none]
|
||||||
if (auto number = parse_number_value(tokens))
|
// <hue> = <number> | <angle>
|
||||||
return number;
|
|
||||||
if (auto angle = parse_angle_value(tokens))
|
auto peek_token = tokens.next_token();
|
||||||
return angle;
|
if (peek_token.is(Token::Type::Number)) {
|
||||||
|
tokens.discard_a_token(); // number
|
||||||
|
return NumberStyleValue::create(peek_token.token().number().value());
|
||||||
|
}
|
||||||
|
if (auto calc = parse_calculated_value(peek_token); calc && (calc->resolves_to_number() || calc->resolves_to_angle())) {
|
||||||
|
tokens.discard_a_token(); // calc number/angle
|
||||||
|
return calc;
|
||||||
|
}
|
||||||
|
if (auto dimension = parse_dimension(peek_token); dimension.has_value() && dimension->is_angle()) {
|
||||||
|
tokens.discard_a_token(); // angle
|
||||||
|
return AngleStyleValue::create(dimension->angle());
|
||||||
|
}
|
||||||
|
if (peek_token.is(Token::Type::Ident)) {
|
||||||
|
auto keyword = keyword_from_string(peek_token.token().ident());
|
||||||
|
if (keyword.has_value() && keyword.value() == Keyword::None) {
|
||||||
|
tokens.discard_a_token(); // keyword none
|
||||||
|
return CSSKeywordValue::create(keyword.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/css-color-4/#typedef-color-alpha-value
|
||||||
RefPtr<CSSStyleValue> Parser::parse_solidus_and_alpha_value(TokenStream<ComponentValue>& tokens)
|
RefPtr<CSSStyleValue> Parser::parse_solidus_and_alpha_value(TokenStream<ComponentValue>& tokens)
|
||||||
{
|
{
|
||||||
// [ / [<alpha-value> | none] ]?
|
// [ / [<alpha-value> | none] ]?
|
||||||
|
// <alpha-value> = <number> | <percentage>
|
||||||
// Common to the modern-syntax color functions.
|
// Common to the modern-syntax color functions.
|
||||||
// TODO: Parse `none`
|
|
||||||
|
|
||||||
auto transaction = tokens.begin_transaction();
|
auto transaction = tokens.begin_transaction();
|
||||||
tokens.discard_whitespace();
|
tokens.discard_whitespace();
|
||||||
if (!tokens.consume_a_token().is_delim('/'))
|
if (!tokens.consume_a_token().is_delim('/'))
|
||||||
return {};
|
return {};
|
||||||
tokens.discard_whitespace();
|
tokens.discard_whitespace();
|
||||||
auto alpha = parse_number_percentage_value(tokens);
|
auto alpha = parse_number_percentage_none_value(tokens);
|
||||||
if (!alpha)
|
if (!alpha)
|
||||||
return {};
|
return {};
|
||||||
tokens.discard_whitespace();
|
tokens.discard_whitespace();
|
||||||
|
@ -2692,7 +2739,6 @@ RefPtr<CSSStyleValue> Parser::parse_rgb_color_value(TokenStream<ComponentValue>&
|
||||||
// <modern-rgba-syntax> = rgba(
|
// <modern-rgba-syntax> = rgba(
|
||||||
// [ <number> | <percentage> | none]{3}
|
// [ <number> | <percentage> | none]{3}
|
||||||
// [ / [<alpha-value> | none] ]? )
|
// [ / [<alpha-value> | none] ]? )
|
||||||
// TODO: Handle none values
|
|
||||||
|
|
||||||
auto transaction = outer_tokens.begin_transaction();
|
auto transaction = outer_tokens.begin_transaction();
|
||||||
outer_tokens.discard_whitespace();
|
outer_tokens.discard_whitespace();
|
||||||
|
@ -2709,7 +2755,7 @@ RefPtr<CSSStyleValue> Parser::parse_rgb_color_value(TokenStream<ComponentValue>&
|
||||||
auto inner_tokens = TokenStream { function_token.function().value };
|
auto inner_tokens = TokenStream { function_token.function().value };
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
red = parse_number_percentage_value(inner_tokens);
|
red = parse_number_percentage_none_value(inner_tokens);
|
||||||
if (!red)
|
if (!red)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
@ -2721,6 +2767,10 @@ RefPtr<CSSStyleValue> Parser::parse_rgb_color_value(TokenStream<ComponentValue>&
|
||||||
// | <number>#{3} , <alpha-value>?
|
// | <number>#{3} , <alpha-value>?
|
||||||
// So, r/g/b can be numbers or percentages, as long as they're all the same type.
|
// So, r/g/b can be numbers or percentages, as long as they're all the same type.
|
||||||
|
|
||||||
|
// We accepted the 'none' keyword when parsing the red value, but it's not allowed in the legacy syntax.
|
||||||
|
if (red->is_keyword())
|
||||||
|
return {};
|
||||||
|
|
||||||
inner_tokens.discard_a_token(); // comma
|
inner_tokens.discard_a_token(); // comma
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
|
@ -2770,12 +2820,12 @@ RefPtr<CSSStyleValue> Parser::parse_rgb_color_value(TokenStream<ComponentValue>&
|
||||||
// Modern syntax
|
// Modern syntax
|
||||||
// [ <number> | <percentage> | none]{3} [ / [<alpha-value> | none] ]?
|
// [ <number> | <percentage> | none]{3} [ / [<alpha-value> | none] ]?
|
||||||
|
|
||||||
green = parse_number_percentage_value(inner_tokens);
|
green = parse_number_percentage_none_value(inner_tokens);
|
||||||
if (!green)
|
if (!green)
|
||||||
return {};
|
return {};
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
blue = parse_number_percentage_value(inner_tokens);
|
blue = parse_number_percentage_none_value(inner_tokens);
|
||||||
if (!blue)
|
if (!blue)
|
||||||
return {};
|
return {};
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
@ -2811,7 +2861,6 @@ RefPtr<CSSStyleValue> Parser::parse_hsl_color_value(TokenStream<ComponentValue>&
|
||||||
// [ / [<alpha-value> | none] ]? )
|
// [ / [<alpha-value> | none] ]? )
|
||||||
// <legacy-hsl-syntax> = hsl( <hue>, <percentage>, <percentage>, <alpha-value>? )
|
// <legacy-hsl-syntax> = hsl( <hue>, <percentage>, <percentage>, <alpha-value>? )
|
||||||
// <legacy-hsla-syntax> = hsla( <hue>, <percentage>, <percentage>, <alpha-value>? )
|
// <legacy-hsla-syntax> = hsla( <hue>, <percentage>, <percentage>, <alpha-value>? )
|
||||||
// TODO: Handle none values
|
|
||||||
|
|
||||||
auto transaction = outer_tokens.begin_transaction();
|
auto transaction = outer_tokens.begin_transaction();
|
||||||
outer_tokens.discard_whitespace();
|
outer_tokens.discard_whitespace();
|
||||||
|
@ -2828,7 +2877,7 @@ RefPtr<CSSStyleValue> Parser::parse_hsl_color_value(TokenStream<ComponentValue>&
|
||||||
auto inner_tokens = TokenStream { function_token.function().value };
|
auto inner_tokens = TokenStream { function_token.function().value };
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
h = parse_hue_value(inner_tokens);
|
h = parse_hue_none_value(inner_tokens);
|
||||||
if (!h)
|
if (!h)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
@ -2837,6 +2886,11 @@ RefPtr<CSSStyleValue> Parser::parse_hsl_color_value(TokenStream<ComponentValue>&
|
||||||
if (legacy_syntax) {
|
if (legacy_syntax) {
|
||||||
// Legacy syntax
|
// Legacy syntax
|
||||||
// <hue>, <percentage>, <percentage>, <alpha-value>?
|
// <hue>, <percentage>, <percentage>, <alpha-value>?
|
||||||
|
|
||||||
|
// We accepted the 'none' keyword when parsing the h value, but it's not allowed in the legacy syntax.
|
||||||
|
if (h->is_keyword())
|
||||||
|
return {};
|
||||||
|
|
||||||
(void)inner_tokens.consume_a_token(); // comma
|
(void)inner_tokens.consume_a_token(); // comma
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
|
@ -2876,12 +2930,12 @@ RefPtr<CSSStyleValue> Parser::parse_hsl_color_value(TokenStream<ComponentValue>&
|
||||||
// [<percentage> | <number> | none]
|
// [<percentage> | <number> | none]
|
||||||
// [ / [<alpha-value> | none] ]?
|
// [ / [<alpha-value> | none] ]?
|
||||||
|
|
||||||
s = parse_number_percentage_value(inner_tokens);
|
s = parse_number_percentage_none_value(inner_tokens);
|
||||||
if (!s)
|
if (!s)
|
||||||
return {};
|
return {};
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
l = parse_number_percentage_value(inner_tokens);
|
l = parse_number_percentage_none_value(inner_tokens);
|
||||||
if (!l)
|
if (!l)
|
||||||
return {};
|
return {};
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
@ -2924,17 +2978,17 @@ RefPtr<CSSStyleValue> Parser::parse_hwb_color_value(TokenStream<ComponentValue>&
|
||||||
auto inner_tokens = TokenStream { function_token.function().value };
|
auto inner_tokens = TokenStream { function_token.function().value };
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
h = parse_hue_value(inner_tokens);
|
h = parse_hue_none_value(inner_tokens);
|
||||||
if (!h)
|
if (!h)
|
||||||
return {};
|
return {};
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
w = parse_number_percentage_value(inner_tokens);
|
w = parse_number_percentage_none_value(inner_tokens);
|
||||||
if (!w)
|
if (!w)
|
||||||
return {};
|
return {};
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
b = parse_number_percentage_value(inner_tokens);
|
b = parse_number_percentage_none_value(inner_tokens);
|
||||||
if (!b)
|
if (!b)
|
||||||
return {};
|
return {};
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
@ -2975,17 +3029,17 @@ Optional<Array<RefPtr<CSSStyleValue>, 4>> Parser::parse_lab_like_color_value(Tok
|
||||||
auto inner_tokens = TokenStream { function_token.function().value };
|
auto inner_tokens = TokenStream { function_token.function().value };
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
l = parse_number_percentage_value(inner_tokens);
|
l = parse_number_percentage_none_value(inner_tokens);
|
||||||
if (!l)
|
if (!l)
|
||||||
return OptionalNone {};
|
return OptionalNone {};
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
a = parse_number_percentage_value(inner_tokens);
|
a = parse_number_percentage_none_value(inner_tokens);
|
||||||
if (!a)
|
if (!a)
|
||||||
return OptionalNone {};
|
return OptionalNone {};
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
b = parse_number_percentage_value(inner_tokens);
|
b = parse_number_percentage_none_value(inner_tokens);
|
||||||
if (!b)
|
if (!b)
|
||||||
return OptionalNone {};
|
return OptionalNone {};
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
@ -3062,17 +3116,17 @@ Optional<Array<RefPtr<CSSStyleValue>, 4>> Parser::parse_lch_like_color_value(Tok
|
||||||
auto inner_tokens = TokenStream { function_token.function().value };
|
auto inner_tokens = TokenStream { function_token.function().value };
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
auto l = parse_number_percentage_value(inner_tokens);
|
auto l = parse_number_percentage_none_value(inner_tokens);
|
||||||
if (!l)
|
if (!l)
|
||||||
return OptionalNone {};
|
return OptionalNone {};
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
auto c = parse_number_percentage_value(inner_tokens);
|
auto c = parse_number_percentage_none_value(inner_tokens);
|
||||||
if (!c)
|
if (!c)
|
||||||
return OptionalNone {};
|
return OptionalNone {};
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
|
||||||
auto h = parse_hue_value(inner_tokens);
|
auto h = parse_hue_none_value(inner_tokens);
|
||||||
if (!h)
|
if (!h)
|
||||||
return OptionalNone {};
|
return OptionalNone {};
|
||||||
inner_tokens.discard_whitespace();
|
inner_tokens.discard_whitespace();
|
||||||
|
|
|
@ -247,7 +247,7 @@ private:
|
||||||
OwnPtr<CalculationNode> parse_math_function(PropertyID, Function const&);
|
OwnPtr<CalculationNode> parse_math_function(PropertyID, Function const&);
|
||||||
OwnPtr<CalculationNode> parse_a_calc_function_node(Function const&);
|
OwnPtr<CalculationNode> parse_a_calc_function_node(Function const&);
|
||||||
RefPtr<CSSStyleValue> parse_keyword_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_keyword_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<CSSStyleValue> parse_hue_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_hue_none_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<CSSStyleValue> parse_solidus_and_alpha_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_solidus_and_alpha_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<CSSStyleValue> parse_rgb_color_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_rgb_color_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<CSSStyleValue> parse_hsl_color_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_hsl_color_value(TokenStream<ComponentValue>&);
|
||||||
|
@ -290,6 +290,7 @@ private:
|
||||||
RefPtr<CSSStyleValue> parse_length_percentage_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_length_percentage_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<CSSStyleValue> parse_number_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_number_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<CSSStyleValue> parse_number_percentage_value(TokenStream<ComponentValue>& tokens);
|
RefPtr<CSSStyleValue> parse_number_percentage_value(TokenStream<ComponentValue>& tokens);
|
||||||
|
RefPtr<CSSStyleValue> parse_number_percentage_none_value(TokenStream<ComponentValue>& tokens);
|
||||||
RefPtr<CSSStyleValue> parse_percentage_value(TokenStream<ComponentValue>& tokens);
|
RefPtr<CSSStyleValue> parse_percentage_value(TokenStream<ComponentValue>& tokens);
|
||||||
RefPtr<CSSStyleValue> parse_resolution_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_resolution_value(TokenStream<ComponentValue>&);
|
||||||
RefPtr<CSSStyleValue> parse_time_value(TokenStream<ComponentValue>&);
|
RefPtr<CSSStyleValue> parse_time_value(TokenStream<ComponentValue>&);
|
||||||
|
|
Loading…
Add table
Reference in a new issue