]> source.dussan.org Git - rspamd.git/commitdiff
[Project] Css: Start semantic parsing for rules
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 17 Feb 2021 15:56:58 +0000 (15:56 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 17 Feb 2021 15:56:58 +0000 (15:56 +0000)
src/libserver/css/css_parser.cxx
src/libserver/css/css_selector.hxx
test/lua/unit/css.lua

index 084d1b50afd46efc1f8af6783a04d3db145e1ffb..a0a9d8847fa50929dd4d75929caba0b37b3584bc 100644 (file)
@@ -22,6 +22,7 @@
 
 namespace rspamd::css {
 
+struct css_consumed_block;
 /*
  * Represents a consumed token by a parser
  */
@@ -33,7 +34,8 @@ struct css_consumed_block {
                css_simple_block,
                css_function,
                css_function_arg,
-               css_component
+               css_component,
+               css_selector,
        };
 
        using consumed_block_ptr = std::unique_ptr<css_consumed_block>;
@@ -81,6 +83,17 @@ struct css_consumed_block {
                content = std::move(tok);
        }
 
+       /* Empty blocks used to avoid type checks in loops */
+       const inline static std::vector<consumed_block_ptr> empty_block_vec{};
+
+       auto get_blocks_or_empty() const -> const std::vector<consumed_block_ptr>& {
+               if (content.index() == 1) {
+                       return std::get<std::vector<consumed_block_ptr>>(content);
+               }
+
+               return empty_block_vec;
+       }
+
        auto token_type_str(void) const -> const char *
        {
                const auto *ret = "";
@@ -107,6 +120,9 @@ struct css_consumed_block {
                case parser_tag_type::css_component:
                        ret = "component";
                        break;
+               case parser_tag_type::css_selector:
+                       ret = "selector";
+                       break;
                }
 
                return ret;
@@ -570,6 +586,35 @@ bool css_parser::consume_input(const std::string_view &sv)
 
        }
 
+       const auto &rules = consumed_blocks->get_blocks_or_empty();
+
+       for (auto &&rule : rules) {
+               /*
+                * For now, we do not need any of the at rules, so we can safely ignore them
+                */
+               auto &&children = rule->get_blocks_or_empty();
+
+               if (children.size() > 1 &&
+                       children[0]->tag == css_consumed_block::parser_tag_type::css_component) {
+                       auto simple_block = std::find_if(children.begin(), children.end(),
+                                       [](auto &bl) {
+                                               return bl->tag == css_consumed_block::parser_tag_type::css_simple_block;
+                                       });
+
+                       if (simple_block != children.end()) {
+                               /*
+                                * We have a component and a simple block,
+                                * so we can parse a declaration
+                                */
+
+                               /* First, tag all components as preamble */
+                               for (auto it = children.begin(); it != simple_block; ++it) {
+                                       (*it)->tag = css_consumed_block::parser_tag_type::css_selector;
+                               }
+                       }
+               }
+       }
+
        auto debug_str = consumed_blocks->debug_str();
        msg_debug_css("consumed css: {%*s}", (int)debug_str.size(), debug_str.data());
 
index c9f3046d51ca13eb0000c560cdae15154c451c00..8611630fd104621a17ff682f0d65d1d89e844453 100644 (file)
@@ -24,6 +24,7 @@
 #include <optional>
 #include "contrib/expected/expected.hpp"
 #include "parse_error.hxx"
+#include "css_tokeniser.hxx"
 #include "html_tags.h"
 
 namespace rspamd::css {
@@ -41,14 +42,14 @@ struct css_selector {
        selector_type type;
        std::variant<tag_id_t, std::string> value;
 
-       constexpr std::optional<tag_id_t> to_tag (void) const {
+        auto to_tag(void) const -> std::optional<tag_id_t> {
                if (type == selector_type::SELECTOR_ELEMENT) {
                        return std::get<tag_id_t>(value);
                }
                return std::nullopt;
        }
 
-       constexpr std::optional<const std::string_view> to_string (void) const {
+       auto to_string(void) const -> std::optional<const std::string_view> {
                if (type == selector_type::SELECTOR_ELEMENT) {
                        return std::string_view(std::get<std::string>(value));
                }
@@ -59,6 +60,8 @@ struct css_selector {
                                                                                                                           size_t inlen);
 };
 
+
+
 }
 
 #endif //RSPAMD_CSS_SELECTOR_HXX
index e040a6fd3e37d6a085628ee2fa57f21dafcca4b8..a5a8f533f173d633cbc838dd50b509ec1062742e 100644 (file)
@@ -50,7 +50,7 @@ p {
 p:first-child {
   color: blue;
 }
-a[target=_blank] {
+a[target=_blank] #id{
   background-color: yellow;
 }
 * {
@@ -75,7 +75,7 @@ body {
 }
 
 /* Style the topnav links */
-.topnav a {
+.topnav a{
   float: left;
   display: block;
   color: #f2f2f2;
@@ -85,7 +85,7 @@ body {
 }
 
 /* Clear floats after the columns */
-.row:after {
+.row:after{
   content: "";
   display: table;
   clear: both;