Skip to content

Commit 9a17e77

Browse files
committed
Refactor code-style
1 parent d1a0e1b commit 9a17e77

19 files changed

+4153
-3084
lines changed

index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* @typedef {import('./lib/types.js').Space} Space
2+
* @typedef {import('./lib/index.js').Space} Space
33
*/
44

55
export {matches, select, selectAll} from './lib/index.js'

lib/attribute.js

Lines changed: 132 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
/**
2-
* @typedef {import('css-selector-parser').AstRule} AstRule
32
* @typedef {import('css-selector-parser').AstAttribute} AstAttribute
3+
* @typedef {import('css-selector-parser').AstRule} AstRule
4+
*
45
* @typedef {import('hast').Element} Element
56
* @typedef {import('hast').Properties} Properties
6-
* @typedef {import('property-information').Schema} Schema
7+
*
78
* @typedef {import('property-information').Info} Info
9+
* @typedef {import('property-information').Schema} Schema
810
*/
911

1012
import {stringify as commas} from 'comma-separated-tokens'
11-
import {ok as assert} from 'devlop'
13+
import {ok as assert, unreachable} from 'devlop'
1214
import {hasProperty} from 'hast-util-has-property'
1315
import {find} from 'property-information'
1416
import {stringify as spaces} from 'space-separated-tokens'
@@ -17,23 +19,27 @@ import {zwitch} from 'zwitch'
1719
/** @type {(query: AstAttribute, element: Element, info: Info) => boolean} */
1820
const handle = zwitch('operator', {
1921
unknown: unknownOperator,
20-
// @ts-expect-error: hush.
22+
// @ts-expect-error: `exists` is fine.
2123
invalid: exists,
2224
handlers: {
2325
'=': exact,
24-
'~=': spaceSeparatedList,
25-
'|=': exactOrPrefix,
26-
'^=': begins,
2726
'$=': ends,
28-
'*=': contains
27+
'*=': contains,
28+
'^=': begins,
29+
'|=': exactOrPrefix,
30+
'~=': spaceSeparatedList
2931
}
3032
})
3133

3234
/**
3335
* @param {AstRule} query
36+
* Query.
3437
* @param {Element} element
38+
* Element.
3539
* @param {Schema} schema
40+
* Schema of element.
3641
* @returns {boolean}
42+
* Whether `element` matches `query`.
3743
*/
3844
export function attribute(query, element, schema) {
3945
let index = -1
@@ -52,187 +58,165 @@ export function attribute(query, element, schema) {
5258
}
5359

5460
/**
55-
* Check whether an attribute exists.
56-
*
57-
* `[attr]`
58-
*
59-
* @param {AstAttribute} _
60-
* @param {Element} element
61-
* @param {Info} info
62-
* @returns {boolean}
63-
*/
64-
function exists(_, element, info) {
65-
return hasProperty(element, info.property)
66-
}
67-
68-
/**
69-
* Check whether an attribute has an exact value.
61+
* Check whether an attribute has a substring as its start.
7062
*
71-
* `[attr=value]`
63+
* `[attr^=value]`
7264
*
7365
* @param {AstAttribute} query
66+
* Query.
7467
* @param {Element} element
68+
* Element.
7569
* @param {Info} info
70+
* Property info.
7671
* @returns {boolean}
72+
* Whether `element` matches `query`.
7773
*/
78-
function exact(query, element, info) {
74+
function begins(query, element, info) {
7975
assert(query.value, 'expected `value`')
8076
assert(query.value.type === 'String', 'expected plain string')
8177

8278
return Boolean(
8379
hasProperty(element, info.property) &&
84-
element.properties &&
85-
normalizeValue(element.properties[info.property], info) ===
86-
query.value.value
80+
normalizeValue(element.properties[info.property], info).slice(
81+
0,
82+
query.value.value.length
83+
) === query.value.value
8784
)
8885
}
8986

9087
/**
91-
* Check whether an attribute, interpreted as a space-separated list, contains
92-
* a value.
88+
* Check whether an attribute contains a substring.
9389
*
94-
* `[attr~=value]`
90+
* `[attr*=value]`
9591
*
9692
* @param {AstAttribute} query
93+
* Query.
9794
* @param {Element} element
95+
* Element.
9896
* @param {Info} info
97+
* Property info.
9998
* @returns {boolean}
99+
* Whether `element` matches `query`.
100100
*/
101-
function spaceSeparatedList(query, element, info) {
101+
function contains(query, element, info) {
102102
assert(query.value, 'expected `value`')
103103
assert(query.value.type === 'String', 'expected plain string')
104104

105-
const value = element.properties && element.properties[info.property]
106-
107-
return (
108-
// If this is a space-separated list, and the query is contained in it, return
109-
// true.
110-
(!info.commaSeparated &&
111-
value &&
112-
typeof value === 'object' &&
113-
value.includes(query.value.value)) ||
114-
// For all other values (including comma-separated lists), return whether this
115-
// is an exact match.
116-
(hasProperty(element, info.property) &&
117-
normalizeValue(value, info) === query.value.value)
105+
return Boolean(
106+
hasProperty(element, info.property) &&
107+
normalizeValue(element.properties[info.property], info).includes(
108+
query.value.value
109+
)
118110
)
119111
}
120112

121113
/**
122-
* Check whether an attribute has a substring as either the exact value or a
123-
* prefix.
114+
* Check whether an attribute has a substring as its end.
124115
*
125-
* `[attr|=value]`
116+
* `[attr$=value]`
126117
*
127118
* @param {AstAttribute} query
119+
* Query.
128120
* @param {Element} element
121+
* Element.
129122
* @param {Info} info
123+
* Property info.
130124
* @returns {boolean}
125+
* Whether `element` matches `query`.
131126
*/
132-
function exactOrPrefix(query, element, info) {
127+
function ends(query, element, info) {
133128
assert(query.value, 'expected `value`')
134129
assert(query.value.type === 'String', 'expected plain string')
135130

136-
const value = normalizeValue(
137-
element.properties && element.properties[info.property],
138-
info
139-
)
140-
141131
return Boolean(
142132
hasProperty(element, info.property) &&
143-
(value === query.value.value ||
144-
(value.slice(0, query.value.value.length) === query.value.value &&
145-
value.charAt(query.value.value.length) === '-'))
133+
normalizeValue(element.properties[info.property], info).slice(
134+
-query.value.value.length
135+
) === query.value.value
146136
)
147137
}
148138

149139
/**
150-
* Check whether an attribute has a substring as its start.
140+
* Check whether an attribute has an exact value.
151141
*
152-
* `[attr^=value]`
142+
* `[attr=value]`
153143
*
154144
* @param {AstAttribute} query
145+
* Query.
155146
* @param {Element} element
147+
* Element.
156148
* @param {Info} info
149+
* Property info.
157150
* @returns {boolean}
151+
* Whether `element` matches `query`.
158152
*/
159-
function begins(query, element, info) {
153+
function exact(query, element, info) {
160154
assert(query.value, 'expected `value`')
161155
assert(query.value.type === 'String', 'expected plain string')
162156

163157
return Boolean(
164158
hasProperty(element, info.property) &&
165-
element.properties &&
166-
normalizeValue(element.properties[info.property], info).slice(
167-
0,
168-
query.value.value.length
169-
) === query.value.value
159+
normalizeValue(element.properties[info.property], info) ===
160+
query.value.value
170161
)
171162
}
172163

173164
/**
174-
* Check whether an attribute has a substring as its end.
165+
* Check whether an attribute has a substring as either the exact value or a
166+
* prefix.
175167
*
176-
* `[attr$=value]`
168+
* `[attr|=value]`
177169
*
178170
* @param {AstAttribute} query
171+
* Query.
179172
* @param {Element} element
173+
* Element.
180174
* @param {Info} info
175+
* Property info.
181176
* @returns {boolean}
177+
* Whether `element` matches `query`.
182178
*/
183-
function ends(query, element, info) {
179+
function exactOrPrefix(query, element, info) {
184180
assert(query.value, 'expected `value`')
185181
assert(query.value.type === 'String', 'expected plain string')
186182

183+
const value = normalizeValue(element.properties[info.property], info)
184+
187185
return Boolean(
188186
hasProperty(element, info.property) &&
189-
element.properties &&
190-
normalizeValue(element.properties[info.property], info).slice(
191-
-query.value.value.length
192-
) === query.value.value
187+
(value === query.value.value ||
188+
(value.slice(0, query.value.value.length) === query.value.value &&
189+
value.charAt(query.value.value.length) === '-'))
193190
)
194191
}
195192

196193
/**
197-
* Check whether an attribute contains a substring.
194+
* Check whether an attribute exists.
198195
*
199-
* `[attr*=value]`
196+
* `[attr]`
200197
*
201-
* @param {AstAttribute} query
198+
* @param {AstAttribute} _
199+
* Query.
202200
* @param {Element} element
201+
* Element.
203202
* @param {Info} info
203+
* Property info.
204204
* @returns {boolean}
205+
* Whether `element` matches `query`.
205206
*/
206-
function contains(query, element, info) {
207-
assert(query.value, 'expected `value`')
208-
assert(query.value.type === 'String', 'expected plain string')
209-
210-
return Boolean(
211-
hasProperty(element, info.property) &&
212-
element.properties &&
213-
normalizeValue(element.properties[info.property], info).includes(
214-
query.value.value
215-
)
216-
)
217-
}
218-
219-
// Shouldn’t be called, Parser throws an error instead.
220-
/**
221-
* @param {unknown} query
222-
* @returns {never}
223-
*/
224-
/* c8 ignore next 4 */
225-
function unknownOperator(query) {
226-
// @ts-expect-error: `operator` guaranteed.
227-
throw new Error('Unknown operator `' + query.operator + '`')
207+
function exists(_, element, info) {
208+
return hasProperty(element, info.property)
228209
}
229210

230211
/**
231212
* Stringify a hast value back to its HTML form.
232213
*
233214
* @param {Properties[keyof Properties]} value
215+
* hast property value.
234216
* @param {Info} info
217+
* Property info.
235218
* @returns {string}
219+
* Normalized value.
236220
*/
237221
function normalizeValue(value, info) {
238222
if (typeof value === 'boolean') {
@@ -245,3 +229,54 @@ function normalizeValue(value, info) {
245229

246230
return String(value)
247231
}
232+
233+
/**
234+
* Check whether an attribute, interpreted as a space-separated list, contains
235+
* a value.
236+
*
237+
* `[attr~=value]`
238+
*
239+
* @param {AstAttribute} query
240+
* Query.
241+
* @param {Element} element
242+
* Element.
243+
* @param {Info} info
244+
* Property info.
245+
* @returns {boolean}
246+
* Whether `element` matches `query`.
247+
*/
248+
function spaceSeparatedList(query, element, info) {
249+
assert(query.value, 'expected `value`')
250+
assert(query.value.type === 'String', 'expected plain string')
251+
252+
const value = element.properties[info.property]
253+
254+
return (
255+
// If this is a space-separated list, and the query is contained in it, return
256+
// true.
257+
(!info.commaSeparated &&
258+
value &&
259+
typeof value === 'object' &&
260+
value.includes(query.value.value)) ||
261+
// For all other values (including comma-separated lists), return whether this
262+
// is an exact match.
263+
(hasProperty(element, info.property) &&
264+
normalizeValue(value, info) === query.value.value)
265+
)
266+
}
267+
268+
// Shouldn’t be called, Parser throws an error instead.
269+
/**
270+
* @param {unknown} query_
271+
* Query.
272+
* @returns {never}
273+
* Nothing.
274+
* @throws {Error}
275+
* Error.
276+
*/
277+
/* c8 ignore next 5 */
278+
function unknownOperator(query_) {
279+
// Runtime guarantees `operator` exists.
280+
const query = /** @type {AstAttribute} */ (query_)
281+
unreachable('Unknown operator `' + query.operator + '`')
282+
}

lib/class-name.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,24 @@
33
* @typedef {import('hast').Element} Element
44
*/
55

6-
// Make VS Code see references to the above types.
7-
''
6+
/** @type {Array<never>} */
7+
const emptyClassNames = []
88

99
/**
1010
* Check whether an element has all class names.
1111
*
1212
* @param {AstRule} query
13+
* AST rule (with `classNames`).
1314
* @param {Element} element
15+
* Element.
1416
* @returns {boolean}
17+
* Whether `element` matches `query`.
1518
*/
1619
export function className(query, element) {
17-
/** @type {Readonly<Array<string>>} */
18-
// @ts-expect-error Assume array.
19-
const value = element.properties.className || []
20+
// Assume array.
21+
const value = /** @type {Readonly<Array<string>>} */ (
22+
element.properties.className || emptyClassNames
23+
)
2024
let index = -1
2125

2226
if (query.classNames) {

0 commit comments

Comments
 (0)