#include "css_rule.hxx"
#include "css.hxx"
+#include "libserver/html/html_block.hxx"
#include <limits>
#define DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
}
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);
}
}
+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);
#include <vector>
#include <memory>
+namespace rspamd::html {
+/* Forward declaration */
+struct html_block;
+}
+
namespace rspamd::css {
class css_rule {
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;
};
}
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};
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);
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 */
>;
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;
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;
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) {
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) {
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) {
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;
bg_color = c;
mask |= bg_color_mask;
}
- auto set_height(float h) -> void {
+ auto set_height(float h, bool is_percent = false) -> void {
+ h = is_percent ? (-h) : h;
if (h < INT16_MIN) {
/* Negative numbers encode percents... */
height = -100;
}
mask |= height_mask;
}
- auto set_width(double w) -> void {
+ auto set_width(float w, bool is_percent = false) -> void {
+ w = is_percent ? (-w) : w;
if (w < INT16_MIN) {
width = INT16_MIN;
}
display = v;
mask |= display_mask;
}
- auto set_font_size(float fs) -> void {
+ auto set_font_size(float fs, bool is_percent = false) -> void {
+ fs = is_percent ? (-fs) : fs;
if (fs < INT8_MIN) {
font_size = -100;
}