diff options
-rw-r--r-- | Userland/Libraries/LibWeb/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/CSSRule.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp | 6 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/CSSSupportsRule.cpp | 34 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/CSSSupportsRule.h | 47 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 24 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Dump.cpp | 14 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Dump.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Forward.h | 1 |
9 files changed, 129 insertions, 0 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 9a6f035b4a..7916a57a12 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -25,6 +25,7 @@ set(SOURCES CSS/CSSStyleDeclaration.cpp CSS/CSSStyleRule.cpp CSS/CSSStyleSheet.cpp + CSS/CSSSupportsRule.cpp CSS/ResolvedCSSStyleDeclaration.cpp CSS/DefaultStyleSheetSource.cpp CSS/Length.cpp diff --git a/Userland/Libraries/LibWeb/CSS/CSSRule.h b/Userland/Libraries/LibWeb/CSS/CSSRule.h index fa818bf806..6d04af17bb 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRule.h +++ b/Userland/Libraries/LibWeb/CSS/CSSRule.h @@ -26,6 +26,7 @@ public: Style, Import, Media, + Supports, __Count, }; diff --git a/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp b/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp index 92f02249d5..acca567e8a 100644 --- a/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp +++ b/Userland/Libraries/LibWeb/CSS/CSSRuleList.cpp @@ -8,6 +8,7 @@ #include <LibWeb/CSS/CSSImportRule.h> #include <LibWeb/CSS/CSSMediaRule.h> #include <LibWeb/CSS/CSSRuleList.h> +#include <LibWeb/CSS/CSSSupportsRule.h> #include <LibWeb/DOM/ExceptionOr.h> namespace Web::CSS { @@ -93,6 +94,9 @@ void CSSRuleList::for_each_effective_style_rule(Function<void(CSSStyleRule const case CSSRule::Type::Media: verify_cast<CSSMediaRule>(rule).for_each_effective_style_rule(callback); break; + case CSSRule::Type::Supports: + verify_cast<CSSSupportsRule>(rule).for_each_effective_style_rule(callback); + break; case CSSRule::Type::__Count: VERIFY_NOT_REACHED(); } @@ -114,6 +118,8 @@ bool CSSRuleList::for_first_not_loaded_import_rule(Function<void(CSSImportRule&) } } else if (rule.type() == CSSRule::Type::Media) { return verify_cast<CSSMediaRule>(rule).for_first_not_loaded_import_rule(callback); + } else if (rule.type() == CSSRule::Type::Supports) { + return verify_cast<CSSSupportsRule>(rule).for_first_not_loaded_import_rule(callback); } } diff --git a/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.cpp b/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.cpp new file mode 100644 index 0000000000..b949d41697 --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibWeb/CSS/CSSSupportsRule.h> +#include <LibWeb/CSS/Parser/Parser.h> + +namespace Web::CSS { + +CSSSupportsRule::CSSSupportsRule(NonnullRefPtr<Supports>&& supports, NonnullRefPtrVector<CSSRule>&& rules) + : CSSConditionRule(move(rules)) + , m_supports(move(supports)) +{ +} + +CSSSupportsRule::~CSSSupportsRule() +{ +} + +String CSSSupportsRule::condition_text() const +{ + // FIXME: Serializing supports rules! + return "<supports-condition>"; +} + +void CSSSupportsRule::set_condition_text(String text) +{ + if (auto new_supports = parse_css_supports({}, text)) + m_supports = new_supports.release_nonnull(); +} + +} diff --git a/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.h b/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.h new file mode 100644 index 0000000000..890fb563cf --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/CSSSupportsRule.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/NonnullRefPtr.h> +#include <AK/NonnullRefPtrVector.h> +#include <LibWeb/CSS/CSSConditionRule.h> +#include <LibWeb/CSS/CSSRule.h> +#include <LibWeb/CSS/Supports.h> +#include <LibWeb/Forward.h> + +namespace Web::CSS { + +// https://www.w3.org/TR/css-conditional-3/#the-csssupportsrule-interface +class CSSSupportsRule final : public CSSConditionRule { + AK_MAKE_NONCOPYABLE(CSSSupportsRule); + AK_MAKE_NONMOVABLE(CSSSupportsRule); + +public: + static NonnullRefPtr<CSSSupportsRule> create(NonnullRefPtr<Supports>&& supports, NonnullRefPtrVector<CSSRule>&& rules) + { + return adopt_ref(*new CSSSupportsRule(move(supports), move(rules))); + } + + ~CSSSupportsRule(); + + virtual StringView class_name() const override { return "CSSSupportsRule"; }; + virtual Type type() const override { return Type::Supports; }; + + String condition_text() const override; + void set_condition_text(String) override; + virtual bool condition_matches() const override { return m_supports->matches(); } + +private: + explicit CSSSupportsRule(NonnullRefPtr<Supports>&&, NonnullRefPtrVector<CSSRule>&&); + + NonnullRefPtr<Supports> m_supports; +}; + +template<> +inline bool CSSRule::fast_is<CSSSupportsRule>() const { return type() == CSSRule::Type::Supports; } + +} diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 3e07c61ded..3c5f8f5b3a 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -16,6 +16,7 @@ #include <LibWeb/CSS/CSSStyleDeclaration.h> #include <LibWeb/CSS/CSSStyleRule.h> #include <LibWeb/CSS/CSSStyleSheet.h> +#include <LibWeb/CSS/CSSSupportsRule.h> #include <LibWeb/CSS/Parser/DeclarationOrAtRule.h> #include <LibWeb/CSS/Parser/Parser.h> #include <LibWeb/CSS/Parser/StyleBlockRule.h> @@ -1735,6 +1736,29 @@ RefPtr<CSSRule> Parser::convert_to_rule(NonnullRefPtr<StyleRule> rule) return CSSImportRule::create(url.value()); else dbgln("Unable to parse url from @import rule"); + + } else if (rule->m_name.equals_ignoring_case("supports"sv)) { + + auto supports_tokens = TokenStream { rule->prelude() }; + auto supports = parse_a_supports(supports_tokens); + if (!supports) { + if constexpr (CSS_PARSER_DEBUG) { + dbgln("CSSParser: @supports rule invalid; discarding."); + supports_tokens.dump_all_tokens(); + } + return {}; + } + + auto child_tokens = TokenStream { rule->block().values() }; + auto parser_rules = consume_a_list_of_rules(child_tokens, false); + NonnullRefPtrVector<CSSRule> child_rules; + for (auto& raw_rule : parser_rules) { + if (auto child_rule = convert_to_rule(raw_rule)) + child_rules.append(*child_rule); + } + + return CSSSupportsRule::create(supports.release_nonnull(), move(child_rules)); + } else { dbgln("Unrecognized CSS at-rule: @{}", rule->m_name); } diff --git a/Userland/Libraries/LibWeb/Dump.cpp b/Userland/Libraries/LibWeb/Dump.cpp index ecad72e0be..bd805aa60f 100644 --- a/Userland/Libraries/LibWeb/Dump.cpp +++ b/Userland/Libraries/LibWeb/Dump.cpp @@ -13,6 +13,7 @@ #include <LibWeb/CSS/CSSRule.h> #include <LibWeb/CSS/CSSStyleRule.h> #include <LibWeb/CSS/CSSStyleSheet.h> +#include <LibWeb/CSS/CSSSupportsRule.h> #include <LibWeb/CSS/PropertyID.h> #include <LibWeb/DOM/Comment.h> #include <LibWeb/DOM/Document.h> @@ -500,6 +501,9 @@ void dump_rule(StringBuilder& builder, CSS::CSSRule const& rule, int indent_leve case CSS::CSSRule::Type::Media: dump_media_rule(builder, verify_cast<CSS::CSSMediaRule const>(rule), indent_levels); break; + case CSS::CSSRule::Type::Supports: + dump_supports_rule(builder, verify_cast<CSS::CSSSupportsRule const>(rule), indent_levels); + break; case CSS::CSSRule::Type::__Count: VERIFY_NOT_REACHED(); } @@ -521,6 +525,16 @@ void dump_media_rule(StringBuilder& builder, CSS::CSSMediaRule const& media, int } } +void dump_supports_rule(StringBuilder& builder, CSS::CSSSupportsRule const& supports, int indent_levels) +{ + indent(builder, indent_levels); + builder.appendff(" Supports: {}\n Rules ({}):\n", supports.condition_text(), supports.css_rules().length()); + + for (auto& rule : supports.css_rules()) { + dump_rule(builder, rule, indent_levels + 1); + } +} + void dump_style_rule(StringBuilder& builder, CSS::CSSStyleRule const& rule, int indent_levels) { for (auto& selector : rule.selectors()) { diff --git a/Userland/Libraries/LibWeb/Dump.h b/Userland/Libraries/LibWeb/Dump.h index 885e46ef08..81a7d4040a 100644 --- a/Userland/Libraries/LibWeb/Dump.h +++ b/Userland/Libraries/LibWeb/Dump.h @@ -23,6 +23,7 @@ void dump_rule(CSS::CSSRule const&); void dump_style_rule(StringBuilder&, CSS::CSSStyleRule const&, int indent_levels = 0); void dump_import_rule(StringBuilder&, CSS::CSSImportRule const&, int indent_levels = 0); void dump_media_rule(StringBuilder&, CSS::CSSMediaRule const&, int indent_levels = 0); +void dump_supports_rule(StringBuilder&, CSS::CSSSupportsRule const&, int indent_levels = 0); void dump_selector(StringBuilder&, CSS::Selector const&); void dump_selector(CSS::Selector const&); diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index cdc6d6a33b..4d01a66e97 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -26,6 +26,7 @@ class CSSRuleList; class CSSStyleDeclaration; class CSSStyleRule; class CSSStyleSheet; +class CSSSupportsRule; class Display; class ElementInlineCSSStyleDeclaration; class Length; |