1
+ /**
2
+ * @typedef {import('css-selector-parser').RuleAttr } CssRuleAttr
3
+ * @typedef {import('css-selector-parser').RulePseudo } CssRulePseudo
4
+ * @typedef {import('css-selector-parser').Selectors } CssSelectors
5
+ * @typedef {import('css-selector-parser').RuleSet } CssRuleSet
6
+ * @typedef {import('css-selector-parser').Rule } CssRule
7
+ *
8
+ * @typedef {import('hast').Element } HastElement
9
+ * @typedef {import('hast').Properties } HastProperties
10
+ *
11
+ * @typedef {'html'|'svg' } Space
12
+ *
13
+ * @typedef Options
14
+ * @property {Space } [space]
15
+ *
16
+ * @typedef Context
17
+ * @property {Space } space
18
+ * @property {boolean } root
19
+ */
20
+
1
21
import { h , s } from 'hastscript'
2
22
import { zwitch } from 'zwitch'
3
23
import { CssSelectorParser } from 'css-selector-parser'
4
24
5
- var compile = zwitch ( 'type' , {
6
- handlers : {
7
- selectors,
8
- ruleSet,
9
- rule
10
- }
11
- } )
25
+ var compile = zwitch ( 'type' , { handlers : { selectors, ruleSet, rule} } )
12
26
13
27
var parser = new CssSelectorParser ( )
14
28
15
29
parser . registerNestingOperators ( '>' , '+' , '~' )
16
30
// Register these so we can throw nicer errors.
17
31
parser . registerAttrEqualityMods ( '~' , '|' , '^' , '$' , '*' )
18
32
33
+ /**
34
+ * @param {string } [selector='']
35
+ * @param {Space|Options } [space='html']
36
+ * @returns {HastElement }
37
+ */
19
38
export function fromSelector ( selector , space ) {
20
- var config = { space : ( space && space . space ) || space || 'html' , root : true }
39
+ /** @type {Context } */
40
+ var config = {
41
+ space :
42
+ ( space && typeof space === 'object' && space . space ) ||
43
+ ( typeof space === 'string' && space ) ||
44
+ 'html' ,
45
+ root : true
46
+ }
21
47
22
48
return (
49
+ // @ts -ignore Assume one element is returned.
23
50
compile ( parser . parse ( selector || '' ) , config ) || build ( config . space ) ( '' )
24
51
)
25
52
}
26
53
27
- function selectors ( ) {
54
+ /**
55
+ * @param {CssSelectors } _
56
+ */
57
+ function selectors ( _ ) {
28
58
throw new Error ( 'Cannot handle selector list' )
29
59
}
30
60
61
+ /**
62
+ * @param {CssRuleSet } query
63
+ * @param {Context } config
64
+ * @returns {HastElement|Array.<HastElement> }
65
+ */
31
66
function ruleSet ( query , config ) {
67
+ // @ts -ignore Assume one or more elements is returned.
32
68
return compile ( query . rule , config )
33
69
}
34
70
71
+ /**
72
+ * @param {CssRule } query
73
+ * @param {Context } config
74
+ * @returns {HastElement|Array.<HastElement> }
75
+ */
35
76
function rule ( query , config ) {
36
77
var parentSpace = config . space
37
78
var name = query . tagName === '*' ? '' : query . tagName || ''
38
79
var space = parentSpace === 'html' && name === 'svg' ? 'svg' : parentSpace
80
+ /** @type {boolean } */
39
81
var sibling
40
- var operator
82
+ /** @type { HastElement } */
41
83
var node
42
84
43
85
if ( query . rule ) {
44
- operator = query . rule . nestingOperator
45
- sibling = operator === '+' || operator === '~'
86
+ sibling =
87
+ query . rule . nestingOperator === '+' || query . rule . nestingOperator === '~'
46
88
47
89
if ( sibling && config . root ) {
48
90
throw new Error (
49
- 'Cannot handle sibling combinator `' + operator + '` at root'
91
+ 'Cannot handle sibling combinator `' +
92
+ query . rule . nestingOperator +
93
+ '` at root'
50
94
)
51
95
}
52
96
}
53
97
98
+ // @ts -ignore Assume one or more elements is returned.
54
99
node = build ( space ) (
55
100
name ,
56
101
Object . assign (
@@ -61,9 +106,14 @@ function rule(query, config) {
61
106
! query . rule || sibling ? [ ] : compile ( query . rule , { space} )
62
107
)
63
108
109
+ // @ts -ignore Assume one or more elements is returned.
64
110
return sibling ? [ node , compile ( query . rule , { space : parentSpace } ) ] : node
65
111
}
66
112
113
+ /**
114
+ * @param {Array.<CssRulePseudo> } pseudos
115
+ * @returns {HastProperties }
116
+ */
67
117
function pseudosToHast ( pseudos ) {
68
118
var pseudo = pseudos [ 0 ]
69
119
@@ -78,15 +128,21 @@ function pseudosToHast(pseudos) {
78
128
return { }
79
129
}
80
130
131
+ /**
132
+ * @param {Array.<CssRuleAttr> } attrs
133
+ * @returns {HastProperties }
134
+ */
81
135
function attrsToHast ( attrs ) {
82
- var props = { }
83
136
var index = - 1
137
+ /** @type {HastProperties } */
138
+ var props = { }
139
+ /** @type {CssRuleAttr } */
84
140
var attr
85
141
86
142
while ( ++ index < attrs . length ) {
87
143
attr = attrs [ index ]
88
144
89
- if ( attr . operator ) {
145
+ if ( ' operator' in attr ) {
90
146
if ( attr . operator === '=' ) {
91
147
props [ attr . name ] = attr . value
92
148
} else {
@@ -102,6 +158,10 @@ function attrsToHast(attrs) {
102
158
return props
103
159
}
104
160
161
+ /**
162
+ * @param {Space } space
163
+ * @returns {typeof h }
164
+ */
105
165
function build ( space ) {
106
166
return space === 'html' ? h : s
107
167
}
0 commit comments