2020-01-18 09:38:21 +01:00
/*
* Copyright ( c ) 2018 - 2020 , Andreas Kling < kling @ serenityos . org >
2023-02-18 15:42:55 +00:00
* Copyright ( c ) 2021 - 2023 , Sam Atkins < atkinssj @ serenityos . org >
2020-01-18 09:38:21 +01:00
*
2021-04-22 01:24:48 -07:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-01-18 09:38:21 +01:00
*/
2021-05-08 23:19:25 +03:00
# include "Selector.h"
2021-10-15 12:18:09 +01:00
# include <LibWeb/CSS/Serialize.h>
2019-06-20 23:25:25 +02:00
2020-07-26 20:01:35 +02:00
namespace Web : : CSS {
2020-03-07 10:27:02 +01:00
2021-07-23 15:24:33 +01:00
Selector : : Selector ( Vector < CompoundSelector > & & compound_selectors )
: m_compound_selectors ( move ( compound_selectors ) )
2019-06-20 23:25:25 +02:00
{
2022-03-21 15:43:59 +00:00
// FIXME: This assumes that only one pseudo-element is allowed in a selector, and that it appears at the end.
// This is not true in Selectors-4!
2022-03-13 16:28:20 +01:00
if ( ! m_compound_selectors . is_empty ( ) ) {
for ( auto const & simple_selector : m_compound_selectors . last ( ) . simple_selectors ) {
if ( simple_selector . type = = SimpleSelector : : Type : : PseudoElement ) {
2022-03-21 15:43:59 +00:00
m_pseudo_element = simple_selector . pseudo_element ( ) ;
2022-03-13 16:28:20 +01:00
break ;
}
}
}
2019-06-20 23:25:25 +02:00
}
2022-02-25 12:56:55 +00:00
// https://www.w3.org/TR/selectors-4/#specificity-rules
2020-06-25 16:43:49 +02:00
u32 Selector : : specificity ( ) const
2019-06-29 17:32:32 +02:00
{
2022-02-05 17:40:18 +02:00
if ( m_specificity . has_value ( ) )
return * m_specificity ;
2022-03-17 16:40:52 +00:00
constexpr u32 ids_shift = 16 ;
constexpr u32 classes_shift = 8 ;
constexpr u32 tag_names_shift = 0 ;
constexpr u32 ids_mask = 0xff < < ids_shift ;
constexpr u32 classes_mask = 0xff < < classes_shift ;
constexpr u32 tag_names_mask = 0xff < < tag_names_shift ;
u32 ids = 0 ;
u32 classes = 0 ;
u32 tag_names = 0 ;
2019-06-29 17:32:32 +02:00
2022-03-17 19:13:51 +00:00
auto count_specificity_of_most_complex_selector = [ & ] ( auto & selector_list ) {
u32 max_selector_list_argument_specificity = 0 ;
for ( auto const & complex_selector : selector_list ) {
2023-03-06 14:17:01 +01:00
max_selector_list_argument_specificity = max ( max_selector_list_argument_specificity , complex_selector - > specificity ( ) ) ;
2022-03-17 19:13:51 +00:00
}
u32 child_ids = ( max_selector_list_argument_specificity & ids_mask ) > > ids_shift ;
u32 child_classes = ( max_selector_list_argument_specificity & classes_mask ) > > classes_shift ;
u32 child_tag_names = ( max_selector_list_argument_specificity & tag_names_mask ) > > tag_names_shift ;
ids + = child_ids ;
classes + = child_classes ;
tag_names + = child_tag_names ;
} ;
2021-07-23 15:24:33 +01:00
for ( auto & list : m_compound_selectors ) {
for ( auto & simple_selector : list . simple_selectors ) {
2019-11-27 20:37:36 +01:00
switch ( simple_selector . type ) {
case SimpleSelector : : Type : : Id :
2022-03-17 16:40:52 +00:00
// count the number of ID selectors in the selector (= A)
2019-11-27 20:37:36 +01:00
+ + ids ;
break ;
case SimpleSelector : : Type : : Class :
2022-02-25 12:56:55 +00:00
case SimpleSelector : : Type : : Attribute :
2022-03-17 16:40:52 +00:00
// count the number of class selectors, attributes selectors, and pseudo-classes in the selector (= B)
2019-11-27 20:37:36 +01:00
+ + classes ;
break ;
2022-03-21 15:43:59 +00:00
case SimpleSelector : : Type : : PseudoClass : {
auto & pseudo_class = simple_selector . pseudo_class ( ) ;
switch ( pseudo_class . type ) {
2022-03-17 16:40:52 +00:00
case SimpleSelector : : PseudoClass : : Type : : Is :
case SimpleSelector : : PseudoClass : : Type : : Not : {
// The specificity of an :is(), :not(), or :has() pseudo-class is replaced by the
// specificity of the most specific complex selector in its selector list argument.
2022-03-21 15:43:59 +00:00
count_specificity_of_most_complex_selector ( pseudo_class . argument_selector_list ) ;
2022-03-17 19:13:51 +00:00
break ;
}
case SimpleSelector : : PseudoClass : : Type : : NthChild :
case SimpleSelector : : PseudoClass : : Type : : NthLastChild : {
// Analogously, the specificity of an :nth-child() or :nth-last-child() selector
// is the specificity of the pseudo class itself (counting as one pseudo-class selector)
// plus the specificity of the most specific complex selector in its selector list argument (if any).
+ + classes ;
2022-03-21 15:43:59 +00:00
count_specificity_of_most_complex_selector ( pseudo_class . argument_selector_list ) ;
2022-03-17 16:40:52 +00:00
break ;
}
case SimpleSelector : : PseudoClass : : Type : : Where :
// The specificity of a :where() pseudo-class is replaced by zero.
break ;
default :
+ + classes ;
break ;
}
break ;
2022-03-21 15:43:59 +00:00
}
2019-11-27 20:37:36 +01:00
case SimpleSelector : : Type : : TagName :
2022-02-25 12:56:55 +00:00
case SimpleSelector : : Type : : PseudoElement :
2022-03-17 16:40:52 +00:00
// count the number of type selectors and pseudo-elements in the selector (= C)
2019-11-27 20:37:36 +01:00
+ + tag_names ;
break ;
2022-03-17 16:40:52 +00:00
case SimpleSelector : : Type : : Universal :
// ignore the universal selector
break ;
2019-11-27 20:37:36 +01:00
}
2019-06-29 17:32:32 +02:00
}
}
2022-03-17 16:40:52 +00:00
// Due to storage limitations, implementations may have limitations on the size of A, B, or C.
// If so, values higher than the limit must be clamped to that limit, and not overflow.
m_specificity = ( min ( ids , 0xff ) < < ids_shift )
+ ( min ( classes , 0xff ) < < classes_shift )
+ ( min ( tag_names , 0xff ) < < tag_names_shift ) ;
2022-02-05 17:40:18 +02:00
return * m_specificity ;
2019-06-29 17:32:32 +02:00
}
2020-03-07 10:27:02 +01:00
2021-10-15 11:30:01 +01:00
// https://www.w3.org/TR/cssom/#serialize-a-simple-selector
2023-02-18 15:42:55 +00:00
ErrorOr < String > Selector : : SimpleSelector : : serialize ( ) const
2021-10-15 11:30:01 +01:00
{
StringBuilder s ;
switch ( type ) {
case Selector : : SimpleSelector : : Type : : TagName :
case Selector : : SimpleSelector : : Type : : Universal :
// FIXME: 1. If the namespace prefix maps to a namespace that is not the default namespace and is not the null namespace (not in a namespace) append the serialization of the namespace prefix as an identifier, followed by a "|" (U+007C) to s.
// FIXME: 2. If the namespace prefix maps to a namespace that is the null namespace (not in a namespace) append "|" (U+007C) to s.
// 3. If this is a type selector append the serialization of the element name as an identifier to s.
if ( type = = Selector : : SimpleSelector : : Type : : TagName ) {
2023-02-18 15:42:55 +00:00
TRY ( serialize_an_identifier ( s , name ( ) ) ) ;
2021-10-15 11:30:01 +01:00
}
// 4. If this is a universal selector append "*" (U+002A) to s.
if ( type = = Selector : : SimpleSelector : : Type : : Universal )
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( ' * ' ) ) ;
2021-10-15 11:30:01 +01:00
break ;
2022-03-21 15:43:59 +00:00
case Selector : : SimpleSelector : : Type : : Attribute : {
auto & attribute = this - > attribute ( ) ;
2021-10-15 11:30:01 +01:00
// 1. Append "[" (U+005B) to s.
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( ' [ ' ) ) ;
2021-10-15 11:30:01 +01:00
// FIXME: 2. If the namespace prefix maps to a namespace that is not the null namespace (not in a namespace) append the serialization of the namespace prefix as an identifier, followed by a "|" (U+007C) to s.
// 3. Append the serialization of the attribute name as an identifier to s.
2023-02-18 15:42:55 +00:00
TRY ( serialize_an_identifier ( s , attribute . name ) ) ;
2021-10-15 11:30:01 +01:00
// 4. If there is an attribute value specified, append "=", "~=", "|=", "^=", "$=", or "*=" as appropriate (depending on the type of attribute selector),
// followed by the serialization of the attribute value as a string, to s.
2023-02-18 15:42:55 +00:00
if ( ! attribute . value . is_empty ( ) ) {
2021-10-15 11:30:01 +01:00
switch ( attribute . match_type ) {
case Selector : : SimpleSelector : : Attribute : : MatchType : : ExactValueMatch :
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( " = " sv ) ) ;
2021-10-15 11:30:01 +01:00
break ;
case Selector : : SimpleSelector : : Attribute : : MatchType : : ContainsWord :
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( " ~= " sv ) ) ;
2021-10-15 11:30:01 +01:00
break ;
case Selector : : SimpleSelector : : Attribute : : MatchType : : ContainsString :
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( " *= " sv ) ) ;
2021-10-15 11:30:01 +01:00
break ;
case Selector : : SimpleSelector : : Attribute : : MatchType : : StartsWithSegment :
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( " |= " sv ) ) ;
2021-10-15 11:30:01 +01:00
break ;
case Selector : : SimpleSelector : : Attribute : : MatchType : : StartsWithString :
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( " ^= " sv ) ) ;
2021-10-15 11:30:01 +01:00
break ;
case Selector : : SimpleSelector : : Attribute : : MatchType : : EndsWithString :
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( " $= " sv ) ) ;
2021-10-15 11:30:01 +01:00
break ;
default :
break ;
}
2021-10-15 12:18:09 +01:00
2023-02-18 15:42:55 +00:00
TRY ( serialize_a_string ( s , attribute . value ) ) ;
2021-10-15 11:30:01 +01:00
}
2022-03-29 18:01:36 +02:00
// 5. If the attribute selector has the case-insensitivity flag present, append " i" (U+0020 U+0069) to s.
// If the attribute selector has the case-insensitivity flag present, append " s" (U+0020 U+0073) to s.
// (the line just above is an addition to CSS OM to match Selectors Level 4 last draft)
switch ( attribute . case_type ) {
case Selector : : SimpleSelector : : Attribute : : CaseType : : CaseInsensitiveMatch :
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( " i " sv ) ) ;
2022-03-29 18:01:36 +02:00
break ;
case Selector : : SimpleSelector : : Attribute : : CaseType : : CaseSensitiveMatch :
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( " s " sv ) ) ;
2022-03-29 18:01:36 +02:00
break ;
default :
break ;
}
2021-10-15 11:30:01 +01:00
// 6. Append "]" (U+005D) to s.
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( ' ] ' ) ) ;
2021-10-15 11:30:01 +01:00
break ;
2022-03-21 15:43:59 +00:00
}
2021-10-15 11:30:01 +01:00
case Selector : : SimpleSelector : : Type : : Class :
// Append a "." (U+002E), followed by the serialization of the class name as an identifier to s.
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( ' . ' ) ) ;
TRY ( serialize_an_identifier ( s , name ( ) ) ) ;
2021-10-15 11:30:01 +01:00
break ;
case Selector : : SimpleSelector : : Type : : Id :
// Append a "#" (U+0023), followed by the serialization of the ID as an identifier to s.
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( ' # ' ) ) ;
TRY ( serialize_an_identifier ( s , name ( ) ) ) ;
2021-10-15 11:30:01 +01:00
break ;
2022-03-21 15:43:59 +00:00
case Selector : : SimpleSelector : : Type : : PseudoClass : {
auto & pseudo_class = this - > pseudo_class ( ) ;
2021-10-15 11:30:01 +01:00
switch ( pseudo_class . type ) {
case Selector : : SimpleSelector : : PseudoClass : : Type : : Link :
case Selector : : SimpleSelector : : PseudoClass : : Type : : Visited :
case Selector : : SimpleSelector : : PseudoClass : : Type : : Hover :
case Selector : : SimpleSelector : : PseudoClass : : Type : : Focus :
2022-06-10 14:45:20 +01:00
case Selector : : SimpleSelector : : PseudoClass : : Type : : FocusWithin :
2021-10-15 11:30:01 +01:00
case Selector : : SimpleSelector : : PseudoClass : : Type : : FirstChild :
case Selector : : SimpleSelector : : PseudoClass : : Type : : LastChild :
case Selector : : SimpleSelector : : PseudoClass : : Type : : OnlyChild :
case Selector : : SimpleSelector : : PseudoClass : : Type : : Empty :
case Selector : : SimpleSelector : : PseudoClass : : Type : : Root :
case Selector : : SimpleSelector : : PseudoClass : : Type : : FirstOfType :
case Selector : : SimpleSelector : : PseudoClass : : Type : : LastOfType :
2022-02-17 22:43:22 +01:00
case Selector : : SimpleSelector : : PseudoClass : : Type : : OnlyOfType :
2021-10-15 11:30:01 +01:00
case Selector : : SimpleSelector : : PseudoClass : : Type : : Disabled :
case Selector : : SimpleSelector : : PseudoClass : : Type : : Enabled :
case Selector : : SimpleSelector : : PseudoClass : : Type : : Checked :
case Selector : : SimpleSelector : : PseudoClass : : Type : : Active :
2023-03-20 23:42:17 +01:00
case Selector : : SimpleSelector : : PseudoClass : : Type : : Scope :
2021-10-15 11:30:01 +01:00
// If the pseudo-class does not accept arguments append ":" (U+003A), followed by the name of the pseudo-class, to s.
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( ' : ' ) ) ;
TRY ( s . try_append ( pseudo_class_name ( pseudo_class . type ) ) ) ;
2021-10-15 11:30:01 +01:00
break ;
case Selector : : SimpleSelector : : PseudoClass : : Type : : NthChild :
case Selector : : SimpleSelector : : PseudoClass : : Type : : NthLastChild :
2022-06-10 14:45:06 +01:00
case Selector : : SimpleSelector : : PseudoClass : : Type : : NthOfType :
case Selector : : SimpleSelector : : PseudoClass : : Type : : NthLastOfType :
2021-10-15 11:30:01 +01:00
case Selector : : SimpleSelector : : PseudoClass : : Type : : Not :
2022-03-17 15:28:42 +00:00
case Selector : : SimpleSelector : : PseudoClass : : Type : : Is :
2022-03-17 16:13:13 +00:00
case Selector : : SimpleSelector : : PseudoClass : : Type : : Where :
2022-11-05 15:18:14 +00:00
case Selector : : SimpleSelector : : PseudoClass : : Type : : Lang :
2021-10-15 11:30:01 +01:00
// Otherwise, append ":" (U+003A), followed by the name of the pseudo-class, followed by "(" (U+0028),
// followed by the value of the pseudo-class argument(s) determined as per below, followed by ")" (U+0029), to s.
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( ' : ' ) ) ;
TRY ( s . try_append ( pseudo_class_name ( pseudo_class . type ) ) ) ;
TRY ( s . try_append ( ' ( ' ) ) ;
2021-10-15 11:30:01 +01:00
if ( pseudo_class . type = = Selector : : SimpleSelector : : PseudoClass : : Type : : NthChild
2022-06-10 14:45:06 +01:00
| | pseudo_class . type = = Selector : : SimpleSelector : : PseudoClass : : Type : : NthLastChild
| | pseudo_class . type = = Selector : : SimpleSelector : : PseudoClass : : Type : : NthOfType
| | pseudo_class . type = = Selector : : SimpleSelector : : PseudoClass : : Type : : NthLastOfType ) {
2021-10-15 12:18:09 +01:00
// The result of serializing the value using the rules to serialize an <an+b> value.
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( TRY ( pseudo_class . nth_child_pattern . serialize ( ) ) ) ) ;
2022-03-17 15:28:42 +00:00
} else if ( pseudo_class . type = = Selector : : SimpleSelector : : PseudoClass : : Type : : Not
2022-03-17 16:13:13 +00:00
| | pseudo_class . type = = Selector : : SimpleSelector : : PseudoClass : : Type : : Is
| | pseudo_class . type = = Selector : : SimpleSelector : : PseudoClass : : Type : : Where ) {
2021-10-15 11:30:01 +01:00
// The result of serializing the value using the rules for serializing a group of selectors.
2022-03-17 16:13:13 +00:00
// NOTE: `:is()` and `:where()` aren't in the spec for this yet, but it should be!
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( TRY ( serialize_a_group_of_selectors ( pseudo_class . argument_selector_list ) ) ) ) ;
2022-11-05 15:18:14 +00:00
} else if ( pseudo_class . type = = Selector : : SimpleSelector : : PseudoClass : : Type : : Lang ) {
// The serialization of a comma-separated list of each argument’ s serialization as a string, preserving relative order.
s . join ( " , " sv , pseudo_class . languages ) ;
2021-10-15 11:30:01 +01:00
}
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( ' ) ' ) ) ;
2021-10-15 11:30:01 +01:00
break ;
default :
2022-11-05 15:18:14 +00:00
dbgln ( " FIXME: Unknown pseudo class type for serialization: {} " , to_underlying ( pseudo_class . type ) ) ;
2021-10-15 11:30:01 +01:00
VERIFY_NOT_REACHED ( ) ;
}
break ;
2022-03-21 15:43:59 +00:00
}
2022-02-25 12:56:55 +00:00
case Selector : : SimpleSelector : : Type : : PseudoElement :
// Note: Pseudo-elements are dealt with in Selector::serialize()
break ;
2021-10-15 11:30:01 +01:00
default :
dbgln ( " FIXME: Unsupported simple selector serialization for type {} " , to_underlying ( type ) ) ;
break ;
}
2023-02-18 15:42:55 +00:00
return s . to_string ( ) ;
2021-10-15 11:30:01 +01:00
}
// https://www.w3.org/TR/cssom/#serialize-a-selector
2023-02-18 15:42:55 +00:00
ErrorOr < String > Selector : : serialize ( ) const
2021-10-15 11:30:01 +01:00
{
StringBuilder s ;
// To serialize a selector let s be the empty string, run the steps below for each part of the chain of the selector, and finally return s:
for ( size_t i = 0 ; i < compound_selectors ( ) . size ( ) ; + + i ) {
auto const & compound_selector = compound_selectors ( ) [ i ] ;
// 1. If there is only one simple selector in the compound selectors which is a universal selector, append the result of serializing the universal selector to s.
if ( compound_selector . simple_selectors . size ( ) = = 1
& & compound_selector . simple_selectors . first ( ) . type = = Selector : : SimpleSelector : : Type : : Universal ) {
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( TRY ( compound_selector . simple_selectors . first ( ) . serialize ( ) ) ) ) ;
2021-10-15 11:30:01 +01:00
}
// 2. Otherwise, for each simple selector in the compound selectors...
// FIXME: ...that is not a universal selector of which the namespace prefix maps to a namespace that is not the default namespace...
// ...serialize the simple selector and append the result to s.
else {
for ( auto & simple_selector : compound_selector . simple_selectors ) {
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( TRY ( simple_selector . serialize ( ) ) ) ) ;
2021-10-15 11:30:01 +01:00
}
}
// 3. If this is not the last part of the chain of the selector append a single SPACE (U+0020),
// followed by the combinator ">", "+", "~", ">>", "||", as appropriate, followed by another
// single SPACE (U+0020) if the combinator was not whitespace, to s.
if ( i ! = compound_selectors ( ) . size ( ) - 1 ) {
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( ' ' ) ) ;
2021-10-15 11:51:54 +01:00
// Note: The combinator that appears between parts `i` and `i+1` appears with the `i+1` selector,
// so we have to check that one.
switch ( compound_selectors ( ) [ i + 1 ] . combinator ) {
2021-10-15 11:30:01 +01:00
case Selector : : Combinator : : ImmediateChild :
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( " > " sv ) ) ;
2021-10-15 11:30:01 +01:00
break ;
case Selector : : Combinator : : NextSibling :
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( " + " sv ) ) ;
2021-10-15 11:30:01 +01:00
break ;
case Selector : : Combinator : : SubsequentSibling :
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( " ~ " sv ) ) ;
2021-10-15 11:30:01 +01:00
break ;
case Selector : : Combinator : : Column :
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( " || " sv ) ) ;
2021-10-15 11:30:01 +01:00
break ;
default :
break ;
}
} else {
2021-10-15 11:53:23 +01:00
// 4. If this is the last part of the chain of the selector and there is a pseudo-element,
// append "::" followed by the name of the pseudo-element, to s.
if ( compound_selector . simple_selectors . last ( ) . type = = Selector : : SimpleSelector : : Type : : PseudoElement ) {
2023-02-18 15:42:55 +00:00
TRY ( s . try_append ( " :: " sv ) ) ;
TRY ( s . try_append ( pseudo_element_name ( compound_selector . simple_selectors . last ( ) . pseudo_element ( ) ) ) ) ;
2021-10-15 11:30:01 +01:00
}
}
}
2023-02-18 15:42:55 +00:00
return s . to_string ( ) ;
2021-10-15 11:30:01 +01:00
}
// https://www.w3.org/TR/cssom/#serialize-a-group-of-selectors
2023-03-06 14:17:01 +01:00
ErrorOr < String > serialize_a_group_of_selectors ( Vector < NonnullRefPtr < Selector > > const & selectors )
2021-10-15 11:30:01 +01:00
{
// To serialize a group of selectors serialize each selector in the group of selectors and then serialize a comma-separated list of these serializations.
2023-02-18 15:42:55 +00:00
return String : : join ( " , " sv , selectors ) ;
2021-10-15 11:30:01 +01:00
}
2022-03-03 14:22:50 +00:00
Optional < Selector : : PseudoElement > pseudo_element_from_string ( StringView name )
{
2023-03-10 08:48:54 +01:00
if ( name . equals_ignoring_ascii_case ( " after " sv ) ) {
2022-03-03 14:22:50 +00:00
return Selector : : PseudoElement : : After ;
2023-03-10 08:48:54 +01:00
} else if ( name . equals_ignoring_ascii_case ( " before " sv ) ) {
2022-03-03 14:22:50 +00:00
return Selector : : PseudoElement : : Before ;
2023-03-10 08:48:54 +01:00
} else if ( name . equals_ignoring_ascii_case ( " first-letter " sv ) ) {
2022-03-03 14:22:50 +00:00
return Selector : : PseudoElement : : FirstLetter ;
2023-03-10 08:48:54 +01:00
} else if ( name . equals_ignoring_ascii_case ( " first-line " sv ) ) {
2022-03-03 14:22:50 +00:00
return Selector : : PseudoElement : : FirstLine ;
2023-03-10 08:48:54 +01:00
} else if ( name . equals_ignoring_ascii_case ( " marker " sv ) ) {
2022-03-03 14:22:50 +00:00
return Selector : : PseudoElement : : Marker ;
2023-03-10 08:48:54 +01:00
} else if ( name . equals_ignoring_ascii_case ( " -webkit-progress-bar " sv ) ) {
2022-07-22 15:58:52 +01:00
return Selector : : PseudoElement : : ProgressBar ;
2023-03-10 08:48:54 +01:00
} else if ( name . equals_ignoring_ascii_case ( " -webkit-progress-value " sv ) ) {
2022-07-22 15:58:52 +01:00
return Selector : : PseudoElement : : ProgressValue ;
2023-03-10 08:48:54 +01:00
} else if ( name . equals_ignoring_ascii_case ( " placeholder " sv ) ) {
2022-11-05 15:17:33 +00:00
return Selector : : PseudoElement : : Placeholder ;
2022-03-03 14:22:50 +00:00
}
return { } ;
}
2020-03-07 10:27:02 +01:00
}