mirror of
https://github.com/RGBCube/serenity
synced 2025-07-19 07:37:34 +00:00
LibWeb: Make MediaCondition a top-level type and add factory methods
This commit is contained in:
parent
ae4f0000c8
commit
b6fe7cc324
4 changed files with 93 additions and 57 deletions
|
@ -139,7 +139,52 @@ bool MediaFeature::evaluate(DOM::Window const& window) const
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
String MediaQuery::MediaCondition::to_string() const
|
NonnullOwnPtr<MediaCondition> MediaCondition::from_general_enclosed(GeneralEnclosed&& general_enclosed)
|
||||||
|
{
|
||||||
|
auto result = new MediaCondition;
|
||||||
|
result->type = Type::GeneralEnclosed;
|
||||||
|
result->general_enclosed = move(general_enclosed);
|
||||||
|
|
||||||
|
return adopt_own(*result);
|
||||||
|
}
|
||||||
|
|
||||||
|
NonnullOwnPtr<MediaCondition> MediaCondition::from_feature(MediaFeature&& feature)
|
||||||
|
{
|
||||||
|
auto result = new MediaCondition;
|
||||||
|
result->type = Type::Single;
|
||||||
|
result->feature = move(feature);
|
||||||
|
|
||||||
|
return adopt_own(*result);
|
||||||
|
}
|
||||||
|
|
||||||
|
NonnullOwnPtr<MediaCondition> MediaCondition::from_not(NonnullOwnPtr<MediaCondition>&& condition)
|
||||||
|
{
|
||||||
|
auto result = new MediaCondition;
|
||||||
|
result->type = Type::Not;
|
||||||
|
result->conditions.append(move(condition));
|
||||||
|
|
||||||
|
return adopt_own(*result);
|
||||||
|
}
|
||||||
|
|
||||||
|
NonnullOwnPtr<MediaCondition> MediaCondition::from_and_list(NonnullOwnPtrVector<MediaCondition>&& conditions)
|
||||||
|
{
|
||||||
|
auto result = new MediaCondition;
|
||||||
|
result->type = Type::And;
|
||||||
|
result->conditions = move(conditions);
|
||||||
|
|
||||||
|
return adopt_own(*result);
|
||||||
|
}
|
||||||
|
|
||||||
|
NonnullOwnPtr<MediaCondition> MediaCondition::from_or_list(NonnullOwnPtrVector<MediaCondition>&& conditions)
|
||||||
|
{
|
||||||
|
auto result = new MediaCondition;
|
||||||
|
result->type = Type::Or;
|
||||||
|
result->conditions = move(conditions);
|
||||||
|
|
||||||
|
return adopt_own(*result);
|
||||||
|
}
|
||||||
|
|
||||||
|
String MediaCondition::to_string() const
|
||||||
{
|
{
|
||||||
StringBuilder builder;
|
StringBuilder builder;
|
||||||
builder.append('(');
|
builder.append('(');
|
||||||
|
@ -165,7 +210,7 @@ String MediaQuery::MediaCondition::to_string() const
|
||||||
return builder.to_string();
|
return builder.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
MatchResult MediaQuery::MediaCondition::evaluate(DOM::Window const& window) const
|
MatchResult MediaCondition::evaluate(DOM::Window const& window) const
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Type::Single:
|
case Type::Single:
|
||||||
|
|
|
@ -112,6 +112,33 @@ private:
|
||||||
Optional<MediaFeatureValue> m_value {};
|
Optional<MediaFeatureValue> m_value {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/mediaqueries-4/#media-conditions
|
||||||
|
struct MediaCondition {
|
||||||
|
enum class Type {
|
||||||
|
Single,
|
||||||
|
And,
|
||||||
|
Or,
|
||||||
|
Not,
|
||||||
|
GeneralEnclosed,
|
||||||
|
};
|
||||||
|
|
||||||
|
static NonnullOwnPtr<MediaCondition> from_general_enclosed(GeneralEnclosed&&);
|
||||||
|
static NonnullOwnPtr<MediaCondition> from_feature(MediaFeature&&);
|
||||||
|
static NonnullOwnPtr<MediaCondition> from_not(NonnullOwnPtr<MediaCondition>&&);
|
||||||
|
static NonnullOwnPtr<MediaCondition> from_and_list(NonnullOwnPtrVector<MediaCondition>&&);
|
||||||
|
static NonnullOwnPtr<MediaCondition> from_or_list(NonnullOwnPtrVector<MediaCondition>&&);
|
||||||
|
|
||||||
|
MatchResult evaluate(DOM::Window const&) const;
|
||||||
|
String to_string() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MediaCondition() { }
|
||||||
|
Type type;
|
||||||
|
Optional<MediaFeature> feature;
|
||||||
|
NonnullOwnPtrVector<MediaCondition> conditions;
|
||||||
|
Optional<GeneralEnclosed> general_enclosed;
|
||||||
|
};
|
||||||
|
|
||||||
class MediaQuery : public RefCounted<MediaQuery> {
|
class MediaQuery : public RefCounted<MediaQuery> {
|
||||||
friend class Parser;
|
friend class Parser;
|
||||||
|
|
||||||
|
@ -135,25 +162,6 @@ public:
|
||||||
Speech,
|
Speech,
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://www.w3.org/TR/mediaqueries-4/#media-conditions
|
|
||||||
struct MediaCondition {
|
|
||||||
enum class Type {
|
|
||||||
Single,
|
|
||||||
And,
|
|
||||||
Or,
|
|
||||||
Not,
|
|
||||||
GeneralEnclosed,
|
|
||||||
};
|
|
||||||
|
|
||||||
Type type;
|
|
||||||
Optional<MediaFeature> feature;
|
|
||||||
NonnullOwnPtrVector<MediaCondition> conditions;
|
|
||||||
Optional<GeneralEnclosed> general_enclosed;
|
|
||||||
|
|
||||||
MatchResult evaluate(DOM::Window const&) const;
|
|
||||||
String to_string() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
static NonnullRefPtr<MediaQuery> create_not_all();
|
static NonnullRefPtr<MediaQuery> create_not_all();
|
||||||
static NonnullRefPtr<MediaQuery> create() { return adopt_ref(*new MediaQuery); }
|
static NonnullRefPtr<MediaQuery> create() { return adopt_ref(*new MediaQuery); }
|
||||||
|
|
||||||
|
@ -188,8 +196,8 @@ struct Formatter<Web::CSS::MediaFeature> : Formatter<StringView> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Formatter<Web::CSS::MediaQuery::MediaCondition> : Formatter<StringView> {
|
struct Formatter<Web::CSS::MediaCondition> : Formatter<StringView> {
|
||||||
ErrorOr<void> format(FormatBuilder& builder, Web::CSS::MediaQuery::MediaCondition const& media_condition)
|
ErrorOr<void> format(FormatBuilder& builder, Web::CSS::MediaCondition const& media_condition)
|
||||||
{
|
{
|
||||||
return Formatter<StringView>::format(builder, media_condition.to_string());
|
return Formatter<StringView>::format(builder, media_condition.to_string());
|
||||||
}
|
}
|
||||||
|
|
|
@ -749,7 +749,7 @@ NonnullRefPtr<MediaQuery> Parser::parse_media_query(TokenStream<StyleComponentVa
|
||||||
return invalid_media_query();
|
return invalid_media_query();
|
||||||
}
|
}
|
||||||
|
|
||||||
OwnPtr<MediaQuery::MediaCondition> Parser::consume_media_condition(TokenStream<StyleComponentValueRule>& tokens)
|
OwnPtr<MediaCondition> Parser::consume_media_condition(TokenStream<StyleComponentValueRule>& tokens)
|
||||||
{
|
{
|
||||||
// "not <media-condition>"
|
// "not <media-condition>"
|
||||||
// ( `<media-not>` in the grammar )
|
// ( `<media-not>` in the grammar )
|
||||||
|
@ -758,13 +758,8 @@ OwnPtr<MediaQuery::MediaCondition> Parser::consume_media_condition(TokenStream<S
|
||||||
if (first_token.is(Token::Type::Ident) && first_token.token().ident().equals_ignoring_case("not"sv)) {
|
if (first_token.is(Token::Type::Ident) && first_token.token().ident().equals_ignoring_case("not"sv)) {
|
||||||
tokens.next_token();
|
tokens.next_token();
|
||||||
|
|
||||||
auto condition = new MediaQuery::MediaCondition;
|
if (auto child_condition = consume_media_condition(tokens))
|
||||||
condition->type = MediaQuery::MediaCondition::Type::Not;
|
return MediaCondition::from_not(child_condition.release_nonnull());
|
||||||
|
|
||||||
if (auto child_condition = consume_media_condition(tokens)) {
|
|
||||||
condition->conditions.append(child_condition.release_nonnull());
|
|
||||||
return adopt_own(*condition);
|
|
||||||
}
|
|
||||||
|
|
||||||
tokens.rewind_to_position(position);
|
tokens.rewind_to_position(position);
|
||||||
return {};
|
return {};
|
||||||
|
@ -772,16 +767,16 @@ OwnPtr<MediaQuery::MediaCondition> Parser::consume_media_condition(TokenStream<S
|
||||||
|
|
||||||
// "<media-condition> ([and | or] <media-condition>)*"
|
// "<media-condition> ([and | or] <media-condition>)*"
|
||||||
// ( `<media-in-parens> [ <media-and>* | <media-or>* ]` in the grammar )
|
// ( `<media-in-parens> [ <media-and>* | <media-or>* ]` in the grammar )
|
||||||
NonnullOwnPtrVector<MediaQuery::MediaCondition> child_conditions;
|
NonnullOwnPtrVector<MediaCondition> child_conditions;
|
||||||
Optional<MediaQuery::MediaCondition::Type> condition_type {};
|
Optional<MediaCondition::Type> condition_type {};
|
||||||
auto as_condition_type = [](auto& token) -> Optional<MediaQuery::MediaCondition::Type> {
|
auto as_condition_type = [](auto& token) -> Optional<MediaCondition::Type> {
|
||||||
if (!token.is(Token::Type::Ident))
|
if (!token.is(Token::Type::Ident))
|
||||||
return {};
|
return {};
|
||||||
auto ident = token.token().ident();
|
auto ident = token.token().ident();
|
||||||
if (ident.equals_ignoring_case("and"))
|
if (ident.equals_ignoring_case("and"))
|
||||||
return MediaQuery::MediaCondition::Type::And;
|
return MediaCondition::Type::And;
|
||||||
if (ident.equals_ignoring_case("or"))
|
if (ident.equals_ignoring_case("or"))
|
||||||
return MediaQuery::MediaCondition::Type::Or;
|
return MediaCondition::Type::Or;
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -806,10 +801,7 @@ OwnPtr<MediaQuery::MediaCondition> Parser::consume_media_condition(TokenStream<S
|
||||||
tokens.skip_whitespace();
|
tokens.skip_whitespace();
|
||||||
|
|
||||||
if (auto child_feature = consume_media_feature(tokens); child_feature.has_value()) {
|
if (auto child_feature = consume_media_feature(tokens); child_feature.has_value()) {
|
||||||
auto child = new MediaQuery::MediaCondition;
|
child_conditions.append(MediaCondition::from_feature(child_feature.release_value()));
|
||||||
child->type = MediaQuery::MediaCondition::Type::Single;
|
|
||||||
child->feature = child_feature.value();
|
|
||||||
child_conditions.append(adopt_own(*child));
|
|
||||||
} else {
|
} else {
|
||||||
auto& token = tokens.next_token();
|
auto& token = tokens.next_token();
|
||||||
if (!token.is_block() || !token.block().is_paren()) {
|
if (!token.is_block() || !token.block().is_paren()) {
|
||||||
|
@ -832,29 +824,20 @@ OwnPtr<MediaQuery::MediaCondition> Parser::consume_media_condition(TokenStream<S
|
||||||
if (child_conditions.size() == 1)
|
if (child_conditions.size() == 1)
|
||||||
return move(child_conditions.ptr_at(0));
|
return move(child_conditions.ptr_at(0));
|
||||||
|
|
||||||
auto condition = new MediaQuery::MediaCondition;
|
if (condition_type.value() == MediaCondition::Type::And)
|
||||||
condition->type = condition_type.value();
|
return MediaCondition::from_and_list(move(child_conditions));
|
||||||
condition->conditions = move(child_conditions);
|
return MediaCondition::from_or_list(move(child_conditions));
|
||||||
return adopt_own(*condition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// `<media-feature>`
|
// `<media-feature>`
|
||||||
tokens.rewind_to_position(position);
|
tokens.rewind_to_position(position);
|
||||||
if (auto feature = consume_media_feature(tokens); feature.has_value()) {
|
if (auto feature = consume_media_feature(tokens); feature.has_value())
|
||||||
auto condition = new MediaQuery::MediaCondition;
|
return MediaCondition::from_feature(feature.release_value());
|
||||||
condition->type = MediaQuery::MediaCondition::Type::Single;
|
|
||||||
condition->feature = feature.value();
|
|
||||||
return adopt_own(*condition);
|
|
||||||
}
|
|
||||||
|
|
||||||
// `<general-enclosed>`
|
// `<general-enclosed>`
|
||||||
tokens.rewind_to_position(position);
|
tokens.rewind_to_position(position);
|
||||||
if (auto general_enclosed = parse_general_enclosed(tokens); general_enclosed.has_value()) {
|
if (auto general_enclosed = parse_general_enclosed(tokens); general_enclosed.has_value())
|
||||||
auto condition = new MediaQuery::MediaCondition;
|
return MediaCondition::from_general_enclosed(general_enclosed.release_value());
|
||||||
condition->type = MediaQuery::MediaCondition::Type::GeneralEnclosed;
|
|
||||||
condition->general_enclosed = general_enclosed.release_value();
|
|
||||||
return adopt_own(*condition);
|
|
||||||
}
|
|
||||||
|
|
||||||
tokens.rewind_to_position(position);
|
tokens.rewind_to_position(position);
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -235,7 +235,7 @@ private:
|
||||||
Result<Selector::SimpleSelector, ParsingResult> parse_simple_selector(TokenStream<StyleComponentValueRule>&);
|
Result<Selector::SimpleSelector, ParsingResult> parse_simple_selector(TokenStream<StyleComponentValueRule>&);
|
||||||
|
|
||||||
NonnullRefPtr<MediaQuery> parse_media_query(TokenStream<StyleComponentValueRule>&);
|
NonnullRefPtr<MediaQuery> parse_media_query(TokenStream<StyleComponentValueRule>&);
|
||||||
OwnPtr<MediaQuery::MediaCondition> consume_media_condition(TokenStream<StyleComponentValueRule>&);
|
OwnPtr<MediaCondition> consume_media_condition(TokenStream<StyleComponentValueRule>&);
|
||||||
Optional<MediaFeature> consume_media_feature(TokenStream<StyleComponentValueRule>&);
|
Optional<MediaFeature> consume_media_feature(TokenStream<StyleComponentValueRule>&);
|
||||||
Optional<MediaQuery::MediaType> consume_media_type(TokenStream<StyleComponentValueRule>&);
|
Optional<MediaQuery::MediaType> consume_media_type(TokenStream<StyleComponentValueRule>&);
|
||||||
Optional<MediaFeatureValue> parse_media_feature_value(TokenStream<StyleComponentValueRule>&);
|
Optional<MediaFeatureValue> parse_media_feature_value(TokenStream<StyleComponentValueRule>&);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue