mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-29 08:11:13 +00:00
LibWeb: Implement and use OverflowStyleValue
Also added a test page for the `overflow` properties. They apparently don't work, but at least they do parse.
This commit is contained in:
parent
168865dbdc
commit
e6c0cb5a7f
Notes:
sideshowbarker
2024-07-18 06:58:35 +09:00
Author: https://github.com/AtkinsSJ Commit: https://github.com/SerenityOS/serenity/commit/e6c0cb5a7f5 Pull-request: https://github.com/SerenityOS/serenity/pull/9301 Reviewed-by: https://github.com/TobyAsE
180
Base/res/html/misc/overflow.html
Normal file
180
Base/res/html/misc/overflow.html
Normal file
|
@ -0,0 +1,180 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<title>CSS Overflow Test</title>
|
||||
<style>
|
||||
.box {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
border: 1px solid red;
|
||||
}
|
||||
.box h1 {
|
||||
width: 2000px;
|
||||
}
|
||||
.box p {
|
||||
width: 2000px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Single-value 'overflow' property</h1>
|
||||
|
||||
<h2>Overflow: inherit</h2>
|
||||
<div class="box" style="overflow: inherit;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
|
||||
<h2>Overflow: initial</h2>
|
||||
<div class="box" style="overflow: initial;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
|
||||
<h2>Overflow: auto</h2>
|
||||
<div class="box" style="overflow: auto;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
|
||||
<h2>Overflow: clip</h2>
|
||||
<div class="box" style="overflow: clip;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
|
||||
<h2>Overflow: hidden</h2>
|
||||
<div class="box" style="overflow: hidden;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
|
||||
<h2>Overflow: scroll</h2>
|
||||
<div class="box" style="overflow: scroll;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
|
||||
<h2>Overflow: visible</h2>
|
||||
<div class="box" style="overflow: visible;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
|
||||
<h1>Two-value 'overflow' property</h1>
|
||||
|
||||
<h2>Overflow: auto hidden</h2>
|
||||
<div class="box" style="overflow: auto hidden;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
|
||||
<h2>Overflow: hidden auto</h2>
|
||||
<div class="box" style="overflow: hidden auto;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
|
||||
<h2>Overflow: scroll clip</h2>
|
||||
<div class="box" style="overflow: scroll clip;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
|
||||
<h2>Overflow: clip scroll</h2>
|
||||
<div class="box" style="overflow: clip scroll;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
|
||||
<h2>Overflow: visible hidden</h2>
|
||||
<div class="box" style="overflow: visible hidden;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
|
||||
<h1>Separate 'overflow-x' / 'overflow-y' property</h1>
|
||||
|
||||
<h2>overflow-x: auto, overflow-y: hidden</h2>
|
||||
<div class="box" style="overflow-x: auto; overflow-y: hidden;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
|
||||
<h2>overflow-x: hidden, overflow-y: auto</h2>
|
||||
<div class="box" style="overflow-x: hidden; overflow-y: auto;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
|
||||
<h2>overflow-x: scroll, overflow-y: clip</h2>
|
||||
<div class="box" style="overflow-x: scroll; overflow-y: clip;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
|
||||
<h2>overflow-y: scroll</h2>
|
||||
<div class="box" style="overflow-y: scroll;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
|
||||
<h2>overflow-x: visible</h2>
|
||||
<div class="box" style="overflow-x: visible;">
|
||||
<h1>Heading extends outside the box!</h1>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
<p>Hello this is some text</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -105,6 +105,7 @@
|
|||
<li><a href="float-1.html">Floating boxes</a></li>
|
||||
<li><a href="float-3.html">Floating boxes with overflow=hidden</a></li>
|
||||
<li><a href="clear-1.html">Float clearing</a></li>
|
||||
<li><a href="overflow.html">Overflow</a></li>
|
||||
<li><h3>Features</h3></li>
|
||||
<li><a href="css.html">Basic functionality</a></li>
|
||||
<li><a href="colors.html">css colors</a></li>
|
||||
|
|
|
@ -2503,6 +2503,47 @@ RefPtr<StyleValue> Parser::parse_list_style_value(ParsingContext const& context,
|
|||
return ListStyleStyleValue::create(list_position.release_nonnull(), list_image.release_nonnull(), list_type.release_nonnull());
|
||||
}
|
||||
|
||||
RefPtr<StyleValue> Parser::parse_overflow_value(ParsingContext const& context, Vector<StyleComponentValueRule> const& component_values)
|
||||
{
|
||||
auto is_overflow = [](StyleValue const& value) -> bool {
|
||||
switch (value.to_identifier()) {
|
||||
case ValueID::Auto:
|
||||
case ValueID::Clip:
|
||||
case ValueID::Hidden:
|
||||
case ValueID::Scroll:
|
||||
case ValueID::Visible:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
if (component_values.size() == 1) {
|
||||
auto maybe_value = parse_css_value(context, PropertyID::Overflow, component_values.first());
|
||||
if (!maybe_value)
|
||||
return nullptr;
|
||||
auto value = maybe_value.release_nonnull();
|
||||
if (is_overflow(*value))
|
||||
return OverflowStyleValue::create(value, value);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (component_values.size() == 2) {
|
||||
auto maybe_x_value = parse_css_value(context, PropertyID::OverflowX, component_values[0]);
|
||||
auto maybe_y_value = parse_css_value(context, PropertyID::OverflowY, component_values[1]);
|
||||
|
||||
if (!maybe_x_value || !maybe_y_value)
|
||||
return nullptr;
|
||||
auto x_value = maybe_x_value.release_nonnull();
|
||||
auto y_value = maybe_y_value.release_nonnull();
|
||||
if (!is_overflow(x_value) || !is_overflow(y_value))
|
||||
return nullptr;
|
||||
return OverflowStyleValue::create(x_value, y_value);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<StyleValue> Parser::parse_text_decoration_value(ParsingContext const& context, Vector<StyleComponentValueRule> const& component_values)
|
||||
{
|
||||
auto is_text_decoration_line = [](StyleValue const& value) -> bool {
|
||||
|
@ -2650,6 +2691,10 @@ RefPtr<StyleValue> Parser::parse_css_value(PropertyID property_id, TokenStream<S
|
|||
if (auto parsed_value = parse_list_style_value(m_context, component_values))
|
||||
return parsed_value;
|
||||
break;
|
||||
case PropertyID::Overflow:
|
||||
if (auto parsed_value = parse_overflow_value(m_context, component_values))
|
||||
return parsed_value;
|
||||
break;
|
||||
case PropertyID::TextDecoration:
|
||||
if (auto parsed_value = parse_text_decoration_value(m_context, component_values))
|
||||
return parsed_value;
|
||||
|
|
|
@ -184,6 +184,7 @@ private:
|
|||
static RefPtr<StyleValue> parse_flex_flow_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
|
||||
static RefPtr<StyleValue> parse_font_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
|
||||
static RefPtr<StyleValue> parse_list_style_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
|
||||
static RefPtr<StyleValue> parse_overflow_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
|
||||
static RefPtr<StyleValue> parse_text_decoration_value(ParsingContext const&, Vector<StyleComponentValueRule> const&);
|
||||
|
||||
// calc() parsing, according to https://www.w3.org/TR/css-values-3/#calc-syntax
|
||||
|
|
|
@ -220,8 +220,17 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
|
|||
}
|
||||
|
||||
if (property_id == CSS::PropertyID::Overflow) {
|
||||
style.set_property(CSS::PropertyID::OverflowX, value);
|
||||
style.set_property(CSS::PropertyID::OverflowY, value);
|
||||
if (value.is_overflow()) {
|
||||
auto& overflow = static_cast<OverflowStyleValue const&>(value);
|
||||
style.set_property(CSS::PropertyID::OverflowX, overflow.overflow_x());
|
||||
style.set_property(CSS::PropertyID::OverflowY, overflow.overflow_y());
|
||||
return;
|
||||
}
|
||||
if (value.is_builtin()) {
|
||||
style.set_property(CSS::PropertyID::OverflowX, value);
|
||||
style.set_property(CSS::PropertyID::OverflowY, value);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -237,6 +237,7 @@ public:
|
|||
FlexFlow,
|
||||
Font,
|
||||
ListStyle,
|
||||
Overflow,
|
||||
TextDecoration,
|
||||
};
|
||||
|
||||
|
@ -262,6 +263,7 @@ public:
|
|||
bool is_flex_flow() const { return type() == Type::FlexFlow; }
|
||||
bool is_font() const { return type() == Type::Font; }
|
||||
bool is_list_style() const { return type() == Type::ListStyle; }
|
||||
bool is_overflow() const { return type() == Type::Overflow; }
|
||||
bool is_text_decoration() const { return type() == Type::TextDecoration; }
|
||||
|
||||
bool is_builtin() const { return is_inherit() || is_initial(); }
|
||||
|
@ -902,6 +904,34 @@ private:
|
|||
NonnullRefPtr<StyleValue> m_style_type;
|
||||
};
|
||||
|
||||
class OverflowStyleValue final : public StyleValue {
|
||||
public:
|
||||
static NonnullRefPtr<OverflowStyleValue> create(NonnullRefPtr<StyleValue> overflow_x, NonnullRefPtr<StyleValue> overflow_y)
|
||||
{
|
||||
return adopt_ref(*new OverflowStyleValue(overflow_x, overflow_y));
|
||||
}
|
||||
virtual ~OverflowStyleValue() override { }
|
||||
|
||||
NonnullRefPtr<StyleValue> overflow_x() const { return m_overflow_x; }
|
||||
NonnullRefPtr<StyleValue> overflow_y() const { return m_overflow_y; }
|
||||
|
||||
virtual String to_string() const override
|
||||
{
|
||||
return String::formatted("{} {}", m_overflow_x->to_string(), m_overflow_y->to_string());
|
||||
}
|
||||
|
||||
private:
|
||||
OverflowStyleValue(NonnullRefPtr<StyleValue> overflow_x, NonnullRefPtr<StyleValue> overflow_y)
|
||||
: StyleValue(Type::Overflow)
|
||||
, m_overflow_x(overflow_x)
|
||||
, m_overflow_y(overflow_y)
|
||||
{
|
||||
}
|
||||
|
||||
NonnullRefPtr<StyleValue> m_overflow_x;
|
||||
NonnullRefPtr<StyleValue> m_overflow_y;
|
||||
};
|
||||
|
||||
class TextDecorationStyleValue final : public StyleValue {
|
||||
public:
|
||||
static NonnullRefPtr<TextDecorationStyleValue> create(
|
||||
|
|
Loading…
Reference in a new issue