1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-09 09:34:57 +09:00

LibWeb/CSS: Parse @page size descriptor

This commit is contained in:
Sam Atkins 2025-05-14 15:07:58 +01:00
parent d8c6b872a3
commit 9415bffd9b
Notes: github-actions[bot] 2025-05-15 08:54:31 +00:00
6 changed files with 114 additions and 23 deletions

View file

@ -137,6 +137,13 @@
"syntax": [
"<'margin-top'>"
]
},
"size": {
"initial": "auto",
"FIXME": "Replace with actual syntax once we parse grammar properly",
"syntax": [
"<page-size>"
]
}
}
},

View file

@ -481,6 +481,18 @@
"scroll",
"visible"
],
"page-size": [
"a5",
"a4",
"a3",
"b5",
"b4",
"jis-b5",
"jis-b4",
"letter",
"legal",
"ledger"
],
"pointer-events": [
"auto",
"all",

View file

@ -60,6 +60,9 @@
"-libweb-palette-window",
"-libweb-palette-window-text",
"-libweb-right",
"a3",
"a4",
"a5",
"absolute",
"accentcolor",
"accentcolortext",
@ -82,6 +85,8 @@
"appworkspace",
"auto",
"auto-add",
"b4",
"b5",
"back",
"background",
"backwards",
@ -120,8 +125,8 @@
"col-resize",
"collapse",
"color",
"color-dodge",
"color-burn",
"color-dodge",
"column",
"column-reverse",
"common-ligatures",
@ -150,9 +155,9 @@
"diagonal-fractions",
"difference",
"disc",
"discretionary-ligatures",
"disclosure-closed",
"disclosure-open",
"discretionary-ligatures",
"distribute",
"dotted",
"double",
@ -243,6 +248,8 @@
"isolate",
"isolate-override",
"italic",
"jis-b4",
"jis-b5",
"jis04",
"jis78",
"jis83",
@ -258,12 +265,15 @@
"larger",
"layout",
"lch",
"ledger",
"left",
"legacy",
"legal",
"less",
"letter",
"light",
"lighter",
"lighten",
"lighter",
"line-through",
"linear",
"lining-nums",
@ -469,12 +479,12 @@
"textfield",
"thick",
"thin",
"titling-caps",
"threeddarkshadow",
"threedface",
"threedhighlight",
"threedlightshadow",
"threedshadow",
"titling-caps",
"to-zero",
"top",
"traditional",

View file

@ -7,6 +7,7 @@
#include <LibWeb/CSS/Parser/Parser.h>
#include <LibWeb/CSS/StyleValues/CSSKeywordValue.h>
#include <LibWeb/CSS/StyleValues/FontSourceStyleValue.h>
#include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
#include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
#include <LibWeb/CSS/StyleValues/StringStyleValue.h>
#include <LibWeb/CSS/StyleValues/StyleValueList.h>
@ -83,12 +84,69 @@ Parser::ParseErrorOr<NonnullRefPtr<CSSStyleValue const>> Parser::parse_descripto
return nullptr;
return StyleValueList::create(move(valid_sources), StyleValueList::Separator::Comma);
}
case DescriptorMetadata::ValueType::OptionalDeclarationValue:
case DescriptorMetadata::ValueType::OptionalDeclarationValue: {
// `component_values` already has what we want. Just skip through its tokens so code below knows we consumed them.
while (tokens.has_next_token())
tokens.discard_a_token();
return UnresolvedStyleValue::create(move(component_values), false, {});
case DescriptorMetadata::ValueType::PositivePercentage:
}
case DescriptorMetadata::ValueType::PageSize: {
// https://drafts.csswg.org/css-page-3/#page-size-prop
// <length [0,∞]>{1,2} | auto | [ <page-size> || [ portrait | landscape ] ]
// auto
if (auto value = parse_all_as_single_keyword_value(tokens, Keyword::Auto))
return value.release_nonnull();
// <length [0,∞]>{1,2}
if (auto first_length = parse_length_value(tokens)) {
if (first_length->is_length() && first_length->as_length().length().raw_value() < 0)
return nullptr;
if (auto second_length = parse_length_value(tokens)) {
if (second_length->is_length() && second_length->as_length().length().raw_value() < 0)
return nullptr;
return StyleValueList::create(StyleValueVector { first_length.release_nonnull(), second_length.release_nonnull() }, StyleValueList::Separator::Space);
}
return first_length.release_nonnull();
}
// [ <page-size> || [ portrait | landscape ] ]
RefPtr<CSSStyleValue const> page_size;
RefPtr<CSSStyleValue const> orientation;
if (auto first_keyword = parse_keyword_value(tokens)) {
if (first_is_one_of(first_keyword->to_keyword(), Keyword::Landscape, Keyword::Portrait)) {
orientation = first_keyword.release_nonnull();
} else if (keyword_to_page_size(first_keyword->to_keyword()).has_value()) {
page_size = first_keyword.release_nonnull();
} else {
return nullptr;
}
} else {
return nullptr;
}
if (auto second_keyword = parse_keyword_value(tokens)) {
if (orientation.is_null() && first_is_one_of(second_keyword->to_keyword(), Keyword::Landscape, Keyword::Portrait)) {
orientation = second_keyword.release_nonnull();
} else if (page_size.is_null() && keyword_to_page_size(second_keyword->to_keyword()).has_value()) {
page_size = second_keyword.release_nonnull();
} else {
return nullptr;
}
// Portrait is considered the default orientation, so don't include it.
if (orientation->to_keyword() == Keyword::Portrait)
return page_size.release_nonnull();
return StyleValueList::create(StyleValueVector { page_size.release_nonnull(), orientation.release_nonnull() }, StyleValueList::Separator::Space);
}
return page_size ? page_size.release_nonnull() : orientation.release_nonnull();
}
case DescriptorMetadata::ValueType::PositivePercentage: {
if (auto percentage_value = parse_percentage_value(tokens)) {
if (percentage_value->is_percentage()) {
if (percentage_value->as_percentage().value() < 0)
@ -104,13 +162,15 @@ Parser::ParseErrorOr<NonnullRefPtr<CSSStyleValue const>> Parser::parse_descripto
}
}
return nullptr;
}
case DescriptorMetadata::ValueType::String:
return parse_string_value(tokens);
case DescriptorMetadata::ValueType::UnicodeRangeTokens:
case DescriptorMetadata::ValueType::UnicodeRangeTokens: {
return parse_comma_separated_value_list(tokens, [this](auto& tokens) -> RefPtr<CSSStyleValue const> {
return parse_unicode_range_value(tokens);
});
}
}
return nullptr;
});
if (!parsed_style_value || tokens.has_next_token())

View file

@ -121,6 +121,7 @@ struct DescriptorMetadata {
FamilyName,
FontSrcList,
OptionalDeclarationValue,
PageSize,
PositivePercentage,
String,
UnicodeRangeTokens,
@ -386,6 +387,8 @@ DescriptorMetadata get_descriptor_metadata(AtRuleID at_rule_id, DescriptorID des
return "FontSrcList"_string;
if (syntax_string == "<declaration-value>?"sv)
return "OptionalDeclarationValue"_string;
if (syntax_string == "<page-size>"sv)
return "PageSize"_string;
if (syntax_string == "<percentage [0,∞]>"sv)
return "PositivePercentage"_string;
if (syntax_string == "<string>"sv)

View file

@ -2,20 +2,19 @@ Harness status: OK
Found 15 tests
1 Pass
14 Fail
15 Pass
Pass Test setup
Fail size: 640px 480px
Fail size: 8.5in 11in
Fail size: 3in 10in
Fail size: auto
Fail size: a5
Fail size: a4
Fail size: a3
Fail size: b5
Fail size: b4
Fail size: jis-b5
Fail size: jis-b4
Fail size: landscape
Fail size: letter
Fail size: legal landscape
Pass size: 640px 480px
Pass size: 8.5in 11in
Pass size: 3in 10in
Pass size: auto
Pass size: a5
Pass size: a4
Pass size: a3
Pass size: b5
Pass size: b4
Pass size: jis-b5
Pass size: jis-b4
Pass size: landscape
Pass size: letter
Pass size: legal landscape