std::vector<consumed_block_ptr> args;
css_function_block(css_parser_token &&tok) :
- function(std::forward<css_parser_token>(tok)) {}
+ function(std::forward<css_parser_token>(tok)) {}
+
+ auto as_string() const -> const std::string_view & {
+ return function.get_string_or_default("");
+ }
+
+ static auto empty_function() -> const css_function_block & {
+ static const css_function_block invalid(
+ css_parser_token(css_parser_token::token_type::eof_token,
+ css_parser_token_placeholder()));
+ return invalid;
+ }
};
css_consumed_block() : tag(parser_tag_type::css_eof_block) {}
const inline static std::vector<consumed_block_ptr> empty_block_vec{};
auto is_blocks_vec() const -> bool {
- return (content.index() == 1);
+ return (std::holds_alternative<std::vector<consumed_block_ptr>>(content));
}
auto get_blocks_or_empty() const -> const std::vector<consumed_block_ptr>& {
}
auto is_token() const -> bool {
- return (content.index() == 2);
+ return (std::holds_alternative<css_parser_token>(content));
}
auto get_token_or_empty() const -> const css_parser_token& {
return css_parser_eof_token();
}
+ auto is_function() const -> bool {
+ return (std::holds_alternative<css_function_block>(content));
+ }
+
+ auto get_function_or_invalid() const -> const css_function_block& {
+ if (is_token()) {
+ return std::get<css_function_block>(content);
+ }
+
+ return css_function_block::empty_function();
+ }
+
auto size() const -> std::size_t {
auto ret = 0;
namespace rspamd::css {
-constexpr const auto max_type = static_cast<int>(css_property_type::PROPERTY_NYI);
-constexpr frozen::unordered_map<frozen::string, css_property_type, max_type> type_map{
+constexpr const auto type_map = frozen::make_unordered_map<frozen::string, css_property_type>({
{"font", css_property_type::PROPERTY_FONT},
+ {"font-color", css_property_type::PROPERTY_FONT_COLOR},
{"color", css_property_type::PROPERTY_COLOR},
{"bgcolor", css_property_type::PROPERTY_BGCOLOR},
{"background", css_property_type::PROPERTY_BACKGROUND},
{"width", css_property_type::PROPERTY_WIDTH},
{"display", css_property_type::PROPERTY_DISPLAY},
{"visibility", css_property_type::PROPERTY_VISIBILITY},
-};
+});
auto token_string_to_property(const std::string_view &inp) -> css_property_type {
*/
enum class css_property_type {
PROPERTY_FONT = 0,
+ PROPERTY_FONT_COLOR,
PROPERTY_COLOR,
PROPERTY_BGCOLOR,
PROPERTY_BACKGROUND,
case css_property_type::PROPERTY_FONT:
ret = "font";
break;
+ case css_property_type::PROPERTY_FONT_COLOR:
+ ret = "font-color";
+ break;
case css_property_type::PROPERTY_COLOR:
ret = "color";
break;
return ret;
}
+
+ constexpr auto is_color(void) const -> bool {
+ 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;
+ }
+ constexpr auto is_dimension(void) const -> bool {
+ return type == css_property_type::PROPERTY_HEIGHT ||
+ type == css_property_type::PROPERTY_WIDTH;
+ }
};
namespace rspamd::css {
+static auto
+allowed_property_value(const css_property &prop, const css_consumed_block &parser_block)
+ -> std::optional<css_value>
+{
+ if (prop.is_color()) {
+ 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::hash_token) {
+ return css_value::maybe_color_from_hex(tok.get_string_or_default(""));
+ }
+ else if (tok.type == css_parser_token::token_type::string_token) {
+ return css_value::maybe_color_from_string(tok.get_string_or_default(""));
+ }
+ }
+ else if (parser_block.is_function()) {
+ const auto &func = parser_block.get_function_or_invalid();
+
+ return css_value::maybe_color_from_function(func);
+ }
+ }
+
+ return std::nullopt;
+}
+
auto process_declaration_tokens(rspamd_mempool_t *pool,
const blocks_gen_functor &next_block_functor)
-> declarations_vec
}
}
- auto maybe_value = css_value::from_css_block(next_tok);
+ auto maybe_value = allowed_property_value(cur_property, next_tok);
if (maybe_value) {
+ msg_debug_css("added value %s to the property %s",
+ maybe_value.value().debug_str().c_str(),
+ cur_property.to_string());
cur_rule->add_value(maybe_value.value());
}
}
return ret; /* copy elision */
}
+
+void css_rule::add_value(std::unique_ptr<css_value> &&value)
+{
+ values.emplace_back(std::forward<std::unique_ptr<css_value>>(value));
+}
+
+void css_rule::add_value(const css_value &value)
+{
+ values.emplace_back(std::make_unique<css_value>(css_value{value}));
+}
+
}
\ No newline at end of file
prop(prop), values(std::forward<css_values_vec>(values)) {}
explicit css_rule(const css_property &prop) : prop(prop), values{} {}
/* Methods */
- void add_value(std::unique_ptr<css_value> &&value) {
- values.emplace_back(std::forward<std::unique_ptr<css_value>>(value));
- }
- void add_value(const css_value &value) {
- values.emplace_back(std::make_unique<css_value>(css_value{value}));
- }
+ void add_value(std::unique_ptr<css_value> &&value);
+ void add_value(const css_value &value);
constexpr const css_values_vec& get_values(void) const { return values; }
constexpr const css_property& get_prop(void) const { return prop; }
};
css_parser_token(css_parser_token &&other) = default;
auto operator=(css_parser_token &&other) -> css_parser_token& = default;
auto adjust_dim(const css_parser_token &dim_token) -> bool;
- auto get_string_or_default(const std::string_view &def) const -> std::string_view {
+
+ auto get_string_or_default(const std::string_view &def) const -> const std::string_view & {
if (value.index() == 0) {
return std::get<std::string_view>(value);
}
return ret;
}
-auto css_value::maybe_color_from_function(const std::string_view &func,
- const std::vector<css_parser_token> &args)
+auto css_value::maybe_color_from_function(const css_consumed_block::css_function_block &func)
-> std::optional<css_value>
{
- if (func == "rgb" && args.size() == 3) {
- css_color col{rgb_color_component_convert(args[0]),
- rgb_color_component_convert(args[1]),
- rgb_color_component_convert(args[2])};
+
+ if (func.as_string() == "rgb" && func.args.size() == 3) {
+ css_color col{rgb_color_component_convert(func.args[0]->get_token_or_empty()),
+ rgb_color_component_convert(func.args[1]->get_token_or_empty()),
+ rgb_color_component_convert(func.args[2]->get_token_or_empty())};
return css_value(col);
}
- else if (func == "rgba" && args.size() == 4) {
- css_color col{rgb_color_component_convert(args[0]),
- rgb_color_component_convert(args[1]),
- rgb_color_component_convert(args[2]),
- alpha_component_convert(args[3])};
+ else if (func.as_string() == "rgba" && func.args.size() == 4) {
+ css_color col{rgb_color_component_convert(func.args[0]->get_token_or_empty()),
+ rgb_color_component_convert(func.args[1]->get_token_or_empty()),
+ rgb_color_component_convert(func.args[2]->get_token_or_empty()),
+ alpha_component_convert(func.args[3]->get_token_or_empty())};
return css_value(col);
}
- else if (func == "hsl" && args.size() == 3) {
- auto h = h_component_convert(args[0]);
- auto s = sl_component_convert(args[1]);
- auto l = sl_component_convert(args[2]);
+ else if (func.as_string() == "hsl" && func.args.size() == 3) {
+ auto h = h_component_convert(func.args[0]->get_token_or_empty());
+ auto s = sl_component_convert(func.args[1]->get_token_or_empty());
+ auto l = sl_component_convert(func.args[2]->get_token_or_empty());
auto col = hsl_to_rgb(h, s, l);
return css_value(col);
}
- else if (func == "hsla" && args.size() == 4) {
- auto h = h_component_convert(args[0]);
- auto s = sl_component_convert(args[1]);
- auto l = sl_component_convert(args[2]);
+ else if (func.as_string() == "hsla" && func.args.size() == 4) {
+ auto h = h_component_convert(func.args[0]->get_token_or_empty());
+ auto s = sl_component_convert(func.args[1]->get_token_or_empty());
+ auto l = sl_component_convert(func.args[2]->get_token_or_empty());
auto col = hsl_to_rgb(h, s, l);
- col.alpha = alpha_component_convert(args[3]);
+ col.alpha = alpha_component_convert(func.args[3]->get_token_or_empty());
return css_value(col);
}
return std::nullopt;
}
+auto css_value::debug_str() const -> std::string
+{
+ std::string ret;
+
+ std::visit([&](auto& arg) {
+ using T = std::decay_t<decltype(arg)>;
+
+ if constexpr (std::is_same_v<T, css_color>) {
+ ret += "color: r=" + std::to_string(arg.r) +
+ "; g=" + std::to_string(arg.g) +
+ "; b=" + std::to_string(arg.b) +
+ "; a=" + std::to_string(arg.alpha);
+ }
+ else if constexpr (std::is_same_v<T, double>) {
+ ret += "size: " + std::to_string(arg);
+ }
+ else if constexpr (std::is_integral_v<T>) {
+ ret += "integral: " + std::to_string(static_cast<int>(arg));
+ }
+ else {
+ ret += "nyi";
+ }
+ }, value);
+
+ return ret;
+}
+
}
return (type != css_value_type::CSS_VALUE_NYI);
}
+ auto debug_str() const -> std::string;
+
static auto from_css_block(const css_consumed_block &bl) -> tl::expected<css_value, css_parse_error>;
static auto maybe_color_from_string(const std::string_view &input)
-> std::optional<css_value>;
static auto maybe_color_from_hex(const std::string_view &input)
-> std::optional<css_value>;
- static auto maybe_color_from_function(const std::string_view &func,
- const std::vector<css_parser_token> &args)
+ static auto maybe_color_from_function(const css_consumed_block::css_function_block &func)
-> std::optional<css_value>;
};