LibWeb: Add CSS property 'border'

This makes it possible to write shorter CSS. Instead of writing
.foo {
        border-width: 3px;
        border-style: solid;
        border-color: blue;
}
it is now possible to write
.foo {
        border: 3px solid blue;
}
while the order of values is irrelevant.
Currently only the basic values are supported. More values should be
added in the future.

Three more value specific parse functions were added:
parse_line_width, parse_color, and parse_line_style

Additionally a few test cases were added to borders.html.
This commit is contained in:
myphs 2020-03-20 20:29:39 +01:00 committed by Andreas Kling
parent 12e8efd74e
commit 0891f860f7
Notes: sideshowbarker 2024-07-19 18:30:55 +09:00
4 changed files with 205 additions and 0 deletions

View file

@ -19,9 +19,88 @@
border-bottom-style: solid;
border-left-style: solid;
}
#bar {
border: 30px solid orange;
}
#bene {
border: solid;
}
#salvete {
border: 30px;
border-color: grey;
border-style: solid;
}
#amici {
border: aquamarine;
border-width: 30px;
border-style: solid;
}
#resetting {
border: 100px;
border: orange;
border: solid;
}
#three-px-solid-blue-separate {
border-width: 3px;
border-style: solid;
border-color: blue;
}
#three-px-solid-blue {
border: 3px solid blue;
}
#foo-but-actually-resetted {
border-top-color: red;
border-right-color: lime;
border-bottom-color: blue;
border-left-color: yellow;
border-top-width: 40px;
border-right-width: 30px;
border-bottom-width: 20px;
border-left-width: 10px;
border-top-style: solid;
border-right-style: solid;
border-bottom-style: solid;
border-left-style: solid;
border: solid;
}
#double-width {
border: 50px 100px solid red;
}
#double-style {
border: 50px solid dotted red;
}
#double-color {
border: 50px solid red blue;
}
#double-width-solo {
border: 50px 100px;
}
#double-style-solo {
border: solid dotted;
}
#double-color-solo {
border: red blue;
}
</style>
</head>
<body>
<div id="foo">One day at a time!</div>
<div id="bar">Another day at another time!</div>
<div id="bene">bene</div>
<div id="salvete">salvete</div>
<div id="amici">amici</div>
<div id="resetting">resetting</div>
<div id="three-px-solid-blue-separate">three px solid blue separate</div>
<div id="three-px-solid-blue">three px solid blue</div>
<div id="foo-but-actually-resetted">foo but actually resetted</div>
<div id="double-width">double width</div>
<div id="double-style">double style</div>
<div id="double-color">double color</div>
<div id="double-width-solo">double width solo</div>
<div id="double-style-solo">double style solo</div>
<div id="double-color-solo">double color solo</div>
</body>
</html>

View file

@ -144,8 +144,94 @@ static Vector<String> split_on_whitespace(const StringView& string)
return v;
}
static inline void set_property_border_width(StyleProperties& style, const StyleValue& value)
{
ASSERT(value.is_length());
style.set_property(CSS::PropertyID::BorderTopWidth, value);
style.set_property(CSS::PropertyID::BorderRightWidth, value);
style.set_property(CSS::PropertyID::BorderBottomWidth, value);
style.set_property(CSS::PropertyID::BorderLeftWidth, value);
}
static inline void set_property_border_color(StyleProperties& style, const StyleValue& value)
{
ASSERT(value.is_color());
style.set_property(CSS::PropertyID::BorderTopColor, value);
style.set_property(CSS::PropertyID::BorderRightColor, value);
style.set_property(CSS::PropertyID::BorderBottomColor, value);
style.set_property(CSS::PropertyID::BorderLeftColor, value);
}
static inline void set_property_border_style(StyleProperties& style, const StyleValue& value)
{
ASSERT(value.is_string());
style.set_property(CSS::PropertyID::BorderTopStyle, value);
style.set_property(CSS::PropertyID::BorderRightStyle, value);
style.set_property(CSS::PropertyID::BorderBottomStyle, value);
style.set_property(CSS::PropertyID::BorderLeftStyle, value);
}
static void set_property_expanding_shorthands(StyleProperties& style, CSS::PropertyID property_id, const StyleValue& value)
{
if (property_id == CSS::PropertyID::Border) {
auto parts = split_on_whitespace(value.to_string());
if (value.is_length()) {
set_property_border_width(style, value);
return;
}
if (value.is_color()) {
set_property_border_color(style, value);
return;
}
if (value.is_string()) {
auto parts = split_on_whitespace(value.to_string());
if (parts.size() == 1) {
if (auto value = parse_line_style(parts[0])) {
set_property_border_style(style, value.release_nonnull());
set_property_border_color(style, ColorStyleValue::create(Gfx::Color::Black));
set_property_border_width(style, LengthStyleValue::create(Length(3, Length::Type::Absolute)));
return;
}
}
RefPtr<LengthStyleValue> line_width_value;
RefPtr<ColorStyleValue> color_value;
RefPtr<StringStyleValue> line_style_value;
for (auto& part : parts) {
if (auto value = parse_line_width(part)) {
if (line_width_value)
return;
line_width_value = move(value);
continue;
}
if (auto value = parse_color(part)) {
if (color_value)
return;
color_value = move(value);
continue;
}
if (auto value = parse_line_style(part)) {
if (line_style_value)
return;
line_style_value = move(value);
continue;
}
}
if (line_width_value)
set_property_border_width(style, line_width_value.release_nonnull());
if (color_value)
set_property_border_color(style, color_value.release_nonnull());
if (line_style_value)
set_property_border_style(style, line_style_value.release_nonnull());
return;
}
return;
}
if (property_id == CSS::PropertyID::BorderStyle) {
style.set_property(CSS::PropertyID::BorderTopStyle, value);
style.set_property(CSS::PropertyID::BorderRightStyle, value);

View file

@ -153,6 +153,42 @@ NonnullRefPtr<StyleValue> parse_css_value(const StringView& string)
return StringStyleValue::create(string);
}
RefPtr<StyleValue> parse_line_width(const StringView& part)
{
NonnullRefPtr<StyleValue> value = parse_css_value(part);
if (value->is_length())
return value;
return nullptr;
}
RefPtr<StyleValue> parse_color(const StringView& part)
{
NonnullRefPtr<StyleValue> value = parse_css_value(part);
if (value->is_color())
return value;
return nullptr;
}
RefPtr<StyleValue> parse_line_style(const StringView& part)
{
NonnullRefPtr<StyleValue> value = parse_css_value(part);
if (value->is_string()) {
if (value->to_string() == "dotted")
return value;
if (value->to_string() == "dashed")
return value;
if (value->to_string() == "solid")
return value;
if (value->to_string() == "double")
return value;
if (value->to_string() == "groove")
return value;
if (value->to_string() == "ridge")
return value;
}
return nullptr;
}
class CSSParser {
public:
CSSParser(const StringView& input)

View file

@ -35,4 +35,8 @@ RefPtr<StyleSheet> parse_css(const StringView&);
RefPtr<StyleDeclaration> parse_css_declaration(const StringView&);
NonnullRefPtr<StyleValue> parse_css_value(const StringView&);
RefPtr<StyleValue> parse_line_width(const StringView&);
RefPtr<StyleValue> parse_color(const StringView&);
RefPtr<StyleValue> parse_line_style(const StringView&);
}