]> source.dussan.org Git - rspamd.git/commitdiff
[Project] Css: Add dimensions handling
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 9 Mar 2021 12:49:11 +0000 (12:49 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 9 Mar 2021 12:49:11 +0000 (12:49 +0000)
src/libserver/css/css_property.cxx
src/libserver/css/css_property.hxx
src/libserver/css/css_rule.cxx
src/libserver/css/css_value.cxx
src/libserver/css/css_value.hxx
test/lua/unit/css.lua

index 54e927057d4c5d3bc3de9315fdbb2c6a777b0e38..2a463f8da5b2b0af3586acdde6b6b32386d07e7a 100644 (file)
@@ -20,7 +20,7 @@
 
 namespace rspamd::css {
 
-constexpr const auto type_map = frozen::make_unordered_map<frozen::string, css_property_type>({
+constexpr const auto prop_names_map = frozen::make_unordered_map<frozen::string, css_property_type>({
                {"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<frozen::string, css_p
                {"opacity", css_property_type::PROPERTY_OPACITY},
 });
 
+/* Ensure that we have all cases listed */
+static_assert(prop_names_map.size() == static_cast<int>(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;
        }
 
index 3908c6d16716abd56625106455a37e4d8ad2397c..597fc20c56b0b3aab0ce30f955679bce0d629b49 100644 (file)
@@ -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;
index 511c226d2357d83a49e4a19a95cae64db0efdaa2..a29577fe912ee3f2b1b6a04979da471a0b38e3c4 100644 (file)
@@ -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();
index 719633e6838313ca24838b4320a07c2f11f0755b..94c340ac5f5ef52e7c800559a50c5072a079e350 100644 (file)
@@ -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<css_value>
+{
+       if (std::holds_alternative<double>(tok.value)) {
+               auto dbl = std::get<double>(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<T, double>) {
                        ret += "size: " + std::to_string(arg);
                }
+               else if constexpr (std::is_same_v<T, css_dimension>) {
+                       ret += "dimension: " + std::to_string(arg.dim);
+                       if (arg.is_percent) {
+                               ret += "%";
+                       }
+               }
                else if constexpr (std::is_integral_v<T>) {
                        ret += "integral: " + std::to_string(static_cast<int>(arg));
                }
index 8fa450e732b8dfad6da30f2c892209eb52709d06..64109c5f014454db355989b5c4d1a36b6d1d18c7 100644 (file)
@@ -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<css_color,
                        double,
                        css_display_value,
+                       css_dimension,
                        std::monostate> 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<css_color> to_color(void) const {
+       auto to_color(void) const -> std::optional<css_color> {
                if (type == css_value_type::CSS_VALUE_COLOR) {
                        return std::get<css_color>(value);
                }
@@ -80,7 +88,7 @@ struct css_value {
                return std::nullopt;
        }
 
-       constexpr std::optional<double> to_number(void) const {
+       auto to_number(void) const -> std::optional<double> {
                if (type == css_value_type::CSS_VALUE_NUMBER) {
                        return std::get<double>(value);
                }
@@ -88,7 +96,15 @@ struct css_value {
                return std::nullopt;
        }
 
-       constexpr std::optional<css_display_value> to_display(void) const {
+       auto to_dimension(void) const -> std::optional<css_dimension> {
+               if (type == css_value_type::CSS_VALUE_DIMENSION) {
+                       return std::get<css_dimension>(value);
+               }
+
+               return std::nullopt;
+       }
+
+       auto to_display(void) const -> std::optional<css_display_value> {
                if (type == css_value_type::CSS_VALUE_DISPLAY) {
                        return std::get<css_display_value>(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<css_value>;
        static auto maybe_color_from_function(const css_consumed_block::css_function_block &func)
                -> std::optional<css_value>;
+       static auto maybe_dimension_from_number(const css_parser_token &tok)
+               -> std::optional<css_value>;
 };
 
 }
index 9f92011918f479396278a83c301445d0bd34bec0..5bb197bf24bca13b0483ffe5d4949b4dd8068f92 100644 (file)
@@ -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 */