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:
parent
d8c6b872a3
commit
9415bffd9b
Notes:
github-actions[bot]
2025-05-15 08:54:31 +00:00
Author: https://github.com/AtkinsSJ
Commit: 9415bffd9b
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4735
6 changed files with 114 additions and 23 deletions
|
@ -137,6 +137,13 @@
|
|||
"syntax": [
|
||||
"<'margin-top'>"
|
||||
]
|
||||
},
|
||||
"size": {
|
||||
"initial": "auto",
|
||||
"FIXME": "Replace with actual syntax once we parse grammar properly",
|
||||
"syntax": [
|
||||
"<page-size>"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -481,6 +481,18 @@
|
|||
"scroll",
|
||||
"visible"
|
||||
],
|
||||
"page-size": [
|
||||
"a5",
|
||||
"a4",
|
||||
"a3",
|
||||
"b5",
|
||||
"b4",
|
||||
"jis-b5",
|
||||
"jis-b4",
|
||||
"letter",
|
||||
"legal",
|
||||
"ledger"
|
||||
],
|
||||
"pointer-events": [
|
||||
"auto",
|
||||
"all",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue