浏览代码

LibWeb: Make MediaCondition a top-level type and add factory methods

Sam Atkins 3 年之前
父节点
当前提交
b6fe7cc324

+ 47 - 2
Userland/Libraries/LibWeb/CSS/MediaQuery.cpp

@@ -139,7 +139,52 @@ bool MediaFeature::evaluate(DOM::Window const& window) const
     VERIFY_NOT_REACHED();
 }
 
-String MediaQuery::MediaCondition::to_string() const
+NonnullOwnPtr<MediaCondition> MediaCondition::from_general_enclosed(GeneralEnclosed&& general_enclosed)
+{
+    auto result = new MediaCondition;
+    result->type = Type::GeneralEnclosed;
+    result->general_enclosed = move(general_enclosed);
+
+    return adopt_own(*result);
+}
+
+NonnullOwnPtr<MediaCondition> MediaCondition::from_feature(MediaFeature&& feature)
+{
+    auto result = new MediaCondition;
+    result->type = Type::Single;
+    result->feature = move(feature);
+
+    return adopt_own(*result);
+}
+
+NonnullOwnPtr<MediaCondition> MediaCondition::from_not(NonnullOwnPtr<MediaCondition>&& condition)
+{
+    auto result = new MediaCondition;
+    result->type = Type::Not;
+    result->conditions.append(move(condition));
+
+    return adopt_own(*result);
+}
+
+NonnullOwnPtr<MediaCondition> MediaCondition::from_and_list(NonnullOwnPtrVector<MediaCondition>&& conditions)
+{
+    auto result = new MediaCondition;
+    result->type = Type::And;
+    result->conditions = move(conditions);
+
+    return adopt_own(*result);
+}
+
+NonnullOwnPtr<MediaCondition> MediaCondition::from_or_list(NonnullOwnPtrVector<MediaCondition>&& conditions)
+{
+    auto result = new MediaCondition;
+    result->type = Type::Or;
+    result->conditions = move(conditions);
+
+    return adopt_own(*result);
+}
+
+String MediaCondition::to_string() const
 {
     StringBuilder builder;
     builder.append('(');
@@ -165,7 +210,7 @@ String MediaQuery::MediaCondition::to_string() const
     return builder.to_string();
 }
 
-MatchResult MediaQuery::MediaCondition::evaluate(DOM::Window const& window) const
+MatchResult MediaCondition::evaluate(DOM::Window const& window) const
 {
     switch (type) {
     case Type::Single:

+ 29 - 21
Userland/Libraries/LibWeb/CSS/MediaQuery.h

@@ -112,6 +112,33 @@ private:
     Optional<MediaFeatureValue> m_value {};
 };
 
+// https://www.w3.org/TR/mediaqueries-4/#media-conditions
+struct MediaCondition {
+    enum class Type {
+        Single,
+        And,
+        Or,
+        Not,
+        GeneralEnclosed,
+    };
+
+    static NonnullOwnPtr<MediaCondition> from_general_enclosed(GeneralEnclosed&&);
+    static NonnullOwnPtr<MediaCondition> from_feature(MediaFeature&&);
+    static NonnullOwnPtr<MediaCondition> from_not(NonnullOwnPtr<MediaCondition>&&);
+    static NonnullOwnPtr<MediaCondition> from_and_list(NonnullOwnPtrVector<MediaCondition>&&);
+    static NonnullOwnPtr<MediaCondition> from_or_list(NonnullOwnPtrVector<MediaCondition>&&);
+
+    MatchResult evaluate(DOM::Window const&) const;
+    String to_string() const;
+
+private:
+    MediaCondition() { }
+    Type type;
+    Optional<MediaFeature> feature;
+    NonnullOwnPtrVector<MediaCondition> conditions;
+    Optional<GeneralEnclosed> general_enclosed;
+};
+
 class MediaQuery : public RefCounted<MediaQuery> {
     friend class Parser;
 
@@ -135,25 +162,6 @@ public:
         Speech,
     };
 
-    // https://www.w3.org/TR/mediaqueries-4/#media-conditions
-    struct MediaCondition {
-        enum class Type {
-            Single,
-            And,
-            Or,
-            Not,
-            GeneralEnclosed,
-        };
-
-        Type type;
-        Optional<MediaFeature> feature;
-        NonnullOwnPtrVector<MediaCondition> conditions;
-        Optional<GeneralEnclosed> general_enclosed;
-
-        MatchResult evaluate(DOM::Window const&) const;
-        String to_string() const;
-    };
-
     static NonnullRefPtr<MediaQuery> create_not_all();
     static NonnullRefPtr<MediaQuery> create() { return adopt_ref(*new MediaQuery); }
 
@@ -188,8 +196,8 @@ struct Formatter<Web::CSS::MediaFeature> : Formatter<StringView> {
 };
 
 template<>
-struct Formatter<Web::CSS::MediaQuery::MediaCondition> : Formatter<StringView> {
-    ErrorOr<void> format(FormatBuilder& builder, Web::CSS::MediaQuery::MediaCondition const& media_condition)
+struct Formatter<Web::CSS::MediaCondition> : Formatter<StringView> {
+    ErrorOr<void> format(FormatBuilder& builder, Web::CSS::MediaCondition const& media_condition)
     {
         return Formatter<StringView>::format(builder, media_condition.to_string());
     }

+ 16 - 33
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -749,7 +749,7 @@ NonnullRefPtr<MediaQuery> Parser::parse_media_query(TokenStream<StyleComponentVa
     return invalid_media_query();
 }
 
-OwnPtr<MediaQuery::MediaCondition> Parser::consume_media_condition(TokenStream<StyleComponentValueRule>& tokens)
+OwnPtr<MediaCondition> Parser::consume_media_condition(TokenStream<StyleComponentValueRule>& tokens)
 {
     // "not <media-condition>"
     // ( `<media-not>` in the grammar )
@@ -758,13 +758,8 @@ OwnPtr<MediaQuery::MediaCondition> Parser::consume_media_condition(TokenStream<S
     if (first_token.is(Token::Type::Ident) && first_token.token().ident().equals_ignoring_case("not"sv)) {
         tokens.next_token();
 
-        auto condition = new MediaQuery::MediaCondition;
-        condition->type = MediaQuery::MediaCondition::Type::Not;
-
-        if (auto child_condition = consume_media_condition(tokens)) {
-            condition->conditions.append(child_condition.release_nonnull());
-            return adopt_own(*condition);
-        }
+        if (auto child_condition = consume_media_condition(tokens))
+            return MediaCondition::from_not(child_condition.release_nonnull());
 
         tokens.rewind_to_position(position);
         return {};
@@ -772,16 +767,16 @@ OwnPtr<MediaQuery::MediaCondition> Parser::consume_media_condition(TokenStream<S
 
     // "<media-condition> ([and | or] <media-condition>)*"
     // ( `<media-in-parens> [ <media-and>* | <media-or>* ]` in the grammar )
-    NonnullOwnPtrVector<MediaQuery::MediaCondition> child_conditions;
-    Optional<MediaQuery::MediaCondition::Type> condition_type {};
-    auto as_condition_type = [](auto& token) -> Optional<MediaQuery::MediaCondition::Type> {
+    NonnullOwnPtrVector<MediaCondition> child_conditions;
+    Optional<MediaCondition::Type> condition_type {};
+    auto as_condition_type = [](auto& token) -> Optional<MediaCondition::Type> {
         if (!token.is(Token::Type::Ident))
             return {};
         auto ident = token.token().ident();
         if (ident.equals_ignoring_case("and"))
-            return MediaQuery::MediaCondition::Type::And;
+            return MediaCondition::Type::And;
         if (ident.equals_ignoring_case("or"))
-            return MediaQuery::MediaCondition::Type::Or;
+            return MediaCondition::Type::Or;
         return {};
     };
 
@@ -806,10 +801,7 @@ OwnPtr<MediaQuery::MediaCondition> Parser::consume_media_condition(TokenStream<S
         tokens.skip_whitespace();
 
         if (auto child_feature = consume_media_feature(tokens); child_feature.has_value()) {
-            auto child = new MediaQuery::MediaCondition;
-            child->type = MediaQuery::MediaCondition::Type::Single;
-            child->feature = child_feature.value();
-            child_conditions.append(adopt_own(*child));
+            child_conditions.append(MediaCondition::from_feature(child_feature.release_value()));
         } else {
             auto& token = tokens.next_token();
             if (!token.is_block() || !token.block().is_paren()) {
@@ -832,29 +824,20 @@ OwnPtr<MediaQuery::MediaCondition> Parser::consume_media_condition(TokenStream<S
         if (child_conditions.size() == 1)
             return move(child_conditions.ptr_at(0));
 
-        auto condition = new MediaQuery::MediaCondition;
-        condition->type = condition_type.value();
-        condition->conditions = move(child_conditions);
-        return adopt_own(*condition);
+        if (condition_type.value() == MediaCondition::Type::And)
+            return MediaCondition::from_and_list(move(child_conditions));
+        return MediaCondition::from_or_list(move(child_conditions));
     }
 
     // `<media-feature>`
     tokens.rewind_to_position(position);
-    if (auto feature = consume_media_feature(tokens); feature.has_value()) {
-        auto condition = new MediaQuery::MediaCondition;
-        condition->type = MediaQuery::MediaCondition::Type::Single;
-        condition->feature = feature.value();
-        return adopt_own(*condition);
-    }
+    if (auto feature = consume_media_feature(tokens); feature.has_value())
+        return MediaCondition::from_feature(feature.release_value());
 
     // `<general-enclosed>`
     tokens.rewind_to_position(position);
-    if (auto general_enclosed = parse_general_enclosed(tokens); general_enclosed.has_value()) {
-        auto condition = new MediaQuery::MediaCondition;
-        condition->type = MediaQuery::MediaCondition::Type::GeneralEnclosed;
-        condition->general_enclosed = general_enclosed.release_value();
-        return adopt_own(*condition);
-    }
+    if (auto general_enclosed = parse_general_enclosed(tokens); general_enclosed.has_value())
+        return MediaCondition::from_general_enclosed(general_enclosed.release_value());
 
     tokens.rewind_to_position(position);
     return {};

+ 1 - 1
Userland/Libraries/LibWeb/CSS/Parser/Parser.h

@@ -235,7 +235,7 @@ private:
     Result<Selector::SimpleSelector, ParsingResult> parse_simple_selector(TokenStream<StyleComponentValueRule>&);
 
     NonnullRefPtr<MediaQuery> parse_media_query(TokenStream<StyleComponentValueRule>&);
-    OwnPtr<MediaQuery::MediaCondition> consume_media_condition(TokenStream<StyleComponentValueRule>&);
+    OwnPtr<MediaCondition> consume_media_condition(TokenStream<StyleComponentValueRule>&);
     Optional<MediaFeature> consume_media_feature(TokenStream<StyleComponentValueRule>&);
     Optional<MediaQuery::MediaType> consume_media_type(TokenStream<StyleComponentValueRule>&);
     Optional<MediaFeatureValue> parse_media_feature_value(TokenStream<StyleComponentValueRule>&);