浏览代码

LibWeb: Add support for pseudo-class functions that take an ident param

This is prep work for `:dir()`, though other pseudo-classes may well use
it in the future too.
Sam Atkins 1 年之前
父节点
当前提交
5b125811f1

+ 3 - 0
Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSPseudoClass.cpp

@@ -73,6 +73,7 @@ struct PseudoClassMetadata {
         ANPlusBOf,
         CompoundSelector,
         ForgivingSelectorList,
+        Ident,
         LanguageRanges,
         SelectorList,
     } parameter_type;
@@ -169,6 +170,8 @@ PseudoClassMetadata pseudo_class_metadata(PseudoClass pseudo_class)
                 parameter_type = "CompoundSelector"_string;
             } else if (argument_string == "<forgiving-selector-list>"sv) {
                 parameter_type = "ForgivingSelectorList"_string;
+            } else if (argument_string == "<ident>"sv) {
+                parameter_type = "Ident"_string;
             } else if (argument_string == "<language-ranges>"sv) {
                 parameter_type = "LanguageRanges"_string;
             } else if (argument_string == "<selector-list>"sv) {

+ 23 - 0
Userland/Libraries/LibWeb/CSS/Parser/SelectorParsing.cpp

@@ -512,6 +512,29 @@ Parser::ParseErrorOr<Selector::SimpleSelector> Parser::parse_pseudo_simple_selec
                     .argument_selector_list = move(argument_selector_list) }
             };
         }
+        case PseudoClassMetadata::ParameterType::Ident: {
+            auto function_token_stream = TokenStream(pseudo_function.values());
+            function_token_stream.skip_whitespace();
+            auto maybe_ident_token = function_token_stream.next_token();
+            function_token_stream.skip_whitespace();
+            if (!maybe_ident_token.is(Token::Type::Ident) || function_token_stream.has_next_token()) {
+                dbgln_if(CSS_PARSER_DEBUG, "Failed to parse :{}() parameter as an ident: not an ident", pseudo_function.name());
+                return ParseError::SyntaxError;
+            }
+
+            auto maybe_ident = value_id_from_string(maybe_ident_token.token().ident());
+            if (!maybe_ident.has_value()) {
+                dbgln_if(CSS_PARSER_DEBUG, "Failed to parse :{}() parameter as an ident: unrecognized ident", pseudo_function.name());
+                return ParseError::SyntaxError;
+            }
+
+            return Selector::SimpleSelector {
+                .type = Selector::SimpleSelector::Type::PseudoClass,
+                .value = Selector::SimpleSelector::PseudoClassSelector {
+                    .type = pseudo_class,
+                    .identifier = maybe_ident.value() }
+            };
+        }
         case PseudoClassMetadata::ParameterType::LanguageRanges: {
             Vector<FlyString> languages;
             auto function_token_stream = TokenStream(pseudo_function.values());

+ 4 - 0
Userland/Libraries/LibWeb/CSS/Selector.h

@@ -12,6 +12,7 @@
 #include <AK/String.h>
 #include <AK/Vector.h>
 #include <LibWeb/CSS/PseudoClass.h>
+#include <LibWeb/CSS/ValueID.h>
 
 namespace Web::CSS {
 
@@ -96,6 +97,9 @@ public:
 
             // Used for :lang(en-gb,dk)
             Vector<FlyString> languages {};
+
+            // Used by :dir()
+            Optional<ValueID> identifier {};
         };
 
         struct Name {

+ 3 - 0
Userland/Libraries/LibWeb/Dump.cpp

@@ -505,6 +505,9 @@ void dump_selector(StringBuilder& builder, CSS::Selector const& selector)
                     builder.append("])"sv);
                     break;
                 }
+                case CSS::PseudoClassMetadata::ParameterType::Ident:
+                    builder.appendff("(ident={})", string_from_value_id(pseudo_class.identifier.value()));
+                    break;
                 case CSS::PseudoClassMetadata::ParameterType::LanguageRanges: {
                     builder.append('(');
                     builder.join(',', pseudo_class.languages);