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},
{"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;
}
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;
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();
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;
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));
}
css_color() = default;
};
+struct css_dimension {
+ float dim;
+ bool is_percent;
+};
+
/*
* Simple enum class for display stuff
*/
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);
}
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);
}
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);
}
return std::nullopt;
}
- constexpr bool is_valid(void) const {
+ auto is_valid(void) const -> bool {
return (type != css_value_type::CSS_VALUE_NYI);
}
-> 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>;
};
}
]],
[[
/* 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 */