summaryrefslogtreecommitdiffstats
path: root/src/libserver/css
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2021-06-10 15:15:45 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2021-06-11 15:09:10 +0100
commit9b2fb6ce7e647bdf719c6598098ecd0f112cb016 (patch)
tree73b7a3d970167e9a89d6b69eaca56111e8c39085 /src/libserver/css
parentb74798de84b52b960cdf98562a62461363da291e (diff)
downloadrspamd-9b2fb6ce7e647bdf719c6598098ecd0f112cb016.tar.gz
rspamd-9b2fb6ce7e647bdf719c6598098ecd0f112cb016.zip
[Project] Html/CSS: Add transform from a CSS rule to html block
Diffstat (limited to 'src/libserver/css')
-rw-r--r--src/libserver/css/css_rule.cxx119
-rw-r--r--src/libserver/css/css_rule.hxx12
-rw-r--r--src/libserver/css/css_tokeniser.cxx6
-rw-r--r--src/libserver/css/css_tokeniser.hxx14
-rw-r--r--src/libserver/css/css_value.cxx10
5 files changed, 144 insertions, 17 deletions
diff --git a/src/libserver/css/css_rule.cxx b/src/libserver/css/css_rule.cxx
index 2e84aaa1c..d06f0aec0 100644
--- a/src/libserver/css/css_rule.cxx
+++ b/src/libserver/css/css_rule.cxx
@@ -16,6 +16,7 @@
#include "css_rule.hxx"
#include "css.hxx"
+#include "libserver/html/html_block.hxx"
#include <limits>
#define DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
@@ -349,10 +350,11 @@ auto process_declaration_tokens(rspamd_mempool_t *pool,
}
auto
-css_declarations_block::merge_block(const css_declarations_block &other, merge_type how)
--> void {
+css_declarations_block::merge_block(const css_declarations_block &other, merge_type how) -> void
+{
const auto &other_rules = other.get_rules();
+
for (auto &rule : other_rules) {
auto &&found_it = rules.find(rule);
@@ -379,6 +381,119 @@ css_declarations_block::merge_block(const css_declarations_block &other, merge_t
}
}
+auto
+css_declarations_block::compile_to_block(rspamd_mempool_t *pool) const -> rspamd::html::html_block *
+{
+ auto *block = rspamd_mempool_alloc0_type(pool, rspamd::html::html_block);
+ auto opacity = -1;
+ const css_rule *font_rule = nullptr, *background_rule = nullptr;
+
+ for (const auto &rule : rules) {
+ auto prop = rule->get_prop().type;
+ const auto &vals = rule->get_values();
+
+ if (vals.empty()) {
+ continue;
+ }
+
+ switch (prop) {
+ case css_property_type::PROPERTY_VISIBILITY:
+ case css_property_type::PROPERTY_DISPLAY: {
+ auto disp = vals.back().to_display().value_or(css_display_value::DISPLAY_NORMAL);
+ block->set_display(disp);
+ break;
+ }
+ case css_property_type::PROPERTY_FONT_SIZE: {
+ auto fs = vals.back().to_dimension();
+ if (fs) {
+ block->set_font_size(fs.value().dim, fs.value().is_percent);
+ }
+ }
+ case css_property_type::PROPERTY_OPACITY: {
+ opacity = vals.back().to_number().value_or(opacity);
+ break;
+ }
+ case css_property_type::PROPERTY_FONT_COLOR: {
+ auto color = vals.back().to_color();
+ if (color) {
+ block->set_fgcolor(color.value());
+ }
+ break;
+ }
+ case css_property_type::PROPERTY_BGCOLOR: {
+ auto color = vals.back().to_color();
+ if (color) {
+ block->set_bgcolor(color.value());
+ }
+ break;
+ }
+ case css_property_type::PROPERTY_HEIGHT: {
+ auto w = vals.back().to_dimension();
+ if (w) {
+ block->set_width(w.value().dim, w.value().is_percent);
+ }
+ break;
+ }
+ case css_property_type::PROPERTY_WIDTH: {
+ auto h = vals.back().to_dimension();
+ if (h) {
+ block->set_width(h.value().dim, h.value().is_percent);
+ }
+ break;
+ }
+ /* Optional attributes */
+ case css_property_type::PROPERTY_FONT:
+ font_rule = rule.get();
+ break;
+ case css_property_type::PROPERTY_BACKGROUND:
+ background_rule = rule.get();
+ break;
+ default:
+ /* Do nothing for now */
+ break;
+ }
+ }
+
+ /* Optional properties */
+ if (!(block->mask & rspamd::html::html_block::fg_color_mask) && font_rule) {
+ auto &vals = font_rule->get_values();
+
+ for (const auto &val : vals) {
+ auto maybe_color = val.to_color();
+
+ if (maybe_color) {
+ block->set_fgcolor(maybe_color.value());
+ }
+ }
+ }
+
+ if (!(block->mask & rspamd::html::html_block::font_size_mask) && font_rule) {
+ auto &vals = font_rule->get_values();
+
+ for (const auto &val : vals) {
+ auto maybe_dim = val.to_dimension();
+
+ if (maybe_dim) {
+ block->set_font_size(maybe_dim.value().dim, maybe_dim.value().is_percent);
+ }
+ }
+ }
+
+ if (!(block->mask & rspamd::html::html_block::bg_color_mask) && background_rule) {
+ auto &vals = background_rule->get_values();
+
+ for (const auto &val : vals) {
+ auto maybe_color = val.to_color();
+
+ if (maybe_color) {
+ block->set_bgcolor(maybe_color.value());
+ }
+ }
+ }
+
+ return block;
+}
+
void css_rule::add_value(const css_value &value)
{
values.push_back(value);
diff --git a/src/libserver/css/css_rule.hxx b/src/libserver/css/css_rule.hxx
index 3353382e7..b29bf298f 100644
--- a/src/libserver/css/css_rule.hxx
+++ b/src/libserver/css/css_rule.hxx
@@ -26,6 +26,11 @@
#include <vector>
#include <memory>
+namespace rspamd::html {
+/* Forward declaration */
+struct html_block;
+}
+
namespace rspamd::css {
class css_rule {
@@ -107,6 +112,13 @@ public:
return (rules.find(css_rule{prop}) != rules.end());
}
+ /**
+ * Compile CSS declaration to the html block
+ * @param pool used to carry memory requred for html_block
+ * @return html block structure
+ */
+ auto compile_to_block(rspamd_mempool_t *pool) const -> rspamd::html::html_block *;
+
private:
robin_hood::unordered_flat_set<rule_shared_ptr, rule_shared_hash, rule_shared_eq> rules;
};
diff --git a/src/libserver/css/css_tokeniser.cxx b/src/libserver/css/css_tokeniser.cxx
index 0b1467d8f..f31fdc009 100644
--- a/src/libserver/css/css_tokeniser.cxx
+++ b/src/libserver/css/css_tokeniser.cxx
@@ -75,7 +75,7 @@ auto make_token<css_parser_token::token_type::delim_token, char>(const char &c)
}
template<>
-auto make_token<css_parser_token::token_type::number_token, double>(const double &d)
+auto make_token<css_parser_token::token_type::number_token, float>(const float &d)
-> css_parser_token
{
return css_parser_token{css_parser_token::token_type::number_token, d};
@@ -145,13 +145,13 @@ constexpr frozen::unordered_map<frozen::string, css_dimension_data, max_dims> di
auto
css_parser_token::adjust_dim(const css_parser_token &dim_token) -> bool
{
- if (!std::holds_alternative<double>(value) ||
+ if (!std::holds_alternative<float>(value) ||
!std::holds_alternative<std::string_view>(dim_token.value)) {
/* Invalid tokens */
return false;
}
- auto num = std::get<double>(value);
+ auto num = std::get<float>(value);
auto sv = std::get<std::string_view>(dim_token.value);
auto dim_found = dimensions_map.find(sv);
diff --git a/src/libserver/css/css_tokeniser.hxx b/src/libserver/css/css_tokeniser.hxx
index a45e56f3f..021284989 100644
--- a/src/libserver/css/css_tokeniser.hxx
+++ b/src/libserver/css/css_tokeniser.hxx
@@ -80,7 +80,7 @@ struct css_parser_token {
using value_type = std::variant<std::string_view, /* For strings and string like tokens */
char, /* For delimiters (might need to move to unicode point) */
- double, /* For numeric stuff */
+ float, /* For numeric stuff */
css_parser_token_placeholder /* For general no token stuff */
>;
@@ -119,9 +119,9 @@ struct css_parser_token {
return (char)-1;
}
- auto get_number_or_default(double def) const -> double {
- if (std::holds_alternative<double>(value)) {
- auto dbl = std::get<double>(value);
+ auto get_number_or_default(float def) const -> float {
+ if (std::holds_alternative<float>(value)) {
+ auto dbl = std::get<float>(value);
if (flags & css_parser_token::number_percent) {
dbl /= 100.0;
@@ -133,9 +133,9 @@ struct css_parser_token {
return def;
}
- auto get_normal_number_or_default(double def) const -> double {
- if (std::holds_alternative<double>(value)) {
- auto dbl = std::get<double>(value);
+ auto get_normal_number_or_default(float def) const -> float {
+ if (std::holds_alternative<float>(value)) {
+ auto dbl = std::get<float>(value);
if (flags & css_parser_token::number_percent) {
dbl /= 100.0;
diff --git a/src/libserver/css/css_value.cxx b/src/libserver/css/css_value.cxx
index 9f1f4dd7f..f573e38be 100644
--- a/src/libserver/css/css_value.cxx
+++ b/src/libserver/css/css_value.cxx
@@ -98,7 +98,7 @@ constexpr static inline auto rgb_color_component_convert(const css_parser_token
std::uint8_t ret = 0;
if (tok.type == css_parser_token::token_type::number_token) {
- auto dbl = std::get<double>(tok.value);
+ auto dbl = std::get<float>(tok.value);
if (tok.flags & css_parser_token::number_percent) {
if (dbl > 100) {
@@ -129,7 +129,7 @@ constexpr static inline auto alpha_component_convert(const css_parser_token &tok
double ret = 1.0;
if (tok.type == css_parser_token::token_type::number_token) {
- auto dbl = std::get<double>(tok.value);
+ auto dbl = std::get<float>(tok.value);
if (tok.flags & css_parser_token::number_percent) {
if (dbl > 100) {
@@ -160,7 +160,7 @@ constexpr static inline auto h_component_convert(const css_parser_token &tok)
double ret = 0.0;
if (tok.type == css_parser_token::token_type::number_token) {
- auto dbl = std::get<double>(tok.value);
+ auto dbl = std::get<float>(tok.value);
if (tok.flags & css_parser_token::number_percent) {
if (dbl > 100) {
@@ -276,8 +276,8 @@ auto css_value::maybe_color_from_function(const css_consumed_block::css_function
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);
+ if (std::holds_alternative<float>(tok.value)) {
+ auto dbl = std::get<float>(tok.value);
css_dimension dim;
dim.dim = dbl;