diff --git a/Userland/Libraries/LibWeb/CSS/MediaQuery.cpp b/Userland/Libraries/LibWeb/CSS/MediaQuery.cpp index 53e286adcd..c45a238ef4 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaQuery.cpp +++ b/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::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::from_feature(MediaFeature&& feature) +{ + auto result = new MediaCondition; + result->type = Type::Single; + result->feature = move(feature); + + return adopt_own(*result); +} + +NonnullOwnPtr MediaCondition::from_not(NonnullOwnPtr&& condition) +{ + auto result = new MediaCondition; + result->type = Type::Not; + result->conditions.append(move(condition)); + + return adopt_own(*result); +} + +NonnullOwnPtr MediaCondition::from_and_list(NonnullOwnPtrVector&& conditions) +{ + auto result = new MediaCondition; + result->type = Type::And; + result->conditions = move(conditions); + + return adopt_own(*result); +} + +NonnullOwnPtr MediaCondition::from_or_list(NonnullOwnPtrVector&& 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: diff --git a/Userland/Libraries/LibWeb/CSS/MediaQuery.h b/Userland/Libraries/LibWeb/CSS/MediaQuery.h index 14e7b92b77..b6eef1fdfb 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaQuery.h +++ b/Userland/Libraries/LibWeb/CSS/MediaQuery.h @@ -112,6 +112,33 @@ private: Optional m_value {}; }; +// https://www.w3.org/TR/mediaqueries-4/#media-conditions +struct MediaCondition { + enum class Type { + Single, + And, + Or, + Not, + GeneralEnclosed, + }; + + static NonnullOwnPtr from_general_enclosed(GeneralEnclosed&&); + static NonnullOwnPtr from_feature(MediaFeature&&); + static NonnullOwnPtr from_not(NonnullOwnPtr&&); + static NonnullOwnPtr from_and_list(NonnullOwnPtrVector&&); + static NonnullOwnPtr from_or_list(NonnullOwnPtrVector&&); + + MatchResult evaluate(DOM::Window const&) const; + String to_string() const; + +private: + MediaCondition() { } + Type type; + Optional feature; + NonnullOwnPtrVector conditions; + Optional general_enclosed; +}; + class MediaQuery : public RefCounted { 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 feature; - NonnullOwnPtrVector conditions; - Optional general_enclosed; - - MatchResult evaluate(DOM::Window const&) const; - String to_string() const; - }; - static NonnullRefPtr create_not_all(); static NonnullRefPtr create() { return adopt_ref(*new MediaQuery); } @@ -188,8 +196,8 @@ struct Formatter : Formatter { }; template<> -struct Formatter : Formatter { - ErrorOr format(FormatBuilder& builder, Web::CSS::MediaQuery::MediaCondition const& media_condition) +struct Formatter : Formatter { + ErrorOr format(FormatBuilder& builder, Web::CSS::MediaCondition const& media_condition) { return Formatter::format(builder, media_condition.to_string()); } diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index b016f9b9f4..9e61b1c844 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -749,7 +749,7 @@ NonnullRefPtr Parser::parse_media_query(TokenStream Parser::consume_media_condition(TokenStream& tokens) +OwnPtr Parser::consume_media_condition(TokenStream& tokens) { // "not " // ( `` in the grammar ) @@ -758,13 +758,8 @@ OwnPtr Parser::consume_media_condition(TokenStreamtype = 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 Parser::consume_media_condition(TokenStream ([and | or] )*" // ( ` [ * | * ]` in the grammar ) - NonnullOwnPtrVector child_conditions; - Optional condition_type {}; - auto as_condition_type = [](auto& token) -> Optional { + NonnullOwnPtrVector child_conditions; + Optional condition_type {}; + auto as_condition_type = [](auto& token) -> Optional { 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 Parser::consume_media_condition(TokenStreamtype = 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 Parser::consume_media_condition(TokenStreamtype = 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)); } // `` 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()); // `` 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 {}; diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index d36f8ac6e8..0edc8eef5a 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -235,7 +235,7 @@ private: Result parse_simple_selector(TokenStream&); NonnullRefPtr parse_media_query(TokenStream&); - OwnPtr consume_media_condition(TokenStream&); + OwnPtr consume_media_condition(TokenStream&); Optional consume_media_feature(TokenStream&); Optional consume_media_type(TokenStream&); Optional parse_media_feature_value(TokenStream&);