diff options
author | Sam Atkins <atkinssj@serenityos.org> | 2021-09-27 17:12:33 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-10-01 20:03:03 +0200 |
commit | 0a4d9c6d313a8fd5e0799dda4c64d2edd8dd1252 (patch) | |
tree | a0930a7b41b88345ca4539266c9acb711e71f3ec /Userland/Libraries | |
parent | b90cc1148a279804ca88f2f6280067ec87cbfd75 (diff) | |
download | serenity-0a4d9c6d313a8fd5e0799dda4c64d2edd8dd1252.zip |
LibWeb: Partially implement MediaQuery class :^)
The main thing that's missing is the actual matching, but this is enough
to get started.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibWeb/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/MediaQuery.cpp | 113 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/MediaQuery.h | 117 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Forward.h | 2 |
4 files changed, 233 insertions, 0 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index a2f0517ea0..911e28bd83 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -25,6 +25,7 @@ set(SOURCES CSS/ResolvedCSSStyleDeclaration.cpp CSS/DefaultStyleSheetSource.cpp CSS/Length.cpp + CSS/MediaQuery.cpp CSS/MediaQueryList.cpp CSS/Parser/Parser.cpp CSS/Parser/StyleRules.cpp diff --git a/Userland/Libraries/LibWeb/CSS/MediaQuery.cpp b/Userland/Libraries/LibWeb/CSS/MediaQuery.cpp new file mode 100644 index 0000000000..507d28a48a --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/MediaQuery.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibWeb/CSS/MediaQuery.h> + +namespace Web::CSS { + +NonnullRefPtr<MediaQuery> MediaQuery::create_not_all() +{ + auto media_query = new MediaQuery; + media_query->m_negated = true; + media_query->m_media_type = MediaType::All; + + return adopt_ref(*media_query); +} + +String MediaQuery::MediaFeature::to_string() const +{ + switch (type) { + case Type::IsTrue: + return name; + case Type::ExactValue: + return String::formatted("{}:{}", name, value->to_string()); + case Type::MinValue: + return String::formatted("min-{}:{}", name, value->to_string()); + case Type::MaxValue: + return String::formatted("max-{}:{}", name, value->to_string()); + } + + VERIFY_NOT_REACHED(); +} + +String MediaQuery::MediaCondition::to_string() const +{ + StringBuilder builder; + builder.append('('); + switch (type) { + case Type::Single: + builder.append(feature.to_string()); + break; + case Type::Not: + builder.append("not "); + builder.append(conditions.first().to_string()); + break; + case Type::And: + builder.join(" and ", conditions); + break; + case Type::Or: + builder.join(" or ", conditions); + break; + } + builder.append(')'); + return builder.to_string(); +} + +String MediaQuery::to_string() const +{ + StringBuilder builder; + + if (m_negated) + builder.append("not "); + + if (m_negated || m_media_type != MediaType::All || !m_media_condition) { + switch (m_media_type) { + case MediaType::All: + builder.append("all"); + break; + case MediaType::Aural: + builder.append("aural"); + break; + case MediaType::Braille: + builder.append("braille"); + break; + case MediaType::Embossed: + builder.append("embossed"); + break; + case MediaType::Handheld: + builder.append("handheld"); + break; + case MediaType::Print: + builder.append("print"); + break; + case MediaType::Projection: + builder.append("projection"); + break; + case MediaType::Screen: + builder.append("screen"); + break; + case MediaType::Speech: + builder.append("speech"); + break; + case MediaType::TTY: + builder.append("tty"); + break; + case MediaType::TV: + builder.append("tv"); + break; + } + if (m_media_condition) + builder.append(" and "); + } + + if (m_media_condition) { + builder.append(m_media_condition->to_string()); + } + + return builder.to_string(); +} + +} diff --git a/Userland/Libraries/LibWeb/CSS/MediaQuery.h b/Userland/Libraries/LibWeb/CSS/MediaQuery.h new file mode 100644 index 0000000000..97775333c3 --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/MediaQuery.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/FlyString.h> +#include <AK/NonnullOwnPtrVector.h> +#include <AK/NonnullRefPtr.h> +#include <AK/Optional.h> +#include <AK/OwnPtr.h> +#include <AK/RefCounted.h> +#include <LibWeb/CSS/StyleValue.h> + +namespace Web::CSS { + +class MediaQuery : public RefCounted<MediaQuery> { + friend class Parser; + +public: + ~MediaQuery() { } + + // https://www.w3.org/TR/mediaqueries-4/#media-types + enum class MediaType { + All, + Print, + Screen, + + // Deprecated, must never match: + TTY, + TV, + Projection, + Handheld, + Braille, + Embossed, + Aural, + 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; + RefPtr<StyleValue> value { nullptr }; + + String to_string() const; + }; + + // https://www.w3.org/TR/mediaqueries-4/#media-conditions + struct MediaCondition { + enum class Type { + Single, + And, + Or, + Not, + }; + + Type type; + MediaFeature feature; + NonnullOwnPtrVector<MediaCondition> conditions; + + String to_string() const; + }; + + static NonnullRefPtr<MediaQuery> create_not_all(); + static NonnullRefPtr<MediaQuery> create() { return adopt_ref(*new MediaQuery); } + + String to_string() const; + +private: + MediaQuery() { } + + // https://www.w3.org/TR/mediaqueries-4/#mq-not + bool m_negated { false }; + MediaType m_media_type { MediaType::All }; + OwnPtr<MediaCondition> m_media_condition { nullptr }; +}; + +} + +namespace AK { + +template<> +struct Formatter<Web::CSS::MediaQuery::MediaFeature> : Formatter<StringView> { + void format(FormatBuilder& builder, Web::CSS::MediaQuery::MediaFeature const& media_feature) + { + Formatter<StringView>::format(builder, media_feature.to_string()); + } +}; + +template<> +struct Formatter<Web::CSS::MediaQuery::MediaCondition> : Formatter<StringView> { + void format(FormatBuilder& builder, Web::CSS::MediaQuery::MediaCondition const& media_condition) + { + Formatter<StringView>::format(builder, media_condition.to_string()); + } +}; + +template<> +struct Formatter<Web::CSS::MediaQuery> : Formatter<StringView> { + void format(FormatBuilder& builder, Web::CSS::MediaQuery const& media_query) + { + Formatter<StringView>::format(builder, media_query.to_string()); + } +}; + +} diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 66f27a3e00..a456b8bae0 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -26,6 +26,8 @@ class CSSStyleRule; class CSSStyleSheet; class ElementInlineCSSStyleDeclaration; class Length; +class MediaQuery; +class MediaQueryList; class PropertyOwningCSSStyleDeclaration; class Screen; class Selector; |