mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-08 06:09:58 +00:00
LibWeb: Parse the position-area property
This commit is contained in:
parent
12bb266bf2
commit
eb571a1a46
Notes:
github-actions[bot]
2025-09-29 07:54:33 +00:00
Author: https://github.com/tcl3
Commit: eb571a1a46
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6335
Reviewed-by: https://github.com/gmta ✅
12 changed files with 2733 additions and 0 deletions
|
|
@ -601,6 +601,58 @@
|
|||
"lch",
|
||||
"oklch"
|
||||
],
|
||||
"position-area": [
|
||||
"left",
|
||||
"center",
|
||||
"right",
|
||||
"span-left",
|
||||
"span-right",
|
||||
"x-start",
|
||||
"x-end",
|
||||
"span-x-start",
|
||||
"span-x-end",
|
||||
"x-self-start",
|
||||
"x-self-end",
|
||||
"span-x-self-start",
|
||||
"span-x-self-end",
|
||||
"span-all",
|
||||
"top",
|
||||
"bottom",
|
||||
"span-top",
|
||||
"span-bottom",
|
||||
"y-start",
|
||||
"y-end",
|
||||
"span-y-start",
|
||||
"span-y-end",
|
||||
"y-self-start",
|
||||
"y-self-end",
|
||||
"span-y-self-start",
|
||||
"span-y-self-end",
|
||||
"block-start",
|
||||
"block-end",
|
||||
"span-block-start",
|
||||
"span-block-end",
|
||||
"inline-start",
|
||||
"inline-end",
|
||||
"span-inline-start",
|
||||
"span-inline-end",
|
||||
"self-block-start",
|
||||
"self-block-end",
|
||||
"span-self-block-start",
|
||||
"span-self-block-end",
|
||||
"self-inline-start",
|
||||
"self-inline-end",
|
||||
"span-self-inline-start",
|
||||
"span-self-inline-end",
|
||||
"start",
|
||||
"end",
|
||||
"span-start",
|
||||
"span-end",
|
||||
"self-start",
|
||||
"self-end",
|
||||
"span-self-start",
|
||||
"span-self-end"
|
||||
],
|
||||
"position-edge": [
|
||||
"center",
|
||||
"left",
|
||||
|
|
|
|||
|
|
@ -100,6 +100,8 @@
|
|||
"bidi-override",
|
||||
"blink",
|
||||
"block",
|
||||
"block-end",
|
||||
"block-start",
|
||||
"bold",
|
||||
"bolder",
|
||||
"border-box",
|
||||
|
|
@ -460,8 +462,12 @@
|
|||
"selecteditem",
|
||||
"selecteditemtext",
|
||||
"self-block",
|
||||
"self-block-end",
|
||||
"self-block-start",
|
||||
"self-end",
|
||||
"self-inline",
|
||||
"self-inline-end",
|
||||
"self-inline-start",
|
||||
"self-start",
|
||||
"semi-condensed",
|
||||
"semi-expanded",
|
||||
|
|
@ -486,6 +492,31 @@
|
|||
"space-around",
|
||||
"space-between",
|
||||
"space-evenly",
|
||||
"span-all",
|
||||
"span-block-end",
|
||||
"span-block-start",
|
||||
"span-bottom",
|
||||
"span-end",
|
||||
"span-inline-end",
|
||||
"span-inline-start",
|
||||
"span-left",
|
||||
"span-right",
|
||||
"span-self-block-end",
|
||||
"span-self-block-start",
|
||||
"span-self-end",
|
||||
"span-self-inline-end",
|
||||
"span-self-inline-start",
|
||||
"span-self-start",
|
||||
"span-start",
|
||||
"span-top",
|
||||
"span-x-end",
|
||||
"span-x-self-end",
|
||||
"span-x-self-start",
|
||||
"span-x-start",
|
||||
"span-y-end",
|
||||
"span-y-self-end",
|
||||
"span-y-self-start",
|
||||
"span-y-start",
|
||||
"spelling-error",
|
||||
"square",
|
||||
"square-button",
|
||||
|
|
@ -573,11 +604,19 @@
|
|||
"windowtext",
|
||||
"wrap",
|
||||
"wrap-reverse",
|
||||
"x-end",
|
||||
"x-large",
|
||||
"x-self-end",
|
||||
"x-self-start",
|
||||
"x-start",
|
||||
"x-small",
|
||||
"xx-large",
|
||||
"xx-small",
|
||||
"xxx-large",
|
||||
"y-end",
|
||||
"y-self-end",
|
||||
"y-self-start",
|
||||
"y-start",
|
||||
"zoom-in",
|
||||
"zoom-out"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -462,6 +462,7 @@ private:
|
|||
RefPtr<StyleValue const> parse_place_content_value(TokenStream<ComponentValue>&);
|
||||
RefPtr<StyleValue const> parse_place_items_value(TokenStream<ComponentValue>&);
|
||||
RefPtr<StyleValue const> parse_place_self_value(TokenStream<ComponentValue>&);
|
||||
RefPtr<StyleValue const> parse_position_area_value(TokenStream<ComponentValue>&);
|
||||
RefPtr<StyleValue const> parse_quotes_value(TokenStream<ComponentValue>&);
|
||||
RefPtr<StyleValue const> parse_single_repeat_style_value(PropertyID, TokenStream<ComponentValue>&);
|
||||
RefPtr<StyleValue const> parse_scrollbar_color_value(TokenStream<ComponentValue>&);
|
||||
|
|
|
|||
|
|
@ -734,6 +734,11 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue const>> Parser::parse_css_value(Pr
|
|||
if (auto parsed_value = parse_place_self_value(tokens); parsed_value && !tokens.has_next_token())
|
||||
return parsed_value.release_nonnull();
|
||||
return ParseError::SyntaxError;
|
||||
case PropertyID::PositionArea:
|
||||
if (auto parsed_value = parse_position_area_value(tokens); parsed_value && !tokens.has_next_token())
|
||||
return parsed_value.release_nonnull();
|
||||
return ParseError::SyntaxError;
|
||||
|
||||
case PropertyID::Quotes:
|
||||
if (auto parsed_value = parse_quotes_value(tokens); parsed_value && !tokens.has_next_token())
|
||||
return parsed_value.release_nonnull();
|
||||
|
|
@ -4157,6 +4162,255 @@ RefPtr<StyleValue const> Parser::parse_place_self_value(TokenStream<ComponentVal
|
|||
{ *maybe_align_self_value, *maybe_justify_self_value });
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-anchor-position/#position-area
|
||||
RefPtr<StyleValue const> Parser::parse_position_area_value(TokenStream<ComponentValue>& tokens)
|
||||
{
|
||||
// none | <position-area>
|
||||
|
||||
// none
|
||||
if (auto none_keyword_value = parse_all_as_single_keyword_value(tokens, Keyword::None))
|
||||
return none_keyword_value;
|
||||
|
||||
// <position-area>
|
||||
// https://drafts.csswg.org/css-anchor-position/#position-area-syntax
|
||||
// <position-area> = [
|
||||
// [ left | center | right | span-left | span-right
|
||||
// | x-start | x-end | span-x-start | span-x-end
|
||||
// | x-self-start | x-self-end | span-x-self-start | span-x-self-end
|
||||
// | span-all ]
|
||||
// ||
|
||||
// [ top | center | bottom | span-top | span-bottom
|
||||
// | y-start | y-end | span-y-start | span-y-end
|
||||
// | y-self-start | y-self-end | span-y-self-start | span-y-self-end
|
||||
// | span-all ]
|
||||
// |
|
||||
// [ block-start | center | block-end | span-block-start | span-block-end | span-all ]
|
||||
// ||
|
||||
// [ inline-start | center | inline-end | span-inline-start | span-inline-end
|
||||
// | span-all ]
|
||||
// |
|
||||
// [ self-block-start | center | self-block-end | span-self-block-start
|
||||
// | span-self-block-end | span-all ]
|
||||
// ||
|
||||
// [ self-inline-start | center | self-inline-end | span-self-inline-start
|
||||
// | span-self-inline-end | span-all ]
|
||||
// |
|
||||
// [ start | center | end | span-start | span-end | span-all ]{1,2}
|
||||
// |
|
||||
// [ self-start | center | self-end | span-self-start | span-self-end | span-all ]{1,2}
|
||||
// ]
|
||||
auto is_x_keyword = [](Keyword keyword) -> bool {
|
||||
switch (keyword) {
|
||||
case Keyword::Left:
|
||||
case Keyword::Center:
|
||||
case Keyword::Right:
|
||||
case Keyword::SpanLeft:
|
||||
case Keyword::SpanRight:
|
||||
case Keyword::XStart:
|
||||
case Keyword::XEnd:
|
||||
case Keyword::SpanXStart:
|
||||
case Keyword::SpanXEnd:
|
||||
case Keyword::XSelfStart:
|
||||
case Keyword::XSelfEnd:
|
||||
case Keyword::SpanXSelfStart:
|
||||
case Keyword::SpanXSelfEnd:
|
||||
case Keyword::SpanAll:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto is_y_keyword = [](Keyword keyword) -> bool {
|
||||
switch (keyword) {
|
||||
case Keyword::Top:
|
||||
case Keyword::Center:
|
||||
case Keyword::Bottom:
|
||||
case Keyword::SpanTop:
|
||||
case Keyword::SpanBottom:
|
||||
case Keyword::YStart:
|
||||
case Keyword::YEnd:
|
||||
case Keyword::SpanYStart:
|
||||
case Keyword::SpanYEnd:
|
||||
case Keyword::YSelfStart:
|
||||
case Keyword::YSelfEnd:
|
||||
case Keyword::SpanYSelfStart:
|
||||
case Keyword::SpanYSelfEnd:
|
||||
case Keyword::SpanAll:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto is_block_keyword = [](Keyword keyword) -> bool {
|
||||
switch (keyword) {
|
||||
case Keyword::BlockStart:
|
||||
case Keyword::Center:
|
||||
case Keyword::BlockEnd:
|
||||
case Keyword::SpanBlockStart:
|
||||
case Keyword::SpanBlockEnd:
|
||||
case Keyword::SpanAll:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto is_inline_keyword = [](Keyword keyword) -> bool {
|
||||
switch (keyword) {
|
||||
case Keyword::InlineStart:
|
||||
case Keyword::Center:
|
||||
case Keyword::InlineEnd:
|
||||
case Keyword::SpanInlineStart:
|
||||
case Keyword::SpanInlineEnd:
|
||||
case Keyword::SpanAll:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto is_self_block_keyword = [](Keyword keyword) -> bool {
|
||||
switch (keyword) {
|
||||
case Keyword::SelfBlockStart:
|
||||
case Keyword::Center:
|
||||
case Keyword::SelfBlockEnd:
|
||||
case Keyword::SpanSelfBlockStart:
|
||||
case Keyword::SpanSelfBlockEnd:
|
||||
case Keyword::SpanAll:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto is_self_inline_keyword = [](Keyword keyword) -> bool {
|
||||
switch (keyword) {
|
||||
case Keyword::SelfInlineStart:
|
||||
case Keyword::Center:
|
||||
case Keyword::SelfInlineEnd:
|
||||
case Keyword::SpanSelfInlineStart:
|
||||
case Keyword::SpanSelfInlineEnd:
|
||||
case Keyword::SpanAll:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto is_start_end_keyword = [](Keyword keyword) -> bool {
|
||||
switch (keyword) {
|
||||
case Keyword::Start:
|
||||
case Keyword::Center:
|
||||
case Keyword::End:
|
||||
case Keyword::SpanStart:
|
||||
case Keyword::SpanEnd:
|
||||
case Keyword::SpanAll:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto is_self_start_end_keyword = [](Keyword keyword) -> bool {
|
||||
switch (keyword) {
|
||||
case Keyword::SelfStart:
|
||||
case Keyword::Center:
|
||||
case Keyword::SelfEnd:
|
||||
case Keyword::SpanSelfStart:
|
||||
case Keyword::SpanSelfEnd:
|
||||
case Keyword::SpanAll:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto is_axis_ambiguous = [](Keyword keyword) -> bool {
|
||||
switch (keyword) {
|
||||
case Keyword::Center:
|
||||
case Keyword::SpanAll:
|
||||
case Keyword::Start:
|
||||
case Keyword::End:
|
||||
case Keyword::SelfStart:
|
||||
case Keyword::SelfEnd:
|
||||
case Keyword::SpanStart:
|
||||
case Keyword::SpanEnd:
|
||||
case Keyword::SpanSelfStart:
|
||||
case Keyword::SpanSelfEnd:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto transaction = tokens.begin_transaction();
|
||||
auto create_keyword_list = [&](StyleValue const& first, StyleValue const& second) -> NonnullRefPtr<StyleValue const> {
|
||||
transaction.commit();
|
||||
|
||||
// If only a single keyword is given, it behaves as if the second keyword is span-all if the given keyword is
|
||||
// unambigous about its axis.
|
||||
// These conditions ensure the span-all keyword is omitted when it would be implied.
|
||||
if (!is_axis_ambiguous(first.as_keyword().keyword()) && second.as_keyword().keyword() == Keyword::SpanAll)
|
||||
return first;
|
||||
if (!is_axis_ambiguous(second.as_keyword().keyword()) && first.as_keyword().keyword() == Keyword::SpanAll)
|
||||
return second;
|
||||
|
||||
return StyleValueList::create({ first, second }, StyleValueList::Separator::Space);
|
||||
};
|
||||
|
||||
auto first_keyword_value = parse_keyword_value(tokens);
|
||||
if (!first_keyword_value)
|
||||
return nullptr;
|
||||
|
||||
tokens.discard_whitespace();
|
||||
if (!tokens.has_next_token()) {
|
||||
auto first_position_area_keyword = keyword_to_position_area(first_keyword_value->as_keyword().keyword());
|
||||
if (!first_position_area_keyword.has_value())
|
||||
return nullptr;
|
||||
transaction.commit();
|
||||
return first_keyword_value;
|
||||
}
|
||||
auto second_keyword_value = parse_keyword_value(tokens);
|
||||
if (!second_keyword_value)
|
||||
return nullptr;
|
||||
|
||||
auto first_keyword = first_keyword_value->as_keyword().keyword();
|
||||
auto second_keyword = second_keyword_value->as_keyword().keyword();
|
||||
|
||||
if (is_x_keyword(first_keyword) && is_y_keyword(second_keyword))
|
||||
return create_keyword_list(*first_keyword_value, *second_keyword_value);
|
||||
if (is_y_keyword(first_keyword) && is_x_keyword(second_keyword))
|
||||
return create_keyword_list(*second_keyword_value, *first_keyword_value);
|
||||
|
||||
if (is_block_keyword(first_keyword) && is_inline_keyword(second_keyword))
|
||||
return create_keyword_list(*first_keyword_value, *second_keyword_value);
|
||||
if (is_inline_keyword(first_keyword) && is_block_keyword(second_keyword))
|
||||
return create_keyword_list(*second_keyword_value, *first_keyword_value);
|
||||
|
||||
if (is_self_block_keyword(first_keyword) && is_self_inline_keyword(second_keyword))
|
||||
return create_keyword_list(*first_keyword_value, *second_keyword_value);
|
||||
if (is_self_inline_keyword(first_keyword) && is_self_block_keyword(second_keyword))
|
||||
return create_keyword_list(*second_keyword_value, *first_keyword_value);
|
||||
|
||||
if (is_start_end_keyword(first_keyword) && is_start_end_keyword(second_keyword))
|
||||
return create_keyword_list(*first_keyword_value, *second_keyword_value);
|
||||
if (is_self_start_end_keyword(first_keyword) && is_self_start_end_keyword(second_keyword))
|
||||
return create_keyword_list(*first_keyword_value, *second_keyword_value);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<StyleValue const> Parser::parse_quotes_value(TokenStream<ComponentValue>& tokens)
|
||||
{
|
||||
// https://www.w3.org/TR/css-content-3/#quotes-property
|
||||
|
|
|
|||
|
|
@ -3010,6 +3010,18 @@
|
|||
"positioning"
|
||||
]
|
||||
},
|
||||
"position-area": {
|
||||
"animation-type": "discrete",
|
||||
"__comment": "Animation type is currently listed as TBD in the specification",
|
||||
"inherited": false,
|
||||
"initial": "none",
|
||||
"valid-types": [
|
||||
"position-area"
|
||||
],
|
||||
"valid-identifiers": [
|
||||
"none"
|
||||
]
|
||||
},
|
||||
"quotes": {
|
||||
"animation-type": "discrete",
|
||||
"inherited": true,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue