mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 22:07:34 +00:00
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:
parent
12e8efd74e
commit
0891f860f7
4 changed files with 205 additions and 0 deletions
|
@ -19,9 +19,88 @@
|
||||||
border-bottom-style: solid;
|
border-bottom-style: solid;
|
||||||
border-left-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>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="foo">One day at a time!</div>
|
<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>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -144,8 +144,94 @@ static Vector<String> split_on_whitespace(const StringView& string)
|
||||||
return v;
|
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)
|
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) {
|
if (property_id == CSS::PropertyID::BorderStyle) {
|
||||||
style.set_property(CSS::PropertyID::BorderTopStyle, value);
|
style.set_property(CSS::PropertyID::BorderTopStyle, value);
|
||||||
style.set_property(CSS::PropertyID::BorderRightStyle, value);
|
style.set_property(CSS::PropertyID::BorderRightStyle, value);
|
||||||
|
|
|
@ -153,6 +153,42 @@ NonnullRefPtr<StyleValue> parse_css_value(const StringView& string)
|
||||||
return StringStyleValue::create(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 {
|
class CSSParser {
|
||||||
public:
|
public:
|
||||||
CSSParser(const StringView& input)
|
CSSParser(const StringView& input)
|
||||||
|
|
|
@ -35,4 +35,8 @@ RefPtr<StyleSheet> parse_css(const StringView&);
|
||||||
RefPtr<StyleDeclaration> parse_css_declaration(const StringView&);
|
RefPtr<StyleDeclaration> parse_css_declaration(const StringView&);
|
||||||
NonnullRefPtr<StyleValue> parse_css_value(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&);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue