diff options
author | Sam Atkins <atkinssj@serenityos.org> | 2021-12-29 21:17:44 +0000 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-01-02 15:43:51 +0100 |
commit | ae4f0000c8e7dcfc20a8f186b547a30b005b8904 (patch) | |
tree | bad623ffbf7468c1dde1d0926d2ebd7b1679ad32 /Userland | |
parent | d470e7e817e07e133eb144daff3b4b3e77de4560 (diff) | |
download | serenity-ae4f0000c8e7dcfc20a8f186b547a30b005b8904.zip |
LibWeb: Make MediaFeature a top-level class and add factory methods
Web::CSS::MediaQuery::MediaFeature::Type was getting a bit ridiculous!
Also, this moves the detection of "min-" and "max-" media-features into
the MediaFeature itself, since this is an implementation detail, not
part of the spec.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/MediaQuery.cpp | 44 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/MediaQuery.h | 67 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 32 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.h | 2 |
4 files changed, 74 insertions, 71 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/MediaQuery.cpp b/Userland/Libraries/LibWeb/CSS/MediaQuery.cpp index b273a7a39c..53e286adcd 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaQuery.cpp +++ b/Userland/Libraries/LibWeb/CSS/MediaQuery.cpp @@ -59,30 +59,30 @@ bool MediaFeatureValue::equals(MediaFeatureValue const& other) const VERIFY_NOT_REACHED(); } -String MediaQuery::MediaFeature::to_string() const +String MediaFeature::to_string() const { - switch (type) { + switch (m_type) { case Type::IsTrue: - return name; + return m_name; case Type::ExactValue: - return String::formatted("{}:{}", name, value->to_string()); + return String::formatted("{}:{}", m_name, m_value->to_string()); case Type::MinValue: - return String::formatted("min-{}:{}", name, value->to_string()); + return String::formatted("min-{}:{}", m_name, m_value->to_string()); case Type::MaxValue: - return String::formatted("max-{}:{}", name, value->to_string()); + return String::formatted("max-{}:{}", m_name, m_value->to_string()); } VERIFY_NOT_REACHED(); } -bool MediaQuery::MediaFeature::evaluate(DOM::Window const& window) const +bool MediaFeature::evaluate(DOM::Window const& window) const { - auto maybe_queried_value = window.query_media_feature(name); + auto maybe_queried_value = window.query_media_feature(m_name); if (!maybe_queried_value.has_value()) return false; auto queried_value = maybe_queried_value.release_value(); - switch (type) { + switch (m_type) { case Type::IsTrue: if (queried_value.is_number()) return queried_value.number() != 0; @@ -93,18 +93,18 @@ bool MediaQuery::MediaFeature::evaluate(DOM::Window const& window) const return false; case Type::ExactValue: - return queried_value.equals(*value); + return queried_value.equals(*m_value); case Type::MinValue: - if (!value->is_same_type(queried_value)) + if (!m_value->is_same_type(queried_value)) return false; - if (value->is_number()) - return queried_value.number() >= value->number(); + if (m_value->is_number()) + return queried_value.number() >= m_value->number(); - if (value->is_length()) { + if (m_value->is_length()) { auto& queried_length = queried_value.length(); - auto& value_length = value->length(); + auto& value_length = m_value->length(); // FIXME: Handle relative lengths. https://www.w3.org/TR/mediaqueries-4/#ref-for-relative-length if (!value_length.is_absolute()) { dbgln("Media feature was given a non-absolute length! {}", value_length.to_string()); @@ -116,15 +116,15 @@ bool MediaQuery::MediaFeature::evaluate(DOM::Window const& window) const return false; case Type::MaxValue: - if (!value->is_same_type(queried_value)) + if (!m_value->is_same_type(queried_value)) return false; - if (value->is_number()) - return queried_value.number() <= value->number(); + if (m_value->is_number()) + return queried_value.number() <= m_value->number(); - if (value->is_length()) { + if (m_value->is_length()) { auto& queried_length = queried_value.length(); - auto& value_length = value->length(); + auto& value_length = m_value->length(); // FIXME: Handle relative lengths. https://www.w3.org/TR/mediaqueries-4/#ref-for-relative-length if (!value_length.is_absolute()) { dbgln("Media feature was given a non-absolute length! {}", value_length.to_string()); @@ -145,7 +145,7 @@ String MediaQuery::MediaCondition::to_string() const builder.append('('); switch (type) { case Type::Single: - builder.append(feature.to_string()); + builder.append(feature->to_string()); break; case Type::Not: builder.append("not "); @@ -169,7 +169,7 @@ MatchResult MediaQuery::MediaCondition::evaluate(DOM::Window const& window) cons { switch (type) { case Type::Single: - return as_match_result(feature.evaluate(window)); + return as_match_result(feature->evaluate(window)); case Type::Not: return negate(conditions.first().evaluate(window)); case Type::And: diff --git a/Userland/Libraries/LibWeb/CSS/MediaQuery.h b/Userland/Libraries/LibWeb/CSS/MediaQuery.h index b7ef4079b1..14e7b92b77 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaQuery.h +++ b/Userland/Libraries/LibWeb/CSS/MediaQuery.h @@ -69,6 +69,49 @@ private: Variant<String, Length, double> m_value; }; +// https://www.w3.org/TR/mediaqueries-4/#mq-features +class MediaFeature { +public: + // Corresponds to `<mf-boolean>` grammar + static MediaFeature boolean(String const& name) + { + return MediaFeature(Type::IsTrue, name); + } + + // Corresponds to `<mf-plain>` grammar + static MediaFeature plain(String const& name, MediaFeatureValue value) + { + if (name.starts_with("min-", CaseSensitivity::CaseInsensitive)) + return MediaFeature(Type::MinValue, name.substring_view(4), move(value)); + if (name.starts_with("max-", CaseSensitivity::CaseInsensitive)) + return MediaFeature(Type::MaxValue, name.substring_view(4), move(value)); + return MediaFeature(Type::ExactValue, move(name), move(value)); + } + + bool evaluate(DOM::Window const&) const; + String to_string() const; + +private: + // FIXME: Implement range syntax: https://www.w3.org/TR/mediaqueries-4/#mq-ranges + enum class Type { + IsTrue, + ExactValue, + MinValue, + MaxValue, + }; + + MediaFeature(Type type, FlyString name, Optional<MediaFeatureValue> value = {}) + : m_type(type) + , m_name(move(name)) + , m_value(move(value)) + { + } + + Type m_type; + FlyString m_name; + Optional<MediaFeatureValue> m_value {}; +}; + class MediaQuery : public RefCounted<MediaQuery> { friend class Parser; @@ -92,24 +135,6 @@ public: Speech, }; - // https://www.w3.org/TR/mediaqueries-4/#mq-features - struct MediaFeature { - // FIXME: Implement range syntax: https://www.w3.org/TR/mediaqueries-4/#mq-ranges - enum class Type { - IsTrue, - ExactValue, - MinValue, - MaxValue, - }; - - Type type; - FlyString name; - Optional<MediaFeatureValue> value {}; - - bool evaluate(DOM::Window const&) const; - String to_string() const; - }; - // https://www.w3.org/TR/mediaqueries-4/#media-conditions struct MediaCondition { enum class Type { @@ -121,7 +146,7 @@ public: }; Type type; - MediaFeature feature; + Optional<MediaFeature> feature; NonnullOwnPtrVector<MediaCondition> conditions; Optional<GeneralEnclosed> general_enclosed; @@ -155,8 +180,8 @@ String serialize_a_media_query_list(NonnullRefPtrVector<MediaQuery> const&); namespace AK { template<> -struct Formatter<Web::CSS::MediaQuery::MediaFeature> : Formatter<StringView> { - ErrorOr<void> format(FormatBuilder& builder, Web::CSS::MediaQuery::MediaFeature const& media_feature) +struct Formatter<Web::CSS::MediaFeature> : Formatter<StringView> { + ErrorOr<void> format(FormatBuilder& builder, Web::CSS::MediaFeature const& media_feature) { return Formatter<StringView>::format(builder, media_feature.to_string()); } diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 972116b29b..b016f9b9f4 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -860,11 +860,11 @@ OwnPtr<MediaQuery::MediaCondition> Parser::consume_media_condition(TokenStream<S return {}; } -Optional<MediaQuery::MediaFeature> Parser::consume_media_feature(TokenStream<StyleComponentValueRule>& outer_tokens) +Optional<MediaFeature> Parser::consume_media_feature(TokenStream<StyleComponentValueRule>& outer_tokens) { outer_tokens.skip_whitespace(); - auto invalid_feature = [&]() -> Optional<MediaQuery::MediaFeature> { + auto invalid_feature = [&]() -> Optional<MediaFeature> { outer_tokens.reconsume_current_input_token(); return {}; }; @@ -884,12 +884,8 @@ Optional<MediaQuery::MediaFeature> Parser::consume_media_feature(TokenStream<Sty auto feature_name = name_token.token().ident(); tokens.skip_whitespace(); - if (!tokens.has_next_token()) { - return MediaQuery::MediaFeature { - .type = MediaQuery::MediaFeature::Type::IsTrue, - .name = feature_name, - }; - } + if (!tokens.has_next_token()) + return MediaFeature::boolean(feature_name); if (!tokens.next_token().is(Token::Type::Colon)) return invalid_feature(); @@ -902,25 +898,7 @@ Optional<MediaQuery::MediaFeature> Parser::consume_media_feature(TokenStream<Sty if (tokens.has_next_token()) return invalid_feature(); - if (feature_name.starts_with("min-", CaseSensitivity::CaseInsensitive)) { - return MediaQuery::MediaFeature { - .type = MediaQuery::MediaFeature::Type::MinValue, - .name = feature_name.substring_view(4), - .value = value.release_value(), - }; - } else if (feature_name.starts_with("max-", CaseSensitivity::CaseInsensitive)) { - return MediaQuery::MediaFeature { - .type = MediaQuery::MediaFeature::Type::MaxValue, - .name = feature_name.substring_view(4), - .value = value.release_value(), - }; - } - - return MediaQuery::MediaFeature { - .type = MediaQuery::MediaFeature::Type::ExactValue, - .name = feature_name, - .value = value.release_value(), - }; + return MediaFeature::plain(feature_name, value.release_value()); } return invalid_feature(); diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index 28640ce686..d36f8ac6e8 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -236,7 +236,7 @@ private: NonnullRefPtr<MediaQuery> parse_media_query(TokenStream<StyleComponentValueRule>&); OwnPtr<MediaQuery::MediaCondition> consume_media_condition(TokenStream<StyleComponentValueRule>&); - Optional<MediaQuery::MediaFeature> consume_media_feature(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>&); |