11/**
2- * @import {AstAttribute, AstRule} from 'css-selector-parser'
2+ * @import {AstRule} from 'css-selector-parser'
33 * @import {Element, Properties} from 'hast'
44 */
55
@@ -79,38 +79,59 @@ export function fromSelector(selector, options) {
7979 * One or more elements.
8080 */
8181function rule ( query , state ) {
82- const space =
83- state . space === 'html' &&
84- query . tag &&
85- query . tag . type === 'TagName' &&
86- query . tag . name === 'svg'
87- ? 'svg'
88- : state . space
89-
90- const pseudoClass = query . pseudoClasses ? query . pseudoClasses [ 0 ] : undefined
91-
92- if ( pseudoClass ) {
93- if ( pseudoClass . name ) {
94- throw new Error ( 'Cannot handle pseudo class `' + pseudoClass . name + '`' )
95- /* c8 ignore next 4 -- types say this can occur, but I don’t understand how */
96- }
82+ let space = state . space
83+ /** @type { Properties } */
84+ const properties = { }
85+ /** @ type { Array<string> | undefined } */
86+ let className
87+ /** @type { Array<string> } */
88+ const ids = [ ]
89+ /** @type { Array<string> } */
90+ const names = [ ]
91+
92+ for ( const item of query . items ) {
93+ if ( item . type === 'Attribute' ) {
94+ if ( 'operator' in item ) {
95+ if ( item . operator === '=' ) {
96+ const value = item . value
9797
98- throw new Error ( 'Cannot handle empty pseudo class' )
98+ // eslint-disable-next-line max-depth
99+ if ( value ) {
100+ assert ( value . type === 'String' , 'substitution are not enabled' )
101+ properties [ item . name ] = value . value
102+ }
103+ } else {
104+ throw new Error (
105+ 'Cannot handle attribute equality modifier `' + item . operator + '`'
106+ )
107+ }
108+ } else {
109+ properties [ item . name ] = true
110+ }
111+ } else if ( item . type === 'ClassName' ) {
112+ if ( ! className ) className = [ ]
113+ className . push ( item . name )
114+ } else if ( item . type === 'Id' ) {
115+ ids . push ( item . name )
116+ } else if ( item . type === 'PseudoClass' ) {
117+ throw new Error ( 'Cannot handle pseudo class `' + item . name + '`' )
118+ } else if ( item . type === 'PseudoElement' ) {
119+ throw new Error ( 'Cannot handle pseudo element `' + item . name + '`' )
120+ } else if ( item . type === 'TagName' ) {
121+ names . push ( item . name )
122+ } else {
123+ assert ( item . type === 'WildcardTag' )
124+ // Ignore.
125+ }
99126 }
100127
101- if ( query . pseudoElement ) {
102- throw new Error (
103- 'Cannot handle pseudo element `' + query . pseudoElement + '`'
104- )
128+ const id = ids [ ids . length - 1 ]
129+ const name = names [ names . length - 1 ] || ''
130+ if ( state . space === 'html' && name === 'svg' ) {
131+ space = 'svg'
105132 }
106133
107- const name = query . tag && query . tag . type === 'TagName' ? query . tag . name : ''
108-
109- const node = build ( space ) ( name , {
110- id : query . ids ? query . ids [ query . ids . length - 1 ] : undefined ,
111- className : query . classNames ,
112- ...attributesToHast ( query . attributes )
113- } )
134+ const node = build ( space ) ( name , { id, className, ...properties } , [ ] )
114135 const results = [ node ]
115136
116137 if ( query . nestedRule ) {
@@ -130,48 +151,6 @@ function rule(query, state) {
130151 return results
131152}
132153
133- /**
134- * Turn attribute selectors into properties.
135- *
136- * @param {Array<AstAttribute> | undefined } attributes
137- * Attribute selectors.
138- * @returns {Properties }
139- * Properties.
140- */
141- function attributesToHast ( attributes ) {
142- /** @type {Properties } */
143- const properties = { }
144- let index = - 1
145-
146- if ( attributes ) {
147- while ( ++ index < attributes . length ) {
148- const attribute = attributes [ index ]
149-
150- if ( 'operator' in attribute ) {
151- if ( attribute . operator === '=' ) {
152- const value = attribute . value
153-
154- // eslint-disable-next-line max-depth
155- if ( value ) {
156- assert ( value . type === 'String' , 'substitution are not enabled' )
157- properties [ attribute . name ] = value . value
158- }
159- } else {
160- throw new Error (
161- 'Cannot handle attribute equality modifier `' +
162- attribute . operator +
163- '`'
164- )
165- }
166- } else {
167- properties [ attribute . name ] = true
168- }
169- }
170- }
171-
172- return properties
173- }
174-
175154/**
176155 * @param {Space } space
177156 * Space.
0 commit comments