/src/serenity/Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2019-2021, Andreas Kling <kling@serenityos.org> |
3 | | * Copyright (c) 2024, Tim Ledbetter <timledbetter@gmail.com> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #pragma once |
9 | | |
10 | | #include <AK/Function.h> |
11 | | #include <LibWeb/CSS/CSSNamespaceRule.h> |
12 | | #include <LibWeb/CSS/CSSRule.h> |
13 | | #include <LibWeb/CSS/CSSRuleList.h> |
14 | | #include <LibWeb/CSS/CSSStyleRule.h> |
15 | | #include <LibWeb/CSS/StyleSheet.h> |
16 | | #include <LibWeb/WebIDL/Types.h> |
17 | | |
18 | | namespace Web::CSS { |
19 | | |
20 | | class CSSImportRule; |
21 | | class FontLoader; |
22 | | |
23 | | struct CSSStyleSheetInit { |
24 | | Optional<String> base_url {}; |
25 | | Variant<JS::Handle<MediaList>, String> media { String {} }; |
26 | | bool disabled { false }; |
27 | | }; |
28 | | |
29 | | class CSSStyleSheet final : public StyleSheet { |
30 | | WEB_PLATFORM_OBJECT(CSSStyleSheet, StyleSheet); |
31 | | JS_DECLARE_ALLOCATOR(CSSStyleSheet); |
32 | | |
33 | | public: |
34 | | [[nodiscard]] static JS::NonnullGCPtr<CSSStyleSheet> create(JS::Realm&, CSSRuleList&, MediaList&, Optional<URL::URL> location); |
35 | | static WebIDL::ExceptionOr<JS::NonnullGCPtr<CSSStyleSheet>> construct_impl(JS::Realm&, Optional<CSSStyleSheetInit> const& options = {}); |
36 | | |
37 | 0 | virtual ~CSSStyleSheet() override = default; |
38 | | |
39 | 0 | JS::GCPtr<CSSRule const> owner_rule() const { return m_owner_css_rule; } |
40 | 0 | JS::GCPtr<CSSRule> owner_rule() { return m_owner_css_rule; } |
41 | 0 | void set_owner_css_rule(CSSRule* rule) { m_owner_css_rule = rule; } |
42 | | |
43 | 0 | virtual String type() const override { return "text/css"_string; } |
44 | | |
45 | 0 | CSSRuleList const& rules() const { return *m_rules; } |
46 | 0 | CSSRuleList& rules() { return *m_rules; } |
47 | | |
48 | 0 | CSSRuleList* css_rules() { return m_rules; } |
49 | 0 | CSSRuleList const* css_rules() const { return m_rules; } |
50 | | |
51 | | WebIDL::ExceptionOr<unsigned> insert_rule(StringView rule, unsigned index); |
52 | | WebIDL::ExceptionOr<WebIDL::Long> add_rule(Optional<String> selector, Optional<String> style, Optional<WebIDL::UnsignedLong> index); |
53 | | WebIDL::ExceptionOr<void> remove_rule(Optional<WebIDL::UnsignedLong> index); |
54 | | WebIDL::ExceptionOr<void> delete_rule(unsigned index); |
55 | | |
56 | | JS::NonnullGCPtr<JS::Promise> replace(String text); |
57 | | WebIDL::ExceptionOr<void> replace_sync(StringView text); |
58 | | |
59 | | void for_each_effective_rule(TraversalOrder, Function<void(CSSRule const&)> const& callback) const; |
60 | | void for_each_effective_style_producing_rule(Function<void(CSSRule const&)> const& callback) const; |
61 | | // Returns whether the match state of any media queries changed after evaluation. |
62 | | bool evaluate_media_queries(HTML::Window const&); |
63 | | void for_each_effective_keyframes_at_rule(Function<void(CSSKeyframesRule const&)> const& callback) const; |
64 | | |
65 | 0 | JS::GCPtr<StyleSheetList> style_sheet_list() const { return m_style_sheet_list; } |
66 | | void set_style_sheet_list(Badge<StyleSheetList>, StyleSheetList*); |
67 | | |
68 | | Optional<FlyString> default_namespace() const; |
69 | 0 | JS::GCPtr<CSSNamespaceRule> default_namespace_rule() const { return m_default_namespace_rule; } |
70 | | |
71 | | Optional<FlyString> namespace_uri(StringView namespace_prefix) const; |
72 | | |
73 | 0 | Vector<JS::NonnullGCPtr<CSSImportRule>> const& import_rules() const { return m_import_rules; } |
74 | | |
75 | 0 | Optional<URL::URL> base_url() const { return m_base_url; } |
76 | 0 | void set_base_url(Optional<URL::URL> base_url) { m_base_url = move(base_url); } |
77 | | |
78 | 0 | bool constructed() const { return m_constructed; } |
79 | | |
80 | 0 | JS::GCPtr<DOM::Document const> constructor_document() const { return m_constructor_document; } |
81 | 0 | void set_constructor_document(JS::GCPtr<DOM::Document const> constructor_document) { m_constructor_document = constructor_document; } |
82 | | |
83 | 0 | bool disallow_modification() const { return m_disallow_modification; } |
84 | | |
85 | | void set_source_text(String); |
86 | | Optional<String> source_text(Badge<DOM::Document>) const; |
87 | | |
88 | | void add_associated_font_loader(WeakPtr<FontLoader const> font_loader) |
89 | 0 | { |
90 | 0 | m_associated_font_loaders.append(font_loader); |
91 | 0 | } |
92 | | bool has_associated_font_loader(FontLoader& font_loader) const; |
93 | | |
94 | | private: |
95 | | CSSStyleSheet(JS::Realm&, CSSRuleList&, MediaList&, Optional<URL::URL> location); |
96 | | |
97 | | virtual void initialize(JS::Realm&) override; |
98 | | virtual void visit_edges(Cell::Visitor&) override; |
99 | | |
100 | | void recalculate_rule_caches(); |
101 | | |
102 | 0 | void set_constructed(bool constructed) { m_constructed = constructed; } |
103 | 0 | void set_disallow_modification(bool disallow_modification) { m_disallow_modification = disallow_modification; } |
104 | | |
105 | | Optional<String> m_source_text; |
106 | | |
107 | | JS::GCPtr<CSSRuleList> m_rules; |
108 | | JS::GCPtr<CSSNamespaceRule> m_default_namespace_rule; |
109 | | HashMap<FlyString, JS::GCPtr<CSSNamespaceRule>> m_namespace_rules; |
110 | | Vector<JS::NonnullGCPtr<CSSImportRule>> m_import_rules; |
111 | | |
112 | | JS::GCPtr<StyleSheetList> m_style_sheet_list; |
113 | | JS::GCPtr<CSSRule> m_owner_css_rule; |
114 | | |
115 | | Optional<URL::URL> m_base_url; |
116 | | JS::GCPtr<DOM::Document const> m_constructor_document; |
117 | | bool m_constructed { false }; |
118 | | bool m_disallow_modification { false }; |
119 | | Optional<bool> m_did_match; |
120 | | |
121 | | Vector<WeakPtr<FontLoader const>> m_associated_font_loaders; |
122 | | }; |
123 | | |
124 | | } |