Supports.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibJS/Runtime/Realm.h>
  7. #include <LibWeb/CSS/Parser/Parser.h>
  8. #include <LibWeb/CSS/Supports.h>
  9. namespace Web::CSS {
  10. static void indent(StringBuilder& builder, int levels)
  11. {
  12. for (int i = 0; i < levels; i++)
  13. builder.append(" "sv);
  14. }
  15. Supports::Supports(JS::Realm& realm, NonnullOwnPtr<Condition>&& condition)
  16. : m_condition(move(condition))
  17. {
  18. m_matches = m_condition->evaluate(realm);
  19. }
  20. bool Supports::Condition::evaluate(JS::Realm& realm) const
  21. {
  22. switch (type) {
  23. case Type::Not:
  24. return !children.first().evaluate(realm);
  25. case Type::And:
  26. for (auto& child : children) {
  27. if (!child.evaluate(realm))
  28. return false;
  29. }
  30. return true;
  31. case Type::Or:
  32. for (auto& child : children) {
  33. if (child.evaluate(realm))
  34. return true;
  35. }
  36. return false;
  37. }
  38. VERIFY_NOT_REACHED();
  39. }
  40. bool Supports::InParens::evaluate(JS::Realm& realm) const
  41. {
  42. return value.visit(
  43. [&](NonnullOwnPtr<Condition> const& condition) {
  44. return condition->evaluate(realm);
  45. },
  46. [&](Feature const& feature) {
  47. return feature.evaluate(realm);
  48. },
  49. [&](GeneralEnclosed const&) {
  50. return false;
  51. });
  52. }
  53. bool Supports::Declaration::evaluate(JS::Realm& realm) const
  54. {
  55. auto style_property = parse_css_supports_condition(Parser::ParsingContext { realm }, declaration);
  56. return style_property.has_value();
  57. }
  58. bool Supports::Selector::evaluate(JS::Realm& realm) const
  59. {
  60. auto style_property = parse_selector(Parser::ParsingContext { realm }, selector);
  61. return style_property.has_value();
  62. }
  63. bool Supports::Feature::evaluate(JS::Realm& realm) const
  64. {
  65. return value.visit(
  66. [&](Declaration const& declaration) {
  67. return declaration.evaluate(realm);
  68. },
  69. [&](Selector const& selector) {
  70. return selector.evaluate(realm);
  71. });
  72. }
  73. String Supports::Declaration::to_string() const
  74. {
  75. return MUST(String::formatted("({})", declaration));
  76. }
  77. String Supports::Selector::to_string() const
  78. {
  79. return MUST(String::formatted("selector({})", selector));
  80. }
  81. String Supports::Feature::to_string() const
  82. {
  83. return value.visit([](auto& it) { return it.to_string(); });
  84. }
  85. String Supports::InParens::to_string() const
  86. {
  87. return value.visit(
  88. [](NonnullOwnPtr<Condition> const& condition) { return MUST(String::formatted("({})", condition->to_string())); },
  89. [](Supports::Feature const& it) { return it.to_string(); },
  90. [](GeneralEnclosed const& it) { return it.to_string(); });
  91. }
  92. String Supports::Condition::to_string() const
  93. {
  94. switch (type) {
  95. case Type::Not:
  96. return MUST(String::formatted("not {}", children.first().to_string()));
  97. case Type::And:
  98. return MUST(String::join(" and "sv, children));
  99. case Type::Or:
  100. return MUST(String::join(" or "sv, children));
  101. }
  102. VERIFY_NOT_REACHED();
  103. }
  104. String Supports::to_string() const
  105. {
  106. return m_condition->to_string();
  107. }
  108. void Supports::Declaration::dump(StringBuilder& builder, int indent_levels) const
  109. {
  110. indent(builder, indent_levels);
  111. builder.appendff("Declaration: {}\n", declaration);
  112. }
  113. void Supports::Selector::dump(StringBuilder& builder, int indent_levels) const
  114. {
  115. indent(builder, indent_levels);
  116. builder.appendff("Selector: {}\n", selector);
  117. }
  118. void Supports::Feature::dump(StringBuilder& builder, int indent_levels) const
  119. {
  120. value.visit([&](auto& it) { it.dump(builder, indent_levels); });
  121. }
  122. void Supports::InParens::dump(StringBuilder& builder, int indent_levels) const
  123. {
  124. value.visit(
  125. [&](NonnullOwnPtr<Condition> const& condition) { condition->dump(builder, indent_levels); },
  126. [&](Supports::Feature const& it) { it.dump(builder, indent_levels); },
  127. [&](GeneralEnclosed const& it) {
  128. indent(builder, indent_levels);
  129. builder.appendff("GeneralEnclosed: {}\n", it.to_string());
  130. });
  131. }
  132. void Supports::Condition::dump(StringBuilder& builder, int indent_levels) const
  133. {
  134. indent(builder, indent_levels);
  135. StringView type_name = [](Type type) {
  136. switch (type) {
  137. case Type::And:
  138. return "AND"sv;
  139. case Type::Or:
  140. return "OR"sv;
  141. case Type::Not:
  142. return "NOT"sv;
  143. }
  144. VERIFY_NOT_REACHED();
  145. }(type);
  146. builder.appendff("Condition: {}\n", type_name);
  147. for (auto const& child : children)
  148. child.dump(builder, indent_levels + 1);
  149. }
  150. void Supports::dump(StringBuilder& builder, int indent_levels) const
  151. {
  152. m_condition->dump(builder, indent_levels);
  153. }
  154. }