summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorSam Atkins <atkinssj@serenityos.org>2021-09-27 17:12:33 +0100
committerAndreas Kling <kling@serenityos.org>2021-10-01 20:03:03 +0200
commit0a4d9c6d313a8fd5e0799dda4c64d2edd8dd1252 (patch)
treea0930a7b41b88345ca4539266c9acb711e71f3ec /Userland/Libraries
parentb90cc1148a279804ca88f2f6280067ec87cbfd75 (diff)
downloadserenity-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.txt1
-rw-r--r--Userland/Libraries/LibWeb/CSS/MediaQuery.cpp113
-rw-r--r--Userland/Libraries/LibWeb/CSS/MediaQuery.h117
-rw-r--r--Userland/Libraries/LibWeb/Forward.h2
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;