aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2021-03-09 12:49:11 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2021-03-09 12:49:11 +0000
commit7e99c501c808a2338017246203b76761cb271fe7 (patch)
tree347d8f3baaf2b188f3fcfc07c58fa338aedca4d0
parentf0de57da10d978a4ceea1dcfad01c6a50d04b467 (diff)
downloadrspamd-7e99c501c808a2338017246203b76761cb271fe7.tar.gz
rspamd-7e99c501c808a2338017246203b76761cb271fe7.zip
[Project] Css: Add dimensions handling
-rw-r--r--src/libserver/css/css_property.cxx9
-rw-r--r--src/libserver/css/css_property.hxx7
-rw-r--r--src/libserver/css/css_rule.cxx14
-rw-r--r--src/libserver/css/css_value.cxx29
-rw-r--r--src/libserver/css/css_value.hxx28
-rw-r--r--test/lua/unit/css.lua5
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<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;
}
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<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));
}
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<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>;
};
}
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 */