1
1
/**
2
- * @typedef {import('./types.js ').Rule } Rule
3
- * @typedef {import('./types.js ').RuleAttr } RuleAttr
4
- * @typedef {import('./types.js ').Element } Element
5
- * @typedef {import('./types.js ').Schema } Schema
6
- * @typedef {import('./types.js ').Info } Info
7
- * @typedef {import('./types.js ').PropertyValue } PropertyValue
2
+ * @typedef {import('css-selector-parser ').AstRule } AstRule
3
+ * @typedef {import('css-selector-parser ').AstAttribute } AstAttribute
4
+ * @typedef {import('hast ').Element } Element
5
+ * @typedef {import('hast ').Properties } Properties
6
+ * @typedef {import('property-information ').Schema } Schema
7
+ * @typedef {import('property-information ').Info } Info
8
8
*/
9
9
10
10
import { stringify as commas } from 'comma-separated-tokens'
11
+ import { ok as assert } from 'devlop'
11
12
import { hasProperty } from 'hast-util-has-property'
12
13
import { find } from 'property-information'
13
14
import { stringify as spaces } from 'space-separated-tokens'
14
15
import { zwitch } from 'zwitch'
15
16
16
- /** @type {(query: RuleAttr , element: Element, info: Info) => boolean } */
17
+ /** @type {(query: AstAttribute , element: Element, info: Info) => boolean } */
17
18
const handle = zwitch ( 'operator' , {
18
19
unknown : unknownOperator ,
19
20
// @ts -expect-error: hush.
@@ -29,18 +30,21 @@ const handle = zwitch('operator', {
29
30
} )
30
31
31
32
/**
32
- * @param {Rule } query
33
+ * @param {AstRule } query
33
34
* @param {Element } element
34
35
* @param {Schema } schema
35
36
* @returns {boolean }
36
37
*/
37
38
export function attribute ( query , element , schema ) {
38
- const attrs = query . attrs
39
39
let index = - 1
40
40
41
- while ( ++ index < attrs . length ) {
42
- if ( ! handle ( attrs [ index ] , element , find ( schema , attrs [ index ] . name ) ) ) {
43
- return false
41
+ if ( query . attributes ) {
42
+ while ( ++ index < query . attributes . length ) {
43
+ const attribute = query . attributes [ index ]
44
+
45
+ if ( ! handle ( attribute , element , find ( schema , attribute . name ) ) ) {
46
+ return false
47
+ }
44
48
}
45
49
}
46
50
@@ -52,7 +56,7 @@ export function attribute(query, element, schema) {
52
56
*
53
57
* `[attr]`
54
58
*
55
- * @param {RuleAttr } _
59
+ * @param {AstAttribute } _
56
60
* @param {Element } element
57
61
* @param {Info } info
58
62
* @returns {boolean }
@@ -66,16 +70,20 @@ function exists(_, element, info) {
66
70
*
67
71
* `[attr=value]`
68
72
*
69
- * @param {RuleAttr } query
73
+ * @param {AstAttribute } query
70
74
* @param {Element } element
71
75
* @param {Info } info
72
76
* @returns {boolean }
73
77
*/
74
78
function exact ( query , element , info ) {
79
+ assert ( query . value , 'expected `value`' )
80
+ assert ( query . value . type === 'String' , 'expected plain string' )
81
+
75
82
return Boolean (
76
83
hasProperty ( element , info . property ) &&
77
84
element . properties &&
78
- normalizeValue ( element . properties [ info . property ] , info ) === query . value
85
+ normalizeValue ( element . properties [ info . property ] , info ) ===
86
+ query . value . value
79
87
)
80
88
}
81
89
@@ -85,12 +93,15 @@ function exact(query, element, info) {
85
93
*
86
94
* `[attr~=value]`
87
95
*
88
- * @param {RuleAttr } query
96
+ * @param {AstAttribute } query
89
97
* @param {Element } element
90
98
* @param {Info } info
91
99
* @returns {boolean }
92
100
*/
93
101
function spaceSeparatedList ( query , element , info ) {
102
+ assert ( query . value , 'expected `value`' )
103
+ assert ( query . value . type === 'String' , 'expected plain string' )
104
+
94
105
const value = element . properties && element . properties [ info . property ]
95
106
96
107
return (
@@ -99,12 +110,11 @@ function spaceSeparatedList(query, element, info) {
99
110
( ! info . commaSeparated &&
100
111
value &&
101
112
typeof value === 'object' &&
102
- query . value &&
103
- value . includes ( query . value ) ) ||
113
+ value . includes ( query . value . value ) ) ||
104
114
// For all other values (including comma-separated lists), return whether this
105
115
// is an exact match.
106
116
( hasProperty ( element , info . property ) &&
107
- normalizeValue ( value , info ) === query . value )
117
+ normalizeValue ( value , info ) === query . value . value )
108
118
)
109
119
}
110
120
@@ -114,23 +124,25 @@ function spaceSeparatedList(query, element, info) {
114
124
*
115
125
* `[attr|=value]`
116
126
*
117
- * @param {RuleAttr } query
127
+ * @param {AstAttribute } query
118
128
* @param {Element } element
119
129
* @param {Info } info
120
130
* @returns {boolean }
121
131
*/
122
132
function exactOrPrefix ( query , element , info ) {
133
+ assert ( query . value , 'expected `value`' )
134
+ assert ( query . value . type === 'String' , 'expected plain string' )
135
+
123
136
const value = normalizeValue (
124
137
element . properties && element . properties [ info . property ] ,
125
138
info
126
139
)
127
140
128
141
return Boolean (
129
142
hasProperty ( element , info . property ) &&
130
- query . value &&
131
- ( value === query . value ||
132
- ( value . slice ( 0 , query . value . length ) === query . value &&
133
- value . charAt ( query . value . length ) === '-' ) )
143
+ ( value === query . value . value ||
144
+ ( value . slice ( 0 , query . value . value . length ) === query . value . value &&
145
+ value . charAt ( query . value . value . length ) === '-' ) )
134
146
)
135
147
}
136
148
@@ -139,20 +151,22 @@ function exactOrPrefix(query, element, info) {
139
151
*
140
152
* `[attr^=value]`
141
153
*
142
- * @param {RuleAttr } query
154
+ * @param {AstAttribute } query
143
155
* @param {Element } element
144
156
* @param {Info } info
145
157
* @returns {boolean }
146
158
*/
147
159
function begins ( query , element , info ) {
160
+ assert ( query . value , 'expected `value`' )
161
+ assert ( query . value . type === 'String' , 'expected plain string' )
162
+
148
163
return Boolean (
149
164
hasProperty ( element , info . property ) &&
150
165
element . properties &&
151
- query . value &&
152
166
normalizeValue ( element . properties [ info . property ] , info ) . slice (
153
167
0 ,
154
- query . value . length
155
- ) === query . value
168
+ query . value . value . length
169
+ ) === query . value . value
156
170
)
157
171
}
158
172
@@ -161,19 +175,21 @@ function begins(query, element, info) {
161
175
*
162
176
* `[attr$=value]`
163
177
*
164
- * @param {RuleAttr } query
178
+ * @param {AstAttribute } query
165
179
* @param {Element } element
166
180
* @param {Info } info
167
181
* @returns {boolean }
168
182
*/
169
183
function ends ( query , element , info ) {
184
+ assert ( query . value , 'expected `value`' )
185
+ assert ( query . value . type === 'String' , 'expected plain string' )
186
+
170
187
return Boolean (
171
188
hasProperty ( element , info . property ) &&
172
189
element . properties &&
173
- query . value &&
174
190
normalizeValue ( element . properties [ info . property ] , info ) . slice (
175
- - query . value . length
176
- ) === query . value
191
+ - query . value . value . length
192
+ ) === query . value . value
177
193
)
178
194
}
179
195
@@ -182,18 +198,20 @@ function ends(query, element, info) {
182
198
*
183
199
* `[attr*=value]`
184
200
*
185
- * @param {RuleAttr } query
201
+ * @param {AstAttribute } query
186
202
* @param {Element } element
187
203
* @param {Info } info
188
204
* @returns {boolean }
189
205
*/
190
206
function contains ( query , element , info ) {
207
+ assert ( query . value , 'expected `value`' )
208
+ assert ( query . value . type === 'String' , 'expected plain string' )
209
+
191
210
return Boolean (
192
211
hasProperty ( element , info . property ) &&
193
212
element . properties &&
194
- query . value &&
195
213
normalizeValue ( element . properties [ info . property ] , info ) . includes (
196
- query . value
214
+ query . value . value
197
215
)
198
216
)
199
217
}
@@ -212,7 +230,7 @@ function unknownOperator(query) {
212
230
/**
213
231
* Stringify a hast value back to its HTML form.
214
232
*
215
- * @param {PropertyValue } value
233
+ * @param {Properties[keyof Properties] } value
216
234
* @param {Info } info
217
235
* @returns {string }
218
236
*/
0 commit comments