mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-06 11:09:05 +03:00
LibWeb: Parse and compute CSS quotes
property
This commit is contained in:
parent
1bc081398e
commit
dc7a52957e
Notes:
sideshowbarker
2024-07-17 09:39:38 +09:00
Author: https://github.com/AtkinsSJ Commit: https://github.com/SerenityOS/serenity/commit/dc7a52957e Pull-request: https://github.com/SerenityOS/serenity/pull/21046 Reviewed-by: https://github.com/ADKaster ✅
@ -38,6 +38,15 @@ struct GridAutoFlow {
|
||||
bool dense { false };
|
||||
};
|
||||
|
||||
struct QuotesData {
|
||||
enum class Type {
|
||||
None,
|
||||
Auto,
|
||||
Specified,
|
||||
} type;
|
||||
Vector<Array<String, 2>> strings {};
|
||||
};
|
||||
|
||||
class InitialValues {
|
||||
public:
|
||||
static AspectRatio aspect_ratio() { return AspectRatio { true, {} }; }
|
||||
@ -120,6 +129,7 @@ public:
|
||||
static CSS::OutlineStyle outline_style() { return CSS::OutlineStyle::None; }
|
||||
static CSS::Length outline_width() { return CSS::Length::make_px(3); }
|
||||
static CSS::TableLayout table_layout() { return CSS::TableLayout::Auto; }
|
||||
static QuotesData quotes() { return QuotesData { .type = QuotesData::Type::Auto }; }
|
||||
|
||||
static CSS::MathShift math_shift() { return CSS::MathShift::Normal; }
|
||||
static CSS::MathStyle math_style() { return CSS::MathStyle::Normal; }
|
||||
@ -350,6 +360,8 @@ public:
|
||||
|
||||
CSS::TableLayout table_layout() const { return m_noninherited.table_layout; }
|
||||
|
||||
CSS::QuotesData quotes() const { return m_inherited.quotes; }
|
||||
|
||||
CSS::MathShift math_shift() const { return m_inherited.math_shift; }
|
||||
CSS::MathStyle math_style() const { return m_inherited.math_style; }
|
||||
int math_depth() const { return m_inherited.math_depth; }
|
||||
@ -383,6 +395,7 @@ protected:
|
||||
CSS::ListStyleType list_style_type { InitialValues::list_style_type() };
|
||||
CSS::ListStylePosition list_style_position { InitialValues::list_style_position() };
|
||||
CSS::Visibility visibility { InitialValues::visibility() };
|
||||
CSS::QuotesData quotes { InitialValues::quotes() };
|
||||
|
||||
Optional<SVGPaint> fill;
|
||||
CSS::FillRule fill_rule { InitialValues::fill_rule() };
|
||||
@ -577,6 +590,7 @@ public:
|
||||
void set_grid_auto_flow(CSS::GridAutoFlow grid_auto_flow) { m_noninherited.grid_auto_flow = grid_auto_flow; }
|
||||
void set_transition_delay(CSS::Time const& transition_delay) { m_noninherited.transition_delay = transition_delay; }
|
||||
void set_table_layout(CSS::TableLayout value) { m_noninherited.table_layout = value; }
|
||||
void set_quotes(CSS::QuotesData value) { m_inherited.quotes = value; }
|
||||
|
||||
void set_fill(SVGPaint value) { m_inherited.fill = value; }
|
||||
void set_stroke(SVGPaint value) { m_inherited.stroke = value; }
|
||||
|
@ -4586,6 +4586,35 @@ RefPtr<StyleValue> Parser::parse_place_self_value(Vector<ComponentValue> const&
|
||||
return PlaceItemsStyleValue::create(*maybe_align_self_value, *maybe_justify_self_value);
|
||||
}
|
||||
|
||||
RefPtr<StyleValue> Parser::parse_quotes_value(Vector<ComponentValue> const& component_values)
|
||||
{
|
||||
// https://www.w3.org/TR/css-content-3/#quotes-property
|
||||
// auto | none | [ <string> <string> ]+
|
||||
|
||||
if (component_values.size() == 1) {
|
||||
auto identifier = parse_identifier_value(component_values.first());
|
||||
if (identifier && property_accepts_identifier(PropertyID::Quotes, identifier->to_identifier()))
|
||||
return identifier;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Parse an even number of <string> values.
|
||||
if (component_values.size() % 2 != 0)
|
||||
return nullptr;
|
||||
|
||||
auto tokens = TokenStream { component_values };
|
||||
StyleValueVector string_values;
|
||||
while (tokens.has_next_token()) {
|
||||
auto maybe_string = parse_string_value(tokens.next_token());
|
||||
if (!maybe_string)
|
||||
return nullptr;
|
||||
|
||||
string_values.append(maybe_string.release_nonnull());
|
||||
}
|
||||
|
||||
return StyleValueList::create(move(string_values), StyleValueList::Separator::Space);
|
||||
}
|
||||
|
||||
RefPtr<StyleValue> Parser::parse_text_decoration_value(Vector<ComponentValue> const& component_values)
|
||||
{
|
||||
RefPtr<StyleValue> decoration_line;
|
||||
@ -5869,6 +5898,10 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue>> Parser::parse_css_value(Property
|
||||
if (auto parsed_value = parse_place_self_value(component_values))
|
||||
return parsed_value.release_nonnull();
|
||||
return ParseError::SyntaxError;
|
||||
case PropertyID::Quotes:
|
||||
if (auto parsed_value = parse_quotes_value(component_values))
|
||||
return parsed_value.release_nonnull();
|
||||
return ParseError::SyntaxError;
|
||||
case PropertyID::TextDecoration:
|
||||
if (auto parsed_value = parse_text_decoration_value(component_values))
|
||||
return parsed_value.release_nonnull();
|
||||
|
@ -243,6 +243,7 @@ private:
|
||||
RefPtr<StyleValue> parse_place_content_value(Vector<ComponentValue> const&);
|
||||
RefPtr<StyleValue> parse_place_items_value(Vector<ComponentValue> const&);
|
||||
RefPtr<StyleValue> parse_place_self_value(Vector<ComponentValue> const&);
|
||||
RefPtr<StyleValue> parse_quotes_value(Vector<ComponentValue> const&);
|
||||
enum class AllowInsetKeyword {
|
||||
No,
|
||||
Yes,
|
||||
|
@ -1836,6 +1836,17 @@
|
||||
"position"
|
||||
]
|
||||
},
|
||||
"quotes": {
|
||||
"inherited": true,
|
||||
"initial": "auto",
|
||||
"valid-types": [
|
||||
"string"
|
||||
],
|
||||
"valid-identifiers": [
|
||||
"auto",
|
||||
"none"
|
||||
]
|
||||
},
|
||||
"right": {
|
||||
"inherited": false,
|
||||
"initial": "auto",
|
||||
|
@ -990,4 +990,32 @@ void StyleProperties::set_math_depth(int math_depth)
|
||||
set_property(PropertyID::MathDepth, MathDepthStyleValue::create_integer(IntegerStyleValue::create(math_depth)));
|
||||
}
|
||||
|
||||
QuotesData StyleProperties::quotes() const
|
||||
{
|
||||
auto value = property(CSS::PropertyID::Quotes);
|
||||
if (value->is_identifier()) {
|
||||
switch (value->to_identifier()) {
|
||||
case ValueID::Auto:
|
||||
return QuotesData { .type = QuotesData::Type::Auto };
|
||||
case ValueID::None:
|
||||
return QuotesData { .type = QuotesData::Type::None };
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (value->is_value_list()) {
|
||||
auto& value_list = value->as_value_list();
|
||||
QuotesData quotes_data { .type = QuotesData::Type::Specified };
|
||||
VERIFY(value_list.size() % 2 == 0);
|
||||
for (auto i = 0u; i < value_list.size(); i += 2) {
|
||||
quotes_data.strings.empend(
|
||||
value_list.value_at(i, false)->as_string().string_value(),
|
||||
value_list.value_at(i + 1, false)->as_string().string_value());
|
||||
}
|
||||
return quotes_data;
|
||||
}
|
||||
|
||||
return InitialValues::quotes();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -146,6 +146,8 @@ public:
|
||||
void set_math_depth(int math_depth);
|
||||
int math_depth() const { return m_math_depth; }
|
||||
|
||||
QuotesData quotes() const;
|
||||
|
||||
static NonnullRefPtr<Gfx::Font const> font_fallback(bool monospace, bool bold);
|
||||
|
||||
private:
|
||||
|
@ -806,6 +806,7 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style)
|
||||
computed_values.set_math_style(math_style.value());
|
||||
|
||||
computed_values.set_math_depth(computed_style.math_depth());
|
||||
computed_values.set_quotes(computed_style.quotes());
|
||||
|
||||
// Update any anonymous children that inherit from this node.
|
||||
// FIXME: This is pretty hackish. It would be nicer if they shared the inherited style
|
||||
|
Loading…
Reference in New Issue
Block a user