Serenity Operating System
1/*
2 * Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <LibJS/Runtime/Realm.h>
8#include <LibWeb/CSS/Parser/Parser.h>
9#include <LibWeb/CSS/Supports.h>
10
11namespace Web::CSS {
12
13Supports::Supports(NonnullOwnPtr<Condition>&& condition)
14 : m_condition(move(condition))
15{
16 m_matches = m_condition->evaluate();
17}
18
19bool Supports::Condition::evaluate() const
20{
21 switch (type) {
22 case Type::Not:
23 return !children.first().evaluate();
24 case Type::And:
25 for (auto& child : children) {
26 if (!child.evaluate())
27 return false;
28 }
29 return true;
30 case Type::Or:
31 for (auto& child : children) {
32 if (child.evaluate())
33 return true;
34 }
35 return false;
36 }
37 VERIFY_NOT_REACHED();
38}
39
40bool Supports::InParens::evaluate() const
41{
42 return value.visit(
43 [&](NonnullOwnPtr<Condition> const& condition) {
44 return condition->evaluate();
45 },
46 [&](Feature const& feature) {
47 return feature.evaluate();
48 },
49 [&](GeneralEnclosed const&) {
50 return false;
51 });
52}
53
54bool Supports::Declaration::evaluate() const
55{
56 auto style_property = parse_css_supports_condition(Parser::ParsingContext { *realm }, declaration);
57 return style_property.has_value();
58}
59
60bool Supports::Selector::evaluate() const
61{
62 auto style_property = parse_selector(Parser::ParsingContext { *realm }, selector);
63 return style_property.has_value();
64}
65
66bool Supports::Feature::evaluate() const
67{
68 return value.visit(
69 [&](Declaration const& declaration) {
70 return declaration.evaluate();
71 },
72 [&](Selector const& selector) {
73 return selector.evaluate();
74 });
75}
76
77ErrorOr<String> Supports::Declaration::to_string() const
78{
79 return String::formatted("({})", declaration);
80}
81
82ErrorOr<String> Supports::Selector::to_string() const
83{
84 return String::formatted("selector({})", selector);
85}
86
87ErrorOr<String> Supports::Feature::to_string() const
88{
89 return value.visit([](auto& it) { return it.to_string(); });
90}
91
92ErrorOr<String> Supports::InParens::to_string() const
93{
94 return value.visit(
95 [](NonnullOwnPtr<Condition> const& condition) -> ErrorOr<String> { return String::formatted("({})", TRY(condition->to_string())); },
96 [](Supports::Feature const& it) -> ErrorOr<String> { return it.to_string(); },
97 [](GeneralEnclosed const& it) -> ErrorOr<String> { return it.to_string(); });
98}
99
100ErrorOr<String> Supports::Condition::to_string() const
101{
102 switch (type) {
103 case Type::Not:
104 return String::formatted("not {}", TRY(children.first().to_string()));
105 case Type::And:
106 return String::join(" and "sv, children);
107 case Type::Or:
108 return String::join(" or "sv, children);
109 }
110 VERIFY_NOT_REACHED();
111}
112
113ErrorOr<String> Supports::to_string() const
114{
115 return m_condition->to_string();
116}
117
118}