From 7e99c501c808a2338017246203b76761cb271fe7 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 9 Mar 2021 12:49:11 +0000 Subject: [PATCH] [Project] Css: Add dimensions handling --- src/libserver/css/css_property.cxx | 9 ++++++--- src/libserver/css/css_property.hxx | 7 +++++-- src/libserver/css/css_rule.cxx | 14 +++++++++----- src/libserver/css/css_value.cxx | 29 +++++++++++++++++++++++++++++ src/libserver/css/css_value.hxx | 28 +++++++++++++++++++++++----- test/lua/unit/css.lua | 5 ++++- 6 files changed, 76 insertions(+), 16 deletions(-) diff --git a/src/libserver/css/css_property.cxx b/src/libserver/css/css_property.cxx index 54e927057..2a463f8da 100644 --- a/src/libserver/css/css_property.cxx +++ b/src/libserver/css/css_property.cxx @@ -20,7 +20,7 @@ namespace rspamd::css { -constexpr const auto type_map = frozen::make_unordered_map({ +constexpr const auto prop_names_map = frozen::make_unordered_map({ {"font", css_property_type::PROPERTY_FONT}, {"font-color", css_property_type::PROPERTY_FONT_COLOR}, {"font-size", css_property_type::PROPERTY_FONT_SIZE}, @@ -34,15 +34,18 @@ constexpr const auto type_map = frozen::make_unordered_map(css_property_type::PROPERTY_NYI)); + auto token_string_to_property(const std::string_view &inp) -> css_property_type { css_property_type ret = css_property_type::PROPERTY_NYI; - auto known_type = type_map.find(inp); + auto known_type = prop_names_map.find(inp); - if (known_type != type_map.end()) { + if (known_type != prop_names_map.end()) { ret = known_type->second; } diff --git a/src/libserver/css/css_property.hxx b/src/libserver/css/css_property.hxx index 3908c6d16..597fc20c5 100644 --- a/src/libserver/css/css_property.hxx +++ b/src/libserver/css/css_property.hxx @@ -106,11 +106,14 @@ struct alignas(int) css_property { return type == css_property_type::PROPERTY_COLOR || type == css_property_type::PROPERTY_BACKGROUND || type == css_property_type::PROPERTY_BGCOLOR || - type == css_property_type::PROPERTY_FONT_COLOR; + type == css_property_type::PROPERTY_FONT_COLOR || + type == css_property_type::PROPERTY_FONT; } constexpr auto is_dimension(void) const -> bool { return type == css_property_type::PROPERTY_HEIGHT || - type == css_property_type::PROPERTY_WIDTH; + type == css_property_type::PROPERTY_WIDTH || + type == css_property_type::PROPERTY_FONT_SIZE || + type == css_property_type::PROPERTY_FONT; } constexpr auto is_normal_number(void) const -> bool { return type == css_property_type::PROPERTY_OPACITY; diff --git a/src/libserver/css/css_rule.cxx b/src/libserver/css/css_rule.cxx index 511c226d2..a29577fe9 100644 --- a/src/libserver/css/css_rule.cxx +++ b/src/libserver/css/css_rule.cxx @@ -31,26 +31,30 @@ allowed_property_value(const css_property &prop, const css_consumed_block &parse return css_value::maybe_color_from_hex(tok.get_string_or_default("")); } else if (tok.type == css_parser_token::token_type::ident_token) { - return css_value::maybe_color_from_string(tok.get_string_or_default("")); + auto &&ret = css_value::maybe_color_from_string(tok.get_string_or_default("")); + + return ret; } } else if (parser_block.is_function()) { const auto &func = parser_block.get_function_or_invalid(); - return css_value::maybe_color_from_function(func); + auto &&ret = css_value::maybe_color_from_function(func); + return ret; } } - else if (prop.is_dimension()) { + + if (prop.is_dimension()) { if (parser_block.is_token()) { /* A single token */ const auto &tok = parser_block.get_token_or_empty(); if (tok.type == css_parser_token::token_type::number_token) { - return css_value{tok.get_number_or_default(0)}; + return css_value::maybe_dimension_from_number(tok); } } } - else if (prop.is_normal_number()) { + if (prop.is_normal_number()) { if (parser_block.is_token()) { /* A single token */ const auto &tok = parser_block.get_token_or_empty(); diff --git a/src/libserver/css/css_value.cxx b/src/libserver/css/css_value.cxx index 719633e68..94c340ac5 100644 --- a/src/libserver/css/css_value.cxx +++ b/src/libserver/css/css_value.cxx @@ -273,6 +273,29 @@ auto css_value::maybe_color_from_function(const css_consumed_block::css_function return std::nullopt; } +auto css_value::maybe_dimension_from_number(const css_parser_token &tok) +-> std::optional +{ + if (std::holds_alternative(tok.value)) { + auto dbl = std::get(tok.value); + css_dimension dim; + + dim.dim = dbl; + + if (tok.flags & css_parser_token::number_percent) { + dim.is_percent = true; + } + else { + dim.is_percent = false; + } + + return css_value{dim}; + } + + return std::nullopt; +} + + auto css_value::debug_str() const -> std::string { std::string ret; @@ -289,6 +312,12 @@ auto css_value::debug_str() const -> std::string else if constexpr (std::is_same_v) { ret += "size: " + std::to_string(arg); } + else if constexpr (std::is_same_v) { + ret += "dimension: " + std::to_string(arg.dim); + if (arg.is_percent) { + ret += "%"; + } + } else if constexpr (std::is_integral_v) { ret += "integral: " + std::to_string(static_cast(arg)); } diff --git a/src/libserver/css/css_value.hxx b/src/libserver/css/css_value.hxx index 8fa450e73..64109c5f0 100644 --- a/src/libserver/css/css_value.hxx +++ b/src/libserver/css/css_value.hxx @@ -41,6 +41,11 @@ struct alignas(int) css_color { css_color() = default; }; +struct css_dimension { + float dim; + bool is_percent; +}; + /* * Simple enum class for display stuff */ @@ -58,21 +63,24 @@ struct css_value { CSS_VALUE_COLOR, CSS_VALUE_NUMBER, CSS_VALUE_DISPLAY, - CSS_VALUE_OPACITY, + CSS_VALUE_DIMENSION, CSS_VALUE_NYI, } type; std::variant value; css_value(const css_color &color) : type(css_value_type::CSS_VALUE_COLOR), value(color) {} css_value(double num) : type(css_value_type::CSS_VALUE_NUMBER), value(num) {} + css_value(css_dimension dim) : + type(css_value_type::CSS_VALUE_DIMENSION), value(dim) {} - constexpr std::optional to_color(void) const { + auto to_color(void) const -> std::optional { if (type == css_value_type::CSS_VALUE_COLOR) { return std::get(value); } @@ -80,7 +88,7 @@ struct css_value { return std::nullopt; } - constexpr std::optional to_number(void) const { + auto to_number(void) const -> std::optional { if (type == css_value_type::CSS_VALUE_NUMBER) { return std::get(value); } @@ -88,7 +96,15 @@ struct css_value { return std::nullopt; } - constexpr std::optional to_display(void) const { + auto to_dimension(void) const -> std::optional { + if (type == css_value_type::CSS_VALUE_DIMENSION) { + return std::get(value); + } + + return std::nullopt; + } + + auto to_display(void) const -> std::optional { if (type == css_value_type::CSS_VALUE_DISPLAY) { return std::get(value); } @@ -96,7 +112,7 @@ struct css_value { return std::nullopt; } - constexpr bool is_valid(void) const { + auto is_valid(void) const -> bool { return (type != css_value_type::CSS_VALUE_NYI); } @@ -110,6 +126,8 @@ struct css_value { -> std::optional; static auto maybe_color_from_function(const css_consumed_block::css_function_block &func) -> std::optional; + static auto maybe_dimension_from_number(const css_parser_token &tok) + -> std::optional; }; } diff --git a/test/lua/unit/css.lua b/test/lua/unit/css.lua index 9f9201191..5bb197bf2 100644 --- a/test/lua/unit/css.lua +++ b/test/lua/unit/css.lua @@ -100,11 +100,14 @@ body { ]], [[ /* Colors */ -p { color: rgb(100%, 50%, 0%); opacity: -1; } /* very transparent solid orange */ +p { color: rgb(100%, 50%, 0%); opacity: -1; width: 1em; } /* very transparent solid orange */ p { color: rgb(100%, 50%, 0%); opacity: 2; } /* very transparent solid orange */ p { color: rgb(100%, 50%, 0%); opacity: 0.5; } /* very transparent solid orange */ p { color: rgb(100%, 50%, 0%); opacity: 1; width: 99%; } /* very transparent solid orange */ p { color: rgb(100%, 50%, 0%); opacity: 10%; width: 99%; } /* very transparent solid orange */ +p { color: rgb(100%, 50%, 0%); opacity: 10%; width: 100px; } /* very transparent solid orange */ +p { color: rgb(100%, 50%, 0%); opacity: 10% } /* very transparent solid orange */ + * { color: hsl(0, 100%, 50%) !important } /* red */ * { color: hsl(120, 100%, 50%) important } /* lime */ * { color: hsl(120, 100%, 25%) } /* dark green */ -- 2.39.5