@@ -99,6 +99,7 @@ pub const PseudoClass = enum {
9999 selection ,
100100 spelling_error ,
101101 modal ,
102+ popover_open ,
102103
103104 pub const Error = error {
104105 InvalidPseudoClass ,
@@ -114,52 +115,107 @@ pub const PseudoClass = enum {
114115 }
115116
116117 pub fn parse (s : []const u8 ) Error ! PseudoClass {
117- if (std .ascii .eqlIgnoreCase (s , "not" )) return .not ;
118- if (std .ascii .eqlIgnoreCase (s , "has" )) return .has ;
119- if (std .ascii .eqlIgnoreCase (s , "haschild" )) return .haschild ;
120- if (std .ascii .eqlIgnoreCase (s , "contains" )) return .contains ;
121- if (std .ascii .eqlIgnoreCase (s , "containsown" )) return .containsown ;
122- if (std .ascii .eqlIgnoreCase (s , "matches" )) return .matches ;
123- if (std .ascii .eqlIgnoreCase (s , "matchesown" )) return .matchesown ;
124- if (std .ascii .eqlIgnoreCase (s , "nth-child" )) return .nth_child ;
125- if (std .ascii .eqlIgnoreCase (s , "nth-last-child" )) return .nth_last_child ;
126- if (std .ascii .eqlIgnoreCase (s , "nth-of-type" )) return .nth_of_type ;
127- if (std .ascii .eqlIgnoreCase (s , "nth-last-of-type" )) return .nth_last_of_type ;
128- if (std .ascii .eqlIgnoreCase (s , "first-child" )) return .first_child ;
129- if (std .ascii .eqlIgnoreCase (s , "last-child" )) return .last_child ;
130- if (std .ascii .eqlIgnoreCase (s , "first-of-type" )) return .first_of_type ;
131- if (std .ascii .eqlIgnoreCase (s , "last-of-type" )) return .last_of_type ;
132- if (std .ascii .eqlIgnoreCase (s , "only-child" )) return .only_child ;
133- if (std .ascii .eqlIgnoreCase (s , "only-of-type" )) return .only_of_type ;
134- if (std .ascii .eqlIgnoreCase (s , "input" )) return .input ;
135- if (std .ascii .eqlIgnoreCase (s , "empty" )) return .empty ;
136- if (std .ascii .eqlIgnoreCase (s , "root" )) return .root ;
137- if (std .ascii .eqlIgnoreCase (s , "link" )) return .link ;
138- if (std .ascii .eqlIgnoreCase (s , "lang" )) return .lang ;
139- if (std .ascii .eqlIgnoreCase (s , "enabled" )) return .enabled ;
140- if (std .ascii .eqlIgnoreCase (s , "disabled" )) return .disabled ;
141- if (std .ascii .eqlIgnoreCase (s , "checked" )) return .checked ;
142- if (std .ascii .eqlIgnoreCase (s , "visited" )) return .visited ;
143- if (std .ascii .eqlIgnoreCase (s , "hover" )) return .hover ;
144- if (std .ascii .eqlIgnoreCase (s , "active" )) return .active ;
145- if (std .ascii .eqlIgnoreCase (s , "focus" )) return .focus ;
146- if (std .ascii .eqlIgnoreCase (s , "target" )) return .target ;
147- if (std .ascii .eqlIgnoreCase (s , "after" )) return .after ;
148- if (std .ascii .eqlIgnoreCase (s , "backdrop" )) return .backdrop ;
149- if (std .ascii .eqlIgnoreCase (s , "before" )) return .before ;
150- if (std .ascii .eqlIgnoreCase (s , "cue" )) return .cue ;
151- if (std .ascii .eqlIgnoreCase (s , "first-letter" )) return .first_letter ;
152- if (std .ascii .eqlIgnoreCase (s , "first-line" )) return .first_line ;
153- if (std .ascii .eqlIgnoreCase (s , "grammar-error" )) return .grammar_error ;
154- if (std .ascii .eqlIgnoreCase (s , "marker" )) return .marker ;
155- if (std .ascii .eqlIgnoreCase (s , "placeholder" )) return .placeholder ;
156- if (std .ascii .eqlIgnoreCase (s , "selection" )) return .selection ;
157- if (std .ascii .eqlIgnoreCase (s , "spelling-error" )) return .spelling_error ;
158- if (std .ascii .eqlIgnoreCase (s , "modal" )) return .modal ;
118+ const longest_selector = "nth-last-of-type" ;
119+ if (s .len > longest_selector .len ) {
120+ return Error .InvalidPseudoClass ;
121+ }
122+
123+ var buf : [longest_selector .len ]u8 = undefined ;
124+ const selector = std .ascii .lowerString (& buf , s );
125+
126+ switch (selector .len ) {
127+ 3 = > switch (@as (u24 , @bitCast (selector [0.. 3].* ))) {
128+ asUint (u24 , "cue" ) = > return .cue ,
129+ asUint (u24 , "has" ) = > return .has ,
130+ asUint (u24 , "not" ) = > return .not ,
131+ else = > {},
132+ },
133+ 4 = > switch (@as (u32 , @bitCast (selector [0.. 4].* ))) {
134+ asUint (u32 , "lang" ) = > return .lang ,
135+ asUint (u32 , "link" ) = > return .link ,
136+ asUint (u32 , "root" ) = > return .root ,
137+ else = > {},
138+ },
139+ 5 = > switch (@as (u40 , @bitCast (selector [0.. 5].* ))) {
140+ asUint (u40 , "after" ) = > return .after ,
141+ asUint (u40 , "empty" ) = > return .empty ,
142+ asUint (u40 , "focus" ) = > return .focus ,
143+ asUint (u40 , "hover" ) = > return .hover ,
144+ asUint (u40 , "input" ) = > return .input ,
145+ asUint (u40 , "modal" ) = > return .modal ,
146+ else = > {},
147+ },
148+ 6 = > switch (@as (u48 , @bitCast (selector [0.. 6].* ))) {
149+ asUint (u48 , "active" ) = > return .active ,
150+ asUint (u48 , "before" ) = > return .before ,
151+ asUint (u48 , "marker" ) = > return .marker ,
152+ asUint (u48 , "target" ) = > return .target ,
153+ else = > {},
154+ },
155+ 7 = > switch (@as (u56 , @bitCast (selector [0.. 7].* ))) {
156+ asUint (u56 , "checked" ) = > return .checked ,
157+ asUint (u56 , "enabled" ) = > return .enabled ,
158+ asUint (u56 , "matches" ) = > return .matches ,
159+ asUint (u56 , "visited" ) = > return .visited ,
160+ else = > {},
161+ },
162+ 8 = > switch (@as (u64 , @bitCast (selector [0.. 8].* ))) {
163+ asUint (u64 , "backdrop" ) = > return .backdrop ,
164+ asUint (u64 , "contains" ) = > return .contains ,
165+ asUint (u64 , "disabled" ) = > return .disabled ,
166+ asUint (u64 , "haschild" ) = > return .haschild ,
167+ else = > {},
168+ },
169+ 9 = > switch (@as (u72 , @bitCast (selector [0.. 9].* ))) {
170+ asUint (u72 , "nth-child" ) = > return .nth_child ,
171+ asUint (u72 , "selection" ) = > return .selection ,
172+ else = > {},
173+ },
174+ 10 = > switch (@as (u80 , @bitCast (selector [0.. 10].* ))) {
175+ asUint (u80 , "first-line" ) = > return .first_line ,
176+ asUint (u80 , "last-child" ) = > return .last_child ,
177+ asUint (u80 , "matchesown" ) = > return .matchesown ,
178+ asUint (u80 , "only-child" ) = > return .only_child ,
179+ else = > {},
180+ },
181+ 11 = > switch (@as (u88 , @bitCast (selector [0.. 11].* ))) {
182+ asUint (u88 , "containsown" ) = > return .containsown ,
183+ asUint (u88 , "first-child" ) = > return .first_child ,
184+ asUint (u88 , "nth-of-type" ) = > return .nth_of_type ,
185+ asUint (u88 , "placeholder" ) = > return .placeholder ,
186+ else = > {},
187+ },
188+ 12 = > switch (@as (u96 , @bitCast (selector [0.. 12].* ))) {
189+ asUint (u96 , "first-letter" ) = > return .first_letter ,
190+ asUint (u96 , "last-of-type" ) = > return .last_of_type ,
191+ asUint (u96 , "only-of-type" ) = > return .only_of_type ,
192+ asUint (u96 , "popover-open" ) = > return .popover_open ,
193+ else = > {},
194+ },
195+ 13 = > switch (@as (u104 , @bitCast (selector [0.. 13].* ))) {
196+ asUint (u104 , "first-of-type" ) = > return .first_of_type ,
197+ asUint (u104 , "grammar-error" ) = > return .grammar_error ,
198+ else = > {},
199+ },
200+ 14 = > switch (@as (u112 , @bitCast (selector [0.. 14].* ))) {
201+ asUint (u112 , "nth-last-child" ) = > return .nth_last_child ,
202+ asUint (u112 , "spelling-error" ) = > return .spelling_error ,
203+ else = > {},
204+ },
205+ 16 = > switch (@as (u128 , @bitCast (selector [0.. 16].* ))) {
206+ asUint (u128 , "nth-last-of-type" ) = > return .nth_last_of_type ,
207+ else = > {},
208+ },
209+ else = > {},
210+ }
159211 return Error .InvalidPseudoClass ;
160212 }
161213};
162214
215+ fn asUint (comptime T : type , comptime string : []const u8 ) T {
216+ return @bitCast (string [0.. string .len ].* );
217+ }
218+
163219pub const Selector = union (enum ) {
164220 pub const Error = error {
165221 UnknownCombinedCombinator ,
0 commit comments